All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShowerReco_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // \file ShowerReco_module.cc
4 //
5 // biagio.rossi@lhep.unibe.ch (FWMK : argoslope.resize(fNPlanes);neut specific)
6 // thomas.strauss@lhep.unibe.ch (ART : general detector)
7 //
8 // andrzej.szelc@yale.edu (port to detector agnostic version)
9 // jasaadi@fnal.gov (Try to rewrite the code to make it more readable and to be able to handle
10 // multiple TPC's and cryostats and more than one cluster per plane.)
11 //
12 // This algorithm is designed to reconstruct showers
13 //
14 ///////////////////////////////////////////////////////////////////////
15 
16 // ### Generic C++ includes ###
17 #include <cmath> // std::tan() ...
18 #include <string>
19 #include <vector>
20 
21 // ### Framework includes ###
22 #include "art/Framework/Core/EDProducer.h"
23 #include "art/Framework/Core/ModuleMacros.h"
24 #include "art/Framework/Principal/Event.h"
25 #include "art/Framework/Principal/Handle.h"
26 #include "art/Framework/Services/Registry/ServiceHandle.h"
27 #include "art_root_io/TFileService.h"
28 #include "canvas/Persistency/Common/FindManyP.h"
29 #include "canvas/Persistency/Common/Ptr.h"
30 #include "canvas/Persistency/Common/PtrVector.h"
31 #include "fhiclcpp/ParameterSet.h"
32 #include "messagefacility/MessageLogger/MessageLogger.h"
33 
34 // ### ROOT includes ###
35 #include "TMath.h"
36 #include "TTree.h"
37 
38 // ### LArSoft includes ###
53 
54 #include "range/v3/view.hpp"
55 
56 namespace shwf {
57 
58  class ShowerReco : public art::EDProducer {
59  public:
60  explicit ShowerReco(fhicl::ParameterSet const& pset);
61 
62  private:
63  void beginJob();
64  void beginRun(art::Run& run);
65  void produce(art::Event& evt); /**Actual routine that reconstruct the shower*/
66 
67  void GetVertexAndAnglesFromCluster(art::Ptr<recob::Cluster> clust,
68  unsigned int plane); // Get shower vertex and slopes.
69 
70  void LongTransEnergy(geo::GeometryCore const* geom,
71  detinfo::DetectorClocksData const& clockData,
73  unsigned int set,
74  std::vector<art::Ptr<recob::Hit>> hitlist); // Longitudinal
75 
76  void ClearandResizeVectors(unsigned int nPlanes);
77 
79  // input labels:
80  float slope[3]; // in cm, cm
81  float angle[3]; // in radians
82 
83  std::string fClusterModuleLabel;
84 
85  float ftimetick; // time sample in us
86 
87  double fMean_wire_pitch; // wire pitch in cm
88  fhicl::ParameterSet fCaloPSet;
89 
90  std::vector<double> fRMS_2cm;
91  std::vector<int> fNpoints_2cm;
92  std::vector<double> fCorr_MeV_2cm;
93  std::vector<double> fCorr_Charge_2cm;
94 
95  std::vector<int> fNpoints_corr_ADC_2cm;
96  std::vector<int> fNpoints_corr_MeV_2cm;
97 
98  std::vector<double> fTotChargeADC; //Total charge in ADC/cm for each plane
99  std::vector<double> fTotChargeMeV; //Total charge in MeV/cm for each plane
100  std::vector<double> fTotChargeMeV_MIPs; //Total charge in MeV/cm for each plane
101 
102  std::vector<double> fChargeADC_2cm; //Initial charge in ADC/cm for each plane first 4cm
103  std::vector<double> fChargeMeV_2cm; //initial charge in MeV/cm for each plane first 4cm
104 
105  std::vector<double> fChargeMeV_2cm_refined;
106  std::vector<double> fChargeMeV_2cm_axsum;
107 
108  std::vector<std::vector<double>> fDistribChargeADC; //vector with the first De/Dx points ADC
109  std::vector<std::vector<double>>
110  fDistribChargeMeV; //vector with the first De/Dx points converted energy
111  std::vector<std::vector<double>> fDistribHalfChargeMeV;
112  std::vector<std::vector<double>>
113  fDistribChargeposition; //vector with the first De/Dx points' positions
114 
115  std::vector<std::vector<double>> fSingleEvtAngle; //vector with the first De/Dx points
116  std::vector<std::vector<double>> fSingleEvtAngleVal; //vector with the first De/Dx points
117 
118  std::vector<unsigned int> fWire_vertex; // wire coordinate of vertex for each plane
119  std::vector<double> fTime_vertex; // time coordinate of vertex for each plane
120 
121  std::vector<double> fWire_vertexError; // wire coordinate of vertex for each plane
122  std::vector<double> fTime_vertexError; // time coordinate of vertex for each plane
123 
124  std::vector<unsigned int> fWire_last; // wire coordinate of last point for each plane
125  std::vector<double> fTime_last; // time coordinate of last point for each plane
126 
127  // reconstructed 3D position of shower start
128  std::vector<double> xyz_vertex_fit;
129 
130  std::vector<std::vector<double>>
131  fNPitch; // double array, to use each plane for each set of angles
132 
133  // calorimetry variables
134  float Kin_En;
135  std::vector<float> vdEdx;
136  std::vector<float> vresRange;
137  std::vector<float> vdQdx;
138  std::vector<float> deadwire; // residual range for dead wires
139  float Trk_Length;
140  float fTrkPitchC;
141  float fdEdxlength; // distance that gets used to determine e/gamma
142  // separation
143  float fcalodEdxlength; // cutoff distance for hits saved to the calo object.
144  bool fUseArea;
145 
146  double xphi, xtheta; // new calculated angles.
147  unsigned int fNPlanes; // number of planes
148  unsigned int fNAngles;
149  TTree* ftree_shwf;
150 
151  // conversion and useful constants
152  double fWirePitch; // wire pitch in cm
153  double fTimeTick;
156 
157  std::vector<int> fNhitsperplane;
158  std::vector<double> fTotADCperplane;
159  }; // class ShowerReco
160 
161  //------------------------------------------------------------------------------
162  ShowerReco::ShowerReco(fhicl::ParameterSet const& pset) : EDProducer{pset}
163  {
164  fClusterModuleLabel = pset.get<std::string>("ClusterModuleLabel");
165  fCaloPSet = pset.get<fhicl::ParameterSet>("CaloAlg");
166 
167  fdEdxlength =
168  pset.get<double>("dEdxlength"); // distance that gets used to determine e/gamma separation
169  fcalodEdxlength =
170  pset.get<double>("calodEdxlength"); // cutoff distance for hits saved to the calo object.
171  fUseArea = pset.get<bool>("UseArea");
172 
173  produces<std::vector<recob::Shower>>();
174  produces<art::Assns<recob::Shower, recob::Cluster>>();
175  produces<art::Assns<recob::Shower, recob::Hit>>();
176  produces<std::vector<anab::Calorimetry>>();
177  produces<art::Assns<recob::Shower, anab::Calorimetry>>();
178  }
179 
180  // ***************** //
181  void
183  {
184  art::ServiceHandle<geo::Geometry const> geo;
185 
186  /// \todo the call to geo->Nplanes() assumes this is a single cryostat and
187  /// single TPC detector; need to generalize to multiple cryostats and
188  /// TPCs
189  fNPlanes = geo->Nplanes();
190  fMean_wire_pitch = geo->WirePitch(); // wire pitch in cm
191 
192  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
193  ftimetick = sampling_rate(clockData) / 1000.;
194 
195  /**Get TFileService and define output Histograms*/
196  art::ServiceHandle<art::TFileService const> tfs;
197 
198  ftree_shwf = tfs->make<TTree>("ShowerReco",
199  "Results"); /**All-knowing tree with reconstruction information*/
200  ftree_shwf->Branch("run", &fRun, "run/I");
201  ftree_shwf->Branch("subrun", &fSubRun, "subrun/I");
202  ftree_shwf->Branch("event", &fEvent, "event/I");
203  ftree_shwf->Branch("nplanes", &fNPlanes, "nplanes/I");
204  ftree_shwf->Branch("nangles", &fNAngles, "nangles/I");
205  ftree_shwf->Branch("xtheta", &xtheta, "xtheta/D");
206  ftree_shwf->Branch("xphi", &xphi, "xphi/D");
207  ftree_shwf->Branch("ftotChargeADC", "std::vector<double>", &fTotChargeADC);
208  ftree_shwf->Branch("ftotChargeMeV", "std::vector<double>", &fTotChargeMeV);
209  ftree_shwf->Branch("fTotChargeMeV_MIPs", "std::vector<double>", &fTotChargeMeV_MIPs);
210  ftree_shwf->Branch("NPitch", "std::vector< std::vector<double> >", &fNPitch);
211 
212  // this should be temporary - until the omega is sorted out.
213  ftree_shwf->Branch("RMS_2cm", "std::vector<double>", &fRMS_2cm);
214  ftree_shwf->Branch("Npoints_2cm", "std::vector<int>", &fNpoints_2cm);
215  ftree_shwf->Branch("ChargeADC_2cm", "std::vector<double>", &fChargeADC_2cm);
216  ftree_shwf->Branch("ChargeMeV_2cm", "std::vector<double>", &fChargeMeV_2cm);
217  ftree_shwf->Branch("ChargeMeV_2cm_refined", "std::vector<double>", &fChargeMeV_2cm_refined);
218  ftree_shwf->Branch("ChargeMeV_2cm_axsum", "std::vector<double>", &fChargeMeV_2cm_axsum);
219  ftree_shwf->Branch("fNhitsperplane", "std::vector<int>", &fNhitsperplane);
220  ftree_shwf->Branch("fTotADCperplane", "std::vector<double>", &fTotADCperplane);
221  ftree_shwf->Branch(
222  "ChargedistributionADC", "std::vector<std::vector<double>>", &fDistribChargeADC);
223  ftree_shwf->Branch(
224  "ChargedistributionMeV", "std::vector<std::vector<double>>", &fDistribChargeMeV);
225  ftree_shwf->Branch(
226  "DistribHalfChargeMeV", "std::vector<std::vector<double>>", &fDistribHalfChargeMeV);
227  ftree_shwf->Branch(
228  "ChargedistributionPosition", "std::vector<std::vector<double>>", &fDistribChargeposition);
229  ftree_shwf->Branch("xyz_vertex_fit", "std::vector<double>", &xyz_vertex_fit);
230  }
231 
232  void
234  {
235  auto const* geom = lar::providerFrom<geo::Geometry>();
236  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
237  auto const detProp =
238  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
239 
240  fWirePitch = geom->WirePitch(); // wire pitch in cm
241  fTimeTick = sampling_rate(clockData) / 1000.;
242  fDriftVelocity = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
244  }
245 
246  void
247  ShowerReco::ShowerReco::ClearandResizeVectors(unsigned int /*nPlanes*/)
248  {
249  //calculate factorial for number of angles
250  int fact = 1;
251  for (unsigned int i = 1; i <= fNPlanes; ++i)
252  fact *= i;
253 
254  fNAngles = fact / 2;
255 
256  fDistribChargeADC.clear();
257  fDistribChargeMeV.clear();
258  fDistribChargeposition.clear();
259 
260  fDistribChargeADC.resize(fNPlanes);
261  fDistribChargeMeV.resize(fNPlanes);
262  fDistribChargeposition.resize(fNPlanes);
263 
264  fNPitch.clear();
265  fDistribChargeADC.clear();
266  fDistribChargeMeV.clear();
267  fDistribHalfChargeMeV.clear();
268  fDistribChargeposition.clear();
269 
270  fNPitch.resize(fNAngles);
271  fDistribChargeADC.resize(fNPlanes);
272  fDistribChargeMeV.resize(fNPlanes);
273  fDistribHalfChargeMeV.resize(fNPlanes);
274  fDistribChargeposition.resize(fNPlanes);
275 
276  for (unsigned int ii = 0; ii < fNAngles; ii++) {
277  fNPitch[ii].resize(fNPlanes, -1);
278  }
279 
280  fNpoints_corr_ADC_2cm.clear();
281  fNpoints_corr_MeV_2cm.clear();
282 
283  fNpoints_corr_ADC_2cm.resize(fNAngles, -1);
284  fNpoints_corr_MeV_2cm.resize(fNAngles, -1);
285 
286  for (unsigned int ii = 0; ii < fNPlanes; ii++) {
287  fDistribChargeADC[ii].resize(0); //vector with the first De/Dx points
288  fDistribChargeMeV[ii].resize(0); //vector with the first De/Dx points
289  fDistribHalfChargeMeV[ii].resize(0);
290  fDistribChargeposition[ii].resize(0); //vector with the first De/Dx points' positions
291  }
292 
293  fWire_vertex.clear();
294  fTime_vertex.clear();
295  fWire_vertexError.clear();
296  fTime_vertexError.clear();
297  fWire_last.clear();
298  fTime_last.clear();
299  fTotChargeADC.clear();
300  fTotChargeMeV.clear();
301  fTotChargeMeV_MIPs.clear();
302  fRMS_2cm.clear();
303  fNpoints_2cm.clear();
304 
305  fNhitsperplane.clear();
306  fTotADCperplane.clear();
307 
308  fWire_vertex.resize(fNAngles, -1);
309  fTime_vertex.resize(fNAngles, -1);
310  fWire_vertexError.resize(fNPlanes, -1);
311  fTime_vertexError.resize(fNPlanes, -1);
312  fWire_last.resize(fNAngles, -1);
313  fTime_last.resize(fNAngles, -1);
314  fTotChargeADC.resize(fNAngles, 0);
315  fTotChargeMeV.resize(fNAngles, 0);
316  fTotChargeMeV_MIPs.resize(fNAngles, 0);
317  fRMS_2cm.resize(fNAngles, 0);
318  fNpoints_2cm.resize(fNAngles, 0);
319 
320  fCorr_MeV_2cm.clear();
321  fCorr_Charge_2cm.clear();
322  xyz_vertex_fit.clear();
323 
324  fChargeADC_2cm.clear();
325  fChargeMeV_2cm.clear();
326  fChargeMeV_2cm_refined.clear();
327  fChargeMeV_2cm_refined.clear();
328  fChargeMeV_2cm_axsum.clear();
329 
330  fCorr_MeV_2cm.resize(fNAngles, 0);
331  fCorr_Charge_2cm.resize(fNAngles, 0);
332  xyz_vertex_fit.resize(3);
333 
334  fChargeADC_2cm.resize(fNAngles,
335  0); //Initial charge in ADC/cm for each plane angle calculation 4cm
336  fChargeMeV_2cm.resize(fNAngles,
337  0); //initial charge in MeV/cm for each angle calculation first 4cm
338  fChargeMeV_2cm_refined.resize(0);
339  fChargeMeV_2cm_refined.resize(fNAngles, 0);
340  fChargeMeV_2cm_axsum.resize(fNAngles, 0);
341 
342  fNhitsperplane.resize(fNPlanes, -1);
343  fTotADCperplane.resize(fNPlanes, -1);
344 
345  vdEdx.clear();
346  vresRange.clear();
347  vdQdx.clear();
348  }
349 
350  // ***************** //
351  void
353  {
354  auto const* geom = lar::providerFrom<geo::Geometry>();
355  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
356  auto const detProp =
357  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
358 
359  util::GeometryUtilities const gser{*geom, clockData, detProp};
360  fNPlanes = geom->Nplanes();
361  auto Shower3DVector = std::make_unique<std::vector<recob::Shower>>();
362  auto cassn = std::make_unique<art::Assns<recob::Shower, recob::Cluster>>();
363  auto hassn = std::make_unique<art::Assns<recob::Shower, recob::Hit>>();
364  auto calorimetrycol = std::make_unique<std::vector<anab::Calorimetry>>();
365  auto calassn = std::make_unique<art::Assns<anab::Calorimetry, recob::Shower>>();
366 
367  /**Get Clusters*/
368 
369  art::Handle<std::vector<recob::Cluster>> clusterListHandle;
370  evt.getByLabel(fClusterModuleLabel, clusterListHandle);
371 
372  art::Handle<std::vector<art::PtrVector<recob::Cluster>>> clusterAssociationHandle;
373  evt.getByLabel(fClusterModuleLabel, clusterAssociationHandle);
374 
375  art::FindManyP<recob::Hit> fmh(clusterListHandle, evt, fClusterModuleLabel);
376 
377  fRun = evt.id().run();
378  fSubRun = evt.id().subRun();
379  fEvent = evt.id().event();
380 
381  // find all the hits associated to all the clusters (once and for all);
382  // the index of the query matches the index of the cluster in the collection
383  // (conveniently carried around in its art pointer)
384  art::FindManyP<recob::Hit> ClusterHits(clusterListHandle, evt, fClusterModuleLabel);
385 
386  std::vector<art::PtrVector<recob::Cluster>>::const_iterator clusterSet =
387  clusterAssociationHandle->begin();
388  // loop over vector of vectors (each size of NPlanes) and reconstruct showers from each of those
389  for (size_t iClustSet = 0; iClustSet < clusterAssociationHandle->size(); iClustSet++) {
390 
391  const art::PtrVector<recob::Cluster> CurrentClusters = (*(clusterSet++));
392 
393  // do some error checking - i.e. are the clusters themselves present.
394  if (clusterListHandle->size() < 2 || CurrentClusters.size() < 2) {
395  ftree_shwf->Fill();
396  return;
397  }
398 
399  ClearandResizeVectors(fNPlanes);
400 
401  std::vector<std::vector<art::Ptr<recob::Hit>>> hitlist_all;
402  hitlist_all.resize(fNPlanes);
403 
404  for (size_t iClust = 0; iClust < CurrentClusters.size(); iClust++) {
405  art::Ptr<recob::Cluster> const& pclust = CurrentClusters[iClust];
406 
407  // get all the hits for this cluster;
408  // pclust is a art::Ptr to the original cluster collection stored in the event;
409  // its key corresponds to its index in the collection
410  // (and therefore to the index in the query)
411  std::vector<art::Ptr<recob::Hit>> const& hitlist = ClusterHits.at(pclust.key());
412 
413  unsigned int p(0); //c=channel, p=plane, w=wire
414 
415  if (hitlist.size() == 0) continue;
416 
417  p = (*hitlist.begin())->WireID().Plane;
418  // get vertex position and slope information to start with - ii is the
419  // posistion of the correct cluster:
421 
422  double ADCcharge = 0;
423  //loop over cluster hits
424  for (art::Ptr<recob::Hit> const& hit : hitlist) {
425  p = hit->WireID().Plane;
426  hitlist_all[p].push_back(hit);
427  ADCcharge += hit->PeakAmplitude();
428  }
429  fNhitsperplane[p] = hitlist_all[p].size();
430  fTotADCperplane[p] = ADCcharge;
431  } // End loop on clusters.
432  // Now I have the Hitlists and the relevent clusters parameters saved.
433 
434  // find best set:
435  unsigned int bp1 = 0, bp2 = 0;
436  double minerror1 = 99999999, minerror2 = 9999999;
437  for (unsigned int ii = 0; ii < fNPlanes; ++ii) {
438  double locerror =
440  fTime_vertexError[ii] * fTime_vertexError[ii]; // time coordinate of vertex for each plane
441 
442  if (minerror1 >= locerror) // the >= sign is to favorize collection
443  {
444  minerror1 = locerror;
445  bp1 = ii;
446  }
447  }
448  for (unsigned int ij = 0; ij < fNPlanes; ++ij) {
449  double locerror =
451  fTime_vertexError[ij] * fTime_vertexError[ij]; // time coordinate of vertex for each plane
452 
453  if (minerror2 >= locerror && ij != bp1) {
454  minerror2 = locerror;
455  bp2 = ij;
456  }
457  }
458 
459  gser.Get3DaxisN(bp1, bp2, angle[bp1], angle[bp2], xphi, xtheta);
460 
461  ///////////////////////////////////////////////////////////
462  const double origin[3] = {0.};
463  std::vector<std::vector<double>> position;
464  double fTimeTick = sampling_rate(clockData) / 1000.;
465  double fDriftVelocity = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
466  // get starting positions for all planes
467  for (unsigned int xx = 0; xx < fNPlanes; xx++) {
468  double pos1[3];
469  geom->Plane(xx).LocalToWorld(origin, pos1);
470  std::vector<double> pos2;
471  pos2.push_back(pos1[0]);
472  pos2.push_back(pos1[1]);
473  pos2.push_back(pos1[2]);
474  position.push_back(pos2);
475  }
476  // Assuming there is no problem ( and we found the best pair that comes
477  // close in time ) we try to get the Y and Z coordinates for the start of
478  // the shower.
479  try {
480  int chan1 = geom->PlaneWireToChannel(bp1, fWire_vertex[bp1], 0);
481  int chan2 = geom->PlaneWireToChannel(bp2, fWire_vertex[bp2], 0);
482 
483  double y, z;
484  geom->ChannelsIntersect(chan1, chan2, y, z);
485 
486  xyz_vertex_fit[1] = y;
487  xyz_vertex_fit[2] = z;
488  xyz_vertex_fit[0] =
489  (fTime_vertex[bp1] - trigger_offset(clockData)) * fDriftVelocity * fTimeTick +
490  position[0][0];
491  }
492  catch (cet::exception const& e) {
493  mf::LogWarning("ShowerReco") << "caught exception \n" << e;
494  xyz_vertex_fit[1] = 0;
495  xyz_vertex_fit[2] = 0;
496  xyz_vertex_fit[0] = 0;
497  }
498 
499  // if collection is not best plane, project starting point from that
500  if (bp1 != fNPlanes - 1 && bp2 != fNPlanes - 1) {
501  double pos[3];
502  unsigned int wirevertex;
503 
504  geom->Plane(fNPlanes - 1).LocalToWorld(origin, pos);
505 
506  pos[1] = xyz_vertex_fit[1];
507  pos[2] = xyz_vertex_fit[2];
508  wirevertex = geom->NearestWire(pos, fNPlanes - 1);
509 
510  double drifttick =
511  (xyz_vertex_fit[0] / detProp.DriftVelocity(detProp.Efield(), detProp.Temperature())) *
512  (1. / fTimeTick);
513  fWire_vertex[fNPlanes - 1] = wirevertex; // wire coordinate of vertex for each plane
514  fTime_vertex[fNPlanes - 1] =
515  drifttick -
516  (pos[0] / detProp.DriftVelocity(detProp.Efield(), detProp.Temperature())) *
517  (1. / fTimeTick) +
518  trigger_offset(clockData);
519  }
520 
521  if (fabs(xphi) < 5.) {
522  xtheta = gser.Get3DSpecialCaseTheta(
523  bp1, bp2, fWire_last[bp1] - fWire_vertex[bp1], fWire_last[bp2] - fWire_vertex[bp2]);
524  }
525 
526  // zero the arrays just to make sure
527  for (unsigned int i = 0; i < fNAngles; ++i) {
528  fTotChargeADC[i] = 0;
529  fTotChargeMeV[i] = 0;
530  fTotChargeMeV_MIPs[i] = 0;
531  fNpoints_corr_ADC_2cm[i] = 0;
532  fNpoints_corr_MeV_2cm[i] = 0;
533 
534  fRMS_2cm[i] = 0;
535  fNpoints_2cm[i] = 0;
536 
537  fCorr_MeV_2cm[i] = 0;
538  fCorr_Charge_2cm[i] = 0;
539 
540  fChargeADC_2cm[i] = 0; //Initial charge in ADC/cm for each plane angle calculation 4cm
541  fChargeMeV_2cm[i] = 0; //initial charge in MeV/cm for each angle calculation first 4cm
542  }
543 
544  // do loop and choose Collection. With ful calorimetry can do all.
545  if (!(fabs(xphi) > 89 && fabs(xphi) < 91)) // do not calculate pitch for extreme angles
546  LongTransEnergy(geom,
547  clockData,
548  detProp,
549  0,
550  hitlist_all[fNPlanes - 1]); // temporary only plane 2.
551 
552  //////create spacepoints, and direction cosines for Shower creation
553 
554  // make an art::PtrVector of the clusters
555  art::PtrVector<recob::Cluster> prodvec;
556  for (unsigned int i = 0; i < clusterListHandle->size(); ++i) {
557  art::Ptr<recob::Cluster> prod(clusterListHandle, i);
558  prodvec.push_back(prod);
559  }
560 
561  //create a singleSpacePoint at vertex.
562  std::vector<recob::SpacePoint> spcpts;
563 
564  //get direction cosines and set them for the shower
565  // TBD determine which angle to use for the actual shower
566  double fPhi = xphi;
567  double fTheta = xtheta;
568 
569  TVector3 dcosVtx(
570  TMath::Cos(fPhi * TMath::Pi() / 180) * TMath::Sin(fTheta * TMath::Pi() / 180),
571  TMath::Cos(fTheta * TMath::Pi() / 180),
572  TMath::Sin(fPhi * TMath::Pi() / 180) * TMath::Sin(fTheta * TMath::Pi() / 180));
573  /// \todo really need to determine the values of the arguments of the
574  /// recob::Shower ctor
575  // fill with bogus values for now
576  TVector3 dcosVtxErr(util::kBogusD, util::kBogusD, util::kBogusD);
577  recob::Shower singShower;
578  singShower.set_direction(dcosVtx);
579  singShower.set_direction_err(dcosVtxErr);
580 
581  Shower3DVector->push_back(singShower);
582  // associate the shower with its clusters
583  util::CreateAssn(evt, *Shower3DVector, prodvec, *cassn);
584 
585  // get the hits associated with each cluster and associate those with the shower
586  for (size_t p = 0; p < prodvec.size(); ++p) {
587  std::vector<art::Ptr<recob::Hit>> hits = fmh.at(p);
588  util::CreateAssn(evt, *Shower3DVector, hits, *hassn);
589  }
590 
591  geo::PlaneID planeID(0, 0, fNPlanes - 1);
592  calorimetrycol->emplace_back(
594 
595  art::PtrVector<recob::Shower> ssvec;
596 
597  art::ProductID aid = evt.getProductID<std::vector<recob::Shower>>();
598  art::Ptr<recob::Shower> aptr(aid, 0, evt.productGetter(aid));
599  ssvec.push_back(aptr);
600 
601  util::CreateAssn(evt, *calorimetrycol, ssvec, *calassn);
602  ftree_shwf->Fill();
603  } // end loop on Vectors of "Associated clusters"
604 
605  evt.put(std::move(Shower3DVector));
606  evt.put(std::move(cassn));
607  evt.put(std::move(hassn));
608  evt.put(std::move(calorimetrycol));
609  evt.put(std::move(calassn));
610  }
611 
612  //------------------------------------------------------------------------------
613  void
615  detinfo::DetectorClocksData const& clockData,
617  unsigned int set,
618  std::vector<art::Ptr<recob::Hit>> hitlist)
619  {
620  // alogorithm for energy vs dx of the shower (roto-translation) COLLECTION
621  // VIEW
622 
624 
625  double totCnrg = 0,
626  totCnrg_corr = 0; // tot enegry of the shower in collection
627 
628  double time;
629  unsigned int wire = 0, plane = fNPlanes - 1;
630 
631  double mevav2cm = 0.;
632  double sum = 0.;
633  double npoints_calo = 0;
634 
635  int direction = -1;
636 
637  //override direction if phi (XZ angle) is less than 90 degrees
638  if (fabs(xphi) < 90) direction = 1;
639 
640  //variables to check whether a hit is close to the shower axis.
641  double ortdist, linedist;
642  double wire_on_line, time_on_line;
643 
644  //get effective pitch using 3D angles
645  util::GeometryUtilities const gser{*geom, clockData, detProp};
646  double newpitch = gser.PitchInView(plane, xphi, xtheta);
647 
648  using lar::to_element;
650  for (auto const& hit : hitlist | transform(to_element)) {
651  time = hit.PeakTime();
652  wire = hit.WireID().Wire;
653  plane = hit.WireID().Plane;
654 
655  double dEdx_new;
656 
657  if (fUseArea) { dEdx_new = calalg.dEdx_AREA(clockData, detProp, hit, newpitch); }
658  else // this will hopefully go away, once all of the calibration factors
659  // are calculated.
660  {
661  dEdx_new = calalg.dEdx_AMP(clockData, detProp, hit, newpitch);
662  }
663 
664  //calculate total energy.
665  totCnrg_corr += dEdx_new;
666 
667  // calculate the wire,time coordinates of the hit projection on to the 2D shower axis
668  gser.GetPointOnLine(slope[plane] / fWireTimetoCmCm,
669  fWire_vertex[plane],
670  fTime_vertex[plane],
671  wire,
672  time,
673  wire_on_line,
674  time_on_line);
675  linedist =
676  gser.Get2DDistance(wire_on_line, time_on_line, fWire_vertex[plane], fTime_vertex[plane]);
677  ortdist = gser.Get2DDistance(wire_on_line, time_on_line, wire, time);
678 
679  //calculate the distance from the vertex using the effective pitch metric
680  double wdist = (((double)wire - (double)fWire_vertex[plane]) * newpitch) *
681  direction; //wdist is always positive
682 
683  if ((wdist < fcalodEdxlength) && (wdist > 0.2)) {
684 
685  vdEdx.push_back(dEdx_new);
686  vresRange.push_back(fabs(wdist));
687  vdQdx.push_back(hit.PeakAmplitude() / newpitch);
688  Trk_Length = wdist;
689  fTrkPitchC = fNPitch[set][plane];
690  Kin_En += dEdx_new * newpitch;
691  npoints_calo++;
692  sum += dEdx_new;
693 
694  if (wdist < fdEdxlength &&
695  ((direction == 1 && wire > fWire_vertex[plane]) // take no hits before vertex
696  // (depending on direction)
697  || (direction == -1 && wire < fWire_vertex[plane])) &&
698  ortdist < 4.5 && linedist < fdEdxlength) {
699  fChargeMeV_2cm[set] += dEdx_new;
700  fNpoints_2cm[set]++;
701  }
702 
703  // fill out for 4cm preshower
704 
705  fDistribChargeMeV[set].push_back(dEdx_new); // vector with the first De/Dx points
706  fDistribChargeposition[set].push_back(
707  wdist); // vector with the first De/Dx points' positions
708 
709  } // end inside range if statement
710 
711  } // end first loop on hits.
712 
713  auto const signalType =
714  hitlist.empty() ? geo::kMysteryType : geom->SignalType(hitlist.front()->WireID());
715 
716  if (signalType == geo::kCollection) {
717  fTotChargeADC[set] = totCnrg * newpitch;
718  fTotChargeMeV[set] = totCnrg_corr * newpitch;
719  }
720 
721  // calculate average dE/dx
722  if (fNpoints_2cm[set] > 0) { mevav2cm = fChargeMeV_2cm[set] / fNpoints_2cm[set]; }
723 
724  // second loop to calculate RMS
725  for (auto const& hit : hitlist | transform(to_element)) {
726  time = hit.PeakTime();
727  wire = hit.WireID().Wire;
728  plane = hit.WireID().Plane;
729  double dEdx = 0;
730 
731  if (fUseArea) { dEdx = calalg.dEdx_AREA(clockData, detProp, hit, newpitch); }
732  else // this will hopefully go away, once all of the calibration factors
733  // are calculated.
734  {
735  dEdx = calalg.dEdx_AMP(clockData, detProp, hit, newpitch);
736  }
737 
738  gser.GetPointOnLine(slope[plane] / fWireTimetoCmCm,
739  fWire_vertex[plane],
740  fTime_vertex[plane],
741  wire,
742  time,
743  wire_on_line,
744  time_on_line);
745  linedist =
746  gser.Get2DDistance(wire_on_line, time_on_line, fWire_vertex[plane], fTime_vertex[plane]);
747  ortdist = gser.Get2DDistance(wire_on_line, time_on_line, wire, time);
748 
749  double wdist = (((double)wire - (double)fWire_vertex[plane]) * newpitch) * direction;
750 
751  if ((wdist < fcalodEdxlength) && (wdist > 0.2)) {
752  if (wdist < fdEdxlength &&
753  ((direction == 1 && wire > fWire_vertex[plane]) ||
754  (direction == -1 && wire < fWire_vertex[plane])) &&
755  ortdist < 4.5 && linedist < fdEdxlength) {
756  fRMS_2cm[set] += (dEdx - mevav2cm) * (dEdx - mevav2cm);
757  }
758 
759  } // end if on correct hits.
760  } // end RMS_calculating loop.
761 
762  if (fNpoints_2cm[set] > 0) { fRMS_2cm[set] = TMath::Sqrt(fRMS_2cm[set] / fNpoints_2cm[set]); }
763 
764  /// third loop to get only points inside of 1RMS of value.
765 
766  for (auto const& hit : hitlist | transform(to_element)) {
767  time = hit.PeakTime();
768  wire = hit.WireID().Wire;
769  plane = hit.WireID().Plane;
770 
771  double dEdx = 0;
772  if (fUseArea) { dEdx = calalg.dEdx_AREA(clockData, detProp, hit, newpitch); }
773  else // this will hopefully go away, once all of the calibration factors
774  // are calculated.
775  {
776  dEdx = calalg.dEdx_AMP(clockData, detProp, hit, newpitch);
777  }
778 
779  gser.GetPointOnLine(slope[plane] / fWireTimetoCmCm,
780  fWire_vertex[plane],
781  fTime_vertex[plane],
782  wire,
783  time,
784  wire_on_line,
785  time_on_line);
786  linedist =
787  gser.Get2DDistance(wire_on_line, time_on_line, fWire_vertex[plane], fTime_vertex[plane]);
788  ortdist = gser.Get2DDistance(wire_on_line, time_on_line, wire, time);
789 
790  double wdist = (((double)wire - (double)fWire_vertex[plane]) * newpitch) * direction;
791 
792  if ((wdist < fcalodEdxlength) && (wdist > 0.2 &&
793  ((direction == 1 && wire > fWire_vertex[plane]) ||
794  (direction == -1 && wire < fWire_vertex[plane])) &&
795  ortdist < 4.5 && linedist < fdEdxlength)) {
796  if (wdist < fdEdxlength) {
797  if (((dEdx > (mevav2cm - fRMS_2cm[set])) && (dEdx < (mevav2cm + fRMS_2cm[set]))) ||
798  (newpitch > 0.3 * fdEdxlength)) {
799  fCorr_MeV_2cm[set] += dEdx;
800  fNpoints_corr_MeV_2cm[set]++;
801  }
802 
803  } // end if on good hits
804  }
805  } // end of third loop on hits
806 
807  if (fNpoints_corr_MeV_2cm[set] > 0) {
810  }
811  }
812 
813  //------------------------------------------------------------------------------------//
814  void
815  ShowerReco::GetVertexAndAnglesFromCluster(art::Ptr<recob::Cluster> clust, unsigned int plane)
816  // Get shower vertex and slopes.
817  {
818  // convert to cm/cm units needed in the calculation
819  angle[plane] = clust->StartAngle();
820  slope[plane] = std::tan(clust->StartAngle());
821  fWire_vertex[plane] = clust->StartWire();
822  fTime_vertex[plane] = clust->StartTick();
823 
824  fWire_vertexError[plane] = clust->SigmaStartWire(); // wire coordinate of vertex for each plane
825  fTime_vertexError[plane] = clust->SigmaStartTick(); // time coordinate of vertex for each plane
826 
827  fWire_last[plane] = clust->EndWire(); // wire coordinate of last point for each plane
828  fTime_last[plane] = clust->EndTick();
829  }
830 
831  DEFINE_ART_MODULE(ShowerReco)
832 }
std::vector< double > fTime_last
process_name opflash particleana ie ie ie z
fhicl::ParameterSet fCaloPSet
std::vector< double > fWire_vertexError
ShowerReco(fhicl::ParameterSet const &pset)
std::vector< double > fTotChargeADC
std::vector< double > fCorr_Charge_2cm
void set_direction_err(const TVector3 &dir_e)
Definition: Shower.h:136
Utilities related to art service access.
constexpr to_element_t to_element
Definition: ToElement.h:24
Who knows?
Definition: geo_types.h:147
static constexpr Sample_t transform(Sample_t sample)
std::vector< int > fNhitsperplane
std::vector< std::vector< double > > fNPitch
Declaration of signal hit object.
pdgs p
Definition: selectors.fcl:22
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< std::vector< double > > fDistribChargeMeV
std::vector< int > fNpoints_corr_MeV_2cm
std::vector< std::vector< double > > fSingleEvtAngle
std::vector< double > fTime_vertex
std::vector< double > fTotADCperplane
process_name hit
Definition: cheaterreco.fcl:51
std::vector< unsigned int > fWire_last
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
std::vector< std::vector< double > > fDistribHalfChargeMeV
std::vector< double > fChargeMeV_2cm_refined
std::vector< float > vdEdx
void GetVertexAndAnglesFromCluster(art::Ptr< recob::Cluster > clust, unsigned int plane)
std::vector< float > vdQdx
std::vector< int > fNpoints_2cm
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< double > fTime_vertexError
std::vector< std::vector< double > > fSingleEvtAngleVal
void set_direction(const TVector3 &dir)
Definition: Shower.h:135
process_name opflash particleana ie ie y
double dEdx_AMP(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::vector< float > vresRange
std::vector< double > fRMS_2cm
void produce(art::Event &evt)
Description of geometry of one entire detector.
Declaration of cluster object.
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2687
std::vector< double > fCorr_MeV_2cm
std::string fClusterModuleLabel
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
std::vector< double > xyz_vertex_fit
void beginRun(art::Run &run)
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
std::vector< double > fChargeMeV_2cm
Var Sqrt(const Var &v)
Use to take sqrt of a var.
Definition: Var.cxx:172
std::vector< double > fTotChargeMeV_MIPs
std::vector< double > fChargeADC_2cm
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
do i e
std::vector< float > deadwire
int trigger_offset(DetectorClocksData const &data)
std::vector< std::vector< double > > fDistribChargeADC
void LongTransEnergy(geo::GeometryCore const *geom, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, unsigned int set, std::vector< art::Ptr< recob::Hit >> hitlist)
constexpr double kBogusD
obviously bogus double value
art::ServiceHandle< art::TFileService > tfs
std::vector< double > fChargeMeV_2cm_axsum
void ClearandResizeVectors(unsigned int nPlanes)
TCEvent evt
Definition: DataStructs.cxx:8
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
std::vector< int > fNpoints_corr_ADC_2cm
std::vector< std::vector< double > > fDistribChargeposition
std::vector< unsigned int > fWire_vertex
art framework interface to geometry description
auto const detProp
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
std::vector< double > fTotChargeMeV
Signal from collection planes.
Definition: geo_types.h:146