This commit was generated by cvs2svn to compensate for changes in r15977,
authorhristov <hristov@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 29 Nov 2006 09:14:09 +0000 (09:14 +0000)
committerhristov <hristov@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 29 Nov 2006 09:14:09 +0000 (09:14 +0000)
which included commits to RCS files with non-trunk default branches.

49 files changed:
HMPID/AliHMPID.cxx [new file with mode: 0644]
HMPID/AliHMPID.h [new file with mode: 0644]
HMPID/AliHMPIDCluster.cxx [new file with mode: 0644]
HMPID/AliHMPIDCluster.h [new file with mode: 0644]
HMPID/AliHMPIDDigit.cxx [new file with mode: 0644]
HMPID/AliHMPIDDigit.h [new file with mode: 0644]
HMPID/AliHMPIDDigitN.cxx [new file with mode: 0644]
HMPID/AliHMPIDDigitN.h [new file with mode: 0644]
HMPID/AliHMPIDDigitizer.cxx [new file with mode: 0644]
HMPID/AliHMPIDDigitizer.h [new file with mode: 0644]
HMPID/AliHMPIDHelix.cxx [new file with mode: 0644]
HMPID/AliHMPIDHelix.h [new file with mode: 0644]
HMPID/AliHMPIDHit.cxx [new file with mode: 0644]
HMPID/AliHMPIDHit.h [new file with mode: 0644]
HMPID/AliHMPIDParam.cxx [new file with mode: 0644]
HMPID/AliHMPIDParam.h [new file with mode: 0644]
HMPID/AliHMPIDPreprocessor.cxx [new file with mode: 0644]
HMPID/AliHMPIDPreprocessor.h [new file with mode: 0644]
HMPID/AliHMPIDRecon.cxx [new file with mode: 0644]
HMPID/AliHMPIDRecon.h [new file with mode: 0644]
HMPID/AliHMPIDReconstructor.cxx [new file with mode: 0644]
HMPID/AliHMPIDReconstructor.h [new file with mode: 0644]
HMPID/AliHMPIDSelector.C [new file with mode: 0644]
HMPID/AliHMPIDTracker.cxx [new file with mode: 0644]
HMPID/AliHMPIDTracker.h [new file with mode: 0644]
HMPID/AliHMPIDv0.cxx [new file with mode: 0644]
HMPID/AliHMPIDv0.h [new file with mode: 0644]
HMPID/AliHMPIDv1.cxx [new file with mode: 0644]
HMPID/AliHMPIDv1.h [new file with mode: 0644]
HMPID/Align/Data/Run0_9999999_v0_s0.root [new file with mode: 0644]
HMPID/HMPIDAlign.C [new file with mode: 0644]
HMPID/HMPIDAna.C [new file with mode: 0644]
HMPID/HMPIDConfig.C [new file with mode: 0644]
HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s0.root [new file with mode: 0644]
HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s1.root [new file with mode: 0644]
HMPID/HMPIDGeom.C [new file with mode: 0644]
HMPID/HMPIDMake [new file with mode: 0644]
HMPID/HMPIDMenu.C [new file with mode: 0644]
HMPID/HMPIDTestShuttle.C [new file with mode: 0644]
HMPID/HMPIDbaseLinkDef.h [new file with mode: 0644]
HMPID/HMPIDrecLinkDef.h [new file with mode: 0644]
HMPID/HMPIDsimLinkDef.h [new file with mode: 0644]
HMPID/MakeHMPIDFullMisAlignment.C [new file with mode: 0644]
HMPID/MakeHMPIDResMisAlignment.C [new file with mode: 0644]
HMPID/api.txt [new file with mode: 0644]
HMPID/libHMPIDbase.pkg [new file with mode: 0644]
HMPID/libHMPIDrec.pkg [new file with mode: 0644]
HMPID/libHMPIDsim.pkg [new file with mode: 0644]
HMPID/red.C [new file with mode: 0644]

