mirror of
https://github.com/chhylp123/hifiasm.git
synced 2026-09-26 02:08:12 +08:00
final DP-based assembly
This commit is contained in:
Vendored
+10
-1
@@ -16,6 +16,15 @@
|
||||
"string": "cpp",
|
||||
"array": "cpp",
|
||||
"utility": "cpp",
|
||||
"cmath": "cpp"
|
||||
"cmath": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"system_error": "cpp",
|
||||
"set": "cpp",
|
||||
"sstream": "cpp",
|
||||
"istream": "cpp",
|
||||
"ostream": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
||||
+1444
-405
File diff suppressed because it is too large
Load Diff
+19
-2
@@ -9,6 +9,7 @@ char* read_file_name = NULL;
|
||||
char* output_file_name = NULL;
|
||||
int thread_num = 1;
|
||||
int k_mer_length = 40;
|
||||
int coverage = -1;
|
||||
//int k_mer_min_freq = 9;
|
||||
int k_mer_min_freq = 3;
|
||||
//int k_mer_min_freq = 2;
|
||||
@@ -16,7 +17,10 @@ int k_mer_max_freq = 66;
|
||||
int load_index_from_disk = 0;
|
||||
int write_index_to_disk = 0;
|
||||
int number_of_round = 1;
|
||||
|
||||
int read_graph = 0;
|
||||
int c_round = 4;
|
||||
int adapterLen = 0;
|
||||
char* required_read_name = NULL;
|
||||
|
||||
double Get_T(void)
|
||||
{
|
||||
@@ -28,6 +32,8 @@ double Get_T(void)
|
||||
void Print_H()
|
||||
{
|
||||
fprintf(stderr, "Incorrect options.\n");
|
||||
fprintf(stderr, "./ccs_assembly -w -l -q NA12878_chr1_10M.fq -o output_NA12878_v11_2.fa -c 31 -k 40 -t 32 -r 2 -a 4 -z 0\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +56,7 @@ int CommandLine_process (int argc, char *argv[])
|
||||
ketopt_t opt = KETOPT_INIT;
|
||||
|
||||
int i, c;
|
||||
while ((c = ketopt(&opt, argc, argv, 1, "ht:o:q:k:lwm:n:r:", longopts)) >= 0) {
|
||||
while ((c = ketopt(&opt, argc, argv, 1, "ht:o:q:k:lwm:n:r:c:a:b:z:", longopts)) >= 0) {
|
||||
if (c == 100 || c == 'h') Print_H();
|
||||
else if (c == 103 || c == 't') thread_num = atoi(opt.arg);
|
||||
else if (c == 102 || c == 'o') output_file_name = opt.arg;
|
||||
@@ -61,6 +67,10 @@ int CommandLine_process (int argc, char *argv[])
|
||||
else if (c == 'k') k_mer_length = atoi(opt.arg);
|
||||
else if (c == 'l') load_index_from_disk = 1;
|
||||
else if (c == 'w') write_index_to_disk = 1;
|
||||
else if (c == 'c') coverage = atoi(opt.arg);
|
||||
else if (c == 'a') c_round = atoi(opt.arg);
|
||||
else if (c == 'z') adapterLen = atoi(opt.arg);
|
||||
else if (c == 'b') required_read_name = opt.arg;
|
||||
else if (c == '?') printf("unknown opt: -%c\n", opt.opt? opt.opt : ':');
|
||||
else if (c == ':') printf("missing arg: -%c\n", opt.opt? opt.opt : ':');
|
||||
}
|
||||
@@ -72,6 +82,13 @@ int CommandLine_process (int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(coverage == -1)
|
||||
{
|
||||
fprintf(stdout, "Please set -c!\n");
|
||||
Print_H();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -13,6 +13,12 @@ extern int k_mer_max_freq;
|
||||
extern int load_index_from_disk;
|
||||
extern int write_index_to_disk;
|
||||
extern int number_of_round;
|
||||
extern int roundID;
|
||||
extern int coverage;
|
||||
extern int read_graph;
|
||||
extern int c_round;
|
||||
extern char* required_read_name;
|
||||
extern int adapterLen;
|
||||
|
||||
|
||||
int CommandLine_process (int argc, char *argv[]);
|
||||
|
||||
+5589
-547
File diff suppressed because it is too large
Load Diff
+1477
-63
File diff suppressed because it is too large
Load Diff
+127
-11
@@ -17,23 +17,23 @@ typedef khash_t(POS64) Pos_Table;
|
||||
///#define THRESHOLD 14
|
||||
|
||||
#define WINDOW 375
|
||||
#define WINDOW_BOUNDARY 150
|
||||
//#define WINDOW_BOUNDARY 150
|
||||
#define WINDOW_BOUNDARY 375
|
||||
///for one side, the first or last WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY bases should not be corrected
|
||||
#define WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY 25
|
||||
#define THRESHOLD 15
|
||||
#define THRESHOLD_RATE 0.04
|
||||
#define OVERLAP_THRESHOLD 0.9
|
||||
#define TAIL_LENGTH int(1/THRESHOLD_RATE)
|
||||
///#define OVERLAP_THRESHOLD 0.9
|
||||
#define OVERLAP_THRESHOLD_FILTER 0.9
|
||||
#define WINDOW_MAX_SIZE WINDOW + TAIL_LENGTH + 3
|
||||
#define THRESHOLD_MAX_SIZE 31
|
||||
|
||||
/**
|
||||
#define WINDOW 500
|
||||
#define THRESHOLD 15
|
||||
#define THRESHOLD_RATE 0.03
|
||||
#define OVERLAP_THRESHOLD 0.95
|
||||
**/
|
||||
|
||||
#define GROUP_SIZE 4
|
||||
///最长是10M10D10M10D10M这种
|
||||
#define CIGAR_MAX_LENGTH THRESHOLD*2+2
|
||||
///#define CIGAR_MAX_LENGTH THRESHOLD*2+2
|
||||
#define CIGAR_MAX_LENGTH 31*2+4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -92,12 +92,21 @@ typedef struct
|
||||
int y_start;
|
||||
int extra_begin;
|
||||
int extra_end;
|
||||
int error_threshold;
|
||||
///int y_pre_start;
|
||||
///error小于等于0都要重新算
|
||||
int error;
|
||||
CIGAR cigar;
|
||||
} window_list;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t* buffer;
|
||||
uint64_t length;
|
||||
uint64_t size;
|
||||
}Fake_Cigar;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t x_id;
|
||||
@@ -113,10 +122,15 @@ typedef struct
|
||||
|
||||
uint64_t shared_seed;
|
||||
uint64_t align_length;
|
||||
///uint64_t total_errors;
|
||||
uint8_t is_match;
|
||||
uint64_t non_homopolymer_errors;
|
||||
|
||||
window_list* w_list;
|
||||
uint64_t w_list_size;
|
||||
uint64_t w_list_length;
|
||||
int8_t strong;
|
||||
Fake_Cigar f_cigar;
|
||||
} overlap_region;
|
||||
|
||||
|
||||
@@ -125,6 +139,8 @@ typedef struct
|
||||
overlap_region* list;
|
||||
uint64_t size;
|
||||
uint64_t length;
|
||||
///uint64_t mapped_overlaps_length;
|
||||
long long mapped_overlaps_length;
|
||||
} overlap_region_alloc;
|
||||
|
||||
typedef struct
|
||||
@@ -153,7 +169,15 @@ typedef struct
|
||||
int MaxSize;
|
||||
} HeapSq;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long long* score;
|
||||
long long* pre;
|
||||
long long* indels;
|
||||
long long* self_length;
|
||||
long long length;
|
||||
long long size;
|
||||
} Chain_Data;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -163,6 +187,7 @@ typedef struct
|
||||
long long size;
|
||||
uint64_t foward_pos;
|
||||
uint64_t rc_pos;
|
||||
Chain_Data chainDP;
|
||||
} Candidates_list;
|
||||
|
||||
typedef struct
|
||||
@@ -206,6 +231,23 @@ inline uint64_t mod_d(uint64_t h_key, uint64_t low_key, uint64_t d)
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int if_k_mer_available(Hash_code* code, int k)
|
||||
{
|
||||
uint64_t h_key, low_key;
|
||||
///k有可能是64,所以可能会有问题
|
||||
///low_key = code->x[0] | (code->x[1] << k);
|
||||
low_key = code->x[0] | (code->x[1] << SAFE_SHIFT(k));
|
||||
//k不可能为0, 所以这个右移不会有问题
|
||||
h_key = code->x[1] >> (64 - k);
|
||||
|
||||
if(mod_d(h_key, low_key, MODE_VALUE) > 3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///inline int get_sub_table(uint64_t* get_sub_ID, uint64_t* get_sub_key, Total_Count_Table* TCB, Hash_code* code, int k)
|
||||
@@ -458,16 +500,84 @@ void append_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp
|
||||
void calculate_overlap_region(Candidates_list* candidates, overlap_region_alloc* overlap_list,
|
||||
uint64_t readID, uint64_t readLength, All_reads* R_INF);
|
||||
void append_window_list(overlap_region* region, uint64_t x_start, uint64_t x_end, int y_start, int y_end, int error,
|
||||
int extra_begin, int extra_end);
|
||||
int extra_begin, int extra_end, int error_threshold);
|
||||
|
||||
|
||||
void insert_kv_list_to_candidates(k_v* list, long long occ, long long y_id, long long y_offset, long long y_strand,
|
||||
Candidates_list* candidates);
|
||||
|
||||
void overlap_region_sort_y_id(overlap_region *a, long long n);
|
||||
|
||||
void calculate_inexact_overlap_region(Candidates_list* candidates, overlap_region_alloc* overlap_list,
|
||||
uint64_t readID, uint64_t readLength, All_reads* R_INF);
|
||||
|
||||
void calculate_overlap_region_by_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list,
|
||||
uint64_t readID, uint64_t readLength, All_reads* R_INF, double band_width_threshold);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const char LogTable256[256] = {
|
||||
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
|
||||
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
|
||||
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
|
||||
};
|
||||
|
||||
static inline int ilog2_32(uint32_t v)
|
||||
{
|
||||
uint32_t t, tt;
|
||||
if ((tt = v>>16)) return (t = tt>>8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
|
||||
return (t = v>>8) ? 8 + LogTable256[t] : LogTable256[v];
|
||||
}
|
||||
|
||||
void init_fake_cigar(Fake_Cigar* x);
|
||||
void destory_fake_cigar(Fake_Cigar* x);
|
||||
void clear_fake_cigar(Fake_Cigar* x);
|
||||
void add_fake_cigar(Fake_Cigar* x, uint32_t gap_site, int32_t gap_shift);
|
||||
void resize_fake_cigar(Fake_Cigar* x, long long size);
|
||||
int get_fake_gap_pos(Fake_Cigar* x, int index);
|
||||
int get_fake_gap_shift(Fake_Cigar* x, int index);
|
||||
inline long long y_start_offset(long long x_start, Fake_Cigar* o)
|
||||
{
|
||||
if(x_start == get_fake_gap_pos(o, o->length - 1))
|
||||
{
|
||||
return get_fake_gap_shift(o, o->length - 1);
|
||||
}
|
||||
|
||||
|
||||
long long i;
|
||||
for (i = 0; i < o->length; i++)
|
||||
{
|
||||
if(x_start < get_fake_gap_pos(o, i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0 || i == o->length)
|
||||
{
|
||||
fprintf(stderr, "ERROR\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
///note here return i - 1
|
||||
return get_fake_gap_shift(o, i - 1);
|
||||
}
|
||||
|
||||
inline void print_fake_gap(Fake_Cigar* o)
|
||||
{
|
||||
long long i;
|
||||
for (i = 0; i < o->length; i++)
|
||||
{
|
||||
fprintf(stderr, "**i: %d, gap_pos_in_x: %d, gap_shift: %d\n",
|
||||
i, get_fake_gap_pos(o, i),
|
||||
get_fake_gap_shift(o, i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -585,4 +695,10 @@ void debug_mode(uint64_t d, uint64_t thread_ID, uint64_t thread_num);
|
||||
/********************************for debug***************************************/
|
||||
void merge_Candidates_list_version(Candidates_list* l, k_mer_pos* n_list, uint64_t n_lengh, uint64_t end_pos, int strand);
|
||||
|
||||
void sort_candidates(Candidates_list* candidates, long long readID,
|
||||
overlap_region_alloc* overlap_list, All_reads* R_INF);
|
||||
void append_overlap_region_alloc_from_existing(overlap_region_alloc* list, overlap_region* tmp, All_reads* R_INF);
|
||||
int cmp_by_x_pos_s(const void * a, const void * b);
|
||||
void resize_Chain_Data(Chain_Data* x, long long size);
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,7 @@ CC=g++
|
||||
CFLAGS = -w -c -msse4.2 -mpopcnt -fomit-frame-pointer -Winline -O3 -lz
|
||||
LDFLAGS = -lm -lz -lpthread -O3 -mpopcnt -msse4.2 -lz -w
|
||||
|
||||
SOURCES = main.cpp Output.cpp CommandLines.cpp Process_Read.cpp Assembly.cpp kmer.cpp Hash_Table.cpp POA.cpp Correct.cpp Levenshtein_distance.cpp edlib.cpp
|
||||
SOURCES = main.cpp Output.cpp CommandLines.cpp Process_Read.cpp Assembly.cpp kmer.cpp Hash_Table.cpp POA.cpp Correct.cpp Levenshtein_distance.cpp edlib.cpp Overlaps.cpp
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
EXECUTABLE = ccs_assembly
|
||||
|
||||
|
||||
+7709
File diff suppressed because it is too large
Load Diff
+322
@@ -0,0 +1,322 @@
|
||||
#ifndef __OVERLAPS__
|
||||
#define __OVERLAPS__
|
||||
#include <stdint.h>
|
||||
#include "kvec.h"
|
||||
#include "kdq.h"
|
||||
///#include "Hash_Table.h"
|
||||
|
||||
///#define MIN_OVERLAP_LEN 2000
|
||||
///#define MIN_OVERLAP_LEN 500
|
||||
#define MIN_OVERLAP_LEN 50
|
||||
#define MIN_OVERLAP_COVERAGE 1
|
||||
#define MAX_HANG_LEN 1000
|
||||
#define MAX_HANG_PRE 0.8
|
||||
#define GAP_FUZZ 1000
|
||||
#define MAX_SHORT_TIPS 3
|
||||
#define MAX_BUBBLE_DIST 10000000
|
||||
#define SMALL_BUBBLE_SIZE (uint32_t)-1
|
||||
//#define SMALL_BUBBLE_SIZE 1000
|
||||
|
||||
|
||||
#define Get_qn(RECORD) ((uint32_t)((RECORD).qns>>32))
|
||||
#define Get_qs(RECORD) ((uint32_t)((RECORD).qns))
|
||||
#define Get_qe(RECORD) ((RECORD).qe)
|
||||
#define Get_tn(RECORD) ((RECORD).tn)
|
||||
#define Get_ts(RECORD) ((RECORD).ts)
|
||||
#define Get_te(RECORD) ((RECORD).te)
|
||||
|
||||
#define LONG_TIPS 0
|
||||
#define TWO_INPUT 1
|
||||
#define TWO_OUTPUT 2
|
||||
#define MUL_INPUT 3
|
||||
#define MUL_OUTPUT 4
|
||||
#define END_TIPS 5
|
||||
#define LONG_TIPS_UNDER_MAX_EXT 6
|
||||
#define LOOP 7
|
||||
|
||||
|
||||
///query is the read itself
|
||||
typedef struct {
|
||||
uint64_t qns;
|
||||
uint32_t qe, tn, ts, te;
|
||||
uint32_t ml:31, rev:1;
|
||||
uint32_t bl:31, del:1;
|
||||
uint8_t el;
|
||||
} ma_hit_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ma_hit_t* buffer;
|
||||
uint32_t size;
|
||||
uint32_t length;
|
||||
uint8_t is_fully_corrected;
|
||||
} ma_hit_t_alloc;
|
||||
|
||||
|
||||
void init_ma_hit_t_alloc(ma_hit_t_alloc* x);
|
||||
void clear_ma_hit_t_alloc(ma_hit_t_alloc* x);
|
||||
void resize_ma_hit_t_alloc(ma_hit_t_alloc* x, uint64_t size);
|
||||
void destory_ma_hit_t_alloc(ma_hit_t_alloc* x);
|
||||
void add_ma_hit_t_alloc(ma_hit_t_alloc* x, ma_hit_t* element);
|
||||
void ma_hit_sort_tn(ma_hit_t *a, long long n);
|
||||
void ma_hit_sort_qns(ma_hit_t *a, long long n);
|
||||
|
||||
int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources,
|
||||
char* output_file_name);
|
||||
|
||||
|
||||
typedef struct {
|
||||
ma_hit_t_alloc overlaps;
|
||||
} Assembly_Graph;
|
||||
|
||||
void init_Assembly_Graph(Assembly_Graph* x);
|
||||
void destory_Assembly_Graph(Assembly_Graph* x);
|
||||
void collect_ma_hit_t(ma_hit_t_alloc* dest, ma_hit_t_alloc* sources, long long num_sources);
|
||||
void normalize_ma_hit_t(ma_hit_t_alloc* sources, long long num_sources);
|
||||
void debug_normalize_ma_hit_t(ma_hit_t_alloc* sources, long long num_sources);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t s:31, del:1, e;
|
||||
} ma_sub_t;
|
||||
|
||||
void ma_hit_sub(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen,
|
||||
long long mini_overlap_length, ma_sub_t** coverage_cut);
|
||||
void ma_hit_cut(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen,
|
||||
long long mini_overlap_length, ma_sub_t** coverage_cut);
|
||||
void ma_hit_flt(ma_hit_t_alloc* sources, long long n_read, const ma_sub_t *coverage_cut,
|
||||
int max_hang, int min_ovlp);
|
||||
long long get_specific_overlap(ma_hit_t_alloc* x, uint32_t qn, uint32_t tn);
|
||||
|
||||
void debug_cut_ma_hit_t(ma_hit_t_alloc* sources, long long num_sources, ma_sub_t *coverage_cut);
|
||||
|
||||
typedef struct {
|
||||
uint64_t ul;
|
||||
uint32_t v;
|
||||
uint32_t ol:31, del:1;
|
||||
uint8_t strong;
|
||||
uint8_t el;
|
||||
} asg_arc_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t len:31, del:1;
|
||||
} asg_seq_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_arc, n_arc:31, is_srt:1;
|
||||
asg_arc_t *arc;
|
||||
uint32_t m_seq, n_seq:31, is_symm:1;
|
||||
asg_seq_t *seq;
|
||||
uint64_t *idx;
|
||||
|
||||
uint8_t* seq_vis;
|
||||
} asg_t;
|
||||
|
||||
typedef struct { size_t n, m; uint64_t *a; } asg64_v;
|
||||
|
||||
|
||||
#define MA_HT_INT (-1)
|
||||
#define MA_HT_QCONT (-2)
|
||||
#define MA_HT_TCONT (-3)
|
||||
#define MA_HT_SHORT_OVLP (-4)
|
||||
|
||||
///in default, max_hang = 1000, int_frac = 0.05, min_ovlp = 2000
|
||||
static inline int ma_hit2arc(const ma_hit_t *h, int ql, int tl, int max_hang, float int_frac, int min_ovlp, asg_arc_t *p)
|
||||
{
|
||||
int32_t tl5, tl3, ext5, ext3, qs = (int32_t)h->qns;
|
||||
uint32_t u, v, l; // u: query end; v: target end; l: length from u to v
|
||||
|
||||
///if query and target are in different strand
|
||||
if (h->rev) tl5 = tl - h->te, tl3 = h->ts; // tl5: 5'-end overhang (on the query strand); tl3: similar
|
||||
else tl5 = h->ts, tl3 = tl - h->te;
|
||||
|
||||
///ext5 and ext3 is the hang on left side and right side, respectively
|
||||
ext5 = qs < tl5? qs : tl5;
|
||||
ext3 = ql - h->qe < tl3? ql - h->qe : tl3;
|
||||
|
||||
|
||||
/**
|
||||
if (ext5 > max_hang || ext3 > max_hang || h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac)
|
||||
return MA_HT_INT;
|
||||
**/
|
||||
if (ext5 > max_hang || ext3 > max_hang
|
||||
|| h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac
|
||||
|| h->te - h->ts < (h->te - h->ts + ext5 + ext3) * int_frac)
|
||||
{
|
||||
return MA_HT_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
********************************query-to-target overlap****************************
|
||||
case 1: u = 0, rev = 0 in the view of target: direction is 1
|
||||
query: CCCCCCCCTAATTAAAAT target: TAATTAAAATGGGGGG (use ex-target as query)
|
||||
|||||||||| <---> ||||||||||
|
||||
target: TAATTAAAATGGGGGG query: CCCCCCCCTAATTAAAAT (use ex-query as target)
|
||||
|
||||
case 2: u = 0, rev = 1 in the view of target: direction is 0
|
||||
query: CCCCCCCCTAATTAAAAT target: CCCCCCATTTTAATTA (use ex-target as query)
|
||||
|||||||||| <---> ||||||||||
|
||||
target: TAATTAAAATGGGGGG query: ATTTTAATTAGGGGGGGG (use ex-query as target)
|
||||
********************************query-to-target overlap****************************
|
||||
|
||||
********************************target-to-query overlap****************************
|
||||
case 3: u = 1, rev = 0 in the view of target: direction is 0
|
||||
query: AAATAATATCCCCCCGCG target: GGGCCGGCAAATAATAT (use ex-target as query)
|
||||
||||||||| <---> |||||||||
|
||||
target: GGGCCGGCAAATAATAT query: AAATAATATCCCCCCGCG (use ex-query as target)
|
||||
|
||||
case 4: u = 1, rev = 1 in the view of target: direction is 1
|
||||
query: AAATAATATCCCCCCGCG target: ATATTATTTGCCGGCCC (use ex-target as query)
|
||||
||||||||| <---> |||||||||
|
||||
target: GGGCCGGCAAATAATAT query: CGCGGGGGATATTATTT (use ex-query as target)
|
||||
********************************target-to-query overlap****************************
|
||||
**/
|
||||
|
||||
if (qs <= tl5 && ql - h->qe <= tl3) return MA_HT_QCONT; // query contained in target
|
||||
else if (qs >= tl5 && ql - h->qe >= tl3) return MA_HT_TCONT; // target contained in query
|
||||
else if (qs > tl5) u = 0, v = !!h->rev, l = qs - tl5; ///u = 0 means query-to-target overlap, l is the length of node in string graph (not the overlap length)
|
||||
else u = 1, v = !h->rev, l = (ql - h->qe) - tl3; ///u = 1 means target-to-query overlaps, l is the length of node in string graph (not the overlap length)
|
||||
if (h->qe - qs + ext5 + ext3 < min_ovlp || h->te - h->ts + ext5 + ext3 < min_ovlp) return MA_HT_SHORT_OVLP; // short overlap
|
||||
///u = 0 / 1 means query-to-target / target-to-query overlaps,
|
||||
///l is the length of node in string graph (not the overlap length between two reads)
|
||||
u |= h->qns>>32<<1, v |= h->tn<<1;
|
||||
/**
|
||||
p->ul: |____________31__________|__________1___________|______________32_____________|
|
||||
qn direction of overlap length of this node (not overlap length)
|
||||
(in the view of query)
|
||||
p->v : |___________31___________|__________1___________|
|
||||
tn reverse direction of overlap
|
||||
(in the view of target)
|
||||
p->ol: overlap length
|
||||
**/
|
||||
p->ul = (uint64_t)u<<32 | l, p->v = v, p->ol = ql - l, p->del = 0;
|
||||
///l is the length of node in string graph (not the overlap length)
|
||||
|
||||
p->strong = h->ml;
|
||||
p->el = h->el;
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void build_string_graph(int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long n_read, uint64_t* readLen,
|
||||
long long mini_overlap_length, long long max_hang_length,
|
||||
long long clean_round, float min_ovlp_drop_ratio, float max_ovlp_drop_ratio,
|
||||
float final_ovlp_drop_ratio, char* output_file_name, long long bubble_dist);
|
||||
|
||||
|
||||
#define asg_arc_len(arc) ((uint32_t)(arc).ul)
|
||||
#define asg_arc_n(g, v) ((uint32_t)(g)->idx[(v)])
|
||||
#define asg_arc_a(g, v) (&(g)->arc[(g)->idx[(v)]>>32])
|
||||
|
||||
// append an arc
|
||||
static inline asg_arc_t *asg_arc_pushp(asg_t *g)
|
||||
{
|
||||
if (g->n_arc == g->m_arc) {
|
||||
g->m_arc = g->m_arc? g->m_arc<<1 : 16;
|
||||
g->arc = (asg_arc_t*)realloc(g->arc, g->m_arc * sizeof(asg_arc_t));
|
||||
}
|
||||
return &g->arc[g->n_arc++];
|
||||
}
|
||||
|
||||
// set asg_arc_t::del for v->w
|
||||
static inline void asg_arc_del(asg_t *g, uint32_t v, uint32_t w, int del)
|
||||
{
|
||||
uint32_t i, nv = asg_arc_n(g, v);
|
||||
asg_arc_t *av = asg_arc_a(g, v);
|
||||
for (i = 0; i < nv; ++i)
|
||||
if (av[i].v == w) av[i].del = !!del;
|
||||
}
|
||||
|
||||
// set asg_arc_t::del and asg_seq_t::del to 1 for sequence s and all its associated arcs
|
||||
static inline void asg_seq_del(asg_t *g, uint32_t s)
|
||||
{
|
||||
uint32_t k;
|
||||
g->seq[s].del = 1;
|
||||
for (k = 0; k < 2; ++k) {
|
||||
uint32_t i, v = s<<1 | k;
|
||||
uint32_t nv = asg_arc_n(g, v);
|
||||
asg_arc_t *av = asg_arc_a(g, v);
|
||||
for (i = 0; i < nv; ++i) {
|
||||
av[i].del = 1;
|
||||
asg_arc_del(g, av[i].v^1, v^1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t len:31, circ:1; // len: length of the unitig; circ: circular if non-zero
|
||||
uint32_t start, end; // start: starting vertex in the string graph; end: ending vertex
|
||||
uint32_t m, n; // number of reads
|
||||
uint64_t *a; // list of reads
|
||||
char *s; // unitig sequence is not null
|
||||
} ma_utg_t;
|
||||
|
||||
typedef struct { size_t n, m; ma_utg_t *a; } ma_utg_v;
|
||||
|
||||
typedef struct {
|
||||
ma_utg_v u;
|
||||
asg_t *g;
|
||||
} ma_ug_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t utg:31, ori:1, start, len;
|
||||
} utg_intv_t;
|
||||
|
||||
|
||||
/******************
|
||||
* Bubble popping *
|
||||
******************/
|
||||
|
||||
typedef struct {
|
||||
uint32_t p; // the optimal parent vertex
|
||||
uint32_t d; // the shortest distance from the initial vertex
|
||||
uint32_t c; // max count of reads
|
||||
uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state
|
||||
//s: state, s=0, this edge has not been visited, otherwise, s=1
|
||||
} binfo_t;
|
||||
|
||||
typedef struct {
|
||||
///all information for each node
|
||||
binfo_t *a;
|
||||
kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited
|
||||
kvec_t(uint32_t) T; // set of tips
|
||||
kvec_t(uint32_t) b; // visited vertices
|
||||
kvec_t(uint32_t) e; // visited edges/arcs
|
||||
} buf_t;
|
||||
|
||||
// count the number of outgoing arcs, including reduced arcs
|
||||
static inline int count_out_with_del(const asg_t *g, uint32_t v)
|
||||
{
|
||||
uint32_t i, n, nv = asg_arc_n(g, v);
|
||||
const asg_arc_t *av = asg_arc_a(g, v);
|
||||
/**
|
||||
for (i = n = 0; i < nv; ++i)
|
||||
if (!av[i].del) ++n;
|
||||
return n;
|
||||
**/
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
// count the number of outgoing arcs, including reduced arcs
|
||||
static inline int count_out_without_del(const asg_t *g, uint32_t v)
|
||||
{
|
||||
uint32_t i, n, nv = asg_arc_n(g, v);
|
||||
const asg_arc_t *av = asg_arc_a(g, v);
|
||||
|
||||
for (i = n = 0; i < nv; ++i)
|
||||
if (!av[i].del) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void debug_info_of_specfic_read(char* name, ma_hit_t_alloc* sources,
|
||||
ma_hit_t_alloc* reverse_sources, int id, char* fun);
|
||||
|
||||
void build_string_graph_without_clean(int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long n_read, uint64_t* readLen,
|
||||
long long mini_overlap_length, long long max_hang_length,
|
||||
long long clean_round, float min_ovlp_drop_ratio, float max_ovlp_drop_ratio,
|
||||
float corase_ovlp_drop_ratio, char* output_file_name, long long bubble_dist, int read_graph,
|
||||
int write);
|
||||
|
||||
#endif
|
||||
@@ -15,11 +15,13 @@ void init_Edge_alloc(Edge_alloc* list)
|
||||
{
|
||||
list->size = INIT_EDGE_SIZE;
|
||||
list->length = 0;
|
||||
list->delete_length = 0;
|
||||
list->list = (Edge*)malloc(sizeof(Edge)*list->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
list->length = 0;
|
||||
list->delete_length = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +29,7 @@ void init_Edge_alloc(Edge_alloc* list)
|
||||
void clear_Edge_alloc(Edge_alloc* list)
|
||||
{
|
||||
list->length = 0;
|
||||
list->delete_length = 0;
|
||||
}
|
||||
|
||||
void destory_Edge_alloc(Edge_alloc* list)
|
||||
@@ -47,17 +50,138 @@ void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, u
|
||||
list->list[list->length].weight = weight;
|
||||
list->list[list->length].length = length;
|
||||
list->list[list->length].num_insertions = 0;
|
||||
list->list[list->length].self_edge_ID = list->length;
|
||||
|
||||
list->length++;
|
||||
}
|
||||
|
||||
|
||||
int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag)
|
||||
{
|
||||
Edge* e_forward;
|
||||
Edge* e_backward;
|
||||
|
||||
//if there are no edge from in_node to out_node
|
||||
if(!get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward))
|
||||
{
|
||||
append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag);
|
||||
append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag);
|
||||
|
||||
Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID
|
||||
= Input_Edges((*out_node)).length - 1;
|
||||
|
||||
Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID
|
||||
= Output_Edges((*in_node)).length - 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else//if there is an edge from in_node to out_node, do nothing
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag)
|
||||
{
|
||||
|
||||
append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag);
|
||||
append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag);
|
||||
|
||||
Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID
|
||||
= Input_Edges((*out_node)).length - 1;
|
||||
|
||||
Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID
|
||||
= Output_Edges((*in_node)).length - 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node)
|
||||
{
|
||||
Edge* e_forward;
|
||||
Edge* e_backward;
|
||||
|
||||
//if there are no edge from in_node to out_node
|
||||
//1. remove these two edges
|
||||
//2. increase the edge_list.delete_length in both in_node and out_node
|
||||
if(get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward))
|
||||
{
|
||||
e_forward->in_node = (uint64_t)-1;
|
||||
e_forward->out_node = (uint64_t)-1;
|
||||
e_forward->weight = (uint64_t)-1;
|
||||
e_forward->length = (uint64_t)-1;
|
||||
e_forward->num_insertions = (uint64_t)-1;
|
||||
e_forward->self_edge_ID = (uint64_t)-1;
|
||||
e_forward->reverse_edge_ID = (uint64_t)-1;
|
||||
|
||||
|
||||
e_backward->in_node = (uint64_t)-1;
|
||||
e_backward->out_node = (uint64_t)-1;
|
||||
e_backward->weight = (uint64_t)-1;
|
||||
e_backward->length = (uint64_t)-1;
|
||||
e_backward->num_insertions = (uint64_t)-1;
|
||||
e_backward->self_edge_ID = (uint64_t)-1;
|
||||
e_backward->reverse_edge_ID = (uint64_t)-1;
|
||||
|
||||
Output_Edges(*in_node).delete_length++;
|
||||
Input_Edges((*out_node)).delete_length++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else//if there is an edge from in_node to out_node, do nothing
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e)
|
||||
{
|
||||
Edge* e_forward;
|
||||
Edge* e_backward;
|
||||
|
||||
if(If_Edge_Exist(*e))
|
||||
{
|
||||
get_bi_direction_edges(graph, e, &e_forward, &e_backward);
|
||||
Output_Edges(G_Node(*graph, e_forward->in_node)).delete_length++;
|
||||
Input_Edges(G_Node(*graph, e_forward->out_node)).delete_length++;
|
||||
|
||||
e_forward->in_node = (uint64_t)-1;
|
||||
e_forward->out_node = (uint64_t)-1;
|
||||
e_forward->weight = (uint64_t)-1;
|
||||
e_forward->length = (uint64_t)-1;
|
||||
e_forward->num_insertions = (uint64_t)-1;
|
||||
e_forward->self_edge_ID = (uint64_t)-1;
|
||||
e_forward->reverse_edge_ID = (uint64_t)-1;
|
||||
|
||||
|
||||
e_backward->in_node = (uint64_t)-1;
|
||||
e_backward->out_node = (uint64_t)-1;
|
||||
e_backward->weight = (uint64_t)-1;
|
||||
e_backward->length = (uint64_t)-1;
|
||||
e_backward->num_insertions = (uint64_t)-1;
|
||||
e_backward->self_edge_ID = (uint64_t)-1;
|
||||
e_backward->reverse_edge_ID = (uint64_t)-1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init_Node_alloc(Node_alloc* list)
|
||||
{
|
||||
list->size = INIT_NODE_SIZE;
|
||||
list->length = 0;
|
||||
list->delete_length = 0;
|
||||
list->list = (Node*)malloc(sizeof(Node)*list->size);
|
||||
list->sort.size = 0;
|
||||
list->sort.list = NULL;
|
||||
@@ -105,6 +229,7 @@ void clear_Node_alloc(Node_alloc* list)
|
||||
}
|
||||
|
||||
list->length = 0;
|
||||
list->delete_length = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,11 +287,14 @@ void init_Graph(Graph* g)
|
||||
g->s_start_nodeID = 0;
|
||||
g->seq = NULL;
|
||||
g->seqID = (uint64_t)-1;
|
||||
|
||||
init_Queue(&(g->node_q));
|
||||
}
|
||||
|
||||
void destory_Graph(Graph* g)
|
||||
{
|
||||
destory_Node_alloc(&g->g_nodes);
|
||||
destory_Queue(&(g->node_q));
|
||||
}
|
||||
|
||||
void clear_Graph(Graph* g)
|
||||
@@ -180,6 +308,8 @@ void clear_Graph(Graph* g)
|
||||
g->s_start_nodeID = 0;
|
||||
g->seq = NULL;
|
||||
g->seqID = (uint64_t)-1;
|
||||
|
||||
clear_Queue(&(g->node_q));
|
||||
}
|
||||
|
||||
|
||||
@@ -237,6 +367,282 @@ void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length,
|
||||
|
||||
|
||||
|
||||
inline void add_insertionEdge_weight_print(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);
|
||||
|
||||
/******************************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;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "###insert_length: %d\n", insert_length);
|
||||
|
||||
///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*************************/
|
||||
|
||||
fprintf(stderr, "###not homopolymer: %d\n", insert_length);
|
||||
|
||||
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]);
|
||||
fprintf(stderr, "edgeID[0]: %d, length: %d\n", edgeID, edge->list[edgeID].length);
|
||||
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);
|
||||
}
|
||||
|
||||
fprintf(stderr, "edge->length: %d\n", edge->length);
|
||||
|
||||
/*******************第0个字符********************* */
|
||||
|
||||
/*******************第1个字符********************* */
|
||||
if (insert[1] != insert[0])
|
||||
{
|
||||
edgeID = getEdge(g, edge, 1, insert[1]);
|
||||
fprintf(stderr, "edgeID[1]: %d, length: %d\n", edgeID, edge->list[edgeID].length);
|
||||
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);
|
||||
}
|
||||
|
||||
fprintf(stderr, "edge->length: %d\n", edge->length);
|
||||
}
|
||||
/*******************第1个字符********************* */
|
||||
|
||||
/**********************两个字符******************* */
|
||||
|
||||
edgeID = get_insertion_Edges(g, edge, 2, insert);
|
||||
fprintf(stderr, "edgeID[len2]: %d, length: %d\n", edgeID, edge->list[edgeID].length);
|
||||
if (edgeID != -1)
|
||||
{
|
||||
///这条路均只有一个出度
|
||||
edge->list[edgeID].weight++;
|
||||
}
|
||||
else
|
||||
{
|
||||
create_insertion_Edges(g, alignNodeID, insert_length, insert);
|
||||
}
|
||||
|
||||
fprintf(stderr, "edge->length: %d\n", edge->length);
|
||||
|
||||
for (i = 0; i < edge->length; i++)
|
||||
{
|
||||
fprintf(stderr, "edgeID[%d].length: %d\n", i, edge->list[i].length);
|
||||
}
|
||||
|
||||
|
||||
/**********************两个字符******************* */
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
fprintf(stderr,"*******\n");
|
||||
///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];
|
||||
|
||||
// fprintf(stderr, "operation: %d, operationLen: %d\n",
|
||||
// operation, operationLen);
|
||||
|
||||
///这种情况代表匹配和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_print(backbone, currentNodeID, y_string + y_i, operationLen);
|
||||
backbone->g_nodes.list[currentNodeID].num_insertions++;
|
||||
}
|
||||
|
||||
///fprintf(stderr, "y_string: %.*s\n", operationLen, y_string+y_i);
|
||||
y_i += operationLen;
|
||||
}
|
||||
else if (operation == 3)
|
||||
{
|
||||
///3是y缺字符(x多字符),也就是backbone多字符
|
||||
///这个相当于在backbone对应字符处变成了‘——’
|
||||
///因此可以用mismatch类似的方法处理
|
||||
///if (operationLen <= CORRECT_INDEL_LENGTH)
|
||||
{
|
||||
///add_deletion_to_backbone(backbone, ¤tNodeID, 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);
|
||||
}
|
||||
**/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -311,28 +717,6 @@ void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_stri
|
||||
|
||||
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);
|
||||
}
|
||||
**/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
+84
-12
@@ -74,9 +74,10 @@ void destory_All_reads(All_reads* r)
|
||||
void write_All_reads(All_reads* r, char* read_file_name)
|
||||
{
|
||||
fprintf(stdout, "Writing reads to disk ...... \n");
|
||||
char* index_name = (char*)malloc(strlen(read_file_name)+5);
|
||||
char* index_name = (char*)malloc(strlen(read_file_name)+15);
|
||||
sprintf(index_name, "%s.bin", read_file_name);
|
||||
FILE* fp = fopen(index_name, "w");
|
||||
fwrite(&adapterLen, sizeof(adapterLen), 1, fp);
|
||||
fwrite(&r->index_size, sizeof(r->index_size), 1, fp);
|
||||
fwrite(&r->name_index_size, sizeof(r->name_index_size), 1, fp);
|
||||
fwrite(&r->total_reads, sizeof(r->total_reads), 1, fp);
|
||||
@@ -127,6 +128,7 @@ void write_All_reads(All_reads* r, char* read_file_name)
|
||||
|
||||
|
||||
free(index_name);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
fprintf(stdout, "Reads has been written.\n");
|
||||
}
|
||||
@@ -136,7 +138,7 @@ void write_All_reads(All_reads* r, char* read_file_name)
|
||||
int load_All_reads(All_reads* r, char* read_file_name)
|
||||
{
|
||||
fprintf(stdout, "Loading reads to disk ...... \n");
|
||||
char* index_name = (char*)malloc(strlen(read_file_name)+5);
|
||||
char* index_name = (char*)malloc(strlen(read_file_name)+15);
|
||||
sprintf(index_name, "%s.bin", read_file_name);
|
||||
FILE* fp = fopen(index_name, "r");
|
||||
if (!fp)
|
||||
@@ -144,7 +146,14 @@ int load_All_reads(All_reads* r, char* read_file_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int local_adapterLen;
|
||||
fread(&local_adapterLen, sizeof(local_adapterLen), 1, fp);
|
||||
if(local_adapterLen != adapterLen)
|
||||
{
|
||||
fprintf(stdout, "the adapterLen of index is: %d, but the adapterLen set by user is: %d\n",
|
||||
local_adapterLen, adapterLen);
|
||||
exit(1);
|
||||
}
|
||||
fread(&r->index_size, sizeof(r->index_size), 1, fp);
|
||||
fread(&r->name_index_size, sizeof(r->name_index_size), 1, fp);
|
||||
fread(&r->total_reads, sizeof(r->total_reads), 1, fp);
|
||||
@@ -210,6 +219,8 @@ int load_All_reads(All_reads* r, char* read_file_name)
|
||||
|
||||
r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads);
|
||||
r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads);
|
||||
r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads);
|
||||
r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads);
|
||||
for (i = 0; i < r->total_reads; i++)
|
||||
{
|
||||
r->second_round_cigar[i].size = r->cigars[i].size = 0;
|
||||
@@ -219,9 +230,14 @@ int load_All_reads(All_reads* r, char* read_file_name)
|
||||
r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0;
|
||||
r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0;
|
||||
r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL;
|
||||
init_ma_hit_t_alloc(&(r->paf[i]));
|
||||
init_ma_hit_t_alloc(&(r->reverse_paf[i]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
free(index_name);
|
||||
fclose(fp);
|
||||
fprintf(stdout, "Reads has been loaded.\n");
|
||||
@@ -279,6 +295,8 @@ void malloc_All_reads(All_reads* r)
|
||||
|
||||
r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads);
|
||||
r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads);
|
||||
r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads);
|
||||
r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads);
|
||||
for (i = 0; i < r->total_reads; i++)
|
||||
{
|
||||
r->second_round_cigar[i].size = r->cigars[i].size = 0;
|
||||
@@ -288,9 +306,19 @@ void malloc_All_reads(All_reads* r)
|
||||
r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0;
|
||||
r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0;
|
||||
r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL;
|
||||
init_ma_hit_t_alloc(&(r->paf[i]));
|
||||
init_ma_hit_t_alloc(&(r->reverse_paf[i]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
r->name = (char*)malloc(sizeof(char)*r->total_name_length);
|
||||
r->N_site = (uint64_t**)calloc(r->total_reads, sizeof(uint64_t*));
|
||||
|
||||
@@ -658,21 +686,47 @@ void compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_l
|
||||
|
||||
while (i + 4 <= src_l)
|
||||
{
|
||||
|
||||
// fprintf(stderr, "0 i: %d, dest_i: %d, src_l: %d\n",
|
||||
// i, dest_i, src_l);
|
||||
// fflush(stderr);
|
||||
|
||||
tmp = 0;
|
||||
|
||||
COMPRESS_BASE;
|
||||
tmp = tmp | (c<<6);
|
||||
|
||||
// fprintf(stderr, "*******1******1 i: %d, tmp: %d, c: %d\n",
|
||||
// i, tmp, c);
|
||||
// fflush(stderr);
|
||||
|
||||
COMPRESS_BASE;
|
||||
tmp = tmp | (c<<4);
|
||||
|
||||
// fprintf(stderr, "*******2******1 i: %d, tmp: %d, c: %d\n",
|
||||
// i, tmp, c);
|
||||
// fflush(stderr);
|
||||
|
||||
COMPRESS_BASE;
|
||||
tmp = tmp | (c<<2);
|
||||
|
||||
// fprintf(stderr, "*******3******1 i: %d, tmp: %d, c: %d\n",
|
||||
// i, tmp, c);
|
||||
// fflush(stderr);
|
||||
|
||||
COMPRESS_BASE;
|
||||
tmp = tmp | c;
|
||||
|
||||
// fprintf(stderr, "*******4******1 i: %d, tmp: %d, c: %d\n",
|
||||
// i, tmp, c);
|
||||
// fflush(stderr);
|
||||
|
||||
dest[dest_i] = tmp;
|
||||
|
||||
// fprintf(stderr, "2 i: %d, dest_i: %d, src_l: %d\n",
|
||||
// i, dest_i, src_l);
|
||||
// fflush(stderr);
|
||||
|
||||
dest_i++;
|
||||
}
|
||||
|
||||
@@ -716,7 +770,7 @@ inline void exchage_kstring_t(kstring_t* a, kstring_t* b)
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
int get_read(kseq_t *s)
|
||||
int get_read(kseq_t *s, int adapterLen)
|
||||
{
|
||||
int l;
|
||||
|
||||
@@ -727,6 +781,24 @@ int get_read(kseq_t *s)
|
||||
exchage_kstring_t(&seq->name, &s->name);
|
||||
exchage_kstring_t(&seq->qual, &s->qual);
|
||||
exchage_kstring_t(&seq->seq, &s->seq);
|
||||
|
||||
if(adapterLen > 0)
|
||||
{
|
||||
if(s->seq.l <= adapterLen*2)
|
||||
{
|
||||
s->seq.l = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
long long i;
|
||||
for (i = 0; i < (s->seq.l - adapterLen*2); i++)
|
||||
{
|
||||
s->seq.s[i] = s->seq.s[i + adapterLen];
|
||||
}
|
||||
s->seq.l -= adapterLen*2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -770,8 +842,8 @@ void init_R_buffer(int thread_num)
|
||||
|
||||
void destory_R_buffer_block(R_buffer_block* curr_sub_block)
|
||||
{
|
||||
|
||||
free(curr_sub_block->read);
|
||||
kseq_destroy(curr_sub_block->read);
|
||||
///free(curr_sub_block->read);
|
||||
}
|
||||
|
||||
|
||||
@@ -790,7 +862,7 @@ void destory_R_buffer()
|
||||
|
||||
|
||||
inline void load_read_block(R_buffer_block* read_batch, int batch_read_size,
|
||||
int* return_file_flag, int is_insert)
|
||||
int* return_file_flag, int is_insert, int adapterLen)
|
||||
{
|
||||
int inner_i = 0;
|
||||
int file_flag = 1;
|
||||
@@ -801,18 +873,18 @@ inline void load_read_block(R_buffer_block* read_batch, int batch_read_size,
|
||||
while (inner_i<batch_read_size)
|
||||
{
|
||||
|
||||
file_flag = get_read(&read_batch->read[inner_i]);
|
||||
file_flag = get_read(&read_batch->read[inner_i], adapterLen);
|
||||
|
||||
if (file_flag == 1)
|
||||
{
|
||||
read_batch->read[inner_i].ID = total_reads;
|
||||
total_reads++;
|
||||
|
||||
///fprintf(stderr, "is_insert: %d\n", is_insert);
|
||||
|
||||
if (is_insert)
|
||||
{
|
||||
insert_read(&R_INF, &read_batch->read[inner_i].seq, &read_batch->read[inner_i].name);
|
||||
insert_read(&R_INF, &read_batch->read[inner_i].seq,
|
||||
&read_batch->read[inner_i].name);
|
||||
}
|
||||
|
||||
inner_i++;
|
||||
@@ -896,7 +968,7 @@ void* input_reads_muti_threads(void* arg)
|
||||
|
||||
|
||||
|
||||
load_read_block(&tmp_buf, RDB.block_inner_size, &file_flag, is_insert);
|
||||
load_read_block(&tmp_buf, RDB.block_inner_size, &file_flag, is_insert, adapterLen);
|
||||
|
||||
if (file_flag == 0)
|
||||
{
|
||||
@@ -1022,7 +1094,7 @@ void Counting_block()
|
||||
|
||||
|
||||
load_read_block(&tmp_buf, RDB.block_inner_size,
|
||||
&file_flag, 0);
|
||||
&file_flag, 0, adapterLen);
|
||||
|
||||
|
||||
if (file_flag == 0)
|
||||
|
||||
+61
-5
@@ -6,6 +6,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "kseq.h"
|
||||
#include "Overlaps.h"
|
||||
#include "CommandLines.h"
|
||||
///#include "Hash_Table.h"
|
||||
|
||||
#define READ_INIT_NUMBER 1000
|
||||
|
||||
@@ -15,11 +18,11 @@
|
||||
#define IS_FULL(buffer) ((buffer.num >= buffer.size)?1:0)
|
||||
#define IS_EMPTY(buffer) ((buffer.num == 0)?1:0)
|
||||
///#define Get_READ_LENGTH(R_INF, ID) (R_INF.index[ID+1] - R_INF.index[ID])
|
||||
#define Get_READ_LENGTH(R_INF, ID) R_INF.read_length[ID]
|
||||
#define Get_NAME_LENGTH(R_INF, ID) (R_INF.name_index[ID+1] - R_INF.name_index[ID])
|
||||
#define Get_READ_LENGTH(R_INF, ID) R_INF.read_length[(ID)]
|
||||
#define Get_NAME_LENGTH(R_INF, ID) (R_INF.name_index[(ID)+1] - R_INF.name_index[(ID)])
|
||||
///#define Get_READ(R_INF, ID) R_INF.read + (R_INF.index[ID]>>2) + ID
|
||||
#define Get_READ(R_INF, ID) R_INF.read_sperate[ID]
|
||||
#define Get_NAME(R_INF, ID) R_INF.name + R_INF.name_index[ID]
|
||||
#define Get_READ(R_INF, ID) R_INF.read_sperate[(ID)]
|
||||
#define Get_NAME(R_INF, ID) R_INF.name + R_INF.name_index[(ID)]
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +59,56 @@ static char rc_Table[5] = {'T', 'G', 'C', 'A', 'N'};
|
||||
|
||||
void init_kseq(char* file);
|
||||
void destory_kseq();
|
||||
int get_read(kseq_t *s);
|
||||
int get_read(kseq_t *s, int adapterLen);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t x_id;
|
||||
uint64_t x_pos_s;
|
||||
uint64_t x_pos_e;
|
||||
uint8_t x_pos_strand;
|
||||
|
||||
uint64_t y_id;
|
||||
uint64_t y_pos_s;
|
||||
uint64_t y_pos_e;
|
||||
uint8_t y_pos_strand;
|
||||
|
||||
uint64_t matchLen;
|
||||
uint64_t totalLen;
|
||||
|
||||
} PAF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PAF* list;
|
||||
uint64_t size;
|
||||
uint64_t length;
|
||||
} PAF_alloc;
|
||||
|
||||
|
||||
inline void init_PAF_alloc(PAF_alloc* list)
|
||||
{
|
||||
list->size = 15;
|
||||
list->length = 0;
|
||||
list->list = (PAF*)malloc(sizeof(PAF)*list->size);
|
||||
}
|
||||
|
||||
|
||||
inline void append_PAF_alloc(PAF_alloc* list, PAF* e)
|
||||
{
|
||||
if(list->length+1 > list->size)
|
||||
{
|
||||
list->size = list->size * 2;
|
||||
list->list = (PAF*)realloc(list->list, sizeof(PAF)*list->size);
|
||||
}
|
||||
|
||||
list->list[list->length] = (*e);
|
||||
list->length++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -100,6 +152,10 @@ typedef struct
|
||||
Compressed_Cigar_record* cigars;
|
||||
Compressed_Cigar_record* second_round_cigar;
|
||||
|
||||
ma_hit_t_alloc* paf;
|
||||
ma_hit_t_alloc* reverse_paf;
|
||||
ma_sub_t* coverage_cut;
|
||||
|
||||
} All_reads;
|
||||
|
||||
extern All_reads R_INF;
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#ifndef __AC_KDQ_H
|
||||
#define __AC_KDQ_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __KDQ_TYPE(type) \
|
||||
typedef struct { \
|
||||
size_t front:58, bits:6, count, mask; \
|
||||
type *a; \
|
||||
} kdq_##type##_t;
|
||||
|
||||
#define kdq_t(type) kdq_##type##_t
|
||||
#define kdq_size(q) ((q)->count)
|
||||
#define kdq_first(q) ((q)->a[(q)->front])
|
||||
#define kdq_last(q) ((q)->a[((q)->front + (q)->count - 1) & (q)->mask])
|
||||
#define kdq_at(q, i) ((q)->a[((q)->front + (i)) & (q)->mask])
|
||||
|
||||
#define __KDQ_IMPL(type, SCOPE) \
|
||||
SCOPE kdq_##type##_t *kdq_init_##type() \
|
||||
{ \
|
||||
kdq_##type##_t *q; \
|
||||
q = (kdq_##type##_t*)calloc(1, sizeof(kdq_##type##_t)); \
|
||||
q->bits = 2, q->mask = (1ULL<<q->bits) - 1; \
|
||||
q->a = (type*)malloc((1<<q->bits) * sizeof(type)); \
|
||||
return q; \
|
||||
} \
|
||||
SCOPE void kdq_destroy_##type(kdq_##type##_t *q) \
|
||||
{ \
|
||||
if (q == 0) return; \
|
||||
free(q->a); free(q); \
|
||||
} \
|
||||
SCOPE int kdq_resize_##type(kdq_##type##_t *q, int new_bits) \
|
||||
{ \
|
||||
size_t new_size = 1ULL<<new_bits, old_size = 1ULL<<q->bits; \
|
||||
if (new_size < q->count) { /* not big enough */ \
|
||||
int i; \
|
||||
for (i = 0; i < 64; ++i) \
|
||||
if (1ULL<<i > q->count) break; \
|
||||
new_bits = i, new_size = 1ULL<<new_bits; \
|
||||
} \
|
||||
if (new_bits == q->bits) return q->bits; /* unchanged */ \
|
||||
if (new_bits > q->bits) q->a = (type*)realloc(q->a, (1ULL<<new_bits) * sizeof(type)); \
|
||||
if (q->front + q->count <= old_size) { /* unwrapped */ \
|
||||
if (q->front + q->count > new_size) /* only happens for shrinking */ \
|
||||
memmove(q->a, q->a + new_size, (q->front + q->count - new_size) * sizeof(type)); \
|
||||
} else { /* wrapped */ \
|
||||
memmove(q->a + (new_size - (old_size - q->front)), q->a + q->front, (old_size - q->front) * sizeof(type)); \
|
||||
q->front = new_size - (old_size - q->front); \
|
||||
} \
|
||||
q->bits = new_bits, q->mask = (1ULL<<q->bits) - 1; \
|
||||
if (new_bits < q->bits) q->a = (type*)realloc(q->a, (1ULL<<new_bits) * sizeof(type)); \
|
||||
return q->bits; \
|
||||
} \
|
||||
SCOPE type *kdq_pushp_##type(kdq_##type##_t *q) \
|
||||
{ \
|
||||
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
|
||||
return &q->a[((q->count++) + q->front) & (q)->mask]; \
|
||||
} \
|
||||
SCOPE void kdq_push_##type(kdq_##type##_t *q, type v) \
|
||||
{ \
|
||||
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
|
||||
q->a[((q->count++) + q->front) & (q)->mask] = v; \
|
||||
} \
|
||||
SCOPE type *kdq_unshiftp_##type(kdq_##type##_t *q) \
|
||||
{ \
|
||||
if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
|
||||
++q->count; \
|
||||
q->front = q->front? q->front - 1 : (1ULL<<q->bits) - 1; \
|
||||
return &q->a[q->front]; \
|
||||
} \
|
||||
SCOPE void kdq_unshift_##type(kdq_##type##_t *q, type v) \
|
||||
{ \
|
||||
type *p; \
|
||||
p = kdq_unshiftp_##type(q); \
|
||||
*p = v; \
|
||||
} \
|
||||
SCOPE type *kdq_pop_##type(kdq_##type##_t *q) \
|
||||
{ \
|
||||
return q->count? &q->a[((--q->count) + q->front) & q->mask] : 0; \
|
||||
} \
|
||||
SCOPE type *kdq_shift_##type(kdq_##type##_t *q) \
|
||||
{ \
|
||||
type *d = 0; \
|
||||
if (q->count == 0) return 0; \
|
||||
d = &q->a[q->front++]; \
|
||||
q->front &= q->mask; \
|
||||
--q->count; \
|
||||
return d; \
|
||||
}
|
||||
|
||||
#define KDQ_INIT2(type, SCOPE) \
|
||||
__KDQ_TYPE(type) \
|
||||
__KDQ_IMPL(type, SCOPE)
|
||||
|
||||
#ifndef klib_unused
|
||||
#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
|
||||
#define klib_unused __attribute__ ((__unused__))
|
||||
#else
|
||||
#define klib_unused
|
||||
#endif
|
||||
#endif /* klib_unused */
|
||||
|
||||
#define KDQ_INIT(type) KDQ_INIT2(type, static inline klib_unused)
|
||||
|
||||
#define KDQ_DECLARE(type) \
|
||||
__KDQ_TYPE(type) \
|
||||
kdq_##type##_t *kdq_init_##type(); \
|
||||
void kdq_destroy_##type(kdq_##type##_t *q); \
|
||||
int kdq_resize_##type(kdq_##type##_t *q, int new_bits); \
|
||||
type *kdq_pushp_##type(kdq_##type##_t *q); \
|
||||
void kdq_push_##type(kdq_##type##_t *q, type v); \
|
||||
type *kdq_unshiftp_##type(kdq_##type##_t *q); \
|
||||
void kdq_unshift_##type(kdq_##type##_t *q, type v); \
|
||||
type *kdq_pop_##type(kdq_##type##_t *q); \
|
||||
type *kdq_shift_##type(kdq_##type##_t *q);
|
||||
|
||||
#define kdq_init(type) kdq_init_##type()
|
||||
#define kdq_destroy(type, q) kdq_destroy_##type(q)
|
||||
#define kdq_resize(type, q, new_bits) kdq_resize_##type(q, new_bits)
|
||||
#define kdq_pushp(type, q) kdq_pushp_##type(q)
|
||||
#define kdq_push(type, q, v) kdq_push_##type(q, v)
|
||||
#define kdq_pop(type, q) kdq_pop_##type(q)
|
||||
#define kdq_unshiftp(type, q) kdq_unshiftp_##type(q)
|
||||
#define kdq_unshift(type, q, v) kdq_unshift_##type(q, v)
|
||||
#define kdq_shift(type, q) kdq_shift_##type(q)
|
||||
|
||||
#endif
|
||||
@@ -209,8 +209,8 @@ static const double __ac_HASH_UPPER = 0.77;
|
||||
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
|
||||
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
|
||||
extern void kh_del_##name(kh_##name##_t *h, khint_t x);\
|
||||
extern void kh_write_##name(kh_##name##_t *h, FILE* fp)\
|
||||
extern void kh_load_##name(kh_##name##_t *h, FILE* fp)
|
||||
extern void kh_write_##name(kh_##name##_t *h, FILE* fp);\
|
||||
extern void kh_load_##name(kh_##name##_t *h, FILE* fp);
|
||||
|
||||
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
SCOPE kh_##name##_t *kh_init_##name(void) { \
|
||||
|
||||
@@ -14,4 +14,182 @@ void init_Hash_code(Hash_code* code)
|
||||
{
|
||||
code->x[0] = 0;
|
||||
code->x[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init_small_hash_table(small_hash_table* x)
|
||||
{
|
||||
x->size = 0;
|
||||
x->buffer = NULL;
|
||||
x->length = 0;
|
||||
}
|
||||
|
||||
void clear_small_hash_table(small_hash_table* x)
|
||||
{
|
||||
x->length = 0;
|
||||
}
|
||||
|
||||
void resize_small_hash_table(small_hash_table* x, uint64_t size)
|
||||
{
|
||||
if(size > x->size)
|
||||
{
|
||||
x->size = size;
|
||||
x->buffer = (k_v*)realloc(x->buffer, x->size*sizeof(k_v));
|
||||
}
|
||||
}
|
||||
|
||||
void destory_small_hash_table(small_hash_table* x)
|
||||
{
|
||||
free(x->buffer);
|
||||
}
|
||||
|
||||
|
||||
void add_small_hash_table(small_hash_table* x, k_v* element)
|
||||
{
|
||||
if(x->length + 1 > x->size)
|
||||
{
|
||||
x->size = (x->length + 1) * 2;
|
||||
x->buffer = (k_v*)realloc(x->buffer, x->size*sizeof(k_v));
|
||||
}
|
||||
|
||||
x->buffer[x->length] = (*element);
|
||||
x->length++;
|
||||
}
|
||||
|
||||
//x > y, return 1; x < y, return -1, x == y, return 0
|
||||
int compare_k_mer(k_v* x, k_v* y)
|
||||
{
|
||||
if(x->key.x[1] != y->key.x[1])
|
||||
{
|
||||
return x->key.x[1] > y->key.x[1] ? 1: -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(x->key.x[0] != y->key.x[0])
|
||||
{
|
||||
return x->key.x[0] > y->key.x[0] ? 1: -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int cmp_k_mer_kv(const void * a, const void * b)
|
||||
{
|
||||
int flag = compare_k_mer((k_v*)a, (k_v*)b);
|
||||
|
||||
if(flag == 0)
|
||||
{
|
||||
if ((*(k_v*)a).value != (*(k_v*)b).value)
|
||||
{
|
||||
return (*(k_v*)a).value > (*(k_v*)b).value ? 1: -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
void sort_small_hash_table(small_hash_table* x)
|
||||
{
|
||||
qsort(x->buffer, x->length, sizeof(k_v), cmp_k_mer_kv);
|
||||
}
|
||||
|
||||
|
||||
inline long long firstEqual(k_v* arr, long long arrLen, k_v* key)
|
||||
{
|
||||
long long L = 0, R = arrLen - 1; //[L, R]
|
||||
long long mid;
|
||||
int flag;
|
||||
while( L <= R)
|
||||
{
|
||||
mid = L + (R - L)/2;
|
||||
|
||||
flag = compare_k_mer(&(arr[mid]), key);
|
||||
|
||||
///arr[mid] >= key
|
||||
if(flag >= 0)
|
||||
{
|
||||
R = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
L = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(L < arrLen && (flag = compare_k_mer(&(arr[L]), key) == 0))
|
||||
{
|
||||
return L;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline long long lastEqual(k_v* arr, long long arrLen, k_v* key)
|
||||
{
|
||||
long long L = 0, R = arrLen - 1; //[L, R]
|
||||
long long mid;
|
||||
int flag;
|
||||
while( L <= R)
|
||||
{
|
||||
mid = L + (R - L)/2;
|
||||
flag = compare_k_mer(&(arr[mid]), key);
|
||||
///arr[mid] <= key
|
||||
if(flag <= 0)
|
||||
{
|
||||
L = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
R = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(R >= 0 && ((flag = compare_k_mer(&(arr[R]), key)) == 0))
|
||||
{
|
||||
return R;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int query_small_hash_table(small_hash_table* target, k_v* query, long long* l_end, long long* r_end)
|
||||
{
|
||||
(*l_end) = -1;
|
||||
(*r_end) = -1;
|
||||
long long left_end;
|
||||
long long right_end;
|
||||
|
||||
left_end = firstEqual(target->buffer, target->length, query);
|
||||
|
||||
if(left_end != -1)
|
||||
{
|
||||
right_end = lastEqual(target->buffer + left_end, target->length - left_end, query) + left_end;
|
||||
|
||||
(*l_end) = left_end;
|
||||
(*r_end) = right_end;
|
||||
|
||||
if(right_end == -1)
|
||||
{
|
||||
fprintf(stderr, "error\n");
|
||||
}
|
||||
|
||||
|
||||
return right_end - left_end + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,25 @@ typedef struct
|
||||
|
||||
} Hash_code;
|
||||
|
||||
typedef struct {
|
||||
Hash_code key; ///k-mer itself
|
||||
uint64_t value; ///offset
|
||||
} k_v;
|
||||
|
||||
typedef struct {
|
||||
k_v* buffer;
|
||||
uint32_t size;
|
||||
uint32_t length;
|
||||
} small_hash_table;
|
||||
|
||||
void init_small_hash_table(small_hash_table* x);
|
||||
void clear_small_hash_table(small_hash_table* x);
|
||||
void resize_small_hash_table(small_hash_table* x, uint64_t size);
|
||||
void destory_small_hash_table(small_hash_table* x);
|
||||
void add_small_hash_table(small_hash_table* x, k_v* element);
|
||||
void sort_small_hash_table(small_hash_table* x);
|
||||
int compare_k_mer(k_v* x, k_v* y);
|
||||
int query_small_hash_table(small_hash_table* target, k_v* query, long long* l_end, long long* r_end);
|
||||
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2008, 2011 Attractive Chaos <attractor@live.co.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// This is a simplified version of ksort.h
|
||||
|
||||
#ifndef AC_KSORT_H
|
||||
#define AC_KSORT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
void *left, *right;
|
||||
int depth;
|
||||
} ks_isort_stack_t;
|
||||
|
||||
#define member_size(type, member) sizeof(((type *)0)->member)
|
||||
|
||||
#define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; }
|
||||
|
||||
#define KSORT_INIT(name, type_t, __sort_lt) \
|
||||
static inline void __ks_insertsort_##name(type_t *s, type_t *t) \
|
||||
{ \
|
||||
type_t *i, *j, swap_tmp; \
|
||||
for (i = s + 1; i < t; ++i) \
|
||||
for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \
|
||||
swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \
|
||||
} \
|
||||
} \
|
||||
void ks_combsort_##name(size_t n, type_t a[]) \
|
||||
{ \
|
||||
const double shrink_factor = 1.2473309501039786540366528676643; \
|
||||
int do_swap; \
|
||||
size_t gap = n; \
|
||||
type_t tmp, *i, *j; \
|
||||
do { \
|
||||
if (gap > 2) { \
|
||||
gap = (size_t)(gap / shrink_factor); \
|
||||
if (gap == 9 || gap == 10) gap = 11; \
|
||||
} \
|
||||
do_swap = 0; \
|
||||
for (i = a; i < a + n - gap; ++i) { \
|
||||
j = i + gap; \
|
||||
if (__sort_lt(*j, *i)) { \
|
||||
tmp = *i; *i = *j; *j = tmp; \
|
||||
do_swap = 1; \
|
||||
} \
|
||||
} \
|
||||
} while (do_swap || gap > 2); \
|
||||
if (gap != 1) __ks_insertsort_##name(a, a + n); \
|
||||
} \
|
||||
void ks_introsort_##name(size_t n, type_t a[]) \
|
||||
{ \
|
||||
int d; \
|
||||
ks_isort_stack_t *top, *stack; \
|
||||
type_t rp, swap_tmp; \
|
||||
type_t *s, *t, *i, *j, *k; \
|
||||
\
|
||||
if (n < 1) return; \
|
||||
else if (n == 2) { \
|
||||
if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \
|
||||
return; \
|
||||
} \
|
||||
for (d = 2; 1ul<<d < n; ++d); \
|
||||
stack = (ks_isort_stack_t*)malloc(sizeof(ks_isort_stack_t) * ((sizeof(size_t)*d)+2)); \
|
||||
top = stack; s = a; t = a + (n-1); d <<= 1; \
|
||||
while (1) { \
|
||||
if (s < t) { \
|
||||
if (--d == 0) { \
|
||||
ks_combsort_##name(t - s + 1, s); \
|
||||
t = s; \
|
||||
continue; \
|
||||
} \
|
||||
i = s; j = t; k = i + ((j-i)>>1) + 1; \
|
||||
if (__sort_lt(*k, *i)) { \
|
||||
if (__sort_lt(*k, *j)) k = j; \
|
||||
} else k = __sort_lt(*j, *i)? i : j; \
|
||||
rp = *k; \
|
||||
if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \
|
||||
for (;;) { \
|
||||
do ++i; while (__sort_lt(*i, rp)); \
|
||||
do --j; while (i <= j && __sort_lt(rp, *j)); \
|
||||
if (j <= i) break; \
|
||||
swap_tmp = *i; *i = *j; *j = swap_tmp; \
|
||||
} \
|
||||
swap_tmp = *i; *i = *t; *t = swap_tmp; \
|
||||
if (i-s > t-i) { \
|
||||
if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \
|
||||
s = t-i > 16? i+1 : t; \
|
||||
} else { \
|
||||
if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \
|
||||
t = i-s > 16? i-1 : s; \
|
||||
} \
|
||||
} else { \
|
||||
if (top == stack) { \
|
||||
free(stack); \
|
||||
__ks_insertsort_##name(a, a+n); \
|
||||
return; \
|
||||
} else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ks_lt_generic(a, b) ((a) < (b))
|
||||
#define ks_lt_str(a, b) (strcmp((a), (b)) < 0)
|
||||
|
||||
typedef const char *ksstr_t;
|
||||
|
||||
#define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic)
|
||||
#define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str)
|
||||
|
||||
#define RS_MIN_SIZE 64
|
||||
|
||||
#define KRADIX_SORT_INIT(name, rstype_t, rskey, sizeof_key) \
|
||||
typedef struct { \
|
||||
rstype_t *b, *e; \
|
||||
} rsbucket_##name##_t; \
|
||||
void rs_insertsort_##name(rstype_t *beg, rstype_t *end) \
|
||||
{ \
|
||||
rstype_t *i; \
|
||||
for (i = beg + 1; i < end; ++i) \
|
||||
if (rskey(*i) < rskey(*(i - 1))) { \
|
||||
rstype_t *j, tmp = *i; \
|
||||
for (j = i; j > beg && rskey(tmp) < rskey(*(j-1)); --j) \
|
||||
*j = *(j - 1); \
|
||||
*j = tmp; \
|
||||
} \
|
||||
} \
|
||||
void rs_sort_##name(rstype_t *beg, rstype_t *end, int n_bits, int s) \
|
||||
{ \
|
||||
rstype_t *i; \
|
||||
int size = 1<<n_bits, m = size - 1; \
|
||||
rsbucket_##name##_t *k, b[size], *be = b + size; \
|
||||
for (k = b; k != be; ++k) k->b = k->e = beg; \
|
||||
for (i = beg; i != end; ++i) ++b[rskey(*i)>>s&m].e; \
|
||||
for (k = b + 1; k != be; ++k) \
|
||||
k->e += (k-1)->e - beg, k->b = (k-1)->e; \
|
||||
for (k = b; k != be;) { \
|
||||
if (k->b != k->e) { \
|
||||
rsbucket_##name##_t *l; \
|
||||
if ((l = b + (rskey(*k->b)>>s&m)) != k) { \
|
||||
rstype_t tmp = *k->b, swap; \
|
||||
do { \
|
||||
swap = tmp; tmp = *l->b; *l->b++ = swap; \
|
||||
l = b + (rskey(tmp)>>s&m); \
|
||||
} while (l != k); \
|
||||
*k->b++ = tmp; \
|
||||
} else ++k->b; \
|
||||
} else ++k; \
|
||||
} \
|
||||
for (b->b = beg, k = b + 1; k != be; ++k) k->b = (k-1)->e; \
|
||||
if (s) { \
|
||||
s = s > n_bits? s - n_bits : 0; \
|
||||
for (k = b; k != be; ++k) \
|
||||
if (k->e - k->b > RS_MIN_SIZE) rs_sort_##name(k->b, k->e, n_bits, s); \
|
||||
else if (k->e - k->b > 1) rs_insertsort_##name(k->b, k->e); \
|
||||
} \
|
||||
} \
|
||||
void radix_sort_##name(rstype_t *beg, rstype_t *end) \
|
||||
{ \
|
||||
if (end - beg <= RS_MIN_SIZE) rs_insertsort_##name(beg, end); \
|
||||
else rs_sort_##name(beg, end, 8, sizeof_key * 8 - 8); \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
An example:
|
||||
|
||||
#include "kvec.h"
|
||||
int main() {
|
||||
kvec_t(int) array;
|
||||
kv_init(array);
|
||||
kv_push(int, array, 10); // append
|
||||
kv_a(int, array, 20) = 5; // dynamic
|
||||
kv_A(array, 20) = 4; // static
|
||||
kv_destroy(array);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
2008-09-22 (0.1.0):
|
||||
|
||||
* The initial version.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef AC_KVEC_H
|
||||
#define AC_KVEC_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
|
||||
|
||||
#define kvec_t(type) struct { size_t n, m; type *a; }
|
||||
#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0)
|
||||
#define kv_destroy(v) free((v).a)
|
||||
#define kv_A(v, i) ((v).a[(i)])
|
||||
#define kv_pop(v) ((v).a[--(v).n])
|
||||
#define kv_size(v) ((v).n)
|
||||
#define kv_max(v) ((v).m)
|
||||
|
||||
#define kv_resize(type, v, s) do { \
|
||||
if ((v).m < (s)) { \
|
||||
(v).m = (s); \
|
||||
kv_roundup32((v).m); \
|
||||
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define kv_copy(type, v1, v0) do { \
|
||||
if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \
|
||||
(v1).n = (v0).n; \
|
||||
memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \
|
||||
} while (0) \
|
||||
|
||||
#define kv_push(type, v, x) do { \
|
||||
if ((v).n == (v).m) { \
|
||||
(v).m = (v).m? (v).m<<1 : 2; \
|
||||
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \
|
||||
} \
|
||||
(v).a[(v).n++] = (x); \
|
||||
} while (0)
|
||||
|
||||
#define kv_pushp(type, v, p) do { \
|
||||
if ((v).n == (v).m) { \
|
||||
(v).m = (v).m? (v).m<<1 : 2; \
|
||||
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \
|
||||
} \
|
||||
*(p) = &(v).a[(v).n++]; \
|
||||
} while (0)
|
||||
|
||||
#define kv_a(type, v, i) ((v).m <= (size_t)(i)? \
|
||||
((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \
|
||||
(v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \
|
||||
: (v).n <= (size_t)(i)? (v).n = (i) \
|
||||
: 0), (v).a[(i)]
|
||||
|
||||
#define kv_reverse(type, v, start) do { \
|
||||
if ((v).m > 0 && (v).n > (start)) { \
|
||||
size_t __i, __end = (v).n - (start); \
|
||||
type *__a = (v).a + (start); \
|
||||
for (__i = 0; __i < __end>>1; ++__i) { \
|
||||
type __t = __a[__end - 1 - __i]; \
|
||||
__a[__end - 1 - __i] = __a[__i]; __a[__i] = __t; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -200,12 +200,6 @@ int main(int argc, char *argv[])
|
||||
if (!CommandLine_process(argc, argv))
|
||||
return 1;
|
||||
|
||||
|
||||
/**
|
||||
debug_edit_distance();
|
||||
|
||||
return 1;
|
||||
**/
|
||||
fprintf(stdout, "Will perform %d round of error correction...\n", number_of_round);
|
||||
|
||||
fprintf(stdout, "defined k_mer_min_freq by user: %d\n", k_mer_min_freq);
|
||||
@@ -213,10 +207,21 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
fprintf(stdout, "k-mer length: %d\n",k_mer_length);
|
||||
fprintf(stdout, "coverage: %d\n",coverage);
|
||||
fprintf(stdout, "read_graph: %d\n", read_graph);
|
||||
fprintf(stdout, "adapterLen: %d\n", adapterLen);
|
||||
fflush(stdout);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(required_read_name)
|
||||
{
|
||||
fprintf(stdout, "required_read_name: %s\n", required_read_name);
|
||||
}
|
||||
|
||||
Correct_Reads(number_of_round);
|
||||
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user