]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONSt345SlatSegmentation.cxx
Obsolete file (Ivana)
[u/mrichter/AliRoot.git] / MUON / AliMUONSt345SlatSegmentation.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 //  Segmentation classes for slat modules          
20 //  This class works with local coordinates
21 //  of the slats via the class AliMUONGeometrySegmentation
22 //  This class contains the size of the slats and the
23 //  and the differents PCB densities. 
24 //  (from old AliMUONSegmentationSlatModule)
25 //  Gines, Subatech, Nov04
26 //  Add electronics mapping
27 //  Christian, Subatech, Mai 05
28 //*********************************************************
29
30 #include <TArrayI.h>
31 #include <TArrayF.h>
32 #include "AliMUONSt345SlatSegmentation.h"
33 #include "AliMUONSegmentationDetectionElement.h"
34 #include "AliMUONSegmentManuIndex.h"
35 #include "AliMUONSegmentIndex.h"
36
37 #include "AliLog.h"
38
39 ClassImp(AliMUONSt345SlatSegmentation)
40
41
42 AliMUONSt345SlatSegmentation::AliMUONSt345SlatSegmentation() 
43   :     AliMUONVGeometryDESegmentation(),
44         fBending(0),
45         fId(0),
46         fNsec(0),
47         fNDiv(0),
48         fDpxD(0),
49         fDpyD(0),
50         fDpx(0),
51         fDpy(0),
52         fNpx(999999),
53         fNpy(999999),
54         fWireD(0.0),
55         fXhit(0.),
56         fYhit(0.),
57         fIx(0),
58         fIy(0),
59         fX(0.),
60         fY(0.),
61         fIxmin(0),
62         fIxmax(0),
63         fIymin(0),
64         fIymax(0),
65         fInitDone(kFALSE),
66         fSegmentationDetectionElement(0x0)
67 {
68   // default constructor
69
70 }
71
72 //___________________________________________
73 AliMUONSt345SlatSegmentation::AliMUONSt345SlatSegmentation(Bool_t bending) 
74   :     AliMUONVGeometryDESegmentation(),
75         fBending(bending),
76         fId(0),
77         fNsec(0),
78         fNDiv(0),
79         fDpxD(0),
80         fDpyD(0),
81         fDpx(0),
82         fDpy(0),
83         fNpx(999999),
84         fNpy(999999),
85         fWireD(0.25),
86         fXhit(0.),
87         fYhit(0.),
88         fIx(0),
89         fIy(0),
90         fX(0.),
91         fY(0.),
92         fIxmin(0),
93         fIxmax(0),
94         fIymin(0),
95         fIymax(0),
96         fInitDone(kFALSE),
97         fSegmentationDetectionElement(0x0)
98
99
100 {
101   // Non default constructor
102   fNsec = 4;  // 4 sector densities at most per slat 
103   fNDiv = new TArrayI(fNsec);      
104   fDpxD = new TArrayF(fNsec);      
105   fDpyD = new TArrayF(fNsec);      
106   (*fNDiv)[0]=(*fNDiv)[1]=(*fNDiv)[2]=(*fNDiv)[3]=0;     
107   (*fDpxD)[0]=(*fDpxD)[1]=(*fDpxD)[2]=(*fDpxD)[3]=0;       
108   (*fDpyD)[0]=(*fDpyD)[1]=(*fDpyD)[2]=(*fDpyD)[3]=0;   
109
110
111 }
112 //----------------------------------------------------------------------
113 AliMUONSt345SlatSegmentation::AliMUONSt345SlatSegmentation(const AliMUONSt345SlatSegmentation& rhs) 
114 :       AliMUONVGeometryDESegmentation(rhs),
115         fBending(0),
116         fId(0),
117         fDpx(0),
118         fDpy(0),
119         fNpx(999999),
120         fNpy(999999),
121         fWireD(0.25),
122         fXhit(0.),
123         fYhit(0.),
124         fIx(0),
125         fIy(0),
126         fX(0.),
127         fY(0.),
128         fIxmin(0),
129         fIxmax(0),
130         fIymin(0),
131         fIymax(0),
132         fSegmentationDetectionElement(0x0)
133 {
134   // default constructor
135 }
136 //----------------------------------------------------------------------
137 AliMUONSt345SlatSegmentation::~AliMUONSt345SlatSegmentation() 
138 {
139   // Destructor
140   if (fNDiv) delete fNDiv;
141   if (fDpxD) delete fDpxD;
142   if (fDpyD) delete fDpyD;
143   // if (fSegmentationDetectionElement) fSegmentationDetectionElement->Delete();
144 }
145 //----------------------------------------------------------------------
146 AliMUONSt345SlatSegmentation& AliMUONSt345SlatSegmentation::operator=(const AliMUONSt345SlatSegmentation& rhs)
147 {
148   // Protected assignement operator
149   if (this == &rhs) return *this;
150   AliFatal("Not implemented.");
151   return *this;  
152 }
153
154
155 //------------------------------------------------------------------------
156 Float_t AliMUONSt345SlatSegmentation::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t * /*dummy*/)
157 {
158   // Returns the square of the distance between 1 pad
159   // labelled by its Channel numbers and a coordinate
160   Float_t x,y;
161   GetPadC(iX,iY,x,y);
162   return (x-X)*(x-X) + (y-Y)*(y-Y);
163 }
164 //____________________________________________________________________________
165 Float_t AliMUONSt345SlatSegmentation::Dpx(Int_t isec) const
166 {
167   // Return x-strip width
168   return (*fDpxD)[isec];
169
170
171 //____________________________________________________________________________
172 Float_t AliMUONSt345SlatSegmentation::Dpy(Int_t  isec) const
173 {
174   // Return y-strip width
175   return (*fDpyD)[isec];
176 }
177 //_____________________________________________________________________________
178 Float_t AliMUONSt345SlatSegmentation::GetAnod(Float_t xhit) const
179 {
180   // Returns for a hit position xhit the position of the nearest anode wire    
181   Float_t wire= (xhit>0)? Int_t(xhit/fWireD)+0.5:Int_t(xhit/fWireD)-0.5;
182   return fWireD*wire;
183 }
184
185
186
187 //--------------------------------------------------------------------------------
188 void AliMUONSt345SlatSegmentation::GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y) 
189 {
190   if (ix < 1 || ix > Npx() || iy < 1 || iy > Npy() ){
191     AliWarning(Form("ix %d or iy %d out of boundaries: Npx=%d and Npy=%d",ix, iy, Npx(), Npy()));
192     x=-99999.; y=-99999.;
193
194   } else { 
195
196     //  Returns real coordinates (x,y) for given pad coordinates (ix,iy)
197     //  Find sector isec
198     Int_t isec = Sector(ix,iy);
199     if (isec == -1) AliWarning(Form("isector = %d  with ix %d, iy %d", isec, ix, iy));
200     if (iy > fNpyS[isec]) {
201       x=-99999.; y=-99999.;
202       return;
203     }
204     if (isec>0) {
205       x = fCx[isec-1]+(ix-fNpxS[isec-1])*(*fDpxD)[isec];
206       x = x-(*fDpxD)[isec]/2;
207       y = Float_t(iy*(*fDpyD)[isec])-(*fDpyD)[isec]/2.- fCy;  // !!!  
208     } else {
209       x = y = 0;
210     }
211   }
212 }
213
214
215 //_____________________________________________________________________________
216 void AliMUONSt345SlatSegmentation::GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy) 
217 {
218 //  Returns pad coordinates (ix,iy) for given real coordinates (x,y)
219
220   //  Find sector isec    
221   Int_t isec=-1;
222   for (Int_t i=fNsec-1; i > 0; i--) {
223     if (x >= fCx[i-1]) {
224       isec=i;
225       if (fCx[isec] == fCx[isec-1]  && isec > 1) isec--;
226       break;
227     }
228   }
229   if (isec == -1) AliWarning(Form("isector equal to %d  with xl %f, yl %f", isec, x, y));
230   if (isec>0) {
231     ix= Int_t((x-fCx[isec-1])/(*fDpxD)[isec])
232       +fNpxS[isec-1]+1;
233     iy= Int_t((y+fCy)/(*fDpyD)[isec])+1;
234   } else if (isec == 0) {
235     ix= Int_t(x/(*fDpxD)[isec])+1;
236     iy= Int_t((y+fCy)/(*fDpyD)[isec])+1;
237   } else {
238     ix=0;
239     iy=0;
240   }
241 }
242 //-------------------------------------------------------------------------
243 void AliMUONSt345SlatSegmentation::GetPadI(Float_t x, Float_t y , Float_t /*z*/, Int_t &ix, Int_t &iy)
244 {
245   GetPadI(x, y, ix, iy);
246 }
247
248 //-------------------------------------------------------------------------
249 void AliMUONSt345SlatSegmentation::GetPadE(Int_t &ix, Int_t &iy,  AliMUONSegmentManuIndex* manuIndex)
250 {
251   //
252   // return Padx and Pady
253   // input value: electronic connection number
254
255   Int_t icathode = (fBending == 1) ? 0 : 1; // cathode 0 == bending
256
257   //  Int_t busPatchId     = manuIndex->GetBusPatchId(); //
258   Int_t manuId         = manuIndex->GetManuId();
259   Int_t manuChannelId  = manuIndex->GetManuChannelId();
260   //  Int_t channelId      = manuIndex->GetChannelId();
261
262   AliMUONSegmentIndex* index = fSegmentationDetectionElement->GetIndex(manuId,  manuChannelId);
263
264   ix = index->GetPadX();
265   iy = index->GetPadY();
266   swap(ix,iy); // swap cos origin in segmentation and mapping file are different for iy (temporary solution)
267
268   if (index->GetCathode() != icathode)
269     AliWarning("Wrong cathode number !");
270
271 }
272
273 //-------------------------------------------------------------------------
274  AliMUONSegmentManuIndex* AliMUONSt345SlatSegmentation::GetMpConnection(Int_t ix, Int_t iy)
275 {
276   //
277   // return electronic connection number
278   // input value: Padx and Pady
279
280   Int_t icathode = (fBending == 1) ? 0 : 1; // cathode 0 == bending
281
282   return fSegmentationDetectionElement->GetManuIndex(ix, iy, icathode);
283   
284 }
285
286 //_______________________________________________________________
287 void AliMUONSt345SlatSegmentation::SetPadDivision(Int_t ndiv[4])
288 {
289   // Defines the pad size perp. to the anode wire (y) for different sectors. 
290   // Pad sizes are defined as integral fractions ndiv of a basis pad size
291   // fDpx
292   // 
293   for (Int_t i=0; i<4; i++) {
294     (*fNDiv)[i]=ndiv[i];
295   }
296   ndiv[0]=ndiv[1];
297 }
298 //____________________________________________________________________________
299 void AliMUONSt345SlatSegmentation::SetPadSize(Float_t p1, Float_t p2)
300 {
301   //  Sets the padsize 
302   fDpx=p1;
303   fDpy=p2;
304 }
305 //_______________________________________________________________          
306 void AliMUONSt345SlatSegmentation::SetPcbBoards(Int_t n[4])
307 {
308   //
309   // Set PcbBoard segmentation zones for each density
310   // n[0] slat type parameter
311   // n[1] PcbBoards for highest density sector fNDiv[1] etc ...
312
313   fRtype = n[0];
314   n[0] = 0;
315   for (Int_t i=0; i<4; i++) fPcbBoards[i]=n[i];
316
317 }
318 //-------------------------------------------------------------------------
319 void AliMUONSt345SlatSegmentation::SetPad(Int_t ix, Int_t iy)
320 {
321   //
322   // Sets virtual pad coordinates, needed for evaluating pad response 
323   // outside the tracking program 
324   GetPadC(ix,iy,fX,fY);
325   fSector=Sector(ix,iy);
326 }
327 //---------------------------------------------------------------------------
328 void AliMUONSt345SlatSegmentation::SetHit(Float_t x, Float_t y)
329 {
330   // Set current hit 
331   //
332   fXhit = x;
333   fYhit = y;
334     
335   if (x <  fCx[0])    fXhit = fCx[0];
336   if (y < -fDyPCB/2.) fYhit = -fDyPCB/2.;
337     
338   if (x > fCx[fNsec-1]) fXhit = fCx[fNsec-1];
339   if (y > fDyPCB/2.)    fYhit = fDyPCB/2.;
340     
341 }
342 //----------------------------------------------------------------------------
343 void AliMUONSt345SlatSegmentation::SetHit(Float_t xhit, Float_t yhit, Float_t /*zhit*/)
344 {
345   SetHit(xhit, yhit);
346 }
347
348 //----------------------------------------------------------
349 void AliMUONSt345SlatSegmentation::FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
350 {
351 // Initialises iteration over pads for charge distribution algorithm
352 //
353     //
354     // Find the wire position (center of charge distribution)
355     Float_t x0a = GetAnod(xhit);
356     fXhit = x0a;
357     fYhit = yhit;
358     //
359     // and take fNsigma*sigma around this center
360     Float_t x01 = x0a  - dx ;
361     Float_t x02 = x0a  + dx;
362     Float_t y01 = yhit - dy;
363     Float_t y02 = yhit + dy;
364
365     // check the limits after adding (fNsigma*sigma)
366     if (x01 <  fCx[0])   x01 =  fCx[0];
367     if (y01 < -fDyPCB/2) y01 = -fDyPCB/2;
368
369     if (x02 >= fCx[fNsec-1]) x02 = fCx[fNsec-1]; // still ok ? (CF)
370
371    
372     Int_t isec=-1;
373     for (Int_t i=fNsec-1; i > 0; i--) {
374       if (x02 >= fCx[i-1]) {
375         isec=i;
376         if (fCx[isec] == fCx[isec-1] && isec > 1) isec--;
377         break;
378       }
379     }
380
381     y02 += Dpy(isec);// why ? (CF)
382     if (y02 >= fDyPCB/2.) y02 = fDyPCB/2;
383    
384     //
385     // find the pads over which the charge distributes
386     GetPadI(x01,y01,fIxmin,fIymin);
387     GetPadI(x02,y02,fIxmax,fIymax);
388     
389     if (fIxmax > fNpx) fIxmax=fNpx;
390     if (fIymax > fNpyS[isec]) fIymax = fNpyS[isec];    
391     if (fIxmin < 1) fIxmin = 1;    // patch for the moment (Ch. Finck)
392     if (fIymin < 1) fIymin = 1;    
393
394     fXmin = x01;
395     fXmax = x02;    
396     fYmin = y01;
397     fYmax = y02;    
398   
399     // 
400     // Set current pad to lower left corner
401     if (fIxmax < fIxmin) fIxmax = fIxmin;
402     if (fIymax < fIymin) fIymax = fIymin;    
403     fIx = fIxmin;
404     fIy = fIymin;
405     
406     GetPadC(fIx,fIy,fX,fY);
407     fSector = Sector(fIx,fIy);
408 /*
409     printf("\n \n First Pad: %d %d %f %f %d %d %d %f" , 
410            fIxmin, fIxmax, fXmin, fXmax, fNpx, fId, isec, Dpy(isec));    
411     printf("\n \n First Pad: %d %d %f %f %d %d %d %f",
412            fIymin, fIymax, fYmin, fYmax,  fNpyS[isec], fId, isec, Dpy(isec));
413 */
414 }
415
416
417
418 //----------------------------------------------------------------------
419 void AliMUONSt345SlatSegmentation::FirstPad(Float_t xhit, Float_t yhit, Float_t /*zhit*/, Float_t dx, Float_t dy)
420 {
421   FirstPad(xhit, yhit, dx, dy);
422 }
423 //----------------------------------------------------------------------
424 void AliMUONSt345SlatSegmentation::NextPad()
425 {
426   // Stepper for the iteration over pads
427   //
428   // Step to next pad in the integration region
429   //  step from left to right    
430   if (fIx != fIxmax) {
431     fIx++;
432     GetPadC(fIx,fIy,fX,fY);
433     fSector=Sector(fIx,fIy);
434     //  step up 
435   } else if (fIy != fIymax) {
436     fIx=fIxmin;
437     fIy++;
438     GetPadC(fIx,fIy,fX,fY);
439     fSector=Sector(fIx,fIy);
440
441   } else {
442     fIx=-999;
443     fIy=-999;
444   }
445 }
446 //-------------------------------------------------------------------------
447 Int_t AliMUONSt345SlatSegmentation::MorePads()
448 {
449   // Stopping condition for the iterator over pads
450   //
451   // Are there more pads in the integration region
452     
453   return  (fIx != -999  || fIy != -999);
454 }
455 //--------------------------------------------------------------------------
456 Int_t AliMUONSt345SlatSegmentation::Sector(Int_t ix, Int_t iy) 
457 {
458   //
459   // Determine segmentation zone from pad coordinates
460   //
461   Int_t isec = -1;
462   for (Int_t i = 0; i < fNsec; i++) {
463     if (ix <= fNpxS[i]) {
464       isec = i;
465       break;
466     }
467   }
468   if (isec == -1) AliWarning(Form("Sector = %d  with ix %d and iy %d, Npx %d",
469                                   isec, ix, iy, fNpx));
470
471   return isec;
472
473 }
474 //-----------------------------------------------------------------------------
475 void AliMUONSt345SlatSegmentation::
476 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2) 
477 {
478   //  Returns integration limits for current pad
479   //
480   x1=fXhit-fX-Dpx(fSector)/2.;
481   x2=x1+Dpx(fSector);
482   y1=fYhit-fY-Dpy(fSector)/2.;
483   y2=y1+Dpy(fSector);    
484   //  printf("\n Integration Limits %f %f %f %f %d %f", x1, x2, y1, y2, fSector, Dpx(fSector));
485
486 }
487 //-----------------------------------------------------------------------------
488 void AliMUONSt345SlatSegmentation::
489 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10]) 
490 {
491   // Returns list of next neighbours for given Pad (iX, iY)
492   Int_t i=0;
493   //  step right
494   if (iX+1 <= fNpx) {
495     Xlist[i]=iX+1;
496     Ylist[i++]=iY;
497   }
498   //  step left    
499   if (iX-1 > 0) {
500     Xlist[i]=iX-1;
501     Ylist[i++]=iY;
502   } 
503   Int_t sector = Sector(iX,iY);
504   //  step up
505   if (iY+1 <= fNpyS[sector]) {
506     Xlist[i]=iX;
507     Ylist[i++]=iY+1;
508   }
509   //  step down    
510   if (iY-1 > 0) {
511     Xlist[i]=iX;
512     Ylist[i++]=iY-1;
513   }
514   *Nlist=i;
515 }
516
517 //--------------------------------------------------------------------------
518 void AliMUONSt345SlatSegmentation::Init(Int_t detectionElementId)
519 {
520   //
521   //  Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
522   //  These arrays help in converting from real to pad co-ordinates and
523   //  vice versa
524   //   
525   //  Segmentation is defined by rectangular modules approximating
526   //  concentric circles as shown below
527   //
528   //  PCB module size in cm
529   //  printf("\n Initialise Segmentation SlatModule \n");
530
531   
532   //  printf(" fBending: %d \n",fBending);
533
534   if (fInitDone) return; // security if init is already done in AliMUONFactory
535   fDxPCB=40;
536   fDyPCB=40;
537
538   //  Calculate padsize along x
539   (*fDpxD)[fNsec-1]=fDpx;
540   (*fDpyD)[fNsec-1]=fDpy;
541   if (fNsec > 1) {
542     for (Int_t i=fNsec-1; i>=0; i--){ // fNsec-2
543       if (!fBending) {
544         (*fDpxD)[i]=fDpx;
545         (*fDpyD)[i]=(*fDpyD)[fNsec-1]/(*fNDiv)[i];
546       } else {
547         (*fDpxD)[i]=(*fDpxD)[fNsec-1]/(*fNDiv)[i];
548         (*fDpyD)[i]=fDpy;
549       }
550     }
551   }
552   //
553   // fill the arrays defining the pad segmentation boundaries
554   //
555   //  
556   //  Loop over sectors (isec=0 for secto close to the beam pipe)
557   Float_t totalLength = 0;
558   for (Int_t isec=0; isec<4; isec++) totalLength += fPcbBoards[isec]*fDxPCB;  // !!!!
559
560   fNpy = 0;   // maximum number of pads in y
561   for (Int_t isec=0; isec<4; isec++) {
562     if (isec==0) {
563       fNpxS[0] = 0;
564       fNpyS[0] = 0;
565       fCx[0]   = -totalLength/2;
566     } else {
567       fNpxS[isec] = fNpxS[isec-1] + fPcbBoards[isec]*Int_t(fDxPCB/(*fDpxD)[isec]); 
568       fNpyS[isec] = Int_t(fDyPCB/(*fDpyD)[isec]);
569       if (fNpyS[isec] >= fNpy) fNpy = fNpyS[isec]; 
570       fCx[isec]= fCx[isec-1] + fPcbBoards[isec]*fDxPCB;
571     }
572   } // sectors
573
574   fNpx = fNpxS[3];  // maximum number of pads in x
575   fCy = fDyPCB/2.;
576   //
577   fId = detectionElementId;
578
579   //
580   // initalize mapping
581   //
582 //   Int_t icathode = (fBending == 1) ? 0 : 1; // cathode 0 == bending
583 //   Char_t name[15];
584 //   GetMpFileName(name);
585 //   fSegmentationDetectionElement = new AliMUONSegmentationDetectionElement();
586 //   fSegmentationDetectionElement->Init(name, icathode);
587   fInitDone = kTRUE;
588 }
589
590 //--------------------------------------------------------------------------
591 void AliMUONSt345SlatSegmentation::GetMpFileName(Char_t* name) const
592 {
593   //
594   // Get mapping file name
595   //
596
597    strcpy(name,"slat");
598
599    for (Int_t isec = 1; isec < 4; isec++) {
600
601      switch(isec) {
602      case 1:
603        for (Int_t i = 0; i < fPcbBoards[isec]; i++)
604          strcat(name,"1");
605        break;
606      case 2 :
607        for (Int_t i = 0; i < fPcbBoards[isec]; i++)
608          strcat(name,"2");
609        break;
610      case 3:
611        for (Int_t i = 0; i < fPcbBoards[isec]; i++)
612          strcat(name,"3");
613        break;
614      }
615    }
616
617    while (strlen(name) < 10)
618      strcat(name,"0");
619    
620    switch(fRtype) {
621    case 0:
622      strcat(name, "N");
623      break;
624    case 1:
625      strcat(name, "NR1");
626      break;
627    case 2:
628      strcat(name, "NR2");
629      break;
630    case 3:
631      strcat(name, "NR3");
632      break;
633    case 4:
634      strcat(name, "S");
635      break;
636    case -1:
637      strcat(name, "SR1");
638      break;
639    case -2:
640      strcat(name, "SR2");
641      break;
642    case -3:
643      strcat(name, "SR3"); // should not exist
644      AliFatal("SR3 Slat type does not exist !!");
645      break;
646    }
647 }
648
649 //--------------------------------------------------------------------------
650 void AliMUONSt345SlatSegmentation::Swap(Int_t padX, Int_t &padY)
651 {
652
653   // swap the numbering between segmentation (i.e. pady = [0,40]) 
654   // and mapping file  (i.e. pady = [-20,20]) 
655
656
657   if (fBending == 1) {
658     if (padY < 0) 
659       padY += fNpy + 1; 
660     else
661       padY += fNpy; 
662   }
663
664
665   if (fBending == 0) {
666     if (padY < 0) 
667       padY += fNpyS[Sector(padX, padY)] + 1; 
668     else
669       padY += fNpyS[Sector(padX, padY)]; 
670   }
671
672 }
673
674