13 #include "art/Framework/Principal/Event.h"
14 #include "fhiclcpp/ParameterSet.h"
18 #include "TPolyLine3D.h"
19 #include "TPolyMarker3D.h"
26 : fUseCollectionOnly(pset.
get<
bool>(
"UseCollectionOnly"))
27 , fPFParticleLabel(pset.
get<art::InputTag>(
"PFParticleLabel"))
28 , fSCEXFlip(pset.
get<
bool>(
"SCEXFlip"))
29 , fSCE(lar::
providerFrom<spacecharge::SpaceChargeService>())
30 , fInitialTrackInputLabel(pset.
get<
std::string>(
"InitialTrackInputLabel"))
31 , fShowerStartPositionInputLabel(pset.
get<
std::string>(
"ShowerStartPositionInputLabel"))
32 , fShowerDirectionInputLabel(pset.
get<
std::string>(
"ShowerDirectionInputLabel"))
33 , fInitialTrackSpacePointsInputLabel(pset.
get<
std::string>(
"InitialTrackSpacePointsInputLabel"))
42 TVector3
const& ShowerStartPosition,
43 TVector3
const& ShowerDirection)
const
46 std::map<double, art::Ptr<recob::Hit>> OrderedHits;
47 art::Ptr<recob::Hit> startHit = hits.front();
56 double pitch =
fGeom->WirePitch(planeid);
58 TVector2 Shower2DStartPosition = {
59 fGeom->WireCoordinate(ShowerStartPosition, startHit->WireID().planeID()) * pitch,
60 ShowerStartPosition.X()};
63 TVector3 PlaneDirection =
fGeom->Plane(planeid).GetIncreasingWireDirection();
66 TVector2 Shower2DDirection = {ShowerDirection.Dot(PlaneDirection), ShowerDirection.X()};
68 Shower2DDirection = Shower2DDirection.Unit();
70 for (
auto const&
hit : hits) {
78 TVector2 hitcoord = HitCoordinates(detProp,
hit);
81 TVector2 pos = hitcoord - Shower2DStartPosition;
82 OrderedHits[pos * Shower2DDirection] =
hit;
86 std::vector<art::Ptr<recob::Hit>> showerHits;
89 std::back_inserter(showerHits),
90 [](std::pair<double, art::Ptr<recob::Hit>>
const&
hit) {
return hit.second; });
93 art::Ptr<recob::Hit> frontHit = showerHits.front();
94 art::Ptr<recob::Hit> backHit = showerHits.back();
97 TVector2 fronthitcoord = HitCoordinates(detProp, frontHit);
98 TVector2 frontpos = fronthitcoord - Shower2DStartPosition;
101 TVector2 backhitcoord = HitCoordinates(detProp, backHit);
102 TVector2 backpos = backhitcoord - Shower2DStartPosition;
104 double frontproj = frontpos * Shower2DDirection;
105 double backproj = backpos * Shower2DDirection;
107 std::reverse(showerHits.begin(), showerHits.end());
118 std::vector<art::Ptr<recob::SpacePoint>>& showersps,
120 TVector3
const& direction)
const
123 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
126 for (
auto const& sp : showersps) {
129 double perp = SpacePointPerpendicular(sp, vertex, direction);
132 OrderedSpacePoints[perp] = sp;
137 for (
auto const& sp : OrderedSpacePoints) {
138 showersps.push_back(sp.second);
146 std::vector<art::Ptr<recob::SpacePoint>>& showersps,
148 TVector3
const& direction)
const
151 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
154 for (
auto const& sp : showersps) {
157 double len = SpacePointProjection(sp, vertex, direction);
160 OrderedSpacePoints[len] = sp;
165 for (
auto const& sp : OrderedSpacePoints) {
166 showersps.push_back(sp.second);
172 std::vector<art::Ptr<recob::SpacePoint>>& showersps,
173 TVector3
const&
vertex)
const
176 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
179 for (
auto const& sp : showersps) {
182 double mag = (SpacePointPosition(sp) -
vertex).Mag();
185 OrderedSpacePoints[mag] = sp;
190 for (
auto const& sp : OrderedSpacePoints) {
191 showersps.push_back(sp.second);
197 std::vector<art::Ptr<recob::SpacePoint>>
const& showersps)
const
200 if (showersps.empty())
return TVector3{};
202 TVector3 centre_position;
203 for (
auto const& sp : showersps) {
204 TVector3 pos = SpacePointPosition(sp);
205 centre_position += pos;
207 centre_position *= (1. / showersps.size());
209 return centre_position;
216 std::vector<art::Ptr<recob::SpacePoint>>
const& showerspcs,
217 art::FindManyP<recob::Hit>
const& fmh)
const
220 float totalCharge = 0;
222 clockData, detProp, showerspcs, fmh, totalCharge);
229 std::vector<art::Ptr<recob::SpacePoint>>
const& showersps,
230 art::FindManyP<recob::Hit>
const& fmh,
231 float& totalCharge)
const
234 TVector3 pos, chargePoint = TVector3(0, 0, 0);
237 for (
auto const& sp : showersps) {
240 pos = SpacePointPosition(sp);
243 std::vector<art::Ptr<recob::Hit>>
const& hits = fmh.at(sp.key());
248 for (
auto const&
hit : hits) {
250 if (fUseCollectionOnly) {
252 charge =
hit->Integral();
270 if (!fUseCollectionOnly) {
272 float mean = charge / ((float)hits.size());
276 if (hits.size() > 1) {
277 rms = std::sqrt((charge2 - charge * charge) / ((
float)(hits.size() - 1)));
282 for (
auto const&
hit : hits) {
285 if (
hit->Integral() * lifetimecorrection > (mean - 2 * rms) &&
286 hit->Integral() * lifetimecorrection < (mean + 2 * rms)) {
287 charge +=
hit->Integral() * lifetimecorrection;
293 mf::LogWarning(
"LArPandoraShowerAlg") <<
"no points used to make the charge value. \n";
299 chargePoint += charge * pos;
300 totalCharge += charge;
303 mf::LogWarning(
"LArPandoraShowerAlg") <<
"Averaged charge, within 2 sigma, for a spacepoint "
304 "is zero, Maybe this not a good method. \n";
308 double intotalcharge = 1 / totalCharge;
309 TVector3 centre = chargePoint * intotalcharge;
318 const Double32_t* sp_xyz = sp->XYZ();
319 return TVector3{sp_xyz[0], sp_xyz[1], sp_xyz[2]};
324 art::Ptr<recob::SpacePoint>
const& sp_a,
325 art::Ptr<recob::SpacePoint>
const& sp_b)
const
327 TVector3 position_a = SpacePointPosition(sp_a);
328 TVector3 position_b = SpacePointPosition(sp_b);
329 return (position_a - position_b).Mag();
335 art::FindManyP<recob::Hit>
const& fmh)
const
341 std::vector<art::Ptr<recob::Hit>>
const& hits = fmh.at(sp.key());
342 for (
auto const&
hit : hits) {
343 Charge +=
hit->Integral();
346 Charge /= (float)hits.size();
354 art::FindManyP<recob::Hit>
const& fmh)
const
360 std::vector<art::Ptr<recob::Hit>>
const& hits = fmh.at(sp.key());
361 for (
auto const&
hit : hits) {
362 Time +=
hit->PeakTime();
365 Time /= (float)hits.size();
372 art::Ptr<recob::Hit>
const&
hit)
const
378 double pitch =
fGeom->WirePitch(planeid);
386 TVector3
const& direction)
const
393 return pos.Dot(direction);
399 TVector3
const& direction)
const
411 TVector3
const& direction,
419 pos = pos - proj * direction;
428 const TVector3& ShowerCentre,
429 const TVector3& Direction,
430 const unsigned int nSegments)
const
434 throw cet::exception(
"LArPandoraShowerAlg")
435 <<
"Unable to calculate RMS Shower Gradient with 0 segments" << std::endl;
437 if (sps.size() < 3)
return 0;
440 this->OrderShowerSpacePoints(sps, ShowerCentre, Direction);
443 const double minProj = this->SpacePointProjection(sps[0], ShowerCentre, Direction);
444 const double maxProj = this->SpacePointProjection(sps[sps.size() - 1], ShowerCentre, Direction);
446 const double length = (maxProj - minProj);
447 const double segmentsize = length / nSegments;
449 if (segmentsize < std::numeric_limits<double>::epsilon())
return 0;
451 std::map<int, std::vector<float>> len_segment_map;
454 for (
auto const& sp : sps) {
457 const double len = this->SpacePointProjection(sp, ShowerCentre, Direction);
460 const double len_perp = this->SpacePointPerpendicular(sp, ShowerCentre, Direction, len);
462 int sg_len = std::round(len / segmentsize);
463 len_segment_map[sg_len].push_back(len_perp);
473 for (
auto const& segment : len_segment_map) {
474 if (segment.second.size() < 2)
continue;
475 float RMS = this->CalculateRMS(segment.second);
478 if (RMS < 0)
continue;
481 sumx += segment.first;
483 sumx2 += segment.first * segment.first;
484 sumxy += RMS * segment.first;
488 const float denom = counter * sumx2 - sumx * sumx;
490 return std::abs(denom) < std::numeric_limits<float>::epsilon() ?
492 (counter * sumxy - sumx * sumy) / denom;
499 if (perps.size() < 2)
return std::numeric_limits<double>::lowest();
502 for (
const auto& perp : perps) {
506 return std::sqrt(sum / (perps.size() - 1));
513 unsigned int const&
TPC)
const
523 unsigned int const&
TPC)
const
526 if (!fSCE || !fSCE->EnableCalSpatialSCE()) {
527 throw cet::exception(
"LArPandoraShowerALG")
528 <<
"Trying to correct SCE pitch when service is not configured" << std::endl;
531 const geo::Point_t uncorrectedPos = pos + fSCE->GetPosOffsets(pos);
533 const geo::Vector_t posOffset = fSCE->GetCalPosOffsets(uncorrectedPos, TPC);
538 const geo::Vector_t nextPosOffset = fSCE->GetCalPosOffsets(nextPos, TPC);
541 const int xFlip(fSCEXFlip ? -1 : 1);
542 geo::Vector_t pitchVec{pitch * dir.X() + xFlip * (nextPosOffset.X() - posOffset.X()),
543 pitch * dir.Y() + (nextPosOffset.Y() - posOffset.Y()),
544 pitch * dir.Z() + (nextPosOffset.Z() - posOffset.Z())};
560 if (!fSCE || !fSCE->EnableSimEfieldSCE()) {
561 throw cet::exception(
"LArPandoraShowerALG")
562 <<
"Trying to correct SCE EField when service is not configured" << std::endl;
569 EFieldOffsets *= EField;
571 return EFieldOffsets.r();
576 art::Event
const& Event,
578 std::string
const& evd_disp_name_append)
const
581 std::cout <<
"Making Debug Event Display" << std::endl;
586 int run = Event.run();
587 int subRun = Event.subRun();
588 int event = Event.event();
589 int PFPID = pfparticle->Self();
592 TString canvasName = Form(
"canvas_%i_%i_%i_%i", run, subRun, event, PFPID);
593 if (evd_disp_name_append.length() > 0) canvasName +=
"_" + evd_disp_name_append;
594 TCanvas* canvas =
tfs->make<TCanvas>(canvasName, canvasName);
601 double x_min = std::numeric_limits<double>::max(), x_max = -std::numeric_limits<double>::max();
602 double y_min = std::numeric_limits<double>::max(), y_max = -std::numeric_limits<double>::max();
603 double z_min = std::numeric_limits<double>::max(), z_max = -std::numeric_limits<double>::max();
609 auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
612 art::FindManyP<recob::SpacePoint> fmspp(pfpHandle, Event, fPFParticleLabel);
613 if (!fmspp.isValid()) {
614 throw cet::exception(
"LArPandoraShowerAlg") <<
"Trying to get the spacepoint and failed. Somet\
615 hing is not configured correctly. Stopping ";
619 std::vector<art::Ptr<recob::SpacePoint>>
const& spacePoints = fmspp.at(pfparticle.key());
622 if (spacePoints.empty()) {
return; }
625 TVector3 showerStartPosition = {-999, -999, -999};
626 TVector3 showerDirection = {-999, -999, -999};
627 std::vector<art::Ptr<recob::SpacePoint>> trackSpacePoints;
632 double startXYZ[3] = {-999, -999, -999};
633 if (!ShowerEleHolder.
CheckElement(fShowerStartPositionInputLabel)) {
634 mf::LogError(
"LArPandoraShowerAlg") <<
"Start position not set, returning " << std::endl;
638 ShowerEleHolder.
GetElement(fShowerStartPositionInputLabel, showerStartPosition);
640 startXYZ[0] = showerStartPosition.X();
641 startXYZ[1] = showerStartPosition.Y();
642 startXYZ[2] = showerStartPosition.Z();
644 auto startPoly = std::make_unique<TPolyMarker3D>(1, startXYZ);
650 double xDirPoints[2] = {-999, -999};
651 double yDirPoints[2] = {-999, -999};
652 double zDirPoints[2] = {-999, -999};
658 auto allPoly = std::make_unique<TPolyMarker3D>(spacePoints.size());
660 if (!ShowerEleHolder.
CheckElement(fShowerDirectionInputLabel) &&
662 mf::LogError(
"LArPandoraShowerAlg") <<
"Direction not set, returning " << std::endl;
667 ShowerEleHolder.
GetElement(fShowerDirectionInputLabel, showerDirection);
670 double minProj = std::numeric_limits<double>::max();
671 double maxProj = -std::numeric_limits<double>::max();
676 for (
auto spacePoint : spacePoints) {
682 allPoly->SetPoint(point, x, y, z);
685 x_min = std::min(x, x_min);
686 x_max = std::max(x, x_max);
687 y_min = std::min(y, y_min);
688 y_max = std::max(y, y_max);
689 z_min = std::min(z, z_min);
690 z_max = std::max(z, z_max);
694 spacePoint, showerStartPosition, showerDirection);
695 maxProj = std::max(proj, maxProj);
696 minProj = std::min(proj, minProj);
699 xDirPoints[0] = (showerStartPosition.X() + minProj * showerDirection.X());
700 xDirPoints[1] = (showerStartPosition.X() + maxProj * showerDirection.X());
702 yDirPoints[0] = (showerStartPosition.Y() + minProj * showerDirection.Y());
703 yDirPoints[1] = (showerStartPosition.Y() + maxProj * showerDirection.Y());
705 zDirPoints[0] = (showerStartPosition.Z() + minProj * showerDirection.Z());
706 zDirPoints[1] = (showerStartPosition.Z() + maxProj * showerDirection.Z());
709 auto dirPoly = std::make_unique<TPolyLine3D>(2, xDirPoints, yDirPoints, zDirPoints);
715 auto trackPoly = std::make_unique<TPolyMarker3D>(trackSpacePoints.size());
716 if (!ShowerEleHolder.
CheckElement(fInitialTrackSpacePointsInputLabel)) {
717 mf::LogError(
"LArPandoraShowerAlg") <<
"TrackSpacePoints not set, returning " << std::endl;
721 ShowerEleHolder.
GetElement(fInitialTrackSpacePointsInputLabel, trackSpacePoints);
723 for (
auto spacePoint : trackSpacePoints) {
729 trackPoly->SetPoint(point, x, y, z);
731 x_min = std::min(x, x_min);
732 x_max = std::max(x, x_max);
733 y_min = std::min(y, y_min);
734 y_max = std::max(y, y_max);
735 z_min = std::min(z, z_min);
736 z_max = std::max(z, z_max);
746 std::vector<art::Ptr<recob::PFParticle>> pfps;
747 art::fill_ptr_vector(pfps, pfpHandle);
751 int pfpTrackCounter = 0;
752 int pfpShowerCounter = 0;
755 for (
auto const& pfp : pfps) {
756 std::vector<art::Ptr<recob::SpacePoint>>
const& sps = fmspp.at(pfp.key());
758 int pdg =
abs(pfp->PdgCode());
759 if (pdg == 11 || pdg == 22) { pfpShowerCounter += sps.size(); }
761 pfpTrackCounter += sps.size();
765 auto pfpPolyTrack = std::make_unique<TPolyMarker3D>(pfpTrackCounter);
766 auto pfpPolyShower = std::make_unique<TPolyMarker3D>(pfpShowerCounter);
770 int showerPoints = 0;
772 for (
auto const& pfp : pfps) {
773 std::vector<art::Ptr<recob::SpacePoint>>
const& sps = fmspp.at(pfp.key());
774 int pdg =
abs(pfp->PdgCode());
775 for (
auto sp : sps) {
782 x_min = std::min(x, x_min);
783 x_max = std::max(x, x_max);
784 y_min = std::min(y, y_min);
785 y_max = std::max(y, y_max);
786 z_min = std::min(z, z_min);
787 z_max = std::max(z, z_max);
790 if (pdg == 11 || pdg == 22) {
791 pfpPolyShower->SetPoint(showerPoints, x, y, z);
795 pfpPolyTrack->SetPoint(trackPoints, x, y, z);
808 auto TrackTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
809 auto TrackInitTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
811 if (ShowerEleHolder.
CheckElement(fInitialTrackInputLabel)) {
815 ShowerEleHolder.
GetElement(fInitialTrackInputLabel, InitialTrack);
828 TVector3 TrajPosition = {
829 TrajPositionPoint.X(), TrajPositionPoint.Y(), TrajPositionPoint.Z()};
831 TVector3 pos = TrajPosition;
836 TrackTrajPoly->SetPoint(point, x, y, z);
841 TVector3 TrajPosition = {
842 TrajInitPositionPoint.X(), TrajInitPositionPoint.Y(), TrajInitPositionPoint.Z()};
843 TVector3 pos = TrajPosition;
847 TrackInitTrajPoly->SetPoint(TrackInitTrajPoly->GetN(),
x,
y,
z);
851 gStyle->SetOptStat(0);
852 TH3F axes(
"axes",
"", 1, x_min, x_max, 1, y_min, y_max, 1, z_min, z_max);
853 axes.SetDirectory(0);
854 axes.GetXaxis()->SetTitle(
"X");
855 axes.GetYaxis()->SetTitle(
"Y");
856 axes.GetZaxis()->SetTitle(
"Z");
860 pfpPolyShower->SetMarkerStyle(20);
861 pfpPolyShower->SetMarkerColor(4);
862 pfpPolyShower->Draw();
863 pfpPolyTrack->SetMarkerStyle(20);
864 pfpPolyTrack->SetMarkerColor(6);
865 pfpPolyTrack->Draw();
866 allPoly->SetMarkerStyle(20);
868 trackPoly->SetMarkerStyle(20);
869 trackPoly->SetMarkerColor(2);
871 startPoly->SetMarkerStyle(21);
872 startPoly->SetMarkerSize(0.5);
873 startPoly->SetMarkerColor(3);
875 dirPoly->SetLineWidth(1);
876 dirPoly->SetLineColor(6);
878 TrackTrajPoly->SetMarkerStyle(22);
879 TrackTrajPoly->SetMarkerColor(7);
880 TrackTrajPoly->Draw();
881 TrackInitTrajPoly->SetMarkerStyle(22);
882 TrackInitTrajPoly->SetMarkerColor(4);
883 TrackInitTrajPoly->Draw();
void OrderShowerSpacePointsPerpendicular(std::vector< art::Ptr< recob::SpacePoint >> &showersps, TVector3 const &vertex, TVector3 const &direction) const
process_name opflash particleana ie ie ie z
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
double SCECorrectPitch(double const &pitch, TVector3 const &pos, TVector3 const &dir, unsigned int const &TPC) const
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
Utilities related to art service access.
void DebugEVD(art::Ptr< recob::PFParticle > const &pfparticle, art::Event const &Event, const reco::shower::ShowerElementHolder &ShowerEleHolder, std::string const &evd_disp_name_append="") const
process_name opflash particleana ie x
static constexpr Flag_t NoPoint
The trajectory point is not defined.
double CalculateRMS(const std::vector< float > &perps) const
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint >> &showersps, TVector3 const &vertex, TVector3 const &direction) const
Declaration of signal hit object.
Point_t const & LocationAtPoint(size_t i) const
The data type to uniquely identify a Plane.
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
double ElectronLifetime() const
WireID_t Wire
Index of the wire within its plane.
double RMSShowerGradient(std::vector< art::Ptr< recob::SpacePoint >> &sps, const TVector3 &ShowerCentre, const TVector3 &Direction, const unsigned int nSegments) const
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
double SCECorrectEField(double const &EField, TVector3 const &pos) const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
LArPandoraShowerAlg(const fhicl::ParameterSet &pset)
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
process_name opflash particleana ie ie y
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
bool CheckElement(const std::string &Name) const
constexpr PlaneID const & asPlaneID() const
Conversion to PlaneID (for convenience of notation).
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, TVector3 const &vertex, TVector3 const &direction) const
int GetElement(const std::string &Name, T &Element) const
Provides recob::Track data product.
double ConvertTicksToX(double ticks, int p, int t, int c) const
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Contains all timing reference information for the detector.
TVector2 HitCoordinates(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit) const
PointFlags_t const & FlagsAtPoint(size_t i) const
constexpr WireID()=default
Default constructor: an invalid TPC ID.
TVector3 ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
double SpacePointPerpendicular(art::Ptr< recob::SpacePoint > const &sp, TVector3 const &vertex, TVector3 const &direction) const
art::ServiceHandle< art::TFileService > tfs
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
BEGIN_PROLOG could also be cout
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
TVector3 SpacePointPosition(art::Ptr< recob::SpacePoint > const &sp) const
Signal from collection planes.
void OrderShowerHits(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> &hits, TVector3 const &ShowerDirection, TVector3 const &ShowerPosition) const