34 #include "cetlib/pow.h"
35 #include "cetlib_except/exception.h"
36 #include "fhiclcpp/ParameterSet.h"
37 #include "messagefacility/MessageLogger/MessageLogger.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() <<
" )";
90 bool hasCategory(cet::exception
const&
e, std::string
const& cat) {
91 for (
auto const& e_category: e.history())
92 if (e_category == cat)
return true;
98 template <
typename Vector>
99 std::string directionName(Vector
const& v) {
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(),
129 std::inserter(fNonFatalExceptions, fNonFatalExceptions.end()));
135 fRunTests.AddToDefinition(
"default",
136 "-CheckOverlaps",
"-ThoroughCheck",
"-PrintWires"
138 fRunTests.ParseNames(
"@default");
141 fRunTests.Parse(pset.get<std::vector<std::string>>(
"RunTests", {}));
143 std::ostringstream sstr;
144 fRunTests.PrintConfiguration(sstr);
146 mf::LogInfo(
"GeometryTestAlg") <<
"Test selection:" << sstr.str();
151 unsigned int GeometryTestAlg::Run()
155 throw cet::exception(
"GeometryTestAlg")
156 <<
"GeometryTestAlg not configured: no valid geometry provided.\n";
166 mf::LogVerbatim(
"GeometryTest") <<
"GeometryTest version 1.1";
168 mf::LogInfo(
"GeometryTestInfo")
169 <<
"Running on detector: '" << geom->DetectorName() <<
"'";
171 mf::LogVerbatim(
"GeometryTest")
172 <<
" Running on detector: '" << geom->DetectorName() <<
"'"
173 <<
"\nGeometry file: " << geom->ROOTFile();
176 if (shouldRunTests(
"DetectorIntro")) {
177 MF_LOG_INFO(
"GeometryTest") <<
"detector introduction:";
178 printDetectorIntro();
179 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
182 if (shouldRunTests(
"CheckOverlaps")) {
183 MF_LOG_INFO(
"GeometryTest") <<
"test for overlaps ...";
184 gGeoManager->CheckOverlaps(1e-5);
185 gGeoManager->PrintOverlaps();
186 if (!gGeoManager->GetListOfOverlaps()->IsEmpty()) {
187 mf::LogError(
"GeometryTest")
188 << gGeoManager->GetListOfOverlaps()->GetSize()
189 <<
" overlaps found in geometry during overlap test!";
192 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
195 if (shouldRunTests(
"ThoroughCheck")) {
196 MF_LOG_INFO(
"GeometryTest") <<
"thorough geometry test ...";
197 gGeoManager->CheckGeometryFull();
198 if (!gGeoManager->GetListOfOverlaps()->IsEmpty()) {
199 mf::LogError(
"GeometryTest")
200 << gGeoManager->GetListOfOverlaps()->GetSize()
201 <<
" overlaps found in geometry during thorough test!";
204 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
207 if (shouldRunTests(
"Cryostat")) {
208 MF_LOG_INFO(
"GeometryTest") <<
"test Cryostat methods ...";
210 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
213 if (shouldRunTests(
"FindVolumes")) {
214 MF_LOG_INFO(
"GeometryTest") <<
"test FindAllVolumes method ...";
216 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
219 if (shouldRunTests(
"PlaneDirections")) {
220 MF_LOG_INFO(
"GeometryTest") <<
"test plane directions...";
221 testPlaneDirections();
222 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
225 if (shouldRunTests(
"WireOrientations")) {
226 MF_LOG_INFO(
"GeometryTest") <<
"test wire orientations...";
227 testWireOrientations();
228 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
231 if (shouldRunTests(
"ChannelToROP")) {
232 MF_LOG_INFO(
"GeometryTest") <<
"test channel to ROP and back ...";
234 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
237 if (shouldRunTests(
"ChannelToWire")) {
238 MF_LOG_INFO(
"GeometryTest") <<
"test channel to plane wire and back ...";
240 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
243 if (shouldRunTests(
"FindPlaneCenters")) {
244 MF_LOG_INFO(
"GeometryTest") <<
"test find plane centers...";
245 testFindPlaneCenters();
246 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
249 if (shouldRunTests(
"WireCoordFromPlane")) {
250 MF_LOG_INFO(
"GeometryTest") <<
"test PlaneGeo::WireCoordinate...";
251 testWireCoordFromPlane();
252 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
255 if (shouldRunTests(
"ParallelWires")) {
256 MF_LOG_INFO(
"GeometryTest") <<
"test wire parallelism...";
258 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
261 if (shouldRunTests(
"PlanePointDecomposition")) {
262 MF_LOG_INFO(
"GeometryTest") <<
"test plane point decomposition...";
263 testPlanePointDecomposition();
264 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
267 if (shouldRunTests(
"PlaneProjections")) {
268 MF_LOG_INFO(
"GeometryTest") <<
"test PlaneGeo::PointProjection...";
269 testPlaneProjection();
270 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
273 if (shouldRunTests(
"WireCoordAngle")) {
274 MF_LOG_INFO(
"GeometryTest") <<
"testWireCoordAngle...";
275 testWireCoordAngle();
276 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
279 if (shouldRunTests(
"Projection")) {
280 MF_LOG_INFO(
"GeometryTest") <<
"testProject...";
282 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
285 if (shouldRunTests(
"WirePos")) {
286 MF_LOG_INFO(
"GeometryTest") <<
"testWirePos...";
289 MF_LOG_INFO(
"GeometryTest") <<
"disabled.";
292 if (shouldRunTests(
"NearestWire")) {
293 MF_LOG_INFO(
"GeometryTest") <<
"testNearestWire...";
295 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
298 if (shouldRunTests(
"WireIntersection")) {
299 MF_LOG_INFO(
"GeometryTest") <<
"testWireIntersection...";
300 testWireIntersection();
301 MF_LOG_INFO(
"GeometryTest") <<
"testWireIntersection complete";
304 if (shouldRunTests(
"ThirdPlane")) {
305 MF_LOG_INFO(
"GeometryTest") <<
"testThirdPlane...";
307 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
310 if (shouldRunTests(
"ThirdPlaneSlope")) {
311 MF_LOG_INFO(
"GeometryTest") <<
"testThirdPlaneSlope...";
312 testThirdPlane_dTdW();
313 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
316 if (shouldRunTests(
"WirePitch")) {
317 MF_LOG_INFO(
"GeometryTest") <<
"testWirePitch...";
319 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
322 if (shouldRunTests(
"InterWireProjectedDistance")) {
323 MF_LOG_INFO(
"GeometryTest") <<
"testInterWireProjectedDistance...";
324 testInterWireProjectedDistance();
325 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
328 if (shouldRunTests(
"PlanePitch")) {
329 MF_LOG_INFO(
"GeometryTest") <<
"testPlanePitch...";
331 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
334 if (shouldRunTests(
"Stepping")) {
335 MF_LOG_INFO(
"GeometryTest") <<
"testStepping...";
337 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
340 if (shouldRunTests(
"FindAuxDet")) {
341 MF_LOG_INFO(
"GeometryTest") <<
"testFindAuxDet...";
343 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
346 if (shouldRunTests(
"PrintWires")) {
347 MF_LOG_INFO(
"GeometryTest") <<
"printAllGeometry...";
349 MF_LOG_INFO(
"GeometryTest") <<
"complete.";
352 catch (cet::exception &e) {
353 mf::LogWarning(
"GeometryTest") <<
"exception caught: \n" <<
e;
354 if (fNonFatalExceptions.count(e.category()) == 0)
throw;
357 std::ostringstream out;
358 if (!fRunTests.CheckQueryRegistry(out)) {
359 throw cet::exception(
"GeometryTest")
360 <<
"(postumous) configuration error detected!\n"
364 mf::LogInfo log(
"GeometryTest");
365 log <<
"Tests completed:";
366 auto tests_run = fRunTests.AcceptedNames();
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;
374 auto tests_skipped = fRunTests.RejectedNames();
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;
386 void GeometryTestAlg::printDetectorIntro()
const {
389 mf::LogVerbatim log(
"GeometryTest");
391 <<
"Wire Rmax " << testWire.
RMax()
392 <<
"\nWire length " << 2.*testWire.
HalfL()
393 <<
"\nWire Rmin " << testWire.
RMin()
398 <<
"\nTotal mass " << geom->TotalMass();
402 <<
"\nNumber of views " << geom->Nviews()
403 <<
"\nNumber of channels " << geom->Nchannels()
404 <<
"\nMaximum number of:"
405 <<
"\n TPC in a cryostat: " << geom->MaxTPCs()
406 <<
"\n planes in a TPC: " << geom->MaxPlanes()
407 <<
"\n wires in a plane: " << geom->MaxWires()
408 <<
"\nTotal number of TPCs " << geom->TotalNTPC()
409 <<
"\nAuxiliary detectors " << geom->NAuxDets()
416 void GeometryTestAlg::printChannelSummary()
418 static unsigned int OneSeg = 0;
419 static unsigned int TwoSegs = 0;
420 static unsigned int ThreeSegs = 0;
421 static unsigned int FourSegs = 0;
422 uint32_t channels = geom->Nchannels();
423 if(geom->NTPC() > 1) channels /= geom->NTPC()/2;
425 for(uint32_t c = 0; c < channels; c++){
427 unsigned int ChanSize = geom->ChannelToWire(c).size();
429 if (ChanSize==1) ++OneSeg;
430 else if(ChanSize==2) ++TwoSegs;
431 else if(ChanSize==3) ++ThreeSegs;
432 else if(ChanSize==4) ++FourSegs;
436 mf::LogVerbatim(
"GeometryTest") <<
"OneSeg: " << OneSeg
437 <<
", TwoSegs: " << TwoSegs
438 <<
", ThreeSegs: " << ThreeSegs
439 <<
", FourSegs: " << FourSegs;
444 void GeometryTestAlg::printVolBounds()
447 double world[3] = {0.};
448 for(
unsigned int c = 0; c < geom->Ncryostats(); ++c){
449 geom->Cryostat(c).LocalToWorld(origin, world);
451 mf::LogVerbatim(
"GeometryTest") <<
"Cryo " << c;
452 mf::LogVerbatim(
"GeometryTest") <<
" -x: " << world[0] - geom->Cryostat(c).HalfWidth();
453 mf::LogVerbatim(
"GeometryTest") <<
" +x: " << world[0] + geom->Cryostat(c).HalfWidth();
454 mf::LogVerbatim(
"GeometryTest") <<
" -y: " << world[1] - geom->Cryostat(c).HalfHeight();
455 mf::LogVerbatim(
"GeometryTest") <<
" +y: " << world[1] + geom->Cryostat(c).HalfHeight();
456 mf::LogVerbatim(
"GeometryTest") <<
" -z: " << world[2] - geom->Cryostat(c).Length()/2;
457 mf::LogVerbatim(
"GeometryTest") <<
" +z: " << world[2] + geom->Cryostat(c).Length()/2;
459 for(
unsigned int t = 0; t < geom->NTPC(c); ++t){
460 geom->Cryostat(c).TPC(t).LocalToWorld(origin, world);
462 mf::LogVerbatim(
"GeometryTest") <<
" TPC " << t;
463 mf::LogVerbatim(
"GeometryTest") <<
" -x: " << world[0] - geom->Cryostat(c).TPC(t).HalfWidth();
464 mf::LogVerbatim(
"GeometryTest") <<
" +x: " << world[0] + geom->Cryostat(c).TPC(t).HalfWidth();
465 mf::LogVerbatim(
"GeometryTest") <<
" -y: " << world[1] - geom->Cryostat(c).TPC(t).HalfHeight();
466 mf::LogVerbatim(
"GeometryTest") <<
" +y: " << world[1] + geom->Cryostat(c).TPC(t).HalfHeight();
467 mf::LogVerbatim(
"GeometryTest") <<
" -z: " << world[2] - geom->Cryostat(c).TPC(t).Length()/2;
468 mf::LogVerbatim(
"GeometryTest") <<
" +z: " << world[2] + geom->Cryostat(c).TPC(t).Length()/2;
478 void GeometryTestAlg::printDetDim()
480 for(
unsigned int c = 0; c < geom->Ncryostats(); ++c){
482 mf::LogVerbatim(
"GeometryTest") <<
"Cryo " << c;
483 mf::LogVerbatim(
"GeometryTest") <<
" width: "
484 << geom->CryostatHalfWidth(c);
485 mf::LogVerbatim(
"GeometryTest") <<
" height: "
486 << geom->CryostatHalfHeight(c);
487 mf::LogVerbatim(
"GeometryTest") <<
" length: "
488 << geom->CryostatLength(c);
490 mf::LogVerbatim(
"GeometryTest") <<
" TPC 0";
491 mf::LogVerbatim(
"GeometryTest") <<
" width: "
492 << geom->DetHalfWidth(0,c);
493 mf::LogVerbatim(
"GeometryTest") <<
" height: "
494 << geom->DetHalfHeight(0,c);
495 mf::LogVerbatim(
"GeometryTest") <<
" length: "
496 << geom->DetLength(0,c);
502 void GeometryTestAlg::printWirePos()
506 for(
unsigned int t=0; t<std::floor(geom->NTPC()/12)+1; ++t){
507 for(
unsigned int p=0;
p<3; ++
p){
508 for(
unsigned int w=0;
w<geom->Cryostat(0).TPC(t).Plane(
p).Nwires();
w++){
510 double xyz[3] = {0.};
511 geom->Cryostat(0).TPC(t).Plane(
p).Wire(
w).GetCenter(xyz);
513 std::cout <<
"WireID (" << cs <<
", " << t <<
", " <<
p <<
", " <<
w
514 <<
"): x = " << xyz[0]
515 <<
", y = " << xyz[1]
516 <<
", z = " << xyz[2] << std::endl;
524 void GeometryTestAlg::printWiresInTPC
527 const unsigned int nPlanes = tpc.
Nplanes();
530 mf::LogVerbatim(
"GeometryTest") << indent,
534 for(
unsigned int p = 0;
p < nPlanes; ++
p) {
536 const unsigned int nWires = plane.
Nwires();
539 mf::LogVerbatim(
"GeometryTest") << indent <<
" ", indent +
" ",
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;
555 mf::LogVerbatim(
"GeometryTest") << indent
557 <<
" at " << lar::dump::array<3>(center)
567 void GeometryTestAlg::printAllGeometry()
const {
568 const unsigned int nCryostats = geom->Ncryostats();
569 mf::LogVerbatim(
"GeometryTest") <<
"Detector " << geom->DetectorName()
570 <<
" has " << nCryostats <<
" cryostats:";
571 for(
unsigned int c = 0; c < nCryostats; ++c) {
573 const unsigned int nTPCs = cryostat.
NTPC();
574 mf::LogVerbatim(
"GeometryTest") <<
" cryostat #" << c <<
" at "
576 << nTPCs <<
" TPC(s):";
577 for(
unsigned int t = 0; t < nTPCs; ++t) {
579 printWiresInTPC(tpc,
" ");
582 printAuxiliaryDetectors();
583 mf::LogVerbatim(
"GeometryTest") <<
"End of detector "
584 << geom->DetectorName() <<
" geometry.";
589 void GeometryTestAlg::printAuxiliaryDetectors()
const {
591 mf::LogVerbatim log(
"GeometryTest");
593 unsigned int const nAuxDets = geom->NAuxDets();
594 log <<
"There are " << nAuxDets <<
" auxiliary detectors:";
595 for (
unsigned int iDet = 0; iDet < nAuxDets; ++iDet) {
596 log <<
"\n[#" << iDet <<
"] ";
597 printAuxDetGeo(log, geom->AuxDet(iDet),
" ",
"");
604 template <
typename Stream>
605 void GeometryTestAlg::printAuxDetGeo(
607 std::string indent, std::string firstIndent
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 ";
630 printAuxDetSensitiveGeo(
631 std::forward<Stream>(out),
636 out <<
"\n" << indent
638 for (
unsigned int iSens = 0; iSens < nSensitive; ++iSens) {
639 out <<
"\n" << indent <<
" [#" << iSens <<
"] ";
640 printAuxDetSensitiveGeo(std::forward<Stream>(out),
650 template <
typename Stream>
651 void GeometryTestAlg::printAuxDetSensitiveGeo(
653 std::string , std::string firstIndent
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);
674 void GeometryTestAlg::testCryostat()
676 mf::LogVerbatim(
"GeometryTest") <<
"There are " << geom->Ncryostats() <<
" cryostats in the detector";
681 mf::LogVerbatim log(
"GeometryTest");
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....";
709 geom->PositionToCryostat(worldLoc, cid);
711 catch(cet::exception &e){
712 mf::LogWarning(
"FailedToLocateCryostat") <<
"\n exception caught:" <<
e;
713 if (fNonFatalExceptions.count(e.category()) == 0)
throw;
715 if (cid != cryo.ID()) {
716 throw cet::exception(
"CryostatTest")
717 <<
"Geometry points the middle of cryostat " << std::string(cryo.ID())
718 <<
" to a different one (" << std::string(cid) <<
")\n";
720 MF_LOG_DEBUG(
"GeometryTest") <<
"done";
722 MF_LOG_DEBUG(
"GeometryTest") <<
"\t Now test the TPCs associated with this cryostat";
730 unsigned int GeometryTestAlg::testFindWorldVolumes() {
734 std::set<std::string> volume_names;
735 std::vector<TGeoNode const*> nodes;
738 volume_names.insert(geom->GetWorldVolumeName());
739 nodes = geom->FindAllVolumes(volume_names);
741 mf::LogVerbatim log(
"GeometryTest");
742 log <<
"Found " << nodes.size() <<
" world volumes '"
743 << geom->GetWorldVolumeName() <<
"':";
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) {
752 mf::LogError(
"GeometryTest")
753 <<
"Found " << nodes.size() <<
" world volumes '"
754 << geom->GetWorldVolumeName() <<
"! [expecting: one!!]";
761 unsigned int GeometryTestAlg::testFindCryostatVolumes() {
765 std::set<std::string> volume_names;
766 volume_names.insert(geom->GetWorldVolumeName());
767 volume_names.insert(
"volCryostat");
769 std::vector<TGeoNode const*> nodes = geom->FindAllVolumes(volume_names);
771 mf::LogVerbatim log(
"GeometryTest");
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() <<
")";
778 if (nodes.size() != (1 + geom->Ncryostats())) {
780 mf::LogError(
"GeometryTest")
781 <<
"Found " << nodes.size() <<
" world and cryostat volumes! "
782 "[expecting: 1 world and " << geom->Ncryostats() <<
" cryostats]";
789 unsigned int GeometryTestAlg::testFindTPCvolumePaths() {
794 std::set<std::string> volume_names;
796 volume_names.insert(
TPC.TotalVolume()->GetName());
799 const unsigned int NTPCs = geom->TotalNTPC();
801 std::vector<std::vector<TGeoNode const*>> node_paths
802 = geom->FindAllVolumePaths(volume_names);
804 mf::LogVerbatim log(
"GeometryTest");
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) {
823 mf::LogError(
"GeometryTest")
824 <<
"Found " << node_paths.size() <<
" TPC volumes! "
825 "[expecting: " << NTPCs <<
" TPCs]";
832 void GeometryTestAlg::testFindVolumes() {
842 nErrors += testFindWorldVolumes();
843 nErrors += testFindCryostatVolumes();
844 nErrors += testFindTPCvolumePaths();
847 throw cet::exception(
"FindVolumes")
848 <<
"Collected " << nErrors <<
" errors during FindAllVolumes() test!\n";
859 mf::LogVerbatim(
"GeometryTest") <<
"\tThere are " << cryo.
NTPC()
860 <<
" TPCs in the detector";
862 for(
size_t t = 0; t < cryo.
NTPC(); ++t){
868 mf::LogVerbatim log {
"GeometryTest" };
870 <<
"\n\t\tTPC " << tpcid
871 <<
" " << geom->GetLArTPCVolumeName(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();
900 (mf::LogVerbatim(
"GeometryTest") <<
"\t\t",
"\t\t ", 8);
902 mf::LogVerbatim(
"GeometryTest")
908 mf::LogVerbatim(
"GeometryTest")
909 <<
"\t\tdrift direction is towards negative values: "
913 mf::LogVerbatim(
"GeometryTest")
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";
933 MF_LOG_DEBUG(
"GeometryTest") <<
"done.";
941 void GeometryTestAlg::testPlaneDirections()
const {
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)) {
972 mf::LogProblem(
"GeometryTestAlg")
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)) {
992 mf::LogProblem(
"GeometryTestAlg")
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 <<
")";
1004 throw cet::exception(
"GeometryTestAlg")
1005 <<
"testPlaneDirections() accumulated " << nErrors
1006 <<
" errors (see messages above)\n";
1013 void GeometryTestAlg::testWireOrientations()
const {
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();
1044 mf::LogProblem(
"GeometryTestAlg")
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 <<
")";
1056 throw cet::exception(
"GeometryTestAlg")
1057 <<
"testWireOrientations() accumulated " << nErrors
1058 <<
" errors (see messages above)\n";
1065 void GeometryTestAlg::testWireCoordFromPlane()
const {
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) > 1e-4) {
1113 mf::LogProblem(
"GeometryTestAlg") <<
"Point " << point
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)";
1130 throw cet::exception(
"GeometryTestAlg")
1131 <<
"testWireCoordFromPlane() accumulated " << nErrors
1132 <<
" errors (see messages above)\n";
1139 void GeometryTestAlg::testParallelWires()
const {
1148 decltype(
auto) genDir = plane.GetWireDirection();
1155 decltype(
auto) wireDir = wire.Direction();
1157 if (vectorIs.nonEqual(wireDir, genDir)) {
1158 throw cet::exception(
"ParallelWires")
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";
1172 void GeometryTestAlg::testPlanePointDecomposition()
const {
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)) {
1238 mf::LogProblem(
"GeometryTestAlg")
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
1244 <<
" (on wire " << std::string(wireID) <<
")";
1250 auto const decomp = plane.DecomposePoint(point);
1251 if (coordIs.
nonEqual(decomp.distance, distance)) {
1253 mf::LogProblem(
"GeometryTestAlg")
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)) {
1261 mf::LogProblem(
"GeometryTestAlg")
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)) {
1270 mf::LogProblem(
"GeometryTestAlg")
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)) {
1284 mf::LogProblem(
"GeometryTestAlg")
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)) {
1292 mf::LogProblem(
"GeometryTestAlg")
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);
1305 mf::LogProblem(
"GeometryTestAlg")
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);
1336 mf::LogProblem(
"GeometryTestAlg")
1337 <<
"[testPlanePointDecomposition] DriftPoint(): "
1338 <<
"Point " << expectedPoint
1339 <<
" (distant " << distance <<
" cm from the plane)"
1340 <<
" (on wire " << std::string(wireID) <<
")"
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)) {
1357 mf::LogProblem(
"GeometryTestAlg")
1358 <<
"[testPlanePointDecomposition] isProjectionOnPlane(): "
1359 <<
"Point " << expectedPoint <<
" (center of " << wireID
1360 <<
") is not believed to be on the plane, but it should.";
1370 throw cet::exception(
"GeometryTestAlg")
1371 <<
"testPlanePointDecomposition() accumulated " << nErrors
1372 <<
" errors (see messages above)\n";
1379 void GeometryTestAlg::testWireCoordAngle()
const {
1390 for (
geo::PlaneID const& planeid: geom->IteratePlaneIDs()) {
1395 const unsigned int nWires = plane.
Nwires();
1398 geo::WireID next_wire_id(planeid, nWires / 2 + 1);
1400 if (next_wire_id.
Wire >= nWires) {
1401 throw cet::exception(
"WeirdGeometry")
1402 <<
"Plane " << std::string(planeid) <<
" has only " << nWires
1407 geo::WireGeo const& middle_wire = geom->Wire(middle_wire_id);
1408 decltype(
auto) middle_wire_center = middle_wire.
GetCenter();
1409 MF_LOG_TRACE(
"GeometryTest")
1410 <<
"Center of " << middle_wire_id <<
" at " << middle_wire_center;
1413 const double middle_coord = geom->WireCoordinate
1414 (middle_wire_center, planeid);
1416 if (
std::abs(middle_coord -
double(middle_wire_id.
Wire)) > 2e-3) {
1417 throw cet::exception(
"WireCoordAngle")
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";
1429 MF_LOG_TRACE(
"GeometryTest")
1430 <<
" pitch: " << pitch <<
" wire coord dir: cos(phi_z): "
1433 auto on_next_wire = middle_wire_center + pitch * wireCoordDir;
1435 const double next_coord = geom->WireCoordinate(on_next_wire, planeid);
1437 if (
std::abs(next_coord -
double(next_wire_id.
Wire)) > 2e-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
1444 throw cet::exception(
"WireCoordAngle")
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";
1456 void GeometryTestAlg::testChannelToROP()
const {
1462 throw cet::exception(
"testChannelToROP")
1463 <<
"ROP from an invalid channel ("
1468 catch (cet::exception
const& e) {
1469 mf::LogWarning(
"testChannelToROP")
1470 <<
"Non-compilant ChannelToROP() throws on invalid channel.";
1475 for (
raw::ChannelID_t channel = 0; channel < geom->Nchannels(); ++channel) {
1479 auto const firstChannel = geom->FirstChannelInROP(ropid);
1480 auto const lastChannel = firstChannel + geom->Nchannels(ropid);
1482 if ((channel < firstChannel) || (channel >= lastChannel)) {
1483 throw cet::exception(
"testChannelToROP")
1484 <<
"Channel " << channel <<
" comes from ROP " << std::string(ropid)
1485 <<
", which contains only channels from " << firstChannel
1486 <<
" to " << lastChannel <<
" (excluded)\n";
1495 void GeometryTestAlg::testChannelToWire()
const
1504 for(
geo::WireID testWireID: geom->IterateWireIDs()){
1509 throw cet::exception(
"BadChannelLookup")
1510 <<
"Invalid channel returned for wire " << std::string(testWireID)
1514 auto const wireIDs = geom->ChannelToWire(channel);
1516 if (wireIDs.empty()) {
1517 throw cet::exception(
"BadChannelLookup")
1518 <<
"List of wires for channel #" << channel <<
" is empty;"
1519 <<
" it should have contained at least " << std::string(testWireID)
1524 mf::LogError log(
"GeometryTest");
1525 log << wireIDs.size() <<
" wire IDs associated with channel #"
1527 for (
auto const& wid: wireIDs)
1528 log <<
"\n " << wid;
1529 throw cet::exception(
"BadChannelLookup")
1530 <<
"Wire " << std::string(testWireID) <<
" is on channel #" << channel
1531 <<
" but ChannelToWire() does not map the channel to that wire\n";
1536 auto const channelSigType = geom->SignalType(channel);
1537 if (channelSigType != geom->SignalType(testWireID.planeID())) {
1538 throw cet::exception(
"BadChannelLookup")
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);
1546 if (channelView != geom->Plane(testWireID).View()) {
1547 throw cet::exception(
"BadChannelLookup")
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) {
1558 throw cet::exception(
"BadChannelLookup")
1559 <<
"Geometry service claims channel #" << channel
1560 <<
" is on view " << channelView
1561 <<
" but its plane " << std::string(lastPlane)
1562 <<
" claims to be on view " << planeView <<
"\n";
1564 if (planeSigType != channelSigType) {
1565 throw cet::exception(
"BadChannelLookup")
1566 <<
"Geometry service claims channel #" << channel
1567 <<
" is if type " << channelSigType
1568 <<
" but its plane " << std::string(lastPlane)
1569 <<
" to be of type " << planeSigType <<
"\n";
1573 lastPlane = testWireID.planeID();
1574 planeView = channelView;
1575 planeSigType = channelSigType;
1583 void GeometryTestAlg::testFindPlaneCenters()
1585 double xyz[3] = {0.}, xyzW[3] = {0.};
1586 for(
size_t i = 0; i < geom->Nplanes(); ++i){
1587 geom->
Plane(i).LocalToWorld(xyz,xyzW);
1588 mf::LogVerbatim(
"GeometryTest") <<
"\n\tplane "
1589 << i <<
" is centered at (x,y,z) = ("
1590 << xyzW[0] <<
"," << xyzW[1]
1591 <<
"," << xyzW[2] <<
")";
1596 void GeometryTestAlg::testPlaneProjectionReference()
const {
1602 for (
auto const& plane: geom->IteratePlanes()) {
1604 TVector3 reference = plane.ProjectionReferencePoint();
1606 auto decomp = plane.DecomposePoint(reference);
1608 if (geom->coordIs.nonZero(decomp.distance)) {
1609 MF_LOG_ERROR(
"GeometryTest")
1610 <<
"Plane " << plane.ID() <<
" reference point " << reference
1611 <<
" has distance " << decomp.distance <<
" cm (should be 0)";
1615 if (geom->coordIs.nonZero(decomp.projection.X())
1616 || geom->coordIs.nonZero(decomp.projection.Y())
1619 MF_LOG_ERROR(
"GeometryTest")
1620 <<
"Plane " << plane.ID() <<
" reference point " << reference
1621 <<
" has projection ( " << decomp.projection.X()
1622 <<
" ; " << decomp.projection.Y() <<
" ) cm (should be (0;0) )";
1628 throw cet::exception(
"GeoTestPlaneProjectionReference")
1629 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
1635 void GeometryTestAlg::testPlanePointDecompositionFrame()
const {
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)) {
1706 mf::LogProblem(
"GeometryTestAlg")
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)) {
1721 mf::LogProblem(
"GeometryTestAlg")
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)) {
1730 mf::LogProblem(
"GeometryTestAlg")
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)) {
1740 mf::LogProblem(
"GeometryTestAlg")
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)) {
1755 mf::LogProblem(
"GeometryTestAlg")
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)) {
1764 mf::LogProblem(
"GeometryTestAlg")
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);
1778 mf::LogProblem(
"GeometryTestAlg")
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);
1810 mf::LogProblem(
"GeometryTestAlg")
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) {
1830 mf::LogProblem(
"GeometryTestAlg")
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") <<
".";
1846 throw cet::exception(
"GeometryTestAlg")
1847 <<
"testPlanePointDecomposition() accumulated " << nErrors
1848 <<
" errors (see messages above)\n";
1855 void GeometryTestAlg::testPlaneProjectionOnFrame()
const {
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) {
1914 mf::LogProblem(
"GeometryTestAlg")
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))
1939 mf::LogProblem(
"GeometryTestAlg")
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)) {
1959 mf::LogProblem(
"GeometryTestAlg")
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
1979 throw cet::exception(
"GeoTestPlaneProjection")
1980 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
1986 void GeometryTestAlg::testPlaneProjection()
const {
1992 testPlaneProjectionReference();
1997 testPlanePointDecompositionFrame();
2002 testPlaneProjectionOnFrame();
2009 void GeometryTestAlg::testStandardWirePos()
2011 double xyz[3] = {0.};
2012 double xyzprev[3] = {0.};
2013 for(
size_t cs = 0; cs < geom->Ncryostats(); ++cs){
2014 for(
size_t t = 0; t < geom->Cryostat(cs).NTPC(); ++t){
2015 const geo::TPCGeo* tpc = &geom->Cryostat(cs).TPC(t);
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";
2044 void GeometryTestAlg::testAPAWirePos()
2047 double tpcworld[3] = {0.};
2048 double xyz[3] = {0.};
2049 double xyzprev[3] = {0.};
2050 for(
size_t cs = 0; cs < geom->Ncryostats(); ++cs){
2051 for(
size_t t = 0; t < geom->Cryostat(cs).NTPC(); ++t){
2052 const geo::TPCGeo* tpc = &geom->Cryostat(cs).TPC(t);
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";
2088 inline std::array<double, 3> GeometryTestAlg::GetIncreasingWireDirection
2095 {{ IncreasingWireDir.X(), IncreasingWireDir.Y(), IncreasingWireDir.Z() }};
2100 void GeometryTestAlg::testNearestWire()
2106 TStopwatch stopWatch;
2109 bool bTestWireCoordinate =
true;
2115 const unsigned int NWires = plane.
Nwires();
2119 MF_LOG_DEBUG(
"GeoTestWireCoordinate")
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;
2140 nearest = geom->NearestChannel(wire_center, planeID);
2143 std::vector<double> posWorldV(3);
2144 for (
int i=0; i<3; ++i) {
2145 posWorldV[i] = wire_center[i] + 0.001;
2147 nearest = geom->NearestChannel(posWorldV, planeID);
2149 catch(cet::exception &e){
2150 mf::LogWarning(
"GeoTestCaughtException") <<
e;
2151 if (fNonFatalExceptions.count(e.category()) == 0)
throw;
2155 wireIDs = geom->ChannelToWire(nearest);
2157 if ( wireIDs.empty() ) {
2158 throw cet::exception(
"BadPositionToChannel")
2159 <<
"test point is at " << wire_center
2160 <<
" nearest channel is " << nearest
2161 <<
" for " << std::string(wireID)
2165 catch(cet::exception &e){
2166 mf::LogWarning(
"GeoTestCaughtException") <<
e;
2167 if (fNonFatalExceptions.count(e.category()) == 0)
throw;
2170 if(std::find(wireIDs.begin(), wireIDs.end(), wireID) == wireIDs.end()) {
2171 throw cet::exception(
"BadPositionToChannel")
2172 <<
"Current wire " << std::string(wireID)
2173 <<
" has a world position at " << wire_center
2174 <<
"\nNearestWire for this position is "
2175 << geom->NearestWire(wire_center, planeID)
2176 <<
"\nNearestChannel is " << nearest
2177 <<
"\nShould be channel " << geom->PlaneWireToChannel(wireID);
2189 const double pitch =
std::abs(geom->WirePitch(planeID));
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) {
2209 wire_from_wc = geom->WireCoordinate(wire_shifted, planeID);
2211 catch (cet::exception& e) {
2212 if (hasCategory(e,
"NotImplemented")) {
2213 MF_LOG_ERROR(
"GeoTestWireCoordinate")
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) {
2224 mf::LogError(
"GeoTestWireCoordinate")
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;
2239 wire_number_from_wc = geom->NearestWire(wire_shifted, planeID);
2241 catch (cet::exception& e) {
2242 throw cet::exception(
"GeoTestErrorWireCoordinate",
"", e)
2244 <<
"wire " << std::string(wireID)
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";
2252 if (mf::isDebugEnabled()) {
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 <<
").";
2264 MF_LOG_ERROR(
"GeoTestWireCoordinate") << e.str();
2267 mf::LogVerbatim(
"GeoTestWireCoordinate") << e.str();
2270 else if (wire_number_from_wc != expected_wire_number) {
2272 throw cet::exception(
"GeoTestErrorWireCoordinate")
2273 <<
"wire " << std::string(wireID)
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 <<
").";
2286 catch(cet::exception &e) {
2287 mf::LogWarning(
"GeoTestCaughtException") <<
e;
2288 if (fNonFatalExceptions.count(e.category()) == 0)
throw;
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";
2304 geom->WorldBox(
nullptr, posWorld + 0,
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;
2311 nearest_to_what = geom->NearestChannel(posWorld, 0, 0, 0);
2314 mf::LogWarning(
"GeoTestCaughtException") << e
2319 catch(cet::exception& e){
2320 mf::LogWarning(
"GeoTestCaughtException") <<
e;
2324 if (fDisableValidWireIDcheck) {
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.";
2336 throw cet::exception(
"GeoTestErrorNearestChannel")
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";
2347 bool GeometryTestAlg::isWireAlignedToPlaneDirections
2354 auto const isOrthogonalTo = [&wireDir](
geo::Vector_t const& other)
2371 void GeometryTestAlg::testWireIntersection()
const {
2390 MF_LOG_DEBUG(
"GeometryTest") <<
"Wire intersection test on " <<
TPC.ID();
2393 if (
TPC.ID().Cryostat < geom->Ncryostats() - 1) {
2400 = geom->Cryostat(
TPC.ID().Cryostat + 1);
2402 for (
geo::PlaneGeo const& plane: geom->IteratePlanes(otherCryo.ID())) {
2403 if (isWireAlignedToPlaneDirections(plane, wireDir))
continue;
2404 otherPlane = &plane;
2409 MF_LOG_TRACE(
"GeometryTest")
2410 <<
"Off cryostat test (" << w1 <<
"): chosen wire " << w2;
2412 if (geom->WireIDsIntersect(w1, w2, xingPoint)) {
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.";
2438 if (
TPC.ID().TPC < geom->NTPC(
TPC.ID().asCryostatID()) - 1) {
2447 for (
geo::PlaneGeo const& plane: geom->IteratePlanes(cryo.ID())) {
2449 if (isWireAlignedToPlaneDirections(plane, wireDir))
continue;
2450 otherPlane = &plane;
2455 MF_LOG_TRACE(
"GeometryTest")
2456 <<
"Off TPC test (" << w1 <<
"): chosen wire " << w2;
2458 if (geom->WireIDsIntersect(w1, w2, xingPoint)) {
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.";
2486 if (geom->WireIDsIntersect(w1, w2, xingPoint)) {
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;
2522 nErrors += testWireIntersectionAt(
TPC, point);
2528 throw cet::exception(
"GeoTestWireIntersection")
2529 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2535 unsigned int GeometryTestAlg::testWireIntersectionAt
2554 const unsigned int NPlanes = TPC.
Nplanes();
2560 std::vector<double> WirePitch(NPlanes);
2562 <decltype(std::declval<geo::PlaneGeo>().GetIncreasingWireDirection())>
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) {
2572 const double WireDistance = geom->WireCoordinate(point, plane.
ID());
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
2578 <<
" on plane " << std::string(plane.
ID())
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) {
2600 if (!geom->WireIDsIntersect(w1, w2, xingPoint)) {
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!";
2613 if (!geom->WireIDsIntersect(w1, w2, widIntersect)) {
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 <<
")!";
2634 if (!geom->WireIDsIntersect(w2, w1, xingPointInv)) {
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)) {
2643 MF_LOG_ERROR(
"GeometryTest")
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(
2662 (cet::square(d1) + cet::square(d2) - 2.0 * d1 * d2 * cosAlpha) / (1 - cet::square(cosAlpha))
2666 MF_LOG_DEBUG(
"GeometryTest")
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]) * 1e-3);
2675 if (wireCoordIs.
nonEqual(d, expected_d)) {
2676 MF_LOG_ERROR(
"GeometryTest")
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)) {
2691 MF_LOG_ERROR(
"GeometryTest")
2692 <<
"geo::WiresIntersection() gives wrong intersection for "
2693 << w1 <<
" and " << w2
2694 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2702 if (vectorIs.nonEqual(objXingPoint, xingPoint)) {
2703 MF_LOG_ERROR(
"GeometryTest")
2704 <<
"geo::WireGeo[" << w1
2705 <<
"]::IntersectionWith() gives wrong intersection with " << w2
2706 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2712 if (vectorIs.nonEqual(objXingPoint, xingPointInv)) {
2713 MF_LOG_ERROR(
"GeometryTest")
2714 <<
"geo::WireGeo[" << w2
2715 <<
"]::IntersectionWith() gives wrong intersection with " << w1
2716 <<
": " << objXingPoint <<
" vs. " << xingPoint <<
" (expected)";
2729 void GeometryTestAlg::testThirdPlane()
const {
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;
2763 third_plane = geom->ThirdPlane(pid1, pid2);
2765 catch (cet::exception
const& e) {
2766 if (isValidInput)
throw;
2769 bError = hasCategory(e,
"GeometryCore");
2772 MF_LOG_TRACE(
"GeometryTest")
2773 <<
" [" << pid1 <<
"], [" << pid2 <<
"] => "
2774 << (bError?
"error": std::string(third_plane));
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";
2822 throw cet::exception(
"GeoTestThirdPlane")
2823 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2830 void GeometryTestAlg::testThirdPlane_dTdW()
const {
2850 const double driftVelocity = 0.1
2853 const unsigned int NPlanes = TPC.
Nplanes();
2854 MF_LOG_DEBUG(
"GeometryTest") << tpcid <<
" (" << NPlanes <<
" planes)";
2857 if (tpcid.
Cryostat < geom->Ncryostats() - 1) {
2859 bool bError =
false;
2862 slope = geom->ThirdPlane_dTdW(
p1, +1.0, p2, -1.0);
2864 catch (cet::exception
const& e) {
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;
2883 slope = geom->ThirdPlane_dTdW(
p1, +1.0, p2, -1.0);
2885 catch (cet::exception
const& e) {
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
2934 = ExpectedPlane_dTdW(A, B, driftVelocity);
2936 if (mf::isDebugEnabled()) {
2937 mf::LogTrace log(
"GeometryTest");
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;
2946 nErrors += testThirdPlane_dTdW_at(dTdWs);
2953 throw cet::exception(
"GeoTestThirdPlane_dTdW")
2954 <<
"Accumulated " << nErrors <<
" errors (see messages above)\n";
2960 std::vector<std::pair<geo::PlaneID, double>>
2961 GeometryTestAlg::ExpectedPlane_dTdW(
2962 std::array<double, 3>
const&
A, std::array<double, 3>
const& B,
2963 const double driftVelocity
2971 geo::TPCID tpcid = geom->FindTPCAtPosition(A.data());
2974 throw cet::exception(
"GeometryTestAlg")
2975 <<
"ExpectedPlane_dTdW(): can't find any TPC containing point A ("
2976 << A[0] <<
"; " << A[1] <<
"; " << A[2] <<
")";
2979 if (geom->FindTPCAtPosition(B.data()) != tpcid) {
2980 throw cet::exception(
"GeometryTestAlg")
2981 <<
"ExpectedPlane_dTdW(): point A ("
2982 << A[0] <<
"; " << A[1] <<
"; " << A[2] <<
") is in "
2983 << std::string(tpcid)
2984 <<
" while point B (" << B[0] <<
"; " << B[1] <<
"; " << B[2]
2985 <<
") is in " << std::string(geom->FindTPCAtPosition(B.data()));
2991 double dT_over_dX = 1. / driftVelocity;
2996 dT_over_dX = -dT_over_dX;
3000 throw cet::exception(
"InternalError")
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);
3014 = geom->WireCoordinate(geo::vect::makeFromCoords<geo::Point_t>(A), pid);
3016 = geom->WireCoordinate(geo::vect::makeFromCoords<geo::Point_t>(B), pid);
3019 = std::make_pair(pid, ((B[0] - A[0]) * dT_over_dX) / (wB - wA));
3027 unsigned int GeometryTestAlg::testThirdPlane_dTdW_at
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.;
3048 output_slope = geom->ThirdPlane_dTdW(
3049 input1.first, input1.second,
3050 input2.first, input2.second,
3054 catch (cet::exception
const& e) {
3057 if (bValidInput)
throw;
3058 bError = hasCategory(e,
"GeometryCore");
3060 MF_LOG_TRACE(
"GeometryTest")
3061 << input1.first <<
" slope:" << input1.second
3062 <<
" " << input2.first <<
" slope:" << input2.second
3067 if (!bValidInput && !bError) {
3068 MF_LOG_ERROR(
"GeometryTest")
3069 <<
"GeometryCore::ThirdPlane_dTdW() on "
3070 << input1.first <<
" and " << input2.first
3071 <<
" should have thrown an exception, it returned "
3072 << output_slope <<
" instead";
3077 MF_LOG_TRACE(
"GeometryTest")
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))
3084 MF_LOG_ERROR(
"testThirdPlane_dTdW_at")
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 <<
")";
3103 void GeometryTestAlg::testWirePitch()
3106 unsigned int nPitchErrors = 0;
3108 if (fExpectedWirePitches.empty()) {
3112 if(geom->DetectorName() ==
"bo") {
3113 fExpectedWirePitches = { 0.46977, 0.46977, 0.46977 };
3115 if (!fExpectedWirePitches.empty()) {
3116 mf::LogInfo(
"WirePitch")
3117 <<
"Using legacy wire pitch parameters hard-coded for the detector '"
3118 << geom->DetectorName() <<
"'";
3121 if (fExpectedWirePitches.empty()) {
3122 mf::LogWarning(
"WirePitch")
3123 <<
"no expected wire pitch; I'll just check that they are all the same";
3126 mf::LogInfo log(
"WirePitch");
3127 log <<
"Expected wire pitch per plane, in centimetres:";
3128 for (
double pitch: fExpectedWirePitches) log <<
" " << pitch;
3132 for (
geo::PlaneID const& planeid: geom->IteratePlaneIDs()) {
3135 const unsigned int nWires = plane.
Nwires();
3136 if (nWires < 2)
continue;
3146 double expectedPitch = 0.;
3147 if (fExpectedWirePitches.empty()) {
3150 MF_LOG_DEBUG(
"WirePitch")
3151 <<
"Wire pitch on " << planeid <<
": " << expectedPitch <<
" cm";
3153 else if (planeid.Plane < fExpectedWirePitches.size())
3154 expectedPitch = fExpectedWirePitches[planeid.Plane];
3156 expectedPitch = fExpectedWirePitches.back();
3159 while (++w < nWires) {
3161 pWire = &(plane.
Wire(w));
3164 if (
std::abs(thisPitch - expectedPitch) > 1e-5) {
3165 mf::LogProblem(
"WirePitch") <<
"ERROR: on plane " << planeid
3166 <<
" pitch between wires W:" << (w-1) <<
" and W:" << w
3167 <<
" is " << thisPitch <<
" cm, not " << expectedPitch
3175 if (nPitchErrors > 0) {
3176 throw cet::exception(
"UnexpectedWirePitch")
3177 <<
"unexpected pitches between " << nPitchErrors <<
" wires!";
3183 void GeometryTestAlg::testInterWireProjectedDistance()
const {
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;
3237 double const expectedSqr = cet::square(expected);
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)) {
3251 mf::LogProblem(
"") <<
"ERROR: on plane " << plane.
ID()
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)) {
3275 mf::LogProblem(
"") <<
"ERROR: on plane " << plane.
ID()
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)) {
3290 mf::LogProblem(
"") <<
"ERROR: on plane " << plane.
ID()
3291 <<
" distance between wires on direction " << testDir
3292 <<
" (from projection " << testProj <<
" and offset "
3293 << driftOffset <<
") is " << interWire3D <<
" cm (expected: "
3294 << expected3D <<
")"
3311 throw cet::exception(
"InterWireProjectedDistance")
3312 <<
"unexpected distances in " << nErrors <<
" tests!";
3319 void GeometryTestAlg::testPlanePitch()
3327 if(geom->DetectorName() ==
"bo") {
3331 mf::LogInfo(
"PlanePitch")
3332 <<
"Using legacy plane pitch parameters hard-coded for the detector '"
3333 << geom->DetectorName() <<
"'";
3337 mf::LogWarning(
"PlanePitch")
3338 <<
"no expected plane pitch;"
3339 " I'll just check that they are all the same";
3342 mf::LogInfo log(
"PlanePitch");
3343 log <<
"Expected plane pitch per plane pair, in centimetres:";
3348 unsigned int nPitchErrors = 0;
3349 for (
geo::TPCID const& tpcid: geom->IterateTPCIDs()) {
3352 const unsigned int nPlanes = TPC.
Nplanes();
3353 if (nPlanes < 2)
continue;
3355 double expectedPitch = 0.;
3358 MF_LOG_DEBUG(
"PlanePitch")
3359 <<
"Plane pitch between the first two planes of " << tpcid <<
": "
3360 << expectedPitch <<
" cm";
3364 while (++p < nPlanes) {
3379 if (
std::abs(thisPitch - expectedPitch) > 1e-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) {
3391 throw cet::exception(
"UnexpectedPlanePitch")
3392 <<
"unexpected pitches between " << nPitchErrors <<
" planes!";
3399 void GeometryTestAlg::testStepping()
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)};
3411 geom->Plane(1).Wire(0).LocalToWorld(xyzWire,xyz);
3412 geom->Plane(1).Wire(0).LocalToWorldVect(dxyzWire,dxyz);
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();
3421 mf::LogVerbatim(
"GeometryTest") <<
"\tnode = "
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);
3441 mf::LogVerbatim(
"GeometryTest") <<
"\tnode = "
3442 << gGeoManager->GetCurrentNode()->GetName()
3444 << gGeoManager->GetCurrentNode()->GetVolume()->GetMaterial()->GetName();
3446 gGeoManager->GetCurrentNode()->GetVolume()->GetMaterial()->Print();
3452 void GeometryTestAlg::testProject()
3457 geom->WorldBox(&xlo, &xhi, &ylo, &yhi, &zlo, &zhi);
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();
3489 bool GeometryTestAlg::CheckAuxDetAtPosition
3490 (
double const pos[3],
unsigned int expected)
const
3492 unsigned int foundDet = std::numeric_limits<unsigned int>::max();
3494 foundDet = geom->FindAuxDetAtPosition(pos);
3496 catch (cet::exception
const& e) {
3497 mf::LogProblem(
"GeometryTestAlg")
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) {
3504 mf::LogProblem(
"GeometryTestAlg")
3505 <<
"Auxiliary detector at position " << lar::dump::array<3U>(pos)
3506 <<
", expected within aux det #" << expected <<
", was returned to be "
3507 << foundDet <<
" instead";
3514 bool GeometryTestAlg::CheckAuxDetSensitiveAtPosition
3515 (
double const pos[3],
unsigned int expectedDet,
unsigned int expectedSens)
3518 size_t foundDet = std::numeric_limits<unsigned int>::max();
3519 size_t foundSensDet = std::numeric_limits<unsigned int>::max();
3521 geom->FindAuxDetSensitiveAtPosition(pos, foundDet, foundSensDet);
3523 catch (cet::exception
const& e) {
3524 mf::LogProblem(
"GeometryTestAlg")
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)) {
3531 mf::LogProblem(
"GeometryTestAlg")
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";
3543 void GeometryTestAlg::testFindAuxDet()
const {
3554 unsigned int const nAuxDets = geom->NAuxDets();
3556 for (
unsigned int iDet = 0; iDet < nAuxDets; ++iDet) {
3561 if (nSensitive == 0) {
3562 std::array<double, 3U> center;
3565 if (!CheckAuxDetAtPosition(center.data(), iDet)) ++
nErrors;
3570 for (
unsigned int iDetSens = 0; iDetSens < nSensitive; ++iDetSens) {
3574 std::array<double, 3U> center;
3577 if (!CheckAuxDetAtPosition(center.data(), iDet)) ++
nErrors;
3578 if (!CheckAuxDetSensitiveAtPosition(center.data(), iDet, iDetSens))
3588 throw cet::exception(
"FindAuxDet")
3589 <<
"Collected " << nErrors <<
" errors during testFindAuxDet() test!\n";
3597 inline bool GeometryTestAlg::shouldRunTests(std::string test_name)
const {
3598 return fRunTests(test_name);
geo::TPCID const & ID() const
Returns the identifier of this TPC.
void GetStart(double *xyz) const
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Unit test for geometry functionalities.
geo::Point_t GetCenter() const
Returns the geometrical center of the cryostat.
GeometryTestAlg(fhicl::ParameterSet const &pset)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Vector DriftDir() const
Returns the direction of the drift (vector pointing toward the planes).
double z
z position of intersection
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
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
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.
decltype(auto) LengthDir() const
Returns the direction Length() is measured on.
Collect all the geometry header files together.
Encapsulate the geometry of the sensitive portion of an auxiliary detector.
BEGIN_PROLOG could also be cerr
Classes identifying readout-related concepts.
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
WireGeo const & Wire(unsigned int iwire) const
fExpectedPlanePitches(pset.get< std::vector< double >>("ExpectedPlanePitches",{}))
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.
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.
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.
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.
double CenterZ() const
Returns the world z coordinate of the center of the box.
CryostatID_t Cryostat
Index of cryostat.
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
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.
static double WirePitch(geo::WireGeo const &w1, geo::WireGeo const &w2)
Returns the pitch (distance on y/z plane) between two wires, in cm.
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.
Class for approximate comparisons.
double Width() const
Width is associated with x coordinate [cm].
double Height() const
Height is associated with y coordinate [cm].
double InterWireProjectedDistance(WireCoordProjection_t const &projDir) const
Returns the distance between wires along the specified direction.
void DriftPoint(geo::Point_t &position, double distance) const
Shifts the position of an electron drifted by a distance.
double Length() const
Length is associated with z coordinate [cm].
geo::Point_t WiresIntersection(geo::WireGeo const &wireA, geo::WireGeo const &wireB)
Returns the point of wireA that is closest to wireB.
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 caloskimCalorimetryCryoE physics caloskimCalorimetryCryoW physics path
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
double HalfWidth2() const
Point GetPositionFromCenter(double localz) const
Returns the position (world coordinate) of a point on the wire.
Access the description of detector geometry.
double HalfHeight() const
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.
Planes that are in the horizontal plane.
Collection of exceptions for Geometry system.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
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
Utilities to dump objects into a stream.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object.
Classes to project and compose a vector on a plane.
enum geo::driftdir DriftDirection_t
Drift direction: positive or negative.
double HalfHeight() const
Definitions of geometry vector data types.
double RMax() const
Returns the outer half-size of the wire [cm].
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WireCoordinateReferenceTag > WireCoordProjection_t
Type for projections in the wire base representation.
enum geo::_plane_sigtype SigType_t
double ActiveHalfWidth() const
Half width (associated with x coordinate) of active TPC volume [cm].
MF_LOG_WARNING("SimWire")<< "SimWire is an example module that works for the "<< "MicroBooNE detector. Each experiment should implement "<< "its own version of this module to simulate electronics "<< "response."
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
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.
auto end(FixedBins< T, C > const &) noexcept
Utilities to extend the interface of geometry vectors.
double MinZ() const
Returns the world z coordinate of the start of the box.
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.
size_t NSensitiveVolume() const
Range_t width
Range along width direction.
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
Definition of data types for geometry description.
double Plane0Pitch(unsigned int p) const
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
Class identifying a set of planes sharing readout channels.
fComputeMass(pset.get("ComputeMass", true))
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.
Encapsulate the geometry of an auxiliary detector.
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.
auto begin(FixedBins< T, C > const &) noexcept
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].
geo::TPCID::TPCID_t FindTPCAtPosition(double const worldLoc[3], double const wiggle) const
Returns the index of the TPC at specified location.
double DriftDistance() const
decltype(auto) HeightDir() const
Returns the direction Height() is measured on.
WireCoordProjection_t VectorProjection(geo::Vector_t const &v) const
Drift towards positive X values.
Encapsulate the construction of a single detector plane.
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.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
void GetEnd(double *xyz) const
double y
y position of intersection
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.
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
unsigned int Nwires() const
Number of wires in this plane.
bool WireIDincreasesWithZ() const
Returns whether the higher z wires have higher wire ID.
Some simple functions to represent geometry entities.
Vector WidthDir() const
Return the direction of plane width.
unsigned int WireID_t
Type for the ID number.
finds tracks best matching by angle
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.
std::size_t count(Cont const &cont)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
Collection of Physical constants used in LArSoft.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
static constexpr unsigned int MaxVerbosity
Maximum verbosity supported by PrintTPCInfo().
double MinY() const
Returns the world y coordinate of the start of the box.
Vector ComposeVector(WireDecomposedVector_t const &decomp) const
Returns the 3D vector from composition of projection and distance.
std::ostream & operator<<(std::ostream &out, lar::example::CheatTrack const &track)
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.
physics associatedGroupsWithLeft p1
BEGIN_PROLOG could also be cout
double HalfWidth() const
Width is associated with x coordinate [cm].
constexpr Point origin()
Returns a origin position with a point of the specified type.
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.
Encapsulate the construction of a single detector plane.
The data type to uniquely identify a cryostat.
void GetCenter(double *xyz, double localz=0.0) const
Return the center position of an AuxDet.
decltype(auto) WidthDir() const
Returns the direction Width() is measured on.