-
Notifications
You must be signed in to change notification settings - Fork 39
Feature/sungbino caf calo updates 2025 a #559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
ba72c99
90cdf65
98b624d
aa5484c
5b70b40
455cb8d
b15f1f8
e70f014
2feb51f
c6a3c29
035418f
a6b090a
1e0a36f
46e144f
6df0c30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,6 +10,10 @@ | |||||||
| #include "FillReco.h" | ||||||||
| #include "RecoUtils/RecoUtils.h" | ||||||||
|
|
||||||||
| #include "larevt/SpaceCharge/SpaceCharge.h" | ||||||||
| #include "larevt/SpaceChargeServices/SpaceChargeService.h" | ||||||||
| #include "larcore/CoreUtils/ServiceUtil.h" | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These will not be needed after the change below.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! And moved |
||||||||
|
|
||||||||
| namespace caf | ||||||||
| { | ||||||||
| const float ng_filter_cut = 0.5; | ||||||||
|
|
@@ -794,8 +798,28 @@ namespace caf | |||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| // Helper function: get the e field | ||||||||
| double GetEfield(const detinfo::DetectorPropertiesData& dprop, const geo::Point_t loc) { | ||||||||
| auto const* sce = lar::providerFrom<spacecharge::SpaceChargeService>(); | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sorry, this is frustrating me and I am sure it will frustrate you too... somehow a comment on this function was not received by GitHub.
Suggested change
Notes:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||||||||
|
|
||||||||
| double EField = dprop.Efield(); | ||||||||
| if (sce->EnableSimEfieldSCE()) { | ||||||||
| // Gets fractional E field distortions w.r.t. the nominal field on x-axis | ||||||||
| geo::Vector_t EFieldOffsets = sce->GetEfieldOffsets(loc); | ||||||||
| // Add 1 in X direction as this is the direction of the drift field, not caring if it is +x or -x direction, since we only want |E| | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to make double sure: does the offset as returned by
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It depends on how the SCE map is saved. For SBN SCE studies, it is assumed the nominal electric field has positive x direction.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it depends on that... unfortunately I don't see that assumption documented. |
||||||||
| EFieldOffsets += geo::Vector_t{1, 0, 0}; | ||||||||
| // Convert to Absolute E Field from relative | ||||||||
| EFieldOffsets *= EField; | ||||||||
| // We only care about the magnitude for recombination | ||||||||
| EField = EFieldOffsets.r(); | ||||||||
| } | ||||||||
| return EField; | ||||||||
| } | ||||||||
|
|
||||||||
| void FillTrackPlaneCalo(const anab::Calorimetry &calo, | ||||||||
| const recob::Track& track, | ||||||||
| const std::vector<art::Ptr<recob::Hit>> &hits, | ||||||||
| const std::vector<const recob::TrackHitMeta*>& thms, | ||||||||
| bool fill_calo_points, float fillhit_rrstart, float fillhit_rrend, | ||||||||
| const detinfo::DetectorPropertiesData &dprop, | ||||||||
| caf::SRTrackCalo &srcalo) { | ||||||||
|
|
@@ -832,7 +856,8 @@ namespace caf | |||||||
|
|
||||||||
| // lookup the wire -- the Calorimery object makes this | ||||||||
| // __way__ harder than it should be | ||||||||
| for (const art::Ptr<recob::Hit> &h: hits) { | ||||||||
| for (unsigned i_hit = 0; i_hit < hits.size(); i_hit++) { | ||||||||
| const art::Ptr<recob::Hit> &h = hits[i_hit]; | ||||||||
| if (h.key() == tps[i]) { | ||||||||
| p.wire = h->WireID().Wire; | ||||||||
| p.tpc = h->WireID().TPC; | ||||||||
|
|
@@ -844,6 +869,19 @@ namespace caf | |||||||
| p.mult = h->Multiplicity(); | ||||||||
| p.start = h->StartTick(); | ||||||||
| p.end = h->EndTick(); | ||||||||
|
|
||||||||
|
|
||||||||
| // Get the trajectory point index from this hit. Again -- this is too hard. | ||||||||
| // | ||||||||
| // Use this to get the (SCE corrected) efield and the angle to the drift direction | ||||||||
| unsigned traj_point_index = thms.at(i_hit)->Index(); | ||||||||
| if (track.HasValidPoint(traj_point_index)) { | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please fix this indentation.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed! |
||||||||
| float costh_drift = track.DirectionAtPoint(traj_point_index).X(); | ||||||||
| float phi = acos(abs(costh_drift)) * 180. / M_PI; | ||||||||
| float efield = GetEfield(dprop, track.LocationAtPoint(traj_point_index)); | ||||||||
| p.efield = efield; | ||||||||
| p.phi = phi; | ||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
|
|
@@ -897,7 +935,9 @@ namespace caf | |||||||
| } | ||||||||
|
|
||||||||
| void FillTrackCalo(const std::vector<art::Ptr<anab::Calorimetry>> &calos, | ||||||||
| const recob::Track& track, | ||||||||
| const std::vector<art::Ptr<recob::Hit>> &hits, | ||||||||
| const std::vector<const recob::TrackHitMeta*>& thms, | ||||||||
| bool fill_calo_points, float fillhit_rrstart, float fillhit_rrend, | ||||||||
| const detinfo::DetectorPropertiesData &dprop, | ||||||||
| caf::SRTrack& srtrack, | ||||||||
|
|
@@ -912,7 +952,7 @@ namespace caf | |||||||
| if (calo.PlaneID()) { | ||||||||
| unsigned plane_id = calo.PlaneID().Plane; | ||||||||
| assert(plane_id < 3); | ||||||||
| FillTrackPlaneCalo(calo, hits, fill_calo_points, fillhit_rrstart, fillhit_rrend, dprop, srtrack.calo[plane_id]); | ||||||||
| FillTrackPlaneCalo(calo, track, hits, thms, fill_calo_points, fillhit_rrstart, fillhit_rrend, dprop, srtrack.calo[plane_id]); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -289,7 +289,7 @@ void sbn::TrackCaloSkimmer::analyze(art::Event const& e) | |
| // Prep truth-to-reco-matching info | ||
| // | ||
| // Use helper functions from CAFMaker/FillTrue | ||
| std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE*>>> id_to_ide_map; | ||
| std::map<int, std::vector<sbn::ReadoutIDE>> id_to_ide_map; | ||
| std::map<int, std::vector<art::Ptr<recob::Hit>>> id_to_truehit_map; | ||
| const cheat::BackTrackerService *bt = NULL; | ||
|
|
||
|
|
@@ -545,14 +545,14 @@ geo::Point_t WireToTrajectoryPosition(const geo::Point_t &loc, const geo::TPCID | |
| sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | ||
| const std::vector<geo::BoxBoundedGeo> &active_volumes, | ||
| const std::vector<std::vector<geo::BoxBoundedGeo>> &tpc_volumes, | ||
| const std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE *>>> &id_to_ide_map, | ||
| const std::map<int, std::vector<sbn::ReadoutIDE>> &id_to_ide_map, | ||
| const std::map<int, std::vector<art::Ptr<recob::Hit>>> &id_to_truehit_map, | ||
| const detinfo::DetectorPropertiesData &dprop, | ||
| const geo::GeometryCore *geo, | ||
| const geo::WireReadoutGeom *wireReadout) { | ||
|
|
||
| std::vector<std::pair<geo::WireID, const sim::IDE *>> empty; | ||
| const std::vector<std::pair<geo::WireID, const sim::IDE *>> &particle_ides = id_to_ide_map.count(particle.TrackId()) ? id_to_ide_map.at(particle.TrackId()) : empty; | ||
| std::vector<sbn::ReadoutIDE> empty; | ||
| const std::vector<sbn::ReadoutIDE> &particle_ides = id_to_ide_map.count(particle.TrackId()) ? id_to_ide_map.at(particle.TrackId()) : empty; | ||
|
|
||
| std::vector<art::Ptr<recob::Hit>> emptyHits; | ||
| const std::vector<art::Ptr<recob::Hit>> &particle_hits = id_to_truehit_map.count(particle.TrackId()) ? id_to_truehit_map.at(particle.TrackId()) : emptyHits; | ||
|
|
@@ -569,9 +569,9 @@ sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | |
| trueparticle.plane0nhit = 0; | ||
| trueparticle.plane1nhit = 0; | ||
| trueparticle.plane2nhit = 0; | ||
| for (auto const &ide_pair: particle_ides) { | ||
| const geo::WireID &w = ide_pair.first; | ||
| const sim::IDE *ide = ide_pair.second; | ||
| for (auto const &ide_p: particle_ides) { | ||
| const geo::WireID &w = ide_p.wire; | ||
| const sim::IDE *ide = ide_p.ide; | ||
|
|
||
| if (w.Plane == 0) { | ||
| trueparticle.plane0VisE += ide->energy / 1000. /* MeV -> GeV*/; | ||
|
|
@@ -720,10 +720,11 @@ sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | |
| // Organize deposition info into per-wire true "Hits" -- key is the Channel Number | ||
| std::map<unsigned, sbn::TrueHit> truehits; | ||
|
|
||
| for (auto const &ide_pair: particle_ides) { | ||
| const geo::WireID &w = ide_pair.first; | ||
| for (auto const &ide_part: particle_ides) { | ||
| const geo::WireID &w = ide_part.wire; | ||
| unsigned c = wireReadout->PlaneWireToChannel(w); | ||
| const sim::IDE *ide = ide_pair.second; | ||
| const sim::IDE *ide = ide_part.ide; | ||
| unsigned short tick = ide_part.tick; | ||
|
|
||
| // Set stuff | ||
| truehits[c].cryo = w.Cryostat; | ||
|
|
@@ -739,6 +740,8 @@ sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | |
| truehits[c].p.y = (truehits[c].p.y*old_elec + ide->y*ide->numElectrons) / new_elec; | ||
| truehits[c].p.z = (truehits[c].p.z*old_elec + ide->z*ide->numElectrons) / new_elec; | ||
|
|
||
| truehits[c].time = (truehits[c].time*old_elec + tick*ide->numElectrons) / new_elec; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This way of processing leaves me puzzled. I think it originates in 12-year old code that was written that way while interfacing with GEANT4 steps (so, at the same time when the true hits were being created) so that the information would be always valid. But here, in a single loop, it's just a waste times the 6 lines it's used in (7 now).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is written purposefully. The number of electrons can get quite large, so you get numerical stability issues if you do a weighted sum the naive way. (sum p_i * w_i / sum w_i). I'm not sure if you mean something else, but in any case I think this is ok as is.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do mean that.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I actually do have my answer, but it assumes the internal precision of the FPU stack/registers is larger than the output CPU registry, plus some compiler optimisation) |
||
|
|
||
| // Also get the position with space charge un-done | ||
| geo::Point_t ide_p(ide->x, ide->y, ide->z); | ||
| geo::Point_t ide_p_scecorr = WireToTrajectoryPosition(ide_p, w); | ||
|
|
@@ -754,10 +757,10 @@ sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | |
| } | ||
|
|
||
| // Compute widths | ||
| for (auto const &ide_pair: particle_ides) { | ||
| const geo::WireID &w = ide_pair.first; | ||
| for (auto const &ide_part: particle_ides) { | ||
| const geo::WireID &w = ide_part.wire; | ||
| unsigned c = wireReadout->PlaneWireToChannel(w); | ||
| const sim::IDE *ide = ide_pair.second; | ||
| const sim::IDE *ide = ide_part.ide; | ||
|
|
||
| geo::Point_t ide_p(ide->x, ide->y, ide->z); | ||
| geo::Point_t ide_p_scecorr = WireToTrajectoryPosition(ide_p, w); | ||
|
|
@@ -782,8 +785,6 @@ sbn::TrueParticle TrueParticleInfo(const simb::MCParticle &particle, | |
|
|
||
| // Compute the time of each hit | ||
| for (sbn::TrueHit &h: truehits_v) { | ||
| h.time = dprop.ConvertXToTicks(h.p.x, h.plane, h.tpc, h.cryo); | ||
|
|
||
| double xdrift = abs(h.p.x - wireReadout->Plane(geo::PlaneID(h.cryo, h.tpc, 0)).GetCenter().X()); | ||
| h.tdrift = xdrift / dprop.DriftVelocity(); | ||
| } | ||
|
|
@@ -1010,7 +1011,7 @@ void sbn::TrackCaloSkimmer::FillTrackTruth(const detinfo::DetectorClocksData &cl | |
| const std::vector<art::Ptr<simb::MCParticle>> &mcparticles, | ||
| const std::vector<geo::BoxBoundedGeo> &active_volumes, | ||
| const std::vector<std::vector<geo::BoxBoundedGeo>> &tpc_volumes, | ||
| const std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE*>>> id_to_ide_map, | ||
| const std::map<int, std::vector<sbn::ReadoutIDE>> id_to_ide_map, | ||
| const std::map<int, std::vector<art::Ptr<recob::Hit>>> id_to_truehit_map, | ||
| const detinfo::DetectorPropertiesData &dprop, | ||
| const geo::GeometryCore *geo, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed this... This library should not be necessary — if it is, there is a problem.
Try with:
(also, make sure it's appropriately indented) for the library, and add
below (e.g. around line 69) for the module.
Rationale:
DetectorPropertiesServiceStandardis an implementation of a service interface. Which implementation to use is decided run-time by reading the FHiCLservicesconfiguration, so it does not make sense to link a specific implementation at build time. What we really need is the "library" pulling in the interface. I hope my suggestion is the LArSoft's right name for the one we need here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have checked
FillReco.h... we do have a problem:lardataalg/DetectorInfo/DetectorPropertiesStandard.his included directly. It should not be. Ever.Please replace that line with the appropriate header, which I think is:
(bonus points if you try to remove also the inclusion of
ParticleInventoryService.hon the previous line, since it looks like it's not used — and if it is needed, leave it there)With my thanks for fixing this pre-existing bug.