fix of some rule violations
[u/mrichter/AliRoot.git] / PWG1 / AliAnaVZEROQA.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 // Analysis task for quality-assurance
18 // of VZERO ESD
19 //
20 // 05/12/2009 cvetan.cheshkov@cern.ch
21 //------------------------------
22
23 #include "TChain.h"
24 #include "TROOT.h"
25 #include "TFile.h"
26 #include "TH1F.h"
27 #include "TH2F.h"
28 #include "TCanvas.h"
29 #include "AliLog.h"
30 #include "AliESDEvent.h"
31 #include "AliESDVZERO.h"
32
33 #include "AliAnaVZEROQA.h"
34
35 ClassImp(AliAnaVZEROQA)
36
37 AliAnaVZEROQA::AliAnaVZEROQA():
38 AliAnalysisTaskSE("AliAnaVZEROQA"),
39   fListOfHistos(0),
40
41   fhAdcNoTimeA(0),
42   fhAdcWithTimeA(0),
43   fhAdcNoTimeC(0),
44   fhAdcWithTimeC(0),
45
46   fhAdcPMTNoTime(0),
47   fhAdcPMTWithTime(0),
48  
49   fhTimeA(0),
50   fhTimeC(0),
51
52   fhWidthA(0),
53   fhWidthC(0),
54
55   fhTimePMT(0),
56   fhWidthPMT(0),
57
58   fhAdcWidthA(0),
59   fhAdcWidthC(0),
60
61   fhTimeCorr(0),
62
63   fhAdcTimeA(0),
64   fhAdcTimeC(0),
65
66   fV0a(0),
67   fV0c(0),
68   fV0multA(0),
69   fV0multC(0),
70   fV0ampl(0),
71
72   fhTimePMTCorr(0),
73   fhEvents(0),
74
75   fhVtxXYBB(0),
76   fhVtxZBB(0),
77   fhVtxXYBGA(0),
78   fhVtxZBGA(0),
79   fhVtxXYBGC(0),
80   fhVtxZBGC(0)
81 {
82   // Default constructor
83   // Define input and output slots here
84   // Input slot #0 works with a TChain
85   DefineInput(0, TChain::Class());
86   // Output slot #1 TList
87   DefineOutput(1, TList::Class());
88 }
89
90 AliAnaVZEROQA::AliAnaVZEROQA(const char* name):
91 AliAnalysisTaskSE(name),
92   fListOfHistos(0),
93   fhAdcNoTimeA(0),
94   fhAdcWithTimeA(0),
95   fhAdcNoTimeC(0),
96   fhAdcWithTimeC(0),
97
98   fhAdcPMTNoTime(0),
99   fhAdcPMTWithTime(0),
100  
101   fhTimeA(0),
102   fhTimeC(0),
103
104   fhWidthA(0),
105   fhWidthC(0),
106
107   fhTimePMT(0),
108   fhWidthPMT(0),
109
110   fhAdcWidthA(0),
111   fhAdcWidthC(0),
112
113   fhTimeCorr(0),
114
115   fhAdcTimeA(0),
116   fhAdcTimeC(0),
117
118   fV0a(0),
119   fV0c(0),
120   fV0multA(0),
121   fV0multC(0),
122   fV0ampl(0),
123
124   fhTimePMTCorr(0),
125   fhEvents(0),
126
127   fhVtxXYBB(0),
128   fhVtxZBB(0),
129   fhVtxXYBGA(0),
130   fhVtxZBGA(0),
131   fhVtxXYBGC(0),
132   fhVtxZBGC(0)
133 {
134   // Constructor
135   AliInfo("Constructor AliAnaVZEROQA");
136   // Define input and output slots here
137   // Input slot #0 works with a TChain
138   DefineInput(0, TChain::Class());
139   // Output slot #1 TList
140   DefineOutput(1, TList::Class());
141 }
142
143 TH1F * AliAnaVZEROQA::CreateHisto1D(const char* name, const char* title,Int_t nBins, 
144                                     Double_t xMin, Double_t xMax,
145                                     const char* xLabel, const char* yLabel)
146 {
147   // create a histogram
148   TH1F* result = new TH1F(name, title, nBins, xMin, xMax);
149   result->SetOption("E");
150   if (xLabel) result->GetXaxis()->SetTitle(xLabel);
151   if (yLabel) result->GetYaxis()->SetTitle(yLabel);
152   result->SetMarkerStyle(kFullCircle);
153   return result;
154 }
155
156 TH2F * AliAnaVZEROQA::CreateHisto2D(const char* name, const char* title,Int_t nBinsX, 
157                                     Double_t xMin, Double_t xMax,
158                                     Int_t nBinsY,
159                                     Double_t yMin, Double_t yMax,
160                                     const char* xLabel, const char* yLabel)
161 {
162   // create a histogram
163   TH2F* result = new TH2F(name, title, nBinsX, xMin, xMax, nBinsY, yMin, yMax);
164   if (xLabel) result->GetXaxis()->SetTitle(xLabel);
165   if (yLabel) result->GetYaxis()->SetTitle(yLabel);
166   return result;
167 }
168
169 void AliAnaVZEROQA::UserCreateOutputObjects()
170 {
171   // Create histograms
172   AliInfo("AliAnaVZEROQA::UserCreateOutputObjects");
173   // Create output container
174   fListOfHistos = new TList();
175
176   fhAdcNoTimeA = CreateHisto1D("hAdcNoTimeA","ADC (no Leading Time) V0A",200,0,200,"ADC charge","Entries");
177   fhAdcWithTimeA = CreateHisto1D("hAdcWithTimeA","ADC ( with Leading Time) V0A",200,0,200,"ADC charge","Entries");
178   fhAdcNoTimeC = CreateHisto1D("hAdcNoTimeC","ADC (no Leading Time) V0C",200,0,200,"ADC charge","Entries");
179   fhAdcWithTimeC = CreateHisto1D("hAdcWithTimeC","ADC ( with Leading Time) V0C",200,0,200,"ADC charge","Entries");
180   
181   fhAdcPMTNoTime = CreateHisto2D("hadcpmtnotime","ADC vs PMT index (no leading time)",64,-0.5,63.5,200,0,200,"PMT index","ADC charge");
182   fhAdcPMTWithTime = CreateHisto2D("hadcpmtwithtime","ADC vs PMT index (with leading time)",64,-0.5,63.5,200,0,200,"PMT index","ADC charge");
183
184   fhTimeA = CreateHisto1D("htimepmtA","Time measured by TDC V0A",400,-100,100,"Leading time (ns)","Entries");
185   fhTimeC = CreateHisto1D("htimepmtC","Time measured by TDC V0C",400,-100,100,"Leading time (ns)","Entries");
186
187   fhWidthA = CreateHisto1D("hwidthA","Signal width measured by TDC V0A",200,0,100,"Signal width (ns)","Entries");
188   fhWidthC = CreateHisto1D("hwidthC","Signal width measured by TDC V0C",200,0,100,"Signal width (ns)","Entries");
189
190   fhTimePMT = CreateHisto2D("htimepmt","Time measured by TDC vs PMT index",64,-0.5,63.5,200,0,100,"PMT Index","Leading time (ns)");
191   fhWidthPMT = CreateHisto2D("hwidthpmt","Time width vs PMT index",64,-0.5,63.5,200,0,100,"PMT Index","Signal width (ns)");
192
193   fhAdcWidthA = CreateHisto2D("hadcwidthA","Time width vs ADC V0A",200,0,200,200,0,100,"ADC charge","Width (ns)");
194   fhAdcWidthC = CreateHisto2D("hadcwidthC","Time width vs ADC V0C",200,0,200,200,0,100,"ADC charge","Width (ns)");
195
196   fhTimeCorr = CreateHisto2D("htimecorr","Average time C side vs. A side",200,0,100,200,0,100,"Time V0A (ns)","Time V0C (ns");
197
198   fhAdcTimeA = CreateHisto2D("hAdcTimeA","ADC vs Time V0A",1000,-100,100,200,0,200,"Time (ns)","ADC charge");
199   fhAdcTimeC = CreateHisto2D("hAdcTimeC","ADC vs Time V0C",1000,-100,100,200,0,200,"Time (ns)","ADC charge");
200
201   fV0a = CreateHisto1D("hV0a","Number of fired PMTs (V0A)",65,-0.5,64.5);
202   fV0c = CreateHisto1D("hV0c","Number of fired PMTs (V0C)",65,-0.5,64.5);
203   fV0multA = CreateHisto1D("hV0multA","Total reconstructed multiplicity (V0A)",100,0.,1000.);
204   fV0multC = CreateHisto1D("hV0multC","Total reconstructed multiplicity (V0C)",100,0.,1000.);
205   fV0ampl  = CreateHisto1D("hV0ampl","V0 multiplicity in single channel (all V0 channels)",400,-0.5,99.5);
206
207   fhTimePMTCorr = CreateHisto2D("htimepmtcorr","Time measured by TDC (corrected for slewing, channels aligned) vs PMT index",64,-0.5,63.5,200,0,100,"PMT Index","Leading time (ns)");
208   fhEvents = CreateHisto2D("hEvents","V0C vs V0A (empty,bb,bg)",3,-0.5,2.5,3,-0.5,2.5);
209
210   fhVtxXYBB = CreateHisto2D("fhVtxXYBB","XY SPD vertex (bb)",200,-2,2,200,-2,2);
211   fhVtxZBB = CreateHisto1D("fhVtxZBB","Z SPD vertex (bb)",400,-50,50);
212   fhVtxXYBGA = CreateHisto2D("fhVtxXYBGA","XY SPD vertex (bga)",200,-2,2,200,-2,2);
213   fhVtxZBGA = CreateHisto1D("fhVtxZBGA","Z SPD vertex (bga)",400,-50,50);
214   fhVtxXYBGC = CreateHisto2D("fhVtxXYBGC","XY SPD vertex (bgc)",200,-2,2,200,-2,2);
215   fhVtxZBGC = CreateHisto1D("fhVtxZBGC","Z SPD vertex (bgc)",400,-50,50);
216
217   fListOfHistos->Add(fhAdcNoTimeA);
218   fListOfHistos->Add(fhAdcWithTimeA);
219   fListOfHistos->Add(fhAdcNoTimeC);
220   fListOfHistos->Add(fhAdcWithTimeC);
221
222   fListOfHistos->Add(fhAdcPMTNoTime);
223   fListOfHistos->Add(fhAdcPMTWithTime);
224  
225   fListOfHistos->Add(fhTimeA);
226   fListOfHistos->Add(fhTimeC);
227
228   fListOfHistos->Add(fhWidthA);
229   fListOfHistos->Add(fhWidthC);
230
231   fListOfHistos->Add(fhTimePMT);
232   fListOfHistos->Add(fhWidthPMT);
233
234   fListOfHistos->Add(fhAdcWidthA);
235   fListOfHistos->Add(fhAdcWidthC);
236
237   fListOfHistos->Add(fhTimeCorr);
238
239   fListOfHistos->Add(fhAdcTimeA);
240   fListOfHistos->Add(fhAdcTimeC);
241
242   fListOfHistos->Add(fV0a);
243   fListOfHistos->Add(fV0c);
244   fListOfHistos->Add(fV0multA);
245   fListOfHistos->Add(fV0multC);
246   fListOfHistos->Add(fV0ampl);
247
248   fListOfHistos->Add(fhTimePMTCorr);
249   fListOfHistos->Add(fhEvents);
250
251   fListOfHistos->Add(fhVtxXYBB);
252   fListOfHistos->Add(fhVtxZBB);
253   fListOfHistos->Add(fhVtxXYBGA);
254   fListOfHistos->Add(fhVtxZBGA);
255   fListOfHistos->Add(fhVtxXYBGC);
256   fListOfHistos->Add(fhVtxZBGC);
257 }
258
259 void AliAnaVZEROQA::UserExec(Option_t */*option*/)
260 {
261   // Fill the QA histograms
262   // using ESD data
263   AliVEvent* event = InputEvent();
264   if (!event) {
265     Printf("ERROR: Could not retrieve event");
266     return;
267   }
268
269   AliESDEvent* esd = dynamic_cast<AliESDEvent*>(event);
270   AliESDVZERO* esdV0 = esd->GetVZEROData();
271
272   Float_t timeA = 0,timeC = 0;
273   Int_t ntimeA = 0, ntimeC = 0;
274   for (Int_t i=0; i<64; ++i) {
275       if (esdV0->GetTime(i) < 1e-6) {
276         if (i >= 32) {
277           fhAdcNoTimeA->Fill(esdV0->GetAdc(i));
278         }
279         else {
280           fhAdcNoTimeC->Fill(esdV0->GetAdc(i));
281         }
282         fhAdcPMTNoTime->Fill(i,esdV0->GetAdc(i));
283       }
284       else {
285         if (i >= 32) {
286           fhAdcWithTimeA->Fill(esdV0->GetAdc(i));
287         }
288         else {
289           fhAdcWithTimeC->Fill(esdV0->GetAdc(i));
290         }
291         fhAdcPMTWithTime->Fill(i,esdV0->GetAdc(i));
292       }
293
294       if (i >= 32) {
295         fhTimeA->Fill(esdV0->GetTime(i));
296         fhWidthA->Fill(esdV0->GetWidth(i));
297         fhAdcWidthA->Fill(esdV0->GetAdc(i),esdV0->GetTime(i));
298         fhAdcTimeA->Fill(esdV0->GetTime(i),esdV0->GetAdc(i));
299       }
300       else {
301         fhTimeC->Fill(esdV0->GetTime(i));
302         fhWidthC->Fill(esdV0->GetWidth(i));
303         fhAdcWidthC->Fill(esdV0->GetAdc(i),esdV0->GetTime(i));
304         fhAdcTimeC->Fill(esdV0->GetTime(i),esdV0->GetAdc(i));
305        }
306       fhTimePMT->Fill(i,esdV0->GetTime(i));
307       fhWidthPMT->Fill(i,esdV0->GetWidth(i));
308
309       Float_t correctedTime = CorrectLeadingTime(i,esdV0->GetTime(i),esdV0->GetAdc(i));
310       fhTimePMTCorr->Fill(i,correctedTime);
311
312       if (esdV0->GetTime(i) > 1e-6) {
313         if (i >= 32) {
314           timeA += correctedTime;
315           ntimeA++;
316         }
317         else {
318           timeC += correctedTime;
319           ntimeC++;
320         }
321       }
322   }
323
324   if (ntimeA > 0) timeA = timeA/ntimeA;
325   if (ntimeC > 0) timeC = timeC/ntimeC;
326
327   fhTimeCorr->Fill(timeA,timeC);
328
329   Int_t flaga = 0, flagc = 0;
330   TString stra("emptyA"),strc("emptyC");
331   if (timeA > 48 && timeA < 62) { flaga = 1; stra = "BBA"; }
332   if (timeA > 26  && timeA < 33) { flaga = 2; stra = "BGA"; }
333   if (timeC > 49 && timeC < 60) { flagc = 1; strc = "BBC"; }
334   if (timeC > 43 && timeC < 48.5) { flagc = 2; strc = "BGC"; }
335
336   fhEvents->Fill(flaga,flagc);
337
338   const AliESDVertex *vtx = esd->GetPrimaryVertexSPD();
339
340   if (flaga <= 1 && flagc <=1) {
341     fhVtxXYBB->Fill(vtx->GetXv(),vtx->GetYv());
342     fhVtxZBB->Fill(vtx->GetZv());
343   }
344   else {
345     if (flaga == 2) {
346       fhVtxXYBGA->Fill(vtx->GetXv(),vtx->GetYv());
347       fhVtxZBGA->Fill(vtx->GetZv());
348     }
349     if (flagc == 2) {
350       fhVtxXYBGC->Fill(vtx->GetXv(),vtx->GetYv());
351       fhVtxZBGC->Fill(vtx->GetZv());
352     }
353   }
354
355   fV0a->Fill(esdV0->GetNbPMV0A());
356   fV0c->Fill(esdV0->GetNbPMV0C());
357   fV0multA->Fill(esdV0->GetMTotV0A());
358   fV0multC->Fill(esdV0->GetMTotV0C());
359   for(Int_t i = 0; i < 64; i++) {
360     fV0ampl->Fill(esdV0->GetMultiplicity(i));
361   }
362
363   // Post output data.
364   PostData(1, fListOfHistos);
365 }
366
367 void AliAnaVZEROQA::Terminate(Option_t *)
368 {
369   // Store the output histograms
370   // from the list
371   fListOfHistos = dynamic_cast<TList*>(GetOutputData(1));
372   if (!fListOfHistos) {
373     Printf("ERROR: fListOfHistos not available");
374     return;
375   }
376         
377   fhAdcNoTimeA = dynamic_cast<TH1F*>(fListOfHistos->At(0));
378   fhAdcWithTimeA = dynamic_cast<TH1F*>(fListOfHistos->At(1));
379   fhAdcNoTimeC = dynamic_cast<TH1F*>(fListOfHistos->At(2));
380   fhAdcWithTimeC = dynamic_cast<TH1F*>(fListOfHistos->At(3));
381
382   fhAdcPMTNoTime = dynamic_cast<TH2F*>(fListOfHistos->At(4));
383   fhAdcPMTWithTime = dynamic_cast<TH2F*>(fListOfHistos->At(5));
384
385   fhTimeA = dynamic_cast<TH1F*>(fListOfHistos->At(6));
386   fhTimeC = dynamic_cast<TH1F*>(fListOfHistos->At(7));
387
388   fhWidthA = dynamic_cast<TH1F*>(fListOfHistos->At(8));
389   fhWidthC = dynamic_cast<TH1F*>(fListOfHistos->At(9));
390
391   fhTimePMT = dynamic_cast<TH2F*>(fListOfHistos->At(10));
392   fhWidthPMT = dynamic_cast<TH2F*>(fListOfHistos->At(11));
393
394   fhAdcWidthA = dynamic_cast<TH2F*>(fListOfHistos->At(12));
395   fhAdcWidthC = dynamic_cast<TH2F*>(fListOfHistos->At(13));
396
397   fhTimeCorr = dynamic_cast<TH2F*>(fListOfHistos->At(14));
398
399   fhAdcTimeA = dynamic_cast<TH2F*>(fListOfHistos->At(15));
400   fhAdcTimeC = dynamic_cast<TH2F*>(fListOfHistos->At(16));
401
402   fV0a = dynamic_cast<TH1F*>(fListOfHistos->At(17));
403   fV0c = dynamic_cast<TH1F*>(fListOfHistos->At(18));
404   fV0multA = dynamic_cast<TH1F*>(fListOfHistos->At(19));
405   fV0multC = dynamic_cast<TH1F*>(fListOfHistos->At(20));
406   fV0ampl  = dynamic_cast<TH1F*>(fListOfHistos->At(21));
407
408   fhTimePMTCorr = dynamic_cast<TH2F*>(fListOfHistos->At(22));
409   fhEvents = dynamic_cast<TH2F*>(fListOfHistos->At(23));
410
411   fhVtxXYBB = dynamic_cast<TH2F*>(fListOfHistos->At(24));
412   fhVtxZBB = dynamic_cast<TH1F*>(fListOfHistos->At(25));
413   fhVtxXYBGA = dynamic_cast<TH2F*>(fListOfHistos->At(26));
414   fhVtxZBGA = dynamic_cast<TH1F*>(fListOfHistos->At(27));
415   fhVtxXYBGC = dynamic_cast<TH2F*>(fListOfHistos->At(28));
416   fhVtxZBGC = dynamic_cast<TH1F*>(fListOfHistos->At(29));
417
418  // draw the histograms if not in batch mode
419   if (!gROOT->IsBatch()) {
420     new TCanvas;
421     fhTimePMT->DrawCopy();
422     new TCanvas;
423     fhAdcTimeA->DrawCopy();
424     new TCanvas;
425     fhAdcTimeC->DrawCopy();
426     new TCanvas;
427     fhAdcPMTNoTime->DrawCopy();
428     new TCanvas;
429     fhAdcPMTWithTime->DrawCopy();
430     new TCanvas;
431     fhTimeCorr->DrawCopy("E");
432     new TCanvas;
433     fV0ampl->DrawCopy("E");
434     new TCanvas;
435     fhTimePMTCorr->DrawCopy("colz");
436     new TCanvas;
437     fhEvents->DrawCopy("colz");
438   }
439
440   // write the output histograms to a file
441   TFile* outputFile = TFile::Open("VZEROQA.root", "recreate");
442   if (!outputFile || !outputFile->IsOpen())
443     {
444       Error("AliAnaVZEROQA", "opening output file VZEROQA.root failed");
445       return;
446     }
447
448   fhAdcNoTimeA->Write();
449   fhAdcWithTimeA->Write();
450   fhAdcNoTimeC->Write();
451   fhAdcWithTimeC->Write();
452
453   fhAdcPMTNoTime->Write();
454   fhAdcPMTWithTime->Write();
455  
456   fhTimeA->Write();
457   fhTimeC->Write();
458
459   fhWidthA->Write();
460   fhWidthC->Write();
461
462   fhTimePMT->Write();
463   fhWidthPMT->Write();
464
465   fhAdcWidthA->Write();
466   fhAdcWidthC->Write();
467
468   fhTimeCorr->Write();
469
470   fhAdcTimeA->Write();
471   fhAdcTimeC->Write();
472
473   fV0a->Write();
474   fV0c->Write();
475   fV0multA->Write();
476   fV0multC->Write();
477   fV0ampl->Write();
478
479   fhTimePMTCorr->Write();
480   fhEvents->Write();
481
482   fhVtxXYBB->Write();
483   fhVtxZBB->Write();
484   fhVtxXYBGA->Write();
485   fhVtxZBGA->Write();
486   fhVtxXYBGC->Write();
487   fhVtxZBGC->Write();
488
489   outputFile->Close();
490   delete outputFile;
491
492   //delete esd;
493   Info("AliAnaVZEROQA", "Successfully finished");
494 }
495
496 Float_t AliAnaVZEROQA::CorrectLeadingTime(Int_t i, Float_t time, Float_t adc) const
497 {
498   // Correct for slewing and align the channels
499
500   if (time < 1e-6) return 0;
501
502   // Time offsets between channels
503   Float_t timeShift[64] = {30.2914 , 30.0019 , 30.7429 , 30.1997 , 30.1511 , 29.6437 , 30.0609 , 29.5452 , 30.1437 , 30.745 , 30.7537 , 30.446 , 30.2771 , 30.838 , 30.3748 , 30.0635 , 30.1786 , 30.282 , 31.0992 , 30.7491 , 30.624 , 30.9268 , 30.6585 , 30.4895 , 31.5815 , 31.3871 , 31.2032 , 31.5778 , 31.0838 , 31.2259 , 31.2122 , 31.5989 , 28.3792 , 28.8325 , 27.8719 , 28.3475 , 26.9925 , 27.9300 , 28.4223 , 28.4996 , 28.2934 , 28.1281 , 27.209 , 28.5327 , 28.1181 , 28.0888 , 29.5111 , 28.6601 , 29.7705 , 29.6531 , 30.3373 , 30.2345 , 30.5935 , 29.8164 , 30.2235 , 29.6505 , 30.1225 , 31.2045 , 30.8399 , 30.6789 , 30.2784 , 31.7028 , 31.4239 , 30.1814};
504   time -= timeShift[i];
505
506   // Slewing correction
507   if (adc < 1e-6) return time;
508
509   time += 30.;
510   if (adc > 300.) adc = 300.;
511   if (adc > 70.) {
512     return (time -
513             2.93028e+01 +
514             adc*1.25188e-02 -
515             adc*adc*2.68348e-05);
516   }
517   else {
518     return (time -
519             3.52314e+01 +
520             adc*5.99289e-01 -
521             adc*adc*2.74668e-02 +
522             adc*adc*adc*6.61224e-04 -
523             adc*adc*adc*adc*7.77105e-06 +
524             adc*adc*adc*adc*adc*3.51229e-08);
525   }
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587