]> git.uio.no Git - u/mrichter/AliRoot.git/blame - ITS/AliITStrackerANN.cxx
hopefully the last refinements for correct type conversion in calibration
[u/mrichter/AliRoot.git] / ITS / AliITStrackerANN.cxx
CommitLineData
cec46807 1// ---------------------------------------------------------------------------------
2// AliITStrackerANN
3// ---------------------------------------------------------------------------------
4// Neural Network-based algorithm for track reconstruction in the ALICE ITS.
5// The class contains all that is necessary in order to perform the tracking
6// using the ITS clusters in the V2 format.
7// The class is organized with some embedded objects which serve for
8// data management, and all setters and getters for all parameters.
9// The usage of the class from a tracking macro should be based essentially
10// in the initialization (constructor) and the call of a method which
11// performs in the right sequence all the operations.
12// Temporarily (and maybe definitively) all the intermediate steps are
13// public functions which could be called independently, but they do not
14// produce any result if all the preventively required steps have not been
15// performed.
16// ---------------------------------------------------------------------------------
17// Author: Alberto Pulvirenti (university of Catania)
18// Email : alberto.pulvirenti@ct.infn.it
19// ---------------------------------------------------------------------------------
20
cec46807 21#include <TString.h>
22#include <TObjArray.h>
23#include <TVector3.h>
24#include <TFile.h>
25#include <TTree.h>
26#include <TRandom.h>
27#include <TMatrixD.h>
292a2409 28#if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,2)
29 #include <TMatrixDEigen.h>
30#endif
cec46807 31
32#include "AliITSgeom.h"
33#include "AliITStrackSA.h"
00a7cc50 34#include "AliITSRecPoint.h"
cec46807 35#include "AliITStrackV2.h"
36
37#include "AliITStrackerANN.h"
38
0db9364f 39const Double_t AliITStrackerANN::fgkPi = 3.141592653; // pi
40const Double_t AliITStrackerANN::fgkHalfPi = 1.570796327; // pi / 2
41const Double_t AliITStrackerANN::fgkTwoPi = 6.283185307; // 2 * pi
cec46807 42
43ClassImp(AliITStrackerANN)
44
cb729508 45
46AliITStrackerANN::AliITStrackerANN() : AliITStrackerV2(),
47fVertexX(0.0),
48fVertexY(0.0),
49fVertexZ(0.0),
50fSectorNum(0),
51fSectorWidth(0),
52fPolarInterval(0),
53fCurvNum(0),
54fCurvCut(0),
55fActMinimum(0),
56fEdge1(0),
57fEdge2(0),
58fStabThreshold(0),
59fTemperature(0),
60fGain2CostRatio(0),
61fExponent(0),
62fNLayers(0),
63fFirstModInLayer(0),
64fIndexMap(0),
65fFoundTracks(0),
66fNodes(0),
67fNeurons(0),
68fMsgLevel(0),
69fStructureOK(0),
70fGeom(0){
71 //Default constructor
72}
cec46807 73//__________________________________________________________________________________
74AliITStrackerANN::AliITStrackerANN(const AliITSgeom *geom, Int_t msglev)
e341247d 75: AliITStrackerV2(0),
cb729508 76fVertexX(0.0),
77fVertexY(0.0),
78fVertexZ(0.0),
79fSectorNum(0),
80fSectorWidth(0),
81fPolarInterval(0),
82fCurvNum(0),
83fCurvCut(0),
84fActMinimum(0),
85fEdge1(0),
86fEdge2(0),
87fStabThreshold(0),
88fTemperature(0),
89fGain2CostRatio(0),
90fExponent(0),
91fNLayers(0),
92fFirstModInLayer(0),
93fIndexMap(0),
94fFoundTracks(0),
95fNodes(0),
96fNeurons(0),
97fMsgLevel(msglev),
98fStructureOK(0),
99fGeom(0)
cec46807 100{
101/**************************************************************************
102
103 CONSTRUCTOR (standard-to-use version)
104
105 Arguments:
106 1) the ITS geometry used in the generated event
107 2) the flag for log-messages writing
108
109 The AliITSgeometry is used along the class,
00a7cc50 110 in order to translate the local AliITSRecPoint coordinates
cec46807 111 into the Global reference frame, which is necessary for the
112 Neural Network algorithm to operate.
113 In case of serialized use, the log messages should be excluded,
114 in order to save real execution time.
115
116 Operations:
117 - all pointer data members are initialized
118 (if possible, otherwise are set to NULL)
119 - all numeric data members are initialized to
120 values which allow the Neural Network to operate
121 even if nothing is externally set.
122
123 NOTE: it is possible that tracking an event
124 with these default values results in a non-sense.
125
126 **************************************************************************/
127
128 Int_t i;
129
130 // Get ITS geometry
131 fGeom = (AliITSgeom*)geom;
132
133 // Initialize the array of first module indexes per layer
134 fNLayers = geom->GetNlayers();
135 fFirstModInLayer = new Int_t[fNLayers + 1];
136 for (i = 0; i < fNLayers; i++) {
137 fFirstModInLayer[i] = fGeom->GetModuleIndex(i + 1, 1, 1);
138 }
139 fFirstModInLayer[fNLayers] = geom->GetIndexMax();
140
141 // initialization: no curvature cut steps
142 fCurvNum = 0;
143 fCurvCut = 0;
144
145 // initialization: 4 sectors (one for each quadrant)
146 fSectorNum = 4;
147 fSectorWidth = fgkHalfPi;
148
149 // initialization: theta offset of 20 degrees
150 fPolarInterval = 20.0;
151
152 // initialization: array structure not defined
153 fStructureOK = kFALSE;
154
155 // initialization: vertex in the origin
156 fVertexX = 0.0;
157 fVertexY = 0.0;
158 fVertexZ = 0.0;
159
160 // initialization: uninitialized point array
161 fNodes = 0;
162
163 // initialization: very large (unuseful) cut values
164 Int_t ilayer;
165 for (ilayer = 0; ilayer < 6; ilayer++) {
166 fThetaCut2D[ilayer] = TMath::Pi();
167 fThetaCut3D[ilayer] = TMath::Pi();
168 fHelixMatchCut[ilayer] = 1.0;
169 }
170
171 // initialization: inictial activation range between 0.3 and 0.7
172 fEdge1 = 0.3;
173 fEdge2 = 0.7;
174
175 // initialization: neural network operation & weights
176 fTemperature = 1.0;
177 fStabThreshold = 0.001;
178 fGain2CostRatio = 1.0;
179 fExponent = 1.0;
180 fActMinimum = 0.5;
181
182 // initialization: uninitialized array of neurons
183 fNeurons = 0;
184
185 // initialization: uninitialized array of tracks
186 fFoundTracks = 0;
187}
188
cb729508 189
190AliITStrackerANN::AliITStrackerANN(const AliITStrackerANN &n) : AliITStrackerV2((AliITStrackerV2&)n),
191fVertexX(n.fVertexX),
192fVertexY(n.fVertexY),
193fVertexZ(n.fVertexZ),
194fSectorNum(n.fSectorNum),
195fSectorWidth(n.fSectorWidth),
196fPolarInterval(n.fPolarInterval),
197fCurvNum(n.fCurvNum),
198fCurvCut(n.fCurvCut),
199fActMinimum(n.fActMinimum),
200fEdge1(n.fEdge1),
201fEdge2(n.fEdge2),
202fStabThreshold(n.fStabThreshold),
203fTemperature(n.fTemperature),
204fGain2CostRatio(n.fGain2CostRatio),
205fExponent(n.fExponent),
206fNLayers(n.fNLayers),
207fFirstModInLayer(n.fFirstModInLayer),
208fIndexMap(n.fIndexMap),
209fFoundTracks(n.fFoundTracks),
210fNodes(n.fNodes),
211fNeurons(n.fNeurons),
212fMsgLevel(n.fMsgLevel),
213fStructureOK(n.fStructureOK),
214fGeom(n.fGeom){
215 //Copy constructor
216}
217
218AliITStrackerANN& AliITStrackerANN::operator=(const AliITStrackerANN& arg){
219 //Assignment operator
220 this->~AliITStrackerANN();
221 new(this) AliITStrackerANN(arg);
222 return *this;
223}
224
cec46807 225//__________________________________________________________________________________
226void AliITStrackerANN::SetCuts
227(Int_t ncurv, Double_t *curv, Double_t *theta2D, Double_t *theta3D, Double_t *helix)
228
229/**************************************************************************
230
231 CUT SETTER
232
233 Allows for the definition of all kind of geometric cuts
234 which have been studied in for the creation of a neuron
235 from a pair of clusters C1 and C2 on consecutive layers.
236 Neuron will be created only if the pair passes ALL of these cuts.
237
238 At the moment, we define 4 kinds of geometrical cuts:
239 a) cut on the difference of the polar 'theta' angle;
240 b) cut on the angle between origin->C1 and C1->C2 in space;
241 c) cut on the curvature of the circle passing
242 through C1, C2 and the primary vertex;
243 d) cut on heli-matching of the same three points.
244
245 Arguments:
246 1) the number of curvature cut steps
247 2) the array of curvature cuts for each step
248 (its dimension is given by the argument 1)
249 3) array of 5 cut values (one for each consecutive lauer pair)
250 related to cut a)
251 4) array of 5 cut values (one for each consecutive lauer pair)
252 related to cut b)
253 5) array of 5 cut values (one for each consecutive lauer pair)
254 related to cut c)
255
256 Operations:
257 - gets the values for each cut and stores them in data members
258 - in the case of curvature cuts, the cut array
259 (whose size is not fixed) is allocated
260
261 NOTE: in case that the user wants to set onyl ONE of the 4 cuts array,
262 he can simply pass NULL arguments for other cuts, and (eventually)
263 a ZERO as the first argument (if curvature cuts have not to be set).
264
265 Anyway, all the cuts have to be set at least once.
266
267 **************************************************************************/
268{
269 // counter
270 Int_t i;
271
272 /*** Curvature cut setting ***/
273
274 // first of all, the curvature cuts are sorted in increasing order
275 // (from the smallest to the largest one)
276 Int_t *ind = new Int_t[ncurv];
277 TMath::Sort(ncurv, curv, ind, kFALSE);
278 // then, the curvature cut array is allocated and filled
279 // (a message with the list of defined cuts can be optionally shown)
280 fCurvCut = new Double_t[ncurv];
281 if (fMsgLevel >= 1) cout << "Number of curvature cuts: " << ncurv << endl;
282 for (i = 0; i < ncurv; i++) {
283 fCurvCut[i] = curv[ind[i]];
284 if (fMsgLevel >= 1) cout << " - " << fCurvCut[i] << endl;
285 }
286 fCurvNum = ncurv;
287
288 /*** 'Fixed' cuts setting ***/
289
290 // checks what cuts have to be set
291 Bool_t doTheta2D = (theta2D != 0);
292 Bool_t doTheta3D = (theta3D != 0);
293 Bool_t doHelix = (helix != 0);
294 // sets the cuts for all layer pairs
295 for (i = 0; i < fNLayers - 1; i++) {
296 if (doTheta2D) fThetaCut2D[i] = theta2D[i];
297 if (doTheta3D) fThetaCut3D[i] = theta3D[i];
298 if (doHelix) fHelixMatchCut[i] = helix[i];
299 }
300 // if required, lists the cuts
301 if (!fMsgLevel < 2) return;
302 cout << "Theta 2D cuts: ";
303 if (!doTheta2D) {
304 cout << "<not set>" << endl;
305 }
306 else {
307 cout << endl;
308 for (i = 0; i < fNLayers - 1; i++) {
309 cout << "For layers " << i << " --> " << i + 1;
310 cout << " cut = " << fThetaCut2D[i] << endl;
311 }
312 }
313 cout << "---" << endl;
314 cout << "Theta 3D cuts: ";
315 if (!doTheta3D) {
316 cout << "<not set>" << endl;
317 }
318 else {
319 cout << endl;
320 for (i = 0; i < fNLayers - 1; i++) {
321 cout << "For layers " << i << " --> " << i + 1;
322 cout << " cut = " << fThetaCut3D[i] << endl;
323 }
324 }
325 cout << "---" << endl;
326 cout << "Helix-match cuts: ";
327 if (!doHelix) {
328 cout << "<not set>" << endl;
329 }
330 else {
331 cout << endl;
332 for (i = 0; i < fNLayers - 1; i++) {
333 cout << "For layers " << i << " --> " << i + 1;
334 cout << " cut = " << fHelixMatchCut[i] << endl;
335 }
336 }
337 cout << "---" << endl;
338}
339
340//__________________________________________________________________________________
341Bool_t AliITStrackerANN::GetGlobalXYZ
342(Int_t refIndex,
343 Double_t &x, Double_t &y, Double_t &z, Double_t &ex2, Double_t &ey2, Double_t &ez2)
344
345/**************************************************************************
346
347 LOCAL TO GLOBAL TRANSLATOR
348
349 Taking information from the ITS geometry stored in the class,
350 gets a stored AliITScluster and calculates it coordinates
351 and errors in the global reference frame.
352 These values are stored in the variables,
353 which are passed by reference.
354
355 Arguments:
356 1) reference index for the cluster to use
357 2) (by reference) place to store the global X-coord into
358 3) (by reference) place to store the global Y-coord into
359 4) (by reference) place to store the global Z-coord into
360 5) (by reference) place to store the global X-coord error into
361 6) (by reference) place to store the global Y-coord error into
362 7) (by reference) place to store the global Z-coord error into
363
364 Operations:
365 essentially, determines the ITS module index from the
00a7cc50 366 detector index of the AliITSRecPoint object, and extracts
cec46807 367 the roto-translation from the ITS geometry, to convert
368 the local module coordinates into the global ones.
369
370 Return value:
371 - kFALSE if the given cluster index points to a non-existing
372 cluster, or if the layer number makes no sense (< 0 or > 6).
373 - otherwise, kTRUE (meaning a successful operation).
374
375 **************************************************************************/
376{
377 // checks if the layer is correct
378 Int_t ilayer = (refIndex & 0xf0000000) >> 28;
379 if (ilayer < 0 || ilayer >= fNLayers) {
380 Error("GetGlobalXYZ", "Wrong layer number: %d [range: %d - %d]", ilayer, 0, fNLayers);
381 return kFALSE;
382 }
383 // checks if the referenced cluster exists and corresponds to the passed reference
00a7cc50 384 AliITSRecPoint *refCluster = (AliITSRecPoint*) GetCluster(refIndex);
cec46807 385 if (!refCluster) {
386 Error("GetGlobalXYZ", "Cluster not found for index %d", refIndex);
387 return kFALSE;
388 }
389
390 // determine the detector number
391 Int_t detID = refCluster->GetDetectorIndex() + fFirstModInLayer[ilayer];
392
393 // get rotation matrix
394 Double_t rot[9];
395 fGeom->GetRotMatrix(detID, rot);
396
397 // get translation vector
398 Float_t tx,ty,tz;
399 fGeom->GetTrans(detID, tx, ty, tz);
400
401 // determine r and phi for the reference conversion
402 Double_t r = -(Double_t)tx * rot[1] + (Double_t)ty * rot[0];
403 if (ilayer == 0) r = -r;
404 Double_t phi = TMath::ATan2(rot[1],rot[0]);
405 if (ilayer == 0) phi -= fgkPi;
406
407 // sets values for X, Y, Z in global coordinates and their errors
408 Double_t cosPhi = TMath::Cos(phi);
409 Double_t sinPhi = TMath::Sin(phi);
410 x = r*cosPhi + refCluster->GetY()*sinPhi;
411 y = -r*sinPhi + refCluster->GetY()*cosPhi;
412 z = refCluster->GetZ();
413 ex2 = refCluster->GetSigmaY2()*sinPhi*sinPhi;
414 ey2 = refCluster->GetSigmaY2()*cosPhi*cosPhi;
415 ez2 = refCluster->GetSigmaZ2();
416
417 return kTRUE;
418}
419
420//__________________________________________________________________________________
421AliITStrackerANN::AliITSnode* AliITStrackerANN::AddNode(Int_t refIndex)
422
423/**************************************************************************
424
425 GENERATOR OF NEURAL NODES
426
427 Fills the array of neural 'nodes', which are the ITS clusters
428 translated in the global reference frame.
429 Given that the global coordinates are used many times, they are
430 stored in a well-defined structure, in the form of an embedded class.
431 Moreover, this class allows a faster navigation among points
432 and neurons, by means of some object arrays, storing only the
433 neurons which start from, or end to, the given node.
434 Finally, each node contains all the other nodes which match it
435 with respect to the fixed walues, in order to perform a faster
436 neuron-creation phase.
437
438 Arguments:
00a7cc50 439 1) reference index of the correlated AliITSRecPoint object
cec46807 440
441 Operations:
442 - allocates the new AliITSnode objects
443 - initializes its object arrays
444 - from the global coordinates, calculates the
445 'phi' and 'theta' coordinates, in order to store it
446 into the correct theta-slot and azimutal sector.
447
448 REturn values:
449 - the pointer of the creater AliITSnode object
450 - in case of errors, a waring is given and a NULL is returned
451
452 **************************************************************************/
453{
454 // create object and set the reference
455 AliITSnode *node = new AliITSnode;
456 if (!node) {
457 Warning("AddNode", "Error occurred when allocating AliITSnode");
458 return 0;
459 }
460 node->ClusterRef() = refIndex;
461
462 // calls the conversion function, which makes also some checks
463 // (layer number within range, existence of referenced cluster)
464 if ( !GetGlobalXYZ (
465 refIndex,
466 node->X(), node->Y(), node->Z(),
467 node->ErrX2(), node->ErrY2(), node->ErrZ2()
468 ) ) {return 0;}
469
470 // initializes the object arrays
471 node->Matches() = new TObjArray;
472 node->InnerOf() = new TObjArray;
473 node->OuterOf() = new TObjArray;
474
475 // finds azimutal and polar sector (in degrees)
476 Double_t phi = node->GetPhi() * 180.0 / fgkPi;
477 Double_t theta = node->GetTheta() * 180.0 / fgkPi;
478 Int_t isector = (Int_t)(phi / fSectorWidth);
479 Int_t itheta = (Int_t)theta;
480 Int_t ilayer = (refIndex & 0xf0000000) >> 28;
481
482 // selects the right TObjArray to store object into
483 TObjArray *sector = (TObjArray*)fNodes[ilayer][itheta]->At(isector);
484 sector->AddLast(node);
485
486 return node;
487}
488
489//__________________________________________________________________________________
490void AliITStrackerANN::CreateArrayStructure(Int_t nsectors)
491
492/**************************************************************************
493
494 ARRAY STRUCTURE CREATOR
495
496 Creates a structure of nested TObjArray's where the AliITSnode's
497 have to be stored:
498 - the first level is made by 6 arrays (one for each layer)
499 - the second level is made by 180 arrays (one for each int part of theta)
500 - the third level is made by a variable number of arrays
501 (one for each azimutal sector)
502
503 Arguments:
504 1) the number of azimutal sectors
505
506 Operations:
507 - calculates the width of each sector, from the argument
508 - allocates and initializes all array levels
509 - sets a flag which tells the user if this NECESSARY operation
510 has been performed (it is needed BEFORE performing tracking)
511
512 **************************************************************************/
513{
514 // Set the number of sectors and their width.
515 fSectorNum = nsectors;
516 fSectorWidth = 360.0 / (Double_t)fSectorNum;
517 if (fMsgLevel >= 2) {
518 cout << fSectorNum << " sectors --> sector width (degrees) = " << fSectorWidth << endl;
519 }
520
521 // Meaningful indexes
522 Int_t ilayer, isector, itheta;
523
524 // Mark for the created objects
525 TObjArray *sector = 0;
526
527 // First index: layer
528 fNodes = new TObjArray**[fNLayers];
529 for (ilayer = 0; ilayer < fNLayers; ilayer++) {
530 fNodes[ilayer] = new TObjArray*[180];
531 for (itheta = 0; itheta < 180; itheta++) fNodes[ilayer][itheta] = 0;
532 for (itheta = 0; itheta < 180; itheta++) {
533 fNodes[ilayer][itheta] = new TObjArray(nsectors);
534 for (isector = 0; isector < nsectors; isector++) {
535 sector = new TObjArray;
536 sector->SetOwner();
537 fNodes[ilayer][itheta]->AddAt(sector, isector);
538 }
539 }
540 }
541
542 // Sets a checking flag to TRUE.
543 // This flag is checked before filling up the arrays with the points.
544 fStructureOK = kTRUE;
545}
546
547//__________________________________________________________________________________
548Int_t AliITStrackerANN::ArrangePoints(char *exportFile)
549
550/**************************************************************************
551
552 POINTS LOCATOR
553
554 This function assembles the operation from the other above methods,
555 and fills the arrays with the clusters already stored in the
556 layers of the tracker.
557 Then, in order to use this method, the user MUSTs call LoadClusters()
558 before.
559
560 Arguments:
561 1) string for a file name where the global ccordinates
562 of all points can be exported (optional).
563 If this file must not be created, simply pass a NULL argument
564
565 Operations:
00a7cc50 566 - for each AliITSRecPoint in each AliITSlayer, a ne AliITSnode
cec46807 567 is created and stored in the correct location.
568
569 Return values:
570 - the number of stored points
571 - when errors occur, or no points are found, 0 is returned
572
573 **************************************************************************/
574{
575 // Check if the array structure has been created
576 if (!fStructureOK) {
577 Error("ArrangePoints", "Structure NOT defined. Call CreateArrayStructure() first");
578 return 0;
579 }
580
581 // meaningful indexes
582 Int_t ientry, ilayer, nentries = 0, index;
583 Int_t nPtsLayer = 0;
584
585 // if the argument is not NULL, a file is opened
586 fstream file(exportFile, ios::out);
587 if (!exportFile || file.fail()) {
588 file.close();
589 exportFile = 0;
590 }
591
592 // scan all layers for node creation
593 for (ilayer = 0; ilayer < fNLayers; ilayer++) {
594 nPtsLayer = GetNumberOfClustersLayer(ilayer);
595 if (fMsgLevel >= 1) {
596 cout << "Layer " << ilayer << " --> " << nPtsLayer << " clusters" << endl;
597 }
598 for (ientry = 0; ientry < nPtsLayer; ientry++) {
599 // calculation of cluster index : (Bit mask LLLLIIIIIIIIIIII)
600 // (L = bits used for layer)
601 // (I = bits used for position in layer)
602 index = ilayer << 28;
603 index += ientry;
604 // add new AliITSnode object
605 AliITSnode *n = AddNode(index);
606 if ( (n != NULL) && exportFile ) {
607 file << index << ' ' << n->X() << ' ' << n->Y() << ' ' << n->Z() << endl;
608 }
609 }
610 nentries += nPtsLayer;
611 }
612
613 // a conventional final message is put at the end of file
614 if (exportFile) {
615 file << "-1 0.0 0.0 0.0" << endl;
616 file.close();
617 }
618
619 // returns the number of points processed
620 return nentries;
621}
622
623//__________________________________________________________________________________
624void AliITStrackerANN::StoreOverallMatches()
625
626/**************************************************************************
627
628 NODE-MATCH ANALYSIS
629
630 Once the nodes have been created, a firs analysis is to check
631 what pairs will satisfy at least the 'fixed' cuts (theta, helix-match)
632 and the most permissive (= larger) curvature cut.
633 All these node pairs are suitable for neuron creation.
634 In fact, when performing a Neural Tracking step, the only further check
635 will be a check against the current curvature step, while the other
636 are always the same.
637 For thi purpose, each AliITSnode has a data member, named 'fMatches'
638 which contains references to all other AliITSnodes in the successive layer
639 that form, with it, a 'good' pair, with respect to the above cited cuts.
640 Then, in each step for neuron creation, the possible neurons starting from
641 each node will be searched ONLY within the nodes referenced in fMatches.
642 This, of course, speeds up a lot the neuron creation procedure, at the
643 cost of some memory occupation, which results not to be critical.
644
645 Operations:
646 - for each AliITSnode, matches are found according to the criteria
647 expressed above, and stored in the node->fMatches array
648
649 **************************************************************************/
650{
651 // meaningful counters
652 Int_t ilayer, isector, itheta1, itheta2, check;
653 TObjArray *list1 = 0, *list2 = 0;
654 AliITSnode *node1 = 0, *node2 = 0;
655 Double_t thetaMin, thetaMax;
656 Int_t imin, imax;
657
658 // Scan for each sector
659 for (isector = 0; isector < fSectorNum; isector++) {
660 // sector is chosen once for both lists
661 for (ilayer = 0; ilayer < fNLayers - 1; ilayer++) {
662 for (itheta1 = 0; itheta1 < 180; itheta1++) {
663 list1 = (TObjArray*)fNodes[ilayer][itheta1]->At(isector);
664 TObjArrayIter iter1(list1);
665 while ( (node1 = (AliITSnode*)iter1.Next()) ) {
666 if (node1->IsUsed()) continue;
667 // clear an eventually already present array
668 // node1->Matches()->Clear();
669 // get the global coordinates and defines the theta interval from cut
670 thetaMin = (node1->GetTheta() * 180.0 / fgkPi) - fPolarInterval;
671 thetaMax = (node1->GetTheta() * 180.0 / fgkPi) + fPolarInterval;
672 imin = (Int_t)thetaMin;
673 imax = (Int_t)thetaMax;
674 if (imin < 0) imin = 0;
675 if (imax > 179) imax = 179;
676 // loop on the selected theta slots
677 for (itheta2 = imin; itheta2 <= imax; itheta2++) {
678 list2 = (TObjArray*)fNodes[ilayer + 1][itheta2]->At(isector);
679 TObjArrayIter iter2(list2);
680 while ( (node2 = (AliITSnode*)iter2.Next()) ) {
681 check = PassAllCuts(node1, node2, fCurvNum - 1, fVertexX, fVertexY, fVertexZ);
682 if (check == 0) {
683 node1->Matches()->AddLast(node2);
684 }
685 } // while (node2...)
686 } // for (itheta2...)
687 } // while (node1...)
688 } // for (itheta...)
689 } // for (ilayer...)
690 } // for (isector...)
691}
692
693//__________________________________________________________________________________
694Int_t AliITStrackerANN::PassAllCuts
695(AliITSnode *inner, AliITSnode *outer, Int_t curvStep,
696 Double_t vx, Double_t vy, Double_t vz)
697{
698// ***********************************************************************************
699//
700// This check is called in the above method for finding the matches of each node
701// It check the passed point pair against all the fixed cuts and a specified
702// curvature cut, among all the ones which have been defined.
703// The cuts need a vertex-constraint, which is not absolute, but it is passed
704// as argument.
705//
706// Arguments:
707// 1) the point in the inner layer
708// 2) the point in the outer layer
709// 3) curvature step for the curvature cut check (preferably the last)
710// 4) X of the used vertex
711// 5) Y of the used vertex
712// 6) Z of the used vertex
713//
714// Operations:
715// - if necessary, swaps the two points
716// (the first must be in the innermost of the two layers)
717// - checks for the theta cuts
718// - calculates the circle passing through the vertex
719// and the given points and checks for the curvature cut
720// - using the radius calculated there, checks for the helix-math cut
721//
722// Return values:
723// 0 - All cuts passed
724// 1 - theta 2D cut not passed
725// 2 - theta 3D cut not passed
726// 3 - curvature calculated but cut not passed
727// 4 - curvature not calculated (division by zero)
728// 5 - helix cut not passed
729// 6 - curvature inxed out of range
730//
731// ***********************************************************************************
732
733 // Check for curvature index
734 if (curvStep < 0 || curvStep >= fCurvNum) return 6;
735
736 // Swap points in order that r1 < r2
737 AliITSnode *temp = 0;
738 if (outer->GetLayer() < inner->GetLayer()) {
739 temp = outer;
740 outer = inner;
741 inner = temp;
742 }
743
744 // All cuts are variable according to the layer of the
745 // innermost point (the other point will surely be
746 // in the further one, because we don't check poin pairs
747 // which are not in adjacent layers)
748 // The reference is given by the innermost point.
749 Int_t layRef = inner->GetLayer();
750
751 // The calculations in the transverse plane are made in
752 // a shifted reference frame, whose origin corresponds to
753 // the reference point passed in the argument.
754 Double_t xIn = inner->X() - vx;
755 Double_t xOut = outer->X() - vx;
756 Double_t yIn = inner->Y() - vy;
757 Double_t yOut = outer->Y() - vy;
758 Double_t zIn = inner->Z() - vz;
759 Double_t zOut = outer->Z() - vz;
760 Double_t rIn = TMath::Sqrt(xIn*xIn + yIn*yIn);
761 Double_t rOut = TMath::Sqrt(xOut*xOut + yOut*yOut);
762
763 // Check for theta cut.
764 // There are two different angular cuts:
765 // one w.r. to the angle in the 2-dimensional r-z plane...
766 Double_t dthetaRZ;
767 TVector3 origin2innerRZ(zIn, rIn, 0.0);
768 TVector3 inner2outerRZ(zOut - zIn, rOut - rIn, 0.0);
769 dthetaRZ = origin2innerRZ.Angle(inner2outerRZ) * 180.0 / fgkPi;
770 if (dthetaRZ > fThetaCut2D[layRef]) {
771 return 1;
772 // r-z theta cut not passed ---> 1
773 }
774 // ...and another w.r. to the angle in the 3-dimensional x-y-z space
775 Double_t dthetaXYZ;
776 TVector3 origin2innerXYZ(xIn, yIn, zIn);
777 TVector3 inner2outerXYZ(xOut - xIn, yOut - yIn, zOut - zIn);
778 dthetaXYZ = origin2innerXYZ.Angle(inner2outerXYZ) * 180.0 / fgkPi;
779 if (dthetaXYZ > fThetaCut3D[layRef]) {
780 return 2;
781 // x-y-z theta cut not passed ---> 2
782 }
783
784 // Calculation & check of curvature
785 Double_t dx = xIn - xOut;
786 Double_t dy = yIn - yOut;
787 Double_t num = 2.0 * (xIn*yOut - xOut*yIn);
788 Double_t den = rIn*rOut*sqrt(dx*dx + dy*dy);
789 Double_t curv = 0.;
790 if (den != 0.) {
791 curv = TMath::Abs(num / den);
792 if (curv > fCurvCut[curvStep]) {
793 return 3;
794 // curvature too large for cut ---> 3
795 }
796 }
797 else {
798 Error("PassAllCuts", "Curvature calculations gives zero denominator");
799 return 4;
800 // error: denominator = 0 ---> 4
801 }
802
803 // Calculation & check of helix matching
804 Double_t helMatch = 0.0;
805 Double_t arcIn = 2.0 * rIn * curv;
806 Double_t arcOut = 2.0 * rOut * curv;
807 if (arcIn > -1.0 && arcIn < 1.0)
808 arcIn = TMath::ASin(arcIn);
809 else
810 arcIn = ((arcIn > 0.0) ? 0.5 : 1.5) * TMath::Pi();
811 if (arcOut > -1.0 && arcOut < 1.0)
812 arcOut = TMath::ASin(arcOut);
813 else
814 arcOut = ((arcOut > 0.0) ? 0.5 : 1.5) * TMath::Pi();
815 arcIn /= 2.0 * curv;
816 arcOut /= 2.0 * curv;
817 if (arcIn == 0.0 || arcOut == 0.0) {
818 Error("PassAllCuts", "Calculation returns zero-length arcs: l1=%f, l2=%f", arcIn, arcOut);
819 return 4;
820 // error: circumference arcs seem to equal zero ---> 4
821 }
822 helMatch = TMath::Abs(zIn / arcIn - zOut / arcOut);
823 if (helMatch > fHelixMatchCut[layRef]) {
824 return 5;
825 // helix match cut not passed ---> 5
826 }
827
828 // ALL CUTS PASSED ---> 0
829 return 0;
830}
831
832//__________________________________________________________________________________
833Bool_t AliITStrackerANN::PassCurvCut
834(AliITSnode *inner, AliITSnode *outer,
835 Int_t curvStep,
836 Double_t vx, Double_t vy, Double_t vz)
837{
838//***********************************************************************************
839//
840// This method operates essentially like the above one, but it is used
841// during a single step of Neural Tracking, where the curvature cut
842// changes.
843// Then, not necessaryly all the nodes stored in the fMatches array
844// will be suitable for neuron creation in an intermediate step.
845//
846// It has the same arguments of the PassAllCuts() method, but
847// the theta cut is not checked.
848// Moreover, it has a boolean return value.
849//
850//***********************************************************************************
851
852 // Check for curvature index
853 if (curvStep < 0 || curvStep >= fCurvNum) return 6;
854
855 // Find the reference layer
856 Int_t layIn = inner->GetLayer();
857 Int_t layOut = outer->GetLayer();
858 Int_t layRef = (layIn < layOut) ? layIn : layOut;
859
860 // The calculations in the transverse plane are made in
861 // a shifted reference frame, whose origin corresponds to
862 // the reference point passed in the argument.
863 Double_t xIn = inner->X() - vx;
864 Double_t xOut = outer->X() - vx;
865 Double_t yIn = inner->Y() - vy;
866 Double_t yOut = outer->Y() - vy;
867 Double_t zIn = inner->Z() - vz;
868 Double_t zOut = outer->Z() - vz;
869 Double_t rIn = TMath::Sqrt(xIn*xIn + yIn*yIn);
870 Double_t rOut = TMath::Sqrt(xOut*xOut + yOut*yOut);
871
872 // Calculation & check of curvature
873 Double_t dx = xIn - xOut;
874 Double_t dy = yIn - yOut;
875 Double_t num = 2.0 * (xIn*yOut - xOut*yIn);
876 Double_t den = rIn*rOut*sqrt(dx*dx + dy*dy);
877 Double_t curv = 0.;
878 /* OLD VERSION
879 if (den != 0.) {
880 curv = TMath::Abs(num / den);
881 if (curv > fCurvCut[curvStep]) return kFALSE;
882 return kTRUE;
883 }
884 else
885 return kFALSE;
886 */
887 // NEW VERSION
888 if (den != 0.) {
889 curv = TMath::Abs(num / den);
890 if (curv > fCurvCut[curvStep]) {
891 return kFALSE;
892 }
893 }
894 else {
895 Error("PassAllCuts", "Curvature calculations gives zero denominator");
896 return kFALSE;
897 }
898
899 // Calculation & check of helix matching
900 Double_t helMatch = 0.0;
901 Double_t arcIn = 2.0 * rIn * curv;
902 Double_t arcOut = 2.0 * rOut * curv;
903 if (arcIn > -1.0 && arcIn < 1.0)
904 arcIn = TMath::ASin(arcIn);
905 else
906 arcIn = ((arcIn > 0.0) ? 0.5 : 1.5) * TMath::Pi();
907 if (arcOut > -1.0 && arcOut < 1.0)
908 arcOut = TMath::ASin(arcOut);
909 else
910 arcOut = ((arcOut > 0.0) ? 0.5 : 1.5) * TMath::Pi();
911 arcIn /= 2.0 * curv;
912 arcOut /= 2.0 * curv;
913 if (arcIn == 0.0 || arcOut == 0.0) {
914 Error("PassAllCuts", "Calculation returns zero-length arcs: l1=%f, l2=%f", arcIn, arcOut);
915 return 4;
916 // error: circumference arcs seem to equal zero ---> 4
917 }
918 helMatch = TMath::Abs(zIn / arcIn - zOut / arcOut);
919 return (helMatch <= fHelixMatchCut[layRef]);
920}
921
922//__________________________________________________________________________________
923void AliITStrackerANN::PrintMatches(Bool_t stop)
924{
925// Prints the list of points which appear to match
926// each one of them, according to the preliminary
927// overall cuts.
928// The arguments states if a pause is required after printing
929// the matches for each one. In this case, a keypress is needed.
930
931 TObjArray *sector = 0;
932 Int_t ilayer, isector, itheta, nF;
933 AliITSnode *node1 = 0, *node2 = 0;
00a7cc50 934 //AliITSRecPoint *cluster1 = 0, *cluster2 = 0;
cec46807 935
936 for (ilayer = 0; ilayer < 6; ilayer++) {
937 for (isector = 0; isector < fSectorNum; isector++) {
938 for (itheta = 0; itheta < 180; itheta++) {
939 sector = (TObjArray*)fNodes[ilayer][itheta]->At(isector);
940 TObjArrayIter points(sector);
941 while ( (node1 = (AliITSnode*)points.Next()) ) {
942 nF = (Int_t)node1->Matches()->GetEntries();
943 cout << "Node layer: " << node1->GetLayer() << " --> ";
944 if (!nF) {
945 cout << "NO Matches!!!" << endl;
946 continue;
947 }
948 cout << nF << " Matches" << endl;
949 cout << "Reference cluster: " << hex << node1->ClusterRef() << endl;
950 TObjArrayIter matches(node1->Matches());
951 while ( (node2 = (AliITSnode*)matches.Next()) ) {
952 cout << "Match with " << hex << node2->ClusterRef() << endl;
953 }
954 if (stop) {
955 cout << "Press a key" << endl;
956 cin.get();
957 }
958 }
959 }
960 }
961 }
962}
963
964//__________________________________________________________________________________
965void AliITStrackerANN::ResetNodes(Int_t isector)
966{
967/***********************************************************************************
968
969 NODE NEURON ARRAY CLEANER
970
971 After a neural tracking step, this method
972 clears the arrays 'fInnerOf' and 'fOuterOf' of each AliITSnode
973
974 Arguments:
975 - the sector where the operation is being executed
976
977 ***********************************************************************************/
978
979 Int_t ilayer, itheta;
980 TObjArray *sector = 0;
981 AliITSnode *node = 0;
982 for (ilayer = 0; ilayer < fNLayers; ilayer++) {
983 for (itheta = 0; itheta < 180; itheta++) {
984 sector = (TObjArray*)fNodes[ilayer][itheta]->At(isector);
985 TObjArrayIter iter(sector);
986 for (;;) {
987 node = (AliITSnode*)iter.Next();
988 if (!node) break;
989 node->InnerOf()->Clear();
990 node->OuterOf()->Clear();
991 /*
992 delete node->InnerOf();
993 delete node->OuterOf();
994 node->InnerOf() = new TObjArray;
995 node->OuterOf() = new TObjArray;
996 */
997 }
998 }
999 }
1000}
1001
1002//__________________________________________________________________________________
1003Int_t AliITStrackerANN::CreateNeurons
1004(AliITSnode *node, Int_t curvStep, Double_t vx, Double_t vy, Double_t vz)
1005{
1006 // This method is used to create alle suitable neurons starting from
1007 // a single AliITSnode. Each unit is also stored in the fInnerOf array
1008 // of the passed node, and in the fOuterOf array of the other neuron edge.
1009 // In the new implementation of the intermediate check steps, a further one
1010 // is made, which chechs how well a helix is matched by three points
1011 // in three consecutive layers.
1012 // Then, a vertex-constrained check is made with vertex located
1013 // in a layer L, for points in layers L+1 and L+2.
1014 //
1015 // In order to do this, the creator works recursively, in a tree-visit like operation.
1016 // The neurons are effectively created only if the node argument passed is in
1017 // the 5th layer (they are created between point of 5th and 6th layer).
1018 // If the node is in an inner layer, its coordinates are passet as vertex for a nested
1019 // call of the same function in the next two layers.
1020 //
1021 // Arguments:
1022 // 1) reference node
1023 // 2) current curvature cut step
1024 // 3) X of referenced temporary (not primary) vertex
1025 // 4) Y of referenced temporary (not primary) vertex
1026 // 5) Z of referenced temporary (not primary) vertex
1027 //
1028 // Operations:
1029 // - if the layer is the 5th, neurons are created with nodes
1030 // in the fMatches array of the passed node
1031 // - otherwise, the X, Y, Z of the passed node are given as
1032 // vertex and the same procedure is recursively called for all
1033 // nodes in the fMatches array of the passed one.
1034 //
1035 // Return values:
1036 // - the total number of neurons created from the passed one
1037 // summed with all neurons created from all nodes well matched with it
1038 // (assumes a meaning only for nodes in the first layer)
1039
1040 // local variables
1041 Int_t made = 0; // counter
1042 Bool_t found = 0; // flag
1043 AliITSnode *match = 0; // cursor for a AliITSnode array
1044 AliITSneuron *unit = 0; // cursor for a AliITSneuron array
1045
1046 // --> Case 0: the passed node has already been used
1047 // as member of a track found in a previous step.
1048 // In this case, of course, the function exits.
1049 if (node->IsUsed()) return 0;
1050
1051 // --> Case 1: there are NO well-matched points.
1052 // This can happen in all ITS layers, but it happens **for sure**
1053 // for a node in the 'last' layer.
1054 // Even in this case, the function exits.
1055 if (node->Matches()->IsEmpty()) return 0;
1056
1057 // --> Case 2: there are well-matched points.
1058 // In this case, the function creates a neuron for each
1059 // well-matched pair (according to the cuts for the current step)
1060 // Moreover, before storing the neuron, a check is necessary
1061 // to avoid the duplicate creation of the same neuron twice.
1062 // (This could happen if the 3 last arguments of the function
1063 // are close enough to cause a good match for the current step
1064 // between two points, independently of their difference).
1065 // Finally, a node is skipped if it has already been used.
1066 // For each matched point for which a neuron is created, the procedure is
1067 // recursively called.
1068 TObjArrayIter matches(node->Matches());
1069 while ( (match = (AliITSnode*)matches.Next()) ) {
1070 if (match->IsUsed()) continue;
1071 if (!PassCurvCut(node, match, curvStep, vx, vy, vz)) continue;
1072 found = kFALSE;
1073 if (!node->InnerOf()->IsEmpty()) {
1074 TObjArrayIter presentUnits(node->InnerOf());
1075 while ( (unit = (AliITSneuron*)presentUnits.Next()) ) {
1076 if (unit->Inner() == node && unit->Outer() == match) {
1077 found = kTRUE;
1078 break;
1079 }
1080 }
1081 }
1082 if (found) continue;
1083 AliITSneuron *unit = new AliITSneuron(node, match, fEdge2, fEdge1);
1084 fNeurons->AddLast(unit);
1085 node->InnerOf()->AddLast(unit);
1086 match->OuterOf()->AddLast(unit);
1087 made += CreateNeurons(match, curvStep, node->X(), node->Y(), node->Z());
1088 made++;
1089 }
1090
1091 // Of course, the return value contains the number of neurons
1092 // counting in also the oned created in all levels of recursive calls.
1093 return made;
1094}
1095
1096//__________________________________________________________________________________
1097Int_t AliITStrackerANN::CreateNetwork(Int_t sector, Int_t curvStep)
1098{
1099 // This function simply recalls the CreateNeurons() method for each node
1100 // in the first layer, for the current sector.
1101 // This generates the whole network, thanks to the recursive calls.
1102 //
1103 // Arguments:
1104 // 1) current sector
1105 // 2) current curvature step
1106 //
1107 // Operations:
1108 // - scans the nodes array for all theta's in the current sector
1109 // and layer 0, and calls the CreateNeurons() function.
1110
1111 // removes all eventually present neurons
1112 if (fNeurons) delete fNeurons;
1113 fNeurons = new TObjArray;
1114 fNeurons->SetOwner(kTRUE);
1115
1116 // calls the ResetNodes() function to free the AliITSnode arrays
1117 if (fMsgLevel >= 2) {
1118 cout << "Sector " << sector << " PHI = ";
1119 cout << fSectorWidth * (Double_t)sector << " --> ";
1120 cout << fSectorWidth * (Double_t)(sector + 1) << endl;
1121 cout << "Curvature step " << curvStep << " [cut = " << fCurvCut[curvStep] << "]" << endl;
1122 }
1123 ResetNodes(sector);
1124
1125 // meaningful counters
1126 Int_t itheta, neurons = 0;
1127 TObjArray *lstSector = 0;
1128
1129 // NEW VERSION
1130 Double_t vx[6], vy[6], vz[6];
1131 AliITSnode *p[6] = {0, 0, 0, 0, 0, 0};
1132 for (itheta = 0; itheta < 180; itheta++) {
1133 lstSector = (TObjArray*)fNodes[0][itheta]->At(sector);
1134 TObjArrayIter lay0(lstSector);
1135 while ( (p[0] = (AliITSnode*)lay0.Next()) ) {
1136 if (p[0]->IsUsed()) continue;
1137 vx[0] = fVertexX;
1138 vy[0] = fVertexY;
1139 vz[0] = fVertexZ;
1140 neurons += CreateNeurons(p[0], curvStep, fVertexX, fVertexY, fVertexZ);
1141 /*
1142 TObjArrayIter lay1(p[0]->Matches());
1143 while ( (p[1] = (AliITSnode*)lay1.Next()) ) {
1144 if (p[1]->IsUsed()) continue;
1145 if (!PassCurvCut(p[0], p[1], curvStep, vx[0], vy[0], vz[0])) continue;
1146 unit = new AliITSneuron;
1147 unit->Inner() = p[0];
1148 unit->Outer() = p[1];
1149 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1150 unit->fGain = new TObjArray;
1151 fNeurons->AddLast(unit);
1152 p[0]->InnerOf()->AddLast(unit);
1153 p[1]->OuterOf()->AddLast(unit);
1154 neurons++;
1155 vx[1] = p[0]->X();
1156 vy[1] = p[0]->Y();
1157 vz[1] = p[0]->Z();
1158 TObjArrayIter lay2(p[1]->Matches());
1159 while ( (p[2] = (AliITSnode*)lay2.Next()) ) {
1160 if (p[2]->IsUsed()) continue;
1161 if (!PassCurvCut(p[1], p[2], curvStep, vx[1], vy[1], vz[1])) continue;
1162 unit = new AliITSneuron;
1163 unit->Inner() = p[1];
1164 unit->Outer() = p[2];
1165 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1166 unit->fGain = new TObjArray;
1167 fNeurons->AddLast(unit);
1168 p[1]->InnerOf()->AddLast(unit);
1169 p[2]->OuterOf()->AddLast(unit);
1170 neurons++;
1171 vx[2] = p[1]->X();
1172 vy[2] = p[1]->Y();
1173 vz[2] = p[1]->Z();
1174 TObjArrayIter lay3(p[2]->Matches());
1175 while ( (p[3] = (AliITSnode*)lay3.Next()) ) {
1176 if (p[3]->IsUsed()) continue;
1177 if (!PassCurvCut(p[2], p[3], curvStep, vx[2], vy[2], vz[2])) continue;
1178 unit = new AliITSneuron;
1179 unit->Inner() = p[2];
1180 unit->Outer() = p[3];
1181 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1182 unit->fGain = new TObjArray;
1183 fNeurons->AddLast(unit);
1184 p[2]->InnerOf()->AddLast(unit);
1185 p[3]->OuterOf()->AddLast(unit);
1186 neurons++;
1187 vx[3] = p[2]->X();
1188 vy[3] = p[2]->Y();
1189 vz[3] = p[2]->Z();
1190 TObjArrayIter lay4(p[3]->Matches());
1191 while ( (p[4] = (AliITSnode*)lay4.Next()) ) {
1192 if (p[4]->IsUsed()) continue;
1193 if (!PassCurvCut(p[3], p[4], curvStep, vx[3], vy[3], vz[3])) continue;
1194 unit = new AliITSneuron;
1195 unit->Inner() = p[3];
1196 unit->Outer() = p[4];
1197 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1198 unit->fGain = new TObjArray;
1199 fNeurons->AddLast(unit);
1200 p[3]->InnerOf()->AddLast(unit);
1201 p[4]->OuterOf()->AddLast(unit);
1202 neurons++;
1203 vx[4] = p[3]->X();
1204 vy[4] = p[3]->Y();
1205 vz[4] = p[3]->Z();
1206 TObjArrayIter lay5(p[4]->Matches());
1207 while ( (p[5] = (AliITSnode*)lay5.Next()) ) {
1208 if (p[5]->IsUsed()) continue;
1209 if (!PassCurvCut(p[4], p[5], curvStep, vx[4], vy[4], vz[4])) continue;
1210 unit = new AliITSneuron;
1211 unit->Inner() = p[4];
1212 unit->Outer() = p[5];
1213 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1214 unit->fGain = new TObjArray;
1215 fNeurons->AddLast(unit);
1216 p[4]->InnerOf()->AddLast(unit);
1217 p[5]->OuterOf()->AddLast(unit);
1218 neurons++;
1219 } // while (p[5])
1220 } // while (p[4])
1221 } // while (p[3])
1222 } // while (p[2])
1223 } // while (p[1])
1224 */
1225 } // while (p[0])
1226 } // for (itheta...)
1227 // END OF NEW VERSION
1228
1229 /* OLD VERSION
1230 for (ilayer = 0; ilayer < 6; ilayer++) {
1231 for (itheta = 0; itheta < 180; itheta++) {
1232 lstSector = (TObjArray*)fNodes[ilayer][itheta]->At(sector_idx);
1233 TObjArrayIter inners(lstSector);
1234 while ( (inner = (AliITSnode*)inners.Next()) ) {
1235 if (inner->GetUser() >= 0) continue;
1236 TObjArrayIter outers(inner->Matches());
1237 while ( (outer = (AliITSnode*)outers.Next()) ) {
1238 if (outer->GetUser() >= 0) continue;
1239 if (!PassCurvCut(inner, outer, curvStep, fVX, fVY, fVZ)) continue;
1240 unit = new AliITSneuron;
1241 unit->Inner() = inner;
1242 unit->Outer() = outer;
1243 unit->Activation() = gRandom->Rndm() * (fEdge1 - fEdge2) + fEdge2;
1244 unit->fGain = new TObjArray;
1245 fNeurons->AddLast(unit);
1246 inner->InnerOf()->AddLast(unit);
1247 outer->OuterOf()->AddLast(unit);
1248 neurons++;
1249 } // for (;;)
1250 } // for (;;)
1251 } // for (itheta...)
1252 } // for (ilayer...)
1253 */
1254
1255 fNeurons->SetOwner();
1256 return neurons;
1257 }
1258
1259 //__________________________________________________________________________________
1260Int_t AliITStrackerANN::LinkNeurons()
1261{
1262/***********************************************************************************
1263
1264 SYNAPSIS GENERATOR
1265
1266 Scans the whole neuron array, in order to find all neuron pairs
1267 which are connected in sequence and share a positive weight.
1268 For each of them, an AliITSlink is created, which stores
1269 the weight value, and will allow for a faster calculation
1270 of the total neural input for each updating cycle.
1271
1272 Every neuron contains an object array which stores all AliITSlink
1273 objects which point to sequenced units, with the respective weights.
1274
1275 Return value:
1276 - the number of link created for the neural network.
1277 If they are 0, no updating can be done and the step is skipped.
1278
1279 ***********************************************************************************/
1280
1281 // meaningful indexes
1282 Int_t total = 0;
1283 Double_t weight = 0.0;
1284 TObjArrayIter neurons(fNeurons), *iter;
1285 AliITSneuron *neuron = 0, *test = 0;
1286
1287 // scan in the neuron array
1288 for (;;) {
1289 neuron = (AliITSneuron*)neurons.Next();
1290 if (!neuron) break;
1291 // checks for neurons startin from its head ( -> )
1292 iter = (TObjArrayIter*)neuron->Inner()->OuterOf()->MakeIterator();
1293 for (;;) {
1294 test = (AliITSneuron*)iter->Next();
1295 if (!test) break;
1296 weight = Weight(test, neuron);
1297 if (weight > 0.0) neuron->Gain()->AddLast(new AliITSlink(weight, test));
1298 total++;
1299 }
1300 delete iter;
1301 // checks for neurons ending in its tail ( >- )
1302 iter = (TObjArrayIter*)neuron->Outer()->InnerOf()->MakeIterator();
1303 for (;;) {
1304 test = (AliITSneuron*)iter->Next();
1305 if (!test) break;
1306 weight = Weight(neuron, test);
1307 if (weight > 0.0) neuron->Gain()->AddLast(new AliITSlink(weight, test));
1308 total++;
1309 }
1310 delete iter;
1311 }
1312 return total;
1313}
1314
1315//__________________________________________________________________________________
1316Bool_t AliITStrackerANN::Update()
1317{
1318/***********************************************************************************
1319
1320 Performs a single updating cycle.
1321
1322 Operations:
1323 - for each neuron, gets the activation with the neuron Activate() method
1324 - checks if stability has been reached (compare mean activation variation
1325 with the stability threshold data member)
1326
1327 Return values:
1328 - kTRUE means that the neural network has stabilized
1329 - kFALSE means that another updating cycle is needed
1330
1331 ***********************************************************************************/
1332
1333 Double_t actVar = 0.0, totDiff = 0.0;
1334 TObjArrayIter iter(fNeurons);
1335 AliITSneuron *unit;
1336 for (;;) {
1337 unit = (AliITSneuron*)iter.Next();
1338 if (!unit) break;
1339 actVar = unit->Activate(fTemperature);
1340 // calculation the relative activation variation
1341 totDiff += actVar;
1342 }
1343 totDiff /= fNeurons->GetSize();
1344 return (totDiff < fStabThreshold);
1345}
1346
1347//__________________________________________________________________________________
1348void AliITStrackerANN::FollowChains(Int_t sector)
1349{
1350/***********************************************************************************
1351
1352 CHAINS CREATION
1353
1354 After that the neural network has stabilized,
1355 the final step is to create polygonal chains
1356 of clusters, one in each layer, which represent
1357 the tracks recognized by the neural algorithm.
1358 This is made by means of a choice of the best
1359 neuron among the ones starting from each point.
1360
1361 Once that such neuron is selected, its inner point
1362 will set the 'fNext' field to its outer point, and
1363 similarly, its outer point will set the 'fPrev' field
1364 to its inner point.
1365 This defines a bi-directional sequence.
1366
1367 In this procedure, it can happen that many neurons
1368 which have the head of the arrow in a given node, will
1369 all select as best following the neuron with the largest
1370 activation starting in that point.
1371 This results in MANY nodes which have the same 'fNext'.
1372 But, this field will be set to NULL for all these points,
1373 but the only one which is pointed by the 'fPrev' field
1374 of this shared node.
1375
1376 ***********************************************************************************/
1377
1378 // meaningful counters
1379 Int_t itheta, ilayer;
1380 TObjArray *lstSector = 0;
1381 Double_t test = fActMinimum;
1382 AliITSnode *p = 0;
1383 AliITSneuron *n = 0;
1384
1385 // scan the whole collection of nodes
1386 for (ilayer = 0; ilayer < fNLayers; ilayer++) {
1387 for (itheta = 0; itheta < 180; itheta++) {
1388 // get the array of point in a given layer/theta-slot/sector
1389 lstSector = (TObjArray*)fNodes[ilayer][itheta]->At(sector);
1390 TObjArrayIter nodes(lstSector);
1391 while ( (p = (AliITSnode*)nodes.Next()) ) {
1392 // if the point is used, it is skipped
1393 if (p->IsUsed()) continue;
1394 // initially, fNext points to nothing, and
1395 // the comparison value is set to the minimum activation
1396 // which allows to say that a neuron is turned 'on'
1397 // a node from which only 'off' neurons start is probably
1398 // a noise point, which will be excluded from the reconstruction.
1399 test = fActMinimum;
1400 p->Next() = 0;
1401 TObjArrayIter innerof(p->InnerOf());
1402 while ( (n = (AliITSneuron*)innerof.Next()) ) {
1403 // if the examined neuron has not the largest activation
1404 // it is skipped and removed from array of all neurons
1405 // and of its outer point (its inner is the cursor p)
1406 if (n->Activation() < test) {
1407 p->InnerOf()->Remove(n);
1408 n->Outer()->OuterOf()->Remove(n);
1409 delete fNeurons->Remove(n);
1410 continue;
1411 }
1412 // otherwise, its activation becomes the maximum reference
1413 p->Next() = n->Outer();
1414 // at the exit of the while(), the fNext will point
1415 // to the outer node of the neuron starting in p, whose
1416 // activation is the largest.
1417 }
1418 // the same procedure is made now for all neurons
1419 // for which p is the outer point
1420 test = fActMinimum;
1421 p->Prev() = 0;
1422 TObjArrayIter outerof(p->OuterOf());
1423 while ( (n = (AliITSneuron*)outerof.Next()) ) {
1424 // if the examined neuron has not the largest activation
1425 // it is skipped and removed from array of all neurons
1426 // and of its inner point (its outer is the cursor p)
1427 if (n->Activation() < test) {
1428 p->OuterOf()->Remove(n);
1429 n->Inner()->InnerOf()->Remove(n);
1430 delete fNeurons->Remove(n);
1431 continue;
1432 }
1433 // otherwise, its activation becomes the maximum reference
1434 p->Prev() = n->Inner();
1435 // at the exit of the while(), the fPrev will point
1436 // to the inner node of the neuron ending in p, whose
1437 // activation is the largest.
1438 }
1439 } // end while (p ...)
1440 } // end for (itheta ...)
1441 } // end for (ilayer ...)
1442
1443 // now the mismatches are solved
1444 Bool_t matchPrev, matchNext;
1445 for (ilayer = 0; ilayer < fNLayers; ilayer++) {
1446 for (itheta = 0; itheta < 180; itheta++) {
1447 // get the array of point in a given layer/theta-slot/sector
1448 lstSector = (TObjArray*)fNodes[ilayer][itheta]->At(sector);
1449 TObjArrayIter nodes(lstSector);
1450 while ( (p = (AliITSnode*)nodes.Next()) ) {
1451 // now p will point to a fPrev and a fNext node.
1452 // Ideally they are placed this way: fPrev --> P --> fNext
1453 // A mismatch happens if the point addressed as fPrev does NOT
1454 // point to p as its fNext. And the same for the point addressed
1455 // as fNext.
1456 // In this case, the fNext and fPrev pointers are set to NULL
1457 // and p is excluded from the reconstruction
1458 matchPrev = matchNext= kFALSE;
1459 if (ilayer > 0 && p->Prev() != NULL)
1460 if (p->Prev()->Next() == p) matchPrev = kTRUE;
1461 if (ilayer < 5 && p->Next() != NULL)
1462 if (p->Next()->Prev() == p) matchNext = kTRUE;
1463 if (ilayer == 0)
1464 matchPrev = kTRUE;
1465 else if (ilayer == 5)
1466 matchNext = kTRUE;
1467 if (!matchNext || !matchPrev) {
1468 p->Prev() = p->Next() = 0;
1469 }
1470 } // end while (p ...)
1471 } // end for (itheta ...)
1472 } // end for (ilayer ...)
1473}
1474
1475//__________________________________________________________________________________
1476Int_t AliITStrackerANN::SaveTracks(Int_t sector)
1477{
1478/********************************************************************************
1479
1480 TRACK SAVING
1481 ------------
1482 Using the fNext and fPrev pointers, the chain is followed
1483 and the track is fitted and saved.
1484 Of course, the track is followed as a chain with a point
1485 for each layer, then the track following starts always
1486 from the clusters in layer 0.
1487
1488***********************************************************************************/
1489
1490 // if not initialized, the tracks TobjArray is initialized
1491 if (!fFoundTracks) fFoundTracks = new TObjArray;
1492
1493 // meaningful counters
1494 Int_t itheta, ilayer, l;
1495 TObjArray *lstSector = 0;
1496 AliITSnode *p = 0, *q = 0, **node = new AliITSnode*[fNLayers];
1497 for (l = 0; l < fNLayers; l++) node[l] = 0;
1498
1499 /*
1500 array = new AliITSnode*[fNLayers + 1];
1501 for (l = 0; l <= fNLayers; l++) array[l] = 0;
1502 array[0] = new AliITSnode();
1503 array[0]->X() = fVertexX;
1504 array[0]->Y() = fVertexY;
1505 array[0]->Z() = fVertexZ;
1506 array[0]->ErrX2() = fVertexErrorX;
1507 array[0]->ErrY2() = fVertexErrorY;
1508 array[0]->ErrZ2() = fVertexErrorZ;
1509 */
1510 Double_t *param = new Double_t[8];
1511
1512 // scan the whole collection of nodes
1513 for (ilayer = 0; ilayer < 1; ilayer++) {
1514 for (itheta = 0; itheta < 180; itheta++) {
1515 // get the array of point in a given layer/theta-slot/sector
1516 lstSector = (TObjArray*)fNodes[ilayer][itheta]->At(sector);
1517 TObjArrayIter nodes(lstSector);
1518 while ( (p = (AliITSnode*)nodes.Next()) ) {
1519 for (q = p; q; q = q->Next()) {
1520 l = q->GetLayer();
1521 node[l] = q;
1522 }
1523 //if (!RiemannFit(fNLayers, node, param)) continue;
1524 // initialization of Kalman Filter Tracking
00a7cc50 1525 AliITSRecPoint *cluster = (AliITSRecPoint*)GetCluster(node[0]->ClusterRef());
cec46807 1526 Int_t mod = cluster->GetDetectorIndex();
1527 Int_t lay, lad, det;
1528 fGeom->GetModuleId(mod, lay, lad, det);
1529 Float_t y0 = cluster->GetY();
1530 Float_t z0 = cluster->GetZ();
cc088660 1531 AliITStrackSA* trac = new AliITStrackSA(lay, lad, det,
cec46807 1532 y0, z0,
1533 param[4], param[7], param[3], 1);
1534 for (l = 0; l < fNLayers; l++) {
00a7cc50 1535 cluster = (AliITSRecPoint*)GetCluster(node[l]->ClusterRef());
cec46807 1536 if (cluster) trac->AddClusterV2(l, (node[l]->ClusterRef() & 0x0fffffff)>>0);
1537 }
1538 AliITStrackV2* ot = new AliITStrackV2(*trac);
6c94f330 1539 ot->ResetCovariance(10.);
cec46807 1540 ot->ResetClusters();
1541 if (RefitAt(49.,ot,trac)) { //fit from layer 1 to layer 6
1542 AliITStrackV2 *otrack2 = new AliITStrackV2(*ot);
6c94f330 1543 otrack2->ResetCovariance(10.);
cec46807 1544 otrack2->ResetClusters();
1545 //fit from layer 6 to layer 1
1546 if (RefitAt(3.7,otrack2,ot)) fFoundTracks->AddLast(otrack2);
1547 }
1548 // end of Kalman Filter fit
1549 }
1550 }
1551 }
1552
1553 return 1;
1554}
1555
1556//__________________________________________________________________________________
1557void AliITStrackerANN::ExportTracks(const char *filename) const
1558{
1559// Exports found tracks into a TTree of AliITStrackV2 objects
1560 TFile *file = new TFile(filename, "RECREATE");
1561 TTree *tree = new TTree("TreeT-ANN", "Tracks found in ITS stand-alone with Neural Tracking");
1562 AliITStrackV2 *track = 0;
1563 tree->Branch("Tracks", &track, "AliITStrackV2");
1564 TObjArrayIter tracks(fFoundTracks);
1565 while ( (track = (AliITStrackV2*)tracks.Next()) ) {
1566 tree->Fill();
1567 }
1568 file->cd();
1569 tree->Write();
1570 file->Close();
1571}
1572
1573
1574//__________________________________________________________________________________
1575void AliITStrackerANN::CleanNetwork()
1576{
1577 // Removes deactivated units from the network
1578
1579 AliITSneuron *unit = 0;
1580 TObjArrayIter neurons(fNeurons);
1581 while ( (unit = (AliITSneuron*)neurons.Next()) ) {
1582 if (unit->Activation() < fActMinimum) {
1583 unit->Inner()->InnerOf()->Remove(unit);
1584 unit->Outer()->OuterOf()->Remove(unit);
1585 delete fNeurons->Remove(unit);
1586 }
1587 }
1588 return;
1589 Bool_t removed;
1590 Int_t nIn, nOut;
1591 AliITSneuron *enemy = 0;
1592 neurons.Reset();
1593 while ( (unit = (AliITSneuron*)neurons.Next()) ) {
1594 nIn = (Int_t)unit->Inner()->InnerOf()->GetSize();
1595 nOut = (Int_t)unit->Outer()->OuterOf()->GetSize();
1596 if (nIn < 2 && nOut < 2) continue;
1597 removed = kFALSE;
1598 if (nIn > 1) {
1599 TObjArrayIter competing(unit->Inner()->InnerOf());
1600 while ( (enemy = (AliITSneuron*)competing.Next()) ) {
1601 if (unit->Activation() > enemy->Activation()) {
1602 enemy->Inner()->InnerOf()->Remove(enemy);
1603 enemy->Outer()->OuterOf()->Remove(enemy);
1604 delete fNeurons->Remove(enemy);
1605 }
1606 else {
1607 unit->Inner()->InnerOf()->Remove(unit);
1608 unit->Outer()->OuterOf()->Remove(unit);
1609 delete fNeurons->Remove(unit);
1610 removed = kTRUE;
1611 break;
1612 }
1613 }
1614 if (removed) continue;
1615 }
1616 if (nOut > 1) {
1617 TObjArrayIter competing(unit->Outer()->OuterOf());
1618 while ( (enemy = (AliITSneuron*)competing.Next()) ) {
1619 if (unit->Activation() > enemy->Activation()) {
1620 enemy->Inner()->InnerOf()->Remove(enemy);
1621 enemy->Outer()->OuterOf()->Remove(enemy);
1622 delete fNeurons->Remove(enemy);
1623 }
1624 else {
1625 unit->Inner()->InnerOf()->Remove(unit);
1626 unit->Outer()->OuterOf()->Remove(unit);
1627 delete fNeurons->Remove(unit);
1628 removed = kTRUE;
1629 break;
1630 }
1631 }
1632 }
1633 }
1634 }
1635
1636//__________________________________________________________________________________
1637Int_t AliITStrackerANN::StoreTracks()
1638{
1639 // Stores the tracks found in a single neural tracking step.
1640 // In order to do this, it sects each neuron which has a point
1641 // in the first layer.
1642 // Then
1643
1644 // if not initialized, the tracks TobjArray is initialized
1645 if (!fFoundTracks) fFoundTracks = new TObjArray;
1646
1647 Int_t i, check, stored = 0;
1648 Double_t testAct = 0;
1649 AliITSneuron *unit = 0, *cursor = 0, *fwd = 0;
1650 AliITSnode *node = 0;
1651 TObjArrayIter iter(fNeurons), *fwdIter;
1652 TObjArray *removedUnits = new TObjArray(0);
1653 removedUnits->SetOwner(kFALSE);
1654 AliITStrackANN annTrack(fNLayers);
1655
1656 for (;;) {
1657 unit = (AliITSneuron*)iter.Next();
1658 if (!unit) break;
1659 if (unit->Inner()->GetLayer() > 0) continue;
1660 annTrack.SetNode(unit->Inner()->GetLayer(), unit->Inner());
1661 annTrack.SetNode(unit->Outer()->GetLayer(), unit->Outer());
1662 node = unit->Outer();
1663 removedUnits->AddLast(unit);
1664 while (node) {
1665 testAct = fActMinimum;
1666 fwdIter = (TObjArrayIter*)node->InnerOf()->MakeIterator();
1667 fwd = 0;
1668 for (;;) {
1669 cursor = (AliITSneuron*)fwdIter->Next();
1670 if (!cursor) break;
1671 if (cursor->Used()) continue;
1672 if (cursor->Activation() >= testAct) {
1673 testAct = cursor->Activation();
1674 fwd = cursor;
1675 }
1676 }
1677 if (!fwd) break;
1678 removedUnits->AddLast(fwd);
1679 node = fwd->Outer();
1680 annTrack.SetNode(node->GetLayer(), node);
1681 }
1682 check = annTrack.CheckOccupation();
1683 if (check >= 6) {
1684 stored++;
1685 // FIT
1686 //if (!RiemannFit(fNLayers, trackitem, param)) continue;
1687 if (!annTrack.RiemannFit()) continue;
1688 // initialization of Kalman Filter Tracking
00a7cc50 1689 AliITSRecPoint *cluster = (AliITSRecPoint*)GetCluster(annTrack[0]->ClusterRef());
cec46807 1690 Int_t mod = cluster->GetDetectorIndex();
1691 Int_t lay, lad, det;
1692 fGeom->GetModuleId(mod, lay, lad, det);
1693 Float_t y0 = cluster->GetY();
1694 Float_t z0 = cluster->GetZ();
cc088660 1695 AliITStrackSA* trac = new AliITStrackSA(lay, lad, det, y0, z0,
cec46807 1696 annTrack.Phi(), annTrack.TanLambda(),
1697 annTrack.Curv(), 1);
1698 for (Int_t l = 0; l < fNLayers; l++) {
1699 if (!annTrack[l]) continue;
00a7cc50 1700 cluster = (AliITSRecPoint*)GetCluster(annTrack[l]->ClusterRef());
cec46807 1701 if (cluster) trac->AddClusterV2(l, (annTrack[l]->ClusterRef() & 0x0fffffff)>>0);
1702 }
1703 AliITStrackV2* ot = new AliITStrackV2(*trac);
6c94f330 1704 ot->ResetCovariance(10.);
cec46807 1705 ot->ResetClusters();
1706 if (RefitAt(49.,ot,trac)) { //fit from layer 1 to layer 6
1707 AliITStrackV2 *otrack2 = new AliITStrackV2(*ot);
6c94f330 1708 otrack2->ResetCovariance(10.);
cec46807 1709 otrack2->ResetClusters();
1710 //fit from layer 6 to layer 1
1711 if (RefitAt(3.7,otrack2,ot)) fFoundTracks->AddLast(otrack2);
1712 }
1713 // end of Kalman Filter fit
1714 // END FIT
1715 for (i = 0; i < fNLayers; i++) {
1716 //node = (AliITSnode*)removedPoints->At(i);
1717 //node->Use();
1718 annTrack[i]->Use();
1719 }
1720 fwdIter = (TObjArrayIter*)removedUnits->MakeIterator();
1721 for (;;) {
1722 cursor = (AliITSneuron*)fwdIter->Next();
1723 if(!cursor) break;
1724 cursor->Used() = 1;
1725 }
1726 }
1727 }
1728
1729 return stored;
1730}
1731
1732Double_t AliITStrackerANN::Weight(AliITSneuron *nAB, AliITSneuron *nBC)
1733{
1734/***********************************************************************************
1735 * Calculation of neural weight.
1736 * The implementation of positive neural weight is set only in the case
1737 * of connected units (e.g.: A->B with B->C).
1738 * Given that B is the **common** point. care should be taken to pass
1739 * as FIRST argument the neuron going "to" B, and
1740 * as SECOND argument the neuron starting "from" B
1741 * anyway, a check is put in order to return 0.0 when arguments are not well given.
1742 ***********************************************************************************/
1743
1744 if (nAB->Outer() != nBC->Inner()) {
1745 if (nBC->Outer() == nAB->Inner()) {
1746 AliITSneuron *temp = nAB;
1747 nAB = nBC;
1748 nBC = temp;
1749 temp = 0;
1750 if (fMsgLevel >= 3) {
1751 Info("Weight", "Switching wrongly ordered arguments.");
1752 }
1753 }
1754 Warning("Weight", "Not connected segments. Returning 0.0");
1755 return 0.0;
1756 }
1757
1758 AliITSnode *pA = nAB->Inner();
1759 AliITSnode *pB = nAB->Outer();
1760 AliITSnode *pC = nBC->Outer();
1761
1762 TVector3 vAB(pB->X() - pA->X(), pB->Y() - pA->Y(), pB->Z() - pA->Z());
1763 TVector3 vBC(pC->X() - pB->X(), pC->Y() - pB->Y(), pC->Z() - pB->Z());
1764
1765 Double_t weight = 1.0 - sin(vAB.Angle(vBC));
1766 return fGain2CostRatio * TMath::Power(weight, fExponent);
1767}
1768
1769
1770
1771/******************************************
1772 ******************************************
1773 *** AliITStrackerANN::AliITSnode class ***
1774 ******************************************
1775 ******************************************/
1776
1777//__________________________________________________________________________________
cb729508 1778AliITStrackerANN::AliITSnode::AliITSnode():
1779fX(0.0),
1780fY(0.0),
1781fZ(0.0),
1782fEX2(0.0),
1783fEY2(0.0),
1784fEZ2(0.0),
1785fUsed(kFALSE),
1786fClusterRef(-1),
1787fMatches(NULL),
1788fInnerOf(NULL),
1789fOuterOf(NULL),
1790fNext(NULL),
1791fPrev(NULL)
cec46807 1792{
1793 // Constructor for the embedded 'AliITSnode' class.
1794 // It initializes all pointer-like objects.
1795
cec46807 1796}
1797
cb729508 1798AliITStrackerANN::AliITSnode::AliITSnode(const AliITSnode &n) : TObject((TObject&)n),
1799fX(n.fX),
1800fY(n.fY),
1801fZ(n.fZ),
1802fEX2(n.fEX2),
1803fEY2(n.fEY2),
1804fEZ2(n.fEZ2),
1805fUsed(n.fUsed),
1806fClusterRef(n.fClusterRef),
1807fMatches(n.fMatches),
1808fInnerOf(n.fInnerOf),
1809fOuterOf(n.fOuterOf),
1810fNext(n.fNext),
1811fPrev(n.fPrev){
1812 //copy constructor
1813}
cec46807 1814//__________________________________________________________________________________
1815AliITStrackerANN::AliITSnode::~AliITSnode()
1816{
1817 // Destructor for the embedded 'AliITSnode' class.
1818 // It should clear the object arrays, but it is possible
1819 // that some objects still are useful after the point deletion
1820 // then the arrays are cleared but their objects are owed by
1821 // another TCollection object, and not deleted.
1822 // For safety reasons, all the pointers are set to zero.
1823
1824 fInnerOf->SetOwner(kFALSE);
1825 fInnerOf->Clear();
1826 delete fInnerOf;
1827 fInnerOf = 0;
1828 fOuterOf->SetOwner(kFALSE);
1829 fOuterOf->Clear();
1830 delete fOuterOf;
1831 fOuterOf = 0;
1832 fMatches->SetOwner(kFALSE);
1833 fMatches->Clear();
1834 delete fMatches;
1835 fMatches = 0;
1836 fNext = 0;
1837 fPrev = 0;
1838}
1839
1840//__________________________________________________________________________________
0db9364f 1841Double_t AliITStrackerANN::AliITSnode::GetPhi() const
cec46807 1842{
1843 // Calculates the 'phi' (azimutal) angle, and returns it
1844 // in the range between 0 and 2Pi radians.
1845
1846 Double_t q;
1847 q = TMath::ATan2(fY,fX);
1848 if (q >= 0.)
1849 return q;
1850 else
1851 return q + TMath::TwoPi();
1852}
1853
1854//__________________________________________________________________________________
0db9364f 1855Double_t AliITStrackerANN::AliITSnode::GetError(Option_t *option)
cec46807 1856{
1857 // Returns the error or the square error of
1858 // values related to the coordinates in different systems.
1859 // The option argument specifies the coordinate error desired:
1860 //
1861 // "R2" --> error in transverse radius
1862 // "R3" --> error in spherical radius
1863 // "PHI" --> error in azimuthal angle
1864 // "THETA" --> error in polar angle
1865 // "SQ" --> get the square of error
1866 //
1867 // In order to get the error on the cartesian coordinates
1868 // reference to the inline ErrX2(), ErrY2() adn ErrZ2() methods.
1869
1870 TString opt(option);
1871 Double_t errorSq = 0.0;
1872 opt.ToUpper();
1873
1874 if (opt.Contains("R2")) {
1875 errorSq = fX*fX*fEX2 + fY*fY*fEY2;
1876 errorSq /= GetR2sq();
1877 }
1878 else if (opt.Contains("R3")) {
1879 errorSq = fX*fX*fEX2 + fY*fY*fEY2 + fZ*fZ*fEZ2;
1880 errorSq /= GetR3sq();
1881 }
1882 else if (opt.Contains("PHI")) {
1883 errorSq = fY*fY*fEX2;
1884 errorSq += fX*fX*fEY2;
1885 errorSq /= GetR2sq() * GetR2sq();
1886 }
1887 else if (opt.Contains("THETA")) {
1888 errorSq = fZ*fZ * (fX*fX*fEX2 + fY*fY*fEY2);
1889 errorSq += GetR2sq() * GetR2sq() * fEZ2;
1890 errorSq /= GetR3sq() * GetR3sq() * GetR2() * GetR2();
1891 }
1892
1893 if (!opt.Contains("SQ"))
1894 return TMath::Sqrt(errorSq);
1895 else
1896 return errorSq;
1897}
1898
1899
1900
1901/********************************************
1902 ********************************************
1903 *** AliITStrackerANN::AliITSneuron class ***
1904 ********************************************
1905 ********************************************/
1906
1907//__________________________________________________________________________________
1908AliITStrackerANN::AliITSneuron::AliITSneuron
cb729508 1909(AliITSnode *inner, AliITSnode *outer, Double_t minAct, Double_t maxAct):
1910fUsed(0),
1911fActivation(0),
1912fInner(inner),
1913fOuter(outer),
1914fGain(0)
cec46807 1915{
1916 // Default neuron constructor
1917 fActivation = gRandom->Rndm() * (maxAct-minAct) + minAct;
1918 fGain = new TObjArray;
1919}
cb729508 1920
1921AliITStrackerANN::AliITSneuron::AliITSneuron(const AliITSneuron &n) : TObject((TObject&)n),
1922fUsed(n.fUsed),
1923fActivation(n.fActivation),
1924fInner(n.fInner),
1925fOuter(n.fOuter),
1926fGain(n.fGain){
1927 //copy constructor
1928}
cec46807 1929//__________________________________________________________________________________
0db9364f 1930Double_t AliITStrackerANN::AliITSneuron::Activate(Double_t temperature)
cec46807 1931{
1932 // This computes the new activation of a neuron, and returns
1933 // its activation variation as a consequence of the updating.
1934 //
1935 // Arguments:
1936 // - the 'temperature' parameter for the neural activation logistic function
1937 //
1938 // Operations:
1939 // - collects the total gain, by summing the products
1940 // of the activation of each sequenced unit by the relative weight.
1941 // - collects the total cost, by summing the activations of
1942 // all competing units
1943 // - passes the sum of gain - cost to the activation function and
1944 // calculates the new activation
1945 //
1946 // Return value:
1947 // - the difference between the old activation and the new one
1948 // (absolute value)
1949
1950 // local variables
1951 Double_t sumGain = 0.0; // total contribution from chained neurons
1952 Double_t sumCost = 0.0; // total contribution from crossing neurons
1953 Double_t input; // total input
1954 Double_t actOld, actNew; // old and new values for the activation
1955 AliITSneuron *linked = 0; // cursor for scanning the neuron arrays (for link check)
1956 AliITSlink *link; // cursor for scanning the synapses arrays (for link check)
1957 TObjArrayIter *iterator = 0; // pointer to the iterator along the neuron arrays
1958
1959 // sum contributions from the correlated units
1960 iterator = (TObjArrayIter*)fGain->MakeIterator();
1961 for(;;) {
1962 link = (AliITSlink*)iterator->Next();
1963 if (!link) break;
1964 sumGain += link->Contribution();
1965 }
1966 delete iterator;
1967
1968 // sum contributions from the competing units:
1969 // the ones which have the same starting point...
1970 iterator = (TObjArrayIter*)fInner->InnerOf()->MakeIterator();
1971 for (;;) {
1972 linked = (AliITSneuron*)iterator->Next();
1973 if (!linked) break;
1974 if (linked == this) continue;
1975 sumCost += linked->fActivation;
1976 }
1977 delete iterator;
1978 // ...and the ones which have the same ending point
1979 iterator = (TObjArrayIter*)fOuter->OuterOf()->MakeIterator();
1980 for (;;) {
1981 linked = (AliITSneuron*)iterator->Next();
1982 if (!linked) break;
1983 if (linked == this) continue;
1984 sumCost += linked->fActivation;
1985 }
1986
1987 // calculate the total input as the difference between gain and cost
1988 input = (sumGain - sumCost) / temperature;
1989 actOld = fActivation;
1990 // calculate the final output
1991#ifdef NEURAL_LINEAR
1992 if (input <= -2.0 * temperature)
1993 actNew = 0.0;
1994 else if (input >= 2.0 * temperature)
1995 actNew = 1.0;
1996 else
1997 actNew = input / (4.0 * temperature) + 0.5;
1998#else
1999 actNew = 1.0 / (1.0 + TMath::Exp(-input));
2000#endif
2001 fActivation = actNew;
2002
2003 // return the activation variation
2004 return TMath::Abs(actNew - actOld);
2005}
2006
2007
2008
2009/******************************************
2010 ******************************************
2011 *** AliITStrackerANN::AliITSlink class ***
2012 ******************************************
2013 ******************************************/
2014
2015 // No methods defined non-inline
2016
2017
2018
2019 /**********************************************
2020 **********************************************
2021 *** AliITStrackerANN::AliITStrackANN class ***
2022 **********************************************
2023 **********************************************/
2024
2025//__________________________________________________________________________________
cb729508 2026AliITStrackerANN::AliITStrackANN::AliITStrackANN(Int_t dim) :
2027fNPoints(dim),
2028fXCenter(0.0),
2029fYCenter(0.0),
2030fRadius(0.0),
2031fCurv(0.0),
2032fDTrans(0.0),
2033fDLong(0.0),
2034fTanLambda(0.0),
2035fPhi(0.0),
2036fNode(0)
cec46807 2037{
2038 // Default constructor for the AliITStrackANN class
2039
cec46807 2040 if (! dim) {
2041 fNode = 0;
2042 }
2043 else{
2044 Int_t i = 0;
2045 fNode = new AliITSnode*[dim];
2046 for (i = 0; i < dim; i++) fNode[i] = 0;
2047 }
2048}
2049
cb729508 2050AliITStrackerANN::AliITStrackANN::AliITStrackANN(const AliITStrackANN &n) : TObject((TObject&)n),
2051fNPoints(n.fNPoints),
2052fXCenter(n.fXCenter),
2053fYCenter(n.fYCenter),
2054fRadius(n.fRadius),
2055fCurv(n.fCurv),
2056fDTrans(n.fDTrans),
2057fDLong(n.fDLong),
2058fTanLambda(n.fTanLambda),
2059fPhi(n.fPhi),
2060fNode(n.fNode)
2061{
2062 //copy constructor
2063}
cec46807 2064//__________________________________________________________________________________
2065Int_t AliITStrackerANN::AliITStrackANN::CheckOccupation() const
2066{
2067 // Returns the number of pointers fNode which are not NULL
2068
2069 Int_t i; // cursor
2070 Int_t count = 0; // counter for how many points are stored in the track
2071
2072 for (i = 0; i < fNPoints; i++) {
2073 if (fNode[i] != NULL) count++;
2074 }
2075
2076 return count;
2077}
2078
2079//__________________________________________________________________________________
2080Bool_t AliITStrackerANN::AliITStrackANN::RiemannFit()
2081{
2082 // Performs the Riemann Sphere fit for the given points to a circle
2083 // and then uses the fit parameters to fit a helix in space.
2084 //
2085 // Return values:
2086 // - kTRUE if all operations have been performed
2087 // - kFALSE if the numbers risk to lead to an arithmetic violation
2088
2089 Int_t i, j, count, dim = fNPoints;
2090
2091 // First check for all points
2092 count = CheckOccupation();
2093 if (count != fNPoints) {
2094 Error ("AliITStrackANN::RiemannFit", "CheckOccupations returns %d, fNPoints = %d ==> MISMATCH", count, fNPoints);
2095 return kFALSE;
2096 }
2097
2098 // matrix of ones
2099 TMatrixD m1(dim,1);
2100 for (i = 0; i < dim; i++) m1(i,0) = 1.0;
2101
2102 // matrix of Rieman projection coordinates
2103 TMatrixD coords(dim,3);
2104 for (i = 0; i < dim; i++) {
2105 coords(i,0) = fNode[i]->X();
2106 coords(i,1) = fNode[i]->Y();
2107 coords(i,2) = fNode[i]->GetR2sq();
2108 }
2109
2110 // matrix of weights
2111 Double_t xterm, yterm, ex, ey;
2112 TMatrixD weights(dim,dim);
2113 for (i = 0; i < dim; i++) {
2114 xterm = fNode[i]->X() * fNode[i]->GetPhi() - fNode[i]->Y() / fNode[i]->GetR2();
2115 ex = fNode[i]->ErrX2();
2116 yterm = fNode[i]->Y() * fNode[i]->GetPhi() + fNode[i]->X() / fNode[i]->GetR2();
2117 ey = fNode[i]->ErrY2();
2118 weights(i,i) = fNode[i]->GetR2sq() / (xterm * xterm * ex + yterm * yterm * ey );
2119 }
2120
2121 // weighted sample mean
2122 Double_t meanX = 0.0, meanY = 0.0, meanW = 0.0, sw = 0.0;
2123 for (i = 0; i < dim; i++) {
2124 meanX += weights(i,i) * coords(i,0);
2125 meanY += weights(i,i) * coords(i,1);
2126 meanW += weights(i,i) * coords(i,2);
2127 sw += weights(i,i);
2128 }
2129 meanX /= sw;
2130 meanY /= sw;
2131 meanW /= sw;
2132
2133 // sample covariance matrix
2134 for (i = 0; i < dim; i++) {
2135 coords(i,0) -= meanX;
2136 coords(i,1) -= meanY;
2137 coords(i,2) -= meanW;
2138 }
2139 TMatrixD coordsT(TMatrixD::kTransposed, coords);
2140 TMatrixD weights4coords(weights, TMatrixD::kMult, coords);
2141 TMatrixD sampleCov(coordsT, TMatrixD::kMult, weights4coords);
2142 for (i = 0; i < 3; i++) {
2143 for (j = i + 1; j < 3; j++) {
2144 sampleCov(i,j) = sampleCov(j,i) = (sampleCov(i,j) + sampleCov(j,i)) * 0.5;
2145 }
2146 }
2147
2148 // Eigenvalue problem solving for V matrix
2149 Int_t ileast = 0;
2150 TVectorD eval(3), n(3);
292a2409 2151#if ROOT_VERSION_CODE < ROOT_VERSION(4,0,2)
cec46807 2152 TMatrixD evec = sampleCov.EigenVectors(eval);
292a2409 2153#else
2154 TMatrixDEigen ei(sampleCov);
2155 TMatrixD evec = ei.GetEigenVectors();
2156 eval = ei.GetEigenValuesRe();
2157#endif
cec46807 2158 if (eval(1) < eval(ileast)) ileast = 1;
2159 if (eval(2) < eval(ileast)) ileast = 2;
2160 n(0) = evec(0, ileast);
2161 n(1) = evec(1, ileast);
2162 n(2) = evec(2, ileast);
2163
2164 // c - known term in the plane intersection with Riemann axes
2165 Double_t c = -(meanX * n(0) + meanY * n(1) + meanW * n(2));
2166
2167 // center and radius of fitted circle
2168 Double_t xc, yc, radius, curv;
2169 xc = -n(0) / (2. * n(2));
2170 yc = -n(1) / (2. * n(2));
2171 radius = (1. - n(2)*n(2) - 4.*c*n(2)) / (4. * n(2) * n(2));
2172
2173 if (radius <= 0.E0) {
2174 Error("RiemannFit", "Radius = %f less than zero!!!", radius);
2175 return kFALSE;
2176 }
2177 radius = TMath::Sqrt(radius);
2178 curv = 1.0 / radius;
2179
2180 // evaluating signs for curvature and others
2181 Double_t phi1 = 0.0, phi2, temp1, temp2, phi0, sumdphi = 0.0;
2182 AliITSnode *p = fNode[0];
2183 phi1 = p->GetPhi();
2184 for (i = 1; i < dim; i++) {
2185 p = (AliITSnode*)fNode[i];
2186 if (!p) break;
2187 phi2 = p->GetPhi();
2188 temp1 = phi1;
2189 temp2 = phi2;
2190 if (temp1 > fgkPi && temp2 < fgkPi)
2191 temp2 += fgkTwoPi;
2192 else if (temp1 < fgkPi && temp2 > fgkPi)
2193 temp1 += fgkTwoPi;
2194 sumdphi += temp2 - temp1;
2195 phi1 = phi2;
2196 }
2197 if (sumdphi < 0.E0) curv = -curv;
2198 Double_t diff, angle = TMath::ATan2(yc, xc);
2199 if (curv < 0.E0)
2200 phi0 = angle + 0.5 * TMath::Pi();
2201 else
2202 phi0 = angle - 0.5 * TMath::Pi();
2203 diff = angle - phi0;
2204
2205 Double_t dt, temp = TMath::Sqrt(xc*xc + yc*yc) - radius;
2206 if (curv >= 0.E0)
2207 dt = temp;
2208 else
2209 dt = -temp;
2210 //cout << "Dt = " << dt << endl;
2211
2212 Double_t halfC = 0.5 * curv, test;
2213 Double_t *s = new Double_t[dim], *zz = new Double_t[dim], *ws = new Double_t[dim];
2214 for (j = 0; j < 6; j++) {
2215 p = fNode[j];
2216 if (!p) break;
2217 //----
2218 s[j] = (p->GetR2sq() - dt * dt) / (1. + curv * dt);
2219 if (s[j] < 0.) {
0db9364f 2220 if (TMath::Abs(s[j]) < 1.E-6) s[j] = 0.;
cec46807 2221 else {
2222 Error("RiemannFit", "Square root argument error: %17.15g < 0", s[j]);
2223 return kFALSE;
2224 }
2225 }
2226 s[j] = TMath::Sqrt(s[j]);
2227 //cout << "Curv = " << halfC << " --- s[" << j << "] = " << s[j] << endl;
2228 s[j] *= halfC;
2229 test = TMath::Abs(s[j]);
2230 if (test > 1.) {
2231 if (test <= 1.1)
2232 s[j] = ((s[j] > 0.) ? 0.99999999999 : -0.9999999999);
2233 else {
2234 Error("RiemannFit", "Value too large: %17.15g", s[j]);
2235 return kFALSE;
2236 }
2237 }
2238 //----
2239 zz[j] = p->Z();
2240 s[j] = TMath::ASin(s[j]) / halfC;
2241 ws[j] = 1.0 / (p->ErrZ2());
2242 }
2243
2244 // second tep final fit
2245 Double_t s2Sum = 0.0, zSum = 0.0, szSum = 0.0, sSum = 0.0, sumw = 0.0;
2246 for (i = 0; i < dim; i++) {
2247 s2Sum += ws[i] * s[i] * s[i];
2248 zSum += ws[i] * zz[i];
2249 sSum += ws[i] * s[i];
2250 szSum += ws[i] * s[i] * zz[i];
2251 sumw += ws[i];
2252 }
2253 s2Sum /= sumw;
2254 zSum /= sumw;
2255 sSum /= sumw;
2256 szSum /= sumw;
2257 temp = s2Sum - sSum*sSum;
2258
2259 Double_t dz, tanL;
2260 dz = (s2Sum*zSum - sSum*szSum) / temp;
2261 tanL = (szSum - sSum*zSum) / temp;
2262
2263 fXCenter = xc;
2264 fYCenter = yc;
2265 fRadius = radius;
2266 fCurv = curv;
2267 fPhi = phi0;
2268 fDTrans = dt;
2269 fDLong = dz;
2270 fTanLambda = tanL;
2271
2272 delete [] s;
2273 delete [] zz;
2274 delete [] ws;
2275
2276 return kTRUE;
2277}