Merge branch 'master' of github.com:chhylp123/hifiasm

This commit is contained in:
Heng Li
2020-04-06 08:25:21 -04:00
30 changed files with 2209 additions and 4602 deletions
+301 -1005
View File
File diff suppressed because it is too large Load Diff
+2 -4
View File
@@ -8,8 +8,6 @@
#define Get_Cigar_Type(RECORD) (RECORD&3)
#define Get_Cigar_Length(RECORD) (RECORD>>2)
void Counting_multiple_thr();
void Build_hash_table_multiple_thr();
void Overlap_calculate_multipe_thr();
void Correct_Reads(int last_round);
int ha_assemble(void);
#endif
+32 -14
View File
@@ -5,11 +5,16 @@
#include "ketopt.h"
#include <sys/time.h>
#define VERSION "0.3.0"
#define DEFAULT_OUTPUT "hifiasm.asm"
hifiasm_opt_t asm_opt;
static ko_longopt_t long_options[] = {
{ "version", ko_no_argument, 300 },
{ "dbg-gfa", ko_no_argument, 301 },
{ 0, 0, 0 }
};
double Get_T(void)
{
struct timeval t;
@@ -23,12 +28,14 @@ void Print_H(hifiasm_opt_t* asm_opt)
fprintf(stderr, "Options:\n");
fprintf(stderr, " Assembly:\n");
fprintf(stderr, " -o FILE prefix of output files [%s]\n", asm_opt->output_file_name);
///fprintf(stderr, " -c FILE file including trio information\n");
fprintf(stderr, " -t INT number of threads [%d]\n", asm_opt->thread_num);
fprintf(stderr, " -r INT round of correction [%d]\n", asm_opt->number_of_round);
fprintf(stderr, " -a INT round of assembly cleaning [%d]\n", asm_opt->clean_round);
fprintf(stderr, " -k INT k-mer length [%d] (must be < 64)\n", asm_opt->k_mer_length);
///fprintf(stderr, " -w write all overlaps to disk, can accelerate assembly next time [%d]\n", asm_opt->write_index_to_disk);
fprintf(stderr, " -k INT k-mer length (must be <64) [%d]\n", asm_opt->k_mer_length);
fprintf(stderr, " -w INT minimizer window size [%d]\n", asm_opt->mz_win);
fprintf(stderr, " -f INT number of bits for bloom filter [%d]\n", asm_opt->bf_shift);
fprintf(stderr, " -D FLOAT drop k-mers occuring >FLOAT*coverage times [%.1f]\n", asm_opt->high_factor);
fprintf(stderr, " -N INT consider up to INT overlaps for each oriented read [%d]\n", asm_opt->max_n_chain);
///fprintf(stderr, " -l load all overlaps from disk, can avoid overlap calculation [%d]\n", asm_opt->load_index_from_disk);
///fprintf(stderr, " -i ignore saved overlaps in *.ovlp*.bin files\n");
fprintf(stderr, " -i ignore saved overlaps in *.ovlp* files\n");
@@ -63,7 +70,13 @@ void init_opt(hifiasm_opt_t* asm_opt)
asm_opt->pat_index = NULL;
asm_opt->mat_index = NULL;
asm_opt->thread_num = 1;
asm_opt->k_mer_length = 40;
asm_opt->k_mer_length = 51;
asm_opt->mz_win = 51;
asm_opt->bf_shift = 37;
asm_opt->high_factor = 5.0f;
asm_opt->no_HPC = 0;
asm_opt->no_kmer_flt = 0;
asm_opt->max_n_chain = 400;
asm_opt->k_mer_min_freq = 3;
asm_opt->k_mer_max_freq = 66;
asm_opt->load_index_from_disk = 1;
@@ -71,7 +84,6 @@ void init_opt(hifiasm_opt_t* asm_opt)
asm_opt->number_of_round = 2;
asm_opt->adapterLen = 0;
asm_opt->clean_round = 4;
asm_opt->complete_threads = 0;
asm_opt->small_pop_bubble_size = 100000;
asm_opt->large_pop_bubble_size = 10000000;
asm_opt->min_drop_rate = 0.2;
@@ -84,6 +96,7 @@ void init_opt(hifiasm_opt_t* asm_opt)
asm_opt->max_short_tip = 3;
asm_opt->min_cnt = 2;
asm_opt->mid_cnt = 5;
asm_opt->verbose_gfa = 0;
}
void destory_opt(hifiasm_opt_t* asm_opt)
@@ -94,13 +107,13 @@ void destory_opt(hifiasm_opt_t* asm_opt)
}
}
void clear_opt(hifiasm_opt_t* asm_opt, int last_round)
void clear_opt(hifiasm_opt_t* asm_opt, int round)
{
asm_opt->complete_threads = 0;
asm_opt->num_bases = 0;
asm_opt->num_corrected_bases = 0;
asm_opt->num_recorrected_bases = 0;
asm_opt->roundID = asm_opt->number_of_round - last_round;
asm_opt->mem_buf = 0;
asm_opt->roundID = round;
}
int check_file(char* name, const char* opt)
@@ -295,24 +308,28 @@ int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt)
int c;
while ((c = ketopt(&opt, argc, argv, 1, "hvt:o:k:lwm:n:r:a:b:z:x:y:p:c:d:M:P:i", 0)) >= 0) {
while ((c = ketopt(&opt, argc, argv, 1, "hvt:o:k:lw:m:n:r:a:b:z:x:y:p:c:d:M:P:if:D:FN:", long_options)) >= 0) {
if (c == 'h')
{
Print_H(asm_opt);
return 0;
}
else if (c == 'v')
else if (c == 'v' || c == 300)
{
fprintf(stderr, "[Version] %s\n", VERSION);
puts(HA_VERSION);
return 0;
}
}
else if (c == 'f') asm_opt->bf_shift = atoi(opt.arg);
else if (c == 't') asm_opt->thread_num = atoi(opt.arg);
else if (c == 'o') asm_opt->output_file_name = opt.arg;
else if (c == 'r') asm_opt->number_of_round = atoi(opt.arg);
else if (c == 'k') asm_opt->k_mer_length = atoi(opt.arg);
else if (c == 'i') asm_opt->load_index_from_disk = 0;
else if (c == 'l') asm_opt->load_index_from_disk = 1;
else if (c == 'w') asm_opt->write_index_to_disk = 1;
else if (c == 'w') asm_opt->mz_win = atoi(opt.arg);
else if (c == 'D') asm_opt->high_factor = atof(opt.arg);
else if (c == 'F') asm_opt->no_kmer_flt = 1;
else if (c == 'N') asm_opt->max_n_chain = atoi(opt.arg);
else if (c == 'a') asm_opt->clean_round = atoi(opt.arg);
else if (c == 'z') asm_opt->adapterLen = atoi(opt.arg);
else if (c == 'b') asm_opt->required_read_name = opt.arg;
@@ -325,6 +342,7 @@ int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt)
else if (c == 'p') asm_opt->small_pop_bubble_size = atoll(opt.arg);
else if (c == 'm') asm_opt->large_pop_bubble_size = atoll(opt.arg);
else if (c == 'n') asm_opt->max_short_tip = atoll(opt.arg);
else if (c == 301) asm_opt->verbose_gfa = 1;
else if (c == ':')
{
fprintf(stderr, "[ERROR] missing option argument in \"%s\"\n", argv[opt.i - 1]);
+13 -5
View File
@@ -3,8 +3,9 @@
#include <pthread.h>
#define HA_VERSION "0.3.0-dirty-r199"
#define VERBOSE 0
#define VERBOSE_GFA 1
typedef struct {
int num_reads;
@@ -15,6 +16,12 @@ typedef struct {
char* mat_index;
int thread_num;
int k_mer_length;
int mz_win;
int bf_shift;
float high_factor;
int no_HPC;
int no_kmer_flt;
int max_n_chain;
int k_mer_min_freq;
int k_mer_max_freq;
int load_index_from_disk;
@@ -22,7 +29,6 @@ typedef struct {
int number_of_round;
int adapterLen;
int clean_round;
int complete_threads;
int roundID;
int max_hang_Len;
int gap_fuzz;
@@ -31,6 +37,7 @@ typedef struct {
int max_short_tip;
int min_cnt;
int mid_cnt;
int verbose_gfa;
float max_hang_rate;
float min_drop_rate;
@@ -41,6 +48,7 @@ typedef struct {
long long num_bases;
long long num_corrected_bases;
long long num_recorrected_bases;
long long mem_buf;
long long coverage;
} hifiasm_opt_t;
@@ -48,8 +56,8 @@ extern hifiasm_opt_t asm_opt;
void init_opt(hifiasm_opt_t* asm_opt);
void destory_opt(hifiasm_opt_t* asm_opt);
void clear_opt(hifiasm_opt_t* asm_opt, int last_round);
int CommandLine_process (int argc, char *argv[], hifiasm_opt_t* asm_opt);
void clear_opt(hifiasm_opt_t* asm_opt, int round);
int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt);
double Get_T(void);
#endif
#endif
-3
View File
@@ -7213,8 +7213,6 @@ void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF,
haplotype_evdience_alloc* hap, Round2_alignment* second_round,
int force_repeat, int is_consensus, int* fully_cov, int* abnormal)
{
reverse_complement(g_read->seq, g_read->length);
clear_Correct_dumy(dumy, overlap_list);
long long window_start, window_end;
@@ -7261,7 +7259,6 @@ void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF,
(*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal);
}
+1 -1
View File
@@ -1173,4 +1173,4 @@ long long* max_t_pos, long long* max_q_pos, long long* score, long long* droped)
#define GAP_EXT_KSW 2
#define Z_DROP_KSW 400
#define BAND_KSW 50
#endif
#endif
+116 -1107
View File
File diff suppressed because it is too large Load Diff
+43 -400
View File
@@ -1,13 +1,6 @@
#ifndef __HASHTABLE__
#define __HASHTABLE__
#include "khash.h"
#include "kmer.h"
KHASH_MAP_INIT_INT64(COUNT64, int)
typedef khash_t(COUNT64) Count_Table;
KHASH_MAP_INIT_INT64(POS64, uint64_t)
typedef khash_t(POS64) Pos_Table;
#include "htab.h"
#define PREFIX_BITS 16
#define MAX_SUFFIX_BITS 64
@@ -37,26 +30,8 @@ typedef khash_t(POS64) Pos_Table;
typedef struct
{
volatile int lock;
}Hash_table_spin_lock;
typedef struct
{
Count_Table** sub_h;
Hash_table_spin_lock* sub_h_lock;
int prefix_bits;
int suffix_bits;
///number of subtable
int size;
uint64_t suffix_mode;
uint64_t non_unique_k_mer;
} Total_Count_Table;
typedef struct
{
uint64_t offset;
uint64_t readID;
uint32_t offset;
uint32_t readID:31, rev:1;
} k_mer_pos;
typedef struct
@@ -70,17 +45,9 @@ typedef struct
typedef struct
{
k_mer_pos_list* list;
uint64_t size;
uint64_t length;
} k_mer_pos_list_alloc;
typedef struct
{
int C_L[CIGAR_MAX_LENGTH];
char C_C[CIGAR_MAX_LENGTH];
int length;
int C_L[CIGAR_MAX_LENGTH];
char C_C[CIGAR_MAX_LENGTH];
int length;
} CIGAR;
typedef struct
@@ -97,407 +64,96 @@ typedef struct
CIGAR cigar;
} window_list;
typedef struct
{
window_list* buffer;
long long length;
long long size;
}window_list_alloc;
int32_t length;
int32_t size;
} window_list_alloc;
typedef struct
{
uint64_t* buffer;
uint64_t length;
uint64_t size;
}Fake_Cigar;
uint32_t length;
uint32_t size;
} Fake_Cigar;
typedef struct
{
uint64_t x_id;
uint32_t x_id;
///the begining and end of the whole overlap
uint64_t x_pos_s;
uint64_t x_pos_e;
uint64_t x_pos_strand;
uint32_t x_pos_s;
uint32_t x_pos_e;
uint32_t x_pos_strand;
uint64_t y_id;
uint64_t y_pos_s;
uint64_t y_pos_e;
uint64_t y_pos_strand;
uint32_t y_id;
uint32_t y_pos_s;
uint32_t y_pos_e;
uint32_t y_pos_strand;
uint64_t overlapLen;
uint64_t shared_seed;
uint64_t align_length;
///uint64_t total_errors;
uint32_t overlapLen;
uint32_t shared_seed;
uint32_t align_length;
uint8_t is_match;
uint8_t without_large_indel;
uint64_t non_homopolymer_errors;
int8_t strong;
uint32_t non_homopolymer_errors;
window_list* w_list;
uint64_t w_list_size;
uint64_t w_list_length;
int8_t strong;
uint32_t w_list_size;
uint32_t w_list_length;
Fake_Cigar f_cigar;
window_list_alloc boundary_cigars;
} overlap_region;
typedef struct
{
overlap_region* list;
uint64_t size;
uint64_t length;
///uint64_t mapped_overlaps_length;
long long mapped_overlaps_length;
int64_t mapped_overlaps_length;
} overlap_region_alloc;
typedef struct
{
///uint64_t offset;
long long offset;
///uint64_t self_offset;
long long self_offset;
uint64_t readID;
uint8_t strand;
uint32_t readID:31, strand:1;
uint32_t offset, self_offset;
} k_mer_hit;
typedef struct
{
k_mer_hit node;
uint64_t ID;
} ElemType;
typedef struct
{
ElemType* heap;
uint64_t* index_i;
int len;
int MaxSize;
} HeapSq;
typedef struct
{
long long* score;
long long* pre;
long long* indels;
long long* self_length;
long long length;
long long size;
typedef struct {
int32_t *score;
int64_t *pre;
int32_t *indels;
int32_t *self_length;
int64_t *tmp; // MUST BE 64-bit integer
int64_t length;
int64_t size;
} Chain_Data;
typedef struct
{
k_mer_hit* list;
k_mer_hit* tmp;
long long length;
long long size;
uint64_t foward_pos;
uint64_t rc_pos;
Chain_Data chainDP;
} Candidates_list;
typedef struct
{
Pos_Table** sub_h;
Hash_table_spin_lock* sub_h_lock;
int prefix_bits;
int suffix_bits;
///number of subtable
int size;
uint64_t suffix_mode;
k_mer_pos* pos;
uint64_t useful_k_mer;
uint64_t total_occ;
uint64_t* k_mer_index;
} Total_Pos_Table;
inline uint64_t mod_d(uint64_t h_key, uint64_t low_key, uint64_t d)
{
uint64_t result = (h_key >> 32) % d;
result = ((result << 32) + (h_key & (uint64_t)0xffffffff)) % d;
result = ((result << 32) + (low_key >> 32)) % d;
result = ((result << 32) + (low_key & (uint64_t)0xffffffff)) % d;
return result;
}
////suffix_bits = 64 in default
inline int recover_hash_code(uint64_t sub_ID, uint64_t sub_key, Hash_code* code,
uint64_t suffix_mode, int suffix_bits, int k)
{
uint64_t h_key, low_key;
h_key = low_key = 0;
low_key = sub_ID << SAFE_SHIFT(suffix_bits);
low_key = low_key | sub_key;
h_key = sub_ID >> (64 - suffix_bits);
code->x[0] = code->x[1] = 0;
uint64_t mask = ALL >> (64 - k);
code->x[0] = low_key & mask;
code->x[1] = h_key << (64 - k);
code->x[1] = code->x[1] | (low_key >> SAFE_SHIFT(k));
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)
inline int get_sub_table(uint64_t* get_sub_ID, uint64_t* get_sub_key, uint64_t suffix_mode, int suffix_bits,
Hash_code* code, int k)
{
uint64_t h_key, low_key;
///k might be 64,so it is unsafe
///low_key = code->x[0] | (code->x[1] << k);
low_key = code->x[0] | (code->x[1] << SAFE_SHIFT(k));
//k cannot be 0, so this shift is safe
h_key = code->x[1] >> (64 - k);
if(mod_d(h_key, low_key, MODE_VALUE) > 3)
{
return 0;
}
uint64_t sub_ID = (low_key >> SAFE_SHIFT(suffix_bits)) | (h_key << (64 - suffix_bits));
uint64_t sub_key = (low_key & suffix_mode);
*get_sub_ID = sub_ID;
*get_sub_key = sub_key;
return 1;
}
inline int insert_Total_Count_Table(Total_Count_Table* TCB, Hash_code* code, int k)
{
uint64_t sub_ID, sub_key;
if(!get_sub_table(&sub_ID, &sub_key, TCB->suffix_mode, TCB->suffix_bits, code, k))
{
return 0;
}
khint_t t;
int absent;
while (__sync_lock_test_and_set(&TCB->sub_h_lock[sub_ID].lock, 1))
{
while (TCB->sub_h_lock[sub_ID].lock);
}
t = kh_put(COUNT64, TCB->sub_h[sub_ID], sub_key, &absent);
if (absent)
{
kh_value(TCB->sub_h[sub_ID], t) = 1;
}
else
{
//kh_value(TCB->sub_h[sub_ID], t) = kh_value(TCB->sub_h[sub_ID], t) + 1;
kh_value(TCB->sub_h[sub_ID], t)++;
}
__sync_lock_release(&TCB->sub_h_lock[sub_ID].lock);
return 1;
}
inline int get_Total_Count_Table(Total_Count_Table* TCB, Hash_code* code, int k)
{
uint64_t sub_ID, sub_key;
if(!get_sub_table(&sub_ID, &sub_key, TCB->suffix_mode, TCB->suffix_bits, code, k))
{
return 0;
}
khint_t t;
///query hash table,key is k
t = kh_get(COUNT64, TCB->sub_h[sub_ID], sub_key);
if (t != kh_end(TCB->sub_h[sub_ID]))
{
return kh_value(TCB->sub_h[sub_ID], t);
}
else
{
return 0;
}
}
inline uint64_t get_Total_Pos_Table(Total_Pos_Table* PCB, Hash_code* code, int k, uint64_t* r_sub_ID)
{
uint64_t sub_ID, sub_key;
if(!get_sub_table(&sub_ID, &sub_key, PCB->suffix_mode, PCB->suffix_bits, code, k))
{
return (uint64_t)-1;
}
khint_t t;
///query hash table,key is k
t = kh_get(POS64, PCB->sub_h[sub_ID], sub_key);
if (t != kh_end(PCB->sub_h[sub_ID]))
{
*r_sub_ID = sub_ID;
return kh_value(PCB->sub_h[sub_ID], t);
}
else
{
return (uint64_t)-1;
}
}
inline uint64_t count_Total_Pos_Table(Total_Pos_Table* PCB, Hash_code* code, int k)
{
uint64_t sub_ID;
uint64_t ret = get_Total_Pos_Table(PCB, code, k, &sub_ID);
if(ret != (uint64_t)-1)
{
return PCB->k_mer_index[ret + 1] - PCB->k_mer_index[ret];
}
else
{
return 0;
}
}
inline uint64_t locate_Total_Pos_Table(Total_Pos_Table* PCB, Hash_code* code, k_mer_pos** list, int k, uint64_t* r_sub_ID)
{
uint64_t ret = get_Total_Pos_Table(PCB, code, k, r_sub_ID);
if(ret != (uint64_t)-1)
{
*list = PCB->k_mer_index[ret] + PCB->pos;
return PCB->k_mer_index[ret + 1] - PCB->k_mer_index[ret];
}
else
{
*list = NULL;
return 0;
}
}
int cmp_k_mer_pos(const void * a, const void * b);
inline uint64_t insert_Total_Pos_Table(Total_Pos_Table* PCB, Hash_code* code, int k, uint64_t readID, uint64_t pos)
{
k_mer_pos* list;
int flag = 0;
uint64_t sub_ID;
uint64_t occ = locate_Total_Pos_Table(PCB, code, &list, k, &sub_ID);
if (occ)
{
while (__sync_lock_test_and_set(&PCB->sub_h_lock[sub_ID].lock, 1))
{
while (PCB->sub_h_lock[sub_ID].lock);
}
if (list[0].offset + 1 < occ)
{
list[0].offset++;
list[list[0].offset].readID = readID;
///list[list[0].offset].readID = readID|direction;
list[list[0].offset].offset = pos;
}
else
{
list[0].readID = readID;
///list[0].readID = readID|direction;
list[0].offset = pos;
flag = 1;
}
__sync_lock_release(&PCB->sub_h_lock[sub_ID].lock);
//if all pos has been saved, it is safe to sort
if (flag && occ>1)
{
qsort(list, occ, sizeof(k_mer_pos), cmp_k_mer_pos);
}
return 1;
}
else
{
return 0;
}
}
void init_Total_Count_Table(int k, Total_Count_Table* TCB);
void init_Total_Pos_Table(Total_Pos_Table* TCB, Total_Count_Table* pre_TCB);
void destory_Total_Count_Table(Total_Count_Table* TCB);
void init_Count_Table(Count_Table** table);
void init_Pos_Table(Count_Table** pre_table, Pos_Table** table);
void destory_Total_Pos_Table(Total_Pos_Table* TCB);
void write_Total_Pos_Table(Total_Pos_Table* TCB, char* read_file_name);
int load_Total_Pos_Table(Total_Pos_Table* TCB, char* read_file_name);
void Traverse_Counting_Table(Total_Count_Table* TCB, Total_Pos_Table* PCB, int k_mer_min_freq, int k_mer_max_freq);
void init_Candidates_list(Candidates_list* l);
void clear_Candidates_list(Candidates_list* l);
void destory_Candidates_list(Candidates_list* l);
void init_k_mer_pos_list_alloc(k_mer_pos_list_alloc* list);
void destory_k_mer_pos_list_alloc(k_mer_pos_list_alloc* list);
void clear_k_mer_pos_list_alloc(k_mer_pos_list_alloc* list);
void append_k_mer_pos_list_alloc(k_mer_pos_list_alloc* list, k_mer_pos* n_list, uint64_t n_length,
uint64_t n_end_pos, uint8_t n_direction);
void merge_k_mer_pos_list_alloc_heap_sort(k_mer_pos_list_alloc* list, Candidates_list* candidates, HeapSq* HBT);
void Init_Heap(HeapSq* HBT);
void destory_Heap(HeapSq* HBT);
void clear_Heap(HeapSq* HBT);
void init_overlap_region_alloc(overlap_region_alloc* list);
void clear_overlap_region_alloc(overlap_region_alloc* list);
void destory_overlap_region_alloc(overlap_region_alloc* list);
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 error_threshold);
void overlap_region_sort_y_id(overlap_region *a, long long n);
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, int add_beg_end);
void init_fake_cigar(Fake_Cigar* x);
void destory_fake_cigar(Fake_Cigar* x);
void clear_fake_cigar(Fake_Cigar* x);
@@ -505,14 +161,14 @@ void add_fake_cigar(Fake_Cigar* x, uint32_t gap_site, int32_t gap_shift);
void resize_fake_cigar(Fake_Cigar* x, uint64_t 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)
static 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 < (long long)o->length; i++)
{
@@ -524,7 +180,7 @@ inline long long y_start_offset(long long x_start, Fake_Cigar* o)
if(i == 0 || i == (long long)o->length)
{
fprintf(stderr, "ERROR\n");
fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
exit(0);
}
@@ -532,24 +188,11 @@ inline long long y_start_offset(long long x_start, Fake_Cigar* o)
return get_fake_gap_shift(o, i - 1);
}
inline void print_fake_gap(Fake_Cigar* o)
{
long long i;
for (i = 0; i < (long long)o->length; i++)
{
fprintf(stderr, "**i: %lld, gap_pos_in_x: %d, gap_shift: %d\n",
i, get_fake_gap_pos(o, i),
get_fake_gap_shift(o, i));
}
}
void resize_Chain_Data(Chain_Data* x, long long size);
void init_window_list_alloc(window_list_alloc* x);
void clear_window_list_alloc(window_list_alloc* x);
void destory_window_list_alloc(window_list_alloc* x);
void resize_window_list_alloc(window_list_alloc* x, long long size);
void chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result,
double band_width_threshold, int max_skip, int x_readLen, int y_readLen);
void chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, double band_width_threshold, int max_skip, int x_readLen, int y_readLen);
#endif
#endif
+32 -24
View File
@@ -1,11 +1,12 @@
CXX= g++
CXXFLAGS= -g -O3 -msse4.2 -mpopcnt -fomit-frame-pointer -Wall #-fsanitize=address -fno-omit-frame-pointer#-Winline
CXXFLAGS= -g -O3 -msse4.2 -mpopcnt -fomit-frame-pointer -Wall
CPPFLAGS=
INCLUDES=
OBJS= Output.o CommandLines.o Process_Read.o Assembly.o kmer.o Hash_Table.o \
POA.o Correct.o Levenshtein_distance.o Overlaps.o Trio.o kthread.o Purge_Dups.o #ksw2_extz2_sse.o
OBJS= Output.o CommandLines.o Process_Read.o Assembly.o Hash_Table.o \
POA.o Correct.o Levenshtein_distance.o Overlaps.o Trio.o kthread.o Purge_Dups.o \
htab.o hist.o sketch.o anchor.o sys.o
EXE= hifiasm
LIBS= -lz -lpthread -lm #-fsanitize=address -fno-omit-frame-pointer
LIBS= -lz -lpthread -lm
ifneq ($(asan),)
CXXFLAGS+=-fsanitize=address
@@ -31,27 +32,34 @@ depend:
# DO NOT DELETE
Assembly.o: Assembly.h Process_Read.h kseq.h Overlaps.h kvec.h kdq.h
Assembly.o: CommandLines.h kmer.h Hash_Table.h khash.h POA.h Correct.h
Assembly.o: Levenshtein_distance.h Output.h Trio.h
Assembly.o: Assembly.h CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h
Assembly.o: Hash_Table.h htab.h POA.h Correct.h Levenshtein_distance.h
Assembly.o: Output.h
CommandLines.o: CommandLines.h ketopt.h
Correct.o: Correct.h Hash_Table.h khash.h kmer.h Process_Read.h kseq.h
Correct.o: Overlaps.h kvec.h kdq.h CommandLines.h Levenshtein_distance.h
Correct.o: POA.h Assembly.h #ksw2.h
Hash_Table.o: Hash_Table.h khash.h kmer.h Process_Read.h kseq.h Overlaps.h
Hash_Table.o: kvec.h kdq.h CommandLines.h Correct.h Levenshtein_distance.h
Hash_Table.o: POA.h ksort.h
Correct.o: Correct.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h
Correct.o: kdq.h CommandLines.h Levenshtein_distance.h POA.h Assembly.h
Hash_Table.o: Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h
Hash_Table.o: CommandLines.h Correct.h Levenshtein_distance.h POA.h ksort.h
Levenshtein_distance.o: Levenshtein_distance.h
Output.o: Output.h CommandLines.h
Overlaps.o: Overlaps.h kvec.h kdq.h ksort.h Process_Read.h kseq.h
Overlaps.o: CommandLines.h Purge_Dups.h
POA.o: POA.h Hash_Table.h khash.h kmer.h Process_Read.h kseq.h Overlaps.h
POA.o: kvec.h kdq.h CommandLines.h Correct.h Levenshtein_distance.h
Process_Read.o: Process_Read.h kseq.h Overlaps.h kvec.h kdq.h CommandLines.h
kmer.o: kmer.h Process_Read.h kseq.h Overlaps.h kvec.h kdq.h CommandLines.h
main.o: CommandLines.h Process_Read.h kseq.h Overlaps.h kvec.h kdq.h
main.o: Assembly.h Levenshtein_distance.h
Trio.o: Trio.h khashl.h kthread.h Process_Read.h CommandLines.h
Overlaps.o: Overlaps.h kvec.h kdq.h ksort.h Process_Read.h CommandLines.h
Overlaps.o: Hash_Table.h htab.h Correct.h Levenshtein_distance.h POA.h
Overlaps.o: Purge_Dups.h
POA.o: POA.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h
POA.o: CommandLines.h Correct.h Levenshtein_distance.h
Process_Read.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h
Purge_Dups.o: ksort.h Purge_Dups.h kvec.h kdq.h Overlaps.h Hash_Table.h
Purge_Dups.o: htab.h Process_Read.h CommandLines.h Correct.h
Purge_Dups.o: Levenshtein_distance.h POA.h
Trio.o: khashl.h kthread.h Process_Read.h Overlaps.h kvec.h kdq.h
Trio.o: CommandLines.h htab.h
anchor.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h
anchor.o: ksort.h Hash_Table.h
hist.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h
htab.o: kthread.h khashl.h kseq.h ksort.h htab.h Process_Read.h Overlaps.h
htab.o: kvec.h kdq.h CommandLines.h
kthread.o: kthread.h
Purge_Dups.o: Purge_Dups.h Overlaps.h Hash_Table.h Correct.h ksort.h
#ksw2_extz2_sse.o: ksw2.h
main.o: CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h Assembly.h
main.o: Levenshtein_distance.h htab.h
sketch.o: kvec.h htab.h Process_Read.h Overlaps.h kdq.h CommandLines.h
sys.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h
+56 -71
View File
@@ -52,7 +52,6 @@ void ma_hit_sort_qns(ma_hit_t *a, long long n)
radix_sort_hit_qns(a, a + n);
}
void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend)
{
radix_sort_arch64(u_vecs->a.a, u_vecs->a.a + u_vecs->a.n);
@@ -68,7 +67,6 @@ void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend)
}
}
asg_t *asg_init(void)
{
return (asg_t*)calloc(1, sizeof(asg_t));
@@ -4356,7 +4354,7 @@ uint32_t startNode, uint32_t endNode)
}
else
{
fprintf(stderr, "ERROR\n");
fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
}
if(asg_arc_a(g, N_list[2])[0].v == (N_list[0]^1))
@@ -4369,7 +4367,7 @@ uint32_t startNode, uint32_t endNode)
}
else
{
fprintf(stderr, "ERROR\n");
fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
}
if(N_list[3] != N_list[4])
@@ -4920,12 +4918,10 @@ int asg_arc_del_short_diploid_unclean(asg_t *g, float drop_ratio, ma_hit_t_alloc
uint32_t detect_single_path_with_dels(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b)
{
uint32_t v = begNode, w;
uint32_t kv, kw;
(*Len) = 0;
while (1)
{
(*Len)++;
@@ -5594,6 +5590,7 @@ ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex)
if(flag1 == LOOP || flag2 == LOOP)
{
free(b_0.b.a); free(b_1.b.a);
return -1;
}
@@ -5612,6 +5609,7 @@ ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex)
if(l1 <= min_edge_length || l2 <= min_edge_length)
{
free(b_0.b.a); free(b_1.b.a);
return -1;
}
@@ -9051,7 +9049,7 @@ ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
break;
}
}
if(k == nv) fprintf(stderr, "ERROR\n");
if(k == nv) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
av = asg_arc_a(read_g, v);
nv = asg_arc_n(read_g, v);
@@ -9065,7 +9063,7 @@ ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
}
}
if(k == nv) fprintf(stderr, "ERROR\n");
if(k == nv) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
if(pE->el == 1 && aE->el == 1) continue;
@@ -9146,7 +9144,7 @@ ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
}
l = asg_arc_len(t_f);
}
if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n");
if(l == (uint32_t)-1) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
/*******************************for debug************************************/
@@ -9195,7 +9193,7 @@ ma_sub_t *coverage_cut, int max_hang, int min_ovlp)
}
l = asg_arc_len(t_f);
}
if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n");
if(l == (uint32_t)-1) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
/*******************************for debug************************************/
@@ -11671,7 +11669,7 @@ void print_untig(ma_ug_t *g, uint32_t uId, const char* info, uint32_t is_print_r
for (k = 0; k < u->n; k++)
{
fprintf(stderr, "%s: rId>>1: %lu, dir: %lu, name: %.*s\n",
info, u->a[k]>>33, (u->a[k]>>32)&1,
info, (unsigned long)(u->a[k]>>33), (unsigned long)((u->a[k]>>32)&1),
(int)Get_NAME_LENGTH((R_INF), (u->a[k]>>33)), Get_NAME((R_INF), (u->a[k]>>33)));
}
}
@@ -13624,6 +13622,9 @@ int load_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name)
f_flag += fread(&((*x)[i].length), sizeof((*x)[i].length), 1, fp);
(*x)[i].size = (*x)[i].length;
(*x)[i].buffer = NULL;
if((*x)[i].length == 0) continue;
(*x)[i].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*(*x)[i].length);
for (k = 0; k < (*x)[i].length; k++)
@@ -13640,8 +13641,6 @@ int load_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name)
}
void write_ma(ma_hit_t* x, FILE* fp)
{
fwrite(&(x->qns), sizeof(x->qns), 1, fp);
@@ -13692,51 +13691,43 @@ void write_ma_hit_ts(ma_hit_t_alloc* x, long long n_read, char* read_file_name)
fprintf(stderr, "ma_hit_ts has been written.\n");
}
void write_all_data_to_disk(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources,
All_reads *RNF, char* output_file_name)
void write_all_data_to_disk(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, All_reads *RNF, char* output_file_name)
{
char* gfa_name = (char*)malloc(strlen(output_file_name)+25);
sprintf(gfa_name, "%s.ovlp", output_file_name);
write_All_reads(RNF, gfa_name);
sprintf(gfa_name, "%s.ovlp.source", output_file_name);
write_ma_hit_ts(sources, RNF->total_reads, gfa_name);
char* gfa_name = (char*)malloc(strlen(output_file_name)+25);
sprintf(gfa_name, "%s.ec", output_file_name);
write_All_reads(RNF, gfa_name);
sprintf(gfa_name, "%s.ovlp.reverse", output_file_name);
write_ma_hit_ts(reverse_sources, RNF->total_reads, gfa_name);
sprintf(gfa_name, "%s.ovlp.source", output_file_name);
write_ma_hit_ts(sources, RNF->total_reads, gfa_name);
free(gfa_name);
sprintf(gfa_name, "%s.ovlp.reverse", output_file_name);
write_ma_hit_ts(reverse_sources, RNF->total_reads, gfa_name);
free(gfa_name);
}
int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources,
char* output_file_name)
int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, char* output_file_name)
{
char* gfa_name = (char*)malloc(strlen(output_file_name)+25);
sprintf(gfa_name, "%s.ovlp", output_file_name);
if(!load_All_reads(&R_INF, gfa_name))
{
return 0;
}
sprintf(gfa_name, "%s.ovlp.source", output_file_name);
if(!load_ma_hit_ts(sources, gfa_name))
{
return 0;
}
sprintf(gfa_name, "%s.ovlp.reverse", output_file_name);
if(!load_ma_hit_ts(reverse_sources, gfa_name))
{
return 0;
}
return 1;
char* gfa_name = (char*)malloc(strlen(output_file_name)+25);
sprintf(gfa_name, "%s.ec", output_file_name);
if (!load_All_reads(&R_INF, gfa_name)) {
free(gfa_name);
return 0;
}
sprintf(gfa_name, "%s.ovlp.source", output_file_name);
if (!load_ma_hit_ts(sources, gfa_name)) {
free(gfa_name);
return 0;
}
sprintf(gfa_name, "%s.ovlp.reverse", output_file_name);
if (!load_ma_hit_ts(reverse_sources, gfa_name)) {
free(gfa_name);
return 0;
}
free(gfa_name);
return 1;
}
// count the number of outgoing arcs, excluding reduced arcs
static inline int count_out(const asg_t *g, uint32_t v)
{
@@ -21006,7 +20997,7 @@ void merge_ug_nodes(ma_ug_t *ug, asg_t* read_g, kvec_t_u64_warp* array)
if(aw[i].del) continue;
if(aw[i].v == (v^1)) break;
}
if(i == nw) fprintf(stderr, "ERROR\n");
if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
kmp = kmp | (uint64_t)(aw[i].ol);
@@ -21037,7 +21028,7 @@ void merge_ug_nodes(ma_ug_t *ug, asg_t* read_g, kvec_t_u64_warp* array)
if(aw[i].del) continue;
if(aw[i].v == (v^1)) break;
}
if(i == nw) fprintf(stderr, "ERROR\n");
if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__);
kmp = kmp | (uint64_t)(aw[i].ol);
@@ -26198,7 +26189,7 @@ void fix_binned_reads(ma_hit_t_alloc* paf, uint64_t n_read, ma_sub_t* coverage_c
}
fprintf(stderr, "n_read: %lu, binned_reads: %lu, binned_error_reads: %lu\n",
n_read, binned_reads, binned_error_reads);
(unsigned long)n_read, (unsigned long)binned_reads, (unsigned long)binned_error_reads);
}
@@ -26301,24 +26292,22 @@ 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, long long gap_fuzz,
float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name,
long long bubble_dist, int read_graph, R_to_U* ruIndex, asg_t* sg,
ma_sub_t* coverage_cut, int debug_g)
long long bubble_dist, int read_graph, R_to_U* ruIndex, asg_t **sg_ptr,
ma_sub_t **coverage_cut_ptr, int debug_g)
{
ma_sub_t *coverage_cut = *coverage_cut_ptr;
asg_t *sg = *sg_ptr;
if(debug_g) goto debug_gfa;
///just for debug
renew_graph_init(sources, reverse_sources, sg, coverage_cut, ruIndex, n_read);
///it's hard to say which function is better
///normalize_ma_hit_t_single_side(sources, n_read);
normalize_ma_hit_t_single_side_advance(sources, n_read);
normalize_ma_hit_t_single_side_advance(reverse_sources, n_read);
// debug_info_of_specfic_read(">m64011_190830_220126/117834372/ccs", sources, reverse_sources,
// -1, "clean");
@@ -26477,7 +26466,7 @@ ma_sub_t* coverage_cut, int debug_g)
asg_arc_del_simple_circle_untig(sources, coverage_cut, sg, 100, 0);
if(VERBOSE_GFA >= 1)
if (asm_opt.verbose_gfa)
{
/*******************************for debug***************************************/
write_debug_graph(sg, sources, coverage_cut, output_file_name, n_read, reverse_sources, ruIndex);
@@ -26532,13 +26521,13 @@ ma_sub_t* coverage_cut, int debug_g)
bubble_dist, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length,
mini_overlap_length);
output_contig_graph_alternative(sg, coverage_cut, output_file_name, sources, max_hang_length, mini_overlap_length);
}
*coverage_cut_ptr = coverage_cut;
*sg_ptr = sg;
}
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,
@@ -26551,13 +26540,12 @@ long long bubble_dist, int read_graph, int write)
asg_t *sg = NULL;
ma_sub_t* coverage_cut = NULL;
// debug_info_of_specfic_read("m64011_190329_072846/80545633/ccs",
// sources, reverse_sources, -1, "clean");
// debug_info_of_specfic_read("m64011_190329_072846/80545633/ccs", sources, reverse_sources, -1, "clean");
///actually min_thres = asm_opt.max_short_tip + 1 there are asm_opt.max_short_tip reads
min_thres = asm_opt.max_short_tip + 1;
if(VERBOSE_GFA >= 1)
if (asm_opt.verbose_gfa)
{
if(load_debug_graph(&sg, &sources, &coverage_cut, output_file_name, &reverse_sources, &ruIndex))
{
@@ -26565,7 +26553,7 @@ long long bubble_dist, int read_graph, int write)
clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length,
max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio,
output_file_name, bubble_dist, read_graph, &ruIndex, sg, coverage_cut, 1);
output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, 1);
asg_destroy(sg);
free(coverage_cut);
destory_R_to_U(&ruIndex);
@@ -26573,20 +26561,17 @@ long long bubble_dist, int read_graph, int write)
}
}
if (asm_opt.write_index_to_disk && write)
{
write_all_data_to_disk(sources, reverse_sources,
&R_INF, output_file_name);
}
try_rescue_overlaps(sources, reverse_sources, n_read, 4);
clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length,
max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio,
output_file_name, bubble_dist, read_graph, &ruIndex, sg, coverage_cut, 0);
output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, 0);
asg_destroy(sg);
free(coverage_cut);
+1 -4
View File
@@ -47,9 +47,6 @@
#define CUT_DIF_HAP 12
///query is the read itself
typedef struct {
uint64_t qns;
@@ -1057,4 +1054,4 @@ int unitig_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio);
#define JUNK_COV 5
#define DISCARD_RATE 0.8
#endif
#endif
+73 -131
View File
@@ -1,29 +1,27 @@
#include "POA.h"
#include <stdlib.h>
#include <string.h>
#include "POA.h"
#include "Correct.h"
#include "Process_Read.h"
#define INIT_EDGE_SIZE 50
#define INCREASE_EDGE_SIZE 5
#define INIT_NODE_SIZE 16000
/********
* Edge *
********/
void init_Edge_alloc(Edge_alloc* list)
{
if (list->list == NULL)
{
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;
}
if (list->list == NULL) {
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;
}
}
void clear_Edge_alloc(Edge_alloc* list)
@@ -34,28 +32,29 @@ void clear_Edge_alloc(Edge_alloc* list)
void destory_Edge_alloc(Edge_alloc* list)
{
free(list->list);
if (list && list->list)
free(list->list);
}
void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length)
{
if (list->length + 1 > list->size)
{
list->size = list->size + INCREASE_EDGE_SIZE;
list->list = (Edge*)realloc(list->list, sizeof(Edge)*list->size);
}
if (list->length + 1 > list->size) {
uint64_t old_size = list->size;
list->size = list->size + INCREASE_EDGE_SIZE;
list->list = (Edge*)realloc(list->list, sizeof(Edge)*list->size);
memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Edge));
}
list->list[list->length].in_node = in_node;
list->list[list->length].out_node = out_node;
list->list[list->length].weight = weight;
list->list[list->length].length = length;
list->list[list->length].num_insertions = 0;
list->list[list->length].self_edge_ID = list->length;
list->list[list->length].in_node = in_node;
list->list[list->length].out_node = out_node;
list->list[list->length].weight = weight;
list->list[list->length].length = length;
list->list[list->length].num_insertions = 0;
list->list[list->length].self_edge_ID = list->length;
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;
@@ -81,7 +80,6 @@ int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node,
}
}
void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag)
{
@@ -95,8 +93,6 @@ void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t
= 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;
@@ -135,8 +131,6 @@ int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, N
}
}
int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e)
{
Edge* e_forward;
@@ -171,109 +165,71 @@ int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e)
{
return 0;
}
}
/********
* Node *
********/
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;
list->sort.visit = NULL;
list->sort.iterative_buffer = NULL;
list->sort.iterative_buffer_visit = NULL;
uint64_t i;
for (i = 0; i < list->size; i++)
{
list->list[i].insertion_edges.list=NULL;
list->list[i].mismatch_edges.list=NULL;
list->list[i].deletion_edges.list=NULL;
}
memset(list, 0, sizeof(Node_alloc));
list->size = INIT_NODE_SIZE;
list->list = (Node*)calloc(list->size, sizeof(Node));
}
void destory_Node_alloc(Node_alloc* list)
{
uint64_t i =0;
for (i = 0; i < list->length; i++)
{
destory_Edge_alloc(&list->list[i].deletion_edges);
destory_Edge_alloc(&list->list[i].insertion_edges);
destory_Edge_alloc(&list->list[i].mismatch_edges);
}
free(list->list);
free(list->sort.list);
free(list->sort.visit);
free(list->sort.iterative_buffer);
free(list->sort.iterative_buffer_visit);
///free(list->topo_order);
uint64_t i;
for (i = 0; i < list->size; i++) {
destory_Edge_alloc(&list->list[i].deletion_edges);
destory_Edge_alloc(&list->list[i].insertion_edges);
destory_Edge_alloc(&list->list[i].mismatch_edges);
}
free(list->list);
free(list->sort.list);
free(list->sort.visit);
free(list->sort.iterative_buffer);
free(list->sort.iterative_buffer_visit);
}
void clear_Node_alloc(Node_alloc* list)
{
uint64_t i =0;
for (i = 0; i < list->length; i++)
{
clear_Edge_alloc(&list->list[i].insertion_edges);
clear_Edge_alloc(&list->list[i].mismatch_edges);
clear_Edge_alloc(&list->list[i].deletion_edges);
}
list->length = 0;
list->delete_length = 0;
uint64_t i =0;
for (i = 0; i < list->length; i++) { // TODO: is this list->size or list->length? The original version is list->length.
clear_Edge_alloc(&list->list[i].insertion_edges);
clear_Edge_alloc(&list->list[i].mismatch_edges);
clear_Edge_alloc(&list->list[i].deletion_edges);
}
list->length = 0;
list->delete_length = 0;
}
uint64_t append_Node_alloc(Node_alloc* list, char base)
{
if (list->length + 1 > list->size)
{
uint64_t i = list->size;
if (list->length + 1 > list->size) {
uint64_t old_size = list->size;
list->size = list->size * 2;
list->list = (Node*)realloc(list->list, sizeof(Node) * list->size);
memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Node));
}
list->size = list->size * 2;
list->list = (Node*)realloc(list->list, sizeof(Node)*list->size);
///list->topo_order = (uint64_t*)realloc(list->topo_order, sizeof(uint64_t)*list->size);
for (; i < list->size; i++)
{
list->list[i].deletion_edges.list=NULL;
list->list[i].insertion_edges.list=NULL;
list->list[i].mismatch_edges.list=NULL;
}
}
list->list[list->length].ID = list->length;
list->list[list->length].base = base;
list->list[list->length].weight = 1;
list->list[list->length].num_insertions = 0;
init_Edge_alloc(&list->list[list->length].deletion_edges);
init_Edge_alloc(&list->list[list->length].insertion_edges);
init_Edge_alloc(&list->list[list->length].mismatch_edges);
list->length++;
list->list[list->length].ID = list->length;
list->list[list->length].base = base;
list->list[list->length].weight = 1;
list->list[list->length].num_insertions = 0;
init_Edge_alloc(&list->list[list->length].deletion_edges);
init_Edge_alloc(&list->list[list->length].insertion_edges);
init_Edge_alloc(&list->list[list->length].mismatch_edges);
return list->length - 1;
list->length++;
return list->length - 1;
}
/*********
* Graph *
*********/
void init_Graph(Graph* g)
{
@@ -310,12 +266,6 @@ void clear_Graph(Graph* g)
clear_Queue(&(g->node_q));
}
void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID)
{
long long firstID, lastID, nodeID, i;
@@ -356,8 +306,6 @@ void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length,
}
void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_string, long long x_length,
char* y_string, long long y_length, CIGAR* cigar, long long backbone_start, long long backbone_end)
{
@@ -422,9 +370,3 @@ void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_stri
cigar_i++;
}
}
+26 -522
View File
@@ -1,25 +1,8 @@
#include "Process_Read.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
gz_files fps;
R_buffer RDB;
static uint64_t total_reads;
pthread_mutex_t i_readinputMutex;
pthread_mutex_t i_queueMutex;
pthread_mutex_t i_terminateMutex;
pthread_cond_t i_flushCond;
pthread_cond_t i_readinputflushCond;
pthread_cond_t i_stallCond;
pthread_cond_t i_readinputstallCond;
pthread_mutex_t i_doneMutex;
#include "Process_Read.h"
uint8_t seq_nt6_table[256] = {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
@@ -45,34 +28,27 @@ char bit_t_seq_table_rc[256][4] = {{0}};
char s_H[5] = {'A', 'C', 'G', 'T', 'N'};
char rc_Table[5] = {'T', 'G', 'C', 'A', 'N'};
void init_All_reads(All_reads* r)
{
memset(r, 0, sizeof(All_reads));
r->index_size = READ_INIT_NUMBER;
r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->index_size);
r->read_sperate = NULL;
r->N_site = NULL;
r->total_reads_bases = 0;
r->name_index_size = READ_INIT_NUMBER;
r->name_index = (uint64_t*)malloc(sizeof(uint64_t)*r->name_index_size);
r->name_index[0] = 0;
r->name = NULL;
r->total_name_length = 0;
r->total_reads = 0;
r->trio_flag = NULL;
}
void destory_All_reads(All_reads* r)
{
uint64_t i = 0;
for (i = 0; i < r->total_reads; i++)
{
if (r->N_site[i] != NULL)
{
free(r->N_site[i]);
}
free(r->read_sperate[i]);
for (i = 0; i < r->total_reads; i++) {
if (r->N_site[i]) free(r->N_site[i]);
if (r->read_sperate[i]) free(r->read_sperate[i]);
if (r->paf&&r->paf[i].buffer) free(r->paf[i].buffer);
if (r->reverse_paf&&r->reverse_paf[i].buffer) free(r->reverse_paf[i].buffer);
}
free(r->paf);
free(r->reverse_paf);
free(r->N_site);
free(r->read_sperate);
free(r->name);
@@ -81,7 +57,6 @@ void destory_All_reads(All_reads* r)
free(r->trio_flag);
}
void write_All_reads(All_reads* r, char* read_file_name)
{
fprintf(stderr, "Writing reads to disk... \n");
@@ -112,9 +87,6 @@ void write_All_reads(All_reads* r, char* read_file_name)
{
fwrite(&zero, sizeof(zero), 1, fp);
}
}
fwrite(r->read_length, sizeof(uint64_t), r->total_reads, fp);
@@ -132,16 +104,13 @@ void write_All_reads(All_reads* r, char* read_file_name)
fprintf(stderr, "Reads has been written.\n");
}
int load_All_reads(All_reads* r, char* read_file_name)
{
fprintf(stderr, "Loading reads from disk... \n");
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)
{
if (!fp) {
free(index_name);
return 0;
}
int local_adapterLen;
@@ -164,12 +133,10 @@ int load_All_reads(All_reads* r, char* read_file_name)
r->N_site = (uint64_t**)malloc(sizeof(uint64_t*)*r->total_reads);
for (i = 0; i < r->total_reads; i++)
{
f_flag += fread(&zero, sizeof(zero), 1, fp);
if (zero)
{
r->N_site[i] = (uint64_t*)malloc(sizeof(uint64_t)*(zero + 1));
r->N_site[i][0] = zero;
if (r->N_site[i][0])
@@ -181,7 +148,6 @@ int load_All_reads(All_reads* r, char* read_file_name)
{
r->N_site[i] = NULL;
}
}
r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads);
@@ -211,8 +177,6 @@ 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;
@@ -222,8 +186,6 @@ 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);
@@ -233,32 +195,28 @@ int load_All_reads(All_reads* r, char* read_file_name)
return 1;
}
inline void insert_read(All_reads* r, kstring_t* read, kstring_t* name)
void ha_insert_read_len(All_reads *r, int read_len, int name_len)
{
r->total_reads++;
r->total_reads_bases = r->total_reads_bases + read->l;
r->total_name_length = r->total_name_length + name->l;
r->total_reads_bases += (uint64_t)read_len;
r->total_name_length += (uint64_t)name_len;
///must +1
if (r->index_size < r->total_reads + 2)
{
// must +1
if (r->index_size < r->total_reads + 2) {
r->index_size = r->index_size * 2 + 2;
r->read_length = (uint64_t*)realloc(r->read_length,sizeof(uint64_t)*(r->index_size));
r->read_length = (uint64_t*)realloc(r->read_length, sizeof(uint64_t) * r->index_size);
r->name_index_size = r->name_index_size * 2 + 2;
r->name_index = (uint64_t*)realloc(r->name_index,sizeof(uint64_t)*(r->name_index_size));
r->name_index = (uint64_t*)realloc(r->name_index, sizeof(uint64_t) * r->name_index_size);
}
r->read_length[r->total_reads - 1] = read->l;
r->name_index[r->total_reads] = r->name_index[r->total_reads-1] + name->l;
r->read_length[r->total_reads - 1] = read_len;
r->name_index[r->total_reads] = r->name_index[r->total_reads - 1] + name_len;
}
void malloc_All_reads(All_reads* r)
{
r->read_size = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads);
memcpy (r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads);
memcpy(r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads);
r->read_sperate = (uint8_t**)malloc(sizeof(uint8_t*)*r->total_reads);
long long i = 0;
@@ -313,7 +271,6 @@ void init_aux_table()
bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]);
bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]);
}
}
}
@@ -338,18 +295,12 @@ void init_UC_Read(UC_Read* r)
bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]);
bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]);
}
}
}
void recover_UC_Read_sub_region_begin_end
(char* r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID, int extra_begin, int extra_end)
void recover_UC_Read_sub_region_begin_end(char* r, long long start_pos, long long length, uint8_t strand,
All_reads* R_INF, long long ID, int extra_begin, int extra_end)
{
long long readLen = Get_READ_LENGTH((*R_INF), ID);
uint8_t* src = Get_READ((*R_INF), ID);
@@ -357,17 +308,11 @@ void recover_UC_Read_sub_region_begin_end
long long copyLen;
long long end_pos = start_pos + length - 1;
if (strand == 0)
{
i = start_pos;
copyLen = 0;
long long initLen = start_pos % 4;
if (initLen != 0)
@@ -376,8 +321,6 @@ void recover_UC_Read_sub_region_begin_end
copyLen = copyLen + 4 - initLen;
i = i + copyLen;
}
while (copyLen < length)
{
memcpy(r+copyLen, bit_t_seq_table[src[i>>2]], 4);
@@ -385,7 +328,6 @@ void recover_UC_Read_sub_region_begin_end
i = i + 4;
}
if (R_INF->N_site[ID])
{
for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++)
@@ -400,17 +342,12 @@ void recover_UC_Read_sub_region_begin_end
}
}
}
}
else
{
start_pos = readLen - start_pos - 1;
end_pos = readLen - end_pos - 1;
///start_pos > end_pos
i = start_pos;
copyLen = 0;
@@ -436,7 +373,6 @@ void recover_UC_Read_sub_region_begin_end
for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++)
{
if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos)
{
r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N';
@@ -447,21 +383,11 @@ void recover_UC_Read_sub_region_begin_end
}
}
}
}
}
void recover_UC_Read_sub_region(char* r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID)
{
long long readLen = Get_READ_LENGTH((*R_INF), ID);
uint8_t* src = Get_READ((*R_INF), ID);
@@ -471,7 +397,6 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
if (strand == 0)
{
i = start_pos;
copyLen = 0;
@@ -483,8 +408,7 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
copyLen = copyLen + 4 - initLen;
i = i + copyLen;
}
while (copyLen < length)
{
memcpy(r+copyLen, bit_t_seq_table[src[i>>2]], 4);
@@ -492,7 +416,6 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
i = i + 4;
}
if (R_INF->N_site[ID])
{
for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++)
@@ -507,17 +430,12 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
}
}
}
}
else
{
start_pos = readLen - start_pos - 1;
end_pos = readLen - end_pos - 1;
///start_pos > end_pos
i = start_pos;
copyLen = 0;
@@ -543,7 +461,6 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++)
{
if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos)
{
r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N';
@@ -554,15 +471,11 @@ void recover_UC_Read_sub_region(char* r, long long start_pos, long long length,
}
}
}
}
}
void recover_UC_Read(UC_Read* r, All_reads* R_INF, uint64_t ID)
void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID)
{
r->length = Get_READ_LENGTH((*R_INF), ID);
uint8_t* src = Get_READ((*R_INF), ID);
@@ -623,7 +536,6 @@ void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID)
index = index + 4;
}
if (R_INF->N_site[ID])
{
for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++)
@@ -631,11 +543,8 @@ void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID)
r->seq[r->length - R_INF->N_site[ID][i] - 1] = 'N';
}
}
}
#define COMPRESS_BASE {c = seq_nt6_table[(uint8_t)src[i]];\
if (c >= 4)\
{\
@@ -645,9 +554,8 @@ void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID)
}\
i++;}\
void compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ)
void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ)
{
///N_site_lis saves the pos of all Ns in this read
///N_site_lis[0] is the number of Ns
if (N_site_occ)
@@ -666,10 +574,8 @@ void compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_l
uint8_t tmp = 0;
uint8_t c = 0;
while (i + 4 <= src_l)
{
tmp = 0;
COMPRESS_BASE;
@@ -705,351 +611,8 @@ void compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_l
dest[dest_i] = tmp;
dest_i++;
}
}
void open_file(gz_files* nfps, char* name)
{
nfps->fp = gzopen(name, "r");
if(nfps->fp == 0)
{
fprintf(stderr, "[ERROR] Cannot find the input file: %s\n", name);
exit(0);
}
nfps->seq = kseq_init(nfps->fp);
}
void close_file(gz_files* nfps)
{
kseq_destroy(nfps->seq);
gzclose(nfps->fp);
}
void init_gz_files(hifiasm_opt_t* asm_opt)
{
fps.idx = 0;
fps.num_reads = asm_opt->num_reads;
fps.reads = asm_opt->read_file_names;
fps.seq = NULL;
fps.fp = NULL;
if(fps.num_reads > 0)
{
open_file(&fps, fps.reads[fps.idx]);
fps.idx++;
}
}
void destory_gz_files()
{
close_file(&fps);
}
int read_item()
{
int l = kseq_read(fps.seq);
if(l >= 0 || (l < 0 && fps.idx >= fps.num_reads))
{
return l;
}
///l < 0 && fps.idx < fps.num_reads
close_file(&fps);
open_file(&fps, fps.reads[fps.idx]);
fps.idx++;
return read_item();
}
inline void exchage_kstring_t(kstring_t* a, kstring_t* b)
{
kstring_t tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int get_read(kseq_t *s, int adapterLen)
{
int l;
///if ((l = kseq_read(seq)) >= 0)
if ((l = read_item()) >= 0)
{
exchage_kstring_t(&(fps.seq->comment), &s->comment);
exchage_kstring_t(&(fps.seq->name), &s->name);
exchage_kstring_t(&(fps.seq->qual), &s->qual);
exchage_kstring_t(&(fps.seq->seq), &s->seq);
if(adapterLen > 0)
{
if((int)s->seq.l <= adapterLen*2)
{
s->seq.l = 0;
}
else
{
long long i;
for (i = 0; i < ((int)s->seq.l - adapterLen*2); i++)
{
s->seq.s[i] = s->seq.s[i + adapterLen];
}
s->seq.l -= adapterLen*2;
}
}
return 1;
}
else
{
return 0;
}
}
void init_R_buffer_block(R_buffer_block* curr_sub_block)
{
curr_sub_block->read = (kseq_t*)calloc(RDB.block_inner_size, sizeof(kseq_t));
curr_sub_block->num = 0;
}
void clear_R_buffer()
{
RDB.all_read_end = 0;
RDB.num = 0;
}
void init_R_buffer(int thread_num)
{
RDB.all_read_end = 0;
RDB.num = 0;
RDB.block_inner_size = READ_BLOCK_SIZE;
RDB.size = thread_num*READ_BLOCK_NUM_PRE_THR;
RDB.sub_block = (R_buffer_block*)malloc(sizeof(R_buffer_block)*RDB.size);
int i = 0;
for (i = 0; i < RDB.size; i++)
{
init_R_buffer_block(&RDB.sub_block[i]);
}
}
void destory_R_buffer_block(R_buffer_block* curr_sub_block)
{
kseq_destroy(curr_sub_block->read);
}
void destory_R_buffer()
{
int i = 0;
for (i = 0; i < RDB.size; i++)
{
destory_R_buffer_block(&RDB.sub_block[i]);
}
free(RDB.sub_block);
}
inline void load_read_block(R_buffer_block* read_batch, int batch_read_size,
int* return_file_flag, int is_insert, int adapterLen)
{
int inner_i = 0;
int file_flag = 1;
while (inner_i<batch_read_size)
{
file_flag = get_read(&read_batch->read[inner_i], adapterLen);
if (file_flag == 1)
{
read_batch->read[inner_i].ID = total_reads;
total_reads++;
if (is_insert)
{
insert_read(&R_INF, &read_batch->read[inner_i].seq,
&read_batch->read[inner_i].name);
}
inner_i++;
}
else if (file_flag == 0)
{
break;
}
}
if (inner_i || file_flag)
{
file_flag = 1;
}
*return_file_flag = file_flag;
read_batch->num = inner_i;
}
inline void push_R_block(R_buffer_block* tmp_sub_block)
{
///only exchange pointers
kseq_t *k1;
k1 = RDB.sub_block[RDB.num].read;
RDB.sub_block[RDB.num].read = tmp_sub_block->read;
tmp_sub_block->read = k1;
RDB.sub_block[RDB.num].num = tmp_sub_block->num;
tmp_sub_block->num = 0;
RDB.num++;
}
inline void pop_R_block(R_buffer_block* curr_sub_block)
{
RDB.num--;
///only exchange pointers
kseq_t *k1;
k1 = RDB.sub_block[RDB.num].read;
RDB.sub_block[RDB.num].read = curr_sub_block->read;
curr_sub_block->read = k1;
curr_sub_block->num = RDB.sub_block[RDB.num].num;
RDB.sub_block[RDB.num].num = 0;
}
void* input_reads_muti_threads(void* arg)
{
int is_insert = *((int*)arg);
total_reads = 0;
int file_flag = 1;
R_buffer_block tmp_buf;
init_R_buffer_block(&tmp_buf);
while (1)
{
load_read_block(&tmp_buf, RDB.block_inner_size, &file_flag, is_insert, asm_opt.adapterLen);
if (file_flag == 0)
{
break;
}
pthread_mutex_lock(&i_readinputMutex);
while (IS_FULL(RDB))
{
pthread_cond_signal(&i_readinputstallCond);
pthread_cond_wait(&i_readinputflushCond, &i_readinputMutex);
}
push_R_block(&tmp_buf);
pthread_cond_signal(&i_readinputstallCond);
pthread_mutex_unlock(&i_readinputMutex);
}
pthread_mutex_lock(&i_readinputMutex);
RDB.all_read_end = 1;
pthread_cond_signal(&i_readinputstallCond); //important
pthread_mutex_unlock(&i_readinputMutex);
destory_R_buffer_block(&tmp_buf);
fprintf(stderr, "Reads #: %lu\n", (unsigned long)total_reads);
fprintf(stderr, "Bases #: %lu\n", (unsigned long)R_INF.total_reads_bases);
return NULL;
}
int get_reads_mul_thread(R_buffer_block* curr_sub_block)
{
pthread_mutex_lock(&i_readinputMutex);
while (IS_EMPTY(RDB) && RDB.all_read_end == 0)
{
pthread_cond_signal(&i_readinputflushCond);
pthread_cond_wait(&i_readinputstallCond, &i_readinputMutex);
}
if (!IS_EMPTY(RDB))
{
pop_R_block(curr_sub_block);
pthread_cond_signal(&i_readinputflushCond);
pthread_mutex_unlock(&i_readinputMutex);
return 1;
}
else
{
curr_sub_block->num = 0;
pthread_cond_signal(&i_readinputstallCond); //important
pthread_mutex_unlock(&i_readinputMutex);
return 0;
}
}
void reverse_complement(char* pattern, uint64_t length)
{
uint64_t i = 0;
@@ -1069,63 +632,4 @@ void reverse_complement(char* pattern, uint64_t length)
{
pattern[end] = RC_CHAR(pattern[end]);
}
}
typedef struct {
char* tmp;
long long tmpSize;
char* dest;
long long destSize;
FILE* fp;
} LineReader;
int get_single_line(LineReader* line)
{
long long currentLen = 0, getLen = 0;
line->tmp[0] = '\0';
while (fgets(line->tmp, line->tmpSize, line->fp) != NULL)
{
getLen = strlen(line->tmp);
if(getLen + currentLen >= line->destSize)
{
line->destSize = getLen + currentLen + 1;
line->dest = (char*)realloc(line->dest, line->destSize);
}
memcpy(line->dest + currentLen, line->tmp, getLen+1);
currentLen = currentLen + getLen;
if(currentLen > 0 && line->dest[currentLen - 1] == '\n')
{
return 1;
}
}
if(currentLen > 0)
{
return 1;
}
else
{
return 0;
}
}
void get_trio_info(char* input, uint8_t* pm)
{
uint32_t i;
(*pm) = AMBIGU;
for (i = 0; input[i] != '\0'; i++)
{
if(input[i] == '\t')
{
break;
}
}
input[i] = '\0';
i++;
if(input[i] == 'p') (*pm) = FATHER;
if(input[i] == 'm') (*pm) = MOTHER;
}
+10 -65
View File
@@ -5,7 +5,6 @@
#include <string.h>
#include <stdlib.h>
#include <zlib.h>
#include "kseq.h"
#include "Overlaps.h"
#include "CommandLines.h"
///#include "Hash_Table.h"
@@ -18,16 +17,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)]
KSEQ_INIT(gzFile, gzread)
#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)])
extern uint8_t seq_nt6_table[256];
@@ -37,12 +31,9 @@ extern char s_H[5];
extern char rc_Table[5];
#define RC_CHAR(x) rc_Table[seq_nt6_table[(uint8_t)x]]
void init_aux_table();
int get_read(kseq_t *s, int adapterLen);
typedef struct
{
@@ -76,7 +67,6 @@ inline void init_PAF_alloc(PAF_alloc* list)
list->list = (PAF*)malloc(sizeof(PAF)*list->size);
}
inline void append_PAF_alloc(PAF_alloc* list, PAF* e)
{
if(list->length+1 > list->size)
@@ -89,9 +79,6 @@ inline void append_PAF_alloc(PAF_alloc* list, PAF* e)
list->length++;
}
typedef struct
{
/**[0-1] bits are type:**/
@@ -104,7 +91,7 @@ typedef struct
uint32_t lost_base_length;
uint32_t lost_base_size;
uint32_t new_length;
}Compressed_Cigar_record;
} Compressed_Cigar_record;
#define AMBIGU 0
#define FATHER 1
@@ -112,13 +99,13 @@ typedef struct
#define MIX_TRIO 3
#define NON_TRIO 4
#define DROP 5
typedef struct
{
uint64_t** N_site;
///uint8_t* read;
char* name;
uint8_t** read_sperate;
uint64_t* read_length;
uint64_t* read_size;
@@ -129,7 +116,6 @@ typedef struct
///uint64_t* index;
uint64_t index_size;
///name start pos in char* name
uint64_t* name_index;
uint64_t name_index_size;
@@ -142,32 +128,10 @@ typedef struct
ma_hit_t_alloc* paf;
ma_hit_t_alloc* reverse_paf;
ma_sub_t* coverage_cut;
} All_reads;
extern All_reads R_INF;
void malloc_All_reads(All_reads* r);
typedef struct
{
kseq_t* read;
long long num;
} R_buffer_block;
typedef struct
{
R_buffer_block* sub_block;
long long block_inner_size;
long long size;
long long num;
int all_read_end;
} R_buffer;
typedef struct
{
char* seq;
@@ -176,23 +140,12 @@ typedef struct
long long RID;
} UC_Read;
typedef struct
{
gzFile fp;
kseq_t *seq;
char** reads;
int num_reads;
int idx;
} gz_files;
void init_R_buffer(int thread_num);
void init_All_reads(All_reads* r);
void* input_reads_muti_threads(void*);
void init_R_buffer_block(R_buffer_block* curr_sub_block);
int get_reads_mul_thread(R_buffer_block* curr_sub_block);
void compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ);
void malloc_All_reads(All_reads* r);
void ha_insert_read_len(All_reads *r, int read_len, int name_len);
void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ);
void init_UC_Read(UC_Read* r);
void recover_UC_Read(UC_Read* r, All_reads* R_INF, uint64_t ID);
void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID);
void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID);
void recover_UC_Read_sub_region(char* r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID);
void destory_UC_Read(UC_Read* r);
@@ -201,12 +154,4 @@ void write_All_reads(All_reads* r, char* read_file_name);
int load_All_reads(All_reads* r, char* read_file_name);
void destory_All_reads(All_reads* r);
void destory_R_buffer_block(R_buffer_block* curr_sub_block);
void destory_R_buffer();
void clear_R_buffer();
void init_gz_files(hifiasm_opt_t* asm_opt);
void destory_gz_files();
#endif
+83 -61
View File
@@ -1,10 +1,10 @@
#include "Purge_Dups.h"
#include "Overlaps.h"
#include "Correct.h"
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <stdlib.h>
#include "ksort.h"
#include "Purge_Dups.h"
#include "Overlaps.h"
#include "Correct.h"
#define Cal_Off(OFF) ((long long)((uint32_t)((OFF)>>32)) - (long long)((uint32_t)((OFF))))
#define Get_match(x) ((x).weight)
@@ -76,6 +76,37 @@ typedef struct {
uint32_t num;
}hap_overlaps_list;
typedef struct {
uint64_t* vote_counting;
uint8_t* visit;
kvec_t_u64_warp u_vecs;
kvec_asg_arc_t_offset u_buffer;
kvec_hap_candidates u_can;
}hap_alignment_struct;
void init_hap_alignment_struct(hap_alignment_struct* x, uint32_t size)
{
x->vote_counting = (uint64_t*)malloc(sizeof(uint64_t)*size);
memset(x->vote_counting, 0, sizeof(uint64_t)*size);
x->visit = (uint8_t*)malloc(sizeof(uint8_t)*size);
memset(x->visit, 0, size);
kv_init(x->u_vecs.a);
kv_init(x->u_buffer.a);
kv_init(x->u_can.a);
}
void destory_hap_alignment_struct(hap_alignment_struct* x, uint32_t size)
{
free(x->vote_counting);
free(x->visit);
kv_destroy(x->u_vecs.a);
kv_destroy(x->u_buffer.a);
kv_destroy(x->u_can.a);
}
void init_hap_overlaps_list(hap_overlaps_list* x, uint32_t num)
{
uint32_t i = 0;
@@ -205,7 +236,20 @@ uint32_t xUnitigLen, uint32_t yUnitigLen, uint64_t* position_index, uint8_t* rev
}
(*rev) = x_dir^y_dir;
if((*rev)) y_pos = yUnitigLen - y_pos - 1;
if((*rev))
{
if(yUnitigLen <= y_pos)
{
y_pos = (uint32_t)-1;
}
else
{
y_pos = yUnitigLen - y_pos - 1;
}
}
if(x_pos>=xUnitigLen) x_pos = (uint32_t)-1;
if(y_pos>=yUnitigLen) y_pos = (uint32_t)-1;
tmp = x_pos; tmp = tmp << 32; tmp = tmp | y_pos;
return tmp;
@@ -439,6 +483,11 @@ long long targetEnd, long long targetID, long long eMatch, long long eTotal, lon
float Hap_rate, uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g,
R_to_U* ruIndex, uint32_t* n_matchLen, uint32_t* n_max_count, uint32_t* n_min_count)
{
if(queryLen == 0)
{
(*n_matchLen) = (*n_min_count) = (*n_max_count) = 0;
return;
}
long long i, maxId, min_count = eTotal, max_count = eMatch, matchLen = 0;
uint32_t is_found, is_match;
if(dir == 0)
@@ -577,7 +626,6 @@ long long* r_y_interval_beg, long long* r_y_interval_end)
long long x_interval_beg, x_interval_end, y_interval_beg, y_interval_end;
long long target_beg, target_end;
x_max_count = x_min_count = y_max_count = y_min_count = 0;
if(type == X2Y)
{
/********************x*********************/
@@ -675,7 +723,7 @@ long long* r_y_interval_beg, long long* r_y_interval_end)
xUid, 0, xReads->n - 1, Hap_rate, position_index, reverse_sources, read_g, ruIndex, rev,
&y_interval_beg, &y_interval_end);
/********************y*********************/
}
} else abort();
(*r_x_interval_beg) = x_interval_beg;
(*r_x_interval_end) = x_interval_end;
@@ -768,17 +816,17 @@ uint32_t* x_off, uint32_t* y_off)
w_dir = (t.v == w)?1:0;
if(rev == 0 && v_dir != w_dir) continue;
if(rev == 1 && v_dir == w_dir) continue;
tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el));
if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue;
///if(is_found == 0 || ((uint32_t)(tmp>>32) > (*x_off) && ((uint32_t)tmp) > (*y_off)))
if(is_found == 0 || t.ol > oLen)
{
(*x_off) = tmp>>32;
(*y_off) = (uint32_t)tmp;
oLen = t.ol;
}
}
is_found = 1;
}
@@ -828,13 +876,15 @@ uint32_t* x_off, uint32_t* y_off)
tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el));
if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue;
///if(is_found == 0 || ((uint32_t)(tmp>>32) < (*x_off) && ((uint32_t)tmp) < (*y_off)))
if(is_found == 0 || t.ol > oLen)
{
(*x_off) = tmp>>32;
(*y_off) = (uint32_t)tmp;
oLen = t.ol;
}
}
is_found = 1;
}
@@ -868,15 +918,7 @@ long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long lon
return (uint32_t)-1;
}
if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1;
/**
fprintf(stderr, "\nrev: %u, weight: %lu\n", Get_rev(*hap_can), Get_match(*hap_can));
fprintf(stderr, "xUid: %u, xLen: %u, xBase: %u, x_interval_beg: %u, x_interval_end: %u, x_pos_beg: %u, x_pos_end: %u\n",
xUid, xReads->n, xReads->len, Get_x_beg(*hap_can), Get_x_end(*hap_can), x_pos_beg, x_pos_end);
fprintf(stderr, "yUid: %u, yLen: %u, yBase: %u, y_interval_beg: %u, y_interval_end: %u, y_pos_beg: %u, y_pos_end: %u\n",
yUid, yReads->n, yReads->len, Get_y_beg(*hap_can), Get_y_end(*hap_can), y_pos_beg, y_pos_end);
**/
/**
#define X2Y 0
#define Y2X 1
@@ -900,8 +942,8 @@ long long* r_y_pos_beg, long long* r_y_pos_end)
uint32_t xLeftBeg, xLeftLen, yLeftBeg, yLeftLen;
uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen;
uint64_t totalWeigth;
double xLeftMatch, xLeftTotal, yLeftMatch, yLeftTotal;
double xRightMatch, xRightTotal, yRightMatch, yRightTotal;
double xLeftMatch = 0, xLeftTotal = 0, yLeftMatch = 0, yLeftTotal = 0;
double xRightMatch = 0, xRightTotal = 0, yRightMatch = 0, yRightTotal = 0;
asg_arc_t_offset* arch = NULL;
for (i = hap_can->index_beg, totalWeigth = 0; i <= hap_can->index_end; i++)
@@ -964,7 +1006,7 @@ long long* r_y_pos_beg, long long* r_y_pos_end)
&yRightMatch, &yRightTotal);
max_count = xLeftMatch + yRightMatch;
min_count = xLeftTotal + yRightTotal;
}
} else abort();
hap_can->weight = hap_can->index_beg = 0;
@@ -972,6 +1014,7 @@ long long* r_y_pos_beg, long long* r_y_pos_end)
if(max_count > min_count*Hap_rate)
{
long long r_x_interval_beg, r_x_interval_end, r_y_interval_beg, r_y_interval_end;
///for containment, don't need to do anything
get_hap_alignment_boundary(xReads, yReads, flag, xLeftMatch, xLeftTotal,
yLeftMatch, yLeftTotal, xRightMatch, xRightTotal, yRightMatch, yRightTotal,
@@ -1007,6 +1050,14 @@ long long* r_y_pos_beg, long long* r_y_pos_end)
}
void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp)
{
fprintf(stderr, "utg%.6d%c\t%u\t%u\t%u\t%c\tutg%.6d%c\t%u\t%u\t%u\t%u\t%u\n",
ovlp->xUid+1, "lc"[ug->u.a[ovlp->xUid].circ], ug->u.a[ovlp->xUid].len, ovlp->x_beg_pos, ovlp->x_end_pos, "+-"[ovlp->rev],
ovlp->yUid+1, "lc"[ug->u.a[ovlp->yUid].circ], ug->u.a[ovlp->yUid].len, ovlp->y_beg_pos, ovlp->y_end_pos, ovlp->type, (uint32_t)ovlp->weight);
}
void hap_alignment(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources,
R_to_U* ruIndex, ma_sub_t *coverage_cut, uint64_t* position_index, uint64_t* vote_counting,
uint8_t* visit, kvec_t_u64_warp* u_vecs, kvec_asg_arc_t_offset* u_buffer, kvec_hap_candidates* u_can,
@@ -1142,19 +1193,12 @@ hap_overlaps_list* all_ovlp)
t_offset.Off = get_xy_pos(read_g, &t, v, (yReads->a[(uint32_t)(position_index[rId])])>>32,
xReads->len, yReads->len, position_index, &(t.el));
if(((t_offset.Off>>32) == (uint32_t)-1) || (((uint32_t)t_offset.Off) == (uint32_t)-1)) continue;
t_offset.x = t;
t_offset.weight = 1;
kv_push(asg_arc_t_offset, u_buffer->a, t_offset);
// if(debug_enable)
// {
// fprintf(stderr, "xUid: %u, yUid: %u, (%u), x_index: %u, y_index: %u, dis: %lld\n\n",
// xUid, yUid, (uint32_t)(u_buffer->a.n-1),
// (uint32_t)(position_index[u_buffer->a.a[u_buffer->a.n-1].x.ul>>33]),
// (uint32_t)(position_index[u_buffer->a.a[u_buffer->a.n-1].x.v>>1]),
// (long long)((uint32_t)(u_buffer->a.a[u_buffer->a.n-1].Off>>32)) -
// (long long)((uint32_t)(u_buffer->a.a[u_buffer->a.n-1].Off)));
// }
}
deduplicate_edge(u_buffer);
@@ -1296,36 +1340,10 @@ hap_overlaps_list* all_ovlp)
if(Get_match(hap_can) == 0 || Get_total(hap_can) == 0) continue;
kv_push(hap_overlaps, all_ovlp->x[hap_align.xUid].a, hap_align);
/**
fprintf(stderr, "\nsplit\nxUid: %u, yUid: %u, u_buffer->a.n: %u\n", xUid, yUid, (uint32_t)u_buffer->a.n);
for (k = 0; k < u_buffer->a.n; k++)
{
v = u_buffer->a.a[k].x.ul>>33;
w = u_buffer->a.a[k].x.v>>1;
fprintf(stderr, "\n(%u), x_index: %u, x_pos: %u, x_real_pos: %u, dis: %lld, dir: %u, weight: %lu\n",
k, (uint32_t)(position_index[v]), (uint32_t)(position_index[v]>>32),
(uint32_t)(u_buffer->a.a[k].Off>>32), Cal_Off(u_buffer->a.a[k].Off),
u_buffer->a.a[k].x.el, u_buffer->a.a[k].weight);
fprintf(stderr, "(%u), y_index: %u, y_pos: %u, y_real_pos: %u\n", k,
(uint32_t)(position_index[w]), (uint32_t)(position_index[w]>>32),
(uint32_t)(u_buffer->a.a[k].Off));
}
**/
}
}
void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp)
{
fprintf(stderr, "utg%.6d%c\t%u\t%u\t%u\t%c\tutg%.6d%c\t%u\t%u\t%u\t%u\t%u\n",
ovlp->xUid+1, "lc"[ug->u.a[ovlp->xUid].circ], ug->u.a[ovlp->xUid].len, ovlp->x_beg_pos, ovlp->x_end_pos, "+-"[ovlp->rev],
ovlp->yUid+1, "lc"[ug->u.a[ovlp->yUid].circ], ug->u.a[ovlp->yUid].len, ovlp->y_beg_pos, ovlp->y_end_pos, ovlp->type, (uint32_t)ovlp->weight);
}
int inline get_specific_hap_overlap(kvec_hap_overlaps* x, uint32_t qn, uint32_t tn)
{
@@ -2014,6 +2032,7 @@ R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, float density, uint32_t bi_graph_Len
float lable_match_rate, int max_hang, int min_ovlp, long long bubble_dist, float drop_ratio,
uint32_t just_contain)
{
fprintf(stderr, "*****************\n");
asg_t *purge_g = NULL;
purge_g = asg_init();
kvec_t_u64_warp u_vecs;
@@ -2140,9 +2159,10 @@ uint32_t just_contain)
purge_g->seq[all_ovlp.x[uId].a.a[i].xUid].del||
purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].c == ALTER_LABLE||
purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].del)
{
continue;
}
{
continue;
}
///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i]));
r = get_hap_arch(&(all_ovlp.x[uId].a.a[i]), ug->u.a[all_ovlp.x[uId].a.a[i].xUid].len,
ug->u.a[all_ovlp.x[uId].a.a[i].yUid].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t);
@@ -2156,7 +2176,8 @@ uint32_t just_contain)
else
{
print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i]));
fprintf(stderr, "error\n");
fprintf(stderr, "error: uId: %u, i: %u, xUid: %u, yUid: %u\n",
uId, i, all_ovlp.x[uId].a.a[i].xUid, all_ovlp.x[uId].a.a[i].yUid);
}
}
}
@@ -2197,5 +2218,6 @@ uint32_t just_contain)
free(position_index);
free(vote_counting);
free(visit);
fprintf(stderr, "#################\n");
}
+56 -129
View File
@@ -6,68 +6,35 @@
#include "khashl.h" // hash table
#include "kthread.h"
#include "Process_Read.h"
#include "Trio.h"
#include "htab.h"
#include "CommandLines.h"
#define CALLOC(ptr, len) ((ptr) = (__typeof__(ptr))calloc((len), sizeof(*(ptr))))
#define MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr))))
#define REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr))))
#define YAK_MAX_KMER 31
#define YAK_COUNTER_BITS 10 // yak uses 10, but hifiasm uses 12; we have to copy over some yak code here due to this
#define YAK_N_COUNTS (1<<YAK_COUNTER_BITS)
#define YAK_MAX_COUNT ((1<<YAK_COUNTER_BITS)-1)
#define YAK_LOAD_ALL 1
#define YAK_LOAD_TRIOBIN1 2
#define YAK_LOAD_TRIOBIN2 3
#define YAK_MAGIC "YAK\2"
#define yak_ch_eq(a, b) ((a)>>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer
#define yak_ch_hash(a) ((a)>>YAK_COUNTER_BITS)
KHASHL_SET_INIT(, yak_ht_t, yak_ht, uint64_t, yak_ch_hash, yak_ch_eq)
KHASHL_SET_INIT(static klib_unused, yak_ht_t, yak_ht, uint64_t, yak_ch_hash, yak_ch_eq)
///#define CHUNK_SIZE 200000
typedef struct {
struct yak_ht_t *h;
} yak_ch1_t;
unsigned char seq_nt4_table[256] = { // translate ACGT to 0123
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
typedef struct {
int k, pre, n_hash, n_shift;
uint64_t tot;
yak_ch1_t *h;
} yak_ch_t;
static inline uint64_t yak_hash64(uint64_t key, uint64_t mask) // invertible integer hash function
{
key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1;
key = key ^ key >> 24;
key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265
key = key ^ key >> 14;
key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21
key = key ^ key >> 28;
key = (key + (key << 31)) & mask;
return key;
}
static inline uint64_t yak_hash64_64(uint64_t key)
{
key = ~key + (key << 21);
key = key ^ key >> 24;
key = (key + (key << 3)) + (key << 8);
key = key ^ key >> 14;
key = (key + (key << 2)) + (key << 4);
key = key ^ key >> 28;
key = key + (key << 31);
return key;
}
static inline uint64_t yak_hash_long(uint64_t x[4])
{
int j = x[1] < x[3]? 0 : 1;
return yak_hash64_64(x[j<<1|0]) + yak_hash64_64(x[j<<1|1]);
}
int yak_ch_get(const yak_ch_t *h, uint64_t x)
static int yak_ch_get(const yak_ch_t *h, uint64_t x)
{
int mask = (1<<h->pre) - 1;
yak_ht_t *g = h->h[x&mask].h;
@@ -76,21 +43,7 @@ int yak_ch_get(const yak_ch_t *h, uint64_t x)
return k == kh_end(g)? -1 : kh_key(g, k)&YAK_MAX_COUNT;
}
yak_bf_t *yak_bf_init(int n_shift, int n_hashes)
{
yak_bf_t *b;
void *ptr = 0;
if (n_shift + YAK_BLK_SHIFT > 64 || n_shift < YAK_BLK_SHIFT) return 0;
b = (yak_bf_t*)calloc(1, sizeof(yak_bf_t));
b->n_shift = n_shift;
b->n_hashes = n_hashes;
posix_memalign(&ptr, 1<<(YAK_BLK_SHIFT-3), 1ULL<<(n_shift-3));
b->b = (uint8_t*)ptr;
bzero(b->b, 1ULL<<(n_shift-3));
return b;
}
yak_ch_t *yak_ch_init(int k, int pre, int n_hash, int n_shift)
static yak_ch_t *yak_ch_init(int k, int pre)
{
yak_ch_t *h;
int i;
@@ -100,32 +53,10 @@ yak_ch_t *yak_ch_init(int k, int pre, int n_hash, int n_shift)
CALLOC(h->h, 1<<h->pre);
for (i = 0; i < 1<<h->pre; ++i)
h->h[i].h = yak_ht_init();
if (n_hash > 0 && n_shift > h->pre) {
h->n_hash = n_hash, h->n_shift = n_shift;
for (i = 0; i < 1<<h->pre; ++i)
h->h[i].b = yak_bf_init(h->n_shift - h->pre, h->n_hash);
}
return h;
}
void yak_bf_destroy(yak_bf_t *b)
{
if (b == 0) return;
free(b->b); free(b);
}
void yak_ch_destroy_bf(yak_ch_t *h)
{
int i;
for (i = 0; i < 1<<h->pre; ++i) {
if (h->h[i].b)
yak_bf_destroy(h->h[i].b);
h->h[i].b = 0;
}
}
yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...)
static yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...)
{
va_list ap;
FILE *fp;
@@ -161,13 +92,13 @@ yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...)
return 0;
}
ch = ch0 == 0? yak_ch_init(t[0], t[1], 0, 0) : ch0;
ch = ch0 == 0? yak_ch_init(t[0], t[1]) : ch0;
assert((int)t[0] == ch->k && (int)t[1] == ch->pre);
for (i = 0; i < 1<<ch->pre; ++i) {
yak_ht_t *h = ch->h[i].h;
fread(t, 4, 2, fp);
if (ch0 == 0) yak_ht_resize(h, t[0]);
for (j = 0; j < t[1]; ++j) {
for (j = 0; j < (int)t[1]; ++j) {
uint64_t key;
fread(&key, 8, 1, fp);
if (mode == YAK_LOAD_ALL) {
@@ -195,17 +126,39 @@ yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...)
return ch;
}
void yak_ch_destroy(yak_ch_t *h)
static void yak_ch_destroy(yak_ch_t *h)
{
int i;
if (h == 0) return;
yak_ch_destroy_bf(h);
for (i = 0; i < 1<<h->pre; ++i)
yak_ht_destroy(h->h[i].h);
free(h->h); free(h);
}
typedef struct {
int max;
uint32_t *s;
} tb_buf_t;
typedef struct {
int k, n_threads, print_diff;
double ratio_thres;
const yak_ch_t *ch;
tb_buf_t *buf;
UC_Read *bseq;
All_reads* seq;
} tb_shared_t;
typedef struct {
int c[16];
int sc[2];
int nk;
} tb_cnt_t;
typedef struct {
int n_seq;
tb_shared_t *aux;
} tb_step_t;
static char tb_classify(const int sc[2], const int *c, int k, double ratio_thres)
{
@@ -229,8 +182,6 @@ static char tb_classify(const int sc[2], const int *c, int k, double ratio_thres
static void tb_worker(void *_data, long k, int tid)
{
///tb_step_t *t = (tb_step_t*)_data;
///tb_shared_t *aux = t->aux;
tb_shared_t *aux = (tb_shared_t*)_data;
UC_Read *s = &aux->bseq[tid];
recover_UC_Read(s, aux->seq, k);
@@ -266,12 +217,7 @@ static void tb_worker(void *_data, long k, int tid)
if (++l >= aux->k) {
int type = 0, c1, c2;
uint64_t y;
//++t->cnt[k].nk;
++cnt.nk;
if (aux->ch->k < 32)
y = yak_hash64(x[0] < x[1]? x[0] : x[1], mask);
else
@@ -282,28 +228,18 @@ static void tb_worker(void *_data, long k, int tid)
if (c1 == 2 && c2 == 0) type = 1;
else if (c2 == 2 && c1 == 0) type = 2;
b->s[i] = type;
///++t->cnt[k].c[flag];
++cnt.c[flag];
// if (aux->print_diff && (flag>>2&3) != (flag&3))
// printf("D\t%s\t%d\t%d\t%d\n", s->name, i, flag&3, flag>>2&3);
}
} else l = 0, x[0] = x[1] = x[2] = x[3] = 0;
}
for (l = 0, i = 1; i <= s->length; ++i) {
if (i == s->length || b->s[i] != b->s[l]) {
if (b->s[l] > 0 && i - l >= aux->k - 4)
{
///t->cnt[k].sc[b->s[l] - 1] += i - l;
cnt.sc[b->s[l] - 1] += i - l;
}
l = i;
}
}
int *c = cnt.c;
char type;
type = tb_classify(cnt.sc, c, aux->k, aux->ratio_thres);
@@ -312,12 +248,9 @@ static void tb_worker(void *_data, long k, int tid)
if(type == 'm') aux->seq->trio_flag[k] = MOTHER;
}
void trio_partition()
void trio_partition(void)
{
if(asm_opt.pat_index == NULL || asm_opt.mat_index == NULL)
{
if (asm_opt.pat_index == NULL || asm_opt.mat_index == NULL) {
memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads*sizeof(uint8_t));
return;
}
@@ -326,32 +259,26 @@ void trio_partition()
fprintf(stderr, "Start trio binning ...... \n");
yak_ch_t *ch;
int i/**, min_cnt = 2, mid_cnt = 5**/;
int i /**, min_cnt = 2, mid_cnt = 5**/;
tb_shared_t aux;
memset(&aux, 0, sizeof(tb_shared_t));
aux.n_threads = asm_opt.thread_num, aux.print_diff = 0;
aux.ratio_thres = 0.33;
aux.seq = &R_INF;
ch = yak_ch_restore_core(0, asm_opt.pat_index, YAK_LOAD_TRIOBIN1, asm_opt.min_cnt, asm_opt.mid_cnt);
ch = yak_ch_restore_core(ch, asm_opt.mat_index, YAK_LOAD_TRIOBIN2, asm_opt.min_cnt, asm_opt.mid_cnt);
aux.k = ch->k;
aux.ch = ch;
aux.buf = (tb_buf_t*)calloc(aux.n_threads, sizeof(tb_buf_t));
aux.bseq = (UC_Read*)calloc(aux.n_threads, sizeof(UC_Read));
for (i = 0; i < aux.n_threads; ++i)
{
init_UC_Read(&aux.bseq[i]);
}
kt_for(aux.n_threads, tb_worker, &aux, aux.seq->total_reads);
for (i = 0; i < aux.n_threads; ++i)
{
for (i = 0; i < aux.n_threads; ++i) {
free(aux.buf[i].s);
destory_UC_Read(&aux.bseq[i]);
}
@@ -361,4 +288,4 @@ void trio_partition()
fprintf(stderr, "Trio binning has been done.\n");
fprintf(stderr, "%-30s%18.2f\n\n", "Trio binning time:", Get_T() - start_time);
}
}
-71
View File
@@ -1,71 +0,0 @@
#ifndef __TRIO__
#define __TRIO__
#include <stdint.h>
#define YAK_MAX_KMER 31
#define YAK_COUNTER_BITS 10
#define YAK_N_COUNTS (1<<YAK_COUNTER_BITS)
#define YAK_MAX_COUNT ((1<<YAK_COUNTER_BITS)-1)
#define YAK_BLK_SHIFT 9 // 64 bytes, the size of a cache line
#define YAK_BLK_MASK ((1<<(YAK_BLK_SHIFT)) - 1)
#define YAK_LOAD_ALL 1
#define YAK_LOAD_TRIOBIN1 2
#define YAK_LOAD_TRIOBIN2 3
#define YAK_MAGIC "YAK\2"
typedef struct {
int n_shift, n_hashes;
uint8_t *b;
} yak_bf_t;
struct yak_ht_t;
typedef struct {
struct yak_ht_t *h;
yak_bf_t *b;
} yak_ch1_t;
typedef struct {
int k, pre, n_hash, n_shift;
uint64_t tot;
yak_ch1_t *h;
} yak_ch_t;
typedef struct {
int max;
uint32_t *s;
} tb_buf_t;
typedef struct {
int k, n_threads, print_diff;
double ratio_thres;
///bseq_file_t *fp;
const yak_ch_t *ch;
tb_buf_t *buf;
UC_Read *bseq;
All_reads* seq;
} tb_shared_t;
typedef struct {
int c[16];
int sc[2];
int nk;
} tb_cnt_t;
typedef struct {
int n_seq;
tb_shared_t *aux;
///bseq1_t *seq;
///All_reads* seq;
///tb_cnt_t *cnt;
} tb_step_t;
void trio_partition();
#endif
+158
View File
@@ -0,0 +1,158 @@
#include <stdio.h>
#include "htab.h"
#include "ksort.h"
#include "Hash_Table.h"
typedef struct { // this struct is not strictly necessary; we can use k_mer_pos instead, with modifications
uint64_t srt;
uint32_t self_off;
uint32_t other_off;
} anchor1_t;
#define an_key1(a) ((a).srt)
#define an_key2(a) ((a).self_off)
KRADIX_SORT_INIT(ha_an1, anchor1_t, an_key1, 8)
KRADIX_SORT_INIT(ha_an2, anchor1_t, an_key2, 4)
#define oreg_xs_lt(a, b) (((uint64_t)(a).x_pos_s<<32|(a).x_pos_e) < ((uint64_t)(b).x_pos_s<<32|(b).x_pos_e))
KSORT_INIT(or_xs, overlap_region, oreg_xs_lt)
#define oreg_ss_lt(a, b) ((a).shared_seed > (b).shared_seed) // in the decending order
KSORT_INIT(or_ss, overlap_region, oreg_ss_lt)
typedef struct {
int n;
const ha_idxpos_t *a;
} seed1_t;
struct ha_abuf_s {
uint64_t n_a, m_a;
uint32_t old_mz_m;
ha_mz1_v mz;
seed1_t *seed;
anchor1_t *a;
};
ha_abuf_t *ha_abuf_init(void)
{
return (ha_abuf_t*)calloc(1, sizeof(ha_abuf_t));
}
void ha_abuf_destroy(ha_abuf_t *ab)
{
free(ab->seed); free(ab->a); free(ab->mz.a); free(ab);
}
uint64_t ha_abuf_mem(const ha_abuf_t *ab)
{
return ab->m_a * sizeof(anchor1_t) + ab->mz.m * (sizeof(ha_mz1_t) + sizeof(seed1_t)) + sizeof(ha_abuf_t);
}
void ha_get_new_candidates(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain)
{
extern void *ha_flt_tab;
extern ha_pt_t *ha_idx;
uint32_t i;
uint64_t k, l;
// prepare
clear_Candidates_list(cl);
clear_overlap_region_alloc(overlap_list);
recover_UC_Read(ucr, &R_INF, rid);
ab->mz.n = 0, ab->n_a = 0;
// get the list of anchors
ha_sketch(ucr->seq, ucr->length, asm_opt.mz_win, asm_opt.k_mer_length, 0, !asm_opt.no_HPC, &ab->mz, ha_flt_tab);
if (ab->mz.m > ab->old_mz_m) {
ab->old_mz_m = ab->mz.m;
REALLOC(ab->seed, ab->old_mz_m);
}
for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) {
ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &ab->seed[i].n);
ab->n_a += ab->seed[i].n;
}
if (ab->n_a > ab->m_a) {
ab->m_a = ab->n_a;
kroundup64(ab->m_a);
REALLOC(ab->a, ab->m_a);
}
for (i = 0, k = 0; i < ab->mz.n; ++i) {
int j;
ha_mz1_t *z = &ab->mz.a[i];
seed1_t *s = &ab->seed[i];
for (j = 0; j < s->n; ++j) {
const ha_idxpos_t *y = &s->a[j];
anchor1_t *an = &ab->a[k++];
uint8_t rev = z->rev == y->rev? 0 : 1;
an->other_off = y->pos;
an->self_off = rev? ucr->length - 1 - (z->pos + 1 - z->span) : z->pos;
an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off;
}
}
// sort anchors
radix_sort_ha_an1(ab->a, ab->a + ab->n_a);
for (k = 1, l = 0; k <= ab->n_a; ++k) {
if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) {
if (k - l > 1)
radix_sort_ha_an2(ab->a + l, ab->a + k);
l = k;
}
}
// copy over to _cl_
if (ab->m_a >= (uint64_t)cl->size) {
cl->size = ab->m_a;
REALLOC(cl->list, cl->size);
}
for (k = 0; k < ab->n_a; ++k) {
k_mer_hit *p = &cl->list[k];
p->readID = ab->a[k].srt >> 33;
p->strand = ab->a[k].srt >> 32 & 1;
p->offset = ab->a[k].other_off;
p->self_offset = ab->a[k].self_off;
}
cl->length = ab->n_a;
calculate_overlap_region_by_chaining(cl, overlap_list, rid, ucr->length, &R_INF, bw_thres, keep_whole_chain);
#if 0
if (overlap_list->length > 2000) {
fprintf(stderr, "B\t%ld\t%ld\t%ld\n", (long)rid, (long)overlap_list->length, (long)Get_READ_LENGTH(R_INF, rid));
for (int i = 0; i < (int)overlap_list->length; ++i) {
overlap_region *r = &overlap_list->list[i];
fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand],
(int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed);
}
}
#endif
if ((int)overlap_list->length > max_n_chain) {
uint32_t n[2], s[2];
n[0] = n[1] = 0, s[0] = s[1] = 0;
for (i = 0; i < (uint32_t)overlap_list->length; ++i) {
const overlap_region *r = &overlap_list->list[i];
int dir = r->x_pos_s == 0? 0 : 1;
++n[dir];
if ((int)n[dir] == max_n_chain) s[dir] = r->shared_seed;
}
if (s[0] > 0 || s[1] > 0) {
for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) {
overlap_region *r = &overlap_list->list[i];
int dir = r->x_pos_s == 0? 0 : 1;
if (r->shared_seed > s[dir]) {
if ((uint32_t)k != i) {
overlap_region t;
t = overlap_list->list[k];
overlap_list->list[k] = overlap_list->list[i];
overlap_list->list[i] = t;
}
++k;
}
}
overlap_list->length = k;
}
}
ks_introsort_or_xs(overlap_list->length, overlap_list->list);
}
+4
View File
@@ -202,7 +202,11 @@ but occurs <
times in the other sample.
.SS Debugging options
.TP 10
.B --dbg-gfa
Write additional files to speed up the debugging of graph cleaning
.SH EXAMPLES
+92
View File
@@ -0,0 +1,92 @@
#include <stdio.h>
#include "htab.h"
static void ha_hist_line(int c, int x, int exceed, int64_t cnt)
{
int j;
if (c >= 0) fprintf(stderr, "[M::%s] %5d: ", __func__, c);
else fprintf(stderr, "[M::%s] %5s: ", __func__, "rest");
for (j = 0; j < x; ++j) fputc('*', stderr);
if (exceed) fputc('>', stderr);
fprintf(stderr, " %lld\n", (long long)cnt);
}
int ha_analyze_count(int n_cnt, const int64_t *cnt, int *peak_het)
{
const int hist_max = 100;
int i, start, low_i, max_i, max2_i, max3_i;
int64_t max, max2, max3, min;
// find the low point from the left
*peak_het = -1;
start = cnt[1] > 0? 1 : 2;
low_i = start;
for (i = low_i + 1; i < n_cnt; ++i)
if (cnt[i] > cnt[i-1]) break;
low_i = i - 1;
fprintf(stderr, "[M::%s] lowest: count[%d] = %ld\n", __func__, low_i, (long)cnt[low_i]);
if (low_i == n_cnt - 1) return -1; // low coverage
// find the highest peak
max_i = low_i + 1, max = cnt[max_i];
for (i = low_i + 1; i < n_cnt; ++i)
if (cnt[i] > max)
max = cnt[i], max_i = i;
fprintf(stderr, "[M::%s] highest: count[%d] = %ld\n", __func__, max_i, (long)cnt[max_i]);
// print histogram
for (i = start; i < n_cnt; ++i) {
int x, exceed = 0;
x = (int)((double)hist_max * cnt[i] / cnt[max_i] + .499);
if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher
if (i > max_i && x == 0) break;
ha_hist_line(i, x, exceed, cnt[i]);
}
{
int x, exceed = 0;
int64_t rest = 0;
for (; i < n_cnt; ++i) rest += cnt[i];
x = (int)((double)hist_max * rest / cnt[max_i] + .499);
if (x > hist_max) exceed = 1, x = hist_max;
ha_hist_line(-1, x, exceed, rest);
}
// look for smaller peak on the low end
max2 = -1; max2_i = -1;
for (i = max_i - 1; i > low_i; --i) {
if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) {
if (cnt[i] > max2) max2 = cnt[i], max2_i = i;
}
}
if (max2_i > low_i && max2_i < max_i) {
for (i = max2_i + 1, min = max; i < max_i; ++i)
if (cnt[i] < min) min = cnt[i];
if (max2 < max * 0.05 || min > max2 * 0.95)
max2 = -1, max2_i = -1;
}
if (max2 > 0) fprintf(stderr, "[M::%s] left: count[%d] = %ld\n", __func__, max2_i, (long)cnt[max2_i]);
else fprintf(stderr, "[M::%s] left: none\n", __func__);
// look for smaller peak on the high end
max3 = -1; max3_i = -1;
for (i = max_i + 1; i < n_cnt - 1; ++i) {
if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) {
if (cnt[i] > max3) max3 = cnt[i], max3_i = i;
}
}
if (max3_i > max_i) {
for (i = max_i + 1, min = max; i < max3_i; ++i)
if (cnt[i] < min) min = cnt[i];
if (max3 < max * 0.05 || min > max3 * 0.95 || max3_i > max_i * 2.5)
max3 = -1, max3_i = -1;
}
if (max3 > 0) fprintf(stderr, "[M::%s] right: count[%d] = %ld\n", __func__, max3_i, (long)cnt[max3_i]);
else fprintf(stderr, "[M::%s] right: none\n", __func__);
if (max3_i > 0) {
*peak_het = max_i;
return max3_i;
} else {
if (max2_i > 0) *peak_het = max2_i;
return max_i;
}
}
+832
View File
@@ -0,0 +1,832 @@
#include <stdint.h>
#include <zlib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "kthread.h"
#include "khashl.h"
#include "kseq.h"
#include "ksort.h"
#include "htab.h"
#define YAK_COUNTER_BITS 12
#define YAK_N_COUNTS (1<<YAK_COUNTER_BITS)
#define YAK_MAX_COUNT ((1<<YAK_COUNTER_BITS)-1)
const unsigned char seq_nt4_table[256] = { // translate ACGT to 0123
0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
void *ha_flt_tab;
ha_pt_t *ha_idx;
/***************************
* Yak specific parameters *
***************************/
typedef struct {
int32_t bf_shift, bf_n_hash;
int32_t k, w, is_HPC;
int32_t pre;
int32_t n_thread;
int64_t chunk_size;
} yak_copt_t;
void yak_copt_init(yak_copt_t *o)
{
memset(o, 0, sizeof(yak_copt_t));
o->bf_shift = 0;
o->bf_n_hash = 4;
o->k = 31;
o->w = 1;
o->pre = YAK_COUNTER_BITS;
o->n_thread = 4;
o->chunk_size = 20000000;
}
/************************
* Blocked bloom filter *
************************/
#define YAK_BLK_SHIFT 9 // 64 bytes, the size of a cache line
#define YAK_BLK_MASK ((1<<(YAK_BLK_SHIFT)) - 1)
typedef struct {
int n_shift, n_hashes;
uint8_t *b;
} yak_bf_t;
yak_bf_t *yak_bf_init(int n_shift, int n_hashes)
{
yak_bf_t *b;
void *ptr = 0;
if (n_shift + YAK_BLK_SHIFT > 64 || n_shift < YAK_BLK_SHIFT) return 0;
CALLOC(b, 1);
b->n_shift = n_shift;
b->n_hashes = n_hashes;
posix_memalign(&ptr, 1<<(YAK_BLK_SHIFT-3), 1ULL<<(n_shift-3));
b->b = (uint8_t*)ptr;
bzero(b->b, 1ULL<<(n_shift-3));
return b;
}
void yak_bf_destroy(yak_bf_t *b)
{
if (b == 0) return;
free(b->b); free(b);
}
int yak_bf_insert(yak_bf_t *b, uint64_t hash)
{
int x = b->n_shift - YAK_BLK_SHIFT;
uint64_t y = hash & ((1ULL<<x) - 1);
int h1 = hash >> x & YAK_BLK_MASK;
int h2 = hash >> b->n_shift & YAK_BLK_MASK;
uint8_t *p = &b->b[y<<(YAK_BLK_SHIFT-3)];
int i, z = h1, cnt = 0;
if ((h2&31) == 0) h2 = (h2 + 1) & YAK_BLK_MASK; // otherwise we may repeatedly use a few bits
for (i = 0; i < b->n_hashes; z = (z + h2) & YAK_BLK_MASK) {
uint8_t *q = &p[z>>3], u;
u = 1<<(z&7);
cnt += !!(*q & u);
*q |= u;
++i;
}
return cnt;
}
/********************
* Count hash table *
********************/
#define yak_ct_eq(a, b) ((a)>>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer
#define yak_ct_hash(a) ((a)>>YAK_COUNTER_BITS)
KHASHL_SET_INIT(static klib_unused, yak_ct_t, yak_ct, uint64_t, yak_ct_hash, yak_ct_eq)
typedef struct {
yak_ct_t *h;
yak_bf_t *b;
} ha_ct1_t;
typedef struct {
int k, pre, n_hash, n_shift;
uint64_t tot;
ha_ct1_t *h;
} ha_ct_t;
static ha_ct_t *ha_ct_init(int k, int pre, int n_hash, int n_shift)
{
ha_ct_t *h;
int i;
if (pre < YAK_COUNTER_BITS) return 0;
CALLOC(h, 1);
h->k = k, h->pre = pre;
CALLOC(h->h, 1<<h->pre);
for (i = 0; i < 1<<h->pre; ++i)
h->h[i].h = yak_ct_init();
if (n_hash > 0 && n_shift > h->pre) {
h->n_hash = n_hash, h->n_shift = n_shift;
for (i = 0; i < 1<<h->pre; ++i)
h->h[i].b = yak_bf_init(h->n_shift - h->pre, h->n_hash);
}
return h;
}
static void ha_ct_destroy_bf(ha_ct_t *h)
{
int i;
for (i = 0; i < 1<<h->pre; ++i) {
if (h->h[i].b)
yak_bf_destroy(h->h[i].b);
h->h[i].b = 0;
}
}
static void ha_ct_destroy(ha_ct_t *h)
{
int i;
if (h == 0) return;
ha_ct_destroy_bf(h);
for (i = 0; i < 1<<h->pre; ++i)
yak_ct_destroy(h->h[i].h);
free(h->h); free(h);
}
static int ha_ct_insert_list(ha_ct_t *h, int create_new, int n, const uint64_t *a)
{
int j, mask = (1<<h->pre) - 1, n_ins = 0;
ha_ct1_t *g;
if (n == 0) return 0;
g = &h->h[a[0]&mask];
for (j = 0; j < n; ++j) {
int ins = 1, absent;
uint64_t x = a[j] >> h->pre;
khint_t k;
if ((a[j]&mask) != (a[0]&mask)) continue;
if (create_new) {
if (g->b)
ins = (yak_bf_insert(g->b, x) == h->n_hash);
if (ins) {
k = yak_ct_put(g->h, x << YAK_COUNTER_BITS | (g->b? 1 : 0), &absent);
if (absent) ++n_ins;
if ((kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT)
++kh_key(g->h, k);
}
} else {
k = yak_ct_get(g->h, x<<YAK_COUNTER_BITS);
if (k != kh_end(g->h) && (kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT)
++kh_key(g->h, k);
}
}
return n_ins;
}
/*** generate histogram ***/
typedef struct {
uint64_t c[YAK_N_COUNTS];
} buf_cnt_t;
typedef struct {
const ha_ct_t *h;
buf_cnt_t *cnt;
} hist_aux_t;
static void worker_ct_hist(void *data, long i, int tid) // callback for kt_for()
{
hist_aux_t *a = (hist_aux_t*)data;
uint64_t *cnt = a->cnt[tid].c;
yak_ct_t *g = a->h->h[i].h;
khint_t k;
for (k = 0; k < kh_end(g); ++k)
if (kh_exist(g, k))
++cnt[kh_key(g, k)&YAK_MAX_COUNT];
}
static void ha_ct_hist(const ha_ct_t *h, int64_t cnt[YAK_N_COUNTS], int n_thread)
{
hist_aux_t a;
int i, j;
a.h = h;
memset(cnt, 0, YAK_N_COUNTS * sizeof(uint64_t));
CALLOC(a.cnt, n_thread);
kt_for(n_thread, worker_ct_hist, &a, 1<<h->pre);
for (i = 0; i < YAK_N_COUNTS; ++i) cnt[i] = 0;
for (j = 0; j < n_thread; ++j)
for (i = 0; i < YAK_N_COUNTS; ++i)
cnt[i] += a.cnt[j].c[i];
free(a.cnt);
}
/*** shrink a hash table ***/
typedef struct {
int min, max;
ha_ct_t *h;
} shrink_aux_t;
static void worker_ct_shrink(void *data, long i, int tid) // callback for kt_for()
{
shrink_aux_t *a = (shrink_aux_t*)data;
ha_ct_t *h = a->h;
yak_ct_t *g = h->h[i].h, *f;
khint_t k;
f = yak_ct_init();
yak_ct_resize(f, kh_size(g));
for (k = 0; k < kh_end(g); ++k) {
if (kh_exist(g, k)) {
int absent, c = kh_key(g, k) & YAK_MAX_COUNT;
if (c >= a->min && c <= a->max)
yak_ct_put(f, kh_key(g, k), &absent);
}
}
yak_ct_destroy(g);
h->h[i].h = f;
}
static void ha_ct_shrink(ha_ct_t *h, int min, int max, int n_thread)
{
int i;
shrink_aux_t a;
a.h = h, a.min = min, a.max = max;
kt_for(n_thread, worker_ct_shrink, &a, 1<<h->pre);
for (i = 0, h->tot = 0; i < 1<<h->pre; ++i)
h->tot += kh_size(h->h[i].h);
}
/***********************
* Position hash table *
***********************/
KHASHL_MAP_INIT(static klib_unused, yak_pt_t, yak_pt, uint64_t, uint64_t, yak_ct_hash, yak_ct_eq)
#define generic_key(x) (x)
KRADIX_SORT_INIT(ha64, uint64_t, generic_key, 8)
typedef struct {
yak_pt_t *h;
uint64_t n;
ha_idxpos_t *a;
} ha_pt1_t;
struct ha_pt_s {
int k, pre;
uint64_t tot, tot_pos;
ha_pt1_t *h;
};
typedef struct {
const ha_ct_t *ct;
ha_pt_t *pt;
} pt_gen_aux_t;
static void worker_pt_gen(void *data, long i, int tid) // callback for kt_for()
{
pt_gen_aux_t *a = (pt_gen_aux_t*)data;
ha_pt1_t *b = &a->pt->h[i];
yak_ct_t *g = a->ct->h[i].h;
khint_t k;
for (k = 0, b->n = 0; k != kh_end(g); ++k) {
if (kh_exist(g, k)) {
int absent;
khint_t l;
l = yak_pt_put(b->h, kh_key(g, k) >> a->ct->pre << YAK_COUNTER_BITS, &absent);
kh_val(b->h, l) = b->n;
b->n += kh_key(g, k) & YAK_MAX_COUNT;
}
}
yak_ct_destroy(g);
a->ct->h[i].h = 0;
CALLOC(b->a, b->n);
}
ha_pt_t *ha_pt_gen(ha_ct_t *ct, int n_thread)
{
pt_gen_aux_t a;
int i;
ha_pt_t *pt;
ha_ct_destroy_bf(ct);
CALLOC(pt, 1);
pt->k = ct->k, pt->pre = ct->pre, pt->tot = ct->tot;
CALLOC(pt->h, 1<<pt->pre);
for (i = 0; i < 1<<pt->pre; ++i) {
pt->h[i].h = yak_pt_init();
yak_pt_resize(pt->h[i].h, kh_size(ct->h[i].h));
}
a.ct = ct, a.pt = pt;
kt_for(n_thread, worker_pt_gen, &a, 1<<pt->pre);
free(ct->h); free(ct);
return pt;
}
int ha_pt_insert_list(ha_pt_t *h, int n, const ha_mz1_t *a)
{
int j, mask = (1<<h->pre) - 1, n_ins = 0;
ha_pt1_t *g;
if (n == 0) return 0;
g = &h->h[a[0].x&mask];
for (j = 0; j < n; ++j) {
uint64_t x = a[j].x >> h->pre;
khint_t k;
int n;
ha_idxpos_t *p;
if ((a[j].x&mask) != (a[0].x&mask)) continue;
k = yak_pt_get(g->h, x<<YAK_COUNTER_BITS);
if (k == kh_end(g->h)) continue;
n = kh_key(g->h, k) & YAK_MAX_COUNT;
assert(n < YAK_MAX_COUNT);
p = &g->a[kh_val(g->h, k) + n];
p->rid = a[j].rid, p->rev = a[j].rev, p->pos = a[j].pos, p->span = a[j].span;
//(uint64_t)a[j].rid<<36 | (uint64_t)a[j].rev<<35 | (uint64_t)a[j].pos<<8 | (uint64_t)a[j].span;
++kh_key(g->h, k);
++n_ins;
}
return n_ins;
}
/*
static void worker_pt_sort(void *data, long i, int tid)
{
ha_pt_t *h = (ha_pt_t*)data;
ha_pt1_t *g = &h->h[i];
khint_t k;
for (k = 0; k < kh_end(g->h); ++k) {
int n;
uint64_t *p;
if (!kh_exist(g->h, k)) continue;
n = kh_key(g->h, k) & YAK_MAX_COUNT;
p = &g->a[kh_val(g->h, k)];
radix_sort_ha64(p, p + n);
}
}
void ha_pt_sort(ha_pt_t *h, int n_thread)
{
kt_for(n_thread, worker_pt_sort, h, 1<<h->pre);
}
*/
void ha_pt_destroy(ha_pt_t *h)
{
int i;
if (h == 0) return;
for (i = 0; i < 1<<h->pre; ++i) {
yak_pt_destroy(h->h[i].h);
free(h->h[i].a);
}
free(h->h); free(h);
}
const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n)
{
khint_t k;
const ha_pt1_t *g = &h->h[hash & ((1ULL<<h->pre) - 1)];
*n = 0;
k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS);
if (k == kh_end(g->h)) return 0;
*n = kh_key(g->h, k) & YAK_MAX_COUNT;
return &g->a[kh_val(g->h, k)];
}
/**********************************
* Buffer for counting all k-mers *
**********************************/
typedef struct {
int n, m;
uint64_t n_ins;
uint64_t *a;
ha_mz1_t *b;
} ch_buf_t;
static inline void ct_insert_buf(ch_buf_t *buf, int p, uint64_t y) // insert a k-mer $y to a linear buffer
{
int pre = y & ((1<<p) - 1);
ch_buf_t *b = &buf[pre];
if (b->n == b->m) {
b->m = b->m < 8? 8 : b->m + (b->m>>1);
REALLOC(b->a, b->m);
}
b->a[b->n++] = y;
}
static inline void pt_insert_buf(ch_buf_t *buf, int p, const ha_mz1_t *y)
{
int pre = y->x & ((1<<p) - 1);
ch_buf_t *b = &buf[pre];
if (b->n == b->m) {
b->m = b->m < 8? 8 : b->m + (b->m>>1);
REALLOC(b->b, b->m);
}
b->b[b->n++] = *y;
}
static void count_seq_buf(ch_buf_t *buf, int k, int p, int len, const char *seq) // insert k-mers in $seq to linear buffer $buf
{
int i, l;
uint64_t x[4], mask = (1ULL<<k) - 1, shift = k - 1;
for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) {
int c = seq_nt4_table[(uint8_t)seq[i]];
if (c < 4) { // not an "N" base
x[0] = (x[0] << 1 | (c&1)) & mask;
x[1] = (x[1] << 1 | (c>>1)) & mask;
x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;
x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;
if (++l >= k)
ct_insert_buf(buf, p, yak_hash_long(x));
} else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart
}
}
static void count_seq_buf_HPC(ch_buf_t *buf, int k, int p, int len, const char *seq) // insert k-mers in $seq to linear buffer $buf
{
int i, l, last = -1;
uint64_t x[4], mask = (1ULL<<k) - 1, shift = k - 1;
for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) {
int c = seq_nt4_table[(uint8_t)seq[i]];
if (c < 4) { // not an "N" base
if (c != last) {
x[0] = (x[0] << 1 | (c&1)) & mask;
x[1] = (x[1] << 1 | (c>>1)) & mask;
x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;
x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;
if (++l >= k)
ct_insert_buf(buf, p, yak_hash_long(x));
last = c;
}
} else l = 0, last = -1, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart
}
}
/******************
* K-mer counting *
******************/
KSEQ_INIT(gzFile, gzread)
#define HAF_COUNT_EXACT 0x1
#define HAF_COUNT_ALL 0x2
#define HAF_RS_WRITE_LEN 0x4
#define HAF_RS_WRITE_SEQ 0x8
#define HAF_RS_READ 0x10
typedef struct { // global data structure for kt_pipeline()
const yak_copt_t *opt;
const void *flt_tab;
int flag, create_new, is_store;
uint64_t n_seq;
kseq_t *ks;
UC_Read ucr;
ha_ct_t *ct;
ha_pt_t *pt;
const All_reads *rs_in;
All_reads *rs_out;
} pl_data_t;
typedef struct { // data structure for each step in kt_pipeline()
pl_data_t *p;
uint64_t n_seq0;
int n_seq, m_seq, sum_len, nk;
int *len;
char **seq;
ha_mz1_v *mz_buf;
ha_mz1_v *mz;
ch_buf_t *buf;
} st_data_t;
static void worker_for_insert(void *data, long i, int tid) // callback for kt_for()
{
st_data_t *s = (st_data_t*)data;
ch_buf_t *b = &s->buf[i];
if (s->p->pt)
b->n_ins += ha_pt_insert_list(s->p->pt, b->n, b->b);
else
b->n_ins += ha_ct_insert_list(s->p->ct, s->p->create_new, b->n, b->a);
}
static void worker_for_mz(void *data, long i, int tid)
{
st_data_t *s = (st_data_t*)data;
ha_mz1_v *b = &s->mz_buf[tid];
s->mz_buf[tid].n = 0;
ha_sketch(s->seq[i], s->len[i], s->p->opt->w, s->p->opt->k, s->n_seq0 + i, s->p->opt->is_HPC, b, s->p->flt_tab);
s->mz[i].n = s->mz[i].m = b->n;
MALLOC(s->mz[i].a, b->n);
memcpy(s->mz[i].a, b->a, b->n * sizeof(ha_mz1_t));
}
static void *worker_count(void *data, int step, void *in) // callback for kt_pipeline()
{
pl_data_t *p = (pl_data_t*)data;
if (step == 0) { // step 1: read a block of sequences
int ret;
st_data_t *s;
CALLOC(s, 1);
s->p = p;
s->n_seq0 = p->n_seq;
if (p->rs_in && (p->flag & HAF_RS_READ)) {
while (p->n_seq < p->rs_in->total_reads) {
int l;
recover_UC_Read(&p->ucr, p->rs_in, p->n_seq);
l = p->ucr.length;
if (s->n_seq == s->m_seq) {
s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);
REALLOC(s->len, s->m_seq);
REALLOC(s->seq, s->m_seq);
}
MALLOC(s->seq[s->n_seq], l);
memcpy(s->seq[s->n_seq], p->ucr.seq, l);
s->len[s->n_seq++] = l;
++p->n_seq;
s->sum_len += l;
s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;
if (s->sum_len >= p->opt->chunk_size)
break;
}
} else {
while ((ret = kseq_read(p->ks)) >= 0) {
int l = p->ks->seq.l;
if (p->n_seq >= 1<<28) {
fprintf(stderr, "ERROR: this implementation supports no more than %d reads\n", 1<<28);
exit(1);
}
if (p->rs_out) {
if (p->flag & HAF_RS_WRITE_LEN) {
assert(p->n_seq == p->rs_out->total_reads);
ha_insert_read_len(p->rs_out, l, p->ks->name.l);
} else if (p->flag & HAF_RS_WRITE_SEQ) {
int i, n_N;
assert(l == (int)p->rs_out->read_length[p->n_seq]);
for (i = n_N = 0; i < l; ++i) // count number of ambiguous bases
if (seq_nt4_table[(uint8_t)p->ks->seq.s[i]] >= 4)
++n_N;
ha_compress_base(Get_READ(*p->rs_out, p->n_seq), p->ks->seq.s, l, &p->rs_out->N_site[p->n_seq], n_N);
memcpy(&p->rs_out->name[p->rs_out->name_index[p->n_seq]], p->ks->name.s, p->ks->name.l);
}
}
if (s->n_seq == s->m_seq) {
s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);
REALLOC(s->len, s->m_seq);
REALLOC(s->seq, s->m_seq);
}
MALLOC(s->seq[s->n_seq], l);
memcpy(s->seq[s->n_seq], p->ks->seq.s, l);
s->len[s->n_seq++] = l;
++p->n_seq;
s->sum_len += l;
s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;
if (s->sum_len >= p->opt->chunk_size)
break;
}
}
if (s->sum_len == 0) free(s);
else return s;
} else if (step == 1) { // step 2: extract k-mers
st_data_t *s = (st_data_t*)in;
int i, n_pre = 1<<p->opt->pre, m;
// allocate the k-mer buffer
CALLOC(s->buf, n_pre);
m = (int)(s->nk * 1.2 / n_pre) + 1;
for (i = 0; i < n_pre; ++i) {
s->buf[i].m = m;
if (p->pt) MALLOC(s->buf[i].b, m);
else MALLOC(s->buf[i].a, m);
}
// fill the buffer
if (p->opt->w == 1) { // enumerate all k-mers
for (i = 0; i < s->n_seq; ++i) {
if (p->opt->is_HPC)
count_seq_buf_HPC(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);
else
count_seq_buf(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);
if (!p->is_store) free(s->seq[i]);
}
} else { // minimizers only
uint32_t j;
// compute minimizers
CALLOC(s->mz, s->n_seq);
CALLOC(s->mz_buf, p->opt->n_thread);
kt_for(p->opt->n_thread, worker_for_mz, s, s->n_seq);
for (i = 0; i < p->opt->n_thread; ++i)
free(s->mz_buf[i].a);
free(s->mz_buf);
// insert minimizers
if (p->pt) {
for (i = 0; i < s->n_seq; ++i)
for (j = 0; j < s->mz[i].n; ++j)
pt_insert_buf(s->buf, p->opt->pre, &s->mz[i].a[j]);
} else {
for (i = 0; i < s->n_seq; ++i)
for (j = 0; j < s->mz[i].n; ++j)
ct_insert_buf(s->buf, p->opt->pre, s->mz[i].a[j].x);
}
for (i = 0; i < s->n_seq; ++i) {
free(s->mz[i].a);
if (!p->is_store) free(s->seq[i]);
}
free(s->mz);
}
free(s->seq); free(s->len);
s->seq = 0, s->len = 0;
return s;
} else if (step == 2) { // step 3: insert k-mers to hash table
st_data_t *s = (st_data_t*)in;
int i, n = 1<<p->opt->pre;
uint64_t n_ins = 0;
kt_for(p->opt->n_thread, worker_for_insert, s, n);
for (i = 0; i < n; ++i) {
n_ins += s->buf[i].n_ins;
if (p->pt) free(s->buf[i].b);
else free(s->buf[i].a);
}
if (p->ct) p->ct->tot += n_ins;
if (p->pt) p->pt->tot_pos += n_ins;
free(s->buf);
#if 0
fprintf(stderr, "[M::%s::%.3f*%.2f] processed %ld sequences; %ld %s in the hash table\n", __func__,
yak_realtime(), yak_cpu_usage(), (long)s->n_seq0 + s->n_seq,
(long)(p->pt? p->pt->tot_pos : p->ct->tot), p->pt? "positions" : "distinct k-mers");
#endif
free(s);
}
return 0;
}
static ha_ct_t *yak_count(const yak_copt_t *opt, const char *fn, int flag, ha_pt_t *p0, ha_ct_t *c0, const void *flt_tab, All_reads *rs)
{
int read_rs = (rs && (flag & HAF_RS_READ));
pl_data_t pl;
gzFile fp = 0;
memset(&pl, 0, sizeof(pl_data_t));
if (read_rs) {
pl.rs_in = rs;
init_UC_Read(&pl.ucr);
} else {
if ((fp = gzopen(fn, "r")) == 0) return 0;
pl.ks = kseq_init(fp);
}
if (rs && (flag & (HAF_RS_WRITE_LEN|HAF_RS_WRITE_SEQ)))
pl.rs_out = rs;
pl.flt_tab = flt_tab;
pl.opt = opt;
pl.flag = flag;
if (p0) {
pl.pt = p0, pl.create_new = 0;
assert(p0->k == opt->k && p0->pre == opt->pre);
} else if (c0) {
pl.ct = c0, pl.create_new = 0;
assert(c0->k == opt->k && c0->pre == opt->pre);
} else {
pl.create_new = 1;
pl.ct = ha_ct_init(opt->k, opt->pre, opt->bf_n_hash, opt->bf_shift);
}
kt_pipeline(3, worker_count, &pl, 3);
if (read_rs) {
destory_UC_Read(&pl.ucr);
} else {
kseq_destroy(pl.ks);
gzclose(fp);
}
return pl.ct;
}
ha_ct_t *ha_count(const hifiasm_opt_t *asm_opt, int flag, ha_pt_t *p0, const void *flt_tab, All_reads *rs)
{
int i;
yak_copt_t opt;
ha_ct_t *h = 0;
assert(!(flag & HAF_RS_WRITE_LEN) || !(flag & HAF_RS_WRITE_SEQ)); // not both
if (rs) {
if (flag & HAF_RS_WRITE_LEN)
init_All_reads(rs);
else if (flag & HAF_RS_WRITE_SEQ)
malloc_All_reads(rs);
}
yak_copt_init(&opt);
opt.k = asm_opt->k_mer_length;
opt.is_HPC = !asm_opt->no_HPC;
opt.w = flag & HAF_COUNT_ALL? 1 : asm_opt->mz_win;
opt.bf_shift = flag & HAF_COUNT_EXACT? 0 : asm_opt->bf_shift;
opt.n_thread = asm_opt->thread_num;
for (i = 0; i < asm_opt->num_reads; ++i)
h = yak_count(&opt, asm_opt->read_file_names[i], flag, p0, h, flt_tab, rs);
if (h && opt.bf_shift > 0)
ha_ct_destroy_bf(h);
return h;
}
/***************************
* High count filter table *
***************************/
KHASHL_SET_INIT(static klib_unused, yak_ft_t, yak_ft, uint64_t, kh_hash_dummy, kh_eq_generic)
static yak_ft_t *gen_hh(const ha_ct_t *h)
{
int i;
yak_ft_t *hh;
hh = yak_ft_init();
yak_ft_resize(hh, h->tot * 2);
for (i = 0; i < 1<<h->pre; ++i) {
yak_ct_t *ht = h->h[i].h;
khint_t k;
for (k = 0; k < kh_end(ht); ++k) {
if (kh_exist(ht, k)) {
uint64_t y = kh_key(ht, k) >> h->pre << YAK_COUNTER_BITS | i;
int absent;
yak_ft_put(hh, y, &absent);
}
}
}
return hh;
}
int ha_ft_isflt(const void *hh, uint64_t y)
{
yak_ft_t *h = (yak_ft_t*)hh;
khint_t k;
k = yak_ft_get(h, y);
return k == kh_end(h)? 0 : 1;
}
void ha_ft_destroy(void *h)
{
if (h) yak_ft_destroy((yak_ft_t*)h);
}
/*************************
* High-level interfaces *
*************************/
void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs)
{
yak_ft_t *flt_tab;
int64_t cnt[YAK_N_COUNTS];
int peak_hom, peak_het, cutoff;
ha_ct_t *h;
h = ha_count(asm_opt, HAF_COUNT_ALL|HAF_RS_WRITE_LEN, NULL, NULL, rs);
ha_ct_hist(h, cnt, asm_opt->thread_num);
peak_hom = ha_analyze_count(YAK_N_COUNTS, cnt, &peak_het);
if (peak_hom > 0) fprintf(stderr, "[M::%s] peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het);
cutoff = (int)(peak_hom * asm_opt->high_factor);
if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1;
ha_ct_shrink(h, cutoff, YAK_MAX_COUNT, asm_opt->thread_num);
flt_tab = gen_hh(h);
ha_ct_destroy(h);
fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> filtered out %ld k-mers occurring %d or more times\n", __func__,
yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb(), (long)kh_size(flt_tab), cutoff);
return (void*)flt_tab;
}
ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, All_reads *rs)
{
int64_t cnt[YAK_N_COUNTS], tot_cnt;
int peak_hom, peak_het, i, extra_flag1, extra_flag2;
ha_ct_t *ct;
ha_pt_t *pt;
if (read_from_store) {
extra_flag1 = extra_flag2 = HAF_RS_READ;
} else if (rs->total_reads == 0) {
extra_flag1 = HAF_RS_WRITE_LEN;
extra_flag2 = HAF_RS_WRITE_SEQ;
} else {
extra_flag1 = HAF_RS_WRITE_SEQ;
extra_flag2 = HAF_RS_READ;
}
ct = ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag1, NULL, flt_tab, rs);
fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__,
yak_realtime(), yak_cpu_usage(), (long)ct->tot);
ha_ct_hist(ct, cnt, asm_opt->thread_num);
fprintf(stderr, "[M::%s] count[%d] = %ld (for sanity check)\n", __func__, YAK_MAX_COUNT, (long)cnt[YAK_MAX_COUNT]);
peak_hom = ha_analyze_count(YAK_N_COUNTS, cnt, &peak_het);
if (peak_hom > 0) fprintf(stderr, "[M::%s] peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het);
if (flt_tab == 0) {
int cutoff = (int)(peak_hom * asm_opt->high_factor);
if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1;
ha_ct_shrink(ct, 2, cutoff, asm_opt->thread_num);
for (i = 2, tot_cnt = 0; i <= cutoff; ++i) tot_cnt += cnt[i] * i;
} else {
ha_ct_shrink(ct, 2, YAK_MAX_COUNT - 1, asm_opt->thread_num);
for (i = 2, tot_cnt = 0; i <= YAK_MAX_COUNT - 1; ++i) tot_cnt += cnt[i] * i;
}
pt = ha_pt_gen(ct, asm_opt->thread_num);
ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag2, pt, flt_tab, rs);
assert((uint64_t)tot_cnt == pt->tot_pos);
//ha_pt_sort(pt, asm_opt->thread_num);
fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions\n", __func__,
yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos);
return pt;
}
+103
View File
@@ -0,0 +1,103 @@
#ifndef __HA_HTAB_H__
#define __HA_HTAB_H__
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include "Process_Read.h"
#include "CommandLines.h"
typedef struct {
uint64_t x;
uint64_t rid:28, pos:27, rev:1, span:8;
} ha_mz1_t;
typedef struct {
uint64_t rid:28, pos:27, rev:1, span:8; // actually it is not necessary to keep span in the index
} ha_idxpos_t;
typedef struct { uint32_t n, m; ha_mz1_t *a; } ha_mz1_v;
struct ha_pt_s;
typedef struct ha_pt_s ha_pt_t;
struct ha_abuf_s;
typedef struct ha_abuf_s ha_abuf_t;
extern const unsigned char seq_nt4_table[256];
extern void *ha_flt_tab;
extern ha_pt_t *ha_idx;
void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs);
int ha_ft_isflt(const void *hh, uint64_t y);
void ha_ft_destroy(void *h);
ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, All_reads *rs);
void ha_pt_destroy(ha_pt_t *h);
const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n);
ha_abuf_t *ha_abuf_init(void);
void ha_abuf_destroy(ha_abuf_t *ab);
uint64_t ha_abuf_mem(const ha_abuf_t *ab);
double yak_cputime(void);
void yak_reset_realtime(void);
double yak_realtime(void);
long yak_peakrss(void);
double yak_peakrss_in_gb(void);
double yak_cpu_usage(void);
void trio_partition(void);
void ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mz1_v *p, const void *hf);
int ha_analyze_count(int n_cnt, const int64_t *cnt, int *peak_het);
static inline uint64_t yak_hash64(uint64_t key, uint64_t mask) // invertible integer hash function
{
key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1;
key = key ^ key >> 24;
key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265
key = key ^ key >> 14;
key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21
key = key ^ key >> 28;
key = (key + (key << 31)) & mask;
return key;
}
static inline uint64_t yak_hash64_64(uint64_t key)
{
key = ~key + (key << 21);
key = key ^ key >> 24;
key = (key + (key << 3)) + (key << 8);
key = key ^ key >> 14;
key = (key + (key << 2)) + (key << 4);
key = key ^ key >> 28;
key = key + (key << 31);
return key;
}
static inline uint64_t yak_hash_long(uint64_t x[4])
{
int j = x[1] < x[3]? 0 : 1;
return yak_hash64_64(x[j<<1|0]) + yak_hash64_64(x[j<<1|1]);
}
#define CALLOC(ptr, len) ((ptr) = (__typeof__(ptr))calloc((len), sizeof(*(ptr))))
#define MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr))))
#define REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr))))
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
#ifndef kroundup64
#define kroundup64(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, x|=(x)>>32, ++(x))
#endif
#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 */
#endif // __YAK_H__
+1 -1
View File
@@ -17,7 +17,7 @@ typedef struct {
} ketopt_t;
typedef struct {
char *name;
const char *name;
int has_arg;
int val;
} ko_longopt_t;
-669
View File
@@ -1,669 +0,0 @@
/* The MIT License
Copyright (c) 2008, 2009, 2011 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 "khash.h"
KHASH_MAP_INIT_INT(32, char)
int main() {
int ret, is_missing;
khiter_t k;
khash_t(32) *h = kh_init(32);
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10;
k = kh_get(32, h, 10);
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k);
for (k = kh_begin(h); k != kh_end(h); ++k)
if (kh_exist(h, k)) kh_value(h, k) = 1;
kh_destroy(32, h);
return 0;
}
*/
/*
2013-05-02 (0.2.8):
* Use quadratic probing. When the capacity is power of 2, stepping function
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
hashing on cache performance and is more robust than linear probing.
In theory, double hashing should be more robust than quadratic probing.
However, my implementation is probably not for large hash tables, because
the second hash function is closely tied to the first hash function,
which reduce the effectiveness of double hashing.
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
2011-12-29 (0.2.7):
* Minor code clean up; no actual effect.
2011-09-16 (0.2.6):
* The capacity is a power of 2. This seems to dramatically improve the
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
- http://code.google.com/p/ulib/
- http://nothings.org/computer/judy/
* Allow to optionally use linear probing which usually has better
performance for random input. Double hashing is still the default as it
is more robust to certain non-random input.
* Added Wang's integer hash function (not used by default). This hash
function is more robust to certain non-random input.
2011-02-14 (0.2.5):
* Allow to declare global functions.
2009-09-26 (0.2.4):
* Improve portability
2008-09-19 (0.2.3):
* Corrected the example
* Improved interfaces
2008-09-11 (0.2.2):
* Improved speed a little in kh_put()
2008-09-10 (0.2.1):
* Added kh_clear()
* Fixed a compiling error
2008-09-02 (0.2.0):
* Changed to token concatenation which increases flexibility.
2008-08-31 (0.1.2):
* Fixed a bug in kh_get(), which has not been tested previously.
2008-08-31 (0.1.1):
* Added destructor
*/
#ifndef __AC_KHASH_H
#define __AC_KHASH_H
/*!
@header
Generic hash table library.
*/
#define AC_VERSION_KHASH_H "0.2.8"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
/* compiler specific configuration */
#if UINT_MAX == 0xffffffffu
typedef unsigned int khint32_t;
#elif ULONG_MAX == 0xffffffffu
typedef unsigned long khint32_t;
#endif
#if ULONG_MAX == ULLONG_MAX
typedef unsigned long khint64_t;
#else
typedef unsigned long long khint64_t;
#endif
#ifndef kh_inline
#ifdef _MSC_VER
#define kh_inline __inline
#else
#define kh_inline inline
#endif
#endif /* kh_inline */
#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 */
typedef khint32_t khint_t;
typedef khint_t khiter_t;
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
#ifndef kcalloc
#define kcalloc(N,Z) calloc(N,Z)
#endif
#ifndef kmalloc
#define kmalloc(Z) malloc(Z)
#endif
#ifndef krealloc
#define krealloc(P,Z) realloc(P,Z)
#endif
#ifndef kfree
#define kfree(P) free(P)
#endif
static const double __ac_HASH_UPPER = 0.77;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
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);
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) { \
return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \
} \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
{ \
if (h) { \
kfree((void *)h->keys); kfree(h->flags); \
kfree((void *)h->vals); \
kfree(h); \
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
h->size = h->n_occupied = 0; \
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
{ \
if (h->n_buckets) { \
khint_t k, i, last, mask, step = 0; \
mask = h->n_buckets - 1; \
k = __hash_func(key); i = k & mask; \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
i = (i + (++step)) & mask; \
if (i == last) return h->n_buckets; \
} \
return __ac_iseither(h->flags, i)? h->n_buckets : i; \
} else return 0; \
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (!new_flags) return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { kfree(new_flags); return -1; } \
h->keys = new_keys; \
if (kh_is_map) { \
khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
if (!new_vals) { kfree(new_flags); return -1; } \
h->vals = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
if (kh_is_map) val = h->vals[j]; \
__ac_set_isdel_true(h->flags, j); \
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
khint_t k, i, step = 0; \
k = __hash_func(key); \
i = k & new_mask; \
while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
__ac_set_isempty_false(new_flags, i); \
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
if (kh_is_map) h->vals[i] = val; \
break; \
} \
} \
} \
} \
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
} \
kfree(h->flags); /* free the working space */ \
h->flags = new_flags; \
h->n_buckets = new_n_buckets; \
h->n_occupied = h->size; \
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
return 0; \
} \
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size<<1)) { \
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
*ret = -1; return h->n_buckets; \
} \
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
*ret = -1; return h->n_buckets; \
} \
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
{ \
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
else { \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
if (__ac_isdel(h->flags, i)) site = i; \
i = (i + (++step)) & mask; \
if (i == last) { x = site; break; } \
} \
if (x == h->n_buckets) { \
if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
else x = i; \
} \
} \
} \
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; ++h->n_occupied; \
*ret = 1; \
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
*ret = 2; \
} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
__ac_set_isdel_true(h->flags, x); \
--h->size; \
} \
} \
SCOPE void kh_write_##name(kh_##name##_t *h, FILE* fp)\
{\
fwrite(&(h->n_buckets), sizeof(khint_t), 1, fp);\
fwrite(&(h->size), sizeof(khint_t), 1, fp);\
fwrite(&(h->n_occupied), sizeof(khint_t), 1, fp);\
fwrite(&(h->upper_bound), sizeof(khint_t), 1, fp);\
if (h->n_buckets)\
{\
fwrite(h->flags, sizeof(khint32_t), __ac_fsize(h->n_buckets), fp);\
fwrite(h->keys, sizeof(khkey_t), h->n_buckets, fp);\
fwrite(h->vals, sizeof(khval_t), h->n_buckets, fp);\
}\
} \
SCOPE void kh_load_##name(kh_##name##_t *h, FILE* fp)\
{\
int f_flag;\
f_flag = fread(&(h->n_buckets), sizeof(khint_t), 1, fp);\
f_flag += fread(&(h->size), sizeof(khint_t), 1, fp);\
f_flag += fread(&(h->n_occupied), sizeof(khint_t), 1, fp);\
f_flag += fread(&(h->upper_bound), sizeof(khint_t), 1, fp);\
if (h->n_buckets)\
{\
h->flags = (khint32_t*)kmalloc(__ac_fsize(h->n_buckets) * sizeof(khint32_t));\
f_flag += fread(h->flags, sizeof(khint32_t), __ac_fsize(h->n_buckets), fp);\
h->keys = (khkey_t*)kmalloc(sizeof(khkey_t)*h->n_buckets);\
f_flag += fread(h->keys, sizeof(khkey_t), h->n_buckets, fp);\
h->vals = (khval_t*)kmalloc(sizeof(khval_t)*h->n_buckets);\
f_flag += fread(h->vals, sizeof(khval_t), h->n_buckets, fp);\
}\
}
#define KHASH_DECLARE(name, khkey_t, khval_t) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
/* --- BEGIN OF HASH FUNCTIONS --- */
/*! @function
@abstract Integer hash function
@param key The integer [khint32_t]
@return The hash value [khint_t]
*/
#define kh_int_hash_func(key) (khint32_t)(key)
/*! @function
@abstract Integer comparison function
*/
#define kh_int_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract 64-bit integer hash function
@param key The integer [khint64_t]
@return The hash value [khint_t]
*/
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
/*! @function
@abstract 64-bit integer comparison function
*/
#define kh_int64_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract const char* hash function
@param s Pointer to a null terminated string
@return The hash value
*/
static kh_inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = (khint_t)*s;
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
return h;
}
/*! @function
@abstract Another interface to const char* hash function
@param key Pointer to a null terminated string [const char*]
@return The hash value [khint_t]
*/
#define kh_str_hash_func(key) __ac_X31_hash_string(key)
/*! @function
@abstract Const char* comparison function
*/
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
static kh_inline khint_t __ac_Wang_hash(khint_t key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
/* --- END OF HASH FUNCTIONS --- */
/* Other convenient macros... */
/*!
@abstract Type of the hash table.
@param name Name of the hash table [symbol]
*/
#define khash_t(name) kh_##name##_t
/*! @function
@abstract Initiate a hash table.
@param name Name of the hash table [symbol]
@return Pointer to the hash table [khash_t(name)*]
*/
#define kh_init(name) kh_init_##name()
/*! @function
@abstract Destroy a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_destroy(name, h) kh_destroy_##name(h)
/*! @function
@abstract Reset a hash table without deallocating memory.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_clear(name, h) kh_clear_##name(h)
/*! @function
@abstract Resize a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param s New size [khint_t]
*/
#define kh_resize(name, h, s) kh_resize_##name(h, s)
/*! @function
@abstract Insert a key to the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@param r Extra return code: -1 if the operation failed;
0 if the key is present in the hash table;
1 if the bucket is empty (never used); 2 if the element in
the bucket has been deleted [int*]
@return Iterator to the inserted element [khint_t]
*/
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
/*! @function
@abstract Retrieve a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@return Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
*/
#define kh_get(name, h, k) kh_get_##name(h, k)
/*! @function
@abstract Remove a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Iterator to the element to be deleted [khint_t]
*/
#define kh_del(name, h, k) kh_del_##name(h, k)
/*! @function
@abstract Test whether a bucket contains data.
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return 1 if containing data; 0 otherwise [int]
*/
#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
/*! @function
@abstract Get key given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Key [type of keys]
*/
#define kh_key(h, x) ((h)->keys[x])
/*! @function
@abstract Get value given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Value [type of values]
@discussion For hash sets, calling this results in segfault.
*/
#define kh_val(h, x) ((h)->vals[x])
/*! @function
@abstract Alias of kh_val()
*/
#define kh_value(h, x) ((h)->vals[x])
/*! @function
@abstract Get the start iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The start iterator [khint_t]
*/
#define kh_begin(h) (khint_t)(0)
/*! @function
@abstract Get the end iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The end iterator [khint_t]
*/
#define kh_end(h) ((h)->n_buckets)
/*! @function
@abstract Get the number of elements in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of elements in the hash table [khint_t]
*/
#define kh_size(h) ((h)->size)
/*! @function
@abstract Get the number of buckets in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of buckets in the hash table [khint_t]
*/
#define kh_n_buckets(h) ((h)->n_buckets)
/*! @function
@abstract Iterate over the entries in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param kvar Variable to which key will be assigned
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
(vvar) = kh_val(h,__i); \
code; \
} }
/*! @function
@abstract Iterate over the values in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach_value(h, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(vvar) = kh_val(h,__i); \
code; \
} }
/* More convenient interfaces */
/*! @function
@abstract Instantiate a hash set containing integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT(name) \
KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash map containing integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT(name, khval_t) \
KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash set containing 64-bit integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT64(name) \
KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
/*! @function
@abstract Instantiate a hash map containing 64-bit integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT64(name, khval_t) \
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
typedef const char *kh_cstr_t;
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_STR(name) \
KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_STR(name, khval_t) \
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#define kh_write(name, h, fp) kh_write_##name(h, fp)
#define kh_load(name, h, fp) kh_load_##name(h, fp)
#endif /* __AC_KHASH_H */
+1
View File
@@ -276,6 +276,7 @@ static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 26
KHASHL_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \
SCOPE HType *prefix##_init(void) { return prefix##_m_init(); } \
SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \
SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_m_resize(h, new_n_buckets); } \
SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \
SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_m_del(h, k); } \
SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); }
-195
View File
@@ -1,195 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "kmer.h"
void init_HPC_seq(HPC_seq* seq, char* str, long long l)
{
seq->i = 0;
seq->l = l;
seq->N_occ = 0;
seq->str = str;
}
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;
}
-114
View File
@@ -1,114 +0,0 @@
#ifndef __KMER__
#define __KMER__
#include "Process_Read.h"
///#define ALL (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
#define ALL (0xffffffffffffffff)
/****************************may have bugs********************************/
#define SAFE_SHIFT(k) k & ((k < 64)?ALL:0)
/****************************may have bugs********************************/
typedef struct
{
//can represent at most 64-mer
uint64_t x[2];
} 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
{
char* str;
long long l;
long long i;
long long N_occ;
} HPC_seq;
inline uint64_t get_HPC_code(HPC_seq* seq, uint64_t* end_pos)
{
if(seq->i < seq ->l)
{
uint8_t code = seq_nt6_table[(uint8_t)seq->str[seq->i]];
(*end_pos) = seq->i;
for (; seq->i < seq->l; seq->i++)
{
///number of Ns
if (seq_nt6_table[(uint8_t)seq->str[seq->i]] >= 4)
{
seq->N_occ++;
}
if (seq_nt6_table[(uint8_t)seq->str[seq->i]] != code)
{
break;
}
}
return (uint64_t)code;
}
else
{
///end
return 6;
}
}
inline void k_mer_append(Hash_code* code, uint64_t c, int k)
{
uint64_t mask = ALL >> (64 -k);
code->x[0] = ((code->x[0]<<1) | (c&1)) & mask;
code->x[1] = ((code->x[1]<<1) | (c>>1)) & mask;
}
inline void Hashcode_to_string(Hash_code* code, char* str, int k)
{
uint8_t c;
int i;
for (i = 0; i < k; i++)
{
c = (code->x[1] >> (k - i - 1)) & ((uint64_t)1);
c = c << 1;
c = c | ((code->x[0] >> (k - i - 1)) & ((uint64_t)1));
str[i] = s_H[c];
}
}
void init_HPC_seq(HPC_seq* seq, char* str, long long l);
void init_Hash_code(Hash_code* code);
#endif
+10 -6
View File
@@ -4,16 +4,20 @@
#include "Process_Read.h"
#include "Assembly.h"
#include "Levenshtein_distance.h"
#include "htab.h"
int main(int argc, char *argv[])
{
int i, ret;
yak_reset_realtime();
init_opt(&asm_opt);
if (!CommandLine_process(argc, argv, &asm_opt)) return 1;
Correct_Reads(asm_opt.number_of_round);
ret = ha_assemble();
destory_opt(&asm_opt);
return 0;
fprintf(stderr, "[M::%s] Version: %s\n", __func__, HA_VERSION);
fprintf(stderr, "[M::%s] CMD:", __func__);
for (i = 0; i < argc; ++i)
fprintf(stderr, " %s", argv[i]);
fprintf(stderr, "\n[M::%s] Real time: %.3f sec; CPU: %.3f sec; Peak RSS: %.3f GB\n", __func__, yak_realtime(), yak_cputime(), yak_peakrss_in_gb());
return ret;
}
+110
View File
@@ -0,0 +1,110 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "kvec.h"
#include "htab.h"
typedef struct { // a simplified version of kdq
int front, count;
int a[64];
} tiny_queue_t;
static inline void tq_push(tiny_queue_t *q, int x)
{
q->a[((q->count++) + q->front) & 0x3f] = x;
}
static inline int tq_shift(tiny_queue_t *q)
{
int x;
if (q->count == 0) return -1;
x = q->a[q->front++];
q->front &= 0x3f;
--q->count;
return x;
}
/**
* Find symmetric (w,k)-minimizers on a DNA sequence
*
* @param str DNA sequence
* @param len length of $str
* @param w find a minimizer for every $w consecutive k-mers
* @param k k-mer size
* @param rid reference ID; will be copied to the output $p array
* @param is_hpc homopolymer-compressed or not
* @param p minimizers
*/
void ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mz1_v *p, const void *hf)
{
static const ha_mz1_t dummy = { UINT64_MAX, 0, 0, 0 };
uint64_t shift1 = k - 1, mask = (1ULL<<k) - 1, kmer[4] = {0,0,0,0};
int i, j, l, buf_pos, min_pos, kmer_span = 0;
ha_mz1_t buf[256], min = dummy;
tiny_queue_t tq;
assert(len > 0 && len < 1<<27 && rid < 1<<28 && (w > 0 && w < 256) && (k > 0 && k <= 63));
memset(buf, 0xff, w * 16);
memset(&tq, 0, sizeof(tiny_queue_t));
kv_resize(ha_mz1_t, *p, p->n + len/w);
for (i = l = buf_pos = min_pos = 0; i < len; ++i) {
int c = seq_nt4_table[(uint8_t)str[i]];
ha_mz1_t info = dummy;
if (c < 4) { // not an ambiguous base
int z;
if (is_hpc) {
int skip_len = 1;
if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) {
for (skip_len = 2; i + skip_len < len; ++skip_len)
if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c)
break;
i += skip_len - 1; // put $i at the end of the current homopolymer run
}
tq_push(&tq, skip_len);
kmer_span += skip_len;
if (tq.count > k) kmer_span -= tq_shift(&tq);
} else kmer_span = l + 1 < k? l + 1 : k;
kmer[0] = (kmer[0] << 1 | (c&1)) & mask; // forward k-mer
kmer[1] = (kmer[1] << 1 | (c>>1)) & mask;
kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; // reverse k-mer
kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1;
if (kmer[1] == kmer[3]) continue; // skip "symmetric k-mers" as we don't know it strand
z = kmer[1] < kmer[3]? 0 : 1; // strand
++l;
if (l >= k && kmer_span < 256) {
uint64_t y;
y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]);
if (hf == 0 || ha_ft_isflt(hf, y) == 0)
info.x = y, info.rid = rid, info.pos = i, info.rev = z, info.span = kmer_span;
}
} else l = 0, tq.count = tq.front = 0, kmer_span = 0;
buf[buf_pos] = info; // need to do this here as appropriate buf_pos and buf[buf_pos] are needed below
if (l == w + k - 1 && min.x != UINT64_MAX) { // special case for the first window - because identical k-mers are not stored yet
for (j = buf_pos + 1; j < w; ++j)
if (min.x == buf[j].x && buf[j].pos != min.pos) kv_push(ha_mz1_t, *p, buf[j]);
for (j = 0; j < buf_pos; ++j)
if (min.x == buf[j].x && buf[j].pos != min.pos) kv_push(ha_mz1_t, *p, buf[j]);
}
if (info.x <= min.x) { // a new minimum; then write the old min
if (l >= w + k && min.x != UINT64_MAX) kv_push(ha_mz1_t, *p, min);
min = info, min_pos = buf_pos;
} else if (buf_pos == min_pos) { // old min has moved outside the window
if (l >= w + k - 1 && min.x != UINT64_MAX) kv_push(ha_mz1_t, *p, min);
for (j = buf_pos + 1, min.x = UINT64_MAX; j < w; ++j) // the two loops are necessary when there are identical k-mers
if (min.x >= buf[j].x) min = buf[j], min_pos = j; // >= is important s.t. min is always the closest k-mer
for (j = 0; j <= buf_pos; ++j)
if (min.x >= buf[j].x) min = buf[j], min_pos = j;
if (l >= w + k - 1 && min.x != UINT64_MAX) { // write identical k-mers
for (j = buf_pos + 1; j < w; ++j) // these two loops make sure the output is sorted
if (min.x == buf[j].x && min.pos != buf[j].pos) kv_push(ha_mz1_t, *p, buf[j]);
for (j = 0; j <= buf_pos; ++j)
if (min.x == buf[j].x && min.pos != buf[j].pos) kv_push(ha_mz1_t, *p, buf[j]);
}
}
if (++buf_pos == w) buf_pos = 0;
}
if (min.x != UINT64_MAX)
kv_push(ha_mz1_t, *p, min);
}
+53
View File
@@ -0,0 +1,53 @@
#include <sys/resource.h>
#include <sys/time.h>
#include "htab.h"
int yak_verbose = 3;
static double yak_realtime0;
double yak_cputime(void)
{
struct rusage r;
getrusage(RUSAGE_SELF, &r);
return r.ru_utime.tv_sec + r.ru_stime.tv_sec + 1e-6 * (r.ru_utime.tv_usec + r.ru_stime.tv_usec);
}
static inline double yak_realtime_core(void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
return tp.tv_sec + tp.tv_usec * 1e-6;
}
void yak_reset_realtime(void)
{
yak_realtime0 = yak_realtime_core();
}
double yak_realtime(void)
{
return yak_realtime_core() - yak_realtime0;
}
long yak_peakrss(void)
{
struct rusage r;
getrusage(RUSAGE_SELF, &r);
#ifdef __linux__
return r.ru_maxrss * 1024;
#else
return r.ru_maxrss;
#endif
}
double yak_peakrss_in_gb(void)
{
return yak_peakrss() / 1073741824.0;
}
double yak_cpu_usage(void)
{
return (yak_cputime() + 1e-9) / (yak_realtime() + 1e-9);
}