LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
CryostatGeo.cxx
Go to the documentation of this file.
1 
7 // class header
9 
10 // LArSoft includes
12 
13 // Framework includes
15 #include "cetlib_except/exception.h"
16 
17 // ROOT includes
18 #include "TGeoNode.h"
19 #include "TGeoBBox.h"
20 #include "TClass.h"
21 
22 // C++ standard libraries
23 #include <limits> // std::numeric_limits<>
24 #include <algorithm> // std::sort()
25 
26 
27 namespace geo{
28 
29 
30  //......................................................................
31  // Define sort order for detector tpcs.
32  static bool opdet_sort(const OpDetGeo* t1, const OpDetGeo* t2)
33  {
34  double xyz1[3] = {0.}, xyz2[3] = {0.};
35  double local[3] = {0.};
36  t1->LocalToWorld(local, xyz1);
37  t2->LocalToWorld(local, xyz2);
38 
39  if(xyz1[2]!=xyz2[2])
40  return xyz1[2]>xyz2[2];
41  else if(xyz1[1]!=xyz2[1])
42  return xyz1[1]>xyz2[1];
43  else
44  return xyz1[0]>xyz2[0];
45  }
46 
47  // DUNE specific sorting originally intended for 10kt
48  // executed when there are 600+ opdets. -talion
50  static bool DUNE_opdet_sort(const OpDetGeo* t1, const OpDetGeo* t2)
51  {
52  double xyz1[3] = {0.}, xyz2[3] = {0.};
53  double local[3] = {0.};
54  t1->LocalToWorld(local, xyz1);
55  t2->LocalToWorld(local, xyz2);
56 
57  if(xyz1[0]!=xyz2[0])
58  return xyz1[0]>xyz2[0];
59  else if(xyz1[2]!=xyz2[2])
60  return xyz1[2]>xyz2[2];
61  else
62  return xyz1[1]>xyz2[1];
63  }
64 
65  //......................................................................
66  CryostatGeo::CryostatGeo(std::vector<const TGeoNode*>& path, int depth)
67  : fTrans(path, depth)
68  , fVolume(nullptr)
69  {
70 
71  // all planes are going to be contained in the volume named volCryostat
72  // now get the total volume of the Cryostat
73  fVolume = path[depth]->GetVolume();
74  if(!fVolume)
75  throw cet::exception("CryostatGeo") << "cannot find cryostat outline volume\n";
76 
77  LOG_DEBUG("Geometry") << "cryostat volume is " << fVolume->GetName();
78 
79  // set the bounding box
81 
82  // find the tpcs for the cryostat so that you can use them later
83  this->FindTPC(path, depth);
84 
85 
86  // Set OpDetName;
87  fOpDetGeoName = "volOpDetSensitive";
88 
89  // find the opdets for the cryostat so that you can use them later
90  this->FindOpDet(path, depth);
91 
92  // sort the OpDets according to xyz position
93  // 600 intended to separate dune10kt geometry from others when sorting
96  auto sorter = (fOpDets.size() != 600)? opdet_sort: DUNE_opdet_sort;
98  [&sorter](auto& coll){ std::sort(coll.begin(), coll.end(), sorter); }
99  );
100 
101  }
102 
103 
104  //......................................................................
105  void CryostatGeo::FindTPC(std::vector<const TGeoNode*>& path,
106  unsigned int depth)
107  {
108 
109  const char* nm = path[depth]->GetName();
110  if( (strncmp(nm, "volTPC", 6) == 0) ){
111  this->MakeTPC(path,depth);
112  return;
113  }
114 
115  //explore the next layer down
116  unsigned int deeper = depth+1;
117  if(deeper >= path.size()){
118  throw cet::exception("BadTGeoNode") << "exceeded maximum TGeoNode depth\n";
119  }
120 
121  const TGeoVolume *v = path[depth]->GetVolume();
122  int nd = v->GetNdaughters();
123  for(int i = 0; i < nd; ++i){
124  path[deeper] = v->GetNode(i);
125  this->FindTPC(path, deeper);
126  }
127 
128  }
129 
130  //......................................................................
131  void CryostatGeo::MakeTPC(std::vector<const TGeoNode*>& path, int depth)
132  {
133  fTPCs.emplace_back(path, depth);
134  }
135 
136 
137  //......................................................................
138  // sort the TPCGeo objects, and the PlaneGeo objects inside
140  {
141  //
142  // TPCs
143  //
145  (fTPCs, [&sorter](auto& coll){ sorter.SortTPCs(coll); });
146 
147  for (geo::TPCGeo& TPC: fTPCs) {
148  TPC.SortSubVolumes(sorter);
149  } // for TPCs
150 
151  //
152  // optical detectors
153  //
154 
155  // sorting of optical detectors happens elsewhere
156 
157  } // CryostatGeo::SortSubVolumes()
158 
159 
160  //......................................................................
162 
163  // update the cryostat ID
164  fID = cryoid;
165 
166  // trigger all the TPCs to update as well
167  for (unsigned int tpc = 0; tpc < NTPC(); ++tpc)
169 
170  } // CryostatGeo::UpdateAfterSorting()
171 
172 
173  //......................................................................
174  const TPCGeo& CryostatGeo::TPC(unsigned int itpc) const
175  {
176  TPCGeo const* pTPC = TPCPtr(itpc);
177  if(!pTPC){
178  throw cet::exception("TPCOutOfRange") << "Request for non-existant TPC "
179  << itpc << "\n";
180  }
181 
182  return *pTPC;
183  }
184 
185 
186 
187  //......................................................................
188  void CryostatGeo::FindOpDet(std::vector<const TGeoNode*>& path,
189  unsigned int depth)
190  {
191 
192  const char* nm = path[depth]->GetName();
193  if( (strncmp(nm, OpDetGeoName().c_str(), 6) == 0) ){
194  this->MakeOpDet(path,depth);
195  return;
196  }
197 
198  //explore the next layer down
199  unsigned int deeper = depth+1;
200  if(deeper >= path.size()){
201  throw cet::exception("BadTGeoNode") << "exceeded maximum TGeoNode depth\n";
202  }
203 
204  const TGeoVolume *v = path[depth]->GetVolume();
205  int nd = v->GetNdaughters();
206  for(int i = 0; i < nd; ++i){
207  path[deeper] = v->GetNode(i);
208  this->FindOpDet(path, deeper);
209  }
210 
211  }
212 
213  //......................................................................
214  void CryostatGeo::MakeOpDet(std::vector<const TGeoNode*>& path, int depth)
215  {
216  fOpDets.emplace_back(path, depth);
217  }
218 
219  //......................................................................
220  const OpDetGeo& CryostatGeo::OpDet(unsigned int iopdet) const
221  {
222  if(iopdet >= fOpDets.size()){
223  throw cet::exception("OpDetOutOfRange") << "Request for non-existant OpDet "
224  << iopdet;
225  }
226 
227  return fOpDets[iopdet];
228  }
229 
230 
231 
232  //......................................................................
233  // wiggle is 1+a small number to allow for rounding errors on the
234  // passed in world loc relative to the boundaries.
236  (double const worldLoc[3], double wiggle) const
237  {
238  geo::TPCID tpcid
239  = PositionToTPCID(geo::vect::makePointFromCoords(worldLoc), wiggle);
240  return tpcid? tpcid.TPC: geo::TPCID::InvalidID;
241  } // CryostatGeo::FindTPCAtPosition()
242 
243  //......................................................................
244  // wiggle is 1+a small number to allow for rounding errors on the
245  // passed in world loc relative to the boundaries.
247  (geo::Point_t const& point, double wiggle) const
248  {
249  geo::TPCGeo const* tpc = PositionToTPCptr(point, wiggle);
250  return tpc? tpc->ID(): geo::TPCID{};
251  }
252 
253  //......................................................................
254  // wiggle is 1+a small number to allow for rounding errors on the
255  // passed in world loc relative to the boundaries.
257  (geo::Point_t const& point, double wiggle) const
258  {
259  geo::TPCGeo const* tpc = PositionToTPCptr(point, wiggle);
260  if (!tpc) {
261  throw cet::exception("CryostatGeo")
262  << "Can't find any TPC for position " << point << " within " << ID()
263  << "\n";
264  }
265  return *tpc;
266  }
267 
268  //......................................................................
270  (geo::Point_t const& point, double wiggle) const
271  {
272  for (auto const& tpc: TPCs())
273  if (tpc.ContainsPosition(point, wiggle)) return &tpc;
274  return nullptr;
275  } // CryostatGeo::PositionToTPCptr()
276 
277 
278  //......................................................................
279  unsigned int CryostatGeo::MaxPlanes() const {
280  unsigned int maxPlanes = 0;
281  for (geo::TPCGeo const& TPC: fTPCs) {
282  unsigned int maxPlanesInTPC = TPC.Nplanes();
283  if (maxPlanesInTPC > maxPlanes) maxPlanes = maxPlanesInTPC;
284  } // for
285  return maxPlanes;
286  } // CryostatGeo::MaxPlanes()
287 
288  //......................................................................
289  unsigned int CryostatGeo::MaxWires() const {
290  unsigned int maxWires = 0;
291  for (geo::TPCGeo const& TPC: fTPCs) {
292  unsigned int maxWiresInTPC = TPC.MaxWires();
293  if (maxWiresInTPC > maxWires) maxWires = maxWiresInTPC;
294  } // for
295  return maxWires;
296  } // CryostatGeo::MaxWires()
297 
298  //......................................................................
299  double CryostatGeo::HalfWidth() const
300  {
301  return static_cast<TGeoBBox const*>(fVolume->GetShape())->GetDX();
302  }
303 
304  //......................................................................
305  double CryostatGeo::HalfHeight() const
306  {
307  return static_cast<TGeoBBox const*>(fVolume->GetShape())->GetDY();
308  }
309 
310  //......................................................................
311  double CryostatGeo::HalfLength() const
312  {
313  return static_cast<TGeoBBox const*>(fVolume->GetShape())->GetDZ();
314  }
315 
316  //......................................................................
317  void CryostatGeo::Boundaries(double* boundaries) const {
318  boundaries[0] = MinX();
319  boundaries[1] = MaxX();
320  boundaries[2] = MinY();
321  boundaries[3] = MaxY();
322  boundaries[4] = MinZ();
323  boundaries[5] = MaxZ();
324  } // CryostatGeo::CryostatBoundaries(double*)
325 
326 
327  //......................................................................
328  // Find the nearest opdet to point in this cryostat
329 
331  (geo::Point_t const& point) const
332  {
333  unsigned int iOpDet = GetClosestOpDet(point);
334  return
335  (iOpDet == std::numeric_limits<double>::max())? nullptr: &OpDet(iOpDet);
336  }
337 
338  //......................................................................
339  unsigned int CryostatGeo::GetClosestOpDet(geo::Point_t const& point) const {
340  unsigned int ClosestDet = std::numeric_limits<unsigned int>::max();
341  double ClosestDist = std::numeric_limits<double>::max();
342 
343  for(unsigned int o = 0U; o < NOpDet(); ++o) {
344  double const ThisDist = OpDet(o).DistanceToPoint(point);
345  if(ThisDist < ClosestDist) {
346  ClosestDist = ThisDist;
347  ClosestDet = o;
348  }
349  } // for
350  return ClosestDet;
351  } // CryostatGeo::GetClosestOpDet(geo::Point_t)
352 
353  //......................................................................
354  unsigned int CryostatGeo::GetClosestOpDet(double const* point) const
356 
357  //......................................................................
359 
360  // check that this is indeed a box
361  if (!dynamic_cast<TGeoBBox*>(Volume()->GetShape())) {
362  // at initialisation time we don't know yet our real ID
363  throw cet::exception("CryostatGeo") << "Cryostat is not a box! (it is a "
364  << Volume()->GetShape()->IsA()->GetName() << ")\n";
365  }
366 
367  // get the half width, height, etc of the cryostat
368  const double halflength = HalfLength();
369  const double halfwidth = HalfWidth();
370  const double halfheight = HalfHeight();
371 
373  toWorldCoords(LocalPoint_t{ -halfwidth, -halfheight, -halflength }),
374  toWorldCoords(LocalPoint_t{ +halfwidth, +halfheight, +halflength })
375  );
376 
377  } // CryostatGeo::InitCryoBoundaries()
378 
379 
380  //......................................................................
381 
382 } // namespace geo
CryostatGeo(std::vector< const TGeoNode * > &path, int depth)
Construct a representation of a single cryostat of the detector.
Definition: CryostatGeo.cxx:66
geo::TPCID const & ID() const
Returns the identifier of this TPC.
Definition: TPCGeo.h:278
void InitCryoBoundaries()
Fill the boundary information of the cryostat.
unsigned int GetClosestOpDet(geo::Point_t const &point) const
double HalfLength() const
Half height of the cryostat [cm].
TTree * t1
Definition: plottest35.C:26
Encapsulate the construction of a single cyostat.
unsigned int MaxPlanes() const
Returns the largest number of planes among the TPCs in this cryostat.
TGeoVolume * fVolume
Total volume of cryostat, called volCryostat in GDML file.
Definition: CryostatGeo.h:411
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:90
Silly utility to sort vectors indirectly.
Geometry information for a single TPC.
Definition: TPCGeo.h:37
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:93
void SortSubVolumes(geo::GeoObjectSorter const &sorter)
Apply sorting to the PlaneGeo objects.
Definition: TPCGeo.cxx:226
geo::TPCGeo const * PositionToTPCptr(geo::Point_t const &point, double wiggle) const
Returns a pointer to the TPC at specified location.
std::string fOpDetGeoName
Name of opdet geometry elements in gdml.
Definition: CryostatGeo.h:412
std::vector< OpDetGeo > fOpDets
List of opdets in this cryostat.
Definition: CryostatGeo.h:410
virtual void SortTPCs(std::vector< geo::TPCGeo * > &tgeo) const =0
void SortSubVolumes(geo::GeoObjectSorter const &sorter)
Method to sort TPCGeo objects.
std::string OpDetGeoName() const
Get name of opdet geometry element.
Definition: CryostatGeo.h:311
Int_t max
Definition: plot.C:27
void SortByPointers(Coll &coll, Sorter sorter)
Applies sorting indirectly, minimizing data copy.
geo::OpDetGeo const * GetClosestOpDetPtr(geo::Point_t const &point) const
const TGeoVolume * Volume() const
Pointer to ROOT&#39;s volume descriptor.
Definition: CryostatGeo.h:95
const OpDetGeo & OpDet(unsigned int iopdet) const
Return the iopdet&#39;th optical detector in the cryostat.
unsigned int TPCID_t
Type for the ID number.
Definition: geo_types.h:196
geo::Point3DBase_t< CryostatGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML cryostat frame.
Definition: CryostatGeo.h:65
double HalfWidth() const
Half width of the cryostat [cm].
double MinZ() const
Returns the world z coordinate of the start of the box.
TPCGeo const * TPCPtr(unsigned int itpc) const
Returns the TPC number itpc from this cryostat.
Definition: CryostatGeo.h:217
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:155
geo::CryostatID fID
ID of this cryostat.
Definition: CryostatGeo.h:413
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
unsigned int MaxWires() const
Returns the largest number of wires among the planes in this TPC.
Definition: TPCGeo.cxx:333
void FindOpDet(std::vector< const TGeoNode * > &path, unsigned int depth)
unsigned int MaxWires() const
Returns the largest number of wires among the TPCs in this cryostat.
void UpdateAfterSorting(geo::CryostatID cryoid)
Performs all needed updates after geometry has sorted the cryostats.
static bool DUNE_opdet_sort(const OpDetGeo *t1, const OpDetGeo *t2)
Definition: CryostatGeo.cxx:50
TTree * t2
Definition: plottest35.C:36
double MaxY() const
Returns the world y coordinate of the end of the box.
double HalfHeight() const
Half height of the cryostat [cm].
geo::TPCID::TPCID_t FindTPCAtPosition(double const worldLoc[3], double const wiggle) const
Returns the index of the TPC at specified location.
double DistanceToPoint(geo::Point_t const &point) const
Returns the distance of the specified point from detector center [cm].
Definition: OpDetGeo.cxx:114
auto const & TPCs() const
Returns a container with references to all TPCs.
Definition: CryostatGeo.h:210
void FindTPC(std::vector< const TGeoNode * > &path, unsigned int depth)
static bool opdet_sort(const OpDetGeo *t1, const OpDetGeo *t2)
Definition: CryostatGeo.cxx:32
TPCList_t fTPCs
List of tpcs in this cryostat.
Definition: CryostatGeo.h:409
void SetBoundaries(Coord_t x_min, Coord_t x_max, Coord_t y_min, Coord_t y_max, Coord_t z_min, Coord_t z_max)
Sets the boundaries in world coordinates as specified.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
unsigned int NOpDet() const
Number of optical detectors in this TPC.
Definition: CryostatGeo.h:295
double MaxZ() const
Returns the world z coordinate of the end of the box.
void MakeOpDet(std::vector< const TGeoNode * > &path, int depth)
static const TPCID_t InvalidID
Special code for an invalid ID.
Definition: geo_types.h:200
#define LOG_DEBUG(id)
geo::BoxBoundedGeo const & Boundaries() const
Returns boundaries of the cryostat (in centimetres).
Definition: CryostatGeo.h:99
TPCGeo const & PositionToTPC(geo::Point_t const &point, double wiggle) const
Returns the ID of the TPC at specified location.
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void MakeTPC(std::vector< const TGeoNode * > &path, int depth)
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:187
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Namespace collecting geometry-related classes utilities.
double MinY() const
Returns the world y coordinate of the start of the box.
geo::Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local cryostat frame to world frame.
Definition: CryostatGeo.h:337
geo::TPCID PositionToTPCID(geo::Point_t const &point, double wiggle) const
Returns the ID of the TPC at specified location.
void LocalToWorld(const double *opdet, double *world) const
Transform point from local optical detector frame to world frame.
Definition: OpDetGeo.h:103
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
The data type to uniquely identify a cryostat.
Definition: geo_types.h:120
geo::CryostatID const & ID() const
Returns the identifier of this cryostat.
Definition: CryostatGeo.h:116