LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
SpacePointSolver_module.cc
Go to the documentation of this file.
1 // Christopher Backhouse - bckhouse@fnal.gov
2 
3 // Test file at Caltech: /nfs/raid11/dunesam/prodgenie_nu_dune10kt_1x2x6_mcc7.0/prodgenie_nu_dune10kt_1x2x6_63_20160811T171439_merged.root
4 
5 // C/C++ standard libraries
6 #include <string>
7 #include <vector>
8 #include <iostream>
9 
10 // framework libraries
11 #include "fhiclcpp/ParameterSet.h"
19 
20 // LArSoft libraries
21 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
23 
27 
33 
34 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
35 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
36 
38 
39 #include "TGraph.h"
40 #include "TH1.h"
41 #include "TPad.h"
42 
43 #include "Solver.h"
44 #include "TripletFinder.h"
45 
46 template<class T> T sqr(T x){return x*x;}
47 
48 namespace reco3d
49 {
50 
54 {
56 
57  bool operator<(const InductionWireWithXPos& w) const {return xpos < w.xpos;}
58 
60  double xpos;
61 };
62 
64 {
65 public:
66 
67  explicit SpacePointSolver(const fhicl::ParameterSet& pset);
68  virtual ~SpacePointSolver();
69 
70  void produce(art::Event& evt);
71  void beginJob();
72  void endJob();
73 
74 protected:
75  void AddNeighbours(const std::vector<SpaceCharge*>& spaceCharges) const;
76 
77  typedef std::map<const WireHit*, const recob::Hit*> HitMap_t;
78 
79  void BuildSystem(const std::vector<HitTriplet>& triplets,
80  std::vector<CollectionWireHit*>& cwires,
81  std::vector<InductionWireHit*>& iwires,
82  std::vector<SpaceCharge*>& orphanSCs,
83  bool incNei,
84  HitMap_t& hitmap) const;
85 
86  void Minimize(const std::vector<CollectionWireHit*>& cwires,
87  const std::vector<SpaceCharge*>& orphanSCs,
88  double alpha,
89  int maxiterations);
90 
92  bool AddSpacePoint(const SpaceCharge& sc,
93  int id,
95 
96  void FillSystemToSpacePoints(const std::vector<CollectionWireHit*>& cwires,
97  const std::vector<SpaceCharge*>& orphanSCs,
99 
100  void FillSystemToSpacePointsAndAssns(const std::vector<art::Ptr<recob::Hit>>& hitlist,
101  const std::vector<CollectionWireHit*>& cwires,
102  const std::vector<SpaceCharge*>& orphanSCs,
103  const HitMap_t& hitmap,
106 
107  std::string fHitLabel;
108 
109  bool fFit;
110  bool fAllowBadInductionHit, fAllowBadCollectionHit;
111 
112  double fAlpha;
113 
114  double fDistThresh;
116 
119 
120  double fXHitOffset;
121 
124 };
125 
127 
128 // ---------------------------------------------------------------------------
129 SpacePointSolver::SpacePointSolver(const fhicl::ParameterSet& pset)
130  : fHitLabel(pset.get<std::string>("HitLabel")),
131  fFit(pset.get<bool>("Fit")),
132  fAllowBadInductionHit(pset.get<bool>("AllowBadInductionHit")),
133  fAllowBadCollectionHit(pset.get<bool>("AllowBadCollectionHit")),
134  fAlpha(pset.get<double>("Alpha")),
135  fDistThresh(pset.get<double>("WireIntersectThreshold")),
136  fDistThreshDrift(pset.get<double>("WireIntersectThresholdDriftDir")),
137  fMaxIterationsNoReg(pset.get<int>("MaxIterationsNoReg")),
138  fMaxIterationsReg(pset.get<int>("MaxIterationsReg")),
139  fXHitOffset(pset.get<double>("XHitOffset"))
140 {
142  if(fFit){
144  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
146  }
147 }
148 
149 // ---------------------------------------------------------------------------
151 {
152 }
153 
154 // ---------------------------------------------------------------------------
156 {
158  geom = art::ServiceHandle<geo::Geometry>()->provider();
159 }
160 
161 // ---------------------------------------------------------------------------
163 {
164 }
165 
166 // ---------------------------------------------------------------------------
168 AddNeighbours(const std::vector<SpaceCharge*>& spaceCharges) const
169 {
170  static const double kCritDist = 5;
171 
172  // Could use a QuadTree or VPTree etc, but seems like overkill
173  class IntCoord
174  {
175  public:
176  IntCoord(const SpaceCharge& sc)
177  : fX(sc.fX/kCritDist),
178  fY(sc.fY/kCritDist),
179  fZ(sc.fZ/kCritDist)
180  {
181  }
182 
183  bool operator<(const IntCoord& i) const
184  {
185  return std::make_tuple(fX, fY, fZ) < std::make_tuple(i.fX, i.fY, i.fZ);
186  }
187 
188  std::vector<IntCoord> Neighbours() const
189  {
190  std::vector<IntCoord> ret;
191  for(int dx = -1; dx <= +1; ++dx){
192  for(int dy = -1; dy <= +1; ++dy){
193  for(int dz = -1; dz <= +1; ++dz){
194  ret.push_back(IntCoord(fX+dx, fY+dy, fZ+dz));
195  }
196  }
197  }
198  return ret;
199  }
200  protected:
201  IntCoord(int x, int y, int z) : fX(x), fY(y), fZ(z) {}
202 
203  int fX, fY, fZ;
204  };
205 
206  std::map<IntCoord, std::vector<SpaceCharge*>> scMap;
207  for(SpaceCharge* sc: spaceCharges){
208  scMap[IntCoord(*sc)].push_back(sc);
209  }
210 
211  std::cout << "Neighbour search..." << std::endl;
212 
213  // Now that we know all the space charges, can go through and assign neighbours
214 
215  int Ntests = 0;
216  int Nnei = 0;
217  for(SpaceCharge* sc1: spaceCharges){
218  IntCoord ic(*sc1);
219  for(IntCoord icn: ic.Neighbours()){
220  for(SpaceCharge* sc2: scMap[icn]){
221 
222  ++Ntests;
223 
224  if(sc1 == sc2) continue;
225  /*const*/ double dist2 = sqr(sc1->fX-sc2->fX) + sqr(sc1->fY-sc2->fY) + sqr(sc1->fZ-sc2->fZ);
226 
227  if(dist2 > sqr(kCritDist)) continue;
228 
229  if(dist2 == 0){
230  std::cout << "ZERO DISTANCE SOMEHOW?" << std::endl;
231  std::cout << sc1->fCWire << " " << sc1->fWire1 << " " << sc1->fWire2 << std::endl;
232  std::cout << sc2->fCWire << " " << sc2->fWire1 << " " << sc2->fWire2 << std::endl;
233  std::cout << dist2 << " " << sc1->fX << " " << sc2->fX << " " << sc1->fY << " " << sc2->fY << " " << sc1->fZ << " " << sc2->fZ << std::endl;
234  continue;
235  dist2 = sqr(kCritDist);
236  }
237 
238  ++Nnei;
239 
240  // This is a pretty random guess
241  const double coupling = exp(-sqrt(dist2)/2);
242  sc1->fNeighbours.emplace_back(sc2, coupling);
243 
244  if(isnan(1/sqrt(dist2)) || isinf(1/sqrt(dist2))){
245  std::cout << dist2 << " " << sc1->fX << " " << sc2->fX << " " << sc1->fY << " " << sc2->fY << " " << sc1->fZ << " " << sc2->fZ << std::endl;
246  abort();
247  }
248  } // end for sc2
249  } // end for icn
250 
251  // The neighbours lists use the most memory, so be careful to trim
252  sc1->fNeighbours.shrink_to_fit();
253  } // end for sc1
254 
255  for(SpaceCharge* sc: spaceCharges){
256  for(Neighbour& nei: sc->fNeighbours){
257  sc->fNeiPotential += nei.fCoupling * nei.fSC->fPred;
258  }
259  }
260 
261  std::cout << Ntests << " tests to find " << Nnei << " neighbours" << std::endl;
262 }
263 
264 // ---------------------------------------------------------------------------
266 BuildSystem(const std::vector<HitTriplet>& triplets,
267  std::vector<CollectionWireHit*>& cwires,
268  std::vector<InductionWireHit*>& iwires,
269  std::vector<SpaceCharge*>& orphanSCs,
270  bool incNei,
271  HitMap_t& hitmap) const
272 {
273  std::set<const recob::Hit*> ihits;
274  std::set<const recob::Hit*> chits;
275  for(const HitTriplet& trip: triplets){
276  if(trip.x) chits.insert(trip.x);
277  if(trip.u) ihits.insert(trip.u);
278  if(trip.v) ihits.insert(trip.v);
279  }
280 
281  std::map<const recob::Hit*, InductionWireHit*> inductionMap;
282  for(const recob::Hit* hit: ihits){
283  InductionWireHit* iwire = new InductionWireHit(hit->Channel(),
284  hit->Integral());
285  inductionMap[hit] = iwire;
286  iwires.emplace_back(iwire);
287  hitmap[iwire] = hit;
288  }
289 
290  std::map<const recob::Hit*, std::vector<SpaceCharge*>> collectionMap;
291  std::map<const recob::Hit*, std::vector<SpaceCharge*>> collectionMapBad;
292 
293  std::set<InductionWireHit*> satisfiedInduction;
294 
295  for(const HitTriplet& trip: triplets){
296  // Don't have a cwire object yet, set it later
297  SpaceCharge* sc = new SpaceCharge(trip.pt.x,
298  trip.pt.y,
299  trip.pt.z,
300  0,
301  inductionMap[trip.u],
302  inductionMap[trip.v]);
303 
304  if(trip.u && trip.v){
305  collectionMap[trip.x].push_back(sc);
306  if(trip.x){
307  satisfiedInduction.insert(inductionMap[trip.u]);
308  satisfiedInduction.insert(inductionMap[trip.v]);
309  }
310  }
311  else{
312  collectionMapBad[trip.x].push_back(sc);
313  }
314  }
315 
316  std::vector<SpaceCharge*> spaceCharges;
317 
318  for(const recob::Hit* hit: chits){
319  // Find the space charges associated with this hit
320  std::vector<SpaceCharge*>& scs = collectionMap[hit];
321  if(scs.empty()){
322  // If there are no full triplets try the triplets with one bad channel
323  scs = collectionMapBad[hit];
324  }
325  else{
326  // If there were good triplets, delete the bad hit ones
327  for(SpaceCharge* sc: collectionMapBad[hit]) delete sc;
328  }
329  // Still no space points, don't bother making a wire
330  if(scs.empty()) continue;
331 
332  CollectionWireHit* cwire = new CollectionWireHit(hit->Channel(),
333  hit->Integral(),
334  scs);
335  hitmap[cwire] = hit;
336  cwires.push_back(cwire);
337  spaceCharges.insert(spaceCharges.end(), scs.begin(), scs.end());
338  for(SpaceCharge* sc: scs) sc->fCWire = cwire;
339  } // end for hit
340 
341  // Space charges whose collection wire is bad, which we have no other way of
342  // addressing.
343  for(SpaceCharge* sc: collectionMap[0]){
344  // Only count orphans where an induction wire has no other explanation
345  if(satisfiedInduction.count(sc->fWire1) == 0 ||
346  satisfiedInduction.count(sc->fWire2) == 0){
347  orphanSCs.push_back(sc);
348  }
349  }
350  spaceCharges.insert(spaceCharges.end(), orphanSCs.begin(), orphanSCs.end());
351 
352  std::cout << cwires.size() << " collection wire objects" << std::endl;
353  std::cout << spaceCharges.size() << " potential space points" << std::endl;
354 
355  if(incNei) AddNeighbours(spaceCharges);
356 }
357 
358 // ---------------------------------------------------------------------------
361  int id,
363 {
364  static const double err[6] = {0,};
365 
366  const float charge = sc.fPred;
367  if(charge == 0) return false;
368 
369  const double xyz[3] = {sc.fX, sc.fY, sc.fZ};
370  points.add({ xyz, err, 0.0, id }, charge);
371 
372  return true;
373 }
374 
375 // ---------------------------------------------------------------------------
377 FillSystemToSpacePoints(const std::vector<CollectionWireHit*>& cwires,
378  const std::vector<SpaceCharge*>& orphanSCs,
380 {
381  int iPoint = 0;
382  for(const CollectionWireHit* cwire: cwires){
383  for(const SpaceCharge* sc: cwire->fCrossings){
384  AddSpacePoint(*sc, iPoint++, points);
385  } // for sc
386  } // for cwire
387 
388  for(const SpaceCharge* sc: orphanSCs) AddSpacePoint(*sc, iPoint++, points);
389 }
390 
391 
392 // ---------------------------------------------------------------------------
395  const std::vector<CollectionWireHit*>& cwires,
396  const std::vector<SpaceCharge*>& orphanSCs,
397  const HitMap_t& hitmap,
400 {
401  std::map<const recob::Hit*, art::Ptr<recob::Hit>> ptrmap;
402  for(art::Ptr<recob::Hit> hit: hitlist) ptrmap[hit.get()] = hit;
403 
404  std::vector<const SpaceCharge*> scs;
405  for(const SpaceCharge* sc: orphanSCs) scs.push_back(sc);
406  for(const CollectionWireHit* cwire: cwires)
407  for(const SpaceCharge* sc: cwire->fCrossings)
408  scs.push_back(sc);
409 
410  int iPoint = 0;
411 
412  for(const SpaceCharge* sc: scs){
413  if(!AddSpacePoint(*sc, iPoint++, points)) continue;
414  const auto& spsPtr = points.lastSpacePointPtr();
415 
416  if(sc->fCWire){
417  assn.addSingle(spsPtr, ptrmap[hitmap.at(sc->fCWire)]);
418  }
419  if(sc->fWire1){
420  assn.addSingle(spsPtr, ptrmap[hitmap.at(sc->fWire1)]);
421  }
422  if(sc->fWire2){
423  assn.addSingle(spsPtr, ptrmap[hitmap.at(sc->fWire2)]);
424  }
425  }
426 }
427 
428 // ---------------------------------------------------------------------------
429 void SpacePointSolver::Minimize(const std::vector<CollectionWireHit*>& cwires,
430  const std::vector<SpaceCharge*>& orphanSCs,
431  double alpha,
432  int maxiterations)
433 {
434  double prevMetric = Metric(cwires, alpha);
435  std::cout << "Begin: " << prevMetric << std::endl;
436  for(int i = 0; i < maxiterations; ++i){
437  Iterate(cwires, orphanSCs, alpha);
438  const double metric = Metric(cwires, alpha);
439  std::cout << i << " " << metric << std::endl;
440  if(metric > prevMetric){
441  std::cout << "Warning: metric increased" << std::endl;
442  return;
443  }
444  if(fabs(metric-prevMetric) < 1e-3*fabs(prevMetric)) return;
445  prevMetric = metric;
446  }
447 }
448 
449 // ---------------------------------------------------------------------------
451 {
453  std::vector<art::Ptr<recob::Hit> > hitlist;
454  if(evt.getByLabel(fHitLabel, hits))
455  art::fill_ptr_vector(hitlist, hits);
456 
457  recob::ChargedSpacePointCollectionCreator spcol_pre(evt, *this, "pre");
458  recob::ChargedSpacePointCollectionCreator spcol_noreg(evt, *this, "noreg");
460  auto assns = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
461 
462  // Skip very small events
463  if(hits->size() < 20){
464  spcol_pre.put();
465  if(fFit){
466  spcol.put();
467  evt.put(std::move(assns));
468  spcol_noreg.put();
469  }
470  return;
471  }
472 
474 
475  bool is2view = false;
476  std::vector<art::Ptr<recob::Hit>> xhits, uhits, vhits;
477  for(auto& hit: hitlist){
478  if(hit->Integral() < 0 || isnan(hit->Integral()) || isinf(hit->Integral())){
479  std::cout << "WARNING: bad recob::Hit::Integral() = "
480  << hit->Integral()
481  << ". Skipping." << std::endl;
482  continue;
483  }
484 
485  if(hit->SignalType() == geo::kCollection){
486  // For DualPhase, both view are collection. Arbitrarily map V to the main
487  // "X" view. For Argoneut and Lariat, collection=V is also the right
488  // convention.
489  if(hit->View() == geo::kZ){
490  xhits.push_back(hit);
491  }
492  if(hit->View() == geo::kV){
493  xhits.push_back(hit);
494  is2view = true;
495  }
496  if(hit->View() == geo::kU || hit->View() == geo::kY){
497  uhits.push_back(hit);
498  is2view = true;
499  }
500  }
501  else{
502  if(hit->View() == geo::kU) uhits.push_back(hit);
503  if(hit->View() == geo::kV) vhits.push_back(hit);
504  }
505  } // end for hit
506 
507  std::vector<raw::ChannelID_t> xbadchans, ubadchans, vbadchans;
508  if(fAllowBadInductionHit || fAllowBadCollectionHit){
509  for(raw::ChannelID_t cid: art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider().BadChannels()){
510  if(geom->SignalType(cid) == geo::kCollection){
511  if(fAllowBadCollectionHit && geom->View(cid) == geo::kZ){
512  xbadchans.push_back(cid);
513  }
514  }
515  else{
516  if(fAllowBadInductionHit){
517  if(geom->View(cid) == geo::kU) ubadchans.push_back(cid);
518  if(geom->View(cid) == geo::kV) vbadchans.push_back(cid);
519  }
520  }
521  }
522  }
523  std::cout << xbadchans.size() << " X, "
524  << ubadchans.size() << " U, "
525  << vbadchans.size() << " V bad channels" << std::endl;
526 
527 
528  std::vector<CollectionWireHit*> cwires;
529  // So we can find them all to free the memory
530  std::vector<InductionWireHit*> iwires;
531  // Nodes with a bad collection wire that we otherwise can't address
532  std::vector<SpaceCharge*> orphanSCs;
533 
534  HitMap_t hitmap;
535  if(is2view){
536  std::cout << "Finding 2-view coincidences..." << std::endl;
537  TripletFinder tf(xhits, uhits, {},
538  xbadchans, ubadchans, {},
539  fDistThresh, fDistThreshDrift, fXHitOffset);
540  BuildSystem(tf.TripletsTwoView(),
541  cwires, iwires, orphanSCs,
542  fAlpha != 0, hitmap);
543  }
544  else{
545  std::cout << "Finding XUV coincidences..." << std::endl;
546  TripletFinder tf(xhits, uhits, vhits,
547  xbadchans, ubadchans, vbadchans,
548  fDistThresh, fDistThreshDrift, fXHitOffset);
549  BuildSystem(tf.Triplets(),
550  cwires, iwires, orphanSCs,
551  fAlpha != 0, hitmap);
552  }
553 
554  FillSystemToSpacePoints(cwires, orphanSCs, spcol_pre);
555  spcol_pre.put();
556 
557  if(fFit){
558  std::cout << "Iterating with no regularization..." << std::endl;
559  Minimize(cwires, orphanSCs, 0, fMaxIterationsNoReg);
560 
561  FillSystemToSpacePoints(cwires, orphanSCs, spcol_noreg);
562  spcol_noreg.put();
563 
564  std::cout << "Now with regularization..." << std::endl;
565  Minimize(cwires, orphanSCs, fAlpha, fMaxIterationsReg);
566 
567  FillSystemToSpacePointsAndAssns(hitlist, cwires, orphanSCs, hitmap, spcol, *assns);
568  spcol.put();
569  evt.put(std::move(assns));
570  } // end if fFit
571 
572  for(InductionWireHit* i: iwires) delete i;
573  for(CollectionWireHit* c: cwires) delete c;
574  for(SpaceCharge* s: orphanSCs) delete s;
575 }
576 
577 } // end namespace reco3d
Float_t x
Definition: compare.C:6
Float_t s
Definition: plot.C:23
const geo::GeometryCore * geom
Planes which measure V.
Definition: geo_types.h:77
art::Ptr< recob::SpacePoint > lastSpacePointPtr() const
Returns an art pointer to the last inserted space point (no check!).
Declaration of signal hit object.
Float_t y
Definition: compare.C:6
void Minimize(const std::vector< CollectionWireHit * > &cwires, const std::vector< SpaceCharge * > &orphanSCs, double alpha, int maxiterations)
Double_t z
Definition: plot.C:279
const detinfo::DetectorProperties * detprop
double fCoupling
Definition: Solver.h:37
void AddNeighbours(const std::vector< SpaceCharge * > &spaceCharges) const
STL namespace.
Planes which measure Z direction.
Definition: geo_types.h:79
Information about charge reconstructed in the active volume.
InductionWireWithXPos(InductionWireHit *w, double x)
h2bis Fit("gaus")
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
Definition: tf_graph.h:23
Planes which measure Y direction.
Definition: geo_types.h:80
static void produces(art::ProducerBase &producer, std::string const &instanceName={})
Declares the data products being produced.
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Planes which measure U.
Definition: geo_types.h:76
double fZ
Definition: Solver.h:52
void hits()
Definition: readHits.C:15
std::map< const WireHit *, const recob::Hit * > HitMap_t
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
void beginJob()
Definition: Breakpoints.cc:14
void Iterate(CollectionWireHit *cwire, double alpha)
Definition: Solver.cxx:263
InductionWireHit * fWire2
Definition: Solver.h:54
T sqr(T x)
double fY
Definition: Solver.h:52
parameter set interface
bool AddSpacePoint(const SpaceCharge &sc, int id, recob::ChargedSpacePointCollectionCreator &points) const
return whether the point was inserted (only happens when it has charge)
InductionWireHit * fWire1
Definition: Solver.h:54
void FillSystemToSpacePointsAndAssns(const std::vector< art::Ptr< recob::Hit >> &hitlist, const std::vector< CollectionWireHit * > &cwires, const std::vector< SpaceCharge * > &orphanSCs, const HitMap_t &hitmap, recob::ChargedSpacePointCollectionCreator &points, art::Assns< recob::SpacePoint, recob::Hit > &assn) const
double fX
Definition: Solver.h:52
double Metric(double q, double p)
Definition: Solver.cxx:71
bool operator<(const InductionWireWithXPos &w) const
Description of geometry of one entire detector.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
Detector simulation of raw signals on wires.
void BuildSystem(const std::vector< HitTriplet > &triplets, std::vector< CollectionWireHit * > &cwires, std::vector< InductionWireHit * > &iwires, std::vector< SpaceCharge * > &orphanSCs, bool incNei, HitMap_t &hitmap) const
Creates a collection of space points with associated charge.
Utility object to perform functions of association.
CollectionWireHit * fCWire
Definition: Solver.h:53
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
void addSingle(Ptr< left_t > const &left, Ptr< right_t > const &right, data_t const &data)
Definition: Assns.h:489
std::vector< HitTriplet > Triplets()
void FillSystemToSpacePoints(const std::vector< CollectionWireHit * > &cwires, const std::vector< SpaceCharge * > &orphanSCs, recob::ChargedSpacePointCollectionCreator &pts) const
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Declaration of basic channel signal object.
Helpers to create space points with associated charge.
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:49
void put()
Puts all data products into the event, leaving the creator empty().
TCEvent evt
Definition: DataStructs.cxx:5
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
Float_t e
Definition: plot.C:34
double fPred
Definition: Solver.h:58
Float_t w
Definition: plot.C:23
void add(recob::SpacePoint const &spacePoint, recob::PointCharge const &charge)
Inserts the specified space point and associated data into the collection.
art framework interface to geometry description
Signal from collection planes.
Definition: geo_types.h:93
SpaceCharge * fSC
Definition: Solver.h:36