2ebb02514d4c3834423ec3e08ca7746f6ff28af8
[u/mrichter/AliRoot.git] / FMD / FMDutil / AliFMDBaseDA.cxx
1  /**************************************************************************
2  * Copyright(c) 2004, 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 /** @file    AliFMDBaseDA.cxx
17     @author  Hans Hjersing Dalsgaard <canute@nbi.dk>
18     @date    Wed Mar 26 11:30:45 2008
19     @brief   Base class for detector algorithms.
20 */
21 //
22 // This is the implementation of the (virtual) base class for the FMD
23 // detector algorithms(DA). It implements the creation of the relevant
24 // containers and handles the loop over the raw data. The derived
25 // classes can control the parameters and action to be taken making
26 // this the base class for the Pedestal, Gain and Physics DA.
27 //
28
29 #include "AliFMDBaseDA.h"
30 #include "AliRawReader.h"
31 #include "AliFMDDigit.h"
32 #include "AliFMDParameters.h"
33 #include "AliFMDRawReader.h"
34 #include "AliFMDCalibSampleRate.h"
35 #include "AliFMDCalibStripRange.h"
36 #include "AliLog.h"
37 #include "AliRawEventHeaderBase.h"
38 #include "AliFMDDigit.h"
39 #include <TClonesArray.h>
40 #include <TFile.h>
41 #include <TDatime.h>
42 #include <TSystem.h>
43 #include <TH2F.h>
44 #include <TStopwatch.h>
45 #include <TROOT.h>
46 #include <TPluginManager.h>
47 #include <iostream>
48 #include <fstream>
49
50 //_____________________________________________________________________
51 ClassImp(AliFMDBaseDA)
52 #if 0 
53 ; // Do not delete  - to let Emacs for mat the code
54 #endif
55
56 //_____________________________________________________________________
57 TString
58 AliFMDBaseDA::GetStripPath(UShort_t det, 
59                            Char_t   ring, 
60                            UShort_t sec, 
61                            UShort_t str, 
62                            Bool_t   full) const
63 {
64   // Get the strip path 
65   // 
66   // Parameters 
67   //     det      Detector number
68   //     ring     Ring identifier 
69   //     sec      Sector number 
70   //     str      Strip number
71   //     full     If true, return full path 
72   // 
73   // Return 
74   //     The path
75   return TString::Format("%s%sFMD%d%c[%02d,%03d]", 
76                          (full ? GetSectorPath(det, ring, sec, full).Data() : ""), 
77                          (full ? "/" : ""), det, ring, sec, str);
78 }
79 //_____________________________________________________________________
80 TString
81 AliFMDBaseDA::GetSectorPath(UShort_t det, 
82                             Char_t   ring, 
83                             UShort_t sec, 
84                             Bool_t   full) const
85 {
86   // Get the strip path 
87   // 
88   // Parameters 
89   //     det      Detector number
90   //     ring     Ring identifier 
91   //     sec      Sector number 
92   //     str      Strip number
93   //     full     If true, return full path 
94   // 
95   // Return 
96   //     The path
97   return TString::Format("%s%sFMD%d%c[%02d]", 
98                          (full ? GetRingPath(det, ring, full).Data() : ""), 
99                          (full ? "/" : ""), det, ring, sec);
100 }
101 //_____________________________________________________________________
102 TString
103 AliFMDBaseDA::GetRingPath(UShort_t det, 
104                           Char_t   ring, 
105                           Bool_t   full) const
106 {
107   // Get the strip path 
108   // 
109   // Parameters 
110   //     det      Detector number
111   //     ring     Ring identifier 
112   //     sec      Sector number 
113   //     str      Strip number
114   //     full     If true, return full path 
115   // 
116   // Return 
117   //     The path
118   return TString::Format("%s%sFMD%d%c", 
119                          (full ? GetDetectorPath(det, full).Data() : ""), 
120                          (full ? "/" : ""), det, ring);
121 }
122 //_____________________________________________________________________
123 TString
124 AliFMDBaseDA::GetDetectorPath(UShort_t det, 
125                               Bool_t   full) const
126 {
127   // Get the strip path 
128   // 
129   // Parameters 
130   //     det      Detector number
131   //     ring     Ring identifier 
132   //     sec      Sector number 
133   //     str      Strip number
134   //     full     If true, return full path 
135   // 
136   // Return 
137   //     The path
138   return TString::Format("%s%sFMD%d", 
139                          (full ? fDiagnosticsFilename.Data() : ""), 
140                          (full ? ":/" : ""), det);
141 }
142
143 //_____________________________________________________________________
144 AliFMDBaseDA::AliFMDBaseDA() : 
145   TNamed(),
146   fDiagnosticsFilename("diagnosticsHistograms.root"),
147   fOutputFile(),
148   fConditionsFile(),
149   fSaveHistograms(kFALSE),
150   fMakeSummaries(kFALSE),
151   fDetectorArray(),
152   fPulseSize(10),
153   fPulseLength(10),
154   fRequiredEvents(0),
155   fCurrentEvent(0), 
156   fRunno(0),
157   fSummaries(0),
158   fAll(false)
159 {
160   //Constructor
161   for(Int_t i = 0; i< 3;i++) {
162     fSeenDetectors[i] = false;
163     fNEventsPerDetector[i] = 0;
164   }
165   fDetectorArray.SetOwner();
166   Rotate("conditions.csv", 3);
167   fConditionsFile.open("conditions.csv");
168 }
169 //_____________________________________________________________________
170 AliFMDBaseDA::AliFMDBaseDA(const AliFMDBaseDA & baseDA) : 
171   TNamed(baseDA),
172   fDiagnosticsFilename(baseDA.fDiagnosticsFilename.Data()),
173   fOutputFile(),
174   fConditionsFile(),
175   fSaveHistograms(baseDA.fSaveHistograms),
176   fMakeSummaries(baseDA.fMakeSummaries),
177   fDetectorArray(baseDA.fDetectorArray),
178   fPulseSize(baseDA.fPulseSize),
179   fPulseLength(baseDA.fPulseLength),
180   fRequiredEvents(baseDA.fRequiredEvents),
181   fCurrentEvent(baseDA.fCurrentEvent),
182   fRunno(baseDA.fRunno),
183   fSummaries(0),
184   fAll(baseDA.fAll)
185 {
186   //Copy constructor
187   for(Int_t i = 0; i< 3;i++) {
188     fSeenDetectors[i] = baseDA.fSeenDetectors[0];
189     fNEventsPerDetector[i] = baseDA.fNEventsPerDetector[i];
190   }
191
192   fDetectorArray.SetOwner();  
193   fDetectorArray.ResetBit(TObject::kMustCleanup);
194   fSummaries.ResetBit(TObject::kMustCleanup);
195   fDetectorArray.ResetBit(TObject::kIsOnHeap);
196   fSummaries.ResetBit(TObject::kIsOnHeap);
197 }
198
199
200 //_____________________________________________________________________
201 AliFMDBaseDA::~AliFMDBaseDA() 
202 {
203   //destructor
204   // fDetectorArray.ls();
205   // fSummaries.ls();
206   // fDetectorArray.SetOwner(false);
207   // fSummaries.SetOwner(false);
208
209 }
210
211 //_____________________________________________________________________
212 Bool_t AliFMDBaseDA::HaveEnough(Int_t nEvents) const
213 {
214   // if (!fAll) return nEvents > GetRequiredEvents();
215   if (nEvents <= 1) return false;
216
217   Bool_t ret = true; // Assume we have it 
218   for (Int_t i = 0; i < 3; i++) { 
219     if (!fSeenDetectors[i]) continue;
220     if (Int_t(fNEventsPerDetector[i]) <= GetRequiredEvents()) ret = false;
221   }
222   return ret;
223 }
224 //_____________________________________________________________________
225 UShort_t AliFMDBaseDA::GetProgress(Int_t nEvents) const
226 {
227   // if (!fAll) 
228   //  return UShort_t((nEvents *100)/ GetRequiredEvents());
229
230   if (nEvents <= 1) return 0;
231
232   Int_t got = 0;
233   Int_t total = 0;
234   for (Int_t i = 0; i < 3; i++) {
235     if (!fSeenDetectors[i]) continue;
236     got   += fNEventsPerDetector[i];
237     total += GetRequiredEvents();
238   }
239   return UShort_t(total > 0 ? (got * 100.) / total : 0);
240 }
241
242 //_____________________________________________________________________
243 void AliFMDBaseDA::Run(AliRawReader* reader, Bool_t isBase) 
244 {
245   //Run the FMD DA
246   TFile* diagFile = 0;
247   // if (fSaveHistograms)
248   //  diagFile = TFile::Open(fDiagnosticsFilename.Data(),"RECREATE");
249   
250   reader->Reset();
251   fRunno = reader->GetRunNumber();
252
253   AliFMDRawReader* fmdReader  = new AliFMDRawReader(reader,0);
254   TClonesArray*    digitArray = new TClonesArray("AliFMDDigit",0);
255   
256   Bool_t sodread = kFALSE;
257   
258   for(Int_t i=0;i<3;i++) {
259     if (!reader->NextEvent()) { 
260       // Read Start-of-Run / Start-of-Files event
261       AliWarning(Form("Failed to read the %d%s event",
262                       i+1, (i == 0 ? "st" : (i == 1 ? "nd" : "rd"))));
263       break;
264     }
265     
266     UInt_t eventType = reader->GetType();
267     if(eventType == AliRawEventHeaderBase::kStartOfData || 
268        eventType == AliRawEventHeaderBase::kFormatError) { 
269       
270       WriteConditionsData(fmdReader);
271       sodread = kTRUE;
272       break;
273     }
274   }
275   if (isBase) return;
276
277   Init();
278   InitContainer(diagFile);
279   if (AliLog::GetDebugLevel("FMD","") >= 3) { 
280     fDetectorArray.ls();
281   }
282   
283   if(!sodread) 
284     AliWarning("No SOD event detected!");
285   
286   int lastProgress = 0;
287
288   for(Int_t i = 0; i< 3;i++) fNEventsPerDetector[i] = 0;
289
290   for(Int_t n = 1; !HaveEnough(n); n++) {
291     AliDebugF(1,"Get the next event %d", n);
292     if(!reader->NextEvent()) { n--; continue; }
293     UInt_t eventType = reader->GetType();
294     AliDebugF(3, "Event type is %d", eventType);
295     if(eventType != AliRawEventHeaderBase::kPhysicsEvent) { n--; continue; }
296
297     Bool_t seen[] = { false, false, false };
298     SetCurrentEvent(n);
299     digitArray->Clear();
300     fmdReader->ReadAdcs(digitArray);
301   
302     for(Int_t i = 0; i<digitArray->GetEntriesFast();i++) {
303       AliFMDDigit* digit = static_cast<AliFMDDigit*>(digitArray->At(i));
304       UShort_t det = digit->Detector();
305       fSeenDetectors[det-1] = true;
306       seen[det-1]           = true;
307
308       // Only fill if we do not have enough for this detector 
309       if (Int_t(fNEventsPerDetector[det-1]) < GetRequiredEvents()) 
310         FillChannels(digit);
311     }
312     for(Int_t i = 0; i< 3;i++) 
313       if (seen[i]) (fNEventsPerDetector[i])++;
314       
315     FinishEvent();
316     
317     Int_t nReq = GetRequiredEvents();
318     AliDebugF(5, "%9d: %6d/%6d %6d/%6d %6d/%6d", n, 
319               fNEventsPerDetector[0], nReq,
320               fNEventsPerDetector[1], nReq,
321               fNEventsPerDetector[2], nReq);
322
323     int progress = GetProgress(n);
324     if (progress <= lastProgress) continue;
325     lastProgress = progress;
326     std::cout << "Progress: " << lastProgress << " / 100 " << std::endl;
327
328     if (AliLog::GetDebugLevel("FMD","") >= 0) { 
329     }
330     
331   }
332   
333   AliInfoF("Looped over %d events (%d,%d,%d)",GetCurrentEvent(),
334            fNEventsPerDetector[0], 
335            fNEventsPerDetector[1], 
336            fNEventsPerDetector[2]);
337   WriteHeaderToFile();
338   
339   for(UShort_t det=1;det<=3;det++) {
340     if (!fSeenDetectors[det-1]) continue;
341     std::cout << "FMD" << det << std::endl;
342     UShort_t firstRing = (det == 1 ? 1 : 0);
343     for (UShort_t ir = firstRing; ir < 2; ir++) {
344       Char_t   ring = (ir == 0 ? 'O' : 'I');
345       UShort_t nsec = (ir == 0 ? 40  : 20);
346       UShort_t nstr = (ir == 0 ? 256 : 512);
347
348       if (fMakeSummaries) MakeSummary(det, ring);
349
350       std::cout << " Ring " << ring << ": " << std::flush;
351       for(UShort_t sec =0; sec < nsec;  sec++)  {
352         for(UShort_t strip = 0; strip < nstr; strip++) {
353           Analyse(det,ring,sec,strip);
354         }
355         std::cout << '.' << std::flush;
356       }
357       // if(fSaveHistograms)
358       // diagFile->Flush();
359       std::cout << "done" << std::endl;
360     }
361   }
362   
363   if(fOutputFile.is_open()) {
364     fOutputFile.write("# EOF\n",6);
365     fOutputFile.close();
366   }
367   
368   Terminate(diagFile);
369     
370   if(fSaveHistograms ) {
371     diagFile = TFile::Open(fDiagnosticsFilename.Data(),"RECREATE");
372     fDetectorArray.Write("FMD", TObject::kSingleKey);
373     fSummaries.Write();
374     AliInfo("Closing diagnostics file - please wait ...");
375     // diagFile->Write();
376     diagFile->Close();
377     AliInfo("done");
378     
379   }
380 }
381 //_____________________________________________________________________
382
383 void AliFMDBaseDA::InitContainer(TDirectory* diagFile)
384 {
385   //Prepare container for diagnostics    
386   TDirectory* savDir   = gDirectory;
387   Bool_t owners = true;
388
389   for(UShort_t det=1;det<=3;det++) {
390     Array* detArray = new Array(det == 1 ? 1 : 2);
391     detArray->SetOwner(owners);
392     detArray->SetName(GetDetectorPath(det, false));
393     fDetectorArray.AddAtAndExpand(detArray,det);
394
395     TDirectory* detDir = 0;
396     if (diagFile) {
397       diagFile->cd();
398       detDir = diagFile->mkdir(GetDetectorPath(det, kFALSE));
399     }
400
401     UShort_t FirstRing = (det == 1 ? 1 : 0);
402     for (UShort_t ir = FirstRing; ir < 2; ir++) {
403       Char_t   ring = (ir == 0 ? 'O' : 'I');
404       UShort_t nsec = (ir == 0 ? 40  : 20);
405       UShort_t nstr = (ir == 0 ? 256 : 512);
406       Array* ringArray = new Array(nsec);
407       ringArray->SetOwner(owners);
408       ringArray->SetName(GetRingPath(det, ring, false));
409       ringArray->ResetBit(TObject::kMustCleanup);
410       detArray->AddAtAndExpand(ringArray,ir);
411
412
413       TDirectory* ringDir = 0;
414       if (detDir) { 
415         detDir->cd();
416         ringDir = detDir->mkdir(GetRingPath(det,ring, kFALSE));
417       }
418       
419
420       for(UShort_t sec =0; sec < nsec;  sec++)  {
421         Array* sectorArray = new Array(nstr);
422         sectorArray->SetOwner(owners);
423         sectorArray->SetName(GetSectorPath(det, ring, sec, false));
424         sectorArray->ResetBit(TObject::kMustCleanup);
425         ringArray->AddAtAndExpand(sectorArray,sec);
426
427
428         TDirectory* secDir = 0;
429         if (ringDir) { 
430           ringDir->cd();
431           secDir = ringDir->mkdir(GetSectorPath(det, ring, sec, kFALSE));
432         }
433         
434         for(UShort_t strip = 0; strip < nstr; strip++) {
435           if (secDir) { 
436             secDir->cd();
437             secDir->mkdir(GetStripPath(det, ring, sec, strip, kFALSE));
438           }
439           Array* stripArray = new Array(0);
440           stripArray->SetOwner(owners);
441           stripArray->SetName(GetStripPath(det, ring, sec, strip, false));
442           stripArray->ResetBit(TObject::kMustCleanup);
443           sectorArray->AddAtAndExpand(stripArray, strip);
444           AddChannelContainer(stripArray, det, ring, sec, strip);
445         }
446         AddSectorSummary(sectorArray, det, ring, sec, nstr);
447       }
448     }
449   }
450   savDir->cd();
451 }
452
453 //_____________________________________________________________________ 
454 void AliFMDBaseDA::WriteConditionsData(AliFMDRawReader* fmdReader) 
455 {
456   //Write the conditions data to file
457   AliFMDParameters* pars       = AliFMDParameters::Instance();
458   fConditionsFile.write(Form("# %s \n",pars->GetConditionsShuttleID()),14);
459   TDatime now;
460   fConditionsFile << "# This file created from run number " << fRunno 
461                   << " at " << now.AsString() << std::endl;
462   
463   AliFMDCalibSampleRate* sampleRate = new AliFMDCalibSampleRate();
464   AliFMDCalibStripRange* stripRange = new AliFMDCalibStripRange();
465   
466   fmdReader->ReadSODevent(sampleRate,stripRange,fPulseSize,fPulseLength,
467                           fSeenDetectors);
468
469   sampleRate->WriteToFile(fConditionsFile, fSeenDetectors);
470   stripRange->WriteToFile(fConditionsFile, fSeenDetectors);
471
472  
473   // Zero Suppresion
474   
475   // Strip Range
476   
477   fConditionsFile.write("# Gain Events \n",15);
478   
479   for(UShort_t det=1; det<=3;det++) {
480     if (!fSeenDetectors[det-1]) { 
481       continue;
482     }
483     UShort_t firstring = (det == 1 ? 1 : 0);
484     for(UShort_t iring = firstring; iring <=1;iring++) {
485       Char_t ring = (iring == 1 ? 'I' : 'O');
486       for(UShort_t board =0 ; board <=1; board++) {
487         
488         Int_t idx = GetHalfringIndex(det,ring,board);
489         
490         fConditionsFile << det                     << ','
491                         << ring                    << ','
492                         << board                   << ','
493                         << fPulseLength.At(idx)    << "\n";
494         
495       }
496     }
497   }
498   
499   fConditionsFile.write("# Gain Pulse \n",14);
500   
501   for(UShort_t det=1; det<=3;det++) {
502     if (!fSeenDetectors[det-1]) { 
503       continue;
504     }
505     UShort_t firstring = (det == 1 ? 1 : 0);
506     for(UShort_t iring = firstring; iring <=1;iring++) {
507       Char_t ring = (iring == 1 ? 'I' : 'O');
508       for(UShort_t board =0 ; board <=1; board++) {
509         
510         Int_t idx = GetHalfringIndex(det,ring,board);
511         
512         fConditionsFile << det                     << ','
513                         << ring                    << ','
514                         << board                   << ','
515                         << fPulseSize.At(idx)      << "\n";
516         
517       }
518     }
519   }
520   // sampleRate->WriteToFile(std::cout, fSeenDetectors);
521   // stripRange->WriteToFile(std::cout, fSeenDetectors);
522
523   if(fConditionsFile.is_open()) {
524     
525     fConditionsFile.write("# EOF\n",6);
526     fConditionsFile.close();
527     
528   }
529   
530 }
531 //_____________________________________________________________________ 
532 Int_t AliFMDBaseDA::GetHalfringIndex(UShort_t det, Char_t ring, 
533                                      UShort_t board) const 
534 {
535   // Get the index corresponding to a half-ring 
536   // 
537   // Parameters: 
538   //   det    Detector number 
539   //   ring   Ring identifier 
540   //   board  Board number 
541   //
542   // Return 
543   //   Internal index of the board 
544   UShort_t iring  =  (ring == 'I' ? 1 : 0);
545   
546   Int_t index = (((det-1) << 2) | (iring << 1) | (board << 0));
547   
548   return index-2;
549   
550 }
551 //_____________________________________________________________________ 
552 void AliFMDBaseDA::Rotate(const char* base, int max) const
553 {
554   // 
555   // Rotate a set of files.   base is the basic name of the files.
556   // If the file base.max exists it is removed. 
557   // If the file base.n exists (where n < max) it is renamed to
558   // base.(n-1).  
559   // If the file base exists, it is renamed to base.1 
560   //
561   // Parameters:
562   //   base Base name of the files
563   //   max  Maximum number to keep (minus one for the current).
564
565   // Note:  TSystem::AccessPathName returns false if the condition is
566   // fulfilled! 
567
568   // Check if we have base.max, and if so, remove it. 
569   TString testName(Form("%s.%d", base, max));
570   if (!gSystem->AccessPathName(testName.Data())) 
571     gSystem->Unlink(testName.Data());
572     
573   // Loop down from max-1 to 1 and move files 
574   for (int i = max-1; i >= 1; i--) { 
575     testName = Form("%s.%d", base, i);
576     if (!gSystem->AccessPathName(testName.Data())) {
577       TString newName(Form("%s.%d", base, i+1));
578       gSystem->Rename(testName.Data(), newName.Data());
579     }
580   }
581
582   // If we have the file base, rename it to base.1 
583   testName = Form("%s", base);
584   if (!gSystem->AccessPathName(testName.Data())){
585     TString newName(Form("%s.%d", base, 1));
586     gSystem->Rename(testName.Data(), newName.Data());
587   }
588 }
589
590 //_____________________________________________________________________ 
591 TH2*
592 AliFMDBaseDA::MakeSummaryHistogram(const char* prefix, const char* title, 
593                                    UShort_t d, Char_t r) 
594 {
595   // 
596   // Utility function for defining summary histograms 
597   // 
598   // Parameters:
599   //    det    Detector 
600   //    ring   Ring identifier 
601   //    prefix Histogram prefix 
602   //    title  Histogram title 
603   //
604   Int_t nX = ((d == 1 || r == 'I' || r == 'i') ?  20 :  40);
605   Int_t nY = ((d == 1 || r == 'I' || r == 'i') ? 512 : 256);
606   
607   TString n = TString::Format("%sFMD%d%c", prefix, d, r);
608   TString t = TString::Format("%s for FMD%d%c", title, d, r);
609   TH2* ret = new TH2F(n, t, nX, -0.5, nX-0.5, nY, -0.5, nY-0.5);
610   ret->SetXTitle("Sector #");
611   ret->SetYTitle("Strip #");
612   ret->SetDirectory(0);
613   // if (!fSummaries) fSummaries = new Array;
614   fSummaries.Add(ret);
615   return ret;
616 }
617
618 //_____________________________________________________________________ 
619 AliFMDBaseDA::Array*
620 AliFMDBaseDA::GetDetectorArray(UShort_t det)
621 {
622   if (det < 1 || det > 3) { 
623     AliErrorF("Detector index %d out of bounds", det);
624     return 0;
625   }
626   return static_cast<Array*>(fDetectorArray.At(det));
627 }
628 //_____________________________________________________________________ 
629 AliFMDBaseDA::Array*
630 AliFMDBaseDA::GetRingArray(UShort_t det, Char_t ring)
631 {
632   Int_t idx = (ring == 'O' || ring == 'o' ? 0 : 1);
633   Array* array = GetDetectorArray(det);
634   if (!array) return 0;
635   array = static_cast<Array*>(array->At(idx));
636   if (!array) AliErrorF("No ring array for FMD%d%c (%d)", det, ring, idx);
637   return array;
638 }
639 //_____________________________________________________________________ 
640 AliFMDBaseDA::Array*
641 AliFMDBaseDA::GetSectorArray(UShort_t det, Char_t ring, UShort_t sector)
642 {
643   Array* array = GetRingArray(det,ring);
644   if (!array) return 0;
645   array = static_cast<Array*>(array->At(sector));
646   if (!array) AliErrorF("No sector array for FMD%d%c[%02d]", det, ring, sector);
647   return array;
648 }
649 //_____________________________________________________________________ 
650 AliFMDBaseDA::Array*
651 AliFMDBaseDA::GetStripArray(UShort_t det, Char_t ring, 
652                             UShort_t sector, UShort_t strip)
653 {
654   Array* array = GetSectorArray(det,ring,sector);
655   if (!array) return 0;
656   array = static_cast<Array*>(array->At(strip));
657   if (!array) AliErrorF("No strip array for FMD%d%c[%02d,%03d]", 
658                         det, ring, sector, strip);
659   return array;
660 }
661
662 //=====================================================================
663 AliFMDBaseDA::Runner::Runner()
664   : fReader(0),
665     fDiagFile(""), 
666     fDiag(false),
667     fAll(false)
668 {}
669
670 //_____________________________________________________________________ 
671 void
672 AliFMDBaseDA::Runner::AddHandlers()
673 {
674   gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
675                                         "*",
676                                         "TStreamerInfo",
677                                         "RIO",
678                                         "TStreamerInfo()");
679   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", "Minuit", 
680                                         "TMinuitMinimizer",
681                                         "Minuit", 
682                                         "TMinuitMinimizer(const char *)");
683   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", 
684                                         "GSLMultiMin", 
685                                         "ROOT::Math::GSLMinimizer",
686                                         "MathMore", 
687                                         "GSLMinimizer(const char *)");
688   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", 
689                                         "GSLMultiFit", 
690                                         "ROOT::Math::GSLNLSMinimizer",
691                                         "MathMore", "GSLNLSMinimizer(int)");
692   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", 
693                                         "GSLSimAn", 
694                                         "ROOT::Math::GSLSimAnMinimizer",
695                                         "MathMore", 
696                                         "GSLSimAnMinimizer(int)");
697   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", 
698                                         "Linear", 
699                                         "TLinearMinimizer",
700                                         "Minuit", 
701                                         "TLinearMinimizer(const char *)");
702   gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", 
703                                         "Fumili", 
704                                         "TFumiliMinimizer",
705                                         "Fumili", 
706                                         "TFumiliMinimizer(int)");
707 }
708 //_____________________________________________________________________ 
709 void
710 AliFMDBaseDA::Runner::ShowUsage(std::ostream& o, const char* progname)
711 {
712   o << "Usage: " << progname << " SOURCE [OPTIONS]\n\n"
713     << "Options:\n"
714     << "   -h,--help                Show this help\n"
715     << "   -d,--diagnostics[=FILE]  Write diagnostics to file\n"
716     << "   -D,--debug=LEVEL         Set the debug level\n"
717     << "   -A,--all                 Try to get data from all detectors\n\n"
718     << "SOURCE is one of\n"
719     << " * FILE.raw                Raw data file\n"
720     << " * FILE.root               ROOT'ified raw data file\n"
721     << " * collection://FILE.root  Event list in a ROOT file\n"
722     << " * collection://FILE       File containing list of ROOT files\n"
723     << " * ^FMD                    Monitor source\n"
724     << "There are other options too.  Check the AliRawReader docs\n"
725     << std::endl;
726 }
727  
728 //_____________________________________________________________________ 
729 namespace {
730   Bool_t ExtractValue(const TString& arg, TString& val)
731   {
732     val = "";
733     Int_t eq = arg.Index("=");
734     if (eq == kNPOS) return false;
735     
736     val = arg(eq+1, arg.Length()-eq-1);
737     return true;
738   }
739 }
740       
741 //_____________________________________________________________________ 
742 Int_t
743 AliFMDBaseDA::Runner::Init(int argc, char** argv)
744 {
745   // AddHandlers();
746
747   // --- Process the command line ------------------------------------
748   TString source;
749   Int_t   debugLevel  = 0;
750   Bool_t  help        = false;
751
752   for (int i = 1; i < argc; i++) { 
753     TString arg(argv[i]);
754     Bool_t  badOption   = false;
755     
756     if (arg[0] == '-') { // It's an option 
757       if (arg[1] == '-') { // It's a long option 
758         TString val;
759         if      (arg.EqualTo("--help"))     help = true; 
760         else if (arg.BeginsWith("--debug")) {
761           if (ExtractValue(arg, val))
762             debugLevel = val.Atoi();
763         }
764         else if (arg.BeginsWith("--diagnostics")) { 
765           fDiag = true;
766           if (ExtractValue(arg, val)) 
767             fDiagFile = val;
768         }
769         else if (arg.EqualTo("--all"))  fAll = true;
770         else badOption = true;
771       }
772       else { // Short option 
773         TString next(i < argc-1 ? argv[i+1] : "");
774         switch (arg[1]) { 
775         case 'h': help = true; break;
776         case 'd': fDiag = true; 
777           if (!next.IsNull() && next[0] != '-') {
778             fDiagFile = next;
779             i++;
780           }
781           break;
782         case 'D': 
783           if (!next.IsNull() && next[0] != '-') {
784             debugLevel = next.Atoi();
785             i++;
786           }
787           break;
788         case 'A': fAll = true ; break ;
789         default: badOption = true;
790         }
791       } // End of options
792       if (badOption) { 
793         std::cerr << argv[0] << ": Unknown option " << argv[i] 
794                   << std::endl;
795         return -1;
796       }
797     }
798     else { // source or compatibility debug level 
799       if (source.IsNull()) source = arg;
800       else                 debugLevel = arg.Atoi();
801     }
802   }
803   
804   // --- Check if help was requested ---------------------------------
805   if (help) { 
806     ShowUsage(std::cout, argv[0]);
807     return 1;
808   }
809
810   // --- Check if we have a source -----------------------------------
811   if (source.IsNull()) { 
812     std::cerr << "No source given" << std::endl;
813     return -2;
814   }
815
816   // --- Initialize various things -----------------------------------
817   AliFMDParameters::Instance()->Init(kFALSE,0);
818
819   //This will only work for FDR 1 data. When newer data becomes
820   //available the ! must be removed!
821   Bool_t old = kTRUE;
822   AliFMDParameters::Instance()->UseCompleteHeader(old);
823   
824   AliLog::EnableDebug(debugLevel > 0);
825   AliLog::SetModuleDebugLevel("FMD", debugLevel);
826
827   // --- Make our reader ---------------------------------------------
828   fReader = AliRawReader::Create(source);
829   if (!fReader) { 
830     std::cerr << "Failed to make raw reader for source \"" << source 
831               << "\"" << std::endl;
832     return -3;
833   }
834   return 0;
835 }
836
837 //_____________________________________________________________________ 
838 Int_t
839 AliFMDBaseDA::Runner::RunNumber() const
840
841   if (!fReader) return -1;
842   return fReader->GetRunNumber(); 
843 }
844
845 //_____________________________________________________________________ 
846 void
847 AliFMDBaseDA::Runner::Exec(AliFMDBaseDA& da)
848 {
849   TStopwatch timer;
850   timer.Start();
851
852   da.SetSaveDiagnostics(fDiag || !fDiagFile.IsNull());
853   da.SetTryAll(fAll);
854   if (!fDiagFile.IsNull()) da.SetDiagnosticsFilename(fDiagFile);
855
856   da.Run(fReader);
857
858   timer.Stop();
859   timer.Print();
860 }
861
862 #if 0
863 AliFMDBaseDA::_Array::~_Array()
864 {
865   // Printf("Deleting %s (%p)", this->GetName(), this);
866   // SetOwner(false);
867   // Clear();
868 }
869 #endif
870   
871   
872 //_____________________________________________________________________ 
873
874 //_____________________________________________________________________ 
875 //
876 // EOF
877 //
878