- a fast HLT version of the SSD clusterfinder created. The speed on pp mc is ~20kHz...
authorsgorbuno <sgorbuno@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sat, 28 Nov 2009 22:05:12 +0000 (22:05 +0000)
committersgorbuno <sgorbuno@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sat, 28 Nov 2009 22:05:12 +0000 (22:05 +0000)
- the off-line finders for SPD, SSD can be used via "-use-offline-finder" config option
- compilation warnings fixed

HLT/ITS/clusterfinders/AliHLTITSClusterFinderSPD.cxx
HLT/ITS/clusterfinders/AliHLTITSClusterFinderSPD.h
HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.cxx [new file with mode: 0644]
HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.h [new file with mode: 0644]
HLT/libAliHLTITS.pkg

index 6b89e6a..3a5cdee 100644 (file)
@@ -38,6 +38,7 @@ ClassImp(AliHLTITSClusterFinderSPD)
 //__________________________________________________________________________
 AliHLTITSClusterFinderSPD::AliHLTITSClusterFinderSPD(AliITSDetTypeRec* dettyp)
   :
+  TObject(),
   fRecoParam(0),
   fDetTypeRec( dettyp ),
   fNModules(AliITSgeomTGeo::GetNModules()),
@@ -97,6 +98,35 @@ AliHLTITSClusterFinderSPD::AliHLTITSClusterFinderSPD(AliITSDetTypeRec* dettyp)
 
 }
 
