Program Listing for File FlowContourMatch.cxx

Return to documentation for file (larflow/FlowContourMatch/FlowContourMatch.cxx)

#include "FlowContourMatch.h"

// larcv
#include "larcv/core/Base/LArCVBaseUtilFunc.h"
#include "larcv/core/Base/larcv_logger.h"
#include "larcv/core/DataFormat/ROI.h"

// ublarcvapp
#include "ublarcvapp/ContourTools/ContourShapeMeta.h"
#include "ublarcvapp/ContourTools/ContourClusterAlgo.h"
#include "ublarcvapp/UBImageMod/UBSplitDetector.h"
#include "ublarcvapp/UBImageMod/UBCropLArFlow.h"

#include "makehitsfrompixels.h"
#include "makecontourflowmatches.h"
#include "makesimpleflowhits.h"
#include "ContourFlowMatch.h"

#include "larcv/core/ROOTUtil/ROOTUtils.h"
#include "TH2D.h"

namespace larflow {

  std::vector<larlite::larflow3dhit> makeFlowHitsFromSparseCrops( const std::vector<larcv::Image2D>& adc_v,
                                                                  const std::vector<larcv::SparseImage>& flowdata,
                                                                  const float threshold,
                                                                  const std::string cropcfg,
                                                                  const larcv::msg::Level_t verbosity,
                                                                  const bool visualize )
  {

    larcv::logger log("larflow::makeFlowHitsFromSparseCrops");
    log.set(verbosity);

    //std::cout << "make pixels from images" << std::endl;
    if ( log.debug() ) log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "make pixels from images" << std::endl;

    std::vector<larlite::event_hit> hit_vv;
    for ( auto const& adc : adc_v ) {
      auto hit_v = makeHitsFromWholeImagePixels( adc, threshold );
      if ( log.debug() ) log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__)
        << "made " << hit_v.size() << " pixel hits in plane[" << adc.meta().plane() << "]" << std::endl;
      hit_vv.emplace_back( std::move(hit_v) );
    }

    ublarcvapp::ContourClusterAlgo contours;
    contours.analyzeImages( adc_v );

    if ( log.debug() ) {
      log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "ContourClusterAlgo results:" << std::endl;
      for ( size_t p=0; p<3; p++ ) {
        log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "  atomic clusters in plane[" << p << "]: "
                                                           << contours.m_plane_atomicmeta_v[p].size() << std::endl;
      }
    }

    // step: crop image
    larcv::PSet cropper_cfg = larcv::CreatePSetFromFile( cropcfg, "ubcropcfg" );
    ublarcvapp::UBSplitDetector cropper_algo;
    cropper_algo.configure( cropper_cfg.get<larcv::PSet>("UBSplitDetector") );
    std::vector<larcv::Image2D> cropped_v;
    std::vector<larcv::ROI> roi_v;
    cropper_algo.process( adc_v, cropped_v, roi_v );

