35 #include "nusimdata/SimulationBase/MCTruth.h"
36 #include "nusimdata/SimulationBase/MCNeutrino.h"
39 #include "art/Framework/Services/Registry/ServiceHandle.h"
40 #include "art/Framework/Core/EDFilter.h"
41 #include "art/Framework/Core/ModuleMacros.h"
42 #include "art/Framework/Principal/Event.h"
43 #include "art/Framework/Principal/Handle.h"
44 #include "canvas/Utilities/Exception.h"
45 #include "fhiclcpp/types/Sequence.h"
46 #include "fhiclcpp/types/OptionalSequence.h"
47 #include "fhiclcpp/types/Table.h"
48 #include "fhiclcpp/types/Atom.h"
49 #include "messagefacility/MessageLogger/MessageLogger.h"
172 Comment(
"minimum x coordinate of the volume [cm]")
176 Comment(
"minimum y coordinate of the volume [cm]")
180 Comment(
"minimum z coordinate of the volume [cm]")
184 Comment(
"maximum x coordinate of the volume [cm]")
188 Comment(
"maximum y coordinate of the volume [cm]")
192 Comment(
"maximum z coordinate of the volume [cm]")
205 Comment(
"selects only events with interactions in TPC active volumes"),
209 fhicl::OptionalSequence<fhicl::Table<BoxCoordConfig>>
volumeBoxes {
211 Comment(
"interactions in box volumes by world coordinates [cm]")
216 Comment(
"interactions in box volumes by name (std::regex pattern)"),
217 std::vector<std::string>{}
221 Name(
"interactionTypes"),
223 "require an interaction of one of these types (`simb::MCNeutrino::InteractionType()`)"
231 "require an interaction of charged or neutral current (\"CC\", \"NC\", \"any\")"
238 Comment(
"category name for message facility message stream"),
239 "FilterNeutrinosActiveVolume"
251 virtual bool filter(art::Event& event)
override;
254 virtual void endJob()
override;
285 (fhicl::OptionalSequence<fhicl::Table<BoxCoordConfig>>
const& boxConfig);
292 bool qualifying(simb::MCTruth
const& truth)
const;
305 template <
typename Coll>
306 static Coll
sorted(Coll
const& coll);
318 : art::EDFilter(config)
319 , fInteractions(sorted(config().interactionTypes()))
320 , fWeakCurrentType(config().weakCurrent())
327 log <<
"Filter configuration:";
329 if (!fInteractions.empty()) {
330 log <<
"\n * required one of these " <<
size(fInteractions)
331 <<
" interaction types:";
332 for (
int intType: fInteractions)
336 log <<
"\n * weak current type: " << std::string(fWeakCurrentType);
338 log <<
"\nConfiguration of qualifying volumes:";
345 if (config().inActive()) addActiveVolumes();
347 addVolumeBoxes(config().volumeBoxes);
349 for (std::string
const& volName: config().volumeNames())
350 addVolumeByName(volName);
356 && fInteractions.empty()
360 throw art::Exception(art::errors::Configuration)
361 <<
"No filtering action specified (volume, current nor interaction type).\n"
380 auto allTruth =
event.getMany<std::vector<simb::MCTruth>>();
382 if (allTruth.empty()) {
383 throw art::Exception(art::errors::ProductNotFound)
384 <<
event.id() <<
" has no truth information!\n";
388 <<
"Event " <<
event.id() <<
" (#" <<
fNObserved <<
") has "
389 << allTruth.size() <<
" truth data products.";
391 for (
auto const& handle: allTruth) {
393 art::InputTag
const& tag [[gnu::unused]] = handle.provenance()->inputTag();
395 std::vector<simb::MCTruth>
const& truths = *handle;
396 if (truths.empty()) {
398 <<
"No truth records from " << tag.encode() <<
": skipped.";
405 <<
"Processing record [" << (iTruth + 1U) <<
"/" << truths.size()
406 <<
"] from " << tag.encode();
412 <<
" (#" <<
fNObserved <<
") passes the filter in virtue of "
413 << tag.encode() <<
" record " << (iTruth + 1U)
424 <<
" passed so far).";
436 <<
"FilterNeutrinosActiveVolume: passed " << fNPassed <<
" / " << fNObserved
439 log <<
" (" << (float(fNPassed) * 100. / fNObserved) <<
"%)";
454 <<
"[volume #" << fVolumes.size() <<
"] active volume from " <<
TPC.ID()
455 <<
": [ " << box.
Min() <<
" -- " << box.
Max() <<
" ]";
457 fVolumes.push_back(box);
466 (fhicl::OptionalSequence<fhicl::Table<BoxCoordConfig>>
const& boxConfig)
468 std::vector<BoxCoordConfig> boxParams;
470 if (!boxConfig(boxParams))
return;
475 boxParam.Xmin(), boxParam.Xmax(),
476 boxParam.Ymin(), boxParam.Ymax(),
477 boxParam.Zmin(), boxParam.Zmax()
481 <<
"[volume #" << fVolumes.size() <<
"] box coordinates #" << iBox
482 <<
": [ " << box.
Min() <<
" -- " << box.Max() <<
" ]";
484 fVolumes.push_back(std::move(box));
493 (std::string
const& volumePattern)
501 std::regex
const namePattern { volumePattern };
502 std::vector<geo::GeoNodePath> volumePaths;
503 auto const matchMe = [&
pattern=namePattern](std::string
const&
s)
504 { std::smatch match;
return (std::regex_match(
s, match,
pattern)); };
505 auto const findVolume = [&volumePaths, &patternMatcher=matchMe](
auto&
path)
507 if (patternMatcher(
path.current().GetVolume()->GetName()))
508 volumePaths.push_back(
path);
514 navigator.
apply(findVolume);
516 if (volumePaths.empty()) {
517 throw art::Exception(art::errors::Configuration)
518 <<
"No volume matching '" << volumePattern
519 <<
"' has been found in the detector '" << geom.
DetectorName()
531 TGeoShape
const* pShape =
path.current().GetVolume()->GetShape();
532 auto pBox =
dynamic_cast<TGeoBBox
const*
>(pShape);
534 throw cet::exception(
"FilterNeutrinosActiveVolume") <<
"Volume '"
535 <<
path.current().GetName() <<
"' is a " << pShape->IsA()->GetName()
536 <<
", not a TGeoBBox.\n";
540 = geo::vect::makeFromCoords<geo::Point_t>(pBox->GetOrigin());
553 trans.Transform(origin - diag, min);
554 trans.Transform(origin + diag, max);
562 <<
" c* [volume #" << fVolumes.size() <<
"] volume box '"
563 <<
path.current().GetVolume()->GetName()
564 <<
"' [(" << (iVolume + 1U) <<
"/" << volumePaths.size()
565 <<
"): [ " << box.Min() <<
" -- " << box.Max() <<
" ]";
567 fVolumes.push_back(std::move(box));
571 return volumePaths.size();
577 (simb::MCTruth
const& truth)
const
590 if (!truth.NeutrinoSet()) {
592 <<
"Interaction does not qualify because it is not tagged as neutrino.";
596 simb::MCNeutrino
const& nuInfo = truth.GetNeutrino();
597 simb::MCParticle
const&
nu = nuInfo.Nu();
602 if (!fInteractions.empty() && !qualifyingInteractionType(nuInfo.InteractionType()))
614 if (!fVolumes.empty() && !qualifyingLocation({ nu.Vx(), nu.Vy(), nu.Vz() }))
625 (
int const interactionType)
const
630 <<
" (" << interactionType <<
")";
632 bool const pass = std::binary_search
633 (
begin(fInteractions),
end(fInteractions), interactionType);
634 log <<
" => :-" << (pass?
')':
'(');
643 (
int const CCNC)
const
649 <<
" (" << CCNC <<
")";
652 switch (fWeakCurrentType) {
658 log <<
" => :-" << (pass?
')':
'(');
670 log <<
"Interaction location: " << location <<
" cm";
673 if (!box.ContainsPosition(location))
continue;
675 log <<
" => in volume #" << iBox
676 <<
" [ " << box.Min() <<
" -- " << box.Max() <<
" ] => :-)";
688 template <
typename Coll>
692 auto sortedColl { coll };
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
fhicl::Atom< std::string > logCategory
icarus::WeakCurrentType const fWeakCurrentType
Selected weak current.
virtual void endJob() override
Framework hook: prints the summary of the passed events.
fhicl::OptionalSequence< fhicl::Table< BoxCoordConfig > > volumeBoxes
std::string const fLogCategory
Category name for the output stream.
fhicl::Atom< double > Zmax
Utilities related to art service access.
Represents a type of weak current.
std::string TruthInteractionTypeName(int type)
bool apply(geo::GeoNodePath &path, Op &&op) const
Applies the specified operation to all nodes under the path.
fhicl::Atom< double > Ymin
fhicl::Atom< std::string > weakCurrent
bool qualifyingInteractionType(int const interactionType) const
Returns whether the interaction type is qualifying.
art::EDFilter::Table< Config > Parameters
Executes an operation on all the nodes of the ROOT geometry.
fhicl::Atom< double > Xmax
Definition of util::enumerate().
fhicl::Atom< double > Xmin
Geometry information for a single TPC.
Class representing a path in ROOT geometry.
std::size_t size(FixedBins< T, C > const &) noexcept
std::string TruthCCNCname(int ccnc)
std::vector< geo::BoxBoundedGeo > fVolumes
Volumes for qualifying interactions.
Class representing a path in ROOT geometry.
std::atomic< unsigned int > fNPassed
Number of passed events.
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
unsigned addVolumeByName(std::string const &volumeName)
Adds all volName from geometry into the qualifying volume list.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Configuration parameter structure.
FilterNeutrinosActiveVolume(Parameters const &config)
Constructor: reads configuration and extracts information from geometry.
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
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Access the description of detector geometry.
Charged-current interactions.
bool qualifyingLocation(geo::Point_t const &location) const
Returns whether the location is among the accepted ones.
fhicl::Sequence< std::string > volumeNames
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
Definitions of geometry vector data types.
IteratorBox< TPC_iterator,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs() const
Enables ranged-for loops on all TPCs of the detector.
void addVolumeBoxes(fhicl::OptionalSequence< fhicl::Table< BoxCoordConfig >> const &boxConfig)
Adds the specified volumes into the qualifying volume list.
auto end(FixedBins< T, C > const &) noexcept
Utilities to extend the interface of geometry vectors.
BEGIN_PROLOG vertical distance to the surface Name
fhicl::Atom< double > Ymax
geo::Point_t Min() const
Returns the corner point with the smallest coordinates.
Description of geometry of one entire detector.
std::vector< int > const fInteractions
List of qualifying interaction types.
A C++ type to describe the type of weak current.
fhicl::Atom< bool > inActive
Provides a base class aware of world box coordinates.
auto begin(FixedBins< T, C > const &) noexcept
fhicl::Sequence< int > interactionTypes
fhicl::Atom< double > Zmin
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Configuration of box volume geometry.
std::atomic< unsigned int > fNObserved
Number of observed events.
then echo File list $list not found else cat $list while read file do echo $file sed s
Utility functions to print MC truth information.
bool qualifying(simb::MCTruth const &truth) const
Returns whether the interaction described in truth qualifies.
Functions pulling in STL customization if available.
Neutral-current interactions.
virtual bool filter(art::Event &event) override
Framework hook: applies the filter.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
bool qualifyingWeakCurrent(int const CCNC) const
Returns whether the weak current type is qualifying.
constexpr WeakCurrentType AnyWeakCurrentType
Constant value for any weak current type.
geo::Point_t Max() const
Returns the corner point with the largest coordinates.
art framework interface to geometry description
ROOT::Math::Transform3D TransformationMatrix
Type of transformation matrix used in geometry.
constexpr Point origin()
Returns a origin position with a point of the specified type.
static Coll sorted(Coll const &coll)
Returns a sorted copy of the specified collection.
Accepts only neutrino-like events with vertices in a specified volume.
void addActiveVolumes()
Adds all active volumes of detector into the qualifying volume list.