23 #include "art/Framework/Core/EDAnalyzer.h"
24 #include "art/Framework/Core/ModuleMacros.h"
25 #include "art/Framework/Principal/Event.h"
26 #include "art/Framework/Principal/Handle.h"
27 #include "canvas/Persistency/Common/FindManyP.h"
28 #include "canvas/Persistency/Common/FindOneP.h"
29 #include "canvas/Utilities/InputTag.h"
32 #include "messagefacility/MessageLogger/MessageLogger.h"
33 #include "fhiclcpp/types/Atom.h"
34 #include "fhiclcpp/types/Name.h"
35 #include "fhiclcpp/types/Comment.h"
38 #include "boost/test/unit_test.hpp"
45 #include <type_traits>
64 Comment(
"tag of the recob::Track data products to run the test on.")
72 : art::EDAnalyzer(config)
82 virtual void analyze(art::Event
const& event)
override;
91 auto getLongTracks(art::Event
const& event,
double minLength)
const;
97 void testTracks(art::Event
const& event)
const;
100 template <
typename Track>
109 template <
typename Cont,
typename Value>
110 std::size_t indexOf(Cont
const& cont, Value
const&
value) {
115 auto const it = std::find(
cbegin,
cend, value);
116 return (it ==
cend)? std::numeric_limits<std::size_t>::max(): (it -
cbegin);
122 template <
typename T>
123 bool areSameObject(T
const&
a, T
const& b)
124 {
return std::addressof(a) == std::addressof(b); }
126 template <
typename T>
128 areSameObject(T&&
a, T&& b)
136 template <
typename Track>
141 mf::LogVerbatim(
"ProxyBaseTest")
142 <<
"[#" << track.index() <<
"] track " << trackRef
143 <<
" " << track->Length() <<
" cm long, with "
144 << trackRef.
NPoints() <<
" points and "
145 << track.template get<recob::Hit>().
size()
165 auto tracks = proxy::getCollection<std::vector<recob::Track>>(
167 proxy::withAssociatedMeta<recob::Hit, recob::TrackHitMeta>()
171 mf::LogVerbatim(
"ProxyBaseTest") <<
"No tracks in '" << tracksTag.encode()
176 mf::LogVerbatim(
"ProxyBaseTest") <<
"Collection '" << tracksTag.encode()
177 <<
"' contains " <<
tracks.size() <<
" tracks.";
182 for (
auto trackInfo:
tracks) {
185 double const startTheta = track.
Theta();
187 double const length = trackInfo->Length();
190 decltype(
auto) hits = trackInfo.get<
recob::Hit>();
194 for (
auto const& hitInfo: hits) {
196 double const hitCharge = hitInfo->Integral();
199 if (onCollection(*hitInfo)) {
200 double const ds = hitInfo.data().Dx();
201 if (ds > 0.0) dQds.add(hitCharge / ds);
206 mf::LogVerbatim log(
"ProxyBaseTest");
208 <<
"[#" << trackInfo.index() <<
"] track ID=" << track.
ID()
209 <<
" (" << length <<
" cm, starting with theta=" << startTheta
210 <<
" rad) deposited charge=" << charge
211 <<
" with " << hits.size() <<
" hits";
213 log <<
" (<dQ/ds> = "
214 << dQds.Average() <<
" +/- " << dQds.RMS() <<
" Q/cm from "
215 << dQds.N() <<
" hits in collection planes)";
225 (art::Event
const& event,
double minLength)
const
232 auto tracks = proxy::getCollection<std::vector<recob::Track>>
233 (event, tracksTag, proxy::withAssociated<recob::Hit>() );
235 std::vector<decltype(tracks)::element_proxy_t> longTracks;
237 if (
track->Length() >= minLength) longTracks.push_back(
track);
247 auto const& expectedTracks
248 =
event.getProduct<std::vector<recob::Track>>(
tracksTag);
250 mf::LogInfo(
"ProxyBaseTest")
251 <<
"Starting test on " << expectedTracks.size() <<
" tracks from '"
254 auto directTracks = proxy::getCollection<std::vector<recob::Track>>(
256 , proxy::withParallelData<std::vector<recob::TrackFitHitInfo>>()
259 auto tracks = proxy::getCollection<std::vector<recob::Track>>(
261 , proxy::withParallelData<std::vector<recob::TrackFitHitInfo>>()
262 , proxy::wrapParallelDataAs<tag::TrackSubproxy>(directTracks)
277 auto const& expectedFitHitInfo
278 = *(
event.getValidHandle<std::vector<std::vector<recob::TrackFitHitInfo>>>
281 std::size_t iExpectedTrack = 0;
282 for (
auto trackProxy:
tracks) {
283 auto const& expectedTrack = expectedTracks[iExpectedTrack];
284 auto const& expectedTrackFitInfo = expectedFitHitInfo[iExpectedTrack];
288 (std::addressof(*directTrackProxy) == std::addressof(expectedTrack));
289 BOOST_TEST(directTrackProxy->ID() == expectedTrack.ID());
290 BOOST_TEST(directTrackProxy->Length() == expectedTrack.Length());
294 (directTrackProxy.get<std::vector<recob::TrackFitHitInfo>>()) ==
295 std::addressof(expectedTrackFitInfo)
309 BOOST_TEST(iExpectedTrack == expectedTracks.size());
316 auto expectedTracksHandle
317 =
event.getValidHandle<std::vector<recob::Track>>(
tracksTag);
318 auto const& expectedTracks = *expectedTracksHandle;
320 auto const& expectedTrackHitAssns = *(
322 <art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>(
tracksTag)
325 mf::LogInfo(
"ProxyBaseTest")
326 <<
"Starting test on " << expectedTracks.size() <<
" tracks from '"
329 art::FindManyP<recob::Hit, recob::TrackHitMeta> hitsPerTrack
330 (expectedTracksHandle, event,
tracksTag);
332 art::FindOneP<recob::TrackTrajectory> trajectoryPerTrack
333 (expectedTracksHandle, event,
tracksTag);
335 auto const& expectedTrackFitHitInfo
336 = *(
event.getValidHandle<std::vector<std::vector<recob::TrackFitHitInfo>>>
339 auto directTracks = proxy::getCollection<std::vector<recob::Track>>(
341 proxy::withParallelData<std::vector<recob::TrackFitHitInfo>>()
344 auto tracks = proxy::getCollection<std::vector<recob::Track>>(
346 , proxy::withAssociated<recob::Hit>()
347 , proxy::withAssociatedAs<recob::Hit, tag::SpecialHits>()
354 , proxy::wrapAssociatedAs<tag::DirectHitAssns>(expectedTrackHitAssns)
355 , proxy::wrapParallelDataAs<tag::DirectFitInfo>(expectedTrackFitHitInfo)
356 , proxy::wrapParallelDataAs<tag::TrackSubproxy>(directTracks)
357 , proxy::withZeroOrOne<recob::TrackTrajectory>(tracksTag)
364 "Track proxy does NOT have space points available!!!");
367 tracks.has<std::vector<recob::TrackFitHitInfo>>(),
368 "recob::TrackFitHitInfo not found!!!"
372 BOOST_TEST(
tracks.empty() == expectedTracks.empty());
373 BOOST_TEST(
tracks.size() == expectedTracks.size());
375 BOOST_TEST(
tracks.size() == expectedTrackFitHitInfo.size());
376 decltype(
auto) allFitHitInfo
377 =
tracks.get<std::vector<recob::TrackFitHitInfo>>();
379 std::is_lvalue_reference<decltype(allFitHitInfo)>(),
380 "Copy of parallel data!"
383 (allFitHitInfo.data() == std::addressof(expectedTrackFitHitInfo));
387 std::addressof(expectedTrackFitHitInfo)
391 directTracks.get<std::vector<recob::TrackFitHitInfo>>().data() ==
392 std::addressof(expectedTrackFitHitInfo)
397 std::addressof(directTracks)
402 BOOST_TEST(fitHitInfoSize == expectedTrackFitHitInfo.size());
405 std::size_t iExpectedTrack = 0;
406 for (
auto trackProxy:
tracks) {
407 auto const& expectedTrack = expectedTracks[iExpectedTrack];
408 art::Ptr<recob::Track>
const expectedTrackPtr
409 { expectedTracksHandle, iExpectedTrack };
410 auto const& expectedHits = hitsPerTrack.at(iExpectedTrack);
411 auto const& expectedHitMeta = hitsPerTrack.data(iExpectedTrack);
412 auto const& expectedFitHitInfo = expectedTrackFitHitInfo[iExpectedTrack];
413 art::Ptr<recob::TrackTrajectory>
const expectedTrajPtr
414 = trajectoryPerTrack.at(iExpectedTrack);
419 (!areSameObject(tracks[iExpectedTrack], tracks[iExpectedTrack]));
423 auto const trackProxyCopy = trackProxy;
424 BOOST_TEST(std::addressof(trackProxyCopy) != std::addressof(trackProxy));
427 (std::addressof(trackRef) == std::addressof(expectedTrack));
429 (std::addressof(*trackProxy) == std::addressof(expectedTrack));
432 BOOST_TEST(trackProxy.get<recob::Hit>().size() == expectedHits.size());
433 for (art::Ptr<recob::Hit>
const& hitPtr: trackProxy.get<recob::Hit>()) {
438 indexOf(expectedHits, hitPtr) !=
439 std::numeric_limits<std::size_t>::max()
444 BOOST_TEST(trackProxy.index() == iExpectedTrack);
446 std::vector<recob::TrackFitHitInfo>
const& fitHitInfo
447 = trackProxy.get<std::vector<recob::TrackFitHitInfo>>();
449 std::is_lvalue_reference<decltype(fitHitInfo)>(),
450 "Copy of parallel data element!"
453 (std::addressof(fitHitInfo) == std::addressof(expectedFitHitInfo));
454 BOOST_TEST(fitHitInfo.size() == expectedFitHitInfo.size());
458 std::addressof(expectedTrackFitHitInfo[iExpectedTrack])
474 (std::addressof(*directTrackProxy) == std::addressof(expectedTrack));
475 BOOST_TEST(directTrackProxy->ID() == expectedTrack.ID());
476 BOOST_TEST(directTrackProxy->Length() == expectedTrack.Length());
479 (directTrackProxy.get<std::vector<recob::TrackFitHitInfo>>()) ==
480 std::addressof(fitHitInfo)
491 !std::decay_t<decltype(hitPtr)>::hasMetadata(),
492 "Expected no metadata for tag::SpecialHits"
495 BOOST_TEST(!hitPtr.hasMetadata());
500 indexOf(expectedHits, hitPtr) !=
501 std::numeric_limits<std::size_t>::max()
508 BOOST_TEST(hits.size() == expectedHits.size());
510 unsigned int nSpecialHits = 0U;
511 for (
auto const& hitInfo: hits) {
518 std::decay_t<decltype(hitInfo)>::hasMetadata(),
519 "Expected metadata for tag::MetadataHits"
521 BOOST_TEST(hitInfo.hasMetadata());
524 art::Ptr<recob::Hit>
const& hitPtr = hitInfo;
528 auto const index = indexOf(expectedHits, hitPtr);
529 BOOST_TEST(index != std::numeric_limits<std::size_t>::max());
531 BOOST_TEST(&(hitInfo.main()) == &expectedTrack);
532 BOOST_TEST(hitInfo.mainPtr() == expectedTrackPtr);
534 if (index < expectedHitMeta.size()) {
535 art::Ptr<recob::Hit>
const& expectedHitPtr = expectedHits.at(index);
536 auto const& expectedMetadata = expectedHitMeta.at(index);
538 BOOST_TEST(hitInfo.valuePtr() == hitPtr);
540 (std::addressof(hitInfo.value()) == std::addressof(*hitPtr));
541 BOOST_TEST(hitInfo.key() == hitPtr.key());
542 BOOST_TEST(hitInfo.id() == hitPtr.id());
544 if (expectedHitPtr) {
546 BOOST_TEST(hitInfo.operator->() == hitPtr);
547 recob::Hit
const&
hit = *expectedHitPtr;
548 BOOST_TEST(std::addressof(*hitInfo) == std::addressof(hit));
551 BOOST_TEST(hitInfo.dataPtr() == expectedMetadata);
552 BOOST_TEST(&(hitInfo.data()) == expectedMetadata);
554 auto hitInfoCopy = hitInfo;
556 (
static_cast<art::Ptr<recob::Hit>
const&
>(hitInfo) == hitPtr);
558 (&(
static_cast<art::Ptr<recob::Hit>
const&
>(hitInfo)) == &hitPtr);
560 art::Ptr<recob::Hit> hitPtrMoved = std::move(hitInfoCopy);
561 BOOST_TEST(hitPtrMoved == hitPtr);
566 BOOST_TEST(nSpecialHits == expectedHits.size());
569 for (
auto iHit = hits.begin(); iHit != hits.end(); ++iHit) {
572 (iHit.hasMetadata(),
"Expected metadata for tag::MetadataHits");
575 art::Ptr<recob::Hit>
const& hitPtr = *iHit;
579 auto const index = indexOf(expectedHits, hitPtr);
580 BOOST_TEST(index != std::numeric_limits<std::size_t>::max());
582 BOOST_TEST(&(iHit.main()) == &expectedTrack);
583 BOOST_TEST(iHit.mainPtr() == expectedTrackPtr);
585 if (index < expectedHitMeta.size()) {
586 art::Ptr<recob::Hit>
const& expectedHitPtr = expectedHits.at(index);
587 auto const* expectedMetadata = expectedHitMeta.at(index);
589 BOOST_TEST(iHit.valuePtr() == hitPtr);
591 (std::addressof(iHit.value()) == std::addressof(*hitPtr));
593 BOOST_TEST(iHit.dataPtr() == expectedMetadata);
594 BOOST_TEST(std::addressof(iHit.data()) == expectedMetadata);
596 BOOST_TEST(iHit.valuePtr() == expectedHitPtr);
597 BOOST_TEST(iHit.dataPtr() == expectedMetadata);
602 BOOST_TEST(nSpecialHits == expectedHits.size());
608 BOOST_TEST(trackProxy->NPoints() == expectedTrack.NPoints());
613 if (expectedTrajPtr.isNull()) {
622 BOOST_TEST(iExpectedTrack == expectedTracks.size());
631 const double minLength = 30.0;
644 mf::LogVerbatim(
"ProxyBaseTest")
645 << longTracks.size() <<
" tracks are longer than " << minLength <<
" cm:";
646 std::for_each(longTracks.begin(), longTracks.end(),
void testProxyComposition(art::Event const &event) const
Tests proxy composition.
ProxyBaseTest & operator=(ProxyBaseTest const &)=delete
art::EDAnalyzer::Table< Config > Parameters
ClusterModuleLabel join with tracks
void testTracks(art::Event const &event) const
Performs the actual test.
ProxyBaseTest(Parameters const &config)
Runs a test of proxy::Tracks interface.
Declaration of signal hit object.
virtual void analyze(art::Event const &event) override
auto withAssociatedMetaAs(Args &&...args)
Helper function to merge associated data with metadata.
std::size_t size(FixedBins< T, C > const &) noexcept
auto cbegin(FixedBins< T, C > const &) noexcept
process_name use argoneut_mc_hitfinder track
Classes gathering simple statistics.
void processTrack(Track const &track) const
Single-track processing function example.
Offers proxy::Tracks and proxy::Track class for recob::Track access.
auto cend(FixedBins< T, C > const &) noexcept
art::InputTag tracksTag
Tag for the input tracks.
auto withParallelData(Args &&...args)
Helper function to merge an auxiliary data product into the proxy.
auto getLongTracks(art::Event const &event, double minLength) const
Returns proxies to tracks longer than a certain length.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
A trajectory in space reconstructed from hits.
double Theta() const
Access to spherical or geographical angles at vertex or at any point.
auto end(FixedBins< T, C > const &) noexcept
BEGIN_PROLOG vertical distance to the surface Name
fhicl::Atom< art::InputTag > tracksTag
Provides recob::Track data product.
auto begin(FixedBins< T, C > const &) noexcept
void proxyUsageExample(art::Event const &event) const
An example of how to access the information via track proxy.
2D representation of charge deposited in the TDC/wire plane
Collects statistics on a single quantity (weighted)
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Signal from collection planes.