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 /* $Id: AliTRDchamberTimeBin.cxx 23313 2008-01-11 14:56:43Z cblume $ */
18 ///////////////////////////////////////////////////////////////////////////////
20 // Organization of clusters at the level of 1 TRD chamber. //
21 // The data structure is used for tracking at the stack level. //
23 // Functionalities: //
24 // 1. cluster organization and sorting //
25 // 2. fast data navigation //
28 // Alex Bercuci <A.Bercuci@gsi.de> //
29 // Markus Fasel <M.Fasel@gsi.de> //
31 ///////////////////////////////////////////////////////////////////////////////
36 #include <TStopwatch.h>
37 #include <TTreeStream.h>
41 #include "AliTRDgeometry.h"
42 #include "AliTRDpadPlane.h"
43 #include "AliTRDchamberTimeBin.h"
44 #include "AliTRDrecoParam.h"
45 #include "AliTRDReconstructor.h"
47 ClassImp(AliTRDchamberTimeBin)
49 //_____________________________________________________________________________
50 AliTRDchamberTimeBin::AliTRDchamberTimeBin(Int_t plane, Int_t stack, Int_t sector, Double_t z0, Double_t zLength)
63 // Default constructor (Only provided to use AliTRDchamberTimeBin with arrays)
66 SetBit(kOwner, kFALSE);
67 memset(fPositions, 1, kMaxRows*sizeof(UChar_t));
68 memset(fClusters, 0, kMaxClustersLayer*sizeof(AliTRDcluster*));
69 memset(fIndex, 1, kMaxClustersLayer*sizeof(UInt_t));
73 //_____________________________________________________________________________
74 AliTRDchamberTimeBin::AliTRDchamberTimeBin(const AliTRDchamberTimeBin &layer):
76 ,fReconstructor(layer.fReconstructor)
79 ,fSector(layer.fSector)
84 ,fZLength(layer.fZLength)
88 SetBit(kT0, layer.IsT0());
89 SetBit(kOwner, kFALSE);
90 for(int i=0; i<kMaxRows; i++) fPositions[i] = layer.fPositions[i];
91 memcpy(&fClusters[0], &layer.fClusters[0], kMaxClustersLayer*sizeof(AliTRDcluster*));
92 memcpy(&fIndex[0], &layer.fIndex[0], kMaxClustersLayer*sizeof(UInt_t));
98 //_____________________________________________________________________________
99 AliTRDchamberTimeBin &AliTRDchamberTimeBin::operator=(const AliTRDchamberTimeBin &layer)
101 // Assignment operator
103 if (this != &layer) layer.Copy(*this);
107 //_____________________________________________________________________________
108 void AliTRDchamberTimeBin::Clear(const Option_t *)
110 for(AliTRDcluster **cit = &fClusters[0]; (*cit); cit++){
111 if(IsOwner()) delete (*cit);
117 //_____________________________________________________________________________
118 void AliTRDchamberTimeBin::Copy(TObject &o) const
120 // Copy method. Performs a deep copy of all data from this object to object o.
122 AliTRDchamberTimeBin &layer = (AliTRDchamberTimeBin &)o;
123 layer.fReconstructor = fReconstructor;
124 layer.fPlane = fPlane;
125 layer.fStack = fStack;
126 layer.fSector = fSector;
127 layer.fNRows = fNRows;
131 layer.fZLength = fZLength;
133 layer.SetBit(kOwner, kFALSE);
135 for(int i=0; i<kMaxRows; i++) layer.fPositions[i] = fPositions[i];
136 memcpy(&layer.fClusters[0], &fClusters[0], kMaxClustersLayer*sizeof(AliTRDcluster*));
137 memcpy(&layer.fIndex[0], &fIndex[0], kMaxClustersLayer*sizeof(UInt_t));
139 TObject::Copy(layer); // copies everything into layer
141 // layer.BuildIndices();
144 //_____________________________________________________________________________
145 AliTRDchamberTimeBin::~AliTRDchamberTimeBin()
149 for(AliTRDcluster **cit = &fClusters[0]; (*cit); cit++) delete (*cit);
153 //_____________________________________________________________________________
154 void AliTRDchamberTimeBin::SetOwner(Bool_t copy)
156 // Sets the ownership of the clusters to this
157 // If option "copy" is kTRUE [default] the clusters
158 // are also copied otherwise only the ownership bit
161 SetBit(kOwner, kTRUE);
163 for(AliTRDcluster **cit = &fClusters[0]; (*cit); ++cit){
164 (*cit) = new AliTRDcluster(*(*cit));
168 //_____________________________________________________________________________
169 void AliTRDchamberTimeBin::SetRange(Float_t z0, Float_t zLength)
171 // Sets the range in z-direction
174 // z0 : starting position of layer in the z direction
175 // zLength : length of layer in the z direction
177 fZ0 = (z0 <= z0 + zLength) ? z0 : z0 + zLength;
178 fZLength = TMath::Abs(zLength);
181 //_____________________________________________________________________________
182 void AliTRDchamberTimeBin::InsertCluster(AliTRDcluster *c, UInt_t index)
185 // Insert cluster in cluster array.
186 // Clusters are sorted according to Y coordinate.
189 //if (fTimeBinIndex < 0) {
190 //AliWarning("Attempt to insert cluster into non-sensitive time bin!\n");
194 if (fN == (Int_t) kMaxClustersLayer) {
195 //AliWarning("Too many clusters !\n");
205 Int_t i = Find(c->GetY());
206 memmove(fClusters+i+1,fClusters+i,(fN-i)*sizeof(AliTRDcluster*));
207 memmove(fIndex +i+1,fIndex +i,(fN-i)*sizeof(UInt_t));
213 //___________________________________________________
214 void AliTRDchamberTimeBin::Bootstrap(const AliTRDReconstructor *rec, Int_t det)
216 // Reinitialize all data members from the clusters array
217 // It has to be used after reading from disk
219 fReconstructor = rec;
220 fPlane = AliTRDgeometry::GetLayer(det);
221 fStack = AliTRDgeometry::GetStack(det);
222 fSector = AliTRDgeometry::GetSector(det);
224 fNRows = g.GetPadPlane(fPlane, fStack)->GetNrows();
226 for(AliTRDcluster **cit = &fClusters[0]; (*cit); cit++) fN++;
230 //_____________________________________________________________________________
231 void AliTRDchamberTimeBin::BuildIndices(Int_t iter)
233 // Rearrangement of the clusters belonging to the propagation layer for the stack.
235 // Detailed description
237 // The array indices of all clusters in one PropagationLayer are stored in
238 // array. The array is divided into several bins.
239 // The clusters are sorted in increasing order of their y coordinate.
241 // Sorting algorithm: TreeSearch
246 // Select clusters that belong to the Stack
247 Int_t nClStack = 0; // Internal counter
248 for(Int_t i = 0; i < fN; i++){
249 if(fClusters[i]->IsUsed() || fClusters[i]->IsShared()){
254 if(nClStack > kMaxClustersLayer) AliWarning(Form("Number of clusters in stack %d exceed buffer size %d. Truncating.", nClStack, kMaxClustersLayer));
256 // Nothing in this time bin. Reset indexes
259 memset(&fPositions[0], 0xff, sizeof(UChar_t) * kMaxRows);
260 memset(&fClusters[0], 0x0, sizeof(AliTRDcluster*) * kMaxClustersLayer);
261 memset(&fIndex[0], 0xffff, sizeof(UInt_t) * kMaxClustersLayer);
266 AliTRDcluster *helpCL[kMaxClustersLayer];
267 UInt_t helpInd[kMaxClustersLayer];
269 // Defining iterators
270 AliTRDcluster **fcliter = &fClusters[0], **hcliter = &helpCL[0]; UInt_t *finditer = &fIndex[0], *hinditer = &helpInd[0];
271 AliTRDcluster *tmpcl = 0x0;
272 for(Int_t i = 0; i < TMath::Min(fN, kMaxClustersLayer); i++){
273 if(!(tmpcl = *(fcliter++))){
277 *(hcliter++) = tmpcl;
278 *(hinditer++) = *finditer;
280 *(finditer++) = 0xffff;
284 // do clusters arrangement
288 // Reset Positions array
289 memset(fPositions, 0, sizeof(UChar_t)*kMaxRows);
290 AliTRDcluster **cliter = &helpCL[0]; // Declare iterator running over the whole array
291 for(Int_t i = 0; i < fN; i++){
293 AliTRDcluster *cl = *(cliter++);
294 UChar_t rowIndex = cl->GetPadRow();
296 Int_t pos = FindYPosition(cl->GetY(), rowIndex, i);
297 if(pos == -1){ // zbin is empty;
298 Int_t upper = (rowIndex == fNRows - 1) ? nClStack : fPositions[rowIndex + 1];
299 memmove(fClusters + upper + 1, fClusters + upper, (sizeof(AliTRDcluster *))*(nClStack-upper));
300 memmove(fIndex + upper + 1, fIndex + upper, (sizeof(UInt_t))*(nClStack-upper));
301 fClusters[upper] = cl;
302 fIndex[upper] = helpInd[i];
303 // Move All pointer one position back
304 for(UChar_t j = rowIndex + 1; j < fNRows; j++) fPositions[j]++;
306 } else { // zbin not empty
307 memmove(fClusters + pos + 2, fClusters + pos+1, (sizeof(AliTRDcluster *))*(nClStack-(pos+1)));
308 memmove(fIndex + pos + 2, fIndex + pos+1, (sizeof(UInt_t))*(nClStack-(pos+1)));
309 fClusters[pos + 1] = cl; //fIndex[i];
310 fIndex[pos + 1] = helpInd[i];
311 // Move All pointer one position back
312 for(UChar_t j = rowIndex + 1; j < fNRows; j++) fPositions[j]++;
320 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kTracker) >= 3){
321 TTreeSRedirector &cstream = *fReconstructor->GetDebugStream(AliTRDReconstructor::kTracker);
322 cstream << "BuildIndices"
323 << "Plane=" << fPlane
324 << "Stack=" << fStack
325 << "Sector=" << fSector
328 << "rowIndex=" << rowIndex
333 // AliInfo("Positions");
334 // for(int ir=0; ir<fNRows; ir++) printf("pos[%d] %d\n", ir, fPositions[ir]);
339 //_____________________________________________________________________________
340 Int_t AliTRDchamberTimeBin::Find(Float_t y) const
343 // Returns index of the cluster nearest in Y
346 if (fN <= 0) return 0;
348 if (y <= fClusters[0]->GetY()) return 0;
350 if (y > fClusters[fN-1]->GetY()) return fN;
355 Int_t m = (b + e) / 2;
357 for ( ; b < e; m = (b + e) / 2) {
358 if (y > fClusters[m]->GetY()) b = m + 1;
365 //_____________________________________________________________________________
366 Int_t AliTRDchamberTimeBin::FindYPosition(Double_t y, UChar_t z, Int_t nClusters) const
369 // Tree search Algorithm to find the nearest left cluster for a given
370 // y-position in a certain z-bin (in fact AVL-tree).
371 // Making use of the fact that clusters are sorted in y-direction.
374 // y : y position of the reference point in tracking coordinates
375 // z : z reference bin.
379 // Index of the nearest left cluster in the StackLayer indexing (-1 if no clusters are found)
382 Int_t start = fPositions[z]; // starting Position of the bin
383 Int_t upper = (Int_t)((z != fNRows - 1) ? fPositions[z+1] : nClusters); // ending Position of the bin
384 Int_t end = upper - 1; // ending Position of the bin
385 if(end < start) return -1; // Bin is empty
386 Int_t middle = static_cast<Int_t>((start + end)/2);
387 // 1st Part: climb down the tree: get the next cluster BEFORE ypos
388 while(start + 1 < end){
389 if(y >= fClusters[middle]->GetY()) start = middle;
391 middle = static_cast<Int_t>((start + end)/2);
393 if(y > fClusters[end]->GetY()) return end;
397 //_____________________________________________________________________________
398 Int_t AliTRDchamberTimeBin::FindNearestYCluster(Double_t y, UChar_t z) const
401 // Tree search Algorithm to find the nearest cluster for a given
402 // y-position in a certain z-bin (in fact AVL-tree).
403 // Making use of the fact that clusters are sorted in y-direction.
406 // y : y position of the reference point in tracking coordinates
407 // z : z reference bin.
410 // Index of the nearest cluster in the StackLayer indexing (-1 if no clusters are found)
413 Int_t position = FindYPosition(y, z, fN);
414 if(position == -1) return position; // bin empty
415 // FindYPosition always returns the left Neighbor. We don't know if the left or the right Neighbor is nearest
416 // to the Reference y-position, so test both
417 Int_t upper = (Int_t)((z < fNRows-1) ? fPositions[z+1] : fN); // ending Position of the bin
418 if((position + 1) < (upper)){
419 if(TMath::Abs(y - fClusters[position + 1]->GetY()) < TMath::Abs(y - fClusters[position]->GetY())) return position + 1;
420 else return position;
425 //_____________________________________________________________________________
426 Int_t AliTRDchamberTimeBin::SearchNearestCluster(Double_t y, Double_t z, Double_t maxroady, Double_t maxroadz) const
429 // Finds the nearest cluster from a given point in a defined range.
430 // Distance is determined in a 2D space by the 2-Norm.
433 // y : y position of the reference point in tracking coordinates
434 // z : z reference bin.
435 // maxroady : maximum searching distance in y direction
436 // maxroadz : maximum searching distance in z direction
439 // Index of the nearest cluster in the StackLayer indexing (-1 if no cluster is found).
440 // Cluster can be accessed with the operator[] or GetCluster(Int_t index)
442 // Detail description
444 // The following steps are perfomed:
445 // 1. Get the expected z bins inside maxroadz.
446 // 2. For each z bin find nearest y cluster.
447 // 3. Select best candidate
450 // initial minimal distance will be represented as ellipse: semi-major = z-direction
451 // later 2-Norm will be used
452 // Float_t nExcentricity = TMath::Sqrt(maxroadz*maxroadz - maxroad*maxroad)/maxroadz;
453 Float_t mindist = maxroadz;
455 // not very nice but unfortunately neccessarry: we have ho check the neighbors in both directions (+ and -) too. How
456 // much neighbors depends on the Quotient maxroadz/fZLength
458 UChar_t zpos[kMaxRows];
459 // Float_t mindist = TMath::Sqrt(maxroad*maxroad + maxroadz*maxroadz);
460 // UChar_t myZbin = FindTreePosition(z, fZ0 + fZLength/2, fZLength/4, 8, 8, kFALSE);
461 UChar_t myZbin = fNRows - 1 - (UChar_t)(TMath::Abs(fZ0 - z)/fZLength * fNRows);
462 if(z < fZ0) myZbin = fNRows - 1;
463 if(z > fZ0 + fZLength) myZbin = 0;
464 //printf("\n%f < %f < %f [%d]\n", fZ0, z, fZ0 + fZLength, myZbin);
465 //for(int ic=0; ic<fN; ic++) printf("%d z = %f row %d\n", ic, fClusters[ic]->GetZ(), fClusters[ic]->GetPadRow());
467 UChar_t nNeighbors = 0;
468 for(UChar_t i = 0; i < maxRows; i++){
469 if((myZbin - 1 + i) < 0) continue;
470 if((myZbin - 1 + i) > fNRows - 1) break;
471 zpos[nNeighbors] = myZbin - 1 + i;
474 Float_t ycl = 0, zcl = 0;
475 for(UChar_t neighbor = 0; neighbor < nNeighbors; neighbor++){ // Always test the neighbors too
476 Int_t pos = FindNearestYCluster(y, zpos[neighbor]);
477 if(pos == -1) continue; // No cluster in bin
478 AliTRDcluster *c = (AliTRDcluster *) (fClusters[pos]);
479 if(c->IsUsed()) continue; // we are only interested in unused clusters
481 // Too far away in y-direction (Prearrangement)
482 if (TMath::Abs(ycl - y) > maxroady){
483 //printf("y[%f] ycl[%f] roady[%f]\n", y, ycl, maxroady);
487 // Too far away in z-Direction
488 // (Prearrangement since we have not so many bins to test)
489 if (TMath::Abs(zcl - z) > maxroadz) continue;
491 Float_t dist; // distance defined as 2-Norm
492 // if we havent found a Particle that is in the ellipse around (y,z) with maxroad as semi-minor and
493 // maxroadz as semi-major, we take the radius of the ellipse concerning the cluster as mindist, later we
494 // take the 2-Norm when we found a cluster inside the ellipse (The value 10000 is taken because it is surely
495 // large enough to be usable as an indicator whether we have found a nearer cluster or not)
496 // if(mindist > 10000.){
497 // Float_t phi = ((zcl - z) == 0) ? TMath::Pi()/2 : TMath::ATan((ycl - y)/(zcl - z));
498 // mindist = maxroad/TMath::Sqrt(1 - nExcentricity*nExcentricity * (TMath::Cos(phi))*(TMath::Cos(phi)));
500 dist = TMath::Max(TMath::Abs(y-ycl),TMath::Abs(z-zcl)); // infinity Norm
501 // dist = TMath::Sqrt((ycl - y)*(ycl - y) + (zcl - z)*(zcl - z));
502 if((Int_t)(dist * 100000) < (Int_t)(mindist * 100000)){
503 //if((dist = TMath::Sqrt((ycl - y)*(ycl - y) + (zcl - z)*(zcl - z))) < mindist){
508 // This is the Array Position in fIndex2D of the Nearest cluster: if a
509 // cluster is called, then the function has to retrieve the Information
510 // which is Stored in the Array called, the function
514 //_____________________________________________________________________________
515 void AliTRDchamberTimeBin::BuildCond(AliTRDcluster *cl, Double_t *cond, UChar_t Layer, Double_t theta, Double_t phi)
517 // Helper function to calculate the area where to expect a cluster in THIS
527 // Detail description
529 // Helper function to calculate the area where to expect a cluster in THIS
530 // layer. by using the information of a former cluster in another layer
531 // and the angle in theta- and phi-direction between layer 0 and layer 3.
532 // If the layer is zero, initial conditions are calculated. Otherwise a
533 // linear interpolation is performed.
535 //<img src="gif/build_cond.gif">
540 AliError("Reconstructor not set.");
545 cond[0] = cl->GetY(); // center: y-Direction
546 cond[1] = cl->GetZ(); // center: z-Direction
547 cond[2] = fReconstructor->GetRecoParam()->GetMaxPhi() * (cl->GetX() - GetX()) + 1.0; // deviation: y-Direction
548 cond[3] = fReconstructor->GetRecoParam()->GetMaxTheta() * (cl->GetX() - GetX()) + 1.0; // deviation: z-Direction
550 cond[0] = cl->GetY() + phi * (GetX() - cl->GetX());
551 cond[1] = cl->GetZ() + theta * (GetX() - cl->GetX());
552 cond[2] = fReconstructor->GetRecoParam()->GetRoad0y() + phi;
553 cond[3] = fReconstructor->GetRecoParam()->GetRoad0z();
557 //_____________________________________________________________________________
558 void AliTRDchamberTimeBin::GetClusters(Double_t *cond, Int_t *index, Int_t& ncl, Int_t BufferSize)
560 // Finds all clusters situated in this layer inside a rectangle given by the center an ranges.
570 // Detail description
572 // Function returs an array containing the indices in the stacklayer of
573 // the clusters found an the number of found clusters in the stacklayer
576 memset(index, 0, BufferSize*sizeof(Int_t));
581 if(((cond[1] - cond[3]) >= (fZ0 + fZLength)) || (cond[1] + cond[3]) <= fZ0) return; // We are outside of the chamvber
582 zvals[0] = ((cond[1] - cond[3]) < fZ0) ? fZ0 : (cond[1] - cond[3]);
583 zvals[1] = ((cond[1] + cond[3]) < fZ0 + fZLength) ? (cond[1] + cond[3]) : fZ0 + fZLength - 1.E-3;
585 UChar_t zhi = fNRows - 1 - (UChar_t)(TMath::Abs(fZ0 - zvals[0])/fZLength * fNRows);
586 UChar_t zlo = fNRows - 1 - (UChar_t)(TMath::Abs(fZ0 - zvals[1])/fZLength * fNRows);
588 /* AliInfo(Form("yc[%f] zc[%f] dy[%f] dz[%f]", cond[0], cond[1], cond[2], cond[3]));
590 AliInfo(Form("zlo[%f] zhi[%f]", zvals[0], zvals[1]));
591 AliInfo(Form("zlo[%d] zhi[%d]", zlo, zhi));*/
593 Double_t ylo = cond[0] - cond[2],
594 yhi = cond[0] + cond[2];
595 //printf("CTB : ylo[%f] yhi[%f]\n", ylo, yhi);
596 //Preordering in Direction z saves a lot of loops (boundary checked)
597 for(UChar_t z = zlo; z <= zhi; z++){
598 UInt_t upper = (z < fNRows-1) ? fPositions[z+1] : fN;
599 //AliInfo(Form("z[%d] y [%d %d]", z, fPositions[z], upper));
600 for(Int_t y = fPositions[z]; y < (Int_t)upper; y++){
601 if(ncl == BufferSize){
602 AliWarning("Buffer size riched. Some clusters may be lost.");
603 return; //Buffer filled
606 if(fClusters[y]->GetY() > yhi) break; // Abbortion conditions!!!
607 if(fClusters[y]->GetY() < ylo) continue; // Too small
608 if(((Int_t)((fClusters[y]->GetZ())*1000) < (Int_t)(zvals[0]*1000)) || ((Int_t)((fClusters[y]->GetZ())*1000) > (Int_t)(zvals[1]*1000))){/*printf("exit z\n"); TODO*/ continue;}
613 if(ncl>fN) AliError(Form("Clusters found %d > %d (clusters in layer)", ncl, fN));
616 //_____________________________________________________________________________
617 AliTRDcluster *AliTRDchamberTimeBin::GetNearestCluster(Double_t *cond)
619 // Function returning a pointer to the nearest cluster (nullpointer if not successfull).
625 // pointer to the nearest cluster (nullpointer if not successfull).
627 // Detail description
629 // returns a pointer to the nearest cluster (nullpointer if not
630 // successfull) by the help of the method FindNearestCluster
633 Double_t maxroad = fReconstructor->GetRecoParam()->GetRoad2y();
634 Double_t maxroadz = fReconstructor->GetRecoParam()->GetRoad2z();
636 Int_t index = SearchNearestCluster(cond[0],cond[1],maxroad,maxroadz);
637 AliTRDcluster *returnCluster = 0x0;
638 if(index != -1) returnCluster = (AliTRDcluster *) fClusters[index];
639 return returnCluster;
642 //_____________________________________________________________________________
643 void AliTRDchamberTimeBin::Print(Option_t *) const
645 // Prints the position of each cluster in the stacklayer on the stdout
648 AliInfo(Form("Layer[%d] Stack[%d] Sector[%2d] nRows[%2d]", fPlane, fStack, fSector, fNRows));
649 AliInfo(Form("Z0[%7.3f] Z1[%7.3f]", fZ0, fZ0+fZLength));
650 AliTRDcluster* const* icl = &fClusters[0];
651 for(Int_t jcl = 0; jcl < fN; jcl++, icl++){
652 AliInfo(Form("%2d X[%7.3f] Y[%7.3f] Z[%7.3f] tb[%2d] col[%3d] row[%2d] used[%s]", jcl, (*icl)->GetX(), (*icl)->GetY(), (*icl)->GetZ(), (*icl)->GetLocalTimeBin(), (*icl)->GetPadCol(), (*icl)->GetPadRow(),
653 (*icl)->IsUsed() ? "y" : "n"));
656 for(UChar_t const* pos = &fPositions[0]; irow<fNRows; pos++, irow++){
657 if((*pos) != 0xff) AliInfo(Form("r[%2d] pos[%d]", irow, (*pos)));