Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | List of all members
shower::EMShowerAlg Class Reference

#include <EMShowerAlg.h>

Public Member Functions

 EMShowerAlg (fhicl::ParameterSet const &pset, int debug=0)
 
void AssociateClustersAndTracks (std::vector< art::Ptr< recob::Cluster >> const &clusters, art::FindManyP< recob::Hit > const &fmh, art::FindManyP< recob::Track > const &fmt, std::map< int, std::vector< int >> &clusterToTracks, std::map< int, std::vector< int >> &trackToClusters) const
 Map associated tracks and clusters together given their associated hits. More...
 
void AssociateClustersAndTracks (std::vector< art::Ptr< recob::Cluster >> const &clusters, art::FindManyP< recob::Hit > const &fmh, art::FindManyP< recob::Track > const &fmt, std::vector< int > const &clustersToIgnore, std::map< int, std::vector< int >> &clusterToTracks, std::map< int, std::vector< int >> &trackToClusters) const
 Map associated tracks and clusters together given their associated hits, whilst ignoring certain clusters. More...
 
std::vector< int > CheckShowerPlanes (std::vector< std::vector< int >> const &initialShowers, std::vector< art::Ptr< recob::Cluster >> const &clusters, art::FindManyP< recob::Hit > const &fmh) const
 Takes the initial showers found and tries to resolve issues where one bad view ruins the event. More...
 
std::unique_ptr< recob::TrackConstructTrack (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &track1, std::vector< art::Ptr< recob::Hit >> const &track2, std::map< int, TVector2 > const &showerCentreMap) const
 
std::unique_ptr< recob::TrackConstructTrack (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &track1, std::vector< art::Ptr< recob::Hit >> const &track2) const
 
void FindInitialTrack (detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &hits, std::unique_ptr< recob::Track > &initialTrack, std::map< int, std::vector< art::Ptr< recob::Hit >>> &initialTrackHits, int plane) const
 
std::vector< std::vector< int > > FindShowers (std::map< int, std::vector< int >> const &trackToClusters) const
 Makes showers given a map between tracks and all clusters associated with them. More...
 
recob::Shower MakeShower (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &hits, std::unique_ptr< recob::Track > const &initialTrack, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &initialTrackHits) const
 Makes a recob::Shower object given the hits in the shower and the initial track-like part. More...
 
recob::Shower MakeShower (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &hits, art::Ptr< recob::Vertex > const &vertex, int &iok) const
 <Tingjun to="" document>=""> More...
 
std::vector< recob::SpacePointMakeSpacePoints (detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &hits, std::vector< std::vector< art::Ptr< recob::Hit >>> &hitAssns) const
 Makes space points from the shower hits in each plane. More...
 
std::map< int, std::vector< art::Ptr< recob::Hit > > > OrderShowerHits (detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Hit > const &shower, int plane) const
 Takes the hits associated with a shower and orders them so they follow the direction of the shower. More...
 
void FindInitialTrackHits (std::vector< art::Ptr< recob::Hit >> const &showerHits, art::Ptr< recob::Vertex > const &vertex, std::vector< art::Ptr< recob::Hit >> &trackHits) const
 <Tingjun to="" document>=""> More...
 
Int_t WeightedFit (const Int_t n, const Double_t *x, const Double_t *y, const Double_t *w, Double_t *parm) const
 <Tingjun to="" document>=""> More...
 
bool isCleanShower (std::vector< art::Ptr< recob::Hit >> const &hits) const
 <Tingjun to="" document>=""> More...
 

Public Attributes

int fDebug
 

Private Member Functions

