void check_mates(const HitList& hits1_in_ref, const HitList& hits2_in_ref, vector<pair<size_t, size_t> >& happy_mates, vector<size_t>& map1_singletons, vector<size_t>& map2_singletons) { std::set<size_t> marked; // TODO: if this shows up on the profile, replace it with a linear // time algorithm. This one is 2*n*lg(n). HitList::const_iterator last_good = hits2_in_ref.begin(); for (size_t i = 0; i < hits1_in_ref.size(); ++i) { pair<HitList::const_iterator, HitList::const_iterator> range_pair; range_pair = equal_range(last_good, hits2_in_ref.end(), hits1_in_ref[i], hit_insert_id_lt); bool found_hit = false; if (range_pair.first != range_pair.second) last_good = range_pair.first; for (HitList::const_iterator f = range_pair.first; f != range_pair.second; ++f) { if (possible_cotranscript(hits1_in_ref[i], *f)) { happy_mates.push_back(make_pair(i,f - hits2_in_ref.begin())); marked.insert(f - hits2_in_ref.begin()); found_hit = true; } } if (!found_hit) map1_singletons.push_back(i); } for (size_t i = 0; i < hits2_in_ref.size(); ++i) { if (marked.find(i) == marked.end()) { map2_singletons.push_back(i); } } }
void best_insert_mappings(uint64_t refid, ReadTable& it, /*const string& name,*/ HitList& hits1_in_ref, HitList& hits2_in_ref, BestInsertAlignmentTable& best_status_for_inserts, bool prefer_shorter_pairs) { long chucked_for_shorter_pair = 0; std::set<size_t> marked; HitList::iterator last_good = hits2_in_ref.begin(); for (size_t i = 0; i < hits1_in_ref.size(); ++i) { BowtieHit& h1 = hits1_in_ref[i]; pair<HitList::iterator, HitList::iterator> range_pair; range_pair = equal_range(last_good, hits2_in_ref.end(), h1, hit_insert_id_lt); bool found_hit = false; if (range_pair.first != range_pair.second) last_good = range_pair.first; uint32_t obs_order = it.observation_order(h1.insert_id()); for (HitList::iterator f = range_pair.first; f != range_pair.second; ++f) { BowtieHit& h2 = *f; if (h1.insert_id() == h2.insert_id()) { // max mate inner distance (genomic) int min_mate_inner_dist = inner_dist_mean - inner_dist_std_dev; if (max_mate_inner_dist == -1) { max_mate_inner_dist = inner_dist_mean + inner_dist_std_dev; } InsertAlignmentGrade s(h1, h2, min_mate_inner_dist, max_mate_inner_dist); pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; // Is the new status better than the current best one? if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } else if (!(s < current)) { if (prefer_shorter_pairs && current.num_mapped == 2) { pair<int, int> dc = pair_distances(*(insert_best.second[0].left_alignment), *(insert_best.second[0].right_alignment)); pair<int, int> ds = pair_distances(h1,h2); if (ds.second < dc.second) { chucked_for_shorter_pair += insert_best.second.size(); insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } } else { insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } } marked.insert(f - hits2_in_ref.begin()); found_hit = true; } } if (!found_hit) { pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; InsertAlignmentGrade s(h1); if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, NULL)); } else if (! (s < current)) { insert_best.second.push_back(InsertAlignment(refid, &h1, NULL)); } } } for (size_t i = 0; i < hits2_in_ref.size(); ++i) { BowtieHit& h2 = hits2_in_ref[i]; uint32_t obs_order = it.observation_order(h2.insert_id()); pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; InsertAlignmentGrade s(h2); // Did we include h2 as part of a pairing already, or is this first time // we've seen it? If so, it's a singleton. if (marked.find(i) == marked.end()) { if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, NULL, &h2)); } else if (! (s < current)) { insert_best.second.push_back(InsertAlignment(refid, NULL, &h2)); } } } fprintf(stderr, "Chucked %ld pairs for shorter pairing of same mates\n", chucked_for_shorter_pair); }
/** * R T _ B R E P _ S H O T * * Intersect a ray with a brep. * If an intersection occurs, a struct seg will be acquired * and filled in. * * Returns - * 0 MISS * >0 HIT */ int rt_brep_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead) { //TRACE1("rt_brep_shot origin:" << ON_PRINT3(rp->r_pt) << " dir:" << ON_PRINT3(rp->r_dir)); TRACE("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); vect_t invdir; struct brep_specific* bs = (struct brep_specific*)stp->st_specific; // check the hierarchy to see if we have a hit at a leaf node BBNode::IsectList inters; ON_Ray r = toXRay(rp); bs->bvh->intersectsHierarchy(r, &inters); if (inters.size() == 0) return 0; // MISS TRACE1("bboxes: " << inters.size()); // find all the hits (XXX very inefficient right now!) HitList all_hits; // record all hits MissList misses; // XXX - get rid of this stuff (for debugging) int s = 0; for (BBNode::IsectList::iterator i = inters.begin(); i != inters.end(); i++) { const SubsurfaceBBNode* sbv = dynamic_cast<SubsurfaceBBNode*>((*i).m_node); const ON_BrepFace* f = sbv->m_face; const ON_Surface* surf = f->SurfaceOf(); brep_hit* hit; pt2d_t uv = {sbv->m_u.Mid(),sbv->m_v.Mid()}; TRACE1("surface: " << s); int status = brep_intersect(sbv, f, surf, uv, r, all_hits); if (status == BREP_INTERSECT_FOUND) { TRACE("INTERSECTION: " << PT(all_hits.back().point) << all_hits.back().trimmed << ", " << all_hits.back().closeToEdge << ", " << all_hits.back().oob); } else { TRACE1("dammit"); misses.push_back(ip_t(all_hits.size()-1,status)); } s++; } HitList hits = all_hits; // sort the hits hits.sort(); int num = 0; for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { TRACE("hit " << num << ": " << PT(i->point) << " [" << VDOT(i->normal,rp->r_dir) << "] " << i->trimmed << ", " << i->closeToEdge << ", " << i->oob); ++num; } TRACE("---"); num = 0; for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { if ((i->trimmed && !i->closeToEdge) || i->oob || NEAR_ZERO(VDOT(i->normal,rp->r_dir),RT_DOT_TOL)) { // remove what we were removing earlier if (i->oob) { TRACE("\toob u: " << i->uv[0] << ", " << IVAL(i->sbv->m_u)); TRACE("\toob v: " << i->uv[1] << ", " << IVAL(i->sbv->m_v)); } i = hits.erase(i); if (i != hits.begin()) --i; continue; } TRACE("hit " << num << ": " << PT(i->point) << " [" << VDOT(i->normal,rp->r_dir) << "]"); ++num; } { // we should have "valid" points now, remove duplicates or grazes HitList::iterator last = hits.begin(); HitList::iterator i = hits.begin(); ++i; while (i != hits.end()) { if ((*i) == (*last)) { double lastDot = VDOT(last->normal,rp->r_dir); double iDot = VDOT(i->normal,rp->r_dir); if (sign(lastDot) != sign(iDot)) { // delete them both i = hits.erase(last); i = hits.erase(i); last = i; if (i != hits.end()) ++i; } else { // just delete the second i = hits.erase(i); } } else { last = i; ++i; } } } // remove "duplicate" points // HitList::iterator new_end = unique(hits.begin(), hits.end()); // hits.erase(new_end, hits.end()); if (hits.size() > 1 && (hits.size() % 2) != 0) { cerr << "WTF???" << endl; #if PLOTTING pcount++; if (pcount > -1) { point_t ray; point_t vscaled; VSCALE(vscaled,rp->r_dir,100); VADD2(ray,rp->r_pt,vscaled); COLOR_PLOT(200,200,200); LINE_PLOT(rp->r_pt,ray); } #endif num = 0; int lastSign = 0; MissList::iterator m = misses.begin(); for (HitList::iterator i = all_hits.begin(); i != all_hits.end(); ++i) { double dot = VDOT(i->normal,rp->r_dir); #if PLOTTING if (pcount > -1) { // set the color of point and normal if (i->trimmed && i->closeToEdge) { COLOR_PLOT(0,0,255); // blue is trimmed but close to edge } else if (i->trimmed) { COLOR_PLOT(255,255,0); // yellow trimmed } else if (i->oob) { COLOR_PLOT(255,0,0); // red is oob } else if (NEAR_ZERO(VDOT(i->normal,rp->r_dir),RT_DOT_TOL)) { COLOR_PLOT(0,255,255); // purple is grazing } else { COLOR_PLOT(0,255,0); // green is regular surface } // draw normal point_t v; VADD2(v,i->point,i->normal); LINE_PLOT(i->point,v); // draw intersection PT_PLOT(i->point); // draw bounding box BB_PLOT(i->sbv->m_node.m_min,i->sbv->m_node.m_max); fflush(plot_file()); } #endif // if ((num == 0 && dot > 0) || sign(dot) == lastSign) { // remove hits with "bad" normals // i = hits.erase(i); // --i; // TRACE("removed a hit!"); // continue; // } else { // lastSign = sign(dot); // } TRACE("hit " << num << ": " << ON_PRINT3(i->point) << " [" << dot << "]"); while ((m != misses.end()) && (m->first == num)) { TRACE("miss " << num << ": " << BREP_INTERSECT_GET_REASON(m->second)); ++m; } num++; } while (m != misses.end()) { TRACE("miss " << BREP_INTERSECT_GET_REASON(m->second)); ++m; } } bool hit = false; if (hits.size() > 0) { if (hits.size() % 2 == 0) { // take each pair as a segment for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { brep_hit& in = *i; i++; brep_hit& out = *i; register struct seg* segp; RT_GET_SEG(segp, ap->a_resource); segp->seg_stp = stp; VMOVE(segp->seg_in.hit_point, in.point); VMOVE(segp->seg_in.hit_normal, in.normal); segp->seg_in.hit_dist = DIST_PT_PT(rp->r_pt,in.point); segp->seg_in.hit_surfno = in.face.m_face_index; VSET(segp->seg_in.hit_vpriv,in.uv[0],in.uv[1],0.0); VMOVE(segp->seg_out.hit_point, out.point); VMOVE(segp->seg_out.hit_normal, out.normal); segp->seg_out.hit_dist = DIST_PT_PT(rp->r_pt,out.point); segp->seg_out.hit_surfno = out.face.m_face_index; VSET(segp->seg_out.hit_vpriv,out.uv[0],out.uv[1],0.0); BU_LIST_INSERT( &(seghead->l), &(segp->l) ); } hit = true; } else { TRACE2("screen xy: " << ap->a_x << "," << ap->a_y); } } return (hit) ? hits.size() : 0; // MISS }