Program Listing for File keypoint_recoana.cxx¶
↰ Return to documentation for file (larflow/Ana/keypoint_recoana.cxx
)
#include <iostream>
#include <string>
#include "TTree.h"
#include "larcv/core/DataFormat/IOManager.h"
#include "larcv/core/DataFormat/EventPGraph.h"
#include "DataFormat/storage_manager.h"
#include "DataFormat/larflow3dhit.h"
#include "LArUtil/LArProperties.h"
#include "LArUtil/Geometry.h"
#include "ublarcvapp/MCTools/LArbysMC.h"
#include "larflow/KeyPoints/PrepKeypointData.h"
#include "larflow/Reco/KPCluster.h"
int main( int nargs, char** argv )
{
// keypoint reco analysis
// output:
// 1) ttree per event storing
// - mc event info
// - number of reco vertices near true neutrino vertex
// - number of reco vertices near true track keypoint
// - number of reco vertices that are false
// 2) if wire-cell cosmic tagger info available, ttree per event storing
// - number of reco vertices near true neutrino vertex w/ wirecell mask
// - number of reco vertices near true track keypoint w/ wirecell mask
// - number of reco vertices that are false w/ wirecell mask
// inputs
// ------
// 1) dlmerged file
// 2) keypoint reco output
std::string dlmerged_file = argv[1];
std::string kpreco_file = argv[2];
// outputs
// 1) ana tfile with ana ttree
std::string outfilename = argv[3];
// Load inputs
larcv::IOManager iocv( larcv::IOManager::kREAD, "larcv", larcv::IOManager::kTickBackward );
iocv.add_in_file( dlmerged_file );
iocv.reverse_all_products();
iocv.initialize();
larlite::storage_manager ioll( larlite::storage_manager::kREAD );
ioll.add_in_filename( dlmerged_file );
ioll.open();
TFile kpreco_tfile(kpreco_file.c_str(),"open");
TTree* kpreco_ttree = (TTree*)kpreco_tfile.Get("larflow_keypointreco");
std::vector<larflow::reco::KPCluster>* ev_kpreco = 0;
kpreco_ttree->SetBranchAddress( "kpcluster_v", &ev_kpreco );
// load outputs
TFile* out = new TFile(outfilename.c_str(),"new");
// define output tree
TTree* ev_ana = new TTree("kprecoana_event","Keypoint Reco Ana Event tree");
int run,subrun,event;
int n_reco_kp;
int n_near_true_vtx;
int n_near_true_trackend;
int n_near_true_showerstart;
int n_false_keypoint;
int n_reco_kp_wct;
int n_near_true_vtx_wct;
int n_near_true_trackend_wct;
int n_near_true_showerstart_wct;
int n_false_keypoint_wct;
float vtx_qsum[3] = { 0., 0., 0. };
float min_dist_to_vtx = 0.;
float min_dist_to_vtx_dl = 0.;
int has_good_dl_vertex = 0;
ev_ana->Branch("run",&run,"run/I");
ev_ana->Branch("subrun",&subrun,"subrun/I");
ev_ana->Branch("event",&event,"event/I");
ev_ana->Branch("n_reco_kp",&n_reco_kp,"n_reco_kp/I");
ev_ana->Branch("n_near_true_vtx",&n_near_true_vtx,"n_near_true_vtx/I");
ev_ana->Branch("n_near_true_trackend",&n_near_true_trackend,"n_near_true_trackend/I");
ev_ana->Branch("n_near_true_showerstart",&n_near_true_showerstart,"n_near_true_showerstart/I");
ev_ana->Branch("n_false_keypoint",&n_false_keypoint,"n_false_keypoint/I");
ev_ana->Branch("n_reco_kp_wct",&n_reco_kp_wct,"n_reco_kp_wct/I");
ev_ana->Branch("n_near_true_vtx_wct",&n_near_true_vtx_wct,"n_near_true_vtx_wct/I");
ev_ana->Branch("n_near_true_trackend_wct",&n_near_true_trackend_wct,"n_near_true_trackend_wct/I");
ev_ana->Branch("n_near_true_showerstart_wct",&n_near_true_showerstart_wct,"n_near_true_showerstart_wct/I");
ev_ana->Branch("n_false_keypoint_wct",&n_false_keypoint_wct,"n_false_keypoint_wct/I");
ev_ana->Branch("min_dist_to_vtx", &min_dist_to_vtx, "min_dist_to_vtx/F" );
ev_ana->Branch("min_dist_to_vtx_dl", &min_dist_to_vtx_dl, "min_dist_to_vtx_dl/F" );
ev_ana->Branch("has_good_dl_vertex", &has_good_dl_vertex, "has_good_dl_vertex/I" );
ev_ana->Branch("vtx_qsum",vtx_qsum, "vtx_qsum[3]/F" );
TTree* kp_ana = new TTree("kprecoana_keypt","Keypoint Reco Ana per True Keypoint tree");
float vtx_sce[3];
float max_score;
float max_score_dist;
int is_nu_vtx;
int n_nearby_5cm;
kp_ana->Branch("vtx_sce",vtx_sce,"vtx_sce[3]/F");
kp_ana->Branch("max_score",&max_score,"max_score/F");
kp_ana->Branch("max_score_dist",&max_score_dist,"max_score_dist/F");
kp_ana->Branch("n_nearby_5cm",&n_nearby_5cm,"n_nearby_5cm/I");
kp_ana->Branch("is_nu_vtx",&is_nu_vtx,"is_nu_vtx/I");
const float cut_off_dist = 10.0; // cm
const float cut_off_distsq = cut_off_dist*cut_off_dist;
// Keypoint Truth Data Maker
larflow::keypoints::PrepKeypointData kpdata;
ublarcvapp::mctools::LArbysMC lmc;
lmc.bindAnaVariables( ev_ana );
int nentries = iocv.get_n_entries();
for (int ientry=0; ientry<nentries; ientry++) {
// load trees
iocv.read_entry(ientry);
ioll.go_to(ientry);
kpreco_ttree->GetEntry(ientry);
// Get neutrino interaction truth
lmc.process( ioll );
float true_vtx[3] = { lmc._vtx_sce_x, lmc._vtx_sce_y, lmc._vtx_sce_z };
// truth keypoints
kpdata.process( iocv, ioll );
// wirecell cosmic pixel image
larcv::EventImage2D* ev_thrumu =
(larcv::EventImage2D*)iocv.get_data(larcv::kProductImage2D,"thrumu");
auto const& thrumu_v = ev_thrumu->Image2DArray();
// ADC images
larcv::EventImage2D* ev_adc =
(larcv::EventImage2D*)iocv.get_data(larcv::kProductImage2D,"wire");
auto const& adc_v = ev_adc->Image2DArray();
// DL Vertex
larcv::EventPGraph* ev_pgraph =
(larcv::EventPGraph*)iocv.get_data(larcv::kProductPGraph,"test");
std::cout << "[ENTRY " << ientry << "]" << std::endl;
std::cout << " number of truth keypoints: " << kpdata.getKPdata().size() << std::endl;
std::cout << " number of reco keypoints: " << ev_kpreco->size() << std::endl;
std::cout << " number of Wirecell images: " << thrumu_v.size() << std::endl;
std::cout << " true neutrino vertex: (" << true_vtx[0] << "," << true_vtx[1] << "," << true_vtx[2] << ")" << std::endl;
std::cout << " number of DL reco vertices: " << ev_pgraph->PGraphArray().size() << std::endl;
lmc.printInteractionInfo();
kpdata.printKeypoints();
n_reco_kp = (int)ev_kpreco->size();
// KP Reco loop
n_near_true_vtx = 0;
n_near_true_trackend = 0;
n_near_true_showerstart = 0;
n_false_keypoint = 0;
n_reco_kp_wct = 0;
n_near_true_vtx_wct = 0;
n_near_true_trackend_wct = 0;
n_near_true_showerstart_wct = 0;
n_false_keypoint_wct = 0;
// characterize vertex
min_dist_to_vtx = 1.0e9;
// get vertex activity
for (int p=0; p<3; p++) vtx_qsum[p] = 0.0;
if ( lmc._vtx_tick>adc_v[0].meta().min_y() && lmc._vtx_tick<adc_v[0].meta().max_y() ) {
int row = adc_v[0].meta().row( lmc._vtx_tick );
for (int p=0; p<3; p++ ) {
if ( lmc._vtx_wire[p]>=adc_v[p].meta().min_x() && lmc._vtx_wire[p]<(int)adc_v[p].meta().max_x() ) {
int col = adc_v[p].meta().col( lmc._vtx_wire[p] );
for (int dr=-3; dr<=3; dr++ ) {
int r=row+dr;
if ( r<0 || r>=(int)adc_v[p].meta().rows() ) continue;
for (int dc=-3; dc<=3; dc++) {
int c = col+dc;
if (c<0 || c>=(int)adc_v[p].meta().cols() ) continue;
if ( adc_v[p].pixel(r,c)>10.0 )
vtx_qsum[p] += adc_v[p].pixel(r,c);
}//end of col loop
}//end of row loop
}//end of if valid wire
}//end of plane loop
}//end of if valid tick
// get dl vertex info
has_good_dl_vertex = 0;
min_dist_to_vtx_dl = 1.0e9;
for ( auto const& pgraph : ev_pgraph->PGraphArray() ) {
for ( auto const& roi : pgraph.ParticleArray() ) {
float dist = 0.;
dist += ( roi.X()-true_vtx[0] )*( roi.X()-true_vtx[0] );
dist += ( roi.Y()-true_vtx[1] )*( roi.Y()-true_vtx[1] );
dist += ( roi.Z()-true_vtx[2] )*( roi.Z()-true_vtx[2] );
dist = sqrt(dist);
std::cout << "dl vtx: (" << roi.X() << "," << roi.Y() << "," << roi.Z() << ") dist2vtx=" << dist << " cm" << std::endl;
if ( min_dist_to_vtx_dl>dist ) {
min_dist_to_vtx_dl = dist;
}
}
}
if ( min_dist_to_vtx_dl<5.0 )
has_good_dl_vertex = 1;
for ( auto const& kpc : *ev_kpreco ) {
// determine if on Wirecell-tagged cosmic
// requirement: be on tagged pixel for 2/3 planes
bool iscosmic = false;
float tick = 3200 + kpc.max_pt_v[0]/larutil::LArProperties::GetME()->DriftVelocity()/0.5;
if ( tick<=thrumu_v[0].meta().min_y() || tick>=thrumu_v[0].meta().max_y() ) {
iscosmic = true;
}
else {
int row = thrumu_v[0].meta().row( tick );
int nplanes_on_wctpixel = 0;
for ( auto const& img : thrumu_v ) {
// out of image? we remove it implicitly by adding to counter
std::vector<double> dpos = { (double)kpc.max_pt_v[0],
(double)kpc.max_pt_v[1],
(double)kpc.max_pt_v[2] };
int nearestwire = larutil::Geometry::GetME()->NearestWire( dpos, img.meta().plane() );
int col = img.meta().col((float)nearestwire);
bool onpixel = false;
for (int dr=-1; dr<=1; dr++) {
int r = row+dr;
if ( r<0 || r>=(int)img.meta().rows() ) continue;
for (int dc=-1; dc<=1; dc++) {
int c = col+dc;
if ( c<0 || c>=(int)img.meta().cols() ) continue;
if ( img.pixel(r,c)>10.0 ) onpixel = true;
if ( onpixel ) break;
}
if ( onpixel ) break;
}
if ( onpixel ) nplanes_on_wctpixel++;
}
if ( nplanes_on_wctpixel>=3 ) iscosmic = true;
}
// dist to vtx
float reco_vtx_dist = 0.;
for (int i=0; i<3; i++) {
reco_vtx_dist += (kpc.max_pt_v[i]-true_vtx[i])*(kpc.max_pt_v[i]-true_vtx[i]);
}
reco_vtx_dist = sqrt(reco_vtx_dist);
if ( reco_vtx_dist < min_dist_to_vtx )
min_dist_to_vtx = reco_vtx_dist;
// loop over truth keypoints and determine if near by
int num_nearby = 0;
float min_dist = 1.0e9;
for ( auto const& kpd : kpdata.getKPdata() ) {
float dist = 0.;
for (int i=0; i<3; i++) {
dist += (kpc.max_pt_v[i]-kpd.keypt[i])*(kpc.max_pt_v[i]-kpd.keypt[i]);
}
dist = sqrt(dist);
if ( min_dist>dist )
min_dist = dist;
if ( dist>5.0 ) {
continue;
}
// is nearby
num_nearby++;
// is neutrino vertex?
float vtx_dist = 0.;
for (int i=0; i<3; i++) {
vtx_dist += (kpd.keypt[i]-true_vtx[i])*(kpd.keypt[i]-true_vtx[i]);
}
vtx_dist = sqrt(vtx_dist);
if ( vtx_dist<1.0 ) {
n_near_true_vtx++;
if ( !iscosmic ) n_near_true_vtx_wct++;
continue;
}
// is shower start?
if ( kpd.is_shower==1 ) {
n_near_true_showerstart++;
if ( !iscosmic ) n_near_true_showerstart++;
continue;
}
// is near track end
n_near_true_trackend++;
if ( !iscosmic ) n_near_true_trackend_wct++;
}//end of loop over true keypoints
//std::cout << "[reco keypoint] closest true keypoint: " << min_dist << " cm" << std::endl;
if ( num_nearby==0 ) {
n_false_keypoint++;
if ( !iscosmic ) n_false_keypoint_wct++;
}
}//end of loop over reco keypoints
std::cout << " nearby true nu vtx: " << n_near_true_vtx << " w/ wire-cell tagger: " << n_near_true_vtx_wct << std::endl;
std::cout << " nearby true shower start: " << n_near_true_showerstart << " w/ wire-cell tagger: " << n_near_true_showerstart_wct << std::endl;
std::cout << " nearby true track end: " << n_near_true_trackend << " w/ wire-cell tagger: " << n_near_true_trackend_wct << std::endl;
std::cout << " false keypoint: " << n_false_keypoint << " w/ wire-cell tagger: " << n_false_keypoint_wct << std::endl;
// for ( auto const& kpd : kpdata.getKPdata() ) {
// // for each truth keypoint, we save max triplet within certain distance
// max_score_dist = 1.0e9;
// max_score = -1.0;
// float dist = 0.;
// for ( auto const& hit : *ev_lmhit ) {
// dist = 0.;
// for (int i=0; i<3; i++) {
// dist += (hit[i]-kpd.keypt[i])*(hit[i]-kpd.keypt[i]);
// vtx_sce[i] = kpd.keypt[i];
// }
// if ( dist<cut_off_distsq ) {
// if ( hit[13]>max_score ) {
// max_score = hit[13];
// max_score_dist = sqrt(dist);
// }
// }
// }
ev_ana->Fill();
}//end of event loop
out->Write();
return 0;
}