Skip to content
5 changes: 4 additions & 1 deletion sbndcode/JobConfigurations/standard/caf/cafmakerjob_sbnd.fcl
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,12 @@ physics.producers.cafmaker.FlashMatchSCECryoSuffixes: [""]
physics.producers.cafmaker.TrackHitFillRRStartCut: 1000
physics.producers.cafmaker.TrackHitFillRREndCut: 1000

# Include 3D barycenter flahs matching
# Include 3D barycenter flash matching
physics.producers.cafmaker.TPCPMTBarycenterMatchLabel: "tpcpmtbarycentermatching"

# Include propagation correction on the flash timing
physics.producers.cafmaker.CorrectedOpFlashLabel: "lightpropagationcorrectionSCE"

# Include MC version of PMT Software Trigger
physics.producers.cafmaker.SBNDSoftwareTriggerLabel: "pmtmetricmc"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ physics.producers.cafmaker.SBNDCRTTrackMatchLabel: "crttrackmatchingSCE"
physics.producers.cafmaker.OpT0Label: "opt0finderSCE"
physics.producers.cafmaker.TPCPMTBarycenterMatchLabel: "tpcpmtbarycentermatchingSCE"
physics.producers.cafmaker.CVNLabel: "cvnSCE"
physics.producers.cafmaker.CorrectedOpFlashLabel: "lightpropagationcorrectionSCE"
physics.producers.cafmaker.LightCaloLabel: "lightcaloSCE"

physics.producers.cnnid.WireLabel: "sptpc2d:dnnsp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "SBNDCVNMapper.fcl"
#include "blipreco_configs.fcl"
#include "lightcalo_sbnd.fcl"
#include "sbnd_lightpropagationcorrection_config.fcl"

BEGIN_PROLOG

Expand Down Expand Up @@ -82,6 +83,7 @@ sbnd_reco2_producers:{
opt0finderSCE: @local::sbnd_opt0_finder_one_to_many
tpcpmtbarycentermatching: @local::TPCPMTBarycenterMatchProducerMC
tpcpmtbarycentermatchingSCE: @local::TPCPMTBarycenterMatchProducerSCEMC
lightpropagationcorrectionSCE: @local::LightPropagationCorrectionSCE

### Uncalibrated calorimetry producer for calibration caloskimmer
caloskimCalorimetry: @local::caloskim_calorimetry
Expand Down Expand Up @@ -136,6 +138,7 @@ sbnd_reco2_producer_sequence: [
#, fmatchoparaSCE
, opt0finderSCE
, tpcpmtbarycentermatchingSCE
, lightpropagationcorrectionSCE
, cvn
, cvnSCE
, blipreco
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class LightPropagationCorrectionAna : public art::EDAnalyzer {
double fNuToFLight;
double fNuToFCharge;
double fOpFlashT0Corrected;
double fParticlePropagationTime;
double fPhotonPropagationTime;

unsigned int _eventID;
unsigned int _runID;
Expand All @@ -76,6 +78,8 @@ void LightPropagationCorrectionAna::analyze(art::Event const& e)
fNuToFLight=-99999.;
fNuToFCharge=-99999.;
fOpFlashT0Corrected=-99999.;
fParticlePropagationTime=-99999.;
fPhotonPropagationTime=-99999.;

_eventID = -1;
_runID = -1;
Expand All @@ -95,7 +99,6 @@ void LightPropagationCorrectionAna::analyze(art::Event const& e)
return;
}


std::vector<art::Ptr<sbn::CorrectedOpFlashTiming>> correctedopflash_v;
art::fill_ptr_vector(correctedopflash_v, correctedopflash_h);

Expand All @@ -121,11 +124,15 @@ void LightPropagationCorrectionAna::analyze(art::Event const& e)
std::cout << "Corrected flash time light only " << correctedopflash->NuToFLight << std::endl;
std::cout << "Corrected flash time tpc z corr " << correctedopflash->NuToFCharge << std::endl;
std::cout << "Corrected flash time prop corr tpc z corr " << correctedopflash->OpFlashT0Corrected << std::endl;
std::cout << "Particle propagation time " << correctedopflash->ParticlePropagationTime << std::endl;
std::cout << "Photon propagation time " << correctedopflash->PhotonPropagationTime << std::endl;

fOpFlashT0 = correctedopflash->OpFlashT0;
fNuToFLight = correctedopflash->NuToFLight;
fNuToFCharge = correctedopflash->NuToFCharge;
fOpFlashT0Corrected = correctedopflash->OpFlashT0Corrected;
fParticlePropagationTime = correctedopflash->ParticlePropagationTime;
fPhotonPropagationTime = correctedopflash->PhotonPropagationTime;
fTree->Fill();
}
}
Expand All @@ -144,7 +151,8 @@ void LightPropagationCorrectionAna::beginJob()
fTree->Branch("fNuToFLight", &fNuToFLight, "NuToFLight/d");
fTree->Branch("fNuToFCharge", &fNuToFCharge, "NuToFCharge/d");
fTree->Branch("fOpFlashT0Corrected", &fOpFlashT0Corrected, "OpFlashT0Corrected/d");

