]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSgeom.cxx
Use global gRandom generator (M.Ivanov)
[u/mrichter/AliRoot.git] / ITS / AliITSgeom.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 Revision 1.16  2001/02/08 23:57:00  nilsen
19 Fixed up some informational printouts.
20
21 Revision 1.15  2001/02/07 20:23:21  nilsen
22 Fixed bug with HP and no unget in iostream.h. Now using putback instead.
23 Other changes and fixes also included.
24
25 Revision 1.14  2001/02/03 00:00:29  nilsen
26 New version of AliITSgeom and related files. Now uses automatic streamers,
27 set up for new formatted .det file which includes detector information.
28 Additional smaller modifications are still to come.
29
30 Revision 1.11  2000/10/02 16:32:35  barbera
31 Forward declaration added
32
33 Revision 1.4.4.15  2000/10/02 15:52:05  barbera
34 Forward declaration added
35
36 Revision 1.10  2000/09/05 14:25:50  nilsen
37 Made fixes for HP compiler. All function parameter default values placed
38 in .h file. Fixed the usual problem with HP comilers and the "for(Int_t i..."
39 business. Replaced casting (Double_t [3][3]) to (Double_t (*)[3]) for HP.
40 Lastly removed all "const" before function parameters which were 2 dim. arrays,
41 because on HP root generates some strange code (?). Thanks Peter for the
42 changes.
43
44 Revision 1.9  2000/08/29 20:19:03  nilsen
45 Removed dependancy on structure AliITSeomS and replaced it with class
46 AliITSgeomMatrix. Added many new functions with many new arguments. Most
47 in the form of in line functions for speed.
48
49 Revision 1.4.4.6  2000/06/04 16:33:32  Nilsen
50 A restructured AliITSgeom class. Now used AliITSgeomMatrix.
51
52 Revision 1.4.4.5  2000/03/04 23:42:39  Nilsen
53 Updated the comments/documentations and improved the maintainability of the
54 code.
55
56 Revision 1.4.4.4  2000/03/02 21:27:07  Nilsen
57 Added two functions, SetByAngles and SetTrans.
58
59 Revision 1.4.4.3  2000/01/23 03:09:10  Nilsen
60 // fixed compiler warnings for new function LtLErrorMatrix(...)
61
62 Revision 1.4.4.2  2000/01/19 23:18:20  Nilsen
63 Added transformations of Error matrix to AliITSgeom and fixed some typos
64 in AliITS.h and AliITShitIndex.h
65
66 Revision 1.4.4.1  2000/01/12 19:03:32  Nilsen
67 This is the version of the files after the merging done in December 1999.
68 See the ReadMe110100.txt file for details
69
70 Revision 1.4  1999/10/15 07:03:20  fca
71 Fixed bug in GetModuleId(Int_t index,Int_t &lay,Int_t &lad, Int_t &det) and
72 a typo in the creator. aliroot need to be rerun to get a fixed geometry.
73
74 Revision 1.3  1999/10/04 15:20:12  fca
75 Correct syntax accepted by g++ but not standard for static members, remove minor warnings
76
77 Revision 1.2  1999/09/29 09:24:20  fca
78 Introduction of the Copyright and cvs Log
79
80 */
81
82 ///////////////////////////////////////////////////////////////////////
83 // ITS geometry manipulation routines.                               //
84 // Created April 15 1999.                                            //
85 // version: 0.0.0                                                    //
86 // By: Bjorn S. Nilsen                                               //
87 // version: 0.0.1                                                    //
88 // Updated May 27 1999.                                              //
89 // Added Cylindrical random and global based changes.               //
90 // Added  function PrintComparison.                                  //
91 ///////////////////////////////////////////////////////////////////////
92
93
94 ////////////////////////////////////////////////////////////////////////
95 //     The local coordinate system by, default, is show in the following
96 // figures. Also shown are the ladder numbering scheme.
97 //Begin_Html
98 /*
99 <img src="picts/ITS/AliITSgeomMatrix_L1.gif">
100 </pre>
101 <br clear=left>
102 <font size=+2 color=blue>
103 <p>This shows the relative geometry differences between the ALICE Global
104 coordinate system and the local detector coordinate system.
105 </font>
106 <pre>
107
108 <pre>
109 <img src="picts/ITS/its1+2_convention_front_5.gif">
110 </pre>
111 <br clear=left>
112 <font size=+2 color=blue>
113 <p>This shows the front view of the SPDs and the orientation of the local
114 pixel coordinate system. Note that the inner pixel layer has its y coordinate
115 in the opposite direction from all of the other layers.
116 </font>
117 <pre>
118
119 <pre>
120 <img src="picts/ITS/its3+4_convention_front_5.gif">
121 </pre>
122 <br clear=left>
123 <font size=+2 color=blue>
124 <p>This shows the front view of the SDDs and the orientation of the local
125 pixel coordinate system.
126 </font>
127 <pre>
128
129 <pre>
130 <img src="picts/ITS/its5+6_convention_front_5.gif">
131 </pre>
132 <br clear=left>
133 <font size=+2 color=blue>
134 <p>This shows the front view of the SSDs and the orientation of the local
135 pixel coordinate system.
136 </font>
137 <pre>
138 */
139 //End_Html
140 //
141 ////////////////////////////////////////////////////////////////////////
142
143 ////////////////////////////////////////////////////////////////////////
144 //
145 // version: 0
146 // Written by Bjorn S. Nilsen
147 //
148 // Data Members:
149 //
150 // Int_t fNlayers
151 //     The number of ITS layers for this geometry. By default this
152 //  is 6, but can be modified by the creator function if there are
153 // more layers defined.
154 //
155 // Int_t *fNlad
156 //     A pointer to an array fNlayers long containing the number of 
157 // ladders for each layer. This array is typically created and filled 
158 // by the AliITSgeom creator function.
159 //
160 // Int_t *fNdet
161 //     A pointer to an array fNlayers long containing the number of
162 // active detector volumes for each ladder. This array is typically
163 // created and filled by the AliITSgeom creator function.
164 //
165 // AliITSgeomMatrix *fGm
166 //     A pointer to an array of AliITSgeomMatrix classes. One element 
167 // per module (detector) in the ITS. AliITSgeomMatrix basicly contains
168 // all of the necessary information about the detector and it's coordinate
169 // transformations.
170 //
171 // TObjArray *fShape
172 //     A pointer to an array of TObjects containing the detailed shape
173 // information for each type of detector used in the ITS. For example
174 // I have created AliITSgeomSPD, AliITSgeomSDD, and AliITSgeomSSD as
175 // example structures, derived from TObjects, to hold the detector
176 // information. I would recommend that one element in each of these
177 // structures, that which describes the shape of the active volume,
178 // be one of the ROOT classes derived from TShape. In this way it would
179 // be easy to have the display program display the correct active
180 // ITS volumes. See the example classes AliITSgeomSPD, AliITSgeomSDD,
181 // and AliITSgeomSSD for a more detailed example.
182 ////////////////////////////////////////////////////////////////////////
183 #include <iostream.h>
184 #include <fstream.h>
185 #include <iomanip.h>
186 #include <stdlib.h>
187 #include <stdio.h>
188 #include <string.h>
189 #include <ctype.h>
190
191 #include <TSystem.h>
192 #include <TVector.h>
193 #include <TObject.h>
194 #include <TRandom.h>
195
196 #include "AliITSgeom.h"
197 //#include "AliITSgeomMatrix.h" // include in AliITSgeom.h
198 #include "AliITSgeomSPD.h"
199 #include "AliITSgeomSDD.h"
200 #include "AliITSgeomSSD.h"
201
202 ClassImp(AliITSgeom)
203
204 //_____________________________________________________________________
205 AliITSgeom::AliITSgeom(){
206 ////////////////////////////////////////////////////////////////////////
207 //     The default constructor for the AliITSgeom class. It, by default,
208 // sets fNlayers to zero and zeros all pointers.
209 ////////////////////////////////////////////////////////////////////////
210     // Default constructor.
211     // Do not allocate anything zero everything
212     fTrans   = 0; // standard GEANT global/local coordinate system.
213     fNlayers = 0;
214     fNlad    = 0;
215     fNdet    = 0;
216     fGm      = 0;
217     fShape   = 0;
218     strcpy(fVersion,"test");
219     return;
220 }
221 //_____________________________________________________________________
222 AliITSgeom::AliITSgeom(Int_t itype,Int_t nlayers,Int_t *nlads,Int_t *ndets,
223                        Int_t mods){
224 ////////////////////////////////////////////////////////////////////////
225 //     A simple constructor to set basic geometry class variables
226 // Input:
227 //      itype  the type of transofmation kept.
228 //             0 => Standard Geant
229 //         bit 1 => ITS tracking
230 //         bit 2 => A change in the coordiante system has been made.
231 //         others are still to be defined as needed.
232 //      nlayers The number of ITS layers also set the size of the arrays
233 //      *nlads  an array of the number of ladders for each layer
234 //      *ndets  an array of the number of detectors per ladder for each layer.
235 ////////////////////////////////////////////////////////////////////////
236     Int_t i;
237
238     fTrans    = itype;
239     fNlayers  = nlayers;
240     fNlad     = new Int_t[nlayers];
241     fNdet     = new Int_t[nlayers];
242     for(i=0;i<nlayers;i++){fNlad[i] = nlads[i];fNdet[i] = ndets[i];}
243     fNmodules = mods;
244     fGm       = new TObjArray(mods,0);
245     fShape    = new TObjArray(5); // default value
246     for(i=0;i<5;i++) fShape->AddAt(0,i);
247     strcpy(fVersion,"test");
248     return;
249 }
250 //______________________________________________________________________
251 void AliITSgeom::CreatMatrix(Int_t mod,Int_t lay,Int_t lad,Int_t det,
252                              AliITSDetector idet,Double_t tran[3],
253                              Double_t rot[10]){
254     Int_t id[3];
255     Double_t r[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
256
257     if(fGm->At(mod)!=0) delete fGm->At(mod);
258     id[0] = lay; id[1] = lad; id[2] = det;
259     if(rot[9]!=0.0) { // null rotation
260         r[0][0] = rot[0]; r[0][1] = rot[1]; r[0][2] = rot[2];
261         r[1][0] = rot[3]; r[1][1] = rot[4]; r[1][2] = rot[5];
262         r[2][0] = rot[6]; r[2][1] = rot[7]; r[2][2] = rot[8];
263     } // end if
264     fGm->AddAt(new AliITSgeomMatrix(idet,id,r,tran),mod);
265 }
266 //_____________________________________________________________________
267 AliITSgeom::~AliITSgeom(){
268 ////////////////////////////////////////////////////////////////////////
269 //     The destructor for the AliITSgeom class. If the arrays fNlad,
270 // fNdet, or fGm have had memory allocated to them, there pointer values
271 // are non zero, then this memory space is freed and they are set
272 // to zero. In addition, fNlayers is set to zero. The destruction of
273 // TObjArray fShape is, by default, handled by the TObjArray destructor.
274 ////////////////////////////////////////////////////////////////////////
275   // Default destructor.
276   // if arrays exist delete them. Then set everything to zero.
277    if(fGm!=0){
278       for(Int_t i=0;i<fNlayers;i++) delete fGm->At(i);
279       delete fGm;
280    } // end if fGm!=0
281    if(fNlad!=0) delete[] fNlad;
282    if(fNdet!=0) delete[] fNdet;
283    fNlayers = 0;
284    fNlad    = 0;
285    fNdet    = 0;
286    fGm      = 0;
287    return;
288 }
289 //______________________________________________________________________
290 void AliITSgeom::ReadNewFile(const char *filename){
291     Int_t ncmd=9;
292     const char *cmda[]={"Version"        ,"fTrans"  ,"fNmodules",
293                         "fNlayers"       ,"fNladers","fNdetectors",
294                         "fNDetectorTypes","fShape"  ,"Matrix"};
295     Int_t i,j,lNdetTypes,ldet;
296     char cmd[20],c;
297     AliITSgeomSPD *spd;
298     AliITSgeomSDD *sdd;
299     AliITSgeomSSD *ssd;
300     AliITSgeomMatrix *m;
301     ifstream *fp;
302     char *filtmp;
303
304     filtmp = gSystem->ExpandPathName(filename);
305     cout << "AliITSgeom, Reading New .det file " << filtmp << endl;
306     fp = new ifstream(filtmp,ios::in);  // open file to write
307     while(fp->get(c)!=NULL){ // for ever loop
308         if(c==' ') continue; // remove blanks
309         if(c=='\n') continue;
310         if(c=='#' || c=='!'){for(;fp->get(c)!=NULL,c!='\n';); continue;}
311         if(c=='/'){
312             fp->get(c);{
313                 if(c=='/'){for(;fp->get(c)!=NULL,c!='\n';);continue;}
314                 if(c=='*'){
315                 NotYet:
316                     for(;fp->get(c)!=NULL,c!='*';);
317                     fp->get(c);{
318                         if(c=='/') continue;
319                         goto NotYet;
320                     } //
321                 } // end if c=='*'
322             } // end if second /
323         } // end if first /
324         fp->putback(c);
325 //      fp->unget();
326         *fp >> cmd;
327         for(i=0;i<ncmd;i++) if(strcmp(cmd,cmda[i])==0) break;
328         switch (i){
329         case 0:   // Version
330             *fp >> fVersion;
331             break;
332         case 1:  // fTrans
333             *fp >> fTrans;
334             break;
335         case 2:  // fNModules
336             *fp >> fNmodules;
337             if(fGm!=0){
338                 for(j=0;j<fGm->GetEntriesFast();j++) delete fGm->At(j);
339                 delete fGm;
340             } // end if
341             fGm = new TObjArray(fNmodules,0);
342             break;
343         case 3:  // fNlayers
344             *fp >> fNlayers;
345             if(fNlad!=0) delete fNlad;
346             if(fNdet!=0) delete fNdet;
347             fNlad = new Int_t[fNlayers];
348             fNdet = new Int_t[fNlayers];
349             break;
350         case 4:  // fNladers
351             for(j=0;j<fNlayers;j++) *fp >> fNlad[j];
352             break;
353         case 5:  // fNdetectors
354             for(j=0;j<fNlayers;j++) *fp >> fNdet[j];
355             break;
356         case 6:  // fNDetectorTypes
357             *fp >> lNdetTypes;
358             if(fShape!=0){
359                 for(j=0;j<fShape->GetEntriesFast();j++) delete fShape->At(j);
360                 delete fShape;
361             } // end if
362             fShape = new TObjArray(lNdetTypes,0);
363             break;
364         case 7:  // fShape
365             *fp >> ldet;
366             if(fShape==0) fShape = new TObjArray(5,0);
367             switch (ldet){
368             case kSPD :
369                 ReSetShape(ldet,(TObject*) new AliITSgeomSPD());
370                 spd = (AliITSgeomSPD*) (fShape->At(ldet));
371                 *fp >> *spd;
372                 spd = 0;
373                 break;
374             case kSDD :
375                 ReSetShape(ldet,(TObject*) new AliITSgeomSDD());
376                 sdd = (AliITSgeomSDD*) (fShape->At(ldet));
377                 *fp >> *sdd;
378                 sdd = 0;
379                 break;
380             case kSSD : case kSSDp :
381                 ReSetShape(ldet,(TObject*) new AliITSgeomSSD());
382                 ssd = (AliITSgeomSSD*) (fShape->At(ldet));
383                 *fp >> *ssd;
384                 ssd = 0;
385                 break;
386             default:
387                 Error("ReadNewFile","Unknown fShape type number=%d c=%c",ldet,c);
388                 for(;fp->get(c)==NULL,c!='\n';); // skip to end of line.
389                 break;
390             } // end switch
391             break;
392         case 8:  // Matrix
393             *fp >> ldet;
394             if(fGm==0) fGm = new TObjArray(2270,0);
395             if(fGm->At(ldet)!=0) delete (fGm->At(ldet));
396             fGm->AddAt((TObject*)new AliITSgeomMatrix(),ldet);
397             m = (AliITSgeomMatrix*) fGm->At(ldet);
398             *fp >> *m;
399             m = 0;
400             break;
401         default:
402             Error("ReadNewFile","Data line i=%d c=%c",i,c);
403             for(;fp->get(c)==NULL,c!='\n';); // skip this line
404             break;
405         } // end switch i
406     } // end while
407     delete fp;
408
409     return;
410 }
411 //______________________________________________________________________
412 void AliITSgeom::WriteNewFile(const char *filename){
413 // Writes AliITSgeom, AliITSgeomMatrix, and the defined AliITSgeomS*D classes
414 // to a file in a format that is more readable and commentable.
415     ofstream *fp;
416     Int_t i;
417     char *filtmp;
418
419     filtmp = gSystem->ExpandPathName(filename);
420     cout << "AliITSgeom, Writing New .det file " << filtmp << endl;
421     fp = new ofstream(filtmp,ios::out);  // open file to write
422     *fp << "//Comment lines begin with two //, one #, or one !" << endl;
423     *fp << "#Blank lines are skipped including /* and */ sections." << endl;
424     *fp << "!and, in principle the order of the lines is not important" <<endl;
425     *fp << "/* In AliITSgeom.h are defined an enumerated type called" << endl;
426     *fp << " AliITSDetectors These are kSPD=" << (Int_t) kSPD ;
427     *fp << ", kSDD=" << (Int_t) kSDD << ", kSSD=" << (Int_t) kSSD;
428     *fp << ", kSSDp=" << (Int_t) kSSDp << ", and kSDDp=" << (Int_t) kSDDp;
429     *fp << "*/" << endl;
430     *fp << "Version " << fVersion << endl;//This should be consistant with the
431                                            // geometry version.
432     *fp << "fTrans " << fTrans << endl;
433     *fp << "fNmodules " << fNmodules << endl;
434     *fp << "fNlayers " << fNlayers << endl;
435     *fp << "fNladers ";
436     for(i=0;i<fNlayers;i++) *fp << fNlad[i] << " ";
437     *fp << endl;
438     *fp << "fNdetectors ";
439     for(i=0;i<fNlayers;i++) *fp << fNdet[i] << " ";
440     *fp << endl;
441     *fp << "fNDetectorTypes " << fShape->GetEntriesFast() << endl;
442     for(i=0;i<fShape->GetEntriesFast();i++){
443         if(!IsShapeDefined(i)) continue; // only print out used shapes.
444         switch (i){
445         case kSPD :
446             *fp << "fShape " << (Int_t) kSPD << " ";
447             *fp << *((AliITSgeomSPD*)(fShape->At(i)));
448             break;
449         case kSDD :
450             *fp << "fShape " << (Int_t) kSDD << " ";
451             *fp << *((AliITSgeomSDD*)(fShape->At(i)));
452             break;
453         case kSSD : case kSSDp :
454             *fp << "fShape " << i << " ";
455             *fp << *((AliITSgeomSSD*)(fShape->At(i)));
456             break;
457         default:
458             Error("AliITSgeom::WriteNewFile","Unknown Shape value");
459         } // end switch (i)
460     } // end for i
461     for(i=0;i<fNmodules;i++){
462         *fp << "Matrix " << i << " ";
463         *fp << *GetGeomMatrix(i);
464     } // end for i
465     *fp << "//End of File" << endl;;
466
467     delete fp;
468     return;
469 }
470 //_____________________________________________________________________
471 AliITSgeom::AliITSgeom(const char *filename){
472 ////////////////////////////////////////////////////////////////////////
473 //     The constructor for the AliITSgeom class. All of the data to fill
474 // this structure is read in from the file given my the input filename.
475 ////////////////////////////////////////////////////////////////////////
476    FILE     *pf=0;
477    Int_t    i,lm=0,id[3];
478    Int_t    l,a,d;
479    Float_t  x,y,z,o,p,q,r,s,t;
480    Double_t rot6[6],tran[3];
481    char     buf[200],*buff=0; // input character buffer;
482    char *filtmp;
483
484    filtmp = gSystem->ExpandPathName(filename);
485    cout << "AliITSgeom reading old .det file " << filtmp << endl;
486    fShape = 0;
487    strcpy(fVersion,"DefauleV5");
488    pf = fopen(filtmp,"r");
489
490    fNlayers = 6; // set default number of ladders
491 TryAgain:
492    fNlad    = new Int_t[fNlayers];
493    fNdet    = new Int_t[fNlayers];
494    fNmodules = 0;
495    // find the number of ladders and detectors in this geometry.
496    for(i=0;i<fNlayers;i++){fNlad[i]=fNdet[i]=0;} // zero out arrays
497    while(fgets(buf,200,pf)!=NULL){ // for ever loop
498       for(i=0;i<200;i++)if(buf[i]!=' '){ // remove blank spaces.
499            buff = &(buf[i]);
500            break;
501       } // end for i
502       // remove blank lines and comments.
503       if(buff[0]=='\n'||buff[0]=='#'||buff[0]=='!'||
504          (buff[0]=='/'&&buff[1]=='/')) continue;
505       if(isalpha(buff[0])) { // must be the new file formated file.
506             fclose(pf);
507             delete[] fNlad;delete[] fNdet;
508             ReadNewFile(filename);
509             return;
510       } // end if isalpha(buff[0])
511       sscanf(buff,"%d %d %d %f %f %f %f %f %f %f %f %f",
512                   &l,&a,&d,&x,&y,&z,&o,&p,&q,&r,&s,&t);
513       if(l>lm) lm = l;
514       if(l<1 || l>fNlayers) {
515          printf("error in file %s layer=%d min. is 1 max is %d\n",
516                  filename,l,fNlayers);
517          continue;
518       }// end if l
519       fNmodules++;
520       if(l<=fNlayers&&fNlad[l-1]<a) fNlad[l-1] = a;
521       if(l<=fNlayers&&fNdet[l-1]<d) fNdet[l-1] = d;
522    } // end while ever loop
523    if(lm>fNlayers){
524         delete[] fNlad;
525         delete[] fNdet;
526         fNlayers = lm;
527         goto TryAgain;
528    } // end if lm>fNlayers
529    // counted the number of ladders and detectors now allocate space.
530    fGm = new TObjArray(fNmodules,0);
531
532    // Set up Shapes for a default configuration of 6 layers.
533    fTrans   = 0; // standard GEANT global/local coordinate system.
534    // prepare to read in transforms
535    lm = 0; // reuse lm as counter of modules.
536    rewind(pf); // start over reading file
537    while(fgets(buf,200,pf)!=NULL){ // for ever loop
538       for(i=0;i<200;i++)if(buf[i]!=' '){ // remove blank spaces.
539            buff = &(buf[i]);
540            break;
541       } // end for i
542       // remove blank lines and comments.
543       if(buff[0]=='\n'||buff[0]=='#'||buff[0]=='!'||
544         (buff[0]=='/'&&buff[1]=='/')) continue;
545       x = y = z = o = p = q = r = s = t = 0.0;
546       sscanf(buff,"%d %d %d %f %f %f %f %f %f %f %f %f",
547                   &l,&a,&d,&x,&y,&z,&o,&p,&q,&r,&s,&t);
548       if(l<1 || l>fNlayers) {
549          printf("error in file %s layer=%d min. is 1 max is %d/n",
550                  filename,l,fNlayers);
551          continue;
552       }// end if l
553       id[0] = l;id[1] = a;id[2] = d;
554       tran[0] = tran[1] = tran[2]  = 0.0;
555       tran[0] = (Double_t)x;tran[1] = (Double_t)y;tran[2] = (Double_t)z;
556       rot6[0] = rot6[1] = rot6[2] = rot6[3] = rot6[4] = rot6[5] =0.0;
557       rot6[0] = (Double_t)o;rot6[1] = (Double_t)p;rot6[2] = (Double_t)q;
558       rot6[3] = (Double_t)r;rot6[4] = (Double_t)s;rot6[5] = (Double_t)t;
559       switch (l){
560       case 1: case 2: // layer 1 or2 SPD
561           fGm->AddAt(new AliITSgeomMatrix(rot6,kSPD,id,tran),lm++);
562           break;
563       case 3: case 4: // layer 3 or 4 SDD
564           fGm->AddAt(new AliITSgeomMatrix(rot6,kSDD,id,tran),lm++);
565           break;
566       case 5: case 6: // layer 5 or 6 SSD
567           fGm->AddAt(new AliITSgeomMatrix(rot6,kSSD,id,tran),lm++);
568           break;
569       } // end switch
570    } // end while ever loop
571    fclose(pf);
572 }
573
574 //________________________________________________________________________
575 AliITSgeom::AliITSgeom(AliITSgeom &source){
576 ////////////////////////////////////////////////////////////////////////
577 //     The copy constructor for the AliITSgeom class. It calls the
578 // = operator function. See the = operator function for more details.
579 ////////////////////////////////////////////////////////////////////////
580
581     *this = source;  // Just use the = operator for now.
582
583     return;
584 }
585
586 //________________________________________________________________________
587 void AliITSgeom::operator=(AliITSgeom &source){
588 ////////////////////////////////////////////////////////////////////////
589 //     The = operator function for the AliITSgeom class. It makes an
590 // independent copy of the class in such a way that any changes made
591 // to the copied class will not affect the source class in any way.
592 // This is required for many ITS alignment studies where the copied
593 // class is then modified by introducing some misalignment.
594 ////////////////////////////////////////////////////////////////////////
595    Int_t i;
596
597    if(this == &source) return; // don't assign to ones self.
598
599    // if there is an old structure allocated delete it first.
600    if(this->fGm != 0){
601       for(i=0;i<this->fNmodules;i++) delete this->fGm->At(i);
602       delete this->fGm;
603    } // end if fGm != 0 
604    if(fNlad != 0) delete[] fNlad;
605    if(fNdet != 0) delete[] fNdet;
606
607    this->fTrans    = source.fTrans;
608    this->fNmodules = source.fNmodules;
609    this->fNlayers = source.fNlayers;
610    this->fNlad = new Int_t[fNlayers];
611    for(i=0;i<this->fNlayers;i++) this->fNlad[i] = source.fNlad[i];
612    this->fNdet = new Int_t[fNlayers];
613    for(i=0;i<this->fNlayers;i++) this->fNdet[i] = source.fNdet[i];
614    this->fShape = new TObjArray(*(source.fShape));//This does not make a proper copy.
615    this->fGm = new TObjArray(this->fNmodules,0);
616    for(i=0;i<this->fNmodules;i++){
617        this->fGm->AddAt(new AliITSgeomMatrix(*(
618            (AliITSgeomMatrix*)(source.fGm->At(i)))),i);
619    } // end for i
620    return;
621 }//_____________________________________________________________________
622 Int_t AliITSgeom::GetModuleIndex(const Int_t lay,const Int_t lad,
623                                  const Int_t det){
624 ////////////////////////////////////////////////////////////////////////
625 //      This routine computes the module index number from the layer,
626 // ladder, and detector numbers. The number of ladders and detectors
627 // per layer is determined when this geometry package is constructed,
628 // see AliITSgeom(const char *filename) for specifics.
629 ////////////////////////////////////////////////////////////////////////
630     Int_t i,j,k,id[3];
631
632     i = fNdet[lay-1] * (lad-1) + det - 1;
633     j = 0;
634     for(k=0;k<lay-1;k++) j += fNdet[k]*fNlad[k];
635     i = i+j;
636     GetGeomMatrix(i)->GetIndex(id);
637     if(id[0]==lay&&id[1]==lad&&id[2]==det) return i;
638     // Array of modules fGm is not in expected order. Search for this index
639     for(i=0;i<fNmodules;i++){
640         GetGeomMatrix(i)->GetIndex(id);
641         if(id[0]==lay&&id[1]==lad&&id[2]==det) return i;
642     } // end for i
643     // This layer ladder and detector combination does not exist return -1.
644     return -1;
645 }
646 //______________________________________________________________________
647 void AliITSgeom::GetModuleId(const Int_t index,
648                              Int_t &lay,Int_t &lad,Int_t &det){
649 ////////////////////////////////////////////////////////////////////////
650 //      This routine computes the layer, ladder and detector number 
651 // given the module index number. The number of ladders and detectors
652 // per layer is determined when this geometry package is constructed,
653 // see AliITSgeom(const char *filename) for specifics.
654 ////////////////////////////////////////////////////////////////////////
655     Int_t id[3];
656
657     GetGeomMatrix(index)->GetIndex(id);
658     lay = id[0]; lad = id[1]; det = id[2];
659     return;
660
661     // The old way kept for posterity.
662 /*
663     Int_t i,j,k;
664     j = 0;
665     for(k=0;k<fNlayers;k++){
666         j += fNdet[k]*fNlad[k];
667         if(j>index)break;
668     } // end for k
669     lay = k+1;
670     i = index -j + fNdet[k]*fNlad[k];
671     j = 0;
672     for(k=0;k<fNlad[lay-1];k++){
673         j += fNdet[lay-1];
674         if(j>i)break;
675     } // end for k
676     lad = k+1;
677     det = 1+i-fNdet[lay-1]*k;
678     return;
679 */
680 }
681 //___________________________________________________________________________
682 Int_t AliITSgeom::GetStartDet(const Int_t dtype){
683   /////////////////////////////////////////////////////////////////////////
684   // returns the starting module index value for a give type of detector id
685   /////////////////////////////////////////////////////////////////////////
686
687   switch(dtype){
688   case 0:
689      return GetModuleIndex(1,1,1);
690      break;
691   case 1:
692      return GetModuleIndex(3,1,1);
693      break;
694   case 2:
695      return GetModuleIndex(5,1,1);
696      break;
697   default:
698      printf("<AliITSgeom::GetFirstDet> undefined detector type\n");
699      return 0;
700   } // end switch
701
702   printf("<AliITSgeom::GetFirstDet> undefined detector type\n");
703   return 0;
704 }
705
706 //___________________________________________________________________________
707 Int_t AliITSgeom::GetLastDet(const Int_t dtype){
708   /////////////////////////////////////////////////////////////////////////
709   // returns the last module index value for a give type of detector id
710   /////////////////////////////////////////////////////////////////////////
711
712   switch(dtype){
713   case 0:
714      return GetLastSPD();
715      break;
716    case 1:
717      return GetLastSDD();
718      break;
719    case 2:
720      return GetLastSSD();
721      break;
722    default:
723      printf("<AliITSgeom::GetLastDet> undefined detector type\n");
724      return 0;
725   } // end switch
726
727   printf("<AliITSgeom::GetLastDet> undefined detector type\n");
728   return 0;
729 }
730
731 //___________________________________________________________________________
732 void AliITSgeom::PrintComparison(FILE *fp,AliITSgeom *other){
733 ////////////////////////////////////////////////////////////////////////
734 //     This function was primarily created for diagnostic reasons. It
735 // print to a file pointed to by the file pointer fp the difference
736 // between two AliITSgeom classes. The format of the file is basicly,
737 // define d? to be the difference between the same element of the two
738 // classes. For example dfrx = this->GetGeomMatrix(i)->frx 
739 // - other->GetGeomMatrix(i)->frx.
740 // if(at least one of dfx0, dfy0, dfz0,dfrx,dfry,dfrz are non zero) then print
741 // layer ladder detector dfx0 dfy0 dfz0 dfrx dfry dfrz
742 // if(at least one of the 9 elements of dfr[] are non zero) then print
743 // layer ladder detector dfr[0] dfr[1] dfr[2]
744 //                       dfr[3] dfr[4] dfr[5]
745 //                       dfr[6] dfr[7] dfr[8]
746 // Only non zero values are printed to save space. The differences are
747 // typical written to a file because there are usually a lot of numbers
748 // printed out and it is usually easier to read them in some nice editor
749 // rather than zooming quickly past you on a screen. fprintf is used to
750 // do the printing. The fShapeIndex difference is not printed at this time.
751 ////////////////////////////////////////////////////////////////////////
752    Int_t    i,j,idt[3],ido[3];
753    Double_t tt[3],to[3];  // translation
754    Double_t rt[3],ro[3];  // phi in radians
755    Double_t mt[3][3],mo[3][3]; // matrixes
756    AliITSgeomMatrix *gt,*go;
757    Bool_t   t;
758
759    for(i=0;i<this->fNmodules;i++){
760          gt  =  this->GetGeomMatrix(i);
761          go  = other->GetGeomMatrix(i);
762          gt->GetIndex(idt);
763          go->GetIndex(ido);
764          t = kFALSE;
765          for(i=0;i<3;i++) t = t&&idt[i]!=ido[i];
766          if(t) fprintf(fp,"%4.4d %1.1d %2.2d %2.2d %1.1d %2.2d %2.2d\n",i,
767                        idt[0],idt[1],idt[2],ido[0],ido[1],ido[2]);
768          gt->GetTranslation(tt);
769          go->GetTranslation(to);
770          gt->GetAngles(rt);
771          go->GetAngles(ro);
772          t = kFALSE;
773          for(i=0;i<3;i++) t = t&&tt[i]!=to[i];
774          if(t) fprintf(fp,"%1.1d %2.2d %2.2d dTrans=%f %f %f drot=%f %f %f\n",
775                        idt[0],idt[1],idt[2],
776                        tt[0]-to[0],tt[1]-to[1],tt[2]-to[2],
777                        rt[0]-ro[0],rt[1]-ro[1],rt[2]-ro[2]);
778          t = kFALSE;
779          gt->GetMatrix(mt);
780          go->GetMatrix(mo);
781          for(i=0;i<3;i++)for(j=0;j<3;j++)  t = mt[i][j] != mo[i][j];
782          if(t){
783              fprintf(fp,"%1.1d %2.2d %2.2d dfr= %e %e %e\n",
784                      idt[0],idt[1],idt[2],
785                  mt[0][0]-mo[0][0],mt[0][1]-mo[0][1],mt[0][2]-mo[0][2]);
786              fprintf(fp,"        dfr= %e %e %e\n",
787                  mt[1][0]-mo[1][0],mt[1][1]-mo[1][1],mt[1][2]-mo[1][2]);
788              fprintf(fp,"        dfr= %e %e %e\n",
789                  mt[2][0]-mo[2][0],mt[2][1]-mo[2][1],mt[2][2]-mo[2][2]);
790          } // end if t
791    } // end for i
792    return;
793 }
794
795 //___________________________________________________________________________
796 void AliITSgeom::PrintData(FILE *fp,
797                            const Int_t lay,const Int_t lad,const Int_t det){
798 ////////////////////////////////////////////////////////////////////////
799 //     This function prints out the coordinate transformations for
800 // the particular detector defined by layer, ladder, and detector
801 // to the file pointed to by the File pointer fp. fprintf statements
802 // are used to print out the numbers. The format is
803 // layer ladder detector Trans= fx0 fy0 fz0 rot= frx fry frz Shape=fShapeIndex
804 //                         dfr= fr[0] fr[1] fr[2]
805 //                         dfr= fr[3] fr[4] fr[5]
806 //                         dfr= fr[6] fr[7] fr[8]
807 // By indicating which detector, some control over the information 
808 // is given to the user. The output it written to the file pointed
809 // to by the file pointer fp. This can be set to stdout if you want.
810 ////////////////////////////////////////////////////////////////////////
811    AliITSgeomMatrix *gt;
812    Double_t t[3],r[3],m[3][3];
813
814    gt = this->GetGeomMatrix(GetModuleIndex(lay,lad,det));
815    gt->GetTranslation(t);
816    gt->GetAngles(r);
817    fprintf(fp,"%1.1d %2.2d %2.2d Trans=%f %f %f rot=%f %f %f Shape=%d\n",
818            lay,lad,det,t[0],t[1],t[2],r[0],r[1],r[2],
819            gt->GetDetectorIndex());
820    gt->GetMatrix(m);
821    fprintf(fp,"        dfr= %e %e %e\n",m[0][0],m[0][1],m[0][2]);
822    fprintf(fp,"        dfr= %e %e %e\n",m[1][0],m[1][1],m[1][2]);
823    fprintf(fp,"        dfr= %e %e %e\n",m[2][0],m[2][1],m[2][2]);
824    return;
825 }
826 //___________________________________________________________________________
827 ofstream & AliITSgeom::PrintGeom(ofstream &R__b){
828 ////////////////////////////////////////////////////////////////////////
829 //     Stream out an object of class AliITSgeom to standard output.
830 ////////////////////////////////////////////////////////////////////////
831     Int_t i;
832
833     R__b.setf(ios::scientific);
834     R__b << fTrans << " ";
835     R__b << fNmodules << " ";
836     R__b << fNlayers << " ";
837     for(i=0;i<fNlayers;i++) R__b << fNlad[i] << " ";
838     for(i=0;i<fNlayers;i++) R__b << fNdet[i] << "\n";
839     for(i=0;i<fNmodules;i++) {
840         R__b <<setprecision(16) << *(GetGeomMatrix(i)) << "\n";
841     } // end for i
842     return R__b;
843 }
844 //___________________________________________________________________________
845 ifstream & AliITSgeom::ReadGeom(ifstream &R__b){
846 ////////////////////////////////////////////////////////////////////////
847 //     Stream in an object of class AliITSgeom from standard input.
848 ////////////////////////////////////////////////////////////////////////
849       Int_t i;
850
851       fNlad = new Int_t[fNlayers];
852       fNdet = new Int_t[fNlayers];
853       if(fGm!=0){
854           for(i=0;i<fNmodules;i++) delete GetGeomMatrix(i);
855           delete fGm;
856       } // end if fGm!=0
857
858       R__b >> fTrans >> fNmodules >> fNlayers;
859       fNlad = new Int_t[fNlayers];
860       fNdet = new Int_t[fNlayers];
861       for(i=0;i<fNlayers;i++) R__b >> fNlad[i];
862       for(i=0;i<fNlayers;i++) R__b >> fNdet[i];
863       fGm = new TObjArray(fNmodules,0);
864       for(i=0;i<fNmodules;i++){
865           fGm->AddAt(new AliITSgeomMatrix,i);
866           R__b >> *(GetGeomMatrix(i));
867       } // end for i
868       return R__b;
869 }
870 //___________________________________________________________________________
871
872 //______________________________________________________________________
873 //     The following routines modify the transformation of "this"
874 // geometry transformations in a number of different ways.
875 //______________________________________________________________________
876 void AliITSgeom::GlobalChange(const Float_t *tran,const Float_t *rot){
877 ////////////////////////////////////////////////////////////////////////
878 //     This function performs a Cartesian translation and rotation of
879 // the full ITS from its default position by an amount determined by
880 // the three element arrays dtranslation and drotation. If every element
881 // of dtranslation and drotation are zero then there is no change made
882 // the geometry. The change is global in that the exact same translation
883 // and rotation is done to every detector element in the exact same way.
884 // The units of the translation are those of the Monte Carlo, usually cm,
885 // and those of the rotation are in radians. The elements of dtranslation
886 // are dtranslation[0] = x, dtranslation[1] = y, and dtranslation[2] = z.
887 // The elements of drotation are drotation[0] = rx, drotation[1] = ry, and
888 // drotation[2] = rz. A change in x will move the hole ITS in the ALICE
889 // global x direction, the same for a change in y. A change in z will
890 // result in a translation of the ITS as a hole up or down the beam line.
891 // A change in the angles will result in the inclination of the ITS with
892 // respect to the beam line, except for an effective rotation about the
893 // beam axis which will just rotate the ITS as a hole about the beam axis.
894 ////////////////////////////////////////////////////////////////////////
895    Int_t    i,j;
896    Double_t t[3],r[3];
897    AliITSgeomMatrix *g;
898
899    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
900    for(i=0;i<fNmodules;i++){
901          g = this->GetGeomMatrix(i);
902          g->GetTranslation(t);
903          g->GetAngles(r);
904          for(j=0;j<3;j++){
905               t[j] += tran[j];
906               r[j] += rot[j];
907          } // end for j
908          g->SetTranslation(t);
909          g->SetAngles(r);
910    } // end for i
911    return;
912 }
913 //___________________________________________________________________________
914 void AliITSgeom::GlobalCylindericalChange(const Float_t *tran,const Float_t *rot){
915 ////////////////////////////////////////////////////////////////////////
916 //     This function performs a cylindrical translation and rotation of
917 // each ITS element by a fixed about in radius, rphi, and z from its
918 // default position by an amount determined by the three element arrays
919 // dtranslation and drotation. If every element of dtranslation and
920 // drotation are zero then there is no change made the geometry. The
921 // change is global in that the exact same distance change in translation
922 // and rotation is done to every detector element in the exact same way.
923 // The units of the translation are those of the Monte Carlo, usually cm,
924 // and those of the rotation are in radians. The elements of dtranslation
925 // are dtranslation[0] = r, dtranslation[1] = rphi, and dtranslation[2] = z.
926 // The elements of drotation are drotation[0] = rx, drotation[1] = ry, and
927 // drotation[2] = rz. A change in r will results in the increase of the
928 // radius of each layer by the same about. A change in rphi will results in
929 // the rotation of each layer by a different angle but by the same
930 // circumferential distance. A change in z will result in a translation
931 // of the ITS as a hole up or down the beam line. A change in the angles
932 // will result in the inclination of the ITS with respect to the beam
933 // line, except for an effective rotation about the beam axis which will
934 // just rotate the ITS as a hole about the beam axis.
935 ////////////////////////////////////////////////////////////////////////
936    Int_t    i,j;
937    Double_t t[3],ro[3],r,r0,phi,rphi;
938    AliITSgeomMatrix *g;
939
940    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
941    for(i=0;i<fNmodules;i++){
942          g = this->GetGeomMatrix(i);
943          g->GetTranslation(t);
944          g->GetAngles(ro);
945          r = r0= TMath::Hypot(t[1],t[0]);
946          phi   = TMath::ATan2(t[1],t[0]);
947          rphi  = r0*phi;
948          r    += tran[0];
949          rphi += tran[1];
950          phi   = rphi/r0;
951          t[0]  = r*TMath::Cos(phi);
952          t[1]  = r*TMath::Sin(phi);
953          t[2] += tran[2];
954          for(j=0;j<3;j++){
955               ro[j] += rot[j];
956          } // end for j
957          g->SetTranslation(t);
958          g->SetAngles(ro);
959    } // end for i
960    return;
961 }
962 //___________________________________________________________________________
963 void AliITSgeom::RandomChange(const Float_t *stran,const Float_t *srot){
964 ////////////////////////////////////////////////////////////////////////
965 //     This function performs a Gaussian random displacement and/or
966 // rotation about the present global position of each active
967 // volume/detector of the ITS. The sigma of the random displacement
968 // is determined by the three element array stran, for the
969 // x y and z translations, and the three element array srot,
970 // for the three rotation about the axis x y and z.
971 ////////////////////////////////////////////////////////////////////////
972    Int_t    i,j;
973    Double_t t[3],r[3];
974    //MI   TRandom ran;
975    AliITSgeomMatrix *g;
976
977    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
978    for(i=0;i<fNmodules;i++){
979          g = this->GetGeomMatrix(i);
980          g->GetTranslation(t);
981          g->GetAngles(r);
982          for(j=0;j<3;j++){
983               t[j] += gRandom->Gaus(0.0,stran[j]);
984               r[j] += gRandom->Gaus(0.0, srot[j]);
985          } // end for j
986          g->SetTranslation(t);
987          g->SetAngles(r);
988    } // end for i
989    return;
990 }
991 //___________________________________________________________________________
992 void AliITSgeom::RandomCylindericalChange(const Float_t *stran,
993                                           const Float_t *srot){
994 ////////////////////////////////////////////////////////////////////////
995 //     This function performs a Gaussian random displacement and/or
996 // rotation about the present global position of each active
997 // volume/detector of the ITS. The sigma of the random displacement
998 // is determined by the three element array stran, for the
999 // r rphi and z translations, and the three element array srot,
1000 // for the three rotation about the axis x y and z. This random change
1001 // in detector position allow for the simulation of a random uncertainty
1002 // in the detector positions of the ITS.
1003 ////////////////////////////////////////////////////////////////////////
1004    Int_t    i,j;
1005    Double_t t[3],ro[3],r,r0,phi,rphi;
1006    TRandom ran;
1007    AliITSgeomMatrix *g;
1008
1009    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
1010    for(i=0;i<fNmodules;i++){
1011          g = this->GetGeomMatrix(i);
1012          g->GetTranslation(t);
1013          g->GetAngles(ro);
1014          r = r0= TMath::Hypot(t[1],t[0]);
1015          phi   = TMath::ATan2(t[1],t[0]);
1016          rphi  = r0*phi;
1017          r    += ran.Gaus(0.0,stran[0]);
1018          rphi += ran.Gaus(0.0,stran[1]);
1019          phi   = rphi/r0;
1020          t[0]  = r*TMath::Cos(phi);
1021          t[1]  = r*TMath::Sin(phi);
1022          t[2] += ran.Gaus(0.0,stran[2]);
1023          for(j=0;j<3;j++){
1024               ro[j] += ran.Gaus(0.0, srot[j]);
1025          } // end for j
1026          g->SetTranslation(t);
1027          g->SetAngles(ro);
1028    } // end for i
1029    return;
1030 }
1031 //______________________________________________________________________
1032 void AliITSgeom::GeantToTracking(AliITSgeom &source){
1033 /////////////////////////////////////////////////////////////////////////
1034 //     Copy the geometry data but change it to go between the ALICE
1035 // Global coordinate system to that used by the ITS tracking. A slightly
1036 // different coordinate system is used when tracking. This coordinate 
1037 // system is only relevant when the geometry represents the cylindrical
1038 // ALICE ITS geometry. For tracking the Z axis is left alone but X-> -Y
1039 // and Y-> X such that X always points out of the ITS cylinder for every
1040 // layer including layer 1 (where the detectors are mounted upside down).
1041 //Begin_Html
1042 /*
1043 <img src="picts/ITS/AliITSgeomMatrix_T1.gif">
1044 */
1045 //End_Html
1046 ////////////////////////////////////////////////////////////////////////
1047    Int_t    i,j,k,l,id[3];
1048    Double_t R0[3][3],R1[3][3];
1049    Double_t A0[3][3] = {{0.,+1.,0.},{-1.,0.,0.},{0.,0.,+1.}};
1050    Double_t A1[3][3] = {{0.,-1.,0.},{+1.,0.,0.},{0.,0.,+1.}};
1051
1052    *this = source;  // copy everything
1053    for(i=0;i<GetIndexMax();i++){
1054        GetGeomMatrix(i)->GetIndex(id);
1055        GetGeomMatrix(i)->GetMatrix(R0);
1056        if(id[0]==1){ // Layer 1 is treated different from the others.
1057            for(j=0;j<3;j++) for(k=0;k<3;k++){
1058                R1[j][k] = 0.;
1059                for(l=0;l<3;l++) R1[j][k] += A0[j][l]*R0[l][k];
1060            } // end for j,k
1061        }else{
1062            for(j=0;j<3;j++) for(k=0;k<3;k++){
1063                R1[j][k] = 0.;
1064                for(l=0;l<3;l++) R1[j][k] += A1[j][l]*R0[l][k];
1065            } // end for j,k
1066        } // end if
1067        GetGeomMatrix(i)->SetMatrix(R1);
1068    } // end for i
1069    this->fTrans = (this->fTrans && 0xfffe) + 1;  // set bit 0 true.
1070    return;
1071 }
1072 //______________________________________________________________________
1073 Int_t AliITSgeom::GetNearest(const Double_t g[3],const Int_t lay){
1074 ////////////////////////////////////////////////////////////////////////
1075 //      Finds the Detector (Module) that is nearest the point g [cm] in
1076 // ALICE Global coordinates. If layer !=0 then the search is restricted
1077 // to Detectors (Modules) in that particular layer.
1078 ////////////////////////////////////////////////////////////////////////
1079      Int_t    i,l,a,e,in=0;
1080      Double_t d,dn=1.0e10;
1081      Bool_t   t=lay!=0; // skip if lay = 0 default value check all layers.
1082
1083      for(i=0;i<fNmodules;i++){
1084           if(t){GetModuleId(i,l,a,e);if(l!=lay) continue;}
1085           if((d=GetGeomMatrix(i)->Distance2(g))<dn){
1086                dn = d;
1087                in = i;
1088           } // end if
1089      } // end for i
1090      return in;
1091 }
1092 //______________________________________________________________________
1093 void AliITSgeom::GetNearest27(const Double_t g[3],Int_t n[27],const Int_t lay){
1094 ////////////////////////////////////////////////////////////////////////
1095 //      Finds 27 Detectors (Modules) that are nearest the point g [cm] in
1096 // ALICE Global coordinates. If layer !=0 then the search is restricted
1097 // to Detectors (Modules) in that particular layer. The number 27 comes 
1098 // from including the nearest detector and all those around it (up, down,
1099 // left, right, forwards, backwards, and the corners).
1100 ////////////////////////////////////////////////////////////////////////
1101      Int_t    i,l,a,e,in[27]={0,0,0,0,0,0,0,0,0,
1102                               0,0,0,0,0,0,0,0,0,
1103                               0,0,0,0,0,0,0,0,0,};
1104      Double_t d,dn[27]={1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,
1105                         1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,
1106                         1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,
1107                         1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,1.0e10,
1108                         1.0e10,1.0e10,1.0e10};
1109      Bool_t   t=(lay!=0); // skip if lay = 0 default value check all layers.
1110
1111      for(i=0;i<fNmodules;i++){
1112           if(t){GetModuleId(i,l,a,e);if(l!=lay) continue;}
1113           for(a=0;a<27;a++){
1114                d = GetGeomMatrix(i)->Distance2(g);
1115                if(d<dn[a]){
1116                    for(e=26;e>a;e--){dn[e] = dn[e-1];in[e] = in[e-1];}
1117                    dn[a] = d; in[a] = i;
1118                } // end if d<dn[i]
1119           } // end for a
1120      } // end for i
1121      for(i=0;i<27;i++) n[i] = in[i];
1122 }
1123 //----------------------------------------------------------------------