8 #include <AliITSUSegmentationPix.h>
9 #include "AliITSUClusterizer.h"
10 #include "AliITSUClusterPix.h"
11 #include "AliITSUGeomTGeo.h"
12 #include "AliITSUSegmentationPix.h"
13 #include "AliITSdigit.h"
14 #include "AliITSURecoParam.h"
15 #include "AliITSUAux.h"
16 using namespace TMath;
17 using namespace AliITSUAux;
19 ClassImp(AliITSUClusterizer)
21 //______________________________________________________________________________
22 AliITSUClusterizer::AliITSUClusterizer(Int_t initNRow)
24 ,fAllowDiagonalClusterization(kFALSE)
28 ,fInputDigitsReadIndex(0)
37 ,fDigitFreelistBptrFirst(0)
38 ,fDigitFreelistBptrLast(0)
41 #ifdef _ClusterTopology_
47 #endif //_ClusterTopology_
54 //______________________________________________________________________________
55 void AliITSUClusterizer::SetSegmentation(const AliITSUSegmentationPix *segm)
57 // attach segmentation, if needed, reinitialize array
59 SetNRow(fSegm->GetNRow()); // reinitialize if needed
63 //______________________________________________________________________________
64 void AliITSUClusterizer::SetNRow(Int_t nr)
67 int nrOld = GetUniqueID();
68 if (nrOld>=nr) return;
70 while (fDigitFreelistBptrFirst) {
71 AliITSUClusterizerClusterDigit *next = fDigitFreelistBptrFirst[kDigitChunkSize-1].fNext;
72 delete[] fDigitFreelistBptrFirst;
73 fDigitFreelistBptrFirst=next;
75 delete[] fPartFreelistBptr;
76 delete[] fCandFreelistBptr;
78 fPartFreelist=fPartFreelistBptr = new AliITSUClusterizerClusterPart[nr+1];
79 fCandFreelist=fCandFreelistBptr = new AliITSUClusterizerClusterCand[nr+1];
80 for (int i=0;i<nr;++i) {
81 fPartFreelistBptr[i].fNextInRow = &fPartFreelistBptr[i+1];
82 fCandFreelistBptr[i].fNext = &fCandFreelistBptr[i+1];
86 //______________________________________________________________________________
87 AliITSUClusterizer::~AliITSUClusterizer()
90 while (fDigitFreelistBptrFirst) {
91 AliITSUClusterizerClusterDigit *next = fDigitFreelistBptrFirst[kDigitChunkSize-1].fNext;
92 delete[] fDigitFreelistBptrFirst;
93 fDigitFreelistBptrFirst=next;
95 delete[] fPartFreelistBptr;
96 delete[] fCandFreelistBptr;
98 #ifdef _ClusterTopology_
100 #endif //_ClusterTopology_
103 //______________________________________________________________________________
104 AliITSUClusterizer::AliITSUClusterizerClusterDigit* AliITSUClusterizer::AllocDigitFreelist()
106 // allocate aux space
107 AliITSUClusterizerClusterDigit *tmp = new AliITSUClusterizerClusterDigit[kDigitChunkSize];
108 for (int i=0;i<kDigitChunkSize-2;++i) tmp[i].fNext=&tmp[i+1];
109 tmp[kDigitChunkSize-2].fNext=0;
110 tmp[kDigitChunkSize-1].fNext=0;
111 if (!fDigitFreelistBptrFirst) fDigitFreelistBptrFirst=tmp;
112 else fDigitFreelistBptrLast[kDigitChunkSize-1].fNext=tmp;
113 fDigitFreelistBptrLast=tmp;
117 //______________________________________________________________________________
118 AliITSUClusterizer::AliITSUClusterizerClusterDigit* AliITSUClusterizer::NextDigit()
121 if (fInputDigitsReadIndex<fInputDigits->GetEntriesFast()) {
122 AliITSdigit *tmp=static_cast<AliITSdigit*>(fInputDigits->UncheckedAt(fInputDigitsReadIndex++));
123 AliITSUClusterizerClusterDigit *digit=AllocDigit();
131 //______________________________________________________________________________
132 void AliITSUClusterizer::AttachPartToCand(AliITSUClusterizerClusterCand *cand,AliITSUClusterizerClusterPart *part)
135 part->fParent = cand;
136 part->fPrevInCluster = 0;
137 part->fNextInCluster = cand->fFirstPart;
138 if (cand->fFirstPart) cand->fFirstPart->fPrevInCluster = part;
139 cand->fFirstPart=part;
142 //______________________________________________________________________________
143 void AliITSUClusterizer::MergeCands(AliITSUClusterizerClusterCand *a,AliITSUClusterizerClusterCand *b)
145 // merge cluster parts
146 AliITSUClusterizerClusterPart *ipart=b->fFirstPart;
147 AliITSUClusterizerClusterPart *jpart;
151 } while ((ipart=ipart->fNextInCluster));
152 jpart->fNextInCluster=a->fFirstPart;
153 jpart->fNextInCluster->fPrevInCluster=jpart;
154 a->fFirstPart=b->fFirstPart;
156 b->fLastDigit->fNext=a->fFirstDigit;
157 a->fFirstDigit=b->fFirstDigit;
161 //______________________________________________________________________________
162 void AliITSUClusterizer::Transform(AliITSUClusterPix *cluster,AliITSUClusterizerClusterCand *cand)
164 // convert set of digits to cluster data in LOCAL frame
165 const double k1to12 = 1./12;
166 static int maxLbinDigit = AliITSdigit::GetNTracks();
170 cand->fLastDigit->fNext=0;
171 double x=0,z=0,xmn=1e9,xmx=-1e9,zmn=1e9,zmx=-1e9,px=0,pz=0;
175 for (AliITSUClusterizerClusterDigit *idigit=cand->fFirstDigit;idigit;idigit=idigit->fNext) {
176 AliITSdigit* dig = idigit->fDigit;
177 fSegm->DetToLocal(dig->GetCoord2(),dig->GetCoord1(),cx,cz); // center of pixel
179 // account for possible diod shift
180 double ddx,ddz, dx=fSegm->Dpx(dig->GetCoord2()), dz=fSegm->Dpz(dig->GetCoord1());
181 fSegm->GetDiodShift(dig->GetCoord2(),dig->GetCoord1(),ddx,ddz);
183 charge += dig->GetSignal();
196 for(Int_t dlab=0;dlab<maxLbinDigit;dlab++){
197 Int_t digitlab = (dig->GetTracks())[dlab];
198 if(digitlab<0) continue;
206 double dx = xmx-xmn, dz = zmx-zmn;
209 x *= fac; // mean coordinates
211 px *= fac; // mean pitch
216 x -= fLorAngCorrection; // LorentzAngle correction
220 cluster->SetSigmaZ2(nz>1 ? dz*dz*k1to12 : pz*pz*k1to12);
221 cluster->SetSigmaY2(nx>1 ? dx*dx*k1to12 : px*px*k1to12);
222 cluster->SetSigmaYZ(0);
223 cluster->SetFrameLoc();
224 cluster->SetNxNzN(nx,nz,n);
225 cluster->SetQ(charge); // note: this is MC info
229 int nl = Min(kMaxLabInCluster,fNLabels);
230 for (int i=nl;i--;) cluster->SetLabel(fCurrLabels[i],i);
234 cluster->SetVolumeId(fVolID);
235 // printf("mod %d: (%.4lf,%.4lf)cm\n",fVolID,x,z);
237 #ifdef _ClusterTopology_
238 FillClusterTopology(cand);
239 #endif //_ClusterTopology_
243 //______________________________________________________________________________
244 void AliITSUClusterizer::CloseCand(AliITSUClusterizerClusterCand *cand)
247 AliITSUClusterPix *cluster = (AliITSUClusterPix*)NextCluster();
248 Transform(cluster,cand);
249 DeallocDigits(cand->fFirstDigit,cand->fLastDigit);
253 //______________________________________________________________________________
254 void AliITSUClusterizer::ClosePart(AliITSUClusterizerClusterPart *part)
256 // finish cluster part
257 AliITSUClusterizerClusterCand *cand=part->fParent;
258 DetachPartFromCand(cand,part);
260 if (!cand->fFirstPart) CloseCand(cand);
263 //______________________________________________________________________________
264 void AliITSUClusterizer::CloseRemainingParts(AliITSUClusterizerClusterPart *part)
266 // finish what is left
268 AliITSUClusterizerClusterPart *next=part->fNextInRow;
274 //______________________________________________________________________________
275 void AliITSUClusterizer::Clusterize()
277 // main algo for MC clustererization
280 AliITSUClusterizerClusterDigit *iDigit=NextDigit();
281 AliITSUClusterizerClusterPart *iPrevRowBegin=0;
282 AliITSUClusterizerClusterPart *iNextRowBegin=0;
283 AliITSUClusterizerClusterPart *iPrevRow=0;
284 AliITSUClusterizerClusterPart *iNextRow=0;
288 if (iDigit->fDigit->GetCoord2()!=lastV) {
290 if (iNextRow) iNextRow->fNextInRow=0;
291 if (iPrevRowBegin) CloseRemainingParts(iPrevRowBegin);
292 if (iDigit->fDigit->GetCoord2()==lastV+1) {
293 iPrevRowBegin=iNextRowBegin;
294 iPrevRow =iNextRowBegin;
297 // there was an empty row
298 CloseRemainingParts(iNextRowBegin);
304 lastV=iDigit->fDigit->GetCoord2();
306 // skip cluster parts before this digit
307 int limCol = iDigit->fDigit->GetCoord1()-fAllowDiagonalClusterization;
308 while (iPrevRow && iPrevRow->fUEnd < limCol) {
309 iPrevRow=iPrevRow->fNextInRow;
311 // find the longest continous line of digits [iDigit,pDigit]=[iDigit,jDigit)
312 AliITSUClusterizerClusterCand *cand=AllocCand();
313 AliITSUClusterizerClusterDigit *pDigit=iDigit;
314 AliITSUClusterizerClusterDigit *jDigit=NextDigit();
316 cand->fFirstDigit=cand->fLastDigit=iDigit; // NB: first diggit is attached differently
318 Int_t lastU =iDigit->fDigit->GetCoord1();
319 Int_t lastU1=lastU+1;
320 while (jDigit && jDigit->fDigit->GetCoord1()==lastU1 && jDigit->fDigit->GetCoord2()==lastV) {
323 AttachDigitToCand(cand,pDigit);
326 if (!fAllowDiagonalClusterization) --lastU1;
327 AliITSUClusterizerClusterPart *part=AllocPart();
328 part->fUBegin=lastU ;
330 AttachPartToCand(cand,part);
331 // merge all cluster candidates of the previous line touching this one,
332 // advance to the last one, but keep that one the next active one
333 AliITSUClusterizerClusterPart *jPrevRow=iPrevRow;
334 while (jPrevRow && jPrevRow->fUBegin<=lastU1) {
335 if (jPrevRow->fParent!=cand) {
336 MergeCands(jPrevRow->fParent,cand);
338 cand=jPrevRow->fParent;
341 jPrevRow=jPrevRow->fNextInRow;
344 iNextRow->fNextInRow=part;
350 // remove remaining cluster parts
351 CloseRemainingParts(iPrevRowBegin);
352 if (iNextRow) iNextRow->fNextInRow=0;
353 CloseRemainingParts(iNextRowBegin);
357 //______________________________________________________________________________
358 void AliITSUClusterizer::PrepareLorentzAngleCorrection(Double_t bz)
360 // calculate parameters for Lorentz Angle correction. Must be called
361 // after setting segmentation and recoparams
362 fLorAngCorrection = 0.5*fRecoParam->GetTanLorentzAngle(fLayerID)*bz/kNominalBz*fSegm->Dy();
365 //______________________________________________________________________
366 void AliITSUClusterizer::CheckLabels()
368 // Tries to find mother's labels
370 if (fNLabels<1) return;
371 AliRunLoader *rl = AliRunLoader::Instance();
373 TTree *trK=(TTree*)rl->TreeK();
376 static int labS[kMaxLabels];
377 static float kine[kMaxLabels];
378 Int_t nlabels = fNLabels;
379 Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
380 for (Int_t i=fNLabels;i--;) labS[i] = fCurrLabels[i];
382 for (Int_t i=0;i<nlabels;i++) {
383 Int_t label = labS[i];
384 if (label>=ntracks) continue;
385 TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
386 kine[i] = part->Energy() - part->GetCalcMass(); // kinetic energy
387 if (kine[i] < 0.02) { // reduce soft particles from the same cluster
388 Int_t m=part->GetFirstMother();
389 if (m<0) continue; // primary
391 if (part->GetStatusCode()>0) continue;
393 // if the parent is within the same cluster, assign parent's label
394 for (int j=0;j<nlabels;j++) if (labS[j]==m) { labS[i] = m; break;}
398 if (nlabels>kMaxLabInCluster) { // only 3 labels are stored in cluster, sort in decreasing momentum
399 static int ind[kMaxLabels],labSS[kMaxLabels];
400 TMath::Sort(nlabels,kine,ind);
401 for (int i=nlabels;i--;) labSS[i] = labS[i];
402 for (int i=nlabels;i--;) labS[i] = labSS[ind[i]];
405 //compress labels -- if multi-times the same
406 for (Int_t i=0;i<nlabels;i++) fCurrLabels[i]=-2;
409 for (int i=0;i<nlabels;i++) {
410 for (j=fNLabels;j--;) if (labS[i]==fCurrLabels[j]) break; // the label already there
411 if (j<0) fCurrLabels[fNLabels++] = labS[i];
416 //------------------------------------------------------------------------
418 #ifdef _ClusterTopology_
420 //______________________________________________________________________
421 void AliITSUClusterizer::FillClusterTopology(AliITSUClusterizerClusterCand *cand)
423 // fill special tree with cluster topology bit pattern
425 enum {kMaxColSpan=30,kMaxRowSpan=30};
427 Int_t mnCol=999999,mxCol=0,mnRow=999999,mxRow=0;
428 for (AliITSUClusterizerClusterDigit *idigit=cand->fFirstDigit;idigit;idigit=idigit->fNext) {
429 AliITSdigit* dig = idigit->fDigit;
430 if (mnCol>dig->GetCoord1()) mnCol = dig->GetCoord1();
431 if (mxCol<dig->GetCoord1()) mxCol = dig->GetCoord1();
432 if (mnRow>dig->GetCoord2()) mnRow = dig->GetCoord2();
433 if (mxRow<dig->GetCoord2()) mxRow = dig->GetCoord2();
435 int nColSpan = mxCol-mnCol+1;
436 int nRowSpan = mxRow-mnRow+1;
437 if (nColSpan<kMaxColSpan && nRowSpan<kMaxRowSpan) {
439 fTopology.SetBitNumber(nColSpan*nRowSpan-1,kFALSE); // set the size
440 fTopology.SetUniqueID( (nRowSpan<<8) + nColSpan );
441 for (AliITSUClusterizerClusterDigit *idigit=cand->fFirstDigit;idigit;idigit=idigit->fNext) {
442 AliITSdigit* dig = idigit->fDigit;
443 fTopology.SetBitNumber( (dig->GetCoord2()-mnRow)*nColSpan + (dig->GetCoord1()-mnCol) );
445 if (!fTreeTopology) InitTopologyTree();
446 AliInfo(Form("Fill Topology, lr %d",fLayerID));
449 fTreeTopology->Fill();
454 //______________________________________________________________________
455 void AliITSUClusterizer::InitTopologyTree()
457 // create output tree for the topology stydy
458 if (fFileTopology || fTreeTopology) AliFatal("Topology structures are already created");
459 TDirectory* cdr = gDirectory;
460 fFileTopology = TFile::Open("clusterTopology.root","recreate");
462 fTreeTopology = new TTree("clTop","ClusterTopology");
463 fTreeTopology->Branch("tp","TBits",&fTopology);
464 fTreeTopology->Branch("volID",&fVolID);
465 fTreeTopology->Branch("mnCol",&fMinCol);
466 fTreeTopology->Branch("mnRow",&fMinRow);
470 //______________________________________________________________________
471 void AliITSUClusterizer::SaveTopologyTree()
473 // write output tree for the topology stydy
474 AliInfo("Storing cluster topology tree");
475 if (!fFileTopology || !fTreeTopology) {AliError("Topology structures are not created"); return;}
477 fTreeTopology->Write();
478 delete fTreeTopology;
479 fFileTopology->Close();
480 delete fFileTopology;
485 #endif //_ClusterTopology_