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 **************************************************************************/
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>
40 #include "AliTRDcluster.h"
42 #include "AliTRDstackLayer.h"
43 #include "AliTRDrecoParam.h"
44 #include "AliTRDReconstructor.h"
48 ClassImp(AliTRDstackLayer)
50 //_____________________________________________________________________________
51 AliTRDstackLayer::AliTRDstackLayer(Double_t z0, Double_t zLength
52 , UChar_t stackNr, AliTRDrecoParam *p)
53 :AliTRDpropagationLayer()
63 // Default constructor (Only provided to use AliTRDstackLayer with arrays)
66 for(int i=0; i<kMaxRows; i++) fPositions[i] = 0;
69 //_____________________________________________________________________________
70 AliTRDstackLayer::AliTRDstackLayer(const AliTRDpropagationLayer &layer, Double_t
71 z0, Double_t zLength, UChar_t stackNr, AliTRDrecoParam *p):
72 AliTRDpropagationLayer(layer)
81 // Standard constructor.
82 // Initialize also the underlying AliTRDpropagationLayer using the copy constructor.
85 for(int i=0; i<kMaxRows; i++) fPositions[i] = 0;
88 //_____________________________________________________________________________
89 AliTRDstackLayer::AliTRDstackLayer(const AliTRDpropagationLayer &layer):
90 AliTRDpropagationLayer(layer)
99 // Standard constructor using only AliTRDpropagationLayer.
102 for(int i=0; i<kMaxRows; i++) fPositions[i] = 0;
105 //_____________________________________________________________________________
106 AliTRDstackLayer::AliTRDstackLayer(const AliTRDstackLayer &layer):
107 AliTRDpropagationLayer(layer)
108 ,fOwner(layer.fOwner)
109 ,fStackNr(layer.fStackNr)
110 ,fNRows(layer.fNRows)
112 ,fZLength(layer.fZLength)
113 ,fRecoParam(layer.fRecoParam)
114 ,fDebugStream(layer.fDebugStream)
116 // Copy Constructor (performs a deep copy)
119 for(Int_t i = 0; i < kMaxRows; i++) fPositions[i] = layer.fPositions[i];
123 //_____________________________________________________________________________
124 AliTRDstackLayer &AliTRDstackLayer::operator=(const AliTRDpropagationLayer &layer)
126 // Assignment operator from an AliTRDpropagationLayer
128 if (this != &layer) layer.Copy(*this);
132 //_____________________________________________________________________________
133 AliTRDstackLayer &AliTRDstackLayer::operator=(const AliTRDstackLayer &layer)
135 // Assignment operator
137 if (this != &layer) layer.Copy(*this);
141 //_____________________________________________________________________________
142 void AliTRDstackLayer::Copy(TObject &o) const
144 // Copy method. Performs a deep copy of all data from this object to object o.
146 AliTRDstackLayer &layer = (AliTRDstackLayer &)o;
148 layer.fOwner = kFALSE;
149 layer.fNRows = fNRows;
150 layer.fZLength = fZLength;
151 layer.fStackNr = fStackNr;
152 layer.fDebugStream = fDebugStream;
153 layer.fRecoParam = fRecoParam;
156 AliTRDpropagationLayer::Copy(layer); // copies everything into layer
157 for(UChar_t i = 0; i < kMaxRows; i++) layer.fPositions[i] = 0;
158 // layer.BuildIndices();
161 //_____________________________________________________________________________
162 AliTRDstackLayer::~AliTRDstackLayer()
165 if(fOwner) for(int ic=0; ic<fN; ic++) delete fClusters[ic];
168 //_____________________________________________________________________________
169 void AliTRDstackLayer::SetRange(const Float_t z0, const 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 AliTRDstackLayer::BuildIndices(Int_t iter)
184 // Rearrangement of the clusters belonging to the propagation layer for the stack.
186 // Detailed description
188 // The array indices of all clusters in one PropagationLayer are stored in
189 // array. The array is divided into several bins.
190 // The clusters are sorted in increasing order of their y coordinate.
192 // Sorting algorithm: TreeSearch
197 // Select clusters that belong to the Stack
198 Int_t nClStack = 0; // Internal counter
199 for(Int_t i = 0; i < fN; i++){
200 Double_t zval = fClusters[i]->GetZ();
201 if(zval < fZ0 || zval > fZ0 + fZLength || fClusters[i]->IsUsed()){
206 if(nClStack > kMaxClustersLayer) AliWarning(Form("Number of clusters in stack %d exceed buffer size %d", nClStack, kMaxClustersLayer));
208 // Nothing in this Stack
215 memset(fPositions, 0, sizeof(UChar_t) * 16);
220 AliTRDcluster *helpCL[kMaxClustersLayer];
221 Int_t helpInd[kMaxClustersLayer];
223 for(Int_t i = 0; i < TMath::Min(fN, kMaxClustersLayer); i++){
224 if(!fClusters[i]) continue;
225 helpCL[nClStack] = fClusters[i];
226 helpInd[nClStack] = fIndex[i];
232 // do clusters arrangement
235 memset(fPositions,0,sizeof(UChar_t)*16); // Reset Positions array
236 for(Int_t i = 0; i < fN; i++){
238 AliTRDcluster *cl = helpCL[i];
239 Double_t zval = cl->GetZ();
240 UChar_t treeIndex = (UChar_t)(TMath::Abs(fZ0 - zval)/fZLength * fNRows);
241 if(treeIndex > fNRows - 1) treeIndex = fNRows - 1;
243 Int_t pos = FindYPosition(cl->GetY(), treeIndex, i);
244 if(pos == -1){ // zbin is empty;
245 Int_t upper = (treeIndex == fNRows - 1) ? nClStack : fPositions[treeIndex + 1];
246 memmove(fClusters + upper + 1, fClusters + upper, (sizeof(AliTRDcluster *))*(nClStack-upper));
247 memmove(fIndex + upper + 1, fIndex + upper, (sizeof(UInt_t))*(nClStack-upper));
248 fClusters[upper] = cl;
249 fIndex[upper] = helpInd[i];
250 // Move All pointer one position back
251 for(UChar_t j = treeIndex + 1; j < fNRows; j++) fPositions[j]++;
253 } else { // zbin not empty
254 memmove(fClusters + pos + 2, fClusters + pos+1, (sizeof(AliTRDcluster *))*(nClStack-(pos+1)));
255 memmove(fIndex + pos + 2, fIndex + pos+1, (sizeof(UInt_t))*(nClStack-(pos+1)));
256 fClusters[pos + 1] = cl; //fIndex[i];
257 fIndex[pos + 1] = helpInd[i];
258 // Move All pointer one position back
259 for(UChar_t j = treeIndex + 1; j < fNRows; j++) fPositions[j]++;
266 if(fDebugStream && AliTRDReconstructor::StreamLevel() >= 3){
267 TTreeSRedirector &cstream = *fDebugStream;
268 cstream << "BuildIndices"
269 << "StackNr=" << fStackNr
270 << "SectorNr=" << fSec
273 << "TreeIdx=" << treeIndex
280 //_____________________________________________________________________________
281 Int_t AliTRDstackLayer::FindYPosition(Double_t y, UChar_t z, Int_t nClusters) const
284 // Tree search Algorithm to find the nearest left cluster for a given
285 // y-position in a certain z-bin (in fact AVL-tree).
286 // Making use of the fact that clusters are sorted in y-direction.
289 // y : y position of the reference point in tracking coordinates
290 // z : z reference bin.
294 // Index of the nearest left cluster in the StackLayer indexing (-1 if no clusters are found)
297 Int_t start = fPositions[z]; // starting Position of the bin
298 Int_t upper = (Int_t)((z != fNRows - 1) ? fPositions[z+1] : nClusters); // ending Position of the bin
299 Int_t end = upper - 1; // ending Position of the bin
300 if(end < start) return -1; // Bin is empty
301 Int_t middle = static_cast<Int_t>((start + end)/2);
302 // 1st Part: climb down the tree: get the next cluster BEFORE ypos
303 while(start + 1 < end){
304 if(y >= fClusters[middle]->GetY()) start = middle;
306 middle = static_cast<Int_t>((start + end)/2);
308 if(y > fClusters[end]->GetY()) return end;
312 //_____________________________________________________________________________
313 Int_t AliTRDstackLayer::FindNearestYCluster(Double_t y, UChar_t z) const
316 // Tree search Algorithm to find the nearest cluster for a given
317 // y-position in a certain z-bin (in fact AVL-tree).
318 // Making use of the fact that clusters are sorted in y-direction.
321 // y : y position of the reference point in tracking coordinates
322 // z : z reference bin.
325 // Index of the nearest cluster in the StackLayer indexing (-1 if no clusters are found)
328 Int_t position = FindYPosition(y, z, fN);
329 if(position == -1) return position; // bin empty
330 // FindYPosition always returns the left Neighbor. We don't know if the left or the right Neighbor is nearest
331 // to the Reference y-position, so test both
332 Int_t upper = (Int_t)((z < fNRows-1) ? fPositions[z+1] : fN); // ending Position of the bin
333 if((position + 1) < (upper)){
334 if(TMath::Abs(y - fClusters[position + 1]->GetY()) < TMath::Abs(y - fClusters[position]->GetY())) return position + 1;
335 else return position;
340 //_____________________________________________________________________________
341 Int_t AliTRDstackLayer::SearchNearestCluster(Double_t y, Double_t z, Double_t maxroady, Double_t maxroadz) const
344 // Finds the nearest cluster from a given point in a defined range.
345 // Distance is determined in a 2D space by the 2-Norm.
348 // y : y position of the reference point in tracking coordinates
349 // z : z reference bin.
350 // maxroady : maximum searching distance in y direction
351 // maxroadz : maximum searching distance in z direction
354 // Index of the nearest cluster in the StackLayer indexing (-1 if no cluster is found).
355 // Cluster can be accessed with the operator[] or GetCluster(Int_t index)
357 // Detail description
359 // The following steps are perfomed:
360 // 1. Get the expected z bins inside maxroadz.
361 // 2. For each z bin find nearest y cluster.
362 // 3. Select best candidate
365 // initial minimal distance will be represented as ellipse: semi-major = z-direction
366 // later 2-Norm will be used
367 // Float_t nExcentricity = TMath::Sqrt(maxroadz*maxroadz - maxroad*maxroad)/maxroadz;
368 Float_t mindist = maxroadz;
370 // not very nice but unfortunately neccessarry: we have ho check the neighbors in both directions (+ and -) too. How
371 // much neighbors depends on the Quotient maxroadz/fZLength
373 UChar_t zpos[kMaxRows];
374 // Float_t mindist = TMath::Sqrt(maxroad*maxroad + maxroadz*maxroadz);
375 // UChar_t myZbin = FindTreePosition(z, fZ0 + fZLength/2, fZLength/4, 8, 8, kFALSE);
376 UChar_t myZbin = (UChar_t)(TMath::Abs(fZ0 - z)/fZLength * fNRows);
377 if(z < fZ0) myZbin = 0;
378 if(z > fZ0 + fZLength) myZbin = fNRows - 1;
380 UChar_t nNeighbors = 0;
381 for(UChar_t i = 0; i < maxRows; i++){
382 if((myZbin - 1 + i) < 0) continue;
383 if((myZbin - 1 + i) > fNRows - 1) break;
384 zpos[nNeighbors] = myZbin - 1 + i;
387 Float_t ycl = 0, zcl = 0;
388 for(UChar_t neighbor = 0; neighbor < nNeighbors; neighbor++){ // Always test the neighbors too
389 Int_t pos = FindNearestYCluster(y,zpos[neighbor]);
390 if(pos == -1) continue; // No cluster in bin
391 AliTRDcluster *c = (AliTRDcluster *) (fClusters[pos]);
392 if(c->IsUsed()) continue; // we are only interested in unused clusters
394 // Too far away in y-direction (Prearrangement)
395 if (TMath::Abs(ycl - y) > maxroady) continue;
398 // Too far away in z-Direction
399 // (Prearrangement since we have not so many bins to test)
400 if (TMath::Abs(zcl - z) > maxroadz) continue;
402 Float_t dist; // distance defined as 2-Norm
403 // if we havent found a Particle that is in the ellipse around (y,z) with maxroad as semi-minor and
404 // maxroadz as semi-major, we take the radius of the ellipse concerning the cluster as mindist, later we
405 // take the 2-Norm when we found a cluster inside the ellipse (The value 10000 is taken because it is surely
406 // large enough to be usable as an indicator whether we have found a nearer cluster or not)
407 // if(mindist > 10000.){
408 // Float_t phi = ((zcl - z) == 0) ? TMath::Pi()/2 : TMath::ATan((ycl - y)/(zcl - z));
409 // mindist = maxroad/TMath::Sqrt(1 - nExcentricity*nExcentricity * (TMath::Cos(phi))*(TMath::Cos(phi)));
411 dist = TMath::Max(TMath::Abs(y-ycl),TMath::Abs(z-zcl)); // infinity Norm
412 // dist = TMath::Sqrt((ycl - y)*(ycl - y) + (zcl - z)*(zcl - z));
413 if((Int_t)(dist * 100000) < (Int_t)(mindist * 100000)){
414 //if((dist = TMath::Sqrt((ycl - y)*(ycl - y) + (zcl - z)*(zcl - z))) < mindist){
419 // This is the Array Position in fIndex2D of the Nearest cluster: if a
420 // cluster is called, then the function has to retrieve the Information
421 // which is Stored in the Array called, the function
425 //_____________________________________________________________________________
426 void AliTRDstackLayer::BuildCond(AliTRDcluster *cl, Double_t *cond, UChar_t Layer, Double_t theta, Double_t phi)
428 // Helper function to calculate the area where to expect a cluster in THIS
438 // Detail description
440 // Helper function to calculate the area where to expect a cluster in THIS
441 // layer. by using the information of a former cluster in another layer
442 // and the angle in theta- and phi-direction between layer 0 and layer 3.
443 // If the layer is zero, initial conditions are calculated. Otherwise a
444 // linear interpolation is performed.
446 //<img src="gif/build_cond.gif">
451 AliError("Reconstruction parameters not initialized.");
456 cond[0] = cl->GetY(); // center: y-Direction
457 cond[1] = cl->GetZ(); // center: z-Direction
458 cond[2] = fRecoParam->GetMaxPhi() * (cl->GetX() - GetX()) + 1.0; // deviation: y-Direction
459 cond[3] = fRecoParam->GetMaxTheta() * (cl->GetX() - GetX()) + 1.0; // deviation: z-Direction
461 cond[0] = cl->GetY() + phi * (GetX() - cl->GetX());
462 cond[1] = cl->GetZ() + theta * (GetX() - cl->GetX());
463 cond[2] = fRecoParam->GetRoad0y() + phi;
464 cond[3] = fRecoParam->GetRoad0z();
468 //_____________________________________________________________________________
469 void AliTRDstackLayer::GetClusters(Double_t *cond, Int_t *index, Int_t& ncl, Int_t BufferSize)
471 // Finds all clusters situated in this layer inside a rectangle given by the center an ranges.
481 // Detail description
483 // Function returs an array containing the indices in the stacklayer of
484 // the clusters found an the number of found clusters in the stacklayer
487 memset(index, 0, BufferSize*sizeof(Int_t));
492 zvals[0] = ((cond[1] - cond[3]) < fZ0) ? fZ0 : (cond[1] - cond[3]);
493 zvals[1] = ((cond[1] + cond[3]) < fZ0 + fZLength) ? (cond[1] + cond[3]) : fZ0 + fZLength;
495 UChar_t zlo = (fZ0>zvals[0]) ? 0 : (UChar_t)(TMath::Abs(fZ0 - zvals[0])/fZLength * fNRows);
496 UChar_t zhi = (fZ0+fZLength<zvals[1]) ? fNRows - 1 : (UChar_t)(TMath::Abs(fZ0 - zvals[1])/fZLength * fNRows);
498 //Preordering in Direction z saves a lot of loops (boundary checked)
499 for(UChar_t z = zlo; z <= zhi; z++){
500 UInt_t upper = (z < fNRows-1) ? fPositions[z+1] : fN;
501 for(Int_t y = fPositions[z]; y < (Int_t)upper; y++){
502 if(ncl == BufferSize){
503 AliWarning("Buffer size riched. Some clusters may be lost.");
504 return; //Buffer filled
506 if(fClusters[y]->GetY() > (cond[0] + cond[2])) break; // Abbortion conditions!!!
507 if(fClusters[y]->GetY() < (cond[0] - cond[2])) continue; // Too small
508 if(((Int_t)((fClusters[y]->GetZ())*1000) < (Int_t)(zvals[0]*1000)) || ((Int_t)((fClusters[y]->GetZ())*1000) > (Int_t)(zvals[1]*1000))) continue;
513 if(ncl>fN) AliError(Form("Clusters found %d > %d (clusters in layer)", ncl, fN));
516 //_____________________________________________________________________________
517 AliTRDcluster *AliTRDstackLayer::GetNearestCluster(Double_t *cond)
519 // Function returning a pointer to the nearest cluster (nullpointer if not successfull).
525 // pointer to the nearest cluster (nullpointer if not successfull).
527 // Detail description
529 // returns a pointer to the nearest cluster (nullpointer if not
530 // successfull) by the help of the method FindNearestCluster
533 Double_t maxroad = fRecoParam->GetRoad2y();
534 Double_t maxroadz = fRecoParam->GetRoad2z();
536 Int_t index = SearchNearestCluster(cond[0],cond[1],maxroad,maxroadz);
537 AliTRDcluster *returnCluster = 0x0;
538 if(index != -1) returnCluster = (AliTRDcluster *) fClusters[index];
539 return returnCluster;
542 //_____________________________________________________________________________
543 void AliTRDstackLayer::PrintClusters() const
545 // Prints the position of each cluster in the stacklayer on the stdout
547 //printf("fDebugStream = %#o\n", ((Int_t) fDebugStream));
548 //printf("fRecoParam = %#o\n", ((Int_t) fRecoParam));
550 for(Int_t i = 0; i < fN; i++){
551 printf("AliTRDstackLayer: index=%i, Cluster: X = %3.3f, Y = %3.3f, Z = %3.3f\n", i, fClusters[i]->GetX(),fClusters[i]->GetY(),fClusters[i]->GetZ());
552 if(fClusters[i]->IsUsed()) printf("cluster allready used. rejected in search algorithm\n");