From fd8ef40f32c8bf52934dd23a0f8996f2759e75ae Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sat, 4 Sep 2021 02:05:37 -0400 Subject: [PATCH 01/80] updating for gen2 larlite --- ublarcvapp/Reco3D/AStar3DAlgo.cxx | 4 ++-- ublarcvapp/Reco3D/AStar3DAlgoProton.cxx | 4 ++-- ublarcvapp/Reco3D/AStarTracker.cxx | 17 +++++++++-------- ublarcvapp/Reco3D/AStarTracker.h | 12 ++++++------ ublarcvapp/Reco3D/AStarUtils.cxx | 4 ++-- ublarcvapp/Reco3D/Lattice.cxx | 4 ++-- ublarcvapp/Reco3D/Run3DTracker.cxx | 22 ++++++++++++---------- ublarcvapp/Reco3D/Run3DTracker.h | 4 ++-- ublarcvapp/Reco3D/TrackReverser.h | 2 +- ublarcvapp/Reco3D/TrackerEventDisplay.h | 4 ++-- 10 files changed, 40 insertions(+), 37 deletions(-) diff --git a/ublarcvapp/Reco3D/AStar3DAlgo.cxx b/ublarcvapp/Reco3D/AStar3DAlgo.cxx index 6a28685..82d1f1c 100644 --- a/ublarcvapp/Reco3D/AStar3DAlgo.cxx +++ b/ublarcvapp/Reco3D/AStar3DAlgo.cxx @@ -6,8 +6,8 @@ #include // larlite -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" // ublarcvapp #include "ublarcvapp/UBWireTool/UBWireTool.h" diff --git a/ublarcvapp/Reco3D/AStar3DAlgoProton.cxx b/ublarcvapp/Reco3D/AStar3DAlgoProton.cxx index b368573..4cd974f 100644 --- a/ublarcvapp/Reco3D/AStar3DAlgoProton.cxx +++ b/ublarcvapp/Reco3D/AStar3DAlgoProton.cxx @@ -11,8 +11,8 @@ #include "ublarcvapp/UBWireTool/UBWireTool.h" // larlite -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/AStarTracker.cxx b/ublarcvapp/Reco3D/AStarTracker.cxx index 011aaf6..459b8fd 100644 --- a/ublarcvapp/Reco3D/AStarTracker.cxx +++ b/ublarcvapp/Reco3D/AStarTracker.cxx @@ -2,15 +2,16 @@ #define LARLITE_AStarTracker_CXX #include "AStarTracker.h" -#include "DataFormat/track.h" -#include "DataFormat/vertex.h" -#include "DataFormat/hit.h" + +#include "larlite/DataFormat/track.h" +#include "larlite/DataFormat/vertex.h" +#include "larlite/DataFormat/hit.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/wire.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/GeometryHelper.h" +#include "larlite/LArUtil/TimeService.h" #include "larcv/core/DataFormat/Image2D.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/wire.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/GeometryHelper.h" -#include "LArUtil/TimeService.h" #include "TCanvas.h" #include "TF1.h" diff --git a/ublarcvapp/Reco3D/AStarTracker.h b/ublarcvapp/Reco3D/AStarTracker.h index 78fc18a..2ce85b4 100644 --- a/ublarcvapp/Reco3D/AStarTracker.h +++ b/ublarcvapp/Reco3D/AStarTracker.h @@ -18,13 +18,14 @@ #include #include -#include "Analysis/ana_base.h" -#include "DataFormat/track.h" -#include "DataFormat/mctrack.h" -#include +//#include "Analysis/ana_base.h" +#include "larlite/DataFormat/track.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/wire.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/DataFormat/ImageMeta.h" -#include "DataFormat/wire.h" +#include #include "TH1D.h" #include "TH2D.h" #include "TSpline.h" @@ -40,7 +41,6 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/AStarUtils.cxx b/ublarcvapp/Reco3D/AStarUtils.cxx index d98ce01..5437269 100644 --- a/ublarcvapp/Reco3D/AStarUtils.cxx +++ b/ublarcvapp/Reco3D/AStarUtils.cxx @@ -2,8 +2,8 @@ #define ASTARUTILS_CXX #include "AStarUtils.h" -#include "LArUtil/GeometryHelper.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/GeometryHelper.h" +#include "larlite/LArUtil/LArProperties.h" #include #include diff --git a/ublarcvapp/Reco3D/Lattice.cxx b/ublarcvapp/Reco3D/Lattice.cxx index 2f3a805..7b59fe4 100644 --- a/ublarcvapp/Reco3D/Lattice.cxx +++ b/ublarcvapp/Reco3D/Lattice.cxx @@ -1,8 +1,8 @@ #include "Lattice.h" // larlite -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/Run3DTracker.cxx b/ublarcvapp/Reco3D/Run3DTracker.cxx index 51190fb..3718063 100644 --- a/ublarcvapp/Reco3D/Run3DTracker.cxx +++ b/ublarcvapp/Reco3D/Run3DTracker.cxx @@ -3,18 +3,20 @@ #include "Run3DTracker.h" -#include "DataFormat/storage_manager.h" -#include "DataFormat/track.h" -#include "DataFormat/vertex.h" -#include "DataFormat/hit.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/track.h" +#include "larlite/DataFormat/vertex.h" +#include "larlite/DataFormat/hit.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/wire.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/GeometryHelper.h" +#include "larlite/LArUtil/TimeService.h" + +#include "larcv/core/DataFormat/EventROI.h" #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/DataFormat/EventImage2D.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/wire.h" -#include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/GeometryHelper.h" -#include "LArUtil/TimeService.h" + #include "TFile.h" #include "TTree.h" #include "TStyle.h" diff --git a/ublarcvapp/Reco3D/Run3DTracker.h b/ublarcvapp/Reco3D/Run3DTracker.h index 6394f13..b40bf27 100644 --- a/ublarcvapp/Reco3D/Run3DTracker.h +++ b/ublarcvapp/Reco3D/Run3DTracker.h @@ -19,8 +19,8 @@ #include "TTree.h" #include "TVector3.h" -#include "DataFormat/storage_manager.h" -#include "DataFormat/track.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/track.h" #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" diff --git a/ublarcvapp/Reco3D/TrackReverser.h b/ublarcvapp/Reco3D/TrackReverser.h index 8a03ba8..325df2f 100644 --- a/ublarcvapp/Reco3D/TrackReverser.h +++ b/ublarcvapp/Reco3D/TrackReverser.h @@ -2,7 +2,7 @@ #define __UBLARCVAPP_RECO3D_TRACK_REVERSER_H__ #include "larcv/core/Base/larcv_base.h" -#include "DataFormat/track.h" +#include "larlite/DataFormat/track.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/TrackerEventDisplay.h b/ublarcvapp/Reco3D/TrackerEventDisplay.h index ce12f21..8d5fb9d 100644 --- a/ublarcvapp/Reco3D/TrackerEventDisplay.h +++ b/ublarcvapp/Reco3D/TrackerEventDisplay.h @@ -19,8 +19,8 @@ #include "TTree.h" #include "TVector3.h" -#include "DataFormat/storage_manager.h" -#include "DataFormat/track.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/track.h" #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" From c479ab993ff6c3db11aac4379a528396f1b78062 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sat, 4 Sep 2021 02:17:19 -0400 Subject: [PATCH 02/80] modified for gen2 larlite --- .../ContourTools/ContourAStarClusterAlgo.cxx | 4 ++-- ublarcvapp/DLTagger/DLTagger.cxx | 4 ++-- ublarcvapp/DLTagger/DLTagger.h | 4 ++-- ublarcvapp/DLTagger/DLTaggerProcess.cxx | 4 ++-- .../DLTagger/mrcnnmatch/AStarMaskCombo.cxx | 4 ++-- .../DLTagger/mrcnnmatch/AStarMaskCombo.h | 2 +- .../DLTagger/mrcnnmatch/CropMaskCombo.cxx | 2 +- .../DLTagger/mrcnnmatch/Gen3DEndpoints.cxx | 2 +- .../DLTagger/mrcnnmatch/GenGraphPoints.cxx | 4 ++-- .../DLTagger/mrcnnmatch/MRCNNMatchTypes.cxx | 2 +- ublarcvapp/LArOpenCVHandle/CosmicPixelAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/CosmicPixelAna.h | 2 +- ublarcvapp/LArOpenCVHandle/CosmicVertexAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/DeadWireAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/DeadWireAna.h | 2 +- ublarcvapp/LArOpenCVHandle/GoodcROIFilter.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/GoodcROIFilter.h | 2 +- ublarcvapp/LArOpenCVHandle/LArbysImageMC.h | 2 +- ublarcvapp/LArOpenCVHandle/LArbysUtils.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/ROIAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/ROIAna.h | 2 +- ublarcvapp/LArOpenCVHandle/SSNetTruthAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/SSNetTruthAna.h | 2 +- ublarcvapp/LArOpenCVHandle/VertexAna.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/VertexAna.h | 2 +- ublarcvapp/LArOpenCVHandle/VertexInROI.cxx | 4 ++-- ublarcvapp/LArOpenCVHandle/VertexInROI.h | 2 +- ublarcvapp/LArliteHandler/LArliteManager.h | 2 +- ublarcvapp/LLCVProcessor/LLCVProcessBase.h | 2 +- ublarcvapp/LLCVProcessor/LLCVProcessDriver.h | 2 +- ublarcvapp/LLCVProcessor/LLCVProcessTest.h | 2 +- ublarcvapp/MCTools/LArbysMC.cxx | 16 ++++++++-------- ublarcvapp/MCTools/LArbysMC.h | 2 +- ublarcvapp/MCTools/MCPixelPGraph.cxx | 12 ++++++------ ublarcvapp/MCTools/MCPixelPGraph.h | 8 ++++---- ublarcvapp/MCTools/NeutrinoPixelFilter.cxx | 6 +++--- ublarcvapp/MCTools/NeutrinoVertex.cxx | 4 ++-- ublarcvapp/MCTools/NeutrinoVertex.h | 4 ++-- ublarcvapp/MCTools/TruthShowerTrunkSCE.h | 6 +++--- ublarcvapp/MCTools/TruthTrackSCE.h | 6 +++--- .../MCTools/crossingPointsAnaMethods.cxx | 10 +++++----- ublarcvapp/MCTools/crossingPointsAnaMethods.h | 4 ++-- ublarcvapp/Reco3D/TrackerEventDisplay.cxx | 18 +++++++++--------- ublarcvapp/UBImageMod/EmptyChannelAlgo.h | 4 ++-- ublarcvapp/UBImageMod/InfillDataCropper.cxx | 4 ++-- ublarcvapp/UBImageMod/TrackImageMask.cxx | 4 ++-- ublarcvapp/UBImageMod/TrackImageMask.h | 2 +- ublarcvapp/UBImageMod/UBCropLArFlow.cxx | 4 ++-- ublarcvapp/UBImageMod/UBCropMask.cxx | 4 ++-- ublarcvapp/UBImageMod/UBSplitDetector.cxx | 2 +- ublarcvapp/UBWireTool/UBWireTool.cxx | 4 ++-- ublarcvapp/ubdllee/DLInteraction.h | 4 ++-- ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.cxx | 4 ++-- ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h | 2 +- ublarcvapp/ubdllee/NuAnaMC.cxx | 14 +++++++------- ublarcvapp/ubdllee/NuAnaMC.h | 2 +- 56 files changed, 121 insertions(+), 121 deletions(-) diff --git a/ublarcvapp/ContourTools/ContourAStarClusterAlgo.cxx b/ublarcvapp/ContourTools/ContourAStarClusterAlgo.cxx index 81d8313..c1d9423 100644 --- a/ublarcvapp/ContourTools/ContourAStarClusterAlgo.cxx +++ b/ublarcvapp/ContourTools/ContourAStarClusterAlgo.cxx @@ -4,8 +4,8 @@ #include // larlite -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" // larcv #include "larcv/core/CVUtil/CVUtil.h" diff --git a/ublarcvapp/DLTagger/DLTagger.cxx b/ublarcvapp/DLTagger/DLTagger.cxx index f5ee3f4..c6219bb 100644 --- a/ublarcvapp/DLTagger/DLTagger.cxx +++ b/ublarcvapp/DLTagger/DLTagger.cxx @@ -6,8 +6,8 @@ #include "ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h" #include "ublarcvapp/ContourTools/ContourClusterAlgo.h" -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" #include "Geo2D/Core/Geo2D.h" diff --git a/ublarcvapp/DLTagger/DLTagger.h b/ublarcvapp/DLTagger/DLTagger.h index a75fa97..aac727a 100644 --- a/ublarcvapp/DLTagger/DLTagger.h +++ b/ublarcvapp/DLTagger/DLTagger.h @@ -11,8 +11,8 @@ #include "larcv/core/DataFormat/ClusterMask.h" // larlite -#include "DataFormat/opflash.h" -#include "DataFormat/track.h" +#include "larlite/DataFormat/opflash.h" +#include "larlite/DataFormat/track.h" // mrcnnmatch #include "MRCNNMatch.h" diff --git a/ublarcvapp/DLTagger/DLTaggerProcess.cxx b/ublarcvapp/DLTagger/DLTaggerProcess.cxx index 1992b90..f0db24f 100644 --- a/ublarcvapp/DLTagger/DLTaggerProcess.cxx +++ b/ublarcvapp/DLTagger/DLTaggerProcess.cxx @@ -1,7 +1,7 @@ #include "DLTaggerProcess.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/EventChStatus.h" diff --git a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.cxx b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.cxx index 9c09612..0bfea16 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.cxx +++ b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.cxx @@ -1,8 +1,8 @@ #include "AStarMaskCombo.h" #include "ublarcvapp/UBImageMod/EmptyChannelAlgo.h" -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" namespace ublarcvapp { namespace dltagger { diff --git a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h index 04510a4..cb4870e 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h +++ b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h @@ -4,7 +4,7 @@ #include // larlite -#include "DataFormat/track.h" +#include "larlite/DataFormat/track.h" // larcv #include "larcv/core/Base/larcv_base.h" diff --git a/ublarcvapp/DLTagger/mrcnnmatch/CropMaskCombo.cxx b/ublarcvapp/DLTagger/mrcnnmatch/CropMaskCombo.cxx index 87c2e84..8390db6 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/CropMaskCombo.cxx +++ b/ublarcvapp/DLTagger/mrcnnmatch/CropMaskCombo.cxx @@ -1,7 +1,7 @@ #include "CropMaskCombo.h" // larlite -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/Geometry.h" namespace ublarcvapp { namespace dltagger { diff --git a/ublarcvapp/DLTagger/mrcnnmatch/Gen3DEndpoints.cxx b/ublarcvapp/DLTagger/mrcnnmatch/Gen3DEndpoints.cxx index c336da9..7856b0c 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/Gen3DEndpoints.cxx +++ b/ublarcvapp/DLTagger/mrcnnmatch/Gen3DEndpoints.cxx @@ -1,7 +1,7 @@ #include "Gen3DEndpoints.h" // larlite -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/Geometry.h" // ublarcvapp #include "ublarcvapp/UBWireTool/UBWireTool.h" diff --git a/ublarcvapp/DLTagger/mrcnnmatch/GenGraphPoints.cxx b/ublarcvapp/DLTagger/mrcnnmatch/GenGraphPoints.cxx index 0d7fe42..7e80877 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/GenGraphPoints.cxx +++ b/ublarcvapp/DLTagger/mrcnnmatch/GenGraphPoints.cxx @@ -1,7 +1,7 @@ #include "GenGraphPoints.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "ublarcvapp/UBWireTool/UBWireTool.h" diff --git a/ublarcvapp/DLTagger/mrcnnmatch/MRCNNMatchTypes.cxx b/ublarcvapp/DLTagger/mrcnnmatch/MRCNNMatchTypes.cxx index 749f7bf..5d063f6 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/MRCNNMatchTypes.cxx +++ b/ublarcvapp/DLTagger/mrcnnmatch/MRCNNMatchTypes.cxx @@ -1,7 +1,7 @@ #include "MRCNNMatchTypes.h" // larlite -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/Geometry.h" namespace ublarcvapp { namespace dltagger { diff --git a/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.cxx b/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.cxx index 9279bd9..c97e97a 100644 --- a/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.cxx @@ -5,8 +5,8 @@ #include "LArbysImageMaker.h" #include "larcv/core/DataFormat/EventROI.h" #include "LArbysUtils.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include #include #include "larcv/core/CVUtil/CVUtil.h" diff --git a/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.h b/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.h index 65c4029..c2a293f 100644 --- a/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.h +++ b/ublarcvapp/LArOpenCVHandle/CosmicPixelAna.h @@ -4,7 +4,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" #include "LArbysImageMaker.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/CosmicVertexAna.cxx b/ublarcvapp/LArOpenCVHandle/CosmicVertexAna.cxx index 19e1681..48b415a 100644 --- a/ublarcvapp/LArOpenCVHandle/CosmicVertexAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/CosmicVertexAna.cxx @@ -9,8 +9,8 @@ #include "larcv/core/DataFormat/EventPixel2D.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "LArOpenCV/ImageCluster/Base/ImageClusterTypes.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "LArbysUtils.h" #include "LArbysImageMaker.h" #include "LArOpenCV/ImageCluster/AlgoFunction/Contour2DAnalysis.h" diff --git a/ublarcvapp/LArOpenCVHandle/DeadWireAna.cxx b/ublarcvapp/LArOpenCVHandle/DeadWireAna.cxx index 2aa8173..ba78caf 100644 --- a/ublarcvapp/LArOpenCVHandle/DeadWireAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/DeadWireAna.cxx @@ -4,8 +4,8 @@ #include "DeadWireAna.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/DeadWireAna.h b/ublarcvapp/LArOpenCVHandle/DeadWireAna.h index 62211c1..dd36583 100644 --- a/ublarcvapp/LArOpenCVHandle/DeadWireAna.h +++ b/ublarcvapp/LArOpenCVHandle/DeadWireAna.h @@ -4,7 +4,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.cxx b/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.cxx index 01f3508..4e6cce4 100644 --- a/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.cxx +++ b/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.cxx @@ -4,8 +4,8 @@ #include "GoodcROIFilter.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.h b/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.h index 65ea1a9..1e7b68f 100644 --- a/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.h +++ b/ublarcvapp/LArOpenCVHandle/GoodcROIFilter.h @@ -18,7 +18,7 @@ #include "larcv/core/Processor/ProcessFactory.h" #include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImageMC.h b/ublarcvapp/LArOpenCVHandle/LArbysImageMC.h index 7fc6505..635a344 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImageMC.h +++ b/ublarcvapp/LArOpenCVHandle/LArbysImageMC.h @@ -6,7 +6,7 @@ #include #include "TTree.h" -#include "LArUtil/PxUtils.h" +#include "larlite/LArUtil/PxUtils.h" #include "larcv/core/DataFormat/Image2D.h" #include "Geo2D/Core/HalfLine.h" #include "Geo2D/Core/Line.h" diff --git a/ublarcvapp/LArOpenCVHandle/LArbysUtils.cxx b/ublarcvapp/LArOpenCVHandle/LArbysUtils.cxx index 5233a83..3da99fe 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysUtils.cxx +++ b/ublarcvapp/LArOpenCVHandle/LArbysUtils.cxx @@ -2,8 +2,8 @@ #define LARBYSUTILS_CXX #include "LArbysUtils.h" -#include "LArUtil/GeometryHelper.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/GeometryHelper.h" +#include "larlite/LArUtil/LArProperties.h" #include #include diff --git a/ublarcvapp/LArOpenCVHandle/ROIAna.cxx b/ublarcvapp/LArOpenCVHandle/ROIAna.cxx index f546f54..f3eaae2 100644 --- a/ublarcvapp/LArOpenCVHandle/ROIAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/ROIAna.cxx @@ -5,8 +5,8 @@ #include #include -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/ROIAna.h b/ublarcvapp/LArOpenCVHandle/ROIAna.h index 358f4d2..8fa9910 100644 --- a/ublarcvapp/LArOpenCVHandle/ROIAna.h +++ b/ublarcvapp/LArOpenCVHandle/ROIAna.h @@ -18,7 +18,7 @@ #include "larcv/core/Processor/ProcessFactory.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.cxx b/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.cxx index 48d1a9b..2fce727 100644 --- a/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.cxx @@ -5,8 +5,8 @@ #include "LArbysImageMaker.h" #include "larcv/core/DataFormat/EventROI.h" #include "LArbysUtils.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "larcv/core/CVUtil/CVUtil.h" #include #include diff --git a/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.h b/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.h index 45b59c3..137bcff 100644 --- a/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.h +++ b/ublarcvapp/LArOpenCVHandle/SSNetTruthAna.h @@ -3,7 +3,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/VertexAna.cxx b/ublarcvapp/LArOpenCVHandle/VertexAna.cxx index 5830b89..4d9a28f 100644 --- a/ublarcvapp/LArOpenCVHandle/VertexAna.cxx +++ b/ublarcvapp/LArOpenCVHandle/VertexAna.cxx @@ -7,8 +7,8 @@ #include "larcv/core/DataFormat/EventPixel2D.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "LArOpenCV/ImageCluster/Base/ImageClusterTypes.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "LArbysUtils.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/VertexAna.h b/ublarcvapp/LArOpenCVHandle/VertexAna.h index c1016c2..2f74864 100644 --- a/ublarcvapp/LArOpenCVHandle/VertexAna.h +++ b/ublarcvapp/LArOpenCVHandle/VertexAna.h @@ -3,7 +3,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include #include diff --git a/ublarcvapp/LArOpenCVHandle/VertexInROI.cxx b/ublarcvapp/LArOpenCVHandle/VertexInROI.cxx index f4b1563..ac1993d 100644 --- a/ublarcvapp/LArOpenCVHandle/VertexInROI.cxx +++ b/ublarcvapp/LArOpenCVHandle/VertexInROI.cxx @@ -3,8 +3,8 @@ #include "VertexInROI.h" #include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace larcv { diff --git a/ublarcvapp/LArOpenCVHandle/VertexInROI.h b/ublarcvapp/LArOpenCVHandle/VertexInROI.h index ed8d8a6..6ed4ac8 100644 --- a/ublarcvapp/LArOpenCVHandle/VertexInROI.h +++ b/ublarcvapp/LArOpenCVHandle/VertexInROI.h @@ -3,7 +3,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace larcv { diff --git a/ublarcvapp/LArliteHandler/LArliteManager.h b/ublarcvapp/LArliteHandler/LArliteManager.h index 44fd6e6..b4c9dcb 100644 --- a/ublarcvapp/LArliteHandler/LArliteManager.h +++ b/ublarcvapp/LArliteHandler/LArliteManager.h @@ -14,7 +14,7 @@ #include // larlite -#include "DataFormat/storage_manager.h" +#include "larlite/DataFormat/storage_manager.h" // larcv #include "larcv/core/Base/larcv_base.h" diff --git a/ublarcvapp/LLCVProcessor/LLCVProcessBase.h b/ublarcvapp/LLCVProcessor/LLCVProcessBase.h index 208a69d..37f5b20 100644 --- a/ublarcvapp/LLCVProcessor/LLCVProcessBase.h +++ b/ublarcvapp/LLCVProcessor/LLCVProcessBase.h @@ -6,7 +6,7 @@ #include "larcv/core/DataFormat/IOManager.h" // larlite -#include "DataFormat/storage_manager.h" +#include "larlite/DataFormat/storage_manager.h" namespace larcv { class ProcessDriver; diff --git a/ublarcvapp/LLCVProcessor/LLCVProcessDriver.h b/ublarcvapp/LLCVProcessor/LLCVProcessDriver.h index 9b3fdbf..f9958b0 100644 --- a/ublarcvapp/LLCVProcessor/LLCVProcessDriver.h +++ b/ublarcvapp/LLCVProcessor/LLCVProcessDriver.h @@ -11,7 +11,7 @@ #include "larcv/core/Processor/ProcessDriver.h" // larlite -#include "core/DataFormat/storage_manager.h" +#include "larlite/DataFormat/storage_manager.h" #include "ublarcvapp/LArliteHandler/LArliteManager.h" diff --git a/ublarcvapp/LLCVProcessor/LLCVProcessTest.h b/ublarcvapp/LLCVProcessor/LLCVProcessTest.h index 3774d49..484c62a 100644 --- a/ublarcvapp/LLCVProcessor/LLCVProcessTest.h +++ b/ublarcvapp/LLCVProcessor/LLCVProcessTest.h @@ -6,7 +6,7 @@ #include #include "larcv/core/Processor/ProcessFactory.h" #include "larcv/core/DataFormat/IOManager.h" -#include "DataFormat/storage_manager.h" +#include "larlite/DataFormat/storage_manager.h" namespace ublarcvapp { namespace llcv { diff --git a/ublarcvapp/MCTools/LArbysMC.cxx b/ublarcvapp/MCTools/LArbysMC.cxx index d669fb2..a57a2d5 100644 --- a/ublarcvapp/MCTools/LArbysMC.cxx +++ b/ublarcvapp/MCTools/LArbysMC.cxx @@ -5,14 +5,14 @@ #include "LArbysMC.h" -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" -#include "Base/MCConstants.h" -#include "DataFormat/storage_manager.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/mcshower.h" -#include "DataFormat/mctruth.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/Base/MCConstants.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/mctruth.h" #include "ublarcvapp/ubdllee/dwall.h" diff --git a/ublarcvapp/MCTools/LArbysMC.h b/ublarcvapp/MCTools/LArbysMC.h index e66a3f2..d5ee104 100644 --- a/ublarcvapp/MCTools/LArbysMC.h +++ b/ublarcvapp/MCTools/LArbysMC.h @@ -6,7 +6,7 @@ #include "TTree.h" -#include "DataFormat/storage_manager.h" +#include "larlite/DataFormat/storage_manager.h" #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/IOManager.h" diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 22ab8a8..8217a7e 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -7,12 +7,12 @@ #include "larcv/core/DataFormat/DataFormatTypes.h" // larlite -#include "DataFormat/mctrack.h" -#include "DataFormat/mcshower.h" -#include "DataFormat/mctruth.h" -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/mctruth.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "crossingPointsAnaMethods.h" diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 2919c68..3c2280c 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -9,10 +9,10 @@ #include "larcv/core/DataFormat/Image2D.h" // larlite -#include "DataFormat/storage_manager.h" -#include "DataFormat/mcshower.h" -#include "DataFormat/mctrack.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" /** * Determine particle graph. Collect pixels for each particle. diff --git a/ublarcvapp/MCTools/NeutrinoPixelFilter.cxx b/ublarcvapp/MCTools/NeutrinoPixelFilter.cxx index 3e0b7d5..afbba5e 100644 --- a/ublarcvapp/MCTools/NeutrinoPixelFilter.cxx +++ b/ublarcvapp/MCTools/NeutrinoPixelFilter.cxx @@ -4,9 +4,9 @@ #include "larcv/core/DataFormat/IOManager.h" #include "larcv/core/DataFormat/EventImage2D.h" -// #include "DataFormat/storage_manager.h" -// #include "DataFormat/mctrack.h" -// #include "DataFormat/mcshower.h" +// #include "larlite/DataFormat/storage_manager.h" +// #include "larlite/DataFormat/mctrack.h" +// #include "larlite/DataFormat/mcshower.h" namespace ublarcvapp { namespace mctools { diff --git a/ublarcvapp/MCTools/NeutrinoVertex.cxx b/ublarcvapp/MCTools/NeutrinoVertex.cxx index d88c5d7..920818f 100644 --- a/ublarcvapp/MCTools/NeutrinoVertex.cxx +++ b/ublarcvapp/MCTools/NeutrinoVertex.cxx @@ -1,7 +1,7 @@ #include "NeutrinoVertex.h" -#include "LArUtil/Geometry.h" -#include "DataFormat/mctruth.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/DataFormat/mctruth.h" #include "crossingPointsAnaMethods.h" diff --git a/ublarcvapp/MCTools/NeutrinoVertex.h b/ublarcvapp/MCTools/NeutrinoVertex.h index 4eeca9b..5b373d3 100644 --- a/ublarcvapp/MCTools/NeutrinoVertex.h +++ b/ublarcvapp/MCTools/NeutrinoVertex.h @@ -10,8 +10,8 @@ #include // larlite/core -#include "DataFormat/storage_manager.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace ublarcvapp { namespace mctools { diff --git a/ublarcvapp/MCTools/TruthShowerTrunkSCE.h b/ublarcvapp/MCTools/TruthShowerTrunkSCE.h index 999da9a..1e86ec2 100644 --- a/ublarcvapp/MCTools/TruthShowerTrunkSCE.h +++ b/ublarcvapp/MCTools/TruthShowerTrunkSCE.h @@ -2,9 +2,9 @@ #define __UBLARCVAPP_MCTOOLS_TRUTHSHOWERTRUNKSCE_H__ #include -#include "LArUtil/SpaceChargeMicroBooNE.h" -#include "DataFormat/mcshower.h" -#include "DataFormat/track.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/track.h" #include "larcv/core/Base/larcv_base.h" namespace ublarcvapp { diff --git a/ublarcvapp/MCTools/TruthTrackSCE.h b/ublarcvapp/MCTools/TruthTrackSCE.h index 93ce8e5..a463bd4 100644 --- a/ublarcvapp/MCTools/TruthTrackSCE.h +++ b/ublarcvapp/MCTools/TruthTrackSCE.h @@ -2,9 +2,9 @@ #define __UBLARCVAPP_MCTOOLS_TRUTHTRACK_SCE_H__ #include -#include "LArUtil/SpaceChargeMicroBooNE.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/track.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/track.h" #include "larcv/core/Base/larcv_base.h" namespace ublarcvapp { diff --git a/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx b/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx index 7fa714b..38ff397 100644 --- a/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx +++ b/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx @@ -6,11 +6,11 @@ #include "TTree.h" #include "TLorentzVector.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/trigger.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/trigger.h" // ublarcvapp #include "ublarcvapp/UBWireTool/UBWireTool.h" diff --git a/ublarcvapp/MCTools/crossingPointsAnaMethods.h b/ublarcvapp/MCTools/crossingPointsAnaMethods.h index 9084367..77d06a9 100644 --- a/ublarcvapp/MCTools/crossingPointsAnaMethods.h +++ b/ublarcvapp/MCTools/crossingPointsAnaMethods.h @@ -4,8 +4,8 @@ #include // larlite -#include "DataFormat/mctrack.h" -#include "DataFormat/mctrajectory.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/mctrajectory.h" class TTree; diff --git a/ublarcvapp/Reco3D/TrackerEventDisplay.cxx b/ublarcvapp/Reco3D/TrackerEventDisplay.cxx index ad3088b..e1c133c 100644 --- a/ublarcvapp/Reco3D/TrackerEventDisplay.cxx +++ b/ublarcvapp/Reco3D/TrackerEventDisplay.cxx @@ -3,18 +3,18 @@ #include "TrackerEventDisplay.h" -#include "DataFormat/storage_manager.h" -#include "DataFormat/track.h" -#include "DataFormat/vertex.h" -#include "DataFormat/hit.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/DataFormat/track.h" +#include "larlite/DataFormat/vertex.h" +#include "larlite/DataFormat/hit.h" #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/DataFormat/EventImage2D.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/wire.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/wire.h" #include "larcv/core/DataFormat/EventROI.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/GeometryHelper.h" -#include "LArUtil/TimeService.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/GeometryHelper.h" +#include "larlite/LArUtil/TimeService.h" #include "TFile.h" #include "TTree.h" #include "TStyle.h" diff --git a/ublarcvapp/UBImageMod/EmptyChannelAlgo.h b/ublarcvapp/UBImageMod/EmptyChannelAlgo.h index 67d93b5..e3a6b50 100644 --- a/ublarcvapp/UBImageMod/EmptyChannelAlgo.h +++ b/ublarcvapp/UBImageMod/EmptyChannelAlgo.h @@ -4,8 +4,8 @@ #include // larlite -#include "larlite/core/Base/DataFormatConstants.h" -#include "larlite/core/DataFormat/chstatus.h" // needed because of duplicate name! +#include "larlite/Base/DataFormatConstants.h" +#include "larlite/DataFormat/chstatus.h" // needed because of duplicate name! // larcv #include "larcv/core/DataFormat/Image2D.h" diff --git a/ublarcvapp/UBImageMod/InfillDataCropper.cxx b/ublarcvapp/UBImageMod/InfillDataCropper.cxx index aa844fa..e8e9f41 100644 --- a/ublarcvapp/UBImageMod/InfillDataCropper.cxx +++ b/ublarcvapp/UBImageMod/InfillDataCropper.cxx @@ -14,8 +14,8 @@ // #include "../../core/ROOTUtil/ROOTUtils.h" // //larlite -// #include "LArUtil/Geometry.h" -// #include "LArUtil/LArProperties.h" +// #include "larlite/LArUtil/Geometry.h" +// #include "larlite/LArUtil/LArProperties.h" //root #include "TCanvas.h" diff --git a/ublarcvapp/UBImageMod/TrackImageMask.cxx b/ublarcvapp/UBImageMod/TrackImageMask.cxx index 840425a..79b637d 100644 --- a/ublarcvapp/UBImageMod/TrackImageMask.cxx +++ b/ublarcvapp/UBImageMod/TrackImageMask.cxx @@ -1,7 +1,7 @@ #include "TrackImageMask.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "larcv/core/DataFormat/ImageMeta.h" #include diff --git a/ublarcvapp/UBImageMod/TrackImageMask.h b/ublarcvapp/UBImageMod/TrackImageMask.h index 65e57d4..5370fbe 100644 --- a/ublarcvapp/UBImageMod/TrackImageMask.h +++ b/ublarcvapp/UBImageMod/TrackImageMask.h @@ -3,7 +3,7 @@ #include "larcv/core/Base/larcv_base.h" #include "larcv/core/DataFormat/Image2D.h" -#include "DataFormat/track.h" +#include "larlite/DataFormat/track.h" namespace ublarcvapp { namespace ubimagemod { diff --git a/ublarcvapp/UBImageMod/UBCropLArFlow.cxx b/ublarcvapp/UBImageMod/UBCropLArFlow.cxx index c28b328..b120276 100644 --- a/ublarcvapp/UBImageMod/UBCropLArFlow.cxx +++ b/ublarcvapp/UBImageMod/UBCropLArFlow.cxx @@ -11,8 +11,8 @@ #include "larcv/core/ROOTUtil/ROOTUtils.h" //larlite -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "TCanvas.h" #include "TH2D.h" diff --git a/ublarcvapp/UBImageMod/UBCropMask.cxx b/ublarcvapp/UBImageMod/UBCropMask.cxx index 073edcd..cbb0c2d 100644 --- a/ublarcvapp/UBImageMod/UBCropMask.cxx +++ b/ublarcvapp/UBImageMod/UBCropMask.cxx @@ -13,8 +13,8 @@ #include "larcv/core/ROOTUtil/ROOTUtils.h" //larlite -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" #include "TCanvas.h" #include "TH2D.h" diff --git a/ublarcvapp/UBImageMod/UBSplitDetector.cxx b/ublarcvapp/UBImageMod/UBSplitDetector.cxx index dd46796..50c6351 100644 --- a/ublarcvapp/UBImageMod/UBSplitDetector.cxx +++ b/ublarcvapp/UBImageMod/UBSplitDetector.cxx @@ -9,7 +9,7 @@ #ifdef HAS_LARLITE //larlite -#include "LArUtil/Geometry.h" +#include "larlite/LArUtil/Geometry.h" #endif // ROOT TRandom3 diff --git a/ublarcvapp/UBWireTool/UBWireTool.cxx b/ublarcvapp/UBWireTool/UBWireTool.cxx index aabbdd6..a352345 100644 --- a/ublarcvapp/UBWireTool/UBWireTool.cxx +++ b/ublarcvapp/UBWireTool/UBWireTool.cxx @@ -7,8 +7,8 @@ #include #include -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace ublarcvapp { diff --git a/ublarcvapp/ubdllee/DLInteraction.h b/ublarcvapp/ubdllee/DLInteraction.h index a936838..d48a3a8 100644 --- a/ublarcvapp/ubdllee/DLInteraction.h +++ b/ublarcvapp/ubdllee/DLInteraction.h @@ -4,8 +4,8 @@ #include // larlite -#include "core/DataFormat/track.h" -#include "core/DataFormat/shower.h" +#include "larlite/DataFormat/track.h" +#include "larlite/DataFormat/shower.h" // larcv #include "larcv/core/DataFormat/ROI.h" diff --git a/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.cxx b/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.cxx index 20e9df4..ee866d9 100644 --- a/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.cxx +++ b/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.cxx @@ -1,7 +1,7 @@ #include "FixedCROIFromFlashAlgo.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" namespace ublarcvapp { namespace ubdllee { diff --git a/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h b/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h index 29548f7..421d647 100644 --- a/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h +++ b/ublarcvapp/ubdllee/FixedCROIFromFlashAlgo.h @@ -6,7 +6,7 @@ #include "larcv/core/DataFormat/ROI.h" #include "larcv/core/DataFormat/ImageMeta.h" -#include "DataFormat/opflash.h" +#include "larlite/DataFormat/opflash.h" #include "FixedCROIFromFlashConfig.h" diff --git a/ublarcvapp/ubdllee/NuAnaMC.cxx b/ublarcvapp/ubdllee/NuAnaMC.cxx index dd983e6..f4bc7b2 100644 --- a/ublarcvapp/ubdllee/NuAnaMC.cxx +++ b/ublarcvapp/ubdllee/NuAnaMC.cxx @@ -7,13 +7,13 @@ #include "larcv/core/DataFormat/EventROI.h" #include "larcv/core/DataFormat/EventChStatus.h" -#include "LArUtil/LArProperties.h" -#include "LArUtil/Geometry.h" -#include "LArUtil/DetectorProperties.h" -#include "LArUtil/TimeService.h" -#include "DataFormat/mctruth.h" -#include "DataFormat/mctrack.h" -#include "DataFormat/mcshower.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/DetectorProperties.h" +#include "larlite/LArUtil/TimeService.h" +#include "larlite/DataFormat/mctruth.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/mcshower.h" #include "ublarcvapp/ubdllee/dwall.h" diff --git a/ublarcvapp/ubdllee/NuAnaMC.h b/ublarcvapp/ubdllee/NuAnaMC.h index af93a8a..eb77bf9 100644 --- a/ublarcvapp/ubdllee/NuAnaMC.h +++ b/ublarcvapp/ubdllee/NuAnaMC.h @@ -20,7 +20,7 @@ #include "larcv/core/DataFormat/EventChStatus.h" #include "larcv/core/DataFormat/IOManager.h" -#include "LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "TTree.h" #include "ublarcvapp/LArliteHandler/LArliteManager.h" From 6f09902558e4cdf43dfee60fe26bb636d33ae2d1 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sat, 4 Sep 2021 02:41:31 -0400 Subject: [PATCH 03/80] fix larlite incdir, though should change to use cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c791cc..bd1cdd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ endif() find_package(Eigen3 REQUIRED) #---LArLite -set( LARLITE_INC_DIRS "$ENV{LARLITE_COREDIR}" "$ENV{LARLITE_BASEDIR}" "$ENV{LARLITE_USERDEVDIR}" "$ENV{LARLITE_BASEDIR}/../" ) +set( LARLITE_INC_DIRS "$ENV{LARLITE_INCDIR}" ) set( LARLITE_LIB_DIR "$ENV{LARLITE_LIBDIR}" ) set( HAS_LARLITE 1 ) file( GLOB LARLITE_LIBS "$ENV{LARLITE_LIBDIR}/libLArLite*.so" ) From eec451e4ab1b38d3310cadd4e90b585f95604a8b Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Thu, 28 Oct 2021 13:25:45 -0400 Subject: [PATCH 04/80] Initial FlashMatcher push --- ublarcvapp/MCTools/CMakeLists.txt | 6 ++- ublarcvapp/MCTools/FlashMatcher.cxx | 28 ++++++++++++ ublarcvapp/MCTools/FlashMatcher.h | 30 +++++++++++++ ublarcvapp/MCTools/LinkDef.h | 1 + ublarcvapp/MCTools/test/run_flashmatcher.py | 48 +++++++++++++++++++++ 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 ublarcvapp/MCTools/FlashMatcher.cxx create mode 100644 ublarcvapp/MCTools/FlashMatcher.h create mode 100644 ublarcvapp/MCTools/test/run_flashmatcher.py diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index ac173cd..c2ddbd2 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -10,7 +10,8 @@ set( HEADERS MCPixelPGraph.h crossingPointsAnaMethods.h NeutrinoVertex.h LArbysMC.h - NeutrinoPixelFilter.h ) + NeutrinoPixelFilter.h + FlashMatcher.h ) # Add sources add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx @@ -19,7 +20,8 @@ add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx crossingPointsAnaMethods.cxx NeutrinoVertex.cxx LArbysMC.cxx - NeutrinoPixelFilter.cxx ) + NeutrinoPixelFilter.cxx + FlashMatcher.cxx ) # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx new file mode 100644 index 0000000..3c97dfd --- /dev/null +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -0,0 +1,28 @@ +#include "FlashMatcher.h" + +#include "larlite/LArUtil/Geometry.h" +#include "larlite/DataFormat/mctruth.h" + +#include "crossingPointsAnaMethods.h" + +namespace ublarcvapp { +namespace mctools { + + /* + * grab time coordinate -> tick from mctrack mcstep, match with opflash + * time -> tick + * + * @param[in] ioll The larlite storage manager that contains mctruth class + * @return ??? + */ + + static std::string matchTrackAndFlash( larlite::storage_manager& ioll ) { + + return "hi"; + + } + + + +} +} diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h new file mode 100644 index 0000000..00844b9 --- /dev/null +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -0,0 +1,30 @@ +#ifndef __FLASH_MATCHER_H__ +#define __FLASH_MATCHER_H__ + +/* + * class for flash matching with mc truth + */ + +#include + +// larlite/core +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" + +namespace ublarcvapp { +namespace mctools { + + class FlashMatcher { + public: + + FlashMatcher() {}; + virtual ~FlashMatcher() {}; + + std::string matchTrackAndFlash( larlite::storage_manager& ioll ); + + }; + +} +} + +#endif diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index f202520..f5bbd66 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -23,6 +23,7 @@ #pragma link C++ class ublarcvapp::mctools::NeutrinoPixelFilter+; #pragma link C++ class ublarcvapp::mctools::TruthTrackSCE+; #pragma link C++ class ublarcvapp::mctools::TruthShowerTrunkSCE+; +#pragma link C++ class ublarcvapp::mctools::FlashMatcher+; #endif diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py new file mode 100644 index 0000000..b583dff --- /dev/null +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -0,0 +1,48 @@ +import os,sys,argparse + +parser = argparse.ArgumentParser("Test FlashMatcher") +parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite file") +# want another argument for opflash file +#parser.add_argument("-ilcv","--input-larcv",required=True,type=str,help="Input LArCV file") +#parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") +#parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") + +args = parser.parse_args() + +import ROOT as rt +from larlite import larlite +#from larcv import larcv +from ublarcvapp import ublarcvapp + +rt.gROOT.ProcessLine( "gErrorIgnoreLevel = 3002;" ) + +""" +test script that demos the Flash Matcher class. +""" + +rt.gStyle.SetOptStat(0) + +ioll = larlite.storage_manager( larlite.storage_manager.kREAD ) +ioll.add_in_filename( args.input_larlite ) +ioll.open() + +nentries = ioll.get_entries() +print("Number of entries: ",nentries) + +print("Start loop.") +fmutil = ublarcvapp.mctools.FlashMatcher +print(fmutil) + +#c = rt.TCanvas("c","c",1200,1800) +#c.Divide(1,3) + +for ientry in range( nentries ): + + print() + print("==========================") + print("===[ EVENT ",ientry," ]===") + ioll.go_to(ientry) +# iolcv.read_entry(ientry) + + +print("=== FIN ==") From cd1aa2ee4c2353d14c4c98bcaec45b7863d003fa Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Mon, 1 Nov 2021 16:08:43 -0400 Subject: [PATCH 05/80] Working script that finds ticks --- ublarcvapp/MCTools/FlashMatcher.cxx | 47 ++++++++++++++++++--- ublarcvapp/MCTools/FlashMatcher.h | 4 +- ublarcvapp/MCTools/test/run_flashmatcher.py | 22 ++++++++-- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 3c97dfd..49c3178 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -2,6 +2,7 @@ #include "larlite/LArUtil/Geometry.h" #include "larlite/DataFormat/mctruth.h" +#include "larlite/DataFormat/opflash.h" #include "crossingPointsAnaMethods.h" @@ -9,20 +10,56 @@ namespace ublarcvapp { namespace mctools { /* - * grab time coordinate -> tick from mctrack mcstep, match with opflash - * time -> tick + * grab time coordinate -> tick from mctrack mcstep * * @param[in] ioll The larlite storage manager that contains mctruth class - * @return ??? + * @return tick */ - static std::string matchTrackAndFlash( larlite::storage_manager& ioll ) { + Float_t FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) + { + larlite::event_mctruth* ev_mctruth + = (larlite::event_mctruth*)ioll.get_data(larlite::data::kMCTruth,"generator"); - return "hi"; + auto const& mctruth = ev_mctruth->at(0); + const larlite::mcstep& start = mctruth.GetNeutrino().Nu().Trajectory().front(); + std::cout << "Time: " << start.T() << std::endl; + + larutil::SpaceChargeMicroBooNE* _sce = nullptr; + Float_t tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + + return tick; + + } + + std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio ) + { + std::vector tickContainer = {}; + + larlite::event_opflash* ev_opflash_cosmic + = (larlite::event_opflash*)opio.get_data(larlite::data::kOpFlash,"simpleFlashCosmic"); + + for (auto const& opflash : *ev_opflash_cosmic) { + double time = opflash.Time(); + std::cout << time << std::endl; + double tick = time*1.0e-3 + 3200.0; + tickContainer.push_back(tick); } + //larutil::SpaceChargeMicroBooNE* _sce = nullptr; + //tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + return tickContainer; + } + +Float_t FlashMatcher::matchTicksFromTrackAndFlash( larlite::storage_manager& opio ) +{ + + +return 0.0; + +} } } diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index 00844b9..dbd5dff 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -20,7 +20,9 @@ namespace mctools { FlashMatcher() {}; virtual ~FlashMatcher() {}; - std::string matchTrackAndFlash( larlite::storage_manager& ioll ); + static Float_t grabTickFromMCTrack( larlite::storage_manager& ioll ); + static std::vector grabTickFromOpflash( larlite::storage_manager& opio ); + static Float_t matchTicksFromTrackAndFlash( larlite::storage_manager& opio ); }; diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py index b583dff..3b7d8e3 100644 --- a/ublarcvapp/MCTools/test/run_flashmatcher.py +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -1,12 +1,13 @@ import os,sys,argparse parser = argparse.ArgumentParser("Test FlashMatcher") -parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite file") +parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite mcinfo file") # want another argument for opflash file +parser.add_argument("-opreco", "--input-opreco",required=True,type=str,help="Input larlite opreco file") #parser.add_argument("-ilcv","--input-larcv",required=True,type=str,help="Input LArCV file") #parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") #parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") - + args = parser.parse_args() import ROOT as rt @@ -26,11 +27,17 @@ ioll.add_in_filename( args.input_larlite ) ioll.open() +opio = larlite.storage_manager( larlite.storage_manager.kREAD ) +opio.add_in_filename( args.input_opreco ) +opio.open() + nentries = ioll.get_entries() print("Number of entries: ",nentries) print("Start loop.") fmutil = ublarcvapp.mctools.FlashMatcher +#vtxutil = ublarcvapp.mctools.NeutrinoVertex +#print(vtxutil) print(fmutil) #c = rt.TCanvas("c","c",1200,1800) @@ -38,11 +45,18 @@ for ientry in range( nentries ): - print() + print() print("==========================") print("===[ EVENT ",ientry," ]===") ioll.go_to(ientry) + opio.go_to(ientry) + + track_tick = fmutil.grabTickFromMCTrack( ioll ) + op_tick = fmutil.grabTickFromOpflash( opio ) +# fmtrack_tick = vtxutil.getImageCoords( ioll ) + print("track_tick",track_tick) + print("op_tick",op_tick) # iolcv.read_entry(ientry) - + print("=== FIN ==") From a005a50b93cf7c9371309d48282bf3412c2047c4 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Fri, 5 Nov 2021 11:38:04 -0400 Subject: [PATCH 06/80] Matches ticks --- ublarcvapp/MCTools/FlashMatcher.cxx | 58 +++++++++++++-------- ublarcvapp/MCTools/FlashMatcher.h | 6 +-- ublarcvapp/MCTools/test/run_flashmatcher.py | 5 +- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 49c3178..237a094 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -1,7 +1,9 @@ #include "FlashMatcher.h" +#include + #include "larlite/LArUtil/Geometry.h" -#include "larlite/DataFormat/mctruth.h" +#include "larlite/DataFormat/mctrack.h" #include "larlite/DataFormat/opflash.h" #include "crossingPointsAnaMethods.h" @@ -16,48 +18,58 @@ namespace mctools { * @return tick */ - Float_t FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) + double FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) { - larlite::event_mctruth* ev_mctruth - = (larlite::event_mctruth*)ioll.get_data(larlite::data::kMCTruth,"generator"); + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); - auto const& mctruth = ev_mctruth->at(0); - const larlite::mcstep& start = mctruth.GetNeutrino().Nu().Trajectory().front(); + auto const& mctrack = ev_mctrack->at(0); + const larlite::mcstep& start = mctrack.Start(); std::cout << "Time: " << start.T() << std::endl; larutil::SpaceChargeMicroBooNE* _sce = nullptr; - Float_t tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); return tick; } - std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio ) - { - std::vector tickContainer = {}; + std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio , std::string producer) { - larlite::event_opflash* ev_opflash_cosmic - = (larlite::event_opflash*)opio.get_data(larlite::data::kOpFlash,"simpleFlashCosmic"); + std::vector tickContainer = {}; - for (auto const& opflash : *ev_opflash_cosmic) { - double time = opflash.Time(); - std::cout << time << std::endl; - double tick = time*1.0e-3 + 3200.0; - tickContainer.push_back(tick); - } + larlite::event_opflash* ev_opflash + = (larlite::event_opflash*)opio.get_data(larlite::data::kOpFlash, producer); + + for (auto const& opflash : *ev_opflash) { + double time = opflash.Time(); + std::cout << time << std::endl; + double tick = time/0.5 + 3200.0; + tickContainer.push_back(tick); + } - //larutil::SpaceChargeMicroBooNE* _sce = nullptr; - //tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + std::sort( tickContainer.begin(), tickContainer.end() ); return tickContainer; } -Float_t FlashMatcher::matchTicksFromTrackAndFlash( larlite::storage_manager& opio ) -{ +double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks ) { + + auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); + + if (match == flashTicks.begin()) { + return flashTicks[0]; + } + + double a = *(match - 1); + double b = *(match); + if (fabs(mctrackTick - a) < fabs(mctrackTick - b)) { + return flashTicks [ match - flashTicks.begin() - 1 ]; + } -return 0.0; + return flashTicks[ match - flashTicks.begin() ]; } diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index dbd5dff..835c271 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -20,9 +20,9 @@ namespace mctools { FlashMatcher() {}; virtual ~FlashMatcher() {}; - static Float_t grabTickFromMCTrack( larlite::storage_manager& ioll ); - static std::vector grabTickFromOpflash( larlite::storage_manager& opio ); - static Float_t matchTicksFromTrackAndFlash( larlite::storage_manager& opio ); + static double grabTickFromMCTrack( larlite::storage_manager& ioll ); + static std::vector grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ); + static double matchTicks( double mctrack_tick, std::vector flash_ticks ); }; diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py index 3b7d8e3..b3fe958 100644 --- a/ublarcvapp/MCTools/test/run_flashmatcher.py +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -52,11 +52,12 @@ opio.go_to(ientry) track_tick = fmutil.grabTickFromMCTrack( ioll ) - op_tick = fmutil.grabTickFromOpflash( opio ) + op_tick = fmutil.grabTickFromOpflash( opio, "simpleFlashCosmic" ) # fmtrack_tick = vtxutil.getImageCoords( ioll ) print("track_tick",track_tick) print("op_tick",op_tick) # iolcv.read_entry(ientry) - + match = fmutil.matchTicks( track_tick, op_tick ) + print("Found match: ", match ) print("=== FIN ==") From 293989ed5230ed06e550be9471ea951206c8110b Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Tue, 9 Nov 2021 09:57:49 -0500 Subject: [PATCH 07/80] Working FlashMatcher for both Cosmic and Beam --- ublarcvapp/MCTools/FlashMatcher.cxx | 59 +++++++++++++++------ ublarcvapp/MCTools/FlashMatcher.h | 4 +- ublarcvapp/MCTools/test/run_flashmatcher.py | 7 +-- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 237a094..1c84423 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -18,24 +18,38 @@ namespace mctools { * @return tick */ - double FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) + std::tuple FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); auto const& mctrack = ev_mctrack->at(0); + + std::cout << "Origin: " << mctrack.Origin() << std::endl; + + std::string producer; + Bool_t isCosmic; + if ( mctrack.Origin() == 1 ) { + producer = "simpleFlashBeam"; + } else { + producer = "simpleFlashCosmic"; + isCosmic = 1; + } + const larlite::mcstep& start = mctrack.Start(); - std::cout << "Time: " << start.T() << std::endl; + //std::cout << "Time: " << start.T() << std::endl; larutil::SpaceChargeMicroBooNE* _sce = nullptr; double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); - return tick; + return std::make_tuple( tick, producer, isCosmic ); } - std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio , std::string producer) { + std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ) { + + //std::cout << "If this is a neutrino, this would print 1: " << isNeutrino << std::endl; std::vector tickContainer = {}; @@ -44,7 +58,7 @@ namespace mctools { for (auto const& opflash : *ev_opflash) { double time = opflash.Time(); - std::cout << time << std::endl; + //std::cout << time << std::endl; double tick = time/0.5 + 3200.0; tickContainer.push_back(tick); } @@ -54,24 +68,37 @@ namespace mctools { return tickContainer; } -double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks ) { + double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks, Bool_t isCosmic ) { - auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); + // for cosmic tracks, will return -999.999 if there is no opflash found within the threshold - if (match == flashTicks.begin()) { - return flashTicks[0]; - } + double threshold; + if (isCosmic == 1) { + threshold = 400.0; // 1 tick = 0.5 us + } else { + threshold = std::numeric_limits::infinity(); + } - double a = *(match - 1); - double b = *(match); + auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); - if (fabs(mctrackTick - a) < fabs(mctrackTick - b)) { - return flashTicks [ match - flashTicks.begin() - 1 ]; + double a = *(match - 1); + double b = *(match); + + if (match == flashTicks.begin() && fabs(b-mctrackTick) <= threshold) { + return flashTicks[0]; + } + + if (fabs(mctrackTick - a) < fabs(mctrackTick - b) && fabs(mctrackTick - a) <= threshold) { + return flashTicks [ match - flashTicks.begin() - 1 ]; } - return flashTicks[ match - flashTicks.begin() ]; + if ( fabs(mctrackTick - b) <= threshold ) + return flashTicks[ match - flashTicks.begin() ]; + + return -999.999; + + } -} } } diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index 835c271..b254222 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -20,9 +20,9 @@ namespace mctools { FlashMatcher() {}; virtual ~FlashMatcher() {}; - static double grabTickFromMCTrack( larlite::storage_manager& ioll ); + static std::tuple grabTickFromMCTrack( larlite::storage_manager& ioll ); static std::vector grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ); - static double matchTicks( double mctrack_tick, std::vector flash_ticks ); + static double matchTicks( double mctrack_tick, std::vector flash_ticks, Bool_t isCosmic ); }; diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py index b3fe958..7b95959 100644 --- a/ublarcvapp/MCTools/test/run_flashmatcher.py +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -51,13 +51,14 @@ ioll.go_to(ientry) opio.go_to(ientry) - track_tick = fmutil.grabTickFromMCTrack( ioll ) - op_tick = fmutil.grabTickFromOpflash( opio, "simpleFlashCosmic" ) + track_tick, producer, isCosmic = fmutil.grabTickFromMCTrack( ioll ) + print(producer) + op_tick = fmutil.grabTickFromOpflash( opio, producer ) # fmtrack_tick = vtxutil.getImageCoords( ioll ) print("track_tick",track_tick) print("op_tick",op_tick) # iolcv.read_entry(ientry) - match = fmutil.matchTicks( track_tick, op_tick ) + match = fmutil.matchTicks( track_tick, op_tick, isCosmic ) print("Found match: ", match ) print("=== FIN ==") From cbbb7655c3d92afa98424544e94a6882505359cf Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Tue, 9 Nov 2021 10:43:14 -0500 Subject: [PATCH 08/80] Cleanup and comments describing methods --- ublarcvapp/MCTools/FlashMatcher.cxx | 32 ++++++++++++++++++----------- ublarcvapp/MCTools/FlashMatcher.h | 3 --- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 1c84423..e195e1b 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -1,8 +1,5 @@ #include "FlashMatcher.h" -#include - -#include "larlite/LArUtil/Geometry.h" #include "larlite/DataFormat/mctrack.h" #include "larlite/DataFormat/opflash.h" @@ -12,12 +9,11 @@ namespace ublarcvapp { namespace mctools { /* - * grab time coordinate -> tick from mctrack mcstep + * grab time coordinate from mctrack mcstep -> convert to tick * * @param[in] ioll The larlite storage manager that contains mctruth class - * @return tick + * @return tuple with tick, producer string, and cosmic flag */ - std::tuple FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) { larlite::event_mctrack* ev_mctrack @@ -38,8 +34,6 @@ namespace mctools { const larlite::mcstep& start = mctrack.Start(); - //std::cout << "Time: " << start.T() << std::endl; - larutil::SpaceChargeMicroBooNE* _sce = nullptr; double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); @@ -47,10 +41,15 @@ namespace mctools { } + /* + * grab time coordinate from opflash -> convert to tick + * + * @param[in] opio The larlite storage manager that contains opflash class + * @param[in] producer String labeling the producer, e.g. "simpleFlashBeam" + * @return Vector containing all opflash times for the track in ticks + */ std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ) { - //std::cout << "If this is a neutrino, this would print 1: " << isNeutrino << std::endl; - std::vector tickContainer = {}; larlite::event_opflash* ev_opflash @@ -68,10 +67,19 @@ namespace mctools { return tickContainer; } + /* + * matches mctrack tick to opflash tick + * for cosmics, will return -999.999 if there is no opflash found within the threshold + * for beam tracks, will find the closest matching opflash + * + * @param[in] mctrackTick Time in ticks for the mctrack to be matched to + * @param[in] flashTicks Vector of potential opflash matches in ticks + * @param[in] isCosmic Cosmic flag to determine threshold + * + * @return Value of the closest matching opflash tick + */ double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks, Bool_t isCosmic ) { - // for cosmic tracks, will return -999.999 if there is no opflash found within the threshold - double threshold; if (isCosmic == 1) { threshold = 400.0; // 1 tick = 0.5 us diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index b254222..d559743 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -5,11 +5,8 @@ * class for flash matching with mc truth */ -#include - // larlite/core #include "larlite/DataFormat/storage_manager.h" -#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" namespace ublarcvapp { namespace mctools { From 126625fa337d33c158741e4253f52bc1e3c2f3a0 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Wed, 10 Nov 2021 10:16:08 -0500 Subject: [PATCH 09/80] looks at all tracks in event; accounts for empty flash vector --- ublarcvapp/MCTools/FlashMatcher.cxx | 27 ++++++++++++++++++++------- ublarcvapp/MCTools/FlashMatcher.h | 3 ++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index e195e1b..933520a 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -8,18 +8,28 @@ namespace ublarcvapp { namespace mctools { + + int FlashMatcher::numTracks( larlite::storage_manager& ioll ) { + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + + int numTracks = ev_mctrack->size(); + + return numTracks; + } /* * grab time coordinate from mctrack mcstep -> convert to tick * * @param[in] ioll The larlite storage manager that contains mctruth class * @return tuple with tick, producer string, and cosmic flag */ - std::tuple FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll ) - { + std::tuple FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll, int i ) { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); - auto const& mctrack = ev_mctrack->at(0); + std::cout << "Number of tracks in event: " << ev_mctrack->size() << std::endl; + + auto const& mctrack = ev_mctrack->at(i); std::cout << "Origin: " << mctrack.Origin() << std::endl; @@ -82,20 +92,23 @@ namespace mctools { double threshold; if (isCosmic == 1) { - threshold = 400.0; // 1 tick = 0.5 us + threshold = 2.0; // 1 tick = 0.5 us } else { threshold = std::numeric_limits::infinity(); } - auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); + if (flashTicks.empty() == 1) + return 999.999; - double a = *(match - 1); + auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); double b = *(match); - if (match == flashTicks.begin() && fabs(b-mctrackTick) <= threshold) { + if (match == flashTicks.begin() && fabs(b - mctrackTick) <= threshold) { return flashTicks[0]; } + double a = *(match - 1); + if (fabs(mctrackTick - a) < fabs(mctrackTick - b) && fabs(mctrackTick - a) <= threshold) { return flashTicks [ match - flashTicks.begin() - 1 ]; } diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index d559743..c620390 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -17,7 +17,8 @@ namespace mctools { FlashMatcher() {}; virtual ~FlashMatcher() {}; - static std::tuple grabTickFromMCTrack( larlite::storage_manager& ioll ); + static int numTracks( larlite::storage_manager& ioll ); + static std::tuple grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); static std::vector grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ); static double matchTicks( double mctrack_tick, std::vector flash_ticks, Bool_t isCosmic ); From 9176810a9a1b0953eefcc24fd8dad53a8276db60 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Fri, 12 Nov 2021 13:50:43 -0500 Subject: [PATCH 10/80] added functionality for showers --- ublarcvapp/MCTools/FlashMatcher.cxx | 70 ++++++++++++++++++++++++++--- ublarcvapp/MCTools/FlashMatcher.h | 19 +++++--- 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 933520a..6060a33 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -1,5 +1,6 @@ #include "FlashMatcher.h" +#include "larlite/DataFormat/mcshower.h" #include "larlite/DataFormat/mctrack.h" #include "larlite/DataFormat/opflash.h" @@ -17,13 +18,24 @@ namespace mctools { return numTracks; } + + int FlashMatcher::numShowers( larlite::storage_manager& ioll ) { + + larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + + int numShowers = ev_mcshower->size(); + + return numShowers; + + } /* * grab time coordinate from mctrack mcstep -> convert to tick * * @param[in] ioll The larlite storage manager that contains mctruth class * @return tuple with tick, producer string, and cosmic flag */ - std::tuple FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll, int i ) { + double FlashMatcher::grabTickFromMCTrack( larlite::storage_manager& ioll, int i ) { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); @@ -31,12 +43,15 @@ namespace mctools { auto const& mctrack = ev_mctrack->at(i); + std::cout << "TrackID is: " << mctrack.TrackID() << std::endl; + std::cout << "Mother TrackID is: " << mctrack.MotherTrackID() << std::endl; + std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; + std::cout << "Origin: " << mctrack.Origin() << std::endl; - std::string producer; - Bool_t isCosmic; if ( mctrack.Origin() == 1 ) { producer = "simpleFlashBeam"; + isCosmic = 0; } else { producer = "simpleFlashCosmic"; isCosmic = 1; @@ -47,7 +62,50 @@ namespace mctools { larutil::SpaceChargeMicroBooNE* _sce = nullptr; double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); - return std::make_tuple( tick, producer, isCosmic ); + // check for primary muons (cosmic) + if ( isCosmic == 1 && mctrack.TrackID() != mctrack.MotherTrackID() && mctrack.PdgCode() != 13 ) { + tick = -999.997; + } + + return tick; + + } + + double FlashMatcher::grabTickFromMCShower( larlite::storage_manager& ioll, int i ) { + + larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + + std::cout << "Number of showers in event: " << ev_mcshower->size() << std::endl; + + auto const& mcshower = ev_mcshower->at(i); + + std::cout << "TrackID is: " << mcshower.TrackID() << std::endl; + std::cout << "Mother TrackID is: " << mcshower.MotherTrackID() << std::endl; + std::cout << "PDG is: " << mcshower.PdgCode() << std::endl; + + std::cout << "Origin: " << mcshower.Origin() << std::endl; + + if ( mcshower.Origin() == 1 ) { + producer = "simpleFlashBeam"; + isCosmic = 0; + } else { + producer = "simpleFlashCosmic"; + isCosmic = 1; + } + + const larlite::mcstep& start = mcshower.Start(); + + larutil::SpaceChargeMicroBooNE* _sce = nullptr; + double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + + // check for primary muons (cosmic) + if ( isCosmic == 1 && mcshower.TrackID() != mcshower.MotherTrackID() ) { + tick = -999.997; + } + + return tick; + } @@ -58,7 +116,7 @@ namespace mctools { * @param[in] producer String labeling the producer, e.g. "simpleFlashBeam" * @return Vector containing all opflash times for the track in ticks */ - std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ) { + std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio ) { std::vector tickContainer = {}; @@ -88,7 +146,7 @@ namespace mctools { * * @return Value of the closest matching opflash tick */ - double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks, Bool_t isCosmic ) { + double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks ) { double threshold; if (isCosmic == 1) { diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index c620390..a457f7f 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -14,13 +14,22 @@ namespace mctools { class FlashMatcher { public: - FlashMatcher() {}; + FlashMatcher() { + + isCosmic = 0; + + }; virtual ~FlashMatcher() {}; - static int numTracks( larlite::storage_manager& ioll ); - static std::tuple grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); - static std::vector grabTickFromOpflash( larlite::storage_manager& opio, std::string producer ); - static double matchTicks( double mctrack_tick, std::vector flash_ticks, Bool_t isCosmic ); + int numTracks( larlite::storage_manager& ioll ); + int numShowers( larlite::storage_manager& ioll ); + double grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); + double grabTickFromMCShower( larlite::storage_manager& ioll, int i ); + std::vector grabTickFromOpflash( larlite::storage_manager& opio ); + double matchTicks( double mctrack_tick, std::vector flash_ticks ); + + Bool_t isCosmic; + std::string producer; }; From 1b89a38398c4caaa58e89ea704676e638c87844b Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 23 Nov 2021 11:36:41 -0500 Subject: [PATCH 11/80] allow one to run the mcpixelpgraph with larlite only --- ublarcvapp/MCTools/test/run_mcpixelpgraph.py | 84 +++++++++++--------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py index 3a3750f..d12ac59 100644 --- a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py +++ b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py @@ -1,8 +1,9 @@ +from __future__ import print_function import os,sys,argparse parser = argparse.ArgumentParser("Test MCPixelPGraph") parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite file") -parser.add_argument("-ilcv","--input-larcv",required=True,type=str,help="Input LArCV file") +parser.add_argument("-ilcv","--input-larcv",required=False,default=None,type=str,help="Input LArCV file") parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") parser.add_argument("-d", "--debug", action='store_true', default=False, help="Run in debug mode") @@ -23,19 +24,24 @@ ioll.add_in_filename( args.input_larlite ) ioll.open() -if args.tick_backward: - iolcv = larcv.IOManager( larcv.IOManager.kREAD, "larcv", larcv.IOManager.kTickBackward ) +if args.input_larcv is not None: + # has larcv images to get pixels + HAS_LARCV = True + if args.tick_backward: + iolcv = larcv.IOManager( larcv.IOManager.kREAD, "larcv", larcv.IOManager.kTickBackward ) + else: + iolcv = larcv.IOManager( larcv.IOManager.kREAD, "larcv", larcv.IOManager.kTickForward ) + iolcv.add_in_file( args.input_larcv ) + iolcv.reverse_all_products() + iolcv.initialize() else: - iolcv = larcv.IOManager( larcv.IOManager.kREAD, "larcv", larcv.IOManager.kTickForward ) -iolcv.add_in_file( args.input_larcv ) -iolcv.reverse_all_products() -iolcv.initialize() + HAS_LARCV = False -nentries = iolcv.get_n_entries() -print "Number of entries: ",nentries +nentries = ioll.get_entries() +print("Number of entries: ",nentries) #nentries = 10 -print "Start loop." +print("Start loop.") mcpg = ublarcvapp.mctools.MCPixelPGraph() if args.debug: @@ -49,29 +55,33 @@ c = rt.TCanvas("c","c",1200,1800) c.Divide(1,3) -for ientry in xrange( nentries ): +for ientry in range( nentries ): - print - print "==========================" - print "===[ EVENT ",ientry," ]===" + print() + print("==========================") + print("===[ EVENT ",ientry," ]===") ioll.go_to(ientry) - iolcv.read_entry(ientry) - - ev_adc = iolcv.get_data( larcv.kProductImage2D, args.adc ) - print "number of images: ",ev_adc.Image2DArray().size() - adc_v = ev_adc.Image2DArray() - for p in xrange(adc_v.size()): - print " image[",p,"] ",adc_v[p].meta().dump() + if HAS_LARCV: + iolcv.read_entry(ientry) + ev_adc = iolcv.get_data( larcv.kProductImage2D, args.adc ) + print("number of images: ",ev_adc.Image2DArray().size()) + adc_v = ev_adc.Image2DArray() + for p in range(adc_v.size()): + print(" image[",p,"] ",adc_v[p].meta().dump()) - # make histogram - hist_v = larcv.rootutils.as_th2d_v( adc_v, "hentry%d"%(ientry) ) - for ih in xrange(adc_v.size()): - h = hist_v[ih] - h.GetZaxis().SetRangeUser(0,100) - - mcpg.buildgraph( iolcv, ioll ) + # make histogram + hist_v = larcv.rootutils.as_th2d_v( adc_v, "hentry%d"%(ientry) ) + for ih in range(adc_v.size()): + h = hist_v[ih] + h.GetZaxis().SetRangeUser(0,100) + + mcpg.buildgraph( iolcv, ioll ) + else: + mcpg.buildgraphonly( ioll ) + mcpg.printAllNodeInfo() #mcpg.printGraph() + sys.exit(0) #primaries = mcpg.getPrimaryParticles() primaries = mcpg.node_v @@ -79,14 +89,14 @@ # get primary electron, make tgraph of pixels graph_v = [] bbox_v = [] - for i in xrange(primaries.size()): + for i in range(primaries.size()): node = primaries.at(i) - print "primary pid[",node.pid,"]" + print("primary pid[",node.pid,"]") if node.pid in [11,2212,13,-13,22,211,-211]: - print " making tgraph for pid=",node.pid + print(" making tgraph for pid=",node.pid) e_v = [] bb_v = [] - for p in xrange(3): + for p in range(3): if node.pix_vv[p].size()==0: e_v.append(None) bb_v.append(None) @@ -100,7 +110,7 @@ bb.SetFillStyle(0) bb.SetLineWidth(2) - for j in xrange( node.pix_vv[p].size()/2 ): + for j in range( node.pix_vv[p].size()/2 ): g.SetPoint(j, node.pix_vv[p][2*j+1], node.pix_vv[p][2*j] ) # wire, tick g.SetMarkerStyle(20) g.SetMarkerSize(0.5) @@ -130,10 +140,10 @@ graph_v.append(e_v) bbox_v.append(bb_v) - print "num graphs: ",len(graph_v) + print("num graphs: ",len(graph_v)) #draw canvas - for p in xrange(3): + for p in range(3): c.cd(p+1) hist_v[p].Draw("colz") for e_v in graph_v: @@ -144,8 +154,8 @@ bb_v[p].Draw() c.Update() - print "[enter to continue]" + print("[enter to continue]") raw_input() -print "=== FIN ==" +print("=== FIN ==") From dfdd9c0c18185ecbad08ba80dc6bcb915f98013a Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Wed, 5 Jan 2022 15:24:41 -0500 Subject: [PATCH 12/80] Latest commit in preparation for merge --- ublarcvapp/MCTools/FlashMatcher.cxx | 27 ++++++++++--- ublarcvapp/MCTools/test/run_flashmatcher.py | 44 ++++++++++++++++----- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 6060a33..3f3a2c6 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -3,6 +3,7 @@ #include "larlite/DataFormat/mcshower.h" #include "larlite/DataFormat/mctrack.h" #include "larlite/DataFormat/opflash.h" +#include "larlite/LArUtil/LArProperties.h" #include "crossingPointsAnaMethods.h" @@ -60,13 +61,20 @@ namespace mctools { const larlite::mcstep& start = mctrack.Start(); larutil::SpaceChargeMicroBooNE* _sce = nullptr; + + const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + double xPos = start.X(); + double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + tick = tick - xPos / cm_per_tick; - // check for primary muons (cosmic) - if ( isCosmic == 1 && mctrack.TrackID() != mctrack.MotherTrackID() && mctrack.PdgCode() != 13 ) { - tick = -999.997; + // check for primaries + if ( mctrack.TrackID() != mctrack.MotherTrackID() ) { + return -999.997; } + std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; + return tick; } @@ -97,13 +105,20 @@ namespace mctools { const larlite::mcstep& start = mcshower.Start(); larutil::SpaceChargeMicroBooNE* _sce = nullptr; + + const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + double xPos = start.X(); + double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + tick = tick - xPos / cm_per_tick; - // check for primary muons (cosmic) - if ( isCosmic == 1 && mcshower.TrackID() != mcshower.MotherTrackID() ) { - tick = -999.997; + // check for primaries + if ( mcshower.TrackID() != mcshower.MotherTrackID() ) { + return -999.997; } + std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; + return tick; diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py index 7b95959..a2c32d3 100644 --- a/ublarcvapp/MCTools/test/run_flashmatcher.py +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -35,7 +35,7 @@ print("Number of entries: ",nentries) print("Start loop.") -fmutil = ublarcvapp.mctools.FlashMatcher +fmutil = ublarcvapp.mctools.FlashMatcher() #vtxutil = ublarcvapp.mctools.NeutrinoVertex #print(vtxutil) print(fmutil) @@ -43,6 +43,15 @@ #c = rt.TCanvas("c","c",1200,1800) #c.Divide(1,3) +listy = [] + +# for testing: +#match = fmutil.matchTicks( 100.0, [], 1 ) +#print(match) + +print("isCosmic from ctor: ",fmutil.isCosmic) + + for ientry in range( nentries ): print() @@ -51,14 +60,29 @@ ioll.go_to(ientry) opio.go_to(ientry) - track_tick, producer, isCosmic = fmutil.grabTickFromMCTrack( ioll ) - print(producer) - op_tick = fmutil.grabTickFromOpflash( opio, producer ) -# fmtrack_tick = vtxutil.getImageCoords( ioll ) - print("track_tick",track_tick) - print("op_tick",op_tick) -# iolcv.read_entry(ientry) - match = fmutil.matchTicks( track_tick, op_tick, isCosmic ) - print("Found match: ", match ) + numTracks = fmutil.numTracks( ioll ) + + for i in range( 0, numTracks, 1 ): + track_tick = fmutil.grabTickFromMCTrack( ioll, i ) + + producer = fmutil.producer + isCosmic = fmutil.isCosmic + + print("Now isCosmic has been set to: ",fmutil.isCosmic) + print(producer) + + op_tick = fmutil.grabTickFromOpflash( opio ) + # fmtrack_tick = vtxutil.getImageCoords( ioll ) + print("track_tick",track_tick) + print("op_tick",op_tick) + # iolcv.read_entry(ientry) + match = fmutil.matchTicks( track_tick, op_tick ) + print("Found match: ", match ) + if isCosmic == 1 and match != -999.999 and track_tick != -999.997: + listy.append( match - track_tick ) +print("list: ", listy) + +print("size of list: ", len(listy)) + print("=== FIN ==") From 126874995917c61a495324f7a4f7e5c53a3d974a Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Fri, 21 Jan 2022 10:42:36 -0500 Subject: [PATCH 13/80] Creates output file with FM info --- ublarcvapp/MCTools/FlashMatcher.cxx | 82 ++++++++++++++++++++- ublarcvapp/MCTools/FlashMatcher.h | 34 +++++++++ ublarcvapp/MCTools/test/run_flashmatcher.py | 35 +++++++-- 3 files changed, 142 insertions(+), 9 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 3f3a2c6..af04043 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -11,6 +11,70 @@ namespace ublarcvapp { namespace mctools { + void FlashMatcher::initialize() + { + _fm_tree = new TTree("fmtree","Flashmatched Tree"); + bindAnaVariables(_fm_tree); + + std::cout << "Made tree and bound vars" << std::endl; + + //_voxelTree = new TTree("voxtree","Voxeldata Tree"); + //_voxelTree = mgr.CloneTree() + + } + + void FlashMatcher::bindAnaVariables( TTree* fm_tree ) + { + + // event indexing + fm_tree->Branch("flashmatcher_run", &_run, "flashmatcher_run/I"); + fm_tree->Branch("flashmatcher_subrun", &_subrun, "flashmatcher_subrun/I"); + fm_tree->Branch("flashmatcher_event", &_event, "flashmatcher_event/I"); + fm_tree->Branch("flashmatcher_ancestorid" , &_ancestorID, "flashmatcher_ancestorid/I"); + fm_tree->Branch("flashmatcher_clustertick" , &_clusterTick, "flashmatcher_clustertick/D"); + fm_tree->Branch("flashmatcher_flashtick" , &_flashTick, "flashmatcher_flashtick/D"); + fm_tree->Branch("flashmatcher_origin" , &_origin, "flashmatcher_origin/I"); + + } + + bool FlashMatcher::process(larlite::storage_manager& mgr) + { + + Clear(); + + _run = mgr.run_id(); + _subrun = mgr.subrun_id(); + _event = mgr.event_id(); + _ancestorID = ancestorID; + _clusterTick = clusterTick; + _flashTick = flashTick; + _origin = origin; + + if ( _fm_tree ) + _fm_tree->Fill(); + + return true; + + } + + void FlashMatcher::finalize() + { + if ( _fm_tree ) + _fm_tree->Write(); + } + + void FlashMatcher::Clear() + { + _run = 0; + _subrun = 0; + _event = 0; + _ancestorID = 0; + _clusterTick = 0; + _flashTick = 0; + _origin = 0; + + } + int FlashMatcher::numTracks( larlite::storage_manager& ioll ) { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); @@ -49,6 +113,7 @@ namespace mctools { std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; std::cout << "Origin: " << mctrack.Origin() << std::endl; + origin = mctrack.Origin(); if ( mctrack.Origin() == 1 ) { producer = "simpleFlashBeam"; @@ -75,6 +140,8 @@ namespace mctools { std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; + ancestorID = mctrack.AncestorTrackID(); + return tick; } @@ -93,6 +160,7 @@ namespace mctools { std::cout << "PDG is: " << mcshower.PdgCode() << std::endl; std::cout << "Origin: " << mcshower.Origin() << std::endl; + origin = mcshower.Origin(); if ( mcshower.Origin() == 1 ) { producer = "simpleFlashBeam"; @@ -170,24 +238,34 @@ namespace mctools { threshold = std::numeric_limits::infinity(); } - if (flashTicks.empty() == 1) + if (flashTicks.empty() == 1) { + clusterTick = mctrackTick; + flashTick = 999.999; return 999.999; + } auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); double b = *(match); if (match == flashTicks.begin() && fabs(b - mctrackTick) <= threshold) { + clusterTick = mctrackTick; + flashTick = flashTicks[0]; return flashTicks[0]; } double a = *(match - 1); if (fabs(mctrackTick - a) < fabs(mctrackTick - b) && fabs(mctrackTick - a) <= threshold) { + clusterTick = mctrackTick; + flashTick = flashTicks [ match - flashTicks.begin() - 1 ]; return flashTicks [ match - flashTicks.begin() - 1 ]; } - if ( fabs(mctrackTick - b) <= threshold ) + if ( fabs(mctrackTick - b) <= threshold ) { + clusterTick = mctrackTick; + flashTick = flashTicks[ match - flashTicks.begin() ]; return flashTicks[ match - flashTicks.begin() ]; + } return -999.999; diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index a457f7f..3d26551 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -8,6 +8,8 @@ // larlite/core #include "larlite/DataFormat/storage_manager.h" +#include "TTree.h" + namespace ublarcvapp { namespace mctools { @@ -17,10 +19,19 @@ namespace mctools { FlashMatcher() { isCosmic = 0; + if (_fm_tree) + delete _fm_tree; + _fm_tree = nullptr; }; virtual ~FlashMatcher() {}; + void initialize(); + void bindAnaVariables( TTree* ); + bool process(larlite::storage_manager& mgr); + void finalize(); + void Clear(); + int numTracks( larlite::storage_manager& ioll ); int numShowers( larlite::storage_manager& ioll ); double grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); @@ -31,6 +42,29 @@ namespace mctools { Bool_t isCosmic; std::string producer; + protected: + + TTree* _fm_tree; + //TTree* _voxelTree; + + public: + + // Variables in TTree + int _run; + int _subrun; + int _event; + int _ancestorID; + double _clusterTick; + double _flashTick; + int _origin; + + // Vars not in tree but in loop + int ancestorID; + double clusterTick; + double flashTick; + int origin; + + }; } diff --git a/ublarcvapp/MCTools/test/run_flashmatcher.py b/ublarcvapp/MCTools/test/run_flashmatcher.py index a2c32d3..877dea0 100644 --- a/ublarcvapp/MCTools/test/run_flashmatcher.py +++ b/ublarcvapp/MCTools/test/run_flashmatcher.py @@ -4,6 +4,8 @@ parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite mcinfo file") # want another argument for opflash file parser.add_argument("-opreco", "--input-opreco",required=True,type=str,help="Input larlite opreco file") +#parser.add_argument("-iv", "--input-voxelfile",required=True,type=str,help="Input voxeldata file") +parser.add_argument("-out", "--output_file",required=True,type=str,help="Output file") #parser.add_argument("-ilcv","--input-larcv",required=True,type=str,help="Input LArCV file") #parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") #parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") @@ -31,6 +33,17 @@ opio.add_in_filename( args.input_opreco ) opio.open() +f = TFile(args.input_voxelfile,"READ") +print("passed tfile part") + +#voxio = larlite.storage_manager( larlite.storage_manager.kREAD ) +#voxio.add_in_filename( args.input_voxelfile ) +#voxio.open() + +outio = larlite.storage_manager( larlite.storage_manager.kWRITE ) +outio.set_out_filename( args.output_file ) +outio.open() + nentries = ioll.get_entries() print("Number of entries: ",nentries) @@ -46,13 +59,15 @@ listy = [] # for testing: -#match = fmutil.matchTicks( 100.0, [], 1 ) +#match = fmutil.matchTicks( 100.0, [], 1 ) #print(match) print("isCosmic from ctor: ",fmutil.isCosmic) +fmutil.initialize( voxio ) -for ientry in range( nentries ): +#for ientry in range( nentries ): +for ientry in range( 3 ): print() print("==========================") @@ -61,16 +76,16 @@ opio.go_to(ientry) numTracks = fmutil.numTracks( ioll ) - + for i in range( 0, numTracks, 1 ): track_tick = fmutil.grabTickFromMCTrack( ioll, i ) producer = fmutil.producer isCosmic = fmutil.isCosmic - + print("Now isCosmic has been set to: ",fmutil.isCosmic) print(producer) - + op_tick = fmutil.grabTickFromOpflash( opio ) # fmtrack_tick = vtxutil.getImageCoords( ioll ) print("track_tick",track_tick) @@ -78,11 +93,17 @@ # iolcv.read_entry(ientry) match = fmutil.matchTicks( track_tick, op_tick ) print("Found match: ", match ) + + if match != -999.999 and match != 999.999 and track_tick != -999.997: + fmutil.process( ioll ) + if isCosmic == 1 and match != -999.999 and track_tick != -999.997: listy.append( match - track_tick ) print("list: ", listy) - + +fmutil.finalize() + print("size of list: ", len(listy)) - + print("=== FIN ==") From 5b0beb2c57e0f4ff9241fc31a5310f61f094464d Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 8 Feb 2022 00:55:18 -0500 Subject: [PATCH 14/80] bump c++ standard to 14 --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd1cdd5..2de4097 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,8 @@ endif() # CFLAGS SET(CMAKE_C_FLAGS "-std=gnu99 -pedantic -fPIC -pedantic -fopenmp -mtune=native") -SET(CMAKE_CXX_FLAGS "-std=c++11 -Wall -fPIC -pedantic -fopenmp -mtune=native") +SET(CMAKE_CXX_FLAGS "-std=c++14 -Wall -fPIC -pedantic -fopenmp -mtune=native") +set(CMAKE_CXX_STANDARD 14) ## Dependencies From addb6b46f43ce6715eea4b9d48cbe5a0d5636af0 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 8 Feb 2022 01:43:25 -0500 Subject: [PATCH 15/80] align with ROOT c++ standard --- CMakeLists.txt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2de4097..d9d4e22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,14 +8,27 @@ endif() # CFLAGS SET(CMAKE_C_FLAGS "-std=gnu99 -pedantic -fPIC -pedantic -fopenmp -mtune=native") -SET(CMAKE_CXX_FLAGS "-std=c++14 -Wall -fPIC -pedantic -fopenmp -mtune=native") -set(CMAKE_CXX_STANDARD 14) +SET(CMAKE_CXX_FLAGS "-Wall -fPIC -pedantic -fopenmp -mtune=native") ## Dependencies #---CERN ROOT (required) find_package(ROOT CONFIG REQUIRED) - +# we set the compiler version based on the one used for ROOT +execute_process( + COMMAND bash "-c" "root-config --features | awk '{print $1}'" + OUTPUT_VARIABLE ROOT_CXX_STANDARD ) +if (${ROOT_CXX_STANDARD} MATCHES "cxx17") + message("Using CXX17") + set(CMAKE_CXX_STANDARD 17) +elseif (${ROOT_CXX_STANDARD} MATCHES "cxx14") + message("Using CXX17") + set(CMAKE_CXX_STANDARD 14) +else () + message("Using CXX11") + set(CMAKE_CXX_STANDARD 11) +endif() + #---LArCV (required) set( larcv_DIR "$ENV{LARCV_LIBDIR}/cmake/larcv") find_package( larcv REQUIRED ) From 9ffa4468ea4a6461799145fbbdcb8b08c7b3a354 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 8 Feb 2022 01:57:57 -0500 Subject: [PATCH 16/80] fix up cxx standard msg --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9d4e22..ef9015b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,13 +19,13 @@ execute_process( COMMAND bash "-c" "root-config --features | awk '{print $1}'" OUTPUT_VARIABLE ROOT_CXX_STANDARD ) if (${ROOT_CXX_STANDARD} MATCHES "cxx17") - message("Using CXX17") + message( STATUS "using cxx17") set(CMAKE_CXX_STANDARD 17) elseif (${ROOT_CXX_STANDARD} MATCHES "cxx14") - message("Using CXX17") + message( STATUS "using cxx14") set(CMAKE_CXX_STANDARD 14) else () - message("Using CXX11") + message( STATUS "using cxx11") set(CMAKE_CXX_STANDARD 11) endif() From ca3c79efef05e9467fb3a5726314457a6fc07114 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 18 Feb 2022 21:12:56 -0500 Subject: [PATCH 17/80] use detprofile start for mcshower start points --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 8217a7e..d186817 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -181,14 +181,14 @@ namespace mctools { showernode.start.resize(4); showernode.aid = mcsh.AncestorTrackID(); showernode.mtid = mcsh.MotherTrackID(); - // showernode.start[0] = mcsh.DetProfile().X(); - // showernode.start[1] = mcsh.DetProfile().Y(); - // showernode.start[2] = mcsh.DetProfile().Z(); - // showernode.start[3] = mcsh.DetProfile().T(); - showernode.start[0] = mcsh.Start().X(); - showernode.start[1] = mcsh.Start().Y(); - showernode.start[2] = mcsh.Start().Z(); - showernode.start[3] = mcsh.Start().T(); + showernode.start[0] = mcsh.DetProfile().X(); + showernode.start[1] = mcsh.DetProfile().Y(); + showernode.start[2] = mcsh.DetProfile().Z(); + showernode.start[3] = mcsh.DetProfile().T(); + // showernode.start[0] = mcsh.Start().X(); + // showernode.start[1] = mcsh.Start().Y(); + // showernode.start[2] = mcsh.Start().Z(); + // showernode.start[3] = mcsh.Start().T(); _get_imgpos( showernode.start, showernode.imgpos4, sce ); //showernode.imgpos4 = showernode.start; //showernode.imgpos4[3] = 3200 + mcsh.DetProfile().X()/larutil::LArProperties::GetME()->DriftVelocity()/0.5; From a79893d56fcad494a8cfc9ddfd762a160df9be00 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 18 Feb 2022 22:34:02 -0500 Subject: [PATCH 18/80] fixed most of shower start point --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 27 +++++++++++++++++++-------- ublarcvapp/MCTools/MCPixelPGraph.h | 5 +++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index d186817..aa22dc4 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -189,7 +189,7 @@ namespace mctools { // showernode.start[1] = mcsh.Start().Y(); // showernode.start[2] = mcsh.Start().Z(); // showernode.start[3] = mcsh.Start().T(); - _get_imgpos( showernode.start, showernode.imgpos4, sce ); + _get_imgpos( showernode.start, showernode.imgpos4, sce, false ); //showernode.imgpos4 = showernode.start; //showernode.imgpos4[3] = 3200 + mcsh.DetProfile().X()/larutil::LArProperties::GetME()->DriftVelocity()/0.5; @@ -697,7 +697,8 @@ namespace mctools { */ void MCPixelPGraph::_get_imgpos( std::vector& realpos4, std::vector& imgpos4, - larutil::SpaceChargeMicroBooNE& sce ) + larutil::SpaceChargeMicroBooNE& sce, + bool apply_sce ) { imgpos4.resize(4,0); @@ -707,17 +708,27 @@ namespace mctools { for (int i=0; i<3; i++) { dpos[i] = realpos4[i]; } + + + std::vector txyz(4,0); + if ( apply_sce ) { + std::vector offset = sce.GetPosOffsets( dpos[0], dpos[1], dpos[2] ); + dpos[0] = dpos[0] - offset[0] + 0.7; + dpos[1] = dpos[1] + offset[1]; + dpos[2] = dpos[2] + offset[2]; + } + - std::vector offset = sce.GetPosOffsets( dpos[0], dpos[1], dpos[2] ); - std::vector txyz(4,0); - dpos[0] = dpos[0] - offset[0] + 0.7; - dpos[1] = dpos[1] + offset[1]; - dpos[2] = dpos[2] + offset[2]; for (int i=0; i<3; i++) { txyz[1+i] = realpos4[i]; } txyz[0] = realpos4[3]; - float tick = CrossingPointsAnaMethods::getTick( txyz, 4050.0, &sce ); + float tick = 0.; + if (apply_sce) + tick = CrossingPointsAnaMethods::getTick( txyz, 4050.0, &sce ); + else + tick = CrossingPointsAnaMethods::getTick( txyz, 4050.0, NULL ); + for (int i=0; i<3; i++) { imgpos4[i] = dpos[i]; } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 3c2280c..54e5ad9 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -140,8 +140,9 @@ namespace mctools { const std::vector threshold_v ); void _get_imgpos( std::vector& realpos4, std::vector& imgpos4, - larutil::SpaceChargeMicroBooNE& sce ); - + larutil::SpaceChargeMicroBooNE& sce, + bool apply_sce=true ); + public: std::map _shower_daughter2mother; From 0e2ebccf6bb7c78708c7911b581c6c715d129f47 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 21 Mar 2022 12:55:41 -0400 Subject: [PATCH 19/80] added features to trackimagemask --- CMakeLists.txt | 2 + ublarcvapp/LLCVProcessor/CMakeLists.txt | 7 +- ublarcvapp/MCTools/TruthTrackSCE.cxx | 12 +- ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx | 48 +++++- ublarcvapp/UBImageMod/EmptyChannelAlgo.h | 3 + ublarcvapp/UBImageMod/TrackImageMask.cxx | 164 ++++++++++++++++++--- ublarcvapp/UBImageMod/TrackImageMask.h | 25 +++- 7 files changed, 224 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef9015b..6dd086a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ endif() find_package(Eigen3 REQUIRED) #---LArLite +set( larlite_DIR $ENV{LARLITE_LIBDIR}/cmake/larlite ) +find_package( larlite REQUIRED ) set( LARLITE_INC_DIRS "$ENV{LARLITE_INCDIR}" ) set( LARLITE_LIB_DIR "$ENV{LARLITE_LIBDIR}" ) set( HAS_LARLITE 1 ) diff --git a/ublarcvapp/LLCVProcessor/CMakeLists.txt b/ublarcvapp/LLCVProcessor/CMakeLists.txt index 5f316a8..e81c030 100644 --- a/ublarcvapp/LLCVProcessor/CMakeLists.txt +++ b/ublarcvapp/LLCVProcessor/CMakeLists.txt @@ -20,7 +20,8 @@ set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") # DEFINE SOME VARS THAT MIGHT BE USEFUL FOR SUBMODULES # larlite includes -set(LARLITE_INCLUDES $ENV{LARLITE_BASEDIR} $ENV{LARLITE_USERDEVDIR} $ENV{LARLITE_COREDIR} $ENV{LARLITE_USERDEVDIR}/BasicTool ) +#set(LARLITE_INCLUDES $ENV{LARLITE_BASEDIR} $ENV{LARLITE_USERDEVDIR} $ENV{LARLITE_COREDIR} $ENV{LARLITE_USERDEVDIR}/BasicTool ) +message( STATUS ${LARLITE_INCLUDE_DIR} ) # larcv libs used set(LARCV_LIBS_USED LArCVCoreBase LArCVCoreDataFormat LArCVCoreCVUtil) @@ -38,13 +39,13 @@ target_include_directories(${LIBNAME} PUBLIC $ ${LARCV_INCLUDE_DIR} - ${LARLITE_INCLUDES} + ${LARLITE_INCLUDE_DIR} PRIVATE ${PROJECT_SOURCE_DIR} ) target_link_libraries(${LIBNAME} ${LARLITE_LIBS_USED} ${LARCV_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) -include_directories( ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME} ${LARCV_INCLUDE_DIR} ${LARLITE_INCLUDES} ) +include_directories( ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME} ${LARCV_INCLUDE_DIR} ${LARLITE_INCLUDE_DIR} ) ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) diff --git a/ublarcvapp/MCTools/TruthTrackSCE.cxx b/ublarcvapp/MCTools/TruthTrackSCE.cxx index 1350f7d..310141b 100644 --- a/ublarcvapp/MCTools/TruthTrackSCE.cxx +++ b/ublarcvapp/MCTools/TruthTrackSCE.cxx @@ -164,9 +164,15 @@ namespace mctools { const std::vector& pt ) { + if ( pt.size()<3 ) + throw std::runtime_error("TruthTrackSCE::pointLineDistance. test pt length < 3"); + if ( linept1.size()<3 ) + throw std::runtime_error("TruthTrackSCE::pointLineDistance. linept1 length < 3"); + if ( linept2.size()<3 ) + throw std::runtime_error("TruthTrackSCE::pointLineDistance. linept2 length < 3"); - std::vector d1(3); - std::vector d2(3); + std::vector d1(3,0); + std::vector d2(3,0); float len1 = 0.; float linelen = 0.; @@ -185,7 +191,7 @@ namespace mctools { } // cross-product - std::vector d1xd2(3); + std::vector d1xd2(3,0); d1xd2[0] = d1[1]*d2[2] - d1[2]*d2[1]; d1xd2[1] = -d1[0]*d2[2] + d1[2]*d2[0]; d1xd2[2] = d1[0]*d2[1] - d1[1]*d2[0]; diff --git a/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx b/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx index 41f7155..3cc7ed5 100644 --- a/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx +++ b/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx @@ -218,15 +218,53 @@ namespace ublarcvapp { empty_ch_max ); for (size_t p=0; p0 ) + badch.paint_col(c,255); } + + // auto& bchv = badch_v[p].as_mod_vector(); + // auto const& gv = gapch_v[p].as_vector(); + // for ( size_t i=0; i EmptyChannelAlgo::makeOverlayedBadChannelImage( const std::vector& img_v, + const larcv::EventChStatus& ev_status, int minstatus, + const float fill_in_value ) + { + + std::vector out_v; + for (auto const& img : img_v ) { + + larcv::Image2D out( img ); + auto const& meta = img.meta(); + int p = meta.plane(); + auto it_chstatus = ev_status.ChStatusMap().find( p ); + if ( it_chstatus!=ev_status.ChStatusMap().end() ) { + + const larcv::ChStatus& chs = ev_status.Status(p); + const std::vector& status_v = chs.as_vector(); + for ( int ch=0; ch<(int)status_v.size(); ch++) { + if ( ch=meta.max_x() ) + continue; + int status = status_v.at(ch); + if ( ch<(int)meta.cols() && status makeOverlayedBadChannelImage( const std::vector& img_v, + const larcv::EventChStatus& ev_status, int minstatus, + const float fill_in_value ); }; diff --git a/ublarcvapp/UBImageMod/TrackImageMask.cxx b/ublarcvapp/UBImageMod/TrackImageMask.cxx index 79b637d..3b55f89 100644 --- a/ublarcvapp/UBImageMod/TrackImageMask.cxx +++ b/ublarcvapp/UBImageMod/TrackImageMask.cxx @@ -13,8 +13,22 @@ namespace ubimagemod { { pixel_v.clear(); pixel_map.clear(); + pixel_kernel_pixval_v.clear(); + nmaskedpixels = 0; + npathpixels = 0; } - + + /** + * @brief Mask pixels in an image along the path of a 3D trajectory + * + * @param[in] track Path represented as sequence of line segments + * @param[in] img Original image, containing wire signal + * @param[out] mask Image whose pixels we mask + * @param[in] threshold + * @param[in] dcol Width of rectangular masking kernel + * @param[in] drow Height of rectangular masking kernel + * @param[in] maxstepsize Maximum step we take along the line segment path (in cm) + */ int TrackImageMask::maskTrack( const larlite::track& track, const larcv::Image2D& img, larcv::Image2D& mask, @@ -23,9 +37,14 @@ namespace ubimagemod { const int drow, const float maxstepsize ) { - + // clear clear(); + + int N = (2*dcol+1)*(2*drow+1); // number of elements in kernel + kernel_dcol = dcol; + kernel_drow = drow; + kernel_N = N; int npts = track.NumberTrajectoryPoints(); LARCV_DEBUG() << "start: track length=" << npts << std::endl; @@ -38,7 +57,7 @@ namespace ubimagemod { auto const& meta = img.meta(); - int npixels = makePixelList( track, img, threshold, maxstepsize, false ); + int npixels = makePixelList( track, img, 0.0, maxstepsize, true ); LARCV_DEBUG() << "Number of pixels: " << pixel_v.size() << std::endl; if ( npixels==0 ) return 0; @@ -65,6 +84,7 @@ namespace ubimagemod { // make data array std::vector crop(colwidth*rowwidth,0); std::vector cropmask(colwidth*rowwidth,0); + std::vector cropmask_threshold(colwidth*rowwidth,0); // copy the data into the cropped matrix // preserve the row-ordered data @@ -78,11 +98,12 @@ namespace ubimagemod { // kernal loop, making mask // trying to write in a way that is easy to accelerate - int N = (2*dcol+1)*(2*drow+1); // number of elements in kernel // parallelize masking with block kernel - int nmasked = 0; - std::chrono::steady_clock::time_point start_mask = std::chrono::steady_clock::now(); + nmaskedpixels = 0; + std::chrono::steady_clock::time_point start_mask = std::chrono::steady_clock::now(); + + pixel_kernel_pixval_v.resize( pixel_v.size()*N, 0.0 ); #pragma omp parallel for for (int ikernel=0; ikernelthreshold ) { #pragma omp atomic - cropmask[ cropindex ] += 1.0; - } + cropmask_threshold[ cropindex ] += 1.0; + } + #pragma omp atomic + cropmask[ cropindex ] += 1.0; + + pixel_kernel_pixval_v[ N*itp + ikernel ] = pixval; } } #pragma omp barrier for (size_t ii=0; ii0 ) { - nmasked++; - cropmask[ii] = 1.0; + if ( cropmask_threshold[ii]>0 ) { + nmaskedpixels++; + cropmask_threshold[ii] = 1.0; int orig_row = (ii%rowwidth)-drow + row_origin; int orig_col = (ii/rowwidth)-dcol + col_origin; mask.set_pixel( orig_row, orig_col, 1.0 ); } + if ( cropmask[ii]>0 ) { + npathpixels++; + cropmask[ii] = 1.0; + } } - LARCV_INFO() << "num pixels masked: " << nmasked << std::endl; + LARCV_INFO() << "num pixels masked: " << nmaskedpixels << " out of num pixels on path (with kernel): " << npathpixels << std::endl; std::chrono::steady_clock::time_point end_mask = std::chrono::steady_clock::now(); if ( show_timing ) LARCV_INFO() << "mask: " << std::chrono::duration_cast(end_mask - start_mask).count() << std::endl; - return nmasked; + return nmaskedpixels; } /** @@ -168,6 +198,17 @@ namespace ubimagemod { return nlabeled; } + /** + * @brief Provide a list of pixels we travel through while stepping along a track + * + * The list of pixels are stored in the internal data member, `pixel_v`. + * + * @param[in] track Path we step along represented as sequence of line segments + * @param[in] img 2D image containing wire signals + * @param[in] threshold + * @param[in] maxstepsize Maximum step we take along the line segment path + * @param[in] fill_map If true, we fill the pixel_map data member + */ int TrackImageMask::makePixelList( const larlite::track& track, const larcv::Image2D& img, const float threshold, @@ -177,6 +218,11 @@ namespace ubimagemod { pixel_v.clear(); pixel_map.clear(); + auto const& meta = img.meta(); + min_col = (int)meta.cols()-1; + min_row = (int)meta.rows()-1; + max_col = 0; + max_row = 0; if ( maxstepsize<0 || std::isnan(maxstepsize) || std::isinf(maxstepsize) ) { LARCV_CRITICAL() << "Bad maxstepsize value: " << maxstepsize << std::endl; @@ -194,7 +240,6 @@ namespace ubimagemod { const float driftv = larutil::LArProperties::GetME()->DriftVelocity(); const float usec_per_tick = 0.5; - auto const& meta = img.meta(); int plane = meta.plane(); if ( plane<0 || plane>=(int)larutil::Geometry::GetME()->Nplanes() ) { LARCV_WARNING() << "Invalid plane: " << plane << std::endl; @@ -210,14 +255,13 @@ namespace ubimagemod { int nrows = meta.rows(); int ncols = meta.cols(); - min_col = (int)meta.cols()-1; - min_row = (int)meta.rows()-1; - max_col = 0; - max_row = 0; - std::set< std::pair > pixel_set; pixel_v.reserve( 2*npts ); + std::pair last_coord; + last_coord.first = 0; + last_coord.second = 0; + float len_traveled = 0.; for (int ipt=0; ipt pixcoord(col,row); + bool newpix = (pixcoord!=last_coord); if ( fill_map ) { auto it = pixel_map.find( pixcoord ); if ( it==pixel_map.end() ) { // new entry - pixel_map[pixcoord] = Pix_t( col, row, s, s ); + pixel_map[pixcoord] = Pix_t( col, row, s, s, pixval ); pixel_v.push_back( std::vector{col,row} ); it = pixel_map.find( pixcoord ); } it->second.smax = s; + + if (newpix) { + auto it_old = pixel_map.find(last_coord); + if ( it_old!=pixel_map.end() ) { + it_old->second.smax = s; + } + last_coord = pixcoord; + } } else { auto it = pixel_set.find( pixcoord ); @@ -540,6 +593,75 @@ namespace ubimagemod { return true; } + + /** + * @brief Find the largest continous distance along path without charge + * + * Uses the list of pixels are stored in the internal data member, `pixel_v`. + * Also uses the charge seen at each spot of the kernel for each pixel in pixel_v. + * This info is stored in `pixel_kernel_pixval_v`. + * Both are created in `maskTrack`. If this was not run, should return 0. + */ + float TrackImageMask::getMaximumChargeGap( std::vector< std::vector >& gap_points ) const + { + float current_gapsize = 0.; + float max_gapsize = 0.; + + gap_points.resize(2); + for (int i=0; i<2; i++) { + gap_points[i].resize(2,0); + } + + for (size_t ipix=0; ipix( pixcoord[0], pixcoord[1] ) ); + auto const& pix = it->second; + + if ( totq>0.0 ) { + // not a gap, reset the gap + if ( current_gapsize>max_gapsize ) { + max_gapsize = current_gapsize; + // set the last gap point + std::vector gap_coord = { (float)pix.col, (float)pix.row }; + gap_points[1] = gap_coord; + } + + current_gapsize = 0; + + } + else { + + if ( current_gapsize==0.0 ) { + // set first gap points + std::vector gap_coord = { (float)pix.col, (float)pix.row }; + gap_points[0] = gap_coord; + } + + current_gapsize += pix.smax-pix.smin; + if ( ipix+1==pixel_v.size() ) { + // the last pixel + if ( current_gapsize>max_gapsize ) { + max_gapsize = current_gapsize; + // set the last gap point + std::vector gap_coord = { (float)pix.col, (float)pix.row }; + gap_points[1] = gap_coord; + } + } + } + // std::cout << "ipix[" << ipix << "]: (c,r)=(" << pix.col << "," << pix.row << ")" + // << " pixval=" << pix.pixval + // << " smin=" << pix.smin << " smax=" << pix.smax + // << " totq=" << totq << " current_gap=" << current_gapsize + // << std::endl; + } + + return max_gapsize; + } } } diff --git a/ublarcvapp/UBImageMod/TrackImageMask.h b/ublarcvapp/UBImageMod/TrackImageMask.h index 5370fbe..d9e5a98 100644 --- a/ublarcvapp/UBImageMod/TrackImageMask.h +++ b/ublarcvapp/UBImageMod/TrackImageMask.h @@ -20,6 +20,10 @@ namespace ubimagemod { max_row(0), show_timing(false) {}; + ~TrackImageMask() + { + clear(); + } void clear(); @@ -58,6 +62,10 @@ namespace ubimagemod { const float thresh, float& pixval_min, float& pixval_max ) const; + + float getMaximumChargeGap( std::vector< std::vector >& gap_points ) const; + int getMaskedPixels() const { return nmaskedpixels; }; + int getPathPixels() const { return npathpixels; }; // first we make a list of pixels covered by the track @@ -67,21 +75,28 @@ namespace ubimagemod { int row; float smin; float smax; + float pixval; Pix_t() - : col(0),row(0),smin(0),smax(0) + : col(0),row(0),smin(0),smax(0),pixval(0) {}; - Pix_t( int c, int r, float ssmin, float ssmax ) - : col(c), row(r), smin(ssmin), smax(ssmax) + Pix_t( int c, int r, float ssmin, float ssmax,float pv ) + : col(c), row(r), smin(ssmin), smax(ssmax),pixval(pv) {}; }; // output data members for use std::map< std::pair, Pix_t > pixel_map; ///< map of pixel (col,row) to Pix_t struct - std::vector< std::vector > pixel_v; ///< list of (col,row) pixels that follows path of tracko + std::vector< std::vector > pixel_v; ///< list of (col,row) pixels that follows path of track + std::vector< float > pixel_kernel_pixval_v; ///< list of charge values within the kernel for each pixel int min_col; int min_row; int max_col; - int max_row; + int max_row; + int kernel_dcol; + int kernel_drow; + int kernel_N; + int nmaskedpixels; + int npathpixels; bool show_timing; ///< set to true to print output }; From ee179801e8273f956f6259ed419826b20642b763 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Mon, 21 Mar 2022 13:04:05 -0400 Subject: [PATCH 20/80] small changes to build on cluster --- CMakeLists.txt | 4 ++-- ublarcvapp/DLTagger/CMakeLists.txt | 3 ++- ublarcvapp/MCTools/LArbysMC.cxx | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dd086a..fb77c86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,10 +99,10 @@ if (Boost_FOUND) message(STATUS "Using boost libraries: ${Boost_LIBRARIES}") message(STATUS "Using boost thread library: ${Boost_THREAD_LIBRARY}") link_directories(${Boost_LIBRARY_DIRS}) +else() + message(STATUS "Boost not found") endif (Boost_FOUND) -#INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} ) - #--- glog #find_package(glog REQUIRED) diff --git a/ublarcvapp/DLTagger/CMakeLists.txt b/ublarcvapp/DLTagger/CMakeLists.txt index 43be887..b4b9826 100644 --- a/ublarcvapp/DLTagger/CMakeLists.txt +++ b/ublarcvapp/DLTagger/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory( mrcnnmatch ) message("headers: ${HEADERS}") message("project source dir: ${PROJECT_SOURCE_DIR}") message("eigen3: ${EIGEN3_INCLUDE_DIRS}") +message("boost include dir: ${Boost_INCLUDE_DIRS}") get_target_property(ALL_HEADERS ${LIBNAME} PUBLIC_HEADER) @@ -57,7 +58,7 @@ target_include_directories(${LIBNAME} ) target_link_libraries(${LIBNAME} ${LARLITE_LIBS_USED} ${LARCV_LIBS_USED} ${UBLARCVAPP_LIBS_USED} ${LAROPENCV_LIBS} ${GEO2D_LIBS} opencv_core) -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/mrcnnmatch ${LARCV_INCLUDE_DIR} ${LARLITE_INCLUDES} $ENV{CILANTRO_INC_DIR} ${EIGEN3_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS} ) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/mrcnnmatch ${LARCV_INCLUDE_DIR} ${LARLITE_INCLUDES} $ENV{CILANTRO_INC_DIR} ${EIGEN3_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ) ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${ALL_HEADERS} LINKDEF LinkDef.h) target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) diff --git a/ublarcvapp/MCTools/LArbysMC.cxx b/ublarcvapp/MCTools/LArbysMC.cxx index a57a2d5..3a95f71 100644 --- a/ublarcvapp/MCTools/LArbysMC.cxx +++ b/ublarcvapp/MCTools/LArbysMC.cxx @@ -137,6 +137,13 @@ namespace mctools { _event = mgr.event_id(); _entry = (int)mgr.get_index(); + // no truth? + if ( ev_mctruth->size()==0 ) { + if ( _mc_tree ) + _mc_tree->Fill(); + return false; + } + // If we've got a neutrino, sample that auto const& mct = ev_mctruth->at(0); _neutrino_present = mct.Origin()==larlite::simb::kBeamNeutrino; From c4ab30b54e99cc639d1c761beec36e3e4344524f Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Thu, 14 Apr 2022 11:37:25 -0400 Subject: [PATCH 21/80] latest flashmatcher save --- ublarcvapp/MCTools/FlashMatcher.cxx | 53 +++++++++++++++++++++++++++++ ublarcvapp/MCTools/FlashMatcher.h | 9 +++++ 2 files changed, 62 insertions(+) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index af04043..18944b0 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -31,6 +31,7 @@ namespace mctools { fm_tree->Branch("flashmatcher_subrun", &_subrun, "flashmatcher_subrun/I"); fm_tree->Branch("flashmatcher_event", &_event, "flashmatcher_event/I"); fm_tree->Branch("flashmatcher_ancestorid" , &_ancestorID, "flashmatcher_ancestorid/I"); + //fm_tree->Branch("flashmatcher_trackid" , &_trackID, "flashmatcher_trackid/I"); fm_tree->Branch("flashmatcher_clustertick" , &_clusterTick, "flashmatcher_clustertick/D"); fm_tree->Branch("flashmatcher_flashtick" , &_flashTick, "flashmatcher_flashtick/D"); fm_tree->Branch("flashmatcher_origin" , &_origin, "flashmatcher_origin/I"); @@ -46,6 +47,7 @@ namespace mctools { _subrun = mgr.subrun_id(); _event = mgr.event_id(); _ancestorID = ancestorID; + //_trackID = trackID; _clusterTick = clusterTick; _flashTick = flashTick; _origin = origin; @@ -69,6 +71,7 @@ namespace mctools { _subrun = 0; _event = 0; _ancestorID = 0; + //_trackID = 0; _clusterTick = 0; _flashTick = 0; _origin = 0; @@ -84,6 +87,55 @@ namespace mctools { return numTracks; } +/* + int FlashMatcher::trackAncestorID( larlite::storage_manager& ioll, int i ) { + + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + + auto const& mctrack = ev_mctrack->at(i); + + auto ancestorID = mctrack.AncestorTrackID(); + + return ancestorID; + + } + */ + + int FlashMatcher::trackAncestorID() { + + if (!ancestorID) + return -999; + + return ancestorID; + + } + + int FlashMatcher::getTrackID() { + + if (!trackID) + return -999; + + return trackID; + + } + + int FlashMatcher::trackOrigin() { + + if (!origin) + return -999; + + return origin; + + } + +/* + int FlashMatcher::trackOrigin( larlite::storage_manager& ioll, int i ) { + + + } + */ + int FlashMatcher::numShowers( larlite::storage_manager& ioll ) { larlite::event_mcshower* ev_mcshower @@ -140,6 +192,7 @@ namespace mctools { std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; + trackID = mctrack.TrackID(); ancestorID = mctrack.AncestorTrackID(); return tick; diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index 3d26551..cd5b812 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -33,6 +33,13 @@ namespace mctools { void Clear(); int numTracks( larlite::storage_manager& ioll ); + //int trackAncestorID( larlite::storage_manager& ioll, int i ); + + // Getters for meta information + int trackAncestorID(); + int getTrackID(); + int trackOrigin(); + int numShowers( larlite::storage_manager& ioll ); double grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); double grabTickFromMCShower( larlite::storage_manager& ioll, int i ); @@ -54,12 +61,14 @@ namespace mctools { int _subrun; int _event; int _ancestorID; + //int _trackID; double _clusterTick; double _flashTick; int _origin; // Vars not in tree but in loop int ancestorID; + int trackID; double clusterTick; double flashTick; int origin; From 1348746876411c4047e5d2c01a074da150651c79 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sun, 24 Apr 2022 16:27:23 -0400 Subject: [PATCH 22/80] made sure to properly initialize node_t variables --- ublarcvapp/MCTools/MCPixelPGraph.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 54e5ad9..1f7668a 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -74,19 +74,27 @@ namespace mctools { vidx(-1), tid(-1), aid(-1), + mtid(-1), pid(-1), mother(nullptr), mid(-1), E_MeV(-1.0), start({0,0,0}), + imgpos4({0,0,0,0}), origin(-1) {}; - Node_t(int _nodeidx, int _type, int _tid, int _vidx, int _pid, Node_t* _mother=nullptr, int _mid=-1, float _energy=-1.0 ) + Node_t(int _nodeidx, int _type, int _tid, int _vidx, + int _pid, + Node_t* _mother=nullptr, + int _mid=-1, + float _energy=-1.0 ) : nodeidx(_nodeidx), type(_type), vidx(_vidx), tid(_tid), + aid(-1), + mtid(-1), pid(_pid), mother(_mother), mid(_mid), From c9f2470b5466610bcf9678bca5bca3ef899f32bd Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 26 Apr 2022 02:05:02 -0400 Subject: [PATCH 23/80] add ancestor ids. add initializations --- ublarcvapp/MCTools/LArbysMC.cxx | 11 ++++++++--- ublarcvapp/MCTools/MCPixelPGraph.cxx | 5 ++++- ublarcvapp/MCTools/MCPixelPGraph.h | 6 +++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ublarcvapp/MCTools/LArbysMC.cxx b/ublarcvapp/MCTools/LArbysMC.cxx index 3a95f71..b9027d9 100644 --- a/ublarcvapp/MCTools/LArbysMC.cxx +++ b/ublarcvapp/MCTools/LArbysMC.cxx @@ -31,7 +31,7 @@ namespace mctools { _producer_wireimage = "wire"; _psce = new larutil::SpaceChargeMicroBooNE(); for (int p=0; p<3; p++) _plane_vtx_pixsum[p] = 0.; - + Clear(); } @@ -138,6 +138,7 @@ namespace mctools { _entry = (int)mgr.get_index(); // no truth? + _neutrino_present = false; if ( ev_mctruth->size()==0 ) { if ( _mc_tree ) _mc_tree->Fill(); @@ -478,6 +479,8 @@ namespace mctools { _genie_mode = -1; _nu_pdg = 0; + _Enu_true = 0.; + _vtx_t = 0; _vtx_x = _vtx_y = _vtx_z = 0.; _vtx_sce_x = _vtx_sce_y = _vtx_sce_z = 0.; _vtx_detx = 0; @@ -494,17 +497,19 @@ namespace mctools { _evis_had = 0.; _evis_vtx =0.; _evis_lep = 0; - _hi_lep_pdg = 0.; + _hi_lep_pdg = 0; + _hi_lep_e = 0.; _nprimary = 0; + _ntotal = 0; _nproton = 0; _nproton_60mev = 0; _nlepton =0; _nlepton_35mev = 0; _nmeson = 0; _nmeson_35mev = 0; + _npi0 = 0; _nshower = 0; _nneutron = 0; - _npi0 =0; _1l1p0pi = 0; _1l0p0pi = 0; diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index aa22dc4..ee63d2f 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -143,7 +143,8 @@ namespace mctools { Node_t tracknode( node_v.size(), 0, mct.TrackID(), vidx, mct.PdgCode() ); tracknode.E_MeV = mct.Start().E(); tracknode.aid = mct.AncestorTrackID(); - tracknode.mtid = mct.MotherTrackID(); + tracknode.mtid = mct.MotherTrackID(); + tracknode.process = mct.Process(); if ( mct.PdgCode()==2212 ) tracknode.E_MeV -= 938.0; else if ( mct.PdgCode()==2112 ) tracknode.E_MeV -= 940.0; else if ( abs(mct.PdgCode())==13 ) tracknode.E_MeV -= 105.; @@ -177,6 +178,7 @@ namespace mctools { Node_t showernode( node_v.size(), 1, mcsh.TrackID(), vidx, mcsh.PdgCode() ); showernode.E_MeV = mcsh.Start().E(); + showernode.process = mcsh.Process(); showernode.origin = mcsh.Origin(); showernode.start.resize(4); showernode.aid = mcsh.AncestorTrackID(); @@ -319,6 +321,7 @@ namespace mctools { ss << "node[" << node.nodeidx << "] " << " (type,vidx)=(" << node.type << "," << node.vidx << ") " << " origin=" << node.origin + << " p=" << node.process << " tid=" << node.tid << " mid=" << node.mtid << " aid=" << node.aid diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 1f7668a..a49b86c 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -60,6 +60,7 @@ namespace mctools { Node_t* mother; // pointer to Mother Node_t int mid; // mother nodeidx float E_MeV; // energy + std::string process; // creating process std::vector daughter_idx_v; // daughter node indices in node_v std::vector daughter_v; // pointer to daughters std::vector< std::vector > pix_vv; // pixels in each plane. pixels stored in (tick,wire) coordinates @@ -79,6 +80,7 @@ namespace mctools { mother(nullptr), mid(-1), E_MeV(-1.0), + process("null"), start({0,0,0}), imgpos4({0,0,0,0}), origin(-1) @@ -88,7 +90,8 @@ namespace mctools { int _pid, Node_t* _mother=nullptr, int _mid=-1, - float _energy=-1.0 ) + float _energy=-1.0, + std::string proc="null") : nodeidx(_nodeidx), type(_type), vidx(_vidx), @@ -99,6 +102,7 @@ namespace mctools { mother(_mother), mid(_mid), E_MeV(_energy), + process(proc), start({0,0,0,0}), imgpos4({0,0,0,0}), origin(-1) From dcddcd58260cbdd9986a4fdaf5ee982836efa997 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Mon, 16 May 2022 15:44:31 -0400 Subject: [PATCH 24/80] grabs position of first mcstep in detector, rather than cosmic origin --- ublarcvapp/MCTools/FlashMatcher.cxx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 18944b0..fabcc85 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -175,16 +175,32 @@ namespace mctools { isCosmic = 1; } - const larlite::mcstep& start = mctrack.Start(); + std::cout << "mctrack.size() = " << mctrack.size() << std::endl; + + if ( mctrack.size() == 0 ) { + std::cout << "Empty vector of mcsteps (probably a cosmic that didn't cross the TPC)" << std::endl; + return -999.998; + } + + //const larlite::mcstep& start = mctrack.Start(); + const larlite::mcstep& start = mctrack.at(0); + + std::cout << "First mcstep X positiom is " << start.X() << " while the track started at: " << mctrack.Start().X() << std::endl; larutil::SpaceChargeMicroBooNE* _sce = nullptr; const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; double xPos = start.X(); + double xPos2 = mctrack.Start().X(); double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); tick = tick - xPos / cm_per_tick; + double tick2 = CrossingPointsAnaMethods::getTick(mctrack.Start(), 4050.0, _sce); + tick2 = tick2 - xPos2 / cm_per_tick; + + std::cout << "Tick for first mcstep in TPC: " << tick << " and tick for starting up in the sky: " << tick2 << std::endl; + // check for primaries if ( mctrack.TrackID() != mctrack.MotherTrackID() ) { return -999.997; From 383ce3b908ae7c43f2e74cec38907dd2e2233c1c Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Thu, 19 May 2022 19:18:09 -0400 Subject: [PATCH 25/80] changes to grab pair with opflash tick and index in ev_opflash --- ublarcvapp/MCTools/FlashMatcher.cxx | 42 ++++++++++++++++++++--------- ublarcvapp/MCTools/FlashMatcher.h | 6 +++-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index fabcc85..6d75678 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -268,22 +268,40 @@ namespace mctools { * @param[in] producer String labeling the producer, e.g. "simpleFlashBeam" * @return Vector containing all opflash times for the track in ticks */ - std::vector FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio ) { + std::vector< std::pair > FlashMatcher::grabTickFromOpflash( larlite::storage_manager& opio ) { - std::vector tickContainer = {}; + std::vector< std::pair > tickContainer; larlite::event_opflash* ev_opflash = (larlite::event_opflash*)opio.get_data(larlite::data::kOpFlash, producer); + int counter = 0; + for (auto const& opflash : *ev_opflash) { double time = opflash.Time(); //std::cout << time << std::endl; double tick = time/0.5 + 3200.0; - tickContainer.push_back(tick); + tickContainer.push_back(std::make_pair(tick,counter)); + counter++; } + std::cout << "Element\t" << "index" << std::endl; + for (int i = 0; i < tickContainer.size(); i++) { + std::cout << tickContainer[i].first << "\t" + << tickContainer[i].second << std::endl; + } + //std::cout << "Tick container: " << tickContainer << std::endl; + std::sort( tickContainer.begin(), tickContainer.end() ); + std::cout << "Element\t" + << "index" << std::endl; + for (int i = 0; i < tickContainer.size(); i++) { + std::cout << tickContainer[i].first << "\t" + << tickContainer[i].second << std::endl; + } + //std::cout << "Tick container: " << tickContainer << std::endl; + return tickContainer; } @@ -298,7 +316,7 @@ namespace mctools { * * @return Value of the closest matching opflash tick */ - double FlashMatcher::matchTicks( double mctrackTick, std::vector flashTicks ) { +std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector< std::pair > flashTicks ) { double threshold; if (isCosmic == 1) { @@ -310,33 +328,33 @@ namespace mctools { if (flashTicks.empty() == 1) { clusterTick = mctrackTick; flashTick = 999.999; - return 999.999; + return std::make_pair(999.999,999); } - auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), mctrackTick ); - double b = *(match); + auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), std::make_pair( mctrackTick, std::numeric_limits::min()) ); + double b = (*(match)).first; if (match == flashTicks.begin() && fabs(b - mctrackTick) <= threshold) { clusterTick = mctrackTick; - flashTick = flashTicks[0]; + flashTick = flashTicks[0].first; return flashTicks[0]; } - double a = *(match - 1); + double a = (*(match - 1)).first; if (fabs(mctrackTick - a) < fabs(mctrackTick - b) && fabs(mctrackTick - a) <= threshold) { clusterTick = mctrackTick; - flashTick = flashTicks [ match - flashTicks.begin() - 1 ]; + flashTick = flashTicks [ match - flashTicks.begin() - 1 ].first; return flashTicks [ match - flashTicks.begin() - 1 ]; } if ( fabs(mctrackTick - b) <= threshold ) { clusterTick = mctrackTick; - flashTick = flashTicks[ match - flashTicks.begin() ]; + flashTick = flashTicks[ match - flashTicks.begin() ].first; return flashTicks[ match - flashTicks.begin() ]; } - return -999.999; + return std::make_pair(-999.999,999); } diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index cd5b812..bed024f 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -9,6 +9,7 @@ #include "larlite/DataFormat/storage_manager.h" #include "TTree.h" +#include namespace ublarcvapp { namespace mctools { @@ -43,8 +44,9 @@ namespace mctools { int numShowers( larlite::storage_manager& ioll ); double grabTickFromMCTrack( larlite::storage_manager& ioll, int i ); double grabTickFromMCShower( larlite::storage_manager& ioll, int i ); - std::vector grabTickFromOpflash( larlite::storage_manager& opio ); - double matchTicks( double mctrack_tick, std::vector flash_ticks ); + std::vector< std::pair > grabTickFromOpflash( larlite::storage_manager& opio ); + //std::vector, std::vector> grabTickFromOpflash( larlite::storage_manager& opio ); + std::pair matchTicks( double mctrack_tick, std::vector< std::pair > flash_ticks ); Bool_t isCosmic; std::string producer; From 1f9ff9fb462f923eff8be0947baa23ecc62ba649 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Thu, 26 May 2022 23:16:08 -0400 Subject: [PATCH 26/80] grab ID for showers as well --- ublarcvapp/MCTools/FlashMatcher.cxx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 6d75678..707fb2c 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -256,6 +256,9 @@ namespace mctools { std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; + trackID = mcshower.TrackID(); + ancestorID = mcshower.AncestorTrackID(); + return tick; @@ -285,7 +288,7 @@ namespace mctools { counter++; } - std::cout << "Element\t" << "index" << std::endl; + std::cout << "Before sort: " << std::endl; for (int i = 0; i < tickContainer.size(); i++) { std::cout << tickContainer[i].first << "\t" << tickContainer[i].second << std::endl; @@ -294,8 +297,7 @@ namespace mctools { std::sort( tickContainer.begin(), tickContainer.end() ); - std::cout << "Element\t" - << "index" << std::endl; + std::cout << "After sort: " << std::endl; for (int i = 0; i < tickContainer.size(); i++) { std::cout << tickContainer[i].first << "\t" << tickContainer[i].second << std::endl; @@ -316,7 +318,7 @@ namespace mctools { * * @return Value of the closest matching opflash tick */ -std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector< std::pair > flashTicks ) { +std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector< std::pair > flashTicks ) { double threshold; if (isCosmic == 1) { @@ -334,6 +336,10 @@ std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), std::make_pair( mctrackTick, std::numeric_limits::min()) ); double b = (*(match)).first; + //std::cout << "match [iterator] is: " << match << std::endl; + //std::cout << "*match [dereferenced iterator, shoudl be a pair] is: " << (*(match)) << std::endl; + std::cout << "(*(match)).first [actual value of the tick] is: " << b << std::endl; + if (match == flashTicks.begin() && fabs(b - mctrackTick) <= threshold) { clusterTick = mctrackTick; flashTick = flashTicks[0].first; From 10acd22b22b2103bf3b7a72aaf53787c29e8a576 Mon Sep 17 00:00:00 2001 From: Matthew Rosenberg Date: Thu, 13 Oct 2022 04:16:14 -0400 Subject: [PATCH 27/80] added MCPixelPMap class to MCTools to return a simulated particle type for an input occupied pixel --- ublarcvapp/MCTools/CMakeLists.txt | 6 ++- ublarcvapp/MCTools/MCPixelPMap.cxx | 64 ++++++++++++++++++++++++++++ ublarcvapp/MCTools/MCPixelPMap.h | 68 ++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 ublarcvapp/MCTools/MCPixelPMap.cxx create mode 100644 ublarcvapp/MCTools/MCPixelPMap.h diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index c2ddbd2..a193fd0 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -11,7 +11,8 @@ set( HEADERS MCPixelPGraph.h NeutrinoVertex.h LArbysMC.h NeutrinoPixelFilter.h - FlashMatcher.h ) + FlashMatcher.h + MCPixelPMap.h ) # Add sources add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx @@ -21,7 +22,8 @@ add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx NeutrinoVertex.cxx LArbysMC.cxx NeutrinoPixelFilter.cxx - FlashMatcher.cxx ) + FlashMatcher.cxx + MCPixelPMap.cxx ) # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) diff --git a/ublarcvapp/MCTools/MCPixelPMap.cxx b/ublarcvapp/MCTools/MCPixelPMap.cxx new file mode 100644 index 0000000..4d5ac51 --- /dev/null +++ b/ublarcvapp/MCTools/MCPixelPMap.cxx @@ -0,0 +1,64 @@ + +#include "MCPixelPMap.h" + +#include "larcv/core/DataFormat/EventImage2D.h" + + +namespace ublarcvapp { +namespace mctools { + + void MCPixelPMap::buildmap( larcv::IOManager& iolcv, larlite::storage_manager& ioll ){ + ublarcvapp::mctools::MCPixelPGraph mcpg; + mcpg.set_adc_treename(adc_tree); + mcpg.buildgraph(iolcv, ioll); + buildmap(iolcv, mcpg); + } + + void MCPixelPMap::buildmap( larcv::IOManager& iolcv, ublarcvapp::mctools::MCPixelPGraph& pixGraph ){ + + larcv::EventImage2D* ev_adc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, adc_tree ); + const auto& adc_v = ev_adc->Image2DArray(); + + for( const auto& node: pixGraph.node_v ){ + for( size_t p=0; p < adc_v.size(); p++ ){ + for( unsigned int iP = 0; iP < node.pix_vv[p].size()/2; iP++ ) { + int row = (node.pix_vv[p][2*iP] - 2400)/6; + int col = node.pix_vv[p][2*iP+1]; + PixLoc_t pixLoc( (int)p, row, col ); + PixCont_t pixCont( node.pid, adc_v[p].pixel(row, col) ); + if(pixMap.count(pixLoc) == 0){ + std::vector pixCont_v{pixCont}; + pixMap.at(pixLoc) = pixCont_v; + } + else{ pixMap[pixLoc].push_back(pixCont); } + } + } + } + + } + + std::vector MCPixelPMap::getPixContent(int plane, int row, int col){ + PixLoc_t pixLoc(plane, row, col); + if(pixMap.count(pixLoc) > 0){ return pixMap.at(pixLoc); } + else{ + std::vector pixCont_v; + return pixCont_v; + } + } + + MCPixelPMap::PixCont_t MCPixelPMap::getPixParticle(int plane, int row, int col){ + auto pixCont_v = getPixContent(plane, row, col); + PixCont_t maxPartPixCont; + for(const auto& pixCont: pixCont_v){ + if(pixCont > maxPartPixCont) maxPartPixCont = pixCont; + } + return maxPartPixCont; + } + + int MCPixelPMap::getPixParticlePDG(int plane, int row, int col){ + return getPixParticle(plane, row, col).pdg; + } + +} +} + diff --git a/ublarcvapp/MCTools/MCPixelPMap.h b/ublarcvapp/MCTools/MCPixelPMap.h new file mode 100644 index 0000000..456d9a7 --- /dev/null +++ b/ublarcvapp/MCTools/MCPixelPMap.h @@ -0,0 +1,68 @@ +#ifndef __MCPIXELPDICT_H__ +#define __MCPIXELPDICT_H__ + +#include +#include +#include + +#include "larcv/core/Base/larcv_base.h" +#include "larcv/core/DataFormat/IOManager.h" +#include "larlite/DataFormat/storage_manager.h" +#include "MCPixelPGraph.h" + +namespace ublarcvapp { +namespace mctools { + + class MCPixelPMap : public larcv::larcv_base { + + public: + + MCPixelPMap() : larcv::larcv_base("MCPixelPMap"), adc_tree("wire") {}; + virtual ~MCPixelPMap() {}; + + struct PixLoc_t { + int plane, row, col; + PixLoc_t() : plane(-1), row(-1), col(-1) {}; + PixLoc_t(int _plane, int _row, int _col) : plane(_plane), row(_row), col(_col) {}; + bool operator==( const PixLoc_t& rhs ) const { + if(plane == rhs.plane && row == rhs.row && col == rhs.col) return true; + return false; + }; + bool operator<( const PixLoc_t& rhs ) const { + if(plane < rhs.plane) return true; + if(plane > rhs.plane) return false; + if(row < rhs.row) return true; + if(row > rhs.row) return false; + if(col < rhs.col) return true; + return false; + } + }; + + struct PixCont_t { + int pdg; + float pixI; + PixCont_t() : pdg(0), pixI(0.) {}; + PixCont_t(int _pdg, float _pixI) : pdg(_pdg), pixI(_pixI) {}; + bool operator>(const PixCont_t& rhs) const { + if(pixI > rhs.pixI) return true; + return false; + } + }; + + void buildmap( larcv::IOManager& iolcv, larlite::storage_manager& ioll ); + void buildmap( larcv::IOManager& iolcv, ublarcvapp::mctools::MCPixelPGraph& pixGraph ); + + std::vector getPixContent(int plane, int row, int col); + PixCont_t getPixParticle(int plane, int row, int col); + int getPixParticlePDG(int plane, int row, int col); + + std::map > pixMap; + std::string adc_tree; + void set_adc_treename( std::string name ) { adc_tree = name; }; + + }; + +} +} + +#endif From 9cf576c8709e3f027d544361d1c87b4d906301a9 Mon Sep 17 00:00:00 2001 From: Matthew Rosenberg Date: Sun, 16 Oct 2022 20:47:25 -0400 Subject: [PATCH 28/80] fixed bug in MCPixelPMap and added python binding --- ublarcvapp/MCTools/LinkDef.h | 1 + ublarcvapp/MCTools/MCPixelPMap.cxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index f5bbd66..f5f722e 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -17,6 +17,7 @@ #pragma link C++ namespace ublarcvapp+; #pragma link C++ namespace ublarcvapp::mctools+; #pragma link C++ class ublarcvapp::mctools::MCPixelPGraph+; +#pragma link C++ class ublarcvapp::mctools::MCPixelPMap+; #pragma link C++ class ublarcvapp::mctools::CrossingPointsAnaMethods+; #pragma link C++ class ublarcvapp::mctools::NeutrinoVertex+; #pragma link C++ class ublarcvapp::mctools::LArbysMC+; diff --git a/ublarcvapp/MCTools/MCPixelPMap.cxx b/ublarcvapp/MCTools/MCPixelPMap.cxx index 4d5ac51..7365b93 100644 --- a/ublarcvapp/MCTools/MCPixelPMap.cxx +++ b/ublarcvapp/MCTools/MCPixelPMap.cxx @@ -28,7 +28,7 @@ namespace mctools { PixCont_t pixCont( node.pid, adc_v[p].pixel(row, col) ); if(pixMap.count(pixLoc) == 0){ std::vector pixCont_v{pixCont}; - pixMap.at(pixLoc) = pixCont_v; + pixMap[pixLoc] = pixCont_v; } else{ pixMap[pixLoc].push_back(pixCont); } } From 7e91fdaa574c6f7b1b184aff1662c6fdd03696d1 Mon Sep 17 00:00:00 2001 From: Matthew Rosenberg Date: Sat, 26 Nov 2022 21:59:50 +0800 Subject: [PATCH 29/80] updated return info for MCPixelPMap --- ublarcvapp/MCTools/MCPixelPMap.cxx | 28 ++++++++-------------------- ublarcvapp/MCTools/MCPixelPMap.h | 24 +++++++++++++++++------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPMap.cxx b/ublarcvapp/MCTools/MCPixelPMap.cxx index 7365b93..555e59f 100644 --- a/ublarcvapp/MCTools/MCPixelPMap.cxx +++ b/ublarcvapp/MCTools/MCPixelPMap.cxx @@ -25,40 +25,28 @@ namespace mctools { int row = (node.pix_vv[p][2*iP] - 2400)/6; int col = node.pix_vv[p][2*iP+1]; PixLoc_t pixLoc( (int)p, row, col ); - PixCont_t pixCont( node.pid, adc_v[p].pixel(row, col) ); + PixPart_t pixPart( node.nodeidx, node.tid, node.pid ); if(pixMap.count(pixLoc) == 0){ - std::vector pixCont_v{pixCont}; - pixMap[pixLoc] = pixCont_v; + PixCont_t pixCont( adc_v[p].pixel(row, col) ); + pixCont.particles.push_back(pixPart); + pixMap[pixLoc] = pixCont; } - else{ pixMap[pixLoc].push_back(pixCont); } + else{ pixMap[pixLoc].particles.push_back(pixPart); } } } } } - std::vector MCPixelPMap::getPixContent(int plane, int row, int col){ + MCPixelPMap::PixCont_t MCPixelPMap::getPixContent(int plane, int row, int col){ PixLoc_t pixLoc(plane, row, col); if(pixMap.count(pixLoc) > 0){ return pixMap.at(pixLoc); } else{ - std::vector pixCont_v; - return pixCont_v; + PixCont_t pixCont; + return pixCont; } } - MCPixelPMap::PixCont_t MCPixelPMap::getPixParticle(int plane, int row, int col){ - auto pixCont_v = getPixContent(plane, row, col); - PixCont_t maxPartPixCont; - for(const auto& pixCont: pixCont_v){ - if(pixCont > maxPartPixCont) maxPartPixCont = pixCont; - } - return maxPartPixCont; - } - - int MCPixelPMap::getPixParticlePDG(int plane, int row, int col){ - return getPixParticle(plane, row, col).pdg; - } - } } diff --git a/ublarcvapp/MCTools/MCPixelPMap.h b/ublarcvapp/MCTools/MCPixelPMap.h index 456d9a7..9e31e20 100644 --- a/ublarcvapp/MCTools/MCPixelPMap.h +++ b/ublarcvapp/MCTools/MCPixelPMap.h @@ -38,11 +38,23 @@ namespace mctools { } }; - struct PixCont_t { + struct PixPart_t { + int nodeidx; + int tid; int pdg; + PixPart_t() : nodeidx(-1), tid(-1), pdg(0) {}; + PixPart_t(int _nodeidx, int _tid, int _pdg) : nodeidx(_nodeidx), tid(_tid), pdg(_pdg) {}; + bool operator>(const PixPart_t& rhs) const { + if(nodeidx > rhs.nodeidx) return true; + return false; + } + }; + + struct PixCont_t { float pixI; - PixCont_t() : pdg(0), pixI(0.) {}; - PixCont_t(int _pdg, float _pixI) : pdg(_pdg), pixI(_pixI) {}; + std::vector particles; + PixCont_t() : pixI(0.) {}; + PixCont_t(float _pixI) : pixI(_pixI) {}; bool operator>(const PixCont_t& rhs) const { if(pixI > rhs.pixI) return true; return false; @@ -52,11 +64,9 @@ namespace mctools { void buildmap( larcv::IOManager& iolcv, larlite::storage_manager& ioll ); void buildmap( larcv::IOManager& iolcv, ublarcvapp::mctools::MCPixelPGraph& pixGraph ); - std::vector getPixContent(int plane, int row, int col); - PixCont_t getPixParticle(int plane, int row, int col); - int getPixParticlePDG(int plane, int row, int col); + PixCont_t getPixContent(int plane, int row, int col); - std::map > pixMap; + std::map pixMap; std::string adc_tree; void set_adc_treename( std::string name ) { adc_tree = name; }; From 378ac68c3a7eae80ec95ecfc9aa5912fc0252f22 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Thu, 26 Jan 2023 12:12:25 -0500 Subject: [PATCH 30/80] made no flash match flag -9999 instead of -999 --- ublarcvapp/MCTools/FlashMatcher.cxx | 32 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index 707fb2c..acd70e9 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -105,7 +105,7 @@ namespace mctools { int FlashMatcher::trackAncestorID() { if (!ancestorID) - return -999; + return -9999; return ancestorID; @@ -114,7 +114,7 @@ namespace mctools { int FlashMatcher::getTrackID() { if (!trackID) - return -999; + return -9999; return trackID; @@ -123,7 +123,7 @@ namespace mctools { int FlashMatcher::trackOrigin() { if (!origin) - return -999; + return -9999; return origin; @@ -160,6 +160,9 @@ namespace mctools { auto const& mctrack = ev_mctrack->at(i); + trackID = mctrack.TrackID(); + ancestorID = mctrack.AncestorTrackID(); + std::cout << "TrackID is: " << mctrack.TrackID() << std::endl; std::cout << "Mother TrackID is: " << mctrack.MotherTrackID() << std::endl; std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; @@ -179,7 +182,7 @@ namespace mctools { if ( mctrack.size() == 0 ) { std::cout << "Empty vector of mcsteps (probably a cosmic that didn't cross the TPC)" << std::endl; - return -999.998; + return -9999.998; } //const larlite::mcstep& start = mctrack.Start(); @@ -203,14 +206,11 @@ namespace mctools { // check for primaries if ( mctrack.TrackID() != mctrack.MotherTrackID() ) { - return -999.997; + return -9999.997; } std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; - trackID = mctrack.TrackID(); - ancestorID = mctrack.AncestorTrackID(); - return tick; } @@ -249,15 +249,17 @@ namespace mctools { double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); tick = tick - xPos / cm_per_tick; + trackID = mcshower.TrackID(); + ancestorID = mcshower.AncestorTrackID(); + // check for primaries if ( mcshower.TrackID() != mcshower.MotherTrackID() ) { - return -999.997; + return -9999.997; } std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; - trackID = mcshower.TrackID(); - ancestorID = mcshower.AncestorTrackID(); + return tick; @@ -309,7 +311,7 @@ namespace mctools { /* * matches mctrack tick to opflash tick - * for cosmics, will return -999.999 if there is no opflash found within the threshold + * for cosmics, will return -9999.999 if there is no opflash found within the threshold * for beam tracks, will find the closest matching opflash * * @param[in] mctrackTick Time in ticks for the mctrack to be matched to @@ -329,8 +331,8 @@ std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector if (flashTicks.empty() == 1) { clusterTick = mctrackTick; - flashTick = 999.999; - return std::make_pair(999.999,999); + flashTick = 9999.999; + return std::make_pair(9999.999,9999); } auto match = std::lower_bound( flashTicks.begin(), flashTicks.end(), std::make_pair( mctrackTick, std::numeric_limits::min()) ); @@ -360,7 +362,7 @@ std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector return flashTicks[ match - flashTicks.begin() ]; } - return std::make_pair(-999.999,999); + return std::make_pair(-9999.999,9999); } From 9c03ff834f90a1e9b1f35fcd36a3309e38b27368 Mon Sep 17 00:00:00 2001 From: Polina Abratenko Date: Tue, 20 Jun 2023 15:33:12 -0400 Subject: [PATCH 31/80] fix constructor/destructor; clean print statements --- ublarcvapp/MCTools/FlashMatcher.cxx | 43 +++++++++++++++-------------- ublarcvapp/MCTools/FlashMatcher.h | 16 +++++++---- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcher.cxx b/ublarcvapp/MCTools/FlashMatcher.cxx index acd70e9..623665b 100644 --- a/ublarcvapp/MCTools/FlashMatcher.cxx +++ b/ublarcvapp/MCTools/FlashMatcher.cxx @@ -16,7 +16,7 @@ namespace mctools { _fm_tree = new TTree("fmtree","Flashmatched Tree"); bindAnaVariables(_fm_tree); - std::cout << "Made tree and bound vars" << std::endl; + std::cout << "FLASHMATCHER: Made tree and bound vars" << std::endl; //_voxelTree = new TTree("voxtree","Voxeldata Tree"); //_voxelTree = mgr.CloneTree() @@ -156,18 +156,18 @@ namespace mctools { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); - std::cout << "Number of tracks in event: " << ev_mctrack->size() << std::endl; + ///std::cout << "Number of tracks in event: " << ev_mctrack->size() << std::endl; auto const& mctrack = ev_mctrack->at(i); trackID = mctrack.TrackID(); ancestorID = mctrack.AncestorTrackID(); - std::cout << "TrackID is: " << mctrack.TrackID() << std::endl; - std::cout << "Mother TrackID is: " << mctrack.MotherTrackID() << std::endl; - std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; + ///std::cout << "TrackID is: " << mctrack.TrackID() << std::endl; + ///std::cout << "Mother TrackID is: " << mctrack.MotherTrackID() << std::endl; + ///std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; - std::cout << "Origin: " << mctrack.Origin() << std::endl; + ///std::cout << "Origin: " << mctrack.Origin() << std::endl; origin = mctrack.Origin(); if ( mctrack.Origin() == 1 ) { @@ -178,17 +178,17 @@ namespace mctools { isCosmic = 1; } - std::cout << "mctrack.size() = " << mctrack.size() << std::endl; + ///std::cout << "mctrack.size() = " << mctrack.size() << std::endl; if ( mctrack.size() == 0 ) { - std::cout << "Empty vector of mcsteps (probably a cosmic that didn't cross the TPC)" << std::endl; + ///std::cout << "Empty vector of mcsteps (probably a cosmic that didn't cross the TPC)" << std::endl; return -9999.998; } //const larlite::mcstep& start = mctrack.Start(); const larlite::mcstep& start = mctrack.at(0); - std::cout << "First mcstep X positiom is " << start.X() << " while the track started at: " << mctrack.Start().X() << std::endl; + ///std::cout << "First mcstep X positiom is " << start.X() << " while the track started at: " << mctrack.Start().X() << std::endl; larutil::SpaceChargeMicroBooNE* _sce = nullptr; @@ -202,14 +202,14 @@ namespace mctools { double tick2 = CrossingPointsAnaMethods::getTick(mctrack.Start(), 4050.0, _sce); tick2 = tick2 - xPos2 / cm_per_tick; - std::cout << "Tick for first mcstep in TPC: " << tick << " and tick for starting up in the sky: " << tick2 << std::endl; + ///std::cout << "Tick for first mcstep in TPC: " << tick << " and tick for starting up in the sky: " << tick2 << std::endl; // check for primaries if ( mctrack.TrackID() != mctrack.MotherTrackID() ) { return -9999.997; } - std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; + ///std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; return tick; @@ -220,15 +220,15 @@ namespace mctools { larlite::event_mcshower* ev_mcshower = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); - std::cout << "Number of showers in event: " << ev_mcshower->size() << std::endl; + ///std::cout << "Number of showers in event: " << ev_mcshower->size() << std::endl; auto const& mcshower = ev_mcshower->at(i); - std::cout << "TrackID is: " << mcshower.TrackID() << std::endl; - std::cout << "Mother TrackID is: " << mcshower.MotherTrackID() << std::endl; - std::cout << "PDG is: " << mcshower.PdgCode() << std::endl; + ///std::cout << "TrackID is: " << mcshower.TrackID() << std::endl; + ///std::cout << "Mother TrackID is: " << mcshower.MotherTrackID() << std::endl; + ///std::cout << "PDG is: " << mcshower.PdgCode() << std::endl; - std::cout << "Origin: " << mcshower.Origin() << std::endl; + ///std::cout << "Origin: " << mcshower.Origin() << std::endl; origin = mcshower.Origin(); if ( mcshower.Origin() == 1 ) { @@ -257,9 +257,7 @@ namespace mctools { return -9999.997; } - std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; - - + ///std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; return tick; @@ -290,20 +288,25 @@ namespace mctools { counter++; } + /* std::cout << "Before sort: " << std::endl; for (int i = 0; i < tickContainer.size(); i++) { std::cout << tickContainer[i].first << "\t" << tickContainer[i].second << std::endl; } + */ //std::cout << "Tick container: " << tickContainer << std::endl; std::sort( tickContainer.begin(), tickContainer.end() ); + /* std::cout << "After sort: " << std::endl; for (int i = 0; i < tickContainer.size(); i++) { std::cout << tickContainer[i].first << "\t" << tickContainer[i].second << std::endl; } + */ + //std::cout << "Tick container: " << tickContainer << std::endl; return tickContainer; @@ -340,7 +343,7 @@ std::pair FlashMatcher::matchTicks( double mctrackTick, std::vector //std::cout << "match [iterator] is: " << match << std::endl; //std::cout << "*match [dereferenced iterator, shoudl be a pair] is: " << (*(match)) << std::endl; - std::cout << "(*(match)).first [actual value of the tick] is: " << b << std::endl; + ///std::cout << "(*(match)).first [actual value of the tick] is: " << b << std::endl; if (match == flashTicks.begin() && fabs(b - mctrackTick) <= threshold) { clusterTick = mctrackTick; diff --git a/ublarcvapp/MCTools/FlashMatcher.h b/ublarcvapp/MCTools/FlashMatcher.h index bed024f..26f4a0b 100644 --- a/ublarcvapp/MCTools/FlashMatcher.h +++ b/ublarcvapp/MCTools/FlashMatcher.h @@ -17,15 +17,19 @@ namespace mctools { class FlashMatcher { public: - FlashMatcher() { + FlashMatcher() + : isCosmic(0), + _fm_tree(nullptr) + { + Clear(); + }; - isCosmic = 0; - if (_fm_tree) - delete _fm_tree; + virtual ~FlashMatcher() { + if (_fm_tree) { + delete _fm_tree; _fm_tree = nullptr; - + } }; - virtual ~FlashMatcher() {}; void initialize(); void bindAnaVariables( TTree* ); From 9d078b11d2241044aa0665e9dfdcbb564f54f016 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 13 Feb 2024 15:07:59 -0500 Subject: [PATCH 32/80] added v2 version of track-flash matching for petastorm tests --- ublarcvapp/MCTools/CMakeLists.txt | 2 + ublarcvapp/MCTools/FlashMatcherV2.cxx | 400 ++++++++++++++++++ ublarcvapp/MCTools/FlashMatcherV2.h | 108 +++++ ublarcvapp/MCTools/LinkDef.h | 2 + .../MCTools/crossingPointsAnaMethods.cxx | 24 ++ ublarcvapp/MCTools/crossingPointsAnaMethods.h | 4 + 6 files changed, 540 insertions(+) create mode 100644 ublarcvapp/MCTools/FlashMatcherV2.cxx create mode 100644 ublarcvapp/MCTools/FlashMatcherV2.h diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index a193fd0..55eb217 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -12,6 +12,7 @@ set( HEADERS MCPixelPGraph.h LArbysMC.h NeutrinoPixelFilter.h FlashMatcher.h + FlashMatcherV2.h MCPixelPMap.h ) # Add sources @@ -23,6 +24,7 @@ add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx LArbysMC.cxx NeutrinoPixelFilter.cxx FlashMatcher.cxx + FlashMatcherV2.cxx MCPixelPMap.cxx ) # larlite libraries diff --git a/ublarcvapp/MCTools/FlashMatcherV2.cxx b/ublarcvapp/MCTools/FlashMatcherV2.cxx new file mode 100644 index 0000000..4c56206 --- /dev/null +++ b/ublarcvapp/MCTools/FlashMatcherV2.cxx @@ -0,0 +1,400 @@ +#include "FlashMatcherV2.h" + +#include + +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/opflash.h" +#include "larlite/LArUtil/LArProperties.h" + +// ublarcvapp/mctools +#include "crossingPointsAnaMethods.h" + +namespace ublarcvapp { +namespace mctools { + + + + bool FlashMatcherV2::process(larlite::storage_manager& mgr) + { + + // first get list of times + buildRecoFlashPool( mgr ); + + // match truth tracks to flashes + matchTracksAndFlashes( mgr ); + + // list results + if ( _verbose_level>=1 ) + printMatches(); + + + return true; + + } + + + int FlashMatcherV2::numTracks( larlite::storage_manager& ioll ) { + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + + int numTracks = ev_mctrack->size(); + + return numTracks; + } + + int FlashMatcherV2::numShowers( larlite::storage_manager& ioll ) { + + larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + + int numShowers = ev_mcshower->size(); + + return numShowers; + + } + + // /* + // * grab time coordinate from mctrack mcstep -> convert to tick + // * + // * @param[in] ioll The larlite storage manager that contains mctruth class + // * @return tuple with tick, producer string, and cosmic flag + // */ + // double FlashMatcherV2::grabTickFromMCTrack( larlite::storage_manager& ioll, int i ) { + // larlite::event_mctrack* ev_mctrack + // = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + + // std::cout << "Number of tracks in event: " << ev_mctrack->size() << std::endl; + + // auto const& mctrack = ev_mctrack->at(i); + + // std::cout << "TrackID is: " << mctrack.TrackID() << std::endl; + // std::cout << "Mother TrackID is: " << mctrack.MotherTrackID() << std::endl; + // std::cout << "PDG is: " << mctrack.PdgCode() << std::endl; + + // std::cout << "Origin: " << mctrack.Origin() << std::endl; + // origin = mctrack.Origin(); + + // if ( mctrack.Origin() == 1 ) { + // producer = "simpleFlashBeam"; + // isCosmic = 0; + // } else { + // producer = "simpleFlashCosmic"; + // isCosmic = 1; + // } + + // const larlite::mcstep& start = mctrack.Start(); + + // larutil::SpaceChargeMicroBooNE* _sce = nullptr; + + // const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + // double xPos = start.X(); + + // double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + // tick = tick - xPos / cm_per_tick; + + // // check for primaries + // if ( mctrack.TrackID() != mctrack.MotherTrackID() ) { + // return -999.997; + // } + + // std::cout << "Ancestor ID: " << mctrack.AncestorTrackID() << std::endl; + + // trackID = mctrack.TrackID(); + // ancestorID = mctrack.AncestorTrackID(); + + // return tick; + + // } + + // double FlashMatcherV2::grabTickFromMCShower( larlite::storage_manager& ioll, int i ) { + + // larlite::event_mcshower* ev_mcshower + // = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + + // std::cout << "Number of showers in event: " << ev_mcshower->size() << std::endl; + + // auto const& mcshower = ev_mcshower->at(i); + + // std::cout << "TrackID is: " << mcshower.TrackID() << std::endl; + // std::cout << "Mother TrackID is: " << mcshower.MotherTrackID() << std::endl; + // std::cout << "PDG is: " << mcshower.PdgCode() << std::endl; + + // std::cout << "Origin: " << mcshower.Origin() << std::endl; + // origin = mcshower.Origin(); + + // if ( mcshower.Origin() == 1 ) { + // producer = "simpleFlashBeam"; + // isCosmic = 0; + // } else { + // producer = "simpleFlashCosmic"; + // isCosmic = 1; + // } + + // const larlite::mcstep& start = mcshower.Start(); + + // larutil::SpaceChargeMicroBooNE* _sce = nullptr; + + // const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + // double xPos = start.X(); + + // double tick = CrossingPointsAnaMethods::getTick(start, 4050.0, _sce); + // tick = tick - xPos / cm_per_tick; + + // // check for primaries + // if ( mcshower.TrackID() != mcshower.MotherTrackID() ) { + // return -999.997; + // } + + // std::cout << "Ancestor ID: " << mcshower.AncestorTrackID() << std::endl; + + // return tick; + + + // } + + + /** + * @brief inspect reco flash containers and store RecoFlash_t objects that store flash times + * + * When this is run, the member container \ref FlashMatcherV2.recoflash_v will be populated. + * This is a vector of RecoFlash_t objects that stores a list of trackIDs to each associated flash. + * + * + * + * params + * ------ + * @param[in] ioll larlite::storage_manager where an entry has already been loaded. + * + */ + void FlashMatcherV2::buildRecoFlashPool( larlite::storage_manager& ioll ) { + + // clear flash pools + recoflash_v.clear(); + + std::vector producer_v = {"simpleFlashBeam","simpleFlashCosmic"} ; + + for (int iproducer=0; iproducer<(int)producer_v.size(); iproducer++) { + std::string producer = producer_v.at(iproducer); + + larlite::event_opflash* ev_opreco + = (larlite::event_opflash*)ioll.get_data(larlite::data::kOpFlash, producer ); + if ( _verbose_level>=2 ) + std::cout << "Reco flashes in producer[" << producer << "]: " << ev_opreco->size() << std::endl; + + for (int iflash=0; iflash<(int)ev_opreco->size(); iflash++) { + + auto const& dataflash = ev_opreco->at(iflash); + + RecoFlash_t flash; + flash.producerid = iproducer; + flash.index = iflash; + flash.used = 0; + flash.time_us = dataflash.Time(); + flash.tick = dataflash.Time()/0.5 + 3200; // assuming optical time origin set at TPC clock tick 3200 + recoflash_v.emplace_back( std::move(flash) ); + }; + } + + // sort all the optical flashes by time + std::sort( recoflash_v.begin(), recoflash_v.end() ); + if ( _verbose_level>=1 ) + std::cout << "Number of reco flashes in the (truth) matching pool: " << recoflash_v.size() << std::endl; + + }; + + /** + * @brief match flashes and to MC tracks + * + * + */ + void FlashMatcherV2::matchTracksAndFlashes( larlite::storage_manager& ioll ) + { + + // use the mc particle graph tool + MCPixelPGraph mcpg; + mcpg.buildgraphonly( ioll ); + + associateTruthTrackIDs2recoFlashes( ioll, mcpg ); + buildNullFlashesToTrackIDs( ioll, mcpg ); + + std::sort( recoflash_v.begin(), recoflash_v.end() ); + + } + + /** + * @brief associate trackIDs from the mctrack and mcshower containers to the reco flashes + * + */ + void FlashMatcherV2::associateTruthTrackIDs2recoFlashes( larlite::storage_manager& ioll, + ublarcvapp::mctools::MCPixelPGraph& mcpg ) + { + + if ( _verbose_level>=2 ) + mcpg.printGraph(nullptr,false); + + // get the primary list + auto node_v = mcpg.getPrimaryParticles(); + + // loop over the primary nodes: these are the recorded list of primary particles + // defined as trackid=ancestorid + for ( auto const& node : node_v ) { + if ( _verbose_level>=2 ) + std::cout << "primary node: trackid=" << node->tid << " ancestorid=" << node->aid << " origin=" << node->origin << std::endl; + + std::vector txyz = { node->start[3] , node->start[0], node->start[1], node->start[2] }; + + float tpctick_nodrift = CrossingPointsAnaMethods::getTrueTick( txyz, 4050.0, NULL ); + if ( _verbose_level>=2 ) + std::cout << " tpctick_nodrift=" << tpctick_nodrift << std::endl; + + int closest_flashidx = -1; + float min_dtick = 1.0e9; + for ( int idx=0; idx<(int)recoflash_v.size(); idx++ ) { + float dtick = fabs(recoflash_v[idx].tick-tpctick_nodrift); + if (dtick=2 ) + std::cout << " closest flashidx=" << closest_flashidx << " dtick=" << min_dtick << std::endl; + + if ( min_dtick < _dtick_threshold && closest_flashidx>=0 ) { + // we've matched this track to a flash + + // get the reco flash that best matched to the primary + auto& flash = recoflash_v[closest_flashidx]; + + // assign this track ID to the flash + if ( node->origin==2 ) { + // cosmic origin track + if ( flash.ancestorid<0 ) { + flash.ancestorid = node->aid; + } + else if (flash.ancestorid>=0 && flash.ancestorid!=node->aid) { + std::cout << " WARNING: flash already matched to node with another ancestorid! old=" << flash.ancestorid << std::endl; + } + } + else if (node->origin==1 ) { + // neutrino origin track, set the flash as neutrino origin + flash.ancestorid = 0; + } + flash.trackid_v.insert( node->tid ); + + // get all the descendent particle records matched to this primary + auto node_et_daughters = mcpg.getNodeAndDescendentsFromTrackID( node->tid ); + int nadded = 0; + for ( auto& dnode : node_et_daughters ) { + flash.trackid_v.insert( dnode->tid ); + nadded++; + } + if ( _verbose_level>=2 ) + std::cout << " inserted " << nadded << " trackids to flash. Flash len(track_id)=" << flash.trackid_v.size() << std::endl; + + }//end of if tick difference is below max threshold + + }//end of loop over vector of primary node pointers + + return; + } + + /** + * @brief find trackIDs that did not have a reco flash + * + */ + void FlashMatcherV2::buildNullFlashesToTrackIDs( larlite::storage_manager& ioll, + ublarcvapp::mctools::MCPixelPGraph& mcpg ) + { + + // we need a list of ancestor ids where we've already matched + std::set< int > matched_ancestor_ids; + for ( auto const& recoflash : recoflash_v ) { + if ( recoflash.ancestorid>0 ) { + matched_ancestor_ids.insert( recoflash.ancestorid ); + } + else if ( recoflash.ancestorid==0 ) { + // for neutrino cluster, the trackids are their own ancestorids + for (auto const& trackid : recoflash.trackid_v ) { + matched_ancestor_ids.insert( trackid ); + } + } + } + + // container for null flashes + std::vector< RecoFlash_t > null_v; + + // now look for ancestor ids not in the above list + auto node_v = mcpg.getPrimaryParticles(); + for ( auto const& node : node_v ) { + + auto it_aid = matched_ancestor_ids.find( node->aid ); + if ( it_aid!=matched_ancestor_ids.end() ) + continue; // we've already matched this ancestor id + + // not in the list, make a null flash and associate + std::vector txyz = { node->start[3] , node->start[0], node->start[1], node->start[2] }; + float tpctick_nodrift = CrossingPointsAnaMethods::getTrueTick( txyz, 4050.0, NULL ); + + RecoFlash_t nullflash; + nullflash.producerid = -1; + nullflash.index = int(null_v.size()); + nullflash.used = 0; + nullflash.ancestorid = node->aid; + nullflash.tick = tpctick_nodrift; + nullflash.time_us = (tpctick_nodrift-3200.0)*(0.5); // (tick diff from trigger tick)*(0.5 usec per tick) + nullflash.trackid_v.insert( node->tid ); + + // put in daughters + auto node_et_daughters = mcpg.getNodeAndDescendentsFromTrackID( node->tid ); + int nadded = 0; + for ( auto& dnode : node_et_daughters ) { + nullflash.trackid_v.insert( dnode->tid ); + nadded++; + } + + if ( _verbose_level>=2 ) { + std::cout << " created null flash for ancestorid=" << node->aid << std::endl; + std::cout << " inserted " << nadded << " trackids to flash. Flash len(track_id)=" << nullflash.trackid_v.size() << std::endl; + } + + null_v.emplace_back( std::move(nullflash) ); + } + + if ( _verbose_level>=1 ) { + std::cout << "created " << null_v.size() << " null flashes" << std::endl; + } + + for (int ii=0; ii<(int)null_v.size(); ii++) { + recoflash_v.push_back( null_v.at(ii) ); + } + + } + + void FlashMatcherV2::printMatches() { + + std::cout << "=================================" << std::endl; + std::cout << " FlashMatcherV2::printMatches" << std::endl; + + for (int iflash=0; iflash<(int)recoflash_v.size(); iflash++) { + auto const& flash = recoflash_v.at(iflash); + std::stringstream flashinfo; + flashinfo << " flash[" << iflash << "]" + << " producer[" << flash.producerid << "]" + << " time_us=" << flash.time_us + << " tick=" << flash.tick + << " aid=" << flash.ancestorid + << " matched={ "; + for ( auto const& tid : flash.trackid_v ) { + flashinfo << tid << " "; + } + flashinfo << "}"; + std::cout << flashinfo.str() << std::endl; + } + std::cout << "==================================" << std::endl; + } + + +} +} diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h new file mode 100644 index 0000000..410f66b --- /dev/null +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -0,0 +1,108 @@ +#ifndef __FLASH_MATCHER_V2_H__ +#define __FLASH_MATCHER_V2_H__ + +#include +#include +#include "TTree.h" + +// larlite/core +#include "larlite/DataFormat/storage_manager.h" + +// ublarcvapp/mctools +#include "ublarcvapp/MCTools/MCPixelPGraph.h" + +namespace ublarcvapp { +namespace mctools { + + /** + * @class RecoFlash_t + * + * class for storing mc tracks associated to a flash + * + * can represent null flashes as well for charge depositing tracks + * that produce zero light in the PMTs. in this case the producerid + * will be 'null'. + * + */ + class RecoFlash_t { + public: + + // default constructor + RecoFlash_t() + : producerid(-1), + index(-1), + used(0), + ancestorid(-1), + time_us(0.0) + { + trackid_v.clear(); + }; + ~RecoFlash_t() {}; + + int producerid; + int index; + int used; + int ancestorid; ///< truth-matched ancestor ID of the particle cascade that made the flash + float time_us; ///< relative to optical system trigger + float tick; ///< TPC clock tick + + float operator<( const RecoFlash_t& rhs ) const { + if ( time_us < rhs.time_us ) return true; + return false; + }; + + std::set trackid_v; // geant track ids + + }; + + + /** + * @class FlashMatcherV2 + * + * class for matching reco optical flashes to true track information. + * + * + */ + class FlashMatcherV2 { + public: + + FlashMatcherV2() + : _dtick_threshold(1.0), + _verbose_level(0) + { + recoflash_v.clear(); + }; + virtual ~FlashMatcherV2() {}; + + bool process(larlite::storage_manager& mgr); + void printMatches(); + + int numTracks( larlite::storage_manager& ioll ); + int numShowers( larlite::storage_manager& ioll ); + + void buildRecoFlashPool( larlite::storage_manager& ioll ); + void matchTracksAndFlashes( larlite::storage_manager& ioll ); + void associateTruthTrackIDs2recoFlashes( larlite::storage_manager& ioll, + ublarcvapp::mctools::MCPixelPGraph& mgpg ); + void buildNullFlashesToTrackIDs( larlite::storage_manager& ioll, + ublarcvapp::mctools::MCPixelPGraph& mgpg ); + + void setVerboseLevel( int level ) { _verbose_level=level; }; + + protected: + + float _dtick_threshold; ///< absolute time difference between flash and mc track object to match + int _verbose_level; ///< control output to stdout. [0] quiet (default), [1] info, [2] debug + + public: + + + // container with matches + std::vector recoflash_v; + + }; + +} +} + +#endif diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index f5f722e..11a8384 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -24,7 +24,9 @@ #pragma link C++ class ublarcvapp::mctools::NeutrinoPixelFilter+; #pragma link C++ class ublarcvapp::mctools::TruthTrackSCE+; #pragma link C++ class ublarcvapp::mctools::TruthShowerTrunkSCE+; +#pragma link C++ class ublarcvapp::mctools::RecoFlash_t+; #pragma link C++ class ublarcvapp::mctools::FlashMatcher+; +#pragma link C++ class ublarcvapp::mctools::FlashMatcherV2+; #endif diff --git a/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx b/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx index 38ff397..75696f6 100644 --- a/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx +++ b/ublarcvapp/MCTools/crossingPointsAnaMethods.cxx @@ -60,6 +60,30 @@ namespace mctools { return tick; } + /** + * @brief get TPC tick from MC step info. do not apply drift time. + * + */ + float CrossingPointsAnaMethods::getTrueTick( const std::vector& step, const float trig_time, + const larutil::SpaceChargeMicroBooNE* psce ) { + // Function returns the tick time of a MC step point + // if SCE pointer is null, we do not correct for the space charge + + std::vector dpos(3,0); + if ( psce ) { + std::vector pos_offset = psce->GetPosOffsets( step[1], step[2], step[3] ); + dpos[0] = step[1] - pos_offset[0] + 0.7; + } + else { + dpos[0] = step[1]; + } + + const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + float tick = ( step[0]*1.0e-3 - (trig_time-4050.0) )/0.5 + 3200.0; + + return tick; + } + /** * doesTrackCrossImageBoundary * diff --git a/ublarcvapp/MCTools/crossingPointsAnaMethods.h b/ublarcvapp/MCTools/crossingPointsAnaMethods.h index 77d06a9..6b5fa8c 100644 --- a/ublarcvapp/MCTools/crossingPointsAnaMethods.h +++ b/ublarcvapp/MCTools/crossingPointsAnaMethods.h @@ -34,6 +34,10 @@ namespace mctools { static float getTick( const larlite::mcstep& step, const float trig_time=4050.0, const larutil::SpaceChargeMicroBooNE* psce=nullptr ); + static float getTrueTick( const std::vector& step, const float trig_time=4050.0, + const larutil::SpaceChargeMicroBooNE* psce=nullptr ); + + static int doesTrackCrossImageBoundary( const larlite::mctrack& track, const larcv::ImageMeta& meta, const float trig_time, const larutil::SpaceChargeMicroBooNE* psce=nullptr ); From 2dc5dffc51c49aae659c16253a9ea4be3077df22 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 22 Feb 2024 12:44:32 -0500 Subject: [PATCH 33/80] provide convenience function for outputing set of trackids --- ublarcvapp/MCTools/FlashMatcherV2.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h index 410f66b..3a093d3 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.h +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -52,6 +52,14 @@ namespace mctools { }; std::set trackid_v; // geant track ids + + std::vector trackid_list() const { + std::vector out_v; + for ( auto const& tid : trackid_v ) { + out_v.push_back(tid); + } + return out_v; + }; }; From 2b76fb0a847a335000c39c21c82db318338be5c0 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Thu, 21 Mar 2024 01:07:50 -0400 Subject: [PATCH 34/80] fixed bugs in flashmatcher. removed compilation warnings. created class for common calculations --- .../DLTagger/mrcnnmatch/AStarMaskCombo.h | 4 +- ublarcvapp/MCTools/CMakeLists.txt | 6 +- ublarcvapp/MCTools/FlashMatcherV2.cxx | 149 +++++++++++++++++- ublarcvapp/MCTools/FlashMatcherV2.h | 16 +- ublarcvapp/MCTools/LinkDef.h | 2 + ublarcvapp/MCTools/MCPos2ImageUtils.cxx | 93 +++++++++++ ublarcvapp/MCTools/MCPos2ImageUtils.h | 77 +++++++++ 7 files changed, 337 insertions(+), 10 deletions(-) create mode 100644 ublarcvapp/MCTools/MCPos2ImageUtils.cxx create mode 100644 ublarcvapp/MCTools/MCPos2ImageUtils.h diff --git a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h index cb4870e..1948702 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h +++ b/ublarcvapp/DLTagger/mrcnnmatch/AStarMaskCombo.h @@ -24,9 +24,9 @@ namespace dltagger { public: AStarMaskCombo() : larcv::larcv_base("AStarMaskCombo"), - pEndpoint(nullptr), astar_completed(0), - used_astar(false) + used_astar(false), + pEndpoint(nullptr) {}; virtual ~AStarMaskCombo() {}; diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 55eb217..c318f90 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -4,7 +4,8 @@ set(MODULE_NAME MCTools) set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers -set( HEADERS MCPixelPGraph.h +set( HEADERS MCPos2ImageUtils.h + MCPixelPGraph.h TruthTrackSCE.h TruthShowerTrunkSCE.h crossingPointsAnaMethods.h @@ -16,7 +17,8 @@ set( HEADERS MCPixelPGraph.h MCPixelPMap.h ) # Add sources -add_library( ${LIBNAME} SHARED MCPixelPGraph.cxx +add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx + MCPixelPGraph.cxx TruthTrackSCE.cxx TruthShowerTrunkSCE.cxx crossingPointsAnaMethods.cxx diff --git a/ublarcvapp/MCTools/FlashMatcherV2.cxx b/ublarcvapp/MCTools/FlashMatcherV2.cxx index 4c56206..35fe485 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.cxx +++ b/ublarcvapp/MCTools/FlashMatcherV2.cxx @@ -9,6 +9,7 @@ // ublarcvapp/mctools #include "crossingPointsAnaMethods.h" +#include "MCPos2ImageUtils.h" namespace ublarcvapp { namespace mctools { @@ -24,9 +25,12 @@ namespace mctools { // match truth tracks to flashes matchTracksAndFlashes( mgr ); + // list results - if ( _verbose_level>=1 ) + if ( _verbose_level>=1 ) { printMatches(); + printFiltered(); + } return true; @@ -171,6 +175,7 @@ namespace mctools { // clear flash pools recoflash_v.clear(); + filtered_v.clear(); std::vector producer_v = {"simpleFlashBeam","simpleFlashCosmic"} ; @@ -190,7 +195,7 @@ namespace mctools { flash.producerid = iproducer; flash.index = iflash; flash.used = 0; - flash.time_us = dataflash.Time(); + flash.time_us = dataflash.Time(); // time relative to optical clock t=0, which is at TPC trigger (tick=3200) flash.tick = dataflash.Time()/0.5 + 3200; // assuming optical time origin set at TPC clock tick 3200 recoflash_v.emplace_back( std::move(flash) ); }; @@ -201,7 +206,7 @@ namespace mctools { if ( _verbose_level>=1 ) std::cout << "Number of reco flashes in the (truth) matching pool: " << recoflash_v.size() << std::endl; - }; + } /** * @brief match flashes and to MC tracks @@ -218,6 +223,15 @@ namespace mctools { associateTruthTrackIDs2recoFlashes( ioll, mcpg ); buildNullFlashesToTrackIDs( ioll, mcpg ); + // tag flashes with matched truth mc track trajectories that + // cross the image boundary + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + tagTracksThatCrossImageBoundary( mcpg, *ev_mctrack ); + + // filter matches + filterMatches(); + std::sort( recoflash_v.begin(), recoflash_v.end() ); } @@ -235,6 +249,7 @@ namespace mctools { // get the primary list auto node_v = mcpg.getPrimaryParticles(); + // loop over the primary nodes: these are the recorded list of primary particles // defined as trackid=ancestorid @@ -276,10 +291,12 @@ namespace mctools { else if (flash.ancestorid>=0 && flash.ancestorid!=node->aid) { std::cout << " WARNING: flash already matched to node with another ancestorid! old=" << flash.ancestorid << std::endl; } + matched_ancestor_ids.insert( node->aid ); } else if (node->origin==1 ) { // neutrino origin track, set the flash as neutrino origin flash.ancestorid = 0; + matched_ancestor_ids.insert( node->tid ); } flash.trackid_v.insert( node->tid ); @@ -309,7 +326,6 @@ namespace mctools { { // we need a list of ancestor ids where we've already matched - std::set< int > matched_ancestor_ids; for ( auto const& recoflash : recoflash_v ) { if ( recoflash.ancestorid>0 ) { matched_ancestor_ids.insert( recoflash.ancestorid ); @@ -337,6 +353,9 @@ namespace mctools { std::vector txyz = { node->start[3] , node->start[0], node->start[1], node->start[2] }; float tpctick_nodrift = CrossingPointsAnaMethods::getTrueTick( txyz, 4050.0, NULL ); + if (std::isinf(tpctick_nodrift)) + continue; + RecoFlash_t nullflash; nullflash.producerid = -1; nullflash.index = int(null_v.size()); @@ -395,6 +414,128 @@ namespace mctools { std::cout << "==================================" << std::endl; } + void FlashMatcherV2::printFiltered() { + + std::cout << "=================================" << std::endl; + std::cout << " FlashMatcherV2::printFiltered" << std::endl; + + for (int iflash=0; iflash<(int)filtered_v.size(); iflash++) { + auto const& flash = filtered_v.at(iflash); + std::stringstream flashinfo; + flashinfo << " flash[" << iflash << "]" + << " producer[" << flash.producerid << "]" + << " time_us=" << flash.time_us + << " tick=" << flash.tick + << " aid=" << flash.ancestorid + << " matched={ "; + for ( auto const& tid : flash.trackid_v ) { + flashinfo << tid << " "; + } + flashinfo << "}"; + std::cout << flashinfo.str() << std::endl; + } + std::cout << "==================================" << std::endl; + } + + /** + * @brief look for tracks with incomplete charge + * + * this is usually due to tracks crossing the image boundary, so + * reconstruction spacepoints in the TPC are missing. + * + */ + void FlashMatcherV2::tagTracksThatCrossImageBoundary( ublarcvapp::mctools::MCPixelPGraph& mcpg, + const std::vector< larlite::mctrack >& track_v ) + { + + for (auto& recoflash : recoflash_v ) { + // for each flash, we loop over the mc truth of the matched particle + // tracks. for track-objects, we check if they cross the image boundary + // and look for missing charge. + if (_verbose_level>=2) { + std::cout << "[check flash] aid=" << recoflash.ancestorid << " tick=" << recoflash.tick << " time_us=" << recoflash.time_us << std::endl; + } + for (auto& trackid : recoflash.trackid_v ) { + + // we get info about this track already parsed by the pgraph class + auto pnode = mcpg.findTrackID(trackid); // returns pointer to MCPixelPGraph::Node_t struct + if ( pnode->type==0 ) { + // is a track + + // used the stored vector index to get larlite::mctrack object + auto const& mctrackinfo = track_v.at( pnode->vidx ); + + // convert track trajectory to list of points + std::vector< std::vector > reco_traj + = MCPos2ImageUtils::Get()->getRecoSpacepoints( mctrackinfo ); + + for (size_t i=0; i=8448.0 ) { + recoflash.within_image_bounds = false; + if ( _verbose_level>=1 ) + std::cout << " [ out of image bounds ]" << std::endl; + if ( _verbose_level>=2 ) { + std::cout << " [step " << i << "] reco=(" + << reco_step[0] << "," + << reco_step[1] << "," + << reco_step[2] << "," + << " tick=" << reco_step[3] << ") " + << " true=(" + << truth_step.X() << "," + << truth_step.Y() << "," + << truth_step.Z() << "," + << " t=" << truth_step.T()*1.0e-3 << " us)" + << std::endl; + } + break; + } + }// end of loop over reco traj points + + }// if node is track-type + + }//end of loop over track ids in reco flash + + }//end of loop over reco flashes + + return; + } + + /** + * @brief filter out matches + * + * moves filtered flash-track matches out of recoflash_v + * and into filtered_v member container. + */ + void FlashMatcherV2::filterMatches() { + + filtered_v.clear(); + + std::vector passes_v; + int nbefore_filter = recoflash_v.size(); + + for ( auto& recoflash : recoflash_v ) { + // apply cuts (truth-only based) + if ( recoflash.within_image_bounds ) { + passes_v.emplace_back( std::move(recoflash) ); + } + else { + filtered_v.emplace_back( std::move(recoflash) ); + } + } + + std::swap( recoflash_v, passes_v ); + + + std::cout << "[FlashMatcherV2::filterMatches] " + << " before filter=" << nbefore_filter + << " num passing=" << recoflash_v.size() + << " num filtered=" << filtered_v.size() + << std::endl; + + } + } } diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h index 3a093d3..2cb4da0 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.h +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -33,7 +33,9 @@ namespace mctools { index(-1), used(0), ancestorid(-1), - time_us(0.0) + time_us(0.0), + tick(0.0), + within_image_bounds(true) { trackid_v.clear(); }; @@ -45,6 +47,7 @@ namespace mctools { int ancestorid; ///< truth-matched ancestor ID of the particle cascade that made the flash float time_us; ///< relative to optical system trigger float tick; ///< TPC clock tick + bool within_image_bounds; float operator<( const RecoFlash_t& rhs ) const { if ( time_us < rhs.time_us ) return true; @@ -84,6 +87,7 @@ namespace mctools { bool process(larlite::storage_manager& mgr); void printMatches(); + void printFiltered(); int numTracks( larlite::storage_manager& ioll ); int numShowers( larlite::storage_manager& ioll ); @@ -97,6 +101,11 @@ namespace mctools { void setVerboseLevel( int level ) { _verbose_level=level; }; + void tagTracksThatCrossImageBoundary( ublarcvapp::mctools::MCPixelPGraph& mcpg, + const std::vector< larlite::mctrack >& track_v ); + + void filterMatches(); + protected: float _dtick_threshold; ///< absolute time difference between flash and mc track object to match @@ -104,9 +113,12 @@ namespace mctools { public: - + // track ancestor ids + std::set< int > matched_ancestor_ids; + // container with matches std::vector recoflash_v; + std::vector filtered_v; }; diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index 11a8384..5032074 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ namespace ublarcvapp+; #pragma link C++ namespace ublarcvapp::mctools+; +#pragma link C++ class ublarcvapp::mctools::MCPos2ImageUtils+; #pragma link C++ class ublarcvapp::mctools::MCPixelPGraph+; #pragma link C++ class ublarcvapp::mctools::MCPixelPMap+; #pragma link C++ class ublarcvapp::mctools::CrossingPointsAnaMethods+; @@ -27,6 +28,7 @@ #pragma link C++ class ublarcvapp::mctools::RecoFlash_t+; #pragma link C++ class ublarcvapp::mctools::FlashMatcher+; #pragma link C++ class ublarcvapp::mctools::FlashMatcherV2+; + #endif diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx new file mode 100644 index 0000000..1ed57d3 --- /dev/null +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx @@ -0,0 +1,93 @@ +#include "MCPos2ImageUtils.h" + +#include "larlite/LArUtil/DetectorProperties.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" + +namespace ublarcvapp { +namespace mctools { + + MCPos2ImageUtils* MCPos2ImageUtils::_p_singleton = nullptr; + + std::vector< std::vector > + MCPos2ImageUtils::getRecoSpacepoints( const larlite::mctrack& track, + bool apply_t0_shift, + bool apply_sce ) + { + std::vector< std::vector > reco( track.size() ); + + size_t istep = 0; + for (auto const& step : track ) { + reco[istep] = truepos_to_recopos( step.X(), step.Y(), step.Z(), step.T(), + apply_t0_shift, apply_sce ); + istep++; + } + + + return reco; + } + + std::vector + MCPos2ImageUtils::truepos_to_recopos( const float x_cm, const float y_cm, const float z_cm, + const float t_ns, + bool apply_t0_shift, + bool apply_sce ) + { + + float v_cm_per_us = ::larutil::LArProperties::GetME()->DriftVelocity(); + float ticks_per_us = (::larutil::DetectorProperties::GetME()->SamplingRate()*1.0e-3); // value return is in MHz, convert to usec + float trig_g4time_ns = 4050.0; + float dx_trigger_cm = 0.0; + + // std::cout << "v_cm_per_us: " << v_cm_per_us << std::endl; + // std::cout << "ticks_per_us: " << ticks_per_us << std::endl; + + std::vector pos_sce = { x_cm, y_cm, z_cm }; + if ( apply_sce ) { + pos_sce = get_sce_shifted_pos( x_cm, y_cm, z_cm ); + } + + std::vector reco_pos = pos_sce; + + if ( apply_t0_shift ) { + // apparent depth from the anode due to relative time to trigger + dx_trigger_cm = (t_ns - trig_g4time_ns)*1.0e-3*v_cm_per_us; + } + reco_pos[0] += dx_trigger_cm; + + // append the tick the charge should appear at + //float tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( reco_pos[0], 0 ); // this is busted + float tickx = reco_pos[0]/v_cm_per_us*ticks_per_us + 3200.0; + //std::cout << "tick=" << tick << " vs " << tickx << std::endl; + reco_pos.push_back( tickx ); + + return reco_pos; + } + + + /** + * @brief get the reco position due to electric field non-uniformity + * + */ + std::vector + MCPos2ImageUtils::get_sce_shifted_pos( const float x, const float y, const float z ) + { + + std::vector out = { x, y, z }; + + if ( psce ) { + std::vector sce_shift = psce->GetPosOffsets( x, y, z ); + out[0] += -sce_shift[0]+0.7; + out[1] += sce_shift[1]; + out[2] += sce_shift[2]; + } + + return out; + } + + + + + +} +} diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.h b/ublarcvapp/MCTools/MCPos2ImageUtils.h new file mode 100644 index 0000000..d3619c0 --- /dev/null +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.h @@ -0,0 +1,77 @@ +#ifndef __UBLARCVAPP_MCTOOLS_MCPOS2IMAGEUTILS_H__ +#define __UBLARCVAPP_MCTOOLS_MCPOS2IMAGEUTILS_H__ + +#include + +#include "larcv/core/Base/larcv_base.h" + +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +#include "larlite/DataFormat/mctrack.h" + +namespace ublarcvapp { +namespace mctools { + + /** + * The purpose of this singleton class is to standardize common conversions between + * the detector geometry and image locations. + * This requires detector-specific information that includes the geometry, drift direction, + * electronics clock, field, and space-charge effect. + * This utility class specializes in the conversions that involve MC values and objects. + * + * This is an attempt to standardize tools for later use across SBN. + * + */ + + class MCPos2ImageUtils : public larcv::larcv_base { + + public: + + // default constructor + MCPos2ImageUtils() + : larcv::larcv_base("MCPos2ImageUtils"), + psce(nullptr) + { + psce = new larutil::SpaceChargeMicroBooNE; + }; + + + // default destructor + virtual ~MCPos2ImageUtils() { + delete psce; + }; + + static MCPos2ImageUtils* Get() { + if ( !_p_singleton ) { + _p_singleton = new MCPos2ImageUtils; + } + return _p_singleton; + }; + + + std::vector< std::vector > + getRecoSpacepoints( const larlite::mctrack& track, + bool apply_t0_shift=true, + bool apply_sce=true ); + + std::vector + truepos_to_recopos( const float x_cm, const float y_cm, const float z_cm, + const float t_ns, + bool apply_t0_shift=true, + bool apply_sce=true ); + + std::vector + get_sce_shifted_pos( const float x, const float y, const float z ); + + + larutil::SpaceChargeMicroBooNE* psce; + + private: + + static MCPos2ImageUtils* _p_singleton; + + }; + +} +} + +#endif From 2cfef2b3ada207dc5df67c61eeee5e26eaf7da6b Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 3 May 2024 01:10:03 -0400 Subject: [PATCH 35/80] update for revised opflash data maker which checks coverage of tracks --- ublarcvapp/MCTools/FlashMatcherV2.cxx | 64 +++++++++++++------------ ublarcvapp/MCTools/FlashMatcherV2.h | 4 ++ ublarcvapp/MCTools/MCPixelPGraph.cxx | 9 ++++ ublarcvapp/MCTools/MCPixelPGraph.h | 3 ++ ublarcvapp/MCTools/MCPos2ImageUtils.cxx | 1 + 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcherV2.cxx b/ublarcvapp/MCTools/FlashMatcherV2.cxx index 35fe485..bcd1349 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.cxx +++ b/ublarcvapp/MCTools/FlashMatcherV2.cxx @@ -25,6 +25,10 @@ namespace mctools { // match truth tracks to flashes matchTracksAndFlashes( mgr ); + // filter matches + filterMatches(); + + std::sort( recoflash_v.begin(), recoflash_v.end() ); // list results if ( _verbose_level>=1 ) { @@ -217,7 +221,7 @@ namespace mctools { { // use the mc particle graph tool - MCPixelPGraph mcpg; + mcpg.clear(); mcpg.buildgraphonly( ioll ); associateTruthTrackIDs2recoFlashes( ioll, mcpg ); @@ -228,11 +232,6 @@ namespace mctools { larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); tagTracksThatCrossImageBoundary( mcpg, *ev_mctrack ); - - // filter matches - filterMatches(); - - std::sort( recoflash_v.begin(), recoflash_v.end() ); } @@ -241,7 +240,7 @@ namespace mctools { * */ void FlashMatcherV2::associateTruthTrackIDs2recoFlashes( larlite::storage_manager& ioll, - ublarcvapp::mctools::MCPixelPGraph& mcpg ) + ublarcvapp::mctools::MCPixelPGraph& mcpg ) { if ( _verbose_level>=2 ) @@ -391,6 +390,31 @@ namespace mctools { } + std::string FlashMatcherV2::strRecoMatchInfo( const RecoFlash_t& flash, int iflash ) const + { + std::stringstream flashinfo; + if ( iflash>=0 ) + flashinfo << "flash[" << iflash << "] index=" << flash.index; + else + flashinfo << "flash[index=" << flash.index << "] "; + + flashinfo << " producer[" << flash.producerid << "]" + << " time_us=" << flash.time_us + << " tick=" << flash.tick + << " aid=" << flash.ancestorid + << " matched={ "; + for ( auto const& tid : flash.trackid_v ) { + flashinfo << tid << " "; + } + flashinfo << "}"; + return flashinfo.str(); + } + + void FlashMatcherV2::printRecoMatchInfo( const RecoFlash_t& flash, int iflash ) const + { + std::cout << strRecoMatchInfo( flash, iflash ) << std::endl; + } + void FlashMatcherV2::printMatches() { std::cout << "=================================" << std::endl; @@ -398,18 +422,7 @@ namespace mctools { for (int iflash=0; iflash<(int)recoflash_v.size(); iflash++) { auto const& flash = recoflash_v.at(iflash); - std::stringstream flashinfo; - flashinfo << " flash[" << iflash << "]" - << " producer[" << flash.producerid << "]" - << " time_us=" << flash.time_us - << " tick=" << flash.tick - << " aid=" << flash.ancestorid - << " matched={ "; - for ( auto const& tid : flash.trackid_v ) { - flashinfo << tid << " "; - } - flashinfo << "}"; - std::cout << flashinfo.str() << std::endl; + std::cout << " " << strRecoMatchInfo(flash, iflash) << std::endl; } std::cout << "==================================" << std::endl; } @@ -421,18 +434,7 @@ namespace mctools { for (int iflash=0; iflash<(int)filtered_v.size(); iflash++) { auto const& flash = filtered_v.at(iflash); - std::stringstream flashinfo; - flashinfo << " flash[" << iflash << "]" - << " producer[" << flash.producerid << "]" - << " time_us=" << flash.time_us - << " tick=" << flash.tick - << " aid=" << flash.ancestorid - << " matched={ "; - for ( auto const& tid : flash.trackid_v ) { - flashinfo << tid << " "; - } - flashinfo << "}"; - std::cout << flashinfo.str() << std::endl; + std::cout << strRecoMatchInfo( flash, iflash ) << std::endl; } std::cout << "==================================" << std::endl; } diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h index 2cb4da0..244ce41 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.h +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -88,6 +88,8 @@ namespace mctools { bool process(larlite::storage_manager& mgr); void printMatches(); void printFiltered(); + std::string strRecoMatchInfo( const RecoFlash_t& flash, int iflash=-1 ) const; + void printRecoMatchInfo( const RecoFlash_t& flash, int iflash=-1 ) const; int numTracks( larlite::storage_manager& ioll ); int numShowers( larlite::storage_manager& ioll ); @@ -111,6 +113,8 @@ namespace mctools { float _dtick_threshold; ///< absolute time difference between flash and mc track object to match int _verbose_level; ///< control output to stdout. [0] quiet (default), [1] info, [2] debug + MCPixelPGraph mcpg; + public: // track ancestor ids diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index ee63d2f..808a8f8 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -759,6 +759,15 @@ namespace mctools { } LARCV_INFO() << "Num entries in daughter2mother map: " << _shower_daughter2mother.size() << std::endl; } + + void MCPixelPGraph::clear() + { + + node_v.clear(); + _unassigned_pixels_vv.clear(); + _shower_daughter2mother.clear(); + + }; } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index a49b86c..a7a46f3 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -141,6 +141,9 @@ namespace mctools { std::vector getPrimaryParticles( bool exclude_neutrons=true ); std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons=true ); std::vector getNeutrinoParticles( bool exclude_neutrons=true ); + + // clear the state + void clear(); protected: diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx index 1ed57d3..f750919 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx @@ -58,6 +58,7 @@ namespace mctools { // append the tick the charge should appear at //float tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( reco_pos[0], 0 ); // this is busted float tickx = reco_pos[0]/v_cm_per_us*ticks_per_us + 3200.0; + //std::cout << "tick=" << tick << " vs " << tickx << std::endl; reco_pos.push_back( tickx ); From 37706cf83d7a0f4d5a9311d999b945cb3d663ad8 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Fri, 3 May 2024 18:28:54 -0400 Subject: [PATCH 36/80] added clear functions --- ublarcvapp/MCTools/FlashMatcherV2.cxx | 19 ++++++++++++++++++- ublarcvapp/MCTools/FlashMatcherV2.h | 2 ++ ublarcvapp/MCTools/MCPixelPGraph.cxx | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcherV2.cxx b/ublarcvapp/MCTools/FlashMatcherV2.cxx index bcd1349..bc3b3ea 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.cxx +++ b/ublarcvapp/MCTools/FlashMatcherV2.cxx @@ -61,6 +61,14 @@ namespace mctools { return numShowers; } + + void FlashMatcherV2::clear() + { + mcpg.clear(); + matched_ancestor_ids.clear(); + recoflash_v.clear(); + filtered_v.clear(); + } // /* // * grab time coordinate from mctrack mcstep -> convert to tick @@ -248,7 +256,9 @@ namespace mctools { // get the primary list auto node_v = mcpg.getPrimaryParticles(); - + + int nwarnings = 0; + int warning_limit = 100; // loop over the primary nodes: these are the recorded list of primary particles // defined as trackid=ancestorid @@ -289,6 +299,13 @@ namespace mctools { } else if (flash.ancestorid>=0 && flash.ancestorid!=node->aid) { std::cout << " WARNING: flash already matched to node with another ancestorid! old=" << flash.ancestorid << std::endl; + nwarnings++; + + if ( nwarnings>warning_limit ) { + std::stringstream msg; + msg << "[FlashMatcherV2::associateTruthTrackIDs2recoFlashes] too many missing ID warnings. Stopping" << std::endl; + throw std::runtime_error(msg.str()); + } } matched_ancestor_ids.insert( node->aid ); } diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h index 244ce41..ba94bf7 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.h +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -108,6 +108,8 @@ namespace mctools { void filterMatches(); + virtual void clear(); + protected: float _dtick_threshold; ///< absolute time difference between flash and mc track object to match diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 808a8f8..48587d4 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -767,7 +767,7 @@ namespace mctools { _unassigned_pixels_vv.clear(); _shower_daughter2mother.clear(); - }; + } } } From 4820d04b87f41f4fcb09bc57b0873f97bb0b03f0 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Sat, 4 May 2024 14:56:24 -0400 Subject: [PATCH 37/80] fix flashmatcher bugs. example adding tracks to second non-neutrino track attached. changed display output of nodes and what is stored for imgpos and start. now attempts to get first xyz position in TPC (imgpos) and first position in LAr (start). i should change the ancestor IDs for the neutrino origin particles --- ublarcvapp/MCTools/FlashMatcherV2.cxx | 29 ++++++++------ ublarcvapp/MCTools/FlashMatcherV2.h | 4 +- ublarcvapp/MCTools/MCPixelPGraph.cxx | 56 +++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/ublarcvapp/MCTools/FlashMatcherV2.cxx b/ublarcvapp/MCTools/FlashMatcherV2.cxx index bc3b3ea..4ff6523 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.cxx +++ b/ublarcvapp/MCTools/FlashMatcherV2.cxx @@ -290,12 +290,16 @@ namespace mctools { // get the reco flash that best matched to the primary auto& flash = recoflash_v[closest_flashidx]; + + bool added_primary = false; // assign this track ID to the flash if ( node->origin==2 ) { // cosmic origin track if ( flash.ancestorid<0 ) { flash.ancestorid = node->aid; + flash.trackid_v.insert( node->tid ); + added_primary = true; } else if (flash.ancestorid>=0 && flash.ancestorid!=node->aid) { std::cout << " WARNING: flash already matched to node with another ancestorid! old=" << flash.ancestorid << std::endl; @@ -313,18 +317,21 @@ namespace mctools { // neutrino origin track, set the flash as neutrino origin flash.ancestorid = 0; matched_ancestor_ids.insert( node->tid ); + flash.trackid_v.insert( node->tid ); + added_primary = true; } - flash.trackid_v.insert( node->tid ); - - // get all the descendent particle records matched to this primary - auto node_et_daughters = mcpg.getNodeAndDescendentsFromTrackID( node->tid ); - int nadded = 0; - for ( auto& dnode : node_et_daughters ) { - flash.trackid_v.insert( dnode->tid ); - nadded++; + + if ( added_primary ) { + // get all the descendent particle records matched to this primary + auto node_et_daughters = mcpg.getNodeAndDescendentsFromTrackID( node->tid ); + int nadded = 0; + for ( auto& dnode : node_et_daughters ) { + flash.trackid_v.insert( dnode->tid ); + nadded++; + } + if ( _verbose_level>=2 ) + std::cout << " inserted " << nadded << " trackids to flash. Flash len(track_id)=" << flash.trackid_v.size() << std::endl; } - if ( _verbose_level>=2 ) - std::cout << " inserted " << nadded << " trackids to flash. Flash len(track_id)=" << flash.trackid_v.size() << std::endl; }//end of if tick difference is below max threshold @@ -338,7 +345,7 @@ namespace mctools { * */ void FlashMatcherV2::buildNullFlashesToTrackIDs( larlite::storage_manager& ioll, - ublarcvapp::mctools::MCPixelPGraph& mcpg ) + ublarcvapp::mctools::MCPixelPGraph& mcpg ) { // we need a list of ancestor ids where we've already matched diff --git a/ublarcvapp/MCTools/FlashMatcherV2.h b/ublarcvapp/MCTools/FlashMatcherV2.h index ba94bf7..c30da31 100644 --- a/ublarcvapp/MCTools/FlashMatcherV2.h +++ b/ublarcvapp/MCTools/FlashMatcherV2.h @@ -114,11 +114,11 @@ namespace mctools { float _dtick_threshold; ///< absolute time difference between flash and mc track object to match int _verbose_level; ///< control output to stdout. [0] quiet (default), [1] info, [2] debug - - MCPixelPGraph mcpg; public: + MCPixelPGraph mcpg; + // track ancestor ids std::set< int > matched_ancestor_ids; diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 48587d4..d8f26de 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -15,6 +15,7 @@ #include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "crossingPointsAnaMethods.h" +#include "MCPos2ImageUtils.h" namespace ublarcvapp { namespace mctools { @@ -110,6 +111,11 @@ namespace mctools { // Create ROOT node Node_t neutrino ( node_v.size(), -1, 0, 0, -1 ); + + float tpc_x = larutil::Geometry::GetME()->DetHalfWidth()*2.0; + float tpc_y = larutil::Geometry::GetME()->DetHalfHeight(); + float tpc_z = larutil::Geometry::GetME()->DetLength(); + // if there is a neutrino, then we add the start position if ( mctruth_v.size()>0 ) { const larlite::mctruth& mct = mctruth_v.front(); @@ -153,13 +159,45 @@ namespace mctools { // real position, time tracknode.start.resize(4); - tracknode.start[0] = mct.Start().X(); - tracknode.start[1] = mct.Start().Y(); - tracknode.start[2] = mct.Start().Z(); - tracknode.start[3] = mct.Start().T(); - _get_imgpos( tracknode.start, tracknode.imgpos4, sce ); + + // set start position. + // try to move it into the tpc first + if ( mct.size()<1 ) { + tracknode.start[0] = mct.Start().X(); + tracknode.start[1] = mct.Start().Y(); + tracknode.start[2] = mct.Start().Z(); + tracknode.start[3] = mct.Start().T(); + } + else { + tracknode.start[0] = mct[0].X(); + tracknode.start[1] = mct[0].Y(); + tracknode.start[2] = mct[0].Z(); + tracknode.start[3] = mct[0].T(); + } + + // first image point + std::vector xyz(4,0); + bool intpc = false; + for (auto const& step : mct ) { + xyz[0] = (float)step.X(); + xyz[1] = (float)step.Y(); + xyz[2] = (float)step.Z(); + xyz[3] = (float)step.T(); + if ( ( xyz[0]>0.0 && xyz[0]0 && xyz[2] recopos(4,0); + if ( intpc ) { + recopos = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_recopos( xyz[0], xyz[1], xyz[2], xyz[3] ); + } + tracknode.imgpos4 = recopos; + //_get_imgpos( tracknode.start, tracknode.imgpos4, sce ); node_v.emplace_back( std::move(tracknode) ); } @@ -182,7 +220,7 @@ namespace mctools { showernode.origin = mcsh.Origin(); showernode.start.resize(4); showernode.aid = mcsh.AncestorTrackID(); - showernode.mtid = mcsh.MotherTrackID(); + showernode.mtid = mcsh.MotherTrackID(); showernode.start[0] = mcsh.DetProfile().X(); showernode.start[1] = mcsh.DetProfile().Y(); showernode.start[2] = mcsh.DetProfile().Z(); @@ -327,8 +365,9 @@ namespace mctools { << " aid=" << node.aid << " pdg=" << node.pid << " KE=" << node.E_MeV << " MeV" - //<< " start=(" << node.start[0] << "," << node.start[1] << "," << node.start[2] << "," << node.start[3] << ")" - << " imgpos=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << ")" + //<< " xyzt=(" << node.start[0] << "," << node.start[1] << "," << node.start[2] << "," << node.start[3]*1.0e-3 << " us)" + << " imgpos=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << " tick)" + << " tusec=" << node.start[3]*1.0e-3 << " us" //<< " (mid,mother)=(" << node.mid << "," << node.mother << ") " //<< " (mid,mother)=(" << node.mid << ") " << " ndaughters=" << node.daughter_v.size() @@ -712,6 +751,7 @@ namespace mctools { dpos[i] = realpos4[i]; } + std::vector txyz(4,0); if ( apply_sce ) { From 87fe255b4e73c23a4a957e20578e3bc6bdaa5852 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 10 May 2024 20:52:54 -0400 Subject: [PATCH 38/80] a more complete accounting of the neutrino interaction is provided. using mctruth in mcpixelpgraph. also grouping particles from nu interaction under one node and fake ancestor id. easier for future studies i hope --- ublarcvapp/MCTools/LinkDef.h | 4 + ublarcvapp/MCTools/MCPixelPGraph.cxx | 629 ++++++++++++++++++- ublarcvapp/MCTools/MCPixelPGraph.h | 79 ++- ublarcvapp/MCTools/test/run_mcpixelpgraph.py | 54 +- 4 files changed, 746 insertions(+), 20 deletions(-) diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index 5032074..f3483a0 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -14,8 +14,12 @@ #pragma link off all classes; #pragma link off all functions; +#pragma link C++ namespace std; +#pragma link C++ class std::vector+; +#pragma link C++ class std::vector >+; #pragma link C++ namespace ublarcvapp+; #pragma link C++ namespace ublarcvapp::mctools+; + #pragma link C++ class ublarcvapp::mctools::MCPos2ImageUtils+; #pragma link C++ class ublarcvapp::mctools::MCPixelPGraph+; #pragma link C++ class ublarcvapp::mctools::MCPixelPMap+; diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 48587d4..34c501e 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -1,6 +1,7 @@ #include "MCPixelPGraph.h" #include +#include // larcv #include "larcv/core/DataFormat/EventImage2D.h" @@ -63,6 +64,8 @@ namespace mctools { larlite::event_mctruth* ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); buildgraphonly( *ev_mcshower, *ev_mctrack, *ev_mctruth ); + + } /** @@ -104,12 +107,31 @@ namespace mctools { // (3) (optional) get depth of each node by doing breath-first traversal // (4) sort vector pointers by depth (necessary?) + // dump mctruth info + // LARCV_DEBUG() << "MCTruth Dump" << std::endl; + // int imctruth=0; + // for ( auto& mctruth : mctruth_v ) { + // LARCV_DEBUG() << "MCTRUTH[" << imctruth << "] --------------" << std::endl; + // int imcpart = 0; + // for ( auto& part : mctruth.GetParticles() ) { + // LARCV_DEBUG() << " mcpart[" << imcpart << "] -------" << std::endl; + // LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; + // LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; + // LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; + // LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; + // LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; + // LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; + // } + // } + node_v.clear(); node_v.reserve( shower_v.size()+track_v.size() ); // Create ROOT node Node_t neutrino ( node_v.size(), -1, 0, 0, -1 ); + std::set tid_list; + // if there is a neutrino, then we add the start position if ( mctruth_v.size()>0 ) { const larlite::mctruth& mct = mctruth_v.front(); @@ -120,12 +142,23 @@ namespace mctools { neutrino.start[2] = mct.GetNeutrino().Nu().Trajectory().front().Z(); neutrino.start[3] = mct.GetNeutrino().Nu().Trajectory().front().T(); } - node_v.emplace_back( std::move(neutrino) ); + _eventRootNode = &node_v[0]; // load spacechargemicroboone larutil::SpaceChargeMicroBooNE sce; + struct NuPart_t { + + int geantid; + int pdg; + float E_MeV; + std::vector pos; + }; + + std::vector< NuPart_t > nu_part_v; + + // collect from mcreco tracks for (int vidx=0; vidx<(int)track_v.size(); vidx++ ) { const larlite::mctrack& mct = track_v[vidx]; LARCV_DEBUG() << "track[" << vidx << "] origin=" << mct.Origin() @@ -158,11 +191,22 @@ namespace mctools { tracknode.start[2] = mct.Start().Z(); tracknode.start[3] = mct.Start().T(); _get_imgpos( tracknode.start, tracknode.imgpos4, sce ); + + if ( tracknode.origin==1 ) { + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = tracknode.tid; + nuparticle.pdg = tracknode.pid; + nuparticle.E_MeV = mct.Start().E(); + nuparticle.pos = tracknode.start; + nu_part_v.push_back( nuparticle ); + } - + tid_list.insert( tracknode.tid ); node_v.emplace_back( std::move(tracknode) ); } + // collect from mcshowers for (int vidx=0; vidx<(int)shower_v.size(); vidx++ ) { const larlite::mcshower& mcsh = shower_v[vidx]; @@ -194,10 +238,130 @@ namespace mctools { _get_imgpos( showernode.start, showernode.imgpos4, sce, false ); //showernode.imgpos4 = showernode.start; //showernode.imgpos4[3] = 3200 + mcsh.DetProfile().X()/larutil::LArProperties::GetME()->DriftVelocity()/0.5; + + if ( showernode.origin==1 ) { + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = showernode.tid; + nuparticle.pdg = showernode.pid; + nuparticle.E_MeV = mcsh.Start().E(); + nuparticle.pos = std::vector{ (float)mcsh.Start().X(), (float)mcsh.Start().Y(), (float)mcsh.Start().Z(), (float)mcsh.Start().T() }; + nu_part_v.push_back( nuparticle ); + } + tid_list.insert( showernode.tid ); node_v.emplace_back( std::move(showernode) ); } + // find the geant4 trackid offset for the neutrinos + long smallest_nu_tid = -1; + for ( auto& node : node_v ) { + if ( node.origin==1 ) { + if (smallest_nu_tid<0 || node.tid < smallest_nu_tid ) { + smallest_nu_tid = node.tid; + } + } + } + LARCV_DEBUG() << "Smallest neutrino Geant4 Track ID: " << smallest_nu_tid << std::endl; + + // collect from mctruth + // we need to match the earliest track or shower object to + // a genie final state particle to get offset + int ifs_1 = 0; + int matched_fs = -1; + int matched_geant_id = -1; + for ( auto& mctruth : mctruth_v ) { + for ( auto& part : mctruth.GetParticles() ) { + if ( part.StatusCode()==1 ) { + ifs_1 += 1; + // does ginal state particel match any of the geant4 particles? + for (auto& nupart : nu_part_v) { + + // match pdg + if ( nupart.pdg!=part.PdgCode() ) + continue; + + // match energy + float dE_MeV = std::fabs(nupart.E_MeV-part.Momentum(0)[3]*1000.0); + LARCV_DEBUG() << "mctruth part: " << dE_MeV << std::endl; + if ( dE_MeV > 10.0 ) + continue; + + matched_fs = ifs_1; + matched_geant_id = nupart.geantid; + LARCV_DEBUG() << "have first match. genie finalstate id=" << matched_fs << " geantid=" << matched_geant_id << std::endl; + break; + } + + }//end of if status code + if (matched_fs>=0) + break; + }//end of mcpart loop + if (matched_fs>=0) + break; + }//end of mctruth loop + + int geantid_offset = smallest_nu_tid - (matched_fs-1); + LARCV_INFO() << "geantid offset: " << geantid_offset << " smallest_nu_tid=" << smallest_nu_tid << std::endl; + LARCV_INFO() << " matched_fs=" << matched_fs << " matched_geant4=" << matched_geant_id << std::endl; + + int imctruth=0; + int ifs = 0; + for ( auto& mctruth : mctruth_v ) { + int imcpart = 0; + for ( auto& part : mctruth.GetParticles() ) { + LARCV_DEBUG() << " mcpart[" << imctruth << "," << imcpart << "] -------" << std::endl; + LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; + LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; + LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; + LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; + LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; + LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; + + if ( part.StatusCode()==1 ) { + int geant_trackid = geantid_offset + ifs; + LARCV_DEBUG() << " Stable Final State. Implied Geant4 ID = " << geant_trackid << std::endl; + ifs++; + + auto it_tid = tid_list.find(geant_trackid); + if (it_tid==tid_list.end() ) { + int nodeidx = node_v.size(); + int type = 3; // genie-final-state + int tid = geant_trackid; + int vidx = imcpart; + int pid = part.PdgCode(); + Node_t* mother = nullptr; + int mid = -1; + float energy = part.Momentum(0)[3]*1e3 - part.Mass()*1.0e3; // in GeV, convert to MeV + std::vector start { (float)part.Position(0)[0], + (float)part.Position(0)[1], + (float)part.Position(0)[2], + (float)part.Position(0)[3]}; + std::vector imgpos4(4,0); + _get_imgpos( start, imgpos4, sce, true ); + + //LARCV_DEBUG() << "Creating Mother node from GENIE final states: tid=" << tid << " type=" << 3 << std::endl; + Node_t fsnode( nodeidx, type, tid, vidx, pid, mother, mid, energy, "primary" ); + fsnode.start = start; + fsnode.imgpos4 = imgpos4; + fsnode.mtid = tid; + fsnode.aid = tid; + fsnode.origin = 1; // neutrino origin (from genie) + LARCV_DEBUG() << "Add Genie Final State Particle to initial List: tid=" << tid << " pdg=" << pid << std::endl; + node_v.emplace_back( std::move(fsnode) ); + } + else { + LARCV_DEBUG() << "Genie Final State Partial [tid=" << geant_trackid << "] Already in MCReco List" << std::endl; + } + } + imcpart++; + } + imctruth++; + } + + // try to connect primary neutrino origin nodes to mctruth info + //_adoptNeutrinoOrphans( &mctruth_v ); + // sort Node_t object by geant track ID, relabel node IDs std::sort( node_v.begin(), node_v.end() ); for ( size_t nid=0; nidvidx); + // to do: check that truth info matches? + return x; + } + catch ( std::exception& ex ) { + std::stringstream err; + err << "Error accessing event_mctrack container at index=" << node->vidx << " for node[idx]=nodeidx" << std::endl; + err << "Node info: " << std::endl; + err << strNodeInfo( *node ) << std::endl; + err << "Exception: " << ex.what() << std::endl; + throw std::runtime_error( err.str() ); + } + } + + /** + * @brief wrapper function to retrieve Node's corresponding mcshower object from larlite container + */ + const larlite::mcshower& MCPixelPGraph::_retrieve_mcshowerobject( const Node_t* node, + const larlite::event_mcshower& ev_shower_v ) + { + try { + const larlite::mcshower& x = ev_shower_v.at(node->vidx); + // to do: check that truth info matches? + return x; + } + catch ( std::exception& ex ) { + std::stringstream err; + err << "Error accessing event_mcshower container at index=" << node->vidx << " for node[idx]=nodeidx" << std::endl; + err << "Node info: " << std::endl; + err << strNodeInfo( *node ) << std::endl; + err << "Exception: " << ex.what() << std::endl; + throw std::runtime_error( err.str() ); + } + } + + /** + * @brief convenience function to retrieve Node's corresponding mctrack object from larlite top-level io interface + */ + const larlite::mctrack& MCPixelPGraph::_retrieve_mctrackobject( const Node_t* node, + larlite::storage_manager& ioll, + std::string producername ) + { + const larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack, producername ); + + return _retrieve_mctrackobject( node, *ev_mctrack ); + } + + /** + * @brief convenience function to retrieve Node's corresponding mcshower object from larlite top-level io interface + */ + const larlite::mcshower& MCPixelPGraph::_retrieve_mcshowerobject( const Node_t* node, + larlite::storage_manager& ioll, + std::string producername ) + { + const larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower, producername ); + + return _retrieve_mcshowerobject( node, *ev_mcshower ); + } + + /** * locate Node_t in node_v using trackid (from geant4) * @@ -316,6 +561,9 @@ namespace mctools { * */ std::string MCPixelPGraph::strNodeInfo( const Node_t& node ) { + + int hasmother = ( node.mother ) ? 1 : 0; + std::stringstream ss; //ss << "node[" << node.nodeidx << "," << &node << "] " ss << "node[" << node.nodeidx << "] " @@ -323,7 +571,7 @@ namespace mctools { << " origin=" << node.origin << " p=" << node.process << " tid=" << node.tid - << " mid=" << node.mtid + << " mtid=" << node.mtid << " aid=" << node.aid << " pdg=" << node.pid << " KE=" << node.E_MeV << " MeV" @@ -331,6 +579,7 @@ namespace mctools { << " imgpos=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << ")" //<< " (mid,mother)=(" << node.mid << "," << node.mother << ") " //<< " (mid,mother)=(" << node.mid << ") " + << " hasmother=" << hasmother << " ndaughters=" << node.daughter_v.size() << " npixs=("; for ( size_t i=0; i0 ) branch += "-- "; + if ( visible_only ) { int nvis = 0; for ( auto const& pix_v : node->pix_vv ) @@ -760,14 +1010,383 @@ namespace mctools { LARCV_INFO() << "Num entries in daughter2mother map: " << _shower_daughter2mother.size() << std::endl; } - void MCPixelPGraph::clear() + int MCPixelPGraph::_define_neutrino_interaction_nodes( larlite::storage_manager& ioll ) { + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + return _define_neutrino_interaction_nodes( *ev_mctrack, *ev_mcshower ); + } + + int MCPixelPGraph::_define_neutrino_interaction_nodes( const larlite::event_mctrack& ev_mctrack, + const larlite::event_mcshower& ev_mcshower ) + { + // first we collect nodes with neutrino origin + bool exclude_neutrons = false; + std::vector< Node_t* > _nu_primary_v = getNeutrinoPrimaryParticles( exclude_neutrons ); + LARCV_DEBUG() << "Number of nu primaries returned: " << _nu_primary_v.size() << std::endl; + + // if we have access to MCTruth info, we should use it to define vertex locations. + // otherwise we use some distance threshold. 0.3 mm, the pitch length? + std::map< int, std::set > _nu_collected_primaries_v; + _nu_vertices_v.clear(); + + + for ( auto& pnode : _nu_primary_v ) { + // we test the vertex for every primary + LARCV_DEBUG() << "Considering Nu Primary node[" << pnode->nodeidx << "] tid=" << pnode->tid << std::endl; + + std::vector start = {0,0,0,0}; + + if ( pnode->isTrackObject() ) { + auto const& track = _retrieve_mctrackobject( pnode, ev_mctrack ); + for (int i=0; i<4; i++) { + start[i] = track.Start().Position()[i]; + } + } + else if (pnode->isShowerObject()) { + auto const& shower = _retrieve_mcshowerobject( pnode, ev_mcshower ); + for (int i=0; i<4; i++) { + start[i] = shower.Start().Position()[i]; // creation point in geant4, for photon, not the same as conversion point where visible EM cascade begins + } + } + else if (pnode->isGenieFinalStateObject()) { + start = pnode->start; + } + else { + LARCV_DEBUG() << "Node Primary neither a shower nor track object: " << pnode->nodeidx << std::endl; + LARCV_DEBUG() << "node: " << strNodeInfo( *pnode ) << std::endl; + continue; + } + + bool found_vertex_match = false; + int idx_matched_vertex = -1; + float closest_match = 1e9; + std::vector pos = start; + + LARCV_DEBUG() << "Nu primary start: " << pos[0] << " " << pos[1] << " " << pos[2] << " " << pos[3] << std::endl; + + for ( int idx_vertex=0; idx_vertex<(int)_nu_vertices_v.size(); idx_vertex++ ) { + + auto& vertex = _nu_vertices_v.at(idx_vertex); + + // distance to existing vertex + float dist = 0.; + for (int i=0; i<3; i++) { + dist += ( pos[i]-vertex[i] )*( pos[i]-vertex[i] ); + } + dist = sqrt(dist); + + // update closest match + if ( dist < closest_match ) { + idx_matched_vertex = idx_vertex; + closest_match = dist; + + // qualifies as found? + if ( dist < _kNuVertexDistCutoff_cm ) { + found_vertex_match = true; + idx_matched_vertex = idx_vertex; + } + } + + }//end of loop over established nu vertices + LARCV_DEBUG() << "result of vertex search: closest=" << closest_match << " idx_matched=" << idx_matched_vertex << " found_match=" << found_vertex_match << std::endl; + + if ( !found_vertex_match ) { + // new neutrino vertex defined using position + LARCV_DEBUG() << "New vertex defined." << std::endl; + std::vector new_vertex = { (float)pos[0], (float)pos[1], (float)pos[2], (float)pos[3] }; + _nu_vertices_v.push_back( new_vertex ); + + int nu_vertex_id = (int)_nu_vertices_v.size()-1; // using position in _nu_vertices as an id number (should use a struct I know) + std::set nu_primary_set; + nu_primary_set.insert( pnode->nodeidx ); // add node index + _nu_collected_primaries_v[ nu_vertex_id ] = nu_primary_set; + } + else { + // found match + LARCV_DEBUG() << "Matched primary to existing vertex. IDX=" << idx_matched_vertex << std::endl; + auto it=_nu_collected_primaries_v.find( idx_matched_vertex ); + it->second.insert( pnode->nodeidx ); + } + + }//end of loop over neutrino primaries + + LARCV_DEBUG() << "Number of vertices defined: " << _nu_vertices_v.size() << std::endl; + + if ( _nu_vertices_v.size()==0 ) + return 0; + + // now that we have nu vertices, we need to define a new neutrino ancestor ID, then relabel ancestor IDs for daughters + long max_geant4_trackid = -1; + if ( _nu_vertices_v.size()>0 ) { + for (auto pnode : node_v) { + if ( pnode.tid>max_geant4_trackid ) { + max_geant4_trackid = pnode.tid; + } + } + } + LARCV_DEBUG() << "Starting with max trackid=" << max_geant4_trackid << " to assign nu vertex nodes" << std::endl; + std::set nu_attached_v; // gather list of indices that have been attached to neutrinos + std::vector< Node_t* > nu_pnode_v; + + for (int inuvtx=0; inuvtx<(int)_nu_vertices_v.size(); inuvtx++) { + + LARCV_DEBUG() << "Build nu vertex node and assign daughters. [NU VTX IDX=" << inuvtx << "]" << std::endl; + + // get the next node index + int nu_node_idx = (int)node_v.size(); + // need an acceptable fake trackID + long fake_trackid = max_geant4_trackid+1; + max_geant4_trackid++; + int type_id = 2; + int pid = -1; + int mtid = fake_trackid; + float energy = 0.0; + std::string proc = "nuvertex"; + Node_t nu_node( nu_node_idx, type_id, fake_trackid, inuvtx, + pid, _eventRootNode, + mtid, energy, proc ); + + nu_node.origin = 1; + nu_node.aid = fake_trackid; + nu_node.mtid = -1; + + // insert into node vector + node_v.emplace_back( std::move(nu_node) ); + + // get pointer + Node_t* pnu_node = &(node_v.at(nu_node_idx)); + nu_pnode_v.push_back( pnu_node ); + + // now we need to + // (1) change the nu primaries associated to this interaction + // to list their mother node to this node representing the neutrino interaction + // (2) relabel the ancestor ID of all primary neutrinos to this ID + auto it_prim = _nu_collected_primaries_v.find( inuvtx ); + if ( it_prim==_nu_collected_primaries_v.end() ) + continue; + + for ( auto& nodeidx : it_prim->second ) { + + LARCV_DEBUG() << "Add primary, node=" << nodeidx << ", to nu vertex[" << inuvtx << "]" << std::endl; + + LARCV_DEBUG() << " reassign mother to nu vertex pnode=" << pnu_node << std::endl; + Node_t* pnode_nuprim = &(node_v.at(nodeidx)); + pnode_nuprim->mother = pnu_node; + + // collect daughters + std::vector prim_daughters = getNodeAndDescendentsFromTrackID( pnode_nuprim->tid ); + LARCV_DEBUG() << "Collect descendents of nu primary node[ " << nodeidx << "] ndaughters=" << (int)prim_daughters.size()-1 << std::endl; + + // reset the ancestor id of all of these nodes to the new fake track ID for nu interaction + // note: the function above returns the node of the starting track id + for ( auto& pdnode : prim_daughters ) { + pdnode->aid = (int)fake_trackid; + } + + // add this primary to the daughter list of the nu node + pnu_node->daughter_idx_v.push_back( pnode_nuprim->nodeidx ); + pnu_node->daughter_v.push_back( pnode_nuprim ); + LARCV_DEBUG() << "Add to NuVertex node list of daughters: now " << pnu_node->daughter_v.size() << std::endl; + nu_attached_v.insert( pnode_nuprim->nodeidx ); + + // add its E + pnu_node->E_MeV += pnode_nuprim->E_MeV; + LARCV_DEBUG() << "Add to NuVertex energy: now " << pnu_node->E_MeV << " MeV" << std::endl; + }//end of loop over primary node + + nu_attached_v.insert( nu_node_idx ); + + }//end of loop over newly creatd neutrino vertices + + // now we have to redefine the root node's connections + _eventRootNode = &(node_v[0]); + std::vector all_prim_v = getPrimaryParticles(exclude_neutrons); + + _eventRootNode->daughter_idx_v.clear(); + _eventRootNode->daughter_v.clear(); + + + for (auto& pnode : all_prim_v ) { + auto it_attached = nu_attached_v.find( pnode->nodeidx ); + if ( it_attached==nu_attached_v.end() ) { + // not attached to neutrino vertex, so add to root node + _eventRootNode->daughter_idx_v.push_back( pnode->nodeidx ); + _eventRootNode->daughter_v.push_back( pnode ); + } + } + + // attach the nu vertex nodes + for (auto& pnode : nu_pnode_v ) { + _eventRootNode->daughter_idx_v.push_back( pnode->nodeidx ); + _eventRootNode->daughter_v.push_back( pnode ); + } + + return _nu_vertices_v.size(); + } + + void MCPixelPGraph::clear() + { + + _unassigned_pixels_vv.clear(); node_v.clear(); - _unassigned_pixels_vv.clear(); + + _eventRootNode = nullptr; + _nu_vertices_v.clear(); _shower_daughter2mother.clear(); + //_map_trackid_to_nu_ancestor_v.clear(); } + + void MCPixelPGraph::_adoptNeutrinoOrphans( const larlite::event_mctruth* ev_mctruth ) + { + // we scan our nodes without mother nodes that come from neutrinos (origin=1) + // if we have mctruth, we look to find mother. then we make new mother node and finish graph + + std::map > final_state_map; + int ifs = 0; + if ( ev_mctruth ) { + int imctruth=0; + for ( auto const& mctruth : *ev_mctruth ) { + //LARCV_DEBUG() << "MCTRUTH[" << imctruth << "] --------------" << std::endl; + int imcpart = 0; + for ( auto& part : mctruth.GetParticles() ) { + if ( part.StatusCode()==1 ) { + int geant_trackid = ifs+1; + ifs++; + std::vector index = {imctruth,imcpart}; + final_state_map[geant_trackid] = index; + } + imcpart++; + } + imctruth++; + }//end of mctruth map + }//end of if have mctruth + + std::set tid_list; + for ( auto& node : node_v ) + tid_list.insert(node.tid); + + std::map< int, int > newmom_tid_to_nodeidx; + + for ( auto& node : node_v ) { + // has mother or is good neutrino mother + if ( node.origin!=1 ) { + continue; + } + + // check if the mother node is not already in the node list + auto it_tid = tid_list.find( node.mtid ); + if ( it_tid!=tid_list.end() ) { + // has a mother in the list, no need to gather one from the mctruth or create one + continue; + } + + // check if we might have a mother now + auto it_newmom = newmom_tid_to_nodeidx.find( node.mtid ); + if ( it_newmom==newmom_tid_to_nodeidx.end() ) { + // try ancestor id + it_newmom = newmom_tid_to_nodeidx.find( node.aid ); + } + + if ( it_newmom!=newmom_tid_to_nodeidx.end() ) { + // connected to a new mom! + //int momtid = it_newmom->first; + int momidx = it_newmom->second; + auto& momnode = node_v.at(momidx); + //momnode.daughter_v.push_back( &node ); + //momnode.daughter_idx_v.push_back( node.nodeidx ); + //node.mother = &momnode; + LARCV_DEBUG() << "Connected primary orphan to a newly created mom! New mom tid=" << momnode.tid << std::endl; + continue; + } + + LARCV_DEBUG() << "node[" << node.nodeidx << "] with mtid=" << node.mtid << " looking to find mom or create it" << std::endl; + + bool created_mother = false; + if ( ev_mctruth ) { + // if we have the mctruth, try to look for missing mother id + std::vector momindex; + int mom_tid = -1; + + auto it_fs = final_state_map.find( node.mtid ); + if ( it_fs!=final_state_map.end() ) { + // has mother, create a node + momindex = it_fs->second; + mom_tid = node.mid; + } + else { + // try using ancestor + auto it_fsa = final_state_map.find( node.aid ); + auto it_tid2 = tid_list.find( node.aid ); + // create a mother if (1) found in final state list AND (2) not found in tid_list (i.e. existing node list) + if ( it_fsa!=final_state_map.end() && it_tid2==tid_list.end() ) { + momindex = it_fsa->second; + mom_tid = node.aid; + } + } + + if ( mom_tid<1 ) + continue; + + LARCV_DEBUG() << "Creating mother node from Genie FSI info. mom_tid=" << mom_tid << std::endl; + std::cin.get(); + + if ( momindex.size()==2 ) { + // create a mother node from mcparticle info + const larlite::mcpart& part = ev_mctruth->at(momindex[0]).GetParticle( momindex[1] ); + int nodeidx = node_v.size(); + int type = 3; // genie-final-state + int tid = mom_tid; + int vidx = momindex[1]; + int pid = part.PdgCode(); + Node_t* mother = &(node_v[0]); // the root node + int mid = 0; + int energy = part.Momentum(0)[3]; + std::vector start { (float)part.Position(0)[0], + (float)part.Position(0)[1], + (float)part.Position(0)[2], + (float)part.Position(0)[3]}; + LARCV_DEBUG() << "Creating Mother node from GENIE final states: tid=" << tid << " type=" << 3 << std::endl; + Node_t momnode( nodeidx, type, tid, vidx, pid, mother, mid, energy, "primary" ); + momnode.start = start; + momnode.imgpos4 = start; + momnode.mtid = tid; + momnode.aid = tid; + momnode.origin = 1; // neutrino origin (from genie) + + //momnode.daughter_v.push_back( &node ); + //momnode.daughter_idx_v.push_back( node.nodeidx ); + + newmom_tid_to_nodeidx[momnode.tid] = momnode.nodeidx; + tid_list.insert(tid); + + node_v.push_back( std::move(momnode) ); + + //node.mother = &(node_v.back()); + + // add new mom to root node + //Node_t& rootnode = node_v.front(); + //rootnode.daughter_v.push_back( &(node_v.back()) ); + //rootnode.daughter_idx_v.push_back( node_v.back().nodeidx ); + + created_mother = true; + + } + else { + LARCV_DEBUG() << "No mother created for this." << std::endl; + } + }//end of if has ev_mctruth + + if ( created_mother ) + continue; + + }//end of loop over nodes + + }//end of adopt orphans } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index a7a46f3..b2e2eb7 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -28,7 +28,15 @@ namespace mctools { MCPixelPGraph() : larcv::larcv_base("MCPixelPGraph"), - adc_tree("wire") + node_v(), + _unassigned_pixels_vv(), + _eventRootNode(nullptr), + _nplanes(3), + _kNuVertexDistCutoff_cm(0.3), + _nu_vertices_v(), + _cluster_neutrino_particles(false), + _shower_daughter2mother(), + adc_tree("wire") {}; virtual ~MCPixelPGraph() {}; @@ -46,12 +54,14 @@ namespace mctools { void buildgraphonly( const larlite::event_mcshower& shower_v, const larlite::event_mctrack& track_v, const larlite::event_mctruth& mctruth_v ); + + void set_cluster_neutrino_particles( bool doit ) { _cluster_neutrino_particles=doit; }; struct Node_t { int nodeidx; // position in node_v - int type; // track=0, shower=1 + int type; // track=0, shower=1, nu-vertex=2, genie_fs=3 int vidx; // position in mcshower or mctrack vector int tid; // geant4 track-ID int aid; // ancestor geant4 trackid @@ -64,10 +74,13 @@ namespace mctools { std::vector daughter_idx_v; // daughter node indices in node_v std::vector daughter_v; // pointer to daughters std::vector< std::vector > pix_vv; // pixels in each plane. pixels stored in (tick,wire) coordinates - std::vector start; //< (x,y,z,t) before sce - std::vector imgpos4; //< (x,y,z,tick) after sce + std::vector start; //< (x,y,z,t) before sce, true start of particle + std::vector first_edep_pos; //< (x,y,z,t) before sce, first step that leaves edep in cryostat + std::vector first_tpc_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image + std::vector first_img_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image + std::vector imgpos4; //< (x,y,z,tick) after sce // the image position corresponding to first_tpc_pos std::vector< std::vector > plane_bbox_twHW_vv; /// bounding box for pixels in each plane - int origin; + int origin; // 1=neutrino, 2=cosmic, 0=unassigned, -1=unassigned Node_t() : nodeidx(-1), @@ -81,10 +94,15 @@ namespace mctools { mid(-1), E_MeV(-1.0), process("null"), - start({0,0,0}), + start({0,0,0,0}), + first_edep_pos({0,0,0,0}), + first_tpc_pos({0,0,0,0}), + first_img_pos({0,0,0,0}), imgpos4({0,0,0,0}), origin(-1) - {}; + { + daughter_v.clear(); + }; Node_t(int _nodeidx, int _type, int _tid, int _vidx, int _pid, @@ -104,6 +122,9 @@ namespace mctools { E_MeV(_energy), process(proc), start({0,0,0,0}), + first_edep_pos({0,0,0,0}), + first_tpc_pos({0,0,0,0}), + first_img_pos({0,0,0,0}), imgpos4({0,0,0,0}), origin(-1) {}; @@ -112,11 +133,37 @@ namespace mctools { if ( tid < rhs.tid ) return true; return false; }; + + bool isTrackObject() const { + if ( type==0 ) + return true; + return false; + }; + + bool isShowerObject() const { + if (type==1) + return true; + return false; + }; + + bool isNuVertexObject() const { + if (type==2) + return true; + return false; + }; + + bool isGenieFinalStateObject() const { + if (type==3) + return true; + return false; + }; + }; // list of nodes std::vector< Node_t > node_v; std::vector< std::vector > _unassigned_pixels_vv; + Node_t* _eventRootNode; // number of planes size_t _nplanes; // set when _scanPixelData is run @@ -142,6 +189,7 @@ namespace mctools { std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons=true ); std::vector getNeutrinoParticles( bool exclude_neutrons=true ); + // clear the state void clear(); @@ -157,11 +205,28 @@ namespace mctools { std::vector& imgpos4, larutil::SpaceChargeMicroBooNE& sce, bool apply_sce=true ); + + void _adoptNeutrinoOrphans( const larlite::event_mctruth* ev_mctruth ); + + virtual const larlite::mctrack& _retrieve_mctrackobject( const Node_t* node, const larlite::event_mctrack& ev_track_v ); + virtual const larlite::mcshower& _retrieve_mcshowerobject( const Node_t* node, const larlite::event_mcshower& ev_shower_v ); + virtual const larlite::mctrack& _retrieve_mctrackobject( const Node_t* node, larlite::storage_manager& ioll, std::string producername="mcreco" ); + virtual const larlite::mcshower& _retrieve_mcshowerobject( const Node_t* node, larlite::storage_manager& ioll, std::string producername="mcreco" ); + + float _kNuVertexDistCutoff_cm; + std::vector< std::vector > _nu_vertices_v; + + //std::map< int, int > _map_trackid_to_nu_ancestor_v; + bool _cluster_neutrino_particles; + int _define_neutrino_interaction_nodes( larlite::storage_manager& ioll ); + int _define_neutrino_interaction_nodes( const larlite::event_mctrack& ev_track_v, const larlite::event_mcshower& ev_shower_v ); public: std::map _shower_daughter2mother; void _fill_shower_daughter2mother_map( const std::vector& mcsh_v ); + + public: diff --git a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py index d12ac59..5bae67b 100644 --- a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py +++ b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py @@ -21,6 +21,9 @@ rt.gStyle.SetOptStat(0) ioll = larlite.storage_manager( larlite.storage_manager.kREAD ) +ioll.set_data_to_read( larlite.data.kMCTrack, "mcreco" ) +ioll.set_data_to_read( larlite.data.kMCShower, "mcreco" ) +ioll.set_data_to_read( larlite.data.kMCTruth, "generator" ) ioll.add_in_filename( args.input_larlite ) ioll.open() @@ -44,16 +47,24 @@ print("Start loop.") mcpg = ublarcvapp.mctools.MCPixelPGraph() +mcpg_nu = ublarcvapp.mctools.MCPixelPGraph() if args.debug: mcpg.set_verbosity( larcv.msg.kDEBUG ) + mcpg_nu.set_verbosity( larcv.msg.kDEBUG ) else: mcpg.set_verbosity( larcv.msg.kINFO ) -mcpg.set_adc_treename( args.adc ) + mcpg_nu.set_verbosity( larcv.msg.kINFO ) -tmp = rt.TFile("temp.root","recreate") +if HAS_LARCV: + mcpg.set_adc_treename( args.adc ) -c = rt.TCanvas("c","c",1200,1800) -c.Divide(1,3) +if HAS_LARCV: + tmp = rt.TFile("temp.root","recreate") + c = rt.TCanvas("c","c",1200,1800) + c.Divide(1,3) + +print("[ENTER to Start") +input() for ientry in range( nentries ): @@ -61,6 +72,12 @@ print("==========================") print("===[ EVENT ",ientry," ]===") ioll.go_to(ientry) + + mcpg.clear() + mcpg_nu.clear() + mcpg.set_cluster_neutrino_particles(False) + mcpg_nu.set_cluster_neutrino_particles(True) + if HAS_LARCV: iolcv.read_entry(ientry) ev_adc = iolcv.get_data( larcv.kProductImage2D, args.adc ) @@ -78,10 +95,31 @@ mcpg.buildgraph( iolcv, ioll ) else: mcpg.buildgraphonly( ioll ) - - mcpg.printAllNodeInfo() - #mcpg.printGraph() - sys.exit(0) + mcpg_nu.buildgraphonly( ioll ) + + if args.debug: + print("ALL NODE INFO [NO NU]======================================") + mcpg.printAllNodeInfo() + print("====================================================") + print("CONSTRUCTED PARTICLE GRAPH [NO NU]") + mcpg.printGraph(0,False) + print("====================================================") + print("====================================================") + print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + print("====================================================") + + print("====================================================") + print("ALL NODE INFO [WITH NU VERTEX GROUPING]======================================") + mcpg_nu.printAllNodeInfo() + print("====================================================") + print("CONSTRUCTED PARTICLE GRAPH [WITH NU VERTEX GROUPING]") + mcpg_nu.printGraph(0,False) + print("====================================================") + + print("[ENTER] to continue") + input() + if True: + continue #primaries = mcpg.getPrimaryParticles() primaries = mcpg.node_v From 7ba292ff952df3d759ba95ff72db0301ede0294c Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 15 May 2024 00:28:04 -0400 Subject: [PATCH 39/80] added start for ub photon vis library interface --- ublarcvapp/UBPhotonLib/CMakeLists.txt | 44 ++++++ ublarcvapp/UBPhotonLib/LinkDef.h | 26 ++++ ublarcvapp/UBPhotonLib/README.md | 196 +++++++++++++++++++++++++ ublarcvapp/UBPhotonLib/UBPhotonLib.cxx | 92 ++++++++++++ ublarcvapp/UBPhotonLib/UBPhotonLib.h | 49 +++++++ ublarcvapp/UBPhotonLib/dat/README.md | 1 + 6 files changed, 408 insertions(+) create mode 100644 ublarcvapp/UBPhotonLib/CMakeLists.txt create mode 100644 ublarcvapp/UBPhotonLib/LinkDef.h create mode 100644 ublarcvapp/UBPhotonLib/README.md create mode 100644 ublarcvapp/UBPhotonLib/UBPhotonLib.cxx create mode 100644 ublarcvapp/UBPhotonLib/UBPhotonLib.h create mode 100644 ublarcvapp/UBPhotonLib/dat/README.md diff --git a/ublarcvapp/UBPhotonLib/CMakeLists.txt b/ublarcvapp/UBPhotonLib/CMakeLists.txt new file mode 100644 index 0000000..165f387 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/CMakeLists.txt @@ -0,0 +1,44 @@ +set(MODULE_NAME UBPhotonLib) + +# library name +set(LIBNAME LArCVApp_${MODULE_NAME}) + +# Collect the headers +set( HEADERS UBPhotonLib.h ) + +# Add sources +add_library( ${LIBNAME} SHARED UBPhotonLib.cxx ) + +# larlite libraries +set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) + +# includes for ROOT dictionary gen +include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME}) + +if (HAS_LARLITE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") + #message("build ubimagemod with larlite") +else() + #message("build ubimagemod without larlite") +endif() + +# Generate the dictionary +ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) + +# Generate the shared library from the sources +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") +target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED}) + +# install libraries and headers +install(TARGETS ${LIBNAME} + EXPORT ublarcvapp + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include/ublarcvapp/${MODULE_NAME}) + +# install files needed for dictionary use in CINT/CLING/PYTHON +install( FILES + ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}_rdict.pcm + ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap + DESTINATION lib ) diff --git a/ublarcvapp/UBPhotonLib/LinkDef.h b/ublarcvapp/UBPhotonLib/LinkDef.h new file mode 100644 index 0000000..d011a7e --- /dev/null +++ b/ublarcvapp/UBPhotonLib/LinkDef.h @@ -0,0 +1,26 @@ +/** \defgroup UBPhotonLib + * + * \brief Interface and utilities for utilizing the UBPhotonLibrary + * + * + * cint script to generate libraries and python bindings. + * Declare namespace & classes you defined + * pragma statement: order matters! Google it ;) + * + */ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ namespace ublarcvapp+; +#pragma link C++ namespace ublarcvapp::ubphotonlib+; + +#pragma link C++ class ublarcvapp::ubphotonlib::UBPhotonLib+; + +#endif + + + + diff --git a/ublarcvapp/UBPhotonLib/README.md b/ublarcvapp/UBPhotonLib/README.md new file mode 100644 index 0000000..ec88436 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/README.md @@ -0,0 +1,196 @@ +# UB Photon Library Interface + + +Where can I get the photon library file? + +On the uboone CVMFS: + +``` +/cvmfs/uboone.opensciencegrid.org/products/uboone_photon_propagation/v01_01_00/PhotonPropagation/LibraryData/ +``` + +This folder contains: +``` +README uboone_photon_library_v6_70kV_EnhancedExtraTPCVis.root uboone_photon_library_variation_Rayleigh.root +uboone_photon_library_v5_0kV.root uboone_photon_library_v6_70kV.root uboone_photon_library_variation_Suppression75percent.root +uboone_photon_library_v5.root uboone_photon_library_variation_Attenuation8m.root +uboone_photon_library_v6_0kV.root uboone_photon_library_variation_Attenuation8m_Suppression75percent.root +``` + +The README in the folder contains the following info: +``` +Available photon libraries +-------------------------- + +uboone_photon_library_v5_0kV.root - MCC7 no E-field +uboone_photon_library_v5.root - MCC7 70kV (this file used for mcc7 g4) +uboone_photon_library_v6_0kV.root - MCC8 no E-field +uboone_photon_library_v6_70kV.root - MCC8 70kV (standard hv) +uboone_photon_library_v6_70kV_EnhancedExtraTPCVis.root + - Increased visibility outside TPC by 50%. + +The zero E-field photon libraries contain the probability that a +photon generated in a particular voxel will be detected by any pmt. + +The nonzero E-field are modified from the zero E-field photon libraries +by including the relative effect of the E-field on photon yield due +to recombination. +``` + + +Of the options, we use for now: `uboone_photon_library_v6_70kV_EnhancedExtraTPCVis.root` + +This file is 101 MB. + + +Inside the file is the following ROOT tree `PhotonLibraryData` located in the TDirectory, `pmtresponse`. +``` +****************************************************************************** +*Tree :PhotonLibraryData: * +*Entries : 33615139 : Total = 403773735 bytes File Size = 105069173 * +* : : Tree compression factor = 3.84 * +****************************************************************************** +*Br 0 :Voxel : Voxel/I * +*Entries : 33615139 : Total Size= 134587491 bytes File Size = 5521593 * +*Baskets : 1206 : Basket Size= 3264000 bytes Compression= 24.37 * +*............................................................................* +*Br 1 :OpChannel : OpChannel/I * +*Entries : 33615139 : Total Size= 134592331 bytes File Size = 7064466 * +*Baskets : 1206 : Basket Size= 3264000 bytes Compression= 19.05 * +*............................................................................* +*Br 2 :Visibility : Visibility/F * +*Entries : 33615139 : Total Size= 134593541 bytes File Size = 92451277 * +*Baskets : 1206 : Basket Size= 3264512 bytes Compression= 1.46 * +*............................................................................* +``` + +Voxels are labeled by a simple integer index. +This means we need to know the voxelization defintion and where it comes from. +We also need to know the OpChannel labeling scheme. + + +Parseing the Table + +Number of entries in the tree is: 33615139. + +Found the following config in the `standard_g4_uboone.fcl`: + +``` + PhotonVisibilityService: { + DoNotLoadLibrary: false + Interpolate: false + LibraryBuildJob: false + LibraryFile: "PhotonPropagation/LibraryData/uboone_photon_library_v6_70kV.root" + NX: 75 + NY: 75 + NZ: 400 + UseCryoBoundary: true + XMax: 120 + XMin: -120 + YMax: 120 + YMin: -120 + ZMax: 1200 + ZMin: 0 + service_type: "PhotonVisibilityService" + } +``` +That implies a total of 75*75*400*32 = 72,000,000 possible entries. +So less than half is filled. I guess that makes sense. + +The bounds don't make total sense. +The X width is only 240 cm. The TPC drift length is 256 cm! +The Y width is 240 cm, which is fine. (TPC height is 2*117 cm) +The Z width is 1200 cm, which is also fine. (TPC is 1036 cm) +OK, I see in `photpropservices.fcl` that these bounds are not used when "UseCryoBoundary: true". + +So then what are the cryo boundaries? +The photonvisibility service gets it from the geometry surface, by calling GetCryostat. +Great, so how does it do this? + +Used dump_geometry to extract cryostat and TPC bounds. + +The Key info (dump with all relevant det geom below). + + +``` +Cryostat C:0 (383.22 x 383.22 x 1221.75) cm^3 at (128.175,0,518.5) +TPC C:0 T:0 (260 x 256 x 1045) cm^3 at (128.175,0.97,518.5) +``` + +We work in the TPC coordinates always. Looks like the center is mostly the same. +There is a y=-0.97 offset (cryostat center is lower in global coordinates). +Dimensions x: 383.22 cm/75 = 5.1096 cm voxels +Origin of the C in global is: (-63.435,-191.61,-92.375) +Origin of TPC in the global is: (-1.825,-127.03,-4) +We use origin_cryo-origin_tpc to get cryo origin in TPC coordinate system. + + + +``` +Detector description: '/cvmfs/uboone.opensciencegrid.org/products/ubcore/v08_00_00_40/gdml/microboonev12.gdml' +Detector microboonev12 has 1 cryostats and 1168 auxiliary detectors: + Detector enclosure: (-613.455,-895.31,-223.13) -- (869.805,895.31,1260.13) cm => ( 1483.26 x 1790.62 x 1483.26 ) cm^3 + Cryostat C:0 (383.22 x 383.22 x 1221.75) cm^3 at (128.175,0,518.5) + hosts 1 TPCs (largest number of planes: 3, of wires: 3456) and 32 optical detectors + bounding box: (-63.435,-191.61,-92.375) -- (319.785,191.61,1129.38) + TPC C:0 T:0 (260 x 256 x 1045) cm^3 at (128.175,0.97,518.5) + drift direction (-1,0,0) from cathode around (254.8,0.97,518.5) through 255.4 cm toward 3 wire planes + maximum wires on any plane: 3456 + active volume (256.35 x 233 x 1036.8) cm^3, front face at (126.625,0.97,0.1) cm; + main directions: width (1,0,0) height (0,1,0) length (0,0,1) + bounding box: (-1.825,-127.03,-4) -- (258.175,128.97,1041) + active volume box: (-1.55,-115.53,0.1) -- (254.8,117.47,1036.9) + plane C:0 T:0 P:0 at (-6.34622e-14,0.97,518.5) cm, theta: 0.523599 rad + normal to wire: -1.0472 rad, with orientation vertical, has 2400 wires measuring U with a wire pitch of 0.3 cm + normal to plane: (1,0,0), direction of increasing wire number: (0,-0.866025,0.5) [wire frame normal: (1,0,0)] (increases with z) + wire direction: (0,0.5,0.866025); width 1037.35 cm in direction: (0,0,-1), depth 233 cm in direction: (0,1,0) [normal: (1,0,0)] + wires cover width -518.411 to 518.411, depth -116.387 to 116.387 cm + bounding box: (-0.075,-115.53,-0.175) -- (0.075,117.47,1037.17) + ... wire stuff ... + plane C:0 T:0 P:1 at (-0.3,0.97,518.5) cm, theta: 2.61799 rad + normal to wire: 1.0472 rad, with orientation vertical, has 2400 wires measuring V with a wire pitch of 0.3 cm + normal to plane: (1,0,0), direction of increasing wire number: (0,0.866025,0.5) [wire frame normal: (1,0,0)] (increases with z) + wire direction: (0,0.5,-0.866025); width 1037.35 cm in direction: (0,0,1), depth 233 cm in direction: (0,-1,0) [normal: (1,0,0)] + wires cover width -518.411 to 518.411, depth -116.387 to 116.387 cm + bounding box: (-0.375,-115.53,-0.175) -- (-0.225,117.47,1037.17) + plane C:0 T:0 P:2 at (-0.6,0.97,518.5) cm, theta: 1.5708 rad + normal to wire: 0 rad, with orientation vertical, has 3456 wires measuring Z with a wire pitch of 0.3 cm + normal to plane: (1,0,0), direction of increasing wire number: (0,0,1) [wire frame normal: (1,0,0)] (increases with z) + wire direction: (0,1,0); width 1037 cm in direction: (0,0,1), depth 233 cm in direction: (0,-1,0) [normal: (1,0,0)] + wires cover width -518.4 to 518.4, depth -116.5 to 116.5 cm + bounding box: (-0.675,-115.53,0) -- (-0.525,117.47,1037) + ... wire stuff ... + + [OpDet #0] centered at (-11.4545,-28.625,990.356) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #1] centered at (-11.4175,27.607,989.712) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #2] centered at (-11.7755,-56.514,951.865) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #3] centered at (-11.6415,55.313,951.861) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #4] centered at (-12.0585,-56.309,911.939) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #5] centered at (-11.8345,55.822,911.065) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #6] centered at (-12.1765,-0.722,865.599) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #7] centered at (-12.3045,-0.502,796.208) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #8] centered at (-12.6045,-56.284,751.905) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #9] centered at (-12.5405,55.625,751.884) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #10] centered at (-12.6125,-56.408,711.274) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #11] centered at (-12.6615,55.8,711.073) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #12] centered at (-12.6245,-0.051,664.203) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #13] centered at (-12.6515,-0.549,585.284) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #14] centered at (-12.8735,55.822,540.929) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #15] centered at (-12.6205,-56.205,540.616) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #16] centered at (-12.5945,-56.323,500.221) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #17] centered at (-12.9835,55.771,500.134) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #18] centered at (-12.6185,-0.875,453.096) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #19] centered at (-13.0855,-0.706,373.839) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #20] centered at (-12.6485,-57.022,328.341) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #21] centered at (-13.1865,54.693,328.212) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #22] centered at (-13.4175,54.646,287.976) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #23] centered at (-13.0075,-56.261,287.639) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #24] centered at (-13.1505,-0.829,242.014) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #25] centered at (-13.4415,-0.303,173.743) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #26] centered at (-13.3965,55.249,128.354) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #27] centered at (-13.2784,-56.203,128.18) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #28] centered at (-13.2375,-56.615,87.8695) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #29] centered at (-13.5415,55.249,87.7605) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #30] centered at (-13.4345,27.431,51.1015) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad + [OpDet #31] centered at (-13.1525,-28.576,50.4745) cm, radius: 15.24 cm, length: 0.2 cm, theta(z): 1.5708 rad +``` diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx new file mode 100644 index 0000000..168942f --- /dev/null +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx @@ -0,0 +1,92 @@ +#include "UBPhotonLib.h" + +#include + +#include "TFile.h" +#include "TTree.h" + +namespace ublarcvapp { +namespace ubphotonlib { + + UBPhotonLib* UBPhotonLib::_ginstance = nullptr; + + UBPhotonLib::UBPhotonLib() + : _tpc_global_origin_cm{-1.55, -115.53 + 0.5*(117.47+115.53), 0.1}, + _cryo_global_origin_cm{-63.435,-191.61,-92.375}, + _cryo_length_cm{383.22,383.22,1221.75}, + _nvoxels_dim{75,75,400}, + _voxel_len_cm{0,0,0}, + _cryo_origin_tpc_coord_cm{0,0,0} + { + + std::cout << "[UBPhotonLib] Loaded" << std::endl; + std::cout << " NVoxels per dim [" << _nvoxels_dim[0] << "," << _nvoxels_dim[1] << "," << _nvoxels_dim[2] << "]" << std::endl; + for (int i=0; i<3; i++) { + _voxel_len_cm[i] = _cryo_length_cm[i]/float(_nvoxels_dim[i]); + _cryo_origin_tpc_coord_cm[i] = _cryo_global_origin_cm[i] - _tpc_global_origin_cm[i]; + } + std::cout << " Voxel Length per dim [" << _voxel_len_cm[0] << "," << _voxel_len_cm[1] << "," << _voxel_len_cm[2] << "]" << std::endl; + + + std::string dat_folder = std::getenv("UBLARCVAPP_BASEDIR"); + std::string photon_vis_path = dat_folder + "/ublarcvapp/UBPhotonLib/dat/uboone_photon_library_v6_70kV_EnhancedExtraTPCVis.root"; + std::cout << " PhotonVis File: " << photon_vis_path << std::endl; + TFile rootfile( photon_vis_path.c_str(), "open"); + TTree* vistree = (TTree*)rootfile.Get("pmtresponse/PhotonLibraryData"); + size_t nentries = vistree->GetEntries(); + std::cout << " Entries in Vis File: " << nentries << std::endl; + Int_t Voxel; + Int_t OpChannel; + Float_t Visibility; + vistree->SetBranchAddress("Voxel",&Voxel); + vistree->SetBranchAddress("OpChannel",&OpChannel); + vistree->SetBranchAddress("Visibility",&Visibility); + + for (size_t i=0; iGetEntry(i); + std::pair voxelkey( (long)Voxel, (int)OpChannel ); + _voxelopchindex_to_visibility[ voxelkey ] = Visibility; + } + + std::cout << " Loaded Visibility Info" << std::endl; + } + + UBPhotonLib::~UBPhotonLib() + { + } + + UBPhotonLib* UBPhotonLib::getPhotonLib() + { + if ( !_ginstance ) { + _ginstance = new UBPhotonLib(); + } + return _ginstance; + } + + void UBPhotonLib::destroy() + { + std::cout<< "[UBPhotonLib::destroy()] free the memory used by the photon library" << std::endl; + delete _ginstance; + _ginstance = nullptr; + } + + long UBPhotonLib::getVoxelIndex( const std::vector& pos ) + { + int iindex[3] = {0,0,0}; + bool valid = true; + for (int i=0; i<3; i++) { + iindex[i] = (int)((pos[i] - _cryo_origin_tpc_coord_cm[i])/_voxel_len_cm[i]); + if ( iindex[i]<0 || iindex[i]>=_nvoxels_dim[i] ) + valid = false; + } + + if (!valid) + return -1; + + long lindex = iindex[0]*_nvoxels_dim[1]*_nvoxels_dim[2] + iindex[1]*_nvoxels_dim[2] + iindex[2]; + + return lindex; + } + +} +} diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.h b/ublarcvapp/UBPhotonLib/UBPhotonLib.h new file mode 100644 index 0000000..ef112e7 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.h @@ -0,0 +1,49 @@ +#ifndef __UBLARCVAPP_UBPHOTONLIB_UBPHOTONLIB_H__ +#define __UBLARCVAPP_UBPHOTONLIB_UBPHOTONLIB_H__ + +#include +#include + +namespace ublarcvapp { +namespace ubphotonlib { + + /** + * @brief Singleton class providing interface to the UB Photon Library + * + * + */ + class UBPhotonLib { + + public: + + static UBPhotonLib* getPhotonLib(); + static void destroy(); ///< to free up memory + + long getVoxelIndex( const std::vector& pos ); + + protected: + + UBPhotonLib(); + virtual ~UBPhotonLib(); + + + float _tpc_global_origin_cm[3]; + float _cryo_global_origin_cm[3]; + float _cryo_length_cm[3]; + int _nvoxels_dim[3]; + float _voxel_len_cm[3]; + float _cryo_origin_tpc_coord_cm[3]; + + std::map< std::pair , float > _voxelopchindex_to_visibility; + + private: + + static UBPhotonLib* _ginstance; + + }; + + +} +} + +#endif diff --git a/ublarcvapp/UBPhotonLib/dat/README.md b/ublarcvapp/UBPhotonLib/dat/README.md new file mode 100644 index 0000000..37c59df --- /dev/null +++ b/ublarcvapp/UBPhotonLib/dat/README.md @@ -0,0 +1 @@ +Copy the photon library file here. \ No newline at end of file From e744fd5af8817bf075361e5f3f7be4737e2a70d0 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 15 May 2024 00:40:06 -0400 Subject: [PATCH 40/80] got simple visibility look-up --- ublarcvapp/CMakeLists.txt | 1 + ublarcvapp/UBPhotonLib/UBPhotonLib.cxx | 46 ++++++++++++++++++++++++-- ublarcvapp/UBPhotonLib/UBPhotonLib.h | 3 ++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index bebffc2..33fe7b3 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -10,6 +10,7 @@ if (HAS_LARLITE) add_subdirectory(ubdllee) add_subdirectory(Filter) add_subdirectory(MCTools) + add_subdirectory(UBPhotonLib) endif() diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx index 168942f..b37759e 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx @@ -70,12 +70,20 @@ namespace ubphotonlib { _ginstance = nullptr; } + std::vector UBPhotonLib::getVoxelDimIndices( const std::vector& pos ) + { + std::vector iindex(3,0); + for (int i=0; i<3; i++) { + iindex[i] = (int)((pos[i] - _cryo_origin_tpc_coord_cm[i])/_voxel_len_cm[i]); + } + return iindex; + } + long UBPhotonLib::getVoxelIndex( const std::vector& pos ) { - int iindex[3] = {0,0,0}; + std::vector iindex = getVoxelDimIndices( pos ); bool valid = true; for (int i=0; i<3; i++) { - iindex[i] = (int)((pos[i] - _cryo_origin_tpc_coord_cm[i])/_voxel_len_cm[i]); if ( iindex[i]<0 || iindex[i]>=_nvoxels_dim[i] ) valid = false; } @@ -87,6 +95,40 @@ namespace ubphotonlib { return lindex; } + + float UBPhotonLib::getVisibility( const std::vector& pos, int opch ) + { + long lindex = getVoxelIndex( pos ); + if ( lindex<0 ) + return 0.0; + + std::pair voxopch_key( lindex, opch ); + auto it=_voxelopchindex_to_visibility.find( voxopch_key ); + if ( it==_voxelopchindex_to_visibility.end() ) { + // not found + return 0.0; + } + + // return visibility + return it->second; + } + + float UBPhotonLib::getVisibilityTrilinear( const std::vector& pos, int opch ) + { + long lindex = getVoxelIndex( pos ); + if ( lindex<0 ) + return 0.0; + + std::pair voxopch_key( lindex, opch ); + auto it=_voxelopchindex_to_visibility.find( voxopch_key ); + if ( it==_voxelopchindex_to_visibility.end() ) { + // not found + return 0.0; + } + + // return visibility + return it->second; + } } } diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.h b/ublarcvapp/UBPhotonLib/UBPhotonLib.h index ef112e7..3cb500c 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.h +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.h @@ -19,7 +19,10 @@ namespace ubphotonlib { static UBPhotonLib* getPhotonLib(); static void destroy(); ///< to free up memory + std::vector getVoxelDimIndices( const std::vector& pos ); long getVoxelIndex( const std::vector& pos ); + float getVisibility( const std::vector& pos, int opch ); + float getVisibilityTrilinear( const std::vector& pos, int opch ); protected: From 9476bc3f34688138f28dd66fa2a8d072cf55dd77 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 15 May 2024 16:07:11 -0400 Subject: [PATCH 41/80] finished simple interface to the ubphotonlib data. confirmed visually that it seems to work --- ublarcvapp/UBPhotonLib/UBPhotonLib.cxx | 132 ++++++++++++++++++++----- ublarcvapp/UBPhotonLib/UBPhotonLib.h | 46 ++++++++- 2 files changed, 147 insertions(+), 31 deletions(-) diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx index b37759e..01eccde 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx @@ -1,6 +1,7 @@ #include "UBPhotonLib.h" #include +#include #include "TFile.h" #include "TTree.h" @@ -16,7 +17,10 @@ namespace ubphotonlib { _cryo_length_cm{383.22,383.22,1221.75}, _nvoxels_dim{75,75,400}, _voxel_len_cm{0,0,0}, - _cryo_origin_tpc_coord_cm{0,0,0} + _cryo_origin_tpc_coord_cm{0,0,0}, + _nopchs(32), + _nvoxels(0), + _nvis(0) { std::cout << "[UBPhotonLib] Loaded" << std::endl; @@ -26,7 +30,18 @@ namespace ubphotonlib { _cryo_origin_tpc_coord_cm[i] = _cryo_global_origin_cm[i] - _tpc_global_origin_cm[i]; } std::cout << " Voxel Length per dim [" << _voxel_len_cm[0] << "," << _voxel_len_cm[1] << "," << _voxel_len_cm[2] << "]" << std::endl; + std::cout << " Cryostat voxel grid origin in TPC coords: (" + << _cryo_origin_tpc_coord_cm[0] << ", " + << _cryo_origin_tpc_coord_cm[1] << ", " + << _cryo_origin_tpc_coord_cm[2] << ")" + << std::endl; + std::cout << " Cryostat Max Coordinates: (" + << _cryo_origin_tpc_coord_cm[0]+_cryo_length_cm[0] << ", " + << _cryo_origin_tpc_coord_cm[1]+_cryo_length_cm[1] << ", " + << _cryo_origin_tpc_coord_cm[2]+_cryo_length_cm[2] << ")" + << std::endl; + std::string dat_folder = std::getenv("UBLARCVAPP_BASEDIR"); std::string photon_vis_path = dat_folder + "/ublarcvapp/UBPhotonLib/dat/uboone_photon_library_v6_70kV_EnhancedExtraTPCVis.root"; @@ -41,14 +56,55 @@ namespace ubphotonlib { vistree->SetBranchAddress("Voxel",&Voxel); vistree->SetBranchAddress("OpChannel",&OpChannel); vistree->SetBranchAddress("Visibility",&Visibility); + + auto t1 = std::chrono::high_resolution_clock::now(); + + //_voxelopchindex_v.resize(nentries); + std::cout << " Allocating memory for " << _nvoxels_dim[0] << "x" << _nvoxels_dim[1] << "x" << _nvoxels_dim[2] << "x" << _nopchs << std::endl; + _nvoxels = _nvoxels_dim[0]*_nvoxels_dim[1]*_nvoxels_dim[2]; + _nvis = _nvoxels*_nopchs; + _visibility_v.resize( _nvis, 0.0 ); + + std::vector vcoord(3,0); + long lindex = 0; for (size_t i=0; iGetEntry(i); - std::pair voxelkey( (long)Voxel, (int)OpChannel ); - _voxelopchindex_to_visibility[ voxelkey ] = Visibility; + //std::pair voxelkey( (long)Voxel, (int)OpChannel ); + //_voxelopchindex_to_visibility[ voxelkey ] = Visibility; + //_voxelopchindex_v[i].voxelid = (long)Voxel; + //_voxelopchindex_v[i].opchid = (int)OpChannel; + //_voxelopchindex_v[i].vis = Visibility; + //_voxel_to_vindex_v[ (long)Voxel ] = (long)i; + // need to slice the Voxel + + // copied from getvoxelcoords to maybe trigger vectorization + //std::vector voxcoord = getVoxelCoords( Voxel ); + // vcoord[0] = voxelid % _nvoxels_dim[0]; + // long ivox = voxelid-(long)vcoord[0]; + // vcoord[1] = ((ivox)/_nvoxels_dim[0]) % _nvoxels_dim[1]; + // vcoord[2] = ((ivox - vcoord[1]*_nvoxels_dim[0])/(_nvoxels_dim[1]*_nvoxels_dim[0])) % _nvoxels_dim[2]; + + //long lindex = getVisLibIndex( Voxel, OpChannel ); + // opchannel is almost certaintly what UB calls "OpDet" + lindex = Voxel*_nopchs + OpChannel; + + if ( i>0 && i%10000000==0 ) { + std::cout << " loading entry " << i << ":" + << " vis=" << Visibility + << " vox=" << Voxel + << " opdet=" << OpChannel + <<" lindex=" << lindex + << std::endl; + } + _visibility_v[lindex] = Visibility; } - - std::cout << " Loaded Visibility Info" << std::endl; + + auto t2 = std::chrono::high_resolution_clock::now(); + std::chrono::duration ms_double = t2 - t1; + double sec = ms_double.count()*0.001; + std::cout << " Loaded Visibility Info in " << sec << " secs" << std::endl; + } UBPhotonLib::~UBPhotonLib() @@ -70,53 +126,77 @@ namespace ubphotonlib { _ginstance = nullptr; } - std::vector UBPhotonLib::getVoxelDimIndices( const std::vector& pos ) + std::vector UBPhotonLib::getVoxelCoords( const std::vector& pos ) const { - std::vector iindex(3,0); + std::vector vcoord(3,0); for (int i=0; i<3; i++) { - iindex[i] = (int)((pos[i] - _cryo_origin_tpc_coord_cm[i])/_voxel_len_cm[i]); + vcoord[i] = (long) (pos[i] - _cryo_origin_tpc_coord_cm[i])/_voxel_len_cm[i]; } - return iindex; + return vcoord; + } + + std::vector UBPhotonLib::getVoxelCoords( long voxelid ) const + { + // taken from larsim/Simulation/PhotonVoxels.cxx + // std::vector ReturnVector; + // ReturnVector.resize(3); + // ReturnVector.at(0) = ID % fxSteps ; + // ReturnVector.at(1) = ((ID - ReturnVector.at(0) ) / fxSteps) % fySteps ; + // ReturnVector.at(2) = ((ID - ReturnVector.at(0) - (ReturnVector.at(1) * fxSteps)) / (fySteps * fxSteps)) % fzSteps ; + // return ReturnVector; + + std::vector vcoord(3,0); + + vcoord[0] = voxelid % _nvoxels_dim[0]; + long ivox = voxelid-(long)vcoord[0]; + vcoord[1] = ((ivox)/_nvoxels_dim[0]) % _nvoxels_dim[1]; + vcoord[2] = ((ivox - vcoord[1]*_nvoxels_dim[0])/(_nvoxels_dim[1]*_nvoxels_dim[0])) % _nvoxels_dim[2]; + return vcoord; + } + + long UBPhotonLib::getVisLibIndex( long voxelid, int opch ) const + { + return voxelid*_nopchs + opch; } - long UBPhotonLib::getVoxelIndex( const std::vector& pos ) + long UBPhotonLib::getVoxelID( const std::vector& voxcoords ) const { - std::vector iindex = getVoxelDimIndices( pos ); bool valid = true; for (int i=0; i<3; i++) { - if ( iindex[i]<0 || iindex[i]>=_nvoxels_dim[i] ) + if ( voxcoords[i]<0 || voxcoords[i]>=_nvoxels_dim[i] ) valid = false; } - if (!valid) return -1; + return voxcoords[0] + voxcoords[1]*_nvoxels_dim[0] + voxcoords[2]*_nvoxels_dim[1]*_nvoxels_dim[0]; + } + + long UBPhotonLib::getVisLibIndex( const std::vector& pos, int opch ) const + { + std::vector iindex = getVoxelCoords( pos ); + long voxelid = getVoxelID(iindex); + if (voxelid<0) + return -1; - long lindex = iindex[0]*_nvoxels_dim[1]*_nvoxels_dim[2] + iindex[1]*_nvoxels_dim[2] + iindex[2]; + long lindex = getVisLibIndex( voxelid, opch ); return lindex; } float UBPhotonLib::getVisibility( const std::vector& pos, int opch ) { - long lindex = getVoxelIndex( pos ); - if ( lindex<0 ) + long lindex = getVisLibIndex( pos, opch ); + if ( lindex<0 || lindex>(long)_visibility_v.size()) return 0.0; - std::pair voxopch_key( lindex, opch ); - auto it=_voxelopchindex_to_visibility.find( voxopch_key ); - if ( it==_voxelopchindex_to_visibility.end() ) { - // not found - return 0.0; - } - // return visibility - return it->second; + return _visibility_v[lindex]; } float UBPhotonLib::getVisibilityTrilinear( const std::vector& pos, int opch ) { - long lindex = getVoxelIndex( pos ); - if ( lindex<0 ) + long lindex = getVoxelIndex( pos, opch ); + if ( lindex<0 || lindex>(long)_visibility_v.size() ) return 0.0; std::pair voxopch_key( lindex, opch ); diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.h b/ublarcvapp/UBPhotonLib/UBPhotonLib.h index 3cb500c..d25c0be 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.h +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.h @@ -19,25 +19,61 @@ namespace ubphotonlib { static UBPhotonLib* getPhotonLib(); static void destroy(); ///< to free up memory - std::vector getVoxelDimIndices( const std::vector& pos ); - long getVoxelIndex( const std::vector& pos ); float getVisibility( const std::vector& pos, int opch ); - float getVisibilityTrilinear( const std::vector& pos, int opch ); + float getVisibilityTrilinear( const std::vector& pos, int opch ); + + std::vector getVoxelCoords( long voxelid ) const; + std::vector getVoxelCoords( const std::vector& pos ) const; + long getVisLibIndex( long voxelid, int opch ) const; + long getVoxelIndex( const std::vector& pos, int opch ) const; + long getVisLibIndex( const std::vector& pos, int opch ) const; + long getVoxelID( const std::vector& voxcoords ) const; + + struct VisData_t { + long voxelid; + long opchid; + int dim_index[3]; + float vis; + VisData_t() + : voxelid(0), + opchid(0), + dim_index{0,0,0}, + vis(0.0) + {}; + bool operator<( VisData_t& rhs ) const { + if (rhs.voxelid < voxelid ) + return true; + if ( rhs.voxelid==voxelid && rhs.opchid < opchid ) + return true; + return false; + }; + }; protected: UBPhotonLib(); virtual ~UBPhotonLib(); - + + float _tpc_global_origin_cm[3]; float _cryo_global_origin_cm[3]; float _cryo_length_cm[3]; int _nvoxels_dim[3]; float _voxel_len_cm[3]; - float _cryo_origin_tpc_coord_cm[3]; + float _cryo_origin_tpc_coord_cm[3]; + int _nopchs; + long _nvoxels; + long _nvis; std::map< std::pair , float > _voxelopchindex_to_visibility; + std::vector< VisData_t > _voxelopchindex_v; + std::map< long, long > _voxel_to_vindex_v; + + // fastest look up is a 4D matrix + // we'll use a 1D vector and execute strides + // will be a lot of zeros. But it's only double the memory. + std::vector _visibility_v; private: From 55a7f5e0b36456f29ea12ecea690ba72917c9d32 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 25 Jun 2024 12:04:17 -0400 Subject: [PATCH 42/80] add visualization of ubphotonlib output. fix cxx standard cmake error --- CMakeLists.txt | 6 +- ublarcvapp/UBPhotonLib/test/vis_photon_lib.py | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 ublarcvapp/UBPhotonLib/test/vis_photon_lib.py diff --git a/CMakeLists.txt b/CMakeLists.txt index fb77c86..5aa433e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,11 +17,11 @@ find_package(ROOT CONFIG REQUIRED) # we set the compiler version based on the one used for ROOT execute_process( COMMAND bash "-c" "root-config --features | awk '{print $1}'" - OUTPUT_VARIABLE ROOT_CXX_STANDARD ) -if (${ROOT_CXX_STANDARD} MATCHES "cxx17") + OUTPUT_VARIABLE TEST_ROOT_CXX_STANDARD ) +if (${TEST_ROOT_CXX_STANDARD} MATCHES "cxx17") message( STATUS "using cxx17") set(CMAKE_CXX_STANDARD 17) -elseif (${ROOT_CXX_STANDARD} MATCHES "cxx14") +elseif (${TEST_ROOT_CXX_STANDARD} MATCHES "cxx14") message( STATUS "using cxx14") set(CMAKE_CXX_STANDARD 14) else () diff --git a/ublarcvapp/UBPhotonLib/test/vis_photon_lib.py b/ublarcvapp/UBPhotonLib/test/vis_photon_lib.py new file mode 100644 index 0000000..0b4f32d --- /dev/null +++ b/ublarcvapp/UBPhotonLib/test/vis_photon_lib.py @@ -0,0 +1,67 @@ +import os,sys +import ROOT as rt +from ROOT import std +from ublarcvapp import ublarcvapp +import lardly +from lardly.ubdl.pmtpos import getPMTPosByOpChannel,getPMTPosByOpDet + +photlib = ublarcvapp.ubphotonlib.UBPhotonLib.getPhotonLib() +print(photlib) + +rt.gStyle.SetOptStat(0) + +def make_yz_hist( xslice, opch, histname="hvis2d_sliceyz", nbinsz=100, nbinsy=20 ): + + h2d = rt.TH2D( histname, "", nbinsz, 0, 1040.0, nbinsy, -120, 120 ) + pos = std.vector("float")(3) + for i in range(nbinsz): + print("get vis for z-bin[",i,"]") + for j in range(nbinsy): + pos[0] = xslice + pos[1] = h2d.GetYaxis().GetBinCenter(j+1) + pos[2] = h2d.GetXaxis().GetBinCenter(i+1) + vis = photlib.getVisibility( pos, opch ) + voxcoord = photlib.getVoxelCoords( pos ) + h2d.SetBinContent( i+1, j+1, vis ) + #print("get vis at pos=",pos," for opch=",opch," vis=",vis," voxcoord=",voxcoord) + return h2d + + +if __name__=="__main__": + + iopch = 15 + xpos = 50.0 + temp = rt.TFile("test.root","recreate") + h2d = make_yz_hist(xpos, iopch, nbinsz=200, nbinsy=40) + c = rt.TCanvas("c","c",2000,600) + c.Draw() + h2d.Draw("colz") + h2d.SetTitle("Photon Visibility vs. (y,z) with x=%.1f cm for OpDet=%d; z position (cm); y position (cm)"%(xpos,iopch)) + + # drop opchannel pos + opch_v = [] + opch_label_v = [] + for ich in range(32): + pos = getPMTPosByOpDet( ich, use_v4_geom=False ) + #pos = getPMTPosByOpChannel( ich, use_v4_geom=False ) + circ = rt.TEllipse( pos[2], pos[1], 15.2, 15.2 ) + circ.SetFillStyle(0) + oplabel = rt.TText(pos[2]-10.0,pos[1]-5.0,"%02d"%(ich)) + if ich==iopch: + circ.SetLineColor(rt.kRed) + oplabel.SetTextColor(rt.kRed) + circ.Draw() + + oplabel.Draw() + opch_v.append( circ ) + opch_label_v.append(oplabel) + tt = rt.TText(826.0, 99.0, "Labels are the OpDetID") + tt.Draw() + opch_label_v.append(tt) + circ.Draw() + + c.Update() + print("[Enter] to continue") + input() + + From 7afd567ec111592a5c5b9ad18dad5fded3311991 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 22 Jul 2024 16:01:29 -0400 Subject: [PATCH 43/80] finally fixed start point of electron and photon showers. photon especially requires more sophisticated analysis to get a good start point and way to measure detectability --- ublarcvapp/MCTools/CMakeLists.txt | 2 +- ublarcvapp/MCTools/MCPixelPGraph.cxx | 520 +- ublarcvapp/MCTools/MCPixelPGraph.h | 52 +- ublarcvapp/MCTools/MCPos2ImageUtils.cxx | 60 +- ublarcvapp/MCTools/MCPos2ImageUtils.h | 8 + ublarcvapp/MCTools/test/run_mcpixelpgraph.py | 221 +- .../info/UBPhotonLibraryPropagation_module.cc | 274 + .../info/microboonev12_nowires.gdml | 32816 ++++++++++++++++ 8 files changed, 33865 insertions(+), 88 deletions(-) mode change 100644 => 100755 ublarcvapp/MCTools/test/run_mcpixelpgraph.py create mode 100644 ublarcvapp/UBPhotonLib/info/UBPhotonLibraryPropagation_module.cc create mode 100644 ublarcvapp/UBPhotonLib/info/microboonev12_nowires.gdml diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index c318f90..d477e55 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -49,7 +49,7 @@ target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # Generate the shared library from the sources set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED}) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index f42e351..aa7793f 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -6,6 +6,7 @@ // larcv #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/DataFormatTypes.h" +#include "larcv/core/ROOTUtil/ROOTUtils.h" // larlite #include "larlite/DataFormat/mctrack.h" @@ -15,6 +16,9 @@ #include "larlite/LArUtil/Geometry.h" #include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +// ublarcvapp +#include "ublarcvapp/dbscan/DBScan.h" + #include "crossingPointsAnaMethods.h" #include "MCPos2ImageUtils.h" @@ -23,11 +27,12 @@ namespace mctools { void MCPixelPGraph::buildgraph( larcv::IOManager& iolcv, larlite::storage_manager& ioll ) { - - larcv::EventImage2D* ev_adc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, adc_tree ); - larcv::EventImage2D* ev_seg = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "segment" ); - larcv::EventImage2D* ev_ins = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "instance" ); - larcv::EventImage2D* ev_anc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "ancestor" ); + + ev_adc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, adc_tree ); + ev_seg = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "segment" ); + ev_ins = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "instance" ); + ev_anc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "ancestor" ); + larcv::EventImage2D* ev_larflow = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "larflow" ); if ( ev_adc->Image2DArray().size()==0 ) { throw std::runtime_error("No ADC images!"); @@ -43,15 +48,30 @@ namespace mctools { } - larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*) ioll.get_data( larlite::data::kMCTrack, "mcreco" ); - larlite::event_mcshower* ev_mcshower = (larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" ); - larlite::event_mctruth* ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); + ev_mctrack = (larlite::event_mctrack*) ioll.get_data( larlite::data::kMCTrack, "mcreco" ); + ev_mcshower = (larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" ); + ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); buildgraph( ev_adc->Image2DArray(), ev_seg->Image2DArray(), ev_ins->Image2DArray(), ev_anc->Image2DArray(), *ev_mcshower, *ev_mctrack, *ev_mctruth ); + + // next we fix photons + for ( auto& node : node_v ) { + if ( node.pid==22 ) { + std::vector startpt_info + = fixingPhotonStartPoints( node, + ev_ins->as_vector(), ev_anc->as_vector(), + ev_adc->as_vector(), ev_larflow->as_vector() ); + // update edep position of the node + for (int v=0; v<4; v++) { + node.first_edep_pos[v] = startpt_info[v]; + node.imgpos4_edep[v] = startpt_info[4+v]; + } + } + } } /** @@ -60,9 +80,10 @@ namespace mctools { */ void MCPixelPGraph::buildgraphonly( larlite::storage_manager& ioll ) { - larlite::event_mctrack* ev_mctrack = (larlite::event_mctrack*) ioll.get_data( larlite::data::kMCTrack, "mcreco" ); - larlite::event_mcshower* ev_mcshower = (larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" ); - larlite::event_mctruth* ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); + + ev_mctrack = (larlite::event_mctrack*) ioll.get_data( larlite::data::kMCTrack, "mcreco" ); + ev_mcshower = (larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" ); + ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); buildgraphonly( *ev_mcshower, *ev_mctrack, *ev_mctruth ); @@ -82,6 +103,8 @@ namespace mctools { const larlite::event_mctruth& mctruth_v ) { + clear(); + buildgraphonly( shower_v, track_v, mctruth_v ); // fill the daugher to mother shower ID map @@ -125,6 +148,8 @@ namespace mctools { // } // } + clear(); + node_v.clear(); node_v.reserve( shower_v.size()+track_v.size() ); @@ -213,10 +238,17 @@ namespace mctools { // set start position. // try to move it into the tpc first - tracknode.imgpos4 = std::vector(4,0); tracknode.first_edep_pos = std::vector(4,0); tracknode.first_tpc_pos = std::vector(4,0); tracknode.first_img_pos = std::vector(4,0); + tracknode.imgpos4 = std::vector(4,0); + tracknode.imgpos4_edep = std::vector(4,0); + tracknode.imgpos4_start = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( tracknode.start[0], + tracknode.start[1], + tracknode.start[2], + tracknode.start[3], + true ); + if ( mct.size()>=1 ) { tracknode.first_edep_pos[0] = mct[0].X(); @@ -225,14 +257,23 @@ namespace mctools { tracknode.first_edep_pos[3] = mct[0].T(); // first TPC point - std::vector recopos(4,0); + std::vector recopos(4,0); + std::vector edep_imgpos(4,0); std::vector xyz(4,0); bool intpc = false; + bool inimage = false; + bool first_step = false; for (auto const& step : mct ) { xyz[0] = (float)step.X(); xyz[1] = (float)step.Y(); xyz[2] = (float)step.Z(); xyz[3] = (float)step.T(); + + if ( !first_step ) { + first_step = true; + tracknode.first_edep_pos = xyz; + } + if ( ( xyz[0]>0.0 && xyz[0]0 && xyz[2]truepos_to_recopos( xyz[0], xyz[1], xyz[2], xyz[3], true, true ); - float tick = recopos[3]; - - if ( tick>2400 && tick<3200+1008) { + recopos = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( xyz[0], xyz[1], xyz[2], xyz[3], true ); + if ( !inimage && recopos[3]>2400.0 && recopos[3]<2400+1008*6 ) { + // in the image + inimage = true; tracknode.first_img_pos = xyz; tracknode.imgpos4 = recopos; - break; + tracknode.imgpos4_edep = recopos; } } + if ( intpc && inimage ) { + // no need to keep searching + break; + } }//end of mcstep loop }//end of if more than 0 mcsteps @@ -283,13 +328,60 @@ namespace mctools { showernode.first_tpc_pos = std::vector(4,0); showernode.first_img_pos = std::vector(4,0); showernode.imgpos4 = std::vector(4,0); - - if ( !std::isinf( mcsh.DetProfile().X() ) && !std::isnan( mcsh.DetProfile().X() ) ) { + showernode.imgpos4_edep = std::vector(4,0); + showernode.imgpos4_start = std::vector(4,0); + + bool x_isinf = false; + if ( mcsh.DetProfile().X()>1.0e100 || mcsh.DetProfile().X()<-1.0e100 ) + x_isinf = true; + if ( !x_isinf && !std::isnan( mcsh.DetProfile().X() ) ) { + std::cout << "inf test: " << mcsh.DetProfile().X() << " " << std::isinf( mcsh.DetProfile().X() ) << std::endl; std::vector detprofile = { (float)mcsh.DetProfile().X(), (float)mcsh.DetProfile().Y(), (float)mcsh.DetProfile().Z(), (float)mcsh.DetProfile().T() }; showernode.first_edep_pos = detprofile; showernode.first_tpc_pos = detprofile; showernode.first_img_pos = detprofile; - _get_imgpos( detprofile, showernode.imgpos4, sce, false ); + //_get_imgpos( detprofile, showernode.imgpos4, sce, false ); + showernode.imgpos4 = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.first_edep_pos[0], + showernode.first_edep_pos[1], + showernode.first_edep_pos[2], + showernode.first_edep_pos[3], + true ); + if ( showernode.imgpos4.size()==0 ) + showernode.imgpos4.resize(4,0); + + if ( abs(showernode.pid)==11 ) { + showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], + showernode.start[1], + showernode.start[2], + showernode.start[3], + true ); + if ( showernode.imgpos4_edep.size()==0 ) + showernode.imgpos4_edep.resize(4,0); + + showernode.first_edep_pos = showernode.start; + } + else { + // photons + showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->to_imagepos( showernode.first_edep_pos[0], + showernode.first_edep_pos[1], + showernode.first_edep_pos[2], + showernode.first_edep_pos[3] ); + if ( showernode.imgpos4_edep.size()==0 ) { + showernode.imgpos4_edep.resize(4,0); + } + else { + showernode.imgpos4_edep[3] += 12.0; // hacky fix for photons + } + } + + showernode.imgpos4_start = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], + showernode.start[1], + showernode.start[2], + showernode.start[3], + true ); + if ( showernode.imgpos4_start.size()==0 ) { + showernode.imgpos4_start.resize(4,0); + } } if ( showernode.origin==1 ) { @@ -563,7 +655,12 @@ namespace mctools { /** - * locate Node_t in node_v using trackid (from geant4) + * @brief locate Node_t in node_v using trackid (from geant4) + * + * we first search our vector of Node_t objects, which are sorted by track id. + * + * we then search the keys of the _shower_daughter2mother map, where the keys + * are track id of particles made by the initial shower. * * @return The node if found, nullptr if not found * @@ -584,7 +681,7 @@ namespace mctools { // still nope return nullptr; } - // try again + // with the mother shower's trackid, try to find the node again it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); if ( it!=node_v.end() ) LARCV_DEBUG() << " mother id maps to existing node" << std::endl; @@ -628,20 +725,37 @@ namespace mctools { << " aid=" << node.aid << " pdg=" << node.pid << " KE=" << node.E_MeV << " MeV" - //<< " xyzt=(" << node.start[0] << "," << node.start[1] << "," << node.start[2] << "," << node.start[3]*1.0e-3 << " us)" - << " imgpos=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << " tick)" - << " tusec=" << node.start[3]*1.0e-3 << " us" + //<< " xyzt= + //<< " tusec=" << node.start[3]*1.0e-3 << " us" //<< " (mid,mother)=(" << node.mid << "," << node.mother << ") " //<< " (mid,mother)=(" << node.mid << ") " << " hasmother=" << hasmother << " ndaughters=" << node.daughter_v.size() - << " npixs=("; + << std::endl; + // additional positional info + if ( node.start.size()>=4 ) + ss << " start(x,y,z,t)=(" << node.start[0] << "," << node.start[1] << "," << node.start[2] << "," << node.start[3]*1.0e-3 << " us) " << std::endl; + + if ( node.first_edep_pos.size()>=4 ) + ss << " edep-tpcpos(x,y,z,t)=(" << node.first_edep_pos[0] << "," + << node.first_edep_pos[1] << "," + << node.first_edep_pos[2] << "," + << node.first_edep_pos[3]*1.0e-3 + << " us)" << std::endl; + + if ( node.imgpos4.size()>=4 ) + ss << " tpc-imgpos4(u,v,y,tick)=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << " tick) " << std::endl; + + if (node.imgpos4_edep.size()>=4) + ss << " edep-imgpos4(u,v,y,tick)=(" << node.imgpos4_edep[0] << "," << node.imgpos4_edep[1] << "," << node.imgpos4_edep[2] << "," << node.imgpos4_edep[3] << " tick) " << std::endl; + + ss << " npixs=("; for ( size_t i=0; i& adc_v, @@ -738,6 +852,7 @@ namespace mctools { for ( size_t p=0; p<_nplanes; p++ ) { _unassigned_pixels_vv[p].clear(); + int num_neg_shower_ids = 0; auto const& meta = adc_v[p].meta(); const float threshold = threshold_v[p]; @@ -755,10 +870,11 @@ namespace mctools { std::cerr << __FILE__ << ":L" << __LINE__ << " error getting ADC pixel (" << r << "," << c << ")" << std::endl; continue; } - if ( adc=threshold ) + nabove_thresh[p]++; // above threshold, now lets find instance or ancestor int tid = 0; @@ -787,36 +903,52 @@ namespace mctools { continue; } - if ( tid<0 && (seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma) ) + // shower pixels have a negative track ID for some reason + // does this always occur? + if ( tid<0 && (seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma) ) { tid *= -1; + num_neg_shower_ids++; + } - if ( tid>0 || aid>0 ) + bool has_id_label = false; + if ( tid>0 || aid>0 ) { nabove_thresh_withlabel[p]++; - - if ( seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma ) { + has_id_label = true; + } + + if ( aid>0 && (seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma) ) { shower_ancestor_ids.insert( aid ); } + if ( !has_id_label ) { + // can't truth associate this pixel to any node + continue; + } + Node_t* node = nullptr; if ( tid>0 ) { - // first we use the instance ID + // first we use the instance ID + // this implicitly uses the _shower_daughter2mother map we filled earlier. node = findTrackID( tid ); if ( node==nullptr && adc>10.0 ) - LARCV_DEBUG() << " no node for charge-pixel tid=" << tid << std::endl; + LARCV_DEBUG() << " no node for above threshold charge-pixel tid=" << tid << std::endl; // if ( node && node->tid!=tid ) // node = nullptr; // reset (what's this?) } // use ancestor if we could not find the node if ( !node && aid>0 ) { + // this implicitly uses the _shower_daughter2mother map we filled earlier. node = findTrackID( aid ); if ( node && node->tid!=aid ) node = nullptr; } if ( node ) { - + // if the address is not null, this means we found a particle node + // store the pixel. + // if ( node->tid!=tid && node->aid!=aid ) { // std::cout << "pixel assigned without matching tid or aid exactly: " // << " pix-tid=" << tid << " pix-aid=" << aid @@ -838,7 +970,7 @@ namespace mctools { }//end of loop over planes - // no make bounding boxes + // now make bounding boxes for ( auto& node : node_v ) { node.plane_bbox_twHW_vv.clear(); node.plane_bbox_twHW_vv.resize(_nplanes); @@ -890,7 +1022,7 @@ namespace mctools { } /** - * get pixels associated with node and its descendents + * @brief get pixels associated with node and its descendents * */ std::vector< std::vector > MCPixelPGraph::getPixelsFromParticleAndDaughters( int trackid ) { @@ -1016,8 +1148,6 @@ namespace mctools { dpos[i] = realpos4[i]; } - - std::vector txyz(4,0); if ( apply_sce ) { std::vector offset = sce.GetPosOffsets( dpos[0], dpos[1], dpos[2] ); @@ -1025,7 +1155,6 @@ namespace mctools { dpos[1] = dpos[1] + offset[1]; dpos[2] = dpos[2] + offset[2]; } - for (int i=0; i<3; i++) { txyz[1+i] = realpos4[i]; @@ -1047,6 +1176,16 @@ namespace mctools { } + /** + * @brief makes a map from daughter track IDs to their mother (shower) track ID + * + * The info comes from the MCShowerObjecs themselves. They store daughter IDs + * in a vector accessed by mcshower::DaughterTrackID(). + * + * This map will let us map the track ids stored in each pixel of the + * the instance ID map to its original shower. + * + */ void MCPixelPGraph::_fill_shower_daughter2mother_map( const std::vector& mcsh_v ) { LARCV_DEBUG() << "daughter2mother fill" << std::endl; @@ -1442,6 +1581,297 @@ namespace mctools { }//end of loop over nodes }//end of adopt orphans + + std::vector MCPixelPGraph::makeTH2D( std::string hist_stem_name ) + { + // first get wire image into th2d + std::vector< TH2D > hist_v; + if ( ev_adc==nullptr ) + return hist_v; + + for ( auto& pmarker : vis_markers_v ) { + delete pmarker; + }; + vis_markers_v.clear(); + + for ( auto& plabel : vis_label_v ) { + delete plabel; + } + vis_label_v.clear(); + + if ( !cvis ) { + cvis = new TCanvas("cmcpg","MCPixel PGraph Canvas",800,2400); + cvis->Divide(1,3); + } + + hist_v = larcv::rootutils::as_th2d_v( ev_adc->as_vector(), hist_stem_name ); + + // label the nodes + for (auto& node : node_v ) { + + for (int p=0; p<(int)hist_v.size(); p++) { + cvis->cd(p+1); + auto& hist = hist_v.at(p); + //auto& meta = ev_adc->as_vector().at(p).meta(); + std::cout << "Draw marker for node[" << node.nodeidx << "]-plane[" << p << "] wire=" << node.imgpos4_edep[p] << " tick=" << node.imgpos4_edep[3] << std::endl; + TMarker* m = new TMarker( node.imgpos4_edep[p], node.imgpos4_edep[3], 20 ); + //m->SetMarkerSize(3); + m->SetMarkerColor(kMagenta); + hist.Draw("colz"); + m->Draw(); + vis_markers_v.push_back( m ); + } + + } + cvis->Update(); + //std::cout << "[enter] to continue" << std::endl; + //std::cin.get(); + return hist_v; + } + + /** + * @brief Fix the location of where the start starts depositing energy + * + */ + std::vector MCPixelPGraph::fixingPhotonStartPoints( Node_t& node, + const std::vector& instance_v, + const std::vector& ancestor_v, + const std::vector& adc_v, + const std::vector& larflow_v ) + { + + // start of photon shower is not something accurately specified in the mcreco + // products. detprofile is provided in mcshower -- but i think its basically trash. + // instead we will use the instanceid + larflow truth to + // (1) build 3d spacepoints + // (2) find the closest spacepoint with evidence for ~MIP level deposits + // (3) place the position there + // the profile also provides a momentum, but I bet its garbage + + // this is only for photons (electrons have a good start point based on node.start) + std::vector shower_start_pt; + + if ( node.pid!=22) + return shower_start_pt; + + // we must collect and scan the instance IDs related to the shower + int shower_aid = node.aid; + int shower_mid = node.mid; + int shower_tid = node.tid; + + // we want to make 3d points from the pixels we have for the shower. + struct flowpt { + int source_plane; + int source_wire; + int target_plane; + int target_wire; + int source_trackid; + int target_trackid; + float src_pixval; + float pos[3]; + int posid[3]; + bool operator<( const flowpt& rhs ) const { + if (posid[0]rhs.posid[0]) + return false; + // neither so [0] must be equal + + if (posid[1]rhs.posid[1]) + return false; + + // neither [1] worked, so must be equal + if (posid[2] pt_v; + + for (size_t p=0; p start_reco_pt = MCPos2ImageUtils::Get()->truepos_to_recopos( node.start[0], + node.start[1], + node.start[2], + node.start[3], + true, true ); + std::cout << " Find closest to start point: (" << start_reco_pt[0] << "," + << start_reco_pt[1] << ", " + << start_reco_pt[2] << ", " + << start_reco_pt[3] << " usec)" + << std::endl; + + shower_start_pt.resize(4); + + std::vector< std::vector > data_v; + + for ( auto& pt : pt_v ) { + std::cout << "3d pt: (" << pt.pos[0] << ", " << pt.pos[1] << ", " << pt.pos[2] << ") " + << " src_pixval=" << pt.src_pixval + << " src_plane=" << pt.source_plane + << std::endl; + + float dist_edep = 0.; + float dx = 0.; + for (int v=0; v<3; v++) { + dx = pt.pos[v] - node.first_edep_pos[v]; + dist_edep += dx*dx; + } + dist_edep = sqrt(dist_edep); + + // if ( dist_edep>photon_start_edep_radius_cm || pt.src_pixval xpt(3,0); + for (int v=0; v<3; v++) + xpt[v] = pt.pos[v]; + data_v.push_back( xpt ); + + } + + auto dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( 0.3, 3, 50, data_v ); + int nlargest = 0; + int icluster = -1; + for (int i=0; i<(int)dbcluster_v.size(); i++) { + int nhits = dbcluster_v.at(i).size(); + if ( (int)nhits>nlargest && (int)nhits>=photon_start_min_cluster_size ) { + nlargest = nhits; + icluster = i; + } + } + + if ( icluster<0 ) { + shower_start_pt = node.first_edep_pos; + } + else { + auto& largest_cluster = dbcluster_v.at(icluster); + for (int ipt=0; ipt<(int)largest_cluster.size(); ipt++) { + auto& xpt = data_v.at( largest_cluster.at(ipt) ); + float dist = 0; + for (int v=0; v<3; v++) { + float dx = xpt[v]-start_reco_pt[v]; + dist += dx*dx; + } + dist = sqrt(dist); + if ( distDriftVelocity()) + 3200; + mindist = dist; + } + } + } + + std::cout << " minimum dist to shower startpt: " << mindist << " cm" << std::endl; + std::cout << " startpt: (" << shower_start_pt[0] << "," + << shower_start_pt[1] << "," + << shower_start_pt[2] << "," + << shower_start_pt[3] << " ticks)" + << std::endl; + + float t_ns = (shower_start_pt[3]-3200)*0.5*1000.0+3050.0; // ticks to ns + std::vector shower_imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( shower_start_pt[0], + shower_start_pt[1], + shower_start_pt[2], + t_ns ); + std::cout << " imgpos: (" << shower_imgpos4[0] << ", " + << shower_imgpos4[1] << ", " + << shower_imgpos4[2] << ", " + << shower_imgpos4[3] << " ticks )" + << std::endl; + + for (int v=0; v<4; v++) + shower_start_pt.push_back( shower_imgpos4[v] ); + + return shower_start_pt; + + } } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index b2e2eb7..5f2dbbc 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -7,6 +7,7 @@ #include "larcv/core/Base/larcv_base.h" #include "larcv/core/DataFormat/IOManager.h" #include "larcv/core/DataFormat/Image2D.h" +#include "larcv/core/DataFormat/EventImage2D.h" // larlite #include "larlite/DataFormat/storage_manager.h" @@ -14,6 +15,12 @@ #include "larlite/DataFormat/mctrack.h" #include "larlite/LArUtil/SpaceChargeMicroBooNE.h" +// ROOT +#include "TH2D.h" +#include "TText.h" +#include "TMarker.h" +#include "TCanvas.h" + /** * Determine particle graph. Collect pixels for each particle. * In particular, handle the showers. @@ -32,9 +39,20 @@ namespace mctools { _unassigned_pixels_vv(), _eventRootNode(nullptr), _nplanes(3), + photon_start_edep_radius_cm(10.0), + photon_start_pixval_threshold(30.0), + photon_start_min_cluster_size(10), + ev_mctrack(nullptr), + ev_mcshower(nullptr), + ev_mctruth(nullptr), + ev_adc(nullptr), + ev_seg(nullptr), + ev_ins(nullptr), + ev_anc(nullptr), _kNuVertexDistCutoff_cm(0.3), _nu_vertices_v(), _cluster_neutrino_particles(false), + cvis(nullptr), _shower_daughter2mother(), adc_tree("wire") {}; @@ -79,6 +97,8 @@ namespace mctools { std::vector first_tpc_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image std::vector first_img_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image std::vector imgpos4; //< (x,y,z,tick) after sce // the image position corresponding to first_tpc_pos + std::vector imgpos4_edep; //< (x,y,z,tick) after sce // the image position corresponding to the first_edep_pos + std::vector imgpos4_start; //< (x,y,z,tick) after sce // the image position corresponding to the start pos after SCE std::vector< std::vector > plane_bbox_twHW_vv; /// bounding box for pixels in each plane int origin; // 1=neutrino, 2=cosmic, 0=unassigned, -1=unassigned @@ -98,7 +118,9 @@ namespace mctools { first_edep_pos({0,0,0,0}), first_tpc_pos({0,0,0,0}), first_img_pos({0,0,0,0}), - imgpos4({0,0,0,0}), + imgpos4({0,0,0,0}), + imgpos4_edep({0,0,0,0}), + imgpos4_start({0,0,0,0}), origin(-1) { daughter_v.clear(); @@ -126,6 +148,8 @@ namespace mctools { first_tpc_pos({0,0,0,0}), first_img_pos({0,0,0,0}), imgpos4({0,0,0,0}), + imgpos4_edep({0,0,0,0}), + imgpos4_start({0,0,0,0}), origin(-1) {}; @@ -189,11 +213,32 @@ namespace mctools { std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons=true ); std::vector getNeutrinoParticles( bool exclude_neutrons=true ); + // make visualization of nu particles + std::vector< TH2D > makeTH2D( std::string hist_stem_name ); + + float photon_start_edep_radius_cm; + float photon_start_pixval_threshold; + int photon_start_min_cluster_size; + + std::vector fixingPhotonStartPoints( Node_t& node, + const std::vector& instance_v, + const std::vector& ancestor_v, + const std::vector& adc_v, + const std::vector& larflow_v ); + // clear the state void clear(); protected: + + larlite::event_mctrack* ev_mctrack; + larlite::event_mcshower* ev_mcshower; + larlite::event_mctruth* ev_mctruth; + larcv::EventImage2D* ev_adc; + larcv::EventImage2D* ev_seg; + larcv::EventImage2D* ev_ins; + larcv::EventImage2D* ev_anc; void _recursivePrintGraph( Node_t* node, int& depth, bool visible_only=true ); void _scanPixelData( const std::vector& adc_v, @@ -220,6 +265,11 @@ namespace mctools { bool _cluster_neutrino_particles; int _define_neutrino_interaction_nodes( larlite::storage_manager& ioll ); int _define_neutrino_interaction_nodes( const larlite::event_mctrack& ev_track_v, const larlite::event_mcshower& ev_shower_v ); + + // visualization + TCanvas* cvis; + std::vector< TMarker* > vis_markers_v; + std::vector< TText* > vis_label_v; public: diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx index f750919..a52856b 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx @@ -35,13 +35,13 @@ namespace mctools { { float v_cm_per_us = ::larutil::LArProperties::GetME()->DriftVelocity(); - float ticks_per_us = (::larutil::DetectorProperties::GetME()->SamplingRate()*1.0e-3); // value return is in MHz, convert to usec + float us_per_tick = (::larutil::DetectorProperties::GetME()->SamplingRate()*1.0e-3); // value return is in MHz, convert to usec float trig_g4time_ns = 4050.0; float dx_trigger_cm = 0.0; // std::cout << "v_cm_per_us: " << v_cm_per_us << std::endl; - // std::cout << "ticks_per_us: " << ticks_per_us << std::endl; - + // std::cout << "us_per_tick: " << us_per_tick << std::endl; + std::vector pos_sce = { x_cm, y_cm, z_cm }; if ( apply_sce ) { pos_sce = get_sce_shifted_pos( x_cm, y_cm, z_cm ); @@ -57,7 +57,7 @@ namespace mctools { // append the tick the charge should appear at //float tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( reco_pos[0], 0 ); // this is busted - float tickx = reco_pos[0]/v_cm_per_us*ticks_per_us + 3200.0; + float tickx = (reco_pos[0])/v_cm_per_us/us_per_tick + 3200.0; //std::cout << "tick=" << tick << " vs " << tickx << std::endl; reco_pos.push_back( tickx ); @@ -86,6 +86,58 @@ namespace mctools { return out; } + std::vector MCPos2ImageUtils::to_imagepos( const float x, const float y, const float z, const float t_ns ) + { + + float v_cm_per_us = ::larutil::LArProperties::GetME()->DriftVelocity(); + float us_per_tick = (::larutil::DetectorProperties::GetME()->SamplingRate()*1.0e-3); // value return is in MHz, convert to usec + + TVector3 vpos; + vpos[0] = x; + vpos[1] = y; + vpos[2] = z; + //std::cout << "vpos: " << vpos[0] << " " << vpos[1] << " " << vpos[2] << std::endl; + + std::vector imgpos(4,0); + if ( std::fabs(vpos[1])>116.5 || vpos[2]<0.0 && vpos[2]>1036.0 ) + return imgpos; + + for (int p=0; p<3; p++) { + float wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + imgpos[p] = wire; + } + float tickx = vpos[0]/v_cm_per_us/us_per_tick + 3200.0; + imgpos[3] = tickx; + + return imgpos; + } + + std::vector MCPos2ImageUtils::truepos_to_imagepos( const float x, const float y, const float z, + const float t_ns, bool apply_sce ) + { + std::vector recopos = truepos_to_recopos( x, y, z, t_ns, true, apply_sce ); + TVector3 vpos; + vpos[0] = recopos[0]; + vpos[1] = recopos[1]; + vpos[2] = recopos[2]; + //std::cout << "vpos: " << vpos[0] << " " << vpos[1] << " " << vpos[2] << std::endl; + + std::vector imgpos(4,0); + if ( std::fabs(vpos[1])>116.5 || vpos[2]<0.0 || vpos[2]>1036.0 ) + return imgpos; + + imgpos[3] = recopos[3]; // should be the tick + + //const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; + //float tick = ( recopos[3]-4.050 )/0.5 + recopos[0]/cm_per_tick + 3200.0; + for (int p=0; p<3; p++) { + float wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + imgpos[p] = wire; + } + + return imgpos; + } + diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.h b/ublarcvapp/MCTools/MCPos2ImageUtils.h index d3619c0..a5ba885 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.h +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.h @@ -4,6 +4,7 @@ #include #include "larcv/core/Base/larcv_base.h" +#include "larcv/core/DataFormat/ImageMeta.h" #include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "larlite/DataFormat/mctrack.h" @@ -63,6 +64,13 @@ namespace mctools { get_sce_shifted_pos( const float x, const float y, const float z ); + std::vector + truepos_to_imagepos( const float x, const float y, const float z, + const float t_ns, bool apply_sce ); + + std::vector + to_imagepos( const float x, const float y, const float z, const float t_ns ); + larutil::SpaceChargeMicroBooNE* psce; private: diff --git a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py old mode 100644 new mode 100755 index 5bae67b..2d2526a --- a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py +++ b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py @@ -1,3 +1,4 @@ +#!/bin/env python3 from __future__ import print_function import os,sys,argparse @@ -7,6 +8,9 @@ parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") parser.add_argument("-d", "--debug", action='store_true', default=False, help="Run in debug mode") +parser.add_argument('-n', "--nentries", required=False, type=int, default=-1, help="number of entries to run") +parser.add_argument('-e', "--entry", required=False, type=int, default=-1, help="start at given entry number") +parser.add_argument('-v', "--vis", required=False, default=False, action='store_true', help="if flag provided, will visualize event") args = parser.parse_args() import ROOT as rt @@ -40,9 +44,21 @@ else: HAS_LARCV = False -nentries = ioll.get_entries() -print("Number of entries: ",nentries) -#nentries = 10 +print("HAS LARCV: ",HAS_LARCV) +tot_nentries = ioll.get_entries() +start_entry = 0 +print("Number of entries: ",tot_nentries) +if args.entry > 0: + start_entry = args.entry +if args.nentries>0: + nentries = args.nentries +else: + nentries = tot_nentries +end_entry = start_entry + nentries +if end_entry>tot_nentries: + end_entry = tot_nentries + + print("Start loop.") @@ -60,13 +76,13 @@ if HAS_LARCV: tmp = rt.TFile("temp.root","recreate") - c = rt.TCanvas("c","c",1200,1800) - c.Divide(1,3) + c = rt.TCanvas("c","c",2100,1500) + c.Divide(3,3) -print("[ENTER to Start") -input() +#print("[ENTER] to Start") +#input() -for ientry in range( nentries ): +for ientry in range( start_entry, end_entry ): print() print("==========================") @@ -77,47 +93,178 @@ mcpg_nu.clear() mcpg.set_cluster_neutrino_particles(False) mcpg_nu.set_cluster_neutrino_particles(True) - - if HAS_LARCV: + + if not HAS_LARCV: + mcpg.buildgraphonly( ioll ) + mcpg_nu.buildgraphonly( ioll ) + else: + print("HAS_LARCV: get images needed for pixel matching to particles") + #mcpg.buildgraphonly( ioll ) iolcv.read_entry(ientry) ev_adc = iolcv.get_data( larcv.kProductImage2D, args.adc ) + ev_instance = iolcv.get_data( larcv.kProductImage2D, "instance" ) + ev_ancestor = iolcv.get_data( larcv.kProductImage2D, "ancestor" ) + ev_segment = iolcv.get_data( larcv.kProductImage2D, "segment" ) + ev_larflow = iolcv.get_data( larcv.kProductImage2D, "larflow" ) print("number of images: ",ev_adc.Image2DArray().size()) adc_v = ev_adc.Image2DArray() + mcpg_nu.buildgraph( iolcv, ioll ) for p in range(adc_v.size()): print(" image[",p,"] ",adc_v[p].meta().dump()) + + + photon_starts = {} + if HAS_LARCV and False: + for i in range(mcpg_nu.node_v.size()): + node = mcpg_nu.node_v.at(i) + if node.pid!=22: + continue; + print("running fixingPhotonStartPoints(...) for photons") + gamma_start = mcpg_nu.fixingPhotonStartPoints( node, + ev_instance.as_vector(), + ev_ancestor.as_vector(), + ev_adc.as_vector(), + ev_larflow.as_vector() ) + photon_starts[node.tid] = gamma_start + + ## isolate events + stop = False + for inode in range(mcpg_nu.node_v.size()): + node = mcpg_nu.node_v.at(inode) + if node.pid in [22]: + npixsum = 0 + for p in range(node.pix_vv.size()): + npixsum += node.pix_vv[p].size() + if npixsum>1: + stop=True + print("STOP TO VISUALIZE/DUMP MCPG INFO: ",stop) + if not stop: + continue + + if args.debug or args.vis: + if not HAS_LARCV: + print("================================================") + print("PARSING PARTICLE GRAPH ONLY: No pixel matching ") + print("================================================") + print("ALL NODE INFO [NO NU] --------------------------") + mcpg.printAllNodeInfo() + print(" -----------------------------------------------") + print("CONSTRUCTED PARTICLE GRAPH [NO NU]") + mcpg.printGraph(0,False) + print("====================================================") + else: + #print("================================================") + #print("PARSING PARTICLE GRAPH ONLY: No pixel matching ") + #print("================================================") + #print("CONSTRUCTED PARTICLE GRAPH [NO NU]") + #mcpg.printGraph(0,False) + #print("====================================================") + + print("====================================================") + print("CONSTRUCTED PARTICLE GRAPH [WITH NU VERTEX GROUPING]") + mcpg_nu.printGraph(0,False) + print("====================================================") + # make histogram - hist_v = larcv.rootutils.as_th2d_v( adc_v, "hentry%d"%(ientry) ) - for ih in range(adc_v.size()): + marker_v = [] + #hist_v = mcpg_nu.makeTH2D( "hentry%d"%(ientry) ) + hist_v = larcv.rootutils.as_th2d_v( ev_adc.as_vector(), "hentry%d"%(ientry) ) + segment_v = larcv.rootutils.as_th2d_v( ev_segment.as_vector(), "hsegment%d"%(ientry)) + instance_v = larcv.rootutils.as_th2d_v( ev_instance.as_vector(), "hinstance%d"%(ientry)) + ancestor_v = larcv.rootutils.as_th2d_v( ev_ancestor.as_vector(), "hancestor%d"%(ientry)) + + c.cd() + c.Draw() + c.Update() + for ih in range(hist_v.size()): + c.cd(3*ih+0+1) h = hist_v[ih] - h.GetZaxis().SetRangeUser(0,100) + h.Draw("colz") + h.GetZaxis().SetRangeUser(0,300) - mcpg.buildgraph( iolcv, ioll ) - else: - mcpg.buildgraphonly( ioll ) - mcpg_nu.buildgraphonly( ioll ) + for i in range(mcpg_nu.node_v.size()): + node = mcpg_nu.node_v.at(i) + if node.pid not in [22,11,-11]: + continue + + x = node.imgpos4_edep[ih] + y = node.imgpos4_edep[3] + #print("nodeidx=",node.nodeidx," pid=",node.pid," (x,y)=",(x,y)) + m = rt.TMarker( x, y, 4 ) + m.SetNDC(False) + m.SetMarkerColor(rt.kMagenta) + m.Draw() + marker_v.append(m) - if args.debug: - print("ALL NODE INFO [NO NU]======================================") - mcpg.printAllNodeInfo() - print("====================================================") - print("CONSTRUCTED PARTICLE GRAPH [NO NU]") - mcpg.printGraph(0,False) - print("====================================================") - print("====================================================") - print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") - print("====================================================") - - print("====================================================") - print("ALL NODE INFO [WITH NU VERTEX GROUPING]======================================") - mcpg_nu.printAllNodeInfo() - print("====================================================") - print("CONSTRUCTED PARTICLE GRAPH [WITH NU VERTEX GROUPING]") - mcpg_nu.printGraph(0,False) - print("====================================================") + if node.tid in photon_starts: + x2 = photon_starts[node.tid][4+ih] + y2 = photon_starts[node.tid][4+3] + m2 = rt.TMarker( x2, y2, 4 ) + m2.SetNDC(False) + m2.SetMarkerColor(rt.kRed) + m2.Draw() + marker_v.append(m2) + + x4 = node.imgpos4_start[ih] + y4 = node.imgpos4_start[3] + m4 = rt.TMarker( x4, y4, 5 ) + m4.SetNDC(False) + m4.SetMarkerSize(3) + m4.SetMarkerColor(rt.kBlack) + #print("x4: ",(x4,y4)) + m4.Draw() + marker_v.append(m4) + + #if ih==2: + # print("DUMP PIXELS [plane=2] for node.nodeidx=",node.nodeidx," trackid=",node.tid," pid=",node.pid) + pix_v = node.pix_vv.at(ih) + npix = int(pix_v.size()/2) + for ipix in range(npix): + xbin = int(pix_v.at(2*ipix+1)) + ybin = int((pix_v.at(2*ipix)-2400)/6.0) + #if ih==2: + # print(" ipix[",ipix,"]: (xbin,ybin)=",(xbin,ybin)," (wire,tick)=",(pix_v.at(2*ipix+1),pix_v.at(2*ipix))) + ancestor_v[ih].SetBinContent( xbin+1, ybin+1, node.tid ) + + c.cd(3*ih+1+1) + #instance_v[ih].SetTitle("instance plane[%d]"%(ih)) + #instance_v[ih].Draw("colz") + segment_v[ih].SetTitle("segment plane[%d]"%(ih)) + segment_v[ih].Draw("colz") + c.cd(3*ih+2+1) + ancestor_v[ih].SetTitle("ancestor plane[%d]"%(ih)) + ancestor_v[ih].Draw("colz") + + c.Update() + # end of loop + c.Update() + + # draw individual showers + cpart = [] + for inode in range(mcpg_nu.node_v.size()): + node = mcpg_nu.node_v.at(inode) + if node.pid not in [22]: + continue + print("Make canvas of particle, tid=",node.tid) + meta = ev_adc.as_vector().at(2).meta() + hpart = rt.TH2D("hnode%d"%(inode),"",3456,0,3456,1008,2400,2400+6*1008) + pix_v = node.pix_vv.at(ih) + npix = int(pix_v.size()/2) + for ipix in range(npix): + xbin = int(pix_v.at(2*ipix+1)) + ybin = int((pix_v.at(2*ipix)-2400)/6.0) + hpart.SetBinContent( xbin+1, ybin+1, 1 ) + cpt = rt.TCanvas("cnode%d"%(inode),"node[%d] pid[%d] tid[%d]"%(inode,node.pid,node.tid),800,600) + hpart.GetZaxis().SetRangeUser(0,10.0) + hpart.Draw("colz") + cpt.Update() + cpart.append(cpt) + cpart.append(hpart) + - print("[ENTER] to continue") - input() + print("[ENTER] to continue") + input() if True: continue diff --git a/ublarcvapp/UBPhotonLib/info/UBPhotonLibraryPropagation_module.cc b/ublarcvapp/UBPhotonLib/info/UBPhotonLibraryPropagation_module.cc new file mode 100644 index 0000000..c7e8391 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/info/UBPhotonLibraryPropagation_module.cc @@ -0,0 +1,274 @@ +//////////////////////////////////////////////////////////////////////// +// Class: UBPhotonLibraryPropagation +// Plugin Type: producer (art v2_05_00) +// File: UBPhotonLibraryPropagation_module.cc +// +// Generated at Tue Mar 21 07:45:42 2017 by Wesley Ketchum using cetskelgen +// from cetlib version v1_21_00. +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art/Framework/Services/Optional/RandomNumberGenerator.h" +#include "nutools/RandomUtils/NuRandomService.h" + +#include +#include + +#include "larcore/Geometry/Geometry.h" +#include "larsim/PhotonPropagation/PhotonVisibilityService.h" +#include "larsim/Simulation/PhotonVoxels.h" + +#include "CLHEP/Random/RandFlat.h" +#include "CLHEP/Random/RandPoissonQ.h" + +#include "lardataobj/Simulation/SimPhotons.h" +#include "lardataobj/Simulation/SimEnergyDeposit.h" +#include "larsim/IonizationScintillation/ISCalcSeparate.h" + +#include "lardata/DetectorInfoServices/LArPropertiesService.h" +#include "lardata/DetectorInfoServices/DetectorPropertiesService.h" +#include "larsim/Simulation/LArG4Parameters.h" +#include "larevt/SpaceChargeServices/SpaceChargeService.h" + + +namespace phot { + class UBPhotonLibraryPropagation; +} + + +class phot::UBPhotonLibraryPropagation : public art::EDProducer { +public: + explicit UBPhotonLibraryPropagation(fhicl::ParameterSet const & p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + UBPhotonLibraryPropagation(UBPhotonLibraryPropagation const &) = delete; + UBPhotonLibraryPropagation(UBPhotonLibraryPropagation &&) = delete; + UBPhotonLibraryPropagation & operator = (UBPhotonLibraryPropagation const &) = delete; + UBPhotonLibraryPropagation & operator = (UBPhotonLibraryPropagation &&) = delete; + + // Required functions. + void produce(art::Event & e) override; + + // Selected optional functions. + void reconfigure(fhicl::ParameterSet const & p); + void beginJob() override; + +private: + + double fRiseTimeFast; + double fRiseTimeSlow; + bool fDoSlowComponent; + + std::vector fEDepTags; + + larg4::ISCalcSeparate fISAlg; + + double GetScintYield(sim::SimEnergyDeposit const&, detinfo::LArProperties const&); + + double GetScintTime(double scint_time, double rise_time, double, double); +}; + + +phot::UBPhotonLibraryPropagation::UBPhotonLibraryPropagation(fhicl::ParameterSet const & p) : art::EDProducer(p) +{ + produces< std::vector >(); + (void)art::ServiceHandle()->createEngine(*this, "HepJamesRandom", "photon", p, "SeedPhoton"); + (void)art::ServiceHandle()->createEngine(*this, "HepJamesRandom", "scinttime", p, "SeedScintTime"); + //art::ServiceHandle()->createEngine(*this, "HepJamesRandom", "photon", p, "SeedPhoton"); + //art::ServiceHandle()->createEngine(*this, "HepJamesRandom", "scinttime", p, "SeedScintTime"); + this->reconfigure(p); +} + +double phot::UBPhotonLibraryPropagation::GetScintYield(sim::SimEnergyDeposit const& edep, + detinfo::LArProperties const& larp) +{ + double yieldRatio = larp.ScintYieldRatio(); + if(larp.ScintByParticleType()){ + switch(edep.PdgCode()) { + case 2212: + yieldRatio = larp.ProtonScintYieldRatio(); + break; + case 13: + case -13: + yieldRatio = larp.MuonScintYieldRatio(); + break; + case 211: + case -211: + yieldRatio = larp.PionScintYieldRatio(); + break; + case 321: + case -321: + yieldRatio = larp.KaonScintYieldRatio(); + break; + case 1000020040: + yieldRatio = larp.AlphaScintYieldRatio(); + break; + case 11: + case -11: + case 22: + yieldRatio = larp.ElectronScintYieldRatio(); + break; + default: + yieldRatio = larp.ElectronScintYieldRatio(); + } + } + return yieldRatio; +} + +void phot::UBPhotonLibraryPropagation::produce(art::Event & e) +{ + art::ServiceHandle pvs; + art::ServiceHandle lgpHandle; + const detinfo::LArProperties* larp = lar::providerFrom(); + + art::ServiceHandle rng; + + auto const& module_label = moduleDescription().moduleLabel(); + + //CLHEP::HepRandomEngine &engine_photon = rng->getEngine("photon"); + auto& engine_photon = rng->getEngine(art::ScheduleID::first(), module_label, "photon"); + CLHEP::RandPoissonQ randpoisphot(engine_photon); + //CLHEP::HepRandomEngine &engine_scinttime = rng->getEngine("scinttime"); + auto& engine_scinttime = rng->getEngine(art::ScheduleID::first(), module_label, "scinttime"); + CLHEP::RandFlat randflatscinttime(engine_scinttime); + + const size_t NOpChannels = pvs->NOpChannels(); + double yieldRatio; + double nphot,nphot_fast,nphot_slow; + + //auto fSCE = lar::providerFrom(); + + sim::OnePhoton photon; + photon.Energy = 9.7e-6; + photon.SetInSD = false; + + fISAlg.Initialize(larp, + lar::providerFrom(), + &(*lgpHandle), + lar::providerFrom()); + + std::unique_ptr< std::vector > photCol ( new std::vector); + auto & photonCollection(*photCol); + + //size_t edep_reserve_size=0; + std::vector< std::vector const*> edep_vecs; + for(auto label : fEDepTags){ + auto const& edep_handle = e.getValidHandle< std::vector >(label); + edep_vecs.push_back(edep_handle); + //edep_reserve_size += edep_handle->size(); + } + + for(size_t i_op=0; i_opGetAllVisibilities(xyz); + if(!Visibilities) + continue; + + yieldRatio = GetScintYield(edep,*larp); + fISAlg.Reset(); + fISAlg.CalculateIonizationAndScintillation(edep); + nphot =fISAlg.NumberScintillationPhotons(); + nphot_fast = yieldRatio*nphot; + + photon.Time = edep.T() + GetScintTime(larp->ScintFastTimeConst(),fRiseTimeFast, + randflatscinttime(),randflatscinttime()); + //std::cout << "\t\tPhoton fast time is " << photon.Time << " (" << edep.T() << " orig)" << std::endl; + for(size_t i_op=0; i_op0){ + photon.Time = edep.T() + GetScintTime(larp->ScintSlowTimeConst(),fRiseTimeSlow, + randflatscinttime(),randflatscinttime()); + //std::cout << "\t\tPhoton slow time is " << photon.Time << " (" << edep.T() << " orig)" << std::endl; + for(size_t i_op=0; i_op("RiseTimeFast",-1.0); + fRiseTimeSlow = p.get("RiseTimeSlow",-1.0); + fDoSlowComponent = p.get("DoSlowComponent"); + + fEDepTags = p.get< std::vector >("EDepModuleLabels"); +} + +void phot::UBPhotonLibraryPropagation::beginJob() +{ + +} + +DEFINE_ART_MODULE(phot::UBPhotonLibraryPropagation) + diff --git a/ublarcvapp/UBPhotonLib/info/microboonev12_nowires.gdml b/ublarcvapp/UBPhotonLib/info/microboonev12_nowires.gdml new file mode 100644 index 0000000..130fe17 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/info/microboonev12_nowires.gdml @@ -0,0 +1,32816 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 962deb8720f5c2ffbae3019f2fd89a4e3639e16f Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 30 Jul 2024 02:09:44 -0400 Subject: [PATCH 44/80] fix mcpixelpgraph bug. add function get get pixel sum --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 347 ++++++++++++++----- ublarcvapp/MCTools/MCPixelPGraph.h | 27 +- ublarcvapp/MCTools/MCPos2ImageUtils.cxx | 2 +- ublarcvapp/MCTools/test/run_mcpixelpgraph.py | 34 +- 4 files changed, 310 insertions(+), 100 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index aa7793f..c97c2d1 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -6,7 +6,7 @@ // larcv #include "larcv/core/DataFormat/EventImage2D.h" #include "larcv/core/DataFormat/DataFormatTypes.h" -#include "larcv/core/ROOTUtil/ROOTUtils.h" +//#include "larcv/core/ROOTUtil/ROOTUtils.h" // larlite #include "larlite/DataFormat/mctrack.h" @@ -32,7 +32,7 @@ namespace mctools { ev_seg = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "segment" ); ev_ins = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "instance" ); ev_anc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "ancestor" ); - larcv::EventImage2D* ev_larflow = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "larflow" ); + ev_larflow = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "larflow" ); if ( ev_adc->Image2DArray().size()==0 ) { throw std::runtime_error("No ADC images!"); @@ -1432,6 +1432,16 @@ namespace mctools { _nu_vertices_v.clear(); _shower_daughter2mother.clear(); //_map_trackid_to_nu_ancestor_v.clear(); + + _nodeidx_to_photonlist_index_v.clear(); + _true_photon_v.clear(); + + _empty_photon_pointlist_v.clear(); + + // ev_adc = nullptr; + // ev_seg = nullptr; + // ev_ins = nullptr; + // ev_anc = nullptr; } @@ -1582,84 +1592,69 @@ namespace mctools { }//end of adopt orphans - std::vector MCPixelPGraph::makeTH2D( std::string hist_stem_name ) - { - // first get wire image into th2d - std::vector< TH2D > hist_v; - if ( ev_adc==nullptr ) - return hist_v; - - for ( auto& pmarker : vis_markers_v ) { - delete pmarker; - }; - vis_markers_v.clear(); - - for ( auto& plabel : vis_label_v ) { - delete plabel; - } - vis_label_v.clear(); + // std::vector MCPixelPGraph::makeTH2D( std::string hist_stem_name ) + // { + // // first get wire image into th2d + // std::vector< TH2D > hist_v; + // if ( ev_adc==nullptr ) + // return hist_v; + + // for ( auto& pmarker : vis_markers_v ) { + // delete pmarker; + // }; + // vis_markers_v.clear(); + + // for ( auto& plabel : vis_label_v ) { + // delete plabel; + // } + // vis_label_v.clear(); - if ( !cvis ) { - cvis = new TCanvas("cmcpg","MCPixel PGraph Canvas",800,2400); - cvis->Divide(1,3); - } + // if ( !cvis ) { + // cvis = new TCanvas("cmcpg","MCPixel PGraph Canvas",800,2400); + // cvis->Divide(1,3); + // } - hist_v = larcv::rootutils::as_th2d_v( ev_adc->as_vector(), hist_stem_name ); - - // label the nodes - for (auto& node : node_v ) { - - for (int p=0; p<(int)hist_v.size(); p++) { - cvis->cd(p+1); - auto& hist = hist_v.at(p); - //auto& meta = ev_adc->as_vector().at(p).meta(); - std::cout << "Draw marker for node[" << node.nodeidx << "]-plane[" << p << "] wire=" << node.imgpos4_edep[p] << " tick=" << node.imgpos4_edep[3] << std::endl; - TMarker* m = new TMarker( node.imgpos4_edep[p], node.imgpos4_edep[3], 20 ); - //m->SetMarkerSize(3); - m->SetMarkerColor(kMagenta); - hist.Draw("colz"); - m->Draw(); - vis_markers_v.push_back( m ); - } + // hist_v = larcv::rootutils::as_th2d_v( ev_adc->as_vector(), hist_stem_name ); + + // // label the nodes + // for (auto& node : node_v ) { + + // for (int p=0; p<(int)hist_v.size(); p++) { + // cvis->cd(p+1); + // auto& hist = hist_v.at(p); + // //auto& meta = ev_adc->as_vector().at(p).meta(); + // std::cout << "Draw marker for node[" << node.nodeidx << "]-plane[" << p << "] wire=" << node.imgpos4_edep[p] << " tick=" << node.imgpos4_edep[3] << std::endl; + // TMarker* m = new TMarker( node.imgpos4_edep[p], node.imgpos4_edep[3], 20 ); + // //m->SetMarkerSize(3); + // m->SetMarkerColor(kMagenta); + // hist.Draw("colz"); + // m->Draw(); + // vis_markers_v.push_back( m ); + // } - } - cvis->Update(); - //std::cout << "[enter] to continue" << std::endl; - //std::cin.get(); - return hist_v; - } - + // } + // cvis->Update(); + // //std::cout << "[enter] to continue" << std::endl; + // //std::cin.get(); + // return hist_v; + // } + /** - * @brief Fix the location of where the start starts depositing energy + * @brief use larflow truth to make 3D spacepoints for a given particle * + * @return a vector of 3d positions + * */ - std::vector MCPixelPGraph::fixingPhotonStartPoints( Node_t& node, - const std::vector& instance_v, - const std::vector& ancestor_v, - const std::vector& adc_v, - const std::vector& larflow_v ) + std::vector< std::vector > + MCPixelPGraph::makeNode3DpointsFromLArFlowTruth( Node_t& node, + const std::vector& adc_v, + const std::vector& larflow_v ) { - // start of photon shower is not something accurately specified in the mcreco - // products. detprofile is provided in mcshower -- but i think its basically trash. - // instead we will use the instanceid + larflow truth to - // (1) build 3d spacepoints - // (2) find the closest spacepoint with evidence for ~MIP level deposits - // (3) place the position there - // the profile also provides a momentum, but I bet its garbage + // we want to make 3d points from the pixels we have for the shower. + std::vector< std::vector > pos_vv; - // this is only for photons (electrons have a good start point based on node.start) - std::vector shower_start_pt; - - if ( node.pid!=22) - return shower_start_pt; - - // we must collect and scan the instance IDs related to the shower - int shower_aid = node.aid; - int shower_mid = node.mid; - int shower_tid = node.tid; - - // we want to make 3d points from the pixels we have for the shower. + // we use the plane-to-plane "flow" map to define 3d spacepoints struct flowpt { int source_plane; int source_wire; @@ -1693,6 +1688,9 @@ namespace mctools { {0,2}, {0,1} }; + // std::cout << "adc images: " << adc_v.size() << std::endl; + // std::cout << "larflow images: " << larflow_v.size() << std::endl; + std::set< flowpt > pt_v; for (size_t p=0; p{ pt_info.pos[0], pt_info.pos[1], pt_info.pos[2] } ); + } + + return pos_vv; + } + + /** + * @brief Fix the location of where the start starts depositing energy + * + */ + std::vector MCPixelPGraph::fixingPhotonStartPoints( Node_t& node, + const std::vector& instance_v, + const std::vector& ancestor_v, + const std::vector& adc_v, + const std::vector& larflow_v ) + { + + // start of photon shower is not something accurately specified in the mcreco + // products. detprofile is provided in mcshower -- but i think its basically trash. + // instead we will use the instanceid + larflow truth to + // (1) build 3d spacepoints + // (2) find the closest spacepoint with evidence for ~MIP level deposits + // (3) place the position there + // the profile also provides a momentum, but I bet its garbage + // this is only for photons (electrons have a good start point based on node.start) + std::vector shower_start_pt; + + if ( node.pid!=22) + return shower_start_pt; + + // we must collect and scan the instance IDs related to the shower + // int shower_aid = node.aid; + // int shower_mid = node.mid; + // int shower_tid = node.tid; + + pointList pos_vv = makeNode3DpointsFromLArFlowTruth( node, adc_v, larflow_v ); + + std::cout << "Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; + std::cout << " Number of spacepoints found from using larflow: " << pos_vv.size() << std::endl; + float mindist = 1.0e9; std::vector start_reco_pt = MCPos2ImageUtils::Get()->truepos_to_recopos( node.start[0], node.start[1], @@ -1791,16 +1831,13 @@ namespace mctools { std::vector< std::vector > data_v; - for ( auto& pt : pt_v ) { - std::cout << "3d pt: (" << pt.pos[0] << ", " << pt.pos[1] << ", " << pt.pos[2] << ") " - << " src_pixval=" << pt.src_pixval - << " src_plane=" << pt.source_plane - << std::endl; + for ( auto& pt : pos_vv ) { + //std::cout << "3d pt: (" << pt[0] << ", " << pt[1] << ", " << pt[2] << ") " << std::endl; float dist_edep = 0.; float dx = 0.; for (int v=0; v<3; v++) { - dx = pt.pos[v] - node.first_edep_pos[v]; + dx = pt[v] - node.first_edep_pos[v]; dist_edep += dx*dx; } dist_edep = sqrt(dist_edep); @@ -1810,7 +1847,7 @@ namespace mctools { std::vector xpt(3,0); for (int v=0; v<3; v++) - xpt[v] = pt.pos[v]; + xpt[v] = pt[v]; data_v.push_back( xpt ); } @@ -1825,7 +1862,9 @@ namespace mctools { icluster = i; } } - + + + pointList trunk_pt_v; if ( icluster<0 ) { shower_start_pt = node.first_edep_pos; } @@ -1845,7 +1884,8 @@ namespace mctools { shower_start_pt[3] = xpt[0]/(0.5*larutil::LArProperties::GetME()->DriftVelocity()) + 3200; mindist = dist; } - } + trunk_pt_v.push_back( xpt ); + }//end of loop over largest cluster points (by index) } std::cout << " minimum dist to shower startpt: " << mindist << " cm" << std::endl; @@ -1868,10 +1908,157 @@ namespace mctools { for (int v=0; v<4; v++) shower_start_pt.push_back( shower_imgpos4[v] ); + + int photon_point_list_index = (int)_true_photon_v.size(); + _true_photon_v.emplace_back( std::move(trunk_pt_v) ); + _nodeidx_to_photonlist_index_v[ node.nodeidx ] = photon_point_list_index; return shower_start_pt; } + + /** + * @brief Get the 3d points representing the true photon trunk + * + */ + const std::vector< std::vector >& MCPixelPGraph::getTruePhotonTrunk3DPoints( Node_t& node ) + { + + auto it_pointlist = _nodeidx_to_photonlist_index_v.find( node.nodeidx ); + if ( it_pointlist==_nodeidx_to_photonlist_index_v.end() ) { + std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find photonlist for " + << " nodeidx=" << node.nodeidx + << " pdg=" << node.pid + << " trackid=" << node.tid << ". " + << "Returning emptry point list." + << std::endl; + _empty_photon_pointlist_v.clear(); + return _empty_photon_pointlist_v; + } + + size_t index = it_pointlist->second; + if ((int)index<0 || index>=_true_photon_v.size() ) { + std::stringstream msg; + msg << "Missing photon list index! node.trackid=" << node.tid + << " map.trackid=" << it_pointlist->first + << " map.index=" << it_pointlist->second + << std::endl; + throw std::runtime_error( msg.str() ); + } + + return _true_photon_v.at( it_pointlist->second ); + } + + /** + * @brief Get the 3d points representing the true photon trunk by Track ID + * + */ + const std::vector< std::vector >& MCPixelPGraph::getTruePhotonTrunk3DPoints( int trackid ) + { + Node_t* pnode = findTrackID( trackid ); + if ( pnode==nullptr ) { + std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not particle Node for " + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; + _empty_photon_pointlist_v.clear(); + return _empty_photon_pointlist_v; + } + + return getTruePhotonTrunk3DPoints( *pnode ); + } + + /** + * @brief Get the sum of pixel values around the trunk plane + */ + std::vector MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + { + // we want to sum using a kernel (3x3) pixels. We want to avoid double counting, + // so we must mark which pixels we used + + const int dpix = 1; + std::vector pixelsum_v; + + const pointList& photonpts = getTruePhotonTrunk3DPoints( trackid ); + if ( photonpts.size()==0 ) { + return pixelsum_v; + } + + // this pointer is saved when buildgraph(...) is called + // it is cleared (set to nullptr) when clear() is called. + if ( ev_adc==nullptr ) { + std::stringstream msg; + msg << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] [ERROR]: Missing ADC image for summing pixel values" << std::endl; + throw std::runtime_error( msg.str() ); + } + + std::cout << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] : number of photon pts = " << photonpts.size() << std::endl; + + const int nplanes = ev_adc->Image2DArray().size(); + std::vector out_of_imgpix(nplanes,0); + pixelsum_v.resize(3,0); + + for (int p=0; p<(int)ev_adc->Image2DArray().size(); p++) { + auto const& img = ev_adc->Image2DArray().at(p); + + std::set< std::pair > _pix_used; + + // loop over 3d points + for (int ipt=0; ipt<(int)photonpts.size(); ipt++) { + auto& pt = photonpts.at(ipt); + // get the point in the image + std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], + pt[1], + pt[2], + 0.0 ); + + //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; + + // sum over 3x3 kernel + // first find center pixel + int row_center = 0; + int col_center = 0; + try { + row_center = img.meta().row( imgpos4[3] ); + col_center = img.meta().col( imgpos4[p] ); + } + catch (...) { + // out of image tick + out_of_imgpix[p]++; + continue; + } + + for (int dr=-dpix; dr<=dpix; dr++) { + for (int dc=-dpix; dc<=dpix; dc++) { + int r = row_center + dr; + int c = col_center + dc; + + auto it_pix = _pix_used.find( std::pair(r,c) ); + if ( it_pix==_pix_used.end() ) { + // did not find it in the set, so add it as part of the sum + float pixval = 0.0; + try { + pixval = img.pixel( r, c ); + _pix_used.insert( std::pair(r,c) ); + pixelsum_v[p] += pixval; + } + catch (...) { + // probably out of image + out_of_imgpix[p]++; + continue; + } + } + + }//end of dc loop + }//end of dr loop + + }//end of point loop + + std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + }//end of plane loop + + return pixelsum_v; + }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 5f2dbbc..e3f25c4 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -214,21 +214,39 @@ namespace mctools { std::vector getNeutrinoParticles( bool exclude_neutrons=true ); // make visualization of nu particles - std::vector< TH2D > makeTH2D( std::string hist_stem_name ); + // std::vector< TH2D > makeTH2D( std::string hist_stem_name ); + + std::vector< std::vector > + makeNode3DpointsFromLArFlowTruth( Node_t& node, + const std::vector& adc_v, + const std::vector& larflow_v ); + + // clear the state + void clear(); + + public: + + // variables and functions for making better quantities to + // characterize true photons float photon_start_edep_radius_cm; float photon_start_pixval_threshold; int photon_start_min_cluster_size; + typedef std::vector< std::vector > pointList; /// just a redefinition + std::vector< pointList > _true_photon_v; /// list of 3d points representing the shower trunk + std::map< int, int > _nodeidx_to_photonlist_index_v; /// map from node.nodeidx to index in _true_photon_v + pointList _empty_photon_pointlist_v; std::vector fixingPhotonStartPoints( Node_t& node, const std::vector& instance_v, const std::vector& ancestor_v, const std::vector& adc_v, const std::vector& larflow_v ); + const pointList& getTruePhotonTrunk3DPoints( Node_t& node ); + const pointList& getTruePhotonTrunk3DPoints( int trackid ); + std::vector getTruePhotonTrunkPlanePixelSums( int trackid ); - // clear the state - void clear(); protected: @@ -238,7 +256,8 @@ namespace mctools { larcv::EventImage2D* ev_adc; larcv::EventImage2D* ev_seg; larcv::EventImage2D* ev_ins; - larcv::EventImage2D* ev_anc; + larcv::EventImage2D* ev_anc; + larcv::EventImage2D* ev_larflow; void _recursivePrintGraph( Node_t* node, int& depth, bool visible_only=true ); void _scanPixelData( const std::vector& adc_v, diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx index a52856b..e0744b3 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx @@ -99,7 +99,7 @@ namespace mctools { //std::cout << "vpos: " << vpos[0] << " " << vpos[1] << " " << vpos[2] << std::endl; std::vector imgpos(4,0); - if ( std::fabs(vpos[1])>116.5 || vpos[2]<0.0 && vpos[2]>1036.0 ) + if ( std::fabs(vpos[1])>116.5 || vpos[2]<0.0 || vpos[2]>1036.0 ) return imgpos; for (int p=0; p<3; p++) { diff --git a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py index 2d2526a..a0ccc95 100755 --- a/ublarcvapp/MCTools/test/run_mcpixelpgraph.py +++ b/ublarcvapp/MCTools/test/run_mcpixelpgraph.py @@ -25,9 +25,9 @@ rt.gStyle.SetOptStat(0) ioll = larlite.storage_manager( larlite.storage_manager.kREAD ) -ioll.set_data_to_read( larlite.data.kMCTrack, "mcreco" ) -ioll.set_data_to_read( larlite.data.kMCShower, "mcreco" ) -ioll.set_data_to_read( larlite.data.kMCTruth, "generator" ) +ioll.set_data_to_read( "mctrack", "mcreco" ) # larlite.data.kMCTrack +ioll.set_data_to_read( "mcshower", "mcreco" ) # larlite.data.kMCShower +ioll.set_data_to_read( "mctruth", "generator" ) # larlite.data.kMCTruth ioll.add_in_filename( args.input_larlite ) ioll.open() @@ -65,11 +65,11 @@ mcpg = ublarcvapp.mctools.MCPixelPGraph() mcpg_nu = ublarcvapp.mctools.MCPixelPGraph() if args.debug: - mcpg.set_verbosity( larcv.msg.kDEBUG ) - mcpg_nu.set_verbosity( larcv.msg.kDEBUG ) + mcpg.set_verbosity( "debug" ) + mcpg_nu.set_verbosity( "debug" ) else: - mcpg.set_verbosity( larcv.msg.kINFO ) - mcpg_nu.set_verbosity( larcv.msg.kINFO ) + mcpg.set_verbosity( "info" ) + mcpg_nu.set_verbosity( "info" ) if HAS_LARCV: mcpg.set_adc_treename( args.adc ) @@ -101,16 +101,17 @@ print("HAS_LARCV: get images needed for pixel matching to particles") #mcpg.buildgraphonly( ioll ) iolcv.read_entry(ientry) - ev_adc = iolcv.get_data( larcv.kProductImage2D, args.adc ) - ev_instance = iolcv.get_data( larcv.kProductImage2D, "instance" ) - ev_ancestor = iolcv.get_data( larcv.kProductImage2D, "ancestor" ) - ev_segment = iolcv.get_data( larcv.kProductImage2D, "segment" ) - ev_larflow = iolcv.get_data( larcv.kProductImage2D, "larflow" ) - print("number of images: ",ev_adc.Image2DArray().size()) + ev_adc = iolcv.get_data( "image2d", args.adc ) + ev_instance = iolcv.get_data( "image2d", "instance" ) + ev_ancestor = iolcv.get_data( "image2d", "ancestor" ) + ev_segment = iolcv.get_data( "image2d", "segment" ) + ev_larflow = iolcv.get_data( "image2d", "larflow" ) + print("number of adc images: ",ev_adc.Image2DArray().size()) + print("number of larflow images: ",ev_larflow.Image2DArray().size()) adc_v = ev_adc.Image2DArray() - mcpg_nu.buildgraph( iolcv, ioll ) for p in range(adc_v.size()): - print(" image[",p,"] ",adc_v[p].meta().dump()) + print(" image[",p,"] ",adc_v[p].meta().dump()) + mcpg_nu.buildgraph( iolcv, ioll ) photon_starts = {} @@ -247,6 +248,9 @@ if node.pid not in [22]: continue print("Make canvas of particle, tid=",node.tid) + pixsum_v = mcpg_nu.getTruePhotonTrunkPlanePixelSums( node.tid ) + if pixsum_v.size()>=3: + print(" pixelsum (",pixsum_v[0],", ",pixsum_v[1],", ",pixsum_v[2],")") meta = ev_adc.as_vector().at(2).meta() hpart = rt.TH2D("hnode%d"%(inode),"",3456,0,3456,1008,2400,2400+6*1008) pix_v = node.pix_vv.at(ih) From 6451f3d0e902de14871f1a90f112dfc597db217a Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 30 Jul 2024 16:46:51 -0400 Subject: [PATCH 45/80] add access function for edep position for a trackid node --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 20 ++++++++++++++++++++ ublarcvapp/MCTools/MCPixelPGraph.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index c97c2d1..d8bfa83 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -2059,6 +2059,26 @@ namespace mctools { return pixelsum_v; }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + + /** + * @brief Get the position the particle first deposited energy + * + */ + std::vector MCPixelPGraph::getParticleEDepPos( const int& trackid ) + { + std::vector edep_pos; + Node_t* pnode = findTrackID( trackid ); + if (pnode==nullptr) { + std::stringstream msg; + msg << "[MCPixelPGraph::getParticleEDepPos] [ERROR] : Could not find a particle node for trackid=" << trackid << std::endl; + throw std::runtime_error( msg.str() ); + } + edep_pos.resize(3,0); + for (int v=0; v<3; v++) { + edep_pos[v] = pnode->first_edep_pos[v]; + } + return edep_pos; + } } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index e3f25c4..b86b4b0 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -213,6 +213,9 @@ namespace mctools { std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons=true ); std::vector getNeutrinoParticles( bool exclude_neutrons=true ); + // get positions + std::vector getParticleEDepPos( const int& trackid ); + // make visualization of nu particles // std::vector< TH2D > makeTH2D( std::string hist_stem_name ); From b78e3cdafcc0803223dd9cda9beb81011e01d63f Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 8 Aug 2024 00:55:53 -0400 Subject: [PATCH 46/80] added pixel sum threshold for shower fragments used to determine start point. pixel sum used as a threshold along with num cluster hits greater than 4. then closest pos to particle start is used to define shower edep position --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 144 +++++++++++++++++++++++++-- ublarcvapp/MCTools/MCPixelPGraph.h | 2 +- 2 files changed, 137 insertions(+), 9 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index d8bfa83..d93f606 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -1812,7 +1812,9 @@ namespace mctools { pointList pos_vv = makeNode3DpointsFromLArFlowTruth( node, adc_v, larflow_v ); - std::cout << "Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; + std::cout << "================================================================" << std::endl; + std::cout << "[fixingPhotonStartPoints]" << std::endl; + std::cout << " Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; std::cout << " Number of spacepoints found from using larflow: " << pos_vv.size() << std::endl; float mindist = 1.0e9; @@ -1845,28 +1847,76 @@ namespace mctools { // if ( dist_edep>photon_start_edep_radius_cm || pt.src_pixval xpt(3,0); + std::vector xpt(4,0); for (int v=0; v<3; v++) xpt[v] = pt[v]; + // add time dim + xpt[3] = 0.0; data_v.push_back( xpt ); } + auto dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( 0.3, 3, 50, data_v ); - int nlargest = 0; int icluster = -1; + float closest_qualified_cluster_dist = 1.0e9; + for (int i=0; i<(int)dbcluster_v.size(); i++) { + + // we calculate the pixel sum in each plane of each cluster. + // (this is costly -- if it starts to be too slow -- we will need some thresholding with easy measures) int nhits = dbcluster_v.at(i).size(); - if ( (int)nhits>nlargest && (int)nhits>=photon_start_min_cluster_size ) { - nlargest = nhits; + + if ( nhits<5 ) + continue; + + float cluster_min_dist_to_source = 1e9; + + pointList cluster_pt_v; + cluster_pt_v.reserve(nhits); + for (int ipt=0; ipt pixsum_v = getPlanePixelSumsFromPointList( cluster_pt_v ); + + // another threshold: one plane must pass 10 MeV threshol + // using MeV = 0.00162*pixsum + int planes_passing = 0; + std::cout << "cluster[" << i << "] dist-to-source=" << cluster_min_dist_to_source << " cm; plane MeV: ("; + for ( int p=0; p<(int)pixsum_v.size(); p++ ) { + float MeV = pixsum_v[p]*0.0162; + std::cout << MeV; + if ( p+120.0 ) { + planes_passing++; + } + } + std::cout << ")" << std::endl; + + if ( planes_passing>=2 && cluster_min_dist_to_source < closest_qualified_cluster_dist ) { + closest_qualified_cluster_dist = cluster_min_dist_to_source; icluster = i; } } - - + + pointList trunk_pt_v; if ( icluster<0 ) { - shower_start_pt = node.first_edep_pos; + shower_start_pt = std::vector{ -1.0, -1.0, -1.0 }; } else { auto& largest_cluster = dbcluster_v.at(icluster); @@ -1912,6 +1962,7 @@ namespace mctools { int photon_point_list_index = (int)_true_photon_v.size(); _true_photon_v.emplace_back( std::move(trunk_pt_v) ); _nodeidx_to_photonlist_index_v[ node.nodeidx ] = photon_point_list_index; + std::cout << "========================================================END======" << std::endl; return shower_start_pt; @@ -2060,6 +2111,83 @@ namespace mctools { return pixelsum_v; }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + std::vector + MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ) + { + std::vector pixsum_v; + + if ( !ev_adc ) + return pixsum_v; + + const int nplanes = ev_adc->Image2DArray().size(); + const int dpix = 2; + std::vector out_of_imgpix(nplanes,0); + pixsum_v.resize(nplanes,0); + + for (int p=0; pImage2DArray().at(p); + + // this lists (row,col) combinations we gathered pixels from + std::set< std::pair > _pix_used; + + // loop over 3d points + for (int ipt=0; ipt<(int)pointlist.size(); ipt++) { + auto& pt = pointlist.at(ipt); + // get the point in the image + std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], + pt[1], + pt[2], + 0.0 ); + + //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; + + // sum over 3x3 kernel + // first find center pixel + int row_center = 0; + int col_center = 0; + try { + row_center = img.meta().row( imgpos4[3] ); + col_center = img.meta().col( imgpos4[p] ); + } + catch (...) { + // out of image tick + out_of_imgpix[p]++; + continue; + } + + for (int dr=-dpix; dr<=dpix; dr++) { + for (int dc=-dpix; dc<=dpix; dc++) { + int r = row_center + dr; + int c = col_center + dc; + + auto it_pix = _pix_used.find( std::pair(r,c) ); + if ( it_pix==_pix_used.end() ) { + // did not find it in the set, so add it as part of the sum + float pixval = 0.0; + try { + pixval = img.pixel( r, c ); + _pix_used.insert( std::pair(r,c) ); + pixsum_v[p] += pixval; + } + catch (...) { + // probably out of image + out_of_imgpix[p]++; + continue; + } + } + + }//end of dc loop + }//end of dr loop + + }//end of point loop + + //std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + }//end of plane loop + + return pixsum_v; + }// end of MCPixelPGraph::getPlanePixelSumsFromPointList + /** * @brief Get the position the particle first deposited energy * diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index b86b4b0..2e88312 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -248,7 +248,7 @@ namespace mctools { const pointList& getTruePhotonTrunk3DPoints( Node_t& node ); const pointList& getTruePhotonTrunk3DPoints( int trackid ); std::vector getTruePhotonTrunkPlanePixelSums( int trackid ); - + std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ); protected: From 6bc4c280497a5157ae963f8631d6a5af93cdc0f8 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 16 Aug 2024 16:16:21 -0400 Subject: [PATCH 47/80] updated mcpg to calc and save pixelsum and crop around trunk with image mask --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 313 +++++++++++++++++++++++---- ublarcvapp/MCTools/MCPixelPGraph.h | 9 +- 2 files changed, 274 insertions(+), 48 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index d93f606..728fb85 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -1435,8 +1435,12 @@ namespace mctools { _nodeidx_to_photonlist_index_v.clear(); _true_photon_v.clear(); + _true_photon_plane_trunkimg_vv.clear(); + _true_photon_plane_pixset_vv.clear(); + _true_photon_plane_pixsum_vv.clear(); _empty_photon_pointlist_v.clear(); + _empty_pixsum_v.clear(); // ev_adc = nullptr; // ev_seg = nullptr; @@ -1895,17 +1899,17 @@ namespace mctools { // another threshold: one plane must pass 10 MeV threshol // using MeV = 0.00162*pixsum int planes_passing = 0; - std::cout << "cluster[" << i << "] dist-to-source=" << cluster_min_dist_to_source << " cm; plane MeV: ("; + //std::cout << "cluster[" << i << "] dist-to-source=" << cluster_min_dist_to_source << " cm; plane MeV: ("; for ( int p=0; p<(int)pixsum_v.size(); p++ ) { float MeV = pixsum_v[p]*0.0162; - std::cout << MeV; - if ( p+120.0 ) { planes_passing++; } } - std::cout << ")" << std::endl; + //std::cout << ")" << std::endl; if ( planes_passing>=2 && cluster_min_dist_to_source < closest_qualified_cluster_dist ) { closest_qualified_cluster_dist = cluster_min_dist_to_source; @@ -1959,9 +1963,89 @@ namespace mctools { for (int v=0; v<4; v++) shower_start_pt.push_back( shower_imgpos4[v] ); + // get an index for this true photon pointList int photon_point_list_index = (int)_true_photon_v.size(); - _true_photon_v.emplace_back( std::move(trunk_pt_v) ); _nodeidx_to_photonlist_index_v[ node.nodeidx ] = photon_point_list_index; + + // making pixellist + const int nplanes = adc_v.size(); + std::vector plane_pixsum_v( nplanes, 0.0 ); + std::vector< PixelSet_t > plane_pixsets_v = getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); + + // making image masks + std::vector< larcv::Image2D > trunk_planeimg_v; + for (int p=0; p pix_row ) min_row = pix_row; + if ( max_row < pix_row ) max_row = pix_row; + if ( min_col > pix_col ) min_col = pix_col; + if ( max_col < pix_col ) max_col = pix_col; + } + auto const& meta = img.meta(); + int colcount = max_col-min_col+1; + int rowcount = max_row-min_row+1; + float width = float( colcount ); + float height = meta.pixel_height()*rowcount; + float origin_x = float( meta.pos_x( min_col ) ); + float origin_y = float( meta.pos_y( min_row ) ); + LARCV_DEBUG() << "min (col,row)=(" << min_col << "," << min_row << ")" << std::endl; + LARCV_DEBUG() << "min (x,y)=(" << origin_x << "," << origin_y << ")" << std::endl; + larcv::ImageMeta trunk_meta( width, height, rowcount, colcount, origin_x, origin_y, meta.plane() ); + larcv::Image2D trunk_img( trunk_meta ); + trunk_img.paint(0.0); + + LARCV_DEBUG() << "Defined plane bounding box for trunk" << std::endl; + LARCV_DEBUG() << trunk_meta.dump() << std::endl; + LARCV_DEBUG() << "original meta: " << meta.dump() << std::endl; + + //fill the mask + for (auto& pix : pixset ) { + int pix_row = pix.first; + int pix_col = pix.second; + //LARCV_DEBUG() << " set pixel (row,col)=(" << pix_row << ", " << pix_col << ") " << std::endl; + try { + trunk_img.set_pixel( pix_row-min_row, pix_col-min_col, 1.0 ); + } + catch (...) { + LARCV_ERROR() << "pixel (row,col)=(" << pix_row << "," << pix_col << ") is outside crop." << std::endl; + } + } + + trunk_planeimg_v.emplace_back( std::move(trunk_img) ); + + }//end of plane loop + + + // store all of this stuff + _true_photon_v.emplace_back( std::move(trunk_pt_v) ); + _true_photon_plane_pixset_vv.emplace_back( std::move( plane_pixsets_v ) ); + _true_photon_plane_pixsum_vv.emplace_back( std::move( plane_pixsum_v ) ); + _true_photon_plane_trunkimg_vv.emplace_back( std::move( trunk_planeimg_v ) ); + + // make sure we didnt screw something up + if ( (int)_true_photon_v.size()!=(photon_point_list_index+1) ) { + LARCV_ERROR() << "index of new true photon 3d point list doesn't match the size of the container" << std::endl; + } + if ( _true_photon_v.size()!=_true_photon_plane_pixset_vv.size() ) + LARCV_ERROR() << "size of the true photon 3d point container is not in the pixset container" << std::endl; + if ( _true_photon_v.size()!=_true_photon_plane_pixsum_vv.size() ) + LARCV_ERROR() << "size of the true photon 3d point container is not in the pixel sum container" << std::endl; + if ( _true_photon_v.size()!=_true_photon_plane_trunkimg_vv.size() ) + LARCV_ERROR() << "size of the true photon 3d point container is not the same as the trunk image mask container" << std::endl; + std::cout << "========================================================END======" << std::endl; return shower_start_pt; @@ -2026,37 +2110,166 @@ namespace mctools { { // we want to sum using a kernel (3x3) pixels. We want to avoid double counting, // so we must mark which pixels we used - - const int dpix = 1; - std::vector pixelsum_v; + Node_t* pnode = findTrackID( trackid ); + if ( pnode==nullptr ) { + std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find particle Node pointer for " + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; + _empty_photon_pointlist_v.clear(); + return _empty_pixsum_v; + } - const pointList& photonpts = getTruePhotonTrunk3DPoints( trackid ); - if ( photonpts.size()==0 ) { - return pixelsum_v; + auto it_pixsum = _nodeidx_to_photonlist_index_v.find( pnode->nodeidx ); + if ( it_pixsum==_nodeidx_to_photonlist_index_v.end() ) { + LARCV_ERROR() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; } - // this pointer is saved when buildgraph(...) is called - // it is cleared (set to nullptr) when clear() is called. - if ( ev_adc==nullptr ) { - std::stringstream msg; - msg << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] [ERROR]: Missing ADC image for summing pixel values" << std::endl; - throw std::runtime_error( msg.str() ); - } + std::vector pixsum_v = _true_photon_plane_pixsum_vv.at( it_pixsum->second ); + return pixsum_v; + + + // const pointList& photonpts = getTruePhotonTrunk3DPoints( trackid ); + // if ( photonpts.size()==0 ) { + // return pixelsum_v; + // } + + // // this pointer is saved when buildgraph(...) is called + // // it is cleared (set to nullptr) when clear() is called. + // if ( ev_adc==nullptr ) { + // std::stringstream msg; + // //msg << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] [ERROR]: Missing ADC image for summing pixel values" << std::endl; + // msg << "Missing ADC image for summing pixel values" << std::endl; + // LARCV_DEBUG() << msg.str(); + // throw std::runtime_error( msg.str() ); + // } - std::cout << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] : number of photon pts = " << photonpts.size() << std::endl; + // std::cout << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] : number of photon pts = " << photonpts.size() << std::endl; + // auto itg = _nodeidx_to_photonlist_index_v + + // const int nplanes = ev_adc->Image2DArray().size(); + // std::vector out_of_imgpix(nplanes,0); + // pixelsum_v.resize(3,0); + + // std::vector trunk_planeimg_v; + + // for (int p=0; p<(int)ev_adc->Image2DArray().size(); p++) { + // auto const& img = ev_adc->Image2DArray().at(p); + + // std::set< std::pair > _pix_used; + + // // loop over 3d points + // for (int ipt=0; ipt<(int)photonpts.size(); ipt++) { + // auto& pt = photonpts.at(ipt); + // // get the point in the image + // std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], + // pt[1], + // pt[2], + // 0.0 ); + + // //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; + + // // sum over 3x3 kernel + // // first find center pixel + // int row_center = 0; + // int col_center = 0; + // try { + // row_center = img.meta().row( imgpos4[3] ); + // col_center = img.meta().col( imgpos4[p] ); + // } + // catch (...) { + // // out of image tick + // out_of_imgpix[p]++; + // continue; + // } + + // for (int dr=-dpix; dr<=dpix; dr++) { + // for (int dc=-dpix; dc<=dpix; dc++) { + // int r = row_center + dr; + // int c = col_center + dc; + + // auto it_pix = _pix_used.find( std::pair(r,c) ); + // if ( it_pix==_pix_used.end() ) { + // // did not find it in the set, so add it as part of the sum + // float pixval = 0.0; + // try { + // pixval = img.pixel( r, c ); + // _pix_used.insert( std::pair(r,c) ); + // pixelsum_v[p] += pixval; + // } + // catch (...) { + // // probably out of image + // out_of_imgpix[p]++; + // continue; + // } + // } + + // }//end of dc loop + // }//end of dr loop + + // }//end of point loop + + // std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + + // // make an image + // int min_row = 999999; + // int max_row = 0; + // int min_col = 999999; + // int max_col = 0; + // for ( auto& pix : _pix_used ) { + // if ( min_row > pix.first ) min_row = pix.first; + // if ( max_row < pix.first ) max_row = pix.first; + // if ( min_col > pix.second ) min_col = pix.second; + // if ( min_col < pix.second ) max_col = pix.second; + // } + // auto const& meta = img.meta(); + // int colcount = max_col-min_col+1; + // int rowcount = max_row-min_row+1; + // float width = float( colcount ); + // float height = meta.pixel_height()*rowcount; + // float origin_x = float( meta.pos_x( min_col ) ); + // float origin_y = float( meta.pos_y( min_row ) ); + // larcv::ImageMeta trunk_meta( width, height, rowcount, colcount, origin_x, origin_y, meta.plane() ); + // larcv::Image2D trunk_img( trunk_meta ); + // trunk_img.paint(0.0); + + // // fill the mask + // for (auto& pix : _pix_used ) { + // trunk_img.set_pixel( pix.second, pix.first, 1.0 ); + // } + + // trunk_planeimg_v.emplace_back( std::move(trunk_img) ); + + // }//end of plane loop + // return pixelsum_v; + + }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + + std::vector + MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ) + { + std::vector pixsum_v; + + if ( !ev_adc ) + return pixsum_v; + const int nplanes = ev_adc->Image2DArray().size(); + const int dpix = 1; std::vector out_of_imgpix(nplanes,0); - pixelsum_v.resize(3,0); + // allocate space to the pixsum + pixsum_v.resize(nplanes,0); - for (int p=0; p<(int)ev_adc->Image2DArray().size(); p++) { + for (int p=0; pImage2DArray().at(p); + // this lists (row,col) combinations we gathered pixels from std::set< std::pair > _pix_used; // loop over 3d points - for (int ipt=0; ipt<(int)photonpts.size(); ipt++) { - auto& pt = photonpts.at(ipt); + for (int ipt=0; ipt<(int)pointlist.size(); ipt++) { + auto& pt = pointlist.at(ipt); // get the point in the image std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], pt[1], @@ -2091,7 +2304,7 @@ namespace mctools { try { pixval = img.pixel( r, c ); _pix_used.insert( std::pair(r,c) ); - pixelsum_v[p] += pixval; + pixsum_v[p] += pixval; } catch (...) { // probably out of image @@ -2104,42 +2317,45 @@ namespace mctools { }//end of dr loop }//end of point loop - - std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + + //std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; }//end of plane loop - return pixelsum_v; - }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + return pixsum_v; + }// end of MCPixelPGraph::getPlanePixelSumsFromPointList - std::vector - MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ) - { - std::vector pixsum_v; - - if ( !ev_adc ) - return pixsum_v; - + /** + * @brief Get set of pixels in each plane from a 3D point list + * + */ + std::vector< MCPixelPGraph::PixelSet_t > + MCPixelPGraph::getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, + std::vector& pixsum_v ) { + + std::vector< MCPixelPGraph::PixelSet_t > plane_pixsets_v; const int nplanes = ev_adc->Image2DArray().size(); const int dpix = 2; + std::vector out_of_imgpix(nplanes,0); - pixsum_v.resize(nplanes,0); - + pixsum_v.resize(nplanes,0.0); + for (int p=0; pImage2DArray().at(p); // this lists (row,col) combinations we gathered pixels from - std::set< std::pair > _pix_used; + PixelSet_t _pix_used; // loop over 3d points - for (int ipt=0; ipt<(int)pointlist.size(); ipt++) { - auto& pt = pointlist.at(ipt); + for (int ipt=0; ipt<(int)pt_v.size(); ipt++) { + auto& pt = pt_v.at(ipt); // get the point in the image std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], pt[1], pt[2], 0.0 ); - //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; // sum over 3x3 kernel @@ -2183,10 +2399,13 @@ namespace mctools { }//end of point loop //std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + + plane_pixsets_v.emplace_back( std::move( _pix_used ) ); + }//end of plane loop - - return pixsum_v; - }// end of MCPixelPGraph::getPlanePixelSumsFromPointList + + return plane_pixsets_v; + } /** * @brief Get the position the particle first deposited energy diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 2e88312..0b237b6 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -235,10 +235,15 @@ namespace mctools { float photon_start_edep_radius_cm; float photon_start_pixval_threshold; int photon_start_min_cluster_size; - typedef std::vector< std::vector > pointList; /// just a redefinition + typedef std::vector< std::vector > pointList; ///< just a redefinition + typedef std::set< std::pair > PixelSet_t; ///< just a redefinition std::vector< pointList > _true_photon_v; /// list of 3d points representing the shower trunk + std::vector< std::vector > _true_photon_plane_trunkimg_vv; + std::vector< std::vector< PixelSet_t > > _true_photon_plane_pixset_vv; + std::vector< std::vector< float > > _true_photon_plane_pixsum_vv; std::map< int, int > _nodeidx_to_photonlist_index_v; /// map from node.nodeidx to index in _true_photon_v pointList _empty_photon_pointlist_v; + std::vector _empty_pixsum_v; std::vector fixingPhotonStartPoints( Node_t& node, const std::vector& instance_v, @@ -249,6 +254,8 @@ namespace mctools { const pointList& getTruePhotonTrunk3DPoints( int trackid ); std::vector getTruePhotonTrunkPlanePixelSums( int trackid ); std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ); + std::vector< MCPixelPGraph::PixelSet_t > getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, + std::vector& pixsum_v ); protected: From 515e1e8452a66d85458221930ba50beb45419663 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sat, 17 Aug 2024 14:24:11 -0400 Subject: [PATCH 48/80] make clear the getter functions for true photon information --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 172 +++++++++------------------ ublarcvapp/MCTools/MCPixelPGraph.h | 16 ++- 2 files changed, 67 insertions(+), 121 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 728fb85..ac31369 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -1970,7 +1970,7 @@ namespace mctools { // making pixellist const int nplanes = adc_v.size(); std::vector plane_pixsum_v( nplanes, 0.0 ); - std::vector< PixelSet_t > plane_pixsets_v = getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); + std::vector< PixelSet_t > plane_pixsets_v = _getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); // making image masks std::vector< larcv::Image2D > trunk_planeimg_v; @@ -2128,124 +2128,64 @@ namespace mctools { std::vector pixsum_v = _true_photon_plane_pixsum_vv.at( it_pixsum->second ); return pixsum_v; - - // const pointList& photonpts = getTruePhotonTrunk3DPoints( trackid ); - // if ( photonpts.size()==0 ) { - // return pixelsum_v; - // } - - // // this pointer is saved when buildgraph(...) is called - // // it is cleared (set to nullptr) when clear() is called. - // if ( ev_adc==nullptr ) { - // std::stringstream msg; - // //msg << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] [ERROR]: Missing ADC image for summing pixel values" << std::endl; - // msg << "Missing ADC image for summing pixel values" << std::endl; - // LARCV_DEBUG() << msg.str(); - // throw std::runtime_error( msg.str() ); - // } - - // std::cout << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSums] : number of photon pts = " << photonpts.size() << std::endl; - // auto itg = _nodeidx_to_photonlist_index_v - - // const int nplanes = ev_adc->Image2DArray().size(); - // std::vector out_of_imgpix(nplanes,0); - // pixelsum_v.resize(3,0); + }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) - // std::vector trunk_planeimg_v; + /** + * @brief Get the sum of pixel values around the trunk plane + */ + const std::vector< MCPixelPGraph::PixelSet_t >& + MCPixelPGraph::getTruePhotonTrunkPlanePixelSets( int trackid ) + { + // we want to sum using a kernel (3x3) pixels. We want to avoid double counting, + // so we must mark which pixels we used + Node_t* pnode = findTrackID( trackid ); + if ( pnode==nullptr ) { + std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find particle Node pointer for " + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; + _empty_pixelset_v.clear(); + return _empty_pixelset_v; + } - // for (int p=0; p<(int)ev_adc->Image2DArray().size(); p++) { - // auto const& img = ev_adc->Image2DArray().at(p); - - // std::set< std::pair > _pix_used; - - // // loop over 3d points - // for (int ipt=0; ipt<(int)photonpts.size(); ipt++) { - // auto& pt = photonpts.at(ipt); - // // get the point in the image - // std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], - // pt[1], - // pt[2], - // 0.0 ); - - // //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; - - // // sum over 3x3 kernel - // // first find center pixel - // int row_center = 0; - // int col_center = 0; - // try { - // row_center = img.meta().row( imgpos4[3] ); - // col_center = img.meta().col( imgpos4[p] ); - // } - // catch (...) { - // // out of image tick - // out_of_imgpix[p]++; - // continue; - // } - - // for (int dr=-dpix; dr<=dpix; dr++) { - // for (int dc=-dpix; dc<=dpix; dc++) { - // int r = row_center + dr; - // int c = col_center + dc; - - // auto it_pix = _pix_used.find( std::pair(r,c) ); - // if ( it_pix==_pix_used.end() ) { - // // did not find it in the set, so add it as part of the sum - // float pixval = 0.0; - // try { - // pixval = img.pixel( r, c ); - // _pix_used.insert( std::pair(r,c) ); - // pixelsum_v[p] += pixval; - // } - // catch (...) { - // // probably out of image - // out_of_imgpix[p]++; - // continue; - // } - // } - - // }//end of dc loop - // }//end of dr loop - - // }//end of point loop - - // std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; - - // // make an image - // int min_row = 999999; - // int max_row = 0; - // int min_col = 999999; - // int max_col = 0; - // for ( auto& pix : _pix_used ) { - // if ( min_row > pix.first ) min_row = pix.first; - // if ( max_row < pix.first ) max_row = pix.first; - // if ( min_col > pix.second ) min_col = pix.second; - // if ( min_col < pix.second ) max_col = pix.second; - // } - // auto const& meta = img.meta(); - // int colcount = max_col-min_col+1; - // int rowcount = max_row-min_row+1; - // float width = float( colcount ); - // float height = meta.pixel_height()*rowcount; - // float origin_x = float( meta.pos_x( min_col ) ); - // float origin_y = float( meta.pos_y( min_row ) ); - // larcv::ImageMeta trunk_meta( width, height, rowcount, colcount, origin_x, origin_y, meta.plane() ); - // larcv::Image2D trunk_img( trunk_meta ); - // trunk_img.paint(0.0); - - // // fill the mask - // for (auto& pix : _pix_used ) { - // trunk_img.set_pixel( pix.second, pix.first, 1.0 ); - // } - - // trunk_planeimg_v.emplace_back( std::move(trunk_img) ); - - // }//end of plane loop + auto it_pixsum = _nodeidx_to_photonlist_index_v.find( pnode->nodeidx ); + if ( it_pixsum==_nodeidx_to_photonlist_index_v.end() ) { + LARCV_ERROR() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; + } + + return _true_photon_plane_pixset_vv.at( it_pixsum->second ); + } + + /** + * @brief Get larcv image containing trunk pixels + */ + const std::vector< larcv::Image2D >& + MCPixelPGraph::getTruePhotonTrunkPlaneImage2DMasks( int trackid ) + { + + Node_t* pnode = findTrackID( trackid ); + if ( pnode==nullptr ) { + LARCV_WARNING() << "[MCPixelPGraph::getTruePhotonTrunkPlanePixelSets] " + << " [WARNING]: did not find particle Node pointer for " + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; + _empty_imagemask_v.clear(); + return _empty_imagemask_v; + } + + auto it_pixsum = _nodeidx_to_photonlist_index_v.find( pnode->nodeidx ); + if ( it_pixsum==_nodeidx_to_photonlist_index_v.end() ) { + LARCV_ERROR() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; + } - // return pixelsum_v; + return _true_photon_plane_trunkimg_vv.at( it_pixsum->second ); - }// end of MCPixelPGraph::getTruePhotonTrunkPlanePixelSums( int trackid ) + } + /** + * @brief Does the calculation to get the pixels in each plane corresponding to 3D points of true shower trunk + */ std::vector MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ) { @@ -2329,8 +2269,8 @@ namespace mctools { * */ std::vector< MCPixelPGraph::PixelSet_t > - MCPixelPGraph::getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, - std::vector& pixsum_v ) { + MCPixelPGraph::_getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, + std::vector& pixsum_v ) { std::vector< MCPixelPGraph::PixelSet_t > plane_pixsets_v; const int nplanes = ev_adc->Image2DArray().size(); diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 0b237b6..7a92c33 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -231,7 +231,7 @@ namespace mctools { // variables and functions for making better quantities to // characterize true photons - + protected: float photon_start_edep_radius_cm; float photon_start_pixval_threshold; int photon_start_min_cluster_size; @@ -244,20 +244,26 @@ namespace mctools { std::map< int, int > _nodeidx_to_photonlist_index_v; /// map from node.nodeidx to index in _true_photon_v pointList _empty_photon_pointlist_v; std::vector _empty_pixsum_v; + std::vector< MCPixelPGraph::PixelSet_t > _empty_pixelset_v; + std::vector< larcv::Image2D > _empty_imagemask_v; std::vector fixingPhotonStartPoints( Node_t& node, const std::vector& instance_v, const std::vector& ancestor_v, const std::vector& adc_v, const std::vector& larflow_v ); + std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ); + std::vector< MCPixelPGraph::PixelSet_t > _getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, + std::vector& pixsum_v ); + + //* Functions to get info about the true photon trunk energy deposits and pixels */ + public: const pointList& getTruePhotonTrunk3DPoints( Node_t& node ); const pointList& getTruePhotonTrunk3DPoints( int trackid ); std::vector getTruePhotonTrunkPlanePixelSums( int trackid ); - std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ); - std::vector< MCPixelPGraph::PixelSet_t > getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, - std::vector& pixsum_v ); + const std::vector< MCPixelPGraph::PixelSet_t >& getTruePhotonTrunkPlanePixelSets( int trackid ); + const std::vector< larcv::Image2D >& getTruePhotonTrunkPlaneImage2DMasks( int trackid ); - protected: larlite::event_mctrack* ev_mctrack; From f58e2d3204ef675054f98a90a807256365f24e2e Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 19 Aug 2024 17:39:17 -0400 Subject: [PATCH 49/80] fixed a lot of tabs so it looks good in vscode --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 846 +++++++++++++++------------ ublarcvapp/MCTools/MCPixelPGraph.h | 42 +- 2 files changed, 491 insertions(+), 397 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index ac31369..f64d303 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -61,15 +61,15 @@ namespace mctools { // next we fix photons for ( auto& node : node_v ) { if ( node.pid==22 ) { - std::vector startpt_info - = fixingPhotonStartPoints( node, - ev_ins->as_vector(), ev_anc->as_vector(), - ev_adc->as_vector(), ev_larflow->as_vector() ); - // update edep position of the node - for (int v=0; v<4; v++) { - node.first_edep_pos[v] = startpt_info[v]; - node.imgpos4_edep[v] = startpt_info[4+v]; - } + std::vector startpt_info + = fixingPhotonStartPoints( node, + ev_ins->as_vector(), ev_anc->as_vector(), + ev_adc->as_vector(), ev_larflow->as_vector() ); + // update edep position of the node + for (int v=0; v<4; v++) { + node.first_edep_pos[v] = startpt_info[v]; + node.imgpos4_edep[v] = startpt_info[4+v]; + } } } } @@ -225,13 +225,13 @@ namespace mctools { if ( tracknode.origin==1 ) { - // store nu particle - NuPart_t nuparticle; - nuparticle.geantid = tracknode.tid; - nuparticle.pdg = tracknode.pid; - nuparticle.E_MeV = mct.Start().E(); - nuparticle.pos = tracknode.start; - nu_part_v.push_back( nuparticle ); + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = tracknode.tid; + nuparticle.pdg = tracknode.pid; + nuparticle.E_MeV = mct.Start().E(); + nuparticle.pos = tracknode.start; + nu_part_v.push_back( nuparticle ); } @@ -383,15 +383,17 @@ namespace mctools { showernode.imgpos4_start.resize(4,0); } } - if ( showernode.origin==1 ) { - // store nu particle - NuPart_t nuparticle; - nuparticle.geantid = showernode.tid; - nuparticle.pdg = showernode.pid; - nuparticle.E_MeV = mcsh.Start().E(); - nuparticle.pos = std::vector{ (float)mcsh.Start().X(), (float)mcsh.Start().Y(), (float)mcsh.Start().Z(), (float)mcsh.Start().T() }; - nu_part_v.push_back( nuparticle ); + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = showernode.tid; + nuparticle.pdg = showernode.pid; + nuparticle.E_MeV = mcsh.Start().E(); + nuparticle.pos = std::vector{ (float)mcsh.Start().X(), + (float)mcsh.Start().Y(), + (float)mcsh.Start().Z(), + (float)mcsh.Start().T() }; + nu_part_v.push_back( nuparticle ); } tid_list.insert( showernode.tid ); @@ -402,9 +404,9 @@ namespace mctools { long smallest_nu_tid = -1; for ( auto& node : node_v ) { if ( node.origin==1 ) { - if (smallest_nu_tid<0 || node.tid < smallest_nu_tid ) { - smallest_nu_tid = node.tid; - } + if (smallest_nu_tid<0 || node.tid < smallest_nu_tid ) { + smallest_nu_tid = node.tid; + } } } LARCV_DEBUG() << "Smallest neutrino Geant4 Track ID: " << smallest_nu_tid << std::endl; @@ -417,33 +419,35 @@ namespace mctools { int matched_geant_id = -1; for ( auto& mctruth : mctruth_v ) { for ( auto& part : mctruth.GetParticles() ) { - if ( part.StatusCode()==1 ) { - ifs_1 += 1; - // does ginal state particel match any of the geant4 particles? - for (auto& nupart : nu_part_v) { - - // match pdg - if ( nupart.pdg!=part.PdgCode() ) - continue; - - // match energy - float dE_MeV = std::fabs(nupart.E_MeV-part.Momentum(0)[3]*1000.0); - LARCV_DEBUG() << "mctruth part: " << dE_MeV << std::endl; - if ( dE_MeV > 10.0 ) - continue; - - matched_fs = ifs_1; - matched_geant_id = nupart.geantid; - LARCV_DEBUG() << "have first match. genie finalstate id=" << matched_fs << " geantid=" << matched_geant_id << std::endl; - break; - } + if ( part.StatusCode()==1 ) { + ifs_1 += 1; + // does ginal state particel match any of the geant4 particles? + for (auto& nupart : nu_part_v) { + // match pdg + if ( nupart.pdg!=part.PdgCode() ) + continue; + + // match energy + float dE_MeV = std::fabs(nupart.E_MeV-part.Momentum(0)[3]*1000.0); + LARCV_DEBUG() << "mctruth part: " << dE_MeV << std::endl; + if ( dE_MeV > 10.0 ) + continue; + + matched_fs = ifs_1; + matched_geant_id = nupart.geantid; + LARCV_DEBUG() << "have first match. " + << "genie finalstate id=" << matched_fs + << " geantid=" << matched_geant_id + << std::endl; + break; + } - }//end of if status code - if (matched_fs>=0) - break; + }//end of if status code + if (matched_fs>=0) + break; }//end of mcpart loop if (matched_fs>=0) - break; + break; }//end of mctruth loop int geantid_offset = smallest_nu_tid - (matched_fs-1); @@ -455,55 +459,55 @@ namespace mctools { for ( auto& mctruth : mctruth_v ) { int imcpart = 0; for ( auto& part : mctruth.GetParticles() ) { - LARCV_DEBUG() << " mcpart[" << imctruth << "," << imcpart << "] -------" << std::endl; - LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; - LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; - LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; - LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; - LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; - LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; + LARCV_DEBUG() << " mcpart[" << imctruth << "," << imcpart << "] -------" << std::endl; + LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; + LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; + LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; + LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; + LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; + LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; - if ( part.StatusCode()==1 ) { - int geant_trackid = geantid_offset + ifs; - LARCV_DEBUG() << " Stable Final State. Implied Geant4 ID = " << geant_trackid << std::endl; - ifs++; - - auto it_tid = tid_list.find(geant_trackid); - if (it_tid==tid_list.end() ) { - int nodeidx = node_v.size(); - int type = 3; // genie-final-state - int tid = geant_trackid; - int vidx = imcpart; - int pid = part.PdgCode(); - Node_t* mother = nullptr; - int mid = -1; - float energy = part.Momentum(0)[3]*1e3 - part.Mass()*1.0e3; // in GeV, convert to MeV - std::vector start { (float)part.Position(0)[0], - (float)part.Position(0)[1], - (float)part.Position(0)[2], - (float)part.Position(0)[3]}; - std::vector imgpos4(4,0); - _get_imgpos( start, imgpos4, sce, true ); - - //LARCV_DEBUG() << "Creating Mother node from GENIE final states: tid=" << tid << " type=" << 3 << std::endl; - Node_t fsnode( nodeidx, type, tid, vidx, pid, mother, mid, energy, "primary" ); - fsnode.start = start; - fsnode.imgpos4 = imgpos4; - fsnode.mtid = tid; - fsnode.aid = tid; - fsnode.origin = 1; // neutrino origin (from genie) - LARCV_DEBUG() << "Add Genie Final State Particle to initial List: tid=" << tid << " pdg=" << pid << std::endl; - node_v.emplace_back( std::move(fsnode) ); - } - else { - LARCV_DEBUG() << "Genie Final State Partial [tid=" << geant_trackid << "] Already in MCReco List" << std::endl; - } - } - imcpart++; + if ( part.StatusCode()==1 ) { + int geant_trackid = geantid_offset + ifs; + LARCV_DEBUG() << " Stable Final State. Implied Geant4 ID = " << geant_trackid << std::endl; + ifs++; + + auto it_tid = tid_list.find(geant_trackid); + if (it_tid==tid_list.end() ) { + int nodeidx = node_v.size(); + int type = 3; // genie-final-state + int tid = geant_trackid; + int vidx = imcpart; + int pid = part.PdgCode(); + Node_t* mother = nullptr; + int mid = -1; + float energy = part.Momentum(0)[3]*1e3 - part.Mass()*1.0e3; // in GeV, convert to MeV + std::vector start { (float)part.Position(0)[0], + (float)part.Position(0)[1], + (float)part.Position(0)[2], + (float)part.Position(0)[3]}; + std::vector imgpos4(4,0); + _get_imgpos( start, imgpos4, sce, true ); + + //LARCV_DEBUG() << "Creating Mother node from GENIE final states: tid=" << tid << " type=" << 3 << std::endl; + Node_t fsnode( nodeidx, type, tid, vidx, pid, mother, mid, energy, "primary" ); + fsnode.start = start; + fsnode.imgpos4 = imgpos4; + fsnode.mtid = tid; + fsnode.aid = tid; + fsnode.origin = 1; // neutrino origin (from genie) + LARCV_DEBUG() << "Add Genie Final State Particle to initial List: tid=" << tid << " pdg=" << pid << std::endl; + node_v.emplace_back( std::move(fsnode) ); + } + else { + LARCV_DEBUG() << "Genie Final State Partial [tid=" << geant_trackid << "] Already in MCReco List" << std::endl; + } + } + imcpart++; } imctruth++; } - + // try to connect primary neutrino origin nodes to mctruth info //_adoptNeutrinoOrphans( &mctruth_v ); @@ -557,12 +561,12 @@ namespace mctools { } } else if (node.type==3) { - // genie fs nodes - // connet to ROOT node as they are primary by definition - mothernode = &(node_v[0]); + // genie fs nodes + // connet to ROOT node as they are primary by definition + mothernode = &(node_v[0]); } else { - continue; + continue; } if (mothernode) { @@ -588,8 +592,9 @@ namespace mctools { /** * @brief wrapper function to retrieve Node's corresponding mctrack object from larlite container */ - const larlite::mctrack& MCPixelPGraph::_retrieve_mctrackobject( const Node_t* node, - const larlite::event_mctrack& ev_track_v ) + const larlite::mctrack& + MCPixelPGraph::_retrieve_mctrackobject( const Node_t* node, + const larlite::event_mctrack& ev_track_v ) { try { const larlite::mctrack& x = ev_track_v.at(node->vidx); @@ -1646,6 +1651,8 @@ namespace mctools { /** * @brief use larflow truth to make 3D spacepoints for a given particle * + * we return all points formed by the intersections + * * @return a vector of 3d positions * */ @@ -1670,24 +1677,31 @@ namespace mctools { float pos[3]; int posid[3]; bool operator<( const flowpt& rhs ) const { - if (posid[0]rhs.posid[0]) - return false; - // neither so [0] must be equal - - if (posid[1]rhs.posid[1]) - return false; - - // neither [1] worked, so must be equal - if (posid[2]rhs.posid[0]) + return false; + // neither so [0] must be equal + + if (posid[1]rhs.posid[1]) + return false; + + // neither [1] worked, so must be equal + if (posid[2] larfow image with index-0 (out of 6) contains the map from U pixels [0] mapped to pixels in the V plane (=1) + // targetmap[0][1] = 2 --> larfow image with index-1 (out of 6) contains the map from U pixels [0] mapped to pixels in the Y plane (=2) + // targetmap[1][0] = 0 --> larfow image with index-2 (out of 6) contains the map from V pixels [1] mapped to pixels in the U plane (=0) + // .. etc .. int targetmap[3][2] = { {1,2}, {0,2}, {0,1} }; @@ -1697,86 +1711,128 @@ namespace mctools { std::set< flowpt > pt_v; + // we loop over the pixels in the wire plane image that has been + // associated to this particle node for (size_t p=0; pPlaneWireToChannel( (UInt_t)src_plane, (UInt_t)wire ); + UInt_t tar_ch = larutil::Geometry::GetME()->PlaneWireToChannel( (UInt_t)tar_plane, (UInt_t)tar_wire ); + Double_t y,z; + bool crosses = larutil::Geometry::GetME()->ChannelsIntersect( src_ch, tar_ch, y, z ); + // check that the intersection point provided is inside the TPC. + // if inside, crosses==true + if ( crosses ) { + // create a spacepoint object, inside the TPC + flowpt pt; + pt.source_plane = src_plane; + pt.source_wire = wire; + pt.target_plane = tar_plane; + pt.target_wire = tar_wire; + pt.source_trackid = node.tid; + pt.target_trackid = 0; // not filled for now + pt.src_pixval = adc_v.at(src_plane).pixel( row, (unsigned int)col ); + pt.pos[1] = y; + pt.pos[2] = z; + pt.pos[0] = (tick-3200.0)*0.5*larutil::LArProperties::GetME()->DriftVelocity(); //< to do, need larutil function to make experiment agnostic + + // convert the flow into an integer 'posid' set of indices. + // posid is effectively defining a voxelized grid + // we do this to avoid close duplicate 3d pts + pt.posid[0] = (int)(pt.pos[0]*1000); + pt.posid[1] = (int)(pt.pos[1]*1000); + pt.posid[2] = (int)(pt.pos[2]*1000); + // look for the posid triplet in our set + auto it_pt = pt_v.find( pt ); + if ( it_pt==pt_v.end() ) { + // a new index, insert into the set + //std::cout << " insert intersection: (" << pt.pos[0] << "," << pt.pos[1] << "," << pt.pos[2] << ")" << std::endl; + pt_v.insert(pt); + } + else { + // if we had a previous intersection at this 3d point, we use the one with the largest + // energy deposition. + // (note: this might actual bias towards suprious intersections due to overlapping ionization due to tomographic projection) + // (note: but, since we restrict to node-only pixels, probably ok. no issues seen so far. so probably minor.) + if ( (*it_pt).src_pixval < pt.src_pixval ) { + // std::cout << " replace src plane [" << (*it_pt).source_plane << " to " << pt.source_plane << "] " + // << " with higher pixval " << (*it_pt).src_pixval << " vs. " << pt.src_pixval + // << std::endl; + pt_v.insert(pt); // replaces? + } + } + } //end of if possible wire intersection found (and calculated) + else { + //std::cout << " failed intersection: (" << y << ", " << z << ")" << std::endl; + } + } // end of loop over pixels in pix_vv list + }// end of loop over flow directions (2 of them) }//end of loop over planes std::cout << "Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; std::cout << " Number of spacepoints found from using larflow: " << pt_v.size() << std::endl; + // store the points into our storage vector, pos_vv, which we return. for (auto& pt_info : pt_v ) { pos_vv.push_back( std::vector{ pt_info.pos[0], pt_info.pos[1], pt_info.pos[2] } ); } @@ -1814,156 +1870,190 @@ namespace mctools { // int shower_mid = node.mid; // int shower_tid = node.tid; + // created 3d points of energy deposition from truth information saved in + // the larflow images. The larflow images encode 2D wire-intersections + // which provide (Y,Z) positions in the detector. The X position is + // inferred by the drift time relative to the beam trigger (at tick 3200). + // We only build 3d points coming from pixels associated with the node. pointList pos_vv = makeNode3DpointsFromLArFlowTruth( node, adc_v, larflow_v ); - std::cout << "================================================================" << std::endl; - std::cout << "[fixingPhotonStartPoints]" << std::endl; - std::cout << " Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; - std::cout << " Number of spacepoints found from using larflow: " << pos_vv.size() << std::endl; + LARCV_INFO() << "================================================================" << std::endl; + LARCV_INFO() << " Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; + LARCV_INFO() << " Number of spacepoints found from using larflow: " << pos_vv.size() << std::endl; - float mindist = 1.0e9; + // get the position where the photon was created + // note: not the same as the location where it first interacted std::vector start_reco_pt = MCPos2ImageUtils::Get()->truepos_to_recopos( node.start[0], node.start[1], node.start[2], node.start[3], true, true ); - std::cout << " Find closest to start point: (" << start_reco_pt[0] << "," + LARCV_DEBUG() << " Find closest cluster to start point: (" << start_reco_pt[0] << "," << start_reco_pt[1] << ", " << start_reco_pt[2] << ", " << start_reco_pt[3] << " usec)" << std::endl; + // ensure the shower_start_pt vector has 4 components + // it will store (x,y,z,t) shower_start_pt.resize(4); + // we want to define the "trunk" cluster of the shower. + // first, convert the information into the form our clustering algorithm needs. std::vector< std::vector > data_v; - + // loop over the 3d points for ( auto& pt : pos_vv ) { //std::cout << "3d pt: (" << pt[0] << ", " << pt[1] << ", " << pt[2] << ") " << std::endl; - float dist_edep = 0.; - float dx = 0.; - for (int v=0; v<3; v++) { - dx = pt[v] - node.first_edep_pos[v]; - dist_edep += dx*dx; - } - dist_edep = sqrt(dist_edep); + // // calculate distance of 3d point to first energy deposition point + // float dist_edep = 0.; + // float dx = 0.; + // for (int v=0; v<3; v++) { + // dx = pt[v] - node.first_edep_pos[v]; + // dist_edep += dx*dx; + // } + // dist_edep = sqrt(dist_edep); // if ( dist_edep>photon_start_edep_radius_cm || pt.src_pixval xpt(4,0); for (int v=0; v<3; v++) - xpt[v] = pt[v]; - // add time dim + xpt[v] = pt[v]; + // add time dim, but put in a useless value. xpt[3] = 0.0; data_v.push_back( xpt ); } - + // use our interface to DBScan auto dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( 0.3, 3, 50, data_v ); + + // loop through the cluster and find the closest one + // that qualifies in terms of size int icluster = -1; float closest_qualified_cluster_dist = 1.0e9; - for (int i=0; i<(int)dbcluster_v.size(); i++) { // we calculate the pixel sum in each plane of each cluster. // (this is costly -- if it starts to be too slow -- we will need some thresholding with easy measures) int nhits = dbcluster_v.at(i).size(); + // ignore small clusters if ( nhits<5 ) - continue; + continue; + // find closest distance to photon start/creation point float cluster_min_dist_to_source = 1e9; + // extract the points for the given cluster (with index i) pointList cluster_pt_v; cluster_pt_v.reserve(nhits); for (int ipt=0; ipt pixsum_v = getPlanePixelSumsFromPointList( cluster_pt_v ); // another threshold: one plane must pass 10 MeV threshol - // using MeV = 0.00162*pixsum + // using MeV = 0.00162*pixsum, from matt's conversion formula int planes_passing = 0; //std::cout << "cluster[" << i << "] dist-to-source=" << cluster_min_dist_to_source << " cm; plane MeV: ("; for ( int p=0; p<(int)pixsum_v.size(); p++ ) { - float MeV = pixsum_v[p]*0.0162; - //std::cout << MeV; - // if ( p+120.0 ) { - planes_passing++; - } + float MeV = pixsum_v[p]*0.0162; + //std::cout << MeV; + // if ( p+120.0 ) { + planes_passing++; + } } //std::cout << ")" << std::endl; + // check if cluster passes 'detectability criterion' + // and, if so, is the closest cluster to the creation point of the photon if ( planes_passing>=2 && cluster_min_dist_to_source < closest_qualified_cluster_dist ) { - closest_qualified_cluster_dist = cluster_min_dist_to_source; - icluster = i; + closest_qualified_cluster_dist = cluster_min_dist_to_source; + icluster = i; } - } + }//end of loop over all hits - - pointList trunk_pt_v; - if ( icluster<0 ) { + // container to store our trunk points + pointList trunk_pt_v; + + if ( icluster<0 ) { + // if we did not find a valid cluster, + // we count this shower as unreconstructable. + // we define a sentinal value for the starting energy deposition point shower_start_pt = std::vector{ -1.0, -1.0, -1.0 }; - } + } else { + // a valid cluster is found. store the points for this cluster auto& largest_cluster = dbcluster_v.at(icluster); + // we also find the min distance between a hit in the cluster + // and the starting reco point. + // this 3d point will serve as the true first energy deposit point + float mindist = 1.0e9; for (int ipt=0; ipt<(int)largest_cluster.size(); ipt++) { - auto& xpt = data_v.at( largest_cluster.at(ipt) ); - float dist = 0; - for (int v=0; v<3; v++) { - float dx = xpt[v]-start_reco_pt[v]; - dist += dx*dx; - } - dist = sqrt(dist); - if ( distDriftVelocity()) + 3200; - mindist = dist; - } - trunk_pt_v.push_back( xpt ); + auto& xpt = data_v.at( largest_cluster.at(ipt) ); + float dist = 0; + for (int v=0; v<3; v++) { + float dx = xpt[v]-start_reco_pt[v]; + dist += dx*dx; + } + dist = sqrt(dist); + if ( distDriftVelocity()) + 3200; + mindist = dist; + } + trunk_pt_v.push_back( xpt ); }//end of loop over largest cluster points (by index) + LARCV_DEBUG() << " minimum dist to shower startpt: " << mindist << " cm" << std::endl; } - std::cout << " minimum dist to shower startpt: " << mindist << " cm" << std::endl; - std::cout << " startpt: (" << shower_start_pt[0] << "," + LARCV_INFO() << " startpt: (" << shower_start_pt[0] << "," << shower_start_pt[1] << "," << shower_start_pt[2] << "," << shower_start_pt[3] << " ticks)" << std::endl; + // convert the first interaction point (x,y,z,t) position into + // image coordinates which are (u,v,y,tick) float t_ns = (shower_start_pt[3]-3200)*0.5*1000.0+3050.0; // ticks to ns std::vector shower_imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( shower_start_pt[0], shower_start_pt[1], shower_start_pt[2], t_ns ); - std::cout << " imgpos: (" << shower_imgpos4[0] << ", " + LARCV_INFO() << " imgpos: (" << shower_imgpos4[0] << ", " << shower_imgpos4[1] << ", " << shower_imgpos4[2] << ", " << shower_imgpos4[3] << " ticks )" << std::endl; + // append the imgcoordantes to the out-going vector for (int v=0; v<4; v++) shower_start_pt.push_back( shower_imgpos4[v] ); // get an index for this true photon pointList + // we will use it to store information about this trunk + // and then retrieve it later. int photon_point_list_index = (int)_true_photon_v.size(); _nodeidx_to_photonlist_index_v[ node.nodeidx ] = photon_point_list_index; @@ -1980,20 +2070,25 @@ namespace mctools { auto& pixset = plane_pixsets_v.at(p); // make an image + // we also keep track of the min/max for the + // rows and columns. this defines + // a bounding box we need to define the image mask + // crop bounds. int min_row = 999999; int max_row = 0; int min_col = 999999; int max_col = 0; - + // loop over the pixels in order to find axis-aligned bounding box for ( auto& pix : pixset ) { - int pix_row = pix.first; - int pix_col = pix.second; - if ( min_row > pix_row ) min_row = pix_row; - if ( max_row < pix_row ) max_row = pix_row; - if ( min_col > pix_col ) min_col = pix_col; - if ( max_col < pix_col ) max_col = pix_col; + int pix_row = pix.first; + int pix_col = pix.second; + if ( min_row > pix_row ) min_row = pix_row; + if ( max_row < pix_row ) max_row = pix_row; + if ( min_col > pix_col ) min_col = pix_col; + if ( max_col < pix_col ) max_col = pix_col; } + // define the imagemeta to make the cropped larcv::Image2d object auto const& meta = img.meta(); int colcount = max_col-min_col+1; int rowcount = max_row-min_row+1; @@ -2011,23 +2106,23 @@ namespace mctools { LARCV_DEBUG() << trunk_meta.dump() << std::endl; LARCV_DEBUG() << "original meta: " << meta.dump() << std::endl; - //fill the mask + // loop over the pixels and fill the mask for (auto& pix : pixset ) { - int pix_row = pix.first; - int pix_col = pix.second; - //LARCV_DEBUG() << " set pixel (row,col)=(" << pix_row << ", " << pix_col << ") " << std::endl; - try { - trunk_img.set_pixel( pix_row-min_row, pix_col-min_col, 1.0 ); - } - catch (...) { - LARCV_ERROR() << "pixel (row,col)=(" << pix_row << "," << pix_col << ") is outside crop." << std::endl; - } + int pix_row = pix.first; + int pix_col = pix.second; + //LARCV_DEBUG() << " set pixel (row,col)=(" << pix_row << ", " << pix_col << ") " << std::endl; + try { + trunk_img.set_pixel( pix_row-min_row, pix_col-min_col, 1.0 ); + } + catch (...) { + LARCV_ERROR() << "pixel (row,col)=(" << pix_row << "," << pix_col << ") is outside crop." << std::endl; + } } + // store the image in the plane container trunk_planeimg_v.emplace_back( std::move(trunk_img) ); }//end of plane loop - // store all of this stuff _true_photon_v.emplace_back( std::move(trunk_pt_v) ); @@ -2062,11 +2157,11 @@ namespace mctools { auto it_pointlist = _nodeidx_to_photonlist_index_v.find( node.nodeidx ); if ( it_pointlist==_nodeidx_to_photonlist_index_v.end() ) { std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find photonlist for " - << " nodeidx=" << node.nodeidx - << " pdg=" << node.pid - << " trackid=" << node.tid << ". " - << "Returning emptry point list." - << std::endl; + << " nodeidx=" << node.nodeidx + << " pdg=" << node.pid + << " trackid=" << node.tid << ". " + << "Returning emptry point list." + << std::endl; _empty_photon_pointlist_v.clear(); return _empty_photon_pointlist_v; } @@ -2075,9 +2170,9 @@ namespace mctools { if ((int)index<0 || index>=_true_photon_v.size() ) { std::stringstream msg; msg << "Missing photon list index! node.trackid=" << node.tid - << " map.trackid=" << it_pointlist->first - << " map.index=" << it_pointlist->second - << std::endl; + << " map.trackid=" << it_pointlist->first + << " map.index=" << it_pointlist->second + << std::endl; throw std::runtime_error( msg.str() ); } @@ -2093,9 +2188,9 @@ namespace mctools { Node_t* pnode = findTrackID( trackid ); if ( pnode==nullptr ) { std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not particle Node for " - << " trackid=" << pnode->tid << ". " - << "Returning emptry point list." - << std::endl; + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; _empty_photon_pointlist_v.clear(); return _empty_photon_pointlist_v; } @@ -2113,9 +2208,9 @@ namespace mctools { Node_t* pnode = findTrackID( trackid ); if ( pnode==nullptr ) { std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find particle Node pointer for " - << " trackid=" << pnode->tid << ". " - << "Returning emptry point list." - << std::endl; + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; _empty_photon_pointlist_v.clear(); return _empty_pixsum_v; } @@ -2141,9 +2236,9 @@ namespace mctools { Node_t* pnode = findTrackID( trackid ); if ( pnode==nullptr ) { std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find particle Node pointer for " - << " trackid=" << pnode->tid << ". " - << "Returning emptry point list." - << std::endl; + << " trackid=" << pnode->tid << ". " + << "Returning emptry point list." + << std::endl; _empty_pixelset_v.clear(); return _empty_pixelset_v; } @@ -2209,52 +2304,52 @@ namespace mctools { // loop over 3d points for (int ipt=0; ipt<(int)pointlist.size(); ipt++) { - auto& pt = pointlist.at(ipt); - // get the point in the image - std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], - pt[1], - pt[2], - 0.0 ); - - //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; + auto& pt = pointlist.at(ipt); + // get the point in the image + std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], + pt[1], + pt[2], + 0.0 ); + + //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; - // sum over 3x3 kernel - // first find center pixel - int row_center = 0; - int col_center = 0; - try { - row_center = img.meta().row( imgpos4[3] ); - col_center = img.meta().col( imgpos4[p] ); - } - catch (...) { - // out of image tick - out_of_imgpix[p]++; - continue; - } + // sum over 3x3 kernel + // first find center pixel + int row_center = 0; + int col_center = 0; + try { + row_center = img.meta().row( imgpos4[3] ); + col_center = img.meta().col( imgpos4[p] ); + } + catch (...) { + // out of image tick + out_of_imgpix[p]++; + continue; + } - for (int dr=-dpix; dr<=dpix; dr++) { - for (int dc=-dpix; dc<=dpix; dc++) { - int r = row_center + dr; - int c = col_center + dc; - - auto it_pix = _pix_used.find( std::pair(r,c) ); - if ( it_pix==_pix_used.end() ) { - // did not find it in the set, so add it as part of the sum - float pixval = 0.0; - try { - pixval = img.pixel( r, c ); - _pix_used.insert( std::pair(r,c) ); - pixsum_v[p] += pixval; - } - catch (...) { - // probably out of image - out_of_imgpix[p]++; - continue; - } - } - - }//end of dc loop - }//end of dr loop + for (int dr=-dpix; dr<=dpix; dr++) { + for (int dc=-dpix; dc<=dpix; dc++) { + int r = row_center + dr; + int c = col_center + dc; + + auto it_pix = _pix_used.find( std::pair(r,c) ); + if ( it_pix==_pix_used.end() ) { + // did not find it in the set, so add it as part of the sum + float pixval = 0.0; + try { + pixval = img.pixel( r, c ); + _pix_used.insert( std::pair(r,c) ); + pixsum_v[p] += pixval; + } + catch (...) { + // probably out of image + out_of_imgpix[p]++; + continue; + } + } + + }//end of dc loop + }//end of dr loop }//end of point loop @@ -2290,60 +2385,57 @@ namespace mctools { // loop over 3d points for (int ipt=0; ipt<(int)pt_v.size(); ipt++) { - auto& pt = pt_v.at(ipt); - // get the point in the image - std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], - pt[1], - pt[2], - 0.0 ); - //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; - - // sum over 3x3 kernel - // first find center pixel - int row_center = 0; - int col_center = 0; - try { - row_center = img.meta().row( imgpos4[3] ); - col_center = img.meta().col( imgpos4[p] ); - } - catch (...) { - // out of image tick - out_of_imgpix[p]++; - continue; - } - - for (int dr=-dpix; dr<=dpix; dr++) { - for (int dc=-dpix; dc<=dpix; dc++) { - int r = row_center + dr; - int c = col_center + dc; - - auto it_pix = _pix_used.find( std::pair(r,c) ); - if ( it_pix==_pix_used.end() ) { - // did not find it in the set, so add it as part of the sum - float pixval = 0.0; - try { - pixval = img.pixel( r, c ); - _pix_used.insert( std::pair(r,c) ); - pixsum_v[p] += pixval; - } - catch (...) { - // probably out of image - out_of_imgpix[p]++; - continue; - } - } - - }//end of dc loop - }//end of dr loop - - }//end of point loop + auto& pt = pt_v.at(ipt); + // get the point in the image + std::vector imgpos4 = MCPos2ImageUtils::Get()->to_imagepos( pt[0], + pt[1], + pt[2], + 0.0 ); + //std::cout << " pt[" << ipt << "] imgpos4: (" << imgpos4[0] << ", " << imgpos4[1] << ", " << imgpos4[2] << ", " << imgpos4[3] << ")" << std::endl; + + // sum over 3x3 kernel + // first find center pixel + int row_center = 0; + int col_center = 0; + try { + row_center = img.meta().row( imgpos4[3] ); + col_center = img.meta().col( imgpos4[p] ); + } + catch (...) { + // out of image tick + out_of_imgpix[p]++; + continue; + } + for (int dr=-dpix; dr<=dpix; dr++) { + for (int dc=-dpix; dc<=dpix; dc++) { + int r = row_center + dr; + int c = col_center + dc; + + auto it_pix = _pix_used.find( std::pair(r,c) ); + if ( it_pix==_pix_used.end() ) { + // did not find it in the set, so add it as part of the sum + float pixval = 0.0; + try { + pixval = img.pixel( r, c ); + _pix_used.insert( std::pair(r,c) ); + pixsum_v[p] += pixval; + } + catch (...) { + // probably out of image + out_of_imgpix[p]++; + continue; + } + } + }//end of dc loop + }//end of dr loop + }//end of point loop + //std::cout << "PixelSum[" << p << "]: sum=" << pixelsum_v[p] << " npixels=" << _pix_used.size() << " out_of_img=" << out_of_imgpix[p] << std::endl; + plane_pixsets_v.emplace_back( std::move( _pix_used ) ); - plane_pixsets_v.emplace_back( std::move( _pix_used ) ); - }//end of plane loop - + return plane_pixsets_v; } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 7a92c33..19382b6 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -108,12 +108,12 @@ namespace mctools { vidx(-1), tid(-1), aid(-1), - mtid(-1), + mtid(-1), pid(-1), mother(nullptr), mid(-1), E_MeV(-1.0), - process("null"), + process("null"), start({0,0,0,0}), first_edep_pos({0,0,0,0}), first_tpc_pos({0,0,0,0}), @@ -123,7 +123,7 @@ namespace mctools { imgpos4_start({0,0,0,0}), origin(-1) { - daughter_v.clear(); + daughter_v.clear(); }; Node_t(int _nodeidx, int _type, int _tid, int _vidx, @@ -136,13 +136,13 @@ namespace mctools { type(_type), vidx(_vidx), tid(_tid), - aid(-1), - mtid(-1), + aid(-1), + mtid(-1), pid(_pid), mother(_mother), mid(_mid), E_MeV(_energy), - process(proc), + process(proc), start({0,0,0,0}), first_edep_pos({0,0,0,0}), first_tpc_pos({0,0,0,0}), @@ -159,27 +159,27 @@ namespace mctools { }; bool isTrackObject() const { - if ( type==0 ) - return true; - return false; + if ( type==0 ) + return true; + return false; }; bool isShowerObject() const { - if (type==1) - return true; - return false; + if (type==1) + return true; + return false; }; bool isNuVertexObject() const { - if (type==2) - return true; - return false; + if (type==2) + return true; + return false; }; bool isGenieFinalStateObject() const { - if (type==3) - return true; - return false; + if (type==3) + return true; + return false; }; }; @@ -231,12 +231,14 @@ namespace mctools { // variables and functions for making better quantities to // characterize true photons + typedef std::vector< std::vector > pointList; ///< just a redefinition for convenience + typedef std::set< std::pair > PixelSet_t; ///< just a redefinition for convenience + typedef std::vector< larcv::Image2D > ImageSet_t; ///< just a redefinition for convenience + protected: float photon_start_edep_radius_cm; float photon_start_pixval_threshold; int photon_start_min_cluster_size; - typedef std::vector< std::vector > pointList; ///< just a redefinition - typedef std::set< std::pair > PixelSet_t; ///< just a redefinition std::vector< pointList > _true_photon_v; /// list of 3d points representing the shower trunk std::vector< std::vector > _true_photon_plane_trunkimg_vv; std::vector< std::vector< PixelSet_t > > _true_photon_plane_pixset_vv; From 85c431c5c0efceb1a36c646bba6110150350169d Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 20 Aug 2024 14:38:06 -0400 Subject: [PATCH 50/80] formatting mostly. some commenting --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 154 +++++++++++++++----------- ublarcvapp/MCTools/MCPos2ImageUtils.h | 4 +- 2 files changed, 92 insertions(+), 66 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index f64d303..0091fc9 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -60,16 +60,18 @@ namespace mctools { // next we fix photons for ( auto& node : node_v ) { - if ( node.pid==22 ) { + if ( node.pid==22 || abs(node.pid)==11 ) { std::vector startpt_info = fixingPhotonStartPoints( node, ev_ins->as_vector(), ev_anc->as_vector(), ev_adc->as_vector(), ev_larflow->as_vector() ); - // update edep position of the node - for (int v=0; v<4; v++) { - node.first_edep_pos[v] = startpt_info[v]; - node.imgpos4_edep[v] = startpt_info[4+v]; - } + // update edep position of the node for photons only + if ( node.pid==22 ) { + for (int v=0; v<4; v++) { + node.first_edep_pos[v] = startpt_info[v]; + node.imgpos4_edep[v] = startpt_info[4+v]; + } + } } } } @@ -333,55 +335,55 @@ namespace mctools { bool x_isinf = false; if ( mcsh.DetProfile().X()>1.0e100 || mcsh.DetProfile().X()<-1.0e100 ) - x_isinf = true; + x_isinf = true; if ( !x_isinf && !std::isnan( mcsh.DetProfile().X() ) ) { - std::cout << "inf test: " << mcsh.DetProfile().X() << " " << std::isinf( mcsh.DetProfile().X() ) << std::endl; - std::vector detprofile = { (float)mcsh.DetProfile().X(), (float)mcsh.DetProfile().Y(), (float)mcsh.DetProfile().Z(), (float)mcsh.DetProfile().T() }; - showernode.first_edep_pos = detprofile; - showernode.first_tpc_pos = detprofile; - showernode.first_img_pos = detprofile; - //_get_imgpos( detprofile, showernode.imgpos4, sce, false ); - showernode.imgpos4 = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.first_edep_pos[0], - showernode.first_edep_pos[1], - showernode.first_edep_pos[2], - showernode.first_edep_pos[3], - true ); - if ( showernode.imgpos4.size()==0 ) - showernode.imgpos4.resize(4,0); - - if ( abs(showernode.pid)==11 ) { - showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], - showernode.start[1], - showernode.start[2], - showernode.start[3], - true ); - if ( showernode.imgpos4_edep.size()==0 ) - showernode.imgpos4_edep.resize(4,0); - - showernode.first_edep_pos = showernode.start; - } - else { - // photons - showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->to_imagepos( showernode.first_edep_pos[0], - showernode.first_edep_pos[1], - showernode.first_edep_pos[2], - showernode.first_edep_pos[3] ); - if ( showernode.imgpos4_edep.size()==0 ) { - showernode.imgpos4_edep.resize(4,0); - } - else { - showernode.imgpos4_edep[3] += 12.0; // hacky fix for photons - } - } - - showernode.imgpos4_start = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], - showernode.start[1], - showernode.start[2], - showernode.start[3], - true ); - if ( showernode.imgpos4_start.size()==0 ) { - showernode.imgpos4_start.resize(4,0); - } + //std::cout << "inf test: " << mcsh.DetProfile().X() << " " << std::isinf( mcsh.DetProfile().X() ) << std::endl; + std::vector detprofile = { (float)mcsh.DetProfile().X(), (float)mcsh.DetProfile().Y(), (float)mcsh.DetProfile().Z(), (float)mcsh.DetProfile().T() }; + showernode.first_edep_pos = detprofile; + showernode.first_tpc_pos = detprofile; + showernode.first_img_pos = detprofile; + //_get_imgpos( detprofile, showernode.imgpos4, sce, false ); + showernode.imgpos4 = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.first_edep_pos[0], + showernode.first_edep_pos[1], + showernode.first_edep_pos[2], + showernode.first_edep_pos[3], + true ); + if ( showernode.imgpos4.size()==0 ) + showernode.imgpos4.resize(4,0); + + if ( abs(showernode.pid)==11 ) { + showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], + showernode.start[1], + showernode.start[2], + showernode.start[3], + true ); + if ( showernode.imgpos4_edep.size()==0 ) + showernode.imgpos4_edep.resize(4,0); + + showernode.first_edep_pos = showernode.start; + } + else { + // photons + showernode.imgpos4_edep = ublarcvapp::mctools::MCPos2ImageUtils::Get()->to_imagepos( showernode.first_edep_pos[0], + showernode.first_edep_pos[1], + showernode.first_edep_pos[2], + showernode.first_edep_pos[3] ); + if ( showernode.imgpos4_edep.size()==0 ) { + showernode.imgpos4_edep.resize(4,0); + } + else { + showernode.imgpos4_edep[3] += 12.0; // hacky fix for photons + } + } + + showernode.imgpos4_start = ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( showernode.start[0], + showernode.start[1], + showernode.start[2], + showernode.start[3], + true ); + if ( showernode.imgpos4_start.size()==0 ) { + showernode.imgpos4_start.resize(4,0); + } } if ( showernode.origin==1 ) { // store nu particle @@ -1829,8 +1831,8 @@ namespace mctools { }// end of loop over flow directions (2 of them) }//end of loop over planes - std::cout << "Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; - std::cout << " Number of spacepoints found from using larflow: " << pt_v.size() << std::endl; + LARCV_INFO() << "Node[" << node.nodeidx << "] tid=" << node.tid << " pid=" << node.pid << std::endl; + LARCV_INFO() << " Number of spacepoints found from using larflow: " << pt_v.size() << std::endl; // store the points into our storage vector, pos_vv, which we return. for (auto& pt_info : pt_v ) { @@ -1862,8 +1864,11 @@ namespace mctools { // this is only for photons (electrons have a good start point based on node.start) std::vector shower_start_pt; - if ( node.pid!=22) + if ( node.pid!=22 && abs(node.pid)!=11) { + // we only apply the following to energy deposits made by photons (pid=22) and electrons (pid=11) + // i.e. those producing EM showers return shower_start_pt; + } // we must collect and scan the instance IDs related to the shower // int shower_aid = node.aid; @@ -1927,12 +1932,14 @@ namespace mctools { } // use our interface to DBScan + LARCV_DEBUG() << "Clustering spacepoints" << std::endl; auto dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( 0.3, 3, 50, data_v ); // loop through the cluster and find the closest one // that qualifies in terms of size int icluster = -1; float closest_qualified_cluster_dist = 1.0e9; + std::vector closest_pixsum_v; for (int i=0; i<(int)dbcluster_v.size(); i++) { // we calculate the pixel sum in each plane of each cluster. @@ -1982,15 +1989,22 @@ namespace mctools { planes_passing++; } } - //std::cout << ")" << std::endl; + // LARCV_DEBUG() << "cluster[" << i << "] npoints=" << nhits + // << " dist-to-source=" << cluster_min_dist_to_source << " cm;" + // << " plane MeV: (" << pixsum_v[0]*0.0162 << ", " + // << pixsum_v[0]*0.0162 << ", " + // << pixsum_v[2]*0.0162 << ")" + // << std::endl; + // LARCV_DEBUG() << "number of planes passing: " << planes_passing << std::endl; // check if cluster passes 'detectability criterion' // and, if so, is the closest cluster to the creation point of the photon if ( planes_passing>=2 && cluster_min_dist_to_source < closest_qualified_cluster_dist ) { closest_qualified_cluster_dist = cluster_min_dist_to_source; icluster = i; + closest_pixsum_v = pixsum_v; } - }//end of loop over all hits + }//end of loop over clusters // container to store our trunk points pointList trunk_pt_v; @@ -2000,6 +2014,7 @@ namespace mctools { // we count this shower as unreconstructable. // we define a sentinal value for the starting energy deposition point shower_start_pt = std::vector{ -1.0, -1.0, -1.0 }; + LARCV_DEBUG() << "No valid trunk cluster found." << std::endl; } else { // a valid cluster is found. store the points for this cluster @@ -2025,8 +2040,14 @@ namespace mctools { } trunk_pt_v.push_back( xpt ); }//end of loop over largest cluster points (by index) + LARCV_DEBUG() << "Defining observable trunk using cluster[" << icluster << "] " << std::endl; + LARCV_DEBUG() << " npoints=" << largest_cluster.size() + << " plane MeV: (" << closest_pixsum_v[0]*0.0162 << ", " + << closest_pixsum_v[1]*0.0162 << ", " + << closest_pixsum_v[2]*0.0162 << ")" + << std::endl; LARCV_DEBUG() << " minimum dist to shower startpt: " << mindist << " cm" << std::endl; - } + }//end of else a valid shower cluster found LARCV_INFO() << " startpt: (" << shower_start_pt[0] << "," << shower_start_pt[1] << "," @@ -2061,6 +2082,12 @@ namespace mctools { const int nplanes = adc_v.size(); std::vector plane_pixsum_v( nplanes, 0.0 ); std::vector< PixelSet_t > plane_pixsets_v = _getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); + if ( plane_pixsum_v.size()>=3 ) { + LARCV_INFO() << " pixel sums MeV: (" << plane_pixsum_v[0]*0.0162 << ", " + << plane_pixsum_v[1]*0.0162 << ", " + << plane_pixsum_v[2]*0.0162 << ") " + << std::endl; + } // making image masks std::vector< larcv::Image2D > trunk_planeimg_v; @@ -2102,9 +2129,8 @@ namespace mctools { larcv::Image2D trunk_img( trunk_meta ); trunk_img.paint(0.0); - LARCV_DEBUG() << "Defined plane bounding box for trunk" << std::endl; - LARCV_DEBUG() << trunk_meta.dump() << std::endl; - LARCV_DEBUG() << "original meta: " << meta.dump() << std::endl; + LARCV_DEBUG() << "Defined plane bounding box for trunk: \n" << trunk_meta.dump() << std::endl; + LARCV_DEBUG() << "original meta: \n " << meta.dump() << std::endl; // loop over the pixels and fill the mask for (auto& pix : pixset ) { @@ -2141,7 +2167,7 @@ namespace mctools { if ( _true_photon_v.size()!=_true_photon_plane_trunkimg_vv.size() ) LARCV_ERROR() << "size of the true photon 3d point container is not the same as the trunk image mask container" << std::endl; - std::cout << "========================================================END======" << std::endl; + //std::cout << "========================================================END======" << std::endl; return shower_start_pt; diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.h b/ublarcvapp/MCTools/MCPos2ImageUtils.h index a5ba885..abae03c 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.h +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.h @@ -32,7 +32,7 @@ namespace mctools { : larcv::larcv_base("MCPos2ImageUtils"), psce(nullptr) { - psce = new larutil::SpaceChargeMicroBooNE; + psce = new larutil::SpaceChargeMicroBooNE; }; @@ -43,7 +43,7 @@ namespace mctools { static MCPos2ImageUtils* Get() { if ( !_p_singleton ) { - _p_singleton = new MCPos2ImageUtils; + _p_singleton = new MCPos2ImageUtils; } return _p_singleton; }; From 61a9d20677bfa1de6a43418f1905a5b0ebd8f797 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Thu, 29 Aug 2024 11:27:50 -0400 Subject: [PATCH 51/80] identify bad image masks --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 0091fc9..c5443d9 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -2080,6 +2080,7 @@ namespace mctools { // making pixellist const int nplanes = adc_v.size(); + bool valid_imagemask = true; std::vector plane_pixsum_v( nplanes, 0.0 ); std::vector< PixelSet_t > plane_pixsets_v = _getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); if ( plane_pixsum_v.size()>=3 ) { @@ -2119,10 +2120,20 @@ namespace mctools { auto const& meta = img.meta(); int colcount = max_col-min_col+1; int rowcount = max_row-min_row+1; + if (colcount<=0 or rowcount<=0) { + // invalid bounding box + colcount = 1; + rowcount = 1; + min_col = 0; + min_row = 0; + max_col = 1; + max_row = 1; + } float width = float( colcount ); float height = meta.pixel_height()*rowcount; float origin_x = float( meta.pos_x( min_col ) ); float origin_y = float( meta.pos_y( min_row ) ); + LARCV_DEBUG() << "min (col,row)=(" << min_col << "," << min_row << ")" << std::endl; LARCV_DEBUG() << "min (x,y)=(" << origin_x << "," << origin_y << ")" << std::endl; larcv::ImageMeta trunk_meta( width, height, rowcount, colcount, origin_x, origin_y, meta.plane() ); From f361d00c47c2efcb2b1b77031d384729630312e4 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 6 Sep 2024 17:09:02 -0400 Subject: [PATCH 52/80] save fixes to photon trunk finding. removed the use of the noise cluster. oops! --- CMakeLists.txt | 4 +- ublarcvapp/MCTools/MCPixelPGraph.cxx | 121 +++++++++++++++++---------- ublarcvapp/MCTools/MCPixelPGraph.h | 7 +- 3 files changed, 82 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5aa433e..44299f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,8 @@ if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) endif() # CFLAGS -SET(CMAKE_C_FLAGS "-std=gnu99 -pedantic -fPIC -pedantic -fopenmp -mtune=native") -SET(CMAKE_CXX_FLAGS "-Wall -fPIC -pedantic -fopenmp -mtune=native") +#SET(CMAKE_C_FLAGS "-std=gnu99 -pedantic -fPIC -pedantic -fopenmp -mtune=native") +#SET(CMAKE_CXX_FLAGS "-Wall -fPIC -pedantic -fopenmp -mtune=native") ## Dependencies diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index c5443d9..36991a4 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -56,24 +56,9 @@ namespace mctools { ev_seg->Image2DArray(), ev_ins->Image2DArray(), ev_anc->Image2DArray(), + ev_larflow->Image2DArray(), *ev_mcshower, *ev_mctrack, *ev_mctruth ); - // next we fix photons - for ( auto& node : node_v ) { - if ( node.pid==22 || abs(node.pid)==11 ) { - std::vector startpt_info - = fixingPhotonStartPoints( node, - ev_ins->as_vector(), ev_anc->as_vector(), - ev_adc->as_vector(), ev_larflow->as_vector() ); - // update edep position of the node for photons only - if ( node.pid==22 ) { - for (int v=0; v<4; v++) { - node.first_edep_pos[v] = startpt_info[v]; - node.imgpos4_edep[v] = startpt_info[4+v]; - } - } - } - } } /** @@ -100,6 +85,7 @@ namespace mctools { const std::vector& segment_v, const std::vector& instance_v, const std::vector& ancestor_v, + const std::vector& larflow_v, const larlite::event_mcshower& shower_v, const larlite::event_mctrack& track_v, const larlite::event_mctruth& mctruth_v ) @@ -114,6 +100,24 @@ namespace mctools { std::vector threshold_v(adc_v.size(),10.0); _scanPixelData( adc_v, segment_v, instance_v, ancestor_v, threshold_v ); + + // next we fix photons + for ( auto& node : node_v ) { + if ( node.pid==22 || abs(node.pid)==11 ) { + std::vector startpt_info + = fixingPhotonStartPoints( node, + instance_v, ancestor_v, + adc_v, larflow_v ); + // update edep position of the node for photons only + if ( node.pid==22 ) { + for (int v=0; v<4; v++) { + node.first_edep_pos[v] = startpt_info[v]; // set the location of the starting edep position (detectort coordinates) + node.imgpos4_edep[v] = startpt_info[4+v]; // set the location ion the image + } + } + } + } + } /** @@ -1730,6 +1734,7 @@ namespace mctools { int ilarflow_image_index = 2*p+iflowdir; // use the index to get the image auto& flowimg = larflow_v.at(ilarflow_image_index); + // loop over the pixels for the given particle for (size_t ipix=0; ipix20.0 ) { + if ( MeV>5.0 ) { planes_passing++; } } - // LARCV_DEBUG() << "cluster[" << i << "] npoints=" << nhits - // << " dist-to-source=" << cluster_min_dist_to_source << " cm;" - // << " plane MeV: (" << pixsum_v[0]*0.0162 << ", " - // << pixsum_v[0]*0.0162 << ", " - // << pixsum_v[2]*0.0162 << ")" - // << std::endl; - // LARCV_DEBUG() << "number of planes passing: " << planes_passing << std::endl; + if (planes_passing>=1 && cluster_min_dist_to_source<100.0) { + LARCV_INFO() << "cluster[" << i << "] npoints=" << nhits + << " dist-to-source=" << cluster_min_dist_to_source << " cm;" + << " plane MeV: (" << pixsum_v[0]*0.0162 << ", " + << pixsum_v[1]*0.0162 << ", " + << pixsum_v[2]*0.0162 << ")" + << " pt=(" << closest_pt[0] << "," << closest_pt[1] << "," << closest_pt[2] << ")" + << "nplanes passing: " << planes_passing << std::endl; + } // check if cluster passes 'detectability criterion' // and, if so, is the closest cluster to the creation point of the photon @@ -2062,7 +2085,7 @@ namespace mctools { shower_start_pt[1], shower_start_pt[2], t_ns ); - LARCV_INFO() << " imgpos: (" << shower_imgpos4[0] << ", " + LARCV_INFO() << " shower imgpos: (" << shower_imgpos4[0] << ", " << shower_imgpos4[1] << ", " << shower_imgpos4[2] << ", " << shower_imgpos4[3] << " ticks )" @@ -2082,7 +2105,7 @@ namespace mctools { const int nplanes = adc_v.size(); bool valid_imagemask = true; std::vector plane_pixsum_v( nplanes, 0.0 ); - std::vector< PixelSet_t > plane_pixsets_v = _getPlanePixelSetsAndPixelSums( trunk_pt_v, plane_pixsum_v ); + std::vector< PixelSet_t > plane_pixsets_v = _getPlanePixelSetsAndPixelSums( trunk_pt_v, adc_v, plane_pixsum_v ); if ( plane_pixsum_v.size()>=3 ) { LARCV_INFO() << " pixel sums MeV: (" << plane_pixsum_v[0]*0.0162 << ", " << plane_pixsum_v[1]*0.0162 << ", " @@ -2244,7 +2267,7 @@ namespace mctools { // so we must mark which pixels we used Node_t* pnode = findTrackID( trackid ); if ( pnode==nullptr ) { - std::cout << "[MCPixelPGraph::getTruePhotonTrunk3DPoints] [WARNING]: did not find particle Node pointer for " + LARCV_ERROR() << ": did not find particle Node pointer for " << " trackid=" << pnode->tid << ". " << "Returning emptry point list." << std::endl; @@ -2254,7 +2277,12 @@ namespace mctools { auto it_pixsum = _nodeidx_to_photonlist_index_v.find( pnode->nodeidx ); if ( it_pixsum==_nodeidx_to_photonlist_index_v.end() ) { - LARCV_ERROR() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; + LARCV_NORMAL() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; + for ( auto& it_x : _nodeidx_to_photonlist_index_v ) { + pnode = &(node_v.at( it_x.first )); + LARCV_NORMAL() << " [nodeidx=" << it_x.first << ", trackid=" << pnode->tid << "] photonlist index=" << it_x.second << std::endl; + } + LARCV_ERROR() << "Stopping on error" << std::endl; } std::vector pixsum_v = _true_photon_plane_pixsum_vv.at( it_pixsum->second ); @@ -2319,14 +2347,12 @@ namespace mctools { * @brief Does the calculation to get the pixels in each plane corresponding to 3D points of true shower trunk */ std::vector - MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ) + MCPixelPGraph::getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist, + const std::vector< larcv::Image2D >& adc_v ) { std::vector pixsum_v; - - if ( !ev_adc ) - return pixsum_v; - - const int nplanes = ev_adc->Image2DArray().size(); + + const int nplanes = adc_v.size(); const int dpix = 1; std::vector out_of_imgpix(nplanes,0); // allocate space to the pixsum @@ -2334,7 +2360,7 @@ namespace mctools { for (int p=0; pImage2DArray().at(p); + auto const& img = adc_v.at(p); // this lists (row,col) combinations we gathered pixels from std::set< std::pair > _pix_used; @@ -2402,10 +2428,13 @@ namespace mctools { */ std::vector< MCPixelPGraph::PixelSet_t > MCPixelPGraph::_getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, - std::vector& pixsum_v ) { + const std::vector& adc_v, + std::vector& pixsum_v ) + { + std::vector< MCPixelPGraph::PixelSet_t > plane_pixsets_v; - const int nplanes = ev_adc->Image2DArray().size(); + const int nplanes = adc_v.size(); const int dpix = 2; std::vector out_of_imgpix(nplanes,0); @@ -2415,7 +2444,7 @@ namespace mctools { for (int p=0; pImage2DArray().at(p); + auto const& img = adc_v.at(p); // this lists (row,col) combinations we gathered pixels from PixelSet_t _pix_used; diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 19382b6..a7e9580 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -64,6 +64,7 @@ namespace mctools { const std::vector& segment_v, const std::vector& instance_v, const std::vector& ancestor_v, + const std::vector& larflow_v, const larlite::event_mcshower& shower_v, const larlite::event_mctrack& track_v, const larlite::event_mctruth& mctruth_v ); @@ -254,9 +255,11 @@ namespace mctools { const std::vector& ancestor_v, const std::vector& adc_v, const std::vector& larflow_v ); - std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist ); + std::vector getPlanePixelSumsFromPointList( const std::vector< std::vector >& pointlist, + const std::vector& adc_v ); std::vector< MCPixelPGraph::PixelSet_t > _getPlanePixelSetsAndPixelSums( const MCPixelPGraph::pointList& pt_v, - std::vector& pixsum_v ); + const std::vector& adc_v, + std::vector& pixsum_v ); //* Functions to get info about the true photon trunk energy deposits and pixels */ public: From f8bd223b204dfdc166f69757f0805d183c6651b4 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sun, 22 Sep 2024 08:12:06 -0400 Subject: [PATCH 53/80] just formatting for vscode maybe --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 197 ++++++++++++++------------- 1 file changed, 105 insertions(+), 92 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 36991a4..7efa416 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -104,17 +104,25 @@ namespace mctools { // next we fix photons for ( auto& node : node_v ) { if ( node.pid==22 || abs(node.pid)==11 ) { - std::vector startpt_info - = fixingPhotonStartPoints( node, + std::vector startpt_info + = fixingPhotonStartPoints( node, instance_v, ancestor_v, adc_v, larflow_v ); - // update edep position of the node for photons only + // update edep position of the node for photons only if ( node.pid==22 ) { for (int v=0; v<4; v++) { node.first_edep_pos[v] = startpt_info[v]; // set the location of the starting edep position (detectort coordinates) node.imgpos4_edep[v] = startpt_info[4+v]; // set the location ion the image } } + // if ( node.origin==2 && abs(node.pid)==11 ) { + // // the cosmics timing are messed up (at least corsika samples are?) + // for (int v=0; v<4; v++) { + // node.start[v] = startpt_info[v]; // set the location of the starting edep position (detectort coordinates) + // node.first_edep_pos[v] = startpt_info[v]; // set the location of the starting edep position (detectort coordinates) + // node.imgpos4_edep[v] = startpt_info[4+v]; // set the location ion the image + // } + // } } } @@ -157,7 +165,7 @@ namespace mctools { clear(); node_v.clear(); - node_v.reserve( shower_v.size()+track_v.size() ); + node_v.reserve( shower_v.size()+track_v.size()+100 ); // Create ROOT node Node_t neutrino ( node_v.size(), -1, 0, 0, -1 ); @@ -257,52 +265,52 @@ namespace mctools { if ( mct.size()>=1 ) { - tracknode.first_edep_pos[0] = mct[0].X(); - tracknode.first_edep_pos[1] = mct[0].Y(); - tracknode.first_edep_pos[2] = mct[0].Z(); - tracknode.first_edep_pos[3] = mct[0].T(); + tracknode.first_edep_pos[0] = mct[0].X(); + tracknode.first_edep_pos[1] = mct[0].Y(); + tracknode.first_edep_pos[2] = mct[0].Z(); + tracknode.first_edep_pos[3] = mct[0].T(); - // first TPC point - std::vector recopos(4,0); - std::vector edep_imgpos(4,0); - std::vector xyz(4,0); - bool intpc = false; - bool inimage = false; - bool first_step = false; - for (auto const& step : mct ) { - xyz[0] = (float)step.X(); - xyz[1] = (float)step.Y(); - xyz[2] = (float)step.Z(); - xyz[3] = (float)step.T(); - - if ( !first_step ) { - first_step = true; - tracknode.first_edep_pos = xyz; - } - - if ( ( xyz[0]>0.0 && xyz[0]0 && xyz[2]truepos_to_imagepos( xyz[0], xyz[1], xyz[2], xyz[3], true ); - if ( !inimage && recopos[3]>2400.0 && recopos[3]<2400+1008*6 ) { - // in the image - inimage = true; - tracknode.first_img_pos = xyz; - tracknode.imgpos4 = recopos; - tracknode.imgpos4_edep = recopos; - } - } - if ( intpc && inimage ) { - // no need to keep searching - break; - } - }//end of mcstep loop + // first TPC point + std::vector recopos(4,0); + std::vector edep_imgpos(4,0); + std::vector xyz(4,0); + bool intpc = false; + bool inimage = false; + bool first_step = false; + for (auto const& step : mct ) { + xyz[0] = (float)step.X(); + xyz[1] = (float)step.Y(); + xyz[2] = (float)step.Z(); + xyz[3] = (float)step.T(); + + if ( !first_step ) { + first_step = true; + tracknode.first_edep_pos = xyz; + } + + if ( ( xyz[0]>0.0 && xyz[0]0 && xyz[2]truepos_to_imagepos( xyz[0], xyz[1], xyz[2], xyz[3], true ); + if ( !inimage && recopos[3]>2400.0 && recopos[3]<2400+1008*6 ) { + // in the image + inimage = true; + tracknode.first_img_pos = xyz; + tracknode.imgpos4 = recopos; + tracknode.imgpos4_edep = recopos; + } + } + if ( intpc && inimage ) { + // no need to keep searching + break; + } + }//end of mcstep loop }//end of if more than 0 mcsteps node_v.emplace_back( std::move(tracknode) ); @@ -317,6 +325,10 @@ namespace mctools { << " mid=" << mcsh.MotherTrackID() << " aid=" << mcsh.AncestorTrackID() << " pid=" << mcsh.PdgCode() + << " start=(" << (float)mcsh.Start().X() << "," + << (float)mcsh.Start().Y() << "," + << (float)mcsh.Start().Z() << "," + << " t=" << (float)mcsh.Start().T() << ")" << std::endl; //if ( mcsh.Origin()==1 ) { @@ -685,7 +697,7 @@ namespace mctools { auto it_showerdaughter = _shower_daughter2mother.find( trackid ); if ( it_showerdaughter!=_shower_daughter2mother.end() ) { // found an id - LARCV_DEBUG() << " found map to mother: " << it_showerdaughter->second << std::endl; + //LARCV_DEBUG() << " found map to mother: " << it_showerdaughter->second << std::endl; dummy.tid = it_showerdaughter->second; } else { @@ -694,8 +706,8 @@ namespace mctools { } // with the mother shower's trackid, try to find the node again it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); - if ( it!=node_v.end() ) - LARCV_DEBUG() << " mother id maps to existing node" << std::endl; + //if ( it!=node_v.end() ) + // LARCV_DEBUG() << " mother id maps to existing node" << std::endl; } if ( it==node_v.end() || it->tid!=dummy.tid ) { @@ -721,7 +733,8 @@ namespace mctools { * @param[in] node Note_t object to make info for. * */ - std::string MCPixelPGraph::strNodeInfo( const Node_t& node ) { + std::string MCPixelPGraph::strNodeInfo( const Node_t& node ) + { int hasmother = ( node.mother ) ? 1 : 0; @@ -749,10 +762,10 @@ namespace mctools { if ( node.first_edep_pos.size()>=4 ) ss << " edep-tpcpos(x,y,z,t)=(" << node.first_edep_pos[0] << "," - << node.first_edep_pos[1] << "," - << node.first_edep_pos[2] << "," - << node.first_edep_pos[3]*1.0e-3 - << " us)" << std::endl; + << node.first_edep_pos[1] << "," + << node.first_edep_pos[2] << "," + << node.first_edep_pos[3]*1.0e-3 + << " us)" << std::endl; if ( node.imgpos4.size()>=4 ) ss << " tpc-imgpos4(u,v,y,tick)=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << " tick) " << std::endl; @@ -884,8 +897,8 @@ namespace mctools { // if ( adc=threshold ) - nabove_thresh[p]++; + if ( adc>=threshold ) + nabove_thresh[p]++; // above threshold, now lets find instance or ancestor int tid = 0; @@ -914,33 +927,33 @@ namespace mctools { continue; } - // shower pixels have a negative track ID for some reason - // does this always occur? + // shower pixels have a negative track ID for some reason + // does this always occur? if ( tid<0 && (seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma) ) { tid *= -1; - num_neg_shower_ids++; - } + num_neg_shower_ids++; + } - bool has_id_label = false; - if ( tid>0 || aid>0 ) { - nabove_thresh_withlabel[p]++; - has_id_label = true; - } + bool has_id_label = false; + if ( tid>0 || aid>0 ) { + nabove_thresh_withlabel[p]++; + has_id_label = true; + } if ( aid>0 && (seg==(int)larcv::kROIEminus || seg==(int)larcv::kROIGamma) ) { shower_ancestor_ids.insert( aid ); } - if ( !has_id_label ) { - // can't truth associate this pixel to any node - continue; - } + if ( !has_id_label ) { + // can't truth associate this pixel to any node + continue; + } Node_t* node = nullptr; if ( tid>0 ) { // first we use the instance ID - // this implicitly uses the _shower_daughter2mother map we filled earlier. + // this implicitly uses the _shower_daughter2mother map we filled earlier. node = findTrackID( tid ); if ( node==nullptr && adc>10.0 ) LARCV_DEBUG() << " no node for above threshold charge-pixel tid=" << tid << std::endl; @@ -950,15 +963,15 @@ namespace mctools { // use ancestor if we could not find the node if ( !node && aid>0 ) { - // this implicitly uses the _shower_daughter2mother map we filled earlier. + // this implicitly uses the _shower_daughter2mother map we filled earlier. node = findTrackID( aid ); if ( node && node->tid!=aid ) node = nullptr; } if ( node ) { - // if the address is not null, this means we found a particle node - // store the pixel. + // if the address is not null, this means we found a particle node + // store the pixel. // if ( node->tid!=tid && node->aid!=aid ) { // std::cout << "pixel assigned without matching tid or aid exactly: " @@ -1209,7 +1222,7 @@ namespace mctools { std::sort( dlist.begin(), dlist.end() ); for (auto const& daughterid : dlist ) { _shower_daughter2mother[daughterid]= showerid; - LARCV_DEBUG() << " " << daughterid << " -> " << showerid << std::endl; + //LARCV_DEBUG() << " " << daughterid << " -> " << showerid << std::endl; } } LARCV_INFO() << "Num entries in daughter2mother map: " << _shower_daughter2mother.size() << std::endl; @@ -1988,7 +2001,7 @@ namespace mctools { dist = sqrt(dist); if ( dist < cluster_min_dist_to_source ) { cluster_min_dist_to_source = dist; - closest_pt = xpt; + closest_pt = xpt; } }//end of loop over hits @@ -2011,13 +2024,13 @@ namespace mctools { } } if (planes_passing>=1 && cluster_min_dist_to_source<100.0) { - LARCV_INFO() << "cluster[" << i << "] npoints=" << nhits - << " dist-to-source=" << cluster_min_dist_to_source << " cm;" - << " plane MeV: (" << pixsum_v[0]*0.0162 << ", " - << pixsum_v[1]*0.0162 << ", " - << pixsum_v[2]*0.0162 << ")" - << " pt=(" << closest_pt[0] << "," << closest_pt[1] << "," << closest_pt[2] << ")" - << "nplanes passing: " << planes_passing << std::endl; + LARCV_INFO() << "cluster[" << i << "] npoints=" << nhits + << " dist-to-source=" << cluster_min_dist_to_source << " cm;" + << " plane MeV: (" << pixsum_v[0]*0.0162 << ", " + << pixsum_v[1]*0.0162 << ", " + << pixsum_v[2]*0.0162 << ")" + << " pt=(" << closest_pt[0] << "," << closest_pt[1] << "," << closest_pt[2] << ")" + << "nplanes passing: " << planes_passing << std::endl; } // check if cluster passes 'detectability criterion' @@ -2144,13 +2157,13 @@ namespace mctools { int colcount = max_col-min_col+1; int rowcount = max_row-min_row+1; if (colcount<=0 or rowcount<=0) { - // invalid bounding box - colcount = 1; - rowcount = 1; - min_col = 0; - min_row = 0; - max_col = 1; - max_row = 1; + // invalid bounding box + colcount = 1; + rowcount = 1; + min_col = 0; + min_row = 0; + max_col = 1; + max_row = 1; } float width = float( colcount ); float height = meta.pixel_height()*rowcount; From cbcf0140370af665b389ac9d50cdd8f951c294dc Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 25 Sep 2024 09:38:17 -0400 Subject: [PATCH 54/80] fix exception that occurs when near boundary of the TPC --- ublarcvapp/MCTools/MCPos2ImageUtils.cxx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx index e0744b3..d578201 100644 --- a/ublarcvapp/MCTools/MCPos2ImageUtils.cxx +++ b/ublarcvapp/MCTools/MCPos2ImageUtils.cxx @@ -3,6 +3,7 @@ #include "larlite/LArUtil/DetectorProperties.h" #include "larlite/LArUtil/LArProperties.h" #include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/InvalidWireError.h" namespace ublarcvapp { namespace mctools { @@ -98,12 +99,21 @@ namespace mctools { vpos[2] = z; //std::cout << "vpos: " << vpos[0] << " " << vpos[1] << " " << vpos[2] << std::endl; + // make sure pos is inside the tpc + + std::vector imgpos(4,0); if ( std::fabs(vpos[1])>116.5 || vpos[2]<0.0 || vpos[2]>1036.0 ) return imgpos; for (int p=0; p<3; p++) { - float wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + float wire = 0; + try { + wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + } + catch (larutil::InvalidWireError& err) { + wire = err.better_wire_number; + } imgpos[p] = wire; } float tickx = vpos[0]/v_cm_per_us/us_per_tick + 3200.0; @@ -131,7 +141,13 @@ namespace mctools { //const float cm_per_tick = ::larutil::LArProperties::GetME()->DriftVelocity()*0.5; //float tick = ( recopos[3]-4.050 )/0.5 + recopos[0]/cm_per_tick + 3200.0; for (int p=0; p<3; p++) { - float wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + float wire = 0.0; + try { + wire = (float)larutil::Geometry::GetME()->NearestWire( vpos, p ); + } + catch (larutil::InvalidWireError& err) { + wire = err.better_wire_number; + } imgpos[p] = wire; } From 84a7e40c72ca4f4b06a2e93d8f0498d255f1d957 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 10 Feb 2025 22:31:42 -0600 Subject: [PATCH 55/80] fixes for ubdl build on cvmfs --- CMakeLists.txt | 2 +- ublarcvapp/DLTagger/mrcnnmatch/CMakeLists.txt | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44299f5..844dfd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ endif() find_package(ROOT CONFIG REQUIRED) # we set the compiler version based on the one used for ROOT execute_process( - COMMAND bash "-c" "root-config --features | awk '{print $1}'" + COMMAND bash "-c" "root-config --features" OUTPUT_VARIABLE TEST_ROOT_CXX_STANDARD ) if (${TEST_ROOT_CXX_STANDARD} MATCHES "cxx17") message( STATUS "using cxx17") diff --git a/ublarcvapp/DLTagger/mrcnnmatch/CMakeLists.txt b/ublarcvapp/DLTagger/mrcnnmatch/CMakeLists.txt index a4a2854..d2e4503 100644 --- a/ublarcvapp/DLTagger/mrcnnmatch/CMakeLists.txt +++ b/ublarcvapp/DLTagger/mrcnnmatch/CMakeLists.txt @@ -2,16 +2,20 @@ # submodule name set(SUBMODULE_NAME MRCNNMatch) -# However, the file(GLOB...) allows for wildcard additions: +# this is a submodule of LARCVAPP_DLTagger +# for the source below, good practice is to get full paths, so we need +# the directory of target property +get_target_property(SOURCE_DIR LArCVApp_DLTagger SOURCE_DIR) + set(SOURCES - mrcnnmatch/MRCNNMatch.cxx - mrcnnmatch/MRCNNMatchConfig.cxx - mrcnnmatch/MRCNNMatchTypes.cxx - mrcnnmatch/CropMaskCombo.cxx - mrcnnmatch/FeaturesMaskCombo.cxx - mrcnnmatch/Gen3DEndpoints.cxx - mrcnnmatch/GenGraphPoints.cxx - mrcnnmatch/AStarMaskCombo.cxx + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatch.cxx + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatchConfig.cxx + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatchTypes.cxx + ${SOURCE_DIR}/mrcnnmatch/CropMaskCombo.cxx + ${SOURCE_DIR}/mrcnnmatch/FeaturesMaskCombo.cxx + ${SOURCE_DIR}/mrcnnmatch/Gen3DEndpoints.cxx + ${SOURCE_DIR}/mrcnnmatch/GenGraphPoints.cxx + ${SOURCE_DIR}/mrcnnmatch/AStarMaskCombo.cxx ) # ADD THE SOURCES @@ -20,13 +24,13 @@ target_sources( ${LIBNAME} PRIVATE ${SOURCES} ) # append the list of public headers for the target set_property( TARGET ${LIBNAME} APPEND PROPERTY PUBLIC_HEADER - mrcnnmatch/MRCNNMatch.h - mrcnnmatch/MRCNNMatchConfig.h - mrcnnmatch/MRCNNMatchTypes.h - mrcnnmatch/CropMaskCombo.h - mrcnnmatch/FeaturesMaskCombo.h - mrcnnmatch/Gen3DEndpoints.h - mrcnnmatch/GenGraphPoints.h - mrcnnmatch/AStarMaskCombo.h + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatch.h + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatchConfig.h + ${SOURCE_DIR}/mrcnnmatch/MRCNNMatchTypes.h + ${SOURCE_DIR}/mrcnnmatch/CropMaskCombo.h + ${SOURCE_DIR}/mrcnnmatch/FeaturesMaskCombo.h + ${SOURCE_DIR}/mrcnnmatch/Gen3DEndpoints.h + ${SOURCE_DIR}/mrcnnmatch/GenGraphPoints.h + ${SOURCE_DIR}/mrcnnmatch/AStarMaskCombo.h ) From c284c49e5d6fac43db37aabb4d05a0dfad6b626a Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 7 Mar 2025 11:46:18 -0500 Subject: [PATCH 56/80] store pixel values --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 31 ++++++++++++++++++++++------ ublarcvapp/MCTools/MCPixelPGraph.h | 3 +++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 7efa416..3ff6197 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -768,10 +768,17 @@ namespace mctools { << " us)" << std::endl; if ( node.imgpos4.size()>=4 ) - ss << " tpc-imgpos4(u,v,y,tick)=(" << node.imgpos4[0] << "," << node.imgpos4[1] << "," << node.imgpos4[2] << "," << node.imgpos4[3] << " tick) " << std::endl; + ss << " tpc-imgpos4(u,v,y,tick)=(" << node.imgpos4[0] << "," + << node.imgpos4[1] << "," + << node.imgpos4[2] << "," + << node.imgpos4[3] << " tick) " << std::endl; if (node.imgpos4_edep.size()>=4) - ss << " edep-imgpos4(u,v,y,tick)=(" << node.imgpos4_edep[0] << "," << node.imgpos4_edep[1] << "," << node.imgpos4_edep[2] << "," << node.imgpos4_edep[3] << " tick) " << std::endl; + ss << " edep-imgpos4(u,v,y,tick)=(" << node.imgpos4_edep[0] << "," + << node.imgpos4_edep[1] << "," + << node.imgpos4_edep[2] << "," + << node.imgpos4_edep[3] << " tick) " + << std::endl; ss << " npixs=("; for ( size_t i=0; ipix_vv[p].push_back( tick ); node->pix_vv[p].push_back( wire ); + node->pixval_vv[p].push_back( adc ); + node->pixsum_v[p] += adc; } else { _unassigned_pixels_vv[p].push_back( tick ); @@ -2008,7 +2027,7 @@ namespace mctools { // get the pixel sum of the cluster std::vector pixsum_v = getPlanePixelSumsFromPointList( cluster_pt_v, adc_v ); - // another threshold: one plane must pass 10 MeV threshol + // another threshold: one plane must pass 5 MeV threshol // using MeV = 0.00162*pixsum, from matt's conversion formula int planes_passing = 0; //std::cout << "cluster[" << i << "] dist-to-source=" << cluster_min_dist_to_source << " cm; plane MeV: ("; @@ -2045,7 +2064,7 @@ namespace mctools { // container to store our trunk points pointList trunk_pt_v; - if ( icluster<0 ) { + if ( icluster<0 ) { // if we did not find a valid cluster, // we count this shower as unreconstructable. // we define a sentinal value for the starting energy deposition point @@ -2292,8 +2311,8 @@ namespace mctools { if ( it_pixsum==_nodeidx_to_photonlist_index_v.end() ) { LARCV_NORMAL() << "Did not find true photon trunk info for trackid=" << trackid << std::endl; for ( auto& it_x : _nodeidx_to_photonlist_index_v ) { - pnode = &(node_v.at( it_x.first )); - LARCV_NORMAL() << " [nodeidx=" << it_x.first << ", trackid=" << pnode->tid << "] photonlist index=" << it_x.second << std::endl; + pnode = &(node_v.at( it_x.first )); + LARCV_NORMAL() << " [nodeidx=" << it_x.first << ", trackid=" << pnode->tid << "] photonlist index=" << it_x.second << std::endl; } LARCV_ERROR() << "Stopping on error" << std::endl; } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index a7e9580..8e3c009 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -93,6 +93,8 @@ namespace mctools { std::vector daughter_idx_v; // daughter node indices in node_v std::vector daughter_v; // pointer to daughters std::vector< std::vector > pix_vv; // pixels in each plane. pixels stored in (tick,wire) coordinates + std::vector< std::vector > pixval_vv; // pixel values in each plane, aligned with pix_vv + std::vector pixsum_v; // sum of pixel values in each plane std::vector start; //< (x,y,z,t) before sce, true start of particle std::vector first_edep_pos; //< (x,y,z,t) before sce, first step that leaves edep in cryostat std::vector first_tpc_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image @@ -101,6 +103,7 @@ namespace mctools { std::vector imgpos4_edep; //< (x,y,z,tick) after sce // the image position corresponding to the first_edep_pos std::vector imgpos4_start; //< (x,y,z,tick) after sce // the image position corresponding to the start pos after SCE std::vector< std::vector > plane_bbox_twHW_vv; /// bounding box for pixels in each plane + int origin; // 1=neutrino, 2=cosmic, 0=unassigned, -1=unassigned Node_t() From a1a5a442da0f432ff94ad90185a8feebab6c88bb Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 11 Mar 2025 23:32:02 -0500 Subject: [PATCH 57/80] changes to build on fnal and not seg fault --- CMakeLists.txt | 1 + python/ublarcvapp/__init__.py | 1 + ublarcvapp/CMakeLists.txt | 22 +++++++-------- ublarcvapp/LArOpenCVHandle/LArbysImage.cxx | 4 +-- ublarcvapp/LArOpenCVHandle/OperateImage.h | 2 +- ublarcvapp/LArOpenCVHandle/PreProcessor.cxx | 30 ++++++++++----------- ublarcvapp/LArOpenCVHandle/PreProcessor.h | 8 +++++- ublarcvapp/MCTools/LinkDef.h | 10 +++---- ublarcvapp/Reco3D/LinkDef.h | 4 +-- ublarcvapp/UBPhotonLib/LinkDef.h | 4 +-- 10 files changed, 45 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 844dfd6..d677cf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ endif() #---Eigen3 find_package(Eigen3 REQUIRED) +get_property(EIGEN3_INCLUDE_DIRS TARGET Eigen3::Eigen PROPERTY INTERFACE_INCLUDE_DIRECTORIES ) #---LArLite set( larlite_DIR $ENV{LARLITE_LIBDIR}/cmake/larlite ) diff --git a/python/ublarcvapp/__init__.py b/python/ublarcvapp/__init__.py index 424ea28..fe67b52 100644 --- a/python/ublarcvapp/__init__.py +++ b/python/ublarcvapp/__init__.py @@ -17,3 +17,4 @@ ROOT.gSystem.Load(l) import ROOT.ublarcvapp as ublarcvapp +ublarcvapp.mctools.MCPixelPGraph diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index 33fe7b3..d2eeea0 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -1,23 +1,19 @@ -add_subdirectory(LLCVProcessor) add_subdirectory(dbscan) add_subdirectory(Reco3D) +add_subdirectory(LArOpenCVHandle) add_subdirectory(ContourTools) if (HAS_LARLITE) add_subdirectory(LArliteHandler) - add_subdirectory(UBImageMod) - add_subdirectory(UBWireTool) - add_subdirectory(ubdllee) - add_subdirectory(Filter) +# add_subdirectory(LLCVProcessor) +# add_subdirectory(UBImageMod) +# add_subdirectory(UBWireTool) +# add_subdirectory(ubdllee) +# add_subdirectory(Filter) add_subdirectory(MCTools) add_subdirectory(UBPhotonLib) endif() - -if (LARCV_USE_GEO2D) - add_subdirectory(LArOpenCVHandle) -endif() - -if (Boost_FOUND) - add_subdirectory(DLTagger) -endif() +#if (Boost_FOUND) +# add_subdirectory(DLTagger) +#endif() diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx b/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx index e45c951..4c8159a 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx +++ b/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx @@ -483,8 +483,8 @@ namespace larcv { kINVALID_DOUBLE); // Store the type - if (par.type==larocv::data::ParticleType_t::kTrack) proi.Shape(kShapeTrack); - else if (par.type==larocv::data::ParticleType_t::kShower) proi.Shape(kShapeShower); + if (par.type==larocv::data::ParticleCluster::ParticleType_t::kTrack) proi.Shape(kShapeTrack); + else if (par.type==larocv::data::ParticleCluster::ParticleType_t::kShower) proi.Shape(kShapeShower); // Push the ROI into the PGraph LARCV_DEBUG() << " @ pg array index " << pidx << std::endl; diff --git a/ublarcvapp/LArOpenCVHandle/OperateImage.h b/ublarcvapp/LArOpenCVHandle/OperateImage.h index a6c4b41..da92791 100644 --- a/ublarcvapp/LArOpenCVHandle/OperateImage.h +++ b/ublarcvapp/LArOpenCVHandle/OperateImage.h @@ -35,7 +35,7 @@ namespace larcv { /// Default destructor ~OperateImage(){} - enum class Operation_t : uint { kSum, kSubtract }; //, kMultiply, kDivide }; + enum Operation_t : uint { kSum, kSubtract }; //, kMultiply, kDivide }; void configure(const PSet&); void initialize() {} diff --git a/ublarcvapp/LArOpenCVHandle/PreProcessor.cxx b/ublarcvapp/LArOpenCVHandle/PreProcessor.cxx index c6145ba..30ba50f 100644 --- a/ublarcvapp/LArOpenCVHandle/PreProcessor.cxx +++ b/ublarcvapp/LArOpenCVHandle/PreProcessor.cxx @@ -207,8 +207,8 @@ namespace larcv { pchunk.overallPCA = larocv::CalcPCA(ctor); pchunk.edge1PCA = larocv::SquarePCA(img,edge1,_pca_box_size,_pca_box_size); pchunk.edge2PCA = larocv::SquarePCA(img,edge2,_pca_box_size,_pca_box_size); - pchunk.track_frac = type==larocv::ChunkType_t::kTrack ? 1 : 0; - pchunk.shower_frac = type==larocv::ChunkType_t::kShower ? 1 : 0; + pchunk.track_frac = type==larocv::ChunkType_t::kTrackPixelChunk ? 1 : 0; + pchunk.shower_frac = type==larocv::ChunkType_t::kShowerPixelChunk ? 1 : 0; auto masked_pts=larocv::MaskImage(img,ctor,0,false); pchunk.mean_pixel_dist = larocv::MeanDistanceToLine(masked_pts,pchunk.overallPCA); pchunk.sigma_pixel_dist = larocv::SigmaDistanceToLine(masked_pts,pchunk.overallPCA); @@ -302,8 +302,8 @@ namespace larcv { auto track_img_t = PrepareImage(track_img); auto shower_img_t = PrepareImage(shower_img); - auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrack,false); - auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShower,false); + auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrackPixelChunk,false); + auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShowerPixelChunk,false); LARCV_DEBUG() << "Track chunks " << track_pchunk_v.size() << " & Shower chunks " << shower_pchunk_v.size() << std::endl; @@ -335,8 +335,8 @@ namespace larcv { auto track_img_t = PrepareImage(track_img); auto shower_img_t = PrepareImage(shower_img); - auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrack,true); - auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShower,true); + auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrackPixelChunk,true); + auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShowerPixelChunk,true); for(auto& shower_pchunk : shower_pchunk_v) { auto& shower_ctor = shower_pchunk.ctor; @@ -364,9 +364,9 @@ namespace larcv { auto track_img_t = PrepareImage(track_img); auto shower_img_t = PrepareImage(shower_img); - auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknown,true); - auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrack,true); - auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShower,true); + auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknownPixelChunk,true); + auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrackPixelChunk,true); + auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShowerPixelChunk,true); /// determine track/shower fraction of ADC contours for(auto& adc_pchunk : adc_pchunk_v) { @@ -462,9 +462,9 @@ namespace larcv { auto track_img_t = PrepareImage(track_img); auto shower_img_t = PrepareImage(shower_img); - auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknown); - auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrack); - auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShower); + auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknownPixelChunk); + auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrackPixelChunk); + auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShowerPixelChunk); std::vector cidx_v; @@ -533,9 +533,9 @@ namespace larcv { auto track_img_t = PrepareImage(track_img); auto shower_img_t = PrepareImage(shower_img); - auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknown,false); - auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrack,false); - auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShower,false); + auto adc_pchunk_v = MakePixelChunks(adc_img_t,larocv::ChunkType_t::kUnknownPixelChunk,false); + auto track_pchunk_v = MakePixelChunks(track_img_t,larocv::ChunkType_t::kTrackPixelChunk,false); + auto shower_pchunk_v = MakePixelChunks(shower_img_t,larocv::ChunkType_t::kShowerPixelChunk,false); std::vector cidx_v; diff --git a/ublarcvapp/LArOpenCVHandle/PreProcessor.h b/ublarcvapp/LArOpenCVHandle/PreProcessor.h index 074c6fd..6be281e 100644 --- a/ublarcvapp/LArOpenCVHandle/PreProcessor.h +++ b/ublarcvapp/LArOpenCVHandle/PreProcessor.h @@ -62,13 +62,19 @@ namespace larcv { void FilterContours(larocv::GEO2D_ContourArray_t& ctor_v); - + +#ifndef __CINT__ +#ifndef __CLING__ + // hide the enum std::vector MakePixelChunks(const cv::Mat& img, larocv::ChunkType_t type, bool calc_params=true, size_t min_ctor_size=0, size_t min_track_size=0); +#endif +#endif + bool EdgeConnected(const larocv::PixelChunk& track1, const larocv::PixelChunk& track2); diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index f3483a0..422443f 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -14,11 +14,11 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace std; -#pragma link C++ class std::vector+; -#pragma link C++ class std::vector >+; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::mctools+; +#pragma link C++ namespace ublarcvapp; +#pragma link C++ namespace ublarcvapp::mctools; + +//#pragma link C++ class std::vector+; +//#pragma link C++ class std::vector >+; #pragma link C++ class ublarcvapp::mctools::MCPos2ImageUtils+; #pragma link C++ class ublarcvapp::mctools::MCPixelPGraph+; diff --git a/ublarcvapp/Reco3D/LinkDef.h b/ublarcvapp/Reco3D/LinkDef.h index 41fc076..b740715 100644 --- a/ublarcvapp/Reco3D/LinkDef.h +++ b/ublarcvapp/Reco3D/LinkDef.h @@ -18,8 +18,8 @@ #pragma link C++ class ublarcvapp::reco3d::Lattice+; #pragma link C++ class ublarcvapp::reco3d::AStar3DNodePtrList+; -#pragma link C++ class ublarcvapp::reco3d::ReadJarrettFile+; -#pragma link C++ class ublarcvapp::reco3d::ReadNueFile+; +//#pragma link C++ class ublarcvapp::reco3d::ReadJarrettFile+; +//#pragma link C++ class ublarcvapp::reco3d::ReadNueFile+; #pragma link C++ class ublarcvapp::reco3d::Run3DTracker+; #pragma link C++ class ublarcvapp::reco3d::TrackerEventDisplay+; diff --git a/ublarcvapp/UBPhotonLib/LinkDef.h b/ublarcvapp/UBPhotonLib/LinkDef.h index d011a7e..9619beb 100644 --- a/ublarcvapp/UBPhotonLib/LinkDef.h +++ b/ublarcvapp/UBPhotonLib/LinkDef.h @@ -14,8 +14,8 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::ubphotonlib+; +#pragma link C++ namespace ublarcvapp; +#pragma link C++ namespace ublarcvapp::ubphotonlib; #pragma link C++ class ublarcvapp::ubphotonlib::UBPhotonLib+; From d2ec3bbc2b3d575ad7a123f24e0b6eec76b5db67 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 12 Mar 2025 00:56:50 -0500 Subject: [PATCH 58/80] tweaks to not seg fault --- ublarcvapp/CMakeLists.txt | 8 ++++---- ublarcvapp/LLCVProcessor/LinkDef.h | 4 +--- ublarcvapp/UBImageMod/LinkDef.h | 3 +-- ublarcvapp/ubdllee/LinkDef.h | 3 +-- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index d2eeea0..8415ffe 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -5,10 +5,10 @@ add_subdirectory(ContourTools) if (HAS_LARLITE) add_subdirectory(LArliteHandler) -# add_subdirectory(LLCVProcessor) -# add_subdirectory(UBImageMod) -# add_subdirectory(UBWireTool) -# add_subdirectory(ubdllee) + add_subdirectory(LLCVProcessor) + add_subdirectory(UBImageMod) + add_subdirectory(UBWireTool) + add_subdirectory(ubdllee) # add_subdirectory(Filter) add_subdirectory(MCTools) add_subdirectory(UBPhotonLib) diff --git a/ublarcvapp/LLCVProcessor/LinkDef.h b/ublarcvapp/LLCVProcessor/LinkDef.h index 56ec8bd..81d0aa3 100644 --- a/ublarcvapp/LLCVProcessor/LinkDef.h +++ b/ublarcvapp/LLCVProcessor/LinkDef.h @@ -9,9 +9,7 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp; -#pragma link C++ namespace ublarcvapp::dltagger; - +#pragma link C++ namespace ublarcvapp::llcv; #pragma link C++ class ublarcvapp::llcv::LLCVProcessDriver+; #pragma link C++ class ublarcvapp::llcv::LLCVProcessTest+; #pragma link C++ class ublarcvapp::llcv::LArCVProcessTest+; diff --git a/ublarcvapp/UBImageMod/LinkDef.h b/ublarcvapp/UBImageMod/LinkDef.h index 7f0d7f2..378b22f 100644 --- a/ublarcvapp/UBImageMod/LinkDef.h +++ b/ublarcvapp/UBImageMod/LinkDef.h @@ -3,8 +3,7 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::ubimagemod+; +#pragma link C++ namespace ublarcvapp::ubimagemod; #pragma link C++ class ublarcvapp::UBSplitDetector+; #pragma link C++ class ublarcvapp::UBCropLArFlow+; #pragma link C++ class ublarcvapp::InfillDataCropper+; diff --git a/ublarcvapp/ubdllee/LinkDef.h b/ublarcvapp/ubdllee/LinkDef.h index 12ecc77..6474afa 100644 --- a/ublarcvapp/ubdllee/LinkDef.h +++ b/ublarcvapp/ubdllee/LinkDef.h @@ -4,8 +4,7 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::ubdllee+; +#pragma link C++ namespace ublarcvapp::ubdllee; #pragma link C++ class ublarcvapp::ubdllee::FixedCROIFromFlashConfig+; #pragma link C++ class ublarcvapp::ubdllee::FixedCROIFromFlashAlgo+; #pragma link C++ class ublarcvapp::ubdllee::NuAnaMC+; From e96f9e101dc28d30d9fb45698b071bf4ba113a0e Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Sat, 22 Mar 2025 23:22:24 -0400 Subject: [PATCH 59/80] remove larlite chstatus --- ublarcvapp/MCTools/CMakeLists.txt | 3 ++- ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx | 5 +++-- ublarcvapp/UBImageMod/EmptyChannelAlgo.h | 8 ++++---- ublarcvapp/UBImageMod/UBSplitDetector.cxx | 2 ++ ublarcvapp/ubdllee/CMakeLists.txt | 3 ++- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index d477e55..833b939 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -31,6 +31,7 @@ add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) +set(UBLARCVAPP_LIBS_USED LArCVApp_ubdllee) # includes for ROOT dictionary gen include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME}) @@ -49,7 +50,7 @@ target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # Generate the shared library from the sources set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx b/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx index 3cc7ed5..d516353 100644 --- a/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx +++ b/ublarcvapp/UBImageMod/EmptyChannelAlgo.cxx @@ -52,7 +52,8 @@ namespace ublarcvapp { return empty_v; } - + + /* std::vector EmptyChannelAlgo::makeBadChImage( int minstatus, int nplanes, int start_tick, int nticks, int nchannels, int time_downsample_factor, int wire_downsample_factor, const larlite::event_chstatus& ev_status ) { @@ -89,7 +90,7 @@ namespace ublarcvapp { } return badchs; } - + */ std::vector EmptyChannelAlgo::makeBadChImage( int minstatus, int nplanes, int start_tick, int nticks, int nchannels, int time_downsample_factor, int wire_downsample_factor, diff --git a/ublarcvapp/UBImageMod/EmptyChannelAlgo.h b/ublarcvapp/UBImageMod/EmptyChannelAlgo.h index ade0f1d..9be2249 100644 --- a/ublarcvapp/UBImageMod/EmptyChannelAlgo.h +++ b/ublarcvapp/UBImageMod/EmptyChannelAlgo.h @@ -5,7 +5,7 @@ // larlite #include "larlite/Base/DataFormatConstants.h" -#include "larlite/DataFormat/chstatus.h" // needed because of duplicate name! +//#include "larlite/DataFormat/chstatus.h" // needed because of duplicate name! // larcv #include "larcv/core/DataFormat/Image2D.h" @@ -24,9 +24,9 @@ namespace ublarcvapp { std::vector findEmptyChannels( float threshold, const larcv::Image2D& tpcimg, const float max_value=-1.0 ); - std::vector makeBadChImage( int minstatus, int nplanes, int start_tick, int nticks, int nchannels, - int time_downsample_factor, int wire_downsample_factor, - const larlite::event_chstatus& ev_status ); + // std::vector makeBadChImage( int minstatus, int nplanes, int start_tick, int nticks, int nchannels, + // int time_downsample_factor, int wire_downsample_factor, + // const larlite::event_chstatus& ev_status ); std::vector makeBadChImage( int minstatus, int nplanes, int start_tick, int nticks, int nchannels, int time_downsample_factor, int wire_downsample_factor, diff --git a/ublarcvapp/UBImageMod/UBSplitDetector.cxx b/ublarcvapp/UBImageMod/UBSplitDetector.cxx index 50c6351..8aac6a5 100644 --- a/ublarcvapp/UBImageMod/UBSplitDetector.cxx +++ b/ublarcvapp/UBImageMod/UBSplitDetector.cxx @@ -573,6 +573,8 @@ namespace ublarcvapp { // give pack the image vector output_imgs.Emplace( std::move(outimg_v) ); + + return true; } bool UBSplitDetector::cropUsingBBox2D( const larcv::ROI& bbox_vec, diff --git a/ublarcvapp/ubdllee/CMakeLists.txt b/ublarcvapp/ubdllee/CMakeLists.txt index 43ca3fb..a9cbe04 100644 --- a/ublarcvapp/ubdllee/CMakeLists.txt +++ b/ublarcvapp/ubdllee/CMakeLists.txt @@ -22,6 +22,7 @@ add_library( ${LIBNAME} SHARED # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) +set(UBLARCVAPP_LIBS_USED LArCVApp_LArliteHandler) # includes for ROOT dictionary gen include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME} ) @@ -40,7 +41,7 @@ target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # Generate the shared library from the sources set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED}) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) # install libraries and headers install(TARGETS ${LIBNAME} From 10d49e55cf21c56e9498ec9ec37a0b05a584eb99 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 26 Mar 2025 03:44:33 -0500 Subject: [PATCH 60/80] fixes to be able to compile with clang 14 --- ublarcvapp/ContourTools/CMakeLists.txt | 2 +- ublarcvapp/LArOpenCVHandle/CMakeLists.txt | 2 +- ublarcvapp/MCTools/LArbysMC.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ublarcvapp/ContourTools/CMakeLists.txt b/ublarcvapp/ContourTools/CMakeLists.txt index 7ad2f7e..6df1627 100644 --- a/ublarcvapp/ContourTools/CMakeLists.txt +++ b/ublarcvapp/ContourTools/CMakeLists.txt @@ -25,7 +25,7 @@ ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreCVUtil LArCVApp_LArOpenCVHandle LArCVApp_Reco3D ${LAROPENCV_LIBS} ${GEO2D_LIBS} opencv_core) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreCVUtil LArCVApp_LArOpenCVHandle LArCVApp_Reco3D ${LAROPENCV_LIBS} ${GEO2D_LIBS} opencv_imgcodecs opencv_core) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/LArOpenCVHandle/CMakeLists.txt b/ublarcvapp/LArOpenCVHandle/CMakeLists.txt index a36d5ff..7dce5a9 100644 --- a/ublarcvapp/LArOpenCVHandle/CMakeLists.txt +++ b/ublarcvapp/LArOpenCVHandle/CMakeLists.txt @@ -31,7 +31,7 @@ ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor opencv_core) +target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor opencv_imgcodecs opencv_core) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/MCTools/LArbysMC.cxx b/ublarcvapp/MCTools/LArbysMC.cxx index b9027d9..41b1bbf 100644 --- a/ublarcvapp/MCTools/LArbysMC.cxx +++ b/ublarcvapp/MCTools/LArbysMC.cxx @@ -397,7 +397,7 @@ namespace mctools { struct plane_pixsum_t { int plane; float pixsum; - bool operator<(const plane_pixsum_t& rhs ) { + bool operator<(const plane_pixsum_t& rhs ) const { if ( pixsum Date: Mon, 31 Mar 2025 11:36:05 -0400 Subject: [PATCH 61/80] removed use of glob commands in cmakelists which has bad behavior with root dict and autocling --- ublarcvapp/CMakeLists.txt | 5 +- ublarcvapp/ContourTools/CMakeLists.txt | 66 +++++++--- .../ContourTools/ContourAStarClusterAlgo.h | 2 +- ublarcvapp/ContourTools/ContourCluster.h | 4 +- ublarcvapp/ContourTools/ContourClusterAlgo.h | 2 +- ublarcvapp/LArOpenCVHandle/CMakeLists.txt | 121 ++++++++++++++---- ublarcvapp/LArliteHandler/CMakeLists.txt | 56 ++++---- ublarcvapp/LLCVProcessor/CMakeLists.txt | 10 +- ublarcvapp/MCTools/CMakeLists.txt | 40 ++++-- ublarcvapp/Reco3D/AStar3DAlgo.h | 6 +- ublarcvapp/Reco3D/AStar3DAlgoProton.h | 2 +- ublarcvapp/Reco3D/AStarTracker.h | 8 +- ublarcvapp/Reco3D/CMakeLists.txt | 65 +++++++--- ublarcvapp/Reco3D/Lattice.h | 2 +- ublarcvapp/Reco3D/LinkDef.h | 5 +- ublarcvapp/Reco3D/Run3DTracker.h | 2 +- ublarcvapp/Reco3D/TrackerEventDisplay.h | 2 +- ublarcvapp/UBImageMod/CMakeLists.txt | 72 +++++++---- ublarcvapp/UBPhotonLib/CMakeLists.txt | 46 ++++--- ublarcvapp/UBWireTool/CMakeLists.txt | 56 ++++---- ublarcvapp/dbscan/CMakeLists.txt | 55 +++++--- ublarcvapp/dbscan/LinkDef.h | 4 +- ublarcvapp/ubdllee/CMakeLists.txt | 63 ++++++--- 23 files changed, 473 insertions(+), 221 deletions(-) diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index 8415ffe..de818ef 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -1,9 +1,9 @@ add_subdirectory(dbscan) add_subdirectory(Reco3D) add_subdirectory(LArOpenCVHandle) -add_subdirectory(ContourTools) - +add_subdirectory(ContourTools) # requires opencv, laropencv if (HAS_LARLITE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") add_subdirectory(LArliteHandler) add_subdirectory(LLCVProcessor) add_subdirectory(UBImageMod) @@ -13,7 +13,6 @@ if (HAS_LARLITE) add_subdirectory(MCTools) add_subdirectory(UBPhotonLib) endif() - #if (Boost_FOUND) # add_subdirectory(DLTagger) #endif() diff --git a/ublarcvapp/ContourTools/CMakeLists.txt b/ublarcvapp/ContourTools/CMakeLists.txt index 6df1627..354a949 100644 --- a/ublarcvapp/ContourTools/CMakeLists.txt +++ b/ublarcvapp/ContourTools/CMakeLists.txt @@ -1,31 +1,61 @@ set(MODULE_NAME ContourTools) +set(LIBNAME LArCVApp_${MODULE_NAME}) + # Collect the headers -file(GLOB HEADERS "*.h") +set( HEADERS + ContourShapeMeta.h + ContourCluster.h + ContourClusterAlgo.h + ContourAStarClusterAlgo.h +) -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") +# Collect the sources +add_library( ${LIBNAME} SHARED + ContourShapeMeta.cxx + ContourCluster.cxx + ContourClusterAlgo.cxx + ContourAStarClusterAlgo.cxx +) -# library name -set(LIBNAME LArCVApp_${MODULE_NAME}) -#message("opencv libs: ${OpenCV_LIBS}") -#message("laropencv libs: ${LAROPENCV_LIBS}") -#message("opencv inc: ${OpenCV_INCLUDE_DIRS}") +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -# includes -include_directories(${LARCV_INCLUDE_DIR} $ENV{LAROPENCV_BASEDIR} $ENV{UBLARCVAPP_BASEDIR} ${OpenCV_INCLUDE_DIRS} ${GEO2D_INC_DIR} $ENV{LARLITE_USERDEVDIR} ) +target_include_directories(${LIBNAME} + PUBLIC + $ + PRIVATE + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + ${OpenCV_INCLUDE_DIRS} + ${GEO2D_INC_DIR} + ${LAROPENCV_INC_DIR} +) +#target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) +target_link_libraries( ${LIBNAME} PUBLIC + opencv_imgcodecs + opencv_core + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreCVUtil + ${GEO2D_LIBS} + ${LAROPENCV_LIBS} + LArCVApp_LArOpenCVHandle + LArCVApp_Reco3D +) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + ${OpenCV_INCLUDE_DIRS} + ${GEO2D_INC_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreCVUtil LArCVApp_LArOpenCVHandle LArCVApp_Reco3D ${LAROPENCV_LIBS} ${GEO2D_LIBS} opencv_imgcodecs opencv_core) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/ContourTools/ContourAStarClusterAlgo.h b/ublarcvapp/ContourTools/ContourAStarClusterAlgo.h index 2b74363..196fddb 100644 --- a/ublarcvapp/ContourTools/ContourAStarClusterAlgo.h +++ b/ublarcvapp/ContourTools/ContourAStarClusterAlgo.h @@ -20,7 +20,7 @@ #include #include -#include "ContourShapeMeta.h" +#include "ublarcvapp/ContourTools/ContourShapeMeta.h" namespace ublarcvapp { diff --git a/ublarcvapp/ContourTools/ContourCluster.h b/ublarcvapp/ContourTools/ContourCluster.h index 1de7d3b..361e534 100644 --- a/ublarcvapp/ContourTools/ContourCluster.h +++ b/ublarcvapp/ContourTools/ContourCluster.h @@ -4,13 +4,13 @@ #include #include -#include "ContourShapeMeta.h" - #ifdef USE_OPENCV #include #include #endif +#include "ublarcvapp/ContourTools/ContourShapeMeta.h" + namespace ublarcvapp { class ContourCluster : public std::vector< std::vector > { diff --git a/ublarcvapp/ContourTools/ContourClusterAlgo.h b/ublarcvapp/ContourTools/ContourClusterAlgo.h index 444cffe..f302de7 100644 --- a/ublarcvapp/ContourTools/ContourClusterAlgo.h +++ b/ublarcvapp/ContourTools/ContourClusterAlgo.h @@ -14,7 +14,7 @@ #include -#include "ContourShapeMeta.h" +#include "ublarcvapp/ContourTools/ContourShapeMeta.h" namespace ublarcvapp { diff --git a/ublarcvapp/LArOpenCVHandle/CMakeLists.txt b/ublarcvapp/LArOpenCVHandle/CMakeLists.txt index 7dce5a9..199b981 100644 --- a/ublarcvapp/LArOpenCVHandle/CMakeLists.txt +++ b/ublarcvapp/LArOpenCVHandle/CMakeLists.txt @@ -1,37 +1,108 @@ set(MODULE_NAME LArOpenCVHandle) -# Collect the headers -file(GLOB HEADERS "*.h") - -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") - -# library name set(LIBNAME LArCVApp_${MODULE_NAME}) -# includes -include_directories(${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARLITE_INCDIRS} ${GEO2D_INC_DIR} ${LAROPENCV_INC_DIR} ${OpenCV_INCLUDE_DIRS} ) -#message("opencv: ${OpenCV_INCLUDE_DIRS}") -#message("opencv: ${OpenCV_LIBS}") +# Collect the headers +set( HEADERS + BadRegionAna.h + BlankImage.h + CosmicPixelAna.h + CosmicTrackAna.h + CosmicVertexAna.h + DeadWireAna.h + GenDeadChannelMap.h + GoodcROIFilter.h + ImageROICheckMC.h + InterWriteOutLC.h + LArbysImage.h + LArbysImageExtract.h + LArbysImageMC.h + LArbysImageMaker.h + LArbysLoader.h + LArbysUtils.h + OperateImage.h + PGraphTruthMatch.h + PIDImageMaker.h + PostTagger.h + PreProcessor.h + ROIAna.h + SSNetEventAna.h + SSNetTruthAna.h + SegmentFilter.h + SingleROIFaker.h + VertexAna.h + VertexFilter.h + VertexInROI.h +) -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +add_library( ${LIBNAME} SHARED + BadRegionAna.cxx + BlankImage.cxx + CosmicPixelAna.cxx + CosmicTrackAna.cxx + CosmicVertexAna.cxx + DeadWireAna.cxx + GenDeadChannelMap.cxx + GoodcROIFilter.cxx + ImageROICheckMC.cxx + InterWriteOutLC.cxx + LArbysImage.cxx + LArbysImageExtract.cxx + LArbysImageMC.cxx + LArbysImageMaker.cxx + LArbysLoader.cxx + LArbysUtils.cxx + OperateImage.cxx + PGraphTruthMatch.cxx + PIDImageMaker.cxx + PostTagger.cxx + PreProcessor.cxx + ROIAna.cxx + SSNetEventAna.cxx + SSNetTruthAna.cxx + SegmentFilter.cxx + SingleROIFaker.cxx + VertexAna.cxx + VertexFilter.cxx + VertexInROI.cxx +) + +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") +target_include_directories(${LIBNAME} + PUBLIC + $ + PRIVATE + ${PROJECT_SOURCE_DIR} + ${OpenCV_INCLUDE_DIRS} + ${LARLITE_INCLUDE_DIR} + ${GEO2D_INC_DIR} + ${LAROPENCV_INC_DIR} + ${LARCV_INCLUDE_DIR} +) +target_link_libraries( ${LIBNAME} PUBLIC + opencv_imgcodecs + opencv_core + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreCVUtil + ${GEO2D_LIBS} + ${LAROPENCV_LIBS} + LArCVApp_Reco3D +) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${OpenCV_INCLUDE_DIRS} + ${LARLITE_INCLUDE_DIR} + ${GEO2D_INC_DIR} + ${LAROPENCV_INC_DIR} + ${LARCV_INCLUDE_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor opencv_imgcodecs opencv_core) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/LArliteHandler/CMakeLists.txt b/ublarcvapp/LArliteHandler/CMakeLists.txt index 158a992..59a8a1a 100644 --- a/ublarcvapp/LArliteHandler/CMakeLists.txt +++ b/ublarcvapp/LArliteHandler/CMakeLists.txt @@ -1,35 +1,47 @@ set(MODULE_NAME LArliteHandler) -# Collect the headers -file(GLOB HEADERS "*.h") +set(LIBNAME LArCVApp_${MODULE_NAME}) -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") +# Collect the headers +set( HEADERS + LArliteManager.h +) -# library name -set(LIBNAME LArCVApp_${MODULE_NAME}) +# Add sources to library +add_library( ${LIBNAME} SHARED + LArliteManager.cxx +) -# includes -include_directories(${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INC_DIRS} + ${LARCV_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries( ${LIBNAME} PUBLIC + larlite_Base + LArCVCoreBase + LArCVCoreDataFormat +) + +# includes for ROOT dictionary gen +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/LLCVProcessor/CMakeLists.txt b/ublarcvapp/LLCVProcessor/CMakeLists.txt index e81c030..39413e7 100644 --- a/ublarcvapp/LLCVProcessor/CMakeLists.txt +++ b/ublarcvapp/LLCVProcessor/CMakeLists.txt @@ -43,13 +43,17 @@ target_include_directories(${LIBNAME} PRIVATE ${PROJECT_SOURCE_DIR} ) -target_link_libraries(${LIBNAME} ${LARLITE_LIBS_USED} ${LARCV_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) + +target_link_libraries(${LIBNAME} + ${LARLITE_LIBS_USED} + ${LARCV_LIBS_USED} + ${UBLARCVAPP_LIBS_USED}) include_directories( ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME} ${LARCV_INCLUDE_DIR} ${LARLITE_INCLUDE_DIR} ) + ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) -#message("public headers: ${ALL_HEADERS}") +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 833b939..940aede 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -33,24 +33,38 @@ add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) set(UBLARCVAPP_LIBS_USED LArCVApp_ubdllee) -# includes for ROOT dictionary gen -include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME}) +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") + +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} + ${LARCV_JSON_INCLUDE_DIR} +) + +target_link_libraries( ${LIBNAME} PUBLIC + ${LARLITE_LIBS_USED} + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreProcessor + ${UBLARCVAPP_LIBS_USED} +) -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +# includes for ROOT dictionary gen +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) -# Generate the shared library from the sources -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/Reco3D/AStar3DAlgo.h b/ublarcvapp/Reco3D/AStar3DAlgo.h index 3a09f43..d3e5170 100644 --- a/ublarcvapp/Reco3D/AStar3DAlgo.h +++ b/ublarcvapp/Reco3D/AStar3DAlgo.h @@ -23,9 +23,9 @@ Uses Image2D to hold image. #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/Base/PSet.h" -#include "AStar3DAlgoConfig.h" -#include "AStar3DTypes.h" -#include "Lattice.h" +#include "ublarcvapp/Reco3D/Lattice.h" +#include "ublarcvapp/Reco3D/AStar3DTypes.h" +#include "ublarcvapp/Reco3D/AStar3DAlgoConfig.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/AStar3DAlgoProton.h b/ublarcvapp/Reco3D/AStar3DAlgoProton.h index 29652b5..9de2cf4 100644 --- a/ublarcvapp/Reco3D/AStar3DAlgoProton.h +++ b/ublarcvapp/Reco3D/AStar3DAlgoProton.h @@ -22,7 +22,7 @@ // larcv #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/Base/PSet.h" -#include "AStar3DAlgo.h" +#include "ublarcvapp/Reco3D/AStar3DAlgo.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/AStarTracker.h b/ublarcvapp/Reco3D/AStarTracker.h index 2ce85b4..0ae80b6 100644 --- a/ublarcvapp/Reco3D/AStarTracker.h +++ b/ublarcvapp/Reco3D/AStarTracker.h @@ -25,6 +25,8 @@ #include "larlite/LArUtil/SpaceChargeMicroBooNE.h" #include "larcv/core/DataFormat/Image2D.h" #include "larcv/core/DataFormat/ImageMeta.h" +#include "larcv/core/Processor/ProcessFactory.h" +#include "larcv/core/Processor/ProcessBase.h" #include #include "TH1D.h" #include "TH2D.h" @@ -36,11 +38,9 @@ //#include "LArCV/core/DataFormat/ChStatus.h" //#include "larcv/app/LArOpenCVHandle/LArbysUtils.h" -#include "AStar3DAlgo.h" -#include "AStar3DAlgoProton.h" +#include "ublarcvapp/Reco3D/AStar3DAlgo.h" +#include "ublarcvapp/Reco3D/AStar3DAlgoProton.h" -#include "larcv/core/Processor/ProcessBase.h" -#include "larcv/core/Processor/ProcessFactory.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/CMakeLists.txt b/ublarcvapp/Reco3D/CMakeLists.txt index 14d926f..7a5e68f 100644 --- a/ublarcvapp/Reco3D/CMakeLists.txt +++ b/ublarcvapp/Reco3D/CMakeLists.txt @@ -1,28 +1,61 @@ set(MODULE_NAME Reco3D) -# Collect the headers -file(GLOB HEADERS "*.h") - -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") - # library name set(LIBNAME LArCVApp_${MODULE_NAME}) -# includes -include_directories(${LARCV_INCLUDE_DIR} $ENV{UBLARCVAPP_BASEDIR} ${LARLITE_INC_DIRS} ${OpenCV_INCLUDE_DIRS}) +# Collect the headers +set( HEADERS + Lattice.h + AStar3DTypes.h + AStar3DAlgoConfig.h + AStarUtils.h + AStar3DAlgo.h + AStar3DAlgoProton.h + AStarTracker.h + Run3DTracker.h + TrackReverser.h + TrackerEventDisplay.h +) + +# collect sources +add_library( ${LIBNAME} SHARED + Lattice.cxx + AStar3DAlgoConfig.cxx + AStarUtils.cxx + AStar3DAlgo.cxx + AStar3DAlgoProton.cxx + AStarTracker.cxx + Run3DTracker.cxx + TrackReverser.cxx + TrackerEventDisplay.cxx +) + +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") +target_include_directories(${LIBNAME} + PUBLIC + $ + PRIVATE + ${PROJECT_SOURCE_DIR} + ${LARCV_INCLUDE_DIR} + ${LARLITE_INC_DIRS} + ${OpenCV_INCLUDE_DIRS} +) +target_link_libraries( ${LIBNAME} PUBLIC + LArCVCoreBase + LArCVCoreDataFormat +) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARCV_INCLUDE_DIR} + ${LARLITE_INC_DIRS} + ${OpenCV_INCLUDE_DIRS} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${OpenCV_INCLUDE_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat opencv_core) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/Reco3D/Lattice.h b/ublarcvapp/Reco3D/Lattice.h index b49735f..3393bba 100644 --- a/ublarcvapp/Reco3D/Lattice.h +++ b/ublarcvapp/Reco3D/Lattice.h @@ -5,7 +5,7 @@ #include "larcv/core/DataFormat/ImageMeta.h" -#include "AStar3DTypes.h" +#include "ublarcvapp/Reco3D/AStar3DTypes.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/LinkDef.h b/ublarcvapp/Reco3D/LinkDef.h index b740715..65eeef6 100644 --- a/ublarcvapp/Reco3D/LinkDef.h +++ b/ublarcvapp/Reco3D/LinkDef.h @@ -4,8 +4,8 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::reco3d+; +#pragma link C++ namespace ublarcvapp::reco3d; +#pragma link C++ class ublarcvapp::reco3d::Lattice+; #pragma link C++ class ublarcvapp::reco3d::A3DPixPos_t+; #pragma link C++ class ublarcvapp::reco3d::AStar3DNode+; #pragma link C++ class std::vector+; @@ -15,7 +15,6 @@ #pragma link C++ class ublarcvapp::reco3d::AStarTracker; #pragma link C++ class ublarcvapp::reco3d::AStarTracker; #pragma link C++ class std::map< ublarcvapp::reco3d::A3DPixPos_t, ublarcvapp::reco3d::AStar3DNode* >+; -#pragma link C++ class ublarcvapp::reco3d::Lattice+; #pragma link C++ class ublarcvapp::reco3d::AStar3DNodePtrList+; //#pragma link C++ class ublarcvapp::reco3d::ReadJarrettFile+; diff --git a/ublarcvapp/Reco3D/Run3DTracker.h b/ublarcvapp/Reco3D/Run3DTracker.h index b40bf27..f112aea 100644 --- a/ublarcvapp/Reco3D/Run3DTracker.h +++ b/ublarcvapp/Reco3D/Run3DTracker.h @@ -24,7 +24,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "AStarTracker.h" +#include "ublarcvapp/Reco3D/AStarTracker.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/Reco3D/TrackerEventDisplay.h b/ublarcvapp/Reco3D/TrackerEventDisplay.h index 8d5fb9d..d722a15 100644 --- a/ublarcvapp/Reco3D/TrackerEventDisplay.h +++ b/ublarcvapp/Reco3D/TrackerEventDisplay.h @@ -24,7 +24,7 @@ #include "larcv/core/Processor/ProcessBase.h" #include "larcv/core/Processor/ProcessFactory.h" -#include "AStarTracker.h" +#include "ublarcvapp/Reco3D/AStarTracker.h" namespace ublarcvapp { namespace reco3d { diff --git a/ublarcvapp/UBImageMod/CMakeLists.txt b/ublarcvapp/UBImageMod/CMakeLists.txt index b9c9f0d..acd4228 100644 --- a/ublarcvapp/UBImageMod/CMakeLists.txt +++ b/ublarcvapp/UBImageMod/CMakeLists.txt @@ -1,35 +1,63 @@ set(MODULE_NAME UBImageMod) -# Collect the headers -file(GLOB HEADERS "*.h") - -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") - # library name set(LIBNAME LArCVApp_${MODULE_NAME}) -# includes -include_directories(${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) +# Collect Headers +set( HEADERS + EmptyChannelAlgo.h + InfillDataCropper.h + InfillImageStitcher.h + InfillSparsifyImage.h + TrackImageMask.h + UBCropLArFlow.h + UBCropMask.h + UBSplitDetector.h + ) + +# Define library and add sources +add_library( ${LIBNAME} SHARED + EmptyChannelAlgo.cxx + InfillDataCropper.cxx + InfillImageStitcher.cxx + InfillSparsifyImage.cxx + TrackImageMask.cxx + UBCropLArFlow.cxx + UBCropMask.cxx + UBSplitDetector.cxx + ) + +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") + +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +target_link_libraries( ${LIBNAME} PUBLIC + ${LARLITE_LIBS} + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreProcessor +) + +# includes for ROOT dict generator +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARCV_INCLUDE_DIR} + ${LARLITE_INC_DIRS} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS}) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/UBPhotonLib/CMakeLists.txt b/ublarcvapp/UBPhotonLib/CMakeLists.txt index 165f387..b9ac2c3 100644 --- a/ublarcvapp/UBPhotonLib/CMakeLists.txt +++ b/ublarcvapp/UBPhotonLib/CMakeLists.txt @@ -4,32 +4,48 @@ set(MODULE_NAME UBPhotonLib) set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers -set( HEADERS UBPhotonLib.h ) +set( HEADERS + UBPhotonLib.h +) # Add sources -add_library( ${LIBNAME} SHARED UBPhotonLib.cxx ) +add_library( ${LIBNAME} SHARED + UBPhotonLib.cxx +) # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) -# includes for ROOT dictionary gen -include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME}) +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} +) + +target_link_libraries( ${LIBNAME} PUBLIC + ${LARLITE_LIBS_USED} + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreProcessor +) + +# includes for ROOT dictionary gen +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) -# Generate the shared library from the sources -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED}) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/UBWireTool/CMakeLists.txt b/ublarcvapp/UBWireTool/CMakeLists.txt index 442e205..fce14c1 100644 --- a/ublarcvapp/UBWireTool/CMakeLists.txt +++ b/ublarcvapp/UBWireTool/CMakeLists.txt @@ -1,35 +1,47 @@ set(MODULE_NAME UBWireTool) -# Collect the headers -file(GLOB HEADERS "*.h") - -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") - # library name set(LIBNAME LArCVApp_${MODULE_NAME}) -# includes -include_directories(${LARCV_INCLUDE_DIR} ${LARLITE_INCDIRS}) +# Collect Headers +set( HEADERS + WireData.h + UBWireTool.h +) + +# Define library and add sources +add_library( ${LIBNAME} SHARED + WireData.cxx + UBWireTool.cxx +) -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") + +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + PRIVATE +) + +target_link_libraries( ${LIBNAME} PUBLIC + ${LARLITE_LIBS} + LArCVCoreBase + LArCVCoreDataFormat + ) + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/dbscan/CMakeLists.txt b/ublarcvapp/dbscan/CMakeLists.txt index 6c199e2..1233930 100644 --- a/ublarcvapp/dbscan/CMakeLists.txt +++ b/ublarcvapp/dbscan/CMakeLists.txt @@ -1,32 +1,45 @@ set(MODULE_NAME dbscan) -# Collect the headers -file(GLOB HEADERS "*.h") -file(GLOB LINKDEF_HEADERS "*.h") - -# Remove LinkDef.h -list(FILTER HEADERS EXCLUDE REGEX ".*LinkDef.h$") - -list(FILTER LINKDEF_HEADERS EXCLUDE REGEX ".*LinkDef.h$") -#list(FILTER LINKDEF_HEADERS EXCLUDE REGEX "DBScan_vp.h" ) - -# However, the file(GLOB...) allows for wildcard additions: -file(GLOB SOURCES "*.cxx") - # library name set(LIBNAME LArCVApp_${MODULE_NAME}) -# includes -include_directories(${LARCV_INCLUDE_DIR} ${cilantro_INCLUDE_DIRS}) +# Collect the headers +set( HEADERS + DBScan.h + DBScanTypes.h + kdtree.h + sDBScan.h +) + +# Collect the sources +add_library( ${LIBNAME} SHARED + DBScan.cxx + kdtree.cxx +) + +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") +target_include_directories(${LIBNAME} + PUBLIC + $ + PRIVATE + ${PROJECT_SOURCE_DIR} +) +#target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) +target_link_libraries( ${LIBNAME} PUBLIC + LArCVCoreBase + LArCVCoreDataFormat +) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARCV_INCLUDE_DIR} + ${cilantro_INCLUDE_DIRS} +) # Generate the dictionary -ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${LINKDEF_HEADERS} LINKDEF LinkDef.h) +ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -# Generate the shared library from the sources -add_library( ${LIBNAME} SHARED ${SOURCES} G__${LIBNAME}.cxx) -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS}) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} diff --git a/ublarcvapp/dbscan/LinkDef.h b/ublarcvapp/dbscan/LinkDef.h index 1367f54..c3c1c3a 100644 --- a/ublarcvapp/dbscan/LinkDef.h +++ b/ublarcvapp/dbscan/LinkDef.h @@ -4,8 +4,8 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ namespace ublarcvapp+; -#pragma link C++ namespace ublarcvapp::dbscan+; +#pragma link C++ namespace ublarcvapp; +#pragma link C++ namespace ublarcvapp::dbscan; #pragma link C++ class ublarcvapp::dbscan::dbPoints+; #pragma link C++ class ublarcvapp::dbscan::dbCluster+; #pragma link C++ class ublarcvapp::dbscan::dbClusters+; diff --git a/ublarcvapp/ubdllee/CMakeLists.txt b/ublarcvapp/ubdllee/CMakeLists.txt index a9cbe04..7f26dc4 100644 --- a/ublarcvapp/ubdllee/CMakeLists.txt +++ b/ublarcvapp/ubdllee/CMakeLists.txt @@ -4,44 +4,65 @@ set(MODULE_NAME ubdllee) set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers -set( HEADERS FixedCROIFromFlashAlgo.h +set( HEADERS + FixedCROIFromFlashAlgo.h FixedCROIFromFlashConfig.h dwall.h NuAnaMC.h DLInteraction.h - MergeDLInteraction.h DLMerger.h ) + MergeDLInteraction.h + DLMerger.h +) # Add sources add_library( ${LIBNAME} SHARED - dwall.cxx - FixedCROIFromFlashAlgo.cxx - FixedCROIFromFlashConfig.cxx - NuAnaMC.cxx - DLInteraction.cxx - MergeDLInteraction.cxx DLMerger.cxx ) + dwall.cxx + FixedCROIFromFlashAlgo.cxx + FixedCROIFromFlashConfig.cxx + NuAnaMC.cxx + DLInteraction.cxx + MergeDLInteraction.cxx + DLMerger.cxx +) # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) set(UBLARCVAPP_LIBS_USED LArCVApp_LArliteHandler) -# includes for ROOT dictionary gen -include_directories(${LARCV_INCLUDE_DIR} ${LARCV_JSON_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/ublarcvapp/${MODULE_NAME} ) +# Generate the shared library from the sources +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") + +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARCV_INCLUDE_DIR} + ${LARLITE_INC_DIRS} + ${LARCV_JSON_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} +) + +target_link_libraries(${LIBNAME} PUBLIC + ${LARLITE_LIBS_USED} + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreProcessor + ${UBLARCVAPP_LIBS_USED} +) -if (HAS_LARLITE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") - #message("build ubimagemod with larlite") -else() - #message("build ubimagemod without larlite") -endif() +# includes for ROOT dictionary gen +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARCV_INCLUDE_DIR} + ${LARCV_JSON_INCLUDE_DIR} + ${LARLITE_INC_DIRS} +) # Generate the dictionary ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) -target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) -# Generate the shared library from the sources -set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") -target_include_directories(${LIBNAME} PUBLIC ${LARCV_INCLUDE_DIR} ${LARLITE_INC_DIRS} ${LARCV_JSON_INCLUDE_DIR} ) -target_link_libraries(${LIBNAME} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${LARLITE_LIBS_USED} ${UBLARCVAPP_LIBS_USED}) +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) # install libraries and headers install(TARGETS ${LIBNAME} From 952d7bb78585d22e770c62308899c16c78618ec8 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 14 Apr 2025 15:06:54 -0400 Subject: [PATCH 62/80] add missing lib needed when linking --- ublarcvapp/MCTools/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 940aede..88661b6 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -31,7 +31,7 @@ add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx # larlite libraries set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) -set(UBLARCVAPP_LIBS_USED LArCVApp_ubdllee) +set(UBLARCVAPP_LIBS_USED LArCVApp_ubdllee LArCVApp_UBWireTool ) set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") From ab8840cd021070378f7fccdf22729df44dd954d3 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Sat, 10 May 2025 18:18:11 -0400 Subject: [PATCH 63/80] added tool to sum pixel values around 3d point projected into larcv image --- ublarcvapp/UBImageMod/CMakeLists.txt | 4 +- ublarcvapp/UBImageMod/LinkDef.h | 1 + .../UBImageMod/PointImageProjection.cxx | 62 +++++++++++++++++++ ublarcvapp/UBImageMod/PointImageProjection.h | 44 +++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 ublarcvapp/UBImageMod/PointImageProjection.cxx create mode 100644 ublarcvapp/UBImageMod/PointImageProjection.h diff --git a/ublarcvapp/UBImageMod/CMakeLists.txt b/ublarcvapp/UBImageMod/CMakeLists.txt index acd4228..184da3c 100644 --- a/ublarcvapp/UBImageMod/CMakeLists.txt +++ b/ublarcvapp/UBImageMod/CMakeLists.txt @@ -13,6 +13,7 @@ set( HEADERS UBCropLArFlow.h UBCropMask.h UBSplitDetector.h + PointImageProjection.h ) # Define library and add sources @@ -24,7 +25,8 @@ add_library( ${LIBNAME} SHARED TrackImageMask.cxx UBCropLArFlow.cxx UBCropMask.cxx - UBSplitDetector.cxx + UBSplitDetector.cxx + PointImageProjection.cxx ) set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") diff --git a/ublarcvapp/UBImageMod/LinkDef.h b/ublarcvapp/UBImageMod/LinkDef.h index 378b22f..795234b 100644 --- a/ublarcvapp/UBImageMod/LinkDef.h +++ b/ublarcvapp/UBImageMod/LinkDef.h @@ -11,6 +11,7 @@ #pragma link C++ class ublarcvapp::InfillImageStitcher+; #pragma link C++ class ublarcvapp::EmptyChannelAlgo+; #pragma link C++ class ublarcvapp::ubimagemod::TrackImageMask+; +#pragma link C++ class ublarcvapp::ubimagemod::PointImageProjection+; #endif diff --git a/ublarcvapp/UBImageMod/PointImageProjection.cxx b/ublarcvapp/UBImageMod/PointImageProjection.cxx new file mode 100644 index 0000000..3fef76a --- /dev/null +++ b/ublarcvapp/UBImageMod/PointImageProjection.cxx @@ -0,0 +1,62 @@ +#include "PointImageProjection.h" + +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/DetectorProperties.h" + +namespace ublarcvapp { +namespace ubimagemod { + + /** + * @brief project a position inside the tpc into a pixel in the wireplane image and sum pixels around it + * + * + */ + float PointImageProjection::getPixelSumAroundProjPoint( const std::vector& xyz, + const larcv::Image2D& img, + int pixel_kernel_radius, + float pixval_threshold ) const + { + + // get wire and time given xyz + TVector3 worldLoc( xyz[0], xyz[1], xyz[2] ); + + UInt_t wireid = larutil::Geometry::GetME()->NearestWire( worldLoc, img.meta().plane() ); + if ( wireid < img.meta().min_x() ) + return 0.0; + if ( wireid >= img.meta().max_x() ) + return 0.0; + + double tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( xyz[0], img.meta().plane() ); + if ( tick < img.meta().min_y() ) + return 0.0; + + if ( tick >= img.meta().max_y() ) + return 0.0; + + int col = (int)img.meta().col( (float)wireid ); + int row = (int)img.meta().row( (float)tick ); + + int dkr = abs(pixel_kernel_radius); + int dkc = abs(pixel_kernel_radius); + + int startcol = ((col-dkc)<0) ? 0 : col-dkc; + int endcol = ((col+dkc)>=(int)img.meta().cols()) ? (int)img.meta().cols()-1 : col+dkc; + int startrow = ((row-dkr)<0) ? 0 : row-dkr; + int endrow = ((row+dkr)>=(int)img.meta().rows()) ? (int)img.meta().rows()-1 : row+dkr; + + float pixsum = 0.; + for (int pixrow=startrow; pixrow<=endrow; pixrow++) { + for (int pixcol=startcol; pixcol<=endcol; pixcol++) { + float pixval = img.pixel( pixrow, pixcol ); + // only add to sum if pixel value above threshold + if ( pixval > pixval_threshold ) + pixsum += pixval; + }//end of dc loop + }//end of dr loop + + return pixsum; + + } + +} +} diff --git a/ublarcvapp/UBImageMod/PointImageProjection.h b/ublarcvapp/UBImageMod/PointImageProjection.h new file mode 100644 index 0000000..78235a6 --- /dev/null +++ b/ublarcvapp/UBImageMod/PointImageProjection.h @@ -0,0 +1,44 @@ +#ifndef __UBLARCAPP_UBIMAGEMOD_POINT_IMAGE_PROJECTION_H__ +#define __UBLARCAPP_UBIMAGEMOD_POINT_IMAGE_PROJECTION_H__ + +/** + * + * @brief Class with functions for projecting a point into a larcv image + * + * Image represents the output of a lartpc wireplane. + * We want to be able to take a 3D point inside the TPC and find the pixel that location + * projects to. Then we can ask about the content of the pixels in the neighborhood of that pixel. + * + * + */ + +#include + +#include "larcv/core/Base/larcv_base.h" +#include "larcv/core/DataFormat/Image2D.h" + + +namespace ublarcvapp { + namespace ubimagemod { + + class PointImageProjection : public larcv::larcv_base + { + + public: + + PointImageProjection() + : larcv::larcv_base("PointImageProjection") + {}; + + ~PointImageProjection() {}; + + + float getPixelSumAroundProjPoint( const std::vector& xyz, const larcv::Image2D& img, int pixel_kernel_radius, float pix_threshold ) const; + + + }; + + } +} + +#endif From 1e72b55bf301e0a2bbda100528106389df40e370 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Mon, 12 May 2025 10:28:02 -0400 Subject: [PATCH 64/80] fix bug where threshold cut in wrong direction --- .../UBImageMod/PointImageProjection.cxx | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ublarcvapp/UBImageMod/PointImageProjection.cxx b/ublarcvapp/UBImageMod/PointImageProjection.cxx index 3fef76a..6fd8680 100644 --- a/ublarcvapp/UBImageMod/PointImageProjection.cxx +++ b/ublarcvapp/UBImageMod/PointImageProjection.cxx @@ -2,6 +2,7 @@ #include "larlite/LArUtil/Geometry.h" #include "larlite/LArUtil/DetectorProperties.h" +#include "larlite/LArUtil/LArProperties.h" namespace ublarcvapp { namespace ubimagemod { @@ -19,19 +20,31 @@ namespace ubimagemod { // get wire and time given xyz TVector3 worldLoc( xyz[0], xyz[1], xyz[2] ); + + //LARCV_NORMAL() << img.meta().dump() << std::endl; UInt_t wireid = larutil::Geometry::GetME()->NearestWire( worldLoc, img.meta().plane() ); - if ( wireid < img.meta().min_x() ) + if ( wireid < img.meta().min_x() ) { + LARCV_NORMAL() << "Wire " << wireid << " below " << img.meta().min_x() << std::endl; return 0.0; - if ( wireid >= img.meta().max_x() ) + } + if ( wireid >= img.meta().max_x() ) { + LARCV_NORMAL() << "Wire " << wireid << " above max=" << img.meta().max_x() << std::endl; return 0.0; + } - double tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( xyz[0], img.meta().plane() ); - if ( tick < img.meta().min_y() ) + //double tick = larutil::DetectorProperties::GetME()->ConvertXToTicks( xyz[0], img.meta().plane() ); + float cm_per_tick = larutil::LArProperties::GetME()->DriftVelocity()*0.5; + double tick = xyz[0]/cm_per_tick + 3200.0; + if ( tick < img.meta().min_y() ) { + LARCV_NORMAL() << "tick " << tick << " below min=" << img.meta().min_y() << std::endl; return 0.0; + } - if ( tick >= img.meta().max_y() ) + if ( tick >= img.meta().max_y() ) { + LARCV_NORMAL() << "tick " << tick << " greater than max=" << img.meta().max_y() << std::endl; return 0.0; + } int col = (int)img.meta().col( (float)wireid ); int row = (int)img.meta().row( (float)tick ); From 430da2ea487ae8a0804f53bdc69a5b25f54708b9 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 11 Jun 2025 13:16:13 -0400 Subject: [PATCH 65/80] added class to employ photonlib given a list of spacepoints with an associated number of photons --- CLAUDE.md | 126 +++++++++++++++++ ublarcvapp/UBPhotonLib/CMakeLists.txt | 2 + ublarcvapp/UBPhotonLib/LinkDef.h | 2 + .../UBPhotonLib/PhotonVisibilityEstimator.cxx | 111 +++++++++++++++ .../UBPhotonLib/PhotonVisibilityEstimator.h | 114 +++++++++++++++ ublarcvapp/UBPhotonLib/README.md | 60 +++++++- ublarcvapp/UBPhotonLib/UBPhotonLib.cxx | 108 +++++++++++--- ublarcvapp/UBPhotonLib/UBPhotonLib.h | 19 ++- .../test/test_photon_estimator.cxx | 93 ++++++++++++ .../UBPhotonLib/test/test_photon_estimator.py | 133 ++++++++++++++++++ 10 files changed, 738 insertions(+), 30 deletions(-) create mode 100644 CLAUDE.md create mode 100644 ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.cxx create mode 100644 ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h create mode 100644 ublarcvapp/UBPhotonLib/test/test_photon_estimator.cxx create mode 100644 ublarcvapp/UBPhotonLib/test/test_photon_estimator.py diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..71e3e7e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,126 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +ublarcvapp is a C++ framework with Python bindings for analyzing Liquid Argon Time Projection Chamber (LArTPC) data from the MicroBooNE neutrino physics experiment. It provides tools for: +- Deep learning-based particle tagging and classification +- 3D reconstruction algorithms +- Image manipulation and processing +- Monte Carlo truth analysis +- Event filtering and selection + +## Build Commands + +### Prerequisites Setup +Ensure these environment variables are set: +- `LARCV_LIBDIR` - LArCV library directory +- `LARLITE_LIBDIR` and `LARLITE_INCDIR` - larlite directories +- `LARCV_INCDIR` - LArCV include directory +- `LAROPENCV_LIBDIR` and `LAROPENCV_INCDIR` - LArOpenCV directories +- Optional: `GEO2D_BASEDIR` - for Geo2D support + +### Building +```bash +mkdir build +cd build +cmake .. +make -j4 +make install +source ../configure.sh +``` + +### Running Tests +Tests are located in individual module `test/` directories. Example: +```bash +cd ublarcvapp/Reco3D/test +python test_astar.py + +cd ublarcvapp/UBImageMod/test +python test_ubsplit.py [input_larcv_file] [adc_producer_name] +``` + +## Code Architecture + +### Core Components + +1. **Processing Framework** (`LLCVProcessor/`) + - `LLCVProcessBase` - Base class for all processing modules + - `LLCVProcessDriver` - Manages processing chain execution + - Configuration via `.cfg` files + +2. **Image Processing** (`UBImageMod/`) + - `UBSplitDetector` - Splits detector images into subregions + - `UBCropLArFlow` - Crops sparse larflow data + - `InfillImageStitcher` - Stitches subimages back together + +3. **3D Reconstruction** (`Reco3D/`) + - `AStar3DAlgo` - A* pathfinding for 3D track reconstruction + - Configuration through `AStar3DAlgoConfig` + - Supports both regular and proton-specific tracking + +4. **Deep Learning Integration** (`DLTagger/`) + - `DLTagger` - Main interface for DL model predictions + - `MRCNNMatch` - Mask R-CNN matching algorithms + - Integrates with external DL model servers + +5. **Monte Carlo Tools** (`MCTools/`) + - Truth matching utilities + - Space charge effect corrections + - Flash matching algorithms + +### Key Design Patterns + +1. **Factory Pattern**: Most algorithms use factory registration: + ```cpp + static LArbysImageFactory __global_LArbysImageFactory__; + ``` + +2. **Configuration**: Algorithms use dedicated config classes: + ```cpp + class AlgoConfig : public larcv::PSet { + // Configuration parameters + }; + ``` + +3. **Process Chain**: Modules inherit from `LLCVProcessBase` and implement: + - `configure()` - Setup from config file + - `initialize()` - One-time initialization + - `process()` - Per-event processing + - `finalize()` - Cleanup + +### Data Flow + +1. Input: ROOT files containing larcv::EventImage2D, larlite::event_* objects +2. Processing: Chain of LLCVProcess modules +3. Output: Modified/new data products saved to output ROOT files + +## Development Guidelines + +### Adding New Modules + +1. Create directory under `ublarcvapp/` +2. Add CMakeLists.txt with: + ```cmake + set(MODULE_NAME YourModule) + add_subdirectory(${MODULE_NAME}) + ``` +3. Implement classes inheriting from `LLCVProcessBase` +4. Add LinkDef.h for ROOT dictionary generation +5. Register with factory if needed + +### Working with Sparse Data + +Many algorithms work with sparse representations: +- Use `larcv::EventSparseTensor2D` for sparse image data +- Convert between dense/sparse with utility functions +- Handle coordinate transformations carefully + +### Coordinate Systems + +Be aware of multiple coordinate systems: +- Wire/tick 2D coordinates per plane +- 3D spatial coordinates (with/without space charge effects) +- Image pixel coordinates +- Detector geometry coordinates \ No newline at end of file diff --git a/ublarcvapp/UBPhotonLib/CMakeLists.txt b/ublarcvapp/UBPhotonLib/CMakeLists.txt index b9ac2c3..817839c 100644 --- a/ublarcvapp/UBPhotonLib/CMakeLists.txt +++ b/ublarcvapp/UBPhotonLib/CMakeLists.txt @@ -6,11 +6,13 @@ set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers set( HEADERS UBPhotonLib.h + PhotonVisibilityEstimator.h ) # Add sources add_library( ${LIBNAME} SHARED UBPhotonLib.cxx + PhotonVisibilityEstimator.cxx ) # larlite libraries diff --git a/ublarcvapp/UBPhotonLib/LinkDef.h b/ublarcvapp/UBPhotonLib/LinkDef.h index 9619beb..21fbbae 100644 --- a/ublarcvapp/UBPhotonLib/LinkDef.h +++ b/ublarcvapp/UBPhotonLib/LinkDef.h @@ -18,6 +18,8 @@ #pragma link C++ namespace ublarcvapp::ubphotonlib; #pragma link C++ class ublarcvapp::ubphotonlib::UBPhotonLib+; +#pragma link C++ class ublarcvapp::ubphotonlib::PhotonVisibilityEstimator+; +#pragma link C++ class ublarcvapp::ubphotonlib::PhotonVisibilityEstimator::PhotonSource+; #endif diff --git a/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.cxx b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.cxx new file mode 100644 index 0000000..db487f1 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.cxx @@ -0,0 +1,111 @@ +#include "PhotonVisibilityEstimator.h" +#include "UBPhotonLib.h" +#include + +namespace ublarcvapp { +namespace ubphotonlib { + + PhotonVisibilityEstimator::PhotonVisibilityEstimator() + : _num_optical_channels(32) // MicroBooNE has 32 PMTs + { + // Ensure photon library is loaded + UBPhotonLib::getPhotonLib(); + } + + PhotonVisibilityEstimator::~PhotonVisibilityEstimator() + { + // Nothing to clean up + } + + void PhotonVisibilityEstimator::clear() + { + _sources.clear(); + } + + void PhotonVisibilityEstimator::addPhotonSource(float x, float y, float z, float num_photons) + { + _sources.emplace_back(x, y, z, num_photons); + } + + void PhotonVisibilityEstimator::addPhotonSource(const PhotonSource& source) + { + _sources.push_back(source); + } + + void PhotonVisibilityEstimator::addPhotonSources(const std::vector& sources) + { + _sources.insert(_sources.end(), sources.begin(), sources.end()); + } + + std::map PhotonVisibilityEstimator::calculateDetectedPhotons(bool use_trilinear) + { + std::map photons_per_opdet; + + // Initialize map with zeros for all optical channels + for (int opch = 0; opch < _num_optical_channels; ++opch) { + photons_per_opdet[opch] = 0.0; + } + + // Get photon library instance + UBPhotonLib* photon_lib = UBPhotonLib::getPhotonLib(); + + // For each point source + for (const auto& source : _sources) { + // Skip if no photons + if (source.num_photons <= 0) continue; + + // For each optical channel + for (int opch = 0; opch < _num_optical_channels; ++opch) { + float visibility = 0.0; + + // Get visibility from photon library + if (use_trilinear) { + visibility = photon_lib->getVisibilityTrilinear(source.position, opch); + } else { + visibility = photon_lib->getVisibility(source.position, opch); + } + + // Calculate number of photons detected by this channel from this source + // Visibility is the probability that a photon from this voxel reaches this opdet + float detected_photons = source.num_photons * visibility; + + // Add to total for this optical channel + photons_per_opdet[opch] += detected_photons; + } + } + + return photons_per_opdet; + } + + float PhotonVisibilityEstimator::getTotalDetectedPhotons(bool use_trilinear) + { + auto photons_per_opdet = calculateDetectedPhotons(use_trilinear); + + float total = 0.0; + for (const auto& entry : photons_per_opdet) { + total += entry.second; + } + + return total; + } + + float PhotonVisibilityEstimator::getTotalEmittedPhotons() const + { + float total = 0.0; + for (const auto& source : _sources) { + total += source.num_photons; + } + return total; + } + + float PhotonVisibilityEstimator::getCollectionEfficiency(bool use_trilinear) + { + float emitted = getTotalEmittedPhotons(); + if (emitted <= 0) return 0.0; + + float detected = getTotalDetectedPhotons(use_trilinear); + return detected / emitted; + } + +} +} \ No newline at end of file diff --git a/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h new file mode 100644 index 0000000..0e476e2 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h @@ -0,0 +1,114 @@ +#ifndef __UBLARCVAPP_UBPHOTONLIB_PHOTONVISIBILITYESTIMATOR_H__ +#define __UBLARCVAPP_UBPHOTONLIB_PHOTONVISIBILITYESTIMATOR_H__ + +#include +#include + +namespace ublarcvapp { +namespace ubphotonlib { + + /** + * @brief Class to estimate photon detection from multiple 3D point sources + * + * This class uses the UBPhotonLib to calculate how many photons from + * multiple 3D point sources will be detected by each optical detector. + */ + class PhotonVisibilityEstimator { + public: + + /** + * @brief Structure to hold a 3D point source with photon count + */ + struct PhotonSource { + std::vector position; ///< 3D position in detector coordinates (x,y,z) in cm + float num_photons; ///< Number of photons emitted at this location + + PhotonSource() : position(3,0), num_photons(0) {} + PhotonSource(float x, float y, float z, float nphotons) + : position{x,y,z}, num_photons(nphotons) {} + }; + + /** + * @brief Constructor + */ + PhotonVisibilityEstimator(); + + /** + * @brief Destructor + */ + ~PhotonVisibilityEstimator(); + + /** + * @brief Clear all point sources + */ + void clear(); + + /** + * @brief Add a single point source + * @param x X position in cm (detector coordinates) + * @param y Y position in cm (detector coordinates) + * @param z Z position in cm (detector coordinates) + * @param num_photons Number of photons emitted at this location + */ + void addPhotonSource(float x, float y, float z, float num_photons); + + /** + * @brief Add a single point source + * @param source PhotonSource struct containing position and photon count + */ + void addPhotonSource(const PhotonSource& source); + + /** + * @brief Add multiple point sources + * @param sources Vector of PhotonSource structs + */ + void addPhotonSources(const std::vector& sources); + + /** + * @brief Calculate photons detected by each optical detector + * @param use_trilinear If true, use trilinear interpolation for visibility (default: true) + * @return Map from optical channel ID to number of detected photons + */ + std::map calculateDetectedPhotons(bool use_trilinear = true); + + /** + * @brief Get total number of photons detected across all optical detectors + * @param use_trilinear If true, use trilinear interpolation for visibility (default: true) + * @return Total number of detected photons + */ + float getTotalDetectedPhotons(bool use_trilinear = true); + + /** + * @brief Get number of point sources + * @return Number of point sources currently stored + */ + size_t getNumSources() const { return _sources.size(); } + + /** + * @brief Get total number of emitted photons from all sources + * @return Total number of emitted photons + */ + float getTotalEmittedPhotons() const; + + /** + * @brief Get the collection efficiency (detected/emitted) + * @param use_trilinear If true, use trilinear interpolation for visibility (default: true) + * @return Collection efficiency as a fraction + */ + float getCollectionEfficiency(bool use_trilinear = true); + + /** + * @brief Get number of optical channels + * @return Number of optical channels in the detector + */ + int getNumOpticalChannels() const { return _num_optical_channels; } + + private: + std::vector _sources; ///< Vector of photon point sources + int _num_optical_channels; ///< Number of optical detectors + }; + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/UBPhotonLib/README.md b/ublarcvapp/UBPhotonLib/README.md index ec88436..a25f582 100644 --- a/ublarcvapp/UBPhotonLib/README.md +++ b/ublarcvapp/UBPhotonLib/README.md @@ -1,4 +1,62 @@ -# UB Photon Library Interface +# UBPhotonLib + +Interface to visibility library for MicroBooNE. + +## Classes + +### UBPhotonLib +Singleton class providing access to the photon visibility library. This class loads the photon library data and provides methods to query the visibility (probability of detection) for photons emitted from any voxel in the detector to any optical detector. + +### PhotonVisibilityEstimator +A utility class that uses UBPhotonLib to estimate photon detection from multiple 3D point sources. This is useful for: +- Estimating scintillation light from particle tracks +- Calculating total light yield from complex geometries +- Comparing detection patterns across different optical detectors + +## Usage Examples + +### Python Example +```python +from ublarcvapp import ublarcvapp + +# Create estimator +estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + +# Add point sources (x, y, z in cm, number of photons) +estimator.addPhotonSource(100.0, 0.0, 400.0, 1000.0) +estimator.addPhotonSource(110.0, 10.0, 420.0, 1500.0) + +# Calculate detected photons per optical detector +photons_per_opdet = estimator.calculateDetectedPhotons(use_trilinear=True) + +# Get total collection efficiency +efficiency = estimator.getCollectionEfficiency(True) +print(f"Collection efficiency: {efficiency:.4f}") +``` + +### C++ Example +```cpp +#include "ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h" + +using namespace ublarcvapp::ubphotonlib; + +PhotonVisibilityEstimator estimator; + +// Add point sources +estimator.addPhotonSource(100.0, 0.0, 400.0, 1000.0); + +// Calculate results +auto photons_map = estimator.calculateDetectedPhotons(true); +float total = estimator.getTotalDetectedPhotons(true); +``` + +## Test Scripts +- `test/test_photon_estimator.py` - Python example with visualization +- `test/test_photon_estimator.cxx` - C++ standalone example + +## Technical Details + +### Photon Library Files Where can I get the photon library file? diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx index 01eccde..86553c9 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.cxx @@ -2,6 +2,7 @@ #include #include +#include #include "TFile.h" #include "TTree.h" @@ -90,12 +91,12 @@ namespace ubphotonlib { lindex = Voxel*_nopchs + OpChannel; if ( i>0 && i%10000000==0 ) { - std::cout << " loading entry " << i << ":" - << " vis=" << Visibility - << " vox=" << Voxel - << " opdet=" << OpChannel - <<" lindex=" << lindex - << std::endl; + std::cout << " loading entry " << i << ":" + << " vis=" << Visibility + << " vox=" << Voxel + << " opdet=" << OpChannel + <<" lindex=" << lindex + << std::endl; } _visibility_v[lindex] = Visibility; } @@ -164,7 +165,7 @@ namespace ubphotonlib { bool valid = true; for (int i=0; i<3; i++) { if ( voxcoords[i]<0 || voxcoords[i]>=_nvoxels_dim[i] ) - valid = false; + valid = false; } if (!valid) return -1; @@ -195,19 +196,88 @@ namespace ubphotonlib { float UBPhotonLib::getVisibilityTrilinear( const std::vector& pos, int opch ) { - long lindex = getVoxelIndex( pos, opch ); - if ( lindex<0 || lindex>(long)_visibility_v.size() ) - return 0.0; - - std::pair voxopch_key( lindex, opch ); - auto it=_voxelopchindex_to_visibility.find( voxopch_key ); - if ( it==_voxelopchindex_to_visibility.end() ) { - // not found - return 0.0; + // Calculate fractional position in grid coordinates + std::vector grid_pos(3, 0); + std::vector base_voxel(3, 0); + std::vector frac(3, 0); + + for (int i = 0; i < 3; i++) { + grid_pos[i] = (pos[i] - _cryo_origin_tpc_coord_cm[i]) / _voxel_len_cm[i]; + base_voxel[i] = (long)std::floor(grid_pos[i]); + frac[i] = grid_pos[i] - base_voxel[i]; + + // Check bounds + if (base_voxel[i] < 0 || base_voxel[i] >= _nvoxels_dim[i] - 1) { + // Outside grid bounds, fall back to nearest neighbor + return getVisibility(pos, opch); + } } - - // return visibility - return it->second; + + // Get visibility values for the 8 surrounding voxels + float vis[2][2][2]; + bool valid = true; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + std::vector voxel_coords = { + base_voxel[0] + i, + base_voxel[1] + j, + base_voxel[2] + k + }; + + // Check if voxel is within bounds + for (int dim = 0; dim < 3; dim++) { + if (voxel_coords[dim] < 0 || voxel_coords[dim] >= _nvoxels_dim[dim]) { + valid = false; + break; + } + } + + if (!valid) break; + + long voxel_id = getVoxelID(voxel_coords); + if (voxel_id < 0) { + valid = false; + break; + } + + long lib_index = getVisLibIndex(voxel_id, opch); + if (lib_index < 0 || lib_index >= (long)_visibility_v.size()) { + vis[i][j][k] = 0.0; + } else { + vis[i][j][k] = _visibility_v[lib_index]; + } + } + if (!valid) break; + } + if (!valid) break; + } + + // If any voxel was invalid, fall back to nearest neighbor + if (!valid) { + return getVisibility(pos, opch); + } + + // Perform trilinear interpolation + // First interpolate along x-axis + float vis_x[2][2]; + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + vis_x[j][k] = vis[0][j][k] * (1.0 - frac[0]) + vis[1][j][k] * frac[0]; + } + } + + // Then interpolate along y-axis + float vis_xy[2]; + for (int k = 0; k < 2; k++) { + vis_xy[k] = vis_x[0][k] * (1.0 - frac[1]) + vis_x[1][k] * frac[1]; + } + + // Finally interpolate along z-axis + float result = vis_xy[0] * (1.0 - frac[2]) + vis_xy[1] * frac[2]; + + return result; } } diff --git a/ublarcvapp/UBPhotonLib/UBPhotonLib.h b/ublarcvapp/UBPhotonLib/UBPhotonLib.h index d25c0be..fbc89d8 100644 --- a/ublarcvapp/UBPhotonLib/UBPhotonLib.h +++ b/ublarcvapp/UBPhotonLib/UBPhotonLib.h @@ -25,7 +25,6 @@ namespace ubphotonlib { std::vector getVoxelCoords( long voxelid ) const; std::vector getVoxelCoords( const std::vector& pos ) const; long getVisLibIndex( long voxelid, int opch ) const; - long getVoxelIndex( const std::vector& pos, int opch ) const; long getVisLibIndex( const std::vector& pos, int opch ) const; long getVoxelID( const std::vector& voxcoords ) const; @@ -35,17 +34,17 @@ namespace ubphotonlib { int dim_index[3]; float vis; VisData_t() - : voxelid(0), - opchid(0), - dim_index{0,0,0}, - vis(0.0) + : voxelid(0), + opchid(0), + dim_index{0,0,0}, + vis(0.0) {}; bool operator<( VisData_t& rhs ) const { - if (rhs.voxelid < voxelid ) - return true; - if ( rhs.voxelid==voxelid && rhs.opchid < opchid ) - return true; - return false; + if (rhs.voxelid < voxelid ) + return true; + if ( rhs.voxelid==voxelid && rhs.opchid < opchid ) + return true; + return false; }; }; diff --git a/ublarcvapp/UBPhotonLib/test/test_photon_estimator.cxx b/ublarcvapp/UBPhotonLib/test/test_photon_estimator.cxx new file mode 100644 index 0000000..07d7f31 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/test/test_photon_estimator.cxx @@ -0,0 +1,93 @@ +/** + * Example C++ usage of PhotonVisibilityEstimator + * + * Compile with: + * g++ -o test_photon_estimator test_photon_estimator.cxx \ + * `root-config --cflags --libs` \ + * -I$UBLARCVAPP_INCDIR -L$UBLARCVAPP_LIBDIR -lLArCVApp_UBPhotonLib + */ + +#include +#include +#include + +#include "ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h" + +using namespace ublarcvapp::ubphotonlib; + +int main() { + + // Create estimator + PhotonVisibilityEstimator estimator; + + std::cout << "PhotonVisibilityEstimator Example" << std::endl; + std::cout << "Number of optical channels: " << estimator.getNumOpticalChannels() << std::endl; + + // Example 1: Track-like distribution + std::cout << "\n--- Example 1: Track-like distribution ---" << std::endl; + + // Add points along a track + float x_start = 128.0, y_start = 0.0, z_start = 500.0; // cm + float x_end = 128.0, y_end = 50.0, z_end = 600.0; // cm + int n_points = 10; + float photons_per_point = 1000.0; + + for (int i = 0; i < n_points; ++i) { + float t = float(i) / (n_points - 1); + float x = x_start + t * (x_end - x_start); + float y = y_start + t * (y_end - y_start); + float z = z_start + t * (z_end - z_start); + + estimator.addPhotonSource(x, y, z, photons_per_point); + } + + std::cout << "Added " << estimator.getNumSources() << " point sources" << std::endl; + std::cout << "Total emitted photons: " << estimator.getTotalEmittedPhotons() << std::endl; + + // Calculate detected photons + auto photons_per_opdet = estimator.calculateDetectedPhotons(true); + + // Print results + std::cout << "\nPhotons detected by each optical detector:" << std::endl; + float total_detected = 0.0; + for (const auto& entry : photons_per_opdet) { + int opch = entry.first; + float n_photons = entry.second; + if (n_photons > 0) { + std::cout << " OpDet " << opch << ": " << n_photons << " photons" << std::endl; + total_detected += n_photons; + } + } + + std::cout << "\nTotal detected photons: " << total_detected << std::endl; + std::cout << "Collection efficiency: " << estimator.getCollectionEfficiency(true) << std::endl; + + // Example 2: Using PhotonSource struct + std::cout << "\n--- Example 2: Using PhotonSource struct ---" << std::endl; + + estimator.clear(); + + // Create a vector of sources + std::vector sources; + + // Add a few discrete sources + sources.emplace_back(100.0, 0.0, 300.0, 5000.0); + sources.emplace_back(150.0, 20.0, 400.0, 3000.0); + sources.emplace_back(200.0, -10.0, 500.0, 4000.0); + + // Add all at once + estimator.addPhotonSources(sources); + + std::cout << "Added " << estimator.getNumSources() << " discrete sources" << std::endl; + std::cout << "Total emitted photons: " << estimator.getTotalEmittedPhotons() << std::endl; + + // Compare with and without trilinear interpolation + float total_trilinear = estimator.getTotalDetectedPhotons(true); + float total_no_trilinear = estimator.getTotalDetectedPhotons(false); + + std::cout << "\nWith trilinear interpolation: " << total_trilinear << " photons detected" << std::endl; + std::cout << "Without trilinear interpolation: " << total_no_trilinear << " photons detected" << std::endl; + std::cout << "Difference: " << (total_trilinear - total_no_trilinear) << " photons" << std::endl; + + return 0; +} \ No newline at end of file diff --git a/ublarcvapp/UBPhotonLib/test/test_photon_estimator.py b/ublarcvapp/UBPhotonLib/test/test_photon_estimator.py new file mode 100644 index 0000000..f6d0a30 --- /dev/null +++ b/ublarcvapp/UBPhotonLib/test/test_photon_estimator.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +""" +Test script for PhotonVisibilityEstimator class +Demonstrates how to estimate photon detection from multiple 3D point sources +""" + +import ROOT as rt +from ROOT import std +from larcv import larcv +from ublarcvapp import ublarcvapp + +# Load the library +rt.gSystem.Load("libLArCVApp_UBPhotonLib.so") + +def test_photon_estimator(): + """Test the PhotonVisibilityEstimator functionality""" + + # Create estimator instance + estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + print("Created PhotonVisibilityEstimator") + print("Number of optical channels:", estimator.getNumOpticalChannels()) + + # Example 1: Add individual point sources + # These positions should be in detector coordinates (cm) + # Let's add some points along a track + print("\n--- Example 1: Individual point sources ---") + + # Add points along a hypothetical track + # Starting near center of detector + x_start, y_start, z_start = 128.0, 0.0, 500.0 # cm + x_end, y_end, z_end = 128.0, 50.0, 600.0 # cm + + # Create 10 points along this track + n_points = 10 + photons_per_point = 1000.0 # photons per point + + for i in range(n_points): + t = float(i) / (n_points - 1) + x = x_start + t * (x_end - x_start) + y = y_start + t * (y_end - y_start) + z = z_start + t * (z_end - z_start) + + estimator.addPhotonSource(x, y, z, photons_per_point) + + print("Added {} point sources".format(estimator.getNumSources())) + print("Total emitted photons: {}".format(estimator.getTotalEmittedPhotons())) + + # Calculate detected photons + photons_per_opdet = estimator.calculateDetectedPhotons(use_trilinear=True) + + # Print results + print("\nPhotons detected by each optical detector:") + total_detected = 0.0 + for opch in range(estimator.getNumOpticalChannels()): + n_photons = photons_per_opdet[opch] + if n_photons > 0: + print(" OpDet {:2d}: {:8.2f} photons".format(opch, n_photons)) + total_detected += n_photons + + print("\nTotal detected photons: {:.2f}".format(total_detected)) + print("Collection efficiency: {:.4f}".format(estimator.getCollectionEfficiency(True))) + + # Example 2: Using PhotonSource struct + print("\n--- Example 2: Using PhotonSource struct ---") + + # Clear previous sources + estimator.clear() + + # Create a vector of sources + sources = std.vector('ublarcvapp::ubphotonlib::PhotonVisibilityEstimator::PhotonSource')() + + # Add sources in a different pattern - a shower-like distribution + center_x, center_y, center_z = 100.0, 0.0, 400.0 + spread = 20.0 # cm + + import random + random.seed(42) + + for i in range(20): + # Random positions around center + x = center_x + random.gauss(0, spread) + y = center_y + random.gauss(0, spread) + z = center_z + random.gauss(0, spread) + + # More photons near center + distance = ((x-center_x)**2 + (y-center_y)**2 + (z-center_z)**2)**0.5 + n_photons = 2000.0 * (1.0 - distance / (3*spread)) + if n_photons < 0: + n_photons = 0 + + source = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator.PhotonSource(x, y, z, n_photons) + sources.push_back(source) + + # Add all sources at once + estimator.addPhotonSources(sources) + + print("Added {} shower-like point sources".format(estimator.getNumSources())) + print("Total emitted photons: {:.2f}".format(estimator.getTotalEmittedPhotons())) + + # Calculate with and without trilinear interpolation + print("\nWith trilinear interpolation:") + total_trilinear = estimator.getTotalDetectedPhotons(use_trilinear=True) + print(" Total detected: {:.2f}".format(total_trilinear)) + print(" Collection efficiency: {:.4f}".format(estimator.getCollectionEfficiency(True))) + + print("\nWithout trilinear interpolation:") + total_no_trilinear = estimator.getTotalDetectedPhotons(use_trilinear=False) + print(" Total detected: {:.2f}".format(total_no_trilinear)) + print(" Collection efficiency: {:.4f}".format(estimator.getCollectionEfficiency(False))) + + # Example 3: Visualize detection pattern + print("\n--- Example 3: Detection pattern visualization ---") + + # Get photons per detector for visualization + photons_per_opdet = estimator.calculateDetectedPhotons(use_trilinear=True) + + # Create a simple histogram + h_opdet = rt.TH1F("h_opdet", "Photons Detected per Optical Detector;OpDet ID;Photons", + 32, 0, 32) + + for opch in range(32): + h_opdet.SetBinContent(opch+1, photons_per_opdet[opch]) + + # Draw if running interactively + canvas = rt.TCanvas("c1", "Photon Detection", 800, 600) + h_opdet.SetFillColor(rt.kBlue-9) + h_opdet.Draw("HIST") + canvas.SaveAs("photon_detection_pattern.png") + print("Saved histogram to photon_detection_pattern.png") + +if __name__ == "__main__": + test_photon_estimator() \ No newline at end of file From 52f9626fa241eba04a0600f469f7772a87bf45c1 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 12 Jun 2025 11:40:59 -0400 Subject: [PATCH 66/80] added track to spacepoint with charge utility for optical signal prediction --- ublarcvapp/CMakeLists.txt | 1 + .../ParticleToPixelUtils/CMakeLists.txt | 61 ++ ublarcvapp/ParticleToPixelUtils/LinkDef.h | 23 + ublarcvapp/ParticleToPixelUtils/README.md | 0 .../TrackToSpacePoints.cxx | 355 +++++++++++ .../ParticleToPixelUtils/TrackToSpacePoints.h | 169 +++++ .../complete_track_light_example.py | 595 ++++++++++++++++++ .../UBImageMod/PointImageProjection.cxx | 9 +- 8 files changed, 1212 insertions(+), 1 deletion(-) create mode 100644 ublarcvapp/ParticleToPixelUtils/CMakeLists.txt create mode 100644 ublarcvapp/ParticleToPixelUtils/LinkDef.h create mode 100644 ublarcvapp/ParticleToPixelUtils/README.md create mode 100644 ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.cxx create mode 100644 ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h create mode 100644 ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index de818ef..13b212d 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -12,6 +12,7 @@ if (HAS_LARLITE) # add_subdirectory(Filter) add_subdirectory(MCTools) add_subdirectory(UBPhotonLib) + add_subdirectory(ParticleToPixelUtils) endif() #if (Boost_FOUND) # add_subdirectory(DLTagger) diff --git a/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt b/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt new file mode 100644 index 0000000..6ee3a2a --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt @@ -0,0 +1,61 @@ +set(MODULE_NAME ParticleToPixelUtils) + +# library name +set(LIBNAME LArCVApp_${MODULE_NAME}) + +# Collect the headers +set( HEADERS + TrackToSpacePoints.h +) + +# Add sources +add_library( ${LIBNAME} SHARED + TrackToSpacePoints.cxx +) + +# larlite libraries +set(LARLITE_LIBS_USED ${LARLITE_LIBS} ) + +set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") + +target_include_directories(${LIBNAME} + PUBLIC + $ + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} + PRIVATE + ${PROJECT_SOURCE_DIR} +) + +target_link_libraries( ${LIBNAME} PUBLIC + ${LARLITE_LIBS_USED} + LArCVCoreBase + LArCVCoreDataFormat + LArCVCoreProcessor + LArCVApp_UBPhotonLib +) + +# includes for ROOT dictionary gen +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR} + ${LARLITE_INCLUDE_DIR} + ${LARCV_INCLUDE_DIR} +) + +# Generate the dictionary +ROOT_GENERATE_DICTIONARY(G__${LIBNAME} ${HEADERS} LINKDEF LinkDef.h) + +# add dictionary file to sources +target_sources( ${LIBNAME} PRIVATE G__${LIBNAME}.cxx ) + +# install libraries and headers +install(TARGETS ${LIBNAME} + EXPORT ublarcvapp + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION include/ublarcvapp/${MODULE_NAME}) + +# install files needed for dictionary use in CINT/CLING/PYTHON +install( FILES + ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}_rdict.pcm + ${CMAKE_CURRENT_BINARY_DIR}/lib${LIBNAME}.rootmap + DESTINATION lib ) \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/LinkDef.h b/ublarcvapp/ParticleToPixelUtils/LinkDef.h new file mode 100644 index 0000000..2b3dd62 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/LinkDef.h @@ -0,0 +1,23 @@ +/** \defgroup ParticleToPixelUtils + * + * \brief Utilities for converting particle representations to pixel/space point data + * + * cint script to generate libraries and python bindings. + * Declare namespace & classes you defined + * pragma statement: order matters! Google it ;) + * + */ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ namespace ublarcvapp; +#pragma link C++ namespace ublarcvapp::pixelutils; + +#pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints+; +#pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints::SpacePointCharge+; +#pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints::PixelData+; + +#endif \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/README.md b/ublarcvapp/ParticleToPixelUtils/README.md new file mode 100644 index 0000000..e69de29 diff --git a/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.cxx b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.cxx new file mode 100644 index 0000000..723f391 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.cxx @@ -0,0 +1,355 @@ +#include "TrackToSpacePoints.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include + +namespace ublarcvapp { +namespace pixelutils { + + TrackToSpacePoints::TrackToSpacePoints() + : _use_charge_weighting(false), + _npix_processed(0), + _total_charge(0.0) + { + } + + TrackToSpacePoints::~TrackToSpacePoints() + { + } + + std::vector + TrackToSpacePoints::convertTrack( + const larlite::track& track, + const std::vector& adc_v, + const float threshold, + const int dcol, + const int drow, + const float minstepsize, + const float maxstepsize) + { + std::vector spacepoints; + + // Reset counters + _npix_processed = 0; + _total_charge = 0.0; + + int npts = track.NumberTrajectoryPoints(); + if (npts <= 1) { + std::cerr << "TrackToSpacePoints: Cannot process track with only " + << npts << " point(s)" << std::endl; + return spacepoints; + } + + // Check we have 3 planes + if (adc_v.size() != 3) { + std::cerr << "TrackToSpacePoints: Expected 3 planes, got " + << adc_v.size() << std::endl; + return spacepoints; + } + + const float driftv = larutil::LArProperties::GetME()->DriftVelocity(); + const float usec_per_tick = 0.5; + float max_tick = adc_v.front().meta().max_y(); + float min_tick = adc_v.front().meta().min_y(); + + // Keep track of processed pixels to avoid double counting + std::set> processed_pixels; // (plane,row,col) + + // Map from 3D position to pixel data + std::map> step_pixels; // step index -> pixels + std::map step_positions; // step index -> 3D position + + int global_step = 0; + + // Loop over track segments + for (int ipt = 0; ipt < npts-1; ipt++) { + + TVector3 start = track.LocationAtPoint(ipt); + TVector3 end = track.LocationAtPoint(ipt+1); + TVector3 dir = end - start; + + double segsize = dir.Mag(); + + int nsteps = 1; + if (segsize > minstepsize) { + nsteps = segsize/maxstepsize + 1; + } + + float stepsize = segsize/float(nsteps); + + // Step along the segment + for (int istep = 0; istep <= nsteps; istep++) { + + // Get 3D position along track + TVector3 pos = start + istep*(stepsize/segsize)*dir; + step_positions[global_step] = pos; + + // Calculate tick from X position + int tick = pos[0]/driftv/usec_per_tick + 3200; + + if (tick < min_tick || tick > max_tick) + continue; + + int row = adc_v.front().meta().row(tick); + + // Project into each wire plane + for (int p = 0; p < 3; p++) { + int wire = larutil::Geometry::GetME()->WireCoordinate(pos, p); + + // Collect charge from neighboring pixels + for (int dr = -abs(drow); dr <= abs(drow); dr++) { + int r = row + dr; + if (r < 0 || r >= (int)adc_v[p].meta().rows()) + continue; + + for (int dc = -abs(dcol); dc <= abs(dcol); dc++) { + int c = wire + dc; + if (c < 0 || c >= (int)adc_v[p].meta().cols()) + continue; + + float pixval = adc_v[p].pixel(r, c); + if (pixval > threshold) { + // Check if we've already processed this pixel + auto pixel_key = std::make_tuple(p, r, c); + if (processed_pixels.find(pixel_key) == processed_pixels.end()) { + processed_pixels.insert(pixel_key); + step_pixels[global_step].insert(PixelData(p, r, c, pixval)); + _npix_processed++; + _total_charge += pixval; + } + } + } + } + } + + global_step++; + } + } + + // Now create space points from the collected pixel data + for (auto& step_entry : step_pixels) { + int step_idx = step_entry.first; + auto& pixels = step_entry.second; + + if (pixels.empty()) + continue; + + SpacePointCharge sp; + + // Use the track position or charge-weighted position + if (_use_charge_weighting && !pixels.empty()) { + sp.position = getChargeWeightedPosition(pixels, adc_v); + } else { + sp.position = step_positions[step_idx]; + } + + // Calculate total charge and per-plane charges + sp.charge = 0; + sp.plane_charges.resize(3, 0); + + int tick_sum = 0; + int tick_count = 0; + std::vector wire_nums(3, -1); + + for (const auto& pix : pixels) { + sp.charge += pix.value; + sp.plane_charges[pix.plane] += pix.value; + + if (pix.plane == 0 && wire_nums[0] == -1) { + wire_nums[0] = pix.col; + } else if (pix.plane == 1 && wire_nums[1] == -1) { + wire_nums[1] = pix.col; + } else if (pix.plane == 2 && wire_nums[2] == -1) { + wire_nums[2] = pix.col; + } + + tick_sum += pix.row; + tick_count++; + } + + // Set wire numbers and average tick + sp.wire_u = wire_nums[0]; + sp.wire_v = wire_nums[1]; + sp.wire_y = wire_nums[2]; + sp.tick = (tick_count > 0) ? tick_sum / tick_count : -1; + + spacepoints.push_back(sp); + } + + return spacepoints; + } + + std::set + TrackToSpacePoints::getUniquePixels( + const larlite::track& track, + const std::vector& adc_v, + const float threshold, + const int dcol, + const int drow, + const float minstepsize, + const float maxstepsize) + { + std::set unique_pixels; + + int npts = track.NumberTrajectoryPoints(); + if (npts <= 1) { + return unique_pixels; + } + + const float driftv = larutil::LArProperties::GetME()->DriftVelocity(); + const float usec_per_tick = 0.5; + float max_tick = adc_v.front().meta().max_y(); + float min_tick = adc_v.front().meta().min_y(); + + // Loop over track segments + for (int ipt = 0; ipt < npts-1; ipt++) { + + TVector3 start = track.LocationAtPoint(ipt); + TVector3 end = track.LocationAtPoint(ipt+1); + TVector3 dir = end - start; + + double segsize = dir.Mag(); + + int nsteps = 1; + if (segsize > minstepsize) { + nsteps = segsize/maxstepsize + 1; + } + + float stepsize = segsize/float(nsteps); + + // Step along the segment + for (int istep = 0; istep <= nsteps; istep++) { + + // Get 3D position along track + TVector3 pos = start + istep*(stepsize/segsize)*dir; + + // Calculate tick from X position + int tick = pos[0]/driftv/usec_per_tick + 3200; + + if (tick < min_tick || tick > max_tick) + continue; + + int row = adc_v.front().meta().row(tick); + + // Project into each wire plane + for (int p = 0; p < 3; p++) { + int wire = larutil::Geometry::GetME()->WireCoordinate(pos, p); + + // Collect charge from neighboring pixels + for (int dr = -abs(drow); dr <= abs(drow); dr++) { + int r = row + dr; + if (r < 0 || r >= (int)adc_v[p].meta().rows()) + continue; + + for (int dc = -abs(dcol); dc <= abs(dcol); dc++) { + int c = wire + dc; + if (c < 0 || c >= (int)adc_v[p].meta().cols()) + continue; + + float pixval = adc_v[p].pixel(r, c); + if (pixval > threshold) { + unique_pixels.insert(PixelData(p, r, c, pixval)); + } + } + } + } + } + } + + return unique_pixels; + } + + TVector3 TrackToSpacePoints::getChargeWeightedPosition( + const std::set& pixels, + const std::vector& adc_v) + { + if (pixels.empty()) { + return TVector3(0, 0, 0); + } + + // Group pixels by plane + std::map> plane_pixels; + for (const auto& pix : pixels) { + plane_pixels[pix.plane].push_back(&pix); + } + + // Calculate charge-weighted wire position for each plane + std::map weighted_wires; + std::map total_charges; + float weighted_tick = 0; + float total_tick_charge = 0; + + for (const auto& plane_pair : plane_pixels) { + int plane = plane_pair.first; + float weighted_wire = 0; + float plane_charge = 0; + + for (const auto* pix : plane_pair.second) { + weighted_wire += pix->col * pix->value; + plane_charge += pix->value; + weighted_tick += pix->row * pix->value; + total_tick_charge += pix->value; + } + + if (plane_charge > 0) { + weighted_wires[plane] = weighted_wire / plane_charge; + total_charges[plane] = plane_charge; + } + } + + if (total_tick_charge > 0) { + weighted_tick /= total_tick_charge; + } + + // Convert weighted wire/tick to 3D position + // This is approximate - ideally would use proper 3D reconstruction + float x = tickToX(weighted_tick); + + // Average Y,Z from different plane projections + float y_sum = 0, z_sum = 0; + int n_planes = 0; + + for (const auto& wire_pair : weighted_wires) { + int plane = wire_pair.first; + float wire = wire_pair.second; + float y, z; + wireTickToYZ(plane, wire, weighted_tick, y, z); + y_sum += y; + z_sum += z; + n_planes++; + } + + if (n_planes > 0) { + y_sum /= n_planes; + z_sum /= n_planes; + } + + return TVector3(x, y_sum, z_sum); + } + + float TrackToSpacePoints::tickToX(int tick) const + { + const float driftv = larutil::LArProperties::GetME()->DriftVelocity(); + const float usec_per_tick = 0.5; + return (tick - 3200) * driftv * usec_per_tick; + } + + void TrackToSpacePoints::wireTickToYZ(int plane, int wire, int tick, + float& y, float& z) const + { + // Get 3D position from wire/tick + // This is a simplified version - in practice would use proper geometry + auto const* geom = larutil::Geometry::GetME(); + + // Get wire start and end points + double xyz_start[3], xyz_end[3]; + geom->WireEndPoints(plane, wire, xyz_start, xyz_end); + + // For now, use wire midpoint for Y,Z + // A more sophisticated approach would use the tick info + y = (xyz_start[1] + xyz_end[1]) / 2.0; + z = (xyz_start[2] + xyz_end[2]) / 2.0; + } + +} +} \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h new file mode 100644 index 0000000..ea8ffb4 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h @@ -0,0 +1,169 @@ +#ifndef __UBLARCVAPP_PARTICLETOPIXELUTILS_TRACKTOSPACEPOINTS_H__ +#define __UBLARCVAPP_PARTICLETOPIXELUTILS_TRACKTOSPACEPOINTS_H__ + +#include +#include +#include + +#include "larlite/DataFormat/track.h" +#include "larcv/core/DataFormat/Image2D.h" +#include "TVector3.h" + +namespace ublarcvapp { +namespace pixelutils { + + /** + * @brief Convert larlite tracks to collections of 3D space points with charge + * + * This class takes a larlite::track object and extracts charge information + * from ADC images at the projected 2D positions along the track. + * It produces a collection of 3D space points with associated charge values. + */ + class TrackToSpacePoints { + public: + + /** + * @brief Structure to hold a 3D space point with charge information + */ + struct SpacePointCharge { + TVector3 position; ///< 3D position in detector coordinates (cm) + float charge; ///< Total charge from neighboring pixels + int wire_u; ///< U-plane wire number + int wire_v; ///< V-plane wire number + int wire_y; ///< Y-plane wire number + int tick; ///< Time tick + std::vector plane_charges; ///< Charge on each plane [U,V,Y] + + SpacePointCharge() + : position(0,0,0), charge(0), + wire_u(-1), wire_v(-1), wire_y(-1), tick(-1), + plane_charges(3,0) {} + }; + + /** + * @brief Structure to hold pixel coordinate and value + */ + struct PixelData { + int plane; ///< Wire plane index + int row; ///< Row (tick) index + int col; ///< Column (wire) index + float value; ///< Pixel ADC value + + PixelData(int p, int r, int c, float v) + : plane(p), row(r), col(c), value(v) {} + + // Define comparison operator for set + bool operator<(const PixelData& other) const { + if (plane != other.plane) return plane < other.plane; + if (row != other.row) return row < other.row; + return col < other.col; + } + }; + + /** + * @brief Constructor + */ + TrackToSpacePoints(); + + /** + * @brief Destructor + */ + ~TrackToSpacePoints(); + + /** + * @brief Convert a track to space points with charge + * @param track The larlite::track to convert + * @param adc_v Vector of ADC images for each wire plane + * @param threshold ADC threshold for pixel selection + * @param dcol Column window around projected wire position + * @param drow Row window around projected tick position + * @param minstepsize Minimum step size along track (cm) + * @param maxstepsize Maximum step size along track (cm) + * @return Vector of SpacePointCharge objects along the track + */ + std::vector convertTrack( + const larlite::track& track, + const std::vector& adc_v, + const float threshold = 10.0, + const int dcol = 3, + const int drow = 3, + const float minstepsize = 0.3, + const float maxstepsize = 0.5 + ); + + /** + * @brief Get all unique pixels touched by the track projection + * @param track The larlite::track to analyze + * @param adc_v Vector of ADC images for each wire plane + * @param threshold ADC threshold for pixel selection + * @param dcol Column window around projected wire position + * @param drow Row window around projected tick position + * @param minstepsize Minimum step size along track (cm) + * @param maxstepsize Maximum step size along track (cm) + * @return Set of unique PixelData objects + */ + std::set getUniquePixels( + const larlite::track& track, + const std::vector& adc_v, + const float threshold = 10.0, + const int dcol = 3, + const int drow = 3, + const float minstepsize = 0.3, + const float maxstepsize = 0.5 + ); + + /** + * @brief Get charge-weighted average position for a collection of pixels + * @param pixels Set of pixels with charge values + * @param adc_v Vector of ADC images for wire/tick to position conversion + * @return Charge-weighted 3D position + */ + TVector3 getChargeWeightedPosition( + const std::set& pixels, + const std::vector& adc_v + ); + + /** + * @brief Set whether to use charge weighting for space point positions + * @param use_weighting If true, use charge-weighted positions + */ + void setUseChargeWeighting(bool use_weighting) { _use_charge_weighting = use_weighting; } + + /** + * @brief Get total number of pixels processed in last conversion + */ + int getNumPixelsProcessed() const { return _npix_processed; } + + /** + * @brief Get total charge collected in last conversion + */ + float getTotalCharge() const { return _total_charge; } + + private: + + bool _use_charge_weighting; ///< Use charge-weighted positions + int _npix_processed; ///< Number of pixels processed + float _total_charge; ///< Total charge collected + + /** + * @brief Convert tick to X position + * @param tick Time tick + * @return X position in cm + */ + float tickToX(int tick) const; + + /** + * @brief Convert wire and tick to Y,Z position + * @param plane Wire plane index + * @param wire Wire number + * @param tick Time tick + * @param y Output Y position + * @param z Output Z position + */ + void wireTickToYZ(int plane, int wire, int tick, float& y, float& z) const; + }; + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py b/ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py new file mode 100644 index 0000000..334b338 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py @@ -0,0 +1,595 @@ +#!/usr/bin/env python3 +""" +Complete example demonstrating the full workflow from track to light detection estimation. + +This script shows: +1. How to create realistic larlite::track objects from line segments +2. How to create realistic ADC images with proper geometry and charge deposits +3. How to use TrackToSpacePoints to convert tracks to space points with charge +4. How to convert charge to photons using LAr physics +5. How to use PhotonVisibilityEstimator to predict light detection + +Usage: + python3 complete_track_light_example.py [--input-file file.root] [--save-output] +""" + +import ROOT as rt +from ROOT import std +import numpy as np +import argparse +import sys + +# Load libraries +from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp + +def create_track_from_segments(segments): + """ + Create a larlite::track from a list of 3D line segments + + Args: + segments: List of tuples [(start_point, end_point), ...] + where each point is (x, y, z) in cm + + Returns: + larlite::track object + """ + track = larlite.track() + + print(f"Creating track from {len(segments)} line segments") + + for i, (start, end) in enumerate(segments): + # Add start point (skip if it's the same as previous end point) + if i == 0: + pos = rt.TVector3(start[0], start[1], start[2]) + track.add_vertex(pos) + + # Add end point + pos = rt.TVector3(end[0], end[1], end[2]) + track.add_vertex(pos) + + # Calculate direction vector + dx = end[0] - start[0] + dy = end[1] - start[1] + dz = end[2] - start[2] + direction = rt.TVector3(dx, dy, dz) + if direction.Mag() > 0: + direction = direction.Unit() + + track.add_direction(direction) + + print(f" Segment {i}: ({start[0]:.1f}, {start[1]:.1f}, {start[2]:.1f}) -> " + f"({end[0]:.1f}, {end[1]:.1f}, {end[2]:.1f})") + + return track + +def create_realistic_adc_images(): + """ + Create realistic ADC Image2D objects with proper MicroBooNE geometry + + Returns: + std::vector with U, V, Y plane images + """ + print("Creating realistic ADC images with MicroBooNE geometry...") + + # MicroBooNE detector parameters + tick_period = 0.5 # microseconds per tick + rows = 6048 # time ticks + + # Wire plane parameters + cols_u = 2400 # U plane wires + cols_v = 2400 # V plane wires + cols_y = 3456 # Y plane wires (collection plane) + + # Create image metadata + # ImageMeta(width, height, row_count, col_count, origin_x, origin_y, plane) + wire_pitch = 0.3 # cm + time_pitch = 0.5 # μs per tick + + width_u = cols_u * wire_pitch + width_v = cols_v * wire_pitch + width_y = cols_y * wire_pitch + height = rows * time_pitch + + meta_u = larcv.ImageMeta(width_u, height, rows, cols_u, 0.0, 0.0, 0) + meta_v = larcv.ImageMeta(width_v, height, rows, cols_v, 0.0, 0.0, 1) + meta_y = larcv.ImageMeta(width_y, height, rows, cols_y, 0.0, 0.0, 2) + + # Create empty images + img_u = larcv.Image2D(meta_u) + img_v = larcv.Image2D(meta_v) + img_y = larcv.Image2D(meta_y) + + # Fill with small baseline noise + for img in [img_u, img_v, img_y]: + img.paint(0.0) + # Add realistic noise + for row in range(0, rows, 50): # Sample every 50 ticks for speed + for col in range(0, img.meta().cols(), 20): # Sample every 20 wires + noise = np.random.normal(0, 2.0) # 2 ADC RMS noise + if noise > 0: + img.set_pixel(row, col, noise) + + print(f" U plane: {cols_u} wires x {rows} ticks") + print(f" V plane: {cols_v} wires x {rows} ticks") + print(f" Y plane: {cols_y} wires x {rows} ticks") + + # Package into vector + adc_images = std.vector('larcv::Image2D')() + adc_images.push_back(img_u) + adc_images.push_back(img_v) + adc_images.push_back(img_y) + + return adc_images + +def get_image_and_tracks_from_rootfile(rootfile): + """ + Get Image2D and track examples for testing TrackToSpacePoints + and the resulting photon prediction using ublarcvapp.ubphotonlib.PhotonVisibilityEstimator. + The test file is a merged file containing TTrees with larcv objects and + the reconstructed tracks. + """ + print(f"Loading data from {rootfile}") + + # Load larcv images + ioman = larcv.IOManager(larcv.IOManager.kREAD) + ioman.add_in_file(rootfile) + ioman.initialize() + + # Get the first entry + ioman.read_entry(0) + + ev_img = ioman.get_data(larcv.kProductImage2D, "wire") + imglist = [] + for p in range(3): + img = ev_img.as_vector().at(p) + imglist.append(img) + print(f" Plane {p}: {img.meta().cols()} x {img.meta().rows()} pixels") + + # Convert to std::vector for TrackToSpacePoints + adc_images = std.vector('larcv::Image2D')() + for img in imglist: + adc_images.push_back(img) + + # Get the opflash data + ioll = larlite.storage_manager(larlite.storage_manager.kREAD) + ioll.add_in_filename(rootfile) + ioll.open() + ioll.go_to(0) + + # Get opflash data using correct casting + ev_opflash = ioll.get_data(larlite.data.kOpFlash,"simpleFlashBeam") + opflashes = std.vector('larlite::opflash')() + + # Try to access the opflash data + print(f" Found {ev_opflash.size()} optical flashes") + for iopflash in range(ev_opflash.size()): + opflashes.push_back(ev_opflash.at(iopflash)) + + # Get the larlite::track examples from the reco file + reco_tfile = rt.TFile(rootfile, 'open') + recotree = reco_tfile.Get("KPSRecoManagerTree") + trackout_v = std.vector('larlite::track')() + + if not recotree: + print("Warning: Could not find KPSRecoManagerTree in file") + return adc_images, trackout_v, opflashes + + recotree.GetEntry(0) + + # Check if we have the expected structure + if not hasattr(recotree, 'nuvetoed_v') or recotree.nuvetoed_v.size() == 0: + print("Warning: No nuvetoed_v found in tree") + return adc_images, [] + + nuvtx = recotree.nuvetoed_v.at(0) + + print(f" Found {nuvtx.track_v.size()} tracks") + + + for itrack in range(nuvtx.track_v.size()): + track = nuvtx.track_v.at(itrack) + if track.NumberTrajectoryPoints()>=2: + trackout_v.push_back(track) + print(f" Track {itrack}: {track.NumberTrajectoryPoints()} points, length {track.Length():.1f} cm") + + ioman.finalize() + reco_tfile.Close() + + return adc_images, trackout_v, opflashes + +def add_track_charge_to_images(adc_images, track, charge_per_cm=1000.0): + """ + Add realistic charge deposits along a track path in the ADC images + + Args: + adc_images: Vector of larcv::Image2D objects + track: larlite::track object + charge_per_cm: Average charge deposition per cm of track + """ + print(f"Adding track charge deposits ({charge_per_cm} ADC/cm)...") + + # MicroBooNE parameters + drift_velocity = 0.1114 # cm/μs (at 273V/cm) + tick_period = 0.5 # μs/tick + x_offset = 3200 # ticks (approximate trigger offset) + + # Wire geometry (simplified - in reality would use larutil::Geometry) + wire_pitch = 0.3 # cm + + n_deposits = 0 + total_charge = 0 + + # Step along track and add charge + n_points = track.NumberTrajectoryPoints() + if n_points < 2: + return + + for i in range(n_points - 1): + start_pos = track.LocationAtPoint(i) + end_pos = track.LocationAtPoint(i + 1) + + # Calculate segment length + dx = end_pos.X() - start_pos.X() + dy = end_pos.Y() - start_pos.Y() + dz = end_pos.Z() - start_pos.Z() + segment_length = np.sqrt(dx*dx + dy*dy + dz*dz) + + if segment_length < 0.1: # Skip very short segments + continue + + # Number of charge deposits along this segment + n_steps = max(1, int(segment_length / 0.2)) # Every 2mm + + for step in range(n_steps): + t = float(step) / n_steps + x = start_pos.X() + t * dx + y = start_pos.Y() + t * dy + z = start_pos.Z() + t * dz + + # Convert 3D position to wire/tick coordinates + tick = x / drift_velocity / tick_period + x_offset + + # Simplified wire calculation (in reality would use proper geometry) + # U plane: 30° from vertical + # V plane: -30° from vertical + # Y plane: vertical (collection) + wire_u = int((y * np.cos(np.pi/6) + z * np.sin(np.pi/6)) / wire_pitch + 1200) + wire_v = int((-y * np.cos(np.pi/6) + z * np.sin(np.pi/6)) / wire_pitch + 1200) + wire_y = int(z / wire_pitch + 1700) + + row = int(tick) + + # Add charge if within image bounds + wires = [wire_u, wire_v, wire_y] + for plane in range(3): + img = adc_images[plane] + col = wires[plane] + + if (0 <= row < img.meta().rows() and + 0 <= col < img.meta().cols()): + + # Calculate charge for this step + step_length = segment_length / n_steps + base_charge = charge_per_cm * step_length + + # Add some fluctuation (Landau-like) + charge = np.random.gamma(2.0, base_charge/2.0) + + # Spread charge over neighboring pixels (diffusion effect) + for dr in range(-1, 2): + for dc in range(-2, 3): + r = row + dr + c = col + dc + if (0 <= r < img.meta().rows() and + 0 <= c < img.meta().cols()): + + # Gaussian spread + weight = np.exp(-(dr*dr + dc*dc) / 2.0) + pixel_charge = charge * weight * 0.1 # 10% of charge per pixel + + current_val = img.pixel(r, c) + img.set_pixel(r, c, current_val + pixel_charge) + + if plane == 2: # Count only Y plane for statistics + n_deposits += 1 + total_charge += pixel_charge + + print(f" Added {n_deposits} charge deposits") + print(f" Total charge: {total_charge:.0f} ADC counts") + +def convert_charge_to_photons(adc_charge): + """ + Convert ADC charge to number of scintillation photons + + Args: + adc_charge: Charge in ADC counts + + Returns: + Number of scintillation photons + """ + # LAr physics parameters (approximate) + adc_per_electron = 200.0 # ADC counts per electron + mev_per_electron = 23.6e-6 # Ionization energy in LAr (MeV) + photons_per_mev = 24000.0 # Scintillation photons per MeV at 500V/cm + recombination_factor = 0.7 # Fraction surviving recombination + + # Convert: ADC -> electrons -> energy -> photons + n_electrons = adc_charge / adc_per_electron + energy_mev = n_electrons * mev_per_electron + n_photons = energy_mev * photons_per_mev * (1.0 - recombination_factor) + + return n_photons + +def main(): + parser = argparse.ArgumentParser(description="Complete track to light estimation example") + parser.add_argument("--input-file", help="ROOT file with track/image data (optional)") + parser.add_argument("--save-output", action="store_true", help="Save output plots") + parser.add_argument("--charge-per-cm", type=float, default=2000.0, + help="Charge deposition per cm (ADC)") + args = parser.parse_args() + + print("Complete Track to Light Estimation Example") + print("="*60) + + opflashes = None # Initialize for synthetic data case + + if args.input_file: + # Use real data from ROOT file + print(f"\nUsing real data from: {args.input_file}") + adc_images, tracks, opflashes = get_image_and_tracks_from_rootfile(args.input_file) + + if len(tracks) == 0: + print("No tracks found in input file, exiting") + return + + # Use the first track for demonstration + track = tracks[0] + track_start = track.LocationAtPoint(0) + print(f"\nUsing track 0: {track.NumberTrajectoryPoints()} points, length {track.Length():.1f} cm") + print(f"Start: ({track_start.X():.1f}, {track_start.Y():.1f}, {track_start.Z():.1f})") + print(f"End: ({track.End().X():.1f}, {track.End().Y():.1f}, {track.End().Z():.1f})") + + # Show information about optical flashes + print(f"\nFound {len(opflashes)} optical flashes") + if len(opflashes) > 0: + flash = opflashes[0] # Use first flash for comparison + print(f"Using flash 0: Total PE = {flash.TotalPE():.1f}, Time = {flash.Time():.1f} μs") + + else: + # Use synthetic data + print("\nUsing synthetic data (use --input-file for real data)") + + # Define track as series of line segments + track_segments = [ + # Start outside detector, enter from top + ((10.0, 100.0, 200.0), (50.0, 80.0, 300.0)), # entering + ((50.0, 80.0, 300.0), (90.0, 50.0, 450.0)), # through detector + ((90.0, 50.0, 450.0), (130.0, 20.0, 600.0)), # continuing + ((130.0, 20.0, 600.0), (170.0, -10.0, 750.0)), # exiting + ] + + # Step 1: Create track from line segments + print("\n1. Creating track from line segments...") + track = create_track_from_segments(track_segments) + + print(f"Track created with {track.NumberTrajectoryPoints()} trajectory points") + print(f"Track length: {track.Length():.1f} cm") + + # Step 2: Create realistic ADC images + print("\n2. Creating ADC images...") + adc_images = create_realistic_adc_images() + + # Step 3: Add charge deposits along track + print("\n3. Adding charge deposits...") + add_track_charge_to_images(adc_images, track, args.charge_per_cm) + + # Convert track to space points + print("\nConverting track to space points...") + converter = ublarcvapp.pixelutils.TrackToSpacePoints() + converter.setUseChargeWeighting(False) + + spacepoints = converter.convertTrack( + track, adc_images, + threshold=10.0, # ADC threshold + dcol=3, # wire window + drow=3, # tick window + minstepsize=0.3, # min step (cm) + maxstepsize=0.5 # max step (cm) + ) + + print(f"Generated {len(spacepoints)} space points") + print(f"Pixels processed: {converter.getNumPixelsProcessed()}") + print(f"Total charge collected: {converter.getTotalCharge():.0f} ADC") + + # Convert to photon sources + print("\nConverting charge to photons...") + photon_estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + total_photons_added = 0 + for i, sp in enumerate(spacepoints): + if sp.charge > 5.0: # Only use points with significant charge + n_photons = convert_charge_to_photons(sp.charge) + + photon_estimator.addPhotonSource( + sp.position.X(), + sp.position.Y(), + sp.position.Z(), + n_photons + ) + total_photons_added += n_photons + + if i < 5: # Print first few + print(f" Point {i}: ({sp.position.X():.1f}, {sp.position.Y():.1f}, {sp.position.Z():.1f}) " + f"charge={sp.charge:.1f} -> {n_photons:.0f} photons") + + print(f"Added {photon_estimator.getNumSources()} photon sources") + print(f"Total emitted photons: {total_photons_added:.0f}") + + # Estimate light detection + print("\nEstimating light detection...") + + # Calculate with trilinear interpolation + photons_per_pmt = photon_estimator.calculateDetectedPhotons(use_trilinear=True) + total_detected = photon_estimator.getTotalDetectedPhotons(True) + efficiency = photon_estimator.getCollectionEfficiency(True) + + print(f"Total detected photons: {total_detected:.1f}") + print(f"Collection efficiency: {efficiency:.4f} ({efficiency*100:.2f}%)") + + # Show detection by PMT + print("\nPhotons detected by PMT:") + for pmt in range(32): + pe = photons_per_pmt[pmt] + if pe > 0.5: + print(f" PMT {pmt:2d}: {pe:7.1f} PE") + + # Create visualization + if args.save_output: + print("\nCreating visualization...") + + # PMT response histogram (predicted) + h_pmt_pred = rt.TH1F("h_pmt_pred", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred.SetBinContent(pmt+1, photons_per_pmt[pmt]) + + # PMT response histogram (observed) - only if we have opflash data + h_pmt_obs = None + if opflashes is not None and len(opflashes) > 0: + flash = opflashes[0] # Use first flash + h_pmt_obs = rt.TH1F("h_pmt_obs", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + + # Fill observed PMT response and normalize to 1 + total_obs_pe = 0 + pe_per_pmt = [] + for pmt in range(32): + pe = flash.PE(pmt) + pe_per_pmt.append(pe) + total_obs_pe += pe + + # Normalize observed data so total = 1 for shape comparison + if total_obs_pe > 0: + for pmt in range(32): + normalized_pe = pe_per_pmt[pmt] / total_obs_pe + h_pmt_obs.SetBinContent(pmt+1, normalized_pe) + + print(f"\nObserved flash: Total PE = {total_obs_pe:.1f}") + print("Observed PE per PMT (>0.1):") + for pmt in range(32): + if pe_per_pmt[pmt] > 0.1: + print(f" PMT {pmt:2d}: {pe_per_pmt[pmt]:6.1f} PE") + + # Normalize predicted data to 1 for shape comparison + if total_detected > 0: + for pmt in range(32): + normalized_pred = photons_per_pmt[pmt] / total_detected + h_pmt_pred.SetBinContent(pmt+1, normalized_pred) + + # Track 3D visualization + h_track_xz = rt.TH2F("h_track_xz", "Track Projection X-Z;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + h_track_yz = rt.TH2F("h_track_yz", "Track Projection Y-Z;Y [cm];Z [cm]", + 100, -50, 150, 100, 100, 800) + + # Fill track histograms + for i in range(track.NumberTrajectoryPoints()): + pos = track.LocationAtPoint(i) + h_track_xz.Fill(pos.X(), pos.Z()) + h_track_yz.Fill(pos.Y(), pos.Z()) + + # Space points with charge + h_charge_xz = rt.TH2F("h_charge_xz", "Space Points with Charge;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + for sp in spacepoints: + if sp.charge > 0: + h_charge_xz.Fill(sp.position.X(), sp.position.Z(), sp.charge) + + # Create canvas with space for comparison plot + canvas = rt.TCanvas("c1", "Track Light Estimation", 1600, 1000) + canvas.Divide(3, 3) + + canvas.cd(1) + h_track_xz.SetMarkerStyle(20) + h_track_xz.SetMarkerColor(rt.kBlue) + h_track_xz.Draw("P") + rt.gPad.SetTitle("Track Path (X-Z)") + + canvas.cd(2) + h_track_yz.SetMarkerStyle(20) + h_track_yz.SetMarkerColor(rt.kBlue) + h_track_yz.Draw("P") + rt.gPad.SetTitle("Track Path (Y-Z)") + + canvas.cd(3) + h_charge_xz.SetMarkerStyle(20) + h_charge_xz.SetMarkerColor(rt.kRed) + h_charge_xz.Draw("COLZ") + rt.gPad.SetTitle("Charge Deposits") + + # PMT comparison plot + canvas.cd(4) + h_pmt_pred.SetLineColor(rt.kRed) + h_pmt_pred.SetLineWidth(2) + h_pmt_pred.SetTitle("PMT Response Comparison;PMT ID;Normalized Response") + max_val = h_pmt_pred.GetMaximum() + + if h_pmt_obs is not None: + h_pmt_obs.SetLineColor(rt.kBlue) + h_pmt_obs.SetLineWidth(2) + max_val = max(max_val, h_pmt_obs.GetMaximum()) + h_pmt_pred.GetYaxis().SetRangeUser(0, max_val * 1.1) + h_pmt_pred.Draw("HIST") + h_pmt_obs.Draw("HIST SAME") + + # Add legend + legend = rt.TLegend(0.6, 0.7, 0.89, 0.89) + legend.AddEntry(h_pmt_pred, "Predicted", "l") + legend.AddEntry(h_pmt_obs, "Observed", "l") + legend.Draw() + else: + h_pmt_pred.SetFillColor(rt.kCyan-9) + h_pmt_pred.Draw("HIST") + + canvas.cd(5) + # Individual predicted PMT response (unnormalized) + h_pmt_pred_raw = rt.TH1F("h_pmt_pred_raw", "Predicted PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred_raw.SetBinContent(pmt+1, photons_per_pmt[pmt]) + h_pmt_pred_raw.SetFillColor(rt.kGreen-9) + h_pmt_pred_raw.Draw("HIST") + + canvas.cd(6) + if h_pmt_obs is not None: + # Individual observed PMT response (unnormalized) + h_pmt_obs_raw = rt.TH1F("h_pmt_obs_raw", "Observed PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_obs_raw.SetBinContent(pmt+1, pe_per_pmt[pmt]) + h_pmt_obs_raw.SetFillColor(rt.kYellow-9) + h_pmt_obs_raw.Draw("HIST") + + # Summary text + canvas.cd(7) + text = rt.TText() + text.SetTextSize(0.08) + text.DrawText(0.1, 0.9, f"Track Length: {track.Length():.1f} cm") + text.DrawText(0.1, 0.8, f"Space Points: {len(spacepoints)}") + text.DrawText(0.1, 0.7, f"Total Charge: {converter.getTotalCharge():.0f} ADC") + text.DrawText(0.1, 0.6, f"Emitted Photons: {total_photons_added:.0f}") + text.DrawText(0.1, 0.5, f"Detected Photons: {total_detected:.0f}") + text.DrawText(0.1, 0.4, f"Efficiency: {efficiency*100:.2f}%") + if opflashes is not None and len(opflashes) > 0: + text.DrawText(0.1, 0.3, f"Observed PE: {total_obs_pe:.0f}") + text.DrawText(0.1, 0.2, f"Flash Time: {flash.Time():.1f} us") + + canvas.SaveAs("complete_track_light_example.png") + print("Saved visualization to complete_track_light_example.png") + + print("\nExample completed successfully!") + +if __name__ == "__main__": + main() diff --git a/ublarcvapp/UBImageMod/PointImageProjection.cxx b/ublarcvapp/UBImageMod/PointImageProjection.cxx index 6fd8680..fe5afff 100644 --- a/ublarcvapp/UBImageMod/PointImageProjection.cxx +++ b/ublarcvapp/UBImageMod/PointImageProjection.cxx @@ -22,8 +22,15 @@ namespace ubimagemod { TVector3 worldLoc( xyz[0], xyz[1], xyz[2] ); //LARCV_NORMAL() << img.meta().dump() << std::endl; + UInt_t wireid = 0; + try { + wireid = larutil::Geometry::GetME()->NearestWire( worldLoc, img.meta().plane() ); + } + catch ( std::exception& e ) { + LARCV_WARNING() << e.what() << " - return 0.0" << std::endl; + return 0.0; + } - UInt_t wireid = larutil::Geometry::GetME()->NearestWire( worldLoc, img.meta().plane() ); if ( wireid < img.meta().min_x() ) { LARCV_NORMAL() << "Wire " << wireid << " below " << img.meta().min_x() << std::endl; return 0.0; From 793a823eb972b85365fca5578a0d61ec14d09c58 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 12 Jun 2025 12:21:02 -0400 Subject: [PATCH 67/80] added shower to optical detector converter --- .../ParticleToPixelUtils/CMakeLists.txt | 2 + ublarcvapp/ParticleToPixelUtils/LinkDef.h | 3 + .../ShowerToSpacePoints.cxx | 154 ++++++++ .../ShowerToSpacePoints.h | 122 ++++++ .../ParticleToPixelUtils/test/.gitignore | 1 + .../complete_track_light_example.py | 0 .../test/test_shower_light_example.py | 365 ++++++++++++++++++ 7 files changed, 647 insertions(+) create mode 100644 ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.cxx create mode 100644 ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.h create mode 100644 ublarcvapp/ParticleToPixelUtils/test/.gitignore rename ublarcvapp/ParticleToPixelUtils/{ => test}/complete_track_light_example.py (100%) create mode 100644 ublarcvapp/ParticleToPixelUtils/test/test_shower_light_example.py diff --git a/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt b/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt index 6ee3a2a..c17f6c3 100644 --- a/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt +++ b/ublarcvapp/ParticleToPixelUtils/CMakeLists.txt @@ -6,11 +6,13 @@ set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers set( HEADERS TrackToSpacePoints.h + ShowerToSpacePoints.h ) # Add sources add_library( ${LIBNAME} SHARED TrackToSpacePoints.cxx + ShowerToSpacePoints.cxx ) # larlite libraries diff --git a/ublarcvapp/ParticleToPixelUtils/LinkDef.h b/ublarcvapp/ParticleToPixelUtils/LinkDef.h index 2b3dd62..d7eb936 100644 --- a/ublarcvapp/ParticleToPixelUtils/LinkDef.h +++ b/ublarcvapp/ParticleToPixelUtils/LinkDef.h @@ -19,5 +19,8 @@ #pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints+; #pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints::SpacePointCharge+; #pragma link C++ class ublarcvapp::pixelutils::TrackToSpacePoints::PixelData+; +#pragma link C++ class ublarcvapp::pixelutils::ShowerToSpacePoints+; +#pragma link C++ class ublarcvapp::pixelutils::ShowerToSpacePoints::SpacePointCharge+; +#pragma link C++ class ublarcvapp::pixelutils::ShowerToSpacePoints::PixelData+; #endif \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.cxx b/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.cxx new file mode 100644 index 0000000..ba17301 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.cxx @@ -0,0 +1,154 @@ +#include "ShowerToSpacePoints.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include + +namespace ublarcvapp { +namespace pixelutils { + + ShowerToSpacePoints::ShowerToSpacePoints() + : _use_charge_weighting(false), + _npix_processed(0), + _total_charge(0.0) + { + } + + ShowerToSpacePoints::~ShowerToSpacePoints() + { + } + + std::vector + ShowerToSpacePoints::convertShower( + const larlite::larflowcluster& cluster, + const std::vector& adc_v, + const float threshold, + const int dcol, + const int drow) + { + std::vector spacepoints; + + // Reset counters + _npix_processed = 0; + _total_charge = 0.0; + _pixel_map.clear(); + + // Check we have 3 planes + if (adc_v.size() != 3) { + std::cerr << "ShowerToSpacePoints: Expected 3 planes, got " + << adc_v.size() << std::endl; + return spacepoints; + } + + // Get detector parameters + const float driftv = larutil::LArProperties::GetME()->DriftVelocity(); + const float usec_per_tick = 0.5; + float max_tick = adc_v.front().meta().max_y(); + float min_tick = adc_v.front().meta().min_y(); + + // Keep track of processed pixels to avoid double counting + std::set> processed_pixels; // (plane,row,col) + + // Process each larflow3dhit in the cluster + for (size_t ihit = 0; ihit < cluster.size(); ihit++) { + + const larlite::larflow3dhit& hit = cluster[ihit]; + + // Get 3D position from the larflow3dhit + // larflow3dhit inherits from std::vector which stores [x,y,z] + if (hit.size() < 3) { + std::cerr << "ShowerToSpacePoints: larflow3dhit " << ihit + << " has insufficient position data" << std::endl; + continue; + } + + TVector3 pos(hit[0], hit[1], hit[2]); // x,y,z stored in vector + + // Calculate tick from X position + float tick = hit[0]/driftv/usec_per_tick + 3200; + + if (tick < min_tick || tick > max_tick) + continue; + + int row = adc_v.front().meta().row(tick); + + // Collect charge from each wire plane + _pixel_map[ihit] = std::set(); + + for (int p = 0; p < 3; p++) { + int wire = larutil::Geometry::GetME()->WireCoordinate(pos, p); + + // Collect charge from neighboring pixels + for (int dr = -abs(drow); dr <= abs(drow); dr++) { + int r = row + dr; + if (r < 0 || r >= (int)adc_v[p].meta().rows()) + continue; + + for (int dc = -abs(dcol); dc <= abs(dcol); dc++) { + int c = wire + dc; + if (c < 0 || c >= (int)adc_v[p].meta().cols()) + continue; + + float pixval = adc_v[p].pixel(r, c); + if (pixval > threshold) { + // Check if we've already processed this pixel + auto pixel_key = std::make_tuple(p, r, c); + if (processed_pixels.find(pixel_key) == processed_pixels.end()) { + processed_pixels.insert(pixel_key); + _pixel_map[ihit].insert(PixelData(p, r, c, pixval)); + _npix_processed++; + _total_charge += pixval; + } + } + } + } + } + } + + // Now create space points from the collected pixel data + for (size_t ihit = 0; ihit < cluster.size(); ihit++) { + + // Skip hits with no associated pixels + if (_pixel_map.find(ihit) == _pixel_map.end() || _pixel_map[ihit].empty()) + continue; + + const larlite::larflow3dhit& hit = cluster[ihit]; + SpacePointCharge sp; + + // Use the original 3D position or charge-weighted position + // Get position from the std::vector base class + TVector3 original_pos(hit[0], hit[1], hit[2]); + + if (_use_charge_weighting && !_pixel_map[ihit].empty()) { + sp.position = getChargeWeightedPosition(_pixel_map[ihit], adc_v, original_pos); + } else { + sp.position = original_pos; + } + + // Calculate total charge and per-plane charges + sp.charge = 0; + sp.plane_charges.resize(3, 0); + + for (const auto& pix : _pixel_map[ihit]) { + sp.charge += pix.value; + sp.plane_charges[pix.plane] += pix.value; + } + + spacepoints.push_back(sp); + } + + return spacepoints; + } + + TVector3 ShowerToSpacePoints::getChargeWeightedPosition( + const std::set& pixels, + const std::vector& adc_v, + const TVector3& original_position) + { + // For now, just return the original position + // In the future, could implement charge-weighted averaging + // across the pixels to refine the position + return original_position; + } + +} +} \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.h b/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.h new file mode 100644 index 0000000..214c40f --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/ShowerToSpacePoints.h @@ -0,0 +1,122 @@ +#ifndef __UBLARCVAPP_PIXELUTILS_SHOWERTOSPACEPOINTS_H__ +#define __UBLARCVAPP_PIXELUTILS_SHOWERTOSPACEPOINTS_H__ + +#include +#include +#include + +#include "larcv/core/DataFormat/Image2D.h" +#include "larlite/DataFormat/larflowcluster.h" +#include "larlite/DataFormat/larflow3dhit.h" + +#include "TVector3.h" + +namespace ublarcvapp { +namespace pixelutils { + + /** + * @class ShowerToSpacePoints + * @brief Convert larlite::larflowcluster (shower representation) to space points with charge + * + * This class takes a larflowcluster which contains a collection of larflow3dhit objects + * (3D space points), projects them into the 2D wire plane images, and collects the + * charge from neighboring pixels. + */ + class ShowerToSpacePoints { + public: + + /** + * @struct SpacePointCharge + * @brief Container for 3D position with associated charge information + */ + struct SpacePointCharge { + TVector3 position; ///< 3D position in detector coordinates (cm) + float charge; ///< Total charge from neighboring pixels + std::vector plane_charges; ///< Charge on each plane [U,V,Y] + + SpacePointCharge() : charge(0) { plane_charges.resize(3, 0); } + }; + + /** + * @struct PixelData + * @brief Container for pixel location and charge + */ + struct PixelData { + int plane; + int row; + int col; + float value; + + PixelData() : plane(0), row(0), col(0), value(0) {} // Default constructor for ROOT + + PixelData(int p, int r, int c, float v) + : plane(p), row(r), col(c), value(v) {} + + // For std::set uniqueness + bool operator<(const PixelData& other) const { + if (plane != other.plane) return plane < other.plane; + if (row != other.row) return row < other.row; + return col < other.col; + } + }; + + ShowerToSpacePoints(); + ~ShowerToSpacePoints(); + + /** + * @brief Convert a larflowcluster (shower) to space points with charge + * + * @param cluster The larflowcluster containing larflow3dhit objects + * @param adc_v Vector of ADC images for each plane + * @param threshold ADC threshold for pixel selection + * @param dcol Column window around projected point + * @param drow Row window around projected point + * @return Vector of SpacePointCharge objects + */ + std::vector convertShower( + const larlite::larflowcluster& cluster, + const std::vector& adc_v, + const float threshold = 10.0, + const int dcol = 3, + const int drow = 3); + + /** + * @brief Get the number of pixels processed in the last conversion + */ + int getNumPixelsProcessed() const { return _npix_processed; } + + /** + * @brief Get the total charge collected in the last conversion + */ + float getTotalCharge() const { return _total_charge; } + + /** + * @brief Get the pixel data collected for each space point + * @return Map from space point index to set of pixels + */ + const std::map>& getPixelMap() const { return _pixel_map; } + + /** + * @brief Set whether to use charge-weighted position calculation + */ + void setUseChargeWeighting(bool use) { _use_charge_weighting = use; } + + protected: + + /** + * @brief Calculate charge-weighted position from pixel data + */ + TVector3 getChargeWeightedPosition(const std::set& pixels, + const std::vector& adc_v, + const TVector3& original_position); + + bool _use_charge_weighting; + int _npix_processed; + float _total_charge; + std::map> _pixel_map; ///< Map from hit index to pixels + }; + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/test/.gitignore b/ublarcvapp/ParticleToPixelUtils/test/.gitignore new file mode 100644 index 0000000..aab52d9 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/test/.gitignore @@ -0,0 +1 @@ +*.png \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py b/ublarcvapp/ParticleToPixelUtils/test/complete_track_light_example.py similarity index 100% rename from ublarcvapp/ParticleToPixelUtils/complete_track_light_example.py rename to ublarcvapp/ParticleToPixelUtils/test/complete_track_light_example.py diff --git a/ublarcvapp/ParticleToPixelUtils/test/test_shower_light_example.py b/ublarcvapp/ParticleToPixelUtils/test/test_shower_light_example.py new file mode 100644 index 0000000..ce7f747 --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/test/test_shower_light_example.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +""" +Complete example demonstrating the full workflow from shower to light detection estimation. + +This script shows: +1. How to create realistic larlite::shower objects from line segments +2. How to create realistic ADC images with proper geometry and charge deposits +3. How to use showerToSpacePoints to convert showers to space points with charge +4. How to convert charge to photons using LAr physics +5. How to use PhotonVisibilityEstimator to predict light detection + +Usage: + python3 complete_shower_light_example.py [--input-file file.root] [--save-output] +""" + +import ROOT as rt +from ROOT import std +import numpy as np +import argparse +import sys + +# Load libraries +from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp + + +def get_image_and_showers_from_rootfile(rootfile): + """ + Get Image2D and shower examples for testing showerToSpacePoints + and the resulting photon prediction using ublarcvapp.ubphotonlib.PhotonVisibilityEstimator. + The test file is a merged file containing TTrees with larcv objects and + the reconstructed showers. + """ + print(f"Loading data from {rootfile}") + + # Load larcv images + ioman = larcv.IOManager(larcv.IOManager.kREAD) + ioman.add_in_file(rootfile) + ioman.initialize() + + # Get the first entry + ioman.read_entry(0) + + ev_img = ioman.get_data(larcv.kProductImage2D, "wire") + imglist = [] + for p in range(3): + img = ev_img.as_vector().at(p) + imglist.append(img) + print(f" Plane {p}: {img.meta().cols()} x {img.meta().rows()} pixels") + + # Convert to std::vector for showerToSpacePoints + adc_images = std.vector('larcv::Image2D')() + for img in imglist: + adc_images.push_back(img) + + # Get the opflash data + ioll = larlite.storage_manager(larlite.storage_manager.kREAD) + ioll.add_in_filename(rootfile) + ioll.open() + ioll.go_to(0) + + # Get opflash data using correct casting + ev_opflash = ioll.get_data(larlite.data.kOpFlash,"simpleFlashBeam") + opflashes = std.vector('larlite::opflash')() + + # Try to access the opflash data + print(f" Found {ev_opflash.size()} optical flashes") + for iopflash in range(ev_opflash.size()): + opflashes.push_back(ev_opflash.at(iopflash)) + + # Get the larlite::shower examples from the reco file + reco_tfile = rt.TFile(rootfile, 'open') + recotree = reco_tfile.Get("KPSRecoManagerTree") + showerout_v = std.vector('larlite::larflowcluster')() + + if not recotree: + print("Warning: Could not find KPSRecoManagerTree in file") + return adc_images, showerout_v, opflashes + + recotree.GetEntry(0) + + # Check if we have the expected structure + if not hasattr(recotree, 'nuvetoed_v') or recotree.nuvetoed_v.size() == 0: + print("Warning: No nuvetoed_v found in tree") + return adc_images, [] + + nuvtx = recotree.nuvetoed_v.at(0) + + print(f" Found {nuvtx.shower_v.size()} showers") + + + for ishower in range(nuvtx.shower_v.size()): + shower = nuvtx.shower_v.at(ishower) + if shower.size()>=2: + showerout_v.push_back(shower) + print(f" Shower {ishower}: {shower.size()} points") + + ioman.finalize() + reco_tfile.Close() + + return adc_images, showerout_v, opflashes + + +def convert_charge_to_photons(adc_charge): + """ + Convert ADC charge to number of scintillation photons + + Args: + adc_charge: Charge in ADC counts + + Returns: + Number of scintillation photons + """ + # LAr physics parameters (approximate) + adc_per_electron = 200.0 # ADC counts per electron + mev_per_electron = 23.6e-6 # Ionization energy in LAr (MeV) + photons_per_mev = 24000.0 # Scintillation photons per MeV at 500V/cm + recombination_factor = 0.7 # Fraction surviving recombination + + # Convert: ADC -> electrons -> energy -> photons + n_electrons = adc_charge / adc_per_electron + energy_mev = n_electrons * mev_per_electron + n_photons = energy_mev * photons_per_mev * (1.0 - recombination_factor) + + return n_photons + +def main(): + parser = argparse.ArgumentParser(description="Complete shower to light estimation example") + parser.add_argument("--input-file", required=True, help="ROOT file with shower/image data (optional)") + parser.add_argument("--save-output", action="store_true", help="Save output plots") + parser.add_argument("--charge-per-cm", type=float, default=2000.0, + help="Charge deposition per cm (ADC)") + args = parser.parse_args() + + print("Complete Shower to Light Estimation Example") + print("="*60) + + opflashes = None # Initialize for synthetic data case + + + # Use real data from ROOT file + print(f"\nUsing real data from: {args.input_file}") + adc_images, showers, opflashes = get_image_and_showers_from_rootfile(args.input_file) + + if len(showers) == 0: + print("No showers found in input file, exiting") + return + + # Use the first shower for demonstration + shower = showers[0] + print(f"\nUsing shower 0: {shower.size()} points") + + # Show information about optical flashes + print(f"\nFound {len(opflashes)} optical flashes") + if len(opflashes) > 0: + flash = opflashes[0] # Use first flash for comparison + print(f"Using flash 0: Total PE = {flash.TotalPE():.1f}, Time = {flash.Time():.1f} μs") + + + # Convert shower to space points + print("\nConverting shower to space points...") + converter = ublarcvapp.pixelutils.ShowerToSpacePoints() + converter.setUseChargeWeighting(False) + + spacepoints = converter.convertShower( + shower, adc_images, + threshold=10.0, # ADC threshold + dcol=3, # wire window + drow=3 # tick window + ) + + print(f"Generated {len(spacepoints)} space points") + print(f"Pixels processed: {converter.getNumPixelsProcessed()}") + print(f"Total charge collected: {converter.getTotalCharge():.0f} ADC") + + # Convert to photon sources + print("\nConverting charge to photons...") + photon_estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + total_photons_added = 0 + for i, sp in enumerate(spacepoints): + if sp.charge > 5.0: # Only use points with significant charge + n_photons = convert_charge_to_photons(sp.charge) + + photon_estimator.addPhotonSource( + sp.position.X(), + sp.position.Y(), + sp.position.Z(), + n_photons + ) + total_photons_added += n_photons + + if i < 5: # Print first few + print(f" Point {i}: ({sp.position.X():.1f}, {sp.position.Y():.1f}, {sp.position.Z():.1f}) " + f"charge={sp.charge:.1f} -> {n_photons:.0f} photons") + + print(f"Added {photon_estimator.getNumSources()} photon sources") + print(f"Total emitted photons: {total_photons_added:.0f}") + + # Estimate light detection + print("\nEstimating light detection...") + + # Calculate with trilinear interpolation + photons_per_pmt = photon_estimator.calculateDetectedPhotons(use_trilinear=True) + total_detected = photon_estimator.getTotalDetectedPhotons(True) + efficiency = photon_estimator.getCollectionEfficiency(True) + + print(f"Total detected photons: {total_detected:.1f}") + print(f"Collection efficiency: {efficiency:.4f} ({efficiency*100:.2f}%)") + + # Show detection by PMT + print("\nPhotons detected by PMT:") + for pmt in range(32): + pe = photons_per_pmt[pmt] + if pe > 0.5: + print(f" PMT {pmt:2d}: {pe:7.1f} PE") + + # Create visualization + if args.save_output: + print("\nCreating visualization...") + + # PMT response histogram (predicted) + h_pmt_pred = rt.TH1F("h_pmt_pred", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred.SetBinContent(pmt+1, photons_per_pmt[pmt]) + + # PMT response histogram (observed) - only if we have opflash data + h_pmt_obs = None + if opflashes is not None and len(opflashes) > 0: + flash = opflashes[0] # Use first flash + h_pmt_obs = rt.TH1F("h_pmt_obs", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + + # Fill observed PMT response and normalize to 1 + total_obs_pe = 0 + pe_per_pmt = [] + for pmt in range(32): + pe = flash.PE(pmt) + pe_per_pmt.append(pe) + total_obs_pe += pe + + # Normalize observed data so total = 1 for shape comparison + if total_obs_pe > 0: + for pmt in range(32): + normalized_pe = pe_per_pmt[pmt] / total_obs_pe + h_pmt_obs.SetBinContent(pmt+1, normalized_pe) + + print(f"\nObserved flash: Total PE = {total_obs_pe:.1f}") + print("Observed PE per PMT (>0.1):") + for pmt in range(32): + if pe_per_pmt[pmt] > 0.1: + print(f" PMT {pmt:2d}: {pe_per_pmt[pmt]:6.1f} PE") + + # Normalize predicted data to 1 for shape comparison + if total_detected > 0: + for pmt in range(32): + normalized_pred = photons_per_pmt[pmt] / total_detected + h_pmt_pred.SetBinContent(pmt+1, normalized_pred) + + # shower 3D visualization + h_shower_xz = rt.TH2F("h_shower_xz", "shower Projection X-Z;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + h_shower_yz = rt.TH2F("h_shower_yz", "shower Projection Y-Z;Y [cm];Z [cm]", + 100, -50, 150, 100, 100, 800) + + # Fill shower histograms + for i in range(shower.size()): + hit = shower.at(i) + h_shower_xz.Fill(hit[0],hit[2]) + h_shower_yz.Fill(hit[1],hit[2]) + + # Space points with charge + h_charge_xz = rt.TH2F("h_charge_xz", "Space Points with Charge;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + for sp in spacepoints: + if sp.charge > 0: + h_charge_xz.Fill(sp.position.X(), sp.position.Z(), sp.charge) + + # Create canvas with space for comparison plot + canvas = rt.TCanvas("c1", "shower Light Estimation", 1600, 1000) + canvas.Divide(3, 3) + + canvas.cd(1) + h_shower_xz.SetMarkerStyle(20) + h_shower_xz.SetMarkerColor(rt.kBlue) + h_shower_xz.Draw("P") + rt.gPad.SetTitle("shower Path (X-Z)") + + canvas.cd(2) + h_shower_yz.SetMarkerStyle(20) + h_shower_yz.SetMarkerColor(rt.kBlue) + h_shower_yz.Draw("P") + rt.gPad.SetTitle("shower Path (Y-Z)") + + canvas.cd(3) + h_charge_xz.SetMarkerStyle(20) + h_charge_xz.SetMarkerColor(rt.kRed) + h_charge_xz.Draw("COLZ") + rt.gPad.SetTitle("Charge Deposits") + + # PMT comparison plot + canvas.cd(4) + h_pmt_pred.SetLineColor(rt.kRed) + h_pmt_pred.SetLineWidth(2) + h_pmt_pred.SetTitle("PMT Response Comparison;PMT ID;Normalized Response") + max_val = h_pmt_pred.GetMaximum() + + if h_pmt_obs is not None: + h_pmt_obs.SetLineColor(rt.kBlue) + h_pmt_obs.SetLineWidth(2) + max_val = max(max_val, h_pmt_obs.GetMaximum()) + h_pmt_pred.GetYaxis().SetRangeUser(0, max_val * 1.1) + h_pmt_pred.Draw("HIST") + h_pmt_obs.Draw("HIST SAME") + + # Add legend + legend = rt.TLegend(0.6, 0.7, 0.89, 0.89) + legend.AddEntry(h_pmt_pred, "Predicted", "l") + legend.AddEntry(h_pmt_obs, "Observed", "l") + legend.Draw() + else: + h_pmt_pred.SetFillColor(rt.kCyan-9) + h_pmt_pred.Draw("HIST") + + canvas.cd(5) + # Individual predicted PMT response (unnormalized) + h_pmt_pred_raw = rt.TH1F("h_pmt_pred_raw", "Predicted PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred_raw.SetBinContent(pmt+1, photons_per_pmt[pmt]) + h_pmt_pred_raw.SetFillColor(rt.kGreen-9) + h_pmt_pred_raw.Draw("HIST") + + canvas.cd(6) + if h_pmt_obs is not None: + # Individual observed PMT response (unnormalized) + h_pmt_obs_raw = rt.TH1F("h_pmt_obs_raw", "Observed PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_obs_raw.SetBinContent(pmt+1, pe_per_pmt[pmt]) + h_pmt_obs_raw.SetFillColor(rt.kYellow-9) + h_pmt_obs_raw.Draw("HIST") + + # Summary text + canvas.cd(7) + text = rt.TText() + text.SetTextSize(0.08) + text.DrawText(0.1, 0.8, f"Space Points: {len(spacepoints)}") + text.DrawText(0.1, 0.7, f"Total Charge: {converter.getTotalCharge():.0f} ADC") + text.DrawText(0.1, 0.6, f"Emitted Photons: {total_photons_added:.0f}") + text.DrawText(0.1, 0.5, f"Detected Photons: {total_detected:.0f}") + text.DrawText(0.1, 0.4, f"Efficiency: {efficiency*100:.2f}%") + if opflashes is not None and len(opflashes) > 0: + text.DrawText(0.1, 0.3, f"Observed PE: {total_obs_pe:.0f}") + text.DrawText(0.1, 0.2, f"Flash Time: {flash.Time():.1f} us") + + canvas.SaveAs("complete_shower_light_example.png") + print("Saved visualization to complete_shower_light_example.png") + + print("\nExample completed successfully!") + +if __name__ == "__main__": + main() From 8e492b59701145dad0854212182fcc8e4db1b34d Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 12 Jun 2025 14:00:28 -0400 Subject: [PATCH 68/80] save examples --- .../test/test_shower_simple.py | 77 ++++ .../test/test_track_light_example.py | 370 ++++++++++++++++++ 2 files changed, 447 insertions(+) create mode 100644 ublarcvapp/ParticleToPixelUtils/test/test_shower_simple.py create mode 100644 ublarcvapp/ParticleToPixelUtils/test/test_track_light_example.py diff --git a/ublarcvapp/ParticleToPixelUtils/test/test_shower_simple.py b/ublarcvapp/ParticleToPixelUtils/test/test_shower_simple.py new file mode 100644 index 0000000..35f430a --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/test/test_shower_simple.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +""" +Simple test for ShowerToSpacePoints without photon library +""" + +import ROOT as rt +from ROOT import std +from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp +import numpy as np + +# Create synthetic shower +print("Creating synthetic shower...") +cluster = larlite.larflowcluster() + +# Create 10 hits in a shower pattern +for i in range(10): + hit = larlite.larflow3dhit() + hit.clear() + + # Simple positions + x = 70.0 + np.random.normal(0, 2) + y = 0.0 + np.random.normal(0, 5) + z = 500.0 + np.random.uniform(0, 20) + + hit.push_back(float(x)) + hit.push_back(float(y)) + hit.push_back(float(z)) + + cluster.push_back(hit) + print(f" Hit {i}: ({x:.1f}, {y:.1f}, {z:.1f})") + +print(f"\nCreated cluster with {cluster.size()} hits") + +# Create simple ADC images +print("\nCreating ADC images...") +rows = 2048 +cols = 3456 + +# Simple metadata +meta = larcv.ImageMeta(cols, rows, rows, cols, 0, 3000, 0) +img = larcv.Image2D(meta) +img.paint(0) + +# Add some charge at expected locations +for row in range(1000, 1500, 10): + for col in range(1500, 2000, 10): + img.set_pixel(row, col, 50.0) + +adc_images = std.vector('larcv::Image2D')() +adc_images.push_back(img) +adc_images.push_back(img) +adc_images.push_back(img) + +# Test ShowerToSpacePoints +print("\nTesting ShowerToSpacePoints...") +converter = ublarcvapp.pixelutils.ShowerToSpacePoints() + +spacepoints = converter.convertShower(cluster, adc_images, 10.0, 5, 5) + +print(f"\nResults:") +print(f" Space points found: {len(spacepoints)}") +print(f" Pixels processed: {converter.getNumPixelsProcessed()}") +print(f" Total charge: {converter.getTotalCharge():.1f}") + +if len(spacepoints) > 0: + print("\nFirst few space points:") + for i, sp in enumerate(spacepoints[:3]): + print(f" SP {i}: pos=({sp.position.X():.1f}, {sp.position.Y():.1f}, {sp.position.Z():.1f}) charge={sp.charge:.1f}") +else: + print("\nNo space points found - this may be due to:") + print(" - Mismatch between hit positions and charge deposit locations") + print(" - Tick/wire conversion issues") + print(" - Threshold too high") + +print("\nShowerToSpacePoints class is working!") \ No newline at end of file diff --git a/ublarcvapp/ParticleToPixelUtils/test/test_track_light_example.py b/ublarcvapp/ParticleToPixelUtils/test/test_track_light_example.py new file mode 100644 index 0000000..340f19c --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/test/test_track_light_example.py @@ -0,0 +1,370 @@ +#!/usr/bin/env python3 +""" +Complete example demonstrating the full workflow from track to light detection estimation. + +This script shows: +1. How to create realistic larlite::track objects from line segments +2. How to create realistic ADC images with proper geometry and charge deposits +3. How to use TrackToSpacePoints to convert tracks to space points with charge +4. How to convert charge to photons using LAr physics +5. How to use PhotonVisibilityEstimator to predict light detection + +Usage: + python3 complete_track_light_example.py [--input-file file.root] [--save-output] +""" + +import ROOT as rt +from ROOT import std +import numpy as np +import argparse +import sys + +# Load libraries +from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp + +def get_image_and_tracks_from_rootfile(rootfile): + """ + Get Image2D and track examples for testing TrackToSpacePoints + and the resulting photon prediction using ublarcvapp.ubphotonlib.PhotonVisibilityEstimator. + The test file is a merged file containing TTrees with larcv objects and + the reconstructed tracks. + """ + print(f"Loading data from {rootfile}") + + # Load larcv images + ioman = larcv.IOManager(larcv.IOManager.kREAD) + ioman.add_in_file(rootfile) + ioman.initialize() + + # Get the first entry + ioman.read_entry(0) + + ev_img = ioman.get_data(larcv.kProductImage2D, "wire") + imglist = [] + for p in range(3): + img = ev_img.as_vector().at(p) + imglist.append(img) + print(f" Plane {p}: {img.meta().cols()} x {img.meta().rows()} pixels") + + # Convert to std::vector for TrackToSpacePoints + adc_images = std.vector('larcv::Image2D')() + for img in imglist: + adc_images.push_back(img) + + # Get the opflash data + ioll = larlite.storage_manager(larlite.storage_manager.kREAD) + ioll.add_in_filename(rootfile) + ioll.open() + ioll.go_to(0) + + # Get opflash data using correct casting + ev_opflash = ioll.get_data(larlite.data.kOpFlash,"simpleFlashBeam") + opflashes = std.vector('larlite::opflash')() + + # Try to access the opflash data + print(f" Found {ev_opflash.size()} optical flashes") + for iopflash in range(ev_opflash.size()): + opflashes.push_back(ev_opflash.at(iopflash)) + + # Get the larlite::track examples from the reco file + reco_tfile = rt.TFile(rootfile, 'open') + recotree = reco_tfile.Get("KPSRecoManagerTree") + trackout_v = std.vector('larlite::track')() + + if not recotree: + print("Warning: Could not find KPSRecoManagerTree in file") + return adc_images, trackout_v, opflashes + + recotree.GetEntry(0) + + # Check if we have the expected structure + if not hasattr(recotree, 'nuvetoed_v') or recotree.nuvetoed_v.size() == 0: + print("Warning: No nuvetoed_v found in tree") + return adc_images, [] + + nuvtx = recotree.nuvetoed_v.at(0) + + print(f" Found {nuvtx.track_v.size()} tracks") + + + for itrack in range(nuvtx.track_v.size()): + track = nuvtx.track_v.at(itrack) + if track.NumberTrajectoryPoints()>=2: + trackout_v.push_back(track) + print(f" Track {itrack}: {track.NumberTrajectoryPoints()} points, length {track.Length():.1f} cm") + + ioman.finalize() + reco_tfile.Close() + + return adc_images, trackout_v, opflashes + + +def convert_charge_to_photons(adc_charge): + """ + Convert ADC charge to number of scintillation photons + + Args: + adc_charge: Charge in ADC counts + + Returns: + Number of scintillation photons + """ + # LAr physics parameters (approximate) + adc_per_electron = 200.0 # ADC counts per electron + mev_per_electron = 23.6e-6 # Ionization energy in LAr (MeV) + photons_per_mev = 24000.0 # Scintillation photons per MeV at 500V/cm + recombination_factor = 0.7 # Fraction surviving recombination + + # Convert: ADC -> electrons -> energy -> photons + n_electrons = adc_charge / adc_per_electron + energy_mev = n_electrons * mev_per_electron + n_photons = energy_mev * photons_per_mev * (1.0 - recombination_factor) + + return n_photons + +def main(): + parser = argparse.ArgumentParser(description="Complete track to light estimation example") + parser.add_argument("--input-file", required=True, help="ROOT file with track/image data (optional)") + parser.add_argument("--save-output", action="store_true", help="Save output plots") + parser.add_argument("--charge-per-cm", type=float, default=2000.0, + help="Charge deposition per cm (ADC)") + args = parser.parse_args() + + print("Complete Track to Light Estimation Example") + print("="*60) + + opflashes = None # Initialize for synthetic data case + + # Use real data from ROOT file + print(f"\nUsing real data from: {args.input_file}") + adc_images, tracks, opflashes = get_image_and_tracks_from_rootfile(args.input_file) + + if len(tracks) == 0: + print("No tracks found in input file, exiting") + return + + # Use the first track for demonstration + track = tracks[0] + track_start = track.LocationAtPoint(0) + print(f"\nUsing track 0: {track.NumberTrajectoryPoints()} points, length {track.Length():.1f} cm") + print(f"Start: ({track_start.X():.1f}, {track_start.Y():.1f}, {track_start.Z():.1f})") + print(f"End: ({track.End().X():.1f}, {track.End().Y():.1f}, {track.End().Z():.1f})") + + # Show information about optical flashes + print(f"\nFound {len(opflashes)} optical flashes") + if len(opflashes) > 0: + flash = opflashes[0] # Use first flash for comparison + print(f"Using flash 0: Total PE = {flash.TotalPE():.1f}, Time = {flash.Time():.1f} μs") + else: + flash = None + + # Convert track to space points + print("\nConverting track to space points...") + converter = ublarcvapp.pixelutils.TrackToSpacePoints() + converter.setUseChargeWeighting(False) + + spacepoints = converter.convertTrack( + track, adc_images, + threshold=10.0, # ADC threshold + dcol=3, # wire window + drow=3, # tick window + minstepsize=0.3, # min step (cm) + maxstepsize=0.5 # max step (cm) + ) + + print(f"Generated {len(spacepoints)} space points") + print(f"Pixels processed: {converter.getNumPixelsProcessed()}") + print(f"Total charge collected: {converter.getTotalCharge():.0f} ADC") + + # Convert to photon sources + print("\nConverting charge to photons...") + photon_estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + total_photons_added = 0 + for i, sp in enumerate(spacepoints): + if sp.charge > 5.0: # Only use points with significant charge + n_photons = convert_charge_to_photons(sp.charge) + + photon_estimator.addPhotonSource( + sp.position.X(), + sp.position.Y(), + sp.position.Z(), + n_photons + ) + total_photons_added += n_photons + + if i < 5: # Print first few + print(f" Point {i}: ({sp.position.X():.1f}, {sp.position.Y():.1f}, {sp.position.Z():.1f}) " + f"charge={sp.charge:.1f} -> {n_photons:.0f} photons") + + print(f"Added {photon_estimator.getNumSources()} photon sources") + print(f"Total emitted photons: {total_photons_added:.0f}") + + # Estimate light detection + print("\nEstimating light detection...") + + # Calculate with trilinear interpolation + photons_per_pmt = photon_estimator.calculateDetectedPhotons(use_trilinear=True) + total_detected = photon_estimator.getTotalDetectedPhotons(True) + efficiency = photon_estimator.getCollectionEfficiency(True) + + print(f"Total detected photons: {total_detected:.1f}") + print(f"Collection efficiency: {efficiency:.4f} ({efficiency*100:.2f}%)") + + # Show detection by PMT + print("\nPhotons detected by PMT:") + for pmt in range(32): + pe = photons_per_pmt[pmt] + if pe > 0.5: + print(f" PMT {pmt:2d}: {pe:7.1f} PE") + + # Create visualization + if args.save_output: + print("\nCreating visualization...") + + # PMT response histogram (predicted) + h_pmt_pred = rt.TH1F("h_pmt_pred", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred.SetBinContent(pmt+1, photons_per_pmt[pmt]) + + # PMT response histogram (observed) - only if we have opflash data + h_pmt_obs = None + if opflashes is not None and len(opflashes) > 0: + flash = opflashes[0] # Use first flash + h_pmt_obs = rt.TH1F("h_pmt_obs", "PMT Light Response;PMT ID;Normalized Response", + 32, 0, 32) + + # Fill observed PMT response and normalize to 1 + total_obs_pe = 0 + pe_per_pmt = [] + for pmt in range(32): + pe = flash.PE(pmt) + pe_per_pmt.append(pe) + total_obs_pe += pe + + # Normalize observed data so total = 1 for shape comparison + if total_obs_pe > 0: + for pmt in range(32): + normalized_pe = pe_per_pmt[pmt] / total_obs_pe + h_pmt_obs.SetBinContent(pmt+1, normalized_pe) + + print(f"\nObserved flash: Total PE = {total_obs_pe:.1f}") + print("Observed PE per PMT (>0.1):") + for pmt in range(32): + if pe_per_pmt[pmt] > 0.1: + print(f" PMT {pmt:2d}: {pe_per_pmt[pmt]:6.1f} PE") + + # Normalize predicted data to 1 for shape comparison + if total_detected > 0: + for pmt in range(32): + normalized_pred = photons_per_pmt[pmt] / total_detected + h_pmt_pred.SetBinContent(pmt+1, normalized_pred) + + # Track 3D visualization + h_track_xz = rt.TH2F("h_track_xz", "Track Projection X-Z;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + h_track_yz = rt.TH2F("h_track_yz", "Track Projection Y-Z;Y [cm];Z [cm]", + 100, -50, 150, 100, 100, 800) + + # Fill track histograms + for i in range(track.NumberTrajectoryPoints()): + pos = track.LocationAtPoint(i) + h_track_xz.Fill(pos.X(), pos.Z()) + h_track_yz.Fill(pos.Y(), pos.Z()) + + # Space points with charge + h_charge_xz = rt.TH2F("h_charge_xz", "Space Points with Charge;X [cm];Z [cm]", + 100, 0, 200, 100, 100, 800) + for sp in spacepoints: + if sp.charge > 0: + h_charge_xz.Fill(sp.position.X(), sp.position.Z(), sp.charge) + + # Create canvas with space for comparison plot + canvas = rt.TCanvas("c1", "Track Light Estimation", 1600, 1000) + canvas.Divide(3, 3) + + canvas.cd(1) + h_track_xz.SetMarkerStyle(20) + h_track_xz.SetMarkerColor(rt.kBlue) + h_track_xz.Draw("P") + rt.gPad.SetTitle("Track Path (X-Z)") + + canvas.cd(2) + h_track_yz.SetMarkerStyle(20) + h_track_yz.SetMarkerColor(rt.kBlue) + h_track_yz.Draw("P") + rt.gPad.SetTitle("Track Path (Y-Z)") + + canvas.cd(3) + h_charge_xz.SetMarkerStyle(20) + h_charge_xz.SetMarkerColor(rt.kRed) + h_charge_xz.Draw("COLZ") + rt.gPad.SetTitle("Charge Deposits") + + # PMT comparison plot + canvas.cd(4) + h_pmt_pred.SetLineColor(rt.kRed) + h_pmt_pred.SetLineWidth(2) + h_pmt_pred.SetTitle("PMT Response Comparison;PMT ID;Normalized Response") + max_val = h_pmt_pred.GetMaximum() + + if h_pmt_obs is not None: + h_pmt_obs.SetLineColor(rt.kBlue) + h_pmt_obs.SetLineWidth(2) + max_val = max(max_val, h_pmt_obs.GetMaximum()) + h_pmt_pred.GetYaxis().SetRangeUser(0, max_val * 1.1) + h_pmt_pred.Draw("HIST") + h_pmt_obs.Draw("HIST SAME") + + # Add legend + legend = rt.TLegend(0.6, 0.7, 0.89, 0.89) + legend.AddEntry(h_pmt_pred, "Predicted", "l") + legend.AddEntry(h_pmt_obs, "Observed", "l") + legend.Draw() + else: + h_pmt_pred.SetFillColor(rt.kCyan-9) + h_pmt_pred.Draw("HIST") + + canvas.cd(5) + # Individual predicted PMT response (unnormalized) + h_pmt_pred_raw = rt.TH1F("h_pmt_pred_raw", "Predicted PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_pred_raw.SetBinContent(pmt+1, photons_per_pmt[pmt]) + h_pmt_pred_raw.SetFillColor(rt.kGreen-9) + h_pmt_pred_raw.Draw("HIST") + + canvas.cd(6) + if h_pmt_obs is not None: + # Individual observed PMT response (unnormalized) + h_pmt_obs_raw = rt.TH1F("h_pmt_obs_raw", "Observed PMT Response;PMT ID;Photoelectrons", + 32, 0, 32) + for pmt in range(32): + h_pmt_obs_raw.SetBinContent(pmt+1, pe_per_pmt[pmt]) + h_pmt_obs_raw.SetFillColor(rt.kYellow-9) + h_pmt_obs_raw.Draw("HIST") + + # Summary text + canvas.cd(7) + text = rt.TText() + text.SetTextSize(0.08) + text.DrawText(0.1, 0.9, f"Track Length: {track.Length():.1f} cm") + text.DrawText(0.1, 0.8, f"Space Points: {len(spacepoints)}") + text.DrawText(0.1, 0.7, f"Total Charge: {converter.getTotalCharge():.0f} ADC") + text.DrawText(0.1, 0.6, f"Emitted Photons: {total_photons_added:.0f}") + text.DrawText(0.1, 0.5, f"Detected Photons: {total_detected:.0f}") + text.DrawText(0.1, 0.4, f"Efficiency: {efficiency*100:.2f}%") + if opflashes is not None and len(opflashes) > 0: + text.DrawText(0.1, 0.3, f"Observed PE: {total_obs_pe:.0f}") + text.DrawText(0.1, 0.2, f"Flash Time: {flash.Time():.1f} us") + + canvas.SaveAs("complete_track_light_example.png") + print("Saved visualization to complete_track_light_example.png") + + print("\nExample completed successfully!") + +if __name__ == "__main__": + main() From 3614db7f594d7bc1143236f22dc868654aa7991a Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 12 Jun 2025 17:39:14 -0400 Subject: [PATCH 69/80] example script that processes all track and showers in order to make an intime prediction --- .../test/test_nucand_light_example.py | 471 ++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100644 ublarcvapp/ParticleToPixelUtils/test/test_nucand_light_example.py diff --git a/ublarcvapp/ParticleToPixelUtils/test/test_nucand_light_example.py b/ublarcvapp/ParticleToPixelUtils/test/test_nucand_light_example.py new file mode 100644 index 0000000..6a4cbed --- /dev/null +++ b/ublarcvapp/ParticleToPixelUtils/test/test_nucand_light_example.py @@ -0,0 +1,471 @@ +#!/usr/bin/env python3 +""" +Complete example demonstrating the full workflow from shower to light detection estimation. + +This script shows: +1. How to create realistic larlite::shower objects from line segments +2. How to create realistic ADC images with proper geometry and charge deposits +3. How to use showerToSpacePoints to convert showers to space points with charge +4. How to convert charge to photons using LAr physics +5. How to use PhotonVisibilityEstimator to predict light detection + +Usage: + python3 complete_shower_light_example.py [--input-file file.root] [--save-output] +""" + +import ROOT as rt +from ROOT import std +import numpy as np +import argparse +import sys +rt.gStyle.SetOptStat(0) + +# Load libraries +from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp + + +def get_data_from_rootfile(rootfile): + """ + Get Image2D and shower examples for testing showerToSpacePoints + and the resulting photon prediction using ublarcvapp.ubphotonlib.PhotonVisibilityEstimator. + The test file is a merged file containing TTrees with larcv objects and + the reconstructed showers. + """ + print(f"Loading data from {rootfile}") + + # Load larcv images + ioman = larcv.IOManager(larcv.IOManager.kREAD) + ioman.add_in_file(rootfile) + ioman.initialize() + + # Get the first entry + ioman.read_entry(0) + + ev_img = ioman.get_data(larcv.kProductImage2D, "wire") + imglist = [] + for p in range(3): + img = ev_img.as_vector().at(p) + imglist.append(img) + print(f" Plane {p}: {img.meta().cols()} x {img.meta().rows()} pixels") + + # Convert to std::vector for showerToSpacePoints + adc_images = std.vector('larcv::Image2D')() + for img in imglist: + adc_images.push_back(img) + + # Get the opflash data + ioll = larlite.storage_manager(larlite.storage_manager.kREAD) + ioll.add_in_filename(rootfile) + ioll.open() + ioll.go_to(0) + + # Get opflash data using correct casting + ev_opflash = ioll.get_data(larlite.data.kOpFlash,"simpleFlashBeam") + opflashes = std.vector('larlite::opflash')() + + # Try to access the opflash data + print(f" Found {ev_opflash.size()} optical flashes") + for iopflash in range(ev_opflash.size()): + opflashes.push_back(ev_opflash.at(iopflash)) + + # Get the larlite::shower examples from the reco file + reco_tfile = rt.TFile(rootfile, 'open') + recotree = reco_tfile.Get("KPSRecoManagerTree") + trackout_v = std.vector('larlite::track')() + showerout_v = std.vector('larlite::larflowcluster')() + + if not recotree: + print("Warning: Could not find KPSRecoManagerTree in file") + return adc_images, showerout_v, opflashes + + recotree.GetEntry(0) + + # Check if we have the expected structure + if not hasattr(recotree, 'nuvetoed_v') or recotree.nuvetoed_v.size() == 0: + print("Warning: No nuvetoed_v found in tree") + return adc_images, [] + + nuvtx = recotree.nuvetoed_v.at(0) + + print(f" Found {nuvtx.shower_v.size()} showers") + + # Get showers + for ishower in range(nuvtx.shower_v.size()): + shower = nuvtx.shower_v.at(ishower) + if shower.size()>=2: + showerout_v.push_back(shower) + print(f" Shower {ishower}: {shower.size()} points") + + # Get track + for itrack in range(nuvtx.track_v.size()): + track = nuvtx.track_v.at(itrack) + if track.NumberTrajectoryPoints()>=2: + trackout_v.push_back(track) + print(f" Track {itrack}: {track.NumberTrajectoryPoints()} points, length {track.Length():.1f} cm") + + ioman.finalize() + reco_tfile.Close() + + return adc_images, trackout_v, showerout_v, opflashes + + +def convert_charge_to_photons(adc_charge): + """ + Convert ADC charge to number of scintillation photons + + Args: + adc_charge: Charge in ADC counts + + Returns: + Number of scintillation photons + """ + # LAr physics parameters (approximate) + adc_per_electron = 200.0 # ADC counts per electron + mev_per_electron = 23.6e-6 # Ionization energy in LAr (MeV) + photons_per_mev = 24000.0 # Scintillation photons per MeV at 500V/cm + recombination_factor = 0.7 # Fraction surviving recombination + + # Convert: ADC -> electrons -> energy -> photons + n_electrons = adc_charge / adc_per_electron + energy_mev = n_electrons * mev_per_electron + n_photons = energy_mev * photons_per_mev * (1.0 - recombination_factor) + + return n_photons + +def get_shower_opdet_predicts( showers, adc_images ): + + # Loop over shower container + total_photons_added = 0 + shower_predictions = [] + for ishower in range( showers.size() ): + shower = showers.at(ishower) + + # make a spacepoint converter for this shower + converter = ublarcvapp.pixelutils.ShowerToSpacePoints() + converter.setUseChargeWeighting(False) + spacepoints = converter.convertShower( + shower, adc_images, + threshold=10.0, # ADC threshold + dcol=3, # wire window + drow=3 # tick window + ) + + # Make photon estimator + photon_estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + for i, sp in enumerate(spacepoints): + if sp.charge > 5.0: # Only use points with significant charge + n_photons = convert_charge_to_photons(sp.charge) + + photon_estimator.addPhotonSource( + sp.position.X(), + sp.position.Y(), + sp.position.Z(), + n_photons + ) + total_photons_added += n_photons + print(f"shower[{ishower}] num photons predicted = {n_photons}") + photons_per_pmt = photon_estimator.calculateDetectedPhotons(use_trilinear=True) + shower_predictions.append( photons_per_pmt ) + + print(f'Number of total photons: {total_photons_added}') + + return shower_predictions + +def get_track_opdet_predicts( tracks, adc_images ): + + # Loop over track container + total_photons_added = 0 + track_predictions = [] + for itrack in range( tracks.size() ): + track = tracks.at(itrack) + + # make a spacepoint converter for this track + converter = ublarcvapp.pixelutils.TrackToSpacePoints() + converter.setUseChargeWeighting(False) + spacepoints = converter.convertTrack( + track, adc_images, + threshold=10.0, # ADC threshold + dcol=3, # wire window + drow=3, # tick window + minstepsize=0.3, # min step (cm) + maxstepsize=0.5 # max step (cm) + ) + + # Make photon estimator + photon_estimator = ublarcvapp.ubphotonlib.PhotonVisibilityEstimator() + + for i, sp in enumerate(spacepoints): + #if sp.charge > 5.0: # Only use points with significant charge + n_photons = convert_charge_to_photons(sp.charge) + + photon_estimator.addPhotonSource( + sp.position.X(), + sp.position.Y(), + sp.position.Z(), + n_photons + ) + total_photons_added += n_photons + print(f"track[{itrack}] num photons predicted = {n_photons}") + photons_per_pmt = photon_estimator.calculateDetectedPhotons(use_trilinear=True) + track_predictions.append( photons_per_pmt ) + + print(f'Number of total photons: {total_photons_added}') + + return track_predictions + +def make_showers_visualization( tracks, showers, adc_images, offset=1 ): + # shower 3D visualization + h_shower_xz = rt.TH2F("h_shower_xz", "shower Projection X-Z;X [cm];Z [cm]", + 100, 0, 256.0, 100, 0, 1036.0) + h_shower_yz = rt.TH2F("h_shower_yz", "shower Projection Y-Z;Y [cm];Z [cm]", + 100, -120, 120.0, 100, 0, 1036.0) + + # Fill shower histogram + for ishower in range( showers.size()): + shower = showers.at(ishower) + for i in range(shower.size()): + hit = shower.at(i) + h_shower_xz.Fill(hit[0],hit[2], offset+ishower) + h_shower_yz.Fill(hit[1],hit[2], offset+ishower) + + return h_shower_xz, h_shower_yz + +def main(): + parser = argparse.ArgumentParser(description="Complete shower to light estimation example") + parser.add_argument("--input-file", required=True, help="ROOT file with shower/image data (optional)") + parser.add_argument("--save-output", action="store_true", help="Save output plots") + parser.add_argument("--charge-per-cm", type=float, default=2000.0, + help="Charge deposition per cm (ADC)") + args = parser.parse_args() + + print("Complete Shower to Light Estimation Example") + print("="*60) + + opflashes = None # Initialize for synthetic data case + + + # Use real data from ROOT file + print(f"\nUsing real data from: {args.input_file}") + adc_images, tracks, showers, opflashes = get_data_from_rootfile( args.input_file ) + + # Show information about optical flashes + print(f"\nFound {len(opflashes)} optical flashes") + if len(opflashes) > 0: + flash = opflashes[0] # Use first flash for comparison + print(f"Using flash 0: Total PE = {flash.TotalPE():.1f}, Time = {flash.Time():.1f} μs") + + + # Convert shower to space points + shower_pmt_preds = get_shower_opdet_predicts( showers, adc_images) + + # Convert track to space points + track_pmt_preds = get_track_opdet_predicts( tracks, adc_images) + + # Create visualization + if args.save_output: + fudge_factor = 1000.0 + print("\nCreating visualization...") + import lardly + from lardly.ubdl.pmtpos import getOpChannelFromOpDet, getOpDetFromOpChannel + + # PMT response histogram (predicted) + # We make a histogram for each object and then a stack histogram as well + h_pmt_pred_stack = rt.THStack("h_pmt_pred_stack", "Total Neutrino Candidate OpDet Prediction") + hists_v = [] + colors = [] + iprong = 0 + tlen = rt.TLegend(0.7,0.7,0.9,0.9) + for itrack, photons_per_pmt in enumerate( track_pmt_preds ): + h_pmt_pred = rt.TH1F(f"h_pmt_pred_track{itrack}", "PMT Light Response;PMT ID;Normalized Response", 32, 0, 32) + + rand_rgb = np.random.randint(0,255,3) + rand_tcolor = rt.TColor.GetColor( rand_rgb[0], rand_rgb[1], rand_rgb[2] ) + pesum = 0.0 + for pmt in range(32): + h_pmt_pred.SetBinContent(pmt+1, photons_per_pmt[pmt]*fudge_factor) + pesum += photons_per_pmt[pmt]*fudge_factor + xcolor = int(51+(iprong//5)+10*(iprong%5)) + print(f"xcolor[{iprong}]: {xcolor}") + h_pmt_pred.SetFillColor( xcolor ) + h_pmt_pred.SetFillStyle(3001) + h_pmt_pred.SetLineColor( xcolor ) + h_pmt_pred_stack.Add( h_pmt_pred ) + tlen.AddEntry( h_pmt_pred, f"Track[{itrack}]: {pesum:0.2f}" ) + hists_v.append( h_pmt_pred ) + colors.append( xcolor ) + iprong += 1 + + for ishower, photons_per_pmt in enumerate( shower_pmt_preds ): + h_pmt_pred = rt.TH1F(f"h_pmt_pred_shower{ishower}", "PMT Light Response;Optical Channel;Normalized Response", 32, 0, 32) + + rand_rgb = np.random.randint(0,255,3) + rand_tcolor = rt.TColor.GetColor( rand_rgb[0], rand_rgb[1], rand_rgb[2] ) + pesum = 0.0 + for pmt in range(32): + # predictions are indexed by opchannel + opchid = pmt + #opdetid = getOpDetFromOpChannel(opchid) + h_pmt_pred.SetBinContent(opchid+1, photons_per_pmt[pmt]*fudge_factor) + pesum += photons_per_pmt[pmt]*fudge_factor + xcolor = int(51+(iprong//5)+10*(iprong%5)) + print(f"xcolor[{iprong}]: {xcolor}") + h_pmt_pred.SetFillColor( xcolor ) + h_pmt_pred.SetFillStyle(3001) + h_pmt_pred_stack.Add( h_pmt_pred ) + tlen.AddEntry( h_pmt_pred, f"Shower[{ishower}]: {pesum:0.2f}" ) + hists_v.append( h_pmt_pred ) + colors.append( xcolor ) + iprong += 1 + + # PMT response histogram (observed) - only if we have opflash data + h_pmt_obs = None + if opflashes is not None and len(opflashes) > 0: + flash = opflashes[0] # Use first flash + h_pmt_obs = rt.TH1F("h_pmt_obs", "PMT Light Response;PMT ID;Normalized Response", 32, 0, 32) + h_pmt_obs.SetLineColor( rt.kBlack ) + h_pmt_obs.SetLineWidth( 2 ) + + # Fill observed PMT response and normalize to 1 + total_obs_pe = 0 + pe_per_pmt = [] + for pmt in range(32): + # opflash is indexed by channel? + #opdetid = getOpDetFromOpChannel( pmt ) + opchanid = pmt + pe = flash.PE(opchanid) + # opflash is indexed by opdet and pmt pred by channel? + #opchid = getOpChannelFromOpDet( pmt ) + #pe = flash.PE(opchid) + pe_per_pmt.append(pe) + total_obs_pe += pe + + # Normalize observed data so total = 1 for shape comparison + if total_obs_pe > 0: + for pmt in range(32): + normalized_pe = pe_per_pmt[pmt] / total_obs_pe + #h_pmt_obs.SetBinContent(pmt+1, normalized_pe) + h_pmt_obs.SetBinContent(pmt+1, pe_per_pmt[pmt]) + + print(f"\nObserved flash: Total PE = {total_obs_pe:.1f}") + print("Observed PE per PMT (>0.1):") + for pmt in range(32): + if pe_per_pmt[pmt] > 0.1: + print(f" PMT {pmt:2d}: {pe_per_pmt[pmt]:6.1f} PE") + + + # # shower 3D visualization + # h_shower_xz = rt.TH2F("h_shower_xz", "shower Projection X-Z;X [cm];Z [cm]", + # 100, 0, 200, 100, 100, 800) + # h_shower_yz = rt.TH2F("h_shower_yz", "shower Projection Y-Z;Y [cm];Z [cm]", + # 100, -50, 150, 100, 100, 800) + + # # Fill shower histograms + # for i in range(shower.size()): + # hit = shower.at(i) + # h_shower_xz.Fill(hit[0],hit[2]) + # h_shower_yz.Fill(hit[1],hit[2]) + + # # Space points with charge + # h_charge_xz = rt.TH2F("h_charge_xz", "Space Points with Charge;X [cm];Z [cm]", + # 100, 0, 200, 100, 100, 800) + # for sp in spacepoints: + # if sp.charge > 0: + # h_charge_xz.Fill(sp.position.X(), sp.position.Z(), sp.charge) + + # Create canvas with space for comparison plot + canvas = rt.TCanvas("c1", "shower Light Estimation", 1600, 1000) + #canvas.Divide(3, 3) + + canvas.cd(1) + pred_max = h_pmt_pred_stack.GetMaximum() + obs_max = h_pmt_obs.GetMaximum() + + if pred_max>obs_max: + h_pmt_pred_stack.Draw("hist") + else: + h_pmt_obs.Draw("hist") + + h_pmt_pred_stack.Draw("histsame") + h_pmt_obs.Draw("E1same") + tlen.Draw() + + # canvas.cd(2) + # h_shower_yz.SetMarkerStyle(20) + # h_shower_yz.SetMarkerColor(rt.kBlue) + # h_shower_yz.Draw("P") + # rt.gPad.SetTitle("shower Path (Y-Z)") + + # canvas.cd(3) + # h_charge_xz.SetMarkerStyle(20) + # h_charge_xz.SetMarkerColor(rt.kRed) + # h_charge_xz.Draw("COLZ") + # rt.gPad.SetTitle("Charge Deposits") + + # # PMT comparison plot + # canvas.cd(4) + # h_pmt_pred.SetLineColor(rt.kRed) + # h_pmt_pred.SetLineWidth(2) + # h_pmt_pred.SetTitle("PMT Response Comparison;PMT ID;Normalized Response") + # max_val = h_pmt_pred.GetMaximum() + + # if h_pmt_obs is not None: + # h_pmt_obs.SetLineColor(rt.kBlue) + # h_pmt_obs.SetLineWidth(2) + # max_val = max(max_val, h_pmt_obs.GetMaximum()) + # h_pmt_pred.GetYaxis().SetRangeUser(0, max_val * 1.1) + # h_pmt_pred.Draw("HIST") + # h_pmt_obs.Draw("HIST SAME") + + # # Add legend + # legend = rt.TLegend(0.6, 0.7, 0.89, 0.89) + # legend.AddEntry(h_pmt_pred, "Predicted", "l") + # legend.AddEntry(h_pmt_obs, "Observed", "l") + # legend.Draw() + # else: + # h_pmt_pred.SetFillColor(rt.kCyan-9) + # h_pmt_pred.Draw("HIST") + + # canvas.cd(5) + # # Individual predicted PMT response (unnormalized) + # h_pmt_pred_raw = rt.TH1F("h_pmt_pred_raw", "Predicted PMT Response;PMT ID;Photoelectrons", + # 32, 0, 32) + # for pmt in range(32): + # h_pmt_pred_raw.SetBinContent(pmt+1, photons_per_pmt[pmt]) + # h_pmt_pred_raw.SetFillColor(rt.kGreen-9) + # h_pmt_pred_raw.Draw("HIST") + + # canvas.cd(6) + # if h_pmt_obs is not None: + # # Individual observed PMT response (unnormalized) + # h_pmt_obs_raw = rt.TH1F("h_pmt_obs_raw", "Observed PMT Response;PMT ID;Photoelectrons", + # 32, 0, 32) + # for pmt in range(32): + # h_pmt_obs_raw.SetBinContent(pmt+1, pe_per_pmt[pmt]) + # h_pmt_obs_raw.SetFillColor(rt.kYellow-9) + # h_pmt_obs_raw.Draw("HIST") + + # # Summary text + # canvas.cd(7) + # text = rt.TText() + # text.SetTextSize(0.08) + # text.DrawText(0.1, 0.8, f"Space Points: {len(spacepoints)}") + # text.DrawText(0.1, 0.7, f"Total Charge: {converter.getTotalCharge():.0f} ADC") + # text.DrawText(0.1, 0.6, f"Emitted Photons: {total_photons_added:.0f}") + # text.DrawText(0.1, 0.5, f"Detected Photons: {total_detected:.0f}") + # text.DrawText(0.1, 0.4, f"Efficiency: {efficiency*100:.2f}%") + # if opflashes is not None and len(opflashes) > 0: + # text.DrawText(0.1, 0.3, f"Observed PE: {total_obs_pe:.0f}") + # text.DrawText(0.1, 0.2, f"Flash Time: {flash.Time():.1f} us") + + canvas.SaveAs("nucand_light_example.png") + print("Saved visualization to nucand_light_example.png") + print("[enter] to exit.") + input() + + print("\nExample completed successfully!") + +if __name__ == "__main__": + main() From b0f603ccbc3f0b57f45b950aafa8e716e32c6aae Mon Sep 17 00:00:00 2001 From: twongjirad Date: Wed, 2 Jul 2025 10:50:11 -0400 Subject: [PATCH 70/80] add missing constructor and destructors --- ublarcvapp/LArOpenCVHandle/LArbysImage.cxx | 4 ++++ ublarcvapp/LArOpenCVHandle/LArbysImage.h | 5 +++-- ublarcvapp/LArOpenCVHandle/LArbysImageExtract.cxx | 4 ++++ ublarcvapp/LArOpenCVHandle/LArbysImageExtract.h | 7 ++++--- ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h | 5 +++-- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx b/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx index 4c8159a..2a0827b 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx +++ b/ublarcvapp/LArOpenCVHandle/LArbysImage.cxx @@ -19,6 +19,10 @@ namespace larcv { static LArbysImageProcessFactory __global_LArbysImageProcessFactory__; + LArbysImage::LArbysImage() + : LArbysImage("LArbysImage") + {}; + LArbysImage::LArbysImage(const std::string name) : ProcessBase(name), _image_cluster_cfg("aho"), diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImage.h b/ublarcvapp/LArOpenCVHandle/LArbysImage.h index 36bb566..5fc52ec 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImage.h +++ b/ublarcvapp/LArOpenCVHandle/LArbysImage.h @@ -19,10 +19,11 @@ namespace larcv { public: /// Default constructor - LArbysImage(const std::string name="LArbysImage"); + LArbysImage(); + LArbysImage(const std::string name); /// Default destructor - virtual ~LArbysImage(){} + virtual ~LArbysImage(){}; void configure(const PSet&); diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.cxx b/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.cxx index e61ffd5..14a3ec2 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.cxx +++ b/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.cxx @@ -7,6 +7,10 @@ namespace larcv { static LArbysImageExtractProcessFactory __global_LArbysImageExtractProcessFactory__; + LArbysImageExtract::LArbysImageExtract() + : LArbysImageExtract("LArbysImageExtract") + {} + LArbysImageExtract::LArbysImageExtract(const std::string name) : ProcessBase(name), _LArbysImageMaker() diff --git a/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.h b/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.h index 8575e61..d580b22 100644 --- a/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.h +++ b/ublarcvapp/LArOpenCVHandle/LArbysImageExtract.h @@ -12,9 +12,10 @@ namespace larcv { class LArbysImageExtract : public ProcessBase { public: - - LArbysImageExtract(const std::string name="LArbysImageExtract"); - ~LArbysImageExtract(){} + + LArbysImageExtract(); + LArbysImageExtract(const std::string name); + ~LArbysImageExtract(){}; void configure(const PSet&); void initialize(); diff --git a/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h index ea8ffb4..0584a5e 100644 --- a/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h +++ b/ublarcvapp/ParticleToPixelUtils/TrackToSpacePoints.h @@ -37,7 +37,8 @@ namespace pixelutils { SpacePointCharge() : position(0,0,0), charge(0), wire_u(-1), wire_v(-1), wire_y(-1), tick(-1), - plane_charges(3,0) {} + plane_charges(3,0) {}; + ~SpacePointCharge() {}; }; /** @@ -166,4 +167,4 @@ namespace pixelutils { } } -#endif \ No newline at end of file +#endif From 991650343c6e8353ec351b540507e2fca89ab9d0 Mon Sep 17 00:00:00 2001 From: twongjirad Date: Wed, 2 Jul 2025 11:32:16 -0400 Subject: [PATCH 71/80] turned off deprecated code --- ublarcvapp/CMakeLists.txt | 4 ++-- ublarcvapp/ContourTools/CMakeLists.txt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ublarcvapp/CMakeLists.txt b/ublarcvapp/CMakeLists.txt index 13b212d..c489072 100644 --- a/ublarcvapp/CMakeLists.txt +++ b/ublarcvapp/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(dbscan) -add_subdirectory(Reco3D) -add_subdirectory(LArOpenCVHandle) +#add_subdirectory(Reco3D) +#add_subdirectory(LArOpenCVHandle) add_subdirectory(ContourTools) # requires opencv, laropencv if (HAS_LARLITE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LARLITE") diff --git a/ublarcvapp/ContourTools/CMakeLists.txt b/ublarcvapp/ContourTools/CMakeLists.txt index 354a949..f51b022 100644 --- a/ublarcvapp/ContourTools/CMakeLists.txt +++ b/ublarcvapp/ContourTools/CMakeLists.txt @@ -7,7 +7,7 @@ set( HEADERS ContourShapeMeta.h ContourCluster.h ContourClusterAlgo.h - ContourAStarClusterAlgo.h + #ContourAStarClusterAlgo.h ) # Collect the sources @@ -15,7 +15,7 @@ add_library( ${LIBNAME} SHARED ContourShapeMeta.cxx ContourCluster.cxx ContourClusterAlgo.cxx - ContourAStarClusterAlgo.cxx + #ContourAStarClusterAlgo.cxx ) set_target_properties(${LIBNAME} PROPERTIES PUBLIC_HEADER "${HEADERS}") @@ -40,8 +40,8 @@ target_link_libraries( ${LIBNAME} PUBLIC LArCVCoreCVUtil ${GEO2D_LIBS} ${LAROPENCV_LIBS} - LArCVApp_LArOpenCVHandle - LArCVApp_Reco3D + #LArCVApp_LArOpenCVHandle + #LArCVApp_Reco3D ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR} From f220940d385e921c2fbb093a888b162e2476efce Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Wed, 12 Nov 2025 12:22:54 +0000 Subject: [PATCH 72/80] provide python friendly methods to get ancestorid and shower mother ids --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 31 ++++++++++++++++++++++++---- ublarcvapp/MCTools/MCPixelPGraph.h | 2 ++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 3ff6197..59e7984 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -93,10 +93,7 @@ namespace mctools { clear(); - buildgraphonly( shower_v, track_v, mctruth_v ); - - // fill the daugher to mother shower ID map - _fill_shower_daughter2mother_map( shower_v ); + buildgraphonly( shower_v, track_v, mctruth_v ); std::vector threshold_v(adc_v.size(),10.0); _scanPixelData( adc_v, segment_v, instance_v, ancestor_v, threshold_v ); @@ -164,6 +161,9 @@ namespace mctools { clear(); + // fill the daugher to mother shower ID map + _fill_shower_daughter2mother_map( shower_v ); + node_v.clear(); node_v.reserve( shower_v.size()+track_v.size()+100 ); @@ -2557,5 +2557,28 @@ namespace mctools { return edep_pos; } + /** + * @brief get ancestor ID for track ID by querying info in Nodes + */ + int MCPixelPGraph::getAncestorID( int trackid ) { + Node_t* pnode = findTrackID(trackid); + if (pnode==nullptr) + return -1; + return pnode->aid; + } + + /** + * @brief get ancestor ID for track ID by querying info in Nodes + */ + int MCPixelPGraph::getShowerMotherID( int trackid ) { + auto it = _shower_daughter2mother.find( trackid ); + if ( it!=_shower_daughter2mother.end() ) { + return it->second; + } + return -1; + } + + + } } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index 8e3c009..a6c99bb 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -198,6 +198,8 @@ namespace mctools { // search methods Node_t* findTrackID( int trackid ); + int getAncestorID( int trackid ); + int getShowerMotherID( int trackid ); // print info methods void printAllNodeInfo(); From a392d71bc08a27a04efd632c1d87539e6bdf253b Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Mon, 17 Nov 2025 15:28:01 +0000 Subject: [PATCH 73/80] add access functions for node objects in mcpixelpgraph --- ublarcvapp/MCTools/MCPixelPGraph.cxx | 10 ++++++++++ ublarcvapp/MCTools/MCPixelPGraph.h | 1 + 2 files changed, 11 insertions(+) diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 59e7984..213f599 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -2578,6 +2578,16 @@ namespace mctools { return -1; } + /** + * @brief get particle ID for track ID by querying info in Nodes + */ + int MCPixelPGraph::getParticleID( int trackid ) { + Node_t* pnode = findTrackID(trackid); + if (pnode==nullptr) + return -1; + return pnode->pid; + } + } diff --git a/ublarcvapp/MCTools/MCPixelPGraph.h b/ublarcvapp/MCTools/MCPixelPGraph.h index a6c99bb..efa4dbc 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.h +++ b/ublarcvapp/MCTools/MCPixelPGraph.h @@ -200,6 +200,7 @@ namespace mctools { Node_t* findTrackID( int trackid ); int getAncestorID( int trackid ); int getShowerMotherID( int trackid ); + int getParticleID( int trackid ); // print info methods void printAllNodeInfo(); From fbd2c3f9d0de35cb9a55f7b66a52f1c1827a67de Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 20 Nov 2025 19:13:21 +0000 Subject: [PATCH 74/80] refactoring mcpixelpgraph. starting by isolating graph part into mcparticlegraph object first --- ublarcvapp/MCTools/CMakeLists.txt | 4 + ublarcvapp/MCTools/LinkDef.h | 4 + ublarcvapp/MCTools/MCPGNode.cxx | 1 + ublarcvapp/MCTools/MCPGNode.h | 116 +++ ublarcvapp/MCTools/MCParticleGraph.cxx | 1104 ++++++++++++++++++++++++ ublarcvapp/MCTools/MCParticleGraph.h | 97 +++ 6 files changed, 1326 insertions(+) create mode 100644 ublarcvapp/MCTools/MCPGNode.cxx create mode 100644 ublarcvapp/MCTools/MCPGNode.h create mode 100644 ublarcvapp/MCTools/MCParticleGraph.cxx create mode 100644 ublarcvapp/MCTools/MCParticleGraph.h diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 88661b6..771d23d 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -5,6 +5,8 @@ set(LIBNAME LArCVApp_${MODULE_NAME}) # Collect the headers set( HEADERS MCPos2ImageUtils.h + MCPGNode.h + MCParticleGraph.h MCPixelPGraph.h TruthTrackSCE.h TruthShowerTrunkSCE.h @@ -18,6 +20,8 @@ set( HEADERS MCPos2ImageUtils.h # Add sources add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx + MCPGNode.cxx + MCParticleGraph.cxx MCPixelPGraph.cxx TruthTrackSCE.cxx TruthShowerTrunkSCE.cxx diff --git a/ublarcvapp/MCTools/LinkDef.h b/ublarcvapp/MCTools/LinkDef.h index 422443f..7e3c3f0 100644 --- a/ublarcvapp/MCTools/LinkDef.h +++ b/ublarcvapp/MCTools/LinkDef.h @@ -20,6 +20,10 @@ //#pragma link C++ class std::vector+; //#pragma link C++ class std::vector >+; +#pragma link C++ class ublarcvapp::mctools::MCPGNode+; +#pragma link C++ class ublarcvapp::mctools::MCParticleGraph+; + +#pragma link C++ class ublarcvapp::mctools::MCPixelLabels+; #pragma link C++ class ublarcvapp::mctools::MCPos2ImageUtils+; #pragma link C++ class ublarcvapp::mctools::MCPixelPGraph+; #pragma link C++ class ublarcvapp::mctools::MCPixelPMap+; diff --git a/ublarcvapp/MCTools/MCPGNode.cxx b/ublarcvapp/MCTools/MCPGNode.cxx new file mode 100644 index 0000000..b4d6732 --- /dev/null +++ b/ublarcvapp/MCTools/MCPGNode.cxx @@ -0,0 +1 @@ +#include "MCPGNode.h" diff --git a/ublarcvapp/MCTools/MCPGNode.h b/ublarcvapp/MCTools/MCPGNode.h new file mode 100644 index 0000000..0297969 --- /dev/null +++ b/ublarcvapp/MCTools/MCPGNode.h @@ -0,0 +1,116 @@ +#ifndef __UBLARCVAPP_MCTOOLS_MCPGNODE_H__ +#define __UBLARCVAPP_MCTOOLS_MCPGNODE_H__ + +#include +#include + +namespace ublarcvapp { +namespace mctools { + + class MCPGNode { + + public: + + int nodeidx; // book-keeping index + int type; // track=0, shower=1, nu-vertex=2, genie_fs=3 + int vidx; // position in mcshower or mctrack vector + int tid; // geant4 track-ID + int aid; // ancestor geant4 trackid + int mtid; // mother geant4 trackid + int pid; // particle ID + MCPGNode* mother; // pointer to Mother Node + int mid; // mother nodeidx + float E_MeV; // energy + std::string process; // creating process + std::string mother_process; // mother process + std::string ancestor_process; // ancestor process + std::vector daughter_v; // pointer to daughters + std::vector daughter_idx_v; // daughter node indices in node_v + std::vector start; //< (x,y,z,t) before sce, true start of particle + std::vector first_edep_pos; //< (x,y,z,t) before sce, first step that leaves edep in cryostat + std::vector first_tpc_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image + + int origin; // 1=neutrino, 2=cosmic, 0=unassigned, -1=unassigned + + MCPGNode() + : nodeidx(-1), + type(-1), + vidx(-1), + tid(-1), + aid(-1), + mtid(-1), + pid(-1), + mother(nullptr), + mid(-1), + E_MeV(-1.0), + process("null"), + start({0,0,0,0}), + first_edep_pos({0,0,0,0}), + first_tpc_pos({0,0,0,0}), + origin(-1) + { + daughter_v.clear(); + daughter_idx_v.clear(); + }; + + MCPGNode(int _nodeidx, int _type, int _tid, int _vidx, + int _pid, + MCPGNode* _mother=nullptr, + int _mid=-1, + float _energy=-1.0, + std::string proc="null") + : nodeidx(_nodeidx), + type(_type), + vidx(_vidx), + tid(_tid), + aid(-1), + mtid(-1), + pid(_pid), + mother(_mother), + mid(_mid), + E_MeV(_energy), + process(proc), + start({0,0,0,0}), + first_edep_pos({0,0,0,0}), + first_tpc_pos({0,0,0,0}), + origin(-1) + { + daughter_v.clear(); + daughter_idx_v.clear(); + }; + + bool operator<( const MCPGNode& rhs ) const { + if ( tid < rhs.tid ) return true; + return false; + }; + + bool isTrackObject() const { + if ( type==0 ) + return true; + return false; + }; + + bool isShowerObject() const { + if (type==1) + return true; + return false; + }; + + bool isNuVertexObject() const { + if (type==2) + return true; + return false; + }; + + bool isGenieFinalStateObject() const { + if (type==3) + return true; + return false; + }; + + }; + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/MCTools/MCParticleGraph.cxx b/ublarcvapp/MCTools/MCParticleGraph.cxx new file mode 100644 index 0000000..fc99c32 --- /dev/null +++ b/ublarcvapp/MCTools/MCParticleGraph.cxx @@ -0,0 +1,1104 @@ +#include "MCParticleGraph.h" + +#include +#include + +// larlite +#include "larlite/DataFormat/mctrack.h" +#include "larlite/DataFormat/mcshower.h" +#include "larlite/DataFormat/mctruth.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" + +// ublarcvapp +#include "ublarcvapp/dbscan/DBScan.h" + +#include "crossingPointsAnaMethods.h" +#include "MCPos2ImageUtils.h" + +namespace ublarcvapp { +namespace mctools { + + /** + * @brief clear all data containers + */ + void MCParticleGraph::clear() + { + node_v.clear(); + _eventRootNode = nullptr; + _shower_daughter2mother.clear(); + } + + /** + * @brief build only the particle graph (no pixel scan) + * + */ + void MCParticleGraph::buildgraph( larlite::storage_manager& ioll ) + { + + auto ev_mctrack = (larlite::event_mctrack*) ioll.get_data( larlite::data::kMCTrack, "mcreco" ); + auto ev_mcshower = (larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" ); + auto ev_mctruth = (larlite::event_mctruth*) ioll.get_data( larlite::data::kMCTruth, "generator" ); + + buildgraph( *ev_mcshower, *ev_mctrack, *ev_mctruth ); + + } + + /** + * @brief build the particle graph (no pixel assignments) + * + */ + void MCParticleGraph::buildgraph( const larlite::event_mcshower& shower_v, + const larlite::event_mctrack& track_v, + const larlite::event_mctruth& mctruth_v ) { + + // how do we build this graph? + // we want to order N + + // (0) create root node + // (1) loop through track and shower, creating node objects + // (2) loop through node objects connecting daughters to mothers + // (3) (optional) get depth of each node by doing breath-first traversal + // (4) sort vector pointers by depth (necessary?) + + // dump mctruth info + // LARCV_DEBUG() << "MCTruth Dump" << std::endl; + // int imctruth=0; + // for ( auto& mctruth : mctruth_v ) { + // LARCV_DEBUG() << "MCTRUTH[" << imctruth << "] --------------" << std::endl; + // int imcpart = 0; + // for ( auto& part : mctruth.GetParticles() ) { + // LARCV_DEBUG() << " mcpart[" << imcpart << "] -------" << std::endl; + // LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; + // LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; + // LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; + // LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; + // LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; + // LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; + // } + // } + + clear(); + + // fill the daugher to mother shower ID map + _fill_shower_daughter2mother_map( shower_v ); + + node_v.clear(); + node_v.reserve( shower_v.size()+track_v.size()+100 ); + + // Create ROOT node + MCPGNode neutrino ( node_v.size(), -1, 0, 0, -1 ); + + // define TPC widths + float tpc_x = larutil::Geometry::GetME()->DetHalfWidth()*2.0; + float tpc_y = larutil::Geometry::GetME()->DetHalfHeight(); + float tpc_z = larutil::Geometry::GetME()->DetLength(); + + // if there is a neutrino, then we add the start position + if ( mctruth_v.size()>0 ) { + const larlite::mctruth& mct = mctruth_v.front(); + neutrino.E_MeV = mct.GetNeutrino().Nu().Trajectory().front().E()*1000.0; + neutrino.start.resize(4); + neutrino.start[0] = mct.GetNeutrino().Nu().Trajectory().front().X(); + neutrino.start[1] = mct.GetNeutrino().Nu().Trajectory().front().Y(); + neutrino.start[2] = mct.GetNeutrino().Nu().Trajectory().front().Z(); + neutrino.start[3] = mct.GetNeutrino().Nu().Trajectory().front().T(); + } + node_v.emplace_back( std::move(neutrino) ); + + _eventRootNode = &node_v[0]; + + // keep tabs on all track IDs found + std::set tid_list; + + // load spacechargemicroboone: forward effect + //larutil::SpaceChargeMicroBooNE sce; + + // struct for primary particles from nu interactions + struct NuPart_t { + int geantid; + int pdg; + float E_MeV; + std::vector pos; + }; + + std::vector< NuPart_t > nu_part_v; + + // collect data from mcreco tracks + int mc_product_type = 0; // larlite::mctrack + for (int vidx=0; vidx<(int)track_v.size(); vidx++ ) { + const larlite::mctrack& mct = track_v[vidx]; + LARCV_DEBUG() << "track[" << vidx << "] origin=" << mct.Origin() + << " tid=" << mct.TrackID() + << " mid=" << mct.MotherTrackID() + << " aid=" << mct.AncestorTrackID() + << " pid=" << mct.PdgCode() + << std::endl; + + MCPGNode tracknode( node_v.size(), mc_product_type, mct.TrackID(), vidx, mct.PdgCode() ); + tracknode.E_MeV = mct.Start().E(); + tracknode.aid = mct.AncestorTrackID(); + tracknode.mtid = mct.MotherTrackID(); + tracknode.process = mct.Process(); + tracknode.mother_process = mct.MotherProcess(); + tracknode.ancestor_process = mct.AncestorProcess(); + + // convert energy into relativistic KE + if ( mct.PdgCode()==2212 ) tracknode.E_MeV -= 938.0; + else if ( mct.PdgCode()==2112 ) tracknode.E_MeV -= 940.0; + else if ( abs(mct.PdgCode())==13 ) tracknode.E_MeV -= 105.; + else if ( abs(mct.PdgCode())==211 ) tracknode.E_MeV -= 135.; + tracknode.origin = mct.Origin(); + + // exception for process=neutronInelastic + if ( mct.PdgCode()==2112 && mct.Process()=="neutronInelastic" ) { + // these are actually protons made by a neutrino inelastic process + // just the way the MC reco producer saves these. + tracknode.E_MeV = mct.Start().E()-938.0; + } + + tid_list.insert( tracknode.tid ); + + // set creation position, time + tracknode.start.resize(4); + tracknode.start[0] = mct.Start().X(); + tracknode.start[1] = mct.Start().Y(); + tracknode.start[2] = mct.Start().Z(); + tracknode.start[3] = mct.Start().T(); + + if ( tracknode.origin==1 ) { + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = tracknode.tid; + nuparticle.pdg = tracknode.pid; + nuparticle.E_MeV = mct.Start().E(); + nuparticle.pos = tracknode.start; + nu_part_v.push_back( nuparticle ); + } + + // find the first position + // - with cryo edep + // - inside the TPC + tracknode.first_edep_pos = std::vector(4,0); + tracknode.first_tpc_pos = std::vector(4,0); + + if ( mct.size()>=1 ) { + tracknode.first_edep_pos[0] = mct[0].X(); + tracknode.first_edep_pos[1] = mct[0].Y(); + tracknode.first_edep_pos[2] = mct[0].Z(); + tracknode.first_edep_pos[3] = mct[0].T(); + + // first TPC point + std::vector recopos(4,0); + std::vector edep_imgpos(4,0); + std::vector xyz(4,0); + bool intpc = false; + bool inimage = false; + bool first_step = false; + for (auto const& step : mct ) { + xyz[0] = (float)step.X(); + xyz[1] = (float)step.Y(); + xyz[2] = (float)step.Z(); + xyz[3] = (float)step.T(); + + if ( !first_step ) { + first_step = true; + tracknode.first_edep_pos = xyz; + } + + if ( ( xyz[0]>0.0 && xyz[0]0 && xyz[2]{ (float)mcsh.Start().X(), (float)mcsh.Start().Y(), (float)mcsh.Start().Z(), (float)mcsh.Start().T() }; + showernode.aid = mcsh.AncestorTrackID(); + showernode.mtid = mcsh.MotherTrackID(); + + showernode.first_edep_pos = std::vector(4,0); + showernode.first_tpc_pos = std::vector(4,0); + + bool x_isinf = false; + if ( mcsh.DetProfile().X()>1.0e100 || mcsh.DetProfile().X()<-1.0e100 ) + x_isinf = true; + if ( !x_isinf && !std::isnan( mcsh.DetProfile().X() ) ) { + //std::cout << "inf test: " << mcsh.DetProfile().X() << " " << std::isinf( mcsh.DetProfile().X() ) << std::endl; + std::vector detprofile = { (float)mcsh.DetProfile().X(), (float)mcsh.DetProfile().Y(), (float)mcsh.DetProfile().Z(), (float)mcsh.DetProfile().T() }; + showernode.first_edep_pos = detprofile; + showernode.first_tpc_pos = detprofile; + } + if ( showernode.origin==1 ) { + // store nu particle + NuPart_t nuparticle; + nuparticle.geantid = showernode.tid; + nuparticle.pdg = showernode.pid; + nuparticle.E_MeV = mcsh.Start().E(); + nuparticle.pos = std::vector{ (float)mcsh.Start().X(), + (float)mcsh.Start().Y(), + (float)mcsh.Start().Z(), + (float)mcsh.Start().T() }; + nu_part_v.push_back( nuparticle ); + } + + tid_list.insert( showernode.tid ); + node_v.emplace_back( std::move(showernode) ); + } + + // find the geant4 trackid offset for the neutrinos + long smallest_nu_tid = -1; + for ( auto& node : node_v ) { + if ( node.origin==1 ) { + if (smallest_nu_tid<0 || node.tid < smallest_nu_tid ) { + smallest_nu_tid = node.tid; + } + } + } + LARCV_DEBUG() << "Smallest neutrino Geant4 Track ID: " << smallest_nu_tid << std::endl; + + // collect from mctruth (data form GENIE generator) + mc_product_type = 3; + + // we need to match the earliest track or shower object to + // a genie final state particle to get offset + int ifs_1 = 0; + int matched_fs = -1; + int matched_geant_id = -1; + for ( auto& mctruth : mctruth_v ) { + for ( auto& part : mctruth.GetParticles() ) { + if ( part.StatusCode()==1 ) { + ifs_1 += 1; + // does ginal state particel match any of the geant4 particles? + for (auto& nupart : nu_part_v) { + // match pdg + if ( nupart.pdg!=part.PdgCode() ) + continue; + + // match energy + float dE_MeV = std::fabs(nupart.E_MeV-part.Momentum(0)[3]*1000.0); + LARCV_DEBUG() << "mctruth part: " << dE_MeV << std::endl; + if ( dE_MeV > 10.0 ) + continue; + + matched_fs = ifs_1; + matched_geant_id = nupart.geantid; + LARCV_DEBUG() << "have first match. " + << "genie finalstate id=" << matched_fs + << " geantid=" << matched_geant_id + << std::endl; + break; + } + + }//end of if status code + if (matched_fs>=0) + break; + }//end of mcpart loop + if (matched_fs>=0) + break; + }//end of mctruth loop + + int geantid_offset = smallest_nu_tid - (matched_fs-1); + LARCV_INFO() << "geantid offset: " << geantid_offset << " smallest_nu_tid=" << smallest_nu_tid << std::endl; + LARCV_INFO() << " matched_fs=" << matched_fs << " matched_geant4=" << matched_geant_id << std::endl; + + int imctruth=0; + int ifs = 0; + for ( auto& mctruth : mctruth_v ) { + int imcpart = 0; + for ( auto& part : mctruth.GetParticles() ) { + LARCV_DEBUG() << " mcpart[" << imctruth << "," << imcpart << "] -------" << std::endl; + LARCV_DEBUG() << " status=" << part.StatusCode() << std::endl; + LARCV_DEBUG() << " trackid=" << part.TrackId() << std::endl; + LARCV_DEBUG() << " pdg=" << part.PdgCode() << std::endl; + LARCV_DEBUG() << " motherid=" << part.Mother() << std::endl; + LARCV_DEBUG() << " process=" << part.Process() << " endprocess=" << part.EndProcess() << std::endl; + LARCV_DEBUG() << " num daughters=" << part.Daughters().size() << std::endl; + + if ( part.StatusCode()==1 ) { + int geant_trackid = geantid_offset + ifs; + LARCV_DEBUG() << " Stable Final State. Implied Geant4 ID = " << geant_trackid << std::endl; + ifs++; + + auto it_tid = tid_list.find(geant_trackid); + if (it_tid==tid_list.end() ) { + int nodeidx = node_v.size(); + int type = 3; // genie-final-state + int tid = geant_trackid; + int vidx = imcpart; + int pid = part.PdgCode(); + MCPGNode* mother = nullptr; + int mid = -1; + float energy = part.Momentum(0)[3]*1e3 - part.Mass()*1.0e3; // in GeV, convert to MeV + std::vector start { (float)part.Position(0)[0], + (float)part.Position(0)[1], + (float)part.Position(0)[2], + (float)part.Position(0)[3]}; + + //LARCV_DEBUG() << "Creating Mother node from GENIE final states: tid=" << tid << " type=" << 3 << std::endl; + MCPGNode fsnode( nodeidx, mc_product_type, tid, vidx, pid, mother, mid, energy, "primary" ); + fsnode.start = start; + // fsnode.first_edep_pos = start; + // fsnode.first_tpc_pos = start; + fsnode.mtid = tid; + fsnode.aid = tid; + fsnode.origin = 1; // neutrino origin (from genie) + LARCV_DEBUG() << "Add Genie Final State Particle to initial List: tid=" << tid << " pdg=" << pid << std::endl; + node_v.emplace_back( std::move(fsnode) ); + } + else { + LARCV_DEBUG() << "Genie Final State Partial [tid=" << geant_trackid << "] Already in MCReco List" << std::endl; + } + } + imcpart++; + } + imctruth++; + } + + // try to connect primary neutrino origin nodes to mctruth info + //_adoptNeutrinoOrphans( &mctruth_v ); // whats this? + + // now we connect the graph + + // sort MCPGNode object by geant track ID, relabel node IDs + std::sort( node_v.begin(), node_v.end() ); + for ( size_t nid=0; nidtid!=(int)track.MotherTrackID() ) { + // try ancestor ID + mothernode = findTrackID( track.AncestorTrackID() ); + if ( mothernode && mothernode->tid!=(int)track.AncestorTrackID() ) + mothernode = nullptr; + } + } + } + else if (node.type==1) { + //shower nodes + const larlite::mcshower& shower = shower_v[node.vidx]; + if (shower.TrackID()==shower.MotherTrackID() ) { + //primary + mothernode = &node_v[0]; + } + else { + //secondary + mothernode = findTrackID( shower.MotherTrackID() ); + if( mothernode==nullptr || mothernode->tid!=(int)shower.MotherTrackID() ) { + // try ancestor ID + mothernode = findTrackID( shower.AncestorTrackID() ); + if ( mothernode && mothernode->tid!=(int)shower.AncestorTrackID() ) + mothernode = nullptr; + } + } + } + else if (node.type==3) { + // genie fs nodes + // connet to ROOT node as they are primary by definition + mothernode = &(node_v[0]); + } + else { + continue; + } + + if (mothernode) { + // found mother, connect + //std::cout << "found mother: " << strNodeInfo(*mothernode) << std::endl; + node.mother = mothernode; + node.mid = mothernode->nodeidx; + mothernode->daughter_v.push_back( &node ); + mothernode->daughter_idx_v.push_back( node.nodeidx ); + } + + }//end of node loop + + if ( _cluster_neutrino_particles ) { + int nnu = _define_neutrino_interaction_nodes( track_v, shower_v ); + LARCV_INFO() << "Rearranged graph to include neutrino vertex nodes. Number of Nu Interactions: " << nnu << std::endl; + } + + //printAllNodeInfo(); + //printGraph(); + } + + /** + * @brief wrapper function to retrieve Node's corresponding mctrack object from larlite container + */ + const larlite::mctrack& + MCParticleGraph::_retrieve_mctrackobject( const MCPGNode* node, + const larlite::event_mctrack& ev_track_v ) + { + try { + const larlite::mctrack& x = ev_track_v.at(node->vidx); + // to do: check that truth info matches? + return x; + } + catch ( std::exception& ex ) { + std::stringstream err; + err << "Error accessing event_mctrack container at index=" << node->vidx << " for node[idx]=nodeidx" << std::endl; + err << "Node info: " << std::endl; + err << strNodeInfo( *node ) << std::endl; + err << "Exception: " << ex.what() << std::endl; + throw std::runtime_error( err.str() ); + } + } + + /** + * @brief wrapper function to retrieve Node's corresponding mcshower object from larlite container + */ + const larlite::mcshower& + MCParticleGraph::_retrieve_mcshowerobject( const MCPGNode* node, + const larlite::event_mcshower& ev_shower_v ) + { + try { + const larlite::mcshower& x = ev_shower_v.at(node->vidx); + // to do: check that truth info matches? + return x; + } + catch ( std::exception& ex ) { + std::stringstream err; + err << "Error accessing event_mcshower container at index=" << node->vidx << " for node[idx]=nodeidx" << std::endl; + err << "Node info: " << std::endl; + err << strNodeInfo( *node ) << std::endl; + err << "Exception: " << ex.what() << std::endl; + throw std::runtime_error( err.str() ); + } + } + + /** + * @brief convenience function to retrieve Node's corresponding mctrack object from larlite top-level io interface + */ + const larlite::mctrack& MCParticleGraph::_retrieve_mctrackobject( const MCPGNode* node, + larlite::storage_manager& ioll, + std::string producername ) + { + const larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack, producername ); + + return _retrieve_mctrackobject( node, *ev_mctrack ); + } + + /** + * @brief convenience function to retrieve Node's corresponding mcshower object from larlite top-level io interface + */ + const larlite::mcshower& + MCParticleGraph::_retrieve_mcshowerobject( const MCPGNode* node, + larlite::storage_manager& ioll, + std::string producername ) + { + const larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower, producername ); + + return _retrieve_mcshowerobject( node, *ev_mcshower ); + } + + + /** + * @brief locate MCPGNode in node_v using trackid (from geant4) + * + * we first search our vector of MCPGNode objects, which are sorted by track id. + * + * we then search the keys of the _shower_daughter2mother map, where the keys + * are track id of particles made by the initial shower. + * + * @return The node if found, nullptr if not found + * + */ + MCPGNode* MCParticleGraph::findTrackID( int trackid ) { + MCPGNode dummy; + dummy.tid = trackid; + auto it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); + if ( it==node_v.end() || it->tid!=dummy.tid ) { + // no node, check the daughter ID map + auto it_showerdaughter = _shower_daughter2mother.find( trackid ); + if ( it_showerdaughter!=_shower_daughter2mother.end() ) { + // found an id + //LARCV_DEBUG() << " found map to mother: " << it_showerdaughter->second << std::endl; + dummy.tid = it_showerdaughter->second; + } + else { + // still nope + return nullptr; + } + // with the mother shower's trackid, try to find the node again + it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); + //if ( it!=node_v.end() ) + // LARCV_DEBUG() << " mother id maps to existing node" << std::endl; + } + + if ( it==node_v.end() || it->tid!=dummy.tid ) { + return nullptr; + } + //std::cout << "find trackid=" << trackid << ": " << strNodeInfo( *it ) << std::endl; + return &*(it+0); + } + + /** + * print node info for all nodes stored in node_v + * + */ + void MCParticleGraph::printAllNodeInfo() { + for ( auto const& node : node_v ) { + printNodeInfo(node); + } + } + + /** + * create string with info from a given MCPGNode + * + * @param[in] node Note_t object to make info for. + * + */ + std::string MCParticleGraph::strNodeInfo( const MCPGNode& node ) + { + + int hasmother = ( node.mother ) ? 1 : 0; + + std::stringstream ss; + //ss << "node[" << node.nodeidx << "," << &node << "] " + ss << "node[" << node.nodeidx << "] " + << " (type,vidx)=(" << node.type << "," << node.vidx << ") " + << " origin=" << node.origin + << " pdg=" << node.pid + << " p=" << node.process; + if ( node.mother_process!="" ) + ss << "/" << node.mother_process; + if ( node.ancestor_process!="" ) + ss << "/" << node.ancestor_process; + ss << " tid=" << node.tid + << " mtid=" << node.mtid + << " aid=" << node.aid + << " KE=" << node.E_MeV << " MeV" + //<< " xyzt= + //<< " tusec=" << node.start[3]*1.0e-3 << " us" + //<< " (mid,mother)=(" << node.mid << "," << node.mother << ") " + //<< " (mid,mother)=(" << node.mid << ") " + << " hasmother=" << hasmother + << " ndaughters=" << node.daughter_v.size() + << std::endl; + // additional positional info + if ( node.start.size()>=4 ) + ss << " start(x,y,z,t)=(" << node.start[0] << "," << node.start[1] << "," << node.start[2] << "," << node.start[3]*1.0e-3 << " us) " << std::endl; + + if ( node.first_edep_pos.size()>=4 ) + ss << " edep-cryo(x,y,z,t)=(" << node.first_edep_pos[0] << "," + << node.first_edep_pos[1] << "," + << node.first_edep_pos[2] << "," + << node.first_edep_pos[3]*1.0e-3 + << " us)" << std::endl; + + if ( node.first_tpc_pos.size()>=4 ) + ss << " edep-tpc(x,y,z,t)=(" << node.first_tpc_pos[0] << "," + << node.first_tpc_pos[1] << "," + << node.first_tpc_pos[2] << "," + << node.first_tpc_pos[3]*1.0e-3 + << " us)" << std::endl; + + + //ss << std::endl; + return ss.str(); + } + + /** + * print MCPGNode info to standard out + * + * @param[in] node MCPGNode object to print info for. + * + */ + void MCParticleGraph::printNodeInfo( const MCPGNode& node ) { + std::cout << strNodeInfo(node) << std::endl; + } + + /** + * dump graph to standard out + * + */ + void MCParticleGraph::printGraph( MCPGNode* rootnode, bool visible_only ) { + // here we go! + std::cout << "=======[ MCParticleGraph::printGraph ]==============" << std::endl; + int depth = 0; + if (rootnode==nullptr ) + rootnode = &node_v.front(); + _recursivePrintGraph( rootnode, depth, visible_only ); + } + + /* + * internal recursive function that prints node info + * + */ + void MCParticleGraph::_recursivePrintGraph( MCPGNode* node, int& depth, bool visible_only ) { + if ( depth<0 ) return; // we're done (error?) + + // depth first printing of nodes + std::string info = strNodeInfo( *node ); + std::string branch = ""; + std::string branch2 = ""; + for ( int i=0; i0 ) { + branch += "-- "; + branch2 += " "; + } + + std::stringstream ss(info); + std::string to; + bool firstline = true; + while(std::getline(ss,to,'\n')) + { + if (firstline) + std::cout << branch << to << std::endl; + else + std::cout << branch2 << to << std::endl; + firstline = false; + } + + //std::cout << branch << info;// << std::endl; + + // we loop through our daughters + ++depth; + for ( auto& daughter : node->daughter_v ) { + _recursivePrintGraph( daughter, depth, visible_only ); + } + --depth; + return; + } + + /** + * get list of Nodes_t that are decendents of the given trackID + * + * + */ + std::vector MCParticleGraph::getNodeAndDescendentsFromTrackID( const int& trackid ) { + std::vector nodelist; + + MCPGNode* rootnode = findTrackID( trackid ); + if ( rootnode==nullptr ) + return nodelist; + + nodelist.push_back( rootnode ); + recursiveGetNodeAndDescendents( rootnode, nodelist ); + return nodelist; + } + + /** + * recursively get list of Nodes_t that are descendents of the given MCPGNode* + * + * follows depth-first traversal + */ + void MCParticleGraph::recursiveGetNodeAndDescendents( MCPGNode* node, std::vector& nodelist ) { + if ( node==nullptr ) return; + for ( auto& pdaughter : node->daughter_v ) { + nodelist.push_back( pdaughter ); + recursiveGetNodeAndDescendents( pdaughter, nodelist ); + } + return; + } + + /** + * get list of primary particles + * + * by default, neutrons are excluded + * + */ + std::vector MCParticleGraph::getPrimaryParticles( bool exclude_neutrons ) { + std::vector nodelist; + MCPGNode* rootnode = &node_v[0]; + for ( auto& node : node_v ) { + if ( node.mother==rootnode ) { + // primary + if ( !exclude_neutrons || node.pid!=2112 ) { + nodelist.push_back( &node ); + } + } + } + return nodelist; + } + + /** + * get list of neutrino-only primary particles + * + * by default, neutrons are excluded + * + */ + std::vector MCParticleGraph::getNeutrinoPrimaryParticles( bool exclude_neutrons ) { + std::vector nodelist; + MCPGNode* rootnode = &node_v[0]; + for ( auto& node : node_v ) { + if ( node.mother==rootnode && node.origin==1 ) { + // primary + if ( !exclude_neutrons || node.pid!=2112 ) { + nodelist.push_back( &node ); + } + } + } + return nodelist; + } + + /** + * get list of neutrino-only primary particles + * + * by default, neutrons are excluded + * + */ + std::vector MCParticleGraph::getNeutrinoParticles( bool exclude_neutrons ) { + std::vector nodelist; + //MCPGNode* rootnode = &node_v[0]; + for ( auto& node : node_v ) { + if ( node.origin==1 ) { + // neutrino particle + if ( !exclude_neutrons || node.pid!=2112 ) { + nodelist.push_back( &node ); + } + } + } + return nodelist; + } + +// /** +// * convert real position+time and calculate apparent position +// */ +// void MCParticleGraph::_get_imgpos( std::vector& realpos4, +// std::vector& imgpos4, +// larutil::SpaceChargeMicroBooNE& sce, +// bool apply_sce ) +// { + +// imgpos4.resize(4,0); + +// // apparent position according to image +// std::vector dpos(3,0); +// for (int i=0; i<3; i++) { +// dpos[i] = realpos4[i]; +// } + +// std::vector txyz(4,0); +// if ( apply_sce ) { +// std::vector offset = sce.GetPosOffsets( dpos[0], dpos[1], dpos[2] ); +// dpos[0] = dpos[0] - offset[0] + 0.7; +// dpos[1] = dpos[1] + offset[1]; +// dpos[2] = dpos[2] + offset[2]; +// } + +// for (int i=0; i<3; i++) { +// txyz[1+i] = realpos4[i]; +// } +// txyz[0] = realpos4[3]; +// float tick = 0.; +// if (apply_sce) +// tick = CrossingPointsAnaMethods::getTick( txyz, 4050.0, &sce ); +// else +// tick = CrossingPointsAnaMethods::getTick( txyz, 4050.0, NULL ); + +// for (int i=0; i<3; i++) { +// imgpos4[i] = dpos[i]; +// } +// imgpos4[3] = tick; + +// // now make x an apparent x +// imgpos4[0] = (tick-3200)*0.5*larutil::LArProperties::GetME()->DriftVelocity(); + +// } + + /** + * @brief makes a map from daughter track IDs to their mother (shower) track ID + * + * The info comes from the MCShowerObjecs themselves. They store daughter IDs + * in a vector accessed by mcshower::DaughterTrackID(). + * + * This map will let us map the track ids stored in each pixel of the + * the instance ID map to its original shower. + * + */ + void MCParticleGraph::_fill_shower_daughter2mother_map( const std::vector& mcsh_v ) + { + LARCV_DEBUG() << "daughter2mother fill" << std::endl; + _shower_daughter2mother.clear(); + + + for (auto const& mcsh : mcsh_v ) { + int showerid = mcsh.TrackID(); + std::vector dlist = mcsh.DaughterTrackID(); + std::sort( dlist.begin(), dlist.end() ); + for (auto const& daughterid : dlist ) { + _shower_daughter2mother[daughterid]= showerid; + //LARCV_DEBUG() << " " << daughterid << " -> " << showerid << std::endl; + } + } + LARCV_INFO() << "Num entries in daughter2mother map: " << _shower_daughter2mother.size() << std::endl; + } + + int MCParticleGraph::_define_neutrino_interaction_nodes( larlite::storage_manager& ioll ) + { + larlite::event_mctrack* ev_mctrack + = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco"); + larlite::event_mcshower* ev_mcshower + = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco"); + + return _define_neutrino_interaction_nodes( *ev_mctrack, *ev_mcshower ); + } + + int MCParticleGraph::_define_neutrino_interaction_nodes( const larlite::event_mctrack& ev_mctrack, + const larlite::event_mcshower& ev_mcshower ) + { + // first we collect nodes with neutrino origin + bool exclude_neutrons = false; + std::vector< MCPGNode* > _nu_primary_v = getNeutrinoPrimaryParticles( exclude_neutrons ); + LARCV_DEBUG() << "Number of nu primaries returned: " << _nu_primary_v.size() << std::endl; + + // if we have access to MCTruth info, we should use it to define vertex locations. + // otherwise we use some distance threshold. 0.3 mm, the pitch length? + std::map< int, std::set > _nu_collected_primaries_v; + _nu_vertices_v.clear(); + + + for ( auto& pnode : _nu_primary_v ) { + // we test the vertex for every primary + LARCV_DEBUG() << "Considering Nu Primary node[" << pnode->nodeidx << "] tid=" << pnode->tid << std::endl; + + std::vector start = {0,0,0,0}; + + if ( pnode->isTrackObject() ) { + auto const& track = _retrieve_mctrackobject( pnode, ev_mctrack ); + for (int i=0; i<4; i++) { + start[i] = track.Start().Position()[i]; + } + } + else if (pnode->isShowerObject()) { + auto const& shower = _retrieve_mcshowerobject( pnode, ev_mcshower ); + for (int i=0; i<4; i++) { + start[i] = shower.Start().Position()[i]; // creation point in geant4, for photon, not the same as conversion point where visible EM cascade begins + } + } + else if (pnode->isGenieFinalStateObject()) { + start = pnode->start; + } + else { + LARCV_DEBUG() << "Node Primary neither a shower nor track object: " << pnode->nodeidx << std::endl; + LARCV_DEBUG() << "node: " << strNodeInfo( *pnode ) << std::endl; + continue; + } + + bool found_vertex_match = false; + int idx_matched_vertex = -1; + float closest_match = 1e9; + std::vector pos = start; + + LARCV_DEBUG() << "Nu primary start: " << pos[0] << " " << pos[1] << " " << pos[2] << " " << pos[3] << std::endl; + + for ( int idx_vertex=0; idx_vertex<(int)_nu_vertices_v.size(); idx_vertex++ ) { + + auto& vertex = _nu_vertices_v.at(idx_vertex); + + // distance to existing vertex + float dist = 0.; + for (int i=0; i<3; i++) { + dist += ( pos[i]-vertex[i] )*( pos[i]-vertex[i] ); + } + dist = sqrt(dist); + + // update closest match + if ( dist < closest_match ) { + idx_matched_vertex = idx_vertex; + closest_match = dist; + + // qualifies as found? + if ( dist < _kNuVertexDistCutoff_cm ) { + found_vertex_match = true; + idx_matched_vertex = idx_vertex; + } + } + + }//end of loop over established nu vertices + LARCV_DEBUG() << "result of vertex search: closest=" << closest_match << " idx_matched=" << idx_matched_vertex << " found_match=" << found_vertex_match << std::endl; + + if ( !found_vertex_match ) { + // new neutrino vertex defined using position + LARCV_DEBUG() << "New vertex defined." << std::endl; + std::vector new_vertex = { (float)pos[0], (float)pos[1], (float)pos[2], (float)pos[3] }; + _nu_vertices_v.push_back( new_vertex ); + + int nu_vertex_id = (int)_nu_vertices_v.size()-1; // using position in _nu_vertices as an id number (should use a struct I know) + std::set nu_primary_set; + nu_primary_set.insert( pnode->nodeidx ); // add node index + _nu_collected_primaries_v[ nu_vertex_id ] = nu_primary_set; + } + else { + // found match + LARCV_DEBUG() << "Matched primary to existing vertex. IDX=" << idx_matched_vertex << std::endl; + auto it=_nu_collected_primaries_v.find( idx_matched_vertex ); + it->second.insert( pnode->nodeidx ); + } + + }//end of loop over neutrino primaries + + LARCV_DEBUG() << "Number of vertices defined: " << _nu_vertices_v.size() << std::endl; + + if ( _nu_vertices_v.size()==0 ) + return 0; + + // now that we have nu vertices, we need to define a new neutrino ancestor ID, then relabel ancestor IDs for daughters + long max_geant4_trackid = -1; + if ( _nu_vertices_v.size()>0 ) { + for (auto pnode : node_v) { + if ( pnode.tid>max_geant4_trackid ) { + max_geant4_trackid = pnode.tid; + } + } + } + LARCV_DEBUG() << "Starting with max trackid=" << max_geant4_trackid << " to assign nu vertex nodes" << std::endl; + std::set nu_attached_v; // gather list of indices that have been attached to neutrinos + std::vector< MCPGNode* > nu_pnode_v; + + for (int inuvtx=0; inuvtx<(int)_nu_vertices_v.size(); inuvtx++) { + + LARCV_DEBUG() << "Build nu vertex node and assign daughters. [NU VTX IDX=" << inuvtx << "]" << std::endl; + + // get the next node index + int nu_node_idx = (int)node_v.size(); + // need an acceptable fake trackID + long fake_trackid = max_geant4_trackid+1; + max_geant4_trackid++; + int type_id = 2; + int pid = -1; + int mtid = fake_trackid; + float energy = 0.0; + std::string proc = "nuvertex"; + MCPGNode nu_node( nu_node_idx, type_id, fake_trackid, inuvtx, + pid, _eventRootNode, + mtid, energy, proc ); + + nu_node.origin = 1; + nu_node.aid = fake_trackid; + nu_node.mtid = -1; + + // insert into node vector + node_v.emplace_back( std::move(nu_node) ); + + // get pointer + MCPGNode* pnu_node = &(node_v.at(nu_node_idx)); + nu_pnode_v.push_back( pnu_node ); + + // now we need to + // (1) change the nu primaries associated to this interaction + // to list their mother node to this node representing the neutrino interaction + // (2) relabel the ancestor ID of all primary neutrinos to this ID + auto it_prim = _nu_collected_primaries_v.find( inuvtx ); + if ( it_prim==_nu_collected_primaries_v.end() ) + continue; + + for ( auto& nodeidx : it_prim->second ) { + + LARCV_DEBUG() << "Add primary, node=" << nodeidx << ", to nu vertex[" << inuvtx << "]" << std::endl; + + LARCV_DEBUG() << " reassign mother to nu vertex pnode=" << pnu_node << std::endl; + MCPGNode* pnode_nuprim = &(node_v.at(nodeidx)); + pnode_nuprim->mother = pnu_node; + + // collect daughters + std::vector prim_daughters = getNodeAndDescendentsFromTrackID( pnode_nuprim->tid ); + LARCV_DEBUG() << "Collect descendents of nu primary node[ " << nodeidx << "] ndaughters=" << (int)prim_daughters.size()-1 << std::endl; + + // reset the ancestor id of all of these nodes to the new fake track ID for nu interaction + // note: the function above returns the node of the starting track id + for ( auto& pdnode : prim_daughters ) { + pdnode->aid = (int)fake_trackid; + } + + // add this primary to the daughter list of the nu node + pnu_node->daughter_idx_v.push_back( pnode_nuprim->nodeidx ); + pnu_node->daughter_v.push_back( pnode_nuprim ); + LARCV_DEBUG() << "Add to NuVertex node list of daughters: now " << pnu_node->daughter_v.size() << std::endl; + nu_attached_v.insert( pnode_nuprim->nodeidx ); + + // add its E + pnu_node->E_MeV += pnode_nuprim->E_MeV; + LARCV_DEBUG() << "Add to NuVertex energy: now " << pnu_node->E_MeV << " MeV" << std::endl; + }//end of loop over primary node + + nu_attached_v.insert( nu_node_idx ); + + }//end of loop over newly creatd neutrino vertices + + // now we have to redefine the root node's connections + _eventRootNode = &(node_v[0]); + std::vector all_prim_v = getPrimaryParticles(exclude_neutrons); + + _eventRootNode->daughter_idx_v.clear(); + _eventRootNode->daughter_v.clear(); + + + for (auto& pnode : all_prim_v ) { + auto it_attached = nu_attached_v.find( pnode->nodeidx ); + if ( it_attached==nu_attached_v.end() ) { + // not attached to neutrino vertex, so add to root node + _eventRootNode->daughter_idx_v.push_back( pnode->nodeidx ); + _eventRootNode->daughter_v.push_back( pnode ); + } + } + + // attach the nu vertex nodes + for (auto& pnode : nu_pnode_v ) { + _eventRootNode->daughter_idx_v.push_back( pnode->nodeidx ); + _eventRootNode->daughter_v.push_back( pnode ); + } + + return _nu_vertices_v.size(); + } + + +} +} diff --git a/ublarcvapp/MCTools/MCParticleGraph.h b/ublarcvapp/MCTools/MCParticleGraph.h new file mode 100644 index 0000000..964643f --- /dev/null +++ b/ublarcvapp/MCTools/MCParticleGraph.h @@ -0,0 +1,97 @@ +#ifndef __UBLARCVAPP_MCTOOLS_MCPARTICLE_GRAPH_H__ +#define __UBLARCVAPP_MCTOOLS_MCPARTICLE_GRAPH_H__ + +/** + * @ingroup ublarcvapp::mctools + * @class MCParticleGraph + * @brief Store simulated particle information in an event in graph form + * + * We build this graph from larlite::mcshower and larlite::mctrack information. + * These data products come from the larsorft MCReco producer. + */ + +#include +#include + +#include "larcv/core/Base/larcv_base.h" +#include "MCPGNode.h" + +// forward declarations +namespace larlite { + class storage_manager; + class event_mcshower; + class event_mctrack; + class event_mctruth; + class mcshower; + class mctrack; +} + +namespace ublarcvapp { +namespace mctools { + + class MCParticleGraph : public larcv::larcv_base { + + public: + + MCParticleGraph() + : larcv::larcv_base("MCParticleGraph"), + _eventRootNode(nullptr), + _cluster_neutrino_particles(false), + _kNuVertexDistCutoff_cm(0.3) + {}; + + ~MCParticleGraph() + {}; + + void clear(); + void cluster_nu_particles( bool doit=true ) { _cluster_neutrino_particles=doit; }; + void buildgraph( larlite::storage_manager& ioll ); + void buildgraph( const larlite::event_mcshower& shower_v, + const larlite::event_mctrack& track_v, + const larlite::event_mctruth& mctruth_v ); + + MCPGNode* findTrackID( int trackid ); + std::vector getNodeAndDescendentsFromTrackID( const int& trackid ); + std::vector getPrimaryParticles( bool exclude_neutrons ); + std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons ); + std::vector getNeutrinoParticles( bool exclude_neutrons ); + + void printAllNodeInfo(); + std::string strNodeInfo( const MCPGNode& node ); + void printNodeInfo( const MCPGNode& node ); + void printGraph( MCPGNode* rootnode, bool visible_only ); + + + protected: + void recursiveGetNodeAndDescendents( MCPGNode* node, std::vector& nodelist ); + void _recursivePrintGraph( MCPGNode* node, int& depth, bool visible_only ); + const larlite::mctrack& _retrieve_mctrackobject( const MCPGNode* node, const larlite::event_mctrack& ev_track_v ); + const larlite::mcshower& _retrieve_mcshowerobject( const MCPGNode* node, const larlite::event_mcshower& ev_shower_v ); + const larlite::mctrack& _retrieve_mctrackobject( const MCPGNode* node, larlite::storage_manager& ioll, std::string producername="mcreco" ); + const larlite::mcshower& _retrieve_mcshowerobject( const MCPGNode* node, larlite::storage_manager& ioll, std::string producername="mcreco" ); + + + public: + std::vector< MCPGNode > node_v; //< collection of nodes + MCPGNode* _eventRootNode; + bool _cluster_neutrino_particles; //< if true, nu primary particles clustered together + float _kNuVertexDistCutoff_cm; + std::vector< std::vector > _nu_vertices_v; + + std::map _shower_daughter2mother; + + protected: + void _fill_shower_daughter2mother_map( const std::vector& mcsh_v ); + int _define_neutrino_interaction_nodes( larlite::storage_manager& ioll ); + int _define_neutrino_interaction_nodes( const larlite::event_mctrack& ev_mctrack, + const larlite::event_mcshower& ev_mcshower ); + + + + + }; + +} +} + +#endif \ No newline at end of file From 66893322e3b62cb8e82291d4d599e3ac3208c123 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 20 Nov 2025 19:24:03 +0000 Subject: [PATCH 75/80] added lookup map for finding node by trackid. less weird that old method. add testing script for mcparticlegraph --- ublarcvapp/MCTools/MCParticleGraph.cxx | 66 ++++++++------ ublarcvapp/MCTools/MCParticleGraph.h | 4 +- .../MCTools/test/run_mcparticlegraph.py | 85 +++++++++++++++++++ 3 files changed, 128 insertions(+), 27 deletions(-) create mode 100755 ublarcvapp/MCTools/test/run_mcparticlegraph.py diff --git a/ublarcvapp/MCTools/MCParticleGraph.cxx b/ublarcvapp/MCTools/MCParticleGraph.cxx index fc99c32..65ced30 100644 --- a/ublarcvapp/MCTools/MCParticleGraph.cxx +++ b/ublarcvapp/MCTools/MCParticleGraph.cxx @@ -29,6 +29,7 @@ namespace mctools { node_v.clear(); _eventRootNode = nullptr; _shower_daughter2mother.clear(); + _tid_to_node_v.clear(); } /** @@ -469,6 +470,11 @@ namespace mctools { LARCV_INFO() << "Rearranged graph to include neutrino vertex nodes. Number of Nu Interactions: " << nnu << std::endl; } + // map track id to position in node_v container + for (size_t i=0; itid!=dummy.tid ) { - // no node, check the daughter ID map - auto it_showerdaughter = _shower_daughter2mother.find( trackid ); - if ( it_showerdaughter!=_shower_daughter2mother.end() ) { - // found an id - //LARCV_DEBUG() << " found map to mother: " << it_showerdaughter->second << std::endl; - dummy.tid = it_showerdaughter->second; - } - else { - // still nope - return nullptr; - } - // with the mother shower's trackid, try to find the node again - it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); - //if ( it!=node_v.end() ) - // LARCV_DEBUG() << " mother id maps to existing node" << std::endl; - } - - if ( it==node_v.end() || it->tid!=dummy.tid ) { + MCPGNode* MCParticleGraph::findTrackID( long trackid ) { + + auto it = _tid_to_node_v.find( (long)trackid ); + if ( it==_tid_to_node_v.end()) return nullptr; - } - //std::cout << "find trackid=" << trackid << ": " << strNodeInfo( *it ) << std::endl; - return &*(it+0); + + auto& node = node_v.at(it->second); + return &node; + + // MCPGNode dummy; + // dummy.tid = trackid; + // auto it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); + // if ( it==node_v.end() || it->tid!=dummy.tid ) { + // // no node, check the daughter ID map + // auto it_showerdaughter = _shower_daughter2mother.find( trackid ); + // if ( it_showerdaughter!=_shower_daughter2mother.end() ) { + // // found an id + // //LARCV_DEBUG() << " found map to mother: " << it_showerdaughter->second << std::endl; + // dummy.tid = it_showerdaughter->second; + // } + // else { + // // still nope + // return nullptr; + // } + // // with the mother shower's trackid, try to find the node again + // it = std::lower_bound( node_v.begin(), node_v.end(), dummy ); + // //if ( it!=node_v.end() ) + // // LARCV_DEBUG() << " mother id maps to existing node" << std::endl; + // } + + // if ( it==node_v.end() || it->tid!=dummy.tid ) { + // return nullptr; + // } + // //std::cout << "find trackid=" << trackid << ": " << strNodeInfo( *it ) << std::endl; + // return &*(it+0); } /** diff --git a/ublarcvapp/MCTools/MCParticleGraph.h b/ublarcvapp/MCTools/MCParticleGraph.h index 964643f..7cca5a6 100644 --- a/ublarcvapp/MCTools/MCParticleGraph.h +++ b/ublarcvapp/MCTools/MCParticleGraph.h @@ -50,7 +50,7 @@ namespace mctools { const larlite::event_mctrack& track_v, const larlite::event_mctruth& mctruth_v ); - MCPGNode* findTrackID( int trackid ); + MCPGNode* findTrackID( long trackid ); std::vector getNodeAndDescendentsFromTrackID( const int& trackid ); std::vector getPrimaryParticles( bool exclude_neutrons ); std::vector getNeutrinoPrimaryParticles( bool exclude_neutrons ); @@ -72,11 +72,13 @@ namespace mctools { public: + std::vector< MCPGNode > node_v; //< collection of nodes MCPGNode* _eventRootNode; bool _cluster_neutrino_particles; //< if true, nu primary particles clustered together float _kNuVertexDistCutoff_cm; std::vector< std::vector > _nu_vertices_v; + std::map _tid_to_node_v; ///< map from trackid to position in node_v std::map _shower_daughter2mother; diff --git a/ublarcvapp/MCTools/test/run_mcparticlegraph.py b/ublarcvapp/MCTools/test/run_mcparticlegraph.py new file mode 100755 index 0000000..60a65e9 --- /dev/null +++ b/ublarcvapp/MCTools/test/run_mcparticlegraph.py @@ -0,0 +1,85 @@ +#!/bin/env python3 +from __future__ import print_function +import os,sys,argparse + +parser = argparse.ArgumentParser("Test MCPixelPGraph") +parser.add_argument("-ill", "--input-larlite",required=True,type=str,help="Input larlite file") +#parser.add_argument("-adc", "--adc",type=str,default="wire",help="Name of tree with Wire ADC values [default: wire]") +#parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") +parser.add_argument("-d", "--debug", action='store_true', default=False, help="Run in debug mode") +parser.add_argument('-n', "--nentries", required=False, type=int, default=-1, help="number of entries to run") +parser.add_argument('-e', "--entry", required=False, type=int, default=-1, help="start at given entry number") +#parser.add_argument('-v', "--vis", required=False, default=False, action='store_true', help="if flag provided, will visualize event") +parser.add_argument("--cluster-nu",action='store_true',default=False, help="Cluster Nu particles together.") +parser.add_argument('-p','--pause',action='store_true',default=False, help="If provided, pause after each entry") +args = parser.parse_args() + +import ROOT as rt +#from larcv import larcv +from larlite import larlite +from ublarcvapp import ublarcvapp + +""" +test script that demos the MCPixelPGraph class. +""" + +rt.gStyle.SetOptStat(0) + +ioll = larlite.storage_manager( larlite.storage_manager.kREAD ) +ioll.set_data_to_read( "mctrack", "mcreco" ) # larlite.data.kMCTrack +ioll.set_data_to_read( "mcshower", "mcreco" ) # larlite.data.kMCShower +ioll.set_data_to_read( "mctruth", "generator" ) # larlite.data.kMCTruth +ioll.add_in_filename( args.input_larlite ) +ioll.open() + +tot_nentries = ioll.get_entries() +start_entry = 0 +print("Number of entries: ",tot_nentries) +if args.entry > 0: + start_entry = args.entry +if args.nentries>0: + nentries = args.nentries +else: + nentries = tot_nentries +end_entry = start_entry + nentries +if end_entry>tot_nentries: + end_entry = tot_nentries + +print("Start loop.") + +mcpg = ublarcvapp.mctools.MCParticleGraph() +if args.debug: + mcpg.set_verbosity( "debug" ) +else: + mcpg.set_verbosity( "info" ) + + +for ientry in range( start_entry, end_entry ): + + print() + print("="*80) + print("===[ EVENT ",ientry," ]===") + ioll.go_to(ientry) + + mcpg.clear() + if args.cluster_nu: + mcpg.cluster_nu_particles( True ) + else: + mcpg.cluster_nu_particles( False ) + + mcpg.buildgraph( ioll ) + + print("================================================",flush=True) + print("PARSING PARTICLE GRAPH ONLY: No pixel matching ",flush=True) + print("================================================",flush=True) + #print("ALL NODE INFO [NO NU] --------------------------") + #mcpg.printAllNodeInfo() + #print(" -----------------------------------------------") + print("CONSTRUCTED PARTICLE GRAPH",flush=True) + mcpg.printGraph(0,False) + #print("====================================================",flush=True) + if args.pause: + print("[ENTER] to continue",flush=True) + input() + +#print("=== FIN ==",flush=True) From 5a4e0824fc3d593a3b773f338746ed0bed2ae274 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 21 Nov 2025 01:34:32 +0000 Subject: [PATCH 76/80] add simch to pixeltriplet labels --- ublarcvapp/MCTools/CMakeLists.txt | 10 +- ublarcvapp/MCTools/EventMCPixelLabels.cxx | 13 + ublarcvapp/MCTools/EventMCPixelLabels.h | 32 ++ ublarcvapp/MCTools/MCParticleGraph.cxx | 27 ++ ublarcvapp/MCTools/MCParticleGraph.h | 5 +- ublarcvapp/MCTools/MCPixelLabelMaker.cxx | 336 ++++++++++++++++++ ublarcvapp/MCTools/MCPixelLabelMaker.h | 51 +++ ublarcvapp/MCTools/MCPixelLabels.cxx | 0 ublarcvapp/MCTools/MCPixelLabels.h | 56 +++ .../MCTools/test/test_mcpixellabelmaker.py | 43 +++ ublarcvapp/MCTools/test/vis_mcpixellabels.py | 198 +++++++++++ 11 files changed, 769 insertions(+), 2 deletions(-) create mode 100644 ublarcvapp/MCTools/EventMCPixelLabels.cxx create mode 100644 ublarcvapp/MCTools/EventMCPixelLabels.h create mode 100644 ublarcvapp/MCTools/MCPixelLabelMaker.cxx create mode 100644 ublarcvapp/MCTools/MCPixelLabelMaker.h create mode 100644 ublarcvapp/MCTools/MCPixelLabels.cxx create mode 100644 ublarcvapp/MCTools/MCPixelLabels.h create mode 100644 ublarcvapp/MCTools/test/test_mcpixellabelmaker.py create mode 100644 ublarcvapp/MCTools/test/vis_mcpixellabels.py diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 771d23d..0b7d4dd 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -15,7 +15,10 @@ set( HEADERS MCPos2ImageUtils.h LArbysMC.h NeutrinoPixelFilter.h FlashMatcher.h - FlashMatcherV2.h + FlashMatcherV2.h + MCPixelLabels.h + EventMCPixelLabels.h + MCPixelLabelMaker.h MCPixelPMap.h ) # Add sources @@ -31,6 +34,9 @@ add_library( ${LIBNAME} SHARED MCPos2ImageUtils.cxx NeutrinoPixelFilter.cxx FlashMatcher.cxx FlashMatcherV2.cxx + MCPixelLabels.cxx + EventMCPixelLabels.cxx + MCPixelLabelMaker.cxx MCPixelPMap.cxx ) # larlite libraries @@ -47,6 +53,8 @@ target_include_directories(${LIBNAME} PRIVATE ${PROJECT_SOURCE_DIR} ${LARCV_JSON_INCLUDE_DIR} + ${HIGHFIVE_INCLUDE_DIR} + ${HDF5_INCLUDE_DIRS} ) target_link_libraries( ${LIBNAME} PUBLIC diff --git a/ublarcvapp/MCTools/EventMCPixelLabels.cxx b/ublarcvapp/MCTools/EventMCPixelLabels.cxx new file mode 100644 index 0000000..d405b1e --- /dev/null +++ b/ublarcvapp/MCTools/EventMCPixelLabels.cxx @@ -0,0 +1,13 @@ +#include "EventMCPixelLabels.h" + +namespace ublarcvapp { +namespace mctools{ + + void EventMCPixelLabels::clear() + { + _triplets_v.clear(); + _imgcoord_to_tripindex.clear(); + } + +} +} \ No newline at end of file diff --git a/ublarcvapp/MCTools/EventMCPixelLabels.h b/ublarcvapp/MCTools/EventMCPixelLabels.h new file mode 100644 index 0000000..b26783f --- /dev/null +++ b/ublarcvapp/MCTools/EventMCPixelLabels.h @@ -0,0 +1,32 @@ +#ifndef __UBLARCVAPP_MCTOOLS_EVENT_MCPIXEL_LABELS_H__ +#define __UBLARCVAPP_MCTOOLS_EVENT_MCPIXEL_LABELS_H__ + +#include +#include +#include + +#include "MCPixelLabels.h" + +namespace ublarcvapp { +namespace mctools { + +class EventMCPixelLabels { + +public: + + EventMCPixelLabels(){}; + ~EventMCPixelLabels(){}; + + void clear(); + + std::vector _triplets_v; //< container of triplet info + std::map< std::array, unsigned long > _imgcoord_to_tripindex; //< (u,v,y,row) to position in _triplets_v + + //MCPixelLabels& get( int u, int v, int y, ) + +}; + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/MCTools/MCParticleGraph.cxx b/ublarcvapp/MCTools/MCParticleGraph.cxx index 65ced30..1fefaa7 100644 --- a/ublarcvapp/MCTools/MCParticleGraph.cxx +++ b/ublarcvapp/MCTools/MCParticleGraph.cxx @@ -1113,6 +1113,33 @@ namespace mctools { return _nu_vertices_v.size(); } + long MCParticleGraph::getShowerMotherID( long trackid ) + { + auto it = _shower_daughter2mother.find( trackid ); + if ( it!=_shower_daughter2mother.end() ) { + return it->second; + } + return -1; + } + + long MCParticleGraph::getParticleID( long trackid ) + { + auto pnode = findTrackID( trackid ); + if ( pnode==nullptr ) + return -1; + + return pnode->pid; + } + + long MCParticleGraph::getAncestorID( long trackid ) + { + auto pnode = findTrackID( trackid ); + if ( pnode==nullptr ) + return -1; + + return pnode->aid; + } + } } diff --git a/ublarcvapp/MCTools/MCParticleGraph.h b/ublarcvapp/MCTools/MCParticleGraph.h index 7cca5a6..bcab877 100644 --- a/ublarcvapp/MCTools/MCParticleGraph.h +++ b/ublarcvapp/MCTools/MCParticleGraph.h @@ -60,7 +60,10 @@ namespace mctools { std::string strNodeInfo( const MCPGNode& node ); void printNodeInfo( const MCPGNode& node ); void printGraph( MCPGNode* rootnode, bool visible_only ); - + + long getShowerMotherID( long trackid ); + long getAncestorID( long trackid ); + long getParticleID( long trackid ); protected: void recursiveGetNodeAndDescendents( MCPGNode* node, std::vector& nodelist ); diff --git a/ublarcvapp/MCTools/MCPixelLabelMaker.cxx b/ublarcvapp/MCTools/MCPixelLabelMaker.cxx new file mode 100644 index 0000000..b33b092 --- /dev/null +++ b/ublarcvapp/MCTools/MCPixelLabelMaker.cxx @@ -0,0 +1,336 @@ +#include "MCPixelLabelMaker.h" + +#include "larlite/LArUtil/TimeService.h" +#include "larlite/LArUtil/Geometry.h" +#include "larlite/LArUtil/LArProperties.h" +#include "larlite/DataFormat/simch.h" + +#include "larcv/core/DataFormat/EventImage2D.h" + +#include "ublarcvapp/MCTools/MCPos2ImageUtils.h" + +#ifdef HAVE_HIGHFIVE +#include +#endif + +namespace ublarcvapp { +namespace mctools { + + void MCPixelLabelMaker::process( + larlite::storage_manager& ioll, + larcv::IOManager& iolcv, + std::string image2d_tree_name ) + { + + // moving real position to apparent position + larutil::SpaceChargeMicroBooNE* psce = + new larutil::SpaceChargeMicroBooNE(larutil::SpaceChargeMicroBooNE::kMCC9_Forward); + + ublarcvapp::mctools::MCParticleGraph mcpg; + mcpg.buildgraph(ioll); + + make_truthlabels_fromsimch(image2d_tree_name,ioll,iolcv,mcpg,psce); + + } + + void MCPixelLabelMaker::make_truthlabels_fromsimch( + std::string image2d_tree_name, + larlite::storage_manager& ioll, + larcv::IOManager& iolcv, + ublarcvapp::mctools::MCParticleGraph& mcpg, + larutil::SpaceChargeMicroBooNE* psce ) + { + + LARCV_INFO() << "start" << std::endl; + + // utility to go from simulated electronics TDC to + // ticks (tdcs after readout trigger) + const larutil::TimeService* timeservice = larutil::TimeService::GetME(); + + // geometry + const larutil::Geometry* geom = larutil::Geometry::GetME(); + + + // drift velocity + float driftv = larutil::LArProperties::GetME()->DriftVelocity(); + + // get the simch product we need + larlite::event_simch* ev_simch = + (larlite::event_simch*)ioll.get_data(larlite::data::kSimChannel,"largeant"); + + // get images + larcv::EventImage2D* ev_img = + (larcv::EventImage2D*)iolcv.get_data(larcv::kProductImage2D,image2d_tree_name); + + auto const& img_v = ev_img->as_vector(); + int nplanes = (int)img_v.size(); + + auto const& meta0 = img_v.at(0).meta(); + + // Clear the triplet info container + _pixels_v.clear(); + + // loop over simch information, making TripletLabels_t + size_t nsimch = ev_simch->size(); + size_t ide_w_no_t0 = 0; + size_t ide_outofimg = 0; + size_t ide_w_badwire = 0; + size_t num_ide_used = 0; + + for (size_t isimch=0; isimchat(isimch); + auto chid = simch.Channel(); + + larlite::geo::WireID wireid = geom->ChannelToWireID(chid); + int plane = wireid.Plane; + + //std::cout << "(" << isimch << ") chid=" << chid << " plane=" << plane << std::endl; + + auto& idcmap = simch.TDCIDEMap(); + for ( auto it=idcmap.begin(); it!=idcmap.end(); it++ ) { + long tdc = it->first; + int tick = int(timeservice->TPCTDC2Tick(tdc)); + size_t nide = it->second.size(); + for (auto& ide : it->second ) { + + std::vector pos = { ide.x, ide.y, ide.z }; + long tid = ide.trackID; + long xtid = (tid>=0) ? tid : -tid; + double edep = ide.energy; + + // get wire coordinates for these positions + std::vector wire_v(nplanes,0); + bool bad_wire = false; + for (int iplane=0; iplaneNearestWire( pos, iplane ); + wire_v[iplane] = wireid; + } + catch (...){ + bad_wire = true; + } + } + if ( bad_wire ) { + ide_w_badwire++; + continue; + } + + // replace low-energy shower trackid label with mother of the shower + long mtid = mcpg.getShowerMotherID( tid ); + if (mtid>0) { + xtid = mtid; + } + + auto pnode_t = mcpg.findTrackID( xtid ); + if ( pnode_t==nullptr ) { + // don't have an alternative for this right now + ide_w_no_t0++; + continue; + } + + long aid = mcpg.getAncestorID( xtid ); + int pid = pnode_t->pid; + int origin = pnode_t->origin; + + double t0 = pnode_t->start.at(3); + + bool applied = false; + std::vector pos_sce = psce->ApplySpaceChargeEffect( pos[0], pos[1], pos[2], applied ); + + // get (u,v,y,tick) + std::vector imgpos = + ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( pos[0], + pos[1], + pos[2], + t0, + true ); + + float tick = imgpos[3]; + if ( tick<(float)meta0.min_y() || tick>=(float)meta0.max_y() ) { + ide_outofimg++; + continue; + } + + int row = meta0.row( imgpos[3] ); + + std::array imgindex = { + (int)imgpos[0], + (int)imgpos[1], + (int)imgpos[2], + row }; + + auto it_index = _pixels_v._imgcoord_to_tripindex.find( imgindex ); + if ( it_index==_pixels_v._imgcoord_to_tripindex.end() ) { + MCPixelLabels trip; + trip.index = (long)_pixels_v._triplets_v.size(); + for (int i=0; i<3; i++) + trip.edep[i] = 0.0; + trip.imgcoord[0] = imgindex[0]; + trip.imgcoord[1] = imgindex[1]; + trip.imgcoord[2] = imgindex[2]; + trip.imgcoord[3] = (int)tick; + trip.imgcoord[4] = row; + trip.pos[0] = pos[0]; + trip.pos[1] = pos[1]; + trip.pos[2] = pos[2]; + trip.pos_reco[0] = (tick-3200)*0.5*driftv; + trip.pos_reco[1] = pos_sce[1]; + trip.pos_reco[2] = pos_sce[2]; + + // make index map + _pixels_v._imgcoord_to_tripindex[imgindex] = trip.index; + + // we also index stuff + for (int iu=-1; iu<=1; iu++) { + for (int iv=-1; iv<=1; iv++) { + for (int iy=-1; iy<=1; iy++) { + for (int ir=-1; ir<=1; ir++) { + std::array modindex = imgindex; + modindex[0] += iu; + modindex[1] += iv; + modindex[2] += iy; + modindex[3] += ir; + auto it_mod = _pixels_v._imgcoord_to_tripindex.find( modindex ); + if ( it_mod==_pixels_v._imgcoord_to_tripindex.end()) { + _pixels_v._imgcoord_to_tripindex[modindex] = trip.index; + } + } + } + } + } + + _pixels_v._triplets_v.emplace_back( std::move(trip) ); + it_index = _pixels_v._imgcoord_to_tripindex.find( imgindex ); + } + + auto& tripinfo = _pixels_v._triplets_v.at(it_index->second); + tripinfo.edep[plane] += edep; + tripinfo.trackids.insert(xtid); + tripinfo.aids.insert(aid); + tripinfo.pids.insert(pid); + tripinfo.origin.insert(origin); + num_ide_used++; + + } + + } + } + + LARCV_INFO() << "Number of Triplets Created: " << _pixels_v._triplets_v.size() << std::endl; + LARCV_INFO() << " IDEs with no track ID match and t0: " << ide_w_no_t0 << std::endl; + LARCV_INFO() << " IDEs out-of-image: " << ide_outofimg << std::endl; + LARCV_INFO() << " IDEs with no nearby-wire: " << ide_w_badwire << std::endl; + LARCV_INFO() << " IDEs used: " << num_ide_used << std::endl; + + + } + + void MCPixelLabelMaker::export_as_hdf( std::string hdf_outfile ) + { + +#ifdef HAVE_HIGHFIVE + + LARCV_INFO() << "export to " << hdf_outfile << std::endl; + + HighFive::File file(hdf_outfile, HighFive::File::Overwrite); + + file.createGroup("/mcpixel_labels"); + + // export different arrays for export + int ntriplets = _pixels_v._triplets_v.size(); + + std::vector pos_x(ntriplets,0); + std::vector pos_y(ntriplets,0); + std::vector pos_z(ntriplets,0); + + std::vector pos_x_reco(ntriplets,0); + std::vector pos_y_reco(ntriplets,0); + std::vector pos_z_reco(ntriplets,0); + + std::vector< std::array > edep(ntriplets); + std::vector trackid(ntriplets,0); + std::vector pid(ntriplets,0); + std::vector aid(ntriplets,0); + std::vector origin(ntriplets,0); + std::vector uwire(ntriplets,0); + std::vector vwire(ntriplets,0); + std::vector ywire(ntriplets,0); + std::vector tick(ntriplets,0); + std::vector row(ntriplets,0); + + for (auto const& triplet : _pixels_v._triplets_v ) { + long idx = triplet.index; + + pos_x[idx] = triplet.pos[0]; + pos_y[idx] = triplet.pos[1]; + pos_z[idx] = triplet.pos[2]; + + pos_x_reco[idx] = triplet.pos_reco[0]; + pos_y_reco[idx] = triplet.pos_reco[1]; + pos_z_reco[idx] = triplet.pos_reco[2]; + + edep[idx] = std::array{0,0,0}; + for (int i=0; i<3; i++) + edep[idx][i] = triplet.edep[i]; + + for ( auto& tid : triplet.trackids ) { + trackid[idx] = tid; + if (trackid[idx]!=-1) + break; + } + + for ( auto& xpid : triplet.pids ) { + pid[idx] = xpid; + if (pid[idx]!=-1) + break; + } + + for ( auto& xaid : triplet.aids ) { + aid[idx] = xaid; + if (aid[idx]!=-1) + break; + } + + for ( auto& xorigin : triplet.origin ) { + origin[idx] = xorigin; + if (origin[idx]!=-1) + break; + } + + uwire[idx] = triplet.imgcoord[0]; + vwire[idx] = triplet.imgcoord[1]; + ywire[idx] = triplet.imgcoord[2]; + tick[idx] = triplet.imgcoord[4]; + row[idx] = triplet.imgcoord[3]; + } + + H5Easy::dump( file, "/mcpixel_labels/pos_x", pos_x); + H5Easy::dump( file, "/mcpixel_labels/pos_y", pos_y); + H5Easy::dump( file, "/mcpixel_labels/pos_z", pos_z); + + H5Easy::dump( file, "/mcpixel_labels/pos_x_reco", pos_x_reco); + H5Easy::dump( file, "/mcpixel_labels/pos_y_reco", pos_y_reco); + H5Easy::dump( file, "/mcpixel_labels/pos_z_reco", pos_z_reco); + + H5Easy::dump( file, "/mcpixel_labels/edep", edep); + H5Easy::dump( file, "/mcpixel_labels/trackid", trackid); + H5Easy::dump( file, "/mcpixel_labels/pid", pid); + H5Easy::dump( file, "/mcpixel_labels/aid", aid); + H5Easy::dump( file, "/mcpixel_labels/origin", origin); + H5Easy::dump( file, "/mcpixel_labels/uwire", uwire); + H5Easy::dump( file, "/mcpixel_labels/vwire", vwire); + H5Easy::dump( file, "/mcpixel_labels/ywire", ywire); + H5Easy::dump( file, "/mcpixel_labels/tick", tick); + H5Easy::dump( file, "/mcpixel_labels/row", row); + + file.flush(); + +#else + LARCV_CRITICAL() << "Compiled without HDF5 support." << std::endl; +#endif + + } + + +} +} \ No newline at end of file diff --git a/ublarcvapp/MCTools/MCPixelLabelMaker.h b/ublarcvapp/MCTools/MCPixelLabelMaker.h new file mode 100644 index 0000000..974cf54 --- /dev/null +++ b/ublarcvapp/MCTools/MCPixelLabelMaker.h @@ -0,0 +1,51 @@ +#ifndef __UBLARCVAPP_MCTOOLS_MCPIXEL_LABEL_MAKER_H__ +#define __UBLARCVAPP_MCTOOLS_MCPIXEL_LABEL_MAKER_H__ + +#include +#include + +#include "larcv/core/Base/larcv_base.h" +#include "larcv/core/DataFormat/IOManager.h" +#include "larlite/DataFormat/storage_manager.h" +#include "larlite/LArUtil/SpaceChargeMicroBooNE.h" + +#include "ublarcvapp/MCTools/MCParticleGraph.h" + +#include "EventMCPixelLabels.h" + +namespace ublarcvapp { +namespace mctools { + +class MCPixelLabelMaker : public larcv::larcv_base { + +public: + + MCPixelLabelMaker() + : larcv::larcv_base("MCPixelLabelMaker") + {}; + + virtual ~MCPixelLabelMaker() {}; + + void process( larlite::storage_manager& ioll, + larcv::IOManager& iolcv, + std::string image2d_tree_name ); + + void make_truthlabels_fromsimch( + std::string image2d_tree_name, + larlite::storage_manager& ioll, + larcv::IOManager& iolcv, + ublarcvapp::mctools::MCParticleGraph& mcpg, + larutil::SpaceChargeMicroBooNE* psce ); + + void export_as_hdf(std::string hdf_outfile); + + EventMCPixelLabels _pixels_v; + + +}; + +} +} + + +#endif \ No newline at end of file diff --git a/ublarcvapp/MCTools/MCPixelLabels.cxx b/ublarcvapp/MCTools/MCPixelLabels.cxx new file mode 100644 index 0000000..e69de29 diff --git a/ublarcvapp/MCTools/MCPixelLabels.h b/ublarcvapp/MCTools/MCPixelLabels.h new file mode 100644 index 0000000..ba24a76 --- /dev/null +++ b/ublarcvapp/MCTools/MCPixelLabels.h @@ -0,0 +1,56 @@ +#ifndef __UBLARCVAPP_MCTOOLS_MCPIXELLABELS_H__ +#define __UBLARCVAPP_MCTOOLS_MCPIXELLABELS_H__ + +#include +#include +#include + +namespace ublarcvapp { +namespace mctools { + +class MCPixelLabels { + +public: + + MCPixelLabels() + : index(-1), + imgcoord({-1,-1,-1,-1,-1}), + pos({0,0,0}), + pos_reco({0,0,0}), + edep({0.0,0.0,0.0}), + pixval({0,0,0}) + { + trackids.clear(); + aids.clear(); + pids.clear(); + origin.clear(); + }; + + ~MCPixelLabels() {}; + + long index; ///< book-keeping label + + std::array imgcoord; //< wire plane image coordinates (u,v,y,row,tick) + std::array pos; //< true energy deposition + std::array pos_reco; //< position as it appears when reco'd from wire plane images + + std::array edep; //< energy deposited as seen per wire plane + std::array pixval; //< pixel value at wire plane + + std::set trackids; //< track IDs contributing to edep position + std::set aids; //< ancestor track ID + std::set pids; //< particle ID + std::set origin; //< origin ID: 1=neutrino, 2=cosmic, 0=other + + int tick() { return imgcoord[4]; }; + int row() { return imgcoord[3]; }; + int numTrackIDs() { return trackids.size(); }; + + +}; + + +} +} + +#endif \ No newline at end of file diff --git a/ublarcvapp/MCTools/test/test_mcpixellabelmaker.py b/ublarcvapp/MCTools/test/test_mcpixellabelmaker.py new file mode 100644 index 0000000..0a1f1da --- /dev/null +++ b/ublarcvapp/MCTools/test/test_mcpixellabelmaker.py @@ -0,0 +1,43 @@ +import os,sys +import argparse + +parser = argparse.ArgumentParser("Test MCPixelLabelMaker") +parser.add_argument("-i", "--input-dlmerged",required=True,type=str,help="Input larlite file") +parser.add_argument('-e', "--entry", required=True, type=int, default=0, help="entry to process") +parser.add_argument("-adc", "--adc", required=False, type=str,default="wiremc",help="Name of tree with Wire ADC values [default: wiremc]") +parser.add_argument("-tb", "--tick-backward",action='store_true',default=False,help="Input LArCV data is tick-backward [default: false]") +parser.add_argument("-d", "--debug", action='store_true', default=False, help="Run in debug mode") +#parser.add_argument('-n', "--nentries", required=False, type=int, default=-1, help="number of entries to run") +parser.add_argument('-o', "--output-hdf5", required=False, default="", help="if provided, will save data to HDF5 file") +args = parser.parse_args() + + +from larlite import larlite +from larcv import larcv +from ublarcvapp import ublarcvapp + +#input_dlmerged = "/mnt/ddrive/data/ub_on_tufts/corsika_bnb_nu_pi0/dlmerged_coriska_bnb_nu_pi0_fileno000001.root" +input_dlmerged = args.input_dlmerged + +ENTRY=args.entry + +mcpixel_label_maker = ublarcvapp.mctools.MCPixelLabelMaker() +mcpixel_label_maker.set_verbosity(1) + +ioll = larlite.storage_manager( larlite.storage_manager.kREAD ) +ioll.add_in_filename( input_dlmerged ) +ioll.set_verbosity(2) +ioll.open() + +iolcv = larcv.IOManager( larcv.IOManager.kREAD, "larcv" ) +iolcv.add_in_file( input_dlmerged ) +iolcv.set_verbosity(2) +iolcv.initialize() + +ioll.go_to(ENTRY) +iolcv.read_entry(ENTRY) + +mcpixel_label_maker.process( ioll, iolcv, args.adc ) + +if args.output_hdf5!="": + mcpixel_label_maker.export_as_hdf(args.output_hdf5) diff --git a/ublarcvapp/MCTools/test/vis_mcpixellabels.py b/ublarcvapp/MCTools/test/vis_mcpixellabels.py new file mode 100644 index 0000000..99169d8 --- /dev/null +++ b/ublarcvapp/MCTools/test/vis_mcpixellabels.py @@ -0,0 +1,198 @@ +import os,sys +import argparse +import h5py +import numpy as np +import dash +import dash_core_components as dcc +import dash_html_components as html +from dash.dependencies import Input, Output, State +from dash.exceptions import PreventUpdate + +parser = argparse.ArgumentParser("Visualize HDF5 output from MCPixelLabels") +parser.add_argument("-i", "--input",required=True,type=str,help="Input HDF5 file.") +parser.add_argument("-c", "--colorby", default='trackid', help="Color mode. Option: [instance,ancestor,edep]") +parser.add_argument("-p", "--pos-mode", default="true",type=str,help="Position mode. Option: [true,reco]") +args = parser.parse_args() + +import lardly +from lardly.detectoroutline import DetectorOutline + +fh5 = h5py.File(args.input, 'r') + +opacity=0.8 +marker_size=1.0 + +colorby_options = ['edep','trackid'] +pos_mode_options = ['true','reco'] + +if args.colorby not in colorby_options: + print("Color Mode option given is invalid. Options: ",colorby_options) + sys.exit(0) + +if args.pos_mode not in pos_mode_options: + print("Position Mode option invalid. Options: ",pos_mode_options) + sys.exit(0) + +#colorby = 'edep' +#colorby = 'trackid' +#colorby = 'hasmatch' +colorby = args.colorby +pos_var = args.pos_mode +#pos_var='true' +#pos_var='reco' + +#NMAX_RECO_PTS=50000 +NMAX_RECO_PTS=-1 + +triplet_truth = fh5['mcpixel_labels'] + +columns = ['pos_x','pos_y','pos_z', + 'pos_x_reco','pos_y_reco','pos_z_reco', + 'edep', + 'trackid', + 'pid', + 'aid', + 'origin', + 'uwire', + 'vwire', + 'ywire', + 'tick', + 'row'] + +data = {} + +for col in columns: + npts = len(triplet_truth[col]) + data[col] = np.array( triplet_truth[col], dtype=np.float32 ) + if len(data[col].shape)==1: + data[col] = data[col].reshape((npts,1)) + print(col,": ",data[col].shape) + +detdata = DetectorOutline() +customdata = np.concatenate( [data['pid'],data['trackid'],data['aid'],data['edep']],axis=1 ) +print("customdata: ",customdata.shape) + +hovertemplate = """ +x: %{x:.1f}
+y: %{y:.1f}
+z: %{z:.1f}
+PID: %{customdata[0]:d}
+TID: %{customdata[1]:d}
+AID: %{customdata[2]:d}
+edep: %{customdata[3]:.3f}, %{customdata[4]:.3f} , %{customdata[5]:.3f} MeV
+""" + +if pos_var=='reco': + pos_var_x = 'pos_x_reco' + pos_var_y = 'pos_y_reco' + pos_var_z = 'pos_z_reco' +else: + pos_var_x = 'pos_x' + pos_var_y = 'pos_y' + pos_var_z = 'pos_z' + +source = data + +simch_plots = [] +if colorby=='edep': + simch_plot = { + "type":"scatter3d", + "x":source[pos_var_x][:,0], + "y":source[pos_var_y][:,0], + "z":source[pos_var_z][:,0], + "mode":"markers", + "name":f"edep", + "hovertemplate":hovertemplate, + "customdata":customdata, + "marker":{"color":source['edep'][:,0],"opacity":opacity,"size":marker_size,'colorscale':'Viridis','cmin':0.0,'cmax':5.0} + } + simch_plots.append(simch_plot) +elif colorby=='trackid': + itrackid = source['trackid'][:,0].astype(np.int64) + unique_ids = np.unique( itrackid ) + for tid in unique_ids: + if tid<=0: + continue + mask = itrackid==tid + xcolor = np.random.randint(0,255,3) + scolor=f'rgba({xcolor[0]},{xcolor[1]},{xcolor[2]},1)' + simch_plot = { + "type":"scatter3d", + "x":source[pos_var_x][mask[:],0], + "y":source[pos_var_y][mask[:],0], + "z":source[pos_var_z][mask[:],0], + "mode":"markers", + "name":f"tid[{tid}]", + "hovertemplate":hovertemplate, + "customdata":customdata[mask[:],:], + "marker":{"color":scolor,"opacity":opacity,"size":marker_size} + } + simch_plots.append(simch_plot) +# elif colorby=='hasmatch': +# simch_plot = { +# "type":"scatter3d", +# "x":source['pos_x'][:,0], +# "y":source['pos_y'][:,0], +# "z":source['pos_z'][:,0], +# "mode":"markers", +# "name":f"recopts", +# "marker":{"color":source['hasmatch'][:,0],"opacity":opacity,"size":marker_size,'colorscale':'Viridis'}, +# #"marker":{"color":"rgba(220,220,220,1)","opacity":opacity,"size":marker_size} +# } +# simch_plots.append( simch_plot ) +else: + print("unknown color option: ",colorby) + sys.exit(0) + +traces = detdata.getlines()+simch_plots + +app = dash.Dash( + __name__, + meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}], +) + +server = app.server + +axis_template = { + "showbackground": True, + "backgroundcolor": "#141414", + "gridcolor": "rgb(255, 255, 255)", + "zerolinecolor": "rgb(255, 255, 255)", +} + +plot_layout = { + "title": "", + "height":800, + "margin": {"t": 0, "b": 0, "l": 0, "r": 0}, + "font": {"size": 12, "color": "white"}, + "showlegend": False, + "plot_bgcolor": "#141414", + "paper_bgcolor": "#141414", + "scene": { + "xaxis": axis_template, + "yaxis": axis_template, + "zaxis": axis_template, + "aspectratio": {"x": 1, "y": 1, "z": 4}, + "camera": {"eye": {"x": 2, "y": 2, "z": 2}, + "up":dict(x=0, y=1, z=0)}, + "annotations": [], + }, +} + +app.layout = html.Div( [ + html.Div( [ + dcc.Graph( + id="det3d", + figure={ + "data": traces, + "layout": plot_layout, + }, + config={"editable": True, "scrollZoom": False}, + )], + className="graph__container"), + ] ) + +app.run_server(debug=True) + + + From e91e9371b3e09a45f70395a807df55d2151b87ba Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Fri, 21 Nov 2025 01:40:34 +0000 Subject: [PATCH 77/80] add hdf5 dependency --- CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d677cf5..75d8110 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,39 @@ else() message(STATUS "Boost not found") endif (Boost_FOUND) +#---HDF5 (for machine learning data output) +find_package(HDF5 COMPONENTS C CXX QUIET) +if(HDF5_FOUND) + message(STATUS "Found HDF5: ${HDF5_VERSION}") + add_compile_definitions(HAVE_HDF5) +else() + message(STATUS "HDF5 not found, HDF5 output features will be disabled") +endif() + +#---HighFive (header-only HDF5 C++ interface) +if(HDF5_FOUND) + # Try to find HighFive as an installed package first + find_package(HighFive QUIET) + if(NOT HighFive_FOUND) + # If not found, check if it exists as a submodule or in a known location + if(EXISTS "$ENV{UBDL_BASEDIR}/extern/highfive/include") + set(HIGHFIVE_INCLUDE_DIR "$ENV{UBDL_BASEDIR}/extern/highfive/include") + message(STATUS "Found HighFive headers at: ${HIGHFIVE_INCLUDE_DIR}") + set(HighFive_FOUND TRUE) + else() + message(STATUS "HighFive not found. To use HDF5 features, please:") + message(STATUS " 1. Install HighFive: https://github.com/highfive-devs/highfive/tree/main ") + message(STATUS " 2. Or add as submodule: git submodule add https://github.com/highfive-devs/highfive/tree/main extern/highfive") + endif() + else() + message(STATUS "Found HighFive package") + endif() + + if(HighFive_FOUND) + add_compile_definitions(HAVE_HIGHFIVE) + endif() +endif() + #--- glog #find_package(glog REQUIRED) From 6127e2723b5f01fb0977756261a174b48458d153 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Tue, 2 Dec 2025 23:40:30 +0000 Subject: [PATCH 78/80] debugged. support simch from driftWC simpleSC product which makes better true edep points --- ublarcvapp/MCTools/MCPGNode.h | 7 +- ublarcvapp/MCTools/MCParticleGraph.cxx | 36 +++++++ ublarcvapp/MCTools/MCPixelLabelMaker.cxx | 128 ++++++++++++++++++----- ublarcvapp/MCTools/MCPixelLabelMaker.h | 28 ++++- ublarcvapp/MCTools/MCPixelPGraph.cxx | 2 +- 5 files changed, 167 insertions(+), 34 deletions(-) diff --git a/ublarcvapp/MCTools/MCPGNode.h b/ublarcvapp/MCTools/MCPGNode.h index 0297969..e253c13 100644 --- a/ublarcvapp/MCTools/MCPGNode.h +++ b/ublarcvapp/MCTools/MCPGNode.h @@ -29,7 +29,8 @@ namespace mctools { std::vector start; //< (x,y,z,t) before sce, true start of particle std::vector first_edep_pos; //< (x,y,z,t) before sce, first step that leaves edep in cryostat std::vector first_tpc_pos; //< (x,y,z,t) before sce, first step inside the TPC, visible in the image - + std::vector mom4; //< (E,px,py,pz) + int origin; // 1=neutrino, 2=cosmic, 0=unassigned, -1=unassigned MCPGNode() @@ -46,7 +47,8 @@ namespace mctools { process("null"), start({0,0,0,0}), first_edep_pos({0,0,0,0}), - first_tpc_pos({0,0,0,0}), + first_tpc_pos({0,0,0,0}), + mom4({0,0,0,0}), origin(-1) { daughter_v.clear(); @@ -73,6 +75,7 @@ namespace mctools { start({0,0,0,0}), first_edep_pos({0,0,0,0}), first_tpc_pos({0,0,0,0}), + mom4({0,0,0,0}), origin(-1) { daughter_v.clear(); diff --git a/ublarcvapp/MCTools/MCParticleGraph.cxx b/ublarcvapp/MCTools/MCParticleGraph.cxx index 1fefaa7..0fdea65 100644 --- a/ublarcvapp/MCTools/MCParticleGraph.cxx +++ b/ublarcvapp/MCTools/MCParticleGraph.cxx @@ -168,6 +168,15 @@ namespace mctools { tracknode.start[1] = mct.Start().Y(); tracknode.start[2] = mct.Start().Z(); tracknode.start[3] = mct.Start().T(); + try { + tracknode.mom4[0] = mct.Start().E(); + tracknode.mom4[1] = mct.Start().Px(); + tracknode.mom4[2] = mct.Start().Py(); + tracknode.mom4[3] = mct.Start().Pz(); + } + catch (...) { + tracknode.mom4 = std::vector{0,0,0,0}; + } if ( tracknode.origin==1 ) { // store nu particle @@ -256,6 +265,16 @@ namespace mctools { showernode.first_edep_pos = std::vector(4,0); showernode.first_tpc_pos = std::vector(4,0); + try { + showernode.mom4[0] = mcsh.Start().E(); + showernode.mom4[1] = mcsh.Start().Px(); + showernode.mom4[2] = mcsh.Start().Py(); + showernode.mom4[3] = mcsh.Start().Pz(); + } + catch (...) { + showernode.mom4 = std::vector{0,0,0,0}; + } + bool x_isinf = false; if ( mcsh.DetProfile().X()>1.0e100 || mcsh.DetProfile().X()<-1.0e100 ) x_isinf = true; @@ -379,6 +398,16 @@ namespace mctools { fsnode.mtid = tid; fsnode.aid = tid; fsnode.origin = 1; // neutrino origin (from genie) + + try { + for (int i=0; i<3; i++) + fsnode.mom4[i+1] = part.Momentum(0)[i]; + fsnode.mom4[0] = part.Momentum(0)[3]; + } + catch (...) { + fsnode.mom4 = std::vector{0,0,0,0}; + } + LARCV_DEBUG() << "Add Genie Final State Particle to initial List: tid=" << tid << " pdg=" << pid << std::endl; node_v.emplace_back( std::move(fsnode) ); } @@ -659,6 +688,13 @@ namespace mctools { << node.first_tpc_pos[2] << "," << node.first_tpc_pos[3]*1.0e-3 << " us)" << std::endl; + + if ( node.mom4.size()>=4 ) + ss << " mom4(E,px,py,pz)=(" << node.mom4[0] << "," + << node.mom4[1] << "," + << node.mom4[2] << "," + << node.mom4[3] << ") " + << " MeV" << std::endl; //ss << std::endl; diff --git a/ublarcvapp/MCTools/MCPixelLabelMaker.cxx b/ublarcvapp/MCTools/MCPixelLabelMaker.cxx index b33b092..d0feeda 100644 --- a/ublarcvapp/MCTools/MCPixelLabelMaker.cxx +++ b/ublarcvapp/MCTools/MCPixelLabelMaker.cxx @@ -16,6 +16,19 @@ namespace ublarcvapp { namespace mctools { + MCPixelLabelMaker::~MCPixelLabelMaker() + { + if ( psce ) { + delete psce; + psce = nullptr; + } + + if ( preverse_sce ) { + delete preverse_sce; + preverse_sce = nullptr; + } + } + void MCPixelLabelMaker::process( larlite::storage_manager& ioll, larcv::IOManager& iolcv, @@ -23,8 +36,9 @@ namespace mctools { { // moving real position to apparent position - larutil::SpaceChargeMicroBooNE* psce = - new larutil::SpaceChargeMicroBooNE(larutil::SpaceChargeMicroBooNE::kMCC9_Forward); + if ( psce==nullptr ) { + psce = new larutil::SpaceChargeMicroBooNE(larutil::SpaceChargeMicroBooNE::kMCC9_Forward); + } ublarcvapp::mctools::MCParticleGraph mcpg; mcpg.buildgraph(ioll); @@ -56,7 +70,7 @@ namespace mctools { // get the simch product we need larlite::event_simch* ev_simch = - (larlite::event_simch*)ioll.get_data(larlite::data::kSimChannel,"largeant"); + (larlite::event_simch*)ioll.get_data(larlite::data::kSimChannel,source); // get images larcv::EventImage2D* ev_img = @@ -132,32 +146,70 @@ namespace mctools { int pid = pnode_t->pid; int origin = pnode_t->origin; - double t0 = pnode_t->start.at(3); + double t0 = pnode_t->start.at(3); // in ns - bool applied = false; - std::vector pos_sce = psce->ApplySpaceChargeEffect( pos[0], pos[1], pos[2], applied ); - // get (u,v,y,tick) - std::vector imgpos = - ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( pos[0], - pos[1], - pos[2], - t0, - true ); + std::vector pos_sce(3,0); + std::vector imgpos(4,0); // (U,V,Y,tick) + int row = -1; + std::array imgindex = {-1,-1,-1,-1}; - float tick = imgpos[3]; - if ( tick<(float)meta0.min_y() || tick>=(float)meta0.max_y() ) { - ide_outofimg++; - continue; - } + if ( source=="largeant" ) { + + bool applied = false; + pos_sce = psce->ApplySpaceChargeEffect( pos[0], pos[1], pos[2], applied ); + + // get (u,v,y,tick) + std::vector imgpos = + ublarcvapp::mctools::MCPos2ImageUtils::Get()->truepos_to_imagepos( pos[0], + pos[1], + pos[2], + t0, + true ); + pos[0] = (tick-3200)*0.5*driftv; + tick = (int)imgpos[3]; + if ( tick<(int)meta0.min_y() || tick>=(int)meta0.max_y() ) { + ide_outofimg++; + continue; + } - int row = meta0.row( imgpos[3] ); + row = meta0.row( imgpos[3] ); - std::array imgindex = { - (int)imgpos[0], - (int)imgpos[1], - (int)imgpos[2], - row }; + imgindex = { + (int)imgpos[0], + (int)imgpos[1], + (int)imgpos[2], + row }; + } + else if ( source=="driftWC:simpleSC:Detsim") { + if ( preverse_sce == nullptr ) { + preverse_sce = new larutil::SpaceChargeMicroBooNE(larutil::SpaceChargeMicroBooNE::kMCC9_Backward); + } + // the (y,z) is post spacecharge effect and x is drifted to the wireplanes + float x_t0_offset = (t0*1.0e-3)*driftv; + x_t0_offset = 0.0; + pos_sce[0] = float(tick-3200)*0.5*driftv - x_t0_offset; + pos_sce[1] = pos[1]; + pos_sce[2] = pos[2]; + pos[0] = pos_sce[0]; + + for (int p=0; p<3; p++) { + imgpos[p] = wire_v[p]; + imgindex[p] = wire_v[p]; + } + imgpos[3] = tick; + if ( tick<(int)meta0.min_y() || tick>=(int)meta0.max_y() ) { + ide_outofimg++; + continue; + } + row = meta0.row( tick ); + imgindex[3] = row; + } + else { + std::stringstream errmsg; + errmsg << "unrecognized simch source: " << source << std::endl; + throw std::runtime_error(errmsg.str()); + } auto it_index = _pixels_v._imgcoord_to_tripindex.find( imgindex ); if ( it_index==_pixels_v._imgcoord_to_tripindex.end() ) { @@ -173,7 +225,7 @@ namespace mctools { trip.pos[0] = pos[0]; trip.pos[1] = pos[1]; trip.pos[2] = pos[2]; - trip.pos_reco[0] = (tick-3200)*0.5*driftv; + trip.pos_reco[0] = pos_sce[0]; trip.pos_reco[1] = pos_sce[1]; trip.pos_reco[2] = pos_sce[2]; @@ -181,10 +233,10 @@ namespace mctools { _pixels_v._imgcoord_to_tripindex[imgindex] = trip.index; // we also index stuff - for (int iu=-1; iu<=1; iu++) { - for (int iv=-1; iv<=1; iv++) { - for (int iy=-1; iy<=1; iy++) { - for (int ir=-1; ir<=1; ir++) { + for (int iu=-dwire; iu<=dwire; iu++) { + for (int iv=-dwire; iv<=dwire; iv++) { + for (int iy=-dwire; iy<=dwire; iy++) { + for (int ir=-drow; ir<=drow; ir++) { std::array modindex = imgindex; modindex[0] += iu; modindex[1] += iv; @@ -194,6 +246,24 @@ namespace mctools { if ( it_mod==_pixels_v._imgcoord_to_tripindex.end()) { _pixels_v._imgcoord_to_tripindex[modindex] = trip.index; } + else { + // found a previous record + int new_dindex = std::abs(iu)+std::abs(iv)+std::abs(iy)+std::abs(ir); + + if ( new_dindex!=0 ) { + auto& oldtrip = _pixels_v._triplets_v.at( it_mod->second ); + int old_dindex = 0; + for (int ii=0; ii<3; ii++) { + old_dindex += std::abs( imgindex[ii]-oldtrip.imgcoord[ii] ); + } + old_dindex += std::abs( imgindex[3]-oldtrip.imgcoord[4] ); + + if ( new_dindex<=old_dindex ) { + // replace index + _pixels_v._imgcoord_to_tripindex[modindex] = trip.index; + } + } + } } } } diff --git a/ublarcvapp/MCTools/MCPixelLabelMaker.h b/ublarcvapp/MCTools/MCPixelLabelMaker.h index 974cf54..280f6d5 100644 --- a/ublarcvapp/MCTools/MCPixelLabelMaker.h +++ b/ublarcvapp/MCTools/MCPixelLabelMaker.h @@ -3,6 +3,7 @@ #include #include +#include #include "larcv/core/Base/larcv_base.h" #include "larcv/core/DataFormat/IOManager.h" @@ -21,10 +22,15 @@ class MCPixelLabelMaker : public larcv::larcv_base { public: MCPixelLabelMaker() - : larcv::larcv_base("MCPixelLabelMaker") + : larcv::larcv_base("MCPixelLabelMaker"), + dwire(1), + drow(1), + source("largeant"), + preverse_sce(nullptr), + psce(nullptr) {}; - virtual ~MCPixelLabelMaker() {}; + virtual ~MCPixelLabelMaker(); void process( larlite::storage_manager& ioll, larcv::IOManager& iolcv, @@ -37,10 +43,28 @@ class MCPixelLabelMaker : public larcv::larcv_base { ublarcvapp::mctools::MCParticleGraph& mcpg, larutil::SpaceChargeMicroBooNE* psce ); + void set_dwire( int dwiremod ) { dwire=std::abs(dwiremod); }; + + void set_drow( int drowmod ) { drow=std::abs(drowmod); }; + + void set_largeant_source() { source="largeant"; }; + + void set_driftwc_source() { source="driftWC:simpleSC:Detsim"; }; + void export_as_hdf(std::string hdf_outfile); + void clear() { + _pixels_v.clear(); + }; + EventMCPixelLabels _pixels_v; + int dwire; ///< create copies of MCPixelLabels with triplet indices with modified wire index, wire+dwire + int drow; ///< create copies of MCPixelLabels with triplet indices with modified row index, row+drow + std::string source; + larutil::SpaceChargeMicroBooNE* preverse_sce; + larutil::SpaceChargeMicroBooNE* psce; + }; diff --git a/ublarcvapp/MCTools/MCPixelPGraph.cxx b/ublarcvapp/MCTools/MCPixelPGraph.cxx index 213f599..f25e820 100644 --- a/ublarcvapp/MCTools/MCPixelPGraph.cxx +++ b/ublarcvapp/MCTools/MCPixelPGraph.cxx @@ -85,7 +85,7 @@ namespace mctools { const std::vector& segment_v, const std::vector& instance_v, const std::vector& ancestor_v, - const std::vector& larflow_v, + const std::vector& larflow_v, const larlite::event_mcshower& shower_v, const larlite::event_mctrack& track_v, const larlite::event_mctruth& mctruth_v ) From 403d5c96e281cc4b94c960fa6809a758984808bc Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 4 Dec 2025 14:02:02 +0000 Subject: [PATCH 79/80] add c std lib for size_t --- ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h index 0e476e2..394ce7d 100644 --- a/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h +++ b/ublarcvapp/UBPhotonLib/PhotonVisibilityEstimator.h @@ -3,6 +3,7 @@ #include #include +#include namespace ublarcvapp { namespace ubphotonlib { @@ -111,4 +112,4 @@ namespace ubphotonlib { } } -#endif \ No newline at end of file +#endif From b2bf0543e63adea874c758bf186a31bc6f62c255 Mon Sep 17 00:00:00 2001 From: Taritree Wongjirad Date: Thu, 4 Dec 2025 18:49:41 +0000 Subject: [PATCH 80/80] make explicit the hdf5 we link against. this is important to use the conda hdf5 library in the pointcept container --- ublarcvapp/MCTools/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ublarcvapp/MCTools/CMakeLists.txt b/ublarcvapp/MCTools/CMakeLists.txt index 0b7d4dd..aa6ab26 100644 --- a/ublarcvapp/MCTools/CMakeLists.txt +++ b/ublarcvapp/MCTools/CMakeLists.txt @@ -58,11 +58,12 @@ target_include_directories(${LIBNAME} ) target_link_libraries( ${LIBNAME} PUBLIC - ${LARLITE_LIBS_USED} + ${LARLITE_LIBS_USED} LArCVCoreBase LArCVCoreDataFormat LArCVCoreProcessor ${UBLARCVAPP_LIBS_USED} + ${HDF5_LIBRARIES} ) # includes for ROOT dictionary gen