final DP-based assembly

This commit is contained in:
Haoyu Cheng
2019-11-13 20:18:11 -05:00
parent d6c6a1fa11
commit ada03ea388
22 changed files with 19432 additions and 1178 deletions
+722 -66
View File
@@ -23,6 +23,120 @@
5. 有两个回溯矩阵,一个是graph的,一个是seq的
**/
typedef struct
{
long long beg;
///end is the index of next input data, instead of the index of last data
long long end;
long long length;
long long size;
long long* buffer;
} Queue;
inline void init_Queue(Queue* q)
{
q->beg = 0;
q->end = 0;
q->length = 0;
q->size = 20;
q->buffer = (long long*)malloc(sizeof(long long)*q->size);
}
inline void clear_Queue(Queue* q)
{
q->beg = 0;
q->end = 0;
q->length = 0;
}
inline void destory_Queue(Queue* q)
{
free(q->buffer);
}
inline int is_empty_Queue(Queue* q)
{
///end is the index of next input data, instead of the index of last data
if(q->beg == q->end)
{
return 1;
}
else
{
return 0;
}
}
inline int is_full_Queue(Queue* q)
{
///end is the index of next input data, instead of the index of last data
if(q->end < q->size)
{
return 0;
}
else
{
return 1;
}
}
inline void push_to_Queue(Queue* q, long long nodeID)
{
if(is_full_Queue(q))
{
long long move_length = q->beg;
///end is the index of next input data, instead of the index of last data
long long current_length = q->end - q->beg;
///recalloc directly
if(move_length == 0)
{
q->size = q->size * 2;
q->buffer = (long long*)realloc(q->buffer, q->size*sizeof(long long));
}
else
{
///won't overlap
if(current_length <= move_length)
{
memcpy(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length);
}
else///may overlap
{
memmove(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length);
}
q->beg = 0;
q->end = current_length;
}
}
q->buffer[q->end] = nodeID;
q->end++;
}
inline int pop_from_Queue(Queue* q, long long* nodeID)
{
if(is_empty_Queue(q))
{
(*nodeID) = -1;
return 0;
}
else
{
(*nodeID) = q->buffer[q->beg];
q->beg++;
return 1;
}
}
typedef struct
{
uint64_t in_node;
@@ -32,6 +146,8 @@ typedef struct
uint64_t num_insertions;
///这条路径上到backbone节点之前总共有多少节点
uint64_t length;
uint64_t self_edge_ID;
uint64_t reverse_edge_ID;
} Edge;
typedef struct
@@ -39,8 +155,27 @@ typedef struct
Edge* list;
uint64_t size;
uint64_t length;
uint64_t delete_length;
} Edge_alloc;
#define Real_Length(X) ((X).length - (X).delete_length)
#define Input_Edges(Node) ((Node).insertion_edges)
#define Output_Edges(Node) ((Node).deletion_edges)
#define G_Node(G, Node) ((G).g_nodes.list[(Node)])
#define If_Node_Exist(Node) ((Node).base != 'D')
#define If_Edge_Exist(E) ((E).out_node != (uint64_t)-1)
#define Visit(E) (E).length
typedef struct
{
long long index;
} RSet;
inline void clear_RSet(RSet* set)
{
set->index = 0;
}
typedef struct
{
uint64_t ID;
@@ -73,6 +208,7 @@ typedef struct
topo_Sorting_buffer sort;
uint64_t size;
uint64_t length;
uint64_t delete_length;
} Node_alloc;
typedef struct
@@ -83,13 +219,222 @@ typedef struct
Node_alloc g_nodes;
Queue node_q;
char* seq;
uint64_t seqID;
uint64_t s_start_nodeID;
uint64_t s_end_nodeID;
} Graph;
int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag);
void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag);
int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node);
int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e);
inline int Pop_Node(Graph* DAGCon, Node** node)
{
long long nodeID = 0;
int return_flag = pop_from_Queue(&(DAGCon->node_q), &nodeID);
(*node) = &(G_Node(*DAGCon, nodeID));
return return_flag;
}
inline int Push_Node(Graph* DAGCon, Node** node)
{
push_to_Queue(&(DAGCon->node_q), (**node).ID);
}
inline int getInputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node)
{
if(set->index >= Input_Edges(*node).length)
{
return 0;
}
///skip all deleted edges
while (
set->index < Input_Edges(*node).length
&&
!(If_Edge_Exist(Input_Edges(*node).list[set->index]))
)
{
set->index++;
}
if(
set->index < Input_Edges(*node).length
&&
If_Edge_Exist(Input_Edges(*node).list[set->index])
)
{
(*get_Node) = &(G_Node((*graph), Input_Edges(*node).list[set->index].in_node));
set->index++;
return 1;
}
else
{
return 0;
}
}
inline int getInputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge)
{
if(set->index >= Input_Edges(*node).length)
{
return 0;
}
///skip all deleted edges
while (
set->index < Input_Edges(*node).length
&&
!(If_Edge_Exist(Input_Edges(*node).list[set->index]))
)
{
set->index++;
}
if(
set->index < Input_Edges(*node).length
&&
If_Edge_Exist(Input_Edges(*node).list[set->index])
)
{
(*get_Edge) = &(Input_Edges(*node).list[set->index]);
set->index++;
return 1;
}
else
{
return 0;
}
}
inline int getOutputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node)
{
if(set->index >= Output_Edges(*node).length)
{
return 0;
}
///skip all deleted edges
while (
set->index < Output_Edges(*node).length
&&
!(If_Edge_Exist(Output_Edges(*node).list[set->index]))
)
{
set->index++;
}
if(set->index < Output_Edges(*node).length &&
If_Edge_Exist(Output_Edges(*node).list[set->index]))
{
(*get_Node) = &(G_Node((*graph), Output_Edges(*node).list[set->index].out_node));
set->index++;
return 1;
}
else
{
return 0;
}
}
inline int getOutputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge)
{
if(set->index >= Output_Edges(*node).length)
{
return 0;
}
///skip all deleted edges
while (
set->index < Output_Edges(*node).length
&&
!(If_Edge_Exist(Output_Edges(*node).list[set->index]))
)
{
set->index++;
}
if(set->index < Output_Edges(*node).length &&
If_Edge_Exist(Output_Edges(*node).list[set->index]))
{
(*get_Edge) = &(Output_Edges(*node).list[set->index]);
set->index++;
return 1;
}
else
{
return 0;
}
}
inline void get_bi_direction_edges(Graph* DAGCon, Edge* edge, Edge** e_forward, Edge** e_backward)
{
long long in_node = edge->in_node;
long long out_node = edge->out_node;
if(
edge->self_edge_ID < Output_Edges(G_Node(*DAGCon, in_node)).length
&&
Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].in_node == in_node
&&
Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].out_node == out_node
)
{
(*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID]);
(*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->reverse_edge_ID]);
}
else
{
(*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->reverse_edge_ID]);
(*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->self_edge_ID]);
}
}
inline long long get_bi_Edge(Graph* DAGCon, Node* inNode, Node* outNode, Edge** e_forward, Edge** e_backward)
{
Edge* e;
RSet iter;
clear_RSet(&iter);
if(If_Node_Exist(*inNode) && If_Node_Exist(*outNode))
{
//find in-edge of outNode
while(getInputEdges(&iter, DAGCon, outNode, &e))
{
if(e->in_node == inNode->ID)
{
get_bi_direction_edges(DAGCon, e, e_forward, e_backward);
return 1;
}
}
}
return 0;
}
inline long long get_Edge_Weight(Graph* DAGCon, Node* inNode, Node* outNode)
{
Edge* e_forward;
Edge* e_backward;
get_bi_Edge(DAGCon, inNode, outNode, &e_forward, &e_backward);
return e_forward->weight;
}
void init_Edge_alloc(Edge_alloc* list);
void clear_Edge_alloc(Edge_alloc* list);
@@ -121,6 +466,48 @@ uint64_t inline add_Node_Graph(Graph* g, char base)
return append_Node_alloc(&g->g_nodes, base);
}
inline Node* add_Node_DAGCon(Graph* g, char base)
{
return &(G_Node(*g, append_Node_alloc(&g->g_nodes, base)));
}
///to delete a node
///1. set the corresponding base to be 'D'
///2. remove all related edges
///2. clear all related edges
///3. g_nodes.delete_length++, please do not substract g_nodes.length
uint64_t inline delete_Node_DAGCon(Graph* g, Node* node)
{
g->g_nodes.delete_length++;
g->g_nodes.list[(*node).ID].base = 'D';
g->g_nodes.list[(*node).ID].num_insertions = (uint64_t)-1;
g->g_nodes.list[(*node).ID].weight = (uint64_t)-1;
RSet iter;
Edge* e;
clear_RSet(&iter);
while (getOutputEdges(&iter, g, node, &e))
{
remove_and_check_bi_direction_edge_from_edge(g, e);
}
clear_RSet(&iter);
while (getInputEdges(&iter, g, node, &e))
{
remove_and_check_bi_direction_edge_from_edge(g, e);
}
clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].insertion_edges));
clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].mismatch_edges));
clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].deletion_edges));
}
///仅仅用于误配边
inline void add_mismatchEdge_weight(Graph* g, uint64_t in_node, char base, int last_operation)
@@ -193,6 +580,7 @@ inline void add_single_deletionEdge_weight(Graph* g, long long alignNodeID, long
inline void add_deletionEdge_weight(Graph* g, long long alignNodeID, long long deletion_length)
{
/**
if (deletion_length == 1)
{
add_single_deletionEdge_weight(g, alignNodeID, alignNodeID + 1, 0);
@@ -208,6 +596,13 @@ inline void add_deletionEdge_weight(Graph* g, long long alignNodeID, long long d
///fprintf(stderr, "too long deletion!\n");
add_single_deletionEdge_weight(g, alignNodeID, alignNodeID + deletion_length, 0);
}
**/
long long i;
for (i = 0; i < deletion_length; i++)
{
add_single_deletionEdge_weight(g, alignNodeID + i, alignNodeID + i + 1, 0);
}
}
@@ -266,8 +661,10 @@ inline int get_insertion_Edges(Graph* g, Edge_alloc* edge, uint64_t edge_length,
return -1;
}
}
return edgeID;
/****************************may have bugs********************************/
///return edgeID;
return return_edgeID;
/****************************may have bugs********************************/
}
@@ -305,19 +702,183 @@ inline int create_insertion_Edges(Graph* g, long long alignNodeID, uint64_t edge
}
inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* insert, long long insert_length)
inline void extract_path(Graph* backbone, int debug_node_in_backbone, int path_i, char* pre)
{
int step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length;
int string_i, preNode, j;
if(step != 0)
{
string_i = 0;
preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node;
for (j = 0; j < step; j++)
{
pre[string_i++] = G_Node(*backbone, preNode).base;
preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node;
}
}
pre[string_i] = '\0';
}
inline void extract_path_debug(Graph* backbone, int debug_node_in_backbone, int path_i, char* pre)
{
int step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length;
int string_i, preNode, preEdge, j;
if(step != 0)
{
string_i = 0;
preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node;
preEdge = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length;
for (j = 0; j < step; j++)
{
///pre[string_i++] = G_Node(*backbone, preNode).base;
fprintf(stderr, "j: %d (%c%d), ", j, G_Node(*backbone, preNode).base, preEdge);
preEdge = G_Node(*backbone, preNode).insertion_edges.list[0].length;
preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node;
}
}
fprintf(stderr, "\n");
///pre[string_i] = '\0';
}
inline int getEdge_DEBUG(Graph* g, Edge_alloc* edge, uint64_t edge_length, char base)
{
long long i = 0;
long long nodeID;
for (i = 0; i < edge->length; i++)
{
///fprintf(stderr, "************i:%d, edge->list[i].length: %d, edge_length: %d\n",i, edge->list[i].length, edge_length);
if (edge->list[i].length == edge_length)
{
nodeID = edge->list[i].out_node;
fprintf(stderr, "########i:%d, edge->list[i].length: %d, edge_length: %d, nodeID: %d, list[nodeID].base: %c, base: %c\n",
i, edge->list[i].length, edge_length, nodeID, g->g_nodes.list[nodeID].base, base);
if(g->g_nodes.list[nodeID].base == base)
{
return i;
}
}
}
return -1;
}
inline int get_insertion_Edges_new(Graph* backbone, int debug_node_in_backbone, uint64_t edge_length, char* bases)
{
int path_i, j, step, preNode;
for (path_i = 0; path_i < G_Node(*backbone, debug_node_in_backbone).insertion_edges.length; path_i++)
{
step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length;
if(step != edge_length)
{
continue;
}
if(step != 0)
{
preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node;
for (j = 0; j < step; j++)
{
///pre[string_i++] = G_Node(*backbone, preNode).base;
///fprintf(stderr, "path_i: %d, ID: %d\n", path_i, G_Node(*backbone, preNode).ID);
if(G_Node(*backbone, preNode).base != bases[j])
{
break;
}
preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node;
}
if(j == step)
{
return path_i;
}
}
}
return -1;
}
inline int get_insertion_Edges_debug(Graph* g, Edge_alloc* edge, uint64_t edge_length, char* bases)
{
long long i = 0;
long long nodeID;
long long edgeID;
if (edge_length < 1)
{
return -1;
}
///fprintf(stderr, "edge_length: %d, edge: %.*s\n", edge_length, edge_length, bases);
edgeID = getEdge_DEBUG(g, edge, edge_length, bases[0]);
fprintf(stderr, "i: %d, edgeID: %d, edge_length - i: %d\n", i, edgeID, edge_length);
long long return_edgeID = edgeID;
if(edgeID == -1)
{
return -1;
}
Edge_alloc* new_edge = edge;
for (i = 1; i < edge_length; i++)
{
nodeID = new_edge->list[edgeID].out_node;
new_edge = &(g->g_nodes.list[nodeID].insertion_edges);
edgeID = getEdge_DEBUG(g, new_edge, edge_length - i, bases[i]);
fprintf(stderr, "i: %d, edgeID: %d, edge_length - i: %d\n", i, edgeID, edge_length - i);
if(edgeID == -1)
{
return -1;
}
}
/****************************may have bugs********************************/
///return edgeID;
return return_edgeID;
/****************************may have bugs********************************/
}
inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* insert, long long insert_length)
{
long long nodeID;
long long edgeID;
Edge_alloc* edge = &(g->g_nodes.list[alignNodeID].insertion_edges);
if (insert_length == 1)
{
edgeID = getEdge(g, edge, 1, insert[0]);
// if(edgeID != get_insertion_Edges_new(g, alignNodeID, insert_length, insert))
// {
// fprintf(stderr, "error\n");
// }
if (edgeID != -1)
{
///这条路均只有一个出度
edge->list[edgeID].weight++;
}
else ///不存在这么一条边
@@ -330,68 +891,10 @@ inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* inse
append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
}
}
else if (insert_length == 2)
else
{
/*******************第0个字符********************* */
edgeID = getEdge(g, edge, 1, insert[0]);
if (edgeID != -1)
{
///这条路均只有一个出度
edge->list[edgeID].weight++;
}
else ///不存在这么一条边
{
nodeID = add_Node_Graph(g, insert[0]);
append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
///将新加入的节点通过insertion_edges接回backbone上
///应该连回到原节点,而不是原节点的下一个节点
///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
}
/*******************第0个字符********************* */
/*******************第1个字符********************* */
if (insert[1] != insert[0])
{
edgeID = getEdge(g, edge, 1, insert[1]);
if (edgeID != -1)
{
///这条路均只有一个出度
edge->list[edgeID].weight++;
}
else ///不存在这么一条边
{
nodeID = add_Node_Graph(g, insert[1]);
append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
///将新加入的节点通过insertion_edges接回backbone上
///应该连回到原节点,而不是原节点的下一个节点
///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
}
}
/*******************第1个字符********************* */
/**********************两个字符******************* */
edgeID = get_insertion_Edges(g, edge, 2, insert);
if (edgeID != -1)
{
///这条路均只有一个出度
edge->list[edgeID].weight++;
}
else
{
create_insertion_Edges(g, alignNodeID, insert_length, insert);
}
/**********************两个字符******************* */
}
else if (insert_length > 2)
{
////fprintf(stderr, "too long insertion\n");
/*************************大于2个字符************************** */
edgeID = get_insertion_Edges(g, edge, insert_length, insert);
///edgeID = get_insertion_Edges(g, edge, insert_length, insert);
edgeID = get_insertion_Edges_new(g, alignNodeID, insert_length, insert);
if (edgeID != -1)
{
///这条路均只有一个出度
@@ -402,10 +905,163 @@ inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* inse
create_insertion_Edges(g, alignNodeID, insert_length, insert);
}
}
// /******************************for homopolymer*************************/
// long long i = 0;
// char hom;
// if (insert_length > 0)
// {
// hom = insert[0];
// }
// for (i = 0; i < insert_length; i++)
// {
// if(insert[i] != hom)
// {
// break;
// }
// }
// ///if it is a homopolymer
// if(i == insert_length)
// {
// ///single base
// edgeID = getEdge(g, edge, 1, insert[0]);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else ///不存在这么一条边
// {
// nodeID = add_Node_Graph(g, insert[0]);
// append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
// ///将新加入的节点通过insertion_edges接回backbone上
// ///应该连回到原节点,而不是原节点的下一个节点
// ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
// append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
// }
// ///multiple bases
// for (i = 1; i < insert_length; i++)
// {
// edgeID = get_insertion_Edges(g, edge, i + 1, insert);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else
// {
// create_insertion_Edges(g, alignNodeID, i + 1, insert);
// }
// }
// return;
// }
// /******************************for homopolymer*************************/
// if (insert_length == 1)
// {
// edgeID = getEdge(g, edge, 1, insert[0]);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else ///不存在这么一条边
// {
// nodeID = add_Node_Graph(g, insert[0]);
// append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
// ///将新加入的节点通过insertion_edges接回backbone上
// ///应该连回到原节点,而不是原节点的下一个节点
// ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
// append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
// }
// }
// else if (insert_length == 2)
// {
// /*******************第0个字符********************* */
// edgeID = getEdge(g, edge, 1, insert[0]);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else ///不存在这么一条边
// {
// nodeID = add_Node_Graph(g, insert[0]);
// append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
// ///将新加入的节点通过insertion_edges接回backbone上
// ///应该连回到原节点,而不是原节点的下一个节点
// ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
// append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
// }
// /*******************第0个字符********************* */
// /*******************第1个字符********************* */
// if (insert[1] != insert[0])
// {
// edgeID = getEdge(g, edge, 1, insert[1]);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else ///不存在这么一条边
// {
// nodeID = add_Node_Graph(g, insert[1]);
// append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1);
// ///将新加入的节点通过insertion_edges接回backbone上
// ///应该连回到原节点,而不是原节点的下一个节点
// ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0);
// append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0);
// }
// }
// /*******************第1个字符********************* */
// /**********************两个字符******************* */
// edgeID = get_insertion_Edges(g, edge, 2, insert);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else
// {
// create_insertion_Edges(g, alignNodeID, insert_length, insert);
// }
// /**********************两个字符******************* */
// }
// else if (insert_length > 2)
// {
// ////fprintf(stderr, "too long insertion\n");
// /*************************大于2个字符************************** */
// edgeID = get_insertion_Edges(g, edge, insert_length, insert);
// if (edgeID != -1)
// {
// ///这条路均只有一个出度
// edge->list[edgeID].weight++;
// }
// else
// {
// create_insertion_Edges(g, alignNodeID, insert_length, insert);
// }
// }
}
void addmatchedSeqToGraph_print(Graph* backbone, long long currentNodeID, char* x_string, long long x_length,
char* y_string, long long y_length, CIGAR* cigar, long long backbone_start, long long backbone_end);
#endif