10 #include "test/Geometry/GeometryTestAlg.h" 35 #include "cetlib_except/exception.h" 40 #include "TGeoManager.h" 41 #include "TStopwatch.h" 43 #include "TGeoVolume.h" 45 #include "Math/GenVector/DisplacementVector2D.h" 46 #include "Math/GenVector/DisplacementVector3D.h" 47 #include "Math/GenVector/PositionVector3D.h" 48 #include "RtypesCore.h" 49 #include "TGeoMaterial.h" 50 #include "TGeoMatrix.h" 51 #include "TGeoShape.h" 52 #include "TObjArray.h" 69 #include <initializer_list> 75 std::ostream&
operator<< (std::ostream& out, TVector3
const& v) {
76 out <<
"( " << v.X() <<
" ; " << v.Y() <<
" ; " << v.Z() <<
" )";
80 std::ostream&
operator<< (std::ostream& out, TVector2
const& v) {
81 out <<
"( " << v.X() <<
" ; " << v.Y() <<
" )";
91 for (
auto const& e_category: e.history())
92 if (e_category == cat)
return true;
98 template <
typename Vector>
100 if (v == geo::Xaxis<Vector>())
return "x";
101 if (v == geo::Yaxis<Vector>())
return "y";
102 if (v == geo::Zaxis<Vector>())
return "z";
103 if (v == -geo::Xaxis<Vector>())
return "-x";
104 if (v == -geo::Yaxis<Vector>())
return "-y";
105 if (v == -geo::Zaxis<Vector>())
return "-z";
106 std::ostringstream sstr;
120 , fDisableValidWireIDcheck( pset.
get<
bool>(
"DisableWireBoundaryCheck", false) )
121 , fExpectedWirePitches( pset.
get<
std::
vector<double>>(
"ExpectedWirePitches", {}) )
126 std::vector<std::string> NonFatalErrors(pset.get<std::vector<std::string>>
127 (
"ForgiveExceptions", std::vector<std::string>()));
128 std::copy(NonFatalErrors.begin(), NonFatalErrors.end(),
136 "-CheckOverlaps",
"-ThoroughCheck",
"-PrintWires" 141 fRunTests.
Parse(pset.get<std::vector<std::string>>(
"RunTests", {}));
143 std::ostringstream sstr;
146 mf::LogInfo(
"GeometryTestAlg") <<
"Test selection:" << sstr.str();
156 <<
"GeometryTestAlg not configured: no valid geometry provided.\n";
177 MF_LOG_INFO(
"GeometryTest") <<
"detector introduction:";
183 MF_LOG_INFO(
"GeometryTest") <<
"test for overlaps ...";
184 gGeoManager->CheckOverlaps(1
e-5);
185 gGeoManager->PrintOverlaps();
186 if (!gGeoManager->GetListOfOverlaps()->IsEmpty()) {
188 << gGeoManager->GetListOfOverlaps()->GetSize()
189 <<
" overlaps found in geometry during overlap test!";
196 MF_LOG_INFO(
"GeometryTest") <<
"thorough geometry test ...";
197 gGeoManager->CheckGeometryFull();
198 if (!gGeoManager->GetListOfOverlaps()->IsEmpty()) {
200 << gGeoManager->GetListOfOverlaps()->GetSize()
201 <<
" overlaps found in geometry during thorough test!";
208 MF_LOG_INFO(
"GeometryTest") <<
"test Cryostat methods ...";
214 MF_LOG_INFO(
"GeometryTest") <<
"test FindAllVolumes method ...";
220 MF_LOG_INFO(
"GeometryTest") <<
"test plane directions...";
226 MF_LOG_INFO(
"GeometryTest") <<
"test wire orientations...";
232 MF_LOG_INFO(
"GeometryTest") <<
"test channel to ROP and back ...";
238 MF_LOG_INFO(
"GeometryTest") <<
"test channel to plane wire and back ...";
244 MF_LOG_INFO(
"GeometryTest") <<
"test find plane centers...";
250 MF_LOG_INFO(
"GeometryTest") <<
"test PlaneGeo::WireCoordinate...";
256 MF_LOG_INFO(
"GeometryTest") <<
"test wire parallelism...";
262 MF_LOG_INFO(
"GeometryTest") <<
"test plane point decomposition...";
268 MF_LOG_INFO(
"GeometryTest") <<
"test PlaneGeo::PointProjection...";
274 MF_LOG_INFO(
"GeometryTest") <<
"testWireCoordAngle...";
293 MF_LOG_INFO(
"GeometryTest") <<
"testNearestWire...";
299 MF_LOG_INFO(
"GeometryTest") <<
"testWireIntersection...";
301 MF_LOG_INFO(
"GeometryTest") <<
"testWireIntersection complete";
305 MF_LOG_INFO(
"GeometryTest") <<
"testThirdPlane...";
311 MF_LOG_INFO(
"GeometryTest") <<
"testThirdPlaneSlope...";
323 MF_LOG_INFO(
"GeometryTest") <<
"testInterWireProjectedDistance...";
329 MF_LOG_INFO(
"GeometryTest") <<
"testPlanePitch...";
341 MF_LOG_INFO(
"GeometryTest") <<
"testFindAuxDet...";
347 MF_LOG_INFO(
"GeometryTest") <<
"printAllGeometry...";
357 std::ostringstream out;
360 <<
"(postumous) configuration error detected!\n" 365 log <<
"Tests completed:";
367 if (tests_run.empty()) {
368 log <<
"\n no test run";
371 log <<
"\n " << tests_run.size() <<
" tests run:\t ";
372 for (
std::string const& test_name: tests_run) log <<
" " << test_name;
375 if (!tests_skipped.empty()) {
376 log <<
"\n " << tests_skipped.size() <<
" tests skipped:\t ";
377 for (
std::string const& test_name: tests_skipped) log <<
" " << test_name;
391 <<
"Wire Rmax " << testWire.
RMax()
392 <<
"\nWire length " << 2.*testWire.
HalfL()
393 <<
"\nWire Rmin " << testWire.
RMin()
404 <<
"\nMaximum number of:" 418 static unsigned int OneSeg = 0;
419 static unsigned int TwoSegs = 0;
420 static unsigned int ThreeSegs = 0;
421 static unsigned int FourSegs = 0;
429 if (ChanSize==1) ++OneSeg;
430 else if(ChanSize==2) ++TwoSegs;
431 else if(ChanSize==3) ++ThreeSegs;
432 else if(ChanSize==4) ++FourSegs;
437 <<
", TwoSegs: " << TwoSegs
438 <<
", ThreeSegs: " << ThreeSegs
439 <<
", FourSegs: " << FourSegs;
447 double world[3] = {0.};
506 for(
unsigned int t=0;
t<std::floor(
geom->
NTPC()/12)+1; ++
t){
507 for(
unsigned int p=0;
p<3; ++
p){
510 double xyz[3] = {0.};
513 std::cout <<
"WireID (" << cs <<
", " <<
t <<
", " <<
p <<
", " <<
w 514 <<
"): x = " << xyz[0]
515 <<
", y = " << xyz[1]
527 const unsigned int nPlanes = tpc.
Nplanes();
534 for(
unsigned int p = 0;
p < nPlanes; ++
p) {
536 const unsigned int nWires = plane.
Nwires();
543 for(
unsigned int w = 0;
w < nWires; ++
w) {
549 std::array<double, 3U>
const local = {{ 0.0, 0.0, 0.0 }};
550 std::array<double, 3U>
center;
557 <<
" at " << lar::dump::array<3>(
center)
570 <<
" has " << nCryostats <<
" cryostats:";
571 for(
unsigned int c = 0;
c < nCryostats; ++
c) {
573 const unsigned int nTPCs = cryostat.
NTPC();
576 << nTPCs <<
" TPC(s):";
577 for(
unsigned int t = 0;
t < nTPCs; ++
t) {
594 log <<
"There are " << nAuxDets <<
" auxiliary detectors:";
595 for (
unsigned int iDet = 0; iDet < nAuxDets; ++iDet) {
596 log <<
"\n[#" << iDet <<
"] ";
604 template <
typename Stream>
613 std::array<double, 3U>
center, normal;
617 out << firstIndent <<
"\"" << auxDet.
Name()
618 <<
"\" centered at " << lar::dump::array<3U>(
center)
619 <<
" cm, size ( " << (2.0 * auxDet.
HalfWidth1());
623 <<
" x " << auxDet.
Length() <<
" ) cm" 624 <<
", normal facing " << lar::dump::array<3U>(normal);
626 switch (nSensitive) {
629 out <<
"\n" << indent <<
"with sensitive volume ";
631 std::forward<Stream>(out),
636 out <<
"\n" << indent
638 for (
unsigned int iSens = 0; iSens < nSensitive; ++iSens) {
639 out <<
"\n" << indent <<
" [#" << iSens <<
"] ";
650 template <
typename Stream>
659 std::array<double, 3U>
center, normal;
663 out << firstIndent <<
"centered at " << lar::dump::array<3U>(
center)
664 <<
" cm, size ( " << (2.0 * auxDetSens.
HalfWidth1());
666 out <<
"/" << (2.0 * auxDetSens.
HalfWidth2());
667 out <<
" x " << (2.0 * auxDetSens.
HalfHeight())
668 <<
" x " << auxDetSens.
Length() <<
" ) cm" 669 <<
", normal facing " << lar::dump::array<3U>(normal);
684 <<
"\n\tCryostat " << cryo.ID()
685 <<
" " << cryo.Volume()->GetName()
686 <<
" Dimensions [cm]: " << cryo.Width()
687 <<
" x " << cryo.Height()
688 <<
" x " << cryo.Length()
692 <<
"\n\t\tmass [kg]: " << cryo.Mass();
695 <<
"\n\t\tCryostat boundaries:" 696 <<
" -x:" << cryo.MinX() <<
" +x:" << cryo.MaxX()
697 <<
" -y:" << cryo.MinY() <<
" +y:" << cryo.MaxY()
698 <<
" -z:" << cryo.MinZ() <<
" +z:" << cryo.MaxZ()
703 double const worldLoc[3]
704 = { cryo.CenterX(), cryo.CenterY(), cryo.CenterZ() };
706 MF_LOG_DEBUG(
"GeometryTest") <<
"\t testing GeometryCore::PoitionToCryostat....";
712 mf::LogWarning(
"FailedToLocateCryostat") <<
"\n exception caught:" <<
e;
715 if (cid != cryo.ID()) {
717 <<
"Geometry points the middle of cryostat " <<
std::string(cryo.ID())
718 <<
" to a different one (" <<
std::string(cid) <<
")\n";
722 MF_LOG_DEBUG(
"GeometryTest") <<
"\t Now test the TPCs associated with this cryostat";
734 std::set<std::string> volume_names;
735 std::vector<TGeoNode const*>
nodes;
742 log <<
"Found " << nodes.size() <<
" world volumes '" 744 for (TGeoNode
const* node: nodes) {
745 TGeoVolume
const* pVolume = node->GetVolume();
746 log <<
"\n - '" << pVolume->GetName() <<
"' (a " 747 << pVolume->GetShape()->GetName() <<
")";
750 if (nodes.size() != 1) {
753 <<
"Found " << nodes.size() <<
" world volumes '" 765 std::set<std::string> volume_names;
767 volume_names.insert(
"volCryostat");
772 log <<
"Found " << nodes.size() <<
" world and cryostat volumes:";
773 for (TGeoNode
const* node: nodes) {
774 TGeoVolume
const* pVolume = node->GetVolume();
775 log <<
"\n - '" << pVolume->GetName() <<
"' (a " 776 << pVolume->GetShape()->GetName() <<
")";
781 <<
"Found " << nodes.size() <<
" world and cryostat volumes! " 782 "[expecting: 1 world and " <<
geom->
Ncryostats() <<
" cryostats]";
794 std::set<std::string> volume_names;
796 volume_names.insert(
TPC.TotalVolume()->GetName());
801 std::vector<std::vector<TGeoNode const*>> node_paths
805 log <<
"Found " << node_paths.size() <<
" TPC volumes:";
806 for (
auto const& path: node_paths) {
807 TGeoNode
const* node = path.back();
808 TGeoVolume
const* pVolume = node->GetVolume();
809 log <<
"\n - '" << pVolume->GetName() <<
"' (a " 810 << pVolume->GetShape()->GetName() <<
") with " << (path.size()-1)
812 for (TGeoNode
const* pNode: path) {
813 TGeoVolume
const* pVolume = pNode->GetVolume();
814 log <<
"\n * '" << pVolume->GetName() <<
"' (a " 815 << pVolume->GetShape()->GetName() <<
") with a " 816 << pNode->GetMatrix()->IsA()->GetName() <<
" that " 817 << (pNode->GetMatrix()->IsTranslation()?
"is":
"is not")
818 <<
" a simple translation";
821 if (node_paths.size() != NTPCs) {
824 <<
"Found " << node_paths.size() <<
" TPC volumes! " 825 "[expecting: " << NTPCs <<
" TPCs]";
848 <<
"Collected " << nErrors <<
" errors during FindAllVolumes() test!\n";
860 <<
" TPCs in the detector";
862 for(
size_t t = 0;
t < cryo.
NTPC(); ++
t){
870 <<
"\n\t\tTPC " << tpcid
872 <<
" has " << tpc.
Nplanes() <<
" planes." 873 <<
"\n\t\tTPC location: ( " 874 << tpc.
MinX() <<
" ; " << tpc.
MinY() <<
" ; "<< tpc.
MinZ()
876 << tpc.
MaxX() <<
" ; " << tpc.
MaxY() <<
" ; "<< tpc.
MaxZ()
878 <<
"\n\t\tTPC Dimensions (W x H x L, cm): " 879 << tpc.
Width() <<
" (" << directionName(tpc.
WidthDir()) <<
")" 880 <<
" x " << tpc.
Height() <<
" (" << directionName(tpc.
HeightDir()) <<
")" 881 <<
" x " << tpc.
Length() <<
" (" << directionName(tpc.
LengthDir()) <<
")" 882 <<
"\n\t\tTPC Active Dimensions: " 884 <<
" around ( " << activeCenter.X() <<
" ; " << activeCenter.Y()
885 <<
" ; "<< activeCenter.Z() <<
" ) cm" 888 log <<
"\n\t\tTPC mass: " << tpc.
ActiveMass();
891 <<
", direction: " << tpc.
DriftDir();
909 <<
"\t\tdrift direction is towards negative values: " 914 <<
"\t\tdrift direction is towards positive values: " 918 throw cet::exception(
"UnknownDriftDirection") <<
"\t\tdrift direction is unknown\n";
921 MF_LOG_DEBUG(
"GeometryTest") <<
"\t testing PositionToTPC...";
923 double worldLoc[3] = {0.};
924 double localLoc[3] = {0.};
930 throw cet::exception(
"BadTPCLookupFromPosition") <<
"TPC look up returned tpc = " 931 << tpcNo <<
" should be " <<
t <<
"\n";
963 decltype(
auto) planeNormal = plane.GetNormalDirection();
964 decltype(
auto) wireCoordDir = plane.GetIncreasingWireDirection();
965 decltype(
auto) wireDir = plane.GetWireDirection();
967 double const wireFrame = wireDir.Cross(wireCoordDir).Dot(planeNormal);
969 if (coordIs.
nonEqual(wireFrame, 1.0)) {
973 <<
"Plane " << plane.ID()
974 <<
" has wire direction " << wireDir
975 <<
" wire coordinate direction " << wireCoordDir
976 <<
" and normal " << planeNormal
977 <<
" , yielding to a non-positive plane-coordinate definition" 978 <<
" (l x w . n = " << wireFrame <<
")";
985 decltype(
auto) widthDir = plane.WidthDir();
986 decltype(
auto) depthDir = plane.DepthDir();
987 double const geoFrame = widthDir.Cross(depthDir).Dot(planeNormal);
989 if (coordIs.
nonEqual(geoFrame, 1.0)) {
993 <<
"Plane " << plane.ID()
994 <<
" has width direction " << widthDir
995 <<
" depth direction " << depthDir
996 <<
" and normal " << planeNormal
997 <<
" , yielding to a non-positive plane-coordinate definition" 998 <<
" (w x d . n = " << geoFrame <<
")";
1005 <<
"testPlaneDirections() accumulated " << nErrors
1006 <<
" errors (see messages above)\n";
1028 decltype(
auto) planeNormal = plane.GetNormalDirection();
1029 decltype(
auto) wireCoordDir = plane.GetIncreasingWireDirection();
1031 unsigned int nWires = plane.Nwires();
1032 for (
unsigned int wireNo = 0; wireNo < nWires; ++wireNo) {
1036 double positive = wire.
Direction().Cross(wireCoordDir).Dot(planeNormal);
1038 if (positive < 0.5) {
1043 decltype(
auto) wireDir = wire.
Direction();
1045 <<
"Wire " << plane.ID() <<
" W: " << wireNo
1046 <<
" has direction ( " << wireDir
1047 <<
" , yielding to a non-positive plane-coordinate definition" 1048 <<
" (l x w . n = " << positive <<
")";
1057 <<
"testWireOrientations() accumulated " << nErrors
1058 <<
" errors (see messages above)\n";
1079 auto const nWires = plane.Nwires();
1080 auto const wirePitch = plane.WirePitch();
1082 double const driftDistance =
geom->
TPC(plane.ID()).DriftDistance();
1084 decltype(
auto) planeNormal = plane.GetNormalDirection();
1090 double const expected = wireNo * wirePitch;
1093 constexpr
int shifts = 3;
1095 for (
int iOfs = -shifts; iOfs <=
shifts; ++iOfs) {
1097 double const offset = iOfs *
step;
1102 constexpr
int quotas = 4;
1103 double const jump = driftDistance / (
std::abs(quotas) + 1);
1104 for (
int iQuota = 0; iQuota < quotas; ++iQuota) {
1108 auto const point = basePoint + iQuota * jump * planeNormal;
1110 double const distance = plane.PlaneCoordinate(point);
1112 if (
std::abs(distance - expected) > 1
e-4) {
1114 <<
" (offset: " << iOfs <<
"x" << step <<
", at " << iQuota
1115 <<
"x" << jump <<
" from plane) is reported to be " << distance
1116 <<
" cm far from wire " << plane.ID() <<
" W: " << wireNo
1117 <<
" (" << expected <<
" expected)";
1131 <<
"testWireCoordFromPlane() accumulated " << nErrors
1132 <<
" errors (see messages above)\n";
1148 decltype(
auto) genDir = plane.GetWireDirection();
1155 decltype(
auto) wireDir = wire.Direction();
1157 if (vectorIs.nonEqual(wireDir, genDir)) {
1159 <<
"Wire " <<
std::string(wireID) <<
" has direction " << wireDir
1160 <<
", not parallel to wire direction " << genDir
1161 <<
" according to the plane " <<
std::string(plane.ID()) <<
"\n";
1199 auto const& planeNorm = plane.GetNormalDirection();
1200 auto const& wirePitch = plane.WirePitch();
1201 auto const& refPoint = plane.ProjectionReferencePoint();
1203 unsigned int const lastWire = plane.Nwires() - 1;
1211 auto const wireDirStep = wire.HalfL() / 2.0;
1213 for (
int iWDStep = -1; iWDStep <= 1; ++iWDStep) {
1218 auto const wireDirOffset = iWDStep * wireDirStep;
1220 auto const expectedPoint = wire.GetCenter()
1221 + wireDirOffset * wire.Direction()
1222 + distance * planeNorm;
1224 auto const expectedWireCoord = wirePitch * wireID.Wire;
1225 auto const expectedWireDirCoord = wireDirOffset
1226 + wire.Direction().Dot(wire.GetCenter() - refPoint);
1229 (expectedWireDirCoord, expectedWireCoord);
1234 auto point = plane.ComposePoint(distance, expectedProj);
1236 if (vectorIs.nonEqual(point, expectedPoint)) {
1239 <<
"[testPlanePointDecomposition] ComposePoint(): " 1240 <<
"Point with projection " << expectedProj
1241 <<
" and distance from plane " << distance
1242 <<
" was reported as " << point
1243 <<
" while it is expected to be at " << expectedPoint
1250 auto const decomp = plane.DecomposePoint(point);
1251 if (coordIs.
nonEqual(decomp.distance, distance)) {
1254 <<
"[testPlanePointDecomposition] DecomposePoint(): " 1255 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1256 <<
" is reported to have distance from plane " << decomp.distance
1257 <<
" cm, while " << distance <<
" is expected";
1259 if (coordIs.
nonEqual(decomp.projection.X(), expectedWireDirCoord)) {
1262 <<
"[testPlanePointDecomposition] DecomposePoint(): " 1263 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1264 <<
" is reported to have wire direction coordinate " 1265 << decomp.projection.X()
1266 <<
" cm, while " << expectedWireDirCoord <<
" is expected";
1268 if (coordIs.
nonEqual(decomp.projection.Y(), expectedWireCoord)) {
1271 <<
"[testPlanePointDecomposition] DecomposePoint(): " 1272 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1273 <<
" is reported to have wire coordinate " 1274 << decomp.projection.Y()
1275 <<
" cm, while " << expectedWireCoord <<
" is expected";
1281 auto const proj = plane.PointProjection(point);
1282 if (coordIs.
nonEqual(proj.X(), expectedWireDirCoord)) {
1285 <<
"[testPlanePointDecomposition] PointProjection(): " 1286 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1287 <<
" is reported to have wire direction coordinate " << proj.X()
1288 <<
" cm, while " << expectedWireDirCoord <<
" is expected";
1290 if (coordIs.
nonEqual(proj.Y(), expectedWireCoord)) {
1293 <<
"[testPlanePointDecomposition] PointProjection(): " 1294 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1295 <<
" is reported to have wire coordinate " << proj.Y()
1296 <<
" cm, while " << expectedWireCoord <<
" is expected";
1302 auto const dist = plane.DistanceFromPlane(point);
1306 <<
"[testPlanePointDecomposition] DistanceFromPlane(): " 1307 <<
"Point " << point <<
" (on wire " <<
std::string(wireID) <<
")" 1308 <<
" is reported to have distance " <<
dist <<
" cm from plane " 1309 << plane.ID() <<
", while " << distance <<
" is expected";
1318 for (
double drift: drifts) {
1322 auto const expectedDistance = distance - drift;
1327 auto point = expectedPoint;
1328 plane.DriftPoint(point, drift);
1333 auto dist = plane.DistanceFromPlane(point);
1337 <<
"[testPlanePointDecomposition] DriftPoint(): " 1338 <<
"Point " << expectedPoint
1339 <<
" (distant " << distance <<
" cm from the plane)" 1341 <<
" drifted by " << drift <<
" became " << point
1342 <<
" which has distance from plane " <<
dist 1343 <<
" cm, while " << expectedDistance <<
" was expected";
1353 bool const isExtremeWire
1354 = (wireID.Wire == 0) || (wireID.Wire == lastWire);
1355 if (!isExtremeWire && !plane.isProjectionOnPlane(expectedPoint)) {
1358 <<
"[testPlanePointDecomposition] isProjectionOnPlane(): " 1359 <<
"Point " << expectedPoint <<
" (center of " << wireID
1360 <<
") is not believed to be on the plane, but it should.";
1371 <<
"testPlanePointDecomposition() accumulated " << nErrors
1372 <<
" errors (see messages above)\n";
1395 const unsigned int nWires = plane.
Nwires();
1398 geo::WireID next_wire_id(planeid, nWires / 2 + 1);
1400 if (next_wire_id.
Wire >= nWires) {
1402 <<
"Plane " <<
std::string(planeid) <<
" has only " << nWires
1408 decltype(
auto) middle_wire_center = middle_wire.
GetCenter();
1410 <<
"Center of " << middle_wire_id <<
" at " << middle_wire_center;
1414 (middle_wire_center, planeid);
1416 if (
std::abs(middle_coord -
double(middle_wire_id.
Wire)) > 2
e-3) {
1418 <<
"Center of " <<
std::string(middle_wire_id) <<
" at (" 1419 << middle_wire_center[0]
1420 <<
"; " << middle_wire_center[1] <<
"; " << middle_wire_center[2]
1421 <<
") has wire coordinate " << middle_coord
1422 <<
" (" << middle_wire_id.
Wire <<
" expected)\n";
1430 <<
" pitch: " << pitch <<
" wire coord dir: cos(phi_z): " 1433 auto on_next_wire = middle_wire_center + pitch * wireCoordDir;
1437 if (
std::abs(next_coord -
double(next_wire_id.
Wire)) > 2
e-3) {
1439 <<
" pitch: " << pitch <<
" wire coord dir: " << wireCoordDir
1440 <<
"\n start wire: " << middle_wire_id
1441 <<
" centered at " << middle_wire_center
1442 <<
"\n querying point " << on_next_wire
1445 <<
"Position " << on_next_wire
1446 <<
" is expected to be on wire " <<
std::string(next_wire_id)
1447 <<
" but it has wire coordinate " << next_coord <<
"\n";
1463 <<
"ROP from an invalid channel (" 1470 <<
"Non-compilant ChannelToROP() throws on invalid channel.";
1480 auto const lastChannel = firstChannel +
geom->
Nchannels(ropid);
1485 <<
", which contains only channels from " << firstChannel
1486 <<
" to " << lastChannel <<
" (excluded)\n";
1510 <<
"Invalid channel returned for wire " <<
std::string(testWireID)
1516 if (wireIDs.empty()) {
1518 <<
"List of wires for channel #" << channel <<
" is empty;" 1519 <<
" it should have contained at least " <<
std::string(testWireID)
1525 log << wireIDs.size() <<
" wire IDs associated with channel #" 1527 for (
auto const& wid: wireIDs)
1528 log <<
"\n " << wid;
1530 <<
"Wire " <<
std::string(testWireID) <<
" is on channel #" << channel
1531 <<
" but ChannelToWire() does not map the channel to that wire\n";
1539 <<
"Geometry service claims channel #" << channel
1540 <<
" to be of type " << channelSigType
1541 <<
" but that the plane of " <<
std::string(testWireID)
1542 <<
" is of type " <<
geom->
SignalType(testWireID.planeID()) <<
"\n";
1545 auto const channelView =
geom->
View(channel);
1548 <<
"Geometry service claims channel #" << channel
1549 <<
" should be on view " <<
geom->
View(channel)
1550 <<
" but the plane of " <<
std::string(testWireID)
1551 <<
" claims to be on view " <<
geom->
Plane(testWireID).
View() <<
"\n";
1556 if (testWireID.planeID() == lastPlane) {
1557 if (planeView != channelView) {
1559 <<
"Geometry service claims channel #" << channel
1560 <<
" is on view " << channelView
1562 <<
" claims to be on view " << planeView <<
"\n";
1564 if (planeSigType != channelSigType) {
1566 <<
"Geometry service claims channel #" << channel
1567 <<
" is if type " << channelSigType
1569 <<
" to be of type " << planeSigType <<
"\n";
1573 lastPlane = testWireID.planeID();
1574 planeView = channelView;
1575 planeSigType = channelSigType;
1585 double xyz[3] = {0.}, xyzW[3] = {0.};
1589 << i <<
" is centered at (x,y,z) = (" 1590 << xyzW[0] <<
"," << xyzW[1]
1591 <<
"," << xyzW[2] <<
")";
1604 TVector3 reference = plane.ProjectionReferencePoint();
1606 auto decomp = plane.DecomposePoint(reference);
1610 <<
"Plane " << plane.ID() <<
" reference point " << reference
1611 <<
" has distance " << decomp.distance <<
" cm (should be 0)";
1620 <<
"Plane " << plane.ID() <<
" reference point " << reference
1621 <<
" has projection ( " << decomp.projection.X()
1622 <<
" ; " << decomp.projection.Y() <<
" ) cm (should be (0;0) )";
1629 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
1658 constexpr
int steps = 5;
1659 static_assert(steps > 0,
"Steps must be a positive number.");
1661 constexpr
int nOutsides = 1;
1666 auto const& planeNorm = plane.GetNormalDirection();
1667 auto const& widthDir = plane.WidthDir();
1668 auto const& depthDir = plane.DepthDir();
1669 auto const& refPoint = plane.GetCenter();
1671 double const halfWidth = plane.Width() / 2;
1672 double const halfDepth = plane.Depth() / 2;
1673 double const dW_2 = halfWidth / (steps * 2);
1674 double const dD_2 = halfDepth / (steps * 2);
1676 for (
int iW = -nOutsides * steps; iW <= +nOutsides * steps; ++iW) {
1678 double const expected_w = dW_2 * (iW * 2 + 1);
1679 bool const inWidth =
std::abs(expected_w) <= halfWidth;
1681 for (
int iD = -nOutsides * steps; iD <= +nOutsides * steps; ++iD) {
1683 double const expected_d = dD_2 * (iD * 2 + 1);
1684 bool const inDepth =
std::abs(expected_d) <= halfDepth;
1691 auto const expectedPoint = refPoint
1692 + expected_w * widthDir
1693 + expected_d * depthDir
1694 + distance * planeNorm;
1697 (expected_w, expected_d);
1702 auto point = plane.ComposePoint(distance, expectedProj);
1704 if (vectorIs.nonEqual(point, expectedPoint)) {
1707 <<
"[testPlanePointDecompositionFrame] ComposePoint(): " 1708 <<
"Point with projection " << expectedProj
1709 <<
" (width: " << expected_w <<
", depth: " << expected_d
1710 <<
") and distance from plane " << distance
1711 <<
" was reported as " << point
1712 <<
" while it is expected to be at " << expectedPoint;
1718 auto const decomp = plane.DecomposePointWidthDepth(point);
1719 if (coordIs.
nonEqual(decomp.distance, distance)) {
1722 <<
"[testPlanePointDecomposition] DecomposePointWidthDepth(): " 1723 <<
"Point " << point
1724 <<
" (width: " << expected_w <<
", depth: " << expected_d
1725 <<
") is reported to have distance from plane " << decomp.distance
1726 <<
" cm, while " << distance <<
" is expected";
1728 if (coordIs.
nonEqual(decomp.projection.X(), expected_w)) {
1731 <<
"[testPlanePointDecomposition] DecomposePointWidthDepth(): " 1732 <<
"Point " << point
1733 <<
" (width: " << expected_w <<
", depth: " << expected_d
1734 <<
") is reported to have width direction coordinate " 1735 << decomp.projection.X()
1736 <<
" cm, while " << expected_w <<
" is expected";
1738 if (coordIs.
nonEqual(decomp.projection.Y(), expected_d)) {
1741 <<
"[testPlanePointDecomposition] DecomposePointWidthDepth(): " 1742 <<
"Point " << point
1743 <<
" (width: " << expected_w <<
", depth: " << expected_d
1744 <<
") is reported to have depth direction coordinate " 1745 << decomp.projection.Y()
1746 <<
" cm, while " << expected_d <<
" is expected";
1752 auto const proj = plane.PointWidthDepthProjection(point);
1753 if (coordIs.
nonEqual(proj.X(), expected_w)) {
1756 <<
"[testPlanePointDecomposition] PointProjection(): " 1757 <<
"Point " << point
1758 <<
" (width: " << expected_w <<
", depth: " << expected_d
1759 <<
") is reported to have width direction coordinate " << proj.X()
1760 <<
" cm, while " << expected_w <<
" is expected";
1762 if (coordIs.
nonEqual(proj.Y(), expected_d)) {
1765 <<
"[testPlanePointDecomposition] PointProjectionWidthDepth(): " 1766 <<
"Point " << point
1767 <<
" (width: " << expected_w <<
", depth: " << expected_d
1768 <<
") is reported to have wire coordinate " << proj.Y()
1769 <<
" cm, while " << expected_d <<
" is expected";
1775 auto const dist = plane.DistanceFromPlane(point);
1779 <<
"[testPlanePointDecomposition] DistanceFromPlane(): " 1780 <<
"Point " << point
1781 <<
" (width: " << expected_w <<
", depth: " << expected_d
1782 <<
") is reported to have distance from plane " <<
dist 1783 <<
" cm, while " << distance <<
" is expected";
1792 for (
double drift: drifts) {
1796 auto const expectedDistance = distance - drift;
1801 auto point = expectedPoint;
1802 plane.DriftPoint(point, drift);
1807 auto dist = plane.DistanceFromPlane(point);
1811 <<
"[testPlanePointDecomposition] DriftPoint(): " 1812 <<
"Point " << expectedPoint
1813 <<
" (distant " << distance <<
" cm from the plane)" 1814 <<
" (width: " << expected_w <<
", depth: " << expected_d
1815 <<
") drifted by " << drift <<
" became " << point
1816 <<
" which has distance from plane " <<
dist 1817 <<
" cm, while " << expectedDistance <<
" was expected";
1825 const bool expected_onPlane = inWidth && inDepth;
1826 const bool onPlane = plane.isProjectionOnPlane(expectedPoint);
1827 if (expected_onPlane != onPlane) {
1831 <<
"[testPlanePointDecompositionFrame] isProjectionOnPlane(): " 1832 <<
"Point " << expectedPoint
1833 <<
" (width: " << expected_w <<
", depth: " << expected_d
1834 <<
") is" << (onPlane?
"":
" not")
1835 <<
" believed to be on plane " << plane.ID()
1836 <<
", but it should" << (expected_onPlane?
"":
" not be") <<
".";
1847 <<
"testPlanePointDecomposition() accumulated " << nErrors
1848 <<
" errors (see messages above)\n";
1868 auto const& vector2Dis = vectorIs.comp2D();
1871 constexpr
int steps = 5;
1872 static_assert(steps > 0,
"Steps must be a positive number.");
1874 constexpr
int nOutsides = 2;
1879 double const halfWidth = plane.Width() / 2;
1880 double const halfDepth = plane.Depth() / 2;
1881 double const dW_2 = halfWidth / (steps * 2);
1882 double const dD_2 = halfDepth / (steps * 2);
1884 for (
int iW = -nOutsides * steps; iW <= +nOutsides * steps; ++iW) {
1886 double const expected_w = dW_2 * (iW * 2 + 1);
1887 bool const inWidth =
std::abs(expected_w) <= halfWidth;
1889 for (
int iD = -nOutsides * steps; iD <= +nOutsides * steps; ++iD) {
1891 double const expected_d = dD_2 * (iD * 2 + 1);
1892 bool const inDepth =
std::abs(expected_d) <= halfDepth;
1894 for (
double distance: { -30., 0.0, +30.0 }) {
1901 (expected_w, expected_d);
1903 auto const expected_point
1904 = plane.ComposePoint(
distance, expected_proj);
1909 const bool expected_onPlane = inWidth && inDepth;
1911 = plane.isProjectionOnPlane(expected_point);
1912 if (expected_onPlane != onPlane) {
1915 <<
"[testPlaneProjectionOnFrame] isProjectionOnPlane(): " 1916 <<
"Point " << expected_point
1917 <<
" (width: " << expected_w <<
", depth: " << expected_d
1918 <<
") is" << (onPlane?
"":
" not")
1919 <<
" believed to be on plane " << plane.ID()
1920 <<
", but it should" << (expected_onPlane?
"":
" not be")
1931 expected_w: (expected_w < 0)? -halfWidth: +halfWidth),
1933 expected_d: (expected_d < 0)? -halfDepth: +halfDepth)
1935 auto movedProjection = plane.MoveProjectionToPlane(expected_proj);
1936 if (vector2Dis.nonEqual(movedProjection, expected_movedProjection))
1940 <<
"[testPlaneProjectionOnFrame] moveProjectionOnPlane():" 1941 <<
"Projection of ooint " << expected_point
1942 <<
" (width: " << expected_w <<
", depth: " << expected_d
1943 <<
") (" << (onPlane?
"on":
"off")
1944 <<
"-plane " << plane.ID() <<
") was moved to " 1945 << movedProjection <<
" while it should have moved to " 1946 << expected_movedProjection
1953 auto expected_movedPoint
1954 = plane.ComposePoint(
distance, expected_movedProjection);
1956 auto movedPoint = plane.MovePointOverPlane(expected_point);
1957 if (vectorIs.nonEqual(movedPoint, expected_movedPoint)) {
1960 <<
"[testPlaneProjectionOnFrame] movePointOnPlane(): " 1961 <<
"Point " << expected_point
1962 <<
" (width: " << expected_w <<
", depth: " << expected_d
1963 <<
") (" << (onPlane?
"on":
"off")
1964 <<
"-plane " << plane.ID() <<
") was moved to " 1965 << movedPoint <<
" while it should have moved to " 1966 << expected_movedPoint
1980 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2011 double xyz[3] = {0.};
2012 double xyzprev[3] = {0.};
2017 for (
size_t i=0; i < tpc->
Nplanes(); ++i) {
2020 for (
size_t j = 1; j < plane->
Nwires(); ++j) {
2029 if(xyz[2] < xyzprev[2])
2030 throw cet::exception(
"WireOrderProblem") <<
"\n\twires do not increase in +z order in" 2031 <<
"Cryostat " <<
cs 2034 <<
"; at wire " << j <<
"\n";
2047 double tpcworld[3] = {0.};
2048 double xyz[3] = {0.};
2049 double xyzprev[3] = {0.};
2055 for (
size_t i=0; i < tpc->
Nplanes(); ++i) {
2058 for (
size_t j = 1; j < plane->
Nwires(); ++j) {
2066 if(tpcworld[1] > 0 && xyz[1] > xyzprev[1])
2067 throw cet::exception(
"WireOrderProblem") <<
"\n\ttop TPC wires do not increase in -y order in" 2068 <<
"Cryostat " <<
cs 2071 <<
"; at wire " << j <<
"\n";
2073 else if(tpcworld[1] < 0 && xyz[1] < xyzprev[1])
2074 throw cet::exception(
"WireOrderProblem") <<
"\n\tbottom TPC wires do not increase in +y order in" 2075 <<
"Cryostat " <<
cs 2078 <<
"; at wire " << j <<
"\n";
2095 {{ IncreasingWireDir.X(), IncreasingWireDir.Y(), IncreasingWireDir.Z() }};
2106 TStopwatch stopWatch;
2109 bool bTestWireCoordinate =
true;
2115 const unsigned int NWires = plane.
Nwires();
2120 <<
"The direction of increasing wires for plane " << planeID
2121 <<
" (theta=" << plane.
Wire(0).
ThetaZ() <<
" pitch=" 2125 <<
") is " << IncreasingWireDir;
2132 decltype(
auto) wire_center = wire.GetCenter();
2134 uint32_t nearest = 0;
2135 std::vector< geo::WireID > wireIDs;
2143 std::vector<double> posWorldV(3);
2144 for (
int i=0; i<3; ++i) {
2145 posWorldV[i] = wire_center[i] + 0.001;
2157 if ( wireIDs.empty() ) {
2159 <<
"test point is at " << wire_center
2160 <<
" nearest channel is " << nearest
2170 if(std::find(wireIDs.begin(), wireIDs.end(), wireID) == wireIDs.end()) {
2173 <<
" has a world position at " << wire_center
2174 <<
"\nNearestWire for this position is " 2176 <<
"\nNearestChannel is " << nearest
2191 TVector3 wire_shifted;
2192 TVector3
const step = pitch * IncreasingWireDir;
2194 constexpr
int NSteps = 5;
2195 for (
int i = -NSteps; i <= +NSteps; ++i) {
2197 const double f = NSteps? (double(i) / NSteps): 0.0;
2200 TVector3
const delta = f *
step;
2201 TVector3
const wire_shifted = wire_center + delta;
2204 const double expected_wire = wireID.
Wire +
f;
2206 double wire_from_wc = 0;
2207 if (bTestWireCoordinate) {
2212 if (hasCategory(e,
"NotImplemented")) {
2214 <<
"WireCoordinate() is not implemented for your ChannelMap;" 2215 " skipping the test";
2216 bTestWireCoordinate =
false;
2218 else if (bTestWireCoordinate)
throw;
2221 if (bTestWireCoordinate) {
2222 if (
std::abs(wire_from_wc - expected_wire) > 1e-3) {
2225 <<
"wire " << wireID
2226 <<
" [center: " << wire_center <<
"] on step of " 2227 << i <<
"/" << NSteps
2228 <<
" x" << step <<
" = " << delta
2229 <<
" cm shows " << wire_from_wc <<
", " << expected_wire
2235 if ((expected_wire > -0.5) && (expected_wire < NWires - 0.5)) {
2236 const unsigned int expected_wire_number = std::round(expected_wire);
2237 unsigned int wire_number_from_wc;
2245 <<
" [center: " << wire_center <<
"] on step of " 2246 << i <<
"/" << NSteps
2247 <<
" x" << step <<
" = " << delta
2248 <<
" cm failed NearestWire(), " << expected_wire_number
2249 <<
" expected (more precisely, " << expected_wire <<
").\n";
2254 std::stringstream
e;
2255 e <<
"wire " << wireID
2256 <<
" [center: " << wire_center <<
"] on step of " 2257 << i <<
"/" << NSteps
2258 <<
" x" << step <<
" = " << delta <<
" cm near to " 2259 << wire_number_from_wc;
2260 if (wire_number_from_wc != expected_wire_number) {
2261 e <<
", " << expected_wire_number
2262 <<
" expected (more precisely, " << expected_wire <<
").";
2270 else if (wire_number_from_wc != expected_wire_number) {
2274 <<
" [center: " << wire_center <<
"] on step of " 2275 << i <<
"/" << NSteps
2276 <<
" x" << step <<
" = " << delta
2277 <<
" cm near to " << wire_number_from_wc
2278 <<
", " << expected_wire_number
2279 <<
" expected (more precisely, " << expected_wire <<
").";
2295 MF_LOG_DEBUG(
"GeoTestWireCoordinate") <<
"\tdone testing closest channel";
2299 mf::LogVerbatim(
"GeoTestWireCoordinate") <<
"\tattempt to cause an exception to be caught " 2300 <<
"when looking for a nearest channel";
2305 nullptr, posWorld + 1,
nullptr, posWorld + 2);
2306 for (
int i = 0; i < 3; ++i) posWorld[i] *= 2.;
2308 bool hasThrown =
false;
2309 unsigned int nearest_to_what = 0;
2329 <<
"GeometryCore::NearestChannel() did not raise an exception" 2330 " on out-of-world position (" << posWorld[0] <<
"; " 2331 << posWorld[1] <<
"; " << posWorld[2] <<
"), and returned " 2332 << nearest_to_what <<
" instead.\n" 2333 "This is normally considered a failure.";
2337 <<
"GeometryCore::NearestChannel() did not raise an exception" 2338 " on out-of-world position (" << posWorld[0] <<
"; " 2339 << posWorld[1] <<
"; " << posWorld[2] <<
"), and returned " 2340 << nearest_to_what <<
" instead\n";
2390 MF_LOG_DEBUG(
"GeometryTest") <<
"Wire intersection test on " <<
TPC.ID();
2404 otherPlane = &plane;
2410 <<
"Off cryostat test (" << w1 <<
"): chosen wire " << w2;
2413 MF_LOG_ERROR(
"GeometryTest") <<
"WireIDsIntersect() on " << w1
2414 <<
" and " << w2 <<
" returned " << xingPoint
2415 <<
" cm, while should have reported no intersection at all";
2423 MF_LOG_ERROR(
"GeometryTest") <<
"WiresIntersect() on " << w1
2424 <<
" and " << w2 <<
" threw an exception, which should not have";
2430 <<
"No wire plane found in " << otherCryo.ID()
2431 <<
" with wires not aligned with " << w1.asPlaneID()
2432 <<
", " << wireDir <<
"; off-cryostat sanity check skipped.";
2450 otherPlane = &plane;
2456 <<
"Off TPC test (" << w1 <<
"): chosen wire " << w2;
2459 MF_LOG_ERROR(
"GeometryTest") <<
"WireIDsIntersect() on " << w1
2460 <<
" and " << w2 <<
" returned " << xingPoint
2461 <<
", while should have reported no intersection at all";
2469 MF_LOG_ERROR(
"GeometryTest") <<
"WiresIntersect() on " << w1
2470 <<
" and " << w2 <<
" threw an exception, which should not have";
2476 <<
"No wire plane found in any TPC of " << cryo.ID()
2477 <<
" with wires not aligned with " << refPlaneID
2478 <<
", " << wireDir <<
"; off-TPC sanity check skipped.";
2487 MF_LOG_ERROR(
"GeometryTest") <<
"WireIDsIntersect() on " << w1
2488 <<
" and " << w2 <<
" returned " << xingPoint
2489 <<
", while should have reported no intersection at all";
2499 constexpr
unsigned int SplitW = 19, SplitD = 17;
2501 auto const driftOffset = -
TPC.DriftDistance() / 2.0 *
TPC.DriftDir();
2502 auto const refPoint = refPlane.
GetCenter() + driftOffset;
2504 decltype(
auto) coverage = refPlane.
ActiveArea();
2505 const double stepW = coverage.
width.
length() / SplitW;
2506 const double stepD = coverage.depth.length() / SplitD;
2507 const int stepsW = SplitW / 2;
2508 const int stepsD = SplitD / 2;
2511 for (
int iW = -stepsW; iW <= +stepsW; ++iW) {
2513 auto const widthOffset = (iW * stepW) * refPlane.
WidthDir();
2515 for (
int iD = -stepsD; iD < +stepsD; ++iD) {
2517 auto const depthOffset = (iD * stepD) * refPlane.
DepthDir();
2519 auto const point = refPoint + widthOffset + depthOffset;
2529 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2554 const unsigned int NPlanes = TPC.
Nplanes();
2560 std::vector<double> WirePitch(NPlanes);
2563 WireCoordDirs(NPlanes);
2564 std::vector<geo::WireID> WireIDs;
2565 WireIDs.reserve(NPlanes);
2566 std::vector<double> WireDistances(NPlanes);
2567 for (
unsigned int iPlane = 0; iPlane < NPlanes; ++iPlane) {
2573 WireIDs.emplace_back(plane.
ID(), (
unsigned int) std::round(WireDistance));
2574 WireDistances[iPlane]
2575 = (WireDistance - std::round(WireDistance)) * WirePitch[iPlane];
2577 MF_LOG_DEBUG(
"GeometryTest") <<
"Nearest wire to " << point
2579 <<
" (pitch: " << WirePitch[iPlane]
2580 <<
", coord.dir.=" << WireCoordDirs[iPlane]
2581 <<
") is " << WireIDs[iPlane] <<
" (position: " << WireDistance <<
")";
2588 for (
unsigned int iPlane1 = 0; iPlane1 < NPlanes; ++iPlane1) {
2594 for (
unsigned int iPlane2 = iPlane1 + 1; iPlane2 < NPlanes; ++iPlane2) {
2601 MF_LOG_ERROR(
"GeometryTest") <<
"Wires " << w1 <<
" and " << w2
2602 <<
" should intersect around " << point <<
" of TPC " << TPC.
ID()
2603 <<
", but they seem not to intersect at all!";
2614 MF_LOG_ERROR(
"GeometryTest") <<
"Legacy check: wires " << w1 <<
" and " 2615 << w2 <<
" should intersect around " << point <<
" of TPC " 2616 << TPC.
ID() <<
", but they seem not to intersect at all!";
2620 if (coordIs.nonEqual(widIntersect.
y, xingPoint.Y())
2621 || coordIs.nonEqual(widIntersect.
z, xingPoint.Z()))
2623 MF_LOG_ERROR(
"GeometryTest") <<
"Legacy check: wires " << w1 <<
" and " 2624 << w2 <<
" should intersect around " << point <<
" of TPC " 2625 << TPC.
ID() <<
", but legacy code says (?, " 2626 << widIntersect.
y <<
", " << widIntersect.
z <<
")!";
2635 MF_LOG_ERROR(
"GeometryTest") <<
"Wires " << w2 <<
" and " << w1
2636 <<
" (reversed test) should intersect around " << point
2637 <<
" of TPC " << TPC.
ID()
2638 <<
", but they seem not to intersect at all!";
2642 if (vectorIs.nonEqual(xingPointInv, xingPoint2)) {
2644 <<
"WireIDsIntersect() gives different intersections for " 2645 << w1 <<
" and " << w2
2646 <<
": " << xingPoint2 <<
" (direct+shift) and " << xingPointInv
2659 const double d1 = WireDistances[iPlane1], d2 = WireDistances[iPlane2],
2660 cosAlpha =
dot(WireCoordDirs[iPlane1], WireCoordDirs[iPlane2]);
2661 const double expected_d = std::sqrt(
2667 <<
" - wires " << w1 <<
" and " << w2 <<
" intersect at " << xingPoint
2668 <<
", " << d <<
" cm far from starting point (expected: " 2669 << expected_d <<
")";
2674 (
std::max(WirePitch[iPlane1], WirePitch[iPlane2]) * 1
e-3);
2675 if (wireCoordIs.
nonEqual(d, expected_d)) {
2677 <<
"wires " << w1 <<
" and " << w2 <<
" intersect at " << xingPoint
2679 << d <<
" cm far from starting point: too far from the expected " 2680 << expected_d <<
" cm!";
2690 if (vectorIs.nonEqual(objXingPoint, xingPoint)) {
2692 <<
"geo::WiresIntersection() gives wrong intersection for " 2693 << w1 <<
" and " << w2
2694 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2702 if (vectorIs.nonEqual(objXingPoint, xingPoint)) {
2704 <<
"geo::WireGeo[" << w1
2705 <<
"]::IntersectionWith() gives wrong intersection with " << w2
2706 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2712 if (vectorIs.nonEqual(objXingPoint, xingPointInv)) {
2714 <<
"geo::WireGeo[" << w2
2715 <<
"]::IntersectionWith() gives wrong intersection with " << w1
2716 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2748 const unsigned int nPlanes = TPC.
Nplanes();
2749 MF_LOG_DEBUG(
"GeometryTest") << tpcid <<
" (" << nPlanes <<
" planes)";
2759 const bool isValidInput = (nPlanes == 3) && (iPlane1 != iPlane2);
2760 bool bError =
false;
2766 if (isValidInput)
throw;
2769 bError = hasCategory(e,
"GeometryCore");
2773 <<
" [" << pid1 <<
"], [" << pid2 <<
"] => " 2775 if (bError)
continue;
2777 if (!bError && !isValidInput) {
2778 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2779 <<
" and " << pid2 <<
" returned " << third_plane
2780 <<
", while should have thrown an exception";
2785 if (third_plane != tpcid) {
2786 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2787 <<
" and " << pid2 <<
" returned " << third_plane
2788 <<
", on a different TPC!!!";
2791 else if (!third_plane.
isValid) {
2792 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2793 <<
" and " << pid2 <<
" returned an invalid " << third_plane;
2796 else if (third_plane.
Plane >= nPlanes) {
2797 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2798 <<
" and " << pid2 <<
" returned " << third_plane
2799 <<
" with plane out of range";
2802 else if (third_plane == pid1) {
2803 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2804 <<
" and " << pid2 <<
" returned " << third_plane
2805 <<
", same as the first input";
2808 else if (third_plane == pid2) {
2809 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane() on " << pid1
2810 <<
" and " << pid2 <<
" returned " << third_plane
2811 <<
", same as the second input";
2823 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2850 const double driftVelocity = 0.1
2853 const unsigned int NPlanes = TPC.
Nplanes();
2854 MF_LOG_DEBUG(
"GeometryTest") << tpcid <<
" (" << NPlanes <<
" planes)";
2859 bool bError =
false;
2867 bError = hasCategory(e,
"GeometryCore");
2870 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane_dTdW() on " << p1
2871 <<
" and " << p2 <<
" returned " << slope
2872 <<
", while should have thrown an exception";
2880 bool bError =
false;
2888 bError = hasCategory(e,
"GeometryCore");
2891 MF_LOG_ERROR(
"GeometryTest") <<
"ThirdPlane_dTdW() on " << p1
2892 <<
" and " << p2 <<
" returned " << slope
2893 <<
", while should have thrown an exception";
2902 const std::array<double, 3>
A 2910 const double dX = radius;
2911 const double dT = driftVelocity * dX;
2914 constexpr
unsigned int NAngles = 19;
2915 const double start_angle = 0.05;
2916 const double step_angle = 2. * util::pi<double>() / NAngles;
2918 for (
unsigned int iAngle = 0; iAngle < NAngles; ++iAngle) {
2919 const double angle = start_angle + iAngle * step_angle;
2925 std::array<double, 3>
B = {{
2927 A[1] + radius * std::sin(angle),
2928 A[2] + radius * std::cos(angle)
2933 std::vector<std::pair<geo::PlaneID, double>> dTdWs
2938 log <<
"Expected dT/dW for a segment with " << radius
2939 <<
" cm long projection at " 2940 << angle <<
" rad, and dT " << dT <<
" cm:";
2941 for (
auto const& dTdW_info: dTdWs)
2942 log <<
" " << dTdW_info.first <<
" slope:" << dTdW_info.second;
2954 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2960 std::vector<std::pair<geo::PlaneID, double>>
2962 std::array<double, 3>
const&
A, std::array<double, 3>
const&
B,
2963 const double driftVelocity
2975 <<
"ExpectedPlane_dTdW(): can't find any TPC containing point A (" 2976 << A[0] <<
"; " << A[1] <<
"; " << A[2] <<
")";
2981 <<
"ExpectedPlane_dTdW(): point A (" 2982 << A[0] <<
"; " << A[1] <<
"; " << A[2] <<
") is in " 2984 <<
" while point B (" << B[0] <<
"; " << B[1] <<
"; " << B[2]
2991 double dT_over_dX = 1. / driftVelocity;
2996 dT_over_dX = -dT_over_dX;
3001 <<
"GeometryTestAlg::ExpectedPlane_dTdW(): drift direction #" 3003 <<
" not supported.\n";
3006 const unsigned int nPlanes = TPC.
Nplanes();
3007 std::vector<std::pair<geo::PlaneID, double>> slopes(nPlanes);
3019 = std::make_pair(pid, ((B[0] - A[0]) * dT_over_dX) / (wB - wA));
3028 (
std::vector<std::pair<geo::PlaneID, double>>
const& plane_dTdW)
const 3039 for (std::pair<geo::PlaneID, double>
const& input1: plane_dTdW) {
3040 for (std::pair<geo::PlaneID, double>
const& input2: plane_dTdW) {
3042 const bool bValidInput = input1.first != input2.first;
3044 for (std::pair<geo::PlaneID, double>
const&
output: plane_dTdW) {
3045 bool bError =
false;
3046 double output_slope = 0.;
3049 input1.first, input1.second,
3050 input2.first, input2.second,
3057 if (bValidInput)
throw;
3058 bError = hasCategory(e,
"GeometryCore");
3061 << input1.first <<
" slope:" << input1.second
3062 <<
" " << input2.first <<
" slope:" << input2.second
3067 if (!bValidInput && !bError) {
3069 <<
"GeometryCore::ThirdPlane_dTdW() on " 3070 << input1.first <<
" and " << input2.first
3071 <<
" should have thrown an exception, it returned " 3072 << output_slope <<
" instead";
3078 << input1.first <<
" slope:" << input1.second
3079 <<
" " << input2.first <<
" slope:" << input2.second
3080 <<
" => " <<
output.first <<
" slope:" << output_slope;
3081 if (((
output.second == 0.) && (output_slope > 1e-3))
3085 <<
"GeometryCore::ThirdPlane_dTdW(): " 3086 << input1.first <<
" slope:" << input1.second
3087 <<
" " << input2.first <<
" slope:" << input2.second
3088 <<
" => " <<
output.first <<
" slope:" << output_slope
3089 <<
" (expected: " <<
output.second <<
")";
3106 unsigned int nPitchErrors = 0;
3117 <<
"Using legacy wire pitch parameters hard-coded for the detector '" 3123 <<
"no expected wire pitch; I'll just check that they are all the same";
3127 log <<
"Expected wire pitch per plane, in centimetres:";
3135 const unsigned int nWires = plane.
Nwires();
3136 if (nWires < 2)
continue;
3146 double expectedPitch = 0.;
3151 <<
"Wire pitch on " << planeid <<
": " << expectedPitch <<
" cm";
3159 while (++w < nWires) {
3161 pWire = &(plane.
Wire(w));
3164 if (
std::abs(thisPitch - expectedPitch) > 1
e-5) {
3166 <<
" pitch between wires W:" << (w-1) <<
" and W:" << w
3167 <<
" is " << thisPitch <<
" cm, not " << expectedPitch
3175 if (nPitchErrors > 0) {
3177 <<
"unexpected pitches between " << nPitchErrors <<
" wires!";
3201 static double const V3 = std::sqrt(3.0);
3208 std::array<geo::PlaneGeo::WireCoordProjection_t, 5U>
const testProjections {{
3221 constexpr std::array<double, 5U> testDriftOffsets
3222 {{ -20.0, -10.0, 0.0, +10.0, +20.0 }};
3231 for (
auto const& testProjBase: testProjections) {
3236 double const expected = testProjBase.R() * pitch;
3240 for (
double dirL: { -1.0, 1.0 })
for (
double dirW: { -1.0, 1.0 })
for (
double scale: { 0.5, 1.0, 3.0 }) {
3246 { scale * dirL * testProjBase.X(), scale * dirW * testProjBase.Y() };
3248 double const interWireFromProj
3250 if (cmp.nonEqual(interWireFromProj, expected)) {
3252 <<
" distance between wires on projected direction " << testProj
3253 <<
" is " << interWireFromProj <<
" cm (expected: " 3261 double const dScale = expected / testProj.R();
3270 for (
double const driftOffset: testDriftOffsets) {
3271 auto const testDir = baseDir + driftOffset * normalDir;
3274 if (cmp.nonEqual(interWire, expected)) {
3276 <<
" projected distance between wires on direction " << testDir
3277 <<
" (from projection " << testProj <<
" and offset " 3278 << driftOffset <<
") is " << interWire <<
" cm (expected: " 3285 double const expected3D
3286 = std::sqrt(expectedSqr +
cet::square(driftOffset * dScale));
3289 if (cmp.nonEqual(interWire3D, expected3D)) {
3291 <<
" distance between wires on direction " << testDir
3292 <<
" (from projection " << testProj <<
" and offset " 3293 << driftOffset <<
") is " << interWire3D <<
" cm (expected: " 3294 << expected3D <<
")" 3312 <<
"unexpected distances in " << nErrors <<
" tests!";
3332 <<
"Using legacy plane pitch parameters hard-coded for the detector '" 3338 <<
"no expected plane pitch;" 3339 " I'll just check that they are all the same";
3343 log <<
"Expected plane pitch per plane pair, in centimetres:";
3348 unsigned int nPitchErrors = 0;
3352 const unsigned int nPlanes = TPC.
Nplanes();
3353 if (nPlanes < 2)
continue;
3355 double expectedPitch = 0.;
3359 <<
"Plane pitch between the first two planes of " << tpcid <<
": " 3360 << expectedPitch <<
" cm";
3364 while (++p < nPlanes) {
3379 if (
std::abs(thisPitch - expectedPitch) > 1
e-5) {
3380 mf::LogProblem(
"PlanePitch") <<
"ERROR: pitch of planes P:" << (p - 1)
3381 <<
" and P: " << p <<
" in " << tpcid
3382 <<
" is " << thisPitch <<
" cm, not " << expectedPitch
3390 if (nPitchErrors > 0) {
3392 <<
"unexpected pitches between " << nPitchErrors <<
" planes!";
3406 double xyz[3] = {0.};
3407 double xyzWire[3] = {0.};
3408 double dxyz[3] = {0.};
3409 double dxyzWire[3] = {0, sin(0.1), cos(0.1)};
3414 mf::LogVerbatim(
"GeometryTest") <<
"\n\t" << xyz[0] <<
"\t" << xyz[1] <<
"\t" << xyz[2] ;
3415 mf::LogVerbatim(
"GeometryTest") <<
"\t" << dxyz[0] <<
"\t" << dxyz[1] <<
"\t" << dxyz[2];
3417 gGeoManager->InitTrack(xyz, dxyz);
3418 for (
int i=0; i<10; ++i) {
3419 const double*
pos = gGeoManager->GetCurrentPoint();
3420 const double*
dir = gGeoManager->GetCurrentDirection();
3422 << gGeoManager->GetCurrentNode()->GetName()
3423 <<
"\n\t\tpos=" <<
"\t" 3427 <<
"\n\t\tdir=" <<
"\t" 3432 << gGeoManager->GetCurrentNode()->GetVolume()->GetMaterial()->GetName();
3434 gGeoManager->FindNextBoundary();
3435 gGeoManager->FindNormal();
3436 gGeoManager->Step(kTRUE,kTRUE);
3439 xyz[0] = 306.108; xyz[1] = -7.23775; xyz[2] = 856.757;
3440 gGeoManager->InitTrack(xyz, dxyz);
3442 << gGeoManager->GetCurrentNode()->GetName()
3444 << gGeoManager->GetCurrentNode()->GetVolume()->GetMaterial()->GetName();
3446 gGeoManager->GetCurrentNode()->GetVolume()->GetMaterial()->Print();
3459 double xyz[3] = { 0.0, 0.0, 0.0};
3460 double dxyz1[3] = { 1.0, 0.0, 0.0};
3461 double dxyz2[3] = {-1.0, 0.0, 0.0};
3462 double dxyz3[3] = { 0.0, 1.0, 0.0};
3463 double dxyz4[3] = { 0.0,-1.0, 0.0};
3464 double dxyz5[3] = { 0.0, 0.0, 1.0};
3465 double dxyz6[3] = { 0.0, 0.0,-1.0};
3469 if (
std::abs(xyzo[0]-xhi)>1.
E-6) abort();
3472 if (
std::abs(xyzo[0]-xlo)>1.
E-6) abort();
3475 if (
std::abs(xyzo[1]-yhi)>1.
E-6) abort();
3478 if (
std::abs(xyzo[1]-ylo)>1.
E-6) abort();
3481 if (
std::abs(xyzo[2]-zhi)>1.
E-6) abort();
3484 if (
std::abs(xyzo[2]-zlo)>1.
E-6) abort();
3498 <<
"Caught an exception while looking for aux det around " 3499 << lar::dump::array<3U>(
pos) <<
" (within aux det #" << expected
3500 <<
"); message:\n" << e.what();
3503 if (foundDet != expected) {
3505 <<
"Auxiliary detector at position " << lar::dump::array<3U>(
pos)
3506 <<
", expected within aux det #" << expected <<
", was returned to be " 3507 << foundDet <<
" instead";
3515 (
double const pos[3],
unsigned int expectedDet,
unsigned int expectedSens)
3525 <<
"Caught an exception while looking for aux det sensitive around " 3526 << lar::dump::array<3U>(
pos) <<
" (within aux det #" << expectedDet
3527 <<
" sensitive volume #" << expectedSens <<
"); message:\n" << e.what();
3530 if ((foundDet != expectedDet) || (foundSensDet != expectedSens)) {
3532 <<
"Auxiliary detector at position " << lar::dump::array<3U>(
pos)
3533 <<
", expected within aux det #" << expectedDet
3534 <<
", sensitive volume #" << expectedSens
3535 <<
", was returned to be in aux det #" 3536 << foundDet <<
" sensitive volume #" << foundSensDet <<
" instead";
3556 for (
unsigned int iDet = 0; iDet < nAuxDets; ++iDet) {
3561 if (nSensitive == 0) {
3562 std::array<double, 3U>
center;
3570 for (
unsigned int iDetSens = 0; iDetSens < nSensitive; ++iDetSens) {
3574 std::array<double, 3U>
center;
3589 <<
"Collected " << nErrors <<
" errors during testFindAuxDet() test!\n";
geo::TPCID const & ID() const
Returns the identifier of this TPC.
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void FindAuxDetSensitiveAtPosition(geo::Point_t const &point, std::size_t &adg, std::size_t &sv, double tolerance=0) const
Fills the indices of the sensitive auxiliary detector at location.
void GetStart(double *xyz) const
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
void testPlaneProjection() const
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
QDataStream & operator<<(QDataStream &s, const QString &str)
Utilities to extend the interface of geometry vectors.
geo::Point_t GetCenter() const
Returns the geometrical center of the cryostat.
GeometryTestAlg(fhicl::ParameterSet const &pset)
geo::Length_t CryostatHalfHeight(geo::CryostatID const &cid) const
Returns the height of the cryostat (y direction)
Vector DriftDir() const
Returns the direction of the drift (vector pointing toward the planes).
double z
z position of intersection
void testPlaneDirections() const
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
std::set< std::string > fNonFatalExceptions
void PrintTPCInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this TPC.
auto vector3D(Vector3D const &v)
Returns a manipulator which will print the specified vector.
Point GetActiveVolumeCenter() const
Returns the center of the TPC active volume in world coordinates [cm].
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
double HalfWidth2() const
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
unsigned int TotalNTPC() const
Returns the total number of TPCs in the detector.
constexpr bool nonEqual(Value_t a, Value_t b) const
Returns whether a and b are farther than the threshold.
Encapsulate the construction of a single cyostat.
unsigned int FindAuxDetAtPosition(double const worldLoc[3], double tolerance=0) const
Returns the index of the auxiliary detector at specified location.
CryostatGeo const & PositionToCryostat(geo::Point_t const &point) const
Returns the cryostat at specified location.
IteratorBox< plane_iterator,&GeometryCore::begin_plane,&GeometryCore::end_plane > IteratePlanes() const
Enables ranged-for loops on all planes of the detector.
decltype(auto) LengthDir() const
Returns the direction Length() is measured on.
Collect all the geometry header files together.
std::vector< double > fExpectedWirePitches
wire pitch on each plane
Classes identifying readout-related concepts.
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
void testPlaneProjectionReference() const
WireGeo const & Wire(unsigned int iwire) const
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
double ActiveHalfHeight() const
Half height (associated with y coordinate) of active TPC volume [cm].
Base forward iterator browsing all TPC IDs in the detector.
void testPlaneProjectionOnFrame() const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
AuxDetSensitiveGeo const & SensitiveVolume(size_t sv) const
double DistanceFrom(geo::WireGeo const &wire) const
Returns 3D distance from the specified wire.
unsigned int Nplanes() const
Number of planes in this tpc.
void WorldBox(double *xlo, double *xhi, double *ylo, double *yhi, double *zlo, double *zhi) const
Fills the arguments with the boundaries of the world.
Provides simple real number checks.
void AddToDefinition(std::string set_name, NAMES...names)
Parses a list of names and add them to the specified definition.
int wire_number
the invalid wire number
double MinX() const
Returns the world x coordinate of the start of the box.
unsigned int PlaneID_t
Type for the ID number.
The data type to uniquely identify a Plane.
bool isValid
Whether this ID points to a valid element.
Geometry information for a single TPC.
void testWireCoordAngle() const
double CenterX() const
Returns the world x coordinate of the center of the box.
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
const std::string GetWorldVolumeName() const
Return the name of the world volume (needed by Geant4 simulation)
#define MF_LOG_ERROR(category)
Names_t RejectedNames() const
Returns a list of names that were rejected.
double CenterZ() const
Returns the world z coordinate of the center of the box.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
CryostatID_t Cryostat
Index of cryostat.
void printDetectorIntro() const
std::vector< std::pair< geo::PlaneID, double > > ExpectedPlane_dTdW(std::array< double, 3 > const &A, std::array< double, 3 > const &B, const double driftVelocity=-0.1) const
Returns dT/dW expected from the specified segment A-to-B.
unsigned int MaxWires() const
Returns the largest number of wires among all planes in this detector.
double MaxX() const
Returns the world x coordinate of the end of the box.
ElementIteratorBox IterateWires() const
WireID_t Wire
Index of the wire within its plane.
double ActiveMass() const
void testWireOrientations() const
void ParseNames(NAMES...names)
Parses a list of names and adds them to the selector.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
void PrintConfiguration(std::ostream &) const
Prints the configuration into a stream.
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
Drift towards negative X values.
Rect const & ActiveArea() const
Returns an area covered by the wires in the plane.
Geometry information for a single cryostat.
Vector GetNormalDirection() const
Returns the direction normal to the plane.
virtual unsigned int Run()
Runs the test, returns a number of errors (very unlikely!)
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
static double WirePitch(geo::WireGeo const &w1, geo::WireGeo const &w2)
Returns the pitch (distance on y/z plane) between two wires, in cm.
geo::PlaneID ThirdPlane(geo::PlaneID const &pid1, geo::PlaneID const &pid2) const
Returns the plane that is not in the specified arguments.
double HalfWidth1() const
Vector GetIncreasingWireDirection() const
Returns the direction of increasing wires.
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int testThirdPlane_dTdW_at(std::vector< std::pair< geo::PlaneID, double >> const &plane_dTdW) const
Performs the third plane slope test with a single configuration.
Class for approximate comparisons.
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
double Width() const
Width is associated with x coordinate [cm].
bool shouldRunTests(std::string test_name) const
double Height() const
Height is associated with y coordinate [cm].
void testWireIntersection() const
double InterWireProjectedDistance(WireCoordProjection_t const &projDir) const
Returns the distance between wires along the specified direction.
std::string ROOTFile() const
Returns the full directory path to the geometry file source.
void DriftPoint(geo::Point_t &position, double distance) const
Shifts the position of an electron drifted by a distance.
bool isWireAlignedToPlaneDirections(geo::PlaneGeo const &plane, geo::Vector_t const &wireDir) const
Helper function for testWireIntersection().
unsigned int Nchannels() const
Returns the number of TPC readout channels in the detector.
void printChannelSummary()
double Length() const
Length is associated with z coordinate [cm].
double TotalMass() const
Returns the total mass [kg] of the specified volume (default: world).
geo::Point_t WiresIntersection(geo::WireGeo const &wireA, geo::WireGeo const &wireB)
Returns the point of wireA that is closest to wireB.
static lar::util::RealComparisons< geo::Length_t > coordIs
Value of tolerance for equality comparisons.
IteratorBox< plane_id_iterator,&GeometryCore::begin_plane_id,&GeometryCore::end_plane_id > IteratePlaneIDs() const
Enables ranged-for loops on all plane IDs of the detector.
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
void LocalToWorldVect(const double *wire, double *world) const
Transform direction vector from local to world.
double HalfWidth2() const
Point GetPositionFromCenter(double localz) const
Returns the position (world coordinate) of a point on the wire.
MaybeLogger_< ELseverityLevel::ELsev_error, true > LogProblem
std::vector< double > fExpectedPlanePitches
plane pitch on each plane
Names_t AcceptedNames() const
Returns a list of names that were accepted.
void testChannelToROP() const
double HalfHeight() const
View_t View() const
Which coordinate does this plane measure.
IteratorBox< wire_id_iterator,&GeometryCore::begin_wire_id,&GeometryCore::end_wire_id > IterateWireIDs() const
Enables ranged-for loops on all wire IDs of the detector.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthProjection_t
void LocalToWorld(const double *wire, double *world) const
Transform point from local wire frame to world frame.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
Planes that are in the horizontal plane.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
Point IntersectionWith(geo::WireGeo const &other) const
Returns the point of this wire that is closest to other wire.
int better_wire_number
a suggestion for a good wire number
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
testing::NameSelector fRunTests
test filter
Classes to project and compose a vector on a plane.
void testThirdPlane_dTdW() const
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
enum geo::driftdir DriftDirection_t
Drift direction: positive or negative.
void testInterWireProjectedDistance() const
double HalfHeight() const
double RMax() const
Returns the outer half-size of the wire [cm].
Collection of exceptions for Geometry system.
void Parse(LIST const &items)
Parses the names in the list and adds them to the selector.
raw::ChannelID_t FirstChannelInROP(readout::ROPID const &ropid) const
Returns the ID of the first channel in the specified readout plane.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WireCoordinateReferenceTag > WireCoordProjection_t
Type for projections in the wire base representation.
enum geo::_plane_sigtype SigType_t
IteratorBox< TPC_iterator,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs() const
Enables ranged-for loops on all TPCs of the detector.
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
void printAuxiliaryDetectors() const
Method to print the auxiliary detectors on screen.
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
void testStandardWirePos()
double HalfWidth() const
Half width of the cryostat [cm].
bool CheckQueryRegistry() const
Checks that no known element with valid response was left unqueried.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
double InterWireDistance(geo::Vector_t const &dir) const
Returns the distance between wires along the specified direction.
double MinZ() const
Returns the world z coordinate of the start of the box.
bool fDisableValidWireIDcheck
disable test on out-of-world NearestWire()
constexpr bool isValidChannelID(raw::ChannelID_t channel)
unsigned int NTPC() const
Number of TPCs in this cryostat.
constexpr Vector Xaxis()
Returns a x axis vector of the specified type.
Encapsulate the geometry of an auxiliary detector.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
size_t NSensitiveVolume() const
bool CheckAuxDetAtPosition(double const pos[3], unsigned int expected) const
Returns whether the auxiliary detector at pos is the expected one.
void testChannelToWire() const
Range_t width
Range along width direction.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
static int max(int a, int b)
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
#define MF_LOG_INFO(category)
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
Definition of data types for geometry description.
double Plane0Pitch(unsigned int p) const
void testWireCoordFromPlane() const
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
void printWiresInTPC(const TPCGeo &tpc, std::string indent="") const
Class identifying a set of planes sharing readout channels.
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
double ActiveLength() const
Length (associated with z coordinate) of active TPC volume [cm].
double MaxY() const
Returns the world y coordinate of the end of the box.
void testTPC(geo::CryostatID const &cid)
Orient_t Orientation() const
What is the orientation of the plane.
constexpr TPCID const & asTPCID() const
Conversion to TPCID (for convenience of notation).
Encapsulate the geometry of a wire.
std::vector< TGeoNode const * > FindAllVolumes(std::set< std::string > const &vol_names) const
Returns all the nodes with volumes with any of the specified names.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
double HalfHeight() const
Half height of the cryostat [cm].
readout::ROPID ChannelToROP(raw::ChannelID_t channel) const
double HalfHeight() const
Height is associated with y coordinate [cm].
Vector DepthDir() const
Return the direction of plane depth.
double HalfL() const
Returns half the length of the wire [cm].
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, geo::Point_t &intersection) const
Computes the intersection between two wires.
geo::TPCID::TPCID_t FindTPCAtPosition(double const worldLoc[3], double const wiggle) const
Returns the index of the TPC at specified location.
WireGeo const & Wire(geo::WireID const &wireid) const
Returns the specified wire.
unsigned int testFindCryostatVolumes()
void LocalToWorld(const double *cryo, double *world) const
Transform point from local cryostat frame to world frame.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
void testPlanePointDecompositionFrame() const
double DriftDistance() const
decltype(auto) HeightDir() const
Returns the direction Height() is measured on.
unsigned int testFindTPCvolumePaths()
WireCoordProjection_t VectorProjection(geo::Vector_t const &v) const
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Drift towards positive X values.
Encapsulate the construction of a single detector plane.
void testFindPlaneCenters()
void PrintPlaneInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Prints information about this plane.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double CenterY() const
Returns the world y coordinate of the center of the box.
geo::Length_t CryostatHalfWidth(geo::CryostatID const &cid) const
Returns the half width of the cryostat (x direction)
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
void GetEnd(double *xyz) const
void printAllGeometry() const
double y
y position of intersection
unsigned int testWireIntersectionAt(geo::TPCGeo const &TPC, TVector3 const &point) const
Performs the wire intersection test at a single point.
double MaxZ() const
Returns the world z coordinate of the end of the box.
geo::PlaneID const & ID() const
Returns the identifier of this plane.
void testParallelWires() const
constexpr bool nonZero(Value_t value) const
Returns whether the value is farther from 0 than the threshold.
unsigned int Nwires() const
Number of wires in this plane.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
bool WireIDincreasesWithZ() const
Returns whether the higher z wires have higher wire ID.
Some simple functions to represent geometry entities.
void testFindAuxDet() const
Vector WidthDir() const
Return the direction of plane width.
void testThirdPlane() const
geo::Length_t CryostatLength(geo::CryostatID const &cid) const
Returns the length of the cryostat (z direction)
unsigned int WireID_t
Type for the ID number.
Definitions of geometry vector data types.
Access the description of detector geometry.
std::vector< std::vector< TGeoNode const * > > FindAllVolumePaths(std::set< std::string > const &vol_names) const
Returns paths of all nodes with volumes with the specified names.
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
void testPlanePointDecomposition() const
Exception thrown on invalid wire number (e.g. NearestWireID())
void ProjectToBoxEdge(const double xyz[], const double dxyz[], double xlo, double xhi, double ylo, double yhi, double zlo, double zhi, double xyzout[])
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
double HalfWidth1() const
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
unsigned int Nviews() const
Returns the number of views (different wire orientations)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
auto const & get(AssnsNode< L, R, D > const &r)
#define MF_LOG_WARNING(category)
TPCID_t TPC
Index of the TPC within its cryostat.
Collection of Physical constants used in LArSoft.
raw::ChannelID_t NearestChannel(geo::Point_t const &worldLoc, geo::PlaneID const &planeid) const
Returns the ID of the channel nearest to the specified position.
unsigned int testFindWorldVolumes()
void printAuxDetSensitiveGeo(Stream &&out, geo::AuxDetSensitiveGeo const &auxDetSens, std::string indent, std::string firstIndent) const
Prints information of the sensitive auxiliary detector into a stream.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintTPCInfo().
LArSoft geometry interface.
double MinY() const
Returns the world y coordinate of the start of the box.
double ThirdPlane_dTdW(geo::PlaneID const &pid1, double slope1, geo::PlaneID const &pid2, double slope2, geo::PlaneID const &output_plane) const
Returns dT/dW on the third plane, given it in the other two.
void printAuxDetGeo(Stream &&out, geo::AuxDetGeo const &auxDet, std::string indent, std::string firstIndent) const
Prints information of an auxiliary detector into the specified stream.
Vector ComposeVector(WireDecomposedVector_t const &decomp) const
Returns the 3D vector from composition of projection and distance.
unsigned int MaxTPCs() const
Returns the largest number of TPCs a cryostat in the detector has.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
double RMin() const
Returns the inner radius of the wire (usually 0) [cm].
void GetCenter(double *xyz, double localz=0.0) const
Return the center position of an AuxDet.
void LocalToWorld(const double *plane, double *world) const
Transform point from local plane frame to world frame.
double HalfWidth() const
Width is associated with x coordinate [cm].
geo::GeometryCore const * geom
pointer to geometry service provider
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Data_t length() const
Returns the distance between upper and lower bounds.
double Length() const
Length of the cryostat [cm].
QTextStream & endl(QTextStream &s)
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
static std::array< double, 3 > GetIncreasingWireDirection(const geo::PlaneGeo &plane)
Returns the direction on plane orthogonal to wires where wire number increases.
Encapsulate the construction of a single detector plane.
The data type to uniquely identify a cryostat.
std::string GetLArTPCVolumeName(geo::TPCID const &tpcid) const
Return the name of specified LAr TPC volume.
void GetCenter(double *xyz, double localz=0.0) const
Return the center position of an AuxDet.
bool fComputeMass
Whether to print the detector mass.
decltype(auto) WidthDir() const
Returns the direction Width() is measured on.
bool CheckAuxDetSensitiveAtPosition(double const pos[3], unsigned int expectedDet, unsigned int expectedSens) const
Returns whether the auxiliary sensitive detector at pos is expected.