-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathhandle.cpp
More file actions
133 lines (109 loc) · 4.76 KB
/
handle.cpp
File metadata and controls
133 lines (109 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "handlegraph/handle_graph.hpp"
#include "handlegraph/path_handle_graph.hpp"
#include "handlegraph/util.hpp"
#include <vector>
#include <limits>
/** \file handle.cpp
* Implement handle graph utility methods, oprtators, and default implementations.
*/
namespace handlegraph {
size_t HandleGraph::get_degree(const handle_t& handle, bool go_left) const {
size_t count = 0;
follow_edges(handle, go_left, [&](const handle_t& ignored) {
// Just manually count every edge we get by looking at the handle in that orientation
count++;
});
return count;
}
handle_t HandleGraph::forward(const handle_t& handle) const {
return this->get_is_reverse(handle) ? this->flip(handle) : handle;
}
std::pair<handle_t, handle_t> HandleGraph::edge_handle(const handle_t& left, const handle_t& right) const {
// The degeneracy is between any pair and a pair of the same nodes but reversed in order and orientation.
// We compare those two pairs and construct the smaller one.
auto flipped_right = this->flip(right);
if (as_integer(left) > as_integer(flipped_right)) {
// The other orientation would be smaller.
return std::make_pair(flipped_right, this->flip(left));
} else if(as_integer(left) == as_integer(flipped_right)) {
// Our left and the flipped pair's left would be equal.
auto flipped_left = this->flip(left);
if (as_integer(right) > as_integer(flipped_left)) {
// And our right is too big, so flip.
return std::make_pair(flipped_right, flipped_left);
} else {
// No difference or we're smaller.
return std::make_pair(left, right);
}
} else {
// We're smaller
return std::make_pair(left, right);
}
}
handle_t HandleGraph::traverse_edge_handle(const edge_t& edge, const handle_t& left) const {
if (left == edge.first) {
// The cannonical orientation is the one we want
return edge.second;
} else if (left == this->flip(edge.second)) {
// We really want the other orientation
return this->flip(edge.first);
} else {
// This isn't either handle that the edge actually connects. Something has gone wrong.
throw std::runtime_error("Cannot view edge " +
std::to_string(this->get_id(edge.first)) + " " + std::to_string(this->get_is_reverse(edge.first)) + " -> " +
std::to_string(this->get_id(edge.second)) + " " + std::to_string(this->get_is_reverse(edge.second)) +
" from non-participant " + std::to_string(this->get_id(left)) + " " + std::to_string(this->get_is_reverse(left)));
}
}
bool HandleGraph::has_edge(const handle_t& left, const handle_t& right) const {
bool not_seen = true;
follow_edges(left, false, [&](const handle_t& next) {
not_seen = (next != right);
return not_seen;
});
return !not_seen;
}
std::vector<occurrence_handle_t> PathHandleGraph::occurrences_of_handle(const handle_t& handle,
bool match_orientation) const {
std::vector<occurrence_handle_t> found;
for_each_occurrence_on_handle(handle, [&](const occurrence_handle_t& occ) {
// For each handle occurrence
if (!match_orientation || get_is_reverse(handle) == get_is_reverse(get_occurrence(occ))) {
// If its orientation is acceptable, keep it
found.push_back(occ);
}
});
return found;
}
bool PathHandleGraph::is_empty(const path_handle_t& path_handle) const {
// By default, we can answer emptiness queries with the length query.
// But some implementations may have an expensive length query and a cheaper emptiness one
return get_occurrence_count(path_handle) == 0;
}
/// Define equality on handles
bool operator==(const handle_t& a, const handle_t& b) {
return as_integer(a) == as_integer(b);
}
/// Define inequality on handles
bool operator!=(const handle_t& a, const handle_t& b) {
return as_integer(a) != as_integer(b);
}
/// Define equality on path handles
bool operator==(const path_handle_t& a, const path_handle_t& b) {
return as_integer(a) == as_integer(b);
}
/// Define inequality on path handles
bool operator!=(const path_handle_t& a, const path_handle_t& b) {
return as_integer(a) != as_integer(b);
}
/// Define equality on occurrence handles
bool operator==(const occurrence_handle_t& a, const occurrence_handle_t& b) {
return as_integers(a)[0] == as_integers(b)[0] && as_integers(a)[1] == as_integers(b)[1];
}
/// Define inequality on occurrence handles
bool operator!=(const occurrence_handle_t& a, const occurrence_handle_t& b) {
return !(a == b);
}
/// Define the null handle.
const handle_t null_handle = as_handle(std::numeric_limits<uint64_t>::max());
}