+
+//______________________________________________________________________
+void AliITSClusterFinder::Print(ostream *os) const{
+ //Standard output format for this class
+ // Inputs:
+ // ostream *os Output stream
+ // Output:
+ // ostream *os Output stream
+ // Return:
+ // none.
+
+ *os << fModule<<",";
+ *os << fNdigits<<",";
+ *os << fNPeaks<<endl;
+}
+//______________________________________________________________________
+void AliITSClusterFinder::Read(istream *is) {
+ //Standard input for this class
+ // Inputs:
+ // istream *is Input stream
+ // Output:
+ // istream *is Input stream
+ // Return:
+ // none.
+
+ *is >> fModule;
+ *is >> fNdigits;
+ *is >> fNPeaks;
+}
+//______________________________________________________________________
+ostream &operator<<(ostream &os,AliITSClusterFinder &source){
+ // Standard output streaming function.
+ // Inputs:
+ // ostream *os Output stream
+ // AliITSClusterFinder &source Class to be printed
+ // Output:
+ // ostream *os Output stream
+ // Return:
+ // none.
+
+ source.Print(&os);
+ return os;
+}
+//______________________________________________________________________
+istream &operator>>(istream &is,AliITSClusterFinder &source){
+ // Standard output streaming function.
+ // Inputs:
+ // istream *is Input stream
+ // AliITSClusterFinder &source Class to be read in.
+ // Output:
+ // istream *is Input stream
+ // Return:
+ // none.
+
+ source.Read(&is);
+ return is;
+}
+
+//______________________________________________________________________
+void AliITSClusterFinder::CheckLabels2(Int_t lab[10])
+{
+ //------------------------------------------------------------
+ // Tries to find mother's labels
+ //------------------------------------------------------------
+ AliRunLoader *rl = AliRunLoader::Instance();
+ if(!rl) return;
+ TTree *trK=(TTree*)rl->TreeK();
+ if (!trK) return;
+ //
+ int labS[10];
+ Int_t nlabels = 0;
+ Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
+ for (Int_t i=0;i<10;i++) if (lab[i]>=0) labS[nlabels++] = lab[i];
+ if (nlabels==0) return;
+ //
+ float mom[10];
+ for (Int_t i=0;i<nlabels;i++) {
+ Int_t label = labS[i];
+ mom[i] = 0;
+ if (label>=ntracks) continue;
+ TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
+ mom[i] = part->P();
+ if (part->P() < 0.02) { // reduce soft particles from the same cluster
+ Int_t m=part->GetFirstMother();
+ if (m<0) continue; // primary
+ //
+ if (part->GetStatusCode()>0) continue;
+ //
+ // if the parent is within the same cluster, reassign the label to it
+ for (int j=0;j<nlabels;j++) if (labS[j]==m) { labS[i] = m; break; }
+ }
+ }
+ //
+ if (nlabels>3) { // only 3 labels are stored in cluster, sort in decreasing momentum
+ int ind[10],labSS[10];
+ TMath::Sort(nlabels,mom,ind);
+ for (int i=nlabels;i--;) labSS[i] = labS[i];
+ for (int i=0;i<nlabels;i++) labS[i] = labSS[ind[i]];
+ }
+ //
+ //compress labels -- if multi-times the same
+ for (Int_t i=0;i<10;i++) lab[i]=-2;
+ int nlabFin=0,j=0;
+ for (int i=0;i<nlabels;i++) {
+ for (j=0;j<nlabFin;j++) if (labS[i]==lab[j]) break; // the label already there
+ if (j==nlabFin) lab[nlabFin++] = labS[i];
+ }
+ //
+}
+
+//______________________________________________________________________
+void AliITSClusterFinder::AddLabel(Int_t lab[10], Int_t label) {
+ //add label to the cluster
+ AliRunLoader *rl = AliRunLoader::Instance();
+ TTree *trK=(TTree*)rl->TreeK();
+ if(trK){
+ if(label<0) return; // In case of no label just exit
+
+ Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
+ if (label>ntracks) return;
+ for (Int_t i=0;i<10;i++){
+ // if (label<0) break;
+ if (lab[i]==label) break;
+ if (lab[i]<0) {
+ lab[i]= label;
+ break;
+ }
+ }
+ }
+}
+
+
+//______________________________________________________________________
+void AliITSClusterFinder::
+FindCluster(Int_t k,Int_t maxz,AliBin *bins,Int_t &n,Int_t *idx) {
+ //------------------------------------------------------------
+ // returns an array of indices of digits belonging to the cluster
+ // (needed when the segmentation is not regular)
+ //------------------------------------------------------------
+ if (n<200) idx[n++]=bins[k].GetIndex();
+ bins[k].Use();
+
+ if (bins[k-maxz].IsNotUsed()) FindCluster(k-maxz,maxz,bins,n,idx);
+ if (bins[k-1 ].IsNotUsed()) FindCluster(k-1 ,maxz,bins,n,idx);
+ if (bins[k+maxz].IsNotUsed()) FindCluster(k+maxz,maxz,bins,n,idx);
+ if (bins[k+1 ].IsNotUsed()) FindCluster(k+1 ,maxz,bins,n,idx);
+ /*
+ if (bins[k-maxz-1].IsNotUsed()) FindCluster(k-maxz-1,maxz,bins,n,idx);
+ if (bins[k-maxz+1].IsNotUsed()) FindCluster(k-maxz+1,maxz,bins,n,idx);
+ if (bins[k+maxz-1].IsNotUsed()) FindCluster(k+maxz-1,maxz,bins,n,idx);
+ if (bins[k+maxz+1].IsNotUsed()) FindCluster(k+maxz+1,maxz,bins,n,idx);
+ */
+}
+
+//______________________________________________________________________
+Bool_t AliITSClusterFinder::IsMaximum(Int_t k,Int_t max,const AliBin *bins) {
+ //------------------------------------------------------------
+ //is this a local maximum ?
+ //------------------------------------------------------------
+ UShort_t q=bins[k].GetQ();
+ if (q==1023) return kFALSE;
+ if (bins[k-max].GetQ() > q) return kFALSE;
+ if (bins[k-1 ].GetQ() > q) return kFALSE;
+ if (bins[k+max].GetQ() > q) return kFALSE;
+ if (bins[k+1 ].GetQ() > q) return kFALSE;
+ if (bins[k-max-1].GetQ() > q) return kFALSE;
+ if (bins[k+max-1].GetQ() > q) return kFALSE;
+ if (bins[k+max+1].GetQ() > q) return kFALSE;
+ if (bins[k-max+1].GetQ() > q) return kFALSE;
+ return kTRUE;
+}
+
+//______________________________________________________________________
+void AliITSClusterFinder::
+FindPeaks(Int_t k,Int_t max,AliBin *b,Int_t *idx,UInt_t *msk,Int_t& n) {
+ //------------------------------------------------------------
+ //find local maxima
+ //------------------------------------------------------------
+ if (n<31)
+ if (IsMaximum(k,max,b)) {
+ idx[n]=k; msk[n]=(2<<n);
+ n++;
+ }
+ b[k].SetMask(0);
+ if (b[k-max].GetMask()&1) FindPeaks(k-max,max,b,idx,msk,n);
+ if (b[k-1 ].GetMask()&1) FindPeaks(k-1 ,max,b,idx,msk,n);
+ if (b[k+max].GetMask()&1) FindPeaks(k+max,max,b,idx,msk,n);
+ if (b[k+1 ].GetMask()&1) FindPeaks(k+1 ,max,b,idx,msk,n);
+}
+
+//______________________________________________________________________
+void AliITSClusterFinder::
+MarkPeak(Int_t k, Int_t max, AliBin *bins, UInt_t m) {
+ //------------------------------------------------------------
+ //mark this peak
+ //------------------------------------------------------------
+ UShort_t q=bins[k].GetQ();
+
+ bins[k].SetMask(bins[k].GetMask()|m);
+
+ if (bins[k-max].GetQ() <= q)
+ if ((bins[k-max].GetMask()&m) == 0) MarkPeak(k-max,max,bins,m);
+ if (bins[k-1 ].GetQ() <= q)
+ if ((bins[k-1 ].GetMask()&m) == 0) MarkPeak(k-1 ,max,bins,m);
+ if (bins[k+max].GetQ() <= q)
+ if ((bins[k+max].GetMask()&m) == 0) MarkPeak(k+max,max,bins,m);
+ if (bins[k+1 ].GetQ() <= q)
+ if ((bins[k+1 ].GetMask()&m) == 0) MarkPeak(k+1 ,max,bins,m);
+}
+
+//______________________________________________________________________
+void AliITSClusterFinder::
+MakeCluster(Int_t k,Int_t max,AliBin *bins,UInt_t m,AliITSRecPoint &c) {
+ //------------------------------------------------------------
+ //make cluster using digits of this peak
+ //------------------------------------------------------------
+ Float_t q=(Float_t)bins[k].GetQ();
+ Int_t i=k/max, j=k-i*max;
+ if(c.GetQ()<0.01){ // first entry in cluster
+ fXmin=i;
+ fXmax=i;
+ fZmin=j;
+ fZmax=j;
+ }else{ // check cluster extension
+ if(i<fXmin) fXmin=i;
+ if(i>fXmax) fXmax=i;
+ if(j<fZmin) fZmin=j;
+ if(j>fZmax) fZmax=j;
+ }
+ c.SetQ(c.GetQ()+q);
+ c.SetY(c.GetY()+i*q);
+ c.SetZ(c.GetZ()+j*q);
+ c.SetSigmaY2(c.GetSigmaY2()+i*i*q);
+ c.SetSigmaZ2(c.GetSigmaZ2()+j*j*q);
+
+ bins[k].SetMask(0xFFFFFFFE);
+
+ if (bins[k-max].GetMask() == m) MakeCluster(k-max,max,bins,m,c);
+ if (bins[k-1 ].GetMask() == m) MakeCluster(k-1 ,max,bins,m,c);
+ if (bins[k+max].GetMask() == m) MakeCluster(k+max,max,bins,m,c);
+ if (bins[k+1 ].GetMask() == m) MakeCluster(k+1 ,max,bins,m,c);
+}