1 /**************************************************************************
2 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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.
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.
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"
37 #include "AliRawEventHeaderBase.h"
38 #include "AliFMDDigit.h"
39 #include <TClonesArray.h>
44 #include <TStopwatch.h>
46 #include <TPluginManager.h>
50 //_____________________________________________________________________
51 ClassImp(AliFMDBaseDA)
53 ; // Do not delete - to let Emacs for mat the code
56 //_____________________________________________________________________
58 AliFMDBaseDA::GetStripPath(UShort_t det,
67 // det Detector number
68 // ring Ring identifier
71 // full If true, return full path
75 return Form("%s%sFMD%d%c[%02d,%03d]",
76 (full ? GetSectorPath(det, ring, sec, full) : ""),
77 (full ? "/" : ""), det, ring, sec, str);
79 //_____________________________________________________________________
81 AliFMDBaseDA::GetSectorPath(UShort_t det,
89 // det Detector number
90 // ring Ring identifier
93 // full If true, return full path
97 return Form("%s%sFMD%d%c[%02d]",
98 (full ? GetRingPath(det, ring, full) : ""),
99 (full ? "/" : ""), det, ring, sec);
101 //_____________________________________________________________________
103 AliFMDBaseDA::GetRingPath(UShort_t det,
107 // Get the strip path
110 // det Detector number
111 // ring Ring identifier
114 // full If true, return full path
118 return Form("%s%sFMD%d%c",
119 (full ? GetDetectorPath(det, full) : ""),
120 (full ? "/" : ""), det, ring);
122 //_____________________________________________________________________
124 AliFMDBaseDA::GetDetectorPath(UShort_t det,
127 // Get the strip path
130 // det Detector number
131 // ring Ring identifier
134 // full If true, return full path
138 return Form("%s%sFMD%d",
139 (full ? fDiagnosticsFilename.Data() : ""),
140 (full ? ":/" : ""), det);
143 //_____________________________________________________________________
144 AliFMDBaseDA::AliFMDBaseDA() :
146 fDiagnosticsFilename("diagnosticsHistograms.root"),
149 fSaveHistograms(kFALSE),
150 fMakeSummaries(kFALSE),
160 fSeenDetectors[0] = fSeenDetectors[1] = fSeenDetectors[2] = kFALSE;
161 fDetectorArray.SetOwner();
162 Rotate("conditions.csv", 3);
163 fConditionsFile.open("conditions.csv");
165 //_____________________________________________________________________
166 AliFMDBaseDA::AliFMDBaseDA(const AliFMDBaseDA & baseDA) :
168 fDiagnosticsFilename(baseDA.fDiagnosticsFilename.Data()),
171 fSaveHistograms(baseDA.fSaveHistograms),
172 fMakeSummaries(baseDA.fMakeSummaries),
173 fDetectorArray(baseDA.fDetectorArray),
174 fPulseSize(baseDA.fPulseSize),
175 fPulseLength(baseDA.fPulseLength),
176 fRequiredEvents(baseDA.fRequiredEvents),
177 fCurrentEvent(baseDA.fCurrentEvent),
178 fRunno(baseDA.fRunno),
182 fSeenDetectors[0] = baseDA.fSeenDetectors[0];
183 fSeenDetectors[1] = baseDA.fSeenDetectors[1];
184 fSeenDetectors[2] = baseDA.fSeenDetectors[2];
186 fDetectorArray.SetOwner();
191 //_____________________________________________________________________
192 AliFMDBaseDA::~AliFMDBaseDA()
197 //_____________________________________________________________________
198 Bool_t AliFMDBaseDA::HaveEnough(Int_t nEvents) const
200 return nEvents > GetRequiredEvents();
202 //_____________________________________________________________________
203 UShort_t AliFMDBaseDA::GetProgress(Int_t nEvents) const
205 return UShort_t((nEvents *100)/ GetRequiredEvents());
208 //_____________________________________________________________________
209 void AliFMDBaseDA::Run(AliRawReader* reader)
213 // if (fSaveHistograms)
214 // diagFile = TFile::Open(fDiagnosticsFilename.Data(),"RECREATE");
217 fRunno = reader->GetRunNumber();
219 AliFMDRawReader* fmdReader = new AliFMDRawReader(reader,0);
220 TClonesArray* digitArray = new TClonesArray("AliFMDDigit",0);
222 Bool_t sodread = kFALSE;
224 for(Int_t i=0;i<3;i++) {
225 if (!reader->NextEvent()) {
226 // Read Start-of-Run / Start-of-Files event
227 AliWarning(Form("Failed to read the %d%s event",
228 i+1, (i == 0 ? "st" : (i == 1 ? "nd" : "rd"))));
232 UInt_t eventType = reader->GetType();
233 if(eventType == AliRawEventHeaderBase::kStartOfData ||
234 eventType == AliRawEventHeaderBase::kFormatError) {
236 WriteConditionsData(fmdReader);
243 InitContainer(diagFile);
244 if (AliLog::GetDebugLevel("FMD","") >= 3) {
249 AliWarning("No SOD event detected!");
251 int lastProgress = 0;
253 for(Int_t i = 0; i< 3;i++) fNEventsPerDetector[i] = 0;
255 for(Int_t n = 1; !HaveEnough(n); n++) {
256 if(!reader->NextEvent()) { n--; continue; }
259 fmdReader->ReadAdcs(digitArray);
261 Bool_t seen[] = { false, false, false };
262 for(Int_t i = 0; i<digitArray->GetEntriesFast();i++) {
263 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digitArray->At(i));
264 UShort_t det = digit->Detector();
265 fSeenDetectors[det-1] = true;
270 for(Int_t i = 0; i< 3;i++)
271 if (seen[i]) (fNEventsPerDetector[i])++;
275 int progress = GetProgress(n);
276 if (progress <= lastProgress) continue;
277 lastProgress = progress;
278 std::cout << "Progress: " << lastProgress << " / 100 " << std::endl;
282 AliInfoF("Looped over %d events (%d,%d,%d)",GetCurrentEvent(),
283 fNEventsPerDetector[0],
284 fNEventsPerDetector[1],
285 fNEventsPerDetector[2]);
288 for(UShort_t det=1;det<=3;det++) {
289 if (!fSeenDetectors[det-1]) continue;
290 std::cout << "FMD" << det << std::endl;
291 UShort_t firstRing = (det == 1 ? 1 : 0);
292 for (UShort_t ir = firstRing; ir < 2; ir++) {
293 Char_t ring = (ir == 0 ? 'O' : 'I');
294 UShort_t nsec = (ir == 0 ? 40 : 20);
295 UShort_t nstr = (ir == 0 ? 256 : 512);
297 if (fMakeSummaries) MakeSummary(det, ring);
299 std::cout << " Ring " << ring << ": " << std::flush;
300 for(UShort_t sec =0; sec < nsec; sec++) {
301 for(UShort_t strip = 0; strip < nstr; strip++) {
302 Analyse(det,ring,sec,strip);
304 std::cout << '.' << std::flush;
306 // if(fSaveHistograms)
307 // diagFile->Flush();
308 std::cout << "done" << std::endl;
312 if(fOutputFile.is_open()) {
313 fOutputFile.write("# EOF\n",6);
319 if(fSaveHistograms ) {
320 diagFile = TFile::Open(fDiagnosticsFilename.Data(),"RECREATE");
321 fDetectorArray.Write("FMD", TObject::kSingleKey);
323 AliInfo("Closing diagnostics file - please wait ...");
324 // diagFile->Write();
330 //_____________________________________________________________________
332 void AliFMDBaseDA::InitContainer(TDirectory* diagFile)
334 //Prepare container for diagnostics
335 TDirectory* savDir = gDirectory;
337 for(UShort_t det=1;det<=3;det++) {
338 TObjArray* detArray = new TObjArray(det == 1 ? 1 : 2);
339 detArray->SetOwner();
340 detArray->SetName(GetDetectorPath(det, false));
341 fDetectorArray.AddAtAndExpand(detArray,det);
343 TDirectory* detDir = 0;
346 detDir = diagFile->mkdir(GetDetectorPath(det, kFALSE));
349 UShort_t FirstRing = (det == 1 ? 1 : 0);
350 for (UShort_t ir = FirstRing; ir < 2; ir++) {
351 Char_t ring = (ir == 0 ? 'O' : 'I');
352 UShort_t nsec = (ir == 0 ? 40 : 20);
353 UShort_t nstr = (ir == 0 ? 256 : 512);
354 TObjArray* ringArray = new TObjArray(nsec);
355 ringArray->SetOwner();
356 ringArray->SetName(GetRingPath(det, ring, false));
357 detArray->AddAtAndExpand(ringArray,ir);
360 TDirectory* ringDir = 0;
363 ringDir = detDir->mkdir(GetRingPath(det,ring, kFALSE));
367 for(UShort_t sec =0; sec < nsec; sec++) {
368 TObjArray* sectorArray = new TObjArray(nstr);
369 sectorArray->SetOwner();
370 sectorArray->SetName(GetSectorPath(det, ring, sec, false));
371 ringArray->AddAtAndExpand(sectorArray,sec);
374 TDirectory* secDir = 0;
377 secDir = ringDir->mkdir(GetSectorPath(det, ring, sec, kFALSE));
380 for(UShort_t strip = 0; strip < nstr; strip++) {
383 secDir->mkdir(GetStripPath(det, ring, sec, strip, kFALSE));
385 TObjArray* stripArray = new TObjArray(0);
386 stripArray->SetOwner(true);
387 stripArray->SetName(GetStripPath(det, ring, sec, strip, false));
388 sectorArray->AddAtAndExpand(stripArray, strip);
389 AddChannelContainer(stripArray, det, ring, sec, strip);
391 AddSectorSummary(sectorArray, det, ring, sec, nstr);
398 //_____________________________________________________________________
399 void AliFMDBaseDA::WriteConditionsData(AliFMDRawReader* fmdReader)
401 //Write the conditions data to file
402 AliFMDParameters* pars = AliFMDParameters::Instance();
403 fConditionsFile.write(Form("# %s \n",pars->GetConditionsShuttleID()),14);
405 fConditionsFile << "# This file created from run number " << fRunno
406 << " at " << now.AsString() << std::endl;
408 AliFMDCalibSampleRate* sampleRate = new AliFMDCalibSampleRate();
409 AliFMDCalibStripRange* stripRange = new AliFMDCalibStripRange();
411 fmdReader->ReadSODevent(sampleRate,stripRange,fPulseSize,fPulseLength,
414 sampleRate->WriteToFile(fConditionsFile, fSeenDetectors);
415 stripRange->WriteToFile(fConditionsFile, fSeenDetectors);
422 fConditionsFile.write("# Gain Events \n",15);
424 for(UShort_t det=1; det<=3;det++) {
425 if (!fSeenDetectors[det-1]) {
428 UShort_t firstring = (det == 1 ? 1 : 0);
429 for(UShort_t iring = firstring; iring <=1;iring++) {
430 Char_t ring = (iring == 1 ? 'I' : 'O');
431 for(UShort_t board =0 ; board <=1; board++) {
433 Int_t idx = GetHalfringIndex(det,ring,board);
435 fConditionsFile << det << ','
438 << fPulseLength.At(idx) << "\n";
444 fConditionsFile.write("# Gain Pulse \n",14);
446 for(UShort_t det=1; det<=3;det++) {
447 if (!fSeenDetectors[det-1]) {
450 UShort_t firstring = (det == 1 ? 1 : 0);
451 for(UShort_t iring = firstring; iring <=1;iring++) {
452 Char_t ring = (iring == 1 ? 'I' : 'O');
453 for(UShort_t board =0 ; board <=1; board++) {
455 Int_t idx = GetHalfringIndex(det,ring,board);
457 fConditionsFile << det << ','
460 << fPulseSize.At(idx) << "\n";
465 // sampleRate->WriteToFile(std::cout, fSeenDetectors);
466 // stripRange->WriteToFile(std::cout, fSeenDetectors);
468 if(fConditionsFile.is_open()) {
470 fConditionsFile.write("# EOF\n",6);
471 fConditionsFile.close();
476 //_____________________________________________________________________
477 Int_t AliFMDBaseDA::GetHalfringIndex(UShort_t det, Char_t ring,
478 UShort_t board) const
480 // Get the index corresponding to a half-ring
483 // det Detector number
484 // ring Ring identifier
485 // board Board number
488 // Internal index of the board
489 UShort_t iring = (ring == 'I' ? 1 : 0);
491 Int_t index = (((det-1) << 2) | (iring << 1) | (board << 0));
496 //_____________________________________________________________________
497 void AliFMDBaseDA::Rotate(const char* base, int max) const
500 // Rotate a set of files. base is the basic name of the files.
501 // If the file base.max exists it is removed.
502 // If the file base.n exists (where n < max) it is renamed to
504 // If the file base exists, it is renamed to base.1
507 // base Base name of the files
508 // max Maximum number to keep (minus one for the current).
510 // Note: TSystem::AccessPathName returns false if the condition is
513 // Check if we have base.max, and if so, remove it.
514 TString testName(Form("%s.%d", base, max));
515 if (!gSystem->AccessPathName(testName.Data()))
516 gSystem->Unlink(testName.Data());
518 // Loop down from max-1 to 1 and move files
519 for (int i = max-1; i >= 1; i--) {
520 testName = Form("%s.%d", base, i);
521 if (!gSystem->AccessPathName(testName.Data())) {
522 TString newName(Form("%s.%d", base, i+1));
523 gSystem->Rename(testName.Data(), newName.Data());
527 // If we have the file base, rename it to base.1
528 testName = Form("%s", base);
529 if (!gSystem->AccessPathName(testName.Data())){
530 TString newName(Form("%s.%d", base, 1));
531 gSystem->Rename(testName.Data(), newName.Data());
535 //_____________________________________________________________________
537 AliFMDBaseDA::MakeSummaryHistogram(const char* prefix, const char* title,
538 UShort_t d, Char_t r)
541 // Utility function for defining summary histograms
545 // ring Ring identifier
546 // prefix Histogram prefix
547 // title Histogram title
549 Int_t nX = ((d == 1 || r == 'I' || r == 'i') ? 20 : 40);
550 Int_t nY = ((d == 1 || r == 'I' || r == 'i') ? 512 : 256);
552 TH2* ret = new TH2F(Form("%sFMD%d%c", prefix, d, r),
553 Form("%s for FMD%d%c", title, d, r),
554 nX, -0.5, nX-0.5, nY, -0.5, nY-0.5);
555 ret->SetXTitle("Sector #");
556 ret->SetYTitle("Strip #");
557 ret->SetDirectory(0);
558 // if (!fSummaries) fSummaries = new TObjArray;
563 //_____________________________________________________________________
565 AliFMDBaseDA::GetDetectorArray(UShort_t det)
567 if (det < 1 || det > 3) {
568 AliErrorF("Detector index %d out of bounds", det);
571 return static_cast<TObjArray*>(fDetectorArray.At(det));
573 //_____________________________________________________________________
575 AliFMDBaseDA::GetRingArray(UShort_t det, Char_t ring)
577 Int_t idx = (ring == 'O' || ring == 'o' ? 0 : 1);
578 TObjArray* array = GetDetectorArray(det);
579 if (!array) return 0;
580 array = static_cast<TObjArray*>(array->At(idx));
581 if (!array) AliErrorF("No ring array for FMD%d%c (%d)", det, ring, idx);
584 //_____________________________________________________________________
586 AliFMDBaseDA::GetSectorArray(UShort_t det, Char_t ring, UShort_t sector)
588 TObjArray* array = GetRingArray(det,ring);
589 if (!array) return 0;
590 array = static_cast<TObjArray*>(array->At(sector));
591 if (!array) AliErrorF("No sector array for FMD%d%c[%02d]", det, ring, sector);
594 //_____________________________________________________________________
596 AliFMDBaseDA::GetStripArray(UShort_t det, Char_t ring,
597 UShort_t sector, UShort_t strip)
599 TObjArray* array = GetSectorArray(det,ring,sector);
600 if (!array) return 0;
601 array = static_cast<TObjArray*>(array->At(strip));
602 if (!array) AliErrorF("No strip array for FMD%d%c[%02d,%03d]",
603 det, ring, sector, strip);
607 //=====================================================================
608 AliFMDBaseDA::Runner::Runner()
614 //_____________________________________________________________________
616 AliFMDBaseDA::Runner::AddHandlers()
618 gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
623 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer", "Minuit",
626 "TMinuitMinimizer(const char *)");
627 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer",
629 "ROOT::Math::GSLMinimizer",
631 "GSLMinimizer(const char *)");
632 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer",
634 "ROOT::Math::GSLNLSMinimizer",
635 "MathMore", "GSLNLSMinimizer(int)");
636 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer",
638 "ROOT::Math::GSLSimAnMinimizer",
640 "GSLSimAnMinimizer(int)");
641 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer",
645 "TLinearMinimizer(const char *)");
646 gROOT->GetPluginManager()->AddHandler("ROOT::Math::Minimizer",
650 "TFumiliMinimizer(int)");
652 //_____________________________________________________________________
654 AliFMDBaseDA::Runner::ShowUsage(std::ostream& o, const char* progname)
656 o << "Usage: " << progname << " SOURCE [OPTIONS]\n\n"
658 << " -h,--help Show this help\n"
659 << " -d,--diagnostics[=FILE] Write diagnostics to file\n"
660 << " -D,--debug=LEVEL Set the debug level\n\n"
661 << "SOURCE is one of\n"
662 << " * FILE.raw Raw data file\n"
663 << " * FILE.root ROOT'ified raw data file\n"
664 << " * collection://FILE.root Event list in a ROOT file\n"
665 << " * collection://FILE File containing list of ROOT files\n"
666 << " * ^FMD Monitor source\n"
667 << "There are other options too. Check the AliRawReader docs\n"
671 //_____________________________________________________________________
673 Bool_t ExtractValue(const TString& arg, TString& val)
676 Int_t eq = arg.Index("=");
677 if (eq == kNPOS) return false;
679 val = arg(eq+1, arg.Length()-eq-1);
684 //_____________________________________________________________________
686 AliFMDBaseDA::Runner::Init(int argc, char** argv)
690 // --- Process the command line ------------------------------------
692 Int_t debugLevel = 0;
695 for (int i = 1; i < argc; i++) {
696 TString arg(argv[i]);
697 Bool_t badOption = false;
699 if (arg[0] == '-') { // It's an option
700 if (arg[1] == '-') { // It's a long option
702 if (arg.EqualTo("--help")) help = true;
703 else if (arg.BeginsWith("--debug")) {
704 if (ExtractValue(arg, val))
705 debugLevel = val.Atoi();
707 else if (arg.BeginsWith("--diagnostics")) {
709 if (ExtractValue(arg, val))
712 else badOption = true;
714 else { // Short option
715 TString next(i < argc-1 ? argv[i+1] : "");
717 case 'h': help = true; break;
718 case 'd': fDiag = true;
719 if (!next.IsNull() && next[0] != '-') {
725 if (!next.IsNull() && next[0] != '-') {
726 debugLevel = next.Atoi();
730 default: badOption = true;
734 std::cerr << argv[0] << ": Unknown option " << argv[i]
739 else { // source or compatibility debug level
740 if (source.IsNull()) source = arg;
741 else debugLevel = arg.Atoi();
745 // --- Check if help was requested ---------------------------------
747 ShowUsage(std::cout, argv[0]);
751 // --- Check if we have a source -----------------------------------
752 if (source.IsNull()) {
753 std::cerr << "No source given" << std::endl;
757 // --- Initialize various things -----------------------------------
758 AliFMDParameters::Instance()->Init(kFALSE,0);
760 //This will only work for FDR 1 data. When newer data becomes
761 //available the ! must be removed!
763 AliFMDParameters::Instance()->UseCompleteHeader(old);
765 AliLog::EnableDebug(debugLevel > 0);
766 AliLog::SetModuleDebugLevel("FMD", debugLevel);
768 // --- Make our reader ---------------------------------------------
769 fReader = AliRawReader::Create(source);
771 std::cerr << "Failed to make raw reader for source \"" << source
772 << "\"" << std::endl;
778 //_____________________________________________________________________
780 AliFMDBaseDA::Runner::RunNumber() const
782 if (!fReader) return -1;
783 return fReader->GetRunNumber();
786 //_____________________________________________________________________
788 AliFMDBaseDA::Runner::Exec(AliFMDBaseDA& da)
793 da.SetSaveDiagnostics(fDiag || !fDiagFile.IsNull());
794 if (!fDiagFile.IsNull()) da.SetDiagnosticsFilename(fDiagFile);
803 amore::da::AmoreDA myAmore(amore::da::AmoreDA::kSender);
805 for (UShort_t det = 1; det <= 3; det++) {
806 if (!da.HasSeenDetector(det)) continue;
807 TObject* runNo = new TObject;
808 runNo->SetUniqueID(fReader->GetRunNumber());
809 myAmore.Send(Form("gainRunNoFMD%d", det), runNo);
812 TIter next(&da.GetSummaries());
814 while ((obj = next()))
815 myAmore.Send(obj->GetName(), obj);
818 catch (exception& e) {
819 cerr << "Failed to make AMORE instance: " << e.what() << endl;
829 //_____________________________________________________________________
831 //_____________________________________________________________________