]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTriggerCircuit.cxx
a565c6c7adddd70fbdeed7e1287d206600195f28
[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 $Log$
17 Revision 1.9  2002/10/23 07:24:56  alibrary
18 Introducing Riostream.h
19
20 Revision 1.8  2001/03/20 13:32:37  egangler
21 includes cleanup
22
23 Revision 1.7  2000/10/02 16:58:29  egangler
24 Cleaning of the code :
25 -> coding conventions
26 -> void Streamers
27 -> some useless includes removed or replaced by "class" statement
28
29 Revision 1.6  2000/07/13 16:19:44  fca
30 Mainly coding conventions + some small bug fixes
31
32 Revision 1.5  2000/07/03 11:54:57  morsch
33 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
34 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
35
36 Revision 1.4  2000/06/28 15:16:35  morsch
37 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
38 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
39 framework. The changes should have no side effects (mostly dummy arguments).
40 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
41 of chambers with overlapping modules (MakePadHits, Disintegration).
42
43 Revision 1.3  2000/06/26 10:04:49  pcrochet
44 problem with HP compiler solved (PH), static variables removed : now defined in AliMUONTriggerConstants
45
46 */
47
48 #include "AliRun.h"
49 #include "AliMUON.h"
50 #include "AliMUONTriggerCircuit.h"
51 #include "AliMUONTriggerConstants.h"
52 #include "AliSegmentation.h"
53 #include "AliMUONResponse.h"
54 #include "AliMUONChamber.h"
55 #include "TMath.h"
56 #include "Riostream.h"
57
58 ClassImp(AliMUONTriggerCircuit)
59
60 //----------------------------------------------------------------------
61 AliMUONTriggerCircuit::AliMUONTriggerCircuit() 
62 {
63 // Constructor
64   fSegmentation=0;
65   fIdCircuit=0;
66   fX2m=0;
67   fX2ud=0;
68   fOrMud[0]=fOrMud[1]=0;
69   Int_t i;  
70   for (i=0; i<4; i++) {
71     for (Int_t j=0; j<32; j++) {      
72       fXcode[i][j]=0;
73       fYcode[i][j]=0;
74     }
75   }
76   for (i=0; i<16; i++) { fXpos11[i]=0.; }
77   for (i=0; i<31; i++) { fYpos11[i]=0.; }
78   for (i=0; i<63; i++) { fYpos21[i]=0.; }
79 }
80
81 //----------------------------------------------------------------------
82 AliMUONTriggerCircuit::AliMUONTriggerCircuit(const AliMUONTriggerCircuit& MUONTriggerCircuit)
83 {
84 // Dummy copy constructor
85 }
86
87 //----------------------------------------------------------------------
88 AliMUONTriggerCircuit & AliMUONTriggerCircuit::operator=(const AliMUONTriggerCircuit& MUONTriggerCircuit)
89 {
90 // Dummy assignment operator
91     return *this;
92 }
93
94 //----------------------------------------------------------------------
95 void AliMUONTriggerCircuit::Init(Int_t iCircuit) {
96 // initialize circuit characteristics
97   fIdCircuit=AliMUONTriggerConstants::CircuitId(iCircuit);
98   LoadX2();
99   LoadXCode();
100   LoadYCode();
101   LoadXPos();
102   LoadYPos();
103 }
104
105 //----------------------------------------------------------------------
106 Int_t AliMUONTriggerCircuit::CircuitNumber(Int_t idCircuit){
107 // returns circuit number iCircuit (0-234) corresponding to circuit idCircuit
108   Int_t iCircuit=0;
109   for (Int_t i=0; i<234; i++) {
110     if (AliMUONTriggerConstants::CircuitId(i)==idCircuit) {
111       iCircuit=i;
112       break;
113     }
114   }
115   return iCircuit;
116 }
117 //----------------------------------------------------------------------
118 Int_t AliMUONTriggerCircuit::ModuleNumber(Int_t idModule){
119 // returns module number imod (from 0 to 63) corresponding to module idmodule
120   Int_t absidModule=TMath::Abs(idModule);
121   Int_t iModule=0;
122   for (Int_t i=0; i<63; i++) {
123     if (AliMUONTriggerConstants::ModuleId(i)==absidModule) { 
124       iModule=i;
125       break;
126     }
127   }
128   return iModule;
129 }
130
131 //----------------------------------------------------------------------
132 Int_t AliMUONTriggerCircuit::Module(Int_t idCircuit) {
133 // returns ModuleId where Circuit idCircuit is sitting
134   return Int_t(idCircuit/10);
135 }
136 //----------------------------------------------------------------------
137 Int_t AliMUONTriggerCircuit::Position(Int_t idCircuit) {
138 // returns position of idCircuit in correcponding Module
139   return TMath::Abs(idCircuit)-TMath::Abs(Module(idCircuit))*10;
140 }
141
142 //----------------------------------------------------------------------
143 void AliMUONTriggerCircuit::LoadX2() {
144 // initialize fX2m, fX2ud and fOrMud
145   
146   Int_t idModule=Module(fIdCircuit);        // corresponding module Id.
147 // and its number of X strips
148   Int_t nStrX=AliMUONTriggerConstants::NstripX(ModuleNumber(idModule)); 
149 // and its number of Y strips
150   Int_t nStrY=AliMUONTriggerConstants::NstripY(ModuleNumber(idModule)); 
151   Int_t iPosCircuit=Position(fIdCircuit); // position of circuit in module
152   
153 // first step : look at lower part 
154   if (iPosCircuit==1) {               // need to scan lower module       
155     if(idModule<91&&TMath::Abs(idModule)!=41&&idModule>-91) { 
156       fOrMud[0]=1;
157       Int_t idModuleD=(TMath::Abs(idModule)+10)*(TMath::Abs(idModule)/idModule); 
158       Int_t nStrD=AliMUONTriggerConstants::NstripY(ModuleNumber(idModuleD));
159       
160       if (nStrY!=nStrD    
161           &&TMath::Abs(idModule)!=42&&TMath::Abs(idModule)!=52) {   
162         if (nStrY==8) fX2m=1; 
163         if (nStrD==8) fX2ud=1; 
164       }      
165     }      
166
167   } else {                         // lower strips within same module       
168     fOrMud[0]=0;
169   }    
170   
171 // second step : look at upper part
172   if ((iPosCircuit==1&&nStrX==16)||(iPosCircuit==2&&nStrX==32)|| 
173       (iPosCircuit==3&&nStrX==48)||(iPosCircuit==4&&nStrX==64)) {   
174     if ((idModule>17||idModule<-17)&&TMath::Abs(idModule)!=61) {  
175       fOrMud[1]=1;
176       Int_t idModuleU=(TMath::Abs(idModule)-10)*(TMath::Abs(idModule)/idModule); 
177       Int_t nStrU=AliMUONTriggerConstants::NstripY(ModuleNumber(idModuleU)); 
178
179       if (nStrY!=nStrU    
180           &&TMath::Abs(idModule)!=62&&TMath::Abs(idModule)!=52) {   
181         if (nStrY==8) fX2m=1; 
182         if (nStrU==8) fX2ud=1;
183       }      
184     }     
185     
186   } else {                       // upper strips within same module       
187     fOrMud[1]=0;
188   }
189 }  
190
191 //----------------------------------------------------------------------
192 void AliMUONTriggerCircuit::LoadXCode(){
193 // assign a Id. number to each X strip of current circuit 
194 // Id.=(corresponding module Id.)*100+(Id. strip of module)
195
196 // first part : fill XMC11 XMC12 and strips 8 to 24 (middle) XMC21 XMC22
197   Int_t iStripCircMT1=0, iStripCircMT2=8;
198   Int_t idModule=Module(fIdCircuit);        // corresponding module Id.
199 // and its number of strips
200   Int_t nStrX=AliMUONTriggerConstants::NstripX(ModuleNumber(idModule)); 
201   Int_t iPosCircuit=Position(fIdCircuit);   // position of circuit in module  
202   Int_t sign=TMath::Abs(idModule)/idModule; // left or right 
203   Int_t istrip;
204
205   for (istrip=(iPosCircuit-1)*16; 
206        istrip<(iPosCircuit-1)*16+16; istrip++) {
207         
208     fXcode[0][iStripCircMT1]=sign*(TMath::Abs(idModule)*100+istrip); 
209     fXcode[1][iStripCircMT1]=sign*(TMath::Abs(idModule)*100+istrip); 
210     fXcode[2][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip); 
211     fXcode[3][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip);     
212     iStripCircMT1++;
213     iStripCircMT2++;
214   }
215
216 // second part 
217 // XMC21 XMC22 strips 0 to 7 and 24 to 31 
218   Int_t idModuleD, idModuleU;
219   Int_t nStrD, nStrU;
220
221   idModule=Module(fIdCircuit); // corresponding module Id.
222 // number of X strips
223   nStrX=AliMUONTriggerConstants::NstripX(ModuleNumber(idModule));  
224   sign=TMath::Abs(idModule)/idModule;
225
226 // fill lower part (0 to 7)
227   if (iPosCircuit==1) {                 // need to scan lower module 
228     if(idModule<91&&TMath::Abs(idModule)!=41&&idModule>-91) { // non-existing
229       idModuleD=sign*(TMath::Abs(idModule)+10);  // lower module Id
230 // and its number of strips
231       nStrD=AliMUONTriggerConstants::NstripX(ModuleNumber(idModuleD)); 
232       
233       iStripCircMT2=0;
234       for (istrip=nStrD-8; istrip<nStrD; istrip++) {  
235         fXcode[2][iStripCircMT2]=sign*(TMath::Abs(idModuleD)*100+istrip); 
236         fXcode[3][iStripCircMT2]=sign*(TMath::Abs(idModuleD)*100+istrip); 
237         iStripCircMT2++;
238       }
239     }
240      
241   } else {                       // lower strips within same module 
242     
243     iStripCircMT2=0;
244     for (istrip=(iPosCircuit-1)*16-8; 
245          istrip<(iPosCircuit-1)*16; istrip++) {  
246       fXcode[2][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip); 
247       fXcode[3][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip); 
248       iStripCircMT2++;
249     }
250   }
251   
252 // fill upper part (24 to 31)
253   if ((iPosCircuit==1&&nStrX==16)||(iPosCircuit==2&&nStrX==32)|| 
254       (iPosCircuit==3&&nStrX==48)||(iPosCircuit==4&&nStrX==64)) {   
255     if ((idModule>17||idModule<-17)&&TMath::Abs(idModule)!=61) {  
256       idModuleU=sign*(TMath::Abs(idModule)-10);  // upper module Id
257 // and its number of strips
258       nStrU=AliMUONTriggerConstants::NstripX(ModuleNumber(idModuleU)); 
259       
260       iStripCircMT2=24;
261       for (istrip=0; istrip<8; istrip++) {        
262         fXcode[2][iStripCircMT2]=sign*(TMath::Abs(idModuleU)*100+istrip); 
263         fXcode[3][iStripCircMT2]=sign*(TMath::Abs(idModuleU)*100+istrip); 
264         iStripCircMT2++;
265       }
266     }
267     
268   } else if ((iPosCircuit==1&&nStrX>16)||(iPosCircuit==2&&nStrX>32)|| 
269              (iPosCircuit==3&&nStrX>48)) { // upper strips within same mod. 
270     
271     iStripCircMT2=24;
272     for (istrip=(iPosCircuit-1)*16+16; 
273          istrip<(iPosCircuit-1)*16+24; istrip++) {  
274       fXcode[2][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip); 
275       fXcode[3][iStripCircMT2]=sign*(TMath::Abs(idModule)*100+istrip); 
276       iStripCircMT2++;
277     }   
278   }
279 }
280
281 //----------------------------------------------------------------------
282 void AliMUONTriggerCircuit::LoadYCode(){
283 // assign a Id. number to each Y strip of current circuit 
284 // Id.=(corresponding module Id.)*100+(Id. strip of module)
285 // note : for Y plane fill only "central part" of circuit
286 // (upper and lower parts are filled in PreHandlingY of AliMUONTriggerDecision)
287     
288   Int_t idModule=Module(fIdCircuit);        // corresponding module Id.
289 // and its number of Y strips
290   Int_t nStrY=AliMUONTriggerConstants::NstripY(ModuleNumber(idModule)); 
291   Int_t sign=TMath::Abs(idModule)/idModule; // left or right 
292
293   for (Int_t istrip=0; istrip<nStrY; istrip++) {
294     fYcode[0][istrip]=sign*(TMath::Abs(idModule)*100+istrip); 
295     fYcode[1][istrip]=sign*(TMath::Abs(idModule)*100+istrip); 
296     fYcode[2][istrip]=sign*(TMath::Abs(idModule)*100+istrip); 
297     fYcode[3][istrip]=sign*(TMath::Abs(idModule)*100+istrip); 
298   }
299 }
300
301 //----------------------------------------------------------------------
302 void AliMUONTriggerCircuit::LoadYPos(){
303 // fill fYpos11 and fYpos21 -> y position of X declusterized strips
304
305   Int_t chamber, cathode;
306   Int_t code, idModule, idStrip, idSector;
307   Float_t x, y, z, width;
308   Int_t istrip;
309
310   AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");  
311   AliMUONChamber*  iChamber;
312   AliSegmentation*  segmentation;    
313
314 // first plane (11)
315   chamber=11;
316   cathode=1;
317   iChamber = &(pMUON->Chamber(chamber-1));
318   segmentation=iChamber->SegmentationModel(cathode);
319   
320   for (istrip=0; istrip<16; istrip++) {
321     code=fXcode[0][istrip];           // decode current strip
322     idModule=Int_t(code/100);           // corresponding module Id.
323     idStrip=TMath::Abs(code-idModule*100); // corresp. strip number in module
324     idSector=segmentation->Sector(idModule,idStrip); // corresponding sector
325     width=segmentation->Dpy(idSector);      // corresponding strip width
326     segmentation->GetPadC(idModule,idStrip,x,y,z); // get strip real position
327     
328     fYpos11[2*istrip]=y;
329     if (istrip!=15) fYpos11[2*istrip+1]=y+width/2.;
330   }   
331    
332 // second plane (21)
333   chamber=13;
334   cathode=1;
335   iChamber = &(pMUON->Chamber(chamber-1));
336   segmentation=iChamber->SegmentationModel(cathode);
337   
338   for (istrip=0; istrip<32; istrip++) {
339     code=fXcode[2][istrip];    // decode current strip
340     idModule=Int_t(code/100);           // corresponding module Id.
341     idStrip=TMath::Abs(code-idModule*100); // corresp. strip number in module
342     idSector=segmentation->Sector(idModule,idStrip); // corresponding sector
343     width=segmentation->Dpy(idSector);      // corresponding strip width
344     segmentation->GetPadC(idModule,idStrip,x,y,z); // get strip real position
345     
346 // using idModule!=0 prevents to fill garbage in case of circuits 
347 // in the first and last rows 
348     if (idModule!=0) { 
349       fYpos21[2*istrip]=y;
350       if (istrip!=31) fYpos21[2*istrip+1]=y+width/2.;
351     }
352   }   
353 }
354
355 //----------------------------------------------------------------------
356 void AliMUONTriggerCircuit::LoadXPos(){
357 // fill fXpos11 -> x position of Y strips for the first plane only
358 // fXpos11 contains the x position of Y strip for the current circuit
359 // taking into account whether or nor not part(s) of the circuit
360 // (middle, up or down) has(have) 16 strips
361   
362   Float_t x, y, z;
363   Int_t istrip;  
364
365   Int_t chamber=11;
366   Int_t cathode=2;
367   AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");  
368   AliMUONChamber*  iChamber;
369   AliSegmentation*  segmentation; 
370   iChamber = &(pMUON->Chamber(chamber-1));
371   segmentation=iChamber->SegmentationModel(cathode);
372   
373   Int_t idModule=Module(fIdCircuit);        // corresponding module Id.  
374 // number of Y strips
375   Int_t nStrY=AliMUONTriggerConstants::NstripY(ModuleNumber(idModule)); 
376   Int_t idSector=segmentation->Sector(idModule,0); // corresp. sector
377   Float_t width=segmentation->Dpx(idSector);      // corresponding strip width
378   
379 // first case : up middle and down parts have all 8 or 16 strip 
380   if ((nStrY==16)||(nStrY==8&&fX2m==0&&fX2ud==0)) { 
381     for (istrip=0; istrip<nStrY; istrip++) {
382       segmentation->GetPadC(idModule,istrip,x,y,z); 
383       fXpos11[istrip]=x;
384     }
385 // second case : mixing 8 and 16 strips within same circuit      
386   } else {
387     for (istrip=0; istrip<nStrY; istrip++) {
388       if (nStrY!=8) { printf(" bug in LoadXpos \n");}
389       segmentation->GetPadC(idModule,istrip,x,y,z); 
390       fXpos11[2*istrip]=x-width/4.;
391       fXpos11[2*istrip+1]=fXpos11[2*istrip]+width/2.;
392     }
393   }   
394 }
395
396 //----------------------------------------------------------------------
397 Float_t AliMUONTriggerCircuit::PtCal(Int_t istripX, Int_t idev, Int_t istripY){
398 // returns calculated pt for circuit/istripX/idev/istripY according 
399 // to the formula of the TRD. Note : idev (input) is in [0+30]
400
401   //  Int_t jdev = idev - 15;        // jdev in [-15+15]
402   Int_t istripX2=istripX+idev+1; // find istripX2 using istripX and idev
403
404   Float_t yPosX1=fYpos11[istripX];
405   Float_t yPosX2=fYpos21[istripX2];
406   Float_t xPosY1=fXpos11[istripY];
407   
408   Float_t zf=975., z1=1603.5, z2=1703.5;
409   Float_t thetaDev=(1./zf)*(yPosX1*z2-yPosX2*z1)/(z2-z1);
410   Float_t xf=xPosY1*zf/z1; 
411   Float_t yf=yPosX2-((yPosX2-yPosX1)*(z2-zf))/(z2-z1);
412   return (3.*0.3/TMath::Abs(thetaDev)) * TMath::Sqrt(xf*xf+yf*yf)/zf;
413 }
414
415 //----------------------------------------------------------------------
416 //--- methods which return member data related info
417 //----------------------------------------------------------------------
418 Int_t AliMUONTriggerCircuit::GetIdCircuit(){ 
419 // returns circuit Id
420   return fIdCircuit;
421 }
422 //----------------------------------------------------------------------
423 Int_t AliMUONTriggerCircuit::GetIdModule(){ 
424 // returns module Id
425   return Module(fIdCircuit);
426 }
427 //----------------------------------------------------------------------
428 Int_t AliMUONTriggerCircuit::GetNstripX() { 
429 // returns the number of X strips in the module where the circuit is sitting
430   return AliMUONTriggerConstants::NstripX(ModuleNumber(Module(fIdCircuit)));
431 }
432 //----------------------------------------------------------------------
433 Int_t AliMUONTriggerCircuit::GetNstripY() { 
434 // returns the number of Y strips in the module where the circuit is sitting
435   return AliMUONTriggerConstants::NstripY(ModuleNumber(Module(fIdCircuit)));
436 }
437 //----------------------------------------------------------------------
438 Int_t AliMUONTriggerCircuit::GetPosCircuit() { 
439 // returns the position of the circuit in its module
440   return Position(fIdCircuit);
441 }
442 //----------------------------------------------------------------------
443 Int_t AliMUONTriggerCircuit::GetIdCircuitD(){
444 // returns the Id of the circuit down 
445   Int_t idModule=Module(fIdCircuit);
446   Int_t idModuleD=(TMath::Abs(idModule)+10)*(TMath::Abs(idModule)/idModule); 
447   return (TMath::Abs(idModuleD)*10+1)*(TMath::Abs(idModule)/idModule);
448 }
449 //----------------------------------------------------------------------
450 Int_t AliMUONTriggerCircuit::GetICircuitD(){
451 // returns the number of the circuit down 
452   Int_t idModule=Module(fIdCircuit);
453   Int_t idModuleD=(TMath::Abs(idModule)+10)*(TMath::Abs(idModule)/idModule); 
454   Int_t idCircuitD=
455     (TMath::Abs(idModuleD)*10+1)*(TMath::Abs(idModule)/idModule);
456   return CircuitNumber(idCircuitD);
457 }
458 //----------------------------------------------------------------------
459 Int_t AliMUONTriggerCircuit::GetIdCircuitU(){
460 // returns the Id of the circuit up 
461   Int_t idModule=Module(fIdCircuit);
462   Int_t idModuleU=(TMath::Abs(idModule)-10)*(TMath::Abs(idModule)/idModule); 
463   return (TMath::Abs(idModuleU)*10+1)*(TMath::Abs(idModule)/idModule);
464 }
465 //----------------------------------------------------------------------
466 Int_t AliMUONTriggerCircuit::GetICircuitU(){
467 // returns the number of the circuit up 
468   Int_t idModule=Module(fIdCircuit);
469   Int_t idModuleU=(TMath::Abs(idModule)-10)*(TMath::Abs(idModule)/idModule); 
470   Int_t idCircuitU=
471     (TMath::Abs(idModuleU)*10+1)*(TMath::Abs(idModule)/idModule);
472   return CircuitNumber(idCircuitU);
473 }
474 //----------------------------------------------------------------------
475 Int_t AliMUONTriggerCircuit::GetX2m(){ 
476 // returns fX2m
477   return fX2m;
478 }
479 //----------------------------------------------------------------------
480 Int_t AliMUONTriggerCircuit::GetX2ud(){ 
481 // returns fX2ud
482   return fX2ud;
483 }
484 //----------------------------------------------------------------------
485 void AliMUONTriggerCircuit::GetOrMud(Int_t orMud[2]){
486 // returns fOrMud 
487   orMud[0]=fOrMud[0];
488   orMud[1]=fOrMud[1];
489 }
490 //----------------------------------------------------------------------
491 Int_t AliMUONTriggerCircuit::GetXcode(Int_t chamber, Int_t istrip){
492 // returns X code of circuit/chamber/istrip (warning : chamber in [0,3])
493   return fXcode[chamber][istrip];
494 }
495 //----------------------------------------------------------------------
496 Int_t AliMUONTriggerCircuit::GetYcode(Int_t chamber, Int_t istrip){
497 // returns Y code of circuit/chamber/istrip (warning : chamber in [0,3])
498   return fYcode[chamber][istrip];
499 }
500 //----------------------------------------------------------------------
501 Float_t AliMUONTriggerCircuit::GetY11Pos(Int_t istrip){
502 // returns Y position of X strip istrip in MC11
503   return fYpos11[istrip];
504 }
505 //----------------------------------------------------------------------
506 Float_t AliMUONTriggerCircuit::GetY21Pos(Int_t istrip){
507 // returns Y position of X strip istrip in MC21
508   return fYpos21[istrip];
509 }
510 //----------------------------------------------------------------------
511 Float_t AliMUONTriggerCircuit::GetX11Pos(Int_t istrip){
512 // returns X position of Y strip istrip in MC11
513   return fXpos11[istrip];
514 }
515 //----------------------------------------------------------------------
516 //--- end of methods which return member data related info
517 //----------------------------------------------------------------------
518
519
520
521
522
523
524