IonAndScint_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: IonAndScint
3 // Plugin Type: producer
4 // File: IonAndScint_module.cc
5 // Description:
6 // - acts on sim::SimEnergyDeposit from LArG4Main,
7 // - calculate the number of photons and electrons
8 // Input: 'sim::SimEnergyDeposit'
9 // Output: updated 'sim::SimEnergyDeposit' with numPhotons and numElectrons
10 //
11 //This module calculate the number of photons and electrons produced at each step where energy is deposited.
12 //The Separate algorithm is used by default, but this can be changed via the "ISCalcAlg"
13 //fhicl parameter tag.
14 //At the end of this module the numPhotons and numElectrons of sim:SimEnergyDeposit have been updated.
15 //
16 // Aug.18 by Mu Wei
17 //
18 // 10/28/2019 Wenqiang Gu (wgu@bnl.gov)
19 // Add the Space Charge Effect (SCE) if the option is enabled
20 ////////////////////////////////////////////////////////////////////////
21 
22 // LArSoft includes
30 #include "nurandom/RandomUtils/NuRandomService.h"
31 
32 // Framework includes
39 #include "fhiclcpp/ParameterSet.h"
41 
42 #include <iostream>
43 #include <sstream> // std::stringstream, std::stringbuf
44 #include <stdio.h>
45 #include <string>
46 
47 using std::string;
48 using SimEnergyDepositCollection = std::vector<sim::SimEnergyDeposit>;
49 
50 namespace larg4 {
51  class IonAndScint : public art::EDProducer {
52  public:
53  explicit IonAndScint(fhicl::ParameterSet const& pset);
54  void produce(art::Event& event) override;
55  void beginJob() override;
56  void endJob() override;
57 
58  private:
59 
60  std::vector<art::Handle<SimEnergyDepositCollection>> inputCollections(art::Event const&) const;
61 
62  // name of calculator: Separate, Correlated, or NEST
64 
65  // The input module labels to specify which SimEnergyDeposit
66  // collections to use as input. Specify only the module label,
67  // not the instance name(s). Instances to be used have to be
68  // passed via the Instances parameter.
69  // If empty, this module uses all the available collections.
70  std::vector<std::string> fInputModuleLabels;
71 
72  std::unique_ptr<ISCalc> fISAlg;
73  CLHEP::HepRandomEngine& fEngine;
74  string Instances;
75  std::vector<string> instanceNames;
77  };
78 
79  //......................................................................
81  : art::EDProducer{pset}
82  , calcTag{pset.get<art::InputTag>("ISCalcAlg")}
83  , fInputModuleLabels{pset.get<std::vector<std::string>>("InputModuleLabels", {})}
85  ->createEngine(*this, "HepJamesRandom", "NEST", pset, "SeedNEST"))
86  , Instances{
87  pset.get<string>("Instances", "LArG4DetectorServicevolTPCActive"),
88  }
89  , fSavePriorSCE{pset.get<bool>("SavePriorSCE", false)}
90  {
91  std::cout << "IonAndScint Module Construct" << std::endl;
92 
93  if (Instances.empty()) {
94  std::cout << "Produce SimEnergyDeposit in default volume - LArG4DetectorServicevolTPCActive"
95  << std::endl;
96  instanceNames.push_back("LArG4DetectorServicevolTPCActive");
97  }
98  else {
99  std::stringstream input(Instances);
100  string temp;
101  while (std::getline(input, temp, ';')) {
102  instanceNames.push_back(temp);
103  }
104 
105  std::cout << "Produce SimEnergyDeposit in volumes: " << std::endl;
106  for (auto instanceName : instanceNames) {
107  std::cout << " - " << instanceName << std::endl;
108  }
109  }
110 
111  produces<std::vector<sim::SimEnergyDeposit>>();
112  if (fSavePriorSCE) produces<std::vector<sim::SimEnergyDeposit>>("priorSCE");
113  }
114 
115  //......................................................................
116  void
118  {
119  std::cout << "IonAndScint beginJob." << std::endl;
120  std::cout << "Using " << calcTag.label() << " algorithm to calculate IS." << std::endl;
121 
122  if (calcTag.label() == "Separate")
123  fISAlg = std::make_unique<ISCalcSeparate>();
124  else if (calcTag.label() == "Correlated") {
125  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataForJob();
126  fISAlg = std::make_unique<ISCalcCorrelated>(detProp);
127  }
128  else if (calcTag.label() == "NEST")
129  fISAlg = std::make_unique<ISCalcNESTLAr>(fEngine);
130  else
131  mf::LogWarning("IonAndScint") << "No ISCalculation set, this can't be good.";
132  }
133 
134  //......................................................................
135  void
137  {
138  std::cout << "IonAndScint endJob." << std::endl;
139  }
140 
141  //......................................................................
142  std::vector<art::Handle<SimEnergyDepositCollection>>
144  {
145  if (empty(fInputModuleLabels)) {
146  mf::LogDebug("IonAndScint") << "Retrieving all products" << std::endl;
148  }
149 
150  std::vector<art::Handle<SimEnergyDepositCollection>> result;
151 
152  for (auto const & module : fInputModuleLabels) {
153 
154  mf::LogDebug("IonAndScint") << "Retrieving products with module label "
155  << module << std::endl;
156 
158 
159  if (empty(handels)) {
161  << "IonAndScint module cannot find any SimEnergyDeposits with module label "
162  << module << " as requested in InputModuleLabels. \n";
163  }
164 
165  result.insert(result.end(), handels.begin(), handels.end());
166  }
167 
168  return result;
169  }
170 
171  //......................................................................
172  void
174  {
175  std::cout << "IonAndScint Module Producer" << std::endl;
176 
177  std::vector<art::Handle<SimEnergyDepositCollection>> edepHandle = inputCollections(event);
178 
179  if (empty(edepHandle)) {
180  std::cout << "IonAndScint Module Cannot Retrive SimEnergyDeposit" << std::endl;
181  return;
182  }
183 
184  auto sce = lar::providerFrom<spacecharge::SpaceChargeService>();
185  auto const detProp =
187 
188  auto simedep = std::make_unique<std::vector<sim::SimEnergyDeposit>>();
189  auto simedep1 = std::make_unique<std::vector<sim::SimEnergyDeposit>>(); // for prior-SCE depos
190  for (auto edeps : edepHandle) {
191  // Do some checking before we proceed
192  if (!edeps.isValid()) {
193  std::cout << "!edeps.isValid()" << std::endl;
194  continue;
195  }
196 
197  auto index = std::find(
198  instanceNames.begin(), instanceNames.end(), edeps.provenance()->productInstanceName());
199  if (index == instanceNames.end()) {
200  std::cout << "Skip SimEnergyDeposit in: " << edeps.provenance()->productInstanceName()
201  << std::endl;
202  continue;
203  }
204 
205  std::cout << "SimEnergyDeposit input module: " << edeps.provenance()->moduleLabel()
206  << ", instance name: " << edeps.provenance()->productInstanceName() << std::endl;
207 
208  for (sim::SimEnergyDeposit const& edepi : *edeps) {
209  auto const isCalcData = fISAlg->CalcIonAndScint(detProp, edepi);
210 
211  int ph_num = round(isCalcData.numPhotons);
212  int ion_num = round(isCalcData.numElectrons);
213  float scintyield = isCalcData.scintillationYieldRatio;
214  float edep_tmp = edepi.Energy();
215  geo::Point_t startPos_tmp = edepi.Start();
216  geo::Point_t endPos_tmp = edepi.End();
217  double startTime_tmp = edepi.StartT();
218  double endTime_tmp = edepi.EndT();
219  int trackID_tmp = edepi.TrackID();
220  int pdgCode_tmp = edepi.PdgCode();
221 
222  if (sce->EnableSimSpatialSCE()) {
223  auto posOffsetsStart =
224  sce->GetPosOffsets({edepi.StartX(), edepi.StartY(), edepi.StartZ()});
225  auto posOffsetsEnd = sce->GetPosOffsets({edepi.EndX(), edepi.EndY(), edepi.EndZ()});
226  startPos_tmp =
227  geo::Point_t{(float)(edepi.StartX() - posOffsetsStart.X()), //x should be subtracted
228  (float)(edepi.StartY() + posOffsetsStart.Y()),
229  (float)(edepi.StartZ() + posOffsetsStart.Z())};
230  endPos_tmp =
231  geo::Point_t{(float)(edepi.EndX() - posOffsetsEnd.X()), //x should be subtracted
232  (float)(edepi.EndY() + posOffsetsEnd.Y()),
233  (float)(edepi.EndZ() + posOffsetsEnd.Z())};
234  }
235 
236  simedep->emplace_back(ph_num,
237  ion_num,
238  scintyield,
239  edep_tmp,
240  startPos_tmp,
241  endPos_tmp,
242  startTime_tmp,
243  endTime_tmp,
244  trackID_tmp,
245  pdgCode_tmp);
246 
247  if (fSavePriorSCE) {
248  simedep1->emplace_back(ph_num,
249  ion_num,
250  scintyield,
251  edepi.Energy(),
252  edepi.Start(),
253  edepi.End(),
254  edepi.StartT(),
255  edepi.EndT(),
256  edepi.TrackID(),
257  edepi.PdgCode());
258  }
259 
260  }
261  }
262  event.put(std::move(simedep));
263  if (fSavePriorSCE) event.put(std::move(simedep1), "priorSCE");
264  }
265 } // namespace
void beginJob() override
static QCString result
IonAndScint(fhicl::ParameterSet const &pset)
CLHEP::HepRandomEngine & fEngine
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
std::vector< std::string > fInputModuleLabels
Geant4 interface.
std::string const & label() const noexcept
Definition: InputTag.cc:79
const double e
static int input(void)
Definition: code.cpp:15695
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
def move(depos, offset)
Definition: depos.py:107
std::vector< string > instanceNames
std::vector< art::Handle< SimEnergyDepositCollection > > inputCollections(art::Event const &) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void endJob() override
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
contains information for a single step in the detector simulation
Energy deposition in the active material.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::unique_ptr< ISCalc > fISAlg
void produce(art::Event &event) override
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)
Event finding and building.
std::vector< sim::SimEnergyDeposit > SimEnergyDepositCollection