Program Listing for File PrepAffinityField.cxx¶
↰ Return to documentation for file (larflow/KeyPoints/PrepAffinityField.cxx
)
#include "PrepAffinityField.h"
#include "LArUtil/Geometry.h"
#include "LArUtil/LArProperties.h"
#include "larflow/Reco/geofuncs.h"
namespace larflow {
namespace keypoints {
PrepAffinityField::PrepAffinityField()
: larcv::larcv_base("PrepAffinityField")
{
psce = new larutil::SpaceChargeMicroBooNE;
}
PrepAffinityField::~PrepAffinityField()
{
delete psce;
}
void PrepAffinityField::process( larcv::IOManager& iolcv,
larlite::storage_manager& ioll,
const larflow::prep::PrepMatchTriplets& match_proposals )
{
larcv::EventImage2D* ev_instance =
(larcv::EventImage2D*)iolcv.get_data( larcv::kProductImage2D, "instance" );
larlite::event_mctrack* ev_mctrack =
(larlite::event_mctrack*)ioll.get_data( larlite::data::kMCTrack, "mcreco" );
larlite::event_mcshower* ev_mcshower =
(larlite::event_mcshower*)ioll.get_data( larlite::data::kMCShower, "mcreco" );
_match_labels_v.clear();
_match_labels_v.reserve( match_proposals._triplet_v.size() );
std::cout << "Make labels for " << match_proposals._triplet_v.size() << " triplet proposals" << std::endl;
std::cout << " plane[" << 0 <<"] pixels: " << match_proposals._sparseimg_vv[0].size() << std::endl;
std::cout << " plane[" << 1 <<"] pixels: " << match_proposals._sparseimg_vv[1].size() << std::endl;
std::cout << " plane[" << 2 <<"] pixels: " << match_proposals._sparseimg_vv[2].size() << std::endl;
for ( size_t itriplet=0; itriplet<match_proposals._triplet_v.size(); itriplet++ ) {
auto const& triplet = match_proposals._triplet_v.at(itriplet);
int true_triplet = match_proposals._truth_v[itriplet];
const std::vector<float>& spacepoint = match_proposals._pos_v[itriplet];
// std::cout << "(" << itriplet << ") [" << triplet[0] << "," << triplet[1] << "," << triplet[2] << "," << triplet[3] << "] "
// << " true=" << true_triplet << std::endl;
std::vector<float> label_v;
float weight = 0.;
if ( true_triplet==1 ) {
std::vector< std::vector<int> > pixlist_v(ev_instance->Image2DArray().size());
for (size_t p=0; p<3; p++) {
int row = match_proposals._sparseimg_vv[p].at( triplet[p] ).row;
int col = match_proposals._sparseimg_vv[p].at( triplet[p] ).col;
pixlist_v[p] = std::vector<int>( { row, col } );
}
_determine_triplet_labels( pixlist_v,
spacepoint,
ev_instance->Image2DArray(),
*ev_mctrack,
*ev_mcshower,
label_v, weight );
}
_match_labels_v.push_back( label_v );
}
}
void PrepAffinityField::_determine_triplet_labels( const std::vector< std::vector<int> >& pixlist_v,
const std::vector<float>& spacepoint_v,
const std::vector< larcv::Image2D >& instance_v,
const larlite::event_mctrack& ev_mctrack_v,
const larlite::event_mcshower& ev_mcshower_v,
std::vector<float>& label_v,
float& weight )
{
weight = 0.0;
// [0-2]: 3D direction
// [3-8]: 3 planes x 2D direction
// [9]: instance id
std::map< int, int > instance_counts;
for ( size_t p=0; p<pixlist_v.size(); p++ ) {
//std::cout << "pixel[plane " << p << "] (" << pixlist_v[p][0] << "," << pixlist_v[p][1] << ")" << std::endl;
int instance_id = (int)instance_v[p].pixel( pixlist_v[p][0], pixlist_v[p][1] );
//std::cout << " instanceid=" << instance_id << std::endl;
if ( instance_id<=0 )
continue;
auto it = instance_counts.find(instance_id);
if ( it==instance_counts.end() ) {
instance_counts[instance_id] = 0;
it = instance_counts.find(instance_id);
}
it->second += 1;
}
int max_id = -1;
int max_count = 0;
for ( auto it=instance_counts.begin(); it!=instance_counts.end(); it++ ) {
if ( it->second>max_count ) {
max_count = it->second;
max_id = it->first;
}
}
if ( max_id<=0 || max_count==0 ) {
return;
}
//std::cout << "max track-id counts: " << max_id << " counts=" << max_count << std::endl;
int is_track = 0;
int idx = -1;
for ( int i=0; i<(int)ev_mctrack_v.size(); i++ ) {
if ( (int)ev_mctrack_v[i].TrackID()==max_id ) {
is_track = 1;
idx = i;
break;
}
}
if ( is_track<1 ) {
for (int i=0; i<(int)ev_mcshower_v.size(); i++ ) {
if ( (int)ev_mcshower_v[i].TrackID()==max_id ) {
is_track = 0;
idx = i;
}
}
}
if ( idx<0 ) {
return;
}
label_v.resize(10,0.0);
for (int i=0; i<10; i++) label_v[i] = 0.;
label_v[9] = (float)max_id;
std::vector<double> dspacepoint = { (double)spacepoint_v[0],
(double)spacepoint_v[1],
(double)spacepoint_v[2] };
if ( is_track==1 ) {
_get_track_direction( ev_mctrack_v[idx], dspacepoint, instance_v, label_v, weight );
}
else {
_get_shower_direction( ev_mcshower_v[idx], dspacepoint, instance_v, label_v, weight );
}
return;
}
bool PrepAffinityField::_get_track_direction( const larlite::mctrack& track,
const std::vector<double>& pt,
const std::vector<larcv::Image2D>& img_v,
std::vector<float>& label_v,
float& weight )
{
int nsteps = track.size();
if ( nsteps==0 ) {
label_v.clear();
return false;
}
std::vector<double> start(3,0);
std::vector<double> end(3,0);
std::vector<double> stepdir(3,0);
double steplen = 0.;
int best_step = -1;
double best_step_r = -1;
std::vector<double> best_stepdir(3,0);
std::vector<double> best_start(3,0);
std::vector<double> best_end(3,0);
//std::cout << " track size: " << nsteps << std::endl;
// set start
for (int i=0; i<3; i++ ) start[i] = track.front().Position()[i];
std::vector<double> offsets = psce->GetPosOffsets( (double)start[0], (double)start[1], (double)start[2] );
start[0] -= offsets[0] + 0.7;
start[1] += offsets[1];
start[2] += offsets[2];
for (int istep=0; istep+1<nsteps; istep++) {
// we get the end point, apply the space charge effect
for (int i=0; i<3; i++ ) end[i] = track[istep+1].Position()[i];
offsets = psce->GetPosOffsets( (double)end[0], (double)end[1], (double)end[2] );
end[0] -= offsets[0] + 0.7;
end[1] += offsets[1];
end[2] += offsets[2];
// std::cout << "step[" << istep << "] "
// << "start=(" << start[0] << "," << start[1] << "," << start[2] << ") -> "
// << "end=(" << end[0] << "," << end[1] << "," << end[2] << ")"
// << std::endl;
steplen = 0.;
for (int i=0; i<3; i++ ) {
stepdir[i] = (end[i]-start[i]);
steplen += stepdir[i]*stepdir[i];
}
if ( steplen>0 ) {
steplen = sqrt(steplen);
for (int i=0; i<3; i++ )
stepdir[i] /= steplen;
}
if ( steplen>0 ) {
double projs = larflow::reco::pointRayProjection<double>( start, stepdir, pt );
if ( projs>0 && projs<steplen ) {
double r = larflow::reco::pointLineDistance<double>( start, end, pt );
if ( best_step==-1 || best_step_r>r ) {
best_step = istep;
best_step_r = r;
best_stepdir = stepdir;
best_start = start;
best_end = end;
}
}
}
// replace the starting step
start = end;
}
if ( best_step==-1 ) {
// no label generated
label_v.clear();
return false;
}
// copy 3d direction
for (int i=0; i<3; i++ ) {
label_v[i] = best_stepdir[i];
}
// calculate 2d projected direction, by projecting into image, making direction
// should use plane directions to do this, but projection into plane is the dumb thing to do for now
float start_tick = 3200 + best_start[0]/larutil::LArProperties::GetME()->DriftVelocity()/0.5;
float end_tick = 3200 + best_end[0]/larutil::LArProperties::GetME()->DriftVelocity()/0.5;
float row_dir = (end_tick-start_tick)/img_v.front().meta().pixel_height();
for (size_t p=0; p<3; p++ ) {
float wire_start = larutil::Geometry::GetME()->WireCoordinate( best_start, p );
float wire_end = larutil::Geometry::GetME()->WireCoordinate( best_end, p );
float col_dir = wire_end-wire_start;
float len2d = 0.;
len2d = row_dir*row_dir + col_dir*col_dir;
len2d = sqrt(len2d);
if ( len2d>0.0 ) {
label_v[ 3+2*p ] = row_dir/len2d;
label_v[ 3+2*p+1 ] = col_dir/len2d;
}
}
return true;
}
bool PrepAffinityField::_get_shower_direction( const larlite::mcshower& shower,
const std::vector<double>& pt,
const std::vector<larcv::Image2D>& img_v,
std::vector<float>& label_v,
float& weight )
{
// use det profile direction for 3D label
float len = 0.;
for (int i=0; i<3; i++) {
label_v[i] = shower.DetProfile().Momentum()[i];
len += label_v[i]*label_v[i];
}
len = sqrt(len);
if (len==0) {
label_v.clear();
return false;
}
for (int i=0; i<3; i++) label_v[i] /= len;
// make step
std::vector<double> start(3,0);
std::vector<double> end(3,0);
for (int i=0; i<3; i++) {
end[i] = start[i] + 1.0*label_v[i];
}
// sce correct step
std::vector<double> offset_start = psce->GetPosOffsets( start[0], start[1], start[2] );
std::vector<double> offset_end = psce->GetPosOffsets( end[0], end[1], end[2] );
start[0] = start[0] - offset_start[0] + 0.7;
start[1] = start[1] + offset_start[1];
start[2] = start[2] + offset_start[2];
end[0] = end[0] - offset_end[0] + 0.7;
end[1] = end[1] + offset_end[1];
end[2] = end[2] + offset_end[2];
// calculate the final direction
len = 0.;
for (int i=0; i<3; i++ ) {
label_v[i] = end[i]-start[i];
len += label_v[i]*label_v[i];
}
len = sqrt(len);
if ( len>0 ) {
for (int i=0; i<3; i++)
label_v[i] /= len;
}
// calculate 2d projected direction, by projecting into image, making direction
// should use plane directions to do this, but projection into plane is the dumb thing to do for now
float start_tick = 3200 + start[0]/larutil::LArProperties::GetME()->DriftVelocity()/0.5;
float end_tick = 3200 + end[0]/larutil::LArProperties::GetME()->DriftVelocity()/0.5;
float row_dir = (end_tick-start_tick)/img_v.front().meta().pixel_height();
for (size_t p=0; p<3; p++ ) {
float wire_start = larutil::Geometry::GetME()->WireCoordinate( start, p );
float wire_end = larutil::Geometry::GetME()->WireCoordinate( end, p );
float col_dir = wire_end-wire_start;
float len2d = 0.;
len2d = row_dir*row_dir + col_dir*col_dir;
len2d = sqrt(len2d);
if ( len2d>0.0 ) {
label_v[ 3+2*p ] = row_dir/len2d;
label_v[ 3+2*p+1 ] = col_dir/len2d;
}
}
return true;
}
void PrepAffinityField::defineAnaTree()
{
_label_tree = new TTree("AffinityFieldTree", "Affinity Field Label Tree");
_label_tree->Branch( "run", &_run, "run/I" );
_label_tree->Branch( "subrun", &_subrun, "subrun/I" );
_label_tree->Branch( "event", &_event, "event/I" );
_label_tree->Branch( "label_v", &_match_labels_v );
}
void PrepAffinityField::fillAnaTree()
{
if (_label_tree) _label_tree->Fill();
}
void PrepAffinityField::writeAnaTree()
{
if ( _label_tree ) _label_tree->Write();
}
}
}