    // loop over flow crops, for each crop,
    // in each crop, for each source pixel,
    //   accumulate number of flows between unique (src/tar) index pairs
    // repeat this for all flow directions
    std::vector< ContourFlowMatchDict_t > matchdict_v(2);
    int src_index[2] = { 2, 2 }; // Y, Y
    int tar_index[2] = { 0, 1 }; // U, V
    for ( int iflowdir=0; iflowdir<2; iflowdir++ ) {

      const larcv::Image2D& srcimg = adc_v.at( src_index[iflowdir] );
      const larcv::Image2D& tarimg = adc_v.at( tar_index[iflowdir] );

      // loop through flow data
      for ( size_t iflowdata=0; iflowdata<flowdata.size(); iflowdata++ ) {
        //const larcv::SparseImage& sparseimg = flowdata.at( 2*iflowdata + iflowdir );
    const larcv::SparseImage& sparseimg = flowdata.at( iflowdata );

        // find the proper cropped meta
        int cropped_index = -1;
        for ( size_t icropset=0; icropset<cropped_v.size()/3; icropset++ ) {
          const larcv::Image2D& crop_y = cropped_v.at( 3*icropset+2 );
          // do the meta's match
          if ( crop_y.meta()==sparseimg.meta_v().front() ) {
            if ( log.debug() ) {
              log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__)
                << "Meta matched between cropped_adc[" << icropset << "] "
                << "and sparse flowimage[" << iflowdata << "] "
                << std::endl;
            }
            cropped_index = (int)icropset;
            break;
          }
        }
        if ( cropped_index==-1 ) {
          for ( size_t icropset=0; icropset<cropped_v.size()/3; icropset++ ) {
            const larcv::Image2D& crop_y = cropped_v.at( 3*icropset+2 );
            log.send(larcv::msg::kDEBUG) << crop_y.meta().dump() << std::endl;
          }
          log.send( larcv::msg::kCRITICAL, __FUNCTION__, __LINE__ ) << "Could not find matching crop.\n"
                                                                    << "       sparsemeta=" << sparseimg.meta_v().front().dump()
                                                                    << std::endl;
          throw std::runtime_error("Could not find matching crop");
        }
        const larcv::Image2D& src_adc_crop = cropped_v.at( 3*cropped_index+2 );
        const larcv::Image2D& tar_adc_crop = cropped_v.at( 3*cropped_index+tar_index[iflowdir] );

    if ( log.debug() ) {
      log.send(larcv::msg::kDEBUG) << "create flowdir[" << iflowdir << "] match data for image set "
                       << cropped_index << " of " << cropped_v.size()/3 << std::endl;
    }
    createMatchData(  contours, srcimg, tarimg,
                          sparseimg.as_Image2D().at(iflowdir),
                          src_adc_crop, tar_adc_crop,
                          matchdict_v.at(iflowdir),
                          threshold, 30.0, verbosity, visualize );

    if ( log.debug() ) {
      log.send(larcv::msg::kDEBUG) << "finished flowdir[" << iflowdir << "] "
                       << "match data for image set " << cropped_index << std::endl;
    }


      }//end of flow data loop
    }//end of flow direction loop

    // make this from this compiled information
    if ( log.debug() )
      log.send(larcv::msg::kDEBUG) << "call function to make simple hits " << std::endl;

    std::vector<larlite::larflow3dhit> flowhits_v
      = makeSimpleFlowHits( adc_v, contours, matchdict_v );

    if ( log.info() )
      log.send(larcv::msg::kINFO,__FUNCTION__,__LINE__) << "Made " << flowhits_v.size() << " flowhits" << std::endl;

    return flowhits_v;
  }

  // ==============================================================================
  //  MCTRUTH FUNCTIONS
  // --------------------

  std::vector<larlite::larflow3dhit> makeTrueFlowHitsFromWholeImage( const std::vector<larcv::Image2D>& adc_v,
                                                                     const larcv::EventChStatus& chstatus,
                                                                     const std::vector<larcv::Image2D>& larflow_v,
                                                                     const float threshold,
                                                                     const std::string cropcfg,
                                                                     const larcv::msg::Level_t verbosity,
                                                                     const bool visualize )
  {

    larcv::logger log("larflow::makeTrueFlowHitsFromWholeImage");
    log.set(verbosity);

    //std::cout << "make pixels from images" << std::endl;
    if ( log.debug() ) log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "make true flow pixels from whole images" << std::endl;

    std::vector<larlite::event_hit> hit_vv;
    for ( auto const& adc : adc_v ) {
      auto hit_v = makeHitsFromWholeImagePixels( adc, threshold );
      if ( log.debug() ) {
        log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__)
          << "made " << hit_v.size() << " pixel hits in plane[" << adc.meta().plane() << "]" << std::endl;
      }
      hit_vv.emplace_back( std::move(hit_v) );
    }

    ublarcvapp::ContourClusterAlgo contours;
    contours.analyzeImages( adc_v );

    if ( log.debug() ) {
      log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "ContourClusterAlgo results:" << std::endl;
      for ( size_t p=0; p<3; p++ ) {
        log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__) << "  atomic clusters in plane[" << p << "]: "
                                                         << contours.m_plane_atomicmeta_v[p].size() << std::endl;
      }
    }

    // step: splitter and cropper
    larcv::PSet cropper_cfg = larcv::CreatePSetFromFile( cropcfg, "ubcropcfg" );

    ublarcvapp::UBSplitDetector split_algo;
    split_algo.configure( cropper_cfg.get<larcv::PSet>("UBSplitDetector") );

    ublarcvapp::UBCropLArFlow   crop_algo;
    crop_algo.configure(  cropper_cfg.get<larcv::PSet>("UBCropLArFlow") );

    // run splitter
    std::vector<larcv::Image2D> cropped_v;
    std::vector<larcv::ROI> roi_v;
    split_algo.process( adc_v, cropped_v, roi_v );

    // run larflow cropper
    std::vector<larcv::Image2D> cropped_flow_v;
    std::vector<float> threshold_v( threshold, 3 );
    for ( auto const& roi : roi_v ) {
      std::vector<larcv::Image2D> crop_from_roi_v;
      crop_algo.make_cropped_flow_images( 2, roi, adc_v,
                                          chstatus, larflow_v, threshold_v,
                                          crop_from_roi_v );
      for ( auto& img : crop_from_roi_v ) {
        cropped_flow_v.emplace_back( std::move(img) );
      }
    }

    // check crop alignment
    if ( log.debug() )
      log.send( larcv::msg::kDEBUG,__FUNCTION__,__LINE__)
        << " ncropped=" << cropped_v.size() << " nflow=" << cropped_flow_v.size() << std::endl;

    if ( cropped_flow_v.size()/2!=cropped_v.size()/3 ) {
      log.send( larcv::msg::kCRITICAL,__FUNCTION__,__LINE__ )
        << "number of flow and ADC crops are inconsistent" << std::endl;
      throw std::runtime_error("number of flow and ADC crops are inconsistent");
    }

    // loop over flow crops, for each crop,
    // in each crop, for each source pixel,
    //   accumulate number of flows between unique (src/tar) index pairs
    // repeat this for all flow directions
    std::vector< ContourFlowMatchDict_t > matchdict_v(2);
    int src_index[2] = { 2, 2 }; // Y, Y
    int tar_index[2] = { 0, 1 }; // U, V
    for ( int iflowdir=0; iflowdir<2; iflowdir++ ) {

      const larcv::Image2D& srcimg = adc_v.at( src_index[iflowdir] );
      const larcv::Image2D& tarimg = adc_v.at( tar_index[iflowdir] );

      // loop through flow data
      for ( size_t iflowdata=0; iflowdata<cropped_flow_v.size()/2; iflowdata++ ) {
        const larcv::Image2D& truthflow = cropped_flow_v.at( 2*iflowdata + iflowdir );

        // find the proper cropped meta
        int cropped_index = -1;
        for ( size_t icropset=0; icropset<cropped_v.size()/3; icropset++ ) {
          const larcv::Image2D& crop_y = cropped_v.at( 3*icropset+2 );
          // do the meta's match
          if ( crop_y.meta()==truthflow.meta() ) {
            if ( log.debug() ) {
              log.send(larcv::msg::kDEBUG,__FUNCTION__,__LINE__)
                << "Meta matched between cropped_adc[" << icropset << "] "
                << "and sparse flowimage[" << iflowdata << "] "
                << std::endl;
            }
            cropped_index = (int)icropset;
            break;
          }
        }
        if ( cropped_index==-1 ) {
          for ( size_t icropset=0; icropset<cropped_v.size()/3; icropset++ ) {
            const larcv::Image2D& crop_y = cropped_v.at( 3*icropset+2 );
            log.send(larcv::msg::kDEBUG) << crop_y.meta().dump() << std::endl;
          }
          log.send( larcv::msg::kCRITICAL, __FUNCTION__, __LINE__ ) << "Could not find matching crop.\n"
                                                                    << "       truthmeta=" << truthflow.meta().dump()
                                                                    << std::endl;
          throw std::runtime_error("Could not find matching crop");
        }
        const larcv::Image2D& src_adc_crop = cropped_v.at( 3*cropped_index+2 );
        const larcv::Image2D& tar_adc_crop = cropped_v.at( 3*cropped_index+tar_index[iflowdir] );

        createMatchData(  contours, srcimg, tarimg,
                          truthflow,
                          src_adc_crop, tar_adc_crop,
                          matchdict_v.at(iflowdir),
                          threshold, 30.0, verbosity, visualize );


      }//end of flow data loop
    }//end of flow direction loop

    // make this from this compiled information
    std::vector<larlite::larflow3dhit> flowhits_v
      = makeSimpleFlowHits( adc_v, contours, matchdict_v );

    if ( log.info() ) log.send(larcv::msg::kINFO,__FUNCTION__,__LINE__) << "Made " << flowhits_v.size() << " flowhits" << std::endl;
    return flowhits_v;
  }

  // same as above, but with EventChStatus pointer, better for python?
}