.. _program_listing_file_larflow_Reco_cluster_functions.cxx: Program Listing for File cluster_functions.cxx ============================================== |exhale_lsh| :ref:`Return to documentation for file ` (``larflow/Reco/cluster_functions.cxx``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "cluster_functions.h" #include #include "ublarcvapp/dbscan/DBScan.h" #include "ublarcvapp/dbscan/sDBScan.h" #include "ublarcvapp/ContourTools/ContourClusterAlgo.h" #include namespace larflow { namespace reco { ClusterFunctions::ClusterFunctions() {} void cluster_larflow3dhits( const std::vector& hit_v, std::vector< cluster_t >& cluster_v, const float maxdist, const int minsize, const int maxkd ) { // convert points into list of floats std::vector< std::vector > points_v; points_v.reserve( hit_v.size() ); for ( auto const& lfhit : hit_v ) { std::vector hit = { (float)lfhit[0], (float)lfhit[1], (float)lfhit[2] }; points_v.push_back( hit ); } clock_t start = clock(); std::vector< ublarcvapp::dbscan::dbCluster > dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( maxdist, minsize, maxkd, points_v ); for (int ic=0; ic<(int)dbcluster_v.size()-1;ic++) { // skip the last cluster, which are noise points auto const& cluster = dbcluster_v[ic]; cluster_t c; c.points_v.reserve(cluster.size()); c.imgcoord_v.reserve(cluster.size()); c.hitidx_v.reserve(cluster.size()); for ( auto const& hitidx : cluster ) { // store 3d position and 2D image coordinates c.points_v.push_back( points_v.at(hitidx) ); std::vector coord(4,0); coord[3] = hit_v[hitidx].tick; coord[0] = (int)hit_v[hitidx].targetwire[0]; // U-plane coord[1] = (int)hit_v[hitidx].targetwire[1]; // V-plane coord[2] = (int)hit_v[hitidx].srcwire; c.imgcoord_v.push_back( coord ); c.hitidx_v.push_back(hitidx); } cluster_v.emplace_back(std::move(c)); } clock_t end = clock(); double elapsed = double(end-start)/CLOCKS_PER_SEC; std::cout << "[cluster_larflow3dhit] made clusters: " << dbcluster_v.size() << " elpased=" << elapsed << " secs" << std::endl; } void cluster_spacepoint_v( const std::vector< std::vector >& points_v, std::vector< cluster_t >& cluster_v, const float maxdist, const int minsize, const int maxkd ) { clock_t start = clock(); std::vector< ublarcvapp::dbscan::dbCluster > dbcluster_v = ublarcvapp::dbscan::DBScan::makeCluster3f( maxdist, minsize, maxkd, points_v ); for (int ic=0; ic<(int)dbcluster_v.size()-1;ic++) { // skip the last cluster, which are noise points auto const& cluster = dbcluster_v[ic]; cluster_t c; c.points_v.reserve(cluster.size()); //c.imgcoord_v.reserve(cluster.size()); c.hitidx_v.reserve(cluster.size()); for ( auto const& hitidx : cluster ) { // store 3d position and 2D image coordinates c.points_v.push_back( points_v.at(hitidx) ); c.hitidx_v.push_back(hitidx); } cluster_v.emplace_back(std::move(c)); } clock_t end = clock(); double elapsed = double(end-start)/CLOCKS_PER_SEC; std::cout << "[cluster_spacepoint] made clusters: " << dbcluster_v.size() << " elpased=" << elapsed << " secs" << std::endl; } void cluster_sdbscan_larflow3dhits( const std::vector& hit_v, std::vector< cluster_t >& cluster_v, const float maxdist, const int minsize, const int maxkd ) { clock_t start = clock(); // convert points into list of floats std::vector< std::vector > points_v; points_v.reserve( hit_v.size() ); for ( auto const& lfhit : hit_v ) { std::vector hit = { lfhit[0], lfhit[1], lfhit[2] }; points_v.push_back( hit ); } auto sdbscan = ublarcvapp::dbscan::SDBSCAN< std::vector, float >(); sdbscan.Run( &points_v, 3, maxdist, minsize ); auto noise = sdbscan.Noise; auto dbcluster_v = sdbscan.Clusters; for (int ic=0; ic<(int)dbcluster_v.size();ic++) { // skip the last cluster, which are noise points auto const& cluster = dbcluster_v[ic]; cluster_t c; c.points_v.reserve(cluster.size()); c.imgcoord_v.reserve(cluster.size()); c.hitidx_v.reserve(cluster.size()); for ( auto const& hitidx : cluster ) { // store 3d position and 2D image coordinates c.points_v.push_back( points_v.at(hitidx) ); std::vector coord(4,0); coord[3] = hit_v[hitidx].tick; coord[0] = (int)hit_v[hitidx].targetwire[0]; // U-plane coord[1] = (int)hit_v[hitidx].targetwire[1]; // V-plane coord[2] = (int)hit_v[hitidx].targetwire[2]; // Y-plane c.imgcoord_v.push_back( coord ); c.hitidx_v.push_back(hitidx); } cluster_v.emplace_back(std::move(c)); } clock_t end = clock(); double elapsed = double(end-start)/CLOCKS_PER_SEC; std::cout << "[cluster_simple_larflow3dhits] made clusters: " << dbcluster_v.size() << " elpased=" << elapsed << " secs" << std::endl; } void cluster_sdbscan_spacepoints( const std::vector< std::vector >& hit_v, std::vector< cluster_t >& cluster_v, const float maxdist, const int minsize, const int maxkd ) { clock_t start = clock(); // convert points into list of floats std::vector< std::vector > points_v; points_v.reserve( hit_v.size() ); for ( auto const& lfhit : hit_v ) { std::vector hit = { lfhit[0], lfhit[1], lfhit[2] }; points_v.push_back( hit ); } auto sdbscan = ublarcvapp::dbscan::SDBSCAN< std::vector, float >(); sdbscan.Run( &points_v, 3, maxdist, minsize ); auto noise = sdbscan.Noise; auto dbcluster_v = sdbscan.Clusters; for (int ic=0; ic<(int)dbcluster_v.size();ic++) { // skip the last cluster, which are noise points auto const& cluster = dbcluster_v[ic]; cluster_t c; c.points_v.reserve(cluster.size()); c.imgcoord_v.reserve(cluster.size()); c.hitidx_v.reserve(cluster.size()); for ( auto const& hitidx : cluster ) { // store 3d position and 2D image coordinates c.points_v.push_back( points_v.at(hitidx) ); c.hitidx_v.push_back(hitidx); } cluster_v.emplace_back(std::move(c)); } clock_t end = clock(); double elapsed = double(end-start)/CLOCKS_PER_SEC; std::cout << "[cluster_sdbscan_spacepoints] made clusters: " << dbcluster_v.size() << " elpased=" << elapsed << " secs" << std::endl; } void cluster_pca( cluster_t& cluster ) { //std::cout << "[cluster_pca]" << std::endl; cluster.bbox_v.resize(3); for (size_t i=0; i<3; i++ ) { cluster.bbox_v[i].resize(2,0); cluster.bbox_v[i][0] = 1.0e9; // initial min value cluster.bbox_v[i][1] = -1.0e9; // initial max value } std::vector< Eigen::Vector3f > eigen_v; eigen_v.reserve( cluster.points_v.size() ); for ( auto const& hit : cluster.points_v ) { // store values for PCA eigen_v.push_back( Eigen::Vector3f( hit[0], hit[1], hit[2] ) ); // also determine axis-aligned bounding box values for (int i=0; i<3; i++ ) { if ( hit[i]cluster.bbox_v[i][1] ) cluster.bbox_v[i][1] = hit[i]; } } cilantro::PrincipalComponentAnalysis3f pca( eigen_v ); cluster.pca_center.resize(3,0); cluster.pca_eigenvalues.resize(3,0); cluster.pca_axis_v.clear(); for (int i=0; i<3; i++) { cluster.pca_center[i] = pca.getDataMean()(i); cluster.pca_eigenvalues[i] = pca.getEigenValues()(i); std::vector e_v = { pca.getEigenVectors()(0,i), pca.getEigenVectors()(1,i), pca.getEigenVectors()(2,i) }; cluster.pca_axis_v.push_back( e_v ); } // we provide a way to order the points struct pca_coord { int idx; float s; bool operator<( const pca_coord& rhs ) const { if ( s0 ) { lenpc = sqrt(lenpc); for ( int i=0; i<3; i++ ) cluster.pca_axis_v[ipca][i] /= lenpc; } } std::vector< pca_coord > ordered_v; ordered_v.reserve( cluster.points_v.size() ); for ( size_t idx=0; idx d3(3); for (int i=0; i<3; i++ ) { d3[i] = cluster.pca_ends_v[1][i] - cluster.pca_ends_v[0][i]; len3 += d3[i]*d3[i]; } len3 = sqrt(len3); cluster.pca_len = len3; // define radius of each point to the pca-axis float max_r = 0.; float ave_r2 = 0.; cluster.pca_radius_v.resize( ordered_v.size(), 0 ); for ( size_t i=0; i& pt = cluster.points_v[ ordered_v[i].idx ]; std::vector d1(3); std::vector d2(3); float len1 = 0.; for (int i=0; i<3; i++ ) { d1[i] = pt[i] - cluster.pca_ends_v[0][i]; d2[i] = pt[i] - cluster.pca_ends_v[1][i]; len1 += d1[i]*d1[i]; } len1 = sqrt(len1); if ( len3<1.0e-4 ) { cluster.pca_radius_v[i] = len1; } else { // cross-product std::vector d1xd2(3); d1xd2[0] = d1[1]*d2[2] - d1[2]*d2[1]; d1xd2[1] = -d1[0]*d2[2] + d1[2]*d2[0]; d1xd2[2] = d1[0]*d2[1] - d1[1]*d2[0]; float len1x2 = 0.; for ( int i=0; i<3; i++ ) { len1x2 += d1xd2[i]*d1xd2[i]; } len1x2 = sqrt(len1x2); cluster.pca_radius_v[i] = len1x2/len3; // distance of point from PCA-axis } ave_r2 += cluster.pca_radius_v[i]*cluster.pca_radius_v[i]; if ( max_r < cluster.pca_radius_v[i] ) max_r = cluster.pca_radius_v[i]; }//end of loop over ordered points ave_r2 = sqrt( ave_r2/cluster.pca_radius_v.size() ); cluster.pca_max_r = max_r; cluster.pca_ave_r2 = ave_r2; } void cluster_runpca( std::vector& cluster_v ) { clock_t start = clock(); for ( auto& cluster : cluster_v ) { cluster_pca( cluster ); } clock_t end = clock(); double elapsed = double(end-start)/CLOCKS_PER_SEC; std::cout << "[ cluster_runpca ] elapsed=" << elapsed << " secs" << std::endl; } void cluster_dump2jsonfile( const std::vector& cluster_v, std::string outfilename ) { nlohmann::json j; std::vector< nlohmann::json > jcluster_v; j["clusters"] = jcluster_v; for ( auto const& cluster : cluster_v ) { //std::cout << "cluster: nhits=" << cluster.points_v.size() << std::endl; nlohmann::json jcluster = cluster_json(cluster); j["clusters"].emplace_back( std::move(jcluster) ); } std::ofstream o(outfilename.c_str()); j >> o; o.close(); } nlohmann::json cluster_json( const cluster_t& cluster ) { nlohmann::json jcluster; jcluster["hits"] = cluster.points_v; // save start, center, end of pca to make line std::vector< std::vector > pca_points(3); for (int i=0; i<3; i++ ) pca_points[i].resize(3,0); for (int i=0; i<3; i++ ) { pca_points[0][i] = cluster.pca_ends_v[0][i];// - 5.0*cluster.pca_axis_v[0][i]; pca_points[1][i] = cluster.pca_center[i]; pca_points[2][i] = cluster.pca_ends_v[1][i];// + 5.0*cluster.pca_axis_v[0][i]; } jcluster["pca"] = pca_points; return jcluster; } void cluster_splitbytrackshower( const std::vector& hit_v, const std::vector& ssnettrack_image_v, std::vector& track_hit_v, std::vector& shower_hit_v, float min_larmatch_score ) { clock_t begin = clock(); track_hit_v.clear(); shower_hit_v.clear(); track_hit_v.reserve( hit_v.size() ); shower_hit_v.reserve( hit_v.size() ); std::vector< const larcv::ImageMeta* > meta_v( ssnettrack_image_v.size(),0); for ( size_t p=0; p& clust2d_images_v ) { // zero the images for ( auto& img : clust2d_images_v ) img.paint(0.0); for ( auto const& imgcoord : cluster.imgcoord_v ) { for ( auto& img : clust2d_images_v ) { img.set_pixel( img.meta().row( imgcoord[3], __FILE__, __LINE__ ), img.meta().col( imgcoord[img.meta().plane()], __FILE__, __LINE__ ), 50.0 /* dummy value */ ); } } } void cluster_getcontours( std::vector& clust2d_images_v ) { ublarcvapp::ContourClusterAlgo contour_algo; contour_algo.analyzeImages( clust2d_images_v, 10.0, 2, 5, 10, 10, 2 ); // contours made. now what. for ( size_t p=0; p<3; p++ ) { int ncontours = contour_algo.m_plane_atomics_v[p].size(); std::cout << "[cluster_getcontours] ncontours plane[" << p << "] = " << ncontours << std::endl; for (int ictr=0; ictr