In AliMUONTriggerQADataMakerRec:
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerCircuit.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 /* $Id$ */
17
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONTriggerCircuit
20 /// Contains as data members the Y positions of the X declusturized strips and 
21 /// the X positions of the (doubled or not) Y strips.
22 /// This is used to associate the global positions to the fired strips of the 
23 /// local trigger output (see AliMUONTrackReconstructor::MakeTriggerTrack)
24 ///
25 /// \author Philippe Crochet (LPCCFd)
26 //-----------------------------------------------------------------------------
27
28 #include "AliMUONTriggerCircuit.h"
29 #include "AliMUONConstants.h"
30 #include "AliMUONGeometryTransformer.h"
31
32 #include "AliMpTrigger.h"
33 #include "AliMpSlat.h"
34 #include "AliMpPCB.h"
35 #include "AliMpSegmentation.h"
36 #include "AliMpVSegmentation.h"
37 #include "AliMpCathodType.h"
38 #include "AliMpDDLStore.h"
39 #include "AliMpLocalBoard.h"
40 #include "AliMpConstants.h"
41 #include "AliMpPad.h"
42 #include "AliMpEncodePair.h"
43
44 #include "AliRun.h"
45 #include "AliLog.h"
46
47 #include <TMath.h>
48 #include <Riostream.h>
49
50 /// \cond CLASSIMP
51 ClassImp(AliMUONTriggerCircuit)
52 /// \endcond
53
54 //----------------------------------------------------------------------
55 AliMUONTriggerCircuit::AliMUONTriggerCircuit(const AliMUONGeometryTransformer* transformer)
56     : TObject(),
57       fkTransformer(transformer),
58       fkCurrentSeg(0x0),
59       fCurrentDetElem(0x0),
60       fCurrentLocalBoard(0x0)
61 {
62 /// Constructor
63   
64     for (Int_t i = 1; i < AliMpConstants::NofLocalBoards()+1; ++i) {
65       fXpos11[i].Set(16); 
66       fYpos11[i].Set(31);
67       fYpos21[i].Set(63);
68       fZpos11[i].Set(31);
69       fZpos21[i].Set(63);
70       fXwidth11[i].Set(16); 
71       fYwidth11[i].Set(31);
72       fYwidth21[i].Set(63);
73     }
74
75     for (Int_t i = 1; i < AliMpConstants::NofLocalBoards()+1; ++i) { // board begins at 1
76   
77     AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(i);
78
79     if (!localBoard)
80     {
81       AliError(Form("Did not get localboard %d",i));
82       continue;
83     }
84
85     LoadXPos(localBoard);
86     LoadYPos(localBoard);
87
88   }
89
90 }
91
92 //----------------------------------------------------------------------
93 AliMUONTriggerCircuit::~AliMUONTriggerCircuit()
94 {
95 /// Destructor
96    for (Int_t i = 1; i < AliMpConstants::NofLocalBoards()+1; ++i) {
97      fXpos11[i].Reset();
98      fYpos11[i].Reset();
99      fYpos21[i].Reset();
100      fZpos11[i].Reset();
101      fZpos21[i].Reset();
102      fXwidth11[i].Reset();
103      fYwidth11[i].Reset();
104      fYwidth21[i].Reset();
105     }
106
107
108
109 //----------------------------------------------------------------------
110 AliMUONTriggerCircuit::AliMUONTriggerCircuit(const AliMUONTriggerCircuit& circuit)
111     :  TObject(circuit),
112        fkTransformer(circuit.fkTransformer), // do not copy, just pointed to
113        fkCurrentSeg(circuit.fkCurrentSeg),
114        fCurrentDetElem(circuit.fCurrentDetElem),
115        fCurrentLocalBoard(circuit.fCurrentLocalBoard)
116 {
117 /// Copy constructor
118
119     for (Int_t i = 1; i < AliMpConstants::NofLocalBoards()+1; ++i) {
120       fXpos11[i] = circuit.fXpos11[i];
121       fYpos11[i] = circuit.fYpos11[i];
122       fYpos21[i] = circuit.fYpos21[i];
123       fZpos11[i] = circuit.fZpos11[i];
124       fZpos21[i] = circuit.fZpos21[i];
125       fXwidth11[i] = circuit.fXwidth11[i];
126       fYwidth11[i] = circuit.fYwidth11[i];
127       fYwidth21[i] = circuit.fYwidth21[i];
128     }
129
130 }
131 //----------------------------------------------------------------------
132 AliMUONTriggerCircuit& AliMUONTriggerCircuit::operator=(const AliMUONTriggerCircuit& circuit) 
133 {
134 /// Assignment operator
135
136   if (this == &circuit) return *this;
137
138   fkTransformer      = circuit.fkTransformer;
139   fkCurrentSeg       = circuit.fkCurrentSeg;
140   fCurrentDetElem    = circuit.fCurrentDetElem;
141   fCurrentLocalBoard = circuit.fCurrentLocalBoard;
142
143   for (Int_t i = 1; i < AliMpConstants::NofLocalBoards()+1; ++i) {
144     fXpos11[i] = circuit.fXpos11[i];
145     fYpos11[i] = circuit.fYpos11[i];
146     fYpos21[i] = circuit.fYpos21[i];
147     fZpos11[i] = circuit.fZpos11[i];
148     fZpos21[i] = circuit.fZpos21[i];
149     fXwidth11[i] = circuit.fXwidth11[i];
150     fYwidth11[i] = circuit.fYwidth11[i];
151     fYwidth21[i] = circuit.fYwidth21[i];
152   }
153
154   return *this;
155
156 }
157
158 //---------------------------------------------------------------------
159 void AliMUONTriggerCircuit::LoadYPos(AliMpLocalBoard* const localBoard)
160 {
161 /// fill fYpos11 and fYpos21 -> y position of X declusterized strips
162   
163   fCurrentLocalBoard = localBoard->GetId();
164   Int_t ichamber = 0;
165   Int_t icathode = 0;    
166     
167   Int_t zeroDown = localBoard->GetSwitch(AliMpLocalBoard::kZeroDown);
168   Int_t zeroUp   = localBoard->GetSwitch(AliMpLocalBoard::kZeroUp);
169  
170   Int_t iline = AliMp::PairFirst(localBoard->GetPosition());
171   Int_t icol  = AliMp::PairSecond(localBoard->GetPosition());
172   if ( iline == 5 ) --icol;
173
174   //--- first plane 
175   ichamber = 10;
176   fCurrentDetElem = AliMpDDLStore::Instance()->GetDEfromLocalBoard(fCurrentLocalBoard, ichamber);
177
178   fkCurrentSeg = AliMpSegmentation::Instance()
179         ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
180
181   Int_t iFirstStrip = FirstStrip(localBoard);
182   Int_t iLastStrip  = iFirstStrip + 16;    
183   Int_t iStripCircuit = 0;
184
185   FillXstrips(icol, iFirstStrip, iLastStrip, 
186               iStripCircuit, kTRUE);
187   
188   //--- second plane 
189   ichamber = 12;
190   fCurrentDetElem = AliMpDDLStore::Instance()->GetDEfromLocalBoard(fCurrentLocalBoard, ichamber);
191
192   fkCurrentSeg = AliMpSegmentation::Instance()
193         ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
194
195   // second plane middle part
196   Int_t iFirstStripMiddle = FirstStrip(localBoard);
197   Int_t iLastStripMiddle  = iFirstStrip + 16;
198   iStripCircuit = 8;
199
200   FillXstrips(icol, iFirstStripMiddle, iLastStripMiddle,
201               iStripCircuit, kFALSE);
202   
203   // second plane upper part
204   if (zeroUp == 0) { // something up
205     Int_t iFirstStripUp;
206     Int_t iLastStripUp;
207     Int_t icolUp = icol;
208
209     // check if we need to move to another detElemId
210     AliMpPad pad = fkCurrentSeg->PadByIndices(icol-1,iLastStripMiddle+1,kFALSE);
211
212     if (pad.IsValid()) { // upper strips within same detElemId
213       iFirstStripUp = iLastStripMiddle;
214       iLastStripUp  = iFirstStripUp + 8;
215
216     } else {             // upper strips in another detElemId
217       fCurrentDetElem = AliMpDDLStore::Instance()->
218                    GetNextDEfromLocalBoard(fCurrentLocalBoard, ichamber);
219
220       fkCurrentSeg = AliMpSegmentation::Instance()
221             ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
222
223       iFirstStripUp = 0;
224       iLastStripUp  = iFirstStripUp + 8;
225       if (iline == 4) icolUp = icol - 1; // special case
226       if (iline == 5) icolUp = icol + 1; // special case
227     }
228     
229     iStripCircuit = 24;
230     FillXstrips(icolUp, iFirstStripUp, iLastStripUp,
231                 iStripCircuit, kFALSE);
232     
233     // fill strip between middle and upper part
234     fYpos21[fCurrentLocalBoard][47] = (fYpos21[fCurrentLocalBoard][46] + 
235                                        fYpos21[fCurrentLocalBoard][48])/2.;
236     fZpos21[fCurrentLocalBoard][47] = (fZpos21[fCurrentLocalBoard][46] + 
237                                        fZpos21[fCurrentLocalBoard][48])/2.;
238     fYwidth21[fCurrentLocalBoard][47] = (fYwidth21[fCurrentLocalBoard][46] + 
239                                          fYwidth21[fCurrentLocalBoard][48])/2.;
240   } // end of something up
241   
242   // restore current detElemId & segmentation
243   fCurrentDetElem = AliMpDDLStore::Instance()->GetDEfromLocalBoard(fCurrentLocalBoard, ichamber);
244   fkCurrentSeg = AliMpSegmentation::Instance()
245       ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
246
247   // second plane lower part
248   if (zeroDown == 0) { // something down
249     Int_t iFirstStripDo;
250     Int_t iLastStripDo;
251     Int_t icolDo = icol;
252     
253     // check if we need to move to another detElemId      
254     AliMpPad pad = fkCurrentSeg->PadByIndices(icol-1,iFirstStripMiddle-1,kFALSE);
255     if (pad.IsValid()) { // lower strips within same detElemId
256       iFirstStripDo = iFirstStripMiddle - 8;
257       iLastStripDo  = iFirstStripDo + 8;              
258
259     } else {             // lower strips in another detElemId 
260       fCurrentDetElem = AliMpDDLStore::Instance()
261           ->GetPreviousDEfromLocalBoard(fCurrentLocalBoard, ichamber);
262
263       fkCurrentSeg = AliMpSegmentation::Instance()
264           ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
265
266       // get iFirstStrip in this module 
267       const AliMpTrigger* t = AliMpSegmentation::Instance()->GetTrigger(fkCurrentSeg);
268       const AliMpSlat* slat = t->GetLayer(0);
269
270       if (iline == 5) icolDo = icol + 1; // special case
271       if (iline == 6) icolDo = icol - 1; // special case
272             
273       const AliMpPCB* pcb = slat->GetPCB(icolDo-1);
274       iFirstStripDo = (pcb->Iymax() + 1) - 8;
275       iLastStripDo =  iFirstStripDo + 8;
276     }  
277     
278     iStripCircuit = 0;
279     FillXstrips(icolDo, iFirstStripDo, iLastStripDo,
280                 iStripCircuit, kFALSE);
281     
282     // fill strip between middle and upper part
283     fYpos21[fCurrentLocalBoard][15] = (fYpos21[fCurrentLocalBoard][14] + 
284                                        fYpos21[fCurrentLocalBoard][16])/2.;
285     fZpos21[fCurrentLocalBoard][15] = (fZpos21[fCurrentLocalBoard][14] + 
286                                        fZpos21[fCurrentLocalBoard][16])/2.;
287     fYwidth21[fCurrentLocalBoard][15] = (fYwidth21[fCurrentLocalBoard][14] + 
288                                          fYwidth21[fCurrentLocalBoard][16])/2.;
289   } // end of something down
290   
291 }
292
293 //----------------------------------------------------------------------
294 void AliMUONTriggerCircuit::FillXstrips(const Int_t icol, 
295                                         const Int_t iFirstStrip, const Int_t iLastStrip, 
296                                         Int_t liStripCircuit, const Bool_t is11)
297 {    
298 /// fill 
299   TArrayF& ypos   = (is11) ? fYpos11[fCurrentLocalBoard] : fYpos21[fCurrentLocalBoard];
300   TArrayF& zpos   = (is11) ? fZpos11[fCurrentLocalBoard] : fZpos21[fCurrentLocalBoard];
301   TArrayF& ywidth = (is11) ? fYwidth11[fCurrentLocalBoard] : fYwidth21[fCurrentLocalBoard];
302
303   Double_t xyGlobal[3] = {0.};
304   for (Int_t istrip = iFirstStrip; istrip < iLastStrip; ++istrip) {
305
306     AliMpPad pad = fkCurrentSeg->PadByIndices(icol-1,istrip,kTRUE);
307     if ( !pad.IsValid() ) {
308       StdoutToAliError(cout << "Pad not found in seg " << endl;
309                        fkCurrentSeg->Print();
310                        cout << " ix,iy=" << icol-1 << "," << istrip << endl;
311                        );
312     }
313     Float_t yDim = pad.GetDimensionY(); // half size! 
314
315     XYGlobal(pad,xyGlobal);
316     
317     ypos[2*liStripCircuit] = xyGlobal[1];
318     zpos[2*liStripCircuit] = xyGlobal[2];
319     ywidth[2*liStripCircuit] = 2. * yDim;
320     if (istrip != (iLastStrip - 1)) {
321       ypos[2*liStripCircuit+1] = xyGlobal[1] + yDim;
322       zpos[2*liStripCircuit+1] = xyGlobal[2];
323       ywidth[2*liStripCircuit+1] = 2. * yDim;
324     }
325     liStripCircuit++;
326   }    
327 }
328
329
330 //----------------------------------------------------------------------
331 void AliMUONTriggerCircuit::LoadXPos(AliMpLocalBoard* const localBoard)
332 {
333 /// fill fXpos11 -> x position of Y strips for the first plane only
334 /// fXpos11 contains the x position of Y strip for the current circuit
335 /// taking into account whether or nor not part(s) of the circuit
336 /// (middle, up or down) has(have) 16 strips (handdled by means of switchs)
337
338   fCurrentLocalBoard = localBoard->GetId();
339
340   Int_t ichamber = 10;
341   Int_t icathode = 1;
342   
343   Int_t x2u = localBoard->GetSwitch(AliMpLocalBoard::kX2u);
344   Int_t x2m = localBoard->GetSwitch(AliMpLocalBoard::kX2m);
345   Int_t x2d = localBoard->GetSwitch(AliMpLocalBoard::kX2d);
346   Int_t zeroAllYLSB = localBoard->GetSwitch(AliMpLocalBoard::kZeroAllYLSB);
347
348   Int_t  iStripCircuit = 0;
349   Int_t  iFirstStrip   = 0;
350   Int_t  iLastStrip    = 0;
351   Bool_t doubling      = kFALSE;
352   
353   Int_t iline = AliMp::PairFirst(localBoard->GetPosition());
354   Int_t icol  = AliMp::PairSecond(localBoard->GetPosition());
355   if ( iline == 5 ) --icol;
356
357   fCurrentDetElem = AliMpDDLStore::Instance()->GetDEfromLocalBoard(fCurrentLocalBoard, ichamber);
358
359   fkCurrentSeg = AliMpSegmentation::Instance()
360         ->GetMpSegmentation(fCurrentDetElem, AliMp::GetCathodType(icathode));  
361
362   // check if one needs a strip doubling or not
363   if ( (x2u || x2m || x2d ) && x2m ) doubling = kTRUE;
364   
365
366   // check if one starts at strip = 0 or 8 (boards 26-29 and 143-146)
367   if (zeroAllYLSB) iStripCircuit = 8;
368   
369   // get iFirstStrip in this module 
370   const AliMpTrigger* t = AliMpSegmentation::Instance()->GetTrigger(fkCurrentSeg);
371   const AliMpSlat* slat = t->GetLayer(0);
372   
373   const AliMpPCB* pcb = slat->GetPCB(icol-1);
374   iFirstStrip = pcb->Ixmin();
375   
376
377   if (doubling || zeroAllYLSB == 1) iLastStrip = iFirstStrip + 8;
378   else iLastStrip = iFirstStrip + 16;
379   
380   FillYstrips(iFirstStrip, iLastStrip, iStripCircuit, doubling);  
381 }
382
383 //----------------------------------------------------------------------
384 void AliMUONTriggerCircuit::FillYstrips(const Int_t iFirstStrip, const Int_t iLastStrip, 
385                                         Int_t liStripCircuit,
386                                         const Bool_t doubling)
387 {    
388 /// fill
389   Double_t xyGlobal[3] = {0.};
390
391   for (Int_t istrip = iFirstStrip; istrip < iLastStrip; ++istrip) {
392
393     AliMpPad pad = fkCurrentSeg->PadByIndices(istrip,0,kTRUE);
394
395     if ( !pad.IsValid() )
396     {
397         StdoutToAliError(cout << "Pad not found in seg " << endl;
398                          fkCurrentSeg->Print();
399                          cout << " ix,iy=" << istrip << "," << 0 << endl;
400                          );
401     }
402     Float_t xDim = pad.GetDimensionX(); // half size!
403
404     XYGlobal(pad,xyGlobal);
405     
406     if (!doubling) {    
407       fXpos11[fCurrentLocalBoard].AddAt(xyGlobal[0], liStripCircuit);
408       fXwidth11[fCurrentLocalBoard].AddAt(2. * xDim, liStripCircuit);
409     } else if (doubling) {
410
411       fXpos11[fCurrentLocalBoard].AddAt(TMath::Sign(1.,xyGlobal[0]) * 
412                                   (TMath::Abs(xyGlobal[0]) - xDim/2.), 2*liStripCircuit);
413       fXwidth11[fCurrentLocalBoard].AddAt(2. * xDim, 2*liStripCircuit);
414
415       fXpos11[fCurrentLocalBoard].AddAt(TMath::Sign(1.,xyGlobal[0]) *
416                                   (TMath::Abs(fXpos11[fCurrentLocalBoard][2*liStripCircuit]) + xDim),
417                                         2*liStripCircuit + 1); 
418       fXwidth11[fCurrentLocalBoard].AddAt(2. * xDim, 2*liStripCircuit + 1);
419     }
420
421     liStripCircuit++;
422   }    
423 }
424
425 //----------------------------------------------------------------------
426 void AliMUONTriggerCircuit::XYGlobal(const AliMpPad& pad,
427                                      Double_t* xyGlobal)
428 {
429 /// returns pad x & y positions and x & y pad dimensions in global coordinates
430 /// note: no need for transformation for pad dimensions
431   
432   // get the pad position and dimensions
433   Double_t xl1 = pad.GetPositionX();
434   Double_t yl1 = pad.GetPositionY();
435   
436   // positions from local to global 
437   fkTransformer->Local2Global(fCurrentDetElem, xl1, yl1, 0, 
438                                  xyGlobal[0], xyGlobal[1], xyGlobal[2]);
439 }
440
441
442 //----------------------------------------------------------------------
443 //--- methods which return member data related info
444 //----------------------------------------------------------------------
445 //----------------------------------------------------------------------
446 Float_t AliMUONTriggerCircuit::GetX11Pos(Int_t localBoardId, Int_t istrip) const 
447 {
448 /// returns X position of Y strip istrip in MC11
449   return fXpos11[localBoardId][istrip];
450 }
451 Float_t AliMUONTriggerCircuit::GetY11Pos(Int_t localBoardId, Int_t istrip) const 
452 {
453 /// returns Y position of X strip istrip in MC11
454   return fYpos11[localBoardId][istrip];
455 }
456 //----------------------------------------------------------------------
457 Float_t AliMUONTriggerCircuit::GetY21Pos(Int_t localBoardId, Int_t istrip) const 
458 {
459 /// returns Y position of X strip istrip in MC21
460   return fYpos21[localBoardId][istrip];
461 }
462 //----------------------------------------------------------------------
463 Float_t AliMUONTriggerCircuit::GetZ11Pos(Int_t localBoardId, Int_t istrip) const 
464 {
465 /// returns Z position of X strip istrip in MC11
466   return fZpos11[localBoardId][istrip];
467 }
468 //----------------------------------------------------------------------
469 Float_t AliMUONTriggerCircuit::GetZ21Pos(Int_t localBoardId, Int_t istrip) const 
470 {
471 /// returns Z position of X strip istrip in MC21
472   return fZpos21[localBoardId][istrip];
473 }
474 Float_t AliMUONTriggerCircuit::GetX11Width(Int_t localBoardId, Int_t istrip) const 
475 {
476 /// returns width of Y strip istrip in MC11
477   return fXwidth11[localBoardId][istrip];
478 }
479 Float_t AliMUONTriggerCircuit::GetY11Width(Int_t localBoardId, Int_t istrip) const 
480 {
481 /// returns width of X strip istrip in MC11
482   return fYwidth11[localBoardId][istrip];
483 }
484 //----------------------------------------------------------------------
485 Float_t AliMUONTriggerCircuit::GetY21Width(Int_t localBoardId, Int_t istrip) const 
486 {
487 /// returns width of X strip istrip in MC21
488   return fYwidth21[localBoardId][istrip];
489 }
490
491 //----------------------------------------------------------------------
492 Int_t AliMUONTriggerCircuit::FirstStrip(AliMpLocalBoard* localBoard)
493 {
494 /// returns the first strip from mapping for board boardName
495 /// take care of special case for boards RC1L6B12 & LC1L6B12
496   Int_t iFirstStrip = -1;
497   Int_t boardNumber = atoi(localBoard->GetName()+6);
498
499   Int_t iline = AliMp::PairFirst(localBoard->GetPosition());
500   Int_t icol  = AliMp::PairSecond(localBoard->GetPosition());
501   if ( iline == 5 ) --icol;
502
503   switch (boardNumber)
504   {
505     case 12:
506       iFirstStrip = 0;
507       break;            
508     case 34:
509       iFirstStrip = 16;
510       break;            
511     case 56:
512       iFirstStrip = 32;
513       break;            
514     case 78:
515       iFirstStrip = 48;
516       break;            
517   }
518   if (icol == 1 && iline == 6) iFirstStrip += 16; // special case
519   return iFirstStrip;
520 }
521
522 //----------------------------------------------------------------------
523 Float_t AliMUONTriggerCircuit::PtCal(Int_t localBoardId, Int_t istripX, Int_t idev, Int_t istripY) const{
524 /// returns calculated pt for circuit/istripX/idev/istripY according 
525 /// to the formula of the TRD. Note : idev (input) is in [0+30]
526
527   //  Int_t jdev = idev - 15;        // jdev in [-15+15]
528   Int_t istripX2=istripX+idev+1; // find istripX2 using istripX and idev
529
530   Float_t yPosX1=fYpos11[localBoardId][istripX];
531   Float_t yPosX2=fYpos21[localBoardId][istripX2];
532   Float_t xPosY1=fXpos11[localBoardId][istripY];
533
534 // Z distance between IP and center of dipole
535   Float_t zf= TMath::Abs(0.5 *(AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ()));
536   Float_t z1=AliMUONConstants::DefaultChamberZ(10);
537   Float_t z2=AliMUONConstants::DefaultChamberZ(12);
538   Float_t thetaDev=(1./zf)*(yPosX1*z2-yPosX2*z1)/(z2-z1);
539   Float_t xf=xPosY1*zf/z1; 
540   Float_t yf=yPosX2-((yPosX2-yPosX1)*(z2-zf))/(z2-z1);
541   return (3.*0.3/TMath::Abs(thetaDev)) * TMath::Sqrt(xf*xf+yf*yf)/zf;
542 }