diff --git a/CMakeLists.txt b/CMakeLists.txt index 329d7b072..5606dd72f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ find_package(ifdh_art REQUIRED ) find_package(Range-v3 REQUIRED ) find_package(sbnalg REQUIRED ) find_package(sbnobj REQUIRED ) +find_package(sbnanaobj REQUIRED ) +find_package(sbncode REQUIRED) find_package(icarus_signal_processing REQUIRED ) find_package(icarusalg REQUIRED ) find_package(icarusutil REQUIRED ) diff --git a/icaruscode/CMakeLists.txt b/icaruscode/CMakeLists.txt index 606f87f42..f05aa4911 100644 --- a/icaruscode/CMakeLists.txt +++ b/icaruscode/CMakeLists.txt @@ -15,4 +15,5 @@ add_subdirectory(RecoUtils) add_subdirectory(TPC) add_subdirectory(Utilities) add_subdirectory(Overlays) +add_subdirectory(WireMod) #add_subdirectory(Supera) diff --git a/icaruscode/WireMod/CMakeLists.txt b/icaruscode/WireMod/CMakeLists.txt new file mode 100644 index 000000000..1c605d42f --- /dev/null +++ b/icaruscode/WireMod/CMakeLists.txt @@ -0,0 +1,312 @@ +set(EXCLUDED_PLUGINS WireModMakeHists_plugin.cc ROICounter_module.cc HitComp_plugin.cc HitTTreeMaker_plugin.cc WireModifier_module.cc WireModifierXXW_module.cc WireModHitDiagnostic_module.cc WireModScaleDebug_module.cc) + +art_make( + LIB_LIBRARIES + ${ART_FRAMEWORK_CORE} + art_Utilities canvas + ${MF_MESSAGELOGGER} + + cetlib cetlib_except + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + MODULE_LIBRARIES + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + lardata::Utilities + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + EXCLUDE ${EXCLUDED_PLUGINS} + #WireMod_Utilities.hh + #WireMod_Utilities.cc + ) + +find_library( sbncode::sbncode_WireMod_Utility_LIBRARY NAMES sbncode::sbncode_WireMod_Utility ) + +simple_plugin(WireModMakeHists "plugin" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + BASENAME_ONLY +) + +simple_plugin(HitComp "plugin" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + BASENAME_ONLY +) + +simple_plugin(HitTTreeMaker "plugin" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + BASENAME_ONLY +) + +cet_build_plugin(ROICounter art::module + LIBRARIES + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + ) + +simple_plugin(WireModifier "module" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + larcore::Geometry_Geometry_service + larcorealg::Geometry + lardataalg::DetectorInfo + lardata::Utilities + lardata::DetectorInfoServices_DetectorClocksServiceStandard_service + sbnobj::ICARUS_TPC + sbncode::WireMod_Utility + BASENAME_ONLY +) + +simple_plugin(WireModifierXXW "module" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + larcore::Geometry_Geometry_service + larcorealg::Geometry + lardataalg::DetectorInfo + lardata::Utilities + lardata::DetectorInfoServices_DetectorClocksServiceStandard_service + sbnobj::ICARUS_TPC + sbncode::WireMod_Utility + BASENAME_ONLY +) + +simple_plugin(WireModHitDiagnostic "module" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + BASENAME_ONLY +) + +simple_plugin(WireModScaleDebug "module" + ${ART_FRAMEWORK_CORE} + ${MF_MESSAGELOGGER} + ${Boost_SYSTEM_LIBRARY} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + art_root_io::TFileService_service + lardataobj::AnalysisBase + lardataobj::RawData + lardataobj::RecoBase + lardata::RecoObjects + larreco::RecoAlg + ${LARRECO_LIB} + ${LARDATA_LIB} + ${ART_FRAMEWORK_CORE} + ${ART_FRAMEWORK_PRINCIPAL} + ${ART_FRAMEWORK_SERVICES_REGISTRY} + ${ART_FRAMEWORK_SERVICES_OPTIONAL} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_RANDOMNUMBERGENERATOR_SERVICE} + ${ART_FRAMEWORK_SERVICES_OPTIONAL_TFILESERVICE_SERVICE} + ${MF_MESSAGELOGGER} + ${FHICLCPP} + ${CLHEP} + ${ROOT_GEOM} + ${ROOT_XMLIO} + ${ROOT_GDML} + ${ROOT_BASIC_LIB_LIST} + ${ROOT_HIST} + larcore::Geometry_Geometry_service + larcorealg::Geometry + BASENAME_ONLY +) + +install_headers() +install_fhicl() +install_source() +FILE(GLOB ratios *.root ) +install(FILES ${ratios} DESTINATION root/WireMod) diff --git a/icaruscode/WireMod/HitComp.fcl b/icaruscode/WireMod/HitComp.fcl new file mode 100644 index 000000000..f43fcd0a0 --- /dev/null +++ b/icaruscode/WireMod/HitComp.fcl @@ -0,0 +1,10 @@ +BEGIN_PROLOG + +standard_hitcomp: +{ + plugin_type: "HitComp" + Label: "gaushit1dTPCEE" + Process: "MCstage0Var" +} + +END_PROLOG diff --git a/icaruscode/WireMod/HitComp_plugin.cc b/icaruscode/WireMod/HitComp_plugin.cc new file mode 100644 index 000000000..3d53a6fc9 --- /dev/null +++ b/icaruscode/WireMod/HitComp_plugin.cc @@ -0,0 +1,286 @@ +//std includes +#include +#include + +//ROOT includes +#include "TF1.h" +#include "TFile.h" +#include "TFitResult.h" +#include "TFitResultPtr.h" +#include "TH1.h" +#include "TH2.h" +#include "TProfile.h" + +//Framework includes +#include "art/Framework/Core/ResultsProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Results.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "art_root_io/TFileDirectory.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "canvas/Utilities/InputTag.h" +#include "larcore/Geometry/Geometry.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/TrackHitMeta.h" +#include "lardataobj/RecoBase/Hit.h" +#include "lardataobj/RecoBase/Wire.h" + +namespace WireMod { + class HitComp : public art::ResultsProducer { + public: + explicit HitComp(fhicl::ParameterSet const& pset); + ~HitComp() override = default; + void event(art::Event const& evt) override; + void reconfigure(fhicl::ParameterSet const& p); + void writeResults(art::Results& r) override; + void clear() override; + + private: + const geo::GeometryCore* fGeometry = lar::providerFrom(); // get the geometry + const geo::WireReadoutGeom* fWireReadout = &(art::ServiceHandle()->Get()); + const double fPi = std::acos(-1); // get pi so I don't have to care later + + art::InputTag fTag; // how the hits/wires are labeled in the input file + TH1D* fHitHeightPlane0; // how tall do the hits look? (1st Ind) + TH1D* fHitWidthPlane0; // how wide do the hits look? (1st Ind) + TH1D* fHitChi2perDOFPlane0; // how well are the hits fit? (1st Ind) + TH2D* fHitHeightVsWidthPlane0; // 2D height vs width distributions (1st Ind) + TH1D* fHitHeightPlane1; // how tall do the hits look? (2nd Ind) + TH1D* fHitWidthPlane1; // how wide do the hits look? (2nd Ind) + TH1D* fHitChi2perDOFPlane1; // how well are the hits fit? (2nd Ind) + TH2D* fHitHeightVsWidthPlane1; // 2D height vs width distributions (2nd Ind) + TH1D* fHitHeightPlane2; // how tall do the hits look? (Collection) + TH1D* fHitWidthPlane2; // how wide do the hits look? (Collection) + TH1D* fHitChi2perDOFPlane2; // how well are the hits fit? (Collection) + TH2D* fHitHeightVsWidthPlane2; // 2D height vs width distributions (Collection) + bool fUseTrackOnly; // do we want to only use hits from tacks? + TH2D* fHitHeightVsThXYPlane0; // 2D height vs ThXY distributions (1st Ind) + TH2D* fHitHeightVsThYZPlane0; // 2D height vs ThYZ distributions (1st Ind) + TH2D* fHitWidthVsThXYPlane0; // 2D width vs ThXY distributions (1st Ind) + TH2D* fHitWidthVsThYZPlane0; // 2D width vs ThYZ distributions (1st Ind) + TH2D* fHitHeightVsThXYPlane1; // 2D height vs ThXY distributions (2nd Ind) + TH2D* fHitHeightVsThYZPlane1; // 2D height vs ThYZ distributions (2nd Ind) + TH2D* fHitWidthVsThXYPlane1; // 2D width vs ThXY distributions (2nd Ind) + TH2D* fHitWidthVsThYZPlane1; // 2D width vs ThYZ distributions (2nd Ind) + TH2D* fHitHeightVsThXYPlane2; // 2D height vs ThXY distributions (Collection) + TH2D* fHitHeightVsThYZPlane2; // 2D height vs ThYZ distributions (Collection) + TH2D* fHitWidthVsThXYPlane2; // 2D width vs ThXY distributions (Collection) + TH2D* fHitWidthVsThYZPlane2; // 2D width vs ThYZ distributions (Collection) + + };// end HitComp class + + //------------------------------------------------------------- + // Define the constructor + // The way ART works is it will call the construct on the fhicl parameter set + // Basically we want it to pull out the variables we defined there + // We're doing this in the reconfigure function (because that makes it clearer what we are doing imo) + // so just call that function + HitComp::HitComp(fhicl::ParameterSet const& pset) + { + this->reconfigure(pset); + } + + //------------------------------------------------------------- + // this function pulls out the stuff we defined in the fhicl file + void HitComp::reconfigure(fhicl::ParameterSet const& pset) + { + // the first arguement is where in the fhicl to look, the second is the default value if that isn't found + std::string label = pset.get("Label" , "gaushitTPCEE"); + std::string process = pset.get("Process", "pMCstage0Var"); + fUseTrackOnly = pset.get("UseTrackOnly", false); + mf::LogVerbatim("HitComp") + << "Getting hits with label " << label << " from process " << process; + std::string tpcStr = (fUseTrackOnly) ? label.substr(label.size() - 1) : label.substr(label.size() - 2); + mf::LogVerbatim("HitComp") + << " These are in the " << tpcStr << " TPC"; + fTag = art::InputTag(label, {}, process); + + art::ServiceHandle tfs; + if (fUseTrackOnly) + { + fHitHeightPlane0 = tfs->make(("HitHeight_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane0 = tfs->make(("HitWidth_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane0 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane0 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, 0, 100, 1000, 0, 100); + fHitHeightPlane1 = tfs->make(("HitHeight_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane1 = tfs->make(("HitWidth_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane1 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane1 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, 0, 100, 1000, 0, 100); + fHitHeightPlane2 = tfs->make(("HitHeight_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane2 = tfs->make(("HitWidth_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane2 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane2 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, 0, 100, 1000, 0, 100); + fHitHeightVsThXYPlane0 = tfs->make(("HitHeightVsThXY_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;#theta^{}_{XY} (radians);Hit Peak Amplitude (ADC Units)").c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitHeightVsThYZPlane0 = tfs->make(("HitHeightVsThYZ_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;#theta^{}_{YZ} (radians);Hit Peak Amplitude (ADC Units)").c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThXYPlane0 = tfs->make(("HitWidthVsThXY_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;#theta^{}_{XY} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThYZPlane0 = tfs->make(("HitWidthVsThYZ_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" Cryostat 1^{st}_{} Induction;#theta^{}_{YZ} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitHeightVsThXYPlane1 = tfs->make(("HitHeightVsThXY_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;#theta^{}_{XY} (radians);Hit Peak Amplitude (ADC Units)").c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitHeightVsThYZPlane1 = tfs->make(("HitHeightVsThYZ_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;#theta^{}_{YZ} (radians);Hit Peak Amplitude (ADC Units)").c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThXYPlane1 = tfs->make(("HitWidthVsThXY_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;#theta^{}_{XY} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThYZPlane1 = tfs->make(("HitWidthVsThYZ_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" Cryostat 2^{nd}_{} Induction;#theta^{}_{YZ} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitHeightVsThXYPlane2 = tfs->make(("HitHeightVsThXY_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;#theta^{}_{XY} (radians);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitHeightVsThYZPlane2 = tfs->make(("HitHeightVsThYZ_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;#theta^{}_{YZ} (radians);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThXYPlane2 = tfs->make(("HitWidthVsThXY_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;#theta^{}_{XY} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + fHitWidthVsThYZPlane2 = tfs->make(("HitWidthVsThYZ_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" Cryostat Collection;#theta^{}_{YZ} (radians);Hit Width (Ticks)" ).c_str(), 1000, -1*fPi, fPi, 1000, 0, 100); + } else { + fHitHeightPlane0 = tfs->make(("HitHeight_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" TPC 1^{st}_{} Induction;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane0 = tfs->make(("HitWidth_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" TPC 1^{st}_{} Induction;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane0 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_1stInd").c_str(), (tpcStr+" TPC 1^{st}_{} Induction;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane0 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_1stInd").c_str(), (tpcStr+" TPC 1^{st}_{} Induction;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)").c_str(), 1000, 0, 100, 1000, 0, 100); + fHitHeightPlane1 = tfs->make(("HitHeight_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" TPC 2^{nd}_{} Induction;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane1 = tfs->make(("HitWidth_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" TPC 2^{nd}_{} Induction;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane1 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_2ndInd").c_str(), (tpcStr+" TPC 2^{nd}_{} Induction;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane1 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_2ndInd").c_str(), (tpcStr+" TPC 2^{nd}_{} Induction;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)").c_str(), 1000, 0, 100, 1000, 0, 100); + fHitHeightPlane2 = tfs->make(("HitHeight_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" TPC Collection;Hit Peak Amplitude (ADC Units);Number of Hits" ).c_str(), 1000, 0, 100); + fHitWidthPlane2 = tfs->make(("HitWidth_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" TPC Collection;Hit Width (Ticks);Number of Hits" ).c_str(), 1000, 0, 100); + fHitChi2perDOFPlane2 = tfs->make(("HitChi2perDOF_" +process+"_"+label+"_Collec").c_str(), (tpcStr+" TPC Collection;Hit Height #chi^{2}_{}/DOF;Number of Hits" ).c_str(), 1000, 0, 100); + fHitHeightVsWidthPlane2 = tfs->make(("HitHeightVsWidth_"+process+"_"+label+"_Collec").c_str(), (tpcStr+" TPC Collection;Hit Width (Ticks);Hit Peak Amplitude (ADC Units)" ).c_str(), 1000, 0, 100, 1000, 0, 100); + } + } + + //------------------------------------------------------------- + // this function is run on every event in the art file + // the event stores the information we want to analyze + void HitComp::event(art::Event const& evt) + { + // DEBUGGING + mf::LogVerbatim("HitComp") + << "List InputTags for std::vector" << '\n' << "looking for" << fTag; + for (auto const& tag : evt.getInputTags>()) + { + mf::LogVerbatim("HitComp") + << " " << tag; + if (tag == fTag) + { + mf::LogVerbatim("HitComp") + << " MATCH!"; + } else { + mf::LogVerbatim("HitComp") + << " NOT A MATCH"; + } + } + // DEBUGGING + + // with or without tracks? + if (fUseTrackOnly) + { + // get the tracks and the associations for the hits + art::Handle> trackHandle; + evt.getByLabel(fTag, trackHandle); + art::FindManyP hitsFromTracks(trackHandle, evt, fTag); + + // loop over tracks, get the hits and the metadata + for (size_t trackIdx = 0; trackIdx < trackHandle->size(); ++trackIdx) + { + art::Ptr track(trackHandle, trackIdx); + std::vector> trackHits = hitsFromTracks.at(track.key()); + std::vector trackMetas = hitsFromTracks.data(track.key()); + + for (size_t hitIdx = 0; hitIdx < trackHits.size(); ++hitIdx) + { + art::Ptr hit = trackHits.at(hitIdx); + const recob::TrackHitMeta* meta = trackMetas.at(hitIdx); + + // get the info + size_t hitInTrack = meta->Index(); + if (hitInTrack == std::numeric_limits::max() || not track->HasValidPoint(hitInTrack)) + continue; + geo::PlaneID planeID = hit->WireID().planeID(); + geo::PlaneGeo planeGeo = fWireReadout->Plane(planeID); + double trackDirX = track->DirectionAtPoint(hitInTrack).X(); + double trackDirY = track->DirectionAtPoint(hitInTrack).Y(); + double trackDirZ = track->DirectionAtPoint(hitInTrack).Z(); + double planeCosTh = std::cos(planeGeo.ThetaZ()); + double planeSinTh = std::sin(planeGeo.ThetaZ()); + double relDirX = trackDirX; + double relDirY = trackDirY * planeCosTh - trackDirZ * planeSinTh; + double relDirZ = trackDirZ * planeCosTh + trackDirY * planeSinTh; + double planeThXY = std::atan2(relDirY, relDirX); + double planeThYZ = std::atan2(relDirY, relDirZ); + + // fill hists + if (planeID.Plane == 0) + { + fHitHeightPlane0 ->Fill(hit->PeakAmplitude()); + fHitWidthPlane0 ->Fill(hit->RMS()); + fHitChi2perDOFPlane0 ->Fill(hit->GoodnessOfFit()); + fHitHeightVsWidthPlane0->Fill(hit->RMS(), hit->PeakAmplitude()); + fHitHeightVsThXYPlane0 ->Fill(planeThXY, hit->PeakAmplitude()); + fHitHeightVsThYZPlane0 ->Fill(planeThYZ, hit->PeakAmplitude()); + fHitWidthVsThXYPlane0 ->Fill(planeThXY, hit->RMS()); + fHitWidthVsThYZPlane0 ->Fill(planeThYZ, hit->RMS()); + } else if (planeID.Plane == 1) { + fHitHeightPlane1 ->Fill(hit->PeakAmplitude()); + fHitWidthPlane1 ->Fill(hit->RMS()); + fHitChi2perDOFPlane1 ->Fill(hit->GoodnessOfFit()); + fHitHeightVsWidthPlane1->Fill(hit->RMS(), hit->PeakAmplitude()); + fHitHeightVsThXYPlane1 ->Fill(planeThXY, hit->PeakAmplitude()); + fHitHeightVsThYZPlane1 ->Fill(planeThYZ, hit->PeakAmplitude()); + fHitWidthVsThXYPlane1 ->Fill(planeThXY, hit->RMS()); + fHitWidthVsThYZPlane1 ->Fill(planeThYZ, hit->RMS()); + } else if (planeID.Plane == 2) { + fHitHeightPlane2 ->Fill(hit->PeakAmplitude()); + fHitWidthPlane2 ->Fill(hit->RMS()); + fHitChi2perDOFPlane2 ->Fill(hit->GoodnessOfFit()); + fHitHeightVsWidthPlane2->Fill(hit->RMS(), hit->PeakAmplitude()); + fHitHeightVsThXYPlane2 ->Fill(planeThXY, hit->PeakAmplitude()); + fHitHeightVsThYZPlane2 ->Fill(planeThYZ, hit->PeakAmplitude()); + fHitWidthVsThXYPlane2 ->Fill(planeThXY, hit->RMS()); + fHitWidthVsThYZPlane2 ->Fill(planeThYZ, hit->RMS()); + } + } + } + } else { + // get the recob::Hits + art::Handle> hitHandle; + evt.getByLabel(fTag, hitHandle); + + // loop over the wires + for (auto const& hit : *hitHandle) + { + geo::PlaneID planeID = hit.WireID().planeID(); + if (planeID.Plane == 0) + { + fHitHeightPlane0 ->Fill(hit.PeakAmplitude()); + fHitWidthPlane0 ->Fill(hit.RMS()); + fHitChi2perDOFPlane0 ->Fill(hit.GoodnessOfFit()); + fHitHeightVsWidthPlane0->Fill(hit.RMS(), hit.PeakAmplitude()); + } else if (planeID.Plane == 1) { + fHitHeightPlane1 ->Fill(hit.PeakAmplitude()); + fHitWidthPlane1 ->Fill(hit.RMS()); + fHitChi2perDOFPlane1 ->Fill(hit.GoodnessOfFit()); + fHitHeightVsWidthPlane1->Fill(hit.RMS(), hit.PeakAmplitude()); + } else if (planeID.Plane == 2) { + fHitHeightPlane2 ->Fill(hit.PeakAmplitude()); + fHitWidthPlane2 ->Fill(hit.RMS()); + fHitChi2perDOFPlane2 ->Fill(hit.GoodnessOfFit()); + fHitHeightVsWidthPlane2->Fill(hit.RMS(), hit.PeakAmplitude()); + } + } + } + } + + //------------------------------------------------------------- + // writeResults is currently unused, but we still need to define it + // just have it do nothing for now + void HitComp::writeResults(art::Results& r) + { + } + + //------------------------------------------------------------- + // lear is currently unused, but we still need to define it + // just have it do nothing for now + void HitComp::clear() + { + } + + DEFINE_ART_RESULTS_PLUGIN(HitComp) +}// end WireMod namespace diff --git a/icaruscode/WireMod/HitTTreeMaker.fcl b/icaruscode/WireMod/HitTTreeMaker.fcl new file mode 100644 index 000000000..51440bedb --- /dev/null +++ b/icaruscode/WireMod/HitTTreeMaker.fcl @@ -0,0 +1,10 @@ +BEGIN_PROLOG + +standard_hitttreemaker: +{ + plugin_type: "HitTTreeMaker" + Label: "gaushit1dTPCEE" + Process: "MCStage0Var" +} + +END_PROLOG diff --git a/icaruscode/WireMod/HitTTreeMaker_plugin.cc b/icaruscode/WireMod/HitTTreeMaker_plugin.cc new file mode 100644 index 000000000..721a7c942 --- /dev/null +++ b/icaruscode/WireMod/HitTTreeMaker_plugin.cc @@ -0,0 +1,201 @@ +//std includes +#include +#include + +//ROOT includes +#include "TF1.h" +#include "TFile.h" +#include "TFitResult.h" +#include "TFitResultPtr.h" +#include "TH1.h" +#include "TH2.h" +#include "TProfile.h" +#include "TTree.h" + +//Framework includes +#include "art/Framework/Core/ResultsProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Results.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "art_root_io/TFileDirectory.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "canvas/Utilities/InputTag.h" +#include "larcore/Geometry/Geometry.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/TrackHitMeta.h" +#include "lardataobj/RecoBase/Hit.h" +#include "lardataobj/RecoBase/Wire.h" + +namespace WireMod { + class HitTTreeMaker : public art::ResultsProducer { + public: + explicit HitTTreeMaker(fhicl::ParameterSet const& pset); + ~HitTTreeMaker() override = default; + void event(art::Event const& evt) override; + void reconfigure(fhicl::ParameterSet const& p); + void reset_values(); + void writeResults(art::Results& r) override; + void clear() override; + + private: + const geo::GeometryCore* fGeometry = lar::providerFrom(); // get the geometry + const double fPi = std::acos(-1); // get pi so I don't have to care later + + art::InputTag fTag; // how the hits/wires are labeled in the input file + bool fUseTrackOnly; // do we want to only use hits from tacks? + TTree* fHitTree; // where we store the info + + // TTree Branches + geo::WireID fWireID = geo::WireID(geo::CryostatID::InvalidID, geo::TPCID::InvalidID, geo::PlaneID::InvalidID, geo::WireID::InvalidID); // the ID of the wire the hit was on + double fHitAmplitude = std::numeric_limits::quiet_NaN(); // how tall was the hit? + double fHitWidth = std::numeric_limits::quiet_NaN(); // how wide was the hit? + double fHitGoF = std::numeric_limits::quiet_NaN(); // how good was the hit fit? + bool fFromTrack = false; // was the hit from a track? + double fTrackDirX = std::numeric_limits::quiet_NaN(); // track direction (in GLOBAL coordinates) + double fTrackDirY = std::numeric_limits::quiet_NaN(); // track direction (in GLOBAL coordinates) + double fTrackDirZ = std::numeric_limits::quiet_NaN(); // track direction (in GLOBAL coordinates) + + };// end HitTTreeMaker class + + //------------------------------------------------------------- + // Define the constructor + // The way ART works is it will call the construct on the fhicl parameter set + // Basically we want it to pull out the variables we defined there + // We're doing this in the reconfigure function (because that makes it clearer what we are doing imo) + // so just call that function + HitTTreeMaker::HitTTreeMaker(fhicl::ParameterSet const& pset) + { + this->reconfigure(pset); + } + + //------------------------------------------------------------- + // this function pulls out the stuff we defined in the fhicl file + void HitTTreeMaker::reconfigure(fhicl::ParameterSet const& pset) + { + // the first arguement is where in the fhicl to look, the second is the default value if that isn't found + std::string label = pset.get("Label" , "gaushitTPCEE"); + std::string process = pset.get("Process", "MCstage0Var" ); + fUseTrackOnly = pset.get("UseTrackOnly", false); + mf::LogVerbatim("HitTTreeMaker") + << "Getting hits with label " << label << " from process " << process; + std::string tpcStr = (fUseTrackOnly) ? label.substr(label.size() - 1) : label.substr(label.size() - 2); + mf::LogVerbatim("HitTTreeMaker") + << " These are in the " << tpcStr << " TPC"; + fTag = art::InputTag(label, {}, process); + + // set up the output TTree + art::ServiceHandle tfs; + std::string treeName = label + "_" + process; + std::string treeTitle = (fUseTrackOnly) ? "Hits From Tracks" : "All Hits"; + fHitTree = tfs->make(treeName.c_str(), treeTitle.c_str()); + fHitTree->Branch("WireID" , &fWireID); + fHitTree->Branch("Amplitude" , &fHitAmplitude); + fHitTree->Branch("Width" , &fHitWidth); + fHitTree->Branch("GoodnessOfFit", &fHitGoF); + fHitTree->Branch("IsTrackHit" , &fFromTrack); + fHitTree->Branch("TrackDirX" , &fTrackDirX); + fHitTree->Branch("TrackDirY" , &fTrackDirY); + fHitTree->Branch("TrackDirZ" , &fTrackDirZ); + } + + //------------------------------------------------------------- + // Reset the values for our TTree + void HitTTreeMaker::reset_values() + { + fWireID = geo::WireID(geo::CryostatID::InvalidID, geo::TPCID::InvalidID, geo::PlaneID::InvalidID, geo::WireID::InvalidID); + fHitAmplitude = std::numeric_limits::quiet_NaN(); + fHitWidth = std::numeric_limits::quiet_NaN(); + fHitGoF = std::numeric_limits::quiet_NaN(); + fFromTrack = false; + fTrackDirX = std::numeric_limits::quiet_NaN(); + fTrackDirY = std::numeric_limits::quiet_NaN(); + fTrackDirZ = std::numeric_limits::quiet_NaN(); + } + + //------------------------------------------------------------- + // this function is run on every event in the art file + // the event stores the information we want to analyze + void HitTTreeMaker::event(art::Event const& evt) + { + + // with or without tracks? + if (fUseTrackOnly) + { + // get the tracks and the associations for the hits + art::Handle> trackHandle; + evt.getByLabel(fTag, trackHandle); + art::FindManyP hitsFromTracks(trackHandle, evt, fTag); + + // loop over tracks, get the hits and the metadata + for (size_t trackIdx = 0; trackIdx < trackHandle->size(); ++trackIdx) + { + art::Ptr track(trackHandle, trackIdx); + std::vector> trackHits = hitsFromTracks.at(track.key()); + std::vector trackMetas = hitsFromTracks.data(track.key()); + + for (size_t hitIdx = 0; hitIdx < trackHits.size(); ++hitIdx) + { + art::Ptr hit = trackHits.at(hitIdx); + const recob::TrackHitMeta* meta = trackMetas.at(hitIdx); + + // get the info + size_t hitInTrack = meta->Index(); + if (hitInTrack == std::numeric_limits::max() || not track->HasValidPoint(hitInTrack)) + continue; + + fWireID = hit->WireID(); + fHitAmplitude = hit->PeakAmplitude(); + fHitWidth = hit->RMS(); + fHitGoF = hit->GoodnessOfFit(); + fFromTrack = true; + fTrackDirX = track->DirectionAtPoint(hitInTrack).X(); + fTrackDirY = track->DirectionAtPoint(hitInTrack).Y(); + fTrackDirZ = track->DirectionAtPoint(hitInTrack).Z(); + + fHitTree->Fill(); + + this->reset_values(); + } + } + } else { + // get the recob::Hits + art::Handle> hitHandle; + evt.getByLabel(fTag, hitHandle); + + // loop over the wires + for (auto const& hit : *hitHandle) + { + fWireID = hit.WireID(); + fHitAmplitude = hit.PeakAmplitude(); + fHitWidth = hit.RMS(); + fHitGoF = hit.GoodnessOfFit(); + + fHitTree->Fill(); + + this->reset_values(); + } + } + } + + //------------------------------------------------------------- + // writeResults is currently unused, but we still need to define it + // just have it do nothing for now + void HitTTreeMaker::writeResults(art::Results& r) + { + } + + //------------------------------------------------------------- + // lear is currently unused, but we still need to define it + // just have it do nothing for now + void HitTTreeMaker::clear() + { + } + + DEFINE_ART_RESULTS_PLUGIN(HitTTreeMaker) +}// end WireMod namespace diff --git a/icaruscode/WireMod/ROICounter.fcl b/icaruscode/WireMod/ROICounter.fcl new file mode 100644 index 000000000..dddc40289 --- /dev/null +++ b/icaruscode/WireMod/ROICounter.fcl @@ -0,0 +1,9 @@ +BEGIN_PROLOG + +standard_roicounter: +{ + module_type: "ROICounter" + Label: "roifinder" +} + +END_PROLOG diff --git a/icaruscode/WireMod/ROICounter_module.cc b/icaruscode/WireMod/ROICounter_module.cc new file mode 100644 index 000000000..e570ce216 --- /dev/null +++ b/icaruscode/WireMod/ROICounter_module.cc @@ -0,0 +1,159 @@ +//std includes +#include +#include + +//ROOT includes +#include "TF1.h" +#include "TFile.h" +#include "TFitResult.h" +#include "TFitResultPtr.h" +#include "TH1.h" +#include "TH2.h" +#include "TProfile.h" + +//Framework includes +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Results.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "art_root_io/TFileDirectory.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "canvas/Utilities/InputTag.h" +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/TrackHitMeta.h" +#include "lardataobj/RecoBase/Hit.h" +#include "lardataobj/RecoBase/Wire.h" + +namespace WireMod { + class ROICounter : public art::EDAnalyzer { + public: + explicit ROICounter(fhicl::ParameterSet const& pset); + ~ROICounter() override = default; + void reconfigure(fhicl::ParameterSet const& p); + void analyze(art::Event const& evt) override; + + private: + art::InputTag fLabel; // how the hits/wires are labeled in the input file + TH1F* fHist; // store N ROI per channel + TH2F* fHeight; // store a hist for the heights + TH2F* fWidth; // store a hist for the widths + TProfile* fHeightProf; // store a profile for the heights + TProfile* fWidthProf; // store a profile for the widths + };// end ROICounter class + + //------------------------------------------------------------- + // Define the constructor + // The way ART works is it will call the construct on the fhicl parameter set + // Basically we want it to pull out the variables we defined there + // We're doing this in the reconfigure function (because that makes it clearer what we are doing imo) + // so just call that function + ROICounter::ROICounter(fhicl::ParameterSet const& pset) + : art::EDAnalyzer(pset) + { + this->reconfigure(pset); + } + + //------------------------------------------------------------- + // this function pulls out the stuff we defined in the fhicl file + void ROICounter::reconfigure(fhicl::ParameterSet const& pset) + { + // the first arguement is where in the fhicl to look, the second is the default value if that isn't found + fLabel = pset.get("Label", "decon1droi"); + + art::ServiceHandle tfs; + fHist = tfs->make ("ROI_vs_Channel" , ";Channel;Number of ROIs", 55296, -0.5, 55295.5); + fHeight = tfs->make ("Height_vs_Channel" , ";Channel;ROI Height" , 55296, -0.5, 55295.5, 1000, 0, 200); + fWidth = tfs->make ("Width_vs_Channel" , ";Channel;ROI Width" , 55296, -0.5, 55295.5, 1000, 0, 200); + fHeightProf = tfs->make("Height_vs_Channel_prof", ";Channel;ROI Height" , 55296, -0.5, 55295.5); + fWidthProf = tfs->make("Width_vs_Channel_prof" , ";Channel;ROI Width" , 55296, -0.5, 55295.5); + } + + //------------------------------------------------------------- + // this function is run on every event in the art file + // the event stores the information we want to analyze + void ROICounter::analyze(art::Event const& evt) + { + // loop for the TPCs + std::string instances[4] = {"PHYSCRATEDATATPCEE", + "PHYSCRATEDATATPCEW", + "PHYSCRATEDATATPCWE", + "PHYSCRATEDATATPCWW"}; + + for (auto const& inst : instances) + { + // get the tag + art::InputTag fullTag(fLabel.label(), inst); + + // get the Wires + art::Handle< std::vector > wireHandle; + evt.getByLabel(fullTag, wireHandle); + + // loop over the wires + for (auto const& wire : *wireHandle) + { + // get the channel the wire lives on + raw::ChannelID_t channel = wire.Channel(); + + // loop over ROIs on wire + for (size_t range_idx = 0; range_idx < wire.SignalROI().n_ranges(); ++range_idx) + { + // couting ROIs... + fHist->Fill(channel); + + // get ROI + std::vector roi = wire.SignalROI().range(range_idx).data(); + if (roi.size() == 0) + continue; + + // make a TH1 and fit it with a Gaussian + TH1F roiHist("roiHist", ";Tick;Abritrary Units", roi.size(), 0, roi.size()); + TF1* gaus = new TF1("gausFunc", "gaus", 0, roi.size()); + + // loop to get min and max + float roi_min = std::numeric_limits::max(); + float roi_max = std::numeric_limits::min(); + float roi_int = 0; + size_t roi_bin = 0; + for (auto const& roi_val : roi) + { + roi_min = (roi_min > roi_val) ? roi_val : roi_min; + roi_max = (roi_max < roi_val) ? roi_val : roi_max; + roi_int += roi_val; + roiHist.SetBinContent(roi_bin, roi_val); + ++roi_bin; + } + + // seed and fit + float heightSeed = roi_max - roi_min; + float widthSeed = roi_int / (std::sqrt(2*std::acos(-1)) * heightSeed); + float meanSeed = roi.size() / 2.0; + gaus->SetParameters(heightSeed, widthSeed, meanSeed); + TFitResultPtr gausFit = roiHist.Fit(gaus, "S"); + + // fill profiles + // proxy the height with the difference between min and max + // and the width as the number of ticks in the ROI + //fHeightProf->Fill(channel, roi_max - roi_min); + //fWidthProf ->Fill(channel, roi.size()); + if ((gausFit.Get() != nullptr) && + (gausFit->Status() == 0) ) + { + mf::LogVerbatim("ROICounter") + << "Filling Hist"; + fHeight ->Fill(channel, gausFit->Parameter(0)); + fWidth ->Fill(channel, gausFit->Parameter(2)); + fHeightProf->Fill(channel, gausFit->Parameter(0)); + fWidthProf ->Fill(channel, gausFit->Parameter(2)); + } + } + } + } + } + + DEFINE_ART_MODULE(ROICounter) +}// end WireMod namespace diff --git a/icaruscode/WireMod/Run4_XTheta_coarse.root b/icaruscode/WireMod/Run4_XTheta_coarse.root new file mode 100644 index 000000000..83ad67cd8 Binary files /dev/null and b/icaruscode/WireMod/Run4_XTheta_coarse.root differ diff --git a/icaruscode/WireMod/WireModHitDiagnostic.fcl b/icaruscode/WireMod/WireModHitDiagnostic.fcl new file mode 100644 index 000000000..604114f4b --- /dev/null +++ b/icaruscode/WireMod/WireModHitDiagnostic.fcl @@ -0,0 +1,53 @@ +BEGIN_PROLOG + +WireModHitDiag: +{ + module_type: "WireModHitDiagnostic" + + BeforeHitLabels: [ + "dummyGaushit2dTPCEE", + "dummyGaushit2dTPCEW", + "dummyGaushit2dTPCWE", + "dummyGaushit2dTPCWW" + ] + + AfterHitLabels: [ + "gaushit2dTPCEE", + "gaushit2dTPCEW", + "gaushit2dTPCWE", + "gaushit2dTPCWW" + ] + + ScaleInfoLabels: [ + "WireModTPCEE", + "WireModTPCEW", + "WireModTPCWE", + "WireModTPCWW" + ] + + TrackLabels: [ + "pandoraTrackGausCryoE", + "pandoraTrackGausCryoW" + ] + + DummyTrackLabels: [] # optional: Pandora on before-hits for PRE-WireMod reco theta + + MatchWindowTicks: 10.0 + OnlyMC: true +} + +WireModROITree: { + SaveROITree: true + SaveTickHistograms: true + SavePerHitData: true + SaveByChannel: true +} + +WireModPerHitData: { + SaveROITree: false + SaveTickHistograms: false + SavePerHitData: true + SaveByChannel: false +} + +END_PROLOG diff --git a/icaruscode/WireMod/WireModHitDiagnostic_module.cc b/icaruscode/WireMod/WireModHitDiagnostic_module.cc new file mode 100644 index 000000000..825559c2d --- /dev/null +++ b/icaruscode/WireMod/WireModHitDiagnostic_module.cc @@ -0,0 +1,571 @@ +// std includes +#include +#include +#include +#include + +// ROOT includes +#include "TTree.h" +#include "TH1F.h" +#include "TH2F.h" +#include "TMath.h" + +// art includes +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/Ptr.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +// larsoft includes +#include "lardataobj/RecoBase/Hit.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/TrackHitMeta.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcore/CoreUtils/ServiceUtil.h" + +namespace wiremod { + +// WireMod ThetaXW replicated from WireModUtility::ThetaXW so reco-track angles +// are computed with exactly the same convention as truth angles from WireModifierXXW. +inline double ThetaXW(double dxdr, double dydr, double dzdr, double planeAngle) +{ + const double s = std::sin(planeAngle - 0.5 * M_PI); + const double c = std::cos(planeAngle - 0.5 * M_PI); + const double cosG = std::abs(dydr * s + dzdr * c); + return (cosG > 1e-9) ? std::abs(std::atan(dxdr / cosG)) : 0.5 * M_PI; +} + +// Map type: channel → (peakTime, plane, reco_thxw_deg) +// Used to carry pre-computed reco angles keyed by the hit they belong to. +using RecoThxwMap = std::unordered_multimap< + raw::ChannelID_t, + std::tuple>; + +static RecoThxwMap buildRecoThxwMap(art::Event const& evt, + std::vector const& tags, + geo::WireReadoutGeom const* wr) +{ + RecoThxwMap m; + for (auto const& tag : tags) { + auto h = evt.getHandle>(tag); + if (!h.isValid()) { + mf::LogWarning("WireModHitDiagnostic") + << "Track collection not found: " << tag; continue; + } + art::FindManyP hfm(h, evt, tag); + if (!hfm.isValid()) continue; + for (size_t iT = 0; iT < h->size(); ++iT) { + auto const& trk = (*h)[iT]; + auto const& hits = hfm.at(iT); + auto const& metas = hfm.data(iT); + for (size_t iH = 0; iH < hits.size(); ++iH) { + size_t pt = metas[iH]->Index(); + if (pt == std::numeric_limits::max() || !trk.HasValidPoint(pt)) + continue; + auto dir = trk.DirectionAtPoint(pt); + if (std::abs(dir.X()) + std::abs(dir.Y()) + std::abs(dir.Z()) < 1e-6) continue; + auto const& wid = hits[iH]->WireID(); + double thetaZ = wr->Plane(wid.planeID()).ThetaZ(); + float thxw_deg = static_cast( + ThetaXW(dir.X(), dir.Y(), dir.Z(), thetaZ) * TMath::RadToDeg()); + m.emplace(hits[iH]->Channel(), + std::make_tuple(hits[iH]->PeakTime(), static_cast(wid.Plane), thxw_deg)); + } + } + } + return m; +} + +// Returns -999 if no match within ±matchWindow ticks. +static float lookupRecoThxw(RecoThxwMap const& m, + raw::ChannelID_t ch, float peakTime, int plane, + float matchWindow) +{ + auto range = m.equal_range(ch); + float best = -999.f, bestDt = matchWindow + 1.f; + for (auto it = range.first; it != range.second; ++it) { + float tp; int pl; float thxw; + std::tie(tp, pl, thxw) = it->second; + if (pl != plane) continue; + float dt = std::abs(tp - peakTime); + if (dt < bestDt) { bestDt = dt; best = thxw; } + } + return best; +} + +class WireModHitDiagnostic : public art::EDAnalyzer +{ +public: + explicit WireModHitDiagnostic(fhicl::ParameterSet const& pset); + void analyze(art::Event const& evt) override; + +private: + std::vector fBeforeHitLabels; // dummyGaushit2dTPC* + std::vector fAfterHitLabels; // gaushit2dTPC* + std::vector fScaleInfoLabels; // WireModTPC* (scale products) + std::vector fTrackLabels; // pandoraTrackGaus* on after-hits + std::vector fDummyTrackLabels; // pandoraTrackGaus* on before-hits (optional) + float fMatchWindowTicks; + bool fOnlyMC; + + const geo::WireReadoutGeom* fWireReadout = + &(art::ServiceHandle()->Get()); + + // ThetaXW 2D: truth vs reco (after-hit tracks) and truth vs dummy-reco (before-hit tracks) + TH2F* fThxwTrueVsReco = nullptr; + TH2F* fThxwTrueVsReco_p[3] = {nullptr, nullptr, nullptr}; + TH1F* fThxwResid = nullptr; + TH2F* fThxwTrueVsDummyReco = nullptr; + TH2F* fThxwTrueVsDummyReco_p[3] = {nullptr, nullptr, nullptr}; + TH1F* fThxwDummyResid = nullptr; + + // HitMatchTree: one entry per before-hit + TTree* fHitMatchTree; + Int_t tm_run, tm_subrun, tm_event; + Int_t tm_channel, tm_cryo, tm_tpc, tm_plane, tm_wire; + Float_t tm_before_peak_time, tm_before_peak_amp, tm_before_integral, tm_before_rms; + Int_t tm_before_start_tick, tm_before_end_tick; + Float_t tm_before_gof; + Int_t tm_before_dof, tm_before_n_multi; + Int_t tm_is_mc; + Float_t tm_scale_q, tm_scale_sigma; + Float_t tm_truth_x; + Float_t tm_theta_xw; // truth ThetaXW from WireMod [deg] + Float_t tm_reco_theta_xw; // reco ThetaXW from after-hit track [deg] + Float_t tm_dummy_reco_theta_xw; // reco ThetaXW from before-hit track [deg] + Float_t tm_truth_dirx, tm_truth_diry, tm_truth_dirz; + Float_t tm_pitch; + Float_t tm_dqdx_before; + Float_t tm_truth_e, tm_truth_nelec; + Int_t tm_is_matched, tm_n_after_matches, tm_n_before_matches; + Float_t tm_after_peak_time, tm_after_peak_amp, tm_after_integral, tm_after_rms; + Int_t tm_after_start_tick, tm_after_end_tick; + Float_t tm_after_gof; + Int_t tm_after_dof, tm_after_n_multi; + Float_t tm_ratio_integral, tm_ratio_rms; + + // NewHitTree: one entry per after-hit without a before-hit match + TTree* fNewHitTree; + Int_t tn_run, tn_subrun, tn_event; + Int_t tn_channel, tn_cryo, tn_tpc, tn_plane, tn_wire; + Float_t tn_peak_time, tn_peak_amp, tn_integral, tn_rms; + Int_t tn_start_tick, tn_end_tick; + Float_t tn_gof; + Int_t tn_dof; +}; + +//---------------------------------------------------------------------------- +WireModHitDiagnostic::WireModHitDiagnostic(fhicl::ParameterSet const& pset) + : EDAnalyzer{pset} + , fMatchWindowTicks{pset.get("MatchWindowTicks", 10.f)} + , fOnlyMC{pset.get("OnlyMC", false)} +{ + for (auto const& s : pset.get>("BeforeHitLabels")) + fBeforeHitLabels.emplace_back(s); + for (auto const& s : pset.get>("AfterHitLabels")) + fAfterHitLabels.emplace_back(s); + for (auto const& s : pset.get>("ScaleInfoLabels", + std::vector{})) + fScaleInfoLabels.emplace_back(s); + for (auto const& s : pset.get>("TrackLabels", + std::vector{})) + fTrackLabels.emplace_back(s); + for (auto const& s : pset.get>("DummyTrackLabels", + std::vector{})) + fDummyTrackLabels.emplace_back(s); + + art::ServiceHandle tfs; + + const int nb = 90; const double lo = 0., hi = 90.; + + // POST-WireMod reco vs truth + fThxwTrueVsReco = tfs->make("ThxwTrueVsReco", + "Truth vs POST-WireMod reco #theta_{XW} (all planes);" + "truth #theta_{XW} [deg];reco #theta_{XW} [deg]", + nb, lo, hi, nb, lo, hi); + for (int p = 0; p < 3; ++p) + fThxwTrueVsReco_p[p] = tfs->make(Form("ThxwTrueVsReco_p%d", p), + Form("Truth vs POST-WireMod reco #theta_{XW} (plane %d);" + "truth #theta_{XW} [deg];reco #theta_{XW} [deg]", p), + nb, lo, hi, nb, lo, hi); + fThxwResid = tfs->make("ThxwResid", + "POST-WireMod reco - truth #theta_{XW};" + "#Delta#theta_{XW} [deg];hits", 200, -45., 45.); + + // PRE-WireMod reco vs truth (only filled when DummyTrackLabels are provided) + fThxwTrueVsDummyReco = tfs->make("ThxwTrueVsDummyReco", + "Truth vs PRE-WireMod reco #theta_{XW} (all planes);" + "truth #theta_{XW} [deg];reco #theta_{XW} [deg]", + nb, lo, hi, nb, lo, hi); + for (int p = 0; p < 3; ++p) + fThxwTrueVsDummyReco_p[p] = tfs->make(Form("ThxwTrueVsDummyReco_p%d", p), + Form("Truth vs PRE-WireMod reco #theta_{XW} (plane %d);" + "truth #theta_{XW} [deg];reco #theta_{XW} [deg]", p), + nb, lo, hi, nb, lo, hi); + fThxwDummyResid = tfs->make("ThxwDummyResid", + "PRE-WireMod reco - truth #theta_{XW};" + "#Delta#theta_{XW} [deg];hits", 200, -45., 45.); + + fHitMatchTree = tfs->make("HitMatchTree", + "WireMod before-after hit comparison"); + fHitMatchTree->Branch("run", &tm_run, "run/I"); + fHitMatchTree->Branch("subrun", &tm_subrun, "subrun/I"); + fHitMatchTree->Branch("event", &tm_event, "event/I"); + fHitMatchTree->Branch("channel", &tm_channel, "channel/I"); + fHitMatchTree->Branch("cryo", &tm_cryo, "cryo/I"); + fHitMatchTree->Branch("tpc", &tm_tpc, "tpc/I"); + fHitMatchTree->Branch("plane", &tm_plane, "plane/I"); + fHitMatchTree->Branch("wire", &tm_wire, "wire/I"); + fHitMatchTree->Branch("before_peak_time", &tm_before_peak_time, "before_peak_time/F"); + fHitMatchTree->Branch("before_peak_amp", &tm_before_peak_amp, "before_peak_amp/F"); + fHitMatchTree->Branch("before_integral", &tm_before_integral, "before_integral/F"); + fHitMatchTree->Branch("before_rms", &tm_before_rms, "before_rms/F"); + fHitMatchTree->Branch("before_start_tick", &tm_before_start_tick, "before_start_tick/I"); + fHitMatchTree->Branch("before_end_tick", &tm_before_end_tick, "before_end_tick/I"); + fHitMatchTree->Branch("before_gof", &tm_before_gof, "before_gof/F"); + fHitMatchTree->Branch("before_dof", &tm_before_dof, "before_dof/I"); + fHitMatchTree->Branch("before_n_multi", &tm_before_n_multi, "before_n_multi/I"); + fHitMatchTree->Branch("is_mc", &tm_is_mc, "is_mc/I"); + fHitMatchTree->Branch("scale_q", &tm_scale_q, "scale_q/F"); + fHitMatchTree->Branch("scale_sigma", &tm_scale_sigma, "scale_sigma/F"); + fHitMatchTree->Branch("truth_x", &tm_truth_x, "truth_x/F"); + // ThetaXW angles: all three perspectives + fHitMatchTree->Branch("theta_xw", &tm_theta_xw, "theta_xw/F"); + fHitMatchTree->Branch("reco_theta_xw", &tm_reco_theta_xw, "reco_theta_xw/F"); + fHitMatchTree->Branch("dummy_reco_theta_xw", &tm_dummy_reco_theta_xw, "dummy_reco_theta_xw/F"); + fHitMatchTree->Branch("truth_dirx", &tm_truth_dirx, "truth_dirx/F"); + fHitMatchTree->Branch("truth_diry", &tm_truth_diry, "truth_diry/F"); + fHitMatchTree->Branch("truth_dirz", &tm_truth_dirz, "truth_dirz/F"); + fHitMatchTree->Branch("pitch", &tm_pitch, "pitch/F"); + fHitMatchTree->Branch("dqdx_before", &tm_dqdx_before, "dqdx_before/F"); + fHitMatchTree->Branch("truth_e", &tm_truth_e, "truth_e/F"); + fHitMatchTree->Branch("truth_nelec", &tm_truth_nelec, "truth_nelec/F"); + fHitMatchTree->Branch("is_matched", &tm_is_matched, "is_matched/I"); + fHitMatchTree->Branch("n_after_matches", &tm_n_after_matches, "n_after_matches/I"); + fHitMatchTree->Branch("n_before_matches", &tm_n_before_matches, "n_before_matches/I"); + fHitMatchTree->Branch("after_peak_time", &tm_after_peak_time, "after_peak_time/F"); + fHitMatchTree->Branch("after_peak_amp", &tm_after_peak_amp, "after_peak_amp/F"); + fHitMatchTree->Branch("after_integral", &tm_after_integral, "after_integral/F"); + fHitMatchTree->Branch("after_rms", &tm_after_rms, "after_rms/F"); + fHitMatchTree->Branch("after_start_tick", &tm_after_start_tick, "after_start_tick/I"); + fHitMatchTree->Branch("after_end_tick", &tm_after_end_tick, "after_end_tick/I"); + fHitMatchTree->Branch("after_gof", &tm_after_gof, "after_gof/F"); + fHitMatchTree->Branch("after_dof", &tm_after_dof, "after_dof/I"); + fHitMatchTree->Branch("after_n_multi", &tm_after_n_multi, "after_n_multi/I"); + fHitMatchTree->Branch("ratio_integral", &tm_ratio_integral, "ratio_integral/F"); + fHitMatchTree->Branch("ratio_rms", &tm_ratio_rms, "ratio_rms/F"); + + fNewHitTree = tfs->make("NewHitTree", + "After-mod hits with no before-mod counterpart"); + fNewHitTree->Branch("run", &tn_run, "run/I"); + fNewHitTree->Branch("subrun", &tn_subrun, "subrun/I"); + fNewHitTree->Branch("event", &tn_event, "event/I"); + fNewHitTree->Branch("channel", &tn_channel, "channel/I"); + fNewHitTree->Branch("cryo", &tn_cryo, "cryo/I"); + fNewHitTree->Branch("tpc", &tn_tpc, "tpc/I"); + fNewHitTree->Branch("plane", &tn_plane, "plane/I"); + fNewHitTree->Branch("wire", &tn_wire, "wire/I"); + fNewHitTree->Branch("peak_time", &tn_peak_time, "peak_time/F"); + fNewHitTree->Branch("peak_amp", &tn_peak_amp, "peak_amp/F"); + fNewHitTree->Branch("integral", &tn_integral, "integral/F"); + fNewHitTree->Branch("rms", &tn_rms, "rms/F"); + fNewHitTree->Branch("start_tick", &tn_start_tick, "start_tick/I"); + fNewHitTree->Branch("end_tick", &tn_end_tick, "end_tick/I"); + fNewHitTree->Branch("gof", &tn_gof, "gof/F"); + fNewHitTree->Branch("dof", &tn_dof, "dof/I"); +} + +// global TPC index: 0=EE (cryo0,tpcset0) 1=EW (cryo0,tpcset1) +// 2=WE (cryo1,tpcset0) 3=WW (cryo1,tpcset1) +int globalTPC(raw::ChannelID_t ch, geo::WireReadoutGeom const* wr) +{ + auto rop = wr->ChannelToROP(ch); + return static_cast(rop.Cryostat) * 2 + static_cast(rop.TPCset); +} + +//---------------------------------------------------------------------------- +void WireModHitDiagnostic::analyze(art::Event const& evt) +{ + tm_run = tn_run = static_cast(evt.run()); + tm_subrun = tn_subrun = static_cast(evt.subRun()); + tm_event = tn_event = static_cast(evt.event()); + + RecoThxwMap recoThxwByChannel = buildRecoThxwMap(evt, fTrackLabels, fWireReadout); + RecoThxwMap dummyRecoThxwByChannel = buildRecoThxwMap(evt, fDummyTrackLabels, fWireReadout); + + std::vector afterHits; + for (auto const& tag : fAfterHitLabels) { + auto h = evt.getHandle>(tag); + if (!h.isValid()) { + mf::LogWarning("WireModHitDiagnostic") + << "After-hit collection not found: " << tag; continue; + } + for (auto const& hit : *h) afterHits.push_back(&hit); + } + + std::unordered_multimap afterByChannel; + afterByChannel.reserve(afterHits.size() * 2); + for (size_t i = 0; i < afterHits.size(); ++i) + afterByChannel.emplace(afterHits[i]->Channel(), i); + + std::vector afterNBeforeMatches(afterHits.size(), 0); + RecoThxwMap truthThxwByChannel; + + for (size_t j = 0; j < fBeforeHitLabels.size(); ++j) + { + auto bHandle = evt.getHandle>(fBeforeHitLabels[j]); + if (!bHandle.isValid()) { + mf::LogWarning("WireModHitDiagnostic") + << "Before-hit collection not found: " << fBeforeHitLabels[j]; continue; + } + auto const& localHits = *bHandle; + + // scale-info parallel vectors for this TPC (indexed 1:1 with localHits) + std::vector const* pScaleQ = nullptr; + std::vector const* pScaleSigma = nullptr; + std::vector const* pTruthX = nullptr; + std::vector const* pThetaXW = nullptr; + std::vector const* pIsMC = nullptr; + std::vector const* pDirX = nullptr; + std::vector const* pDirY = nullptr; + std::vector const* pDirZ = nullptr; + std::vector const* pPitch = nullptr; + std::vector const* pDQdX = nullptr; + std::vector const* pTruthE = nullptr; + std::vector const* pTruthNelec = nullptr; + + if (j < fScaleInfoLabels.size()) { + auto const& siLabel = fScaleInfoLabels[j]; + auto sqH = evt.getHandle>(art::InputTag(siLabel.label(), "scaleQ")); + auto ssH = evt.getHandle>(art::InputTag(siLabel.label(), "scaleSigma")); + auto txH = evt.getHandle>(art::InputTag(siLabel.label(), "truthX")); + auto thH = evt.getHandle>(art::InputTag(siLabel.label(), "thetaXW")); + auto imH = evt.getHandle> (art::InputTag(siLabel.label(), "isMC")); + auto dxH = evt.getHandle>(art::InputTag(siLabel.label(), "dirX")); + auto dyH = evt.getHandle>(art::InputTag(siLabel.label(), "dirY")); + auto dzH = evt.getHandle>(art::InputTag(siLabel.label(), "dirZ")); + auto ptH = evt.getHandle>(art::InputTag(siLabel.label(), "pitch")); + auto dqH = evt.getHandle>(art::InputTag(siLabel.label(), "dQdX")); + auto teH = evt.getHandle>(art::InputTag(siLabel.label(), "truthE")); + auto tnH = evt.getHandle>(art::InputTag(siLabel.label(), "truthNelec")); + if (sqH.isValid()) pScaleQ = &(*sqH); + if (ssH.isValid()) pScaleSigma = &(*ssH); + if (txH.isValid()) pTruthX = &(*txH); + if (thH.isValid()) pThetaXW = &(*thH); + if (imH.isValid()) pIsMC = &(*imH); + if (dxH.isValid()) pDirX = &(*dxH); + if (dyH.isValid()) pDirY = &(*dyH); + if (dzH.isValid()) pDirZ = &(*dzH); + if (ptH.isValid()) pPitch = &(*ptH); + if (dqH.isValid()) pDQdX = &(*dqH); + if (teH.isValid()) pTruthE = &(*teH); + if (tnH.isValid()) pTruthNelec = &(*tnH); + } + + // pre-pass: count before-hits per after-hit so n_before_matches is ready for tree fill. + // Window on PeakTime (not StartTick/EndTick) to avoid multi-Gaussian group mismatches. + for (size_t i = 0; i < localHits.size(); ++i) { + auto const& bh = localHits[i]; + if (fOnlyMC) { + int isMC = (pIsMC && i < pIsMC->size()) ? (*pIsMC)[i] : -1; + if (isMC != 1) continue; + } + float winLo = bh.PeakTime() - fMatchWindowTicks; + float winHi = bh.PeakTime() + fMatchWindowTicks; + auto range = afterByChannel.equal_range(bh.Channel()); + for (auto it = range.first; it != range.second; ++it) { + if (afterHits[it->second]->PeakTime() >= winLo && + afterHits[it->second]->PeakTime() <= winHi) + ++afterNBeforeMatches[it->second]; + } + } + + for (size_t i = 0; i < localHits.size(); ++i) + { + auto const& bh = localHits[i]; + auto const& wid = bh.WireID(); + + tm_channel = static_cast(bh.Channel()); + tm_cryo = static_cast(wid.Cryostat); + tm_tpc = globalTPC(bh.Channel(), fWireReadout); + tm_plane = static_cast(wid.Plane); + tm_wire = static_cast(wid.Wire); + tm_before_peak_time = bh.PeakTime(); + tm_before_peak_amp = bh.PeakAmplitude(); + tm_before_integral = bh.Integral(); + tm_before_rms = bh.RMS(); + tm_before_start_tick = bh.StartTick(); + tm_before_end_tick = bh.EndTick(); + tm_before_gof = bh.GoodnessOfFit(); + tm_before_dof = bh.DegreesOfFreedom(); + tm_before_n_multi = bh.Multiplicity(); + + tm_is_mc = (pIsMC && i < pIsMC->size()) ? (*pIsMC)[i] : -1; + tm_scale_q = (pScaleQ && i < pScaleQ->size()) ? (*pScaleQ)[i] : -999.f; + tm_scale_sigma = (pScaleSigma && i < pScaleSigma->size()) ? (*pScaleSigma)[i] : -999.f; + tm_truth_x = (pTruthX && i < pTruthX->size()) ? (*pTruthX)[i] : -999.f; + tm_theta_xw = (pThetaXW && i < pThetaXW->size()) ? (*pThetaXW)[i] : -999.f; + tm_truth_dirx = (pDirX && i < pDirX->size()) ? (*pDirX)[i] : -999.f; + tm_truth_diry = (pDirY && i < pDirY->size()) ? (*pDirY)[i] : -999.f; + tm_truth_dirz = (pDirZ && i < pDirZ->size()) ? (*pDirZ)[i] : -999.f; + tm_pitch = (pPitch && i < pPitch->size()) ? (*pPitch)[i] : -999.f; + tm_dqdx_before = (pDQdX && i < pDQdX->size()) ? (*pDQdX)[i] : -999.f; + tm_truth_e = (pTruthE && i < pTruthE->size()) ? (*pTruthE)[i] : -1.f; + tm_truth_nelec = (pTruthNelec && i < pTruthNelec->size()) ? (*pTruthNelec)[i] : -1.f; + + tm_dummy_reco_theta_xw = lookupRecoThxw(dummyRecoThxwByChannel, + bh.Channel(), bh.PeakTime(), tm_plane, + fMatchWindowTicks); + + if (tm_theta_xw > -900.f) + truthThxwByChannel.emplace(bh.Channel(), + std::make_tuple(bh.PeakTime(), tm_plane, tm_theta_xw)); + + if (fOnlyMC && tm_is_mc != 1) continue; + + float winLo = bh.PeakTime() - fMatchWindowTicks; + float winHi = bh.PeakTime() + fMatchWindowTicks; + + size_t bestIdx = std::numeric_limits::max(); + float bestDist = std::numeric_limits::max(); + int nMatch = 0; + + auto range = afterByChannel.equal_range(bh.Channel()); + for (auto it = range.first; it != range.second; ++it) { + float aPeak = afterHits[it->second]->PeakTime(); + if (aPeak < winLo || aPeak > winHi) continue; + ++nMatch; + float dist = std::abs(aPeak - bh.PeakTime()); + if (dist < bestDist) { bestDist = dist; bestIdx = it->second; } + } + + tm_n_after_matches = nMatch; + tm_is_matched = (bestIdx != std::numeric_limits::max()) ? 1 : 0; + tm_n_before_matches = (bestIdx != std::numeric_limits::max()) + ? afterNBeforeMatches[bestIdx] : 0; + + if (tm_is_matched) { + auto const* ah = afterHits[bestIdx]; + tm_after_peak_time = ah->PeakTime(); + tm_after_peak_amp = ah->PeakAmplitude(); + tm_after_integral = ah->Integral(); + tm_after_rms = ah->RMS(); + tm_after_start_tick = ah->StartTick(); + tm_after_end_tick = ah->EndTick(); + tm_after_gof = ah->GoodnessOfFit(); + tm_after_dof = ah->DegreesOfFreedom(); + tm_after_n_multi = ah->Multiplicity(); + tm_ratio_integral = (bh.Integral() > 0.f) + ? ah->Integral() / bh.Integral() : -999.f; + tm_ratio_rms = (bh.RMS() > 0.f) + ? ah->RMS() / bh.RMS() : -999.f; + + tm_reco_theta_xw = lookupRecoThxw(recoThxwByChannel, + ah->Channel(), ah->PeakTime(), tm_plane, + fMatchWindowTicks); + } else { + tm_after_peak_time = -999.f; tm_after_peak_amp = -999.f; + tm_after_integral = -999.f; tm_after_rms = -999.f; + tm_after_start_tick = -999; tm_after_end_tick = -999; + tm_after_gof = -999.f; tm_after_dof = -999; + tm_after_n_multi = -999; + tm_ratio_integral = -999.f; tm_ratio_rms = -999.f; + tm_reco_theta_xw = -999.f; + } + + fHitMatchTree->Fill(); + } + } + + for (size_t i = 0; i < afterHits.size(); ++i) { + if (afterNBeforeMatches[i] > 0) continue; + auto const* ah = afterHits[i]; + auto const& wid = ah->WireID(); + tn_channel = static_cast(ah->Channel()); + tn_cryo = static_cast(wid.Cryostat); + tn_tpc = globalTPC(ah->Channel(), fWireReadout); + tn_plane = static_cast(wid.Plane); + tn_wire = static_cast(wid.Wire); + tn_peak_time = ah->PeakTime(); + tn_peak_amp = ah->PeakAmplitude(); + tn_integral = ah->Integral(); + tn_rms = ah->RMS(); + tn_start_tick = ah->StartTick(); + tn_end_tick = ah->EndTick(); + tn_gof = ah->GoodnessOfFit(); + tn_dof = ah->DegreesOfFreedom(); + fNewHitTree->Fill(); + } + + for (auto const& tag : fTrackLabels) { + auto h = evt.getHandle>(tag); + if (!h.isValid()) continue; + art::FindManyP hfm(h, evt, tag); + if (!hfm.isValid()) continue; + for (size_t iT = 0; iT < h->size(); ++iT) { + auto const& trk = (*h)[iT]; + auto const& hits = hfm.at(iT); + auto const& metas = hfm.data(iT); + for (size_t iH = 0; iH < hits.size(); ++iH) { + size_t pt = metas[iH]->Index(); + if (pt == std::numeric_limits::max() || !trk.HasValidPoint(pt)) continue; + auto dir = trk.DirectionAtPoint(pt); + if (std::abs(dir.X()) + std::abs(dir.Y()) + std::abs(dir.Z()) < 1e-6) continue; + auto const& wid = hits[iH]->WireID(); + int plane = static_cast(wid.Plane); + double thetaZ = fWireReadout->Plane(wid.planeID()).ThetaZ(); + float recoThxw = static_cast( + ThetaXW(dir.X(), dir.Y(), dir.Z(), thetaZ) * TMath::RadToDeg()); + float trueThxw = lookupRecoThxw(truthThxwByChannel, + hits[iH]->Channel(), hits[iH]->PeakTime(), plane, + fMatchWindowTicks); + if (trueThxw < 0.f) continue; + fThxwTrueVsReco->Fill(trueThxw, recoThxw); + if (plane >= 0 && plane < 3) fThxwTrueVsReco_p[plane]->Fill(trueThxw, recoThxw); + fThxwResid->Fill(recoThxw - trueThxw); + } + } + } + + for (auto const& tag : fDummyTrackLabels) { + auto h = evt.getHandle>(tag); + if (!h.isValid()) continue; + art::FindManyP hfm(h, evt, tag); + if (!hfm.isValid()) continue; + for (size_t iT = 0; iT < h->size(); ++iT) { + auto const& trk = (*h)[iT]; + auto const& hits = hfm.at(iT); + auto const& metas = hfm.data(iT); + for (size_t iH = 0; iH < hits.size(); ++iH) { + size_t pt = metas[iH]->Index(); + if (pt == std::numeric_limits::max() || !trk.HasValidPoint(pt)) continue; + auto dir = trk.DirectionAtPoint(pt); + if (std::abs(dir.X()) + std::abs(dir.Y()) + std::abs(dir.Z()) < 1e-6) continue; + auto const& wid = hits[iH]->WireID(); + int plane = static_cast(wid.Plane); + double thetaZ = fWireReadout->Plane(wid.planeID()).ThetaZ(); + float dummyRecoThxw = static_cast( + ThetaXW(dir.X(), dir.Y(), dir.Z(), thetaZ) * TMath::RadToDeg()); + float trueThxw = lookupRecoThxw(truthThxwByChannel, + hits[iH]->Channel(), hits[iH]->PeakTime(), plane, + fMatchWindowTicks); + if (trueThxw < 0.f) continue; + fThxwTrueVsDummyReco->Fill(trueThxw, dummyRecoThxw); + if (plane >= 0 && plane < 3) fThxwTrueVsDummyReco_p[plane]->Fill(trueThxw, dummyRecoThxw); + fThxwDummyResid->Fill(dummyRecoThxw - trueThxw); + } + } + } +} + +DEFINE_ART_MODULE(WireModHitDiagnostic) + +} // namespace wiremod diff --git a/icaruscode/WireMod/WireModMakeHists.fcl b/icaruscode/WireMod/WireModMakeHists.fcl new file mode 100644 index 000000000..6bdd614fc --- /dev/null +++ b/icaruscode/WireMod/WireModMakeHists.fcl @@ -0,0 +1,38 @@ +BEGIN_PROLOG + +standard_makehists: +{ + plugin_type: "WireModMakeHists" + Label: "decon1droi" + GetHits: false +} + +makehists_ee: @local::standard_makehists +makehists_ee.Label: "decon1droi:PHYSCRATEDATATPCEE" + +makehists_ew: @local::standard_makehists +makehists_ew.Label: "decon1droi:PHYSCRATEDATATPCEW" + +makehists_we: @local::standard_makehists +makehists_we.Label: "decon1droi:PHYSCRATEDATATPCWE" + +makehists_ww: @local::standard_makehists +makehists_ww.Label: "decon1droi:PHYSCRATEDATATPCWW" + +makehists_ee_withHits: @local::standard_makehists +makehists_ee_withHits.Label: "gaushitTPCEE" +makehists_ee_withHits.GetHits: true + +makehists_ew_withHits: @local::standard_makehists +makehists_ew_withHits.Label: "gaushitTPCEW" +makehists_ew_withHits.GetHits: true + +makehists_we_withHits: @local::standard_makehists +makehists_we_withHits.Label: "gaushitTPCWE" +makehists_we_withHits.GetHits: true + +makehists_ww_withHits: @local::standard_makehists +makehists_ww_withHits.Label: "gaushitTPCWW" +makehists_ww_withHits.GetHits: true + +END_PROLOG diff --git a/icaruscode/WireMod/WireModMakeHists_plugin.cc b/icaruscode/WireMod/WireModMakeHists_plugin.cc new file mode 100644 index 000000000..9aec9e258 --- /dev/null +++ b/icaruscode/WireMod/WireModMakeHists_plugin.cc @@ -0,0 +1,660 @@ +// std includes +#include +#include +#include +#include +#include + +// ROOT includes +#include "TFile.h" +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" +#include "TGraph.h" +#include "TGraph2D.h" +#include "TCanvas.h" +#include "TProfile.h" +#include "TSpline.h" + +// Framework includes +#include "larcore/Geometry/Geometry.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() +#include "art/Framework/Core/ResultsProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Results.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "art_root_io/TFileDirectory.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "canvas/Utilities/InputTag.h" +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/TrackHitMeta.h" +#include "lardataobj/RecoBase/Hit.h" +#include "lardataobj/RecoBase/Wire.h" +#include "lardataobj/RecoBase/PFParticle.h" +#include "lardataobj/AnalysisBase/T0.h" +#include "lardataobj/RecoBase/PFParticleMetadata.h" + +namespace WireMod { + + // 5D map to store all of the data to be made in Histograms + /* The Following are what the indices correspond to: + a = 0, 1, 2 are the planes + b = 0, 1 are E and W + c = 0, 1, 2, 3 are E, E, W, W respectively + d = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 correspond to values of x, y, z, theta, phi, inetgral, fwhm, gaussian width, gaussian integral, and gaussian chi^2 respectively + e = 0, 1: 1 indicates if the track crosses any anode or cathode + */ + class FiveDMap { + class FourDMap { + class ThreeDMap { + class TwoDMap { + class OneDMap { + public: + std::vector& operator[](int index) { + return data[index]; + } + private: + std::map> data; + }; + public: + OneDMap& operator[](int index) { + return data[index]; + } + private: + std::map data; + }; + public: + TwoDMap& operator[](int index) { + return data[index]; + } + private: + std::map data; + }; + + public: + ThreeDMap& operator[](int index) { + return data[index]; + } + private: + std::map data; + }; + + public: + FourDMap& operator[](int index) { + return data[index]; + } + private: + std::map data; + }; + + /** + * @brief Class for making histograms from wire modification data. + */ + class WireModMakeHists : public art::ResultsProducer { + public: + explicit WireModMakeHists(fhicl::ParameterSet const& pset); + ~WireModMakeHists() override = default; + void event(art::Event const& evt) override; + void reconfigure(fhicl::ParameterSet const& p); + void writeResults(art::Results& r) override; + void clear() override; + void endJob(); // added so histograms can be made and saved after all the events have been processed + + private: + const geo::GeometryCore* fGeometry = lar::providerFrom(); + const geo::WireReadoutGeom* fWireReadout = &(art::ServiceHandle()->Get()); + art::InputTag fLabel; ///< Label for hits/wires in the input file + art::InputTag fTrackLabel; ///< Label for tracks in the input file + bool fGetHits; ///< Flag for getting hits + bool fGetTracks; ///< Flag for getting tracks + bool fXCorrection; ///< Flag for applying X correction + TFile* fXCorrFile; ///< File containing the X corrections + FiveDMap data; ///< 5D map to store data for histograms + }; + + + /** + * @brief Constructor for WireModMakeHists class. + * @param pset The parameter set from which to extract the configuration variables. + */ + WireModMakeHists::WireModMakeHists(fhicl::ParameterSet const& pset) { + this->reconfigure(pset); + } + + + // This function pulls out the stuff we defined in the fhicl file + /** + * @brief Reconfigures the WireModMakeHists object. + * @param pset The parameter set where to look for the configuration parameters. + */ + void WireModMakeHists::reconfigure(fhicl::ParameterSet const& pset) { + fLabel = pset.get("Label", "decon1droi"); + fTrackLabel = pset.get("TrackLabel"); + fGetHits = pset.get("GetHits", false); + fGetTracks = pset.get("GetTracks", false); + fXCorrection = pset.get("XCorrection", false); + if (fXCorrection) { + fXCorrFile = new TFile("XCorrFile.root", "READ"); + } + } + + + /** + * @brief Checks if the path goes through anode or cathode by seeing if there are values around specified points. + * @param vec The vector of values to be checked against the points. + * @param points The vector of points to check if there are values around them in the 'vec' vector. + * @return true if any point in 'points' has values in 'vec' both above and below it, false otherwise. + */ + bool hasValuesAroundPoints(const std::vector& vec, const std::vector& points) { + for (double point : points) { + bool hasAbove = false; + bool hasBelow = false; + for (double value : vec) { + if (value > point) { + hasAbove = true; + } + if (value < point) { + hasBelow = true; + } + if (hasAbove && hasBelow) { + return true; + } + } + } + return false; + } + + + // Used to generate unique histogram names + const std::vector planes = {"0", "1", "2"}; + const std::vector tpc0s = {"E", "W"}; + const std::vector tpc1s = {"E", "E", "W", "W"}; + const std::vector variables = {"X", "Y", "Z", "Theta", "Phi", "Integral", "FWHM", "GaussWidth", "GaussIntegral", "GaussFit"}; + const std::vector hitchoices = {"ALL_HITS", "SELECTED_HITS"}; + + + // Bin information + const int nbins_amp = 100; + const std::vector mins = {-360.0, -182.0, -896, 0, 0, 0, 0, 0, 0, 0}; + const std::vector maxs = {360.0, 182.0, 896, acos(0), acos(0), 2000, 2000, 200, 2000, 2000}; + + + /** + * @brief Creates and saves a 2D histogram. + * @param name The name of the histogram. + * @param title The title of the histogram. + * @param nbinsX The number of bins for the X axis. + * @param minX The minimum value for the X axis. + * @param maxX The maximum value for the X axis. + * @param x_values The vector of X values to fill the histogram. + * @param y_values The vector of Y values to fill the histogram. + * @param minY The minimum value for the Y axis. + * @param maxY The maximum value for the Y axis. + */ + void CreateAndSaveHist(const char* name, const char* title, int nbinsX, double minX, double maxX, std::vector& x_values, double minY, double maxY, std::vector& y_values) { + if (x_values.size() != y_values.size() || x_values.empty()) { + return; + } + art::ServiceHandle tfs; + TH2D* hist = tfs->make(name, title, nbinsX, minX, maxX, nbins_amp, minY, maxY); + for (size_t i = 0; i < x_values.size(); i++) { + hist->Fill(x_values[i], y_values[i]); + } + mf::LogVerbatim("WireModMakeHists") << "Made 2D histogram " << hist->GetName(); + } + + + // Function for making and saving 3D histograms + /** + * @brief Creates and saves a 3D histogram. + * @param name The name of the histogram. + * @param title The title of the histogram. + * @param nbinsX The number of bins for the X axis. + * @param minX The minimum value for the X axis. + * @param maxX The maximum value for the X axis. + * @param x_values The vector of X values to fill the histogram. + * @param nbinsY The number of bins for the Y axis. + * @param minY The minimum value for the Y axis. + * @param maxY The maximum value for the Y axis. + * @param y_values The vector of Y values to fill the histogram. + * @param nbinsZ The number of bins for the Z axis. + * @param minZ The minimum value for the Z axis. + * @param maxZ The maximum value for the Z axis. + * @param z_values The vector of Z values to fill the histogram. + */ + void CreateAndSaveHist3D(const char* name, const char* title, int nbinsX, double minX, double maxX, std::vector& x_values, int nbinsY, double minY, double maxY, std::vector& y_values, int nbinsZ, double minZ, double maxZ, std::vector& z_values) { + if (x_values.size() != y_values.size() || x_values.size() != z_values.size() || x_values.empty() || z_values.empty()) { + return; + } + art::ServiceHandle tfs; + TH3D* hist = tfs->make(name, title, nbinsX, minX, maxX, nbinsY, minY, maxY, nbinsZ, minZ, maxZ); + for (size_t i = 0; i < x_values.size(); i++) { + hist->Fill(x_values[i], y_values[i], z_values[i]); + } + mf::LogVerbatim("WireModMakeHists") << "Made 3D histogram " << hist->GetName(); + } + + + /** + * @brief Generates a unique filename by appending a counter if the file already exists. + * @param baseName The base name of the file. + * @param extension The extension of the file. + * @return A unique filename. + */ + std::string generateUniqueFilename(const std::string& baseName, const std::string& extension) { + std::string filename = baseName + extension; + std::ifstream file(filename); + int counter = 1; + while (file.good()) { + file.close(); + // Generate a new filename with an incremented counter + filename = baseName + "_" + std::to_string(counter++) + extension; + file.open(filename); + } + return filename; + } + + + /** + * @brief Creates and saves histograms after all events have been processed. + */ + void WireModMakeHists::endJob(){ + std::string labelStr = fLabel.label(); + std::string instanceStr = fLabel.instance(); + auto instance = labelStr + instanceStr; + //std::cout << instance << std::endl; + // all of the instances produce the same histograms, so only make histograms on one of them. I picked this one + if (instance == "gaushitTPCWW"){ + //making a Tfile for the histograms + auto name = generateUniqueFilename("Data_Histograms",".root"); + TFile *file = new TFile(name.c_str(),"RECREATE"); + + //looping over the data mapping to make histograms of all the data (if confused see top for what variables are) + for (int a : {0, 1, 2}) { + for (int b : {0, 1}) { + for (int c : {0, 1}){ + for (int d : {0, 1, 2, 3, 4}) { + for (int e : {0,1}){ + mf::LogVerbatim("WireModMakeHists") + << "a: " << a << ", b: " << b << ", c: " << c << ", d: " << d << ", e: " << e; + //amp_histograms + CreateAndSaveHist(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[d] + "_" + variables[5] + "_" + hitchoices[e]).c_str(), + (variables[d] + "_" + variables[5] + ";" + variables[d] + ";" + variables[5]).c_str(), + nbins_amp, + mins[d], + maxs[d], + data[a][b][c][d][e], + mins[5], + maxs[5], + data[a][b][c][5][e] + ); + //FWHM Histograms + CreateAndSaveHist(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[d] + "_" + variables[6] + "_" + hitchoices[e]).c_str(), + (variables[d] + "_" + variables[6] + ";" + variables[d] + ";" + variables[6]).c_str(), + nbins_amp, + mins[d], + maxs[d], + data[a][b][c][d][e], + mins[6], + maxs[6], + data[a][b][c][6][e] + ); + //Gaussian Hitograms + CreateAndSaveHist(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[d] + "_" + variables[7] + "_" + hitchoices[e]).c_str(), + (variables[d] + "_" + variables[7] + ";" + variables[d] + ";" + variables[7]).c_str(), + nbins_amp, + mins[d], + maxs[d], + data[a][b][c][d][e], + mins[7], + maxs[7], + data[a][b][c][7][e] + ); + CreateAndSaveHist(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[d] + "_" + variables[8] + "_" + hitchoices[e]).c_str(), + (variables[d] + "_" + variables[8] + ";" + variables[d] + ";" + variables[8]).c_str(), + nbins_amp, + mins[d], + maxs[d], + data[a][b][c][d][e], + mins[8], + maxs[8], + data[a][b][c][8][e] + ); + CreateAndSaveHist(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[d] + "_" + variables[9] + "_" + hitchoices[e]).c_str(), + (variables[d] + "_" + variables[9] + ";" + variables[d] + ";" + variables[9]).c_str(), + nbins_amp, + mins[d], + maxs[d], + data[a][b][c][d][e], + mins[9], + maxs[9], + data[a][b][c][9][e] + ); + } + } + } + } + } + //now for making the Y Z (variables[1] + variables[2] 3D histograms: + for (int a : {0, 1, 2}) { + for (int b : {0, 1}) { + for (int c : {0, 1}){ + for (int e : {0,1}){ + //amp_histograms + CreateAndSaveHist3D(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[1] + "_" + variables[2] + "_" + variables[5] + "_" + hitchoices[e]).c_str(), + (variables[1] + "_" + variables[2] + "_" + variables[5] + ";" + variables[1] + "_" + variables[2] + ";" + variables[5]).c_str(), + nbins_amp, + mins[1], + maxs[1], + data[a][b][c][1][e], + nbins_amp, + mins[2], + maxs[2], + data[a][b][c][2][e], + nbins_amp, + 0., + 200., + data[a][b][c][5][e] + ); + //FWHM Histograms + CreateAndSaveHist3D(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[1] + "_" + variables[2] + "_" + variables[6] + "_" + hitchoices[e]).c_str(), + (variables[1] + "_" + variables[2] + "_" + variables[6] + ";" + variables[1] + "_" + variables[2] + ";" + variables[6]).c_str(), + nbins_amp, + mins[1], + maxs[1], + data[a][b][c][1][e], + nbins_amp, + mins[2], + maxs[2], + data[a][b][c][2][e], + nbins_amp, + 0., + 200., + data[a][b][c][6][e] + ); + + //gauss amp histograms + CreateAndSaveHist3D(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[1] + "_" + variables[2] + "_" + variables[7] + "_" + hitchoices[e]).c_str(), + (variables[1] + "_" + variables[2] + "_" + variables[7] + ";" + variables[1] + "_" + variables[2] + ";" + variables[7]).c_str(), + nbins_amp, + mins[1], + maxs[1], + data[a][b][c][1][e], + nbins_amp, + mins[2], + maxs[2], + data[a][b][c][2][e], + nbins_amp, + 0., + 200., + data[a][b][c][7][e] + ); + //gauss width Histograms + CreateAndSaveHist3D(("Plane_" + planes[a] + "_" + tpc0s[b] + "_" + tpc0s[c] + "_" + variables[1] + "_" + variables[2] + "_" + variables[8] + "_" + hitchoices[e]).c_str(), + (variables[1] + "_" + variables[2] + "_" + variables[8] + ";" + variables[1] + "_" + variables[2] + ";" + variables[8]).c_str(), + nbins_amp, + mins[1], + maxs[1], + data[a][b][c][1][e], + nbins_amp, + mins[2], + maxs[2], + data[a][b][c][2][e], + nbins_amp, + 0., + 200., + data[a][b][c][8][e] + ); + } + } + } + } + file->Close(); + delete file; + } + } + + + /** + * @brief Writes results to the ART framework. TODO + * @param r The results object to be written. + */ + void WireModMakeHists::writeResults(art::Results& r) {} + + + /** + * @brief Clears the data. TODO + */ + void WireModMakeHists::clear() {} + + + /** + * @brief Processes each event in the ART file. + * @param evt The event to be processed. + */ + void WireModMakeHists::event(art::Event const& evt) + { + // this is what will make our histograms for us + art::ServiceHandle tfs; + + // get a unique string for this event + std::string evtStr = std::to_string(evt.id().run()) + "_" + + std::to_string(evt.id().subRun()) + "_" + + std::to_string(evt.id().event()) + "_"; + if (fGetTracks) + { + // we need both the hits and the tracks separeately + art::Handle> hitHandle; + evt.getByLabel(fLabel, hitHandle); + if (not hitHandle.isValid()) + { + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Hit handle is not valid!" << '\n' + //<< "Tried " << fLabel << '\n' + //<< "abort"; + return; + } + std::vector> hitPtrVec; + art::fill_ptr_vector(hitPtrVec, hitHandle); + + // also get tracks and the hits for each track + art::FindOneP hitToWireAssns(hitHandle, evt, fLabel); + art::Handle> trackHandle; + evt.getByLabel(fTrackLabel, trackHandle); + if (not trackHandle.isValid()) + { + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Track handle is not valid!" << '\n' + //<< "Tried " << fTrackLabel << '\n' + //<< "abort"; + return; + } + std::vector> trackPtrVec; + art::fill_ptr_vector(trackPtrVec, trackHandle); + + // the recob::TrackHitMeta will let us find where in the track each hit is + art::FindManyP trackToHits(trackHandle, evt, fTrackLabel); + + //Get PFParticles + //auto pfpListHandle = evt.getValidHandle >(fPFParticleLabel[it]); + //if (!pfpListHandle.isValid()) continue; + + for (auto const& trackPtr : trackPtrVec){ + //creating a data set for this track to check for selected hits + FiveDMap loopdata; + // get the tracks hits and metadata for the hits + std::vector> const& trackHits = trackToHits.at(trackPtr.key()); + std::vector const& trackHitMetas = trackToHits.data(trackPtr.key()); + // loop over the track hits + // will need to also find the same hit in hitPtrVec to get the associated wire + for (size_t hitIdx = 0; hitIdx < trackHits.size(); ++hitIdx){ + // get the track hit and metadata + art::Ptr trackHit = trackHits[hitIdx]; + const recob::TrackHitMeta& hitMeta = *trackHitMetas[hitIdx]; + if (hitMeta.Index() == std::numeric_limits::max() || not trackPtr->HasValidPoint(hitMeta.Index())) + { + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Bad Hit, get another one"; + continue; + } + recob::Track::Point_t const& hitLoc = trackPtr->LocationAtPoint(hitMeta.Index()); + recob::Track::Vector_t const& hitDir = trackPtr->DirectionAtPoint(hitMeta.Index()); + + // set up a wirePtr, loop over hitPtrVec to find the right wire + art::Ptr wirePtr; + for (auto const& hitPtr : hitPtrVec) + { + // check channel etc to see if the hits are a match + if (trackHit->Channel() == hitPtr->Channel() && + trackHit->StartTick() == hitPtr->StartTick() && + trackHit->EndTick() == hitPtr->EndTick() && + trackHit->PeakTime() == hitPtr->PeakTime() ) + { + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Wire Found!"; + wirePtr = hitToWireAssns.at(hitPtr.key()); + + //getting the wire plane and TPC info + int planeID = hitPtr->WireID().Plane; + int tpcID = (hitPtr->WireID().TPC) / 2; + int cryoID = hitPtr->WireID().Cryostat; + + //Making a histogram of the hit information + size_t fstTick = hitPtr->StartTick(); + size_t endTick = hitPtr->EndTick(); + size_t hitWidth = endTick - fstTick; + // the start and end ticks were aquired assuming the hits are gaussian + // we want to plot a bit of buffer around the region of interest to get the full shape + // default to a hit width on either side, but if the wire doesn't have enough ticks then use what we can + size_t nTicks = wirePtr->NSignal(); + size_t fstBuffer = (fstTick > hitWidth) ? hitWidth : fstTick; + size_t endBuffer = (nTicks > endTick + hitWidth) ? hitWidth : nTicks - endTick; + // put the waveform in the histogram + // tfs will make a whatever is in the <>, (in this case a TH1F) + // the agruements past to it should be the same as for the constructor for the + auto waveformHist = std::make_unique(("adc_"+evtStr+fLabel.label()+"_"+std::to_string(wirePtr.key())).c_str(), //> name of the object + ";Sample;Arbitrary Units", //> axes labels + hitWidth + fstBuffer + endBuffer, //> number of bins + fstTick - fstBuffer, //> lowest edge + endTick + endBuffer); //> upper edge + // ROOT counts from 1, everyone else counts from 0 + //for (size_t bin = 1; bin < endTick - fstTick + 1; ++bin) + double integral = 0; + for (size_t bin = 1; bin < hitWidth + fstBuffer + endBuffer + 1; ++bin){ + float wvfmVal = (wirePtr->Signal())[fstTick - fstBuffer + bin - 1]; + integral += wvfmVal; + waveformHist->SetBinContent(bin, wvfmVal); + } + + // Calculate integral and FWHM and adding to vector of data + double amplitude = waveformHist-> GetMaximum(); + double half_max = amplitude / 2.0; + int bin1 = waveformHist->FindFirstBinAbove(half_max); + int bin2 = waveformHist->FindLastBinAbove(half_max); + double fwhm = waveformHist->GetBinCenter(bin2) - waveformHist->GetBinCenter(bin1); + + data[planeID][cryoID][tpcID][5][0].push_back(integral); + loopdata[planeID][cryoID][tpcID][5][0].push_back(integral); + data[planeID][cryoID][tpcID][6][0].push_back(fwhm); + loopdata[planeID][cryoID][tpcID][6][0].push_back(fwhm); + + //getting the gaussian information + double gaussintegral = hitPtr->Integral(); + double gausswidth = hitPtr->RMS(); + double gaussfit = hitPtr->GoodnessOfFit(); + if (fXCorrection) + { + TSpline3* integralSpline = fXCorrFile->Get(("xIntegral_" + std::to_string(planeID) + "_ratio_prof").c_str()); + TSpline3* widthSpline = fXCorrFile->Get(("xWidth_" + std::to_string(planeID) + "_ratio_prof").c_str()); + gaussintegral *= integralSpline->Eval(hitLoc.X()); + gausswidth *= widthSpline ->Eval(hitLoc.X()); + } + + data[planeID][cryoID][tpcID][7][0].push_back(gausswidth); + data[planeID][cryoID][tpcID][8][0].push_back(gaussintegral); + data[planeID][cryoID][tpcID][9][0].push_back(gaussfit); + loopdata[planeID][cryoID][tpcID][7][0].push_back(gausswidth); + loopdata[planeID][cryoID][tpcID][8][0].push_back(gaussintegral); + loopdata[planeID][cryoID][tpcID][9][0].push_back(gaussfit); + + //Adding values to vectors for plotting + data[planeID][cryoID][tpcID][0][0].push_back(hitLoc.X()); + data[planeID][cryoID][tpcID][1][0].push_back(hitLoc.Y()); + data[planeID][cryoID][tpcID][2][0].push_back(hitLoc.Z()); + loopdata[planeID][cryoID][tpcID][0][0].push_back(hitLoc.X()); + loopdata[planeID][cryoID][tpcID][1][0].push_back(hitLoc.Y()); + loopdata[planeID][cryoID][tpcID][2][0].push_back(hitLoc.Z()); + + double sinZ = fWireReadout->WirePtr(hitPtr->WireID())->SinThetaZ(); + double cosZ = fWireReadout->WirePtr(hitPtr->WireID())->CosThetaZ(); + double localXDir = hitDir.X(); + double localYDir = cosZ*hitDir.Y() + sinZ*hitDir.Z(); + double localZDir = cosZ*hitDir.Z() - sinZ*hitDir.Y(); + double theta = abs(atan(localXDir / localZDir)); + double phi = abs(atan(localYDir / localZDir)); + + //if (planeID == 0){ + // theta = atan(abs(hitLoc.X()) / abs(0.867* hitLoc.Y() - 0.5*hitLoc.Z())); + // phi = atan( abs((0.5*hitLoc.Y() + 0.867* hitLoc.Z())) / abs(0.867* hitLoc.Y() - 0.5*hitLoc.Z())); + //} + //else if (planeID == 1){ + // theta = atan(hitLoc.X() / (0.867* hitLoc.Y() + 0.5*hitLoc.Z())); + // phi = atan( (0.5*hitLoc.Y() - 0.867* hitLoc.Z()) / (0.867* hitLoc.Y() + 0.5*hitLoc.Z())); + //} + //if (planeID == 2){ + // theta = atan(hitLoc.X() / (hitLoc.Z())); + // phi = atan( (hitLoc.Y()) / (hitLoc.Z())); + //} + + data[planeID][cryoID][tpcID][3][0].push_back(theta); + loopdata[planeID][cryoID][tpcID][3][0].push_back(theta); + data[planeID][cryoID][tpcID][4][0].push_back(phi); + loopdata[planeID][cryoID][tpcID][4][0].push_back(phi); + //delete waveformHist; + } + } + if (wirePtr.isNull()) + { + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Couldn't find wire" << '\n' + // << "Continue..."; + continue; + } + // get the location from the track using the hitMeta + // get X using hitLoc.X(), similarly for Y and Z + // more info from what you can get at https://sbnsoftware.github.io/doxygen/d9/dca/classrecob_1_1Track.html + //MF_LOG_VERBATIM("WireModWireModMakeHists"); + //<< "Hit Pos is (" << hitLoc.X() << ", " << hitLoc.Y() << ", " << hitLoc.Z() << ")"; + } + //finding the tracks that have selected hits + std::vector points = {-358.49,-210.15,-61.94,61.94,210.15,358.49}; + for (int a : {0, 1, 2}) { + for (int b : {0, 1}) { + for (int c : {0, 1, 2, 3}){ + if (hasValuesAroundPoints(loopdata[a][b][c][0][0],points)){ + data[a][b][c][0][1].insert(data[a][b][c][0][1].end(), loopdata[a][b][c][0][0].begin(), loopdata[a][b][c][0][0].end()); + data[a][b][c][1][1].insert(data[a][b][c][1][1].end(), loopdata[a][b][c][1][0].begin(), loopdata[a][b][c][1][0].end()); + data[a][b][c][2][1].insert(data[a][b][c][2][1].end(), loopdata[a][b][c][2][0].begin(), loopdata[a][b][c][2][0].end()); + data[a][b][c][3][1].insert(data[a][b][c][3][1].end(), loopdata[a][b][c][3][0].begin(), loopdata[a][b][c][3][0].end()); + data[a][b][c][4][1].insert(data[a][b][c][4][1].end(), loopdata[a][b][c][4][0].begin(), loopdata[a][b][c][4][0].end()); + data[a][b][c][5][1].insert(data[a][b][c][5][1].end(), loopdata[a][b][c][5][0].begin(), loopdata[a][b][c][5][0].end()); + data[a][b][c][6][1].insert(data[a][b][c][6][1].end(), loopdata[a][b][c][6][0].begin(), loopdata[a][b][c][6][0].end()); + data[a][b][c][7][1].insert(data[a][b][c][7][1].end(), loopdata[a][b][c][7][0].begin(), loopdata[a][b][c][7][0].end()); + data[a][b][c][8][1].insert(data[a][b][c][8][1].end(), loopdata[a][b][c][8][0].begin(), loopdata[a][b][c][8][0].end()); + data[a][b][c][9][1].insert(data[a][b][c][9][1].end(), loopdata[a][b][c][9][0].begin(), loopdata[a][b][c][9][0].end()); + } + } + } + } + } + } + } + DEFINE_ART_RESULTS_PLUGIN(WireModMakeHists) +} // end WireMod namespace diff --git a/icaruscode/WireMod/WireModScaleDebug_module.cc b/icaruscode/WireMod/WireModScaleDebug_module.cc new file mode 100644 index 000000000..6f4b4f5c4 --- /dev/null +++ b/icaruscode/WireMod/WireModScaleDebug_module.cc @@ -0,0 +1,178 @@ +// std includes +#include +#include +#include +#include + +// ROOT includes +#include "TFile.h" +#include "TGraph2D.h" +#include "TMath.h" + +// art includes +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +// larsoft includes +#include "larcore/CoreUtils/ServiceUtil.h" +#include "larcore/Geometry/Geometry.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" + +namespace wiremod { + +class WireModScaleDebug : public art::EDAnalyzer { +public: + explicit WireModScaleDebug(fhicl::ParameterSet const& pset); + void beginJob() override; + void analyze(art::Event const&) override {} + +private: + std::string fRatioFileName_XXW; + std::vector fThetaEdges; + + static void shapeGraphAngle(TGraph2D& graph) + { + double* xPtr = graph.GetX(); + double* yPtr = graph.GetY(); + double* zPtr = graph.GetZ(); + for (int idx = 0; idx < graph.GetN(); ++idx) { + double x = *(xPtr + idx); + double y = *(yPtr + idx); + double z = *(zPtr + idx); + graph.SetPoint(idx, x, TMath::DegToRad() * y, z); + } + } + + static void shapeGraphPosNegate(TGraph2D& graph, bool negate) + { + if (!negate) return; + double* xPtr = graph.GetX(); + double* yPtr = graph.GetY(); + double* zPtr = graph.GetZ(); + for (int idx = 0; idx < graph.GetN(); ++idx) { + double x = *(xPtr + idx); + double y = *(yPtr + idx); + double z = *(zPtr + idx); + graph.SetPoint(idx, -x, y, z); + } + } +}; + +WireModScaleDebug::WireModScaleDebug(fhicl::ParameterSet const& pset) + : EDAnalyzer{pset} + , fRatioFileName_XXW{pset.get("RatioFileName_XXW", "Run4_Coarse_XW.root")} + , fThetaEdges{pset.get>("ThetaEdges", + {0, 6, 12, 18, 24, 30, 38, 46, 56, 90})} +{ +} + +void WireModScaleDebug::beginJob() +{ + const geo::GeometryCore* geometry = lar::providerFrom(); + const geo::WireReadoutGeom* wireReadout = &(art::ServiceHandle()->Get()); + + TFile* ratioFile = new TFile(("./" + fRatioFileName_XXW).c_str(), "READ"); + if (!ratioFile || ratioFile->IsZombie()) { + std::cout << "ERROR: could not open " << fRatioFileName_XXW + << " in current directory. Run lar from the directory containing it.\n"; + return; + } + + struct TPCSetInfo { unsigned cryo; unsigned tpcset; unsigned globalTPC; std::string name; }; + std::vector tpcsets = { + {0, 0, 0, "EE"}, {0, 1, 1, "EW"}, {1, 0, 2, "WE"}, {1, 1, 3, "WW"} + }; + + std::cout + << "TPC,plane,cathode_X,test_X,theta_xw_deg,theta_bin," + << "interp_raw_q,found_scale_q,interp_raw_sigma,found_scale_sigma," + << "nearest_node_theta_deg,expected_scale_q,expected_scale_sigma\n"; + + for (auto const& tpcinfo : tpcsets) { + readout::TPCsetID tpcsetid(tpcinfo.cryo, tpcinfo.tpcset); + geo::TPCID tpcid = wireReadout->TPCsetToTPCs(tpcsetid).front(); + const geo::TPCGeo* tpcGeom = geometry->TPCPtr(tpcid); + double cathodeX = tpcGeom->GetCathodeCenter().X(); + bool negate = (cathodeX <= 0); + + for (int plane = 0; plane < 3; ++plane) { + std::string nameQ = "TPC" + std::to_string(tpcinfo.globalTPC) + "_plane" + + std::to_string(plane) + "_ratio_integral"; + std::string nameS = "TPC" + std::to_string(tpcinfo.globalTPC) + "_plane" + + std::to_string(plane) + "_ratio_width"; + + TGraph2D* gQ_orig = dynamic_cast(ratioFile->Get(nameQ.c_str())); + TGraph2D* gS_orig = dynamic_cast(ratioFile->Get(nameS.c_str())); + if (!gQ_orig || !gS_orig) { + std::cout << "MISSING graph " << nameQ << " or " << nameS << "\n"; + continue; + } + TGraph2D* gQ = static_cast(gQ_orig->Clone()); + TGraph2D* gS = static_cast(gS_orig->Clone()); + + // mirrors WireModifierXXW_module.cc reconfigure() (InRadians:false, XAbs:true) + shapeGraphAngle(*gQ); + shapeGraphAngle(*gS); + shapeGraphPosNegate(*gQ, negate); + shapeGraphPosNegate(*gS, negate); + + double xmin = gQ->GetXmin(), xmax = gQ->GetXmax(); + double xmag = 0.5 * (std::abs(xmin) + std::abs(xmax)); + double testX = negate ? -xmag : xmag; + + double* xPtrQ = gQ->GetX(); + double* yPtrQ = gQ->GetY(); + double* zPtrQ = gQ->GetZ(); + double* zPtrS = gS->GetZ(); + int nPts = gQ->GetN(); + + for (double theta_deg = 0.0; theta_deg <= 90.0; theta_deg += 2.0) { + double theta_rad = theta_deg * TMath::DegToRad(); + + double raw_q = gQ->Interpolate(testX, theta_rad); + double raw_s = gS->Interpolate(testX, theta_rad); + // production threshold check (WireModUtility.cc): > 0.001 else default 1.0 + double found_q = (raw_q > 0.001) ? raw_q : 1.0; + double found_s = (raw_s > 0.001) ? raw_s : 1.0; + + // nearest real calibration grid node (2D nearest neighbor) + double bestD = 1e18; + int bestIdx = -1; + for (int i = 0; i < nPts; ++i) { + double dx = xPtrQ[i] - testX; + double dy = yPtrQ[i] - theta_rad; + double d = dx * dx * 1e-4 + dy * dy; // theta-dominated distance (X fixed at midpoint) + if (d < bestD) { bestD = d; bestIdx = i; } + } + double nearest_theta_deg = yPtrQ[bestIdx] * TMath::RadToDeg(); + double expected_q = zPtrQ[bestIdx]; + double expected_s = zPtrS[bestIdx]; + + int thetaBin = -1; + for (size_t b = 0; b + 1 < fThetaEdges.size(); ++b) + if (theta_deg >= fThetaEdges[b] && theta_deg < fThetaEdges[b + 1]) { thetaBin = (int)b; break; } + + std::cout << std::fixed + << tpcinfo.name << "," << plane << "," + << std::setprecision(1) << cathodeX << "," + << std::setprecision(1) << testX << "," + << std::setprecision(1) << theta_deg << "," << thetaBin << "," + << std::setprecision(4) << raw_q << "," << found_q << "," + << raw_s << "," << found_s << "," + << std::setprecision(1) << nearest_theta_deg << "," + << std::setprecision(4) << expected_q << "," << expected_s + << "\n"; + } + } + } + + ratioFile->Close(); +} + +DEFINE_ART_MODULE(WireModScaleDebug) + +} // namespace wiremod diff --git a/icaruscode/WireMod/WireModifier.fcl b/icaruscode/WireMod/WireModifier.fcl new file mode 100644 index 000000000..b0056cca2 --- /dev/null +++ b/icaruscode/WireMod/WireModifier.fcl @@ -0,0 +1,125 @@ +#include "stage0_icarus_defs.fcl" + +BEGIN_PROLOG + +standard_wiremod: +{ + module_type: "WireModifier" + WireLabel: "roifinder1d:PHYSCRATEDATATPCEE" + HitLabel: "gaushit1dTPCEE" + EDepOrigLabel: "ionization" + EDepShftLabel: "largeant:TPCActive" + OutputInstanceLabel: "PHYSCRATEDATATPCEE" + CryoNumber : 0 + TPCNumbers : [ 0, 1 ] + ApplyChannelScale : false + ApplyXScale : false + ApplyYZScale : false + ApplyXZAngleScale : false + ApplyYZAngleScale : false + ApplydEdXScale : false + RatioFileName : "NOFILE" + ChannelScaleHeight : "channelHeight_ratio" + ChannelScaleWidth : "channelWidth_ratio" + XScaleHeight : [ "xHeight_0_ratio_prof" , "xHeight_1_ratio_prof" , "xHeight_2_ratio_prof" ] + XScaleWidth : [ "xWidth_0_ratio_prof" , "xWidth_1_ratio_prof" , "xWidth_2_ratio_prof" ] + YZScaleHeight : [ "Graph2D_from_yzHeight_EE_0_ratio", "Graph2D_from_yzHeight_EE_1_ratio", "Graph2D_from_yzHeight_EE_2_ratio" ] + YZScaleWidth : [ "Graph2D_from_yzWidth_EE_0_ratio" , "Graph2D_from_yzWidth_EE_1_ratio" , "Graph2D_from_yzWidth_EE_0_ratio" ] + XZAngleScaleHeight : [ "thHeight_EE_0_ratio" , "thHeight_EE_1_ratio" , "thHeight_EE_2_ratio" ] + XZAngleScaleWidth : [ "thWidth_EE_0_ratio" , "thWidth_EE_1_ratio" , "thWidth_EE_2_ratio" ] + YZAngleScaleHeight : [ "phHeight_EE_0_ratio" , "phHeight_EE_1_ratio" , "phHeight_EE_2_ratio" ] + YZAngleScaleWidth : [ "phWidth_EE_0_ratio" , "phWidth_EE_1_ratio" , "phWidth_EE_2_ratio" ] + dEdXScaleHeight : [ "dEdXHeight_EE_0_ratio" , "dEdXHeight_EE_1_ratio" , "dEdXHeight_EE_2_ratio" ] + dEdXScaleWidth : [ "dEdXWidth_EE_0_ratio" , "dEdXWidth_EE_1_ratio" , "dEdXWidth_EE_2_ratio" ] +} + +ww_wiremod: @local::standard_wiremod +ww_wiremod.WireLabel: "roifinder1d:PHYSCRATEDATATPCWW" +ww_wiremod.HitLabel: "gaushit1dTPCWW" +ww_wiremodOutputInstanceLabel: "PHYSCRATEDATATPCWW" +ww_wiremod.CryoNumber: 1 +ww_wiremod.TPCNumbers: [ 2, 3 ] +ww_wiremod.YZScaleHeight : [ "Graph2D_from_yzHeight_WW_0_ratio", "Graph2D_from_yzHeight_WW_1_ratio", "Graph2D_from_yzHeight_WW_2_ratio" ] +ww_wiremod.YZScaleWidth : [ "Graph2D_from_yzWidth_WW_0_ratio" , "Graph2D_from_yzWidth_WW_1_ratio" , "Graph2D_from_yzWidth_WW_0_ratio" ] +ww_wiremod.XZAngleScaleHeight : [ "thHeight_WW_0_ratio" , "thHeight_WW_1_ratio" , "thHeight_WW_2_ratio" ] +ww_wiremod.XZAngleScaleWidth : [ "thWidth_WW_0_ratio" , "thWidth_WW_1_ratio" , "thWidth_WW_2_ratio" ] +ww_wiremod.YZAngleScaleHeight : [ "phHeight_WW_0_ratio" , "phHeight_WW_1_ratio" , "phHeight_WW_2_ratio" ] +ww_wiremod.YZAngleScaleWidth : [ "phWidth_WW_0_ratio" , "phWidth_WW_1_ratio" , "phWidth_WW_2_ratio" ] +ww_wiremod.dEdXScaleHeight : [ "dEdXHeight_WW_0_ratio" , "dEdXHeight_WW_1_ratio" , "dEdXHeight_WW_2_ratio" ] +ww_wiremod.dEdXScaleWidth : [ "dEdXWidth_WW_0_ratio" , "dEdXWidth_WW_1_ratio" , "dEdXWidth_WW_2_ratio" ] + +we_wiremod: @local::standard_wiremod +we_wiremod.WireLabel: "roifinder1d:PHYSCRATEDATATPCWE" +we_wiremod.HitLabel: "gaushit1dTPCWE" +we_wiremodOutputInstanceLabel: "PHYSCRATEDATATPCWE" +we_wiremod.CryoNumber: 1 +we_wiremod.TPCNumbers: [ 0, 1 ] +we_wiremod.YZScaleHeight : [ "Graph2D_from_yzHeight_WE_0_ratio", "Graph2D_from_yzHeight_WE_1_ratio", "Graph2D_from_yzHeight_WE_2_ratio" ] +we_wiremod.YZScaleWidth : [ "Graph2D_from_yzWidth_WE_0_ratio" , "Graph2D_from_yzWidth_WE_1_ratio" , "Graph2D_from_yzWidth_WE_0_ratio" ] +we_wiremod.XZAngleScaleHeight : [ "thHeight_WE_0_ratio" , "thHeight_WE_1_ratio" , "thHeight_WE_2_ratio" ] +we_wiremod.XZAngleScaleWidth : [ "thWidth_WE_0_ratio" , "thWidth_WE_1_ratio" , "thWidth_WE_2_ratio" ] +we_wiremod.YZAngleScaleHeight : [ "phHeight_WE_0_ratio" , "phHeight_WE_1_ratio" , "phHeight_WE_2_ratio" ] +we_wiremod.YZAngleScaleWidth : [ "phWidth_WE_0_ratio" , "phWidth_WE_1_ratio" , "phWidth_WE_2_ratio" ] +we_wiremod.dEdXScaleHeight : [ "dEdXHeight_WE_0_ratio" , "dEdXHeight_WE_1_ratio" , "dEdXHeight_WE_2_ratio" ] +we_wiremod.dEdXScaleWidth : [ "dEdXWidth_WE_0_ratio" , "dEdXWidth_WE_1_ratio" , "dEdXWidth_WE_2_ratio" ] + +ew_wiremod: @local::standard_wiremod +ew_wiremod.WireLabel: "roifinder1d:PHYSCRATEDATATPCEW" +ew_wiremod.HitLabel: "gaushit1dTPCEW" +ew_wiremodOutputInstanceLabel: "PHYSCRATEDATATPCEW" +ew_wiremod.CryoNumber: 0 +ew_wiremod.TPCNumbers: [ 2, 3 ] +ew_wiremod.YZScaleHeight : [ "Graph2D_from_yzHeight_EW_0_ratio", "Graph2D_from_yzHeight_EW_1_ratio", "Graph2D_from_yzHeight_EW_2_ratio" ] +ew_wiremod.YZScaleWidth : [ "Graph2D_from_yzWidth_EW_0_ratio" , "Graph2D_from_yzWidth_EW_1_ratio" , "Graph2D_from_yzWidth_EW_0_ratio" ] +ew_wiremod.XZAngleScaleHeight : [ "thHeight_EW_0_ratio" , "thHeight_EW_1_ratio" , "thHeight_EW_2_ratio" ] +ew_wiremod.XZAngleScaleWidth : [ "thWidth_EW_0_ratio" , "thWidth_EW_1_ratio" , "thWidth_EW_2_ratio" ] +ew_wiremod.YZAngleScaleHeight : [ "phHeight_EW_0_ratio" , "phHeight_EW_1_ratio" , "phHeight_EW_2_ratio" ] +ew_wiremod.YZAngleScaleWidth : [ "phWidth_EW_0_ratio" , "phWidth_EW_1_ratio" , "phWidth_EW_2_ratio" ] +ew_wiremod.dEdXScaleHeight : [ "dEdXHeight_EW_0_ratio" , "dEdXHeight_EW_1_ratio" , "dEdXHeight_EW_2_ratio" ] +ew_wiremod.dEdXScaleWidth : [ "dEdXWidth_EW_0_ratio" , "dEdXWidth_EW_1_ratio" , "dEdXWidth_EW_2_ratio" ] + +ee_wiremod: @local::standard_wiremod +ee_wiremod.WireLabel: "roifinder1d:PHYSCRATEDATATPCEE" +ee_wiremod.HitLabel: "gaushit1dTPCEE" +ee_wiremodOutputInstanceLabel: "PHYSCRATEDATATPCEE" +ee_wiremod.CryoNumber: 0 +ee_wiremod.TPCNumbers: [ 0, 1 ] +ee_wiremod.YZScaleHeight : [ "Graph2D_from_yzHeight_EE_0_ratio", "Graph2D_from_yzHeight_EE_1_ratio", "Graph2D_from_yzHeight_EE_2_ratio" ] +ee_wiremod.YZScaleWidth : [ "Graph2D_from_yzWidth_EE_0_ratio" , "Graph2D_from_yzWidth_EE_1_ratio" , "Graph2D_from_yzWidth_EE_0_ratio" ] +ee_wiremod.XZAngleScaleHeight : [ "thHeight_EE_0_ratio" , "thHeight_EE_1_ratio" , "thHeight_EE_2_ratio" ] +ee_wiremod.XZAngleScaleWidth : [ "thWidth_EE_0_ratio" , "thWidth_EE_1_ratio" , "thWidth_EE_2_ratio" ] +ee_wiremod.YZAngleScaleHeight : [ "phHeight_EE_0_ratio" , "phHeight_EE_1_ratio" , "phHeight_EE_2_ratio" ] +ee_wiremod.YZAngleScaleWidth : [ "phWidth_EE_0_ratio" , "phWidth_EE_1_ratio" , "phWidth_EE_2_ratio" ] +ee_wiremod.dEdXScaleHeight : [ "dEdXHeight_EE_0_ratio" , "dEdXHeight_EE_1_ratio" , "dEdXHeight_EE_2_ratio" ] +ee_wiremod.dEdXScaleWidth : [ "dEdXWidth_EE_0_ratio" , "dEdXWidth_EE_1_ratio" , "dEdXWidth_EE_2_ratio" ] + +wiremod_Producers: { + WireModEE: @local::ee_wiremod + WireModEW: @local::ew_wiremod + WireModWE: @local::we_wiremod + WireModWW: @local::ww_wiremod + gaushit1dWireModTPCEE: @local::icarus_stage0_producers.gaushit1dTPCEE + gaushit1dWireModTPCEW: @local::icarus_stage0_producers.gaushit1dTPCEW + gaushit1dWireModTPCWE: @local::icarus_stage0_producers.gaushit1dTPCWE + gaushit1dWireModTPCWW: @local::icarus_stage0_producers.gaushit1dTPCWW + } +wiremod_Producers.gaushit1dWireModTPCEE.CalDataModuleLabel: "WireModEE" +wiremod_Producers.gaushit1dWireModTPCEW.CalDataModuleLabel: "WireModEW" +wiremod_Producers.gaushit1dWireModTPCWE.CalDataModuleLabel: "WireModWE" +wiremod_Producers.gaushit1dWireModTPCWW.CalDataModuleLabel: "WireModWW" + +wiremod_allTPC: [ + WireModEE, + WireModEW, + WireModWE, + WireModWW + ] + +icarus_stage0_WireModTPC: [ + gaushit1dWireModTPCEE, + gaushit1dWireModTPCEW, + gaushit1dWireModTPCWE, + gaushit1dWireModTPCWW + ] + +END_PROLOG diff --git a/icaruscode/WireMod/WireModifierXXW.fcl b/icaruscode/WireMod/WireModifierXXW.fcl new file mode 100644 index 000000000..3f656a6bb --- /dev/null +++ b/icaruscode/WireMod/WireModifierXXW.fcl @@ -0,0 +1,149 @@ +#include "stage1_icarus_defs.fcl" +#include "wirechannelroiconverters_sbn.fcl" + +BEGIN_PROLOG + +dummyGaushit2dTPCEE: { @table::icarus_stage1_producers.gaushit2dTPCEE } +dummyGaushit2dTPCEW: { @table::icarus_stage1_producers.gaushit2dTPCEW } +dummyGaushit2dTPCWE: { @table::icarus_stage1_producers.gaushit2dTPCWE } +dummyGaushit2dTPCWW: { @table::icarus_stage1_producers.gaushit2dTPCWW } +dummyGaushit2dSeq: [dummyGaushit2dTPCEE, dummyGaushit2dTPCEW, dummyGaushit2dTPCWE, dummyGaushit2dTPCWW] +dummyGaushit2dTab: { dummyGaushit2dTPCEE: @local::dummyGaushit2dTPCEE + dummyGaushit2dTPCEW: @local::dummyGaushit2dTPCEW + dummyGaushit2dTPCWE: @local::dummyGaushit2dTPCWE + dummyGaushit2dTPCWW: @local::dummyGaushit2dTPCWW } + +WMROI2Wire: +{ + module_type: "ChannelROIToWire" + WireModuleLabelVec: [ "wire2channelroi2d:PHYSCRATEDATATPCEE", + "wire2channelroi2d:PHYSCRATEDATATPCEW", + "wire2channelroi2d:PHYSCRATEDATATPCWE", + "wire2channelroi2d:PHYSCRATEDATATPCWW" ] + OutInstanceLabelVec: [ "PHYSCRATEDATATPCEE", + "PHYSCRATEDATATPCEW", + "PHYSCRATEDATATPCWE", + "PHYSCRATEDATATPCWW" ] + DiagnosticOutput: false + UseFloatPrecision: true +} + +WireMod: +{ + module_type: "WireModifierXXW" + RatioFileName_YZ: "NOFILE" + RatioFileName_XXW: "allRatio_Coarse_XW.root" + LocalRatios: false + EDepLabel: "filtersed" + EDepShiftedLabel: "shiftedpriorSCE" + SaveByChannel: false + SaveByWire: false + SaveROITree: false + SaveTickHistograms: false + SavePerHitData: false + InRadians: false + XAbs: true +} + +WireModTPCEE: @local::WireMod +WireModTPCEE.Cryo: 0 +WireModTPCEE.TPCset: 0 +WireModTPCEE.XXWScaleIntegral: [ "TPC0_plane0_ratio_integral", + "TPC0_plane1_ratio_integral", + "TPC0_plane2_ratio_integral"] +WireModTPCEE.XXWScaleWidth: [ "TPC0_plane0_ratio_width", + "TPC0_plane1_ratio_width", + "TPC0_plane2_ratio_width"] +WireModTPCEE.YZScaleIntegral: [ "TPC0_plane0_ratio_integral", + "TPC0_plane1_ratio_integral", + "TPC0_plane2_ratio_integral"] +WireModTPCEE.YZScaleWidth: [ "TPC0_plane0_ratio_width", + "TPC0_plane1_ratio_width", + "TPC0_plane2_ratio_width"] +WireModTPCEE.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCEE" +WireModTPCEE.HitLabel: "dummyGaushit2dTPCEE" + +WireModTPCEW: @local::WireMod +WireModTPCEW.Cryo: 0 +WireModTPCEW.TPCset: 1 +WireModTPCEW.XXWScaleIntegral: [ "TPC1_plane0_ratio_integral", + "TPC1_plane1_ratio_integral", + "TPC1_plane2_ratio_integral"] +WireModTPCEW.XXWScaleWidth: [ "TPC1_plane0_ratio_width", + "TPC1_plane1_ratio_width", + "TPC1_plane2_ratio_width"] +WireModTPCEW.YZScaleIntegral: [ "TPC1_plane0_ratio_integral", + "TPC1_plane1_ratio_integral", + "TPC1_plane2_ratio_integral"] +WireModTPCEW.YZScaleWidth: [ "TPC1_plane0_ratio_width", + "TPC1_plane1_ratio_width", + "TPC1_plane2_ratio_width"] +WireModTPCEW.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCEW" +WireModTPCEW.HitLabel: "dummyGaushit2dTPCEW" + +WireModTPCWE: @local::WireMod +WireModTPCWE.Cryo: 1 +WireModTPCWE.TPCset: 0 +WireModTPCWE.XXWScaleIntegral: [ "TPC2_plane0_ratio_integral", + "TPC2_plane1_ratio_integral", + "TPC2_plane2_ratio_integral"] +WireModTPCWE.XXWScaleWidth: [ "TPC2_plane0_ratio_width", + "TPC2_plane1_ratio_width", + "TPC2_plane2_ratio_width"] +WireModTPCWE.YZScaleIntegral: [ "TPC2_plane0_ratio_integral", + "TPC2_plane1_ratio_integral", + "TPC2_plane2_ratio_integral"] +WireModTPCWE.YZScaleWidth: [ "TPC2_plane0_ratio_width", + "TPC2_plane1_ratio_width", + "TPC2_plane2_ratio_width"] +WireModTPCWE.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCWE" +WireModTPCWE.HitLabel: "dummyGaushit2dTPCWE" + +WireModTPCWW: @local::WireMod +WireModTPCWW.Cryo: 1 +WireModTPCWW.TPCset: 1 +WireModTPCWW.XXWScaleIntegral: [ "TPC3_plane0_ratio_integral", + "TPC3_plane1_ratio_integral", + "TPC3_plane2_ratio_integral"] +WireModTPCWW.XXWScaleWidth: [ "TPC3_plane0_ratio_width", + "TPC3_plane1_ratio_width", + "TPC3_plane2_ratio_width"] +WireModTPCWW.YZScaleIntegral: [ "TPC3_plane0_ratio_integral", + "TPC3_plane1_ratio_integral", + "TPC3_plane2_ratio_integral"] +WireModTPCWW.YZScaleWidth: [ "TPC3_plane0_ratio_width", + "TPC3_plane1_ratio_width", + "TPC3_plane2_ratio_width"] +WireModTPCWW.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCWW" +WireModTPCWW.HitLabel: "dummyGaushit2dTPCWW" + +WireModSeq: [ WireModTPCEE, WireModTPCEW, WireModTPCWE, WireModTPCWW ] +WireModTab: { WireModTPCEE: @local::WireModTPCEE + WireModTPCEW: @local::WireModTPCEW + WireModTPCWE: @local::WireModTPCWE + WireModTPCWW: @local::WireModTPCWW } + +WMWireToROI: +{ + module_type: "WireToChannelROI" + WireModuleLabelVec: [ "WireModTPCEE", + "WireModTPCEW", + "WireModTPCWE", + "WireModTPCWW" ] + OutInstanceLabelVec: [ "PHYSCRATEDATATPCEE", + "PHYSCRATEDATATPCEW", + "PHYSCRATEDATATPCWE", + "PHYSCRATEDATATPCWW" ] + DiagnosticOutput: false +} + +WireModSequence: [ @sequence::dummyGaushit2dSeq, WMROI2Wire, @sequence::WireModSeq, WMWireToROI ] +WireModTable: +{ + @table::dummyGaushit2dTab + WMROI2Wire: @local::WMROI2Wire + @table::WireModTab + WMWireToROI: @local::WMWireToROI +} + +END_PROLOG diff --git a/icaruscode/WireMod/WireModifierXXW_closure.fcl b/icaruscode/WireMod/WireModifierXXW_closure.fcl new file mode 100644 index 000000000..ed1dff124 --- /dev/null +++ b/icaruscode/WireMod/WireModifierXXW_closure.fcl @@ -0,0 +1,160 @@ +#include "stage1_icarus_defs.fcl" +#include "wirechannelroiconverters_sbn.fcl" + +BEGIN_PROLOG + +dummyGaushit2dTPCEE: { @table::icarus_stage1_producers.gaushit2dTPCEE } +dummyGaushit2dTPCEW: { @table::icarus_stage1_producers.gaushit2dTPCEW } +dummyGaushit2dTPCWE: { @table::icarus_stage1_producers.gaushit2dTPCWE } +dummyGaushit2dTPCWW: { @table::icarus_stage1_producers.gaushit2dTPCWW } +dummyGaushit2dSeq: [dummyGaushit2dTPCEE, dummyGaushit2dTPCEW, dummyGaushit2dTPCWE, dummyGaushit2dTPCWW] +dummyGaushit2dTab: { dummyGaushit2dTPCEE: @local::dummyGaushit2dTPCEE + dummyGaushit2dTPCEW: @local::dummyGaushit2dTPCEW + dummyGaushit2dTPCWE: @local::dummyGaushit2dTPCWE + dummyGaushit2dTPCWW: @local::dummyGaushit2dTPCWW } + +WMROI2Wire: +{ + module_type: "ChannelROIToWire" + WireModuleLabelVec: [ "wire2channelroi2d:PHYSCRATEDATATPCEE", + "wire2channelroi2d:PHYSCRATEDATATPCEW", + "wire2channelroi2d:PHYSCRATEDATATPCWE", + "wire2channelroi2d:PHYSCRATEDATATPCWW" ] + OutInstanceLabelVec: [ "PHYSCRATEDATATPCEE", + "PHYSCRATEDATATPCEW", + "PHYSCRATEDATATPCWE", + "PHYSCRATEDATATPCWW" ] + DiagnosticOutput: false + UseFloatPrecision: true # avoid std::round() to 1 ADC steps +} + +WireMod: +{ + module_type: "WireModifierXXW" + RatioFileName_XXW: "Run4_Coarse_XW.root" + RatioFileName_YZ: "allRatio_Coarse_XW.root" + LocalRatios: true + EDepLabel: "filtersed" + EDepShiftedLabel: "shiftedpriorSCE" + SaveByChannel: false + SaveByWire: false + SaveROITree: false + SaveTickHistograms: false + SavePerHitData: false + InRadians: false + XAbs: true + UseChannelROIMode: false # true = read ChannelROI directly, bypassing Wire rounding + AdditiveModification: false # true = after = before + (q_mod - q_orig) + + SetNullScaleIntegral: false # true = force r_Q=1 + SetNullScaleWidth: false # true = force r_sigma=1 + UseGraph2DInterpolation: true # false = nearest bin center instead of Delaunay interpolation +} + +WireModTPCEE: @local::WireMod +WireModTPCEE.Cryo: 0 +WireModTPCEE.TPCset: 0 +WireModTPCEE.XXWScaleIntegral: [ "TPC0_plane0_ratio_integral", + "TPC0_plane1_ratio_integral", + "TPC0_plane2_ratio_integral"] +WireModTPCEE.XXWScaleWidth: [ "TPC0_plane0_ratio_width", + "TPC0_plane1_ratio_width", + "TPC0_plane2_ratio_width"] +WireModTPCEE.YZScaleIntegral: [ "TPC0_plane0_ratio_integral", + "TPC0_plane1_ratio_integral", + "TPC0_plane2_ratio_integral"] +WireModTPCEE.YZScaleWidth: [ "TPC0_plane0_ratio_width", + "TPC0_plane1_ratio_width", + "TPC0_plane2_ratio_width"] +WireModTPCEE.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCEE" +WireModTPCEE.ChannelLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +WireModTPCEE.HitLabel: "dummyGaushit2dTPCEE" + +WireModTPCEW: @local::WireMod +WireModTPCEW.Cryo: 0 +WireModTPCEW.TPCset: 1 +WireModTPCEW.XXWScaleIntegral: [ "TPC1_plane0_ratio_integral", + "TPC1_plane1_ratio_integral", + "TPC1_plane2_ratio_integral"] +WireModTPCEW.XXWScaleWidth: [ "TPC1_plane0_ratio_width", + "TPC1_plane1_ratio_width", + "TPC1_plane2_ratio_width"] +WireModTPCEW.YZScaleIntegral: [ "TPC1_plane0_ratio_integral", + "TPC1_plane1_ratio_integral", + "TPC1_plane2_ratio_integral"] +WireModTPCEW.YZScaleWidth: [ "TPC1_plane0_ratio_width", + "TPC1_plane1_ratio_width", + "TPC1_plane2_ratio_width"] +WireModTPCEW.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCEW" +WireModTPCEW.ChannelLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +WireModTPCEW.HitLabel: "dummyGaushit2dTPCEW" + +WireModTPCWE: @local::WireMod +WireModTPCWE.Cryo: 1 +WireModTPCWE.TPCset: 0 +WireModTPCWE.XXWScaleIntegral: [ "TPC2_plane0_ratio_integral", + "TPC2_plane1_ratio_integral", + "TPC2_plane2_ratio_integral"] +WireModTPCWE.XXWScaleWidth: [ "TPC2_plane0_ratio_width", + "TPC2_plane1_ratio_width", + "TPC2_plane2_ratio_width"] +WireModTPCWE.YZScaleIntegral: [ "TPC2_plane0_ratio_integral", + "TPC2_plane1_ratio_integral", + "TPC2_plane2_ratio_integral"] +WireModTPCWE.YZScaleWidth: [ "TPC2_plane0_ratio_width", + "TPC2_plane1_ratio_width", + "TPC2_plane2_ratio_width"] +WireModTPCWE.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCWE" +WireModTPCWE.ChannelLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +WireModTPCWE.HitLabel: "dummyGaushit2dTPCWE" + +WireModTPCWW: @local::WireMod +WireModTPCWW.Cryo: 1 +WireModTPCWW.TPCset: 1 +WireModTPCWW.XXWScaleIntegral: [ "TPC3_plane0_ratio_integral", + "TPC3_plane1_ratio_integral", + "TPC3_plane2_ratio_integral"] +WireModTPCWW.XXWScaleWidth: [ "TPC3_plane0_ratio_width", + "TPC3_plane1_ratio_width", + "TPC3_plane2_ratio_width"] +WireModTPCWW.YZScaleIntegral: [ "TPC3_plane0_ratio_integral", + "TPC3_plane1_ratio_integral", + "TPC3_plane2_ratio_integral"] +WireModTPCWW.YZScaleWidth: [ "TPC3_plane0_ratio_width", + "TPC3_plane1_ratio_width", + "TPC3_plane2_ratio_width"] +WireModTPCWW.WireLabel: "WMROI2Wire:PHYSCRATEDATATPCWW" +WireModTPCWW.ChannelLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" +WireModTPCWW.HitLabel: "dummyGaushit2dTPCWW" + +WireModSeq: [ WireModTPCEE, WireModTPCEW, WireModTPCWE, WireModTPCWW ] +WireModTab: { WireModTPCEE: @local::WireModTPCEE + WireModTPCEW: @local::WireModTPCEW + WireModTPCWE: @local::WireModTPCWE + WireModTPCWW: @local::WireModTPCWW } + +WMWireToROI: +{ + module_type: "WireToChannelROI" + WireModuleLabelVec: [ "WireModTPCEE", + "WireModTPCEW", + "WireModTPCWE", + "WireModTPCWW" ] + OutInstanceLabelVec: [ "PHYSCRATEDATATPCEE", + "PHYSCRATEDATATPCEW", + "PHYSCRATEDATATPCWE", + "PHYSCRATEDATATPCWW" ] + DiagnosticOutput: false +} + +WireModSequence: [ @sequence::dummyGaushit2dSeq, WMROI2Wire, @sequence::WireModSeq, WMWireToROI ] +WireModTable: +{ + @table::dummyGaushit2dTab + WMROI2Wire: @local::WMROI2Wire + @table::WireModTab + WMWireToROI: @local::WMWireToROI +} + +END_PROLOG + diff --git a/icaruscode/WireMod/WireModifierXXW_module.cc b/icaruscode/WireMod/WireModifierXXW_module.cc new file mode 100644 index 000000000..200241a06 --- /dev/null +++ b/icaruscode/WireMod/WireModifierXXW_module.cc @@ -0,0 +1,1618 @@ +// std inlcudes +#include +#include +#include +#include + +// ROOT includes +#include "TF1.h" +#include "TGraph.h" +#include "TH1D.h" +#include "TH2F.h" +#include "TTree.h" + +// art includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "cetlib_except/exception.h" + +// larsoft includes +#include "larcore/Geometry/Geometry.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() +#include "lardata/DetectorInfoServices/DetectorPropertiesService.h" +#include "lardata/DetectorInfoServices/DetectorClocksService.h" +#include "larsim/MCCheater/BackTrackerService.h" +#include "larevt/SpaceCharge/SpaceCharge.h" +#include "larevt/SpaceChargeServices/SpaceChargeService.h" +#include "lardataobj/Simulation/SimChannel.h" +#include "nusimdata/SimulationBase/MCParticle.h" +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RawData/RawDigit.h" +#include "lardataobj/RecoBase/Wire.h" +#include "sbnobj/ICARUS/TPC/ChannelROI.h" +#include "icaruscode/TPC/Utilities/ChannelROICreator.h" + +// wiremod +#include "sbncode/WireMod/Utility/WireModUtility.hh" + +//namespace +namespace wiremod +{ + + class WireModifierXXW : public art::EDProducer + { + public: + explicit WireModifierXXW(fhicl::ParameterSet const& pset); + void shapeGraphAngle(TGraph2D& graph); + void shapeGraphPos(TGraph2D& graph, const readout::TPCsetID& tpcsetid); + void reconfigure(fhicl::ParameterSet const& pset); + void produce(art::Event& evt) override; + + private: + const geo::GeometryCore* fGeometry = lar::providerFrom(); // get the geometry + const geo::WireReadoutGeom* fWireReadout = &(art::ServiceHandle()->Get()); + const detinfo::DetectorClocksData fDetClocksData = art::ServiceHandle()->DataForJob(); + const art::ServiceHandle fBT; + std::string fRatioFileName_XXW; // there is where we try to grab the splines/graphs (if they exist) + std::vector fGraph_charge_XXW; + std::vector fGraph_sigma_XXW; + std::string fRatioFileName_YZ; + std::vector fGraph_charge_YZ; + std::vector fGraph_sigma_YZ; + art::InputTag fWireLabel; // which wires are we pulling in? + art::InputTag fHitLabel; // which hits are we pulling in? + art::InputTag fEDepLabel; // which are the EDeps? (legacy; now only the tick diagnostic) + art::InputTag fEDepShiftedLabel; // which are the EDeps? (legacy; now only the tick diagnostic) + art::InputTag fSimChannelLabel; // SimChannels for IDE-based scale truth (default "merge") + art::InputTag fG4Label; // MCParticles for trajectory direction (default "largeant") + unsigned int fCryo; // which Cryo are we in? + unsigned int fTPCset; // which TPC are we in? + bool fLocalRatios; // is the ratio file local? + bool fSaveHistsByChannel; // save modified signals by channel? + bool fSaveHistsByWire; // save modified signals by wire? + bool fSaveROITree; // fill ROITree TTree (before/after waveforms)? + bool fSaveTickHistograms; // fill EDep/Hit tick-vs-channel TH2Fs? + bool fSavePerHitData; // write per-hit scaleQ/scaleSigma/truthX/thetaXW/isMC art products? + bool fInRads; // is the TGraph2D angle axis in radians? + bool fXAbs; // is the TGraph2D x an absolute value? + bool fAdditiveModification; // additive (true) vs multiplicative (false) ROI modification + bool fSetNullScaleIntegral; // if true, force r_Q=1 for all sub-ROIs (disable integral scaling) + bool fSetNullScaleWidth; // if true, force r_sigma=1 for all sub-ROIs (disable width scaling) + bool fUseGraph2DInterpolation; // true = Delaunay interp (default), false = nearest bin center + bool fUseChannelROIMode; // true = read ChannelROI directly (float precision), false = Wire (nominal) + art::InputTag fChannelLabel; // ChannelROI input label, used only when fUseChannelROIMode is true + double fOffset; // ad hoc offset + TH2F* fEdepTickInd1 = nullptr; + TH2F* fEdepTickInd2 = nullptr; + TH2F* fEdepTickColl = nullptr; + TH2F* fHitTickInd1 = nullptr; + TH2F* fHitTickInd2 = nullptr; + TH2F* fHitTickColl = nullptr; + TH2F* fEdepXvsChan = nullptr; + TH2F* fHitXvsChan = nullptr; + TH2F* fHitBTvsDetProp = nullptr; + + // diagnostic tree for ROI modification studies + TTree* fROITree = nullptr; + Int_t tb_run; + Int_t tb_subrun; + Int_t tb_event; + Int_t tb_channel; + Int_t tb_wire; + Int_t tb_tpc; + Int_t tb_plane; + Int_t tb_roi_idx; + Float_t tb_roi_begin; + Float_t tb_roi_before_total_q; + Float_t tb_roi_before_center; + Float_t tb_roi_before_sigma; + Float_t tb_roi_after_total_q; + Float_t tb_roi_after_center; + Float_t tb_roi_after_sigma; + std::vector tb_roi_before; + std::vector tb_roi_after; + std::vector tb_hit_before_center; + std::vector tb_hit_before_integral; + std::vector tb_hit_before_sigma; + std::vector tb_hit_after_center; + std::vector tb_hit_after_integral; + std::vector tb_hit_after_sigma; + std::vector tb_scale_Q; + std::vector tb_scale_sigma; + std::vector tb_theta_xw; + std::vector tb_truth_x; // truth X coordinate used for XXW graph lookup + std::vector tb_track_id; + // 0=no EDep matched (overlay data hit) + // 1=energy veto (truth_E<0.3 && Q>80) + // 2=scaling applied (scale!=1) + // 3=EDep matched but map evaluates to 1 + std::vector tb_scale_reason; + char tb_xxw_graph_name[128]; // name of the sigma TGraph2D used for this ROI's plane + std::vector fNameVec_sigma_XXW; // kept from reconfigure for tree output + Int_t tb_roi_n_hits; // total hits matched to this ROI + Int_t tb_roi_n_pulse_train_hits; // hits with GoodnessOfFit==-1 && DoF==1 + Int_t tb_roi_is_pulse_train; // 1 if any hit is a pulse train + + }; // end WireModifierXXW class + + //------------------------------------------------ + WireModifierXXW::WireModifierXXW(fhicl::ParameterSet const& pset) : EDProducer{pset} + { + // get the fhicl parameters + this->reconfigure(pset); + } + + //------------------------------------------------ + void WireModifierXXW::shapeGraphAngle(TGraph2D& graph) + { + // The graphs can be passed in degrees, but we want radians + // convert the y-axis to radians + double* xPtr = graph.GetX(); + double* yPtr = graph.GetY(); + double* zPtr = graph.GetZ(); + for (int idx = 0; idx < graph.GetN(); ++idx) + { + double x = *(xPtr+idx); + double y = *(yPtr+idx); + double z = *(zPtr+idx); + graph.SetPoint(idx, x, TMath::DegToRad() * y, z); + } + } + + //------------------------------------------------ + void WireModifierXXW::shapeGraphPos(TGraph2D& graph, const readout::TPCsetID& tpcsetid) + { + // The graphs can be passed in abs(x), but we want global x + // convert the x-axis to detector x,y,z coordinates + mf::LogDebug("WireModifierXXW") + << "Starting graph x range: [" << graph.GetXmin() + << ", " << graph.GetXmax() << "]"; + + // get the cathode possition, the drift direction, and the drift distance from geom + // get the first TPC Geom since the cathode should be the same in all of them + geo::TPCID tpcid = fWireReadout->TPCsetToTPCs(tpcsetid).front(); + const geo::TPCGeo* tpcGeom = fGeometry->TPCPtr(tpcid); + double cathode = tpcGeom->GetCathodeCenter().X(); + + double* xPtr = graph.GetX(); + double* yPtr = graph.GetY(); + double* zPtr = graph.GetZ(); + for (int idx = 0; idx < graph.GetN(); ++idx) + { + double x = *(xPtr+idx); + double y = *(yPtr+idx); + double z = *(zPtr+idx); + if (cathode > 0) + { + graph.SetPoint(idx, x, y, z); + } else { + graph.SetPoint(idx, -x, y, z); + } + } + + mf::LogDebug("WireModifierXXW") + << "Ending graph x range: [" << graph.GetXmin() + << ", " << graph.GetXmax() << "]"; + } + + //------------------------------------------------ + void WireModifierXXW::reconfigure(fhicl::ParameterSet const& pset) + { + fWireLabel = pset.get("WireLabel"); + fHitLabel = pset.get("HitLabel"); + fEDepLabel = pset.get("EDepLabel"); + fEDepShiftedLabel = pset.get("EDepShiftedLabel"); + fSimChannelLabel = pset.get("SimChannelLabel", art::InputTag("merge")); + fG4Label = pset.get("G4Label", art::InputTag("largeant")); + fCryo = pset.get("Cryo"); + fTPCset = pset.get("TPCset"); + + // what, if anything, are we putting in the histogram files + fSaveHistsByChannel = pset.get("SaveByChannel", false); + fSaveHistsByWire = pset.get("SaveByWire", false); + fSaveROITree = pset.get("SaveROITree", false); + fSaveTickHistograms = pset.get("SaveTickHistograms", false); + fSavePerHitData = pset.get("SavePerHitData", false); + + // do we need to reshape the TGraph2D? + fInRads = pset.get("InRadians", true); + fXAbs = pset.get("XAbs", false); + + // additive vs multiplicative ROI modification + fAdditiveModification = pset.get("AdditiveModification", false); + fSetNullScaleIntegral = pset.get("SetNullScaleIntegral", false); + fSetNullScaleWidth = pset.get("SetNullScaleWidth", false); + fUseGraph2DInterpolation = pset.get("UseGraph2DInterpolation", true); + + // ChannelROI direct mode (float precision, bypasses Wire intermediate) + fUseChannelROIMode = pset.get("UseChannelROIMode", false); + if (fUseChannelROIMode) + fChannelLabel = pset.get("ChannelLabel"); + + // try to read in the graphs/splines from a file + // if that file does not exist then fake them + fRatioFileName_XXW = pset.get("RatioFileName_XXW", "NOFILE"); + fLocalRatios = pset.get("LocalRatios", false); + if (fRatioFileName_XXW == "NOFILE") + { + mf::LogVerbatim("WireModifierXXW") + << "WireModifierXXW::reconfigure - No ratio file given. No scaling is applied..."; + } else if (fRatioFileName_XXW == "DUMMYSCALE") + { + mf::LogVerbatim("WireModifierXXW") + << "WireModifierXXW::reconfigure - Fake universal 2x scaling is applied..."; + + // make a graph spanning -400 to 400 in X and -4 to 4 in ThXW (for completeness) + // all point have a value of 2 + TGraph2D* temp = new TGraph2D(); + for (size_t idx = 0; idx < 4; ++idx) + { + double x = (static_cast(idx & 2) - 1)*400; + double y = (static_cast(2*(idx & 1)) - 1)*4; + temp->AddPoint(x, y, 2); + } + for (size_t idx = 0; idx < 3; ++idx) + { + fGraph_charge_XXW.push_back(temp); + fGraph_sigma_XXW.push_back(temp); + } + } else { + std::string dir_path; + if (not fLocalRatios) + { + char* icaruscode_dir = std::getenv("ICARUSCODE_DIR"); + if (not icaruscode_dir) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - ICARUSCODE_DIR environment variable must be set!"; + } + dir_path = std::string(icaruscode_dir) + "/root/WireMod"; + } else + { + dir_path = "."; + } + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Get file " << fRatioFileName_XXW + << " from directory " << dir_path; + TFile* ratioFile = new TFile((dir_path + "/" + fRatioFileName_XXW).c_str(), "READ"); // read only + if (not ratioFile) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - Could not open ratio file"; + } + // the file exists! pull the ratios + if (not ratioFile) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - WireMod Ratio File Must Exist!"; + } + if (ratioFile->IsZombie()) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - WireMod Ratio File Must Not be a Zombie!"; + } + mf::LogVerbatim("WireModifierXXW") + << "WireModifierXXW::reconfigure - Getting XXW Scales..."; + std::vector nameVec_charge_XXW = pset.get>("XXWScaleIntegral"); + for (auto const& name : nameVec_charge_XXW) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Looking for " << name << " in TFile " << fRatioFileName_XXW << "..."; + TGraph2D* temp = static_cast(ratioFile->Get(name.c_str())->Clone()); + if (temp != nullptr) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...found"; + if (not fInRads) + shapeGraphAngle(*temp); + if (fXAbs) + shapeGraphPos(*temp, readout::TPCsetID(fCryo, fTPCset)); + fGraph_charge_XXW.push_back(temp); + } else { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...not found. Don't scale for this plane."; + // make a graph spanning -400 to 400 in X and -4 to 4 in ThXW (for completeness) + // all point have a value of 1 + temp = new TGraph2D(); + for (size_t idx = 0; idx < 4; ++idx) + { + double x = (static_cast(idx & 2) - 1)*400; + double y = (static_cast(2*(idx & 1)) - 1)*4; + temp->AddPoint(x, y, 1); + } + fGraph_charge_XXW.push_back(temp); + } + } + std::vector nameVec_sigma_XXW = pset.get>("XXWScaleWidth"); + fNameVec_sigma_XXW = nameVec_sigma_XXW; + for (auto const& name : nameVec_sigma_XXW) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Looking for " << name << " in TFile " << fRatioFileName_XXW << "..."; + TGraph2D* temp = static_cast(ratioFile->Get(name.c_str())->Clone()); + if (temp != nullptr) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...found"; + if (not fInRads) + shapeGraphAngle(*temp); + if (fXAbs) + shapeGraphPos(*temp, readout::TPCsetID(fCryo, fTPCset)); + fGraph_sigma_XXW.push_back(temp); + } else { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...not found. Don't scale for this plane."; + // make a graph spanning -400 to 400 in X and -4 to 4 in ThXW (for completeness) + // all point have a value of 1 + temp = new TGraph2D(); + for (size_t idx = 0; idx < 4; ++idx) + { + double x = (static_cast(idx & 2) - 1)*400; + double y = (static_cast(2*(idx & 1)) - 1)*4; + temp->AddPoint(x, y, 1); + } + fGraph_sigma_XXW.push_back(temp); + } + } + } + fRatioFileName_YZ = pset.get("RatioFileName_YZ", "NOFILE"); + fLocalRatios = pset.get("LocalRatios", false); + if (fRatioFileName_YZ == "NOFILE") + { + mf::LogVerbatim("WireModifierXXW") + << "WireModifierXXW::reconfigure - No ratio file given. No scaling is applied..."; + } else { + std::string dir_path; + if (not fLocalRatios) + { + char* icaruscode_dir = std::getenv("ICARUSCODE_DIR"); + if (not icaruscode_dir) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - ICARUSCODE_DIR environment variable must be set!"; + } + dir_path = std::string(icaruscode_dir) + "/root/WireMod"; + } else + { + dir_path = "."; + } + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Get file " << fRatioFileName_YZ + << " from directory " << dir_path; + TFile* ratioFile = new TFile((dir_path + "/" + fRatioFileName_YZ).c_str(), "READ"); // read only + if (not ratioFile) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - Could not open ratio file"; + } + // the file exists! pull the ratios + if (not ratioFile) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - WireMod Ratio File Must Exist!"; + } + if (ratioFile->IsZombie()) + { + throw cet::exception("WireModifierXXW") + << "WireModifierXXW::reconfigure - WireMod Ratio File Must Not be a Zombie!"; + } + mf::LogVerbatim("WireModifierXXW") + << "WireModifierXXW::reconfigure - Getting XXW Scales..."; + std::vector nameVec_charge_YZ = pset.get>("YZScaleIntegral"); + for (auto const& name : nameVec_charge_YZ) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Looking for " << name << " in TFile " << fRatioFileName_YZ << "..."; + TGraph2D* temp = static_cast(ratioFile->Get(name.c_str())->Clone()); + if (temp != nullptr) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...found"; + fGraph_charge_YZ.push_back(temp); + } else { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...not found. Don't scale for this plane."; + // make a graph spanning -400 to 400 in X and -4 to 4 in ThXW (for completeness) + // all point have a value of 1 + temp = new TGraph2D(); + for (size_t idx = 0; idx < 4; ++idx) + { + double x = (static_cast(idx & 2) - 1)*400; + double y = (static_cast(2*(idx & 1)) - 1)*4; + temp->AddPoint(x, y, 1); + } + fGraph_charge_YZ.push_back(temp); + } + } + std::vector nameVec_sigma_YZ = pset.get>("YZScaleWidth"); + for (auto const& name : nameVec_sigma_YZ) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - Looking for " << name << " in TFile " << fRatioFileName_YZ << "..."; + TGraph2D* temp = static_cast(ratioFile->Get(name.c_str())->Clone()); + if (temp != nullptr) + { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...found"; + fGraph_sigma_YZ.push_back(temp); + } else { + mf::LogDebug("WireModifierXXW") + << "WireModifierXXW::reconfigure - ...not found. Don't scale for this plane."; + // make a graph spanning -400 to 400 in X and -4 to 4 in ThXW (for completeness) + // all point have a value of 1 + temp = new TGraph2D(); + for (size_t idx = 0; idx < 4; ++idx) + { + double x = (static_cast(idx & 2) - 1)*400; + double y = (static_cast(2*(idx & 1)) - 1)*4; + temp->AddPoint(x, y, 1); + } + fGraph_sigma_YZ.push_back(temp); + } + } + } + + // we make these things (mode-dependent) + if (!fUseChannelROIMode) + produces>(); + else + produces>(); + // per-hit scale info: one entry per hit in fHitLabel, sentinel -999 if no EDep match + produces>("scaleQ"); + produces>("scaleSigma"); + produces>("truthX"); + produces>("thetaXW"); + // per-hit MC flag: 1 = MC hit (BackTracker matched), 0 = overlay data hit + produces>("isMC"); + // per-hit SimChannel/BackTracker truth, computed identically to TrackCaloSkimmer::MakeHit + // (ChannelToTrackIDEs over the hit [StartTick,EndTick] window): total true energy [MeV] + // and number of ionization electrons summed over all TrackIDEs under the hit. + produces>("truthE"); + produces>("truthNelec"); + // per-hit truth direction and derived geometry (filled only when SavePerHitData: true) + produces>("dirX"); // truth dxdr + produces>("dirY"); // truth dydr + produces>("dirZ"); // truth dzdr + produces>("pitch"); // wirePitch / cosG [cm] + produces>("dQdX"); // integral_before / pitch [ADC/cm], no lifetime correction + + art::ServiceHandle tfs; + + if (fSaveTickHistograms) + { + fEdepTickInd1 = tfs->make("EdepTickInd1", "1st Induction;Projected Tick;Projected Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fEdepTickInd2 = tfs->make("EdepTickInd2", "2nd Induction;Projected Tick;Projected Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fEdepTickColl = tfs->make("EdepTickColl", "Collection;Projected Tick;Projected Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fHitTickInd1 = tfs->make("HitTickInd1", "1st Induction;Tick;Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fHitTickInd2 = tfs->make("HitTickInd2", "2nd Induction;Tick;Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fHitTickColl = tfs->make("HitTickColl", "Collection;Tick;Channel", + 4096, -128, 4096, + 4603, 0, 55296); + fEdepXvsChan = tfs->make("EdepXvsChan", ";X (cm);Channel", + 800, -400, 400, + 4603, 0, 55296); + fHitXvsChan = tfs->make("HitXvsChan", ";X (cm);Channel", + 800, -400, 400, + 4603, 0, 55296); + fHitBTvsDetProp = tfs->make("HitBTvsDetProp", + ";X (cm) From BackTracker;X (cm) From DetectorProperties", + 800, -400, 400, + 800, -400, 400); + fEdepTickInd1->SetMarkerColor(kRed); + fEdepTickInd2->SetMarkerColor(kRed); + fEdepTickColl->SetMarkerColor(kRed); + fEdepXvsChan->SetMarkerColor(kRed); + fHitTickInd1->SetMarkerColor(kBlack); + fHitTickInd2->SetMarkerColor(kBlack); + fHitTickColl->SetMarkerColor(kBlack); + fHitXvsChan->SetMarkerColor(kBlack); + } + + fROITree = tfs->make("ROITree", "ROI modification diagnostic"); + if (fSaveROITree) + { + fROITree->Branch("run", &tb_run, "run/I"); + fROITree->Branch("subrun", &tb_subrun, "subrun/I"); + fROITree->Branch("event", &tb_event, "event/I"); + fROITree->Branch("channel", &tb_channel, "channel/I"); + fROITree->Branch("wire", &tb_wire, "wire/I"); + fROITree->Branch("tpc", &tb_tpc, "tpc/I"); + fROITree->Branch("plane", &tb_plane, "plane/I"); + fROITree->Branch("roi_idx", &tb_roi_idx, "roi_idx/I"); + fROITree->Branch("roi_begin", &tb_roi_begin, "roi_begin/F"); + fROITree->Branch("roi_before_total_q", &tb_roi_before_total_q, "roi_before_total_q/F"); + fROITree->Branch("roi_before_center", &tb_roi_before_center, "roi_before_center/F"); + fROITree->Branch("roi_before_sigma", &tb_roi_before_sigma, "roi_before_sigma/F"); + fROITree->Branch("roi_after_total_q", &tb_roi_after_total_q, "roi_after_total_q/F"); + fROITree->Branch("roi_after_center", &tb_roi_after_center, "roi_after_center/F"); + fROITree->Branch("roi_after_sigma", &tb_roi_after_sigma, "roi_after_sigma/F"); + fROITree->Branch("roi_before", &tb_roi_before); + fROITree->Branch("roi_after", &tb_roi_after); + fROITree->Branch("hit_before_center", &tb_hit_before_center); + fROITree->Branch("hit_before_integral", &tb_hit_before_integral); + fROITree->Branch("hit_before_sigma", &tb_hit_before_sigma); + fROITree->Branch("hit_after_center", &tb_hit_after_center); + fROITree->Branch("hit_after_integral", &tb_hit_after_integral); + fROITree->Branch("hit_after_sigma", &tb_hit_after_sigma); + fROITree->Branch("scale_Q", &tb_scale_Q); + fROITree->Branch("scale_sigma", &tb_scale_sigma); + fROITree->Branch("theta_xw", &tb_theta_xw); + fROITree->Branch("truth_x", &tb_truth_x); + fROITree->Branch("track_id", &tb_track_id); + fROITree->Branch("scale_reason", &tb_scale_reason); + fROITree->Branch("xxw_graph_name", tb_xxw_graph_name, "xxw_graph_name/C"); + fROITree->Branch("roi_n_hits", &tb_roi_n_hits, "roi_n_hits/I"); + fROITree->Branch("roi_n_pulse_train_hits", &tb_roi_n_pulse_train_hits, "roi_n_pulse_train_hits/I"); + fROITree->Branch("roi_is_pulse_train", &tb_roi_is_pulse_train, "roi_is_pulse_train/I"); + } + } + + //------------------------------------------------ + void WireModifierXXW::produce(art::Event& evt) + { + // here's where the "magic" happens + art::ServiceHandle tfs; + + // get a clock and det props for the event + const detinfo::DetectorPropertiesData detProp = + art::ServiceHandle()->DataFor(evt); + + // handles, read conditionally based on mode + art::Handle< std::vector > wireHandle; + art::Handle< std::vector > chanROIHandle; + if (!fUseChannelROIMode) + evt.getByLabel(fWireLabel, wireHandle); + else + evt.getByLabel(fChannelLabel, chanROIHandle); + + art::Handle< std::vector > edepHandle; + evt.getByLabel(fEDepLabel, edepHandle); + auto const& edepVec(*edepHandle); + + art::Handle< std::vector > edepShiftedHandle; + evt.getByLabel(fEDepShiftedLabel, edepShiftedHandle); + auto const& edepShiftedVec(*edepShiftedHandle); + + // SimChannel + MCParticle inputs: the scale-value truth (position/direction/dE-dQ per + // sub-ROI) is derived from these, replacing the SimEnergyDeposit path. The SimChannel + // ionization gives the charge-weighted true position; the MCParticle trajectory gives + // the local track direction used by the ThetaXW/XXW scale lookup. + auto const& simchVec = *evt.getValidHandle>(fSimChannelLabel); + auto const& mcpVec = *evt.getValidHandle>(fG4Label); + std::map particleMap; + for (auto const& p : mcpVec) particleMap[p.TrackId()] = &p; + + art::Handle< std::vector > hitHandle; + evt.getByLabel(fHitLabel, hitHandle); + auto const& hitVec(*hitHandle); + + // per-hit scale products, only sized when SavePerHitData is on + const size_t perHitN = fSavePerHitData ? hitVec.size() : 0; + auto vec_scale_q = std::make_unique>(perHitN, -999.f); + auto vec_scale_sigma = std::make_unique>(perHitN, -999.f); + auto vec_truth_x = std::make_unique>(perHitN, -999.f); + auto vec_theta_xw = std::make_unique>(perHitN, -999.f); + auto vec_is_mc = std::make_unique> (perHitN, 0); + auto vec_dirx = std::make_unique>(perHitN, -999.f); + auto vec_diry = std::make_unique>(perHitN, -999.f); + auto vec_dirz = std::make_unique>(perHitN, -999.f); + auto vec_pitch = std::make_unique>(perHitN, -999.f); + auto vec_dqdx = std::make_unique>(perHitN, -999.f); + // SimChannel/BackTracker truth per hit (TrackCaloSkimmer-identical), -1 when no truth. + auto vec_truth_e = std::make_unique>(perHitN, -1.f); + auto vec_truth_nelec = std::make_unique>(perHitN, -1.f); + + // Per-hit truth matching, computed IDENTICALLY to TrackCaloSkimmer::MakeHit: + // ChannelToTrackIDEs(channel, StartTick, EndTick) summed over all TrackIDEs. + // isMC is now defined as "this window has any SimChannel ionization" (i.e. the hit is + // truth-matched), matching the TrackCaloSkimmer notion of a matched hit. A hit with no + // IDEs in its window is an overlay/data hit (isMC = 0, truthE/truthNelec = -1). + // + // The BackTracker HitToXYZ projection below is retained only to derive the legacy + // SimEnergyDeposit tick offset (BT_Offset) used by the edep scale path; it is removed + // once the scale path is migrated to SimChannel (see CalcPropertiesFromIDEs). + double BT_Offset = 0; + unsigned int BT_Hits = 0; + for (size_t i_h = 0; i_h < hitVec.size(); ++i_h) + { + auto const& hit = hitVec[i_h]; + + // --- TrackCaloSkimmer-identical per-hit SimChannel truth --- + std::vector ides; + try + { + ides = fBT->ChannelToTrackIDEs(fDetClocksData, hit.Channel(), hit.StartTick(), hit.EndTick()); + } + catch (...) + { + ides.clear(); + } + if (fSavePerHitData) + { + if (!ides.empty()) + { + (*vec_is_mc)[i_h] = 1; + (*vec_truth_e)[i_h] = 0.f; + (*vec_truth_nelec)[i_h] = 0.f; + for (auto const& ide : ides) + { + (*vec_truth_e)[i_h] += ide.energy; + (*vec_truth_nelec)[i_h] += ide.numElectrons; + } + } + else + { + (*vec_is_mc)[i_h] = 0; // overlay/data hit (no SimChannel ionization in window) + } + } + + // --- legacy SimEnergyDeposit tick offset (BackTracker HitToXYZ) --- + double hitX = std::numeric_limits::max(); + try + { + hitX = fBT->HitToXYZ(fDetClocksData, hit).at(0); + } + catch (...) + { + // Overlay hit -- no contribution to the tick offset + continue; + } + double hitTick = hit.PeakTime(); + double projTick = detProp.ConvertXToTicks(hitX, hit.WireID().Plane, hit.WireID().TPC, hit.WireID().Cryostat); + BT_Offset += (hitTick - projTick); + ++BT_Hits; + } + if (BT_Hits > 0) BT_Offset /= BT_Hits; + (void)BT_Offset; // legacy edep tick offset; unused by the SimChannel/IDE scale path + + sys::WireModUtility wmUtil(fGeometry, fWireReadout, detProp, + false, // Channel Scale + false, // X + (fRatioFileName_YZ != "NOFILE"), // YZ + false, // XZ-Angle + false, // YZ-Angle + false, // dE/dx + false, // X-XZAngle + false, // X-dQ/dX + false, // XZAngledQdX + (fRatioFileName_XXW != "NOFILE"), // X-ThXW + 0.0); // Tick Offset: IDEs carry their native readout tick (no offset) + // Space-charge provider for mapping IDE (at-the-wire) positions to the true trajectory + // frame inside CalcPropertiesFromIDEs. Null/disabled -> identity. + wmUtil.fSCE = lar::providerFrom(); + if (fRatioFileName_YZ != "NOFILE") + { + wmUtil.graph2Ds_Charge_YZ = fGraph_charge_YZ; + wmUtil.graph2Ds_Sigma_YZ = fGraph_sigma_YZ; + } + if (fRatioFileName_XXW != "NOFILE") + { + wmUtil.graph2Ds_Charge_XXW = fGraph_charge_XXW; + wmUtil.graph2Ds_Sigma_XXW = fGraph_sigma_XXW; + } + + wmUtil.additiveModification = fAdditiveModification; + wmUtil.useGraph2DInterpolation = fUseGraph2DInterpolation; + + // add some debugging here + mf::LogVerbatim("WireModifierXXW") + << "DUMP CONFIG:" << '\n' + << "---------------------------------------------------" << '\n' + << " applyChannelScale: " << wmUtil.applyChannelScale << '\n' + << " applyXScale: " << wmUtil.applyXScale << '\n' + << " applyYZScale: " << wmUtil.applyYZScale << '\n' + << " applyXXWScale: " << wmUtil.applyXXWScale << '\n' + << " applyXZAngleScale: " << wmUtil.applyXZAngleScale << '\n' + << " applyYZAngleScale: " << wmUtil.applyYZAngleScale << '\n' + << " applydEdXScale: " << wmUtil.applydEdXScale << '\n' + << " additiveModification: " << wmUtil.additiveModification << '\n' + << " useGraph2DInterpolation: " << wmUtil.useGraph2DInterpolation << '\n' + << " setNullScaleIntegral: " << fSetNullScaleIntegral << '\n' + << " setNullScaleWidth: " << fSetNullScaleWidth << '\n' + << " readoutWindowTicks: " << wmUtil.readoutWindowTicks << '\n' + << " tickOffset: " << wmUtil.tickOffset << '\n' + << "---------------------------------------------------"; + + // tick check + mf::LogDebug("WireModifierXXW") + << "edepVec.size() = " << edepVec.size() << '\n' + << "edepShiftedVec.size() = " << edepShiftedVec.size() << '\n' + << "hitVec.size() = " << hitVec.size(); + if (fSaveTickHistograms) + { + for (auto const& edep : edepVec) + { + if (fWireReadout->FindTPCsetAtPosition(edep.MidPoint()) != readout::TPCsetID(fCryo, fTPCset)) + continue; + + geo::TPCID curTPCGeomID; + try { + curTPCGeomID = fGeometry->PositionToTPC(edep.MidPoint()).ID(); + } + catch(...) { + continue; // ignore depositions outside TPC + } + + geo::TPCGeo const* curTPCGeomPtr = fGeometry->PositionToTPCptr(edep.MidPoint()); + for (auto const& plane : fWireReadout->Iterate(curTPCGeomPtr->ID())) + { + TH2F* targetHist = (plane.View() == geo::kY) ? fEdepTickInd1 + : (plane.View() == geo::kV) ? fEdepTickInd2 + : (plane.View() == geo::kU) ? fEdepTickColl + : nullptr; + if (targetHist == nullptr) continue; + + geo::WireID wireID; + try { wireID = plane.NearestWireID(edep.MidPoint()); } + catch (...) { continue; } + float projTick = detProp.ConvertXToTicks(edep.X(), wireID.Plane, wireID.TPC, wireID.Cryostat) + wmUtil.tickOffset; + float projChan = fWireReadout->PlaneWireToChannel(wireID); + targetHist->Fill(projTick, projChan); + fEdepXvsChan->Fill(edep.X(), projChan); + } + } + for (auto const& hit : hitVec) + { + TH2F* targetHist = (hit.View() == geo::kY) ? fHitTickInd1 + : (hit.View() == geo::kV) ? fHitTickInd2 + : (hit.View() == geo::kU) ? fHitTickColl + : nullptr; + if (targetHist == nullptr) continue; + + float tick = hit.PeakTime(); + float chan = hit.Channel(); + targetHist->Fill(tick, chan); + float hitX = detProp.ConvertTicksToX(tick, + hit.WireID().Plane, hit.WireID().TPC, hit.WireID().Cryostat); + try + { + float hitXBT = fBT->HitToXYZ(fDetClocksData, hit).at(0); + fHitBTvsDetProp->Fill(hitXBT, hitX); + hitX = hitXBT; + } + catch (...) { } + fHitXvsChan->Fill(hitX, chan); + } + } + + double offset_ADC = 0; + + if (!fUseChannelROIMode) { + // Wire (nominal) mode + auto const& wireVec(*wireHandle); + std::unique_ptr> new_wires(new std::vector()); + + mf::LogVerbatim("WireModifierXXW") << "Get IDE Map"; + wmUtil.FillROIMatchedIDEMap(simchVec, wireVec, fDetClocksData, offset_ADC); + mf::LogVerbatim("WireModifierXXW") << "Got IDE Map." << '\n' << "Get Hit Map"; + wmUtil.FillROIMatchedHitMap(hitVec, wireVec); + mf::LogVerbatim("WireModifierXXW") << "Got Hit Map."; + + tb_run = static_cast(evt.run()); + tb_subrun = static_cast(evt.subRun()); + tb_event = static_cast(evt.event()); + + // loop-de-loop + for(size_t i_w = 0; i_w < wireVec.size(); ++i_w) + { + mf::LogDebug("WireModifierXXW") + << "Checking wire " << i_w; + + auto const& wire = wireVec.at(i_w); + recob::Wire::RegionsOfInterest_t new_rois; + bool isModified = false; + + if (wire.NSignal() == 0) + continue; + + new_rois.resize(wire.NSignal()); + + unsigned int my_plane = geo::kUnknown; + if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 0)).View()) + { + mf::LogDebug("WireModifierXXW") + << "Wire is on plane 0, view " << wire.View(); + my_plane = 0; + } else if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 1)).View()) { + mf::LogDebug("WireModifierXXW") + << "Wire is on plane 1, view " << wire.View(); + my_plane = 1; + } else if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 2)).View()) { + mf::LogDebug("WireModifierXXW") + << "Wire is on plane 2, view " << wire.View(); + my_plane = 2; + } + + if (my_plane == geo::kUnknown) + { + mf::LogDebug("WireModifierXXW") + << "Wire is on unsupported plane. Skip."; + } + + for(size_t i_r = 0; i_r < wire.SignalROI().get_ranges().size(); ++i_r) + { + mf::LogDebug("WireModifierXXW") + << " Checking ROI " << i_r; + + auto const& range = wire.SignalROI().get_ranges()[i_r]; + + sys::WireModUtility::ROI_Key_t roi_key(wire.Channel(), i_r); + + std::vector modified_data(range.data()); + + auto it_map = wmUtil.ROIMatchedIDEMap.find(roi_key); + if(it_map==wmUtil.ROIMatchedIDEMap.end()){ + new_rois.add_range(range.begin_index(), modified_data); + mf::LogDebug("WireModifierXXW") + << " Could not find matching IDE. Skip"; + continue; + } + std::vector matchedIDEIdxVec = it_map->second; + if(matchedIDEIdxVec.size() == 0) + { + new_rois.add_range(range.begin_index(), modified_data); + mf::LogDebug("WireModifierXXW") + << " No indices for IDE. Skip"; + continue; + } + std::vector matchedIDEPtrVec; + for(auto i_e : matchedIDEIdxVec) + matchedIDEPtrVec.push_back(&wmUtil.fIDEVec[i_e]); + mf::LogDebug("WireModifierXXW") + << " Found " << matchedIDEPtrVec.size() << " IDEs"; + + std::vector matchedHitPtrVec; + auto it_hit_map = wmUtil.ROIMatchedHitMap.find(roi_key); + if( it_hit_map != wmUtil.ROIMatchedHitMap.end() ) { + for( auto i_h : it_hit_map->second ) + matchedHitPtrVec.push_back(&hitVec[i_h]); + } + + mf::LogDebug("WireModifierXXW") + << " Found " << matchedHitPtrVec.size() << " matching hits"; + + auto roi_properties = wmUtil.CalcROIProperties(wire, i_r); + mf::LogDebug("WireModifierXXW") + << " ROI Properties:" << '\n' + << " key: (" << roi_properties.key.first + << ", " << roi_properties.key.second << ")" << '\n' + << " view: " << roi_properties.view << '\n' + << " begin: " << roi_properties.begin << '\n' + << " end: " << roi_properties.end << '\n' + << " total_q: " << roi_properties.total_q << '\n' + << " center: " << roi_properties.center << '\n' + << " sigma: " << roi_properties.sigma; + + auto subROIPropVec = wmUtil.CalcSubROIProperties(roi_properties, matchedHitPtrVec); + + mf::LogDebug("WireModifierXXW") + << " have " << subROIPropVec.size() << " SubROI"; + + auto SubROIMatchedIDEMap = + wmUtil.MatchIDEsToSubROIs(subROIPropVec, matchedIDEPtrVec); + + std::map SubROIMatchedScalesMap; + std::map SubROIMatchedTruthMap; + std::map SubROIScaleReasonMap; + for (auto const& subroi_prop : subROIPropVec) + { + sys::WireModUtility::ScaleValues_t scale_vals; + auto key = subroi_prop.key; + auto key_it = SubROIMatchedIDEMap.find(key); + int scale_reason = 0; + + if (key_it != SubROIMatchedIDEMap.end() && key_it->second.size() > 0) + { + auto truth_vals = wmUtil.CalcPropertiesFromIDEs(key_it->second, particleMap); + SubROIMatchedTruthMap[key] = truth_vals; + + if (truth_vals.total_energy < 0.3 && subroi_prop.total_q > 80) + { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + scale_reason = 1; // energy veto + } else + { + scale_vals = wmUtil.GetScaleValues(truth_vals, roi_properties); + if (scale_vals.r_Q != 1. || scale_vals.r_sigma != 1.) + { + mf::LogDebug("WireModifierXXW") + << "Scaling! Q scale: " << scale_vals.r_Q + << " sigma scale: " << scale_vals.r_sigma; + isModified = true; + scale_reason = 2; // scaling applied + } else { + scale_reason = 3; // EDep matched but map evaluates to 1 + } + } + } else + { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + scale_reason = 0; // no EDep matched (likely overlay data hit) + } + + SubROIMatchedScalesMap[key] = scale_vals; + SubROIScaleReasonMap[key] = scale_reason; + } + + // null-scale overrides: force r_Q and/or r_sigma to 1 for all sub-ROIs. + // applied in-place so the diagnostic tree records what was actually used. + if (fSetNullScaleIntegral || fSetNullScaleWidth) { + for (auto& kv : SubROIMatchedScalesMap) { + if (fSetNullScaleIntegral) kv.second.r_Q = 1.0; + if (fSetNullScaleWidth) kv.second.r_sigma = 1.0; + } + } + + wmUtil.ModifyROI(modified_data, roi_properties, subROIPropVec, SubROIMatchedScalesMap, 1.5); + + // fill diagnostic tree + if (fSaveROITree) + { + // wire/geometry info + std::vector wireIDs = fWireReadout->ChannelToWire(wire.Channel()); + geo::WireID firstWireID = wireIDs.empty() ? geo::WireID{} : wireIDs.front(); + tb_channel = static_cast(wire.Channel()); + tb_wire = static_cast(firstWireID.Wire); + tb_tpc = static_cast(firstWireID.TPC); + tb_plane = static_cast(my_plane); + tb_roi_idx = static_cast(i_r); + + // ROI before + tb_roi_begin = roi_properties.begin; + tb_roi_before_total_q = roi_properties.total_q; + tb_roi_before_center = roi_properties.center; + tb_roi_before_sigma = roi_properties.sigma; + tb_roi_before.assign(range.data().begin(), range.data().end()); + + // ROI after: compute charge-weighted properties from modified waveform + float mod_total_q = 0.f, mod_center = 0.f, mod_sigma = 0.f; + for (size_t i_t = 0; i_t < modified_data.size(); ++i_t) + { + mod_total_q += modified_data[i_t]; + mod_center += modified_data[i_t] * (i_t + roi_properties.begin); + } + if (mod_total_q > 0.f) mod_center /= mod_total_q; + for (size_t i_t = 0; i_t < modified_data.size(); ++i_t) + { + float t = static_cast(i_t) + roi_properties.begin; + mod_sigma += modified_data[i_t] * (t - mod_center) * (t - mod_center); + } + if (mod_total_q > 0.f) mod_sigma = std::sqrt(mod_sigma / mod_total_q); + tb_roi_after_total_q = mod_total_q; + tb_roi_after_center = mod_center; + tb_roi_after_sigma = mod_sigma; + tb_roi_after = modified_data; + + // pulse train detection (GoodnessOfFit==-1 && DoF==1 is gaushit's sentinel) + { + int n_pt = 0; + for (auto const& hptr : matchedHitPtrVec) + if (hptr->GoodnessOfFit() == -1.0f && hptr->DegreesOfFreedom() == 1) + ++n_pt; + tb_roi_n_hits = static_cast(matchedHitPtrVec.size()); + tb_roi_n_pulse_train_hits = static_cast(n_pt); + tb_roi_is_pulse_train = (n_pt > 0) ? 1 : 0; + } + + // per-subROI hit candidate info and scale factors + tb_hit_before_center.clear(); + tb_hit_before_integral.clear(); + tb_hit_before_sigma.clear(); + tb_hit_after_center.clear(); + tb_hit_after_integral.clear(); + tb_hit_after_sigma.clear(); + tb_scale_Q.clear(); + tb_scale_sigma.clear(); + tb_theta_xw.clear(); + tb_truth_x.clear(); + tb_track_id.clear(); + tb_scale_reason.clear(); + { + std::string gname = (tb_plane < (int)fNameVec_sigma_XXW.size()) + ? fNameVec_sigma_XXW[tb_plane] : "unknown"; + std::strncpy(tb_xxw_graph_name, gname.c_str(), 127); + tb_xxw_graph_name[127] = '\0'; + } + + for (auto const& subroi_prop : subROIPropVec) + { + auto key = subroi_prop.key; + auto scale_vals = SubROIMatchedScalesMap.at(key); + + tb_hit_before_center.push_back(subroi_prop.center); + tb_hit_before_integral.push_back(subroi_prop.total_q); + tb_hit_before_sigma.push_back(subroi_prop.sigma); + tb_hit_after_center.push_back(subroi_prop.center); + tb_hit_after_integral.push_back(subroi_prop.total_q * static_cast(scale_vals.r_Q)); + tb_hit_after_sigma.push_back(subroi_prop.sigma * static_cast(scale_vals.r_sigma)); + tb_scale_Q.push_back(static_cast(scale_vals.r_Q)); + tb_scale_sigma.push_back(static_cast(scale_vals.r_sigma)); + + // dominant track ID: pick the TrackID with highest summed energy + int dominant_tid = -999; + auto edep_it = SubROIMatchedIDEMap.find(key); + if (edep_it != SubROIMatchedIDEMap.end() && !edep_it->second.empty()) + { + std::map tidEnergy; + for (auto const& ep : edep_it->second) + tidEnergy[std::abs(ep->ide->trackID)] += ep->ide->energy; + double maxE = 0.; + for (auto const& te : tidEnergy) + if (te.second > maxE) { maxE = te.second; dominant_tid = te.first; } + } + tb_track_id.push_back(dominant_tid); + tb_scale_reason.push_back(SubROIScaleReasonMap.at(key)); + + // angle in degrees (ThetaXW returns radians) + truth X for graph lookup + float theta_deg = -999.f; + float truth_x_val = -9999.f; + auto truth_it = SubROIMatchedTruthMap.find(key); + if (truth_it != SubROIMatchedTruthMap.end()) + { + auto const& tv = truth_it->second; + truth_x_val = static_cast(tv.x); + geo::TPCGeo const* tpcPtr = fGeometry->PositionToTPCptr( + geo::Point_t{(double)tv.x, (double)tv.y, (double)tv.z}); + if (tpcPtr != nullptr) + { + try + { + auto const& plane_obj = fWireReadout->Plane(tpcPtr->ID(), wire.View()); + theta_deg = static_cast(wmUtil.ThetaXW( + tv.dxdr, tv.dydr, tv.dzdr, plane_obj.ThetaZ()) * TMath::RadToDeg()); + } + catch (...) {} + } + } + tb_theta_xw.push_back(theta_deg); + tb_truth_x.push_back(truth_x_val); + } + + fROITree->Fill(); + } + + // Fill per-hit scale product vectors indexed by position in hitVec + if (fSavePerHitData && it_hit_map != wmUtil.ROIMatchedHitMap.end()) + { + for (auto const& subroi_prop : subROIPropVec) + { + size_t i_subroi = subroi_prop.key.second; + if (i_subroi >= it_hit_map->second.size()) continue; + size_t hitVec_idx = it_hit_map->second[i_subroi]; + + auto const& scale_vals = SubROIMatchedScalesMap.at(subroi_prop.key); + (*vec_scale_q )[hitVec_idx] = static_cast(scale_vals.r_Q); + (*vec_scale_sigma)[hitVec_idx] = static_cast(scale_vals.r_sigma); + + auto truth_it = SubROIMatchedTruthMap.find(subroi_prop.key); + if (truth_it != SubROIMatchedTruthMap.end()) + { + auto const& tv = truth_it->second; + (*vec_truth_x)[hitVec_idx] = static_cast(tv.x); + geo::TPCGeo const* tpcPtr = fGeometry->PositionToTPCptr( + geo::Point_t{tv.x, tv.y, tv.z}); + if (tpcPtr) + { + try { + auto const& plane_obj = fWireReadout->Plane( + hitVec[hitVec_idx].WireID().planeID()); + double thetaZ = plane_obj.ThetaZ(); + (*vec_theta_xw)[hitVec_idx] = static_cast( + wmUtil.ThetaXW(tv.dxdr, tv.dydr, tv.dzdr, thetaZ) * TMath::RadToDeg()); + (*vec_dirx)[hitVec_idx] = static_cast(tv.dxdr); + (*vec_diry)[hitVec_idx] = static_cast(tv.dydr); + (*vec_dirz)[hitVec_idx] = static_cast(tv.dzdr); + double cosG = std::abs(tv.dydr * std::cos(thetaZ) - tv.dzdr * std::sin(thetaZ)); // pitch: project onto wire-normal (thetaZ - pi/2) + float wp = static_cast(plane_obj.WirePitch()); + float pval = (cosG > 1e-6) ? wp / static_cast(cosG) : -999.f; + (*vec_pitch)[hitVec_idx] = pval; + (*vec_dqdx)[hitVec_idx] = (pval > 0.f) + ? hitVec[hitVec_idx].Integral() / pval : -999.f; + } + catch (...) {} + } + } + } + } + + new_rois.add_range(roi_properties.begin, modified_data); + } + + new_wires->emplace_back(new_rois, wire.Channel(), wire.View()); + + if (fSaveHistsByChannel && isModified) + { + readout::ROPID ropID = fWireReadout->ChannelToROP(wire.Channel()); + std::string titleStr = "Cryo-" + std::to_string(ropID.Cryostat) + + "_TPCset-" + std::to_string(ropID.TPCset) + + "_ReadOutPlane-" + std::to_string(ropID.ROP) + + "_Channel-" + std::to_string(wire.Channel()); + TH1F* oldChannelHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newChannelHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = + (tick < wire .Signal().size() ) ? wire .Signal().at(tick) : 0; + float newSample = + (tick < new_wires->back().Signal().size() ) ? new_wires->back().Signal().at(tick) : 0; + oldChannelHist->SetBinContent(tick + 1, oldSample); + newChannelHist->SetBinContent(tick + 1, newSample); + } + + TH1F* oldChannelHist_toSave = tfs->make(*oldChannelHist); + TH1F* newChannelHist_toSave = tfs->make(*newChannelHist); + mf::LogDebug("WireModifierXXW") + << "Saved histograms " << oldChannelHist_toSave->GetName() << '\n' + << " and " << newChannelHist_toSave->GetName(); + } + + if (fSaveHistsByWire && isModified) + { + std::vector wireIDs = fWireReadout->ChannelToWire(wire.Channel()); + mf::LogDebug("WireModifierXXW") + << "Channel " << wire.Channel() << " has " << wireIDs.size() << " wire(s)"; + for (auto const& wireID : wireIDs) + { + std::string titleStr = "Cryo-" + std::to_string(wireID.Cryostat) + + "_TPC-" + std::to_string(wireID.TPC) + + "_Plane-" + std::to_string(wireID.Plane) + + "_Wire-" + std::to_string(wireID.Wire); + TH1F* oldWireHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newWireHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = + (tick < wire .Signal().size() ) ? wire .Signal().at(tick) : 0; + float newSample = + (tick < new_wires->back().Signal().size() ) ? new_wires->back().Signal().at(tick) : 0; + oldWireHist->SetBinContent(tick + 1, oldSample); + newWireHist->SetBinContent(tick + 1, newSample); + } + + TH1F* oldWireHist_toSave = tfs->make(*oldWireHist); + TH1F* newWireHist_toSave = tfs->make(*newWireHist); + mf::LogDebug("WireModifierXXW") + << "Saved histograms " << oldWireHist_toSave->GetName() << '\n' + << " and " << newWireHist_toSave->GetName(); + } + } + + } // end loop over wires + + evt.put(std::move(new_wires)); + + } else { + // ChannelROI (float precision) mode + auto const& chanROIVec(*chanROIHandle); + std::unique_ptr> new_chanROIs(new std::vector()); + + mf::LogVerbatim("WireModifierXXW") << "Get IDE Map"; + wmUtil.FillROIMatchedIDEMap(simchVec, chanROIVec, fDetClocksData, offset_ADC); + mf::LogVerbatim("WireModifierXXW") << "Got IDE Map." << '\n' << "Get Hit Map"; + wmUtil.FillROIMatchedHitMap(hitVec, chanROIVec); + mf::LogVerbatim("WireModifierXXW") << "Got Hit Map."; + + tb_run = static_cast(evt.run()); + tb_subrun = static_cast(evt.subRun()); + tb_event = static_cast(evt.event()); + + for(size_t i_c = 0; i_c < chanROIVec.size(); ++i_c) + { + mf::LogDebug("WireModifierXXW") << "Checking chanROI " << i_c; + + auto const& chanROI = chanROIVec.at(i_c); + recob::ChannelROI::RegionsOfInterest_t new_rois; + bool isModified = false; + + if (chanROI.NSignal() == 0) + continue; + + new_rois.resize(chanROI.NSignal()); + + geo::View_t chanView = fWireReadout->View(chanROI.Channel()); + unsigned int my_plane = geo::kUnknown; + if (chanView == fWireReadout->Plane(geo::PlaneID(0, 0, 0)).View()) my_plane = 0; + else if (chanView == fWireReadout->Plane(geo::PlaneID(0, 0, 1)).View()) my_plane = 1; + else if (chanView == fWireReadout->Plane(geo::PlaneID(0, 0, 2)).View()) my_plane = 2; + + if (my_plane == geo::kUnknown) + mf::LogDebug("WireModifierXXW") << "ChannelROI on unsupported plane. Skip."; + + // SignalROIF() returns by value, so a const& to its sub-objects would dangle. + // SignalROI() is a stable const ref instead. + auto const& roiShort = chanROI.SignalROI(); + const float adcScale = 1.0f / static_cast(chanROI.ADCScaleFactor()); + + for(size_t i_r = 0; i_r < roiShort.get_ranges().size(); ++i_r) + { + mf::LogDebug("WireModifierXXW") << " Checking ROI " << i_r; + + auto const& range_short = roiShort.get_ranges()[i_r]; + sys::WireModUtility::ROI_Key_t roi_key(chanROI.Channel(), i_r); + + // convert short -> float (same as SignalROIF() but without the temporary) + std::vector modified_data; + modified_data.reserve(range_short.data().size()); + for (auto s : range_short.data()) + modified_data.push_back(static_cast(s) * adcScale); + + auto toShort = [&chanROI](float v) { + return static_cast(std::round(v * chanROI.ADCScaleFactor())); + }; + + auto it_map = wmUtil.ROIMatchedIDEMap.find(roi_key); + if(it_map==wmUtil.ROIMatchedIDEMap.end()){ + std::vector pass_short(modified_data.size()); + std::transform(modified_data.begin(), modified_data.end(), pass_short.begin(), toShort); + new_rois.add_range(range_short.begin_index(), pass_short); + mf::LogDebug("WireModifierXXW") << " Could not find matching IDE. Skip"; + continue; + } + std::vector matchedIDEIdxVec = it_map->second; + if(matchedIDEIdxVec.size() == 0) + { + std::vector pass_short(modified_data.size()); + std::transform(modified_data.begin(), modified_data.end(), pass_short.begin(), toShort); + new_rois.add_range(range_short.begin_index(), pass_short); + mf::LogDebug("WireModifierXXW") << " No indices for IDE. Skip"; + continue; + } + std::vector matchedIDEPtrVec; + for(auto i_e : matchedIDEIdxVec) + matchedIDEPtrVec.push_back(&wmUtil.fIDEVec[i_e]); + mf::LogDebug("WireModifierXXW") << " Found " << matchedIDEPtrVec.size() << " IDEs"; + + std::vector matchedHitPtrVec; + auto it_hit_map = wmUtil.ROIMatchedHitMap.find(roi_key); + if( it_hit_map != wmUtil.ROIMatchedHitMap.end() ) { + for( auto i_h : it_hit_map->second ) + matchedHitPtrVec.push_back(&hitVec[i_h]); + } + mf::LogDebug("WireModifierXXW") << " Found " << matchedHitPtrVec.size() << " matching hits"; + + auto roi_properties = wmUtil.CalcROIProperties(chanROI, i_r); + mf::LogDebug("WireModifierXXW") + << " ROI Properties:" << '\n' + << " key: (" << roi_properties.key.first + << ", " << roi_properties.key.second << ")" << '\n' + << " view: " << roi_properties.view << '\n' + << " begin: " << roi_properties.begin << '\n' + << " end: " << roi_properties.end << '\n' + << " total_q: " << roi_properties.total_q << '\n' + << " center: " << roi_properties.center << '\n' + << " sigma: " << roi_properties.sigma; + + auto subROIPropVec = wmUtil.CalcSubROIProperties(roi_properties, matchedHitPtrVec); + mf::LogDebug("WireModifierXXW") << " have " << subROIPropVec.size() << " SubROI"; + + auto SubROIMatchedIDEMap = + wmUtil.MatchIDEsToSubROIs(subROIPropVec, matchedIDEPtrVec); + + std::map SubROIMatchedScalesMap; + std::map SubROIMatchedTruthMap; + std::map SubROIScaleReasonMap; + for (auto const& subroi_prop : subROIPropVec) + { + sys::WireModUtility::ScaleValues_t scale_vals; + auto key = subroi_prop.key; + auto key_it = SubROIMatchedIDEMap.find(key); + int scale_reason = 0; + + if (key_it != SubROIMatchedIDEMap.end() && key_it->second.size() > 0) + { + auto truth_vals = wmUtil.CalcPropertiesFromIDEs(key_it->second, particleMap); + SubROIMatchedTruthMap[key] = truth_vals; + + if (truth_vals.total_energy < 0.3 && subroi_prop.total_q > 80) + { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + scale_reason = 1; + } else + { + scale_vals = wmUtil.GetScaleValues(truth_vals, roi_properties); + if (scale_vals.r_Q != 1. || scale_vals.r_sigma != 1.) + { + mf::LogDebug("WireModifierXXW") + << "Scaling! Q scale: " << scale_vals.r_Q + << " sigma scale: " << scale_vals.r_sigma; + isModified = true; + scale_reason = 2; + } else { + scale_reason = 3; + } + } + } else + { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + scale_reason = 0; + } + + SubROIMatchedScalesMap[key] = scale_vals; + SubROIScaleReasonMap[key] = scale_reason; + } + + if (fSetNullScaleIntegral || fSetNullScaleWidth) { + for (auto& kv : SubROIMatchedScalesMap) { + if (fSetNullScaleIntegral) kv.second.r_Q = 1.0; + if (fSetNullScaleWidth) kv.second.r_sigma = 1.0; + } + } + + // snapshot of float data before in-place modification (used by ROITree "before" branch) + std::vector modified_data_before = fSaveROITree ? modified_data : std::vector{}; + + wmUtil.ModifyROI(modified_data, roi_properties, subROIPropVec, SubROIMatchedScalesMap, 1.5); + + if (fSaveROITree) + { + std::vector wireIDs = fWireReadout->ChannelToWire(chanROI.Channel()); + geo::WireID firstWireID = wireIDs.empty() ? geo::WireID{} : wireIDs.front(); + tb_channel = static_cast(chanROI.Channel()); + tb_wire = static_cast(firstWireID.Wire); + tb_tpc = static_cast(firstWireID.TPC); + tb_plane = static_cast(my_plane); + tb_roi_idx = static_cast(i_r); + + tb_roi_begin = roi_properties.begin; + tb_roi_before_total_q = roi_properties.total_q; + tb_roi_before_center = roi_properties.center; + tb_roi_before_sigma = roi_properties.sigma; + // modified_data holds the float-converted original (before ModifyROI runs) + tb_roi_before = modified_data_before; + + float mod_total_q = 0.f, mod_center = 0.f, mod_sigma = 0.f; + for (size_t i_t = 0; i_t < modified_data.size(); ++i_t) + { + mod_total_q += modified_data[i_t]; + mod_center += modified_data[i_t] * (i_t + roi_properties.begin); + } + if (mod_total_q > 0.f) mod_center /= mod_total_q; + for (size_t i_t = 0; i_t < modified_data.size(); ++i_t) + { + float t = static_cast(i_t) + roi_properties.begin; + mod_sigma += modified_data[i_t] * (t - mod_center) * (t - mod_center); + } + if (mod_total_q > 0.f) mod_sigma = std::sqrt(mod_sigma / mod_total_q); + tb_roi_after_total_q = mod_total_q; + tb_roi_after_center = mod_center; + tb_roi_after_sigma = mod_sigma; + tb_roi_after = modified_data; + + { + int n_pt = 0; + for (auto const& hptr : matchedHitPtrVec) + if (hptr->GoodnessOfFit() == -1.0f && hptr->DegreesOfFreedom() == 1) + ++n_pt; + tb_roi_n_hits = static_cast(matchedHitPtrVec.size()); + tb_roi_n_pulse_train_hits = static_cast(n_pt); + tb_roi_is_pulse_train = (n_pt > 0) ? 1 : 0; + } + + tb_hit_before_center.clear(); + tb_hit_before_integral.clear(); + tb_hit_before_sigma.clear(); + tb_hit_after_center.clear(); + tb_hit_after_integral.clear(); + tb_hit_after_sigma.clear(); + tb_scale_Q.clear(); + tb_scale_sigma.clear(); + tb_theta_xw.clear(); + tb_truth_x.clear(); + tb_track_id.clear(); + tb_scale_reason.clear(); + { + std::string gname = (tb_plane < (int)fNameVec_sigma_XXW.size()) + ? fNameVec_sigma_XXW[tb_plane] : "unknown"; + std::strncpy(tb_xxw_graph_name, gname.c_str(), 127); + tb_xxw_graph_name[127] = '\0'; + } + + for (auto const& subroi_prop : subROIPropVec) + { + auto key = subroi_prop.key; + auto scale_vals = SubROIMatchedScalesMap.at(key); + + tb_hit_before_center.push_back(subroi_prop.center); + tb_hit_before_integral.push_back(subroi_prop.total_q); + tb_hit_before_sigma.push_back(subroi_prop.sigma); + tb_hit_after_center.push_back(subroi_prop.center); + tb_hit_after_integral.push_back(subroi_prop.total_q * static_cast(scale_vals.r_Q)); + tb_hit_after_sigma.push_back(subroi_prop.sigma * static_cast(scale_vals.r_sigma)); + tb_scale_Q.push_back(static_cast(scale_vals.r_Q)); + tb_scale_sigma.push_back(static_cast(scale_vals.r_sigma)); + + int dominant_tid = -999; + auto edep_it = SubROIMatchedIDEMap.find(key); + if (edep_it != SubROIMatchedIDEMap.end() && !edep_it->second.empty()) + { + std::map tidEnergy; + for (auto const& ep : edep_it->second) + tidEnergy[std::abs(ep->ide->trackID)] += ep->ide->energy; + double maxE = 0.; + for (auto const& te : tidEnergy) + if (te.second > maxE) { maxE = te.second; dominant_tid = te.first; } + } + tb_track_id.push_back(dominant_tid); + tb_scale_reason.push_back(SubROIScaleReasonMap.at(key)); + + float theta_deg = -999.f; + float truth_x_val = -9999.f; + auto truth_it = SubROIMatchedTruthMap.find(key); + if (truth_it != SubROIMatchedTruthMap.end()) + { + auto const& tv = truth_it->second; + truth_x_val = static_cast(tv.x); + geo::TPCGeo const* tpcPtr = fGeometry->PositionToTPCptr( + geo::Point_t{(double)tv.x, (double)tv.y, (double)tv.z}); + if (tpcPtr != nullptr) + { + try + { + auto const& plane_obj = fWireReadout->Plane(tpcPtr->ID(), roi_properties.view); + theta_deg = static_cast(wmUtil.ThetaXW( + tv.dxdr, tv.dydr, tv.dzdr, plane_obj.ThetaZ()) * TMath::RadToDeg()); + } + catch (...) {} + } + } + tb_theta_xw.push_back(theta_deg); + tb_truth_x.push_back(truth_x_val); + } + + fROITree->Fill(); + } + + if (fSavePerHitData && it_hit_map != wmUtil.ROIMatchedHitMap.end()) + { + for (auto const& subroi_prop : subROIPropVec) + { + size_t i_subroi = subroi_prop.key.second; + if (i_subroi >= it_hit_map->second.size()) continue; + size_t hitVec_idx = it_hit_map->second[i_subroi]; + + auto const& scale_vals = SubROIMatchedScalesMap.at(subroi_prop.key); + (*vec_scale_q )[hitVec_idx] = static_cast(scale_vals.r_Q); + (*vec_scale_sigma)[hitVec_idx] = static_cast(scale_vals.r_sigma); + + auto truth_it = SubROIMatchedTruthMap.find(subroi_prop.key); + if (truth_it != SubROIMatchedTruthMap.end()) + { + auto const& tv = truth_it->second; + (*vec_truth_x)[hitVec_idx] = static_cast(tv.x); + geo::TPCGeo const* tpcPtr = fGeometry->PositionToTPCptr( + geo::Point_t{tv.x, tv.y, tv.z}); + if (tpcPtr) + { + try { + auto const& plane_obj = fWireReadout->Plane( + hitVec[hitVec_idx].WireID().planeID()); + double thetaZ = plane_obj.ThetaZ(); + (*vec_theta_xw)[hitVec_idx] = static_cast( + wmUtil.ThetaXW(tv.dxdr, tv.dydr, tv.dzdr, thetaZ) * TMath::RadToDeg()); + (*vec_dirx)[hitVec_idx] = static_cast(tv.dxdr); + (*vec_diry)[hitVec_idx] = static_cast(tv.dydr); + (*vec_dirz)[hitVec_idx] = static_cast(tv.dzdr); + double cosG = std::abs(tv.dydr * std::cos(thetaZ) - tv.dzdr * std::sin(thetaZ)); // pitch: project onto wire-normal (thetaZ - pi/2) + float wp = static_cast(plane_obj.WirePitch()); + float pval = (cosG > 1e-6) ? wp / static_cast(cosG) : -999.f; + (*vec_pitch)[hitVec_idx] = pval; + (*vec_dqdx)[hitVec_idx] = (pval > 0.f) + ? hitVec[hitVec_idx].Integral() / pval : -999.f; + } + catch (...) {} + } + } + } + } + + std::vector mod_short(modified_data.size()); + std::transform(modified_data.begin(), modified_data.end(), mod_short.begin(), toShort); + new_rois.add_range(roi_properties.begin, mod_short); + } // end ROI loop + + new_chanROIs->emplace_back(new_rois, chanROI.Channel(), chanROI.ADCScaleFactor()); + + if (fSaveHistsByChannel && isModified) + { + readout::ROPID ropID = fWireReadout->ChannelToROP(chanROI.Channel()); + std::string titleStr = "Cryo-" + std::to_string(ropID.Cryostat) + + "_TPCset-" + std::to_string(ropID.TPCset) + + "_ReadOutPlane-" + std::to_string(ropID.ROP) + + "_Channel-" + std::to_string(chanROI.Channel()); + TH1F* oldChannelHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newChannelHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = (tick < chanROI.Signal().size()) ? chanROI.Signal().at(tick) : 0; + float newSample = (tick < new_chanROIs->back().Signal().size()) ? new_chanROIs->back().Signal().at(tick) : 0; + oldChannelHist->SetBinContent(tick + 1, oldSample); + newChannelHist->SetBinContent(tick + 1, newSample); + } + TH1F* oldChannelHist_toSave = tfs->make(*oldChannelHist); + TH1F* newChannelHist_toSave = tfs->make(*newChannelHist); + mf::LogDebug("WireModifierXXW") + << "Saved histograms " << oldChannelHist_toSave->GetName() << '\n' + << " and " << newChannelHist_toSave->GetName(); + } + + if (fSaveHistsByWire && isModified) + { + std::vector wireIDs = fWireReadout->ChannelToWire(chanROI.Channel()); + mf::LogDebug("WireModifierXXW") + << "Channel " << chanROI.Channel() << " has " << wireIDs.size() << " wire(s)"; + for (auto const& wireID : wireIDs) + { + std::string titleStr = "Cryo-" + std::to_string(wireID.Cryostat) + + "_TPC-" + std::to_string(wireID.TPC) + + "_Plane-" + std::to_string(wireID.Plane) + + "_Wire-" + std::to_string(wireID.Wire); + TH1F* oldWireHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newWireHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", + wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = (tick < chanROI.Signal().size()) ? chanROI.Signal().at(tick) : 0; + float newSample = (tick < new_chanROIs->back().Signal().size()) ? new_chanROIs->back().Signal().at(tick) : 0; + oldWireHist->SetBinContent(tick + 1, oldSample); + newWireHist->SetBinContent(tick + 1, newSample); + } + TH1F* oldWireHist_toSave = tfs->make(*oldWireHist); + TH1F* newWireHist_toSave = tfs->make(*newWireHist); + mf::LogDebug("WireModifierXXW") + << "Saved histograms " << oldWireHist_toSave->GetName() << '\n' + << " and " << newWireHist_toSave->GetName(); + } + } + + } // end loop over chanROIs + + evt.put(std::move(new_chanROIs)); + + } // end else (ChannelROI mode) + + evt.put(std::move(vec_scale_q), "scaleQ"); + evt.put(std::move(vec_scale_sigma), "scaleSigma"); + evt.put(std::move(vec_truth_x), "truthX"); + evt.put(std::move(vec_theta_xw), "thetaXW"); + evt.put(std::move(vec_is_mc), "isMC"); + evt.put(std::move(vec_truth_e), "truthE"); + evt.put(std::move(vec_truth_nelec), "truthNelec"); + evt.put(std::move(vec_dirx), "dirX"); + evt.put(std::move(vec_diry), "dirY"); + evt.put(std::move(vec_dirz), "dirZ"); + evt.put(std::move(vec_pitch), "pitch"); + evt.put(std::move(vec_dqdx), "dQdX"); + } + DEFINE_ART_MODULE(WireModifierXXW) +} // end namespace diff --git a/icaruscode/WireMod/WireModifier_module.cc b/icaruscode/WireMod/WireModifier_module.cc new file mode 100644 index 000000000..a6720ca5e --- /dev/null +++ b/icaruscode/WireMod/WireModifier_module.cc @@ -0,0 +1,814 @@ +// std inlcudes +#include +#include + +// ROOT includes +#include "TF1.h" +#include "TGraph.h" +#include "TH1D.h" + +// art includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art_root_io/TFileService.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +// larsoft includes +#include "larcore/Geometry/Geometry.h" +#include "larcore/Geometry/WireReadout.h" +#include "larcorealg/Geometry/WireReadoutGeom.h" +#include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom() +#include "lardata/DetectorInfoServices/DetectorPropertiesService.h" +#include "lardata/Utilities/AssociationUtil.h" +#include "lardataobj/RawData/RawDigit.h" +#include "lardataobj/RecoBase/Wire.h" +#include "sbnobj/ICARUS/TPC/ChannelROI.h" +#include "icaruscode/TPC/Utilities/ChannelROICreator.h" + +// wiremod +#include "sbncode/WireMod/Utility/WireModUtility.hh" + +//namespace +namespace wiremod +{ + + class WireModifier : public art::EDProducer + { + public: + explicit WireModifier(fhicl::ParameterSet const& pset); + void reconfigure(fhicl::ParameterSet const& pset); + void produce(art::Event& evt) override; + void produceData(art::Event& evt); + + private: + const geo::GeometryCore* fGeometry = lar::providerFrom(); // get the geometry + const geo::WireReadoutGeom* fWireReadout = &(art::ServiceHandle()->Get()); + std::string fRatioFileName; // there is where we try to grab the splines/graphs (if they exist) + TSpline3* fSpline_charge_Channel; + TSpline3* fSpline_sigma_Channel; + std::vector fSpline_charge_X; + std::vector fSpline_sigma_X; + std::vector fSpline_charge_XZAngle; + std::vector fSpline_sigma_XZAngle; + std::vector fSpline_charge_YZAngle; + std::vector fSpline_sigma_YZAngle; + std::vector fSpline_charge_dEdX; + std::vector fSpline_sigma_dEdX; + std::vector fGraph_charge_YZ; + std::vector fGraph_sigma_YZ; + art::InputTag fWireLabel; // which wires are we pulling in? + art::InputTag fHitLabel; // which hits are we pulling in? + art::InputTag fEDepOrigLabel; // which are the unshifted EDeps? + art::InputTag fEDepShftLabel; // which are the shifted EDeps? + bool fApplyChannel; // do we apply the channel scaling? + bool fApplyX; // do we apply the X scaling? + bool fApplyYZ; // do we apply the YZ scaling? + bool fApplyXZAngle; // do we apply the XZ angle scaling? + bool fApplyYZAngle; // do we apply the YZ angle scaling? + bool fApplydEdX; // do we apply the dEdX scaling? + bool fSaveHistsByChannel; // save modified signals by channel? + bool fSaveHistsByWire; // save modified signals by wire? + bool fIsData; // DEBUG: get data wires + + }; // end WireModifier class + + //------------------------------------------------ + WireModifier::WireModifier(fhicl::ParameterSet const& pset) : EDProducer{pset} + { + // get the fhicl parameters + this->reconfigure(pset); + } + + //------------------------------------------------ + void WireModifier::reconfigure(fhicl::ParameterSet const& pset) + { + fWireLabel = pset.get("WireLabel", "roifinder:PHYSCRATEDATATPCEE"); + fHitLabel = pset.get("HitLabel", "gaushitTPCEE"); + fEDepOrigLabel = pset.get("EDepOrigLabel", "ionization"); + fEDepShftLabel = pset.get("EDepShftLabel", "largeant:TPCActive"); + + // what, if anything, are we putting in the histogram files + //fSaveHistsByChannel = pset.get("SaveByChannel", false); + fSaveHistsByChannel = pset.get("SaveByChannel", true); + fSaveHistsByWire = pset.get("SaveByWire" , false); + fIsData = pset.get("IsData" , false); + + // try to read in the graphs/splines from a file + // if that file does not exist then fake them + fRatioFileName = pset.get("RatioFileName", "NOFILE"); + fApplyChannel = pset.get("ApplyChannelScale", false); + fApplyX = pset.get("ApplyXScale" , false); + fApplyYZ = pset.get("ApplyYZScale" , false); + fApplyXZAngle = pset.get("ApplyXZAngleScale", false); + fApplyYZAngle = pset.get("ApplyYZAngleScale", false); + fApplydEdX = pset.get("ApplydEdXscale" , false); + if (fRatioFileName == "NOFILE") + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - No ratio file given. No scaling is applied..."; + } else { + TFile* ratioFile = new TFile(fRatioFileName.c_str(), "READ"); // read only + // the file exists! pull the ratios + if (fApplyChannel) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting Channel Scales..."; + std::string name_charge_Channel = pset.get("ChannelScaleHeight"); + std::string name_sigma_Channel = pset.get("ChannelScaleWidth"); + fSpline_charge_Channel = ratioFile->Get(name_charge_Channel.c_str()); + fSpline_sigma_Channel = ratioFile->Get(name_sigma_Channel .c_str()); + } + if (fApplyX) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting X Scales..."; + std::vector nameVec_charge_X = pset.get>("XScaleHeight"); + for (auto const& name : nameVec_charge_X) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_charge_X.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + std::vector nameVec_sigma_X = pset.get>("XScaleHeight"); + for (auto const& name : nameVec_sigma_X) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_sigma_X.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + } + if (fApplyYZ) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting YZ Scales..."; + std::vector nameVec_charge_YZ = pset.get>("YZScaleHeight"); + for (auto const& name : nameVec_charge_YZ) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TGraph2D* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fGraph_charge_YZ.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + std::vector nameVec_sigma_YZ = pset.get>("YZScaleHeight"); + for (auto const& name : nameVec_sigma_YZ) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TGraph2D* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fGraph_sigma_YZ.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + } + if (fApplyXZAngle) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting XZ Angle Scales..."; + std::vector nameVec_charge_XZAngle = pset.get>("XZAngleScaleHeight"); + for (auto const& name : nameVec_charge_XZAngle) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_charge_XZAngle.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + std::vector nameVec_sigma_XZAngle = pset.get>("XZAngleScaleHeight"); + for (auto const& name : nameVec_sigma_XZAngle) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_sigma_XZAngle.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + } + if (fApplyYZAngle) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting YZ Angle Scales..."; + std::vector nameVec_charge_YZAngle = pset.get>("YZAngleScaleHeight"); + for (auto const& name : nameVec_charge_YZAngle) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_charge_YZAngle.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + std::vector nameVec_sigma_YZAngle = pset.get>("YZAngleScaleHeight"); + for (auto const& name : nameVec_sigma_YZAngle) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_sigma_YZAngle.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + } + if (fApplydEdX) + { + mf::LogVerbatim("WireModifier") + << "WireModifier::reconfigure - Getting dEdX Scales..."; + std::vector nameVec_charge_dEdX = pset.get>("dEdXScaleHeight"); + for (auto const& name : nameVec_charge_dEdX) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_charge_dEdX.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + std::vector nameVec_sigma_dEdX = pset.get>("dEdXScaleHeight"); + for (auto const& name : nameVec_sigma_dEdX) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - Looking for " << name << " in TFile " << fRatioFileName << "..."; + TSpline3* temp = ratioFile->Get(name.c_str()); + if (temp != nullptr) + { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...found"; + fSpline_sigma_dEdX.push_back(temp); + } else { + mf::LogDebug("WireModifier") + << "WireModifier::reconfigure - ...not found"; + } + } + } + } + + // we make these things + produces>(); + produces>(); + //produces>(); + } + + //------------------------------------------------ + void WireModifier::produceData(art::Event& evt) + { + // DEBUG: get data wires + mf::LogVerbatim("WireModifier") + << "DEBUG: get data wires!"; + + // here's where the "magic" happens + art::ServiceHandle tfs; + + // get a clock and det props for the event + const detinfo::DetectorPropertiesData detProp = art::ServiceHandle()->DataFor(evt); + + // get the things to do the things on + //art::Handle< std::vector > wireHandle; + //evt.getByLabel(fWireLabel, wireHandle); + //auto const& wireVec(*wireHandle); + + //art::FindManyP digit_assn(wireHandle, evt, fWireLabel); + + // get the _hits_ + art::Handle< std::vector > hitHandle; + evt.getByLabel(fHitLabel, hitHandle); + //auto const& hitVec(*hitHandle); + std::vector> hitPtrVec; + art::fill_ptr_vector(hitPtrVec, hitHandle); + art::FindOneP hitToWireAssns(hitHandle, evt, fHitLabel); + + // put the new stuff somewhere + std::unique_ptr> new_wires(new std::vector()); + std::unique_ptr> new_crois(new std::vector()); + //std::unique_ptr> new_digit_assn(new art::Assns()); + + sys::WireModUtility wmUtil(fGeometry, fWireReadout, detProp); // detector geometry & properties + wmUtil.applyChannelScale = fApplyChannel; + wmUtil.applyXScale = fApplyX; + wmUtil.applyYZScale = fApplyYZ; + wmUtil.applyXZAngleScale = fApplyXZAngle; + wmUtil.applyYZAngleScale = fApplyYZAngle; + wmUtil.applydEdXScale = fApplydEdX; + if (wmUtil.applyChannelScale) + { + wmUtil.spline_Charge_Channel = fSpline_charge_Channel; + wmUtil.spline_Sigma_Channel = fSpline_sigma_Channel; + } + if (wmUtil.applyXScale) + { + wmUtil.splines_Charge_X = fSpline_charge_X; + wmUtil.splines_Sigma_X = fSpline_sigma_X; + } + if (wmUtil.applyYZScale) + { + wmUtil.graph2Ds_Charge_YZ = fGraph_charge_YZ; + wmUtil.graph2Ds_Sigma_YZ = fGraph_sigma_YZ; + } + if (wmUtil.applyXZAngleScale) + { + wmUtil.splines_Charge_XZAngle = fSpline_charge_XZAngle; + wmUtil.splines_Sigma_XZAngle = fSpline_sigma_XZAngle; + } + if (wmUtil.applyYZAngleScale) + { + wmUtil.splines_Charge_YZAngle = fSpline_charge_YZAngle; + wmUtil.splines_Sigma_YZAngle = fSpline_sigma_YZAngle; + } + if (wmUtil.applydEdXScale) + { + wmUtil.splines_Charge_dEdX = fSpline_charge_dEdX; + wmUtil.splines_Sigma_dEdX = fSpline_sigma_dEdX; + } + + // add some debugging here + MF_LOG_VERBATIM("WireModifier") + << "DUMP CONFIG:" << '\n' + << "---------------------------------------------------" << '\n' + << " applyChannelScale: " << wmUtil.applyChannelScale << '\n' + << " applyXScale: " << wmUtil.applyXScale << '\n' + << " applyYZScale: " << wmUtil.applyYZScale << '\n' + << " applyXZAngleScale: " << wmUtil.applyXZAngleScale << '\n' + << " applyYZAngleScale: " << wmUtil.applyYZAngleScale << '\n' + << " applydEdXScale: " << wmUtil.applydEdXScale << '\n' + << " readoutWindowTicks: " << wmUtil.readoutWindowTicks << '\n' + << " tickOffset: " << wmUtil.tickOffset << '\n' + << "---------------------------------------------------"; + + // loop-de-loop + for(size_t i_w = 0; i_w < hitPtrVec.size(); ++i_w) + { + MF_LOG_DEBUG("WireModifier") + << "Checking hit " << i_w; + + art::Ptr hitPtr = hitPtrVec.at(i_w); + + if (std::abs(hitPtr->RMS() - 10.0 / 3.0) > 0.00001) + continue; + mf::LogVerbatim("WireModified") + << "HIT " << i_w << ": Does Integral / (Amplitude * Sigma * sqrt(2*pi)) = 1? " + << "(" << hitPtr->Integral() << ") / (" << hitPtr->PeakAmplitude() << " * " << hitPtr->RMS() << " * 2.506628275) = " << (hitPtr->Integral() / (hitPtr->PeakAmplitude() * hitPtr->RMS() * 2.506628275)); + art::Ptr wirePtr = hitToWireAssns.at(hitPtr.key()); + + readout::ROPID ropID = fWireReadout->ChannelToROP(wirePtr->Channel()); + std::string titleStr = "Cryo_" + std::to_string(ropID.Cryostat) + + "_TPCset_" + std::to_string(ropID.TPCset) + + "_ReadOutPlane_" + std::to_string(ropID.ROP) + + "_Hit_" + std::to_string(i_w); + TH1F* dataHitHist = new TH1F(("Data_" + titleStr).c_str(), ";Sample;Arbitrary Units", hitPtr->EndTick() - hitPtr->StartTick() + 10, hitPtr->StartTick() - 5, hitPtr->EndTick() + 5); + for (int tick = hitPtr->StartTick() - 5; tick < hitPtr->EndTick() + 5; ++tick) + { + float dataSample = 0.0; + if (tick < (int)wirePtr->Signal().size() && tick > 0) + dataSample = wirePtr->Signal().at(tick); + dataHitHist->SetBinContent(tick - (hitPtr->StartTick() - 5) + 1, dataSample); + } + TH1F* dataHitHist_toSave = tfs->make(*dataHitHist); + TF1* fitHitHist = new TF1(("Fit_" + titleStr).c_str(), "gaus(0)", hitPtr->StartTick(), hitPtr->EndTick()); + fitHitHist->SetParameters(hitPtr->PeakAmplitude(), hitPtr->PeakTime(), hitPtr->RMS()); + TGraph* fitHitGraph = tfs->make(fitHitHist); + fitHitGraph->Write(); + + mf::LogDebug("WireModifier") + << "Saved histogram " << dataHitHist_toSave->GetName() << " with fit " << fitHitGraph->GetName(); + + //if (fSaveHistsByChannel) + //{ + // readout::ROPID ropID = fGeometry->ChannelToROP(wirePtr->Channel()); + // std::string titleStr = "Cryo-" + std::to_string(ropID.Cryostat) + // + "_TPCset-" + std::to_string(ropID.TPCset) + // + "_ReadOutPlane-" + std::to_string(ropID.ROP) + // + "_Channel-" + std::to_string(wirePtr->Channel()); + // TH1F* dataChannelHist = new TH1F(("Data_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + // for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + // { + // float dataSample = (tick < wirePtr->Signal().size()) ? wirePtr->Signal().at(tick) : 0; + // dataChannelHist->SetBinContent(tick + 1, dataSample); + // } + // + // TH1F* dataChannelHist_toSave = tfs->make(*dataChannelHist); + // mf::LogDebug("WireModifier") + // << "Saved histograms " << dataChannelHist_toSave->GetName(); + //} + + //if (fSaveHistsByWire) + //{ + // std::vector wireIDs = fGeometry->ChannelToWire(wirePtr->Channel()); + // mf::LogDebug("WireModifier") + // << "Channel " << wirePtr->Channel() << " has " << wireIDs.size() << " wire(s)"; + // for (auto const& wireID : wireIDs) + // { + // std::string titleStr = "Cryo-" + std::to_string(wireID.Cryostat) + // + "_TPC-" + std::to_string(wireID.TPC) + // + "_Plane-" + std::to_string(wireID.Plane) + // + "_Wire-" + std::to_string(wireID.Wire); + // TH1F* dataWireHist = new TH1F(("Data_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + // for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + // { + // float dataSample = (tick < wirePtr->Signal().size()) ? wirePtr->Signal().at(tick) : 0; + // dataWireHist->SetBinContent(tick + 1, dataSample); + // } + + // TH1F* dataWireHist_toSave = tfs->make(*dataWireHist); + // mf::LogDebug("WireModifier") + // << "Saved histograms " << dataWireHist_toSave->GetName(); + // } + //} + } + + evt.put(std::move(new_wires)); + evt.put(std::move(new_crois)); + } + + //------------------------------------------------ + void WireModifier::produce(art::Event& evt) + { + //DEBUG: data mode + if (fIsData) + { + this->produceData(evt); + return; + } + + // here's where the "magic" happens + art::ServiceHandle tfs; + + // get a clock and det props for the event + const detinfo::DetectorPropertiesData detProp = art::ServiceHandle()->DataFor(evt); + + // get the things to do the things on + art::Handle< std::vector > wireHandle; + evt.getByLabel(fWireLabel, wireHandle); + auto const& wireVec(*wireHandle); + + art::FindManyP digit_assn(wireHandle, evt, fWireLabel); + + art::Handle< std::vector > edepOrigHandle; + evt.getByLabel(fEDepOrigLabel, edepOrigHandle); + auto const& edepOrigVec(*edepOrigHandle); + + art::Handle< std::vector > edepShiftedHandle; + evt.getByLabel(fEDepShftLabel, edepShiftedHandle); + auto const& edepShiftedVec(*edepShiftedHandle); + + art::Handle< std::vector > hitHandle; + evt.getByLabel(fHitLabel, hitHandle); + auto const& hitVec(*hitHandle); + + // put the new stuff somewhere + std::unique_ptr> new_wires(new std::vector()); + std::unique_ptr> new_crois(new std::vector()); + //std::unique_ptr> new_digit_assn(new art::Assns()); + + sys::WireModUtility wmUtil(fGeometry, fWireReadout, detProp); // detector geometry & properties + wmUtil.applyChannelScale = fApplyChannel; + wmUtil.applyXScale = fApplyX; + wmUtil.applyYZScale = fApplyYZ; + wmUtil.applyXZAngleScale = fApplyXZAngle; + wmUtil.applyYZAngleScale = fApplyYZAngle; + wmUtil.applydEdXScale = fApplydEdX; + if (wmUtil.applyChannelScale) + { + wmUtil.spline_Charge_Channel = fSpline_charge_Channel; + wmUtil.spline_Sigma_Channel = fSpline_sigma_Channel; + } + if (wmUtil.applyXScale) + { + wmUtil.splines_Charge_X = fSpline_charge_X; + wmUtil.splines_Sigma_X = fSpline_sigma_X; + } + if (wmUtil.applyYZScale) + { + wmUtil.graph2Ds_Charge_YZ = fGraph_charge_YZ; + wmUtil.graph2Ds_Sigma_YZ = fGraph_sigma_YZ; + } + if (wmUtil.applyXZAngleScale) + { + wmUtil.splines_Charge_XZAngle = fSpline_charge_XZAngle; + wmUtil.splines_Sigma_XZAngle = fSpline_sigma_XZAngle; + } + if (wmUtil.applyYZAngleScale) + { + wmUtil.splines_Charge_YZAngle = fSpline_charge_YZAngle; + wmUtil.splines_Sigma_YZAngle = fSpline_sigma_YZAngle; + } + if (wmUtil.applydEdXScale) + { + wmUtil.splines_Charge_dEdX = fSpline_charge_dEdX; + wmUtil.splines_Sigma_dEdX = fSpline_sigma_dEdX; + } + + // add some debugging here + MF_LOG_VERBATIM("WireModifier") + << "DUMP CONFIG:" << '\n' + << "---------------------------------------------------" << '\n' + << " applyChannelScale: " << wmUtil.applyChannelScale << '\n' + << " applyXScale: " << wmUtil.applyXScale << '\n' + << " applyYZScale: " << wmUtil.applyYZScale << '\n' + << " applyXZAngleScale: " << wmUtil.applyXZAngleScale << '\n' + << " applyYZAngleScale: " << wmUtil.applyYZAngleScale << '\n' + << " applydEdXScale: " << wmUtil.applydEdXScale << '\n' + << " readoutWindowTicks: " << wmUtil.readoutWindowTicks << '\n' + << " tickOffset: " << wmUtil.tickOffset << '\n' + << "---------------------------------------------------"; + + // do the things + double offset_ADC = 0; // don't use an offset atm + MF_LOG_VERBATIM("WireModifier") + << "Get Edep Map"; + wmUtil.FillROIMatchedEdepMap(edepShiftedVec, wireVec, offset_ADC); + MF_LOG_VERBATIM("WireModifier") + << "Got Edep Map." << '\n' + << "Get Hit Map"; + wmUtil.FillROIMatchedHitMap(hitVec, wireVec); + MF_LOG_VERBATIM("WireModifier") + << "Got Hit Map."; + + // loop-de-loop + for(size_t i_w = 0; i_w < wireVec.size(); ++i_w) + { + MF_LOG_DEBUG("WireModifier") + << "Checking wire " << i_w; + + auto const& wire = wireVec.at(i_w); + + + recob::Wire::RegionsOfInterest_t new_rois; + recob::ChannelROI::RegionsOfInterest_t new_rois_ints; + new_rois .resize(wire.SignalROI().size()); + new_rois_ints.resize(wire.SignalROI().size()); + + unsigned int my_plane = geo::kUnknown; + if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 0)).View()) + { + MF_LOG_DEBUG("WireModifier") + << "Wire is on plane 0, view " << wire.View(); + my_plane = 0; + } else if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 1)).View()) { + MF_LOG_DEBUG("WireModifier") + << "Wire is on plane 1, view " << wire.View(); + my_plane = 1; + } else if (wire.View() == fWireReadout->Plane(geo::PlaneID(0, 0, 2)).View()) { + MF_LOG_DEBUG("WireModifier") + << "Wire is on plane 2, view " << wire.View(); + my_plane = 2; + } + + if (my_plane == geo::kUnknown) + { + MF_LOG_DEBUG("WireModifier") + << "Wire is on unsupported plane. Skip."; + } + + // keep track of if this wire is modified + bool isModified = false; + + for(size_t i_r = 0; i_r < wire.SignalROI().get_ranges().size(); ++i_r) + { + MF_LOG_DEBUG("WireModifier") + << " Checking ROI " << i_r; + + auto const& range = wire.SignalROI().get_ranges()[i_r]; + sys::WireModUtility::ROI_Key_t roi_key(wire.Channel(), i_r); + + std::vector modified_data(range.data()); + + auto it_map = wmUtil.ROIMatchedEdepMap.find(roi_key); + if(it_map==wmUtil.ROIMatchedEdepMap.end()){ + new_rois .add_range(range.begin_index(), modified_data); + new_rois_ints.add_range(range.begin_index(), modified_data); + MF_LOG_DEBUG("WireModifier") + << " Could not find matching Edep. Skip"; + continue; + } + std::vector matchedEdepIdxVec = it_map->second; + if(matchedEdepIdxVec.size() == 0) + { + new_rois .add_range(range.begin_index(), modified_data); + new_rois_ints.add_range(range.begin_index(), modified_data); + MF_LOG_DEBUG("WireModifier") + << " No indices for Edep. Skip"; + continue; + } + std::vector matchedEdepPtrVec; + std::vector matchedShiftedEdepPtrVec; + for(auto i_e : matchedEdepIdxVec) + { + matchedEdepPtrVec.push_back(&edepOrigVec[i_e]); + matchedShiftedEdepPtrVec.push_back(&edepShiftedVec[i_e]); + } + MF_LOG_DEBUG("WireModifier") + << " Found " << matchedShiftedEdepPtrVec.size() << " shifted Edeps"; + + std::vector matchedHitPtrVec; + auto it_hit_map = wmUtil.ROIMatchedHitMap.find(roi_key); + if( it_hit_map != wmUtil.ROIMatchedHitMap.end() ) { + for( auto i_h : it_hit_map->second ) + matchedHitPtrVec.push_back(&hitVec[i_h]); + } + + MF_LOG_DEBUG("WireModifier") + << " Found " << matchedHitPtrVec.size() << " matching hits"; + + auto roi_properties = wmUtil.CalcROIProperties(wire, i_r); + MF_LOG_DEBUG("WireModifier") + << " ROI Properties:" << '\n' + << " key: (" << roi_properties.key.first << ", " << roi_properties.key.second << ")" << '\n' + << " view: " << roi_properties.view << '\n' + << " begin: " << roi_properties.begin << '\n' + << " end: " << roi_properties.end << '\n' + << " total_q: " << roi_properties.total_q << '\n' + << " center: " << roi_properties.center << '\n' + << " sigma: " << roi_properties.sigma; + + auto subROIPropVec = wmUtil.CalcSubROIProperties(roi_properties, matchedHitPtrVec); + + MF_LOG_DEBUG("WireModifier") + << " have " << subROIPropVec.size() << " SubROT"; + + auto SubROIMatchedShiftedEdepMap = wmUtil.MatchEdepsToSubROIs(subROIPropVec, matchedShiftedEdepPtrVec, offset_ADC); + MF_LOG_DEBUG("WireModifier") + << " size of SubROIMatchedShiftedEdepMap: " << SubROIMatchedShiftedEdepMap.size(); + std::map> SubROIMatchedEdepMap; + for ( auto const& key_edepPtrVec_pair : SubROIMatchedShiftedEdepMap ) { + auto key = key_edepPtrVec_pair.first; + for ( auto const& shifted_edep_ptr : key_edepPtrVec_pair.second ) { + for ( unsigned int i_e=0; i_e < matchedShiftedEdepPtrVec.size(); i_e++ ) { + if ( shifted_edep_ptr == matchedShiftedEdepPtrVec[i_e] ) { + MF_LOG_DEBUG("WireModifier") + << " found matching shifted Edep!"; + SubROIMatchedEdepMap[key].push_back(matchedEdepPtrVec[i_e]); + break; + } + } + } + } + MF_LOG_DEBUG("WireModifier") + << " size of SubROIMatchedEdepMap: " << SubROIMatchedEdepMap.size(); + + std::map SubROIMatchedScalesMap; + for ( auto const& subroi_prop : subROIPropVec ) { + sys::WireModUtility::ScaleValues_t scale_vals; + auto key = subroi_prop.key; + auto key_it = SubROIMatchedEdepMap.find(key); + + if ( key_it != SubROIMatchedEdepMap.end() && key_it->second.size() > 0 ) { + auto truth_vals = wmUtil.CalcPropertiesFromEdeps(key_it->second, offset_ADC); + + if ( truth_vals.total_energy < 0.3 && subroi_prop.total_q > 80 ) { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + } + else { + scale_vals = wmUtil.GetScaleValues(truth_vals, roi_properties); + mf::LogDebug("WireModifier") + << "Scaling! Q scale: " << scale_vals.r_Q + << " sigma scale: " << scale_vals.r_sigma; + isModified = true; + } + } + else { + scale_vals.r_Q = 1.; + scale_vals.r_sigma = 1.; + } + + SubROIMatchedScalesMap[key] = scale_vals; + } + + wmUtil.ModifyROI(modified_data, roi_properties, subROIPropVec, SubROIMatchedScalesMap); + new_rois .add_range(roi_properties.begin, modified_data); + new_rois_ints.add_range(roi_properties.begin, modified_data); + } + + + + new_wires->emplace_back(new_rois, wire.Channel(), wire.View()); + new_crois->emplace_back(new_rois_ints, wire.Channel() ); + + if (fSaveHistsByChannel && isModified) + { + readout::ROPID ropID = fWireReadout->ChannelToROP(wire.Channel()); + std::string titleStr = "Cryo-" + std::to_string(ropID.Cryostat) + + "_TPCset-" + std::to_string(ropID.TPCset) + + "_ReadOutPlane-" + std::to_string(ropID.ROP) + + "_Channel-" + std::to_string(wire.Channel()); + TH1F* oldChannelHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newChannelHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = (tick < wire .Signal().size() ) ? wire .Signal().at(tick) : 0; + float newSample = (tick < new_wires->back().Signal().size() ) ? new_wires->back().Signal().at(tick) : 0; + oldChannelHist->SetBinContent(tick + 1, oldSample); + newChannelHist->SetBinContent(tick + 1, newSample); + } + + TH1F* oldChannelHist_toSave = tfs->make(*oldChannelHist); + TH1F* newChannelHist_toSave = tfs->make(*newChannelHist); + mf::LogDebug("WireModifier") + << "Saved histograms " << oldChannelHist_toSave->GetName() << '\n' + << " and " << newChannelHist_toSave->GetName(); + } + + if (fSaveHistsByWire && isModified) + { + std::vector wireIDs = fWireReadout->ChannelToWire(wire.Channel()); + mf::LogDebug("WireModifier") + << "Channel " << wire.Channel() << " has " << wireIDs.size() << " wire(s)"; + for (auto const& wireID : wireIDs) + { + std::string titleStr = "Cryo-" + std::to_string(wireID.Cryostat) + + "_TPC-" + std::to_string(wireID.TPC) + + "_Plane-" + std::to_string(wireID.Plane) + + "_Wire-" + std::to_string(wireID.Wire); + TH1F* oldWireHist = new TH1F(("Old_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + TH1F* newWireHist = new TH1F(("New_" + titleStr).c_str(), ";Sample;Arbitrary Units", wmUtil.readoutWindowTicks, 0, wmUtil.readoutWindowTicks); + for (size_t tick = 0; tick < wmUtil.readoutWindowTicks; ++tick) + { + float oldSample = (tick < wire .Signal().size() ) ? wire .Signal().at(tick) : 0; + float newSample = (tick < new_wires->back().Signal().size() ) ? new_wires->back().Signal().at(tick) : 0; + oldWireHist->SetBinContent(tick + 1, oldSample); + newWireHist->SetBinContent(tick + 1, newSample); + } + + TH1F* oldWireHist_toSave = tfs->make(*oldWireHist); + TH1F* newWireHist_toSave = tfs->make(*newWireHist); + mf::LogDebug("WireModifier") + << "Saved histograms " << oldWireHist_toSave->GetName() << '\n' + << " and " << newWireHist_toSave->GetName(); + } + } + + //auto const& rd_ptrs = digit_assn.at(i_w); + //for(auto const& rd_ptr : rd_ptrs) + // util::CreateAssn(*this, evt, *new_wires, rd_ptr, *new_digit_assn, new_wires->size() - 1); + } // end loop over wires + + evt.put(std::move(new_wires)); + evt.put(std::move(new_crois)); + //evt.put(std::move(new_digit_assn)); + } + DEFINE_ART_MODULE(WireModifier) +} // end namespace diff --git a/icaruscode/WireMod/allRatio_Coarse_XW.root b/icaruscode/WireMod/allRatio_Coarse_XW.root new file mode 100644 index 000000000..ac01e5a23 Binary files /dev/null and b/icaruscode/WireMod/allRatio_Coarse_XW.root differ diff --git a/icaruscode/WireMod/hitcompjob.fcl b/icaruscode/WireMod/hitcompjob.fcl new file mode 100644 index 000000000..a231d1ea8 --- /dev/null +++ b/icaruscode/WireMod/hitcompjob.fcl @@ -0,0 +1,61 @@ +#include "services_common_icarus.fcl" +#include "HitComp.fcl" + +process_name: HitComp + +services: +{ + @table::icarus_basic_services + TFileService: { fileName: "hitcomp_hist.root" closeFileFast: false } + message: @local::icarus_message_services_interactive_debug +} + +outputs: +{ + hitcomp: + { + module_type: RootOutput + fileName: "hitcomp_out.root" + results: + { + producers: + { + originalEE: { @table::standard_hitcomp } + originalEW: { @table::standard_hitcomp } + originalWE: { @table::standard_hitcomp } + originalWW: { @table::standard_hitcomp } + modifiedEE: { @table::standard_hitcomp } + modifiedEW: { @table::standard_hitcomp } + modifiedWE: { @table::standard_hitcomp } + modifiedWW: { @table::standard_hitcomp } + } + rpPath: [originalEE, originalEW, originalWE, originalWW, modifiedEE, modifiedEW, modifiedWE, modifiedWW] + } + } +} + +physics: +{ + stream1: [ hitcomp ] +} + +outputs.hitcomp.results.producers.originalEE: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.originalEE.Label: "gaushitTPCEE" +outputs.hitcomp.results.producers.originalEW: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.originalEW.Label: "gaushitTPCEW" +outputs.hitcomp.results.producers.originalWE: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.originalWE.Label: "gaushitTPCWE" +outputs.hitcomp.results.producers.originalWW: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.originalWW.Label: "gaushitTPCWW" +outputs.hitcomp.results.producers.modifiedEE: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.modifiedEE.Label: "gaushit1dTPCEE" +outputs.hitcomp.results.producers.modifiedEE.Process: "WireModifier" +outputs.hitcomp.results.producers.modifiedEW: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.modifiedEW.Label: "gaushit1dTPCEW" +outputs.hitcomp.results.producers.modifiedEW.Process: "WireModifier" +outputs.hitcomp.results.producers.modifiedWE: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.modifiedWE.Label: "gaushit1dTPCWE" +outputs.hitcomp.results.producers.modifiedWE.Process: "WireModifier" +outputs.hitcomp.results.producers.modifiedWW: { @table::standard_hitcomp } +outputs.hitcomp.results.producers.modifiedWW.Label: "gaushit1dTPCWW" +outputs.hitcomp.results.producers.modifiedWW.Process: "WireModifier" diff --git a/icaruscode/WireMod/hitttreemakerjob.fcl b/icaruscode/WireMod/hitttreemakerjob.fcl new file mode 100644 index 000000000..209067da7 --- /dev/null +++ b/icaruscode/WireMod/hitttreemakerjob.fcl @@ -0,0 +1,61 @@ +#include "services_common_icarus.fcl" +#include "HitTTreeMaker.fcl" + +process_name: HitTTreeMaker + +services: +{ + @table::icarus_basic_services + TFileService: { fileName: "hitttreemaker_hist.root" closeFileFast: false } + message: @local::icarus_message_services_interactive_debug +} + +outputs: +{ + hitttreemaker: + { + module_type: RootOutput + fileName: "hitttreemaker_out.root" + results: + { + producers: + { + originalEE: { @table::standard_hitttreemaker } + originalEW: { @table::standard_hitttreemaker } + originalWE: { @table::standard_hitttreemaker } + originalWW: { @table::standard_hitttreemaker } + modifiedEE: { @table::standard_hitttreemaker } + modifiedEW: { @table::standard_hitttreemaker } + modifiedWE: { @table::standard_hitttreemaker } + modifiedWW: { @table::standard_hitttreemaker } + } + rpPath: [originalEE, originalEW, originalWE, originalWW, modifiedEE, modifiedEW, modifiedWE, modifiedWW] + } + } +} + +physics: +{ + stream1: [ hitttreemaker ] +} + +outputs.hitttreemaker.results.producers.originalEE: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.originalEE.Label: "gaushitTPCEE" +outputs.hitttreemaker.results.producers.originalEW: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.originalEW.Label: "gaushitTPCEW" +outputs.hitttreemaker.results.producers.originalWE: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.originalWE.Label: "gaushitTPCWE" +outputs.hitttreemaker.results.producers.originalWW: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.originalWW.Label: "gaushitTPCWW" +outputs.hitttreemaker.results.producers.modifiedEE: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.modifiedEE.Label: "gaushit1dTPCEE" +outputs.hitttreemaker.results.producers.modifiedEE.Process: "WireModifier" +outputs.hitttreemaker.results.producers.modifiedEW: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.modifiedEW.Label: "gaushit1dTPCEW" +outputs.hitttreemaker.results.producers.modifiedEW.Process: "WireModifier" +outputs.hitttreemaker.results.producers.modifiedWE: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.modifiedWE.Label: "gaushit1dTPCWE" +outputs.hitttreemaker.results.producers.modifiedWE.Process: "WireModifier" +outputs.hitttreemaker.results.producers.modifiedWW: { @table::standard_hitttreemaker } +outputs.hitttreemaker.results.producers.modifiedWW.Label: "gaushit1dTPCWW" +outputs.hitttreemaker.results.producers.modifiedWW.Process: "WireModifier" diff --git a/icaruscode/WireMod/roicounterjob.fcl b/icaruscode/WireMod/roicounterjob.fcl new file mode 100644 index 000000000..805f71dcb --- /dev/null +++ b/icaruscode/WireMod/roicounterjob.fcl @@ -0,0 +1,20 @@ +#include "ROICounter.fcl" +#include "messages_icarus.fcl" + +process_name: ROICounter + +services: +{ + TFileService: { fileName: "roicount_hist.root" closeFileFast: false } + message: @local::icarus_message_services_interactive_debug +} + +physics: +{ + analyzers: + { + roicounts: @local::standard_roicounter + } + countroi: [ roicounts ] + end_paths: [ countroi ] +} diff --git a/icaruscode/WireMod/stage1_icarus_wiremod_develop.fcl b/icaruscode/WireMod/stage1_icarus_wiremod_develop.fcl new file mode 100644 index 000000000..7e43eb6d1 --- /dev/null +++ b/icaruscode/WireMod/stage1_icarus_wiremod_develop.fcl @@ -0,0 +1,84 @@ +#include "WireModifierXXW_closure.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +# add the WireMod sequence to the standard stage1 sequence +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +# produce the WireMod products +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# tell gaushit2d to use the ROIs from WireMod +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# tell gaushitPT2d to use the ROIs from WireMod +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.UseGraph2DInterpolation: false +physics.producers.WireModTPCEW.UseGraph2DInterpolation: false +physics.producers.WireModTPCWE.UseGraph2DInterpolation: false +physics.producers.WireModTPCWW.UseGraph2DInterpolation: false + + +# allRatio_Coarse_XW.root has X/theta axes, not Y/Z: disable YZ correction +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +# tell the caloskimmer to use the ROIs from WireMod +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# drop products that we don't need +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag.fcl b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag.fcl new file mode 100644 index 000000000..2e67a701f --- /dev/null +++ b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag.fcl @@ -0,0 +1,89 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.UseGraph2DInterpolation: false +physics.producers.WireModTPCEW.UseGraph2DInterpolation: false +physics.producers.WireModTPCWE.UseGraph2DInterpolation: false +physics.producers.WireModTPCWW.UseGraph2DInterpolation: false + +# allRatio_Coarse_XW.root has (X, theta) axes, not (Y, Z): disable YZ correction +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_null.fcl b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_null.fcl new file mode 100644 index 000000000..3260279ab --- /dev/null +++ b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_null.fcl @@ -0,0 +1,13 @@ +# Null-scale baseline: identical to stage1_icarus_wiremod_develop_hitdiag.fcl +# but with r_Q = r_sigma = 1 forced everywhere (no WireMod correction applied). + +#include "stage1_icarus_wiremod_develop_hitdiag.fcl" + +physics.producers.WireModTPCEE.SetNullScaleIntegral: true +physics.producers.WireModTPCEE.SetNullScaleWidth: true +physics.producers.WireModTPCEW.SetNullScaleIntegral: true +physics.producers.WireModTPCEW.SetNullScaleWidth: true +physics.producers.WireModTPCWE.SetNullScaleIntegral: true +physics.producers.WireModTPCWE.SetNullScaleWidth: true +physics.producers.WireModTPCWW.SetNullScaleIntegral: true +physics.producers.WireModTPCWW.SetNullScaleWidth: true diff --git a/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_roi.fcl b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_roi.fcl new file mode 100644 index 000000000..333fa6762 --- /dev/null +++ b/icaruscode/WireMod/stage1_icarus_wiremod_develop_hitdiag_roi.fcl @@ -0,0 +1,107 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.UseGraph2DInterpolation: false +physics.producers.WireModTPCEW.UseGraph2DInterpolation: false +physics.producers.WireModTPCWE.UseGraph2DInterpolation: false +physics.producers.WireModTPCWW.UseGraph2DInterpolation: false + +# allRatio_Coarse_XW.root has (X, theta) axes, not (Y, Z): disable YZ correction +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +# SavePerHitData: fills the per-hit WireModTPCxx/ROITree used by the notebook. +# SaveROITree: saves the full ROI waveform (roi_before) alongside the hit parameters. +# SaveTickHistograms / SaveByChannel: kept false to limit output file size. +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.producers.WireModTPCEE.SaveROITree: true +physics.producers.WireModTPCEW.SaveROITree: true +physics.producers.WireModTPCWE.SaveROITree: true +physics.producers.WireModTPCWW.SaveROITree: true + +physics.producers.WireModTPCEE.SaveTickHistograms: false +physics.producers.WireModTPCEW.SaveTickHistograms: false +physics.producers.WireModTPCWE.SaveTickHistograms: false +physics.producers.WireModTPCWW.SaveTickHistograms: false + +physics.producers.WireModTPCEE.SaveByChannel: false +physics.producers.WireModTPCEW.SaveByChannel: false +physics.producers.WireModTPCWE.SaveByChannel: false +physics.producers.WireModTPCWW.SaveByChannel: false + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr.fcl b/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr.fcl new file mode 100644 index 000000000..3695afc0b --- /dev/null +++ b/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr.fcl @@ -0,0 +1,75 @@ +#include "WireModifierXXW.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +# add the WireMod sequence to the standard stage1 sequence +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +# produce the WireMod products +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# tell gaushit2d to use the ROIs from WireMod +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# tell gaushitPT2d to use the ROIs from WireMod +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.UseGraph2DInterpolation: false +physics.producers.WireModTPCEW.UseGraph2DInterpolation: false +physics.producers.WireModTPCWE.UseGraph2DInterpolation: false +physics.producers.WireModTPCWW.UseGraph2DInterpolation: false + +# tell the caloskimmer to use the ROIs from WireMod +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# drop products that we don't need +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModTPC*_*_*" +] +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" diff --git a/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr_run4.fcl b/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr_run4.fcl new file mode 100644 index 000000000..39ea338ed --- /dev/null +++ b/icaruscode/WireMod/stage1_run2_icarus_overlay_wiremodcorr_run4.fcl @@ -0,0 +1,6 @@ +#include "stage1_run2_icarus_overlay_wiremodcorr.fcl" + +physics.producers.WireModTPCEE.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCEW.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCWE.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCWW.RatioFileName_XXW: "Run4_XTheta_coarse.root" diff --git a/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr.fcl b/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr.fcl new file mode 100644 index 000000000..a773fdce4 --- /dev/null +++ b/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr.fcl @@ -0,0 +1,75 @@ +#include "WireModifierXXW.fcl" +#include "stage1_run2_larcv_icarus_overlay.fcl" + +# add the WireMod sequence to the standard stage1 sequence +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +# produce the WireMod products +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# tell gaushit2d to use the ROIs from WireMod +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# tell gaushitPT2d to use the ROIs from WireMod +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.UseGraph2DInterpolation: false +physics.producers.WireModTPCEW.UseGraph2DInterpolation: false +physics.producers.WireModTPCWE.UseGraph2DInterpolation: false +physics.producers.WireModTPCWW.UseGraph2DInterpolation: false + +# tell the caloskimmer to use the ROIs from WireMod +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# drop products that we don't need +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModTPC*_*_*" +] +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" diff --git a/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr_run4.fcl b/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr_run4.fcl new file mode 100644 index 000000000..a8d238468 --- /dev/null +++ b/icaruscode/WireMod/stage1_run2_larcv_icarus_overlay_wiremodcorr_run4.fcl @@ -0,0 +1,6 @@ +#include "stage1_run2_larcv_icarus_overlay_wiremodcorr.fcl" + +physics.producers.WireModTPCEE.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCEW.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCWE.RatioFileName_XXW: "Run4_XTheta_coarse.root" +physics.producers.WireModTPCWW.RatioFileName_XXW: "Run4_XTheta_coarse.root" diff --git a/icaruscode/WireMod/stage1_wiremod_2d_noscaling.fcl b/icaruscode/WireMod/stage1_wiremod_2d_noscaling.fcl new file mode 100644 index 000000000..a01872f35 --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_2d_noscaling.fcl @@ -0,0 +1,88 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: true +physics.producers.WireModTPCEE.SetNullScaleWidth: true +physics.producers.WireModTPCEW.SetNullScaleIntegral: true +physics.producers.WireModTPCEW.SetNullScaleWidth: true +physics.producers.WireModTPCWE.SetNullScaleIntegral: true +physics.producers.WireModTPCWE.SetNullScaleWidth: true +physics.producers.WireModTPCWW.SetNullScaleIntegral: true +physics.producers.WireModTPCWW.SetNullScaleWidth: true + +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# force cluster3D (Pandora/TrackCaloSkimmer) onto gaushit2dTPCXX, same hit-finder +# WireMod/WireModHitDiag use (default points it at gaushitPT2dTPCXX instead) +physics.producers.cluster3DCryoE.Hit3DBuilderAlg.HitFinderTagVec: [ "gaushit2dTPCEW", "gaushit2dTPCEE" ] +physics.producers.cluster3DCryoW.Hit3DBuilderAlg.HitFinderTagVec: [ "gaushit2dTPCWW", "gaushit2dTPCWE" ] + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_wiremod_2d_scaled.fcl b/icaruscode/WireMod/stage1_wiremod_2d_scaled.fcl new file mode 100644 index 000000000..ecd51ae46 --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_2d_scaled.fcl @@ -0,0 +1,88 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# force cluster3D (Pandora/TrackCaloSkimmer) onto gaushit2dTPCXX, same hit-finder +# WireMod/WireModHitDiag use (default points it at gaushitPT2dTPCXX instead) +physics.producers.cluster3DCryoE.Hit3DBuilderAlg.HitFinderTagVec: [ "gaushit2dTPCEW", "gaushit2dTPCEE" ] +physics.producers.cluster3DCryoW.Hit3DBuilderAlg.HitFinderTagVec: [ "gaushit2dTPCWW", "gaushit2dTPCWE" ] + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_wiremod_PT_noscaling.fcl b/icaruscode/WireMod/stage1_wiremod_PT_noscaling.fcl new file mode 100644 index 000000000..e6542fe45 --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_PT_noscaling.fcl @@ -0,0 +1,96 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + dummyGaushitPT2dTPCEE, dummyGaushitPT2dTPCEW, dummyGaushitPT2dTPCWE, dummyGaushitPT2dTPCWW, + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# Keep the "before" hit finder (dummyGaushitPT2dTPC*) configuration identical to the "after" +# finder (gaushitPT2dTPC*): clone the fully-configured gaushitPT2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushitPT2dTPCEE: @local::physics.producers.gaushitPT2dTPCEE +physics.producers.dummyGaushitPT2dTPCEW: @local::physics.producers.gaushitPT2dTPCEW +physics.producers.dummyGaushitPT2dTPCWE: @local::physics.producers.gaushitPT2dTPCWE +physics.producers.dummyGaushitPT2dTPCWW: @local::physics.producers.gaushitPT2dTPCWW +physics.producers.dummyGaushitPT2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushitPT2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushitPT2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushitPT2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: true +physics.producers.WireModTPCEE.SetNullScaleWidth: true +physics.producers.WireModTPCEW.SetNullScaleIntegral: true +physics.producers.WireModTPCEW.SetNullScaleWidth: true +physics.producers.WireModTPCWE.SetNullScaleIntegral: true +physics.producers.WireModTPCWE.SetNullScaleWidth: true +physics.producers.WireModTPCWW.SetNullScaleIntegral: true +physics.producers.WireModTPCWW.SetNullScaleWidth: true + +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.producers.WireModTPCEE.HitLabel: "dummyGaushitPT2dTPCEE" +physics.producers.WireModTPCEW.HitLabel: "dummyGaushitPT2dTPCEW" +physics.producers.WireModTPCWE.HitLabel: "dummyGaushitPT2dTPCWE" +physics.producers.WireModTPCWW.HitLabel: "dummyGaushitPT2dTPCWW" + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analyzers.WireModHitDiag.BeforeHitLabels: [ "dummyGaushitPT2dTPCEE", "dummyGaushitPT2dTPCEW", "dummyGaushitPT2dTPCWE", "dummyGaushitPT2dTPCWW" ] +physics.analyzers.WireModHitDiag.AfterHitLabels: [ "gaushitPT2dTPCEE", "gaushitPT2dTPCEW", "gaushitPT2dTPCWE", "gaushitPT2dTPCWW" ] +physics.analyzers.WireModHitDiag.ScaleInfoLabels: [ "WireModTPCEE", "WireModTPCEW", "WireModTPCWE", "WireModTPCWW" ] + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# Pandora/TrackCaloSkimmer already default to gaushitPT2dTPCXX, no override needed + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_dummyGaushitPT2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_wiremod_PT_scaled.fcl b/icaruscode/WireMod/stage1_wiremod_PT_scaled.fcl new file mode 100644 index 000000000..997b62fab --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_PT_scaled.fcl @@ -0,0 +1,96 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + dummyGaushitPT2dTPCEE, dummyGaushitPT2dTPCEW, dummyGaushitPT2dTPCWE, dummyGaushitPT2dTPCWW, + @sequence::WireModSequence, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# Keep the "before" hit finder (dummyGaushitPT2dTPC*) configuration identical to the "after" +# finder (gaushitPT2dTPC*): clone the fully-configured gaushitPT2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushitPT2dTPCEE: @local::physics.producers.gaushitPT2dTPCEE +physics.producers.dummyGaushitPT2dTPCEW: @local::physics.producers.gaushitPT2dTPCEW +physics.producers.dummyGaushitPT2dTPCWE: @local::physics.producers.gaushitPT2dTPCWE +physics.producers.dummyGaushitPT2dTPCWW: @local::physics.producers.gaushitPT2dTPCWW +physics.producers.dummyGaushitPT2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushitPT2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushitPT2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushitPT2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +physics.producers.WireModTPCEE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCEW.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWE.RatioFileName_YZ: "NOFILE" +physics.producers.WireModTPCWW.RatioFileName_YZ: "NOFILE" + +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWW.SavePerHitData: true + +physics.producers.WireModTPCEE.HitLabel: "dummyGaushitPT2dTPCEE" +physics.producers.WireModTPCEW.HitLabel: "dummyGaushitPT2dTPCEW" +physics.producers.WireModTPCWE.HitLabel: "dummyGaushitPT2dTPCWE" +physics.producers.WireModTPCWW.HitLabel: "dummyGaushitPT2dTPCWW" + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag + +physics.analyzers.WireModHitDiag.BeforeHitLabels: [ "dummyGaushitPT2dTPCEE", "dummyGaushitPT2dTPCEW", "dummyGaushitPT2dTPCWE", "dummyGaushitPT2dTPCWW" ] +physics.analyzers.WireModHitDiag.AfterHitLabels: [ "gaushitPT2dTPCEE", "gaushitPT2dTPCEW", "gaushitPT2dTPCWE", "gaushitPT2dTPCWW" ] +physics.analyzers.WireModHitDiag.ScaleInfoLabels: [ "WireModTPCEE", "WireModTPCEW", "WireModTPCWE", "WireModTPCWW" ] + +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# Pandora/TrackCaloSkimmer already default to gaushitPT2dTPCXX, no override needed + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_dummyGaushitPT2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "WARNING" diff --git a/icaruscode/WireMod/stage1_wiremod_diagnostic.fcl b/icaruscode/WireMod/stage1_wiremod_diagnostic.fcl new file mode 100644 index 000000000..ee1be4347 --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_diagnostic.fcl @@ -0,0 +1,94 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +# produce the WireMod products +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# tell gaushit2d to use the ROIs from WireMod +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# tell gaushitPT2d to use the ROIs from WireMod +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +# tell the caloskimmer to use the ROIs from WireMod +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] +physics.analyzers.WireModHitDiag: @local::WireModHitDiag +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +# drop products that we don't need +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModXXWTPC*_*_*" +] +# use additive ROI modification (after = before + [q_mod - q_orig]) +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +# enable full diagnostic output (ROITree, tick histograms, per-hit scale vectors) +physics.producers.WireModTPCEE.SaveROITree: true +physics.producers.WireModTPCEE.SaveTickHistograms: true +physics.producers.WireModTPCEE.SavePerHitData: true +physics.producers.WireModTPCEE.SaveByChannel: true +physics.producers.WireModTPCEW.SaveROITree: true +physics.producers.WireModTPCEW.SaveTickHistograms: true +physics.producers.WireModTPCEW.SavePerHitData: true +physics.producers.WireModTPCEW.SaveByChannel: true +physics.producers.WireModTPCWE.SaveROITree: true +physics.producers.WireModTPCWE.SaveTickHistograms: true +physics.producers.WireModTPCWE.SavePerHitData: true +physics.producers.WireModTPCWE.SaveByChannel: true +physics.producers.WireModTPCWW.SaveROITree: true +physics.producers.WireModTPCWW.SaveTickHistograms: true +physics.producers.WireModTPCWW.SavePerHitData: true +physics.producers.WireModTPCWW.SaveByChannel: true + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "DEBUG" diff --git a/icaruscode/WireMod/stage1_wiremod_float_diagnostic.fcl b/icaruscode/WireMod/stage1_wiremod_float_diagnostic.fcl new file mode 100644 index 000000000..8c3170b4b --- /dev/null +++ b/icaruscode/WireMod/stage1_wiremod_float_diagnostic.fcl @@ -0,0 +1,85 @@ +#include "WireModifierXXW_closure.fcl" +#include "WireModHitDiagnostic.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +# float (ChannelROI-direct) mode: no WMWireToROI, WireModTPCxx produces ChannelROI directly +physics.reco: +[ + @sequence::dummyGaushit2dSeq, + WMROI2Wire, + @sequence::WireModSeq, + @sequence::physics.reco +] + +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +physics.producers.WireModTPCEE.UseChannelROIMode: true +physics.producers.WireModTPCEW.UseChannelROIMode: true +physics.producers.WireModTPCWE.UseChannelROIMode: true +physics.producers.WireModTPCWW.UseChannelROIMode: true + +physics.producers.WireModTPCEE: { @table::physics.producers.WireModTPCEE @table::WireModROITree } +physics.producers.WireModTPCEW: { @table::physics.producers.WireModTPCEW @table::WireModROITree } +physics.producers.WireModTPCWE: { @table::physics.producers.WireModTPCWE @table::WireModROITree } +physics.producers.WireModTPCWW: { @table::physics.producers.WireModTPCWW @table::WireModROITree } + +physics.producers.WireModTPCEE.AdditiveModification: true +physics.producers.WireModTPCEW.AdditiveModification: true +physics.producers.WireModTPCWE.AdditiveModification: true +physics.producers.WireModTPCWW.AdditiveModification: true + +physics.producers.WireModTPCEE.SetNullScaleIntegral: false +physics.producers.WireModTPCEE.SetNullScaleWidth: false +physics.producers.WireModTPCEW.SetNullScaleIntegral: false +physics.producers.WireModTPCEW.SetNullScaleWidth: false +physics.producers.WireModTPCWE.SetNullScaleIntegral: false +physics.producers.WireModTPCWE.SetNullScaleWidth: false +physics.producers.WireModTPCWW.SetNullScaleIntegral: false +physics.producers.WireModTPCWW.SetNullScaleWidth: false + +# WireModTPCxx produces ChannelROI with empty instance label in float mode +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WireModTPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WireModTPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WireModTPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WireModTPCWW" + +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WireModTPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WireModTPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WireModTPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WireModTPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +# WMWireToROI doesn't run in float mode, redirect to original ChannelROI +physics.analyzers.caloskimE.RawDigitproducers: [ "wire2channelroi2d:PHYSCRATEDATATPCEW", + "wire2channelroi2d:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "wire2channelroi2d:PHYSCRATEDATATPCWW", + "wire2channelroi2d:PHYSCRATEDATATPCWE" ] + +physics.analyzers.WireModHitDiag: @local::WireModHitDiag +physics.analysisPath: [ WireModHitDiag ] +physics.end_paths: [ outana, stream1, analysisPath ] + +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*" +] + +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" +services.message.destinations.STDCOUT.threshold: "DEBUG" diff --git a/icaruscode/WireMod/wireMod_stage1.fcl b/icaruscode/WireMod/wireMod_stage1.fcl new file mode 100644 index 000000000..794bd9f24 --- /dev/null +++ b/icaruscode/WireMod/wireMod_stage1.fcl @@ -0,0 +1,59 @@ +#include "WireModifierXXW_closure.fcl" +#include "stage1_run2_icarus_overlay.fcl" + +# add the WireMod sequence to the standard stage1 sequence +physics.reco: +[ + @sequence::WireModSequence, + @sequence::physics.reco +] + +# produce the WireMod products +physics.producers: +{ + @table::WireModTable + @table::physics.producers +} + +# tell gaushit2d to use the ROIs from WireMod +physics.producers.gaushit2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushit2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushit2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushit2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# tell gaushitPT2d to use the ROIs from WireMod +physics.producers.gaushitPT2dTPCEE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEE" +physics.producers.gaushitPT2dTPCEW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCEW" +physics.producers.gaushitPT2dTPCWE.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWE" +physics.producers.gaushitPT2dTPCWW.CalDataModuleLabel: "WMWireToROI:PHYSCRATEDATATPCWW" + +# Keep the "before" hit finder (dummyGaushit2dTPC*) configuration identical to the "after" +# finder (gaushit2dTPC*): clone the fully-configured gaushit2d and reset ONLY the input ROIs +# to the un-modified wire2channelroi2d collection. +physics.producers.dummyGaushit2dTPCEE: @local::physics.producers.gaushit2dTPCEE +physics.producers.dummyGaushit2dTPCEW: @local::physics.producers.gaushit2dTPCEW +physics.producers.dummyGaushit2dTPCWE: @local::physics.producers.gaushit2dTPCWE +physics.producers.dummyGaushit2dTPCWW: @local::physics.producers.gaushit2dTPCWW +physics.producers.dummyGaushit2dTPCEE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEE" +physics.producers.dummyGaushit2dTPCEW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCEW" +physics.producers.dummyGaushit2dTPCWE.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWE" +physics.producers.dummyGaushit2dTPCWW.CalDataModuleLabel: "wire2channelroi2d:PHYSCRATEDATATPCWW" + +# tell the caloskimmer to use the ROIs from WireMod +physics.analyzers.caloskimE.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCEW", + "WMWireToROI:PHYSCRATEDATATPCEE" ] +physics.analyzers.caloskimW.RawDigitproducers: [ "WMWireToROI:PHYSCRATEDATATPCWW", + "WMWireToROI:PHYSCRATEDATATPCWE" ] + +# drop products that we don't need +outputs.out1.outputCommands: +[ + @sequence::outputs.out1.outputCommands, + "drop *_dummyGaushit2dTPC*_*_*", + "drop *_WMROI2Wire_*_*", + "drop *_WireModTPC*_*_*" +] +services.BackTrackerService.BackTracker.SimChannelModuleLabel: "merge" + +services.message.destinations.STDCOUT.threshold: "DEBUG" + diff --git a/icaruscode/WireMod/wiremod_scale_debug.fcl b/icaruscode/WireMod/wiremod_scale_debug.fcl new file mode 100644 index 000000000..cb0bded6a --- /dev/null +++ b/icaruscode/WireMod/wiremod_scale_debug.fcl @@ -0,0 +1,26 @@ +# EmptyEvent job: runs WireModScaleDebug once in beginJob(), no input file needed. +# Run from the directory containing Run4_Coarse_XW.root (LocalRatios convention). + +#include "stage1_icarus_wiremod_pops_hitdiag.fcl" + +source: { + module_type: EmptyEvent + maxEvents: 1 +} + +physics: { + analyzers: { + scaledebug: { + module_type: "WireModScaleDebug" + RatioFileName_XXW: "Run4_Coarse_XW.root" + ThetaEdges: [0, 6, 12, 18, 24, 30, 38, 46, 56, 90] + } + } + ana: [ scaledebug ] + trigger_paths: [] + end_paths: [ ana ] +} + +outputs: {} + +services.message.destinations.STDCOUT.threshold: "ERROR" diff --git a/icaruscode/WireMod/wiremodifierjob.fcl b/icaruscode/WireMod/wiremodifierjob.fcl new file mode 100644 index 000000000..bb98d3ab2 --- /dev/null +++ b/icaruscode/WireMod/wiremodifierjob.fcl @@ -0,0 +1,48 @@ +#include "services_common_icarus.fcl" + +#include "WireModifier.fcl" + +process_name: WireMod + +services: +{ + # what services do we need? + @table::icarus_basic_services + TFileService: { fileName: "testwiremod_hist.root" } # we will want to store some histograms at some point +} + +source: +{ +} + +physics: +{ + producers: + { + wiremodEE: @local::ee_wiremod + wiremodEW: @local::ew_wiremod + wiremodWE: @local::we_wiremod + wiremodWW: @local::ww_wiremod + } + + wmproduce: [ wiremodEE, wiremodEW, wiremodWE, wiremodWW ] + + # you gotta have an output stream + stream1: [ out1 ] + + # trigger_paths is for anything that modifies art::Events + # ie what we want to do + trigger_paths: [ wmproduce ] + + # end_paths is for stuff that doesn't modify art::Events + end_paths: [ stream1 ] +} + +outputs: +{ + out1: + { + module_type: RootOutput + fileName: "wiremod_out.root" + } +} diff --git a/icaruscode/WireMod/wiremodmakehistsjob.fcl b/icaruscode/WireMod/wiremodmakehistsjob.fcl new file mode 100644 index 000000000..ec8bd5c92 --- /dev/null +++ b/icaruscode/WireMod/wiremodmakehistsjob.fcl @@ -0,0 +1,44 @@ +#include "WireModMakeHists.fcl" +#include "services_common_icarus.fcl" + +process_name: WireModMakeHist + +services: +{ + @table::icarus_basic_services + TFileService: { fileName: "wireMod_hist.root" closeFileFast: false } +} + +outputs: +{ + makehists: + { + module_type: RootOutput + fileName: "wireMod_out.root" + results: + { + producers: + { + makehists_ee: { @table::makehists_ee_withHits } + makehists_ew: { @table::makehists_ew_withHits } + makehists_we: { @table::makehists_we_withHits } + makehists_ww: { @table::makehists_ww_withHits } + } + rpPath: [makehists_ee, makehists_ew, makehists_we, makehists_ww] + } + } +} + +physics: +{ + stream1: [ makehists ] +} + +outputs.makehists.results.producers.makehists_ee.TrackLabel: "pandoraKalmanTrackGausCryoE" +outputs.makehists.results.producers.makehists_ee.GetTracks: true +outputs.makehists.results.producers.makehists_ew.TrackLabel: "pandoraKalmanTrackGausCryoE" +outputs.makehists.results.producers.makehists_ew.GetTracks: true +outputs.makehists.results.producers.makehists_we.TrackLabel: "pandoraKalmanTrackGausCryoW" +outputs.makehists.results.producers.makehists_we.GetTracks: true +outputs.makehists.results.producers.makehists_ww.TrackLabel: "pandoraKalmanTrackGausCryoW" +outputs.makehists.results.producers.makehists_ww.GetTracks: true