void CheckIsolatedHits_ (std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
 
bool CheckShowerHits_ (detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &showerHitsMap) const
 
TVector3 Construct3DPoint_ (detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit1, art::Ptr< recob::Hit > const &hit2) const
 Constructs a 3D point (in [cm]) to represent the hits given in two views. More...
 
double FinddEdx_ (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &trackHits, std::unique_ptr< recob::Track > const &track) const
 Finds dE/dx for the track given a set of hits. More...
 
std::vector< art::Ptr< recob::Hit > > FindOrderOfHits_ (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, bool perpendicular=false) const
 
std::map< int, std::vector< art::Ptr< recob::Hit > > > FindShowerStart_ (std::map< int, std::vector< art::Ptr< recob::Hit >>> const &orderedShowerMap) const
 
std::map< int, std::map< int, bool > > GetPlanePermutations_ (const detinfo::DetectorPropertiesData &detProp, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
 
double GlobalWire_ (const geo::WireID &wireID) const
 Find the global wire position. More...
 
TVector2 HitCoordinates_ (recob::Hit const &hit) const
 Return the coordinates of this hit in global wire/tick space. More...
 
TVector2 HitPosition_ (detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
 Return the coordinates of this hit in units of cm. More...
 
TVector2 HitPosition_ (detinfo::DetectorPropertiesData const &detProp, TVector2 const &pos, geo::PlaneID planeID) const
 Return the coordinates of this hit in units of cm. More...
 
std::unique_ptr< recob::TrackMakeInitialTrack_ (detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &initialHitsMap, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &showerHitsMap) const
 
void OrderShowerHits_ (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &shower, std::vector< art::Ptr< recob::Hit >> &orderedShower, art::Ptr< recob::Vertex > const &vertex) const
 
TVector2 Project3DPointOntoPlane_ (detinfo::DetectorPropertiesData const &detProp, TVector3 const &point, int plane, int cryostat=0) const
 
std::map< double, int > RelativeWireWidth_ (const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
 
TVector2 ShowerCenter_ (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
 Returns the charge-weighted shower center. More...
 
TVector2 ShowerDirection_ (detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
 
double ShowerHitRMS_ (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
 
double ShowerHitRMSGradient_ (detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
 Returns the gradient of the RMS vs shower segment graph. More...
 
int WorstPlane_ (const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
 Returns the plane which is determined to be the least likely to be correct. More...
 

Private Attributes

double const fMinTrackLength
 
double const fdEdxTrackLength
 
double const fSpacePointSize
 
unsigned int const fNfitpass
 
std::vector< unsigned int > const fNfithits
 
std::vector< double > const fToler
 
art::ServiceHandle< geo::Geometry const > fGeom
 
shower::ShowerEnergyAlg const fShowerEnergyAlg
 
calo::CalorimetryAlg const fCalorimetryAlg
 
pma::ProjectionMatchingAlg const fProjectionMatchingAlg
 
std::string const fDetector
 
bool const fMakeGradientPlot
 
bool const fMakeRMSGradientPlot
 
int const fNumShowerSegments
 

Detailed Description

Definition at line 58 of file EMShowerAlg.h.

Constructor & Destructor Documentation

shower::EMShowerAlg::EMShowerAlg ( fhicl::ParameterSet const &  pset,
int  debug = 0 
)

Definition at line 37 of file EMShowerAlg.cxx.

38  : fDebug{debug}
39  , fMinTrackLength{pset.get<double>("MinTrackLength")}
40  , fdEdxTrackLength{pset.get<double>("dEdxTrackLength")}
41  , fSpacePointSize{pset.get<double>("SpacePointSize")}
42  , fNfitpass{pset.get<unsigned int>("Nfitpass")}
43  , fNfithits{pset.get<std::vector<unsigned int>>("Nfithits")}
44  , fToler{pset.get<std::vector<double>>("Toler")}
45  , fShowerEnergyAlg(pset.get<fhicl::ParameterSet>("ShowerEnergyAlg"))
46  , fCalorimetryAlg(pset.get<fhicl::ParameterSet>("CalorimetryAlg"))
47  , fProjectionMatchingAlg(pset.get<fhicl::ParameterSet>("ProjectionMatchingAlg"))
48  , fDetector{pset.get<std::string>("Detector", "dune35t")} // tmp
49  , fMakeGradientPlot{pset.get<bool>("MakeGradientPlot", false)}
50  , fMakeRMSGradientPlot{pset.get<bool>("MakeRMSGradientPlot", false)}
51  , fNumShowerSegments{pset.get<int>("NumShowerSegments", 4)}
52 {
53  if (fNfitpass != fNfithits.size() || fNfitpass != fToler.size()) {
55  << "EMShowerAlg: fNfithits and fToler need to have size fNfitpass";
56  }
57 }
shower::ShowerEnergyAlg const fShowerEnergyAlg
Definition: EMShowerAlg.h:277
pma::ProjectionMatchingAlg const fProjectionMatchingAlg
Definition: EMShowerAlg.h:279
std::string string
Definition: nybbler.cc:12
double const fdEdxTrackLength
Definition: EMShowerAlg.h:265
unsigned int const fNfitpass
Definition: EMShowerAlg.h:269
std::vector< double > const fToler
Definition: EMShowerAlg.h:271
bool const fMakeRMSGradientPlot
Definition: EMShowerAlg.h:285
std::vector< unsigned int > const fNfithits
Definition: EMShowerAlg.h:270
double const fMinTrackLength
Definition: EMShowerAlg.h:264
bool const fMakeGradientPlot
Definition: EMShowerAlg.h:284
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
int const fNumShowerSegments
Definition: EMShowerAlg.h:286
calo::CalorimetryAlg const fCalorimetryAlg
Definition: EMShowerAlg.h:278
double const fSpacePointSize
Definition: EMShowerAlg.h:266
std::string const fDetector
Definition: EMShowerAlg.h:281

Member Function Documentation

void shower::EMShowerAlg::AssociateClustersAndTracks ( std::vector< art::Ptr< recob::Cluster >> const &  clusters,
art::FindManyP< recob::Hit > const &  fmh,
art::FindManyP< recob::Track > const &  fmt,
std::map< int, std::vector< int >> &  clusterToTracks,
std::map< int, std::vector< int >> &  trackToClusters 
) const

Map associated tracks and clusters together given their associated hits.

Definition at line 60 of file EMShowerAlg.cxx.

66 {
67  std::vector<int> clustersToIgnore = {-999};
69  clusters, fmh, fmt, clustersToIgnore, clusterToTracks, trackToClusters);
70 }
void AssociateClustersAndTracks(std::vector< art::Ptr< recob::Cluster >> const &clusters, art::FindManyP< recob::Hit > const &fmh, art::FindManyP< recob::Track > const &fmt, std::map< int, std::vector< int >> &clusterToTracks, std::map< int, std::vector< int >> &trackToClusters) const
Map associated tracks and clusters together given their associated hits.
Definition: EMShowerAlg.cxx:60
void shower::EMShowerAlg::AssociateClustersAndTracks ( std::vector< art::Ptr< recob::Cluster >> const &  clusters,
art::FindManyP< recob::Hit > const &  fmh,
art::FindManyP< recob::Track > const &  fmt,
std::vector< int > const &  clustersToIgnore,
std::map< int, std::vector< int >> &  clusterToTracks,
std::map< int, std::vector< int >> &  trackToClusters 
) const

Map associated tracks and clusters together given their associated hits, whilst ignoring certain clusters.

Definition at line 73 of file EMShowerAlg.cxx.

80 {
81  // Look through all the clusters
82  for (auto const& clusterPtr : clusters) {
83 
84  // Get the hits in this cluster
85  auto const& clusterHits = fmh.at(clusterPtr.key());
86 
87  // Look at all these hits and find the associated tracks
88  for (auto const& clusterHitPtr : clusterHits) {
89  // Get the tracks associated with this hit
90  auto const& clusterHitTracks = fmt.at(clusterHitPtr.key());
91  if (clusterHitTracks.size() > 1) {
92  std::cout << "More than one track associated with this hit!\n";
93  continue;
94  }
95 
96  if (clusterHitTracks.size() < 1) continue;
97 
98  auto const& clusterHitTrackPtr = clusterHitTracks[0];
99  if (clusterHitTrackPtr->Length() < fMinTrackLength) {
100  if (fDebug > 2)
101  std::cout << "Track " << clusterHitTrackPtr->ID() << " is too short! ("
102  << clusterHitTrackPtr->Length() << ")\n";
103  continue;
104  }
105 
106  // Add this cluster to the track map
107  int track = clusterHitTrackPtr.key();
108  int cluster = clusterPtr.key();
109  if (cet::search_all(clustersToIgnore, cluster)) continue;
110  if (not cet::search_all(trackToClusters[track], cluster))
111  trackToClusters[track].push_back(cluster);
112  if (not cet::search_all(clusterToTracks[cluster], track))
113  clusterToTracks[cluster].push_back(track);
114  }
115  }
116 }
void cluster(In first, In last, Out result, Pred *pred)
Definition: NNClusters.h:41
Cluster finding and building.
bool search_all(FwdCont const &, Datum const &)
double const fMinTrackLength
Definition: EMShowerAlg.h:264
void shower::EMShowerAlg::CheckIsolatedHits_ ( std::map< int, std::vector< art::Ptr< recob::Hit >>> &  showerHitsMap) const
private

Checks the hits across the views in a given shower to determine if there is one in the incorrect TPC

Definition at line 119 of file EMShowerAlg.cxx.

121 {
122  std::map<int, std::vector<int>> firstTPC;
123  for (auto const& [plane, hits] : showerHitsMap)
124  firstTPC[hits.at(0)->WireID().TPC].push_back(plane);
125 
126  // If all in the same TPC then that's great!
127  if (firstTPC.size() != 2) return;
128 
129  // If they are in more than two TPCs, not much we can do
130  else if (firstTPC.size() > 2)
131  return;
132 
133  // If we get to this point, there should be something we can do!
134 
135  // Find the problem plane
136  int problemPlane = -1;
137  for (auto const& planes : firstTPC | views::values)
138  if (planes.size() == 1) problemPlane = planes[0];
139 
140  // Require three hits
141  if (showerHitsMap.at(problemPlane).size() < 3) return;
142 
143  // and get the other planes with at least three hits
144  std::vector<int> otherPlanes;
145  for (int plane = 0; plane < (int)fGeom->MaxPlanes(); ++plane)
146  if (plane != problemPlane and showerHitsMap.count(plane) and
147  showerHitsMap.at(plane).size() >= 3)
148  otherPlanes.push_back(plane);
149 
150  if (otherPlanes.size() == 0) return;
151 
152  // Look at the hits after the first one
153  unsigned int wrongTPC = showerHitsMap.at(problemPlane).at(0)->WireID().TPC;
154  unsigned int nHits = 0;
155  for (std::vector<art::Ptr<recob::Hit>>::iterator hitIt = showerHitsMap.at(problemPlane).begin();
156  hitIt != showerHitsMap.at(problemPlane).end() and (*hitIt)->WireID().TPC == wrongTPC;
157  ++hitIt)
158  ++nHits;
159 
160  // If there are more than two hits in the 'wrong TPC', we can't be sure it is indeed wrong
161  if (nHits > 2) return;
162 
163  // See if at least the next four times as many hits are in a different TPC
164  std::map<int, int> otherTPCs;
166  std::next(showerHitsMap.at(problemPlane).begin(), nHits);
167  hitIt != showerHitsMap.at(problemPlane).end() and
168  std::distance(std::next(showerHitsMap.at(problemPlane).begin(), nHits), hitIt) < 4 * nHits;
169  ++hitIt)
170  ++otherTPCs[(*hitIt)->WireID().TPC];
171 
172  if (otherTPCs.size() > 1) return;
173 
174  // If we get this far, we can move the problem hits from the front of the shower to the back
175  std::map<int, int> tpcCount;
176  for (int const otherPlane : otherPlanes)
178  std::next(showerHitsMap.at(otherPlane).begin());
179  hitIt != showerHitsMap.at(otherPlane).end() and
180  hitIt != std::next(showerHitsMap.at(otherPlane).begin(), 2);
181  ++hitIt)
182  ++tpcCount[(*hitIt)->WireID().TPC];
183 
184  // Remove the first hit if it is in the wrong TPC
185  if (tpcCount.size() == 1 and
186  tpcCount.begin()->first ==
187  (int)(*std::next(showerHitsMap.at(problemPlane).begin(), nHits))->WireID().TPC) {
188  std::vector<art::Ptr<recob::Hit>> naughty_hits;
189  for (std::vector<art::Ptr<recob::Hit>>::iterator hitIt = showerHitsMap.at(problemPlane).begin();
190  hitIt != std::next(showerHitsMap.at(problemPlane).begin(), nHits);
191  ++hitIt) {
192  naughty_hits.push_back(*hitIt);
193  showerHitsMap.at(problemPlane).erase(hitIt);
194  }
195  for (auto const& naughty_hit : naughty_hits)
196  showerHitsMap.at(problemPlane).push_back(naughty_hit);
197  }
198 }
struct vector vector
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
Q_UINT16 values[128]
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
bool shower::EMShowerAlg::CheckShowerHits_ ( detinfo::DetectorPropertiesData const &  detProp,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  showerHitsMap 
) const
private

Takes the shower hits in all views and ensure the ordering is consistent Returns bool, indicating whether or not everything makes sense!

Definition at line 201 of file EMShowerAlg.cxx.

204 {
205  bool consistencyCheck = true;
206 
207  if (showerHitsMap.size() < 2) { consistencyCheck = true; }
208  else if (showerHitsMap.size() == 2) {
209 
210  // With two views, we can check:
211  // -- timing between views is consistent
212  // -- the 3D start point makes sense when projected back onto the individual planes
213 
214  std::vector<art::Ptr<recob::Hit>> startHits;
215  std::vector<int> planes;
216  for (auto const& [plane, hits] : showerHitsMap) {
217  startHits.push_back(hits.front());
218  planes.push_back(plane);
219  }
220 
221  TVector3 showerStartPos = Construct3DPoint_(detProp, startHits.at(0), startHits.at(1));
222  TVector2 proj1 = Project3DPointOntoPlane_(detProp, showerStartPos, planes.at(0));
223  TVector2 proj2 = Project3DPointOntoPlane_(detProp, showerStartPos, planes.at(1));
224 
225  double timingDifference = std::abs(startHits.at(0)->PeakTime() - startHits.at(1)->PeakTime());
226  double projectionDifference = ((HitPosition_(detProp, *startHits.at(0)) - proj1).Mod() +
227  (HitPosition_(detProp, *startHits.at(1)) - proj2).Mod()) /
228  (double)2;
229 
230  if (timingDifference > 40 or projectionDifference > 5 or showerStartPos.X() == -9999 or
231  showerStartPos.Y() == -9999 or showerStartPos.Z() == -9999)
232  consistencyCheck = false;
233 
234  if (fDebug > 1)
235  std::cout << "Timing difference is " << timingDifference << " and projection distance is "
236  << projectionDifference << " (start is (" << showerStartPos.X() << ", "
237  << showerStartPos.Y() << ", " << showerStartPos.Z() << ")\n";
238  }
239  else if (showerHitsMap.size() == 3) {
240 
241  // With three views, we can check:
242  // -- the timing between views is consistent
243  // -- the 3D start point formed by two views and projected back into the third is close to the start point in that view
244 
245  std::map<int, art::Ptr<recob::Hit>> start2DMap;
246  for (auto const& [plane, hits] : showerHitsMap) {
247  start2DMap[plane] = hits.front();
248  }
249 
250  std::map<int, double> projDiff;
251  std::map<int, double> timingDiff;
252 
253  for (int plane = 0; plane < 3; ++plane) {
254 
255  std::vector<int> otherPlanes;
256  for (int otherPlane = 0; otherPlane < 3; ++otherPlane)
257  if (otherPlane != plane) otherPlanes.push_back(otherPlane);
258 
259  TVector3 showerStartPos = Construct3DPoint_(
260  detProp, start2DMap.at(otherPlanes.at(0)), start2DMap.at(otherPlanes.at(1)));
261  TVector2 showerStartProj = Project3DPointOntoPlane_(detProp, showerStartPos, plane);
262 
263  if (fDebug > 2) {
264  std::cout << "Plane... " << plane;
265  std::cout << "\nStart position in this plane is "
266  << HitPosition_(detProp, *start2DMap.at(plane)).X() << ", "
267  << HitPosition_(detProp, *start2DMap.at(plane)).Y() << ")\n";
268  std::cout << "Shower start from other two planes is (" << showerStartPos.X() << ", "
269  << showerStartPos.Y() << ", " << showerStartPos.Z() << ")\n";
270  std::cout << "Projecting the other two planes gives position (" << showerStartProj.X()
271  << ", " << showerStartProj.Y() << ")\n";
272  }
273 
274  double projDiff =
275  std::abs((showerStartProj - HitPosition_(detProp, *start2DMap.at(plane))).Mod());
276  double timeDiff = TMath::Max(
277  std::abs(start2DMap.at(plane)->PeakTime() - start2DMap.at(otherPlanes.at(0))->PeakTime()),
278  std::abs(start2DMap.at(plane)->PeakTime() - start2DMap.at(otherPlanes.at(1))->PeakTime()));
279 
280  if (fDebug > 1)
281  std::cout << "Plane " << plane << " has projDiff " << projDiff << " and timeDiff "
282  << timeDiff << '\n';
283 
284  if (projDiff > 5 or timeDiff > 40) consistencyCheck = false;
285  }
286  }
287 
288  if (fDebug > 1) std::cout << "Consistency check is " << consistencyCheck << '\n';
289 
290  return consistencyCheck;
291 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
T abs(T value)
TVector3 Construct3DPoint_(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit1, art::Ptr< recob::Hit > const &hit2) const
Constructs a 3D point (in [cm]) to represent the hits given in two views.
TVector2 Project3DPointOntoPlane_(detinfo::DetectorPropertiesData const &detProp, TVector3 const &point, int plane, int cryostat=0) const
std::vector< int > shower::EMShowerAlg::CheckShowerPlanes ( std::vector< std::vector< int >> const &  initialShowers,
std::vector< art::Ptr< recob::Cluster >> const &  clusters,
art::FindManyP< recob::Hit > const &  fmh 
) const

Takes the initial showers found and tries to resolve issues where one bad view ruins the event.

Definition at line 294 of file EMShowerAlg.cxx.

297 {
298  std::vector<int> clustersToIgnore;
299 
300  // Look at each shower
301  for (auto initialShowerIt = initialShowers.cbegin(); initialShowerIt != initialShowers.cend();
302  ++initialShowerIt) {
303 
304  if (std::distance(initialShowers.cbegin(), initialShowerIt) > 0) continue;
305 
306  // Map the clusters and cluster hits to each view
307  std::map<int, std::vector<art::Ptr<recob::Cluster>>> planeClusters;
308  std::map<int, std::vector<art::Ptr<recob::Hit>>> planeHits;
309  for (int const clusterIndex : *initialShowerIt) {
310  art::Ptr<recob::Cluster> const& cluster = clusters.at(clusterIndex);
311  planeClusters[cluster->Plane().Plane].push_back(cluster);
312  for (auto const& hit : fmh.at(cluster.key()))
313  planeHits[hit->WireID().Plane].push_back(hit);
314  }
315 
316  TFile* outFile = new TFile("chargeDistributions.root", "RECREATE");
317  std::map<int, TH1D*> chargeDist;
318  for (auto const& [plane, clusterPtrs] : planeClusters) {
319  for (auto const& clusterPtr : clusterPtrs) {
320  chargeDist[plane] = new TH1D(std::string("chargeDist_Plane" + std::to_string(plane) +
321  "_Cluster" + std::to_string(clusterPtr.key()))
322  .c_str(),
323  "",
324  150,
325  0,
326  1000);
327  auto const& hits = fmh.at(clusterPtr.key());
328  for (auto const& hit : hits | views::transform(to_element)) {
329  chargeDist[plane]->Fill(hit.Integral());
330  }
331  outFile->cd();
332  chargeDist[plane]->Write();
333  }
334  }
335  outFile->Close();
336  delete outFile;
337 
338  // Can't do much with fewer than three views
339  if (planeClusters.size() < 3) continue;
340 
341  // Look at how many clusters each plane has, and the proportion of hits each one uses
342  std::map<int, std::vector<double>> planeClusterSizes;
343  for (std::map<int, std::vector<art::Ptr<recob::Cluster>>>::iterator planeClustersIt =
344  planeClusters.begin();
345  planeClustersIt != planeClusters.end();
346  ++planeClustersIt) {
347  for (std::vector<art::Ptr<recob::Cluster>>::iterator planeClusterIt =
348  planeClustersIt->second.begin();
349  planeClusterIt != planeClustersIt->second.end();
350  ++planeClusterIt) {
351  std::vector<art::Ptr<recob::Hit>> hits = fmh.at(planeClusterIt->key());
352  planeClusterSizes[planeClustersIt->first].push_back(
353  (double)hits.size() / (double)planeHits.at(planeClustersIt->first).size());
354  }
355  }
356 
357  // Find the average hit fraction across all clusters in the plane
358  std::map<int, double> planeClustersAvSizes;
359  for (auto const& [plane, cluster_sizes] : planeClusterSizes) {
360  double const average = accumulate(cluster_sizes, 0.) / cluster_sizes.size();
361  planeClustersAvSizes[plane] = average;
362  }
363 
364  // Now decide if there is one plane which is ruining the reconstruction
365  // If two planes have a low average cluster fraction and one high, this plane likely merges two particle deposits together
366  int badPlane = -1;
367  for (auto const [plane, avg] : planeClustersAvSizes) {
368 
369  // Get averages from other planes and add in quadrature
370  std::vector<double> otherAverages;
371  for (auto const [other_plane, other_avg] : planeClustersAvSizes)
372  if (plane != other_plane) otherAverages.push_back(other_avg);
373 
374  double const sumSquareAvgsOtherPlanes = accumulate(
375  otherAverages, 0., [](double sum, double avg) { return sum + cet::square(avg); });
376  double const quadOtherPlanes = std::sqrt(sumSquareAvgsOtherPlanes);
377 
378  // If this plane has an average higher than the quadratic sum of the
379  // others, it may be bad
380  if (avg >= quadOtherPlanes) badPlane = plane;
381  }
382 
383  if (badPlane != -1) {
384  if (fDebug > 1) std::cout << "Bad plane is " << badPlane << '\n';
385  for (auto const& cluster : planeClusters.at(badPlane))
386  clustersToIgnore.push_back(cluster.key());
387  }
388  }
389 
390  return clustersToIgnore;
391 }
constexpr to_element_t to_element
Definition: ToElement.h:24
std::string string
Definition: nybbler.cc:12
struct vector vector
TFile * outFile
Definition: makeDST.cxx:36
geo::PlaneID Plane() const
Returns the plane ID this cluster lies on.
Definition: Cluster.h:744
Cluster finding and building.
constexpr T square(T x)
Definition: pow.h:21
key_type key() const noexcept
Definition: Ptr.h:216
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Detector simulation of raw signals on wires.
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
TVector3 shower::EMShowerAlg::Construct3DPoint_ ( detinfo::DetectorPropertiesData const &  detProp,
art::Ptr< recob::Hit > const &  hit1,
art::Ptr< recob::Hit > const &  hit2 
) const
private

Constructs a 3D point (in [cm]) to represent the hits given in two views.

Definition at line 394 of file EMShowerAlg.cxx.

397 {
398 
399  // x is average of the two x's
400  double x = (detProp.ConvertTicksToX(hit1->PeakTime(), hit1->WireID().planeID()) +
401  detProp.ConvertTicksToX(hit2->PeakTime(), hit2->WireID().planeID())) /
402  (double)2;
403 
404  // y and z got from the wire interections
405  geo::WireIDIntersection intersection;
406  fGeom->WireIDsIntersect(hit1->WireID(), hit2->WireID(), intersection);
407 
408  return TVector3(x, intersection.y, intersection.z);
409 }
double z
z position of intersection
Definition: geo_types.h:805
geo::WireID WireID() const
Definition: Hit.h:233
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
double y
y position of intersection
Definition: geo_types.h:804
list x
Definition: train.py:276
constexpr PlaneID const & planeID() const
Definition: geo_types.h:638
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
std::unique_ptr< recob::Track > shower::EMShowerAlg::ConstructTrack ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  track1,
std::vector< art::Ptr< recob::Hit >> const &  track2,
std::map< int, TVector2 > const &  showerCentreMap 
) const

Constructs a recob::Track from sets of hits in two views. Intended to be used to construct the initial first part of a shower. All PMA methods taken from the pma tracking algorithm (R. Sulej and D. Stefan). This implementation also orients the track in the correct direction if a map of shower centres (units [cm]) in each view is provided.

Definition at line 412 of file EMShowerAlg.cxx.

416 {
417 
418  std::unique_ptr<recob::Track> track;
419 
420  std::vector<art::Ptr<recob::Hit>> track1, track2;
421 
422  // Check the TPCs
423  if ((*hits1.begin())->WireID().TPC != (*hits2.begin())->WireID().TPC) {
424  mf::LogWarning("EMShowerAlg") << "Warning: attempting to construct a track from two different "
425  "TPCs. Returning a null track.";
426  return track;
427  }
428 
429  // Check for tracks crossing TPC boundaries
430  std::map<int, int> tpcMap;
431  for (auto const& hit : hits1)
432  ++tpcMap[hit->WireID().TPC];
433  for (auto const& hit : hits2)
434  ++tpcMap[hit->WireID().TPC];
435  if (tpcMap.size() > 1) {
436  mf::LogWarning("EMShowerAlg")
437  << "Warning: attempting to construct a track which crosses more than one TPC -- PMTrack "
438  "can't handle this right now. Returning a track made just from hits in the first TPC it "
439  "traverses.";
440  unsigned int firstTPC1 = hits1.at(0)->WireID().TPC, firstTPC2 = hits2.at(0)->WireID().TPC;
441  for (auto const& hit : hits1)
442  if (hit->WireID().TPC == firstTPC1) track1.push_back(hit);
443  for (auto const& hit : hits2)
444  if (hit->WireID().TPC == firstTPC2) track2.push_back(hit);
445  }
446  else {
447  track1 = hits1;
448  track2 = hits2;
449  }
450 
451  if (fDebug > 1) {
452  std::cout << "About to make a track from these hits:\n";
453  auto print_hits = [this](auto const& track) {
454  for (auto const& hit : track | views::transform(to_element)) {
455  std::cout << "Hit (" << HitCoordinates_(hit).X() << ", " << HitCoordinates_(hit).Y()
456  << ") (real wire " << hit.WireID().Wire << ") in TPC " << hit.WireID().TPC
457  << '\n';
458  }
459  };
460  print_hits(track1);
461  print_hits(track2);
462  }
463 
464  TVector3 trackStart = Construct3DPoint_(detProp, track1.at(0), track2.at(0));
465  pma::Track3D* pmatrack = fProjectionMatchingAlg.buildSegment(detProp, track1, track2, trackStart);
466 
467  if (!pmatrack) {
468  mf::LogInfo("EMShowerAlg") << "Skipping this event because not enough hits in two views";
469  return track;
470  }
471 
472  std::vector<TVector3> xyz, dircos;
473 
474  for (unsigned int i = 0; i < pmatrack->size(); i++) {
475 
476  xyz.push_back((*pmatrack)[i]->Point3D());
477 
478  if (i < pmatrack->size() - 1) {
479  size_t j = i + 1;
480  double mag = 0.0;
481  TVector3 dc(0., 0., 0.);
482  while ((mag == 0.0) and (j < pmatrack->size())) {
483  dc = (*pmatrack)[j]->Point3D();
484  dc -= (*pmatrack)[i]->Point3D();
485  mag = dc.Mag();
486  ++j;
487  }
488  if (mag > 0.0)
489  dc *= 1.0 / mag;
490  else if (!dircos.empty())
491  dc = dircos.back();
492  dircos.push_back(dc);
493  }
494  else
495  dircos.push_back(dircos.back());
496  }
497 
498  // Orient the track correctly
499  std::map<int, double> distanceToVertex, distanceToEnd;
500  TVector3 vertex = *xyz.begin(), end = *xyz.rbegin();
501 
502  // Loop over all the planes and find the distance from the vertex and end
503  // projections to the centre in each plane
504  for (std::map<int, TVector2>::const_iterator showerCentreIt = showerCentreMap.begin();
505  showerCentreIt != showerCentreMap.end();
506  ++showerCentreIt) {
507 
508  // Project the vertex and the end point onto this plane
509  TVector2 vertexProj = Project3DPointOntoPlane_(detProp, vertex, showerCentreIt->first);
510  TVector2 endProj = Project3DPointOntoPlane_(detProp, end, showerCentreIt->first);
511 
512  // Find the distance of each to the centre of the cluster
513  distanceToVertex[showerCentreIt->first] = (vertexProj - showerCentreIt->second).Mod();
514  distanceToEnd[showerCentreIt->first] = (endProj - showerCentreIt->second).Mod();
515  }
516 
517  // Find the average distance to the vertex and the end across the planes
518  double avDistanceToVertex = 0, avDistanceToEnd = 0;
519  for (std::map<int, double>::iterator distanceToVertexIt = distanceToVertex.begin();
520  distanceToVertexIt != distanceToVertex.end();
521  ++distanceToVertexIt)
522  avDistanceToVertex += distanceToVertexIt->second;
523  avDistanceToVertex /= distanceToVertex.size();
524 
525  for (std::map<int, double>::iterator distanceToEndIt = distanceToEnd.begin();
526  distanceToEndIt != distanceToEnd.end();
527  ++distanceToEndIt)
528  avDistanceToEnd += distanceToEndIt->second;
529  if (distanceToEnd.size() != 0) avDistanceToEnd /= distanceToEnd.size();
530 
531  if (fDebug > 2)
532  std::cout << "Distance to vertex is " << avDistanceToVertex << " and distance to end is "
533  << avDistanceToEnd << '\n';
534 
535  // Change order if necessary
536  if (avDistanceToEnd > avDistanceToVertex) {
537  std::reverse(xyz.begin(), xyz.end());
538  std::transform(
539  dircos.begin(), dircos.end(), dircos.begin(), [](TVector3 const& vec) { return -1 * vec; });
540  }
541 
542  if (xyz.size() != dircos.size())
543  mf::LogError("EMShowerAlg") << "Problem converting pma::Track3D to recob::Track";
544 
545  track = std::make_unique<recob::Track>(
548  recob::Track::Flags_t(xyz.size()),
549  false),
550  0,
551  -1.,
552  0,
555  -1);
556 
557  return track;
558 }
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::iterator iterator
constexpr to_element_t to_element
Definition: ToElement.h:24
pma::ProjectionMatchingAlg const fProjectionMatchingAlg
Definition: EMShowerAlg.h:279
ROOT::Math::SMatrix< Double32_t, 5, 5, ROOT::Math::MatRepSym< Double32_t, 5 > > SMatrixSym55
Definition: TrackingTypes.h:85
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::vector< Vector_t > convertCollToVector(std::vector< Vector > const &coll)
Definition: TrackingTypes.h:58
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
TrackTrajectory::Flags_t Flags_t
Definition: Track.h:68
intermediate_table::const_iterator const_iterator
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
TVector3 Construct3DPoint_(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit1, art::Ptr< recob::Hit > const &hit2) const
Constructs a 3D point (in [cm]) to represent the hits given in two views.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
A trajectory in space reconstructed from hits.
std::vector< Point_t > convertCollToPoint(std::vector< Point > const &coll)
Definition: TrackingTypes.h:55
pma::Track3D * buildSegment(const detinfo::DetectorPropertiesData &clockData, const std::vector< art::Ptr< recob::Hit >> &hits_1, const std::vector< art::Ptr< recob::Hit >> &hits_2={}) const
TVector2 Project3DPointOntoPlane_(detinfo::DetectorPropertiesData const &detProp, TVector3 const &point, int plane, int cryostat=0) const
Detector simulation of raw signals on wires.
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
if(!yymsg) yymsg
vertex reconstruction
std::unique_ptr< recob::Track > shower::EMShowerAlg::ConstructTrack ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  track1,
std::vector< art::Ptr< recob::Hit >> const &  track2 
) const

Constructs a recob::Track from sets of hits in two views. Intended to be used to construct the initial first part of a shower. All methods taken from the pma tracking algorithm (R. Sulej and D. Stefan).

Definition at line 561 of file EMShowerAlg.cxx.

564 {
565  std::map<int, TVector2> showerCentreMap;
566  return ConstructTrack(detProp, track1, track2, showerCentreMap);
567 }
std::unique_ptr< recob::Track > ConstructTrack(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &track1, std::vector< art::Ptr< recob::Hit >> const &track2, std::map< int, TVector2 > const &showerCentreMap) const
double shower::EMShowerAlg::FinddEdx_ ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  trackHits,
std::unique_ptr< recob::Track > const &  track 
) const
private

Finds dE/dx for the track given a set of hits.

Definition at line 570 of file EMShowerAlg.cxx.

574 {
575  assert(not empty(trackHits));
576  if (!track) return -999;
577 
578  recob::Hit const& firstHit = *trackHits.front();
579 
580  // Get the pitch
581  double pitch = 0;
582  try {
583  pitch = lar::util::TrackPitchInView(*track, firstHit.View());
584  }
585  catch (...) {
586  }
587 
588  // Deal with large pitches
589  if (pitch > fdEdxTrackLength) {
590  return fCalorimetryAlg.dEdx_AREA(clockData, detProp, firstHit, pitch);
591  }
592 
593  double totalCharge = 0, totalDistance = 0, avHitTime = 0;
594  unsigned int nHits = 0;
595 
596  for (auto const& hit : trackHits | views::transform(to_element)) {
597  if (totalDistance + pitch < fdEdxTrackLength) {
598  totalDistance += pitch;
599  totalCharge += hit.Integral();
600  avHitTime += hit.PeakTime();
601  ++nHits;
602  }
603  }
604 
605  avHitTime /= (double)nHits;
606 
607  double const dQdx = totalCharge / totalDistance;
608  return fCalorimetryAlg.dEdx_AREA(clockData, detProp, dQdx, avHitTime, firstHit.WireID().Plane);
609 }
constexpr to_element_t to_element
Definition: ToElement.h:24
geo::WireID WireID() const
Definition: Hit.h:233
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
double const fdEdxTrackLength
Definition: EMShowerAlg.h:265
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Detector simulation of raw signals on wires.
double TrackPitchInView(recob::Track const &track, geo::View_t view, size_t trajectory_point=0U)
Returns the projected length of track on a wire pitch step [cm].
Definition: TrackUtils.cxx:78
calo::CalorimetryAlg const fCalorimetryAlg
Definition: EMShowerAlg.h:278
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
void shower::EMShowerAlg::FindInitialTrack ( detinfo::DetectorPropertiesData const &  detProp,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  hits,
std::unique_ptr< recob::Track > &  initialTrack,
std::map< int, std::vector< art::Ptr< recob::Hit >>> &  initialTrackHits,
int  plane 
) const

Finds the initial track-like part of the shower and the hits in all views associated with it

Finding the initial track requires three stages: – find the initial track-like hits in each view – use these to construct a track

Definition at line 612 of file EMShowerAlg.cxx.

618 {
619 
620  /// Finding the initial track requires three stages:
621  /// -- find the initial track-like hits in each view
622  /// -- use these to construct a track
623 
624  // Now find the hits belonging to the track
625  if (fDebug > 1)
626  std::cout << " ------------------ Finding initial track hits "
627  "-------------------- \n";
628  initialTrackHits = FindShowerStart_(showerHitsMap);
629  if (fDebug > 1) {
630  std::cout << "Here are the initial shower hits... \n";
631  for (auto const& [plane, hitPtrs] : initialTrackHits) {
632  std::cout << " Plane " << plane << '\n';
633  for (auto const& hit : hitPtrs | views::transform(to_element)) {
634  std::cout << " Hit is (" << HitCoordinates_(hit).X() << " (real hit " << hit.WireID()
635  << "), " << HitCoordinates_(hit).Y() << ")\n";
636  }
637  }
638  }
639  if (fDebug > 1)
640  std::cout << " ------------------ End finding initial track hits "
641  "-------------------- \n";
642 
643  // Now we have the track hits -- can make a track!
644  if (fDebug > 1) std::cout << " ------------------ Finding initial track -------------------- \n";
645  initialTrack = MakeInitialTrack_(detProp, initialTrackHits, showerHitsMap);
646  if (initialTrack and fDebug > 1) {
647  std::cout << "The track start is (" << initialTrack->Vertex().X() << ", "
648  << initialTrack->Vertex().Y() << ", " << initialTrack->Vertex().Z() << ")\n";
649  std::cout << "The track direction is (" << initialTrack->VertexDirection().X() << ", "
650  << initialTrack->VertexDirection().Y() << ", " << initialTrack->VertexDirection().Z()
651  << ")\n";
652  }
653  if (fDebug > 1)
654  std::cout << " ------------------ End finding initial track "
655  "-------------------- \n";
656 }
constexpr to_element_t to_element
Definition: ToElement.h:24
Vector_t VertexDirection() const
Definition: Track.h:132
Point_t const & Vertex() const
Definition: Track.h:124
Detector simulation of raw signals on wires.
std::unique_ptr< recob::Track > MakeInitialTrack_(detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &initialHitsMap, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &showerHitsMap) const
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
std::map< int, std::vector< art::Ptr< recob::Hit > > > FindShowerStart_(std::map< int, std::vector< art::Ptr< recob::Hit >>> const &orderedShowerMap) const
void shower::EMShowerAlg::FindInitialTrackHits ( std::vector< art::Ptr< recob::Hit >> const &  showerHits,
art::Ptr< recob::Vertex > const &  vertex,
std::vector< art::Ptr< recob::Hit >> &  trackHits 
) const

<Tingjun to="" document>="">

Definition at line 1620 of file EMShowerAlg.cxx.

1623 {
1624 
1625  // Find TPC for the vertex
1626  double xyz[3];
1627  vertex->XYZ(xyz);
1628  geo::TPCID tpc = fGeom->FindTPCAtPosition(xyz);
1629 
1630  // vertex cannot be projected into a TPC, find the TPC that has the most hits
1631  if (!tpc.isValid) {
1632  std::map<geo::TPCID, unsigned int> tpcmap;
1633  unsigned maxhits = 0;
1634  for (auto const& hit : showerHits) {
1635  ++tpcmap[geo::TPCID(hit->WireID())];
1636  }
1637  for (auto const& t : tpcmap) {
1638  if (t.second > maxhits) {
1639  maxhits = t.second;
1640  tpc = t.first;
1641  }
1642  }
1643  }
1644  if (!tpc.isValid) return;
1645 
1646  double parm[2];
1647  int fitok = 0;
1648  std::vector<double> wfit;
1649  std::vector<double> tfit;
1650  std::vector<double> cfit;
1651 
1652  for (size_t i = 0; i < fNfitpass; ++i) {
1653 
1654  // Fit a straight line through hits
1655  unsigned int nhits = 0;
1656  for (auto& hit : showerHits) {
1657  if (hit->WireID().TPC == tpc.TPC) {
1658  TVector2 coord = HitCoordinates_(*hit);
1659  if (i == 0 ||
1660  (std::abs((coord.Y() - (parm[0] + coord.X() * parm[1])) * cos(atan(parm[1]))) <
1661  fToler[i - 1]) ||
1662  fitok == 1) {
1663  ++nhits;
1664  if (nhits == fNfithits[i] + 1) break;
1665  wfit.push_back(coord.X());
1666  tfit.push_back(coord.Y());
1667  cfit.push_back(1.);
1668  if (i == fNfitpass - 1) { trackHits.push_back(hit); }
1669  }
1670  }
1671  }
1672 
1673  if (i < fNfitpass - 1 && wfit.size()) {
1674  fitok = WeightedFit(wfit.size(), &wfit[0], &tfit[0], &cfit[0], &parm[0]);
1675  }
1676  wfit.clear();
1677  tfit.clear();
1678  cfit.clear();
1679  }
1680 }
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:36
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
unsigned int const fNfitpass
Definition: EMShowerAlg.h:269
std::vector< double > const fToler
Definition: EMShowerAlg.h:271
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
T abs(T value)
std::vector< unsigned int > const fNfithits
Definition: EMShowerAlg.h:270
Int_t WeightedFit(const Int_t n, const Double_t *x, const Double_t *y, const Double_t *w, Double_t *parm) const
<Tingjun to="" document>="">
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Detector simulation of raw signals on wires.
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
IDparameter< geo::TPCID > TPCID
Member type of validated geo::TPCID parameter.
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
std::vector< art::Ptr< recob::Hit > > shower::EMShowerAlg::FindOrderOfHits_ ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  hits,
bool  perpendicular = false 
) const
private

Orders hits along the best fit line through the charge-weighted centre of the hits. Orders along the line perpendicular to the least squares line if perpendicular is set to true.

Definition at line 659 of file EMShowerAlg.cxx.

662 {
663  // Find the charge-weighted centre (in [cm]) of this shower
664  TVector2 centre = ShowerCenter_(detProp, hits);
665 
666  // Find a rough shower 'direction'
667  TVector2 direction = ShowerDirection_(detProp, hits);
668 
669  if (perpendicular) direction = direction.Rotate(TMath::Pi() / 2);
670 
671  // Find how far each hit (projected onto this axis) is from the centre
672  TVector2 pos;
673  std::map<double, art::Ptr<recob::Hit>> hitProjection;
674  for (auto const& hitPtr : hits) {
675  pos = HitPosition_(detProp, *hitPtr) - centre;
676  hitProjection[direction * pos] = hitPtr;
677  }
678 
679  // Get a vector of hits in order of the shower
680  std::vector<art::Ptr<recob::Hit>> showerHits;
682  hitProjection, std::back_inserter(showerHits), [](auto const& pr) { return pr.second; });
683 
684  // Make gradient plot
685  if (fMakeGradientPlot) {
686  std::map<int, TGraph*> graphs;
687  for (auto const& hit : showerHits | views::transform(to_element)) {
688  int tpc = hit.WireID().TPC;
689  if (graphs[tpc] == nullptr) graphs[tpc] = new TGraph();
690  graphs[tpc]->SetPoint(
691  graphs[tpc]->GetN(), HitPosition_(detProp, hit).X(), HitPosition_(detProp, hit).Y());
692  }
693  TMultiGraph* multigraph = new TMultiGraph();
694  for (auto const [color, graph] : graphs) {
695  graph->SetMarkerColor(color);
696  graph->SetMarkerStyle(8);
697  graph->SetMarkerSize(2);
698  multigraph->Add(graph);
699  }
700  TCanvas* canvas = new TCanvas();
701  multigraph->Draw("AP");
702  TLine line;
703  line.SetLineColor(2);
704  line.DrawLine(centre.X() - 1000 * direction.X(),
705  centre.Y() - 1000 * direction.Y(),
706  centre.X() + 1000 * direction.X(),
707  centre.Y() + 1000 * direction.Y());
708  canvas->SaveAs("Gradient.png");
709  delete canvas;
710  delete multigraph;
711  }
712 
713  return showerHits;
714 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
constexpr to_element_t to_element
Definition: ToElement.h:24
def graph(desc, maker=maker)
Definition: apa.py:294
TVector2 ShowerCenter_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
Returns the charge-weighted shower center.
auto transform_all(Container &, OutputIt, UnaryOp)
bool const fMakeGradientPlot
Definition: EMShowerAlg.h:284
TVector2 ShowerDirection_(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
Detector simulation of raw signals on wires.
std::size_t color(std::string const &procname)
void line(double t, double *p, double &x, double &y, double &z)
std::vector< std::vector< int > > shower::EMShowerAlg::FindShowers ( std::map< int, std::vector< int >> const &  trackToClusters) const

Makes showers given a map between tracks and all clusters associated with them.

Definition at line 717 of file EMShowerAlg.cxx.

718 {
719  // Showers are vectors of clusters
720  std::vector<std::vector<int>> showers;
721 
722  // Loop over all tracks
723  for (auto const& clusters : trackToClusters | views::values) {
724 
725  // Find which showers already made are associated with this track
726  std::vector<int> matchingShowers;
727  for (unsigned int shower = 0; shower < showers.size(); ++shower)
728  for (int const cluster : clusters) {
729  if (cet::search_all(showers[shower], cluster) and
730  not cet::search_all(matchingShowers, shower)) {
731  matchingShowers.push_back(shower);
732  }
733  }
734 
735  // THINK THERE PROBABLY CAN BE MORE THAN ONE!
736  // IN FACT, THIS WOULD BE A SUCCESS OF THE SHOWERING METHOD!
737  // // Shouldn't be more than one
738  // if (matchingShowers.size() > 1)
739  // mf::LogInfo("EMShowerAlg") << "Number of showers this track matches is " << matchingShowers.size() << std::endl;
740 
741  // New shower
742  if (matchingShowers.size() < 1) showers.push_back(clusters);
743 
744  // Add to existing shower
745  else {
746  for (int const cluster : clusters) {
747  if (not cet::search_all(showers.at(matchingShowers[0]), cluster))
748  showers.at(matchingShowers.at(0)).push_back(cluster);
749  }
750  }
751  }
752 
753  return showers;
754 }
void cluster(In first, In last, Out result, Pred *pred)
Definition: NNClusters.h:41
Cluster finding and building.
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
bool search_all(FwdCont const &, Datum const &)
Q_UINT16 values[128]
std::map< int, std::vector< art::Ptr< recob::Hit > > > shower::EMShowerAlg::FindShowerStart_ ( std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  orderedShowerMap) const
private

Takes a map of the shower hits on each plane (ordered from what has been decided to be the start) Returns a map of the initial track-like part of the shower on each plane

Definition at line 757 of file EMShowerAlg.cxx.

759 {
760 
761  std::map<int, std::vector<art::Ptr<recob::Hit>>> initialHitsMap;
762 
763  for (auto const& [plane, orderedShower] : orderedShowerMap) {
764  std::vector<art::Ptr<recob::Hit>> initialHits;
765 
766  // Find if the shower is traveling along ticks or wires
767  bool wireDirection = true;
768  std::vector<int> wires;
769  for (auto const& hit : orderedShower | views::transform(to_element))
770  wires.push_back(std::round(HitCoordinates_(hit).X()));
771 
772  cet::sort_all(wires);
773  if (std::abs(*wires.begin() - std::round(HitCoordinates_(**orderedShower.begin()).X())) > 3 and
774  std::abs(*wires.rbegin() - std::round(HitCoordinates_(**orderedShower.begin()).X())) > 3)
775  wireDirection = false;
776 
777  // Deal with showers traveling along wires
778  if (wireDirection) {
779  bool increasing = HitCoordinates_(**orderedShower.rbegin()).X() >
780  HitCoordinates_(**orderedShower.begin()).X();
781  std::map<int, std::vector<art::Ptr<recob::Hit>>> wireHitMap;
782  int multipleWires = 0;
783  for (auto const& hitPtr : orderedShower)
784  wireHitMap[std::round(HitCoordinates_(*hitPtr).X())].push_back(hitPtr);
785 
786  for (auto const& hitPtr : orderedShower) {
787  int wire = std::round(HitCoordinates_(*hitPtr).X());
788  if (wireHitMap[wire].size() > 1) {
789  ++multipleWires;
790  if (multipleWires > 5) break;
791  continue;
792  }
793  else if ((increasing and wireHitMap[wire + 1].size() > 1 and
794  (wireHitMap[wire + 2].size() > 1 or wireHitMap[wire + 3].size() > 1)) or
795  (!increasing and wireHitMap[wire - 1].size() > 1 and
796  (wireHitMap[wire - 2].size() > 1 or wireHitMap[wire - 3].size() > 1))) {
797  if ((increasing and
798  (wireHitMap[wire + 4].size() < 2 and wireHitMap[wire + 5].size() < 2 and
799  wireHitMap[wire + 6].size() < 2 and wireHitMap[wire + 9].size() > 1)) or
800  (!increasing and
801  (wireHitMap[wire - 4].size() < 2 and wireHitMap[wire - 5].size() < 2 and
802  wireHitMap[wire - 6].size() < 2) and
803  wireHitMap[wire - 9].size() > 1))
804  initialHits.push_back(hitPtr);
805  else
806  break;
807  }
808  else
809  initialHits.push_back(hitPtr);
810  }
811  if (!initialHits.size()) initialHits.push_back(*orderedShower.begin());
812  }
813 
814  // Deal with showers travelling along ticks
815  else {
816  bool increasing = HitCoordinates_(**orderedShower.rbegin()).Y() >
817  HitCoordinates_(**orderedShower.begin()).Y();
818  std::map<int, std::vector<art::Ptr<recob::Hit>>> tickHitMap;
819  for (std::vector<art::Ptr<recob::Hit>>::const_iterator hitIt = orderedShower.begin();
820  hitIt != orderedShower.end();
821  ++hitIt)
822  tickHitMap[std::round(HitCoordinates_(**hitIt).Y())].push_back(*hitIt);
823 
824  for (auto const& hitPtr : orderedShower) {
825  int const tick = std::round(HitCoordinates_(*hitPtr).Y());
826  if ((increasing and (tickHitMap[tick + 1].size() or tickHitMap[tick + 2].size() or
827  tickHitMap[tick + 3].size() or tickHitMap[tick + 4].size() or
828  tickHitMap[tick + 5].size())) or
829  (!increasing and (tickHitMap[tick - 1].size() or tickHitMap[tick - 2].size() or
830  tickHitMap[tick - 3].size() or tickHitMap[tick - 4].size() or
831  tickHitMap[tick - 5].size())))
832  break;
833  else
834  initialHits.push_back(hitPtr);
835  }
836  if (initialHits.empty()) initialHits.push_back(*orderedShower.begin());
837  }
838 
839  // Need at least two hits to make a track
840  if (initialHits.size() == 1 and orderedShower.size() > 2)
841  initialHits.push_back(orderedShower[1]);
842 
843  // Quality check -- make sure there isn't a single hit in a different TPC (artefact of tracking failure)
844  std::vector<art::Ptr<recob::Hit>> newInitialHits;
845  std::map<int, int> tpcHitMap;
846  std::vector<int> singleHitTPCs;
847  for (auto const& hit : initialHits | views::transform(to_element))
848  ++tpcHitMap[hit.WireID().TPC];
849 
850  for (auto const [tpc, count] : tpcHitMap)
851  if (count == 1) singleHitTPCs.push_back(tpc);
852 
853  if (singleHitTPCs.size()) {
854  if (fDebug > 2)
855  for (int const tpc : singleHitTPCs)
856  std::cout << "Removed hits in TPC " << tpc << '\n';
857 
858  for (auto const& hitPtr : initialHits)
859  if (not cet::search_all(singleHitTPCs, hitPtr->WireID().TPC))
860  newInitialHits.push_back(hitPtr);
861  if (!newInitialHits.size()) newInitialHits.push_back(*orderedShower.begin());
862  }
863  else
864  newInitialHits = initialHits;
865 
866  initialHitsMap[plane] = newInitialHits;
867  }
868 
869  return initialHitsMap;
870 }
constexpr to_element_t to_element
Definition: ToElement.h:24
struct vector vector
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
void sort_all(RandCont &)
T abs(T value)
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
bool search_all(FwdCont const &, Datum const &)
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
Detector simulation of raw signals on wires.
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
std::map< int, std::map< int, bool > > shower::EMShowerAlg::GetPlanePermutations_ ( const detinfo::DetectorPropertiesData detProp,
const std::map< int, std::vector< art::Ptr< recob::Hit >>> &  showerHitsMap 
) const
private

Takes all the shower hits, ready ordered, and returns information to help with the orientation of the shower in each view Returns map of most likely permutations of reorientation Starts at 0,0,0 (i.e. don't need to reorient any plane) and ends with 1,1,1 (i.e. every plane needs reorienting) Every permutation inbetween represent increasing less likely changes to satisfy the correct orientation criteria

Definition at line 873 of file EMShowerAlg.cxx.

876 {
877 
878  // The map to return
879  std::map<int, std::map<int, bool>> permutations;
880 
881  // Get the properties of the shower hits across the planes which will be used to
882  // determine the likelihood of a particular reorientation permutation
883  // -- relative width in the wire direction (if showers travel along the wire
884  // direction in a particular plane)
885  // -- the RMS gradients (how likely it is the RMS of the hit positions from
886  // central axis increases along a particular orientation)
887 
888  // Find the RMS, RMS gradient and wire widths
889  std::map<int, double> planeRMSGradients, planeRMS;
890  for (auto const& [plane, hitPtrs] : showerHitsMap) {
891  planeRMS[plane] = ShowerHitRMS_(detProp, hitPtrs);
892  planeRMSGradients[plane] = ShowerHitRMSGradient_(detProp, hitPtrs);
893  }
894 
895  // Order these backwards so they can be used to discriminate between planes
896  std::map<double, int> gradientMap;
897  for (int const plane : showerHitsMap | views::keys)
898  gradientMap[std::abs(planeRMSGradients.at(plane))] = plane;
899 
900  std::map<double, int> wireWidthMap = RelativeWireWidth_(showerHitsMap);
901 
902  if (fDebug > 1)
903  for (auto const [gradient, plane] : wireWidthMap)
904  std::cout << "Plane " << plane << " has relative width in wire of " << gradient
905  << "; and an RMS gradient of " << planeRMSGradients[plane] << '\n';
906 
907  // Find the correct permutations
908  int perm = 0;
909  std::vector<std::map<int, bool>> usedPermutations;
910 
911  // Most likely is to not change anything
912  for (int const plane : showerHitsMap | views::keys)
913  permutations[perm][plane] = 0;
914  ++perm;
915 
916  // Use properties of the shower to determine the middle cases
917  for (int const plane : wireWidthMap | views::values) {
918  std::map<int, bool> permutation;
919  permutation[plane] = true;
920  for (int const plane2 : wireWidthMap | views::values)
921  if (plane != plane2) permutation[plane2] = false;
922 
923  if (not cet::search_all(usedPermutations, permutation)) {
924  permutations[perm] = permutation;
925  usedPermutations.push_back(permutation);
926  ++perm;
927  }
928  }
929  for (int const plane : wireWidthMap | views::reverse | views::values) {
930  std::map<int, bool> permutation;
931  permutation[plane] = false;
932  for (int const plane2 : wireWidthMap | views::values)
933  if (plane != plane2) permutation[plane2] = true;
934 
935  if (not cet::search_all(usedPermutations, permutation)) {
936  permutations[perm] = permutation;
937  usedPermutations.push_back(permutation);
938  ++perm;
939  }
940  }
941 
942  // Least likely is to change everything
943  for (int const plane : showerHitsMap | views::keys)
944  permutations[perm][plane] = 1;
945  ++perm;
946 
947  if (fDebug > 1) {
948  std::cout << "Here are the permutations!\n";
949  for (auto const& [index, permutation] : permutations) {
950  std::cout << "Permutation " << index << '\n';
951  for (auto const [plane, value] : permutation)
952  std::cout << " Plane " << plane << " has value " << value << '\n';
953  }
954  }
955 
956  return permutations;
957 }
T abs(T value)
bool search_all(FwdCont const &, Datum const &)
double ShowerHitRMS_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
Q_UINT16 values[128]
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
std::map< double, int > RelativeWireWidth_(const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
double ShowerHitRMSGradient_(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
Returns the gradient of the RMS vs shower segment graph.
double shower::EMShowerAlg::GlobalWire_ ( const geo::WireID wireID) const
private

Find the global wire position.

Definition at line 1705 of file EMShowerAlg.cxx.

1706 {
1707  double globalWire = -999;
1708 
1709  // Induction
1710  if (fGeom->SignalType(wireID) == geo::kInduction) {
1711  double wireCentre[3];
1712  fGeom->WireIDToWireGeo(wireID).GetCenter(wireCentre);
1713  if (wireID.TPC % 2 == 0)
1714  globalWire =
1715  fGeom->WireCoordinate(wireCentre[1], wireCentre[2], wireID.Plane, 0, wireID.Cryostat);
1716  else
1717  globalWire =
1718  fGeom->WireCoordinate(wireCentre[1], wireCentre[2], wireID.Plane, 1, wireID.Cryostat);
1719  }
1720 
1721  // Collection
1722  else {
1723  // FOR COLLECTION WIRES, HARD CODE THE GEOMETRY FOR GIVEN DETECTORS
1724  // THIS _SHOULD_ BE TEMPORARY. GLOBAL WIRE SUPPORT IS BEING ADDED TO THE LARSOFT GEOMETRY AND SHOULD BE AVAILABLE SOON
1725  if (fDetector == "dune35t") {
1726  unsigned int nwires = fGeom->Nwires(wireID.Plane, 0, wireID.Cryostat);
1727  if (wireID.TPC == 0 or wireID.TPC == 1)
1728  globalWire = wireID.Wire;
1729  else if (wireID.TPC == 2 or wireID.TPC == 3 or wireID.TPC == 4 or wireID.TPC == 5)
1730  globalWire = nwires + wireID.Wire;
1731  else if (wireID.TPC == 6 or wireID.TPC == 7)
1732  globalWire = (2 * nwires) + wireID.Wire;
1733  else
1734  mf::LogError("BlurredClusterAlg")
1735  << "Error when trying to find a global induction plane coordinate for TPC " << wireID.TPC
1736  << " (geometry" << fDetector << ")";
1737  }
1738  else if (fDetector == "dune10kt") {
1739  unsigned int nwires = fGeom->Nwires(wireID.Plane, 0, wireID.Cryostat);
1740  // Detector geometry has four TPCs, two on top of each other, repeated along z...
1741  int block = wireID.TPC / 4;
1742  globalWire = (nwires * block) + wireID.Wire;
1743  }
1744  else {
1745  double wireCentre[3];
1746  fGeom->WireIDToWireGeo(wireID).GetCenter(wireCentre);
1747  if (wireID.TPC % 2 == 0)
1748  globalWire =
1749  fGeom->WireCoordinate(wireCentre[1], wireCentre[2], wireID.Plane, 0, wireID.Cryostat);
1750  else
1751  globalWire =
1752  fGeom->WireCoordinate(wireCentre[1], wireCentre[2], wireID.Plane, 1, wireID.Cryostat);
1753  }
1754  }
1755 
1756  return globalWire;
1757 }
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
Signal from induction planes.
Definition: geo_types.h:145
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
Definition: WireGeo.cxx:73
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
std::string const fDetector
Definition: EMShowerAlg.h:281
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const
TVector2 shower::EMShowerAlg::HitCoordinates_ ( recob::Hit const &  hit) const
private

Return the coordinates of this hit in global wire/tick space.

Definition at line 1683 of file EMShowerAlg.cxx.

1684 {
1685  return TVector2(GlobalWire_(hit.WireID()), hit.PeakTime());
1686 }
double GlobalWire_(const geo::WireID &wireID) const
Find the global wire position.
Detector simulation of raw signals on wires.
TVector2 shower::EMShowerAlg::HitPosition_ ( detinfo::DetectorPropertiesData const &  detProp,
recob::Hit const &  hit 
) const
private

Return the coordinates of this hit in units of cm.

Definition at line 1689 of file EMShowerAlg.cxx.

1691 {
1692  geo::PlaneID planeID = hit.WireID().planeID();
1693  return HitPosition_(detProp, HitCoordinates_(hit), planeID);
1694 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
Detector simulation of raw signals on wires.
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
TVector2 shower::EMShowerAlg::HitPosition_ ( detinfo::DetectorPropertiesData const &  detProp,
TVector2 const &  pos,
geo::PlaneID  planeID 
) const
private

Return the coordinates of this hit in units of cm.

Definition at line 1697 of file EMShowerAlg.cxx.

1700 {
1701  return TVector2(pos.X() * fGeom->WirePitch(planeID), detProp.ConvertTicksToX(pos.Y(), planeID));
1702 }
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
bool shower::EMShowerAlg::isCleanShower ( std::vector< art::Ptr< recob::Hit >> const &  hits) const

<Tingjun to="" document>="">

Definition at line 2065 of file EMShowerAlg.cxx.

2066 {
2067  if (hits.empty()) return false;
2068  if (hits.size() > 2000) return true;
2069  if (hits.size() < 20) return true;
2070 
2071  std::map<int, int> hitmap;
2072  unsigned nhits = 0;
2073  for (auto const& hit : hits | views::transform(to_element)) {
2074  ++nhits;
2075  if (nhits > 2) ++hitmap[hit.WireID().Wire];
2076  if (nhits == 20) break;
2077  }
2078  if (float(nhits - 2) / hitmap.size() > 1.4)
2079  return false;
2080  else
2081  return true;
2082 }
constexpr to_element_t to_element
Definition: ToElement.h:24
Detector simulation of raw signals on wires.
std::unique_ptr< recob::Track > shower::EMShowerAlg::MakeInitialTrack_ ( detinfo::DetectorPropertiesData const &  detProp,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  initialHitsMap,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  showerHitsMap 
) const
private

Takes initial track hits from multiple views and forms a track object which best represents the start of the shower

Definition at line 960 of file EMShowerAlg.cxx.

964 {
965  // Can't do much with just one view
966  if (initialHitsMap.size() < 2) {
967  mf::LogInfo("EMShowerAlg") << "Only one useful view for this shower; nothing can be done\n";
968  return std::unique_ptr<recob::Track>();
969  }
970 
971  std::vector<std::pair<int, int>> initialHitsSize;
972  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::const_iterator initialHitIt =
973  initialHitsMap.begin();
974  initialHitIt != initialHitsMap.end();
975  ++initialHitIt)
976  initialHitsSize.push_back(std::make_pair(initialHitIt->first, initialHitIt->second.size()));
977 
978  // Sort the planes by number of hits
979  std::sort(initialHitsSize.begin(),
980  initialHitsSize.end(),
981  [](std::pair<int, int> const& size1, std::pair<int, int> const& size2) {
982  return size1.second > size2.second;
983  });
984 
985  // Pick the two planes to use to make the track
986  // -- if more than two planes, can choose the two views
987  // more accurately
988  // -- if not, just use the two views available
989 
990  std::vector<int> planes;
991 
992  if (initialHitsSize.size() > 2 and !CheckShowerHits_(detProp, showerHitsMap)) {
993  int planeToIgnore = WorstPlane_(showerHitsMap);
994  if (fDebug > 1)
995  std::cout << "Igoring plane " << planeToIgnore << " in creation of initial track\n";
996  for (std::vector<std::pair<int, int>>::iterator hitsSizeIt = initialHitsSize.begin();
997  hitsSizeIt != initialHitsSize.end() and planes.size() < 2;
998  ++hitsSizeIt) {
999  if (hitsSizeIt->first == planeToIgnore) continue;
1000  planes.push_back(hitsSizeIt->first);
1001  }
1002  }
1003  else
1004  planes = {initialHitsSize.at(0).first, initialHitsSize.at(1).first};
1005 
1006  return ConstructTrack(detProp, initialHitsMap.at(planes.at(0)), initialHitsMap.at(planes.at(1)));
1007 }
int WorstPlane_(const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
Returns the plane which is determined to be the least likely to be correct.
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
struct vector vector
std::unique_ptr< recob::Track > ConstructTrack(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &track1, std::vector< art::Ptr< recob::Hit >> const &track2, std::map< int, TVector2 > const &showerCentreMap) const
bool CheckShowerHits_(detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &showerHitsMap) const
recob::Shower shower::EMShowerAlg::MakeShower ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
art::PtrVector< recob::Hit > const &  hits,
std::unique_ptr< recob::Track > const &  initialTrack,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  initialTrackHits 
) const

Makes a recob::Shower object given the hits in the shower and the initial track-like part.

Definition at line 1010 of file EMShowerAlg.cxx.

1016 {
1017 
1018  // Find the shower hits on each plane
1019  std::map<int, std::vector<art::Ptr<recob::Hit>>> planeHitsMap;
1020  for (auto const& hitPtr : hits)
1021  planeHitsMap[hitPtr->View()].push_back(hitPtr);
1022 
1023  int bestPlane = -1;
1024  unsigned int highestNumberOfHits = 0;
1025  std::vector<double> totalEnergy, totalEnergyError, dEdx, dEdxError;
1026 
1027  // Look at each of the planes
1028  for (unsigned int plane = 0; plane < fGeom->MaxPlanes(); ++plane) {
1029 
1030  // If there's hits on this plane...
1031  if (planeHitsMap.count(plane)) {
1032  dEdx.push_back(FinddEdx_(clockData, detProp, initialHitsMap.at(plane), initialTrack));
1033  totalEnergy.push_back(
1034  fShowerEnergyAlg.ShowerEnergy(clockData, detProp, planeHitsMap.at(plane), plane));
1035  if (planeHitsMap.at(plane).size() > highestNumberOfHits and initialHitsMap.count(plane)) {
1036  bestPlane = plane;
1037  highestNumberOfHits = planeHitsMap.at(plane).size();
1038  }
1039  }
1040 
1041  // If not...
1042  else {
1043  dEdx.push_back(0);
1044  totalEnergy.push_back(0);
1045  }
1046  }
1047 
1048  TVector3 direction, directionError, showerStart, showerStartError;
1049  if (initialTrack) {
1050  direction = initialTrack->VertexDirection<TVector3>();
1051  showerStart = initialTrack->Vertex<TVector3>();
1052  }
1053 
1054  if (fDebug > 0) {
1055  std::cout << "Best plane is " << bestPlane;
1056  std::cout << "\ndE/dx for each plane is: " << dEdx[0] << ", " << dEdx[1] << " and " << dEdx[2];
1057  std::cout << "\nTotal energy for each plane is: " << totalEnergy[0] << ", " << totalEnergy[1]
1058  << " and " << totalEnergy[2];
1059  std::cout << "\nThe shower start is (" << showerStart.X() << ", " << showerStart.Y() << ", "
1060  << showerStart.Z() << ")\n";
1061  std::cout << "The shower direction is (" << direction.X() << ", " << direction.Y() << ", "
1062  << direction.Z() << ")\n";
1063  }
1064 
1065  return recob::Shower(direction,
1066  directionError,
1067  showerStart,
1068  showerStartError,
1069  totalEnergy,
1070  totalEnergyError,
1071  dEdx,
1072  dEdxError,
1073  bestPlane);
1074 }
shower::ShowerEnergyAlg const fShowerEnergyAlg
Definition: EMShowerAlg.h:277
double ShowerEnergy(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, geo::PlaneID::PlaneID_t plane) const
Vector_t VertexDirection() const
Definition: Track.h:132
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
Point_t const & Vertex() const
Definition: Track.h:124
double FinddEdx_(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &trackHits, std::unique_ptr< recob::Track > const &track) const
Finds dE/dx for the track given a set of hits.
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
recob::Shower shower::EMShowerAlg::MakeShower ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
art::PtrVector< recob::Hit > const &  hits,
art::Ptr< recob::Vertex > const &  vertex,
int &  iok 
) const

<Tingjun to="" document>="">

Definition at line 1077 of file EMShowerAlg.cxx.

1082 {
1083  iok = 1;
1084 
1085  // Find the shower hits on each plane
1086  std::map<int, std::vector<art::Ptr<recob::Hit>>> planeHitsMap;
1087  for (auto const& hitPtr : hits)
1088  planeHitsMap[hitPtr->WireID().Plane].push_back(hitPtr);
1089 
1090  std::vector<std::vector<art::Ptr<recob::Hit>>> initialTrackHits(3);
1091 
1092  int pl0 = -1;
1093  int pl1 = -1;
1094  unsigned maxhits0 = 0;
1095  unsigned maxhits1 = 0;
1096 
1097  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::iterator planeHits = planeHitsMap.begin();
1098  planeHits != planeHitsMap.end();
1099  ++planeHits) {
1100 
1101  std::vector<art::Ptr<recob::Hit>> showerHits;
1102  OrderShowerHits_(detProp, planeHits->second, showerHits, vertex);
1103  FindInitialTrackHits(showerHits, vertex, initialTrackHits[planeHits->first]);
1104  if ((planeHits->second).size() > maxhits0) {
1105  if (pl0 != -1) {
1106  maxhits1 = maxhits0;
1107  pl1 = pl0;
1108  }
1109  pl0 = planeHits->first;
1110  maxhits0 = (planeHits->second).size();
1111  }
1112  else if ((planeHits->second).size() > maxhits1) {
1113  pl1 = planeHits->first;
1114  maxhits1 = (planeHits->second).size();
1115  }
1116  }
1117  if (pl0 != -1 && pl1 != -1 && initialTrackHits[pl0].size() >= 2 &&
1118  initialTrackHits[pl1].size() >= 2 &&
1119  initialTrackHits[pl0][0]->WireID().TPC == initialTrackHits[pl1][0]->WireID().TPC) {
1120  double xyz[3];
1121  vertex->XYZ(xyz);
1122  TVector3 vtx(xyz);
1123  pma::Track3D* pmatrack =
1124  fProjectionMatchingAlg.buildSegment(detProp, initialTrackHits[pl0], initialTrackHits[pl1]);
1125  std::vector<TVector3> spts;
1126 
1127  for (size_t i = 0; i < pmatrack->size(); ++i) {
1128  if ((*pmatrack)[i]->IsEnabled()) {
1129  TVector3 p3d = (*pmatrack)[i]->Point3D();
1130  spts.push_back(p3d);
1131  }
1132  }
1133  if (spts.size() >= 2) { // at least two space points
1134  TVector3 shwxyz, shwxyzerr;
1135  TVector3 shwdir, shwdirerr;
1136  std::vector<double> totalEnergy, totalEnergyError, dEdx, dEdxError;
1137  int bestPlane = pl0;
1138  double minpitch = 1000;
1139  std::vector<TVector3> dirs;
1140  if ((spts[0] - vtx).Mag() < (spts.back() - vtx).Mag()) {
1141  shwxyz = spts[0];
1142  size_t i = 5;
1143  if (spts.size() - 1 < 5) i = spts.size() - 1;
1144  shwdir = spts[i] - spts[0];
1145  shwdir = shwdir.Unit();
1146  }
1147  else {
1148  shwxyz = spts.back();
1149  size_t i = 0;
1150  if (spts.size() > 6) i = spts.size() - 6;
1151  shwdir = spts[i] - spts[spts.size() - 1];
1152  shwdir = shwdir.Unit();
1153  }
1154  for (unsigned int plane = 0; plane < fGeom->MaxPlanes(); ++plane) {
1155  if (planeHitsMap.find(plane) != planeHitsMap.end()) {
1156  totalEnergy.push_back(
1157  fShowerEnergyAlg.ShowerEnergy(clockData, detProp, planeHitsMap[plane], plane));
1158  }
1159  else {
1160  totalEnergy.push_back(0);
1161  }
1162  if (initialTrackHits[plane].size()) {
1163  double fdEdx = 0;
1164  double totQ = 0;
1165  double avgT = 0;
1166  double pitch = 0;
1167  double wirepitch = fGeom->WirePitch(initialTrackHits[plane][0]->WireID().planeID());
1168  double angleToVert =
1170  initialTrackHits[plane][0]->WireID().planeID()) -
1171  0.5 * TMath::Pi();
1172  double cosgamma = std::abs(sin(angleToVert) * shwdir.Y() + cos(angleToVert) * shwdir.Z());
1173  if (cosgamma > 0) pitch = wirepitch / cosgamma;
1174  if (pitch) {
1175  if (pitch < minpitch) {
1176  minpitch = pitch;
1177  bestPlane = plane;
1178  }
1179  int nhits = 0;
1180  std::vector<float> vQ;
1181  for (auto const& hit : initialTrackHits[plane]) {
1182  int w1 = hit->WireID().Wire;
1183  int w0 = initialTrackHits[plane][0]->WireID().Wire;
1184  if (std::abs((w1 - w0) * pitch) < fdEdxTrackLength) {
1185  vQ.push_back(hit->Integral());
1186  totQ += hit->Integral();
1187  avgT += hit->PeakTime();
1188  ++nhits;
1189  }
1190  }
1191  if (totQ) {
1192  double dQdx = TMath::Median(vQ.size(), &vQ[0]) / pitch;
1193  fdEdx = fCalorimetryAlg.dEdx_AREA(
1194  clockData, detProp, dQdx, avgT / nhits, initialTrackHits[plane][0]->WireID().Plane);
1195  }
1196  }
1197  dEdx.push_back(fdEdx);
1198  }
1199  else {
1200  dEdx.push_back(0);
1201  }
1202  }
1203  iok = 0;
1204  if (fDebug > 1) {
1205  std::cout << "Best plane is " << bestPlane;
1206  std::cout << "\ndE/dx for each plane is: " << dEdx[0] << ", " << dEdx[1] << " and "
1207  << dEdx[2];
1208  std::cout << "\nTotal energy for each plane is: " << totalEnergy[0] << ", "
1209  << totalEnergy[1] << " and " << totalEnergy[2];
1210  std::cout << "\nThe shower start is (" << shwxyz.X() << ", " << shwxyz.Y() << ", "
1211  << shwxyz.Z() << ")\n";
1212  shwxyz.Print();
1213  }
1214 
1215  return recob::Shower(shwdir,
1216  shwdirerr,
1217  shwxyz,
1218  shwxyzerr,
1219  totalEnergy,
1220  totalEnergyError,
1221  dEdx,
1222  dEdxError,
1223  bestPlane);
1224  }
1225  }
1226  return recob::Shower();
1227 }
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:36
void FindInitialTrackHits(std::vector< art::Ptr< recob::Hit >> const &showerHits, art::Ptr< recob::Vertex > const &vertex, std::vector< art::Ptr< recob::Hit >> &trackHits) const
<Tingjun to="" document>="">
shower::ShowerEnergyAlg const fShowerEnergyAlg
Definition: EMShowerAlg.h:277
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
pma::ProjectionMatchingAlg const fProjectionMatchingAlg
Definition: EMShowerAlg.h:279
double ShowerEnergy(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, geo::PlaneID::PlaneID_t plane) const
struct vector vector
double const fdEdxTrackLength
Definition: EMShowerAlg.h:265
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:184
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
pma::Track3D * buildSegment(const detinfo::DetectorPropertiesData &clockData, const std::vector< art::Ptr< recob::Hit >> &hits_1, const std::vector< art::Ptr< recob::Hit >> &hits_2={}) const
Detector simulation of raw signals on wires.
void OrderShowerHits_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &shower, std::vector< art::Ptr< recob::Hit >> &orderedShower, art::Ptr< recob::Vertex > const &vertex) const
calo::CalorimetryAlg const fCalorimetryAlg
Definition: EMShowerAlg.h:278
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
size_t size() const
Definition: PmaTrack3D.h:108
recob::tracking::Plane Plane
Definition: TrackState.h:17
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
std::vector< recob::SpacePoint > shower::EMShowerAlg::MakeSpacePoints ( detinfo::DetectorPropertiesData const &  detProp,
std::map< int, std::vector< art::Ptr< recob::Hit >>> const &  hits,
std::vector< std::vector< art::Ptr< recob::Hit >>> &  hitAssns 
) const

Makes space points from the shower hits in each plane.

Definition at line 1230 of file EMShowerAlg.cxx.

1234 {
1235  // Space points to return
1236  std::vector<recob::SpacePoint> spacePoints;
1237 
1238  // Make space points
1239  // Use the following procedure:
1240  // -- Consider hits plane by plane
1241  // -- For each hit on the first plane, consider the 3D point made by combining with each hit from the second plane
1242  // -- Project this 3D point back into the two planes
1243  // -- Determine how close to a the original hits this point lies
1244  // -- If close enough, make a 3D space point from this point
1245  // -- Discard these used hits in future iterations, along with hits in the
1246  // third plane (if exists) close to the projection of the point into this
1247  // plane
1248 
1249  // Container to hold used hits
1250  std::vector<int> usedHits;
1251 
1252  // Look through plane by plane
1253  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::const_iterator showerHitIt =
1254  showerHits.begin();
1255  showerHitIt != showerHits.end();
1256  ++showerHitIt) {
1257 
1258  // Find the other planes with hits
1259  std::vector<int> otherPlanes;
1260  for (unsigned int otherPlane = 0; otherPlane < fGeom->MaxPlanes(); ++otherPlane)
1261  if ((int)otherPlane != showerHitIt->first and showerHits.count(otherPlane))
1262  otherPlanes.push_back(otherPlane);
1263 
1264  // Can't make space points if we only have one view
1265  if (otherPlanes.size() == 0) return spacePoints;
1266 
1267  // Look at all hits on this plane
1268  for (std::vector<art::Ptr<recob::Hit>>::const_iterator planeHitIt = showerHitIt->second.begin();
1269  planeHitIt != showerHitIt->second.end();
1270  ++planeHitIt) {
1271 
1272  if (std::find(usedHits.begin(), usedHits.end(), planeHitIt->key()) != usedHits.end())
1273  continue;
1274 
1275  // Make a 3D point with every hit on the second plane
1276  const std::vector<art::Ptr<recob::Hit>> otherPlaneHits = showerHits.at(otherPlanes.at(0));
1277  for (std::vector<art::Ptr<recob::Hit>>::const_iterator otherPlaneHitIt =
1278  otherPlaneHits.begin();
1279  otherPlaneHitIt != otherPlaneHits.end() and
1280  std::find(usedHits.begin(), usedHits.end(), planeHitIt->key()) == usedHits.end();
1281  ++otherPlaneHitIt) {
1282 
1283  if ((*otherPlaneHitIt)->WireID().TPC != (*planeHitIt)->WireID().TPC or
1284  std::find(usedHits.begin(), usedHits.end(), otherPlaneHitIt->key()) != usedHits.end())
1285  continue;
1286 
1287  TVector3 point = Construct3DPoint_(detProp, *planeHitIt, *otherPlaneHitIt);
1288  std::vector<art::Ptr<recob::Hit>> pointHits;
1289  bool truePoint = false;
1290 
1291  if (otherPlanes.size() > 1) {
1292 
1293  TVector2 projThirdPlane = Project3DPointOntoPlane_(detProp, point, otherPlanes.at(1));
1294  const std::vector<art::Ptr<recob::Hit>> otherOtherPlaneHits =
1295  showerHits.at(otherPlanes.at(1));
1296 
1297  for (std::vector<art::Ptr<recob::Hit>>::const_iterator otherOtherPlaneHitIt =
1298  otherOtherPlaneHits.begin();
1299  otherOtherPlaneHitIt != otherOtherPlaneHits.end() and !truePoint;
1300  ++otherOtherPlaneHitIt) {
1301 
1302  if ((*otherOtherPlaneHitIt)->WireID().TPC == (*planeHitIt)->WireID().TPC and
1303  (projThirdPlane - HitPosition_(detProp, **otherOtherPlaneHitIt)).Mod() <
1304  fSpacePointSize) {
1305 
1306  truePoint = true;
1307 
1308  // Remove hits used to make the point
1309  usedHits.push_back(planeHitIt->key());
1310  usedHits.push_back(otherPlaneHitIt->key());
1311  usedHits.push_back(otherOtherPlaneHitIt->key());
1312 
1313  pointHits.push_back(*planeHitIt);
1314  pointHits.push_back(*otherPlaneHitIt);
1315  pointHits.push_back(*otherOtherPlaneHitIt);
1316  }
1317  }
1318  }
1319 
1320  else if ((Project3DPointOntoPlane_(detProp, point, (*planeHitIt)->WireID().Plane) -
1321  HitPosition_(detProp, **planeHitIt))
1322  .Mod() < fSpacePointSize and
1323  (Project3DPointOntoPlane_(detProp, point, (*otherPlaneHitIt)->WireID().Plane) -
1324  HitPosition_(detProp, **otherPlaneHitIt))
1325  .Mod() < fSpacePointSize) {
1326 
1327  truePoint = true;
1328 
1329  usedHits.push_back(planeHitIt->key());
1330  usedHits.push_back(otherPlaneHitIt->key());
1331 
1332  pointHits.push_back(*planeHitIt);
1333  pointHits.push_back(*otherPlaneHitIt);
1334  }
1335 
1336  // Make space point
1337  if (truePoint) {
1338  double xyz[3] = {point.X(), point.Y(), point.Z()};
1339  double xyzerr[6] = {fSpacePointSize,
1344  fSpacePointSize};
1345  double chisq = 0.;
1346  spacePoints.emplace_back(xyz, xyzerr, chisq);
1347  hitAssns.push_back(pointHits);
1348  }
1349 
1350  } // end loop over second plane hits
1351 
1352  } // end loop over first plane hits
1353 
1354  } // end loop over planes
1355 
1356  if (fDebug > 0) {
1357  std::cout << "-------------------- Space points -------------------\n";
1358  std::cout << "There are " << spacePoints.size() << " space points:\n";
1359  if (fDebug > 1)
1360  for (std::vector<recob::SpacePoint>::const_iterator spacePointIt = spacePoints.begin();
1361  spacePointIt != spacePoints.end();
1362  ++spacePointIt) {
1363  const double* xyz = spacePointIt->XYZ();
1364  std::cout << " Space point (" << xyz[0] << ", " << xyz[1] << ", " << xyz[2] << ")\n";
1365  }
1366  }
1367 
1368  return spacePoints;
1369 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
struct vector vector
intermediate_table::const_iterator const_iterator
TVector3 Construct3DPoint_(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit1, art::Ptr< recob::Hit > const &hit2) const
Constructs a 3D point (in [cm]) to represent the hits given in two views.
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
TVector2 Project3DPointOntoPlane_(detinfo::DetectorPropertiesData const &detProp, TVector3 const &point, int plane, int cryostat=0) const
double const fSpacePointSize
Definition: EMShowerAlg.h:266
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
std::map< int, std::vector< art::Ptr< recob::Hit > > > shower::EMShowerAlg::OrderShowerHits ( detinfo::DetectorPropertiesData const &  detProp,
art::PtrVector< recob::Hit > const &  shower,
int  plane 
) const

Takes the hits associated with a shower and orders them so they follow the direction of the shower.

Ordering the shower hits requires three stages: – putting all the hits in a given plane in some kind of order – use the properties of the hits in all three planes to check this order – orient the hits correctly using properties of the shower

Definition at line 1372 of file EMShowerAlg.cxx.

1375 {
1376  /// Ordering the shower hits requires three stages:
1377  /// -- putting all the hits in a given plane in some kind of order
1378  /// -- use the properties of the hits in all three planes to check this order
1379  /// -- orient the hits correctly using properties of the shower
1380 
1381  // ------------- Put hits in order ------------
1382 
1383  // Find the shower hits on each plane
1384  std::map<int, std::vector<art::Ptr<recob::Hit>>> showerHitsMap;
1385  for (auto const& hitPtr : shower) {
1386  showerHitsMap[hitPtr->WireID().Plane].push_back(hitPtr);
1387  }
1388 
1389  // Order the hits, get the RMS and the RMS gradient for the hits in this plane
1390  std::map<int, double> planeRMSGradients, planeRMS;
1391  for (auto const& [plane, hits] : showerHitsMap) {
1392  if (desired_plane != plane and desired_plane != -1) continue;
1393  std::vector<art::Ptr<recob::Hit>> orderedHits = FindOrderOfHits_(detProp, hits);
1394  planeRMS[plane] = ShowerHitRMS_(detProp, orderedHits);
1395  planeRMSGradients[plane] = ShowerHitRMSGradient_(detProp, orderedHits);
1396  showerHitsMap[plane] = orderedHits;
1397  }
1398 
1399  if (fDebug > 1) {
1400  for (auto const [plane, shower_hit_rms] : planeRMS) {
1401  std::cout << "Plane " << plane << " has RMS " << shower_hit_rms << " and RMS gradient "
1402  << planeRMSGradients.at(plane) << '\n';
1403  }
1404  }
1405 
1406  if (fDebug > 2) {
1407  std::cout << "\nHits in order; after ordering, before reversing...\n";
1408  for (auto const& [plane, hitPtrs] : showerHitsMap) {
1409  std::cout << " Plane " << plane << '\n';
1410  for (auto const& hit : hitPtrs | views::transform(to_element)) {
1411  std::cout << " Hit at (" << HitCoordinates_(hit).X() << ", " << HitCoordinates_(hit).Y()
1412  << ") -- real wire " << hit.WireID() << ", hit position ("
1413  << HitPosition_(detProp, hit).X() << ", " << HitPosition_(detProp, hit).Y()
1414  << ")\n";
1415  }
1416  }
1417  }
1418 
1419  // ------------- Check between the views to ensure consistency of ordering -------------
1420 
1421  // Check between the views to make sure there isn't a poorly formed shower in just one view
1422  // First, determine the average RMS and RMS gradient across the other planes
1423  std::map<int, double> planeOtherRMS, planeOtherRMSGradients;
1424  for (std::map<int, double>::iterator planeRMSIt = planeRMS.begin(); planeRMSIt != planeRMS.end();
1425  ++planeRMSIt) {
1426  planeOtherRMS[planeRMSIt->first] = 0;
1427  planeOtherRMSGradients[planeRMSIt->first] = 0;
1428  int nOtherPlanes = 0;
1429  for (int plane = 0; plane < (int)fGeom->MaxPlanes(); ++plane) {
1430  if (plane != planeRMSIt->first and planeRMS.count(plane)) {
1431  planeOtherRMS[planeRMSIt->first] += planeRMS.at(plane);
1432  planeOtherRMSGradients[planeRMSIt->first] += planeRMSGradients.at(plane);
1433  ++nOtherPlanes;
1434  }
1435  }
1436  planeOtherRMS[planeRMSIt->first] /= (double)nOtherPlanes;
1437  planeOtherRMSGradients[planeRMSIt->first] /= (double)nOtherPlanes;
1438  }
1439 
1440  // Look to see if one plane has a particularly high RMS (compared to the
1441  // others) whilst having a similar gradient
1442  for (auto const& [plane, hitPtrs] : showerHitsMap) {
1443  if (planeRMS.at(plane) > planeOtherRMS.at(plane) * 2) {
1444  if (fDebug > 1) std::cout << "Plane " << plane << " was perpendicular... recalculating\n";
1445  std::vector<art::Ptr<recob::Hit>> orderedHits =
1446  this->FindOrderOfHits_(detProp, hitPtrs, true);
1447  showerHitsMap[plane] = orderedHits;
1448  planeRMSGradients[plane] = this->ShowerHitRMSGradient_(detProp, orderedHits);
1449  }
1450  }
1451 
1452  // ------------- Orient the shower correctly ---------------
1453 
1454  if (fDebug > 1) {
1455  std::cout << "Before reversing, here are the start and end points...\n";
1456  for (auto const& [plane, hitPtrs] : showerHitsMap) {
1457  std::cout << " Plane " << plane << " has start (" << HitCoordinates_(*hitPtrs.front()).X()
1458  << ", " << HitCoordinates_(*hitPtrs.front()).Y() << ") (real wire "
1459  << hitPtrs.front()->WireID() << ") and end ("
1460  << HitCoordinates_(*hitPtrs.back()).X() << ", "
1461  << HitCoordinates_(*hitPtrs.back()).Y() << ") (real wire "
1462  << hitPtrs.back()->WireID() << ")\n";
1463  }
1464  }
1465 
1466  // Use the RMS gradient information to get an initial ordering
1467  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::iterator showerHitsIt =
1468  showerHitsMap.begin();
1469  showerHitsIt != showerHitsMap.end();
1470  ++showerHitsIt) {
1471  double gradient = planeRMSGradients.at(showerHitsIt->first);
1472  if (gradient < 0) std::reverse(showerHitsIt->second.begin(), showerHitsIt->second.end());
1473  }
1474 
1475  if (fDebug > 2) {
1476  std::cout << "\nHits in order; after reversing, before checking isolated hits...\n";
1477  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::iterator showerHitsIt =
1478  showerHitsMap.begin();
1479  showerHitsIt != showerHitsMap.end();
1480  ++showerHitsIt) {
1481  std::cout << " Plane " << showerHitsIt->first << '\n';
1482  for (std::vector<art::Ptr<recob::Hit>>::iterator hitIt = showerHitsIt->second.begin();
1483  hitIt != showerHitsIt->second.end();
1484  ++hitIt)
1485  std::cout << " Hit at (" << HitCoordinates_(**hitIt).X() << ", "
1486  << HitCoordinates_(**hitIt).Y() << ") -- real wire " << (*hitIt)->WireID()
1487  << ", hit position (" << HitPosition_(detProp, **hitIt).X() << ", "
1488  << HitPosition_(detProp, **hitIt).Y() << ")\n";
1489  }
1490  }
1491 
1492  CheckIsolatedHits_(showerHitsMap);
1493 
1494  if (fDebug > 2) {
1495  std::cout << "\nHits in order; after checking isolated hits...\n";
1496  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::iterator showerHitsIt =
1497  showerHitsMap.begin();
1498  showerHitsIt != showerHitsMap.end();
1499  ++showerHitsIt) {
1500  std::cout << " Plane " << showerHitsIt->first << '\n';
1501  for (std::vector<art::Ptr<recob::Hit>>::iterator hitIt = showerHitsIt->second.begin();
1502  hitIt != showerHitsIt->second.end();
1503  ++hitIt)
1504  std::cout << " Hit at (" << HitCoordinates_(**hitIt).X() << ", "
1505  << HitCoordinates_(**hitIt).Y() << ") -- real wire " << (*hitIt)->WireID()
1506  << ", hit position (" << HitPosition_(detProp, **hitIt).X() << ", "
1507  << HitPosition_(detProp, **hitIt).Y() << ")\n";
1508  }
1509  }
1510 
1511  if (fDebug > 1) {
1512  std::cout << "After reversing and checking isolated hits, here are the "
1513  "start and end points...\n";
1514  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::iterator showerHitsIt =
1515  showerHitsMap.begin();
1516  showerHitsIt != showerHitsMap.end();
1517  ++showerHitsIt)
1518  std::cout << " Plane " << showerHitsIt->first << " has start ("
1519  << HitCoordinates_(*showerHitsIt->second.front()).X() << ", "
1520  << HitCoordinates_(*showerHitsIt->second.front()).Y() << ") (real wire "
1521  << showerHitsIt->second.front()->WireID() << ") and end ("
1522  << HitCoordinates_(*showerHitsIt->second.back()).X() << ", "
1523  << HitCoordinates_(*showerHitsIt->second.back()).Y() << ")\n";
1524  }
1525 
1526  // Check for views in which the shower travels almost along the wire planes
1527  // (shown by a small relative wire width)
1528  std::map<double, int> wireWidths = RelativeWireWidth_(showerHitsMap);
1529  std::vector<int> badPlanes;
1530  if (fDebug > 1) std::cout << "Here are the relative wire widths... \n";
1531  for (auto const [relative_wire_width, plane] : wireWidths) {
1532  if (fDebug > 1)
1533  std::cout << "Plane " << plane << " has relative wire width " << relative_wire_width << '\n';
1534  if (relative_wire_width < 1 / (double)wireWidths.size()) badPlanes.push_back(plane);
1535  }
1536 
1537  std::map<int, std::vector<art::Ptr<recob::Hit>>> ignoredPlanes;
1538  if (badPlanes.size() == 1) {
1539  int const badPlane = badPlanes[0];
1540  if (fDebug > 1) std::cout << "Ignoring plane " << badPlane << " when orientating\n";
1541  ignoredPlanes[badPlane] = showerHitsMap.at(badPlane);
1542  showerHitsMap.erase(badPlane);
1543  }
1544 
1545  // Consider all possible permutations of planes (0/1, oriented
1546  // correctly/incorrectly)
1547  std::map<int, std::map<int, bool>> permutations = GetPlanePermutations_(detProp, showerHitsMap);
1548 
1549  // Go through all permutations until we have a satisfactory orientation
1550  auto const originalShowerHitsMap = showerHitsMap;
1551 
1552  int n = 0;
1553  while (!CheckShowerHits_(detProp, showerHitsMap) and
1554  n < TMath::Power(2, (int)showerHitsMap.size())) {
1555  if (fDebug > 1) std::cout << "Permutation " << n << '\n';
1556  for (int const plane : showerHitsMap | views::keys) {
1557  auto hits = originalShowerHitsMap.at(plane);
1558  if (permutations[n][plane] == 1) { std::reverse(hits.begin(), hits.end()); }
1559  showerHitsMap[plane] = hits;
1560  }
1561  ++n;
1562  }
1563 
1564  // Go back to original if still no consistency
1565  if (!CheckShowerHits_(detProp, showerHitsMap)) showerHitsMap = originalShowerHitsMap;
1566 
1567  if (fDebug > 2) {
1568  std::cout << "End of OrderShowerHits: here are the order of hits:\n";
1569  for (auto const& [plane, hitPtrs] : showerHitsMap) {
1570  std::cout << " Plane " << plane << '\n';
1571  for (auto const& hit : hitPtrs | views::transform(to_element)) {
1572  std::cout << " Hit (" << HitCoordinates_(hit).X() << " (real wire " << hit.WireID()
1573  << "), " << HitCoordinates_(hit).Y() << ") -- pos ("
1574  << HitPosition_(detProp, hit).X() << ", " << HitPosition_(detProp, hit).Y()
1575  << ")\n";
1576  }
1577  }
1578  }
1579 
1580  if (ignoredPlanes.size())
1581  showerHitsMap[ignoredPlanes.begin()->first] = ignoredPlanes.begin()->second;
1582 
1583  return showerHitsMap;
1584 }
intermediate_table::iterator iterator
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
constexpr to_element_t to_element
Definition: ToElement.h:24
struct vector vector
std::map< int, std::map< int, bool > > GetPlanePermutations_(const detinfo::DetectorPropertiesData &detProp, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
void CheckIsolatedHits_(std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
std::void_t< T > n
double ShowerHitRMS_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
Detector simulation of raw signals on wires.
bool CheckShowerHits_(detinfo::DetectorPropertiesData const &detProp, std::map< int, std::vector< art::Ptr< recob::Hit >>> const &showerHitsMap) const
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
std::vector< art::Ptr< recob::Hit > > FindOrderOfHits_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, bool perpendicular=false) const
std::map< double, int > RelativeWireWidth_(const std::map< int, std::vector< art::Ptr< recob::Hit >>> &showerHitsMap) const
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
double ShowerHitRMSGradient_(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
Returns the gradient of the RMS vs shower segment graph.
void shower::EMShowerAlg::OrderShowerHits_ ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  shower,
std::vector< art::Ptr< recob::Hit >> &  orderedShower,
art::Ptr< recob::Vertex > const &  vertex 
) const
private

Takes the hits associated with a shower and orders then so they follow the direction of the shower

Definition at line 1587 of file EMShowerAlg.cxx.

1591 {
1592 
1593  showerHits = FindOrderOfHits_(detProp, shower);
1594 
1595  // Find TPC for the vertex
1596  double xyz[3];
1597  vertex->XYZ(xyz);
1598  geo::TPCID tpc = fGeom->FindTPCAtPosition(xyz);
1599  if (!tpc.isValid && showerHits.size()) tpc = geo::TPCID(showerHits[0]->WireID());
1600 
1601  // Find hits in the same TPC
1602  art::Ptr<recob::Hit> hit0, hit1;
1603  for (auto& hit : showerHits) {
1604  if (hit->WireID().TPC == tpc.TPC) {
1605  if (hit0.isNull()) { hit0 = hit; }
1606  hit1 = hit;
1607  }
1608  }
1609  if (hit0.isNull() || hit1.isNull()) return;
1610  TVector2 coord0 = TVector2(hit0->WireID().Wire, hit0->PeakTime());
1611  TVector2 coord1 = TVector2(hit1->WireID().Wire, hit1->PeakTime());
1612  TVector2 coordvtx = TVector2(fGeom->WireCoordinate(xyz[1], xyz[2], hit0->WireID().planeID()),
1613  detProp.ConvertXToTicks(xyz[0], hit0->WireID().planeID()));
1614  if ((coord1 - coordvtx).Mod() < (coord0 - coordvtx).Mod()) {
1615  std::reverse(showerHits.begin(), showerHits.end());
1616  }
1617 }
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:36
geo::WireID WireID() const
Definition: Hit.h:233
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
bool isNull() const noexcept
Definition: Ptr.h:173
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Detector simulation of raw signals on wires.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
std::vector< art::Ptr< recob::Hit > > FindOrderOfHits_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, bool perpendicular=false) const
constexpr PlaneID const & planeID() const
Definition: geo_types.h:638
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
TVector2 shower::EMShowerAlg::Project3DPointOntoPlane_ ( detinfo::DetectorPropertiesData const &  detProp,
TVector3 const &  point,
int  plane,
int  cryostat = 0 
) const
private

