This method will group TPCs into drift volumes (these are regions of the detector that share a common drift direction, common range of X coordinates, and common detector parameters such as wire pitch and wire angle).
239 if (!driftVolumeList.empty())
240 throw cet::exception(
"LArPandora")
241 <<
" LArPandoraGeometry::LoadGeometry --- detector geometry has already been loaded ";
243 typedef std::set<unsigned int> UIntSet;
246 art::ServiceHandle<geo::Geometry const> theGeometry;
248 const float wirePitchU(detType->WirePitchU());
249 const float wirePitchV(detType->WirePitchV());
250 const float wirePitchW(detType->WirePitchW());
251 const float maxDeltaTheta(0.01f);
254 for (
unsigned int icstat = 0; icstat < theGeometry->Ncryostats(); ++icstat) {
258 for (
unsigned int itpc1 = 0; itpc1 < theGeometry->NTPC(icstat); ++itpc1) {
259 if (cstatList.end() != cstatList.find(itpc1))
continue;
262 const geo::TPCGeo& theTpc1(theGeometry->TPC(itpc1, icstat));
263 cstatList.insert(itpc1);
265 const float wireAngleU(detType->WireAngleU(itpc1, icstat));
266 const float wireAngleV(detType->WireAngleV(itpc1, icstat));
267 const float wireAngleW(detType->WireAngleW(itpc1, icstat));
269 double localCoord1[3] = {0., 0., 0.};
270 double worldCoord1[3] = {0., 0., 0.};
273 float driftMinX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinX() :
274 (worldCoord1[0] - theTpc1.ActiveHalfWidth()));
275 float driftMaxX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxX() :
276 (worldCoord1[0] + theTpc1.ActiveHalfWidth()));
277 float driftMinY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinY() :
278 (worldCoord1[1] - theTpc1.ActiveHalfHeight()));
279 float driftMaxY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxY() :
280 (worldCoord1[1] + theTpc1.ActiveHalfHeight()));
281 float driftMinZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinZ() :
282 (worldCoord1[2] - 0.5f * theTpc1.ActiveLength()));
283 float driftMaxZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxZ() :
284 (worldCoord1[2] + 0.5f * theTpc1.ActiveLength()));
287 useActiveBoundingBox ?
288 (0.5 * (driftMinX + driftMaxX) - 0.25 * std::fabs(driftMaxX - driftMinX)) :
289 (worldCoord1[0] - 0.5 * theTpc1.ActiveHalfWidth()));
291 useActiveBoundingBox ?
292 (0.5 * (driftMinX + driftMaxX) + 0.25 * std::fabs(driftMaxX - driftMinX)) :
293 (worldCoord1[0] + 0.5 * theTpc1.ActiveHalfWidth()));
295 const bool isPositiveDrift(theTpc1.DriftDirection() ==
geo::kPosX);
298 tpcList.insert(itpc1);
301 tpcVolumeList.emplace_back(LArDaughterDriftVolume(icstat,
303 0.5f * (driftMaxX + driftMinX),
304 0.5f * (driftMaxY + driftMinY),
305 0.5f * (driftMaxZ + driftMinZ),
306 (driftMaxX - driftMinX),
307 (driftMaxY - driftMinY),
308 (driftMaxZ - driftMinZ)));
311 for (
unsigned int itpc2 = itpc1 + 1; itpc2 < theGeometry->NTPC(icstat); ++itpc2) {
312 if (cstatList.end() != cstatList.find(itpc2))
continue;
314 const geo::TPCGeo& theTpc2(theGeometry->TPC(itpc2, icstat));
316 if (theTpc1.DriftDirection() != theTpc2.DriftDirection())
continue;
318 const float dThetaU(detType->WireAngleU(itpc1, icstat) -
319 detType->WireAngleU(itpc2, icstat));
320 const float dThetaV(detType->WireAngleV(itpc1, icstat) -
321 detType->WireAngleV(itpc2, icstat));
322 const float dThetaW(detType->WireAngleW(itpc1, icstat) -
323 detType->WireAngleW(itpc2, icstat));
324 if (dThetaU > maxDeltaTheta || dThetaV > maxDeltaTheta || dThetaW > maxDeltaTheta)
327 double localCoord2[3] = {0., 0., 0.};
328 double worldCoord2[3] = {0., 0., 0.};
331 const float driftMinX2(useActiveBoundingBox ?
332 theTpc2.ActiveBoundingBox().MinX() :
333 (worldCoord2[0] - theTpc2.ActiveHalfWidth()));
334 const float driftMaxX2(useActiveBoundingBox ?
335 theTpc2.ActiveBoundingBox().MaxX() :
336 (worldCoord2[0] + theTpc2.ActiveHalfWidth()));
339 useActiveBoundingBox ?
340 (0.5 * (driftMinX2 + driftMaxX2) - 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
341 (worldCoord2[0] - 0.5 * theTpc2.ActiveHalfWidth()));
343 useActiveBoundingBox ?
344 (0.5 * (driftMinX2 + driftMaxX2) + 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
345 (worldCoord2[0] + 0.5 * theTpc2.ActiveHalfWidth()));
347 if ((min2 > max1) || (min1 > max2))
continue;
349 cstatList.insert(itpc2);
350 tpcList.insert(itpc2);
352 const float driftMinY2(useActiveBoundingBox ?
353 theTpc2.ActiveBoundingBox().MinY() :
354 (worldCoord2[1] - theTpc2.ActiveHalfHeight()));
355 const float driftMaxY2(useActiveBoundingBox ?
356 theTpc2.ActiveBoundingBox().MaxY() :
357 (worldCoord2[1] + theTpc2.ActiveHalfHeight()));
358 const float driftMinZ2(useActiveBoundingBox ?
359 theTpc2.ActiveBoundingBox().MinZ() :
360 (worldCoord2[2] - 0.5f * theTpc2.ActiveLength()));
361 const float driftMaxZ2(useActiveBoundingBox ?
362 theTpc2.ActiveBoundingBox().MaxZ() :
363 (worldCoord2[2] + 0.5f * theTpc2.ActiveLength()));
365 driftMinX = std::min(driftMinX, driftMinX2);
366 driftMaxX = std::max(driftMaxX, driftMaxX2);
367 driftMinY = std::min(driftMinY, driftMinY2);
368 driftMaxY = std::max(driftMaxY, driftMaxY2);
369 driftMinZ = std::min(driftMinZ, driftMinZ2);
370 driftMaxZ = std::max(driftMaxZ, driftMaxZ2);
372 tpcVolumeList.emplace_back(LArDaughterDriftVolume(icstat,
374 0.5f * (driftMaxX2 + driftMinX2),
375 0.5f * (driftMaxY2 + driftMinY2),
376 0.5f * (driftMaxZ2 + driftMinZ2),
377 (driftMaxX2 - driftMinX2),
378 (driftMaxY2 - driftMinY2),
379 (driftMaxZ2 - driftMinZ2)));
383 driftVolumeList.emplace_back(driftVolumeList.size(),
391 0.5f * (driftMaxX + driftMinX),
392 0.5f * (driftMaxY + driftMinY),
393 0.5f * (driftMaxZ + driftMinZ),
394 (driftMaxX - driftMinX),
395 (driftMaxY - driftMinY),
396 (driftMaxZ - driftMinZ),
397 (wirePitchU + wirePitchV + wirePitchW + 0.1f),
402 if (driftVolumeList.empty())
403 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- failed to find "
404 "any drift volumes in this detector geometry ";
Geometry information for a single TPC.
std::vector< LArDaughterDriftVolume > LArDaughterDriftVolumeList
LArPandoraDetectorType * GetDetectorType()
Factory class that returns the correct detector type interface.
Drift towards positive X values.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.