LCOV - code coverage report
Current view: top level - EMCAL/EMCALbase - AliCaloCalibSignal.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 431 0.2 %
Date: 2016-06-14 17:26:59 Functions: 1 22 4.5 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : /* $Id: AliCaloCalibSignal.cxx $ */
      16             : 
      17             : //________________________________________________________________________
      18             : //
      19             : // A help class for monitoring and calibration tools: MOOD, AMORE etc.,
      20             : // It can be created and used a la (ctor):
      21             : /*
      22             :   //Create the object for making the histograms
      23             :   fSignals = new AliCaloCalibSignal( fDetType );
      24             :   // AliCaloCalibSignal knows how many modules we have for PHOS or EMCAL
      25             :   fNumModules = fSignals->GetModules();
      26             : */
      27             : // fed an event:
      28             : //  fSignals->ProcessEvent(fCaloRawStream,fRawEventHeaderBase);
      29             : // get some info:
      30             : //  fSignals->GetXXX..()
      31             : // etc.
      32             : //________________________________________________________________________
      33             : #include <string>
      34             : #include <sstream>
      35             : #include <fstream>
      36             : 
      37             : #include "TProfile.h"
      38             : #include "TFile.h"
      39             : 
      40             : #include "AliRawReader.h"
      41             : #include "AliCaloRawStreamV3.h"
      42             : 
      43             : #include "AliCaloConstants.h"
      44             : #include "AliCaloBunchInfo.h"
      45             : #include "AliCaloFitResults.h"
      46             : #include "AliCaloRawAnalyzer.h"
      47             : #include "AliCaloRawAnalyzerFactory.h"
      48             : 
      49             : //The include file
      50             : #include "AliCaloCalibSignal.h"
      51             : #include "AliDAQ.h"
      52             : 
      53          42 : ClassImp(AliCaloCalibSignal)
      54             : 
      55             : using namespace std;
      56             : 
      57             : // variables for TTree filling; not sure if they should be static or not
      58             : static int fChannelNum = 0; // for regular towers
      59             : static int fRefNum = 0; // for LED
      60             : static double fAmp = 0;
      61             : static double fAvgAmp = 0;
      62             : static double fRMS = 0;
      63             : 
      64             : // ctor; initialize everything in order to avoid compiler warnings
      65             : // put some reasonable defaults
      66             : AliCaloCalibSignal::AliCaloCalibSignal(kDetType detectorType) :  
      67           0 :   TObject(),
      68           0 :   fDetType(kNone),
      69           0 :   fColumns(0),
      70           0 :   fRows(0),
      71           0 :   fLEDRefs(0),
      72           0 :   fModules(0),
      73           0 :   fCaloString(),
      74           0 :   fMapping(NULL),
      75           0 :   fFittingAlgorithm(0),  
      76           0 :   fRawAnalyzer(0),
      77           0 :   fRunNumber(-1),
      78           0 :   fStartTime(0),
      79           0 :   fAmpCut(40), // min. 40 ADC counts as default
      80           0 :   fReqFractionAboveAmpCutVal(0.6), // 60% in a strip, per default
      81           0 :   fReqFractionAboveAmp(kTRUE),
      82           0 :   fAmpCutLEDRef(100), // min. 100 ADC counts as default
      83           0 :   fReqLEDRefAboveAmpCutVal(kTRUE),
      84           0 :   fHour(0),
      85           0 :   fLatestHour(0),
      86           0 :   fUseAverage(kTRUE),
      87           0 :   fSecInAverage(1800), 
      88           0 :   fDownscale(10), 
      89           0 :   fNEvents(0),
      90           0 :   fNAcceptedEvents(0),
      91           0 :   fTreeAmpVsTime(NULL),
      92           0 :   fTreeAvgAmpVsTime(NULL),
      93           0 :   fTreeLEDAmpVsTime(NULL),
      94           0 :   fTreeLEDAvgAmpVsTime(NULL)
      95           0 : {
      96             :   //Default constructor. First we set the detector-type related constants.
      97           0 :   if (detectorType == kPhos) {
      98           0 :     fColumns = fgkPhosCols;
      99           0 :     fRows = fgkPhosRows;
     100           0 :     fLEDRefs = fgkPhosLEDRefs;
     101           0 :     fModules = fgkPhosModules;
     102           0 :     fCaloString = "PHOS";
     103             :   } 
     104             :   else {
     105             :     //We'll just trust the enum to keep everything in line, so that if detectorType
     106             :     //isn't kPhos then it is kEmCal. Note, however, that this is not necessarily the
     107             :     //case, if someone intentionally gives another number
     108           0 :     fColumns = AliEMCALGeoParams::fgkEMCALCols;
     109           0 :     fRows = AliEMCALGeoParams::fgkEMCALRows;
     110           0 :     fLEDRefs = AliEMCALGeoParams::fgkEMCALLEDRefs;
     111           0 :     fModules = 20; // AliEMCALGeoParams::fgkEMCALModules is set to a higher number due to simulation constraints...
     112           0 :     fCaloString = "EMCAL";
     113             :   }
     114             : 
     115           0 :   fDetType = detectorType;
     116           0 :   SetFittingAlgorithm(Algo::kStandard);
     117           0 :   ResetInfo(); // trees and counters
     118           0 : } 
     119             : 
     120             : // dtor
     121             : //_____________________________________________________________________
     122             : AliCaloCalibSignal::~AliCaloCalibSignal()
     123           0 : {
     124           0 :   DeleteTrees();
     125           0 : }
     126             : 
     127             : //_____________________________________________________________________
     128             : void AliCaloCalibSignal::DeleteTrees()
     129             : {
     130             :   // delete what was created in the ctor (TTrees)
     131           0 :   if (fTreeAmpVsTime) delete fTreeAmpVsTime;
     132           0 :   if (fTreeAvgAmpVsTime) delete fTreeAvgAmpVsTime;
     133           0 :   if (fTreeLEDAmpVsTime) delete fTreeLEDAmpVsTime;
     134           0 :   if (fTreeLEDAvgAmpVsTime) delete fTreeLEDAvgAmpVsTime;
     135             :   // and reset pointers
     136           0 :   fTreeAmpVsTime = NULL;
     137           0 :   fTreeAvgAmpVsTime = NULL;
     138           0 :   fTreeLEDAmpVsTime = NULL;
     139           0 :   fTreeLEDAvgAmpVsTime = NULL;
     140             : 
     141           0 :   return;
     142             : }
     143             : 
     144             : // copy ctor
     145             : //_____________________________________________________________________
     146             : //AliCaloCalibSignal::AliCaloCalibSignal(const AliCaloCalibSignal &sig) :
     147             : //  TObject(sig),
     148             : //  fDetType(sig.GetDetectorType()),
     149             : //  fColumns(sig.GetColumns()),
     150             : //  fRows(sig.GetRows()),
     151             : //  fLEDRefs(sig.GetLEDRefs()),
     152             : //  fModules(sig.GetModules()),
     153             : //  fCaloString(sig.GetCaloString()),
     154             : //  fMapping(), //! note that we are not copying the map info
     155             : //  fRunNumber(sig.GetRunNumber()),
     156             : //  fStartTime(sig.GetStartTime()),
     157             : //  fAmpCut(sig.GetAmpCut()),
     158             : //  fReqFractionAboveAmpCutVal(sig.GetReqFractionAboveAmpCutVal()),
     159             : //  fReqFractionAboveAmp(sig.GetReqFractionAboveAmp()),
     160             : //  fAmpCutLEDRef(sig.GetAmpCutLEDRef()),
     161             : //  fReqLEDRefAboveAmpCutVal(sig.GetReqLEDRefAboveAmpCutVal()),
     162             : //  fHour(sig.GetHour()),
     163             : //  fLatestHour(sig.GetLatestHour()),
     164             : //  fUseAverage(sig.GetUseAverage()),
     165             : //  fSecInAverage(sig.GetSecInAverage()),
     166             : //  fDownscale(sig.GetDownscale()),
     167             : //  fNEvents(sig.GetNEvents()),
     168             : //  fNAcceptedEvents(sig.GetNAcceptedEvents()),
     169             : //  fTreeAmpVsTime(),
     170             : //  fTreeAvgAmpVsTime(),
     171             : //  fTreeLEDAmpVsTime(),
     172             : //  fTreeLEDAvgAmpVsTime()
     173             : //{
     174             : //  // also the TTree contents
     175             : //  AddInfo(&sig);
     176             : //  for (Int_t i = 0; i<fgkMaxTowers; i++) {
     177             : //      fNHighGain[i] = sig.fNHighGain[i];
     178             : //      fNLowGain[i]  = sig.fNLowGain[i]; 
     179             : //  }
     180             : //  for (Int_t i = 0; i<(2*fgkMaxRefs); i++) {
     181             : //    fNRef[i] = sig.fNRef[i]; 
     182             : //  }
     183             : //  
     184             : //  
     185             : //}
     186             : //
     187             : // assignment operator; use copy ctor to make life easy..
     188             : //_____________________________________________________________________
     189             : //AliCaloCalibSignal& AliCaloCalibSignal::operator = (const AliCaloCalibSignal &source)
     190             : //{
     191             : //  // assignment operator; use copy ctor
     192             : //  if (&source == this) return *this;
     193             : //
     194             : //  new (this) AliCaloCalibSignal(source);
     195             : //  return *this;
     196             : //}
     197             : 
     198             : //_____________________________________________________________________
     199             : void AliCaloCalibSignal::CreateTrees()
     200             : {
     201             :   // initialize trees
     202             :   // first, regular version
     203           0 :   fTreeAmpVsTime = new TTree("fTreeAmpVsTime","Amplitude vs. Time Tree Variables");
     204             : 
     205           0 :   fTreeAmpVsTime->Branch("fChannelNum", &fChannelNum, "fChannelNum/I");
     206           0 :   fTreeAmpVsTime->Branch("fHour", &fHour, "fHour/D");
     207           0 :   fTreeAmpVsTime->Branch("fAmp", &fAmp, "fAmp/D");
     208             : 
     209             :   // then, average version
     210           0 :   fTreeAvgAmpVsTime = new TTree("fTreeAvgAmpVsTime","Average Amplitude vs. Time Tree Variables");
     211             : 
     212           0 :   fTreeAvgAmpVsTime->Branch("fChannelNum", &fChannelNum, "fChannelNum/I");
     213           0 :   fTreeAvgAmpVsTime->Branch("fHour", &fHour, "fHour/D");
     214           0 :   fTreeAvgAmpVsTime->Branch("fAvgAmp", &fAvgAmp, "fAvgAmp/D");
     215           0 :   fTreeAvgAmpVsTime->Branch("fRMS", &fRMS, "fRMS/D");
     216             : 
     217             :   // then same for LED..
     218           0 :   fTreeLEDAmpVsTime = new TTree("fTreeLEDAmpVsTime","LED Amplitude vs. Time Tree Variables");
     219           0 :   fTreeLEDAmpVsTime->Branch("fRefNum", &fRefNum, "fRefNum/I");
     220           0 :   fTreeLEDAmpVsTime->Branch("fHour", &fHour, "fHour/D");
     221           0 :   fTreeLEDAmpVsTime->Branch("fAmp", &fAmp, "fAmp/D");
     222             : 
     223           0 :   fTreeLEDAvgAmpVsTime = new TTree("fTreeLEDAvgAmpVsTime","Average LED Amplitude vs. Time Tree Variables");
     224           0 :   fTreeLEDAvgAmpVsTime->Branch("fRefNum", &fRefNum, "fRefNum/I");
     225           0 :   fTreeLEDAvgAmpVsTime->Branch("fHour", &fHour, "fHour/D");
     226           0 :   fTreeLEDAvgAmpVsTime->Branch("fAvgAmp", &fAvgAmp, "fAvgAmp/D");
     227           0 :   fTreeLEDAvgAmpVsTime->Branch("fRMS", &fRMS, "fRMS/D");
     228             : 
     229           0 :   return;
     230           0 : }
     231             : 
     232             : //_____________________________________________________________________
     233             : void AliCaloCalibSignal::ResetInfo()
     234             : { // reset trees and counters
     235           0 :   Zero(); // set all counters to 0
     236           0 :   DeleteTrees(); // delete previous stuff
     237           0 :   CreateTrees(); // and create some new ones
     238           0 :   return;
     239             : }
     240             : 
     241             : //_____________________________________________________________________
     242             : void AliCaloCalibSignal::Zero()
     243             : {
     244             :   // set all counters to 0; not cuts etc. though
     245           0 :   fHour = 0;
     246           0 :   fLatestHour = 0;
     247           0 :   fNEvents = 0;
     248           0 :   fNAcceptedEvents = 0;
     249             : 
     250             :   // Set the number of points for each tower: Amp vs. Time
     251           0 :   memset(fNHighGain, 0, sizeof(fNHighGain));
     252           0 :   memset(fNLowGain, 0, sizeof(fNLowGain));
     253             :   // and LED reference
     254           0 :   memset(fNRef, 0, sizeof(fNRef));
     255             : 
     256           0 :   return;
     257             : }
     258             : 
     259             : //_____________________________________________________________________
     260             : Bool_t AliCaloCalibSignal::CheckFractionAboveAmp(const int *iAmpVal, 
     261             :                                                  int resultArray[]) const
     262             : { // check fraction of towers, per column, that are above amplitude cut
     263             :   Bool_t returnCode = false;
     264             :     
     265             :   int iTowerNum = 0;
     266             :   double fraction = 0;
     267           0 :   for (int i = 0; i<fModules; i++) {
     268           0 :     for (int j = 0; j<fColumns; j++) {
     269             :       int nAbove = 0;
     270           0 :       for (int k = 0; k<fRows; k++) {
     271           0 :         iTowerNum = GetTowerNum(i,j,k);
     272           0 :         if (iAmpVal[iTowerNum] > fAmpCut) { 
     273           0 :           nAbove++;
     274           0 :         }
     275             :       }
     276           0 :       resultArray[i*fColumns +j] = 0; // init. to denied
     277           0 :       if (nAbove > 0) {
     278           0 :         fraction = (1.0*nAbove) / fRows;
     279             :         /*
     280             :         printf("DS mod %d col %d nAbove %d fraction %3.2f\n",
     281             :                i, j, nAbove, fraction);
     282             :         */
     283           0 :         if (fraction > fReqFractionAboveAmpCutVal) {
     284           0 :           resultArray[i*fColumns + j] = nAbove;
     285             :           returnCode = true;
     286           0 :         }  
     287             :       }
     288             :     }
     289             :   } // modules loop
     290             :   
     291           0 :   return returnCode;
     292             : }
     293             : 
     294             : 
     295             : //_____________________________________________________________________
     296             : Bool_t AliCaloCalibSignal::CheckLEDRefAboveAmp(const int *iAmpVal, 
     297             :                                                int resultArray[]) const
     298             : { // check which LEDRef/Mon strips are above amplitude cut
     299             :   Bool_t returnCode = false;
     300             :     
     301             :   int iRefNum = 0;
     302             :   int gain = 1; // look at high gain; this should be rather saturated usually..
     303           0 :   for (int i = 0; i<fModules; i++) {
     304           0 :     for (int j = 0; j<fLEDRefs; j++) {
     305           0 :       iRefNum = GetRefNum(i, j, gain);
     306           0 :       if (iAmpVal[iRefNum] > fAmpCutLEDRef) { 
     307           0 :         resultArray[i*fLEDRefs +j] = 1; // enough signal
     308             :         returnCode = true;
     309           0 :       }
     310             :       else {
     311           0 :         resultArray[i*fLEDRefs +j] = 0; // not enough signal
     312             :       }
     313             :       
     314             :       /*
     315             :       printf("DS mod %d LEDRef %d ampVal %d\n",
     316             :              i, j, iAmpVal[iRefNum]);
     317             :       */
     318             :     } // LEDRefs
     319             :   } // modules loop
     320             :   
     321           0 :   return returnCode;
     322             : }
     323             : 
     324             : // Parameter/cut handling
     325             : //_____________________________________________________________________
     326             : void AliCaloCalibSignal::SetParametersFromFile(const char *parameterFile)
     327             : { // set parameters from file
     328           0 :   static const string delimitor("::");
     329             :         
     330             :   // open, check input file
     331           0 :   ifstream in( parameterFile );
     332           0 :   if( !in ) {
     333           0 :     printf("in AliCaloCalibSignal::SetParametersFromFile - Using default/run_time parameters.\n");
     334           0 :     return;
     335             :   } 
     336             : 
     337             :   // Note: this method is a bit more complicated than it really has to be
     338             :   // - allowing for multiple entries per line, arbitrary order of the
     339             :   // different variables etc. But I wanted to try and do this in as
     340             :   // correct a C++ way as I could (as an exercise).
     341             : 
     342             :   // read in
     343           0 :   char readline[1024];
     344           0 :   while ((in.rdstate() & ios::failbit) == 0 ) {
     345             :     
     346             :     // Read into the raw char array and then construct a string
     347             :     // to do the searching
     348           0 :     in.getline(readline, 1024);
     349           0 :     istringstream s(readline);          
     350             :                 
     351           0 :     while ( ( s.rdstate() & ios::failbit ) == 0 ) {
     352             :                         
     353           0 :       string keyValue; 
     354           0 :       s >> keyValue;
     355             :       
     356             :       // check stream status
     357           0 :       if( ( s.rdstate() & ios::failbit ) == ios::failbit ) break;
     358             :                         
     359             :       // skip rest of line if comments found
     360           0 :       if( keyValue.substr( 0, 2 ) == "//" ) break;
     361             :                         
     362             :       // look for "::" in keyValue pair
     363           0 :       size_t position = keyValue.find( delimitor );
     364           0 :       if( position == string::npos ) {
     365           0 :         printf("wrong format for key::value pair: %s\n", keyValue.c_str());
     366             :       }
     367             :                                 
     368             :       // split keyValue pair
     369           0 :       string key( keyValue.substr( 0, position ) );
     370           0 :       string value( keyValue.substr( position+delimitor.size(), 
     371           0 :                                       keyValue.size()-delimitor.size() ) );
     372             :                         
     373             :       // check value does not contain a new delimitor
     374           0 :       if( value.find( delimitor ) != string::npos ) {
     375           0 :         printf("wrong format for key::value pair: %s\n", keyValue.c_str());
     376             :       }
     377             :       
     378             :       // debug: check key value pair
     379             :       // printf("AliCaloCalibSignal::SetParametersFromFile - key %s value %s\n", key.c_str(), value.c_str());
     380             : 
     381             :       // if the key matches with something we expect, we assign the new value
     382           0 :       if ( (key == "fAmpCut") || (key == "fReqFractionAboveAmpCutVal") ||
     383           0 :            (key == "fAmpCutLEDRef") || (key == "fSecInAverage") || 
     384           0 :            (key == "fFittingAlgorithm") || (key == "fDownscale") ) {
     385           0 :         istringstream iss(value);
     386           0 :         printf("AliCaloCalibSignal::SetParametersFromFile - key %s value %s\n", key.c_str(), value.c_str());
     387             : 
     388           0 :         if (key == "fAmpCut") { 
     389           0 :           iss >> fAmpCut; 
     390             :         }
     391           0 :         else if (key == "fReqFractionAboveAmpCutVal") { 
     392           0 :           iss >> fReqFractionAboveAmpCutVal; 
     393             :         }
     394           0 :         else if (key == "fAmpCutLEDRef") { 
     395           0 :           iss >> fAmpCutLEDRef; 
     396             :         }
     397           0 :         else if (key == "fSecInAverage") { 
     398           0 :           iss >> fSecInAverage; 
     399             :         }
     400           0 :         else if (key == "fFittingAlgorithm") { 
     401           0 :           iss >> fFittingAlgorithm;
     402           0 :           SetFittingAlgorithm( fFittingAlgorithm );
     403             :         }
     404           0 :         else if (key == "fDownscale") { 
     405           0 :           iss >> fDownscale; 
     406             :         }
     407           0 :       } // some match found/expected
     408             : 
     409           0 :     }           
     410           0 :   }
     411             : 
     412           0 :   in.close();
     413             :   return;       
     414           0 : }
     415             : 
     416             : //_____________________________________________________________________
     417             : void AliCaloCalibSignal::WriteParametersToFile(const char *parameterFile)
     418             : { // write parameters to file
     419           0 :   static const string delimitor("::");
     420           0 :   ofstream out( parameterFile );
     421           0 :   out << "// " << parameterFile << endl;
     422           0 :   out << "fAmpCut" << "::" << fAmpCut << endl;
     423           0 :   out << "fReqFractionAboveAmpCutVal" << "::" << fReqFractionAboveAmpCutVal << endl;
     424           0 :   out << "fAmpCutLEDRef" << "::" << fAmpCutLEDRef << endl;
     425           0 :   out << "fSecInAverage" << "::" << fSecInAverage << endl;
     426           0 :   out << "fFittingAlgorithm" << "::" << fFittingAlgorithm << endl;
     427           0 :   out << "fDownscale" << "::" << fDownscale << endl;
     428             : 
     429           0 :   out.close();
     430             :   return;
     431           0 : }
     432             : 
     433             : //_____________________________________________________________________
     434             : void AliCaloCalibSignal::SetFittingAlgorithm(Int_t fitAlgo)              
     435             : { // select which fitting algo should be used
     436           0 :   fFittingAlgorithm = fitAlgo;
     437           0 :   delete fRawAnalyzer; // delete doesn't do anything if the pointer is 0x0
     438           0 :   fRawAnalyzer = AliCaloRawAnalyzerFactory::CreateAnalyzer( fitAlgo );
     439           0 :   fRawAnalyzer->SetIsZeroSuppressed(true); // TMP - should use stream->IsZeroSuppressed(), or altro cfg registers later
     440           0 : }
     441             : 
     442             : //_____________________________________________________________________
     443             : Bool_t AliCaloCalibSignal::AddInfo(const AliCaloCalibSignal *sig)
     444             : { 
     445             :   // note/FIXME: we are not yet adding correctly the info for fN{HighGain,LowGain,Ref} here - but consider this a feature for now (20080905): we'll do Analyze() unless entries were found for a tower in this original object.
     446             : 
     447             :   // add info from sig's TTrees to ours..
     448           0 :   TTree *sigAmp = sig->GetTreeAmpVsTime();
     449           0 :   TTree *sigAvgAmp = sig->GetTreeAvgAmpVsTime();
     450             : 
     451             :   // we could try some merging via TList or what also as a more elegant approach
     452             :   // but I wanted with the stupid/simple and hopefully safe approach of looping
     453             :   // over what we want to add..
     454             : 
     455             :   // associate variables for sigAmp and sigAvgAmp:
     456           0 :   sigAmp->SetBranchAddress("fChannelNum",&fChannelNum);
     457           0 :   sigAmp->SetBranchAddress("fHour",&fHour);
     458           0 :   sigAmp->SetBranchAddress("fAmp",&fAmp);
     459             : 
     460             :   // loop over the trees.. note that since we use the same variables we should not need
     461             :   // to do any assignments between the getting and filling
     462           0 :   for (int i=0; i<sigAmp->GetEntries(); i++) {
     463           0 :     sigAmp->GetEntry(i);
     464           0 :     fTreeAmpVsTime->Fill();
     465             :   }
     466             : 
     467           0 :   sigAvgAmp->SetBranchAddress("fChannelNum",&fChannelNum);
     468           0 :   sigAvgAmp->SetBranchAddress("fHour",&fHour);
     469           0 :   sigAvgAmp->SetBranchAddress("fAvgAmp",&fAvgAmp);
     470           0 :   sigAvgAmp->SetBranchAddress("fRMS",&fRMS);
     471             : 
     472           0 :   for (int i=0; i<sigAvgAmp->GetEntries(); i++) {
     473           0 :     sigAvgAmp->GetEntry(i);
     474           0 :     fTreeAvgAmpVsTime->Fill();
     475             :   }
     476             : 
     477             :   // also LED.. 
     478           0 :   TTree *sigLEDAmp = sig->GetTreeLEDAmpVsTime();
     479           0 :   TTree *sigLEDAvgAmp = sig->GetTreeLEDAvgAmpVsTime();
     480             : 
     481             :   // associate variables for sigAmp and sigAvgAmp:
     482           0 :   sigLEDAmp->SetBranchAddress("fRefNum",&fRefNum);
     483           0 :   sigLEDAmp->SetBranchAddress("fHour",&fHour);
     484           0 :   sigLEDAmp->SetBranchAddress("fAmp",&fAmp);
     485             : 
     486             :   // loop over the trees.. note that since we use the same variables we should not need
     487             :   // to do any assignments between the getting and filling
     488           0 :   for (int i=0; i<sigLEDAmp->GetEntries(); i++) {
     489           0 :     sigLEDAmp->GetEntry(i);
     490           0 :     fTreeLEDAmpVsTime->Fill();
     491             :   }
     492             : 
     493           0 :   sigLEDAvgAmp->SetBranchAddress("fRefNum",&fRefNum);
     494           0 :   sigLEDAvgAmp->SetBranchAddress("fHour",&fHour);
     495           0 :   sigLEDAvgAmp->SetBranchAddress("fAvgAmp",&fAvgAmp);
     496           0 :   sigLEDAvgAmp->SetBranchAddress("fRMS",&fRMS);
     497             : 
     498           0 :   for (int i=0; i<sigLEDAvgAmp->GetEntries(); i++) {
     499           0 :     sigLEDAvgAmp->GetEntry(i);
     500           0 :     fTreeLEDAvgAmpVsTime->Fill();
     501             :   }
     502             : 
     503             :   // We should also copy other pieces of info: counters and parameters 
     504             :   // (not number of columns and rows etc which should be the same)
     505             :   // note that I just assign them here rather than Add them, but we
     506             :   // normally just Add (e.g. in Preprocessor) one object so this should be fine.
     507           0 :   fRunNumber = sig->GetRunNumber();
     508           0 :   fStartTime = sig->GetStartTime();
     509           0 :   fAmpCut = sig->GetAmpCut();
     510           0 :   fReqFractionAboveAmpCutVal = sig->GetReqFractionAboveAmpCutVal();
     511           0 :   fReqFractionAboveAmp = sig->GetReqFractionAboveAmp();
     512           0 :   fAmpCutLEDRef = sig->GetAmpCutLEDRef();
     513           0 :   fReqLEDRefAboveAmpCutVal = sig->GetReqLEDRefAboveAmpCutVal();
     514           0 :   fHour = sig->GetHour();
     515           0 :   fLatestHour = sig->GetLatestHour();
     516           0 :   fUseAverage = sig->GetUseAverage();
     517           0 :   fSecInAverage = sig->GetSecInAverage();
     518           0 :   fDownscale = sig->GetDownscale();
     519           0 :   fNEvents = sig->GetNEvents();
     520           0 :   fNAcceptedEvents = sig->GetNAcceptedEvents();
     521             : 
     522           0 :   return kTRUE;//We hopefully succesfully added info from the supplied object
     523             : }
     524             : 
     525             : //_____________________________________________________________________
     526             : Bool_t AliCaloCalibSignal::ProcessEvent(AliRawReader *rawReader)
     527             : {
     528             :   // if fMapping is NULL the rawstream will crate its own mapping
     529           0 :   AliCaloRawStreamV3 rawStream(rawReader, fCaloString, (AliAltroMapping**)fMapping);  
     530           0 :   if (fDetType == kEmCal) {
     531           0 :     rawReader->Select("EMCAL",0,AliDAQ::GetFirstSTUDDL()-1) ; //select EMCAL DDL range 
     532             :   }
     533             : 
     534           0 :   return ProcessEvent( &rawStream, rawReader->GetTimestamp() );
     535           0 : }
     536             : 
     537             : //_____________________________________________________________________
     538             : Bool_t AliCaloCalibSignal::ProcessEvent(AliCaloRawStreamV3 *in, UInt_t Timestamp)
     539             : { 
     540             :   // Method to process=analyze one event in the data stream
     541           0 :   if (!in) return kFALSE; //Return right away if there's a null pointer
     542             :   
     543           0 :   fNEvents++; // one more event
     544             : 
     545           0 :   if ( (fNEvents%fDownscale)!=0 ) return kFALSE; // mechanism to skip some of the input events, if we want
     546             : 
     547             :   // use maximum numbers to set array sizes
     548           0 :   int iAmpValHighGain[fgkMaxTowers];
     549           0 :   int iAmpValLowGain[fgkMaxTowers];
     550           0 :   memset(iAmpValHighGain, 0, sizeof(iAmpValHighGain));
     551           0 :   memset(iAmpValLowGain, 0, sizeof(iAmpValLowGain));
     552             : 
     553             :   // also for LED reference
     554           0 :   int iLEDAmpVal[fgkMaxRefs * 2]; // factor 2 is for the two gain values
     555           0 :   memset(iLEDAmpVal, 0, sizeof(iLEDAmpVal));
     556             : 
     557             :   int gain = 0; // high or low gain
     558             :   
     559             :   // Number of Low and High gain, and LED Ref, channels for this event:
     560             :   int nLowChan = 0; 
     561             :   int nHighChan = 0; 
     562             :   int nLEDRefChan = 0;
     563             : 
     564             :   int iTowerNum = 0; // array index for regular towers
     565             :   int iRefNum = 0; // array index for LED references
     566             : 
     567             :   // loop first to get the fraction of channels with amplitudes above cut
     568             : 
     569           0 :   while (in->NextDDL()) {
     570           0 :     while (in->NextChannel()) {
     571             : 
     572           0 :       vector<AliCaloBunchInfo> bunchlist; 
     573           0 :       while (in->NextBunch()) {
     574           0 :         bunchlist.push_back( AliCaloBunchInfo(in->GetStartTimeBin(), in->GetBunchLength(), in->GetSignals() ) );
     575             :       } 
     576           0 :       if (bunchlist.size() == 0) continue;
     577             : 
     578             :       gain = -1; // init to not valid value
     579             :       //If we're here then we're done with this tower
     580           0 :       if ( in->IsLowGain() ) {
     581             :         gain = 0;
     582           0 :       }
     583           0 :       else if ( in->IsHighGain() ) {
     584             :         gain = 1;
     585           0 :       }
     586           0 :       else if ( in->IsLEDMonData() ) {
     587           0 :         gain = in->GetRow(); // gain coded in (in RCU/Altro mapping) as Row info for LED refs..
     588             :       }
     589           0 :       else { continue; } // don't try to fit TRU..
     590             : 
     591             :       // it should be enough to check the SuperModule info for each DDL really, but let's keep it here for now
     592           0 :       int arrayPos = in->GetModule(); //The modules are numbered starting from 0
     593             :       //Debug
     594           0 :       if (arrayPos < 0 || arrayPos >= fModules) {
     595           0 :         printf("AliCaloCalibSignal::ProcessEvent = Oh no: arrayPos = %i.\n", arrayPos); 
     596           0 :         return kFALSE;
     597             :       }
     598             : 
     599           0 :       AliCaloFitResults res =  fRawAnalyzer->Evaluate( bunchlist, in->GetAltroCFG1(), in->GetAltroCFG2());  
     600           0 :       if ( in->IsHighGain() || in->IsLowGain() ) { // regular tower
     601             :         // get tower number for AmpVal array
     602           0 :         iTowerNum = GetTowerNum(arrayPos, in->GetColumn(), in->GetRow()); 
     603             : 
     604           0 :         if (gain == 0) {
     605             :           // fill amplitude into the array         
     606           0 :           iAmpValLowGain[iTowerNum]  = (int) res.GetAmp();
     607           0 :           nLowChan++;
     608           0 :         } 
     609           0 :         else if (gain==1) {//fill the high gain ones
     610             :           // fill amplitude into the array
     611           0 :           iAmpValHighGain[iTowerNum] = (int) res.GetAmp();
     612           0 :           nHighChan++;
     613           0 :         }//end if gain
     614             :       } // regular tower
     615           0 :       else if ( in->IsLEDMonData() ) { // LED ref.; 
     616             :         // strip # is coded is 'column' in the channel maps 
     617           0 :         iRefNum = GetRefNum(arrayPos, in->GetColumn(), gain); 
     618           0 :         iLEDAmpVal[iRefNum] = (int) res.GetAmp();
     619           0 :         nLEDRefChan++;
     620           0 :       } // end of LED ref
     621             : 
     622           0 :     } // end while over channel 
     623             :    
     624             :   }//end while over DDL's, of input stream
     625             :   
     626           0 :   in->Reset(); // just in case the next customer forgets to check if the stream was reset..
     627             : 
     628             :   // now check if it was an LED event, using the LED Reference info per strip
     629             : 
     630             :   // by default all columns are accepted (init check to > 0)
     631           0 :   int checkResultArray[AliEMCALGeoParams::fgkEMCALModules * AliEMCALGeoParams::fgkEMCALCols];
     632           0 :   for (int ia=0; ia<(AliEMCALGeoParams::fgkEMCALModules * AliEMCALGeoParams::fgkEMCALCols); ia++) { 
     633           0 :     checkResultArray[ia] = 1; 
     634             :   }
     635           0 :   if (fReqFractionAboveAmp) {
     636             :     bool ok = false;
     637           0 :     if (nHighChan > 0) { 
     638           0 :       ok = CheckFractionAboveAmp(iAmpValHighGain, checkResultArray); 
     639           0 :     }
     640           0 :     if (!ok) return false; // skip event
     641           0 :   }
     642             : 
     643             :   // by default all columns are accepted (init check to > 0)
     644           0 :   int checkResultArrayLEDRef[AliEMCALGeoParams::fgkEMCALModules * AliEMCALGeoParams::fgkEMCALLEDRefs];
     645           0 :   for (int ia=0; ia<(AliEMCALGeoParams::fgkEMCALModules * AliEMCALGeoParams::fgkEMCALLEDRefs); ia++) { 
     646           0 :     checkResultArrayLEDRef[ia] = 1; 
     647             :   }
     648           0 :   if (fReqLEDRefAboveAmpCutVal) {
     649             :     bool ok = false;
     650           0 :     if (nLEDRefChan > 0) { 
     651           0 :       ok = CheckLEDRefAboveAmp(iLEDAmpVal, checkResultArrayLEDRef); 
     652           0 :     }
     653           0 :     if (!ok) return false; // skip event
     654           0 :   }
     655             : 
     656           0 :   fNAcceptedEvents++; // one more event accepted
     657             : 
     658           0 :   if (fStartTime == 0) { // if start-timestamp wasn't set,we'll pick it up from the first event we encounter
     659           0 :     fStartTime = Timestamp;
     660           0 :   }
     661             : 
     662           0 :   fHour = (Timestamp - fStartTime)/(double)fgkNumSecInHr;
     663           0 :   if (fLatestHour < fHour) {
     664           0 :     fLatestHour = fHour; 
     665           0 :   }
     666             :   
     667             :   // it is a led event, now fill TTree
     668             :   // We also do the activity check for LEDRefs/Strips, but need to translate between column
     669             :   // and strip indices for that; based on these relations: 
     670             :   // iStrip = AliEMCALGeoParams::GetStripModule(iSM, iCol);
     671             :   // iStrip = (iSM%2==0) ? iCol/2 : AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - iCol/2;
     672             :   // which leads to
     673             :   // iColFirst = (iSM%2==0) ? iStrip*2 : (AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - iStrip)*2;
     674             : 
     675           0 :   for(int i=0; i<fModules; i++){
     676           0 :     for(int j=0; j<fColumns; j++) {
     677           0 :       int iStrip = (i%2==0) ? j/2 : AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - j/2;
     678           0 :       if (checkResultArray[i*fColumns + j]>0  && checkResultArrayLEDRef[i*fLEDRefs + iStrip]>0) { // column passed check 
     679           0 :       for(int k=0; k<fRows; k++){
     680             :         
     681           0 :         iTowerNum = GetTowerNum(i, j, k); 
     682             : 
     683           0 :         if(iAmpValHighGain[iTowerNum]) {
     684           0 :           fAmp = iAmpValHighGain[iTowerNum];
     685           0 :           fChannelNum = GetChannelNum(i,j,k,1);
     686           0 :           fTreeAmpVsTime->Fill();//fChannelNum,fHour,AmpValHighGain[iTowerNum]);
     687           0 :           fNHighGain[iTowerNum]++;
     688           0 :         }
     689           0 :         if(iAmpValLowGain[iTowerNum]) {
     690           0 :           fAmp = iAmpValLowGain[iTowerNum];
     691           0 :           fChannelNum = GetChannelNum(i,j,k,0);
     692           0 :           fTreeAmpVsTime->Fill();//fChannelNum,fHour,AmpValLowGain[iTowerNum]);
     693           0 :           fNLowGain[iTowerNum]++;
     694           0 :         }
     695             :       } // rows
     696           0 :       } // column passed check, and LED Ref for strip passed check (if any)
     697             :     } // columns
     698             : 
     699             :     // also LED refs
     700           0 :     for(int j=0; j<fLEDRefs; j++){
     701           0 :       int iColFirst = (i%2==0) ? j*2 : (AliEMCALGeoParams::fgkEMCALLEDRefs - 1 - j)*2; //CHECKME!!!
     702           0 :       if ( ((checkResultArray[i*fColumns + iColFirst]>0) || (checkResultArray[i*fColumns + iColFirst + 1]>0)) && // at least one column in strip passed check 
     703           0 :            (checkResultArrayLEDRef[i*fLEDRefs + j]>0) ) { // and LED Ref passed checks
     704           0 :         for (gain=0; gain<2; gain++) {
     705           0 :           fRefNum = GetRefNum(i, j, gain); 
     706           0 :           if (iLEDAmpVal[fRefNum]) {
     707           0 :             fAmp = iLEDAmpVal[fRefNum];
     708           0 :             fTreeLEDAmpVsTime->Fill();//fRefNum,fHour,fAmp);
     709           0 :             fNRef[fRefNum]++;
     710           0 :           }
     711             :         } // gain
     712             :       } // at least one column in strip passed check, and LED Ref passed check (if any) 
     713             :     }
     714             : 
     715             :   } // modules
     716             :   
     717           0 :   return kTRUE;
     718           0 : }
     719             : 
     720             : //_____________________________________________________________________
     721             : Bool_t AliCaloCalibSignal::Save(TString fileName)
     722             : {
     723             :   //Saves all the TTrees to the designated file
     724             :   
     725           0 :   TFile destFile(fileName, "recreate");
     726             :   
     727           0 :   if (destFile.IsZombie()) {
     728           0 :     return kFALSE;
     729             :   }
     730             :   
     731           0 :   destFile.cd();
     732             : 
     733             :   // save the trees
     734           0 :   fTreeAmpVsTime->Write();
     735           0 :   fTreeLEDAmpVsTime->Write();
     736           0 :   if (fUseAverage) { 
     737           0 :     Analyze(); // get the latest and greatest averages
     738           0 :     fTreeAvgAmpVsTime->Write();
     739           0 :     fTreeLEDAvgAmpVsTime->Write();
     740             :   }
     741             : 
     742           0 :   destFile.Close();
     743             :   
     744           0 :   return kTRUE;
     745           0 : }
     746             : 
     747             : //_____________________________________________________________________
     748             : Bool_t AliCaloCalibSignal::Analyze()
     749             : {
     750             :   // Fill the tree holding the average values
     751           0 :   if (!fUseAverage) { return kFALSE; }
     752             : 
     753             :   // Reset the average TTree if Analyze has already been called earlier,
     754             :   // meaning that the TTree could have been partially filled
     755           0 :   if (fTreeAvgAmpVsTime->GetEntries() > 0) {
     756           0 :     fTreeAvgAmpVsTime->Reset();
     757           0 :   }
     758             : 
     759             :   //0: setup variables for the TProfile plots that we'll use to do the averages
     760             :   int numProfBins = 0;
     761             :   double timeMin = 0;
     762             :   double timeMax = 0;
     763           0 :   if (fSecInAverage > 0) {
     764           0 :     numProfBins = (int)( (fLatestHour*fgkNumSecInHr)/fSecInAverage + 1 ); // round-off
     765           0 :   }
     766           0 :   numProfBins += 2; // add extra buffer : first and last
     767           0 :   double binSize = 1.0*fSecInAverage / fgkNumSecInHr;
     768           0 :   timeMin = - binSize;
     769           0 :   timeMax = timeMin + numProfBins*binSize;
     770             : 
     771             :   //1: set up TProfiles for the towers that had data
     772           0 :   TProfile * profile[fgkMaxTowers*2]; // *2 is since we include both high and low gains
     773           0 :   memset(profile, 0, sizeof(profile));
     774             :   const Int_t buffersize = 200;
     775           0 :   char name[buffersize]; // for profile id and title
     776             :   int iTowerNum = 0;
     777             : 
     778           0 :   for (int i = 0; i<fModules; i++) {
     779           0 :     for (int ic=0; ic<fColumns; ic++){
     780           0 :       for (int ir=0; ir<fRows; ir++) {
     781             : 
     782           0 :         iTowerNum = GetTowerNum(i, ic, ir);
     783             :         // high gain
     784           0 :         if (fNHighGain[iTowerNum] > 0) {
     785           0 :           fChannelNum = GetChannelNum(i, ic, ir, 1); 
     786           0 :           snprintf(name,buffersize,"profileChan%d", fChannelNum);
     787           0 :           profile[fChannelNum] = new TProfile(name, name, numProfBins, timeMin, timeMax, "s");
     788           0 :         }
     789             : 
     790             :         // same for low gain
     791           0 :         if (fNLowGain[iTowerNum] > 0) {
     792           0 :           fChannelNum = GetChannelNum(i, ic, ir, 0); 
     793           0 :           snprintf(name,buffersize,"profileChan%d", fChannelNum);
     794           0 :           profile[fChannelNum] = new TProfile(name, name, numProfBins, timeMin, timeMax, "s");
     795           0 :         }
     796             : 
     797             :       } // rows
     798             :     } // columns
     799             :   } // modules
     800             : 
     801             :   //2: fill profiles by looping over tree
     802             :   // Set addresses for tree-readback also
     803           0 :   fTreeAmpVsTime->SetBranchAddress("fChannelNum", &fChannelNum);
     804           0 :   fTreeAmpVsTime->SetBranchAddress("fHour", &fHour);
     805           0 :   fTreeAmpVsTime->SetBranchAddress("fAmp", &fAmp);
     806             : 
     807           0 :   for (int ient=0; ient<fTreeAmpVsTime->GetEntries(); ient++) {
     808           0 :     fTreeAmpVsTime->GetEntry(ient);
     809           0 :     if (profile[fChannelNum]) { 
     810             :       // profile should always have been created above, for active channels
     811           0 :       profile[fChannelNum]->Fill(fHour, fAmp);
     812           0 :     }
     813             :   }
     814             : 
     815             :   // re-associating the branch addresses here seems to be needed for OK 'average' storage           
     816           0 :   fTreeAvgAmpVsTime->SetBranchAddress("fChannelNum", &fChannelNum);
     817           0 :   fTreeAvgAmpVsTime->SetBranchAddress("fHour", &fHour);
     818           0 :   fTreeAvgAmpVsTime->SetBranchAddress("fAvgAmp", &fAvgAmp);
     819           0 :   fTreeAvgAmpVsTime->SetBranchAddress("fRMS", &fRMS);
     820             : 
     821             :   //3: fill avg tree by looping over the profiles
     822           0 :   for (fChannelNum = 0; fChannelNum<(fgkMaxTowers*2); fChannelNum++) {
     823           0 :     if (profile[fChannelNum]) { // profile was created
     824           0 :       if (profile[fChannelNum]->GetEntries() > 0) { // profile had some entries
     825           0 :         for(int it=0; it<numProfBins; it++) {
     826           0 :           if (profile[fChannelNum]->GetBinEntries(it+1) > 0) {
     827           0 :             fAvgAmp = profile[fChannelNum]->GetBinContent(it+1);
     828           0 :             fHour = profile[fChannelNum]->GetBinCenter(it+1);
     829           0 :             fRMS = profile[fChannelNum]->GetBinError(it+1);
     830           0 :             fTreeAvgAmpVsTime->Fill();
     831           0 :           } // some entries for this bin
     832             :         } // loop over bins
     833           0 :       } // some entries for this profile
     834             :     } // profile exists  
     835             :   } // loop over all possible channels
     836             : 
     837             : 
     838             :   // and finally, go through same exercise for LED also.. 
     839             : 
     840             :   //1: set up TProfiles for the towers that had data
     841           0 :   TProfile * profileLED[fgkMaxRefs*2]; // *2 is since we include both high and low gains
     842           0 :   memset(profileLED, 0, sizeof(profileLED));
     843             : 
     844           0 :   for (int i = 0; i<fModules; i++) {
     845           0 :     for(int j=0; j<fLEDRefs; j++){
     846           0 :       for (int gain=0; gain<2; gain++) {
     847           0 :         fRefNum = GetRefNum(i, j, gain);
     848           0 :         if (fNRef[fRefNum] > 0) { 
     849           0 :           snprintf(name, buffersize, "profileLEDRef%d", fRefNum);
     850           0 :           profileLED[fRefNum] = new TProfile(name, name, numProfBins, timeMin, timeMax, "s");
     851           0 :         } 
     852             :       }// gain
     853             :     } 
     854             :   } // modules
     855             : 
     856             :   //2: fill profiles by looping over tree
     857             :   // Set addresses for tree-readback also
     858           0 :   fTreeLEDAmpVsTime->SetBranchAddress("fRefNum", &fRefNum);
     859           0 :   fTreeLEDAmpVsTime->SetBranchAddress("fHour", &fHour);
     860           0 :   fTreeLEDAmpVsTime->SetBranchAddress("fAmp", &fAmp);
     861             : 
     862           0 :   for (int ient=0; ient<fTreeLEDAmpVsTime->GetEntries(); ient++) {
     863           0 :     fTreeLEDAmpVsTime->GetEntry(ient);
     864           0 :     if (profileLED[fRefNum]) { 
     865             :       // profile should always have been created above, for active channels
     866           0 :       profileLED[fRefNum]->Fill(fHour, fAmp);
     867           0 :     }
     868             :   }
     869             : 
     870             :   // re-associating the branch addresses here seems to be needed for OK 'average' storage           
     871           0 :   fTreeLEDAvgAmpVsTime->SetBranchAddress("fRefNum", &fRefNum);
     872           0 :   fTreeLEDAvgAmpVsTime->SetBranchAddress("fHour", &fHour);
     873           0 :   fTreeLEDAvgAmpVsTime->SetBranchAddress("fAvgAmp", &fAvgAmp);
     874           0 :   fTreeLEDAvgAmpVsTime->SetBranchAddress("fRMS", &fRMS);
     875             : 
     876             :   //3: fill avg tree by looping over the profiles
     877           0 :   for (fRefNum = 0; fRefNum<(fgkMaxRefs*2); fRefNum++) {
     878           0 :     if (profileLED[fRefNum]) { // profile was created
     879           0 :       if (profileLED[fRefNum]->GetEntries() > 0) { // profile had some entries
     880           0 :         for(int it=0; it<numProfBins; it++) {
     881           0 :           if (profileLED[fRefNum]->GetBinEntries(it+1) > 0) {
     882           0 :             fAvgAmp = profileLED[fRefNum]->GetBinContent(it+1);
     883           0 :             fHour = profileLED[fRefNum]->GetBinCenter(it+1);
     884           0 :             fRMS = profileLED[fRefNum]->GetBinError(it+1);
     885           0 :             fTreeLEDAvgAmpVsTime->Fill();
     886           0 :           } // some entries for this bin
     887             :         } // loop over bins
     888           0 :       } // some entries for this profile
     889             :     } // profile exists  
     890             :   } // loop over all possible channels
     891             : 
     892             :   // OK, we're done..
     893             : 
     894             :   return kTRUE;
     895           0 : }
     896             : 
     897             : //_____________________________________________________________________
     898             : Bool_t AliCaloCalibSignal::DecodeChannelNum(const int chanId, 
     899             :                                             int *imod, int *icol, int *irow, int *igain) const  
     900             : { // return the module, column, row, and gain for a given channel number
     901           0 :   *igain = chanId/(fModules*fColumns*fRows);
     902           0 :   *imod = (chanId/(fColumns*fRows)) % fModules;
     903           0 :   *icol = (chanId/fRows) % fColumns;
     904           0 :   *irow = chanId % fRows;
     905           0 :   return kTRUE;
     906             : } 
     907             : 
     908             : //_____________________________________________________________________
     909             : Bool_t AliCaloCalibSignal::DecodeRefNum(const int refId, 
     910             :                                         int *imod, int *istripMod, int *igain) const 
     911             : { // return the module, stripModule, and gain for a given reference number
     912           0 :   *igain = refId/(fModules*fLEDRefs);
     913           0 :   *imod = (refId/(fLEDRefs)) % fModules;
     914           0 :   *istripMod = refId % fLEDRefs;
     915           0 :   return kTRUE;
     916             : } 

Generated by: LCOV version 1.11