/**************************************************************************
- * 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. *
**************************************************************************/
-
/* $Id$ */
-
-//_________________________________________________________________________
-// 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
+/** @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)
//////////////////////////////////////////////////////////////////////////////
-// --- Standard library ---
-#include <Riostream.h>
-#include <stdlib.h>
-
-// --- ROOT system ---
-#include <TFile.h>
-#include <TFolder.h>
-#include <TROOT.h>
-#include <TSystem.h>
-#include <TTask.h>
-#include <TTree.h>
-#include <TVirtualMC.h>
-
-// --- AliRoot header files ---
-#include "AliConfig.h"
-#include "AliDetector.h"
-#include "AliFMD.h"
-#include "AliFMDSDigitizer.h"
-#include "AliFMDdigit.h"
-#include "AliFMDhit.h"
-#include "AliFMDv1.h"
-#include "AliLoader.h"
-#include "AliRun.h"
-#include "AliRunLoader.h"
-#include "AliStack.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 "AliFMDDebug.h" // Better debug macros
+#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","")
-{
- // ctor
- fNevents = 0 ;
- fSDigits = 0 ;
- fHits = 0 ;
- fRunLoader = 0;
-}
-
-//____________________________________________________________________________
-AliFMDSDigitizer::AliFMDSDigitizer(const char* HeaderFile,char *SdigitsFile ):TTask("AliFMDSDigitizer","")
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer()
{
- fNevents = 0 ; // Number of events to digitize, 0 means all evens in current file
- // add Task to //root/Tasks folder
- fRunLoader = AliRunLoader::Open(HeaderFile);//Load event in default folder
- if (fRunLoader == 0x0)
- {
- Fatal("AliFMDSDigitizer","Can not open session. Header File is %s ",HeaderFile);
- return;//never reached
- }
- AliLoader* gime = fRunLoader->GetLoader("FMDLoader");
- if (gime == 0x0)
- {
- Fatal("AliFMDSDigitizer","Can not find FMD (loader) in specified event");
- return;//never reached
- }
- //add Task to //root/Tasks folder
- gime->PostSDigitizer(this);
+ // Default ctor - don't use it
}
-//____________________________________________________________________________
- AliFMDSDigitizer::~AliFMDSDigitizer()
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer(const Char_t* headerFile,
+ const Char_t* /* sdigfile */)
+ : AliFMDBaseDigitizer("FMDSDigitizer", "FMD SDigitizer")
{
- // dtor
- AliLoader* gime = fRunLoader->GetLoader("FMDLoader");
- gime->CleanSDigitizer();
-}
+ // Normal CTOR
+ AliFMDDebug(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);
-//---------------------------------------------------------------------
-void AliFMDSDigitizer::SetRingsSi1(Int_t ringsSi1)
-{
- fRingsSi1=ringsSi1;
-}
-void AliFMDSDigitizer::SetSectorsSi1(Int_t sectorsSi1)
-{
- fSectorsSi1=sectorsSi1;
-}
-void AliFMDSDigitizer::SetRingsSi2(Int_t ringsSi2)
-{
- fRingsSi2=ringsSi2;
}
-void AliFMDSDigitizer::SetSectorsSi2(Int_t sectorsSi2)
+
+//____________________________________________________________________
+AliFMDSDigitizer::~AliFMDSDigitizer()
{
- fSectorsSi2=sectorsSi2;
+ // Destructor
+ AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
+ loader->CleanSDigitizer();
}
-//____________________________________________________________________________
-void AliFMDSDigitizer::Exec(Option_t *option)
- {
- Int_t NumberOfRings[5]=
- {fRingsSi1,fRingsSi2,fRingsSi1,fRingsSi2,fRingsSi1};
- Int_t NumberOfSectors[5]=
- {fSectorsSi1,fSectorsSi2,fSectorsSi1,fSectorsSi2,fSectorsSi1};
-
- if (fRunLoader)
- {
- Error("Exec","Run Loader loader is NULL - Session not opened");
+//____________________________________________________________________
+void
+AliFMDSDigitizer::Exec(Option_t*)
+{
+ // Get the output manager
+ if (!fRunLoader) {
+ Error("Exec", "Run loader is not set");
return;
- }
- AliLoader* gime = fRunLoader->GetLoader("FMDLoader");
- if (gime == 0x0)
- {
- Fatal("AliFMDReconstruction","Can not find FMD (loader) in specified event");
- return;//never reached
- }
-
- fRunLoader->LoadgAlice();
- fRunLoader->LoadHeader();
- fRunLoader->LoadKinematics("READ");
+ }
+ if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
+ if (!fRunLoader->TreeE()) fRunLoader->LoadHeader();
- Int_t retval;
-
- retval = gime->LoadHits("READ");
- if (retval)
- {
- Error("Exec","Error occured while loading hits. Exiting.");
- return;
- }
-
-
- // Initialise Hit array
- fHits = new TClonesArray ("AliFMDhit", 1000);
- fSDigits = new TClonesArray ("AliFMDdigit", 1000);
-
- AliFMD *FMD = (AliFMD *) gAlice->GetDetector ("FMD");
-
- if (fNevents == 0)
- fNevents = (Int_t) fRunLoader->TreeE ()->GetEntries ();
-
- for (Int_t ievent = 0; ievent < fNevents; ievent++)
- {
- fRunLoader->GetEvent (ievent);
-
- TTree* TH = gime->TreeH();
- if (TH == 0x0)
- {
- Error("Exec","Can not get TreeH");
- return;
- }
- if (gime->TreeS () == 0) gime->MakeTree("S");
-
- //Make branch for digits
- FMD->MakeBranch ("S");
- //Now made SDigits from hits, for PHOS it is the same
- Int_t volume, sector, ring, charge;
- Float_t e;
- Float_t de[10][50][150];
- Int_t ivol, isec, iring;
- Int_t hit, nbytes;
- TParticle *particle;
- AliFMDhit *fmdHit;
- TClonesArray *FMDhits = FMD->Hits ();
-
- // Event ------------------------- LOOP
-
- for (ivol = 0; ivol < 10; ivol++)
- for (isec = 0; isec < 50; isec++)
- for (iring = 0; iring < 150; iring++)
- de[ivol][isec][iring] = 0;
-
- if (FMD)
- {
- FMDhits = FMD->Hits ();
-
-
- Stat_t ntracks = TH->GetEntries ();
- for (Int_t track = 0; track < ntracks; track++)
- {
- gAlice->ResetHits ();
- nbytes += TH->GetEvent(track);
- particle = fRunLoader->Stack()->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] += e;
- } //hit loop
- } //track loop
- } //if FMD
+ 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;
+ }
+
+ Int_t nEvents = Int_t(fRunLoader->TreeE()->GetEntries());
+ for (Int_t event = 0; event < nEvents; event++) {
+ AliFMDDebug(1, (" Digitizing event number %d", event));
+ // Get the current loader
+ fRunLoader->GetEvent(event);
+
+ if (!fmdLoader->TreeS()) fmdLoader->MakeTree("S");
+ // Make a branch
+ fmd->MakeBranch("S");
+
+ // Cache contriutions
+ SumContributions(fmd);
+
+ // Digitize the event
+ DigitizeHits(fmd);
+
+ 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);
+}
- 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 = 1; isec <= NumberOfSectors[ivol-1]; isec++)
- {
- for (iring = 1; iring <= NumberOfRings[ivol-1]; iring++)
- {
- 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);
- FMD->AddSDigit(digit);
+//____________________________________________________________________
+//
+// EOF
+//
- } // iring loop
- } //sector loop
- } // volume loop
-
- gime->TreeS()->Reset();
- gime->TreeS()->Fill();
- gime->WriteSDigits("OVERWRITE");
- } //event loop
-}
-
-//__________________________________________________________________
-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 ;
-}