Program Listing for File ana_showercluster.cxx

Return to documentation for file (larflow/Reco/ana/ana_showercluster.cxx)

#include <iostream>
#include <vector>
#include <set>

#include "larcv/core/DataFormat/IOManager.h"
#include "larcv/core/DataFormat/EventImage2D.h"

#include "DataFormat/storage_manager.h"
#include "DataFormat/larflowcluster.h"
#include "DataFormat/mctrack.h"
#include "DataFormat/mcshower.h"
#include "DataFormat/mctrajectory.h"
#include "DataFormat/mctruth.h"

#include "larflow/Reco/MCPixelPGraph.h"
#include "larflow/Reco/cluster_functions.h"


int main( int nargs, char** argv ) {

  std::cout << "Ana ShowerCluster" << std::endl;

  // we want to know
  // 1) which shower cluster, if any, matches best to the truth shower-trunk
  // 2) purity of that best shower cluster
  // 3) efficiency of that shower cluster
  // 4) pca-line versus shower direction
  // 5) statistics of matched clusters and false clusters

  larlite::storage_manager ioll( larlite::storage_manager::kREAD );
  ioll.add_in_filename( "../test/merged_dlreco_eLEE_sample2.root" );
  ioll.add_in_filename( "../test/larmatch_eLEE_sample2.root" );
  ioll.add_in_filename( "../test/larflow_cluster_eLEE_sample2_full.root" );
  ioll.open();

  larcv::IOManager iolcv( larcv::IOManager::kREAD, "iolcv", larcv::IOManager::kTickBackward );
  iolcv.add_in_file( "../test/merged_dlreco_eLEE_sample2.root" );
  iolcv.reverse_all_products();
  iolcv.initialize();

  int nentries_iolcv = iolcv.get_n_entries();
  int nentries_ioll  = ioll.get_entries();

  int nentries = std::min(nentries_iolcv,nentries_ioll);

  std::cout << "Num entries: " << nentries << std::endl;

  TFile* out = new TFile("out_ana_showercluster.root","recreate");

  TTree* truthmatchana = new TTree("truthmatchana","Info for best Truth-Matched Cluster");
  int entry;
  float EnuMeV;
  float EeMeV;
  int   cluster_max_truthpix;
  int   cluster_max_recopix;
  float cluster_max_truthfraction;
  float cluster_max_pixelsum[3];
  float truetrunk_pix_planeave;
  truthmatchana->Branch( "entry",  &entry,  "entry/I" );
  truthmatchana->Branch( "EnuMeV", &EnuMeV, "ENuMeV/F" );
  truthmatchana->Branch( "EeMeV",  &EeMeV,  "EeMeV/F" );
  truthmatchana->Branch( "cluster_max_recopix",       &cluster_max_recopix,       "cluster_max_recopix/I" );
  truthmatchana->Branch( "cluster_max_truthpix",      &cluster_max_truthpix,      "cluster_max_truthpix/I" );
  truthmatchana->Branch( "cluster_max_truthfraction", &cluster_max_truthfraction, "cluster_max_truthfraction/F" );
  truthmatchana->Branch( "cluster_max_pixelsum",      cluster_max_pixelsum,       "cluster_max_pixelsum[3]/F" );
  truthmatchana->Branch( "truetrunk_pix_planeave",    &truetrunk_pix_planeave,    "truetrunk_pix_planeave/F" );

  larflow::reco::MCPixelPGraph mcpg;

  for ( int ientry=0; ientry<nentries; ientry++ ) {

    std::cout << "===============" << std::endl;
    std::cout << " Entry " << ientry << std::endl;
    std::cout << "===============" << std::endl;

    entry = ientry;

    // load entry
    ioll.go_to(ientry);
    iolcv.read_entry( ientry );

    // build MC pgraph and assign image pixels to them
    mcpg.buildgraph( iolcv, ioll );
    mcpg.printGraph();

    // get reco shower clusters
    larlite::event_larflowcluster* shower_lfcluster_v
      = (larlite::event_larflowcluster*)ioll.get_data( larlite::data::kLArFlowCluster, "lfshower" );

    // get back to cluster_t objects
    std::vector< larflow::reco::cluster_t > shower_cluster_v;
    for ( auto& lfcluster : *shower_lfcluster_v ) {
      larflow::reco::cluster_t c = larflow::reco::cluster_from_larflowcluster( lfcluster );
      shower_cluster_v.emplace_back( std::move(c) );
    }

    // get ADC images
    larcv::EventImage2D* ev_adc = (larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "wire" );
    auto const& adc_v = ev_adc->Image2DArray();

    // we are after the primary electron, get it's data
    std::vector<larflow::reco::MCPixelPGraph::Node_t*> nodelist
      = mcpg.getPrimaryParticles();

    larflow::reco::MCPixelPGraph::Node_t* prim_electron = nullptr;
    for ( auto& pnode : nodelist ) {
      if ( std::abs(pnode->pid)==11 ) {
        prim_electron = pnode;
        break; // don't expect another primary
      }
    }

    if ( prim_electron==nullptr )
      continue;

    // we build a set of (tick,wire) pairs for look up reasons
    std::set< std::pair<int,int> > electron_pixels_vv[3];

    truetrunk_pix_planeave = 0.;
    int nplane_w_truth = 0;
    for ( size_t p=0; p<3; p++ ) {

      int ntruthpixels = prim_electron->pix_vv[p].size()/2;
      truetrunk_pix_planeave += (float)ntruthpixels;
      if ( ntruthpixels>0 )
        nplane_w_truth++;

      for ( int ipix=0; ipix<ntruthpixels; ipix++ ) {
        int tick = prim_electron->pix_vv[p][ 2*ipix ];
        int wire = prim_electron->pix_vv[p][ 2*ipix+1 ];
        electron_pixels_vv[p].insert( std::pair<int,int>(tick,wire) );
      }

      if ( nplane_w_truth>0 )
        truetrunk_pix_planeave /= (float)nplane_w_truth;
    }

    // get truth info for primary electron
    larlite::event_mctrack* mctrack_v
      = (larlite::event_mctrack*)ioll.get_data(larlite::data::kMCTrack,"mcreco");
    larlite::event_mcshower* mcshower_v
      = (larlite::event_mcshower*)ioll.get_data(larlite::data::kMCShower,"mcreco");
    double profE = mcshower_v->at( prim_electron->vidx ).DetProfile().E();
    double stepE = mcshower_v->at( prim_electron->vidx ).Start().E();
    std::cout << "truth shower profileE=" << profE << " MeV stepE=" << stepE << " MeV" << std::endl;
    EeMeV = profE;

    // neutrino energy
    const larlite::mctruth& mctruth
      = ((larlite::event_mctruth*)ioll.get_data(larlite::data::kMCTruth,"generator"))->front();
    float trueNuE = mctruth.GetNeutrino().Nu().Trajectory().front().E()*1000.0;
    std::cout << "truth neutrino energy= " << trueNuE << " MeV" << std::endl;
    EnuMeV = trueNuE;

    // loop over clusters, get the fraction that lie on truth pixels
    // for larflow, might make mistakes, so 2 of 3 planes must be on pixels
    std::vector<int>   truth_pixels_v(   shower_cluster_v.size(), 0 );
    std::vector<float> truth_fraction_v( shower_cluster_v.size(), 0 );

    for ( size_t i=0; i<shower_cluster_v.size(); i++ ) {
      // scan over hits
      auto const& cluster = shower_cluster_v[i];
      for ( size_t ihit=0; ihit<cluster.imgcoord_v.size(); ihit++ ) {
        const std::vector<int>& coord = cluster.imgcoord_v[ihit];
        int noverlap = 0;
        for ( size_t p=0; p<3; p++ ) {
          std::pair<int,int> tw(coord[3],coord[p]);
          if ( electron_pixels_vv[p].find( tw )!=electron_pixels_vv[p].end() ) {
            noverlap++;
          }
        }
        if (noverlap>=2 ) {
          truth_pixels_v[i]++;
          truth_fraction_v[i] += 1.0;
        }
      }
      if ( cluster.imgcoord_v.size()>0 ) {
        truth_fraction_v[i] /= (float)cluster.imgcoord_v.size();
      }
    }

    int max_cluster = -1;
    int max_pixels  = 0;
    for ( int i=0; i<truth_pixels_v.size(); i++ ) {
      if ( truth_pixels_v[i]>max_pixels ) {
        max_pixels = truth_pixels_v[i];
        max_cluster = i;
      }
    }
    if ( max_cluster>=0 ) {
      cluster_max_truthpix = max_pixels;
      cluster_max_truthfraction = truth_fraction_v[max_cluster];
      cluster_max_recopix  = (int)shower_cluster_v[max_cluster].imgcoord_v.size();
      std::vector<float> pixsum = larflow::reco::cluster_pixelsum( shower_cluster_v[max_cluster], adc_v );
      for (int i=0; i<3; i++ ) cluster_max_pixelsum[i] = pixsum[i];
    }
    else {
      cluster_max_truthpix = 0;
      cluster_max_recopix  = 0;
      cluster_max_truthfraction = 0.0;
      for (int i=0; i<3; i++ ) cluster_max_pixelsum[i] = 0.;
    }


    std::cout << "--------------------------------------------------------------------------" << std::endl;
    std::cout << "Max shower reco cluster=" << max_cluster
              << " max pixels in cluster=" << max_pixels
              << " fraction=" << truth_fraction_v[max_cluster]
              << std::endl;
    std::cout << "--------------------------------------------------------------------------" << std::endl;

    truthmatchana->Fill();

  }

  truthmatchana->Write();

  out->Close();

  return 0;

}