Projects a 3D point (units [cm]) onto a 2D plane Returns 2D point (units [cm])

Definition at line 1947 of file EMShowerAlg.cxx.

1951 {
1952 
1953  TVector2 wireTickPos = TVector2(-999., -999.);
1954 
1955  double pointPosition[3] = {point.X(), point.Y(), point.Z()};
1956 
1957  geo::TPCID tpcID = fGeom->FindTPCAtPosition(pointPosition);
1958  int tpc = 0;
1959  if (tpcID.isValid)
1960  tpc = tpcID.TPC;
1961  else
1962  return wireTickPos;
1963 
1964  // Construct wire ID for this point projected onto the plane
1965  geo::PlaneID planeID = geo::PlaneID(cryostat, tpc, plane);
1966  geo::WireID wireID;
1967  try {
1968  wireID = fGeom->NearestWireID(point, planeID);
1969  }
1970  catch (geo::InvalidWireError const& e) {
1971  wireID = e.suggestedWireID(); // pick the closest valid wire
1972  }
1973 
1974  wireTickPos = TVector2(GlobalWire_(wireID), detProp.ConvertXToTicks(point.X(), planeID));
1975 
1976  return HitPosition_(detProp, wireTickPos, planeID);
1977 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
double GlobalWire_(const geo::WireID &wireID) const
Find the global wire position.
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
const double e
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Exception thrown on invalid wire number.
Definition: Exceptions.h:42
geo::WireID NearestWireID(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the ID of wire closest to position in the specified TPC.
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
geo::WireID suggestedWireID() const
Returns a better wire ID.
Definition: Exceptions.h:120
std::map< double, int > shower::EMShowerAlg::RelativeWireWidth_ ( const std::map< int, std::vector< art::Ptr< recob::Hit >>> &  showerHitsMap) const
private

Determines the 'relative wire width', i.e. how spread a shower is across wires of each plane relative to the others If a shower travels along the wire directions in a particular view, it will have a smaller wire width in that view Returns a map relating these widths to each plane

Definition at line 1760 of file EMShowerAlg.cxx.

1762 {
1763 
1764  // Get the wire widths
1765  std::map<int, int> planeWireLength;
1766  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::const_iterator showerHitsIt =
1767  showerHitsMap.begin();
1768  showerHitsIt != showerHitsMap.end();
1769  ++showerHitsIt)
1770  planeWireLength[showerHitsIt->first] =
1771  std::abs(HitCoordinates_(*showerHitsIt->second.front()).X() -
1772  HitCoordinates_(*showerHitsIt->second.back()).X());
1773 
1774  // Find the relative wire width for each plane with respect to the others
1775  std::map<int, double> planeOtherWireLengths;
1776  for (std::map<int, int>::iterator planeWireLengthIt = planeWireLength.begin();
1777  planeWireLengthIt != planeWireLength.end();
1778  ++planeWireLengthIt) {
1779  double quad = 0.;
1780  for (int plane = 0; plane < (int)fGeom->MaxPlanes(); ++plane)
1781  if (plane != planeWireLengthIt->first and planeWireLength.count(plane))
1782  quad += cet::square(planeWireLength[plane]);
1783  quad = std::sqrt(quad);
1784  planeOtherWireLengths[planeWireLengthIt->first] =
1785  planeWireLength[planeWireLengthIt->first] / (double)quad;
1786  }
1787 
1788  // Order these backwards
1789  std::map<double, int> wireWidthMap;
1790  for (std::map<int, std::vector<art::Ptr<recob::Hit>>>::const_iterator showerHitsIt =
1791  showerHitsMap.begin();
1792  showerHitsIt != showerHitsMap.end();
1793  ++showerHitsIt)
1794  wireWidthMap[planeOtherWireLengths.at(showerHitsIt->first)] = showerHitsIt->first;
1795 
1796  return wireWidthMap;
1797 }
intermediate_table::iterator iterator
struct vector vector
constexpr T square(T x)
Definition: pow.h:21
T abs(T value)
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274
TVector2 shower::EMShowerAlg::ShowerCenter_ ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  showerHits 
) const
private

