/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
* *
* Author: The ALICE Off-line Project. *
* Contributors are mentioned in the code where appropriate. *
* about the suitability of this software for any purpose. It is *
* provided "as is" without express or implied warranty. *
**************************************************************************/
-
-//_________________________________________________________________________
-// This is a TTask that constructs SDigits out of Hits
-// A Summable Digits is the sum of all hits in a cell
-// A threshold is applied
+/* $Id$ */
+/** @file AliFMDSDigitizer.cxx
+ @author Christian Holm Christensen <cholm@nbi.dk>
+ @date Mon Mar 27 12:38:26 2006
+ @brief FMD Digitizers implementation
+ @ingroup FMD_sim
+*/
+//////////////////////////////////////////////////////////////////////////////
+//
+// This class contains the procedures simulation ADC signal for the
+// Forward Multiplicity detector : Hits->Digits and Hits->SDigits
+//
+// Digits consists of
+// - Detector #
+// - Ring ID
+// - Sector #
+// - Strip #
+// - ADC count in this channel
+//
+// Digits consists of
+// - Detector #
+// - Ring ID
+// - Sector #
+// - Strip #
+// - Total energy deposited in the strip
+// - ADC count in this channel
+//
+// As the Digits and SDigits have so much in common, the classes
+// AliFMDDigitizer and AliFMDSDigitizer are implemented via a base
+// class AliFMDBaseDigitizer.
+//
+// +---------------------+
+// | AliFMDBaseDigitizer |
+// +---------------------+
+// ^
+// |
+// +----------+---------+
+// | |
+// +-----------------+ +------------------+
+// | AliFMDDigitizer | | AliFMDSDigitizer |
+// +-----------------+ +------------------+
+//
+// These classes has several paramters:
+//
+// fPedestal
+// fPedestalWidth
+// (Only AliFMDDigitizer)
+// Mean and width of the pedestal. The pedestal is simulated
+// by a Guassian, but derived classes my override MakePedestal
+// to simulate it differently (or pick it up from a database).
+//
+// fVA1MipRange
+// The dymamic MIP range of the VA1_ALICE pre-amplifier chip
+//
+// fAltroChannelSize
+// The largest number plus one that can be stored in one
+// channel in one time step in the ALTRO ADC chip.
+//
+// fSampleRate
+// How many times the ALTRO ADC chip samples the VA1_ALICE
+// pre-amplifier signal. The VA1_ALICE chip is read-out at
+// 10MHz, while it's possible to drive the ALTRO chip at
+// 25MHz. That means, that the ALTRO chip can have time to
+// sample each VA1_ALICE signal up to 2 times. Although it's
+// not certain this feature will be used in the production,
+// we'd like have the option, and so it should be reflected in
+// the code.
+//
+//
+// The shaping function of the VA1_ALICE is generally given by
+//
+// f(x) = A(1 - exp(-Bx))
+//
+// where A is the total charge collected in the pre-amp., and B is a
+// paramter that depends on the shaping time of the VA1_ALICE circut.
+//
+// When simulating the shaping function of the VA1_ALICe
+// pre-amp. chip, we have to take into account, that the shaping
+// function depends on the previous value of read from the pre-amp.
+//
+// That results in the following algorithm:
+//
+// last = 0;
+// FOR charge IN pre-amp. charge train DO
+// IF last < charge THEN
+// f(t) = (charge - last) * (1 - exp(-B * t)) + last
+// ELSE
+// f(t) = (last - charge) * exp(-B * t) + charge)
+// ENDIF
+// FOR i IN # samples DO
+// adc_i = f(i / (# samples))
+// DONE
+// last = charge
+// DONE
+//
+// Here,
+//
+// pre-amp. charge train
+// is a series of 128 charges read from the VA1_ALICE chip
+//
+// # samples
+// is the number of times the ALTRO ADC samples each of the 128
+// charges from the pre-amp.
+//
+// Where Q is the total charge collected by the VA1_ALICE
+// pre-amplifier. Q is then given by
+//
+// E S
+// Q = - -
+// e R
+//
+// where E is the total energy deposited in a silicon strip, R is the
+// dynamic range of the VA1_ALICE pre-amp (fVA1MipRange), e is the
+// energy deposited by a single MIP, and S ALTRO channel size in each
+// time step (fAltroChannelSize).
+//
+// The energy deposited per MIP is given by
+//
+// e = M * rho * w
+//
+// where M is the universal number 1.664, rho is the density of
+// silicon, and w is the depth of the silicon sensor.
+//
+// The final ADC count is given by
+//
+// C' = C + P
+//
+// where P is the (randomized) pedestal (see MakePedestal)
+//
+// This class uses the class template AliFMDMap<Type> to make an
+// internal cache of the energy deposted of the hits. The class
+// template is instantasized as
+//
+// typedef AliFMDMap<std::pair<Float_t, UShort_t> > AliFMDEdepMap;
+//
+// The first member of the values is the summed energy deposition in a
+// given strip, while the second member of the values is the number of
+// hits in a given strip. Using the second member, it's possible to
+// do some checks on just how many times a strip got hit, and what
+// kind of error we get in our reconstructed hits. Note, that this
+// information is currently not written to the digits tree. I think a
+// QA (Quality Assurance) digit tree is better suited for that task.
+// However, the information is there to be used in the future.
+//
+//
+// Latest changes by Christian Holm Christensen
//
-//-- Author: Alla Maevskaia(INR)
//////////////////////////////////////////////////////////////////////////////
-// --- ROOT system ---
-#include "TTask.h"
-#include "TTree.h"
-#include "TSystem.h"
-#include "TFile.h"
-// --- Standard library ---
-
-// --- AliRoot header files ---
-
-#include "AliFMDdigit.h"
-#include "AliFMDhit.h"
-#include "AliFMD.h"
-#include "AliFMDv1.h"
-#include "AliFMDSDigitizer.h"
-#include "AliRun.h"
-#include "AliDetector.h"
-#include "AliMC.h"
-
-#include "TROOT.h"
-#include "TFolder.h"
-#include <stdlib.h>
-#include <iostream.h>
-#include <fstream.h>
+// /1
+// | A(-1 + B + exp(-B))
+// | f(x) dx = ------------------- = 1
+// | B
+// / 0
+//
+// and B is the a parameter defined by the shaping time (fShapingTime).
+//
+// Solving the above equation, for A gives
+//
+// B
+// A = ----------------
+// -1 + B + exp(-B)
+//
+// So, if we define the function g: [0,1] -> [0:1] by
+//
+// / v
+// | Bu + exp(-Bu) - Bv - exp(-Bv)
+// g(u,v) = | f(x) dx = -A -----------------------------
+// | B
+// / u
+//
+// we can evaluate the ALTRO sample of the VA1_ALICE pre-amp between
+// any two times (u, v), by
+//
+//
+// B Bu + exp(-Bu) - Bv - exp(-Bv)
+// C = Q g(u,v) = - Q ---------------- -----------------------------
+// -1 + B + exp(-B) B
+//
+// Bu + exp(-Bu) - Bv - exp(-Bv)
+// = - Q -----------------------------
+// -1 + B + exp(-B)
+//
+// #include <TTree.h> // ROOT_TTree
+//#include <TRandom.h> // ROOT_TRandom
+#include <AliLog.h> // ALILOG_H
+#include "AliFMDSDigitizer.h" // ALIFMDDIGITIZER_H
+#include "AliFMD.h" // ALIFMD_H
+// #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
+// #include "AliFMDDetector.h" // ALIFMDDETECTOR_H
+// #include "AliFMDRing.h" // ALIFMDRING_H
+#include "AliFMDHit.h" // ALIFMDHIT_H
+// #include "AliFMDDigit.h" // ALIFMDDIGIT_H
+// #include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
+// #include <AliRunDigitizer.h> // ALIRUNDIGITIZER_H
+#include <AliRun.h> // ALIRUN_H
+#include <AliLoader.h> // ALILOADER_H
+#include <AliRunLoader.h> // ALIRUNLOADER_H
+
+//====================================================================
ClassImp(AliFMDSDigitizer)
-
-//____________________________________________________________________________
- AliFMDSDigitizer::AliFMDSDigitizer():TTask("AliFMDSDigitizer","")
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer()
{
- fNevents = 0 ; // Number of events to digitize, 0 means all evens in current file
- // add Task to //root/Tasks folder
- TTask * roottasks = (TTask*)gROOT->GetRootFolder()->FindObject("Tasks") ;
- roottasks->Add(this) ;
+ // Default ctor - don't use it
}
-//____________________________________________________________________________
-AliFMDSDigitizer::AliFMDSDigitizer(char* HeaderFile, char *SDigitsFile):TTask("AliFMDSDigitizer","")
+
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer(const Char_t* headerFile,
+ const Char_t* /* sdigfile */)
+ : AliFMDBaseDigitizer("FMDSDigitizer", "FMD SDigitizer")
{
- // ctor
- fNevents = 0 ; // Number of events to digitize, 0 means all events in current file
- fSDigitsFile = SDigitsFile ;
- fHeadersFile = HeaderFile ;
- //add Task to //root/Tasks folder
- TTask * roottasks = (TTask*)gROOT->GetRootFolder()->FindObject("Tasks") ;
- roottasks->Add(this) ;
-
+ // Normal CTOR
+ AliDebug(1," processed");
+
+ fRunLoader = AliRunLoader::GetRunLoader(); // Open(headerFile);
+ if (!fRunLoader)
+ Fatal("AliFMDSDigitizer", "cannot open session, header file '%s'",
+ headerFile);
+ AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
+ if (!loader)
+ Fatal("AliFMDSDigitizer", "cannot find FMD loader in specified event");
+
+ // Add task to tasks folder
+ loader->PostSDigitizer(this);
+
}
-//____________________________________________________________________________
- AliFMDSDigitizer::~AliFMDSDigitizer()
+//____________________________________________________________________
+AliFMDSDigitizer::~AliFMDSDigitizer()
{
- // dtor
+ // Destructor
+ AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
+ loader->CleanSDigitizer();
}
-
-//____________________________________________________________________________
-void AliFMDSDigitizer::Exec(Option_t *option) {
- //Collects all hits in the same active volume into digit
- TClonesArray * sdigits = new TClonesArray("AliFMDdigit",1000) ;
- TFile * file = 0;
-
- AliFMD * FMD = (AliFMD *) gAlice->GetDetector("FMD") ;
+//____________________________________________________________________
+void
+AliFMDSDigitizer::Exec(Option_t*)
+{
+ // Get the output manager
+ if (!fRunLoader) {
+ Error("Exec", "Run loader is not set");
+ return;
+ }
+ if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
+ if (!fRunLoader->TreeE()) fRunLoader->LoadHeader();
- if(fNevents == 0)
- fNevents = (Int_t) gAlice->TreeE()->GetEntries() ;
+ AliLoader* fmdLoader = fRunLoader->GetLoader("FMDLoader");
+ if (!fmdLoader) Fatal("Exec", "no FMD loader");
+
+ // Get the AliFMD object
+ AliFMD* fmd =
+ static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
+ if (!fmd) {
+ AliError("Can not get FMD from gAlice");
+ return;
+ }
- cout<<"AliFMDSDigitizer-> Nevents"<<fNevents<<endl;
- for(Int_t ievent = 0; ievent < fNevents; ievent++){
- gAlice->GetEvent(ievent) ;
- if(gAlice->TreeH()==0) return ;
+ Int_t nEvents = Int_t(fRunLoader->TreeE()->GetEntries());
+ for (Int_t event = 0; event < nEvents; event++) {
+ AliDebug(1,Form(" Digitizing event number %d", event));
+ // Get the current loader
+ fRunLoader->GetEvent(event);
- if(gAlice->TreeS() == 0)
- gAlice->MakeTree("S") ;
+ if (!fmdLoader->TreeS()) fmdLoader->MakeTree("S");
+ // Make a branch
+ fmd->MakeBranch("S");
- TClonesArray * FMDhits = FMD->Hits() ;
+ // Cache contriutions
+ SumContributions(fmd);
-
+ // Digitize the event
+ DigitizeHits(fmd);
- Int_t nSdigits = 0 ;
-
- //Make branches
- char branchname[20];
- sprintf(branchname,"%s",FMD->GetName());
-
- Int_t bufferSize = 16000 ;
- char * file =0;
- if(!fSDigitsFile.IsNull())
- file = (char*) fSDigitsFile.Data() ; //ievent ;
- else
- if(gSystem->Getenv("CONFIG_SPLIT_FILE")){ //generating file name
- file = new char[30] ;
- sprintf(file,"FMD.SDigits.root") ;
- cout<<"CONFIG_SPLIT_FILE "<<file<<endl;
- }
- else{
- file = 0 ;
- cout<<" FILE =0 "<<endl;}
- cout<<"After CONFIG_SPLIT_FILE "<<file<<endl;
-
- gAlice->MakeBranchInTree(gAlice->TreeS(),branchname,&sdigits,bufferSize,file);
- /*
- Int_t splitlevel = 0 ;
- sprintf(branchname,"AliFMDSDigitizer");
- AliFMDSDigitizer * sd = this ;
- gAlice->MakeBranchInTree(gAlice->TreeS(),branchname,"AliFMDSDigitizer",&sd, bufferSize, splitlevel,file);
- */
-
- //Now made SDigits from hits, for PHOS it is the same
- Int_t volume,sector,ring,charge;
- Float_t e;
- Float_t de[10][20][150];
- Int_t ivol,isec,iring;
- Int_t hit,nbytes;
- TParticle *particle;
- AliFMDhit *fmdHit;
-
-
- // Event ------------------------- LOOP
-
- for (ivol=1; ivol<=6; ivol++)
- for(isec=0; isec<16; isec++)
- for(iring=0; iring<128; iring++)
- de[ivol][isec][iring]=0;
-
- if (FMD){
- FMDhits = FMD->Hits();
- TTree *TH = gAlice->TreeH();
- Stat_t ntracks = TH->GetEntries();
-
- for (Int_t track=0; track<ntracks;track++) {
- gAlice->ResetHits();
- nbytes += TH->GetEvent(track);
- particle=gAlice->Particle(track);
- Int_t nhits =FMDhits->GetEntriesFast();
-
- for (hit=0;hit<nhits;hit++) {
- fmdHit = (AliFMDhit*)FMDhits->UncheckedAt(hit);
-
- volume = fmdHit->Volume();
- sector = fmdHit->NumberOfSector();
- ring = fmdHit->NumberOfRing();
- e = fmdHit->Edep();
- de[volume][sector][ring]=de[volume][sector][ring]+e;
-
- } //hit loop
- } //track loop
- }//if FMD
- Int_t digit[5];
- Float_t I=1.664*0.04*2.33/22400; // = 0.69e-6;
- for(ivol=1; ivol<=6; ivol++){
- for(isec=0; isec<16; isec++){
- for(iring=0; iring<128; iring++){
- if(de[ivol][isec][iring]>0.){
- digit[0]=ivol;
- digit[1]=isec;
- digit[2]=iring;
- charge=Int_t (de[ivol][isec][iring]/I);
- digit[3]=charge;
-
- //dinamic diapason from MIP(0.155MeV) to 30MIP(4.65MeV)
- //1024 ADC channels
- Float_t channelWidth=(22400*30)/1024;
- digit[4]=Int_t(digit[3]/channelWidth);
-
- new((*sdigits)[nSdigits++]) AliFMDdigit(digit) ;
-
- } //de >threshold
- }// iring loop
- }//sector loop
- } // volume loop
+ fmdLoader->TreeS()->Reset();
+ fmdLoader->TreeS()->Fill();
+ fmdLoader->WriteSDigits("OVERWRITE");
+ }
+}
+//____________________________________________________________________
+void
+AliFMDSDigitizer::AddDigit(AliFMD* fmd,
+ UShort_t detector,
+ Char_t ring,
+ UShort_t sector,
+ UShort_t strip,
+ Float_t edep,
+ UShort_t count1,
+ Short_t count2,
+ Short_t count3) const
+{
+ // Add a summable digit
+ fmd->AddSDigitByFields(detector, ring, sector, strip, edep,
+ count1, count2, count3);
+}
+
+
+
+//____________________________________________________________________
+//
+// EOF
+//
-
-
- gAlice->TreeS()->Fill() ;
- TFile *f1 = new TFile(file,"RECREATE");
- f1->cd();
- gAlice->TreeS()->Write(0,TObject::kOverwrite) ;
- }
- delete sdigits ;
- if(file)
- file->Close() ;
-}
-//__________________________________________________________________
-void AliFMDSDigitizer::SetSDigitsFile(char * file ){
- if(!fSDigitsFile.IsNull())
- cout << "Changing SDigits file from " <<(char *)fSDigitsFile.Data() << " to " << file << endl ;
- fSDigitsFile=file ;
-}
-//__________________________________________________________________
-void AliFMDSDigitizer::Print(Option_t* option)const{
- cout << "------------------- "<< GetName() << " -------------" << endl ;
- if(fSDigitsFile.IsNull())
- cout << " Writing SDigitis to file galice.root "<< endl ;
- else
- cout << " Writing SDigitis to file " << (char*) fSDigitsFile.Data() << endl ;
-}