21 #include "messagefacility/MessageLogger/MessageLogger.h" 
   22 #include "cetlib_except/exception.h"  
   30 #include <type_traits>  
   40   template <
typename Coll, 
typename Op>
 
   41   auto transformCollection(Coll 
const& coll, Op op) {
 
   44       = std::decay_t<decltype(op(std::declval<typename Coll::value_type>()))>;
 
   46     std::vector<Result_t> transformed;
 
   49       (coll.begin(), coll.end(), std::back_inserter(transformed), op);
 
   62 namespace icarus::details {
 
   64   template <
typename SetColl> SetColl 
stableMerge(SetColl 
const& sets);
 
   67 template <
typename SetColl>
 
   76   using Coll_t = 
typename SetColl_t::value_type;
 
   77   using Value_t = 
typename Coll_t::value_type;
 
   91 template <
typename SetColl>
 
   97 template <
typename SetColl>
 
  101   if (std::find(coll.begin(), coll.end(), 
value) != coll.end()) 
return false;
 
  102   coll.push_back(value);
 
  108 template <
typename SetColl>
 
  113   for (
Value_t const& value: a) addNewValue(merged, value);
 
  114   for (
Value_t const& value: b) addNewValue(merged, value);
 
  120 template <
typename SetColl>
 
  125   for (
auto const& aElem: a) {
 
  126     if (std::find(b.begin(), b.end(), aElem) != b.end()) 
return true;
 
  133 template <
typename SetColl>
 
  139   for (
Coll_t const& set: sets) {
 
  144     Coll_t* mergeWith = 
nullptr;
 
  145     for (
Coll_t& mergedSet: mergedSets) {
 
  146       if (!
overlap(mergedSet, set)) 
continue;
 
  147       mergeWith = &mergedSet;
 
  152       *mergeWith = (mergeWith->size() < set.size())
 
  153         ? mergeColls(set, *mergeWith)
 
  154         : mergeColls(*mergeWith, set)
 
  158       mergedSets.push_back(set);
 
  167 template <
typename SetColl>
 
  180     nSets = mergedSets.size();
 
  182     mergedSets = mergePass(mergedSets);
 
  184   } 
while (mergedSets.size() != nSets);
 
  219   template <
typename T>
 
  235     (std::vector<PlaneColl_t> 
const& ROPplanes) 
const;
 
  239     (std::vector<PlaneColl_t> 
const& ROPs) 
const;
 
  244     (std::vector<PlaneColl_t> 
const& refROP, std::string 
const& logCategory)
 
  266   (std::vector<PlaneColl_t> 
const& ROPs) 
const 
  289     if (!FirstROPno.emplace(view, nextAvailable).second) 
continue;
 
  293       << 
" preferring numbers from " << nextAvailable
 
  294       << 
" (" << viewROPcounts.at(view) << 
" numbers reserved)";
 
  297     nextAvailable += viewROPcounts.at(view);
 
  308   (std::vector<PlaneColl_t> 
const& ROPplanes) 
const 
  314     if (
planes.empty()) 
continue;
 
  319       log << 
"A ROP spans multiple views:";
 
  322           << 
" (" << plane->ID() << 
")";
 
  326     ++(viewROPcounts[view]);
 
  330   return viewROPcounts;
 
  338   auto iPlane = planes.begin();
 
  339   auto const pend = planes.end();
 
  342   while (++iPlane != pend) {
 
  376     << 
"Building TPC sets and readout planes from " << Cryostats.size()
 
  379   fCryostats = &Cryostats;
 
  390   auto standaloneHorizontalWires = [](
geo::PlaneGeo const& plane)
 
  391     { 
return std::abs(plane.ThetaZ()) < 1
e-3; };
 
  393   std::vector<std::vector<PlaneColl_t>> AllPlanesInROPs
 
  394     = groupPlanesAndTPCs(standaloneHorizontalWires);
 
  396   std::vector<std::vector<std::vector<geo::TPCID>>> 
const AllTPCsInTPCsets
 
  397     = extractTPCsetsFromROPs(AllPlanesInROPs);
 
  403   fillTPCsInSet(AllTPCsInTPCsets);
 
  409     = groupPlanesIntoROPs(AllTPCsInTPCsets, std::move(AllPlanesInROPs));
 
  414   fillPlanesInROP(PlanesInProtoROPs);
 
  419   fillTPCtoTPCsetMap();
 
  425   assert(!fTPCsetCount.empty());
 
  426   assert(!fTPCsetTPCs .
empty());
 
  427   assert(!fROPcount   .
empty());
 
  428   assert(!fTPCtoTPCset.empty());
 
  429   assert(!fPlaneToROP .
empty());
 
  431     std::move(fTPCsetCount),
 
  432     std::move(fTPCsetTPCs ),
 
  433     std::move(fROPcount   ),
 
  434     std::move(fROPplanes  ),
 
  435     std::move(fTPCtoTPCset),
 
  436     std::move(fPlaneToROP )
 
  455 template <
typename Pred>
 
  457   (Pred standalonePlane)
 
  458   -> std::vector<std::vector<PlaneColl_t>>
 
  479   std::vector<std::vector<PlaneColl_t>> AllPlanesInROPs;
 
  485       log << 
"New group of " << planes.size() << 
" planes:";
 
  487         log << 
" <" << plane->ID() << 
">";
 
  500     std::vector<geo::PlaneGeo const*> 
planes;
 
  503         planes.push_back(&plane);
 
  507     std::vector<PlaneColl_t> protoGroups = groupPlanesByDriftCoord(planes);
 
  515     std::vector<PlaneColl_t> groupedPlanes;
 
  517       if (protoGroup.empty()) 
continue;
 
  520         if (standalonePlane(*plane)) {
 
  521           groupedPlanes.push_back({ plane });
 
  522           logPlanes(groupedPlanes.back());
 
  524         else group.push_back(plane);
 
  526       if (!group.empty()) {
 
  527         groupedPlanes.push_back(std::move(group));
 
  528         logPlanes(groupedPlanes.back());
 
  535     AllPlanesInROPs.push_back(std::move(groupedPlanes));
 
  539   return AllPlanesInROPs;
 
  546   -> std::vector<std::vector<PlaneColl_t>>
 
  547 { 
return groupPlanesAndTPCs([](
geo::PlaneGeo const&){ 
return false; }); }
 
  551 std::vector<std::vector<std::vector<geo::TPCID>>>
 
  559   std::vector<std::vector<std::vector<geo::TPCID>>> AllTPCsOnROPs;
 
  564   unsigned int& MaxTPCsets = fMaxTPCsets;
 
  569   for (std::vector<PlaneColl_t> 
const& planeGroupsInCryostat: groupedPlanes) {
 
  578     std::vector<std::vector<geo::TPCID>> TPCsOnROPs
 
  579       = transformCollection(planeGroupsInCryostat, extractTPCIDs);
 
  591       = std::max(MaxTPCsets, static_cast<unsigned int>(TPCsOnROPs.size()));
 
  592     AllTPCsOnROPs.push_back(std::move(TPCsOnROPs));
 
  595   mf::LogTrace(
"ICARUSChannelMapAlg")
 
  596     << 
"The maximum number of TPC sets in any cryostat is " << MaxTPCsets;
 
  598   return AllTPCsOnROPs;
 
  619   unsigned int const MaxTPCsets = fMaxTPCsets;
 
  625   fTPCsetCount.clear();
 
  626   fTPCsetCount.resize(AllTPCsOnROPs.size(), 0U);
 
  627   std::vector<unsigned int>& TPCsetCount = fTPCsetCount;
 
  629   fTPCsetTPCs.resize(AllTPCsOnROPs.size(), MaxTPCsets); 
 
  638     TPCsetCount[c] = TPCsets.size();
 
  639     mf::LogTrace(
"ICARUSChannelMapAlg")
 
  640       << 
"Cryostat " << cryo.
ID() << 
" has " << TPCsetCount[c] << 
" TPC sets";
 
  646       TPCsetTPCs[tpcsetid] = transformCollection(
 
  647         TPCIDs, [&cryo](
geo::TPCID const& tpcid){ 
return &(cryo.
TPC(tpcid)); }
 
  651         auto const& 
TPCs = TPCsetTPCs[tpcsetid];
 
  652         mf::LogTrace log(
"ICARUSChannelMapAlg");
 
  653         log << tpcsetid << 
" has " << 
TPCs.size() << 
" TPCs:";
 
  665   std::vector<std::vector<PlaneColl_t>>&& AllPlanesInROPs
 
  679   assert(!fTPCsetTPCs.empty());
 
  686     (TPCsetTPCs.dimSize<0U>(), TPCsetTPCs.dimSize<1U>());
 
  687   unsigned int& MaxROPs = fMaxROPs;
 
  699     std::vector<std::vector<geo::TPCID>> 
const& TPCsets = AllTPCsOnROPs[c];
 
  700     for (std::vector<geo::PlaneGeo const*>& ROPplanes: ROPs) {
 
  701       std::vector<geo::TPCID> 
const ROPTPCIDs = extractTPCIDs(ROPplanes);
 
  708         if (!isROPinTPCset(ROPTPCIDs, TPCset)) 
continue;
 
  715         log << 
"Candidate ROP did not match any TPC set.";
 
  716         log << 
"\nROP planes:";
 
  718           log << 
" (" << plane->ID() << 
")";
 
  719         log << 
"\nAvailable TPC sets (" << TPCsets.size() << 
"):";
 
  723           log << 
"\n - " << tpcsetid << 
", " << TPCset.size() << 
" TPC's:";
 
  724           for (
geo::TPCID const& tpcid: TPCset) log << 
" (" << tpcid << 
")";
 
  732       auto& TPCsetROPs = PlanesInProtoROPs[tpcsetid];
 
  733       TPCsetROPs.push_back(std::move(ROPplanes));
 
  734       MaxROPs = std::max(MaxROPs, static_cast<unsigned int>(TPCsetROPs.size()));
 
  739   AllPlanesInROPs.clear(); 
 
  743       << 
"Encountered " << nErrors
 
  744       << 
" errors while assigning TPC sets to ROPs (see error messages above)\n" 
  749     << 
"The maximum number of readout planes in any TPC set is " << MaxROPs;
 
  751   return PlanesInProtoROPs;
 
  765   assert(!fTPCsetTPCs.empty());
 
  766   assert(!fTPCsetCount.empty());
 
  767   assert(fMaxROPs > 0U);
 
  772   auto const& TPCsetTPCs = fTPCsetTPCs;
 
  773   auto const& TPCsetCount = fTPCsetCount;
 
  779   fROPcount.resize(TPCsetTPCs.dimSize<0U>(), TPCsetTPCs.dimSize<1U>(), 0U);
 
  781     (TPCsetTPCs.dimSize<0U>(), TPCsetTPCs.dimSize<1U>(), fMaxROPs); 
 
  783   auto& ROPcount = fROPcount;
 
  784   auto& ROPplanes = fROPplanes;
 
  789   std::vector<PlaneColl_t> 
const sortedTPCset0
 
  790     = sortByNormalCoordinate(PlanesInProtoROPs[{ 0, 0 }]);
 
  803       std::vector<PlaneColl_t> 
const& ROPs = PlanesInProtoROPs[tpcsetid];
 
  805       ROPcount[tpcsetid] = ROPs.size();
 
  807       ROPIDdispatcher.setTPCset(tpcsetid);
 
  814           log << 
"Readout plane " << ropid << 
" assigned with " << planes.size()
 
  817             log << 
" (" << plane->ID() << 
")";
 
  819         if (!ROPplanes[ropid].
empty()) {
 
  827             << 
"Logic error: ROPID " << ropid
 
  828             << 
" has already been assigned!\n";
 
  830         ROPplanes[ropid] = std::move(planes);
 
  846   assert(!fCryostats->empty());
 
  847   assert(!fTPCsetTPCs.empty());
 
  852   auto const& Cryostats = *fCryostats;
 
  853   auto const& TPCsetTPCs = fTPCsetTPCs;
 
  858   auto const [ NCryostats, MaxTPCs ]
 
  859     = geo::details::extractMaxGeometryElements<2U>(Cryostats);
 
  862     << 
"Detected " << NCryostats << 
" cryostats." 
  863     << 
"\nDetected at most " << MaxTPCs << 
" TPCs per cryostat." 
  865   fTPCtoTPCset.resize(NCryostats, MaxTPCs, {});
 
  868     : util::counter<geo::CryostatID::CryostatID_t>(TPCsetTPCs.dimSize<0>())
 
  872     for (
auto s: util::counter<readout::TPCsetID::TPCsetID_t>(TPCsetTPCs.dimSize<1>()))
 
  878         fTPCtoTPCset[
TPC->ID()] = sid;
 
  896   assert(!fCryostats->empty());
 
  897   assert(!fROPplanes.empty());
 
  902   auto const& Cryostats = *fCryostats;
 
  903   auto const& ROPplanes = fROPplanes;
 
  908   auto const [ NCryostats, MaxTPCs, MaxPlanes ]
 
  909     = geo::details::extractMaxGeometryElements<3U>(Cryostats);
 
  912     << 
"Detected " << NCryostats << 
" cryostats." 
  913     << 
"\nDetected at most " << MaxTPCs << 
" TPCs per cryostat." 
  914     << 
"\nDetected at most " << MaxPlanes << 
" planes per TPC." 
  916   fPlaneToROP.resize(NCryostats, MaxTPCs, MaxPlanes, {});
 
  919     : util::counter<geo::CryostatID::CryostatID_t>(ROPplanes.dimSize<0>())
 
  923     for (
auto s: util::counter<readout::TPCsetID::TPCsetID_t>(ROPplanes.dimSize<1>()))
 
  926       for (
auto r: util::counter<readout::ROPID::ROPID_t>(ROPplanes.dimSize<2>()))
 
  931           assert(plane && plane->ID());
 
  932           fPlaneToROP[plane->ID()] = rid;
 
  933           MF_LOG_TRACE(
fLogCategory) << plane->ID() << 
" => " << rid;
 
  947   (std::vector<PlaneColl_t> 
const& ROPs) 
const -> std::vector<PlaneColl_t>
 
  958   assert(!ROPs.empty()); 
 
  960   checkNormalDirection(ROPs); 
 
  963   auto sortedROPs { ROPs };
 
  964   std::stable_sort(sortedROPs.begin(), sortedROPs.end(),
 
  979   (std::vector<PlaneColl_t> 
const& ROPs) 
const 
  985   if (ROPs.empty()) 
return;
 
  987   auto iROP = ROPs.begin();
 
  988   assert(!iROP->empty()); 
 
  998         << 
"icarus::details::ROPandTPCsetBuildingAlg::checkNormalDirection(): " 
  999         "ROP must contain planes.\n" 
 1003       if (comp.equal(normDir, plane->GetNormalDirection<
geo::Vector_t>()))
 
 1007         << 
"icarus::details::ROPandTPCsetBuildingAlg::checkNormalDirection(): " 
 1008         " plane " << plane->ID()
 
 1009         << 
" has normal " << plane->GetNormalDirection<
geo::Vector_t>()
 
 1010         << 
", " << normDir << 
" (as for " << pFirstPlane->
ID()
 
 1021 template <
typename PlaneColl>
 
 1024   -> std::vector<PlaneColl_t>
 
 1026   std::map<double, PlaneColl_t> groupedByDrift;
 
 1039     double const planeD = plane->GetCenter<
geo::Point_t>().Dot(driftDir);
 
 1042     auto iGroup = groupedByDrift.lower_bound(planeD);
 
 1048     if ((iGroup != groupedByDrift.end())
 
 1049       && (iGroup->first - planeD <= tolerance))
 
 1051       iGroup->second.push_back(plane);
 
 1060     groupedByDrift.emplace_hint
 
 1061       (iGroup, planeD + tolerance / 2.0, 
PlaneColl_t({ plane }));
 
 1069   std::vector<PlaneColl_t> groups;
 
 1070   groups.reserve(groupedByDrift.size());
 
 1071   for (
auto&& 
group: groupedByDrift)
 
 1072     groups.push_back(std::move(std::get<1U>(
group)));
 
 1080   (std::vector<geo::PlaneGeo const*> 
const& planes)
 
 1082   return transformCollection(planes,
 
 1095     if (!plane) 
continue;
 
 1097     auto const fromPlane
 
 1102     else if (r != fromPlane)
 
 1112   std::vector<geo::TPCID> 
const& ROPTPCIDs,
 
 1113   std::vector<geo::TPCID> 
const& TPCsetTPCIDs
 
 1119       if (
TPC != ROPTPC) 
continue;
 
 1123     if (found) 
continue;
 
void reset()
Sets all the elements to a default-constructed value_type. 
 
typename Coll_t::value_type Value_t
 
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space. 
 
readout::TPCsetDataContainer< TPCColl_t > fTPCsetTPCs
Output: TPC's in each TPC set. 
 
void fillTPCsInSet(std::vector< std::vector< std::vector< geo::TPCID >>> const &AllTPCsOnROPs)
Extracts the final set of TPC sets. 
 
static std::string ViewName(geo::View_t view)
Returns the name of the specified view. 
 
static bool addNewValue(Coll_t &coll, Value_t const &value)
 
Container with one element per readout TPC set. 
 
icarus::details::PlaneColl_t PlaneColl_t
 
Classes identifying readout-related concepts. 
 
static constexpr ROPID_t getInvalidID()
Return the value of the invalid ROP ID as a r-value. 
 
Definition of util::enumerate(). 
 
enum geo::_plane_proj View_t
Enumerate the possible plane projections. 
 
unsigned int ROPID_t
Type for the ID number. 
 
unsigned int fMaxTPCsets
Highest number of TPC sets in any cryostat. 
 
readout::TPCsetDataContainer< unsigned int > fROPcount
Output: number of readout planes in each TPC set. 
 
BEGIN_PROLOG opflashtpc1 TPCs
 
unsigned short TPCsetID_t
Type for the ID number. 
 
Geometry information for a single TPC. 
 
Class identifying a set of TPC sharing readout channels. 
 
DataByView_t< readout::ROPID::ROPID_t > fAvailableROPno
The first available ROP number for each view. 
 
std::map< geo::View_t, T > DataByView_t
Type of collection of T by view. 
 
static std::vector< std::vector< geo::PlaneGeo const * > > groupPlanesByDriftCoord(PlaneColl const &planes, double tolerance=0.1)
Returns the planes grouped by their drift coordinate. 
 
std::vector< geo::CryostatGeo > CryostatList_t
Type of list of cryostats. 
 
std::string const fLogCategory
Log category name for messages. 
 
std::vector< std::vector< PlaneColl_t > > groupPlanesAndTPCs()
Extracts composition of all readout planes. 
 
void fillTPCtoTPCsetMap()
Creates the map from each TPC to its TPC set. 
 
SetColl stableMerge(SetColl const &sets)
 
void setTPCset(readout::TPCsetID const &TPCset)
Rests the object to work with the specified TPC set next. 
 
Geometry information for a single cryostat. 
 
Vector GetNormalDirection() const 
Returns the direction normal to the plane. 
 
static bool overlap(Coll_t const &a, Coll_t const &b)
 
DataByView_t< unsigned int > ViewROPcounts(std::vector< PlaneColl_t > const &ROPplanes) const 
Returns the number of planes with each view. 
 
Class for approximate comparisons. 
 
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration. 
 
std::vector< unsigned int > fTPCsetCount
Output: number of TPC sets in each cryostat. 
 
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size. 
 
auto vector(Vector const &v)
Returns a manipulator which will print the specified array. 
 
DataByView_t< readout::ROPID::ROPID_t > const fFirstROPno
The first ROP number for each view. 
 
static readout::ROPID::ROPID_t ROPnumberFromPlanes(PlaneColl_t const &planes)
Returns ROP number matching the plane number shared by all planes. 
 
ROPnumberDispatcher(std::vector< PlaneColl_t > const &refROP, std::string const &logCategory)
Constructor: uses refROP as reference to assign number ranges to views. 
 
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object. 
 
static std::vector< geo::TPCID > extractTPCIDs(std::vector< geo::PlaneGeo const * > const &planes)
Returns a collection with a TPC ID for each plane in the list of planes. 
 
std::vector< PlaneColl_t > sortByNormalCoordinate(std::vector< PlaneColl_t > const &planes) const 
Returns the planes sorted by decreasing normal coordinate. 
 
void fillPlanesInROP(readout::TPCsetDataContainer< std::vector< PlaneColl_t >> const &PlanesInProtoROPs)
Builds final readout plane information. 
 
readout::TPCsetID fTPCset
The TPC set being served. 
 
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
 
std::vector< std::vector< std::vector< geo::TPCID > > > extractTPCsetsFromROPs(std::vector< std::vector< PlaneColl_t >> const &planes)
Extracts all the TPC sets covered by any of the plane groups. 
 
readout::TPCsetDataContainer< std::vector< PlaneColl_t > > groupPlanesIntoROPs(std::vector< std::vector< std::vector< geo::TPCID >>> const &AllTPCsOnROPs, std::vector< std::vector< PlaneColl_t >> &&AllPlanesInROPs)
Assigns each of the readout planes to a TPC set. 
 
constexpr Vector Xaxis()
Returns a x axis vector of the specified type. 
 
std::tuple< std::vector< unsigned int >, readout::TPCsetDataContainer< TPCColl_t >, readout::TPCsetDataContainer< unsigned int >, readout::ROPDataContainer< PlaneColl_t >, geo::TPCDataContainer< readout::TPCsetID >, geo::PlaneDataContainer< readout::ROPID > > ResultsBase_t
Full group of results of the algorithm. 
 
Algorithm discovering TPC sets and readout planes for ICARUS. 
 
static SetColl_t merge(SetColl_t const &sets)
 
static SetColl_t mergePass(SetColl_t const &sets)
 
std::vector< geo::PlaneGeo const * > PlaneColl_t
Type of collection of planes (pointers to geo::PlaneGeo). 
 
Algorithm assigning IDs to readout planes. 
 
The data type to uniquely identify a TPC. 
 
Definition of data types for geometry description. 
 
typename SetColl_t::value_type Coll_t
 
Class identifying a set of planes sharing readout channels. 
 
static geo::View_t ROPview(PlaneColl_t const &planes)
Returns the view of the planes (geo::kUnknown if mixed or none). 
 
unsigned int fMaxROPs
Highest number of ROPs in any TPC set. 
 
constexpr TPCID const & asTPCID() const 
Conversion to TPCID (for convenience of notation). 
 
geo::PlaneDataContainer< readout::ROPID > fPlaneToROP
Output: the ROP each wire plane belongs to. 
 
readout::ROPDataContainer< PlaneColl_t > fROPplanes
Output: planes in each of the readout plane. 
 
unsigned int CryostatID_t
Type for the ID number. 
 
geo::TPCDataContainer< readout::TPCsetID > fTPCtoTPCset
Output: the TPC set each TPC belongs to. 
 
DataByView_t< readout::ROPID::ROPID_t > PreferredROPrangesByView(std::vector< PlaneColl_t > const &ROPs) const 
Returns the fist ROP number for each view in ROP. 
 
double DistanceFromPlane(geo::Point_t const &point) const 
Returns the distance of the specified point from the wire plane. 
 
const TPCGeo & TPC(unsigned int itpc) const 
Return the itpc'th TPC in the cryostat. 
 
then echo File list $list not found else cat $list while read file do echo $file sed s
 
static Coll_t mergeColls(Coll_t const &a, Coll_t const &b)
 
geo::PlaneID const & ID() const 
Returns the identifier of this plane. 
 
Functions pulling in STL customization if available. 
 
readout::ROPID assignID(PlaneColl_t const &ROP)
Returns the next available ID for the specified ROP. 
 
void fillPlaneToROPmap()
Creates the map from each wire plane to its readout plane. 
 
static bool isROPinTPCset(std::vector< geo::TPCID > const &ROPTPCIDs, std::vector< geo::TPCID > const &TPCsetTPCIDs)
Returns whether all the TPCs covered by a ROP are in a given TPC set. 
 
void clear()
Destroys all the result data members. 
 
Results_t run(geo::GeometryData_t::CryostatList_t const &Cryostats)
Runs the algorithm as configured from start to end. 
 
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space. 
 
void checkNormalDirection(std::vector< PlaneColl_t > const &planes) const 
Throws an exception if planes do not share the same normal direction. 
 
bool empty(FixedBins< T, C > const &) noexcept
 
The data type to uniquely identify a cryostat. 
 
geo::CryostatID const & ID() const 
Returns the identifier of this cryostat.