1
2
3 #include <vibrant.h>
4 #include <drawseq.h>
5 #include <edutil.h>
6
7 Uint1 custom_color[3];
8
9 #define SCALE_SPACE 20
10 static Boolean AddFlatNodeSymbol PROTO((SegmenT pseg, ValNodePtr fnp_node, Int4 scale));
11
12 /*######################################################################
13 #
14 # functions for setting up the color for different object
15 #
16 ######################################################################*/
17
18
19 #define RGB_B(x) (Uint1)((x)&255);
20 #define RGB_G(x) (Uint1)(((x)>>8)&255);
21 #define RGB_R(x) (Uint1)(((x)>>16)&255);
convert_color(Int4 val,Uint1Ptr color)22 static Boolean convert_color(Int4 val, Uint1Ptr color)
23 {
24
25 if(val<0 || color == NULL)
26 return FALSE;
27 color[0] = RGB_R(val);
28 color[1] = RGB_G(val);
29 color[2] = RGB_B(val);
30 return TRUE;
31 }
32
33
34 Uint1 MUSK_COLOR[3];
35 /************************************************************************
36 *
37 * get_seg_color(order)
38 * set up the color for a segmented sequence
39 *
40 *************************************************************************/
get_seg_color(Int2 order)41 Uint1Ptr get_seg_color(Int2 order)
42 {
43 Int2 c_num;
44 Int4 color_val;
45
46 c_num = (Int2)GetMuskCParam(MSM_CCOLOR, MSM_NOSUBCLASS, MSM_NUM);
47 if(c_num != 0)
48 {
49 order = (Int2)(order)%c_num +1;
50 color_val = GetMuskCParam(MSM_CCOLOR, order, MSM_COLOR);
51 if(convert_color(color_val, MUSK_COLOR))
52 return MUSK_COLOR;
53 }
54 return NULL;
55
56 }
57
58
59 /**********************************************************************
60 *
61 * get the color for different enzymes
62 * used in drawing the restriction map
63 *
64 **********************************************************************/
get_enz_color(Int2 enzID)65 Uint1Ptr get_enz_color(Int2 enzID)
66 {
67 return get_seg_color(enzID);
68 }
69
70
71 /**********************************************************************
72 *
73 *
74 *
75 ***********************************************************************/
DrawSquiggle(SegmenT seg,Int4 x,Int4 y,Int2 primID,Boolean is_left)76 static void DrawSquiggle(SegmenT seg, Int4 x, Int4 y, Int2 primID, Boolean is_left)
77 {
78 Int4 space;
79
80 space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
81 AddLine(seg, x, y, x, y-space, FALSE, 0);
82 if(is_left)
83 AddSymbol(seg, x+2, y - space, LEFT_TRIANGLE_SYMBOL, TRUE, LOWER_LEFT, primID);
84 else
85 AddSymbol(seg, x, y - space, RIGHT_TRIANGLE_SYMBOL, TRUE, LOWER_RIGHT, primID);
86
87 }
88
89
get_arrow_for_strand(Uint1 strand)90 static Int2 get_arrow_for_strand(Uint1 strand)
91 {
92 switch(strand)
93 {
94 case Seq_strand_minus:
95 return LEFT_ARROW;
96 case Seq_strand_plus:
97 return RIGHT_ARROW;
98 default:
99 return NO_ARROW;
100 }
101 }
102
add_attribute_pen(SegmenT seg,Int2 p_class,Int2 sub_class)103 void add_attribute_pen(SegmenT seg, Int2 p_class, Int2 sub_class)
104 {
105 Uint1 color[3];
106 Uint1 flags = COLOR_ATT|STYLE_ATT|SHADING_ATT|WIDTH_ATT;
107 Int4 c_val;
108 Uint1 linestyle;
109 Uint1 penwidth;
110 Uint1 shading;
111
112 c_val = GetMuskCParam(p_class, sub_class, MSM_COLOR);
113 convert_color(c_val, color);
114
115 linestyle = (Uint1)GetMuskCParam(p_class, sub_class, MSM_LTYPE);
116 penwidth = (Uint1)GetMuskCParam(p_class, sub_class, MSM_PENWIDTH);
117 shading = (Uint1)GetMuskCParam(p_class, sub_class, MSM_SHADING);
118
119 AddAttribute(seg, flags, &color[0], linestyle, shading, penwidth, COPY_MODE);
120
121 }
122
123 /*************************************************************************
124 *
125 * DrawFeatNode(vnp, type, rec_width, scale, seg, label_type, fill)
126 * Draw a list of featnode, return TRUE for success
127 * vnp: a list of featnode
128 * rec_width: width for drawing a rectangle. if <2, draw a line
129 * scale: max scale
130 * seg: drawing segment
131 * label_type: Add label on the segment
132 * fill: fill the rectangle?
133 *
134 *************************************************************************/
135
AddLabelWithAlign(SegmenT seg,Uint1 label_align,Int4 left,Int4 right,Int4 top,Int4 bottom,CharPtr label,FonT font,Uint4 itemID)136 static void AddLabelWithAlign(SegmenT seg, Uint1 label_align, Int4 left, Int4 right, Int4 top, Int4 bottom, CharPtr label, FonT font, Uint4 itemID)
137 {
138 Int4 center, middle;
139
140
141 switch(label_align)
142 {
143 case MSM_LABEL_TOP:
144 center = (left + right)/2;
145 AddTextLabel(seg, center, top, label, font, 0, UPPER_CENTER, itemID);
146 break;
147 case MSM_LABEL_BOTTOM:
148 center = (left + right)/2;
149 AddTextLabel(seg, center, bottom, label, font, 0, LOWER_CENTER, itemID);
150 break;
151 case MSM_LABEL_LEFT:
152 middle = (top + bottom)/2;
153 AddTextLabel(seg, left, middle, label, font, 0, MIDDLE_LEFT, itemID);
154 break;
155 case MSM_LABEL_RIGHT:
156 middle = (top + bottom)/2;
157 AddTextLabel(seg, right, middle, label, font, 0, MIDDLE_RIGHT, itemID);
158 break;
159 default:
160 break;
161 }
162 }
163
load_gene_data(GeneDataPtr gdp,FeatNodePtr fnp,Uint2 itemType,Int4 x,Int4 y)164 static Boolean load_gene_data(GeneDataPtr gdp, FeatNodePtr fnp, Uint2 itemType, Int4 x, Int4 y)
165 {
166 while(gdp)
167 {
168 if(gdp->entityID == fnp->entityID)
169 {
170 if(gdp->itemID == fnp->itemID)
171 {
172 if(gdp->itemType == itemType)
173 {
174 gdp->x = x;
175 gdp->y = y;
176 return TRUE;
177 }
178 }
179 }
180 gdp = gdp->next;
181 }
182 return FALSE;
183 }
184
AddBoxWithAlign(SegmenT seg,Uint1 label_align,FeatNodePtr fnp,Int4 scale,GeneDataPtr gdp,Uint2 itemType)185 static Boolean AddBoxWithAlign(SegmenT seg, Uint1 label_align, FeatNodePtr fnp, Int4 scale, GeneDataPtr gdp, Uint2 itemType)
186 {
187 Int4 center, middle;
188 Int4 width;
189 Int4 left, right, top, bottom;
190 CharPtr label;
191 Int4 labelHeight;
192 Uint4 itemID;
193 Char buf[10];
194
195 if(fnp == NULL || fnp->label == NULL)
196 return FALSE;
197 left = fnp->extremes.left;
198 right = fnp->extremes.right;
199 top = fnp->top;
200 bottom = fnp->bottom;
201 labelHeight = fnp->labelHeight;
202 itemID = fnp->itemID;
203 label = fnp->label;
204 if(labelHeight == 0) /*the label will NOT be displayed*/
205 {
206 StringCpy(buf, "XXXX");
207 label = buf;
208 /* font = (FonT)GetMuskCParam(fnp->feattype, MSM_FLABEL, MSM_FONT);
209 SelectFont(font); */
210 labelHeight = FontHeight();
211 label_align = MSM_LABEL_TOP;
212 top -= labelHeight;
213
214 }
215
216 width = scale * StringWidth(label);
217 AddAttribute (seg, COLOR_ATT, YELLOW_COLOR, 0, 0, 0, 0);
218 switch(label_align)
219 {
220 case MSM_LABEL_TOP:
221 center = (left + right)/2;
222 left = center - width/2;
223 right = center + width/2;
224 bottom = top;
225 top += labelHeight;
226 break;
227 case MSM_LABEL_BOTTOM:
228 center = (left + right)/2;
229 left = center - width/2;
230 right = center + width/2;
231 top = bottom;
232 bottom -= labelHeight;
233 break;
234 case MSM_LABEL_LEFT:
235 middle = (top + bottom)/2;
236 top = middle - labelHeight/2;
237 bottom = middle + labelHeight/2;
238 right = left;
239 left = left - width;
240
241 break;
242 case MSM_LABEL_RIGHT:
243 middle = (top + bottom)/2;
244 top = middle - labelHeight/2;
245 bottom = middle + labelHeight/2;
246 left = right;
247 right += width;
248 break;
249 default:
250 return FALSE;
251 }
252 AddRectangle (seg, left, top+5, right, bottom+5, FALSE, TRUE, itemID);
253 load_gene_data(gdp, fnp, itemType, left, top);
254
255 /*show the partial label*/
256 if(fnp->labelHeight == 0 && fnp->label != NULL)
257 {
258 center = (fnp->extremes.left + fnp->extremes.right)/2;
259 middle = (fnp->top + fnp->bottom)/2;
260 AddAttribute (seg, COLOR_ATT, RED_COLOR, 0, 0, 0, 0);
261 AddSymbol(seg, center, middle, DIAMOND_SYMBOL, TRUE, MIDDLE_CENTER, fnp->itemID);
262 }
263 return TRUE;
264 }
265
266
267
AddFeatNodeLabel(SegmenT seg,FeatNodePtr fnp,Uint1 label_align,FonT font)268 static void AddFeatNodeLabel(SegmenT seg, FeatNodePtr fnp, Uint1 label_align, FonT font)
269 {
270 if(fnp->labelHeight > 0)
271 AddLabelWithAlign(seg, label_align, fnp->extremes.left, fnp->extremes.right, fnp->top, fnp->bottom, fnp->label, font, fnp->itemID);
272 }
273
AddFeatNodeTickMark(SegmenT seg,FeatNodePtr fnp,Uint1 label_align)274 static void AddFeatNodeTickMark(SegmenT seg, FeatNodePtr fnp, Uint1 label_align)
275 {
276 Int4 center, middle;
277 Int4 y_pos, x_pos;
278 Int4 tick_len;
279
280
281 tick_len = TICK_LEN;
282 switch(label_align)
283 {
284 case MSM_LABEL_TOP:
285 center = (fnp->extremes.left + fnp->extremes.right)/2;
286 y_pos = fnp->bottom;
287 AddLine(seg, center, y_pos, center, y_pos-tick_len, FALSE, fnp->itemID);
288 break;
289 case MSM_LABEL_BOTTOM:
290 center = (fnp->extremes.left + fnp->extremes.right)/2;
291 y_pos = fnp->top;
292 AddLine(seg, center, y_pos, center, y_pos+tick_len, FALSE, fnp->itemID);
293 break;
294 case MSM_LABEL_LEFT:
295 middle = (fnp->top + fnp->bottom)/2;
296 x_pos = fnp->extremes.left;
297 AddLine(seg, x_pos, middle, x_pos-tick_len, middle, FALSE, fnp->itemID);
298 break;
299 case MSM_LABEL_RIGHT:
300 middle = (fnp->top + fnp->bottom)/2;
301 x_pos = fnp->extremes.right;
302 AddLine(seg, x_pos, middle, x_pos+tick_len, middle, FALSE, fnp->itemID);
303 break;
304 default:
305 break;
306 }
307 }
308
309
310 /*gdata is added to record the possible selected marker*/
AddFeatNodeListLabel(SegmenT p_seg,ValNodePtr fnp_node,Uint1 label_align,Int4 scale,GeneDataPtr gdata)311 static Boolean AddFeatNodeListLabel(SegmenT p_seg, ValNodePtr fnp_node, Uint1 label_align, Int4 scale, GeneDataPtr gdata)
312 {
313 FeatNodePtr fnp;
314 Boolean has_prev = FALSE;
315 Int2 ptype = 0, _class;
316 FonT font = NULL;
317 Int4 color_val;
318 Uint1 color[3];
319
320 SegmenT seg = NULL;
321 Uint2 p_entityID = 0;
322
323 /* if(label_align > MSM_LABEL_RIGHT || label_align < MSM_LABEL_TOP)*/
324 if(label_align > 3 /* || label_align < 0 */)
325 return FALSE;
326 while(fnp_node)
327 {
328 fnp = fnp_node->data.ptrvalue;
329 if(!has_prev || fnp->entityID != p_entityID)
330 {
331 seg = CreateSegment(p_seg, fnp->entityID, 0);
332 p_entityID = fnp->entityID;
333 has_prev = FALSE;
334 }
335 if(fnp && fnp->label)
336 {
337 _class = get_current_class(fnp);
338
339 if(!has_prev || ptype != _class)
340 {
341 /*if(has_prev)
342 DeleteFont(font);*/
343 font = (FonT)GetMuskCParam(_class, MSM_FLABEL, MSM_FONT);
344 SelectFont(font);
345 color_val = GetMuskCParam(_class, MSM_FLABEL, MSM_COLOR);
346 convert_color(color_val, color);
347 AddAttribute(seg, COLOR_ATT, &(color[0]), 0, 0, 0, 0);
348
349 has_prev = TRUE;
350 ptype = _class;
351 }
352 if(fnp->landmark)
353 {
354 AddBoxWithAlign(seg, label_align, fnp, scale, gdata, (Uint2)(fnp_node->choice));
355 AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
356 }
357 AddFeatNodeLabel(seg, fnp, label_align, font);
358 }
359 if(fnp->draw_tick)
360 AddFeatNodeTickMark(seg, fnp, label_align);
361
362 fnp_node = fnp_node->next;
363 }
364
365 /*if(has_prev)
366 DeleteFont(font);*/
367 return TRUE;
368 }
369
DrawGapInterval(SegmenT seg,Int4 left,Int4 right,Int4 top,Int4 bottom,Int4 gap_style,Uint4 itemID)370 static void DrawGapInterval(SegmenT seg, Int4 left, Int4 right, Int4 top, Int4 bottom, Int4 gap_style, Uint4 itemID)
371 {
372 Int4 center, middle;
373
374 switch(gap_style)
375 {
376 case MSM_GAP_LINE:
377 middle = (top + bottom)/2;
378 AddLine(seg, left, middle, right, middle, FALSE, itemID);
379 break;
380 case MSM_GAP_ANGLE:
381 center = (left + right)/2;
382 middle = (top + bottom)/2;
383 AddLine(seg, left, middle, center, top, FALSE, itemID);
384 AddLine(seg, center, top, right, middle, FALSE, itemID);
385 break;
386 default:
387 break;
388 }
389 }
390
391
AddGapForOneFeatNode(FeatNodePtr fnp,Int4Ptr pstyle,Int2Ptr p_class,BoolPtr has_prev,SegmenT seg)392 static void AddGapForOneFeatNode(FeatNodePtr fnp, Int4Ptr pstyle, Int2Ptr p_class, BoolPtr has_prev, SegmenT seg)
393 {
394 Int4 prev_pos, i_left, i_right;
395 Int4 start, stop;
396 Int4 style, segstyle;
397 ValNodePtr ivals;
398 IvalNodePtr inp = NULL;
399 Int4 top, bottom;
400 Int2 _class;
401 Boolean show_gap;
402
403 ivals = fnp->interval;
404
405 _class = get_current_class(fnp);
406 if(!(*has_prev) || (*p_class) != _class)
407 {
408 style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
409 segstyle = (style & MSM_SEG_FORM);
410 show_gap = ((segstyle == MSM_SEG_BOX) || (segstyle == MSM_SEG_LINE));
411 if(!show_gap)
412 return;
413
414 add_attribute_pen(seg, _class, MSM_FGAP);
415 style = GetMuskCParam(_class, MSM_FGAP, MSM_STYLE);
416 *has_prev = TRUE;
417 *p_class = _class;
418 *pstyle = segstyle;
419 }
420 else
421 {
422 segstyle = *pstyle;
423 show_gap =(segstyle == MSM_SEG_BOX || segstyle == MSM_SEG_LINE);
424 if(!show_gap)
425 return;
426 else
427 style = GetMuskCParam(_class, MSM_FGAP, MSM_STYLE);
428
429 }
430
431
432 top = fnp->top;
433 bottom = fnp->bottom;
434 if(ivals == NULL)
435 {
436 start = fnp->extremes.left;
437 stop = fnp->extremes.right;
438 DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
439 return;
440 }
441
442 if(fnp->extremes.strand == Seq_strand_minus)
443 prev_pos = fnp->extremes.right;
444 else
445 prev_pos = fnp->extremes.left;
446 while(ivals)
447 {
448 inp = ivals->data.ptrvalue;
449 i_left = inp->gr.left;
450 i_right = inp->gr.right;
451 if(inp->gr.strand == Seq_strand_minus)
452 {
453 stop = prev_pos;
454 start = i_right;
455 prev_pos = i_left;
456 }
457 else
458 {
459 start = prev_pos;
460 stop = i_left;
461 prev_pos = i_right;
462 }
463 if(stop > start)
464 DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
465 ivals = ivals->next;
466 }
467
468 /*check the last piece*/
469 if(inp !=NULL)
470 {
471 if(inp->gr.strand == Seq_strand_minus)
472 {
473 stop = prev_pos;
474 start = fnp->extremes.left;
475 }
476 else
477 {
478 start = prev_pos;
479 stop = fnp->extremes.right;
480 }
481 if(stop > start)
482 DrawGapInterval(seg, start, stop, top, bottom, style, fnp->itemID);
483 }
484 }
485
486
AddFeatNodeListGaps(SegmenT p_seg,ValNodePtr fnp_node)487 static void AddFeatNodeListGaps(SegmenT p_seg, ValNodePtr fnp_node)
488 {
489 FeatNodePtr fnp;
490 Boolean has_prev = FALSE;
491 Int2 pclass = -1;
492 Int4 style = 0;
493 SegmenT seg = NULL;
494 Uint2 p_entityID = 0;
495
496 while(fnp_node)
497 {
498 fnp = fnp_node->data.ptrvalue;
499 if(!has_prev || fnp->entityID != p_entityID)
500 {
501 seg = CreateSegment(p_seg, fnp->entityID, 0);
502 p_entityID = fnp->entityID;
503 has_prev = FALSE; /*Reset has_prev to reset the style of the current seg*/
504 }
505 AddGapForOneFeatNode(fnp, &style, &pclass, &has_prev, seg);
506 fnp_node = fnp_node->next;
507 }
508 }
509
DrawFeatNodeSegment(FeatNodePtr fnp,Int4 segstyle,Int2 subclass,SegmenT seg,Boolean show_arrow,Boolean show_interval)510 static Boolean DrawFeatNodeSegment(FeatNodePtr fnp, Int4 segstyle, Int2 subclass, SegmenT seg, Boolean show_arrow, Boolean show_interval)
511 {
512 Int4 e_left, e_right, end_pos;
513 Int4 i_left, i_right;
514 Int4 top, bottom;
515 Uint1 strand;
516 Boolean fill;
517 Int2 arrow = NO_ARROW;
518 ValNodePtr ivals;
519 IvalNodePtr inp;
520
521 if(fnp == NULL)
522 return FALSE;
523 if(subclass != MSM_SEGMENT && subclass != MSM_SEG_BORD)
524 return FALSE;
525 if(segstyle != MSM_SEG_LINE && segstyle != MSM_SEG_BOX)
526 return FALSE;
527 if(segstyle == MSM_SEG_LINE && subclass == MSM_SEG_BORD)
528 return FALSE;
529 fill = (subclass == MSM_SEGMENT);
530
531 e_left = fnp->extremes.left;
532 e_right = fnp->extremes.right;
533 top = fnp->top;
534 bottom = fnp->bottom;
535 strand = fnp->extremes.strand;
536 if(fnp->interval == NULL)
537 {
538 if(show_interval)
539 return TRUE;
540 if(show_arrow)
541 arrow = get_arrow_for_strand(strand);
542 if(segstyle == MSM_SEG_BOX)
543 AddRectangle(seg, e_left, top, e_right, bottom, arrow, fill, fnp->itemID);
544 else
545 AddLine(seg, e_left, bottom, e_right, bottom, FALSE, fnp->itemID);
546 }
547 if(strand == Seq_strand_minus)
548 end_pos = e_left;
549 else
550 end_pos = e_right;
551
552 for(ivals = fnp->interval; ivals !=NULL; ivals = ivals->next)
553 {
554 arrow = NO_ARROW;
555 inp = ivals->data.ptrvalue;
556 i_left = inp->gr.left;
557 i_right = inp->gr.right;
558 if(show_arrow)
559 {
560 if(strand == Seq_strand_minus && i_left == end_pos)
561 arrow = LEFT_ARROW;
562 if(strand == Seq_strand_plus && i_right == end_pos)
563 arrow = RIGHT_ARROW;
564 }
565 if(segstyle == MSM_SEG_BOX)
566 AddRectangle (seg, i_left, top, i_right, bottom, arrow, fill, fnp->itemID);
567 else
568 AddLine(seg, i_left, bottom, i_right, bottom, FALSE, fnp->itemID);
569 }
570 return TRUE;
571 }
572
573
AddFeatNodeListBorder(SegmenT p_seg,ValNodePtr fnp_node,Boolean show_arrow,Boolean show_interval)574 static void AddFeatNodeListBorder(SegmenT p_seg, ValNodePtr fnp_node, Boolean show_arrow, Boolean show_interval)
575 {
576 FeatNodePtr fnp;
577 Boolean has_prev = FALSE;
578 Int2 ptype = 0, _class;
579 Boolean show_border = FALSE;
580 Int4 style, segstyle = 0;
581 Boolean arrow = FALSE;
582 SegmenT seg = NULL;
583 Uint2 p_entityID = 0;
584
585
586
587 while(fnp_node)
588 {
589 fnp = fnp_node->data.ptrvalue;
590 _class = get_current_class(fnp);
591 if(!has_prev || fnp->entityID != p_entityID)
592 {
593 seg = CreateSegment(p_seg, fnp->entityID, 0);
594 p_entityID = fnp->entityID;
595 has_prev = FALSE; /*force reset of the current style*/
596 }
597 if(!has_prev || ptype != _class)
598 {
599 /*the border is drawn only when the segment is drawn as a box */
600 style = GetMuskCParam(_class, MSM_SEG_BORD, MSM_TRUEFALSE);
601 if(style != 0)
602 {
603 style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
604 segstyle = (style & MSM_SEG_FORM);
605 show_border = (segstyle == MSM_SEG_BOX);
606 if(show_border)
607 {
608 add_attribute_pen(seg, _class, MSM_SEG_BORD);
609 if(show_arrow)
610 arrow = (Boolean)(style & (Int4)MSM_SEG_SHOWORIENT);
611 else
612 arrow = FALSE;
613 }
614 }
615 else
616 show_border = FALSE;
617 has_prev = TRUE;
618 ptype = _class;
619 }
620 if(show_border)
621 DrawFeatNodeSegment(fnp, segstyle, MSM_SEG_BORD, seg, arrow, show_interval);
622 fnp_node = fnp_node->next;
623 }
624 }
625
AddFeatNodeListSegments(SegmenT p_seg,ValNodePtr fnp_node,Boolean show_arrow,Boolean show_interval)626 static void AddFeatNodeListSegments(SegmenT p_seg, ValNodePtr fnp_node, Boolean show_arrow, Boolean show_interval)
627 {
628 Int4 style, segstyle = 0;
629 FeatNodePtr fnp;
630 Boolean has_prev = FALSE;
631 Int2 ptype = 0, _class;
632 Boolean show_segments = FALSE;
633 Boolean arrow = FALSE;
634 SegmenT seg = NULL;
635 Uint2 p_entityID = 0;
636
637 while(fnp_node)
638 {
639 fnp = fnp_node->data.ptrvalue;
640 if(!has_prev || fnp->entityID != p_entityID)
641 {
642 seg = CreateSegment(p_seg, fnp->entityID, 0);
643 p_entityID = fnp->entityID;
644 has_prev = FALSE; /*force to reset the style*/
645 }
646 _class = get_current_class(fnp);
647 if(!has_prev || ptype != _class)
648 {
649
650 style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
651 segstyle = (style & MSM_SEG_FORM);
652 if(segstyle == MSM_SEG_BOX || segstyle == MSM_SEG_LINE)
653 {
654 add_attribute_pen(seg, _class, MSM_SEGMENT);
655 has_prev = TRUE;
656 ptype = _class;
657 show_segments = TRUE;
658 if(show_arrow)
659 arrow = (Boolean)(style & (Int4)MSM_SEG_SHOWORIENT);
660 else
661 arrow = FALSE;
662 }
663 }
664 if(show_segments)
665 DrawFeatNodeSegment(fnp, segstyle, MSM_SEGMENT, seg, arrow, show_interval);
666 fnp_node = fnp_node->next;
667 }
668 }
669
670
create_flat_node(ValNodePtr fnp_node)671 static ValNodePtr create_flat_node (ValNodePtr fnp_node)
672 {
673 ValNodePtr flat_list = NULL, prev = NULL, curr;
674 FeatNodePtr fnp;
675 Int4 segstyle, style;
676 Int2 _class;
677
678 while(fnp_node)
679 {
680 if(fnp_node->choice == OBJ_SEQFEAT)
681 {
682 fnp = fnp_node->data.ptrvalue;
683 _class = get_current_class(fnp);
684 style = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
685 segstyle = (style & MSM_SEG_FORM);
686 if(segstyle != MSM_SEG_BOX && segstyle != MSM_SEG_LINE)
687 {
688 curr = ValNodeNew(NULL);
689 curr->choice = fnp_node->choice;
690 curr->data.ptrvalue = fnp;
691 if(prev == NULL)
692 flat_list = curr;
693 else
694 prev->next = curr;
695 prev = curr;
696 }
697 }
698 fnp_node = fnp_node->next;
699 }
700
701 return flat_list;
702 }
703
DrawFeatNode(ValNodePtr fnp_node,SegmenT seg,Uint1 label_type,Boolean show_arrow,Int4 scale,GeneDataPtr gdata)704 Boolean DrawFeatNode (ValNodePtr fnp_node, SegmenT seg, Uint1 label_type, Boolean show_arrow, Int4 scale, GeneDataPtr gdata)
705 {
706 Uint1 label_align;
707 Boolean show_interval = TRUE;
708 ValNodePtr flat_list;
709
710 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
711 flat_list = create_flat_node (fnp_node);
712 if(flat_list != NULL)
713 {
714 if(label_type != NO_LABEL)
715 AddFeatNodeListLabel(seg, flat_list, label_align, scale, gdata);
716 AddFlatNodeSymbol(seg, flat_list, scale);
717 ValNodeFree(flat_list);
718 }
719
720 if(scale > GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE))
721 show_interval = FALSE;
722 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
723
724 if(fnp_node == NULL || fnp_node->choice !=OBJ_SEQFEAT)
725 return FALSE;
726 if(label_type != NO_LABEL)
727 AddFeatNodeListLabel(seg, fnp_node, label_align, scale, gdata);
728 if(show_interval)
729 AddFeatNodeListGaps(seg, fnp_node);
730 AddFeatNodeListSegments(seg, fnp_node, show_arrow, show_interval);
731 AddFeatNodeListBorder(seg, fnp_node, show_arrow, show_interval);
732
733 /**if(draw_trunc)
734 {
735 if(fnp->extremes.l_trunc)
736 DrawSquiggle(seg, e_left, fnp->line, fnp->itemID, TRUE);
737 if(fnp->extremes.r_trunc)
738 DrawSquiggle(seg, e_right, fnp->line, fnp->itemID, FALSE);
739 }**/
740
741 return TRUE;
742 }
743
get_bin_symbol(Uint2 bin_order)744 static Uint1 get_bin_symbol(Uint2 bin_order)
745 {
746 switch(bin_order%4)
747 {
748 case 0:
749 return UP_TRIANGLE_SYMBOL;
750 case 1:
751 return LEFT_TRIANGLE_SYMBOL;
752 case 2:
753 return DOWN_TRIANGLE_SYMBOL;
754 default:
755 return RIGHT_TRIANGLE_SYMBOL;
756 }
757 }
758
get_map_type(Uint4 extra)759 Uint1 get_map_type(Uint4 extra)
760 {
761 if(extra & EXTRA_FRAME_WORK)
762 return FRAME_WORK;
763
764 if(extra & EXTRA_RECMIN)
765 return RECMIN;
766
767 if(extra & EXTRA_LIKELY)
768 return LIKELY;
769
770 if(extra & EXTRA_MDUP)
771 return MDUP;
772
773 if(extra & EXTRA_DUP)
774 return DUP;
775
776 if(extra & EXTRA_CONTIG_STS)
777 return CONTIG_STS;
778
779 return 0;
780 }
781
get_symbol_color(Uint4 extra)782 static Uint1Ptr get_symbol_color(Uint4 extra)
783 {
784 if(extra & EXTRA_YAC_END)
785 return GREEN_COLOR;
786 if(extra & EXTRA_RANDOM)
787 { /*this is a gold color */
788 custom_color[0] = 255;
789 custom_color[1] = 200;
790 /* custom_color[1] = 215; */
791 custom_color[2] = 0;
792 return custom_color;
793 }
794 if(extra & EXTRA_GENETIC)
795 return MAGENTA_COLOR;
796 if(extra & EXTRA_GENE)
797 return RED_COLOR;
798 if(extra & EXTRA_EST)
799 return BLUE_COLOR;
800 if(extra & EXTRA_MISC)
801 return CYAN_COLOR;
802 return BLACK_COLOR;
803 }
804
AddFlatNodeSymbol(SegmenT pseg,ValNodePtr fnp_node,Int4 scale)805 static Boolean AddFlatNodeSymbol(SegmenT pseg, ValNodePtr fnp_node, Int4 scale)
806 {
807 FeatNodePtr fnp;
808 Boolean has_prev = FALSE;
809 SegmenT seg = NULL;
810 Int2 ptype, _class;
811 Int4 symbol_height = 8;
812 Int4 middle, center;
813 /*Int4 color_val;*/
814 Int4 segstyle;
815 /*Uint1 color[3];*/
816 Uint1Ptr this_color;
817 Uint1 symbol_type = 0, symbol;
818 /*Uint2 bin_order;*/
819 Boolean fill;
820 Uint1 map_mark_type;
821 Uint2 p_entityID;
822
823 if(fnp_node == NULL)
824 return FALSE;
825 ptype = 0;
826 p_entityID = 0;
827 while(fnp_node)
828 {
829 fnp = fnp_node->data.ptrvalue;
830 _class = get_current_class(fnp);
831 fnp = fnp_node->data.ptrvalue;
832 if(!has_prev || fnp->entityID != p_entityID)
833 {
834 seg = CreateSegment(pseg, fnp->entityID, 0);
835 p_entityID = fnp->entityID;
836 has_prev = FALSE;
837 }
838 if(!has_prev || ptype != _class)
839 {
840 /*color_val = GetMuskCParam(_class, MSM_SEGMENT, MSM_COLOR);
841 convert_color(color_val, color);
842 AddAttribute(seg, COLOR_ATT, &(color[0]), 0, 0, 0, 0);*/
843 segstyle = GetMuskCParam(_class, MSM_SEGMENT, MSM_STYLE);
844 switch(segstyle & MSM_SEG_FORM)
845 {
846 case MSM_SEG_SYM_RECT:
847 symbol_type = RECT_SYMBOL;
848 break;
849 case MSM_SEG_SYM_DIAMOND:
850 symbol_type = DIAMOND_SYMBOL;
851 break;
852 case MSM_SEG_SYM_OVAL:
853 symbol_type = OVAL_SYMBOL;
854 break;
855 case MSM_SEG_SYM_TRIANGLE:
856 symbol_type = UP_TRIANGLE_SYMBOL;
857 break;
858 default:
859 symbol_type = DIAMOND_SYMBOL;
860 break;
861 }
862
863 ptype = _class;
864 }
865 this_color = get_symbol_color(fnp->extra_data);
866 AddAttribute(seg, COLOR_ATT, this_color, 0, 0, 0, 0);
867 map_mark_type = get_map_type(fnp->extra_data);
868 if(fnp->bin_order != 0)
869 symbol = get_bin_symbol(fnp->bin_order);
870 else
871 symbol = symbol_type;
872 fill = TRUE;
873 if(map_mark_type == LIKELY || map_mark_type == MDUP || map_mark_type == DUP || map_mark_type == CONTIG_STS)
874 fill = FALSE;
875 center = (fnp->extremes.left + fnp->extremes.right)/2;
876 middle = (fnp->top + fnp->bottom)/2;
877 AddSymbol(seg, center, middle, symbol, fill, MIDDLE_CENTER, fnp->itemID);
878 if(map_mark_type == FRAME_WORK)
879 {
880 AddSymbol(seg, center-8*scale, middle, symbol, TRUE, MIDDLE_CENTER, fnp->itemID);
881 AddSymbol(seg, center+8*scale, middle, symbol, TRUE, MIDDLE_CENTER, fnp->itemID);
882 }
883 p_entityID = fnp->entityID;
884 fnp_node = fnp_node->next;
885 }
886 return TRUE;
887 }
888
DrawFlatNode(ValNodePtr vnp,SegmenT seg,Uint1 label_type,Int4 scale,GeneDataPtr gdata)889 Boolean DrawFlatNode(ValNodePtr vnp, SegmenT seg, Uint1 label_type, Int4 scale, GeneDataPtr gdata)
890 {
891 Uint1 label_align;
892
893 if(label_type == UPPER_LABEL)
894 label_align = MSM_LABEL_TOP;
895 else
896 label_align = MSM_LABEL_BOTTOM;
897 AddFeatNodeListLabel(seg, vnp, label_align, scale, gdata);
898 AddFlatNodeSymbol(seg, vnp, scale);
899 return TRUE;
900 }
901
902
AddAlignmentLabel(ValNodePtr anp_list,SegmenT seg)903 static void AddAlignmentLabel(ValNodePtr anp_list, SegmenT seg)
904 {
905 FonT font;
906 Int4 color_val;
907 Uint1 color[3];
908 AlignNodePtr anp;
909 Uint1 label_align;
910 Uint4 itemID;
911
912
913 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
914 SelectFont(font);
915 color_val = GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_COLOR);
916 convert_color(color_val, color);
917 AddAttribute(seg, COLOR_ATT|SHADING_ATT, &(color[0]), 0, SOLID_SHADING, 0, COPY_MODE);
918
919 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
920 while(anp_list)
921 {
922 anp = anp_list->data.ptrvalue;
923 if(anp->use_seq_ids)
924 itemID = anp->bsp_itemID;
925 else
926 itemID = anp->itemID;
927 AddLabelWithAlign(seg, label_align, anp->extremes.left, anp->extremes.right, anp->top, anp->bottom, anp->label, font, itemID);
928 anp_list = anp_list->next;
929 }
930 /*DeleteFont(font);*/
931 }
932
933
get_color_for_block(AlignNodePtr anp,Uint2 val)934 static Uint1Ptr get_color_for_block (AlignNodePtr anp, Uint2 val)
935 {
936 switch(anp->index)
937 {
938 case 0:
939 return get_seg_color((Int2)val);
940 case 1: /*it is a map index */
941 if(val == MAP_STATUS_Mapping)
942 return MAGENTA_COLOR;
943 if(val == MAP_STATUS_Mapped)
944 return RED_COLOR;
945 if(val == MAP_STATUS_Paused)
946 return BLUE_COLOR;
947 return BLACK_COLOR;
948 case 2: /*it is a sequence index*/
949 if(val == SEQ_STATUS_Plan)
950 return CYAN_COLOR;
951 if(val == SEQ_STATUS_Sequencing)
952 return MAGENTA_COLOR;
953 if(val == SEQ_STATUS_Sequenced)
954 return RED_COLOR;
955 if(val == SEQ_STATUS_Paused)
956 return BLUE_COLOR;
957 return BLACK_COLOR;
958 default:
959 return BLACK_COLOR;
960 }
961 }
962
963
AddAlignBlocks(ValNodePtr anp_list,SegmenT seg)964 static void AddAlignBlocks(ValNodePtr anp_list, SegmenT seg)
965 {
966 AlignNodePtr anp;
967 Uint1Ptr color;
968 AlignBlockPtr abp;
969 Int2 arrow;
970 Int2 c_num;
971 Uint4 itemID;
972
973
974 c_num = (Int2)GetMuskCParam(MSM_CCOLOR, MSM_NOSUBCLASS, MSM_NUM);
975 while(anp_list)
976 {
977 anp = anp_list->data.ptrvalue;
978 if(anp->use_seq_ids)
979 itemID = anp->bsp_itemID;
980 else
981 itemID = anp->itemID;
982 for(abp = anp->blocks; abp != NULL; abp = abp->next)
983 {
984 arrow = get_arrow_for_strand(abp->gr.strand);
985 color = get_color_for_block (anp,(Int2)(abp->order));
986
987 /* pseg = CreateSegment(seg, OBJ_BIOSEQ_SEG, 0);
988 sseg = CreateSegment(pseg, anp->entityID, 0);
989 AddAttribute(sseg, COLOR_ATT, color, 0, 0, 0, 0);
990 AddRectangle(sseg, abp->gr.left, anp->top, abp->gr.right, anp->bottom, arrow, TRUE, abp->order); */
991 AddAttribute(seg, COLOR_ATT, color, 0, 0, 0, 0);
992 AddRectangle(seg, abp->gr.left, anp->top, abp->gr.right, anp->bottom, arrow, TRUE, itemID);
993 }
994 anp_list = anp_list->next;
995 }
996 }
997
AddSeqWithAlignmentSymbol(SegmenT seg,ValNodePtr anp_list,Int4 scale)998 static void AddSeqWithAlignmentSymbol(SegmenT seg, ValNodePtr anp_list, Int4 scale)
999 {
1000 Int4 length, width;
1001 AlignNodePtr anp;
1002 Int4 left, right, center;
1003 Uint4 itemID;
1004
1005
1006 length = scale *4;
1007 width = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
1008 if(width > 3)
1009 width = 3;
1010
1011 while(anp_list)
1012 {
1013 anp = anp_list->data.ptrvalue;
1014 if(anp && anp->seq_has_align == TRUE)
1015 {
1016 center = (anp->extremes.left + anp->extremes.right)/2;
1017 left = center - length/2;
1018 right = center + length/2;
1019 if(anp->use_seq_ids)
1020 itemID = anp->bsp_itemID;
1021 else
1022 itemID = anp->itemID;
1023 AddRectangle(seg, left, anp->top + width, right, anp->top, FALSE, TRUE, itemID);
1024 }
1025
1026 anp_list = anp_list->next;
1027 }
1028
1029 }
1030 /*#######################################################################
1031 #
1032 # functions related to DrawAlignNode
1033 #
1034 #######################################################################*/
1035
1036
AddRepeatsToAlignment(ValNodePtr anp_list,SegmenT seg)1037 static void AddRepeatsToAlignment (ValNodePtr anp_list, SegmenT seg)
1038 {
1039 AlignNodePtr anp;
1040 AlignSegPtr asp;
1041 Int4 left, right;
1042 ValNodePtr f_node;
1043 FeatNodePtr fnp;
1044 Uint4 itemID;
1045 Uint1 arrow;
1046
1047 AddAttribute(seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, 0, LIGHT_SHADING, 0, 0);
1048 while(anp_list)
1049 {
1050 if(anp_list->choice != OBJ_SEQANNOT)
1051 {
1052 anp = anp_list->data.ptrvalue;
1053 if(anp != NULL && anp->segs != NULL)
1054 {
1055 if(anp->use_seq_ids)
1056 itemID = anp->bsp_itemID;
1057 else
1058 itemID = anp->itemID;
1059 for(asp = anp->segs; asp != NULL; asp = asp->next)
1060 {
1061 f_node = asp->cnp;
1062 while(f_node)
1063 {
1064 fnp = f_node->data.ptrvalue;
1065 arrow = NO_ARROW;
1066 left = fnp->extremes.right;
1067 right =fnp->extremes.left;
1068 if(anp->extremes.strand == Seq_strand_minus)
1069 {
1070 if(fnp->extremes.left == anp->extremes.left)
1071 arrow = LEFT_ARROW;
1072 }
1073 else
1074 {
1075 if(fnp->extremes.right == anp->extremes.right)
1076 arrow = RIGHT_ARROW;
1077 }
1078
1079 if(fnp->feattype == FEATDEF_repeat_region || fnp->feattype == FEATDEF_repeat_unit)
1080 AddRectangle(seg, left, asp->top-1, right, asp->bottom+1, arrow, TRUE, itemID);
1081 f_node = f_node->next;
1082 }
1083 }
1084 }
1085 }
1086 anp_list = anp_list->next;
1087 }
1088 AddAttribute(seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, 0, SOLID_SHADING, 0, COPY_MODE);
1089 }
1090
1091
DrawAlignSegs(SegmenT seg,AlignNodePtr anp)1092 static void DrawAlignSegs(SegmenT seg, AlignNodePtr anp)
1093 {
1094 Int4 i_left, i_right, e_left, e_right;
1095 Int4 p_left = 0, p_right = 0, p_top = 0, p_bottom = 0;
1096 AlignSegPtr asp;
1097 Int2 c_arrow, p_arrow = 0;
1098 Uint1 strand;
1099 Boolean has_prev = FALSE;
1100 Boolean load;
1101 Int4 seglen;
1102 Uint4 itemID;
1103
1104
1105
1106 /*add each segment in alignment*/
1107 strand = anp->extremes.strand;
1108 e_left = anp->extremes.left;
1109 e_right = anp->extremes.right;
1110 if(anp->use_seq_ids)
1111 itemID = anp->bsp_itemID;
1112 else
1113 itemID = anp->itemID;
1114
1115
1116 if(anp->extremes.l_trunc == TRUE)
1117 DrawSquiggle(seg, e_left, anp->bottom, itemID, TRUE);
1118 if(anp->extremes.r_trunc == TRUE)
1119 DrawSquiggle(seg, e_right, anp->bottom, itemID, FALSE);
1120
1121 if(anp->segs == NULL) /*no intervals*/
1122 {
1123 c_arrow = get_arrow_for_strand(strand);
1124 if(ABS(anp->bottom - anp->top) <= 3)
1125 AddLine(seg, e_left, anp->top, e_right, anp->top, FALSE, itemID);
1126 else
1127 AddRectangle(seg, e_left, anp->top, e_right, anp->bottom, c_arrow, FALSE, itemID);
1128 return;
1129 }
1130
1131
1132
1133 for(asp = anp->segs; asp !=NULL; asp = asp->next)
1134 {
1135 switch(asp->type)
1136 {
1137 case INS_SEG:
1138 seglen = asp->gr.right;
1139 AddRectangle(seg, asp->gr.left, asp->top, (asp->gr.left+seglen-1), asp->bottom, NO_ARROW, FALSE, itemID);
1140 AddLine(seg, asp->ins_pos, anp->bottom, asp->ins_pos, asp->top, FALSE, itemID);
1141 break;
1142 case GAP_SEG:
1143 AddLine(seg, asp->gr.left, asp->top, asp->gr.right, asp->top, FALSE, itemID);
1144 break;
1145 default:
1146 i_left = asp->gr.left;
1147 i_right = asp->gr.right;
1148 c_arrow = NO_ARROW;
1149 if(i_left == e_left && strand == Seq_strand_minus)
1150 c_arrow = LEFT_ARROW;
1151 if(i_right == e_right && strand == Seq_strand_plus)
1152 c_arrow = RIGHT_ARROW;
1153 load = FALSE;
1154
1155 if(has_prev)
1156 {
1157 if(p_right+1 == i_left)
1158 {
1159 p_right = i_right;
1160 if(strand != Seq_strand_minus)
1161 p_arrow = c_arrow;
1162 load = TRUE;
1163 }
1164 else
1165 AddRectangle(seg, p_left, asp->top, p_right, asp->bottom, p_arrow, FALSE, itemID);
1166 }
1167 if(!load)
1168 {
1169 p_left = i_left;
1170 p_right = i_right;
1171 p_top = asp->top;
1172 p_bottom = asp->bottom;
1173 p_arrow = c_arrow;
1174 }
1175 has_prev = TRUE;
1176 break;
1177 }
1178 }
1179 if(has_prev)
1180 AddRectangle(seg, p_left, p_top, p_right, p_bottom, p_arrow, FALSE, itemID);
1181
1182
1183 }
1184
AddAlignmentSegs(ValNodePtr anp_list,SegmenT seg)1185 static void AddAlignmentSegs(ValNodePtr anp_list, SegmenT seg)
1186 {
1187 AlignNodePtr anp;
1188 Int2 num; /*counting the number of the follower groups*/
1189 Boolean p_follower = FALSE;
1190
1191 add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEG_BORD);
1192 num = 0;
1193 while(anp_list)
1194 {
1195 anp = anp_list->data.ptrvalue;
1196 if(anp->num_follower != 0 )
1197 {
1198 ++num;
1199 switch(num%3)
1200 {
1201 case 1:
1202 AddAttribute (seg, COLOR_ATT, BLUE_COLOR,
1203 NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1204 break;
1205 case 2:
1206 AddAttribute (seg, COLOR_ATT, CYAN_COLOR,
1207 NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1208 break;
1209 default:
1210 AddAttribute (seg, COLOR_ATT, GREEN_COLOR,
1211 NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1212 break;
1213 }
1214 }
1215 else if(num > 0 && anp->follower == FALSE && p_follower == TRUE)
1216 AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1217 p_follower = anp->follower;
1218 DrawAlignSegs(seg, anp);
1219 anp_list = anp_list->next;
1220 }
1221 }
1222
1223
1224
1225 typedef struct alignfeature{
1226 Uint4 itemID;
1227 Int4 e_left;
1228 Int4 e_right;
1229 }AlignFeature, PNTR AlignFeaturePtr;
1230
ck_load_itemID(Uint4 itemID,Int4 e_left,Int4 e_right,ValNodePtr PNTR item_list)1231 static void ck_load_itemID (Uint4 itemID, Int4 e_left, Int4 e_right, ValNodePtr PNTR item_list)
1232 {
1233 ValNodePtr curr;
1234 AlignFeaturePtr afp;
1235
1236
1237 for(curr = *item_list; curr !=NULL; curr = curr->next)
1238 {
1239 afp = curr->data.ptrvalue;
1240 if(afp->itemID == itemID)
1241 {
1242 afp->e_left = MIN(afp->e_left, e_left);
1243 afp->e_right = MAX(afp->e_right, e_right);
1244 return;
1245 }
1246 }
1247
1248 afp = MemNew(sizeof(AlignFeature));
1249 afp->e_left = e_left;
1250 afp->e_right = e_right;
1251 afp->itemID = itemID;
1252
1253 ValNodeAddPointer(item_list, 0, (Pointer)afp);
1254 }
1255
1256
dup_interval_node(ValNodePtr list)1257 static ValNodePtr dup_interval_node(ValNodePtr list)
1258 {
1259 ValNodePtr new = NULL;
1260 IvalNodePtr inp, n_inp;
1261
1262 while(list)
1263 {
1264 inp = list->data.ptrvalue;
1265 n_inp = MemNew(sizeof(IvalNode));
1266 MemCopy((Pointer)n_inp, (Pointer)inp, sizeof(IvalNode));
1267 ValNodeAddPointer(&new, 0, n_inp);
1268
1269 list = list->next;
1270 }
1271
1272 return new;
1273 }
1274
get_last_node(ValNodePtr list)1275 static ValNodePtr get_last_node(ValNodePtr list)
1276 {
1277 if(list == NULL)
1278 return NULL;
1279
1280 while(list->next != NULL)
1281 list = list->next;
1282 return list;
1283 }
1284
merge_feature_interval_node(ValNodePtr PNTR i_node,ValNodePtr list,GatherRangePtr grp_i,GatherRangePtr grp_l)1285 static Boolean merge_feature_interval_node(ValNodePtr PNTR i_node, ValNodePtr list, GatherRangePtr grp_i, GatherRangePtr grp_l)
1286 {
1287 ValNodePtr i_last, l_last, new;
1288 IvalNodePtr i_inp, l_inp;
1289
1290
1291 if(grp_i->right +1 == grp_l->left)
1292 {
1293 if(list != NULL)
1294 {
1295 if(*i_node == NULL)
1296 *i_node = dup_interval_node(list);
1297 else
1298 {
1299 i_last = get_last_node(*i_node);
1300 i_inp = i_last->data.ptrvalue;
1301 l_inp = list->data.ptrvalue;
1302 if(i_inp->gr.right +1 == l_inp->gr.left)
1303 {
1304 i_inp->gr.right = l_inp->gr.right;
1305 i_last->next = dup_interval_node(list->next);
1306 }
1307 else
1308 i_last->next = dup_interval_node(list);
1309 }
1310 }
1311 grp_i->right = grp_l->right;
1312 return TRUE;
1313 }
1314
1315 if(grp_i->left == grp_l->right +1)
1316 {
1317 if(list != NULL)
1318 {
1319 if(*i_node == NULL)
1320 *i_node = dup_interval_node(list);
1321 else
1322 {
1323 new = dup_interval_node(list);
1324 l_last = get_last_node(list);
1325 l_inp = l_last->data.ptrvalue;
1326 i_inp = (*i_node)->data.ptrvalue;
1327 if(l_inp->gr.right +1 == i_inp->gr.left)
1328 {
1329 l_last = get_last_node(new);
1330 l_inp = l_last->data.ptrvalue;
1331 l_inp->gr.right = i_inp->gr.right;
1332 l_last->next = (*i_node)->next;
1333 (*i_node)->next = NULL;
1334 ValNodeFreeData(*i_node);
1335 }
1336 else
1337 {
1338 ValNodeLink(&new, *i_node);
1339 *i_node = new;
1340 }
1341 }
1342
1343 grp_i->left = grp_l->left;
1344 }
1345
1346 return TRUE;
1347 }
1348
1349 return FALSE;
1350 }
1351
1352
1353
is_repeat_feature(Uint1 feattype)1354 static Boolean is_repeat_feature (Uint1 feattype)
1355 {
1356 return (feattype == FEATDEF_repeat_region ||feattype == FEATDEF_repeat_unit);
1357 }
1358
AddAlignFeature(AlignNodePtr anp,SegmenT a_seg,Boolean show_arrow)1359 static void AddAlignFeature(AlignNodePtr anp, SegmenT a_seg, Boolean show_arrow)
1360 {
1361 ValNodePtr item_list = NULL, c_list;
1362 ValNodePtr i_node, p_node;
1363 Uint4 itemID;
1364 AlignSegPtr asp;
1365 FeatNodePtr fnp, c_fnp;
1366 GatherRange extremes;
1367 ValNode vn;
1368 ValNodePtr f_list;
1369 Uint1 ptype = 0;
1370 ValNodePtr repeat_node;
1371
1372 SegmenT seg;
1373 Int4 offset;
1374 Uint1 strand;
1375 Boolean arrow;
1376 AlignFeaturePtr afp;
1377
1378
1379 /*collect a list of feature itemIDs for REG_SEGs because some
1380 may need to be merged later */
1381 /*features in INS_SEG+DIAG_SEG are drawn because they don't need
1382 to be merged */
1383 for(asp = anp->segs; asp !=NULL; asp = asp->next)
1384 {
1385 if(asp->type == INS_SEG || asp->type == DIAG_SEG)
1386 {
1387 if(asp->cnp !=NULL)
1388 {
1389 repeat_node = strip_repeat_feature(&(asp->cnp));
1390 seg = CreateSegment(a_seg, OBJ_SEQFEAT, 0);
1391 /*not showing any arrow here*/
1392 DrawFeatNode (asp->cnp, seg, NO_LABEL, FALSE, 1, NULL);
1393 if(repeat_node != NULL)
1394 ValNodeLink(&(asp->cnp), repeat_node);
1395 /*resume the previous layout for FeatNode*/
1396 if(asp->type == INS_SEG)
1397 {
1398 offset = asp->gr.left - asp->ins_pos;
1399 if(offset != 0)
1400 modify_insert_fnode(asp->cnp, (-offset));
1401 }
1402 }
1403 }
1404 if(asp->type == REG_SEG) /*need some merging process*/
1405 {
1406 for(f_list = asp->cnp; f_list !=NULL; f_list = f_list->next)
1407 {
1408 fnp = f_list->data.ptrvalue;
1409 if(!is_repeat_feature (fnp->feattype))
1410 ck_load_itemID (fnp->itemID, fnp->extremes.left, fnp->extremes.right, &item_list);
1411 }
1412 }
1413 }
1414
1415 if(item_list != NULL)
1416 {
1417
1418 /*merge the features in REG_SEG according to their itemID*/
1419 for(c_list = item_list; c_list != NULL; c_list = c_list->next)
1420 {
1421 seg = CreateSegment(a_seg, OBJ_SEQFEAT, 0);
1422 afp = c_list->data.ptrvalue;
1423 itemID = afp->itemID;
1424 c_fnp = NULL;
1425 i_node = NULL;
1426 for(asp = anp->segs; asp !=NULL; asp = asp->next)
1427 { if(asp->type == REG_SEG)
1428 {
1429 for(f_list = asp->cnp; f_list !=NULL; f_list = f_list->next)
1430 {
1431 fnp = f_list->data.ptrvalue;
1432 if(fnp->itemID == itemID && !is_repeat_feature(fnp->feattype)) /*find the match*/
1433 {
1434 if(c_fnp == NULL)
1435 {
1436 c_fnp = fnp;
1437 if(fnp->interval != NULL)
1438 i_node = dup_interval_node(fnp->interval);
1439 MemCopy(&extremes, &(fnp->extremes), sizeof(GatherRange));
1440
1441 }
1442 else if(!merge_feature_interval_node(&i_node, fnp->interval, &(c_fnp->extremes), &(fnp->extremes)))
1443 {
1444 if(show_arrow)
1445 {
1446 strand = c_fnp->extremes.strand;
1447 if(strand == Seq_strand_minus)
1448 arrow = (c_fnp->extremes.left == afp->e_left);
1449 else
1450 arrow = (c_fnp->extremes.right == afp->e_right);
1451 }
1452 else
1453 arrow = FALSE;
1454 p_node = c_fnp->interval;
1455 c_fnp->interval = i_node;
1456 vn.choice = OBJ_SEQFEAT;
1457 vn.data.ptrvalue = c_fnp;
1458 vn.next = NULL;
1459 DrawFeatNode (&vn, seg, NO_LABEL, arrow, 1, NULL);
1460 c_fnp->interval = p_node;
1461 MemCopy((Pointer)&(c_fnp->extremes), (Pointer)&extremes, sizeof(GatherRange));
1462 if(i_node != NULL)
1463 i_node = ValNodeFreeData(i_node);
1464 c_fnp = fnp;
1465 if(fnp->interval != NULL)
1466 i_node = dup_interval_node(fnp->interval);
1467 MemCopy((Pointer)&extremes, (Pointer)&(fnp->extremes), sizeof(GatherRange));
1468 }
1469 }
1470
1471 }
1472 }
1473 }
1474
1475 if(c_fnp != NULL)
1476 {
1477 if(show_arrow)
1478 {
1479 strand = c_fnp->extremes.strand;
1480 if(strand == Seq_strand_minus)
1481 arrow = (c_fnp->extremes.left == afp->e_left);
1482 else
1483 arrow = (c_fnp->extremes.right == afp->e_right);
1484 }
1485 else
1486 arrow = FALSE;
1487 p_node = c_fnp->interval;
1488 c_fnp->interval = i_node;
1489 vn.choice = OBJ_SEQFEAT;
1490 vn.data.ptrvalue = c_fnp;
1491 vn.next = NULL;
1492 DrawFeatNode (&vn, seg, NO_LABEL, arrow, 1, NULL);
1493 c_fnp->interval = p_node;
1494 MemCopy((Pointer)&(c_fnp->extremes), (Pointer)&extremes, sizeof(GatherRange));
1495 }
1496 if(i_node != NULL)
1497 i_node = ValNodeFreeData(i_node);
1498 }
1499
1500 ValNodeFreeData(item_list);
1501 }
1502
1503 }
1504
AddAlignmentFeature(ValNodePtr anp_node,SegmenT seg,Int4 scale)1505 static void AddAlignmentFeature(ValNodePtr anp_node, SegmenT seg, Int4 scale)
1506 {
1507 AlignNodePtr anp;
1508 Boolean show_arrow;
1509
1510 show_arrow = (GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE) >= scale);
1511
1512 while(anp_node)
1513 {
1514 anp = anp_node->data.ptrvalue;
1515 if(anp->segs !=NULL)
1516 AddAlignFeature(anp, seg, show_arrow);
1517 anp_node = anp_node->next;
1518 }
1519 }
1520
AddAlignmentMismatch(ValNodePtr anp_node,Int4 scale,SegmenT seg)1521 static void AddAlignmentMismatch(ValNodePtr anp_node, Int4 scale, SegmenT seg)
1522 {
1523 Int4 i_right;
1524 Int4 top, bottom;
1525 Int4 p_i, j;
1526 ValNodePtr curr, list;
1527 AlignNodePtr anp;
1528 AlignSegPtr asp;
1529 Int4 symbol_width = 8;
1530 Int2 p_type = -1, type;
1531 Uint4 itemID;
1532
1533 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, RED_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1534
1535 for(list = anp_node; list !=NULL; list = list->next)
1536 {
1537 anp = list->data.ptrvalue;
1538 p_i = -1;
1539 if(anp->use_seq_ids)
1540 itemID = anp->bsp_itemID;
1541 else
1542 itemID = anp->itemID;
1543 for(asp = anp->segs; asp !=NULL; asp = asp->next)
1544 {
1545 i_right = asp->gr.right;
1546 top = asp->top;
1547 bottom = asp->bottom;
1548 for(curr = asp->mismatch; curr!=NULL; curr = curr->next)
1549 {
1550 j = curr->data.intvalue;
1551 type = curr->choice;
1552 if(type == 0)
1553 symbol_width = 1;
1554 else
1555 symbol_width = 8;
1556 if(p_i == -1 || (j-p_i) > scale * symbol_width || p_type != type)
1557 {
1558 switch (type)
1559 {
1560 case MISMATCH_OPEN:
1561 AddSymbol(seg, j, (top+bottom)/2, OVAL_SYMBOL, FALSE, MIDDLE_CENTER, itemID);
1562 break;
1563 case MISMATCH_CLOSE:
1564 AddSymbol(seg, j, (top+bottom)/2, OVAL_SYMBOL, TRUE, MIDDLE_CENTER, itemID);
1565 break;
1566 case MISMATCH_SQUARE:
1567 AddSymbol(seg, j, (top+bottom)/2, RECT_SYMBOL, TRUE, MIDDLE_CENTER, itemID);
1568 break;
1569 default:
1570 AddLine(seg, j, asp->top, j, (asp->bottom), FALSE, itemID);
1571 break;
1572 }
1573 p_i = j;
1574 p_type = type;
1575 }
1576 }
1577 }
1578 }
1579 }
1580
extra_align_node(ValNodePtr anp_node,Boolean use_seq_ids)1581 static ValNodePtr extra_align_node(ValNodePtr anp_node, Boolean use_seq_ids)
1582 {
1583 ValNodePtr head = NULL;
1584 AlignNodePtr anp;
1585
1586 while(anp_node)
1587 {
1588 anp = anp_node->data.ptrvalue;
1589 if(anp->use_seq_ids == use_seq_ids)
1590 ValNodeAddPointer(&head, anp_node->choice, anp);
1591 anp_node = anp_node->next;
1592 }
1593
1594 return head;
1595 }
1596
1597 /**********************************************************************
1598 *
1599 * DrawAlignNode(vnp, scale, seg)
1600 * Draw a list of AlignNode.
1601 * 1) It always labels the sequences
1602 * 2) the label is always on top of the sequence
1603 * 3) right now, it does NOT show the truncation
1604 *
1605 **********************************************************************/
DrawAlignNode(ValNodePtr vnp,Int4 scale,SegmenT seg)1606 Boolean DrawAlignNode(ValNodePtr vnp, Int4 scale, SegmenT seg)
1607 {
1608 ValNodePtr anp_node, curr, next;
1609 AlignNodePtr anp;
1610 SegmenT t_seg, p_seg;
1611
1612 if(vnp == NULL)
1613 return FALSE;
1614
1615 anp_node = extra_align_node(vnp, TRUE);
1616 if(anp_node != NULL)
1617 {
1618 p_seg = CreateSegment(seg, OBJ_BIOSEQ, 0);
1619 curr = anp_node;
1620 while(curr)
1621 {
1622 next = curr->next;
1623 curr->next = NULL;
1624 anp = curr->data.ptrvalue;
1625 t_seg = CreateSegment(p_seg, anp->seq_entityID, 0);
1626 AddAlignmentSegs(curr, t_seg);
1627 AddSeqWithAlignmentSymbol(t_seg, curr, scale);
1628 AddAlignmentMismatch(curr, scale, t_seg);
1629 AddAlignmentFeature(curr, t_seg, scale);
1630 AddAlignBlocks(curr, t_seg); /*add the blocks that are used in segmented seq*/
1631 AddAlignmentLabel(curr, t_seg);
1632 AddRepeatsToAlignment (curr, t_seg);
1633 curr->next = next;
1634 curr = next;
1635 }
1636 ValNodeFree(anp_node);
1637 }
1638
1639
1640 anp_node = extra_align_node(vnp, FALSE);
1641 if(anp_node != NULL)
1642 {
1643 AddAlignmentSegs(anp_node, seg);
1644 AddSeqWithAlignmentSymbol(seg, anp_node, scale);
1645 AddAlignmentMismatch(anp_node, scale, seg);
1646 AddAlignmentFeature(anp_node, seg, scale);
1647 AddAlignBlocks(anp_node, seg); /*add the blocks that are used in segmented seq*/
1648 AddAlignmentLabel(anp_node, seg);
1649 AddRepeatsToAlignment(anp_node, seg);
1650 ValNodeFree(anp_node);
1651 }
1652
1653 return TRUE;
1654 }
1655
1656
DrawFlatAlign(SegmenT seg,ValNodePtr anp_list)1657 Boolean DrawFlatAlign(SegmenT seg, ValNodePtr anp_list)
1658 {
1659 Uint4 itemID;
1660 AlignNodePtr anp;
1661 Int4 pos;
1662
1663 if(anp_list == NULL)
1664 return FALSE;
1665 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1666 while(anp_list)
1667 {
1668 if(anp_list->choice != OBJ_SEQANNOT)
1669 {
1670 anp = anp_list->data.ptrvalue;
1671 itemID = anp->itemID;
1672 pos = anp->extremes.left;
1673
1674 AddSymbol(seg, pos, anp->line, DIAMOND_SYMBOL, TRUE, UPPER_CENTER, itemID);
1675
1676 }
1677 anp_list = anp_list->next;
1678 }
1679
1680 return TRUE;
1681 }
1682
1683
1684
1685 /*************************************************************************
1686 *
1687 * DrawGeneticMap(features, mpp, pic, scale)
1688 * draw the genetic map from featnode
1689 * features: the list of FeatNode, will be resorted
1690 * mpp: the current map position. The drawing will recalculate
1691 * mpp->seq_top and mpp->bottom
1692 * pic: the drawing picture
1693 * scale: the maximum scale in drawing. Will be used in the layout
1694 * gdata: to include the possible selected marker
1695 *
1696 *************************************************************************/
DrawGeneticMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR image_list)1697 Boolean DrawGeneticMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR image_list)
1698 {
1699 SegmenT seg;
1700 Int4 top;
1701 ValNodePtr g_node;
1702 Boolean retval = FALSE;
1703
1704 seg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1705 g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1706 top = mpp->seq_top;
1707 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1708 if(g_node)
1709 {
1710 top = LayoutNodeFlat(&g_node, scale, top, UPPER_LABEL, FALSE);
1711 if(image_list != NULL)
1712 load_align_label_rectangle(g_node, image_list, scale, TRUE);
1713 DrawFlatNode(g_node, seg, UPPER_LABEL, scale, gdata);
1714 FreeFeatureList(g_node);
1715 mpp->seq_bottom = mpp->seq_top = top;
1716 retval = TRUE;
1717 }
1718 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1719 AddLine(seg, mpp->left, mpp->seq_top, mpp->right, mpp->seq_top, FALSE, 0);
1720 DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_top, scale, FALSE);
1721 mpp->bottom = mpp->seq_bottom - SCALE_SPACE;
1722 return retval;
1723 }
1724
1725
1726
1727 /*************************************************************************
1728 *
1729 * DrawPhysicalMap(features, mpp, pic, scale)
1730 * draw the physical map from featnode
1731 * features: the list of FeatNode, will be resorted
1732 * mpp: the current map position. The drawing will recalculate
1733 * mpp->seq_top and mpp->bottom
1734 * pic: the drawing picture
1735 * scale: the maximum scale in drawing. Will be used in the layout
1736 *
1737 *************************************************************************/
DrawPhysicalMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,ValNodePtr PNTR image_list)1738 Boolean DrawPhysicalMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, ValNodePtr PNTR image_list)
1739 {
1740 SegmenT pseg, seg;
1741 Int4 top;
1742 ValNodePtr g_node;
1743 Boolean retval = FALSE;
1744
1745 pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1746 seg = CreateSegment(pseg, mpp->entityID, 0);
1747 g_node = extract_node_list(features, OBJ_SEQFEAT, 0, 0, NUM_LABEL);
1748 top = mpp->seq_top;
1749 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1750 AddLine(seg, mpp->left, top, mpp->right, top, FALSE, 0);
1751 if(g_node)
1752 {
1753 top = LayoutNodeFlat(&g_node, scale, top, LOWER_LABEL, FALSE);
1754 if(image_list != NULL)
1755 load_align_label_rectangle(g_node, image_list, scale, TRUE);
1756 DrawFlatNode(g_node, pseg, LOWER_LABEL, scale, NULL);
1757 top -= (TICK_LEN+LABEL_SPACE);
1758 FreeFeatureList(g_node);
1759 mpp->seq_bottom = mpp->seq_top;
1760 retval = TRUE;
1761 }
1762 else
1763 DrawSeqScale(pic, mpp->slp, mpp->left, mpp->bottom, scale, FALSE);
1764
1765 top -= (LABEL_SPACE+TICK_LEN);
1766 mpp->bottom = top;
1767 return retval;
1768 }
1769
1770
sort_same_itemID(ValNodePtr head)1771 static ValNodePtr sort_same_itemID(ValNodePtr head)
1772 {
1773 FeatNodePtr fnp;
1774 ValNodePtr list = NULL, new;
1775
1776 while(head)
1777 {
1778 fnp = head->data.ptrvalue;
1779 new = merge_same_itemID(&head, fnp->itemID);
1780 ValNodeLink(&list, new);
1781 }
1782
1783 return list;
1784 }
1785
1786
1787
1788 /***********************************************************************
1789 *
1790 * DrawRestrictionMap(features, mpp, pic, rsite_flat, strand)
1791 * draw the restriction map
1792 * features: the FeatNode contains the info for restriction map
1793 * mpp: the map position
1794 * pic: picture
1795 * rsite_flat: if(TRUE), all the enzymes are shown in one line.
1796 * strand: the orientation of the map
1797 *
1798 ***********************************************************************/
DrawRestrictionMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Boolean rsite_flat,Uint1 strand,Int4 scale)1799 Boolean DrawRestrictionMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Boolean rsite_flat, Uint1 strand, Int4 scale)
1800 {
1801
1802 Int4 x1, x2, center;
1803 Int2 arrow;
1804 ValNodePtr seq_node, g_node, curr, c_head;
1805 FeatNodePtr fnp;
1806 IvalNodePtr inp;
1807 ValNodePtr ivals;
1808 Int4 top;
1809 Int2 i;
1810 Uint1Ptr color;
1811 Boolean retval = FALSE;
1812 SegmenT pseg, seg;
1813 Int4 seq_width;
1814 FonT font;
1815
1816 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
1817 SelectFont(font);
1818 seq_width = FontHeight();
1819 /* seq_width = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT); */
1820 arrow = get_arrow_for_strand(strand);
1821 x1 = mpp->left;
1822 x2 = mpp->right;
1823 center = (x1+x2)/2;
1824 top = mpp->seq_top;
1825
1826 pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1827 seg = CreateSegment(pseg, mpp->entityID, 0);
1828 if(rsite_flat)
1829 {
1830 seq_node = extract_node_list(features, OBJ_BIOSEQ, 0, 0, ALL_LABEL);
1831 fnp = seq_node->data.ptrvalue;
1832 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
1833 AddRectangle (seg, x1, top, x2, top-seq_width, arrow, FALSE, fnp->itemID);
1834 AddLabel(seg, x1, top, fnp->label, SMALL_TEXT, 0, LOWER_CENTER, fnp->itemID);
1835 mpp->seq_top = top;
1836 mpp->seq_bottom = top - seq_width;
1837 top -= LABEL_SPACE;
1838 FreeFeatureList(seq_node);
1839 mpp->bottom = top;
1840 }
1841
1842 g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1843 if(g_node == NULL)
1844 return FALSE;
1845 i = 0;
1846 while(g_node)
1847 {
1848 fnp = (FeatNodePtr)(g_node->data.ptrvalue);
1849 c_head = merge_same_itemID(&g_node, fnp->itemID);
1850 if(c_head)
1851 {
1852 if(!rsite_flat)
1853 {
1854 (mpp->seq_bottom) -=seq_width;
1855 top = mpp->seq_bottom + seq_width;
1856 AddAttribute (seg, WIDTH_ATT | COLOR_ATT,BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
1857 AddLabel(seg, mpp->left, top+seq_width/2, fnp->label, SMALL_TEXT, 5, LOWER_LEFT, fnp->itemID);
1858 AddLine(seg, mpp->left, top - seq_width, mpp->right, top-seq_width, FALSE, 0);
1859 if(i == 0)
1860 AddLine(seg, mpp->left, top, mpp->right, top, FALSE, 0);
1861 }
1862
1863 for(curr = c_head; curr !=NULL; curr = curr->next)
1864 {
1865 fnp = (FeatNodePtr)(curr->data.ptrvalue);
1866 color = get_enz_color(i);
1867 AddAttribute (seg, WIDTH_ATT | COLOR_ATT,color, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
1868 ivals = fnp->interval;
1869 while(ivals)
1870 {
1871 inp = ivals->data.ptrvalue;
1872 AddLine(seg, inp->gr.left, (mpp->seq_bottom+seq_width), inp->gr.left, mpp->seq_bottom, FALSE, fnp->itemID);
1873 ivals = ivals->next;
1874 }
1875 }
1876 if(!rsite_flat)
1877 top = mpp->seq_bottom;
1878 ++i;
1879 FreeFeatureList(c_head);
1880 }
1881 }
1882 DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_bottom, scale, FALSE);
1883 mpp->bottom = mpp->seq_bottom - SCALE_SPACE;
1884 return TRUE;
1885 }
1886
1887 /***********************************************************************
1888 *
1889 * DrawCytoMap(features, mpp, scale, pic)
1890 * draw the cytogenetic map
1891 * features: the FeatNode for cytogenetic map
1892 * scale: maximum scale, used in layout
1893 * pic: the drawing segment
1894 *
1895 ***********************************************************************/
label_cyto_band(Int4 x1,Int4 x2,Int4Ptr prev,CharPtr label,Int4 scale)1896 static Boolean label_cyto_band(Int4 x1, Int4 x2, Int4Ptr prev, CharPtr label, Int4 scale)
1897 {
1898 Int4 center;
1899 Int4 half_len;
1900
1901 half_len = StringWidth(label)/2;
1902 center = (x1+x2)/(2 * scale);
1903 if((*prev == -1) || ((center - half_len) > (*prev)))
1904 {
1905 *prev = center + half_len;
1906 return TRUE;
1907 }
1908 else
1909 return FALSE;
1910 }
1911
DrawCytoMap(ValNodePtr PNTR features,MapPosPtr mpp,Int4 scale,SegmenT pic)1912 Boolean DrawCytoMap(ValNodePtr PNTR features, MapPosPtr mpp, Int4 scale, SegmenT pic)
1913 {
1914 Int4 x1, x2, center;
1915 SegmenT seg, pseg;
1916 Int4 top;
1917 Int4 prev_pos = -1;
1918 ValNodePtr g_node, curr;
1919 FeatNodePtr fnp;
1920 Boolean retval = FALSE;
1921 Uint1Ptr color = NULL;
1922 Uint1 shading = 0;
1923 CharPtr subdiv = NULL;
1924 Int2 numdiv =0;
1925 Int4 prev_right = -1;
1926 Int4 seq_width;
1927
1928
1929 top = mpp->seq_top;
1930 seq_width = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
1931
1932 pseg = CreateSegment(pic, OBJ_BIOSEQ_MAPFEAT, 0);
1933 seg = CreateSegment(pseg, mpp->entityID, 0);
1934
1935 g_node = extract_node_list(features, OBJ_BIOSEQ_MAPFEAT, 0, 0, ALL_LABEL);
1936 if(g_node)
1937 {
1938 for(curr = g_node; curr!=NULL; curr = curr->next)
1939 {
1940 fnp = curr->data.ptrvalue;
1941 switch(fnp->band)
1942 {
1943 case BND:
1944 color = BLACK_COLOR;
1945 break;
1946 case HET :
1947 color = BLUE_COLOR;
1948 break;
1949 case TEL:
1950 case CEN:
1951 color = RED_COLOR;
1952 shading = SOLID_SHADING;
1953 break;
1954 case BAND_POINT:
1955 color = RED_COLOR;
1956 shading = SOLID_SHADING;
1957 break;
1958 case GIEMSA_POS:
1959 color = BLACK_COLOR;
1960 shading = SOLID_SHADING;
1961 break;
1962 case GIEMSA_NEG:
1963 color = WHITE_COLOR;
1964 shading = SOLID_SHADING;
1965 break;
1966 case ACRO_CENTRIC:
1967 color = BLACK_COLOR;
1968 shading = THICK_NWSE_SHADING;
1969 break;
1970 case VARIABLE_REG:
1971 color = BLACK_COLOR;
1972 shading = THIN_NESW_SHADING;
1973 break;
1974
1975 case MISC_BND:
1976 color = BLACK_COLOR;
1977 shading = SOLID_SHADING;
1978 break;
1979
1980 default:
1981 Message(MSG_ERROR, "Illegal type");
1982 exit(1);
1983 }
1984
1985 if(fnp->band == BND || fnp->band == HET)
1986 {
1987 if(numdiv == 0)
1988 {
1989 ++numdiv;
1990 subdiv = fnp->pos_label;
1991 }
1992 else
1993 {
1994 if(StringCmp(subdiv, fnp->pos_label))
1995 {
1996 ++numdiv;
1997 subdiv = fnp->pos_label;
1998 }
1999 }
2000 if(numdiv%2 == 0)
2001 shading = THIN_NESW_SHADING;
2002 else
2003 shading = THIN_NWSE_SHADING;
2004 }
2005
2006 x1= fnp->extremes.left;
2007 x2= fnp->extremes.right;
2008 if(prev_right !=-1 && (x1 - prev_right) > scale)
2009 {
2010 AddAttribute (seg, SHADING_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2011 AddLine(seg, prev_right, top, x1, top, FALSE, 0);
2012 AddLine(seg, prev_right, top-seq_width, x1, top-seq_width, FALSE, 0);
2013 }
2014 prev_right = x2;
2015
2016 if(fnp->band == MISC_BND)
2017 {
2018 AddAttribute (seg, COLOR_ATT|SHADING_ATT, BLACK_COLOR, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2019 AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, FALSE, fnp->itemID);
2020 }
2021 else
2022 {
2023 AddAttribute (seg, SHADING_ATT | COLOR_ATT, color, NO_LINE_STYLE, shading, 1, COPY_MODE);
2024 AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, TRUE, fnp->itemID);
2025 if(fnp->band == GIEMSA_NEG)
2026 color = BLACK_COLOR;
2027 AddAttribute (seg, SHADING_ATT | COLOR_ATT, color, NO_LINE_STYLE, SOLID_SHADING, 1, COPY_MODE);
2028 AddRectangle(seg, x1, top, x2, top-seq_width, NO_ARROW, FALSE, fnp->itemID);
2029 }
2030 if(fnp->label)
2031 {
2032 if(label_cyto_band(x1, x2, &prev_pos, fnp->label, scale))
2033 {
2034 center = (x1+ x2)/2;
2035 AddLabel(seg, center, top-seq_width-5, fnp->label, SMALL_TEXT, 0, LOWER_CENTER, fnp->itemID);
2036 }
2037 }
2038 }
2039 mpp->seq_top = top;
2040 mpp->seq_bottom = top - seq_width;
2041
2042 top -= ( seq_width + LABEL_SPACE+5);
2043 mpp->bottom = top;
2044 FreeFeatureList(g_node);
2045 retval = TRUE;
2046 }
2047
2048 return retval;
2049 }
2050
2051
2052
draw_sequence_fnp(FeatNodePtr fnp,Boolean fill,Uint1 label_align,SegmenT seg,Uint1Ptr color,Int4 segstyle,Boolean show_border)2053 static void draw_sequence_fnp(FeatNodePtr fnp, Boolean fill, Uint1 label_align, SegmenT seg, Uint1Ptr color, Int4 segstyle, Boolean show_border)
2054 {
2055 Int2 arrow;
2056 FonT font;
2057 Int4 c_val;
2058 Uint1 label_color[3];
2059 Uint1 flags = COLOR_ATT|STYLE_ATT|SHADING_ATT|WIDTH_ATT;
2060 Uint1 linestyle, penwidth, shading;
2061
2062
2063 if(fnp->label != NULL)
2064 {
2065
2066 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
2067 SelectFont(font);
2068 fnp->labelHeight = FontHeight();
2069
2070 c_val = GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_COLOR);
2071 convert_color(c_val, label_color);
2072 AddAttribute (seg, COLOR_ATT, &label_color[0], 0, 0, 0, 0);
2073 AddFeatNodeLabel(seg, fnp, label_align, font);
2074 }
2075
2076 arrow = get_arrow_for_strand(fnp->extremes.strand);
2077
2078 if(color == NULL)
2079 {
2080 if(segstyle == MSM_SEG_BOX)
2081 add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEGMENT);
2082 else
2083 add_attribute_pen(seg, MSM_SEQUENCE, (Int2)segstyle);
2084 }
2085 else /*the one's that uses cycle color*/
2086 {
2087 linestyle = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_LTYPE);
2088 penwidth = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_PENWIDTH);
2089 shading = (Uint1)GetMuskCParam(MSM_SEQUENCE, (Int2)segstyle, MSM_SHADING);
2090 AddAttribute(seg, flags, color, linestyle, shading, penwidth, COPY_MODE);
2091 }
2092
2093 if(fill)
2094 {
2095
2096 if(segstyle == MSM_SEG_LINE)
2097 AddLine(seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->top, FALSE, fnp->itemID);
2098 else
2099 AddRectangle (seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->bottom, arrow, fill, fnp->itemID);
2100 }
2101
2102 if(show_border || !fill)
2103 {
2104 add_attribute_pen(seg, MSM_SEQUENCE, MSM_SEG_BORD);
2105 AddRectangle (seg, fnp->extremes.left, fnp->top, fnp->extremes.right, fnp->bottom, arrow, FALSE, fnp->itemID);
2106 }
2107
2108 }
2109
2110
2111 /*********************************************************************
2112 *
2113 * DrawSeqMap(features, mpp, pic, flat, scale, is_raw_seq)
2114 * Draw the real sequence map
2115 * features: FeatNode from which the Bioseqs can be extracted
2116 * mpp: the MapPos that contains the current map position
2117 * pic: the picture
2118 * flat: if TRUE, draw the map with features stacked on top
2119 * scale: maximum scale of the sequence
2120 * is_raw_seq: if TRUE, it is a raw DNA sequence. (This is
2121 * used to distinguish raw sequence from virtual sequence
2122 * if(show_segment and image_list), record the positions of the
2123 * segments
2124 *
2125 *********************************************************************/
DrawSeqMap(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic,Int4 scale,Boolean is_raw_seq,Boolean show_segment,ValNodePtr PNTR image_list)2126 Boolean DrawSeqMap(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic, Int4 scale, Boolean is_raw_seq, Boolean show_segment, ValNodePtr PNTR image_list)
2127 {
2128 ValNodePtr seg_node = NULL, g_node, c_node;
2129 ValNodePtr prev, next, gap_node = NULL;
2130 Int4 middle;
2131 FeatNodePtr fnp, c_fnp;
2132 SegmenT seg, pseg;
2133 Uint1Ptr color;
2134 Boolean fill;
2135 Int4 top;
2136 Int4 e_left, e_right;
2137 Uint2 entityID;
2138 Int2 arrow;
2139 Uint1 label_align;
2140 Uint1 seq_label_align;
2141 Int4 style, segstyle;
2142 Boolean show_border;
2143 Int2 obj_bioseq_seg_or_delta;
2144
2145
2146
2147 entityID = (Uint2)mpp->entityID;
2148 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2149
2150 c_node = extract_node_list(features, OBJ_BIOSEQ, entityID, 0, ALL_LABEL);
2151 c_node = sort_same_itemID(c_node);
2152 if(c_node == NULL)
2153 return FALSE;
2154 c_fnp = c_node->data.ptrvalue;
2155 c_fnp->line = 0;
2156
2157 style = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_STYLE);
2158 segstyle = (style & MSM_SEG_FORM);
2159 if(segstyle != MSM_SEG_BOX && segstyle != MSM_SEG_LINE)
2160 segstyle = MSM_SEG_BOX;
2161 if(segstyle ==MSM_SEG_BOX)
2162 show_border = (Boolean)GetMuskCParam(MSM_SEQUENCE, MSM_SEG_BORD, MSM_TRUEFALSE);
2163 else
2164 show_border = FALSE;
2165
2166 top = LayoutFeatNode(c_node, mpp->seq_top, scale, 0, TRUE, FALSE);
2167 obj_bioseq_seg_or_delta = OBJ_BIOSEQ_SEG;
2168 seg_node = extract_node_list(features, OBJ_BIOSEQ_SEG, entityID, 0, ALL_LABEL);
2169 if(seg_node == NULL) {
2170 obj_bioseq_seg_or_delta = OBJ_BIOSEQ_DELTA;
2171 seg_node = extract_node_list(features, OBJ_BIOSEQ_DELTA, entityID, 0, ALL_LABEL);
2172 }
2173 fill = (is_raw_seq && seg_node == NULL);
2174
2175 pseg = CreateSegment(pic, OBJ_BIOSEQ, 0);
2176 seg = CreateSegment(pseg, entityID, 0);
2177 if(label_align != MSM_LABEL_RIGHT)
2178 seq_label_align = MSM_LABEL_LEFT;
2179 else
2180 seq_label_align = MSM_LABEL_RIGHT;
2181
2182 draw_sequence_fnp(c_fnp, fill, seq_label_align, seg, NULL, segstyle, show_border);
2183 /* if(image_list != NULL)
2184 {
2185 vn.choice = OBJ_BIOSEQ;
2186 vn.data.ptrvalue = c_fnp;
2187 vn.next = NULL;
2188 load_align_label_rectangle(&vn, image_list, scale, FALSE);
2189 } */
2190 mpp->seq_top = c_fnp->top;
2191 mpp->seq_bottom = c_fnp->bottom;
2192
2193
2194 /*add the segments to the sequence picture. Also get rid of the
2195 FeatNode that only contains the gaps. if(fnp->follower = TRUE), it
2196 is a gap */
2197
2198 g_node = seg_node;
2199 prev = NULL;
2200 gap_node = NULL;
2201 while(g_node)
2202 {
2203 next = g_node->next;
2204 arrow = NO_ARROW;
2205 fnp = g_node->data.ptrvalue;
2206 e_left = fnp->extremes.left;
2207 e_right = fnp->extremes.right;
2208 if(fnp->follower) /*it is a gap between the segment*/
2209 {
2210 if(prev == NULL)
2211 seg_node = g_node->next;
2212 else
2213 prev->next = g_node->next;
2214 g_node->next = NULL;
2215 ValNodeLink(&gap_node, g_node);
2216 }
2217 else
2218 {
2219 if(e_left == c_fnp->extremes.left && c_fnp->extremes.strand == Seq_strand_minus)
2220 arrow = LEFT_ARROW;
2221 if(e_right == c_fnp->extremes.right && c_fnp->extremes.strand == Seq_strand_plus)
2222 arrow = RIGHT_ARROW;
2223 color = get_seg_color(fnp->itemID);
2224 AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, COPY_MODE);
2225 if(segstyle == MSM_SEG_BOX)
2226 AddRectangle (seg, e_left, c_fnp->top, e_right, c_fnp->bottom, arrow, TRUE, c_fnp->itemID);
2227 else
2228 AddLine(seg, e_left, c_fnp->top, e_right, c_fnp->top, FALSE, c_fnp->itemID);
2229 prev = g_node;
2230 }
2231 g_node = next;
2232 }
2233
2234
2235 if(gap_node != NULL)
2236 {
2237 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 2, NO_MODE);
2238 middle = (c_fnp->top + c_fnp->bottom)/2;
2239 for(g_node = gap_node; g_node != NULL; g_node = g_node->next)
2240 {
2241 fnp = g_node->data.ptrvalue;
2242 e_left = fnp->extremes.left;
2243 AddSymbol(seg, e_left, middle, DIAMOND_SYMBOL, FALSE, MIDDLE_CENTER, fnp->itemID);
2244 }
2245 FreeFeatureList(gap_node);
2246 }
2247
2248 DrawSeqScale(seg, mpp->slp, mpp->left, mpp->seq_bottom, scale, FALSE);
2249 top -= SCALE_SPACE; /*space for drawing the scale */
2250 if(seg_node !=NULL && show_segment)
2251 {
2252 top -= GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2253 pseg = CreateSegment(pic, obj_bioseq_seg_or_delta, 0);
2254 seg = CreateSegment(pseg, entityID, 0);
2255
2256 ReSetFeatNode(seg_node);
2257 top = LayoutFeatNode(seg_node, top, scale, 0, TRUE, FALSE);
2258
2259 for(g_node = seg_node; g_node !=NULL; g_node = g_node->next)
2260 {
2261 fnp = g_node->data.ptrvalue;
2262 e_left = fnp->extremes.left;
2263 e_right = fnp->extremes.right;
2264 color = get_seg_color(fnp->itemID);
2265 draw_sequence_fnp(fnp, TRUE, label_align, seg, color, segstyle, show_border);
2266 }
2267 if(image_list != NULL)
2268 load_align_label_rectangle(seg_node, image_list, scale, FALSE);
2269 }
2270
2271
2272 mpp->bottom = top;
2273
2274 FreeFeatureList(c_node);
2275 FreeFeatureList(seg_node);
2276 return TRUE;
2277 }
2278
2279
2280
DrawOneFeatNode(ValNodePtr g_node,Int4 top,SegmenT seg,Int4 scale,Int2 group_num,GeneDataPtr gdata,ValNodePtr PNTR image_rect)2281 static Int4 DrawOneFeatNode(ValNodePtr g_node, Int4 top, SegmenT seg, Int4 scale, Int2 group_num, GeneDataPtr gdata, ValNodePtr PNTR image_rect)
2282 {
2283 Boolean show_arrow;
2284 Boolean compress;
2285
2286
2287 if(g_node != NULL)
2288 {
2289
2290 show_arrow = (GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE) >= scale);
2291 compress = (GetMuskCParam(MSM_GROUPS, group_num, MSM_STYLE) == MSM_COMPRESS);
2292
2293 top -= GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2294
2295 top = LayoutFeatNode(g_node,top, scale, scale, TRUE, compress);
2296
2297 if(image_rect)
2298 load_align_label_rectangle(g_node, image_rect, scale, FALSE);
2299 DrawFeatNode (g_node, seg, UPPER_LABEL, show_arrow, scale, gdata);
2300 }
2301
2302 return top;
2303 }
2304
2305 /******************************************************************
2306 *
2307 * ck_ordered_group(): check if the internal order is important
2308 * to a group. Currently, only set up for the Gene-CDS-mRNA feature
2309 *
2310 *******************************************************************/
ck_ordered_group(Uint1 group_num,Uint1Ptr groupOrder)2311 static Boolean ck_ordered_group(Uint1 group_num, Uint1Ptr groupOrder)
2312 {
2313 Uint2 i;
2314
2315 if(groupOrder == NULL)
2316 return FALSE;
2317
2318 for(i =0; i<FEATDEF_ANY; ++i)
2319 {
2320 if(groupOrder[i] == group_num)
2321 {
2322 if(i == FEATDEF_GENE || i == FEATDEF_mRNA || i == FEATDEF_CDS)
2323 return TRUE;
2324 }
2325 }
2326 return FALSE;
2327 }
2328
2329
fnp_from_same_annot(FeatNodePtr fnp,CharPtr annot_db)2330 static Boolean fnp_from_same_annot(FeatNodePtr fnp, CharPtr annot_db)
2331 {
2332 if(annot_db[0] == '\0')
2333 return (fnp->annotDB[0] == '\0');
2334 else
2335 return (StringCmp(fnp->annotDB, annot_db) ==0);
2336 }
2337
group_feature_by_annot_label(ValNodePtr PNTR g_node,CharPtr annot_db)2338 static ValNodePtr group_feature_by_annot_label(ValNodePtr PNTR g_node, CharPtr annot_db)
2339 {
2340 ValNodePtr list = NULL;
2341 FeatNodePtr fnp;
2342 ValNodePtr curr, next, prev = NULL;
2343
2344 if(g_node == NULL || *g_node == NULL)
2345 return NULL;
2346
2347 curr = *g_node;
2348 fnp = curr->data.ptrvalue;
2349 if(fnp == NULL)
2350 return NULL;
2351 if(fnp->annotDB[0] == '\0')
2352 annot_db[0] = '\0';
2353 else
2354 StringCpy(annot_db, fnp->annotDB);
2355
2356 while(curr)
2357 {
2358 next = curr->next;
2359 fnp = curr->data.ptrvalue;
2360 if(fnp_from_same_annot(fnp, annot_db))
2361 {
2362 if(prev == NULL)
2363 *g_node = next;
2364 else
2365 prev->next = next;
2366 curr->next = NULL;
2367 ValNodeLink(&list, curr);
2368 }
2369 else
2370 prev = curr;
2371 curr = next;
2372 }
2373
2374 return list;
2375 }
2376
AddAnnotGroup(Int4 left,Int4 top,Int4 right,Int4 bottom,Int2 order,CharPtr annot_db,Uint4 itemID,SegmenT seg)2377 static void AddAnnotGroup(Int4 left, Int4 top, Int4 right, Int4 bottom, Int2 order, CharPtr annot_db, Uint4 itemID, SegmenT seg)
2378 {
2379 Uint1Ptr color;
2380 Int4 center;
2381
2382 color = get_seg_color(order);
2383 AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
2384
2385 /*need to draw the rectangle line by line. Otherwise, the segments
2386 will be incorrect*/
2387 AddLine(seg, left, top, right, top, FALSE, itemID);
2388 AddLine(seg, left, bottom, right, bottom, FALSE, itemID);
2389 AddLine(seg, left, top, left, bottom, FALSE, itemID);
2390 AddLine(seg, right, top, right, bottom, FALSE, itemID);
2391
2392 if(annot_db != NULL && annot_db[0] != '\0')
2393 {
2394 AddAttribute (seg, COLOR_ATT, BLACK_COLOR, 0, 0, 0, 0);
2395 center = (left + right)/2;
2396 AddTextLabel(seg, center, top, annot_db, programFont, 0, MIDDLE_CENTER, itemID);
2397 }
2398 }
2399
2400
2401
is_featnode_lod_score(ValNodePtr fnp_list)2402 static Boolean is_featnode_lod_score (ValNodePtr fnp_list)
2403 {
2404 FeatNodePtr fnp;
2405
2406 while(fnp_list)
2407 {
2408 if(fnp_list->choice == OBJ_SEQFEAT || fnp_list->choice == OBJ_BIOSEQ_MAPFEAT)
2409 {
2410 fnp = fnp_list->data.ptrvalue;
2411 if(fnp != NULL)
2412 {
2413 if((fnp->extra_data) & EXTRA_LOD_SCORE)
2414 return TRUE;
2415 else
2416 return FALSE;
2417 }
2418 }
2419
2420 fnp_list = fnp_list->next;
2421 }
2422
2423 return FALSE;
2424 }
2425
2426
GetLodScoreBitColor(Uint1 bit_val)2427 static Uint1Ptr GetLodScoreBitColor(Uint1 bit_val)
2428 {
2429 switch(bit_val)
2430 {
2431 case 1:
2432 return BLUE_COLOR;
2433 case 2:
2434 return CYAN_COLOR;
2435 case 3:
2436 return GREEN_COLOR;
2437 case 4:
2438 return YELLOW_COLOR;
2439 case 5:
2440 return MAGENTA_COLOR;
2441 case 6:
2442 return RED_COLOR;
2443 default:
2444 return BLACK_COLOR;
2445 }
2446 }
2447
DrawLODScore(ValNodePtr t_node,SegmenT seg,Int4 scale,Int4 top)2448 static Int4 DrawLODScore(ValNodePtr t_node, SegmenT seg, Int4 scale, Int4 top)
2449 {
2450 Int4 height;
2451 FeatNodePtr fnp;
2452 Uint1Ptr color;
2453 Int4 space;
2454
2455 height = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
2456 space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
2457 top -= space;
2458
2459 while(t_node)
2460 {
2461 fnp = t_node->data.ptrvalue;
2462 if(fnp != NULL)
2463 {
2464 color = GetLodScoreBitColor((Uint1)(fnp->bin_order));
2465 AddAttribute (seg, COLOR_ATT, color, 0, 0, 0, 0);
2466 AddRectangle (seg, fnp->extremes.left, top,
2467 fnp->extremes.right, top-height, FALSE, TRUE, 0);
2468 }
2469
2470 t_node = t_node->next;
2471 }
2472
2473 return (top - space - height);
2474 }
2475
2476
DrawFeatureWithAnnot(ValNodePtr PNTR t_head,Int4 top,Int4 scale,Boolean flat,Int4 group_num,Boolean order_group,Int4 left,Int4 right,GeneDataPtr gdata,SegmenT seg,ValNodePtr PNTR image_list)2477 static Int4 DrawFeatureWithAnnot(ValNodePtr PNTR t_head, Int4 top, Int4 scale, Boolean flat, Int4 group_num, Boolean order_group, Int4 left, Int4 right, GeneDataPtr gdata, SegmenT seg, ValNodePtr PNTR image_list)
2478 {
2479 Char annot_db[100];
2480 Int4 g_top = 0, g_bottom;
2481 Int4 group_font_height;
2482 Boolean draw_annot_group;
2483 Int2 annot_order;
2484 ValNodePtr t_node;
2485
2486 SelectFont(programFont);
2487 group_font_height = FontHeight();
2488
2489 annot_order = 0;
2490 while((t_node = group_feature_by_annot_label(t_head, annot_db)) != NULL)
2491 {
2492 if(*t_head == NULL && annot_order == 0 && annot_db[0] == '\0')
2493 draw_annot_group = FALSE;
2494 else
2495 draw_annot_group = TRUE;
2496 if(draw_annot_group )
2497 {
2498 if(annot_db[0] == '\0')
2499 g_top = top;
2500 else
2501 {
2502 top -= group_font_height;
2503 g_top = top + group_font_height/2;
2504 }
2505 }
2506 if(is_featnode_lod_score (t_node))
2507 top = DrawLODScore(t_node, seg, scale, top);
2508 else
2509 {
2510 if(flat)
2511 {
2512 top = LayoutNodeFlat(&t_node, scale, top, UPPER_LABEL, TRUE);
2513 if(image_list != NULL)
2514 load_align_label_rectangle(t_node, image_list, scale, TRUE);
2515 DrawFlatNode(t_node, seg, UPPER_LABEL, scale, gdata);
2516 }
2517 else
2518 {
2519 if(order_group)
2520 /* GroupFeatNode(&t_node); */
2521 t_node = OrderCdsmRNA(&t_node);
2522 else
2523 t_node= SortFeatNode(t_node, NULL, NULL);
2524 top = DrawOneFeatNode(t_node, top, seg, scale, (Int2)group_num, gdata, image_list);
2525 }
2526 }
2527 t_node= FreeFeatureList(t_node);
2528 g_bottom = top;
2529
2530 if(draw_annot_group)
2531 {
2532 g_bottom -= group_font_height/2;
2533 AddAnnotGroup(left, g_top, right, g_bottom, annot_order, annot_db, 0, seg);
2534 top = g_bottom;
2535 }
2536 ++annot_order;
2537 }
2538
2539 return top;
2540 }
2541
2542 /***********************************************************************
2543 *
2544 * DrawFeatures(features, mpp, pic, flat, simple, compact,
2545 * scale)
2546 *
2547 * Draw the features in the a sequence
2548 * features: the FeatNdoe contains the features
2549 * mpp: the graphic position of the current sequence
2550 * pic: the drawing segment
2551 * flat: if TRUE, stack features on top
2552 * simple: if TRUE, draw the feature intervals as line
2553 * compact: if TRUE, does not distinguish subtype of different features
2554 * scale: the maximum scale for drawing
2555 * image_list: the list of AlignRect to store the image information
2556 *
2557 *********************************************************************/
DrawFeatures(ValNodePtr g_node,MapPosPtr mpp,SegmenT pic,Boolean flat,Uint1Ptr featureOrder,Uint1Ptr groupOrder,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR image_list)2558 Boolean DrawFeatures(ValNodePtr g_node, MapPosPtr mpp, SegmenT pic, Boolean flat, Uint1Ptr featureOrder, Uint1Ptr groupOrder, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR image_list)
2559 {
2560 ValNodePtr t_node, t_head;
2561 Int4 top;
2562 Int4 left, right;
2563 Int2 entityID;
2564 SegmenT seg;
2565 Uint1 i, j, k, maxGroup;
2566 Boolean is_end = FALSE;
2567 Boolean order_group; /*need to show the order of the group*/
2568
2569 if(g_node == NULL)
2570 return FALSE;
2571 left = mpp->left;
2572 right = mpp->right;
2573 top = mpp->bottom;
2574 entityID = mpp->entityID;
2575 seg = CreateSegment(pic, OBJ_SEQFEAT, 0);
2576
2577 if(flat) /*show the features first*/
2578 {
2579 mpp->bottom = DrawFeatureWithAnnot(&g_node, top, scale, TRUE, 0, FALSE, left, right, gdata, seg, image_list);
2580 }
2581 else
2582 {
2583 maxGroup= 0;
2584 for(k = 0; k<FEATDEF_ANY; ++k)
2585 maxGroup = MAX(maxGroup, groupOrder[k]);
2586
2587 is_end = FALSE;
2588 order_group = FALSE;
2589
2590 for(k =1; k<=maxGroup && !is_end; ++k)
2591 {
2592 order_group = ck_ordered_group(k, groupOrder);
2593 t_head = NULL;
2594 for(i =1; i<FEATDEF_ANY && !is_end; ++i) /*this is the order of features*/
2595 {
2596 for(j = 1; j<FEATDEF_ANY && !is_end; ++j)
2597 {
2598 if(groupOrder[j] == k && featureOrder[j] == i)
2599 {
2600 t_node = extract_node_list(&g_node, OBJ_SEQFEAT, 0, j, ALL_LABEL);
2601 if(t_node != NULL)
2602 {
2603 ValNodeLink(&t_head, t_node);
2604 is_end = (g_node == NULL);
2605 }
2606 }
2607 }
2608 }
2609
2610 top = DrawFeatureWithAnnot(&t_head, top, scale, FALSE, k,order_group, left, right, gdata, seg, image_list);
2611 }
2612 mpp->bottom = top;
2613 if(g_node != NULL)
2614 FreeFeatureList(g_node);
2615 }
2616
2617 return TRUE;
2618 }
2619
2620
2621
DrawHistory(ValNodePtr aligns,MapPosPtr mpp,Int4 seq_label_len,SegmenT pic,Int4 scale,ValNodePtr PNTR image_list)2622 Boolean DrawHistory(ValNodePtr aligns, MapPosPtr mpp, Int4 seq_label_len, SegmenT pic, Int4 scale, ValNodePtr PNTR image_list)
2623 {
2624
2625 Boolean retval;
2626 Uint1 label_align;
2627 Int4 left, right;
2628 Int4 offset;
2629
2630 if(aligns)
2631 {
2632 (mpp->bottom) -= 20;
2633
2634 offset = scale * (MAX(seq_label_len, 8));
2635 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2636
2637 left = mpp->left;
2638 right = mpp->right;
2639 switch(label_align)
2640 {
2641 case MSM_LABEL_RIGHT:
2642 left -= (8 * scale);
2643 right += offset;
2644 break;
2645
2646 case MSM_LABEL_TOP:
2647 case MSM_LABEL_BOTTOM:
2648 left -= (8*8*scale);
2649 right += (8*8*scale);
2650 break;
2651
2652 case MSM_LABEL_LEFT:
2653 left -=offset;
2654 right += (8 * scale); /*8 is the size of a symbol*/
2655 break;
2656
2657 default:
2658 break;
2659 }
2660 retval = DrawMPAlignment(aligns, left, right, NULL, mpp->entityID, scale, &(mpp->bottom), MSM_SEQHIST, FALSE, pic);
2661 if(image_list != NULL)
2662 load_align_label_rectangle (aligns, image_list, scale, FALSE);
2663 FreeAlignNode(aligns);
2664 return retval;
2665 }
2666 else
2667 return FALSE;
2668 }
2669
2670
get_next_ypos(MapLayoutPtr mlp,Int4Ptr top)2671 static MapLayoutPtr get_next_ypos(MapLayoutPtr mlp, Int4Ptr top)
2672 {
2673 MapPosPtr mpp;
2674
2675 if(mlp == NULL)
2676 {
2677 *top = -20;
2678 return NULL;
2679 }
2680 else
2681 {
2682 while(mlp->next != NULL)
2683 mlp = mlp->next;
2684 mpp = mlp->data.ptrvalue;
2685 *top = mpp->bottom -MAX(10, GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT));
2686 return mlp;
2687 }
2688 }
2689
2690
2691
set_seq_collect_option(CollectSeqOptionPtr csop,Int4 scale)2692 static Boolean set_seq_collect_option(CollectSeqOptionPtr csop, Int4 scale)
2693 {
2694 Int4 topstyle;
2695 Int4 ends;
2696 Int2 i;
2697
2698 if(csop == NULL || scale <= 0)
2699 return FALSE;
2700
2701 topstyle = GetMuskCParam(MSM_TOPSTYLE, 0, MSM_STYLE);
2702
2703 /*collect the features, maps, and features*/
2704 csop->seglevels = (topstyle & MSM_SEGMENTS) ? 1:0;
2705 ends = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
2706 csop->nointerval = (ends < scale);
2707 csop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
2708 for(i =0; i<FEATDEF_ANY; ++i)
2709 csop->flabel_format[i] = (Uint1)GetMuskCParam(i, MSM_FLABEL, MSM_STYLE);
2710 csop->label_size = (Int2)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_NUM);
2711 csop->filter_level = 0;
2712
2713 for( i =0; i<FEATDEF_ANY; ++i) /*for checking the features to load*/
2714 csop->features[i] = (GetMuskCParam(i, MSM_FORDER, MSM_NUM) !=0);
2715
2716 return TRUE;
2717 }
2718
2719
2720 /*add the label to draw the sequence*/
add_seq_label_for_map(ValNodePtr PNTR features,MapPosPtr mpp,SegmenT pic)2721 static Int4 add_seq_label_for_map(ValNodePtr PNTR features, MapPosPtr mpp, SegmenT pic)
2722 {
2723 ValNodePtr c_node;
2724 FeatNodePtr fnp;
2725 FonT font;
2726 Int4 c_val;
2727 Uint1 label_color[3];
2728 SegmenT seg, pseg;
2729 Uint1 label_align;
2730 Int4 label_len;
2731
2732 label_len = 0;
2733 c_node = extract_node_list(features, OBJ_BIOSEQ, mpp->entityID, 0, ALL_LABEL);
2734 if(c_node == NULL)
2735 return 0;
2736 fnp = c_node->data.ptrvalue;
2737
2738 if(fnp->label != NULL)
2739 {
2740
2741 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
2742 SelectFont(font);
2743
2744 label_len = StringWidth(fnp->label);
2745 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
2746 if(label_align != MSM_LABEL_RIGHT)
2747 label_align = MSM_LABEL_LEFT;
2748 c_val = GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_COLOR);
2749 convert_color(c_val, label_color);
2750 pseg = CreateSegment(pic, OBJ_BIOSEQ, 0);
2751 seg = CreateSegment(pseg, mpp->entityID, 0);
2752 AddAttribute (seg, COLOR_ATT, &label_color[0], 0, 0, 0, 0);
2753
2754 AddLabelWithAlign(seg, label_align, mpp->left, mpp->left, mpp->seq_top, mpp->seq_bottom, fnp->label, font, fnp->itemID);
2755 }
2756 FreeFeatureList(c_node);
2757 return label_len;
2758 }
2759
2760
set_lolli_pop_feature(Uint1Ptr l_feature)2761 static void set_lolli_pop_feature(Uint1Ptr l_feature)
2762 {
2763 Int2 i;
2764 Int4 segstyle;
2765
2766 for(i =0; i<FEATDEF_ANY; ++i)
2767 {
2768 segstyle = GetMuskCParam(i, MSM_SEGMENT, MSM_STYLE);
2769 switch (segstyle & MSM_SEG_FORM)
2770 {
2771 case MSM_SEG_SYM_RECT:
2772 case MSM_SEG_SYM_DIAMOND:
2773 case MSM_SEG_SYM_OVAL:
2774 case MSM_SEG_SYM_TRIANGLE:
2775 l_feature[i] = TRUE;
2776 break;
2777 default:
2778 l_feature[i]= FALSE;
2779 }
2780 }
2781 }
2782
load_feature_class(ValNodePtr PNTR type_list,Int2 _class)2783 static void load_feature_class(ValNodePtr PNTR type_list, Int2 _class)
2784 {
2785 ValNodePtr curr;
2786
2787 for(curr = *type_list; curr != NULL; curr = curr->next)
2788 {
2789 if(curr->data.intvalue == (Int4)_class)
2790 return;
2791 }
2792 ValNodeAddInt(type_list, 0, (Int4)_class);
2793 }
2794
2795 /*******************************************************************
2796 *
2797 * from the list of FeatNode, load the feature types contained
2798 * for this seq-loc. It will be used to draw the legend
2799 *
2800 *******************************************************************/
load_feature_type(ValNodePtr fnp_list,ValNodePtr PNTR type_list)2801 static void load_feature_type (ValNodePtr fnp_list, ValNodePtr PNTR type_list)
2802 {
2803 FeatNodePtr fnp;
2804 Int2 _class;
2805
2806 if(type_list == NULL)
2807 return;
2808 while(fnp_list)
2809 {
2810 if(fnp_list->choice == OBJ_SEQFEAT)
2811 {
2812 fnp = fnp_list->data.ptrvalue;
2813 if(fnp != NULL)
2814 {
2815 _class = get_current_class(fnp);
2816 load_feature_class(type_list, _class);
2817 }
2818 }
2819
2820 fnp_list = fnp_list->next;
2821 }
2822 }
2823
2824
2825
2826 /*********************************************************************
2827 *
2828 * from the list of AlignNode, extract all the alignments
2829 * that were considered as the bins of the FISH maps
2830 * since the alignment of the FISH map is displayed at the
2831 * top, those were extracted at the first
2832 *
2833 *********************************************************************/
extract_fish_align(ValNodePtr PNTR anp_list)2834 static ValNodePtr extract_fish_align(ValNodePtr PNTR anp_list)
2835 {
2836 ValNodePtr curr, prev, next;
2837 ValNodePtr fish_list;
2838 AnnotInfoPtr info;
2839 AlignNodePtr anp;
2840 Boolean is_fish;
2841
2842 if(*anp_list == NULL)
2843 return NULL;
2844 fish_list = NULL;
2845 prev = NULL;
2846 curr = *anp_list;
2847
2848 is_fish = FALSE;
2849 while(curr)
2850 {
2851 next = curr->next;
2852 if(curr->choice == OBJ_SEQANNOT)
2853 {
2854 info = (AnnotInfoPtr)(curr->data.ptrvalue);
2855 is_fish = info->is_fish_align;
2856 }
2857 else
2858 {
2859 anp = curr->data.ptrvalue;
2860 if(is_fish)
2861 anp->label = MemFree(anp->label);
2862 }
2863 if(is_fish)
2864 {
2865 if(prev == NULL)
2866 *anp_list = next;
2867 else
2868 prev->next = next;
2869 curr->next = NULL;
2870 if(curr->choice == OBJ_SEQANNOT)
2871 FreeAlignNode(curr);
2872 else
2873 ValNodeLink(&fish_list, curr);
2874 }
2875 else
2876 prev = curr;
2877 curr = next;
2878 }
2879
2880 return fish_list;
2881 }
2882
2883
add_fish_align(Int4 top,Uint2 entityID,ValNodePtr fish_align,Int4 scale,SegmenT pic)2884 static Int4 add_fish_align (Int4 top, Uint2 entityID, ValNodePtr fish_align,
2885 Int4 scale, SegmenT pic)
2886 {
2887 Int4 bottom;
2888 SegmenT pseg, seg;
2889 AlignNodePtr anp;
2890 Int4 middle;
2891 ValNodePtr curr;
2892 Int4 space = 4;
2893 Int4Ptr y_pos;
2894 Int2 num;
2895 Int4 line;
2896
2897 num = get_vnp_num(fish_align);
2898 y_pos = MemNew((size_t)(2*num) * sizeof(Int4));
2899 for(curr = fish_align; curr != NULL; curr = curr->next)
2900 {
2901 anp = curr->data.ptrvalue;
2902 if(anp->extremes.right - anp->extremes.left >= 5* scale)
2903 anp->line = find_f_pos(anp->extremes.left,
2904 anp->extremes.right, y_pos, scale, num);
2905 }
2906 MemFree(y_pos);
2907
2908 /* 1 is the pen-width */
2909 pseg = CreateSegment(pic, OBJ_SEQALIGN, 0);
2910 seg = CreateSegment(pseg, entityID, 0);
2911
2912 AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
2913 top -= 8;
2914 bottom = top;
2915 while(fish_align)
2916 {
2917 anp = fish_align->data.ptrvalue;
2918 if(anp->extremes.right - anp->extremes.left >= 5* scale)
2919 {
2920 line = top - space * (anp->line +1);
2921 bottom = MIN(bottom, line);
2922 AddLine(seg, anp->extremes.left, line, anp->extremes.right,
2923 line, FALSE, anp->itemID);
2924 middle = (anp->extremes.left + anp->extremes.right)/2;
2925 AddLine(seg, middle, line, middle, top, FALSE, anp->itemID);
2926 AddSymbol(seg, middle, top, UP_TRIANGLE_SYMBOL, TRUE, UPPER_CENTER, anp->itemID);
2927 }
2928 fish_align = fish_align->next;
2929 }
2930
2931 return bottom-4;
2932 }
2933
extract_sts_search_node(ValNodePtr PNTR features,ValNodePtr PNTR g_node)2934 static void extract_sts_search_node(ValNodePtr PNTR features, ValNodePtr PNTR g_node)
2935 {
2936 ValNodePtr curr, prev, next;
2937 FeatNodePtr fnp;
2938 ValNodePtr g_prev;
2939 Boolean found;
2940
2941 if(features == NULL || *features == NULL)
2942 return;
2943 g_prev = NULL;
2944 if(*g_node != NULL)
2945 {
2946 g_prev = *g_node;
2947 while(g_prev->next != NULL)
2948 g_prev = g_prev->next;
2949 }
2950
2951 curr = *features;
2952 prev = NULL;
2953 while(curr)
2954 {
2955 next = curr->next;
2956 fnp = curr->data.ptrvalue;
2957 found = FALSE;
2958 if(fnp->annotDB[0] != '\0')
2959 {
2960 if(StringCmp(fnp->annotDB, "STS Search") == 0)
2961 {
2962 curr->next = NULL;
2963 if(g_prev == NULL)
2964 *g_node = curr;
2965 else
2966 g_prev->next = curr;
2967 g_prev = curr;
2968
2969 if(prev == NULL)
2970 *features = next;
2971 else
2972 prev->next = next;
2973 found = TRUE;
2974 }
2975 }
2976 if(!found)
2977 prev = curr;
2978 curr = next;
2979 }
2980 }
2981
2982
2983 /**********************************************************************
2984 *
2985 * DrawOneSeqLoc(slp, left, scale, pic, mlp, gdata, priority)
2986 * draw the current Seq-loc picture
2987 *
2988 * slp: the location on a Sequence, can be a list of Seq-loc for a
2989 * circular molecule
2990 * left: the leftmost position on the graph
2991 * scale: the scale for the current picture
2992 * pic: the current picture
2993 * mlp: to obtain the layout information
2994 * gdata: the selected gene symbols for display
2995 * priority: the priority of search for the current sequence
2996 * ftype_list: return a list of type of features for the current
2997 * Seq-loc. This is going to be used for drawing the legend
2998 * image_list: the list to store the image mapping information
2999 * align_num: the top number of alignment for display
3000 *
3001 ***********************************************************************/
DrawOneSeqLoc(SeqLocPtr slp,Int4 left,Int4 scale,SegmenT pic,MapLayoutPtr PNTR mlp,GeneDataPtr gdata,Uint2 priority,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3002 static Boolean DrawOneSeqLoc(SeqLocPtr slp, Int4 left, Int4 scale, SegmenT pic, MapLayoutPtr PNTR mlp,
3003 GeneDataPtr gdata, Uint2 priority, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list,
3004 Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3005 {
3006 ValNodePtr aligns = NULL, features = NULL;
3007 ValNodePtr g_node;
3008 Uint2 entityID;
3009 Boolean ends;
3010 CollectSeqOption cs_option;
3011 CollectAlignOption ca_option;
3012 SeqIdPtr sip;
3013 BioseqPtr bsp;
3014 Uint1 bsptype;
3015 Char buf[41];
3016 Int2 i;
3017 MapPosPtr mpp;
3018 Int4 top;
3019 Int4 topstyle;
3020 Boolean show_seq_label = TRUE; /*show the label of a sequence*/
3021 Boolean is_raw_seq; /*is it a raw sequence*/
3022 Boolean show_segment = TRUE; /*draw each segments in a segmented sequence?*/
3023 Boolean is_aa;
3024 SeqIdPtr maybe_mapid; /*a possible map-id*/
3025 Boolean is_map;
3026
3027 Uint1 featureOrder[FEATDEF_ANY];
3028 Uint1 groupOrder[FEATDEF_ANY];
3029 Boolean lolli_feature[FEATDEF_ANY]; /*identify the lollipop features*/
3030 Int4 groupNum;
3031 Int4 top_ends;
3032 Int4 seq_label_len;
3033 SeqIntPtr sint;
3034 Boolean has_align;
3035 ValNodePtr fish_align;
3036 Int4 fish_top;
3037 ValNodePtr cyto_node;
3038 ValNodePtr vnp1, vnp2;
3039 DeltaSeqPtr dsp;
3040 SeqLocPtr loc;
3041
3042
3043 if(slp == NULL || pic == NULL || scale <=0)
3044 return FALSE;
3045
3046 /*set up the option for collecting sequences and features*/
3047 if(!set_seq_collect_option(&cs_option, scale))
3048 return FALSE;
3049 ends = cs_option.nointerval; /*only show the two-ends of a feature*/
3050
3051 /*fetch the current Bioseq*/
3052 sip = SeqLocId(slp);
3053 bsp = BioseqLockById(sip);
3054 if(bsp == NULL)
3055 {
3056 SeqIdWrite(sip, buf, PRINTID_TEXTID_ACCESSION, 40);
3057 Message(MSG_ERROR, "fail to get the sequence %s", buf);
3058 return FALSE;
3059 }
3060 /* adjust the interval */
3061 if(slp->choice == SEQLOC_INT)
3062 {
3063 sint = slp->data.ptrvalue;
3064 if(sint->from < 0)
3065 sint->from = 0;
3066 if(sint->to <0 || sint->to > bsp->length-1)
3067 sint->to = bsp->length-1;
3068 }
3069 entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
3070 if(entityID == 0)
3071 {
3072 BioseqUnlock(bsp);
3073 Message(MSG_ERROR, "Fail to find the entityID");
3074 return FALSE;
3075 }
3076 if(bsp->repr == Seq_repr_seg)
3077 maybe_mapid = figure_map_seqid((SeqLocPtr)(bsp->seq_ext));
3078 else if (bsp->repr == Seq_repr_delta && bsp->seq_ext_type == 4)
3079 {
3080 dsp = (DeltaSeqPtr) bsp->seq_ext;
3081 loc = DeltaSeqsToSeqLocs (dsp);
3082 maybe_mapid = figure_map_seqid(loc);
3083 SeqLocFree (loc);
3084 }
3085 else
3086 maybe_mapid = NULL;
3087
3088 if(bsp->repr == Seq_repr_seg || bsp->repr == Seq_repr_delta)
3089 {
3090 /* cs_option.seglevels = 0; */
3091 /* cs_option.seglevels = 1; */
3092 if (forceSeglevelsTo1) {
3093 cs_option.seglevels = 1;
3094 } else
3095 if(BioseqHasFeature(bsp))
3096 {
3097 if(maybe_mapid !=NULL)
3098 cs_option.seglevels = 0;
3099 if(!BioseqHasLandMark(bsp))
3100 cs_option.seglevels = 0;
3101 if(cs_option.seglevels == 1)
3102 cs_option.filter_level = 1;
3103 }
3104 else
3105 cs_option.seglevels = 1;
3106 }
3107 else
3108 cs_option.seglevels = 0;
3109
3110
3111
3112 /*collecting the features + sequence segments*/
3113 bsptype = get_Bioseq_type(bsp);
3114 cs_option.bsp_type = bsptype;
3115 is_aa = (bsp->mol == Seq_mol_aa);
3116 features = CollectItemForSeqLocEx(slp, entityID, left, is_aa, maybe_mapid, &cs_option, gdata, priority, forceSeglevelsTo1);
3117 for (vnp1 = extraEntityList; vnp1 != NULL; vnp1 = vnp1->next) {
3118 if ((Uint2) (vnp1->data.intvalue) != entityID) {
3119 vnp2 = CollectItemForSeqLocEx(slp, (Uint2) (vnp1->data.intvalue), left, is_aa, maybe_mapid, &cs_option, gdata, priority, forceSeglevelsTo1);
3120 ValNodeLink (&features, vnp2);
3121 }
3122 }
3123 if(features == NULL)
3124 {
3125 return FALSE;
3126 }
3127 /*load the type of the features to draw the legend for the features*/
3128 load_feature_type (features, ftype_list);
3129
3130 /*collecting the history*/
3131 topstyle = GetMuskCParam(MSM_TOPSTYLE, 0, MSM_STYLE);
3132 has_align = FALSE;
3133 if(topstyle & MSM_HISTORY)
3134 {
3135 set_option_for_collect_align(&ca_option, cs_option.label_size, COLLECT_HISTORY);
3136 ca_option.only_history = FALSE;
3137 ca_option.map_insert = TRUE;
3138 ca_option.slabel_format = cs_option.slabel_format;
3139 ca_option.nointerval = cs_option.nointerval;
3140 ca_option.no_sort = FALSE;
3141 ca_option.flat_insert = FALSE;
3142 aligns = collect_anpnode_with_option(&ca_option, slp, entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3143 for (vnp1 = extraEntityList; vnp1 != NULL; vnp1 = vnp1->next) {
3144 if ((Uint2) (vnp1->data.intvalue) != entityID) {
3145 vnp2 = collect_anpnode_with_option(&ca_option, slp, (Uint2) (vnp1->data.intvalue), COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3146 ValNodeLink (&aligns, vnp2);
3147 }
3148 }
3149 has_align = alignode_has_alignments(aligns);
3150 if(has_align)
3151 {
3152 show_segment = FALSE;
3153 /*for the alignment of STSs in SegMap*/
3154 CollectSegMapSTSAlign(entityID, aligns, slp, left);
3155 }
3156 }
3157 else
3158 show_segment = FALSE;
3159
3160
3161
3162 /*set the layout for the current Seq-loc*/
3163 get_next_ypos(*mlp, &top);
3164 mpp = MemNew(sizeof(MapPos));
3165 mpp->slp = slp;
3166 mpp->left = left;
3167 mpp->right = left + slp_list_len(slp);
3168 mpp->top = top;
3169 mpp->bottom = top;
3170 mpp->seq_top = top;
3171 mpp->seq_bottom = top;
3172 mpp->entityID = entityID;
3173
3174
3175 /*display the alignment to the FISH map first */
3176 fish_top = 99999;
3177 if(get_FISH_align(bsp) != NULL && has_align)
3178 {
3179 fish_align = extract_fish_align(&aligns);
3180 if(fish_align != NULL)
3181 {
3182 fish_top = top;
3183 mpp->top = add_fish_align (top, entityID, fish_align, scale, pic);
3184 mpp->bottom = mpp->top;
3185 mpp->seq_top = mpp->top;
3186 mpp->seq_bottom = mpp->top;
3187 mpp->bottom = mpp->top;
3188 FreeAlignNode(fish_align);
3189 }
3190 }
3191
3192 /*map the feature order and group order*/
3193 for( i =0; i<FEATDEF_ANY; ++i) /*for checking the features to load*/
3194 {
3195 featureOrder[i] = (Uint1)GetMuskCParam(i, MSM_FORDER, MSM_NUM);
3196 groupNum = (Uint1)GetMuskCParam(i, MSM_FGROUP, MSM_NUM);
3197 groupOrder[i] = (Uint1)GetMuskCParam(MSM_GROUPS, (Int2)groupNum, MSM_NUM);
3198 }
3199
3200
3201
3202 g_node = NULL;
3203 if(topstyle & MSM_STACKGENE) /*draw the features on top of the sequence*/
3204 g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3205 else
3206 {
3207
3208 if((bsptype==SEG_SEQ && maybe_mapid == NULL)|| bsptype == RAW_SEQ)
3209 {
3210 set_lolli_pop_feature(lolli_feature);
3211 g_node = extract_lollipop_feature(&features, 0, lolli_feature);
3212 }
3213
3214 else
3215 {
3216 top_ends = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
3217 if(scale > top_ends)
3218 g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3219 else
3220 g_node = extract_lollipop_feature(&features, scale*10, NULL);
3221
3222 /*g_node = extract_lollipop_feature(&features, scale, NULL);*/
3223 }
3224 }
3225
3226 extract_sts_search_node(&features, &g_node);
3227 if(g_node)
3228 if(DrawFeatures(g_node, mpp, pic, TRUE, featureOrder, groupOrder, scale, gdata, image_list))
3229 show_seq_label = FALSE;
3230 mpp->seq_top = mpp->bottom;
3231 mpp->seq_bottom = mpp->bottom;
3232 is_map = TRUE; /*map does not extract bioseqs*/
3233 switch(bsptype)
3234 {
3235 case GENETIC_MAP:
3236 DrawGeneticMap(&features, mpp, pic, scale, gdata, image_list);
3237 break;
3238
3239 case PHYSICAL_MAP:
3240 DrawPhysicalMap(&features, mpp, pic, scale, image_list);
3241 break;
3242
3243 case RESTRICTION_MAP:
3244 DrawRestrictionMap(&features, mpp, pic, FALSE, SeqLocStrand(slp), scale);
3245 break;
3246
3247 case CYTO_MAP:
3248 DrawCytoMap(&features, mpp, scale, pic);
3249 break;
3250
3251 default:
3252 is_raw_seq = (bsptype == RAW_SEQ);
3253 is_map = FALSE;
3254 DrawSeqMap(&features, mpp, pic, scale, is_raw_seq, show_segment, image_list);
3255 break;
3256 }
3257
3258 if(is_map && bsptype != RESTRICTION_MAP) /*need to extract from the Bioseq*/
3259 seq_label_len = add_seq_label_for_map(&features, mpp, pic);
3260 else
3261 seq_label_len = 0;
3262
3263 /*add the label of the sequence*/
3264
3265
3266 DrawHistory(aligns, mpp, seq_label_len, pic, scale, image_list);
3267
3268 if(bsptype == CYTO_MAP && gdata != NULL)
3269 {
3270 cyto_node = convert_gdata_to_featnode(gdata, mpp->slp, mpp->left);
3271 if(cyto_node != NULL)
3272 ValNodeLink(&features, cyto_node);
3273 }
3274
3275
3276 g_node = extract_node_list(&features, OBJ_SEQFEAT, 0, 0, ALL_LABEL);
3277 DrawFeatures(g_node, mpp, pic, FALSE, featureOrder, groupOrder, scale, gdata, image_list);
3278 FreeFeatureList(features);
3279
3280
3281 if(fish_top != 99999)
3282 { /*there is a FISH mapping data */
3283 mpp->seq_bottom = fish_top - (mpp->seq_top - mpp->seq_bottom);
3284 mpp->seq_top = fish_top;
3285 }
3286 ValNodeAddPointer(mlp, 0, mpp);
3287 BioseqUnlock(bsp);
3288 return TRUE;
3289
3290 }
3291
3292
3293 /*
3294 * MakeCompressAlignList: Build the AlignNode for a compact alignment
3295 * view associated
3296 * with a sequence
3297 * query_bsp is the query sequence
3298 * annot: the alignment data. If NULL, the alignment data will be extracted
3299 * from sequence
3300 * return the list of AlignNode
3301 */
MakeCompressAlignList(BioseqPtr query_bsp,SeqAnnotPtr annot,Uint2Ptr p_entityID)3302 ValNodePtr MakeCompressAlignList(BioseqPtr query_bsp, SeqAnnotPtr annot, Uint2Ptr p_entityID)
3303 {
3304 SeqAnnotPtr sap;
3305 SeqLocPtr slp;
3306 CollectAlignOption ca_option;
3307 CollectSeqOption cs_option;
3308 Uint2 entityID, t_entityID;
3309
3310 ValNodePtr aligns = NULL, h_aligns, t_aligns;
3311
3312
3313 if(query_bsp == NULL)
3314 return NULL;
3315
3316 entityID = ObjMgrGetEntityIDForPointer((Pointer)query_bsp);
3317 if(entityID == 0)
3318 {
3319 Message(MSG_ERROR, "Fail to find the entityID for the Bioseq");
3320 return NULL;
3321 }
3322
3323 if(!set_seq_collect_option(&cs_option, 200))
3324 return NULL;
3325
3326
3327 slp = SeqLocIntNew(0, query_bsp->length-1, 0, query_bsp->id);
3328 set_option_for_collect_align(&ca_option, 0, COLLECT_HISTORY);
3329 ca_option.only_history = FALSE;
3330 ca_option.map_insert = TRUE;
3331 ca_option.slabel_format = cs_option.slabel_format;
3332 ca_option.nointerval = TRUE;
3333 ca_option.no_sort = FALSE;
3334 ca_option.flat_insert = FALSE;
3335 ca_option.align_num = -1;
3336 ca_option.csop = &cs_option;
3337 aligns = collect_anpnode_with_option(&ca_option, slp, entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
3338 if(!alignode_has_alignments(aligns))
3339 {
3340 FreeAlignNode(aligns);
3341 aligns = NULL;
3342 }
3343
3344 /*no alignment from the Bioseq, trying the Seq-annot*/
3345 if(aligns == NULL)
3346 {
3347 for(sap = annot; sap != NULL; sap = sap->next)
3348 {
3349 if(sap->type == 2)
3350 {
3351 t_entityID = ObjMgrRegister(OBJ_SEQANNOT, (Pointer)sap);
3352 if(t_entityID == 0)
3353 {
3354 Message(MSG_ERROR, "Fail to register the Seq-annot");
3355 }
3356 else
3357 {
3358 t_aligns = collect_anpnode_with_option(&ca_option, slp, t_entityID, COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, TRUE);
3359 ValNodeLink(&aligns, t_aligns);
3360 }
3361 *p_entityID = t_entityID;
3362 break;
3363 }
3364 }
3365 }
3366 else
3367 *p_entityID = entityID;
3368 if(aligns == NULL)
3369 {
3370 ErrPostEx(SEV_WARNING, 0, 0, "No alignment data");
3371 SeqLocFree(slp);
3372 return NULL;
3373 }
3374
3375 /*collecting the alignment for the query sequence*/
3376 cs_option.features[FEATDEF_repeat_region] = TRUE;
3377 cs_option.features[FEATDEF_repeat_unit] = TRUE;
3378 ca_option.show_feature = TRUE;
3379 ca_option.nointerval = FALSE;
3380 ca_option.label_size = cs_option.label_size;
3381 h_aligns = collect_master_align_node(&ca_option, slp, OBJ_SEQALIGN, entityID);
3382 SeqLocFree(slp);
3383
3384 ValNodeLink(&h_aligns, aligns);
3385
3386 return h_aligns;
3387 }
3388
3389
DrawCompressAlignment(ValNodePtr anp_list,SeqLocPtr m_loc,Int4 width,Int4Ptr p_scale,Int4Ptr p_maxwidth,Uint2 entityID,ValNodePtr PNTR arect_list)3390 SegmenT DrawCompressAlignment(ValNodePtr anp_list, SeqLocPtr m_loc, Int4 width, Int4Ptr p_scale, Int4Ptr p_maxwidth, Uint2 entityID, ValNodePtr PNTR arect_list)
3391 {
3392 Int2 styleNum;
3393 CharPtr old_style;
3394 Int4 scale;
3395 SegmenT pic;
3396 ValNode vn;
3397 Int4 max_width;
3398 Int4 y_pos;
3399
3400
3401 if(anp_list == NULL)
3402 return NULL;
3403 if(arect_list != NULL)
3404 *arect_list = NULL;
3405 vn.data.ptrvalue = m_loc;
3406 vn.next = NULL;
3407 max_width = CountMaxSeqLabel(&vn);
3408 scale = FigureMaxScale(&vn, (Int2)width, max_width);
3409 if(scale <=0)
3410 return NULL;
3411 pic = CreatePicture();
3412
3413 /*set up the sepcial style */
3414 styleNum = GetMuskCurrentSt();
3415 old_style = GetMuskStyleName(styleNum);
3416 SetMuskCurrentSt("StyleX");
3417
3418 y_pos = 0;
3419 DrawMPAlignment(anp_list, 0, SeqLocLen(m_loc)-1, m_loc, entityID, scale, &y_pos, MSM_SEQHIST, TRUE, pic);
3420 if(arect_list != NULL)
3421 load_align_label_rectangle(anp_list, arect_list, scale, FALSE);
3422
3423 *p_scale = scale;
3424 *p_maxwidth = max_width;
3425 SetMuskCurrentSt(old_style);
3426 return pic;
3427 }
3428
3429
3430 /*************************************************************************
3431 *
3432 * Label_GData(): Label the gene_data node specified by the user
3433 *
3434 *************************************************************************/
Label_GData(GeneDataPtr gdata,SeqLocPtr slp,Int4 left,Int4 top,SegmenT seg)3435 Boolean Label_GData(GeneDataPtr gdata, SeqLocPtr slp, Int4 left, Int4 top, SegmenT seg)
3436 {
3437 SeqLocPtr c_slp;
3438 Int4 c_left;
3439 Boolean success = FALSE;
3440 Int4 m_start, m_stop, t_start, t_stop;
3441 Int4 g_pos;
3442
3443
3444 if(slp == NULL ||gdata == NULL)
3445 return FALSE;
3446 while(gdata)
3447 {
3448 t_start = SeqLocStart(gdata->location);
3449 t_stop = SeqLocStop(gdata->location);
3450 for(c_slp = slp, c_left = left; slp!=NULL; c_slp=c_slp->next)
3451 {
3452 m_start = SeqLocStart(c_slp);
3453 m_stop = SeqLocStop(c_slp);
3454
3455 if(!(t_start > m_stop || t_stop < m_start))
3456 {
3457 g_pos = MAX(0, (t_start - m_start)) + c_left;
3458 AddSymbol(seg, g_pos, top, DIAMOND_SYMBOL, TRUE, LOWER_CENTER, 0);
3459 success = TRUE;
3460 }
3461 c_left += SeqLocLen(c_slp);
3462 }
3463 gdata = gdata->next;
3464 }
3465
3466 return TRUE;
3467 }
3468
3469
3470
3471
3472
3473
3474
3475 /*************************************************************************
3476 *
3477 * DrawVerticalAlign (align, pic, mlp)
3478 * draw alignment among the sequences. (connecting aligned seg by line)
3479 * align: the Seq-align which contains the alignment among sequence
3480 * It is assumed to be a Std-seg
3481 * pic: the drawing segment
3482 * mlp: the list of the layout of the sequences
3483 *
3484 *************************************************************************/
3485
draw_one_align(AlignPos ap,Int2 num,Int2 order,SegmenT seg)3486 void draw_one_align(AlignPos ap, Int2 num, Int2 order, SegmenT seg)
3487 {
3488 Int4 x1, x2;
3489 Int2 i;
3490
3491 for(i = 0; i<num-1; ++i)
3492 {
3493 x1 = (ABS(ap.left[i]) + ABS(ap.right[i]))/2;
3494 x2 = (ABS(ap.left[i+1]) + ABS(ap.right[i+1]))/2;
3495 AddLine(seg, x1, ap.top[i], x2, ap.bottom[i+1], FALSE, order);
3496 if(ap.left[i] < 0)
3497 {
3498 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLUE_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3499 AddSymbol(seg, x1, ap.bottom[i], UP_TRIANGLE_SYMBOL, TRUE, MIDDLE_CENTER, 0);
3500 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3501 }
3502 if(ap.left[i+1] < 0)
3503 {
3504 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLUE_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3505 AddSymbol(seg, x2, ap.bottom[i], DOWN_TRIANGLE_SYMBOL, TRUE, MIDDLE_CENTER, 0);
3506 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, COPY_MODE);
3507 }
3508 }
3509 }
3510
get_map_pos(MapLayoutPtr mlp,SeqIdPtr sip)3511 static MapPosPtr get_map_pos(MapLayoutPtr mlp, SeqIdPtr sip)
3512 {
3513 MapPosPtr mpp;
3514
3515 while(mlp)
3516 {
3517 mpp = mlp->data.ptrvalue;
3518 if(SeqIdMatch(sip, SeqLocId(mpp->slp)))
3519 return mpp;
3520 mlp = mlp->next;
3521 }
3522 return NULL;
3523 }
3524
get_ith_arp(AlignRangePtr arp,Int2 i)3525 static AlignRangePtr get_ith_arp(AlignRangePtr arp, Int2 i)
3526 {
3527 Int2 k = 0;
3528
3529 while(arp)
3530 {
3531 if(k == i)
3532 return arp;
3533 arp = arp->next;
3534 ++k;
3535 }
3536 return NULL;
3537 }
3538
DrawVerticalAlign(SeqAlignPtr align,SegmenT pic,MapLayoutPtr mlp)3539 Boolean DrawVerticalAlign (SeqAlignPtr align, SegmenT pic, MapLayoutPtr mlp)
3540 {
3541 StdSegPtr ssp;
3542 SeqLocPtr locs;
3543 MapLayoutPtr curr;
3544 MapPosPtr mpp;
3545 Int2 j;
3546 GatherRange gr;
3547 AlignPos ap;
3548 SeqLoc sl_1;
3549
3550
3551
3552 sl_1.choice = SEQLOC_MIX;
3553 sl_1.next = NULL;
3554 j = 0;
3555 if(align->segtype != 3)
3556 return FALSE;
3557 ssp= align->segs;
3558 for(curr = mlp; curr != NULL; curr = curr->next)
3559 {
3560 mpp = (MapPosPtr)(curr->data.ptrvalue);
3561 sl_1.data.ptrvalue = mpp->slp;
3562 for(locs = ssp->loc; locs != NULL; locs = locs->next)
3563 {
3564 if(SeqLocOffset(&sl_1, locs, &gr, mpp->left))
3565 {
3566
3567 ap.left[j] = gr.left;
3568 ap.right[j] = gr.right;
3569 ap.top[j] = mpp->seq_top;
3570 ap.bottom[j] = mpp->seq_bottom;
3571 ++j;
3572 }
3573 }
3574 }
3575
3576 if(j >1)
3577 {
3578 SortAlignPosition(&ap, j);
3579 draw_one_align(ap, j, 0, pic);
3580 return TRUE;
3581 }
3582 else
3583 return FALSE;
3584 }
3585
3586
3587
3588
DrawEquivAlign(ValNodePtr e_align_list,SegmenT pic,MapLayoutPtr mlp)3589 static void DrawEquivAlign (ValNodePtr e_align_list, SegmenT pic, MapLayoutPtr mlp)
3590 {
3591 SeqAlignPtr align;
3592 SeqAnnotPtr annot;
3593 Int2 type;
3594 Uint1 my_gray_color[]={63, 63, 63};
3595
3596 /* AddAttribute (pic, WIDTH_ATT | COLOR_ATT, GREEN_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE); */
3597 while(e_align_list)
3598 {
3599 annot = (SeqAnnotPtr)(e_align_list->data.ptrvalue);
3600 type = GetEquivAlignType (annot);
3601 add_attribute_pen(pic, MSM_ALIGNMENT, MSM_ALINE);
3602 switch(type)
3603 {
3604 case 2: /*it is inconsistent markers*/
3605 AddAttribute(pic, COLOR_ATT|STYLE_ATT, RED_COLOR, DOTTED_LINE, 0, 0, 0);
3606 break;
3607 case 3: /*it is unknown type*/
3608 case 0:
3609 AddAttribute(pic, COLOR_ATT|STYLE_ATT, CYAN_COLOR, SOLID_LINE, 0, 0, 0);
3610 break;
3611 case 4: /*it is the alignment to the FISH map*/
3612 AddAttribute(pic, COLOR_ATT|STYLE_ATT, BLACK_COLOR, SOLID_LINE, 0, 0, 0);
3613 break;
3614 default:
3615 AddAttribute(pic, STYLE_ATT, 0, SOLID_LINE, 0, 0, 0);
3616 break;
3617 }
3618 align = (SeqAlignPtr)(annot->data);
3619 while(align)
3620 {
3621 DrawVerticalAlign (align, pic, mlp);
3622 align = align->next;
3623 }
3624 e_align_list = e_align_list->next;
3625 }
3626 }
3627
3628
3629
3630
3631
3632
3633
3634 /*********************************************************************
3635 *
3636 * DrawGenomeMap(slp_list, e_align_list, scale, mlp)
3637 *
3638 * draw all the SeqLocs in the list and show their alignment (if any)
3639 * slp_list: the list of Seq-locs
3640 * e_align_list: the list of alignment among the Seq-locs
3641 * scale: the scale for the picture
3642 * mlp: store the layout of the current picture
3643 * return the picture of the genome map
3644 * ftype_list: return a list of type of features for the current
3645 * Seq-loc. This is going to be used for drawing the legend
3646 * image_list: the list to store the image mapping information
3647 * align_num: number of the top alignment to show. -1 = show everything
3648 *
3649 *********************************************************************/
DrawGenomeMapEx(ValNodePtr slp_list,ValNodePtr e_align_list,Int4 scale,GeneDataPtr gdata,MapLayoutPtr PNTR mlp,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3650 SegmenT DrawGenomeMapEx (ValNodePtr slp_list, ValNodePtr e_align_list, Int4 scale, GeneDataPtr gdata,
3651 MapLayoutPtr PNTR mlp, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list,
3652 Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3653 {
3654 Boolean success = FALSE;
3655 ValNodePtr curr;
3656 SeqLocPtr slp;
3657 MapLayoutPtr mlp_head= NULL;
3658 SegmenT pic;
3659 /* ValNodePtr t_image = NULL; */
3660
3661 if(slp_list == NULL || scale <=0)
3662 return NULL;
3663
3664 scale = MIN(scale, MAX_SCALE);
3665 pic = CreatePicture();
3666 if(ftype_list != NULL)
3667 *ftype_list = NULL;
3668 if(image_list != NULL)
3669 *image_list = NULL;
3670
3671 for(curr = slp_list; curr !=NULL; curr = curr->next)
3672 {
3673 slp = curr->data.ptrvalue;
3674 /* if(DrawOneSeqLoc(slp, 0, scale, pic, &mlp_head, gdata, (Uint2)(curr->choice), ftype_list, &t_image)) */
3675 if(DrawOneSeqLoc(slp, 0, scale, pic, &mlp_head, gdata, (Uint2)(curr->choice), ftype_list,
3676 image_list, forceSeglevelsTo1, extraEntityList))
3677 success = TRUE;
3678 }
3679 /* ValNodeFreeData(t_image); */
3680 if(!success)
3681 {
3682 DeletePicture(pic);
3683 return NULL;
3684 }
3685
3686 DrawEquivAlign (e_align_list, pic, mlp_head);
3687 if(mlp !=NULL)
3688 *mlp = mlp_head;
3689 else
3690 MapLayoutFree(mlp_head);
3691 return pic;
3692 }
3693
DrawGenomeMap(ValNodePtr slp_list,ValNodePtr e_align_list,Int4 scale,GeneDataPtr gdata,MapLayoutPtr PNTR mlp,ValNodePtr PNTR ftype_list,ValNodePtr PNTR image_list)3694 SegmenT DrawGenomeMap (ValNodePtr slp_list, ValNodePtr e_align_list, Int4 scale, GeneDataPtr gdata, MapLayoutPtr PNTR mlp, ValNodePtr PNTR ftype_list, ValNodePtr PNTR image_list)
3695 {
3696 return DrawGenomeMapEx (slp_list, e_align_list, scale, gdata, mlp, ftype_list, image_list, FALSE, NULL);
3697 }
3698
3699 /**************************************************************************
3700 *
3701 * DrawSequinMap(slp_list, sep, scale)
3702 * return a picture with the interface defined by Jonathan K.
3703 * slp_list: a ValNode list of Seq-loc
3704 * sep: the Seq-entry pointer
3705 * scale: the scale of the picture
3706 *
3707 **************************************************************************/
DrawSequinMapEx(ValNodePtr slp_list,SeqEntryPtr sep,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR ftype_list,Boolean forceSeglevelsTo1,ValNodePtr extraEntityList)3708 SegmenT DrawSequinMapEx (ValNodePtr slp_list, SeqEntryPtr sep, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR ftype_list, Boolean forceSeglevelsTo1, ValNodePtr extraEntityList)
3709 {
3710 ValNodePtr e_align_list = NULL;
3711 SegmenT pic;
3712
3713 if(slp_list == NULL || sep == NULL || scale <=0)
3714 return NULL;
3715
3716 e_align_list = get_equiv_align(sep);
3717 /*gdata = make_gene_data(g_list);*/
3718
3719 pic = DrawGenomeMapEx(slp_list, e_align_list, scale, gdata, NULL, ftype_list, NULL, forceSeglevelsTo1, extraEntityList);
3720 /*GeneDataFree(gdata);*/
3721 ValNodeFree(e_align_list);
3722 return pic;
3723 }
3724
DrawSequinMap(ValNodePtr slp_list,SeqEntryPtr sep,Int4 scale,GeneDataPtr gdata,ValNodePtr PNTR ftype_list)3725 SegmenT DrawSequinMap (ValNodePtr slp_list, SeqEntryPtr sep, Int4 scale, GeneDataPtr gdata, ValNodePtr PNTR ftype_list)
3726 {
3727 return DrawSequinMapEx (slp_list, sep, scale, gdata, ftype_list, FALSE, NULL);
3728 }
3729
load_align_option_for_graphic(CollectAlignOptionPtr caop,CollectSeqOptionPtr csop,Int4 style,Boolean flat_insert)3730 Boolean load_align_option_for_graphic(CollectAlignOptionPtr caop, CollectSeqOptionPtr csop, Int4 style, Boolean flat_insert)
3731 {
3732 Int2 i;
3733
3734 if(style < MSM_SEQHIST || style > MSM_MDIM)
3735 return FALSE;
3736 MemSet((Pointer)caop, 0, sizeof(CollectAlignOption));
3737 caop->graphic_offset = 0;
3738 caop->only_history = FALSE;
3739 caop->show_mismatch = (style == MSM_MPAIR); /*can not show mismatch for MDIM for now*/
3740 caop->label_size= (Int2)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_NUM);
3741 caop->nointerval = FALSE;
3742 caop->map_insert = (style== MSM_MPAIR || style == MSM_SEQHIST);
3743 caop->flat_insert = (style == MSM_MPAIR && flat_insert);
3744 caop->map_graphic = TRUE;
3745 caop->show_feature = TRUE;
3746 caop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
3747 caop->align_num = DEFAULT_ALIGN_NUM;
3748 /* caop->align_num = (Int4)GetMuskCParam(MSM_ALIGNMENT, MSM_NOSUBCLASS, MSM_SCALE); */
3749
3750 csop->seglevels = 0;
3751 csop->nointerval = FALSE;
3752 csop->slabel_format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
3753 for(i =0; i<FEATDEF_ANY; ++i)
3754 csop->flabel_format[i] = (Uint1)GetMuskCParam(i, MSM_FLABEL, MSM_STYLE);
3755 csop->label_size = caop->label_size;
3756 csop->filter_level = 0;
3757 return TRUE;
3758 }
3759
3760
3761
3762 /************************************************************
3763 *
3764 * collect_alignnode_from_alp(m_loc)
3765 * collect all the alignment stored as the history of the
3766 * master sequence
3767 * m_loc: the selected location of the master sequence
3768 * return a list of AlignNode
3769 *
3770 ************************************************************/
collect_alignnode_from_slp(SeqLocPtr m_loc,Uint2Ptr t_entityID,Boolean flat_insert)3771 ValNodePtr collect_alignnode_from_slp(SeqLocPtr m_loc, Uint2Ptr t_entityID, Boolean flat_insert)
3772 {
3773 ValNodePtr anp_node;
3774 CollectAlignOption ca_option;
3775 CollectSeqOption cs_option;
3776 BioseqPtr bsp;
3777 Uint2 entityID;
3778
3779 if(m_loc == NULL)
3780 return NULL;
3781 bsp = BioseqLockById(SeqLocId(m_loc));
3782 if(bsp == NULL)
3783 return NULL;
3784 entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
3785 if(entityID == 0)
3786 return NULL;
3787 if(t_entityID != NULL)
3788 *t_entityID = entityID;
3789 load_align_option_for_graphic(&ca_option, &cs_option, MSM_MPAIR, flat_insert);
3790 ca_option.csop = &cs_option;
3791 if(!BioseqHasFeature(bsp))
3792 cs_option.seglevels = 1;
3793 anp_node= collect_anpnode_with_option(&ca_option, m_loc, entityID, COLLECT_MP, OBJ_SEQHIST_ALIGN, NULL, NULL, FALSE);
3794
3795 BioseqUnlock(bsp);
3796 return anp_node;
3797 }
3798
3799
3800
3801
3802 /************************************************************************
3803 *
3804 *
3805 ************************************************************************/
DrawSeqHistoryAlignment(SeqLocPtr m_loc,Int4 scale,ValNodePtr PNTR anp_list,Uint2Ptr seq_entityID,Boolean flat_insert)3806 SegmenT DrawSeqHistoryAlignment(SeqLocPtr m_loc, Int4 scale, ValNodePtr PNTR anp_list, Uint2Ptr seq_entityID, Boolean flat_insert)
3807 {
3808 ValNodePtr anp_node;
3809 SegmenT pic;
3810 Int4 y_pos = 0;
3811 Int4 len;
3812 Uint2 entityID;
3813
3814 anp_node = collect_alignnode_from_slp(m_loc, &entityID, flat_insert);
3815 if(anp_node == NULL)
3816 return NULL;
3817 pic = CreatePicture();
3818 len = slp_list_len(m_loc);
3819 DrawMPAlignment(anp_node, 0, len-1, m_loc, entityID, scale, &y_pos, MSM_MPAIR, FALSE, pic);
3820
3821 if(seq_entityID != NULL)
3822 *seq_entityID = entityID;
3823 if(anp_list != NULL)
3824 *anp_list = anp_node;
3825 else
3826 FreeAlignNode(anp_node);
3827 return pic;
3828 }
3829
3830 /*draw something that looks like a folder for the un-aligned contigs in
3831 Eric Green's map
3832 */
3833
draw_unknown_folder(SegmenT seg,Int4 left,Int4 right,Int4 y_pos,AnnotInfoPtr annot_info)3834 static Boolean draw_unknown_folder(SegmenT seg, Int4 left, Int4 right, Int4 y_pos, AnnotInfoPtr annot_info)
3835 {
3836 Char label[101];
3837 Int4 center, middle;
3838 Int4 font_height;
3839
3840 if(annot_info->annotDB[0] == '\0')
3841 return FALSE;
3842 font_height = FontHeight();
3843 middle = y_pos - font_height/2;
3844 SelectFont(programFont);
3845 sprintf(label, "[%s]", annot_info->annotDB);
3846 center = (left + right)/2;
3847
3848 AddAttribute (seg, COLOR_ATT, YELLOW_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
3849 AddRectangle (seg, left, y_pos, right, y_pos-font_height, FALSE, TRUE, annot_info->itemID);
3850 AddAttribute (seg, COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
3851 AddTextLabel(seg, center, middle, label, programFont, 0, MIDDLE_CENTER, annot_info->itemID);
3852 return TRUE;
3853 }
3854
3855
get_master_alignnode_extremes(ValNodePtr anp_node,Int4Ptr m_left,Int4Ptr m_right)3856 static Boolean get_master_alignnode_extremes (ValNodePtr anp_node, Int4Ptr m_left, Int4Ptr m_right)
3857 {
3858 AlignNodePtr anp;
3859
3860 while(anp_node != NULL)
3861 {
3862 if(anp_node->choice != OBJ_SEQANNOT)
3863 {
3864 anp = anp_node->data.ptrvalue;
3865 if(anp->is_master)
3866 {
3867 *m_left = anp->extremes.left;
3868 *m_right = anp->extremes.right;
3869 return TRUE;
3870 }
3871 }
3872
3873 anp_node = anp_node->next;
3874 }
3875
3876 return FALSE;
3877 }
3878
3879
DrawMPAlignment(ValNodePtr anp_node,Int4 left,Int4 right,SeqLocPtr m_loc,Uint2 entityID,Int4 scale,Int4Ptr cur_pos,Uint1 style,Boolean compress,SegmenT pic)3880 Boolean DrawMPAlignment(ValNodePtr anp_node, Int4 left, Int4 right, SeqLocPtr m_loc, Uint2 entityID, Int4 scale, Int4Ptr cur_pos, Uint1 style, Boolean compress, SegmenT pic)
3881 {
3882 Int4 y_pos;
3883 SegmenT pseg, seg;
3884 Boolean ends = FALSE;
3885 Int4 height, ends_scale;
3886
3887 Int4 g_top, g_bottom;
3888 Int4 group_font_height;
3889
3890 ValNodePtr list, curr, prev, last, next;
3891 ValNodePtr head;
3892 AnnotInfoPtr annot_info;
3893 Int4 space;
3894 Int4 m_left = -1, m_right = -1;
3895 Int4 offset;
3896 SeqLocPtr last_loc;
3897 SeqIntPtr sint;
3898 Int4 len;
3899 Boolean use_symbol_for_align; /*for each alignment, only use
3900 the diamond symbol to indicate
3901 the alignment location*/
3902
3903
3904 if(anp_node == NULL || pic == NULL || cur_pos == NULL)
3905 return FALSE;
3906 if(style > MSM_FIXED || style < MSM_SEQHIST)
3907 return FALSE;
3908 if(style == MSM_SEQHIST )
3909 {
3910 ends_scale = GetMuskCParam(MSM_TOPSTYLE, MSM_ENDS, MSM_SCALE);
3911 if(ends_scale < scale)
3912 ends = TRUE;
3913 }
3914 if(compress)
3915 ends = TRUE;
3916 if(ends)
3917 height = GetMuskCParam(MSM_SEQUENCE, MSM_SEG_BORD, MSM_PENWIDTH);
3918 else
3919 height = GetMuskCParam(MSM_SEQUENCE, MSM_SEGMENT, MSM_HEIGHT);
3920
3921 y_pos = *cur_pos;
3922 if(m_loc != NULL)
3923 y_pos -= 40; /*leaves enough space for drawing the ruler*/
3924
3925 pseg = CreateSegment(pic, anp_node->choice, 0);
3926 seg = CreateSegment(pseg, entityID, 0);
3927
3928 if(!get_master_alignnode_extremes(anp_node, &m_left, &m_right))
3929 {
3930 m_left = left;
3931 m_right = right;
3932 }
3933 if(m_loc != NULL)
3934 {
3935 len = SeqLocLen(m_loc);
3936 last_loc = m_loc;
3937 offset = 0;
3938 sint = NULL;
3939 while(last_loc->next != NULL)
3940 {
3941 len += SeqLocLen(last_loc->next);
3942 last_loc = last_loc->next;
3943 }
3944 if(m_left != -1 && m_right != -1 && last_loc->choice == SEQLOC_INT)
3945 {
3946 offset = m_right - m_left + 1 - len;
3947 if(offset > 0)
3948 {
3949 sint = last_loc->data.ptrvalue;
3950 if(sint->strand == Seq_strand_minus)
3951 sint->from -= offset;
3952 else
3953 sint->to += offset;
3954 }
3955 }
3956 DrawSeqScale(seg, m_loc, 0, 0, scale, TRUE);
3957 if(offset > 0 && sint != NULL)
3958 {
3959 if(sint->strand == Seq_strand_minus)
3960 sint->from += offset;
3961 else
3962 sint->to -= offset;
3963 }
3964 }
3965
3966 SelectFont(programFont);
3967 group_font_height = FontHeight();
3968 space = GetMuskCParam(MSM_TOPSTYLE, MSM_SPACE, MSM_HEIGHT);
3969
3970
3971 if(anp_node == NULL)
3972 return FALSE;
3973 list = anp_node;
3974 prev = NULL;
3975 head = NULL;
3976 use_symbol_for_align = FALSE;
3977 while(list != NULL)
3978 {
3979 annot_info = NULL;
3980 /* if(prev != NULL)
3981 prev->next = list; */
3982 while(list && list->choice == OBJ_SEQANNOT)
3983 {
3984 annot_info = (AnnotInfoPtr)(list->data.ptrvalue);
3985 if(annot_info != NULL && annot_info->consistent == ALIGN_UNKNOWN)
3986 {
3987 /*it is the folder like un-aligned thing*/
3988 pseg = CreateSegment(pic, OBJ_SEQANNOT, 0);
3989 seg = CreateSegment(pseg, annot_info->entityID, 0);
3990 if(draw_unknown_folder(seg, m_left, m_right, y_pos, annot_info))
3991 {
3992 y_pos -= (group_font_height + space);
3993 *cur_pos = y_pos;
3994 }
3995 }
3996 if(head == NULL)
3997 head = list;
3998 prev = list;
3999 list = list->next;
4000 }
4001 if(list != NULL)
4002 {
4003 use_symbol_for_align = FALSE;
4004 curr = list;
4005 last = NULL;
4006 while(curr && curr->choice != OBJ_SEQANNOT)
4007 {
4008 last = curr;
4009 curr = curr->next;
4010 }
4011 next = last->next;
4012 last->next = NULL;
4013 g_top = y_pos;
4014 if(annot_info != NULL) /*there is a Seq-annot wrapper*/
4015 {
4016 y_pos -= group_font_height;
4017 g_top -= group_font_height/2;
4018 if(annot_info->annotDB[0] != '\0')
4019 {
4020 if(StringCmp(annot_info->annotDB, "UniGene") == 0)
4021 use_symbol_for_align = TRUE;
4022 }
4023 }
4024 if(use_symbol_for_align)
4025 *cur_pos = LayoutAlignFlat(list, scale, y_pos);
4026 else
4027 *cur_pos = LayoutAlignNode(list, y_pos, scale, height);
4028 g_bottom = *cur_pos;
4029 y_pos = *cur_pos;
4030
4031 pseg = CreateSegment(pic, list->choice, 0);
4032 seg = CreateSegment(pseg, entityID, 0);
4033 if(use_symbol_for_align)
4034 DrawFlatAlign(seg, list);
4035 else
4036 DrawAlignNode(list, scale, seg);
4037
4038 if(annot_info != NULL)
4039 {
4040 pseg = CreateSegment(pic, OBJ_SEQANNOT, 0);
4041 seg = CreateSegment(pseg, annot_info->entityID, 0);
4042 AddAnnotGroup(m_left, g_top, m_right, g_bottom, (Int2)(annot_info->displayOrder), annot_info->annotDB, annot_info->itemID, seg);
4043 y_pos -= group_font_height;
4044 }
4045 /* last->next = next; */
4046 if(prev != NULL)
4047 prev->next = list;
4048 last = list;
4049 while(last->next != NULL)
4050 last = last->next;
4051 last->next = next;
4052 prev = last;
4053 list = next;
4054 }
4055 }
4056 return TRUE;
4057 }
4058
4059
4060
4061
4062
4063
4064 /************************************************************************
4065 *
4066 * DrawSeqScale(seg, slp, left, ypos, scaleX)
4067 * draw a scale for the Seq-loc. It can be a list of Seq-loc
4068 * seg: the drawing segment
4069 * slp: the Seq-loc
4070 * left: the left offset
4071 * ypos: the top position
4072 * scaleX: the current scale of the picture
4073 *
4074 ************************************************************************/
DrawSeqScale(SegmenT seg,SeqLocPtr slp,Int4 left,Int4 ypos,Int4 scaleX,Boolean add_x_line)4075 void DrawSeqScale(SegmenT seg, SeqLocPtr slp, Int4 left, Int4 ypos, Int4 scaleX, Boolean add_x_line)
4076 {
4077
4078 Int4 ruler;
4079 Int4 r_start, r_stop, curpos;
4080 Int4 xpos;
4081 Char str[20];
4082 Int2 i;
4083 NumberingPtr np;
4084 Boolean use_kb;
4085 Int2 label_width = 0;
4086 Int2 c_width;
4087 Int4 pre_pos = -1;
4088 BioseqPtr bsp;
4089
4090
4091
4092 ruler = calculate_ruler(scaleX);
4093 AddAttribute (seg, WIDTH_ATT | COLOR_ATT, BLACK_COLOR, NO_LINE_STYLE, NO_SHADING, 1, NO_MODE);
4094 ypos -=2;
4095 bsp = BioseqFind(SeqLocId(slp));
4096 if(bsp == NULL)
4097 np = NULL;
4098 else
4099 np = getBioseqNumbering(bsp);
4100 use_kb = (scaleX >= 1000);
4101 while(slp)
4102 {
4103 r_start = SeqLocStart(slp);
4104 r_stop = SeqLocStop(slp);
4105 if(add_x_line)
4106 AddLine(seg, left, ypos, left+SeqLocLen(slp), ypos, FALSE, 0);
4107 for(curpos = r_start; curpos <=r_stop; curpos +=ruler)
4108 {
4109 map_unit_label(curpos, np, str, use_kb);
4110 xpos = left + curpos - r_start;
4111 AddLine(seg, xpos, ypos, xpos, ypos-8, FALSE, 0);
4112 c_width = StringWidth(str);
4113 if(start_new_stack(pre_pos, xpos, scaleX, &label_width, c_width))
4114 {
4115 pre_pos = xpos;
4116 AddLabel(seg, xpos, ypos-4, str, SMALL_TEXT, 5, LOWER_CENTER, 0);
4117 }
4118 for(i =1; i<10; ++i)
4119 {
4120 if(curpos + ruler/10*i <=r_stop)
4121 {
4122 xpos = left + curpos + ruler/10*i - r_start;
4123 if(i ==5)
4124 AddLine(seg, xpos, ypos, xpos, ypos-5, FALSE, 0);
4125 else
4126 AddLine(seg, xpos, ypos, xpos, ypos-3, FALSE, 0);
4127 }
4128 }
4129 }
4130 left += SeqLocLen(slp);
4131 slp = slp->next;
4132 }
4133 }
4134
4135
4136
CountMaxSeqLabel(ValNodePtr slp_list)4137 Int4 CountMaxSeqLabel(ValNodePtr slp_list)
4138 {
4139 FonT font;
4140 SeqLocPtr slp;
4141 BioseqPtr bsp;
4142 Uint1 format;
4143 Char label[100];
4144 Int4 max_width = 0;
4145
4146
4147 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_FONT);
4148 format = (Uint1)GetMuskCParam(MSM_SEQUENCE, MSM_SLABEL, MSM_STYLE);
4149
4150 SelectFont(font);
4151
4152 while(slp_list)
4153 {
4154 slp = slp_list->data.ptrvalue;
4155 if(slp != NULL)
4156 {
4157 bsp = BioseqFind(SeqLocId(slp));
4158 if(bsp != NULL)
4159 MuskSeqIdWrite(bsp->id, label, 99, format, TRUE, FALSE);
4160 else
4161 MuskSeqIdWrite(SeqLocId(slp), label, 99, format, FALSE, FALSE);
4162 max_width = MAX(StringWidth(label), max_width);
4163 }
4164 slp_list = slp_list->next;
4165 }
4166 return max_width;
4167 }
4168
4169
FigureMaxScale(ValNodePtr slp_list,Int2 view_width,Int4 max_label)4170 Int4 FigureMaxScale(ValNodePtr slp_list, Int2 view_width, Int4 max_label)
4171 {
4172 Int4 width;
4173 Int4 scale;
4174
4175 Int4 seq_len;
4176 SeqLocPtr slp;
4177 ValNodePtr curr;
4178 Int4 len;
4179
4180 seq_len = 0;
4181 for(curr = slp_list; curr !=NULL; curr = curr->next)
4182 {
4183 slp = (SeqLocPtr)(curr->data.ptrvalue);
4184 len = slp_list_len(slp);
4185 seq_len = MAX(len, seq_len);
4186 }
4187 if(seq_len == 0)
4188 return -1;
4189 width = (Int4)view_width- max_label;
4190 if(width <=0)
4191 width = view_width/2;
4192 scale = seq_len/width + (((Int4)width%(Int4)view_width)>0);
4193 return MIN(scale, MAX_SCALE);
4194 /* return scale; */
4195 }
4196
FigureMinScale(ValNodePtr slp_list,Int4 max_label)4197 Int4 FigureMinScale(ValNodePtr slp_list, Int4 max_label)
4198 {
4199 Int4 seq_len;
4200 SeqLocPtr slp;
4201 ValNodePtr curr;
4202
4203 seq_len = 0;
4204 for(curr = slp_list; curr !=NULL; curr = curr->next)
4205 {
4206 slp = (SeqLocPtr)(slp_list->data.ptrvalue);
4207 seq_len = MAX(slp_list_len(slp), seq_len);
4208 }
4209 if(seq_len == 0)
4210 return 1;
4211 return MAX(1, (seq_len + max_label)/320000L);
4212 }
4213
4214
find_hot_link_gi(SeqIdPtr h_sip,Int4Ptr gi)4215 static Uint1 find_hot_link_gi(SeqIdPtr h_sip, Int4Ptr gi)
4216 {
4217 DbtagPtr db_tag;
4218 ObjectIdPtr oip;
4219 SeqIdPtr sip;
4220
4221 *gi = 0;
4222 sip = h_sip;
4223 while(sip)
4224 {
4225 if(sip->choice == SEQID_GI)
4226 {
4227 *gi = sip->data.intvalue;
4228 return ENTREZ_DB;
4229 }
4230 else if(sip->choice == SEQID_GENERAL)
4231 {
4232 db_tag = sip->data.ptrvalue;
4233 if(db_tag && db_tag->db && StringCmp(db_tag->db, "THC") == 0)
4234 {
4235 oip = db_tag->tag;
4236 if(oip && oip->id != 0)
4237 {
4238 *gi = oip->id;
4239 return THC_DB;
4240 }
4241 }
4242 }
4243
4244 sip = sip->next;
4245 }
4246
4247 for(sip = h_sip; sip != NULL; sip = sip->next)
4248 {
4249 if(sip->choice == SEQID_GENERAL)
4250 {
4251 *gi = GetUniGeneIDForSeqId (sip);
4252 if(*gi != 0)
4253 return ENTREZ_KLUDGE_ID;
4254 }
4255 }
4256
4257
4258 return 0;
4259 }
4260
link_new_align_label(ValNodePtr PNTR head,ValNodePtr PNTR prev,Uint1 choice,AlignLabelRectPtr alrp)4261 static void link_new_align_label(ValNodePtr PNTR head, ValNodePtr PNTR prev, Uint1 choice, AlignLabelRectPtr alrp)
4262 {
4263 ValNodePtr curr;
4264
4265 curr = ValNodeNew(NULL);
4266 curr->choice = choice;
4267 curr->data.ptrvalue = alrp;
4268
4269 if(*prev == NULL)
4270 *head = curr;
4271 else
4272 (*prev)->next = curr;
4273 *prev = curr;
4274 }
4275
4276
4277 /*
4278 *
4279 * Add the rectangle for the label of the sequence
4280 * width is the width of the label
4281 *
4282 */
add_label_rectangle(AlignLabelRectPtr alrp,Int4 width,Int4 label_height,Uint1 label_align,Int4 e_left,Int4 e_top,Int4 e_right,Int4 e_bottom)4283 static Boolean add_label_rectangle (AlignLabelRectPtr alrp, Int4 width, Int4 label_height,
4284 Uint1 label_align, Int4 e_left, Int4 e_top, Int4 e_right, Int4 e_bottom)
4285 {
4286 Int4 center, middle;
4287
4288 if(alrp == NULL || width == 0)
4289 return FALSE;
4290
4291 switch(label_align)
4292 {
4293 case MSM_LABEL_TOP:
4294 center = (e_left + e_right)/2;
4295 alrp->left = center - width/2;
4296 alrp->right = center + width/2;
4297 alrp->bottom = e_top;
4298 alrp->top = e_top + label_height;
4299 break;
4300
4301 case MSM_LABEL_BOTTOM:
4302 center = (e_left + e_right)/2;
4303 alrp->left = center - width/2;
4304 alrp->right = center + width/2;
4305 alrp->top = e_bottom;
4306 alrp->bottom = e_bottom - label_height;
4307 break;
4308
4309 case MSM_LABEL_LEFT:
4310 middle = (e_top + e_bottom)/2;
4311 alrp->right= e_left;
4312 alrp->left= alrp->right - width;
4313 alrp->bottom = middle - label_height/2;
4314 alrp->top = middle + label_height/2;
4315 break;
4316
4317 case MSM_LABEL_RIGHT:
4318 middle = (e_top + e_bottom)/2;
4319 alrp->left=e_right;
4320 alrp->right = alrp->left + width;
4321 alrp->bottom = middle - label_height/2;
4322 alrp->top = middle + label_height/2;
4323 break;
4324 default:
4325 break;
4326 }
4327 return TRUE;
4328 }
4329
4330 /************************************************************************
4331 *
4332 * load the information for image mapping
4333 *
4334 ************************************************************************/
load_align_label_rectangle(ValNodePtr data_list,ValNodePtr PNTR arect_list,Int4 scale,Boolean flat)4335 Boolean load_align_label_rectangle(ValNodePtr data_list, ValNodePtr PNTR arect_list, Int4 scale, Boolean flat)
4336 {
4337 AlignNodePtr anp;
4338 FeatNodePtr fnp;
4339 BioseqPtr bsp;
4340 Uint1 label_align, t_label_align;
4341 AlignLabelRectPtr alrp;
4342 Int4 width;
4343 Int4 e_left = 0, e_right = 0;
4344 Int4 e_top = 0, e_bottom = 0;
4345 Int4 font_height;
4346 FonT font;
4347 Uint1 link_db;
4348 Int4 gi;
4349 Int4 label_height = stdLineHeight;
4350 ValNodePtr prev, curr;
4351 Uint1 choice;
4352 Boolean found_it;
4353
4354 if(data_list == NULL || arect_list == NULL)
4355 return FALSE;
4356 prev = NULL;
4357 curr = *arect_list;
4358 if(curr != NULL)
4359 {
4360 while(curr->next != NULL)
4361 {
4362 prev = curr;
4363 curr = curr->next;
4364 }
4365 }
4366
4367 font = (FonT)GetMuskCParam(MSM_SEQUENCE, MSM_FLABEL, MSM_FONT);
4368 SelectFont(font);
4369 font_height = FontHeight();
4370 label_align = (Uint1)GetMuskCParam(MSM_TOPSTYLE, MSM_LABEL, MSM_STYLE);
4371
4372 while(data_list)
4373 {
4374 found_it = FALSE;
4375 alrp = NULL;
4376 /* t_label_align = label_align; */
4377 if(flat)
4378 t_label_align = MSM_LABEL_TOP;
4379 else
4380 t_label_align = label_align;
4381 width = 0;
4382 choice = 0;
4383 /*process the intervals first */
4384 switch(data_list->choice)
4385 {
4386 case OBJ_SEQALIGN:
4387 case OBJ_SEQHIST_ALIGN:
4388 anp = data_list->data.ptrvalue;
4389 e_left = anp->extremes.left;
4390 e_right = anp->extremes.right;
4391 e_top = anp->top;
4392 e_bottom = anp->bottom;
4393 label_height = font_height;
4394 if(anp->label != NULL)
4395 width = StringWidth(anp->label) * scale;
4396
4397 bsp = BioseqFindCore(anp->sip);
4398 gi = 0;
4399 link_db = 0;
4400 choice = 0;
4401 if(bsp != NULL)
4402 {
4403 link_db = find_hot_link_gi(bsp->id, &gi);
4404 choice = bsp->mol;
4405 }
4406 else
4407 {
4408 link_db = find_hot_link_gi(anp->sip, &gi);
4409 }
4410 if((e_right - e_left) /scale > 1)
4411 {
4412 alrp = MemNew(sizeof(AlignLabelRect));
4413 alrp->itemID = anp->itemID;
4414 alrp->itemType = data_list->choice;
4415 if(link_db != UNKNOWN_DB && gi != 0)
4416 {
4417 alrp->link_db = link_db;
4418 alrp->gi = gi;
4419 }
4420 alrp->left = e_left;
4421 alrp->right = e_right;
4422 alrp->top = e_top;
4423 alrp->bottom = e_bottom;
4424 link_new_align_label(arect_list, &prev, choice, alrp);
4425 }
4426 /*create the new one for the label*/
4427 if(width > 0)
4428 {
4429 alrp = MemNew(sizeof(AlignLabelRect));
4430 alrp->itemID = anp->itemID;
4431 alrp->itemType = data_list->choice;
4432 alrp->link_db = link_db;
4433 alrp->gi = gi;
4434 }
4435
4436 break;
4437
4438 case OBJ_SEQFEAT:
4439 case OBJ_BIOSEQ:
4440 case OBJ_BIOSEQ_SEG:
4441 fnp = data_list->data.ptrvalue;
4442 if((fnp->extremes.right - fnp->extremes.left)/scale > 1)
4443 {
4444 alrp = MemNew(sizeof(AlignLabelRect));
4445 alrp->itemID = fnp->itemID;
4446 alrp->itemType = data_list->choice;
4447 alrp->right= fnp->extremes.right;
4448 alrp->left= fnp->extremes.left;
4449 alrp->bottom = fnp->bottom;
4450 alrp->top = fnp->top;
4451 link_new_align_label(arect_list, &prev, choice, alrp);
4452 }
4453
4454 if(fnp->label != NULL && fnp->labelHeight > 0 && fnp->label_len > 0)
4455 {
4456 e_left = fnp->extremes.left;
4457 e_right = fnp->extremes.right;
4458 e_top = fnp->top;
4459 e_bottom = fnp->bottom;
4460 label_height = fnp->labelHeight;
4461 width = scale * (fnp->label_len);
4462 alrp = MemNew(sizeof(AlignLabelRect));
4463 alrp->itemID = fnp->itemID;
4464 alrp->itemType = data_list->choice;
4465 }
4466 if(data_list->choice != OBJ_SEQFEAT)
4467 { /*it is a Bioseq or a segment of a Bioseq*/
4468 if(label_align != MSM_LABEL_RIGHT)
4469 t_label_align = MSM_LABEL_LEFT;
4470 else
4471 t_label_align = MSM_LABEL_RIGHT;
4472 }
4473 break;
4474
4475 case OBJ_BIOSEQ_MAPFEAT:
4476 fnp = data_list->data.ptrvalue;
4477 if(fnp->label != NULL && fnp->labelHeight > 0 && fnp->label_len > 0)
4478 {
4479 e_left = fnp->extremes.left;
4480 e_right = fnp->extremes.right;
4481 e_top = fnp->top;
4482 e_bottom = fnp->bottom;
4483 label_height = fnp->labelHeight;
4484 width = scale * (fnp->label_len);
4485 t_label_align = MSM_LABEL_TOP;
4486 alrp = MemNew(sizeof(AlignLabelRect));
4487 alrp->itemID = fnp->itemID;
4488 alrp->itemType = data_list->choice;
4489
4490 }
4491 break;
4492 default:
4493 break;
4494 }
4495
4496 /*process the labels*/
4497 if(width > 0)
4498 {
4499
4500 add_label_rectangle (alrp, width, label_height, t_label_align,
4501 e_left, e_top, e_right, e_bottom);
4502 link_new_align_label(arect_list, &prev, choice, alrp);
4503 }
4504
4505 data_list = data_list->next;
4506 }
4507
4508 return TRUE;
4509 }
4510
4511 /*
4512 * for the contig maps, the real contig length may not correspond
4513 * with the mapped interval on the graphics. Need a way to find the
4514 * store the interval mapped in proportion to what is in the graphic
4515 * the intervals are mapped by the function: FindContigList
4516 */
AddIntervalForImage(ValNodePtr contig_list,ValNodePtr image_list)4517 void AddIntervalForImage(ValNodePtr contig_list, ValNodePtr image_list)
4518 {
4519 SeqLocPtr contig_slp;
4520 SeqIdPtr sip;
4521 ObjectIdPtr oip;
4522 DbtagPtr db_tag;
4523 ValNodePtr curr, vnp;
4524 AlignLabelRectPtr alrp;
4525 Uint1 db_type;
4526
4527
4528 for(vnp = contig_list; vnp != NULL; vnp = vnp->next)
4529 {
4530 contig_slp = vnp->data.ptrvalue;
4531 sip = SeqLocId(contig_slp);
4532 if(sip != NULL && (db_type = FindContigDB(sip)) != 0)
4533 {
4534 db_tag = sip->data.ptrvalue;
4535 oip = db_tag->tag;
4536 for(curr = image_list; curr != NULL; curr = curr->next)
4537 {
4538 alrp = curr->data.ptrvalue;
4539 if(alrp->link_db == db_type &&
4540 StringCmp(alrp->label, oip->str) == 0)
4541 {
4542 alrp->from = SeqLocStart(contig_slp);
4543 alrp->to = SeqLocStop(contig_slp);
4544 }
4545 }
4546 }
4547 }
4548 }
4549
4550
4551
4552
PicForAlignNode(ValNodePtr anp_list,SeqLocPtr m_loc,Int4 width,Int4Ptr p_scale,Int4Ptr p_maxwidth,ValNodePtr PNTR arect_list)4553 SegmenT PicForAlignNode(ValNodePtr anp_list, SeqLocPtr m_loc, Int4 width, Int4Ptr p_scale, Int4Ptr p_maxwidth, ValNodePtr PNTR arect_list)
4554 {
4555 Int4 scale;
4556 SegmenT pic;
4557 ValNode vn;
4558 Int4 max_width, min_scale;
4559 Int4 y_pos;
4560 Uint2 entityID;
4561 BioseqPtr bsp;
4562
4563
4564 if(anp_list == NULL)
4565 return NULL;
4566 if(arect_list != NULL)
4567 *arect_list = NULL;
4568 vn.data.ptrvalue = m_loc;
4569 vn.next = NULL;
4570 max_width = CountMaxSeqLabel(&vn);
4571 scale = FigureMaxScale(&vn, (Int2)width, max_width);
4572 min_scale = FigureMinScale (&vn, max_width);
4573 if(scale <=0)
4574 return NULL;
4575 pic = CreatePicture();
4576 y_pos = 0;
4577 bsp = BioseqFind(SeqLocId(m_loc));
4578 entityID = ObjMgrGetEntityIDForPointer((Pointer)bsp);
4579 DrawMPAlignment(anp_list, 0, SeqLocLen(m_loc)-1, m_loc, entityID, scale, &y_pos, MSM_MPAIR, FALSE, pic);
4580 load_align_label_rectangle(anp_list, arect_list, scale, FALSE);
4581 /* ObjMgrClearHold(); */
4582 SeqMgrFreeCache();
4583
4584 *p_scale = scale;
4585 *p_maxwidth = max_width;
4586 return pic;
4587 }
4588
4589
setup_option_for_cytomap(CollectSeqOptionPtr csop)4590 static void setup_option_for_cytomap(CollectSeqOptionPtr csop)
4591 {
4592 Int2 i;
4593
4594 csop->nointerval = TRUE;
4595 csop->slabel_format = PRINTID_TEXTID_ACCESSION;
4596 csop->seglevels = 0;
4597 csop->label_size = 20;
4598 csop->filter_level = 0;
4599 csop->bsp_type = CYTO_MAP;
4600
4601 for(i = 0; i<FEATDEF_ANY; ++i)
4602 {
4603 csop->flabel_format[i] = OM_LABEL_CONTENT;
4604 csop->features[i] = FALSE;
4605 }
4606 }
4607
CleanUnanchoredContig(ValNodePtr PNTR anp_list)4608 static void CleanUnanchoredContig(ValNodePtr PNTR anp_list)
4609 {
4610 ValNodePtr vnp, prev, next;
4611 AnnotInfoPtr info;
4612 Boolean clean = FALSE;
4613
4614 vnp = *anp_list;
4615 prev = NULL;
4616 while(vnp != NULL)
4617 {
4618 next = vnp->next;
4619 if(vnp->choice == OBJ_SEQANNOT)
4620 {
4621 info = vnp->data.ptrvalue;
4622 if(info && info->consistent == ALIGN_UNKNOWN)
4623 clean = TRUE;
4624 else
4625 clean = FALSE;
4626 }
4627 if(clean)
4628 {
4629 if(prev == NULL)
4630 *anp_list = next;
4631 else
4632 prev->next = next;
4633 vnp->next = NULL;
4634 FreeAlignNode(vnp);
4635 }
4636 else
4637 prev = vnp;
4638 vnp = next;
4639 }
4640 }
4641
AddAlignNodeOffset(ValNodePtr anp_list,Int4 offset)4642 static void AddAlignNodeOffset(ValNodePtr anp_list, Int4 offset)
4643 {
4644 AlignNodePtr anp;
4645 AlignSegPtr asp;
4646
4647 while(anp_list)
4648 {
4649 if(anp_list->choice != OBJ_SEQANNOT)
4650 {
4651 anp = anp_list->data.ptrvalue;
4652 anp->extremes.left += offset;
4653 anp->extremes.right += offset;
4654
4655 for(asp = anp->segs; asp != NULL; asp = asp->next)
4656 {
4657 asp->gr.left += offset;
4658 asp->gr.right += offset;
4659 }
4660 }
4661
4662 anp_list = anp_list->next;
4663 }
4664 }
4665
AddYACAnnotInfo(ValNodePtr PNTR anp_list,Uint1 type)4666 static void AddYACAnnotInfo(ValNodePtr PNTR anp_list, Uint1 type)
4667 {
4668 AnnotInfoPtr info;
4669 ValNodePtr vnp;
4670
4671 vnp = *anp_list;
4672 if(vnp->choice == OBJ_SEQANNOT)
4673 {
4674 info = vnp->data.ptrvalue;
4675 if(type == YAC_MIT)
4676 StringCpy(info->annotDB, "Contigs from WI/MIT");
4677 else
4678 StringCpy(info->annotDB, "Contigs from NHGRI");
4679 return;
4680 }
4681
4682 info = MemNew(sizeof(AnnotInfo));
4683 if(type == YAC_MIT)
4684 StringCpy(info->annotDB, "Contigs from WI/MIT");
4685 else
4686 StringCpy(info->annotDB, "Contigs from NHGRI");
4687 vnp = ValNodeNew(NULL);
4688 vnp->choice = OBJ_SEQANNOT;
4689 vnp->data.ptrvalue = info;
4690 vnp->next = *anp_list;
4691 *anp_list = vnp;
4692 }
4693
4694
find_anp_for_image(AlignLabelRectPtr alrp,ValNodePtr anp_list)4695 static AlignNodePtr find_anp_for_image(AlignLabelRectPtr alrp, ValNodePtr anp_list)
4696 {
4697 AlignNodePtr anp;
4698
4699 while(anp_list)
4700 {
4701 if(anp_list->choice != OBJ_SEQANNOT)
4702 {
4703 anp = anp_list->data.ptrvalue;
4704 if(anp->itemID == alrp->itemID && anp_list->choice == alrp->itemType)
4705 return anp;
4706 }
4707 anp_list = anp_list->next;
4708 }
4709
4710 return NULL;
4711 }
4712
4713
add_label_to_image(ValNodePtr PNTR image_list,ValNodePtr anp_list)4714 static void add_label_to_image(ValNodePtr PNTR image_list, ValNodePtr anp_list)
4715 {
4716 AlignLabelRectPtr alrp;
4717 AlignNodePtr anp;
4718 ValNodePtr prev, next, curr;
4719 Uint1 db_type;
4720 DbtagPtr db_tag;
4721 ObjectIdPtr oip;
4722
4723 curr = *image_list;
4724 prev = NULL;
4725 while(curr)
4726 {
4727 next = curr->next;
4728 alrp = curr->data.ptrvalue;
4729 anp = find_anp_for_image(alrp, anp_list);
4730 if(anp == NULL || anp->sip == NULL ||
4731 (db_type = FindContigDB(anp->sip)) == 0)
4732 {
4733 if(prev == NULL)
4734 *image_list = next;
4735 else
4736 prev->next = next;
4737 curr->next = NULL;
4738 ValNodeFreeData(curr);
4739 }
4740 else
4741 {
4742 prev = curr;
4743 alrp->link_db = db_type;
4744 db_tag = anp->sip->data.ptrvalue;
4745 oip = db_tag->tag;
4746 alrp->label = StringSave(oip->str);
4747 }
4748
4749 curr = next;
4750 }
4751 }
4752
4753
4754
4755 /*produce a picture which shows the contigs that align to the
4756 * cytogenetic band. It will expand left to the half band size and
4757 * right to the half band size. pic_width is the width of the picture
4758 * in the image map, use link_db to do MIT_YAC or NHGRI_YAC and use
4759 * label to load oip->str. that should give enough information to
4760 * re-produce the seq-id
4761 */
DrawCytoContigMap(ValNodePtr slp_list,BioseqPtr cyto_bsp,Int4 pic_width,Int4Ptr pscale,ValNodePtr PNTR image_list)4762 SegmenT DrawCytoContigMap (ValNodePtr slp_list, BioseqPtr cyto_bsp,
4763 Int4 pic_width, Int4Ptr pscale, ValNodePtr PNTR image_list)
4764 {
4765 ValNodePtr curr;
4766 SeqLocPtr cyto_slp;
4767 SeqLocPtr slp, t_slp;
4768 Int4 off_start = 0, off_stop = 0;
4769 SeqIntPtr sint;
4770 Int4 len;
4771
4772 SegmenT pic;
4773 CollectSeqOption cs_option;
4774 CollectAlignOption ca_option;
4775
4776 ValNodePtr features;
4777 Uint2 entityID;
4778 Int4 max_label;
4779
4780 MapPosPtr mpp;
4781 Int4 scale;
4782 Int4 left;
4783
4784 BioseqPtr bsp;
4785 ValNodePtr aligns;
4786 ValNodePtr anp_list;
4787 Uint1 db_type;
4788
4789 ValNodePtr contig_slp_list, list; /*stores the mapped loc for each contig*/
4790
4791
4792 if(slp_list == NULL || cyto_bsp == NULL || pic_width < 100)
4793 return NULL;
4794 entityID = ObjMgrGetEntityIDForPointer((Pointer)cyto_bsp);
4795 if(entityID == 0)
4796 return NULL;
4797
4798 if(image_list != NULL)
4799 *image_list = NULL;
4800 cyto_slp = NULL;
4801 for(curr = slp_list; curr != NULL; curr = curr->next)
4802 {
4803 slp = curr->data.ptrvalue;
4804 if(BioseqMatch(cyto_bsp, SeqLocId(slp)))
4805 {
4806 cyto_slp = SeqLocIntNew(SeqLocStart(slp), SeqLocStop(slp),
4807 Seq_strand_plus, SeqLocId(slp));
4808 len = SeqLocLen(cyto_slp);
4809 sint = cyto_slp->data.ptrvalue;
4810 sint->from = MAX(0, sint->from - len/2);
4811 sint->to = MIN(cyto_bsp->length-1, sint->to + len/2);
4812 off_start = SeqLocStart(slp) - sint->from;
4813 off_stop = sint->to - SeqLocStop(slp);
4814 break;
4815 }
4816 }
4817
4818 if(cyto_slp == NULL)
4819 return NULL;
4820
4821 /*calculate the scale for the picture*/
4822 SelectFont(systemFont);
4823 max_label = StringWidth("XXXXXXXXXX");
4824 pic_width -= max_label;
4825 if(pic_width < 50)
4826 {
4827 SeqLocFree(cyto_slp);
4828 return NULL;
4829 }
4830 len = SeqLocLen(cyto_slp);
4831 scale = len/pic_width;
4832 if(len%pic_width > 0)
4833 scale += 1;
4834
4835 /*collect information about the cytogenetic band*/
4836 setup_option_for_cytomap(&cs_option);
4837 features = CollectItemForSeqLoc(cyto_slp, entityID, 0, FALSE, NULL,
4838 &cs_option, NULL, 0);
4839 if(features == NULL)
4840 {
4841 SeqLocFree(cyto_slp);
4842 return NULL;
4843 }
4844
4845 pic = CreatePicture();
4846 /*draw the cytogenetic map*/
4847 mpp = MemNew(sizeof(MapPos));
4848 mpp->slp = cyto_slp;
4849 mpp->left = 0;
4850 mpp->right = len;
4851 mpp->top = 0;
4852 mpp->bottom = 0;
4853 mpp->seq_top = 0;
4854 mpp->seq_bottom = 0;
4855 mpp->entityID = entityID;
4856 if(!DrawCytoMap(&features, mpp, scale, pic))
4857 {
4858 FreeFeatureList(features);
4859 MemFree(mpp);
4860 SeqLocFree(cyto_slp);
4861 DeletePicture(pic);
4862 return NULL;
4863 }
4864 add_seq_label_for_map(&features, mpp, pic);
4865 FreeFeatureList(features);
4866 SeqLocFree(cyto_slp);
4867
4868 /*draw the contigs */
4869 *pscale = scale;
4870 set_option_for_collect_align(&ca_option, cs_option.label_size, COLLECT_HISTORY);
4871 ca_option.only_history = FALSE;
4872 ca_option.map_insert = TRUE;
4873 ca_option.slabel_format = cs_option.slabel_format;
4874 ca_option.nointerval = cs_option.nointerval;
4875 ca_option.no_sort = FALSE;
4876 ca_option.flat_insert = FALSE;
4877
4878 anp_list = NULL;
4879 contig_slp_list = NULL;
4880 for(curr = slp_list; curr != NULL; curr = curr->next)
4881 {
4882 slp = curr->data.ptrvalue;
4883 /*check if it is the WI map or the Eric Green map*/
4884 if((db_type = FindContigDB(SeqLocId(slp))) != 0)
4885 {
4886 sint = slp->data.ptrvalue;
4887 left = 0;
4888 bsp = BioseqFind(sint->id);
4889 if(bsp != NULL)
4890 {
4891 t_slp = SeqLocIntNew(SeqLocStart(slp), SeqLocStop(slp),
4892 Seq_strand_plus, SeqLocId(slp));
4893 sint = t_slp->data.ptrvalue;
4894 if(off_start > 0)
4895 {
4896 sint->from -= off_start;
4897 if(sint->from < 0)
4898 {
4899 left = ABS(sint->from);
4900 sint->from = 0;
4901 }
4902 }
4903 if(off_stop > 0)
4904 {
4905 sint->to += off_stop;
4906 if(sint->to > bsp->length -1 )
4907 sint->to = bsp->length;
4908 }
4909
4910 aligns = collect_anpnode_with_option(&ca_option, t_slp, entityID,
4911 COLLECT_HISTORY, OBJ_SEQALIGN, NULL, NULL, FALSE);
4912 if(aligns != NULL)
4913 CleanUnanchoredContig(&aligns);
4914 if(aligns != NULL)
4915 {
4916 list = FindContigList(t_slp);
4917 ValNodeLink(&contig_slp_list, list);
4918 if(left > 0)
4919 AddAlignNodeOffset(aligns, left);
4920 AddYACAnnotInfo(&aligns, db_type);
4921 ValNodeLink(&anp_list, aligns);
4922 }
4923 SeqLocFree(t_slp);
4924 }
4925 }
4926 }
4927
4928 if(anp_list != NULL)
4929 {
4930 len = StringWidth("XXXXXX");
4931 DrawMPAlignment(anp_list, mpp->left-len*scale, mpp->right + 8*scale, NULL, mpp->entityID, scale, &(mpp->bottom), MSM_SEQHIST, FALSE, pic);
4932 if(image_list != NULL)
4933 {
4934 load_align_label_rectangle(anp_list, image_list, scale, FALSE);
4935 /*add the label so that a Seq-id can be made from link_db+label*/
4936 add_label_to_image(image_list,anp_list);
4937 /*add the real interval in a contig sequence*/
4938 AddIntervalForImage(contig_slp_list, *image_list);
4939 }
4940 FreeAlignNode(anp_list);
4941 }
4942 MemFree(mpp);
4943 free_slp_list(contig_slp_list);
4944
4945 return pic;
4946 }
4947
4948
4949
4950
4951
4952
4953
4954
4955