+AliHLTITSClusterFinderSPD::AliHLTITSClusterFinderSPD( const AliHLTITSClusterFinderSPD &)
+  :
+  TObject(),
+  fRecoParam(0),
+  fDetTypeRec(0),
+  fNModules(0),
+  fLastSPD1(0),
+  fNySPD(256),
+  fNzSPD(160),
+  fNzBins( fNzSPD + 2 ),
+  fNyBins( fNySPD + 2),
+  fMaxBin( fNzBins * fNyBins ),
+  fYpitchSPD(0.0050),
+  fZ1pitchSPD(0.0425),
+  fZ2pitchSPD(0.0625),
+  fHwSPD(0.64),
+  fHlSPD(3.48),
+  fNSignals(0),
+  fSignal2Bin(0),
+  fBin2Signal(0)
+{
+  // dummy
+}
+
+AliHLTITSClusterFinderSPD &AliHLTITSClusterFinderSPD::operator=( const AliHLTITSClusterFinderSPD &)
+{
+  // dummy
+  return *this;
+}
 
 void AliHLTITSClusterFinderSPD::RawdataToClusters(AliRawReader* rawReader, std::vector<AliITSRecPoint> & clusters){
   //------------------------------------------------------------
index 67d8bbe..f8d1587 100644 (file)
@@ -21,7 +21,7 @@ class AliHLTITSClusterFinderSPD : public TObject
 {
 public:
   AliHLTITSClusterFinderSPD(AliITSDetTypeRec* dettyp);
-
   virtual ~AliHLTITSClusterFinderSPD(){
     delete[] fSignal2Bin;
     delete[] fBin2Signal;
@@ -60,6 +60,11 @@ public:
   UShort_t *fSignal2Bin; // array of input SPD signals
   UShort_t *fBin2Signal; // 2D map of SPD signals;
 
+ private:
+
+  AliHLTITSClusterFinderSPD(const AliHLTITSClusterFinderSPD&);
+  AliHLTITSClusterFinderSPD &operator=( const AliHLTITSClusterFinderSPD &);
+
   ClassDef(AliHLTITSClusterFinderSPD,0)  // ITS cluster finder V2 for SPD
 };
 
diff --git a/HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.cxx b/HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.cxx
new file mode 100644 (file)
index 0000000..82d0c28
--- /dev/null
@@ -0,0 +1,1241 @@
+/**************************************************************************
+ * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id: AliHLTITSClusterFinderSSD.cxx 34920 2009-09-22 07:48:53Z masera $ */
+
+////////////////////////////////////////////////////////////////////////////
+//            Implementation of the ITS clusterer V2 class                //
+//                                                                        //
+//          Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch            //
+//          Last revision: 13-05-09 Enrico Fragiacomo                     //
+//                                  enrico.fragiacomo@ts.infn.it          //
+//                                                                        //
+///////////////////////////////////////////////////////////////////////////
+
+#include <Riostream.h>
+#include "AliLog.h"
+
+#include "AliHLTITSClusterFinderSSD.h"
+#include "AliITSRecPoint.h"
+#include "AliITSgeomTGeo.h"
+#include "AliITSDetTypeRec.h"
+#include "AliRawReader.h"
+#include "AliITSRawStreamSSD.h"
+#include <TClonesArray.h>
+#include "AliITSdigitSSD.h"
+#include "AliITSReconstructor.h"
+#include "AliITSCalibrationSSD.h"
+#include "AliITSsegmentationSSD.h"
+
+Short_t *AliHLTITSClusterFinderSSD::fgPairs = 0x0;
+Int_t    AliHLTITSClusterFinderSSD::fgPairsSize = 0;
+const Float_t  AliHLTITSClusterFinderSSD::fgkThreshold = 5.;
+
+const Float_t AliHLTITSClusterFinderSSD::fgkCosmic2008StripShifts[16][9] = 
+  {{-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35},  // DDL 512
+   {-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35},  // DDL 513
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 514
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 515
+   { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 516
+   { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 517
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 518
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 519
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.25,-0.15},  // DDL 520
+   {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 521
+   {-0.10,-0.10,-0.10,-0.40,-0.40,-0.40,-0.10,-0.10,-0.45},  // DDL 522
+   {-0.10,-0.10,-0.10,-0.35,-0.35,-0.35,-0.10,-0.35,-0.50},  // DDL 523
+   { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 524
+   { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 525
+   { 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35},  // DDL 526
+   { 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45}}; // DDL 527
+
+ClassImp(AliHLTITSClusterFinderSSD)
+
+
+  AliHLTITSClusterFinderSSD::AliHLTITSClusterFinderSSD(AliITSDetTypeRec* dettyp, AliRawReader *reader)
+    :
+    AliITSClusterFinder(dettyp),
+    fRecoParam(0),
+    fRawReader( reader ),
+    fRawStream( 0 ),
+    fLastSSD1(AliITSgeomTGeo::GetModuleIndex(6,1,1)-1)
+{
+//Default constructor
+ //
+ // Initialisation of ITS geometry
+ //
+  Int_t mmax=AliITSgeomTGeo::GetNModules();
+  for (Int_t m=0; m<mmax; m++) {
+    Int_t lay,lad,det; AliITSgeomTGeo::GetModuleId(m,lay,lad,det);
+    fNdet[m] = (lad-1)*AliITSgeomTGeo::GetNDetectors(lay) + (det-1);
+    fNlayer[m] = lay-1;
+  }
+
+  fRecoParam = (AliITSRecoParam*) AliITSReconstructor::GetRecoParam();
+  if( !fRecoParam ){
+    fRecoParam = AliITSRecoParam::GetHighFluxParam();
+    AliWarning("Using default AliITSRecoParam class");  
+  }
+  fRawStream = new AliITSRawStreamSSD( fRawReader);
+}
+//______________________________________________________________________
+AliHLTITSClusterFinderSSD::AliHLTITSClusterFinderSSD(const AliHLTITSClusterFinderSSD &cf) : AliITSClusterFinder(cf),                                           fRecoParam(cf.fRecoParam), fRawReader(cf.fRawReader), fRawStream(0), fLastSSD1(cf.fLastSSD1)
+{
+  // Dummy
+}
+
+//______________________________________________________________________
+AliHLTITSClusterFinderSSD& AliHLTITSClusterFinderSSD::operator=(const AliHLTITSClusterFinderSSD&  ){
+  // Dummy
+  return *this;
+}
+
+AliHLTITSClusterFinderSSD::~AliHLTITSClusterFinderSSD()
+{
+  // destructor 
+  delete fRawStream;
+}
+
+void AliHLTITSClusterFinderSSD::RawdataToClusters( std::vector<AliITSRecPoint> &clusters )
+{
+  //------------------------------------------------------------
+  // Actual SSD cluster finder for raw data
+  //------------------------------------------------------------
+
+  fRawReader->Reset();  
+
+  const Int_t kMax = 1000;
+  Ali1Dcluster clusters1D[2][kMax];
+  Int_t nClusters[2] = {0, 0};
+  Int_t lab[3]={-2,-2,-2};
+
+  Int_t oddl = -1;
+  Int_t oad = -1;
+  Int_t oadc = -1;
+  Float_t dStrip = 0;
+
+  Float_t q = 0.;
+  Float_t y = 0.;
+  Int_t nDigits = 0;
+  Int_t ostrip = -1;
+  Bool_t oside = 0;
+  Bool_t snFlag = 0;
+  fModule = AliITSRawStreamSSD::GetModuleNumber(0,0);
+  AliITSCalibrationSSD* cal = (AliITSCalibrationSSD *) fDetTypeRec->GetCalibrationModel( fModule );
+  Int_t currModule = 0;
+
+  // read raw data input stream
+  while (kTRUE) {
+    
+    bool next = fRawStream->Next();
+    
+    // if( (!next)&&(fRawStream->flag) ) continue; //SG ??
+
+    Int_t ddl = fRawStream->GetDDL(); 
+    Int_t ad = fRawStream->GetAD();
+    Int_t adc = fRawStream->GetADC(); 
+    adc = (adc<6)? adc : adc - 2;
+    Bool_t side = fRawStream->GetSideFlag();
+    Int_t strip = fRawStream->GetStrip();
+    Int_t signal = fRawStream->GetSignal();
+
+    bool newModule = ( !next || ddl!= oddl || ad!=oad || adc!=oadc );
+
+    if( next && newModule ){
+      if( ddl>=0 && fRecoParam->GetUseCosmicRunShiftsSSD()) {  // Special condition for 2007/2008 cosmic data
+       dStrip = fgkCosmic2008StripShifts[ddl][ad-1];
+       if (TMath::Abs(dStrip) > 1.5)
+         AliError(Form("Indexing error ? ddl = %d, dStrip %f\n",ddl,dStrip));
+      }
+      Int_t iimod = (ad - 1)  * 12 + adc;
+      currModule = AliITSRawStreamSSD::GetModuleNumber(ddl,iimod);
+      if( currModule>=0 ) cal = (AliITSCalibrationSSD*)fDetTypeRec->GetCalibrationModel(currModule);       
+    }
+
+    Float_t noise=1, gain=0;
+    Bool_t stripOK = (strip>=0 && strip<768 );
+    
+    if( stripOK && cal ){
+      noise = side ?cal->GetNoiseN(strip) :cal->GetNoiseP(strip); 
+      gain = side ?cal->GetGainN(strip) :cal->GetGainP(strip);
+      stripOK = ( noise>=1. && signal>=3*noise 
+                 //&& !cal->IsPChannelBad(strip) 
+                 );
+    }
+    
+    bool newCluster = ( newModule || side!=oside);
+    if( !newCluster ){ 
+      // check for the order
+      if( strip<=ostrip ){
+       AliWarning("HLT ClustersFinderSSD: Unexpected order of SSD signals");
+       cout<<"HLT ClustersFinderSSD: Unexpected order of SSD signals"<<endl;
+      }
+      if( strip==ostrip ) continue; // duplicated signal
+      newCluster = ( strip!=ostrip+1 || !stripOK );
+    }
+
+    // Store the previous cluster
+    
+    if( newCluster ){
+      if( nDigits>0 && q>0 && snFlag ){
+       if (nClusters[0] >= kMax-1 ) {
+         AliWarning("HLT ClustersFinderSSD: Too many 1D clusters !");
+       }else {
+         Ali1Dcluster &cluster = clusters1D[oside][nClusters[oside]++];        
+         cluster.SetY( y / q + dStrip);
+         cluster.SetQ(q);
+         cluster.SetNd(nDigits);
+         cluster.SetLabels(lab);
+
+         //Split suspiciously big cluster
+
+         if( fRecoParam->GetUseUnfoldingInClusterFinderSSD()
+             && nDigits > 4 && nDigits < 25 
+             ){
+           cluster.SetY(y/q + dStrip - 0.25*nDigits);      
+           cluster.SetQ(0.5*q);          
+           Ali1Dcluster& cluster2 = clusters1D[oside][nClusters[oside]++];
+           cluster2.SetY(y/q + dStrip + 0.25*nDigits);     
+           cluster2.SetQ(0.5*q);
+           cluster2.SetNd(nDigits);
+           cluster2.SetLabels(lab);      
+         } // unfolding is on          
+       }
+      }
+      oside = side;
+      y = q = 0.;
+      nDigits = 0;
+      snFlag = 0;
+    }
+    
+    // Find 2D clusters in the previous adc and reset the 1D arrays
+
+    if( newModule ){ 
+      if( nClusters[0] && nClusters[1] && fModule>=0 ){
+       FindClustersSSD( clusters1D[0], nClusters[0], clusters1D[1], nClusters[1], clusters); 
+      }    
+      nClusters[0] = nClusters[1] = 0;
+      oddl = ddl;
+      oad = ad;
+      oadc = adc;
+      fModule = currModule;
+    }
+
+    if( !next ) break;       
+    
+    //cout<<ddl<<" "<<ad<<" "<<adc<<" "<<side<<" "<<strip<<endl;
+
+    if( stripOK ){ // add new signal to the cluster
+      signal = (Int_t) ( signal * gain ); // signal is corrected for gain
+      if( signal>fgkThreshold*noise) snFlag = 1;
+      signal = (Int_t) cal->ADCToKeV( signal ); // signal is  converted in KeV           
+      q += signal;       // add digit to current cluster
+      y += strip * signal;       
+      nDigits++;
+    }
+    ostrip = strip;
+  }
+}
+
+
+void AliHLTITSClusterFinderSSD::
+FindClustersSSD(Ali1Dcluster* neg, Int_t nn, 
+               Ali1Dcluster* pos, Int_t np,
+               std::vector<AliITSRecPoint> &clusters) {
+  //------------------------------------------------------------
+  // Actual SSD cluster finder
+  //------------------------------------------------------------
+
+  const TGeoHMatrix *mT2L=AliITSgeomTGeo::GetTracking2LocalMatrix(fModule);
+
+  AliITSsegmentationSSD *seg = dynamic_cast<AliITSsegmentationSSD*>(fDetTypeRec->GetSegmentationModel(2));
+  if (fModule>fLastSSD1) 
+    seg->SetLayer(6);
+  else 
+    seg->SetLayer(5);
+
+  Float_t hwSSD = seg->Dx()*1e-4/2;
+  Float_t hlSSD = seg->Dz()*1e-4/2;
+
+  Int_t idet=fNdet[fModule];
+  Int_t ncl=0;
+
+  //
+  Int_t *cnegative = new Int_t[np];  
+  Int_t *cused1 = new Int_t[np];
+  Int_t *negativepair = new Int_t[10*np];
+  Int_t *cpositive = new Int_t[nn];  
+  Int_t *cused2 = new Int_t[nn];  
+  Int_t *positivepair = new Int_t[10*nn];  
+  for (Int_t i=0;i<np;i++) {cnegative[i]=0; cused1[i]=0;}
+  for (Int_t i=0;i<nn;i++) {cpositive[i]=0; cused2[i]=0;}
+  for (Int_t i=0;i<10*np;i++) {negativepair[i]=0;}
+  for (Int_t i=0;i<10*nn;i++) {positivepair[i]=0;}
+
+  if ((np*nn) > fgPairsSize) {
+
+    if (fgPairs) delete [] fgPairs;
+    fgPairsSize = 4*np*nn;
+    fgPairs = new Short_t[fgPairsSize];
+  }
+  memset(fgPairs,0,sizeof(Short_t)*np*nn);
+
+  //
+  // find available pairs
+  //
+  for (Int_t i=0; i<np; i++) {
+    Float_t yp=pos[i].GetY(); 
+    if ( (pos[i].GetQ()>0) && (pos[i].GetQ()<3) ) continue;
+    for (Int_t j=0; j<nn; j++) {
+      if ( (neg[j].GetQ()>0) && (neg[j].GetQ()<3) ) continue;
+      Float_t yn=neg[j].GetY();
+
+      Float_t xt, zt;
+      seg->GetPadCxz(yn, yp, xt, zt);
+      //cout<<yn<<" "<<yp<<" "<<xt<<" "<<zt<<endl;
+      
+      if (TMath::Abs(xt)<hwSSD)
+      if (TMath::Abs(zt)<hlSSD) {
+       Int_t in = i*10+cnegative[i];
+       Int_t ip = j*10+cpositive[j];
+       if ((in < 10*np) && (ip < 10*nn)) {
+         negativepair[in] =j;  //index
+         positivepair[ip] =i;
+         cnegative[i]++;  //counters
+         cpositive[j]++;       
+         fgPairs[i*nn+j]=100;
+       }
+       else
+         AliError(Form("Index out of range: ip=%d, in=%d",ip,in));
+      }
+    }
+  }
+
+
+  //
+  Float_t lp[6];
+  Int_t milab[10];
+  Double_t ratio;
+  
+
+  if(fRecoParam->GetUseChargeMatchingInClusterFinderSSD()==kTRUE) {
+
+
+    //
+    // sign gold tracks
+    //
+    for (Int_t ip=0;ip<np;ip++){
+
+      Float_t xbest=1000,zbest=1000,qbest=0;
+      //
+      // select gold clusters
+      if ( (cnegative[ip]==1) && cpositive[negativepair[10*ip]]==1){ 
+
+       Float_t yp=pos[ip].GetY(); 
+       Int_t j = negativepair[10*ip];      
+
+       if( (pos[ip].GetQ()==0) && (neg[j].GetQ() ==0) ) { 
+         // both bad, hence continue;    
+         // mark both as used (to avoid recover at the end)
+         cused1[ip]++; 
+         cused2[j]++;
+         continue;
+       }
+
+       ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
+       //cout<<"ratio="<<ratio<<endl;
+
+       // charge matching (note that if posQ or negQ is 0 -> ratio=1 and the following condition is met
+       if (TMath::Abs(ratio)>0.2) continue; // note: 0.2=3xsigma_ratio calculated in cosmics tests
+
+       //
+       Float_t yn=neg[j].GetY();
+       
+       Float_t xt, zt;
+       seg->GetPadCxz(yn, yp, xt, zt);
+       
+       xbest=xt; zbest=zt; 
+
+       
+       qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
+       if( (pos[ip].GetQ()==0)||(neg[j].GetQ()==0)) qbest*=2; // in case of bad strips on one side keep all charge from the other one
+       
+       {
+         Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+         mT2L->MasterToLocal(loc,trk);
+         lp[0]=trk[1];
+         lp[1]=trk[2];
+       }
+       lp[4]=qbest;        //Q
+       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+       for (Int_t ilab=0;ilab<3;ilab++){
+         milab[ilab] = pos[ip].GetLabel(ilab);
+         milab[ilab+3] = neg[j].GetLabel(ilab);
+       }
+       //
+       CheckLabels2(milab);
+       milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det    
+       Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
+
+       lp[2]=0.0022*0.0022;  //SigmaY2
+       lp[3]=0.110*0.110;  //SigmaZ2
+       // out-of-diagonal element of covariance matrix
+       if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+       else if ( (info[0]>1) && (info[1]>1) ) { 
+         lp[2]=0.0016*0.0016;  //SigmaY2
+         lp[3]=0.08*0.08;  //SigmaZ2
+         lp[5]=-0.00006;
+       }
+       else {
+         lp[3]=0.093*0.093;
+         if (info[0]==1) { lp[5]=-0.00014;}
+         else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+       }
+       AliITSRecPoint cl2(milab,lp,info);      
+       cl2.SetChargeRatio(ratio);      
+       cl2.SetType(1);
+             
+       fgPairs[ip*nn+j]=1;
+       if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
+         cl2.SetType(2);
+         fgPairs[ip*nn+j]=2;
+       }
+
+       if(pos[ip].GetQ()==0) cl2.SetType(3);
+       if(neg[j].GetQ()==0) cl2.SetType(4);
+
+       cused1[ip]++;
+       cused2[j]++;
+
+       clusters.push_back(cl2);
+       
+       ncl++;
+      }
+    }
+
+    for (Int_t ip=0;ip<np;ip++){
+      Float_t xbest=1000,zbest=1000,qbest=0;
+      //
+      //
+      // select "silber" cluster
+      if ( cnegative[ip]==1 && cpositive[negativepair[10*ip]]==2){
+       Int_t in  = negativepair[10*ip];
+       Int_t ip2 = positivepair[10*in];
+       if (ip2==ip) ip2 =  positivepair[10*in+1];
+       Float_t pcharge = pos[ip].GetQ()+pos[ip2].GetQ();
+       
+
+
+       ratio = (pcharge-neg[in].GetQ())/(pcharge+neg[in].GetQ());
+       if ( (TMath::Abs(ratio)<0.2) && (pcharge!=0) ) {
+         //if ( (TMath::Abs(pcharge-neg[in].GetQ())<30) && (pcharge!=0) ) { // 
+         
+         //
+         // add first pair
+         if ( (fgPairs[ip*nn+in]==100)&&(pos[ip].GetQ() ) ) {  //
+           
+           Float_t yp=pos[ip].GetY(); 
+           Float_t yn=neg[in].GetY();
+           
+           Float_t xt, zt;
+           seg->GetPadCxz(yn, yp, xt, zt);
+           
+           xbest=xt; zbest=zt; 
+
+           qbest =pos[ip].GetQ();
+           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+           mT2L->MasterToLocal(loc,trk);
+           lp[0]=trk[1];
+           lp[1]=trk[2];
+           
+           lp[4]=qbest;        //Q
+           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+           for (Int_t ilab=0;ilab<3;ilab++){
+             milab[ilab] = pos[ip].GetLabel(ilab);
+             milab[ilab+3] = neg[in].GetLabel(ilab);
+           }
+           //
+           CheckLabels2(milab);
+           ratio = (pos[ip].GetQ()-neg[in].GetQ())/(pos[ip].GetQ()+neg[in].GetQ());
+           milab[3]=(((ip<<10) + in)<<10) + idet; // pos|neg|det
+           Int_t info[3] = {pos[ip].GetNd(),neg[in].GetNd(),fNlayer[fModule]};
+           
+           lp[2]=0.0022*0.0022;  //SigmaY2
+           lp[3]=0.110*0.110;  //SigmaZ2
+           // out-of-diagonal element of covariance matrix
+           if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+           else if ( (info[0]>1) && (info[1]>1) ) { 
+             lp[2]=0.0016*0.0016;  //SigmaY2
+             lp[3]=0.08*0.08;  //SigmaZ2
+             lp[5]=-0.00006;
+           }
+           else {
+             lp[3]=0.093*0.093;
+             if (info[0]==1) { lp[5]=-0.00014;}
+             else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+           }
+
+           AliITSRecPoint cl2(milab,lp,info);      
+           cl2.SetChargeRatio(ratio);          
+           cl2.SetType(5);
+           fgPairs[ip*nn+in] = 5;
+           if ((pos[ip].GetNd()+neg[in].GetNd())>6){ //multi cluster
+             cl2.SetType(6);
+             fgPairs[ip*nn+in] = 6;
+           }       
+           clusters.push_back(cl2);
+           ncl++;
+         }
+         
+         
+         //
+         // add second pair
+         
+         //    if (!(cused1[ip2] || cused2[in])){  //
+         if ( (fgPairs[ip2*nn+in]==100) && (pos[ip2].GetQ()) ) {
+           
+           Float_t yp=pos[ip2].GetY();
+           Float_t yn=neg[in].GetY();
+           
+           Float_t xt, zt;
+           seg->GetPadCxz(yn, yp, xt, zt);
+           
+           xbest=xt; zbest=zt; 
+
+           qbest =pos[ip2].GetQ();
+           
+           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+           mT2L->MasterToLocal(loc,trk);
+           lp[0]=trk[1];
+           lp[1]=trk[2];
+           
+           lp[4]=qbest;        //Q
+           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+           for (Int_t ilab=0;ilab<3;ilab++){
+             milab[ilab] = pos[ip2].GetLabel(ilab);
+             milab[ilab+3] = neg[in].GetLabel(ilab);
+           }
+           //
+           CheckLabels2(milab);
+           ratio = (pos[ip2].GetQ()-neg[in].GetQ())/(pos[ip2].GetQ()+neg[in].GetQ());
+           milab[3]=(((ip2<<10) + in)<<10) + idet; // pos|neg|det
+           Int_t info[3] = {pos[ip2].GetNd(),neg[in].GetNd(),fNlayer[fModule]};
+           
+           lp[2]=0.0022*0.0022;  //SigmaY2
+           lp[3]=0.110*0.110;  //SigmaZ2
+           // out-of-diagonal element of covariance matrix
+           if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+           else if ( (info[0]>1) && (info[1]>1) ) { 
+             lp[2]=0.0016*0.0016;  //SigmaY2
+             lp[3]=0.08*0.08;  //SigmaZ2
+             lp[5]=-0.00006;
+           }
+           else {
+             lp[3]=0.093*0.093;
+             if (info[0]==1) { lp[5]=-0.00014;}
+             else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+           }
+           
+           AliITSRecPoint cl2(milab,lp,info);
+           cl2.SetChargeRatio(ratio);          
+           cl2.SetType(5);
+           fgPairs[ip2*nn+in] =5;
+           if ((pos[ip2].GetNd()+neg[in].GetNd())>6){ //multi cluster
+             cl2.SetType(6);
+             fgPairs[ip2*nn+in] =6;
+           }
+           clusters.push_back(cl2);
+           ncl++;
+         }
+         
+         cused1[ip]++;
+         cused1[ip2]++;
+         cused2[in]++;
+         
+       } // charge matching condition
+       
+      } // 2 Pside cross 1 Nside
+    } // loop over Pside clusters
+    
+      
+      //  
+    for (Int_t jn=0;jn<nn;jn++){
+      if (cused2[jn]) continue;
+      Float_t xbest=1000,zbest=1000,qbest=0;
+      // select "silber" cluster
+      if ( cpositive[jn]==1 && cnegative[positivepair[10*jn]]==2){
+       Int_t ip  = positivepair[10*jn];
+       Int_t jn2 = negativepair[10*ip];
+       if (jn2==jn) jn2 =  negativepair[10*ip+1];
+       Float_t pcharge = neg[jn].GetQ()+neg[jn2].GetQ();
+       //
+       
+
+       ratio = (pcharge-pos[ip].GetQ())/(pcharge+pos[ip].GetQ());
+       if ( (TMath::Abs(ratio)<0.2) && (pcharge!=0) ) {
+
+         /*
+       if ( (TMath::Abs(pcharge-pos[ip].GetQ())<30) &&  // charge matching 
+            (pcharge!=0) ) { // reject combinations of bad strips
+         */
+
+
+         //
+         // add first pair
+         //    if (!(cused1[ip]||cused2[jn])){
+         if ( (fgPairs[ip*nn+jn]==100) && (neg[jn].GetQ()) ) {  //
+           
+           Float_t yn=neg[jn].GetY(); 
+           Float_t yp=pos[ip].GetY();
+
+           Float_t xt, zt;
+           seg->GetPadCxz(yn, yp, xt, zt);
+           
+           xbest=xt; zbest=zt; 
+
+           qbest =neg[jn].GetQ();
+
+           {
+             Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+             mT2L->MasterToLocal(loc,trk);
+             lp[0]=trk[1];
+             lp[1]=trk[2];
+          }
+         
+         lp[4]=qbest;        //Q
+         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+         for (Int_t ilab=0;ilab<3;ilab++){
+           milab[ilab] = pos[ip].GetLabel(ilab);
+           milab[ilab+3] = neg[jn].GetLabel(ilab);
+         }
+         //
+         CheckLabels2(milab);
+         ratio = (pos[ip].GetQ()-neg[jn].GetQ())/(pos[ip].GetQ()+neg[jn].GetQ());
+         milab[3]=(((ip<<10) + jn)<<10) + idet; // pos|neg|det
+         Int_t info[3] = {pos[ip].GetNd(),neg[jn].GetNd(),fNlayer[fModule]};
+
+         lp[2]=0.0022*0.0022;  //SigmaY2
+         lp[3]=0.110*0.110;  //SigmaZ2
+         // out-of-diagonal element of covariance matrix
+         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+         else if ( (info[0]>1) && (info[1]>1) ) { 
+           lp[2]=0.0016*0.0016;  //SigmaY2
+           lp[3]=0.08*0.08;  //SigmaZ2
+           lp[5]=-0.00006;
+         }
+         else {
+           lp[3]=0.093*0.093;
+           if (info[0]==1) { lp[5]=-0.00014;}
+           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+         }
+         
+         AliITSRecPoint cl2(milab,lp,info);
+         cl2.SetChargeRatio(ratio);            
+         cl2.SetType(7);
+         fgPairs[ip*nn+jn] =7;
+         if ((pos[ip].GetNd()+neg[jn].GetNd())>6){ //multi cluster
+           cl2.SetType(8);
+           fgPairs[ip*nn+jn]=8;
+         }
+         clusters.push_back(cl2);
+         
+         ncl++;
+         }
+       //
+       // add second pair
+       //      if (!(cused1[ip]||cused2[jn2])){
+       if ( (fgPairs[ip*nn+jn2]==100)&&(neg[jn2].GetQ() ) ) {  //
+
+         Float_t yn=neg[jn2].GetY(); 
+         Double_t yp=pos[ip].GetY(); 
+
+         Float_t xt, zt;
+         seg->GetPadCxz(yn, yp, xt, zt);
+         
+         xbest=xt; zbest=zt; 
+
+         qbest =neg[jn2].GetQ();
+
+          {
+          Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+          mT2L->MasterToLocal(loc,trk);
+          lp[0]=trk[1];
+          lp[1]=trk[2];
+          }
+
+         lp[4]=qbest;        //Q
+         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+         for (Int_t ilab=0;ilab<3;ilab++){
+           milab[ilab] = pos[ip].GetLabel(ilab);
+           milab[ilab+3] = neg[jn2].GetLabel(ilab);
+         }
+         //
+         CheckLabels2(milab);
+         ratio = (pos[ip].GetQ()-neg[jn2].GetQ())/(pos[ip].GetQ()+neg[jn2].GetQ());
+         milab[3]=(((ip<<10) + jn2)<<10) + idet; // pos|neg|det
+         Int_t info[3] = {pos[ip].GetNd(),neg[jn2].GetNd(),fNlayer[fModule]};
+
+         lp[2]=0.0022*0.0022;  //SigmaY2
+         lp[3]=0.110*0.110;  //SigmaZ2
+         // out-of-diagonal element of covariance matrix
+         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+         else if ( (info[0]>1) && (info[1]>1) ) { 
+           lp[2]=0.0016*0.0016;  //SigmaY2
+           lp[3]=0.08*0.08;  //SigmaZ2
+           lp[5]=-0.00006;
+         }
+         else {
+           lp[3]=0.093*0.093;
+           if (info[0]==1) { lp[5]=-0.00014;}
+         else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+         }
+         
+         AliITSRecPoint cl2(milab,lp,info);
+         cl2.SetChargeRatio(ratio);            
+         fgPairs[ip*nn+jn2]=7;
+         cl2.SetType(7);
+         if ((pos[ip].GetNd()+neg[jn2].GetNd())>6){ //multi cluster
+           cl2.SetType(8);
+           fgPairs[ip*nn+jn2]=8;
+         }
+         clusters.push_back( cl2 );
+         ncl++;
+       }
+       cused1[ip]++;
+       cused2[jn]++;
+       cused2[jn2]++;
+       
+       } // charge matching condition
+       
+      } // 2 Nside cross 1 Pside
+    } // loop over Pside clusters
+
+  
+
+    for (Int_t ip=0;ip<np;ip++){
+
+      if(cused1[ip]) continue;
+
+
+      Float_t xbest=1000,zbest=1000,qbest=0;
+      //
+      // 2x2 clusters
+      //
+      if ( (cnegative[ip]==2) && cpositive[negativepair[10*ip]]==2){ 
+       Float_t minchargediff =4.;
+       Float_t minchargeratio =0.2;
+
+       Int_t j=-1;
+       for (Int_t di=0;di<cnegative[ip];di++){
+         Int_t   jc = negativepair[ip*10+di];
+         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
+         ratio = (pos[ip].GetQ()-neg[jc].GetQ())/(pos[ip].GetQ()+neg[jc].GetQ()); 
+         //if (TMath::Abs(chargedif)<minchargediff){
+         if (TMath::Abs(ratio)<0.2){
+           j =jc;
+           minchargediff = TMath::Abs(chargedif);
+           minchargeratio = TMath::Abs(ratio);
+         }
+       }
+       if (j<0) continue;  // not proper cluster      
+       
+
+       Int_t count =0;
+       for (Int_t di=0;di<cnegative[ip];di++){
+         Int_t   jc = negativepair[ip*10+di];
+         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
+       }
+       if (count>1) continue;  // more than one "proper" cluster for positive
+       //
+       
+       count =0;
+       for (Int_t dj=0;dj<cpositive[j];dj++){
+         Int_t   ic  = positivepair[j*10+dj];
+         Float_t chargedif = pos[ic].GetQ()-neg[j].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
+       }
+       if (count>1) continue;  // more than one "proper" cluster for negative
+       
+       Int_t jp = 0;
+       
+       count =0;
+       for (Int_t dj=0;dj<cnegative[jp];dj++){
+         Int_t   ic = positivepair[jp*10+dj];
+         Float_t chargedif = pos[ic].GetQ()-neg[jp].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+4.) count++;
+       }
+       if (count>1) continue;   
+       if (fgPairs[ip*nn+j]<100) continue;
+       //
+       
+
+
+       //almost gold clusters
+       Float_t yp=pos[ip].GetY(); 
+       Float_t yn=neg[j].GetY();      
+       Float_t xt, zt;
+       seg->GetPadCxz(yn, yp, xt, zt); 
+       xbest=xt; zbest=zt; 
+       qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
+       {
+         Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+         mT2L->MasterToLocal(loc,trk);
+         lp[0]=trk[1];
+         lp[1]=trk[2];
+       }
+       lp[4]=qbest;        //Q
+       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+       for (Int_t ilab=0;ilab<3;ilab++){
+         milab[ilab] = pos[ip].GetLabel(ilab);
+         milab[ilab+3] = neg[j].GetLabel(ilab);
+       }
+       //
+       CheckLabels2(milab);
+        if ((neg[j].GetQ()==0)&&(pos[ip].GetQ()==0)) continue; // reject crosses of bad strips!!
+       ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
+       milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
+       Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
+
+       lp[2]=0.0022*0.0022;  //SigmaY2
+       lp[3]=0.110*0.110;  //SigmaZ2
+       // out-of-diagonal element of covariance matrix
+       if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+       else if ( (info[0]>1) && (info[1]>1) ) { 
+         lp[2]=0.0016*0.0016;  //SigmaY2
+         lp[3]=0.08*0.08;  //SigmaZ2
+         lp[5]=-0.00006;
+       }
+       else {
+         lp[3]=0.093*0.093;
+         if (info[0]==1) { lp[5]=-0.00014;}
+         else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+       }
+
+       AliITSRecPoint cl2(milab,lp,info);
+       cl2.SetChargeRatio(ratio);      
+       cl2.SetType(10);
+       fgPairs[ip*nn+j]=10;
+       if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
+         cl2.SetType(11);
+         fgPairs[ip*nn+j]=11;
+       }
+       cused1[ip]++;
+       cused2[j]++;      
+       
+       clusters.push_back(cl2);
+       ncl++;
+       
+      } // 2X2
+    } // loop over Pside 1Dclusters
+
+
+    for (Int_t ip=0;ip<np;ip++){
+
+      if(cused1[ip]) continue;
+
+
+      Float_t xbest=1000,zbest=1000,qbest=0;
+      //
+      // manyxmany clusters
+      //
+      if ( (cnegative[ip]<5) && cpositive[negativepair[10*ip]]<5){ 
+       Float_t minchargediff =4.;
+       Int_t j=-1;
+       for (Int_t di=0;di<cnegative[ip];di++){
+         Int_t   jc = negativepair[ip*10+di];
+         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff){
+           j =jc;
+           minchargediff = TMath::Abs(chargedif);
+         }
+       }
+       if (j<0) continue;  // not proper cluster      
+       
+       Int_t count =0;
+       for (Int_t di=0;di<cnegative[ip];di++){
+         Int_t   jc = negativepair[ip*10+di];
+         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
+       }
+       if (count>1) continue;  // more than one "proper" cluster for positive
+       //
+       
+       count =0;
+       for (Int_t dj=0;dj<cpositive[j];dj++){
+         Int_t   ic  = positivepair[j*10+dj];
+         Float_t chargedif = pos[ic].GetQ()-neg[j].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
+       }
+       if (count>1) continue;  // more than one "proper" cluster for negative
+       
+       Int_t jp = 0;
+       
+       count =0;
+       for (Int_t dj=0;dj<cnegative[jp];dj++){
+         Int_t   ic = positivepair[jp*10+dj];
+         Float_t chargedif = pos[ic].GetQ()-neg[jp].GetQ();
+         if (TMath::Abs(chargedif)<minchargediff+4.) count++;
+       }
+       if (count>1) continue;   
+       if (fgPairs[ip*nn+j]<100) continue;
+       //
+       
+       //almost gold clusters
+       Float_t yp=pos[ip].GetY(); 
+       Float_t yn=neg[j].GetY();
+      
+
+       Float_t xt, zt;
+       seg->GetPadCxz(yn, yp, xt, zt);
+       
+       xbest=xt; zbest=zt; 
+
+       qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
+
+       {
+         Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+         mT2L->MasterToLocal(loc,trk);
+         lp[0]=trk[1];
+         lp[1]=trk[2];
+       }
+       lp[4]=qbest;        //Q
+       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+       for (Int_t ilab=0;ilab<3;ilab++){
+         milab[ilab] = pos[ip].GetLabel(ilab);
+         milab[ilab+3] = neg[j].GetLabel(ilab);
+       }
+       //
+       CheckLabels2(milab);
+        if ((neg[j].GetQ()==0)&&(pos[ip].GetQ()==0)) continue; // reject crosses of bad strips!!
+       ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
+       milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
+       Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
+
+       lp[2]=0.0022*0.0022;  //SigmaY2
+       lp[3]=0.110*0.110;  //SigmaZ2
+       // out-of-diagonal element of covariance matrix
+       if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+       else if ( (info[0]>1) && (info[1]>1) ) { 
+         lp[2]=0.0016*0.0016;  //SigmaY2
+         lp[3]=0.08*0.08;  //SigmaZ2
+         lp[5]=-0.00006;
+       }
+       else {
+         lp[3]=0.093*0.093;
+         if (info[0]==1) { lp[5]=-0.00014;}
+         else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+       }
+
+       AliITSRecPoint cl2(milab,lp,info);
+       cl2.SetChargeRatio(ratio);      
+       cl2.SetType(12);
+       fgPairs[ip*nn+j]=12;
+       if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
+         cl2.SetType(13);
+         fgPairs[ip*nn+j]=13;
+       }
+       cused1[ip]++;
+       cused2[j]++;      
+       clusters.push_back( cl2 );
+       ncl++;
+       
+      } // manyXmany
+    } // loop over Pside 1Dclusters
+    
+  } // use charge matching
+  
+  // recover all the other crosses
+  //  
+  for (Int_t i=0; i<np; i++) {
+    Float_t xbest=1000,zbest=1000,qbest=0;
+    Float_t yp=pos[i].GetY(); 
+    if ((pos[i].GetQ()>0)&&(pos[i].GetQ()<3)) continue;
+    for (Int_t j=0; j<nn; j++) {
+    //    for (Int_t di = 0;di<cpositive[i];di++){
+    //  Int_t j = negativepair[10*i+di];
+      if ((neg[j].GetQ()>0)&&(neg[j].GetQ()<3)) continue;
+
+      if ((neg[j].GetQ()==0)&&(pos[i].GetQ()==0)) continue; // reject crosses of bad strips!!
+
+      if (cused2[j]||cused1[i]) continue;      
+      if (fgPairs[i*nn+j]>0 &&fgPairs[i*nn+j]<100) continue;
+      ratio = (pos[i].GetQ()-neg[j].GetQ())/(pos[i].GetQ()+neg[j].GetQ());      
+      Float_t yn=neg[j].GetY();
+      
+      Float_t xt, zt;
+      seg->GetPadCxz(yn, yp, xt, zt);
+      
+      if (TMath::Abs(xt)<hwSSD)
+      if (TMath::Abs(zt)<hlSSD) {
+       xbest=xt; zbest=zt; 
+
+        qbest=0.5*(pos[i].GetQ()+neg[j].GetQ());
+
+        {
+        Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
+        mT2L->MasterToLocal(loc,trk);
+        lp[0]=trk[1];
+        lp[1]=trk[2];
+        }
+        lp[4]=qbest;        //Q
+       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+       for (Int_t ilab=0;ilab<3;ilab++){
+         milab[ilab] = pos[i].GetLabel(ilab);
+         milab[ilab+3] = neg[j].GetLabel(ilab);
+       }
+       //
+       CheckLabels2(milab);
+       milab[3]=(((i<<10) + j)<<10) + idet; // pos|neg|det
+       Int_t info[3] = {pos[i].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
+
+       lp[2]=0.0022*0.0022;  //SigmaY2
+       lp[3]=0.110*0.110;  //SigmaZ2
+       // out-of-diagonal element of covariance matrix
+       if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
+       else if ( (info[0]>1) && (info[1]>1) ) { 
+         lp[2]=0.0016*0.0016;  //SigmaY2
+         lp[3]=0.08*0.08;  //SigmaZ2
+         lp[5]=-0.00006;
+       }
+       else {
+         lp[3]=0.093*0.093;
+         if (info[0]==1) { lp[5]=-0.00014;}
+         else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
+       }
+
+       AliITSRecPoint cl2(milab,lp,info);
+       cl2.SetChargeRatio(ratio);
+       cl2.SetType(100+cpositive[j]+cnegative[i]);       
+
+       if(pos[i].GetQ()==0) cl2.SetType(200+cpositive[j]+cnegative[i]);
+       if(neg[j].GetQ()==0) cl2.SetType(300+cpositive[j]+cnegative[i]);
+       clusters.push_back( cl2 );
+       ncl++;
+      }
+    }
+  }
+
+
+  if(fRecoParam->GetUseBadChannelsInClusterFinderSSD()==kTRUE) {
+    
+    //---------------------------------------------------------
+    // recover crosses of good 1D clusters with bad strips on the other side
+    // Note1: at first iteration skip modules with a bad side (or almost), (would produce too many fake!) 
+    // Note2: for modules with a bad side see below 
+    
+    AliITSCalibrationSSD* cal = (AliITSCalibrationSSD*) fDetTypeRec->GetCalibrationModel(fModule);
+    Int_t countPbad=0, countNbad=0;
+    for(Int_t ib=0; ib<768; ib++) {
+      if(cal->IsPChannelBad(ib)) countPbad++;
+      if(cal->IsNChannelBad(ib)) countNbad++;
+    }
+    //  AliInfo(Form("module %d has %d P- and %d N-bad strips",fModule,countPbad,countNbad));
+    
+    if( (countPbad<100) && (countNbad<100) ) { // no bad side!!
+      
+      for (Int_t i=0; i<np; i++) { // loop over Nside 1Dclusters with no crosses
+       if(cnegative[i]) continue; // if intersecting Pside clusters continue;
+       
+       //      for(Int_t ib=0; ib<768; ib++) { // loop over all Pstrips
+       for(Int_t ib=15; ib<753; ib++) { // loop over all Pstrips
+         
+         if(cal->IsPChannelBad(ib)) { // check if strips is bad
+           Float_t yN=pos[i].GetY();   
+           Float_t xt, zt;
+           seg->GetPadCxz(1.*ib, yN, xt, zt);  
+           
+           //----------
+           // bad Pstrip is crossing the Nside 1Dcluster -> create recpoint
+           // 
+           if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
+             Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
+             mT2L->MasterToLocal(loc,trk);
+             lp[0]=trk[1];
+             lp[1]=trk[2];        
+             lp[4]=pos[i].GetQ(); //Q
+             for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+             for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = pos[i].GetLabel(ilab);       
+             CheckLabels2(milab);
+             milab[3]=( (i<<10) << 10 ) + idet; // pos|neg|det
+             Int_t info[3] = {pos[i].GetNd(),0,fNlayer[fModule]};
+             
+             // out-of-diagonal element of covariance matrix
+             if (info[0]==1) lp[5]=0.0065;
+             else lp[5]=0.0093;
+             
+             lp[2]=0.0022*0.0022;  //SigmaY2
+             lp[3]=0.110*0.110;  //SigmaZ2
+             lp[5]=-0.00012; // out-of-diagonal element of covariance matrix
+             
+             AliITSRecPoint cl2(milab,lp,info);
+             cl2.SetChargeRatio(1.);
+             cl2.SetType(50);    
+             clusters.push_back( cl2 );
+             ncl++;
+           } // cross is within the detector
+           //
+           //--------------
+           
+         } // bad Pstrip
+         
+       } // end loop over Pstrips
+       
+      } // end loop over Nside 1D clusters
+      
+      for (Int_t j=0; j<nn; j++) { // loop over Pside 1D clusters with no crosses
+       if(cpositive[j]) continue;
+       
+       //      for(Int_t ib=0; ib<768; ib++) { // loop over all Nside strips
+       for(Int_t ib=15; ib<753; ib++) { // loop over all Nside strips
+         
+         if(cal->IsNChannelBad(ib)) { // check if strip is bad
+           Float_t yP=neg[j].GetY();   
+           Float_t xt, zt;
+           seg->GetPadCxz(yP, 1.*ib, xt, zt);  
+           
+           //----------
+           // bad Nstrip is crossing the Pside 1Dcluster -> create recpoint
+           // 
+           if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
+             Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
+             mT2L->MasterToLocal(loc,trk);
+             lp[0]=trk[1];
+             lp[1]=trk[2];        
+             lp[4]=neg[j].GetQ(); //Q
+             for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+             for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = neg[j].GetLabel(ilab);       
+             CheckLabels2(milab);
+             milab[3]=( j << 10 ) + idet; // pos|neg|det
+             Int_t info[3]={0,(Int_t)neg[j].GetNd(),fNlayer[fModule]};
+             
+             lp[2]=0.0022*0.0022;  //SigmaY2
+             lp[3]=0.110*0.110;  //SigmaZ2
+             lp[5]=-0.00012; // out-of-diagonal element of covariance matrix
+             
+             AliITSRecPoint cl2(milab,lp,info);
+             cl2.SetChargeRatio(1.);
+             cl2.SetType(60);    
+             clusters.push_back( cl2 );
+             ncl++;
+           } // cross is within the detector
+           //
+           //--------------
+           
+         } // bad Nstrip
+       } // end loop over Nstrips
+      } // end loop over Pside 1D clusters
+      
+    } // no bad sides 
+    
+    //---------------------------------------------------------
+    
+    else if( (countPbad>700) && (countNbad<100) ) { // bad Pside!!
+      
+      for (Int_t i=0; i<np; i++) { // loop over Nside 1Dclusters with no crosses
+       if(cnegative[i]) continue; // if intersecting Pside clusters continue;
+       
+       Float_t xt, zt;
+       Float_t yN=pos[i].GetY();       
+       Float_t yP=0.;
+       if (seg->GetLayer()==5) yP = yN + (7.6/1.9);
+       else yP = yN - (7.6/1.9);
+       seg->GetPadCxz(yP, yN, xt, zt); 
+       
+       if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
+         Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
+         mT2L->MasterToLocal(loc,trk);
+         lp[0]=trk[1];
+         lp[1]=trk[2];        
+         lp[4]=pos[i].GetQ(); //Q
+         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+         for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = pos[i].GetLabel(ilab);   
+         CheckLabels2(milab);
+         milab[3]=( (i<<10) << 10 ) + idet; // pos|neg|det
+         Int_t info[3] = {(Int_t)pos[i].GetNd(),0,fNlayer[fModule]};
+         
+         lp[2]=0.031*0.031;  //SigmaY2
+         lp[3]=1.15*1.15;  //SigmaZ2
+         lp[5]=-0.036;
+         
+         AliITSRecPoint cl2(milab,lp,info);
+         cl2.SetChargeRatio(1.);
+         cl2.SetType(70);        
+         clusters.push_back( cl2 );
+         ncl++;
+       } // cross is within the detector
+       //
+       //--------------
+       
+      } // end loop over Nside 1D clusters
+      
+    } // bad Pside module
+    
+    else if( (countNbad>700) && (countPbad<100) ) { // bad Nside!!
+      
+      for (Int_t j=0; j<nn; j++) { // loop over Pside 1D clusters with no crosses
+       if(cpositive[j]) continue;
+       
+       Float_t xt, zt;
+       Float_t yP=neg[j].GetY();       
+       Float_t yN=0.;
+       if (seg->GetLayer()==5) yN = yP - (7.6/1.9);
+       else yN = yP + (7.6/1.9);
+       seg->GetPadCxz(yP, yN, xt, zt); 
+       
+       if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
+         Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
+         mT2L->MasterToLocal(loc,trk);
+         lp[0]=trk[1];
+         lp[1]=trk[2];        
+         lp[4]=neg[j].GetQ(); //Q
+         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
+         for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = neg[j].GetLabel(ilab);   
+         CheckLabels2(milab);
+         milab[3]=( j << 10 ) + idet; // pos|neg|det
+         Int_t info[3] = {0,(Int_t)neg[j].GetNd(),fNlayer[fModule]};
+         
+         lp[2]=0.0085*0.0085;  //SigmaY2
+         lp[3]=1.15*1.15;  //SigmaZ2
+         lp[5]=0.0093;
+         
+         AliITSRecPoint cl2(milab,lp,info);        
+         cl2.SetChargeRatio(1.);
+         cl2.SetType(80);        
+         clusters.push_back( cl2 );
+         ncl++;
+       } // cross is within the detector
+       //
+       //--------------
+       
+      } // end loop over Pside 1D clusters
+      
+    } // bad Nside module
+    
+    //---------------------------------------------------------
+    
+  } // use bad channels
+
+  //cout<<ncl<<" clusters for this module"<<endl;
+
+  delete [] cnegative;
+  delete [] cused1;
+  delete [] negativepair;
+  delete [] cpositive;
+  delete [] cused2;
+  delete [] positivepair;
+
+}
diff --git a/HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.h b/HLT/ITS/clusterfinders/AliHLTITSClusterFinderSSD.h
new file mode 100644 (file)
index 0000000..3758a8c
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef ALIHLTITSCLUSTERFINDERSSD_H
+#define ALIHLTITSCLUSTERFINDERSSD_H
+/* Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id: AliHLTITSClusterFinderSSD.h 32604 2009-05-29 10:41:46Z masera $ */
+
+//--------------------------------------------------------------
+//                       ITS clusterer V2 for SSD
+//
+//   This can be a "wrapping" for the V1 cluster finding classes
+//   if compiled with uncommented "#define V1" line 
+//   in the AliITSclustererV2.cxx file.
+//
+//   Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch 
+//--------------------------------------------------------------
+#include "AliITSClusterFinder.h"
+#include <vector>
+
+class TClonesArray;
+class AliRawReader;
+class AliITSRawStream;
+class AliITSRawStreamSSD;
+class AliITSCalibrationSSD;
+class AliITSRecoParam;
+
+class AliHLTITSClusterFinderSSD : public AliITSClusterFinder {
+public:
+  AliHLTITSClusterFinderSSD(AliITSDetTypeRec* dettyp, AliRawReader *reader);
+  virtual ~AliHLTITSClusterFinderSSD();
+  virtual void FindRawClusters(Int_t /*mod*/){;}
+  virtual void RawdataToClusters(AliRawReader* /*rawReader*/,TClonesArray** /*clusters*/){;}
+
+  virtual void RawdataToClusters( std::vector<AliITSRecPoint> &clusters);
+ protected:
+
+  void FindClustersSSD(Ali1Dcluster* neg, Int_t nn, 
+                      Ali1Dcluster* pos, Int_t np,
+                      std::vector<AliITSRecPoint> &);
+
+  AliITSRecoParam *fRecoParam; //!
+  AliRawReader *fRawReader; //!
+  AliITSRawStreamSSD *fRawStream;//!
+
+  Int_t fLastSSD1;        //index of the last SSD1 detector   
+  static Short_t* fgPairs;       //array used to build positive-negative pairs
+  static Int_t    fgPairsSize;    //actual size of pairs array
+  static const Float_t fgkCosmic2008StripShifts[16][9]; // Shifts for 2007/2008 Cosmic data (timing problem)
+  static const Float_t fgkThreshold; // threshold for the seed
+
+ private:
+  AliHLTITSClusterFinderSSD(const AliHLTITSClusterFinderSSD& );
+  AliHLTITSClusterFinderSSD& operator=(const AliHLTITSClusterFinderSSD&  );
+
+  ClassDef(AliHLTITSClusterFinderSSD,0)  // ITS cluster finder V2 for SDD
+};
+
+#endif
index 44ee6f9..5c43d38 100644 (file)
@@ -17,6 +17,7 @@ CLASS_HDRS:=          AliHLTITStrack.h \
                tracking/AliHLTITSLayer.h \
                tracking/AliHLTITSTrack.h \
                clusterfinders/AliHLTITSClusterFinderSPD.h \
+               clusterfinders/AliHLTITSClusterFinderSSD.h \
                AliHLTITSVertexerSPDComponent.h 
 
 MODULE_SRCS=   $(CLASS_HDRS:.h=.cxx)