LCOV - code coverage report
Current view: top level - PHOS/PHOSbase - AliPHOSRawDigiProducer.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 242 61.2 %
Date: 2016-06-14 17:26:59 Functions: 11 19 57.9 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 2007, 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             : /* $Id$ */
      17             : 
      18             : //This class produces PHOS digits of one event
      19             : //using AliPHOSRawFitter. 
      20             : //
      21             : //   For example:
      22             : //   TClonesArray *digits = new TClonesArray("AliPHOSDigit",100);
      23             : //   AliRawReader* rawReader = new AliRawReaderDate("2006run2211.raw");
      24             : //   AliPHOSRawDecoder dc(rawReader);
      25             : //   while (rawReader->NextEvent()) {
      26             : //     AliPHOSRawDigiProducer producer;
      27             : //     producer.MakeDigits(digits,&dc);
      28             : //   }
      29             : 
      30             : // Author: Boris Polichtchouk
      31             : 
      32             : // --- ROOT system ---
      33             : #include "TClonesArray.h"
      34             : 
      35             : // --- AliRoot header files ---
      36             : #include "AliPHOSRawDigiProducer.h"
      37             : #include "AliPHOSRawFitterv0.h"
      38             : #include "AliPHOSGeometry.h"
      39             : #include "AliPHOSDigit.h"
      40             : #include "AliPHOSCalibData.h"
      41             : #include "AliPHOSPulseGenerator.h"
      42             : #include "AliCaloRawStreamV3.h"
      43             : #include "AliDAQ.h"
      44             : #include "AliRawReader.h"
      45             : #include "AliLog.h"
      46             : 
      47          22 : ClassImp(AliPHOSRawDigiProducer)
      48             : 
      49             : AliPHOSCalibData * AliPHOSRawDigiProducer::fgCalibData  = 0 ; 
      50             : 
      51             : //--------------------------------------------------------------------------------------
      52             : AliPHOSRawDigiProducer::AliPHOSRawDigiProducer():
      53           0 :   TObject(),
      54           0 :   fSubtractL1phase(kTRUE),
      55           0 :   fEmcMinE(0.),
      56           0 :   fCpvMinE(0.),
      57           0 :   fSampleQualityCut(1.),
      58           0 :   fSampleToSec(0.),
      59           0 :   fEmcCrystals(0),
      60           0 :   fGeom(0),
      61           0 :   fPulseGenerator(0),
      62           0 :   fRawReader(0),
      63           0 :   fRawStream(0),
      64           0 :   fADCValuesLG(0),
      65           0 :   fADCValuesHG(0)
      66           0 : {
      67             :   // Default constructor
      68             : 
      69           0 :   fGeom=AliPHOSGeometry::GetInstance() ;
      70           0 :   if(!fGeom) fGeom = AliPHOSGeometry::GetInstance("IHEP");
      71             : 
      72           0 :   fEmcCrystals=fGeom->GetNCristalsInModule()*fGeom->GetNModules() ;
      73           0 :   fPulseGenerator = new AliPHOSPulseGenerator();
      74           0 :   GetCalibrationParameters() ; 
      75             : 
      76           0 : }
      77             : //--------------------------------------------------------------------------------------
      78             : AliPHOSRawDigiProducer::AliPHOSRawDigiProducer(AliRawReader *rawReader,
      79             :                                                AliAltroMapping **mapping):
      80           4 :   TObject(),
      81           4 :   fSubtractL1phase(kTRUE),
      82           4 :   fEmcMinE(0.),
      83           4 :   fCpvMinE(0.),
      84           4 :   fSampleQualityCut(1.),
      85           4 :   fSampleToSec(0.),
      86           4 :   fEmcCrystals(0),
      87           4 :   fGeom(0),
      88           4 :   fPulseGenerator(0),
      89           4 :   fRawReader(rawReader),
      90           4 :   fRawStream(0),
      91           4 :   fADCValuesLG(0),
      92           4 :   fADCValuesHG(0)
      93          20 : {
      94             :   // Default constructor
      95             : 
      96           8 :   fGeom=AliPHOSGeometry::GetInstance() ;
      97           4 :   if(!fGeom) fGeom = AliPHOSGeometry::GetInstance("IHEP");
      98             : 
      99           8 :   fEmcCrystals=fGeom->GetNCristalsInModule()*fGeom->GetNModules() ;
     100          12 :   fPulseGenerator = new AliPHOSPulseGenerator();
     101           4 :   GetCalibrationParameters() ; 
     102             : 
     103          16 :   fRawStream = new AliCaloRawStreamV3(rawReader,"PHOS",mapping);
     104             :   // Select only data in ALTRO format and skip STU, the last PHOS DDL
     105           8 :   rawReader->Select("PHOS",0,AliDAQ::NumberOfDdls("PHOS")-2);
     106             : 
     107           8 : }
     108             : //--------------------------------------------------------------------------------------
     109             : AliPHOSRawDigiProducer::AliPHOSRawDigiProducer(const AliPHOSRawDigiProducer &dp):
     110           0 :   TObject(),
     111           0 :   fSubtractL1phase(kTRUE),
     112           0 :   fEmcMinE(0.),
     113           0 :   fCpvMinE(0.),
     114           0 :   fSampleQualityCut(1.),
     115           0 :   fSampleToSec(0.),
     116           0 :   fEmcCrystals(0),
     117           0 :   fGeom(0),
     118           0 :   fPulseGenerator(0),
     119           0 :   fRawReader(0),
     120           0 :   fRawStream(0),
     121           0 :   fADCValuesLG(0),
     122           0 :   fADCValuesHG(0)
     123             : 
     124           0 : {                                                          
     125             :   // Copy constructor
     126             : 
     127           0 :   fEmcMinE = dp.fEmcMinE ;
     128           0 :   fCpvMinE = dp.fCpvMinE ;
     129           0 :   fSampleQualityCut = dp.fSampleQualityCut;
     130           0 :   fSampleToSec = dp.fSampleToSec ;
     131           0 :   fEmcCrystals = dp.fEmcCrystals ;
     132           0 :   fPulseGenerator = new AliPHOSPulseGenerator();
     133           0 :   fGeom = dp.fGeom ;
     134           0 : }
     135             : //--------------------------------------------------------------------------------------
     136             : AliPHOSRawDigiProducer& AliPHOSRawDigiProducer::operator= (const AliPHOSRawDigiProducer &dp)
     137             : {
     138             :   // Assign operator
     139             : 
     140           0 :   if(&dp == this) return *this;
     141             : 
     142           0 :   fSubtractL1phase = dp.fSubtractL1phase ;
     143           0 :   fEmcMinE = dp.fEmcMinE ;
     144           0 :   fCpvMinE = dp.fCpvMinE ;
     145           0 :   fSampleQualityCut = dp.fSampleQualityCut ;
     146           0 :   fSampleToSec = dp.fSampleToSec ;
     147           0 :   fEmcCrystals = dp.fEmcCrystals ;
     148           0 :   fGeom = dp.fGeom ;
     149           0 :   if(fPulseGenerator) delete fPulseGenerator ;
     150           0 :   fPulseGenerator = new AliPHOSPulseGenerator();
     151           0 :   return  *this;
     152           0 : } 
     153             : //--------------------------------------------------------------------------------------
     154             : AliPHOSRawDigiProducer::~AliPHOSRawDigiProducer()
     155          16 : {
     156             :   // Destructor
     157          12 :   if(fPulseGenerator) delete fPulseGenerator ;
     158           4 :   fPulseGenerator=0 ;
     159           8 :   delete fRawStream;
     160           8 :   delete [] fADCValuesLG;
     161           8 :   delete [] fADCValuesHG;
     162           8 : }
     163             : //--------------------------------------------------------------------------------------
     164             : void AliPHOSRawDigiProducer::MakeDigits(TClonesArray *digits, AliPHOSRawFitterv0* fitter) 
     165             : {
     166             :   // Create a temporary array of LG digits and then make digits from raw data
     167             : 
     168           0 :   TClonesArray *tmpLG = new TClonesArray("AliPHOSDigit",10000) ;
     169           0 :   MakeDigits(digits, tmpLG, fitter);
     170           0 :   tmpLG->Delete();
     171           0 :   delete tmpLG;
     172           0 : }
     173             : //--------------------------------------------------------------------------------------
     174             : void AliPHOSRawDigiProducer::MakeDigits(TClonesArray *digits, TClonesArray *tmpDigLG, AliPHOSRawFitterv0* fitter) 
     175             : {
     176             :   //Makes the job.
     177             :   //TClonesArray *digits, *tmpDigLG and raw data fitter should be provided by calling function.
     178             :   Int_t iDigit=0 ;
     179           8 :   Int_t relId[4], absId=-1, caloFlag=-1;
     180             :   
     181             :   const Double_t baseLine=1. ; //Minimal energy of digit in ADC ch. 
     182             : 
     183             :   //Calculate conversion coeff. from Sample time step to seconds
     184             :   //If OCDB contains negative or zero value - use one from RCU trailer
     185             :   //Negative value in OCDB is used only for simulation of raw digits
     186           4 :   if(fgCalibData->GetSampleTimeStep()>0.)
     187           4 :     fSampleToSec=fgCalibData->GetSampleTimeStep() ;
     188             :   else
     189           0 :     fSampleToSec=fRawStream->GetTSample() ;
     190             :   
     191             :   // Clear a temporary array for LowGain digits
     192           4 :   tmpDigLG->Clear();
     193             :   Int_t ilgDigit=0 ;
     194             : 
     195             :   //Let fitter subtract pedestals in case of ZS
     196           4 :   fitter->SetCalibData(fgCalibData) ;
     197             :   
     198          62 :   while (fRawStream->NextDDL()) {
     199             :     // Skip STU DDL
     200          27 :     if (fRawStream->GetDDLNumber() == fgkSTUDDL) continue; 
     201         181 :     while (fRawStream->NextChannel()) {
     202         154 :       relId[0] = 5 - fRawStream->GetModule() ; // counts from 1 to 5
     203         154 :       relId[1] = 0;                            // 0=EMC
     204         154 :       relId[2] = fRawStream->GetCellX()  + 1;  // counts from 1 to 64
     205         154 :       relId[3] = fRawStream->GetCellZ()  + 1;  // counts from 1 to 56
     206         154 :       caloFlag = fRawStream->GetCaloFlag();    // 0=LG, 1=HG, 2=TRU
     207             :       
     208         154 :       if(caloFlag!=0 && caloFlag!=1) continue; //TRU data!
     209             :       
     210         154 :       fitter->SetChannelGeo(relId[0],relId[2],relId[3],caloFlag);
     211             : 
     212         308 :       if(fitter->GetAmpOffset()==0 && fitter->GetAmpThreshold()==0) {
     213         154 :         short value = fRawStream->GetAltroCFG1();
     214         154 :         bool ZeroSuppressionEnabled = (value >> 15) & 0x1;
     215         154 :         if(ZeroSuppressionEnabled) {
     216           0 :           short offset = (value >> 10) & 0xf;
     217           0 :           short threshold = value & 0x3ff;
     218           0 :           fitter->SubtractPedestals(kFALSE);
     219           0 :           fitter->SetAmpOffset(offset);
     220           0 :           fitter->SetAmpThreshold(threshold);
     221           0 :         }
     222         154 :       }
     223             :       
     224         154 :       fGeom->RelToAbsNumbering(relId, absId);
     225             :       
     226         154 :       fitter->SetNBunches(0);
     227             :       Int_t sigStart =0 ;
     228             :       Int_t sigLength=0 ;
     229         616 :       while (fRawStream->NextBunch()) { //Take the first in time bunch
     230         154 :         const UShort_t *sig = fRawStream->GetSignals();
     231         154 :         sigStart  = fRawStream->GetStartTimeBin();
     232         154 :         sigLength = fRawStream->GetBunchLength();
     233         154 :         fitter->Eval(sig,sigStart,sigLength);
     234         154 :         if      (caloFlag == AliCaloRawStreamV3::kLowGain) {
     235          88 :           delete [] fADCValuesLG;
     236          46 :           fADCValuesLG = new Int_t[sigLength];
     237        3204 :           for (Int_t i=0; i<sigLength; i++)
     238        1556 :             fADCValuesLG[sigLength-i-1] = sig[i];
     239          46 :         }
     240         108 :         else if (caloFlag == AliCaloRawStreamV3::kHighGain) {
     241         212 :           delete [] fADCValuesHG;
     242         108 :           fADCValuesHG = new Int_t[sigLength];
     243       14134 :           for (Int_t i=0; i<sigLength; i++)
     244        6959 :             fADCValuesHG[sigLength-i-1] = sig[i];
     245         108 :         }
     246             :       } // End of NextBunch()
     247             : 
     248             :       
     249         154 :       Double_t energy = fitter->GetEnergy() ; 
     250         154 :       Double_t time   = fitter->GetTime() ;
     251         154 :       if(energy<=baseLine) //in ADC channels
     252          27 :         continue ;
     253             : 
     254             :       //remove digits with bad shape. Fitter should calculate quality so that 
     255             :       //in default case quality [0,1], while larger values of quality mean somehow 
     256             :       //corrupted samples, 999 means obviously corrupted sample.
     257             :       //It is difficult to fit samples with overflow (even setting cut on overflow values)
     258             :       //because too few points are left to fit. So we do not evaluate samples with overflow
     259             : 
     260         127 :       if(fitter->GetSignalQuality() > fSampleQualityCut && !(fitter->IsOverflow()))
     261           0 :         continue ;
     262             :       
     263         127 :       energy = CalibrateE(energy,relId,!caloFlag) ;
     264             : 
     265             :       //convert time from sample bin units to s
     266         127 :       time*=fSampleToSec ;
     267             : //CalibrateT moved to Clusterizer
     268             : //      time = CalibrateT(time,relId,!caloFlag) ;
     269             :       // subtract RCU L1 phase (L1Phase is in seconds) w.r.t. L0:
     270             :       //Very strange behaviour of electronics, but cross-checkes several times...
     271         127 :       if(fSubtractL1phase){
     272         127 :         if( fRawStream->GetL1Phase()<55.*1.e-9 ) //for phase=0,25,50
     273         127 :           time -= fRawStream->GetL1Phase();
     274             :         else //for phase 75
     275           0 :           time += 25.*1.e-9 ;
     276             :       }
     277             :       
     278         127 :       if(energy <= 0.) 
     279           0 :         continue;
     280             :       
     281         127 :       if (caloFlag == AliCaloRawStreamV3::kLowGain) {
     282          19 :         new((*tmpDigLG)[ilgDigit]) AliPHOSDigit(-1,absId,(Float_t)energy,(Float_t)time);
     283          38 :         if (sigLength>0 && fADCValuesLG!=0)
     284          19 :           static_cast<AliPHOSDigit*>(tmpDigLG->At(ilgDigit))->SetALTROSamplesLG(sigLength,fADCValuesLG);
     285          19 :         ilgDigit++ ; 
     286          19 :       }
     287         108 :       else if (caloFlag == AliCaloRawStreamV3::kHighGain) {
     288         216 :         if(fitter->IsOverflow()) //Keep this digit to replace it by Low Gain later.
     289             :           //If there is no LogGain it wil be removed by cut on Min E
     290         110 :           new((*digits)[iDigit]) AliPHOSDigit(-1,absId,-1.f,(Float_t)time);
     291             :         else
     292         106 :           new((*digits)[iDigit]) AliPHOSDigit(-1,absId,(Float_t)energy,(Float_t)time);
     293         216 :         if (sigLength>0 && fADCValuesHG!=0)
     294         108 :           static_cast<AliPHOSDigit*>(digits->At(iDigit))->SetALTROSamplesHG(sigLength,fADCValuesHG);
     295         108 :         iDigit++;
     296         108 :       }
     297         127 :     } // End of NextChannel()
     298             : 
     299             :     //Now scan created LG and HG digits and keep only those which appeared in both lists 
     300             :     //replace energy of HighGain digits only if there is overflow
     301             :     //negative energy (overflow)
     302          27 :     digits->Sort() ;
     303          27 :     tmpDigLG->Sort() ;
     304             :     Int_t iLG = 0;
     305          27 :     Int_t nLG1 = tmpDigLG->GetEntriesFast()-1 ;
     306             :     
     307        1284 :     for(Int_t iDig=0 ; iDig < digits->GetEntriesFast() ; iDig++) { 
     308        1845 :       AliPHOSDigit * digHG = dynamic_cast<AliPHOSDigit*>(digits->At(iDig)) ;
     309         615 :       if (!digHG) continue;
     310        1835 :       AliPHOSDigit * digLG = dynamic_cast<AliPHOSDigit*>(tmpDigLG->At(iLG)) ;
     311        2649 :       while(digLG && iLG<nLG1 && digHG->GetId()> digLG->GetId()){
     312          90 :         iLG++ ;
     313         270 :         digLG = dynamic_cast<AliPHOSDigit*>(tmpDigLG->At(iLG)) ;
     314             :       }
     315         615 :       absId=digHG->GetId() ;
     316         615 :       fGeom->AbsToRelNumbering(absId,relId) ;
     317             :  
     318        1220 :       if(digLG && digHG->GetId() == digLG->GetId()){ //we found pair
     319         113 :         if(digHG->GetEnergy()<0.){ //This is overflow in HG
     320           2 :           digHG->SetTime(digLG->GetTime()) ;
     321           2 :           digHG->SetEnergy(digLG->GetEnergy()) ;
     322           2 :           digHG->SetLG(kTRUE) ;
     323           2 :         }
     324             :       }
     325             :       else{ //no pair - remove
     326         502 :         if(digHG->GetEnergy()<0.) //no pair, in saturation
     327           0 :           digits->RemoveAt(iDig) ;                                                          
     328             :       }
     329         615 :     }
     330             :   } // End of NextDDL()
     331             : 
     332           4 :   CleanDigits(digits) ;
     333             :   
     334           4 : }
     335             : //____________________________________________________________________________
     336             : Double_t AliPHOSRawDigiProducer::CalibrateE(Double_t amp, Int_t* relId, Bool_t isLowGain)
     337             : {
     338             :   // Convert EMC LG amplitude to HG (multipli by ~16)
     339             :   // Calibration parameters are taken from calibration data base 
     340         127 :   if(fgCalibData){ 
     341         127 :     Int_t   module = relId[0];  
     342         127 :     Int_t   column = relId[3];
     343         127 :     Int_t   row    = relId[2];
     344         127 :     if(relId[1]==0) { // this is EMC 
     345         127 :       if(isLowGain){
     346          19 :         amp*= fgCalibData->GetHighLowRatioEmc(module,column,row);
     347          19 :       }
     348         127 :       return amp ;         
     349             :     }         
     350           0 :   }          
     351           0 :   return 0;        
     352         127 : }
     353             : //____________________________________________________________________________
     354             : Double_t AliPHOSRawDigiProducer::CalibrateT(Double_t time, Int_t * relId, Bool_t /* isLowGain */)
     355             : {
     356             :   //Calibrate time
     357           0 :   if(fgCalibData){
     358           0 :     Int_t   module = relId[0];
     359           0 :     Int_t   column = relId[3];
     360           0 :     Int_t   row    = relId[2];
     361           0 :     if(relId[1]==0) { // this is EMC
     362           0 :       time += fgCalibData->GetTimeShiftEmc(module,column,row);                   
     363           0 :       return time ;             
     364             :     }
     365           0 :   }
     366             :  
     367           0 :   return -999.;
     368           0 : }
     369             : //____________________________________________________________________________
     370             : void AliPHOSRawDigiProducer::CleanDigits(TClonesArray * digits)
     371             : {
     372             :   // remove digits with amplitudes below threshold.
     373             :   // remove digits in bad channels
     374             :   // sort digits with icreasing AbsId
     375             :   
     376             :   //remove digits in bad map and below threshold
     377             :   Bool_t isBadMap = 0 ;
     378           8 :   if(fgCalibData->GetNumOfEmcBadChannels()){
     379             :     isBadMap=1 ;
     380           0 :   }
     381             :   
     382         224 :   for(Int_t i=0; i<digits->GetEntriesFast(); i++){
     383         108 :     AliPHOSDigit * digit = static_cast<AliPHOSDigit*>(digits->At(i)) ;
     384         108 :     if(!digit)
     385           0 :       continue  ;
     386         216 :     if ( (IsInEMC(digit) && digit->GetEnergy() < fEmcMinE) ||
     387         108 :          (IsInCPV(digit) && digit->GetEnergy() < fCpvMinE) ){
     388           0 :       digits->RemoveAt(i) ;
     389           0 :       continue ;
     390             :     }
     391         108 :     if(isBadMap){ //check bad map now
     392           0 :       Int_t relid[4] ;
     393           0 :       fGeom->AbsToRelNumbering(digit->GetId(), relid) ; 
     394           0 :       if(fgCalibData->IsBadChannelEmc(relid[0],relid[3],relid[2])){
     395           0 :         digits->RemoveAt(i) ;
     396           0 :       }
     397           0 :     }
     398         108 :   }
     399             : 
     400             :   //Compress, sort and set indexes
     401           4 :   digits->Compress() ;
     402             : //  digits->Sort(); already sorted earlier
     403         224 :   for (Int_t i = 0 ; i < digits->GetEntriesFast() ; i++) { 
     404         108 :     AliPHOSDigit *digit = static_cast<AliPHOSDigit*>( digits->At(i) ) ; 
     405         108 :     digit->SetIndexInList(i) ;     
     406             :   }
     407           4 : }
     408             : //____________________________________________________________________________
     409             : Bool_t AliPHOSRawDigiProducer::IsInEMC(AliPHOSDigit * digit) const
     410             : {
     411             :   // Tells if (true) or not (false) the digit is in a PHOS-EMC module
     412         216 :   return digit->GetId() <= fEmcCrystals ;
     413             : 
     414             : }
     415             : 
     416             : //____________________________________________________________________________
     417             : Bool_t AliPHOSRawDigiProducer::IsInCPV(AliPHOSDigit * digit) const
     418             : {
     419             :   // Tells if (true) or not (false) the digit is in a PHOS-CPV module
     420         216 :   return digit->GetId() > fEmcCrystals ;
     421             : }
     422             : //____________________________________________________________________________
     423             : void AliPHOSRawDigiProducer::GetCalibrationParameters() 
     424             : {
     425             :   // Set calibration parameters:
     426             :   // if calibration database exists, they are read from database,
     427             :   // otherwise, reconstruction stops in the constructor of AliPHOSCalibData
     428             :   //
     429             :   // It is a user responsilibity to open CDB before reconstruction, for example: 
     430             :   // AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage("local://CalibDB");
     431             : 
     432           8 :   if (!fgCalibData){
     433           2 :     fgCalibData = new AliPHOSCalibData(-1); //use AliCDBManager's run number
     434           1 :   }
     435           4 :   if (fgCalibData->GetCalibDataEmc() == 0)
     436           0 :     AliFatal("Calibration parameters for PHOS EMC not found. Stop reconstruction.\n");
     437           4 :   if (fgCalibData->GetCalibDataCpv() == 0)
     438           0 :     AliFatal("Calibration parameters for PHOS CPV not found. Stop reconstruction.\n");
     439           4 : }

Generated by: LCOV version 1.11