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