LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DisambigCheater_module.cc
Go to the documentation of this file.
1 // Class: DisambigCheater
3 // Module Type: producer
4 // File: DisambigCheater_module.cc
5 //
6 // tylerdalion@gmail.com
7 //
9 
16 
28 
29 namespace hit {
30 
32  public:
33  explicit DisambigCheater(fhicl::ParameterSet const& p);
34 
35  private:
36  void produce(art::Event& e) override;
37  void endJob() override;
38 
41 
42  std::string fChanHitLabel;
43  std::string fWidHitLabel;
44 
45  std::map<std::pair<double, double>, std::vector<geo::WireID>> fHitToWids;
46  void InitHitToWids(detinfo::DetectorClocksData const& clockData,
47  const std::vector<art::Ptr<recob::Hit>>& ChHits);
48 
50  geo::WireID const& wid,
51  art::Ptr<recob::Wire> const& wire,
53 
54  unsigned int fFalseChanHits =
55  0; // hits with no IDEs - could be noise or other technical problems
56  unsigned int fBadIDENearestWire = 0; // Just to count the inconsistent IDE wire returns
57 
58  std::vector<unsigned int> fMaxWireShift; // shift to account for space charge and diffusion
59  };
60 
61  //-------------------------------------------------------------------
63  {
64  fChanHitLabel = p.get<std::string>("ChanHitLabel");
65 
66  // let HitCollectionCreator declare that we are going to produce
67  // hits and associations with wires and raw digits
68  // (with no particular product label)
70 
71  // Space charge can shift true IDE postiion to far-off channels.
72  // Calculate maximum number of wires to shift hit in order to be on correct channel.
73  // Shift no more than half of the number of channels, as beyond there will
74  // have been a closer wire segment.
75  if (geom->Ncryostats() != 1 || geom->NTPC() < 1) {
76  fMaxWireShift.resize(3);
77  fMaxWireShift[0] = 1;
78  fMaxWireShift[1] = 1;
79  fMaxWireShift[2] = 1;
80  }
81  else {
82  // assume TPC 0 is typical of all in terms of number of channels
83  unsigned int np = geom->TPC().Nplanes();
84  fMaxWireShift.resize(np);
85  for (unsigned int p = 0; p < np; ++p) {
86  auto const& planeGeo = geom->Plane({0, 0, p});
87  unsigned int nw = planeGeo.Nwires();
88  for (unsigned int w = 0; w < nw; ++w) {
89 
90  // for vertical planes
91  if (planeGeo.View() == geo::kZ) {
92  fMaxWireShift[2] = planeGeo.Nwires();
93  break;
94  }
95 
96  auto const xyz = planeGeo.Wire(w).GetCenter();
97  auto const xyz_next = planeGeo.Wire(w + 1).GetCenter();
98 
99  if (xyz.Z() == xyz_next.Z()) {
100  fMaxWireShift[p] = w;
101  break;
102  }
103  } // end wire loop
104  } // end plane loop
105 
106  for (unsigned int i = 0; i < np; i++)
107  fMaxWireShift[i] = std::floor(fMaxWireShift[i] / 2);
108  }
109  }
110 
111  //-------------------------------------------------------------------
113  {
114  // get hits on channels
116  evt.getByLabel(fChanHitLabel, ChanHits);
117  std::vector<art::Ptr<recob::Hit>> ChHits;
118  art::fill_ptr_vector(ChHits, ChanHits);
119 
120  // also get the associated wires and raw digits;
121  // we assume they have been created by the same module as the hits
122  const bool doRawDigitAssns = false;
123 
124  art::FindOneP<recob::Wire> ChannelHitWires(ChanHits, evt, fChanHitLabel);
125  const bool doWireAssns = ChannelHitWires.isValid();
126 
127  // this object contains the hit collection
128  // and its associations to wires and raw digits
129  // (if the original objects have them):
130  recob::HitCollectionCreator hits(evt, doWireAssns, doRawDigitAssns);
131 
132  // find the wireIDs each hit is on
133  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
134  this->InitHitToWids(clockData, ChHits);
135 
136  // make all of the hits
137  for (size_t h = 0; h < ChHits.size(); h++) {
138 
139  // get the objects associated with this hit
141  if (doWireAssns) wire = ChannelHitWires.at(h);
142 
143  // the trivial Z hits
144  if (ChHits[h]->View() == geo::kZ) {
145  this->MakeDisambigHit(ChHits[h], ChHits[h]->WireID(), wire, hits);
146  continue;
147  }
148 
149  // make U/V hits if any wire IDs are associated
150  // count hits without a wireID
152  std::pair<double, double> ChanTime(ChHits[h]->Channel() * 1., ChHits[h]->PeakTime() * 1.);
153  if (fHitToWids[ChanTime].size() == 1)
154  this->MakeDisambigHit(ChHits[h], fHitToWids[ChanTime][0], wire, hits);
155  else if (fHitToWids[ChanTime].size() == 0)
156  fFalseChanHits++;
157  else if (fHitToWids[ChanTime].size() > 1)
158  this->MakeDisambigHit(ChHits[h], fHitToWids[ChanTime][0], wire, hits); // same thing for now
159 
160  } // for
161 
162  // put the hit collection and associations into the event
163  hits.put_into(evt);
164 
165  fHitToWids.clear();
166  }
167 
168  //-------------------------------------------------
170  art::Ptr<recob::Hit> const& original_hit,
171  geo::WireID const& wid,
172  art::Ptr<recob::Wire> const& wire, // art::Ptr<raw::RawDigit> const& rawdigits,
174  {
175 
176  if (!wid.isValid) {
177  mf::LogWarning("InvalidWireID") << "wid is invalid, hit not being made\n";
178  return;
179  }
180 
181  // create a hit copy of the original one, but with a different wire ID
182  recob::HitCreator hit(*original_hit, wid);
183  hcol.emplace_back(hit.move(), wire);
184  }
185 
186  //-------------------------------------------------------------------
188  const std::vector<art::Ptr<recob::Hit>>& ChHits)
189  {
190 
191  unsigned int Ucount(0), Vcount(0);
192  for (size_t h = 0; h < ChHits.size(); h++) {
193  recob::Hit const& chit = *(ChHits[h]);
194  if (ChHits[h]->View() == geo::kZ) continue;
195  if (ChHits[h]->View() == geo::kU)
196  Ucount++;
197  else if (ChHits[h]->View() == geo::kV)
198  Vcount++;
199  std::vector<geo::WireID> cwids = geom->ChannelToWire(chit.Channel());
200  std::pair<double, double> ChanTime((double)chit.Channel(),
201  (double)chit.PeakTime()); // hit key value
202 
203  // get hit IDEs
204  std::vector<const sim::IDE*> ides;
205  try {
206  ides = bt_serv->HitToSimIDEs_Ps(clockData, chit);
207  }
208  catch (...) {
209  };
210 
211  // catch the hits that have no IDEs
212  bool hasIDEs = !ides.empty();
213  if (hasIDEs) {
214  try {
215  bt_serv->SimIDEsToXYZ(ides);
216  } //What is this supposed to be doing? It get a vector, but never assigns it anywhere. There has to be a better way to do this check
217  catch (...) {
218  hasIDEs = false;
219  }
220  } // if
221  if (!hasIDEs) {
222  mf::LogVerbatim("DisambigCheat")
223  << "Hit on channel " << chit.Channel() << " between " << chit.PeakTimeMinusRMS()
224  << " and " << chit.PeakTimePlusRMS() << " matches no IDEs.";
225  fHitToWids[ChanTime] = std::vector<geo::WireID>();
226  continue;
227  } // if no IDEs
228 
229  // see what wire ID(s) the hit-IDEs are on
230  // if none: hit maps to empty vector
231  // if one: we have a unique hit, vector of size 1
232  // if more than one: make a vector of all wids
233  std::vector<geo::WireID> widsWithIdes;
234  for (size_t i = 0; i < ides.size(); i++) {
235  geo::Point_t const xyzIde{ides[i]->x, ides[i]->y, ides[i]->z};
236 
237  // Occasionally, ide position is not in TPC
239  geo::TPCID tpcID = geom->FindTPCAtPosition(xyzIde);
240  if (!tpcID.isValid) {
241  mf::LogWarning("DisambigCheat")
242  << "IDE at x = " << xyzIde.X() << ", y = " << xyzIde.Y() << ", z = " << xyzIde.Z()
243  << " does not correspond to a TPC.";
244  continue;
245  }
246  unsigned int tpc = tpcID.TPC, cryo = tpcID.Cryostat;
247 
248  // NearestWire seems to be missing some correction that is applied in LArG4, and is
249  // sometimes off by one or two wires. Use it and then correct it given channel
251  geo::WireID IdeWid;
252  try {
253  IdeWid = geom->NearestWireID(xyzIde, geo::PlaneID{tpcID, cwids[0].Plane});
254  }
255  catch (geo::InvalidWireError const& e) { // adopt suggestion if possible
256  if (!e.hasSuggestedWire()) throw;
257  IdeWid = e.suggestedWireID();
258  mf::LogError("DisambigCheat") << "Detected a point out of its wire plane:\n"
259  << e.what() << "\nUsing suggested wire " << IdeWid << "\n";
260  }
261  geo::WireID storethis = IdeWid; // default...
262  bool foundmatch(false);
263  for (size_t w = 0; w < cwids.size(); w++) {
264  if (cwids[w].TPC != tpc || cwids[w].Cryostat != cryo) continue;
265  if ((unsigned int)std::abs((int)(IdeWid.Wire) - (int)(cwids[w].Wire)) <=
266  fMaxWireShift[cwids[0].Plane]) {
267  storethis = cwids[w]; // ...apply correction
268  foundmatch = true;
269  break;
270  }
271  }
272  if (!foundmatch) {
273  mf::LogWarning("DisambigCheat")
274  << "IDE NearestWire return more than 1 off from channel wids: wire " << IdeWid.Wire;
276  }
277 
278  bool alreadyStored(false);
279  for (size_t wid = 0; wid < widsWithIdes.size(); wid++)
280  if (storethis == widsWithIdes[wid]) alreadyStored = true;
281  if (!alreadyStored) widsWithIdes.push_back(storethis);
282  } // end loop through ides from HitToSimIdes
283 
284  fHitToWids[ChanTime] = widsWithIdes;
285 
286  } // end U/V channel hit loop
287 
288  if (fHitToWids.size() != Ucount + Vcount) {
289  mf::LogWarning("DisambigCheat")
290  << "Nhits mismatch: " << fHitToWids.size() << " " << Ucount + Vcount;
291  }
292  }
293 
294  //-------------------------------------------------------------------
296  {
297 
298  if (fFalseChanHits > 0)
299  mf::LogWarning("DisambigCheater")
300  << fFalseChanHits << " hits had no associated IDE or WireIDs";
301  }
302 
304 
305 } // end hit namespace
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int NTPC(CryostatID const &cryoid=cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
Definition: GeometryCore.h:686
void produce(art::Event &e) override
std::vector< WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
DisambigCheater(fhicl::ParameterSet const &p)
art::ServiceHandle< cheat::BackTrackerService const > bt_serv
void InitHitToWids(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit >> &ChHits)
Planes which measure V.
Definition: geo_types.h:136
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:137
Declaration of signal hit object.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
std::vector< unsigned int > fMaxWireShift
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:210
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:211
Planes which measure Z direction.
Definition: geo_types.h:138
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:563
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition: GeometryCore.h:430
static void declare_products(art::ProducesCollector &collector, std::string instance_name="", bool doWireAssns=true, bool doRawDigitAssns=true)
Declares the hit products we are going to fill.
Definition: HitCreator.cxx:248
art::ServiceHandle< geo::Geometry const > geom
TPCGeo const & TPC(TPCID const &tpcid=tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:722
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
Class managing the creation of a new recob::Hit object.
Definition: HitCreator.h:87
Planes which measure U.
Definition: geo_types.h:135
Helper functions to create a hit.
PlaneGeo const & Plane(PlaneID const &planeid) const
Returns the specified wire.
Collection of exceptions for Geometry system.
void hits()
Definition: readHits.C:15
TPCID FindTPCAtPosition(Point_t const &point) const
Returns the ID of the TPC at specified location.
A class handling a collection of hits and its associations.
Definition: HitCreator.h:481
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::map< std::pair< double, double >, std::vector< geo::WireID > > fHitToWids
void emplace_back(recob::Hit &&hit, art::Ptr< recob::Wire > const &wire=art::Ptr< recob::Wire >(), art::Ptr< raw::RawDigit > const &digits=art::Ptr< raw::RawDigit >())
Adds the specified hit to the data collection.
Definition: HitCreator.cxx:286
The data type to uniquely identify a TPC.
Definition: geo_types.h:381
Definition of data types for geometry description.
float PeakTimeMinusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:290
void put_into(art::Event &)
Moves the data into an event.
Definition: HitCreator.h:614
Detector simulation of raw signals on wires.
ProducesCollector & producesCollector() noexcept
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:220
WireID NearestWireID(Point_t const &point, PlaneID const &planeid) const
Returns the ID of wire closest to position in the specified TPC.
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:242
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
object containing MC truth information necessary for making RawDigits and doing back tracking ...
std::vector< double > SimIDEsToXYZ(std::vector< sim::IDE > const &ides) const
Exception thrown on invalid wire number.
Definition: Exceptions.h:39
Declaration of basic channel signal object.
std::vector< const sim::IDE * > HitToSimIDEs_Ps(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:285
TCEvent evt
Definition: DataStructs.cxx:8
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:399
void MakeDisambigHit(art::Ptr< recob::Hit > const &hit, geo::WireID const &wid, art::Ptr< recob::Wire > const &wire, recob::HitCollectionCreator &hcol)
Float_t e
Definition: plot.C:35
geo::WireID suggestedWireID() const
Returns a better wire ID.
Definition: Exceptions.h:87
bool hasSuggestedWire() const
Returns whether we known a better wire number.
Definition: Exceptions.h:81
Float_t w
Definition: plot.C:20
recob::Hit && move()
Prepares the constructed hit to be moved away.
Definition: HitCreator.h:330
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:268
art framework interface to geometry description
Encapsulate the construction of a single detector plane.