4
#define MAX_INS 40 /*maximum levels for insertions*/
5
#define MAX_STACK 5 /*maximum allowed level of stacks*/
8
/**********************************************************************
10
* LayoutNodeFlat(head, maxScale, top, seq_pos, downward, label_pos)
11
* layout the FeatNode as a stacked layout
12
* head: the list of FeatNode. Will be resorted
13
* maxScale: the maximum scale in the picture
14
* top: current available position at y-axis
15
* seq_pos: store the position for drawing the sequence after the
17
* downward: stack the genes below the sequence line
18
* label_pos: if(TRUE), label the map position for each cluster
20
**********************************************************************/
22
/***********************************************************************
24
* ModLabelInterval(left, right, maxScale, label)
25
* Modify left, right position to take the StringWidth of label into
28
************************************************************************/
30
static Boolean ModLabelInterval(Int4Ptr left, Int4Ptr right, Int4 maxScale, Int4 label_len, Uint1 label_align)
37
if(maxScale <=0 || label_len == 0)
42
case MSM_LABEL_BOTTOM:
43
p_left = (*left)/maxScale;
44
p_right = (*right)/maxScale;
45
if(label_len > (p_right - p_left))
47
center = (*left + (*right))/2;
48
*left = center - (label_len/2) * maxScale;
49
*right = center + (label_len/2) * maxScale;
54
*left -= (label_len +1)*maxScale;
57
*right += (label_len +1)*maxScale;
66
Int2 get_current_class(FeatNodePtr fnp)
69
Boolean has_gb, has_medline;
71
c_class = (fnp->feattype == 0) ? MSM_SEQUENCE: (Int2)(fnp->feattype);
72
has_gb = (Boolean)((fnp->extra_data) & EXTRA_GENBANK);
73
has_medline = (Boolean)((fnp->extra_data) & EXTRA_MEDLINE);
74
if(has_gb && has_medline)
75
return MSM_EXTRA_BOTH;
77
return MSM_EXTRA_GENBANK;
79
return MSM_EXTRA_MEDLINE;
84
static void modify_label_for_supress(FeatNodePtr c_fnp)
88
if(c_fnp->supress_node != NULL)
90
if(c_fnp->label != NULL)
92
sprintf(label, "[%s]", c_fnp->label);
93
MemFree(c_fnp->label);
94
c_fnp->label = StringSave(label);
99
static Boolean is_Dseg_label(CharPtr label)
109
for(str = label+1; str != NULL && *str != '\0'; ++str)
114
return (*str == 'S');
129
static Boolean load_supress_node(ValNodePtr head, ValNodePtr s_node)
138
Uint1 merge_code; /*1=merge_to_exiting 2=exiting_merge_to_me */
140
s_fnp = s_node->data.ptrvalue;
141
if(!is_Dseg_label(s_fnp->label))
143
has_gb = (Boolean)((s_fnp->extra_data) & EXTRA_GENBANK);
144
has_med = (Boolean)((s_fnp->extra_data) & EXTRA_MEDLINE);
146
s_pos = s_fnp->extremes.left;
152
fnp = vnp->data.ptrvalue;
153
pos = fnp->extremes.left;
156
if(is_Dseg_label(fnp->label))
157
/* if(StringNCmp(fnp->label, s_fnp->label, 3) == 0) */
160
if(!has_gb && !has_med)
164
if(((fnp->extra_data) & EXTRA_GENBANK) == 0)
170
if(((fnp->extra_data) & EXTRA_MEDLINE) == 0)
179
/*deal with the landmark genes*/
180
if(s_fnp->landmark) /*it is a landmark gene*/
184
else if(merge_code == 1)
187
else if(fnp->landmark && merge_code == 2)
193
ValNodeLink(&(fnp->supress_node), s_node);
198
s_fnp->supress_node = fnp->supress_node;
199
fnp->supress_node = NULL;
200
vnp->data.ptrvalue = s_fnp;
201
s_node->data.ptrvalue = fnp;
203
ValNodeLink(&(s_fnp->supress_node), s_node);
216
fnp = vnp->data.ptrvalue;
217
pos = fnp->extremes.left;
220
/* if(StringNCmp(fnp->label, s_fnp->label, 3) == 0) */
221
if(is_Dseg_label(fnp->label))
231
ValNodeLink(&(fnp->supress_node), s_node);
236
s_fnp->supress_node = fnp->supress_node;
237
fnp->supress_node = NULL;
238
vnp->data.ptrvalue = s_fnp;
239
s_node->data.ptrvalue = fnp;
253
static Int2 find_flat_line(Int4 left, Int4 right, ValNodePtr PNTR lines, Int4 space, Int4 num, ValNodePtr curr)
256
ValNodePtr vnp, next, prev;
257
FeatNodePtr fnp, n_fnp;
258
Int4 space_l, space_r;
260
for(i = 0; i<num; ++i)
274
fnp = vnp->data.ptrvalue;
277
if(right+space <= fnp->ef_left)
287
if(fnp->ef_right + space <= left)
295
n_fnp = next->data.ptrvalue;
296
space_l = fnp->ef_right + space;
297
space_r = n_fnp->ef_left - space;
298
if(left >=space_l && right <= space_r)
314
Int4 LayoutNodeFlat(ValNodePtr PNTR head, Int4 maxScale, Int4 top, Uint1 label_type, Boolean supress)
319
Boolean has_prev = FALSE;
321
Int2 p_class, ptype = 0;
322
Int4 font_height = 0;
325
Int4 left, right, center;
326
ValNodePtr vnp, next, prev;
328
Int4 symbol_width, symbol_height;
332
ValNodePtr maptype_list[MARK_TYPE_NUM];
333
ValNodePtr PNTR lines;
335
Uint1 display_order[MARK_TYPE_NUM];
338
if(label_type != UPPER_LABEL && label_type != LOWER_LABEL)
340
if(label_type == UPPER_LABEL)
341
label_align = MSM_LABEL_TOP;
342
if(label_type == LOWER_LABEL)
343
label_align = MSM_LABEL_BOTTOM;
345
/*pre-treat the supress node*/
354
if(!load_supress_node(*head, vnp))
355
ValNodeLink(head, vnp);
358
for(vnp = *head; vnp != NULL; vnp = vnp->next)
360
fnp = vnp->data.ptrvalue;
361
modify_label_for_supress(fnp);
365
for(num = 0; num<MARK_TYPE_NUM; ++num)
366
display_order[num] = (Uint1)num;
367
display_order[1] = NO_TYPE; /*reverse the order of FRAME_WORK*/
368
display_order[0] = FRAME_WORK;
370
for(num = 0; num<MARK_TYPE_NUM; ++num)
371
maptype_list[num] = NULL;
378
fnp = vnp->data.ptrvalue;
379
center = (fnp->extremes.left + fnp->extremes.right)/2;
380
fnp->extremes.left = center;
381
fnp->extremes.right = center;
382
map_mark_type = get_map_type(fnp->extra_data);
384
ValNodeLink(&(maptype_list[map_mark_type]), vnp);
391
lines = MemNew((size_t)(num) * sizeof(ValNodePtr));
392
y_height = MemNew((size_t)(2*num) * sizeof (Int4));
393
symbol_width = 8; /*temporary*/
394
symbol_height = 8; /*temporary*/
397
labelstyle = NO_LABEL;
398
for(j = 0; j<MARK_TYPE_NUM; ++j)
401
vnp = maptype_list[display_order[j]];
407
fnp = vnp->data.ptrvalue;
409
/*get the height of the box and the font of label*/
410
p_class = get_current_class(fnp);
411
if(!has_prev || (p_class != ptype))
414
labelstyle = (Uint1)GetMuskCParam(p_class, MSM_FLABEL, MSM_STYLE);
415
if(labelstyle != NO_LABEL)
417
font = (FonT)GetMuskCParam(p_class, MSM_FLABEL, MSM_FONT);
419
font_height = FontHeight();
423
left = fnp->extremes.left;
424
right = fnp->extremes.right;
425
label_len = symbol_width * 3;
426
if(fnp->label == NULL)
427
fnp->labelHeight = 0;
430
fnp->labelHeight = font_height;
431
fnp->label_len = StringWidth(fnp->label);
432
label_len = MAX(label_len, fnp->label_len);
434
ModLabelInterval(&left, &right, maxScale, label_len, label_align);
437
fnp->ef_right = right;
438
i = find_flat_line(left, right, lines, 2L*maxScale, num, vnp);
440
currentHeight = fnp->labelHeight + symbol_width;
441
y_height[i] = MAX(y_height[i], currentHeight);
448
for(i = 0; i<=k; ++i)
450
ValNodeLink(head, lines[i]);
456
for(i =0; i<= k; ++i)
457
y_max += y_height[i];
459
next_y = top - y_max;
460
if(label_align == MSM_LABEL_TOP)
464
for(i =0; i<= k; ++i)
466
for(vnp = (*head); vnp !=NULL; vnp = vnp->next)
468
fnp = vnp->data.ptrvalue;
476
fnp->top = top + symbol_height;
479
case MSM_LABEL_BOTTOM:
486
fnp->bottom = fnp->top - symbol_width;
490
if(label_align == MSM_LABEL_TOP)
500
/*for each alignnode, only use the symbol to indicate the center of its left/right
503
Int4 LayoutAlignFlat(ValNodePtr head, Int4 maxScale, Int4 top)
512
num_line = get_vnp_num(head);
516
y_pos = MemNew((size_t)2*num_line * sizeof (Int4));
517
symbol_height = 8 + 2; /*8 is the height of symbol, 2 is for separation space*/
520
if(head->choice != OBJ_SEQANNOT)
522
anp = head->data.ptrvalue;
523
left = anp->extremes.left;
524
right = left + symbol_height * maxScale;
525
line = find_f_pos(left, right, y_pos, 0, (Int2)num_line);
526
anp->line = top - (line + 1) * symbol_height;
527
next_line = MIN(anp->line, next_line);
536
static Int4 count_one_interval(GatherRange gr_1, GatherRange gr_2)
540
count += ABS(gr_1.left - gr_2.left);
541
count += ABS(gr_1.right - gr_2.right);
545
static Int4 count_mismatch(FeatNodePtr fnp_1, FeatNodePtr fnp_2, BoolPtr same_num)
548
ValNodePtr vnp_1, vnp_2;
550
IvalNodePtr inp_1, inp_2;
554
if(fnp_1->interval != NULL && fnp_2->interval != NULL)
556
num_1 = get_vnp_num(fnp_1->interval);
557
num_2 = get_vnp_num(fnp_2->interval);
560
vnp_1 = fnp_1->interval;
561
vnp_2 = fnp_2->interval;
562
while(vnp_1 && vnp_2)
564
inp_1 = vnp_1->data.ptrvalue;
565
inp_2 = vnp_2->data.ptrvalue;
566
count += count_one_interval(inp_1->gr, inp_2->gr);
575
return count_one_interval(fnp_1->extremes, fnp_2->extremes);
578
static FloatHi calculate_overlap(Int4 left_1, Int4 right_1, Int4 left_2, Int4 right_2)
582
temp1 = MAX(left_1, left_2);
583
temp2 = MIN(right_1, right_2);
584
if ( right_1 == left_1 ) return 1.0;
585
return (FloatHi)(temp2 - temp1 +1)/(FloatHi)(right_1 - left_1 +1);
590
static void link_to_group(ValNodePtr this_group, ValNodePtr new)
594
ValNodePtr my_node = NULL, curr, prev, next;
596
Boolean same, p_same;
599
if(this_group == NULL || new == NULL)
601
n_fnp = new->data.ptrvalue;
603
n_fnp->follower= TRUE;
607
fnp = curr->data.ptrvalue;
608
count = count_mismatch(fnp, n_fnp, &same);
609
if(curr != this_group && !(fnp->follower))
612
if(fnp->feattype != n_fnp->feattype)
621
found = (p_count >= count);
656
static void ordered_link(ValNodePtr PNTR head, ValNodePtr new)
658
ValNodePtr group, prev = NULL;
659
FeatNodePtr g_fnp, fnp;
667
fnp = new->data.ptrvalue;
668
left = fnp->extremes.left;
671
g_fnp = group->data.ptrvalue;
672
if(!(g_fnp->follower))
673
if(g_fnp->extremes.left > left)
685
new->next = prev->next;
691
static void make_prev_group(ValNodePtr PNTR h_group, ValNodePtr new)
693
ValNodePtr next, group;
694
FeatNodePtr fnp, n_fnp;
695
Int4 e_left, e_right, left, right;
696
ValNodePtr this_group;
697
FloatHi g_overlap = 0.0, t_overlap = 0.0;
698
FloatHi overlap_1, overlap_2;
700
ValNodePtr head_group;
702
head_group = *h_group;
703
if(new == NULL || head_group == NULL)
708
n_fnp = new->data.ptrvalue;
709
e_left = n_fnp->extremes.left;
710
e_right = n_fnp->extremes.right;
714
for(group = head_group; group != NULL; group = group->next)
716
fnp = group->data.ptrvalue;
717
if(!(fnp->follower) && (fnp->extremes.strand == n_fnp->extremes.strand)) /*only checks the leaders*/
719
left = fnp->extremes.left;
720
right = fnp->extremes.right;
721
if(!(left > e_right || right < e_left)) /*overlaps*/
724
overlap_1 = calculate_overlap(left, right, e_left, e_right);
725
overlap_2 = calculate_overlap(e_left, e_right, left, right);
726
if(overlap_1 < 0.50 && overlap_2 < 0.50)
730
if(fnp->feattype == n_fnp->feattype)
731
/*found = (overlap_1 == 1.00 && overlap_2 == 1.00);*/
738
if(this_group != NULL)
740
if(overlap_1 > t_overlap)
744
if(overlap_1 == t_overlap)
745
found = (overlap_2 > g_overlap);
752
g_overlap = overlap_2;
753
t_overlap = overlap_1;
760
if(this_group != NULL)
761
link_to_group(this_group, new);
762
else /*link to the end*/
764
n_fnp->follower= FALSE;
765
ordered_link(h_group, new);
766
/*ValNodeLink(&head_group, new);*/
773
/*************************************************************************
775
* ReSetFeatNode(fnp_node): set all the fnp->line = 0. Before the layout,
776
* fnp->line == 0 indicate the start of a new group.
778
**************************************************************************/
779
void ReSetFeatNode(ValNodePtr fnp_node)
784
for(curr = fnp_node; curr != NULL; curr = curr->next)
786
fnp = curr->data.ptrvalue;
787
fnp->follower = FALSE;
792
/*************************************************************************
794
* GroupFeatNode(head, new_group)
795
* Add a new list of FeatNode (from the same feattype) to the head
796
* of its group. The new group will be sorted
798
**************************************************************************/
799
ValNodePtr GroupFeatNode(ValNodePtr PNTR head)
803
ValNodePtr new_group;
805
if(head == NULL || *head == NULL)
808
next = new_group->next;
809
new_group->next = NULL;
810
make_prev_group(head, next);
814
static Boolean is_inside_interval(Int4 a, Int4 x, Int4 y)
816
return (a >=x && a<=y);
819
static Boolean is_mRNA_CDS_compatible(FeatNodePtr cds_node, FeatNodePtr mRNA_node, Int4Ptr offset, Int2Ptr interval_missed)
821
Int2 cds_num, mRNA_num;
822
ValNodePtr cds_interval, mRNA_interval;
823
IvalNodePtr cds_inp, mRNA_inp;
826
if(cds_node->interval == NULL || mRNA_node->interval == NULL)
829
*interval_missed = 0;
831
cds_num = get_vnp_num(cds_node->interval);
832
mRNA_num = get_vnp_num(mRNA_node->interval);
834
if(mRNA_num < cds_num)
837
if(cds_node->extremes.strand == Seq_strand_minus)
839
if(mRNA_node->extremes.strand != Seq_strand_minus)
842
if(mRNA_node->extremes.strand == Seq_strand_minus)
844
if(cds_node->extremes.strand != Seq_strand_minus)
850
cds_interval = cds_node->interval;
851
cds_inp = cds_interval->data.ptrvalue;
852
mRNA_interval = mRNA_node->interval;
853
while(mRNA_interval != NULL)
855
mRNA_inp = mRNA_interval->data.ptrvalue;
856
if(is_inside_interval(cds_inp->gr.left, mRNA_inp->gr.left, mRNA_inp->gr.right))
858
if(is_inside_interval(cds_inp->gr.right, mRNA_inp->gr.left, mRNA_inp->gr.right))
861
if(cds_interval->next != NULL) /*there is more than one exon in CDS*/
863
if(cds_inp->gr.strand == Seq_strand_minus)
864
found = (cds_inp->gr.left == mRNA_inp->gr.left);
866
found = (cds_inp->gr.right == mRNA_inp->gr.right);
870
*offset += (cds_inp->gr.left - mRNA_inp->gr.left);
871
*offset += (mRNA_inp->gr.right - cds_inp->gr.right);
879
++(*interval_missed);
880
mRNA_interval = mRNA_interval->next;
884
if(!found || mRNA_interval == NULL)
887
cds_num = get_vnp_num(cds_interval->next);
888
mRNA_num = get_vnp_num(mRNA_interval->next);
889
if(cds_num > mRNA_num)
895
cds_interval = cds_interval->next;
896
mRNA_interval = mRNA_interval->next;
897
while(cds_interval && mRNA_interval)
899
cds_inp = cds_interval->data.ptrvalue;
900
mRNA_inp = mRNA_interval->data.ptrvalue;
901
if(cds_interval->next == NULL) /*the last CDS*/
903
if(cds_inp->gr.strand == Seq_strand_minus)
905
if(mRNA_inp->gr.right!= cds_inp->gr.right)
907
if(cds_inp->gr.left< mRNA_inp->gr.left)
912
if(mRNA_inp->gr.left != cds_inp->gr.left)
914
if(cds_inp->gr.right > mRNA_inp->gr.right)
917
*offset += (mRNA_inp->gr.right - cds_inp->gr.right);
921
if(cds_inp->gr.right != mRNA_inp->gr.right)
923
if(cds_inp->gr.left != mRNA_inp->gr.left)
927
cds_interval = cds_interval->next;
928
mRNA_interval = mRNA_interval->next;
934
static Boolean insert_CDS_to_best_mRNA(ValNodePtr mRNA_head, ValNodePtr cds)
936
ValNodePtr curr, next;
937
FeatNodePtr fnp, c_fnp;
938
ValNodePtr best_mRNA = NULL;
939
Int4 offset, m_offset = -1;
940
Int2 missed, m_missed; /*number of exons missed at both end*/
942
if(mRNA_head == NULL || cds == NULL)
946
c_fnp = cds->data.ptrvalue;
950
fnp = curr->data.ptrvalue;
951
if(fnp->feattype == FEATDEF_mRNA)
953
if(is_mRNA_CDS_compatible(c_fnp, fnp, &offset, &missed))
955
if(best_mRNA == NULL)
963
if(missed < m_missed)
969
else if(missed == m_missed && m_offset > offset)
984
if(best_mRNA != NULL)
987
c_fnp->follower = TRUE;
990
if(curr == best_mRNA)
1005
static ValNodePtr find_best_gene(ValNodePtr curr, Int4 cds_left, Int4 cds_right)
1008
ValNodePtr best_gene = NULL;
1009
Int4 offset, m_offset = -1;
1018
fnp = curr->data.ptrvalue;
1019
if(fnp->feattype == FEATDEF_GENE)
1021
if(!(fnp->extremes.left > cds_right|| fnp->extremes.right < cds_left))
1024
left = fnp->extremes.left;
1025
right = fnp->extremes.right;
1026
offset += ABS(left - cds_left);
1027
offset += ABS(cds_right - right);
1029
if(best_gene == NULL)
1034
else if(offset < m_offset)
1050
static ValNodePtr find_next_group(ValNodePtr head, Int4Ptr left, Int4Ptr right, ValNodePtr PNTR prev)
1062
fnp = list->data.ptrvalue;
1063
if(!fnp->follower && list != head)
1068
*left = fnp->extremes.left;
1070
*left = MIN(*left, fnp->extremes.left);
1072
*right = fnp->extremes.right;
1074
*right = MAX(*right, fnp->extremes.right);
1084
static void make_group_follower(ValNodePtr first, ValNodePtr last)
1090
fnp = first->data.ptrvalue;
1091
fnp->follower = TRUE;
1095
first = first->next;
1100
static void insert_cds_mRNA_to_gene(ValNodePtr PNTR g_head, ValNodePtr PNTR cds_head)
1102
ValNodePtr cds_list, prev_list = NULL, prev;
1103
ValNodePtr best_gene, curr;
1104
ValNodePtr next, g_next;
1109
*g_head = *cds_head;
1113
cds_list = *cds_head;
1116
next = find_next_group(cds_list, &left, &right, &prev);
1118
if(left != -1 && right != -1)
1120
best_gene = find_best_gene(*g_head, left, right);
1121
if(best_gene != NULL)
1123
make_group_follower(cds_list, prev);
1124
if(prev_list == NULL)
1125
*cds_head = prev->next;
1127
prev_list->next = prev->next;
1132
if(curr == best_gene)
1134
g_next = curr->next;
1135
curr->next = cds_list;
1136
prev->next = g_next;
1144
if(best_gene == NULL)
1149
if(*cds_head != NULL) /*there is some leftovers*/
1151
ValNodeLink(g_head, *cds_head);
1158
ValNodePtr OrderCdsmRNA(ValNodePtr PNTR head)
1161
ValNodePtr cds_head, curr, next, prev;
1162
ValNodePtr mRNA_head;
1164
if(head == NULL || *head == NULL)
1167
ReSetFeatNode(*head);
1168
*head = SortFeatNode(*head, NULL, NULL);
1174
g_head = extract_node_list(head, OBJ_SEQFEAT, 0, FEATDEF_GENE, ALL_LABEL);
1175
mRNA_head = extract_node_list(head, OBJ_SEQFEAT, 0, FEATDEF_mRNA, ALL_LABEL);
1176
cds_head = extract_node_list(head, OBJ_SEQFEAT, 0, FEATDEF_CDS, ALL_LABEL);
1178
if(cds_head != NULL) /*try to group the CDS feature to the mRNA*/
1186
if(insert_CDS_to_best_mRNA(mRNA_head, curr))
1203
if(cds_head != NULL)
1204
ValNodeLink(&mRNA_head, cds_head);
1206
insert_cds_mRNA_to_gene(&g_head, &mRNA_head);
1208
ValNodeLink(&g_head, *head);
1216
static Int4 get_interval_height(Int4 p_class)
1218
Int4 segstyle, style;
1220
style = GetMuskCParam((Int2)p_class, MSM_SEGMENT, MSM_STYLE);
1221
segstyle = (style & MSM_SEG_FORM);
1225
return GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_PENWIDTH);
1227
return GetMuskCParam((Int2)p_class, MSM_SEGMENT, MSM_HEIGHT);
1229
return 8; /*8 is the value for the symbols*/
1234
static Int4 layout_uncompressed_group(ValNodePtr prev, ValNodePtr next, Int4Ptr y_pos, Int4Ptr group_value, Int4 next_sp, Int2 num_line, Int4Ptr com_height)
1236
/*this will allow the layout among the features of the same type
1239
ValNodePtr t_prev, t_curr;
1240
FeatNodePtr c_fnp, t_fnp;
1243
Boolean has_prev = FALSE;
1244
Int2 group_start, group_stop;
1258
y_offset = 0; /*after the first line, everything should be layed down*/
1265
is_end = (curr == next || curr == NULL);
1269
c_fnp = curr->data.ptrvalue;
1270
if(p_feattype != c_fnp->feattype || t_prev == NULL)
1271
{ /*need to find everything in the group*/
1276
if(!process) /*linking it to the current size*/
1281
else if(t_prev != NULL)
1283
/*either the running to the end or mapped to
1284
the same type of Seq-feat*/
1286
if(group_size == 1) /*there is only one sequence*/
1288
left = group_value[2*group_start];
1289
right = group_value[2*group_start +1];
1290
i = find_f_pos(left, right, y_pos+2*y_offset, next_sp, (Int2)(num_line - y_offset));
1293
i = find_group_pos(y_pos+2*y_offset, next_sp, (Int2)(num_line -y_offset), group_size, group_value + group_start*2);
1298
y_offset = i+group_size -1;
1303
i+= (Int2)(y_offset);
1305
maxline = MAX(i+group_size-1, maxline);
1306
for(t_curr = t_prev; t_curr != curr; t_curr = t_curr->next)
1308
t_fnp = t_curr->data.ptrvalue;
1312
com_height[i] = MAX(com_height[i], t_fnp->bottom);
1317
group_start += group_size;
1321
p_feattype = c_fnp->feattype;
1329
/***********************************************************************
1331
* Int4 LayoutFeatNode(head, top, next_sp, space, maxScale, check_interval)
1332
* Layout the fnp->line, inp->line according to Maximun packing, return
1333
* the next availabel space for drawing
1334
* head: the FeatNode. will be sorted
1335
* top: the current y position
1336
* next_sp: min. space for separating two neibouring objects
1337
* space: the vertical space consumed by each line
1338
* maxScale: max scale for the picture
1339
* check_interval: layout each interval?
1342
************************************************************************/
1343
Int4 LayoutFeatNode(ValNodePtr head, Int4 top, Int4 maxScale, Int4 next_sp, Boolean show_label, Boolean compress)
1345
Int4Ptr y_pos, com_height; /*com_height: storing height for compressed layout*/
1349
Int2 maxline = 0, group_size;
1351
Int4 left, right, p_left, p_right;
1352
Int4 line_scale; /*scale for showing only the two-ends of interval*/
1353
Boolean drawline; /*draw a line between the two ends of the interval*/
1356
ValNodePtr vnp, curr, prev;
1357
FeatNodePtr fnp, c_fnp;
1358
Int2 ptype = 0; /*previous feature type. to save some time*/
1361
Int4 font_height = 0;
1362
Int4 f_space; /*space separate features at different level*/
1363
Boolean show_trunc = FALSE;
1364
Int4 segstyle, labelstyle;
1365
Int4 cur_line, y_next;
1366
Boolean has_prev = FALSE;
1368
Uint1 label_align; /*the alignment of a labe: top, left, bottom, right*/
1369
Int4Ptr group_value;
1374
line_scale = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
1375
drawline = (maxScale >= line_scale);
1376
f_space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
1377
/*the alignment of a label in relation to the object*/
1378
label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
1380
num_line = (Int2)get_vnp_num(head);
1382
/*for layout each level*/
1383
y_pos = MemNew((size_t)2*num_line * sizeof (Int4));
1384
com_height = MemNew((size_t)num_line* sizeof (Int4));
1385
group_value = MemNew((size_t)2*num_line* sizeof (Int4));
1388
labelstyle = NO_LABEL;
1395
fnp = vnp->data.ptrvalue;
1397
/*get the height of the box and the font of label*/
1398
p_class = get_current_class(fnp);
1399
if(p_class == MSM_SEQUENCE) /*assume it is a sequence*/
1401
if(!has_prev || (p_class != ptype)) /*get the styles*/
1404
if(drawline && fnp->landmark == FALSE)
1405
height = GetMuskCParam(p_class, MSM_SEG_BORD, MSM_PENWIDTH);
1408
height = get_interval_height(p_class);
1409
segstyle = GetMuskCParam(p_class, MSM_SEGMENT, MSM_STYLE);
1410
labelstyle = GetMuskCParam(p_class, MSM_FLABEL, MSM_STYLE);
1411
show_trunc = (Boolean)(segstyle & (Int4)MSM_SEG_SHOWTRUNC);
1414
font = (FonT)GetMuskCParam(p_class, MSM_FLABEL, MSM_FONT);
1416
font_height = FontHeight();
1422
/*convert label to type, content, both, summary format*/
1423
left = fnp->extremes.left;
1424
right = fnp->extremes.right;
1425
/*if(fnp->extremes.l_trunc && show_trunc)
1426
left -= (6*maxScale);
1427
if(fnp->extremes.r_trunc && show_trunc)
1428
right += (6*maxScale);*/
1429
fnp->labelHeight = font_height;
1430
if(compress && fnp->follower)
1432
fnp->labelHeight = 0;
1433
if(label_align == MSM_LABEL_LEFT)
1437
fnp->labelHeight = font_height;
1440
c_fnp = prev->data.ptrvalue;
1441
c_fnp->labelHeight = 0;
1445
if(label_align == MSM_LABEL_RIGHT)
1449
fnp->labelHeight = font_height;
1452
c_fnp = prev->data.ptrvalue;
1453
c_fnp->labelHeight = 0;
1460
/*temporary store the value*/
1461
fnp->bottom = height;
1462
if(fnp->labelHeight!= 0)
1464
label_len = StringWidth(fnp->label);
1465
fnp->label_len = label_len;
1466
ModLabelInterval(&left, &right, maxScale, label_len, label_align);
1469
/*load the data for each level*/
1470
if(!(fnp->follower)) /*start of a new group*/
1472
if( prev != NULL) /*process the previous group*/
1476
i = find_f_pos(p_left, p_right, y_pos, next_sp, (Int2)num_line);
1477
com_height[i] = MAX(com_height[i], maxHeight);
1478
maxline = MAX(i, maxline);
1479
for(curr = prev; curr != vnp; curr = curr->next)
1481
c_fnp = curr->data.ptrvalue;
1487
i = (Int2)layout_uncompressed_group(prev, vnp, y_pos, group_value, next_sp, num_line, com_height);
1488
maxline = MAX(i, maxline);
1496
group_value[2*(group_size-1)] = left;
1497
group_value[2*(group_size-1) +1] = right;
1502
p_left = MIN(left, p_left);
1503
p_right = MAX(right, p_right);
1504
maxHeight = MAX(height, maxHeight);
1506
group_value[2*(group_size-1)] = left;
1507
group_value[2*(group_size-1) +1] = right;
1512
if(prev != NULL) /*process the last one*/
1516
i = find_f_pos(p_left, p_right, y_pos, next_sp, (Int2)num_line);
1517
com_height[i] = MAX(com_height[i], maxHeight);
1518
maxline = MAX(i, maxline);
1519
for(curr = prev; curr != vnp; curr = curr->next)
1521
c_fnp = curr->data.ptrvalue;
1527
i = (Int2)layout_uncompressed_group(prev, vnp, y_pos, group_value, next_sp, num_line, com_height);
1528
maxline = MAX(i, maxline);
1533
MemFree(group_value);
1538
for(i = 0; i<= maxline; ++i) /*Layout each line in each level*/
1541
for(vnp = head; vnp != NULL; vnp = vnp->next)
1543
fnp = vnp->data.ptrvalue;
1544
if(fnp->line == i+1)
1546
if(!(fnp->follower))
1547
font_height = fnp->labelHeight;
1548
maxHeight = MAX(maxHeight, font_height);
1550
top -= (com_height[i] - fnp->bottom)/2;
1556
case MSM_LABEL_LEFT:
1557
case MSM_LABEL_RIGHT:
1558
if(font_height > com_height[i])
1559
top -= (font_height - com_height[i])/2;
1565
fnp->bottom = top - fnp->bottom;
1571
case MSM_LABEL_BOTTOM:
1572
cur_line -= (maxHeight + com_height[i]);
1574
case MSM_LABEL_LEFT:
1575
case MSM_LABEL_RIGHT:
1576
cur_line -= MAX(maxHeight, com_height[i]);
1581
cur_line -= f_space;
1584
MemFree(com_height);
1592
void modify_insert_fnode(ValNodePtr fnode, Int4 offset)
1600
fnp = fnode->data.ptrvalue;
1601
(fnp->extremes.left) += offset;
1602
(fnp->extremes.right) += offset;
1604
for(ival = fnp->interval; ival!=NULL; ival = ival->next)
1606
inp = ival->data.ptrvalue;
1607
(inp->gr.left) += offset;
1608
(inp->gr.right) += offset;
1611
fnode = fnode->next;
1615
static Int4 LayoutInsertions(AlignNodePtr anp, Int4 maxScale, Int4 cur_line, Int4 height, Int4 space, Int4 l_bound, Int4 r_bound)
1618
Int4 insert_ypos[MAX_INS];
1620
Int4 left, seglen, ins;
1621
Int4 next_line, feat_line;
1622
Boolean has_insertion = FALSE;
1623
Int4 offset; /*offset between the left pos and the insert pos*/
1624
ValNodePtr repeat_node;
1627
if(anp == NULL || anp->segs== NULL)
1630
MemSet((Pointer)(insert_ypos), 0, (size_t)MAX_INS * sizeof(Int4));
1632
for(asp = anp->segs; asp !=NULL; asp = asp->next)
1634
if(asp->type == INS_SEG)
1636
has_insertion = TRUE;
1638
seglen = asp->gr.right;
1640
asp->line = find_insert_ypos(&left, seglen, ins, l_bound, r_bound, insert_ypos, 0, MAX_INS);
1641
/*asp->line = find_insert_ypos(&left, seglen, ins, l_bound, r_bound, insert_ypos, 3*maxScale, MAX_INS);*/
1643
/*resume the previous layout for FeatNode*/
1644
/*offset = asp->gr.left - asp->ins_pos;
1646
modify_insert_fnode(asp->cnp, (-offset));*/
1647
asp->gr.left = left;
1648
level = MAX((Int2)(asp->line), level);
1655
for(i = 0; i<(level+1); ++i)
1657
next_line = cur_line - space - height - space;
1658
for(asp = anp->segs; asp !=NULL; asp = asp->next)
1660
if(asp->type == INS_SEG && asp->line == i)
1662
asp->top = cur_line;
1663
asp->bottom = asp->top - height;
1664
if(asp->cnp != NULL)
1666
/*offset = asp->gr.left - (asp->ins_pos - asp->gr.right +1);*/
1667
offset = asp->gr.left - asp->ins_pos;
1668
modify_insert_fnode(asp->cnp, offset);
1669
ReSetFeatNode(asp->cnp);
1670
repeat_node = strip_repeat_feature(&(asp->cnp));
1671
feat_line = LayoutFeatNode(asp->cnp, (asp->bottom - space), maxScale, 0, FALSE, FALSE);
1672
if(repeat_node != NULL)
1673
ValNodeLink(&(asp->cnp), repeat_node);
1674
next_line = MIN(feat_line, next_line);
1678
cur_line = next_line ;
1686
/**********************************************************************
1688
* merge_same_itemID(head, itemID)
1689
* search in the list of FeatNode to link all the FeatNode that has
1691
* head: the list of FeatNode
1692
* itemID: the itemID in search
1693
* return the list of FeatNode with the same itemID
1695
**********************************************************************/
1696
ValNodePtr merge_same_itemID(ValNodePtr PNTR head, Int2 itemID)
1698
FeatNodePtr fnp, l_fnp;
1699
ValNodePtr curr, prev = NULL, next;
1700
ValNodePtr list = NULL;
1705
fnp = curr->data.ptrvalue;
1707
if(fnp->itemID == (Uint2)itemID)
1712
prev->next = curr->next;
1718
l_fnp = list->data.ptrvalue;
1719
l_fnp->extremes.right = fnp->extremes.right;
1720
l_fnp->extremes.r_trunc = fnp->extremes.r_trunc;
1721
if(fnp->interval != NULL)
1723
ValNodeLink(&(l_fnp->interval), (fnp->interval));
1724
fnp->interval = NULL;
1726
FreeFeatureList(curr);
1741
ValNodePtr strip_repeat_feature(ValNodePtr PNTR f_node)
1743
ValNodePtr list = NULL, curr;
1755
fnp = curr->data.ptrvalue;
1756
if(fnp->feattype == FEATDEF_repeat_region || fnp->feattype == FEATDEF_repeat_unit)
1759
ValNodeLink(&list, curr);
1773
/******************************************************************
1775
* check to see if the master line has any follower. If does,
1776
* add the length of the followers
1778
*******************************************************************/
1779
static Boolean modify_master_line(ValNodePtr vnp, Int4Ptr m_left, Int4Ptr m_right, Int4 maxScale, Uint1 label_align)
1784
Boolean retval = FALSE;
1788
anp = vnp->data.ptrvalue;
1789
if(anp->follower == FALSE)
1793
anp = vnp->data.ptrvalue;
1794
left = anp->extremes.left;
1795
right = anp->extremes.right;
1796
if(anp->label != NULL)
1798
label_len = StringWidth(anp->label);
1799
ModLabelInterval(&left, &right, maxScale, label_len, label_align);
1801
if(anp->extremes.l_trunc == TRUE)
1802
left -= (6*maxScale);
1803
if(anp->extremes.r_trunc == TRUE)
1804
right += (6*maxScale);
1805
*m_left = MIN(*m_left, left);
1806
*m_right = MAX(*m_right, right);
1813
typedef struct align_feature{
1816
Int4 e_left, e_right;
1817
Int4 p_left, p_right;
1819
}AlignFeature, PNTR AlignFeaturePtr;
1821
/*create a summarry of the features in alignment. Get the extremities. So,
1822
it only needed to be layed out once */
1823
static void load_align_feature_list(ValNodePtr PNTR list, ValNodePtr fnp_list)
1827
ValNodePtr prev = NULL;
1828
AlignFeaturePtr afp;
1831
fnp = fnp_list->data.ptrvalue;
1832
if(fnp->feattype == FEATDEF_repeat_region || fnp->feattype == FEATDEF_repeat_unit)
1836
if(curr->choice == fnp_list->choice)
1838
afp = curr->data.ptrvalue;
1840
if(afp->itemID == fnp->itemID)
1842
afp->e_left = MIN(afp->e_left, fnp->extremes.left);
1843
afp->e_right = MAX(afp->e_right, fnp->extremes.right);
1852
curr = ValNodeNew(NULL);
1853
curr->choice = fnp_list->choice;
1854
afp = MemNew(sizeof(AlignFeature));
1855
afp->itemID = fnp->itemID;
1856
afp->e_left = fnp->extremes.left;
1857
afp->e_right = fnp->extremes.right;
1859
curr->data.ptrvalue = afp;
1869
static Int4 LayoutAlignmentFeature (AlignSegPtr h_asp, Int4 top, Int4 space, Int4 maxScale)
1871
ValNodePtr list, curr;
1872
ValNodePtr fnp_list;
1874
ValNodePtr layout_list;
1875
AlignFeaturePtr afp;
1884
if(asp->type != INS_SEG)
1886
fnp_list = asp->cnp;
1889
load_align_feature_list(&list, fnp_list);
1890
fnp_list = fnp_list->next;
1902
for(curr = list; curr != NULL; curr = curr->next)
1904
afp = curr->data.ptrvalue;
1905
afp->p_left = afp->fnp->extremes.left;
1906
afp->p_right = afp->fnp->extremes.right;
1907
afp->fnp->extremes.left = afp->e_left;
1908
afp->fnp->extremes.right = afp->e_right;
1910
ValNodeAddPointer(&layout_list, curr->choice, afp->fnp);
1913
if(layout_list != NULL)
1915
n_y_pos = LayoutFeatNode (layout_list, top, maxScale, 0, FALSE, FALSE);
1916
for(curr = list; curr != NULL; curr = curr->next)
1918
afp = curr->data.ptrvalue;
1919
afp->fnp->extremes.left = afp->p_left;
1920
afp->fnp->extremes.right = afp->p_right;
1922
for(asp = h_asp; asp != NULL; asp = asp->next)
1924
if(asp->type != INS_SEG)
1926
for(fnp_list = asp->cnp; fnp_list != NULL; fnp_list =
1929
fnp = fnp_list->data.ptrvalue;
1930
if(fnp != afp->fnp && fnp->itemID == afp->fnp->itemID
1931
&& fnp_list->choice == curr->choice)
1933
fnp->top = afp->fnp->top;
1934
fnp->bottom = afp->fnp->bottom;
1940
ValNodeFree(layout_list);
1944
ValNodeFreeData(list);
1948
static void load_status_flag(ValNodePtr prev, ValNodePtr curr, Int4 left, Int4 right)
1953
for(vnp = prev; vnp != NULL; vnp = vnp->next)
1955
status = (BoolPtr)(vnp->data.ptrvalue);
1956
MemSet(status+left, 1, (size_t)(right - left + 1) *sizeof(Boolean));
1962
static ValNodePtr init_new_status_list(Int4 level, Int4 size)
1969
for(i = 0; i<level; ++i)
1971
status = MemNew((size_t)(size+1) * sizeof(Boolean));
1972
ValNodeAddPointer(&list, 0, status);
1978
static Int4 figure_alignment_level(ValNodePtr PNTR line_status_list, Int4 left, Int4 right, Int4 num_seq, Int4 size)
1983
BoolPtr line_status;
1986
ValNodePtr p_node, n_node;
1991
for(list = *line_status_list; list != NULL; list = list->next)
1993
line_status = list->data.ptrvalue;
1995
for(i = left; i<= right; ++i)
2013
if(c_num_seq == num_seq)
2015
load_status_flag(p_node, list, left, right);
2016
return (max_level + 1 - (c_num_seq -1));
2022
n_node = init_new_status_list(num_seq-c_num_seq, size);
2025
ValNodeLink(line_status_list, n_node);
2026
load_status_flag(p_node, NULL, left, right);
2027
return (max_level - c_num_seq + 1);
2033
static void mod_left_right_by_scale(Int4Ptr left, Int4Ptr right, Int4 maxScale)
2035
Int4 t_left, t_right;
2042
*left = t_left/maxScale;
2043
if(t_left%maxScale > 0)
2045
*right = t_right/maxScale;
2046
if(t_right%maxScale > 0)
2052
static void figure_alignment_boundary(AlignNodePtr anp, Int4Ptr pleft,
2053
Int4Ptr pright, Int4 max_len, Uint1 label_align, Int4 maxScale)
2058
left = anp->extremes.left;
2059
right = anp->extremes.right;
2060
mod_left_right_by_scale(&left, &right, maxScale);
2063
if(anp->label != NULL)
2065
label_len = StringWidth(anp->label);
2066
ModLabelInterval(&left, &right, 1, label_len, label_align);
2068
if(anp->extremes.l_trunc == TRUE)
2071
if(anp->extremes.r_trunc == TRUE)
2075
*pleft = MAX(left, 0);
2076
*pright = MIN(right, max_len);
2080
static Boolean is_level_overlap(ValNodePtr PNTR pleft_list,
2081
ValNodePtr PNTR pright_list, Int4 left, Int4 right, AlignNodePtr anp)
2083
Int4 l_left, l_right;
2085
ValNodePtr left_list, right_list;
2087
left_list = *pleft_list;
2088
right_list = *pright_list;
2090
while(left_list && right_list)
2092
l_left = left_list->data.intvalue;
2093
l_right = right_list->data.intvalue;
2095
if(left >= l_right || right <= l_left)
2097
left_list->data.intvalue = MIN(l_left, left);
2098
right_list->data.intvalue = MAX(l_right, right);
2103
left_list = left_list->next;
2104
right_list = right_list->next;
2108
ValNodeAddInt(pleft_list, 0, left);
2109
ValNodeAddInt(pright_list, 0, right);
2114
static Int4 find_align_line_number(AlignNodePtr anp,
2115
ValNodePtr t_next_list, Uint1 label_align, ValNodePtr PNTR pnext,
2116
ValNodePtr PNTR line_status_list, Int4 size, Int4 maxScale )
2118
Int4 m_left, m_right;
2121
ValNodePtr left_list= NULL, right_list = NULL;
2124
ValNodePtr next_list;
2129
*pnext = t_next_list;
2131
figure_alignment_boundary(anp, &left, &right, size, label_align, maxScale);
2132
ValNodeAddInt(&left_list, 1, left);
2133
ValNodeAddInt(&right_list, 1, right);
2138
next_list = t_next_list;
2142
n_anp = next_list->data.ptrvalue;
2143
if(n_anp->follower == TRUE)
2146
figure_alignment_boundary(n_anp, &left, &right, size, label_align, maxScale);
2147
if(is_level_overlap(&left_list, &right_list, left, right, n_anp))
2149
m_left = MIN(m_left, left);
2150
m_right = MAX(m_right, right);
2151
*pnext = next_list->next;
2152
next_list = next_list->next;
2158
line = figure_alignment_level(line_status_list,
2159
m_left, m_right, level, size);
2162
for(next_list = t_next_list; next_list != NULL && next_list != *pnext; next_list = next_list->next)
2164
n_anp = next_list->data.ptrvalue;
2165
n_anp->line += line;
2167
ValNodeFree(left_list);
2168
ValNodeFree(right_list);
2169
return (line + level -1);
2172
static Boolean get_anp_extremes(ValNodePtr anp_list, Int4Ptr m_left, Int4Ptr m_right)
2180
anp = anp_list->data.ptrvalue;
2181
if(*m_left == -1 || *m_left > anp->extremes.left)
2182
*m_left = anp->extremes.left;
2184
if(*m_right == -1 || *m_right < anp->extremes.right)
2185
*m_right = anp->extremes.right;
2187
anp_list = anp_list->next;
2190
return (*m_left != -1);
2197
/**********************************************************************
2199
* LayoutAlignNode(head, top, maxScale)
2200
* head: the list of AlignNode
2201
* top: the current y position
2202
* maxScale: the maximum scale
2203
* the labels on the features of a sequence is not counted in the layout
2205
***********************************************************************/
2206
Int4 LayoutAlignNode (ValNodePtr head, Int4 top, Int4 maxScale, Int4 height)
2210
Int4 left, right, m_left, m_right;
2212
ValNodePtr vnp, curr, next;
2215
Int4 cur_line, next_line;
2217
Int4 font_height = 0; /*height of the Font*/
2218
Int4 h_font_height, h_height;
2220
Int4 space; /*the space separate the two object*/
2223
Int4 font_offset = 0, h_font_offset;
2225
ValNodePtr line_status_list = NULL;
2232
SortSameSeqInAlignNode(head);
2234
space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2235
label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2236
font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
2238
font_height = FontHeight();
2239
master_height = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
2241
get_anp_extremes(head, &m_left, &m_right);
2242
mod_left_right_by_scale(&m_left, &m_right, maxScale);
2247
line_status_list = NULL;
2250
anp = vnp->data.ptrvalue;
2251
i = find_align_line_number(anp, vnp->next,
2252
label_align, &next, &line_status_list, m_right, maxScale);
2258
if(line_status_list != NULL)
2259
ValNodeFreeData(line_status_list);
2266
case MSM_LABEL_BOTTOM:
2267
font_offset = font_height;
2269
case MSM_LABEL_LEFT:
2270
case MSM_LABEL_RIGHT:
2271
if(font_height > height)
2272
font_offset = (font_height - height);
2278
cur_line = top; /*layout the actural y positions*/
2279
h_font_height = font_height;
2280
h_font_offset = font_offset;
2285
for(vnp=(head); vnp!=NULL; vnp=vnp->next)
2287
anp = vnp->data.ptrvalue;
2290
font_height = (anp->label) ? h_font_height : 0;
2291
font_offset= (anp->label) ? h_font_offset : 0;
2293
height = master_height;
2298
next_line = cur_line - height - font_offset - space;
2304
anp->top = cur_line - font_height;
2306
case MSM_LABEL_BOTTOM:
2307
anp->top = cur_line;
2309
case MSM_LABEL_LEFT:
2310
case MSM_LABEL_RIGHT:
2311
anp->top = cur_line - font_offset/2;
2317
anp->bottom = anp->top- height;
2319
left = anp->extremes.left;
2320
right = anp->extremes.right;
2321
ins_line = anp->bottom - space;
2323
/*Layout the Non-insertions*/
2324
/*collect all the features in the alignment */
2325
for(asp = anp->segs; asp !=NULL; asp = asp->next)
2327
if(asp->type != INS_SEG)
2329
if(asp->type == GAP_SEG)
2331
asp->bottom = anp->bottom + height/2;
2332
asp->top = asp->bottom;
2336
asp->bottom = anp->bottom;
2337
asp->top = asp->bottom + height;
2341
ins_line = LayoutAlignmentFeature (anp->segs, anp->bottom, space, maxScale);
2342
ins_line = LayoutInsertions(anp, maxScale, ins_line, height, space, left, right);
2343
if(anp->extremes.l_trunc == TRUE|| anp->extremes.r_trunc == TRUE)
2344
ins_line = MIN(ins_line, anp->bottom - space - 8);
2345
next_line = MIN(next_line, ins_line);
2349
cur_line = next_line;
2356
/****************************************************************
2358
* extract a list of AlignNode that matches the sip
2359
* or things with the same clone id
2361
*****************************************************************/
2362
static ValNodePtr extract_match_seqid_list(ValNodePtr PNTR n_curr, SeqIdPtr sip, CharPtr clone_id, Int2Ptr num_follower)
2364
ValNodePtr curr, prev, next;
2375
anp = curr->data.ptrvalue;
2376
if(SeqIdMatch(anp->sip, sip) ||
2377
(clone_id != NULL && StringCmp(anp->clone_id, clone_id) == 0))
2379
anp->follower = TRUE;
2381
*n_curr = curr->next;
2383
prev->next = curr->next;
2385
ValNodeLink(&list, curr);
2395
/******************************************************************
2397
* SortSameSeqInAlignNode(anp_list)
2398
* if the same sequence appears multiple times in the anp_list,
2399
* it will be moved to the sequence that are the head of this
2400
* list. The field anp->follower is set as the order of the
2401
* repeats in this list
2403
******************************************************************/
2404
void SortSameSeqInAlignNode(ValNodePtr anp_list)
2406
ValNodePtr curr, n_curr;
2408
ValNodePtr same_list;
2414
anp = curr->data.ptrvalue;
2415
n_curr = curr->next;
2418
same_list = extract_match_seqid_list(&n_curr, anp->sip, anp->clone_id, &num_follower);
2419
if(same_list != NULL)
2421
anp->num_follower = num_follower;
2422
ValNodeLink(&same_list, n_curr);
2423
curr->next = same_list;