EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicCalorimeterDigiHitProducer.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicCalorimeterDigiHitProducer.h
1 //
2 // AYK (ayk@bnl.gov), 2013/06/13
3 //
4 // Calorimeter digi hit producer classes;
5 //
6 
7 #include <TH1F.h>
8 
9 //#include <EicFakeMoCaPoint.h>
10 //#include <EicFakeMoCaPointDatabase.h>
11 //#include <EicFakeMoCaPointDbEntry.h>
12 #include <EicCalorimeterDigiHit.h>
13 #include <EicDigiHitProducer.h>
14 #include <CalorimeterGeoParData.h>
15 
16 #ifndef _EIC_CALORIMETER_DIGI_HIT_PRODUCER_
17 #define _EIC_CALORIMETER_DIGI_HIT_PRODUCER_
18 
20 {
21  public:
23 
26 
27  SensorGroupType mGroupType; // either dead end (default) or reflective or actual sensor
28  Double_t mReflectivity; // fraction of reflected light if qREFLECTION end; 1. by default
29 
31 };
32 
34 {
35  // Yes, avoid complications; this "class" is a data placeholder;
38 
39  public:
40  enum SensorType {Off, SiPM, APD, PMT};
41 
49 
50  private:
51  // Time array dimension; default is 0 (not needed);
52  UInt_t mTimeDim; // number of bins in cell timing plot
53  // Full scale in [ns] and bin width;
54  Double_t mTimeRange; // cell timing plot range in [ns]
55  Double_t mTimeBinWidth;
56 
57  // Cells below this threshold will not be present in digi file output;
58  unsigned mCleanupThreshold; // single cell threshold in [photon]; default is 0
59 
60  // This is the number of photons produced per GeV deposited energy (after Birk's
61  // correction); overall "capture rate" and "inefficiency" is accounted here; the
62  // actual detected photon count will naturally be smaller because of poor reflection
63  // on one of the ends and attenuation length; this value should be tuned by hand in
64  // order to match *registered* photon count (see respective 1D histogram) and the
65  // measured rate; can not be done vice versa (setting *measured* average light yield)
66  // because of an interplay of shower depth and attenuation length which is hard to
67  // "reverse engineer" into the primary yield without having processed the MC sample
68  // on-the-fly prior to the actual digitization; in other words: for a config with
69  // 1) 100% sampling fraction, 2) one end having 100% reflection mirror, 3) other end 100%
70  // efficient SiPM, 4) very long attenuation length -> this number will match the
71  // "measured" number of photons in 1D plot;
72  Double_t mPrimaryLightYield; // expected max photon yield per [GeV]; no default
73 
74  // Timing gate parameters; default: accept all;
75  Double_t mTimingGateOffset; // timing gate offset in [ns]
76  Double_t mTimingGateWidth; // timing gate width in [ns]; NB: it is unrelated to fTRange
77 
78  SensorType mSensorType; // SiPM/APD; digitization differs a bit (see below)
79 
80  // NB: in order not to complicate things, even if sensors are installed on both ends,
81  // noise is accounted only once (it is anyway not specified, how many APD/SiPMs are installed
82  // where, right?);
83  Double_t mSipmSingleCellNoiseLevel; // SiPM noise level [counts/ns]; default: 0.0; gate setting required!
84  // So if every cell is equipped with 4x 25um 3x3mm^2 sensors, this number should be 4*14400;
85  // ignored for now; later on may want to simulate saturation effects;
86  UInt_t mSipmSingleCellDynamicRange; // max number of pixels per cell (and assume uniform light collection)
87 
88  Double_t mApdEquivalentNoiseCharge; // APD ENC [e-] for selected operating conditions; default: 0.0
89  Double_t mApdGainFactor; // APD gain factor; default: 1.0
90  Double_t mApdExcessNoiseFactor; // APD ENF; default: 1.0
91 
92  Double_t mAttenuationLength; // material attenuation length in [cm]; default: infinity
93 
94  // Want to have some simplified yet realistic sensor model; at the very least account
95  // for possible reflection and extra attenuation on the way back; both ends can be
96  // equipped with (identical) sensors, but photon counts will be added; later may want
97  // to consider split between sensors (but at that point will have to implement fiber-to-sensor
98  // routing logic); will very likely not be needed, so skip for now;
99  CalorimeterSensorGroup mSensors[2]; // upstream and downstream sensor groups
100  // Of no use for now; assume, that it suffices to set light yield and
101  // attenuation length to some reasonable number;
102  Double_t mSensorEfficiency; // something like overall QE & fill factor; 1.0 by default
103 
104  Double_t mDecayConstant; // scintillating material decay constant in [ns]; default is 0
105 
106  // Default value is "infinity";
107  Double_t mLightPropagationVelocity; // light propagation velocity in the material in [cm/ns]
108 
109  UInt_t mZCoordDim; // number of bins in {dE,<t>,<z>} vs Z-coord plot; default is 1
110 
111  //EicNamePatternHub mSensitiveVolumes;// sensitive volumes with their respective Birks' constants
112 
114 };
115 
117 {
118  public:
120  EicCalorimeterDigiHitProducer(const char *name/*, TString inFileName*/);
122 
123  // Have to maintain default constructor as well -> split variable reset
124  // call in a separate routine;
125  void ResetVars() {
126  /*mFakeDB = 0; mFakeMoCaPointArray = 0;*/ mLastOkNode = 0;
129  };
130 
131  //int UseFakeMoCaPointDatabase(const char *dbFileName, UInt_t energyBinNum);
132 
133  // Per default cell distributions will have no timing info on output;
134  int RequestTimeSpectra(Double_t tRange, UInt_t tDim);
135  void RequestEnergyDepositAccounting(double dEmax = 1.0, unsigned nBins = 100) {
139  };
141  // NB: "const" modifier here and below is ~fake (pointer contents is obviously affected);
142  void SetZBinning(UInt_t zDim) const { mDigi->mZCoordDim = zDim; };
143  void SetCleanupThreshold(unsigned threshold) const { mDigi->mCleanupThreshold = threshold; };
144  void SetPrimaryLightYield(Double_t yield) const { mDigi->mPrimaryLightYield = yield; };
145  void SetTimingGate(Double_t gateMin, Double_t gateMax) const {
146  mDigi->mTimingGateOffset = gateMin;
147  mDigi->mTimingGateWidth = gateMax - gateMin;
148  };
149 
151 
152  void SetSipmSingleCellNoiseLevel(Double_t noiseLevel) const {
153  mDigi->mSipmSingleCellNoiseLevel = noiseLevel;
154  };
155  void SetSipmSingleCellDynamicRange(UInt_t range) const {
157  };
158 
159  // FIXME: how about validity checks here?; later;
160  void SetApdEquivalentNoiseCharge(Double_t ENC) const { mDigi->mApdEquivalentNoiseCharge = ENC; };
161  void SetApdGainFactor(Double_t M) const { mDigi->mApdGainFactor= M; };
162  void SetApdExcessNoiseFactor(Double_t ENF) const { mDigi->mApdExcessNoiseFactor = ENF; };
163 
164  void SetAttenuationLength(Double_t attenuationLength) const {
165  mDigi->mAttenuationLength = attenuationLength;
166  };
167  void SetDecayConstant(Double_t decayConstant) const { mDigi->mDecayConstant = decayConstant; };
168  void SetLightPropagationVelocity(Double_t velocity) const {
169  mDigi->mLightPropagationVelocity = velocity;
170  };
171  //void SetGeantPrimaryMotherAcknowledgementFlag() const { mDigi->mAcknowledgePrimaryMother = true; };
172 
173  // Well, prefer to have two separate calls for a better readability;
175  Double_t reflectivity = 1.0) const {
176  ConfigureSensorGroupCore(mDigi->mSensors + 0, sType, reflectivity);
177  }
179  Double_t reflectivity = 1.0) const {
180  ConfigureSensorGroupCore(mDigi->mSensors + 1, sType, reflectivity);
181  };
182 
184 
185  // Yes, for now the whole point of this class is to handle hit
186  // production in a way totally different from the default method
187  // of EicDigiHitProducer class;
188  int PreExec();
189  int PostExec();
190  int HandleHit(const EicMoCaPoint *point);
191 
192  // Shared between HandleHit() and ProcessFakeMoCaPoints(); empty call for now;
193  int HandleHitCore(CalorimeterCell *cell);
194 
195  virtual void Finish();
196 
197  private:
198  // Just import mapping table from the Monte-Carlo file;
199  //TString mInFileName; //!
200 
201  // Map of cells which were hit; index is <xy,primary_mother>;
202  //std::map<std::pair<UInt_t, UInt_t>, CalorimeterCell> mCells; //!
203  // Map of cells which were hit; index is "xy";
204  std::map<ULogicalIndex_t, CalorimeterCell> mCells;
205 
206  // May want to account true energy deposits associated with all cells;
210 
211  // Want to dump this information into the output file;
213 
214  //EicFakeMoCaPointDatabase *mFakeDB; //!
215 
216  void FillEnergyDepositPlot(const char *name, double dE);
217 
218  std::map<std::string, TH1F*> mEnergyDepositPlots;
219 
220  // Input array of detector-specific EicFakeMoCaPoint's;
221  //TClonesArray* mFakeMoCaPointArray; //!
222 
223  // A working variable;
225  //int ProcessFakeMoCaPoints( void );
226 
227  //LogicalVolumeLookupTableEntry *findHitNode(EicFakeMoCaPoint *point, double master[3], double local[3]);
228 
230  CalorimeterSensorGroup::SensorGroupType sgType, Double_t reflectivity) const {
231  sgroup->mGroupType = sgType;
232  // Set for all types, even that it makes sense for qREFLECTION only; well, how about
233  // range [0..1] check?; fix later;
234  sgroup->mReflectivity = reflectivity;
235  };
236 
238 };
239 
240 #endif