19 #include "TPolyLine3D.h" 20 #include "TPolyMarker3D.h" 27 : fUseCollectionOnly(pset.
get<bool>(
"UseCollectionOnly"))
28 , fPFParticleLabel(pset.
get<
art::InputTag>(
"PFParticleLabel"))
29 , fSCEXFlip(pset.
get<bool>(
"SCEXFlip"))
31 , fInitialTrackInputLabel(pset.
get<
std::string>(
"InitialTrackInputLabel"))
32 , fShowerStartPositionInputLabel(pset.
get<
std::string>(
"ShowerStartPositionInputLabel"))
33 , fShowerDirectionInputLabel(pset.
get<
std::string>(
"ShowerDirectionInputLabel"))
34 , fInitialTrackSpacePointsInputLabel(pset.
get<
std::string>(
"InitialTrackSpacePointsInputLabel"))
45 std::map<double, art::Ptr<recob::Hit>> OrderedHits;
58 TVector2 Shower2DStartPosition = {plane.WireCoordinate(ShowerStartPosition) * pitch,
59 ShowerStartPosition.X()};
62 auto const PlaneDirection = plane.GetIncreasingWireDirection();
65 TVector2 Shower2DDirection = {ShowerDirection.Dot(PlaneDirection), ShowerDirection.X()};
67 Shower2DDirection = Shower2DDirection.Unit();
74 if (WireID.
asPlaneID() != planeid) {
break; }
80 TVector2 pos = hitcoord - Shower2DStartPosition;
81 OrderedHits[pos * Shower2DDirection] =
hit;
85 std::vector<art::Ptr<recob::Hit>> showerHits;
86 std::transform(OrderedHits.begin(),
88 std::back_inserter(showerHits),
89 [](std::pair<double, art::Ptr<recob::Hit>>
const&
hit) {
return hit.second; });
97 TVector2 frontpos = fronthitcoord - Shower2DStartPosition;
101 TVector2 backpos = backhitcoord - Shower2DStartPosition;
103 double frontproj = frontpos * Shower2DDirection;
104 double backproj = backpos * Shower2DDirection;
106 std::reverse(showerHits.begin(), showerHits.end());
121 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
124 for (
auto const& sp : showersps) {
130 OrderedSpacePoints[perp] = sp;
135 for (
auto const& sp : OrderedSpacePoints) {
136 showersps.push_back(sp.second);
148 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
151 for (
auto const& sp : showersps) {
157 OrderedSpacePoints[len] = sp;
162 for (
auto const& sp : OrderedSpacePoints) {
163 showersps.push_back(sp.second);
171 std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
174 for (
auto const& sp : showersps) {
177 double mag = (sp->position() - vertex).R();
180 OrderedSpacePoints[mag] = sp;
185 for (
auto const& sp : OrderedSpacePoints) {
186 showersps.push_back(sp.second);
193 if (showersps.empty())
return {};
198 for (
auto const& sp : showersps) {
199 auto const pos = sp->position();
205 centre_position *= (1. / showersps.size());
206 return centre_position;
215 float totalCharge = 0;
217 clockData, detProp, showerspcs, fmh, totalCharge);
226 float& totalCharge)
const 231 for (
auto const& sp : showersps) {
234 std::vector<art::Ptr<recob::Hit>>
const&
hits = fmh.at(sp.key());
239 for (
auto const&
hit : hits) {
243 charge =
hit->Integral();
263 float mean = charge / ((float)hits.size());
267 if (hits.size() > 1) {
268 rms = std::sqrt((charge2 - charge * charge) / ((
float)(hits.size() - 1)));
273 for (
auto const&
hit : hits) {
274 double lifetimecorrection = std::exp((
sampling_rate(clockData) *
hit->PeakTime()) /
276 if (
hit->Integral() * lifetimecorrection > (mean - 2 * rms) &&
277 hit->Integral() * lifetimecorrection < (mean + 2 * rms)) {
278 charge +=
hit->Integral() * lifetimecorrection;
284 mf::LogWarning(
"LArPandoraShowerAlg") <<
"no points used to make the charge value. \n";
291 auto const pos = sp->position();
292 double const x = pos.X();
293 double const y = pos.Y();
294 double const z = pos.Z();
297 chargePoint.X() + charge *
x, chargePoint.Y() + charge *
y, chargePoint.Z() + charge *
z);
298 totalCharge += charge;
301 mf::LogWarning(
"LArPandoraShowerAlg") <<
"Averaged charge, within 2 sigma, for a spacepoint " 302 "is zero, Maybe this not a good method. \n";
306 double intotalcharge = 1 / totalCharge;
307 return chargePoint * intotalcharge;
324 std::vector<art::Ptr<recob::Hit>>
const&
hits = fmh.at(sp.
key());
325 for (
auto const&
hit : hits) {
326 Charge +=
hit->Integral();
329 Charge /= (float)hits.size();
341 std::vector<art::Ptr<recob::Hit>>
const&
hits = fmh.at(sp.
key());
342 for (
auto const&
hit : hits) {
343 Time +=
hit->PeakTime();
346 Time /= (float)hits.size();
367 auto const pos = sp->
position() - vertex;
370 return pos.Dot(direction);
392 pos = pos - proj * direction;
402 const unsigned int nSegments)
const 406 <<
"Unable to calculate RMS Shower Gradient with 0 segments" << std::endl;
408 if (sps.size() < 3)
return 0;
417 const double length = (maxProj - minProj);
418 const double segmentsize = length / nSegments;
420 if (segmentsize < std::numeric_limits<double>::epsilon())
return 0;
422 std::map<int, std::vector<float>> len_segment_map;
425 for (
auto const& sp : sps) {
433 int sg_len = std::round(len / segmentsize);
434 len_segment_map[sg_len].push_back(len_perp);
444 for (
auto const& segment : len_segment_map) {
445 if (segment.second.size() < 2)
continue;
449 if (RMS < 0)
continue;
452 sumx += segment.first;
454 sumx2 += segment.first * segment.first;
455 sumxy += RMS * segment.first;
459 const float denom = counter * sumx2 - sumx * sumx;
461 return std::abs(denom) < std::numeric_limits<float>::epsilon() ?
463 (counter * sumxy - sumx * sumy) / denom;
469 if (perps.size() < 2)
return std::numeric_limits<double>::lowest();
472 for (
const auto& perp : perps) {
476 return std::sqrt(sum / (perps.size() - 1));
482 unsigned int const& TPC)
const 487 <<
"Trying to correct SCE pitch when service is not configured" << std::endl;
501 geo::Vector_t pitchVec{pitch * dir.X() + xFlip * (nextPosOffset.X() - posOffset.X()),
502 pitch * dir.Y() + (nextPosOffset.Y() - posOffset.Y()),
503 pitch * dir.Z() + (nextPosOffset.Z() - posOffset.Z())};
515 <<
"Trying to correct SCE EField when service is not configured" << std::endl;
522 EFieldOffsets *= EField;
524 return EFieldOffsets.r();
527 std::map<art::Ptr<recob::Hit>, std::vector<art::Ptr<recob::Hit>>>
535 typedef std::pair<unsigned, std::vector<unsigned>> OrganizedHits;
536 struct HitIdentifier {
551 inline bool operator==(
const HitIdentifier& rhs)
const 553 return startTick == rhs.startTick && endTick == rhs.endTick && wire == rhs.wire;
557 inline bool operator>(
const HitIdentifier& rhs)
const {
return integral > rhs.integral; }
560 unsigned nplanes = 6;
561 std::vector<std::vector<OrganizedHits>> hits_org(nplanes);
562 std::vector<std::vector<HitIdentifier>> hit_idents(nplanes);
563 for (
unsigned i = 0; i <
hits.size(); i++) {
564 HitIdentifier this_ident(*
hits[i]);
567 bool found_snippet =
false;
568 for (
unsigned j = 0; j < hits_org[
hits[i]->WireID().Plane].size(); j++) {
569 if (this_ident == hit_idents[
hits[i]->
WireID().Plane][j]) {
570 found_snippet =
true;
571 if (this_ident > hit_idents[
hits[i]->
WireID().Plane][j]) {
572 hits_org[
hits[i]->WireID().Plane][j].second.push_back(
574 hits_org[
hits[i]->WireID().Plane][j].first = i;
575 hit_idents[
hits[i]->WireID().Plane][j] = this_ident;
578 hits_org[
hits[i]->WireID().Plane][j].second.push_back(i);
583 if (!found_snippet) {
584 hits_org[
hits[i]->WireID().Plane].push_back({i, {}});
585 hit_idents[
hits[i]->WireID().Plane].push_back(this_ident);
588 std::map<art::Ptr<recob::Hit>, std::vector<art::Ptr<recob::Hit>>> ret;
589 for (
auto const& planeHits : hits_org) {
590 for (
const OrganizedHits& hit_org : planeHits) {
591 std::vector<art::Ptr<recob::Hit>> secondaryHits{};
592 for (
const unsigned secondaryID : hit_org.second) {
593 secondaryHits.push_back(
hits[secondaryID]);
595 ret[
hits[hit_org.first]] = std::move(secondaryHits);
604 std::string
const& evd_disp_name_append)
const 607 std::cout <<
"Making Debug Event Display" << std::endl;
612 int run = Event.
run();
613 int subRun = Event.
subRun();
614 int event = Event.
event();
615 int PFPID = pfparticle->
Self();
618 TString canvasName = Form(
"canvas_%i_%i_%i_%i", run, subRun,
event, PFPID);
619 if (evd_disp_name_append.length() > 0) canvasName +=
"_" + evd_disp_name_append;
620 TCanvas* canvas =
tfs->make<TCanvas>(canvasName, canvasName);
627 double x_min = std::numeric_limits<double>::max(),
x_max = -std::numeric_limits<double>::max();
628 double y_min = std::numeric_limits<double>::max(), y_max = -std::numeric_limits<double>::max();
629 double z_min = std::numeric_limits<double>::max(), z_max = -std::numeric_limits<double>::max();
639 if (!fmspp.isValid()) {
640 throw cet::exception(
"LArPandoraShowerAlg") <<
"Trying to get the spacepoint and failed. Somet\ 641 hing is not configured correctly. Stopping ";
645 std::vector<art::Ptr<recob::SpacePoint>>
const& spacePoints = fmspp.at(pfparticle.
key());
648 if (spacePoints.empty()) {
return; }
653 std::vector<art::Ptr<recob::SpacePoint>> trackSpacePoints;
658 double startXYZ[3] = {-999, -999, -999};
660 mf::LogError(
"LArPandoraShowerAlg") <<
"Start position not set, returning " << std::endl;
666 startXYZ[0] = showerStartPosition.X();
667 startXYZ[1] = showerStartPosition.Y();
668 startXYZ[2] = showerStartPosition.Z();
670 auto startPoly = std::make_unique<TPolyMarker3D>(1, startXYZ);
676 double xDirPoints[2] = {-999, -999};
677 double yDirPoints[2] = {-999, -999};
678 double zDirPoints[2] = {-999, -999};
684 auto allPoly = std::make_unique<TPolyMarker3D>(spacePoints.size());
688 mf::LogError(
"LArPandoraShowerAlg") <<
"Direction not set, returning " << std::endl;
696 double minProj = std::numeric_limits<double>::max();
697 double maxProj = -std::numeric_limits<double>::max();
702 for (
auto spacePoint : spacePoints) {
703 auto const pos = spacePoint->position();
707 allPoly->SetPoint(point, x, y, z);
710 x_min = std::min(x, x_min);
712 y_min = std::min(y, y_min);
713 y_max = std::max(y, y_max);
714 z_min = std::min(z, z_min);
715 z_max = std::max(z, z_max);
719 spacePoint, showerStartPosition, showerDirection);
720 maxProj = std::max(proj, maxProj);
721 minProj = std::min(proj, minProj);
724 xDirPoints[0] = (showerStartPosition.X() + minProj * showerDirection.X());
725 xDirPoints[1] = (showerStartPosition.X() + maxProj * showerDirection.X());
727 yDirPoints[0] = (showerStartPosition.Y() + minProj * showerDirection.Y());
728 yDirPoints[1] = (showerStartPosition.Y() + maxProj * showerDirection.Y());
730 zDirPoints[0] = (showerStartPosition.Z() + minProj * showerDirection.Z());
731 zDirPoints[1] = (showerStartPosition.Z() + maxProj * showerDirection.Z());
734 auto dirPoly = std::make_unique<TPolyLine3D>(2, xDirPoints, yDirPoints, zDirPoints);
740 auto trackPoly = std::make_unique<TPolyMarker3D>(trackSpacePoints.size());
742 mf::LogError(
"LArPandoraShowerAlg") <<
"TrackSpacePoints not set, returning " << std::endl;
748 for (
auto spacePoint : trackSpacePoints) {
749 auto const pos = spacePoint->position();
753 trackPoly->SetPoint(point, x, y, z);
755 x_min = std::min(x, x_min);
757 y_min = std::min(y, y_min);
758 y_max = std::max(y, y_max);
759 z_min = std::min(z, z_min);
760 z_max = std::max(z, z_max);
770 std::vector<art::Ptr<recob::PFParticle>> pfps;
775 int pfpTrackCounter = 0;
776 int pfpShowerCounter = 0;
779 for (
auto const& pfp : pfps) {
780 std::vector<art::Ptr<recob::SpacePoint>>
const& sps = fmspp.at(pfp.key());
782 int pdg =
abs(pfp->PdgCode());
783 if (pdg == 11 || pdg == 22) { pfpShowerCounter += sps.size(); }
785 pfpTrackCounter += sps.size();
789 auto pfpPolyTrack = std::make_unique<TPolyMarker3D>(pfpTrackCounter);
790 auto pfpPolyShower = std::make_unique<TPolyMarker3D>(pfpShowerCounter);
794 int showerPoints = 0;
796 for (
auto const& pfp : pfps) {
797 std::vector<art::Ptr<recob::SpacePoint>>
const& sps = fmspp.at(pfp.key());
798 int pdg =
abs(pfp->PdgCode());
799 for (
auto const& sp : sps) {
800 auto const pos = sp->position();
804 x_min = std::min(x, x_min);
806 y_min = std::min(y, y_min);
807 y_max = std::max(y, y_max);
808 z_min = std::min(z, z_min);
809 z_max = std::max(z, z_max);
812 if (pdg == 11 || pdg == 22) {
813 pfpPolyShower->SetPoint(showerPoints, x, y, z);
817 pfpPolyTrack->SetPoint(trackPoints, x, y, z);
830 auto TrackTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
831 auto TrackInitTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
850 x = TrajPositionPoint.X();
851 y = TrajPositionPoint.Y();
852 z = TrajPositionPoint.Z();
853 TrackTrajPoly->SetPoint(point, x, y, z);
858 x = TrajInitPositionPoint.X();
859 y = TrajInitPositionPoint.Y();
860 z = TrajInitPositionPoint.Z();
861 TrackInitTrajPoly->SetPoint(TrackInitTrajPoly->GetN(),
x,
y,
z);
865 gStyle->SetOptStat(0);
866 TH3F axes(
"axes",
"", 1, x_min,
x_max, 1, y_min, y_max, 1, z_min, z_max);
867 axes.SetDirectory(0);
868 axes.GetXaxis()->SetTitle(
"X");
869 axes.GetYaxis()->SetTitle(
"Y");
870 axes.GetZaxis()->SetTitle(
"Z");
874 pfpPolyShower->SetMarkerStyle(20);
875 pfpPolyShower->SetMarkerColor(4);
876 pfpPolyShower->Draw();
877 pfpPolyTrack->SetMarkerStyle(20);
878 pfpPolyTrack->SetMarkerColor(6);
879 pfpPolyTrack->Draw();
880 allPoly->SetMarkerStyle(20);
882 trackPoly->SetMarkerStyle(20);
883 trackPoly->SetMarkerColor(2);
885 startPoly->SetMarkerStyle(21);
886 startPoly->SetMarkerSize(0.5);
887 startPoly->SetMarkerColor(3);
889 dirPoly->SetLineWidth(1);
890 dirPoly->SetLineColor(6);
892 TrackTrajPoly->SetMarkerStyle(22);
893 TrackTrajPoly->SetMarkerColor(7);
894 TrackTrajPoly->Draw();
895 TrackInitTrajPoly->SetMarkerStyle(22);
896 TrackInitTrajPoly->SetMarkerColor(4);
897 TrackInitTrajPoly->Draw();
virtual bool EnableSimEfieldSCE() const =0
SubRunNumber_t subRun() const
double SCECorrectPitch(double const &pitch, geo::Point_t const &pos, geo::Vector_t const &dir, unsigned int const &TPC) const
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
void OrderShowerSpacePointsPerpendicular(std::vector< art::Ptr< recob::SpacePoint >> &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
Utilities related to art service access.
size_t Self() const
Returns the index of this particle.
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
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
static constexpr Flag_t NoPoint
The trajectory point is not defined.
double CalculateRMS(const std::vector< float > &perps) const
constexpr bool operator>(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
virtual geo::Vector_t GetCalPosOffsets(geo::Point_t const &point, int const &TPCid) const =0
art::InputTag fPFParticleLabel
Declaration of signal hit object.
Point_t const & LocationAtPoint(size_t i) const
Access to track position at different points.
The data type to uniquely identify a Plane.
geo::Point_t position() const
Returns the position of the point in world coordinates [cm].
const std::string fInitialTrackInputLabel
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
constexpr auto abs(T v)
Returns the absolute value of the argument.
double ElectronLifetime() const
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
WireID_t Wire
Index of the wire within its plane.
geo::WireID const & WireID() const
Initial tdc tick for hit.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
LArPandoraShowerAlg(const fhicl::ParameterSet &pset)
geo::WireReadoutGeom const * fChannelMap
double SpacePointPerpendicular(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
virtual geo::Vector_t GetPosOffsets(geo::Point_t const &point) const =0
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
const std::string fInitialTrackSpacePointsInputLabel
key_type key() const noexcept
std::map< art::Ptr< recob::Hit >, std::vector< art::Ptr< recob::Hit > > > OrganizeHits(const std::vector< art::Ptr< recob::Hit >> &hits) const
bool CheckElement(const std::string &Name) const
const std::string fShowerDirectionInputLabel
EventNumber_t event() const
int GetElement(const std::string &Name, T &Element) const
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
void OrderShowerHits(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> &hits, geo::Point_t const &ShowerPosition, geo::Vector_t const &ShowerDirection) const
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const
const std::string fShowerStartPositionInputLabel
Detector simulation of raw signals on wires.
double ConvertTicksToX(double ticks, int p, int t, int c) const
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
art::ServiceHandle< art::TFileService > tfs
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
float PeakTime() const
Time of the signal peak, in tick units.
virtual bool EnableCalSpatialSCE() const =0
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Encapsulate the construction of a single detector plane .
LArSoft-specific namespace.
Contains all timing reference information for the detector.
Provides recob::Track data product.
geo::Point_t ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
TVector2 HitCoordinates(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit) const
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint >> &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
PointFlags_t const & FlagsAtPoint(size_t i) const
Access to i-th TrajectoryPoint or its Flags.
double RMSShowerGradient(std::vector< art::Ptr< recob::SpacePoint >> &sps, const geo::Point_t &ShowerCentre, const geo::Vector_t &Direction, const unsigned int nSegments) const
double SCECorrectEField(double const &EField, geo::Point_t const &pos) const
2D representation of charge deposited in the TDC/wire plane
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
recob::tracking::Plane Plane
spacecharge::SpaceCharge const * fSCE
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
cet::coded_exception< error, detail::translate > exception
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Event finding and building.
Signal from collection planes.
constexpr PlaneID const & asPlaneID() const
Conversion to WireID (for convenience of notation).