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