1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /**************************************************************************
17 * The package was revised and changed by Boris Batiounia in the time *
18 * period of March - June 2001 *
19 **************************************************************************/
26 #include "AliITSdigit.h"
27 #include "AliITSRawCluster.h"
28 #include "AliITSRecPoint.h"
29 #include "AliITSMapA1.h"
30 #include "AliITSClusterFinderSSD.h"
31 #include "AliITSclusterSSD.h"
32 #include "AliITSpackageSSD.h"
33 #include "AliITSsegmentation.h"
34 #include "AliITSgeom.h"
36 const Bool_t AliITSClusterFinderSSD::fgkSIDEP=kTRUE;
37 const Bool_t AliITSClusterFinderSSD::fgkSIDEN=kFALSE;
40 ClassImp(AliITSClusterFinderSSD)
42 //____________________________________________________________________
45 //____________________________________________________________________
49 AliITSClusterFinderSSD::AliITSClusterFinderSSD(AliITSsegmentation *seg, TClonesArray *digits)
51 //Standard constructor
56 fMap = new AliITSMapA1(fSegmentation,fDigits);
58 fITS=(AliITS*)gAlice->GetModule("ITS");
60 fClusterP = new TClonesArray ("AliITSclusterSSD",200);
63 fClusterN= new TClonesArray ("AliITSclusterSSD",200);
66 fPackages = new TClonesArray ("AliITSpackageSSD",200); //packages
70 fDigitsIndexP = new TArrayI(300);
73 fDigitsIndexN = new TArrayI(300);
76 fPitch = fSegmentation->Dpx(0);
77 fPNsignalRatio=7./8.; // warning: hard-wired number
81 //-------------------------------------------------------
82 AliITSClusterFinderSSD::~AliITSClusterFinderSSD() {
94 //-------------------------------------------------------
95 void AliITSClusterFinderSSD::InitReconstruction()
97 // initialization of the cluster finder
99 register Int_t i; //iterator
101 for (i=0;i<fNClusterP;i++)
103 fClusterP->RemoveAt(i);
106 for (i=0;i<fNClusterN;i++)
108 fClusterN->RemoveAt(i);
112 for (i=0;i<fNPackages;i++)
114 fPackages->RemoveAt(i);
121 Float_t StereoP,StereoN;
122 fSegmentation->Angles(StereoP,StereoN);
124 CalcStepFactor (StereoP,StereoN);
126 if (debug) cout<<"fSFF = "<<fSFF<<" fSFB = "<<fSFB<<"\n";
130 //---------------------------------------------
131 void AliITSClusterFinderSSD::FindRawClusters(Int_t module)
133 // This function findes out all clusters belonging to one module
134 // 1. Zeroes all space after previous module reconstruction
135 // 2. Finds all neighbouring digits, create clusters
136 // 3. If necesery, resolves for each group of neighbouring digits
137 // how many clusters creates it.
138 // 4. Colculate the x and z coordinate
139 Int_t lay, lad, detect;
140 AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
141 AliITSgeom *geom = aliITS->GetITSgeom();
143 geom->GetModuleId(module,lay, lad, detect);
145 //cout<<"FindRawCl: layer,module ="<<lay<<","<<module<<endl;
148 ((AliITSsegmentationSSD*)fSegmentation)->SetLayer(6);
150 ((AliITSsegmentationSSD*)fSegmentation)->SetLayer(5);
152 InitReconstruction(); //ad. 1
156 FindNeighbouringDigits(); //ad. 2
157 //SeparateOverlappedClusters(); //ad. 3
158 ClustersToPackages(); //ad. 4
163 //-------------------------------------------------
164 void AliITSClusterFinderSSD::FindNeighbouringDigits()
166 //If there are any digits on this side, create 1st Cluster,
167 // add to it this digit, and increment number of clusters
173 if ((fNDigitsP>0 ) && (fNDigitsN > 0 )) {
175 Int_t currentstripNo;
176 Int_t *dbuffer = new Int_t [300]; //buffer for strip numbers
177 Int_t dnumber; //curent number of digits in buffer
178 TArrayI &lDigitsIndexP = *fDigitsIndexP;
179 TArrayI &lDigitsIndexN = *fDigitsIndexN;
180 TObjArray &lDigits = *(Digits());
181 TClonesArray &lClusterP = *fClusterP;
182 TClonesArray &lClusterN = *fClusterN;
186 dbuffer[0]=lDigitsIndexP[0];
187 //If next digit is a neighbour of previous, adds to last cluster this digit
188 for (i=1; i<fNDigitsP; i++) {
190 currentstripNo = ((AliITSdigitSSD*)lDigits[lDigitsIndexP[i]])->
192 //check if it is a neighbour of a previous one
193 if ( (((AliITSdigitSSD*)lDigits[lDigitsIndexP[i-1]])->GetStripNumber())
194 == (currentstripNo-1) ) dbuffer[dnumber++]=lDigitsIndexP[i];
196 //create a new one side cluster
197 new(lClusterP[fNClusterP++]) AliITSclusterSSD(dnumber,dbuffer,Digits(),fgkSIDEP);
198 dbuffer[0]=lDigitsIndexP[i];
201 } // end loop over fNDigitsP
202 new(lClusterP[fNClusterP++]) AliITSclusterSSD(dnumber,dbuffer,Digits(),fgkSIDEP);
206 //for comments, see above
208 dbuffer[0]=lDigitsIndexN[0];
209 //If next digit is a neighbour of previous, adds to last cluster this digit
210 for (i=1; i<fNDigitsN; i++) {
211 currentstripNo = ((AliITSdigitSSD*)(lDigits[lDigitsIndexN[i]]))->
213 if ( (((AliITSdigitSSD*)lDigits[lDigitsIndexN[i-1]])->GetStripNumber())
214 == (currentstripNo-1) ) dbuffer[dnumber++]=lDigitsIndexN[i];
216 new(lClusterN[fNClusterN++]) AliITSclusterSSD(dnumber,dbuffer,Digits(),fgkSIDEN);
217 dbuffer[0]=lDigitsIndexN[i];
220 } // end loop over fNDigitsN
221 new(lClusterN[fNClusterN++]) AliITSclusterSSD(dnumber,dbuffer,Digits(),fgkSIDEN);
224 } // end condition on NDigits
226 if (debug) cout<<"\n Found clusters: fNClusterP = "<<fNClusterP<<" fNClusterN ="<<fNClusterN<<"\n";
230 //--------------------------------------------------------------
232 void AliITSClusterFinderSSD::SeparateOverlappedClusters()
234 // overlapped clusters separation
236 register Int_t i; //iterator
238 Float_t factor=0.75; // How many percent must be lower signal
239 // on the middle one digit
240 // from its neighbours
241 Int_t signal0; //signal on the strip before the current one
242 Int_t signal1; //signal on the current one signal
243 Int_t signal2; //signal on the strip after the current one
244 TArrayI *splitlist; // List of splits
245 Int_t numerofsplits=0; // number of splits
246 Int_t initPsize = fNClusterP; //initial size of the arrays
247 Int_t initNsize = fNClusterN; //we have to keep it because it will grow
248 // in this function and it doasn't make
249 // sense to pass through it again
251 splitlist = new TArrayI(300);
253 for (i=0;i<initPsize;i++)
255 if (( ((AliITSclusterSSD*)(*fClusterP)[i])->GetNumOfDigits())==1) continue;
256 if (( ((AliITSclusterSSD*)(*fClusterP)[i])->GetNumOfDigits())==2) continue;
257 Int_t nj=(((AliITSclusterSSD*)(*fClusterP)[i])->GetNumOfDigits()-1);
258 for (Int_t j=1; j<nj; j++)
260 signal1=((AliITSclusterSSD*)(*fClusterP)[i])->GetDigitSignal(j);
261 signal0=((AliITSclusterSSD*)(*fClusterP)[i])->GetDigitSignal(j-1);
262 signal2=((AliITSclusterSSD*)(*fClusterP)[i])->GetDigitSignal(j+1);
263 //if signal is less then factor*signal of its neighbours
264 if ( (signal1<(factor*signal0)) && (signal1<(factor*signal2)) )
266 (*splitlist)[numerofsplits++]=j;
268 } // end loop over number of digits
269 //split this cluster if necessary
270 if(numerofsplits>0) SplitCluster(splitlist,numerofsplits,i,fgkSIDEP);
273 //in signed places (splitlist)
274 } // end loop over clusters on Pside
276 for (i=0;i<initNsize;i++) {
277 if (( ((AliITSclusterSSD*)(*fClusterN)[i])->GetNumOfDigits())==1) continue;
278 if (( ((AliITSclusterSSD*)(*fClusterN)[i])->GetNumOfDigits())==2) continue;
279 Int_t nj=(((AliITSclusterSSD*)(*fClusterN)[i])->GetNumOfDigits()-1);
280 for (Int_t j=1; j<nj; j++)
282 signal1=((AliITSclusterSSD*)(*fClusterN)[i])->GetDigitSignal(j);
283 signal0=((AliITSclusterSSD*)(*fClusterN)[i])->GetDigitSignal(j-1);
284 signal2=((AliITSclusterSSD*)(*fClusterN)[i])->GetDigitSignal(j+1);
285 //if signal is less then factor*signal of its neighbours
286 if ( (signal1<(factor*signal0)) && (signal1<(factor*signal2)) )
287 (*splitlist)[numerofsplits++]=j;
288 } // end loop over number of digits
289 //split this cluster into more clusters
290 if(numerofsplits>0) SplitCluster(splitlist,numerofsplits,i,fgkSIDEN);
291 numerofsplits=0; //in signed places (splitlist)
292 } // end loop over clusters on Nside
297 //-------------------------------------------------------
298 void AliITSClusterFinderSSD::SplitCluster(TArrayI *list, Int_t nsplits, Int_t index, Bool_t side)
300 //This function splits one side cluster into more clusters
301 //number of splits is defined by "nsplits"
302 //Place of splits are defined in the TArray "list"
304 // For further optimisation: Replace this function by two
305 // specialised ones (each for one side)
308 //For comlete comments see AliITSclusterSSD::SplitCluster
311 register Int_t i; //iterator
313 AliITSclusterSSD* curentcluster;
314 Int_t *tmpdigits = new Int_t[100];
316 // side true means P side
318 curentcluster =((AliITSclusterSSD*)((*fClusterP)[index])) ;
319 for (i = nsplits; i>0 ;i--) {
320 NN=curentcluster->SplitCluster((*list)[(i-1)],tmpdigits);
321 new ((*fClusterP)[fNClusterP]) AliITSclusterSSD(NN,tmpdigits,Digits(),side);
322 ( (AliITSclusterSSD*)((*fClusterP)[fNClusterP]) )->
323 SetLeftNeighbour(kTRUE);
324 //if left cluster had neighbour on the right before split
325 //new should have it too
326 if ( curentcluster->GetRightNeighbour() )
327 ( (AliITSclusterSSD*)((*fClusterP)[fNClusterP]) )->
328 SetRightNeighbour(kTRUE);
329 else curentcluster->SetRightNeighbour(kTRUE);
331 } // end loop over nplits
333 curentcluster =((AliITSclusterSSD*)((*fClusterN)[index]));
334 for (i = nsplits; i>0 ;i--) {
335 NN=curentcluster->SplitCluster((*list)[(i-1)],tmpdigits);
336 new ((*fClusterN)[fNClusterN]) AliITSclusterSSD(NN,tmpdigits,Digits(),side);
337 ((AliITSclusterSSD*)((*fClusterN)[fNClusterN]))->
338 SetRightNeighbour(kTRUE);
339 if (curentcluster->GetRightNeighbour())
340 ( (AliITSclusterSSD*)( (*fClusterN)[fNClusterN]) )->
341 SetRightNeighbour(kTRUE);
342 else curentcluster->SetRightNeighbour(kTRUE);
344 } // end loop over nplits
351 //-------------------------------------------------
352 Int_t AliITSClusterFinderSSD::SortDigitsP(Int_t start, Int_t end)
354 // sort digits on the P side
359 if (start != (end - 1) )
361 left=this->SortDigitsP(start,(start+end)/2);
362 right=this->SortDigitsP((start+end)/2,end);
363 return (left || right);
367 left = ((AliITSdigitSSD*)((*(Digits()))[(*fDigitsIndexP)[start]]))->GetStripNumber();
368 right= ((AliITSdigitSSD*)((*(Digits()))[(*fDigitsIndexP)[end]]))->GetStripNumber();
371 Int_t tmp = (*fDigitsIndexP)[start];
372 (*fDigitsIndexP)[start]=(*fDigitsIndexP)[end];
373 (*fDigitsIndexP)[end]=tmp;
381 //--------------------------------------------------
383 Int_t AliITSClusterFinderSSD::SortDigitsN(Int_t start, Int_t end)
385 // sort digits on the N side
389 if (start != (end - 1))
391 left=this->SortDigitsN(start,(start+end)/2);
392 right=this->SortDigitsN((start+end)/2,end);
393 return (left || right);
397 left =((AliITSdigitSSD*)((*(Digits()))[(*fDigitsIndexN)[start]]))->GetStripNumber();
398 right=((AliITSdigitSSD*)((*(Digits()))[(*fDigitsIndexN)[end]]))->GetStripNumber();
401 Int_t tmp = (*fDigitsIndexN)[start];
402 (*fDigitsIndexN)[start]=(*fDigitsIndexN)[end];
403 (*fDigitsIndexN)[end]=tmp;
410 //------------------------------------------------
411 void AliITSClusterFinderSSD::FillDigitsIndex()
413 //Fill the indexes of the clusters belonging to a given ITS module
420 N = fDigits->GetEntriesFast();
422 Int_t* PSidx = new Int_t [N*sizeof(Int_t)];
423 Int_t* NSidx = new Int_t [N*sizeof(Int_t)];
424 if (fDigitsIndexP==NULL) fDigitsIndexP = new TArrayI(N);
425 if (fDigitsIndexN==NULL) fDigitsIndexN = new TArrayI(N);
429 for ( i = 0 ; i< N; i++ ) {
430 dig = (AliITSdigitSSD*)GetDigit(i);
433 tmp=dig->GetStripNumber();
434 // I find this totally unnecessary - it's just a
435 // CPU consuming double check
440 if (debug) cout<<"Such a digit exists \n";
446 fDigitsIndexP->AddAt(i,fNDigitsP++);
451 tmp=dig->GetStripNumber();
457 if (debug) cout<<"Such a digit exists \n";
463 fDigitsIndexN->AddAt(i,fNDigitsN++);
472 if (debug) cout<<"Digits : P = "<<fNDigitsP<<" N = "<<fNDigitsN<<endl;
477 //-------------------------------------------
479 void AliITSClusterFinderSSD::SortDigits()
485 for (i=0;i<fNDigitsP-1;i++)
486 if (SortDigitsP(0,(fNDigitsP-1-i))==0) break;
489 for (i=0;i<fNDigitsN-1;i++)
490 if(SortDigitsN(0,(fNDigitsN-1-i))==0) break;
495 //----------------------------------------------
496 void AliITSClusterFinderSSD::FillClIndexArrays(Int_t* arrayP, Int_t *arrayN)
498 // fill cluster index array
501 for (i=0; i<fNClusterP;i++)
505 for (i=0; i<fNClusterN;i++)
512 //------------------------------------------------------
513 void AliITSClusterFinderSSD::SortClusters(Int_t* arrayP, Int_t *arrayN)
519 for (i=0;i<fNClusterP-1;i++)
520 if (SortClustersP(0,(fNClusterP-1),arrayP)==0) break;
524 for (i=0;i<fNClusterN-1;i++)
525 if (SortClustersN(0,(fNClusterN-1),arrayN)==0) break;
531 //---------------------------------------------------
532 Int_t AliITSClusterFinderSSD::SortClustersP(Int_t start, Int_t end, Int_t *array)
534 //Sort P side clusters
539 if (start != (end - 1) ) {
540 left=this->SortClustersP(start,(start+end)/2,array);
541 right=this->SortClustersP((start+end)/2,end,array);
542 return (left || right);
544 left =((AliITSclusterSSD*)((*fClusterP)[array[start]]))->
546 right=((AliITSclusterSSD*)((*fClusterP)[array[ end ]]))->
549 Int_t tmp = array[start];
550 array[start]=array[end];
561 //-------------------------------------------------------
562 Int_t AliITSClusterFinderSSD::SortClustersN(Int_t start, Int_t end, Int_t *array)
564 //Sort N side clusters
570 if (start != (end - 1) ) {
571 left=this->SortClustersN(start,(start+end)/2,array);
572 right=this->SortClustersN((start+end)/2,end,array);
573 return (left || right);
575 left =((AliITSclusterSSD*)((*fClusterN)[array[start]]))->
577 right=((AliITSclusterSSD*)((*fClusterN)[array[ end ]]))->
580 Int_t tmp = array[start];
581 array[start]=array[end];
591 //-------------------------------------------------------
592 void AliITSClusterFinderSSD::ClustersToPackages()
596 Int_t *oneSclP = new Int_t[fNClusterP]; //I want to have sorted 1 S clusters
597 Int_t *oneSclN = new Int_t[fNClusterN]; //I can not sort it in TClonesArray
598 //so, I create table of indexes and
600 //I do not use TArrayI on purpose
601 // MB: well, that's not true that one
602 //cannot sort objects in TClonesArray
604 AliITSclusterSSD *currentP;
605 AliITSclusterSSD *currentN;
608 //Fills in One Side Clusters Index Array
609 FillClIndexArrays(oneSclP,oneSclN);
610 //Sorts filled Arrays
611 //SortClusters(oneSclP,oneSclN);
614 new ((*fPackages)[0]) AliITSpackageSSD(fClusterP,fClusterN);
617 //This part was includede by Boris Batiounia in March 2001.
619 // Take all recpoint pairs (x coordinates) in both P and N sides
620 // to calculate z coordinates of the recpoints
622 for (j1=0;j1<fNClusterP;j1++) {
623 currentP = GetPSideCluster(oneSclP[j1]);
624 Double_t xP = currentP->GetPosition();
625 Float_t signalP = currentP->GetTotalSignal();
626 for (j2=0;j2<fNClusterN;j2++) {
627 currentN = GetNSideCluster(oneSclN[j2]);
628 Double_t xN = currentN->GetPosition();
629 Float_t signalN = currentN->GetTotalSignal();
630 CreateNewRecPoint(xP,1,xN,1,signalP,signalN,currentP, currentN, 0.75);
641 //------------------------------------------------------
642 Bool_t AliITSClusterFinderSSD::
643 CreateNewRecPoint(Float_t P, Float_t dP, Float_t N, Float_t dN,
644 Float_t SigP,Float_t SigN,
645 AliITSclusterSSD *clusterP, AliITSclusterSSD *clusterN,
648 // create the recpoints
649 const Float_t kADCtoKeV = 2.16;
650 // 50 ADC units -> 30000 e-h pairs; 1e-h pair -> 3.6e-3 KeV;
651 // 1 ADC unit -> (30000/50)*3.6e-3 = 2.16 KeV
652 const Float_t kconv = 1.0e-4;
654 const Float_t kRMSx = 20.0*kconv;
655 const Float_t kRMSz = 800.0*kconv;
661 if (GetCrossing(P,N)) {
663 //GetCrossingError(dP,dN);
664 AliITSRawClusterSSD cnew;
665 Int_t nstripsP=clusterP->GetNumOfDigits();
666 Int_t nstripsN=clusterN->GetNumOfDigits();
673 dedx = SigP*kADCtoKeV;
676 dedx = SigN*kADCtoKeV;
679 tr = (Int_t*) clusterP->GetTracks(n);
680 NTracks = clusterP->GetNTracks();
684 cnew.fMultiplicity=nstripsP;
685 cnew.fMultiplicityN=nstripsN;
686 cnew.fQErr=TMath::Abs(SigP-SigN);
687 cnew.fNtracks=NTracks;
689 fITS->AddCluster(2,&cnew);
696 rnew.SetSigmaX2( kRMSx* kRMSx);
697 rnew.SetSigmaZ2( kRMSz* kRMSz);
698 rnew.fTracks[0]=tr[0];
699 rnew.fTracks[1]=tr[1];
700 rnew.fTracks[2]=tr[2];
702 fITS->AddRecPoint(rnew);
711 //------------------------------------------------------
712 void AliITSClusterFinderSSD::CalcStepFactor(Float_t Psteo, Float_t Nsteo )
714 // calculate the step factor for matching clusters
717 // 95 is the pitch, 4000 - dimension along z ?
720 Float_t dz=fSegmentation->Dz();
722 fSFF = ( (Int_t) (Psteo*dz/fPitch ) );// +1;
723 fSFB = ( (Int_t) (Nsteo*dz/fPitch ) );// +1;
728 //-----------------------------------------------------------
729 AliITSclusterSSD* AliITSClusterFinderSSD::GetPSideCluster(Int_t idx)
731 // get P side clusters
736 if((idx<0)||(idx>=fNClusterP))
738 printf("AliITSClusterFinderSSD::GetPSideCluster : index out of range\n");
743 return (AliITSclusterSSD*)((*fClusterP)[idx]);
747 //-------------------------------------------------------
748 AliITSclusterSSD* AliITSClusterFinderSSD::GetNSideCluster(Int_t idx)
750 // get N side clusters
752 if((idx<0)||(idx>=fNClusterN))
754 printf("AliITSClusterFinderSSD::GetNSideCluster : index out of range\n");
759 return (AliITSclusterSSD*)((*fClusterN)[idx]);
763 //--------------------------------------------------------
764 AliITSclusterSSD* AliITSClusterFinderSSD::GetCluster(Int_t idx, Bool_t side)
768 return (side) ? GetPSideCluster(idx) : GetNSideCluster(idx);
771 //_______________________________________________________________________
773 Bool_t AliITSClusterFinderSSD::GetCrossing (Float_t &P, Float_t &N)
777 // This function was rivised and changed by Boris Batiounia in March 2001
781 Float_t Dx = fSegmentation->Dx(); // detector size in x direction, microns
782 Float_t Dz = fSegmentation->Dz(); // detector size in z direction, microns
784 Float_t xL; // x local coordinate
785 Float_t zL; // z local coordinate
786 Float_t x; // x = xL + Dx/2
787 Float_t z; // z = zL + Dz/2
788 Float_t xP; // x coordinate in the P side from the first P strip
789 Float_t xN; // x coordinate in the N side from the first N strip
790 Float_t StereoP,StereoN;
792 fSegmentation->Angles(StereoP,StereoN);
793 fTanP=TMath::Tan(StereoP);
794 fTanN=TMath::Tan(StereoN);
795 Float_t kP = fTanP; // Tangent of 0.0075 mrad
796 Float_t kN = fTanN; // Tangent of 0.0275 mrad
801 xP = N; // change the mistake for the P/N
802 xN = P; // coordinates correspondence in this function
804 x = xP + kP*(Dz*kN-xP+xN)/(kP+kN);
805 z = (Dz*kN-xP+xN)/(kP+kN);
811 if(TMath::Abs(xL) > Dx/2 || TMath::Abs(zL) > Dz/2) return kFALSE;
813 // Check that xL and zL are inside the detector for the
814 // correspondent xP and xN coordinates
820 //_________________________________________________________________________
822 void AliITSClusterFinderSSD::GetCrossingError(Float_t& dP, Float_t& dN)
824 // get crossing error
828 dz = TMath::Abs(( dP + dN )*fPitch/(fTanP + fTanN) );
829 dx = fPitch*(TMath::Abs(dP*(1 - fTanP/(fTanP + fTanN))) +
830 TMath::Abs(dN *fTanP/(fTanP + fTanN) ));