diff --git a/HMPID/AliHMPID.cxx b/HMPID/AliHMPID.cxx
new file mode 100644 (file)
index 0000000..a11e9f0
--- /dev/null
@@ -0,0 +1,240 @@
+//  **************************************************************************
+//  * 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();
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPID.h b/HMPID/AliHMPID.h
new file mode 100644 (file)
index 0000000..89812cb
--- /dev/null
@@ -0,0 +1,63 @@
+#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
diff --git a/HMPID/AliHMPIDCluster.cxx b/HMPID/AliHMPIDCluster.cxx
new file mode 100644 (file)
index 0000000..70cd58b
--- /dev/null
@@ -0,0 +1,148 @@
+//  **************************************************************************
+//  * 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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDCluster.h b/HMPID/AliHMPIDCluster.h
new file mode 100644 (file)
index 0000000..99bebfe
--- /dev/null
@@ -0,0 +1,60 @@
+#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
diff --git a/HMPID/AliHMPIDDigit.cxx b/HMPID/AliHMPIDDigit.cxx
new file mode 100644 (file)
index 0000000..6df0e81
--- /dev/null
@@ -0,0 +1,198 @@
+//  **************************************************************************
+//  * 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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDDigit.h b/HMPID/AliHMPIDDigit.h
new file mode 100644 (file)
index 0000000..bf89f76
--- /dev/null
@@ -0,0 +1,176 @@
+#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
diff --git a/HMPID/AliHMPIDDigitN.cxx b/HMPID/AliHMPIDDigitN.cxx
new file mode 100644 (file)
index 0000000..3aa1fe2
--- /dev/null
@@ -0,0 +1,168 @@
+//  **************************************************************************
+//  * 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()
diff --git a/HMPID/AliHMPIDDigitN.h b/HMPID/AliHMPIDDigitN.h
new file mode 100644 (file)
index 0000000..260f29f
--- /dev/null
@@ -0,0 +1,90 @@
+#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
diff --git a/HMPID/AliHMPIDDigitizer.cxx b/HMPID/AliHMPIDDigitizer.cxx
new file mode 100644 (file)
index 0000000..6b41fb2
--- /dev/null
@@ -0,0 +1,104 @@
+/**************************************************************************
+ * 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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDDigitizer.h b/HMPID/AliHMPIDDigitizer.h
new file mode 100644 (file)
index 0000000..4ab8033
--- /dev/null
@@ -0,0 +1,24 @@
+#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
diff --git a/HMPID/AliHMPIDHelix.cxx b/HMPID/AliHMPIDHelix.cxx
new file mode 100644 (file)
index 0000000..8e57efa
--- /dev/null
@@ -0,0 +1,25 @@
+#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();
+}
diff --git a/HMPID/AliHMPIDHelix.h b/HMPID/AliHMPIDHelix.h
new file mode 100644 (file)
index 0000000..bd0db62
--- /dev/null
@@ -0,0 +1,71 @@
+#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
diff --git a/HMPID/AliHMPIDHit.cxx b/HMPID/AliHMPIDHit.cxx
new file mode 100644 (file)
index 0000000..6390076
--- /dev/null
@@ -0,0 +1,43 @@
+//  **************************************************************************
+//  * 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());
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDHit.h b/HMPID/AliHMPIDHit.h
new file mode 100644 (file)
index 0000000..3feeea8
--- /dev/null
@@ -0,0 +1,35 @@
+#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
diff --git a/HMPID/AliHMPIDParam.cxx b/HMPID/AliHMPIDParam.cxx
new file mode 100644 (file)
index 0000000..c264b68
--- /dev/null
@@ -0,0 +1,99 @@
+//  **************************************************************************
+//  * 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;
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDParam.h b/HMPID/AliHMPIDParam.h
new file mode 100644 (file)
index 0000000..8b16361
--- /dev/null
@@ -0,0 +1,57 @@
+#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
diff --git a/HMPID/AliHMPIDPreprocessor.cxx b/HMPID/AliHMPIDPreprocessor.cxx
new file mode 100644 (file)
index 0000000..6198ce6
--- /dev/null
@@ -0,0 +1,75 @@
+#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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDPreprocessor.h b/HMPID/AliHMPIDPreprocessor.h
new file mode 100644 (file)
index 0000000..2648875
--- /dev/null
@@ -0,0 +1,19 @@
+#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
diff --git a/HMPID/AliHMPIDRecon.cxx b/HMPID/AliHMPIDRecon.cxx
new file mode 100644 (file)
index 0000000..a005e4e
--- /dev/null
@@ -0,0 +1,442 @@
+/**************************************************************************
+ * 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()
diff --git a/HMPID/AliHMPIDRecon.h b/HMPID/AliHMPIDRecon.h
new file mode 100644 (file)
index 0000000..394995f
--- /dev/null
@@ -0,0 +1,71 @@
+#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
+
diff --git a/HMPID/AliHMPIDReconstructor.cxx b/HMPID/AliHMPIDReconstructor.cxx
new file mode 100644 (file)
index 0000000..2b3d96c
--- /dev/null
@@ -0,0 +1,237 @@
+/**************************************************************************
+ * 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
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDReconstructor.h b/HMPID/AliHMPIDReconstructor.h
new file mode 100644 (file)
index 0000000..ccf3c15
--- /dev/null
@@ -0,0 +1,54 @@
+#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
diff --git a/HMPID/AliHMPIDSelector.C b/HMPID/AliHMPIDSelector.C
new file mode 100644 (file)
index 0000000..841e640
--- /dev/null
@@ -0,0 +1,186 @@
+#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");
+}
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
diff --git a/HMPID/AliHMPIDTracker.cxx b/HMPID/AliHMPIDTracker.cxx
new file mode 100644 (file)
index 0000000..46a1da7
--- /dev/null
@@ -0,0 +1,112 @@
+#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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDTracker.h b/HMPID/AliHMPIDTracker.h
new file mode 100644 (file)
index 0000000..116aec3
--- /dev/null
@@ -0,0 +1,28 @@
+#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
diff --git a/HMPID/AliHMPIDv0.cxx b/HMPID/AliHMPIDv0.cxx
new file mode 100644 (file)
index 0000000..8fb2ea1
--- /dev/null
@@ -0,0 +1,26 @@
+//**************************************************************************
+//  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()
diff --git a/HMPID/AliHMPIDv0.h b/HMPID/AliHMPIDv0.h
new file mode 100644 (file)
index 0000000..0850054
--- /dev/null
@@ -0,0 +1,22 @@
+#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
diff --git a/HMPID/AliHMPIDv1.cxx b/HMPID/AliHMPIDv1.cxx
new file mode 100644 (file)
index 0000000..7ff7967
--- /dev/null
@@ -0,0 +1,657 @@
+// **************************************************************************
+// * 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()
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/HMPID/AliHMPIDv1.h b/HMPID/AliHMPIDv1.h
new file mode 100644 (file)
index 0000000..33a8cc4
--- /dev/null
@@ -0,0 +1,42 @@
+#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
diff --git a/HMPID/Align/Data/Run0_9999999_v0_s0.root b/HMPID/Align/Data/Run0_9999999_v0_s0.root
new file mode 100644 (file)
index 0000000..1436080
Binary files /dev/null and b/HMPID/Align/Data/Run0_9999999_v0_s0.root differ
diff --git a/HMPID/HMPIDAlign.C b/HMPID/HMPIDAlign.C
new file mode 100644 (file)
index 0000000..e8e1897
--- /dev/null
@@ -0,0 +1,28 @@
+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();
+}
diff --git a/HMPID/HMPIDAna.C b/HMPID/HMPIDAna.C
new file mode 100644 (file)
index 0000000..f4ca4ce
--- /dev/null
@@ -0,0 +1,68 @@
+//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"); 
+}   
diff --git a/HMPID/HMPIDConfig.C b/HMPID/HMPIDConfig.C
new file mode 100644 (file)
index 0000000..e4bfa40
--- /dev/null
@@ -0,0 +1,620 @@
+#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");
+}   
diff --git a/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s0.root b/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s0.root
new file mode 100644 (file)
index 0000000..bc34bea
Binary files /dev/null and b/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s0.root differ
diff --git a/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s1.root b/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s1.root
new file mode 100644 (file)
index 0000000..efb5367
Binary files /dev/null and b/HMPID/HMPIDConfig/RefIdxC6F14/Run0_0_v0_s1.root differ
diff --git a/HMPID/HMPIDGeom.C b/HMPID/HMPIDGeom.C
new file mode 100644 (file)
index 0000000..fe46f4f
--- /dev/null
@@ -0,0 +1,434 @@
+
+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();  
+}
+//__________________________________________________________________________________________________
diff --git a/HMPID/HMPIDMake b/HMPID/HMPIDMake
new file mode 100644 (file)
index 0000000..b008622
--- /dev/null
@@ -0,0 +1,135 @@
+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) 
diff --git a/HMPID/HMPIDMenu.C b/HMPID/HMPIDMenu.C
new file mode 100644 (file)
index 0000000..16ccc7e
--- /dev/null
@@ -0,0 +1,501 @@
+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()
+
+
+
+
+
diff --git a/HMPID/HMPIDTestShuttle.C b/HMPID/HMPIDTestShuttle.C
new file mode 100644 (file)
index 0000000..2fb1f0e
--- /dev/null
@@ -0,0 +1,62 @@
+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  
+      }
+      pDcsMap->Add(new TObjString(Form("HMP_DET/HMP_MP%i/HMP_MP%i_LIQ_LOOP.actual.sensors.Rad%iIn_Temp",iCh,iCh,iRad)),pValLst); //add new list to the map
+    }//radiators loop
+  }//chambers loop
+  
+  
+  AliCDBManager::Instance()->SetDefaultStorage("local://$HOME/tstCDB"); // initialize location of CDB
+      
+  gSystem->Load("libTestShuttle.so"); 
+  Int_t iRun=1;   
+  AliTestShuttle* pShuttle = new AliTestShuttle(iRun,0,100000);   
+  pShuttle->SetDCSInput(pDcsMap);                                                    //DCS map
+  AliPreprocessor* pp = new AliHMPIDPreprocessor(pShuttle);                           //actual ipreprocessor is created here
+  pShuttle->Process();                                                               //run SHUTTLE simulator
+  delete pp;
+  
+    
+  AliCDBEntry *pTempEn=AliCDBManager::Instance()->Get("HMPID/DCS/RadTemp",iRun);
+  if(!pTempEn) {Printf("ERROR file is not retrieved!!!");return;}
+
+  TObjArray *pTempLst=(TObjArray*)pTempEn->GetObject(); TF1 *pRad0,*pRad1,*pRad2;  
+  TCanvas *pC=new TCanvas; pC->Divide(3,3);
+  for(Int_t iCh=0;iCh<7;iCh++){//chambers loop
+    if(iCh==6) pC->cd(1);  if(iCh==5) pC->cd(2);                          //this is just to see the input
+    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); 
+    pMG[iCh]->Draw("ap"); pMG[iCh]->GetXaxis()->SetTimeDisplay(kTRUE);
+    pRad0=(TF1*)pTempLst->At(iCh*3+0); pRad0->Draw("same");
+    pRad1=(TF1*)pTempLst->At(iCh*3+1); pRad1->Draw("same");
+    pRad2=(TF1*)pTempLst->At(iCh*3+2); pRad2->Draw("same");
+  }  
+