All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
larsim/larsim/Simulation/PhotonVoxels.cxx
Go to the documentation of this file.
1 /**
2  * @file larsim/Simulation/PhotonVoxels.cxx
3  * @brief Definitions of voxel data structures: implementation.
4  * @see larsim/Simulation/PhotonVoxels.h
5  */
6 
7 // library header
10 
11 // C++ standard libraries
12 #include <algorithm> // std::min(), std::max()
13 #include <cmath> // std::abs(), std::floor()
14 #include <stdexcept> // std::runtime_error
15 #include <string>
16 
17 namespace sim {
18 
19  //----------------------------------------------------------------------------
20  // PhotonVoxelDef class
21  //----------------------------------------------------------------------------
23  double xMax,
24  int xN,
25  double yMin,
26  double yMax,
27  int yN,
28  double zMin,
29  double zMax,
30  int zN)
31  : fLowerCorner(xMin, yMin, zMin)
32  , fUpperCorner(xMax, yMax, zMax)
33  , fxSteps(xN)
34  , fySteps(yN)
35  , fzSteps(zN)
36  {}
37 
38  //----------------------------------------------------------------------------
39  std::array<unsigned int, 3U>
41  {
42  // BUG the double brace syntax is required to work around clang bug 21629
43  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
44  return {{fxSteps, fySteps, fzSteps}};
45  }
46 
47  //----------------------------------------------------------------------------
48  bool
50  {
51  return ((GetRegionUpperCorner() == right.GetRegionUpperCorner()) &&
53  (GetSteps() == right.GetSteps()));
54  }
55 
56  //----------------------------------------------------------------------------
57  unsigned int
59  {
60  return fxSteps * fySteps * fzSteps;
61  }
62 
63  //----------------------------------------------------------------------------
64  int
65  PhotonVoxelDef::GetVoxelID(double const* Position) const
66  {
67  return GetVoxelIDImpl(geo::vect::makeFromCoords<geo::Point_t>(Position));
68  }
69 
70  //----------------------------------------------------------------------------
71  std::optional<std::array<sim::PhotonVoxelDef::NeiInfo, 8U>>
73  {
74  if (!isInside(v)) return {};
75 
76  std::array<sim::PhotonVoxelDef::NeiInfo, 8U> ret;
77 
78  // Position in voxel coordinates including floating point part
79  auto const rStepD = GetVoxelStepCoordsUnchecked(v);
80 
81  // The neighbours are the 8 corners of a cube around this point
82  std::size_t iNeigh = 0U;
83  for (int dx : {0, 1}) {
84  for (int dy : {0, 1}) {
85  for (int dz : {0, 1}) {
86  // The full 3D step
87  const int dr[3] = {dx, dy, dz};
88 
89  // The integer-only position of the current corner
90  int rStepI[3];
91  for (int d = 0; d < 3; ++d) {
92  // Round down to get the "lower left" corner
93  rStepI[d] = int(rStepD[d]);
94  // Ensure we'll stay in-bounds
95  rStepI[d] = std::max(0, rStepI[d]);
96  rStepI[d] = std::min(rStepI[d], int(GetSteps()[d]) - 2);
97  // Adjust to the corner we're actually considering
98  rStepI[d] += dr[d];
99  }
100 
101  double w = 1;
102  for (int d = 0; d < 3; ++d) {
103  // These expressions will interpolate when between the 8 corners,
104  // and extrapolate in the half-voxel space around the edges.
105  if (dr[d] == 0)
106  w *= 1 + rStepI[d] - rStepD[d];
107  else
108  w *= 1 - rStepI[d] + rStepD[d];
109  }
110 
111  const int id = (rStepI[0] + rStepI[1] * (fxSteps) + rStepI[2] * (fxSteps * fySteps));
112 
113  ret[iNeigh++] = {id, w};
114  }
115  }
116  }
117 
118  // Sanity check the weights sum to 1
119  double wSum = 0;
120  for (const NeiInfo& n : ret)
121  wSum += n.weight;
122  if (std::abs(wSum - 1) > 1e-3) {
123  std::string msg = "PhotonVoxelDef::GetNeighboringVoxelIDs():"
124  " Weights sum to " +
125  std::to_string(wSum) +
126  " (should be 1)."
127  " Weights are:";
128  for (const NeiInfo& n : ret) {
129  msg += ' ';
130  msg += std::to_string(n.weight);
131  }
132  throw std::runtime_error(msg);
133  }
134  return {ret};
135  }
136 
137  //----------------------------------------------------------------------------
140  {
141  // float TempID = (float) ID;
142 
143  // Decompose ID into steps in each direction
144  int xStep = ID % fxSteps;
145  int yStep = ((ID - xStep) / fxSteps) % fySteps;
146  int zStep = ((ID - xStep - (yStep * fxSteps)) / (fySteps * fxSteps)) % fzSteps;
147 
148  auto const VoxelSize = GetVoxelSize<geo::Vector_t>();
149 
150  double const xMin = VoxelSize.X() * (xStep) + fLowerCorner.X();
151  double const xMax = VoxelSize.X() * (xStep + 1) + fLowerCorner.X();
152  double const yMin = VoxelSize.Y() * (yStep) + fLowerCorner.Y();
153  double const yMax = VoxelSize.Y() * (yStep + 1) + fLowerCorner.Y();
154  double const zMin = VoxelSize.Z() * (zStep) + fLowerCorner.Z();
155  double const zMax = VoxelSize.Z() * (zStep + 1) + fLowerCorner.Z();
156 
157  return PhotonVoxel(xMin, xMax, yMin, yMax, zMin, zMax);
158  }
159 
160  //----------------------------------------------------------------------------
161  bool
163  {
164  return ((ID >= 0) && (static_cast<unsigned int>(ID) < GetNVoxels()));
165  }
166 
167  std::array<int, 3U>
169  {
170  std::array<int, 3U> ReturnVector;
171  ReturnVector[0] = ID % fxSteps;
172  ReturnVector[1] = ((ID - ReturnVector[0]) / fxSteps) % fySteps;
173  ReturnVector[2] =
174  ((ID - ReturnVector[0] - (ReturnVector[1] * fxSteps)) / (fySteps * fxSteps)) % fzSteps;
175  return ReturnVector;
176  }
177 
178  //----------------------------------------------------------------------------
179  std::array<double, 3U>
181  {
182 
183  auto const span = fUpperCorner - fLowerCorner;
184  auto const relPos = p - fLowerCorner;
185 
186  // BUG the double brace syntax is required to work around clang bug 21629
187  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
188  return {{(relPos.X() / span.X()) * fxSteps,
189  (relPos.Y() / span.Y()) * fySteps,
190  (relPos.Z() / span.Z()) * fzSteps}};
191  } // PhotonVoxelDef::GetVoxelStepCoordsUnchecked()
192 
193  //----------------------------------------------------------------------------
194  int
196  {
197  if (!isInside(p)) return -1;
198 
199  auto const stepCoords = GetVoxelStepCoordsUnchecked(p);
200 
201  // figure out how many steps this point is in the x,y,z directions;
202  // `p` is guaranteed to be in the mapped volume by the previous check
203  int xStep = static_cast<int>(stepCoords[0]);
204  int yStep = static_cast<int>(stepCoords[1]);
205  int zStep = static_cast<int>(stepCoords[2]);
206 
207  // if within bounds, generate the voxel ID
208  return (xStep + yStep * (fxSteps) + zStep * (fxSteps * fySteps));
209  }
210 
211  //----------------------------------------------------------------------------
212  bool
214  geo::Point_t const& lower,
215  geo::Point_t const& upper)
216  {
217  return isInsideRange(point.X(), lower.X(), upper.X()) &&
218  isInsideRange(point.Y(), lower.Y(), upper.Y()) &&
219  isInsideRange(point.Z(), lower.Z(), upper.Z());
220  }
221 
222  bool
223  PhotonVoxelDef::isInsideRange(double value, double lower, double upper)
224  {
225 
226  return (value >= lower) && (value < upper);
227 
228  } // PhotonVoxelDef::isInsideRange()
229 
230  //----------------------------------------------------------------------------
231 
232  std::ostream&
233  operator<<(std::ostream& out, sim::PhotonVoxelDef const& voxelDef)
234  {
235 
236  auto const& lower = voxelDef.GetRegionLowerCorner();
237  auto const& upper = voxelDef.GetRegionUpperCorner();
238  auto const& steps = voxelDef.GetSteps();
239  auto const& stepSize = voxelDef.GetVoxelSize();
240 
241  out << "Volume " << voxelDef.GetVolumeSize() << " cm^3 split in " << voxelDef.GetNVoxels()
242  << " voxels:"
243  << "\n - x axis: [ " << lower.X() << " ; " << upper.X() << " ] split in " << steps[0]
244  << "x " << stepSize.X() << " cm steps"
245  << "\n - y axis: [ " << lower.Y() << " ; " << upper.Y() << " ] split in " << steps[1]
246  << "x " << stepSize.Y() << " cm steps"
247  << "\n - z axis: [ " << lower.Z() << " ; " << upper.Z() << " ] split in " << steps[2]
248  << "x " << stepSize.Z() << " cm steps"
249  << "\n";
250 
251  return out;
252  } // operator<< (sim::PhotonVoxelDef)
253 
254  //----------------------------------------------------------------------------
255 
256 } // namespace sim
Vector GetVoxelSize() const
Returns a vector describing the span of a single voxel in x, y an z [cm].
walls no right
Definition: selectors.fcl:105
int GetVoxelIDImpl(geo::Point_t const &p) const
std::array< unsigned int, 3U > GetSteps() const
Returns the number of voxels along each of the three dimensions.
pdgs p
Definition: selectors.fcl:22
bool operator==(const PhotonVoxelDef &rhs) const
Representation of a region of space diced into voxels.
std::array< double, 3U > GetVoxelStepCoordsUnchecked(geo::Point_t const &p) const
Returns the coordinates of the cvoxel containing p in step units.
int GetVoxelID(Point const &p) const
Returns the ID of the voxel containing p, or -1 if none.
unsigned int GetNVoxels() const
Returns the total number of voxels in the volume.
bool isInside(geo::Point_t const &p) const
Returns whether point p is inside the region (upper border excluded).
Definitions of voxel data structures.
T abs(T value)
decltype(auto) GetRegionLowerCorner() const
Returns the volume vertex (type Point) with the lowest coordinates.
static bool isInsideRange(double value, double lower, double upper)
Utilities to extend the interface of geometry vectors.
decltype(auto) GetRegionUpperCorner() const
Returns the volume vertex (type Point) with the highest coordinates.
std::array< int, 3U > GetVoxelCoords(int ID) const
Representation of a single small volume (voxel).
std::string to_string(WindowPattern const &pattern)
do i e
Vector GetVolumeSize() const
Returns a vector describing the full span in x, y an z [cm].
temporary value
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:184
std::ostream & operator<<(std::ostream &output, const LArVoxelData &data)
static bool isInsideVolume(geo::Point_t const &point, geo::Point_t const &lower, geo::Point_t const &upper)
std::optional< std::array< NeiInfo, 8U > > GetNeighboringVoxelIDsImpl(geo::Point_t const &v) const