DuneApaChannelMapAlg.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file DuneApaChannelMapAlg.cxx
3 /// \brief Interface to algorithm class for a specific detector channel mapping
4 ///
5 /// \version $Id: $
6 /// \author tylerdalion@gmail.com
7 ////////////////////////////////////////////////////////////////////////
8 
18 
19 using std::string;
20 using std::vector;
21 using std::find;
22 using raw::ChannelID_t;
24 using geo::PlaneID;
25 using geo::WireID;
26 using geo::View_t;
27 using geo::CryostatGeo;
28 using geo::TPCID;
29 using geo::PlaneGeo;
30 using readout::TPCsetID;
31 using readout::ROPID;
32 using geo::SigType_t;
33 
34 typedef unsigned int Index;
35 Index badIndex = 999999;
36 
37 #include <iostream>
38 using std::cout;
39 using std::endl;
40 //----------------------------------------------------------------------------
41 
42 DuneApaChannelMapAlg::
43 DuneApaChannelMapAlg(const fhicl::ParameterSet& p)
44 : fSorter(nullptr) {
45  fChannelsPerOpDet = p.get<unsigned int>("ChannelsPerOpDet");
46  fOpDetFlag = 0;
47  // If DetectorVersion is present, then check if this is 35t.
48  string sdet;
49  p.get_if_present<string>("DetectorVersion", sdet);
50  if ( sdet.substr(0,7) == "dune35t" ) fOpDetFlag = 1;
51 }
52 
53 //----------------------------------------------------------------------------
54 
56  fSorter = &sort;
57 }
58 
59 //----------------------------------------------------------------------------
60 
62  Uninitialize();
63 
64  vector<CryostatGeo> const& crygeos = geodata.cryostats;
65  Index ncry = crygeos.size();
66  fNcryostat = ncry;
67  if ( ncry == 0 ) {
68  mf::LogError("DuneApaChannelMapAlg") << "No cryostats found.";
69  return;
70  }
71  CryostatGeo const& crygeo = crygeos[0];
72 
73  mf::LogInfo("DuneApaChannelMapAlg") << "Initializing channel map...";
74  fNTpc.resize(ncry);
75  fNApa.resize(ncry);
76  // The first channel array for each APA plane allow the cryostats to differ.
77  fPlanesPerTpc.resize(ncry);
78  fWiresPerPlane.resize(ncry);
79  fApaTpcs.resize(ncry);
80  fFirstChannelInThisPlane.resize(ncry);
81  fFirstChannelInNextPlane.resize(ncry);
82  fAnchoredPlaneRop.resize(ncry);
83  fPlaneApa.resize(ncry);
84  fPlaneRop.resize(ncry);
85  fPlaneRopIndex.resize(ncry);
86  fAnchoredWires.resize(ncry);
87  fFirstChannelInThisRop.resize(ncry);
88  fFirstChannelInNextRop.resize(ncry);
89  fRopsPerApa.resize(ncry);
90  fChannelsPerApa.resize(ncry);
91  fChannelsPerRop.resize(ncry);
92  fPlanesPerRop.resize(ncry);
93  fRopTpc.resize(ncry);
94  fRopPlane.resize(ncry);
95  fNTpcMax = 0;
96  fNApaMax = 0;
97  fNRopMax = 0;
98  for ( Index icry=0; icry<ncry; ++icry ) {
99  Index ntpc = crygeos[icry].NTPC();
100  Index napa = ntpc/2; // Assume 1 APA for every two TPCs
101  fNTpc[icry] = ntpc;
102  fNApa[icry] = napa;
103  if ( ntpc > fNTpcMax ) fNTpcMax = ntpc;
104  if ( napa > fNApaMax ) fNApaMax = napa;
105  fPlanesPerTpc[icry].resize(ntpc);
106  fWiresPerPlane[icry].resize(ntpc);
107  fFirstChannelInThisPlane[icry].resize(ntpc);
108  fFirstChannelInNextPlane[icry].resize(ntpc);
109  fAnchoredPlaneRop[icry].resize(ntpc);
110  fPlaneApa[icry].resize(ntpc);
111  fPlaneRop[icry].resize(ntpc);
112  fPlaneRopIndex[icry].resize(ntpc);
113  fAnchoredWires[icry].resize(ntpc);
114  fRopsPerApa[icry].resize(napa, 4);
115  fChannelsPerApa[icry].resize(napa, 0);
116  fApaTpcs[icry].resize(napa);
117  fChannelsPerRop[icry].resize(napa);
118  fPlanesPerRop[icry].resize(napa);
119  fFirstChannelInThisRop[icry].resize(napa);
120  fFirstChannelInNextRop[icry].resize(napa);
121  fRopTpc[icry].resize(napa);
122  fRopPlane[icry].resize(napa);
123  for ( Index itpc=0; itpc<ntpc; ++itpc ) {
124  Index npla = crygeo.TPC(itpc).Nplanes();
125  if ( npla != 3 ) {
126  mf::LogError("DuneApaChannelMapAlg")
127  << "# planes/TPC is " << npla << " rather than 3 " << " for TPC " << itpc;
128  return;
129  }
130  fPlaneApa[icry][itpc].resize(npla, badIndex);
131  fPlaneRop[icry][itpc].resize(npla, badIndex);
132  fPlaneRopIndex[icry][itpc].resize(npla, badIndex);
133  fFirstChannelInThisPlane[icry][itpc].resize(npla, 0);
134  fFirstChannelInNextPlane[icry][itpc].resize(npla, 0);
135  fAnchoredPlaneRop[icry][itpc].resize(npla, 0);
136  fAnchoredWires[icry][itpc].resize(npla, 0);
137  fWiresPerPlane[icry][itpc].resize(npla, 0);
138  fPlanesPerTpc[icry][itpc] = npla;
139  for ( Index ipla=0; ipla<npla; ++ipla ) {
140  Index nwir = crygeo.TPC(itpc).Plane(ipla).Nwires();
141  fWiresPerPlane[icry][itpc][ipla] = nwir;
142  }
143  }
144  Index itpc = 0;
145  for ( Index iapa=0; iapa<napa; ++iapa ) {
146  Index nrop = fRopsPerApa[icry][iapa];
147  if ( nrop > fNRopMax ) fNRopMax = nrop;
148  fApaTpcs[icry][iapa].push_back(itpc);
149  fApaTpcs[icry][iapa].push_back(itpc+1);
150  fChannelsPerRop[icry][iapa].resize(nrop);
151  fFirstChannelInThisRop[icry][iapa].resize(nrop, 0);
152  fFirstChannelInNextRop[icry][iapa].resize(nrop, 0);
153  fPlanesPerRop[icry][iapa].resize(nrop, 0);
154  fRopTpc[icry][iapa].resize(nrop);
155  fRopPlane[icry][iapa].resize(nrop);
156  Index ipla = 0;
157  // Induction planes
158  for ( Index irop=0; irop<2; ++irop ) {
159  fPlanesPerRop[icry][iapa][irop] = 2;
160  fRopTpc[icry][iapa][irop].push_back(itpc);
161  fRopTpc[icry][iapa][irop].push_back(itpc+1);
162  fRopPlane[icry][iapa][irop].push_back(ipla);
163  fRopPlane[icry][iapa][irop].push_back(ipla);
164  ++ipla;
165  }
166  // Collection planes.
167  for ( Index irop=2; irop<4; ++irop ) {
168  fPlanesPerRop[icry][iapa][irop] = 1;
169  fRopTpc[icry][iapa][irop].push_back(itpc);
170  fRopPlane[icry][iapa][irop].push_back(ipla);
171  ++itpc;
172  }
173  }
174  }
175  fPlaneIDs.clear();
176  fTopChannel = 0;
177 
178  // Map planes to ROPs and wires to channels.
179  // We use the geometry to deduce the numbers of channels/plane.
180  // For induction planes, we look for the first adjacent pair of wires
181  // with the same center z-position and assume the index of the first
182  // of those gives the count of wires read out from one side.
183  // These are called anchored wires.
184  ChannelID_t icha = 0;
185  for ( Index icry=0; icry!=ncry; ++icry ) {
186  Index napa = fNApa[icry];
187  for ( Index iapa=0; iapa!=napa; ++iapa ) {
188  Index nrop = fRopsPerApa[icry][iapa];
189  for ( Index irop=0; irop!=nrop; ++irop ) {
190  Index nrpl = fPlanesPerRop[icry][iapa][irop];
191  fFirstChannelInThisRop[icry][iapa][irop] = icha;
192  for ( Index irpl=0; irpl!=nrpl; ++irpl ) {
193  Index itpc = fRopTpc[icry][iapa][irop][irpl];
194  Index ipla = fRopPlane[icry][iapa][irop][irpl];
195  fPlaneApa[icry][itpc][ipla] = iapa;
196  fPlaneRop[icry][itpc][ipla] = irop;
197  fPlaneRopIndex[icry][itpc][ipla] = irpl;
198  const PlaneGeo& plageo = crygeos[icry].TPC(itpc).Plane(ipla);
199 #if 0
200 const PlaneGeo plageo2 = plageo;
201 #endif
202  View_t view = plageo.View();
203  const Vector<View_t> eview = {geo::kU, geo::kV, geo::kZ};
204  if ( view != eview[ipla] ) {
205  throw cet::exception("DuneApaChannelMapAlg") << __func__
206  << ": View " << view << " is not the expected " << eview[ipla];
207  }
208  double xyz[3] = {0.};
209  double xyz_next[3] = {0.};
210  Index nAnchoredWires = 0; // # wires from this TPC plane contributing to the ROP
211  // Collection plane.
212  Index nwir = fWiresPerPlane[icry][itpc][ipla];
213  if ( view == geo::kZ ) {
214  nAnchoredWires = nwir;
215  // Induction planes.
216  } else {
217  for ( unsigned int iwir=0; iwir+1<nwir; ++iwir ) {
218  plageo.Wire(iwir).GetCenter(xyz);
219  plageo.Wire(iwir+1).GetCenter(xyz_next);
220  if ( xyz[2] == xyz_next[2] ) {
221  nAnchoredWires = iwir;
222  break;
223  }
224  }
225  }
226  fAnchoredWires[icry][itpc][ipla] = nAnchoredWires;
227  fFirstChannelInThisPlane[icry][itpc][ipla] = icha;
228  icha += nAnchoredWires;
229  fFirstChannelInNextPlane[icry][itpc][ipla] = icha;
230  fAnchoredPlaneRop[icry][itpc][ipla] = irop;
231  }
232  fFirstChannelInNextRop[icry][iapa][irop] = icha;
233  }
234  }
235  }
236  fNchannels = icha;
238 
239  // Assign first channels for the TPCs.
240  fPlaneData.resize(ncry);
241  for ( Index icry=0; icry<ncry; ++icry ) {
242  Index ntpc = fNTpc[icry];
243  fPlaneData[icry].resize(ntpc);
244  for ( Index itpc=0; itpc<ntpc; ++itpc ) {
245  fPlaneData[icry][itpc].resize(crygeos[icry].TPC(itpc).Nplanes());
246  for ( Index ipla=0; ipla<crygeos[icry].TPC(itpc).Nplanes(); ++ipla ) {
247  PlaneData_t& PlaneData = fPlaneData[icry][itpc][ipla];
248  const PlaneGeo& thePlane = crygeos[icry].TPC(itpc).Plane(ipla);
249  double xyz[3];
250  fPlaneIDs.emplace(icry, itpc, ipla);
251  thePlane.Wire(0).GetCenter(xyz);
252  PlaneData.fFirstWireCenterY = xyz[1];
253  PlaneData.fFirstWireCenterZ = xyz[2];
254  // we are interested in the ordering of wire numbers: we find that a
255  // point is N wires left of a wire W: is that wire W + N or W - N?
256  // In fact, for TPC #0 it is W + N for V and Z planes, W - N for U
257  // plane; for TPC #0 it is W + N for V and Z planes, W - N for U
258  PlaneData.fWireSortingInZ = thePlane.WireIDincreasesWithZ()? +1.: -1.;
259 
260  // find boundaries of the outside APAs for this plane by looking at endpoints of wires
261 
262  double endpoint[3];
263  thePlane.Wire(0).GetStart(endpoint);
264  PlaneData.fYmax = endpoint[1];
265  PlaneData.fYmin = endpoint[1];
266  PlaneData.fZmax = endpoint[2];
267  PlaneData.fZmin = endpoint[2];
268  unsigned int nwires = thePlane.Nwires();
269  for (unsigned int iwire=0;iwire<nwires;iwire++){
270  thePlane.Wire(iwire).GetStart(endpoint);
271  PlaneData.fYmax = std::max(PlaneData.fYmax,endpoint[1]);
272  PlaneData.fYmin = std::min(PlaneData.fYmin,endpoint[1]);
273  PlaneData.fZmax = std::max(PlaneData.fZmax,endpoint[2]);
274  PlaneData.fZmin = std::min(PlaneData.fZmin,endpoint[2]);
275  thePlane.Wire(iwire).GetEnd(endpoint);
276  PlaneData.fYmax = std::max(PlaneData.fYmax,endpoint[1]);
277  PlaneData.fYmin = std::min(PlaneData.fYmin,endpoint[1]);
278  PlaneData.fZmax = std::max(PlaneData.fZmax,endpoint[2]);
279  PlaneData.fZmin = std::min(PlaneData.fZmin,endpoint[2]);
280  } // loop on wire
281 
282  } // for plane
283  } // for TPC
284  } // for cryostat
285 
286  Index npla = crygeo.TPC(0).Nplanes();
287  fWirePitch.resize(npla);
288  fOrientation.resize(npla);
289  fSinOrientation.resize(npla);
290  fCosOrientation.resize(npla);
291 
292  for ( Index ipla=0; ipla<npla; ++ipla ) {
293  fWirePitch[ipla] = crygeo.TPC(0).WirePitch(ipla);
294  fOrientation[ipla] = crygeo.TPC(0).Plane(ipla).Wire(0).ThetaZ();
295  fSinOrientation[ipla] = sin(fOrientation[ipla]);
296  fCosOrientation[ipla] = cos(fOrientation[ipla]);
297  }
298 
299  for ( Index icry=0; icry<ncry; ++icry ) {
300  mf::LogVerbatim("DuneApaChannelMapAlg") << "Cryostat " << icry << ":";
301  mf::LogVerbatim("DuneApaChannelMapAlg") << " " << fNchannels << " total channels";
302  mf::LogVerbatim("DuneApaChannelMapAlg") << " " << fNTpc[icry]/2 << " APAs";
303  mf::LogVerbatim("DuneApaChannelMapAlg") << " For all identical APA:" ;
304  mf::LogVerbatim("DuneApaChannelMapAlg") << " Number of channels per APA = " << fChannelsPerAPA ;
305  mf::LogVerbatim("DuneApaChannelMapAlg") << " U channels per APA = " << 2*fAnchoredWires[0][0][0] ;
306  mf::LogVerbatim("DuneApaChannelMapAlg") << " V channels per APA = " << 2*fAnchoredWires[0][0][1] ;
307  mf::LogVerbatim("DuneApaChannelMapAlg") << " Z channels per APA = " << 2*fAnchoredWires[0][0][2] ;
308  mf::LogVerbatim("DuneApaChannelMapAlg") << " Pitch in U Plane = " << fWirePitch[0] ;
309  mf::LogVerbatim("DuneApaChannelMapAlg") << " Pitch in V Plane = " << fWirePitch[1] ;
310  mf::LogVerbatim("DuneApaChannelMapAlg") << " Pitch in Z Plane = " << fWirePitch[2] ;
311  }
312 
313 }
314 
315 //----------------------------------------------------------------------------
316 
320 }
321 
322 //----------------------------------------------------------------------------
323 
325  vector< WireID > wirids;
326  if ( icha >= fNchannels ) return wirids;
327  // Loop over ROPs to find the one holding this channel.
328  Index ncry = fNcryostat;
329  Index icry = badIndex;
330  Index iapa = badIndex;
331  Index irop = badIndex;
332  Index ichaRop = badIndex; // Channel number in the ROP
333  bool found = false;
334  for ( icry=0; icry<ncry; ++icry ) {
335  Index napa = fNApa[icry];
336  for ( iapa=0; iapa<napa; ++iapa ) {
337  Index nrop = fRopsPerApa[icry][iapa];
338  for ( irop=0; irop<nrop; ++irop ) {
339  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
340  Index icha2 = fFirstChannelInNextRop[icry][iapa][irop];
341  found = icha >= icha1 && icha < icha2;
342  if ( found ) {
343  ichaRop = icha - icha1;
344  break;
345  }
346  }
347  if ( found ) break;
348  }
349  if ( found ) break;
350  }
351  if ( icry >= ncry ) {
352  mf::LogError("DuneApaChannelMapAlg") << "Unable to find APA plane for channel " << icha;
353  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Unable to find APA plane for channel " << icha;
354  return wirids;
355  }
356  // Extract TPC(s) from ROP
357  Index nrpl = fPlanesPerRop[icry][iapa][irop];
358  if ( nrpl == 0 ) throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": No TPC planes.";
359  if ( nrpl > 2 ) throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Too many TPC planes.";
360  Index itpc1 = fRopTpc[icry][iapa][irop][0];
361  Index ipla = fRopPlane[icry][iapa][irop][0];
362  Index itpc2 = (nrpl > 1 ) ? fRopTpc[icry][iapa][irop][1] : itpc1;
363  Index nAnchored = fAnchoredWires[icry][itpc1][ipla];
364  bool wrapped = ipla < 2;
365  if ( wrapped && itpc2 == itpc1 )
366  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": 2nd plane not found for wrapped ROP";
367  if ( wrapped && ipla != fRopPlane[icry][iapa][irop][1] )
368  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Wrapped planes have inconsistent indices.";
369  // For now, assume the second TPC plane has the same # anchored wires.
370  // Code will need some work if we want to relax this assumption.
371  if ( wrapped && fAnchoredWires[icry][itpc2][ipla] != nAnchored )
372  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Planes have inconsistent anchor counts.";
373  // If this is a wrapped ROP and the wire number is larger than nAnchored, then
374  // the first wire for this channel is in the other TPC plane.
375  Index itpc = itpc1;
376  Index iwir = ichaRop;
377  if ( wrapped && iwir >= nAnchored ) {
378  itpc = itpc2;
379  iwir -= nAnchored;
380  }
381  if ( iwir >= nAnchored ) {
382  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Invalid channel: iwir =" << iwir;
383  }
384  // Loop over wires and create IDs.
385  while ( iwir < fWiresPerPlane[icry][itpc][ipla] ) {
386  WireID wirid(icry, itpc, ipla, iwir);
387  wirids.push_back(wirid);
388  iwir += fAnchoredWires[icry][itpc][ipla];
389  itpc = (itpc == itpc1) ? itpc2 : itpc1;
390  }
391  return wirids;
392 }
393 
394 //----------------------------------------------------------------------------
395 
396 unsigned int DuneApaChannelMapAlg::Nchannels() const {
397  return fNchannels;
398 }
399 
400 //----------------------------------------------------------------------------
401 
402 unsigned int DuneApaChannelMapAlg::Nchannels(ROPID const& ropid) const {
403  Index icry = ropid.Cryostat;
404  Index iapa = ropid.TPCset;
405  Index irop = ropid.ROP;
406  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
407  Index icha2 = fFirstChannelInNextRop[icry][iapa][irop];
408  return icha2 - icha1;
409 }
410 
411 //----------------------------------------------------------------------------
412 
414 WireCoordinate(double YPos, double ZPos, unsigned int PlaneNo, unsigned int TPCNo,
415  unsigned int cstat) const {
416  return WireCoordinate(YPos, ZPos, PlaneID(cstat, TPCNo, PlaneNo));
417 }
418 
419 //----------------------------------------------------------------------------
420 
422 WireCoordinate(double YPos, double ZPos, PlaneID const& plaid) const {
423  const PlaneData_t& PlaneData = AccessElement(fPlaneData, plaid);
424  Index icry = plaid.Cryostat;
425  Index itpc = plaid.TPC;
426  Index ipla = plaid.Plane;
427  // The formula used here is geometric:
428  // distance = delta_y cos(theta_z) + delta_z sin(theta_z)
429  // with a correction for the orientation of the TPC:
430  // odd TPCs have supplementary wire angle (pi-theta_z), changing cosine sign
431  double backsign = (fPlaneRopIndex[icry][itpc][ipla] == 1) ? -1.0 : 1.0;
432  float distance =
433  -(YPos - PlaneData.fFirstWireCenterY) * backsign * fCosOrientation[ipla]
434  + (ZPos - PlaneData.fFirstWireCenterZ) * fSinOrientation[ipla]
435  ;
436  // The sign of this formula is correct if the wire with larger ID is on the
437  // "right" (intuitively, larger z; rigorously, smaller intercept)
438  // than this one.
439  // Of course, we are not always that lucky. fWireSortingInZ fixes our luck.
440  return PlaneData.fWireSortingInZ * distance/fWirePitch[ipla];
441 }
442 
443 //----------------------------------------------------------------------------
444 
446 NearestWireID(const TVector3& xyz, PlaneID const& plaid) const {
447 
448 
449  // cap the position to be within the boundaries of the wire endpoints.
450  // This simulates charge drifting in from outside of the wire frames inwards towards
451  // the first and last collection wires on the side, and towards the right endpoints
452 
453  const PlaneData_t& PlaneData = AccessElement(fPlaneData, plaid);
454  double ycap = std::max(PlaneData.fYmin,std::min(PlaneData.fYmax,xyz.Y()));
455  double zcap = std::max(PlaneData.fZmin,std::min(PlaneData.fZmax,xyz.Z()));
456 
457  int iwirSigned = 0.5 + WireCoordinate(ycap, zcap, plaid);
458  Index iwir = (iwirSigned < 0) ? 0 : iwirSigned;
459  Index icry = plaid.Cryostat;
460  Index itpc = plaid.TPC;
461  Index ipla = plaid.Plane;
462  Index iwirMax = fWiresPerPlane[icry][itpc][ipla] - 1;
463  if ( iwir > iwirMax ) iwir = iwirMax;
464  return WireID(plaid, iwir);
465 }
466 
467 //----------------------------------------------------------------------------
468 
470  Index icry = wirid.Cryostat;
471  Index itpc = wirid.TPC;
472  Index ipla = wirid.Plane;
473  Index ichaRop = wirid.Wire;
474  Index iapa = fPlaneApa[icry][itpc][ipla];
475  Index irop = fPlaneRop[icry][itpc][ipla];
476  Index irpl = fPlaneRopIndex[icry][itpc][ipla];
477  Index nrpl = fPlanesPerRop[icry][iapa][irop];
478  Index ncha = fAnchoredWires[icry][itpc][ipla];
479  if ( nrpl > 1 ) { // Wrapped ROP
480  Index ipla1 = fRopPlane[icry][iapa][irop][0];
481  Index ipla2 = fRopPlane[icry][iapa][irop][1];
482  // Wire is in the back TPC.
483  if ( irpl == 1 ) {
484  ichaRop += fAnchoredWires[icry][itpc][ipla1];
485  ncha += fAnchoredWires[icry][itpc][ipla1];
486  // Wire is in the front TPC.
487  } else {
488  ncha += fAnchoredWires[icry][itpc][ipla2];
489  }
490  }
491  // Channel # in ROP is modulus the # channels in the ROP.
492  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
493  Index icha = icha1 + ichaRop%ncha;
494  return icha;
495 }
496 
497 //----------------------------------------------------------------------------
498 
500  Index ncry = fNcryostat;
501  for ( Index icry=0; icry<ncry; ++icry ) {
502  Index napa=fNApa[icry];
503  for ( Index iapa=0; iapa<napa; ++iapa ) {
504  Index nrop = fRopsPerApa[icry][iapa];
505  for ( Index irop=0; irop<nrop; ++irop ) {
506  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
507  Index icha2 = fFirstChannelInNextRop[icry][iapa][irop];
508  if ( icha >= icha1 && icha < icha2 ) {
509  if ( irop < 2 ) return geo::kInduction;
510  else if ( irop < 4 ) return geo::kCollection;
511  else return geo::kMysteryType;
512  }
513  }
514  }
515  }
516  return geo::kMysteryType;
517 }
518 
519 //----------------------------------------------------------------------------
520 /* // this code should be equivalent to the logic implemented in geo::PlaneGeo::UpdateView()
521 View_t DuneApaChannelMapAlg::View(ChannelID_t const icha) const {
522  Index ncry = fNcryostat;
523  for ( Index icry=0; icry<ncry; ++icry ) {
524  Index napa=fNApa[icry];
525  for ( Index iapa=0; iapa<napa; ++iapa ) {
526  Index nrop = fRopsPerApa[icry][iapa];
527  for ( Index irop=0; irop<nrop; ++irop ) {
528  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
529  Index icha2 = fFirstChannelInNextRop[icry][iapa][irop];
530  if ( icha >= icha1 && icha < icha2 ) {
531  if ( irop == 0 ) return geo::kU;
532  if ( irop == 1 ) return geo::kV;
533  if ( irop == 2 ) return geo::kZ;
534  if ( irop == 3 ) return geo::kZ;
535  return geo::kUnknown;
536  }
537  }
538  }
539  }
540  return geo::kUnknown;
541 }
542 */
543 
544 //----------------------------------------------------------------------------
545 
546 std::set<PlaneID> const& DuneApaChannelMapAlg::PlaneIDs() const {
547  return fPlaneIDs;
548 }
549 
550 //----------------------------------------------------------------------------
551 
552 Index DuneApaChannelMapAlg::NOpChannels(unsigned int NOpDets) const {
553  if ( fOpDetFlag == 1 ) return 12*NOpDets;
554  return fChannelsPerOpDet*NOpDets;
555 }
556 
557 //----------------------------------------------------------------------------
558 
560  if ( fOpDetFlag == 1 ) {
561  // CSU 3-sipm design
562  if (opDet == 0 || opDet == 4 || opDet == 6) return 8;
563  // LSU 2-sipm design
564  if (opDet == 2) return 2;
565  // IU 12-sipm design
566  return 12;
567  }
568  return fChannelsPerOpDet;
569 }
570 
571 //----------------------------------------------------------------------------
572 
573 Index DuneApaChannelMapAlg::OpChannel(unsigned int detNum, unsigned int channel) const {
574  if ( fOpDetFlag == 1 ) return (detNum * 12) + channel;
575  unsigned int uniqueChannel = (detNum * fChannelsPerOpDet) + channel;
576  return uniqueChannel;
577 }
578 
579 //----------------------------------------------------------------------------
580 
581 Index DuneApaChannelMapAlg::OpDetFromOpChannel(unsigned int opChannel) const {
582  if ( fOpDetFlag == 1 ) return opChannel/12;
583  unsigned int detectorNum = opChannel/fChannelsPerOpDet;
584  return detectorNum;
585 }
586 
587 //----------------------------------------------------------------------------
588 
590  if ( fOpDetFlag == 1 ) return opChannel%12;
591  unsigned int channel = opChannel % fChannelsPerOpDet;
592  return channel;
593 }
594 
595 //----------------------------------------------------------------------------
596 
598  if (!HasCryostat(cryid)) return 0;
599  Index icry = cryid.Cryostat;
600  return fNApa[icry];
601 }
602 
603 //----------------------------------------------------------------------------
604 
606  return fNApaMax;
607 }
608 
609 //----------------------------------------------------------------------------
610 
611 bool DuneApaChannelMapAlg::HasTPCset(TPCsetID const& tpcsetid) const {
612  return HasCryostat(tpcsetid) && (tpcsetid.TPCset < NTPCsets(tpcsetid));
613 }
614 
615 //----------------------------------------------------------------------------
616 
618  Index icry = tpcid.Cryostat;
619  Index itpc = tpcid.TPC;
620  Index ipla = 0;
621  Index iapa = fPlaneApa[icry][itpc][ipla];
622  return TPCsetID(icry, iapa);
623 }
624 
625 //----------------------------------------------------------------------------
626 
627 vector<TPCID> DuneApaChannelMapAlg::TPCsetToTPCs(TPCsetID const& apaid) const {
628  Index icry = apaid.Cryostat;
629  Index iapa = apaid.TPCset;
630  vector<TPCID> tpcids;
631  for ( Index itpc : fApaTpcs[icry][iapa] ) tpcids.push_back(TPCID(icry, itpc));
632  return tpcids;
633 }
634 
635 //----------------------------------------------------------------------------
636 
638  Index icry = apaid.Cryostat;
639  Index iapa = apaid.TPCset;
640  Index itpc = TPCID::InvalidID;
641  if ( fApaTpcs[icry][iapa].size() ) itpc = fApaTpcs[icry][iapa][0];
642  return TPCID(icry, itpc);
643 }
644 
645 //----------------------------------------------------------------------------
646 
648  if (!HasTPCset(apaid)) return 0;
649  Index icry = apaid.Cryostat;
650  Index iapa = apaid.TPCset;
651  return fRopsPerApa[icry][iapa];
652 }
653 
654 //----------------------------------------------------------------------------
655 
657  return fNRopMax;
658 }
659 
660 //----------------------------------------------------------------------------
661 
662 bool DuneApaChannelMapAlg::HasROP(ROPID const& ropid) const {
663  return HasTPCset(ropid) && (ropid.ROP < NROPs(ropid));
664 }
665 
666 //----------------------------------------------------------------------------
667 
669  Index icry = plaid.Cryostat;
670  Index itpc = plaid.TPC;
671  Index ipla = plaid.Plane;
672  Index iapa = fPlaneApa[icry][itpc][ipla];
673  Index irop = fPlaneRop[icry][itpc][ipla];
674  return ROPID(icry, iapa, irop);
675 }
676 
677 //----------------------------------------------------------------------------
678 
679 vector<PlaneID> DuneApaChannelMapAlg::ROPtoWirePlanes(ROPID const& ropid) const {
680  vector<PlaneID> plaids;
681  Index icry = ropid.Cryostat;
682  Index iapa = ropid.TPCset;
683  Index irop = ropid.ROP;
684  Index nrpl = fPlanesPerRop[icry][iapa][irop];
685  for ( Index irpl=0; irpl<nrpl; ++irpl ) {
686  Index itpc = fRopTpc[icry][iapa][irop][irpl];
687  Index ipla = fRopPlane[icry][iapa][irop][irpl];
688  plaids.push_back(PlaneID(icry, itpc, ipla));
689  }
690  return plaids;
691 }
692 
693 //----------------------------------------------------------------------------
694 
695 vector<TPCID> DuneApaChannelMapAlg::ROPtoTPCs(ROPID const& ropid) const {
696  vector<TPCID> tpcids;
697  vector<PlaneID> plaids = ROPtoWirePlanes(ropid);
698  for ( const PlaneID& plaid : plaids ) {
699  TPCID tpcid = plaid;
700  if ( find(tpcids.begin(), tpcids.end(), tpcid) == tpcids.end() ) tpcids.push_back(tpcid);
701  }
702  return tpcids;
703 }
704 
705 //----------------------------------------------------------------------------
706 
708  Index ncry = fNcryostat;
709  for ( Index icry=0; icry<ncry; ++icry ) {
710  Index napa = fNApa[icry];
711  for ( Index iapa=0; iapa<napa; ++iapa ) {
712  Index nrop = fRopsPerApa[icry][iapa];
713  for ( Index irop=0; irop<nrop; ++irop ) {
714  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
715  Index icha2 = fFirstChannelInNextRop[icry][iapa][irop];
716  if ( icha >= icha1 && icha < icha2 ) return ROPID(icry, iapa, irop);
717  }
718  }
719  }
720  return(ROPID(CryostatID::InvalidID, TPCsetID::InvalidID, ROPID::InvalidID));
721 }
722 
723 //----------------------------------------------------------------------------
725  if ( fSorter == nullptr )
726  throw cet::exception("DuneApaChannelMapAlg") << __func__ << ": Sorter is missing.";
727  return *fSorter;
728 } // DuneApaChannelMapAlg::Sorter()
729 
730 //----------------------------------------------------------------------------
731 
733  Index icry = ropid.Cryostat;
734  Index iapa = ropid.TPCset;
735  Index irop = ropid.ROP;
736  Index icha1 = fFirstChannelInThisRop[icry][iapa][irop];
737  return icha1;
738 }
739 
740 //----------------------------------------------------------------------------
741 
743  vector<PlaneID> plaids = ROPtoWirePlanes(ropid);
744  if ( plaids.size() ) return plaids[0];
746 }
747 
748 //----------------------------------------------------------------------------
unsigned int Nchannels() const override
Returns the total number of channels present (not necessarily contiguous)
unsigned int fNApaMax
Max # TPCs in any cryostat.
void GetStart(double *xyz) const
Definition: WireGeo.h:157
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int fNRopMax
Max # ROPs in any APA.
Index badIndex
bool HasCryostat(CryostatID const &cid) const
Returns whether the specified ID represents a valid cryostat.
virtual readout::ROPID WirePlaneToROP(geo::PlaneID const &planeid) const override
Returns the ID of the ROP planeid belongs to, or invalid if none.
std::set< PlaneID > fPlaneIDs
vector of the PlaneIDs present in the detector
static constexpr TPCID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:403
Who knows?
Definition: geo_types.h:147
Encapsulate the construction of a single cyostat.
unsigned int OpDetFromOpChannel(unsigned int opChannel) const override
Returns the optical detector the specified optical channel belongs.
virtual geo::PlaneID FirstWirePlaneInROP(readout::ROPID const &ropid) const override
Returns the ID of the first plane belonging to the specified ROP.
float fWireSortingInZ
+1 if the wire ID order follow z (larger z, or smaller intercept => larger wire ID); -1 otherwise ...
std::vector< double > fOrientation
SigType_t SignalTypeForChannelImpl(raw::ChannelID_t const channel) const override
Return the signal type of the specified channel.
WireGeo const & Wire(unsigned int iwire) const
Definition: PlaneGeo.cxx:506
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
Planes which measure V.
Definition: geo_types.h:130
ThreeVector< unsigned int > fApaTpcs
TPCs for each APA.
ThreeVector< unsigned int > fChannelsPerRop
channels for each Rop
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
std::vector< double > fCosOrientation
PlaneInfoMap_t< raw::ChannelID_t > fFirstChannelInThisRop
(cry, apa, rop)
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
double WireCoordinate(double YPos, double ZPos, unsigned int PlaneNo, unsigned int TPCNo, unsigned int cstat) const override
Returns the index of the wire nearest to the specified position.
struct vector vector
Class identifying a set of TPC sharing readout channels.
Definition: readout_types.h:70
virtual WireID NearestWireID(const TVector3 &worldPos, unsigned int PlaneNo, unsigned int TPCNo, unsigned int cstat) const override
Returns the ID of the wire nearest to the specified position.
const geo::GeoObjectSorter * fSorter
sorts geo::XXXGeo objects
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
Planes which measure Z direction.
Definition: geo_types.h:132
virtual unsigned int MaxROPs() const override
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
Interface to algorithm class for a specific detector channel mapping.
T const & AccessElement(TPCInfoMap_t< T > const &map, geo::TPCID const &id) const
Returns the specified element of the TPC map.
CryostatList_t cryostats
The detector cryostats.
Definition: GeometryData.h:38
uint8_t channel
Definition: CRTFragment.hh:201
ThreeVector< unsigned int > fPlaneRop
ROP for each TPC plane (cry, tpc, pla)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int Index
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
PlaneInfoMap_t< raw::ChannelID_t > fFirstChannelInThisPlane
ThreeVector< unsigned int > fAnchoredWires
anchored wires for each (cry, tpc, pla)
virtual geo::GeoObjectSorter const & Sorter() const override
Returns the object to sort geometry with.
unsigned int NOpChannels(unsigned int NOpDets) const override
Returns the number of optical channels contained in some detectors.
virtual unsigned int MaxTPCsets() const override
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
Definition: WireGeo.h:250
std::vector< double > fWirePitch
void setSorter(const geo::GeoObjectSorter &sort)
PlaneInfoMap_t< PlaneData_t > fPlaneData
TwoVector< unsigned int > fPlanesPerTpc
planes for each (cry, tpc)
TPCInfoMap_t< std::vector< T >> PlaneInfoMap_t
Data type for per-plane information.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
ThreeVector< unsigned int > fPlaneApa
APA for each TPC plane (cry, tpc, pla)
Planes which measure U.
Definition: geo_types.h:129
TwoVector< unsigned int > fChannelsPerApa
channels for each APA
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:184
readout::ROPID ROPID
virtual unsigned int NROPs(readout::TPCsetID const &tpcsetid) const override
Returns the total number of ROP in the specified TPC set.
virtual raw::ChannelID_t FirstChannelInROP(readout::ROPID const &ropid) const override
Returns the ID of the first channel in the specified readout plane.
ROPID_t ROP
Index of the readout plane within its TPC set.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
unsigned int fChannelsPerOpDet
Flag for OpDet channel map.
Signal from induction planes.
Definition: geo_types.h:145
void swap(Handle< T > &a, Handle< T > &b)
void Initialize(GeometryData_t const &geodata) override
Geometry initialisation.
enum geo::_plane_sigtype SigType_t
IDparameter< readout::TPCsetID > TPCsetID
Member type of validated readout::TPCsetID parameter.
FourVector< unsigned int > fRopPlane
TPC plane index for each (cry, apa, rop, rpl)
unsigned int OpChannel(unsigned int detNum, unsigned int channel=0) const override
Returns the channel ID of the specified hardware channel.
std::vector< WireID > ChannelToWire(raw::ChannelID_t channel) const override
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::vector< unsigned int > fNApa
number of APAs in each cryostat
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
p
Definition: test.py:223
virtual readout::ROPID ChannelToROP(raw::ChannelID_t channel) const override
Encapsulate the geometry of an auxiliary detector.
ThreeVector< unsigned int > fPlanesPerRop
TPC planes for each (cry, apa, rop)
unsigned int fNcryostat
number of cryostats in the detector
double WirePitch(unsigned plane=0) const
Definition: TPCGeo.cxx:396
std::vector< double > fSinOrientation
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Class identifying a set of planes sharing readout channels.
TPCsetID_t TPCset
Index of the TPC set within its cryostat.
Definition: readout_types.h:90
virtual std::vector< geo::PlaneID > ROPtoWirePlanes(readout::ROPID const &ropid) const override
Returns a list of ID of wire planes belonging to the specified ROP.
FourVector< unsigned int > fRopTpc
TPC planes for each (cry, apa, rop, rpl)
Encapsulate the geometry of a wire.
void Uninitialize() override
Deconfiguration: prepare for a following call of Initialize()
virtual readout::TPCsetID TPCtoTPCset(geo::TPCID const &tpcid) const override
Returns the ID of the TPC set the specified TPC belongs to.
virtual bool HasTPCset(readout::TPCsetID const &tpcsetid) const override
virtual std::vector< geo::TPCID > TPCsetToTPCs(readout::TPCsetID const &tpcsetid) const override
Returns a list of ID of TPCs belonging to the specified TPC set.
virtual raw::ChannelID_t PlaneWireToChannel(unsigned int plane, unsigned int wire, unsigned int tpc, unsigned int cstat) const override
Returns the channel ID a wire is connected to.
unsigned int fChannelsPerAPA
number of channels in each APA
ThreeVector< unsigned int > fPlaneRopIndex
Index in ROP for each TPC plane (cry, tpc, pla)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Encapsulate the construction of a single detector plane.
unsigned int fNchannels
number of channels in the detector
unsigned int HardwareChannelFromOpChannel(unsigned int opChannel) const override
Returns the hardware channel number of specified optical channel.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
virtual unsigned int NTPCsets(readout::CryostatID const &cryoid) const override
Returns the total number of TPC sets in the specified cryostat.
void GetEnd(double *xyz) const
Definition: WireGeo.h:163
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:224
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:269
bool WireIDincreasesWithZ() const
Returns whether the higher z wires have higher wire ID.
Definition: PlaneGeo.cxx:525
unsigned int NOpHardwareChannels(unsigned int opDet) const override
Returns the number of channels in the specified optical detectors.
TwoVector< unsigned int > fRopsPerApa
ROPs for each (cry, apa)
std::set< PlaneID > const & PlaneIDs() const override
Returns a list of the plane IDs in the whole detector.
Access the description of detector geometry.
unsigned int fNTpcMax
Max # TPCs in any cryostat.
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
raw::ChannelID_t fTopChannel
book keeping highest channel #
IDparameter< geo::TPCID > TPCID
Member type of validated geo::TPCID parameter.
static constexpr CryostatID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:208
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
ThreeVector< unsigned int > fWiresPerPlane
wires/TPC plane for each (cry, tpc, pla)
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
Definition: WireGeo.cxx:73
Data in the geometry description.
Definition: GeometryData.h:31
PlaneInfoMap_t< raw::ChannelID_t > fFirstChannelInNextPlane
static constexpr PlaneID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:490
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
std::vector< unsigned int > fNTpc
number of TPCs in each cryostat
virtual bool HasROP(readout::ROPID const &ropid) const override
static constexpr ROPID_t InvalidID
Special code for an invalid ID.
unsigned int Index
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
virtual geo::TPCID FirstTPCinTPCset(readout::TPCsetID const &tpcsetid) const override
QTextStream & endl(QTextStream &s)
virtual std::vector< geo::TPCID > ROPtoTPCs(readout::ROPID const &ropid) const override
Returns a list of ID of TPCs the specified ROP spans.
Encapsulate the construction of a single detector plane.
The data type to uniquely identify a cryostat.
Definition: geo_types.h:190
Signal from collection planes.
Definition: geo_types.h:146
ThreeVector< unsigned int > fAnchoredPlaneRop
ROP holding the anchored wires for (cry, tpc, pla)
PlaneInfoMap_t< raw::ChannelID_t > fFirstChannelInNextRop
(cry, apa, rop)