source: JEM-EUSO/esaf_cc_at_lal/packages/simulation/detector/electronics/src/R8900M36Photomultiplier.cc @ 114

Last change on this file since 114 was 114, checked in by moretto, 11 years ago

actual version of ESAF at CCin2p3

File size: 8.9 KB
Line 
1// $Id: R8900M36Photomultiplier.cc 2920 2011-06-11 06:46:41Z mabl $
2// A.Thea created Mar, 26 2003
3//
4// S.Ogawa & M.Bertaina
5// 2004-11-26
6// LastUpdate: 2005-01-20
7
8/*****************************************************************************
9 * ESAF: Euso Simulation and Analysis Framework                              *
10 *                                                                           *
11 *  Id: R8900M36Photomultiplier                                               *
12 *  Package: Electronics                                                     *
13 *  Coordinator: Marco.Pallavicini                                           *
14 *                                                                           *
15 *****************************************************************************/
16
17//_____________________________________________________________________________
18//
19//   R8900-M36 Weakly focused Photomultiplier
20//   ========================================
21//
22//   This class implements the R8900 36 pixels weakly focused photomultiplier.
23//   In weakly focused photomultipliers border pixel behavior can be sensibly
24//   different from the central one. A static map, with the average pixel
25//   detector efficiency has been introduced to simulate the border effect.
26//   Efficiency Wavelength dependency has been also introduced.
27//
28//   Config file parameters
29//   ======================
30//
31//   fgUsePmtAdd [string]: if yes Add() method calls Photomultiplier::Add() and
32//   uses average values for all pixels.
33//
34
35#include "R8900M36Photomultiplier.hh"
36#include "EusoElectronics.hh"
37#include "EusoDetector.hh"
38#include "EsafRandom.hh"
39#include "EConst.hh"
40#include "EDetectorPhotonAdder.hh"
41#include "NumbersFileParser.hh"
42#include "Photon.hh"
43
44using namespace sou;
45
46ClassImp(R8900M36Photomultiplier)
47
48R8900M36Photomultiplier::EStatus R8900M36Photomultiplier::fgStatus = kUndefined;
49
50vector<Double_t> R8900M36Photomultiplier::fgColEff;
51Interpolate* R8900M36Photomultiplier::fgQuantumEff           = NULL;
52Interpolate* R8900M36Photomultiplier::fgAngularDependence    = NULL;
53vector<Double_t>* R8900M36Photomultiplier::fgCrossTalkTable = NULL;
54
55//______________________________________________________________________________
56R8900M36Photomultiplier::R8900M36Photomultiplier( Int_t id, PmtGeometry* g ) :
57    Photomultiplier(id, g ) {
58    //
59    // Constructor
60    //
61    // initialize static data members
62    if ( fgStatus == kUndefined )  {
63
64        if ( Conf()->GetBool("R8900M36Photomultiplier.fgUsePmtAdd") )
65            fgStatus = kPmtAdd;
66        else {
67            fgStatus = kR8900Add;
68
69            //--------------------  begin  Satoi & Mario 's changes  -----------------
70
71            string cfgdir = Conf()->GetCfgDir()+"/"+Conf()->GetType()+"/"+Conf()->GetName()+"/";
72
73            // load Collection Efficiency from file
74            string s = cfgdir + Conf()->GetStr("R8900M36Photomultiplier.fCollectionEfficiency.FileName");
75            NumbersFileParser pce(s,4);
76            vector<Double_t> dummy=pce.GetCol(3);
77
78            if(dummy.size()==0)
79                Msg(EsafMsg::Panic) << "R8900M36Photomultipiler: "+s+"is empty!" << MsgDispatch;
80
81            for(size_t i(0);i<dummy.size();i++)
82                fgColEff.push_back(dummy[i]);
83            Msg(EsafMsg::Debug) << fgColEff.size() << " C.E. data loading..." << MsgDispatch;
84
85            // load Quantum Efficiency from file
86            fgQuantumEff = new Interpolate(cfgdir+Conf()->GetStr("R8900M36Photomultiplier.fQuantumEfficiency.FileName"));
87            fgQuantumEff->SetXUnit(nm);
88            Msg(EsafMsg::Debug) << "Quantum Efficiency data loading..." << MsgDispatch;
89
90            // load Angular Dependence from file
91            fgAngularDependence = new Interpolate(cfgdir+Conf()->GetStr("R8900M36Photomultiplier.fAngularDependence.FileName"));
92            fgAngularDependence->SetXUnit(deg);
93            Msg(EsafMsg::Debug) << "Angular Dependece data loading..." << MsgDispatch;
94
95            // load Cross Talk form file
96            // Cross Talk File Format:
97            // (ch.),x,y,(data1),(data2),...(data36)[CR] for each line
98            fgCrossTalkTable= new vector<Double_t>[36];
99            s = cfgdir + Conf()->GetStr("R8900M36Photomultiplier.fCrossTalk.FileName");
100            NumbersFileParser *dummy2 = new NumbersFileParser(s,39);
101            for(size_t j(0);j<36;j++){
102                // Get row No."j"
103                vector<Double_t> dummy2_line=dummy2->GetRow(j);
104                // Get data from colum No.3 to No.39
105                for(size_t k(3);k<dummy2_line.size();k++){
106                    // Load fgCrossTalkTable
107                    fgCrossTalkTable[j].push_back(dummy2_line[k]);
108                }
109            }
110
111            Msg(EsafMsg::Debug) << "Cross Talk data loading..." << MsgDispatch;
112        }
113    }
114    //--------------------  end  Satoi & Mario 's changes  -----------------
115
116}
117
118//______________________________________________________________________________
119R8900M36Photomultiplier::~R8900M36Photomultiplier() {
120    // Destructor
121}
122
123
124//______________________________________________________________________________
125Bool_t R8900M36Photomultiplier::Add(Photon& ph) {
126    //
127    // add a photon hit to be simulated
128    //
129    // use Photomultiplier::Add, temporary disabled
130    if ( fgStatus == kPmtAdd )
131        return Photomultiplier::Add(ph);
132
133    // new features after this line
134
135    // check if this photon hits this pmt
136    if (!Geometry()->IsInside( ph )) {
137        TVector3 r = (ph.pos-Geometry()->Position()) ;
138        Double_t x = r.Dot(Geometry()->GetX());
139        Double_t y = r.Dot(Geometry()->GetY());
140        Double_t z = r.Dot(Geometry()->GetZ());
141        MsgForm(EsafMsg::Warning, "Wrong ph. DIFF=(%.3e, %.3e, %.3e)  PROJ=(%.3e, %.3e, %.3e)",
142                r[0], r[1], r[2], x, y, z);
143        return kFALSE;
144    }
145
146    // get the channel number
147    Int_t ch = Geometry()->Pad(ph);
148
149    // negative if Photon is lost for geometrical reasons (dead spaces)
150    if ( ch < 0 )
151        return kFALSE;
152
153    // saving pixel id on the photon
154    ph.pixelUid = GetUniqueId(ch);
155
156    // if required, do association mapping between original
157    // theta phi in field of view and this channel
158    //FIXME: EusoMapping::Get()->Associate(this,ch,ph);
159
160    // if signal simulation is disabled, stop here
161    // if ( !(GetEusoDetector()->GetEusoElectronics()->GetSimulationStatus()) ) return kTRUE;
162    if ( !(GetEusoElectronics()->GetSimulationStatus()) ) return kTRUE;
163
164    TRandom* rndm = EsafRandom::Get();
165
166    //--------------------  beginning  Satoi & Mario 's changes  -----------------
167    // fgQuantum is not the same as our fgQuantumEff.
168    // fgQuantum    : constant.
169    // fgQuantumEff : depend on wavelength
170
171    // fgColEff depend on ch (pixel number).
172    // QuantumEff depend on wavelength of photon.
173    // AngularDependence depend on Theta of photon got by Detector.
174
175    // Computing D.E.
176    double ph_dir_theta = ph.dir.Theta();
177    if (fGeometry){
178        // calculate direction angle in relation with the geometry direction
179        ph_dir_theta = (ph.dir.Angle(-fGeometry->Normal()));
180    }
181    else {
182        Msg(EsafMsg::Panic) << "Geometry not defined." << MsgDispatch;
183    }
184    Double_t DetEff=fgColEff[ch]*fgQuantumEff->GetValue(ph.wl)*fgAngularDependence->GetValue(ph_dir_theta);
185
186    // Shot for D.E.
187    Double_t shot=rndm->Rndm(); // [0,1]
188    // Check if photon generate electron or not
189    if(shot > DetEff)
190            return kFALSE;  // photon is lost
191
192    // Shot2 for CrossTalk
193    Double_t shot2=rndm->Rndm(); // [0,1]
194
195    // Cross Talk
196    //  Get Cross Talk Data
197    vector<Double_t> *ChCrossTalk = &fgCrossTalkTable[ch];
198
199    // apply CrossTalk Technique
200    if (shot2 <= (*ChCrossTalk)[0] ) {
201        ch=0;
202    } else {
203        for(size_t kch(1); kch < ChCrossTalk->size(); kch++){
204            if( (shot2 >= (*ChCrossTalk)[kch-1] ) && ( shot2 <= (*ChCrossTalk)[kch] ) ){
205                ch=kch;
206                break;
207            }
208        }
209    }
210
211    // end of judge
212    // Msg(EsafMsg::Debug) << "photon hit pixel no. " << ch <<  MsgDispatch;
213
214    //-------------------------------- end Satoi & Mario 's changes --------------
215
216    // compute charge
217    Double_t delta = fgGainSigma * rndm->Gaus();
218    Double_t charge = fgGain + delta;
219    charge *= EConst::ElectronCharge();
220
221    // create the list if this does not exist
222    if ( fPmtHits[ch] == NULL ) {
223        fPmtHits[ch] = new vector<PmtSignal*>;
224    }
225
226    // create the PmtSignal and add it to the list
227    PmtSignal* sig = new PmtSignal(ph.time,charge,fgWidth,GetUniqueId(ch),ch+1);
228    fPmtHits[ch]->push_back( sig );
229
230    SetState(kPmtFilling);
231
232    ph.madeSignal = kTRUE;
233
234    // add this level of information to photon history in root file
235    if ( EEvent::GetCurrent() ) {
236        EDetectorPhotonAdder a(&ph,sig,kFALSE);
237        EEvent::GetCurrent()->Fill(a);
238    }
239
240    // keep memory of the time interval of this event
241    if ( sig->Time() > fEndTime )
242        fEndTime = sig->Time();
243    if ( sig->Time() < fStartTime )
244        fStartTime = sig->Time();
245
246    SetEmpty( kFALSE );
247
248    return kTRUE;
249}
Note: See TracBrowser for help on using the repository browser.