ECALReadoutSimStandardAlg.cxx
Go to the documentation of this file.
1 //
2 // ECALReadoutSimStandardAlg.cxx
3 //
4 // Created by Eldwan Brianne on 8/27/18
5 //
6 
9 
12 #include "Geometry/GeometryGAr.h"
13 #include "Geometry/LocalTransformation.h"
14 #include "CoreUtils/ServiceUtil.h"
15 
18 
19 #include "CLHEP/Units/SystemOfUnits.h"
20 #include "CLHEP/Random/RandGauss.h"
21 #include "CLHEP/Random/RandBinomial.h"
22 
23 #include "TGeoManager.h"
24 
25 namespace gar {
26  namespace rosim{
27 
28  //----------------------------------------------------------------------------
30  : SiPMReadoutSimAlg(engine, pset)
31  {
32  fGeo = gar::providerFrom<geo::GeometryGAr>();
34  fDetProp = gar::providerFrom<detinfo::DetectorPropertiesService>();
35 
36  this->reconfigure(pset);
37 
38  return;
39  }
40 
41  //----------------------------------------------------------------------------
43  {
44  return;
45  }
46 
47  //----------------------------------------------------------------------------
49  {
50  fAddNoise = pset.get<bool>("AddNoise", false);
51  fSaturation = pset.get<bool>("Saturation", false);
52  fTimeSmearing = pset.get<bool>("TimeSmearing", false);
53 
54  fSiPMUtils = std::make_unique<util::SiPMUtils>(fDetProp->EffectivePixel());
55 
56  return;
57  }
58 
59  //----------------------------------------------------------------------------
61  {
62  m_SimCaloHitVec.clear();
63  m_DigitHitVec.clear();
64  }
65 
66  //----------------------------------------------------------------------------
68  {
69  //Clear the lists
70  ClearLists();
71 
72  //Loop over all hits
73  for (std::vector< art::Ptr<sdp::CaloDeposit> >::const_iterator iter = hitVector.begin(), iterEnd = hitVector.end(); iter != iterEnd; ++iter)
74  {
75  art::Ptr<sdp::CaloDeposit> hitPtr = *iter;
76  const sdp::CaloDeposit *hit = hitPtr.get();
77  m_SimCaloHitVec.emplace_back(hit);
78  }
79 
80  //Sort the list by time
81  std::sort(m_SimCaloHitVec.begin(), m_SimCaloHitVec.end(), [](const sdp::CaloDeposit *rha, const sdp::CaloDeposit *rhb) { return rha->Time() < rhb->Time(); } );
82 
83  return;
84  }
85 
86  //----------------------------------------------------------------------------
88  {
89  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "DoDigitization()";
90 
91  //Treating tiled hits
92  for(auto const &it : m_SimCaloHitVec)
93  {
94  float energy = it->Energy();
95  float time = it->Time();
96  float x = it->X();
97  float y = it->Y();
98  float z = it->Z();
99  std::array<double, 3> point = {x, y, z};
100  raw::CellID_t cellID = it->CellID();
101 
102  raw::CaloRawDigit *digihit = nullptr;
103 
104  if(fGeo->isTile(point, cellID)) {
105  digihit = this->DoTileDigitization(x, y, z, energy, time, cellID);
106  } else {
107  digihit = this->DoStripDigitization(x, y, z, energy, time, cellID);
108  }
109 
110  if( nullptr != digihit) {
111  m_DigitHitVec.emplace_back(digihit);
112  } else {
113  MF_LOG_DEBUG("ECALReadoutSimStandardAlg")
114  << "Could not digitize the simulated hit " << it;
115  }
116  }
117  }
118 
119  //----------------------------------------------------------------------------
121  {
122  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "DoTileDigitization()";
123 
124  float new_energy = this->DoPhotonStatistics(x, y, z, energy);
125  float new_time = time;
126 
127  if(fTimeSmearing)
128  new_time = this->DoTimeSmearing(time);
129 
130  //Calculate the position of the strip
131  std::pair< std::array<double, 3>, bool > calc_pos = this->CalculatePosition(x, y, z, cID);
132  //Check if need to drop the hit
133  if ( calc_pos.second ) {
134  return nullptr;
135  }
136 
137  std::array<double, 3> pos = calc_pos.first;
138 
139  raw::CaloRawDigit *digihit = new raw::CaloRawDigit( static_cast<unsigned int>(new_energy), new_time, pos[0], pos[1], pos[2], cID );
140 
141  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "Tile digihit " << digihit
142  << " with cellID " << cID
143  << " has energy " << static_cast<unsigned int>(new_energy)
144  << " time " << new_time << " ns"
145  << " pos (" << pos[0] << ", " << pos[1] << ", " << pos[2] << ")";
146 
147  return digihit;
148  }
149 
150  //----------------------------------------------------------------------------
152  {
153  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "DoStripDigitization()";
154 
155  //Calculate the light propagation along the strip
156  std::pair<float, float> times = this->DoLightPropagation(x, y, z, time, cID);
157 
158  //Calculate the SiPM energy
159  float new_energy = this->DoPhotonStatistics(x, y, z, energy);
160 
161  //Calculate the position of the strip
162  std::pair< std::array<double, 3>, bool > calc_pos = this->CalculatePosition(x, y, z, cID);
163  //Check if need to drop the hit
164  if ( calc_pos.second ) {
165  return nullptr;
166  }
167 
168  std::array<double, 3> pos = calc_pos.first;
169 
170  //make the shared ptr
171  raw::CaloRawDigit *digihit = new raw::CaloRawDigit( static_cast<unsigned int>(new_energy), times, pos[0], pos[1], pos[2], cID );
172 
173  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "Strip digihit " << digihit
174  << " with cellID " << cID
175  << " has energy " << static_cast<unsigned int>(new_energy)
176  << " time (" << times.first << ", " << times.second << ")"
177  << " pos (" << pos[0] << ", " << pos[1] << ", " << pos[2] << ")";
178 
179  return digihit;
180  }
181 
182  //----------------------------------------------------------------------------
183  float ECALReadoutSimStandardAlg::DoPhotonStatistics(float x, float y, float z, float energy) const
184  {
185  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "DoPhotonStatistics()";
186  CLHEP::RandBinomial BinomialRand(fEngine);
187 
188  TVector3 point(x, y, z);
189  float factor = fGeo->GetSensVolumeThickness(point) / 0.5;
190 
191  //Convert energy from GeV to MIP
192  float energy_mip = energy / (fDetProp->MeVtoMIP() * factor * CLHEP::MeV / CLHEP::GeV);
193 
194  //conversion to px
195  float pixel = energy_mip * fDetProp->LightYield();
196 
197  //Saturation
198  float sat_pixel = 0.;
199  if(fSaturation)
200  sat_pixel = fSiPMUtils->Saturate(pixel);
201  else
202  sat_pixel = pixel;
203 
204  //Binomial Smearing
205  double prob = sat_pixel / fDetProp->EffectivePixel();
206  float smeared_px = BinomialRand.shoot(fDetProp->EffectivePixel(), prob);
207 
208  float smeared_px_noise = smeared_px;
209  //Add noise
210  if(fAddNoise)
211  smeared_px_noise = this->AddElectronicNoise(smeared_px);
212 
213  //Convertion to ADC
214  float ADC = 0.;
215 
216  if(smeared_px_noise > 0)
217  ADC = smeared_px_noise * fDetProp->SiPMGain();
218 
221 
222  return ADC;
223  }
224 
225  //----------------------------------------------------------------------------
227  {
228  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "DoTimeSmearing()";
229  CLHEP::RandGauss GausRand(fEngine);
230  float smeared_time = time + GausRand.fire(0., fDetProp->TimeResolution());
231  return smeared_time;
232  }
233 
234  //----------------------------------------------------------------------------
236  {
237  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "AddElectronicNoise()";
238 
239  //Random noise shooting (Gaussian electronic noise)
240  CLHEP::RandGauss GausRand(fEngine);
241  float smeared_energy = energy + GausRand.shoot(0., fDetProp->NoisePx());
242  return smeared_energy;
243  }
244 
245  //----------------------------------------------------------------------------
246  std::pair< std::array<double, 3>, bool > ECALReadoutSimStandardAlg::CalculatePosition(float x, float y, float z, raw::CellID_t cID) const
247  {
248  bool drop = false;
249 
250  //Use the segmentation algo to get the position
251  std::array<double, 3> point = {x, y, z};
252  TGeoNode *node = fGeo->FindNode(point);//Node in cm...
253  std::string nodename = node->GetName();
254  std::array<double, 3> pointLocal;
256  fGeo->WorldToLocal(point, pointLocal, trans);
257 
258  std::array<double, 3> pointLocal_back = fGeo->GetPosition(node, cID);//returns in cm
259  std::array<double, 3> point_back;
260  fGeo->LocalToWorld(pointLocal_back, point_back, trans);
261  TGeoNode *new_node = fGeo->FindNode(point_back);//Node in cm...
262  std::string newnodename = new_node->GetName();
263 
264  //get the base of the node names (slice can be added in the new node)
265  std::string base_node_name = nodename.substr(0, nodename.find("_layer_") + 9);
266  std::string base_new_node_name = newnodename.substr(0, newnodename.find("_layer_") + 9);
267 
268  if( base_new_node_name != base_node_name ){
269  MF_LOG_DEBUG("ECALReadoutSimStandardAlg") << "CalculatePosition()"
270  << " isTile " << fGeo->isTile(point, cID) << "\n"
271  << " Strip length " << fGeo->getStripLength(point, cID) << "\n"
272  << " Local Point before new position ( " << pointLocal[0] << ", " << pointLocal[1] << ", " << pointLocal[2] << " ) in node " << nodename << "\n"
273  << " Local Point after new position ( " << pointLocal_back[0] << ", " << pointLocal_back[1] << ", " << pointLocal_back[2] << " ) in node " << newnodename << "\n"
274  << " Dropping the hit ";
275 
276  //Drop the hit
277  drop = true;
278  }
279 
280  return std::make_pair(point_back, drop);
281  }
282 
283  //----------------------------------------------------------------------------
284  std::pair<float, float> ECALReadoutSimStandardAlg::DoLightPropagation(float x, float y, float z, float time, raw::CellID_t cID) const
285  {
286  //Find the volume path
287  std::array<double, 3> point = {x, y, z};
288  std::array<double, 3> pointLocal;
290  fGeo->WorldToLocal(point, pointLocal, trans);
291 
292  //Calculate light propagation along the strip
293  std::pair<float, float> times = fGeo->CalculateLightPropagation(point, pointLocal, cID);
294 
295  //t1 is left SiPM, t2 is right SiPM
296  float time1 = time + times.first;
297  float time2 = time + times.second;
298 
299  //Smear the times
300  float smeared_time1 = this->DoTimeSmearing(time1);
301  float smeared_time2 = this->DoTimeSmearing(time2);
302 
303  return std::make_pair(smeared_time1, smeared_time2);
304  }
305 
306  } // rosim
307 } // gar
TGeoNode * FindNode(T const &x, T const &y, T const &z) const
virtual double SiPMGain() const =0
bool WorldToLocal(std::array< double, 3 > const &world, std::array< double, 3 > &local, gar::geo::LocalTransformation< TGeoHMatrix > &trans) const
float GetSensVolumeThickness(const TVector3 &point) const
float const & Time() const
Definition: CaloDeposit.h:71
bool fSaturation
flag for sipm saturation or not
void reconfigure(fhicl::ParameterSet const &pset)
std::string string
Definition: nybbler.cc:12
struct vector vector
void PrepareAlgo(const std::vector< art::Ptr< sdp::CaloDeposit > > &hitVector)
CLHEP::HepRandomEngine & fEngine
random number engine
virtual double IntercalibrationFactor() const =0
static constexpr double MeV
Definition: Units.h:129
double getStripLength(const std::array< double, 3 > &point, const gar::raw::CellID_t &cID) const
const detinfo::DetectorProperties * fDetProp
detector properties
virtual double EffectivePixel() const =0
Class to transform between world and local coordinates.
raw::CaloRawDigit * DoTileDigitization(float x, float y, float z, float energy, float time, raw::CellID_t cID) const
virtual double ADCSaturation() const =0
bool fAddNoise
flag to add noise or not
bool isTile(const std::array< double, 3 > &point, const gar::raw::CellID_t &cID) const
virtual double NoisePx() const =0
std::array< double, 3 > GetPosition(const TGeoNode *node, const gar::raw::CellID_t &cID) const
static constexpr double GeV
Definition: Units.h:28
T get(std::string const &key) const
Definition: ParameterSet.h:271
virtual double LightYield() const =0
bool LocalToWorld(std::array< double, 3 > const &local, std::array< double, 3 > &world, gar::geo::LocalTransformation< TGeoHMatrix > const &trans) const
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
Definition of basic calo raw digits.
long long int CellID_t
Definition: CaloRawDigit.h:24
std::pair< std::array< double, 3 >, bool > CalculatePosition(float x, float y, float z, raw::CellID_t cID) const
Detector simulation of raw signals on wires.
virtual double MeVtoMIP() const =0
General GArSoft Utilities.
ECALReadoutSimStandardAlg(CLHEP::HepRandomEngine &engine, fhicl::ParameterSet const &pset)
std::vector< raw::CaloRawDigit * > m_DigitHitVec
vector of digitized hits
std::unique_ptr< util::SiPMUtils > fSiPMUtils
used for the SiPM saturation
virtual double TimeResolution() const =0
#define MF_LOG_DEBUG(id)
list x
Definition: train.py:276
bool fTimeSmearing
flag for time smearing or not
float DoPhotonStatistics(float x, float y, float z, float energy) const
std::pair< float, float > CalculateLightPropagation(const std::array< double, 3 > &point, const std::array< double, 3 > &local, const gar::raw::CellID_t &cID) const
std::pair< float, float > DoLightPropagation(float x, float y, float z, float time, raw::CellID_t cID) const
T const * get() const
Definition: Ptr.h:149
art framework interface to geometry description
std::vector< const sdp::CaloDeposit * > m_SimCaloHitVec
used to store the simulated hits
Definition: fwd.h:31
gar::geo::GeometryCore const * fGeo
geometry information
raw::CaloRawDigit * DoStripDigitization(float x, float y, float z, float energy, float time, raw::CellID_t cID) const