1 /***************************************************************
2 
3    The Subread software package is free software package:
4    you can redistribute it and/or modify it under the terms
5    of the GNU General Public License as published by the
6    Free Software Foundation, either version 3 of the License,
7    or (at your option) any later version.
8 
9    Subread is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty
11    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13    See the GNU General Public License for more details.
14 
15    Authors: Drs Yang Liao and Wei Shi
16 
17   ***************************************************************/
18 
19 
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "LRMsorted-hashtable.h"
24 
25 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
26 #include <malloc.h>
27 #endif
28 
29 #include<math.h>
30 #include "LRMfile-io.h"
31 
32 #define _gehash_hash(k) ((unsigned int)(k))
33 #define WITHOUT_CLUSTER_ORDERING 0
34 
LRM_gehash_get_bucket(LRMgehash_t * the_table,LRMgehash_key_t key)35 struct LRMgehash_bucket * LRM_gehash_get_bucket(LRMgehash_t * the_table, LRMgehash_key_t key) {
36 	int bucket_number;
37 
38 	bucket_number = _gehash_hash(key) % the_table -> buckets_number;
39 	return  the_table -> buckets +bucket_number;
40 }
41 
42 
43 
44 #define INDEL_SEGMENT_SIZE 5
45 
46 #define _index_vote(key) (((unsigned int)(key))%LRMGENE_VOTE_TABLE_SIZE)
47 #define _index_vote_tol(key) (((unsigned int)(key)/INDEL_SEGMENT_SIZE)%LRMGENE_VOTE_TABLE_SIZE)
48 
49 
50 #define is_quality_subread(scr)	((scr)>15?1:0)
51 
52 
LRMgehash_go_q(LRMgehash_t * the_table,LRMgehash_key_t raw_key,int offset,int read_len,int is_reversed,LRMgene_vote_t * vote,int indel_tolerance,int subread_number)53 size_t LRMgehash_go_q(LRMgehash_t * the_table, LRMgehash_key_t raw_key, int offset, int read_len, int is_reversed, LRMgene_vote_t * vote, int indel_tolerance, int subread_number){
54 	//LRMprintf("Q=%u, OFFSET=%d, B=%u ~ %u\n", raw_key, offset, low_border, high_border);
55 
56 	// VER_1
57 	// VER_2
58 
59 	struct LRMgehash_bucket * current_bucket;
60 	int i = 0, items;
61 
62 	short *current_keys;//, *endp12;
63 	short key = raw_key / the_table->buckets_number;
64 
65 	current_bucket = LRM_gehash_get_bucket (the_table, raw_key);
66 	items = current_bucket -> current_items;
67 	current_keys = current_bucket -> new_item_keys;
68 
69 	if(!items) return 0;
70 
71 	int imin=0, imax=items;
72 	int last_accepted_index = 0;
73 
74 	while( imin < items )
75 	{
76 		last_accepted_index=(imin+imax)/2;
77 		short current_key = current_keys[last_accepted_index];
78 		if(current_key>key)
79 		{
80 			imax = last_accepted_index - 1;
81 		}
82 		else if(current_key<key)
83 		{
84 			imin = last_accepted_index + 1;
85 		}
86 		else
87 			break;
88 
89 		if(imax<imin)
90 			return 0;
91 
92 	}
93 
94 	while(last_accepted_index){
95 		if(current_keys[last_accepted_index-1] == key) last_accepted_index-=1;
96 		else break;
97 	}
98 
99 	int ii_end = INDEL_SEGMENT_SIZE;
100 	if(indel_tolerance>5) ii_end=(indel_tolerance % INDEL_SEGMENT_SIZE)?(indel_tolerance - indel_tolerance%INDEL_SEGMENT_SIZE+INDEL_SEGMENT_SIZE):indel_tolerance;
101 
102 	for (; last_accepted_index<items && current_keys[last_accepted_index] == key ; last_accepted_index++)
103 	{
104 		unsigned int kv = current_bucket->item_values[last_accepted_index] - offset;
105 		int iix, offsetX2, offsetX, datalen, datalen2;
106 		offsetX2 = offsetX = _index_vote_tol(kv);
107 		datalen = datalen2 = vote -> items[offsetX2];
108 		unsigned int * dat2, *dat;
109 		dat = dat2 = vote -> pos[offsetX2];
110 
111 		//LRMprintf("You can find KV at %u\n", kv);
112 
113 		for(iix = 0; iix<=ii_end; iix = iix>0?-iix:(-iix+INDEL_SEGMENT_SIZE))
114 		{
115 			if(iix)
116 			{
117 				offsetX = _index_vote_tol(kv+iix);
118 				datalen = vote -> items[offsetX];
119 				dat = vote -> pos[offsetX];
120 			}
121 
122 
123 			if(!datalen)continue;
124 
125 			for (i=0;i<datalen;i++)
126 			{
127 				int di = dat[i];
128 				int dist0 = kv-di;
129 				if( dist0 >= -indel_tolerance && dist0 <= indel_tolerance )
130 				{
131 					if(is_reversed  == (0!=(vote -> masks[offsetX][i]&LRMIS_NEGATIVE_STRAND)))
132 					{
133 						if(offset < vote->coverage_end [offsetX][i] + 10){
134 								unsigned char test_max = (vote->votes[offsetX][i]);
135 								test_max += 1;
136 								vote -> votes[offsetX][i] = test_max;
137 
138 								if (offset +16 > vote->coverage_end [offsetX][i])
139 									vote->coverage_end [offsetX][i] = offset+16;
140 
141 								/*
142 								int toli =  vote -> toli[offsetX][i];
143 
144 								if (dist0 !=  vote->current_indel_cursor[offsetX][i])
145 								{
146 									toli +=3;
147 									if (toli < LRMMAX_INDEL_SECTIONS*3)
148 									{
149 										vote -> toli[offsetX][i] = toli;
150 										vote -> indel_recorder[offsetX][i][toli] = subread_number+1;
151 										vote -> indel_recorder[offsetX][i][toli+1] = subread_number+1;
152 										vote -> indel_recorder[offsetX][i][toli+2] = dist0;
153 										//LRMprintf("subread=#%d ,TOLI=%d, DIST0=%d, POS=%u \n", subread_number, toli, dist0, kv);
154 
155 										if(toli < LRMMAX_INDEL_SECTIONS*3-3) vote -> indel_recorder[offsetX][i][toli+3]=0;
156 									}
157 									vote->current_indel_cursor [offsetX][i] = (char)dist0;
158 								} else vote -> indel_recorder[offsetX][i][toli+1] = subread_number+1;
159 								*/
160 								i = 9999999;
161 						}
162 					}
163 				}
164 			}
165 			if (i>=9999999){
166 				break;
167 			}
168 
169 		}
170 
171 		if (i < 9999999)
172 		{
173 			if (datalen2<LRMGENE_VOTE_SPACE)
174 			{
175 				vote -> items[offsetX2] ++;
176 				dat2[datalen2] = kv;
177 				vote -> masks[offsetX2][datalen2]=(is_reversed?LRMIS_NEGATIVE_STRAND:0);
178 				vote -> votes[offsetX2][datalen2]=1;
179 				vote -> toli[offsetX2][datalen2]=0;
180 
181 				// data structure of recorder:
182 				// {unsigned char subread_start; unsigned char subread_end, char indel_offset_from_start}
183 				// All subread numbers are added with 1 for not being 0.
184 
185 				vote -> indel_recorder[offsetX2][datalen2][0] = vote -> indel_recorder[offsetX2][datalen2][1] = subread_number+1;
186 				vote -> indel_recorder[offsetX2][datalen2][2] = 0;
187 				vote -> indel_recorder[offsetX2][datalen2][3] = 0;
188 				vote -> current_indel_cursor [offsetX2][datalen2] = 0;
189 				vote -> coverage_start [offsetX2][datalen2] = offset;
190 				vote -> coverage_end [offsetX2][datalen2] = offset+16;
191 				//LRMprintf("subread=#%d ,NEW RECORD =%u\n", subread_number, kv);
192 			}
193 		}
194 		else i=0;
195 	}
196 	return 1;
197 }
198 
199 
LRMindel_recorder_copy(unsigned short * dst,unsigned short * src)200 short LRMindel_recorder_copy(unsigned short *dst, unsigned short * src)
201 {
202 	short all_indels = 0;
203 //	memcpy(dst, src, 3*MAX_INDEL_TOLERANCE);  return;
204 
205 
206 	int i=0;
207 	while(src[i] && (i<3*LRMMAX_INDEL_TOLERANCE-2))
208 	{
209 		dst[i] = src[i];
210 		i++;
211 		dst[i] = src[i];
212 		i++;
213 		dst[i] = src[i];
214 		all_indels = dst[i];
215 		i++;
216 	}
217 	dst[i] = 0;
218 	return all_indels;
219 
220 }
221 
222 // Data Struct of dumpping:
223 // {
224 //      size_t current_items;
225 //      size_t buckets_number;
226 //      struct
227 //      {
228 //	      size_t current_items;
229 //	      size_t space_size;
230 //	      gehash_key_t item_keys [current_items];
231 //	      gehash_data_t item_values [current_items]
232 //      } [buckets_number];
233 // }
234 //
235 
LRMload_int32(FILE * fp)236 unsigned int LRMload_int32(FILE * fp)
237 {
238 	int ret;
239 	int read_length;
240 	read_length = fread(&ret, sizeof(int), 1, fp);
241 	if(read_length<=0)assert(0);
242 	return ret;
243 }
244 
LRMload_int64(FILE * fp)245 long long int LRMload_int64(FILE * fp)
246 {
247 	long long int ret;
248 	int read_length;
249 	read_length = fread(&ret, sizeof(long long int), 1, fp);
250 	if(read_length<=0)assert(0);
251 	return ret;
252 }
253 
254 
LRMgehash_load_option(const char fname[],int option_no,int * result)255 int LRMgehash_load_option(const char fname [], int option_no, int * result){
256 	char tabname[LRMMAX_FILENAME_LENGTH];
257 	char magic_chars[8];
258 	int found = 0;
259 	sprintf(tabname, "%s.00.b.tab", fname);
260 	FILE * fp = fopen(tabname, "rb");
261 	if(fp == NULL){
262 		sprintf(tabname, "%s.00.c.tab", fname);
263 		fp = fopen(tabname, "rb");
264 	}
265 	if(fp){
266 		int rlen = fread(magic_chars,1,8,fp);
267 		if(rlen < 8){
268 			LRMprintf("ERROR: Unable to read-in the index.\n");
269 			return -1;
270 		}
271 		if(memcmp(magic_chars, "2subindx",7)==0) {
272 			while(1) {
273 				short option_key, option_length;
274 
275 				rlen = fread(&option_key, 2, 1, fp);
276 				if(rlen<1){
277 					LRMprintf("ERROR: Unable to read-in the index.\n");
278 					return -1;
279 				}
280 
281 				if(!option_key) break;
282 
283 				rlen = fread(&option_length, 2, 1, fp);
284 				if(rlen<1){
285 					LRMprintf("ERROR: Unable to read-in the index.\n");
286 					return -1;
287 				}
288 
289 
290 				if(option_key == option_no){
291 					*result = 0;
292 					rlen = fread(result ,option_length,1,fp);
293 					if(rlen<1){
294 						LRMprintf("ERROR: Unable to read-in the index.\n");
295 						return -1;
296 					}
297 					found = 1;
298 				}
299 				else
300 					fseek(fp, option_length, SEEK_CUR);
301 			}
302 		}
303 		fclose(fp);
304 	}
305 	return found;
306 }
307 
LRMgehash_load(LRMgehash_t * the_table,const char fname[])308 int LRMgehash_load(LRMgehash_t * the_table, const char fname [])
309 {
310 	int i, read_length;
311 	char magic_chars[8];
312 	magic_chars[7]=0;
313 
314 	the_table -> index_gap = 0;
315 
316 	FILE * fp = fopen(fname, "rb");
317 	if (!fp)
318 	{
319 		LRMprintf ("Table file '%s' is not found.\n", fname);
320 		return 1;
321 	}
322 
323 	int rlen = fread(magic_chars,1,8,fp);
324 	if(rlen<8){
325 		LRMprintf("ERROR: Unable to read-in the index.\n");
326 		return -1;
327 	}
328 
329 	if(memcmp(magic_chars+1, "subindx",7)==0)
330 	{
331 		if('2'==magic_chars[0])
332 			the_table -> version_number = LRMSUBINDEX_VER2;
333 		else	assert(0);
334 
335 		while(1)
336 		{
337 			short option_key, option_length;
338 
339 			rlen = fread(&option_key, 2, 1, fp);
340 			if(rlen<1){
341 				LRMprintf("ERROR: Unable to read-in the index.\n");
342 				return -1;
343 			}
344 			if(!option_key) break;
345 
346 			rlen = fread(&option_length, 2, 1, fp);
347 			if(rlen<1){
348 				LRMprintf("ERROR: Unable to read-in the index.\n");
349 				return -1;
350 			}
351 
352 			rlen = 999;
353 			if(option_key == LRMSUBREAD_INDEX_OPTION_INDEX_GAP)
354 				rlen = fread(&(the_table -> index_gap),2,1,fp);
355 			else if (option_key == LRMSUBREAD_INDEX_OPTION_INDEX_PADDING)
356 				rlen = fread(&(the_table -> padding),2,1,fp);
357 			else
358 				fseek(fp, option_length, SEEK_CUR);
359 
360 			if(rlen<1){
361 				LRMprintf("ERROR: Unable to read-in the index.\n");
362 				return -1;
363 			}
364 		}
365 		assert(the_table -> index_gap);
366 
367 		the_table -> current_items = LRMload_int64(fp);
368 		if(the_table -> current_items < 1 || the_table -> current_items > 0xffffffffllu){
369 			LRMputs("ERROR: the index format is unrecognizable.");
370 			return 1;
371 		}
372 		the_table -> buckets_number = LRMload_int32(fp);
373 		the_table -> buckets = (struct LRMgehash_bucket * )malloc(sizeof(struct LRMgehash_bucket) * the_table -> buckets_number);
374 		if(!the_table -> buckets)
375 		{
376 			LRMputs("Error: out of memory");
377 			return 1;
378 		}
379 
380 		for (i=0; i<the_table -> buckets_number; i++)
381 		{
382 			struct LRMgehash_bucket * current_bucket = &(the_table -> buckets[i]);
383 			current_bucket -> current_items = LRMload_int32(fp);
384 			current_bucket -> space_size = LRMload_int32(fp);
385 			current_bucket -> space_size = current_bucket -> current_items;
386 			current_bucket -> new_item_keys = (short *) malloc ( sizeof(short) * current_bucket -> space_size);
387 			current_bucket -> item_values = (LRMgehash_data_t *) malloc ( sizeof(LRMgehash_data_t) * current_bucket -> space_size);
388 
389 			if(!(current_bucket -> new_item_keys&&current_bucket -> item_values))
390 			{
391 				LRMputs("Error: out of memory");
392 				return 1;
393 
394 			}
395 
396 			if(current_bucket -> current_items > 0)
397 			{
398 				read_length = fread(current_bucket -> new_item_keys, sizeof(short), current_bucket -> current_items, fp);
399 				if(read_length < current_bucket -> current_items){
400 					LRMprintf("ERROR: the index is incomplete : %d < %u.\n",read_length, current_bucket -> current_items);
401 					return 1;
402 				}
403 				read_length = fread(current_bucket -> item_values, sizeof(LRMgehash_data_t), current_bucket -> current_items, fp);
404 				if(read_length < current_bucket -> current_items){
405 					LRMprintf("ERROR: the index value is incomplete : %d < %u.\n",read_length, current_bucket -> current_items);
406 					return 1;
407 				}
408 			}
409 
410 		}
411 
412 		read_length = fread(&(the_table -> is_small_table), sizeof(char), 1, fp);
413 		assert(read_length>0);
414 		fclose(fp);
415 		return 0;
416 
417 	}
418 	else assert(0);
419 	return 0;
420 }
421 
LRMtest2key(unsigned int kk,char * obuf)422 void LRMtest2key(unsigned int kk, char * obuf){
423 	int xx,oo=0;
424 	for(xx=0; xx<32;xx++){
425 		obuf[oo++] = (kk & (1<<xx))  ?'1':'0';
426 		if(xx%2 == 1 && xx < 31) obuf[oo++]=' ';
427 	}
428 	obuf[oo]=0;
429 }
430 
LRMtest2key_dist(unsigned int k1,unsigned int k2)431 int LRMtest2key_dist(unsigned int k1, unsigned int k2){
432 	int xx, ret = 0;
433 	for(xx=0; xx<16;xx++){
434 		int b1 = (k1 >> (xx*2)) & 3;
435 		int b2 = (k2 >> (xx*2)) & 3;
436 		if(b1!=b2) ret++;
437 	}
438 	return ret;
439 }
440 
LRMgehash_go_QQ(LRMcontext_t * context,LRMthread_context_t * thread_context,LRMread_iteration_context_t * iteration_context,LRMgehash_t * the_table,LRMgehash_key_t raw_key,int offset,int read_len,int is_reversed,LRMgene_vote_t * vote,int indel_tolerance,int subread_number)441 size_t LRMgehash_go_QQ(LRMcontext_t * context, LRMthread_context_t * thread_context, LRMread_iteration_context_t * iteration_context, LRMgehash_t * the_table, LRMgehash_key_t raw_key, int offset, int read_len, int is_reversed, LRMgene_vote_t * vote, int indel_tolerance, int subread_number){
442 
443 	struct LRMgehash_bucket * current_bucket;
444 	int i = 0, items;
445 
446 	short *current_keys;//, *endp12;
447 	short key = raw_key / the_table->buckets_number;
448 
449 	current_bucket = LRM_gehash_get_bucket (the_table, raw_key);
450 	items = current_bucket -> current_items;
451 	current_keys = current_bucket -> new_item_keys;
452 
453 	if(!items) return 0;
454 
455 	int imin=0, imax=items;
456 	int last_accepted_index = 0;
457 
458 	while( imin < items )
459 	{
460 		last_accepted_index=(imin+imax)/2;
461 		short current_key = current_keys[last_accepted_index];
462 		if(current_key>key)
463 			imax = last_accepted_index - 1;
464 		else if(current_key<key)
465 			imin = last_accepted_index + 1;
466 		else
467 			break;
468 
469 		if(imax<imin)
470 			return 0;
471 
472 	}
473 
474 	while(last_accepted_index){
475 		if(current_keys[last_accepted_index-1] == key) last_accepted_index-=1;
476 		else break;
477 	}
478 
479 	for (; last_accepted_index<items && current_keys[last_accepted_index] == key ; last_accepted_index++)
480 	{
481 		unsigned int kv = current_bucket->item_values[last_accepted_index] - offset;
482 		int offsetX, datalen;
483 		offsetX = _index_vote(kv);
484 		datalen = vote -> items[offsetX];
485 		unsigned int *dat;
486 		dat = vote -> pos[offsetX];
487 
488 
489 		for (i=0;i<datalen;i++)
490 		{
491 			int di = dat[i];
492 			if( kv == di && is_reversed  == (0!=(vote -> masks[offsetX][i]&LRMIS_NEGATIVE_STRAND))  && offset < vote->coverage_end [offsetX][i] + 14){
493 				vote -> votes[offsetX][i]++;
494 
495 				if (offset +16 > vote->coverage_end [offsetX][i])
496 					vote->coverage_end [offsetX][i] = offset+16;
497 				i = 9999999;
498 			}
499 		}
500 
501 		if (i < 9999999)
502 		{
503 			if (datalen<LRMGENE_VOTE_SPACE)
504 			{
505 				vote -> items[offsetX] ++;
506 				dat[datalen]=kv;
507 				vote -> masks[offsetX][datalen]=(is_reversed?LRMIS_NEGATIVE_STRAND:0);
508 				vote -> votes[offsetX][datalen]=1;
509 				vote -> coverage_start [offsetX][datalen] = offset;
510 				vote -> coverage_end [offsetX][datalen] = offset+16;
511 			}
512 		}
513 		else i=0;
514 	}
515 	return 1;
516 }
517 
LRMgehash_go_tolerance(LRMcontext_t * context,LRMthread_context_t * thread_context,LRMread_iteration_context_t * iteration_context,LRMgehash_t * the_table,LRMgehash_key_t key,int offset,int read_len,int is_reversed,LRMgene_vote_t * vote,int indel_tolerance,int subread_number,int max_MM)518 size_t LRMgehash_go_tolerance(LRMcontext_t * context, LRMthread_context_t * thread_context, LRMread_iteration_context_t * iteration_context, LRMgehash_t * the_table, LRMgehash_key_t key, int offset, int read_len, int is_reversed, LRMgene_vote_t * vote, int indel_tolerance, int subread_number, int max_MM){
519 	if(max_MM >= 10) return 0;
520 	int ret = 0;
521 
522 	ret+=LRMgehash_go_q(the_table, key, offset, read_len, is_reversed, vote, indel_tolerance, subread_number);
523 	int error_bases ;
524 	for (error_bases=1; error_bases <= max_MM; error_bases++)
525 	{
526 		assert(error_bases<5);
527 		int i, j;
528 		char error_pos_stack[10];	// max error bases = 10;
529 		LRMgehash_key_t mutation_key;
530 
531 		for(i=0; i<error_bases; i++)
532 			error_pos_stack [i] = i;
533 		while (1)
534 		{
535 
536 			char mutation_stack[10];
537 			memset(mutation_stack, 0 , error_bases);
538 			while(1)
539 			{
540 				int base_to_change=-1;
541 				mutation_key = key;
542 
543 				for (j = 0; j < error_bases; j++)
544 				{
545 					base_to_change = error_pos_stack[j];
546 					int old_value = (key >> 2*base_to_change) & 3;
547 					int new_index = mutation_stack[j];
548 
549 					int new_value;
550 					if(old_value <= new_index) new_value = 1+ new_index;
551 					else new_value = new_index;
552 
553 					mutation_key = mutation_key & ~(0x3 << (2*base_to_change));
554 					mutation_key = mutation_key | (new_value << (2*base_to_change));
555 				}
556 
557 				if(key != mutation_key ){
558 					int dret=LRMgehash_go_q(the_table, mutation_key, offset, read_len, is_reversed, vote,  indel_tolerance, subread_number);
559 					ret += dret;
560 					if(0 && LRMFIXLENstrcmp("@39076b1f-df29-4487-be51-4c30bf6c1cc4_Basecall_Alignment_template", iteration_context->read_name)==0){
561 						char bin_mutation_key[53], bin_key[53];
562 						LRMtest2key(mutation_key, bin_mutation_key);
563 						LRMtest2key(key, bin_key);
564 						LRMprintf("GO_TOLE_TEST: %s + %d DIST = %d HITS = %d :\nNEWKY:      %s\nORGKY:      %s\n",  iteration_context->read_name , offset, LRMtest2key_dist(mutation_key,key), dret, bin_mutation_key, bin_key);
565 					}
566 				}
567 				// increase one in the mutation_stack
568 				mutation_stack[error_bases-1]++;
569 				for(i = error_bases-1; i>=0; i--){
570 					if( mutation_stack[i]>2 ) {
571 						if(i == 0)break;
572 						else{
573 							mutation_stack[i] = 0;
574 							mutation_stack[i-1]++;
575 						}
576 					}
577 				}
578 				if(mutation_stack[0]>2)break;
579 			}
580 
581 
582 			int is_end = 1;
583 			for (i = error_bases-1; i>=0; i--)
584 				if (error_pos_stack[i] < 16 - (error_bases - i))
585 				{
586 					error_pos_stack[i] ++;
587 					for (j = i+1; j<error_bases; j++)
588 						error_pos_stack[j] = error_pos_stack[i] + (j-i);
589 					is_end = 0;
590 					break;
591 				}
592 
593 			if(is_end) break;
594 		}
595 	}
596 	return ret;
597 }
598 
LRMgehash_destory(LRMgehash_t * the_table)599 void LRMgehash_destory(LRMgehash_t * the_table)
600 {
601 	int i;
602 
603 	for (i=0; i<the_table -> buckets_number; i++)
604 	{
605 		struct LRMgehash_bucket * current_bucket = &(the_table -> buckets[i]);
606 		if (current_bucket -> space_size > 0)
607 		{
608 			free (current_bucket -> new_item_keys);
609 			free (current_bucket -> item_values);
610 		}
611 	}
612 
613 	free (the_table -> buckets);
614 
615 	the_table -> current_items = 0;
616 	the_table -> buckets_number = 0;
617 }
618 
LRMprint_v(LRMcontext_t * context,LRMread_iteration_context_t * iteration_context,int min_votes)619 void LRMprint_v(LRMcontext_t * context, LRMread_iteration_context_t * iteration_context, int min_votes){
620 	LRMgene_vote_t * v = &iteration_context-> vote_table;
621 
622 	LRMprintf(" ==== VOTING TABLE ========================= \n");
623 	int iii, jjj;
624 	for(iii=0; iii < LRMGENE_VOTE_TABLE_SIZE; iii++){
625 		for(jjj = 0; jjj <  v -> items[iii]; jjj++){
626 			unsigned int this_pos = v -> pos[iii][jjj];
627 			int votes = v -> votes[iii][jjj];
628 			if(votes >= min_votes){
629 				char postxt[100];
630 				int conf_start = v -> coverage_start[iii][jjj] , conf_end = v -> coverage_end [iii][jjj];
631 				LRMpos2txt(context, this_pos, postxt);
632 				LRMprintf("     %d (%s) %3d - %3d : %16s   ", votes,(v -> masks[iii][jjj]&LRMIS_NEGATIVE_STRAND)?"NEG":"POS", conf_start, conf_end, postxt);
633 				int ix;
634 				for(ix=0; v->indel_recorder[iii][jjj][ix]; ix+=3){
635 					LRMprintf(" %d ~ %d : %d ",  v->indel_recorder[iii][jjj][ix] ,  v->indel_recorder[iii][jjj][ix+1],  v->indel_recorder[iii][jjj][ix+2]);
636 				}
637 				LRMprintf("\n");
638 			}
639 		}
640 	}
641 	LRMprintf(" =========================================== \n\n");
642 }
643