Files
hifiasm/POA.cpp
Haoyu Cheng d5327fe9ee phasing
2019-09-02 10:30:14 -04:00

621 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "POA.h"
#include <stdlib.h>
#include "Correct.h"
#include "Process_Read.h"
#define INIT_EDGE_SIZE 50
#define INCREASE_EDGE_SIZE 5
#define INIT_NODE_SIZE 16000
void init_Edge_alloc(Edge_alloc* list)
{
if (list->list == NULL)
{
list->size = INIT_EDGE_SIZE;
list->length = 0;
list->list = (Edge*)malloc(sizeof(Edge)*list->size);
}
else
{
list->length = 0;
}
}
void clear_Edge_alloc(Edge_alloc* list)
{
list->length = 0;
}
void destory_Edge_alloc(Edge_alloc* list)
{
free(list->list);
}
void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length)
{
if (list->length + 1 > list->size)
{
list->size = list->size + INCREASE_EDGE_SIZE;
list->list = (Edge*)realloc(list->list, sizeof(Edge)*list->size);
}
list->list[list->length].in_node = in_node;
list->list[list->length].out_node = out_node;
list->list[list->length].weight = weight;
list->list[list->length].length = length;
list->list[list->length].num_insertions = 0;
list->length++;
}
void init_Node_alloc(Node_alloc* list)
{
list->size = INIT_NODE_SIZE;
list->length = 0;
list->list = (Node*)malloc(sizeof(Node)*list->size);
list->sort.size = 0;
list->sort.list = NULL;
list->sort.visit = NULL;
list->sort.iterative_buffer = NULL;
list->sort.iterative_buffer_visit = NULL;
long long i;
for (i = 0; i < list->size; i++)
{
list->list[i].insertion_edges.list=NULL;
list->list[i].mismatch_edges.list=NULL;
list->list[i].deletion_edges.list=NULL;
}
}
void destory_Node_alloc(Node_alloc* list)
{
uint64_t i =0;
for (i = 0; i < list->length; i++)
{
destory_Edge_alloc(&list->list[i].deletion_edges);
destory_Edge_alloc(&list->list[i].insertion_edges);
destory_Edge_alloc(&list->list[i].mismatch_edges);
}
free(list->list);
free(list->sort.list);
free(list->sort.visit);
free(list->sort.iterative_buffer);
free(list->sort.iterative_buffer_visit);
///free(list->topo_order);
}
void clear_Node_alloc(Node_alloc* list)
{
uint64_t i =0;
for (i = 0; i < list->length; i++)
{
clear_Edge_alloc(&list->list[i].insertion_edges);
clear_Edge_alloc(&list->list[i].mismatch_edges);
clear_Edge_alloc(&list->list[i].deletion_edges);
}
list->length = 0;
}
uint64_t append_Node_alloc(Node_alloc* list, char base)
{
if (list->length + 1 > list->size)
{
long long i = list->size;
///list->topo_order这里用不到所以不用先分配空间
///但是还是一起分配了吧,免得麻烦
list->size = list->size * 2;
list->list = (Node*)realloc(list->list, sizeof(Node)*list->size);
///list->topo_order = (uint64_t*)realloc(list->topo_order, sizeof(uint64_t)*list->size);
for (; i < list->size; i++)
{
list->list[i].deletion_edges.list=NULL;
list->list[i].insertion_edges.list=NULL;
list->list[i].mismatch_edges.list=NULL;
}
}
list->list[list->length].ID = list->length;
list->list[list->length].base = base;
list->list[list->length].weight = 1;
list->list[list->length].num_insertions = 0;
init_Edge_alloc(&list->list[list->length].deletion_edges);
init_Edge_alloc(&list->list[list->length].insertion_edges);
init_Edge_alloc(&list->list[list->length].mismatch_edges);
list->length++;
return list->length - 1;
}
void init_Graph(Graph* g)
{
init_Node_alloc(&g->g_nodes);
g->g_n_edges = 0;
g->g_n_nodes = 0;
g->g_next_nodeID = 0;
g->s_end_nodeID = 0;
g->s_start_nodeID = 0;
g->seq = NULL;
g->seqID = (uint64_t)-1;
}
void destory_Graph(Graph* g)
{
destory_Node_alloc(&g->g_nodes);
}
void clear_Graph(Graph* g)
{
clear_Node_alloc(&g->g_nodes);
g->g_n_edges = 0;
g->g_n_nodes = 0;
g->g_next_nodeID = 0;
g->s_end_nodeID = 0;
g->s_start_nodeID = 0;
g->seq = NULL;
g->seqID = (uint64_t)-1;
}
void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID)
{
long long firstID, lastID, nodeID, i;
firstID = -1;
lastID = -1;
if(g_read_length == 0)
return;
///start node
nodeID = add_Node_Graph(g, 'S');
firstID = nodeID;
lastID = nodeID;
for (i = 0; i < g_read_length; i++)
{
nodeID = add_Node_Graph(g, g_read_seq[i]);
////fprintf(stderr, "nodeID: %llu\n", nodeID);
if (firstID == -1)
{
firstID = nodeID;
}
if (lastID != -1)
{
/**
///0是match边
add_Edge_Graph(g, lastID, nodeID, 0);
**/
///只有match边长度是0
///mismatch边长度都是1
append_Edge_alloc(&(g->g_nodes.list[lastID].mismatch_edges), lastID, nodeID, 1, 0);
}
lastID = nodeID;
}
*startID = firstID;
*endID = lastID;
g->s_start_nodeID = firstID;
g->s_end_nodeID = lastID;
}
void addmatchedSeqToGraph(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)
{
int x_i, y_i, cigar_i;
x_i = 0;
y_i = 0;
cigar_i = 0;
int operation;
int operationLen;
int i;
int last_operation = -1;
///note that node 0 is the start node
///0 is match, 1 is mismatch, 2 is up, 3 is left
///2是x缺字符y多字符而3是y缺字符x多字符
while (cigar_i < cigar->length)
{
operation = cigar->C_C[cigar_i];
operationLen = cigar->C_L[cigar_i];
///这种情况代表匹配和mismatch
if (operation == 0 || operation == 1)
{
for (i = 0; i < operationLen; i++)
{
//backbone->g_nodes.list[currentNodeID].weight++;
///前面是插入,后面有可能是误配,也有可能是匹配
add_mismatchEdge_weight(backbone, currentNodeID, y_string[y_i], last_operation);
x_i++;
y_i++;
currentNodeID++;
}
}///insertion
else if (operation == 2)
{
///cigar的起始和结尾不可能是2所以这里-1没问题
///if (operationLen <= CORRECT_INDEL_LENGTH)
{
add_insertionEdge_weight(backbone, currentNodeID, y_string + y_i, operationLen);
backbone->g_nodes.list[currentNodeID].num_insertions++;
}
y_i += operationLen;
}
else if (operation == 3)
{
///3是y缺字符x多字符也就是backbone多字符
///这个相当于在backbone对应字符处变成了——
///因此可以用mismatch类似的方法处理
///if (operationLen <= CORRECT_INDEL_LENGTH)
{
///add_deletion_to_backbone(backbone, &currentNodeID, operationLen);
///在编辑距离中,前面是个插入,后面是个删除,这种情况是不存在的
///为了保险要不还给他加上吧
///先不加
add_deletionEdge_weight(backbone, currentNodeID, operationLen);
}
currentNodeID += operationLen;
x_i += operationLen;
}
last_operation = operation;
cigar_i++;
}
/**
///cigar的起始和结尾不可能是2
if (cigar->C_C[0] == 2 || cigar->C_C[cigar->length - 1] == 2)
{
fprintf(stderr, "error\n");
}
if (x_i != x_length)
{
fprintf(stderr, "x_i: %d, x_length: %d\n", x_i, x_length);
}
if (y_i != y_length)
{
fprintf(stderr, "y_i: %d, y_length: %d\n", y_i, y_length);
}
**/
}
void debug_graph(Graph* g, long long backbone_length)
{
long long i = 0;
if (g->s_start_nodeID != 0 || g->s_end_nodeID != backbone_length)
{
fprintf(stderr, "error\n");
}
for (i = g->s_start_nodeID; i <= g->s_end_nodeID; i++)
{
if(g->g_nodes.list[i].weight != 1)
{
fprintf(stderr, "error node weight\n");
}
if(g->g_nodes.list[i].mismatch_edges.length > 4)
{
fprintf(stderr, "error mismatch_edges\n");
}
if(g->g_nodes.list[i].mismatch_edges.length < 1 && i != g->s_end_nodeID)
{
fprintf(stderr, "i: %d, error mismatch_edges: %d\n", i, g->g_nodes.list[i].mismatch_edges.length);
}
}
for (i = 0; i < g->g_nodes.length; i++)
{
if(g->g_nodes.list[i].ID < g->s_start_nodeID || g->g_nodes.list[i].ID > g->s_end_nodeID)
{
if (g->g_nodes.list[i].deletion_edges.length +
g->g_nodes.list[i].insertion_edges.length +
g->g_nodes.list[i].mismatch_edges.length
!= 1)
{
fprintf(stderr, "g->s_start_nodeID: %lld\n",
g->s_start_nodeID);
fprintf(stderr, "g->s_end_nodeID: %lld\n",
g->s_end_nodeID);
fprintf(stderr, "deletion_edges_length: %lld\n",
g->g_nodes.list[i].deletion_edges.length);
fprintf(stderr, "insertion_edges_length: %lld, \n",
g->g_nodes.list[i].insertion_edges.length);
fprintf(stderr, "g->g_nodes.list[i].insertion_edges.list[0].length: %lld, \n",
g->g_nodes.list[i].insertion_edges.list[0].length);
fprintf(stderr, "g->g_nodes.list[i].insertion_edges.list[1].length: %lld, \n",
g->g_nodes.list[i].insertion_edges.list[1].length);
fprintf(stderr, "mismatch_edges_length: %lld\n",
g->g_nodes.list[i].mismatch_edges.length);
}
else
{
///不是0肯定是1
if (g->g_nodes.list[i].deletion_edges.length != 0)
{
long long step = g->g_nodes.list[i].deletion_edges.list[0].length;
long long nodeID = i;
for (int j = 0; j < step; j++)
{
nodeID = g->g_nodes.list[nodeID].deletion_edges.list[0].out_node;
}
nodeID = g->g_nodes.list[nodeID].deletion_edges.list[0].out_node;
if (nodeID < g->s_start_nodeID || nodeID > g->s_end_nodeID)
{
fprintf(stderr, "error\n");
}
}
if (g->g_nodes.list[i].insertion_edges.length != 0)
{
long long step = g->g_nodes.list[i].insertion_edges.list[0].length;
long long nodeID = i;
for (int j = 0; j < step; j++)
{
nodeID = g->g_nodes.list[nodeID].insertion_edges.list[0].out_node;
}
nodeID = g->g_nodes.list[nodeID].insertion_edges.list[0].out_node;
if ((nodeID < g->s_start_nodeID || nodeID > g->s_end_nodeID))
{
fprintf(stderr, "error: step: %d\n", step);
}
}
if (g->g_nodes.list[i].mismatch_edges.length != 0)
{
long long step = g->g_nodes.list[i].mismatch_edges.list[0].length;
long long nodeID = i;
for (int j = 0; j < step; j++)
{
nodeID = g->g_nodes.list[nodeID].mismatch_edges.list[0].out_node;
}
nodeID = g->g_nodes.list[nodeID].mismatch_edges.list[0].out_node;
if (nodeID < g->s_start_nodeID || nodeID > g->s_end_nodeID)
{
fprintf(stderr, "error\n");
}
}
}
}
}
}
void Graph_debug(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)
{
/**
int x_i, y_i, cigar_i;
x_i = 0;
y_i = 0;
cigar_i = 0;
int operation;
int operationLen;
int i;
///0 is match, 1 is mismatch, 2 is up, 3 is left
///2是x缺字符y多字符而3是y缺字符x多字符
///while (x_i < x_len && y_i < y_len && cigar_i < cigar->length)
while (cigar_i < cigar->length)
{
operation = cigar->C_C[cigar_i];
operationLen = cigar->C_L[cigar_i];
///这种情况代表匹配
if (operation == 0)
{
for (i = 0; i < operationLen; i++)
{
if (backbone->g_nodes.list[currentNodeID].base != y_string[y_i])
{
fprintf(stderr, "error match\n");
}
backbone->g_nodes.list[currentNodeID].weight--;
x_i++;
y_i++;
currentNodeID++;
}
}
else if (operation == 1)
{
for (i = 0; i < operationLen; i++)
{
if (backbone->g_nodes.list[currentNodeID].base == y_string[y_i])
{
fprintf(stderr, "error mismatch 1\n");
}
long long mismatchID = get_alignToNode(backbone, currentNodeID, y_string[y_i]);
if(mismatchID == -1)
{
fprintf(stderr, "error mismatch 2\n");
}
else
{
backbone->g_nodes.list[mismatchID].weight--;
}
x_i++;
y_i++;
currentNodeID++;
}
}
else if (operation == 2)
{
long long nodeID = currentNodeID - 1;
long long mismatchID;
for (i = 0; i < operationLen; i++)
{
mismatchID = get_insertion_Node(backbone, nodeID, y_string[y_i]);
if (mismatchID == -1)
{
fprintf(stderr, "error insertion 1, i: %d\n", i);
}
else
{
backbone->g_nodes.list[mismatchID].weight--;
}
nodeID = mismatchID;
y_i++;
}
///注意这里是x_string[x_i]而不是x_string[currentNodeID]
mismatchID = get_insertion_Node(backbone, nodeID, x_string[x_i]);
if (mismatchID == -1)
{
fprintf(stderr, "error insertion 2, i: %d, x_i: %d\n", i, x_i);
}
if (mismatchID != currentNodeID)
{
fprintf(stderr, "error insertion 3, i: mismatchID: %d, currentNodeID: %d\n", mismatchID, currentNodeID);
}
}
else if (operation == 3)
{
for (i = 0; i < operationLen; i++)
{
long long mismatchID = get_alignToNode(backbone, currentNodeID, 'D');
if(mismatchID == -1)
{
fprintf(stderr, "error deletion 2\n");
}
else
{
backbone->g_nodes.list[mismatchID].weight--;
}
x_i++;
currentNodeID++;
}
}
cigar_i++;
}
if (cigar->C_C[0] == 2 || cigar->C_C[cigar->length - 1] == 2)
{
fprintf(stderr, "error\n");
}
if (x_i != x_length)
{
fprintf(stderr, "x_i: %d, x_length: %d\n", x_i, x_length);
}
if (y_i != y_length)
{
fprintf(stderr, "y_i: %d, y_length: %d\n", y_i, y_length);
}
**/
}