fTree->Branch("fParticlePropagationTime", &fParticlePropagationTime, "ParticlePropagationTime/d");
fTree->Branch("fPhotonPropagationTime", &fPhotonPropagationTime, "PhotonPropagationTime/d");
}

DEFINE_ART_MODULE(LightPropagationCorrectionAna)
206 changes: 149 additions & 57 deletions sbndcode/LightPropagationCorrection/LightPropagationCorrection_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ sbnd::LightPropagationCorrection::LightPropagationCorrection(fhicl::ParameterSet
fVGroupVUV( p.get<double>("VGroupVUV") ),
fNuScoreThreshold( p.get<double>("NuScoreThreshold") ),
fFMScoreThreshold( p.get<double>("FMScoreThreshold") ),
fMinHitPE ( p.get<int>("MinHitPE") ),
fPreWindow ( p.get<double>("PreWindow") ),
fPostWindow ( p.get<double>("PostWindow") ),
fPDFraction ( p.get<double>("PDFraction") ),
fDebug( p.get<bool>("Debug", false) )
//
// More initializers here.
{
fNOpChannels = fWireReadout.NOpChannels();
// Initialize the TimeCorrectionVector PerChannel
fTimeCorrectionPerChannel.resize(fNOpChannels, 0.0); // Initialize with zero or any default value
fParticlePropagationTimePerChannel.resize(fNOpChannels, 0.0); // Initialize with zero or any default value
fPhotonPropagationTimePerChannel.resize(fNOpChannels, 0.0); // Initialize with zero or any default value

for(unsigned int opch=0; opch<fNOpChannels; opch++){
auto pdCenter = fWireReadout.OpDetGeoFromOpChannel(opch).GetCenter();
Expand Down Expand Up @@ -231,63 +237,14 @@ void sbnd::LightPropagationCorrection::produce(art::Event & e)
}
else throw art::Exception(art::errors::LogicError) << " Flash matching tool " << fFlashMatchingTool << " not supported ." << std::endl;


// Get the ophits associated to the flash
std::vector<art::Ptr<recob::OpHit>> ophitlist;
if(flashFM[0]->XCenter()<0)
{
ophitlist = flashToOpHitAssns_tpc0.at(flashFM[0].key());
_mgr = _mgr_tpc0; // Use the TPC 0 flash finder manager
}
else
{
ophitlist = flashToOpHitAssns_tpc1.at(flashFM[0].key());
_mgr = _mgr_tpc1; // Use the TPC 1 flash finder manager
}

std::vector<recob::OpHit> newOpHitList;
std::vector<recob::OpHit> oldOpHitList;
for(const auto& ophit : ophitlist) {
oldOpHitList.push_back(*ophit);
}
// Get the list of the corrected OpHits
this->CorrectOpHitTime(ophitlist, newOpHitList);
// Create the list of ophit lite to be used in the flash finder
::lightana::LiteOpHitArray_t ophits;
this->FillLiteOpHit(newOpHitList, ophits);
// Create the flash manager
auto const flash_v = _mgr.RecoFlash(ophits);
double originalFlashTime = flashFM[0]->Time();
double newFlashTime = 0.0;
for(const auto& lflash : flash_v) {
// Get Flash Barycenter
double Ycenter, Zcenter, Ywidth, Zwidth;
_flashgeo->GetFlashLocation(lflash.channel_pe, Ycenter, Zcenter, Ywidth, Zwidth);
// Get flasht0
double flasht0 = lflash.time;
// Refine t0 calculation
flasht0 = _flasht0calculator->GetFlashT0(lflash.time, GetAssociatedLiteHits(lflash, ophits));
recob::OpFlash flash(flasht0, lflash.time_err, flasht0,
( flasht0) / 1600., lflash.channel_pe,
0, 0, 1, // this are just default values
100., -1., Ycenter, Ywidth, Zcenter, Zwidth);
newFlashTime = flasht0;
sbn::CorrectedOpFlashTiming correctedOpFlashTiming;
correctedOpFlashTiming.OpFlashT0 = originalFlashTime;
correctedOpFlashTiming.NuToFLight = (Zcenter/fSpeedOfLight)/1000;
correctedOpFlashTiming.NuToFCharge = (fRecoVz/fSpeedOfLight)/1000;
correctedOpFlashTiming.OpFlashT0Corrected = newFlashTime;
correctedOpFlashTimes->emplace_back(std::move(correctedOpFlashTiming));
}

sbn::CorrectedOpFlashTiming correctedOpFlashTiming;
CorrectOpFlash(flashFM[0], correctedOpFlashTiming, flashToOpHitAssns_tpc0, flashToOpHitAssns_tpc1);
correctedOpFlashTimes->emplace_back(std::move(correctedOpFlashTiming));
art::Ptr<sbn::CorrectedOpFlashTiming> newCorrectedOpFlashTimingPtr = make_correctedopflashtime_ptr(correctedOpFlashTimes->size()-1);
newCorrectedOpFlashTimingSliceAssn->addSingle(slice, newCorrectedOpFlashTimingPtr);
newCorrectedOpFlashTimingOpFlashAssn->addSingle(flashFM[0], newCorrectedOpFlashTimingPtr);
if(fSaveCorrectionTree){
this->FillCorrectionTree(newFlashTime, *flashFM[0], oldOpHitList, newOpHitList);
}
}
if(fSaveCorrectionTree) fTree->Fill();

ResetEventVars();
e.put(std::move(correctedOpFlashTimes));
e.put(std::move(newCorrectedOpFlashTimingSliceAssn));
Expand Down Expand Up @@ -396,6 +353,8 @@ void sbnd::LightPropagationCorrection::ResetSliceInfo()
fSpacePointZ.clear();
fSpacePointIntegral.clear();
fTimeCorrectionPerChannel.assign(fNOpChannels, 0.0); // Reset the time correction vector for each channel
fParticlePropagationTimePerChannel.assign(fNOpChannels, 0.0); // Reset the particle propagation time vector for each channel
fPhotonPropagationTimePerChannel.assign(fNOpChannels, 0.0); // Reset the photon propagation time vector for each channel
fChargeBarycenterX.assign(2, 0.0);
fChargeBarycenterY.assign(2, 0.0);
fChargeBarycenterZ.assign(2, 0.0);
Expand All @@ -408,13 +367,17 @@ void sbnd::LightPropagationCorrection::ResetSliceInfo()
void sbnd::LightPropagationCorrection::GetPropagationTimeCorrectionPerChannel()
{
// Implementation
for(size_t opdet = 0; opdet < fOpDetID.size(); ++opdet) {
for(size_t opdet = 0; opdet < fOpDetID.size(); ++opdet) {
double _opDetX = fOpDetX[opdet];
double _opDetY = fOpDetY[opdet];
double _opDetZ = fOpDetZ[opdet];
float minPropTime = 999999999.;
float minPartPropTime = 999999999.;
float minLightPropTime = 999999999.;
for(size_t sp=0; sp<fSpacePointX.size(); sp++)
{
bool isInSameTPC = (fSpacePointX[sp] * _opDetX) > 0;
if(!isInSameTPC) continue; // Skip points not in the same TPC
double dx = fSpacePointX[sp] - _opDetX;
double dy = fSpacePointY[sp] - _opDetY;
double dz = fSpacePointZ[sp] - _opDetZ;
Expand All @@ -434,9 +397,15 @@ void sbnd::LightPropagationCorrection::GetPropagationTimeCorrectionPerChannel()
throw std::runtime_error("LightPropagationCorrection: unexpected pdType '" + pdType + "' for opdet " + std::to_string(opdet));
float partPropTime = std::sqrt((fSpacePointX[sp]-fRecoVx)*(fSpacePointX[sp]-fRecoVx) + (fSpacePointY[sp]-fRecoVy)*(fSpacePointY[sp]-fRecoVy) + (fSpacePointZ[sp]-fRecoVz)*(fSpacePointZ[sp]-fRecoVz))/fSpeedOfLight;
float PropTime = lightPropTime + partPropTime;
if(PropTime < minPropTime) minPropTime = PropTime;
if(PropTime < minPropTime) {
minPropTime = PropTime;
minPartPropTime = partPropTime;
minLightPropTime = lightPropTime;
}
}
fTimeCorrectionPerChannel[opdet] = -minPropTime;
fParticlePropagationTimePerChannel[opdet] = minPartPropTime;
fPhotonPropagationTimePerChannel[opdet] = minLightPropTime;
}
}

Expand Down Expand Up @@ -515,12 +484,135 @@ void sbnd::LightPropagationCorrection::FillCorrectionTree(double & newFlashTime,


::lightana::LiteOpHitArray_t sbnd::LightPropagationCorrection::GetAssociatedLiteHits(::lightana::LiteOpFlash_t lite_flash, ::lightana::LiteOpHitArray_t lite_hits_v)
{
{
::lightana::LiteOpHitArray_t flash_hits_v;

for(auto const& hitidx : lite_flash.asshit_idx) {
flash_hits_v.emplace_back(std::move(lite_hits_v.at(hitidx)));
}

return flash_hits_v;
}
}

double sbnd::LightPropagationCorrection::GetAverageParticlePropagationTime()
{
double sum = 0.0;
int n = 0;
for (size_t i=0; i<fSelectedChannelList.size(); i++) {
sum+= fParticlePropagationTimePerChannel[fSelectedChannelList[i]];
n++;
}
double average_prop_time = n ? sum / n : 0;
return average_prop_time;
}


double sbnd::LightPropagationCorrection::GetAveragePhotonPropagationTime()
{
double sum = 0.0;
int n = 0;
for (size_t i=0; i<fSelectedChannelList.size(); i++) {
sum+= fPhotonPropagationTimePerChannel[fSelectedChannelList[i]];
n++;
}
double average_prop_time = n ? sum / n : 0;
return average_prop_time;
}

void sbnd::LightPropagationCorrection::GetSelectedChannelsFlash(
double flash_time,
::lightana::LiteOpHitArray_t ophit_list)
{
std::vector< std::tuple<double, double, size_t> > selected_hits;
double pe_sum = 0.0;
fSelectedChannelList.clear();
// Fill vector with selected hits in the specified window
for (auto const& hit : ophit_list) {

if (hit.peak_time < flash_time + fPostWindow &&
hit.peak_time > flash_time - fPreWindow &&
hit.pe > fMinHitPE) {

// (PE, peak_time, channel)
selected_hits.emplace_back(hit.pe, hit.peak_time, hit.channel);
pe_sum += hit.pe;
}
}

// Sort by PE in descending order
std::sort(selected_hits.begin(), selected_hits.end(), [](auto const& a, auto const& b) {return std::get<0>(a) > std::get<0>(b);});
double pe_count = 0.0;

// Loop over selected ophits
for (size_t ix = 0; ix < selected_hits.size(); ix++) {

double pe = std::get<0>(selected_hits[ix]);
size_t channel = std::get<2>(selected_hits[ix]);

// Save channel ID
fSelectedChannelList.push_back(channel);

pe_count += pe;
if (pe_count / pe_sum > fPDFraction)
break;
}
}

void sbnd::LightPropagationCorrection::CorrectOpFlash(art::Ptr<recob::OpFlash> const& flash, sbn::CorrectedOpFlashTiming &correctedOpFlashTiming, const art::FindManyP<recob::OpHit> &flashToOpHitAssns_tpc0, const art::FindManyP<recob::OpHit> &flashToOpHitAssns_tpc1)
{
// Get the ophits associated to the flash
std::vector<art::Ptr<recob::OpHit>> ophitlist;
if(flash->XCenter()<0)
{
ophitlist = flashToOpHitAssns_tpc0.at(flash.key());
_mgr = _mgr_tpc0; // Use the TPC 0 flash finder manager
}
else
{
ophitlist = flashToOpHitAssns_tpc1.at(flash.key());
_mgr = _mgr_tpc1; // Use the TPC 1 flash finder manager
}
std::vector<recob::OpHit> newOpHitList;
std::vector<recob::OpHit> oldOpHitList;
for(const auto& ophit : ophitlist) {
oldOpHitList.push_back(*ophit);
}
// Get the list of the corrected OpHits
this->CorrectOpHitTime(ophitlist, newOpHitList);
// Create the list of ophit lite to be used in the flash finder
::lightana::LiteOpHitArray_t ophits;
this->FillLiteOpHit(newOpHitList, ophits);
// Create the flash manager
auto const flash_v = _mgr.RecoFlash(ophits);
double originalFlashTime = flash->Time();
double newFlashTime = 0.0;
double particlePropTime = 0.0;
double photonPropTime = 0.0;
for(const auto& lflash : flash_v) {
// Get Flash Barycenter
double Ycenter, Zcenter, Ywidth, Zwidth;
_flashgeo->GetFlashLocation(lflash.channel_pe, Ycenter, Zcenter, Ywidth, Zwidth);
// Get flasht0
double flasht0 = lflash.time;
// Refine t0 calculation
flasht0 = _flasht0calculator->GetFlashT0(lflash.time, GetAssociatedLiteHits(lflash, ophits));
this->GetSelectedChannelsFlash(lflash.time, GetAssociatedLiteHits(lflash, ophits));
recob::OpFlash flash(flasht0, lflash.time_err, flasht0,
( flasht0) / 1600., lflash.channel_pe,
0, 0, 1, // this are just default values
100., -1., Ycenter, Ywidth, Zcenter, Zwidth);
newFlashTime = flasht0;
particlePropTime = GetAverageParticlePropagationTime()/1000;
photonPropTime = GetAveragePhotonPropagationTime()/1000;
correctedOpFlashTiming.OpFlashT0 = originalFlashTime;
correctedOpFlashTiming.NuToFLight = (Zcenter/fSpeedOfLight)/1000;
correctedOpFlashTiming.NuToFCharge = (fRecoVz/fSpeedOfLight)/1000;
correctedOpFlashTiming.OpFlashT0Corrected = newFlashTime;
correctedOpFlashTiming.ParticlePropagationTime = particlePropTime;
correctedOpFlashTiming.PhotonPropagationTime = photonPropTime;
}

if(fSaveCorrectionTree){
this->FillCorrectionTree(newFlashTime, *flash, oldOpHitList, newOpHitList);
}
}
Loading