which included commits to RCS files with non-trunk default branches.
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+#include "AliHMPID.h"
+#include "AliHMPIDHit.h" //OccupancyPrint(), HitQa()
+#include "AliHMPIDDigit.h" //OccupancyPrint()
+#include <TParticle.h> //SummaryOfEvent(), HitQa()
+#include <TBenchmark.h> //HitQA()
+#include <TPDGCode.h> //HitQA()
+#include <AliStack.h> //OccupancyPrint(), SummaryOfEvent(), HitQa()
+#include <AliRun.h> //HitQa()
+#include <AliMC.h> //ctor
+#include <AliHeader.h>
+#include <AliGenEventHeader.h>
+#include <AliGenHijingEventHeader.h>
+#include <TH1F.h> //HitQA()
+#include <AliLog.h> //in many methods to print AliInfo
+ClassImp(AliHMPID)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPID::AliHMPID(const char *name, const char *title):AliDetector(name,title),fSdi(0),fDig(0),fClu(0)
+{
+//Named ctor
+ AliDebug(1,"Start.");
+//AliDetector ctor deals with Hits and Digits (reset them to 0, does not create them)
+ HitCreate(); gAlice->GetMCApp()->AddHitList(fHits);
+ AliDebug(1,"Stop.");
+}//AliHMPID::AliHMPID(const char *name, const char *title)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPID::~AliHMPID()
+{
+//dtor
+ AliDebug(1,"Start.");
+
+
+ if(fHits) delete fHits;
+ if(fDigits) delete fDigits;
+ if(fSdi) delete fSdi;
+ if(fDig) {fDig->Delete(); delete fDig;}
+ if(fClu) {fClu->Delete(); delete fClu;}
+ AliDebug(1,"Stop.");
+}//AliHMPID::~AliHMPID()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::MakeBranch(Option_t* option)
+{
+//Create Tree branches for the HMPID.
+ AliDebug(1,Form("Start with option= %s.",option));
+
+ const Int_t kBufSize = 4000;
+
+ const char *cH = strstr(option,"H");
+ const char *cD = strstr(option,"D");
+ const char *cR = strstr(option,"R");
+ const char *cS = strstr(option,"S");
+
+ if(cH&& TreeH()){HitCreate(); MakeBranchInTree( TreeH(), "HMPID" ,&fHits ,kBufSize,0);}
+ if(cS&&fLoader->TreeS()){SdiCreate(); MakeBranchInTree(fLoader->TreeS(), "HMPID" ,&fSdi ,kBufSize,0);}
+ if(cD&&fLoader->TreeD()){DigCreate();for(Int_t i=0;i<7;i++) MakeBranchInTree(fLoader->TreeD(),Form("HMPID%d",i),&((*fDig)[i]),kBufSize,0);}
+ if(cR&&fLoader->TreeR()){CluCreate();for(Int_t i=0;i<7;i++) MakeBranchInTree(fLoader->TreeR(),Form("HMPID%d",i),&((*fClu)[i]),kBufSize,0);}
+
+ AliDebug(1,"Stop.");
+}//void AliHMPID::MakeBranch(Option_t* option)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::SetTreeAddress()
+{
+//Set branch address for the Hits and Digits Tree.
+ AliDebug(1,"Start.");
+ if(fLoader->TreeH() && fLoader->TreeH()->GetBranch("HMPID" )){HitCreate(); fLoader->TreeH()->SetBranchAddress( "HMPID" ,&fHits );}
+ if(fLoader->TreeS() && fLoader->TreeS()->GetBranch("HMPID" )){SdiCreate(); fLoader->TreeS()->SetBranchAddress( "HMPID" ,&fSdi );}
+ if(fLoader->TreeD() && fLoader->TreeD()->GetBranch("HMPID0")){DigCreate(); for(int i=0;i<7;i++) fLoader->TreeD()->SetBranchAddress(Form("HMPID%d",i),&((*fDig)[i]));}
+ if(fLoader->TreeR() && fLoader->TreeR()->GetBranch("HMPID0")){CluCreate(); for(int i=0;i<7;i++) fLoader->TreeR()->SetBranchAddress(Form("HMPID%d",i),&((*fClu)[i]));}
+ AliDebug(1,"Stop.");
+}//void AliHMPID::SetTreeAddress()
+//__________________________________________________________________________________________________
+// AliHMPIDHit* AliHMPID::Hit(Int_t tid)const
+// {
+// // Search for the first HMPID hit belonging to the given tid
+// GetLoader()->LoadHits();
+// for(Int_t iPrimN=0;iPrimN<GetLoader()->TreeH()->GetEntries();iPrimN++){//prims loop
+// GetLoader()->TreeH()->GetEntry(iPrimN);
+// for(Int_t iHitN=0;iHitN<Hits()->GetEntries();iHitN++){
+// AliHMPIDHit *pHit=(AliHMPIDHit*)Hits()->At(iHitN);
+// if(tid==pHit->Track()) {GetLoader()->UnloadHits();return pHit;}
+// }//hits
+// }//prims loop
+// GetLoader()->UnloadHits();
+// return 0;
+// }
+//__________________________________________________________________________________________________
+void AliHMPID::HitPrint(Int_t iEvtN)const
+{
+//Prints a list of HMPID hits for a given event. Default is event number 0.
+ if(GetLoader()->GetRunLoader()->GetEvent(iEvtN)) return;
+ AliInfo(Form("List of HMPID hits for event %i",iEvtN));
+ if(GetLoader()->LoadHits()) return;
+
+ Int_t iTotalHits=0;
+ for(Int_t iPrimN=0;iPrimN<GetLoader()->TreeH()->GetEntries();iPrimN++){//prims loop
+ GetLoader()->TreeH()->GetEntry(iPrimN);
+ Hits()->Print();
+ iTotalHits+=Hits()->GetEntries();
+ }
+ GetLoader()->UnloadHits();
+ AliInfo(Form("totally %i hits",iTotalHits));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::SdiPrint(Int_t iEvt)const
+{
+//prints a list of HMPID sdigits for a given event
+ if(GetLoader()->GetRunLoader()->GetEvent(iEvt)) return;
+ Info("PrintSDigits","List of HMPID sdigits for event %i",iEvt);
+ if(GetLoader()->LoadSDigits()) return;
+
+ GetLoader()->TreeS()->GetEntry(0);
+ SdiLst()->Print();
+ GetLoader()->UnloadSDigits();
+ Printf("totally %i sdigits",SdiLst()->GetEntries());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::DigPrint(Int_t iEvt)const
+{
+//prints a list of HMPID digits for a given event
+ if(GetLoader()->GetRunLoader()->GetEvent(iEvt)) return;
+ Printf("List of HMPID digits for event %i",iEvt);
+ if(GetLoader()->LoadDigits()) return;
+
+ GetLoader()->TreeD()->GetEntry(0);
+ DigLst()->Print();
+ GetLoader()->UnloadDigits();
+ Printf("totally %i Digits",DigLst()->GetEntries());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::OccupancyPrint(Int_t iEvtNreq)
+{
+//prints occupancy for each chamber in a given event
+ Int_t iEvtNmin,iEvtNmax;
+ if(iEvtNreq==-1){
+ iEvtNmin=0;
+ iEvtNmax=gAlice->GetEventsPerRun();
+ } else {
+ iEvtNmin=iEvtNreq;iEvtNmax=iEvtNreq+1;
+ }
+
+ if(GetLoader()->GetRunLoader()->LoadHeader()) return;
+ if(GetLoader()->GetRunLoader()->LoadKinematics()) return;
+
+// Info("Occupancy","for event %i",iEvtN);
+ if(GetLoader()->LoadHits()) return;
+ if(GetLoader()->LoadDigits()) return;
+
+
+ for(Int_t iEvtN=iEvtNmin;iEvtN<iEvtNmax;iEvtN++){
+ Int_t nDigCh[7]={0,0,0,0,0,0,0};
+ Int_t iChHits[7]={0,0,0,0,0,0,0};
+ Int_t nPrim[7]={0,0,0,0,0,0,0};
+ Int_t nSec[7]={0,0,0,0,0,0,0};
+ AliInfo(Form("events processed %i",iEvtN));
+ if(GetLoader()->GetRunLoader()->GetEvent(iEvtN)) return;
+ AliStack *pStack = GetLoader()->GetRunLoader()->Stack();
+ for(Int_t iPrimN=0;iPrimN<GetLoader()->TreeH()->GetEntries();iPrimN++){//prims loop
+ GetLoader()->TreeH()->GetEntry(iPrimN);
+ for(Int_t iHitN=0;iHitN<Hits()->GetEntries();iHitN++){
+ AliHMPIDHit *pHit = (AliHMPIDHit*)Hits()->At(iHitN);
+ if(pHit->E()>0){
+ iChHits[pHit->Ch()]++;
+ if(pStack->Particle(pHit->GetTrack())->Rho()<0.01) nPrim[pHit->Ch()]++;else nSec[pHit->Ch()]++;
+ }
+ }
+ }
+
+ GetLoader()->TreeD()->GetEntry(0);
+ for(Int_t iCh=0;iCh<7;iCh++){
+ for(Int_t iDig=0;iDig<DigLst(iCh)->GetEntries();iDig++){
+ AliHMPIDDigit *pDig=(AliHMPIDDigit*)DigLst(iCh)->At(iDig);
+ nDigCh[pDig->Ch()]++;
+ }
+ Printf("Occupancy for chamber %i = %4.2f %% and charged prim tracks %i and sec. tracks %i with total %i",
+ iCh,Float_t(nDigCh[iCh])*100/AliHMPIDDigit::kPadAll,nPrim[iCh],nSec[iCh],iChHits[iCh]);
+ }
+
+
+ }//events loop
+ GetLoader()->UnloadHits();
+ GetLoader()->UnloadDigits();
+ GetLoader()->GetRunLoader()->UnloadHeader();
+ GetLoader()->GetRunLoader()->UnloadKinematics();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::CluPrint(Int_t iEvtN)const
+{
+//prints a list of HMPID clusters for a given event
+ Printf("List of HMPID clusters for event %i",iEvtN);
+ GetLoader()->GetRunLoader()->GetEvent(iEvtN);
+ if(GetLoader()->LoadRecPoints()) return;
+
+ Int_t iCluCnt=0;
+ GetLoader()->TreeR()->GetEntry(0);
+ for(Int_t iCh=0;iCh<7;iCh++){
+ TClonesArray *pCluLst=(TClonesArray*)fClu->At(iCh); iCluCnt+=pCluLst->GetEntries(); pCluLst->Print();
+ }
+ GetLoader()->UnloadRecPoints();
+ Printf("totally %i clusters for event %i",iCluCnt,iEvtN);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPID::SummaryOfEvent(Int_t iEvtN) const
+{
+//prints a summary for a given event
+ AliInfo(Form("Summary of event %i",iEvtN));
+ GetLoader()->GetRunLoader()->GetEvent(iEvtN);
+ if(GetLoader()->GetRunLoader()->LoadHeader()) return;
+ if(GetLoader()->GetRunLoader()->LoadKinematics()) return;
+ AliStack *pStack=GetLoader()->GetRunLoader()->Stack();
+
+ AliGenEventHeader* pGenHeader = gAlice->GetHeader()->GenEventHeader();
+ if(pGenHeader->InheritsFrom("AliGenHijingEventHeader")) {
+ AliInfo(Form(" Hijing event with impact parameter b = %.2f (fm)",((AliGenHijingEventHeader*) pGenHeader)->ImpactParameter()));
+ }
+ Int_t nChargedPrimaries=0;
+ for(Int_t i=0;i<pStack->GetNtrack();i++) {
+ TParticle *pParticle = pStack->Particle(i);
+ if(pParticle->IsPrimary()&&pParticle->GetPDG()->Charge()!=0) nChargedPrimaries++;
+ }
+ AliInfo(Form("Total number of primaries %i",pStack->GetNprimary()));
+ AliInfo(Form("Total number of charged primaries %i",nChargedPrimaries));
+ AliInfo(Form("Total n. of tracks in stack(+sec) %i",pStack->GetNtrack()));
+ GetLoader()->GetRunLoader()->UnloadHeader();
+ GetLoader()->GetRunLoader()->UnloadKinematics();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPID_h
+#define AliHMPID_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include <AliDetector.h> //base class
+#include <TClonesArray.h> //XxxCreate()
+#include <TObjArray.h> //fClu field
+
+
+
+class AliHMPID : public AliDetector //TObject-TNamed-AliModule-AliDetector-AliHMPID
+{
+public:
+//ctor & dtor
+ AliHMPID(const char *nm,const char *ttl); //named ctor
+ AliHMPID( ):AliDetector( ),fSdi(0),fDig(0),fClu(0) {} //default ctor
+ virtual ~AliHMPID();
+//framework part
+ void BuildGeometry ( ) {} //from AliModule invoked from AliMC::InitGeometry() to build geometry for old event display
+ virtual void CreateMaterials ( )=0; //from AliModule invoked from AliMC::ConstructGeometry() to define detector materials
+ virtual void CreateGeometry ( )=0; //from AliModule invoked from AliMC::ConstructGeometry() to build detector for simulation
+ virtual Int_t IsVersion ( )const=0; //from AliModule not used
+ virtual void Init ( )=0; //from AliModule invoked from AliMC::InitGeometry() after CreateGeometry() to do VolID initialization
+ void MakeBranch (Option_t *opt=""); //from AliModule invokde from AliRun::Tree2Tree() to make requested HMPID branch
+ void SetTreeAddress ( ); //from AliModule invoked from AliRun::GetEvent(), AliLoader::SetTAddrInDet()
+ virtual void StepManager ( )=0; //from AliModule invoked from AliMC
+//private part +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ void HitCreate( ) {if(fHits)return; fHits=new TClonesArray("AliHMPIDHit"); fNhits=0; }//create hits list
+ void HitPrint (Int_t evt)const; //print hits list
+
+ TClonesArray* SdiLst ( )const{return fSdi; }//get sdigits list
+ void SdiCreate( ) {if(fSdi)return; fSdi=new TClonesArray("AliHMPIDDigit"); }//create sdigits list
+ void SdiReset ( ) {if(fSdi) fSdi ->Clear(); }//clean sdigits list
+ void SdiPrint (Int_t evt)const; //print sdigits
+
+ TObjArray* DigLst ( )const{return fDig; }//get digits list for all chambers
+ TClonesArray* DigLst (Int_t c )const{return fDig ? (TClonesArray *)fDig->At(c):0; }//get digits list for chamber
+ void DigCreate( ) {fDig=new TObjArray(7);for(Int_t i=0;i<7;i++)fDig->AddAt(new TClonesArray("AliHMPIDDigit"),i);}//create digits list
+ void DigReset ( ) {if(fDig)for(int i=0;i<7;i++)fDig->At(i)->Clear(); }//clean digits list
+ void DigPrint (Int_t evt)const; //print digits
+
+ TClonesArray* CluLst (Int_t c )const{return fClu ? (TClonesArray *)fClu->At(c):0; }//get clusters list for chamber
+ inline void CluCreate( ) {fClu=new TObjArray(7); for(Int_t i=0;i<7;i++)fClu->AddAt(new TClonesArray("AliHMPIDCluster"),i);}//create clusters list
+ void CluReset ( ) {if(fClu)for(int i=0;i<7;i++)fClu->At(i)->Clear(); }//clean clusters list
+ void CluPrint (Int_t evt)const; //print clusters list
+
+ void OccupancyPrint(Int_t evt=-1); //print chambers occupancy
+ void SummaryOfEvent(Int_t evt=0)const;
+
+protected:
+ TClonesArray *fSdi; //! list of sdigits
+ TObjArray *fDig; //! each chamber holds it's one list of digits
+ TObjArray *fClu; //! each chamber holds it's one list of clusters
+
+ private:
+ AliHMPID(const AliHMPID &rich );
+ AliHMPID& operator=(const AliHMPID&);
+
+ ClassDef(AliHMPID,11) //Main HMPID class
+};//class AliHMPID
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+#include "AliHMPIDCluster.h" //class header
+#include <TMinuit.h> //Solve()
+#include <TClonesArray.h> //Solve()
+
+ClassImp(AliHMPIDCluster)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDCluster::CoG()
+{
+// Calculates naive cluster position as a center of gravity of its digits.
+// Arguments: none
+// Returns: shape of the cluster i.e. the box which fully contains the cluster
+ if(fDigs==0) return; //no digits in this cluster
+ fX=fY=0; //set cluster position to (0,0) to start to collect contributions
+ for(Int_t iDig=0;iDig<fDigs->GetEntriesFast();iDig++){//digits loop
+ AliHMPIDDigit *pDig=(AliHMPIDDigit*)fDigs->At(iDig); //get pointer to next digit
+ Float_t q=pDig->Q(); //get QDC
+ fX += pDig->LorsX()*q;fY +=pDig->LorsY()*q; //add digit center weighted by QDC
+ }//digits loop
+ fX/=fQ;fY/=fQ; //final center of gravity
+
+ CorrSin();
+
+ fSt=kCoG;
+}//CoG()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDCluster::CorrSin()
+{
+// Correction of cluster x position due to sinoid, see HMPID TDR page 30
+// Arguments: none
+// Returns: none
+ AliHMPIDDigit dig(Ch(),100,1,fX,fY); //tmp digit to get it center
+ Float_t x=fX-dig.LorsX();
+ fX+=3.31267e-2*TMath::Sin(2*TMath::Pi()/0.8*x)-2.66575e-3*TMath::Sin(4*TMath::Pi()/0.8*x)+2.80553e-3*TMath::Sin(6*TMath::Pi()/0.8*x)+0.0070;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDCluster::FitFunc(Int_t &iNpars, Double_t *, Double_t &chi2, Double_t *par, Int_t )
+{
+// Cluster fit function
+// par[0]=x par[1]=y par[2]=q for the first Mathieson shape
+// par[3]=x par[4]=y par[5]=q for the second Mathieson shape and so on up to iNpars/3 Mathieson shapes
+// For each pad of the cluster calculates the difference between actual pad charge and the charge induced to this pad by all Mathieson distributions
+// Then the chi2 is calculated as the sum of this value squared for all pad in the cluster.
+// Arguments: iNpars - number of parameters which is number of local maxima of cluster * 3
+// chi2 - function result to be minimised
+// par - parameters array of size iNpars
+// Returns: none
+ AliHMPIDCluster *pClu=(AliHMPIDCluster*)gMinuit->GetObjectFit();
+ Int_t iNshape = iNpars/3;
+
+ chi2 = 0;
+ for(Int_t i=0;i<pClu->Size();i++){ //loop on all pads of the cluster
+ Double_t dQpadMath = 0; //pad charge collector
+ for(Int_t j=0;j<iNshape;j++){ //Mathiesons loop as all of them may contribute to this pad
+ dQpadMath+=par[3*j+2]*pClu->Dig(i)->Mathieson(par[3*j],par[3*j+1]); // par[3*j+2] is charge par[3*j] is x par[3*j+1] is y of current Mathieson
+ }
+ chi2 +=TMath::Power((pClu->Dig(i)->Q()-dQpadMath),2); //
+ } //loop on all pads of the cluster
+}//FitFunction()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDCluster::Print(Option_t* opt)const
+{
+//Print current cluster
+ const char *status=0;
+ switch(fSt){
+ case kFor: status="formed" ;break;
+ case kUnf: status="unfolded" ;break;
+ case kCoG: status="coged" ;break;
+ case kEmp: status="empty" ;break;
+ }
+ Printf("%s cs=%2i, Size=%2i (x=%7.3f cm,y=%7.3f cm,Q=%4i qdc), %s",
+ opt,Ch(),Size(),X(),Y(),Q(),status);
+ for(Int_t i=0;i<Size();i++) Dig(i)->Print();
+}//Print()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDCluster::Solve(TClonesArray *pCluLst,Bool_t isTryUnfold)
+{
+//This methode is invoked when the cluster is formed to solve it. Solve the cluster means to try to unfold the cluster
+//into the local maxima number of clusters. This methode is invoked by AliHMPIDRconstructor::Dig2Clu() on cluster by cluster basis.
+//At this point, cluster contains a list of digits, cluster charge and size is precalculated in AddDigit(), position is preset to (-1,-1) in ctor,
+//status is preset to kFormed in AddDigit(), chamber-sector info is preseted to actual values in AddDigit()
+//Method first finds number of local maxima and if it's more then one tries to unfold this cluster into local maxima number of clusters
+//Arguments: pCluLst - cluster list pointer where to add new cluster(s)
+// isTryUnfold - flag to switch on/off unfolding
+// Returns: number of local maxima of original cluster
+
+//Phase 0. Initialise TMinuit
+ const Int_t kMaxLocMax=6; //max allowed number of loc max for fitting
+ TMinuit *pMinuit = new TMinuit(3*kMaxLocMax); //init MINUIT with this number of parameters (3 params per mathieson)
+ pMinuit->SetObjectFit((TObject*)this); pMinuit->SetFCN(AliHMPIDCluster::FitFunc); //set fit function
+ Double_t aArg=-1,parStart,parStep,parLow,parHigh; Int_t iErrFlg; //tmp vars for TMinuit
+ pMinuit->mnexcm("SET PRI",&aArg,1,iErrFlg); //suspend all printout from TMinuit
+ pMinuit->mnexcm("SET NOW",&aArg,0,iErrFlg); //suspend all warning printout from TMinuit
+//Phase 1. Find number of local maxima. Strategy is to check if the current pad has QDC more then all neigbours
+ Int_t iLocMaxCnt=0;
+ for(Int_t iDig1=0;iDig1<Size();iDig1++) { //first digits loop
+ AliHMPIDDigit *pDig1 = Dig(iDig1); //take next digit
+ Int_t iHowManyMoreCnt = 0; //counts how many neighbouring pads has QDC more then current one
+ for(Int_t iDig2=0;iDig2<Size();iDig2++) { //loop on all digits again
+ if(iDig1==iDig2) continue; //the same digit, no need to compare
+ AliHMPIDDigit *pDig2 = Dig(iDig2); //take second digit to compare with the first one
+ Int_t dist = TMath::Sign(Int_t(pDig1->PadX()-pDig2->PadX()),1)+TMath::Sign(Int_t(pDig1->PadY()-pDig2->PadY()),1);//distance between pads
+ if(dist==1) //means dig2 is a neighbour of dig1
+ if(pDig2->Q()>=pDig1->Q()) iHowManyMoreCnt++; //count number of pads with Q more then Q of current pad
+ }//second digits loop
+ if(iHowManyMoreCnt==0&&iLocMaxCnt<kMaxLocMax){ //this pad has Q more then any neighbour so it's local maximum
+ pMinuit->mnparm(3*iLocMaxCnt ,Form("x%i",iLocMaxCnt),parStart=pDig1->LorsX(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
+ pMinuit->mnparm(3*iLocMaxCnt+1,Form("y%i",iLocMaxCnt),parStart=pDig1->LorsY(),parStep=0.01,parLow=0,parHigh=0,iErrFlg);
+ pMinuit->mnparm(3*iLocMaxCnt+2,Form("q%i",iLocMaxCnt),parStart=pDig1->Q() ,parStep=0.01,parLow=0,parHigh=0,iErrFlg);
+ iLocMaxCnt++;
+ }//if this pad is local maximum
+ }//first digits loop
+//Phase 2. Fit loc max number of Mathiesons or add this current cluster to the list
+ Int_t iCluCnt=pCluLst->GetEntriesFast(); //get current number of clusters already stored in the list by previous operations
+ if(isTryUnfold==kTRUE && iLocMaxCnt<kMaxLocMax){ //resonable number of local maxima to fit and user requested it
+ pMinuit->mnexcm("MIGRAD" ,&aArg,0,iErrFlg); //start fitting
+ if (!iErrFlg) { // Only if MIGRAD converged normally
+ Double_t fitX,fitY,fitQ,d1,d2,d3; TString sName; //vars to get results from TMinuit
+ for(Int_t i=0;i<iLocMaxCnt;i++){//local maxima loop
+ pMinuit->mnpout(3*i ,sName, fitX, d1 , d2, d3, iErrFlg);
+ pMinuit->mnpout(3*i+1 ,sName, fitY, d1 , d2, d3, iErrFlg);
+ pMinuit->mnpout(3*i+2 ,sName, fitQ, d1 , d2, d3, iErrFlg);
+ if (TMath::Abs(fitQ)>2147483647.0) fitQ = TMath::Sign((Double_t)2147483647,fitQ);//???????????????
+ new ((*pCluLst)[iCluCnt++]) AliHMPIDCluster(Ch(),fitX,fitY,(Int_t)fitQ); //add new unfolded clusters
+ }//local maxima loop
+ }
+ }else{//do not unfold since number of loc max is unresonably high or user's baned unfolding
+ CoG();
+ new ((*pCluLst)[iCluCnt++]) AliHMPIDCluster(*this); //add this raw cluster
+ }
+ delete pMinuit;
+ return iLocMaxCnt;
+}//Solve()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDCluster_h
+#define AliHMPIDCluster_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include "AliHMPIDDigit.h" //DigAdd()
+#include <TObjArray.h> //DigAdd()
+class TClonesArray; //Solve()
+
+class AliHMPIDCluster :public TObject
+{
+public:
+ enum EClusterStatus {kFor,kCoG,kUnf,kEmp=-1}; //status flags
+ AliHMPIDCluster( ):TObject( ),fSt(kEmp ),fCh(-1 ),fQ(-1 ),fX(-1 ),fY(-1 ),fDigs(0 ) {}
+ AliHMPIDCluster(Int_t c,Float_t x,Float_t y,Int_t q):TObject( ),fSt(kUnf ),fCh(c ),fQ(q ),fX(x ),fY(y ),fDigs(0 ) {}
+ AliHMPIDCluster(const AliHMPIDCluster &c ):TObject(c),fSt(c.fSt),fCh(c.fCh),fQ(c.fQ),fX(c.fX),fY(c.fY),fDigs(c.fDigs ? new TObjArray(*c.fDigs):0) {}
+ AliHMPIDCluster &operator=(const AliHMPIDCluster &c) {
+ if(this == &c)return *this;TObject::operator=(c); fSt=c.fSt; fCh=c.fCh; fQ=c.fQ; fX=c.fX; fY=c.fY; fDigs=c.fDigs ? new TObjArray(*c.fDigs):0; return *this;}
+
+ virtual ~AliHMPIDCluster( ) {DigDel();}
+//framework part
+ void Print (Option_t *opt="" )const; //overloaded TObject::Print() to print cluster info
+ static void FitFunc(Int_t &, Double_t *, Double_t &, Double_t *, Int_t); //fit function to be used by MINUIT
+//private part
+ void CoG ( ); //calculates center of gravity
+ void CorrSin ( ); //sinoidal correction
+ Int_t Ch ( )const{return fCh; } //chamber number
+ inline void DigAdd (AliHMPIDDigit *pDig ); //add new digit ot the cluster
+ void DigDel ( ) {if(fDigs) {delete fDigs;fDigs=0;} } //deletes the list of digits (not digits!)
+ AliHMPIDDigit* Dig (Int_t i )const{return (AliHMPIDDigit*)fDigs->At(i); } //pointer to i-th digit
+ TObjArray* DigLst ( )const{return fDigs; } //list of digits
+ void Reset ( ) {DigDel();fQ=fCh=-1;fX=fY=-1;fSt=kEmp; } //cleans the cluster
+ Int_t Solve (TClonesArray *pCluLst,Bool_t isUnfold ); //solve cluster: MINUIT fit or CoG
+ Int_t Size ( )const{return (fDigs)?fDigs->GetEntriesFast():0; } //number of pads in cluster
+ Int_t Q ( )const{return fQ; } //cluster charge in QDC channels
+ Float_t X ( )const{return fX; } //cluster x position in LRS
+ Float_t Y ( )const{return fY; } //cluster y position in LRS
+protected:
+ Int_t fSt; //flag to mark the quality of the cluster
+ Int_t fCh; //chamber number
+ Int_t fQ; //QDC value
+ Float_t fX; //local x postion, [cm]
+ Float_t fY; //local y postion, [cm]
+ TObjArray *fDigs; //! list of digits forming this cluster
+ ClassDef(AliHMPIDCluster,5) //HMPID cluster class
+};//class AliHMPIDCluster
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDCluster::DigAdd(AliHMPIDDigit *pDig)
+{
+// Adds a given digit to the list of digits belonging to this cluster, cluster is not owner of digits
+// Arguments: pDig - pointer to digit to be added
+// Returns: none
+ if(!fDigs) {fQ=0;fDigs = new TObjArray;}
+ fDigs->Add(pDig);
+ fQ+=(Int_t)pDig->Q();
+ fCh=pDig->Ch();
+ fSt=kFor;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+#include "AliHMPIDDigit.h" //class header
+#include "AliHMPIDHit.h" //Hit2Sdi()
+#include <TClonesArray.h> //Hit2Sdi()
+#include <TCanvas.h> //TestSeg()
+#include <TLine.h> //TestSeg()
+#include <TLatex.h> //TestSeg()
+#include <TPolyLine.h> //DrawPc()
+#include <TGStatusBar.h> //Zoom()
+#include <TRootCanvas.h> //Zoom()
+ClassImp(AliHMPIDDigit)
+
+/*
+Any given LDC collects data from a number of D-RORC cards connected to this same LDC by separate DDLs. This data is stored in corresponding number
+of DDL buffers.
+
+Each DDL buffer corresponds to a single D-RORC. The data this buffer contains are hardware generated by D-RORC. The buffer starts with common header
+which size and structure is standartized and mandatory for all detectors.
+The header contains among other words, so called Equipment ID word. This unique value for each D-RORC is calculated as detector ID << 8 + DDL index.
+For HMPID the detector ID is 6 (reffered in the code as kRichRawId) while DDL indexes are from 0 to 13.
+
+Common header might be followed by the private one although HMPID has no any private header, just uses the common one.
+
+Single HMPID D-RORC serves one half of a chamber i.e. 3 photocathodes even LDC for left part( PCs 0-2-4) and odd LDC for right part(1-3-5)
+as it's seen from electronics side.
+
+So the LDC -chamber-ddl map is:
+DDL index 0 -> ch 1 left -> DDL ID 0x600 DDL index 1 -> ch 1 right -> DDL ID 0x601
+DDL index 2 -> ch 2 left -> DDL ID 0x602 DDL index 3 -> ch 2 right -> DDL ID 0x603
+DDL index 4 -> ch 3 left -> DDL ID 0x604 DDL index 5 -> ch 3 right -> DDL ID 0x605
+DDL index 6 -> ch 4 left -> DDL ID 0x606 DDL index 7 -> ch 4 right -> DDL ID 0x607
+DDL index 8 -> ch 5 left -> DDL ID 0x608 DDL index 9 -> ch 5 right -> DDL ID 0x609
+DDL index 10 -> ch 6 left -> DDL ID 0x60a DDL index 11 -> ch 6 right -> DDL ID 0x60b
+DDL index 12 -> ch 7 left -> DDL ID 0x60c DDL index 13 -> ch 7 right -> DDL ID 0x60d
+
+HMPID FEE as seen by single D-RORC is composed from a number of DILOGIC chips organized in vertical stack of rows.
+Each DILOGIC chip serves 48 channels for the 8x6 pads (reffered in the code as kDilX,kDilY). Channels counted from 0 to 47.
+
+The mapping inside DILOGIC chip has the following structure (see from electronics side):
+
+5 04 10 16 22 28 34 40 46
+4 02 08 14 20 26 32 38 44
+3 00 06 12 18 24 30 36 42
+2 01 07 13 19 25 31 37 43
+1 03 09 15 21 27 33 39 45
+0 05 11 17 23 29 35 41 47
+
+ 0 1 2 3 4 5 6 7 padx
+
+10 DILOGIC chips composes so called "row" in horizontal direction (reffered in the code as kNdil), so the row is 80x6 pads structure.
+DILOGIC chips in the row are counted from right to left as seen from electronics side, from 1 to 10.
+24 rows are piled up forming the whole FEE served by single D-RORC, so one DDL sees 80x144 pads separated in 3 photocathodes.
+Rows are counted from 1 to 24 from top to bottom for right half of the chamber (PCs 1-3-5) as seen from electronics side, meaning even LDC number
+ and from bottom to top for left half of the chamber (PCs 0-2-4) as seen from electronics side, meaning odd LDC number.
+
+HMPID raw word is 32 bits with the structure:
+ 00000 rrrrr dddd aaaaaa qqqqqqqqqqqq
+ 5 bits zero 5 bits row number (1..24) 4 bits DILOGIC chip number (1..10) 6 bits DILOGIC address (0..47) 12 bits QDC value (0..4095)
+*/
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Float_t AliHMPIDDigit::Hit2Sdi(AliHMPIDHit *pHit,TClonesArray *pSdiLst)
+{
+// Creates a list of sdigits out of provided hit
+// Arguments: pHit- hit
+// Returns: none
+
+ Float_t x=(pHit->LorsX() > SizePcX())? pHit->LorsX()-SizePcX()-SizeDead():pHit->LorsX(); //sagita is for PC (0-64) and not for chamber
+ Float_t qdcEle=34.06311+0.2337070*x+5.807476e-3*x*x-2.956471e-04*x*x*x+2.310001e-06*x*x*x*x; //reparametrised from DiMauro
+
+ Int_t iNele=Int_t(pHit->E()/26e-9); if(iNele<1) iNele=1; //number of electrons created by hit
+ Float_t qdcTot=0; for(Int_t i=1;i<=iNele;i++) qdcTot-=qdcEle*TMath::Log(gRandom->Rndm()+1e-6); //total qdc fro hit, 1e-6 is a protection against 0 from rndm
+
+ AliHMPIDDigit dd(1,1,1,pHit->LorsX(),pHit->LorsY()); //tmp digit to shift hit y to the nearest anod wire
+ Float_t y= (pHit->LorsY() > dd.LorsY()) ? dd.LorsY()+0.21 : dd.LorsY()-0.21;
+
+ Int_t iSdiCnt=pSdiLst->GetEntries();
+ for(Int_t i=0;i<9;i++){ //affected pads loop
+ AliHMPIDDigit dig(pHit->Ch(),qdcTot,pHit->Tid(),pHit->LorsX(),y,i); //c,q,tid,x,y create tmp sdigit for pad i around hit position
+ if(dig.PadX()==-1) continue;
+ new((*pSdiLst)[iSdiCnt++]) AliHMPIDDigit(dig);
+ }
+ return qdcTot;
+}//Hit2Sdi()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::Print(Option_t*)const
+{
+// Print current digit
+// Arguments: option string not used
+// Returns: none
+ Printf("pad=(%2i,%2i,%3i,%3i),pos=(%7.2f,%7.2f) QDC=%8.3f, TID=(%5i,%5i,%5i) raw r=%2i d=%2i a=%2i",
+ Ch(),Pc(),PadX(),PadY(),LorsX(),LorsY(), Q(), fTracks[0],fTracks[1],fTracks[2], Row(), Dilogic(), Addr());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::PrintSize()
+{
+// Print all segmentaion related sizes
+// Arguments: none
+// Returns: none
+ Printf("-->pad =(%6.2f,%6.2f) cm dead zone %.2f cm\n"
+ "-->PC =(%6.2f,%6.2f) cm\n"
+ "-->all PCs=(%6.2f,%6.2f) cm",
+ SizePadX(),SizePadY(),SizeDead(),SizePcX(),SizePcY(),SizeAllX(),SizeAllY());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::TestSeg()
+{
+// Draws the picture of segmentation
+// Arguments: none
+// Returns: none
+ TCanvas *pC=new TCanvas("pads","View from electronics side, IP is behind the picture.");pC->ToggleEventStatus();
+ gPad->AddExec("test","AliHMPIDDigit::Zoom()");
+ DrawPc();
+}//TestSeg()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::Zoom()
+{
+// Show info about current cursur position in status bar of the canvas
+// Arguments: none
+// Returns: none
+ TCanvas *pC=(TCanvas*)gPad;
+ TRootCanvas *pRC= (TRootCanvas*)pC->GetCanvasImp();
+ TGStatusBar *pBar=pRC->GetStatusBar();
+ pBar->SetParts(5);
+ Float_t x=gPad->AbsPixeltoX(gPad->GetEventX());
+ Float_t y=gPad->AbsPixeltoY(gPad->GetEventY());
+ AliHMPIDDigit dig(1,100,1,x,y);
+ if(IsInDead(x,y))
+ pBar->SetText("Out of sensitive area",4);
+ else
+ pBar->SetText(Form("p%i x%i y%i r%i d%i a%i (%.2f,%.2f)",dig.Pc(),dig.PadX(),dig.PadY(),dig.Row(),dig.Dilogic(),dig.Addr(),dig.LorsX(),dig.LorsY()),4);
+ if(gPad->GetEvent()==1){
+ new TCanvas("zoom",Form("Row %i DILOGIC %i",dig.Row(),dig.Dilogic()));
+ }
+}//Zoom()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::DrawPc(Bool_t isFill)
+{
+// Utility methode draws HMPID chamber PCs on event display.
+// Arguments: none
+// Returns: none
+// y6 ---------- ----------
+// | | | |
+// | 4 | | 5 |
+// y5 ---------- ----------
+//
+// y4 ---------- ----------
+// | | | |
+// | 2 | | 3 | view from electronics side
+// y3 ---------- ----------
+//
+// y2 ---------- ----------
+// | | | |
+// | 0 | | 1 |
+// y1 ---------- ----------
+// x1 x2 x3 x4
+ gPad->Range(-5,-5,SizeAllX()+5,SizeAllY()+5);
+ Float_t x1=0,x2=SizePcX(),x3=SizePcX()+SizeDead(), x4=SizeAllX();
+ Float_t y1=0,y2=SizePcY(),y3=SizePcY()+SizeDead(),y4=2*SizePcY()+SizeDead(),y5=SizeAllY()-SizePcY(),y6=SizeAllY();
+
+ Float_t xL[5]={x1,x1,x2,x2,x1}; //clockwise
+ Float_t xR[5]={x3,x3,x4,x4,x3};
+ Float_t yD[5]={y1,y2,y2,y1,y1};
+ Float_t yC[5]={y3,y4,y4,y3,y3};
+ Float_t yU[5]={y5,y6,y6,y5,y5};
+
+ TLatex t; t.SetTextSize(0.01); t.SetTextAlign(22);
+ Int_t iColLeft=29,iColRight=41;
+ TPolyLine *pc=0; TLine *pL; Float_t x0=0,y0=0,wRow=kDilY*SizePadY(),wDil=kDilX*SizePadX();
+ for(Int_t iPc=0;iPc<kPcAll;iPc++){
+ if(iPc==4) {pc=new TPolyLine(5,xL,yU);t.DrawText(x1-3.5,y6-20,"PC4");x0=x1;y0=y5;} if(iPc==5) {pc=new TPolyLine(5,xR,yU);t.DrawText(x4+3.5,y6-20,"PC5");x0=x3;y0=y5;}
+ if(iPc==2) {pc=new TPolyLine(5,xL,yC);t.DrawText(x1-3.5,y4-20,"PC2");x0=x1;y0=y3;} if(iPc==3) {pc=new TPolyLine(5,xR,yC);t.DrawText(x4+3.5,y4-20,"PC3");x0=x3;y0=y3;}
+ if(iPc==0) {pc=new TPolyLine(5,xL,yD);t.DrawText(x1-3.5,y2-20,"PC0");x0=x1;y0=y1;} if(iPc==1) {pc=new TPolyLine(5,xR,yD);t.DrawText(x4+3.5,y2-20,"PC1");x0=x3;y0=y1;}
+ (iPc%2)? pc->SetFillColor(iColLeft): pc->SetFillColor(iColRight);
+ if(isFill) pc->Draw("f"); else pc->Draw();
+ for(Int_t i=1;i<=8 ;i++){//draw row lines (horizontal)
+ Float_t y=y0+i*wRow;
+ Int_t row=i+iPc/2*8; if(iPc%2!=0) row=25-row; t.DrawText(x0-1,y -3,Form("r%i",row));
+ if(i==8) break; //do not draw the last line of PC
+ pL=new TLine(x0,y,x0+SizePcX(),y); pL->Draw();
+ }
+ for(Int_t iDil=1;iDil<=10;iDil++){Float_t x=x0+iDil*wDil;t.DrawText(x -3,y0-1,Form("d%i",11-iDil)); if(iDil==10) break; pL=new TLine(x,y0,x,y0+SizePcY()); pL->Draw();}
+ }
+}//DrawPc()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDDigit_h
+#define AliHMPIDDigit_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include <AliDigit.h> //base class
+#include <TMath.h> //Mathieson()
+#include <TRandom.h> //IsOverTh()
+#include <AliBitPacking.h> //Raw()
+
+class AliHMPIDHit; //Hit2Sdi()
+class TClonesArray; //Hit2Sdi()
+
+class AliHMPIDDigit :public AliDigit //TObject-AliDigit-AliHMPIDDigit
+{
+public:
+ enum EAbsPad {kChAbs=100000000,kPcAbs=1000000,kPadAbsX=1000,kPadAbsY=1}; //absolute pad number structure
+ enum ERawData{kDilX=8,kDilY=6,kNdil=10,kNrow=24,kNddls=14}; //RAW data structure
+ enum EPadData{kPcX=2,kPcY=3,kPad1=0,kPadPcX=80,kPadPcY=48,kPadAllX=kPadPcX*kPcX,kPadAllY=kPadPcY*kPcY,kPcAll=kPcX*kPcY,kPadAll=kPadAllX*kPadAllY}; //Segmentation structure
+ enum EPadShif{kC=0,kU=1,kUR=2,kR=3,kDR=4,kD=5,kDL=6,kL=7,kUL=8};
+//ctor&dtor
+ AliHMPIDDigit( ):AliDigit( ),fPad(Abs(-1,-1,-1,-1)),fQ(-1) {} //default ctor
+ AliHMPIDDigit(Int_t pad,Int_t q,Int_t *t ):AliDigit(t),fPad(pad ),fQ(q ) {} //digit ctor
+ inline AliHMPIDDigit(Int_t c,Float_t q,Int_t t,Float_t x,Float_t y,Int_t f=0); //sdigit ctor
+ virtual ~AliHMPIDDigit() {} //dtor
+//framework part
+ Bool_t IsSortable ( )const{return kTRUE;} //provision to use TObject::Sort()
+ inline Int_t Compare (const TObject *pObj )const; //provision to use TObject::Sort()
+ void Print (Option_t *opt="" )const; //TObject::Print() overloaded
+//private part
+ static Int_t Abs (Int_t c,Int_t s,Int_t x,Int_t y) {return c*kChAbs+s*kPcAbs+x*kPadAbsX+y*kPadAbsY; } //(ch,pc,padx,pady)-> abs pad
+ static Int_t A2C (Int_t pad ) {return pad/kChAbs; } //abs pad -> chamber
+ static Int_t A2P (Int_t pad ) {return pad%kChAbs/kPcAbs; } //abs pad -> pc
+ static Int_t A2X (Int_t pad ) {return pad%kPcAbs/kPadAbsX; } //abs pad -> pad X
+ static Int_t A2Y (Int_t pad ) {return pad%kPadAbsX; } //abs pad -> pad Y
+ Int_t Addr ( )const{Int_t mapY2A[kDilY]={5,3,1,0,2,4}; return mapY2A[A2Y(fPad)%kDilY]+kDilY*(A2X(fPad)%kDilX);}//raw a=0..47
+ void AddTidOffset(Int_t offset ) {for (Int_t i=0; i<3; i++) if (fTracks[i]>0) fTracks[i]+=offset;}; //needed for merging
+ Int_t Ch ( )const{return A2C(fPad); } //chamber number
+ Int_t Dilogic ( )const{return 10-PadX()/kDilX; } //raw d=1..10
+ static void DrawPc (Bool_t isFill=kTRUE ); //draw PCs
+ Int_t Ddl ( )const{return (PadX()<kPadPcX) ? 2*Ch() : 2*Ch()+1; } //DDL number 0..13
+ static Float_t Hit2Sdi (AliHMPIDHit *pHit,TClonesArray *); //hit -> 9 sdigits, returns total QDC
+ static Bool_t IsOverTh (Float_t q ) {return q > 6; } //is digit over threshold????
+ static Bool_t IsInside (Float_t x,Float_t y ) {return x>0&&y>0&&x<SizeAllX()&&y<SizeAllY(); } //is point inside pc boundary?
+ inline static Bool_t IsInDead (Float_t x,Float_t y ); //is point in dead area?
+ Float_t LorsX ( )const{return (PadX()+0.5)*SizePadX()+(Pc()%2)*(SizePcX()+SizeDead());} //center of the pad x, [cm]
+ Float_t LorsY ( )const{return (PadY()+0.5)*SizePadY()+(Pc()/2)*(SizePcY()+SizeDead());} //center of the pad y, [cm]
+ inline Float_t Mathieson (Float_t x,Float_t y )const; //Mathieson distribution
+ Int_t PadX ( )const{return A2X(fPad);} //x position of the pad
+ Int_t PadY ( )const{return A2Y(fPad);} //y postion of the pad
+ Int_t Pad ( )const{return fPad;} //absolute id of this pad
+ Float_t Q ( )const{return fQ;} //charge, [QDC]
+ Int_t Pc ( )const{return A2P(fPad);} //PC position number
+ static void PrintSize ( ); //print all segmentation sizes
+ inline Int_t Raw (UInt_t &w32 )const; //raw
+ Int_t Row ( )const{Int_t r=1+Pc()/2*8+PadY()/kDilY; return (Pc()%2)?kNrow-r+1:r;} //row r=1..24
+ void Set (Int_t c,Int_t s,Int_t x,Int_t y) {fPad=Abs(c,s,x,y);} //set new digit
+ void ReadRaw (Int_t ddl,Int_t r,Int_t d,Int_t a){Int_t mapA2Y[kDilY]={3,2,4,1,5,0};fPad=Abs(ddl/2,ddl%7,d*kDilX+a/kDilY,r*kDilY+mapA2Y[a%kDilY]);} //from raw
+ inline void ReadRaw (Int_t ddl,UInt_t w32 ); //read raw word
+
+ static Float_t SizeAllX ( ) {return SizePadX()*kPadAllX+SizeDead();} //all PCs size x, [cm]
+ static Float_t SizeAllY ( ) {return SizePadY()*kPadAllY+2*SizeDead();} //all PCs size y, [cm]
+ static Float_t SizeArea ( ) {return SizePcX()*SizePcY()*kPcAll;} //sence area, [cm^2]
+ static Float_t SizeDead ( ) {return 2.6;} //dead zone size x, [cm]
+ static Float_t SizeGap ( ) {return 8; }
+ static Float_t SizePadX ( ) {return 0.8;} //pad size x, [cm]
+ static Float_t SizePadY ( ) {return 0.84;} //pad size y, [cm]
+ static Float_t SizePcX ( ) {return SizePadX()*kPadPcX;} //PC size x, [cm]
+ static Float_t SizePcY ( ) {return SizePadY()*kPadPcY;} //PC size y, [cm]
+ static Float_t SizeWin ( ) {return 0.5;}
+ static Float_t SizeRad ( ) {return 1.5;}
+ static void TestSeg ( ); //test segmentation
+ void Zoom ( );
+protected: //AliDigit has fTracks[3]
+ Int_t fPad; //absolute pad number is chamber*kCham
+ Float_t fQ; //QDC value, fractions are permitted for summable procedure
+ ClassDef(AliHMPIDDigit,4) //HMPID digit class
+};//class AliHMPIDDigitN
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDDigit::AliHMPIDDigit(Int_t c,Float_t q,Int_t t,Float_t x,Float_t y,Int_t flag):AliDigit(),fPad(Abs(-1,-1,-1,-1)),fQ(-1)
+{
+// Creation of sdigit
+// Arguments: c- chamber
+// q- total QDC
+// t -TID
+// x,y - hit position, LORS
+// Returns: none
+ Int_t pc,padx,pady;
+ if (x>= 0 && x<= SizePcX() ) {pc=0; padx=Int_t( x / SizePadX());}//PC 0 or 2 or 4
+ else if(x>=SizePcX()+SizeDead() && x<= SizeAllX() ) {pc=1; padx=Int_t((x- SizePcX()- SizeDead()) / SizePadX());}//PC 2 or 4 or 6
+ else return;
+ if (y>= 0 && y<= SizePcY() ) { pady=Int_t( y / SizePadY());}//PC 0 or 1
+ else if(y>=SizePcY()+SizeDead() && y<=2*SizePcY()+SizeDead() ) {pc+=2;pady=Int_t((y- SizePcY()- SizeDead()) / SizePadY());}//PC 2 or 3
+ else if(y>=SizeAllY()-SizePcY() && y<= SizeAllY() ) {pc+=4;pady=Int_t((y-2*SizePcY()-2*SizeDead()) / SizePadY());}//PC 4 or 5
+ else return;
+
+ switch(flag){
+ case kUL:padx--;pady++;break; case kU:pady++;break; case kUR:padx++; pady++;break;
+
+ case kL: padx--; break; case kC: break; case kR:padx++; break;
+
+ case kDL:padx--;pady--;break; case kD:pady--;break; case kDR:padx++; pady--;break;
+ }
+ if(padx<0 || padx>=kPadPcX) return;
+ if(pady<0 || pady>=kPadPcY) return;
+ fPad=Abs(c,pc,padx,pady);
+ fQ=q*Mathieson(x,y);
+ fTracks[0]=t;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDDigit::Compare(const TObject *pObj) const
+{
+// Used in Sort() method to compare to objects. Note that abs pad structure is first x then y, hence will be sorted on column basis.
+// This feature is used in digitizer to facilitate finding of sdigits for the same pad since they all will come together after sorting.
+// Arguments: pObj - pointer to object to compare with
+// Retunrs: -1 if AbsPad less then in pObj, 1 if more and 0 if they are the same
+ if (fPad==((AliHMPIDDigit*)pObj)->Pad()) return 0;
+ else if(fPad >((AliHMPIDDigit*)pObj)->Pad()) return 1;
+ else return -1;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDDigit::IsInDead(Float_t x,Float_t y)
+{
+// Check is the current point is outside of sensitive area or in dead zones
+// Arguments: x,y -position
+// Returns: 1 if not in sensitive zone
+ if(x<0 || x>SizeAllX() || y<0 || y>SizeAllY()) return kTRUE; //out of pc
+
+ if(x>SizePcX() && x<SizePcX()+SizeDead()) return kTRUE; //in dead zone along x
+
+ if(y>SizePcY() && y<SizePcY()+SizeDead()) return kTRUE; //in first dead zone along y
+ if(y>SizeAllY()-SizePcY()-SizeDead() && y<SizeAllY()-SizePcY()) return kTRUE; //in second dead zone along y
+ return kFALSE;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Float_t AliHMPIDDigit::Mathieson(Float_t x,Float_t y)const
+{
+// This is the answer to electrostatic problem of charge distrubution in MWPC described elsewhere. (NIM A370(1988)602-603)
+// Arguments: x,y- position of the center of Mathieson distribution
+// Returns: a charge fraction [0-1] imposed into the pad
+ const Float_t kSqrtK3=0.77459667,k2=0.962,k4=0.379;
+
+ Float_t ux1=kSqrtK3*TMath::TanH(k2*(x-LorsX()+0.5*SizePadX())/0.425);
+ Float_t ux2=kSqrtK3*TMath::TanH(k2*(x-LorsX()-0.5*SizePadX())/0.425);
+ Float_t uy1=kSqrtK3*TMath::TanH(k2*(y-LorsY()+0.5*SizePadY())/0.425);
+ Float_t uy2=kSqrtK3*TMath::TanH(k2*(y-LorsY()-0.5*SizePadY())/0.425);
+ return 4*k4*(TMath::ATan(ux2)-TMath::ATan(ux1))*k4*(TMath::ATan(uy2)-TMath::ATan(uy1));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDDigit::Raw(UInt_t &w32)const
+{
+// Convert digit structure to raw word format
+// Arguments: 32 bits raw word to fill
+// Returns: DDL ID where to write this digit
+ w32=0;
+ AliBitPacking::PackWord((UInt_t)fQ ,w32, 0,11); // 0000 0rrr rrdd ddaa aaaa qqqq qqqq qqqq Qdc bits (00..11) counts (0..4095)
+ AliBitPacking::PackWord( Addr() ,w32,12,17); // 3322 2222 2222 1111 1111 1000 0000 0000 DILOGIC address bits (12..17) counts (0..47)
+ AliBitPacking::PackWord( Dilogic(),w32,18,21); // 1098 7654 3210 9876 5432 1098 7654 3210 DILOGIC number bits (18..21) counts (1..10)
+ AliBitPacking::PackWord( Row() ,w32,22,26); // Row number bits (22..26) counts (1..24)
+ return Ddl(); //ddl 0..13 where to write this digit
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigit::ReadRaw(Int_t ddl,UInt_t w32)
+{
+// Converts a given raw data word to a digit
+// Arguments: w32 - 32 bits raw data word
+// ddl - DDL idx 0 1 2 3 4 ... 13
+// Returns: none
+ fQ = AliBitPacking::UnpackWord(w32, 0,11); // 0000 0rrr rrdd ddaa aaaa qqqq qqqq qqqq Qdc bits (00..11) counts (0..4095)
+ UInt_t a = AliBitPacking::UnpackWord(w32,12,17); // 3322 2222 2222 1111 1111 1000 0000 0000 DILOGIC address bits (12..17) counts (0..47)
+ UInt_t d = AliBitPacking::UnpackWord(w32,18,21); // 1098 7654 3210 9876 5432 1098 7654 3210 DILOGIC number bits (18..21) counts (1..10)
+ UInt_t r = AliBitPacking::UnpackWord(w32,22,26); // Row number bits (22..26) counts (1..24)
+ ReadRaw(ddl,r,d,a);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+#include "AliHMPIDDigitN.h"//class header
+#include <TCanvas.h> //TestSeg()
+#include <TLine.h> //TestSeg()
+#include <TLatex.h> //TestSeg()
+#include <TPolyLine.h> //DrawPc()
+#include <TGStatusBar.h> //Zoom()
+#include <TRootCanvas.h> //Zoom()
+ClassImp(AliHMPIDDigitN)
+
+/*
+Any given LDC collects data from a number of D-RORC cards connected to this same LDC by separate DDLs. This data is stored in corresponding number
+of DDL buffers.
+
+Each DDL buffer corresponds to a single D-RORC. The data this buffer contains are hardware generated by D-RORC. The buffer starts with common header
+which size and structure is standartized and mandatory for all detectors.
+The header contains among other words, so called Equipment ID word. This unique value for each D-RORC is calculated as detector ID << 8 + DDL index.
+For HMPID the detector ID is 6 (reffered in the code as kRichRawId) while DDL indexes are from 0 to 13.
+
+Common header might be followed by the private one although HMPID has no any private header, just uses the common one.
+
+Single HMPID D-RORC serves one half of a chamber i.e. 3 photocathodes even LDC for left part( PCs 0-2-4) and odd LDC for right part(1-3-5)
+as it's seen from electronics side.
+
+So the LDC -chamber-ddl map is:
+DDL index 0 -> ch 1 left -> DDL ID 0x600 DDL index 1 -> ch 1 right -> DDL ID 0x601
+DDL index 2 -> ch 2 left -> DDL ID 0x602 DDL index 3 -> ch 2 right -> DDL ID 0x603
+DDL index 4 -> ch 3 left -> DDL ID 0x604 DDL index 5 -> ch 3 right -> DDL ID 0x605
+DDL index 6 -> ch 4 left -> DDL ID 0x606 DDL index 7 -> ch 4 right -> DDL ID 0x607
+DDL index 8 -> ch 5 left -> DDL ID 0x608 DDL index 9 -> ch 5 right -> DDL ID 0x609
+DDL index 10 -> ch 6 left -> DDL ID 0x60a DDL index 11 -> ch 6 right -> DDL ID 0x60b
+DDL index 12 -> ch 7 left -> DDL ID 0x60c DDL index 13 -> ch 7 right -> DDL ID 0x60d
+
+HMPID FEE as seen by single D-RORC is composed from a number of DILOGIC chips organized in vertical stack of rows.
+Each DILOGIC chip serves 48 channels for the 8x6 pads (reffered in the code as kDilX,kDilY). Channels counted from 0 to 47.
+
+The mapping inside DILOGIC chip has the following structure (see from electronics side):
+
+5 04 10 16 22 28 34 40 46
+4 02 08 14 20 26 32 38 44
+3 00 06 12 18 24 30 36 42
+2 01 07 13 19 25 31 37 43
+1 03 09 15 21 27 33 39 45
+0 05 11 17 23 29 35 41 47
+
+ 0 1 2 3 4 5 6 7 padx
+
+10 DILOGIC chips composes so called "row" in horizontal direction (reffered in the code as kNdil), so the row is 80x6 pads structure.
+DILOGIC chips in the row are counted from right to left as seen from electronics side, from 1 to 10.
+24 rows are piled up forming the whole FEE served by single D-RORC, so one DDL sees 80x144 pads separated in 3 photocathodes.
+Rows are counted from 1 to 24 from top to bottom for right half of the chamber (PCs 1-3-5) as seen from electronics side, meaning even LDC number
+ and from bottom to top for left half of the chamber (PCs 0-2-4) as seen from electronics side, meaning odd LDC number.
+
+HMPID raw word is 32 bits with the structure:
+ 00000 rrrrr dddd aaaaaa qqqqqqqqqqqq
+ 5 bits zero 5 bits row number (1..24) 4 bits DILOGIC chip number (1..10) 6 bits DILOGIC address (0..47) 12 bits QDC value (0..4095)
+*/
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitN::Print(Option_t*)const
+{
+// Print current digit
+// Arguments: option string not used
+// Returns: none
+ Printf("pad=(%2i,%2i,%3i,%3i),pos=(%.2f,%.2f) QDC=%8.3f, TID=(%5i,%5i,%5i) raw r=%2i d=%2i a=%2i",
+ Ch(),Pc(),PadX(),PadY(),LorsX(),LorsY(), Qdc(), fTracks[0],fTracks[1],fTracks[2], Row(), Dilogic(), Addr());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitN::PrintSize()
+{
+// Print all segmentaion related sizes
+// Arguments: none
+// Returns: none
+ Printf("-->pad =(%6.2f,%6.2f) cm dead zone %.2f cm\n"
+ "-->PC =(%6.2f,%6.2f) cm\n"
+ "-->all PCs=(%6.2f,%6.2f) cm",
+ SizePadX(),SizePadY(),SizeDead(),SizePcX(),SizePcY(),SizeAllX(),SizeAllY());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitN::TestSeg()
+{
+// Draws the picture of segmentation
+// Arguments: none
+// Returns: none
+ TCanvas *pC=new TCanvas("pads","View from electronics side, IP is behind the picture.");pC->ToggleEventStatus();
+ gPad->AddExec("test","AliHMPIDDigitN::Zoom()");
+ DrawPc();
+}//TestSeg()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitN::Zoom()
+{
+// Show info about current cursur position in status bar of the canvas
+// Arguments: none
+// Returns: none
+ TCanvas *pC=(TCanvas*)gPad;
+ TRootCanvas *pRC= (TRootCanvas*)pC->GetCanvasImp();
+ TGStatusBar *pBar=pRC->GetStatusBar();
+ pBar->SetParts(5);
+ Float_t x=gPad->AbsPixeltoX(gPad->GetEventX());
+ Float_t y=gPad->AbsPixeltoY(gPad->GetEventY());
+ AliHMPIDDigitN dig(1,x,y,100);
+ pBar->SetText(Form("(p=%i,x=%i,y=%i) (r%i d%i a%i)",dig.Pc(),dig.PadX(),dig.PadY(),dig.Row(),dig.Dilogic(),dig.Addr()),4);
+ if(gPad->GetEvent()==1){
+ new TCanvas("zoom",Form("Row %i DILOGIC %i",dig.Row(),dig.Dilogic()));
+ }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitN::DrawPc()
+{
+// Utility methode draws HMPID chamber PCs on event display.
+// Arguments: none
+// Returns: none
+// y6 ---------- ----------
+// | | | |
+// | 4 | | 5 |
+// y5 ---------- ----------
+//
+// y4 ---------- ----------
+// | | | |
+// | 2 | | 3 | view from electronic side
+// y3 ---------- ----------
+//
+// y2 ---------- ----------
+// | | | |
+// | 0 | | 1 |
+// y1 ---------- ----------
+// x1 x2 x3 x4
+ gPad->Range(-5,-5,SizeAllX()+5,SizeAllY()+5);
+ Float_t x1=0,x2=SizePcX(),x3=SizePcX()+SizeDead(), x4=SizeAllX();
+ Float_t y1=0,y2=SizePcY(),y3=SizePcY()+SizeDead(),y4=2*SizePcY()+SizeDead(),y5=SizeAllY()-SizePcY(),y6=SizeAllY();
+
+ Float_t xL[5]={x1,x1,x2,x2,x1}; //clockwise
+ Float_t xR[5]={x3,x3,x4,x4,x3};
+ Float_t yD[5]={y1,y2,y2,y1,y1};
+ Float_t yC[5]={y3,y4,y4,y3,y3};
+ Float_t yU[5]={y5,y6,y6,y5,y5};
+
+ TLatex t; t.SetTextSize(0.01); t.SetTextAlign(22);
+ Int_t iColLeft=29,iColRight=41;
+ TPolyLine *pc=0; TLine *pL; Float_t x0=0,y0=0,wRow=kDilY*SizePadY(),wDil=kDilX*SizePadX();
+ for(Int_t iPc=0;iPc<kNpc;iPc++){
+ if(iPc==4) {pc=new TPolyLine(5,xL,yU);t.DrawText(x1-3.5,y6-20,"PC4");x0=x1;y0=y5;} if(iPc==5) {pc=new TPolyLine(5,xR,yU);t.DrawText(x4+3.5,y6-20,"PC5");x0=x3;y0=y5;}
+ if(iPc==2) {pc=new TPolyLine(5,xL,yC);t.DrawText(x1-3.5,y4-20,"PC2");x0=x1;y0=y3;} if(iPc==3) {pc=new TPolyLine(5,xR,yC);t.DrawText(x4+3.5,y4-20,"PC3");x0=x3;y0=y3;}
+ if(iPc==0) {pc=new TPolyLine(5,xL,yD);t.DrawText(x1-3.5,y2-20,"PC0");x0=x1;y0=y1;} if(iPc==1) {pc=new TPolyLine(5,xR,yD);t.DrawText(x4+3.5,y2-20,"PC1");x0=x3;y0=y1;}
+ (iPc%2)? pc->SetFillColor(iColLeft): pc->SetFillColor(iColRight);
+ pc->Draw("f");
+ for(Int_t i=1;i<=8 ;i++){//draw row lines (horizontal)
+ Float_t y=y0+i*wRow;
+ Int_t row=i+iPc/2*8; if(iPc%2!=0) row=25-row; t.DrawText(x0-1,y -3,Form("r%i",row));
+ if(i==8) break; //do not draw the last line of PC
+ pL=new TLine(x0,y,x0+SizePcX(),y); pL->Draw();
+ }
+ for(Int_t iDil=1;iDil<=10;iDil++){Float_t x=x0+iDil*wDil;t.DrawText(x -3,y0-1,Form("d%i",11-iDil)); if(iDil==10) break; pL=new TLine(x,y0,x,y0+SizePcY()); pL->Draw();}
+ }
+}//DrawPc()
--- /dev/null
+#ifndef AliHMPIDDigitN_h
+#define AliHMPIDDigitN_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include <AliDigit.h> //base class
+
+class AliHMPIDDigitN :public AliDigit //TObject-AliDigit-AliHMPIDDigit
+{
+public:
+ enum EAbsPad {kChAbs=100000000,kPcAbs=1000000,kPadAbsX=1000,kPadAbsY=1}; //absolute pad number structure
+ enum ERawData{kDilX=8,kDilY=6,kNdil=10,kNrow=24,kNddls=14}; //RAW data structure
+ enum EPadData{kPadsPcX=80,kPadsPcY=48,kPadsChamX=160,kPadsChamY=144,kNpc=6}; //Segmentation structure
+//ctor&dtor
+ AliHMPIDDigitN( ):AliDigit(),fPad(Abs(-1,-1,-1,-1)) ,fQdc(-1) {} //default ctor
+ inline AliHMPIDDigitN(Int_t c,Float_t x,Float_t y,Float_t q); //ctor
+ virtual ~AliHMPIDDigitN() {} //dtor
+//framework part
+ Bool_t IsSortable ( )const{return kTRUE;} //provision to use TObject::Sort()
+ inline Int_t Compare (const TObject *pObj )const; //provision to use TObject::Sort()
+ void Print (Option_t *opt="" )const; //TObject::Print() overloaded
+//private part
+ static Int_t Abs (Int_t c,Int_t s,Int_t x,Int_t y) {return c*kChAbs+s*kPcAbs+x*kPadAbsX+y*kPadAbsY; } //(ch,pc,padx,pady)-> abs pad
+ static Int_t A2C (Int_t pad ) {return pad/kChAbs; } //abs pad -> chamber
+ static Int_t A2P (Int_t pad ) {return pad%kChAbs/kPcAbs; } //abs pad -> pc
+ static Int_t A2X (Int_t pad ) {return pad%kPcAbs/kPadAbsX; } //abs pad -> pad X
+ static Int_t A2Y (Int_t pad ) {return pad%kPadAbsX; } //abs pad -> pad Y
+ Int_t Addr ( )const{Int_t mapY2A[kDilY]={5,3,1,0,2,4}; return mapY2A[A2Y(fPad)%kDilY]+kDilY*(A2X(fPad)%kDilX);}//raw a=0..47
+ void AddTidOffset(Int_t offset ) {for (Int_t i=0; i<3; i++) if (fTracks[i]>0) fTracks[i]+=offset;}; //needed for merging
+ Int_t Ch ( )const{return A2C(fPad); } //chamber number
+ Int_t Dilogic ( )const{return 10-PadX()/kDilX; } //raw d=1..10
+ static void DrawPc ( ); //draw PCs
+ Int_t Ddl ( )const{return (PadX()<kPadsPcX) ? 2*Ch()-2 : 2*Ch()-1;} //DDL number 0..13
+ Float_t LorsX ( )const{return (PadX()+0.5)*SizePadX()+(Pc()%2)*(SizePcX()+SizeDead());} //center of the pad x, [cm]
+ Float_t LorsY ( )const{return (PadY()+0.5)*SizePadY()+(Pc()/2)*(SizePcY()+SizeDead());} //center of the pad y, [cm]
+ Int_t PadX ( )const{return A2X(fPad);} //x position of the pad
+ Int_t PadY ( )const{return A2Y(fPad);} //y postion of the pad
+ Int_t Pad ( )const{return fPad;} //absolute id of this pad
+ Float_t Qdc ( )const{return fQdc;} //charge, [QDC]
+ Int_t Pc ( )const{return A2P(fPad);} //PC position number
+ static void PrintSize ( ); //print all segmentation sizes
+ Int_t Row ( )const{Int_t r=1+Pc()/2*8+PadY()/kDilY; return (Pc()%2)?kNrow-r+1:r;} //row r=1..24
+ void Set (Int_t c,Int_t s,Int_t x,Int_t y) {fPad=Abs(c,s,x,y);} //set new digit
+ void ReadRaw (Int_t ddl,Int_t r,Int_t d,Int_t a){Int_t mapA2Y[kDilY]={3,2,4,1,5,0};fPad=Abs(ddl/2,ddl%7,d*kDilX+a/kDilY,r*kDilY+mapA2Y[a%kDilY]);} //from raw
+ static Float_t SizePadX ( ) {return 0.8;} //pad size x, [cm]
+ static Float_t SizePadY ( ) {return 0.84;} //pad size y, [cm]
+ static Float_t SizePcX ( ) {return SizePadX()*kPadsPcX;} //PC size x, [cm]
+ static Float_t SizePcY ( ) {return SizePadY()*kPadsPcY;} //PC size y, [cm]
+ static Float_t SizeAllX ( ) {return SizePadX()*kPadsChamX+SizeDead();} //all PCs size x, [cm]
+ static Float_t SizeAllY ( ) {return SizePadY()*kPadsChamY+2*SizeDead();} //all PCs size y, [cm]
+ static Float_t SizeDead ( ) {return 2.6;} //dead zone size x, [cm]
+ static void TestSeg ( ); //test segmentation
+ void Zoom ( );
+protected:
+ Int_t fPad; //absolute pad number is chamber*kCham
+ Float_t fQdc; //QDC value, fractions are permitted for summable procedure
+ ClassDef(AliHMPIDDigitN,4) //HMPID digit class
+};//class AliHMPIDDigitN
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDDigitN::Compare(const TObject *pObj) const
+{
+// Used in Sort() method to compare to objects. Note that abs pad structure is first x then y, hence will be sorted on column basis.
+// This feature is used in digitizer to facilitate finding of sdigits for the same pad since they all will come together after sorting.
+// Arguments: pObj - pointer to object to compare with
+// Retunrs: -1 if AbsPad less then in pObj, 1 if more and 0 if they are the same
+ if (fPad==((AliHMPIDDigitN*)pObj)->Pad()) return 0;
+ else if(fPad >((AliHMPIDDigitN*)pObj)->Pad()) return 1;
+ else return -1;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDDigitN::AliHMPIDDigitN(Int_t c,Float_t x,Float_t y,Float_t q):AliDigit(),fPad(Abs(-1,-1,-1,-1)),fQdc(-1)
+{
+// Determines abs pad number containing the given point (x,y) defined in the chamber RS.
+// Pad count starts in lower left corner from 1,1 to 144,160 in upper right corner of a chamber.
+// y ^ 4 5
+// | 2 3
+// | 0 1
+// -------> x
+ Int_t pc,padx,pady;
+ if (x>= 0 && x<= SizePcX() ) {pc=0; padx=Int_t( x / SizePadX());}//PC 0 or 2 or 4
+ else if(x>=SizePcX()+SizeDead() && x<= SizeAllX() ) {pc=1; padx=Int_t((x- SizePcX()- SizeDead()) / SizePadX());}//PC 2 or 4 or 6
+ else return;
+ if (y>= 0 && y<= SizePcY() ) { pady=Int_t( y / SizePadY());}//PC 0 or 1
+ else if(y>=SizePcY()+SizeDead() && y<=2*SizePcY()+SizeDead() ) {pc+=2;pady=Int_t((y- SizePcY()- SizeDead()) / SizePadY());}//PC 2 or 3
+ else if(y>=SizeAllY()-SizePcY() && y<= SizeAllY() ) {pc+=4;pady=Int_t((y-2*SizePcY()-2*SizeDead()) / SizePadY());}//PC 4 or 5
+ else return;
+ fPad=Abs(c,pc,padx,pady);
+ fQdc=q;
+}
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+#include "AliHMPIDDigitizer.h"
+#include "AliHMPID.h"
+#include "AliHMPIDDigit.h"
+#include <AliRun.h>
+#include <AliRunLoader.h>
+#include "AliRunDigitizer.h"
+#include <AliLoader.h>
+#include <AliLog.h>
+
+
+ClassImp(AliHMPIDDigitizer)
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitizer::Exec(Option_t*)
+{
+// This methode is responsible for merging sdigits to a list of digits
+//Disintegration leeds to the fact that one hit affects several neighbouring pads, which means that the same pad might be affected by few hits.
+ AliDebug(1,Form("Start with %i input(s) for event %i",fManager->GetNinputs(),fManager->GetOutputEventNr()));
+//First we read all sdigits from all inputs
+ AliRunLoader *pInRunLoader=0;//in and out Run loaders
+ AliLoader *pInRichLoader=0;//in and out HMPID loaders
+ TClonesArray sdigs("AliHMPIDDigit");//tmp storage for sdigits sum up from all input files
+ Int_t total=0;
+ for(Int_t inFileN=0;inFileN<fManager->GetNinputs();inFileN++){//files loop
+ pInRunLoader = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inFileN)); //get run loader from current input
+ pInRichLoader = pInRunLoader->GetLoader("HMPIDLoader"); if(pInRichLoader==0) continue; //no HMPID in this input, check the next input
+ if (!pInRunLoader->GetAliRun()) pInRunLoader->LoadgAlice();
+ AliHMPID* pInRich=(AliHMPID*)pInRunLoader->GetAliRun()->GetDetector("HMPID"); //take HMPID from current input
+ pInRichLoader->LoadSDigits(); pInRichLoader->TreeS()->GetEntry(0); //take list of HMPID sdigits from current input
+ AliDebug(1,Form("input %i has %i sdigits",inFileN,pInRich->SdiLst()->GetEntries()));
+ for(Int_t i=0;i<pInRich->SdiLst()->GetEntries();i++){ //collect sdigits from current input
+ AliHMPIDDigit *pSDig=(AliHMPIDDigit*)pInRich->SdiLst()->At(i);
+ pSDig->AddTidOffset(fManager->GetMask(inFileN)); //apply TID shift since all inputs count tracks independently starting from 0
+ new(sdigs[total++]) AliHMPIDDigit(*pSDig);
+ }
+ pInRichLoader->UnloadSDigits(); pInRich->SdiReset(); //close current input and reset
+ }//files loop
+
+ //PH if(sdigs.GetEntries()==0) return; //no sdigits collected, nothing to convert
+
+ AliRunLoader *pOutRunLoader = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName()); //open output stream (only 1 possible)
+ AliLoader *pOutRichLoader = pOutRunLoader->GetLoader("HMPIDLoader"); //take output HMPID loader
+ AliHMPID *pOutRich = (AliHMPID*)pOutRunLoader->GetAliRun()->GetDetector("HMPID"); //take output HMPID
+ pOutRichLoader->MakeTree("D"); pOutRich->MakeBranch("D"); //create TreeD in output stream
+
+ Sdi2Dig(&sdigs,pOutRich->DigLst());
+
+ pOutRichLoader->TreeD()->Fill(); //fill the output tree with the list of digits
+ pOutRichLoader->WriteDigits("OVERWRITE"); //serialize them to file
+
+ sdigs.Clear(); //remove all tmp sdigits
+ pOutRichLoader->UnloadDigits(); pOutRich->DigReset();
+}//Exec()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDDigitizer::Sdi2Dig(TClonesArray *pSdiLst,TObjArray *pDigLst)
+{
+// Converts list of sdigits to 7 lists of digits, one per each chamber
+// Arguments: pSDigLst - list of all sdigits
+// pDigLst - list of 7 lists of digits
+// Returns: none
+
+ TClonesArray *pLst[7]; Int_t iCnt[7];
+
+ for(Int_t i=0;i<7;i++){
+ pLst[i]=(TClonesArray*)(*pDigLst)[i];
+ iCnt[i]=pLst[i]->GetEntries(); //in principle those lists should be empty
+ }
+
+ pSdiLst->Sort();
+
+ Int_t iPad=-1,iCh=-1,iNdigPad=-1,aTids[3]={-1,-1,-1}; Float_t q=-1;
+ for(Int_t i=0;i<pSdiLst->GetEntries();i++){ //sdigits loop (sorted)
+ AliHMPIDDigit *pSdig=(AliHMPIDDigit*)pSdiLst->At(i); //take current sdigit
+ if(pSdig->Pad()==iPad){ //if the same pad
+ q+=pSdig->Q(); //sum up charge
+ iNdigPad++; if(iNdigPad<=3) aTids[iNdigPad-1]=pSdig->GetTrack(0); //collect TID
+ continue;
+ }
+ if(i!=0 && AliHMPIDDigit::IsOverTh(q)) new((*pLst[iCh])[iCnt[iCh]++]) AliHMPIDDigit(iPad,(Int_t)q,aTids); //do not create digit for the very first sdigit
+ iPad=pSdig->Pad(); iCh=AliHMPIDDigit::A2C(iPad); //new sdigit comes, reset collectors
+ iNdigPad=1;
+ aTids[0]=pSdig->GetTrack(0);aTids[1]=aTids[2]=-1;
+ q=pSdig->Q();
+ }//sdigits loop (sorted)
+
+ if(AliHMPIDDigit::IsOverTh(q)) new((*pLst[iCh])[iCnt[iCh]++]) AliHMPIDDigit(iPad,(Int_t)q,aTids); //add the last one, in case of empty sdigits list q=-1
+ //so digit is not created
+}//Sdi2Dig()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDDigitizer_h
+#define AliHMPIDDigitizer_h
+/* Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+
+#include <AliDigitizer.h>
+class AliRunDigitizer;
+class TClonesArray;
+class TObjArray;
+
+class AliHMPIDDigitizer : public AliDigitizer //TObject-TNamed-TTask-AliDigitizer-AliHMPIDDigitizer
+{
+public:
+ AliHMPIDDigitizer() {}
+ AliHMPIDDigitizer(AliRunDigitizer *pRunDig):AliDigitizer(pRunDig) {}
+ virtual ~AliHMPIDDigitizer() {}
+ void Exec(Option_t* option=0); //virtual
+//
+ static void Sdi2Dig(TClonesArray *pSDigLst,TObjArray *pDigLst);
+protected:
+ ClassDef(AliHMPIDDigitizer,0)
+};
+#endif
--- /dev/null
+#include "AliHMPIDHelix.h" //class header
+#include <TPolyLine3D.h> //Draw()
+
+ClassImp(AliHMPIDHelix)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDHelix::Print(Option_t *opt) const
+{
+// Debug printout
+ Printf("%s helix for Q=%i in B=(0,0,%.2f) tesla",opt,fQ,fBz);
+ Printf("Helix parametrised @ x0=(%6.2f,%6.2f,%6.2f) cm p0=(%6.2f,%6.2f,%6.2f) GeV P=%.2f GeV Theta=%.2f Phi=%.2f degrees",
+ fX0.X(),fX0.Y(),fX0.Z(), fP0.Px(),fP0.Py(),fP0.Pz(), fP0.Mag(),fP0.Theta()*TMath::RadToDeg(),fP0.Phi()*TMath::RadToDeg());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDHelix::Draw(const Option_t *)
+{
+// Draw helix by a set of points seperated by 1 cm distance
+ TVector3 pos,mom;
+ const Int_t kNpoints=500;
+ TPolyLine3D *pHelDraw = new TPolyLine3D(kNpoints); pHelDraw->SetLineColor(kGreen);
+ for(Int_t i=0;i<kNpoints;i++) {
+ Propagate(i,pos,mom);
+ pHelDraw->SetPoint(i,pos.X(),pos.Y(),pos.Z());
+ }
+ pHelDraw->Draw();
+}
--- /dev/null
+#ifndef AliHMPIDHelix_h
+#define AliHMPIDHelix_h
+
+#include <TObject.h> //base class
+#include <TVector3.h> //used extensively
+
+class AliHMPIDHelix: public TObject
+{
+public:
+ AliHMPIDHelix( ):TObject(),fX0(TVector3(0,0,0)),fP0(TVector3(0,0,0)),fQ(0),fBz(0 ) {}
+ AliHMPIDHelix(const TVector3 &x0,const TVector3 &p0,Int_t q=1,Double_t b=2):TObject(),fX0(x0 ),fP0(p0 ),fQ(q),fBz(b ) {}
+ AliHMPIDHelix(Double_t p,Double_t theta,Double_t phi,Double_t bz=2 ):TObject(),fX0(TVector3(0,0,0)),fP0(TVector3(0,0,0)),fQ(0),fBz(bz)
+ {fP0.SetMagThetaPhi(p,theta*TMath::DegToRad(),phi*TMath::DegToRad());} //p [GeV], theta,phi [deg], Bz [Tesla];
+ virtual ~AliHMPIDHelix() {}
+
+ void Draw (const Option_t *opt="" ); //from TObject, draw helix
+ void Print (const Option_t *opt="" )const; //from TObject, print status
+//private part++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ inline Bool_t Intersect( TVector3 &pnt,TVector3 &norm ); //intersection with plane given by point and normal vector
+ inline void Propagate(Float_t len,TVector3 &x, TVector3 &p ); //propogate helix by given length along it
+protected:
+ TVector3 fX0; //helix position in point of definition, [cm] in MARS
+ TVector3 fP0; //helix momentum in point of definition, [GeV/c] in MARS
+ Int_t fQ; //sign of track charge
+ Float_t fBz; //magnetic field along z, [kGaus]
+ ClassDef(AliHMPIDHelix,0) //General helix
+};//class AliHMPIDHelix
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDHelix::Propagate(Float_t len,TVector3 &x,TVector3 &p)
+{
+// Propogates the helix from inintial point by a given distance along helix. Assumes uniform magnetic field along z direction.
+// Arguments: len - distance to propagate by, [cm]
+// Returns: none
+ if(fBz==0){//no magnetic field->straight line
+ x=fX0+fP0.Unit()*len;
+ p=fP0;
+ }else{
+ const Float_t c = 0.000299792458;//this speed of light value provides that coordinates are in [cm] momentum in [GeV/c] field in [kGaus]
+ Float_t a = -c*fBz*fQ;
+ Float_t rho = a/fP0.Mag();
+ x.SetX( fX0.X()+fP0.X()*TMath::Sin(rho*len)/a-fP0.Y()*(1-TMath::Cos(rho*len))/a );
+ x.SetY( fX0.Y()+fP0.Y()*TMath::Sin(rho*len)/a+fP0.X()*(1-TMath::Cos(rho*len))/a );
+ x.SetZ( fX0.Z()+fP0.Z()*len/fP0.Mag() );
+ x.SetX( fP0.X()*TMath::Cos(rho*len)-fP0.Y()*TMath::Sin(rho*len) );
+ p.SetY( fP0.Y()*TMath::Cos(rho*len)+fP0.X()*TMath::Sin(rho*len) );
+ p.SetZ( fP0.Z() );
+ }
+}//Propagate()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDHelix::Intersect(TVector3 &pnt,TVector3 &norm)
+{
+// Finds point of intersection (if exists) of the helix with the plane. Stores result in fX and fP.
+// Arguments: pnt - arbitrary point of the plane, [cm] in MARS
+// norm - vector, normal to the plane, [cm] in MARS
+// Returns: - kTrue if helix intersects the plane, kFALSE otherwise.
+// - pnt contains the point of intersection, [cm] in MARS
+ TVector3 x,p; //current helix position and momentum
+ Double_t s=(pnt-fX0)*norm,dist=99999,distPrev=dist; //estimates initial distance to plane
+ while(TMath::Abs(dist)>0.00001){ //loop while the distance is less then precision
+ Propagate(s,x,p); //calculates helix at the distance s from x0 ALONG the helix
+ dist=(x-pnt)*norm; //distance between current helix position and plane
+ if(TMath::Abs(dist) >= TMath::Abs(distPrev)) { return kFALSE;} //if distance increases then no intersection
+ distPrev=dist;
+ s-=dist;
+ }
+ norm=p;
+ pnt=x;
+ return kTRUE;
+}//Intersect()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+#include "AliHMPIDHit.h" //class header
+#include <TPDGCode.h> //Print()
+#include <TString.h>
+
+ClassImp(AliHMPIDHit)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDHit::Print(Option_t*)const
+{
+//Print hit
+ char *sPart=Form("pid=%i",Pid());
+ switch(Pid()){
+ case kProton: sPart="p+ ";break;
+ case kProtonBar: sPart="p- ";break;
+ case kKPlus: sPart="K+ ";break;
+ case kKMinus: sPart="K- ";break;
+ case kPiPlus: sPart="Pi+ ";break;
+ case kPiMinus: sPart="Pi- ";break;
+ case kMuonPlus: sPart="Mu+ ";break;
+ case kMuonMinus: sPart="Mu- ";break;
+ case kElectron: sPart="e- ";break;
+ case kPositron: sPart="e+ ";break;
+ case 50000050: sPart="ckov";break;
+ case 50000051: sPart="feed";break;
+ }
+
+ Printf("%s Ch:%i TID:%6i,E:%9.3f eV, LORS:(%7.2f,%7.2f) MARS:(%7.2f,%7.2f,%7.2f)cm",sPart,Ch(),Tid(),E()*1e9,LorsX(),LorsY(),X(),Y(),Z());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDHit_h
+#define AliHMPIDHit_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include <AliHit.h> //base class
+#include <TVector3.h> //ctor
+
+class AliHMPIDHit : public AliHit // TObject-AliHit-AliHMPIDHit
+{
+public:
+ AliHMPIDHit( ):AliHit( ),fCh(-1),fPid(-1 ),fE(-1),fLorsX(-1),fLorsY(-1) {} //default ctor
+ AliHMPIDHit(Int_t c,Float_t e,Int_t pid,Int_t tid,Float_t xl,Float_t yl,const TVector3 &p):AliHit(0,tid),fCh(c ),fPid(pid),fE(e ),fLorsX(xl),fLorsY(yl) {fX=p.X();fY=p.Y();fZ=p.Z();}
+ AliHMPIDHit(Int_t c,Float_t e,Int_t pid,Int_t tid,Float_t xl,Float_t yl ): fCh(c ),fPid(pid),fE(e ),fLorsX(xl),fLorsY(yl) {fTrack=tid;}
+ virtual ~AliHMPIDHit() {}
+//framework part
+ void Print(Option_t *option="")const; //from TObject to print current status
+//private part
+ Int_t Ch ()const{return fCh; } //Chamber
+ Float_t E ()const{return fE; } //Eloss for MIP hit or Etot for photon hit, [GeV]
+ Float_t LorsX ()const{return fLorsX; } //hit X position in LORS, [cm]
+ Float_t LorsY ()const{return fLorsY; } //hit Y position in LORS, [cm]
+ Int_t Pid ()const{return fPid; } //PID
+ Int_t Tid ()const{return fTrack; } //TID
+
+protected: //AliHit has fTid,fX,fY,fZ
+ Int_t fCh; //Chamber
+ Int_t fPid; //PID
+ Float_t fE; //Eloss for MIP or Etot for photon [GeV]
+ Float_t fLorsX; //hit X position in chamber LORS, [cm]
+ Float_t fLorsY; //hit Y position in chamber LORS, [cm]
+ ClassDef(AliHMPIDHit,4) //HMPID hit class
+};//class AliHMPIDhit
+
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+#include "AliHMPIDParam.h" //class header
+#include "AliHMPIDDigit.h" //ctor
+#include <TCanvas.h> //TestXXX()
+#include <TLatex.h> //TestTrans()
+#include <TView.h> //TestTrans()
+#include <TPolyMarker3D.h> //TestTrans()
+#include <TRotation.h>
+#include <AliRunLoader.h> //Stack()
+#include <AliStack.h> //Stack()
+#include <TParticle.h> //Stack()
+#include "AliHMPIDHelix.h" //TestTrans()
+
+ClassImp(AliHMPIDParam)
+
+AliHMPIDParam* AliHMPIDParam::fgInstance=0x0; //singleton pointer
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDParam::AliHMPIDParam():TNamed("RichParam","default version")
+{
+// Here all the intitializition is taken place when AliHMPIDParam::Instance() is invoked for the first time.
+// In particulare, matrices to be used for LORS<->MARS trasnformations are initialized from TGeo structure.
+// Note that TGeoManager should be already initialized from geometry.root file
+ fX=0.5*AliHMPIDDigit::SizeAllX();
+ fY=0.5*AliHMPIDDigit::SizeAllY();
+ for(Int_t i=0;i<7;i++) fM[i]=(TGeoHMatrix*)gGeoManager->GetVolume("ALIC")->GetNode(Form("HMPID_%i",i))->GetMatrix();
+ fgInstance=this;
+}//ctor
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDParam::Print(Option_t* opt) const
+{
+// print some usefull (hopefully) info on some internal guts of HMPID parametrisation
+
+ for(Int_t i=0;i<7;i++) fM[i]->Print(opt);
+}//Print()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDParam::Stack(Int_t evt,Int_t tid)
+{
+// Prints some usefull info from stack
+// Arguments: evt - event number. if not -1 print info only for that event
+// tid - track id. if not -1 then print it and all it's mothers if any
+// Returns: mother tid of the given tid if any
+ AliRunLoader *pAL=AliRunLoader::Open();
+ if(pAL->LoadHeader()) return -1;
+ if(pAL->LoadKinematics()) return -1;
+
+ Int_t mtid=-1;
+ Int_t iNevt=pAL->GetNumberOfEvents(); Printf("This session contains %i event(s)",iNevt);
+
+ for(Int_t iEvt=0;iEvt<iNevt;iEvt++){//events loop
+ if(evt!=-1 && evt!=iEvt) continue; //in case one needs to print the requested event, ignore all others
+ pAL->GetEvent(iEvt);
+ AliStack *pStack=pAL->Stack();
+ if(tid==-1){ //print all tids for this event
+ for(Int_t i=0;i<pStack->GetNtrack();i++) pStack->Particle(i)->Print();
+ Printf("totally %i tracks including %i primaries for event %i out of %i event(s)",pStack->GetNtrack(),pStack->GetNprimary(),iEvt,iNevt);
+ }else{ //print only this tid and it;s mothers
+ if(tid<0 || tid>pStack->GetNtrack()) {Printf("Wrong tid, valid tid range for event %i is 0-%i",iEvt,pStack->GetNtrack());break;}
+ TParticle *pTrack=pStack->Particle(tid); mtid=pTrack->GetFirstMother();
+ TString str=pTrack->GetName();
+ while((tid=pTrack->GetFirstMother()) >= 0){
+ pTrack=pStack->Particle(tid);
+ str+=" from ";str+=pTrack->GetName();
+ }
+ Printf("%s",str.Data());
+ }//if(tid==-1)
+ }//events loop
+ pAL->UnloadHeader(); pAL->UnloadKinematics();
+ return mtid;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDParam::StackCount(Int_t pid,Int_t evt)
+{
+// Counts total number of particles of given sort (including secondary) for a given event
+ AliRunLoader *pAL=AliRunLoader::Open();
+ pAL->GetEvent(evt);
+ if(pAL->LoadHeader()) return 0;
+ if(pAL->LoadKinematics()) return 0;
+ AliStack *pStack=pAL->Stack();
+
+ Int_t iCnt=0;
+ for(Int_t i=0;i<pStack->GetNtrack();i++) if(pStack->Particle(i)->GetPdgCode()==pid) iCnt++;
+
+ pAL->UnloadHeader(); pAL->UnloadKinematics();
+ return iCnt;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDParam_h
+#define AliHMPIDParam_h
+
+#include <TNamed.h> //base class
+#include <TGeoManager.h> //Instance()
+#include <TVector3.h> //Lors2Mars() Mars2Lors()
+
+static const int kCerenkov=50000050; //??? go to something more general like TPDGCode
+static const int kFeedback=50000051; //??? go to something more general like TPDGCode
+
+// Class providing all the needed parametrised information
+// to construct the geometry, to define segmentation and to provide response model
+// In future will also provide all the staff needed for alignment and calibration
+
+class AliHMPIDParam :public TNamed
+{
+public:
+//ctor&dtor
+ virtual ~AliHMPIDParam() {for(Int_t i=0;i<7;i++) delete fM[i]; delete fgInstance; fgInstance=0;}
+ void Print(Option_t *opt="") const; //print current parametrization
+ static inline AliHMPIDParam* Instance(); //pointer to AliHMPIDParam singleton
+
+ Double_t MeanIdxRad () {return 1.29204;}//???????????
+ Double_t MeanIdxWin () {return 1.57819;}//???????????
+ static Int_t Stack(Int_t evt=-1,Int_t tid=-1); //Print stack info for event and tid
+ static Int_t StackCount(Int_t pid,Int_t evt); //Counts stack particles of given sort in given event
+//trasformation methodes
+ void Lors2Mars (Int_t c,Float_t x,Float_t y,Double_t *m,Int_t pl=kPc)const{Double_t z=0; switch(pl){case kPc:z=8.0;break; case kAnod:z=7.806;break; case kRad:z=-1.25; break;} Double_t l[3]={x-fX,y-fY,z}; fM[c]->LocalToMaster(l,m); }
+ TVector3 Lors2Mars (Int_t c,Float_t x,Float_t y, Int_t pl=kPc)const{Double_t m[3];Lors2Mars(c,x,y,m,pl); return TVector3(m); }//MRS->LRS
+ void Mars2Lors (Int_t c,Double_t *m,Float_t &x,Float_t &y )const{Double_t l[3];fM[c]->MasterToLocal(m,l);x=l[0]+fX;y=l[1]+fY;}//MRS->LRS
+ void Mars2LorsVec(Int_t c,Double_t *m,Float_t &th,Float_t &ph )const{Double_t l[3]; fM[c]->MasterToLocalVect(m,l); Float_t pt=TMath::Sqrt(l[0]*l[0]+l[1]*l[1]); th=TMath::ATan(l[3]/pt); ph=TMath::ATan(l[0]/pt);}
+ TVector3 Norm (Int_t c )const{Double_t n[3]; Norm(c,n); return TVector3(n); }//norm
+ void Norm (Int_t c,Double_t *n )const{Double_t l[3]={0,0,1};fM[c]->LocalToMasterVect(l,n); }//norm
+
+ enum EPlaneId {kPc,kRad,kAnod}; //3 planes in chamber
+protected:
+ AliHMPIDParam(); //default ctor is protected to enforce it to be singleton
+ static AliHMPIDParam *fgInstance; //static pointer to instance of AliHMPIDParam singleton
+ TGeoHMatrix *fM[7]; //poiners to matrices defining HMPID chambers rotations-translations
+ Float_t fX; //x shift of LORS with respect to rotated MARS
+ Float_t fY; //y shift of LORS with respect to rotated MARS
+ ClassDef(AliHMPIDParam,0) //HMPID main parameters class
+};
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDParam* AliHMPIDParam::Instance()
+{
+// Return pointer to the AliHMPIDParam singleton.
+// Arguments: none
+// Returns: pointer to the instance of AliHMPIDParam or 0 if no geometry
+ if(!fgInstance)
+ if(gGeoManager) new AliHMPIDParam;
+ else Printf("AliHMPIDParam> Error:: No geometry defined!");
+ return fgInstance;
+}//Instance()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#endif
--- /dev/null
+#include "AliHMPIDPreprocessor.h" //header
+
+#include <AliCDBMetaData.h>
+#include <AliDCSValue.h>
+#include <TObjArray.h> //Test()
+#include <TObjString.h> //Test()
+#include <AliCDBManager.h> //Test()
+#include <AliCDBEntry.h> //Test()
+//#include <AliTestShuttle.h> //Test()
+#include <TRandom.h> //Test()
+#include <TF1.h> //Process()
+#include <TF2.h> //Process()
+#include <TGraph.h> //Process()
+
+ClassImp(AliHMPIDPreprocessor)
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDPreprocessor::Initialize(Int_t run, UInt_t startTime,UInt_t endTime)
+{
+ AliPreprocessor::Initialize(run, startTime, endTime);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+UInt_t AliHMPIDPreprocessor::Process(TMap* pDcsMap)
+{
+//
+// Argumets: pDcsMap - map of structure "alias name" - TObjArray of AliDCSValue
+
+// TList* list = GetFileSources(kDAQ, "MAP"); //first analyse a set of pedestal files
+// if (list){
+// Log("The following sources produced files with the id MAP");
+// list->Print();
+// delete list;
+// }
+
+ if(!pDcsMap) return 0; //no DCS map provided
+
+ TF2 idxC6F14("RidxC4F14","sqrt(1+0.554*(1239.84/x)^2/((1239.84/x)^2-5796)-0.0005*(y-20))",5.5,8.5,0,50); //DiMauro mail temp 0-50 degrees C
+ Double_t eMean=6.67786; //mean energy of photon defined by transperancy window
+
+ TObjArray radTemp; radTemp.SetOwner(kTRUE); //store temp versus time as TF1 array for all radiators (21)
+ TObjArray meanIdx; meanIdx.SetOwner(kTRUE); //store ref idx versus time as TF1 array for all radiators (21)
+
+
+ for(Int_t iCh=0;iCh<7;iCh++){ //aliases loop
+ for(Int_t iRad=0;iRad<3;iRad++){
+ TObjArray *pValLst=(TObjArray*)pDcsMap->GetValue(Form("HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iIn_Temp",iCh,iCh,iRad));//get data points for this alias
+ if(!pValLst) continue; //no data points
+ TF1 *pRadTempF=new TF1(Form("RadTemp%i%i",iCh,iRad),"[0]+[1]*x+[2]*sin([3]*x)",0,10); pRadTempF->SetLineColor(iRad+2); //temp=f(time)
+ TF1 *pMeanIdxF=new TF1(Form("MeanIdx%i%i",iCh,iRad),"[0]+[1]*x+[2]*sin([3]*x)",0,10); pMeanIdxF->SetLineColor(iRad+2); //idx=f(time)
+ TGraph *pRadTempG=new TGraph; //tmp graph of rad temp versus time
+ TGraph *pMeanIdxG=new TGraph; //tmp graph of mean ref idx versus time
+ TIter next(pValLst); AliDCSValue *pDcsVal; Int_t i=0;
+ while((pDcsVal=(AliDCSValue*)next())){ //loop over data points for this sensor
+ pRadTempG->SetPoint(i,pDcsVal->GetTimeStamp(), pDcsVal->GetFloat()); //and fill the temp graph
+ pMeanIdxG->SetPoint(i,pDcsVal->GetTimeStamp(),idxC6F14.Eval(eMean,pDcsVal->GetFloat())); //and fill the maen ref idx graph
+ i++;
+ }
+ pRadTempG->Fit(pRadTempF,"Q"); //now fit the temp graph
+ pMeanIdxG->Fit(pMeanIdxF,"Q"); //now fit the mean idx graph
+ delete pRadTempG;
+ delete pMeanIdxG;
+ radTemp.Add(pRadTempF);
+ meanIdx.Add(pMeanIdxF);
+ }//radiators loop
+ }//chambers loop
+
+ AliCDBMetaData metaData; metaData.SetBeamPeriod(0); metaData.SetResponsible("AliHMPIDPreprocessor"); metaData.SetComment("SIMULATED");
+
+ Store("DCS", "RadTemp" , &radTemp , &metaData); //use AliPreprocessor::Store(), not allowed to use AliCDBManager directly
+ Store("DCS", "MeanIdx" , &meanIdx , &metaData);
+
+ return 1;
+
+}//Process()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDPreprocessor_h
+#define AliHMPIDPreprocessor_h
+
+#include <AliPreprocessor.h> //base class
+
+class TMap;
+
+class AliHMPIDPreprocessor : public AliPreprocessor
+{
+public:
+ AliHMPIDPreprocessor(AliShuttleInterface* pShuttle):AliPreprocessor("HMPID",pShuttle) {}
+ virtual ~AliHMPIDPreprocessor( ) {}
+protected:
+ virtual void Initialize(Int_t run, UInt_t startTime, UInt_t endTime);
+ virtual UInt_t Process (TMap* pDcsMap );
+ ClassDef(AliHMPIDPreprocessor, 0);
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+// //
+// AliHMPIDRecon //
+// //
+// HMPID class to perfom pattern recognition based on Hough transfrom //
+// for single chamber //
+//////////////////////////////////////////////////////////////////////////
+
+#include "AliHMPIDRecon.h" //class header
+#include "AliHMPIDCluster.h" //CkovAngle()
+#include <TRotation.h> //TracePhoton()
+#include <TH1D.h> //HoughResponse()
+#include <TClonesArray.h> //CkovAngle()
+
+#include <TTree.h> //Display()
+#include <TFile.h> //Display()
+#include <AliESD.h> //Display()
+#include <TPolyMarker.h> //Display()
+#include <TLatex.h> //Display()
+#include <TCanvas.h> //Display()
+
+
+const Double_t AliHMPIDRecon::fgkRadThick=1.5;
+const Double_t AliHMPIDRecon::fgkWinThick=0.5;
+const Double_t AliHMPIDRecon::fgkGapThick=8.0;
+const Double_t AliHMPIDRecon::fgkRadIdx =1.292;
+const Double_t AliHMPIDRecon::fgkWinIdx =1.5787;
+const Double_t AliHMPIDRecon::fgkGapIdx =1.0005;
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDRecon::AliHMPIDRecon():TTask("RichRec","RichPat"),
+ fPhotCnt(-1),
+ fCkovSigma2(0),
+ fIsWEIGHT(kFALSE),
+ fDTheta(0.001),
+ fWindowWidth(0.045),
+ fTrkDir(TVector3(0,0,1)),fTrkPos(TVector2(30,40))
+{
+// main ctor
+ for (Int_t i=0; i<3000; i++) {
+ fPhotFlag[i] = 0;
+ fPhotCkov[i] = -1;
+ fPhotPhi [i] = -1;
+ fPhotWei [i] = 0;
+ }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::CkovAngle(TClonesArray *pCluLst,Int_t &iNaccepted)
+{
+// Pattern recognition method based on Hough transform
+// Arguments: pCluLst - list of clusters for this chamber
+// Returns: - track ckov angle, [rad],
+
+ if(pCluLst->GetEntries()>200) fIsWEIGHT = kTRUE; // offset to take into account bkg in reconstruction
+ else fIsWEIGHT = kFALSE;
+
+ // Photon Flag: Flag = 0 initial set; Flag = 1 good candidate (charge compatible with photon); Flag = 2 photon used for the ring;
+
+ fPhotCnt=0;
+ for (Int_t iClu=0; iClu<pCluLst->GetEntriesFast();iClu++){//clusters loop
+ AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->UncheckedAt(iClu); //get pointer to current cluster
+ if(pClu->Q()>100) continue; //avoid MIP clusters from bkg
+
+ fPhotCkov[fPhotCnt]=FindPhotCkov(pClu->X(),pClu->Y()); //find ckov angle for this photon candidate
+ fPhotCnt++; //increment counter of photon candidates
+ }//clusters loop
+
+ iNaccepted=FlagPhot(HoughResponse()); //flag photons according to individual theta ckov with respect to most probable track theta ckov
+ if(iNaccepted<1) return -11;
+ else return FindRingCkov(pCluLst->GetEntries()); //find best Theta ckov for ring i.e. track
+}//ThetaCerenkov()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::FindPhotCkov(Double_t cluX,Double_t cluY)
+{
+// Finds Cerenkov angle for this photon candidate
+// Arguments: cluX,cluY - position of cadidate's cluster
+// Returns: Cerenkov angle
+
+ TVector2 pos(cluX,cluY); Double_t cluR=(pos-fTrkPos).Mod(); Double_t phi=FindPhotPhi(cluX,cluY);
+ Printf("new dist %f phi %f",cluR,phi);
+ Double_t ckov1=0,ckov2=0.75;
+ const Double_t kTol=0.05;
+ Int_t iIterCnt = 0;
+ while(1){
+ if(iIterCnt>=50) return -1;
+ Double_t ckov=0.5*(ckov1+ckov2);
+ Double_t dist=cluR-TracePhot(ckov,phi,pos); iIterCnt++; //get distance between trial point and cluster position
+ Printf("New: phi %f ckov %f dist %f",phi,ckov,dist);
+ if (dist> kTol) ckov1=ckov; //cluster @ larger ckov
+ else if(dist<-kTol) ckov2=ckov; //cluster @ smaller ckov
+ else return ckov; //precision achived
+ }
+}//FindPhotTheta()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::FindPhotPhi(Double_t cluX,Double_t cluY)
+{
+// Finds phi angle og photon candidate by considering the cluster's position of this candudate w.r.t track position
+
+ Double_t emiss=0;
+ return fPhotPhi[fPhotCnt]=TMath::ATan2(cluY-fTrkPos.Y()-emiss*TMath::Tan(fTrkDir.Theta())*TMath::Sin(fTrkDir.Phi()),
+ cluX-fTrkPos.X()-emiss*TMath::Tan(fTrkDir.Theta())*TMath::Cos(fTrkDir.Phi()));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::FindRingArea(Double_t ckovAng)const
+{
+// Find area inside the cerenkov ring which lays inside PCs
+// Arguments: ckovThe - cernkov
+// Returns: area of the ring in cm^2 for given theta ckov
+
+
+ TVector2 pos1,pos2;
+
+ const Int_t kN=100;
+ Double_t area=0;
+ for(Int_t i=0;i<kN;i++){
+ TracePhot(ckovAng,Double_t(TMath::TwoPi()*i /kN),pos1);//trace this photon
+ TracePhot(ckovAng,Double_t(TMath::TwoPi()*(i+1)/kN),pos2);//trace this photon
+ area+=(pos1-fTrkPos)*(pos2-fTrkPos);
+
+ }
+ return area;
+}//FindRingArea()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::FindRingCkov(Int_t)
+{
+// Loops on all Ckov candidates and estimates the best Theta Ckov for a ring formed by those candidates. Also estimates an error for that Theat Ckov
+// collecting errors for all single Ckov candidates thetas. (Assuming they are independent)
+// Arguments: iNclus- total number of clusters in chamber for background estimation
+// Return: best estimation of track Theta ckov
+
+ Double_t wei = 0.;
+ Double_t weightThetaCerenkov = 0.;
+
+ Double_t ckovMin=9999.,ckovMax=0.;
+ Double_t sigma2 = 0; //to collect error squared for this ring
+
+ for(Int_t i=0;i<fPhotCnt;i++){//candidates loop
+ if(fPhotFlag[i] == 2){
+ if(fPhotCkov[i]<ckovMin) ckovMin=fPhotCkov[i]; //find max and min Theta ckov from all candidates within probable window
+ if(fPhotCkov[i]>ckovMax) ckovMax=fPhotCkov[i];
+ weightThetaCerenkov += fPhotCkov[i]*fPhotWei[i]; wei += fPhotWei[i]; //collect weight as sum of all candidate weghts
+
+ //Double_t phiref=(GetPhiPoint()-GetTrackPhi());
+ if(fPhotCkov[i]<=0) continue;//?????????????????Flag photos = 2 may imply CkovEta = 0??????????????
+
+ sigma2 += 1./Sigma2(fPhotCkov[i],fPhotPhi[i]);
+ }
+ }//candidates loop
+
+ if(sigma2>0) fCkovSigma2=1./sigma2;
+ else fCkovSigma2=1e10;
+
+
+ if(wei != 0.) weightThetaCerenkov /= wei; else weightThetaCerenkov = 0.;
+ return weightThetaCerenkov;
+}//FindCkovRing()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDRecon::FlagPhot(Double_t ckov)
+{
+// Flag photon candidates if their individual ckov angle is inside the window around ckov angle returned by HoughResponse()
+// Arguments: ckov- value of most probable ckov angle for track as returned by HoughResponse()
+// Returns: number of photon candidates happened to be inside the window
+
+
+ Int_t steps = (Int_t)((ckov )/ fDTheta); //how many times we need to have fDTheta to fill the distance between 0 and thetaCkovHough
+
+ Double_t tmin = (Double_t)(steps - 1)*fDTheta;
+ Double_t tmax = (Double_t)(steps)*fDTheta;
+ Double_t tavg = 0.5*(tmin+tmax);
+
+ tmin = tavg - 0.5*fWindowWidth; tmax = tavg + 0.5*fWindowWidth;
+
+ Int_t iInsideCnt = 0; //count photons which Theta ckov inside the window
+ for(Int_t i=0;i<fPhotCnt;i++){//photon candidates loop
+ if(fPhotCkov[i] >= tmin && fPhotCkov[i] <= tmax) {
+ fPhotFlag[i]=2;
+ iInsideCnt++;
+ }
+ }
+ return iInsideCnt;
+}//FlagPhot()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::TracePhot(Double_t ckovThe,Double_t ckovPhi,TVector2 &pos)const
+{
+// Trace a single Ckov photon from emission point somewhere in radiator up to photocathode taking into account ref indexes of materials it travereses
+// Arguments: ckovThe,ckovPhi- photon ckov angles, [rad] (warning: not photon theta and phi)
+// Returns: distance between photon point on PC and track projection
+ TRotation mtheta; mtheta.RotateY(fTrkDir.Theta());
+ TRotation mphi; mphi.RotateZ(fTrkDir.Phi());
+ TRotation mrot=mphi*mtheta;
+
+ TVector3 posCkov(fTrkPos.X(),fTrkPos.Y(),-0.5*fgkRadThick-fgkWinThick-fgkGapThick); //RAD: photon position is track position @ middle of RAD
+ TVector3 dirCkov; dirCkov.SetMagThetaPhi(1,ckovThe,ckovPhi); //initially photon is directed according to requested ckov angle
+ dirCkov=mrot*dirCkov; //now we know photon direction in LORS
+ dirCkov.SetPhi(ckovPhi);
+ if(dirCkov.Theta() > TMath::ASin(1./fgkRadIdx)) return -999;//total refraction on WIN-GAP boundary
+
+ Propagate(dirCkov,posCkov,-fgkWinThick-fgkGapThick); //go to RAD-WIN boundary remeber that z=0 is PC plane
+ Refract (dirCkov, fgkRadIdx,fgkWinIdx ); //RAD-WIN refraction
+ Propagate(dirCkov,posCkov,-fgkGapThick ); //go to WIN-GAP boundary
+ Refract (dirCkov, fgkWinIdx,fgkGapIdx ); //WIN-GAP refraction
+ Propagate(dirCkov,posCkov,0 ); //go to PC
+
+ pos.Set(posCkov.X(),posCkov.Y());
+ return (pos-fTrkPos).Mod();
+}//TracePhoton()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDRecon::Propagate(const TVector3 &dir,TVector3 &pos,Double_t z)const
+{
+// Finds an intersection point between a line and XY plane shifted along Z.
+// Arguments: dir,pos - vector along the line and any point of the line
+// z - z coordinate of plain
+// Returns: none
+// On exit: pos is the position if this intesection if any
+ static TVector3 nrm(0,0,1);
+ TVector3 pnt(0,0,z);
+
+ TVector3 diff=pnt-pos;
+ Double_t sint=(nrm*diff)/(nrm*dir);
+ pos+=sint*dir;
+}//Propagate()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDRecon::Refract(TVector3 &dir,Double_t n1,Double_t n2)const
+{
+// Refract direction vector according to Snell law
+// Arguments:
+// n1 - ref idx of first substance
+// n2 - ref idx of second substance
+// Returns: none
+// On exit: dir is new direction
+ Double_t sinref=(n1/n2)*TMath::Sin(dir.Theta());
+ if(sinref>1.) dir.SetXYZ(-999,-999,-999);
+ else dir.SetTheta(TMath::ASin(sinref));
+}//Refract()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::HoughResponse()
+{
+//
+//
+//
+ Double_t kThetaMax=0.75;
+ Int_t nChannels = (Int_t)(kThetaMax/fDTheta+0.5);
+ TH1D *phots = new TH1D("Rphot" ,"phots" ,nChannels,0,kThetaMax);
+ TH1D *photsw = new TH1D("RphotWeighted" ,"photsw" ,nChannels,0,kThetaMax);
+ TH1D *resultw = new TH1D("resultw","resultw" ,nChannels,0,kThetaMax);
+ Int_t nBin = (Int_t)(kThetaMax/fDTheta);
+ Int_t nCorrBand = (Int_t)(fWindowWidth/(2*fDTheta));
+
+ for (Int_t i=0; i< fPhotCnt; i++){//photon cadidates loop
+ Double_t angle = fPhotCkov[i]; if(angle<0||angle>kThetaMax) continue;
+ phots->Fill(angle);
+ Int_t bin = (Int_t)(0.5+angle/(fDTheta));
+ Double_t weight=1.;
+ if(fIsWEIGHT){
+ Double_t lowerlimit = ((Double_t)bin)*fDTheta - 0.5*fDTheta; Double_t upperlimit = ((Double_t)bin)*fDTheta + 0.5*fDTheta;
+ Double_t diffArea = FindRingArea(upperlimit)-FindRingArea(lowerlimit);
+ if(diffArea>0) weight = 1./diffArea;
+ }
+ photsw->Fill(angle,weight);
+ fPhotWei[i]=weight;
+ }//photon candidates loop
+
+ for (Int_t i=1; i<=nBin;i++){
+ Int_t bin1= i-nCorrBand;
+ Int_t bin2= i+nCorrBand;
+ if(bin1<1) bin1=1;
+ if(bin2>nBin)bin2=nBin;
+ Double_t sumPhots=phots->Integral(bin1,bin2);
+ if(sumPhots<3) continue; // if less then 3 photons don't trust to this ring
+ Double_t sumPhotsw=photsw->Integral(bin1,bin2);
+ resultw->Fill((Double_t)((i+0.5)*fDTheta),sumPhotsw);
+ }
+// evaluate the "BEST" theta ckov as the maximum value of histogramm
+ Double_t *pVec = resultw->GetArray();
+ Int_t locMax = TMath::LocMax(nBin,pVec);
+ phots->Delete();photsw->Delete();resultw->Delete(); // Reset and delete objects
+
+ return (Double_t)(locMax*fDTheta+0.5*fDTheta); //final most probable track theta ckov
+}//HoughResponse()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::Sigma2(Double_t ckovTh, Double_t ckovPh)const
+{
+// Analithical calculation of total error (as a sum of localization, geometrical and chromatic errors) on Cerenkov angle for a given Cerenkov photon
+// created by a given MIP. Fromulae according to CERN-EP-2000-058
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+// dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]
+// MIP beta
+// Returns: absolute error on Cerenkov angle, [radians]
+
+ TVector3 v(-999,-999,-999);
+ Double_t trkBeta = 1./(TMath::Cos(ckovTh)*fgkRadIdx);
+
+ v.SetX(SigLoc (ckovTh,ckovPh,trkBeta));
+ v.SetY(SigGeom(ckovTh,ckovPh,trkBeta));
+ v.SetZ(SigCrom(ckovTh,ckovPh,trkBeta));
+
+ return v.Mag2();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::SigLoc(Double_t thetaC, Double_t phiC,Double_t betaM)const
+{
+// Analithical calculation of localization error (due to finite segmentation of PC) on Cerenkov angle for a given Cerenkov photon
+// created by a given MIP. Fromulae according to CERN-EP-2000-058
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+// dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]
+// MIP beta
+// Returns: absolute error on Cerenkov angle, [radians]
+ Double_t phiDelta = phiC - fTrkDir.Phi();
+
+ Double_t alpha =TMath::Cos(fTrkDir.Theta())-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(fTrkDir.Theta());
+ Double_t k = 1.-fgkRadIdx*fgkRadIdx+alpha*alpha/(betaM*betaM);
+ if (k<0) return 1e10;
+
+ Double_t mu =TMath::Sin(fTrkDir.Theta())*TMath::Sin(fTrkDir.Phi())+TMath::Tan(thetaC)*(TMath::Cos(fTrkDir.Theta())*TMath::Cos(phiDelta)*TMath::Sin(fTrkDir.Phi())+TMath::Sin(phiDelta)*TMath::Cos(fTrkDir.Phi()));
+ Double_t e =TMath::Sin(fTrkDir.Theta())*TMath::Cos(fTrkDir.Phi())+TMath::Tan(thetaC)*(TMath::Cos(fTrkDir.Theta())*TMath::Cos(phiDelta)*TMath::Cos(fTrkDir.Phi())-TMath::Sin(phiDelta)*TMath::Sin(fTrkDir.Phi()));
+
+ Double_t kk = betaM*TMath::Sqrt(k)/(8*alpha);
+ Double_t dtdxc = kk*(k*(TMath::Cos(phiDelta)*TMath::Cos(fTrkDir.Phi())-TMath::Cos(fTrkDir.Theta())*TMath::Sin(phiDelta)*TMath::Sin(fTrkDir.Phi()))-(alpha*mu/(betaM*betaM))*TMath::Sin(fTrkDir.Theta())*TMath::Sin(phiDelta));
+ Double_t dtdyc = kk*(k*(TMath::Cos(phiDelta)*TMath::Sin(fTrkDir.Phi())+TMath::Cos(fTrkDir.Theta())*TMath::Sin(phiDelta)*TMath::Cos(fTrkDir.Phi()))+(alpha* e/(betaM*betaM))*TMath::Sin(fTrkDir.Theta())*TMath::Sin(phiDelta));
+
+ return TMath::Sqrt(0.2*0.2*dtdxc*dtdxc + 0.25*0.25*dtdyc*dtdyc);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::SigCrom(Double_t thetaC, Double_t phiC,Double_t betaM)const
+{
+// Analithical calculation of chromatic error (due to lack of knowledge of Cerenkov photon energy) on Cerenkov angle for a given Cerenkov photon
+// created by a given MIP. Fromulae according to CERN-EP-2000-058
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+// dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]
+// MIP beta
+// Returns: absolute error on Cerenkov angle, [radians]
+ Double_t phiDelta = phiC - fTrkDir.Phi();
+ Double_t alpha =TMath::Cos(fTrkDir.Theta())-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(fTrkDir.Theta());
+
+ Double_t dtdn = TMath::Cos(fTrkDir.Theta())*fgkRadIdx*betaM*betaM/(alpha*TMath::Tan(thetaC));
+
+ Double_t f = 0.00928*(7.75-5.635)/TMath::Sqrt(12.);
+
+ return f*dtdn;
+}//SigCrom()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Double_t AliHMPIDRecon::SigGeom(Double_t thetaC, Double_t phiC,Double_t betaM)const
+{
+// Analithical calculation of geometric error (due to lack of knowledge of creation point in radiator) on Cerenkov angle for a given Cerenkov photon
+// created by a given MIP. Formulae according to CERN-EP-2000-058
+// Arguments: Cerenkov and azimuthal angles for Cerenkov photon, [radians]
+// dip and azimuthal angles for MIP taken at the entrance to radiator, [radians]
+// MIP beta
+// Returns: absolute error on Cerenkov angle, [radians]
+
+ Double_t phiDelta = phiC - fTrkDir.Phi();
+ Double_t alpha =TMath::Cos(fTrkDir.Theta())-TMath::Tan(thetaC)*TMath::Cos(phiDelta)*TMath::Sin(fTrkDir.Theta());
+
+ Double_t k = 1.-fgkRadIdx*fgkRadIdx+alpha*alpha/(betaM*betaM);
+ if (k<0) return 1e10;
+
+ Double_t eTr = 0.5*1.5*betaM*TMath::Sqrt(k)/(8*alpha);
+ Double_t lambda = 1.-TMath::Sin(fTrkDir.Theta())*TMath::Sin(fTrkDir.Theta())*TMath::Sin(phiC)*TMath::Sin(phiC);
+
+ Double_t c = 1./(1.+ eTr*k/(alpha*alpha*TMath::Cos(thetaC)*TMath::Cos(thetaC)));
+ Double_t i = betaM*TMath::Tan(thetaC)*lambda*TMath::Power(k,1.5);
+ Double_t ii = 1.+eTr*betaM*i;
+
+ Double_t err = c * (i/(alpha*alpha*8) + ii*(1.-lambda) / ( alpha*alpha*8*betaM*(1.+eTr)) );
+ Double_t trErr = 1.5/(TMath::Sqrt(12.)*TMath::Cos(fTrkDir.Theta()));
+
+ return trErr*err;
+}//SigGeom()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDRecon::Display()
+{
+// Display digits, reconstructed tracks intersections and HMPID rings if available
+// Arguments: none
+// Returns: none
+ TFile *pEsdFl=TFile::Open("AliESDs.root"); if(!pEsdFl || !pEsdFl->IsOpen()) return;//open AliESDs.root
+ TTree *pEsdTr=(TTree*) pEsdFl->Get("esdTree"); if(!pEsdTr) return;//get ESD tree
+
+ AliESD *pEsd=new AliESD; pEsdTr->SetBranchAddress("ESD", &pEsd);
+
+ TPolyMarker *pDigMap[7]; //digits map
+ TPolyMarker *pTrkMap[7]; Int_t aTrkCnt[7]; //TRKxPC intersection map
+
+ for(Int_t i=0;i<7;i++){
+ pDigMap[i]=new TPolyMarker(); pDigMap[i]->SetMarkerStyle(25); pDigMap[i]->SetMarkerSize(0.5); pDigMap[i]->SetMarkerColor(kGreen);
+ aTrkCnt[i]=0; pTrkMap[i]=new TPolyMarker(); pTrkMap[i]->SetMarkerStyle(4); pTrkMap[i]->SetMarkerSize(0.5); pTrkMap[i]->SetMarkerColor(kRed);
+ }
+
+ AliHMPIDRecon rec;
+
+ TLatex t;
+ TCanvas *pC = new TCanvas("HMPIDDisplay","HMPID Display",0,0,1226,900); pC->Divide(3,3);
+
+ for(Int_t iEvt=0;iEvt<pEsdTr->GetEntries();iEvt++) { //events loop
+ pC->cd(3); t.DrawText(0.2,0.4,Form("Event %i",iEvt)); //print current event number
+ pEsdTr->GetEntry(iEvt); //get ESD for this event
+ for(Int_t iTrk=0;iTrk<pEsd->GetNumberOfTracks();iTrk++){//ESD tracks loop
+ AliESDtrack *pTrk = pEsd->GetTrack(iTrk); //
+ Float_t th,ph,x,y; pTrk->GetHMPIDtrk(x,y,th,ph); if(x<0) continue;
+ Int_t ch=pTrk->GetHMPIDcluIdx()/1000000; Printf("ch=%i",ch);
+ pTrkMap[ch]->SetPoint(aTrkCnt[ch]++,x,y);
+ }//ESD tracks loop
+
+// al->GetEvent(iEvt); rl->TreeD()->GetEntry(0); //get digits list
+ for(Int_t iCh=0;iCh<7;iCh++) {//chambers loop
+// for(Int_t iDig=0;iDig < r->DigLst(iCh)->GetEntries();iDig++) { //digits loop
+// AliHMPIDDigit *pDig = (AliHMPIDDigit*)r->DigLst(iCh)->At(iDig);
+// pDigMap[iCh]->SetPoint(iDig,pDig->LorsX(),pDig->LorsY());
+// } //digits loop
+//
+//
+ if(iCh==6) pC->cd(1); if(iCh==5) pC->cd(2);
+ if(iCh==4) pC->cd(4); if(iCh==3) pC->cd(5); if(iCh==2) pC->cd(6);
+ if(iCh==1) pC->cd(8); if(iCh==0) pC->cd(9);
+
+ AliHMPIDDigit::DrawPc(); pTrkMap[iCh]->Draw(); pDigMap[iCh]->Draw();
+ }//chambers loop
+// pC->Update();
+// pC->Modified();
+// if(iEvt<iEvtTo) {gPad->WaitPrimitive();pC->Clear();}
+
+
+
+ }//events loop
+ delete pEsd; pEsdFl->Close();//close AliESDs.root
+// rl->UnloadDigits();
+}//Display()
--- /dev/null
+#ifndef AliHMPIDRecon_h
+#define AliHMPIDRecon_h
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+//////////////////////////////////////////////////////////////////////////
+// //
+// AliHMPIDRecon //
+// //
+// HMPID class to perfom pattern recognition based on Hough transfrom //
+// //
+//////////////////////////////////////////////////////////////////////////
+
+
+#include <TTask.h> //base class
+#include <TVector3.h> //fields
+
+class TClonesArray;
+class AliHMPIDRecon : public TTask
+{
+public :
+ AliHMPIDRecon();
+ virtual ~AliHMPIDRecon() {}
+
+
+ Double_t CkovAngle (TClonesArray *pCluLst,Int_t &iNaccepted); //reconstructed Theta Cerenkov
+ Double_t CkovSigma2 ( )const{ return fCkovSigma2;} //track ckov angle error squared
+ Double_t FindPhotCkov (Double_t cluX,Double_t cluY ); //find ckov angle for single photon candidate
+ Double_t FindPhotPhi (Double_t cluX,Double_t cluY ); //find phi angle for single photon candidate
+ Double_t FindRingCkov (Int_t iNclus ); //best ckov for ring formed by found photon candidates
+ Double_t FindRingArea (Double_t ckov )const;//estimated area of ring in cm^2
+ Int_t FlagPhot (Double_t ckov ); //is photon ckov near most probable track ckov
+ Double_t HoughResponse( ); //most probable track ckov angle
+ void Propagate (const TVector3 &dir, TVector3 &pos,Double_t z )const;//propagate photon alogn the line
+ void Refract ( TVector3 &dir, Double_t n1, Double_t n2)const;//refract photon on the boundary
+ Double_t TracePhot (Double_t ckovTh,Double_t ckovPh,TVector2 &pos )const;//trace photon created by track to PC
+ void SetTrack (Double_t th,Double_t ph,Double_t x,Double_t y ){fTrkDir.SetMagThetaPhi(1,th,ph); fTrkPos.Set(x,y);}//set track
+ Double_t SigLoc (Double_t ckovTh,Double_t ckovPh,Double_t beta )const;//error due to cathode segmetation
+ Double_t SigGeom (Double_t ckovTh,Double_t ckovPh,Double_t beta )const;//error due to unknown photon origin
+ Double_t SigCrom (Double_t ckovTh,Double_t ckovPh,Double_t beta )const;//error due to unknonw photon energy
+ Double_t Sigma2 (Double_t ckovTh,Double_t ckovPh )const;//photon candidate sigma
+
+ static void Display ( ); //event display
+
+
+protected:
+ const static Double_t fgkRadThick; //radiator thickness
+ const static Double_t fgkWinThick; //window thickness
+ const static Double_t fgkGapThick; //proximity gap thickness
+ const static Double_t fgkRadIdx; //mean refractive index of RAD material (C6F14)
+ const static Double_t fgkWinIdx; //mean refractive index of WIN material (SiO2)
+ const static Double_t fgkGapIdx; //mean refractive index of GAP material (CH4)
+ Int_t fPhotCnt; // counter of photons candidate
+ Int_t fPhotFlag[3000]; // flags of photon candidates
+ Double_t fPhotCkov[3000]; // Ckov angles of photon candidates, [rad]
+ Double_t fPhotPhi [3000]; // phis of photons candidates, [rad]
+ Double_t fPhotWei [3000]; // weigths of photon candidates
+ Double_t fCkovSigma2; // sigma2 of the reconstructed ring
+
+ Bool_t fIsWEIGHT; // flag to consider weight procedure
+ Float_t fDTheta; // Step for sliding window
+ Float_t fWindowWidth; // Hough width of sliding window
+
+ TVector3 fTrkDir; //track direction in LORS
+ TVector2 fTrkPos; //track positon in LORS at the middle of radiator
+ ClassDef(AliHMPIDRecon,0)
+};
+
+#endif // #ifdef AliHMPIDRecon_cxx
+
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+#include "AliHMPIDReconstructor.h" //class header
+#include "AliHMPID.h" //Reconstruct()
+#include "AliHMPIDCluster.h" //CluQA()
+#include "AliHMPIDParam.h" //FillEsd()
+#include <AliESD.h> //FillEsd()
+#include <AliRunLoader.h> //Reconstruct() for simulated digits
+#include <AliRawReader.h> //Reconstruct() for raw digits
+#include <AliRun.h> //Reconstruct()
+#include <TH1F.h> //CluQA()
+#include <TH2F.h> //CluQA()
+#include <TCanvas.h> //CluQA()
+#include <TNtupleD.h> //CheckPR()
+ClassImp(AliHMPIDReconstructor)
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDReconstructor::CluQA(AliRunLoader *pAL)
+{
+// Quality assesment plots for clusters.
+// This methode takes list of digits and form list of clusters again in order to
+// calculate cluster shape and cluster particle mixture
+ AliLoader *pRL=pAL->GetDetectorLoader("HMPID"); AliHMPID *pRich=(AliHMPID*)pAL->GetAliRun()->GetDetector("HMPID");//get pointers for HMPID and HMPID loader
+ Int_t iNevt=pAL->GetNumberOfEvents(); if(iNevt==0) {AliInfoClass("No events");return;}
+ if(pRL->LoadDigits()) {AliInfoClass("No digits file");return;}
+ pAL->LoadHeader();
+ pAL->LoadKinematics();
+// AliStack *pStack=pAL->Stack();
+ TH1::AddDirectory(kFALSE);
+
+
+ TH1F* pQ=new TH1F("RiAllQ" ,"Charge All" ,4000 ,0 ,4000);// Q hists
+ TH1F* pCerQ=new TH1F("RiCerQ" ,"Charge Ckov" ,4000 ,0 ,4000);
+ TH1F* pMipQ=new TH1F("RiMipQ" ,"Charge MIP" ,4000 ,0 ,4000);
+
+ TH1F* pS=new TH1F("RichCluSize" ,"Cluster size;size" ,100 ,0 ,100 );// size hists
+ TH1F* pCerS=new TH1F("RichCluCerSize" ,"Ckov size;size" ,100 ,0 ,100 );
+ TH1F* pMipS=new TH1F("RichCluMipSize" ,"MIP size;size" ,100 ,0 ,100 );
+
+ TH2F* pM=new TH2F("RichCluMap" ,"Cluster map;x [cm];y [cm]" ,1000 ,0 ,AliHMPIDDigit::SizePcX(),1000,0,AliHMPIDDigit::SizePcY()); // maps
+ TH2F* pMipM=new TH2F("RichCluMipMap" ,"MIP map;x [cm];y [cm]" ,1000 ,0 ,AliHMPIDDigit::SizePcX(),1000,0,AliHMPIDDigit::SizePcY());
+ TH2F* pCerM=new TH2F("RichCluCerMap" ,"Ckov map;x [cm];y [cm]" ,1000 ,0 ,AliHMPIDDigit::SizePcX(),1000,0,AliHMPIDDigit::SizePcY());
+
+
+
+ for(Int_t iEvt=0;iEvt<iNevt;iEvt++){
+ pAL->GetEvent(iEvt);
+ pRL->TreeD()->GetEntry(0);
+ TClonesArray *pCluLst=new TClonesArray("AliHMPIDCluster");//tmp list of clusters for this event
+
+ for(Int_t iCh=0;iCh<7;iCh++) Dig2Clu(pRich->DigLst(iCh),pCluLst,kFALSE);//cluster finder for all chamber if any digits present
+
+ for(Int_t iClu=0;iClu<pCluLst->GetEntriesFast();iClu++){
+ AliHMPIDCluster *pClu = (AliHMPIDCluster*)pCluLst->At(iClu);
+ Int_t cfm=0; for(Int_t iDig=0;iDig<pClu->Size();iDig++) cfm+=pClu->Dig(iDig)->Ch(); //collect ckov-fee-mip structure of current cluster ?????
+ Int_t iNckov=cfm/1000000; Int_t iNfee =cfm%1000000/1000; Int_t iNmip =cfm%1000000%1000;
+
+ pQ ->Fill(pClu->Q()) ; pS ->Fill(pClu->Size()) ; pM ->Fill(pClu->X(),pClu->Y()); //all clusters
+ if(iNckov!=0 && iNfee==0 && iNmip==0) {pCerQ->Fill(pClu->Q()) ; pCerS->Fill(pClu->Size()) ; pCerM ->Fill(pClu->X(),pClu->Y());}//ckov only cluster
+ if(iNckov==0 && iNfee==0 && iNmip!=0) {pMipQ->Fill(pClu->Q()) ; pMipS->Fill(pClu->Size()) ; pMipM ->Fill(pClu->X(),pClu->Y());}//mip only cluster
+
+ }//clusters loop
+ pCluLst->Clear();delete pCluLst;
+ }//events loop
+
+ pRL->UnloadDigits(); pAL->UnloadKinematics(); pAL->UnloadHeader();
+ TCanvas *pC=new TCanvas("RichCluQA",Form("QA for cluster from %i events",iNevt),1000,900); pC->Divide(3,3);
+ pC->cd(1); pM->Draw(); pC->cd(2); pQ->Draw(); pC->cd(3); pS->Draw();
+ pC->cd(4); pMipM->Draw(); pC->cd(5); pMipQ->Draw(); pC->cd(6); pMipS->Draw();
+ pC->cd(7); pCerM->Draw(); pC->cd(8); pCerQ->Draw(); pC->cd(9); pCerS->Draw();
+}//CluQA()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDReconstructor::Dig2Clu(TClonesArray *pDigLst,TClonesArray *pCluLst,Bool_t isTryUnfold)
+{
+// Finds all clusters for a given digits list provided not empty. Currently digits list is a list of all digits for a single chamber.
+// Puts all found clusters in separate lists, one per clusters.
+// Arguments: pDigLst - list of digits provided not empty
+// pCluLst - list of clusters, provided empty
+// isTryUnfold - flag to choose between CoG and Mathieson fitting
+// Returns: none
+ TMatrixF digMap(AliHMPIDDigit::kPadAllX,AliHMPIDDigit::kPadAllY); digMap=(Float_t)-1; //digit map for single chamber reseted to -1
+ for(Int_t iDig=0;iDig<pDigLst->GetEntriesFast();iDig++){ //digits loop to fill digits map
+ AliHMPIDDigit *pDig= (AliHMPIDDigit*)pDigLst->At(iDig); //get current digit
+ digMap( pDig->PadX(), pDig->PadY() )=iDig; //fill the map, (padx,pady) cell takes digit index
+ } //digits loop to fill digits map
+
+ AliHMPIDCluster clu; //tmp cluster to be used as current
+
+ for(Int_t iDig=0;iDig<pDigLst->GetEntriesFast();iDig++){ //digits loop to form clusters list
+ AliHMPIDDigit *pDig=(AliHMPIDDigit*)pDigLst->At(iDig); //take current digit
+ if(!(pDig=UseDig(pDig->PadX(),pDig->PadY(),pDigLst,&digMap))) continue; //this digit is already taken in FormClu(), go after next digit
+ FormClu(&clu,pDig,pDigLst,&digMap); //form cluster starting from this digit by recursion
+ clu.Solve(pCluLst,isTryUnfold); //solve this cluster and add all unfolded clusters to provided list
+ clu.Reset(); //empty current cluster
+ } //digits loop to form clusters list
+}//Dig2Clu()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDReconstructor::FormClu(AliHMPIDCluster *pClu,AliHMPIDDigit *pDig,TClonesArray *pDigLst,TMatrixF *pDigMap)
+{
+// Forms the initial cluster as a sum of all adjascent digits. Starts from the given digit
+// then calls itself recursevly for all neighbours.
+// Arguments: pClu - pointer to cluster being formed
+// Returns: none
+ pClu->DigAdd(pDig);//take this digit in cluster
+
+ Int_t x[4],y[4];
+
+
+ Int_t iPadCnt=0; Int_t iPadX=pDig->PadX(); Int_t iPadY=pDig->PadY();
+ if(iPadX != AliHMPIDDigit::kPad1) {x[iPadCnt]=iPadX-1; y[iPadCnt]=iPadY; iPadCnt++;} //left
+ if(iPadX != AliHMPIDDigit::kPadPcX) {x[iPadCnt]=iPadX+1; y[iPadCnt]=iPadY; iPadCnt++;} //right
+ if(iPadY != AliHMPIDDigit::kPad1) {x[iPadCnt]=iPadX; y[iPadCnt]=iPadY-1; iPadCnt++;} //down
+ if(iPadY != AliHMPIDDigit::kPadPcY) {x[iPadCnt]=iPadX; y[iPadCnt]=iPadY+1; iPadCnt++;} //up
+
+ for (Int_t i=0;i<iPadCnt;i++)
+ if((pDig=UseDig(x[i],y[i],pDigLst,pDigMap))) FormClu(pClu,pDig,pDigLst,pDigMap); //check if this neighbour hit and mark it as taken
+}//FormClu()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDReconstructor::Reconstruct(AliRunLoader *pAL)const
+{
+//Invoked by AliReconstruction to convert digits to clusters i.e. reconstruct simulated data
+//Arguments: pAL - ALICE run loader pointer
+// Returns: none
+ AliDebug(1,"Start.");
+ AliLoader *pRL=pAL->GetDetectorLoader("HMPID");
+ AliHMPID *pRich=(AliHMPID*)pAL->GetAliRun()->GetDetector("HMPID");//get pointers for HMPID and HMPID loader
+ pRL->LoadDigits();
+ pRL->LoadRecPoints("recreate");
+
+ for(Int_t iEvtN=0;iEvtN<pAL->GetNumberOfEvents();iEvtN++){//events loop
+ pAL->GetEvent(iEvtN); AliDebug(1,Form("Processing event %i...",iEvtN)); //switch current directory to next event
+ pRL->TreeD()->GetEntry(0); pRL->MakeTree("R"); pRich->MakeBranch("R"); //load digits to memory and create branches for clusters
+
+ for(Int_t iCh=0;iCh<7;iCh++) Dig2Clu(pRich->DigLst(iCh),pRich->CluLst(iCh));//cluster finder
+
+ pRL->TreeR()->Fill(); //fill tree for current event
+ pRL->WriteRecPoints("OVERWRITE");//write out clusters for current event
+ pRich->DigReset(); pRich->CluReset();
+ }//events loop
+
+ pRL->UnloadDigits();
+ pRL->UnloadRecPoints();
+
+ AliDebug(1,"Stop.");
+}//Reconstruct(for simulated digits)
+//__________________________________________________________________________________________________
+void AliHMPIDReconstructor::Reconstruct(AliRunLoader *pAL,AliRawReader* pRR)const
+{
+//Invoked by AliReconstruction to convert raw digits from DDL files to clusters
+//Arguments: pAL - ALICE run loader pointer
+// pRR - ALICE raw reader pointer
+// Returns: none
+ AliLoader *pRL=pAL->GetDetectorLoader("HMPID"); AliHMPID *pRich=(AliHMPID*)pAL->GetAliRun()->GetDetector("HMPID");//get pointers for HMPID and HMPID loader
+
+ AliHMPIDDigit dig; //tmp digit, raw digit will be converted to it
+
+ Int_t iEvtN=0;
+ while(pRR->NextEvent()){//events loop
+ pAL->GetEvent(iEvtN++);
+ pRL->MakeTree("R"); pRich->MakeBranch("R");
+
+ for(Int_t iCh=0;iCh<7;iCh++){//chambers loop
+ TClonesArray *pDigLst=new TClonesArray("AliHMPIDDigit"); Int_t iDigCnt=0; //tmp list of digits for single chamber
+ pRR->Select("HMPID",2*iCh,2*iCh+1);//select only DDL files for the current chamber
+ UInt_t w32=0;
+ while(pRR->ReadNextInt(w32)){//raw records loop (in selected DDL files)
+ UInt_t ddl=pRR->GetDDLID(); //returns 0,1,2 ... 13
+ dig.ReadRaw(ddl,w32);
+ AliDebug(1,Form("Ch=%i DDL=%i raw=0x%x digit=(%3i,%3i,%3i,%3i) Q=%5.2f",iCh,ddl,w32,dig.Ch(),dig.Pc(),dig.PadX(),dig.PadY(),dig.Q()));
+ new((*pDigLst)[iDigCnt++]) AliHMPIDDigit(dig); //add this digit to the tmp list
+ }//raw records loop
+ if(iDigCnt) Dig2Clu(pDigLst,pRich->CluLst(iCh));//cluster finder for the current chamber if any digits present
+ pRR->Reset();
+ pDigLst->Delete(); iDigCnt=0;//clean up list of digits for the current chamber
+ }//chambers loop
+ pRL->TreeR()->Fill(); //fill tree for current event
+ pRL->WriteRecPoints("OVERWRITE");//write out clusters for current event
+ pRich->CluReset();
+ }//events loop
+ pRL->UnloadRecPoints();
+}//Reconstruct raw data
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+void AliHMPIDReconstructor::FillESD(AliRunLoader *, AliESD *pESD) const
+{
+// Calculates probability to be a electron-muon-pion-kaon-proton
+// from the given Cerenkov angle and momentum assuming no initial particle composition
+// (i.e. apriory probability to be the particle of the given sort is the same for all sorts)
+
+ AliPID ppp; //needed
+ Double_t pid[AliPID::kSPECIES],h[AliPID::kSPECIES];
+
+ for(Int_t iTrk=0;iTrk<pESD->GetNumberOfTracks();iTrk++){//ESD tracks loop
+ AliESDtrack *pTrk = pESD->GetTrack(iTrk);// get next reconstructed track
+ if(pTrk->GetHMPIDsignal()<=0){//HMPID does not find anything reasonable for this track, assign 0.2 for all species
+ for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++) pid[iPart]=1.0/AliPID::kSPECIES;
+ pTrk->SetHMPIDpid(pid);
+ continue;
+ }
+ Double_t pmod = pTrk->GetP();
+ Double_t hTot=0;
+ for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++){
+ Double_t mass = AliPID::ParticleMass(iPart);
+ Double_t cosThetaTh = TMath::Sqrt(mass*mass+pmod*pmod)/(AliHMPIDParam::Instance()->MeanIdxRad()*pmod);
+ if(cosThetaTh<1) //calculate the height of theortical theta ckov on the gaus of experimental one
+ h[iPart] =TMath::Gaus(TMath::ACos(cosThetaTh),pTrk->GetHMPIDsignal(),TMath::Sqrt(pTrk->GetHMPIDchi2()),kTRUE);
+
+ else //beta < 1/ref. idx. => no light at all
+ h[iPart] =0 ;
+ hTot +=h[iPart]; //total height of all theoretical heights for normalization
+ }//species loop
+
+ Double_t hMin=TMath::Gaus(pTrk->GetHMPIDsignal()-4*TMath::Sqrt(pTrk->GetHMPIDchi2()),pTrk->GetHMPIDsignal(),TMath::Sqrt(pTrk->GetHMPIDchi2()),kTRUE);//5 sigma protection
+
+ for(Int_t iPart=0;iPart<AliPID::kSPECIES;iPart++)//species loop to assign probabilities
+ if(hTot>hMin)
+ pid[iPart]=h[iPart]/hTot;
+ else //all theoretical values are far away from experemental one
+ pid[iPart]=1.0/AliPID::kSPECIES;
+ pTrk->SetHMPIDpid(pid);
+ }//ESD tracks loop
+ //last line is to check if the nearest thetacerenkov to the teorethical one is within 5 sigma, otherwise no response (equal prob to every particle
+}//FillESD
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDReconstructor_h
+#define AliHMPIDReconstructor_h
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include <AliReconstructor.h> //base class
+#include "AliHMPIDTracker.h" //CreateTracker()
+#include <TMatrixF.h> //UseDig()
+#include <TClonesArray.h> //UseDig()
+class AliRawReader; //Reconstruct() with raw data
+class AliHMPIDDigit; //Dig2Clu(), UseDig()
+class AliHMPIDCluster; //Dig2Clu()
+
+class AliHMPIDReconstructor: public AliReconstructor
+{
+public:
+ AliHMPIDReconstructor(): AliReconstructor() {}//default ctor
+ virtual ~AliHMPIDReconstructor() {}//dtor
+//framework part
+ AliTracker* CreateTracker (AliRunLoader* )const{return new AliHMPIDTracker;} //from AliReconstructor for clusters->PID
+ void Reconstruct (AliRunLoader* pAL )const; //from AliReconstruction for digits->clusters
+ void Reconstruct (AliRunLoader* pAL,AliRawReader *pRR)const; //from AliReconstruction for raws->clusters
+ virtual void FillESD (AliRunLoader* pAL,AliESD *pESD)const; //calculate pid for HMPID
+ virtual void FillESD(AliRunLoader*, AliRawReader*, AliESD*) const { };
+ virtual void FillESD(AliRawReader*, TTree*, AliESD*) const { };
+ virtual void FillESD(TTree*, TTree*, AliESD*) const { };
+
+
+ using AliReconstructor::Reconstruct; //to get rid of virtual hidden warning
+
+ //private part
+ static void Dig2Clu (TClonesArray*pDigLst,TClonesArray *pCluLst,Bool_t isTryUnfold=kTRUE );//digits list -> clusters list
+ static void CluQA (AliRunLoader* pAL );//QA for clusters
+ static void FormClu (AliHMPIDCluster *pClu,AliHMPIDDigit *pDig,TClonesArray *pDigLst,TMatrixF *pDigMap);//cluster formation recursive algorithm
+ static inline AliHMPIDDigit* UseDig (Int_t padX,Int_t padY,TClonesArray *pDigList,TMatrixF *pDigMap );//use this pad's digit to form a cluster
+
+ protected:
+ ClassDef(AliHMPIDReconstructor, 0) //class for the HMPID reconstruction
+};
+//__________________________________________________________________________________________________
+AliHMPIDDigit* AliHMPIDReconstructor::UseDig(Int_t padX,Int_t padY,TClonesArray *pDigLst,TMatrixF *pDigMap)
+{
+//Digit map contains a matrix if digit numbers.
+//Main operation in forming initial cluster is done here. Requested digit pointer is returned and this digit marked as taken.
+//Arguments: padX,padY - pad number
+// pDigLst - list of digits for one sector
+// pDigMap - map of those digits
+// Returns: pointer to digit if not yet used or 0 if used
+ Int_t iDig=(Int_t)(*pDigMap)(padX,padY);(*pDigMap)(padX,padY)=-1;//take digit number from the map and reset this map cell to -1
+ if(iDig!=-1) return (AliHMPIDDigit*)pDigLst->At(iDig); //digit pointer
+ else return 0;
+}
+
+#endif
--- /dev/null
+#include <TF1.h>
+#include <TH2F.h>
+#include <TCanvas.h> //Terminate()
+#include <TChain.h>
+#include <TBenchmark.h>
+#include <fstream> //caf()
+#include <TProof.h> //caf()
+#include <AliSelector.h> //base class
+#include <AliESD.h>
+
+
+class AliHMPIDSelector : public AliSelector {
+ public :
+ AliHMPIDSelector():AliSelector(),fChain(0),fEsd(0),fCkovP(0),fMipXY(0),fDifXY(0),fSigP(0) {for(Int_t i=0;i<5;i++) fProb[i]=0;}
+ virtual ~AliHMPIDSelector() {delete fEsd;}
+
+
+ virtual Int_t Version () const {return 2;}
+ virtual void Begin (TTree *) {}
+ virtual void SlaveBegin (TTree *tree);
+ virtual void Init (TTree *tree);
+ virtual Bool_t Notify () {return kTRUE;}
+ virtual Bool_t Process (Long64_t entry);
+ virtual void SetOption (const char *option) { fOption = option; }
+ virtual void SetObject (TObject *obj) { fObject = obj; }
+ virtual void SetInputList (TList *input) {fInput = input;}
+ virtual TList *GetOutputList () const { return fOutput; }
+ virtual void SlaveTerminate ();
+ virtual void Terminate ();
+
+ private:
+ TTree *fChain ; //!pointer to the analyzed TTree or TChain
+ AliESD *fEsd ; //!
+
+ TH2F *fCkovP,*fMipXY,*fDifXY,*fSigP; //!
+ TH1F *fProb[5]; //!
+
+ ClassDef(AliHMPIDSelector,0);
+};
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDSelector::SlaveBegin(TTree *tree)
+{
+// The SlaveBegin() function is called after the Begin() function. When running with PROOF SlaveBegin() is called on each slave server.
+// The tree argument is deprecated (on PROOF 0 is passed).
+
+ Init(tree);
+
+ TString option = GetOption();
+
+ // create histograms on each slave server
+ fCkovP = new TH2F("CkovP" , "#theta_{c}, [rad];P, [GeV]", 150, 0, 7 ,100, -3, 1);
+ fSigP = new TH2F("SigP" ,"#sigma_{#theta_c}" , 150, 0, 7 ,100, 0, 1e20);
+ fMipXY = new TH2F("MipXY" ,"mip position" , 260, 0,130 ,252,0,126);
+ fDifXY = new TH2F("DifXY" ,"diff" , 260, -10, 10 ,252,-10,10);
+
+ fProb[0] = new TH1F("PidE" ,"PID: e yellow #mu magenta" ,100,0,1); fProb[0]->SetLineColor(kYellow);
+ fProb[1] = new TH1F("PidMu","pid of #mu" ,100,0,1); fProb[1]->SetLineColor(kMagenta);
+ fProb[2] = new TH1F("PidPi","PID: #pi red K green p blue",100,0,1); fProb[2]->SetLineColor(kRed);
+ fProb[3] = new TH1F("PidK" ,"pid of K" ,100,0,1); fProb[3]->SetLineColor(kGreen);
+ fProb[4] = new TH1F("PidP" ,"pid of p" ,100,0,1); fProb[4]->SetLineColor(kBlue);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDSelector::Init(TTree *pTr)
+{
+ // The Init() function is called when the selector needs to initialize
+ // a new tree or chain. Typically here the branch addresses of the tree
+ // will be set. It is normaly not necessary to make changes to the
+ // generated code, but the routine can be extended by the user if needed.
+ // Init() will be called many times when running with PROOF.
+
+ // Set branch addresses
+ if ( !pTr ) return ;
+ fChain = pTr ;
+ fChain->SetBranchAddress("ESD", &fEsd) ;
+ fChain->SetBranchStatus("*", 0);
+ fChain->SetBranchStatus("fTracks.*", 1);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDSelector::Process(Long64_t entry)
+{
+
+ fChain->GetTree()->GetEntry(entry);
+
+ for(Int_t iTrk=0;iTrk<fEsd->GetNumberOfTracks();iTrk++){
+ AliESDtrack *pTrk=fEsd->GetTrack(iTrk);
+
+// if(pTrk->GetHMPIDsignal()<0) continue;
+
+ fCkovP->Fill(pTrk->GetP(),pTrk->GetHMPIDsignal()) ;
+ fSigP ->Fill(pTrk->GetP(),TMath::Sqrt(pTrk->GetHMPIDchi2()));
+
+// Float_t xm,ym; Int_t q,np; pTrk->GetHMPIDmip(xm,ym,q,np); fMipXY->Fill(xm,ym); //mip info
+// Float_t xd,yd,th,ph; pTrk->GetHMPIDtrk(xd,yd,th,ph); fDifXY->Fill(xd,yd); //track info
+
+ Double_t pid[5]; pTrk->GetHMPIDpid(pid); for(Int_t i =0;i<5;i++) fProb[i]->Fill(pid[i]);
+ }//tracks loop
+
+ return kTRUE;
+}//Process()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDSelector::SlaveTerminate()
+{
+ // The SlaveTerminate() function is called after all entries or objects
+ // have been processed. When running with PROOF SlaveTerminate() is called
+ // on each slave server.
+
+ // Add the histograms to the output on each slave server
+
+ fOutput->Add(fCkovP);
+ fOutput->Add(fSigP);
+ fOutput->Add(fMipXY);
+ fOutput->Add(fDifXY);
+
+ for(Int_t i=0;i<5;i++) fOutput->Add(fProb[i]);
+}//SlaveTerminate()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDSelector::Terminate()
+{
+ // The Terminate() function is the last function to be called during
+ // a query. It always runs on the client, it can be used to present
+ // the results graphically or save the results to file.
+
+ fCkovP = dynamic_cast<TH2F*>(fOutput->FindObject("CkovP")) ;
+ fSigP = dynamic_cast<TH2F*>(fOutput->FindObject("SigP")) ;
+ fMipXY = dynamic_cast<TH2F*>(fOutput->FindObject("MipXY")) ;
+ fDifXY = dynamic_cast<TH2F*>(fOutput->FindObject("DifXY")) ;
+
+ fProb[0] = dynamic_cast<TH1F*>(fOutput->FindObject("PidE")) ;
+ fProb[1] = dynamic_cast<TH1F*>(fOutput->FindObject("PidMu")) ;
+ fProb[2] = dynamic_cast<TH1F*>(fOutput->FindObject("PidPi")) ;
+ fProb[3] = dynamic_cast<TH1F*>(fOutput->FindObject("PidK")) ;
+ fProb[4] = dynamic_cast<TH1F*>(fOutput->FindObject("PidP")) ;
+
+ Float_t n=1.292; //mean freon ref idx
+ TF1 *pPi=new TF1("RiPiTheo","acos(sqrt(x*x+[0]*[0])/(x*[1]))",1.2,7); pPi->SetLineWidth(1); pPi->SetParameter(1,n);
+ AliPID ppp; pPi->SetLineColor(kRed); pPi->SetParameter(0,AliPID::ParticleMass(AliPID::kPion)); //mass
+ TF1 *pK=(TF1*)pPi->Clone(); pK ->SetLineColor(kGreen); pK ->SetParameter(0,AliPID::ParticleMass(AliPID::kKaon));
+ TF1 *pP=(TF1*)pPi->Clone(); pP ->SetLineColor(kBlue); pP ->SetParameter(0,AliPID::ParticleMass(AliPID::kProton));
+
+ TCanvas *pC=new TCanvas("c1","ESD QA");pC->SetFillColor(10); pC->SetHighLightColor(10); pC->Divide(3,2);
+ pC->cd(1); fCkovP->Draw(); pPi->Draw("same"); pK->Draw("same"); pP->Draw("same"); pC->cd(2); fMipXY->Draw(); pC->cd(3); fProb[0]->Draw(); fProb[1]->Draw("same");
+ pC->cd(4); fSigP ->Draw(); pC->cd(5); fDifXY->Draw(); pC->cd(6); fProb[2]->Draw(); fProb[3]->Draw("same"); fProb[4]->Draw("same");
+
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+
+void loc()
+{
+ TChain* pChain =new TChain("esdTree");
+ pChain->Add("AliESDs.root");
+
+ pChain->Process("AliHMPIDSelector.C+");
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void caf()
+{
+ gBenchmark->Start("PRooF exec");
+ TChain* pChain =new TChain("esdTree");
+
+ ifstream list; list.open("list.txt");
+
+ TString file;
+ while(list.good()) {
+ list>>file;
+ if (!file.Contains("root")) continue; //it's wrong file name
+ pChain->Add(file.Data());
+ }
+ list.close();
+
+ pChain->GetListOfFiles()->Print();
+
+ TVirtualProof *pProof=TProof::Open("kir@lxb6046.cern.ch");
+ pProof->UploadPackage("ESD.par");
+ pProof->EnablePackage("ESD");
+
+ pChain->SetProof(pProof);
+ pChain->Process("AliHMPIDSelector.C+");
+
+ gBenchmark->Show("PRooF exec");
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
--- /dev/null
+#include "AliHMPIDTracker.h" //class header
+#include "AliHMPID.h" //GetTrackPoint(),PropagateBack()
+#include "AliHMPIDCluster.h" //GetTrackPoint(),PropagateBack()
+#include "AliHMPIDParam.h" //GetTrackPoint(),PropagateBack()
+#include "AliHMPIDRecon.h" //PropagateBack()
+#include <AliESD.h> //PropagateBack()
+#include <AliRun.h> //GetTrackPoint(),PropagateBack()
+#include <AliTrackPointArray.h> //GetTrackPoint()
+#include <AliAlignObj.h> //GetTrackPoint()
+ClassImp(AliHMPIDTracker)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+AliHMPIDTracker::AliHMPIDTracker():AliTracker()
+{
+// AliHMPIDTracker is created from AliReconstraction::Run() which invokes AliReconstraction::CreateTrackers()
+// which in turn invokes AliHMPIDReconstructor::CreateTracker().
+// Note that this is done just once per session before AliReconstruction::Run() goes to events loop.
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDTracker::GetTrackPoint(Int_t idx, AliTrackPoint& point) const
+{
+// Interface callback methode invoked from AliReconstruction::WriteAlignmentData() to get position of MIP cluster in MARS associated to a current track.
+// MIP cluster is reffered by index which is stored in AliESDtrack ???????
+// Arguments: idx- cluster index which is stored by HMPID in AliESDtrack
+// point- reference to the object where to store the point
+// Returns: status of operation if FALSE then AliReconstruction::WriteAlignmentData() do not store this point to array of points for current track.
+ if(idx<0) return kFALSE; //no MIP cluster assigned to this track in PropagateBack()
+ Int_t iCham=idx/1000000;
+ Int_t iClu=idx%1000000;
+ point.SetVolumeID(AliAlignObj::LayerToVolUID(AliAlignObj::kHMPID,iCham-1));//layer and chamber number
+ AliHMPID *pRich=((AliHMPID*)gAlice->GetDetector("HMPID"));
+ AliHMPIDCluster *pClu=(AliHMPIDCluster*)pRich->CluLst(iCham)->UncheckedAt(iClu);//get pointer to cluster
+ Double_t mars[3];
+ AliHMPIDParam::Instance()->Lors2Mars(iCham,pClu->X(),pClu->Y(),mars);
+ point.SetXYZ(mars[0],mars[1],mars[2]);
+ return kTRUE;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDTracker::LoadClusters(TTree *pCluTree)
+{
+// Interface callback methode invoked from AliReconstruction::RunTracking() to load HMPID clusters before PropagateBack() gets control
+// Arguments: pCluTree- pointer to clusters tree got by AliHMPIDLoader::LoadRecPoints("read") then AliHMPIDLoader::TreeR()
+// Returns: error code (currently ignored in AliReconstruction::RunTraking())
+ AliDebug(1,"Start."); pCluTree->GetEntry(0); AliDebug(1,"Stop."); return 0;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Int_t AliHMPIDTracker::PropagateBack(AliESD *pESD)
+{
+// Interface callback methode invoked by AliRecontruction::RunTracking() during tracking after TOF. It's done just once per event
+// Arguments: pESD - pointer to Event Summary Data class instance which contains a list of tracks
+// Returns: error code, 0 if no errors
+ Int_t iNtracks=pESD->GetNumberOfTracks(); AliDebug(1,Form("Start with %i tracks",iNtracks));
+ AliHMPID *pRich=((AliHMPID*)gAlice->GetDetector("HMPID"));
+ AliHMPIDRecon recon; //instance of reconstruction class, nothing important in ctor
+
+ AliHMPIDParam *pParam=AliHMPIDParam::Instance();
+
+ for(Int_t iTrk=0;iTrk<iNtracks;iTrk++){ //ESD tracks loop
+ AliESDtrack *pTrk = pESD->GetTrack(iTrk); //get next reconstructed track
+
+ Float_t xRa=0,yRa=0,xPc=0,yPc=0,th=0,ph=0; //track intersection point and angles, LORS
+ Int_t iCh=-1; //intersected chamber
+ for(Int_t i=0;i<7;i++){ //chambers loop
+ Double_t p1[3],n1[3]; pParam->Norm(i,n1); pParam->Lors2Mars(i,0,0,p1,AliHMPIDParam::kRad); //point & norm for RAD
+ Double_t p2[3],n2[3]; pParam->Norm(i,n2); pParam->Lors2Mars(i,0,0,p2,AliHMPIDParam::kPc); //point & norm for PC
+
+ if(pTrk->Intersect(p1,n1,-GetBz())==kFALSE) continue; //try to intersect track with the middle of radiator
+ if(pTrk->Intersect(p2,n2,-GetBz())==kFALSE) continue; //try to intersect track with PC
+
+ pParam->Mars2LorsVec(i,n1,th,ph); //track angles
+ pParam->Mars2Lors (i,p1,xRa,yRa); //TRKxRAD position
+ pParam->Mars2Lors (i,p2,xPc,yPc); //TRKxPC position
+
+ if(AliHMPIDDigit::IsInside(xPc,yPc)==kFALSE) continue; //not in active area
+ iCh=i;
+ break;
+ }//chambers loop
+
+ if(iCh==-1) continue; //no intersection at all, go after next track
+
+ TClonesArray *pCluLst=pRich->CluLst(iCh); //get clusters list for intersected chamber
+
+ Double_t dMin=999; //distance between track-PC intersection point and current cluster
+ Int_t iMip=-1; //index of cluster nearest to intersection point
+ for(Int_t iClu=0;iClu<pCluLst->GetEntries();iClu++){ //clusters loop for intersected chamber
+ AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->At(iClu); //get pointer to current cluster
+ if(pClu->Q()<100) continue; //QDC is incompartible with mip, go after another one
+
+ Float_t dX=xPc-pClu->X(); //distance between current cluster and intersection point
+ Float_t dY=yPc-pClu->Y();
+ Float_t d =TMath::Sqrt(dX*dX+dY*dY);
+
+ if( d < dMin) {iMip=iClu; dMin=d;} //current cluster is closer, overwrite data for min cluster
+ }//clusters loop for intersected chamber
+
+ pTrk->SetHMPIDtrk (xPc,yPc,th,ph); //store track info
+ if(iMip==-1) {pTrk->SetHMPIDsignal (kMipQdcCut); continue;} //no clusters with QDC more the threshold at all
+
+ AliHMPIDCluster *pMipClu=(AliHMPIDCluster*)pCluLst->At(iMip); //take mip cluster
+
+ pTrk->SetHMPIDmip (pMipClu->X(),pMipClu->Y(),pMipClu->Q()); //store mip info
+ if(dMin>1) {pTrk->SetHMPIDsignal (kMipDistCut); continue;} //closest cluster with enough charge is still too far
+ pTrk->SetHMPIDcluIdx (iCh,iMip); //set mip cluster index
+ recon.SetTrack(th,ph,xRa,yRa); Int_t iNphot=0; //initialize track parameters
+ pTrk->SetHMPIDsignal (recon.CkovAngle(pCluLst,iNphot)); //search for Cerenkov angle for this track
+ pTrk->SetHMPIDchi2 (recon.CkovSigma2()); //error squared
+ pTrk->SetHMPIDmip (pMipClu->X(),pMipClu->Y(),pMipClu->Q(),iMip); //info on mip cluster + n. phot.
+ Printf("Ch=%i MIP-TRK=%5.2f cm Th=%f+-%f", iCh, dMin,pTrk->GetHMPIDsignal(),pTrk->GetHMPIDchi2());
+ }//ESD tracks loop
+ AliDebug(1,"Stop pattern recognition");
+ return 0; // error code: 0=no error;
+}//PropagateBack()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDTracker_h
+#define AliHMPIDTracker_h
+
+#include <AliTracker.h> //base class
+
+class TNtupleD; //RecWithStack()
+class AliESD; //Clusters2Tracks(), RefitInward(), PropagateBack(), RecWithESD()
+
+class AliHMPIDTracker : public AliTracker
+{
+public:
+ AliHMPIDTracker();
+ virtual ~AliHMPIDTracker() {}
+//framework part
+ AliCluster *GetCluster (Int_t )const {return 0;} //pure virtual from AliTracker
+ Bool_t GetTrackPoint (Int_t idx,AliTrackPoint &pt)const; // from AliTracker
+ Int_t Clusters2Tracks(AliESD * ) {return 0;} //pure virtual from AliTracker
+ Int_t LoadClusters (TTree *pCluTr ); //pure virtual from AliTracker
+ Int_t PropagateBack (AliESD * ); //pure virtual from AliTracker invoked from AliReconstruction::RunTracking()
+ Int_t RefitInward (AliESD * ) {return 0;} //pure virtual from AliTracker
+ void UnloadClusters ( ) { } //pure virtual from AliTracker
+//private part
+ enum ETrackingFlags {kMipDistCut=-9,kMipQdcCut=-5};
+protected:
+ ClassDef(AliHMPIDTracker,0)
+};//class AliHMPIDTracker
+
+#endif//AliHMPIDTracker_h
--- /dev/null
+//**************************************************************************
+// Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// *
+// Author: The ALICE Off-line Project. *
+// Contributors are mentioned in the code where appropriate. *
+// *
+// Permission to use, copy, modify and distribute this software and its *
+// documentation strictly for non-commercial purposes is hereby granted *
+// without fee, provided that the above copyright notice appears in all *
+// copies and that both the copyright notice and this permission notice *
+// appear in the supporting documentation. The authors make no claims *
+// about the suitability of this software for any purpose. It is *
+// provided "as is" without express or implied warranty. *
+//**************************************************************************
+
+#include "AliHMPIDv0.h"
+
+#include <TGeoManager.h>
+
+ClassImp(AliHMPIDv0)
+
+void AliHMPIDv0::StepManager()
+{
+//This StepManager is a provision for different test-learn activities on the current MC layer
+
+}//StepManager()
--- /dev/null
+#ifndef AliHMPIDv0_h
+#define AliHMPIDv0_h
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include "AliHMPID.h"
+
+class AliHMPIDv0 : public AliHMPID
+{
+public:
+ AliHMPIDv0():AliHMPID() {;} //default ctor
+ AliHMPIDv0(const char *name, const char *title):AliHMPID(name,title) {;} //named ctor
+ virtual ~AliHMPIDv0() {;} //dtor
+ virtual void Init() {;} //interface from AliHMPID
+ virtual Int_t IsVersion() const{return 0;} //interface from AliHMPID
+ virtual void StepManager(); //interface from AliHMPID
+protected:
+ ClassDef(AliHMPIDv0,1) //HMPID coarse version for material budget study and debuging
+};
+
+#endif
--- /dev/null
+// **************************************************************************
+// * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+// * *
+// * Author: The ALICE Off-line Project. *
+// * Contributors are mentioned in the code where appropriate. *
+// * *
+// * Permission to use, copy, modify and distribute this software and its *
+// * documentation strictly for non-commercial purposes is hereby granted *
+// * without fee, provided that the above copyright notice appears in all *
+// * copies and that both the copyright notice and this permission notice *
+// * appear in the supporting documentation. The authors make no claims *
+// * about the suitability of this software for any purpose. It is *
+// * provided "as is" without express or implied warranty. *
+// **************************************************************************
+
+
+#include "AliHMPIDv1.h" //class header
+#include "AliHMPIDParam.h" //CreateMaterials()
+#include "AliHMPIDHit.h" //Hits2SDigs(),StepManager()
+#include "AliHMPIDDigit.h" //CreateMaterials()
+#include "AliRawReader.h" //Raw2SDigits()
+#include <TParticle.h> //Hits2SDigits()
+#include <TRandom.h>
+#include <TVirtualMC.h> //StepManager() for gMC
+#include <TPDGCode.h> //StepHistory()
+#include <AliStack.h> //StepManager(),Hits2SDigits()
+#include <AliLoader.h> //Hits2SDigits()
+#include <AliRunLoader.h> //Hits2SDigits()
+#include <AliConst.h>
+#include <AliPDG.h>
+#include <AliMC.h> //StepManager()
+#include <AliRawDataHeader.h> //Digits2Raw()
+#include <AliDAQ.h> //Digits2Raw()
+#include <AliRun.h> //CreateMaterials()
+#include <AliMagF.h> //CreateMaterials()
+#include <TGeoManager.h> //CreateGeometry()
+#include <TMultiGraph.h> //Optics()
+#include <TGraph.h> //Optics()
+#include <TLegend.h> //Optics()
+#include <TCanvas.h> //Optics()
+#include <TF2.h> //CreateMaterials()
+#include <AliCDBManager.h> //CreateMaterials()
+#include <AliCDBEntry.h> //CreateMaterials()
+
+ClassImp(AliHMPIDv1)
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::AddAlignableVolumes()const
+{
+// Associates the symbolic volume name with the corresponding volume path. Interface methode from AliModule ivoked from AliMC
+// Arguments: none
+// Returns: none
+ for(Int_t i=0;i<7;i++)
+ gGeoManager->SetAlignableEntry(Form("/HMPID/Chamber%i",i),Form("ALIC_1/HMPID_%i",i));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::CreateMaterials()
+{
+// Definition of available HMPID materials
+// Arguments: none
+// Returns: none
+ AliDebug(1,"Start v1 HMPID.");
+
+ Float_t emin=5.5,emax=8.5; //Photon energy range,[eV]
+
+ TF2 *pRaIF=new TF2("RidxRad","sqrt(1+0.554*(1239.84/x)^2/((1239.84/x)^2-5796)-0.0005*(y-20))" ,emin,emax,0,50); //DiMauro mail temp 0-50 degrees C
+ TF1 *pWiIF=new TF1("RidxWin","sqrt(1+46.411/(10.666*10.666-x*x)+228.71/(18.125*18.125-x*x))" ,emin,emax); //SiO2 idx TDR p.35
+ TF1 *pGaIF=new TF1("RidxGap","1+0.12489e-6/(2.62e-4 - x*x/1239.84/1239.84)" ,emin,emax); //?????? from where
+
+ TF1 *pRaAF=new TF1("RabsRad","(x<7.8)*(gaus+gaus(3))+(x>=7.8)*0.0001" ,emin,emax); //fit from DiMauro data 28.10.03
+ pRaAF->SetParameters(3.20491e16,-0.00917890,0.742402,3035.37,4.81171,0.626309);
+ TF1 *pWiAF=new TF1("RabsWin","(x<8.2)*(818.8638-301.0436*x+36.89642*x*x-1.507555*x*x*x)+(x>=8.2)*0.0001" ,emin,emax); //fit from DiMauro data 28.10.03
+ TF1 *pGaAF=new TF1("RabsGap","(x<7.75)*6512.399+(x>=7.75)*3.90743e-2/(-1.655279e-1+6.307392e-2*x-8.011441e-3*x*x+3.392126e-4*x*x*x)",emin,emax); //????? from where
+
+ TF1 *pQeF =new TF1("Qe" ,"0+(x>6.07267)*0.344811*(1-exp(-1.29730*(x-6.07267)))" ,emin,emax); //fit from DiMauro data 28.10.03
+
+ const Int_t kNbins=30; //number of photon energy points
+ Float_t aEckov [kNbins];
+ Float_t aAbsRad[kNbins], aAbsWin[kNbins], aAbsGap[kNbins], aAbsMet[kNbins];
+ Float_t aIdxRad[kNbins], aIdxWin[kNbins], aIdxGap[kNbins], aIdxMet[kNbins], aIdxPc[kNbins];
+ Float_t aQeAll [kNbins], aQePc [kNbins];
+
+ for(Int_t i=0;i<kNbins;i++){
+ Float_t eV=emin+0.1*i; //Ckov energy in eV
+ aEckov [i] =1e-9*eV; //Ckov energy in GeV
+ aAbsRad[i]=pRaAF->Eval(eV); aIdxRad[i]=1.292;//pRaIF->Eval(eV,20); //Simulation for 20 degress C
+ aAbsWin[i]=pWiAF->Eval(eV); aIdxWin[i]=1.5787;//pWiIF->Eval(eV);
+ aAbsGap[i]=pGaAF->Eval(eV); aIdxGap[i]=1.0005;//pGaIF->Eval(eV); aQeAll[i] =1; //QE for all other materials except for PC must be 1.
+ aAbsMet[i] =0.0001; aIdxMet[i]=0; //metal ref idx must be 0 in order to reflect photon
+ aIdxPc [i]=1; aQePc [i]=pQeF->Eval(eV); //PC ref idx must be 1 in order to apply photon to QE conversion
+
+ }
+
+//data from PDG booklet 2002 density [gr/cm^3] rad len [cm] abs len [cm]
+ Float_t aAir[4]={12,14,16,36} , zAir[4]={6,7,8,18} , wAir[4]={0.000124,0.755267,0.231781,0.012827} , dAir=0.00120479; Int_t nAir=4;//mixture 0.9999999
+ Float_t aC6F14[2]={ 12.01 , 18.99} , zC6F14[2]={ 6 , 9} , wC6F14[2]={6 , 14} , dC6F14=1.68 ; Int_t nC6F14=-2;
+ Float_t aSiO2[2]={ 28.09 , 15.99} , zSiO2[2]={14 , 8} , wSiO2[2]={1 , 2} , dSiO2=2.64 ; Int_t nSiO2=-2;
+ Float_t aCH4[2]={ 12.01 , 1.01} , zCH4[2]={ 6 , 1} , wCH4[2]={1 , 4} , dCH4=7.17e-4 ; Int_t nCH4=-2;
+ Float_t aCsI[2]={132.90 ,126.90} , zCsI[2]={55 ,53} , wCsI[2]={1 , 1} , dCsI=0.1 ; Int_t nCsI=-2;
+ Float_t aRoha= 12.01 , zRoha= 6 , dRoha= 0.10 , radRoha= 18.80 , absRoha= 86.3/dRoha; //special material- quazi carbon
+ Float_t aCu= 63.55 , zCu= 29 , dCu= 8.96 , radCu= 1.43 , absCu= 134.9/dCu ;
+ Float_t aW=183.84 , zW= 74 , dW= 19.30 , radW= 0.35 , absW= 185.0/dW ;
+ Float_t aAl= 26.98 , zAl= 13 , dAl= 2.70 , radAl= 8.90 , absAl= 106.4/dAl ;
+
+ Int_t matId=0; //tmp material id number
+ Int_t unsens = 0, sens=1; //sensitive or unsensitive medium
+ Int_t itgfld = gAlice->Field()->Integ(); //type of field intergration 0 no field -1 user in guswim 1 Runge Kutta 2 helix 3 const field along z
+ Float_t maxfld = gAlice->Field()->Max(); //max field value
+ Float_t tmaxfd = -10.0; //max deflection angle due to magnetic field in one step
+ Float_t deemax = - 0.2; //max fractional energy loss in one step
+ Float_t stemax = - 0.1; //mas step allowed [cm]
+ Float_t epsil = 0.001; //abs tracking precision [cm]
+ Float_t stmin = - 0.001; //min step size [cm] in continius process transport, negative value: choose it automatically
+ AliMixture(++matId,"Air" ,aAir ,zAir ,dAir ,nAir ,wAir ); AliMedium(kAir ,"Air" ,matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMixture(++matId,"C6F14",aC6F14,zC6F14,dC6F14,nC6F14,wC6F14); AliMedium(kC6F14,"C6F14",matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMixture(++matId,"SiO2" ,aSiO2 ,zSiO2 ,dSiO2 ,nSiO2 ,wSiO2 ); AliMedium(kSiO2 ,"SiO2" ,matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMixture(++matId,"CH4" ,aCH4 ,zCH4 ,dCH4 ,nCH4 ,wCH4 ); AliMedium(kCH4 ,"CH4" ,matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMixture(++matId,"CsI" ,aCsI ,zCsI ,dCsI ,nCsI ,wCsI ); AliMedium(kCsI ,"CsI" ,matId, sens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);//sensitive
+
+ AliMaterial(++matId,"Roha",aRoha,zRoha,dRoha,radRoha,absRoha); AliMedium(kRoha,"Roha", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMaterial(++matId,"Cu" ,aCu ,zCu ,dCu ,radCu ,absCu ); AliMedium(kCu ,"Cu" , matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMaterial(++matId,"W" ,aW ,zW ,dW ,radW ,absW ); AliMedium(kW ,"W" , matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+ AliMaterial(++matId,"Al" ,aAl ,zAl ,dAl ,radAl ,absAl ); AliMedium(kAl ,"Al" , matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
+
+ gMC->SetCerenkov((*fIdtmed)[kC6F14] , kNbins, aEckov, aAbsRad , aQeAll , aIdxRad );
+ gMC->SetCerenkov((*fIdtmed)[kSiO2] , kNbins, aEckov, aAbsWin , aQeAll , aIdxWin );
+ gMC->SetCerenkov((*fIdtmed)[kCH4] , kNbins, aEckov, aAbsGap , aQeAll , aIdxGap );
+ gMC->SetCerenkov((*fIdtmed)[kCu] , kNbins, aEckov, aAbsMet , aQeAll , aIdxMet );
+ gMC->SetCerenkov((*fIdtmed)[kW] , kNbins, aEckov, aAbsMet , aQeAll , aIdxMet ); //n=0 means reflect photons
+ gMC->SetCerenkov((*fIdtmed)[kCsI] , kNbins, aEckov, aAbsMet , aQePc , aIdxPc ); //n=1 means convert photons
+ gMC->SetCerenkov((*fIdtmed)[kAl] , kNbins, aEckov, aAbsMet , aQeAll , aIdxMet );
+
+ delete pRaAF;delete pWiAF;delete pGaAF; delete pRaIF; delete pWiIF; delete pGaIF; delete pQeF;
+ AliDebug(1,"Stop v1 HMPID.");
+
+ TString ttl=GetTitle(); if(!ttl.Contains("ShowOptics")) return; //user didn't aks to plot optical curves
+
+ const Double_t kWidth=0.25,kHeight=0.2;
+ const Int_t kRadM=24 , kRadC=kRed;
+ const Int_t kWinM=26 , kWinC=kBlue;
+ const Int_t kGapM=25 , kGapC=kGreen;
+ const Int_t kPcM = 2 , kPcC =kMagenta;
+
+ Float_t aTraRad[kNbins],aTraWin[kNbins],aTraGap[kNbins],aTraTot[kNbins];
+ for(Int_t i=0;i<kNbins;i++){//calculate probability for photon to survive during transversing a volume of material with absorption length
+ aTraRad[i]=TMath::Exp(-AliHMPIDDigit::SizeRad()/ (aAbsRad[i]+0.0001)); //radiator
+ aTraWin[i]=TMath::Exp(-AliHMPIDDigit::SizeWin()/ (aAbsWin[i] +0.0001)); //window
+ aTraGap[i]=TMath::Exp(-AliHMPIDDigit::SizeGap()/ (aAbsGap[i] +0.0001)); //from window to PC
+ aTraTot[i]=aTraRad[i]*aTraWin[i]*aTraGap[i]*aQePc[i];
+ }
+
+ TGraph *pRaAG=new TGraph(kNbins,aEckov,aAbsRad);pRaAG->SetMarkerStyle(kRadM);pRaAG->SetMarkerColor(kRadC);
+ TGraph *pRaIG=new TGraph(kNbins,aEckov,aIdxRad);pRaIG->SetMarkerStyle(kRadM);pRaIG->SetMarkerColor(kRadC);
+ TGraph *pRaTG=new TGraph(kNbins,aEckov,aTraRad);pRaTG->SetMarkerStyle(kRadM);pRaTG->SetMarkerColor(kRadC);
+
+ TGraph *pWiAG=new TGraph(kNbins,aEckov,aAbsWin);pWiAG->SetMarkerStyle(kWinM);pWiAG->SetMarkerColor(kWinC);
+ TGraph *pWiIG=new TGraph(kNbins,aEckov,aIdxWin);pWiIG->SetMarkerStyle(kWinM);pWiIG->SetMarkerColor(kWinC);
+ TGraph *pWiTG=new TGraph(kNbins,aEckov,aTraWin);pWiTG->SetMarkerStyle(kWinM);pWiTG->SetMarkerColor(kWinC);
+
+ TGraph *pGaAG=new TGraph(kNbins,aEckov,aAbsGap);pGaAG->SetMarkerStyle(kGapM);pGaAG->SetMarkerColor(kGapC);
+ TGraph *pGaIG=new TGraph(kNbins,aEckov,aIdxGap);pGaIG->SetMarkerStyle(kGapM);pGaIG->SetMarkerColor(kGapC);
+ TGraph *pGaTG=new TGraph(kNbins,aEckov,aTraGap);pGaTG->SetMarkerStyle(kGapM);pGaTG->SetMarkerColor(kGapC);
+
+ TGraph *pQeG =new TGraph(kNbins,aEckov,aQePc); pQeG ->SetMarkerStyle(kPcM );pQeG->SetMarkerColor(kPcC);
+ TGraph *pToG =new TGraph(kNbins,aEckov,aTraTot);pToG ->SetMarkerStyle(30) ;pToG->SetMarkerColor(kYellow);
+
+ TMultiGraph *pIdxMG=new TMultiGraph("idx","Ref index;E_{#check{C}} [GeV]");
+ TMultiGraph *pAbsMG=new TMultiGraph("abs","Absorption [cm];E_{#check{C}} [GeV]");
+ TMultiGraph *pTraMG=new TMultiGraph("tra","Transmission;E_{#check{C}} [GeV]"); TLegend *pTraLe=new TLegend(0.2,0.4,0.2+kWidth,0.4+kHeight);
+ pAbsMG->Add(pRaAG); pIdxMG->Add(pRaIG); pTraMG->Add(pRaTG); pTraLe->AddEntry(pRaTG, "Rad", "p");
+ pAbsMG->Add(pWiAG); pIdxMG->Add(pWiIG); pTraMG->Add(pWiTG); pTraLe->AddEntry(pWiTG, "Win", "p");
+ pAbsMG->Add(pGaAG); pIdxMG->Add(pGaIG); pTraMG->Add(pGaTG); pTraLe->AddEntry(pGaTG, "Gap", "p");
+ pTraMG->Add(pToG); pTraLe->AddEntry(pToG, "Tot", "p");
+ pTraMG->Add(pQeG); pTraLe->AddEntry(pQeG, "QE" , "p");
+ TCanvas *pC=new TCanvas("c1","HMPID optics to check",1100,900); pC->Divide(2,2);
+ pC->cd(1); pIdxMG->Draw("AP");
+ pC->cd(2); gPad->SetLogy(); pAbsMG->Draw("AP");
+ pC->cd(3); pTraLe->Draw();
+ pC->cd(4); pTraMG->Draw("AP");
+}//void AliHMPID::CreateMaterials()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::CreateGeometry()
+{
+//Creates detailed geometry simulation (currently GEANT volumes tree)
+ AliDebug(1,"Start main.");
+ if(!gMC->IsRootGeometrySupported()) return;
+
+ Double_t cm=1,mm=0.1*cm,mkm=0.001*mm,dx,dy,dz;//default is cm
+
+ TGeoVolume *pRich=gGeoManager->MakeBox("HMPID",gGeoManager->GetMedium("HMPID_CH4"),dx=(6*mm+1681*mm+6*mm)/2, //main HMPID volume
+ dy=(6*mm+1466*mm+6*mm)/2,
+ dz=(80*mm+40*mm)*2/2); //x,y taken from 2033P1 z from p84 TDR
+ const Double_t kAngHor=19.5; // horizontal angle between chambers 19.5 grad
+ const Double_t kAngVer=20; // vertical angle between chambers 20 grad
+ const Double_t kAngCom=30; // common HMPID rotation with respect to x axis 30 grad
+ const Double_t trans[3]={490,0,0}; //center of the chamber is on window-gap surface
+ for(Int_t iCh=0;iCh<7;iCh++){//place 7 chambers
+ TGeoHMatrix *pMatrix=new TGeoHMatrix;
+ pMatrix->RotateY(90); //rotate around y since initial position is in XY plane -> now in YZ plane
+ pMatrix->SetTranslation(trans); //now plane in YZ is shifted along x
+ switch(iCh){
+ case 0: pMatrix->RotateY(kAngHor); pMatrix->RotateZ(-kAngVer); break; //right and down
+ case 1: pMatrix->RotateZ(-kAngVer); break; //down
+ case 2: pMatrix->RotateY(kAngHor); break; //right
+ case 3: break; //no rotation
+ case 4: pMatrix->RotateY(-kAngHor); break; //left
+ case 5: pMatrix->RotateZ(kAngVer); break; //up
+ case 6: pMatrix->RotateY(-kAngHor); pMatrix->RotateZ(kAngVer); break; //left and up
+ }
+ pMatrix->RotateZ(kAngCom); //apply common rotation in XY plane
+ gGeoManager->GetVolume("ALIC")->AddNode(pRich,iCh,pMatrix);
+ }
+
+ Float_t par[3];
+ Int_t matrixIdReturn=0; //matrix id returned by AliMatrix
+//Pad Panel frame 6 sectors
+ par[0]=648*mm/2;par[1]= 411*mm/2;par[2]=40 *mm/2;gMC->Gsvolu("Rppf" ,"BOX ",(*fIdtmed)[kAl] ,par,3);//PPF 2001P2 inner size of the slab by 1mm more
+ par[0]=181*mm/2;par[1]=89.25*mm/2;par[2]=38.3*mm/2;gMC->Gsvolu("RppfLarge","BOX ",(*fIdtmed)[kAir] ,par,3);//large whole
+ par[0]=114*mm/2;par[1]=89.25*mm/2;par[2]=38.3*mm/2;gMC->Gsvolu("RppfSmall","BOX ",(*fIdtmed)[kAir] ,par,3);//small whole
+ par[0]=644*mm/2;par[1]= 407*mm/2;par[2]= 1.7*mm/2;gMC->Gsvolu("Rpc" ,"BOX ",(*fIdtmed)[kCsI] ,par,3);//by 0.2 mm more then actual size (PCB 2006P1)
+
+ gMC->Gspos("Rppf",0,"HMPID", -335*mm, -433*mm, 8*cm+20*mm, 0,"ONLY");//F1 2040P1 z p.84 TDR
+ gMC->Gspos("Rppf",1,"HMPID", +335*mm, -433*mm, 8*cm+20*mm, 0,"ONLY");
+ gMC->Gspos("Rppf",2,"HMPID", -335*mm, 0*mm, 8*cm+20*mm, 0,"ONLY");
+ gMC->Gspos("Rppf",3,"HMPID", +335*mm, 0*mm, 8*cm+20*mm, 0,"ONLY");
+ gMC->Gspos("Rppf",4,"HMPID", -335*mm, +433*mm, 8*cm+20*mm, 0,"ONLY");
+ gMC->Gspos("Rppf",5,"HMPID", +335*mm, +433*mm, 8*cm+20*mm, 0,"ONLY");
+ gMC->Gspos("Rpc" ,1,"Rppf", 0*mm, 0*mm, -19.15*mm, 0,"ONLY");//PPF 2001P2
+ gMC->Gspos("RppfLarge",1,"Rppf", -224.5*mm, -151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",2,"Rppf", -224.5*mm, - 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",3,"Rppf", -224.5*mm, + 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",4,"Rppf", -224.5*mm, +151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",1,"Rppf", - 65.0*mm, -151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",2,"Rppf", - 65.0*mm, - 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",3,"Rppf", - 65.0*mm, + 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",4,"Rppf", - 65.0*mm, +151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",5,"Rppf", + 65.0*mm, -151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",6,"Rppf", + 65.0*mm, - 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",7,"Rppf", + 65.0*mm, + 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfSmall",8,"Rppf", + 65.0*mm, +151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",5,"Rppf", +224.5*mm, -151.875*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",6,"Rppf", +224.5*mm, - 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",7,"Rppf", +224.5*mm, + 50.625*mm, 0.85*mm, 0,"ONLY");
+ gMC->Gspos("RppfLarge",8,"Rppf", +224.5*mm, +151.875*mm, 0.85*mm, 0,"ONLY");
+//Gap - anod wires 6 copies to HMPID
+ par[0]=648*mm/2;par[1]= 411*mm/2 ;par[2]=4.45*mm/2;gMC->Gsvolu("Rgap","BOX ",(*fIdtmed)[kCH4] ,par,3);//xy as PPF 2001P2 z WP 2099P1
+ par[0]= 0*mm ;par[1]= 20*mkm/2 ;par[2]= 648*mm/2;gMC->Gsvolu("Rano","TUBE",(*fIdtmed)[kW] ,par,3);//WP 2099P1 z = gap x PPF 2001P2
+ AliMatrix(matrixIdReturn,180,0, 90,90, 90,0); //wires along x
+
+ gMC->Gspos("Rgap",0,"HMPID", -335*mm, -433*mm,8*cm-2.225*mm, 0,"ONLY"); //F1 2040P1 z WP 2099P1
+ gMC->Gspos("Rgap",1,"HMPID", +335*mm, -433*mm,8*cm-2.225*mm, 0,"ONLY");
+ gMC->Gspos("Rgap",2,"HMPID", -335*mm, 0*mm,8*cm-2.225*mm, 0,"ONLY");
+ gMC->Gspos("Rgap",3,"HMPID", +335*mm, 0*mm,8*cm-2.225*mm, 0,"ONLY");
+ gMC->Gspos("Rgap",4,"HMPID", -335*mm, +433*mm,8*cm-2.225*mm, 0,"ONLY");
+ gMC->Gspos("Rgap",5,"HMPID", +335*mm, +433*mm,8*cm-2.225*mm, 0,"ONLY");
+ for(int i=1;i<=96;i++)
+ gMC->Gspos("Rano",i,"Rgap", 0*mm, -411/2*mm+i*4*mm, 0.185*mm, matrixIdReturn,"ONLY"); //WP 2099P1
+//Defines radiators geometry
+ par[0]=1330*mm/2 ;par[1]= 413*mm/2 ;par[2]= 24*mm/2; gMC->Gsvolu("Rrad" ,"BOX ",(*fIdtmed)[kC6F14] ,par,3); // Rad 2011P1
+ par[0]=1330*mm/2 ;par[1]= 413*mm/2 ;par[2]= 4*mm/2; gMC->Gsvolu("RradFront" ,"BOX ",(*fIdtmed)[kRoha] ,par,3); //front
+ par[0]=1330*mm/2 ;par[1]= 413*mm/2 ;par[2]= 5*mm/2; gMC->Gsvolu("RradWin" ,"BOX ",(*fIdtmed)[kSiO2] ,par,3); //window
+ par[0]=1330*mm/2 ;par[1]= 5*mm/2 ;par[2]= 15*mm/2; gMC->Gsvolu("RradLong" ,"BOX ",(*fIdtmed)[kRoha] ,par,3); //long side
+ par[0]= 10*mm/2 ;par[1]= 403*mm/2 ;par[2]= 15*mm/2; gMC->Gsvolu("RradShort" ,"BOX ",(*fIdtmed)[kRoha] ,par,3); //short side
+ par[0]= 0 ;par[1]= 10*mm/2 ;par[2]= 15*mm/2; gMC->Gsvolu("RradSpacer","TUBE",(*fIdtmed)[kSiO2] ,par,3); //spacer
+
+ gMC->Gspos("Rrad",1,"HMPID", 0*mm,-434*mm, -12*mm, 0,"ONLY"); //3 radiators to HMPID
+ gMC->Gspos("Rrad",2,"HMPID", 0*mm, 0*mm, -12*mm, 0,"ONLY");
+ gMC->Gspos("Rrad",3,"HMPID", 0*mm,+434*mm, -12*mm, 0,"ONLY");
+ gMC->Gspos("RradFront",1,"Rrad", 0*mm, 0*mm, -10.0*mm, 0,"ONLY"); //front cover
+ gMC->Gspos("RradWin" ,1,"Rrad", 0*mm, 0*mm, 9.5*mm, 0,"ONLY"); //quartz window (back cover)
+ gMC->Gspos("RradLong" ,1,"Rrad", 0*mm,-204*mm, -0.5*mm, 0,"ONLY"); //long side
+ gMC->Gspos("RradLong" ,2,"Rrad", 0*mm,+204*mm, -0.5*mm, 0,"ONLY"); //long side
+ gMC->Gspos("RradShort",1,"Rrad",-660*mm, 0*mm, -0.5*mm, 0,"ONLY"); //short side
+ gMC->Gspos("RradShort",2,"Rrad",+660*mm, 0*mm, -0.5*mm, 0,"ONLY"); //short side
+ for(int i=0;i<3;i++)
+ for(int j=0;j<10;j++)
+ gMC->Gspos("RradSpacer",10*i+j,"Rrad",-1330*mm/2+116*mm+j*122*mm,(i-1)*105*mm,-0.5*mm,0,"ONLY");//spacers
+//Defines SandBox geometry
+ par[0]=1419*mm/2 ;par[1]=1378*mm/2;par[2]=50.5*mm/2; gMC->Gsvolu("Rsb" ,"BOX ",(*fIdtmed)[kAir] ,par,3); //2072P1
+ par[0]=1419*mm/2 ;par[1]=1378*mm/2;par[2]= 0.5*mm/2; gMC->Gsvolu("RsbCover","BOX ",(*fIdtmed)[kAl] ,par,3); //cover
+ par[0]=1359*mm/2 ;par[1]=1318*mm/2;par[2]=49.5*mm/2; gMC->Gsvolu("RsbComb" ,"BOX ",(*fIdtmed)[kRoha] ,par,3); //honeycomb structure
+
+ gMC->Gspos("Rsb",1,"HMPID", 0*mm, 0*mm, -73.75*mm, 0,"ONLY"); //p.84 TDR sandbox to rich
+ gMC->Gspos("RsbComb" ,1,"Rsb", 0*mm, 0*mm, 0*mm, 0,"ONLY"); //2072P1 honeycomv to sandbox
+ gMC->Gspos("RsbCover",1,"Rsb", 0*mm, 0*mm, +25*mm, 0,"ONLY"); //cover to sandbox
+ gMC->Gspos("RsbCover",2,"Rsb", 0*mm, 0*mm, -25*mm, 0,"ONLY"); //cover to sandbox
+ AliDebug(1,"Stop v1. HMPID option");
+}//CreateGeometry()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::Init()
+{
+// This methode defines ID for sensitive volumes, i.e. such geometry volumes for which there are if(gMC->CurrentVolID()==XXX) statements in StepManager()
+// Arguments: none
+// Returns: none
+ AliDebug(1,"Start v1 HMPID.");
+ fIdRad = gMC->VolId("Rrad");
+ fIdWin = gMC->VolId("RradWin");
+ fIdPc = gMC->VolId("Rpc");
+ fIdAmpGap = gMC->VolId("Rgap");
+ fIdProxGap = gMC->VolId("Rgap");
+ AliDebug(1,"Stop v1 HMPID.");
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDv1::IsLostByFresnel()
+{
+// Calculate probability for the photon to be lost by Fresnel reflection.
+ TLorentzVector p4;
+ Double_t mom[3],localMom[3];
+ gMC->TrackMomentum(p4); mom[0]=p4(1); mom[1]=p4(2); mom[2]=p4(3);
+ localMom[0]=0; localMom[1]=0; localMom[2]=0;
+ gMC->Gmtod(mom,localMom,2);
+ Double_t localTc = localMom[0]*localMom[0]+localMom[2]*localMom[2];
+ Double_t localTheta = TMath::ATan2(TMath::Sqrt(localTc),localMom[1]);
+ Double_t cotheta = TMath::Abs(TMath::Cos(localTheta));
+ if(gMC->GetRandom()->Rndm() < Fresnel(p4.E()*1e9,cotheta,1)){
+ AliDebug(1,"Photon lost");
+ return kTRUE;
+ }else
+ return kFALSE;
+}//IsLostByFresnel()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::GenFee(Int_t iCh,Float_t eloss)
+{
+// Generate FeedBack photons for the current particle. To be invoked from StepManager().
+// eloss=0 means photon so only pulse height distribution is to be analysed. This one is done in AliHMPIDParam::TotQdc()
+ TLorentzVector x4;
+ gMC->TrackPosition(x4);
+ Int_t iNphotons=gMC->GetRandom()->Poisson(0.02*200); eloss++; iCh++; //??????????????????????
+ AliDebug(1,Form("N photons=%i",iNphotons));
+ Int_t j;
+ Float_t cthf, phif, enfp = 0, sthf, e1[3], e2[3], e3[3], vmod, uswop,dir[3], phi,pol[3], mom[4];
+//Generate photons
+ for(Int_t i=0;i<iNphotons;i++){//feedbacks loop
+ Double_t ranf[2];
+ gMC->GetRandom()->RndmArray(2,ranf); //Sample direction
+ cthf=ranf[0]*2-1.0;
+ if(cthf<0) continue;
+ sthf = TMath::Sqrt((1 - cthf) * (1 + cthf));
+ phif = ranf[1] * 2 * TMath::Pi();
+
+ if(Double_t randomNumber=gMC->GetRandom()->Rndm()<=0.57)
+ enfp = 7.5e-9;
+ else if(randomNumber<=0.7)
+ enfp = 6.4e-9;
+ else
+ enfp = 7.9e-9;
+
+
+ dir[0] = sthf * TMath::Sin(phif); dir[1] = cthf; dir[2] = sthf * TMath::Cos(phif);
+ gMC->Gdtom(dir, mom, 2);
+ mom[0]*=enfp; mom[1]*=enfp; mom[2]*=enfp;
+ mom[3] = TMath::Sqrt(mom[0]*mom[0]+mom[1]*mom[1]+mom[2]*mom[2]);
+
+ // Polarisation
+ e1[0]= 0; e1[1]=-dir[2]; e1[2]= dir[1];
+ e2[0]=-dir[1]; e2[1]= dir[0]; e2[2]= 0;
+ e3[0]= dir[1]; e3[1]= 0; e3[2]=-dir[0];
+
+ vmod=0;
+ for(j=0;j<3;j++) vmod+=e1[j]*e1[j];
+ if (!vmod) for(j=0;j<3;j++) {
+ uswop=e1[j];
+ e1[j]=e3[j];
+ e3[j]=uswop;
+ }
+ vmod=0;
+ for(j=0;j<3;j++) vmod+=e2[j]*e2[j];
+ if (!vmod) for(j=0;j<3;j++) {
+ uswop=e2[j];
+ e2[j]=e3[j];
+ e3[j]=uswop;
+ }
+
+ vmod=0; for(j=0;j<3;j++) vmod+=e1[j]*e1[j]; vmod=TMath::Sqrt(1/vmod); for(j=0;j<3;j++) e1[j]*=vmod;
+ vmod=0; for(j=0;j<3;j++) vmod+=e2[j]*e2[j]; vmod=TMath::Sqrt(1/vmod); for(j=0;j<3;j++) e2[j]*=vmod;
+
+ phi = gMC->GetRandom()->Rndm()* 2 * TMath::Pi();
+ for(j=0;j<3;j++) pol[j]=e1[j]*TMath::Sin(phi)+e2[j]*TMath::Cos(phi);
+ gMC->Gdtom(pol, pol, 2);
+ Int_t outputNtracksStored;
+ gAlice->GetMCApp()->PushTrack(1, //transport
+ gAlice->GetMCApp()->GetCurrentTrackNumber(),//parent track
+ kFeedback, //PID
+ mom[0],mom[1],mom[2],mom[3], //track momentum
+ x4.X(),x4.Y(),x4.Z(),x4.T(), //track origin
+ pol[0],pol[1],pol[2], //polarization
+ kPFeedBackPhoton, //process ID
+ outputNtracksStored, //on return how many new photons stored on stack
+ 1.0); //weight
+ }//feedbacks loop
+ AliDebug(1,"Stop.");
+}//GenerateFeedbacks()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::Hits2SDigits()
+{
+// Interface methode ivoked from AliSimulation to create a list of sdigits corresponding to list of hits. Every hit generates one or more sdigits.
+// Arguments: none
+// Returns: none
+ AliDebug(1,"Start.");
+ for(Int_t iEvt=0;iEvt < GetLoader()->GetRunLoader()->GetNumberOfEvents();iEvt++){ //events loop
+ GetLoader()->GetRunLoader()->GetEvent(iEvt); //get next event
+
+ if(!GetLoader()->TreeH()) {GetLoader()->LoadHits(); }
+ if(!GetLoader()->TreeS()) {GetLoader()->MakeTree("S"); MakeBranch("S");}//to
+
+ for(Int_t iPrimN=0;iPrimN<GetLoader()->TreeH()->GetEntries();iPrimN++){//prims loop
+ GetLoader()->TreeH()->GetEntry(iPrimN);
+ Hit2Sdi(Hits(),SdiLst());
+ }//prims loop
+ GetLoader()->TreeS()->Fill();
+ GetLoader()->WriteSDigits("OVERWRITE");
+ SdiReset();
+ }//events loop
+ GetLoader()->UnloadHits();
+ GetLoader()->UnloadSDigits();
+ AliDebug(1,"Stop.");
+}//Hits2SDigits()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::Hit2Sdi(TClonesArray *pHitLst,TClonesArray *pSdiLst)
+{
+// Converts list of hits to list of sdigits. For each hit in a loop the following steps are done:
+// - calcultion of the total charge induced by the hit
+// - determination of the pad contaning the hit and shifting hit y position to the nearest anod wire y
+// - defining a set of pads affected (up to 9 including the hitted pad)
+// - calculating charge induced to all those pads using integrated Mathieson distribution and creating sdigit
+// Arguments: pHitLst - list of hits provided not empty
+// pSDigLst - list of sdigits where to store the results
+// Returns: none
+ for(Int_t iHit=0;iHit<pHitLst->GetEntries();iHit++){ //hits loop
+ AliHMPIDHit *pHit=(AliHMPIDHit*)pHitLst->At(iHit); //get pointer to current hit
+ AliHMPIDDigit::Hit2Sdi(pHit,pSdiLst); //convert this hit to list of sdigits
+ }//hits loop loop
+}//Hits2SDigs() for TVector2
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::Digits2Raw()
+{
+// Creates raw data files in DDL format. Invoked by AliSimulation where loop over events is done
+// Arguments: none
+// Returns: none
+ AliDebug(1,"Start.");
+ GetLoader()->LoadDigits();
+ TTree * treeD = GetLoader()->TreeD();
+ if(!treeD) {
+ AliError("No digits tree!");
+ return;
+ }
+ treeD->GetEntry(0);
+
+ ofstream file[AliHMPIDDigit::kNddls]; //output streams
+ Int_t cnt[AliHMPIDDigit::kNddls]; //data words counters for DDLs
+ AliRawDataHeader header; //empty DDL header
+ UInt_t w32=0; //32 bits data word
+
+ for(Int_t i=0;i<AliHMPIDDigit::kNddls;i++){
+ file[i].open(AliDAQ::DdlFileName(GetName(),i)); //open all 14 DDL in parallel
+ file[i].write((char*)&header,sizeof(header)); //write dummy header as place holder, actual will be written later when total size of DDL is known
+ cnt[i]=0; //reset counters
+ }
+
+ for(Int_t iCh=0;iCh<7;iCh++)
+ for(Int_t iDig=0;iDig<DigLst(iCh)->GetEntriesFast();iDig++){//digits loop for a given chamber
+ AliHMPIDDigit *pDig=(AliHMPIDDigit*)DigLst(iCh)->At(iDig);
+ Int_t ddl=pDig->Raw(w32); //ddl is 0..13
+ file[ddl].write((char*)&w32,sizeof(w32)); cnt[ddl]++;//write formated digit to the propriate file (as decided in Dig2Raw) and increment corresponding counter
+ }//digits
+
+
+ for(Int_t i=0;i<AliHMPIDDigit::kNddls;i++){
+ header.fSize=sizeof(header)+cnt[i]*sizeof(w32); //now calculate total number of bytes for each DDL file
+ header.SetAttribute(0);
+ file[i].seekp(0); file[i].write((char*)&header,sizeof(header));//rewrite DDL header with fSize field properly set
+ file[i].close(); //close DDL file
+ }
+ GetLoader()->UnloadDigits();
+ AliDebug(1,"Stop.");
+}//Digits2Raw()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Float_t AliHMPIDv1::Fresnel(Float_t ene,Float_t pdoti, Bool_t pola)
+{
+// Correction for Fresnel ???????????
+// Arguments: ene - photon energy [GeV],
+// PDOTI=COS(INC.ANG.), PDOTR=COS(POL.PLANE ROT.ANG.)
+// Returns:
+ Float_t en[36] = {5.0,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6.0,6.1,6.2,
+ 6.3,6.4,6.5,6.6,6.7,6.8,6.9,7.0,7.1,7.2,7.3,7.4,7.5,7.6,7.7,
+ 7.8,7.9,8.0,8.1,8.2,8.3,8.4,8.5};
+ Float_t csin[36] = {2.14,2.21,2.33,2.48,2.76,2.97,2.99,2.59,2.81,3.05,
+ 2.86,2.53,2.55,2.66,2.79,2.96,3.18,3.05,2.84,2.81,2.38,2.11,
+ 2.01,2.13,2.39,2.73,3.08,3.15,2.95,2.73,2.56,2.41,2.12,1.95,
+ 1.72,1.53};
+ Float_t csik[36] = {0.,0.,0.,0.,0.,0.196,0.408,0.208,0.118,0.49,0.784,0.543,
+ 0.424,0.404,0.371,0.514,0.922,1.102,1.139,1.376,1.461,1.253,0.878,
+ 0.69,0.612,0.649,0.824,1.347,1.571,1.678,1.763,1.857,1.824,1.824,
+ 1.714,1.498};
+ Float_t xe=ene;
+ Int_t j=Int_t(xe*10)-49;
+ Float_t cn=csin[j]+((csin[j+1]-csin[j])/0.1)*(xe-en[j]);
+ Float_t ck=csik[j]+((csik[j+1]-csik[j])/0.1)*(xe-en[j]);
+
+ //FORMULAE FROM HANDBOOK OF OPTICS, 33.23 OR
+ //W.R. HUNTER, J.O.S.A. 54 (1964),15 , J.O.S.A. 55(1965),1197
+
+ Float_t sinin=TMath::Sqrt(1-pdoti*pdoti);
+ Float_t tanin=sinin/pdoti;
+
+ Float_t c1=cn*cn-ck*ck-sinin*sinin;
+ Float_t c2=4*cn*cn*ck*ck;
+ Float_t aO=TMath::Sqrt(0.5*(TMath::Sqrt(c1*c1+c2)+c1));
+ Float_t b2=0.5*(TMath::Sqrt(c1*c1+c2)-c1);
+
+ Float_t rs=((aO-pdoti)*(aO-pdoti)+b2)/((aO+pdoti)*(aO+pdoti)+b2);
+ Float_t rp=rs*((aO-sinin*tanin)*(aO-sinin*tanin)+b2)/((aO+sinin*tanin)*(aO+sinin*tanin)+b2);
+
+
+ //CORRECTION FACTOR FOR SURFACE ROUGHNESS
+ //B.J. STAGG APPLIED OPTICS, 30(1991),4113
+
+ Float_t sigraf=18.;
+ Float_t lamb=1240/ene;
+ Float_t fresn;
+
+ Float_t rO=TMath::Exp(-(4*TMath::Pi()*pdoti*sigraf/lamb)*(4*TMath::Pi()*pdoti*sigraf/lamb));
+
+ if(pola)
+ {
+ Float_t pdotr=0.8; //DEGREE OF POLARIZATION : 1->P , -1->S
+ fresn=0.5*(rp*(1+pdotr)+rs*(1-pdotr));
+ }
+ else
+ fresn=0.5*(rp+rs);
+
+ fresn = fresn*rO;
+ return fresn;
+}//Fresnel()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::Print(Option_t *option)const
+{
+// Debug printout
+ TObject::Print(option);
+}//void AliHMPID::Print(Option_t *option)const
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Bool_t AliHMPIDv1::Raw2SDigits(AliRawReader *pRR)
+{
+// Interface methode ivoked from AliSimulation to create a list of sdigits from raw digits. Events loop is done in AliSimulation
+// Arguments: pRR- raw reader
+// Returns: kTRUE on success (currently ignored in AliSimulation::ConvertRaw2SDigits())
+ AliHMPIDDigit sdi; //tmp sdigit, raw digit will be converted to it
+
+ if(!GetLoader()->TreeS()) {MakeTree("S"); MakeBranch("S");}
+
+ TClonesArray *pSdiLst=SdiLst(); Int_t iSdiCnt=0; //tmp list of sdigits for all chambers
+ pRR->Select("HMPID",0,13);//select all HMPID DDL files
+ UInt_t w32=0;
+ while(pRR->ReadNextInt(w32)){//raw records loop (in selected DDL files)
+ UInt_t ddl=pRR->GetDDLID(); //returns 0,1,2 ... 13
+ sdi.ReadRaw(ddl,w32);
+ new((*pSdiLst)[iSdiCnt++]) AliHMPIDDigit(sdi); //add this digit to the tmp list
+ }//raw records loop
+ GetLoader()->TreeS()->Fill(); GetLoader()->WriteSDigits("OVERWRITE");//write out sdigits
+ SdiReset();
+ return kTRUE;
+}//Raw2SDigits
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::StepCount()
+{
+// Count number of ckovs created
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::StepHistory()
+{
+// This methode is invoked from StepManager() in order to print out
+ static Int_t iStepN;
+ const char *sParticle;
+ switch(gMC->TrackPid()){
+ case kProton: sParticle="PROTON" ;break;
+ case kNeutron: sParticle="neutron" ;break;
+ case kGamma: sParticle="gamma" ;break;
+ case kCerenkov: sParticle="CKOV" ;break;
+ case kPi0: sParticle="Pi0" ;break;
+ case kPiPlus: sParticle="Pi+" ;break;
+ case kPiMinus: sParticle="Pi-" ;break;
+ case kElectron: sParticle="electron" ;break;
+ default: sParticle="not known" ;break;
+ }
+
+ TString flag="fanny combination";
+ if(gMC->IsTrackAlive())
+ if(gMC->IsTrackEntering()) flag="enters to";
+ else if(gMC->IsTrackExiting()) flag="exits from";
+ else if(gMC->IsTrackInside()) flag="inside";
+ else
+ if(gMC->IsTrackStop()) flag="stoped in";
+
+ Int_t vid=0,copy=0;
+ TString path=gMC->CurrentVolName(); path.Prepend("-");path.Prepend(gMC->CurrentVolOffName(1));//current volume and his mother are always there
+ vid=gMC->CurrentVolOffID(2,copy); if(vid) {path.Prepend("-");path.Prepend(gMC->VolName(vid));}
+ vid=gMC->CurrentVolOffID(3,copy); if(vid) {path.Prepend("-");path.Prepend(gMC->VolName(vid));}
+
+ Printf("Step %i: %s (%i) %s %s m=%.6f GeV q=%.1f dEdX=%.4f",iStepN,sParticle,gMC->TrackPid(),flag.Data(),path.Data(),gMC->TrackMass(),gMC->TrackCharge(),gMC->Edep()*1e9);
+
+ Printf("Step %i: tid=%i flags alive=%i disap=%i enter=%i exit=%i inside=%i out=%i stop=%i new=%i",
+ iStepN, gAlice->GetMCApp()->GetCurrentTrackNumber(),
+ gMC->IsTrackAlive(), gMC->IsTrackDisappeared(),gMC->IsTrackEntering(), gMC->IsTrackExiting(),
+ gMC->IsTrackInside(),gMC->IsTrackOut(), gMC->IsTrackStop(), gMC->IsNewTrack());
+
+ Float_t a,z,den,rad,abs; a=z=den=rad=abs=-1;
+ Int_t mid=gMC->CurrentMaterial(a,z,den,rad,abs);
+ Printf("Step %i: id=%i a=%7.2f z=%7.2f den=%9.4f rad=%9.2f abs=%9.2f\n\n",iStepN,mid,a,z,den,rad,abs);
+ iStepN++;
+}//StepHistory()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void AliHMPIDv1::StepManager()
+{
+// Full Step Manager.
+// Arguments: none
+// Returns: none
+// StepHistory(); return; //uncomment to print tracks history
+// StepCount(); return; //uncomment to count photons
+
+ Int_t copy; //volume copy aka node
+
+//Treat photons
+ if((gMC->TrackPid()==kCerenkov||gMC->TrackPid()==kFeedback)&&gMC->CurrentVolID(copy)==fIdPc){ //photon (Ckov or feedback) hit PC (fIdPc)
+ if(gMC->Edep()>0){ //photon survided QE test i.e. produces electron
+ if(IsLostByFresnel()){ gMC->StopTrack(); return;} //photon lost due to fersnel reflection on PC
+ gMC->CurrentVolOffID(2,copy); //current chamber since geomtry tree is HMPID-Rppf-Rpc
+ Int_t tid= gMC->GetStack()->GetCurrentTrackNumber(); //take TID
+ Int_t pid= gMC->TrackPid(); //take PID
+ Float_t etot= gMC->Etot(); //total hpoton energy, [GeV]
+ Double_t x[3]; gMC->TrackPosition(x[0],x[1],x[2]); //take MARS position at entrance to PC
+ Float_t xl,yl; AliHMPIDParam::Instance()->Mars2Lors(copy,x,xl,yl); //take LORS position
+ new((*fHits)[fNhits++])AliHMPIDHit(copy,etot,pid,tid,xl,yl,x); //HIT for photon, position at PC
+ GenFee(copy); //generate feedback photons
+ }//photon hit PC and DE >0
+ }//photon hit PC
+
+//Treat charged particles
+ static Double_t dEdX; //need to store mip parameters between different steps
+ static Double_t in[3];
+ if(gMC->TrackCharge() && gMC->CurrentVolID(copy)==fIdAmpGap){ //charged particle in amplification gap (fIdAmpGap)
+ if(gMC->IsTrackEntering()||gMC->IsNewTrack()) { //entering or newly created
+ dEdX=0; //reset dEdX collector
+ gMC->TrackPosition(in[0],in[1],in[2]); //take position at the entrance
+ }else if(gMC->IsTrackExiting()||gMC->IsTrackStop()||gMC->IsTrackDisappeared()){ //exiting or disappeared
+ dEdX +=gMC->Edep(); //take into account last step dEdX
+ gMC->CurrentVolOffID(1,copy); //take current chamber since geometry tree is HMPID-Rgap
+ Int_t tid= gMC->GetStack()->GetCurrentTrackNumber(); //take TID
+ Int_t pid= gMC->TrackPid(); //take PID
+ Double_t out[3]; gMC->TrackPosition(out[0],out[1],out[2]); //take MARS position at exit
+ out[0]=0.5*(out[0]+in[0]); out[1]=0.5*(out[1]+in[1]); out[1]=0.5*(out[1]+in[1]); //take hit position at the anod plane
+ Float_t xl,yl;AliHMPIDParam::Instance()->Mars2Lors(copy,out,xl,yl); //take LORS position
+ new((*fHits)[fNhits++])AliHMPIDHit(copy,dEdX,pid,tid,xl,yl,out); //HIT for MIP, position near anod plane
+ GenFee(copy,dEdX); //generate feedback photons
+ }else //just going inside
+ dEdX += gMC->Edep(); //collect this step dEdX
+ }//MIP in GAP
+}//StepManager()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+#ifndef AliHMPIDv1_h
+#define AliHMPIDv1_h
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+#include "AliHMPID.h" //base class
+#include "AliHMPIDDigitizer.h" //CreateDigitizer()
+
+class AliHMPIDv1 : public AliHMPID //TObject-TNamed-AliModule-AliDetector-AliHMPID-AliHMPIDv0
+{
+public:
+ AliHMPIDv1() :AliHMPID( ),fIdRad(-1),fIdWin(-1),fIdProxGap(-1),fIdAmpGap(-1),fIdPc(-1),fIdAnod(-1),fIdCath(-1),fIdColl(-1) {;} //default ctor
+ AliHMPIDv1(const char *name, const char *title):AliHMPID(name,title),fIdRad(-1),fIdWin(-1),fIdProxGap(-1),fIdAmpGap(-1),fIdPc(-1),fIdAnod(-1),fIdCath(-1),fIdColl(-1) {;} //named ctor
+ virtual ~AliHMPIDv1() {;} //dtor
+//framework part++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ void AddAlignableVolumes( )const; //from AliModule invoked from AliMC
+ void CreateMaterials ( ); //from AliModule invoked from AliMC
+ void CreateGeometry ( ); //from AliModule invoked from AliMC
+ AliDigitizer* CreateDigitizer (AliRunDigitizer *m )const{return new AliHMPIDDigitizer(m);} //from AliModule invoked from AliSimulation::RunDigitization()
+ void Digits2Raw ( ); //from AliModule invoked from AliSimulation::WriteRawFiles()
+ void Hits2SDigits ( ); //from AliModule invoked from AliSimulation::RunSDigitization()
+ void Init ( ); //from AliModule invoked from AliMC::InitGeometry()
+ Int_t IsVersion ( )const{return 1; } //from AliModule not used
+ void Print (const Option_t *opt="" )const; //from TObject
+ Bool_t Raw2SDigits (AliRawReader * ); //from AliMOdule invoked from AliSimulation
+ void StepManager ( ); //from AliModule invoked from AliMC::Stepping()
+//private part++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ void GenFee (Int_t iCh,Float_t eloss=0 ); //generates feedback photons; eloss=0 for photon
+ static Float_t Fresnel (Float_t geV,Float_t p, Bool_t pl ); //deals with Fresnel absorption on PC
+ static void Hit2Sdi (TClonesArray *pH,TClonesArray *pS);
+ Bool_t IsLostByFresnel ( ); //checks if the photon lost on Fresnel reflection
+ void StepCount ( ); //counts particles in StepManager()
+ void StepHistory ( ); //prints history of tracking in StepManager()
+protected:
+ enum EMedia {kAir=1,kRoha=2,kSiO2=3,kC6F14=4,kCH4=5,kCsI=6,kAl=7,kCu=8,kW=9}; //media ids, used for geometry creation
+ enum Ecounters {kMipEnterRad=1,kCkovNew,kCkovNewRad,kCkovNewWin,kCkovNewProxGap,kCkovNewAmpGap,kCkovEnterPc,kPhotoEle}; //counters id's
+ Int_t fIdRad,fIdWin,fIdProxGap,fIdAmpGap,fIdPc,fIdAnod,fIdCath,fIdColl; //! volumes ID's used in StepManager() and Count()
+ ClassDef(AliHMPIDv1,2) //HMPID full version for simulation
+};
+
+#endif
--- /dev/null
+void RichAlign(Float_t sigmaTrans=0.1, Float_t sigmaRot=0.001)
+{
+ Float_t dX, dY, dZ; Float_t dPsi, dTheta, dPhi; //displacements
+
+ TClonesArray *pCA = new TClonesArray("AliAlignObjMatrix",10000);
+
+ TRandom *pRnd = new TRandom(4357);
+
+ AliAlignObjMatrix o;
+
+ Int_t idHMPID = AliAlignObj::kHMPID;
+ for (Int_t iCh = 0; iCh < 7; iCh++) {
+ dX = pRnd->Gaus(0,sigmaTrans); dY = pRnd->Gaus(0,sigmaTrans); dZ = pRnd->Gaus(0,sigmaTrans);
+ dPsi = pRnd->Gaus(0,sigmaRot); dTheta = pRnd->Gaus(0,sigmaRot); dPhi = pRnd->Gaus(0,sigmaRot);
+ new((*pCA)[iCh]) AliAlignObjMatrix(AliAlignObj::GetVolPath(idHMPID,iCh), AliAlignObj::LayerToVolUID(idHMPID,iCh),dX,dY,dZ,dPsi,dTheta,dPhi);
+ }
+
+ pCA->Print();
+
+ AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
+
+ AliCDBMetaData *pMeta= new AliCDBMetaData();
+ pMeta->SetResponsible("HMPID Expert");
+ pMeta->SetComment("Alignment objects for ideal geometry, i.e. applying them to TGeo has to leave geometry unchanged");
+ AliCDBId id("HMPID/Align/Data",0,0); //you have to specify the run validity, although in the case of saving ideal objects makes not much sense
+ AliCDBManager::Instance()->Put(pCA,id,pMeta);
+ pCA->Delete();
+}
--- /dev/null
+//This script is a skeleton for HMPID analisys. It consequently reads events in a givent set of directories and provides
+//resulting RANA.root file in home directory which contains all the requested hists.
+#if !defined( __CINT__) || defined(__MAKECINT__)
+#include <TCanvas.h>
+#include <TTree.h>
+#include <TH2F.h>
+#include <AliESD.h>
+#include <AliESDtrack.h>
+#include <TFile.h>
+#endif
+
+
+TH2F *pMassLen2;
+
+void HistBook()
+{
+ pMassLen2=new TH2F("masslen","Particle mass versus track length;cm;GeV",200,0,600,200,0,1.2);
+}
+//__________________________________________________________________________________________________
+void HistFill(AliESDtrack *pTrack)
+{
+ pMassLen2->Fill(pTrack->GetIntegratedLength(),pTrack->GetMass());
+
+}
+//__________________________________________________________________________________________________
+void HistOut()
+{
+ TCanvas *pC=new TCanvas("HMPID analisys");
+ pMassLen2->Draw();
+
+ TFile outFile("~/RANA.root","RECREATE"); pC->Write(); outFile.Close();
+}
+//__________________________________________________________________________________________________
+void Analyse(char *sDirName)
+{
+//Analyse info from single directory
+ ::Info("","Tring to open from %s",sDirName);
+ TFile *pFile=TFile::Open(Form("%s/AliESDs.root",sDirName));if(!pFile || !pFile->IsOpen()) return;//open AliESDs.root
+ TTree* pTree = (TTree*) pFile->Get("esdTree"); if(!pTree) return;//get ESD tree
+
+ AliESD *pESD=new AliESD; pTree->SetBranchAddress("ESD", &pESD);
+
+ Int_t iNevents=pTree->GetEntries(); //how many events in this given directory
+ ::Info("","have %i events",iNevents);
+ for(Int_t iEventN=0;iEventN<iNevents;iEventN++){//ESD events loop
+ pTree->GetEvent(iEventN);
+ Int_t iNtracks=pESD->GetNumberOfTracks();
+ for(Int_t iTrackN=0;iTrackN<iNtracks;iTrackN++){//ESD tracks loop
+ HistFill(pESD->GetTrack(iTrackN));
+ }//ESD tracks loop
+ }//ESD events loop
+
+ delete pESD; pFile->Close();//close AliESDs.root
+}
+//__________________________________________________________________________________________________
+void RichAna(Int_t iDirFirst=1,Int_t iDirLast=4)
+{
+ gBenchmark->Start("HMPIDanalisys");
+
+ HistBook();
+
+ for(Int_t iDirN=iDirFirst;iDirN<=iDirLast;iDirN++) Analyse(Form("Ev%04i",iDirN)); //analise for single directory
+
+ HistOut();
+
+ gBenchmark->Stop("HMPIDanalisys");
+ gBenchmark->Show("HMPIDanalisys");
+}
--- /dev/null
+#include <TPDGCode.h>
+
+class RichConfig : public TGMainFrame
+{
+RQ_OBJECT()
+public:
+ RichConfig(const char*sFileName);
+ ~RichConfig() {Info("ctor","");Cleanup();}
+
+ enum EVersOpts {kNo=101,kVer0,kVer1,kVer2,kTest, kDeclust=301,kSagita,kFeedback,kSecRad,kQe0=400,kQeNorm,kOptics};
+ enum EGenTypes {kGunZ=1,kGun1,kGun7,kBox,kHijing,kHijingPara,kPythia,kRichLib,kNotUsed=999};
+
+ enum EDetectors {kPIPE=1,kITS,kTPC,kTRD,kTOF,kFRAME,kMAG,kCRT,kHALL,kPHOS,kSTART,kFMD,kABSO,kPMD,kDIPO,kEMCAL,kVZERO,kMUON,kZDC,kSHILD};
+ enum EProcesses {kDCAY=1,kPAIR,kCOMP,kPHOT,kPFIS,kDRAY,kANNI,kBREM,kMUNU,kCKOV,kHADR,kLOSS,kMULS,kRAYL,kALL};
+ enum EBatchFlags{kPrim=555,kTransport,kAll,kOnly,kRawDdl,kRawDate,kRawRoot,kVertex,kTrack,kHlt,kEsd,kAlign};
+ enum EMagField {kFld0,kFld2,kFld4,kFld5,kFld_2,kFld_4,kFld_5};
+
+ Float_t Eta2Theta (Float_t arg) const{return (180./TMath::Pi())*2.*TMath::ATan(TMath::Exp(-arg));}
+
+ void GuiRich (TGHorizontalFrame *pMainF); void WriteRich (FILE *pF); void RichSlot (Int_t ver);
+ void GuiPhys (TGHorizontalFrame *pMainF); void WritePhys (FILE *pF); void PhysAddSlot(Int_t id); void PhysRemSlot(Int_t id);
+ void GuiGen (TGCompositeFrame *pMainF); void WriteGen (FILE *pF); void GenAddSlot (Int_t id); void GenRemSlot (Int_t id);
+ void GuiDet (TGHorizontalFrame *pMainF); void WriteDet (FILE *pF); void DetAddSlot (Int_t id); void DetRemSlot (Int_t id);
+ void GuiBatch(TGHorizontalFrame *pMainF); void WriteBatch( ); void SlotBatch (Int_t id);
+
+ void WriteConfig();
+ void ExitSlot();
+
+ TGButtonGroup *fVerBG,*fOptBG,*fQeBG; //Rich widgets
+ TGButtonGroup *fMagBG; //mag field widgets
+ TGButton *fDecayerB; //external decayer widgets
+
+ TGComboBox *fGenPidCO,*fGenPminCO,*fGenPmaxCO,*fGenChamCO,*fGenNprimCO; //generator widgets combos
+ TGCompositeFrame *fGenF; //generator widgets frames
+ TGButtonGroup *fGenBG; //generator widgets
+
+ TGButtonGroup *fDetBG,*fProcBG; //detectors and processes widgets
+ TGButtonGroup *fSimBG,*fSDigBG,*fDigBG,*fRawBG,*fClusBG,*fRecoBG; //batch control widgets
+
+ char *fFileName;
+};//class RichConfig
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+RichConfig::RichConfig(const char *sFileName):TGMainFrame(gClient->GetRoot(),700,400)
+{
+ fFileName=sFileName;
+
+ AddFrame(pMainF=new TGHorizontalFrame(this,100,200)); //main horizontal frame
+
+ GuiRich (pMainF);
+ GuiGen (pMainF);
+ GuiDet (pMainF);
+ GuiPhys (pMainF);
+ GuiBatch(pMainF);
+
+//File
+ AddFrame(pFileHF=new TGHorizontalFrame(this,100,200));
+ pFileHF->AddFrame(pCrtTB=new TGTextButton(pFileHF,"Create"));
+ pCrtTB->Connect("Clicked()","RichConfig",this,"ExitSlot()");
+ pFileHF->AddFrame(new TGLabel(pFileHF,Form(" config file as %s",fFileName)));
+
+ MapSubwindows();
+ Resize(GetDefaultSize());
+ SetWindowName("Create AliROOT scripts");
+ MapWindow();
+}//ctor
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GuiRich(TGHorizontalFrame *pMainHF)
+{
+ pMainHF->AddFrame(pLeftVF=new TGVerticalFrame(pMainHF,100,200));
+ pLeftVF->AddFrame(pRichGF=new TGGroupFrame(pLeftVF,"HMPID"));
+ pRichGF->AddFrame(fVerBG=new TGButtonGroup(pRichGF,"")); fVerBG->Connect("Pressed(Int_t)" ,"RichConfig",this,"RichVerSlot(Int_t)");
+ new TGRadioButton(fVerBG, "No" ,kNo ));
+ new TGRadioButton(fVerBG, "ver0" ,kVer0 ));
+ new TGRadioButton(fVerBG, "ver1" ,kVer1 )); fVerBG->SetButton(kVer1);
+ new TGRadioButton(fVerBG, "ver2" ,kVer2 ));
+ pRichGF->AddFrame(fOptBG=new TGButtonGroup(pRichGF,"")); fOptBG->Connect("Pressed(Int_t)" ,"RichConfig",this,"RichVerSlot(Int_t)");
+ new TGCheckButton(fOptBG,"Test beam position?" ,kTest);
+ new TGCheckButton(fOptBG,"Second radiator?" ,kSecRad);
+ new TGCheckButton(fOptBG,"Decluster?" ,kDeclust); fOptBG->SetButton(kDeclust);
+ new TGCheckButton(fOptBG,"Wire sagita?" ,kSagita); fOptBG->SetButton(kSagita);
+ new TGCheckButton(fOptBG,"Feedbacks?" ,kFeedback); fOptBG->SetButton(kFeedback);
+ new TGCheckButton(fOptBG,"Plot optics?" ,kOptics);
+ pRichGF->AddFrame(fQeBG=new TGButtonGroup(pRichGF,""));
+ new TGRadioButton(fQeBG,"QE=0" ,kQe0);
+ new TGRadioButton(fQeBG,"QE normal" ,kQeNorm); fQeBG->SetButton(kQeNorm);
+ pLeftVF->AddFrame(fDecayerB=new TGCheckButton(pLeftVF,"Puthia decayer On/Off")); fDecayerB->SetState(kButtonDown);
+ pLeftVF->AddFrame(fMagBG=new TGButtonGroup(pLeftVF,"Mag field"));
+ new TGRadioButton(fMagBG, "0.5 T" ,kFld5 ));
+ new TGRadioButton(fMagBG, "0.4 T" ,kFld4 ));
+ new TGRadioButton(fMagBG, "0.2 T" ,kFld2 )); fMagBG->SetButton(kFld2);
+ new TGRadioButton(fMagBG, "0 T" ,kFld0 ));
+ new TGRadioButton(fMagBG, "-0.2 T" ,kFld_2 ));
+ new TGRadioButton(fMagBG, "-0.4 T" ,kFld_4 ));
+ new TGRadioButton(fMagBG, "-0.5 T" ,kFld_5 ));
+}//Rich()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::RichVerSlot(Int_t ver)
+{
+ if(ver==kTest) {fMagBG->SetButton(kFld0); fGenBG->SetButton(kGunZ); }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WriteRich(FILE *pF)
+{
+ if(!fVerBG->GetButton(kNo)->GetState()){
+ TString title;
+ if( fOptBG->GetButton(kSecRad)->GetState()) title+=" Radiator2 ";
+ if(!fOptBG->GetButton(kSagita)->GetState()) fprintf(pF," AliHMPIDParam::fgIsWireSagita=kFALSE;\n");
+ if( fOptBG->GetButton(kTest) ->GetState()) title+=" TestBeam ";
+ if( fOptBG->GetButton(kOptics)->GetState()) title+=" ShowOptics ";
+ if(title.Length()==0) title="Default";
+
+ if (fVerBG->GetButton(kVer0)->GetState()) fprintf(pF," new AliHMPIDv0(\"Gel %s\");\n\n",title.Data());
+ else if(fVerBG->GetButton(kVer1)->GetState()) fprintf(pF," new AliHMPIDv1(\"HMPID\",\"%s\");\n\n",title.Data());
+ else if(fVerBG->GetButton(kVer2)->GetState()) fprintf(pF," new AliHMPIDv2(\"Tic %s\");\n\n",title.Data());
+ }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GuiPhys(TGHorizontalFrame *pMainHF)
+{
+ pMainHF->AddFrame(fProcBG=new TGButtonGroup(pMainHF,"Procs"));
+ fProcBG->Connect("Pressed(Int_t)" ,"RichConfig",this,"PhysAddSlot(Int_t)");
+ fProcBG->Connect("Released(Int_t)","RichConfig",this,"PhysRemSlot(Int_t)");
+ new TGCheckButton(fProcBG,"ALL ON/OFF" ,kALL)) ;
+ new TGCheckButton(fProcBG,"DCAY Decay" ,kDCAY)); fProcBG->SetButton(kDCAY);
+ new TGCheckButton(fProcBG,"PAIR Pair production" ,kPAIR)); fProcBG->SetButton(kPAIR);
+ new TGCheckButton(fProcBG,"COMP Compton" ,kCOMP)); fProcBG->SetButton(kCOMP);
+ new TGCheckButton(fProcBG,"PHOT" ,kPHOT)); fProcBG->SetButton(kPHOT);
+ new TGCheckButton(fProcBG,"PFIS Photofission" ,kPFIS));
+ new TGCheckButton(fProcBG,"DRAY Delta electrons" ,kDRAY));
+ new TGCheckButton(fProcBG,"ANNI Annihilation" ,kANNI)); fProcBG->SetButton(kANNI);
+ new TGCheckButton(fProcBG,"BREM Bremstraslung" ,kBREM)); fProcBG->SetButton(kBREM);
+ new TGCheckButton(fProcBG,"MUNU Muon-Nuclear" ,kMUNU)); fProcBG->SetButton(kMUNU);
+ new TGCheckButton(fProcBG,"CKOV Cerenkovs" ,kCKOV)); fProcBG->SetButton(kCKOV);
+ new TGCheckButton(fProcBG,"HADR Hadronic interactions " ,kHADR)); fProcBG->SetButton(kHADR);
+ new TGCheckButton(fProcBG,"LOSS Energy losses" ,kLOSS)); fProcBG->SetButton(kLOSS);
+ new TGCheckButton(fProcBG,"MULS Multiple scattering" ,kMULS)); fProcBG->SetButton(kMULS);
+ new TGCheckButton(fProcBG,"RAYL Rayleigh scattering" ,kRAYL)); fProcBG->SetButton(kRAYL);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::PhysAddSlot(Int_t id)
+{//slot is invoked when any of physics check button is pressed
+ if(id==kALL) //if the pressed check button is kALL then switch on all the buttons
+ for(int i=1;i<=fProcBG->GetCount();i++)
+ fProcBG->SetButton(i,kButtonDown);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::PhysRemSlot(Int_t id)
+{//slot is invoked when any of physics check button is released
+ if(id==kALL) //if the released check button is kALL then switch off all the buttons
+ for(int i=1;i<=fProcBG->GetCount();i++)
+ fProcBG->SetButton(i,kButtonUp);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WritePhys(FILE *pF)
+{
+ if(fProcBG->GetButton(kDCAY)->GetState()) fprintf(pF," gMC->SetProcess(\"DCAY\",1); ");else fprintf(pF," gMC->SetProcess(\"DCAY\",0); ");
+ if(fProcBG->GetButton(kPAIR)->GetState()) fprintf(pF," gMC->SetProcess(\"PAIR\",1); ");else fprintf(pF," gMC->SetProcess(\"PAIR\",0); ");
+ if(fProcBG->GetButton(kCOMP)->GetState()) fprintf(pF," gMC->SetProcess(\"COMP\",1);\n");else fprintf(pF," gMC->SetProcess(\"COMP\",0);\n");
+ if(fProcBG->GetButton(kPHOT)->GetState()) fprintf(pF," gMC->SetProcess(\"PHOT\",1); ");else fprintf(pF," gMC->SetProcess(\"PHOT\",0); ");
+ if(fProcBG->GetButton(kPFIS)->GetState()) fprintf(pF," gMC->SetProcess(\"PFIS\",1); ");else fprintf(pF," gMC->SetProcess(\"PFIS\",0); ");
+ if(fProcBG->GetButton(kDRAY)->GetState()) fprintf(pF," gMC->SetProcess(\"DRAY\",1);\n");else fprintf(pF," gMC->SetProcess(\"DRAY\",0);\n");
+ if(fProcBG->GetButton(kANNI)->GetState()) fprintf(pF," gMC->SetProcess(\"ANNI\",1); ");else fprintf(pF," gMC->SetProcess(\"ANNI\",0); ");
+ if(fProcBG->GetButton(kBREM)->GetState()) fprintf(pF," gMC->SetProcess(\"BREM\",1); ");else fprintf(pF," gMC->SetProcess(\"BREM\",0); ");
+ if(fProcBG->GetButton(kMUNU)->GetState()) fprintf(pF," gMC->SetProcess(\"MUNU\",1);\n");else fprintf(pF," gMC->SetProcess(\"MUNU\",0);\n");
+ if(fProcBG->GetButton(kCKOV)->GetState()) fprintf(pF," gMC->SetProcess(\"CKOV\",1); ");else fprintf(pF," gMC->SetProcess(\"CKOV\",0); ");
+ if(fProcBG->GetButton(kHADR)->GetState()) fprintf(pF," gMC->SetProcess(\"HADR\",1); ");else fprintf(pF," gMC->SetProcess(\"HADR\",0); ");
+ if(fProcBG->GetButton(kLOSS)->GetState()) fprintf(pF," gMC->SetProcess(\"LOSS\",2);\n");else fprintf(pF," gMC->SetProcess(\"LOSS\",0);\n");
+ if(fProcBG->GetButton(kMULS)->GetState()) fprintf(pF," gMC->SetProcess(\"MULS\",1); ");else fprintf(pF," gMC->SetProcess(\"MULS\",0); ");
+ if(fProcBG->GetButton(kRAYL)->GetState()) fprintf(pF," gMC->SetProcess(\"RAYL\",1);\n");else fprintf(pF," gMC->SetProcess(\"RAYL\",0);\n");
+
+ fprintf(pF,"\n");
+ fprintf(pF," gMC->SetCut(\"CUTGAM\",0.001); "); fprintf(pF," gMC->SetCut(\"CUTELE\",0.001); "); fprintf(pF," gMC->SetCut(\"CUTNEU\",0.001);\n");
+ fprintf(pF," gMC->SetCut(\"CUTHAD\",0.001); "); fprintf(pF," gMC->SetCut(\"CUTMUO\",0.001); "); fprintf(pF," gMC->SetCut(\"BCUTE\" ,0.001);\n");
+ fprintf(pF," gMC->SetCut(\"BCUTM\" ,0.001); "); fprintf(pF," gMC->SetCut(\"DCUTE\" ,0.001); "); fprintf(pF," gMC->SetCut(\"DCUTM\" ,0.001);\n");
+ fprintf(pF," gMC->SetCut(\"PPCUTM\",0.001); "); fprintf(pF," gMC->SetCut(\"TOFMAX\",1e10);\n\n");
+}//WritePhys()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GuiGen(TGCompositeFrame *pMainF)
+{//generator configurator implemented as group of radio buttons
+ pMainF->AddFrame(fGenF=new TGVerticalFrame(pMainF));//add generator vertical frame to horizontal main frame
+ fGenF->AddFrame(fGenBG=new TGButtonGroup(fGenF,"Gene"));//add type button group to vertical generator frame
+ fGenBG->Connect("Pressed(Int_t)","RichConfig",this,"GenAddSlot(Int_t)"); fGenBG->Connect("Released(Int_t)","RichConfig",this,"GenRemSlot(Int_t)");
+ new TGCheckButton(fGenBG,"gun along z" ,kGunZ);
+ new TGCheckButton(fGenBG,"gun to 1 chamber" ,kGun1);
+ new TGCheckButton(fGenBG,"gun to 7 chambers" ,kGun7);
+ new TGCheckButton(fGenBG,"box HMPID phase space" ,kBox );
+ new TGCheckButton(fGenBG,"HIJING" ,kHijing);
+ new TGCheckButton(fGenBG,"HIJING para" ,kHijingPara);
+ new TGCheckButton(fGenBG,"Pythia" ,kPythia);
+ new TGCheckButton(fGenBG,"HMPID lib" ,kRichLib);
+//N prims for box and Hijing para
+ fGenF->AddFrame(fGenNprimCO=new TGComboBox(fGenF,100)); //add N prims combo to generator vertical frame
+ fGenNprimCO->AddEntry("not used" ,kNotUsed);
+ fGenNprimCO->AddEntry("N prim=1" ,1);
+ fGenNprimCO->AddEntry("N prim=2" ,2);
+ fGenNprimCO->AddEntry("N prim=5" ,5);
+ fGenNprimCO->AddEntry("N prim=100" ,100);
+ fGenNprimCO->AddEntry("N prim=500" ,500);
+ fGenNprimCO->AddEntry("N prim=1000" ,1000);
+ fGenNprimCO->AddEntry("N prim=10000",10000);
+ fGenNprimCO->AddEntry("N prim=80000",80000); fGenNprimCO->Resize(160,20); fGenNprimCO->Select(kNotUsed);
+//PID
+ fGenF->AddFrame(fGenPidCO=new TGComboBox(fGenF,100)); //add pid combo to generator vertical frame
+ fGenPidCO->AddEntry("not used" ,kNotUsed);
+ fGenPidCO->AddEntry("electron" ,kElectron);
+ fGenPidCO->AddEntry("positron" ,kPositron);
+ fGenPidCO->AddEntry("pion +" ,kPiPlus);
+ fGenPidCO->AddEntry("pion -" ,kPiMinus);
+ fGenPidCO->AddEntry("kaon +" ,kKPlus);
+ fGenPidCO->AddEntry("kaon -" ,kKMinus);
+ fGenPidCO->AddEntry("kaon 0" ,kK0Short);
+ fGenPidCO->AddEntry("proton" ,kProton);
+ fGenPidCO->AddEntry("antiproton" ,kProtonBar);
+ fGenPidCO->AddEntry("lambda" ,kLambda0);
+ fGenPidCO->AddEntry("antilambda" ,kLambda0Bar); fGenPidCO->Resize(160,20); fGenPidCO->Select(kNotUsed);
+//Pmin
+ fGenF->AddFrame(fGenPminCO=new TGComboBox(fGenF,100)); //add Pmin combo to generator vertical frame
+ fGenPminCO->AddEntry("not used",kNotUsed);
+ for(Int_t i=5;i<=295;i+=5) fGenPminCO->AddEntry(Form("Pmin=%3.1f GeV",0.1*i), i); fGenPminCO->Resize(160,20); fGenPminCO->Select(kNotUsed);
+//Pmax
+ fGenF->AddFrame(fGenPmaxCO=new TGComboBox(fGenF,100)); //add Pmax combo to generator vertical frame
+ fGenPmaxCO->AddEntry("not used",kNotUsed);
+ for(Int_t i=10;i<=295;i+=5) fGenPmaxCO->AddEntry(Form("Pmax=%3.1f GeV",0.1*i), i); fGenPmaxCO->Resize(160,20); fGenPmaxCO->Select(kNotUsed);
+//Chamber number
+ fGenF->AddFrame(fGenChamCO=new TGComboBox(fGenF,100)); //add chamber number combo to generator vertical frame
+ fGenChamCO->AddEntry("not used",kNotUsed);
+ for(int i=1;i<=7;i++) fGenChamCO->AddEntry(Form("Chamber %i",i),i); fGenChamCO->Resize(160,20); fGenChamCO->Select(kNotUsed);
+}//GuiGen()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GenAddSlot(Int_t id)
+{//is invoked when any of generator check button is pressed
+ if(id==kGunZ){
+ fGenBG->GetButton(kGun1)->SetEnabled(kFALSE); fGenF->HideFrame(fGenNprimCO); fGenF->HideFrame(fGenPmaxCO);
+ fGenBG->GetButton(kGun7)->SetEnabled(kFALSE);
+ fGenBG->GetButton(kBox )->SetEnabled(kFALSE); fGenPidCO->Select(kProton); fGenPminCO->Select(25);
+ }
+ if(id==kGun1){
+ fGenBG->GetButton(kGunZ)->SetEnabled(kFALSE); fGenF->HideFrame(fGenNprimCO); fGenF->HideFrame(fGenPmaxCO);
+ fGenBG->GetButton(kGun7)->SetEnabled(kFALSE); fGenPidCO->Select(kProton); fGenPminCO->Select(25); fGenChamCO->Select(4);
+ fGenBG->GetButton(kBox )->SetEnabled(kFALSE);
+ }
+ if(id==kGun7){
+ fGenBG->GetButton(kGunZ)->SetEnabled(kFALSE); fGenF->HideFrame(fGenNprimCO);
+ fGenBG->GetButton(kGun1)->SetEnabled(kFALSE); fGenPidCO->Select(kProton);
+ fGenBG->GetButton(kBox )->SetEnabled(kFALSE); fGenF->HideFrame(fGenPmaxCO); fGenPminCO->Select(25);
+ fGenF->HideFrame(fGenChamCO);
+ }
+ if(id==kBox){
+ fGenBG->GetButton(kGunZ)->SetEnabled(kFALSE); fGenNprimCO->Select(500);
+ fGenBG->GetButton(kGun1)->SetEnabled(kFALSE); fGenPidCO ->Select(kProton);
+ fGenBG->GetButton(kGun7)->SetEnabled(kFALSE); fGenPminCO ->Select(15); fGenPmaxCO->Select(15);
+ }
+ if(id==kHijing){
+ fGenBG->GetButton(kHijing)->ChangeBackground(0xff0000);
+ fGenBG->GetButton(kHijingPara)->SetEnabled(kFALSE);
+ fGenBG->GetButton(kPythia)->SetEnabled(kFALSE);
+ }
+ if(id==kHijingPara){
+ fGenBG->GetButton(kHijing)->SetEnabled(kFALSE); fGenNprimCO->Select(500);
+ fGenBG->GetButton(kPythia)->SetEnabled(kFALSE);
+ }
+ if(id==kPythia){
+ fGenBG->GetButton(kHijing)->SetEnabled(kFALSE);
+ fGenBG->GetButton(kHijingPara)->SetEnabled(kFALSE);
+ }
+}//GenAddSlot()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GenRemSlot(Int_t id)
+{//is invoked when any of generator check button is released
+ if(id==kGunZ){
+ fGenBG->GetButton(kGun1)->SetEnabled(); fGenF->ShowFrame(fGenNprimCO);
+ fGenBG->GetButton(kGun7)->SetEnabled(); fGenPidCO ->Select(kNotUsed);
+ fGenBG->GetButton(kBox )->SetEnabled(); fGenF->ShowFrame(fGenPmaxCO); fGenPminCO ->Select(kNotUsed);
+ }
+ if(id==kGun1){
+ fGenBG->GetButton(kGunZ)->SetEnabled(); fGenF->ShowFrame(fGenNprimCO);
+ fGenBG->GetButton(kGun7)->SetEnabled(); fGenPidCO ->Select(kNotUsed);
+ fGenBG->GetButton(kBox )->SetEnabled(); fGenF->ShowFrame(fGenPmaxCO); fGenPminCO ->Select(kNotUsed);
+ }
+ if(id==kGun7){
+ fGenBG->GetButton(kGunZ)->SetEnabled(); fGenF->ShowFrame(fGenNprimCO);
+ fGenBG->GetButton(kGun1)->SetEnabled(); fGenPidCO ->Select(kNotUsed);
+ fGenBG->GetButton(kBox )->SetEnabled(); fGenF->ShowFrame(fGenPmaxCO); fGenPminCO ->Select(kNotUsed);
+ fGenF->ShowFrame(fGenChamCO);
+ }
+ if(id==kBox){
+ fGenBG->GetButton(kGunZ)->SetEnabled(); fGenNprimCO->Select(kNotUsed);
+ fGenBG->GetButton(kGun1)->SetEnabled(); fGenPidCO ->Select(kNotUsed);
+ fGenBG->GetButton(kGun7)->SetEnabled(); fGenPminCO ->Select(kNotUsed); fGenPmaxCO->Select(kNotUsed);
+ fGenChamCO ->Select(kNotUsed);
+ }
+ if(id==kHijing){
+ fGenBG->GetButton(kHijing)->ChangeBackground(0xbebebe);
+ fGenBG->GetButton(kHijingPara)->SetEnabled();
+ fGenBG->GetButton(kPythia)->SetEnabled();
+ }
+ if(id==kHijingPara){
+ fGenBG->GetButton(kHijing)->SetEnabled();
+ fGenBG->GetButton(kPythia)->SetEnabled();
+ }
+ if(id==kPythia){
+ fGenBG->GetButton(kHijing)->SetEnabled();
+ fGenBG->GetButton(kHijingPara)->SetEnabled();
+ }
+}//GenRemSlot()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WriteGen(FILE *pF)
+{
+ Int_t pid=fGenPidCO->GetSelected();
+ Float_t pmin=0.1*fGenPminCO->GetSelected(); //particle momentum, GeV
+ Float_t pmax=0.1*fGenPmaxCO->GetSelected(); //particle momentum, GeV
+
+ fprintf(pF," AliGenCocktail *pG=new AliGenCocktail();\n\n");
+
+ if(fGenBG->GetButton(kGunZ)->GetState()==kButtonDown)//1 particle along Z axis
+ fprintf(pF," AliGenFixed *pGz=new AliGenFixed(1); pGz->SetPart(%i); pGz->SetMomentum(%.1f); pGz->SetOrigin(0,0,-200); pG->AddGenerator(pGz,\"Gz\",1);\n",pid,p);
+
+ if(fGenBG->GetButton(kGun1)->GetState()==kButtonDown){//1 gun towards 1 HMPID chamber
+ switch(fGenChamCO->GetSelected()){
+ case 1: fprintf(pF," AliGenFixed *pG1=new AliGenFixed(1); pG1->SetPart(%i); pG1->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG1->SetTheta(109.5); pG1->SetPhi(10); pG->AddGenerator(pG1,\"g1\",1);\n"); break;
+ case 2: fprintf(pF," AliGenFixed *pG2=new AliGenFixed(1); pG2->SetPart(%i); pG2->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG2->SetTheta( 90.0); pG2->SetPhi(10); pG->AddGenerator(pG2,\"g2\",1);\n"); break;
+ case 3: fprintf(pF," AliGenFixed *pG3=new AliGenFixed(1); pG3->SetPart(%i); pG3->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG3->SetTheta(109.5); pG3->SetPhi(30); pG->AddGenerator(pG3,\"g3\",1);\n"); break;
+ case 4: fprintf(pF," AliGenFixed *pG4=new AliGenFixed(1); pG4->SetPart(%i); pG4->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG4->SetTheta( 90.0); pG4->SetPhi(30); pG->AddGenerator(pG4,\"g4\",1);\n"); break;
+ case 5: fprintf(pF," AliGenFixed *pG5=new AliGenFixed(1); pG5->SetPart(%i); pG5->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG5->SetTheta( 70.5); pG5->SetPhi(30); pG->AddGenerator(pG5,\"g5\",1);\n"); break;
+ case 6: fprintf(pF," AliGenFixed *pG6=new AliGenFixed(1); pG6->SetPart(%i); pG6->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG6->SetTheta( 90.0); pG6->SetPhi(50); pG->AddGenerator(pG6,\"g6\",1);\n"); break;
+ case 7: fprintf(pF," AliGenFixed *pG7=new AliGenFixed(1); pG7->SetPart(%i); pG7->SetMomentum(%.1f);\n",pid,pmin);
+ fprintf(pF," pG7->SetTheta( 70.5); pG7->SetPhi(50); pG->AddGenerator(pG7,\"g7\",1);\n"); break;
+ }
+ }
+
+ if(fGenBG->GetButton(kGun7)->GetState()==kButtonDown){//7 guns towards 7 HMPID chambers
+ fprintf(pF," AliGenFixed *pG1=new AliGenFixed(1); pG1->SetPart(%i); pG1->SetMomentum(%.1f);pG1->SetTheta(109.5-3); pG1->SetPhi(10);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG1,\"g1\",1);\n");
+ fprintf(pF," AliGenFixed *pG2=new AliGenFixed(1); pG2->SetPart(%i); pG2->SetMomentum(%.1f);pG2->SetTheta( 90.0-3); pG2->SetPhi(10);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG2,\"g2\",1);\n");
+ fprintf(pF," AliGenFixed *pG3=new AliGenFixed(1); pG3->SetPart(%i); pG3->SetMomentum(%.1f);pG3->SetTheta(109.5-3); pG3->SetPhi(30);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG3,\"g3\",1);\n");
+ fprintf(pF," AliGenFixed *pG4=new AliGenFixed(1); pG4->SetPart(%i); pG4->SetMomentum(%.1f);pG4->SetTheta( 90.0-3); pG4->SetPhi(30);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG4,\"g4\",1);\n");
+ fprintf(pF," AliGenFixed *pG5=new AliGenFixed(1); pG5->SetPart(%i); pG5->SetMomentum(%.1f);pG5->SetTheta( 70.0-3); pG5->SetPhi(30);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG5,\"g5\",1);\n");
+ fprintf(pF," AliGenFixed *pG6=new AliGenFixed(1); pG6->SetPart(%i); pG6->SetMomentum(%.1f);pG6->SetTheta( 90.0-3); pG6->SetPhi(50);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG6,\"g6\",1);\n");
+ fprintf(pF," AliGenFixed *pG7=new AliGenFixed(1); pG7->SetPart(%i); pG7->SetMomentum(%.1f);pG7->SetTheta( 70.0-3); pG7->SetPhi(50);\n",pid,pmin);
+ fprintf(pF," pG->AddGenerator(pG7,\"g7\",1);\n");
+ }
+
+ if(fGenBG->GetButton(kBox)->GetState()==kButtonDown){// box towards HMPID phase space
+ fprintf(pF," AliGenBox *pB=new AliGenBox(%i); pB->SetPart(%i); pB->SetMomentumRange(%.1f,%.1f);\n",(int)fGenNprimCO->GetSelected(),pid,pmin,pmax);
+ fprintf(pF," pB->SetThetaRange(65,115); pB->SetPhiRange(5,55); pG->AddGenerator(pB,\"b\",1);\n");
+ }
+
+ if(fGenBG->GetButton(kHijing)->GetState()==kButtonDown){//normal HIJING
+ fprintf(pF," AliGenHijing *pH=new AliGenHijing(-1); pH->SetEnergyCMS(5500); pH->SetReferenceFrame(\"CMS\");\n");
+ fprintf(pF," pH->SetProjectile(\"A\", 208, 82); pH->SetTarget(\"A\", 208, 82); pH->SetJetQuenching(0);\n");
+ fprintf(pF," pH->SetShadowing(0); pH->KeepFullEvent(); pH->SetSelectAll(0);\n");
+ fprintf(pF," pH->SetImpactParameterRange(0, 5); //fermi\n");
+ fprintf(pF," pG->AddGenerator(pH,\"h\",1);\n\n");
+ }
+
+ if(fGenBG->GetButton(kHijingPara)->GetState()==kButtonDown){//parametrized HIJING
+ fprintf(pF," AliGenHIJINGpara *pHP=new AliGenHIJINGpara(%i);\n",(int)fGenNprimCO->GetSelected());
+ fprintf(pF," pHP->SetMomentumRange(0,999); pHP->SetThetaRange(%f,%f); pHP->SetPhiRange(0,360);\n",Eta2Theta(8),Eta2Theta(-8));
+ fprintf(pF," pG->AddGenerator(pHP,\"hp\",1);\n\n");
+ }
+
+ if(fGenBG->GetButton(kPythia)->GetState()==kButtonDown){//Pythia
+ fprintf(pF," AliGenPythia *pP=new AliGenPythia(-1);\n");
+ fprintf(pF," pP->SetMomentumRange(0,999); pP->SetPhiRange(20,80); pP->SetThetaRange(75,115);\n");
+ fprintf(pF," pP->SetYRange(-12,12); pP->SetPtRange(0,1000); pP->SetStrucFunc(kCTEQ4L);\n");
+ fprintf(pF," pP->SetProcess(kPyMb); pP->SetEnergyCMS(14000);\n");
+ fprintf(pF," pG->AddGenerator(pP,\"p\",1);\n\n");
+ }
+ fprintf(pF," pG->Init();\n\n");
+}//WriteGenerator()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GuiDet(TGHorizontalFrame *pMainHF)
+{
+ pMainHF->AddFrame(fDetBG=new TGButtonGroup(pMainHF,"Dets"));
+ fDetBG->Connect("Pressed(Int_t)" ,"RichConfig",this,"DetAddSlot(Int_t)");
+ fDetBG->Connect("Released(Int_t)","RichConfig",this,"DetRemSlot(Int_t)");
+ new TGCheckButton(fDetBG,"PIPE" ,kPIPE)); new TGCheckButton(fDetBG,"ITS" ,kITS)); new TGCheckButton(fDetBG,"TPC" ,kTPC));
+ new TGCheckButton(fDetBG,"TRD" ,kTRD)); new TGCheckButton(fDetBG,"TOF" ,kTOF)); new TGCheckButton(fDetBG,"FRAME" ,kFRAME));
+ new TGCheckButton(fDetBG,"MAG" ,kMAG)); new TGCheckButton(fDetBG,"CRT" ,kCRT)); new TGCheckButton(fDetBG,"HALL" ,kHALL));
+ new TGCheckButton(fDetBG,"PHOS" ,kPHOS)); new TGCheckButton(fDetBG,"START" ,kSTART)); new TGCheckButton(fDetBG,"FMD" ,kFMD));
+ new TGCheckButton(fDetBG,"ABSO" ,kABSO)); new TGCheckButton(fDetBG,"PMD" ,kPMD)); new TGCheckButton(fDetBG,"DIPO" ,kDIPO));
+ new TGCheckButton(fDetBG,"EMCAL" ,kEMCAL)); new TGCheckButton(fDetBG,"VZERO" ,kVZERO)); new TGCheckButton(fDetBG,"MUON" ,kMUON));
+ new TGCheckButton(fDetBG,"ZDC" ,kZDC)); new TGCheckButton(fDetBG,"SHILD" ,kSHILD));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::DetAddSlot(Int_t id)
+{//slot is invoked when any detector check button is pressed
+ if(id==kTRD || id==kTOF) //TRD and TOF geometries depend on FRAME
+ fDetBG->SetButton(kFRAME);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::DetRemSlot(Int_t id)
+{//slot is invoked when any detector check button is released
+ if(id==kFRAME){
+ fDetBG->SetButton(kTRD,kFALSE); //switch off TRD and TOF when FRAME is switched off by user hence TRD&TOF depend on FRAME
+ fDetBG->SetButton(kTOF,kFALSE);
+ }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WriteDet(FILE *pF)
+{
+//CORE detectors
+ if(fDetBG->GetButton(kPIPE )->GetState()) fprintf(pF,"\n new AliPIPEv0(\"PIPE\",\"Beam Pipe\");\n");
+ if(fDetBG->GetButton(kSHILD)->GetState()) fprintf(pF,"\n new AliSHILv2(\"SHIL\",\"Shielding Version 2\");\n");
+ if(fDetBG->GetButton(kITS )->GetState()){
+ fprintf(pF,"\n AliITSvPPRasymmFMD *pIts =new AliITSvPPRasymmFMD(\"ITS\",\"ITS PPR detailed version\");\n");
+ fprintf(pF," pIts->SetMinorVersion(2); pIts->SetReadDet(kFALSE);\n");
+ fprintf(pF," pIts->SetThicknessDet1(200.); pIts->SetThicknessDet2(200.);\n");
+ fprintf(pF," pIts->SetThicknessChip1(150.); pIts->SetThicknessChip2(150.);\n");
+ fprintf(pF," pIts->SetRails(0); pIts->SetCoolingFluid(1);\n");
+ fprintf(pF," pIts->SetEUCLID(0);\n");
+ }
+ if(fDetBG->GetButton(kTPC )->GetState()) fprintf(pF,"\n new AliTPCv2(\"TPC\",\"Default\");\n");
+ if(fDetBG->GetButton(kFRAME)->GetState()) fprintf(pF,"\n AliFRAMEv2 *pFrame=new AliFRAMEv2(\"FRAME\",\"Space Frame\"); pFrame->SetHoles(1);\n");
+ if(fDetBG->GetButton(kTRD )->GetState()) fprintf(pF,"\n AliTRD *pTrd=new AliTRDv1(\"TRD\",\"TRD slow simulator\");\n");
+ if(fDetBG->GetButton(kTOF )->GetState()) fprintf(pF,"\n new AliTOFv4T0(\"TOF\", \"normal TOF\");\n");
+//central detectors behind HMPID
+ if(fDetBG->GetButton(kMAG )->GetState()) fprintf(pF,"\n new AliMAG(\"MAG\",\"Magnet\");\n");
+ if(fDetBG->GetButton(kHALL )->GetState()) fprintf(pF,"\n new AliHALL(\"HALL\",\"Alice Hall\");\n");
+//forward detectors
+ if(fDetBG->GetButton(kFMD )->GetState()) fprintf(pF,"\n new AliFMDv1(\"FMD\",\"normal FMD\");\n");
+ if(fDetBG->GetButton(kABSO )->GetState()) fprintf(pF,"\n new AliABSOv0(\"ABSO\",\"Muon absorber\");\n");
+ if(fDetBG->GetButton(kDIPO )->GetState()) fprintf(pF,"\n new AliDIPOv2(\"DIPO\",\"Dipole version 2\");\n");
+ if(fDetBG->GetButton(kMUON )->GetState()) fprintf(pF,"\n new AliMUONv1(\"MUON\",\"default\");\n");
+ if(fDetBG->GetButton(kPMD )->GetState()) fprintf(pF,"\n new AliPMDv1(\"PMD\",\"normal PMD\");\n");
+ if(fDetBG->GetButton(kSTART)->GetState()) fprintf(pF,"\n new AliSTARTv1(\"START\",\"START Detector\");\n");
+ if(fDetBG->GetButton(kVZERO)->GetState()) fprintf(pF,"\n new AliVZEROv2(\"VZERO\",\"normal VZERO\");\n");
+ if(fDetBG->GetButton(kZDC )->GetState()) fprintf(pF,"\n new AliZDCv2(\"ZDC\",\"normal ZDC\");\n");
+//different phase space detectors
+ if(fDetBG->GetButton(kPHOS )->GetState()) fprintf(pF,"\n new AliPHOSv1(\"PHOS\",\"IHEP\");\n");
+ if(fDetBG->GetButton(kEMCAL)->GetState()) fprintf(pF,"\n new AliEMCALv1(\"EMCAL\",\"G56_2_55_19_104_14\");\n");
+ if(fDetBG->GetButton(kCRT )->GetState()) fprintf(pF,"\n new AliCRTv0(\"CRT\",\"normal ACORDE\");\n");
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::GuiBatch(TGHorizontalFrame *pMainF)
+{
+ TGGroupFrame *pSimF=new TGGroupFrame(pMainF,"Simu"); pMainF->AddFrame(pSimF);
+ pSimF->AddFrame(fSimBG=new TGButtonGroup(pSimF,"" ));
+ new TGCheckButton(fSimBG, "Primary" ,kPrim )); fSimBG->SetButton(kPrim);
+ new TGCheckButton(fSimBG, "Transport" ,kTransport)); fSimBG->SetButton(kTransport);
+ pSimF->AddFrame (fSDigBG=new TGButtonGroup(pSimF,"" ));
+ new TGRadioButton(fSDigBG, "No SDigits" ,kNo ));
+ new TGRadioButton(fSDigBG, "SDigits CORE" ,kAll ));
+ new TGRadioButton(fSDigBG, "SDigits HMPID" ,kOnly )); fSDigBG->SetButton(kOnly);
+ pSimF->AddFrame (fDigBG=new TGButtonGroup(pSimF,"" ));
+ new TGRadioButton(fDigBG, "No Digits" ,kNo ));
+ new TGRadioButton(fDigBG, "Digits CORE" ,kAll ));
+ new TGRadioButton(fDigBG, "Digits HMPID" ,kOnly )); fDigBG->SetButton(kOnly);
+ pSimF->AddFrame(fRawBG=new TGButtonGroup(pSimF,"" ));
+ new TGRadioButton(fRawBG, "No RAW files" ,kNo )); fRawBG->SetButton(kNo);
+ new TGRadioButton(fRawBG, "RAW DDL" ,kRawDdl ));
+ new TGRadioButton(fRawBG, "RAW DATE" ,kRawDate ));
+ new TGRadioButton(fRawBG, "RAW ROOT" ,kRawRoot ));
+
+ TGCompositeFrame *pRecF=new TGGroupFrame(pMainF,"Reco"); pMainF->AddFrame(pRecF);
+ pRecF->AddFrame(fClusBG=new TGButtonGroup(pRecF,"" ));
+ new TGRadioButton(fClusBG, "No Clusters" ,kNo ));
+ new TGRadioButton(fClusBG, "Clusters CORE" ,kAll ));
+ new TGRadioButton(fClusBG, "Clusters HMPID" ,kOnly )); fClusBG->SetButton(kOnly);
+
+ pRecF->AddFrame(fRecoBG=new TGButtonGroup(pRecF,"" )); fRecoBG->Connect("Pressed(Int_t)","RichConfig",this,"SlotBatch(Int_t)");
+ new TGCheckButton(fRecoBG, "Load Align data" ,kAlign ));
+ new TGCheckButton(fRecoBG, "Find ESD tracks" ,kTrack ));
+ new TGCheckButton(fRecoBG, "Find vertex" ,kVertex ));
+ new TGCheckButton(fRecoBG, "Fill ESD" ,kEsd ));
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::SlotBatch(Int_t id)
+{//slot is invoked when any button in fRecoBG is pressed
+ if(id==kTrack){
+ fSDigBG->SetButton(kAll);
+ fDigBG->SetButton(kAll);
+ fClusBG->SetButton(kAll);
+ fDetBG->SetButton(kITS);
+ fDetBG->SetButton(kTPC);
+ fDetBG->SetButton(kTRD);
+ }
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WriteBatch()
+{//creates Batch.C file
+ char *sBatchName="RichBatch";
+ FILE *fp=fopen(Form("%s.C",sBatchName),"w"); if(!fp){Info("CreateBatch","Cannot open output file: %s.C",sBatchName);return;}
+
+ fprintf(fp,"void %s(const Int_t iNevents,const Bool_t isDebug,const char *sConfigFileName)\n{\n",sBatchName);
+
+ if(fSimBG->GetButton(kPrim)->GetState()) fprintf(fp," gSystem->Exec(\"rm -rf *.root hlt hough fort* raw* ZZZ*\");\n");
+ else fprintf(fp," gSystem->Exec(\"rm -rf hlt hough raw* ZZZ*\");\n");
+
+ fprintf(fp," if(isDebug) AliLog::SetGlobalDebugLevel(AliLog::kDebug);\n");
+ fprintf(fp," gBenchmark->Start(\"ALICE\");\n TDatime time;\n\n");
+//simulation section
+ if(fSimBG->GetButton(kPrim)->GetState()){
+ fprintf(fp," AliSimulation *pSim=new AliSimulation(sConfigFileName);\n");
+
+ if(fSimBG->GetButton(kPrim)->GetState()) fprintf(fp," pSim->SetRunGeneration(kTRUE); //initial kinematics generated\n");
+ else fprintf(fp," pSim->SetRunGeneration(kFALSE); //no initial kinematics generated\n");
+//transport and hit creations
+ if(fSimBG->GetButton(kTransport)->GetState())
+ fprintf(fp," pSim->SetRunSimulation(kTRUE); //transport and hits creation\n");
+ else
+ fprintf(fp," pSim->SetRunSimulation(kFALSE); //no transport and hits creation\n");
+//sdigits
+ if (fSDigBG->GetButton(kNo) ->GetState()) fprintf(fp," pSim->SetMakeSDigits(\"\"); //no sdigits created\n");
+ else if(fSDigBG->GetButton(kAll) ->GetState()) fprintf(fp," pSim->SetMakeSDigits(\"ITS TPC TRD TOF HMPID\"); //sdigits created for these detectors\n");
+ else if(fSDigBG->GetButton(kOnly) ->GetState()) fprintf(fp," pSim->SetMakeSDigits(\"HMPID\"); //sdigits created for HMPID only\n");
+//digits
+ if (fDigBG->GetButton(kNo) ->GetState()) fprintf(fp," pSim->SetMakeDigits(\"\"); //no digits created\n");
+ else if(fDigBG->GetButton(kAll) ->GetState()) fprintf(fp," pSim->SetMakeDigits(\"ITS TPC TRD TOF HMPID\"); //digits created for these detectors\n");
+ else if(fDigBG->GetButton(kOnly) ->GetState()) fprintf(fp," pSim->SetMakeDigits(\"HMPID\"); //digits created for HMPID only\n");
+//raw data generation
+ if (fRawBG->GetButton(kRawDdl)->GetState()) fprintf(fp," pSim->SetWriteRawData(\"ITS TPC TRD TOF HMPID\");//raw data in DDL format for these detectors\n");
+ else if(fRawBG->GetButton(kRawDate)->GetState()) fprintf(fp," pSim->SetWriteRawData(\"ITS TPC TRD TOF HMPID\",\".date\");//raw data in DATE format for these detectors\n");
+ else if(fRawBG->GetButton(kRawRoot)->GetState()) fprintf(fp," pSim->SetWriteRawData(\"ITS TPC TRD TOF HMPID\",\".root\");//raw data in ROOT format for these detectors\n");
+
+ fprintf(fp," pSim->Run(iNevents);\n delete pSim;\n\n");
+ }
+
+
+//reconstraction section - cluster finder
+ fprintf(fp," AliReconstruction *pRec=new AliReconstruction;\n");
+ if(fRecoBG->GetButton(kAlign)->GetState()) fprintf(fp," pRec->SetLoadAlignData(\"ITS TPC TRD TOF HMPID\"); //Misalign data for these detectors\n");
+ else fprintf(fp," pRec->SetLoadAlignData(\"\"); //Misalign data not loaded\n");
+
+ if (fClusBG->GetButton(kAll) ->GetState()) fprintf(fp," pRec->SetRunLocalReconstruction(\"ITS TPC TRD TOF HMPID\"); //clusters created for these detectors\n");
+ else if(fClusBG->GetButton(kOnly) ->GetState()) fprintf(fp," pRec->SetRunLocalReconstruction(\"HMPID\"); //clusters created for HMPID only\n");
+ else if(fClusBG->GetButton(kNo) ->GetState()) fprintf(fp," pRec->SetRunLocalReconstruction(\"\"); //clusters are not created\n");
+//reconstraction section - vertex finder
+ if (fRecoBG->GetButton(kVertex)->GetState()) fprintf(fp," pRec->SetRunVertexFinder(kTRUE); //run vertex finder\n");
+ else fprintf(fp," pRec->SetRunVertexFinder(kFALSE); //do not run vertex finder\n");
+//reconstraction section - tracks finder
+ if (fRecoBG->GetButton(kTrack) ->GetState()) fprintf(fp," pRec->SetRunTracking(\"ITS TPC TRD TOF HMPID\"); //run tracking for these detectors\n");
+ else fprintf(fp," pRec->SetRunTracking(\"\"); //do not run tracking\n");
+//reconstraction section - fill ESD (prob vector creator)
+ if (fRecoBG->GetButton(kEsd) ->GetState()) fprintf(fp," pRec->SetFillESD(\"ITS TPC TRD TOF HMPID\"); //run fill ESD (prob vect)\n");
+ else fprintf(fp," pRec->SetFillESD(\"\"); //do not run fill ESD (prob vect)\n");
+ fprintf(fp," pRec->Run();delete pRec;\n\n");
+//benchmarks
+ fprintf(fp," cout<<\"!!!!!!!!!!!!Info in <my/Batch.C>: Start time: \";time.Print();\n");
+ fprintf(fp," cout<<\"!!!!!!!!!!!!Info in <my/Batch.C>: Stop time: \";time.Set(); time.Print();\n");
+ fprintf(fp," gBenchmark->Show(\"ALICE\");\n");
+
+ fprintf(fp," gSystem->Exec(\"play -c 2 ~/my/end.wav\");\n");
+ fprintf(fp," gSystem->Exec(\"touch ZZZ______finished_______ZZZ\");\n}\n");
+ fclose(fp);
+}//WriteBatch()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::ExitSlot()
+{
+//slot to be invoked by clik on the Create button
+ WriteConfig();
+ WriteBatch();
+ SendCloseMessage();
+ gApplication->Terminate(0);
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig::WriteConfig()
+{
+ FILE *pF=fopen(fFileName,"w"); if(!pF){Info("CreateConfigFile","Cannot open output file:%sn",fFileName);return;}
+
+ fprintf(pF,"void Config()\n");
+ fprintf(pF,"{\n");
+ fprintf(pF,"\n ::Info(\"\\n\\n\\n----------> HMPID private config\",\"Start\");\n");
+//Random
+ fprintf(pF," gRandom->SetSeed(123456);//put 0 to use system time\n\n");
+//Geant
+ fprintf(pF," gSystem->Load(\"libgeant321\");\n");
+ fprintf(pF," new TGeant3TGeo(\"C++ Interface to Geant3\");\n\n");
+//File
+ fprintf(pF," AliRunLoader *pAL=AliRunLoader::Open(\"galice.root\",AliConfig::GetDefaultEventFolderName(),\"recreate\");\n");
+ fprintf(pF," pAL->SetCompressionLevel(2);\n");
+ fprintf(pF," pAL->SetNumberOfEventsPerFile(1000);\n");
+ fprintf(pF," gAlice->SetRunLoader(pAL);\n\n");
+//Decayer
+ if(fDecayerB->GetState()==kButtonDown){
+ fprintf(pF," TVirtualMCDecayer *pDecayer=new AliDecayerPythia();\n");
+ fprintf(pF," pDecayer->SetForceDecay(kAll);\n");
+ fprintf(pF," pDecayer->Init();\n");
+ fprintf(pF," gMC->SetExternalDecayer(pDecayer);\n\n");
+ }
+ WritePhys(pF); //physics processes
+
+//Field
+ if(fMagBG->GetButton(kFld0)->GetState()) fprintf(pF," gAlice->SetField(0); //no field\n\n");
+ else if(fMagBG->GetButton(kFld2)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,1,10,0));//0.2 Tesla field\n\n");
+ else if(fMagBG->GetButton(kFld4)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,1,10,1));//0.4 Tesla field\n\n");
+ else if(fMagBG->GetButton(kFld5)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,1,10,2));//0.5 Tesla field\n\n");
+ else if(fMagBG->GetButton(kFld_2)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,-1,10,0));//-0.2 Tesla field\n\n");
+ else if(fMagBG->GetButton(kFld_4)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,-1,10,1));//-0.4 Tesla field\n\n");
+ else if(fMagBG->GetButton(kFld_5)->GetState()) fprintf(pF," gAlice->SetField(new AliMagFMaps(\"Maps\",\"Maps\",2,-1,10,2));//-0.5 Tesla field\n\n");
+
+ fprintf(pF," pAL->CdGAFile();\n\n"); //????
+//Generator
+ WriteGen(pF);//generator
+//BODY-ALIC
+ fprintf(pF," new AliBODY(\"BODY\",\"Alice envelop\");\n\n");
+//HMPID
+ WriteRich(pF); //private HMPID part
+ WriteDet(pF); //other detectors
+//end of Config.C file:
+ fprintf(pF,"\n ::Info(\"----------> HMPID private config\",\"Stop\\n\\n\\n\");\n");
+ fprintf(pF,"}\n");
+ fclose(pF);
+}//WriteConfig()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichConfig()
+{
+ new RichConfig("Config.C");
+}
--- /dev/null
+
+Int_t copy; //volume copy number
+Double_t dx,dy,dz,r1,r2;//tmp vars for volume dimentions
+Double_t cm=1,m=100*cm,mm=0.1*cm,mkm=0.001*cm;//length units
+TGeoManager *g=0;
+
+void RichGeom(Bool_t isOnlyChambers=kFALSE)
+{
+
+ g=new TGeoManager("HMPID","Private HMPID geometry");
+ Materials();
+ gGeoManager->MakeBox("ALIC",gGeoManager->GetMedium("Air"),dx=30*m/2,dy=30*m/2,dz=30*m/2); //arbitrary values
+ gGeoManager->SetTopVolume(gGeoManager->GetVolume("ALIC"));
+
+ Rich(isOnlyChambers);
+
+// RusGel();
+
+// Vhmpid();
+
+ gGeoManager->CloseGeometry();
+
+ gGeoManager->SetVisOption(0); gGeoManager->SetVisLevel(5);
+
+ gGeoManager->GetMasterVolume()->Draw();
+ Axis();
+// gPad->GetView()->SetView(3,94,-70,0);
+ new TBrowser;
+}
+//__________________________________________________________________________________________________
+void Materials()
+{
+//Media for HMPID
+ Double_t a=0,z=0,den=0,radlen=0,intlen=0;//tmp vars for material parameters
+ new TGeoMaterial("Air" ,a=26.98 ,z=13,den=0.4224 ); new TGeoMedium("Air" ,1,gGeoManager->GetMaterial("Air"));
+ new TGeoMaterial("HMPID_CH4" ,a=26.98 ,z=13,den=0.4224 ); new TGeoMedium("HMPID_CH4" ,2,gGeoManager->GetMaterial("HMPID_CH4"));
+ new TGeoMaterial("HMPID_CsI" ,a=26.98 ,z=13,den=2.7 ,radlen=24.01*cm,intlen=70.6*cm); new TGeoMedium("HMPID_CsI" ,3,gGeoManager->GetMaterial("HMPID_CsI"));
+ new TGeoMaterial("HMPID_Al" ,a=26.98 ,z=13,den=2.7 ,radlen=24.01*cm,intlen=70.6*cm); new TGeoMedium("HMPID_Al" ,4,gGeoManager->GetMaterial("HMPID_Al"));
+ new TGeoMaterial("HMPID_W" ,a=183.84,z=27,den=19.3,radlen= 9.59*cm,intlen=0.35*cm); new TGeoMedium("HMPID_W" ,5,gGeoManager->GetMaterial("HMPID_W"));
+ new TGeoMaterial("HMPID_Cu" ,a=55.845,z=26,den=7.87,radlen=13.84*cm,intlen=82.8*cm); new TGeoMedium("HMPID_Cu" ,6,gGeoManager->GetMaterial("HMPID_Cu"));
+ new TGeoMaterial("HMPID_Rohacell" ,a=12.01 ,z=6 ,den=0.1 ,radlen=18.8,intlen=0); new TGeoMedium("HMPID_Rohacell",7,gGeoManager->GetMaterial("HMPID_Rohacell"));
+ new TGeoMaterial("HMPID_SiO2" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_SiO2" ,8,gGeoManager->GetMaterial("HMPID_SiO2"));
+ new TGeoMaterial("HMPID_C6F14" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_C6F14" ,9,gGeoManager->GetMaterial("HMPID_C6F14"));
+//Media for Sr90 source
+ new TGeoMaterial("HMPID_Perpex" ,a=55.845,z=26,den=7.87,radlen=13.84*cm,intlen=82.8*cm); new TGeoMedium("HMPID_Perpex" ,10,gGeoManager->GetMaterial("HMPID_Perpex"));
+ new TGeoMaterial("HMPID_Steel" ,a=55.845,z=26,den=7.87,radlen=13.84*cm,intlen=82.8*cm); new TGeoMedium("HMPID_Steel" ,11,gGeoManager->GetMaterial("HMPID_Steel"));
+ new TGeoMaterial("HMPID_Mylar" ,a=55.845,z=26,den=7.87,radlen=13.84*cm,intlen=82.8*cm); new TGeoMedium("HMPID_Mylar" ,12,gGeoManager->GetMaterial("HMPID_Mylar"));
+ new TGeoMaterial("HMPID_Sr90" ,a=87.62 ,z=38,den=7.87,radlen=13.84*cm,intlen=82.8*cm); new TGeoMedium("HMPID_Sr90" ,13,gGeoManager->GetMaterial("HMPID_Sr90"));
+//Media for VHMPID Gas option
+ new TGeoMaterial("HMPID_CF4" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_CF4" ,14,gGeoManager->GetMaterial("HMPID_CF4"));
+ new TGeoMaterial("HMPID_C4F10" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_C4F10" ,15,gGeoManager->GetMaterial("HMPID_C4F10"));
+ new TGeoMaterial("HMPID_Ag" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Ag" ,16,gGeoManager->GetMaterial("HMPID_Ag"));
+//Media for VHMPID aerogel option
+ new TGeoMaterial("HMPID_Gel24" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Gel24" ,17,gGeoManager->GetMaterial("HMPID_Gel24"));
+ new TGeoMaterial("HMPID_Gel26" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Gel26" ,18,gGeoManager->GetMaterial("HMPID_Gel26"));
+ new TGeoMaterial("HMPID_Gel28" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Gel28" ,19,gGeoManager->GetMaterial("HMPID_Gel28"));
+ new TGeoMaterial("HMPID_Gel30" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Gel30" ,20,gGeoManager->GetMaterial("HMPID_Gel30"));
+ new TGeoMaterial("HMPID_Si" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Si" ,21,gGeoManager->GetMaterial("HMPID_Si"));
+ new TGeoMaterial("HMPID_Apd" ,a=0 ,z=0 ,den=0); new TGeoMedium("HMPID_Apd" ,22,gGeoManager->GetMaterial("HMPID_Apd"));
+}//Materials()
+//__________________________________________________________________________________________________
+void Rich(Bool_t isOnlyChambers)
+{
+//Rich chamber
+ TGeoVolume *pRich=gGeoManager->MakeBox("HMPID",gGeoManager->GetMedium("Air"),dx=(6*mm+1681*mm+6*mm)/2, //main HMPID volume
+ dy=(6*mm+1466*mm+6*mm)/2,
+ dz=(80*mm+40*mm)*2/2); //x,y taken from 2033P1 z from p84 TDR
+ const Double_t kAngHor=19.5; // horizontal angle between chambers 19.5 grad
+ const Double_t kAngVer=20; // vertical angle between chambers 20 grad
+ const Double_t kAngCom=30; // common HMPID rotation with respect to x axis 30 grad
+ const Double_t trans[3]={490,0,0}; //center of the chamber is on window-gap surface
+ for(Int_t iCh=1;iCh<=7;iCh++){//place 7 chambers
+ TGeoHMatrix *pMatrix=new TGeoHMatrix;
+ pMatrix->RotateY(90); //rotate around y since initial position is in XY plane -> now in YZ plane
+ pMatrix->SetTranslation(trans); //now plane in YZ is shifted along x
+ switch(iCh){
+ case 1: pMatrix->RotateY(kAngHor); pMatrix->RotateZ(-kAngVer); break; //right and down
+ case 2: pMatrix->RotateZ(-kAngVer); break; //down
+ case 3: pMatrix->RotateY(kAngHor); break; //right
+ case 4: break; //no rotation
+ case 5: pMatrix->RotateY(-kAngHor); break; //left
+ case 6: pMatrix->RotateZ(kAngVer); break; //up
+ case 7: pMatrix->RotateY(-kAngHor); pMatrix->RotateZ(kAngVer); break; //left and up
+ }
+ pMatrix->RotateZ(kAngCom); //apply common rotation in XY plane
+ gGeoManager->GetVolume("ALIC")->AddNode(pRich,iCh,pMatrix);
+ }
+ if(isOnlyChambers) return; //do not construct the detailed geometry
+//Pad Panel frame
+ TGeoVolume *pPpf =gGeoManager->MakeBox("Rppf" ,gGeoManager->GetMedium("HMPID_Al") ,dx=648*mm/2,dy= 411*mm/2 ,dz=40 *mm/2);//PPF 2001P2 inner size of the slab by 1mm more
+ TGeoVolume *pPpfLarge=gGeoManager->MakeBox("Rppf1" ,gGeoManager->GetMedium("Air") ,dx=181*mm/2,dy=89.25*mm/2 ,dz=38.3*mm/2); //large whole
+ TGeoVolume *pPpfSmall=gGeoManager->MakeBox("Rppf2" ,gGeoManager->GetMedium("Air") ,dx=114*mm/2,dy=89.25*mm/2 ,dz=38.3*mm/2);//small whole
+ TGeoVolume *pPc =gGeoManager->MakeBox("Rpc" ,gGeoManager->GetMedium("HMPID_CsI") ,dx=644*mm/2,dy= 407*mm/2 ,dz= 1.7*mm/2);//by 0.2 mm more then actual size (PCB 2006P1)
+
+ pRich->AddNode(pPpf,copy=1,new TGeoTranslation(-335*mm,-433*mm,8*cm+20*mm));//F1 2040P1 z p.84 TDR
+ pRich->AddNode(pPpf,copy=2,new TGeoTranslation(+335*mm,-433*mm,8*cm+20*mm));
+ pRich->AddNode(pPpf,copy=3,new TGeoTranslation(-335*mm, 0*mm,8*cm+20*mm));
+ pRich->AddNode(pPpf,copy=4,new TGeoTranslation(+335*mm, 0*mm,8*cm+20*mm));
+ pRich->AddNode(pPpf,copy=5,new TGeoTranslation(-335*mm,+433*mm,8*cm+20*mm));
+ pRich->AddNode(pPpf,copy=6,new TGeoTranslation(+335*mm,+433*mm,8*cm+20*mm));
+ pPpf->AddNode( pPc ,copy=1,new TGeoTranslation( 0*mm, 0*mm,-19.15*mm));//PPF 2001P2
+ pPpf->AddNode(pPpfLarge,copy=1,new TGeoTranslation(-224.5*mm,-151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=2,new TGeoTranslation(-224.5*mm,- 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=3,new TGeoTranslation(-224.5*mm,+ 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=4,new TGeoTranslation(-224.5*mm,+151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=1,new TGeoTranslation(- 65.0*mm,-151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=2,new TGeoTranslation(- 65.0*mm,- 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=3,new TGeoTranslation(- 65.0*mm,+ 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=4,new TGeoTranslation(- 65.0*mm,+151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=5,new TGeoTranslation(+ 65.0*mm,-151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=6,new TGeoTranslation(+ 65.0*mm,- 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=7,new TGeoTranslation(+ 65.0*mm,+ 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfSmall,copy=8,new TGeoTranslation(+ 65.0*mm,+151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=5,new TGeoTranslation(+224.5*mm,-151.875*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=6,new TGeoTranslation(+224.5*mm,- 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=7,new TGeoTranslation(+224.5*mm,+ 50.625*mm, 0.85*mm));
+ pPpf->AddNode(pPpfLarge,copy=8,new TGeoTranslation(+224.5*mm,+151.875*mm, 0.85*mm));
+//gap - anod wires
+ TGeoVolume *pGap =gGeoManager->MakeBox ("Rgap" ,gGeoManager->GetMedium("HMPID_CH4") ,dx=648*mm/2,dy= 411*mm/2 ,dz=4.45*mm/2);//xy as PPF 2001P2 z WP 2099P1
+ TGeoVolume *pAnod=gGeoManager->MakeTube("Rano" ,gGeoManager->GetMedium("HMPID_W") ,r1= 0*mm ,r2= 20*mkm/2 ,dz=648*mm/2); //WP 2099P1 z = gap x PPF 2001P2
+ TGeoRotation *pAnodRot=new TGeoRotation("RanW",90,90,0);
+
+ pRich->AddNode(pGap,copy=1,new TGeoTranslation(-335*mm,-433*mm,8*cm-2.225*mm)); //F1 2040P1 z WP 2099P1
+ pRich->AddNode(pGap,copy=2,new TGeoTranslation(+335*mm,-433*mm,8*cm-2.225*mm));
+ pRich->AddNode(pGap,copy=3,new TGeoTranslation(-335*mm, 0*mm,8*cm-2.225*mm));
+ pRich->AddNode(pGap,copy=4,new TGeoTranslation(+335*mm, 0*mm,8*cm-2.225*mm));
+ pRich->AddNode(pGap,copy=5,new TGeoTranslation(-335*mm,+433*mm,8*cm-2.225*mm));
+ pRich->AddNode(pGap,copy=6,new TGeoTranslation(+335*mm,+433*mm,8*cm-2.225*mm));
+ for(int i=1;i<=96;i++)
+ pGap->AddNode(pAnod,copy=i,new TGeoCombiTrans( 0*mm, -411/2*mm+i*4*mm, 0.185*mm,pAnodRot)); //WP 2099P1
+//frame 3- cathode wires
+ TGeoVolume *pCath=gGeoManager->MakeTube("RcaW" ,gGeoManager->GetMedium("Cu") ,r1=0 ,r2=100*mkm/2,dz=1323*mm/2);//r WP 2099P1 z F3 2041P1
+ TGeoRotation *pCathRot=new TGeoRotation("CathRot",90,90,0);
+ for(int i=1;i<=618;i++)
+ pRich->AddNode(pCath,copy=i,new TGeoCombiTrans( 0*mm, -649.5*mm+i*2.1*mm, 75*mm,pCathRot)); //WP 2099P1
+//Frame 4- collection wires
+ TGeoVolume *pF4 =gGeoManager->MakeBox( "Rfr4" ,gGeoManager->GetMedium("HMPID_CH4") ,dx=1407*mm/2 ,dy=1366*mm/2 ,dz= 15*mm/2);//F4 2043P1
+ TGeoVolume *pF4al=gGeoManager->MakeBox( "Rfr4al" ,gGeoManager->GetMedium("HMPID_Al") ,dx=1407*mm/2 ,dy=1366*mm/2 ,dz= 10*mm/2);
+ TGeoVolume *pF4in=gGeoManager->MakeBox( "Rfr4in" ,gGeoManager->GetMedium("HMPID_CH4") ,dx=1323*mm/2 ,dy=1296*mm/2 ,dz= 10*mm/2);
+ TGeoVolume *pColl=gGeoManager->MakeTube("RcoW" ,gGeoManager->GetMedium("HMPID_Cu") ,r1= 0*mm ,r2=100*mkm/2 ,dz=1323*mm/2);
+ TGeoRotation *pCollRot=new TGeoRotation("RcoRot",90,90,0);
+
+ pRich->AddNode(pF4 ,copy=1,new TGeoTranslation( 0*mm,0*mm, 9*mm)); //F4 to Rich p.84 TDR
+ pF4 ->AddNode(pF4al ,copy=1,new TGeoTranslation( 0*mm,0*mm, 2.5*mm)); //F4 al to F4 2043P1
+ pF4al->AddNode(pF4in ,copy=1,new TGeoTranslation( 0*mm,0*mm, 0*mm)); //F4 whole F4 al 2043P1
+ for(int i=1;i<=322;i++)
+ pF4->AddNode(pColl,copy=i,new TGeoCombiTrans( 0*mm, -1296/2*mm+i*4*mm, -5*mm,pCollRot)); //F4 2043P1
+//radiators
+ TGeoVolume *pRad =gGeoManager->MakeBox( "Rad" ,gGeoManager->GetMedium("HMPID_C6F14") ,dx=1330*mm/2 ,dy= 413*mm/2 ,dz= 24*mm/2); // Rad 2011P1
+ TGeoVolume *pRadFront =gGeoManager->MakeBox( "RadFront" ,gGeoManager->GetMedium("HMPID_Neoceram") ,dx=1330*mm/2 ,dy= 413*mm/2 ,dz= 4*mm/2);
+ TGeoVolume *pRadWin =gGeoManager->MakeBox( "RadWin" ,gGeoManager->GetMedium("HMPID_SiO2") ,dx=1330*mm/2 ,dy= 413*mm/2 ,dz= 5*mm/2);
+ TGeoVolume *pRadLong =gGeoManager->MakeBox( "RadLong" ,gGeoManager->GetMedium("HMPID_Neoceram") ,dx=1330*mm/2 ,dy= 5*mm/2 ,dz= 15*mm/2);
+ TGeoVolume *pRadShort =gGeoManager->MakeBox( "RadShort" ,gGeoManager->GetMedium("HMPID_Neoceram") ,dx= 10*mm/2 ,dy= 403*mm/2 ,dz= 15*mm/2);
+ TGeoVolume *pRadSpacer=gGeoManager->MakeTube("RadSpacer",gGeoManager->GetMedium("HMPID_SiO2") ,r1= 0 ,r2=10*mm/2 ,dz= 15*mm/2);
+
+ pRich->AddNode(pRad ,copy=1,new TGeoTranslation( 0*mm,-434*mm, -12*mm));
+ pRich->AddNode(pRad ,copy=2,new TGeoTranslation( 0*mm, 0*mm, -12*mm));
+ pRich->AddNode(pRad ,copy=3,new TGeoTranslation( 0*mm,+434*mm, -12*mm));
+
+ pRad ->AddNode(pRadFront ,copy=1,new TGeoTranslation( 0*mm, 0*mm, -10.0*mm));
+ pRad ->AddNode(pRadWin ,copy=1,new TGeoTranslation( 0*mm, 0*mm, 9.5*mm));
+ pRad ->AddNode(pRadLong ,copy=1,new TGeoTranslation( 0*mm,-204*mm, -0.5*mm));
+ pRad ->AddNode(pRadLong ,copy=2,new TGeoTranslation( 0*mm,+204*mm, -0.5*mm));
+ pRad ->AddNode(pRadShort ,copy=1,new TGeoTranslation(-660*mm, 0*mm, -0.5*mm));
+ pRad ->AddNode(pRadShort ,copy=2,new TGeoTranslation(+660*mm, 0*mm, -0.5*mm));
+ for(int i=0;i<3;i++) for(int j=0;j<10;j++) pRad->AddNode(pRadSpacer,copy=10*i+j,new TGeoTranslation(-1330*mm/2+116*mm+j*122*mm,(i-1)*105*mm,-0.5*mm));
+//sandbox
+ TGeoVolume *pSandBox =gGeoManager->MakeBox( "RSandBox" ,gGeoManager->GetMedium("Air") ,dx=1419*mm/2 ,dy=1378*mm/2 ,dz=50.5*mm/2); //2072P1
+ TGeoVolume *pSandCover=gGeoManager->MakeBox( "RSandCover",gGeoManager->GetMedium("HMPID_Al") ,dx=1419*mm/2 ,dy=1378*mm/2 ,dz= 0.5*mm/2);
+ TGeoVolume *pSandComb =gGeoManager->MakeBox( "RSandComb" ,gGeoManager->GetMedium("HMPID_Rohacell") ,dx=1359*mm/2 ,dy=1318*mm/2 ,dz=49.5*mm/2);
+
+ pRich->AddNode(pSandBox,copy=1,new TGeoTranslation( 0*mm,0*mm, -73.75*mm)); //p.84 TDR
+ pSandBox->AddNode(pSandComb ,copy=1,new TGeoTranslation( 0*mm,0*mm, 0*mm)); //2072P1
+ pSandBox->AddNode(pSandCover ,copy=1,new TGeoTranslation( 0*mm,0*mm, +25*mm));
+ pSandBox->AddNode(pSandCover ,copy=2,new TGeoTranslation( 0*mm,0*mm, -25*mm));
+}//Rich()
+//__________________________________________________________________________________________________
+void Sr90(TGeoVolume *pTop)
+{
+ pSrc =gGeoManager->MakeTube("Src" ,gGeoManager->GetMedium("Air") , 0 , 70*mm/2 , 30*mm/2); //top container
+ pAlGlass =gGeoManager->MakeTube("SrcAlGlass" ,gGeoManager->GetMedium("HMPID_Al") , 0 , 38*mm/2 ,21.8*mm/2); //Al glass wall
+ pPerpexPlug =gGeoManager->MakeTube("SrcPerpex" ,gGeoManager->GetMedium("HMPID_Perpex"), 0 , 34*mm/2 , 20*mm/2); //Perpex plug
+ pScrewCentral=gGeoManager->MakeTube("SrcScrewCentral" ,gGeoManager->GetMedium("HMPID_Steel") , 0 , 5*mm/2 , 15*mm/2); //Steel screw in the center
+ pScrewSr90 =gGeoManager->MakeTube("SrcScrewSr90" ,gGeoManager->GetMedium("HMPID_Steel") , 0 , 2*mm/2 , 10*mm/2); //Steel screw to support Sr90
+ pSr90 =gGeoManager->MakeTube("SrcSr90" ,gGeoManager->GetMedium("HMPID_Sr90") , 0 , 1*mm/2 , 1*mm/2); //Sr90 source
+ pHolePerpex =gGeoManager->MakeTube("SrcHolePerpex" ,gGeoManager->GetMedium("Air") , 0 , 4*mm/2 , 10*mm/2); //Air hole in perpex plug
+ pHoleAl =gGeoManager->MakeTube("SrcHoleAl" ,gGeoManager->GetMedium("Air") , 0 , 5*mm/2 , 1.8*mm/2); //Air hole in Al glass bottom
+ pMylarFoil =gGeoManager->MakeTube("SrcMylarFoil" ,gGeoManager->GetMedium("HMPID_Mylar") , 0 , 30*mm/2 , 50*mkm/2); //Mylar foil
+
+ pTop->AddNode(pSrc,1,new TGeoTranslation(30*cm,0,1*cm));
+ pSrc ->AddNode(pMylarFoil,1,new TGeoTranslation(0,0,21.8*mm/2+50*mkm/2));
+ pSrc ->AddNode(pAlGlass,1,new TGeoTranslation(0,0,0)); //Al glass to fake Src volume
+ pAlGlass->AddNode( pHoleAl ,1,new TGeoTranslation(6*mm,0, -10*mm));
+ pAlGlass->AddNode( pPerpexPlug ,1,new TGeoTranslation(0*mm,0, 0.9*mm));
+ pPerpexPlug->AddNode( pHolePerpex ,1,new TGeoTranslation(6*mm,0, -5*mm));
+ pPerpexPlug->AddNode( pScrewCentral,1,new TGeoTranslation(0 ,0, 2.5*mm));
+ pPerpexPlug->AddNode( pScrewSr90 ,1,new TGeoTranslation(6*mm,0, 5*mm));
+ pScrewSr90->AddNode( pSr90 ,1,new TGeoTranslation(0 ,0,-4.5*mm));
+}//Sr90()
+//__________________________________________________________________________________________________
+void RusGel()
+{
+//Defines VHMPID aerogel option geometry.
+// top view normal position side view normal position
+// ^ y
+// -------- |
+// | | |
+// | | z<-----* y z<-------* x ----> MUON side
+// | | | ----
+// | | | | |
+// ________ v x | |
+// |--|
+// | |
+// ----
+//Chamber consists from Al box filled with air where 4 aerogel blocks and APD wall are positioned.
+// ------------------------------
+// |-| |-| |-| |-| |-||
+// |-| | | | | | | | ||
+// |-| | | | | | | | ||
+// |-| APD wall | | | | | | | || z<---* y top view
+// |-| | | | | | | | || |
+// |-| | | | | | | | || |
+// |-| |_| |_| |_| |_|| v x
+// ------------------------------
+//
+// ALIC
+// |
+// Vbox (Al)
+// |
+// Vair (Air)
+// _______|________
+// | |
+// 4*Vgel Vwall
+// |
+// Vcolumn (division along X)
+// |
+// Vcell (division along Y)
+// |
+// Vapd
+
+ Double_t cm=1 , m=100 , mm=0.1 ;//dimentions, default is cm
+
+ Int_t iNapdsX =10 ;//number of APDs along x
+ Int_t iNapdsY =16 ;//number of APDs along y
+ Double_t dCellX =1.5*mm *0.5 ;//cell X half size
+ Double_t dCellY =1.5*mm *0.5 ;//cell Y half size
+ Double_t dCellZ =0.5*mm *0.5 ;//APD wall thickness
+ Double_t dWallX = iNapdsX*dCellX;//APD wall X half size
+ Double_t dWallY = iNapdsY*dCellY;//APD wall Y half size
+ Double_t dWallZ = dCellZ;//APD wall half thickness
+ Double_t dApdR =0.5*mm ;//APD radius
+ Double_t dApdZ = dCellZ;//APD Z half size
+ Double_t dGelX = dWallX;//gel block X half size
+ Double_t dGelY = dWallY;//gel block Y half size
+ Double_t dGelZ =10*mm *0.5 ;//gel block Z half size
+ Double_t dProxGap =50*cm ;//half distance between APD wall and last aerogel block
+ Double_t dAirX = dWallX;//internal air X hald size
+ Double_t dAirY = dWallY;//internal air Y hald size
+ Double_t dAirZ = dWallZ+dProxGap+7*dGelZ;//internal air Z hald size
+ Double_t dBoxWall =2*mm *0.5 ;//Al box walls thickness
+ Double_t dBoxX = dAirX+dBoxWall;//Al box x half size
+ Double_t dBoxY = dAirY+dBoxWall;//Al box y half size
+ Double_t dBoxZ = dAirZ+dBoxWall;//Al box z half size
+
+ Int_t copy; Double_t rmin,rmax,dx,dy,dz;
+//make external Al box
+ TGeoVolume *pBox=gGeoManager->MakeBox("Gbox",gGeoManager->GetMedium("HMPID_Al"),dx=dBoxX,dy=dBoxY,dz=dBoxZ);
+ TGeoRotation *pRot=new TGeoRotation("GboxRot"); pRot->RotateX(90);
+ gGeoManager->GetVolume("ALIC")->AddNode(pBox,copy=1,new TGeoCombiTrans(0*m,-5.2*m,2.5*m,pRot));//normal position
+//position Air to Al box
+ TGeoVolume *pAir=gGeoManager->MakeBox( "Gair",gGeoManager->GetMedium("Air"),dx=dAirX,dy=dAirY,dz=dAirZ);
+ pBox->AddNode(pAir,copy=1);
+//position 4 gel blocks to Air
+ TGeoVolume *pGel24=gGeoManager->MakeBox( "Ggel24",gGeoManager->GetMedium("HMPID_Gel24"),dx=dGelX,dy=dGelY,dz=dGelZ);
+ pAir->AddNode(pGel24,copy=1,new TGeoTranslation(0,0,-dAirZ+1*dGelZ));
+ TGeoVolume *pGel26=gGeoManager->MakeBox( "Ggel26",gGeoManager->GetMedium("HMPID_Gel26"),dx=dGelX,dy=dGelY,dz=dGelZ);
+ pAir->AddNode(pGel26,copy=1,new TGeoTranslation(0,0,-dAirZ+5*dGelZ));
+ TGeoVolume *pGel28=gGeoManager->MakeBox( "Ggel28",gGeoManager->GetMedium("HMPID_Gel28"),dx=dGelX,dy=dGelY,dz=dGelZ);
+ pAir->AddNode(pGel28,copy=1,new TGeoTranslation(0,0,-dAirZ+9*dGelZ));
+ TGeoVolume *pGel30=gGeoManager->MakeBox( "Ggel30",gGeoManager->GetMedium("HMPID_Gel30"),dx=dGelX,dy=dGelY,dz=dGelZ);
+ pAir->AddNode(pGel30,copy=1,new TGeoTranslation(0,0,-dAirZ+13*dGelZ));
+//position APD wall to air
+ TGeoVolume *pWall =gGeoManager->MakeBox ("Gwall",gGeoManager->GetMedium("HMPID_Si"),dx=dWallX , dy=dWallY , dz=dWallZ );
+ pAir->AddNode(pWall,copy=1,new TGeoTranslation(0,0,dAirZ-dWallZ));
+//divide wall into cells
+ Int_t axis,ndiv; Double_t start,step;
+ TGeoVolume *pWallCol =pWall ->Divide("Gcol",axis=1,ndiv=iNapdsX,start=0,step=0);//divide VhGap along X by NpadsX columns
+ TGeoVolume *pWallCell=pWallCol ->Divide("Gcel",axis=2,ndiv=iNapdsY,start=0,step=0);//divide VhGapCol along Y by NpadsY cells
+//position APD to wall cell
+ TGeoVolume *pApd=gGeoManager->MakeTube("Gapd",gGeoManager->GetMedium("HMPID_Apd"),rmin=0,rmax=dApdR,dz=dApdZ); pWallCell->AddNode(pApd,copy=1);
+}//RusGel()
+//__________________________________________________________________________________________________
+void Vhmpid()
+{
+//Defines VHMPID geometry for TIC option.
+// top view normal position side view normal position
+// ^ y
+// -------- |
+// |------| |
+// | | z<-----* y z<-------* x ----> MUON side
+// | | | ----
+// | | | | |
+// ________ v x | |
+// |--|
+// | |
+// ----
+//Chamber consists from Al box filled with radiator CF4 and C4F10 quartz window in between , Al mirror and MWPC.
+// --------------------------------------------------- top view chamber in test position
+// | -------------- MWPC | quartz window |
+// | . . . . . . | |
+// | \ | |
+// | \ CF4 | C4F10 | z<-----* y
+// | \ mirror | | |
+// | \ | | |
+// | \ | | v x
+// ---------------------------------------------------
+// z ^
+// |
+// |
+// <-Y0-> X <--Y1--> X <--Y1--> X <--Y1--> X <-Y0-> | cath wires: r 50mkm; shift Y0=1.05m;, pitch Y1=2.1; center to PC 4.45mm; material Cu
+// x *------->y
+//
+// <--Y0--> x <-----------Y1-----------> x <--Y0--> anod wires: r 20mkm; shift Y0=2.2mm; pitch Y1=4.0mm; center to PC 2.04mm; material W
+//
+//
+// |________________________________________________| pad size y 8.4mm
+//
+// ALIC
+// |
+// Vbox
+// _______|______
+// | | |
+// Vc4f Vwin Vcf4
+// _____|________
+// | |
+// Vmir |
+// |
+// Vgap
+// |
+// Vcol (column of gap cells) X
+// |
+// Vcel cell in the column Y
+// ______|______
+// | | |
+// Vpad Vano Vcat
+ Double_t cm=1 , m=100 , mm=0.1 , um=1e-4 ;//dimentions, default is cm
+
+ Int_t iNpadsX = AliHMPIDParam::NpadsX() ;//number of pads along x parametrised
+ Int_t iNpadsY = AliHMPIDParam::NpadsY() ;//number of pads along y parametrised
+ Double_t wCathR =50 *um ;//cathode wire radius defined by USER
+ Double_t wCathShift =1.05*mm ;//cathode wire shift from pad edge defined by USER
+ Double_t wCathPitch =2.1 *mm ;//cathode wire pitch defined by USER
+ Double_t wCathPc =4.45*mm ;//distance from pc to cathode wire defined by USER
+ Double_t wAnodR =20 *um ;//anod wire radius defined by USER
+ Double_t wAnodShift =2.2 *mm ;//anod wire shift from pad edge defined by USER
+ Double_t wAnodPc =2.04*mm ;//distance from anod wire center to pc defined by USER
+ Double_t dPadX = 0.5* AliHMPIDParam::PadSizeX() ;//pad X half size parametrised
+ Double_t dPadY = 0.5* AliHMPIDParam::PadSizeY() ;//pad Y half size parametrised
+ Double_t dPadZ =1.0 *mm *0.5 ;//CsI film thickness
+ Double_t dGapX = 0.5* iNpadsX*2*dPadX ;//gap x half size n. pads x * pad size
+ Double_t dGapY = 0.5* iNpadsY*2*dPadY ;//gap y half size
+ Double_t dGapZ = 0.5* (2*dPadZ+wCathPc+wCathR) ;//gap half thickness
+ Double_t dMirX = 0.5* 2*dGapX/TMath::Cos(45*TMath::DegToRad());//Ag mirror x half size defined by gap size and angle 45 degrees
+ Double_t dMirY = 0.5* 2*dGapY ;//Ag mirror y half size defined by gap size
+ Double_t dMirZ =1.0 *mm *0.5 ;//Ag mirror z half size defined by USER
+ Double_t wBoxWall =2.0 *mm ;//Al box walls thickness defined by USER
+ Double_t dBoxX = 0.5* (2*dGapX+2*cm) ;//Al box x half size defined by gap size 2 cm for tolerance
+ Double_t dBoxY = 0.5* (2*dGapY+2*cm) ;//Al box y half size defined by gap size 2 cm for tolerance
+ Double_t dBoxZ =1.8*m *0.5 ;//Al box z half size defined by USER
+ Double_t dWinX = (dBoxX-wBoxWall) ;//SiO2 window x half size defined by box size
+ Double_t dWinY = (dBoxY-wBoxWall) ;//SiO2 window y half size defined by box size
+ Double_t dWinZ =1.0*cm *0.5 ;//SiO2 window z half size defined by USER
+ Double_t dCF4X = (dBoxX-wBoxWall) ;//CF4 radiator x half size defined by box size
+ Double_t dCF4Y = (dBoxY-wBoxWall) ;//CF4 radiator y half size defined by box size
+ Double_t dCF4Z = 0.4*dBoxZ ;//CF4 radiator z half size defined by box size or by USER
+ Double_t dC4F10X = (dBoxX-wBoxWall) ;//C4F10 radiator x half size defined by box size
+ Double_t dC4F10Y = (dBoxY-wBoxWall) ;//C4F10 radiator y half size defined by box size
+ Double_t dC4F10Z = (dBoxZ-dWinZ-dCF4Z-wBoxWall) ;//C4F10 radiator z half size defined by box, CF4 and window sizes
+
+ Int_t copy;
+ Double_t rmin,rmax,dx,dy,dz;
+
+//make VHMPID type 2 volume (2 radiators)
+ TGeoVolume *pBox=gGeoManager->MakeBox("Vbox",gGeoManager->GetMedium("HMPID_Al"),dx=dBoxX,dy=dBoxY,dz=dBoxZ);
+
+ TGeoRotation *pRot=new TGeoRotation("VboxRot"); pRot->RotateX(90);//normal position
+ gGeoManager->GetVolume("ALIC")->AddNode(pBox,copy=1,new TGeoCombiTrans(0*m,-5.2*m,2.5*m,pRot));
+//position C4F10 radiator to Al box
+ TGeoVolume *pC4F10=gGeoManager->MakeBox("Vc4f",gGeoManager->GetMedium("HMPID_C4F10"),dx=dC4F10X,dy=dC4F10Y,dz=dC4F10Z);
+ pBox->AddNode(pC4F10,copy=1,new TGeoTranslation(0*cm,0*cm,-dBoxZ+wBoxWall+dC4F10Z));
+//position quartz window to Al box
+ TGeoVolume *pWindow=gGeoManager->MakeBox( "Vwin",gGeoManager->GetMedium("HMPID_SiO2"),dx=dWinX,dy=dWinY,dz=dWinZ);
+ pBox->AddNode(pWindow,copy=1,new TGeoTranslation(0*cm,0*cm,-dBoxZ+wBoxWall+2*dCF4Z+dWinZ));
+//position CF4 radiator to Al box
+ TGeoVolume *pCF4=gGeoManager->MakeBox( "Vcf4",gGeoManager->GetMedium("HMPID_CF4"),dx=dCF4X,dy=dCF4Y,dz=dCF4Z);
+ pBox->AddNode(pCF4,copy=1,new TGeoTranslation(0*cm,0*cm,dBoxZ-wBoxWall-dCF4Z));
+//position mirror to CF4 radiator
+ TGeoVolume *pMirror=gGeoManager->MakeBox( "Vmir",gGeoManager->GetMedium("HMPID_Ag"),dx=dMirX,dy=dMirY,dz=dMirZ);
+ TGeoRotation *pMirrorRot=new TGeoRotation("VmirRot"); pMirrorRot->RotateY(45);
+ pCF4->AddNode(pMirror,copy=1,new TGeoCombiTrans(0*cm,0*cm,dCF4Z-1*cm-dGapX,pMirrorRot));
+//position gap to CF4 radiator
+ TGeoVolume *pGap =gGeoManager->MakeBox ("Vgap" ,gGeoManager->GetMedium("HMPID_CF4"),dx=dGapX , dy=dGapY , dz=dGapZ );
+ TGeoRotation *pMwpcRot=new TGeoRotation("VmpcRot"); pMwpcRot->RotateY(90);
+ pCF4->AddNode(pGap,copy=1,new TGeoCombiTrans(-dBoxX+1*cm,0*cm,dCF4Z-1*cm-dGapX,pMwpcRot));
+//divide gap into 80x48 cells
+ Int_t axis,ndiv; Double_t start,step;
+ TGeoVolume *pGapCol =pGap ->Divide("Vcol",axis=1,ndiv=iNpadsX,start=0,step=0);//divide VhGap along X by NpadsX columns
+ TGeoVolume *pGapCell=pGapCol ->Divide("Vcel",axis=2,ndiv=iNpadsY,start=0,step=0);//divide VhGapCol along Y by NpadsY cells
+//position pad to gap cell
+ TGeoVolume *pPad=gGeoManager->MakeBox ("Vpad",gGeoManager->GetMedium("HMPID_CsI"),dx=dPadX,dy=dPadY,dz=dPadZ);
+ pGapCell->AddNode(pPad,copy=1,new TGeoTranslation(0,0,-dGapZ+dPadZ));
+//define wire rotation common for both anod and cathode wires
+ TGeoRotation *pWireRot=new TGeoRotation("VwireRot"); pWireRot->RotateY(90); //rotate wires around Y to be along X (initially along Z)
+//position 2 anod wires to gap cell
+ TGeoVolume *pAnodWire =gGeoManager->MakeTube("Vano",gGeoManager->GetMedium("HMPID_W") ,rmin=0 , rmax=wAnodR , dz=dPadX );
+ pGapCell->AddNode(pAnodWire,copy=1,new TGeoCombiTrans (0, -dPadY+wAnodShift , -dGapZ+wAnodPc+2*dPadZ , pWireRot));
+ pGapCell->AddNode(pAnodWire,copy=2,new TGeoCombiTrans (0, dPadY-wAnodShift , -dGapZ+wAnodPc+2*dPadZ , pWireRot));
+//position 4 cathode wires to gap cell
+ TGeoVolume *pCathWire =gGeoManager->MakeTube("Vcat",gGeoManager->GetMedium("HMPID_Cu") ,rmin=0 , rmax=wCathR , dz=dPadX );
+ pGapCell->AddNode(pCathWire,copy=1,new TGeoCombiTrans (0, -dPadY+wCathShift , -dGapZ+wCathPc+2*dPadZ , pWireRot));
+ pGapCell->AddNode(pCathWire,copy=2,new TGeoCombiTrans (0, -dPadY+wCathShift+wCathPitch , -dGapZ+wCathPc+2*dPadZ , pWireRot));
+ pGapCell->AddNode(pCathWire,copy=3,new TGeoCombiTrans (0, dPadY-wCathShift-wCathPitch , -dGapZ+wCathPc+2*dPadZ , pWireRot));
+ pGapCell->AddNode(pCathWire,copy=4,new TGeoCombiTrans (0, dPadY-wCathShift , -dGapZ+wCathPc+2*dPadZ , pWireRot));
+}//Vhmpid()
+//__________________________________________________________________________________________________
+void Axis()
+{
+// Draw axises on top of geometry
+ Double_t X[6]={0,0,0,300,0,0}; Double_t Y[6]={0,0,0,0,300,0}; Double_t Z[6]={0,0,0,0,0,300};
+ TPolyLine3D *pXaxis=new TPolyLine3D(2,X);pXaxis->SetLineColor(kRed); pXaxis->Draw();
+ TPolyLine3D *pYaxis=new TPolyLine3D(2,Y);pYaxis->SetLineColor(kGreen); pYaxis->Draw();
+ TPolyLine3D *pZaxis=new TPolyLine3D(2,Z);pZaxis->SetLineColor(kBlue); pZaxis->Draw();
+}
+//__________________________________________________________________________________________________
--- /dev/null
+Module :=HMPID
+
+include lib$(Module)base.pkg
+SrcBase :=$(SRCS)
+
+include lib$(Module)sim.pkg
+SrcSim :=$(SRCS)
+
+include lib$(Module)rec.pkg
+SrcRec :=$(SRCS)
+
+RootTarget :=$(shell root-config --arch)
+DirOut :=/tmp/$(USER)_$(Module)_obj
+LibBase :=$(LIB_MY)/lib$(Module)base.so
+LibSim :=$(LIB_MY)/lib$(Module)sim.so
+LibRec :=$(LIB_MY)/lib$(Module)rec.so
+
+
+HdrBase := $(SrcBase:.cxx=.h) $(Module)baseLinkDef.h
+HdrSim := $(SrcSim:.cxx=.h) $(Module)simLinkDef.h
+HdrRec := $(SrcRec:.cxx=.h) $(Module)recLinkDef.h
+
+DictSrcBase := $(DirOut)/Dict$(Module)base.cxx
+DictObjBase := $(DictSrcBase:.cxx=.o)
+
+DictSrcSim := $(DirOut)/Dict$(Module)sim.cxx
+DictObjSim := $(DictSrcSim:.cxx=.o)
+
+DictSrcRec := $(DirOut)/Dict$(Module)rec.cxx
+DictObjRec := $(DictSrcRec:.cxx=.o)
+
+
+
+ObjBase := $(patsubst %.cxx,$(DirOut)/%.o,$(SrcBase)) $(DictObjBase)
+ObjSim := $(patsubst %.cxx,$(DirOut)/%.o,$(SrcSim)) $(DictObjSim)
+ObjRec := $(patsubst %.cxx,$(DirOut)/%.o,$(SrcRec)) $(DictObjRec)
+
+
+DepFile := $(DirOut)/$(Module).depend
+
+ifeq ($(RootTarget),linuxicc)
+ Compiler :=icc
+ CompilerOpt :=-fpstkchk -I$(shell root-config --incdir) -I$(ALICE_ROOT)/include
+ LibOpt :=-g -shared -Wl
+else
+ Compiler :=g++
+ CompilerOpt :=-g -W -Wall -Werror -Woverloaded-virtual -fPIC -pipe -fmessage-length=0 -Wno-long-long -pedantic-errors -ansi -Dlinux -D`uname` -I$(shell root-config --incdir) -I$(ALICE_ROOT)/include
+ LibOpt :=-g -shared -Wl
+endif
+
+ifdef ALIVERBOSE
+ Mute :=
+else
+ Mute :=@
+endif
+
+##### TARGETS #####
+
+all: $(LibBase) $(LibSim) $(LibRec)
+$(LibBase): $(ObjBase)
+ @echo "Creating $@"
+ $(Mute)$(Compiler) $(LibOpt) $^ -o $@
+
+$(LibSim): $(ObjSim)
+ @echo "Creating $@"
+ $(Mute)$(Compiler) $(LibOpt) $^ -o $@
+
+$(LibRec): $(ObjRec)
+ @echo "Creating $@"
+ $(Mute)$(Compiler) $(LibOpt) $^ -o $@
+
+$(DepFile): $(HdrBase) $(HdrSim) $(HdrRec)
+ @[ -d $(DirOut) ] || mkdir -p $(DirOut)
+ @[ -d $(LIB_MY) ] || mkdir -p $(LIB_MY)
+ @touch $(DepFile)
+ @echo "Generating dependency $@"
+ $(Mute)rmkdepend -f$(DepFile) -p$(DirOut)/ -- $(CompilerOpt) -- $(SrcBase) $(SrcSim) $(SrcRec) 2>/dev/null
+
+$(DictSrcBase): $(HdrBase)
+ @echo "Generating $@"
+ $(Mute)rootcint -f $@ -c $(filter -I%,$(CompilerOpt)) $^
+
+$(DictSrcSim): $(HdrSim)
+ @echo "Generating $@"
+ $(Mute)rootcint -f $@ -c $(filter -I%,$(CompilerOpt)) $^
+
+$(DictSrcRec): $(HdrRec)
+ @echo "Generating $@"
+ $(Mute)rootcint -f $@ -c $(filter -I%,$(CompilerOpt)) $^
+
+$(DictObjBase) : $(DictSrcBase)
+ @echo "Compiling $^"
+ $(Mute)$(Compiler) $(CompilerOpt) -I. -c $^ -o $@
+
+$(DictObjSim) : $(DictSrcSim)
+ @echo "Compiling $^"
+ $(Mute)$(Compiler) $(CompilerOpt) -I. -c $^ -o $@
+
+$(DictObjRec) : $(DictSrcRec)
+ @echo "Compiling $^"
+ $(Mute)$(Compiler) $(CompilerOpt) -I. -c $^ -o $@
+
+show:
+ @echo "Base Headers: $(HdrBase)"
+ @echo "Base Sources: $(SrcBase)"
+ @echo "Base Objects: $(ObjBase)"
+ @echo "Base Dict: $(DictSrcBase)"
+ @echo -e "Base Library: $(LibBase)\n"
+
+ @echo "Sim Headers: $(HdrSim)"
+ @echo "Sim Sources: $(SrcSim)"
+ @echo "Sim Objects: $(ObjSim)"
+ @echo -e "Sim Library: $(LibSim)\n"
+
+ @echo "Rec Headers: $(HdrRec)"
+ @echo "Rec Sources: $(SrcRec)"
+ @echo "Rec Objects: $(ObjRec)"
+ @echo -e "Rec Library: $(LibRec)\n"
+
+spec: $(SrcBase)
+ @echo "^ $^"
+ @echo "@ $@"
+ @echo "< $<"
+
+clean:
+ @echo "Cleaning..."
+ $(Mute)rm -rf $(DirOut) $(LibBase) $(LibSim) $(LibRec)
+
+############################ cxx rule #########################################
+$(DirOut)/%.o : %.cxx
+ @echo $*.cxx
+ $(Mute)$(Compiler) $(CompilerOpt) -c $*.cxx -o $(DirOut)/$*.o
+############################ Dependencies #####################################
+
+-include $(DepFile)
--- /dev/null
+AliRun *a; AliStack *s; AliRunLoader *al; TGeoManager *g; //globals for easy manual manipulations
+AliHMPID *r; AliLoader *rl; AliHMPIDParam *rp;
+Bool_t isGeomType=kFALSE;
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void GetParam()
+{
+ isGeomType=!isGeomType;
+ if(g) delete g; if(rp) delete rp; //delete current TGeoManager and AliHMPIDParam
+ if(isGeomType) g=TGeoManager::Import("geometry.root");
+ else g=TGeoManager::Import("misaligned_geometry.root");
+ rp=AliHMPIDParam::Instance();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RichMenu()
+{
+ TString status="Status: ";
+ if(gSystem->IsFileInIncludePath("galice.root")){
+ status+="galice.root found";
+ al=AliRunLoader::Open(); //try to open galice.root from current dir
+ if(gAlice) delete gAlice; //in case we execute this in aliroot delete default AliRun object
+ al->LoadgAlice(); a=al->GetAliRun(); //take new AliRun object from galice.root
+ rl=al->GetDetectorLoader("HMPID"); r=(AliHMPID*)a->GetDetector("HMPID"); //get HMPID object from galice.root
+
+ status+=Form(" with %i event(s)",al->GetNumberOfEvents()); status+=(r)? " with HMPID": " without HMPID";
+ }else
+ status+="No galice.root";
+
+ GetParam();
+
+ TControlBar *pMenu = new TControlBar("horizontal",status.Data(),0,0);
+ pMenu->AddButton(" ","","");
+ pMenu->AddButton(" General " ,"General()" ,"general items which do not depend on any files");
+ pMenu->AddButton(" ","" ,"");
+ pMenu->AddButton(" Sim data " ,"SimData()" ,"items which expect to have simulated files" );
+ pMenu->AddButton(" ","" ,"");
+ pMenu->AddButton(" Raw data " ,"RawData()" ,"items which expect to have raw files" );
+ pMenu->AddButton(" ","print()" ,"");
+ pMenu->AddButton("Test" ,"Test()" ,"all test utilities");
+ pMenu->AddButton(" ","GetParam()" ,"");
+ pMenu->AddButton("Quit" ,".q" ,"close session" );
+ pMenu->Show();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void General()
+{
+ TControlBar *pMenu = new TControlBar("vertical","Sim data",60,50);
+ pMenu->AddButton("Debug ON" ,"don();" ,"Switch debug on-off" );
+ pMenu->AddButton("Debug OFF" ,"doff();" ,"Switch debug on-off" );
+ pMenu->AddButton("Geo GUI" ,"geo();" ,"Shows geometry" );
+ pMenu->AddButton("Browser" ,"new TBrowser;" ,"Start ROOT TBrowser" );
+ pMenu->Show();
+}//menu()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void SimData()
+{
+ TControlBar *pMenu = new TControlBar("vertical","Sim",190,50);
+ pMenu->AddButton("Display ALL chambers" ,"ed();" , "Display Fast");
+ pMenu->AddButton("HITS QA" ,"hqa()" ,"QA plots for hits: hqa()");
+
+ pMenu->AddButton("Print hits" ,"hp();" ,"To print hits: hp(evt)");
+ pMenu->AddButton("Print sdigits" ,"sp();" ,"To print sdigits: sp(evt)");
+ pMenu->AddButton("Print digits" ,"dp();" ,"To print digits: dp(evt)");
+ pMenu->AddButton("Print clusters" ,"cp();" ,"To print clusters: cp(evt)");
+
+ pMenu->Show();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void RawData()
+{
+ TControlBar *pMenu = new TControlBar("vertical","Raw",350,50);
+ pMenu->AddButton("ESD print" ,"ep();" ,"To print ESD info: ep()" );
+ pMenu->AddButton("ESD QA" ,"eq();" ,"To draw ESD hists: eq()" );
+ pMenu->AddButton("Clusters print" ,"cp();" ,"To print clusters: cp()" );
+ pMenu->AddButton("Clusters QA" ,"cq();" ,"To draw clusters hists: cq()" );
+ pMenu->AddButton("Print Matrix" ,"mp();" ,"To print prob matrix: mp()" );
+ pMenu->AddButton("Print occupancy" ,"r->OccupancyPrint(-1);" ,"To print occupancy" );
+ pMenu->AddButton("Print event summary " ,"r->SummaryOfEvent();" ,"To print a summary of the event" );
+ pMenu->Show();
+}//RawData
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+void Test()
+{
+ TControlBar *pMenu = new TControlBar("vertical","Test",400,50);
+ pMenu->AddButton("Hits->Digits" ,"thd();" ,"test hits->sdigits->digits" );
+ pMenu->AddButton("Segmentation" ,"ts()" ,"test segmentation methods" );
+ pMenu->AddButton("Test response" ,"AliHMPIDParam::TestResp();" ,"Test AliHMPIDParam response methods" );
+ pMenu->AddButton("Test transformation","AliHMPIDParam::TestTrans();","Test AliHMPIDParam transformation methods" );
+ pMenu->AddButton("Test Recon" ,"rec();" ,"Test AliHMPIDRecon" );
+ pMenu->Show();
+}//Test()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+void doff(){ Printf("DebugOFF"); AliLog::SetGlobalDebugLevel(0);}
+void don() { Printf("DebugON"); AliLog::SetGlobalDebugLevel(AliLog::kDebug);}
+
+void geo ( ) {gGeoManager->GetTopVolume()->Draw("ogl");}
+
+void du ( ) {r->Dump ( );} //utility display
+
+void hp (Int_t evt=0 ) {r->HitPrint (evt);} //print hits for requested event
+void hq ( ) {r->HitQA ( );} //hits QA plots for all events
+void sp (Int_t evt=0 ) {r->SdiPrint (evt);} //print sdigits for requested event
+void sq (Int_t evt=0 ) {r->SdiPrint (evt);} //print sdigits for requested event
+void dp (Int_t evt=0 ) {r->DigPrint (evt);} //print digits for requested event
+void dq ( ) {AliHMPIDReconstructor::DigQA (al );} //digits QA plots for all events
+void cp (Int_t evt=0 ) {r->CluPrint (evt); } //print clusters for requested event
+void cq ( ) {AliHMPIDReconstructor::CluQA (al );} //clusters QA plots for all events
+
+void ep ( ) {AliHMPIDTracker::EsdQA(1); }
+void eq ( ) {AliHMPIDTracker::EsdQA(); }
+void mp (Double_t probCut=0.7 ) {AliHMPIDTracker::MatrixPrint(probCut);}
+
+
+void t (Int_t evt=0 ) {AliHMPIDParam::Stack(evt);}
+void tid (Int_t tid,Int_t evt=0) {AliHMPIDParam::Stack(evt,tid);}
+
+
+Int_t nem (Int_t evt=0) {AliHMPIDParam::StackCount(kElectron ,evt);} //utility number of electrons
+Int_t nep (Int_t evt=0) {AliHMPIDParam::StackCount(kPositron ,evt);} //utility number of positrons
+Int_t nmup(Int_t evt=0) {AliHMPIDParam::StackCount(kMuonPlus ,evt);} //utility number of positive muons
+Int_t nmum(Int_t evt=0) {AliHMPIDParam::StackCount(kMuonMinus ,evt);} //utility number of negative muons
+Int_t npi0(Int_t evt=0) {AliHMPIDParam::StackCount(kPi0 ,evt);} //utility number of neutral pions
+Int_t npip(Int_t evt=0) {AliHMPIDParam::StackCount(kPiPlus ,evt);} //utility number of positive pions
+Int_t npim(Int_t evt=0) {AliHMPIDParam::StackCount(kPiMinus ,evt);} //utility number of negative pions
+Int_t nk0 (Int_t evt=0) {AliHMPIDParam::StackCount(kK0 ,evt);} //utility number of neutral kaons
+Int_t nkp (Int_t evt=0) {AliHMPIDParam::StackCount(kKPlus ,evt);} //utility number of positive kaons
+Int_t nkm (Int_t evt=0) {AliHMPIDParam::StackCount(kKMinus ,evt);} //utility number of negative kaons
+Int_t npp (Int_t evt=0) {AliHMPIDParam::StackCount(kProton ,evt);} //utility number of protons
+Int_t npm (Int_t evt=0) {AliHMPIDParam::StackCount(kProtonBar ,evt);} //utility number of antiprotons
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+void tst()
+{
+ Int_t ch=3;
+ TClonesArray hitLst("AliHMPIDHit");
+ TClonesArray sdiLst("AliHMPIDDigit");
+ TObjArray digLst; for(Int_t i=0;i<7;i++) digLst.AddAt(new TClonesArray("AliHMPIDDigit"),i);
+ TClonesArray cluLst("AliHMPIDCluster");
+
+ Int_t iHitCnt=0; new(hitLst[iHitCnt++]) AliHMPIDHit(ch,200e-9,kProton,1, 8.40 , 60.14); //c,e,pid,tid,xl,yl
+// new(hitLst[iHitCnt++]) AliHMPIDHit(ch,e*1e-9,kProton,2,x,y); //c,e,pid,tid,xl,yl,x,y,z
+
+ Printf("HIT------HIT---------HIT--------HIT------HIT------HIT");hitLst.Print();Printf("");
+ AliHMPIDv1::Hit2Sdi(&hitLst,&sdiLst); Printf("SDI------DIG---------SDI--------SDI------SDI------SDI");sdiLst.Print();Printf("");
+ AliHMPIDDigitizer::Sdi2Dig(&sdiLst,&digLst); Printf("DIG------DIG---------DIG--------DIG------DIG------DIG");digLst.Print();Printf("");
+ AliHMPIDReconstructor::Dig2Clu((TClonesArray*)digLst[ch],&cluLst); Printf("CLU------CLU---------CLU--------CLU------CLU------CLU");cluLst.Print();Printf("");
+
+
+}
+
+
+void print()
+{
+
+ Double_t r2d=TMath::RadToDeg();
+
+ Double_t x=AliHMPIDDigit::SizeAllX(),y=AliHMPIDDigit::SizeAllY();
+
+ TVector3 c6lt=rp->Lors2Mars(6,0,y); TVector3 c6rt=rp->Lors2Mars(6,x,y);
+ TVector3 c6ce=rp->Lors2Mars(6,x/2,y/2);
+ TVector3 c6lb=rp->Lors2Mars(6,0,0); TVector3 c6rb=rp->Lors2Mars(6,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c5lt=rp->Lors2Mars(5,0,y); TVector3 c5rt=rp->Lors2Mars(5,x,y);
+ TVector3 c5ce=rp->Lors2Mars(5,x/2,y/2);
+ TVector3 c5lb=rp->Lors2Mars(5,0,0); TVector3 c5rb=rp->Lors2Mars(5,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c4lt=rp->Lors2Mars(4,0,y); TVector3 c4rt=rp->Lors2Mars(4,x,y);
+ TVector3 c4ce=rp->Lors2Mars(4,x/2,y/2);
+ TVector3 c4lb=rp->Lors2Mars(4,0,0); TVector3 c4rb=rp->Lors2Mars(4,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c3lt=rp->Lors2Mars(3,0,y); TVector3 c3rt=rp->Lors2Mars(3,x,y);
+ TVector3 c3ce=rp->Lors2Mars(3,x/2,y/2);
+ TVector3 c3lb=rp->Lors2Mars(3,0,0); TVector3 c3rb=rp->Lors2Mars(3,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c2lt=rp->Lors2Mars(2,0,y); TVector3 c2rt=rp->Lors2Mars(2,x,y);
+ TVector3 c2ce=rp->Lors2Mars(2,x/2,y/2);
+ TVector3 c2lb=rp->Lors2Mars(2,0,0); TVector3 c2rb=rp->Lors2Mars(2,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c1lt=rp->Lors2Mars(1,0,y); TVector3 c1rt=rp->Lors2Mars(1,x,y);
+ TVector3 c1ce=rp->Lors2Mars(1,x/2,y/2);
+ TVector3 c1lb=rp->Lors2Mars(1,0,0); TVector3 c1rb=rp->Lors2Mars(1,x,0);
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ TVector3 c0lt=rp->Lors2Mars(0,0,y); TVector3 c0rt=rp->Lors2Mars(0,x,y);
+ TVector3 c0ce=rp->Lors2Mars(0,x/2,y/2);
+ TVector3 c0lb=rp->Lors2Mars(0,0,0); TVector3 c0rb=rp->Lors2Mars(0,x,0);
+
+
+ Printf("\n\n\n");
+
+ Printf("_______________________________ _______________________________");
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lt.Mag() ,c6rt.Mag() ,c5lt.Mag() ,c5rt.Mag() );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lt.Theta()*r2d ,c6rt.Theta()*r2d ,c5lt.Theta()*r2d ,c5rt.Theta()*r2d );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lt.Phi()*r2d ,c6rt.Phi()*r2d ,c5lt.Phi()*r2d ,c5rt.Phi()*r2d );
+ Printf("| | | |");
+ Printf("| %7.2f | | %7.2f | Sensitive area (130.60,126.16)" ,c6ce.Mag() ,c5ce.Mag() );
+ Printf("| %7.2f | | %7.2f | Lors Center ( 65.30, 63.08)" ,c6ce.Theta()*r2d ,c5ce.Theta()*r2d );
+ Printf("| %7.2f | | %7.2f |" ,c6ce.Phi()*r2d ,c5ce.Phi()*r2d );
+ Printf("| | | |");
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lb.Mag() ,c6rb.Mag() ,c5lb.Mag() ,c5rb.Mag() );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lb.Theta()*r2d ,c6rb.Theta()*r2d ,c5lb.Theta()*r2d ,c5rb.Theta()*r2d );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f|",c6lb.Phi()*r2d ,c6rb.Phi()*r2d ,c5lb.Phi()*r2d ,c5rb.Phi()*r2d );
+ Printf("------------------------------- -------------------------------");
+ Printf("");
+ Printf("_______________________________ _______________________________ _______________________________");
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lt.Mag() ,c4rt.Mag() ,c3lt.Mag() ,c3rt.Mag() ,c2lt.Mag() ,c2rt.Mag() );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lt.Theta()*r2d,c4rt.Theta()*r2d,c3lt.Theta()*r2d,c3rt.Theta()*r2d,c2lt.Theta()*r2d ,c2rt.Theta()*r2d);
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lt.Phi()*r2d ,c4rt.Phi()*r2d ,c3lt.Phi()*r2d ,c3rt.Phi()*r2d ,c2lt.Phi()*r2d ,c2rt.Phi()*r2d );
+ Printf("| | | | | |");
+ Printf("| %7.2f | | %7.2f | | %7.2f |" ,c4ce.Mag() ,c3ce.Mag() ,c2ce.Mag());
+ Printf("| %7.2f | | %7.2f | | %7.2f |" ,c4ce.Theta()*r2d,c3ce.Theta()*r2d,c2ce.Theta()*r2d);
+ Printf("| %7.2f | | %7.2f | | %7.2f |" ,c4ce.Phi()*r2d ,c3ce.Phi()*r2d ,c3ce.Phi()*r2d);
+ Printf("| | | | | |");
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lb.Mag() ,c4rb.Mag() ,c3lb.Mag() ,c3rb.Mag() ,c2lt.Mag() ,c2rt.Mag() );
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lb.Theta()*r2d,c4rb.Theta()*r2d,c3lb.Theta()*r2d,c3rb.Theta()*r2d,c2lt.Theta()*r2d ,c2rt.Theta()*r2d);
+ Printf("|%7.2f %7.2f| |%7.2f %7.2f| |%7.2f %7.2f|",c4lb.Phi()*r2d ,c4rb.Phi()*r2d ,c3lb.Phi()*r2d ,c3rb.Phi()*r2d ,c2lt.Phi()*r2d ,c2rt.Phi()*r2d );
+ Printf("------------------------------- ------------------------------- -------------------------------");
+ Printf("");
+ Printf(" _______________________________ _______________________________");
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lt.Mag() ,c1rt.Mag() ,c0lt.Mag() ,c0rt.Mag() );
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lt.Theta()*r2d,c1rt.Theta()*r2d,c0lt.Theta()*r2d,c0rt.Theta()*r2d);
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lt.Phi()*r2d ,c1rt.Phi()*r2d ,c0lt.Phi()*r2d ,c0rt.Phi()*r2d );
+ Printf(" | | | |");
+ Printf(" | %7.2f | | %7.2f |" ,c1ce.Mag() ,c0ce.Mag() );
+ Printf(" | %7.2f | | %7.2f |" ,c1ce.Theta()*r2d,c0ce.Theta()*r2d);
+ Printf(" | %7.2f | | %7.2f |" ,c1ce.Phi()*r2d ,c0ce.Phi()*r2d );
+ Printf(" | | | |");
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lb.Mag() ,c1rb.Mag() ,c0lb.Mag() ,c0rb.Mag() );
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lb.Theta()*r2d,c1rb.Theta()*r2d,c0lb.Theta()*r2d,c0rb.Theta()*r2d );
+ Printf(" |%7.2f %7.2f| |%7.2f %7.2f|",c1lb.Phi()*r2d ,c1rb.Phi()*r2d ,c0lb.Phi()*r2d ,c0rb.Phi()*r2d );
+ Printf(" ------------------------------- -------------------------------");
+
+
+ Double_t m[3];
+ for(int i=0;i<1000;i++){
+ Float_t xout=0,xin=gRandom->Rndm()*130.60;
+ Float_t yout=0,yin=gRandom->Rndm()*126.16;
+ Int_t c=gRandom->Rndm()*6;
+ rp->Lors2Mars(c,xin,yin,m);
+ rp->Mars2Lors(c,m,xout,yout);
+ if( (xin-xout) != 0) Printf("Problem in X");
+ if( (yin-yout) != 0) Printf("Problem in Y");
+ }
+}//print()
+
+
+void rec()
+{
+ Double_t th=8*TMath::DegToRad();//gRandom->Rndm()*TMath::PiOver4();
+ Double_t ph=gRandom->Rndm()*TMath::TwoPi(); 172.51*TMath::DegToRad();
+ Double_t x=gRandom->Rndm()*AliHMPIDDigit::SizeAllX(); //101.59;
+ Double_t y=gRandom->Rndm()*2*AliHMPIDDigit::SizePcY();//38.06;
+
+
+ Double_t ckovMax=0.75,ckovSim;
+ Int_t nSim=0;
+ while(nSim<3){
+ ckovSim=gRandom->Rndm()*ckovMax;//0.6468;
+ nSim=20*TMath::Power(TMath::Sin(ckovSim)/TMath::Sin(ckovMax),2); //scale number of photons
+ }
+
+
+ TClonesArray *pCluLst=new TClonesArray("AliHMPIDCluster");
+ TPolyMarker *pMipMap=new TPolyMarker(); pMipMap->SetMarkerStyle(8); pMipMap->SetMarkerColor(kRed);
+ TPolyMarker *pPhoMap=new TPolyMarker(); pPhoMap->SetMarkerStyle(4); pPhoMap->SetMarkerColor(kRed);
+ TPolyMarker *pBkgMap=new TPolyMarker(); pBkgMap->SetMarkerStyle(25); pBkgMap->SetMarkerColor(kRed);
+ TPolyLine *pRing =new TPolyLine; pRing->SetLineColor(kGreen);
+ TPolyLine *pOld =new TPolyLine; pOld->SetLineColor(kBlue);
+
+ Int_t iCluCnt=0; pMipMap->SetPoint(iCluCnt,x,y); new((*pCluLst)[iCluCnt++]) AliHMPIDCluster(1,x,y,200); //add mip cluster
+
+// for(int j=0;j<30;j++){ //add bkg photons
+// Float_t bkgX=gRandom->Rndm()*AliHMPIDDigit::SizeAllX();
+// Float_t bkgY=gRandom->Rndm()*AliHMPIDDigit::SizeAllY();
+// pBkgMap->SetPoint(iCluCnt,bkgX,bkgY); new((*pCluLst)[iCluCnt++]) AliHMPIDCluster(1,bkgX,bkgY,35);
+// }
+
+
+
+
+ AliHMPIDRecon rec; rec.SetTrack(th,ph,x,y);
+ AliHMPIDReconOld old; old.SetTrack(th,ph,x,y);
+
+ TVector2 pos;
+ for(int i=0;i<nSim;i++){
+ rec.TracePhot(ckovSim,gRandom->Rndm()*2*TMath::Pi(),pos); //add photons
+ if(AliHMPIDDigit::IsInDead(pos.X(),pos.Y())) continue;
+ pPhoMap->SetPoint(iCluCnt,pos.X(),pos.Y()); new((*pCluLst)[iCluCnt++]) AliHMPIDCluster(1,pos.X(),pos.Y(),35);
+ }
+
+ for(int i=0;i<pCluLst->GetEntries();i++){
+ AliHMPIDCluster *pClu=(AliHMPIDCluster*)pCluLst->At(i);
+ Printf("diff phi %f ckov new %f ckov old %f",rec.FindPhotPhi(pClu->X(),pClu->Y())-old.FindPhotPhi(pClu->X(),pClu->Y()),rec.FindPhotCkov(pClu->X(),pClu->Y()),old.FindPhotCkov(pClu->X(),pClu->Y()));
+ }
+
+ Int_t nRec=0,nOld=0;
+ Double_t ckovRec=rec.CkovAngle(pCluLst,nRec); Double_t err=TMath::Sqrt(rec.CkovSigma2());
+ Double_t ckovOld=old.CkovAngle(pCluLst,nOld);
+
+ Printf("---------------- Now reconstructed --------------------");
+
+
+ for(int j=0;j<100;j++){rec.TracePhot(ckovRec,j*0.0628,pos); pRing->SetPoint(j,pos.X(),pos.Y());}
+ for(int j=0;j<100;j++){rec.TracePhot(ckovOld,j*0.0628,pos); pOld->SetPoint(j,pos.X(),pos.Y());}
+
+ new TCanvas; AliHMPIDDigit::DrawPc(); pMipMap->Draw(); pPhoMap->Draw(); pBkgMap->Draw(); pRing->Draw(); pOld->Draw();
+
+ TLatex txt; txt.SetTextSize(0.03);
+ txt.DrawLatex(65,127,Form("#theta=%.4f#pm%.5f with %2i #check{C}" ,ckovSim, 0.,nSim ));
+ txt.DrawLatex(65,122,Form("#theta=%.4f#pm%.5f with %2i #check{C} Old=%.4f with %i #check{C}" ,ckovRec,err,nRec,ckovOld,nOld));
+ txt.DrawLatex(0 ,127,Form("#theta=%.2f#circ #phi=%.2f#circ @(%.2f,%.2f) ",th*TMath::RadToDeg(),ph*TMath::RadToDeg(),x,y));
+
+// for(int i=0;i<35;i++){
+// Double_t ckov=0.1+i*0.02;
+// Printf("Ckov=%.2f Old=%.3f New=%.3f",ckov,old.FindRingArea(ckov),rec.FindRingArea(ckov));
+// }
+
+
+}//rec()
+
+AliHMPIDRecon rec; AliHMPIDReconOld old;
+
+void aaa()
+{
+ rec.SetTrack(10*TMath::DegToRad(),1,30,60); old.SetTrack(10*TMath::DegToRad(),1,30,60);
+ TVector2 pos;
+ Double_t ckovSim=0.6234;
+ rec.TracePhot(ckovSim,1,pos);
+ Printf("ckovSim %f",ckovSim);
+ double ckovRec=rec.FindPhotCkov(pos.X(),pos.Y());
+ double ckovOld=old.FindPhotCkov(pos.X(),pos.Y());
+ Printf("new %f old %f",ckovRec,ckovOld);
+}
+
+
+
+
+
+
+
+void AliHMPID::HitQA(Double_t cut,Double_t cutele,Double_t cutR)
+{
+// Provides a set of control plots intended primarily for charged particle flux analisys
+// Arguments: cut (GeV) - cut on momentum of any charged particles but electrons,
+// cetele (GeV) - the same for electrons-positrons
+// cutR (cm) - cut on production vertex radius (cylindrical system)
+ gBenchmark->Start("HitsAna");
+
+ Double_t cutPantiproton =cut;
+ Double_t cutPkaonminus =cut;
+ Double_t cutPpionminus =cut;
+ Double_t cutPmuonminus =cut;
+ Double_t cutPpositron =cutele;
+
+ Double_t cutPelectron =cutele;
+ Double_t cutPmuonplus =cut;
+ Double_t cutPpionplus =cut;
+ Double_t cutPkaonplus =cut;
+ Double_t cutPproton =cut;
+
+
+ TH2F *pEleHitRZ =new TH2F("EleHitRZ" ,Form("e^{+} e^{-} hit %s;z[cm];R[cm]" ,GetName()) , 400,-300,300 ,400,-500,500); //R-z plot 0cm<R<550cm -300cm<z<300cm
+ TH2F *pEleHitRP =new TH2F("EleHitRP" ,Form("e^{+} e^{-} hit %s;p[GeV];R[cm]",GetName()) ,1000,-1 ,1 ,400, 0,550); //R-p plot 0cm<R<550cm -1GeV<p<1GeV
+ TH1F *pEleAllP =new TH1F("EleAllP" , "e^{+} e^{-} all;p[GeV]" ,1000,-1 ,1 );
+ TH1F *pEleHitP =new TH1F("EleHitP" ,Form("e^{+} e^{-} hit %s;p[GeV]" ,GetName()) ,1000,-1 ,1 );
+ TH1F *pMuoHitP =new TH1F("MuoHitP" ,Form("#mu^{-} #mu^{+} hit %s;p[GeV]" ,GetName()) ,1000,-4 ,4 );
+ TH1F *pPioHitP =new TH1F("PioHitP" ,Form("#pi^{-} #pi^{+} hit %s;p[GeV]" ,GetName()) ,1000,-4 ,4 );
+ TH1F *pKaoHitP =new TH1F("KaoHitP" ,Form("K^{-} K^{+} hit %s;p[GeV]" ,GetName()) ,1000,-4 ,4 );
+ TH1F *pProHitP =new TH1F("ProHitP" ,Form("p^{-} p^{+} hit %s;p[GeV]" ,GetName()) ,1000,-4 ,4 );
+ TH2F *pFlux =new TH2F("flux" ,Form("%s flux with Rvertex<%.1fcm" ,GetName(),cutR),10 ,-5 ,5 , 10,0 ,10); //special text hist
+ TH2F *pVertex =new TH2F("vertex" ,Form("%s 2D vertex of HMPID hit;x;y" ,GetName()) ,120 ,0 ,600 ,120,0 ,600); //special text hist
+ TH1F *pRho =new TH1F("rho" ,Form("%s r of HMPID hit" ,GetName()) ,600 ,0 ,600); //special text hist
+ pFlux->SetStats(0);
+ pFlux->GetXaxis()->SetBinLabel(1 ,Form("p^{-}>%.3fGeV/c" ,cutPantiproton));
+ pFlux->GetXaxis()->SetBinLabel(2 ,Form("K^{-}>%.3fGeV/c" ,cutPkaonminus ));
+ pFlux->GetXaxis()->SetBinLabel(3 ,Form("#pi^{-}>%.3fGeV/c" ,cutPpionminus ));
+ pFlux->GetXaxis()->SetBinLabel(4 ,Form("#mu^{-}>%.3fGeV/c" ,cutPmuonminus ));
+ pFlux->GetXaxis()->SetBinLabel(5 ,Form("e^{+}>%.3fGeV/c" ,cutPpositron ));
+
+ pFlux->GetXaxis()->SetBinLabel(6 ,Form("e^{-}>%.3fGeV/c" ,cutPelectron ));
+ pFlux->GetXaxis()->SetBinLabel(7 ,Form("#mu^{+}>%.3fGeV/c" ,cutPmuonplus ));
+ pFlux->GetXaxis()->SetBinLabel(8 ,Form("#pi^{+}>%.3fGeV/c" ,cutPpionplus ));
+ pFlux->GetXaxis()->SetBinLabel(9 ,Form("K^{+}>%.3fGeV/c" ,cutPkaonplus ));
+ pFlux->GetXaxis()->SetBinLabel(10,Form("p^{+}>%.3fGeV/c" ,cutPproton ));
+
+ pFlux->GetYaxis()->SetBinLabel(1,"sum");
+ pFlux->GetYaxis()->SetBinLabel(2,"ch1");
+ pFlux->GetYaxis()->SetBinLabel(3,"ch2");
+ pFlux->GetYaxis()->SetBinLabel(4,"ch3");
+ pFlux->GetYaxis()->SetBinLabel(5,"ch4");
+ pFlux->GetYaxis()->SetBinLabel(6,"ch5");
+ pFlux->GetYaxis()->SetBinLabel(7,"ch6");
+ pFlux->GetYaxis()->SetBinLabel(8,"ch7");
+ pFlux->GetYaxis()->SetBinLabel(9,"prim");
+ pFlux->GetYaxis()->SetBinLabel(10,"tot");
+
+//end of hists definition
+
+ Int_t iNevents=fLoader->GetRunLoader()->GetAliRun()->GetEventsPerRun(),iCntPrimParts=0,iCntTotParts=0;
+//load all needed trees
+ fLoader->LoadHits();
+ fLoader->GetRunLoader()->LoadHeader();
+ fLoader->GetRunLoader()->LoadKinematics();
+
+ for(Int_t iEvtN=0;iEvtN < iNevents;iEvtN++){//events loop
+ fLoader->GetRunLoader()->GetEvent(iEvtN);
+ AliInfo(Form(" %i event processes",fLoader->GetRunLoader()->GetEventNumber()));
+ AliStack *pStack= fLoader->GetRunLoader()->Stack();
+
+ for(Int_t iParticleN=0;iParticleN<pStack->GetNtrack();iParticleN++){//stack loop
+ TParticle *pPart=pStack->Particle(iParticleN);
+
+ if(iParticleN%10000==0) AliInfo(Form(" %i particles read",iParticleN));
+
+ switch(pPart->GetPdgCode()){
+ case kProtonBar: pFlux->Fill(-4.5,9); if(pPart->Rho()<0.01) pFlux->Fill(-4.5,8); break;
+ case kKMinus: pFlux->Fill(-3.5,9); if(pPart->Rho()<0.01) pFlux->Fill(-3.5,8); break;
+ case kPiMinus: pFlux->Fill(-2.5,9); if(pPart->Rho()<0.01) pFlux->Fill(-2.5,8); break;
+ case kMuonMinus: pFlux->Fill(-1.5,9); if(pPart->Rho()<0.01) pFlux->Fill(-1.5,8); break;
+ case kPositron: pFlux->Fill(-0.5,9); if(pPart->Rho()<0.01) pFlux->Fill(-0.5,8); pEleAllP->Fill(-pPart->P()); break;
+
+ case kElectron: pFlux->Fill( 0.5,9); if(pPart->Rho()<0.01) pFlux->Fill( 0.5,8); pEleAllP->Fill( pPart->P()); break;
+ case kMuonPlus: pFlux->Fill( 1.5,9); if(pPart->Rho()<0.01) pFlux->Fill( 1.5,8); break;
+ case kPiPlus: pFlux->Fill( 2.5,9); if(pPart->Rho()<0.01) pFlux->Fill( 2.5,8); break;
+ case kKPlus: pFlux->Fill( 3.5,9); if(pPart->Rho()<0.01) pFlux->Fill( 3.5,8); break;
+ case kProton: pFlux->Fill( 4.5,9); if(pPart->Rho()<0.01) pFlux->Fill( 4.5,8); break;
+ }//switch
+ }//stack loop
+//now hits analiser
+ for(Int_t iEntryN=0;iEntryN < fLoader->TreeH()->GetEntries();iEntryN++){//TreeH loop
+ fLoader->TreeH()->GetEntry(iEntryN); //get current entry (prim)
+ for(Int_t iHitN=0;iHitN < Hits()->GetEntries();iHitN++){//hits loop
+ AliHMPIDHit *pHit = (AliHMPIDHit*)Hits()->At(iHitN); //get current hit
+ TParticle *pPart=pStack->Particle(pHit->GetTrack()); //get stack particle which produced the current hit
+
+ if(pPart->GetPDG()->Charge()!=0&&pPart->Rho()>0.1) pVertex->Fill(pPart->Vx(),pPart->Vy()); //safe margin for sec.
+ if(pPart->GetPDG()->Charge()!=0) pRho->Fill(pPart->Rho()); //safe margin for sec.
+ if(pPart->R()>cutR) continue; //cut on production radius (cylindrical system)
+
+ switch(pPart->GetPdgCode()){
+ case kProtonBar: if(pPart->P()>cutPantiproton) {pProHitP->Fill(-pPart->P()); pFlux->Fill(-4.5,pHit->Ch());}break;
+ case kKMinus : if(pPart->P()>cutPkaonminus) {pKaoHitP->Fill(-pPart->P()); pFlux->Fill(-3.5,pHit->Ch());}break;
+ case kPiMinus : if(pPart->P()>cutPpionminus) {pPioHitP->Fill(-pPart->P()); pFlux->Fill(-2.5,pHit->Ch());}break;
+ case kMuonMinus: if(pPart->P()>cutPmuonminus) {pMuoHitP->Fill(-pPart->P()); pFlux->Fill(-1.5,pHit->Ch());}break;
+ case kPositron : if(pPart->P()>cutPpositron) {pEleHitP->Fill(-pPart->P()); pFlux->Fill(-0.5,pHit->Ch());
+ pEleHitRP->Fill(-pPart->P(),pPart->R()); pEleHitRZ->Fill(pPart->Vz(),pPart->R()); }break;
+
+ case kElectron : if(pPart->P()>cutPelectron) {pEleHitP->Fill( pPart->P()); pFlux->Fill( 0.5,pHit->Ch());
+ pEleHitRP->Fill( pPart->P(),pPart->R()); pEleHitRZ->Fill(pPart->Vz(),pPart->R()); }break;
+ case kMuonPlus : if(pPart->P()>cutPmuonplus) {pMuoHitP->Fill( pPart->P()); pFlux->Fill( 1.5,pHit->Ch());}break;
+ case kPiPlus : if(pPart->P()>cutPpionplus) {pPioHitP->Fill( pPart->P()); pFlux->Fill( 2.5,pHit->Ch());}break;
+ case kKPlus : if(pPart->P()>cutPkaonplus) {pKaoHitP->Fill( pPart->P()); pFlux->Fill( 3.5,pHit->Ch());}break;
+ case kProton : if(pPart->P()>cutPproton) {pProHitP->Fill( pPart->P()); pFlux->Fill( 4.5,pHit->Ch());}break;
+ }
+ }//hits loop
+ }//TreeH loop
+ iCntPrimParts +=pStack->GetNprimary();
+ iCntTotParts +=pStack->GetNtrack();
+ }//events loop
+//unload all loaded staff
+ fLoader->UnloadHits();
+ fLoader->GetRunLoader()->UnloadHeader();
+ fLoader->GetRunLoader()->UnloadKinematics();
+//Calculater some sums
+ Stat_t sum=0;
+//sum row, sum over rows
+ for(Int_t i=1;i<=pFlux->GetNbinsX();i++){
+ sum=0; for(Int_t j=2;j<=8;j++) sum+=pFlux->GetBinContent(i,j);
+ pFlux->SetBinContent(i,1,sum);
+ }
+
+//display everything
+ new TCanvas("canvas1",Form("Events %i Nprims=%i Nparticles=%i",iNevents,iCntPrimParts,iCntTotParts),1000,900); pFlux->Draw("text"); gPad->SetGrid();
+//total prims and particles
+ TLatex latex; latex.SetTextSize(0.02);
+ sum=0; for(Int_t i=1;i<=pFlux->GetNbinsX();i++) sum+=pFlux->GetBinContent(i,10); latex.DrawLatex(5.1,9.5,Form("%.0f",sum));
+ sum=0; for(Int_t i=1;i<=pFlux->GetNbinsX();i++) sum+=pFlux->GetBinContent(i,9); latex.DrawLatex(5.1,8.5,Form("%.0f",sum));
+ for(Int_t iCh=0;iCh<7;iCh++) {
+ sum=0; for(Int_t i=1;i<=pFlux->GetNbinsX();i++) sum+=pFlux->GetBinContent(i,iCh+2);latex.DrawLatex(5.1,iCh+1.5,Form("%.0f",sum));
+ }
+ sum=0; for(Int_t i=1;i<=pFlux->GetNbinsX();i++) sum+=pFlux->GetBinContent(i,1); latex.DrawLatex(5.1,0.5,Form("%.0f",sum));
+
+ new TCanvas("cEleAllP" ,"e" ,200,100); pEleAllP->Draw();
+ new TCanvas("cEleHitRP" ,"e" ,200,100); pEleHitRP->Draw();
+ new TCanvas("cEleHitRZ" ,"e" ,200,100); pEleHitRZ->Draw();
+ new TCanvas("cEleHitP" ,"e" ,200,100); pEleHitP->Draw();
+ new TCanvas("cMuoHitP" ,"mu",200,100); pMuoHitP->Draw();
+ new TCanvas("cPioHitP" ,"pi",200,100); pPioHitP->Draw();
+ new TCanvas("cKaoHitP" ,"K" ,200,100); pKaoHitP->Draw();
+ new TCanvas("cProHitP" ,"p" ,200,100); pProHitP->Draw();
+ new TCanvas("cVertex" ,"2d vertex" ,200,100); pVertex->Draw();
+ new TCanvas("cRho" ,"Rho of sec" ,200,100); pRho->Draw();
+
+ gBenchmark->Show("HitsPlots");
+}//HitQA()
+
+
+
+
+
--- /dev/null
+void RichTestShuttle()
+{
+// this macro is to simulate the functionality of SHUTTLE.
+// Here the list of DCS aliases is created and packed in TMap of structure "alias name" - TObjArray of AliDCSValue
+ TMultiGraph *pMG[7]; for(Int_t i=0;i<7;i++) {pMG[i]=new TMultiGraph; pMG[i]->SetTitle("T,grad C;time");}
+ TGraph *pGr[21];for(Int_t i=0;i<21;i++){pGr[i]=new TGraph; pGr[i]->SetMarkerStyle(i%3+24); pGr[i]->SetMarkerColor(i%3+2); pMG[i/3]->Add(pGr[i]);}
+ TMap *pDcsMap = new TMap; pDcsMap->SetOwner(1); //DCS archive map
+
+ for(Int_t iCh=0;iCh<7;iCh++){//chambers loop
+ for(Int_t iRad=0;iRad<3;iRad++){//radiators loop
+ TObjArray* pValLst = new TObjArray; pValLst->SetOwner(1);
+ Int_t iPoint=0;
+ for (Int_t time=0;time<1000;time+=50) {
+ AliDCSValue* pVal = new AliDCSValue(Float_t(iCh*3+iRad+0.1*gRandom->Gaus()), time); //sample new data point
+ pValLst->Add(pVal); //add it to the list
+ pGr[3*iCh+iRad]->SetPoint(iPoint++,time,pVal->GetFloat()); //and also to the graph