Returns the charge-weighted shower center.

Definition at line 1826 of file EMShowerAlg.cxx.

1828 {
1829 
1830  TVector2 pos, chargePoint = TVector2(0, 0);
1831  double totalCharge = 0;
1832  for (std::vector<art::Ptr<recob::Hit>>::const_iterator hit = showerHits.begin();
1833  hit != showerHits.end();
1834  ++hit) {
1835  pos = HitPosition_(detProp, **hit);
1836  chargePoint += (*hit)->Integral() * pos;
1837  totalCharge += (*hit)->Integral();
1838  }
1839  TVector2 centre = chargePoint / totalCharge;
1840 
1841  return centre;
1842 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
struct vector vector
Detector simulation of raw signals on wires.
TVector2 shower::EMShowerAlg::ShowerDirection_ ( detinfo::DetectorPropertiesData const &  detProp,
const std::vector< art::Ptr< recob::Hit >> &  showerHits 
) const
private

Returns a rough charge-weighted shower 'direction' given the hits in the shower

Definition at line 1800 of file EMShowerAlg.cxx.

1802 {
1803 
1804  TVector2 pos;
1805  double weight = 1;
1806  double sumx = 0., sumy = 0., sumx2 = 0., sumxy = 0., sumweight = 0.;
1807  for (std::vector<art::Ptr<recob::Hit>>::const_iterator hit = showerHits.begin();
1808  hit != showerHits.end();
1809  ++hit) {
1810  //++nhits;
1811  pos = HitPosition_(detProp, **hit);
1812  weight = cet::square((*hit)->Integral());
1813  sumweight += weight;
1814  sumx += weight * pos.X();
1815  sumy += weight * pos.Y();
1816  sumx2 += weight * pos.X() * pos.X();
1817  sumxy += weight * pos.X() * pos.Y();
1818  }
1819  double gradient = (sumweight * sumxy - sumx * sumy) / (sumweight * sumx2 - sumx * sumx);
1820  TVector2 direction = TVector2(1, gradient).Unit();
1821 
1822  return direction;
1823 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
struct vector vector
constexpr T square(T x)
Definition: pow.h:21
weight
Definition: test.py:257
Detector simulation of raw signals on wires.
double shower::EMShowerAlg::ShowerHitRMS_ ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  showerHits 
) const
private

Returns the RMS of the hits from the central shower 'axis' along the length of the shower

Definition at line 1845 of file EMShowerAlg.cxx.

1847 {
1848 
1849  TVector2 direction = ShowerDirection_(detProp, showerHits);
1850  TVector2 centre = ShowerCenter_(detProp, showerHits);
1851 
1852  std::vector<double> distanceToAxis;
1853  for (std::vector<art::Ptr<recob::Hit>>::const_iterator showerHitsIt = showerHits.begin();
1854  showerHitsIt != showerHits.end();
1855  ++showerHitsIt) {
1856  TVector2 proj = (HitPosition_(detProp, **showerHitsIt) - centre).Proj(direction) + centre;
1857  distanceToAxis.push_back((HitPosition_(detProp, **showerHitsIt) - proj).Mod());
1858  }
1859  double RMS = TMath::RMS(distanceToAxis.begin(), distanceToAxis.end());
1860 
1861  return RMS;
1862 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
struct vector vector
TVector2 ShowerCenter_(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &showerHits) const
Returns the charge-weighted shower center.
TVector2 ShowerDirection_(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
double shower::EMShowerAlg::ShowerHitRMSGradient_ ( detinfo::DetectorPropertiesData const &  detProp,
const std::vector< art::Ptr< recob::Hit >> &  showerHits 
) const
private

Returns the gradient of the RMS vs shower segment graph.

Definition at line 1865 of file EMShowerAlg.cxx.

1868 {
1869  // Find a rough shower 'direction' and center
1870  TVector2 direction = ShowerDirection_(detProp, showerHits);
1871 
1872  // Bin the hits into discreet chunks
1873  int nShowerSegments = fNumShowerSegments;
1874  double lengthOfShower =
1875  (HitPosition_(detProp, *showerHits.back()) - HitPosition_(detProp, *showerHits.front())).Mod();
1876  double lengthOfSegment = lengthOfShower / (double)nShowerSegments;
1877  std::map<int, std::vector<art::Ptr<recob::Hit>>> showerSegments;
1878  std::map<int, double> segmentCharge;
1879  for (auto const& hitPtr : showerHits) {
1880  auto const& hit = *hitPtr;
1881  int const segment =
1882  (HitPosition_(detProp, hit) - HitPosition_(detProp, *showerHits.front())).Mod() /
1883  lengthOfSegment;
1884  showerSegments[segment].push_back(hitPtr);
1885  segmentCharge[segment] += hit.Integral();
1886  }
1887 
1888  TGraph* graph = new TGraph();
1889  std::vector<std::pair<int, double>> binVsRMS;
1890 
1891  // Loop over the bins to find the distribution of hits as the shower
1892  // progresses
1893  for (auto const& [segment, hitPtrs] : showerSegments) {
1894 
1895  // Get the mean position of the hits in this bin
1896  TVector2 meanPosition(0, 0);
1897  for (auto const& hit : hitPtrs | views::transform(to_element))
1898  meanPosition += HitPosition_(detProp, hit);
1899  meanPosition /= (double)hitPtrs.size();
1900 
1901  // Get the RMS of this bin
1902  std::vector<double> distanceToAxisBin;
1903  for (auto const& hit : hitPtrs | views::transform(to_element)) {
1904  TVector2 proj = (HitPosition_(detProp, hit) - meanPosition).Proj(direction) + meanPosition;
1905  distanceToAxisBin.push_back((HitPosition_(detProp, hit) - proj).Mod());
1906  }
1907 
1908  double RMSBin = TMath::RMS(distanceToAxisBin.begin(), distanceToAxisBin.end());
1909  binVsRMS.emplace_back(segment, RMSBin);
1910  if (fMakeRMSGradientPlot) graph->SetPoint(graph->GetN(), segment, RMSBin);
1911  }
1912 
1913  // Get the gradient of the RMS-bin plot
1914  double sumx = 0., sumy = 0., sumx2 = 0., sumxy = 0., sumweight = 0.;
1915  for (auto const [bin, RMSBin] : binVsRMS) {
1916  double weight = segmentCharge.at(bin);
1917  sumweight += weight;
1918  sumx += weight * bin;
1919  sumy += weight * RMSBin;
1920  sumx2 += weight * bin * bin;
1921  sumxy += weight * bin * RMSBin;
1922  }
1923  double RMSgradient = (sumweight * sumxy - sumx * sumy) / (sumweight * sumx2 - sumx * sumx);
1924 
1925  if (fMakeRMSGradientPlot) {
1926  TVector2 direction = TVector2(1, RMSgradient).Unit();
1927  TCanvas* canv = new TCanvas();
1928  graph->Draw();
1929  graph->GetXaxis()->SetTitle("Shower segment");
1930  graph->GetYaxis()->SetTitle("RMS of hit distribution");
1931  TVector2 centre = TVector2(graph->GetMean(1), graph->GetMean(2));
1932  TLine line;
1933  line.SetLineColor(2);
1934  line.DrawLine(centre.X() - 1000 * direction.X(),
1935  centre.Y() - 1000 * direction.Y(),
1936  centre.X() + 1000 * direction.X(),
1937  centre.Y() + 1000 * direction.Y());
1938  canv->SaveAs("RMSGradient.png");
1939  delete canv;
1940  }
1941  delete graph;
1942 
1943  return RMSgradient;
1944 }
TVector2 HitPosition_(detinfo::DetectorPropertiesData const &detProp, recob::Hit const &hit) const
Return the coordinates of this hit in units of cm.
constexpr to_element_t to_element
Definition: ToElement.h:24
def graph(desc, maker=maker)
Definition: apa.py:294
weight
Definition: test.py:257
bool const fMakeRMSGradientPlot
Definition: EMShowerAlg.h:285
TVector2 ShowerDirection_(detinfo::DetectorPropertiesData const &detProp, const std::vector< art::Ptr< recob::Hit >> &showerHits) const
Detector simulation of raw signals on wires.
void line(double t, double *p, double &x, double &y, double &z)
int const fNumShowerSegments
Definition: EMShowerAlg.h:286
QTextStream & bin(QTextStream &s)
Int_t shower::EMShowerAlg::WeightedFit ( const Int_t  n,
const Double_t *  x,
const Double_t *  y,
const Double_t *  w,
Double_t *  parm 
) const

<Tingjun to="" document>="">

Definition at line 2018 of file EMShowerAlg.cxx.

2023 {
2024 
2025  Double_t sumx = 0.;
2026  Double_t sumx2 = 0.;
2027  Double_t sumy = 0.;
2028  Double_t sumy2 = 0.;
2029  Double_t sumxy = 0.;
2030  Double_t sumw = 0.;
2031  Double_t eparm[2];
2032 
2033  parm[0] = 0.;
2034  parm[1] = 0.;
2035  eparm[0] = 0.;
2036  eparm[1] = 0.;
2037 
2038  for (Int_t i = 0; i < n; i++) {
2039  sumx += x[i] * w[i];
2040  sumx2 += x[i] * x[i] * w[i];
2041  sumy += y[i] * w[i];
2042  sumy2 += y[i] * y[i] * w[i];
2043  sumxy += x[i] * y[i] * w[i];
2044  sumw += w[i];
2045  }
2046 
2047  if (sumx2 * sumw - sumx * sumx == 0.) return 1;
2048  if (sumx2 - sumx * sumx / sumw == 0.) return 1;
2049 
2050  parm[0] = (sumy * sumx2 - sumx * sumxy) / (sumx2 * sumw - sumx * sumx);
2051  parm[1] = (sumxy - sumx * sumy / sumw) / (sumx2 - sumx * sumx / sumw);
2052 
2053  eparm[0] = sumx2 * (sumx2 * sumw - sumx * sumx);
2054  eparm[1] = (sumx2 - sumx * sumx / sumw);
2055 
2056  if (eparm[0] < 0. || eparm[1] < 0.) return 1;
2057 
2058  eparm[0] = sqrt(eparm[0]) / (sumx2 * sumw - sumx * sumx);
2059  eparm[1] = sqrt(eparm[1]) / (sumx2 - sumx * sumx / sumw);
2060 
2061  return 0;
2062 }
std::void_t< T > n
list x
Definition: train.py:276
int shower::EMShowerAlg::WorstPlane_ ( const std::map< int, std::vector< art::Ptr< recob::Hit >>> &  showerHitsMap) const
private

Returns the plane which is determined to be the least likely to be correct.

Definition at line 1980 of file EMShowerAlg.cxx.

1982 {
1983  // Get the width of the shower in wire coordinate
1984  std::map<int, int> planeWireLength;
1985  std::map<int, double> planeOtherWireLengths;
1986  for (auto const& [plane, hits] : showerHitsMap)
1987  planeWireLength[plane] =
1988  std::abs(HitCoordinates_(*hits.front()).X() - HitCoordinates_(*hits.back()).X());
1989  for (std::map<int, int>::iterator planeWireLengthIt = planeWireLength.begin();
1990  planeWireLengthIt != planeWireLength.end();
1991  ++planeWireLengthIt) {
1992  double quad = 0.;
1993  for (int plane = 0; plane < (int)fGeom->MaxPlanes(); ++plane)
1994  if (plane != planeWireLengthIt->first and planeWireLength.count(plane))
1995  quad += cet::square(planeWireLength[plane]);
1996  quad = std::sqrt(quad);
1997  planeOtherWireLengths[planeWireLengthIt->first] =
1998  planeWireLength[planeWireLengthIt->first] / (double)quad;
1999  }
2000 
2001  if (fDebug > 1)
2002  for (auto const [plane, relative_width] : planeOtherWireLengths) {
2003  std::cout << "Plane " << plane << " has " << planeWireLength[plane]
2004  << " wire width and therefore has relative width in wire of " << relative_width
2005  << '\n';
2006  }
2007 
2008  std::map<double, int> wireWidthMap;
2009  for (int const plane : showerHitsMap | views::keys) {
2010  double wireWidth = planeWireLength.at(plane);
2011  wireWidthMap[wireWidth] = plane;
2012  }
2013 
2014  return wireWidthMap.begin()->second;
2015 }
intermediate_table::iterator iterator
constexpr T square(T x)
Definition: pow.h:21
T abs(T value)
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
TVector2 HitCoordinates_(recob::Hit const &hit) const
Return the coordinates of this hit in global wire/tick space.
art::ServiceHandle< geo::Geometry const > fGeom
Definition: EMShowerAlg.h:274

Member Data Documentation

calo::CalorimetryAlg const shower::EMShowerAlg::fCalorimetryAlg
private

Definition at line 278 of file EMShowerAlg.h.

int shower::EMShowerAlg::fDebug

Definition at line 152 of file EMShowerAlg.h.

double const shower::EMShowerAlg::fdEdxTrackLength
private

Definition at line 265 of file EMShowerAlg.h.

std::string const shower::EMShowerAlg::fDetector
private

Definition at line 281 of file EMShowerAlg.h.

art::ServiceHandle<geo::Geometry const> shower::EMShowerAlg::fGeom
private

Definition at line 274 of file EMShowerAlg.h.

bool const shower::EMShowerAlg::fMakeGradientPlot
private

Definition at line 284 of file EMShowerAlg.h.

bool const shower::EMShowerAlg::fMakeRMSGradientPlot
private

Definition at line 285 of file EMShowerAlg.h.

double const shower::EMShowerAlg::fMinTrackLength
private

Definition at line 264 of file EMShowerAlg.h.

std::vector<unsigned int> const shower::EMShowerAlg::fNfithits
private

Definition at line 270 of file EMShowerAlg.h.

unsigned int const shower::EMShowerAlg::fNfitpass
private

Definition at line 269 of file EMShowerAlg.h.

int const shower::EMShowerAlg::fNumShowerSegments
private

Definition at line 286 of file EMShowerAlg.h.

pma::ProjectionMatchingAlg const shower::EMShowerAlg::fProjectionMatchingAlg
private

Definition at line 279 of file EMShowerAlg.h.

shower::ShowerEnergyAlg const shower::EMShowerAlg::fShowerEnergyAlg
private

Definition at line 277 of file EMShowerAlg.h.

double const shower::EMShowerAlg::fSpacePointSize
private

Definition at line 266 of file EMShowerAlg.h.

std::vector<double> const shower::EMShowerAlg::fToler
private

Definition at line 271 of file EMShowerAlg.h.


The documentation for this class was generated from the following files: