]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGLF/FORWARD/analysis2/corrs/CorrDrawer.C
162eeae4a1cf896905f6c3bddd1e3d2aeaf8c35e
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / corrs / CorrDrawer.C
1 #ifndef __CINT__
2 # include "SummaryDrawer.C"
3 # include "AliFMDCorrAcceptance.h"
4 # include "AliFMDCorrSecondaryMap.h"
5 # include "AliFMDCorrELossFit.h"
6 # include "AliForwardUtil.h"
7 # include "AliForwardCorrectionManager.h"
8 # include "AliLog.h"
9 # include <TString.h>
10 # include <TError.h>
11 #else
12 class SummaryDrawer;
13 class TObject;
14 // class TAxis;
15 class AliFMDCorrAcceptance;
16 class AliFMDCorrSecondaryMap;
17 class AliFMDCorrELossFit;
18 #include <TString.h>
19 #endif
20
21 class CorrDrawer : public SummaryDrawer
22 {
23 public:
24   TString  fELossExtra;
25   UShort_t fMinQuality;
26   /** 
27    * Constructor 
28    */
29   CorrDrawer() 
30   {
31     fELossExtra = "forward_eloss.root";
32     fMinQuality = 8;
33   }
34   /** 
35    * Destructor.  Closes the PDF 
36    */
37   ~CorrDrawer() 
38   {
39     CloseCanvas();
40   }
41   /** 
42    * Create output file name 
43    * 
44    * @param out    Output file name on return 
45    * @param prefix Prefix of the file name 
46    */
47   static void MakeFileName(TString&        out,
48                            const TString&  prefix)
49   /*
50    * @param runNo  Run Number
51    * @param sys    Collision system 
52    * @param sNN    Center of mass energy 
53    * @param field  L3 Field 
54    * @param mc     Simulations or not
55    * @param sat    Satellite interactions or not 
56                            ULong_t         runNo, 
57                            UShort_t        sys, 
58                            UShort_t        sNN, 
59                            Short_t         field,
60                            Bool_t          mc=false, 
61                            Bool_t          sat=false) */
62   {
63     out = TString::Format("forward_%s.pdf", prefix.Data());
64 #if 0
65     out = TString::Format("%s_run%09lu_%s_%04dGeV_%c%dkG_%s_%s.pdf",
66                           prefix.Data(), runNo, 
67                           (sys == 1 ? "pp" : 
68                            sys == 2 ? "PbPb" : 
69                            sys == 3 ? "pPb" : "unknown"), sNN, 
70                           (field >= 0 ? 'p' : 'm'), TMath::Abs(field), 
71                           (mc ? "MC" : "real"),
72                           (sat ? "satellite" : "nominal"));
73 #endif
74   }
75   /** 
76    * Draw corrections using the correction manager to get them 
77    *  
78    * @param what    What to draw 
79    * @param runNo   Run Number
80    * @param sys     Collision system 
81    * @param sNN     Center of mass energy 
82    * @param field   L3 Field 
83    * @param mc      Simulations or not
84    * @param sat     Satellite interactions or not 
85    * @param options Options
86    * @param local   Local database file 
87    */
88   void Run(const Char_t* what, 
89            ULong_t       runNo, 
90            const Char_t* sys, 
91            UShort_t      sNN, 
92            UShort_t      field,
93            Bool_t        mc=false, 
94            Bool_t        sat=false,
95            Option_t*     options="",
96            const char*   local="")         
97   {
98     Run(AliForwardCorrectionManager::ParseFields(what), 
99         runNo, AliForwardUtil::ParseCollisionSystem(sys), 
100         sNN, field, mc, sat, options, local);
101   }
102   void AppendName(TString& what, UShort_t which)
103   {
104     if (!what.IsNull()) what.Append("_");
105     switch (which) {
106     case AliForwardCorrectionManager::kSecondaryMap:
107       what.Append("secondary"); break;
108     case AliForwardCorrectionManager::kAcceptance:
109       what.Append("acceptance"); break;
110     case AliForwardCorrectionManager::kELossFits:                 
111       what.Append("elossfits"); break;
112     default:
113       what.Append("unknown"); break;
114     }
115   }
116   /** 
117    * Draw corrections using the correction manager to get them 
118    *  
119    * @param what    What to draw 
120    * @param runNo   Run Number
121    * @param sys     Collision system 
122    * @param sNN     Center of mass energy 
123    * @param field   L3 Field 
124    * @param mc      Simulations or not
125    * @param sat     Satellite interactions or not 
126    * @param local   Local database file 
127    */
128   void Run(UShort_t    what, 
129            ULong_t     runNo, 
130            UShort_t    sys, 
131            UShort_t    sNN, 
132            UShort_t    field,
133            Bool_t      mc=false, 
134            Bool_t      sat=false,
135            Option_t*   /*options*/="",
136            const char* local="")
137   {
138     AliForwardCorrectionManager& mgr = AliForwardCorrectionManager::Instance();
139     mgr.SetDebug(true);
140     UShort_t flags = 0;
141
142     TString name;
143     if (what & AliForwardCorrectionManager::kSecondaryMap) {
144       flags |= AliForwardCorrectionManager::kSecondaryMap;
145       if (local) mgr.SetSecondaryMapPath(local);
146       AppendName(name, AliForwardCorrectionManager::kSecondaryMap);
147     }
148     if (what & AliForwardCorrectionManager::kAcceptance) {
149       flags |= AliForwardCorrectionManager::kAcceptance;
150       if (local) mgr.SetAcceptancePath(local);
151       AppendName(name, AliForwardCorrectionManager::kAcceptance);
152     }
153     if (what & AliForwardCorrectionManager::kELossFits) {
154       flags |= AliForwardCorrectionManager::kELossFits;
155       if (local) mgr.SetELossFitsPath(local);
156       AppendName(name, AliForwardCorrectionManager::kELossFits);
157     }
158     if (what & AliForwardCorrectionManager::kVertexBias) 
159       Warning("CorrDrawer","Vertex bias not implemented yet");
160     if (what & AliForwardCorrectionManager::kDoubleHit) 
161       Warning("CorrDrawer","Double hit not implemented yet");    
162     if (what & AliForwardCorrectionManager::kMergingEfficiency) 
163       Warning("CorrDrawer","Merging efficiency not implemented yet");
164     
165     if (!mgr.Init(runNo, sys, sNN, field, mc, sat, flags, true)) {
166       Error("CorrDrawer", "Failed to initialize for flags=0x%02x"
167                 "run=%lu, sys=%hu, sNN=%hu, field=%hd, mc=%d, sat=%d",
168                 flags, runNo, sys, sNN, field, mc, sat);
169       return;
170     }
171
172     TString out;
173     MakeFileName(out, name); // , runNo, sys, sNN, field, mc, sat);
174     CreateCanvas(out);
175
176     fBody->cd();
177     Double_t y = .8;
178     DrawParameter(y, "Run #", Form("%lu", runNo));
179     DrawParameter(y, "System", AliForwardUtil::CollisionSystemString(sys));
180     DrawParameter(y, "#sqrt{s_{NN}}", 
181                   AliForwardUtil::CenterOfMassEnergyString(sNN));
182     DrawParameter(y, "L3 field", AliForwardUtil::MagneticFieldString(field));
183     DrawParameter(y, "Simulation", Form("%s", mc ? "yes" : "no"));
184     DrawParameter(y, "Satellite", Form("%s", sat ? "yes" : "no"));
185     PrintCanvas("Title");
186       
187     if (what & AliForwardCorrectionManager::kSecondaryMap) {
188       const AliFMDCorrSecondaryMap* sec = mgr.GetSecondaryMap();
189       if (!sec) 
190         Warning("CorrDrawer","No secondary map available");
191       else 
192         DrawIt(sec, true);
193     }
194     if (what & AliForwardCorrectionManager::kAcceptance) {
195       const AliFMDCorrAcceptance* acc = mgr.GetAcceptance();
196       if (!acc) 
197         Warning("CorrDrawer","No acceptance available");
198       else 
199         DrawIt(acc, true);
200     }
201     if (what & AliForwardCorrectionManager::kELossFits) {
202       const AliFMDCorrELossFit* fit = mgr.GetELossFit();
203       if (!fit) 
204         Warning("CorrDrawer","No energy loss fits available");
205       else 
206         DrawIt(fit, true);
207     }
208     CloseCanvas();
209   }
210   /** 
211    * Fall-back method
212    * 
213    * @param o Object to draw
214    */
215   virtual void Draw(const TObject* o) 
216   {
217     if (!o) return;
218     Warning("CorrDrawer", "Don't know how to draw a %s object", 
219             o->ClassName());
220   }
221   /** 
222    * Draw a single plot of the mean acceptance correction
223    * 
224    * @param acc Acceptance correction
225    */
226   virtual void Draw(const AliFMDCorrAcceptance* acc) { Summarize(acc, false); }
227   /** 
228    * Draw a single plot of the mean secondary correction 
229    * 
230    * @param sec Secondary correction
231    */
232   virtual void Draw(const AliFMDCorrSecondaryMap* sec) { Summarize(sec, false);}
233   /** 
234    * Draw a single plot summarizing the energy loss fits
235    * 
236    * @param fits Energy loss fits
237    */
238   virtual void Draw(const AliFMDCorrELossFit* fits) { Summarize(fits, false); }
239   /** 
240    * A generalized entry to the summarization functions
241    * 
242    * @param what    What to show - only one field
243    * @param runNo   Run number
244    * @param sys     System 
245    * @param sNN     Center of mass energy in GeV
246    * @param field   L3 magnetic field
247    * @param mc      Simulation flag
248    * @param sat     Satellite interaction flag
249    * @param options Options 
250    * @param local   Local storage
251    */
252   virtual void Summarize(const TString& what, 
253                          ULong_t        runNo, 
254                          const Char_t*  sys, 
255                          UShort_t       sNN, 
256                          Short_t        field,
257                          Bool_t         mc=false, 
258                          Bool_t         sat=false,
259                          Option_t*      options="",
260                          const char*    local="")
261   {
262     Summarize(AliForwardCorrectionManager::ParseFields(what), 
263               runNo, AliForwardUtil::ParseCollisionSystem(sys), 
264               sNN, field, mc, sat, options, local);
265   }
266   /** 
267    * A generalized entry to the summarization functions
268    * 
269    * @param what    What to show - only one field
270    * @param runNo   Run number
271    * @param sys     System 
272    * @param sNN     Center of mass energy in GeV
273    * @param field   L3 magnetic field
274    * @param mc      Simulation flag
275    * @param sat     Satellite interaction flag
276    * @param local   Local storage
277    */
278   virtual void Summarize(UShort_t    what, 
279                          ULong_t     runNo, 
280                          UShort_t    sys, 
281                          UShort_t    sNN, 
282                          Short_t     field,
283                          Bool_t      mc=false, 
284                          Bool_t      sat=false,
285                          Option_t*   /*options*/="",
286                          const char* local="")
287   {
288     AliForwardCorrectionManager& mgr = AliForwardCorrectionManager::Instance();
289     mgr.SetDebug(true);
290     if (local) mgr.SetPrefix(gSystem->DirName(local));
291     UShort_t flag = 0;
292     
293     if (what & AliForwardCorrectionManager::kSecondaryMap) 
294       flag = AliForwardCorrectionManager::kSecondaryMap;
295     if (what & AliForwardCorrectionManager::kAcceptance) 
296       flag = AliForwardCorrectionManager::kAcceptance;
297     if (what & AliForwardCorrectionManager::kELossFits) 
298       flag = AliForwardCorrectionManager::kELossFits;
299     if (what & AliForwardCorrectionManager::kVertexBias) 
300       Warning("CorrDrawer","Vertex bias not implemented yet");
301     if (what & AliForwardCorrectionManager::kDoubleHit) 
302       Warning("CorrDrawer","Double hit not implemented yet");    
303     if (what & AliForwardCorrectionManager::kMergingEfficiency) 
304       Warning("CorrDrawer","Merging efficiency not implemented yet");
305     if (flag == 0) { 
306       Warning("CorrDrawer", "Nothing to draw");
307       return;
308     }
309     
310     if (!mgr.Init(runNo, sys, sNN, field, mc, sat, flag, true)) {
311       Error("CorrDrawer", "Failed to initialize for flags=0x%02x "
312             "run=%lu, sys=%hu, sNN=%hu, field=%hd, mc=%d, sat=%d",
313             flag, runNo, sys, sNN, field, mc, sat);
314       return;
315     }
316
317     TString prefix;
318     if      (flag == AliForwardCorrectionManager::kSecondaryMap) 
319       prefix = "secondarymap";
320     else if (flag == AliForwardCorrectionManager::kAcceptance)
321       prefix = "acceptance";
322     else if (flag == AliForwardCorrectionManager::kELossFits) 
323       prefix = "elossfits";
324     else 
325       prefix = "unknown";
326     TString out;
327     MakeFileName(out, prefix); // , runNo, sys, sNN, field, mc, sat);
328     CreateCanvas(out);
329
330     fBody->cd();
331     Double_t y = .8;
332     DrawParameter(y, "Run #", Form("%lu", runNo));
333     DrawParameter(y, "System", AliForwardUtil::CollisionSystemString(sys));
334     DrawParameter(y, "#sqrt{s_{NN}}", 
335                   AliForwardUtil::CenterOfMassEnergyString(sys));
336     DrawParameter(y, "L3 field", AliForwardUtil::MagneticFieldString(field));
337     DrawParameter(y, "Simulation", Form("%s", mc ? "yes" : "no"));
338     DrawParameter(y, "Satellite", Form("%s", sat ? "yes" : "no"));
339     PrintCanvas("Title");
340       
341     if (flag == AliForwardCorrectionManager::kSecondaryMap) {
342       const AliFMDCorrSecondaryMap* sec = mgr.GetSecondaryMap();
343       if (!sec) 
344         Warning("CorrDrawer","No secondary map available");
345       else 
346         DrawIt(sec, true);
347     }
348     else if (flag == AliForwardCorrectionManager::kAcceptance) {
349       const AliFMDCorrAcceptance* acc = mgr.GetAcceptance();
350       if (!acc) 
351         Warning("CorrDrawer","No acceptance available");
352       else 
353         DrawIt(acc, true);
354     }
355     if (flag == AliForwardCorrectionManager::kELossFits) {
356       const AliFMDCorrELossFit* fit = mgr.GetELossFit();
357       if (!fit) 
358         Warning("CorrDrawer","No energy loss fits available");
359       else 
360         DrawIt(fit, true);
361     }
362     CloseCanvas();
363   }
364   /** 
365    * Fall-back method
366    * 
367    * @param o Object to draw
368    * @param pdf Not used
369    */
370   virtual void Summarize(const TObject* o, Bool_t pdf=true) 
371   {
372     if (!o) return;
373     Warning("CorrDrawer", "Don't know how to draw a %s object (PDF: %s)", 
374             o->ClassName(), pdf ? "yes" : "no");
375   }
376   /** 
377    * Draw a single summary plot or multiple plots of the acceptance
378    * correction. A new Canvas is created for this.
379    * 
380    * @param acc Acceptance correction
381    * @param pdf If true, do multiple plots. Otherwise a single summary plot
382    */
383   virtual void Summarize(const AliFMDCorrAcceptance* acc, Bool_t pdf=true) 
384   { 
385     CreateCanvas("acceptance.pdf", false, pdf);
386     DrawIt(acc, pdf); 
387     if (pdf) CloseCanvas();
388   }
389   /** 
390    * Draw a single summary plot multiple plots of the secondary
391    * correction. A new canvas is created for this.
392    * 
393    * @param sec Secondary correction
394    * @param pdf If true, do multiple plots. Otherwise a single summary plot
395    */
396   virtual void Summarize(const AliFMDCorrSecondaryMap* sec, Bool_t pdf=true) 
397   { 
398     CreateCanvas("secondarymap.pdf", false, pdf);
399     DrawIt(sec, pdf); 
400     if (pdf) CloseCanvas();
401   }
402   /** 
403    * Draw a single summary plot multiple plots of the energy loss
404    * fits.  A new canvas is created for this.
405    * 
406    * @param fits Energy loss fits
407    * @param pdf  If true, do multiple plots. Otherwise a single summary plot
408    */
409   virtual void Summarize(const AliFMDCorrELossFit* fits, Bool_t pdf=true) 
410   { 
411     CreateCanvas("elossfits.pdf", false, pdf);
412     DrawIt(fits, pdf); 
413     if (pdf) CloseCanvas();
414   }
415
416   static void Summarize(const TString& what   = TString(""), 
417                         Bool_t         mc     = false,
418                         const TString& output = TString("forward_eloss.root"), 
419                         const TString& local  = TString("fmd_corrections.root"),
420                         Option_t*      options= "")
421   {
422     Summarize(AliForwardCorrectionManager::ParseFields(what), mc, 
423               output, local, options);
424   }
425   static void Summarize(UShort_t       what, 
426                         Bool_t         mc     = false,
427                         const TString& output = "forward_eloss.root", 
428                         const TString& local  = "fmd_corrections.root",
429                         Option_t*      options= "")
430   {
431     TFile* fout = TFile::Open(output, "READ");
432     if (!fout) { 
433       Warning("SummarizeELoss", "Energy loss task output %s not found",
434               output.Data());
435       return;
436     }
437     TCollection* forward = GetCollection(fout, "ForwardELossSums");
438     if (!forward) return;
439     
440     TCollection* eventInsp = GetCollection(forward, "fmdEventInspector");
441     if (!eventInsp) return;
442
443     UShort_t sys   = 0, sNN = 0;
444     Int_t    field = 0;
445     ULong_t  runNo = 0; 
446     Bool_t satellite;
447     if (!GetParameter(eventInsp, "sys",       sys))       return;
448     if (!GetParameter(eventInsp, "sNN",       sNN))       return;
449     if (!GetParameter(eventInsp, "field",     field))     return;
450     if (!GetParameter(eventInsp, "satellite", satellite)) return;
451     if (!GetParameter(eventInsp, "runNo",     runNo))     return;
452     
453     CorrDrawer* drawer = new CorrDrawer;
454     drawer->Run(what, runNo, sys, sNN, field, mc, satellite,
455                 options, local);
456   }
457 protected:
458   /** 
459    * Fall-back method
460    * 
461    * @param o Object to summarize
462    */
463   virtual void DrawIt(const TObject* o) 
464   {
465     if (!o) return;
466     Warning("CorrDrawer", "Don't know how to summarize a %s object", 
467             o->ClassName());
468   }
469   /** 
470    * Draw the acceptance correction 
471    * 
472    * @param corr    Correction
473    * @param details If true, make a multipage PDF, otherwise plot the mean. 
474    */
475   virtual void DrawIt(const AliFMDCorrAcceptance* corr, Bool_t details=true)
476   {
477     if (!corr || !fCanvas) return;
478
479     // --- Get vertex axis ---------------------------------------------
480     const TAxis& vtxAxis = corr->GetVertexAxis();
481     Int_t        nVtx    = vtxAxis.GetNbins();
482
483     // --- Create stacks for summaries ---------------------------------
484     TObjArray* stacks  = CreateVtxStacks(vtxAxis);
485     TObjArray* stacks2 = (corr->HasOverflow() && details 
486                           ? CreateVtxStacks(vtxAxis) : 0);
487     
488     //__________________________________________________________________
489     // Create a title page 
490     if (details) {
491       fBody->cd();
492       TLatex* ll = new TLatex(.5,.8, fCanvas->GetTitle());
493       ll->SetTextAlign(22);
494       ll->SetTextSize(0.03);
495       ll->SetNDC();
496       ll->Draw();
497       
498       TLatex* l = new TLatex(.5,.8, "");
499       l->SetNDC();
500       l->SetTextSize(0.03);
501       l->SetTextFont(132);
502       l->SetTextAlign(12);
503       l->DrawLatex(0.2, 0.70, "Acceptance due to dead channels");
504       l->SetTextAlign(22);
505       l->DrawLatex(0.5, 0.55, "c_{v,r}(#eta,#phi) = #frac{"
506                    "#sum active strips #in (#eta,#phi)}{"
507                  "#sum strips #in (#eta,#phi)}");
508       
509       PrintCanvas("Acceptance");
510     }
511     
512     // --- Loop over vertex ------------------------------------------
513     for (UShort_t v=1; v <= nVtx; v++) { 
514       Double_t vzMin = vtxAxis.GetBinLowEdge(v);
515       Double_t vzMax = vtxAxis.GetBinUpEdge(v);
516
517       if (details) DivideForRings(true, true);
518
519       // --- Loop over detectors -------------------------------------
520       for (UShort_t d = 1; d <= 3; d++) {
521         UShort_t     nQ = (d == 1 ? 1 : 2);
522         for (UShort_t q = 0; q < nQ; q++) { 
523           Char_t r = (q == 0 ? 'I' : 'O');
524           
525           TH2* h2 = corr->GetCorrection(d, r, v);
526           if (!h2) { 
527             Warning("DrawCorrAcc", "No correction for FMD%d%c, v=%d", d, r, v);
528             corr->ls();
529             continue;
530           }
531           
532           if (details) DrawInRingPad(d, r, h2, "colz");
533
534           Int_t nY = h2->GetNbinsY();
535           TH1* hh = h2->ProjectionX(Form("FMD%d%c", d, r), 1, nY);
536           hh->Scale(1. / nY);
537           hh->SetDirectory(0);
538           hh->SetMarkerColor(AliForwardUtil::RingColor(d, r));
539           hh->SetLineColor(AliForwardUtil::RingColor(d, r));
540           hh->SetFillColor(AliForwardUtil::RingColor(d, r));
541           hh->SetFillStyle(3001);
542           
543           THStack* stack = static_cast<THStack*>(stacks->At(v-1));
544           if (!stack) { 
545             Error("", "No stack at v=%d", v-1);
546             continue;
547           }
548           stack->Add(hh);
549
550           if (!stacks2) {
551             Warning("", "No phi acceptance defined");
552             continue;
553           }
554           stack = static_cast<THStack*>(stacks2->At(v-1));
555           if (!stack) { 
556             Error("", "No stack at v=%d", v-1);
557             continue;
558           }
559           TH1* hp = corr->GetPhiAcceptance(d, r, v);
560           if (!hp) { 
561             Error("", "No phi acceptance at v=%d", v-1);
562             continue;
563           }
564           hp->SetDirectory(0);
565           hp->SetMarkerColor(AliForwardUtil::RingColor(d, r));
566           hp->SetLineColor(AliForwardUtil::RingColor(d, r));
567           hp->SetFillColor(AliForwardUtil::RingColor(d, r));
568           hp->SetFillStyle(3001);
569           // Info("", "Adding phi acceptance plot %d", Int_t(hp->GetEntries()));
570           stack->Add(hp);
571
572         }
573       }
574       if (details) 
575         PrintCanvas(Form("%+5.1fcm<IP_{z}<%+5.1fcm", vzMin, vzMax));
576     }
577     if (DrawVtxStacks(stacks2, 1.2)) {
578       PrintCanvas("#phi acceptance");
579     }
580     if (DrawVtxStacks(stacks, 1.2)) {
581       PrintCanvas("#LTacceptance#GT");
582     }
583   }
584   /** 
585    * Draw the secondary correction 
586    * 
587    * @param corr       Correction
588    * @param details If true, make a multipage PDF, otherwise plot the mean. 
589    */
590   virtual void DrawIt(const AliFMDCorrSecondaryMap* corr, bool details) 
591   {
592     if (!corr || !fCanvas) return;
593     
594     const TAxis& vtxAxis = corr->GetVertexAxis();
595     Int_t        nVtx    = vtxAxis.GetNbins();
596     TObjArray*   stacks  = CreateVtxStacks(vtxAxis);
597     
598     //__________________________________________________________________
599     // Create a title page 
600     if (details) {
601       fBody->cd();
602       TLatex* ll = new TLatex(.5,.8, fCanvas->GetTitle());
603       ll->SetTextAlign(22);
604       ll->SetTextSize(0.03);
605       ll->SetNDC();
606       ll->Draw();
607       
608       TLatex* l = new TLatex(.5,.8, "");
609       l->SetNDC();
610       l->SetTextSize(0.03);
611       l->SetTextFont(132);
612       l->SetTextAlign(12);
613       l->DrawLatex(0.2, 0.70, "Secondary map");
614       l->SetTextAlign(22);
615       l->DrawLatex(0.5, 0.60, "c_{v,r}(#eta,#phi)=#frac{"
616                    "#sum N_{ch,primary,i}(#eta,#phi)}{"
617                    "#sum N_{ch,FMD,i}(#eta,#phi)}");
618       l->SetTextAlign(12);
619       l->DrawLatex(0.2, 0.50, "N: Number of events");
620       l->DrawLatex(0.2, 0.45, "N_{ch,primary,i}(#eta,#phi): Number of charged, "
621                    "primary particles in (#eta,#phi) bin");
622       l->DrawLatex(0.2, 0.40, "N_{ch,primary,i}(#eta,#phi): Number of charged, "
623                    "particles that hit the FMD in (#eta,#phi) bin");
624       l->DrawLatex(0.2, 0.35, "All quantities determined in MC");
625       
626       PrintCanvas("Secondary maps");
627     }
628     
629     // --- Loop over vertex ------------------------------------------
630     for (UShort_t v=1; v <= nVtx; v++) { 
631       Double_t vzMin = vtxAxis.GetBinLowEdge(v);
632       Double_t vzMax = vtxAxis.GetBinUpEdge(v);
633
634       if (details) DivideForRings(true, true);
635
636       // --- Loop over detectors -------------------------------------
637       for (UShort_t d = 1; d <= 3; d++) {
638         UShort_t     nQ = (d == 1 ? 1 : 2);
639         for (UShort_t q = 0; q < nQ; q++) { 
640           Char_t r = (q == 0 ? 'I' : 'O');
641           
642           TH2* h2 = corr->GetCorrection(d, r, v);
643           if (!h2) { 
644             Warning("DrawCorrSec", "No correction for FMD%d%c, v=%d", d, r, v);
645             continue;
646           }
647           
648           if (details) DrawInRingPad(d, r, h2, "colz");
649
650           Int_t nY = h2->GetNbinsY();
651           TH1* hh = h2->ProjectionX(Form("FMD%d%c", d, r), 1, nY);
652           hh->Scale(1. / nY);
653           hh->SetDirectory(0);
654           hh->SetMarkerColor(AliForwardUtil::RingColor(d, r));
655           hh->SetLineColor(AliForwardUtil::RingColor(d, r));
656           hh->SetFillColor(AliForwardUtil::RingColor(d, r));
657           hh->SetFillStyle(3001);
658           
659           THStack* stack = static_cast<THStack*>(stacks->At(v-1));
660           if (!stack) { 
661             Error("", "No stack at v=%d", v-1);
662             continue;
663           }
664           stack->Add(hh);
665         }
666       }
667       if (details) 
668         PrintCanvas(Form("%+5.1fcm<IP_{z}<%+5.1fcm", vzMin, vzMax));
669     }
670     if (DrawVtxStacks(stacks, 3.5)) {
671       PrintCanvas("#LTsecondary map#GT");
672     }
673   }
674   /** 
675    * Draw the energy loss fits correction 
676    * 
677    * @param corr       Correction
678    * @param details If true, make a multipage PDF, 
679    *                   otherwise plot the parameters. 
680    */
681   virtual void DrawIt(const AliFMDCorrELossFit* corr, bool details) 
682   {
683     if (!corr || !fCanvas) return;
684
685     AliFMDCorrELossFit* fits = const_cast<AliFMDCorrELossFit*>(corr);
686     fits->CacheBins(8);
687     fits->Print("C");
688     TList* fitter = 0;
689     if (details) { 
690       TFile* hists = 0;
691       TDirectory* savDir = gDirectory;
692       if (!gSystem->AccessPathName(fELossExtra.Data())) {
693         hists = TFile::Open(fELossExtra, "READ");
694         // Info("", "Opened forward_eloss.root -> %p", hists);
695       }
696       if (hists) {
697         TList* fr = static_cast<TList*>(hists->Get("ForwardELossResults"));
698         // Info("", "Got forward results -> %p", fr);
699         if (fr) { 
700           fitter = static_cast<TList*>(fr->FindObject("fmdEnergyFitter"));
701           // Info("", "Got fitter -> %p", fitter);
702         }
703         hists->Close();
704         savDir->cd();
705       }
706       fBody->cd();
707       TLatex* ll = new TLatex(.5,.8, "ESD #rightarrow #Delta-fits"
708                               /* fCanvas->GetTitle() */);
709       ll->SetTextAlign(22);
710       ll->SetTextSize(0.05);
711       ll->SetNDC();
712       ll->Draw();
713       
714       TLatex* l = new TLatex(.5,.8, "");
715       l->SetNDC();
716       l->SetTextSize(0.03);
717       l->SetTextFont(132);
718       l->SetTextAlign(12);
719       l->DrawLatex(0.2, 0.70, "1^{st} page is a summary of fit parameters");
720       l->DrawLatex(0.2, 0.67, "2^{nd} page is a summary of relative errors");
721       l->DrawLatex(0.2, 0.64, "Subsequent pages shows the fitted functions");
722       l->DrawLatex(0.3, 0.60, "Black line is the full fitted function");
723       l->DrawLatex(0.3, 0.57, "Coloured lines are the individual N-mip comp.");
724       //l->DrawLatex(0.3, 0.54, "Full drawn lines correspond to used components");
725       //l->DrawLatex(0.3, 0.51, "Dashed lines correspond to ignored components");
726       l->DrawLatex(0.2, 0.54, "Each component has the form");
727       l->DrawLatex(0.3, 0.49, "f_{n}(x; #Delta, #xi, #sigma') = "
728                    "#int_{-#infty}^{+#infty}d#Delta' "
729                    "landau(x; #Delta', #xi)gaus(#Delta'; #Delta, #sigma')");
730       l->DrawLatex(0.2, 0.44, "The full function is given by");
731       l->DrawLatex(0.3, 0.41, "f_{N}(x; #Delta, #xi, #sigma', #bf{a}) = "
732                  "C #sum_{i=1}^{N} a_{i} "
733                    "f_{i}(x; #Delta_{i}, #xi_{i}, #sigma_{i}')");
734       l->DrawLatex(0.3, 0.35, "#Delta_{i} = i (#Delta_{1} + #xi_{1} log(i))");
735       l->DrawLatex(0.3, 0.32, "#xi_{i} = i #xi_{1}");
736       l->DrawLatex(0.3, 0.29, "#sigma_{i} = #sqrt{i} #sigma_{1}");
737       l->DrawLatex(0.3, 0.26, "#sigma_{n} #dot{=} 0");
738       l->DrawLatex(0.3, 0.23, "#sigma_{i}'^{2} = #sigma^{2}_{n} + #sigma_{i}^{2}");
739       l->DrawLatex(0.3, 0.20, "a_{1} #dot{=} 1");
740       l->DrawLatex(0.3, 0.15, Form("Least quality: %d", fMinQuality));
741       if (fitter) {
742         TObject* refit = fitter->FindObject("refitted");
743         if (refit) l->DrawLatex(0.3, .10, "Refitted distributions");
744       }
745       PrintCanvas("Energy loss fits");
746     }
747
748     fBody->cd();
749     fits->Draw("error");
750     PrintCanvas("Fit overview");
751     if (!details) return;
752
753     //__________________________________________________________________
754     // Draw relative parameter errors 
755     fBody->cd();
756     fits->Draw("relative");
757     PrintCanvas("Relative parameter errors");
758
759     //__________________________________________________________________
760     // Draw all fits individually
761     for (UShort_t d=1; d<=3; d++) { 
762       UShort_t nQ = (d == 1 ? 1 : 2);
763       for (UShort_t q = 0; q < nQ; q++) { 
764         Char_t r = (q == 0 ? 'I' : 'O');
765         TList* dists = 0;
766         TList* resis = 0;
767         if (fitter) { 
768           // Info("", "Fitter: %s", fitter->GetName());
769           TList* dl = 
770             static_cast<TList*>(fitter->FindObject(Form("FMD%d%c",d,r)));
771           // Info("", "Got detector list -> %p", dl);
772           if (dl) { 
773             // Info("", "Detector list: %s", dl->GetName());
774             dists = static_cast<TList*>(dl->FindObject("EDists"));
775             // Info("", "Got distributions -> %p", dists);
776             resis = static_cast<TList*>(dl->FindObject("residuals"));
777           }
778         }
779         
780         printf("FMD%d%c ", d, r);
781         ClearCanvas();
782         TObjArray*  ra = fits->GetRingArray(d, r);
783         if (!ra) continue;
784         DrawELossFits(d, r, ra, dists, resis);
785       }
786     }
787   }
788   /** 
789    * CINT does too much when optimizing on a loop, so we take this out
790    * to force CINT to not optimize the third nested loop.
791    * 
792    * @param d     Detector
793    * @param r     Ring 
794    * @param ra    Ring array 
795    * @param dists Distributions (optional)
796    * @param resis Residuals (optional)   
797    */
798   void DrawELossFits(UShort_t d, Char_t r, TObjArray* ra, 
799                      TList* dists, TList* resis)
800   {
801     Int_t nPad = 6;
802     AliFMDCorrELossFit::ELossFit* fit = 0;
803     TIter next(ra);
804     Int_t i = 0;
805     Int_t j = 0;
806     while ((fit = static_cast<AliFMDCorrELossFit::ELossFit*>(next()))) {
807       j           = i % nPad;
808       Bool_t last = j == nPad-1;
809       if (j == 0) DivideForRings(true, true);
810
811       Bool_t        same    = false;
812       TVirtualPad*  drawPad = fBody->GetPad(j+1);
813       Int_t         subPad  = 0;
814       if (dists) { 
815         // Info("", "Distributions: %s", dists->GetName());
816         TString hName(Form("FMD%d%c_etabin%03d", d,r,fit->GetBin()));
817         TH1* dist = static_cast<TH1*>(dists->FindObject(hName));
818         TH1* resi = 0;
819         if (resis) resi = static_cast<TH1*>(resis->FindObject(hName));
820         // Info("", "Got histogram -> %p", dist);
821         if (resi) { 
822           Bool_t err = resi->GetUniqueID() <= 1;
823           drawPad->SetGridx();
824           if (err) {
825             resi->SetYTitle("#chi^{2}_{bin}=(h-f)^{2}/#delta^{2}h");
826             for (Int_t k=1; k<=resi->GetNbinsX(); k++) { 
827               Double_t c = resi->GetBinContent(k);
828               Double_t e = resi->GetBinError(k);
829               if (e <= 0) continue;
830               c          *= c;
831               c          /= (e*e);
832               resi->SetBinContent(k, c);
833               resi->SetBinError(k, 0);
834             }
835           }
836           drawPad->Divide(1,2,0,0);
837           DrawInPad(drawPad, 2, resi, "HIST", kGridx);
838           subPad = 1;
839           Double_t red = fit->GetNu() > 0 ? fit->GetChi2() / fit->GetNu() : 0;
840           if (red > 0) {
841             drawPad->cd(2);
842             TLine* l = new TLine(resi->GetXaxis()->GetXmin(), red,
843                                  resi->GetXaxis()->GetXmax(), red);
844             l->SetLineWidth(2);
845             l->SetLineStyle(2);
846             l->Draw();
847             TLatex* cltx = new TLatex(0.5, 0.5,
848                                       Form("#chi^{2}/#nu=%6.2f", red));
849             cltx->SetNDC();
850             cltx->SetTextAlign(22);
851             cltx->SetTextFont(42);
852             cltx->SetTextSize(0.07);
853             cltx->Draw();
854             cltx->DrawLatex(0.5,0.4,Form("%g", dist->GetEntries()));
855           }
856         }
857         if (dist) { 
858           // Info("", "Histogram: %s", dist->GetName());
859           DrawInPad(drawPad, subPad, dist, "HIST E", (subPad * kGridx) + kLogy);
860           same = true;    
861         }
862       }
863       // if (same)
864       DrawInPad(drawPad, subPad, fit, 
865                 Form("comp good values legend %s", (same ? "same" : "")),
866                 kLogy);
867       if (fit->GetQuality() < fMinQuality) { 
868         TLatex* ltx = new TLatex(.2, .2, "NOT USED");
869         ltx->SetNDC();
870         ltx->SetTextFont(62);
871         ltx->SetTextColor(kRed+1);
872         ltx->SetTextAngle(30);
873         ltx->SetTextSize(0.2);
874         DrawInPad(fBody, j+1, ltx, "", 0);
875         // ltx->Draw();
876       }
877
878       // else 
879       // DrawInPad(fBody, j+1, fit, "comp good values legend", kLogy);
880       printf(".");
881       
882       if (last) 
883         PrintCanvas(Form("FMD%d%c page %d", d, r, (i/nPad)+1));
884       i++;
885     }
886     j = i % nPad;
887     if (j != 0) 
888       PrintCanvas(Form("FMD%d%c page %d", d, r, (i/nPad)+1));
889     printf(" done\n");
890   }
891
892   /** 
893    * Create an array of per-vertex bin stacks 
894    * 
895    * @param vtxAxis Vertex axis 
896    * 
897    * @return Array of stacks 
898    */
899   TObjArray* CreateVtxStacks(const TAxis& vtxAxis)
900   {
901     // --- Create stacks for summaries ---------------------------------
902     Int_t      nVtx    = vtxAxis.GetNbins();
903     TObjArray* stacks  = new TObjArray(nVtx);
904     for (UShort_t v = 1; v <= nVtx; v++) { 
905       THStack* stack = new THStack(Form("vtx%02d", v),
906                                    Form("%+5.1f<v_{z}<%+5.1f",
907                                         vtxAxis.GetBinLowEdge(v),
908                                         vtxAxis.GetBinUpEdge(v)));
909       stacks->AddAt(stack, v-1);
910     }
911     return stacks;
912   }
913   /** 
914    * Draw the vertex stacks in the canvas 
915    * 
916    * @param stacks Stacks to draw
917    * @param max    Possible maximum of the stacks 
918    * 
919    * @return true on success 
920    */
921   Bool_t DrawVtxStacks(TObjArray* stacks, Double_t max=-1)
922   {
923     if (!stacks) return false;
924     // --- Make summary page -------------------------------------------
925     Int_t nVtx = 10; // stacks->GetEntries();
926
927     fBody->Divide(3, (nVtx+2)/3, 0, 0);
928     Int_t ipad = 0;
929     for (UShort_t v = 1; v <= nVtx; v++) {
930       ipad++;
931     
932       if (ipad == 1 || ipad == 12) ipad++;
933
934       THStack*     stack = static_cast<THStack*>(stacks->At(v-1));
935       if (!stack) { 
936         Error("", "No stack at v=%d", v-1);
937         continue;
938       }
939       TVirtualPad* pad   = fBody->cd(ipad);
940       if (!pad) { 
941         Error("", "No pad at %d", ipad);
942         continue;
943       }
944       pad->SetFillColor(kWhite);
945     
946       if (max > 0) stack->SetMaximum(max);
947       stack->Draw("nostack hist");
948     }
949     return true;
950   }
951
952 };
953
954
955   
956 //
957 // EOF
958 //