CRTID.h
Go to the documentation of this file.
1 //File: CRTID.h
2 //Brief: Tools for sorting CRT channels by detector groupings.
3 // Organizing CRT channels this way should help users
4 // identify overlapping channels for reconstruction.
5 //Author: Andrew Olivier aolivier@ur.rochester.edu
6 
7 #ifndef CRTID_H
8 #define CRTID_H
9 
10 //c++ includes
11 #include <cstdint> //For uint8_t and friends
12 #include <cstddef> //For size_t
13 #include <map> //For CRT::map definition
14 
15 namespace CRT
16 {
17  //Programming model:
18  //
19  //I want to express the CRT geometry as a series of abstract layers
20  //that can be better defined based on what I know about the geometry
21  //in a particular application for particular run conditions. To keep
22  //things as simple as possible, I'm defining "key" classes to uniquely
23  //identify layers of the geometry while letting users decide what
24  //they want to do with those layers. I'm planning to use these
25  //identifiers with std::map, but you can probably find other ways to be
26  //even more creative.
27  //
28  //The top-level geometry concept isa frame. Inside of each frame are
29  //2 planes of modules in different orientations. So, to specify a plane,
30  //one also has to specify what frame that plane is a part of. There are 5
31  //layers like this in the CRT geometry: Frame, Plane, Module, Layer, and Strip.
32  //I have provided a typedef for each layer below so that you can "effortlessly"
33  //use these concepts in your code without ever knowing that I'm using class
34  //template.
35 
36  //Implementation details:
37  //
38  //The original design of this scheme, where I wrote a separate struct
39  //for each abstract layer and hoped I didn't type any mistakes, failed
40  //miserably because it was very hard to maintain when I came across my
41  //first bug. So, I made the compiler do (almost) all of the work for me!
42  //
43  //Essentially, I want to create a tree at compile-time to sort
44  //based on multiple layers of CRT geometry abstraction. To reduce
45  //the opportunity for typing mistakes and the number of points
46  //of maintenence, I'm going to write a tree node once as an ugly
47  //class template, then I'll typedef the appropriate class template
48  //instantiations to make things more user-friendly.
49  namespace detail
50  {
51  //Abandon all hope ye who enter here. Somewhat-complicated class
52  //templates ahead. If you want to read this, you should be comfortable
53  //with class templates, operator overloading, and partial template
54  //speicializations.
55  template <class BASE, class ID>
56  //BASE is the Node above this one. I plan
57  //to write a partial template specialization
58  //to allow for a root node shortly.
59  //
60  //ID is a comparable type that uniquely identifies
61  //elements within a layer of this compile-time octree.
62  struct Node: public BASE
63  {
64  explicit Node(const BASE& base, const ID& id): BASE(base), fID(id) {}
65  virtual ~Node() = default;
66 
67  //Compare Nodes that represent the same layer based on
68  //their identifier within this layer. If Nodes are from
69  //a different layer, they should not compare equal.
70  //
71  //Comparison operators are intentionally NOT virtual so
72  //that users can choose to sort strips only into modules
73  //for example.
74  bool operator ==(const Node<BASE, ID>& other) const
75  {
76  if(!(this->BASE::operator==(other))) return false;
77  return fID == other.fID;
78  }
79 
80  bool operator < (const Node<BASE, ID>& other) const
81  {
82  //if(this->BASE::operator<(other)) return true;
83  if(!(this->BASE::operator==(other))) return this->BASE::operator<(other);
84  return fID < other.fID;
85  }
86 
87  protected:
88  const ID fID; //Unique identifier for an element in this layer of a compile-time octree.
89  };
90 
91  //Specialization for BASE=void that defines a root node
92  template <class ID>
93  struct Node<void, ID>
94  {
95  explicit Node(const ID& id): fID(id) {}
96  virtual ~Node() = default;
97 
98  bool operator ==(const Node<void, ID>& other) const
99  {
100  return fID == other.fID;
101  }
102 
103  bool operator < (const Node<void, ID>& other) const
104  {
105  return fID < other.fID;
106  }
107 
108  protected:
109  const ID fID; //Unique identifier for an element in this layer of a compile-time octree.
110  };
111  }
112 
113  //A CRT Frame consists of 4 modules in 2 layers.
114  //One layer is horizontal and gives y positions, and
115  //the other layer is vertical and gives x positions.
116  //In the ProtoDUNE-SP Cosmic Ray Tagger, there are
117  //4 frames upstream of the TPC and 4 frames downstream.
118  //
119  //In terms of a tree, FrameID is the root node.
121 
122  //Within each frame, there are two planes of CRT modules to give
123  //a 2D position readout. A plane belongs to a frame, so a PlaneID
124  //is a FrameID.
126 
127  //Each CRT module has 2 layers of 32 scintillator strips
128  //each. A CRT module belongs to a plane within a frame.
129  //So, a CRT::ModuleID is a PlaneID. In the ProtoDUNE-SP
130  //CRT, there were two modules in each orientation in
131  //a frame.
133 
134  //A CRT module has 2 layers of 32 scintillator strips each.
135  //A layer is inside a module, so a LayerID is a ModuleID.
136  //Since modules may have been rotated during mounting, define
137  //layers based on which layer is closer to the HV connector on
138  //a CRT module's board. The PMT can only be mounted in one
139  //direction.
141 
142  //There are 32 strips in each layer of a CRT module.
143  //A strip belongs to a layer, so a StripID is a LayerID.
144  //typedef detail::Node<LayerID, uint8_t> StripID;
145  struct StripID: public detail::Node<LayerID, uint8_t>
146  {
147  StripID(const LayerID& layer, const uint8_t local): detail::Node<LayerID, uint8_t>(layer, local) {}
148  virtual ~StripID() = default;
149 
150  bool Overlaps(const StripID& other) const
151  {
152  if(!(this->ModuleID::operator==(other))) return false; //Strips from different modules can't overlap
153  if(this->LayerID::operator==(other)) return false; //Strips from the same layer can't overlap
154 
155  const auto diff = fID - other.fID;
156 
157  //diff == 0 overlaps for either the top or the bottom.
158  if(diff == 0) return true;
159 
160  const auto layer = this->LayerID::fID;
161  //If this is the bottom layer
162  if(layer) return diff == 1;
163 
164  //If we survived this far, this is the top layer
165  return diff == -1;
166  }
167  };
168 
169  //Provide a clone of std::map that has a less cumbersome interface. We really just want to repeatedly
170  //cast a StripID to different types for different nodes' comparisons.
171  //
172  //VALUE is any class that can be the second template argument to std::map.
173  //Each of KEY and KEYS is an object that can be used as the first template argument to std::map.
174  template <class VALUE, class KEY, class ...KEYS>
175  class map
176  {
177  private:
178  std::map<KEY, CRT::map<VALUE, KEYS...>> fMap; //Implement this class with std::map and just give a signature
179  //for operator [] that better matches what I want to do.
180 
181  public:
182  map(): fMap() {}
183  virtual ~map() = default;
184 
185  //Find the most-derived key type for the argument to operator[]
186  using most_derived_key_type = typename CRT::map<VALUE, KEYS...>::most_derived_key_type;
187 
188  //Public interface from std::map but with operator [] better suited to my needs.
189  //TODO: Every Map's operator[] needs to take the most-derived argument, but CRT::StripIDs need to be sorted
190  // into less-derived ID objects.
191  inline VALUE& operator [](const most_derived_key_type& key) { return fMap[key][key]; }
192 
193  using iterator = decltype(fMap.begin());
194  inline iterator begin() { return fMap.begin(); }
195  inline iterator end() { return fMap.end(); }
196 
197  using const_iterator = decltype(fMap.cbegin());
198  inline const_iterator begin() const { return fMap.cbegin(); }
199  inline const_iterator end() const { return fMap.cend(); }
200 
201  inline size_t size() const { return fMap.size(); }
202  };
203 
204  //Specialization for CRT::map with just one type as key. Basically, expose std::map<KEY, VALUE>'s interface
205  template <class VALUE, class KEY>
206  class map<VALUE, KEY>
207  {
208  private:
209  std::map<KEY, VALUE> fMap; //Implement this class with std::map and just give a signature
210  //for operator [] that better matches what I want to do.
211 
212  public:
213  map(): fMap() {}
214  virtual ~map() = default;
215 
217 
218  //Public interface from std::map but with operator [] better suited to my needs.
219  inline VALUE& operator [](const KEY& key) { return fMap[key]; }
220 
221  using iterator = decltype(fMap.begin());
222  inline iterator begin() { return fMap.begin(); }
223  inline iterator end() { return fMap.end(); }
224 
225  using const_iterator = decltype(fMap.cbegin());
226  inline const_iterator begin() const { return fMap.cbegin(); }
227  inline const_iterator end() const { return fMap.cend(); }
228 
229  inline size_t size() const { return fMap.size(); }
230  };
231 
232  //TODO: I could probably just use map instead of geoMap if I wrote some implementation class that splits the parameter pack above
233  template <class VALUE>
235 }
236 
237 #endif //CRTID_H
bool operator==(const Node< BASE, ID > &other) const
Definition: CRTID.h:74
unsigned int ID
detail::Node< void, uint8_t > FrameID
Definition: CRTID.h:120
detail::Node< ModuleID, bool > LayerID
Definition: CRTID.h:140
Node(const ID &id)
Definition: CRTID.h:95
detail::Node< PlaneID, bool > ModuleID
Definition: CRTID.h:132
virtual ~Node()=default
const_iterator begin() const
Definition: CRTID.h:226
bool Overlaps(const StripID &other) const
Definition: CRTID.h:150
decltype(fMap.cbegin()) const_iterator
Definition: CRTID.h:225
size_t size() const
Definition: CRTID.h:201
decltype(fMap.begin()) iterator
Definition: CRTID.h:221
const_iterator begin() const
Definition: CRTID.h:198
def key(type, name=None)
Definition: graph.py:13
const ID fID
Definition: CRTID.h:88
const_iterator end() const
Definition: CRTID.h:199
typename CRT::map< VALUE, KEYS... >::most_derived_key_type most_derived_key_type
Definition: CRTID.h:186
decltype(fMap.cbegin()) const_iterator
Definition: CRTID.h:197
size_t size() const
Definition: CRTID.h:229
decltype(fMap.begin()) iterator
Definition: CRTID.h:193
iterator end()
Definition: CRTID.h:195
map()
Definition: CRTID.h:182
iterator begin()
Definition: CRTID.h:194
iterator begin()
Definition: CRTID.h:222
std::map< KEY, CRT::map< VALUE, KEYS... > > fMap
Definition: CRTID.h:178
iterator end()
Definition: CRTID.h:223
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
Node(const BASE &base, const ID &id)
Definition: CRTID.h:64
const_iterator end() const
Definition: CRTID.h:227
std::map< KEY, VALUE > fMap
Definition: CRTID.h:209
StripID(const LayerID &layer, const uint8_t local)
Definition: CRTID.h:147