LCOV - code coverage report
Current view: top level - MUON/MUONsim - AliMUONDigitizerV3.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 202 337 59.9 %
Date: 2016-06-14 17:26:59 Functions: 20 23 87.0 %

          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             : 
      16             : // $Id$
      17             : 
      18             : 
      19             : #include "AliMUONDigitizerV3.h"
      20             : 
      21             : #include "AliMUON.h"
      22             : #include "AliMUONCalibrationData.h"
      23             : #include "AliMUONConstants.h"
      24             : #include "AliMUONDigit.h"
      25             : #include "AliMUONLogger.h"
      26             : #include "AliMUONTriggerElectronics.h"
      27             : #include "AliMUONTriggerStoreV1.h"
      28             : #include "AliMUONVCalibParam.h"
      29             : #include "AliMUONVDigitStore.h"
      30             : #include "AliMUONGeometryTransformer.h" //ADDED for trigger noise
      31             : #include "AliMUONRecoParam.h"
      32             : #include "AliMUONTriggerChamberEfficiency.h"
      33             : #include "AliMUONTriggerUtilities.h"
      34             : 
      35             : #include "AliMpCDB.h"
      36             : #include "AliMpSegmentation.h"
      37             : #include "AliMpCathodType.h"
      38             : #include "AliMpConstants.h"
      39             : #include "AliMpDEIterator.h"
      40             : #include "AliMpDEManager.h"
      41             : #include "AliMpPad.h"
      42             : #include "AliMpStationType.h"
      43             : #include "AliMpVSegmentation.h"
      44             : #include "AliMpDDLStore.h"
      45             : 
      46             : #include "AliCDBManager.h"
      47             : #include "AliCodeTimer.h"
      48             : #include "AliLog.h"
      49             : #include "AliRun.h"
      50             : #include "AliDigitizationInput.h"
      51             : #include "AliLoader.h"
      52             : #include "AliRunLoader.h"
      53             : 
      54             : #include <Riostream.h>
      55             : #include <TF1.h>
      56             : #include <TFile.h>
      57             : #include <TMath.h>
      58             : #include <TRandom.h>
      59             : #include <TString.h>
      60             : #include <TSystem.h>
      61             : #include <TTree.h>
      62             : 
      63             : //-----------------------------------------------------------------------------
      64             : /// \class AliMUONDigitizerV3
      65             : ///
      66             : /// The digitizer is performing the transformation to go from SDigits (digits
      67             : /// w/o any electronic noise) to Digits (w/ electronic noise, and decalibration)
      68             : /// 
      69             : /// The decalibration is performed by doing the reverse operation of the
      70             : /// calibration, that is we do (Signal+pedestal)/gain -> ADC
      71             : ///
      72             : /// Note also that the digitizer takes care of merging sdigits that belongs
      73             : /// to the same pad, either because we're merging several input sdigit files
      74             : /// or with a single file because the sdigitizer does not merge sdigits itself
      75             : /// (for performance reason mainly, and because anyway we know we have to do it
      76             : /// here, at the digitization level).
      77             : ///
      78             : /// August 2011. In order to remove the need for specific MC OCDB storages,
      79             : /// we're introducing a dependence of simulation on AliMUONRecoParam (stored
      80             : /// in MUON/Calib/RecoParam in OCDB), which is normally (or conceptually, if
      81             : /// you will) only a reconstruction object. That's not a pretty solution, but,
      82             : /// well, we have to do it...
      83             : /// This dependence comes from the fact that we must know how to decalibrate
      84             : /// the digits, so that the decalibration (done here) - calibration (done during
      85             : /// reco) process is (as much as possible) neutral.
      86             : ///
      87             : ///
      88             : /// \author Laurent Aphecetche
      89             : ///
      90             : //-----------------------------------------------------------------------------
      91             : 
      92             : namespace
      93             : {
      94             :   AliMUON* muon()
      95             :   {
      96           2 :     return static_cast<AliMUON*>(gAlice->GetModule("MUON"));
      97             :   }
      98             : 
      99             :   //ADDED for trigger noise
     100             :   const AliMUONGeometryTransformer* GetTransformer()
     101             :   {
     102           0 :       return muon()->GetGeometryTransformer();
     103             :   }
     104             : }
     105             : 
     106             : Double_t AliMUONDigitizerV3::fgNSigmas = 4.0;
     107             : 
     108             : /// \cond CLASSIMP
     109          16 : ClassImp(AliMUONDigitizerV3)
     110             : /// \endcond
     111             : 
     112             : //_____________________________________________________________________________
     113             : AliMUONDigitizerV3::AliMUONDigitizerV3(AliDigitizationInput* digInput, 
     114             :                                        Int_t generateNoisyDigits)
     115           1 : : AliDigitizer(digInput),
     116           1 : fIsInitialized(kFALSE),
     117           1 : fCalibrationData(0x0),
     118           1 : fTriggerProcessor(0x0),
     119           1 : fNoiseFunctionTrig(0x0),
     120           1 : fGenerateNoisyDigits(generateNoisyDigits),
     121           3 : fLogger(new AliMUONLogger(4207)), /* 4207 = 25% of the 16828 MCH manus */
     122           3 : fTriggerStore(new AliMUONTriggerStoreV1),
     123           1 : fDigitStore(0x0),
     124           1 : fOutputDigitStore(0x0),
     125           1 : fInputDigitStores(0x0),
     126           1 : fRecoParam(0x0),
     127           1 : fTriggerEfficiency(0x0),
     128           1 : fTriggerUtilities(0x0),
     129           2 : fEfficiencyResponse(2*AliMUONConstants::NTriggerCh()*AliMUONConstants::NTriggerCircuit())
     130           5 : {
     131             :   /// Ctor.
     132             : 
     133           5 :   AliDebug(1,Form("AliDigitizationInput=%p",fDigInput));
     134             : 
     135           2 : }
     136             : 
     137             : //_____________________________________________________________________________
     138             : AliMUONDigitizerV3::~AliMUONDigitizerV3()
     139           6 : {
     140             :   /// Dtor. Note we're the owner of some pointers.
     141             : 
     142           5 :   AliDebug(1,"dtor");
     143             : 
     144             :  // delete fCalibrationData;
     145           2 :   delete fTriggerProcessor;
     146           1 :   delete fNoiseFunctionTrig;
     147           2 :   delete fTriggerStore;
     148           2 :   delete fDigitStore;
     149           2 :   delete fOutputDigitStore;
     150           2 :   delete fInputDigitStores;
     151           2 :   delete fTriggerUtilities;
     152             :   
     153           2 :   AliInfo("Summary of messages");
     154           1 :   fLogger->Print();
     155             :   
     156           2 :   delete fLogger;
     157           3 : }
     158             : 
     159             : //_____________________________________________________________________________
     160             : void 
     161             : AliMUONDigitizerV3::ApplyResponseToTrackerDigit(AliMUONVDigit& digit, Bool_t addNoise)
     162             : {
     163             :   /// For tracking digits, starting from an ideal digit's charge, we :
     164             :   ///
     165             :   /// - "divide" by a gain (thus decalibrating the digit)
     166             :   /// - add a pedestal (thus decalibrating the digit)
     167             :   /// - add some electronics noise (thus leading to a realistic adc), if requested to do so
     168             :   /// - sets the signal to zero if below 3*sigma of the noise
     169             : 
     170         857 :   Float_t charge = digit.Charge();
     171             :   
     172         857 :   if (!digit.IsChargeInFC())
     173             :   {
     174           0 :     charge *= AliMUONConstants::DefaultADC2MV()*AliMUONConstants::DefaultA0()*AliMUONConstants::DefaultCapa();
     175           0 :     fLogger->Log("CHECK ME ! WAS NOT SUPPOSED TO BE HERE !!! ARE YOU RECONSTRUCTING OLD SIMULATIONS ? ");
     176           0 :     AliError("CHECK ME ! WAS NOT SUPPOSED TO BE HERE !!! ARE YOU RECONSTRUCTING OLD SIMULATIONS ? ");
     177           0 :   }
     178             :   
     179             :   // We set the charge to 0, as the only relevant piece of information
     180             :   // after Digitization is the ADC value.  
     181         857 :   digit.SetCharge(0);
     182             :     
     183         857 :   Int_t detElemId = digit.DetElemId();
     184         857 :   Int_t manuId = digit.ManuId();
     185             :   
     186         857 :   AliMUONVCalibParam* pedestal = fCalibrationData->Pedestals(detElemId,manuId);
     187         857 :   if (!pedestal)
     188             :   {
     189           0 :     fLogger->Log(Form("%s:%d:Could not get pedestal for DE=%4d manuId=%4d. Disabling.",
     190             :                       __FILE__,__LINE__,
     191             :                       detElemId,manuId));
     192           0 :     digit.SetADC(0);
     193           0 :     return;    
     194             :   }
     195             :   
     196         857 :   Int_t manuChannel = digit.ManuChannel();
     197             :   
     198        1714 :   if ( pedestal->ValueAsFloat(manuChannel,0) == AliMUONVCalibParam::InvalidFloatValue() ||
     199         857 :       pedestal->ValueAsFloat(manuChannel,1) == AliMUONVCalibParam::InvalidFloatValue() )
     200             :   {
     201             :     // protection against invalid pedestal value
     202           0 :     digit.SetADC(0);
     203           0 :     return;
     204             :   }
     205             : 
     206        1714 :   Int_t adc = DecalibrateTrackerDigit(*pedestal,manuChannel,charge,addNoise,
     207         857 :                                       digit.IsNoiseOnly());
     208             :   
     209         857 :   digit.SetADC(adc);
     210        1714 : }
     211             : 
     212             : 
     213             : //_____________________________________________________________________________
     214             : void 
     215             : AliMUONDigitizerV3::ApplyResponseToTriggerDigit(AliMUONVDigit& digit)
     216             : {
     217             :   /// For trigger digits, starting from an ideal digit, we :
     218             :   ///
     219             :   /// - apply efficiency (on demand)
     220             :   /// - apply trigger masks
     221             :     
     222         224 :   Int_t detElemId = digit.DetElemId();
     223         112 :   Int_t localCircuit = digit.ManuId();
     224         112 :   Int_t strip = digit.ManuChannel();
     225         112 :   Int_t cathode = digit.Cathode();
     226         112 :   Int_t trigCh = detElemId/100 - 11;
     227             :   
     228             :   // Masked channels
     229         112 :   Bool_t isMasked = fTriggerUtilities->IsMasked(digit);
     230         336 :   AliDebug(1,Form("detElemId %i  cath %i  board %i  strip %i  is masked %i\n", detElemId, cathode, localCircuit, strip, isMasked));
     231         112 :   if ( isMasked ) {
     232           0 :     digit.SetCharge(0);
     233           0 :     digit.SetADC(0);
     234             :     //AliDebug(1,Form("ch %i  cath %i  board %i  strip %i  masked\n", trigCh, cathode, localCircuit, strip));
     235           0 :     return;
     236             :   }
     237             :   
     238             :   
     239         112 :   Int_t arrayIndex = GetArrayIndex(cathode, trigCh, localCircuit);
     240             :   
     241             :   // Trigger chamber efficiency
     242         112 :   if ( fTriggerEfficiency ) {
     243         112 :     if ( fEfficiencyResponse[arrayIndex] < 0 ) {
     244          43 :       Bool_t isTrig[2] = {kTRUE, kTRUE};
     245          43 :       fTriggerEfficiency->IsTriggered(detElemId, localCircuit, isTrig[0], isTrig[1]);
     246          43 :       Int_t arrayIndexBend = GetArrayIndex(0, trigCh, localCircuit);
     247          43 :       Int_t arrayIndexNonBend = GetArrayIndex(1, trigCh, localCircuit);
     248          43 :       fEfficiencyResponse[arrayIndexBend] = isTrig[0];
     249          43 :       fEfficiencyResponse[arrayIndexNonBend] = isTrig[1];
     250          43 :     }
     251         336 :     AliDebug(1,Form("detElemId %i  cath %i  board %i  strip %i  efficiency %i\n", detElemId, cathode, localCircuit, strip, fEfficiencyResponse[arrayIndex]));
     252         112 :     if ( fEfficiencyResponse[arrayIndex] == 0 ) {
     253           0 :       digit.SetCharge(0);
     254           0 :       digit.SetADC(0);
     255             :       //AliDebug(1,Form("ch %i  cath %i  board %i  strip %i  NOT efficient\n", trigCh, cathode, localCircuit, strip));
     256           0 :       return;
     257             :     }
     258             :   }  
     259         224 : }
     260             : 
     261             : 
     262             : 
     263             : //_____________________________________________________________________________
     264             : void
     265             : AliMUONDigitizerV3::ApplyResponse(const AliMUONVDigitStore& store,
     266             :                                   AliMUONVDigitStore& filteredStore)
     267             : {
     268             :   /// Loop over all chamber digits, and apply the response to them
     269             :   /// Note that this method may remove digits.
     270             : 
     271           8 :   filteredStore.Clear();
     272             :   
     273             :   const Bool_t kAddNoise = kTRUE;
     274             :   
     275           4 :   TIter next(store.CreateIterator());
     276             :   AliMUONVDigit* digit;
     277             :   
     278           8 :   if ( fTriggerEfficiency ) fEfficiencyResponse.Reset(-1);
     279             :   
     280        2915 :   while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) )
     281             :   {
     282        1938 :     AliMp::StationType stationType = AliMpDEManager::GetStationType(digit->DetElemId());
     283             :     
     284         969 :     if ( stationType != AliMp::kStationTrigger )
     285             :     {
     286             :       Bool_t addNoise = kAddNoise;
     287        1714 :       if (digit->IsConverted()) addNoise = kFALSE; // No need to add extra noise to a converted real digit
     288         857 :       ApplyResponseToTrackerDigit(*digit,addNoise);
     289         857 :     }
     290             :     else {
     291         112 :       ApplyResponseToTriggerDigit(*digit);
     292             :     }
     293             : 
     294        2460 :     if ( digit->ADC() > 0  || digit->Charge() > 0 )
     295             :     {
     296         820 :       filteredStore.Add(*digit,AliMUONVDigitStore::kIgnore);
     297             :     }
     298             :   }
     299           4 : }    
     300             : 
     301             : //_____________________________________________________________________________
     302             : Int_t 
     303             : AliMUONDigitizerV3::DecalibrateTrackerDigit(const AliMUONVCalibParam& pedestals,
     304             :                                             Int_t channel,
     305             :                                             Float_t charge,
     306             :                                             Bool_t addNoise,
     307             :                                             Bool_t noiseOnly)
     308             : {
     309             :   /// Decalibrate (i.e. go from charge to adc) a tracker digit, given its
     310             :   /// pedestal and gain parameters.
     311             :   /// Must insure before calling that channel is valid (i.e. between 0 and
     312             :   /// pedestals->GetSize()-1, but also corresponding to a valid channel
     313             :   /// otherwise results are not predictible...)
     314             :   ///
     315             :   /// This method is completely tied to what happens in its sister method :
     316             :   /// AliMUONDigitCalibrator::CalibrateDigit, which is doing the reverse work...
     317             :   ///
     318             :   
     319             :   static const Int_t kMaxADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
     320             :   
     321             :   Int_t thres(4095);
     322             :   Int_t qual(0xF);
     323         857 :   Float_t capa(AliMUONConstants::DefaultCapa()); // capa = 0.2 and a0 = 1.25
     324         857 :   Float_t a0(AliMUONConstants::DefaultA0());  // is equivalent to gain = 4 mV/fC
     325         857 :   Float_t adc2mv(AliMUONConstants::DefaultADC2MV()); // 1 ADC channel = 0.61 mV
     326             :                
     327         857 :   Float_t pedestalMean = pedestals.ValueAsFloat(channel,0);
     328         857 :   Float_t pedestalSigma = pedestals.ValueAsFloat(channel,1);
     329             :   
     330        2571 :   AliDebugClass(2,Form("DE %04d MANU %04d CH %02d PEDMEAN %7.2f PEDSIGMA %7.2f",
     331             :                        pedestals.ID0(),pedestals.ID1(),channel,pedestalMean,pedestalSigma));
     332             :   
     333         857 :   if ( qual <= 0 ) return 0;
     334             :   
     335             :   Float_t chargeThres = a0*thres;
     336             :   
     337         857 :   Float_t padc = charge/a0; // (adc - ped) value
     338             :   
     339         857 :   padc /= capa*adc2mv;
     340             :   
     341             :   Int_t adc(0);
     342             :   
     343             :   Float_t adcNoise = 0.0;
     344             :     
     345         857 :   if ( addNoise ) 
     346             :   {
     347         857 :     if ( noiseOnly )
     348             :     {      
     349           0 :       adcNoise = NoiseFunction()->GetRandom()*pedestalSigma;
     350           0 :     }
     351             :     else
     352             :     {
     353         857 :       adcNoise = gRandom->Gaus(0.0,pedestalSigma);
     354             :     }
     355             :   }
     356             :     
     357         857 :   adc = TMath::Nint(padc + pedestalMean + adcNoise + 0.5);
     358             :   
     359         857 :   if ( adc < TMath::Nint(pedestalMean + fgNSigmas*pedestalSigma + 0.5) ) 
     360             :   {
     361             :     // this is an error only in specific cases
     362         447 :     if ( !addNoise || (addNoise && noiseOnly) ) 
     363             :     {
     364           0 :       AliDebugClass(1,Form(" DE %04d Manu %04d Channel %02d "
     365             :                                                                                                          " a0 %7.2f thres %04d ped %7.2f pedsig %7.2f adcNoise %7.2f "
     366             :                                                                                                          " charge=%7.2f padc=%7.2f adc=%04d ZS=%04d fgNSigmas=%e addNoise %d noiseOnly %d ",
     367             :                                                                                                          pedestals.ID0(),pedestals.ID1(),channel, 
     368             :                                                                                                          a0, thres, pedestalMean, pedestalSigma, adcNoise,
     369             :                                                                                                          charge, padc, adc, 
     370             :                                                                                                          TMath::Nint(pedestalMean + fgNSigmas*pedestalSigma + 0.5),
     371             :                                                                                                          fgNSigmas,addNoise,noiseOnly));
     372             :     }
     373             :     
     374             :     adc = 0;
     375         149 :   }
     376             :   
     377             :   // be sure we stick to 12 bits.
     378         857 :   if ( adc > kMaxADC )
     379             :   {
     380             :     adc = kMaxADC;
     381           0 :   }
     382             :   
     383             :   return adc;
     384         857 : }
     385             : 
     386             : //_____________________________________________________________________________
     387             : void
     388             : AliMUONDigitizerV3::CreateInputDigitStores()
     389             : {
     390             :   /// Create input digit stores
     391             :   /// 
     392             :   
     393           2 :   if (fInputDigitStores)
     394             :   {
     395           0 :     AliFatal("Should be called only once !");
     396           0 :   }
     397             :   
     398           2 :   fInputDigitStores = new TObjArray;
     399             :   
     400           1 :   fInputDigitStores->SetOwner(kTRUE);
     401             :   
     402           4 :   for ( Int_t iFile = 0; iFile < fDigInput->GetNinputs(); ++iFile )
     403             :   {    
     404           1 :     AliLoader* inputLoader = GetLoader(fDigInput->GetInputFolderName(iFile));
     405             :     
     406           1 :     inputLoader->LoadSDigits("READ");
     407             :     
     408           1 :     TTree* iTreeS = inputLoader->TreeS();
     409           1 :     if (!iTreeS)
     410             :     {
     411           0 :       AliFatal(Form("Could not get access to input file #%d",iFile));
     412           0 :     }
     413             :     
     414           1 :     fInputDigitStores->AddAt(AliMUONVDigitStore::Create(*iTreeS),iFile);
     415             :   }
     416           1 : }
     417             : 
     418             : //_____________________________________________________________________________
     419             : void
     420             : AliMUONDigitizerV3::Digitize(Option_t*)
     421             : {
     422             :   /// Main method.
     423             :   /// We first loop over input files, and merge the sdigits we found there.
     424             :   /// Second, we digitize all the resulting sdigits
     425             :   /// Then we generate noise-only digits (for tracker only)
     426             :   /// And we finally generate the trigger outputs.
     427             :     
     428           8 :   AliCodeTimerAuto("",0)
     429             :   
     430           4 :   if ( fDigInput->GetNinputs() == 0 )
     431             :   {
     432           0 :     AliWarning("No input set. Nothing to do.");
     433           0 :     return;
     434             :   }
     435             :   
     436           4 :   if ( !fIsInitialized )
     437             :   {
     438           0 :     AliError("Not initialized. Cannot perform the work. Sorry");
     439           0 :     return;
     440             :   }
     441             :   
     442           4 :   Int_t nInputFiles = fDigInput->GetNinputs();
     443             :   
     444          16 :   AliLoader* outputLoader = GetLoader(fDigInput->GetOutputFolderName());
     445             :   
     446           4 :   outputLoader->MakeDigitsContainer();
     447             :   
     448           4 :   TTree* oTreeD = outputLoader->TreeD();
     449             :   
     450           4 :   if (!oTreeD) 
     451             :   {
     452           0 :     AliFatal("Cannot create output TreeD");
     453             :   }
     454             : 
     455             :   // Loop over all the input files, and merge the sdigits found in those
     456             :   // files.
     457             :   
     458          16 :   for ( Int_t iFile = 0; iFile < nInputFiles; ++iFile )
     459             :   {  
     460           8 :     AliLoader* inputLoader = GetLoader(fDigInput->GetInputFolderName(iFile));
     461             : 
     462           4 :     inputLoader->LoadSDigits("READ");
     463             : 
     464           4 :     TTree* iTreeS = inputLoader->TreeS();
     465           4 :     if (!iTreeS)
     466             :     {
     467           0 :       AliFatal(Form("Could not get access to input file #%d",iFile));
     468             :     }
     469             : 
     470           4 :     if (!fInputDigitStores)
     471             :     {
     472           1 :       CreateInputDigitStores();      
     473             :     }
     474             :     
     475           8 :     AliMUONVDigitStore* dstore = static_cast<AliMUONVDigitStore*>(fInputDigitStores->At(iFile));
     476             :     
     477           4 :     dstore->Connect(*iTreeS);
     478             :     
     479           4 :     iTreeS->GetEvent(0);
     480             : 
     481           4 :     MergeWithSDigits(fDigitStore,*dstore,fDigInput->GetMask(iFile));
     482             : 
     483           4 :     inputLoader->UnloadSDigits();
     484             :     
     485           4 :     dstore->Clear();
     486             :   }
     487             : 
     488             :   
     489             :   // At this point, we do have digit arrays (one per chamber) which contains 
     490             :   // the merging of all the sdigits of the input file(s).
     491             :   // We now massage them to apply the detector response, i.e. this
     492             :   // is here that we do the "digitization" work.
     493             :   
     494           4 :   if (!fOutputDigitStore)
     495             :   {
     496           2 :     fOutputDigitStore = fDigitStore->Create();
     497           1 :   }
     498             :   
     499           4 :   if ( fGenerateNoisyDigits>=2 )
     500             :   {
     501             :     // Generate noise-only digits for trigger.
     502           0 :     GenerateNoisyDigitsForTrigger(*fDigitStore);
     503             :   }
     504           4 :   ApplyResponse(*fDigitStore,*fOutputDigitStore);
     505             : 
     506           4 :   if ( fGenerateNoisyDigits )
     507             :   {
     508             :     // Generate noise-only digits for tracker.
     509           4 :     GenerateNoisyDigits(*fOutputDigitStore);
     510             :   }
     511             :   
     512             :   // We generate the global and local trigger decisions.
     513           4 :   fTriggerProcessor->Digits2Trigger(*fOutputDigitStore,*fTriggerStore);
     514             : 
     515             :   // Prepare output tree
     516           8 :   Bool_t okD = fOutputDigitStore->Connect(*oTreeD,kFALSE);
     517           8 :   Bool_t okT = fTriggerStore->Connect(*oTreeD,kFALSE);
     518           8 :   if (!okD || !okT)
     519             :   {
     520           0 :     AliError(Form("Could not make branch : Digit %d Trigger %d",okD,okT));
     521           0 :     return;
     522             :   }
     523             :   
     524             :   // Fill the output treeD
     525           4 :   oTreeD->Fill();
     526             :   
     527             :   // Write to the output tree(D).
     528             :   // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
     529             :   // tree (=TreeD) in different branches, this WriteDigits in fact writes all of 
     530             :   // the 3 branches.
     531           4 :   outputLoader->WriteDigits("OVERWRITE");  
     532             :   
     533           4 :   outputLoader->UnloadDigits();
     534             :   
     535             :   // Finally, we clean up after ourselves.
     536           4 :   fTriggerStore->Clear();
     537           4 :   fDigitStore->Clear();
     538           4 :   fOutputDigitStore->Clear();
     539           8 : }
     540             : 
     541             : 
     542             : //_____________________________________________________________________________
     543             : void
     544             : AliMUONDigitizerV3::GenerateNoisyDigits(AliMUONVDigitStore& digitStore)
     545             : {
     546             :   /// According to a given probability, generate digits that
     547             :   /// have a signal above the noise cut (ped+n*sigma_ped), i.e. digits
     548             :   /// that are "only noise".
     549             :   
     550           8 :   AliCodeTimerAuto("",0)
     551             :   
     552         132 :   for ( Int_t i = 0; i < AliMUONConstants::NTrackingCh(); ++i )
     553             :   {
     554          40 :     AliMpDEIterator it;
     555             :   
     556          40 :     it.First(i);
     557             :   
     558        1328 :     while ( !it.IsDone() )
     559             :     {
     560        3744 :       for ( Int_t cathode = 0; cathode < 2; ++cathode )
     561             :       {
     562        2496 :         GenerateNoisyDigitsForOneCathode(digitStore,it.CurrentDEId(),cathode);
     563             :       }
     564         624 :       it.Next();
     565             :     }
     566          40 :   }
     567           4 : }
     568             :  
     569             : //_____________________________________________________________________________
     570             : void
     571             : AliMUONDigitizerV3::GenerateNoisyDigitsForOneCathode(AliMUONVDigitStore& digitStore,
     572             :                                                      Int_t detElemId, Int_t cathode)
     573             : {
     574             :   /// Generate noise-only digits for one cathode of one detection element.
     575             :   /// Called by GenerateNoisyDigits()
     576             :   
     577             :   const AliMpVSegmentation* seg 
     578        2496 :     = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
     579        1248 :   Int_t nofPads = seg->NofPads();
     580             :   
     581        1248 :   Int_t maxIx = seg->MaxPadIndexX();
     582        1248 :   Int_t maxIy = seg->MaxPadIndexY();
     583             :   
     584        1251 :   static const Double_t kProbToBeOutsideNsigmas = TMath::Erfc(fgNSigmas/TMath::Sqrt(2.0)) / 2. ;
     585             :   
     586        1248 :   Int_t nofNoisyPads = TMath::Nint(kProbToBeOutsideNsigmas*nofPads);
     587        2496 :   if ( !nofNoisyPads ) return;
     588             :   
     589             :   nofNoisyPads = 
     590           0 :     TMath::Nint(gRandom->Gaus(nofNoisyPads,
     591           0 :                               nofNoisyPads/TMath::Sqrt(nofNoisyPads)));
     592             :   
     593           0 :   AliDebug(3,Form("DE %d cath %d nofNoisyPads %d",detElemId,cathode,nofNoisyPads));
     594             :   
     595           0 :   for ( Int_t i = 0; i < nofNoisyPads; ++i ) 
     596             :   {
     597             :     Int_t ix(-1);
     598             :     Int_t iy(-1);
     599           0 :     AliMpPad pad;
     600             :     
     601           0 :     do {
     602           0 :       ix = gRandom->Integer(maxIx+1);
     603           0 :       iy = gRandom->Integer(maxIy+1);
     604           0 :       pad = seg->PadByIndices(ix,iy,kFALSE);
     605           0 :     } while ( !pad.IsValid() );
     606             : 
     607           0 :     Int_t manuId = pad.GetManuId();
     608           0 :     Int_t manuChannel = pad.GetManuChannel();    
     609             : 
     610           0 :     AliMUONVCalibParam* pedestals = fCalibrationData->Pedestals(detElemId,manuId);
     611             :     
     612           0 :     if (!pedestals) 
     613             :     {
     614             :       // no pedestal available for this channel, simply give up
     615           0 :       continue;
     616             :     }
     617             :     
     618           0 :     AliMUONVDigit* d = digitStore.CreateDigit(detElemId,manuId,manuChannel,cathode);
     619             :     
     620           0 :     d->SetPadXY(ix,iy);
     621             :     
     622           0 :     d->SetCharge(0.0); // charge is zero, the ApplyResponseToTrackerDigit will add the noise
     623           0 :     d->NoiseOnly(kTRUE);
     624           0 :     ApplyResponseToTrackerDigit(*d,kTRUE);
     625           0 :     if ( d->ADC() > 0 )
     626             :     {
     627           0 :       Bool_t ok = digitStore.Add(*d,AliMUONVDigitStore::kDeny);
     628             :       // this can happen (that we randomly chose a digit that is
     629             :       // already there). We simply ignore this, but log the occurence
     630             :       // to cross-check that it's not too frequent.
     631           0 :       if (!ok)
     632             :       {
     633           0 :         fLogger->Log("Collision while adding noiseOnly digit");
     634             :       }
     635             :       else
     636             :       {
     637           0 :         fLogger->Log("Added noiseOnly digit");
     638             :       }
     639           0 :     }
     640           0 :     delete d;
     641           0 :   }
     642        1248 : }
     643             : 
     644             : 
     645             : //_____________________________________________________________________________
     646             : void
     647             : AliMUONDigitizerV3::GenerateNoisyDigitsForTrigger(AliMUONVDigitStore& digitStore)
     648             : {
     649             :   /// Generate noise-only digits for one cathode of one detection element.
     650             :   /// Called by GenerateNoisyDigits()
     651             : 
     652           0 :   if ( !fNoiseFunctionTrig )
     653             :   {
     654           0 :     fNoiseFunctionTrig = new TF1("AliMUONDigitizerV3::fNoiseFunctionTrig","landau",
     655             :                                  50.,270.);
     656             :     
     657           0 :     fNoiseFunctionTrig->SetParameters(3.91070e+02, 9.85026, 9.35881e-02);
     658           0 :   }
     659             : 
     660           0 :   AliMpPad pad[2];
     661           0 :   AliMUONVDigit *d[2]={0x0};
     662             : 
     663           0 :   for ( Int_t chamberId = AliMUONConstants::NTrackingCh(); chamberId < AliMUONConstants::NCh(); ++chamberId )
     664             :   {
     665             :   
     666             :     Int_t nofNoisyPads = 50;
     667             : 
     668           0 :     Float_t r=-1, fi = 0., gx, gy, x, y, z, xg01, yg01, zg, xg02, yg02;
     669           0 :     AliMpDEIterator it;
     670             :   
     671           0 :     AliDebug(3,Form("Chamber %d nofNoisyPads %d",chamberId,nofNoisyPads));
     672             : 
     673           0 :     for ( Int_t i = 0; i < nofNoisyPads; ++i )
     674             :     {
     675             :       //printf("Generating noise %i\n",i);
     676             :         Int_t ix(-1);
     677             :         Int_t iy(-1);
     678             :         Bool_t isOk = kFALSE;
     679             :         Int_t detElemId = -1;
     680           0 :         do {
     681             :           //r = gRandom->Landau(9.85026, 9.35881e-02);
     682           0 :             r = fNoiseFunctionTrig->GetRandom();
     683           0 :             fi = 2. * TMath::Pi() * gRandom->Rndm();
     684             :             //printf("r = %f\tfi = %f\n", r, fi);
     685           0 :             gx = r * TMath::Cos(fi);
     686           0 :             gy = r * TMath::Sin(fi);
     687             : 
     688           0 :             for ( it.First(chamberId); ! it.IsDone(); it.Next() ){
     689           0 :                 Int_t currDetElemId = it.CurrentDEId();
     690             :                 const AliMpVSegmentation* seg
     691           0 :                     = AliMpSegmentation::Instance()->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(0));
     692           0 :                 if (!seg) continue;
     693           0 :                 Float_t deltax = seg->GetDimensionX();
     694           0 :                 Float_t deltay = seg->GetDimensionY();
     695           0 :                 GetTransformer()->Local2Global(currDetElemId, -deltax, -deltay, 0, xg01, yg01, zg);
     696           0 :                 GetTransformer()->Local2Global(currDetElemId,  deltax,  deltay, 0, xg02, yg02, zg);
     697           0 :                 Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
     698           0 :                 if(xg01>xg02){
     699             :                     xg1 = xg02;
     700             :                     xg2 = xg01;
     701           0 :                 }
     702           0 :                 if(yg01>yg02){
     703             :                     yg1 = yg02;
     704             :                     yg2 = yg01;
     705           0 :                 }
     706           0 :                 if(gx>=xg1 && gx<=xg2 && gy>=yg1 && gy<=yg2){
     707             :                     detElemId = currDetElemId;
     708           0 :                     GetTransformer()->Global2Local(detElemId, gx, gy, 0, x, y, z);
     709           0 :                     pad[0] = seg->PadByPosition(x,y,kFALSE);
     710           0 :                     if(!pad[0].IsValid()) continue;
     711             :                     isOk = kTRUE;
     712           0 :                     break;
     713             :                 }
     714           0 :             } // loop on slats
     715           0 :         } while ( !isOk );
     716             : 
     717             :         const AliMpVSegmentation* seg1
     718           0 :             = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(1));
     719           0 :         pad[1] = seg1->PadByPosition(x,y,kFALSE);
     720             : 
     721           0 :         for ( Int_t cathode = 0; cathode < 2; ++cathode ){
     722           0 :           Int_t manuId = pad[cathode].GetLocalBoardId(0);
     723           0 :           Int_t manuChannel = pad[cathode].GetLocalBoardChannel(0);    
     724           0 :           d[cathode] = digitStore.CreateDigit(detElemId,manuId,manuChannel,cathode);
     725           0 :           ix = pad[cathode].GetIx();
     726           0 :           iy = pad[cathode].GetIy();
     727           0 :           d[cathode]->SetPadXY(ix,iy);
     728             :           //d[cathode].SetSignal(1);
     729             :           //d[cathode].SetPhysicsSignal(0);
     730           0 :           d[cathode]->SetCharge(1);
     731           0 :           d[cathode]->NoiseOnly(kTRUE);
     732           0 :           AliDebug(3,Form("Adding a pure noise digit :"));
     733             : 
     734           0 :           Bool_t ok = digitStore.Add(*d[cathode],AliMUONVDigitStore::kDeny);
     735           0 :           if (!ok)
     736             :           {
     737           0 :               fLogger->Log("Collision while adding TriggerNoise digit");
     738             :           }
     739             :           else
     740             :           {
     741           0 :               fLogger->Log("Added triggerNoise digit");
     742             :           }
     743             :         } //loop on cathodes
     744             :     } // loop on noisy pads
     745           0 :   } // loop on chambers
     746           0 : }
     747             : 
     748             : 
     749             : //_____________________________________________________________________________
     750             : AliLoader*
     751             : AliMUONDigitizerV3::GetLoader(const TString& folderName)
     752             : {
     753             :   /// Get a MUON loader
     754             : 
     755          36 :   AliDebug(2,Form("Getting access to folder %s",folderName.Data()));
     756           9 :   AliLoader* loader = AliRunLoader::GetDetectorLoader("MUON",folderName.Data());
     757           9 :   if (!loader)
     758             :   {
     759           0 :     AliError(Form("Could not get MuonLoader from folder %s",folderName.Data()));
     760           0 :     return 0x0;
     761             :   }
     762           9 :   return loader;
     763           9 : }
     764             : 
     765             : //_____________________________________________________________________________
     766             : Bool_t
     767             : AliMUONDigitizerV3::Init()
     768             : {
     769             :   /// Initialization of the digitization :
     770             :   /// a) create the calibrationData, according to run number
     771             :   /// b) create the trigger processing task
     772             : 
     773           4 :   AliDebug(2,"");
     774             :   
     775           1 :   if ( fIsInitialized )
     776             :   {
     777           0 :     AliError("Object already initialized.");
     778           0 :     return kFALSE;
     779             :   }
     780             :   
     781           1 :   if (!fDigInput)
     782             :   {
     783           0 :     AliError("fDigInput is null !");
     784           0 :     return kFALSE;
     785             :   }
     786             :   
     787             :   // Load mapping
     788           1 :   if ( ! AliMpCDB::LoadDDLStore() ) {
     789           0 :     AliFatal("Could not access mapping from OCDB !");
     790           0 :   }
     791             :   
     792           1 :   if (!fCalibrationData)
     793           0 :       AliFatal("Calibration data object not defined");
     794             : 
     795           1 :   if ( !fCalibrationData->Pedestals() )
     796             :   {
     797           0 :     AliFatal("Could not access pedestals from OCDB !");
     798           0 :   }
     799             :   
     800           1 :   AliInfo("Using trigger configuration from CDB");
     801             :   
     802           2 :   fTriggerProcessor = new AliMUONTriggerElectronics(fCalibrationData);
     803             :   
     804           3 :   AliDebug(1, Form("Will %s generate noise-only digits for tracker",
     805             :                      (fGenerateNoisyDigits ? "":"NOT")));
     806             :   
     807           2 :   fTriggerUtilities = new AliMUONTriggerUtilities(fCalibrationData);
     808             :   
     809           1 :   if ( muon()->GetTriggerEffCells() ) {
     810             :     // Apply trigger efficiency
     811           3 :     AliDebug(1, "Will apply trigger efficiency");
     812           3 :     fTriggerEfficiency = new AliMUONTriggerChamberEfficiency(fCalibrationData->TriggerEfficiency());
     813           1 :   }
     814             : 
     815           1 :   fIsInitialized = kTRUE;
     816           1 :   return kTRUE;
     817           1 : }
     818             : 
     819             : 
     820             : //_____________________________________________________________________________
     821             : Int_t AliMUONDigitizerV3::GetArrayIndex(Int_t cathode, Int_t trigCh, Int_t localCircuit)
     822             : {
     823             :   /// Get index of array with trigger status map or efficiency
     824         198 :   return
     825         594 :     AliMUONConstants::NTriggerCircuit() * AliMUONConstants::NTriggerCh() * cathode +
     826         396 :     AliMUONConstants::NTriggerCircuit() * trigCh + localCircuit-1;
     827             : }
     828             : 
     829             : 
     830             : //_____________________________________________________________________________
     831             : void 
     832             : AliMUONDigitizerV3::MergeWithSDigits(AliMUONVDigitStore*& outputStore,
     833             :                                      const AliMUONVDigitStore& input,
     834             :                                      Int_t mask)
     835             : {
     836             :   /// Merge the sdigits in inputData with the digits already present in outputData
     837             :   
     838           9 :   if ( !outputStore ) outputStore = input.Create();
     839             :   
     840           4 :   TIter next(input.CreateIterator());
     841             :   AliMUONVDigit* sdigit;
     842             :   
     843        2919 :   while ( ( sdigit = static_cast<AliMUONVDigit*>(next()) ) )
     844             :   {
     845             :     // Update the track references using the mask.
     846             :     // FIXME: this is dirty, for backward compatibility only.
     847             :     // Should re-design all this way of keeping track of MC information...
     848         969 :     if ( mask ) sdigit->PatchTracks(mask);
     849             :     // Then add or update the digit to the output.
     850         969 :     AliMUONVDigit* added = outputStore->Add(*sdigit,AliMUONVDigitStore::kMerge);
     851         969 :     if (!added)
     852             :     {
     853           0 :       AliError("Could not add digit in merge mode");
     854             :     }
     855             :   }
     856           4 : }
     857             : 
     858             : //_____________________________________________________________________________
     859             : TF1*
     860             : AliMUONDigitizerV3::NoiseFunction()
     861             : {
     862             :   /// Return noise function
     863             :   static TF1* f = 0x0;
     864           0 :   if (!f)
     865             :   {
     866           0 :     f = new TF1("AliMUONDigitizerV3::NoiseFunction","gaus",fgNSigmas,fgNSigmas*10);
     867           0 :     f->SetParameters(1,0,1);
     868           0 :   }
     869           0 :   return f;
     870           0 : }
     871             : 
     872             : //_____________________________________________________________________________
     873             : void AliMUONDigitizerV3::SetCalibrationData(AliMUONCalibrationData* calibrationData, 
     874             :                                             AliMUONRecoParam* recoParam) 
     875             : {
     876           2 :   fCalibrationData = calibrationData;
     877           1 :   fRecoParam = recoParam;
     878           1 :   if (!fRecoParam)
     879             :   {
     880           0 :     AliError("Cannot work (e.g. decalibrate) without recoparams !");
     881           0 :   }
     882           1 : }
     883             : 

Generated by: LCOV version 1.11