New version of MUON from M.Bondila & A.Morsch
authorfca <fca@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 30 Jul 1999 10:53:20 +0000 (10:53 +0000)
committerfca <fca@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 30 Jul 1999 10:53:20 +0000 (10:53 +0000)
46 files changed:
MUON/AliMUON.cxx
MUON/AliMUON.h
MUON/AliMUONClusterFinder.cxx [new file with mode: 0644]
MUON/AliMUONClusterFinder.h [new file with mode: 0644]
MUON/AliMUONClusterFinderv0.cxx [new file with mode: 0644]
MUON/AliMUONClusterFinderv0.h [new file with mode: 0644]
MUON/AliMUONConst.h
MUON/AliMUONHitMap.cxx [new file with mode: 0644]
MUON/AliMUONHitMap.h [new file with mode: 0644]
MUON/AliMUONSegRes.h [new file with mode: 0644]
MUON/AliMUONSegResV0.cxx [new file with mode: 0644]
MUON/AliMUONSegResV0.h [new file with mode: 0644]
MUON/AliMUONSegResV01.cxx [new file with mode: 0644]
MUON/AliMUONSegResV01.h [new file with mode: 0644]
MUON/AliMUONSegResV02.cxx [new file with mode: 0644]
MUON/AliMUONSegResV02.h [new file with mode: 0644]
MUON/AliMUONSegResV04.cxx [new file with mode: 0644]
MUON/AliMUONSegResV04.h [new file with mode: 0644]
MUON/AliMUONSegResV05.cxx [new file with mode: 0644]
MUON/AliMUONSegResV05.h [new file with mode: 0644]
MUON/AliMUONSegResV1.cxx [new file with mode: 0644]
MUON/AliMUONSegResV1.h [new file with mode: 0644]
MUON/AliMUONTUBE.cxx [new file with mode: 0644]
MUON/AliMUONTUBE.h [new file with mode: 0644]
MUON/AliMUONchamber.cxx [new file with mode: 0644]
MUON/AliMUONchamber.h [new file with mode: 0644]
MUON/AliMUONdisplay.cxx
MUON/AliMUONdisplay.h
MUON/AliMUONpoints.cxx
MUON/AliMUONpoints.h
MUON/AliMUONpoints.h.cxx [new file with mode: 0644]
MUON/AliMUONv0.cxx
MUON/AliMUONv0.h
MUON/MUONDigitsTestnew.C
MUON/MUONLinkDef.h
MUON/MUONcathcorel.C [new file with mode: 0644]
MUON/MUONcombi.C
MUON/MUONdigit.C
MUON/MUONdisplay.C
MUON/MUONrawclusters.C [new file with mode: 0644]
MUON/MUONtest.C
MUON/MUONtestabso.C [new file with mode: 0644]
MUON/MUONtestzaza.C [new file with mode: 0644]
MUON/Makefile
MUON/algo.F
MUON/reco_muon.F [new file with mode: 0644]

index 9606ca8..2ce4bf4 100644 (file)
 ////////////////////////////////////////////////
 
 #include <TTUBE.h>
+#include <TBRIK.h>
+#include <TRotMatrix.h>
 #include <TNode.h> 
+#include <TTree.h> 
 #include <TRandom.h> 
 #include <TObject.h>
 #include <TVector.h>
 #include <TObjArray.h>
+#include <TMinuit.h>
+#include <TParticle.h>
+#include <TROOT.h>
+#include <TFile.h>
+#include <TNtuple.h>
+#include <TCanvas.h>
+#include <TPad.h>
+#include <TDirectory.h>
+#include <TObjectTable.h>
+#include <AliPDG.h>
 
 #include "AliMUON.h"
+#include "TTUBE.h"
+#include "AliMUONClusterFinder.h"
 #include "AliRun.h"
 #include "AliMC.h"
 #include "iostream.h"
 #include "AliCallf77.h" 
 
+#ifndef WIN32 
+# define reco_init       reco_init_
+# define cutpxz          cutpxz_
+# define sigmacut        sigmacut_
+# define xpreci          xpreci_
+# define ypreci          ypreci_
+# define reconstmuon     reconstmuon_
+# define trackf_read_geant     trackf_read_geant_
+# define trackf_read_spoint     trackf_read_spoint_
+# define chfill          chfill_
+# define chfill2         chfill2_
+# define chf1            chf1_
+# define chfnt           chfnt_
+# define hist_create     hist_create_
+# define hist_closed     hist_closed_
+# define rndm            rndm_
+# define fcn             fcn_
+# define trackf_fit      trackf_fit_
+# define prec_fit        prec_fit_
+# define fcnfit          fcnfit_
+# define reco_term       reco_term_
+#else 
+# define reco_init       RECO_INIT
+# define cutpxz          CUTPXZ
+# define sigmacut        SIGMACUT
+# define xpreci          XPRECI
+# define ypreci          YPRECI
+# define reconstmuon     RECONSTMUON
+# define trackf_read_geant     TRACKF_READ_GEANT
+# define trackf_read_spoint     TRACKF_READ_SPOINT
+# define chfill          CHFILL
+# define chfill2         CHFILL2
+# define chf1            CHF1
+# define chfnt           CHFNT
+# define hist_create     HIST_CREATE
+# define hist_closed     HIST_CLOSED
+# define rndm            RNDM
+# define fcn             FCN
+# define trackf_fit      TRACKF_FIT
+# define prec_fit        PREC_FIT
+# define fcnfit          FCNFIT
+# define reco_term       RECO_TERM
+#endif 
+
+extern "C"
+{
+void type_of_call reco_init(Double_t &, Double_t &, Double_t &);
+void type_of_call reco_term();
+void type_of_call cutpxz(Double_t &);
+void type_of_call sigmacut(Double_t &);
+void type_of_call xpreci(Double_t &);
+void type_of_call ypreci(Double_t &);
+void type_of_call reconstmuon(Int_t &, Int_t &, Int_t &, Int_t &, Int_t &);
+void type_of_call trackf_read_geant(Int_t *, Double_t *, Double_t *, Double_t *, Int_t *, Int_t *, Double_t *, Double_t *, Double_t *, Double_t *,Int_t &, Double_t *, Double_t *, Double_t *, Int_t &, Int_t &, Double_t *, Double_t *, Double_t *, Double_t *); 
+void type_of_call trackf_read_spoint(Int_t *, Double_t *, Double_t *, Double_t *, Int_t *, Int_t *, Double_t *, Double_t *, Double_t *, Double_t *,Int_t &, Double_t *, Double_t *, Double_t *, Int_t &, Int_t &, Double_t *, Double_t *, Double_t *, Double_t *); 
+void type_of_call chfill(Int_t &, Float_t &, Float_t &, Float_t &);
+void type_of_call chfill2(Int_t &, Float_t &, Float_t &, Float_t &);
+void type_of_call chf1(Int_t &, Float_t &, Float_t &);
+void type_of_call chfnt(Int_t &, Int_t &, Int_t *, Int_t *, Float_t *, Float_t *, Float_t *, Float_t *, Float_t *, Float_t *, Float_t *, Float_t *);
+void type_of_call hist_create();
+void type_of_call hist_closed();
+void type_of_call fcnf(Int_t &, Double_t *, Double_t &, Double_t *, Int_t);
+void type_of_call fcn(Int_t &, Double_t *, Double_t &, Double_t *, Int_t &, Int_t &);
+void type_of_call trackf_fit(Int_t &, Double_t *, Double_t *, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &);
+void type_of_call prec_fit(Double_t &, Double_t &, Double_t &, Double_t &, Double_t&, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &, Double_t &);
+void type_of_call fcnfitf(Int_t &, Double_t *, Double_t &, Double_t *, Int_t);
+void type_of_call fcnfit(Int_t &, Double_t *, Double_t &, Double_t *, Int_t &, Int_t &);
+Float_t type_of_call rndm() {return gRandom->Rndm();}
+}
+
 // Static variables for the pad-hit iterator routines
 static Int_t sMaxIterPad=0;
 static Int_t sCurIterPad=0;
+static TTree *TH1;
+static TTree *TK1;
+static TClonesArray *fHits2;        //Listof hits for one track only
+static TClonesArray *fClusters2;    //List of clusters for one track only
+static TClonesArray *fParticles2;   //List of particles in the Kine tree
 ClassImp(AliMUON)
 //___________________________________________
 AliMUON::AliMUON()
 {
@@ -29,8 +117,24 @@ AliMUON::AliMUON()
    fClusters   = 0;
    fNclusters  = 0;
    fDchambers  = 0;
-   fRecClusters= 0;
+   //   fRecClusters= 0;
    fNdch       = 0;
+   fRawClusters= 0;
+   fNrawch     = 0;
+   fCathCorrel= 0;
+   fNcorch     = 0;
+   fTreeC = 0;
+
+   // modifs perso
+   fSPxzCut    = 0;
+   fSSigmaCut  = 0;
+   fSXPrec     = 0; 
+   fSYPrec     = 0;
+   /*
+   fSSigmaCut = 4.0;
+   fSXPrec    = 0.006; 
+   fSYPrec    = 0.12;
+   */
 }
  
 //___________________________________________
@@ -39,29 +143,43 @@ AliMUON::AliMUON(const char *name, const char *title)
 {
 //Begin_Html
 /*
-<img src="picts/alimuon.gif">
+<img src="gif/alimuon.gif">
 */
 //End_Html
  
-   fHits     = new TClonesArray("AliMUONhit",1000  );
+   fHits     = new TClonesArray("AliMUONhit",1000);
    fClusters = new TClonesArray("AliMUONcluster",10000);
    fNclusters  =  0;
    fIshunt     =  0;
 
-   fNdch      = new Int_t[11];
+   fNdch      = new Int_t[10];
 
-   fDchambers = new TObjArray(11);
+   fDchambers = new TObjArray(10);
 
    Int_t i;
    
-   for (i=0; i<11 ;i++) {
+   for (i=0; i<10 ;i++) {
        (*fDchambers)[i] = new TClonesArray("AliMUONdigit",10000); 
        fNdch[i]=0;
    }
 
-   fRecClusters=new TObjArray(20);
-   for (i=0; i<20;i++)
-     (*fRecClusters)[i] = new TObjArray(1000);
+   fNrawch      = new Int_t[10];
+
+   fRawClusters = new TObjArray(10);
+
+   for (i=0; i<10 ;i++) {
+       (*fRawClusters)[i] = new TClonesArray("AliMUONRawCluster",10000); 
+       fNrawch[i]=0;
+   }
+
+   fNcorch      = new Int_t[10];
+   fCathCorrel = new TObjArray(10);
+   for (i=0; i<10 ;i++) {
+       (*fCathCorrel)[i] = new TClonesArray("AliMUONcorrelation",1000); 
+       fNcorch[i]=0;
+   }
+
+   fTreeC = 0;
 
 //   
 // Transport angular cut
@@ -69,24 +187,47 @@ AliMUON::AliMUON(const char *name, const char *title)
    fAccMin=2;
    fAccMax=9;
 
+   // modifs perso
+   fSPxzCut   = 3.0;
+   fSSigmaCut = 1.0;
+   fSXPrec    = 0.01; 
+   fSYPrec    = 0.144;
+   /*
+   fSSigmaCut = 4.0;
+   fSXPrec    = 0.006; 
+   fSYPrec    = 0.12;
+   */
    SetMarkerColor(kRed);
 }
  
 //___________________________________________
 AliMUON::~AliMUON()
 {
+
+    printf("Calling AliMUON destructor !!!\n");
+    
   fIshunt  = 0;
   delete fHits;
   delete fClusters;
-//  for (Int_t i=0;i<10;i++) {
-//      delete (*fDchambers)[i];
-//      fNdch[i]=0;
-//  }
-//  delete fDchambers;
-  for (Int_t i=0;i<20;i++) 
-      delete (*fRecClusters)[i];
-  delete fRecClusters;
+  delete fTreeC;
 
+  for (Int_t i=0;i<10;i++) {
+      delete (*fDchambers)[i];
+      fNdch[i]=0;
+  }
+  delete fDchambers;
+
+  for (Int_t i=0;i<10;i++) {
+      delete (*fRawClusters)[i];
+      fNrawch[i]=0;
+  }
+  delete fRawClusters;
+
+  for (Int_t i=0;i<10;i++) {
+      delete (*fCathCorrel)[i];
+      fNcorch[i]=0;
+  }
+  delete fCathCorrel;
 }
  
 //___________________________________________
@@ -112,6 +253,27 @@ void AliMUON::AddDigits(Int_t id, Int_t *tracks, Int_t *charges, Int_t *digits)
     new(ldigits[fNdch[id]++]) AliMUONdigit(tracks,charges,digits);
 }
 
+//_____________________________________________________________________________
+void AliMUON::AddRawCluster(Int_t id, const AliMUONRawCluster& c)
+{
+    //
+    // Add a MUON digit to the list
+    //
+
+    TClonesArray &lrawcl = *((TClonesArray*)(*fRawClusters)[id]);
+    new(lrawcl[fNrawch[id]++]) AliMUONRawCluster(c);
+}
+//_____________________________________________________________________________
+void AliMUON::AddCathCorrel(Int_t id, Int_t *idx, Float_t *x, Float_t *y)
+{
+    //
+    // Add a MUON digit to the list
+    //
+
+    TClonesArray &lcorrel = *((TClonesArray*)(*fCathCorrel)[id]);
+    new(lcorrel[fNcorch[id]++]) AliMUONcorrelation(idx,x,y);
+}
+
 
 //_____________________________________________________________________________
 void AliMUON::AddRecCluster(Int_t iCh, Int_t iCat, AliMUONRecCluster* Cluster)
@@ -119,116 +281,93 @@ void AliMUON::AddRecCluster(Int_t iCh, Int_t iCat, AliMUONRecCluster* Cluster)
     //
     // Add a MUON reconstructed cluster to the list
     //
+  /*
     TObjArray* ClusterList = RecClusters(iCh,iCat);
     ClusterList->Add(Cluster);
+  */
 }
 
 //___________________________________________
 void AliMUON::BuildGeometry()
 {
-  TNode *Node, *Top;
-  const int kColorMUON = kBlue;
-  //
-  Top=gAlice->GetGeometry()->GetNode("alice");
-
-  // MUON
-  const float cz[10] = { 511, 519, 686, 694, 971, 979, 1245, 1253, 1445, 1453};
-  const float acc_min = TMath::Tan( 2*.0174532925199432958);
-  const float acc_max = TMath::Tan(9*.0174532925199432958);
-  float rmin, rmax;
-  
-  // Chamber 1
-  rmin = (cz[0]+0.25)*acc_min;
-  rmax = cz[0]*acc_max;
-  new TTUBE("S_MUON1","MUON chamber 1","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON1","MUON chamber 1","S_MUON1",0,0,cz[0],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-  
-  // Chamber 2
-  rmin = (cz[1]+0.25)*acc_min;
-  rmax = cz[1]*acc_max;
-  new TTUBE("S_MUON2","MUON chamber 2","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON2","MUON chamber 2","S_MUON2",0,0,cz[1],"");
-  fNodes->Add(Node);
-  Node->SetLineColor(kColorMUON);
-  
-  // Chamber 3
-  rmin = (cz[2]+0.25)*acc_min;
-  rmax =  cz[2]*acc_max;
-  new TTUBE("S_MUON3","MUON chamber 3","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON3","MUON chamber 3","S_MUON3",0,0,cz[2],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-  
-  // Chamber 4
-  rmin = (cz[3]+0.25)*acc_min;
-  rmax = cz[3]*acc_max;
-  new TTUBE("S_MUON4","MUON chamber 4","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON4","MUON chamber 4","S_MUON4",0,0,cz[3],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-
-  // Chamber 5
-  rmin = 30;
-  rmax = cz[4]*acc_max;
-  new TTUBE("S_MUON5","MUON chamber 5","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON5","MUON chamber 5","S_MUON5",0,0,cz[4],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-  
-  // Chamber 6
-  rmin = 30;
-  rmax = cz[5]*acc_max;
-  new TTUBE("S_MUON6","MUON chamber 6","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON6","MUON chamber 6","S_MUON6",0,0,cz[5],"");
-  fNodes->Add(Node);
-  Node->SetLineColor(kColorMUON);
-  
-  // Chamber 7
-  rmin = 30;
-  rmax = cz[6]*acc_max;
-  new TTUBE("S_MUON7","MUON chamber 7","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON7","MUON chamber 7","S_MUON7",0,0,cz[6],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-
-  // Chamber 8
-  rmin = 30;
-  rmax = cz[7]*acc_max;
-  new TTUBE("S_MUON8","MUON chamber 8","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON8","MUON chamber 8","S_MUON8",0,0,cz[7],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-
-  // Chamber 9
-  rmin = 30;
-  rmax = cz[8]*acc_max;
-  new TTUBE("S_MUON9","MUON chamber 9","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON9","MUON chamber 9","S_MUON9",0,0,cz[8],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-
-  // Chamber 10
-  rmin = 30;
-  rmax = cz[9]*acc_max;
-  new TTUBE("S_MUON10","MUON chamber 10","void",rmin,rmax,0.25);
-  Top->cd();
-  Node = new TNode("MUON10","MUON chamber 10","S_MUON10",0,0,cz[9],"");
-  Node->SetLineColor(kColorMUON);
-  fNodes->Add(Node);
-
+    TNode *Node, *NodeF, *Top;
+    const int kColorMUON = kBlue;
+    //
+    Top=gAlice->GetGeometry()->GetNode("alice");
+// MUON
+//
+//  z-Positions of Chambers
+    const Float_t cz[5]={511., 686., 971., 1245., 1445.};
+//
+//  inner diameter
+    const Float_t dmi[5]={ 35.,  47.,  67.,   86.,  100.};
+//
+//  outer diameter
+    const Float_t dma[5]={183., 245., 346.,  520.,  520.};
+
+    TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90,  0, 90, 90, 0, 0);
+    TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
+    TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
+    TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90,  0, 0, 0);
+    
+
+    float rmin, rmax, dx, dy, dz, dr, zpos;
+    float dzc=4.;
+    char NameChamber[9], NameSense[9], NameFrame[9], NameNode[7];
+    for (Int_t i=0; i<5; i++) {
+       for (Int_t j=0; j<2; j++) {
+           Int_t id=2*i+j+1;
+           if (j==0) {
+               zpos=cz[i]-dzc;
+           } else {
+               zpos=cz[i]+dzc;
+           }
+           
+           
+           sprintf(NameChamber,"C_MUON%d",id);
+           sprintf(NameSense,"S_MUON%d",id);
+           sprintf(NameFrame,"F_MUON%d",id);   
+           rmin = dmi[i]/2.-3;
+           rmax = dma[i]/2.+3;
+           new TTUBE(NameChamber,"Mother","void",rmin,rmax,0.25,1.);
+           rmin = dmi[i]/2.;
+           rmax = dma[i]/2.;
+           new TTUBE(NameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
+           dx=(rmax-rmin)/2;
+           dy=3.;
+           dz=0.25;
+           TBRIK* FMUON = new TBRIK(NameFrame,"Frame","void",dx,dy,dz);
+           Top->cd();
+           sprintf(NameNode,"MUON%d",100+id);
+           Node = new TNode(NameNode,"ChamberNode",NameChamber,0,0,zpos,"");
+           Node->SetLineColor(kColorMUON);
+           fNodes->Add(Node);
+           Node->cd();
+           sprintf(NameNode,"MUON%d",200+id);
+           Node = new TNode(NameNode,"Sens. Region Node",NameSense,0,0,0,"");
+           Node->SetLineColor(kColorMUON);
+           Node->cd();
+           dr=dx+rmin;
+           sprintf(NameNode,"MUON%d",300+id);
+           NodeF = new TNode(NameNode,"Frame0",FMUON,dr, 0, 0,rot000,"");
+           NodeF->SetLineColor(kColorMUON);
+           Node->cd();
+           sprintf(NameNode,"MUON%d",400+id);
+           NodeF = new TNode(NameNode,"Frame1",FMUON,0 ,dr,0,rot090,"");
+           NodeF->SetLineColor(kColorMUON);
+           Node->cd();
+           sprintf(NameNode,"MUON%d",500+id);
+           NodeF = new TNode(NameNode,"Frame2",FMUON,-dr,0,0,rot180,"");
+           NodeF->SetLineColor(kColorMUON);
+           Node  ->cd();
+           sprintf(NameNode,"MUON%d",600+id);   
+           NodeF = new TNode(NameNode,"Frame3",FMUON,0,-dr,0,rot270,"");
+           NodeF->SetLineColor(kColorMUON);
+       }
+    }
 }
 
+
 //___________________________________________
 Int_t AliMUON::DistancetoPrimitive(Int_t , Int_t )
 {
@@ -241,7 +380,7 @@ void AliMUON::MakeBranch(Option_t* option)
   // Create Tree branches for the MUON.
   
   const Int_t buffersize = 4000;
-  char branchname[20];
+  char branchname[30];
   sprintf(branchname,"%sCluster",GetName());
 
   AliDetector::MakeBranch(option);
@@ -262,7 +401,21 @@ void AliMUON::MakeBranch(Option_t* option)
          printf("Making Branch %s for digits in chamber %d\n",branchname,i+1);
       }        
   }
-// one branch for rec clusters
+
+  printf("Make Branch - TreeR address %p\n",gAlice->TreeR());
+
+// one branch for raw clusters per chamber
+  for (i=0; i<10 ;i++) {
+      sprintf(branchname,"%sRawClusters%d",GetName(),i+1);
+      
+      if (fRawClusters   && gAlice->TreeR()) {
+        gAlice->TreeR()->Branch(branchname,&((*fRawClusters)[i]), buffersize);
+        printf("Making Branch %s for raw clusters in chamber %d\n",branchname,i+1);
+      }        
+  }
+
+// Emmanuel's stuff - one branch for rec clusters
+  /*
   for (i=0; i<20; i++) {
       sprintf(branchname,"%sRecClus%d",GetName(),i+1);
       if (fRecClusters   && gAlice->TreeD()) {
@@ -273,18 +426,21 @@ void AliMUON::MakeBranch(Option_t* option)
                 branchname,i+1);
       }
   }
+  */
+
 }
 
 //___________________________________________
 void AliMUON::SetTreeAddress()
 {
   // Set branch address for the Hits and Digits Tree.
-  char branchname[20];
+  char branchname[30];
   AliDetector::SetTreeAddress();
 
   TBranch *branch;
   TTree *treeH = gAlice->TreeH();
   TTree *treeD = gAlice->TreeD();
+  TTree *treeR = gAlice->TreeR();
 
   if (treeH) {
     if (fClusters) {
@@ -302,6 +458,31 @@ void AliMUON::SetTreeAddress()
          }
       }
   }
+
+  // printf("SetTreeAddress --- treeR address  %p \n",treeR);
+
+  if (treeR) {
+      for (int i=0; i<10; i++) {
+         sprintf(branchname,"%sRawClusters%d",GetName(),i+1);
+         if (fRawClusters) {
+             branch = treeR->GetBranch(branchname);
+             if (branch) branch->SetAddress(&((*fRawClusters)[i]));
+         }
+      }
+  }
+
+  // Emmanuel's stuff
+  /*
+  if (treeR) {
+      for (int i=0; i<20; i++) {
+         sprintf(branchname,"%sRecClus%d",GetName(),i+1);
+         if (fRecClusters) {
+             branch = treeR->GetBranch(branchname);
+             if (branch) branch->SetAddress(&((*fRecClusters)[i]));
+         }
+      }
+  }
+  */
 }
 //___________________________________________
 void AliMUON::ResetHits()
@@ -319,19 +500,45 @@ void AliMUON::ResetDigits()
     // Reset number of digits and the digits array for this detector
     //
     for ( int i=0;i<10;i++ ) {
-       if ((*fDchambers)[i])   (*fDchambers)[i]->Clear();
+       if ((*fDchambers)[i])    ((TClonesArray*)(*fDchambers)[i])->Clear();
        if (fNdch)  fNdch[i]=0;
     }
 }
 //____________________________________________
+void AliMUON::ResetRawClusters()
+{
+    //
+    // Reset number of raw clusters and the raw clust array for this detector
+    //
+    for ( int i=0;i<10;i++ ) {
+       if ((*fRawClusters)[i])    ((TClonesArray*)(*fRawClusters)[i])->Clear();
+       if (fNrawch)  fNrawch[i]=0;
+    }
+}
+//____________________________________________
+void AliMUON::ResetCorrelation()
+{
+    //
+    // Reset number of correl clusters and the correl clust array for 
+    // this detector
+    //
+    for ( int i=0;i<10;i++ ) {
+       if ((*fCathCorrel)[i])   ((TClonesArray*)(*fCathCorrel)[i])->Clear();
+       if (fNcorch)  fNcorch[i]=0;
+    }
+}
+
+//____________________________________________
 void AliMUON::ResetRecClusters()
 {
     //
     // Reset the rec clusters
     //
+  /*
     for ( int i=0;i<20;i++ ) {
        if ((*fRecClusters)[i])   (*fRecClusters)[i]->Clear();
     }
+  */
 }
 //___________________________________________
 
@@ -343,62 +550,62 @@ void AliMUON::SetPADSIZ(Int_t id, Int_t isec, Float_t p1, Float_t p2)
 }
 
 //___________________________________________
-void AliMUON::SetMUCHSP(Int_t id, Float_t p1)
+void AliMUON::SetChargeSlope(Int_t id, Float_t p1)
 {
     Int_t i=2*(id-1);
-    ((AliMUONchamber*) (*fChambers)[i])->SetMUCHSP(p1);
-    ((AliMUONchamber*) (*fChambers)[i+1])->SetMUCHSP(p1);
+    ((AliMUONchamber*) (*fChambers)[i])->SetChargeSlope(p1);
+    ((AliMUONchamber*) (*fChambers)[i+1])->SetChargeSlope(p1);
 }
 
 //___________________________________________
-void AliMUON::SetMUSIGM(Int_t id, Float_t p1, Float_t p2)
+void AliMUON::SetChargeSpread(Int_t id, Float_t p1, Float_t p2)
 {
     Int_t i=2*(id-1);
-    ((AliMUONchamber*) (*fChambers)[i])->SetMUSIGM(p1,p2);
-    ((AliMUONchamber*) (*fChambers)[i+1])->SetMUSIGM(p1,p2);
+    ((AliMUONchamber*) (*fChambers)[i])->SetChargeSpread(p1,p2);
+    ((AliMUONchamber*) (*fChambers)[i+1])->SetChargeSpread(p1,p2);
 }
 
 //___________________________________________
-void AliMUON::SetRSIGM(Int_t id, Float_t p1)
+void AliMUON::SetSigmaIntegration(Int_t id, Float_t p1)
 {
     Int_t i=2*(id-1);
-    ((AliMUONchamber*) (*fChambers)[i])->SetRSIGM(p1);
-    ((AliMUONchamber*) (*fChambers)[i+1])->SetRSIGM(p1);
+    ((AliMUONchamber*) (*fChambers)[i])->SetSigmaIntegration(p1);
+    ((AliMUONchamber*) (*fChambers)[i+1])->SetSigmaIntegration(p1);
 }
 
 //___________________________________________
-void AliMUON::SetMAXADC(Int_t id, Float_t p1)
+void AliMUON::SetMaxAdc(Int_t id, Float_t p1)
 {
     Int_t i=2*(id-1);
-    ((AliMUONchamber*) (*fChambers)[i])->SetMAXADC(p1);
-    ((AliMUONchamber*) (*fChambers)[i+1])->SetMAXADC(p1);
+    ((AliMUONchamber*) (*fChambers)[i])->SetMaxAdc(p1);
+    ((AliMUONchamber*) (*fChambers)[i+1])->SetMaxAdc(p1);
 }
 
 //___________________________________________
-void AliMUON::SetSMAXAR(Float_t p1)
+void AliMUON::SetMaxStepGas(Float_t p1)
 {
      fMaxStepGas=p1;
 }
 
 //___________________________________________
-void AliMUON::SetSMAXAL(Float_t p1)
+void AliMUON::SetMaxStepAlu(Float_t p1)
 {
     fMaxStepAlu=p1;
 }
 
 //___________________________________________
-void AliMUON::SetDMAXAR(Float_t p1)
+void AliMUON::SetMaxDestepGas(Float_t p1)
 {
     fMaxDestepGas=p1;
 }
 
 //___________________________________________
-void AliMUON::SetDMAXAL(Float_t p1)
+void AliMUON::SetMaxDestepAlu(Float_t p1)
 {
     fMaxDestepAlu=p1;
 }
 //___________________________________________
-void AliMUON::SetMUONACC(Bool_t acc, Float_t angmin, Float_t angmax)
+void AliMUON::SetMuonAcc(Bool_t acc, Float_t angmin, Float_t angmax)
 {
    fAccCut=acc;
    fAccMin=angmin;
@@ -416,6 +623,11 @@ void   AliMUON::SetResponseModel(Int_t id, AliMUONresponse *response)
     ((AliMUONchamber*) (*fChambers)[id])->ResponseModel(response);
 }
 
+void   AliMUON::SetReconstructionModel(Int_t id, AliMUONClusterFinder *reconst)
+{
+    ((AliMUONchamber*) (*fChambers)[id])->ReconstructionModel(reconst);
+}
+
 void   AliMUON::SetNsec(Int_t id, Int_t nsec)
 {
     ((AliMUONchamber*) (*fChambers)[id])->SetNsec(nsec);
@@ -428,139 +640,990 @@ void AliMUON::StepManager()
 {
     printf("Dummy version of muon step -- it should never happen!!\n");
     const Float_t kRaddeg = 180/TMath::Pi();
+    AliMC* pMC = AliMC::GetMC();
     Int_t nsec, ipart;
     Float_t x[4], p[4];
-    Float_t pt, th0, th1;
+    Float_t pt, th0, th2;
     char proc[5];
     if(fAccCut) {
-       if((nsec=gMC->NSecondaries())>0) {
-           gMC->ProdProcess(proc);
-           if((gMC->TrackPid()==113 || gMC->TrackPid()==114) && !strcmp(proc,"DCAY")) {
+       if((nsec=pMC->NSecondaries())>0) {
+           pMC->ProdProcess(proc);
+           if((pMC->TrackPid()==443 || pMC->TrackPid()==553) && !strcmp(proc,"DCAY")) {
                //
                // Check angular acceptance
                //* --- and have muons from resonance decays in the wanted window --- 
                if(nsec != 2) {
                    printf(" AliMUON::StepManager: Strange resonance Decay into %d particles\n",nsec);
-                   gMC->StopEvent();
+                   pMC->StopEvent();
                } else {
-                   gMC->GetSecondary(0,ipart,x,p);
+                   pMC->GetSecondary(0,ipart,x,p);
                    pt  = TMath::Sqrt(p[0]*p[0]+p[1]*p[1]);
                    th0 = TMath::ATan2(pt,p[2])*kRaddeg;
-                   gMC->GetSecondary(1,ipart,x,p);
+                   pMC->GetSecondary(1,ipart,x,p);
                    pt  = TMath::Sqrt(p[0]*p[0]+p[1]*p[1]);
-                   th1 = TMath::ATan2(pt,p[2])*kRaddeg;
+                   th2 = TMath::ATan2(pt,p[2])*kRaddeg;
                    if(!(fAccMin < th0 && th0 < fAccMax) ||
-                      !(fAccMin < th1 && th1 < fAccMax)) 
-                       gMC->StopEvent();
+                      !(fAccMin < th2 && th2 < fAccMax)) 
+                       pMC->StopEvent();
                }
            }
        }
     }
 }
-void AliMUON::ReconstructClusters()
+
+void AliMUON::MakePadHits(Float_t xhit,Float_t yhit,Float_t eloss, Int_t idvol)
 {
 //
-// Initialize the necessary correspondance table
+//  Calls the charge disintegration method of the current chamber and adds
+//  the simulated cluster to the root treee 
 //
-    static const Int_t kMaxNpadx = 600;
-    static const Int_t kMaxNpady = 600;
-    Int_t elem[kMaxNpadx*2][kMaxNpady*2];
+    Int_t clhits[7];
+    Float_t newclust[6][500];
+    Int_t nnew;
+    
+    
 //
-// Loop on chambers and on cathode planes
+//  Integrated pulse height on chamber
+
+    
+    clhits[0]=fNhits+1;
 //
-    for (Int_t ich=0;ich<10;ich++)
-       for (Int_t icat=0;icat<2;icat++) {
-           //
-           // Get ready the current chamber stuff
-           //
-           AliMUONchamber*  iChamber= &(this->Chamber(ich));
-           AliMUONsegmentation*  segmentation = 
-               iChamber->GetSegmentationModel(icat+1);
-           if (!segmentation) 
-               continue;
-           TClonesArray *MUONdigits  = this->DigitsAddress(ich);
-           if (MUONdigits == 0) 
-               continue;
-           cout << "Npx " << segmentation->Npx() 
-                << " Npy " << segmentation->Npy() << endl;
-           //      
-           // Ready the digits
-           //  
-           gAlice->ResetDigits();
-           gAlice->TreeD()->GetEvent(icat+1); // spurious +1 ...
-           Int_t ndigits = MUONdigits->GetEntriesFast();
-           if (ndigits == 0) 
+//
+    ((AliMUONchamber*) (*fChambers)[idvol])->DisIntegration(eloss, xhit, yhit, nnew, newclust);
+//    printf("\n Add new clusters %d %f \n", nnew, eloss*1.e9);
+    Int_t ic=0;
+    
+//
+//  Add new clusters
+    for (Int_t i=0; i<nnew; i++) {
+       if (Int_t(newclust[3][i]) > 0) {
+           ic++;
+// Cathode plane
+           clhits[1] = Int_t(newclust[5][i]);
+//  Cluster Charge
+           clhits[2] = Int_t(newclust[0][i]);
+//  Pad: ix
+           clhits[3] = Int_t(newclust[1][i]);
+//  Pad: iy 
+           clhits[4] = Int_t(newclust[2][i]);
+//  Pad: charge
+           clhits[5] = Int_t(newclust[3][i]);
+//  Pad: chamber sector
+           clhits[6] = Int_t(newclust[4][i]);
+           
+           AddCluster(clhits);
+       }
+    }
+//    printf("\n %d new clusters added", ic);
+}
+
+void AliMUON::Digitise(Int_t nev,Int_t bgr_ev,Option_t *option,Option_t *opt,Text_t *filename)
+{
+    // keep galice.root for signal and name differently the file for 
+    // background when add! otherwise the track info for signal will be lost !
+  
+    static Bool_t first=true;
+//    static TTree *TH1;
+    static TFile *File;
+    char *Add = strstr(option,"Add");
+    //char *listoftracks = strstr(opt,"listoftracks");
+
+    AliMUONchamber*  iChamber;
+    AliMUONsegmentation*  segmentation;
+
+    
+    Int_t trk[50];
+    Int_t chtrk[50];  
+    TObjArray *list=new TObjArray;
+    static TClonesArray *p_adr=0;
+    if(!p_adr) p_adr=new TClonesArray("TVector",1000);
+    Int_t digits[5]; 
+
+    AliMUON *MUON  = (AliMUON *) gAlice->GetModule("MUON");
+    AliMUONHitMap * HitMap[10];
+    for (Int_t i=0; i<10; i++) {HitMap[i]=0;}
+    if (Add ) {
+       if(first) {
+           fFileName=filename;
+           cout<<"filename"<<fFileName<<endl;
+           File=new TFile(fFileName);
+           cout<<"I have opened "<<fFileName<<" file "<<endl;
+           fHits2     = new TClonesArray("AliMUONhit",1000  );
+           fClusters2 = new TClonesArray("AliMUONcluster",10000);
+       }           
+       first=false;
+       File->cd();
+       //File->ls();
+       // Get Hits Tree header from file
+       if(fHits2) fHits2->Clear();
+       if(fClusters2) fClusters2->Clear();
+       if(TH1) delete TH1;
+       TH1=0;
+       
+       char treeName[20];
+       sprintf(treeName,"TreeH%d",bgr_ev);
+       TH1 = (TTree*)gDirectory->Get(treeName);
+        //printf("TH1 %p of treename %s for event %d \n",TH1,treeName,bgr_ev);
+       
+       if (!TH1) {
+           printf("ERROR: cannot find Hits Tree for event:%d\n",bgr_ev);
+       }
+       // Set branch addresses
+       TBranch *branch;
+       char branchname[20];
+       sprintf(branchname,"%s",GetName());
+       if (TH1 && fHits2) {
+           branch = TH1->GetBranch(branchname);
+           if (branch) branch->SetAddress(&fHits2);
+       }
+       if (TH1 && fClusters2) {
+           branch = TH1->GetBranch("MUONCluster");
+           if (branch) branch->SetAddress(&fClusters2);
+       }
+// test
+       //Int_t ntracks1 =(Int_t)TH1->GetEntries();
+       //printf("background - ntracks1 - %d\n",ntracks1);
+    }
+    //
+    // loop over cathodes
+    //
+    AliMUONHitMap* hm;
+    Int_t countadr=0;
+    for (int icat=0; icat<2; icat++) { 
+/*
+       for (Int_t i=0; i<10; i++) {
+           if (HitMap[i]) {
+               hm=HitMap[i];
+               delete hm;
+               HitMap[i]=0;
+           }
+       }
+*/
+
+       Int_t counter=0;
+       for (Int_t i =0; i<10; i++) {
+           iChamber=(AliMUONchamber*) (*fChambers)[i];
+           if (iChamber->Nsec()==1 && icat==1) {
                continue;
-           printf("Found %d digits for cathode %d in chamber %d \n",
-                  ndigits,icat,ich+1);
-           AliMUONdigit  *mdig;
-           AliMUONRecCluster *Cluster;
-           //
-           // Build the correspondance table
-           //
-           memset(elem,0,sizeof(Int_t)*kMaxNpadx*kMaxNpady*4);
-           Int_t digit;
-           for (digit=0; digit<ndigits; digit++) 
-           {
-               mdig    = (AliMUONdigit*)MUONdigits->UncheckedAt(digit);
-               elem[kMaxNpadx+mdig->fPadX][kMaxNpady+mdig->fPadY] = digit+1;
-               // because default is 0
+           } else {
+               segmentation=iChamber->GetSegmentationModel(icat+1);
            }
-           //
-           // Declare some useful variables
-           //
-           Int_t Xlist[10];
-           Int_t Ylist[10];
-           Int_t Nlist;
-           Int_t nclust=0;
-           //
-           // loop over digits
-           //
-           for (digit=0;digit<ndigits;digit++) {
-               mdig    = (AliMUONdigit*)MUONdigits->UncheckedAt(digit);
-               //
-               // if digit still available, start clustering
-               //
-               if (elem[kMaxNpadx+mdig->fPadX][kMaxNpady+mdig->fPadY]) {
-                   Cluster = new AliMUONRecCluster(digit, ich, icat);
-                   elem[kMaxNpadx+mdig->fPadX][kMaxNpady+mdig->fPadY]=0;
-                   //
-                   // loop over the current list of digits 
-                    // and look for neighbours
-                   //
-                   for(Int_t clusDigit=Cluster->FirstDigitIndex();
-                       clusDigit!=Cluster->InvalidDigitIndex();
-                       clusDigit=Cluster->NextDigitIndex()) {
-                       AliMUONdigit* pDigit=(AliMUONdigit*)MUONdigits
-                           ->UncheckedAt(clusDigit);
-                       segmentation->Neighbours(pDigit->fPadX,pDigit->fPadY, 
-                                                &Nlist, Xlist, Ylist);
-                       for (Int_t Ilist=0;Ilist<Nlist;Ilist++) {
-                           if (elem[kMaxNpadx+Xlist[Ilist]][kMaxNpady
-                                                           +Ylist[Ilist]]) {
-                               //
-                               // Add the digit at the end and reset the table
-                               //
-                               Cluster->AddDigit(elem[kMaxNpadx+Xlist[Ilist]][kMaxNpady+Ylist[Ilist]]-1);
-                               elem[kMaxNpadx+Xlist[Ilist]][kMaxNpady
-                                                           +Ylist[Ilist]] =0;
-                           } // if elem
-                       } // for Ilist
-                   } // for pDigit
-                   //
-                   // Store the cluster (good time to do Cluster polishing)
-                   //
-                   segmentation->FitXY(Cluster,MUONdigits);
-                   nclust ++;
-                   AddRecCluster(ich,icat,Cluster);
+           HitMap[i] = new AliMUONHitMapA1(segmentation, list);
+       }
+       //printf("Start loop over tracks \n");     
+//
+//   Loop over tracks
+//
+
+       TTree *TH = gAlice->TreeH();
+       Int_t ntracks =(Int_t) TH->GetEntries();
+        //printf("signal - ntracks %d\n",ntracks);
+       Int_t nmuon[10]={0,0,0,0,0,0,0,0,0,0};
+       Float_t xhit[10][2];
+       Float_t yhit[10][2];
+       
+       for (Int_t track=0; track<ntracks; track++) {
+           gAlice->ResetHits();
+           TH->GetEvent(track);
+           
+//
+//   Loop over hits
+           for(AliMUONhit* mHit=(AliMUONhit*)MUON->FirstHit(-1); 
+               mHit;
+               mHit=(AliMUONhit*)MUON->NextHit()) 
+           {
+               Int_t   nch   = mHit->fChamber-1;  // chamber number
+               if (nch >9) continue;
+               iChamber = &(MUON->Chamber(nch));
+               Int_t rmin = (Int_t)iChamber->RInner();
+               Int_t rmax = (Int_t)iChamber->ROuter();
+                // new 17.07.99
+               if (Add) {
+
+                 if (mHit->fParticle == kMuonPlus || mHit->fParticle == kMuonMinus) {
+                   xhit[nch][nmuon[nch]]=mHit->fX;
+                   yhit[nch][nmuon[nch]]=mHit->fY;
+                   nmuon[nch]++;
+                    if (nmuon[nch] >2) printf("nmuon %d\n",nmuon[nch]);
+                   
+                 }
                }
+
+
+
+               
+//
+// Loop over pad hits
+               for (AliMUONcluster* mPad=
+                        (AliMUONcluster*)MUON->FirstPad(mHit,fClusters);
+                    mPad;
+                    mPad=(AliMUONcluster*)MUON->NextPad(fClusters))
+               {
+                   Int_t cathode  = mPad->fCathode;    // cathode number
+                   Int_t ipx      = mPad->fPadX;       // pad number on X
+                   Int_t ipy      = mPad->fPadY;       // pad number on Y
+                   Int_t iqpad    = Int_t(mPad->fQpad*kScale);// charge per pad
+//                 Int_t iqpad    = mPad->fQpad;       // charge per pad
+//
+//
+                   
+                   if (cathode != (icat+1)) continue;
+                   // fill the info array
+                   Float_t thex, they;
+                   segmentation=iChamber->GetSegmentationModel(cathode);
+                   segmentation->GetPadCxy(ipx,ipy,thex,they);
+                   Float_t rpad=TMath::Sqrt(thex*thex+they*they);
+                   if (rpad < rmin || iqpad ==0 || rpad > rmax) continue;
+
+                   new((*p_adr)[countadr++]) TVector(2);
+                   TVector &trinfo=*((TVector*) (*p_adr)[countadr-1]);
+                   trinfo(0)=(Float_t)track;
+                   trinfo(1)=(Float_t)iqpad;
+
+                   digits[0]=ipx;
+                   digits[1]=ipy;
+                   digits[2]=iqpad;
+                   digits[3]=iqpad;
+                   if (mHit->fParticle == kMuonPlus || mHit->fParticle == kMuonMinus) {
+                   digits[4]=mPad->fHitNumber;
+                   } else digits[4]=-1;
+
+                   AliMUONlist* pdigit;
+                   // build the list of fired pads and update the info
+                   if (!HitMap[nch]->TestHit(ipx, ipy)) {
+
+                       list->AddAtAndExpand(
+                           new AliMUONlist(nch,digits),counter);
+                       
+                       HitMap[nch]->SetHit(ipx, ipy, counter);
+                       counter++;
+                       pdigit=(AliMUONlist*)list->At(list->GetLast());
+                       // list of tracks
+                       TObjArray *trlist=(TObjArray*)pdigit->TrackList();
+                       trlist->Add(&trinfo);
+                   } else {
+                       pdigit=(AliMUONlist*) HitMap[nch]->GetHit(ipx, ipy);
+                       // update charge
+                       (*pdigit).fSignal+=iqpad;
+                       (*pdigit).fPhysics+=iqpad;                      
+                       // update list of tracks
+                       TObjArray* trlist=(TObjArray*)pdigit->TrackList();
+                       Int_t last_entry=trlist->GetLast();
+                       TVector *ptrk_p=(TVector*)trlist->At(last_entry);
+                       TVector &ptrk=*ptrk_p;
+                       Int_t last_track=Int_t(ptrk(0));
+                       Int_t last_charge=Int_t(ptrk(1));
+                       if (last_track==track) {
+                           last_charge+=iqpad;
+                           trlist->RemoveAt(last_entry);
+                           trinfo(0)=last_track;
+                           trinfo(1)=last_charge;
+                           trlist->AddAt(&trinfo,last_entry);
+                       } else {
+                           trlist->Add(&trinfo);
+                       }
+                       // check the track list
+                       Int_t nptracks=trlist->GetEntriesFast();
+                       if (nptracks > 2) {
+                           for (Int_t tr=0;tr<nptracks;tr++) {
+                               TVector *pptrk_p=(TVector*)trlist->At(tr);
+                               TVector &pptrk=*pptrk_p;
+                               trk[tr]=Int_t(pptrk(0));
+                               chtrk[tr]=Int_t(pptrk(1));
+                           }
+                       } // end if nptracks
+                   } //  end if pdigit
+               } //end loop over clusters
+           } // hit loop
+       } // track loop
+       
+       //Int_t nentr1=list->GetEntriesFast();
+       //printf(" \n counter, nentr1 %d %d\n",counter,nentr1);
+
+       // open the file with background
+       
+       if (Add ) {
+           ntracks =(Int_t)TH1->GetEntries();
+           //printf("background - icat,ntracks1  %d %d\n",icat,ntracks);
+           //printf("background - Start loop over tracks \n");     
+//
+//   Loop over tracks
+//
+           for (Int_t track=0; track<ntracks; track++) {
+
+               if (fHits2)       fHits2->Clear();
+               if (fClusters2)   fClusters2->Clear();
+
+               TH1->GetEvent(track);
+//
+//   Loop over hits
+               AliMUONhit* mHit;
+               for(int i=0;i<fHits2->GetEntriesFast();++i) 
+       {       
+                   mHit=(AliMUONhit*) (*fHits2)[i];
+                   Int_t   nch   = mHit->fChamber-1;  // chamber number
+                   if (nch >9) continue;
+                   iChamber = &(MUON->Chamber(nch));
+                   Int_t rmin = (Int_t)iChamber->RInner();
+                   Int_t rmax = (Int_t)iChamber->ROuter();
+                    Float_t xbgr=mHit->fX;
+                   Float_t ybgr=mHit->fY;
+                   Bool_t cond=false;
+                   
+                   for (Int_t imuon =0; imuon < nmuon[nch]; imuon++) {
+                       Float_t dist= (xbgr-xhit[nch][imuon])*(xbgr-xhit[nch][imuon])
+                           +(ybgr-yhit[nch][imuon])*(ybgr-yhit[nch][imuon]);
+                       if (dist<100) cond=true;
+                   }
+                   if (!cond) continue;
+                   
+//
+// Loop over pad hits
+                   //for(int j=0;j<fClusters2->GetEntriesFast();++j)
+                   for (AliMUONcluster* mPad=
+                            (AliMUONcluster*)MUON->FirstPad(mHit,fClusters2);
+                        mPad;
+                        mPad=(AliMUONcluster*)MUON->NextPad(fClusters2))
+                   {
+                       //                  mPad = (AliMUONcluster*) (*fClusters2)[j];
+                       Int_t cathode  = mPad->fCathode;    // cathode number
+                       Int_t ipx      = mPad->fPadX;       // pad number on X
+                       Int_t ipy      = mPad->fPadY;       // pad number on Y
+                       Int_t iqpad    = Int_t(mPad->fQpad*kScale);// charge per pad
+//                     Int_t iqpad    = mPad->fQpad;       // charge per pad
+
+                       if (cathode != (icat+1)) continue;
+//                 if (!HitMap[nch]->CheckBoundary()) continue;
+                       // fill the info array
+                       Float_t thex, they;
+                       segmentation=iChamber->GetSegmentationModel(cathode);
+                       segmentation->GetPadCxy(ipx,ipy,thex,they);
+                       Float_t rpad=TMath::Sqrt(thex*thex+they*they);
+                       if (rpad < rmin || iqpad ==0 || rpad > rmax) continue;
+
+                           new((*p_adr)[countadr++]) TVector(2);
+                           TVector &trinfo=*((TVector*) (*p_adr)[countadr-1]);
+                           trinfo(0)=-1;  // tag background
+                           trinfo(1)=-1;
+
+                       digits[0]=ipx;
+                       digits[1]=ipy;
+                       digits[2]=iqpad;
+                       digits[3]=0;
+                       digits[4]=-1;
+
+                       AliMUONlist* pdigit;
+                       // build the list of fired pads and update the info
+                       if (!HitMap[nch]->TestHit(ipx, ipy)) {
+                           list->AddAtAndExpand(new AliMUONlist(nch,digits),counter);
+                       
+                           HitMap[nch]->SetHit(ipx, ipy, counter);
+                           counter++;
+                           
+                           pdigit=(AliMUONlist*)list->At(list->GetLast());
+                           // list of tracks
+                               TObjArray *trlist=(TObjArray*)pdigit->
+                                                  TrackList();
+                               trlist->Add(&trinfo);
+                       } else {
+                           pdigit=(AliMUONlist*) HitMap[nch]->GetHit(ipx, ipy);
+                           // update charge
+                           (*pdigit).fSignal+=iqpad;
+
+                           // update list of tracks
+                               TObjArray* trlist=(TObjArray*)pdigit->
+                                                  TrackList();
+                               Int_t last_entry=trlist->GetLast();
+                               TVector *ptrk_p=(TVector*)trlist->
+                                                At(last_entry);
+                               TVector &ptrk=*ptrk_p;
+                               Int_t last_track=Int_t(ptrk(0));
+                               if (last_track==-1) {
+                                   continue;
+                               } else {
+                                   trlist->Add(&trinfo);
+                               }
+                               // check the track list
+                               Int_t nptracks=trlist->GetEntriesFast();
+                               if (nptracks > 0) {
+                                   for (Int_t tr=0;tr<nptracks;tr++) {
+                                       TVector *pptrk_p=(TVector*)trlist->At(tr);
+                                       TVector &pptrk=*pptrk_p;
+                                       trk[tr]=Int_t(pptrk(0));
+                                       chtrk[tr]=Int_t(pptrk(1));
+                                   }
+                               } // end if nptracks
+                       } //  end if pdigit
+                   } //end loop over clusters
+               } // hit loop
+           } // track loop
+           //Int_t nentr2=list->GetEntriesFast();
+           //printf(" \n counter2, nentr2 %d %d \n",counter,nentr2);
+           TTree *fAli=gAlice->TreeK();
+            TFile *file;
+           
+           if (fAli) file =fAli->GetCurrentFile();
+           file->cd();
+       } // if Add     
+
+       Int_t tracks[10];
+       Int_t charges[10];
+       //cout<<"start filling digits \n "<<endl;
+       //      const Float_t zero_supm =    6.;
+       Int_t nentries=list->GetEntriesFast();
+       //printf(" \n \n nentries %d \n",nentries);
+       // start filling the digits
+       
+       for (Int_t nent=0;nent<nentries;nent++) {
+           AliMUONlist *address=(AliMUONlist*)list->At(nent);
+           if (address==0) continue; 
+           Int_t ich=address->fChamber;
+           Int_t q=address->fSignal; 
+           iChamber=(AliMUONchamber*) (*fChambers)[ich];
+           AliMUONresponse * response=iChamber->GetResponseModel();
+           Int_t adcmax= (Int_t) response->MaxAdc();
+           // add white noise and do zero-suppression and signal truncation
+           Float_t MeanNoise = gRandom->Gaus(1, 0.2);
+           Float_t Noise     = gRandom->Gaus(0, MeanNoise);
+           q+=(Int_t)Noise; 
+           if (address->fPhysics !=0 ) address->fPhysics+=(Int_t)Noise; 
+           if ( q <= zero_supm ) continue;
+           if ( q > adcmax)  q=adcmax;
+           digits[0]=address->fPadX;
+           digits[1]=address->fPadY;
+           digits[2]=q;
+           digits[3]=address->fPhysics;
+           digits[4]=address->fHit;
+            //printf("fSignal, fPhysics fTrack %d %d %d \n",digits[2],digits[3],digits[4]);
+           
+           TObjArray* trlist=(TObjArray*)address->TrackList();
+           Int_t nptracks=trlist->GetEntriesFast();
+           //printf("nptracks, trlist   %d  %p\n",nptracks,trlist);
+
+               // this was changed to accomodate the real number of tracks
+               if (nptracks > 10) {
+                   cout<<"Attention - nptracks > 10 "<<nptracks<<endl;
+                   nptracks=10;
+               }
+               if (nptracks > 2) {
+                   printf("Attention - nptracks > 2  %d \n",nptracks);
+                   printf("cat,ich,ix,iy,q %d %d %d %d %d \n",icat,ich,digits[0],digits[1],q);
+               }
+               for (Int_t tr=0;tr<nptracks;tr++) {
+                   TVector *pp_p=(TVector*)trlist->At(tr);
+                   if(!pp_p ) printf("pp_p - %p\n",pp_p);
+                   TVector &pp  =*pp_p;
+                   tracks[tr]=Int_t(pp(0));
+                   charges[tr]=Int_t(pp(1));
+                //printf("tracks, charges - %d %d\n",tracks[tr],charges[tr]);
+               }      //end loop over list of tracks for one pad
+            // Sort list of tracks according to charge
+               if (nptracks > 1) {
+                   SortTracks(tracks,charges,nptracks);
+               }
+               if (nptracks < 10 ) {
+                   for (Int_t i=nptracks; i<10; i++) {
+                       tracks[i]=0;
+                       charges[i]=0;
+                   }
+               }
+
+           // fill digits
+           MUON->AddDigits(ich,tracks,charges,digits);
+           // delete trlist;
+//         delete address;
+       }
+       //cout<<"I'm out of the loops for digitisation"<<endl;
+       //      gAlice->GetEvent(nev);
+       gAlice->TreeD()->Fill();
+       //TTree *TD=gAlice->TreeD();
+       /*
+       Stat_t ndig=TD->GetEntries();
+       cout<<"number of digits  "<<ndig<<endl;
+       TClonesArray *fDch;
+       for (int i=0;i<10;i++) {
+           fDch= MUON->DigitsAddress(i);
+           int ndig=fDch->GetEntriesFast();
+           printf (" i, ndig %d %d \n",i,ndig);
+       }
+       */
+       MUON->ResetDigits();
+       list->Delete();
+       //printf("Here\n");
+       for(Int_t i=0;i<10;++i) {
+           if (HitMap[i]) {
+               hm=HitMap[i];
+               delete hm;
+               HitMap[i]=0;
            }
-           printf("===> %d Clusters\n",nclust); 
-       } // for icat
+       }
+       
+    } //end loop over cathodes
+
+       char hname[30];
+       sprintf(hname,"TreeD%d",nev);
+       gAlice->TreeD()->Write(hname);
+       // reset tree
+       gAlice->TreeD()->Reset();
+       delete list;
+       //Int_t nadr=p_adr->GetEntriesFast();
+       // printf(" \n \n nadr %d \n",nadr);
+
+       // start filling the digits
+       /*
+       for (Int_t nent=0;nent<nadr;nent++) {
+           TVector *pv=(TVector*)p_adr->At(nent);
+            pv->Delete();
+           //delete pv;
+       }
+       */
+       p_adr->Clear();
+       // gObjectTable->Print();
+       
+}
+
+void AliMUON::SortTracks(Int_t *tracks,Int_t *charges,Int_t ntr)
+{
+  //
+  // Sort the list of tracks contributing to a given digit
+  // Only the 3 most significant tracks are acctually sorted
+  //
+  
+  //
+  //  Loop over signals, only 3 times
+  //
+  
+  Int_t qmax;
+  Int_t jmax;
+  Int_t idx[3] = {-2,-2,-2};
+  Int_t jch[3] = {-2,-2,-2};
+  Int_t jtr[3] = {-2,-2,-2};
+  Int_t i,j,imax;
+  
+  if (ntr<3) imax=ntr;
+  else imax=3;
+  for(i=0;i<imax;i++){
+    qmax=0;
+    jmax=0;
+    
+    for(j=0;j<ntr;j++){
+      
+      if((i == 1 && j == idx[i-1]) 
+        ||(i == 2 && (j == idx[i-1] || j == idx[i-2]))) continue;
+      
+      if(charges[j] > qmax) {
+       qmax = charges[j];
+       jmax=j;
+      }       
+    } 
+    
+    if(qmax > 0) {
+      idx[i]=jmax;
+      jch[i]=charges[jmax]; 
+      jtr[i]=tracks[jmax]; 
+    }
+    
+  } 
+  
+  for(i=0;i<3;i++){
+    if (jtr[i] == -2) {
+         charges[i]=0;
+         tracks[i]=0;
+    } else {
+         charges[i]=jch[i];
+         tracks[i]=jtr[i];
+    }
+  }
+
 }
 
+void AliMUON::FindClusters(Int_t nev,Int_t last_entry)
+{
+
+//
+// Loop on chambers and on cathode planes
+//
+  for (Int_t icat=0;icat<2;icat++) {
+           gAlice->ResetDigits();
+           gAlice->TreeD()->GetEvent(last_entry+icat); // spurious +1 ...
+           if (nev < 10) printf("last_entry , icat - %d %d \n",last_entry,icat);
+           //gAlice->TreeD()->GetEvent(icat+1); // spurious +1 ...
+
+      for (Int_t ich=0;ich<10;ich++) {
+         AliMUONchamber* iChamber=(AliMUONchamber*) (*fChambers)[ich];
+         TClonesArray *MUONdigits  = this->DigitsAddress(ich);
+         if (MUONdigits == 0) continue;
+          //
+         // Get ready the current chamber stuff
+         //
+         AliMUONresponse* response = iChamber->GetResponseModel();
+         AliMUONsegmentation*  seg = iChamber->GetSegmentationModel(icat+1);
+         AliMUONClusterFinder* rec = iChamber->GetReconstructionModel();
+//       if (icat==1 && (ich==4 || ich==5)) continue;
+//       printf("icat, ich, seg - %d %d %p\n",icat,ich,seg);
+         if (seg) {      
+             rec->SetSegmentation(seg);
+             rec->SetResponse(response);
+             rec->SetDigits(MUONdigits);
+             rec->SetChamber(ich);
+             if (nev==0) rec->CalibrateCOG(); 
+//           rec->CalibrateCOG(); 
+             rec->FindRawClusters();
+         }  
+          //printf("Finish FindRawClusters for cathode %d in chamber %d\n",icat,ich);
+         
+          TClonesArray *fRch;
+         fRch=RawClustAddress(ich);
+         fRch->Sort();
+          // it seems to work 
+         
+
+      } // for ich
+      // fill the tree
+      //TTree *TR=gAlice->TreeR();
+
+      gAlice->TreeR()->Fill();
+      /*
+      Stat_t nent=TR->GetEntries();
+      cout<<"number of entries  "<<nent<<endl;
+      TClonesArray *fRch;
+      for (int i=0;i<10;i++) {
+         fRch=RawClustAddress(i);
+         int nraw=fRch->GetEntriesFast();
+         printf (" i, nraw %d %d \n",i,nraw);
+      }
+      */
+      ResetRawClusters();
+
+  } // for icat
+
+  char hname[30];
+  sprintf(hname,"TreeR%d",nev);
+  gAlice->TreeR()->Write(hname);
+  gAlice->TreeR()->Reset();
+
+  //gObjectTable->Print();
+
+}
  
 //______________________________________________________________________________
+//_____________________________________________________________________________ 
+void AliMUON::CathodeCorrelation(Int_t nev)
+{
+
+// Correlates the clusters on the two cathode planes and build a list of
+// other possible combinations (potential ghosts) - for the moment use the
+// criteria of minimum distance between the CoGs of the two correlated
+// clusters
+
+
+//
+// Loop on chambers and on clusters on the cathode plane with the highest
+// number of clusters
+
+    static Bool_t first=true;
+
+     AliMUONRawCluster  *mRaw1;
+     AliMUONRawCluster  *mRaw2;
+     AliMUONchamber     *iChamber;
+     AliMUONsegmentation *seg;
+     TArrayF x1, y1, x2, y2, q1, q2;
+     x1.Set(5000);
+     x2.Set(5000);     
+     y1.Set(5000);
+     y2.Set(5000);     
+     q1.Set(5000);
+     q2.Set(5000);     
+     
+// Get pointers to Alice detectors and Digits containers
+     TTree *TR = gAlice->TreeR();
+     Int_t nent=(Int_t)TR->GetEntries();
+     if (nev < 10) printf("Found %d entries in the tree (must be one per cathode per event! + 1empty)\n",nent);
+  
+
+     Int_t idx[4]; 
+     Float_t xc2[4],yc2[4];
+     Float_t xrec2, yrec2;
+     Float_t xd0, xdif, ydif;
+     Float_t ysrch,xd,xmax,ymax;
+     Int_t ilow, iup, iraw1;
+     //
+     Float_t xarray[50];
+     Float_t xdarray[50];
+     Float_t yarray[50];
+     Float_t qarray[50];
+     Int_t idx2[50];
+
+     // Int_t nraw[2], entry,cathode;
+
+     for (int i=0;i<50;i++) {
+         xdarray[i]=1100.;
+         xarray[i]=0.;
+         yarray[i]=0.;
+         qarray[i]=0.;
+         idx2[i]=-1;
+     }
+     for (int i=0;i<4;i++) {
+          idx[i]=-1;
+          xc2[i]=0.;
+          yc2[i]=0.;
+     }
+
+     // access to the Raw Clusters tree
+     for (Int_t ich=0;ich<10;ich++) {
+        iChamber = &(Chamber(ich));
+        TClonesArray *MUONrawclust  = RawClustAddress(ich);
+        ResetRawClusters();
+        TR->GetEvent(nent-2);
+        //TR->GetEvent(1);
+        Int_t nrawcl1 = MUONrawclust->GetEntries();
+        // printf("Found %d raw clusters for cathode 1 in chamber %d \n"
+        //      ,nrawcl1,ich+1);
+         if (!nrawcl1) continue;
+
+        seg = iChamber->GetSegmentationModel(1);
+         // loop over raw clusters of first cathode
+        for (iraw1=0; iraw1<nrawcl1; iraw1++) {
+                mRaw1= (AliMUONRawCluster*)MUONrawclust->UncheckedAt(iraw1);
+                x1[iraw1]=mRaw1->fX;
+                y1[iraw1]=mRaw1->fY;
+                q1[iraw1]=(Float_t)mRaw1->fQ; //maybe better fPeakSignal
+        } // rawclusters cathode 1
+//
+         // Get information from 2nd cathode
+        ResetRawClusters();
+        TR->GetEvent(nent-1);
+        //TR->GetEvent(2);
+        Int_t nrawcl2 = MUONrawclust->GetEntries();
+        if (!nrawcl2) {
+            for (iraw1=0; iraw1<nrawcl1; iraw1++) {
+                idx[3]=iraw1;
+                xc2[3]=x1[iraw1];
+                yc2[3]=y1[iraw1];
+                 //printf("nrawcl2 is zero - idx[0] %d\n",idx[0]);
+                
+                AddCathCorrel(ich,idx,xc2,yc2);
+                // reset
+                idx[3]=-1;
+                xc2[3]=0.;
+                yc2[3]=0.;
+                
+            } // store information from cathode 1 only 
+        } else {
+          //  printf("Found %d raw clusters for cathode 2 in chamber %d \n",
+          // nrawcl2, ich+1);
+
+            for (Int_t iraw2=0; iraw2<nrawcl2; iraw2++) {
+                mRaw2= (AliMUONRawCluster*)MUONrawclust->UncheckedAt(iraw2);
+                x2[iraw2]=mRaw2->fX;
+                y2[iraw2]=mRaw2->fY;   
+                q2[iraw2]=(Float_t)mRaw2->fQ;  
+            } // rawclusters cathode 2
+//
+// Initalisation finished
+            for (iraw1=0; iraw1<nrawcl1; iraw1++) {
+            // find the sector
+                 Int_t ix,iy;
+                 seg->GetPadIxy(x1[iraw1],y1[iraw1],ix,iy);   
+                 Int_t isec=seg->Sector(ix,iy);
+                // range to look for ghosts ?!
+                 if (ich < 5) {
+                    ymax = seg->Dpy(isec)*7/2;
+                    xmax = seg->Dpx(isec)*7/2;
+                 } else {
+                    ymax = seg->Dpy(isec)*13/2;
+                    xmax = seg->Dpx(isec)*3/2;
+                }
+                ysrch=ymax+y1[iraw1];
+                
+                ilow = AliMUONRawCluster::
+                    BinarySearch(ysrch-2*ymax,y2,0,nrawcl2+1);
+                iup=   AliMUONRawCluster::
+                    BinarySearch(ysrch,y2,ilow,nrawcl2+1);
+                if (ilow<0 || iup <0 || iup>nrawcl2) continue;
+                Int_t counter=0;
+                for (Int_t iraw2=ilow; iraw2<=iup; iraw2++) {
+                    xrec2=x2[iraw2];
+                    yrec2=y2[iraw2];   
+                    xdif=x1[iraw1]-xrec2;
+                    ydif=y1[iraw1]-yrec2;
+                    xd=TMath::Sqrt(xdif*xdif+ydif*ydif);
+                    if (iraw2==ilow) { 
+                        if (ilow==iup) 
+                            xd0=TMath::
+                            Sqrt(2*xmax*2*xmax+2*ymax*2*ymax);
+                        else xd0=101.; 
+                    } 
+                     Float_t qdif=TMath::Abs(q1[iraw1]-q2[iraw2])/q1[iraw1];
+                    
+                    if (x1[iraw1]*xrec2 > 0) {
+                        if (xd <= xd0 )  {
+//                          printf("q1, q2 qdif % f %f %f \n",q1[iraw1],q2[iraw2],qdif);
+//                          printf("x1, x2 y1 y2 % f %f %f %f \n",x1[iraw1],xrec2,y1[iraw1],yrec2);
+                          //if (qdif <0.3) { //check this number
+                                
+                                xd0=xd;
+                                idx2[counter]=iraw2;
+                                xdarray[counter]=xd;
+                                xarray[counter]=xdif;
+                                yarray[counter]=ydif;
+                                qarray[counter]=qdif;
+                                counter++;
+                          // }
+                            
+                        }
+                    } // check for same quadrant
+                 } // loop over 2nd cathode range 
+                
+                
+                 if (counter >=2) {
+                    AliMUONRawCluster::
+                        SortMin(idx2,xdarray,xarray,yarray,qarray,counter);
+                    if (xdarray[0]<seg->Dpx(isec) && xdarray[1]<seg->Dpx(isec)) {
+                        if (qarray[0]>qarray[1]){
+                            Int_t swap=idx2[0];
+                            idx2[0]=idx2[1];
+                            idx2[1]=swap;
+                        }
+                    }
+                }
+                 int imax;
+                 if (counter <3) imax=counter;
+                 else imax=3;
+
+                 for (int i=0;i<imax;i++) {
+                    if (idx2[i] >= 0 && idx2[i] < nrawcl2) {
+                        if (xarray[i] > xmax || yarray[i] > 2*ymax) 
+                            continue;
+                        idx[i]=idx2[i];
+                        xc2[i]=x2[idx2[i]];
+                        yc2[i]=y2[idx2[i]];
+                    }
+                }
+                 // add info about the cluster on the 'starting' cathode
+
+                 idx[3]=iraw1;
+                 xc2[3]=x1[iraw1];
+                 yc2[3]=y1[iraw1];
+                //if (idx[0] <0)  printf("iraw1 imax idx2[0] idx[0] %d %d %d %d\n",iraw1,imax,idx2[0],idx[0]);
+                 AddCathCorrel(ich,idx,xc2,yc2);
+                // reset
+                 for (int i=0;i<counter;i++) {
+                    xdarray[i]=1100.;
+                    xarray[i]=0.;
+                    yarray[i]=0.;
+                    qarray[i]=0.;
+                    idx2[i]=-1;
+                }
+                 for (int i=0;i<3;i++) {
+                    idx[i]=-1;
+                    xc2[i]=0.;
+                    yc2[i]=0.;
+                }
+            } // iraw1
+        }
+        x1.Reset();
+        x2.Reset();     
+        y1.Reset();
+        y2.Reset();     
+        q1.Reset();
+        q2.Reset();     
+     } //ich
+// 
+     if (first) {
+         MakeTreeC("C");
+         first=false;
+     }
+     TTree *TC=TreeC();
+     TC->Fill();
+     //Int_t nentries=(Int_t)TC->GetEntries();
+    //cout<<"number entries in tree of correlated clusters  "<<nentries<<endl;
+     TClonesArray *fCch;
+     static Int_t countev=0;
+     Int_t countch=0;
+
+     for (int i=0;i<10;i++) {
+          fCch= CathCorrelAddress(i);
+          Int_t ncor=fCch->GetEntriesFast();
+          printf (" i, ncor %d %d \n",i,ncor);
+           if (ncor>=2) countch++;
+     }
+
+     // write
+     char hname[30];
+     sprintf(hname,"TreeC%d",nev);
+     TC->Write(hname);
+     // reset tree
+     ResetCorrelation();
+     TC->Reset();
+
+     if (countch==10) countev++;
+     printf("countev - %d\n",countev);
+    
+//     gObjectTable->Print();
+     
+     
+}
+
+
+//_____________________________________________________________________________
+
+void AliMUON::MakeTreeC(Option_t *option)
+{
+     char *C = strstr(option,"C");
+     if (C && !fTreeC) fTreeC = new TTree("TC","CathodeCorrelation");
+
+//  Create a branch for correlation 
+
+     const Int_t buffersize = 4000;
+     char branchname[30];
+
+// one branch for correlation per chamber
+     for (int i=0; i<10 ;i++) {
+         sprintf(branchname,"%sCorrelation%d",GetName(),i+1);
+      
+         if (fCathCorrel   && fTreeC) {
+           TreeC()->Branch(branchname,&((*fCathCorrel)[i]), buffersize);
+           printf("Making Branch %s for correlation in chamber %d\n",branchname,i+1);
+         }     
+     }
+}
+
+//_____________________________________________________________________________
+void AliMUON::GetTreeC(Int_t event)
+{
+
+    // set the branch address
+    char treeName[20];
+    char branchname[30];
+
+    ResetCorrelation();
+    if (fTreeC) {
+         delete fTreeC;
+    }
+
+    sprintf(treeName,"TreeC%d",event);
+    fTreeC = (TTree*)gDirectory->Get(treeName);
+
+
+    TBranch *branch;
+    if (fTreeC) {
+       for (int i=0; i<10; i++) {
+           sprintf(branchname,"%sCorrelation%d",GetName(),i+1);
+           if (fCathCorrel) {
+               branch = fTreeC->GetBranch(branchname);
+               if (branch) branch->SetAddress(&((*fCathCorrel)[i]));
+           }
+       }
+    } else {
+       printf("ERROR: cannot find CathodeCorrelation Tree for event:%d\n",event);
+    }
+
+    // gObjectTable->Print();
+
+}
+
+
 void AliMUON::Streamer(TBuffer &R__b)
 {
    // Stream an object of class AliMUON.
@@ -568,6 +1631,9 @@ void AliMUON::Streamer(TBuffer &R__b)
       AliMUONsegmentation  *segmentation;
       AliMUONresponse      *response;
       TClonesArray         *digitsaddress;
+      TClonesArray         *rawcladdress;
+      TClonesArray         *corcladdress;
+      //      TObjArray            *clustaddress;
       
    if (R__b.IsReading()) {
       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
@@ -575,12 +1641,23 @@ void AliMUON::Streamer(TBuffer &R__b)
       R__b >> fNclusters;
       R__b >> fClusters; // diff
       R__b >> fDchambers;
+      R__b >> fRawClusters;
+      R__b >> fCathCorrel;
       R__b.ReadArray(fNdch);
+      R__b.ReadArray(fNrawch);
+      R__b.ReadArray(fNcorch);
+      //      R__b >> fRecClusters;
       //
       R__b >> fAccCut;
       R__b >> fAccMin;
       R__b >> fAccMax; 
       //   
+      // modifs perso  
+      R__b >> fSPxzCut;  
+      R__b >> fSSigmaCut;
+      R__b >> fSXPrec; 
+      R__b >> fSYPrec;
+      //
       R__b >> fChambers;
 // Stream chamber related information
       for (Int_t i =0; i<10; i++) {
@@ -599,6 +1676,10 @@ void AliMUON::Streamer(TBuffer &R__b)
          response->Streamer(R__b);       
          digitsaddress=(TClonesArray*) (*fDchambers)[i];
          digitsaddress->Streamer(R__b);
+         rawcladdress=(TClonesArray*) (*fRawClusters)[i];
+         rawcladdress->Streamer(R__b);
+         corcladdress=(TClonesArray*) (*fCathCorrel)[i];
+         corcladdress->Streamer(R__b);
       }
       
    } else {
@@ -607,14 +1688,31 @@ void AliMUON::Streamer(TBuffer &R__b)
       R__b << fNclusters;
       R__b << fClusters; // diff
       R__b << fDchambers;
+      R__b << fRawClusters;
+      R__b << fCathCorrel;
       R__b.WriteArray(fNdch, 10);
+      R__b.WriteArray(fNrawch, 10);
+      R__b.WriteArray(fNcorch, 10);
+      //      R__b << fRecClusters;
       //
       R__b << fAccCut;
       R__b << fAccMin;
       R__b << fAccMax; 
       //   
+      // modifs perso  
+      R__b << fSPxzCut;  
+      R__b << fSSigmaCut;
+      R__b << fSXPrec; 
+      R__b << fSYPrec;
+      //
       R__b << fChambers;
 //  Stream chamber related information
+      /*
+      for (Int_t i =0; i<20; i++) {
+         clustaddress=(TObjArray*) (*fRecClusters)[i];
+         clustaddress->Streamer(R__b);
+      }
+      */
       for (Int_t i =0; i<10; i++) {
          iChamber=(AliMUONchamber*) (*fChambers)[i];
          iChamber->Streamer(R__b);
@@ -629,38 +1727,1298 @@ void AliMUON::Streamer(TBuffer &R__b)
          }
           response=iChamber->GetResponseModel();
          response->Streamer(R__b);
-         
          digitsaddress=(TClonesArray*) (*fDchambers)[i];
          digitsaddress->Streamer(R__b);
+         rawcladdress=(TClonesArray*) (*fRawClusters)[i];
+         rawcladdress->Streamer(R__b);
+         corcladdress=(TClonesArray*) (*fCathCorrel)[i];
+         corcladdress->Streamer(R__b);
       }
    }
 }
-AliMUONcluster* AliMUON::FirstPad(AliMUONhit*  hit) 
+AliMUONcluster* AliMUON::FirstPad(AliMUONhit*  hit, TClonesArray *clusters) 
 {
 //
     // Initialise the pad iterator
     // Return the address of the first padhit for hit
-    TClonesArray *theClusters = Clusters();
+    TClonesArray *theClusters = clusters;
     Int_t nclust = theClusters->GetEntriesFast();
     if (nclust && hit->fPHlast > 0) {
        sMaxIterPad=hit->fPHlast;
        sCurIterPad=hit->fPHfirst;
-       return (AliMUONcluster*) fClusters->UncheckedAt(sCurIterPad-1);
+       return (AliMUONcluster*) clusters->UncheckedAt(sCurIterPad-1);
     } else {
        return 0;
     }
 }
 
-AliMUONcluster* AliMUON::NextPad() 
+AliMUONcluster* AliMUON::NextPad(TClonesArray *clusters) 
 {
     sCurIterPad++;
     if (sCurIterPad <= sMaxIterPad) {
-       return (AliMUONcluster*) fClusters->UncheckedAt(sCurIterPad-1);
+       return (AliMUONcluster*) clusters->UncheckedAt(sCurIterPad-1);
     } else {
        return 0;
     }
 }
 
+//////////////////////////// modifs perso ///////////////
+
+static TTree *ntuple_global;
+static TFile *hfile_global;
+
+// variables of the tracking ntuple 
+struct { 
+  Int_t ievr;           // number of event 
+  Int_t ntrackr;        // number of tracks per event
+  Int_t istatr[500];    // 1 = good muon, 2 = ghost, 0 = something else
+  Int_t isignr[500];    // sign of the track
+  Float_t pxr[500];     // x momentum of the reconstructed track
+  Float_t pyr[500];     // y momentum of the reconstructed track
+  Float_t pzr[500];     // z momentum of the reconstructed track
+  Float_t zvr[500];     // z vertex 
+  Float_t chi2r[500];   // chi2 of the fit of the track with the field map
+  Float_t pxv[500];     // x momentum at vertex
+  Float_t pyv[500];     // y momentum at vertex
+  Float_t pzv[500];     // z momentum at vertex
+} ntuple_st;
+
+AliMUONRawCluster *AliMUON::RawCluster(Int_t ichamber, Int_t icathod, Int_t icluster)
+{
+    TClonesArray *MUONrawclust  = RawClustAddress(ichamber);
+    ResetRawClusters();
+    TTree *TR = gAlice->TreeR();
+    Int_t nent=(Int_t)TR->GetEntries();
+    TR->GetEvent(nent-2+icathod-1);
+    //TR->GetEvent(icathod);
+    //Int_t nrawcl = (Int_t)MUONrawclust->GetEntriesFast();
+
+    AliMUONRawCluster * mRaw = (AliMUONRawCluster*)MUONrawclust->UncheckedAt(icluster);
+    //printf("RawCluster _ nent nrawcl icluster mRaw %d %d %d%p\n",nent,nrawcl,icluster,mRaw);
+    
+    return  mRaw;
+}
+
+void AliMUON::Reconst(Int_t &ifit, Int_t &idebug, Int_t bgd_ev, Int_t &nev, Int_t &idres, Int_t &ireadgeant, Option_t *option,Text_t *filename)
+{
+  //
+  // open kine and hits tree of background file for reconstruction of geant hits 
+  // call tracking fortran program
+  static Bool_t first=true;
+  static TFile *File;
+  char *Add = strstr(option,"Add");
+  
+  if (Add ) { // only in case of background with geant hits 
+    if(first) {
+      fFileName=filename;
+      cout<<"filename  "<<fFileName<<endl;
+      File=new TFile(fFileName);
+      cout<<"I have opened "<<fFileName<<" file "<<endl;
+      fHits2     = new TClonesArray("AliMUONhit",1000  );
+      fParticles2 = new TClonesArray("GParticle",1000);
+      first=false;
+    }
+    File->cd();
+    if(fHits2) fHits2->Clear();
+    if(fParticles2) fParticles2->Clear();
+    if(TH1) delete TH1;
+    TH1=0;
+    if(TK1) delete TK1;
+    TK1=0;
+    // Get Hits Tree header from file
+    char treeName[20];
+    sprintf(treeName,"TreeH%d",bgd_ev);
+    TH1 = (TTree*)gDirectory->Get(treeName);
+    if (!TH1) {
+      printf("ERROR: cannot find Hits Tree for event:%d\n",bgd_ev);
+    }
+    // set branch addresses
+    TBranch *branch;
+    char branchname[30];
+    sprintf(branchname,"%s",GetName());
+    if (TH1 && fHits2) {
+      branch = TH1->GetBranch(branchname);
+      if (branch) branch->SetAddress(&fHits2);
+    }
+    TH1->GetEntries();
+    // get the Kine tree
+    sprintf(treeName,"TreeK%d",bgd_ev);
+    TK1 = (TTree*)gDirectory->Get(treeName);
+    if (!TK1) {
+      printf("ERROR: cannot find Kine Tree for event:%d\n",bgd_ev);
+    }
+    // set branch addresses
+    if (TK1) 
+      TK1->SetBranchAddress("Particles", &fParticles2);
+    TK1->GetEvent(0);
+    
+    // get back to the first file
+    TTree *TK = gAlice->TreeK();
+    TFile *file1 = 0;
+    if (TK) file1 = TK->GetCurrentFile();
+    file1->cd();
+    
+  } // end if Add
+  
+  // call tracking fortran program
+  reconstmuon(ifit,idebug,nev,idres,ireadgeant);
+}
+
+
+void AliMUON::Init(Double_t &seff, Double_t &sb0, Double_t &sbl3)
+{
+  //
+  // introduce in fortran program somme parameters and cuts for tracking 
+  // create output file "reconst.root" (histos + ntuple)
+  cutpxz(fSPxzCut);          // Pxz cut (GeV/c) to begin the track finding
+  sigmacut(fSSigmaCut);      // Number of sigmas delimiting the searching areas
+  xpreci(fSXPrec);           // Chamber precision in X (cm) 
+  ypreci(fSYPrec);           // Chamber precision in Y (cm)
+  reco_init(seff,sb0,sbl3);
+}
+
+void AliMUON::FinishEvent()
+{
+    TTree *TK = gAlice->TreeK();
+    TFile *file1 = 0;
+    if (TK) file1 = TK->GetCurrentFile();
+    file1->cd();
+}
+
+void AliMUON::Close()
+{
+  //
+  // write histos and ntuple to "reconst.root" file
+    reco_term();
+}
+
+void chfill(Int_t &id, Float_t &x, Float_t &y, Float_t &w)
+{
+  //
+  // fill histo like hfill in fortran
+    char name[5];
+    sprintf(name,"h%d",id);
+    TH1F *h1 = (TH1F*) gDirectory->Get(name);
+    h1->Fill(x);
+}
+
+void chfill2(Int_t &id, Float_t &x, Float_t &y, Float_t &w)
+{
+  //
+  // fill histo like hfill2 in fortran
+    char name[5];
+    sprintf(name,"h%d",id);
+    TH2F *h2 = (TH2F*) gDirectory->Get(name);
+    h2->Fill(x,y,w);
+}
+
+void chf1(Int_t &id, Float_t &x, Float_t &w)
+{
+  //
+  // fill histo like hf1 in fortran
+    char name[5];
+    sprintf(name,"h%d",id);
+    TH1F *h1 = (TH1F*) gDirectory->Get(name);
+    h1->Fill(x,w);
+}
+
+void hist_create()
+{
+  //
+  // Create an output file ("reconst.root")
+  // Create some histograms and an ntuple
+
+    hfile_global = new TFile("reconst.root","RECREATE","Ntuple - reconstruction");
+
+   ntuple_global = new TTree("ntuple","Reconst ntuple");
+   ntuple_global->Branch("ievr",&ntuple_st.ievr,"ievr/I");
+   ntuple_global->Branch("ntrackr",&ntuple_st.ntrackr,"ntrackr/I");
+   ntuple_global->Branch("istatr",&ntuple_st.istatr[0],"istatr[500]/I");
+   ntuple_global->Branch("isignr",&ntuple_st.isignr[0],"isignr[500]/I");
+   ntuple_global->Branch("pxr",&ntuple_st.pxr[0],"pxr[500]/F");
+   ntuple_global->Branch("pyr",&ntuple_st.pyr[0],"pyr[500]/F");
+   ntuple_global->Branch("pzr",&ntuple_st.pzr[0],"pzr[500]/F");
+   ntuple_global->Branch("zvr",&ntuple_st.zvr[0],"zvr[500]/F");
+   ntuple_global->Branch("chi2r",&ntuple_st.chi2r[0],"chi2r[500]/F");
+   ntuple_global->Branch("pxv",&ntuple_st.pxv[0],"pxv[500]/F");
+   ntuple_global->Branch("pyv",&ntuple_st.pyv[0],"pyv[500]/F");
+   ntuple_global->Branch("pzv",&ntuple_st.pzv[0],"pzv[500]/F");
+
+   // test aliroot
+
+  new TH1F("h100","particule id du hit geant",20,0.,20.);
+  new TH1F("h101","position en x du hit geant",100,-200.,200.);
+  new TH1F("h102","position en y du hit geant",100,-200.,200.);
+  new TH1F("h103","chambre de tracking concernee",15,0.,14.);
+  new TH1F("h104","moment ptot du hit geant",50,0.,100.);
+  new TH1F("h105","px au vertex",50,0.,20.);
+  new TH1F("h106","py au vertex",50,0.,20.);
+  new TH1F("h107","pz au vertex",50,0.,20.);
+  new TH1F("h108","position zv",50,-15.,15.);
+  new TH1F("h109","position en x du hit reconstruit",100,-300.,300.);
+  new TH1F("h110","position en y du hit reconstruit",100,-300.,300.);
+  new TH1F("h111","delta x ",100,-0.4,0.4);
+  new TH1F("h112","delta y ",100,-0.4,0.4);
+
+  char hname[30];
+  char hname1[30];
+  for (int i=0;i<10;i++) {
+    sprintf(hname,"deltax%d",i);
+    sprintf(hname1,"h12%d",i);
+    new TH1F(hname1,hname ,100,-0.4,0.4);
+    sprintf(hname,"deltay%d",i);
+    sprintf(hname1,"h13%d",i);
+    new TH1F(hname1,hname ,100,-0.4,0.4);
+  }
+  new TH2F("h2000","VAR X st. 5",30,3.0,183.0,100,0.,25.);
+  new TH2F("h2001","VAR Y st. 5",30,3.0,183.0,100,0.,25.);
+
+  new TH2F("h2500","P vs X HHIT",30,3.0,183.0,200,0.,200.);
+  new TH2F("h2501","P vs X HHIT**2",30,3.0,183.0,200,0.,5000.);
+  new TH2F("h2502","P vs X EPH2 st. 5",30,3.0,183.0,100,0.,0.000005);
+  new TH2F("h2503","P vs X EAL2 st. 5",30,3.0,183.0,100,0.,0.01);
+  //new TH2F("h2504","P vs X EXM2 st. 5",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2504","P vs X EXM2 st. 5",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2505","P vs X EYM2 st. 5",30,3.0,183.0,100,0.,30.);
+
+  new TH2F("h2507","P vs X EPH st. 5",30,3.0,183.0,100,0.,0.003);
+  new TH2F("h2508","P vs X EAL st. 5",30,3.0,183.0,100,0.,0.3);
+  //new TH2F("h2509","P vs X EXM st. 5",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2509","P vs X EXM st. 5",30,3.0,183.0,100,0.,0.4);
+  new TH2F("h2510","P vs X EYM st. 5",30,3.0,183.0,100,0.,30.);
+
+  new TH2F("h2511","P vs X EPH cut st. 5",30,3.0,183.0,100,0.,0.01);
+  new TH2F("h2512","P vs X EAL cut st. 5",30,3.0,183.0,100,0.,0.3);
+  //new TH2F("h2513","P vs X EXM cut st. 5",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2513","P vs X EXM cut st. 5",30,3.0,183.0,100,0.,0.4);
+  new TH2F("h2514","P vs X EYM cut st. 5",30,3.0,183.0,100,0.,30.);
+  // 4
+  new TH2F("h2400","P vs X HHIT",30,3.0,183.0,200,0.,200.);
+  new TH2F("h2401","P vs X HHIT**2",30,3.0,183.0,200,0.,5000.);
+  new TH2F("h2402","P vs X EPH2 st. 4",30,3.0,183.0,100,0.,0.000005);
+  new TH2F("h2403","P vs X EAL2 st. 4",30,3.0,183.0,100,0.,0.05);
+  //new TH2F("h2404","P vs X EXM2 st. 4",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2404","P vs X EXM2 st. 4",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2405","P vs X EYM2 st. 4",30,3.0,183.0,100,0.,30.);
+
+  new TH2F("h2407","P vs X EPH st. 4",30,3.0,183.0,100,0.,0.003);
+  new TH2F("h2408","P vs X EAL st. 4",30,3.0,183.0,100,0.,0.3);
+  //new TH2F("h2409","P vs X EXM st. 4",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2409","P vs X EXM st. 4",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2410","P vs X EYM st. 4",30,3.0,183.0,100,0.,30.);
+
+  new TH2F("h2411","P vs X EPH cut st. 4",30,3.0,183.0,100,0.,0.01);
+  new TH2F("h2412","P vs X EAL cut st. 4",30,3.0,183.0,100,0.,0.3);
+  //new TH2F("h2413","P vs X EXM cut st. 4",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2413","P vs X EXM cut st. 4",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2414","P vs X EYM cut st. 4",30,3.0,183.0,100,0.,30.);
+  // 3
+  new TH1F("h2301","P2",30,3.0,183.0);
+  new TH2F("h2302","P2 vs X EPH2 st. 3",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2303","P2 vs X EAL2 st. 3",30,3.0,183.0,100,0.,0.0005);
+  //new TH2F("h2304","P2 vs X EXM2 st. 3",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2304","P2 vs X EXM2 st. 3",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2305","P2 vs X EYM2 st. 3",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2307","P vs X EPH2 st. 3",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2308","P vs X EAL2 st. 3",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2309","P vs X EXM2 st. 3",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2309","P vs X EXM2 st. 3",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2310","P vs X EYM2 st. 3",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2311","P vs X EPH cut st. 3",30,3.0,183.0,100,0.,0.06);
+  new TH2F("h2312","P vs X EAL cut st. 3",30,3.0,183.0,100,0.,0.05);
+  //new TH2F("h2313","P vs X EXM cut st. 3",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2313","P vs X EXM cut st. 3",30,3.0,183.0,100,0.,6.);
+  new TH2F("h2314","P vs X EYM cut st. 3",30,3.0,183.0,100,0.,7.);
+
+  new TH2F("h2315","P2 vs X EPH cut st. 3",30,3.0,183.0,100,0.,0.06);
+  new TH2F("h2316","P2 vs X EAL cut st. 3",30,3.0,183.0,100,0.,0.05);
+  //new TH2F("h2317","P2 vs X EXM cut st. 3",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2317","P2 vs X EXM cut st. 3",30,3.0,183.0,100,0.,6.);
+  new TH2F("h2318","P2 vs X EYM cut st. 3",30,3.0,183.0,100,0.,7.);
+  
+  // 2
+  new TH1F("h2201","P2",30,3.0,183.0);
+  new TH2F("h2202","P2 vs X EPH2 st. 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2203","P2 vs X EAL2 st. 2",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2204","P2 vs X EXM2 st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2204","P2 vs X EXM2 st. 2",30,3.0,183.0,100,0.,7.);
+  new TH2F("h2205","P2 vs X EYM2 st. 2",30,3.0,183.0,100,0.,5.);
+
+  new TH2F("h2207","P vs X EPH2 st. 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2208","P vs X EAL2 st. 2",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2209","P vs X EXM2 st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2209","P vs X EXM2 st. 2",30,3.0,183.0,100,0.,7.);
+  new TH2F("h2210","P vs X EYM2 st. 2",30,3.0,183.0,100,0.,5.);
+
+  new TH2F("h2211","P vs X EPH cut st. 2",30,3.0,183.0,100,0.,0.05);
+  new TH2F("h2212","P vs X EAL cut st. 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2213","P vs X EXM cut st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2213","P vs X EXM cut st. 2",30,3.0,183.0,100,0.,11.);
+  new TH2F("h2214","P vs X EYM cut st. 2",30,3.0,183.0,100,0.,10.);
+
+  new TH2F("h2215","P2 vs X EPH cut st. 2",30,3.0,183.0,100,0.,0.05);
+  new TH2F("h2216","P2 vs X EAL cut st. 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2217","P2 vs X EXM cut st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2217","P2 vs X EXM cut st. 2",30,3.0,183.0,100,0.,11.);
+  new TH2F("h2218","P2 vs X EYM cut st. 2",30,3.0,183.0,100,0.,10.);
+
+  // 1
+  new TH2F("h2102","P2 vs X EPH2 st. 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2103","P2 vs X EAL2 st. 2",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2104","P2 vs X EXM2 st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2104","P2 vs X EXM2 st. 2",30,3.0,183.0,100,0.,7.);
+  new TH2F("h2105","P2 vs X EYM2 st. 2",30,3.0,183.0,100,0.,7.);
+
+  new TH2F("h2107","P vs X EPH2 st. 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2108","P vs X EAL2 st. 2",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2109","P vs X EXM2 st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2109","P vs X EXM2 st. 2",30,3.0,183.0,100,0.,7.);
+  new TH2F("h2110","P vs X EYM2 st. 2",30,3.0,183.0,100,0.,7.);
+
+  new TH2F("h2111","P vs X EPH cut st. 2",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2112","P vs X EAL cut st. 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2113","P vs X EXM cut st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2113","P vs X EXM cut st. 2",30,3.0,183.0,100,0.,11.);
+  new TH2F("h2114","P vs X EYM cut st. 2",30,3.0,183.0,100,0.,11.);
+
+  new TH2F("h2115","P2 vs X EPH cut st. 2",30,3.0,183.0,100,0.,0.1);
+  new TH2F("h2116","P2 vs X EAL cut st. 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2117","P2 vs X EXM cut st. 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2117","P2 vs X EXM cut st. 2",30,3.0,183.0,100,0.,11.);
+  new TH2F("h2118","P2 vs X EYM cut st. 2",30,3.0,183.0,100,0.,11.);
+
+  // 2,3,4,5
+  new TH1F("h2701","P2 fit 2",30,3.0,183.0);
+  new TH2F("h2702","P2 vs X EPH2 st. 1 fit 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2703","P2 vs X EAL2 st. 1 fit 2",30,3.0,183.0,100,0.,0.005);
+  // new TH2F("h2704","P2 vs X EXM2 st. 1 fit 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2704","P2 vs X EXM2 st. 1 fit 2",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2705","P2 vs X EYM2 st. 1 fit 2",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2707","P vs X EPH2 st. 1 fit 2",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2708","P vs X EAL2 st. 1 fit 2",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2709","P vs X EXM2 st. 1 fit 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2709","P vs X EXM2 st. 1 fit 2",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2710","P vs X EYM2 st. 1 fit 2",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2711","P vs X EPH cut st. 1 fit 2",30,3.0,183.0,100,0.,0.07);
+  new TH2F("h2712","P vs X EAL cut st. 1 fit 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2713","P vs X EXM cut st. 1 fit 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2713","P vs X EXM cut st. 1 fit 2",30,3.0,183.0,100,0.,6.);
+  new TH2F("h2714","P vs X EYM cut st. 1 fit 2",30,3.0,183.0,100,0.,7.);
+
+  new TH2F("h2715","P2 vs X EPH cut st. 1 fit 2",30,3.0,183.0,100,0.,0.07);
+  new TH2F("h2716","P2 vs X EAL cut st. 1 fit 2",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2717","P2 vs X EXM cut st. 1 fit 2",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2717","P2 vs X EXM cut st. 1 fit 2",30,3.0,183.0,100,0.,6.);
+  new TH2F("h2718","P2 vs X EYM cut st. 1 fit 2",30,3.0,183.0,100,0.,7.);
+
+  // 1,3,4,5
+  new TH1F("h2801","P2 fit 1",30,3.0,183.0);
+  new TH2F("h2802","P2 vs X EPH2 st. 2 fit 1",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2803","P2 vs X EAL2 st. 2 fit 1",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2804","P2 vs X EXM2 st. 2 fit 1",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2804","P2 vs X EXM2 st. 2 fit 1",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2805","P2 vs X EYM2 st. 2 fit 1",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2807","P vs X EPH2 st. 2 fit 1",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h2808","P vs X EAL2 st. 2 fit 1",30,3.0,183.0,100,0.,0.005);
+  //new TH2F("h2809","P vs X EXM2 st. 2 fit 1",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2809","P vs X EXM2 st. 2 fit 1",30,3.0,183.0,100,0.,2.);
+  new TH2F("h2810","P vs X EYM2 st. 2 fit 1",30,3.0,183.0,100,0.,3.);
+
+  new TH2F("h2811","P vs X EPH cut st. 2 fit 1",30,3.0,183.0,100,0.,0.05);
+  new TH2F("h2812","P vs X EAL cut st. 2 fit 1",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2813","P vs X EXM cut st. 2 fit 1",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2813","P vs X EXM cut st. 2 fit 1",30,3.0,183.0,100,0.,5.);
+  new TH2F("h2814","P vs X EYM cut st. 2 fit 1",30,3.0,183.0,100,0.,7.);
+
+  new TH2F("h2815","P2 vs X EPH cut st. 2 fit 1",30,3.0,183.0,100,0.,0.05);
+  new TH2F("h2816","P2 vs X EAL cut st. 2 fit 1",30,3.0,183.0,100,0.,0.2);
+  //new TH2F("h2817","P2 vs X EXM cut st. 2 fit 1",30,3.0,183.0,100,0.,1.5);
+  new TH2F("h2817","P2 vs X EXM cut st. 2 fit 1",30,3.0,183.0,100,0.,5.);
+  new TH2F("h2818","P2 vs X EYM cut st. 2 fit 1",30,3.0,183.0,100,0.,7.);
+  // fin de test
+
+  new TH1F("h500","Acceptance en H st. 4",500,0.,500.);
+  new TH1F("h600","Acceptance en H st. 5",500,0.,500.);
+  new TH1F("h700","X vertex track found",200,-10.,10.);
+  new TH1F("h701","Y vertex track found",200,-10.,10.);
+  new TH1F("h800","Rap. muon gen.",100,0.,5.);
+  new TH1F("h801","Rap. muon gen. recons.",100,0.,5.);
+  new TH1F("h802","Rap. muon gen. ghost ",100,0.,5.);
+  new TH1F("h900","Pt muon gen.",100,0.,20.);
+  new TH1F("h901","Pt muon gen. recons.",100,0.,20.);
+  new TH1F("h902","Pt muon gen. ghost",100,0.,20.);
+  new TH1F("h910","phi muon gen.",100,-10.,10.);
+  new TH1F("h911","phi muon gen. recons.",100,-10.,10.);
+  new TH1F("h912","phi muon gen. ghost",100,-10.,10.);
+  new TH2F("h1001","Y VS X hit st. 1",300,-300.,300.,300,-300.,300.);
+  new TH2F("h1002","Y VS X hit st. 2",300,-300.,300.,300,-300.,300.);
+  new TH2F("h1003","Y VS X hit st. 3",300,-300.,300.,300,-300.,300.);
+  new TH2F("h1004","Y VS X hit st. 4",300,-300.,300.,300,-300.,300.);
+  new TH2F("h1005","Y VS X hit st. 5",300,-300.,300.,300,-300.,300.);
+  //  Histos variance dans 4      
+  new TH2F("h11","VAR X st. 4",30,3.0,183.0,100,0.,2.);
+  new TH2F("h12","VAR Y st. 4",30,3.0,183.0,100,0.,600.);
+  new TH2F("h13","VAR PHI st. 4",30,3.0,183.0,100,0.,0.0001);
+  new TH2F("h14","VAR ALM st. 4",30,3.0,183.0,100,0.,0.05);
+  new TH1F("h15","P",30,3.0,183.0);
+  new TH1F("h411","VAR X st. 4",100,-1.42,1.42);
+  new TH1F("h412","VAR Y st. 4",100,-25.,25.);
+  new TH1F("h413","VAR PHI st. 4",100,-0.01,0.01);
+  new TH1F("h414","VAR ALM st. 4",100,-0.23,0.23);
+  // histo2
+  new TH2F("h211","histo2-VAR X st. 4",30,3.0,183.0,100,0.,2.);
+  new TH2F("h212","histo2-VAR Y st. 4",30,3.0,183.0,100,0.,600.);
+  new TH1F("h213","histo2-VAR X st. 4",100,-1.42,1.42);
+  new TH1F("h214","histo2-VAR Y st. 4",100,-25.,25.);
+  new TH1F("h215","histo2-P",30,3.0,183.0);
+
+  //  Histos variance dans 2      
+  new TH2F("h21","VAR X st. 2",30,3.0,183.0,100,0.,3.);
+  new TH2F("h22","VAR Y st. 2",30,3.0,183.0,100,0.,7.);
+  new TH2F("h23","VAR PHI st. 2",30,3.0,183.0,100,0.,0.006);
+  new TH2F("h24","VAR ALM st. 2",30,3.0,183.0,100,0.,0.005);
+  new TH1F("h25","P",30,3.0,183.0);
+  new TH1F("h421","VAR X st. 2",100,-1.72,1.72);
+  new TH1F("h422","VAR Y st. 2",100,-2.7,2.7);
+  new TH1F("h423","VAR PHI st. 2",100,-0.08,0.08);
+  new TH1F("h424","VAR ALM st. 2",100,-0.072,0.072);
+  // histo2
+  new TH2F("h221","histo2-VAR X st. 2",30,3.0,183.0,100,0.,3.);
+  new TH2F("h222","histo2-VAR Y st. 2",30,3.0,183.0,100,0.,7.);
+  new TH1F("h223","histo2-VAR X st. 2",100,-1.72,1.72);
+  new TH1F("h224","histo2-VAR Y st. 2",100,-2.7,2.7);
+  new TH1F("h225","histo2-P",30,3.0,183.0);
+
+  //  Histos variance dans 1      
+  new TH2F("h31","VAR X st. 1",30,3.0,183.0,100,0.,2.);
+  new TH2F("h32","VAR Y st. 1",30,3.0,183.0,100,0.,0.5);
+  new TH2F("h33","VAR PHI st. 1",30,3.0,183.0,100,0.,0.006);
+  new TH2F("h34","VAR ALM st. 1",30,3.0,183.0,100,0.,0.005);
+  new TH1F("h35","P",30,3.0,183.0);
+  new TH1F("h431","VAR X st. 1",100,-1.42,1.42);
+  new TH1F("h432","VAR Y st. 1",100,-0.72,0.72);
+  new TH1F("h433","VAR PHI st. 1",100,-0.08,0.08);
+  new TH1F("h434","VAR ALM st. 1",100,-0.072,0.072);
+  //  Histos variance dans 1      
+  new TH2F("h41","VAR X st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,4.);
+  new TH2F("h42","VAR Y st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,20.);
+  new TH2F("h43","VAR PHI st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,0.005);
+  new TH2F("h44","VAR ALM st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,0.005);
+  new TH1F("h45","P",30,3.0,183.0);
+  new TH1F("h441","VAR X st. 1 fit 5,4,3,2,V",100,-2.,2.);
+  new TH1F("h442","VAR Y st. 1 fit 5,4,3,2,V",100,-4.5,4.5);
+  new TH1F("h443","VAR PHI st. 1 fit 5,4,3,2,V",100,-0.072,0.072);
+  new TH1F("h444","VAR ALM st. 1 fit 5,4,3,2,V",100,-0.072,0.072);
+  // histo2
+  new TH2F("h241","histo2-VAR X st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,4.);
+  new TH2F("h242","histo2-VAR Y st. 1 fit 5,4,3,2,V",30,3.0,183.0,100,0.,20.);
+  new TH1F("h243","histo2-VAR X st. 1 fit 5,4,3,2,V",100,-2.,2.);
+  new TH1F("h244","histo2-VAR Y st. 1 fit 5,4,3,2,V",100,-4.5,4.5);
+  new TH1F("h245","histo2-P",30,3.0,183.0);
+
+  //  Histos variance dans 2      
+  new TH2F("h51","VAR X st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,0.5);
+  new TH2F("h52","VAR Y st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,2.);
+  new TH2F("h53","VAR PHI st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,0.005);
+  new TH2F("h54","VAR ALM st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,0.01);
+  new TH1F("h55","P",30,3.0,183.0);
+  new TH1F("h451","VAR X st. 2 fit 5,4,3,1,V",100,-0.72,0.72);
+  new TH1F("h452","VAR Y st. 2 fit 5,4,3,1,V",100,-1.42,1.42);
+  new TH1F("h453","VAR PHI st. 2 fit 5,4,3,1,V",100,-0.072,0.072);
+  new TH1F("h454","VAR ALM st. 2 fit 5,4,3,1,V",100,-0.1,0.1);
+  new TH1F("h999","PTOT",30,3.0,183.0);
+  // histo2
+  new TH2F("h251","histo2-VAR X st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,0.5);
+  new TH2F("h252","histo2-VAR Y st. 2 fit 5,4,3,1,V",30,3.0,183.0,100,0.,2.);
+  new TH1F("h253","histo2-VAR X st. 2 fit 5,4,3,1,V",100,-0.72,0.72);
+  new TH1F("h254","histo2-VAR Y st. 2 fit 5,4,3,1,V",100,-1.42,1.42);
+  new TH1F("h255","histo2-P",30,3.0,183.0);
+  //  Histos variance dans 3      
+  new TH2F("h61","VAR X st. 3 fit 4,5,V",30,3.0,183.0,100,0.,5.);
+  new TH2F("h62","VAR Y st. 3 fit 4,5,V",30,3.0,183.0,100,0.,2.);
+  new TH2F("h63","VAR PHI st. 3 fit 4,5,V",30,3.0,183.0,100,0.,0.0006);
+  new TH2F("h64","VAR ALM st. 3 fit 4,5,V",30,3.0,183.0,100,0.,0.0006);
+  new TH1F("h65","P",30,3.0,183.0);
+  new TH1F("h461","VAR X st. 3 fit 4,5,V",100,-2.25,2.25);
+  new TH1F("h462","VAR Y st. 3 fit 4,5,V",100,-1.42,1.42);
+  new TH1F("h463","VAR PHI st. 3 fit 4,5,V",100,-0.024,0.024);
+  new TH1F("h464","VAR ALM st. 3 fit 4,5,V",100,-0.024,0.024);
+  // histo2
+  new TH2F("h261","histo2-VAR X st. 3 fit 4,5,V",30,3.0,183.0,100,0.,5.);
+  new TH2F("h262","histo2-VAR Y st. 3 fit 4,5,V",30,3.0,183.0,100,0.,2.);
+  new TH1F("h263","histo2-VAR X st. 3 fit 4,5,V",100,-2.25,2.25);
+  new TH1F("h264","histo2-VAR Y st. 3 fit 4,5,V",100,-1.42,1.42);
+  new TH1F("h265","Phisto2-",30,3.0,183.0);
+  // Histos dx,dy distribution between chambers inside stations
+  new TH1F("h71","DX in st. ID-70",100,-5.,5.);
+  new TH1F("h81","DY in st. ID-80",100,-5.,5.);
+  new TH1F("h72","DX in st. ID-70",100,-5.,5.);
+  new TH1F("h82","DY in st. ID-80",100,-5.,5.);
+  new TH1F("h73","DX in st. ID-70",100,-5.,5.);
+  new TH1F("h83","DY in st. ID-80",100,-5.,5.);
+  new TH1F("h74","DX in st. ID-70",100,-5.,5.);
+  new TH1F("h84","DY in st. ID-80",100,-5.,5.);
+  new TH1F("h75","DX in st. ID-70",100,-5.,5.);
+  new TH1F("h85","DY in st. ID-80",100,-5.,5.);
+}
+
+void chfnt(Int_t &ievr, Int_t &ntrackr, Int_t *istatr, Int_t *isignr, Float_t *pxr, Float_t *pyr, Float_t *pzr, Float_t *zvr, Float_t *chi2r,  Float_t *pxv, Float_t *pyv, Float_t *pzv)
+{
+  //
+  // fill the ntuple 
+    ntuple_st.ievr = ievr;
+    ntuple_st.ntrackr = ntrackr;
+    for (Int_t i=0; i<500; i++) {
+       ntuple_st.istatr[i] = istatr[i];
+       ntuple_st.isignr[i] = isignr[i]; 
+       ntuple_st.pxr[i]    = pxr[i]; 
+       ntuple_st.pyr[i]    = pyr[i];
+       ntuple_st.pzr[i]    = pzr[i];
+       ntuple_st.zvr[i]    = zvr[i];
+       ntuple_st.chi2r[i]  = chi2r[i];
+       ntuple_st.pxv[i]    = pxv[i]; 
+       ntuple_st.pyv[i]    = pyv[i];
+       ntuple_st.pzv[i]    = pzv[i];
+    }
+    ntuple_global->Fill();   
+}
+
+void hist_closed()
+{
+  //
+  // write histos and ntuple to "reconst.root" file
+  hfile_global->Write();
+}
+
+void trackf_read_geant(Int_t *itypg, Double_t *xtrg, Double_t *ytrg, Double_t *ptotg, Int_t *idg, Int_t *izch, Double_t *pvert1g, Double_t *pvert2g, Double_t *pvert3g, Double_t *zvertg, Int_t &nhittot1, Double_t *cx, Double_t *cy, Double_t *cz, Int_t &ievr,Int_t &nev,Double_t *xgeant, Double_t *ygeant,Double_t *clsize1, Double_t *clsize2) 
+{
+  //
+  // introduce aliroot variables in fortran common 
+  // tracking study from geant hits 
+  //
+
+  AliMUON *MUON  = (AliMUON*) gAlice->GetModule("MUON");
+  
+  //  TTree *TK = gAlice->TreeK();
+  TTree *TH = gAlice->TreeH();
+  Int_t ntracks = (Int_t)TH->GetEntries();
+  cout<<"ntrack="<<ntracks<<endl;
+
+  Int_t maxidg = 0;
+  Int_t nres=0;
+  
+//
+//  Loop over tracks
+//
+
+  for (Int_t track=0; track<ntracks;track++) {
+      gAlice->ResetHits();
+      TH->GetEvent(track);
+      
+      if (MUON)  {
+//
+//  Loop over hits
+//
+         for(AliMUONhit* mHit=(AliMUONhit*)MUON->FirstHit(-1); 
+             mHit;
+             mHit=(AliMUONhit*)MUON->NextHit()) 
+         {
+             if (maxidg<=20000) {
+               
+               if (mHit->fChamber > 10) continue;
+               TClonesArray *fPartArray = gAlice->Particles();
+               TParticle *Part;
+               Int_t ftrack = mHit->fTrack;
+               Int_t id = ((TParticle*) fPartArray->UncheckedAt(ftrack))->GetPdgCode();
+
+               if (id==kMuonPlus||id==kMuonMinus) {
+                   
+                   // inversion de x et y car le champ est inverse dans le programme tracking
+                   xtrg[maxidg]   = 0;       
+                   ytrg[maxidg]   = 0;       
+                   xgeant[maxidg]   = mHit->fY;             // x-pos of hit
+                   ygeant[maxidg]   = mHit->fX;             // y-pos of hit
+                   clsize1[maxidg]   = 0;     // cluster size on 1-st cathode
+                   clsize2[maxidg]   = 0;     // cluster size on 2-nd cathode
+                   cx[maxidg]     = mHit->fCyHit;            // Px/P of hit
+                   cy[maxidg]     = mHit->fCxHit;            // Py/P of hit
+                   cz[maxidg]     = mHit->fCzHit;            // Pz/P of hit
+                   izch[maxidg]   = mHit->fChamber; 
+                   /*      
+                   Int_t pdgtype  = Int_t(mHit->fParticle); // particle number
+                   itypg[maxidg]  = gMC->IdFromPDG(pdgtype);
+
+                   */
+                    if (id==kMuonPlus) itypg[maxidg]  = 5;
+                   else  itypg[maxidg]  = 6;
+
+
+
+                    //printf("ich, itypg[maxidg] %d %d\n",izch[maxidg],itypg[maxidg]);
+
+                   ptotg[maxidg]  = mHit->fPTot;          // P of hit 
+                   
+                   Part = (TParticle*) fPartArray->UncheckedAt(ftrack);
+                   Float_t thet = Part->Theta();
+                   thet = thet*180./3.1416;
+                   
+                   //cout<<"chambre "<<izch[maxidg]<<"  ptot="<<ptotg[maxidg]<<"   theta="<<thet<<"   phi="<<mHit->fPhi<<" z="<<zz<<endl;          
+                   
+                   Int_t iparent = Part->GetFirstMother();
+                   if (iparent >= 0) {
+                       Int_t ip;
+                       while(1) {
+                           ip=((TParticle*) fPartArray->UncheckedAt(iparent))->GetFirstMother();
+                           if (ip < 0) {
+                               break;
+                           } else {
+                               iparent = ip;
+                           }
+                       }
+                   }
+                   //printf("iparent - %d\n",iparent);
+                   Int_t id1  = ftrack; // numero de la particule generee au vertex
+                   Int_t idum = track+1;
+                   Int_t id2 = ((TParticle*) fPartArray->UncheckedAt(iparent))->GetPdgCode();
+
+                   if (id2==443) id2=114;
+                   else id2=116;
+                   
+                    if (id2==116) {
+                     nres++;
+                   }
+                   //printf("id2 %d\n",id2);
+                   idg[maxidg] = 30000*id1+10000*idum+id2;
+                   
+                   pvert1g[maxidg] = Part->Py();      // Px vertex
+                   pvert2g[maxidg] = Part->Px();      // Py vertex  
+                   pvert3g[maxidg] = Part->Pz();      // Pz vertex
+                   zvertg[maxidg]  = Part->Vz();      // z vertex 
+           
+                   //      cout<<"x="<<xgeant[maxidg]<<endl;
+                   //cout<<"y="<<ygeant[maxidg]<<endl;
+                   //cout<<"typ="<<itypg[maxidg]<<endl;
+
+                   maxidg ++;
+
+               }
+             }
+         } // hit loop
+      } // if MUON
+  } // track loop first file
+
+  if (TH1 && fHits2 ) { // if background file
+    ntracks =(Int_t)TH1->GetEntries();
+    printf("Trackf_read - 2-nd file - ntracks %d\n",ntracks);
+
+    //  Loop over tracks
+    for (Int_t track=0; track<ntracks; track++) {
+      
+      if (fHits2) fHits2->Clear();
+      TH1->GetEvent(track);
+
+      //  Loop over hits
+      for (int i=0;i<fHits2->GetEntriesFast();i++) 
+       {
+         AliMUONhit *mHit=(AliMUONhit*) (*fHits2)[i];
+         
+          if (mHit->fChamber > 10) continue;
+
+         if (maxidg<=20000) {
+           
+           // inversion de x et y car le champ est inverse dans le programme tracking !!!!
+           xtrg[maxidg]   = 0;                    // only for reconstructed point
+           ytrg[maxidg]   = 0;                    // only for reconstructed point
+           xgeant[maxidg]   = mHit->fY;           // x-pos of hit
+           ygeant[maxidg]   = mHit->fX;           // y-pos of hit
+           clsize1[maxidg]   = 0;           // cluster size on 1-st cathode
+           clsize2[maxidg]   = 0;           // cluster size on 2-nd cathode
+           cx[maxidg]     = mHit->fCyHit;         // Px/P of hit
+           cy[maxidg]     = mHit->fCxHit;         // Py/P of hit
+           cz[maxidg]     = mHit->fCzHit;         // Pz/P of hit
+           izch[maxidg]   = mHit->fChamber;       // chamber number
+           ptotg[maxidg]  = mHit->fPTot;          // P of hit 
+           
+           Int_t ftrack = mHit->fTrack;
+           Int_t id1  = ftrack;                   // track number 
+           Int_t idum = track+1;
+           
+           TClonesArray *fPartArray = fParticles2;
+           TParticle *Part;
+           Int_t id = ((TParticle*) fPartArray->UncheckedAt(ftrack))->GetPdgCode();
+           if (id==kMuonPlus||id==kMuonMinus) {
+               if (id==kMuonPlus) itypg[maxidg]  = 5;
+               else  itypg[maxidg]  = 6;
+           } else itypg[maxidg]=0;
+           
+           Int_t id2=0; // set parent to 0 for background !!
+           idg[maxidg] = 30000*id1+10000*idum+id2;
+           
+           pvert1g[maxidg] = Part->Py();      // Px vertex
+           pvert2g[maxidg] = Part->Px();      // Py vertex  
+           pvert3g[maxidg] = Part->Pz();      // Pz vertex
+           zvertg[maxidg]  = Part->Vz();      // z vertex 
+
+           maxidg ++;
+
+         } // check limits (maxidg)
+       } // hit loop 
+    } // track loop
+  } // if TH1
+
+  ievr = nev;
+  nhittot1 = maxidg ;
+  cout<<"nhittot1="<<nhittot1<<endl;
+
+  static Int_t nbres=0;
+  if (nres>=19) nbres++;
+  printf("nres, nbres %d %d \n",nres,nbres);
+
+  hfile_global->cd();      
+
+}
+
+
+
+void trackf_read_spoint(Int_t *itypg, Double_t *xtrg, Double_t *ytrg, Double_t *ptotg, Int_t *idg, Int_t *izch, Double_t *pvert1g, Double_t *pvert2g, Double_t *pvert3g, Double_t *zvertg, Int_t &nhittot1, Double_t *cx, Double_t *cy, Double_t *cz, Int_t &ievr,Int_t &nev,Double_t *xgeant, Double_t *ygeant,Double_t *clsize1, Double_t *clsize2) 
+
+{
+  //
+  // introduce aliroot variables in fortran common 
+  // tracking study from reconstructed points 
+  //
+  AliMUON *MUON  = (AliMUON*) gAlice->GetModule("MUON");
+
+  cout<<"numero de l'evenement "<<nev<<endl;
+  
+  MUON->GetTreeC(nev);
+  TTree *TC=MUON->TreeC();
+  TC->GetEntries();
+
+  Int_t maxidg = 0;
+  Int_t nres=0;
+  Int_t nncor=0;
+  static Int_t nuncor=0;
+  static Int_t nbadcor=0;
+  AliMUONRawCluster * mRaw;
+  AliMUONRawCluster * mRaw1;
+  TTree *TH = gAlice->TreeH();
+
+  Int_t ihit;
+  Int_t mult1, mult2;
+  if (MUON) {
+      for (Int_t ich=0;ich<10;ich++) {
+         TClonesArray *MUONcorrel  = MUON->CathCorrelAddress(ich);
+         MUON->ResetCorrelation();
+         TC->GetEvent();
+         Int_t ncor = (Int_t)MUONcorrel->GetEntries();
+         if (ncor>=2) nncor++;
+         if (!ncor) continue;
+
+         //  Loop over correlated clusters
+         for (Int_t icor=0;icor<ncor;icor++) {
+             AliMUONcorrelation * mCor = (AliMUONcorrelation*)MUONcorrel->UncheckedAt(icor);
+
+              Int_t flag=0;   // = 1 if no information in the second cathode
+             Int_t index = mCor->fCorrelIndex[0]; // for the second cathode
+              if (index >= 0) {
+                 Int_t index1 = mCor->fCorrelIndex[3]; // for the 1-st cathode
+                 mRaw1 = MUON->RawCluster(ich,1,index1);
+                  mult1=mRaw1->fMultiplicity;
+                 mRaw = MUON->RawCluster(ich,2,index);
+                 mult2=mRaw->fMultiplicity;
+              } else {
+                 index = mCor->fCorrelIndex[3];
+                 mRaw = MUON->RawCluster(ich,1,index);
+                 mult1=mRaw->fMultiplicity;
+                 mult2=0;
+                  flag=1;
+                 nuncor++;
+             }
+             if (!mRaw) continue;
+
+             Int_t ftrack1 = mRaw->fTracks[1]; // qui doit etre le meme pour 
+                                               // la cathode 1 et 2
+              ihit= mRaw->fTracks[0];
+             //printf("icor, ftrack1 ihit %d %d %d\n",icor,ftrack1,ihit);
+
+              if (mRaw->fClusterType == 0 ) {
+
+                 if (maxidg<=20000) {
+                     if (flag == 0) {
+                         xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                         ytrg[maxidg]   = (Double_t) mCor->fX[0];
+                         Int_t index1 = mCor->fCorrelIndex[3];
+                         mRaw1 = MUON->RawCluster(ich,1,index1);
+                         if (mRaw1->fClusterType==1 || mRaw1->fClusterType==2) {
+                           Float_t xclust=mCor->fX[3];
+                           Float_t yclust=mCor->fY[3];
+                           AliMUONchamber *iChamber=&(MUON->Chamber(ich));
+                           AliMUONsegmentation *seg = iChamber->GetSegmentationModel(1);
+                           Int_t ix,iy;
+                           seg->GetPadIxy(xclust,yclust,ix,iy);   
+                           Int_t isec=seg->Sector(ix,iy);
+                           printf("nev, CORRELATION with pure background in chamber sector %d  %d  %d !!!!!!!!!!!!!!!!!!!!!\n",nev,ich+1,isec);
+                           nbadcor++;
+                           
+                         } // end if cluster type on cathode 1
+                     }else {
+                         xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                         ytrg[maxidg]   = (Double_t) mCor->fX[3];
+                     } // if iflag
+                     izch[maxidg]   = ich+1;
+                     xgeant[maxidg] = 0;
+                     ygeant[maxidg] = 0;
+                     clsize1[maxidg] = mult1;
+                     clsize2[maxidg] = mult2;
+
+                     cx[maxidg]     = 0; // Px/P of hit
+                     cy[maxidg]     = 0; // Py/P of hit
+                     cz[maxidg]     = 0; // Pz/P of hit
+                     itypg[maxidg]  = 0; // particle number
+                     ptotg[maxidg]  = 0; // P of hit
+                     idg[maxidg]    = 0;
+                     pvert1g[maxidg] = 0; // Px vertex
+                     pvert2g[maxidg] = 0; // Py vertex  
+                     pvert3g[maxidg] = 0; // Pz vertex
+                     zvertg[maxidg]  = 0; // z vertex     
+                     maxidg++;
+                     
+                 }// fin maxidg
+                 
+             } else if (mRaw->fClusterType ==1 && ftrack1 < 0) // background + resonance
+               {
+                  nres++;
+                 // get indexmap and loop over digits to find the signal
+                 Int_t nent=(Int_t)gAlice->TreeD()->GetEntries();
+                 gAlice->ResetDigits();
+                 if (flag==0) {
+                   //gAlice->TreeD()->GetEvent(2); // cathode 2
+                   gAlice->TreeD()->GetEvent(nent-1); // cathode 2
+                 } else {
+                   //gAlice->TreeD()->GetEvent(1); // cathode 1
+                   gAlice->TreeD()->GetEvent(nent-2); // cathode 1
+                 }
+
+                  TClonesArray *MUONdigits  = MUON->DigitsAddress(ich);
+                   Int_t mul=mRaw->fMultiplicity;
+                   Int_t trsign;
+                   for (int i=0;i<mul;i++) {
+                    Int_t idx=mRaw->fIndexMap[i];
+                     AliMUONdigit *dig= (AliMUONdigit*)MUONdigits->UncheckedAt(idx);
+                    trsign=dig->fTracks[0];
+                     ihit=dig->fHit-1;
+                     if (trsign > 0 && ihit >= 0) break;
+
+                  } // loop over indexmap
+
+                  //printf("trsign, ihit %d %d\n",trsign,ihit);
+                  //printf("signal+background : trsign  %d\n",trsign);
+                  
+                  if (trsign < 0 || ihit < 0) { // no signal muon  was found
+                    
+                    if (maxidg<=20000) {
+                      if (flag == 0) {
+                        xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                        ytrg[maxidg]   = (Double_t) mCor->fX[0];
+                      }else {
+                        xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                        ytrg[maxidg]   = (Double_t) mCor->fX[3];
+                      }
+                      
+                      izch[maxidg]   = ich+1;
+
+                     // initialisation of informations which 
+                     // can't be reached for background
+                      
+                      xgeant[maxidg] = 0; // only for resonances
+                      ygeant[maxidg] = 0; // only for resonances
+                      clsize1[maxidg] = mult1;
+                      clsize2[maxidg] = mult2;
+
+                      cx[maxidg]     = 0; // Px/P of hit
+                      cy[maxidg]     = 0; // Py/P of hit
+                      cz[maxidg]     = 0; // Pz/P of hit
+                      itypg[maxidg]  = 0; // particle number
+                      ptotg[maxidg]  = 0; // P of hit
+                      idg[maxidg]    = 0;
+                      pvert1g[maxidg] = 0; // Px vertex
+                      pvert2g[maxidg] = 0; // Py vertex  
+                      pvert3g[maxidg] = 0; // Pz vertex
+                      zvertg[maxidg]  = 0;                
+                      maxidg++;
+                      
+                    }// fin maxidg
+                  } else { // signal muon - retrieve info
+                    //printf("inside trsign, ihit %d %d\n",trsign,ihit);
+                    if (maxidg<=20000) {
+                      if (flag == 0) {
+                        xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                        ytrg[maxidg]   = (Double_t) mCor->fX[0];
+                      }else {
+                        xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                        ytrg[maxidg]   = (Double_t) mCor->fX[3];
+                      }
+                      izch[maxidg]   = ich+1;
+                      clsize1[maxidg] = mult1;
+                      clsize2[maxidg] = mult2;
+
+                     // initialise and set to the correct values 
+                     // if signal muons 
+                      
+                      xgeant[maxidg] = 0; // only for resonances
+                      ygeant[maxidg] = 0; // only for resonances
+                      
+                      cx[maxidg]     = 0; // Px/P of hit
+                      cy[maxidg]     = 0; // Py/P of hit
+                      cz[maxidg]     = 0; // Pz/P of hit
+                      itypg[maxidg]  = 0; // particle number
+                      ptotg[maxidg]  = 0; // P of hit
+                      idg[maxidg]    = 0;
+                      pvert1g[maxidg] = 0; // Px vertex
+                      pvert2g[maxidg] = 0; // Py vertex  
+                      pvert3g[maxidg] = 0; // Pz vertex
+                      zvertg[maxidg]  = 0;     
+                      // try to retrieve info about signal muons          
+                      gAlice->ResetHits();
+                      TH->GetEvent(trsign);
+
+                      TClonesArray *MUONhits  = MUON->Hits();
+                      AliMUONhit *mHit= (AliMUONhit*)MUONhits->
+                                                        UncheckedAt(ihit);
+                          TClonesArray *fPartArray = gAlice->Particles();
+                          TParticle *Part;
+                          Int_t nch=mHit->fChamber-1;
+                          //printf("sig+bgr ich, nch %d %d \n",ich,nch);
+                          if (nch==ich) {
+                            Int_t ftrack = mHit->fTrack;
+                            Int_t id = ((TParticle*) fPartArray->
+                                        UncheckedAt(ftrack))->GetPdgCode();
+                            if (id==kMuonPlus||id==kMuonMinus) {
+                                xgeant[maxidg] = (Double_t) mHit->fY;
+                                ygeant[maxidg] = (Double_t) mHit->fX;
+                                cx[maxidg]     = (Double_t) mHit->fCyHit; 
+                                cy[maxidg]     = (Double_t) mHit->fCxHit; 
+                                cz[maxidg]     = (Double_t) mHit->fCzHit; 
+
+                                if (id==kMuonPlus) {
+                                  itypg[maxidg]  = 5;
+                                } else if (id==kMuonMinus) {
+                                  itypg[maxidg]  = 6;
+                                } else itypg[maxidg]  = 0;
+                            
+                                ptotg[maxidg]  = (Double_t) mHit->fPTot;  
+                                Part = (TParticle*) fPartArray->
+                                                    UncheckedAt(ftrack);
+                                Int_t iparent = Part->GetFirstMother();
+                                Int_t id2;
+                                id2 = ((TParticle*) fPartArray->
+                                       UncheckedAt(ftrack))->GetPdgCode();
+                            
+                                if (iparent >= 0) {
+                                  Int_t ip;
+                                  while(1) {
+                                    ip=((TParticle*) fPartArray->
+                                      UncheckedAt(iparent))->GetFirstMother();
+                                    if (ip < 0) {
+                                      id2 = ((TParticle*) fPartArray->
+                                          UncheckedAt(iparent))->GetPdgCode();
+                                      break;
+                                    } else {
+                                      iparent = ip;
+                                      id2 = ((TParticle*) fPartArray->
+                                          UncheckedAt(iparent))->GetPdgCode();
+                                    } // ip<0
+                                  } // while
+                                }// iparent
+                                Int_t id1  = ftrack; 
+                                Int_t idum = trsign+1;
+                            
+                                if (id2==443 || id2==553) {
+                                  nres++;
+                                  if (id2==443) id2=114;
+                                  else id2=116;
+                                }
+                            
+                                idg[maxidg] = 30000*id1+10000*idum+id2;
+                                pvert1g[maxidg] = (Double_t) Part->Py(); 
+                                pvert2g[maxidg] = (Double_t) Part->Px();   
+                                pvert3g[maxidg] = (Double_t) Part->Pz(); 
+                                zvertg[maxidg]  = (Double_t) Part->Vz();  
+                            } //if muon                             
+                          } //if nch
+                    maxidg++;
+                    } // check limits
+                  } // sign+bgr, highest bgr
+             } 
+              //pure resonance or mixed cluster with the highest 
+             //contribution coming from resonance
+             if (mRaw->fClusterType >= 1 && ftrack1>=0)  
+               {                             
+                 if (maxidg<=20000) {
+                   if (flag == 0) {
+                     xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                     ytrg[maxidg]   = (Double_t) mCor->fX[0];
+                   }else {
+                     xtrg[maxidg]   = (Double_t) mCor->fY[3];
+                     ytrg[maxidg]   = (Double_t) mCor->fX[3];
+                   }
+                   clsize1[maxidg] = mult1;
+                   clsize2[maxidg] = mult2;
+                   izch[maxidg]   = ich+1;
+
+                   Int_t nent=(Int_t)gAlice->TreeD()->GetEntries();
+                   gAlice->ResetDigits();
+                   if (flag==0) {
+                     //gAlice->TreeD()->GetEvent(2); // cathode 2
+                     gAlice->TreeD()->GetEvent(nent-1); // cathode 2
+                   } else {
+                     //gAlice->TreeD()->GetEvent(1);        // cathode 1
+                     gAlice->TreeD()->GetEvent(nent-2); // cathode 1
+                   }
+
+                   TClonesArray *MUONdigits  = MUON->DigitsAddress(ich);
+                   Int_t mul=mRaw->fMultiplicity;
+                   for (int i=0;i<mul;i++) {
+                     Int_t idx=mRaw->fIndexMap[i];
+                     AliMUONdigit *dig= (AliMUONdigit*)MUONdigits->UncheckedAt(idx);
+                     ihit=dig->fHit-1;
+                     if (ihit >= 0) break;
+
+                  } // loop over indexmap
+                   //printf("fClusterType, ihit %d %d \n",mRaw->fClusterType,ihit);
+                   if (ihit < 0) {
+                      xgeant[maxidg] = 0; // only for resonances
+                      ygeant[maxidg] = 0; // only for resonances
+                      
+                      cx[maxidg]     = 0; // Px/P of hit
+                      cy[maxidg]     = 0; // Py/P of hit
+                      cz[maxidg]     = 0; // Pz/P of hit
+                      itypg[maxidg]  = 0; // particle number
+                      ptotg[maxidg]  = 0; // P of hit
+                      idg[maxidg]    = 0;
+                      pvert1g[maxidg] = 0; // Px vertex
+                      pvert2g[maxidg] = 0; // Py vertex  
+                      pvert3g[maxidg] = 0; // Pz vertex
+                      zvertg[maxidg]  = 0;     
+                   } else {
+                   gAlice->ResetHits();
+                   TH->GetEvent(ftrack1);
+                   TClonesArray *MUONhits  = MUON->Hits();
+                   AliMUONhit *mHit= (AliMUONhit*)MUONhits->
+                                                       UncheckedAt(ihit);
+                          TClonesArray *fPartArray = gAlice->Particles();
+                          TParticle *Part;
+                          Int_t nch=mHit->fChamber-1;
+                          //printf("signal ich, nch %d %d \n",ich,nch);
+                          if (nch==ich) {
+                            Int_t ftrack = mHit->fTrack;
+                            Int_t id = ((TParticle*) fPartArray->
+                                        UncheckedAt(ftrack))->GetPdgCode();
+                            //printf("id %d \n",id);
+                            if (id==kMuonPlus||id==kMuonMinus) {
+                                xgeant[maxidg] = (Double_t) mHit->fY;
+                                ygeant[maxidg] = (Double_t) mHit->fX;
+                                cx[maxidg]     = (Double_t) mHit->fCyHit; 
+                                cy[maxidg]     = (Double_t) mHit->fCxHit; 
+                                cz[maxidg]     = (Double_t) mHit->fCzHit; 
+
+                                if (id==kMuonPlus) {
+                                  itypg[maxidg]  = 5;
+                                } else if (id==kMuonMinus) {
+                                  itypg[maxidg]  = 6;
+                                } else itypg[maxidg]  = 0;
+                            
+                                ptotg[maxidg]  = (Double_t) mHit->fPTot;  
+                                Part = (TParticle*) fPartArray->
+                                                    UncheckedAt(ftrack);
+                                Int_t iparent = Part->GetFirstMother();
+                                Int_t id2;
+                                id2 = ((TParticle*) fPartArray->
+                                       UncheckedAt(ftrack))->GetPdgCode();
+                            
+                                if (iparent >= 0) {
+                                  Int_t ip;
+                                  while(1) {
+                                    ip=((TParticle*) fPartArray->
+                                      UncheckedAt(iparent))->GetFirstMother();
+                                    if (ip < 0) {
+                                      id2 = ((TParticle*) fPartArray->
+                                          UncheckedAt(iparent))->GetPdgCode();
+                                      break;
+                                    } else {
+                                      iparent = ip;
+                                      id2 = ((TParticle*) fPartArray->
+                                          UncheckedAt(iparent))->GetPdgCode();
+                                    } // ip<0
+                                  } // while
+                                }// iparent
+                                Int_t id1  = ftrack; 
+                                Int_t idum = ftrack1+1;
+                            
+                                if (id2==443 || id2==553) {
+                                  nres++;
+                                  if (id2==443) id2=114;
+                                  else id2=116;
+                                }
+                                // printf("id2 %d\n",id2);
+                                idg[maxidg] = 30000*id1+10000*idum+id2;
+                                pvert1g[maxidg] = (Double_t) Part->Py(); 
+                                pvert2g[maxidg] = (Double_t) Part->Px();   
+                                pvert3g[maxidg] = (Double_t) Part->Pz(); 
+                                zvertg[maxidg]  = (Double_t) Part->Vz();  
+                            } //if muon                             
+                          } //if nch
+                   } // ihit
+                   maxidg++;
+                 } // check limits
+               } // if cluster type
+         } // icor loop
+      } // ich loop
+  }// if MUON
+
+
+  ievr = nev;
+  cout<<"evenement "<<ievr<<endl;
+  nhittot1 = maxidg ;
+  cout<<"nhittot1="<<nhittot1<<endl;
+
+  static Int_t nbres=0;
+  static Int_t nbcor=0; 
+  if (nres>=19) nbres++;
+  printf("nres ,nncor - %d %d\n",nres,nncor);
+  printf("nbres - %d\n",nbres);
+  if (nncor>=20) nbcor++;
+  printf("nbcor - %d\n",nbcor);
+  printf("nuncor - %d\n",nuncor);
+  printf("nbadcor - %d\n",nbadcor);
+  
+  TC->Reset();
+
+  hfile_global->cd();
+  
+}
+
+void trackf_fit(Int_t &ivertex, Double_t *pest, Double_t *pstep, Double_t &pxzinv, Double_t &tphi, Double_t &talam, Double_t &xvert, Double_t &yvert)
+{
+  //
+  //  Fit a track candidate with the following input parameters: 
+  //  INPUT :  IVERTEX  : vertex flag, if IVERTEX=1 (XVERT,YVERT) are free paramaters
+  //                                   if IVERTEX=1 (XVERT,YVERT)=(0.,0.) 
+  //           PEST(5)  : starting value of parameters (minuit)
+  //           PSTEP(5) : step size for parameters (minuit)
+  //  OUTPUT : PXZINV,TPHI,TALAM,XVERT,YVERT : fitted value of the parameters
+
+  static Double_t arglist[10];
+  static Double_t c[5] = {0.4, 0.45, 0.45, 90., 90.};
+  static Double_t b1, b2, epxz, efi, exs, exvert, eyvert;
+  TString chname;
+  Int_t ierflg = 0;
+  
+  TMinuit *gMinuit = new TMinuit(5);
+  gMinuit->mninit(5,10,7);
+  gMinuit->SetFCN(fcnf);  // constant m.f.
+
+  arglist[0] = -1;
+  
+  gMinuit->mnexcm("SET PRINT", arglist, 1, ierflg);
+  //      gMinuit->mnseti('track fitting');
+  
+  gMinuit->mnparm(0, "invmom",  pest[0], pstep[0], -c[0], c[0], ierflg);
+  gMinuit->mnparm(1, "azimuth", pest[1], pstep[1], -c[1], c[1], ierflg);
+  gMinuit->mnparm(2, "deep",    pest[2], pstep[2], -c[2], c[2], ierflg);
+  if (ivertex==1) {
+    gMinuit->mnparm(3, "x ", pest[3], pstep[3], -c[3], c[3], ierflg);
+    gMinuit->mnparm(4, "y ", pest[4], pstep[4], -c[4], c[4], ierflg);  
+  }   
+  
+  gMinuit->mnexcm("SET NOGR", arglist, 0, ierflg);
+  gMinuit->mnexcm("MINIMIZE", arglist, 0, ierflg);
+  gMinuit->mnexcm("EXIT" , arglist, 0, ierflg);
+  
+  gMinuit->mnpout(0, chname, pxzinv, epxz, b1, b2, ierflg);
+  gMinuit->mnpout(1, chname, tphi, efi, b1, b2, ierflg);
+  gMinuit->mnpout(2, chname, talam, exs, b1, b2, ierflg);
+  if (ivertex==1) {
+    gMinuit->mnpout(3, chname, xvert, exvert, b1, b2, ierflg);
+    gMinuit->mnpout(4, chname, yvert, eyvert, b1, b2, ierflg);
+  }   
+  
+  delete gMinuit;
+
+}
+          
+void fcnf(Int_t &npar, Double_t *grad, Double_t &fval, Double_t *pest, Int_t iflag)
+{
+  //
+  // function called by trackf_fit
+      Int_t futil = 0;
+      fcn(npar,grad,fval,pest,iflag,futil);
+}
+
+void prec_fit(Double_t &pxzinv, Double_t &fis, Double_t &alams, Double_t &xvert, Double_t &yvert, Double_t &pxzinvf, Double_t &fif, Double_t &alf, Double_t &xvertf, Double_t &yvertf, Double_t &epxzinv, Double_t &efi, Double_t &exs, Double_t &exvert, Double_t &eyvert)
+{
+  // 
+  // minuit fits for tracking finding 
+                                                                            
+      static Double_t arglist[10];
+      static Double_t c1[5] = {0.001, 0.001, 0.001, 1., 1.};
+      static Double_t c2[5] = {0.5, 0.5, 0.5, 120., 120.};
+      static Double_t emat[9];
+      static Double_t b1, b2;
+      Double_t fmin, fedm, errdef; 
+      Int_t npari, nparx, istat;
+
+      TString chname;
+      Int_t ierflg = 0;
+      
+      TMinuit *gMinuit = new TMinuit(5);
+      gMinuit->mninit(5,10,7);
+      gMinuit->SetFCN(fcnfitf);
+
+      arglist[0] = -1.;
+      gMinuit->mnexcm("SET PRINT", arglist, 1, ierflg);
+      
+      //      gMinuit->mnseti('track fitting');
+
+      gMinuit->mnparm(0,"invmom",   pxzinv, c1[0], -c2[0], c2[0], ierflg); // 0.003, 0.5
+      gMinuit->mnparm(1,"azimuth ", fis,    c1[1], -c2[1], c2[1], ierflg);
+      gMinuit->mnparm(2,"deep    ", alams,  c1[2], -c2[2], c2[2], ierflg);
+      gMinuit->mnparm(3,"xvert",    xvert,  c1[3], -c2[3], c2[3], ierflg);
+      gMinuit->mnparm(4,"yvert",    yvert,  c1[4], -c2[4], c2[4], ierflg);
+
+      gMinuit->mnexcm("SET NOGR", arglist, 0, ierflg);
+      arglist[0] = 2.;
+      gMinuit->mnexcm("MINIMIZE", arglist, 0, ierflg);
+      gMinuit->mnexcm("EXIT", arglist, 0, ierflg);
+      gMinuit->mnpout(0, chname, pxzinvf, epxzinv, b1, b2, ierflg);
+      gMinuit->mnpout(1, chname, fif, efi, b1, b2, ierflg);
+      gMinuit->mnpout(2, chname, alf, exs, b1, b2, ierflg);
+      gMinuit->mnpout(3, chname, xvertf, exvert, b1, b2, ierflg);
+      gMinuit->mnpout(4, chname, yvertf, eyvert, b1, b2, ierflg);
+  
+      gMinuit->mnemat(emat, 3);
+      gMinuit->mnstat(fmin, fedm, errdef, npari, nparx, istat);
+
+     delete gMinuit;
+}
+
+void fcnfitf(Int_t &npar, Double_t *grad, Double_t &fval, Double_t *xval, Int_t iflag)
+{
+  //
+  // function called by prec_fit 
+      Int_t futil = 0;
+      fcnfit(npar,grad,fval,xval,iflag,futil);
+}
+
+///////////////////// fin modifs perso //////////////////////
+
 ClassImp(AliMUONcluster)
  
 //___________________________________________
@@ -681,9 +3039,11 @@ AliMUONdigit::AliMUONdigit(Int_t *digits)
   //
   // Creates a MUON digit object to be updated
   //
-  fPadX        = digits[0];
-  fPadY        = digits[1];
-  fSignal      = digits[2];
+    fPadX        = digits[0];
+    fPadY        = digits[1];
+    fSignal      = digits[2];
+    fPhysics     = digits[3];
+    fHit       = digits[4];
 
 }
 //_____________________________________________________________________________
@@ -695,28 +3055,33 @@ AliMUONdigit::AliMUONdigit(Int_t *tracks, Int_t *charges, Int_t *digits)
     fPadX        = digits[0];
     fPadY        = digits[1];
     fSignal      = digits[2];
+    fPhysics     = digits[3];
+    fHit       = digits[4];
     for(Int_t i=0; i<10; i++) {
        fTcharges[i]  = charges[i];
        fTracks[i]    = tracks[i];
     }
 }
 
+AliMUONdigit::~AliMUONdigit()
+{
+    
+}
+
 ClassImp(AliMUONlist)
  
 //____________________________________________________________________________
-    AliMUONlist::AliMUONlist(Int_t rpad, Int_t *digits): 
+    AliMUONlist::AliMUONlist(Int_t ich, Int_t *digits): 
        AliMUONdigit(digits)
 {
     //
     // Creates a MUON digit list object
     //
 
-    fRpad = rpad;
+    fChamber     = ich;
     fTrackList   = new TObjArray;
  
 }
-//_____________________________________________________________________________
-
 
 ClassImp(AliMUONhit)
  
@@ -725,7 +3090,7 @@ ClassImp(AliMUONhit)
        AliHit(shunt, track)
 {
     fChamber=vol[0];
-    fParticle=(Int_t) hits[0];
+    fParticle=hits[0];
     fX=hits[1];
     fY=hits[2];
     fZ=hits[3];
@@ -735,78 +3100,154 @@ ClassImp(AliMUONhit)
     fEloss=hits[7];
     fPHfirst=(Int_t) hits[8];
     fPHlast=(Int_t) hits[9];
-}
-ClassImp(AliMUONreccluster) 
-
-ClassImp(AliMUONRecCluster)
 
-//_____________________________________________________________________
-AliMUONRecCluster::AliMUONRecCluster()
+    // modifs perso
+    fPTot=hits[10];
+    fCxHit=hits[11];
+    fCyHit=hits[12];
+    fCzHit=hits[13];
+}
+ClassImp(AliMUONcorrelation)
+//___________________________________________
+//_____________________________________________________________________________
+AliMUONcorrelation::AliMUONcorrelation(Int_t *idx, Float_t *x, Float_t *y)
+{
+    //
+    // Creates a MUON correlation object
+    //
+    for(Int_t i=0; i<4; i++) {
+       fCorrelIndex[i]  = idx[i];
+       fX[i]    = x[i];
+       fY[i]    = y[i];
+    }
+}
+ClassImp(AliMUONRawCluster)
+Int_t AliMUONRawCluster::Compare(TObject *obj)
 {
-    fDigits=0;
-    fNdigit=-1;
+  /*
+         AliMUONRawCluster *raw=(AliMUONRawCluster *)obj;
+        Float_t r=GetRadius();
+         Float_t ro=raw->GetRadius();
+         if (r>ro) return 1;
+         else if (r<ro) return -1;
+         else return 0;
+  */
+         AliMUONRawCluster *raw=(AliMUONRawCluster *)obj;
+        Float_t y=fY;
+         Float_t yo=raw->fY;
+         if (y>yo) return 1;
+         else if (y<yo) return -1;
+         else return 0;
+
 }
 
-AliMUONRecCluster::
-AliMUONRecCluster(Int_t FirstDigit,Int_t Ichamber, Int_t Icathod)
+Int_t AliMUONRawCluster::
+BinarySearch(Float_t y, TArrayF coord, Int_t from, Int_t upto)
 {
-    fX = 0.;
-    fY = 0.;
-    fDigits = new TArrayI(10);
-    fNdigit=0;
-    AddDigit(FirstDigit);
-    fChamber=Ichamber;
-    fCathod=Icathod;
+   // Find object using a binary search. Array must first have been sorted.
+   // Search can be limited by setting upto to desired index.
+
+   Int_t low=from, high=upto-1, half;
+   while(high-low>1) {
+        half=(high+low)/2;
+        if(y>coord[half]) low=half;
+        else high=half;
+   }
+   return low;
 }
 
-void AliMUONRecCluster::AddDigit(Int_t Digit)
+void AliMUONRawCluster::SortMin(Int_t *idx,Float_t *xdarray,Float_t *xarray,Float_t *yarray,Float_t *qarray, Int_t ntr)
 {
-    if (fNdigit==fDigits->GetSize()) {
-       //enlarge the list by hand!
-       Int_t *array= new Int_t[fNdigit*2];
-       for(Int_t i=0;i<fNdigit;i++)
-           array[i] = fDigits->At(i);
-       fDigits->Adopt(fNdigit*2,array);
+  //
+  // Get the 3 closest points(cog) one can find on the second cathode 
+  // starting from a given cog on first cathode
+  //
+  
+  //
+  //  Loop over deltax, only 3 times
+  //
+  
+    Float_t xmin;
+    Int_t jmin;
+    Int_t id[3] = {-2,-2,-2};
+    Float_t jx[3] = {0.,0.,0.};
+    Float_t jy[3] = {0.,0.,0.};
+    Float_t jq[3] = {0.,0.,0.};
+    Int_t jid[3] = {-2,-2,-2};
+    Int_t i,j,imax;
+  
+    if (ntr<3) imax=ntr;
+    else imax=3;
+    for(i=0;i<imax;i++){
+        xmin=1001.;
+        jmin=0;
+    
+        for(j=0;j<ntr;j++){
+            if ((i == 1 && j == id[i-1]) 
+                 ||(i == 2 && (j == id[i-1] || j == id[i-2]))) continue;
+           if (TMath::Abs(xdarray[j]) < xmin) {
+             xmin = TMath::Abs(xdarray[j]);
+             jmin=j;
+           }       
+        } // j
+        if (xmin != 1001.) {    
+           id[i]=jmin;
+           jx[i]=xarray[jmin]; 
+           jy[i]=yarray[jmin]; 
+           jq[i]=qarray[jmin]; 
+           jid[i]=idx[jmin];
+        } 
+    
+    }  // i
+  
+    for (i=0;i<3;i++){
+        if (jid[i] == -2) {
+            xarray[i]=1001.;
+            yarray[i]=1001.;
+            qarray[i]=1001.;
+            idx[i]=-1;
+        } else {
+            xarray[i]=jx[i];
+            yarray[i]=jy[i];
+            qarray[i]=jq[i];
+            idx[i]=jid[i];
+        }
     }
-    fDigits->AddAt(Digit,fNdigit);
-    fNdigit++;
+
 }
 
 
-AliMUONRecCluster::~AliMUONRecCluster()
+Int_t AliMUONRawCluster::PhysicsContribution()
 {
-    if (fDigits)
-       delete fDigits;
+  Int_t iPhys=0;
+  Int_t iBg=0;
+  Int_t iMixed=0;
+  for (Int_t i=0; i<fMultiplicity; i++) {
+    if (fPhysicsMap[i]==2) iPhys++;
+    if (fPhysicsMap[i]==1) iMixed++;
+    if (fPhysicsMap[i]==0) iBg++;
+  }
+  if (iMixed==0 && iBg==0) {
+    return 2;
+  } else if ((iPhys != 0 && iBg !=0) || iMixed != 0) {
+    return 1;
+  } else {
+    return 0;
+  }
 }
 
-Int_t AliMUONRecCluster::FirstDigitIndex()
-{
-    fCurrentDigit=0;
-    return fDigits->At(fCurrentDigit);
-}
+   
+ClassImp(AliMUONreccluster) 
+ClassImp(AliMUONsegmentation)
+ClassImp(AliMUONresponse)      
+
+
+
+
+
 
-Int_t AliMUONRecCluster::NextDigitIndex()
-{
-    fCurrentDigit++;
-    if (fCurrentDigit<fNdigit)
-       return fDigits->At(fCurrentDigit);
-    else 
-       return InvalidDigitIndex();
-}
 
-Int_t AliMUONRecCluster::NDigits()
-{
-    return fNdigit;
-}
 
-void AliMUONRecCluster::Finish()
-{
-    // In order to reconstruct coordinates, one has to
-    // get back to the digits which is not trivial here,
-    // because we don't know where digits are stored!
-    // Center Of Gravity, or other method should be
-    // a property of AliMUON class!
-}
 
 
 
index c755a5b..3e32f6f 100644 (file)
 #include "AliDetector.h"
 #include "AliHit.h"
 #include "AliMUONConst.h"
-#include "AliDigit.h" 
+#include "AliDigit.h"
+#include "AliMUONchamber.h"
+#include "AliMUONSegRes.h"
 #include <TVector.h>
 #include <TObjArray.h>
-
+#include <TArrayF.h>
+#include <TFile.h>
+#include <TTree.h>
+typedef enum {simple, medium, big} Cluster_t;
 
 static const int NCH=14;
 
 class AliMUONcluster;
-class AliMUONchamber;
 class AliMUONRecCluster;
-//----------------------------------------------
-class AliMUONgeometry 
-{
- public:
-    AliMUONgeometry(){}
-    virtual ~AliMUONgeometry(){}
-    void    InitGeo(Float_t z);
-    Float_t fdGas; // half gaz gap
-    Float_t fdAlu; // half Alu width
-    Float_t frMin; // innermost sensitive radius
-    Float_t frMax; // outermost sensitive radius
-    ClassDef(AliMUONgeometry,1)
-};
-//----------------------------------------------
-//
-// Chamber segmentation virtual base class
-//
-class AliMUONsegmentation :
-public TObject {
-    
- public:
+class AliMUONRawCluster;
+class AliMUONClusterFinder;
+class AliMUONcorrelation;
 
-    // Set Chamber Segmentation Parameters
-    virtual void    SetPADSIZ(Float_t p1, Float_t p2)  =0;
-    virtual void    SetDAnod(Float_t D)                =0;
-    // Transform from pad (wire) to real coordinates and vice versa
-    virtual Float_t GetAnod(Float_t xhit)              =0;
-    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy)=0;
-    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y )=0;
-    //
-    // Initialisation
-    virtual void Init(AliMUONchamber*)                 =0;
-    //
-    // Get member data
-    virtual Float_t Dpx()                              =0;
-    virtual Float_t Dpy()                              =0;
-    virtual Int_t Npx()                                =0;
-    virtual Int_t Npy()                                =0;
-    //
-    // Iterate over pads
-    virtual void  FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy) =0;
-    virtual void  NextPad()=0;
-    virtual Int_t MorePads()                           =0;
-    // Get next neighbours 
-    virtual void Neighbours
-       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])     =0;
-    // Provisory RecCluster coordinates reconstructor
-    virtual void FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits)    =0;
-    //
-    // Current pad cursor during disintegration 
-    virtual Int_t  Ix()                                =0;
-    virtual Int_t  Iy()                                =0;
-    virtual Int_t  ISector()                           =0;
-    //
-    // Signal Generation Condition during Stepping
-    virtual Int_t SigGenCond(Float_t x, Float_t y, Float_t z) = 0;
-    virtual void  SigGenInit(Float_t x, Float_t y, Float_t z) = 0;
-    virtual void  IntegrationLimits
-       (Float_t& x1, Float_t& x2, Float_t& y1, Float_t& y2)  = 0;
-    //
-    // Identification
-    ClassDef(AliMUONsegmentation,1)
-};
-//----------------------------------------------
-//
-// Chamber response virtual base class
-//
-class AliMUONresponse :
-public TObject {
- public:
-    //
-    // Configuration methods
-    virtual void   SetRSIGM(Float_t p1)                =0;
-    virtual void   SetMUCHSP(Float_t p1)               =0;
-    virtual void   SetMUSIGM(Float_t p1, Float_t p2)   =0;
-    virtual void   SetMAXADC(Float_t p1)               =0;
-    //
-    // Get member data
-    virtual Float_t Chslope()                          =0;
-    virtual Float_t ChwX()                             =0;
-    virtual Float_t ChwY()                             =0;
-    virtual Float_t Nsigma()                           =0;
-    virtual Float_t adc_satm()                         =0;
-    //  
-    // Chamber response methods
-    // Pulse height from scored quantity (eloss)
-    virtual Float_t IntPH(Float_t eloss)               =0;
-    // Charge disintegration
-    virtual Float_t IntXY(AliMUONsegmentation *)       =0;
-    //
-    // Identification
-    ClassDef(AliMUONresponse,1)
-};
 
 //----------------------------------------------
-class AliMUONchamber :
-public TObject,
-public AliMUONgeometry{
- public:
-    AliMUONchamber();
-    ~AliMUONchamber(){}
-//
-// Set and get GEANT id  
-  Int_t   GetGid()         {return fGid;}
-  void    SetGid(Int_t id) {fGid=id;}
-//  
-// Initialisation and z-Position
-  void    Init();
-  void    SetZPOS(Float_t p1) {fzPos=p1;}
-  Float_t ZPosition()         {return fzPos;}
-//  
-// Configure response model
-  void    ResponseModel(AliMUONresponse* thisResponse) {fResponse=thisResponse;}
-//  
-// Configure segmentation model
-  void    SegmentationModel(Int_t i, AliMUONsegmentation* thisSegmentation) {
-      (*fSegmentation)[i-1] = thisSegmentation;
-  }
-//  
-//  Get reference to response model
-  AliMUONresponse*     &GetResponseModel(){return fResponse;}
-//  
-//  Get reference to segmentation model
-  AliMUONsegmentation*  GetSegmentationModel(Int_t isec) {
-      return (AliMUONsegmentation *) (*fSegmentation)[isec-1];
-  }
-  Int_t Nsec()              {return fnsec;}
-  void  SetNsec(Int_t nsec) {fnsec=nsec;}
-//
-// Member function forwarding to the segmentation and response models
-//
-// Calculate pulse height from energy loss  
-  Float_t IntPH(Float_t eloss) {return fResponse->IntPH(eloss);}
-//  
-// Ask segmentation if signal should be generated  
-  Int_t   SigGenCond(Float_t x, Float_t y, Float_t z)
-      {
-         if (fnsec==1) {
-             return ((AliMUONsegmentation*) (*fSegmentation)[0])
-                 ->SigGenCond(x, y, z) ;
-         } else {
-             return (((AliMUONsegmentation*) (*fSegmentation)[0])
-                     ->SigGenCond(x, y, z)) ||
-                 (((AliMUONsegmentation*) (*fSegmentation)[1])
-                  ->SigGenCond(x, y, z)) ;
-         }
-  }
-//
-// Initialisation of segmentation for hit  
-  void    SigGenInit(Float_t x, Float_t y, Float_t z)
-      {
-         
-         if (fnsec==1) {
-             ((AliMUONsegmentation*) (*fSegmentation)[0])->SigGenInit(x, y, z) ;
-         } else {
-             ((AliMUONsegmentation*) (*fSegmentation)[0])->SigGenInit(x, y, z) ;
-             ((AliMUONsegmentation*) (*fSegmentation)[1])->SigGenInit(x, y, z) ;
-         }
-      }
-  
-// Configuration forwarding
-//
-  void   SetRSIGM(Float_t p1)              {fResponse->SetRSIGM(p1);}
-  void   SetMUCHSP(Float_t p1)             {fResponse->SetMUCHSP(p1);}
-  void   SetMUSIGM(Float_t p1, Float_t p2) {fResponse->SetMUSIGM(p1,p2);}
-  void   SetMAXADC(Float_t p1)             {fResponse->SetMAXADC(p1);}
-
-  void   SetPADSIZ(Int_t isec, Float_t p1, Float_t p2) {
-      ((AliMUONsegmentation*) (*fSegmentation)[isec-1])->SetPADSIZ(p1,p2);
-  }
-//  
-// Cluster formation method
-  void   DisIntegration(Float_t, Float_t, Float_t, Int_t&x, Float_t newclust[6][500]);
-    ClassDef(AliMUONchamber,1)
-
- private:
-// GEANT volume if for sensitive volume of this chamber
-  Int_t   fGid;
-// z-position of this chamber
-  Float_t fzPos;
-// The segmentation models for the cathode planes
-// fnsec=1: one plane segmented, fnsec=2: both planes are segmented.
-  Int_t   fnsec;
-  TObjArray           *fSegmentation;
-  AliMUONresponse     *fResponse;
-
-};
-
 
  
 class AliMUONcluster : public TObject {
@@ -236,11 +58,11 @@ public:
    Int_t       fQ  ;          // Q of cluster (in ADC counts)     
    Float_t     fX  ;          // X of cluster
    Float_t     fY  ;          // Y of cluster
+
 public:
    AliMUONreccluster() {
        fTracks[0]=fTracks[1]=fTracks[2]=0; 
-       fQ=0; fX=fY=0;   
+       fQ=0; fX=fY=0; 
    }
    virtual ~AliMUONreccluster() {;}
  
@@ -254,10 +76,10 @@ class AliMUONdigit : public TObject {
     Int_t     fPadX;        // Pad number along x
     Int_t     fPadY ;       // Pad number along y
     Int_t     fSignal;      // Signal amplitude
-    
-
-    Int_t     fTcharges[10];  // charge per track making this digit (up to 10)
-    Int_t     fTracks[10];    // tracks making this digit (up to 10)
+    Int_t     fTcharges[10];   // charge per track making this digit (up to 10)
+    Int_t     fTracks[10];     // primary tracks making this digit (up to 10)
+    Int_t     fPhysics;        // physics contribution to signal 
+    Int_t     fHit;            // hit number - temporary solution
 
 
  
@@ -265,28 +87,21 @@ class AliMUONdigit : public TObject {
     AliMUONdigit() {}
     AliMUONdigit(Int_t *digits);
     AliMUONdigit(Int_t *tracks, Int_t *charges, Int_t *digits);
-    virtual ~AliMUONdigit() {}
-
+    virtual ~AliMUONdigit();
+    
     ClassDef(AliMUONdigit,1)  //Digits for set:MUON
 };
 //_____________________________________________________________________________
 
 class AliMUONlist : public AliMUONdigit {
  public:
-    
-    Int_t          fRpad;       // r_pos of pad
-    
+    Int_t          fChamber;       // chamber number of pad
     TObjArray     *fTrackList; 
-
  public:
     AliMUONlist() {fTrackList=0;}
     AliMUONlist(Int_t rpad, Int_t *digits);
-    virtual ~AliMUONlist() {}
-
+    virtual ~AliMUONlist() {delete fTrackList;}
     TObjArray  *TrackList()   {return fTrackList;}
     ClassDef(AliMUONlist,1)  //Digits for set:MUON
 };
 //___________________________________________
@@ -297,13 +112,20 @@ class AliMUONlist : public AliMUONdigit {
 class AliMUONhit : public AliHit {
  public:
     Int_t     fChamber;       // Chamber number
-    Int_t     fParticle;      // PDG particle type
+    Float_t   fParticle;      // Geant3 particle type
     Float_t   fTheta ;        // Incident theta angle in degrees      
     Float_t   fPhi   ;        // Incident phi angle in degrees
     Float_t   fTlength;       // Track length inside the chamber
     Float_t   fEloss;         // ionisation energy loss in gas   
     Int_t     fPHfirst;       // first padhit
     Int_t     fPHlast;        // last padhit
+
+// modifs perso
+    Float_t   fPTot;          // hit momentum P
+    Float_t   fCxHit;            // Px/P
+    Float_t   fCyHit;            // Py/P
+    Float_t   fCzHit;            // Pz/P
+
  public:
     AliMUONhit() {}
     AliMUONhit(Int_t fIshunt, Int_t track, Int_t *vol, Float_t *hits);
@@ -320,8 +142,10 @@ class AliMUON : public  AliDetector {
     virtual void   AddHit(Int_t, Int_t*, Float_t*);
     virtual void   AddCluster(Int_t*);
     virtual void   AddDigits(Int_t, Int_t*, Int_t*, Int_t*);
+    virtual void   AddRawCluster(Int_t, const AliMUONRawCluster&);
     virtual void   AddRecCluster(Int_t iCh, Int_t iCat,
                                 AliMUONRecCluster* Cluster);
+    virtual void   AddCathCorrel(Int_t, Int_t*, Float_t*, Float_t*);
     virtual void   BuildGeometry();
     virtual void   CreateGeometry() {}
     virtual void   CreateMaterials() {}
@@ -330,13 +154,36 @@ class AliMUON : public  AliDetector {
     virtual Int_t  IsVersion() const =0;
 //
     TClonesArray  *Clusters() {return fClusters;}
+    virtual  void  MakeTreeC(Option_t *option="C");
+    void           GetTreeC(Int_t);
     virtual void   MakeBranch(Option_t *opt=" ");
     void           SetTreeAddress();
     virtual void   ResetHits();
     virtual void   ResetDigits();
+    virtual void   ResetRawClusters();
     virtual void   ResetRecClusters();
-    virtual void   ReconstructClusters();
-// 
+    virtual void   ResetCorrelation();
+    virtual void   FindClusters(Int_t,Int_t);
+    virtual void   Digitise(Int_t,Int_t,Option_t *opt=" ",Option_t *opt=" ",Text_t *name=" ");
+    virtual void   CathodeCorrelation(Int_t);
+    virtual void   SortTracks(Int_t *,Int_t *,Int_t);
+//
+// modifs perso
+
+    void     Init(Double_t &, Double_t &, Double_t &);
+    void     Reconst(Int_t &,Int_t &,Int_t,Int_t &,Int_t&,Int_t&, Option_t *option,Text_t *filename);
+    void     FinishEvent();
+    void     Close();
+    void     SetCutPxz(Double_t p) {fSPxzCut=p;}
+    void     SetSigmaCut(Double_t p) {fSSigmaCut=p;}
+    void     SetXPrec(Double_t p) {fSXPrec=p;}
+    void     SetYPrec(Double_t p) {fSYPrec=p;}
+    Double_t GetCutPxz() {return fSPxzCut;}
+    Double_t GetSigmaCut() {return fSSigmaCut;}
+    Double_t GetXPrec() {return fSXPrec;}
+    Double_t GetYPrec() {return fSYPrec;}
+// fin modifs perso 
+    
 // Configuration Methods (per station id)
 //
 // Set Chamber Segmentation Parameters
@@ -344,43 +191,72 @@ class AliMUON : public  AliDetector {
     virtual void   SetPADSIZ(Int_t id, Int_t isec, Float_t p1, Float_t p2);
 
 // Set Signal Generation Parameters
-    virtual void   SetRSIGM(Int_t id, Float_t p1);
-    virtual void   SetMUCHSP(Int_t id, Float_t p1);
-    virtual void   SetMUSIGM(Int_t id, Float_t p1, Float_t p2);
-    virtual void   SetMAXADC(Int_t id, Float_t p1);
+    virtual void   SetSigmaIntegration(Int_t id, Float_t p1);
+    virtual void   SetChargeSlope(Int_t id, Float_t p1);
+    virtual void   SetChargeSpread(Int_t id, Float_t p1, Float_t p2);
+    virtual void   SetMaxAdc(Int_t id, Float_t p1);
 // Set Segmentation and Response Model
     virtual void   SetSegmentationModel(Int_t id, Int_t isec, AliMUONsegmentation *segmentation);
     virtual void   SetResponseModel(Int_t id, AliMUONresponse *response);
     virtual void   SetNsec(Int_t id, Int_t nsec);
+// Set Reconstruction Model
+    virtual void   SetReconstructionModel(Int_t id, AliMUONClusterFinder *reconstruction);
 // Set Stepping Parameters
-    virtual void   SetSMAXAR(Float_t p1);
-    virtual void   SetSMAXAL(Float_t p1);
-    virtual void   SetDMAXAR(Float_t p1);
-    virtual void   SetDMAXAL(Float_t p1);
-    virtual void   SetMUONACC(Bool_t acc=0, Float_t angmin=2, Float_t angmax=9);
+    virtual void   SetMaxStepGas(Float_t p1);
+    virtual void   SetMaxStepAlu(Float_t p1);
+    virtual void   SetMaxDestepGas(Float_t p1);
+    virtual void   SetMaxDestepAlu(Float_t p1);
+    virtual void   SetMuonAcc(Bool_t acc=0, Float_t angmin=2, Float_t angmax=9);
 // Response Simulation
     virtual void   MakePadHits(Float_t xhit,Float_t yhit,Float_t eloss,Int_t id);
 // Return reference to Chamber #id
     virtual AliMUONchamber& Chamber(Int_t id) {return *((AliMUONchamber *) (*fChambers)[id]);}
 // Retrieve pad hits for a given Hit
-    virtual AliMUONcluster* FirstPad(AliMUONhit *);
-    virtual AliMUONcluster* NextPad();
+    virtual AliMUONcluster* FirstPad(AliMUONhit *, TClonesArray *);
+    virtual AliMUONcluster* NextPad(TClonesArray *);
 // Return pointers to digits 
     TObjArray            *Dchambers() {return fDchambers;}
     Int_t                *Ndch() {return fNdch;}
     virtual TClonesArray *DigitsAddress(Int_t id) {return ((TClonesArray *) (*fDchambers)[id]);}
 // Return pointers to reconstructed clusters
-    virtual TObjArray *RecClusters(Int_t iCh, Int_t iCat) 
-       {return ( (TObjArray*) (*fRecClusters)[iCh+iCat*10]);}
+  //    virtual TObjArray *RecClusters(Int_t iCh, Int_t iCat) 
+  //   {return ( (TObjArray*) (*fRecClusters)[iCh+iCat*10]);}
 
-   
+    TObjArray            *RawClusters() {return fRawClusters;}
+    Int_t                *Nrawch() {return fNrawch;}
+    virtual TClonesArray *RawClustAddress(Int_t id) {return ((TClonesArray *) (*fRawClusters)[id]);}
+
+// modifs perso
+    AliMUONRawCluster *RawCluster(Int_t ichamber, Int_t icathod, Int_t icluster);
+    
+    
+    // Return pointers to list of correlated clusters
+    TObjArray            *CathCorrel() {return fCathCorrel;}
+    Int_t                *Ncorch() {return fNcorch;}
+    virtual TClonesArray *CathCorrelAddress(Int_t id)
+       {return ((TClonesArray *) (*fCathCorrel)[id]);}
+
+// modifs perso
+//  virtual TClonesArray *CathCorrelAddress2(Int_t id)
+//     {return ((TClonesArray *) (*fCathCorrel2)[id]);}    
+    
+// Return pointer to TreeC
+    TTree      *TreeC() {return fTreeC;} 
  protected:
     TObjArray            *fChambers;           // List of Tracking Chambers
     Int_t                fNclusters;           // Number of clusters
     TClonesArray         *fClusters;           // List of clusters
     TObjArray            *fDchambers;          // List of digits
-    TObjArray            *fRecClusters;        // List of clusters
     Int_t                *fNdch;               // Number of digits
+
+  //    TObjArray            *fRecClusters;        // List of clusters
+
+    TObjArray            *fRawClusters;            // List of raw clusters
+    Int_t                *fNrawch;                 // Number of raw clusters
+    TObjArray            *fCathCorrel;             // List of correlated clusters
+    Int_t                *fNcorch;                 // Number of correl clusters
+    TTree                *fTreeC;                  // Cathode correl index tree
+
 //
     Bool_t   fAccCut;          //Transport acceptance cut
     Float_t  fAccMin;          //Minimum acceptance cut used during transport
@@ -392,6 +268,15 @@ class AliMUON : public  AliDetector {
    Float_t fMaxStepAlu;      // Maximum step size inside the chamber aluminum
    Float_t fMaxDestepGas;    // Maximum relative energy loss in gas
    Float_t fMaxDestepAlu;    // Maximum relative energy loss in aluminum
+//
+// modifs perso
+//  Parameters for reconstruction program
+   Double_t fSPxzCut;        // Pxz cut  (GeV/c) to begin the track finding
+   Double_t fSSigmaCut;      // Number of sig. delimiting the searching areas
+   Double_t fSXPrec;         // Chamber precision in X (cm) 
+   Double_t fSYPrec;         // Chamber precision in Y (cm)
+
+   Text_t *fFileName;
    
  protected:
 
@@ -427,6 +312,69 @@ protected:
    ClassDef(AliMUONRecCluster,1)  //Cluster object for set:MUON
 };
 //___________________________________________
+
+class AliMUONRawCluster : public TObject {
+public:
+
+   Int_t     fTracks[3];      //labels of overlapped tracks
+   Int_t       fQ  ;          // Q of cluster (in ADC counts)     
+   Float_t     fX  ;          // X of cluster
+   Float_t     fY  ;          // Y of cluster
+   Int_t       fPeakSignal;
+   Int_t       fIndexMap[50];  //indeces of digits
+   Int_t       fOffsetMap[50]; //Emmanuel special
+   Float_t     fContMap[50];   //Contribution from digit
+   Int_t       fPhysicsMap[50];
+   Int_t       fMultiplicity;  //cluster multiplicity
+   Int_t       fNcluster[2];
+   Int_t       fClusterType;   
+ public:
+   AliMUONRawCluster() {
+       fTracks[0]=fTracks[1]=fTracks[2]=-1; 
+       fQ=0; fX=fY=0; fMultiplicity=0;
+       for (int k=0;k<50;k++) {
+           fIndexMap[k]=-1;
+           fOffsetMap[k]=0;
+          fContMap[k]=0;
+          fPhysicsMap[k]=-1;
+       }
+       fNcluster[0]=fNcluster[1]=-1;
+   }
+   virtual ~AliMUONRawCluster() {}
+
+   Float_t GetRadius() {return TMath::Sqrt(fX*fX+fY*fY);}
+
+   Bool_t IsSortable() const {return true;}
+   Int_t  Compare(TObject *obj);
+   Int_t PhysicsContribution();
+   static Int_t BinarySearch(Float_t r, TArrayF, Int_t from, Int_t upto);
+   static void  SortMin(Int_t *,Float_t *,Float_t *,Float_t *,Float_t *,Int_t);
+   ClassDef(AliMUONRawCluster,1)  //Cluster object for set:MUON
+};
+
+//___________________________________________
+class AliMUONcorrelation : public TObject {
+public:
+
+  // correlation starts from the 1-st cathode  
+  // last number in arrays corresponds to cluster on 1-st cathode
+
+   Int_t       fCorrelIndex[4];  // entry number in TreeR for the associated 
+                                 // cluster candidates on the 2-nd cathode
+   Float_t     fX[4]  ;          // X of clusters on the 2-nd cathode  
+   Float_t     fY[4]  ;          // Y of clusters
+
+public:
+   AliMUONcorrelation() {
+       fCorrelIndex[0]=fCorrelIndex[1]=fCorrelIndex[2]=fCorrelIndex[3]=0;
+       fX[0]=fX[1]=fX[2]=fX[3]=0; fY[0]=fY[1]=fY[2]=fY[3]=0; 
+   }
+   AliMUONcorrelation(Int_t *idx, Float_t *x, Float_t *y);
+   virtual ~AliMUONcorrelation() {}
+   ClassDef(AliMUONcorrelation,1)  //Cathode correlation object for set:MUON
+};
+
 #endif
 
 
diff --git a/MUON/AliMUONClusterFinder.cxx b/MUON/AliMUONClusterFinder.cxx
new file mode 100644 (file)
index 0000000..687559a
--- /dev/null
@@ -0,0 +1,1110 @@
+#include "AliMUONClusterFinder.h"
+#include "TTree.h"
+#include "AliRun.h"
+#include <TCanvas.h>
+#include <TH1.h>
+#include <TPad.h>
+#include <TGraph.h> 
+#include <TPostScript.h> 
+#include <TMinuit.h> 
+
+ClassImp(AliMUONRecCluster)
+//_____________________________________________________________________
+static AliMUONsegmentation* gSegmentation;
+static AliMUONresponse*     gResponse;
+static Int_t                gix[500];
+static Int_t                giy[500];
+static Float_t              gCharge[500];
+static Int_t                gNbins;
+static Int_t                gFirst=kTRUE;
+static TMinuit *gMyMinuit ;
+void fcn(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
+static Int_t                gChargeTot;
+
+
+AliMUONRecCluster::AliMUONRecCluster()
+
+{
+    fDigits=0;
+    fNdigit=-1;
+}
+
+AliMUONRecCluster::
+AliMUONRecCluster(Int_t FirstDigit,Int_t Ichamber, Int_t Icathod)
+{
+    fX = 0.;
+    fY = 0.;
+    fDigits = new TArrayI(10);
+    fNdigit=0;
+    AddDigit(FirstDigit);
+    fChamber=Ichamber;
+    fCathod=Icathod;
+}
+
+void AliMUONRecCluster::AddDigit(Int_t Digit)
+{
+    if (fNdigit==fDigits->GetSize()) {
+       //enlarge the list by hand!
+       Int_t *array= new Int_t[fNdigit*2];
+       for(Int_t i=0;i<fNdigit;i++)
+           array[i] = fDigits->At(i);
+       fDigits->Adopt(fNdigit*2,array);
+    }
+    fDigits->AddAt(Digit,fNdigit);
+    fNdigit++;
+}
+
+
+AliMUONRecCluster::~AliMUONRecCluster()
+{
+    if (fDigits)
+       delete fDigits;
+}
+
+Int_t AliMUONRecCluster::FirstDigitIndex()
+{
+    fCurrentDigit=0;
+    return fDigits->At(fCurrentDigit);
+}
+
+Int_t AliMUONRecCluster::NextDigitIndex()
+{
+    fCurrentDigit++;
+    if (fCurrentDigit<fNdigit)
+       return fDigits->At(fCurrentDigit);
+    else 
+       return InvalidDigitIndex();
+}
+
+Int_t AliMUONRecCluster::NDigits()
+{
+    return fNdigit;
+}
+void AliMUONRecCluster::Finish()
+{
+    // In order to reconstruct coordinates, one has to
+    // get back to the digits which is not trivial here,
+    // because we don't know where digits are stored!
+    // Center Of Gravity, or other method should be
+    // a property of AliMUON class!
+}
+
+
+//----------------------------------------------------------
+ClassImp(AliMUONClusterFinder)
+
+    AliMUONClusterFinder::AliMUONClusterFinder
+(AliMUONsegmentation *segmentation, AliMUONresponse *response, 
+ TClonesArray *digits, Int_t chamber)   
+{
+    fSegmentation=segmentation;
+    fResponse=response;
+    
+    fDigits=digits;
+    fNdigits = fDigits->GetEntriesFast();
+    fChamber=chamber;
+    fRawClusters=new TClonesArray("AliMUONRawCluster",10000);
+    fNRawClusters=0;
+    fCogCorr = 0;
+    SetNperMax();
+    SetClusterSize();
+    SetDeclusterFlag();
+    fNPeaks=-1;
+}
+
+    AliMUONClusterFinder::AliMUONClusterFinder()
+{
+    fSegmentation=0;
+    fResponse=0;
+    
+    fDigits=0;
+    fNdigits = 0;
+    fChamber=-1;
+    fRawClusters=new TClonesArray("AliMUONRawCluster",10000);
+    fNRawClusters=0;
+    fHitMap = 0;
+    fCogCorr = 0;
+    SetNperMax();
+    SetClusterSize();
+    SetDeclusterFlag();
+    fNPeaks=-1;
+}
+
+void AliMUONClusterFinder::AddRawCluster(const AliMUONRawCluster c)
+{
+  //
+  // Add a raw cluster copy to the list
+  //
+    AliMUON *MUON=(AliMUON*)gAlice->GetModule("MUON");
+    MUON->AddRawCluster(fChamber,c); 
+    fNRawClusters++;
+}
+
+
+
+void AliMUONClusterFinder::Decluster(AliMUONRawCluster *cluster)
+{
+//    AliMUONdigit *dig;
+//    Int_t q;
+
+    
+    Int_t mul = cluster->fMultiplicity;
+//    printf("Decluster - multiplicity   %d \n",mul);
+
+    if (mul == 1 || mul ==2) {
+//     printf("\n Nothing special for 1- and 2-clusters \n");
+//
+// Nothing special for 1- and 2-clusters
+       if (fNPeaks != 0) {
+            cluster->fNcluster[0]=fNPeaks;
+            cluster->fNcluster[1]=0;
+        } 
+       AddRawCluster(*cluster); 
+        fNPeaks++;
+    } else if (mul ==3) {
+//
+// 3-cluster, check topology
+//     printf("\n 3-cluster, check topology \n");
+       if (fDeclusterFlag) {
+         if (Centered(cluster)) {
+           // ok, cluster is centered 
+           //      printf("\n ok, cluster is centered \n");
+         } else {
+           // cluster is not centered, split into 2+1
+           //      printf("\n cluster is not centered, split into 2+1 \n");
+         }
+       } else {
+         if (fNPeaks != 0) {
+            cluster->fNcluster[0]=fNPeaks;
+            cluster->fNcluster[1]=0;
+         } 
+         AddRawCluster(*cluster); 
+         fNPeaks++;
+       }           
+    } else {
+      //if (mul < 12) {
+         //      printf("Decluster - multiplicity > 45   %d \n",mul);
+         //printf("Decluster - multiplicity < 25   %d \n",mul);
+// 
+// 4-and more-pad clusters
+//
+      if (mul <= fClusterSize) {
+       if (fDeclusterFlag) {
+           SplitByLocalMaxima(cluster);
+       } else {
+           if (fNPeaks != 0) {
+               cluster->fNcluster[0]=fNPeaks;
+               cluster->fNcluster[1]=0;
+            } 
+           AddRawCluster(*cluster);
+           fNPeaks++;
+       }       
+      }
+       //}
+    } // multiplicity 
+}
+
+
+Bool_t AliMUONClusterFinder::Centered(AliMUONRawCluster *cluster)
+{
+    AliMUONdigit* dig;
+    dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[0]);
+    Int_t ix=dig->fPadX;
+    Int_t iy=dig->fPadY;
+    Int_t nn;
+    Int_t X[kMaxNeighbours], Y[kMaxNeighbours], XN[kMaxNeighbours], YN[kMaxNeighbours];
+    
+    fSegmentation->Neighbours(ix,iy,&nn,X,Y);
+    Int_t nd=0;
+    for (Int_t i=0; i<nn; i++) {
+       if (fHitMap->TestHit(X[i],Y[i]) == used) {
+           XN[nd]=X[i];
+           YN[nd]=Y[i];
+           nd++;
+       }
+    }
+    if (nd==2) {
+//
+// cluster is centered !
+       if (fNPeaks != 0) {
+            cluster->fNcluster[0]=fNPeaks;
+            cluster->fNcluster[1]=0;
+        }  
+       AddRawCluster(*cluster);
+       fNPeaks++;
+       return kTRUE;
+    } else if (nd ==1) {
+//
+// Highest signal on an edge, split cluster into 2+1
+//
+// who is the neighbour ?
+       Int_t nind=fHitMap->GetHitIndex(XN[0], YN[0]);
+       Int_t i1= (nind==cluster->fIndexMap[1]) ? 1:2;
+       Int_t i2= (nind==cluster->fIndexMap[1]) ? 2:1;    
+//
+// 2-cluster
+       AliMUONRawCluster cnew;
+       if (fNPeaks == 0) {
+            cnew.fNcluster[0]=-1;
+            cnew.fNcluster[1]=fNRawClusters;
+        } else {
+            cnew.fNcluster[0]=fNPeaks;
+            cnew.fNcluster[1]=0;
+        }
+       cnew.fMultiplicity=2;
+       cnew.fIndexMap[0]=cluster->fIndexMap[0];
+       cnew.fIndexMap[1]=cluster->fIndexMap[i1];
+       FillCluster(&cnew);
+       cnew.fClusterType=cnew.PhysicsContribution();
+       AddRawCluster(cnew);
+        fNPeaks++;
+//
+// 1-cluster
+       cluster->fMultiplicity=1;
+       cluster->fIndexMap[0]=cluster->fIndexMap[i2];
+       cluster->fIndexMap[1]=0;
+       cluster->fIndexMap[2]=0;        
+       FillCluster(cluster);
+        if (fNPeaks != 0) {
+            cluster->fNcluster[0]=fNPeaks;
+            cluster->fNcluster[1]=0;
+        }  
+       cluster->fClusterType=cluster->PhysicsContribution();
+       AddRawCluster(*cluster);
+       fNPeaks++;
+       return kFALSE;
+    } else {
+       printf("\n Completely screwed up %d !! \n",nd);
+       
+    }
+    
+       return kFALSE;
+}
+void AliMUONClusterFinder::SplitByLocalMaxima(AliMUONRawCluster *c)
+{
+    AliMUONdigit* dig[100], *digt;
+    Int_t ix[100], iy[100], q[100];
+    Float_t x[100], y[100];
+    Int_t i; // loops over digits
+    Int_t j; // loops over local maxima
+    //    Float_t xPeak[2];
+    //    Float_t yPeak[2];
+    //    Int_t threshold=500;
+    Int_t mul=c->fMultiplicity;
+//
+//  dump digit information into arrays
+//
+    for (i=0; i<mul; i++)
+    {
+       dig[i]= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
+       ix[i]= dig[i]->fPadX;
+       iy[i]= dig[i]->fPadY;
+       q[i] = dig[i]->fSignal;
+       fSegmentation->GetPadCxy(ix[i], iy[i], x[i], y[i]);
+    }
+//
+//  Find local maxima
+//
+    Bool_t IsLocal[100];
+    Int_t NLocal=0;
+    Int_t AssocPeak[100];
+    Int_t IndLocal[100];
+    Int_t nn;
+    Int_t X[kMaxNeighbours], Y[kMaxNeighbours];
+    for (i=0; i<mul; i++) {
+       fSegmentation->Neighbours(ix[i], iy[i], &nn, X, Y);
+       IsLocal[i]=kTRUE;
+       for (j=0; j<nn; j++) {
+           if (fHitMap->TestHit(X[j], Y[j])==empty) continue;
+           digt=(AliMUONdigit*) fHitMap->GetHit(X[j], Y[j]);
+           if (digt->fSignal > q[i]) {
+               IsLocal[i]=kFALSE;
+               break;
+//
+// handle special case of neighbouring pads with equal signal
+           } else if (digt->fSignal == q[i]) {
+               if (NLocal >0) {
+                   for (Int_t k=0; k<NLocal; k++) {
+                       if (X[j]==ix[IndLocal[k]] && Y[j]==iy[IndLocal[k]]){
+                           IsLocal[i]=kFALSE;
+                       }
+                   }
+               }
+           } 
+       } // loop over next neighbours
+       // Maxima should not be on the edge
+       if (IsLocal[i]) {
+           IndLocal[NLocal]=i;
+           NLocal++;
+       } 
+    } // loop over all digits
+//    printf("Found %d local Maxima",NLocal);
+//
+// If only one local maximum found but multiplicity is high 
+// take global maximum from the list of digits.    
+    if (NLocal==1 && mul>12) {
+       Int_t nnew=0;
+       for (i=0; i<mul; i++) {
+           if (!IsLocal[i]) {
+               IndLocal[NLocal]=i;
+               IsLocal[i]=kTRUE;
+               NLocal++;
+               nnew++;
+           }
+           if (nnew==1) break;
+       }
+    }
+    
+// If number of local maxima is 2 try to fit a double gaussian
+    if (NLocal==2) {
+//
+//  Initialise global variables for fit
+       gFirst=1;
+       gSegmentation=fSegmentation;
+       gResponse    =fResponse;
+       gNbins=mul;
+       
+       for (i=0; i<mul; i++) {
+           gix[i]=ix[i];
+           giy[i]=iy[i];
+           gCharge[i]=Float_t(q[i]);
+       }
+//
+       if (gFirst) {
+         gFirst=kFALSE;
+         gMyMinuit = new TMinuit(5);
+       }
+       gMyMinuit->SetFCN(fcn);
+       gMyMinuit->mninit(5,10,7);
+       Double_t arglist[20];
+       Int_t ierflag=0;
+       arglist[0]=1;
+//     gMyMinuit->mnexcm("SET ERR",arglist,1,ierflag);
+// Set starting values 
+       static Double_t vstart[5];
+       vstart[0]=x[IndLocal[0]];
+       vstart[1]=y[IndLocal[0]];       
+       vstart[2]=x[IndLocal[1]];
+       vstart[3]=y[IndLocal[1]];       
+       vstart[4]=Float_t(q[IndLocal[0]])/
+           Float_t(q[IndLocal[0]]+q[IndLocal[1]]);
+// lower and upper limits
+       static Double_t lower[5], upper[5];
+       Int_t isec=fSegmentation->Sector(ix[IndLocal[0]], iy[IndLocal[0]]);
+       lower[0]=vstart[0]-fSegmentation->Dpx(isec)/2;
+       lower[1]=vstart[1]-fSegmentation->Dpy(isec)/2;
+//     lower[1]=vstart[1];
+       
+       upper[0]=lower[0]+fSegmentation->Dpx(isec);
+       upper[1]=lower[1]+fSegmentation->Dpy(isec);
+//     upper[1]=vstart[1];
+       
+       isec=fSegmentation->Sector(ix[IndLocal[1]], iy[IndLocal[1]]);
+       lower[2]=vstart[2]-fSegmentation->Dpx(isec)/2;
+       lower[3]=vstart[3]-fSegmentation->Dpy(isec)/2;
+//     lower[3]=vstart[3];
+       
+       upper[2]=lower[2]+fSegmentation->Dpx(isec);
+       upper[3]=lower[3]+fSegmentation->Dpy(isec);
+//     upper[3]=vstart[3];
+       
+       lower[4]=0.;
+       upper[4]=1.;
+// step sizes
+       static Double_t step[5]={0.005, 0.03, 0.005, 0.03, 0.01};
+       
+       gMyMinuit->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
+       gMyMinuit->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
+       gMyMinuit->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
+       gMyMinuit->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
+       gMyMinuit->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
+// ready for minimisation      
+       gMyMinuit->SetPrintLevel(-1);
+       gMyMinuit->mnexcm("SET OUT", arglist, 0, ierflag);
+       arglist[0]= -1;
+       arglist[1]= 0;
+       
+       gMyMinuit->mnexcm("SET NOGR", arglist, 0, ierflag);
+       gMyMinuit->mnexcm("SCAN", arglist, 0, ierflag);
+       gMyMinuit->mnexcm("EXIT" , arglist, 0, ierflag);
+// Print results
+//     Double_t amin,edm,errdef;
+//     Int_t nvpar,nparx,icstat;
+//     gMyMinuit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
+//     gMyMinuit->mnprin(3,amin);
+// Get fitted parameters
+
+       Double_t xrec[2], yrec[2], qfrac;
+       TString chname;
+       Double_t epxz, b1, b2;
+       Int_t ierflg;
+       gMyMinuit->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);    
+       gMyMinuit->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);    
+       gMyMinuit->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);    
+       gMyMinuit->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);    
+       gMyMinuit->mnpout(4, chname, qfrac,   epxz, b1, b2, ierflg);    
+       printf("\n %f %f %f %f %f\n", xrec[0], yrec[0], xrec[1], yrec[1],qfrac);
+//     delete gMyMinuit;
+       
+       
+ //
+ // One cluster for each maximum
+ //
+        for (j=0; j<2; j++) {
+            AliMUONRawCluster cnew;
+            if (fNPeaks == 0) {
+                cnew.fNcluster[0]=-1;
+                cnew.fNcluster[1]=fNRawClusters;
+            } else {
+                cnew.fNcluster[0]=fNPeaks;
+                cnew.fNcluster[1]=0;
+            }
+            cnew.fMultiplicity=0;
+            cnew.fX=Float_t(xrec[j]);
+            cnew.fY=Float_t(yrec[j]);
+            if (j==0) {
+                cnew.fQ=static_cast<Int_t>(gChargeTot*qfrac);
+            } else {
+                cnew.fQ=static_cast<Int_t>(gChargeTot*(1-qfrac));
+            }
+            gSegmentation->SetHit(xrec[j],yrec[j]);
+            for (i=0; i<mul; i++) {
+                cnew.fIndexMap[cnew.fMultiplicity]=c->fIndexMap[i];
+                gSegmentation->SetPad(gix[i], giy[i]);
+                Float_t q1=gResponse->IntXY(gSegmentation);
+                cnew.fContMap[cnew.fMultiplicity]=Float_t(q[i])/(q1*cnew.fQ);
+                cnew.fMultiplicity++;
+            }
+            FillCluster(&cnew,0);
+            //printf("\n x,y %f %f ", cnew.fX, cnew.fY);
+            cnew.fClusterType=cnew.PhysicsContribution();
+            AddRawCluster(cnew);
+            fNPeaks++;
+        }
+     }
+
+     Bool_t fitted=true;
+
+     if (NLocal !=2 || !fitted) {
+ // Check if enough local clusters have been found,
+ // if not add global maxima to the list 
+ //
+        Int_t nPerMax;
+        if (NLocal!=0) {
+            nPerMax=mul/NLocal;
+        } else {
+            printf("\n Warning, no local maximum found \n");
+            nPerMax=fNperMax+1;
+        }
+
+        if (nPerMax > fNperMax) {
+            Int_t nGlob=mul/fNperMax-NLocal+1;
+            if (nGlob > 0) {
+                Int_t nnew=0;
+                for (i=0; i<mul; i++) {
+                    if (!IsLocal[i]) {
+                        IndLocal[NLocal]=i;
+                        IsLocal[i]=kTRUE;
+                        NLocal++;
+                        nnew++;
+                    }
+                    if (nnew==nGlob) break;
+                }
+            }
+        }
+ //
+ // Associate hits to peaks
+ //
+        for (i=0; i<mul; i++) {
+            Float_t dmin=1.E10;
+            Float_t qmax=0;
+            if (IsLocal[i]) continue;
+            for (j=0; j<NLocal; j++) {
+                Int_t il=IndLocal[j];
+                Float_t d=TMath::Sqrt((x[i]-x[il])*(x[i]-x[il])
+                                  +(y[i]-y[il])*(y[i]-y[il]));
+                Float_t ql=q[il];
+ //
+ // Select nearest peak
+ //
+                if (d<dmin) {
+                    dmin=d;
+                    qmax=ql;
+                    AssocPeak[i]=j;
+                } else if (d==dmin) {
+ //
+ // If more than one take highest peak
+ //
+                    if (ql>qmax) {
+                        dmin=d;
+                        qmax=ql;
+                        AssocPeak[i]=j;
+                    }
+                }
+            }
+        }
+
+
+ //
+ // One cluster for each maximum
+ //
+        for (j=0; j<NLocal; j++) {
+            AliMUONRawCluster cnew;
+            if (fNPeaks == 0) {
+                cnew.fNcluster[0]=-1;
+                cnew.fNcluster[1]=fNRawClusters;
+            } else {
+                cnew.fNcluster[0]=fNPeaks;
+                cnew.fNcluster[1]=0;
+            }
+            cnew.fIndexMap[0]=c->fIndexMap[IndLocal[j]];
+            cnew.fMultiplicity=1;
+            for (i=0; i<mul; i++) {
+                if (IsLocal[i]) continue;
+                if (AssocPeak[i]==j) {
+                    cnew.fIndexMap[cnew.fMultiplicity]=c->fIndexMap[i];
+                    cnew.fMultiplicity++;
+                }
+            }
+            FillCluster(&cnew);
+            cnew.fClusterType=cnew.PhysicsContribution();
+            AddRawCluster(cnew);
+            fNPeaks++;
+        }
+     }
+     
+}
+
+
+void  AliMUONClusterFinder::FillCluster(AliMUONRawCluster* c, Int_t flag) 
+{
+//
+//  Completes cluster information starting from list of digits
+//
+    AliMUONdigit* dig;
+    Float_t x, y;
+    Int_t  ix, iy;
+    Float_t frac=0;
+    
+    c->fPeakSignal=0;
+    if (flag) {
+       c->fX=0;
+       c->fY=0;
+       c->fQ=0;
+    }
+    //c->fQ=0;
+
+    for (Int_t i=0; i<c->fMultiplicity; i++)
+    {
+       dig= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
+       ix=dig->fPadX+c->fOffsetMap[i];
+       iy=dig->fPadY;
+       Int_t q=dig->fSignal;
+       if (dig->fPhysics >= dig->fSignal) {
+         c->fPhysicsMap[i]=2;
+       } else if (dig->fPhysics == 0) {
+         c->fPhysicsMap[i]=0;
+       } else  c->fPhysicsMap[i]=1;
+//
+//
+// peak signal and track list
+       if (flag) {
+          if (q>c->fPeakSignal) {
+             c->fPeakSignal=q;
+/*
+           c->fTracks[0]=dig->fTracks[0];
+           c->fTracks[1]=dig->fTracks[1];
+           c->fTracks[2]=dig->fTracks[2];
+*/
+             //c->fTracks[0]=dig->fTrack;
+           c->fTracks[0]=dig->fHit;
+           c->fTracks[1]=dig->fTracks[0];
+           c->fTracks[2]=dig->fTracks[1];
+          }
+       } else {
+          if (c->fContMap[i] > frac) {
+              frac=c->fContMap[i];
+             c->fPeakSignal=q;
+/*
+           c->fTracks[0]=dig->fTracks[0];
+           c->fTracks[1]=dig->fTracks[1];
+           c->fTracks[2]=dig->fTracks[2];
+*/
+             //c->fTracks[0]=dig->fTrack;
+           c->fTracks[0]=dig->fHit;
+           c->fTracks[1]=dig->fTracks[0];
+           c->fTracks[2]=dig->fTracks[1];
+          }
+       }
+//
+       if (flag) {
+           fSegmentation->GetPadCxy(ix, iy, x, y);
+           c->fX += q*x;
+           c->fY += q*y;
+           c->fQ += q;
+       }
+
+    } // loop over digits
+
+ if (flag) {
+     
+     c->fX/=c->fQ;
+     c->fX=fSegmentation->GetAnod(c->fX);
+     c->fY/=c->fQ; 
+//
+//  apply correction to the coordinate along the anode wire
+//
+     x=c->fX;   
+     y=c->fY;
+     fSegmentation->GetPadIxy(x, y, ix, iy);
+     fSegmentation->GetPadCxy(ix, iy, x, y);
+     Int_t isec=fSegmentation->Sector(ix,iy);
+     TF1* CogCorr = fSegmentation->CorrFunc(isec-1);
+     
+     if (CogCorr) {
+        Float_t YonPad=(c->fY-y)/fSegmentation->Dpy(isec);
+        c->fY=c->fY-CogCorr->Eval(YonPad, 0, 0);
+     }
+ }
+}
+
+
+void  AliMUONClusterFinder::FindCluster(Int_t i, Int_t j, AliMUONRawCluster &c){
+//
+//  Find clusters
+//
+//
+//  Add i,j as element of the cluster
+//    
+    
+    Int_t idx = fHitMap->GetHitIndex(i,j);
+    AliMUONdigit* dig = (AliMUONdigit*) fHitMap->GetHit(i,j);
+    Int_t q=dig->fSignal;
+    if (q > TMath::Abs(c.fPeakSignal)) {
+       c.fPeakSignal=q;
+/*
+       c.fTracks[0]=dig->fTracks[0];
+       c.fTracks[1]=dig->fTracks[1];
+       c.fTracks[2]=dig->fTracks[2];
+*/
+       //c.fTracks[0]=dig->fTrack;
+       c.fTracks[0]=dig->fHit;
+       c.fTracks[1]=dig->fTracks[0];
+       c.fTracks[2]=dig->fTracks[1];
+    }
+//
+//  Make sure that list of digits is ordered 
+// 
+    Int_t mu=c.fMultiplicity;
+    c.fIndexMap[mu]=idx;
+
+    if (dig->fPhysics >= dig->fSignal) {
+        c.fPhysicsMap[mu]=2;
+    } else if (dig->fPhysics == 0) {
+        c.fPhysicsMap[mu]=0;
+    } else  c.fPhysicsMap[mu]=1;
+
+    if (mu > 0) {
+       for (Int_t ind=mu-1; ind>=0; ind--) {
+           Int_t ist=(c.fIndexMap)[ind];
+           Int_t ql=((AliMUONdigit*)fDigits
+                     ->UncheckedAt(ist))->fSignal;
+           if (q>ql) {
+               c.fIndexMap[ind]=idx;
+               c.fIndexMap[ind+1]=ist;
+           } else {
+               break;
+           }
+       }
+    }
+    
+    c.fMultiplicity++;
+    
+    if (c.fMultiplicity >= 50 ) {
+       printf("FindCluster - multiplicity >50  %d \n",c.fMultiplicity);
+       c.fMultiplicity=49;
+    }
+
+// Prepare center of gravity calculation
+    Float_t x, y;
+    fSegmentation->GetPadCxy(i, j, x, y);
+    c.fX += q*x;
+    c.fY += q*y;
+    c.fQ += q;
+// Flag hit as taken  
+    fHitMap->FlagHit(i,j);
+//
+//  Now look recursively for all neighbours
+//  
+    Int_t nn;
+    Int_t Xlist[kMaxNeighbours], Ylist[kMaxNeighbours];
+    fSegmentation->Neighbours(i,j,&nn,Xlist,Ylist);
+    for (Int_t in=0; in<nn; in++) {
+       Int_t ix=Xlist[in];
+       Int_t iy=Ylist[in];
+       if (fHitMap->TestHit(ix,iy)==unused) FindCluster(ix, iy, c);
+    }
+}
+
+//_____________________________________________________________________________
+
+void AliMUONClusterFinder::FindRawClusters()
+{
+  //
+  // simple MUON cluster finder from digits -- finds neighbours and 
+  // fill the tree with raw clusters
+  //
+    if (!fNdigits) return;
+
+    fHitMap = new AliMUONHitMapA1(fSegmentation, fDigits);
+
+    AliMUONdigit *dig;
+
+    Int_t ndig;
+    Int_t nskip=0;
+    Int_t ncls=0;
+    fHitMap->FillHits();
+    for (ndig=0; ndig<fNdigits; ndig++) {
+       dig = (AliMUONdigit*)fDigits->UncheckedAt(ndig);
+       Int_t i=dig->fPadX;
+       Int_t j=dig->fPadY;
+       if (fHitMap->TestHit(i,j)==used ||fHitMap->TestHit(i,j)==empty) {
+           nskip++;
+           continue;
+       }
+       AliMUONRawCluster c;
+       c.fMultiplicity=0;
+       c.fPeakSignal=dig->fSignal;
+/*
+       c.fTracks[0]=dig->fTracks[0];
+       c.fTracks[1]=dig->fTracks[1];
+       c.fTracks[2]=dig->fTracks[2];
+*/
+       //c.fTracks[0]=dig->fTrack;
+       c.fTracks[0]=dig->fHit;
+       c.fTracks[1]=dig->fTracks[0];
+       c.fTracks[2]=dig->fTracks[1];
+        // tag the beginning of cluster list in a raw cluster
+        c.fNcluster[0]=-1;
+       FindCluster(i,j, c);
+       // center of gravity
+       c.fX /= c.fQ;
+       c.fX=fSegmentation->GetAnod(c.fX);
+       c.fY /= c.fQ;
+//
+//  apply correction to the coordinate along the anode wire
+//
+       Int_t ix,iy;
+       Float_t x=c.fX;   
+       Float_t y=c.fY;
+       fSegmentation->GetPadIxy(x, y, ix, iy);
+       fSegmentation->GetPadCxy(ix, iy, x, y);
+       Int_t isec=fSegmentation->Sector(ix,iy);
+       TF1* CogCorr=fSegmentation->CorrFunc(isec-1);
+       if (CogCorr) {
+           Float_t YonPad=(c.fY-y)/fSegmentation->Dpy(isec);
+           c.fY=c.fY-CogCorr->Eval(YonPad,0,0);
+       }
+
+//
+//      Analyse cluster and decluster if necessary
+//     
+    ncls++;
+    c.fNcluster[1]=fNRawClusters;
+    c.fClusterType=c.PhysicsContribution();
+    Decluster(&c);
+    fNPeaks=0;
+//
+//
+//
+//      reset Cluster object
+       for (int k=0;k<c.fMultiplicity;k++) {
+           c.fIndexMap[k]=0;
+       }
+       c.fMultiplicity=0;
+    } // end loop ndig    
+    delete fHitMap;
+}
+
+void AliMUONClusterFinder::
+CalibrateCOG()
+{
+    Float_t x[5];
+    Float_t y[5];
+    Int_t n, i;
+    TF1 func;
+    if (fSegmentation) {
+       fSegmentation->GiveTestPoints(n, x, y);
+       for (i=0; i<n; i++) {
+           Float_t xtest=x[i];
+           Float_t ytest=y[i];     
+           SinoidalFit(xtest, ytest, func);
+           fSegmentation->SetCorrFunc(i, new TF1(func));
+       }
+    }
+}
+
+
+void AliMUONClusterFinder::
+SinoidalFit(Float_t x, Float_t y, TF1 &func)
+{
+//
+    static Int_t count=0;
+    char canvasname[3];
+    count++;
+    sprintf(canvasname,"c%d",count);
+
+    Int_t ns=101;
+    Float_t xg[ns], yg[ns], xrg[ns], yrg[ns];
+    Float_t xsig[ns], ysig[ns];
+   
+    AliMUONsegmentation *segmentation=fSegmentation;
+
+    Int_t ix,iy;
+    segmentation->GetPadIxy(x,y,ix,iy);   
+    segmentation->GetPadCxy(ix,iy,x,y);   
+    Int_t isec=segmentation->Sector(ix,iy);
+// Pad Limits    
+    Float_t xmin = x-segmentation->Dpx(isec)/2;
+    Float_t ymin = y-segmentation->Dpy(isec)/2;
+//             
+//      Integration Limits
+    Float_t dxI=fResponse->SigmaIntegration()*fResponse->ChargeSpreadX();
+    Float_t dyI=fResponse->SigmaIntegration()*fResponse->ChargeSpreadY();
+
+//
+//  Scanning
+//
+    Int_t i;
+    Float_t qp;
+//
+//  y-position
+    Float_t yscan=ymin;
+    Float_t dy=segmentation->Dpy(isec)/(ns-1);
+
+    for (i=0; i<ns; i++) {
+//
+//      Pad Loop
+//      
+       Float_t sum=0;
+       Float_t qcheck=0;
+       segmentation->SigGenInit(x, yscan, 0);
+       
+       for (segmentation->FirstPad(x, yscan, dxI, dyI); 
+            segmentation->MorePads(); 
+            segmentation->NextPad()) 
+       {
+           qp=fResponse->IntXY(segmentation);
+           qp=TMath::Abs(qp);
+//
+//
+           if (qp > 1.e-4) {
+               qcheck+=qp;
+               Int_t ixs=segmentation->Ix();
+               Int_t iys=segmentation->Iy();
+               Float_t xs,ys;
+               segmentation->GetPadCxy(ixs,iys,xs,ys);
+               sum+=qp*ys;
+           }
+       } // Pad loop
+       Float_t ycog=sum/qcheck;
+       yg[i]=(yscan-y)/segmentation->Dpy(isec);
+       yrg[i]=(ycog-y)/segmentation->Dpy(isec);
+       ysig[i]=ycog-yscan;
+       yscan+=dy;
+    } // scan loop
+//
+//  x-position
+    Float_t xscan=xmin;
+    Float_t dx=segmentation->Dpx(isec)/(ns-1);
+
+    for (i=0; i<ns; i++) {
+//
+//      Pad Loop
+//      
+       Float_t sum=0;
+       Float_t qcheck=0;
+       segmentation->SigGenInit(xscan, y, 0);
+       
+       for (segmentation->FirstPad(xscan, y, dxI, dyI); 
+            segmentation->MorePads(); 
+            segmentation->NextPad()) 
+       {
+           qp=fResponse->IntXY(segmentation);
+           qp=TMath::Abs(qp);
+//
+//
+           if (qp > 1.e-2) {
+               qcheck+=qp;
+               Int_t ixs=segmentation->Ix();
+               Int_t iys=segmentation->Iy();
+               Float_t xs,ys;
+               segmentation->GetPadCxy(ixs,iys,xs,ys);
+               sum+=qp*xs;
+           }
+       } // Pad loop
+       Float_t xcog=sum/qcheck;
+       xcog=segmentation->GetAnod(xcog);
+       
+       xg[i]=(xscan-x)/segmentation->Dpx(isec);
+       xrg[i]=(xcog-x)/segmentation->Dpx(isec);
+       xsig[i]=xcog-xscan;
+       xscan+=dx;
+    }
+//
+// Creates a Root function based on function sinoid above
+// and perform the fit
+//
+    //    TGraph *graphx = new TGraph(ns,xg ,xsig);
+    //    TGraph *graphxr= new TGraph(ns,xrg,xsig);   
+    //    TGraph *graphy = new TGraph(ns,yg ,ysig);
+    TGraph *graphyr= new TGraph(ns,yrg,ysig);
+
+    Double_t sinoid(Double_t *x, Double_t *par);
+    new TF1("sinoidf",sinoid,0.5,0.5,5);
+    graphyr->Fit("sinoidf","Q");
+    func = *((TF1*)((graphyr->GetListOfFunctions())->At(0)));
+/*
+    
+    TCanvas *c1=new TCanvas(canvasname,canvasname,400,10,600,700);
+    TPad* pad11 = new TPad("pad11"," ",0.01,0.51,0.49,0.99);
+    TPad* pad12 = new TPad("pad12"," ",0.51,0.51,0.99,0.99);
+    TPad* pad13 = new TPad("pad13"," ",0.01,0.01,0.49,0.49);
+    TPad* pad14 = new TPad("pad14"," ",0.51,0.01,0.99,0.49);
+    pad11->SetFillColor(11);
+    pad12->SetFillColor(11);
+    pad13->SetFillColor(11);
+    pad14->SetFillColor(11);
+    pad11->Draw();
+    pad12->Draw();
+    pad13->Draw();
+    pad14->Draw();
+    
+//
+    pad11->cd();
+    graphx->SetFillColor(42);
+    graphx->SetMarkerColor(4);
+    graphx->SetMarkerStyle(21);
+    graphx->Draw("AC");
+    graphx->GetHistogram()->SetXTitle("x on pad");
+    graphx->GetHistogram()->SetYTitle("xcog-x");   
+
+
+    pad12->cd();
+    graphxr->SetFillColor(42);
+    graphxr->SetMarkerColor(4);
+    graphxr->SetMarkerStyle(21);
+    graphxr->Draw("AP");
+    graphxr->GetHistogram()->SetXTitle("xcog on pad");
+    graphxr->GetHistogram()->SetYTitle("xcog-x");   
+    
+
+    pad13->cd();
+    graphy->SetFillColor(42);
+    graphy->SetMarkerColor(4);
+    graphy->SetMarkerStyle(21);
+    graphy->Draw("AF");
+    graphy->GetHistogram()->SetXTitle("y on pad");
+    graphy->GetHistogram()->SetYTitle("ycog-y");   
+    
+
+
+    pad14->cd();
+    graphyr->SetFillColor(42);
+    graphyr->SetMarkerColor(4);
+    graphyr->SetMarkerStyle(21);
+    graphyr->Draw("AF");
+    graphyr->GetHistogram()->SetXTitle("ycog on pad");
+    graphyr->GetHistogram()->SetYTitle("ycog-y");   
+    
+    c1->Update();
+*/
+}
+
+Double_t sinoid(Double_t *x, Double_t *par)
+{
+    Double_t arg = -2*TMath::Pi()*x[0];
+    Double_t fitval= par[0]*TMath::Sin(arg)+
+       par[1]*TMath::Sin(2*arg)+
+       par[2]*TMath::Sin(3*arg)+
+       par[3]*TMath::Sin(4*arg)+
+       par[4]*TMath::Sin(5*arg);
+    return fitval;
+ }
+
+
+Double_t DoubleGauss(Double_t *x, Double_t *par)
+{
+    Double_t arg1 = (x[0]-par[1])/0.18;
+    Double_t arg2 = (x[0]-par[3])/0.18;
+    Double_t fitval= par[0]*TMath::Exp(-arg1*arg1/2)
+       +par[2]*TMath::Exp(-arg2*arg2/2);
+    return fitval;
+ }
+
+Float_t DiscrCharge(Int_t i,Double_t *par) 
+{
+// par[0]    x-position of first  cluster
+// par[1]    y-position of first  cluster
+// par[2]    x-position of second cluster
+// par[3]    y-position of second cluster
+// par[4]    charge fraction of first  cluster
+// 1-par[4]  charge fraction of second cluster
+
+    static Float_t qtot;
+    if (gFirst) {
+       qtot=0;
+       for (Int_t jbin=0; jbin<gNbins; jbin++) {
+           qtot+=gCharge[jbin];
+       }
+       gFirst=0;
+       //printf("\n sum of charge from DiscrCharge %f\n", qtot);
+       gChargeTot=static_cast<Int_t>(qtot);
+       
+    }
+    gSegmentation->SetPad(gix[i], giy[i]);
+//  First Cluster
+    gSegmentation->SetHit(par[0],par[1]);
+    Float_t q1=gResponse->IntXY(gSegmentation);
+    
+//  Second Cluster
+    gSegmentation->SetHit(par[2],par[3]);
+    Float_t q2=gResponse->IntXY(gSegmentation);
+    
+    Float_t value = qtot*(par[4]*q1+(1.-par[4])*q2);
+    return value;
+}
+
+//
+// Minimisation function
+void fcn(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
+{
+    Int_t i;
+    Float_t delta;
+    Float_t chisq=0;
+    Float_t qcont=0;
+    Float_t qtot=0;
+    
+    for (i=0; i<gNbins; i++) {
+       Float_t q0=gCharge[i];
+       Float_t q1=DiscrCharge(i,par);
+       delta=(q0-q1)/TMath::Sqrt(q0);
+       chisq+=delta*delta;
+       qcont+=q1;
+       qtot+=q0;
+    }
+    chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
+    f=chisq;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONClusterFinder.h b/MUON/AliMUONClusterFinder.h
new file mode 100644 (file)
index 0000000..303d73d
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef AliMUONClusterFinder_H
+#define AliMUONClusterFinder_H
+////////////////////////////////////////////////
+//  MUON Cluster Finder Class                 //
+////////////////////////////////////////////////
+#include "AliMUONHitMap.h"
+#include "TF1.h"
+class AliMUONClusterFinder :
+ public TObject
+{
+public:
+    TClonesArray*           fDigits;
+    Int_t                   fNdigits;
+protected:
+    AliMUONsegmentation*    fSegmentation;
+    AliMUONresponse*        fResponse;
+    TClonesArray*           fRawClusters;
+    Int_t                   fChamber;
+    Int_t                   fNRawClusters;
+    AliMUONHitMapA1*        fHitMap;
+    TF1*                    fCogCorr;
+    Int_t                   fNperMax;
+    Int_t                   fDeclusterFlag;
+    Int_t                   fClusterSize;
+    Int_t                   fNPeaks; 
+ public:
+    AliMUONClusterFinder
+       (AliMUONsegmentation *segmentation,
+        AliMUONresponse *response, TClonesArray *digits, Int_t chamber);
+    AliMUONClusterFinder();
+    ~AliMUONClusterFinder(){delete fRawClusters;}
+    virtual void SetSegmentation(
+       AliMUONsegmentation *segmentation){
+       fSegmentation=segmentation;
+    }
+    virtual void SetResponse(AliMUONresponse *response) {
+       fResponse=response;
+    }
+
+    virtual void SetDigits(TClonesArray *MUONdigits) {
+       fDigits=MUONdigits;
+       fNdigits = fDigits->GetEntriesFast();
+    }
+    
+    virtual void SetChamber(Int_t ich){
+       fChamber=ich;
+    }
+    
+    virtual void AddRawCluster(const AliMUONRawCluster);
+    // Search for raw clusters
+    virtual void FindRawClusters();
+    virtual void  FindCluster(Int_t i, Int_t j, AliMUONRawCluster &c);
+    // Decluster
+    virtual void Decluster(AliMUONRawCluster *cluster);
+    // Set max. Number of pads per local cluster
+    virtual void SetNperMax(Int_t npermax=5) {fNperMax = npermax;}
+    // Decluster ?
+    virtual void SetDeclusterFlag(Int_t flag=1) {fDeclusterFlag =flag;}
+    // Set max. cluster size ; bigger clusters will be rejected
+    virtual void SetClusterSize(Int_t clsize=5) {fClusterSize = clsize;}
+    // Self Calibration of COG 
+    virtual void CalibrateCOG();
+    virtual void SinoidalFit(Float_t x, Float_t y, TF1 &func);
+    //
+    virtual void CorrectCOG(){;}
+    
+    //
+    virtual Bool_t Centered(AliMUONRawCluster *cluster);
+    virtual void   SplitByLocalMaxima(AliMUONRawCluster *cluster);
+    virtual void   FillCluster(AliMUONRawCluster *cluster, Int_t);
+    virtual void   FillCluster(AliMUONRawCluster *cluster) {
+       FillCluster(cluster,1);}
+    TClonesArray* RawClusters(){return fRawClusters;}
+    ClassDef(AliMUONClusterFinder,1) //Class for clustering and reconstruction of space points
+};
+#endif
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONClusterFinderv0.cxx b/MUON/AliMUONClusterFinderv0.cxx
new file mode 100644 (file)
index 0000000..64b138f
--- /dev/null
@@ -0,0 +1,766 @@
+#include "AliMUONClusterFinderv0.h"
+#include "AliMUONSegResV1.h"
+//#include "TTree.h"
+//#include "AliRun.h"
+//#include <TCanvas.h>
+//#include <TH1.h>
+//#include <TPad.h>
+//#include <TGraph.h> 
+
+//----------------------------------------------------------
+ClassImp(AliMUONClusterFinderv0)
+
+    AliMUONClusterFinderv0::AliMUONClusterFinderv0
+(AliMUONsegmentation *segmentation, AliMUONresponse *response, 
+ TClonesArray *digits, Int_t chamber) : AliMUONClusterFinder(segmentation,response,digits,chamber)
+{;}
+
+    AliMUONClusterFinderv0::AliMUONClusterFinderv0():AliMUONClusterFinder()
+{;}
+
+/*
+void AliMUONClusterFinder::AddRawCluster(const AliMUONRawCluster c)
+{
+  //
+  // Add a raw cluster copy to the list
+  //
+    AliMUON *MUON=(AliMUON*)gAlice->GetModule("MUON");
+    MUON->AddRawCluster(fChamber,c); 
+    fNRawClusters++;
+}
+*/
+
+
+
+void AliMUONClusterFinderv0::Decluster(AliMUONRawCluster *cluster)
+{
+//    AliMUONdigit *dig;
+//    Int_t q;
+    static int done=0;
+    if (!done) {
+       printf("Calling decluster\n");
+       done=1;
+    }
+    
+
+    
+    Int_t mul = cluster->fMultiplicity;
+//    printf("Decluster - multiplicity   %d \n",mul);
+
+    if (mul == 1) {
+//     printf("\n Nothing special for 1-clusters \n");
+//
+// Nothing special for 1-clusters
+//
+       AddRawCluster(*cluster); 
+    } else if (mul ==2) {
+//
+// 2-cluster, compute offset
+//
+        SetOffset(cluster);
+       FillCluster(cluster);
+        AddRawCluster(*cluster); 
+    } else if (mul ==3) {
+//
+// 3-cluster, check topology
+//     printf("\n 3-cluster, check topology \n");
+//
+       if (Centered(cluster)) {
+//
+// ok, cluster is centered 
+//         printf("\n ok, cluster is centered \n");
+       } else {
+//
+// cluster is not centered, split into 2+1
+//         printf("\n cluster is not centered, split into 2+1 \n");
+       }
+           
+    } else {
+       if (mul >(50-5)) printf("Decluster - multiplicity %d approaching 50\n",mul);
+// 
+// 4-and more-pad clusters
+//
+       SplitByLocalMaxima(cluster);
+    } // multiplicity 
+}
+
+Int_t AliMUONClusterFinderv0::PeakOffsetAndCoordinates(Int_t DigitIndex, Float_t *X, Float_t *Y)
+//
+// Computes for which allowed offsets the digit has the highest neighbouring charge
+// Returns the value of the offset, and sets the pyisical coordinates of that pad
+// Loop on physical neighbours is specific to AliMUONsegmentationV1
+{
+Int_t nPara, offset, returnOffset=0 ;
+AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(DigitIndex);
+AliMUONsegmentationV1* seg = (AliMUONsegmentationV1*) fSegmentation;
+seg->GetNParallelAndOffset(dig->fPadX,dig->fPadY,&nPara,&offset);
+if (nPara>1)
+  {
+  Float_t qMax=0;
+  for (Int_t i=0;i<nPara; i++)
+    {
+    // Compute the charge on the 9 neighbouring pads
+    // We assume that there are no pads connected in parallel in the neighbourhood
+    //
+    Float_t q=0;
+    for (Int_t dx=-1;dx<2;dx++)
+      for (Int_t dy=-1;dy<2;dy++)
+        {
+        if (dx==dy && dy==0)
+          continue; 
+        Int_t padY=dig->fPadY+dy;
+        Int_t padX=seg->Ix((Int_t) (dig->fPadX+dx+i*offset) , padY);
+       if (fHitMap->TestHit(padX, padY)==empty) 
+          continue;
+        AliMUONdigit* digt = (AliMUONdigit*) fHitMap->GetHit(padX,padY);
+        q += digt->fSignal;
+        }
+    if (q>qMax)
+      {
+      returnOffset=i*offset;
+      qMax=q;
+      }
+    }
+  }
+fSegmentation->GetPadCxy(dig->fPadX+returnOffset,dig->fPadY,*X,*Y);
+return returnOffset;
+}
+
+
+void AliMUONClusterFinderv0::SetOffset(AliMUONRawCluster *cluster)
+// compute the offsets assuming that there is only one peak !
+{
+//DumpCluster(cluster);
+Float_t X,Y;
+cluster->fOffsetMap[0]=PeakOffsetAndCoordinates(cluster->fIndexMap[0],&X,&Y);
+for (Int_t i=1;i<cluster->fMultiplicity;i++) {
+  AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[i]);
+  fSegmentation->Distance2AndOffset(dig->fPadX,dig->fPadY,X,Y,&(cluster->fOffsetMap[i]));
+  }
+}
+
+void AliMUONClusterFinderv0::DumpCluster(AliMUONRawCluster *cluster)
+{    
+printf ("other cluster\n");
+for (Int_t i=0; i<cluster->fMultiplicity; i++)
+    {
+       AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[i]);
+       Int_t nPara, offset;
+       fSegmentation->GetNParallelAndOffset(dig->fPadX,dig->fPadY,&nPara,&offset);
+
+       printf("X %d Y %d Q %d NPara %d \n",dig->fPadX, dig->fPadY,dig->fSignal, nPara);
+    }
+}
+
+Bool_t AliMUONClusterFinderv0::Centered(AliMUONRawCluster *cluster)
+{
+    AliMUONdigit* dig;
+    dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[0]);
+    Int_t ix=dig->fPadX;
+    Int_t iy=dig->fPadY;
+    Int_t nn;
+    Int_t X[kMaxNeighbours], Y[kMaxNeighbours], XN[kMaxNeighbours], YN[kMaxNeighbours];
+    fSegmentation->Neighbours(ix,iy,&nn,X,Y);
+
+    Int_t nd=0;
+    for (Int_t i=0; i<nn; i++) {
+       if (fHitMap->TestHit(X[i],Y[i]) == used) {
+           XN[nd]=X[i];
+           YN[nd]=Y[i];
+           nd++;
+       }
+    }
+    if (nd==2) {
+//
+// cluster is centered !
+       SetOffset(cluster);
+       FillCluster(cluster);
+       AddRawCluster(*cluster);
+       return kTRUE;
+    } else if (nd ==1) {
+//
+// Highest signal on an edge, split cluster into 2+1
+//
+// who is the neighbour ?
+       Int_t nind=fHitMap->GetHitIndex(XN[0], YN[0]);
+       Int_t i1= (nind==cluster->fIndexMap[1]) ? 1:2;
+       Int_t i2= (nind==cluster->fIndexMap[1]) ? 2:1;    
+//
+// 2-cluster
+       AliMUONRawCluster cnew;
+       cnew.fMultiplicity=2;
+       cnew.fIndexMap[0]=cluster->fIndexMap[0];
+       cnew.fIndexMap[1]=cluster->fIndexMap[i1];
+       SetOffset(&cnew);
+       FillCluster(&cnew);
+       AddRawCluster(cnew);
+//
+// 1-cluster
+       cluster->fMultiplicity=1;
+       cluster->fIndexMap[0]=cluster->fIndexMap[i2];
+       cluster->fIndexMap[1]=0;
+       cluster->fIndexMap[2]=0;        
+       FillCluster(cluster);
+       AddRawCluster(*cluster);
+       return kFALSE;
+    } else {
+       printf("\n Completely screwed up %d !! \n",nd);
+       
+    }
+    
+       return kFALSE;
+}
+
+
+void AliMUONClusterFinderv0::SplitByLocalMaxima(AliMUONRawCluster *c)
+{
+    AliMUONdigit* dig[50], *digt;
+    Int_t ix[50], iy[50], q[50];
+    Float_t x[50], y[50];
+    Int_t i; // loops over digits
+    Int_t j; // loops over local maxima
+    
+    Int_t mul=c->fMultiplicity;
+//
+//  dump digit information into arrays
+//
+    for (i=0; i<mul; i++)
+    {
+       dig[i]= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
+       ix[i]= dig[i]->fPadX;
+       iy[i]= dig[i]->fPadY;
+       q[i] = dig[i]->fSignal;
+       fSegmentation->GetPadCxy(ix[i], iy[i], x[i], y[i]);
+    }
+//
+//  Find local maxima
+//
+    Bool_t IsLocal[50];
+    Int_t NLocal=0;
+    Int_t AssocPeak[50];
+    Int_t IndLocal[50];
+    Int_t nn;
+    Int_t X[kMaxNeighbours], Y[kMaxNeighbours];
+    for (i=0; i<mul; i++) {
+       fSegmentation->Neighbours(ix[i], iy[i], &nn, X, Y);
+       IsLocal[i]=kTRUE;
+       for (j=0; j<nn; j++) {
+           if (fHitMap->TestHit(X[j], Y[j])==empty) continue;
+           digt=(AliMUONdigit*) fHitMap->GetHit(X[j], Y[j]);
+           if (digt->fSignal > q[i]) {
+               IsLocal[i]=kFALSE;
+               break;
+//
+// handle special case of neighbouring pads with equal signal
+           } else if (digt->fSignal == q[i]) {
+               if (NLocal >0) {
+                   for (Int_t k=0; k<NLocal; k++) {
+                       if (X[j]==ix[IndLocal[k]] && Y[j]==iy[IndLocal[k]]){
+                           IsLocal[i]=kFALSE;
+                       }
+                   }
+               }
+           } 
+       } // loop over next neighbours
+       if (IsLocal[i]) {
+           IndLocal[NLocal]=i;
+            // New for LYON : we guess which is the actual position of the pad hit
+           // But this would run like that for normal chamber !
+            c->fOffsetMap[i]=PeakOffsetAndCoordinates(c->fIndexMap[i], &(x[i]), &(y[i]));
+           NLocal++;
+       } 
+    } // loop over all digits
+//    printf("Found %d local Maxima",NLocal);
+// 
+// Check if enough local clusters have been found,
+// if not add global maxima to the list 
+//
+// But what the hell is that ? (Manu)
+//
+//    Int_t nPerMax=mul/NLocal;
+//    if (nPerMax > 5) {
+//     Int_t nGlob=mul/5-NLocal+1;
+//     if (nGlob > 0) {
+//         Int_t nnew=0;
+//         for (i=0; i<mul; i++) {
+//             if (!IsLocal[i]) {
+//                 IndLocal[NLocal]=i;
+//                 IsLocal[i]=kTRUE;
+//                 NLocal++;
+//                 nnew++;
+//             }
+//             if (nnew==nGlob) break;
+//         }
+//     }
+//   }
+//
+//
+// Associate hits to peaks
+//
+    for (i=0; i<mul; i++) {
+        //
+        // loop on digits
+        //
+       Float_t dmin=1.E10;
+       Float_t qmax=0;
+       Int_t offset;
+       if (IsLocal[i]) continue;
+       for (j=0; j<NLocal; j++) {
+            //
+            // Loop on peaks
+            //
+           Int_t il=IndLocal[j];
+//         Float_t d=TMath::Sqrt((x[i]-x[il])*(x[i]-x[il])
+//                               +(y[i]-y[il])*(y[i]-y[il]));
+            // Can run like that for non-Lyon chambers
+           Float_t d = fSegmentation->Distance2AndOffset(ix[i],iy[i],x[il],y[il], &offset);
+           Float_t ql=q[il];
+//
+// Select nearest peak
+//
+           if (d<dmin) {
+               dmin=d;
+               qmax=ql;
+               AssocPeak[i]=j;
+               c->fOffsetMap[i]=offset;
+           } else if (d==dmin) {
+//
+// If more than one take highest peak
+//
+               if (ql>qmax) {
+                   dmin=d;
+                   qmax=ql;
+                   AssocPeak[i]=j;
+                   c->fOffsetMap[i]=offset;
+               }
+           } // end if
+       } // End loop on peaks
+    } // end loop on digits
+//
+// One cluster for each maximum
+//
+    for (j=0; j<NLocal; j++) {
+       AliMUONRawCluster cnew;
+       cnew.fIndexMap[0]=c->fIndexMap[IndLocal[j]];
+       cnew.fOffsetMap[0]=c->fOffsetMap[IndLocal[j]];
+       cnew.fMultiplicity=1;
+       for (i=0; i<mul; i++) {
+           if (IsLocal[i]) continue;
+           if (AssocPeak[i]==j) {
+               cnew.fIndexMap[cnew.fMultiplicity]=c->fIndexMap[i];
+               cnew.fOffsetMap[cnew.fMultiplicity]=c->fOffsetMap[i];
+               cnew.fMultiplicity++;
+           }
+       }
+       FillCluster(&cnew);
+       AddRawCluster(cnew);
+    }
+}
+
+/*
+void  AliMUONClusterFinderv0::FillCluster(AliMUONRawCluster* c)
+{
+//
+//  Completes cluster information starting from list of digits
+//
+    AliMUONdigit* dig;
+    Float_t x, y;
+    Int_t  ix, iy;
+    
+    c->fPeakSignal=0;
+    c->fX=0;
+    c->fY=0;
+    c->fQ=0;
+    for (Int_t i=0; i<c->fMultiplicity; i++)
+    {
+       dig= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
+       ix=dig->fPadX + c.fOffsetMap[i]; // should be 0 for non-LYON
+       iy=dig->fPadY;
+       Int_t q=dig->fSignal;
+//
+//
+// peak signal and track list
+       if (q>c->fPeakSignal) {
+           c->fPeakSignal=0;
+           c->fTracks[0]=dig->fTracks[0];
+           c->fTracks[1]=dig->fTracks[1];
+           c->fTracks[2]=dig->fTracks[2];
+       }
+//
+// centre of gravity
+       fSegmentation->GetPadCxy(ix, iy, x, y);
+       c->fX += q*x;
+       c->fY += q*y;
+       c->fQ += q;
+    }
+    c->fX/=c->fQ;
+// Not valid for inclined tracks in X !!! (Manu)
+//    c->fX=fSegmentation->GetAnod(c->fX);
+    c->fY/=c->fQ; 
+//
+//  apply correction to the coordinate along the anode wire
+//
+    if (fCogCorr) {
+       x=c->fX;   
+       y=c->fY;
+       fSegmentation->GetPadIxy(x, y, ix, iy);
+       fSegmentation->GetPadCxy(ix, iy, x, y);
+       Float_t YonPad=(c->fY-y)/fSegmentation->Dpy();
+       c->fY=y-fCogCorr->Eval(YonPad, 0, 0);
+    }
+
+}
+*/
+/*
+void  AliMUONClusterFinder::FindCluster(Int_t i, Int_t j, AliMUONRawCluster &c){
+//
+//  Find clusters
+//
+//
+//  Add i,j as element of the cluster
+//    
+    
+    Int_t idx = fHitMap->GetHitIndex(i,j);
+    AliMUONdigit* dig = (AliMUONdigit*) fHitMap->GetHit(i,j);
+    Int_t q=dig->fSignal;
+    if (q > TMath::Abs(c.fPeakSignal)) {
+       c.fPeakSignal=q;
+       c.fTracks[0]=dig->fTracks[0];
+       c.fTracks[1]=dig->fTracks[1];
+       c.fTracks[2]=dig->fTracks[2];
+    }
+//
+//  Make sure that list of digits is ordered 
+// 
+    Int_t mu=c.fMultiplicity;
+    c.fIndexMap[mu]=idx;
+
+    if (mu > 0) {
+       for (Int_t ind=mu-1; ind>=0; ind--) {
+           Int_t ist=(c.fIndexMap)[ind];
+           Int_t ql=((AliMUONdigit*)fDigits
+                     ->UncheckedAt(ist))->fSignal;
+           if (q>ql) {
+               c.fIndexMap[ind]=idx;
+               c.fIndexMap[ind+1]=ist;
+           } else {
+               break;
+           }
+       }
+    }
+    
+    c.fMultiplicity++;
+    
+    if (c.fMultiplicity >= 50 ) {
+       printf("FindCluster - multiplicity >50  %d \n",c.fMultiplicity);
+       c.fMultiplicity=50-1;
+    }
+
+// Prepare center of gravity calculation
+    Float_t x, y;
+    fSegmentation->GetPadCxy(i, j, x, y);
+    c.fX += q*x;
+    c.fY += q*y;
+    c.fQ += q;
+// Flag hit as taken  
+    fHitMap->FlagHit(i,j);
+//
+//  Now look recursively for all neighbours
+//  
+    Int_t nn;
+    Int_t Xlist[kMaxNeighbours], Ylist[kMaxNeighbours];
+    fSegmentation->Neighbours(i,j,&nn,Xlist,Ylist);
+    for (Int_t in=0; in<nn; in++) {
+       Int_t ix=Xlist[in];
+       Int_t iy=Ylist[in];
+       if (fHitMap->TestHit(ix,iy)==unused) FindCluster(ix, iy, c);
+    }
+}
+*/
+
+//_____________________________________________________________________________
+
+void AliMUONClusterFinderv0::FindRawClusters()
+{
+  //
+  // simple MUON cluster finder from digits -- finds neighbours and 
+  // fill the tree with raw clusters
+  //
+    if (!fNdigits) return;
+
+    fHitMap = new AliMUONHitMapA1(fSegmentation, fDigits);
+
+    AliMUONdigit *dig;
+
+    int ndig;
+    int nskip=0;
+
+    fHitMap->FillHits();
+    for (ndig=0; ndig<fNdigits; ndig++) {
+       dig = (AliMUONdigit*)fDigits->UncheckedAt(ndig);
+       Int_t i=dig->fPadX;
+       Int_t j=dig->fPadY;
+       if (fHitMap->TestHit(i,j)==used ||fHitMap->TestHit(i,j)==empty) {
+           nskip++;
+           continue;
+       }
+       AliMUONRawCluster c;
+       c.fMultiplicity=0;
+//     c.fPeakSignal=dig->fSignal;
+//     c.fTracks[0]=dig->fTracks[0];
+//     c.fTracks[1]=dig->fTracks[1];
+//     c.fTracks[2]=dig->fTracks[2];
+       c.fPeakSignal=0;
+       FindCluster(i,j, c);
+       // center of gravity
+       c.fX /= c.fQ;
+       c.fX=fSegmentation->GetAnod(c.fX);
+       c.fY /= c.fQ;
+//
+//  apply correction to the coordinate along the anode wire
+//
+
+       
+    if (fCogCorr) {
+       Int_t ix,iy;
+       Float_t x=c.fX;   
+       Float_t y=c.fY;
+       fSegmentation->GetPadIxy(x, y, ix, iy);
+       fSegmentation->GetPadCxy(ix, iy, x, y);
+       Float_t YonPad=(c.fY-y)/fSegmentation->Dpy();
+       c.fY=y-fCogCorr->Eval(YonPad,0,0);
+    }
+//
+//      Analyse cluster and decluster if necessary
+//     
+       Decluster(&c);
+//
+//
+//
+//      reset Cluster object
+       for (int k=0;k<c.fMultiplicity;k++) {
+           c.fIndexMap[k]=0;
+           c.fOffsetMap[k]=0;
+       }
+       c.fMultiplicity=0;
+    } // end loop ndig    
+    delete fHitMap;
+}
+
+/*
+
+void AliMUONClusterFinder::
+CalibrateCOG()
+{
+    Float_t x[5];
+    Float_t y[5];
+    Int_t n, i;
+    TF1 func;
+    
+    if (fSegmentation) {
+       fSegmentation->GiveTestPoints(n, x, y);
+       for (i=0; i<n; i++) {
+           Float_t xtest=x[i];
+           Float_t ytest=y[i];     
+           SinoidalFit(xtest, ytest, func);
+       }
+       fCogCorr = new TF1(func);
+    }
+}
+*/
+/*
+
+void AliMUONClusterFinder::
+SinoidalFit(Float_t x, Float_t y, TF1 &func)
+{
+//
+    static Int_t count=0;
+    char canvasname[3];
+    count++;
+    sprintf(canvasname,"c%d",count);
+
+// MANU : without const, error on HP
+    const Int_t ns=101;
+    Float_t xg[ns], yg[ns], xrg[ns], yrg[ns];
+    Float_t xsig[ns], ysig[ns];
+   
+    AliMUONsegmentation *segmentation=fSegmentation;
+
+    Int_t ix,iy;
+    segmentation->GetPadIxy(x,y,ix,iy);   
+    segmentation->GetPadCxy(ix,iy,x,y);   
+    Int_t isec=segmentation->Sector(ix,iy);
+// Pad Limits    
+    Float_t xmin = x-segmentation->GetRealDpx(isec)/2;
+    Float_t ymin = y-segmentation->Dpy()/2;
+//             
+//      Integration Limits
+    Float_t dxI=fResponse->Nsigma()*fResponse->ChwX();
+    Float_t dyI=fResponse->Nsigma()*fResponse->ChwY();
+
+//
+//  Scanning
+//
+    Int_t i;
+    Float_t qp;
+//
+//  y-position
+    Float_t yscan=ymin;
+    Float_t dy=segmentation->Dpy()/(ns-1);
+
+    for (i=0; i<ns; i++) {
+//
+//      Pad Loop
+//      
+       Float_t sum=0;
+       Float_t qcheck=0;
+       segmentation->SigGenInit(x, yscan, 0);
+       
+       for (segmentation->FirstPad(x, yscan, dxI, dyI); 
+            segmentation->MorePads(); 
+            segmentation->NextPad()) 
+       {
+           qp=fResponse->IntXY(segmentation);
+           qp=TMath::Abs(qp);
+//
+//
+           if (qp > 1.e-4) {
+               qcheck+=qp;
+               Int_t ixs=segmentation->Ix();
+               Int_t iys=segmentation->Iy();
+               Float_t xs,ys;
+               segmentation->GetPadCxy(ixs,iys,xs,ys);
+               sum+=qp*ys;
+           }
+       } // Pad loop
+       Float_t ycog=sum/qcheck;
+       yg[i]=(yscan-y)/segmentation->Dpy();
+       yrg[i]=(ycog-y)/segmentation->Dpy();
+       ysig[i]=ycog-yscan;
+       yscan+=dy;
+    } // scan loop
+//
+//  x-position
+    Float_t xscan=xmin;
+    Float_t dx=segmentation->GetRealDpx(isec)/(ns-1);
+
+    for (i=0; i<ns; i++) {
+//
+//      Pad Loop
+//      
+       Float_t sum=0;
+       Float_t qcheck=0;
+       segmentation->SigGenInit(xscan, y, 0);
+       
+       for (segmentation->FirstPad(xscan, y, dxI, dyI); 
+            segmentation->MorePads(); 
+            segmentation->NextPad()) 
+       {
+           qp=fResponse->IntXY(segmentation);
+           qp=TMath::Abs(qp);
+//
+//
+           if (qp > 1.e-2) {
+               qcheck+=qp;
+               Int_t ixs=segmentation->Ix();
+               Int_t iys=segmentation->Iy();
+               Float_t xs,ys;
+               segmentation->GetPadCxy(ixs,iys,xs,ys);
+               sum+=qp*xs;
+           }
+       } // Pad loop
+       Float_t xcog=sum/qcheck;
+       xcog=segmentation->GetAnod(xcog);
+       
+       xg[i]=(xscan-x)/segmentation->GetRealDpx(isec);
+       xrg[i]=(xcog-x)/segmentation->GetRealDpx(isec);
+       xsig[i]=xcog-xscan;
+       xscan+=dx;
+    }
+
+   TCanvas *c1=new TCanvas(canvasname,canvasname,400,10,600,700);
+   TPad* pad11 = new TPad("pad11"," ",0.01,0.51,0.49,0.99);
+   TPad* pad12 = new TPad("pad12"," ",0.51,0.51,0.99,0.99);
+   TPad* pad13 = new TPad("pad13"," ",0.01,0.01,0.49,0.49);
+   TPad* pad14 = new TPad("pad14"," ",0.51,0.01,0.99,0.49);
+   pad11->SetFillColor(11);
+   pad12->SetFillColor(11);
+   pad13->SetFillColor(11);
+   pad14->SetFillColor(11);
+   pad11->Draw();
+   pad12->Draw();
+   pad13->Draw();
+   pad14->Draw();
+   TGraph *graphx = new TGraph(ns,xg ,xsig);
+   TGraph *graphxr= new TGraph(ns,xrg,xsig);   
+   TGraph *graphy = new TGraph(ns,yg ,ysig);
+   TGraph *graphyr= new TGraph(ns,yrg,ysig);
+//
+// Creates a Root function based on function sinoid above
+// and perform the fit
+//
+   Double_t sinoid(Double_t *x, Double_t *par);
+   TF1 *sinoidf = new TF1("sinoidf",sinoid,0.5,0.5,5);
+   graphyr->Fit("sinoidf","V");
+   sinoidf->Copy(func);
+   func.Eval(0,0,0);
+//
+   pad11->cd();
+   graphx->SetFillColor(42);
+   graphx->SetMarkerColor(4);
+   graphx->SetMarkerStyle(21);
+   graphx->Draw("AC");
+   graphx->GetHistogram()->SetXTitle("x on pad");
+   graphx->GetHistogram()->SetYTitle("xcog-x");   
+
+
+   pad12->cd();
+   graphxr->SetFillColor(42);
+   graphxr->SetMarkerColor(4);
+   graphxr->SetMarkerStyle(21);
+   graphxr->Draw("AP");
+   graphxr->GetHistogram()->SetXTitle("xcog on pad");
+   graphxr->GetHistogram()->SetYTitle("xcog-x");   
+
+
+   pad13->cd();
+   graphy->SetFillColor(42);
+   graphy->SetMarkerColor(4);
+   graphy->SetMarkerStyle(21);
+   graphy->Draw("AF");
+   graphy->GetHistogram()->SetXTitle("y on pad");
+   graphy->GetHistogram()->SetYTitle("ycog-y");   
+
+
+
+   pad14->cd();
+   graphyr->SetFillColor(42);
+   graphyr->SetMarkerColor(4);
+   graphyr->SetMarkerStyle(21);
+   graphyr->Draw("AF");
+   graphyr->GetHistogram()->SetXTitle("ycog on pad");
+   graphyr->GetHistogram()->SetYTitle("ycog-y");   
+
+   c1->Update();
+   
+}
+*/
+/*
+Double_t sinoid(Double_t *x, Double_t *par)
+{
+    Double_t arg = -2*TMath::Pi()*x[0];
+    Double_t fitval= par[0]*TMath::Sin(arg)+
+       par[1]*TMath::Sin(2*arg)+
+       par[2]*TMath::Sin(3*arg)+
+       par[3]*TMath::Sin(4*arg)+
+       par[4]*TMath::Sin(5*arg);
+    return fitval;
+ }
+*/
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONClusterFinderv0.h b/MUON/AliMUONClusterFinderv0.h
new file mode 100644 (file)
index 0000000..6cdf610
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef AliMUONClusterFinderv0_H
+#define AliMUONClusterFinderv0_H
+////////////////////////////////////////////////
+//  MUON Cluster Finder Class                 //
+////////////////////////////////////////////////
+#include "AliMUONClusterFinder.h"
+//#include "TF1.h"
+
+class AliMUONClusterFinderv0 :
+public AliMUONClusterFinder {
+//public:
+//    TClonesArray*           fDigits;
+//    Int_t                   fNdigits;
+//protected:
+//    AliMUONsegmentation*    fSegmentation;
+//    AliMUONresponse*        fResponse;
+//    TClonesArray*           fRawClusters;
+//    Int_t                   fChamber;
+//    Int_t                   fNRawClusters;
+//    AliMUONHitMapA1*        fHitMap;
+//    TF1*                   fCogCorr;
+    
+ public:
+    AliMUONClusterFinderv0
+       (AliMUONsegmentation *segmentation,
+        AliMUONresponse *response, TClonesArray *digits, Int_t chamber);
+    AliMUONClusterFinderv0();
+    ~AliMUONClusterFinderv0(){delete fRawClusters;}
+//    virtual void SetSegmentation(
+//     AliMUONsegmentation *segmentation){
+//     fSegmentation=segmentation;
+//   }
+//    virtual void SetResponse(AliMUONresponse *response) {
+//     fResponse=response;
+//   }
+
+//    virtual void SetDigits(TClonesArray *MUONdigits) {
+//     fDigits=MUONdigits;
+//     fNdigits = fDigits->GetEntriesFast();
+//   }
+    
+//    virtual void SetChamber(Int_t ich){
+//     fChamber=ich;
+//   }
+    
+//    virtual void AddRawCluster(const AliMUONRawCluster);
+    // Search for raw clusters
+    virtual void FindRawClusters();
+//    virtual void  FindCluster(Int_t i, Int_t j, AliMUONRawCluster &c);
+    // Specific methods
+    virtual void SetOffset(AliMUONRawCluster *cluster);
+    virtual Int_t PeakOffsetAndCoordinates(Int_t DigitIndex, Float_t *X, Float_t *Y);
+    // Decluster
+    virtual void Decluster(AliMUONRawCluster *cluster);
+    // Self Calibration of COG 
+//    virtual void CalibrateCOG();
+//    virtual void SinoidalFit(Float_t x, Float_t y, TF1 &func);
+    //
+//    virtual void CorrectCOG(){;}
+    
+    //
+    virtual Bool_t Centered(AliMUONRawCluster *cluster);
+    virtual void   SplitByLocalMaxima(AliMUONRawCluster *cluster);
+//    virtual void   FillCluster(AliMUONRawCluster *cluster);
+    void AliMUONClusterFinderv0::DumpCluster(class AliMUONRawCluster *);
+    
+    
+    TClonesArray* RawClusters(){return fRawClusters;}
+    ClassDef(AliMUONClusterFinderv0,1) //Class for clustering and reconstruction of space points
+};
+#endif
+
+
+
+
+
+
+
index 1cbc196..968ea4d 100644 (file)
@@ -18,7 +18,19 @@ const Float_t zend = 511.+0.15-2*0.001; // z-out position of first chamber
 //
 
 const Float_t adc_satm  = 1024; // dynamic range (10 bits)
-const Float_t zero_supm = 6.; // zero suppression
+const Int_t zero_supm = 6; // zero suppression
 const Float_t sig_noise = 500.; // electronics noise (no. of electrons)
+const Float_t kScale=1.;
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+//---------------------------------------------------------------------
+//   ALICE MUON  segmentation Parameters
+//--------------------------------------------------------------------
+//
+//
+const Int_t kMaxNeighbours = 24; // max number of neighbours
 
 #endif
+
diff --git a/MUON/AliMUONHitMap.cxx b/MUON/AliMUONHitMap.cxx
new file mode 100644 (file)
index 0000000..297cba6
--- /dev/null
@@ -0,0 +1,98 @@
+#include "AliMUONHitMap.h"
+ClassImp(AliMUONHitMap)
+ClassImp(AliMUONHitMapA1)
+
+AliMUONHitMapA1::AliMUONHitMapA1(AliMUONsegmentation *seg, TObjArray *dig)
+{
+    fSegmentation = seg;
+    fNpx  = fSegmentation->Npx();
+    fNpy  = fSegmentation->Npy();
+    fMaxIndex=2*(fNpx+1)*2*(fNpy+1)+2*fNpy;
+    
+    fHitMap = new Int_t[fMaxIndex];
+    fDigits =  dig;
+    fNdigits = fDigits->GetEntriesFast();
+    Clear();
+}
+
+
+AliMUONHitMapA1::~AliMUONHitMapA1()
+{
+//    if (fDigits) delete   fDigits;
+    if (fHitMap) delete[] fHitMap;
+}
+
+void AliMUONHitMapA1::Clear()
+{
+    memset(fHitMap,0,sizeof(int)*fMaxIndex);
+}
+
+Int_t AliMUONHitMapA1::CheckedIndex(Int_t ix, Int_t iy)
+{
+    Int_t index=2*fNpy*(ix+fNpx)+(iy+fNpy);
+    if (index > fMaxIndex) {
+       printf("\n \n \n Try to read/write outside array !!!! \n \n %d %d %d %d %d %d",ix,iy, fMaxIndex, index, fNpx, fNpy);
+       return  fMaxIndex-1;
+    } else {
+       return index;
+    }
+}
+
+       
+void  AliMUONHitMapA1::FillHits()
+{
+    Int_t ndigits = fDigits->GetEntriesFast();
+    //printf("\n Filling hits into HitMap\n");
+    //printf("FindRawClusters -- ndigits %d \n",ndigits);
+    if (!ndigits) return;
+    AliMUONdigit *dig;
+    for (Int_t ndig=0; ndig<fNdigits; ndig++) {
+       dig = (AliMUONdigit*)fDigits->UncheckedAt(ndig);
+       SetHit(dig->fPadX,dig->fPadY,ndig);
+    }
+}
+
+
+void  AliMUONHitMapA1::SetHit(Int_t ix, Int_t iy, Int_t idigit)
+{
+//    fHitMap[kMaxNpady*(ix+fNpx)+(iy+fNpy)]=idigit+1;
+    fHitMap[CheckedIndex(ix, iy)]=idigit+1;
+}
+
+void AliMUONHitMapA1::DeleteHit(Int_t ix, Int_t iy)
+{
+//    fHitMap[kMaxNpady*(ix+fNpx)+(iy+fNpy)]=0;
+    fHitMap[CheckedIndex(ix, iy)]=0;
+}
+
+void AliMUONHitMapA1::FlagHit(Int_t ix, Int_t iy)
+{
+    fHitMap[CheckedIndex(ix, iy)]=
+       -TMath::Abs(fHitMap[CheckedIndex(ix, iy)]);
+}
+
+Int_t AliMUONHitMapA1::GetHitIndex(Int_t ix, Int_t iy)
+{
+    return TMath::Abs(fHitMap[CheckedIndex(ix, iy)])-1;
+}
+
+TObject* AliMUONHitMapA1::GetHit(Int_t ix, Int_t iy)
+{
+    Int_t index=GetHitIndex(ix,iy);
+    // Force crash if index does not exist ! (Manu)
+    return (index <0) ? 0 : fDigits->UncheckedAt(GetHitIndex(ix,iy));
+}
+
+Flag_t AliMUONHitMapA1::TestHit(Int_t ix, Int_t iy)
+{
+    Int_t inf=fHitMap[CheckedIndex(ix, iy)];
+    if (inf < 0) {
+       return used;
+    } else if (inf == 0) {
+       return empty;
+    } else {
+       return unused;
+    }
+}
+
+
diff --git a/MUON/AliMUONHitMap.h b/MUON/AliMUONHitMap.h
new file mode 100644 (file)
index 0000000..49dff3c
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef AliMUONHitMap_H
+#define AliMUONHitMap_H
+
+#include "AliMUON.h"
+#include "TArrayI.h"
+typedef enum {empty, used, unused} Flag_t;
+const Int_t kMaxNpadx=1200, kMaxNpady=1200;
+
+class AliMUONHitMap :
+public TObject {
+ public:
+    virtual  void  FillHits()                                      =0;
+    virtual  void  Clear()                                         =0;
+    virtual  void  SetHit(Int_t ix, Int_t iy, Int_t idigit)        =0;
+    virtual  void  DeleteHit(Int_t ix, Int_t iy)                   =0;
+    virtual Int_t  GetHitIndex(Int_t ix, Int_t iy)                 =0;
+    virtual TObject * GetHit(Int_t ix, Int_t iy)                   =0;
+    virtual void   FlagHit(Int_t ix, Int_t iy)                     =0;    
+    virtual Flag_t TestHit(Int_t ix, Int_t iy)                     =0;
+    
+    ClassDef(AliMUONHitMap,1) //virtual base class for muon HitMap
+};
+
+class AliMUONHitMapA1 :
+public AliMUONHitMap 
+{
+ private:
+    AliMUONsegmentation *fSegmentation;
+    Int_t fNpx;
+    Int_t fNpy;
+    TObjArray *fDigits;
+    Int_t fNdigits;
+    Int_t *fHitMap;
+    Int_t fMaxIndex;
+    
+ public:
+    AliMUONHitMapA1(AliMUONsegmentation *seg, TObjArray *dig);
+    virtual ~AliMUONHitMapA1();
+    virtual  void  FillHits();
+    virtual  void  Clear();    
+    virtual  void  SetHit(Int_t ix, Int_t iy, Int_t idigit);
+    virtual  void  DeleteHit(Int_t ix, Int_t iy);
+    virtual Int_t  GetHitIndex(Int_t ix, Int_t iy);
+    virtual TObject*  GetHit(Int_t ix, Int_t);
+    virtual  void  FlagHit(Int_t ix, Int_t iy);    
+    virtual Flag_t TestHit(Int_t ix, Int_t iy);
+    private:
+    Int_t CheckedIndex(Int_t ix, Int_t iy);
+    ClassDef(AliMUONHitMapA1,1) // Implements HitMap as a 2-dim array
+};
+#endif 
+
+
diff --git a/MUON/AliMUONSegRes.h b/MUON/AliMUONSegRes.h
new file mode 100644 (file)
index 0000000..57b64ba
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef MUONSegRes_H
+#define MUONSegRes_H
+#include "TObject.h"
+#include "TClonesArray.h"
+#include "TF1.h"
+class AliMUONchamber;
+class AliMUONRecCluster;
+
+//----------------------------------------------
+//
+// Chamber segmentation virtual base class
+//
+class AliMUONsegmentation :
+public TObject {
+ public:
+    // Set Chamber Segmentation Parameters
+    //
+    // Pad size Dx*Dy 
+    virtual void    SetPADSIZ(Float_t p1, Float_t p2)  =0;
+    // Anod Pitch
+    virtual void    SetDAnod(Float_t D)                =0;
+    // Transform from pad (wire) to real coordinates and vice versa
+    //
+    // Anod wire coordinate closest to xhit
+    virtual Float_t GetAnod(Float_t xhit)              =0;
+    // Transform from pad to real coordinates
+    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy)=0;
+    // Transform from real to pad coordinates
+    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y )=0;
+    //
+    // Initialisation
+    virtual void Init(AliMUONchamber*)                 =0;
+    //
+    // Get member data
+    //
+    // Pad size in x
+    virtual Float_t Dpx()                              =0;
+    // Pad size in y 
+    virtual Float_t Dpy()                              =0;
+    // Pad size in x by Sector 
+    virtual Float_t Dpx(Int_t)                         =0;
+    // Pad size in y by Sector 
+    virtual Float_t Dpy(Int_t)                         =0;
+    // Max number of Pads in x
+    virtual Int_t    Npx()                             =0;
+    // max number of Pads in y
+    virtual Int_t    Npy()                             =0;
+    // set pad position
+    virtual void     SetPad(Int_t, Int_t)              =0;
+    // set hit position
+    virtual void     SetHit(Float_t, Float_t)          =0;
+    
+    //
+    // Iterate over pads
+    // Initialiser
+    virtual void  FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy) =0;
+    // Stepper
+    virtual void  NextPad()                            =0;
+    // Condition
+    virtual Int_t MorePads()                           =0;
+    //
+    // Distance between 1 pad and a position
+    virtual Float_t Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *dummy) =0;
+    // Number of pads read in parallel and offset to add to x 
+    // (specific to LYON, but mandatory for display)
+    virtual void GetNParallelAndOffset(Int_t iX, Int_t iY,
+                                      Int_t *Nparallel, Int_t *Offset) =0;
+    // Get next neighbours 
+    virtual void Neighbours
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])     =0;
+    // Provisory RecCluster coordinates reconstructor
+    virtual void FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits)    =0;
+    //
+    // Current pad cursor during disintegration
+    // x-coordinate
+    virtual Int_t  Ix()                                =0;
+    // y-coordinate
+    virtual Int_t  Iy()                                =0;
+    // current sector
+    virtual Int_t  ISector()                           =0;
+    // calculate sector from pad coordinates
+    virtual Int_t  Sector(Int_t ix, Int_t iy)          =0;
+    //
+    // Signal Generation Condition during Stepping
+    virtual Int_t SigGenCond(Float_t x, Float_t y, Float_t z) = 0;
+    // Initialise signal gneration at coord (x,y,z)
+    virtual void  SigGenInit(Float_t x, Float_t y, Float_t z) = 0;
+    // Current integration limits 
+    virtual void  IntegrationLimits
+       (Float_t& x1, Float_t& x2, Float_t& y1, Float_t& y2)  = 0;
+    // Test points for auto calibration
+    virtual void GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) = 0;
+    // Debug utilities
+    virtual void Draw()                                           = 0;
+    // Function for systematic corrections
+    virtual void SetCorrFunc(Int_t, TF1*)                         = 0;
+    virtual TF1* CorrFunc(Int_t)                                  = 0;
+           
+    ClassDef(AliMUONsegmentation,1) //Segmentation class for homogeneous segmentation
+};
+//----------------------------------------------
+//
+// Chamber response virtual base class
+//
+class AliMUONresponse :
+public TObject {
+ public:
+    //
+    // Configuration methods
+    //
+    // Number of sigmas over which cluster didintegration is performed
+    virtual void    SetSigmaIntegration(Float_t p1)           =0;
+    virtual Float_t SigmaIntegration()                        =0;
+    // charge slope in ADC/e
+    virtual void    SetChargeSlope(Float_t p1)                =0;
+    virtual Float_t ChargeSlope()                             =0;
+    // sigma of the charge spread function
+    virtual void    SetChargeSpread(Float_t p1, Float_t p2)   =0;
+    virtual Float_t ChargeSpreadX()                           =0;
+    virtual Float_t ChargeSpreadY()                           =0;
+    // Adc-count saturation value
+    virtual void    SetMaxAdc(Float_t p1)                     =0;
+    virtual Float_t MaxAdc()                                  =0;
+    // anode cathode Pitch
+    virtual void    SetPitch(Float_t)                         =0;
+    virtual Float_t Pitch()                                   =0;
+    //  
+    // Chamber response methods
+    // Pulse height from scored quantity (eloss)
+    virtual Float_t IntPH(Float_t eloss)                      =0;
+    // Charge disintegration 
+    virtual Float_t IntXY(AliMUONsegmentation *)              =0;
+
+    ClassDef(AliMUONresponse,1) // Implementation of Mathieson CPC response 
+};
+#endif
+
+
+
diff --git a/MUON/AliMUONSegResV0.cxx b/MUON/AliMUONSegResV0.cxx
new file mode 100644 (file)
index 0000000..c23c625
--- /dev/null
@@ -0,0 +1,280 @@
+#include "AliMUONSegResV0.h"
+#include "TMath.h"
+#include "TRandom.h"
+#include "TArc.h"
+#include "AliMUONchamber.h"
+ClassImp(AliMUONsegmentationV0)
+    void AliMUONsegmentationV0::Init(AliMUONchamber* Chamber)
+{
+    fNpx=(Int_t) (Chamber->ROuter()/fDpx+1);
+    fNpy=(Int_t) (Chamber->ROuter()/fDpy+1);
+    fRmin=Chamber->RInner();
+    fRmax=Chamber->ROuter();    
+    fCorr=0;
+    
+}
+
+
+Float_t AliMUONsegmentationV0::GetAnod(Float_t xhit)
+{
+    Float_t wire= (xhit>0)? Int_t(xhit/fWireD)+0.5:Int_t(xhit/fWireD)-0.5;
+    return fWireD*wire;
+}
+
+void AliMUONsegmentationV0::SetPADSIZ(Float_t p1, Float_t p2)
+{
+    fDpx=p1;
+    fDpy=p2;
+}
+void AliMUONsegmentationV0::
+    GetPadIxy(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
+{
+//  returns pad coordinates (ix,iy) for given real coordinates (x,y)
+//
+    ix = (x>0)? Int_t(x/fDpx)+1 : Int_t(x/fDpx)-1;
+    iy = (y>0)? Int_t(y/fDpy)+1 : Int_t(y/fDpy)-1;
+    if (iy >  fNpy) iy= fNpy;
+    if (iy < -fNpy) iy=-fNpy;
+    if (ix >  fNpx) ix= fNpx;
+    if (ix < -fNpx) ix=-fNpx;
+}
+void AliMUONsegmentationV0::
+GetPadCxy(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
+{
+//  returns real coordinates (x,y) for given pad coordinates (ix,iy)
+//
+    x = (ix>0) ? Float_t(ix*fDpx)-fDpx/2. : Float_t(ix*fDpx)+fDpx/2.;
+    y = (iy>0) ? Float_t(iy*fDpy)-fDpy/2. : Float_t(iy*fDpy)+fDpy/2.;
+}
+
+void AliMUONsegmentationV0::
+SetHit(Float_t xhit, Float_t yhit)
+{
+    //
+    // Find the wire position (center of charge distribution)
+//    Float_t x0a=GetAnod(xhit);
+    fxhit=xhit;
+    fyhit=yhit;
+}
+
+void AliMUONsegmentationV0::
+SetPad(Int_t ix, Int_t iy)
+{
+    GetPadCxy(ix,iy,fx,fy);
+}
+
+void AliMUONsegmentationV0::
+FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
+{
+    //
+    // Find the wire position (center of charge distribution)
+    Float_t x0a=GetAnod(xhit);
+    fxhit=x0a;
+    fyhit=yhit;
+    //
+    // and take fNsigma*sigma around this center
+    Float_t x01=x0a  - dx;
+    Float_t x02=x0a  + dx;
+    Float_t y01=yhit - dy;
+    Float_t y02=yhit + dy;
+    //
+    // find the pads over which the charge distributes
+    GetPadIxy(x01,y01,fixmin,fiymin);
+    GetPadIxy(x02,y02,fixmax,fiymax);    
+//    printf("\n %f %f %d %d \n",x02,y02,fixmax,fiymax);
+//    printf("\n FirstPad called %f %f \n", fDpx, fDpy);
+//    printf("\n Hit Position %f %f \n",xhit,yhit);
+//    printf("\n Integration limits: %i %i %i %i",fixmin,fixmax,fiymin,fiymax);
+//    printf("\n Integration limits: %f %f %f %f \n",x01,x02,y01,y02);
+    // 
+    // Set current pad to lower left corner
+    fix=fixmin;
+    fiy=fiymin;
+    GetPadCxy(fix,fiy,fx,fy);
+}
+
+void AliMUONsegmentationV0::NextPad()
+{
+  // 
+  // Step to next pad in integration region
+    if (fix != fixmax) {
+       if (fix==-1) fix++;
+       fix++;
+    } else if (fiy != fiymax) {
+       fix=fixmin;
+       if (fiy==-1) fiy++;
+       fiy++;
+    } else {
+       printf("\n Error: Stepping outside integration region\n ");
+    }
+    GetPadCxy(fix,fiy,fx,fy);
+}
+
+Int_t AliMUONsegmentationV0::MorePads()
+//
+// Are there more pads in the integration region
+{
+    if (fix == fixmax && fiy == fiymax) {
+       return 0;
+    } else {
+       return 1;
+       
+    }
+}
+
+void AliMUONsegmentationV0::SigGenInit(Float_t x,Float_t y,Float_t z)
+{
+//
+//  Initialises pad and wire position during stepping
+    fxt =x;
+    fyt =y;
+    GetPadIxy(x,y,fixt,fiyt);
+    fiwt= (x>0) ? Int_t(x/fWireD)+1 : Int_t(x/fWireD)-1 ;
+}
+
+Int_t AliMUONsegmentationV0::SigGenCond(Float_t x,Float_t y,Float_t z)
+{
+//
+//  Signal will be generated if particle crosses pad boundary or
+//  boundary between two wires. 
+    Int_t ixt, iyt;
+    GetPadIxy(x,y,ixt,iyt);
+    Int_t iwt=(x>0) ? Int_t(x/fWireD)+1 : Int_t(x/fWireD)-1;
+    if ((ixt != fixt) || (iyt !=fiyt) || (iwt != fiwt)) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+void AliMUONsegmentationV0::
+IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
+{
+//    x1=GetAnod(fxt)-fx-fDpx/2.;
+    x1=fxhit-fx-fDpx/2.;
+    x2=x1+fDpx;
+    y1=fyhit-fy-fDpy/2.;
+    y2=y1+fDpy;    
+}
+
+void AliMUONsegmentationV0::
+Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[7], Int_t Ylist[7])
+{
+  /*
+    *Nlist=4;Xlist[0]=Xlist[1]=iX;Xlist[2]=iX-1;Xlist[3]=iX+1;
+    Ylist[0]=iY-1;Ylist[1]=iY+1;Ylist[2]=Ylist[3]=iY;
+  */
+    *Nlist=8;
+    Xlist[0]=Xlist[1]=iX;
+    Xlist[2]=iX-1;
+    Xlist[3]=iX+1;
+    Ylist[0]=iY-1;
+    Ylist[1]=iY+1;
+    Ylist[2]=Ylist[3]=iY;
+
+   // Diagonal elements
+    Xlist[4]=iX+1;
+    Ylist[4]=iY+1;
+
+    Xlist[5]=iX-1;
+    Ylist[5]=iY-1;
+
+    Xlist[6]=iX-1;
+    Ylist[6]=iY+1;
+
+    Xlist[7]=iX+1;
+    Ylist[7]=iY-1;
+}
+
+Float_t AliMUONsegmentationV0::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y
+, Int_t *dummy)
+// Returns the square of the distance between 1 pad
+// labelled by its Channel numbers and a coordinate
+{
+  Float_t x,y;
+  GetPadCxy(iX,iY,x,y);
+  return (x-X)*(x-X) + (y-Y)*(y-Y);
+}
+
+
+void AliMUONsegmentationV0::
+FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits)
+    // Default : Centre of gravity method
+{
+    ;
+}
+
+void  AliMUONsegmentationV0::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y)
+{
+    n=1;
+    x[0]=(fRmax+fRmin)/2/TMath::Sqrt(2.);
+    y[0]=x[0];
+}
+
+void AliMUONsegmentationV0::Draw()
+{
+    TArc *circle;
+    Float_t scale=0.95/fRmax/2.;
+    
+
+    circle = new TArc(0.5,0.5,fRmax*scale,0.,360.);
+    circle->SetFillColor(2);
+    circle->Draw();
+
+    circle = new TArc(0.5,0.5,fRmin*scale,0.,360.);
+    circle->SetFillColor(1);
+    circle->Draw();
+}
+
+
+
+//___________________________________________
+ClassImp(AliMUONresponseV0)    
+Float_t AliMUONresponseV0::IntPH(Float_t eloss)
+{
+  // Get number of electrons and return charge
+     
+  Int_t nel;
+  nel= Int_t(eloss*1.e9/32.);
+  Float_t charge=0;
+  if (nel == 0) nel=1;
+  for (Int_t i=1;i<=nel;i++) {
+    charge -= fChargeSlope*TMath::Log(gRandom->Rndm());    
+  }
+  return charge;
+}
+// -------------------------------------------
+
+Float_t AliMUONresponseV0::IntXY(AliMUONsegmentation * segmentation)
+{
+
+    const Float_t invpitch = 1/fPitch;
+//
+//  Integration limits defined by segmentation model
+//  
+    Float_t xi1, xi2, yi1, yi2;
+    segmentation->IntegrationLimits(xi1,xi2,yi1,yi2);
+    xi1=xi1*invpitch;
+    xi2=xi2*invpitch;
+    yi1=yi1*invpitch;
+    yi2=yi2*invpitch;
+//
+// The Mathieson function 
+    Double_t ux1=fSqrtKx3*TMath::TanH(fKx2*xi1);
+    Double_t ux2=fSqrtKx3*TMath::TanH(fKx2*xi2);
+
+    Double_t uy1=fSqrtKy3*TMath::TanH(fKy2*yi1);
+    Double_t uy2=fSqrtKy3*TMath::TanH(fKy2*yi2);
+
+    
+    return Float_t(4.*fKx4*(TMath::ATan(ux2)-TMath::ATan(ux1))*
+                     fKy4*(TMath::ATan(uy2)-TMath::ATan(uy1)));
+}
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV0.h b/MUON/AliMUONSegResV0.h
new file mode 100644 (file)
index 0000000..7e714a9
--- /dev/null
@@ -0,0 +1,208 @@
+#ifndef MUONSegResV0_H
+#define MUONSegResV0_H
+
+#include "AliMUONSegRes.h"
+class AliMUONchamber;
+
+class AliMUONsegmentationV0 :
+public AliMUONsegmentation {
+ public:
+    AliMUONsegmentationV0(){}
+    virtual ~AliMUONsegmentationV0(){}
+    // Set Chamber Segmentation Parameters
+    //
+    // Pad size Dx*Dy 
+    virtual  void    SetPADSIZ(Float_t p1, Float_t p2);
+    // Anod Pitch
+    virtual  void    SetDAnod(Float_t D) {fWireD = D;};
+    // Transform from pad (wire) to real coordinates and vice versa
+    //
+    // Anod wire coordinate closest to xhit
+    virtual Float_t GetAnod(Float_t xhit);
+    // Transform from pad to real coordinates
+    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy);
+    // Transform from real to pad coordinates
+    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y );
+    //
+    // Initialisation
+    virtual void Init(AliMUONchamber*);
+    //
+    // Get member data
+    //
+    // Pad size in x
+    virtual Float_t Dpx(){return fDpx;}
+    // Pad size in y
+    virtual Float_t Dpy(){return fDpy;}
+    // Pad size in x by Sector
+    virtual Float_t Dpx(Int_t) {return fDpx;}
+    // Pad size in y by Secto
+    virtual Float_t Dpy(Int_t) {return fDpy;}
+    // Max number of Pads in x
+    virtual Int_t   Npx(){return fNpx;}
+    // max number of Pads in y
+    virtual Int_t   Npy(){return fNpy;}
+    // set pad position
+    virtual void     SetPad(Int_t, Int_t);
+    // set hit position
+    virtual void     SetHit(Float_t, Float_t);
+    //
+    // Iterate over pads
+    // Initialiser
+    virtual void  FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy);
+    // Stepper
+    virtual void  NextPad();
+    // Condition
+    virtual Int_t MorePads();
+    //
+    // Distance between 1 pad and a position
+    virtual Float_t Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *
+dummy);
+    // Number of pads read in parallel and offset to add to x 
+    // (specific to LYON, but mandatory for display)
+    virtual void GetNParallelAndOffset(Int_t iX, Int_t iY,
+        Int_t *Nparallel, Int_t *Offset) {*Nparallel=1;*Offset=0;}
+    // Get next neighbours 
+    virtual void Neighbours
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10]);
+    // Provisory RecCluster coordinates reconstructor
+    virtual void FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits);
+    //
+    // Current Pad during Integration
+    // x-coordinaten
+    virtual Int_t  Ix(){return fix;}
+    // y-coordinate
+    virtual Int_t  Iy(){return fiy;}
+    // current sector
+    virtual Int_t  ISector(){return 1;}
+    // calculate sector from pad coordinates
+    virtual Int_t  Sector(Int_t ix, Int_t iy) {return 1;}
+    //
+    // Signal Generation Condition during Stepping
+    virtual Int_t SigGenCond(Float_t x, Float_t y, Float_t z);
+    // Initialise signal gneration at coord (x,y,z)
+    virtual void  SigGenInit(Float_t x, Float_t y, Float_t z);
+    // Current integration limits
+    virtual void IntegrationLimits
+       (Float_t& x1, Float_t& x2, Float_t& y1, Float_t& y2);
+    // Test points for auto calibration
+    virtual void GiveTestPoints(Int_t &n, Float_t *x, Float_t *y);
+    // Debugging utilities
+    virtual void Draw();
+    // Function for systematic corrections
+    virtual void SetCorrFunc(Int_t dum, TF1* func) {fCorr=func;}
+    
+    virtual TF1* CorrFunc(Int_t) {return fCorr;} 
+
+    
+    ClassDef(AliMUONsegmentationV0,1)
+        protected:
+    //
+    // Implementation of the segmentation data
+    // Version 0 models rectangular pads with the same dimensions all
+    // over the cathode plane
+    //
+    //  geometry
+    //
+    Float_t    fDpx;           // x pad width per sector  
+    Float_t    fDpy;           // y pad base width
+    Int_t      fNpx;           // Number of pads in x
+    Int_t      fNpy;           // Number of pads in y
+    Float_t    fWireD;         // wire pitch
+    Float_t    fRmin;          // inner radius
+    Float_t    fRmax;          // outer radius
+    
+    
+    // Chamber region consideres during disintegration   
+    Int_t fixmin; // lower left  x
+    Int_t fixmax; // lower left  y
+    Int_t fiymin; // upper right x
+    Int_t fiymax; // upper right y 
+    //
+    // Current pad during integration (cursor for disintegration)
+    Int_t fix;  // pad coord. x 
+    Int_t fiy;  // pad coord. y 
+    Float_t fx; // x
+    Float_t fy; // y
+    //
+    // Current pad and wire during tracking (cursor at hit centre)
+    //
+    //
+    Float_t fxhit;
+    Float_t fyhit;
+    // Reference point to define signal generation condition
+    Int_t fixt;     // pad coord. x
+    Int_t fiyt;     // pad coord. y
+    Int_t fiwt;     // wire number
+    Float_t fxt;    // x
+    Float_t fyt;    // y
+    TF1*    fCorr;  // correction function
+    
+};
+
+class AliMUONresponseV0 : //Mathieson response
+public AliMUONresponse {
+ public:
+    AliMUONresponseV0(){}
+    virtual ~AliMUONresponseV0(){}
+    //
+    // Configuration methods
+    //
+    // Number of sigmas over which cluster didintegration is performed
+    virtual void    SetSigmaIntegration(Float_t p1) {fSigmaIntegration=p1;}
+    virtual Float_t SigmaIntegration() {return fSigmaIntegration;}    
+    // charge slope in ADC/e
+    virtual void    SetChargeSlope(Float_t p1) {fChargeSlope=p1;}
+    virtual Float_t ChargeSlope()      {return fChargeSlope;}
+    // sigma of the charge spread function
+    virtual void    SetChargeSpread(Float_t p1, Float_t p2)
+       {fChargeSpreadX=p1; fChargeSpreadY=p2;}
+    virtual Float_t ChargeSpreadX()    {return fChargeSpreadX;}    
+    virtual Float_t ChargeSpreadY()    {return fChargeSpreadY;}        
+    // Adc-count saturation value
+    virtual void    SetMaxAdc(Float_t p1) {fMaxAdc=p1;}
+    virtual Float_t MaxAdc()           {return fMaxAdc;}
+    // anode cathode Pitch
+    virtual Float_t Pitch()            {return fPitch;}
+    virtual void    SetPitch(Float_t p1) {fPitch=p1;};
+    // Mathieson parameters
+    virtual void    SetSqrtKx3(Float_t p1) {fSqrtKx3=p1;};
+    virtual void    SetKx2(Float_t p1) {fKx2=p1;};
+    virtual void    SetKx4(Float_t p1) {fKx4=p1;};
+    virtual void    SetSqrtKy3(Float_t p1) {fSqrtKy3=p1;};
+    virtual void    SetKy2(Float_t p1) {fKy2=p1;};
+    virtual void    SetKy4(Float_t p1) {fKy4=p1;};
+
+    //  
+    // Chamber response methods
+    // Pulse height from scored quantity (eloss)
+    virtual Float_t  IntPH(Float_t eloss);
+    // Charge disintegration
+    virtual Float_t  IntXY(AliMUONsegmentation * segmentation);
+
+    ClassDef(AliMUONresponseV0,1)
+ protected:
+    Float_t fChargeSlope;              // Slope of the charge distribution
+    Float_t fChargeSpreadX;            // Width of the charge distribution in x
+    Float_t fChargeSpreadY;            // Width of the charge distribution in y
+    Float_t fSigmaIntegration;         // Number of sigma's used for charge distribution
+    Float_t fMaxAdc;                   // Maximum ADC channel
+    Float_t fSqrtKx3;                  // Mathieson parameters for x
+    Float_t fKx2;
+    Float_t fKx4;
+    Float_t fSqrtKy3;                  // Mathieson parameters for y
+    Float_t fKy2;
+    Float_t fKy4;
+    Float_t fPitch;                    //anode-cathode pitch
+};
+#endif
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV01.cxx b/MUON/AliMUONSegResV01.cxx
new file mode 100644 (file)
index 0000000..5a60360
--- /dev/null
@@ -0,0 +1,473 @@
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 01   //
+/////////////////////////////////////////////////////
+
+#include <TTUBE.h>
+#include <TNode.h> 
+#include <TBox.h> 
+#include <TRandom.h> 
+
+#include "AliMUONSegResV01.h"
+#include "AliRun.h"
+#include "AliMC.h"
+#include "iostream.h"
+
+//___________________________________________
+ClassImp(AliMUONsegmentationV01)
+
+Float_t AliMUONsegmentationV01::Dpx(Int_t isec)
+{
+   return fDpxD[isec];
+}
+
+Float_t AliMUONsegmentationV01::Dpy(Int_t isec)
+{
+   return fDpy;
+}
+
+AliMUONsegmentationV01::AliMUONsegmentationV01() 
+{
+    fNsec=4;
+    fRSec.Set(fNsec);    
+    fNDiv.Set(fNsec);      
+    fDpxD.Set(fNsec);      
+    fRSec[0]=fRSec[1]=fRSec[2]=fRSec[3]=0;     
+    fNDiv[0]=fNDiv[1]=fNDiv[2]=fNDiv[3]=0;     
+    fDpxD[0]=fDpxD[1]=fDpxD[2]=fDpxD[3]=0;     
+    fCorr = new TObjArray(3);
+    (*fCorr)[0]=0;
+    (*fCorr)[1]=0;
+    (*fCorr)[2]=0;
+} 
+    
+void   AliMUONsegmentationV01::SetSegRadii(Float_t  r[4])
+{
+    for (Int_t i=0; i<4; i++) {
+       fRSec[i]=r[i];
+       printf("\n R %d %f \n",i,fRSec[i]);
+       
+    }
+}
+
+
+void AliMUONsegmentationV01::SetPadDivision(Int_t ndiv[4])
+{
+//
+// Defines the pad size perp. to the anode wire (y) for different sectors. 
+//
+    for (Int_t i=0; i<4; i++) {
+       fNDiv[i]=ndiv[i];
+       printf("\n Ndiv %d %d \n",i,fNDiv[i]);
+    }
+    ndiv[0]=ndiv[1];
+}
+
+
+void AliMUONsegmentationV01::Init(AliMUONchamber* Chamber)
+{
+//
+//  Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
+//  These arrays help in converting from real to pad co-ordinates and
+//  vice versa
+//
+    Int_t isec;
+    printf("\n Initialise segmentation v01 -- test !!!!!!!!!!!!!! \n");
+    fNpy=Int_t(fRSec[fNsec-1]/fDpy)+1;
+
+    fDpxD[fNsec-1]=fDpx;
+    if (fNsec > 1) {
+       for (Int_t i=fNsec-2; i>=0; i--){
+           fDpxD[i]=fDpxD[fNsec-1]/fNDiv[i];
+           printf("\n test ---dx %d %f \n",i,fDpxD[i]);
+       }
+    }
+//
+// fill the arrays defining the pad segmentation boundaries
+    Float_t ry;
+    Int_t   dnx;
+    Int_t   add;
+//
+//  loop over sections
+    for(isec=0; isec<fNsec; isec++) {
+//  
+//  loop over pads along the aode wires
+       for (Int_t iy=1; iy<=fNpy; iy++) {
+//
+           Float_t x=iy*fDpy-fDpy/2;
+           if (x > fRSec[isec]) {
+               fNpxS[isec][iy]=0;
+                fCx[isec][iy]=0;
+           } else {
+               ry=TMath::Sqrt(fRSec[isec]*fRSec[isec]-x*x);
+               if (isec > 1) {
+                   dnx= Int_t((ry-fCx[isec-1][iy])/fDpxD[isec]);
+                   if (isec < fNsec-1) {
+                       if (TMath::Odd((Long_t)dnx)) dnx++;             
+                   }
+                    fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
+                   fCx[isec][iy]=fCx[isec-1][iy]+dnx*fDpxD[isec];
+               } else if (isec == 1) {
+                   dnx= Int_t((ry-fCx[isec-1][iy])/fDpxD[isec]);
+                   fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
+                    add=4 - (fNpxS[isec][iy])%4;
+                    if (add < 4) fNpxS[isec][iy]+=add; 
+                   dnx=fNpxS[isec][iy]-fNpxS[isec-1][iy];
+                   fCx[isec][iy]=fCx[isec-1][iy]+dnx*fDpxD[isec];
+               } else {
+                   dnx=Int_t(ry/fDpxD[isec]);
+                    fNpxS[isec][iy]=dnx;
+                   fCx[isec][iy]=dnx*fDpxD[isec];
+               }
+           }
+       } // y-pad loop
+    } // sector loop
+    //   
+    // for debugging only 
+   
+    printf("segmentationv01 - I was here ! \n");
+}
+
+Int_t AliMUONsegmentationV01::Sector(Int_t ix, Int_t iy)
+{
+    Int_t absix=TMath::Abs(ix);
+    Int_t absiy=TMath::Abs(iy);
+    Int_t isec=0;
+    for (Int_t i=0; i<fNsec; i++) {
+       if (absix<=fNpxS[i][absiy]){
+           isec=i;
+           break;
+       }
+    }
+    return isec;
+}
+
+    void AliMUONsegmentationV01::
+    GetPadIxy(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
+{
+//  returns pad coordinates (ix,iy) for given real coordinates (x,y)
+//
+    iy = (y>0)? Int_t(y/fDpy)+1 : Int_t(y/fDpy)-1;
+    if (iy >  fNpy) iy= fNpy;
+    if (iy < -fNpy) iy=-fNpy;
+//
+//  Find sector isec
+    Int_t isec=-1;
+    Float_t absx=TMath::Abs(x);
+    Int_t absiy=TMath::Abs(iy);
+    for (Int_t i=0; i < fNsec; i++) {
+       if (absx <= fCx[i][absiy]) {
+           isec=i;
+           break;
+       }
+    }
+    if (isec>0) {
+       ix= Int_t((absx-fCx[isec-1][absiy])/fDpxD[isec])
+           +fNpxS[isec-1][absiy]+1;
+    } else if (isec == 0) {
+       ix= Int_t(absx/fDpxD[isec])+1;
+    } else {
+       ix=fNpxS[fNsec-1][absiy]+1;     
+    }
+//    printf("\n something %d %d \n",isec,absiy);
+    
+    ix = (x>0) ? ix:-ix;
+}
+
+void AliMUONsegmentationV01::
+GetPadCxy(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
+{
+//  returns real coordinates (x,y) for given pad coordinates (ix,iy)
+//
+    y = (iy>0) ? Float_t(iy*fDpy)-fDpy/2. : Float_t(iy*fDpy)+fDpy/2.;
+//
+//  Find sector isec
+    Int_t isec=AliMUONsegmentationV01::Sector(ix,iy);
+//
+    Int_t absix=TMath::Abs(ix);
+    Int_t absiy=TMath::Abs(iy);
+    if (isec) {
+       x=fCx[isec-1][absiy]+(absix-fNpxS[isec-1][absiy])*fDpxD[isec];
+       x=(ix>0) ?  x-fDpxD[isec]/2 : -x+fDpxD[isec]/2;
+    } else {
+       x=y=0;
+    }
+}
+
+void AliMUONsegmentationV01::
+SetPad(Int_t ix, Int_t iy)
+{
+    GetPadCxy(ix,iy,fx,fy);
+    fSector=Sector(ix,iy);
+}
+
+
+void AliMUONsegmentationV01::
+FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
+{
+    //
+    // Find the wire position (center of charge distribution)
+    Float_t x0a=GetAnod(xhit);
+    fxhit=x0a;
+    fyhit=yhit;
+    
+    //
+    // and take fNsigma*sigma around this center
+    Float_t x01=x0a  - dx;
+    Float_t x02=x0a  + dx;
+    Float_t y01=yhit - dy;
+    Float_t y02=yhit + dy;
+    //
+    // find the pads over which the charge distributes
+    GetPadIxy(x01,y01,fixmin,fiymin);
+    GetPadIxy(x02,y02,fixmax,fiymax);
+    fxmin=x01;
+    fxmax=x02;
+    fymin=y01;
+    fymax=y02;
+    
+    // 
+    // Set current pad to lower left corner
+    if (fixmax < fixmin) fixmax=fixmin;
+    if (fiymax < fiymin) fiymax=fiymin;    
+    fix=fixmin;
+    fiy=fiymin;
+    GetPadCxy(fix,fiy,fx,fy);
+}
+
+
+void AliMUONsegmentationV01::NextPad()
+{
+  // 
+  // Step to next pad in integration region
+    Float_t xc,yc;
+    Int_t   iyc;
+    
+//  step from left to right    
+    if (fx < fxmax && fx != 0) {
+       if (fix==-1) fix++;
+       fix++;
+//  step up 
+    } else if (fiy != fiymax) {
+       if (fiy==-1) fiy++;
+       fiy++;
+//      get y-position of next row (yc), xc not used here      
+       GetPadCxy(fix,fiy,xc,yc);
+//      get x-pad coordiante for 1 pad in row (fix)
+       GetPadIxy(fxmin,yc,fix,iyc);
+    } else {
+       printf("\n Error: Stepping outside integration region\n ");
+    }
+    GetPadCxy(fix,fiy,fx,fy);
+    fSector=Sector(fix,fiy);
+    if (MorePads() && 
+       (fSector ==-1 || fSector==0 || 
+        TMath::Abs(fx)<1.5 || TMath::Abs(fy)<1.5)) 
+       NextPad();
+    
+//    printf("\n this pad %f %f %d %d \n",fx,fy,fix,fiy);
+    
+}
+
+Int_t AliMUONsegmentationV01::MorePads()
+//
+// Are there more pads in the integration region
+{
+    if ((fx >= fxmax  && fiy >= fiymax) || fy==0) {
+       return 0;
+    } else {
+       return 1;
+    }
+}
+
+void AliMUONsegmentationV01::
+IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
+{
+    x1=fxhit-fx-Dpx(fSector)/2.;
+    x2=x1+Dpx(fSector);
+    y1=fyhit-fy-Dpy(fSector)/2.;
+    y2=y1+Dpy(fSector);    
+}
+
+void AliMUONsegmentationV01::
+Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
+{
+    const Float_t epsilon=fDpy/1000;
+    
+    Float_t x,y;
+    Int_t   ixx, iyy, isec1;
+//
+    Int_t   isec0=AliMUONsegmentationV01::Sector(iX,iY);
+    Int_t i=0;
+//    
+//  step right
+    Xlist[i]=iX+1;
+    Ylist[i++]=iY;
+//
+//  step left    
+    Xlist[i]=iX-1;
+    Ylist[i++]=iY;
+//
+//  step up 
+    AliMUONsegmentationV01::GetPadCxy(iX,iY,x,y);
+    AliMUONsegmentationV01::GetPadIxy(x+epsilon,y+fDpy,ixx,iyy);
+    Xlist[i]=ixx;
+    Ylist[i++]=iY+1;
+    isec1=AliMUONsegmentationV01::Sector(ixx,iyy);
+    if (isec1==isec0) {
+//
+//  no sector boundary crossing
+       Xlist[i]=ixx+1;
+       Ylist[i++]=iY+1;
+       
+       Xlist[i]=ixx-1;
+       Ylist[i++]=iY+1;
+    } else if (isec1 < isec0) {
+// finer segmentation
+       Xlist[i]=ixx+1;
+       Ylist[i++]=iY+1;
+       
+       Xlist[i]=ixx-1;
+       Ylist[i++]=iY+1;
+       
+       Xlist[i]=ixx-2;
+       Ylist[i++]=iY+1;
+    } else {
+// coarser segmenation 
+
+       if (TMath::Odd(iX-fNpxS[isec1-1][iY+1])) {
+           Xlist[i]=ixx-1;
+           Ylist[i++]=iY+1;
+       } else {
+           Xlist[i]=ixx+1;
+           Ylist[i++]=iY+1;
+       }
+    }
+//
+// step down 
+    AliMUONsegmentationV01::GetPadCxy(iX,iY,x,y);
+    AliMUONsegmentationV01::GetPadIxy(x+epsilon,y-fDpy,ixx,iyy);
+    Xlist[i]=ixx;
+    Ylist[i++]=iY-1;
+    isec1=AliMUONsegmentationV01::Sector(ixx,iyy);
+    if (isec1==isec0) {
+//
+//  no sector boundary crossing
+    Xlist[i]=ixx+1;
+    Ylist[i++]=iY-1;
+       
+    Xlist[i]=ixx-1;
+    Ylist[i++]=iY-1;
+    } else if (isec1 < isec0) {
+// finer segmentation
+       Xlist[i]=ixx+1;
+       Ylist[i++]=iY-1;
+       
+       Xlist[i]=ixx-1;
+       Ylist[i++]=iY-1;
+       
+       Xlist[i]=ixx-2;
+       Ylist[i++]=iY-1;
+    } else {
+// coarser segmentation        
+
+       if (TMath::Odd(iX-fNpxS[isec1-1][iY-1])) {
+           Xlist[i]=ixx-1;
+           Ylist[i++]=iY-1;
+       } else {
+           Xlist[i]=ixx+1;
+           Ylist[i++]=iY-1;
+       }
+
+    }
+    *Nlist=i;
+}
+
+//___________________________________________
+void AliMUONsegmentationV01::
+FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits)
+    // Default : Centre of gravity method
+{
+    Float_t x=0;
+    Float_t y=0;
+    Float_t q=0;
+    Float_t xToAdd;
+    Float_t yToAdd;
+    
+    if (gAlice->TreeD()->GetReadEvent() != Cluster->GetCathod()+1)
+       // next line warns if in the future cathod 1 is not event 2 !
+       printf("ClusterFillXY : not reading the right cathod !\n");
+    for(Int_t clusDigit=Cluster->FirstDigitIndex();
+       clusDigit!=Cluster->InvalidDigitIndex();
+       clusDigit=Cluster->NextDigitIndex()) {
+       AliMUONdigit* pDigit=(AliMUONdigit*)MUONdigits->UncheckedAt(clusDigit);
+       GetPadCxy(pDigit->fPadX,pDigit->fPadY,xToAdd,yToAdd);
+       x+= xToAdd*pDigit->fSignal;
+       y+= yToAdd*pDigit->fSignal;
+       q+= (Float_t) pDigit->fSignal;
+    }
+    Cluster->fX=x/q;
+    Cluster->fY=y/q;
+}
+
+void AliMUONsegmentationV01::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y)
+{
+    n=3;
+    x[0]=(fRSec[0]+fRSec[1])/2/TMath::Sqrt(2.);
+    y[0]=x[0];
+    x[1]=(fRSec[1]+fRSec[2])/2/TMath::Sqrt(2.);
+    y[1]=x[1];
+    x[2]=(fRSec[2]+fRSec[3])/2/TMath::Sqrt(2.);
+    y[2]=x[2];
+}
+
+void AliMUONsegmentationV01::Draw()
+{
+    TBox *box;
+    
+    Float_t dx=0.95/fCx[3][1]/2;
+    Float_t dy=0.95/(Float_t(Npy()))/2;
+    Float_t x0,y0,x1,y1;
+    Float_t xc=0.5;
+    Float_t yc=0.5;
+    
+    for (Int_t iy=1; iy<Npy(); iy++)
+    {
+       for (Int_t isec=0; isec<4; isec++) {
+           if (isec==0) {
+               x0=0;
+               x1=fCx[isec][iy]*dx;
+           } else {
+               x0=fCx[isec-1][iy]*dx;
+               x1=fCx[isec][iy]*dx;
+           }
+           y0=Float_t(iy-1)*dy;
+           y1=y0+dy;
+           box=new TBox(x0+xc,y0+yc,x1+xc,y1+yc);
+           box->SetFillColor(isec+1);
+           box->Draw();
+
+           box=new TBox(-x1+xc,y0+yc,-x0+xc,y1+yc);
+           box->SetFillColor(isec+1);
+           box->Draw();
+
+           box=new TBox(x0+xc,-y1+yc,x1+xc,-y0+yc);
+           box->SetFillColor(isec+1);
+           box->Draw();
+
+           box=new TBox(-x1+xc,-y1+yc,-x0+xc,-y0+yc);
+           box->SetFillColor(isec+1);
+           box->Draw();
+       }
+    }
+}
+void AliMUONsegmentationV01::SetCorrFunc(Int_t isec, TF1* func)
+{
+    (*fCorr)[isec]=func;
+    
+}
+
+TF1* AliMUONsegmentationV01::CorrFunc(Int_t isec)
+{ 
+    return (TF1*) (*fCorr)[isec];
+}
+
diff --git a/MUON/AliMUONSegResV01.h b/MUON/AliMUONSegResV01.h
new file mode 100644 (file)
index 0000000..c072d37
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef MUONSegResV01_H
+#define MUONSegResV01_H
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 01   //
+/////////////////////////////////////////////////////
+#include "AliMUON.h"
+#include "AliMUONSegResV0.h"
+#include "TArrayF.h"
+#include "TArrayI.h"
+#include "TObjArray.h"
+
+class AliMUONsegmentationV01 :
+public AliMUONsegmentationV0 {
+ public:
+    AliMUONsegmentationV01();
+    virtual ~AliMUONsegmentationV01(){}
+    //    
+    // Set Chamber Segmentation Parameters
+    // 
+    virtual  void    SetPadDivision(Int_t ndiv[4]);
+    // Radii
+    virtual  void    SetSegRadii(Float_t  r[4]);
+    //
+    // Transform from pad (wire) to real coordinates and vice versa
+    //
+    // Transform from pad to real coordinates
+    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy);
+    // Transform from real to pad coordinates
+    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y );    
+    //
+    // Initialisation
+    virtual void Init(AliMUONchamber*);
+    //
+    // Get member data
+    //
+    // Pad size in x by Sector
+    virtual Float_t Dpx(Int_t isec);
+    // Pad size in y by Sector
+    virtual Float_t Dpy(Int_t isec);
+    // Max number of Pads in x
+    virtual Int_t   Npx(){return fNpxS[fNsec-1][1]+1;}
+    //
+    virtual void     SetPad(Int_t,Int_t);
+    //
+    // Iterate over pads
+    // Initialiser
+    virtual void  FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy);
+    // Stepper
+    virtual void  NextPad();
+    // Condition
+    virtual Int_t MorePads();
+    // Get next neighbours 
+    virtual void Neighbours
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10]);
+    // Provisory RecCluster coordinates reconstructor
+    virtual void FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits);
+    //
+    // Current Pad during Integration
+    // current sector
+    virtual Int_t ISector()  {return fSector;}
+    // calculate sector from pad coordinates
+    virtual Int_t Sector(Int_t ix, Int_t iy);
+    //
+    // Integration
+    // Current integration limits
+     virtual void IntegrationLimits
+       (Float_t& x1, Float_t& x2, Float_t& y1, Float_t& y2);
+     // Test points for auto calibration
+    void GiveTestPoints(Int_t &n, Float_t *x, Float_t *y);
+    //
+    // Debugging utilities
+    virtual void Draw();
+    // Function for systematic corrections
+    virtual void SetCorrFunc(Int_t dum, TF1* func);
+    virtual TF1* CorrFunc(Int_t);
+    
+
+    ClassDef(AliMUONsegmentationV01,1)
+ protected:
+    //
+    // Implementation of the segmentation data
+    // Version 0 models rectangular pads with the same dimensions all
+    // over the cathode plane
+    //
+    //  geometry
+    //
+    Int_t      fNsec;           // Number of sectors
+    TArrayF    fRSec;           // sector outer radia
+    TArrayI    fNDiv;           // pad size division
+    TArrayF    fDpxD;           // y pad width per sector
+    Int_t      fNpxS[10][1000]; // Number of pads per sector in x
+    Float_t    fCx[10][1000];   // pad-sector contour x vs y  
+    // Chamber region consideres during disintegration
+    // (lower left and upper right corner)
+    //
+    Float_t fxmin;
+    Float_t fxmax;
+    Float_t fymin;
+    Float_t fymax;
+
+    //
+    // Current pad during integration (cursor for disintegration)
+    Int_t   fSector;
+    TObjArray *fCorr;
+};
+#endif
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV02.cxx b/MUON/AliMUONSegResV02.cxx
new file mode 100644 (file)
index 0000000..b0a3871
--- /dev/null
@@ -0,0 +1,110 @@
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 02   //
+/////////////////////////////////////////////////////
+
+#include <TTUBE.h>
+#include <TNode.h> 
+#include <TRandom.h> 
+#include "AliMUONSegResV02.h"
+#include "AliRun.h"
+#include "AliMC.h"
+#include "iostream.h"
+
+//___________________________________________
+ClassImp(AliMUONsegmentationV02)
+
+void AliMUONsegmentationV02::SetPADSIZ(Float_t p1, Float_t p2)
+{
+    fDpy=p1;
+    fDpx=p2;
+}
+
+Int_t AliMUONsegmentationV02::Npx()
+{return AliMUONsegmentationV01::Npy();}
+
+Int_t AliMUONsegmentationV02::Npy()
+{return AliMUONsegmentationV01::Npx();}
+
+
+Float_t AliMUONsegmentationV02::Dpx(Int_t isec)
+{return fDpy;}
+
+Float_t AliMUONsegmentationV02::Dpy(Int_t isec)
+{return fDpxD[isec];}
+
+Int_t AliMUONsegmentationV02::Sector(Int_t ix, Int_t iy)
+{return AliMUONsegmentationV01::Sector(iy, ix);}
+
+void AliMUONsegmentationV02::
+GetPadIxy(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
+{
+AliMUONsegmentationV01::GetPadIxy(y, x, iy, ix);
+// printf("\n x,y,ix,iy %f %f %d %d", x,y,ix,iy);
+}
+
+void AliMUONsegmentationV02::
+GetPadCxy(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
+{
+    AliMUONsegmentationV01::GetPadCxy(iy, ix, y, x);
+//    printf("\n ix,iy,x,y %d %d %f %f ", ix,iy,x,y);
+}
+void    AliMUONsegmentationV02::SetPad(Int_t ix,Int_t iy)
+{
+    GetPadCxy(ix,iy,fx,fy);
+    fSector=Sector(ix,iy);    
+}
+
+
+
+void AliMUONsegmentationV02::NextPad()
+{
+  // 
+  // Step to next pad in integration region
+    Float_t xc,yc;
+    Int_t   ixc;
+    
+//  step up    
+    if (fy < fymax && fy != 0) {
+       if (fiy==-1) fiy++;
+       fiy++;
+//  step right 
+    } else if (fix != fixmax) {
+       if (fix==-1) fix++;
+       fix++;
+//      get y-position of next row (yc), xc not used here      
+       GetPadCxy(fix,fiy,xc,yc);
+//      get x-pad coordiante for 1 pad in row (fix)
+       GetPadIxy(xc,fymin,ixc,fiy);
+    } else {
+       printf("\n Error: Stepping outside integration region\n ");
+    }
+    GetPadCxy(fix,fiy,fx,fy);
+    fSector=Sector(fix,fiy);
+    if (MorePads() && 
+       (fSector ==-1 || fSector==0 || 
+        TMath::Abs(fx)<1.5 || TMath::Abs(fy)<1.5)) 
+       NextPad();
+//    printf("\n this pad %f %f %d %d \n",fx,fy,fix,fiy);
+    
+}
+
+Int_t AliMUONsegmentationV02::MorePads()
+//
+// Are there more pads in the integration region
+{
+    if ((fy >= fymax  && fix >= fixmax) || fx==0) {
+       return 0;
+    } else {
+       return 1;
+    }
+}
+
+void AliMUONsegmentationV02::
+Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
+{
+    Int_t N;
+    AliMUONsegmentationV01::Neighbours(iY, iX, &N, Ylist, Xlist);
+    *Nlist=N;
+}
+
+
diff --git a/MUON/AliMUONSegResV02.h b/MUON/AliMUONSegResV02.h
new file mode 100644 (file)
index 0000000..f1e8386
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef MUONv02_H
+#define MUONv02_H
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 01   //
+/////////////////////////////////////////////////////
+#include "AliMUON.h"
+#include "TArrayF.h"
+#include "TArrayI.h"
+#include "AliMUONSegResV01.h"
+class AliMUONsegmentationV02 :
+public AliMUONsegmentationV01 {
+ public:
+    AliMUONsegmentationV02(){};
+    virtual ~AliMUONsegmentationV02(){}
+    //
+    virtual void SetPADSIZ(Float_t p1, Float_t p2);
+    //
+    // Get member data
+    // Pad size in x
+    virtual Float_t Dpx() {return fDpy;}
+    // Pad size in y
+    virtual Float_t Dpy() {return fDpx;}
+    // Pad size in x by Sector
+    virtual Float_t Dpx(Int_t isec);
+    // Pad size in y by Sector
+    virtual Float_t Dpy(Int_t isec);
+    // Max number of Pads in x
+    virtual Int_t   Npx();
+     // max number of Pads in y
+    virtual Int_t   Npy();
+    // calculate sector from pad coordinates
+    virtual Int_t   Sector(Int_t ix, Int_t iy);
+    //
+    // Transform from pad (wire) to real coordinates and vice versa
+    // Transform from pad to real coordinates
+    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y );
+    // Transform from pad to real coordinates
+    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy);
+    virtual void    SetPad(Int_t ix,Int_t iy);
+    // Stepper
+    virtual void    NextPad();
+    // Condition
+    virtual Int_t   MorePads();
+    
+    virtual void Neighbours
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10]);
+    // Get next neighbours 
+    ClassDef(AliMUONsegmentationV02,1) //Muon chamber segmentation version 02
+       };
+#endif
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV04.cxx b/MUON/AliMUONSegResV04.cxx
new file mode 100644 (file)
index 0000000..06c372a
--- /dev/null
@@ -0,0 +1,137 @@
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 04   //
+/////////////////////////////////////////////////////
+
+#include <TTUBE.h>
+#include <TNode.h> 
+#include <TRandom.h> 
+
+#include "AliMUONSegResV04.h"
+#include "AliRun.h"
+#include "AliMC.h"
+#include "iostream.h"
+
+//___________________________________________
+ClassImp(AliMUONsegmentationV04)
+
+
+void AliMUONsegmentationV04::Init(AliMUONchamber* Chamber)
+{
+    printf("\n Initialise segmentation v04 \n");
+//
+//  Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
+//  These arrays help in converting from real to pad co-ordinates and
+//  vice versa
+//
+//
+//  PCB module size in cm
+    const Float_t dxPCB=40, dyPCB=40;
+//  PCB distribution (7 rows with 1+3 segmentation regions)
+    const Int_t kpcb[7][4] = {{1, 2, 2, 2}, 
+                             {0, 3, 2, 2}, 
+                             {0, 2, 2, 2}, 
+                             {0, 0, 3, 3}, 
+                             {0, 0, 2, 3}, 
+                             {0, 0, 0, 4}, 
+                             {0, 0, 0, 3}};
+    
+    
+//
+//                             3 3 3 | 3 3 3
+//                           3 3 3 3 | 3 3 3 3
+//                         3 3 3 2 2 | 2 2 3 3 3
+//                       3 3 3 2 2 2 | 2 2 2 3 3 3
+//                       3 3 2 2 1 1 | 1 1 2 2 3 3      
+//                     3 3 2 2 1 1 1 | 1 1 1 2 2 3 3
+//                     3 3 2 2 1 1 0 | 0 1 1 2 2 3 3
+//                    ------------------------------
+//                     3 3 2 2 1 1 0 | 0 1 1 2 2 3 3
+//                     3 3 2 2 1 1 1 | 1 1 1 2 2 3 3
+//                       3 3 2 2 1 1 | 1 1 2 2 3 3      
+//                       3 3 3 2 2 2 | 2 2 2 3 3 3                      
+//                         3 3 3 2 2 | 2 2 3 3 3
+//                           3 3 3 3 | 3 3 3 3
+//                             3 3 3 | 3 3 3
+//
+// number of pad rows per PCB
+//    
+    Int_t NpyPCB=Int_t(dyPCB/fDpy);
+//
+// maximum number of pad rows    
+    fNpy=7*NpyPCB;
+//
+//  Calculate padsize along x
+    fDpxD[fNsec-1]=fDpx;
+    if (fNsec > 1) {
+       for (Int_t i=fNsec-2; i>=0; i--){
+           fDpxD[i]=fDpxD[fNsec-1]/fNDiv[i];
+           printf("\n test ---dx %d %f \n",i,fDpxD[i]);
+       }
+    }
+//
+// fill the arrays defining the pad segmentation boundaries
+//
+//  loop over pcb module rows
+    Int_t iy=0;
+    for (Int_t irow=0; irow<7; irow++) {
+//  
+//  loop over pads along the anode wires
+       for (Int_t i=0; i<=NpyPCB; i++) {
+//  iy counts the padrow
+           iy++;
+//  Loop over sectors (isec=0 is the dead space surounding the beam pipe)
+           for (Int_t isec=0; isec<4; isec++) {
+               if (isec==0) {
+                   fNpxS[0][iy]=kpcb[irow][0]*Int_t(dxPCB/fDpxD[0]);
+                   fCx[0][iy]=kpcb[irow][0]*dxPCB;
+               } else {
+                   fNpxS[isec][iy]=fNpxS[isec-1][iy]
+                       +kpcb[irow][isec]*Int_t(dxPCB/fDpxD[isec]);
+
+                   fCx[isec][iy]=fCx[isec-1][iy]
+                   +kpcb[irow][isec]*dxPCB;
+               }
+           } // sectors
+       } // pad raws in module
+    } // PCB rows
+/*
+    for (Int_t iy=1; iy< fNpy; iy++) {
+           printf("\nBoundary %d %f %d %f %d %f %d %f",
+                  fNpxS[0][iy], fCx[0][iy],
+                  fNpxS[1][iy], fCx[1][iy],
+                  fNpxS[2][iy], fCx[2][iy],
+                  fNpxS[3][iy], fCx[3][iy]);
+           
+    }
+*/
+}
+
+void AliMUONsegmentationV04::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y)
+{
+    n=3;
+    x[0]=(fCx[1][1]+fCx[0][1])/2/TMath::Sqrt(2.);
+    y[0]=x[0];
+    x[1]=(fCx[2][1]+fCx[1][1])/2/TMath::Sqrt(2.);
+    y[1]=x[1];
+    x[2]=(fCx[3][1]+fCx[2][1])/2/TMath::Sqrt(2.);
+    y[2]=x[2];
+    printf("\n 1%f %f", x[0], y[0]);
+    printf("\n 2%f %f", x[1], y[1]);
+    printf("\n 3%f %f\n ", x[2], y[2]);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV04.h b/MUON/AliMUONSegResV04.h
new file mode 100644 (file)
index 0000000..4a24fcc
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef MUONSegResV04_H
+#define MUONSegResV04_H
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 01   //
+/////////////////////////////////////////////////////
+#include "AliMUON.h"
+#include "AliMUONSegResV01.h"
+#include "TArrayF.h"
+#include "TArrayI.h"
+class AliMUONsegmentationV04 :
+public AliMUONsegmentationV01 {
+ public:
+    AliMUONsegmentationV04(){}
+    virtual ~AliMUONsegmentationV04(){}
+    // Initialisation
+    virtual void Init(AliMUONchamber*);
+    // Test points for auto calibration
+    void GiveTestPoints(Int_t &n, Float_t *x, Float_t *y);
+    ClassDef(AliMUONsegmentationV04,1)
+};
+       
+
+#endif
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV05.cxx b/MUON/AliMUONSegResV05.cxx
new file mode 100644 (file)
index 0000000..e4815f8
--- /dev/null
@@ -0,0 +1,135 @@
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 04   //
+/////////////////////////////////////////////////////
+
+#include <TTUBE.h>
+#include <TNode.h> 
+#include <TRandom.h> 
+
+#include "AliMUONSegResV05.h"
+#include "AliRun.h"
+#include "AliMC.h"
+#include "iostream.h"
+
+//___________________________________________
+ClassImp(AliMUONsegmentationV05)
+
+
+void AliMUONsegmentationV05::Init(AliMUONchamber* Chamber)
+{
+    printf("\n Initialise segmentation v05 \n");
+//
+//  Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
+//  These arrays help in converting from real to pad co-ordinates and
+//  vice versa
+//
+//
+//  PCB module size in cm
+    const Float_t dxPCB=40, dyPCB=40;
+//  PCB distribution (7 rows with 1+3 segmentation regions)
+    const Int_t kpcb[7][4] = {{1, 2, 2, 2}, 
+                             {0, 3, 2, 2}, 
+                             {0, 2, 2, 2}, 
+                             {0, 0, 3, 3}, 
+                             {0, 0, 2, 3}, 
+                             {0, 0, 0, 4}, 
+                             {0, 0, 0, 3}};
+    
+    
+//
+//                             3 3 3 | 3 3 3
+//                           3 3 3 3 | 3 3 3 3
+//                         3 3 3 2 2 | 2 2 3 3 3
+//                       3 3 3 2 2 2 | 2 2 2 3 3 3
+//                       3 3 2 2 1 1 | 1 1 2 2 3 3      
+//                     3 3 2 2 1 1 1 | 1 1 1 2 2 3 3
+//                     3 3 2 2 1 1 0 | 0 1 1 2 2 3 3
+//                    ------------------------------
+//                     3 3 2 2 1 1 0 | 0 1 1 2 2 3 3
+//                     3 3 2 2 1 1 1 | 1 1 1 2 2 3 3
+//                       3 3 2 2 1 1 | 1 1 2 2 3 3      
+//                       3 3 3 2 2 2 | 2 2 2 3 3 3                      
+//                         3 3 3 2 2 | 2 2 3 3 3
+//                           3 3 3 3 | 3 3 3 3
+//                             3 3 3 | 3 3 3
+//
+// number of pad rows per PCB
+//    
+    Int_t NpyPCB=Int_t(dyPCB/fDpy);
+//
+// maximum number of pad rows    
+    fNpy=7*NpyPCB;
+//
+//  Calculate padsize along x
+    fDpxD[fNsec-1]=fDpx;
+    if (fNsec > 1) {
+       for (Int_t i=fNsec-2; i>=0; i--){
+           fDpxD[i]=fDpxD[fNsec-1]/fNDiv[i];
+           printf("\n test ---dx %d %f \n",i,fDpxD[i]);
+       }
+    }
+//
+// fill the arrays defining the pad segmentation boundaries
+//
+//  loop over pcb module rows
+    Int_t iy=0;
+    for (Int_t irow=0; irow<7; irow++) {
+//  
+//  loop over pads along the anode wires
+       for (Int_t i=0; i<=NpyPCB; i++) {
+//  iy counts the padrow
+           iy++;
+//  Loop over sectors (isec=0 is the dead space surounding the beam pipe)
+           for (Int_t isec=0; isec<4; isec++) {
+               if (isec==0) {
+                   fNpxS[0][iy]=kpcb[irow][0]*Int_t(dxPCB/fDpxD[0]);
+                   fCx[0][iy]=kpcb[irow][0]*dxPCB;
+               } else {
+                   fNpxS[isec][iy]=fNpxS[isec-1][iy]
+                       +kpcb[irow][isec]*Int_t(dxPCB/fDpxD[isec]);
+
+                   fCx[isec][iy]=fCx[isec-1][iy]
+                   +kpcb[irow][isec]*dxPCB;
+               }
+           } // sectors
+       } // pad raws in module
+    } // PCB rows
+/*
+    for (Int_t iy=1; iy< fNpy; iy++) {
+           printf("\nBoundary %d %f %d %f %d %f %d %f",
+                  fNpxS[0][iy], fCx[0][iy],
+                  fNpxS[1][iy], fCx[1][iy],
+                  fNpxS[2][iy], fCx[2][iy],
+                  fNpxS[3][iy], fCx[3][iy]);
+           
+    }
+*/
+}
+
+void AliMUONsegmentationV05::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y)
+{
+    n=1;
+    x[0]=(fCx[1][1]+fCx[0][1])/2/TMath::Sqrt(2.);
+    y[0]=x[0];
+//    x[1]=(fCx[2][1]+fCx[1][1])/2;
+//    y[1]=x[1];
+//    x[2]=(fCx[3][1]+fCx[2][1])/2;
+//    y[2]=x[2];
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV05.h b/MUON/AliMUONSegResV05.h
new file mode 100644 (file)
index 0000000..01c1751
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef MUONSegResV05_H
+#define MUONSegResV05_H
+/////////////////////////////////////////////////////
+//  Segmentation and Response classes version 01   //
+/////////////////////////////////////////////////////
+#include "AliMUON.h"
+#include "AliMUONSegResV02.h"
+#include "TArrayF.h"
+#include "TArrayI.h"
+class AliMUONsegmentationV05 :
+public AliMUONsegmentationV02 {
+ public:
+    AliMUONsegmentationV05(){}
+    virtual ~AliMUONsegmentationV05(){}
+    // Initialisation
+    virtual void Init(AliMUONchamber*);
+    // Test points for auto calibration
+    void GiveTestPoints(Int_t &n, Float_t *x, Float_t *y);
+    ClassDef(AliMUONsegmentationV05,1)
+};
+#endif
+
+
+
+
+
+
diff --git a/MUON/AliMUONSegResV1.cxx b/MUON/AliMUONSegResV1.cxx
new file mode 100644 (file)
index 0000000..78e6447
--- /dev/null
@@ -0,0 +1,497 @@
+/////////////////////////////////////////////////////////
+//  Manager and hits classes for set:MUON version LYON //
+/////////////////////////////////////////////////////////
+
+#include <TTUBE.h>
+#include <TNode.h> 
+#include <TRandom.h> 
+
+//#include "AliMUONv0.h"
+#include "AliMUONchamber.h"
+#include "AliMUONSegResV1.h"
+#include "AliRun.h"
+#include "AliMC.h"
+#include "iostream.h"
+
+//___________________________________________
+ClassImp(AliMUONsegmentationV1)
+
+AliMUONsegmentationV1::AliMUONsegmentationV1()
+  // initizalize the class with default settings
+{
+fNzone=1;
+fDAnod=0.0;
+fDpx=0.0;
+fDpx=0.0; // forces crash if not initialized by user
+fNZoneCut[0]=0;
+fSensOffset=0;
+}
+
+
+void AliMUONsegmentationV1::Init(AliMUONchamber* Chamber)
+{
+  // valid only for T5/6
+  // beware : frMin is SENSITIVE radius by definition.
+  frSensMin2 = (Chamber->RInner())*(Chamber->RInner());
+  frSensMax2 = (Chamber->ROuter())*(Chamber->ROuter());
+  fNpx=(Int_t) (Chamber->ROuter()/fDpx) + 1;
+  fNpy=(Int_t) (Chamber->ROuter()/fDpy) + 1;
+  //    fNwire=3;
+  DefaultCut();
+  fCorr=0;
+}
+
+void AliMUONsegmentationV1::DefaultCut(void)
+{
+SetNzone(3);
+AddCut(0,5*6,18*8);
+AddCut(0,9*6,15*8);
+AddCut(0,11*6,12*8);
+AddCut(0,12*6,9*8);
+AddCut(0,13*6,6*8);
+AddCut(1,6*6,20*12);
+AddCut(1,12*6,18*12);
+AddCut(1,15*6,15*12);
+AddCut(1,18*6,12*12);
+AddCut(1,21*6,9*12);
+SetSensOffset(3.0);
+SetDAnod(0.325);
+}
+
+Int_t AliMUONsegmentationV1::GetiAnod(Float_t xhit)
+{
+Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1;
+return (xhit>0) ? kwire : -kwire ;
+}
+
+Float_t AliMUONsegmentationV1::GetAnod(Float_t xhit)
+{
+  Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1; // to be compatible ...
+    return (xhit>0) ? fDAnod*(kwire-0.5)+fSensOffset : -fDAnod*(kwire-0.5)-fSensOffset ;
+}
+
+// For chamber T5/6 p1 and p2 should be same for each zone
+void AliMUONsegmentationV1::SetPADSIZ(Float_t p1, Float_t p2)
+{
+  fDpx=p1;
+  fDpy=p2;
+}
+
+void AliMUONsegmentationV1::
+    GetPadIxy(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
+{
+//  returns pad coordinates (ix,iy) for given real coordinates (x,y)
+//
+    ix = (x>0)? Int_t((x-fSensOffset)/fDpx)+1 : Int_t((x+fSensOffset)/fDpx)-1;
+    iy = (y>0)? Int_t((y-fSensOffset)/fDpy)+1 : Int_t((y+fSensOffset)/fDpy)-1;
+}
+
+void AliMUONsegmentationV1::
+GetPadCxy(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
+{
+//  returns real coordinates (x,y) for given pad coordinates (ix,iy)
+//
+    x = (ix>0) ? (Float_t(ix)-0.5)*fDpx+fSensOffset : (Float_t(ix)+0.5)*fDpx-fSensOffset;
+    y = (iy>0) ? (Float_t(iy)-0.5)*fDpy+fSensOffset : (Float_t(iy)+0.5)*fDpy-fSensOffset;
+}
+
+void AliMUONsegmentationV1::AddCut(Int_t Zone, Int_t nX, Int_t nY)
+{// the pad nX,nY is last INSIDE zone Zone. First pad is labelled 1 and not 0
+if (Zone+1>=fNzone) // no cut for last Zone : it is the natural boundary of the chamber
+  printf("AliMUONsegmentationV1::AddCut ==> Zone %d not allowed !\n",Zone);
+fZoneX[Zone][fNZoneCut[Zone]] = nX;
+fZoneY[Zone][fNZoneCut[Zone]] = nY;
+fNZoneCut[Zone]++;
+}
+
+Int_t AliMUONsegmentationV1::GetZone(Float_t X, Float_t Y)
+{
+Int_t iX, iY;
+GetPadIxy(X,Y,iX,iY);
+return GetZone( iX , iY );
+}
+
+Int_t AliMUONsegmentationV1::GetZone(Int_t nX, Int_t nY)
+{// Beware : first pad begins at 1 !!
+Int_t aX =  TMath::Abs(nX);
+Int_t aY =  TMath::Abs(nY);
+Int_t zone=fNzone-1;
+for (Int_t iZone=fNzone-2;iZone>=0;iZone--) 
+  {
+  for (Int_t iCut=0;iCut<fNZoneCut[iZone];iCut++)
+    if ( aY<=fZoneY[iZone][iCut] && aX<=fZoneX[iZone][iCut] )
+      {
+      zone=iZone;
+      break;
+      } 
+  }
+return zone;
+}
+
+void AliMUONsegmentationV1::
+SetHit(Float_t xhit, Float_t yhit)
+{
+    //
+    // Find the wire position (center of charge distribution)
+//    Float_t x0a=GetAnod(xhit);
+    fxhit=xhit;
+    fyhit=yhit;
+}
+
+void AliMUONsegmentationV1::
+SetPad(Int_t ix, Int_t iy)
+{
+    GetPadCxy(ix,iy,fx,fy);
+}
+
+
+void AliMUONsegmentationV1::SetPadCoord(Int_t iX, Int_t iY)
+{    
+GetPadCxy(iX,iY,fx,fy);
+Float_t radius2;
+if ( ( (radius2=fx*fx+fy*fy) > frSensMax2 || radius2 < frSensMin2 ) 
+     && MorePads() )
+  NextPad();
+}
+
+void AliMUONsegmentationV1::FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
+{
+    //
+    // Find the wire position (center of charge distribution)
+    Float_t x0a=GetAnod(xhit);
+    fxhit=x0a;
+    fyhit=yhit;
+    
+    //
+    // and take fNsigma*sigma around this center
+    Float_t x01=x0a  - dx;
+    Float_t x02=x0a  + dx;
+    Float_t y01=yhit - dy;
+    Float_t y02=yhit + dy;
+
+    // Do not cross over frames...
+    if (x01 * x0a < 0) 
+      x01 = TMath::Sign(fSensOffset, x0a);
+    if (x02 * x0a < 0) 
+      x02 = TMath::Sign(fSensOffset, x0a);
+    if (y01 * yhit < 0) 
+      y01 = TMath::Sign(fSensOffset, yhit);
+    if (y02 * yhit < 0) 
+      y02 = TMath::Sign(fSensOffset, yhit);
+    //
+    // find the pads over which the charge distributes
+    GetPadIxy(x01,y01,fixmin,fiymin);
+    GetPadIxy(x02,y02,fixmax,fiymax);
+    // 
+    // Set current pad to lower left corner
+    fix=fixmin;
+    fiy=fiymin;
+    SetPadCoord(fix,fiy);
+}
+
+void AliMUONsegmentationV1::NextPad()
+{
+  // 
+  // Step to next pad in integration region
+    if (fix != fixmax) {
+       fix++;
+    } else if (fiy != fiymax) {
+       fix=fixmin;
+       fiy++;
+    } else 
+       printf("\n Error: Stepping outside integration region\n ");
+    SetPadCoord(fix,fiy);
+}
+
+Int_t AliMUONsegmentationV1::MorePads()
+//
+// Are there more pads in the integration region
+{
+    if (fix == fixmax && fiy == fiymax) {
+       return 0;
+    } else {
+       return 1;       
+    }
+}
+
+Int_t AliMUONsegmentationV1::IsParallel2(Int_t iX, Int_t iY)
+// test if the pad is read in parallel for zone 2
+// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
+// returns 1 or 2 if read in parallel, 
+// according to the actual number in the chain, 0 else
+//
+// chainage is        result is 
+// 1  2  3  1  2  3   1 1 1 2 2 2     y
+// 7  8  9 10 11 12   0 0 0 0 0 0     ^
+// 4  5  6  4  5  6   1 1 1 2 2 2     +->x
+//
+{
+if (iY%3==1) return 0;
+return (iX%6)/3+1;
+}
+
+Int_t AliMUONsegmentationV1::IsParallel3(Int_t iX, Int_t iY)
+// test if the pad is read in parallel for zone 3
+// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
+// returns 1,2 or 3 if read in parallel, 
+// according to the actual number in the chain, 0 else
+//
+// chainage is                 result is
+//16  2  3  1  2  3  1  2  3   0 1 1 1 2 2 2 3 3
+// 7  8  9 10 11 12 13 14 15   0 0 0 0 0 0 0 0 0
+// 4  5  6  4  5  6  4  5  6   1 1 1 2 2 2 3 3 3
+//
+{
+if (iY%3==1) return 0;
+return (iX%9)/3+1 - (iY%3==2 && iX%3==0);
+}
+
+Int_t AliMUONsegmentationV1::NParallel2(Int_t iX, Int_t iY)
+// returns the number of pads connected in parallel for zone 2
+// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
+//
+// result is
+// 2 2 2 2 2 2
+// 1 1 1 1 1 1
+// 2 2 2 2 2 2
+//
+{
+if (iY%3==1) return 1;
+return 2;
+}
+
+Int_t AliMUONsegmentationV1::NParallel3(Int_t iX, Int_t iY)
+// test if the pad is read in parallel for zone 3
+// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
+// returns 1,2 or 3 if read in parallel, 
+// according to the actual number in the chain, 0 else
+//
+// result is 
+// 1 3 3 2 3 3 2 3 3 
+// 1 1 1 1 1 1 1 1 1
+// 3 3 3 3 3 3 3 3 3
+//
+{
+if (iY%3==1) return 1;
+if (iY%3==2 && iX%9==0) return 1;
+return 3 - (iY%3==2 && iX%3==0);
+}
+
+
+Int_t AliMUONsegmentationV1::Ix(Int_t trueX, Int_t trueY)
+// returns the X number of pad which corresponds to the logical 
+// channel, expressed in x and y.
+{
+Int_t wix = TMath::Abs(trueX)-1;
+Int_t wiy = TMath::Abs(trueY)-1;
+Int_t zone = GetZone(trueX,trueY);
+Int_t par3;
+switch (zone) {
+ case 0: return trueX;
+ case 1:
+   if (IsParallel2(wix,wiy) == 2)
+     return (trueX>0)? trueX-3 : trueX+3 ;
+   return trueX;
+ case 2:
+   if ( (par3= IsParallel3(wix,wiy)) )
+     return (trueX>0) ? trueX-3*(par3-1) : trueX+3*(par3-1) ;
+   return trueX ;
+ default :
+   printf("Couille dans AliMUONsegmentationV1::ix\n");
+ }
+return -1;
+}
+
+Int_t AliMUONsegmentationV1::Ix()
+// returns the X number of pad which has to increment charge
+// due to parallel read-out
+{return Ix(fix,fiy);}
+
+Int_t AliMUONsegmentationV1::ISector()
+// This function is of no use for this kind of segmentation.
+{
+return GetZone(fix,fiy);
+}
+
+void AliMUONsegmentationV1::SigGenInit(Float_t x,Float_t y,Float_t z)
+{
+//
+//  Initialises pad and wire position during stepping
+    fxt =x;
+    fyt =y;
+    GetPadIxy(x,y,fixt,fiyt);
+    fiwt= GetiAnod(x);
+
+}
+
+Int_t AliMUONsegmentationV1::SigGenCond(Float_t x,Float_t y,Float_t z)
+{
+//
+//  Signal will be generated if particle crosses pad boundary or
+//  boundary between two wires. 
+    Int_t ixt;
+    Int_t iyt;
+    GetPadIxy(x,y,ixt,iyt);
+    Int_t iwt= GetiAnod(x);
+    
+    if ((ixt != fixt) || (iyt !=fiyt) || (iwt != fiwt)) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+void AliMUONsegmentationV1::
+IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
+{
+    x1=fxhit-fx-fDpx/2.;
+    x2=x1+fDpx;
+    y1=fyhit-fy-fDpy/2.;
+    y2=y1+fDpy;    
+}
+
+void AliMUONsegmentationV1::GetNParallelAndOffset(Int_t iX, Int_t iY,Int_t
+*Nparallel, Int_t* Offset)
+{
+Int_t wix = TMath::Abs(iX)-1;
+Int_t wiy = TMath::Abs(iY)-1;
+Int_t zone = GetZone(iX,iY);
+switch (zone) {
+ case 0: 
+    *Nparallel=1;
+    *Offset=0;
+    break;
+ case 1:
+    *Nparallel = NParallel2(wix,wiy);
+    (iX>0) ? *Offset =3 : *Offset = -3;
+    if (IsParallel2(wix,wiy)>1)
+      printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
+    break;
+ case 2:
+    *Nparallel = NParallel3(wix,wiy);
+    (iX>0) ? *Offset =3 : *Offset = -3;
+    if (IsParallel3(wix,wiy)>1)
+      printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
+    break;
+ }
+}
+
+
+Float_t AliMUONsegmentationV1::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *Offset)
+//
+// Computes the offset for which the physical pad has the minimum distance squared
+// (returned value) to the given coordinates
+{
+Int_t nPara,offset;
+GetNParallelAndOffset(iX,iY,&nPara,&offset);
+Float_t d2min=1E10;
+for (Int_t i=0;i<nPara; i++)
+  {
+  Float_t x,y;
+  GetPadCxy(iX+i*offset,iY,x,y);
+  Float_t d2=(x-X)*(x-X) + (y-Y)*(y-Y);
+  if ( d2min > d2)
+    {
+    d2min = d2;
+    *Offset = i*offset;
+    }
+  }
+return d2min; 
+}
+
+void AliMUONsegmentationV1::CleanNeighbours(Int_t* Nlist, Int_t *Xlist, 
+       Int_t *Ylist)
+// In the raw neighbours list, some pads do not exist 
+// and some others are read in parallel ...
+// So we prune non-existing neighbours from the list (event if this should be
+// at last not be a problem due to the clustering algorithm...)
+{
+Int_t nTot=0;
+for (Int_t nList=0;nList<*Nlist;nList++)
+  {
+  // prune if it does not exist
+  if ( Xlist[nList]==0 || Ylist[nList]==0 )
+    continue;
+  // compute true position
+  Xlist[nTot] = Ix(Xlist[nList],Ylist[nList]) ;
+  Ylist[nTot] = Ylist[nList] ;
+  // and prune if it does already exist
+  Int_t nTest;
+  for (nTest=0;nTest<nTot; nTest++)
+    {
+    if ( Xlist[nTest]==Xlist[nTot] && Ylist[nTest]==Ylist[nTot])
+      // we found it
+      break ;
+    }
+  if (nTest==nTot)
+    nTot++;
+  }
+*Nlist = nTot;
+}
+
+void AliMUONsegmentationV1::
+NeighboursNonDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[12], Int_t Ylist[12])
+// returns the X number of pad which has to increment charge
+// due to parallel read-out
+{
+Int_t nParallel, offset;
+GetNParallelAndOffset(iX,iY,&nParallel,&offset);
+//
+// now fill raw list of neighbours
+*Nlist=4*nParallel;
+Xlist[0]=Xlist[1]=iX;Xlist[2]=iX-1;Xlist[3]=iX+1;
+Ylist[0]=iY-1;Ylist[1]=iY+1;Ylist[2]=Ylist[3]=iY;
+if (nParallel>1) {
+  Xlist[4]=Xlist[5]=iX+offset;Xlist[6]=iX+offset-1;Xlist[7]=iX+offset+1;
+  Ylist[4]=iY-1;Ylist[5]=iY+1;Ylist[6]=Ylist[7]=iY;
+  if (nParallel>2) {
+    Xlist[8]=Xlist[9]=iX+2*offset;Xlist[10]=iX+2*offset-1;Xlist[11]=iX+2*offset+1;
+    Ylist[8]=iY-1;Ylist[9]=iY+1;Ylist[10]=Ylist[11]=iY;
+    }
+  }
+CleanNeighbours(Nlist,Xlist,Ylist);
+}
+
+void AliMUONsegmentationV1::
+NeighboursDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[24], Int_t Ylist[24])
+// returns the X number of pad which has to increment charge
+// due to parallel read-out
+{
+Int_t nParallel, offset;
+GetNParallelAndOffset(iX,iY,&nParallel,&offset);
+//
+// now fill raw list of neighbours
+*Nlist=0;
+for (Int_t i=0;i<nParallel;i++)
+  for (Int_t dx=-1;dx<2;dx++)
+    for (Int_t dy=-1;dy<2;dy++)
+      {
+      if (dx==dy && dy==0)
+        continue; 
+      Xlist[*Nlist] = iX + dx + i*offset;
+      Ylist[*Nlist] = iY + dy;
+      (*Nlist)++;
+      }
+CleanNeighbours(Nlist,Xlist,Ylist);
+}
+
+void AliMUONsegmentationV1::Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, 
+       Int_t Xlist[24], Int_t Ylist[24])
+{NeighboursDiag(iX,iY,Nlist,Xlist,Ylist);}
+
+
+void AliMUONsegmentationV1::
+FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits)
+    // Default : Centre of gravity method
+{
+printf (" AliMUONsegmentationV1::FitXY called!\n");
+    ;
+}
+
+void AliMUONsegmentationV1::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y)
+{
+    n=1;
+    x[0]=(TMath::Sqrt(frSensMax2)-TMath::Sqrt(frSensMin2))/2/TMath::Sqrt(2.);
+    y[0]=x[0];
+}
+
diff --git a/MUON/AliMUONSegResV1.h b/MUON/AliMUONSegResV1.h
new file mode 100644 (file)
index 0000000..a9ae947
--- /dev/null
@@ -0,0 +1,163 @@
+#ifndef MUONSegResV1_H
+#define MUONSegResV1_H
+/////////////////////////////////////////////////////////
+//  Manager and hits classes for set:MUON version 0    //
+/////////////////////////////////////////////////////////
+#include "AliMUONSegRes.h"
+
+const Int_t NZONE = 3; // Specific for chamber with equal pads
+const Int_t NZONEm1 = 2; // NZONE - 1
+const Int_t NZONECUT = 30;
+
+class AliMUONsegmentationV1 :
+public AliMUONsegmentation {
+ public:
+    AliMUONsegmentationV1();
+    virtual ~AliMUONsegmentationV1(){}
+    //    
+    // Set Chamber Segmentation Parameters
+    void SetNzone(Int_t N) {fNzone = N;};
+    virtual  void    SetPADSIZ(Float_t p1, Float_t p2);
+    void SetSensOffset(Float_t Offset) {fSensOffset = Offset;};
+    void SetDAnod(Float_t D) {fDAnod = D;};
+      // max x and y for the zone in number of pads units 
+      //(WARNING : first pad is labelled 0 !!) 
+    virtual void AddCut(Int_t Zone, Int_t nX, Int_t nY); 
+    virtual void DefaultCut(void);
+
+    //
+    // Initialisation
+    virtual void Init(AliMUONchamber*);
+    //
+    // Get member data
+    virtual Float_t Dpx(){return fDpx;}
+    virtual Float_t Dpy(){return fDpy;}
+    virtual Float_t Dpx(Int_t i){return fDpx;}
+    virtual Float_t Dpy(Int_t i){return fDpy;}
+    virtual Int_t   Npx(){return fNpx;}
+    virtual Int_t   Npy(){return fNpy;}
+    virtual Float_t GetRealDpx(Int_t isec) {return fDpx;}
+    //
+    // know the zone of segmentation
+    virtual Int_t GetZone(Float_t X, Float_t Y);
+    virtual Int_t GetZone(Int_t X, Int_t Y);
+    //
+    // Transform from pad (wire) to real coordinates and vice versa  
+    virtual Int_t GetiAnod(Float_t xhit);
+    virtual Float_t GetAnod(Float_t xhit);
+    virtual void    GetPadIxy(Float_t x ,Float_t y ,Int_t   &ix,Int_t   &iy);
+    virtual void    GetPadCxy(Int_t   ix,Int_t   iy,Float_t &x ,Float_t &y );
+    // set pad position
+    virtual void     SetPad(Int_t, Int_t);
+    // set hit position
+    virtual void     SetHit(Float_t, Float_t);
+    //
+    // Iterate over pads
+    virtual void SetPadCoord(Int_t iX, Int_t iY);
+    virtual void  FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy);
+    virtual void  NextPad();
+    virtual Int_t MorePads();
+    // Get next neighbours 
+    virtual void Neighbours // implementation Neighbours function
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t *Xlist, Int_t *Ylist);
+    virtual void NeighboursDiag // with diagonal elements
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t *Xlist, Int_t *Ylist);
+    virtual void NeighboursNonDiag // without diagonal elements
+       (Int_t iX, Int_t iY, Int_t* Nlist, Int_t *Xlist, Int_t *Ylist);
+    void CleanNeighbours(Int_t* Nlist, Int_t *Xlist, Int_t *Ylist);
+    // Provisory RecCluster coordinates reconstructor
+    virtual void FitXY(AliMUONRecCluster* Cluster,TClonesArray* MUONdigits);
+    //
+    // Channel number expressed in pad coordinates (stored in Cluster)
+    virtual Int_t Ix(Int_t trueX, Int_t trueY);
+    virtual Int_t Ix();
+    virtual Int_t Iy(){return fiy;}
+    // Actual number of pad in the chain
+    virtual Int_t ISector();
+    virtual Int_t Sector(Int_t ix, Int_t iy) {return 1;}
+    // Position of pad in perellel read-out
+    virtual Int_t IsParallel2(Int_t iX, Int_t iY);
+    virtual Int_t IsParallel3(Int_t iX, Int_t iY);
+    // Number of pads read in parallel
+    virtual Int_t NParallel2(Int_t iX, Int_t iY);
+    virtual Int_t NParallel3(Int_t iX, Int_t iY);
+    //
+    // Number of pads read in parallel and offset to add to x
+    virtual void GetNParallelAndOffset(Int_t iX, Int_t iY,
+       Int_t *Nparallel, Int_t *Offset);
+    // Minimum distance between 1 pad and a position
+    virtual Float_t Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *Offset);
+    //
+    // Signal Generation Condition during Stepping
+    Int_t SigGenCond(Float_t x, Float_t y, Float_t z);
+    void  SigGenInit(Float_t x, Float_t y, Float_t z);
+    void  GiveTestPoints(Int_t &n, Float_t *x, Float_t *y);
+    virtual void IntegrationLimits
+       (Float_t& x1, Float_t& x2, Float_t& y1, Float_t& y2);
+    //
+    virtual void Draw(){;}
+    // Function for systematic corrections
+    virtual void SetCorrFunc(Int_t dum, TF1* func) {fCorr=func;}
+    virtual TF1* CorrFunc(Int_t) {return fCorr;} 
+
+    //
+    // Identification
+    virtual char* YourName() {return fName;}
+    
+    ClassDef(AliMUONsegmentationV1,1)
+ protected:
+    //
+    // Implementation of the segmentation data
+    // Version This models rectangular pads with the same dimensions all
+    // over the cathode plane but let the possibilit for different design
+    //
+    //  geometry
+    Int_t fNzone; // Number of differents sensitive zones
+    Float_t fDpx;         // X pad width
+    Float_t fDpy;         // Y pad width
+    Int_t   fNZoneCut[NZONEm1];    // Number of cuts for given zone 
+    Int_t fZoneX[NZONEm1][NZONECUT]; // X descriptor of zone segmentations
+    Int_t fZoneY[NZONEm1][NZONECUT]; // Y descriptor of zone segmentations
+    Float_t frSensMax2; // square of maximum sensitive radius
+    Float_t frSensMin2; // square of minimum sensitive radius
+    Int_t   fNpx;         // Maximum number of pads along x
+    Int_t   fNpy;         // Maximum number of pads along y
+    Float_t fDAnod;       // Anod gap
+    Float_t fSensOffset;  // Offset of sensitive zone with respect to quadrant (positive)
+    
+    // Chamber region consideres during disintegration (lower left and upper right corner)
+    //
+    Int_t fixmin;
+    Int_t fixmax;
+    Int_t fiymin;
+    Int_t fiymax;
+    //
+    // Current pad during integration (cursor for disintegration)
+    Int_t fix;
+    Int_t fiy;
+    Float_t fx;
+    Float_t fy;
+    //
+    // Current pad and wire during tracking (cursor at hit centre)
+    Int_t fixt;
+    Int_t fiyt;
+    Int_t fiwt;
+    Float_t fxt;
+    Float_t fyt;
+    Float_t fxhit;
+    Float_t fyhit;
+    
+    TF1* fCorr;
+    
+    //
+    // Version Identifier
+    char    *fName;       
+
+
+
+};
+
+#endif
+
+
diff --git a/MUON/AliMUONTUBE.cxx b/MUON/AliMUONTUBE.cxx
new file mode 100644 (file)
index 0000000..a5daf97
--- /dev/null
@@ -0,0 +1,141 @@
+#include <AliMUONTUBE.h>
+#include <TTUBE.h>
+#include "TVirtualPad.h"
+ClassImp(AliMUONTUBE)
+
+AliMUONTUBE::AliMUONTUBE():TTUBE()
+{;}
+
+//_____________________________________________________________________________
+
+AliMUONTUBE::AliMUONTUBE(Text_t *name, Text_t *title, Text_t *material, Float_t rmin, 
+                        Float_t rmax, Float_t dz,Float_t aspect):
+    TTUBE(name, title, material, rmin, rmax, dz, aspect)
+{}
+
+//______________________________________________________________________________
+ AliMUONTUBE::AliMUONTUBE(Text_t *name, Text_t *title, Text_t *material, Float_t rmax, 
+                         Float_t dz)
+      : TTUBE(name, title, material, rmax, dz)
+{
+}
+
+//______________________________________________________________________________
+ void AliMUONTUBE::Paint(Option_t *option)
+{
+//*-*-*-*-*-*-*-*Paint this 3-D shape with its current attributes*-*-*-*-*-*-*-*
+//*-*            ================================================
+
+   Int_t i, j;
+   Int_t n = GetNumberOfDivisions();
+   const Int_t numpoints = 4*n;
+
+//*-* Allocate memory for points *-*
+
+   Float_t *points = new Float_t[3*numpoints];
+   if (!points) return;
+
+   SetPoints(points);
+
+   if (gPad->GetView3D()) PaintGLPoints(points);
+
+//==   for (i = 0; i < numpoints; i++)
+//==            gNode->Local2Master(&points[3*i],&points[3*i]);
+
+    X3DBuffer *buff = new X3DBuffer;
+    if (buff) {
+        buff->numPoints = numpoints;
+        buff->numSegs   = n*6;
+       if (strstr(option, "x3d"))  buff->numSegs   = n*8;
+        buff->numPolys  = n*4;
+    }
+
+//*-* Allocate memory for points *-*
+
+    buff->points = points;
+
+    Int_t c = ((GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
+    if (c < 0) c = 0;
+
+//*-* Allocate memory for segments *-*
+
+    buff->segs = new Int_t[buff->numSegs*3];
+    if (buff->segs) {
+        for (i = 0; i < 4; i++) {
+            for (j = 0; j < n; j++) {
+                buff->segs[(i*n+j)*3  ] = c;
+                buff->segs[(i*n+j)*3+1] = i*n+j;
+                buff->segs[(i*n+j)*3+2] = i*n+j+1;
+            }
+            buff->segs[(i*n+j-1)*3+2] = i*n;
+        }
+       for (i = 4; i < 6; i++) {
+           for (j = 0; j < n; j++) {
+               buff->segs[(i*n+j)*3  ] = c+1;
+               buff->segs[(i*n+j)*3+1] = (i-4)*n+j;
+               buff->segs[(i*n+j)*3+2] = (i-2)*n+j;
+           }
+       }
+       if (strstr(option, "x3d")) 
+       {
+           for (i = 6; i < 8; i++) {
+               for (j = 0; j < n; j++) {
+                   buff->segs[(i*n+j)*3  ] = c;
+                   buff->segs[(i*n+j)*3+1] = 2*(i-6)*n+j;
+                   buff->segs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
+               }
+           }
+       }
+    }
+//*-* Allocate memory for polygons *-*
+
+    Int_t indx = 0;
+
+    buff->polys = new Int_t[buff->numPolys*6];
+    if (buff->polys) {
+        for (i = 0; i < 2; i++) {
+            for (j = 0; j < n; j++) {
+                indx = 6*(i*n+j);
+                buff->polys[indx  ] = c;
+                buff->polys[indx+1] = 4;
+                buff->polys[indx+2] = i*n+j;
+                buff->polys[indx+3] = (4+i)*n+j;
+                buff->polys[indx+4] = (2+i)*n+j;
+                buff->polys[indx+5] = (4+i)*n+j+1;
+            }
+            buff->polys[indx+5] = (4+i)*n;
+        }
+        for (i = 2; i < 4; i++) {
+            for (j = 0; j < n; j++) {
+                indx = 6*(i*n+j);
+                buff->polys[indx  ] = c+(i-2)*2+1;
+                buff->polys[indx+1] = 4;
+                buff->polys[indx+2] = (i-2)*2*n+j;
+                buff->polys[indx+3] = (4+i)*n+j;
+                buff->polys[indx+4] = ((i-2)*2+1)*n+j;
+                buff->polys[indx+5] = (4+i)*n+j+1;
+            }
+            buff->polys[indx+5] = (4+i)*n;
+        }
+    }
+
+    //*-* Paint in the pad
+    Bool_t rangeView = strcmp(option,"range")==0 ? kTRUE : kFALSE;
+    PaintShape(buff,rangeView);
+
+    if (strstr(option, "x3d")) {
+        if(buff && buff->points && buff->segs)
+            FillX3DBuffer(buff);
+        else {
+            gSize3D.numPoints -= buff->numPoints;
+            gSize3D.numSegs   -= buff->numSegs;
+            gSize3D.numPolys  -= buff->numPolys;
+        }
+    }
+
+    if (buff->points)   delete [] buff->points;
+    if (buff->segs)     delete [] buff->segs;
+    if (buff->polys)    delete [] buff->polys;
+    if (buff)           delete    buff;
+}
+
diff --git a/MUON/AliMUONTUBE.h b/MUON/AliMUONTUBE.h
new file mode 100644 (file)
index 0000000..414c6da
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef AliMUONTube_H
+#define AliMUONTube_H
+////////////////////////////////////////////////
+//  Manager and hits classes for set:MUON     //
+////////////////////////////////////////////////
+#include "TTUBE.h"
+
+class AliMUONTUBE :
+public TTUBE {
+    
+ public:
+    AliMUONTUBE();
+    AliMUONTUBE(Text_t *name, Text_t *title, Text_t *material, Float_t rmin, Float_t rmax, Float_t dz,Float_t aspect);
+    AliMUONTUBE(Text_t *name, Text_t *title, Text_t *material, Float_t rmax, Float_t dz);
+    virtual ~AliMUONTUBE(){};
+    virtual void Paint(Option_t* option);
+    ClassDef(AliMUONTUBE,1)
+};
+#endif
diff --git a/MUON/AliMUONchamber.cxx b/MUON/AliMUONchamber.cxx
new file mode 100644 (file)
index 0000000..b670ee3
--- /dev/null
@@ -0,0 +1,81 @@
+#include "AliMUONchamber.h"
+#include "TMath.h"
+ClassImp(AliMUONchamber)       
+    AliMUONchamber::AliMUONchamber() 
+{
+    fSegmentation = new TObjArray(2);
+    fResponse=0;
+    fnsec=1;
+}
+
+void AliMUONchamber::Init()
+{
+    
+    ((AliMUONsegmentation *) (*fSegmentation)[0])->Init(this);
+    if (fnsec==2) {
+       ((AliMUONsegmentation *) (*fSegmentation)[1])->Init(this);
+    }
+    
+}
+
+void AliMUONchamber::DisIntegration(Float_t eloss, Float_t xhit, Float_t yhit,
+                                   Int_t& nnew,Float_t newclust[6][500]) 
+{
+//    
+//  Generates pad hits (simulated cluster) 
+//  using the segmentation and the response model 
+    Float_t dx, dy;
+    //
+    // Width of the integration area
+    //
+    dx=fResponse->SigmaIntegration()*fResponse->ChargeSpreadX();
+    dy=fResponse->SigmaIntegration()*fResponse->ChargeSpreadY();
+    //
+    // Get pulse height from energy loss
+    Float_t qtot = fResponse->IntPH(eloss);
+    //
+    // Loop Over Pads
+    
+    Float_t qcheck=0, qp;
+    nnew=0;
+    for (Int_t i=1; i<=fnsec; i++) {
+       qcheck=0;
+       AliMUONsegmentation * segmentation=(AliMUONsegmentation *) (*fSegmentation)[i-1];
+       for (segmentation->FirstPad(xhit, yhit, dx, dy); 
+            segmentation->MorePads(); 
+            segmentation->NextPad()) 
+       {
+           qp=fResponse->IntXY(segmentation);
+           qp=TMath::Abs(qp);
+           
+//
+//
+           if (qp > 1.e-4) {
+               qcheck+=qp;
+           //
+           // --- store signal information
+               newclust[0][nnew]=qtot;
+               newclust[1][nnew]=segmentation->Ix();
+               newclust[2][nnew]=segmentation->Iy();
+               newclust[3][nnew]=qp * qtot;
+               newclust[4][nnew]=segmentation->ISector();
+               newclust[5][nnew]=(Float_t) i;
+//             printf("\n pad hit %d %d %f %f \n",nnew,i,newclust[1][nnew],newclust[2][nnew]);
+               nnew++;
+
+               
+           }
+       } // Pad loop
+//     printf("\n check sum is %f %f %f %f %d \n",qcheck,qtot,xhit,yhit,fGid);
+    } // Cathode plane loop
+}
+
+
+
+    void AliMUONchamber::InitGeo(Float_t zpos)
+{
+//    sensitive gas gap
+      fdGas= 0.5;
+//    3% radiation length of aluminum (X0=8.9 cm)      
+      fdAlu= 3.0/100*8.9;
+}
diff --git a/MUON/AliMUONchamber.h b/MUON/AliMUONchamber.h
new file mode 100644 (file)
index 0000000..b0bb093
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef MUONchamber_H
+#define MUONchamber_H
+#include "TObjArray.h"
+#include "AliMUONSegRes.h"
+
+class AliMUONClusterFinder;
+class AliMUONresponse ;
+class AliMUONsegmentation ;
+
+class AliMUONchamber:
+public TObject
+{
+ public:
+    AliMUONchamber();
+    ~AliMUONchamber(){}
+//
+// Set and get GEANT id  
+  Int_t   GetGid()         {return fGid;}
+  void    SetGid(Int_t id) {fGid=id;}
+//  
+// Initialisation and z-Position
+  void    Init();
+  void    SetZPOS(Float_t p1) {fzPos=p1;}
+  Float_t ZPosition()         {return fzPos;}
+// Set inner radius of sensitive volume 
+  void SetRInner(Float_t rmin) {frMin=rmin;}
+// Set outer radius of sensitive volum  
+  void SetROuter(Float_t rmax) {frMax=rmax;}  
+
+// Return inner radius of sensitive volume 
+  Float_t RInner()            {return frMin;}
+// Return outer radius of sensitive volum  
+  Float_t ROuter()            {return frMax;}  
+//  
+// Configure response model
+  void    ResponseModel(AliMUONresponse* thisResponse) {fResponse=thisResponse;}
+//  
+// Configure segmentation model
+  void    SegmentationModel(Int_t i, AliMUONsegmentation* thisSegmentation) {
+      (*fSegmentation)[i-1] = thisSegmentation;
+  }
+  void    ReconstructionModel(AliMUONClusterFinder *thisReconstruction) {
+      fReconstruction = thisReconstruction;
+  }
+  
+//  
+//  Get reference to response model
+  AliMUONresponse*          &GetResponseModel(){return fResponse;}
+//
+  AliMUONClusterFinder*     &GetReconstructionModel(){return fReconstruction;}
+//  
+//  Get reference to segmentation model
+  AliMUONsegmentation*  GetSegmentationModel(Int_t isec) {
+      return (AliMUONsegmentation *) (*fSegmentation)[isec-1];
+  }
+  TObjArray* GetChamberSegmentation(){return fSegmentation;}
+  
+  Int_t Nsec()              {return fnsec;}
+  void  SetNsec(Int_t nsec) {fnsec=nsec;}
+//
+// Member function forwarding to the segmentation and response models
+//
+// Calculate pulse height from energy loss  
+  Float_t IntPH(Float_t eloss) {return fResponse->IntPH(eloss);}
+//  
+// Ask segmentation if signal should be generated  
+  Int_t   SigGenCond(Float_t x, Float_t y, Float_t z)
+      {
+         if (fnsec==1) {
+             return ((AliMUONsegmentation*) (*fSegmentation)[0])
+                 ->SigGenCond(x, y, z) ;
+         } else {
+             return (((AliMUONsegmentation*) (*fSegmentation)[0])
+                     ->SigGenCond(x, y, z)) ||
+                 (((AliMUONsegmentation*) (*fSegmentation)[1])
+                  ->SigGenCond(x, y, z)) ;
+         }
+  }
+//
+// Initialisation of segmentation for hit  
+  void    SigGenInit(Float_t x, Float_t y, Float_t z)
+      {
+         
+         if (fnsec==1) {
+             ((AliMUONsegmentation*) (*fSegmentation)[0])->SigGenInit(x, y, z) ;
+         } else {
+             ((AliMUONsegmentation*) (*fSegmentation)[0])->SigGenInit(x, y, z) ;
+             ((AliMUONsegmentation*) (*fSegmentation)[1])->SigGenInit(x, y, z) ;
+         }
+      }
+
+// Configuration forwarding
+//
+  void   SetSigmaIntegration(Float_t p1)         {fResponse->SetSigmaIntegration(p1);}
+  void   SetChargeSlope(Float_t p1)              {fResponse->SetChargeSlope(p1);}
+  void   SetChargeSpread(Float_t p1, Float_t p2) {fResponse->SetChargeSpread(p1,p2);}
+  void   SetMaxAdc(Float_t p1)                   {fResponse->SetMaxAdc(p1);}
+
+  void   SetPADSIZ(Int_t isec, Float_t p1, Float_t p2) {
+      ((AliMUONsegmentation*) (*fSegmentation)[isec-1])->SetPADSIZ(p1,p2);
+  }
+//  
+// Cluster formation method
+  void   DisIntegration(Float_t, Float_t, Float_t, Int_t&x, Float_t newclust[6][500]);
+    ClassDef(AliMUONchamber,1)
+   void    InitGeo(Float_t z);
+
+ private:
+// GEANT volume if for sensitive volume of this chamber
+  Int_t   fGid;
+// z-position of this chamber
+  Float_t fzPos; // z-position of chambers
+  Int_t   fnsec; // number of segmentation zones
+  Float_t frMin; // innermost sensitive radius
+  Float_t frMax; // outermost sensitive radius
+// The segmentation models for the cathode planes
+// fnsec=1: one plane segmented, fnsec=2: both planes are segmented.
+
+  TObjArray            *fSegmentation;
+  AliMUONClusterFinder *fReconstruction;
+  AliMUONresponse      *fResponse;
+  
+ public:
+  Float_t fdGas; // half gaz gap
+  Float_t fdAlu; // half Alu width
+};
+
+#endif
index af6a00e..69c3c16 100644 (file)
@@ -15,7 +15,6 @@
 #include <TView.h>
 #include <TText.h>
 #include <TPolyMarker3D.h>
-#include <TPolyMarker.h>
 #include <TPaveLabel.h>
 #include <TPaveText.h>
 #include <TList.h>
@@ -28,6 +27,7 @@
 #include <TGaxis.h>
 #include <TGXW.h>
 #include <TMath.h>
+#include <TMatrix.h>
 #include <X3DBuffer.h>
 
 #include "AliRun.h"
@@ -39,6 +39,7 @@
 #include "TParticle.h"
 
 
+
 ClassImp(AliMUONdisplay)
 
 
@@ -47,6 +48,9 @@ AliMUONdisplay::AliMUONdisplay()
 {
    fPoints = 0;
    fPhits = 0;
+   fRpoints = 0;
+   fR2points = 0;
+   fCpoints = 0;
    fCanvas = 0;
 }
 
@@ -99,7 +103,7 @@ AliMUONdisplay::AliMUONdisplay(Int_t size)
 //   If you are lost, you can click on HELP in any Root canvas or browser.
 //Begin_Html
 /*
-<img src="picts/aliMUONdisplay.gif">
+<img src="gif/aliMUONdisplay.gif">
 */
 //End_Html
 
@@ -109,21 +113,26 @@ AliMUONdisplay::AliMUONdisplay(Int_t size)
    gAlice->SetDisplay(this);
    
    // Initialize display default parameters
-   SetRange();
-
+   SetRange(200,2000);
    // Set front view by default
-   fTheta = 0;
+   fTheta =   0;
    fPhi   = -90;
-   fPsi   = 0;
+   fPsi   =   0;
    fChamber = 1;
    fCathode = 1;
    //   fRzone   = 1.e10;
    fDrawClusters  = kTRUE;
+   fDrawCoG       = kTRUE;
+   fDrawCoG  = kTRUE;
+   fDrawCathCor  = kTRUE;
    fZoomMode      = 1;
    fZooms         = 0;
    fClustersCuts  = 0;
    fPoints        = 0;
-   fPhits        = 0;
+   fPhits         = 0;
+   fRpoints       = 0;
+   fR2points = 0;
+   fCpoints = 0;
    // Create colors
    CreateColors();
    // Create display canvas
@@ -202,6 +211,18 @@ AliMUONdisplay::~AliMUONdisplay()
   if (fPhits) fPhits->Delete();
   delete fPhits;
   fPhits     = 0;
+  //
+  if (fRpoints) fRpoints->Delete();
+  delete fRpoints;
+  fRpoints     = 0;
+//
+  if (fR2points) fR2points->Delete();
+  delete fR2points;
+  fR2points     = 0;
+//
+  if (fCpoints) fCpoints->Delete();
+  delete fCpoints;
+  fCpoints     = 0;
 }
 
 //_____________________________________________________________________________
@@ -222,7 +243,7 @@ void AliMUONdisplay::DisplayButtons()
    fButtons->SetBorderSize(2);
    fButtons->cd();
 
-   //   Int_t butcolor = 33;
+//   Int_t butcolor = 33;
    Float_t dbutton = 0.08;
    Float_t y  = 0.96;
    Float_t dy = 0.014;
@@ -278,7 +299,7 @@ void AliMUONdisplay::CreateColors()
         g=i*0.2;  
         b=0.;
         color=i;
-        color=50+23-color;
+        color=260+23-color;
        //        printf("CreateColors - i, k, color %d %d %d \n",i,k,color);
         new TColor(color,r,g,b);
       } 
@@ -290,7 +311,7 @@ void AliMUONdisplay::CreateColors()
         g=1.;  
         b=0.;
         color=i+5;
-        color=50+23-color;
+        color=260+23-color;
        //        printf("CreateColors - i, k, color %d %d %d \n",i,k,color);
         new TColor(color,r,g,b);
       } 
@@ -302,7 +323,7 @@ void AliMUONdisplay::CreateColors()
         g=1.;  
         b=i*0.2+0.2;
         color=i+9;
-        color=50+23-color;
+        color=260+23-color;
        //        printf("CreateColors - i, k, color %d %d %d \n",i,k,color);
         new TColor(color,r,g,b);
       } 
@@ -314,7 +335,7 @@ void AliMUONdisplay::CreateColors()
         g=1.1-i*0.2;  
         b=1.;
         color=i+13;
-        color=50+23-color;
+        color=260+23-color;
        //        printf("CreateColors - i, k, color %d %d %d \n",i,k,color);
         new TColor(color,r,g,b);
       } 
@@ -326,7 +347,7 @@ void AliMUONdisplay::CreateColors()
         g=0.;  
         b=1.;
         color=i+17;
-        color=50+23-color;
+        color=260+23-color;
        //        printf("CreateColors - i, k, color %d %d %d \n",i,k,color);
         new TColor(color,r,g,b);
       } 
@@ -355,8 +376,14 @@ void AliMUONdisplay::DisplayColorScale()
 
    TText *text = new TText(0,0,"");
    text->SetTextFont(61);
-   text->SetTextSize(0.03);
+   text->SetTextSize(0.2);
    text->SetTextAlign(22);
+   
+          AliMUON *MUON  = (AliMUON*)gAlice->GetModule("MUON");
+          AliMUONchamber *iChamber = &(MUON->Chamber(fChamber-1));
+           AliMUONresponse * response=iChamber->GetResponseModel();
+           Int_t adcmax= (Int_t) response->MaxAdc();
+   
 
    TBox *box;
    char label[8];
@@ -367,10 +394,11 @@ void AliMUONdisplay::DisplayColorScale()
    for (i=0;i<22;i++) {
        ylow = y1 + hs*(Float_t(i));
        yup  = y1 + hs*(Float_t(i+1));
-         color = 51+i;
+         color = 261+i;
         //      Int_t scale=(i+1)*(Int_t)adc_satm/22;
         //      sprintf(label,"%d",scale);
-        Double_t logscale=Double_t(i+1)*(TMath::Log(adc_satm)/22);
+        //Double_t logscale=Double_t(i+1)*(TMath::Log(adc_satm)/22);
+        Double_t logscale=Double_t(i+1)*(TMath::Log(adcmax)/22);
          Int_t scale=(Int_t)TMath::Exp(logscale);
         sprintf(label,"%d",scale);
          box = new TBox(xlow, ylow, xup, yup);
@@ -408,8 +436,7 @@ void AliMUONdisplay::Draw(Option_t *)
 
    fPad->cd();
 
-   DrawView(fTheta, fPhi, fPsi);      // see how to draw PGON+inner frames
-
+   DrawView(fTheta, fPhi, fPsi);   
    // Display the event number and title
    fPad->cd();
    DrawTitle();
@@ -435,13 +462,23 @@ void AliMUONdisplay::DrawClusters()
       for (digit=0;digit<ndigits;digit++){
          pm = (AliMUONpoints*)points->UncheckedAt(digit);
          if (!pm) continue;
-        //        Float_t *pxyz;
-        //        pxyz=pm->GetP();
+         Float_t *pxyz;
+         pxyz=pm->GetP();
+//         Int_t color=(Int_t)pm->GetMarkerColor();
+        //      printf("DrawClusters - color %d \n",color);
+        //              DrawP(pxyz[0],pxyz[1],pxyz[2],0.75,0.5,color);
         //        printf("DrawClusters - pxyz[0],pxyz[1] %f %f \n",pxyz[0],pxyz[1]);
-         pm->Draw();
+        for (Int_t im=0;im<3;im++) {
+          TMarker3DBox *marker=pm->GetMarker(im);
+          //    marker->Dump();
+          if (marker)
+            marker->Draw();
+          }
+        pm->Draw();
         //               Int_t n=pm->GetN();
         //               printf("DrawClusters - n %d \n",n);
          fClustersCuts +=pm->GetN();
+
       }
 }
 
@@ -471,6 +508,79 @@ void AliMUONdisplay::DrawHits()
 
 
 //_____________________________________________________________________________
+void AliMUONdisplay::DrawCoG()
+{
+//    Draw hits for MUON chambers
+    if (!fDrawCoG) return;
+   LoadCoG(fChamber,fCathode);
+
+   Int_t ncog, icog;
+   TObjArray *points;
+   AliMUONpoints *pm;
+
+      points = Rpoints();
+      if (!points) return;
+      ncog = points->GetEntriesFast();
+      printf("DrawCoG - ncog %d \n",ncog);
+      for (icog=0;icog<ncog;icog++) {
+         pm = (AliMUONpoints*)points->UncheckedAt(icog);
+        if (!pm) continue;
+         pm->Draw();
+      }
+}
+void AliMUONdisplay::DrawCoG2()
+{
+//    Draw hits for MUON chambers
+
+   if (!fDrawCoG) return;
+  
+
+  if (fCathode==1) {
+     LoadCoG2(fChamber,2);
+  } else if (fCathode==2) {
+     LoadCoG2(fChamber,1);
+  }
+
+   Int_t ncog, icog;
+   TObjArray *points;
+   AliMUONpoints *pm;
+
+      points = R2points();
+      if (!points) return;
+      ncog = points->GetEntriesFast();
+      printf("DrawCoG - ncog %d \n",ncog);
+      for (icog=0;icog<ncog;icog++) {
+         pm = (AliMUONpoints*)points->UncheckedAt(icog);
+        if (!pm) continue;
+         pm->Draw();
+      }
+
+}
+//_____________________________________________________________________________
+void AliMUONdisplay::DrawCathCor()
+{
+//    Draw hits for MUON chambers
+    
+   if (!fDrawCathCor) return;
+
+   LoadCathCor(fChamber);
+
+   Int_t ncog, icog;
+   TObjArray *points;
+   AliMUONpoints *pm;
+
+      points = Cpoints();
+      if (!points) return;
+      ncog = points->GetEntriesFast();
+      printf("DrawCathCor - ncog %d \n",ncog);
+      for (icog=0;icog<ncog;icog++) {
+         pm = (AliMUONpoints*)points->UncheckedAt(icog);
+        if (!pm) continue;
+         pm->Draw();
+      }
+}
+//_____________________________________________________________________________
+//_____________________________________________________________________________
 void AliMUONdisplay::DrawTitle(Option_t *option)
 {
 //    D