1 /* @source embshow ************************************************************
2 **
3 ** General routines for sequence display.
4 **
5 ** @author Copyright (c) 2000 Gary Williams
6 ** @version $Revision: 1.52 $
7 ** @modified $Date: 2013/06/29 22:39:26 $ by $Author: rice $
8 ** @@
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 ** MA 02110-1301, USA.
24 ******************************************************************************/
25
26
27 #include "ajlib.h"
28
29 #include "embshow.h"
30 #include "embprop.h"
31 #include "embmat.h"
32 #include "ajlist.h"
33 #include "ajseq.h"
34 #include "ajfeat.h"
35 #include "ajrange.h"
36 #include "ajtranslate.h"
37
38 #include <ctype.h>
39
40
41
42 /*
43 **
44 ** TO ADD A NEW DISPLAY TYPE:
45 **
46 **
47 **
48 ** Example: complement of the sequence
49 **
50 ** Create a new type in the descriptor object types 'enum ShowEValtype'.
51 ** eg: SH_COMP
52 ** Use this to refer to this type in later routines. (eg: by embShowAddComp)
53 **
54 ** Create a structure to hold information about what options for this type
55 ** you can have.
56 ** eg: typedef struct EmbSShowComp { ... }
57 **
58 ** Create a function called by the user to set up the new type as the next
59 ** thing to be displayed in the list of things.
60 ** eg: embShowAddComp
61 **
62 ** Create the routine to actually output a line's length of whatever is
63 ** being displayed from position 'pos' of the sequence - the output is
64 ** added to the end of a list of AjPStr.
65 ** Everything to be printed should be ajListPushAppend'd on to the 'lines' list.
66 ** These strings need not be complete lines - you can push many strings of
67 ** partial lines if you prefer.
68 ** End the lines to be output by pushing a string ending with a '\n'.
69 ** As many lines as you wish may be pushed onto the lines list.
70 ** eg: showFillComp
71 **
72 ** Add a case statement to showFillLines to call the showFill* routine.
73 ** eg:
74 ** case SH_COMP:
75 ** showFillComp(this, lines, info, pos);
76 ** break;
77 **
78 ** Changes needed:
79 ** Sorting of ranges for translation
80 **
81 ** Translation of entire sequence range and then division of the
82 ** resulting sequence into reading frames. Needed so that translation
83 ** across the joins gives the correct residue. This may involve some
84 ** changes to the timing of conversion from 1 letter to 3 letter code.
85 **
86 */
87
88
89
90
91 static void showFillRE(const EmbPShow thys, AjPList lines,
92 EmbPShowRE info, ajuint pos,ajuint last);
93 static void showFillREflat(const EmbPShow thys,
94 AjPList lines, const EmbPShowRE info,
95 ajuint pos,ajuint last);
96 static void showFillREupright(const EmbPShow thys, AjPList lines,
97 EmbPShowRE info, ajuint pos,ajuint last);
98 static ajint showFillREuprightSort(const void* a, const void* b);
99 static void showOverPrint(AjPStr *target, ajint start, AjPStr insert);
100 static AjBool showLineIsClear(AjPStr *line, ajint start, ajint end);
101 static void showFillLines(AjPList lines, const EmbPShow thys,
102 ajuint pos, ajuint last);
103 static void showPrintLines(AjPFile out, const AjPList lines);
104 static void showMargin(const EmbPShow thys, AjPList lines);
105 static void showMarginNumber(const EmbPShow thys,
106 AjPList lines, ajint number);
107 static void showPad(AjPList lines, ajint number);
108 static void showInsertHTML(AjPStr *target, ajuint pos, const AjPStr insert);
109
110 static void showFillSeq(const EmbPShow thys,
111 AjPList lines, const EmbPShowSeq info,
112 ajuint pos,ajuint last);
113 static void showFillBlank(const EmbPShow thys,
114 AjPList lines, const EmbPShowBlank info,
115 ajuint pos,ajuint last);
116 static void showFillTicks(const EmbPShow thys,
117 AjPList lines, const EmbPShowTicks info,
118 ajuint pos,ajuint last);
119 static void showFillTicknum(const EmbPShow thys, AjPList lines,
120 const EmbPShowTicknum info,
121 ajuint pos,ajuint last);
122 static void showFillComp(const EmbPShow thys,
123 AjPList lines, const EmbPShowComp info,
124 ajuint pos,ajuint last);
125 static void showFillTran(const EmbPShow thys,
126 AjPList lines, EmbPShowTran info,
127 ajuint pos,ajuint last);
128 static void showFillFT(const EmbPShow thys,
129 AjPList lines, const EmbPShowFT info,
130 ajuint pos,ajuint last);
131 static void showFillNote(const EmbPShow thys,
132 AjPList lines, const EmbPShowNote info,
133 ajuint pos,ajuint last);
134
135 static void showDelSeq(EmbPShowSeq* pinfo);
136 static void showDelBlank(EmbPShowBlank* pinfo);
137 static void showDelTicks(EmbPShowTicks* pinfo);
138 static void showDelTicknum(EmbPShowTicknum* pinfo);
139 static void showDelComp(EmbPShowComp* pinfo);
140 static void showDelTran(EmbPShowTran* pinfo);
141 static void showDelRE(EmbPShowRE* pinfo);
142 static void showDelFT(EmbPShowFT* pinfo);
143 static void showDelNote(EmbPShowNote* pinfo);
144 static void showAddTags(AjPStr *tagsout, const AjPFeature feat, AjBool values);
145
146
147
148 /* ==================================================================== */
149 /* ========================= constructors ============================= */
150 /* ==================================================================== */
151
152
153
154
155 /* @section Show Sequence Constructors ****************************************
156 **
157 ** All constructors return a new show sequence object by pointer.
158 ** The target pointer does not need to be initialised to NULL, but it is
159 ** good programming practice to do so anyway.
160 **
161 ******************************************************************************/
162
163
164
165
166 /* @func embShowNew ***********************************************************
167 **
168 ** Creates a new sequence show object.
169 **
170 ** @param [r] seq [const AjPSeq] Sequence to describe
171 ** @param [r] begin [ajint] start position in sequence
172 ** @param [r] end [ajint] end position in sequence
173 ** @param [r] width [ajint] width of displayed sequence on a line
174 ** @param [r] length [ajint] length of a page in lines (0=no length)
175 ** @param [r] margin [ajint] margin for numbers etc.
176 ** @param [r] html [AjBool] format output for HTML
177 ** @param [r] offset [ajint] number to start display of position numbering at
178 ** @return [EmbPShow] New sequence show object.
179 **
180 ** @release 1.0.0
181 ** @@
182 ******************************************************************************/
183
embShowNew(const AjPSeq seq,ajint begin,ajint end,ajint width,ajint length,ajint margin,AjBool html,ajint offset)184 EmbPShow embShowNew(const AjPSeq seq, ajint begin, ajint end, ajint width,
185 ajint length, ajint margin, AjBool html, ajint offset)
186 {
187 EmbPShow pthis;
188
189 AJNEW0(pthis);
190
191 pthis->list = ajListNew();
192
193 /* information about the sequence */
194 pthis->seq = seq;
195 pthis->nucleic = ajSeqIsNuc(seq); /* ajTrue = sequence is nucleic */
196 pthis->start = begin;
197 pthis->end = end;
198
199 /* information about the page layout */
200 pthis->width = width; /* length of sequence per line */
201 pthis->length = length; /* length of a page (0 = indefinite) */
202 pthis->margin = margin; /* margin for numbering */
203 pthis->html = html; /* ajTrue = format for HTML */
204 pthis->offset = offset; /* number to start displaying with */
205
206 return pthis;
207 }
208
209
210
211
212 /* @funcstatic showInfoNew ****************************************************
213 **
214 ** Creates a new descriptor structure to be pushed on the list
215 **
216 ** @param [r] info [void*] descriptor
217 ** @param [r] type [ajint] type of descriptor
218 ** @return [EmbPShowInfo] New sequence show object.
219 **
220 ** @release 1.0.0
221 ** @@
222 ******************************************************************************/
223
showInfoNew(void * info,ajint type)224 static EmbPShowInfo showInfoNew(void* info, ajint type)
225 {
226 EmbPShowInfo pthis;
227
228 AJNEW0(pthis);
229
230 pthis->info = info;
231 pthis->type = type;
232
233 return pthis;
234 }
235
236
237
238
239 /* ==================================================================== */
240 /* ========================== destructors ============================= */
241 /* ==================================================================== */
242
243
244
245
246 /* @section Show Sequence Destructors *****************************************
247 **
248 ** Destruction destroys all internal data structures and frees the
249 ** memory allocated for the show sequence object.
250 **
251 ******************************************************************************/
252
253
254
255
256 /* @func embShowDel ***********************************************************
257 **
258 ** Deletes a show sequence object.
259 **
260 ** @param [d] pthis [EmbPShow*] Show sequence object
261 ** @return [void]
262 **
263 ** @release 1.0.0
264 ** @@
265 ******************************************************************************/
266
embShowDel(EmbPShow * pthis)267 void embShowDel(EmbPShow* pthis)
268 {
269 EmbPShow thys;
270 AjIList iter;
271 EmbPShowInfo infostruct;
272 ajint type; /* descriptor type */
273 void *ptr = NULL;
274
275 ajDebug("embShowDel\n");
276
277 /***** DO NOT: ajSeqDel(&pthis->seq); *****/
278
279 thys = *pthis;
280
281 /* free the descriptors */
282 iter = ajListIterNewread(thys->list);
283
284 while((infostruct = ajListIterGet(iter)) != NULL)
285 {
286
287 /* iterate through the descriptors filling out the lines */
288 type = infostruct->type;
289
290 switch(type)
291 {
292 case SH_SEQ:
293 showDelSeq((EmbPShowSeq*) &infostruct->info);
294 break;
295
296 case SH_BLANK:
297 showDelBlank((EmbPShowBlank*) &infostruct->info);
298 break;
299
300 case SH_TICK:
301 showDelTicks((EmbPShowTicks*) &infostruct->info);
302 break;
303
304 case SH_TICKNUM:
305 showDelTicknum((EmbPShowTicknum*) &infostruct->info);
306 break;
307
308 case SH_COMP:
309 showDelComp((EmbPShowComp*) &infostruct->info);
310 break;
311
312 case SH_TRAN:
313 showDelTran((EmbPShowTran*) &infostruct->info);
314 break;
315
316 case SH_RE:
317 showDelRE((EmbPShowRE*) &infostruct->info);
318 break;
319
320 case SH_FT:
321 showDelFT((EmbPShowFT*) &infostruct->info);
322 break;
323
324 case SH_NOTE:
325 showDelNote((EmbPShowNote*) &infostruct->info);
326 break;
327
328 default:
329 ajFatal("Unknown descriptor type found in embShowDel: %d",
330 type);
331 }
332
333
334 AJFREE(infostruct);
335 }
336
337 ajListIterDel(&iter);
338
339 /* we have already freed the descriptors, so use ajListFree here */
340 while(ajListPop(thys->list,(void **)&ptr));
341 ajListFree(&thys->list);
342
343 AJFREE(*pthis);
344
345 return;
346 }
347
348
349
350
351 /* @funcstatic showDelSeq *****************************************************
352 **
353 ** Deletes a show sequence descriptor object.
354 **
355 ** @param [d] pinfo [EmbPShowSeq*] Show sequence descriptor object
356 ** @return [void]
357 **
358 ** @release 1.0.0
359 ** @@
360 ******************************************************************************/
361
showDelSeq(EmbPShowSeq * pinfo)362 static void showDelSeq(EmbPShowSeq* pinfo)
363 {
364 AJFREE(*pinfo);
365
366 return;
367 }
368
369
370
371
372 /* @funcstatic showDelBlank ***************************************************
373 **
374 ** Deletes a show blank descriptor object.
375 **
376 ** @param [d] pinfo [EmbPShowBlank*] Show blank descriptor object
377 ** @return [void]
378 **
379 ** @release 1.0.0
380 ** @@
381 ******************************************************************************/
382
showDelBlank(EmbPShowBlank * pinfo)383 static void showDelBlank(EmbPShowBlank* pinfo)
384 {
385 AJFREE(*pinfo);
386
387 return;
388 }
389
390
391
392
393 /* @funcstatic showDelTicks ***************************************************
394 **
395 ** Deletes a show ticks descriptor object.
396 **
397 ** @param [d] pinfo [EmbPShowTicks*] Show ticks descriptor object
398 ** @return [void]
399 **
400 ** @release 1.0.0
401 ** @@
402 ******************************************************************************/
403
showDelTicks(EmbPShowTicks * pinfo)404 static void showDelTicks(EmbPShowTicks* pinfo)
405 {
406 AJFREE(*pinfo);
407
408 return;
409 }
410
411
412
413
414 /* @funcstatic showDelTicknum *************************************************
415 **
416 ** Deletes a show tick numbers descriptor object.
417 **
418 ** @param [d] pinfo [EmbPShowTicknum*] Show tick numbers descriptor object
419 ** @return [void]
420 **
421 ** @release 1.0.0
422 ** @@
423 ******************************************************************************/
424
showDelTicknum(EmbPShowTicknum * pinfo)425 static void showDelTicknum(EmbPShowTicknum* pinfo)
426 {
427 AJFREE(*pinfo);
428
429 return;
430 }
431
432
433
434
435 /* @funcstatic showDelComp ****************************************************
436 **
437 ** Deletes a show complement descriptor object.
438 **
439 ** @param [d] pinfo [EmbPShowComp*] Show complement descriptor object
440 ** @return [void]
441 **
442 ** @release 1.0.0
443 ** @@
444 ******************************************************************************/
445
showDelComp(EmbPShowComp * pinfo)446 static void showDelComp(EmbPShowComp* pinfo)
447 {
448 AJFREE(*pinfo);
449
450 return;
451 }
452
453
454
455
456 /* @funcstatic showDelTran ****************************************************
457 **
458 ** Deletes a show translation descriptor object.
459 **
460 ** @param [d] pinfo [EmbPShowTran*] Show translation descriptor object
461 ** @return [void]
462 **
463 ** @release 1.0.0
464 ** @@
465 ******************************************************************************/
466
showDelTran(EmbPShowTran * pinfo)467 static void showDelTran(EmbPShowTran* pinfo)
468 {
469 EmbPShowTran info;
470
471 info = *pinfo;
472
473 /* AJB: Why was the seqdel commented out? Memory leak without it */
474 ajSeqDel(&info->transeq);
475 AJFREE(*pinfo);
476
477 return;
478 }
479
480
481
482
483 /* @funcstatic showDelRE ******************************************************
484 **
485 ** Deletes a show restriction enzyme descriptor object.
486 **
487 ** @param [d] pinfo [EmbPShowRE*] Show restriction enzyme descriptor object
488 ** @return [void]
489 **
490 ** @release 1.0.0
491 ** @@
492 ******************************************************************************/
493
showDelRE(EmbPShowRE * pinfo)494 static void showDelRE(EmbPShowRE* pinfo)
495 {
496 void *ptr;
497 EmbPShowRE info;
498
499 info = *pinfo;
500
501 ajListFree(&info->matches); /* the nodes are elsewhere */
502
503 while(ajListPop(info->sitelist,(void **)&ptr))
504 AJFREE(ptr);
505
506 ajListFree(&info->sitelist);
507
508 AJFREE(*pinfo);
509
510 return;
511 }
512
513
514
515
516 /* @funcstatic showDelFT ******************************************************
517 **
518 ** Deletes a show feature table descriptor object.
519 **
520 ** @param [d] pinfo [EmbPShowFT*] Show feature table descriptor object
521 ** @return [void]
522 **
523 ** @release 1.0.0
524 ** @@
525 ******************************************************************************/
526
showDelFT(EmbPShowFT * pinfo)527 static void showDelFT(EmbPShowFT* pinfo)
528 {
529 EmbPShowFT info;
530
531 info = *pinfo;
532
533 ajFeattableDel(&info->feat); /* cloned pointer in showseq etc.*/
534 AJFREE(*pinfo);
535
536 return;
537 }
538
539
540
541
542 /* @funcstatic showDelNote ****************************************************
543 **
544 ** Deletes a show annotation region descriptor object.
545 **
546 ** @param [d] pinfo [EmbPShowNote*] Show annotation region descriptor object
547 ** @return [void]
548 **
549 ** @release 2.1.0
550 ** @@
551 ******************************************************************************/
552
showDelNote(EmbPShowNote * pinfo)553 static void showDelNote(EmbPShowNote* pinfo)
554 {
555 AJFREE(*pinfo);
556
557 return;
558 }
559
560
561
562
563 /* ==================================================================== */
564 /* ========================== Assignments ============================= */
565 /* ==================================================================== */
566
567
568
569
570 /* @section Show Sequence Assignments *****************************************
571 **
572 ** These functions add to the show sequence object provided as the
573 ** first argument.
574 **
575 ******************************************************************************/
576
577
578
579
580 /* @func embShowAddSeq ********************************************************
581 **
582 ** Adds the sequence to be displayed to the list of things to show
583 ** This must be done before the final printing is done as without a sequence
584 ** to hang all the other features and things on, there can be no output to
585 ** show.
586 **
587 ** @param [u] thys [EmbPShow] Show sequence object
588 ** @param [r] number [AjBool] Number the sequence
589 ** @param [r] threeletter [AjBool] Use three letter protein code
590 ** @param [r] upperrange [const AjPRange] Range of sequence to uppercase
591 ** @param [r] colour [const AjPRange] Range of sequence to colour in HTML
592 ** @return [void]
593 **
594 ** @release 1.0.0
595 ** @@
596 ******************************************************************************/
597
embShowAddSeq(EmbPShow thys,AjBool number,AjBool threeletter,const AjPRange upperrange,const AjPRange colour)598 void embShowAddSeq(EmbPShow thys, AjBool number, AjBool threeletter,
599 const AjPRange upperrange, const AjPRange colour)
600 {
601 EmbPShowSeq info;
602
603 AJNEW0(info);
604
605 info->number = number;
606 info->threeletter = threeletter; /* use three-letter protein code */
607 info->upperrange = upperrange; /* Range of sequence to uppercase */
608 info->highlight = colour; /* Range to colour in HTML */
609
610 ajListPushAppend(thys->list, showInfoNew(info, SH_SEQ));
611
612 return;
613 }
614
615
616
617
618 /* @func embShowAddBlank ******************************************************
619 **
620 ** Adds a blank line to the list of things to show.
621 **
622 ** @param [u] thys [EmbPShow] Show sequence object
623 ** @return [void]
624 **
625 ** @release 1.0.0
626 ** @@
627 ******************************************************************************/
628
embShowAddBlank(EmbPShow thys)629 void embShowAddBlank(EmbPShow thys)
630 {
631 EmbPShowBlank info;
632
633 ajDebug("embShowAddBlank\n");
634
635 AJNEW0(info);
636
637 ajListPushAppend(thys->list, showInfoNew(info, SH_BLANK));
638
639 return;
640 }
641
642
643
644
645 /* @func embShowAddTicks ******************************************************
646 **
647 ** Adds a ticks line to the list of things to show.
648 **
649 ** @param [u] thys [EmbPShow] Show sequence object
650 ** @return [void]
651 **
652 ** @release 1.0.0
653 ** @@
654 ******************************************************************************/
655
embShowAddTicks(EmbPShow thys)656 void embShowAddTicks(EmbPShow thys)
657 {
658
659 EmbPShowTicks info;
660
661 ajDebug("embShowAddTicks\n");
662
663 AJNEW0(info);
664
665 ajListPushAppend(thys->list, showInfoNew(info, SH_TICK));
666
667 return;
668 }
669
670
671
672
673 /* @func embShowAddTicknum ****************************************************
674 **
675 ** Adds a ticks number line to the list of things to show.
676 **
677 ** @param [u] thys [EmbPShow] Show sequence object
678 ** @return [void]
679 **
680 ** @release 1.0.0
681 ** @@
682 ******************************************************************************/
683
embShowAddTicknum(EmbPShow thys)684 void embShowAddTicknum(EmbPShow thys)
685 {
686 EmbPShowTicknum info;
687
688 ajDebug("embShowAddTicknum\n");
689
690 AJNEW0(info);
691
692 ajListPushAppend(thys->list, showInfoNew(info, SH_TICKNUM));
693
694 return;
695 }
696
697
698
699
700 /* @func embShowAddComp *******************************************************
701 **
702 ** Adds the sequence complement to be displayed to the list of things to show
703 **
704 ** @param [u] thys [EmbPShow] Show sequence object
705 ** @param [r] number [AjBool] ajTrue = number the complement
706 ** @return [void]
707 **
708 ** @release 1.0.0
709 ** @@
710 ******************************************************************************/
711
embShowAddComp(EmbPShow thys,AjBool number)712 void embShowAddComp(EmbPShow thys, AjBool number)
713 {
714 EmbPShowComp info;
715
716 ajDebug("embShowAddComp\n");
717
718 AJNEW0(info);
719
720 info->number = number;
721
722 ajListPushAppend(thys->list, showInfoNew(info, SH_COMP));
723
724 return;
725 }
726
727
728
729
730 /* @func embShowAddTran *******************************************************
731 **
732 ** Adds the translation to be displayed to the list of things to show
733 **
734 ** @param [u] thys [EmbPShow] Show sequence object
735 ** @param [r] trnTable [const AjPTrn] Translation table
736 ** @param [r] frame [ajint] Reading frame to translate
737 ** @param [r] threeletter [AjBool] ajTrue for 3 letter code
738 ** @param [r] number [AjBool] ajTrue for numbering
739 ** @param [r] regions [const AjPRange] Sequence range(s)
740 ** @param [r] orfminsize [ajint] Minimum length of ORF to be shown
741 ** @param [r] lcinterorf [AjBool] ajTrue to put inter-orf regions in lowercase
742 ** @param [r] firstorf [AjBool] ajTrue beginning of the seq is a possible ORF
743 ** @param [r] lastorf [AjBool] ajTrue end of the seq is a possible ORF
744 ** @param [r] showframe [AjBool] ajTrue write the frame number
745 ** @return [void]
746 **
747 ** @release 1.0.0
748 ** @@
749 ******************************************************************************/
750
embShowAddTran(EmbPShow thys,const AjPTrn trnTable,ajint frame,AjBool threeletter,AjBool number,const AjPRange regions,ajint orfminsize,AjBool lcinterorf,AjBool firstorf,AjBool lastorf,AjBool showframe)751 void embShowAddTran(EmbPShow thys, const AjPTrn trnTable, ajint frame,
752 AjBool threeletter, AjBool number, const AjPRange regions,
753 ajint orfminsize, AjBool lcinterorf, AjBool firstorf,
754 AjBool lastorf, AjBool showframe)
755 {
756 EmbPShowTran info;
757
758 ajDebug("embShowAddTran\n");
759
760 AJNEW0(info);
761
762 info->trnTable = trnTable; /* translation table */
763 info->frame = frame; /* 1,2,3,-1,-2 or -3 = frame to
764 translate */
765 info->threeletter = threeletter; /* ajTrue = display in 3 letter code */
766 info->regions = regions; /* only translate these regions,
767 NULL = all */
768 info->number = number; /* ajTrue = number the translation */
769 info->orfminsize = orfminsize; /* minimum size of ORF to display */
770
771 /* these are used by showFillTran */
772 info->transeq = NULL; /* not yet stored the translation
773 here */
774 info->tranpos = 0; /* store translation position for
775 numbering */
776 info->lcinterorf = lcinterorf; /* ajTrue = put the inter-orf regions
777 in lower case */
778 info->firstorf = firstorf;
779 info->lastorf = lastorf;
780 info->showframe = showframe;
781
782 ajListPushAppend(thys->list, showInfoNew(info, SH_TRAN));
783
784 return;
785 }
786
787
788
789
790 /* @func embShowAddRE *********************************************************
791 **
792 ** Adds the Restriction Enzymes to be displayed to the list of things to show
793 **
794 ** @param [u] thys [EmbPShow] Show sequence object
795 ** @param [r] sense [ajint] sense to translate (+1 or -1)
796 ** @param [r] restrictlist [const AjPList] restriction enzyme cut site list
797 ** @param [r] plasmid [AjBool] Circular (plasmid) sequence
798 ** @param [r] flat [AjBool] show in flat format with recognition sites
799 ** @return [void]
800 **
801 ** @release 1.0.0
802 ** @@
803 ******************************************************************************/
804
embShowAddRE(EmbPShow thys,ajint sense,const AjPList restrictlist,AjBool plasmid,AjBool flat)805 void embShowAddRE(EmbPShow thys, ajint sense, const AjPList restrictlist,
806 AjBool plasmid, AjBool flat)
807 {
808 EmbPShowRE info;
809 ajDebug("embShowAddRE\n");
810
811 AJNEW0(info);
812
813 info->sense = sense; /* 1 or -1 = sense to translate */
814 info->flat = flat; /* upright or flat display */
815 info->hits = (ajuint) ajListGetLength(restrictlist);
816 info->matches = ajListNewListref(restrictlist);
817 info->sitelist = NULL; /* show we have not yet created this
818 list */
819 info->plasmid = plasmid;
820
821 ajListPushAppend(thys->list, showInfoNew(info, SH_RE));
822
823 return;
824 }
825
826
827
828
829 /* @func embShowAddFT *********************************************************
830 **
831 ** Adds the Features to be displayed to the list of things to show
832 **
833 ** @param [u] thys [EmbPShow] Show sequence object
834 ** @param [r] feat [const AjPFeattable] features
835 ** @return [void]
836 **
837 ** @release 1.0.0
838 ** @@
839 ******************************************************************************/
840
embShowAddFT(EmbPShow thys,const AjPFeattable feat)841 void embShowAddFT(EmbPShow thys, const AjPFeattable feat)
842 {
843 EmbPShowFT info;
844
845 ajDebug("embShowAddFT\n");
846
847 AJNEW0(info);
848
849 info->feat = ajFeattableNewFtable(feat); /* store the feature table */
850
851 ajListPushAppend(thys->list, showInfoNew(info, SH_FT));
852
853 return;
854 }
855
856
857
858
859 /* @func embShowAddNote *******************************************************
860 **
861 ** Adds the annotations to be displayed to the list of things to show
862 **
863 ** @param [u] thys [EmbPShow] Show sequence object
864 ** @param [r] regions [const AjPRange] Sequence range(s)
865 ** @return [void]
866 **
867 ** @release 2.1.0
868 ** @@
869 ******************************************************************************/
870
embShowAddNote(EmbPShow thys,const AjPRange regions)871 void embShowAddNote(EmbPShow thys, const AjPRange regions)
872 {
873 EmbPShowNote info;
874 ajDebug("embShowAddNote\n");
875
876 AJNEW0(info);
877
878 info->regions = regions; /* regions to note */
879
880 ajListPushAppend(thys->list, showInfoNew(info, SH_NOTE));
881
882 return;
883 }
884
885
886
887
888 /* ==================================================================== */
889 /* =========================== Modifiers ============================== */
890 /* ==================================================================== */
891
892
893
894
895 /* @section Show Sequence Modifiers *******************************************
896 **
897 ** These functions modify the behaviour of the last show descriptor on
898 ** the list.
899 **
900 **
901 ******************************************************************************/
902
903
904
905
906
907
908 /* ==================================================================== */
909 /* ======================== Operators ==================================*/
910 /* ==================================================================== */
911
912
913
914
915 /* @section Show Sequence Operators *******************************************
916 **
917 ** These functions use the contents of a Show object but do not modify it.
918 **
919 ******************************************************************************/
920
921
922
923
924 /* @func embShowPrint *********************************************************
925 **
926 ** Prints a Show object
927 **
928 ** @param [u] out [AjPFile] Output file handle
929 ** @param [r] thys [const EmbPShow] Show sequence object
930 ** @return [void]
931 **
932 ** @release 1.0.0
933 ** @@
934 ******************************************************************************/
935
embShowPrint(AjPFile out,const EmbPShow thys)936 void embShowPrint(AjPFile out, const EmbPShow thys)
937 {
938 AjPList lines; /* list of lines to be printed */
939 ajuint pos; /* current printing position in sequence */
940 ajuint start;
941 ajuint end;
942 AjIList liter; /* iterator for lines */
943 AjPStr line;
944 ajuint count = 0; /* count of newlines in the list */
945 ajuint line_no = 0; /* line number on page */
946 ajuint last = 0;
947
948 ajDebug("embShowPrint start:%u end:%u\n", thys->start, thys->end);
949
950 /* set up the start and end positions to print */
951 start = thys->start;
952 end = thys->end;
953 last = start-1;
954
955 /* run through the whole sequence, line-width by line-width */
956 for(pos = start; pos<=end; pos += thys->width)
957 {
958 last += thys->width;
959
960 if(last >= end)
961 last = end;
962
963 /* make a new list of lines */
964 lines=ajListstrNew();
965 /* put the sequence and any other descriptors in the lines list */
966 showFillLines(lines, thys, pos, last);
967
968 /* throw a formfeed if we would go over the length of the page */
969 count = 0;
970 liter = ajListIterNewread(lines);
971
972 while((line = ajListIterGet(liter)) != NULL)
973 if(ajStrGetLen(line))
974 if(ajStrGetPtr(line)[ajStrGetLen(line)-1] == '\n')
975 count++;
976 ajListIterDel(&liter);
977
978 /* thys->length is zero if we have an indefinite page length */
979 if(thys->length && (count+line_no > thys->length) &&
980 (count < thys->length))
981 {
982 line_no = 0;
983 ajFmtPrintF(out, "%c", '\f'); /* form feed character */
984 }
985
986 showPrintLines(out, lines);
987 ajListstrFreeData(&lines);
988 }
989
990 return;
991 }
992
993
994
995
996 /* @funcstatic showPrintLines *************************************************
997 **
998 ** Print the lines to the output.
999 **
1000 ** @param [u] out [AjPFile] Output file handle
1001 ** @param [r] lines [const AjPList] lines to print
1002 ** @return [void]
1003 **
1004 ** @release 1.0.0
1005 ** @@
1006 ******************************************************************************/
1007
showPrintLines(AjPFile out,const AjPList lines)1008 static void showPrintLines(AjPFile out, const AjPList lines)
1009 {
1010 AjIList liter; /* iterator for lines */
1011 AjPStr str;
1012
1013 ajDebug("showPrintLines\n");
1014
1015 /* iterate through the lines and print them */
1016 liter = ajListIterNewread(lines);
1017
1018 while((str = ajListIterGet(liter)) != NULL)
1019 ajFmtPrintF(out, "%S", str);
1020
1021 ajListIterDel(&liter);
1022
1023 return;
1024 }
1025
1026
1027
1028
1029 /* ==================================================================== */
1030 /* ======================== Assignments ================================*/
1031 /* ==================================================================== */
1032
1033
1034
1035
1036 /* @section Show Fill Assignments *********************************************
1037 **
1038 ** These functions fill out the sequence and features lines according to the
1039 ** descriptor data.
1040 **
1041 ******************************************************************************/
1042
1043
1044
1045
1046 /* @funcstatic showFillLines **************************************************
1047 **
1048 ** Calls the descriptor routines to fill the lines.
1049 **
1050 ** @param [u] lines [AjPList] Lines list
1051 ** @param [r] thys [const EmbPShow] Show sequence object
1052 ** @param [r] pos [ajuint] position in sequence so far while printing
1053 ** @param [r] last [ajuint] final position in sequence so far while printing
1054 ** @return [void]
1055 **
1056 ** @release 1.0.0
1057 ** @@
1058 ******************************************************************************/
1059
showFillLines(AjPList lines,const EmbPShow thys,ajuint pos,ajuint last)1060 static void showFillLines(AjPList lines, const EmbPShow thys,
1061 ajuint pos, ajuint last)
1062 {
1063 EmbPShowInfo infostruct; /* structure of type and descriptor */
1064 ajint type; /* descriptor type */
1065 void * info; /* descriptor */
1066
1067 AjIList diter; /* iterator for descriptors */
1068
1069 ajDebug("showFillLines\n");
1070
1071 /* iterate through the descriptors filling out the lines */
1072 diter = ajListIterNewread(thys->list);
1073
1074 while((infostruct = ajListIterGet(diter)) != NULL)
1075 {
1076 type = infostruct->type;
1077 info = infostruct->info;
1078
1079 switch(type)
1080 {
1081 case SH_SEQ:
1082 showFillSeq(thys, lines, info, pos, last);
1083 break;
1084
1085 case SH_BLANK:
1086 showFillBlank(thys, lines, info, pos, last);
1087 break;
1088
1089 case SH_TICK:
1090 showFillTicks(thys, lines, info, pos, last);
1091 break;
1092
1093 case SH_TICKNUM:
1094 showFillTicknum(thys, lines, info, pos, last);
1095 break;
1096
1097 case SH_COMP:
1098 showFillComp(thys, lines, info, pos, last);
1099 break;
1100
1101 case SH_TRAN:
1102 showFillTran(thys, lines, info, pos, last);
1103 break;
1104
1105 case SH_RE:
1106 showFillRE(thys, lines, info, pos, last);
1107 break;
1108
1109 case SH_FT:
1110 showFillFT(thys, lines, info, pos, last);
1111 break;
1112
1113 case SH_NOTE:
1114 showFillNote(thys, lines, info, pos, last);
1115 break;
1116
1117 default:
1118 ajFatal("Unknown descriptor type found in "
1119 "showFillLines: %d",type);
1120 }
1121 }
1122
1123 ajListIterDel(&diter);
1124
1125 return;
1126 }
1127
1128
1129
1130
1131 /* @funcstatic showMargin *****************************************************
1132 **
1133 ** Add a blank margin to the lines list
1134 **
1135 ** @param [r] thys [const EmbPShow] Show sequence object
1136 ** @param [u] lines [AjPList] list of lines to add to
1137 ** @return [void]
1138 **
1139 ** @release 1.0.0
1140 ** @@
1141 ******************************************************************************/
1142
showMargin(const EmbPShow thys,AjPList lines)1143 static void showMargin(const EmbPShow thys, AjPList lines)
1144 {
1145 AjPStr marginfmt;
1146
1147 marginfmt = ajStrNewRes(10);
1148
1149 /* variable width margin */
1150 if(thys->margin)
1151 {
1152 ajFmtPrintS(&marginfmt, "%%-%ds ", thys->margin-1);
1153 ajListstrPushAppend(lines, ajFmtStr(ajStrGetPtr(marginfmt), ""));
1154 }
1155
1156 ajStrDel(&marginfmt);
1157
1158 return;
1159 }
1160
1161
1162
1163
1164 /* @funcstatic showMarginNumber ***********************************************
1165 ** Add a margin containing a number to the lines list
1166 **
1167 ** @param [r] thys [const EmbPShow] Show sequence object
1168 ** @param [u] lines [AjPList] list of lines to add to
1169 ** @param [r] number [ajint] number to display
1170 ** @return [void]
1171 **
1172 ** @release 1.0.0
1173 ** @@
1174 ******************************************************************************/
1175
showMarginNumber(const EmbPShow thys,AjPList lines,ajint number)1176 static void showMarginNumber(const EmbPShow thys, AjPList lines, ajint number)
1177 {
1178 AjPStr marginfmt;
1179
1180 marginfmt = ajStrNewRes(10);
1181
1182 /* variable width margin containing a number */
1183 if(thys->margin)
1184 {
1185 ajFmtPrintS(&marginfmt, "%%%dd ", thys->margin-1);
1186 ajListstrPushAppend(lines, ajFmtStr(ajStrGetPtr(marginfmt), number));
1187 }
1188
1189 ajStrDel(&marginfmt);
1190
1191 return;
1192 }
1193
1194
1195
1196
1197 /* @funcstatic showPad ********************************************************
1198 **
1199 ** Add a set of space characters to the lines list to pad out an output line
1200 **
1201 ** @param [u] lines [AjPList] list of lines to add to
1202 ** @param [r] number [ajint] number of space characters to output
1203 ** @return [void]
1204 **
1205 ** @release 1.0.0
1206 ** @@
1207 ******************************************************************************/
1208
showPad(AjPList lines,ajint number)1209 static void showPad(AjPList lines, ajint number)
1210 {
1211 AjPStr marginfmt;
1212
1213 marginfmt=ajStrNewRes(10);
1214
1215 /* variable width pad of spaces */
1216 if(number>0)
1217 {
1218 ajFmtPrintS(&marginfmt, "%%-%ds", number);
1219 ajListstrPushAppend(lines, ajFmtStr(ajStrGetPtr(marginfmt), ""));
1220 }
1221
1222 ajStrDel(&marginfmt);
1223
1224 return;
1225 }
1226
1227
1228
1229
1230 /* @func embShowUpperRange ****************************************************
1231 **
1232 ** Uppercase a string from a sequence with a range
1233 ** I.e ranges of a sequence are to be uppercased.
1234 ** We have a small region of the original sequence in a string.
1235 ** We want to uppercase any bits of the string that are in the ranges.
1236 **
1237 ** @param [u] line [AjPStr *] line to uppercase if it is in the ranges
1238 ** @param [r] upperrange [const AjPRange] range of original sequence
1239 ** to uppercase
1240 ** @param [r] pos [ajuint] position in sequence that line starts at
1241 ** @return [void]
1242 **
1243 ** @release 1.13.0
1244 ** @@
1245 ******************************************************************************/
1246
embShowUpperRange(AjPStr * line,const AjPRange upperrange,ajuint pos)1247 void embShowUpperRange(AjPStr * line, const AjPRange upperrange, ajuint pos)
1248 {
1249 ajint nr;
1250 ajint i;
1251 ajuint j;
1252 ajuint start; /* start of next range */
1253 ajuint end; /* end of next range */
1254 ajint value; /* code for type of overlap of range with line */
1255 char *p; /* ptr to start of range in line to uppercase */
1256
1257 nr = ajRangeGetSize(upperrange);
1258
1259 for(i=0; i<nr; i++)
1260 {
1261 /* for each range in AjPRange upperrange */
1262 ajRangeElementGetValues(upperrange, i, &start, &end);
1263
1264 /* get type of overlap */
1265 value = ajRangeElementTypeOverlap(upperrange, i,
1266 pos, ajStrGetLen(*line));
1267
1268
1269 ajDebug("embShowUpperRange %d %u..%u pos:%u len:%u value:%d\n",
1270 i, start, end, pos, ajStrGetLen(*line), value);
1271
1272 /* complete overlap */
1273 if(value == 2)
1274 {
1275 ajStrFmtUpper(line);
1276
1277 return;
1278 }
1279 else if(value)
1280 {
1281 /* partial overlap */
1282 start--; /* change start,end from human-readable position*/
1283 end--;
1284
1285 if(start < pos)
1286 start = pos;
1287
1288 ajDebug("make uppercase start:%u end:%u pos:%u '%S'\n",
1289 start, end, pos, *line);
1290 p = ajStrGetuniquePtr(line)+start-pos;
1291
1292 for(j=start; *p && j<=end; j++, p++)
1293 {
1294 ajDebug("uppercase test pos:%u j:%u pos-j:%u\n",
1295 pos, j, pos-j);
1296
1297 if(j-pos < ajStrGetLen(*line))
1298 {
1299 ajDebug("uppercase char %u '%c'\n", pos-j, *p);
1300 *p = toupper((ajint) *p);
1301 }
1302 }
1303
1304 ajDebug("made uppercase start:%u pos:%u end:%u '%S'\n",
1305 start, end, pos, *line);
1306 }
1307 }
1308
1309 return;
1310 }
1311
1312
1313
1314
1315 /* @func embShowColourRange ***************************************************
1316 **
1317 ** colour a string from a sequence with a range
1318 ** I.e ranges of a sequence are to be coloured in HTML.
1319 ** We have a small region of the original sequence in a string.
1320 ** We want to colour any bits of the string that are in the ranges.
1321 **
1322 ** @param [u] line [AjPStr *] line to colour if it is in the ranges
1323 ** @param [r] colour [const AjPRange] range of original sequence to colour
1324 ** @param [r] pos [ajuint] position in sequence that line starts at
1325 ** @return [void]
1326 **
1327 ** @release 1.13.0
1328 ** @@
1329 ******************************************************************************/
1330
embShowColourRange(AjPStr * line,const AjPRange colour,ajuint pos)1331 void embShowColourRange(AjPStr * line, const AjPRange colour, ajuint pos)
1332 {
1333 ajint nr;
1334 ajint i;
1335 ajuint start; /* start of next range */
1336 ajuint end; /* end of next range */
1337 ajint istart;
1338 ajint iend;
1339 ajint value; /* code for type of overlap of
1340 range with line */
1341 AjPStr html = NULL;
1342 AjPStr col = NULL;
1343
1344 nr = ajRangeGetSize(colour);
1345
1346 for(i=0; i<nr; i++)
1347 {
1348 /* for each range in AjPRange colour */
1349 ajRangeElementGetValues(colour, i, &start, &end);
1350
1351 /* get type of overlap */
1352 value = ajRangeElementTypeOverlap(colour, i, pos, ajStrGetLen(*line));
1353
1354 /* partial or complete overlap */
1355 if(value)
1356 {
1357 istart = start - pos - 1;
1358 iend = end - pos - 1;
1359
1360 if(istart < 0)
1361 istart = 0;
1362
1363 if(iend > (ajint)ajStrGetLen(*line)-1)
1364 iend = ajStrGetLen(*line)-1;
1365
1366 /* start */
1367 ajStrAssignC(&html, "<font color=");
1368 ajRangeElementGetText(colour, i, &col);
1369
1370 if(ajStrGetLen(col))
1371 ajStrAppendS(&html, col);
1372 else
1373 {
1374 /* no colour, use 'red' as default */
1375 ajStrAppendC(&html, "red");
1376 }
1377
1378 ajStrAppendC(&html, ">");
1379 showInsertHTML(line, istart, html);
1380
1381 /* end */
1382 ajStrAssignC(&html, "</font>");
1383
1384 /* end+1 because want the tag after this position */
1385 showInsertHTML(line, iend+1, html);
1386 }
1387 }
1388
1389 ajStrDel(&col);
1390 ajStrDel(&html);
1391
1392 return;
1393 }
1394
1395
1396
1397
1398 /* @funcstatic showInsertHTML *************************************************
1399 **
1400 ** Insert a string at a position in another string
1401 ** The position ignores any inserted HTML tags (anything between '<>')
1402 ** For example, insert "*" at position 3 of "<html tag>0123"
1403 ** gives "<html tag>012*3"
1404 **
1405 ** If the insert position is past the end of the string, it inserts at the end.
1406 **
1407 ** @param [u] target [AjPStr *] HTMLised string to insert into
1408 ** @param [r] pos [ajuint] position (ignoring HTML tags) to insert at
1409 ** @param [r] insert [const AjPStr] string to insert
1410 ** @return [void]
1411 **
1412 ** @release 1.0.0
1413 ** @@
1414 ******************************************************************************/
1415
showInsertHTML(AjPStr * target,ajuint pos,const AjPStr insert)1416 static void showInsertHTML(AjPStr *target, ajuint pos, const AjPStr insert)
1417 {
1418 ajuint i;
1419 ajuint j;
1420 AjBool tag = ajFalse;
1421
1422 /* find the required position, not including tags */
1423 for(i=0, j=0; j<pos && i<ajStrGetLen(*target); i++)
1424 if(tag == ajFalse)
1425 {
1426 if(ajStrGetPtr(*target)[i] == '<')
1427 tag = ajTrue;
1428 else
1429 j++; /* count the non-tag characters */
1430 }
1431 else
1432 {
1433 if(ajStrGetPtr(*target)[i] == '>')
1434 tag = ajFalse;
1435 }
1436
1437 /* we may have some tags at this position which still need to be skippped */
1438 while (ajStrGetPtr(*target)[i] == '<')
1439 {
1440 while (ajStrGetPtr(*target)[i] != '>')
1441 i++;
1442 i++;
1443 }
1444
1445
1446 ajStrInsertS(target, i, insert);
1447
1448 return;
1449 }
1450
1451
1452
1453
1454 /* @funcstatic showFillSeq ****************************************************
1455 **
1456 ** Add this line's worth of sequence to the lines list
1457 **
1458 ** @param [r] thys [const EmbPShow] Show sequence object
1459 ** @param [u] lines [AjPList] list of lines to add to
1460 ** @param [r] info [const EmbPShowSeq] data on how to display the sequence data
1461 ** @param [r] pos [ajuint] current printing position in the sequence
1462 ** @param [r] last [ajuint] last printing position in the sequence
1463 ** @return [void]
1464 **
1465 ** @release 1.0.0
1466 ** @@
1467 ******************************************************************************/
1468
showFillSeq(const EmbPShow thys,AjPList lines,const EmbPShowSeq info,ajuint pos,ajuint last)1469 static void showFillSeq(const EmbPShow thys,
1470 AjPList lines, const EmbPShowSeq info,
1471 ajuint pos, ajuint last)
1472 {
1473 AjPStr line;
1474
1475 AjPStr line1; /* used to make the three-letter codes */
1476 AjPStr line2;
1477 AjPStr line3;
1478 const char *p;
1479 const char *p3;
1480 ajuint count;
1481 ajuint width;
1482
1483 ajDebug("showFillSeq\n");
1484
1485 line = ajStrNewRes(81);
1486 width = last - pos + 1;
1487
1488 /* variable width margin at left with optional number in it */
1489 if(info->number)
1490 showMarginNumber(thys, lines, pos+thys->offset);
1491 else
1492 showMargin(thys, lines);
1493
1494 /* get the bit of the sequence to display */
1495 ajStrAppendSubS(&line, ajSeqGetSeqS(thys->seq), pos, last);
1496
1497 /* change to three-letter code */
1498 if(!thys->nucleic && info->threeletter)
1499 {
1500
1501 line1=ajStrNewRes(81);
1502 line2=ajStrNewRes(81);
1503 line3=ajStrNewRes(81);
1504
1505 for(count=0, p=ajStrGetPtr(line);
1506 count < ajStrGetLen(line);
1507 count++, p++)
1508 if(*p == '*')
1509 {
1510 ajStrAppendC(&line1, "*");
1511 ajStrAppendC(&line2, "*");
1512 ajStrAppendC(&line3, "*");
1513 }
1514 else if(!isalpha((ajint)*p))
1515 {
1516 ajStrAppendC(&line1, "?");
1517 ajStrAppendC(&line2, "?");
1518 ajStrAppendC(&line3, "?");
1519 }
1520 else
1521 {
1522 p3 = embPropCharToThree(*p);
1523 ajStrAppendK(&line1, *p3);
1524 ajStrAppendK(&line2, *(p3+1));
1525 ajStrAppendK(&line3, *(p3+2));
1526 }
1527
1528 ajListstrPushAppend(lines, line1);
1529 line1 = NULL;
1530 ajStrDel(&line);
1531
1532 }
1533 else
1534 {
1535 /*
1536 ** nucleic or single-letter code
1537 ** do uppercase ranges
1538 */
1539 if(ajRangeCountOverlaps(info->upperrange, pos, width))
1540 embShowUpperRange(&line, info->upperrange, pos);
1541
1542 /* do colour ranges if we are displaying HTML*/
1543 if(thys->html && ajRangeCountOverlaps(info->highlight, pos, width))
1544 embShowColourRange(&line, info->highlight, pos);
1545
1546 ajListstrPushAppend(lines, line);
1547 line = NULL;
1548 }
1549
1550 /* optional number at right */
1551 if(info->number)
1552 {
1553 /*
1554 ** if the sequence has ended we might have to fill out the end
1555 ** with blanks
1556 */
1557 if(last >= ajSeqGetLen(thys->seq))
1558 {
1559 showPad(lines, thys->width - ajSeqGetLen(thys->seq) + pos);
1560 ajListstrPushAppend(lines,
1561 ajFmtStr(" %d",
1562 ajSeqGetLen(thys->seq)+thys->offset-1));
1563 }
1564 else
1565 ajListstrPushAppend(lines,
1566 ajFmtStr(" %d",
1567 pos+width+thys->offset-1));
1568 }
1569
1570 /* end the output line */
1571 ajListstrPushAppend(lines, ajFmtStr("\n"));
1572
1573
1574 /* if three-letter code, add the other 3-letter output lines */
1575 if(!thys->nucleic && info->threeletter)
1576 {
1577 showMargin(thys, lines);
1578 ajListstrPushAppend(lines, line2);
1579 line2 = NULL;
1580 ajListstrPushAppend(lines, ajFmtStr("\n"));
1581 showMargin(thys, lines);
1582 ajListstrPushAppend(lines, line3);
1583 line3 = NULL;
1584 ajListstrPushAppend(lines, ajFmtStr("\n"));
1585 }
1586
1587 return;
1588 }
1589
1590
1591
1592
1593 /* @funcstatic showFillBlank **************************************************
1594 **
1595 ** Add a blank line to the lines list
1596 **
1597 ** @param [r] thys [const EmbPShow] Show sequence object
1598 ** @param [u] lines [AjPList] list of lines to add to
1599 ** @param [r] info [const EmbPShowBlank] data on how to display the
1600 ** sequence data
1601 ** @param [r] pos [ajuint] current printing position in the sequence
1602 ** @param [r] last [ajuint] last printing position in the sequence
1603 ** @return [void]
1604 **
1605 ** @release 1.0.0
1606 ** @@
1607 ******************************************************************************/
1608
showFillBlank(const EmbPShow thys,AjPList lines,const EmbPShowBlank info,ajuint pos,ajuint last)1609 static void showFillBlank(const EmbPShow thys,
1610 AjPList lines, const EmbPShowBlank info,
1611 ajuint pos,ajuint last)
1612 {
1613 AjPStr line;
1614
1615 ajDebug("showFillBlank\n");
1616
1617 (void) thys; /* make it used */
1618 (void) info; /* make it used */
1619 (void) pos; /* make it used */
1620 (void) last; /* make it used */
1621
1622 line = ajStrNewRes(2);
1623
1624 ajStrAssignC(&line, "\n");
1625 ajListstrPushAppend(lines, line);
1626 line = NULL;
1627 return;
1628 }
1629
1630
1631
1632
1633 /* @funcstatic showFillTicks **************************************************
1634 **
1635 ** Add a tick line to the lines list
1636 **
1637 ** @param [r] thys [const EmbPShow] Show sequence object
1638 ** @param [u] lines [AjPList] list of lines to add to
1639 ** @param [r] info [const EmbPShowTicks] data on how to display the
1640 ** sequence data
1641 ** @param [r] pos [ajuint] current printing position in the sequence
1642 ** @param [r] last [ajuint] last printing position in the sequence
1643 ** @return [void]
1644 **
1645 ** @release 1.0.0
1646 ** @@
1647 ******************************************************************************/
1648
showFillTicks(const EmbPShow thys,AjPList lines,const EmbPShowTicks info,ajuint pos,ajuint last)1649 static void showFillTicks(const EmbPShow thys,
1650 AjPList lines, const EmbPShowTicks info,
1651 ajuint pos,ajuint last)
1652 {
1653 AjPStr line;
1654 ajuint i;
1655 ajuint offset;
1656 ajuint width;
1657
1658 ajDebug("showFillTicks\n");
1659
1660 (void) info; /* make it used */
1661
1662 line = ajStrNewRes(81);
1663 offset = thys->offset;
1664 width = last - pos + 1;
1665
1666
1667 /* make the ticks line */
1668 for(i=pos+offset; i<pos+offset+width; i++)
1669 if(!(i % 10))
1670 ajStrAppendC(&line, "|");
1671 else if(!(i % 5))
1672 ajStrAppendC(&line, ":");
1673 else
1674 ajStrAppendC(&line, "-");
1675
1676 showMargin(thys, lines);
1677 ajListstrPushAppend(lines, line);
1678 line = NULL;
1679 /* end the output ticks line */
1680 ajListstrPushAppend(lines, ajFmtStr("\n"));
1681
1682 return;
1683 }
1684
1685
1686
1687
1688 /* @funcstatic showFillTicknum ************************************************
1689 **
1690 ** Add a tick line numbers to the lines list
1691 **
1692 ** @param [r] thys [const EmbPShow] Show sequence object
1693 ** @param [u] lines [AjPList] list of lines to add to
1694 ** @param [r] info [const EmbPShowTicknum] data on how to display
1695 ** the sequence data
1696 ** @param [r] pos [ajuint] current printing position in the sequence
1697 ** @param [r] last [ajuint] last printing position in the sequence
1698 ** @return [void]
1699 **
1700 ** @release 1.0.0
1701 ** @@
1702 ******************************************************************************/
1703
showFillTicknum(const EmbPShow thys,AjPList lines,const EmbPShowTicknum info,ajuint pos,ajuint last)1704 static void showFillTicknum(const EmbPShow thys,
1705 AjPList lines, const EmbPShowTicknum info,
1706 ajuint pos, ajuint last)
1707 {
1708 AjPStr line;
1709 ajuint i;
1710 ajuint offset;
1711 ajuint width;
1712 ajuint pad;
1713
1714 ajDebug("showFillTicknum\n");
1715
1716 (void) info; /* make it used */
1717
1718 line = ajStrNewRes(81);
1719 offset = thys->offset;
1720 width = last - pos + 1;
1721
1722 showMargin(thys, lines);
1723 pad = 9 - ((pos+offset-1) % 10);
1724
1725 if(pad)
1726 showPad(lines, pad);
1727
1728 for(i=pos + offset + pad; i < pos+offset+width; i+=10)
1729 ajFmtPrintAppS(&line, "%-10d", i);
1730
1731 ajListstrPushAppend(lines, line);
1732 line = NULL;
1733 /* end the output line */
1734 ajListstrPushAppend(lines, ajFmtStr("\n"));
1735
1736 return;
1737 }
1738
1739
1740
1741
1742 /* @funcstatic showFillComp ***************************************************
1743 **
1744 ** Add thys line's worth of sequence complement to the lines list
1745 **
1746 ** @param [r] thys [const EmbPShow] Show sequence object
1747 ** @param [u] lines [AjPList] list of lines to add to
1748 ** @param [r] info [const EmbPShowComp] data on how to display the
1749 ** sequence data
1750 ** @param [r] pos [ajuint] current printing position in the sequence
1751 ** @param [r] last [ajuint] last printing position in the sequence
1752 ** @return [void]
1753 **
1754 ** @release 1.0.0
1755 ** @@
1756 ******************************************************************************/
1757
showFillComp(const EmbPShow thys,AjPList lines,const EmbPShowComp info,ajuint pos,ajuint last)1758 static void showFillComp(const EmbPShow thys,
1759 AjPList lines, const EmbPShowComp info,
1760 ajuint pos, ajuint last)
1761 {
1762 AjPStr line;
1763 ajuint width;
1764
1765 ajDebug("showFillComp\n");
1766
1767 line = ajStrNewRes(81);
1768 width = last - pos + 1;
1769
1770 /*
1771 ** do a quick check that we have a nucleic sequence
1772 ** - else just ignore this
1773 */
1774 if(!thys->nucleic)
1775 return;
1776
1777 /* variable width margin at left with optional number in it */
1778 if(info->number)
1779 showMarginNumber(thys, lines, pos+thys->offset);
1780 else
1781 showMargin(thys, lines);
1782
1783
1784 /* get the sequence at this position */
1785 ajStrAppendSubS(&line, ajSeqGetSeqS(thys->seq), pos, pos+width-1);
1786
1787 /* get the complement */
1788 ajSeqstrComplement(&line);
1789 ajListstrPushAppend(lines, line);
1790 line = NULL;
1791
1792 /* optional number at right */
1793 if(info->number)
1794 {
1795 /*
1796 ** if the sequence has ended we might have to fill
1797 ** out the end with blanks
1798 */
1799 if(last >= ajSeqGetLen(thys->seq))
1800 {
1801 showPad(lines, thys->width - ajSeqGetLen(thys->seq) + pos);
1802 ajListstrPushAppend(lines,
1803 ajFmtStr(" %d",
1804 ajSeqGetLen(thys->seq)+thys->offset-1));
1805 }
1806 else
1807 ajListstrPushAppend(lines, ajFmtStr(" %d",
1808 pos+width+thys->offset-1));
1809 }
1810
1811 /* end the output line */
1812 ajListstrPushAppend(lines, ajFmtStr("\n"));
1813
1814 return;
1815 }
1816
1817
1818
1819
1820 /* @funcstatic showFillTran ***************************************************
1821 **
1822 ** Add this line's worth of sequence translation to the lines list
1823 **
1824 ** @param [r] thys [const EmbPShow] Show sequence object
1825 ** @param [u] lines [AjPList] list of lines to add to
1826 ** @param [u] info [EmbPShowTran] data on how to display the
1827 ** sequence data
1828 ** @param [r] pos [ajuint] current printing position in the sequence
1829 ** @param [r] last [ajuint] last printing position in the sequence
1830 ** @return [void]
1831 **
1832 ** @release 1.0.0
1833 ** @@
1834 ******************************************************************************/
1835
showFillTran(const EmbPShow thys,AjPList lines,EmbPShowTran info,ajuint pos,ajuint last)1836 static void showFillTran(const EmbPShow thys,
1837 AjPList lines, EmbPShowTran info,
1838 ajuint pos, ajuint last)
1839 {
1840
1841 AjPStr line;
1842 AjPSeq tran = NULL;
1843 AjPSeq seq = NULL; /* local copy of sequence for translating ranges */
1844 AjPStr temp = NULL;
1845 AjPStr tmpaa =NULL; /* peptide expanded to 3-let code or by 2 spaces */
1846 AjPStr transeq =NULL; /* sequence copy for editing */
1847 ajint frame;
1848 ajuint framepad = 0; /* no. of spaces to pad to the correct frame pos */
1849 ajuint linepos;
1850 ajuint startpos; /* number at start of line */
1851 ajuint endpos; /* number at end of line */
1852 ajuint i;
1853 ajint j;
1854 ajint orflast;
1855
1856 ajDebug("showFillTran pos:%u last:%u\n", pos, last);
1857
1858 line = ajStrNewRes(81);
1859
1860 /*
1861 ** do a quick check that we have a nucleic sequence - else just
1862 ** ignore this
1863 */
1864 if(!thys->nucleic)
1865 return;
1866
1867
1868 /* if the translation has not yet been done, do it now - once only */
1869 if(!info->transeq)
1870 {
1871 /* translate a set of ranges ... using frame number */
1872 if(info->regions && ajRangeGetSize(info->regions))
1873 {
1874 frame = info->frame;
1875
1876 /* shift the translation to the correct frame */
1877 if(frame == 1 || frame == 5)
1878 framepad = 0;
1879 else if(frame == 2 || frame == 6)
1880 framepad = 1;
1881 else if(frame == 3 || frame == 4)
1882 framepad = 2;
1883
1884 framepad = 0;
1885 seq = ajSeqNewSeq(thys->seq);
1886 tran = ajRangeSeqExtractPep(info->regions, seq,
1887 info->trnTable, frame);
1888
1889 /* expand to fill line or change to three-letter code */
1890 if(info->threeletter)
1891 {
1892 tmpaa = embPropProt1to3(tran,framepad);
1893 ajSeqAssignSeqS(tran, tmpaa);
1894 }
1895 else
1896 {
1897 /* pad with 2 spaces after every residue */
1898 tmpaa = embPropProtGaps(tran,framepad);
1899 ajSeqAssignSeqS(tran,tmpaa);
1900 }
1901 ajStrDel(&tmpaa);
1902
1903 /*
1904 ** now put in spaces to align the translation to the
1905 ** sequence ranges
1906 */
1907 ajRangeSeqStuffPep(info->regions, tran, frame);
1908 ajStrSetClear(&temp);
1909 /* store the resulting translation in our descriptor structure */
1910 info->transeq = tran;
1911 ajSeqDel(&seq);
1912 }
1913 else
1914 {
1915 /* ... or just translate in the required frame */
1916
1917 /*
1918 ** change frames -1 to -3 to frames 4 to 6 for translation
1919 ** of complement (NB that really should say just 'complement', not
1920 ** 'reverse-complement' as we will be putting the resulting
1921 ** reversed peptide under the forward nucleic sequence.)
1922 */
1923 frame = info->frame;
1924
1925 if(frame < 0)
1926 frame = 3-frame;
1927
1928 /* do the translation */
1929 tran = ajTrnSeqOrig(info->trnTable, thys->seq, frame);
1930
1931 /* shift the translation to the correct frame */
1932 if(frame == 1 || frame == 5)
1933 framepad = 0;
1934 else if(frame == 2 || frame == 6)
1935 framepad = 1;
1936 else if(frame == 3 || frame == 4)
1937 framepad = 2;
1938
1939 /* convert inter-ORF regions to '-'s or put it in lower case*/
1940 orflast = -1;
1941
1942 /*
1943 for(i=0; i<ajSeqGetLen(tran); i++)
1944 if(ajStrGetPtr(ajSeqGetSeqS(tran))[i] == '*')
1945 {
1946 if(i-orflast < info->orfminsize+1)
1947 {
1948 if(info->lcinterorf)
1949 for(j=orflast+1; j<i; j++)
1950 ajStrGetPtr(ajSeqGetSeqS(tran))[j] =
1951 tolower((ajint) ajStrGetPtr(ajSeqGetSeqS(tran))
1952 [j]);
1953 else
1954 for(j=orflast+1; j<i; j++)
1955 ajStrGetPtr(ajSeqGetSeqS(tran))[j] = '-';
1956 }
1957 orflast = i;
1958 }
1959 */
1960
1961 /* Thomas version */
1962 if(frame < 4)
1963 {
1964 transeq = ajSeqGetSeqCopyS(tran);
1965
1966 for(i=0; i<ajStrGetLen(transeq); i++)
1967 if(ajStrGetCharPos(transeq,i) == '*')
1968 {
1969 if(i-orflast < info->orfminsize+1)
1970 {
1971 if(!(info->firstorf && orflast == -1))
1972 {
1973 j = orflast+1;
1974
1975 if(info->lcinterorf)
1976 ajStrFmtLowerSub(&transeq,j,i-1);
1977 else
1978 ajStrPasteCountK(&transeq,j,'-',i-j);
1979 }
1980 }
1981
1982 orflast = i;
1983 }
1984
1985 /* put the last ORF in lower case or convert it to -'s */
1986 if(i == ajStrGetLen(transeq) && !(info->lastorf)
1987 && i-orflast < info->orfminsize+1)
1988 {
1989 j = orflast+1;
1990 if(info->lcinterorf)
1991 ajStrFmtLowerSub(&transeq,j,i-1);
1992 else
1993 ajStrPasteCountK(&transeq,j,'-',i-j);
1994 }
1995
1996 ajSeqAssignSeqS(tran, transeq);
1997 ajStrDel(&transeq);
1998 }
1999 else /* frame 4,5,6 */
2000 {
2001 transeq = ajSeqGetSeqCopyS(tran);
2002
2003 for(i=0; i<ajStrGetLen(transeq); i++)
2004 if(ajStrGetCharPos(transeq,i) == '*')
2005 {
2006 if(i-orflast < info->orfminsize+1)
2007 if(!(info->lastorf && orflast == -1))
2008 {
2009 j = orflast+1;
2010 if(info->lcinterorf)
2011 ajStrFmtLowerSub(&transeq,j,i-1);
2012 else
2013 ajStrPasteCountK(&transeq,j,'-',i-j);
2014 }
2015
2016 orflast = i;
2017 }
2018
2019 /* put the first ORF in lower case or convert it to -'s */
2020 if(i == ajSeqGetLen(tran) && !(info->firstorf)
2021 && i-orflast < info->orfminsize+1)
2022 {
2023 j = orflast+1;
2024 if(info->lcinterorf)
2025 ajStrFmtLowerSub(&transeq,j,i-1);
2026 else
2027 ajStrPasteCountK(&transeq,j,'-',i-j);
2028 }
2029
2030 ajSeqAssignSeqS(tran, transeq);
2031 ajStrDel(&transeq);
2032 }
2033
2034 /* expand to fill line or change to three-letter code */
2035 if(info->threeletter)
2036 {
2037 if(info->frame > 0)
2038 tmpaa = embPropProt1to3(tran,framepad);
2039 else
2040 tmpaa = embPropProt1to3Rev(tran,framepad);
2041
2042 ajSeqAssignSeqS(tran,tmpaa);
2043 }
2044 else
2045 {
2046 tmpaa = embPropProtGaps(tran,framepad);
2047
2048 /* pad with 2 spaces after every residue */
2049 ajSeqAssignSeqS(tran,tmpaa);
2050 }
2051
2052 ajStrDel(&tmpaa);
2053 /* store the resulting translation in our descriptor structure */
2054 info->transeq = tran;
2055 }
2056
2057 }
2058
2059 /* get the sequence at this position */
2060 if(pos < ajSeqGetLen(info->transeq))
2061 ajStrAppendSubS(&line, ajSeqGetSeqS(info->transeq),
2062 pos, last);
2063
2064 /* get the number of the starting and ending amino-acid on this line */
2065 startpos = info->tranpos;
2066 endpos = info->tranpos;
2067
2068 for(linepos=0; linepos<ajStrGetLen(line); linepos++)
2069 /*
2070 ** only count the starting letter of 3-letter codes and don't
2071 ** count *'s
2072 */
2073 if(ajStrGetPtr(line)[linepos] >= 'A' &&
2074 ajStrGetPtr(line)[linepos] <= 'Z')
2075 info->tranpos++;
2076
2077 /* less than width in the line? Add blanks to pad it out */
2078 for(;linepos < thys->width; linepos++)
2079 ajStrAppendC(&line, " ");
2080
2081 /* if at least one residue, count it at start */
2082 if(info->tranpos != endpos)
2083 startpos++;
2084
2085
2086 /* variable width margin at left with optional number in it */
2087 if(info->number)
2088 showMarginNumber(thys, lines, startpos);
2089 else
2090 showMargin(thys, lines);
2091
2092
2093 /* put the translation line on the output list */
2094 ajListstrPushAppend(lines, line);
2095 line = NULL;
2096
2097 /* optional number at right */
2098 if(info->number)
2099 ajListstrPushAppend(lines, ajFmtStr(" %d", info->tranpos));
2100
2101 if(info->showframe)
2102 {
2103 frame = info->frame;
2104 if(frame < 0)
2105 frame = 3 - frame;
2106 ajListstrPushAppend(lines, ajFmtStr("%4s%d", "F", frame));
2107 }
2108
2109 /* end the output line */
2110 ajListstrPushAppend(lines, ajFmtStr("\n"));
2111
2112 return;
2113 }
2114
2115
2116
2117
2118 /* @funcstatic showFillRE *****************************************************
2119 **
2120 ** Add this line's worth of Restriction Enzyme cut sites to the lines list
2121 **
2122 ** @param [r] thys [const EmbPShow] Show sequence object
2123 ** @param [u] lines [AjPList] list of lines to add to
2124 ** @param [u] info [EmbPShowRE] data on how to display the RE cut sites
2125 ** @param [r] pos [ajuint] current printing position in the sequence
2126 ** @param [r] last [ajuint] last printing position in the sequence
2127 ** @return [void]
2128 **
2129 ** @release 1.0.0
2130 ** @@
2131 ******************************************************************************/
2132
showFillRE(const EmbPShow thys,AjPList lines,EmbPShowRE info,ajuint pos,ajuint last)2133 static void showFillRE(const EmbPShow thys,
2134 AjPList lines, EmbPShowRE info,
2135 ajuint pos, ajuint last)
2136 {
2137 ajDebug("showFillRE\n");
2138
2139 /*
2140 ** do a quick check that we have a nucleic sequence - else just ignore
2141 ** this
2142 */
2143 if(!thys->nucleic)
2144 return;
2145
2146 if(info->flat)
2147 showFillREflat(thys, lines, info, pos, last);
2148 else
2149 showFillREupright(thys, lines, info, pos, last);
2150
2151 return;
2152 }
2153
2154
2155
2156
2157 /* @funcstatic showFillREupright **********************************************
2158 **
2159 ** Add this line's worth of Restriction Enzyme cut sites to the lines list
2160 ** Display in upright sit-up-and-beg format
2161 **
2162 ** @param [r] thys [const EmbPShow] Show sequence object
2163 ** @param [u] lines [AjPList] list of lines to add to
2164 ** @param [u] info [EmbPShowRE] data on how to display the RE cut sites
2165 ** @param [r] pos [ajuint] current printing position in the sequence
2166 ** @param [r] last [ajuint] last printing position in the sequence
2167 ** @return [void]
2168 **
2169 ** @release 1.0.0
2170 ** @@
2171 ******************************************************************************/
2172
showFillREupright(const EmbPShow thys,AjPList lines,EmbPShowRE info,ajuint pos,ajuint last)2173 static void showFillREupright(const EmbPShow thys,
2174 AjPList lines, EmbPShowRE info,
2175 ajuint pos, ajuint last)
2176 {
2177 AjPStr line = NULL;
2178 AjPStr newline = NULL;
2179 AjPStr baseline; /* line holding first set of ticks */
2180 AjPList linelist; /* list of lines to fill */
2181 ajuint cut; /* the sites to display */
2182 AjIList liter; /* iterator for linelist */
2183 AjBool freespace; /* flag: found free space to print */
2184 EmbPMatMatch m = NULL; /* restriction enz match structure */
2185 AjIList miter; /* iterator for matches list */
2186 EmbPShowREsite sitenode; /* site node structure */
2187 AjIList siter; /* iterator for sites list */
2188 EmbPShowREsite s = NULL; /* site node structure */
2189 AjPStr tick = NULL; /* tick "|" string */
2190 ajint ln;
2191 void* sajb = NULL;
2192
2193 linelist = ajListstrNew();
2194 baseline = ajStrNew();
2195
2196 /* if not yet produced a sorted list of cut sites, do it now */
2197 if(info->sitelist == NULL)
2198 {
2199 info->sitelist = ajListNew();
2200
2201 miter = ajListIterNewread(info->matches);
2202
2203 while((m = ajListIterGet(miter)) != NULL)
2204 {
2205 /* store the first cut site in this sense */
2206 if(info->sense == 1) /* forward sense */
2207 cut = m->cut1;
2208 else /* reverse sense */
2209 cut = m->cut2;
2210
2211 cut--;
2212
2213 AJNEW0(sitenode);
2214 sitenode->pos = cut;
2215 sitenode->name = m->cod;
2216 ajListPushAppend(info->sitelist, sitenode);
2217
2218 /* now store the potential second cut site on this sense */
2219 if(info->sense == 1) /* forward sense */
2220 cut = m->cut3;
2221 else /* reverse sense */
2222 cut = m->cut4;
2223
2224 if(cut)
2225 {
2226 cut--;
2227 AJNEW0(sitenode);
2228 sitenode->pos = cut;
2229 sitenode->name = m->cod;
2230 ajListPushAppend(info->sitelist, sitenode);
2231 }
2232 }
2233
2234 ajListIterDel(&miter);
2235 ajListSort(info->sitelist, &showFillREuprightSort);
2236 }
2237
2238 ajStrAssignC(&tick, "|"); /* a useful string */
2239
2240 /* iterate through the site list */
2241 siter = ajListIterNewread(info->sitelist);
2242
2243 while((s = ajListIterGet(siter)) != NULL)
2244 {
2245 cut = s->pos;
2246
2247 /* ignore this match if nothing is to be displayed on this line */
2248 if(cut >= pos && cut <= last)
2249 {
2250
2251 /* convert to position in the line */
2252 cut = cut-pos;
2253
2254 /* put tick in base line */
2255 showOverPrint(&baseline, cut, tick);
2256
2257 /* work up list of lines */
2258 freespace = ajFalse;
2259
2260 /*
2261 ** potentially updating the nodes of linelist, so
2262 ** don't just iterate, use ajListstrPop and ajListstrPushApp
2263 ** to pop off the bottom and then push the altered node back on
2264 ** the top of the list
2265 */
2266 for(ln = (ajuint) ajListstrGetLength(linelist); ln>0; ln--)
2267 {
2268 ajListstrPop(linelist, &line);
2269 /*
2270 ** if not yet written the name in this set of
2271 ** iterations, see if if it can be done so now
2272 */
2273 if(!freespace)
2274 {
2275 /* if name space is clear, write name and break */
2276 if(showLineIsClear(&line, cut, cut+ajStrGetLen(s->name)))
2277 {
2278 showOverPrint(&line, cut, s->name);
2279
2280 /* flag to show we have written name */
2281 freespace = ajTrue;
2282 }
2283 else
2284 /*
2285 ** if cut site position character is space, change
2286 ** it to a tick
2287 */
2288 if(*(ajStrGetPtr(line)+cut) == ' ')
2289 showOverPrint(&line, cut, tick);
2290 }
2291
2292 ajListstrPushAppend(linelist, line);
2293 line = NULL;
2294
2295 /* end 'iteration' through lines */
2296 }
2297
2298
2299 /* if name was not written, append a new line and write name */
2300 if(!freespace)
2301 {
2302 newline=ajStrNew();
2303 showOverPrint(&newline, cut, s->name);
2304 ajListstrPushAppend(linelist, newline);
2305 newline = NULL;
2306 }
2307 }
2308 }
2309
2310 ajListIterDel(&siter);
2311
2312
2313 /* convert base line ticks to forward or reverse slashes */
2314 if(info->sense == 1) /* forward sense */
2315 ajStrExchangeSetCC(&baseline, "|", "\\");
2316 else /* reverse sense */
2317 ajStrExchangeSetCC(&baseline, "|", "/");
2318
2319
2320 /* put base line at start of lines list */
2321 ajListstrPush(linelist, baseline);
2322 baseline = NULL;
2323
2324 /*
2325 ** reverse the order of the lines if we are in the forward sense as
2326 ** then we get the ticks pointing downwards :-)
2327 */
2328 if(info->sense == 1) ajListstrReverse(linelist);
2329
2330 /* iterate through the lines and print them */
2331 liter = ajListIterNewread(linelist);
2332
2333 while((line = ajListIterGet(liter)) != NULL)
2334 {
2335 /* output to the lines list */
2336 /* variable width margin at left */
2337 /* with optional number in it */
2338 showMargin(thys, lines);
2339 /* put the translation line */
2340 /* on the output list */
2341 ajListstrPushAppend(lines, line);
2342 line = NULL;
2343 /* end the output line */
2344 ajListstrPushAppend(lines, ajFmtStr("\n"));
2345 }
2346
2347 ajListIterDel(&liter);
2348
2349 while(ajListPop(linelist,&sajb));
2350
2351 ajListstrFree(&linelist);
2352 ajStrDel(&tick);
2353
2354 return;
2355 }
2356
2357
2358
2359
2360 /* @funcstatic showFillREuprightSort ******************************************
2361 **
2362 ** Sort routine for showFillREupright - produces reverse cut site order
2363 **
2364 ** @param [r] a [const void*] First pos
2365 ** @param [r] b [const void*] Second pos
2366 ** @return [ajint] Comparison value. 0 if equal, -1 if first is lower,
2367 ** +1 if first is higher.
2368 **
2369 ** @release 1.0.0
2370 ** @@
2371 ******************************************************************************/
2372
showFillREuprightSort(const void * a,const void * b)2373 static ajint showFillREuprightSort(const void* a, const void* b)
2374 {
2375 ajint res;
2376
2377 res = (*(EmbPShowREsite const *)b)->pos -
2378 (*(EmbPShowREsite const *)a)->pos;
2379
2380 /* if the cut sites are equal, reverse sort by the length of the name */
2381 if(!res)
2382 res = ajStrGetLen((*(EmbPShowREsite const *)b)->name) -
2383 ajStrGetLen((*(EmbPShowREsite const *)a)->name);
2384
2385 return res;
2386 }
2387
2388
2389
2390
2391 /* @funcstatic showFillREflat *************************************************
2392 **
2393 ** Add this line's worth of Restriction Enzyme cut sites to the lines list
2394 ** Display in flat format with recognition sites
2395 **
2396 ** @param [r] thys [const EmbPShow] Show sequence object
2397 ** @param [u] lines [AjPList] list of lines to add to
2398 ** @param [r] info [const EmbPShowRE] data on how to display the RE cut sites
2399 ** @param [r] pos [ajuint] current printing position in the sequence
2400 ** @param [r] last [ajuint] last printing position in the sequence
2401 ** @return [void]
2402 **
2403 ** @release 1.0.0
2404 ** @@
2405 ******************************************************************************/
2406
showFillREflat(const EmbPShow thys,AjPList lines,const EmbPShowRE info,ajuint pos,ajuint last)2407 static void showFillREflat(const EmbPShow thys,
2408 AjPList lines, const EmbPShowRE info,
2409 ajuint pos, ajuint last)
2410 {
2411 AjPStr line = NULL;
2412 AjPStr line2 = NULL;
2413 AjPList linelist = NULL; /* list of lines to fill */
2414 ajuint start;
2415 ajuint end; /* start and end position of site */
2416 ajuint nameend; /* end position of name */
2417 ajuint base; /* base position of binding site */
2418 ajint cut1;
2419 ajint cut2;
2420 ajint cut3;
2421 ajint cut4;
2422 AjIList liter; /* iterator for linelist */
2423 AjPStr namestr = NULL; /* name of RE to insert into line */
2424 AjPStr sitestr = NULL; /* binding and cut site to insert */
2425 ajuint i;
2426 const char *claimchar = "*"; /* char used to stake a claim to */
2427 /* that position in the string */
2428 AjBool freespace; /* flag for found a free space to
2429 print in */
2430 EmbPMatMatch m = NULL; /* restriction enzyme match struct */
2431 AjIList miter; /* iterator for matches list */
2432 ajuint ln;
2433 void* sajb = NULL;
2434 ajuint width;
2435
2436 width = last - pos + 1;
2437
2438 linelist = ajListstrNew();
2439
2440 /* iterate through the list */
2441 miter = ajListIterNewread(info->matches);
2442
2443 while((m = ajListIterGet(miter)) != NULL)
2444 {
2445 /* get the start and end positions */
2446 cut1 = m->cut1;
2447 /* the display points back '<' at cut pos */
2448 cut2 = m->cut2+1;
2449 cut3 = m->cut3;
2450 cut4 = m->cut4;
2451
2452 if(m->cut4)
2453 cut4++; /* the display points back '<' at cut pos */
2454
2455 base = m->start;
2456 start = base;
2457
2458 ajDebug("showFillRE start:%d sense:%b plasmid:%b circ12:%b 34:%b\n",
2459 start, info->sense, info->plasmid, m->circ12, m->circ34);
2460 ajDebug(" cut1:%d 2:%d 3:%d 4:%d\n",
2461 cut1, cut2, cut3, cut4);
2462
2463 if(info->sense == 1)
2464 { /* forward sense */
2465 if(info->plasmid || !m->circ12)
2466 if(cut1 < (ajint)start)
2467 start = cut1;
2468
2469 if(info->plasmid || !m->circ34)
2470 if(cut3 && cut3 < (ajint)start)
2471 start = cut3;
2472 }
2473 else
2474 { /* reverse sense */
2475 if(info->plasmid || !m->circ12)
2476 if(cut2 < (ajint)start)
2477 start = cut2;
2478
2479 if(info->plasmid || !m->circ34)
2480 if(cut4 && cut4 < (ajint)start)
2481 start = cut4;
2482 }
2483
2484 end = base + ajStrGetLen(m->pat)-1;
2485 ajDebug("showFillRE end: %d base: %d patlen: %d pat: '%S'\n",
2486 end, base, ajStrGetLen(m->pat), m->pat);
2487
2488 nameend = base + ajStrGetLen(m->cod)-1;
2489
2490 if(info->sense == 1)
2491 { /* forward sense */
2492 ajDebug("showFillRE fwd end: %d cut1:%d cut3:%d\n",
2493 end, cut1, cut3);
2494
2495 if(info->plasmid || !m->circ12)
2496 if(cut1 > (ajint)end)
2497 end = cut1;
2498
2499 if(info->plasmid || !m->circ34)
2500 if(cut3 && cut3 > (ajint)end)
2501 end = cut3;
2502
2503 ajDebug("showFillRE fwd set end: %d\n",
2504 end);
2505 }
2506 else
2507 { /* reverse sense */
2508 ajDebug("showFillRE rev end: %d cut2:%d cut4:%d\n",
2509 end, cut2, cut4);
2510
2511 if(info->plasmid || !m->circ12)
2512 if(cut2 > (ajint)end)
2513 end = cut2;
2514
2515 if(info->plasmid || !m->circ34)
2516 if(cut4 && cut4 > (ajint)end)
2517 end = cut4;
2518
2519 ajDebug("showFillRE rev set end: %d\n",
2520 end);
2521 }
2522
2523 /* convert human-readable sequence positions to string positions */
2524 start--;
2525 end--;
2526 base--;
2527 nameend--;
2528
2529 ajDebug("showFillREFlat start:%d end:%d pos:%d width:%d\n",
2530 start, end, pos, width);
2531
2532 /* ignore this match if nothing is to be displayed on this line */
2533 if(start <= last && end >= pos)
2534 {
2535 ajDebug("showFillREFlat site within range\n");
2536
2537 /* make a standard name and site string to be chopped up later */
2538
2539 /* site string stuff */
2540 /* initial string of '.'s */
2541 sitestr = ajStrNew();
2542 ajStrAppendCountK(&sitestr, '.', end-start+1 );
2543 ajDebug("showFillREFlat ajStrAppKI '.' %d\n", end-start+1);
2544
2545 /*
2546 ** add on any claim characters required to stake a claim to
2547 ** positions used by the name
2548 */
2549 if(nameend > end)
2550 {
2551 ajStrAppendCountK(&sitestr, *claimchar, nameend-end);
2552 ajDebug("showFillREFlat ajStrAppKI '%c' %d\n",
2553 *claimchar, nameend-end);
2554 }
2555
2556 /* cover binding site with '='s */
2557 for(i=base-start; i<base-start+ajStrGetLen(m->pat); i++)
2558 ajStrPasteCountK(&sitestr, i, '=', 1);
2559
2560 ajDebug("showFillREFlat ajStrReplaceK '=' %d..%d\n",
2561 base-start, i-1);
2562
2563 /*
2564 ** I tried showing the pattern instead of '='s, but it looks
2565 ** awful - GWW 12 Jan 2000
2566 ** for(j=0, i=base-start; i<base-start+ajStrGetLen(m->pat);
2567 ** j++, i++)
2568 ** (ajStrGetPtr(sitestr)+i) = ajStrGetPtr(m->pat)[j];
2569 */
2570
2571 /* put in cut sites */
2572 if(info->sense == 1)
2573 { /* forward sense */
2574 if(info->plasmid || !m->circ12)
2575 {
2576 ajStrPasteCountK(&sitestr, (cut1-start-1), '>', 1);
2577 ajDebug("showFillREFlat ajStrReplaceK1 '>' %d\n",
2578 (cut1-start-1));
2579 }
2580
2581 if(info->plasmid || !m->circ34)
2582 {
2583 if(cut3)
2584 {
2585 ajStrPasteCountK(&sitestr, (cut3-start-1), '>', 1);
2586
2587 ajDebug("showFillREFlat ajStrReplaceK3 '>' %d\n",
2588 (cut3-start-1));
2589 }
2590 }
2591 }
2592 else
2593 { /* reverse sense */
2594 if(info->plasmid || !m->circ12)
2595 {
2596 ajStrPasteCountK(&sitestr, (cut2-start-1), '<', 1);
2597 ajDebug("showFillREFlat ajStrReplaceK2 '<' %d\n",
2598 (cut2-start-1));
2599 }
2600
2601 if(info->plasmid || !m->circ34)
2602 {
2603 if(cut4)
2604 {
2605 ajStrPasteCountK(&sitestr, (cut4-start-1), '<', 1);
2606 ajDebug("showFillREFlat ajStrReplaceK4 '<' %d\n",
2607 (cut4-start-1));
2608 }
2609 }
2610 }
2611
2612
2613 /* name string stuff */
2614 /* initial string of claimchar's */
2615 namestr = ajStrNew();
2616 ajStrAppendCountK(&namestr, *claimchar, end-start+1 );
2617 ajDebug("showFillREFlat ajStrAppKI name '%c' %d\n",
2618 *claimchar, end-start+1 );
2619
2620 if(nameend > end)
2621 {
2622 ajStrAppendCountK(&namestr, *claimchar, nameend-end);
2623 ajDebug("showFillREFlat ajStrAppKI nameend '%c' %d\n",
2624 *claimchar, nameend-end );
2625 }
2626
2627 /* insert the name in the namestr */
2628 ajStrPasteS(&namestr, (base-start), m->cod);
2629
2630 /* now chop up the name and site strings to fit in the line */
2631
2632 /* is the feature completely within the line */
2633 if(start >= pos && end <= last)
2634 {
2635 /*
2636 * add on an extra couple of claim chars to make a space
2637 * between adjacent matches
2638 */
2639 ajStrAppendC(&sitestr, claimchar);
2640 ajStrAppendC(&sitestr, claimchar);
2641
2642 }
2643 else if(start < pos && end <= last)
2644 {
2645 /* starts before the line. cut off the start */
2646 ajStrKeepRange(&sitestr, pos-start, ajStrGetLen(sitestr)-1);
2647
2648 /*
2649 ** add on an extra couple of claim chars to make a space
2650 ** between adjacent matches
2651 */
2652 ajStrAppendC(&sitestr, claimchar);
2653 ajStrAppendC(&sitestr, claimchar);
2654
2655 /*
2656 ** if the base position is not displayed, move the name to
2657 ** the start
2658 */
2659 if(base < pos)
2660 {
2661 ajStrAssignS(&namestr, m->cod);
2662 ajStrAppendC(&namestr, claimchar);
2663 ajStrAppendC(&namestr, claimchar);
2664
2665 /*
2666 ** add claim characters to end of namestring if
2667 ** sitestring is longer, and vice versa
2668 */
2669 if(ajStrGetLen(namestr) < ajStrGetLen(sitestr))
2670 ajStrAppendCountK(&namestr, *claimchar,
2671 ajStrGetLen(sitestr)-
2672 ajStrGetLen(namestr));
2673 if(ajStrGetLen(namestr) > ajStrGetLen(sitestr))
2674 ajStrAppendCountK(&sitestr, *claimchar,
2675 ajStrGetLen(namestr)-
2676 ajStrGetLen(sitestr));
2677 }
2678 else
2679 /*
2680 ** cut off the start of the name string to make it line
2681 ** up with the sitestr
2682 */
2683 ajStrKeepRange(&namestr, pos-start, ajStrGetLen(namestr)-1);
2684
2685 /* make it display from the start of the line */
2686 start = pos;
2687
2688
2689 }
2690 else if(start >= pos && end > last)
2691 {
2692 /* ends after the line. cut off the end */
2693 ajStrKeepRange(&sitestr, 0, last - start);
2694 /*
2695 ** if the base position is not displayed, move the name
2696 ** to the start
2697 */
2698 if(base > last)
2699 {
2700 ajStrAssignS(&namestr, m->cod);
2701 ajStrAppendC(&namestr, claimchar);
2702 ajStrAppendC(&namestr, claimchar);
2703
2704 /*
2705 ** add claim characters to end of namestring if
2706 ** sitestring is longer, and vice versa
2707 */
2708 if(ajStrGetLen(namestr) < ajStrGetLen(sitestr))
2709 ajStrAppendCountK(&namestr, *claimchar,
2710 ajStrGetLen(sitestr)-
2711 ajStrGetLen(namestr));
2712 if(ajStrGetLen(namestr) > ajStrGetLen(sitestr))
2713 ajStrAppendCountK(&sitestr, *claimchar,
2714 ajStrGetLen(namestr)-
2715 ajStrGetLen(sitestr));
2716 }
2717
2718 /* make it display to the end of the line */
2719 end = last;
2720
2721
2722 }
2723 else if(start < pos && end > last)
2724 {
2725 /* completely overlaps the line! cut off the start and end */
2726 ajStrKeepRange(&sitestr, pos-start, last-start);
2727
2728 /*
2729 ** if the base position is not displayed, move the name to
2730 ** the start
2731 */
2732 if(base < pos)
2733 {
2734 ajStrAssignS(&namestr, m->cod);
2735 ajStrAppendC(&namestr, claimchar);
2736 ajStrAppendC(&namestr, claimchar);
2737
2738 /*
2739 ** add claim characters to end of namestring if
2740 ** sitestring is longer, and vice versa
2741 */
2742 if(ajStrGetLen(namestr) < ajStrGetLen(sitestr))
2743 ajStrAppendCountK(&namestr, *claimchar,
2744 ajStrGetLen(sitestr)-
2745 ajStrGetLen(namestr));
2746 if(ajStrGetLen(namestr) > ajStrGetLen(sitestr))
2747 ajStrAppendCountK(&sitestr, *claimchar,
2748 ajStrGetLen(namestr)-
2749 ajStrGetLen(sitestr));
2750 }
2751 else
2752 {
2753 /*
2754 ** cut off the start of the name string to make it line
2755 ** up with the sitestr
2756 */
2757 ajStrKeepRange(&namestr, pos-start,
2758 /* ...or should this be , */
2759 /* last-start); */
2760 ajStrGetLen(namestr)-1);
2761 }
2762
2763 /* make it display from the start of the line */
2764 start = pos;
2765 end = last;
2766 }
2767 else
2768 {
2769 ajDebug("Shouldn't get to here!");
2770 continue;
2771 }
2772
2773 /* work up list of lines */
2774 freespace = ajFalse;
2775
2776 /*
2777 ** potentially updating the nodes of linelist, so
2778 ** don't just iterate, use ajListstrPop and ajListstrPushApp
2779 ** to pop off the bottom and then push the altered node back on
2780 ** the top of the list
2781 */
2782 for(ln = (ajuint) ajListstrGetLength(linelist); ln>0; ln--)
2783 {
2784 ajListstrPop(linelist, &line); /* get the site line */
2785 ajListstrPop(linelist, &line2); /* get the name line */
2786
2787 /*
2788 ** if not yet written the name in this set of
2789 ** iterations, see if can be done now
2790 */
2791 if(!freespace)
2792 {
2793 if(showLineIsClear(&line, start-pos, end-pos))
2794 {
2795 showOverPrint(&line, start-pos, sitestr);
2796 showOverPrint(&line2, start-pos, namestr);
2797 /* flag to show name written */
2798 freespace = ajTrue;
2799 }
2800 }
2801
2802 ajListstrPushAppend(linelist, line);
2803 ajListstrPushAppend(linelist, line2);
2804 line = NULL;
2805 line2 = NULL;
2806 /* end 'iteration' through lines */
2807 }
2808
2809 /*
2810 ** if didn't find a clear region to print in, append two new
2811 ** strings and print in them
2812 */
2813 if(!freespace)
2814 {
2815 line=ajStrNew();
2816
2817 /* fill with spaces */
2818 ajStrAppendCountK(&line, ' ', width);
2819 line2=ajStrNew();
2820
2821 /* fill with spaces */
2822 ajStrAppendCountK(&line2, ' ', width);
2823
2824 showOverPrint(&line, start-pos, sitestr);
2825 showOverPrint(&line2, start-pos, namestr);
2826 ajListstrPushAppend(linelist, line);
2827 ajListstrPushAppend(linelist, line2);
2828 line = NULL;
2829 line2 = NULL;
2830 }
2831
2832 ajStrDel(&namestr);
2833 ajStrDel(&sitestr);
2834 }
2835 }
2836
2837 ajListIterDel(&miter);
2838
2839
2840 /*
2841 ** reverse the order of the lines if we are in the forward sense as then
2842 ** we get the most densely populated lines at the bottom closest to the
2843 ** sequence (and we get the names above the cut-sites)
2844 */
2845 if(info->sense == 1)
2846 ajListstrReverse(linelist);
2847
2848 /* iterate through the lines and print them */
2849 liter = ajListIterNewread(linelist);
2850
2851 while((line = ajListIterGet(liter)) != NULL)
2852 {
2853 /*
2854 ** convert claim characters in the line to spaces as these were
2855 ** used to stake a claim to the space
2856 */
2857 ajStrExchangeSetCC(&line, claimchar, " ");
2858
2859 /*
2860 ** remove trailing spaces - these can be very long in namestr when
2861 ** the cut and recognition sites are widely separated and so many
2862 ** claimchars have been appended
2863 */
2864 ajStrTrimEndC(&line, " ");
2865
2866 showMargin(thys, lines);
2867 ajListstrPushAppend(lines, line);
2868 line = NULL;
2869 ajListstrPushAppend(lines, ajFmtStr("\n"));
2870 }
2871
2872 ajListIterDel(&liter);
2873
2874
2875 while(ajListPop(linelist,&sajb));
2876
2877 ajListstrFree(&linelist);
2878
2879 return;
2880 }
2881
2882
2883
2884
2885 /* @funcstatic showFillFT *****************************************************
2886 **
2887 ** Add this line's worth of features to the lines list
2888 ** NB. the 'source' feature is always ignored
2889 **
2890 ** @param [r] thys [const EmbPShow] Show sequence object
2891 ** @param [u] lines [AjPList] list of lines to add to
2892 ** @param [r] info [const EmbPShowFT] data on how to display the features
2893 ** @param [r] pos [ajuint] current printing position in the sequence
2894 ** @param [r] last [ajuint] last printing position in the sequence
2895 ** @return [void]
2896 **
2897 ** @release 1.0.0
2898 ** @@
2899 ******************************************************************************/
2900
showFillFT(const EmbPShow thys,AjPList lines,const EmbPShowFT info,ajuint pos,ajuint last)2901 static void showFillFT(const EmbPShow thys,
2902 AjPList lines, const EmbPShowFT info,
2903 ajuint pos, ajuint last)
2904 {
2905
2906
2907 AjIList iter = NULL;
2908 AjPFeature gf = NULL;
2909
2910 AjPStr line = NULL;
2911 AjPStr line2 = NULL;
2912 AjPList linelist = NULL; /* list of lines to fill */
2913 ajuint start;
2914 ajuint end;
2915 ajuint namestart;
2916 ajuint nameend; /* start and end position of namestr */
2917 AjIList liter; /* iterator for linelist */
2918 AjPStr namestr = NULL; /* name of feature to insert into line */
2919 AjPStr linestr = NULL; /* line graphics to insert */
2920 const char *claimchar = "*"; /* char used to stake a claim to */
2921 /* that position in the string */
2922 AjBool freespace; /* flag for found a free space to
2923 print in */
2924 ajuint ln;
2925 void* sajb = NULL;
2926
2927 ajuint width;
2928
2929 width = last - pos + 1;
2930
2931 ajDebug("showFillFT\n");
2932 linelist = ajListstrNew();
2933
2934 /*
2935 ** if feat is NULL then there are no features associated with this
2936 ** sequence
2937 */
2938 if(!info->feat)
2939 return;
2940
2941
2942 /* iterate through the features */
2943 if(info->feat->Features)
2944 {
2945 iter = ajListIterNewread(info->feat->Features) ;
2946
2947 while(!ajListIterDone(iter))
2948 {
2949 gf = ajListIterGet(iter) ;
2950
2951 /* ignore remote IDs */
2952 if(!ajFeatIsLocal(gf))
2953 continue;
2954
2955 /* don't output the 'source' feature */
2956 if(!ajStrCmpC(ajFeatGetType(gf), "source"))
2957 continue;
2958
2959 /*
2960 ** check that the feature is within the line to display (NB.
2961 ** Working in human coordinates here: 1 to SeqLength,
2962 ** not 0 to SeqLength-1)
2963 */
2964 if(pos >= ajFeatGetEnd(gf) ||
2965 last <= ajFeatGetStart(gf))
2966 continue;
2967
2968 /* prepare name string */
2969 namestr = ajStrNew();
2970 ajStrAssignS(&namestr, ajFeatGetType(gf));
2971
2972 /* add tags to namestr*/
2973 showAddTags(&namestr, gf, ajTrue);
2974
2975 /*
2976 ** note the start and end positions of the name and line
2977 ** graphics
2978 */
2979 start = (ajFeatGetStart(gf)-1<pos) ?
2980 pos : ajFeatGetStart(gf)-1;
2981 end = (ajFeatGetEnd(gf)-1>last) ?
2982 last : ajFeatGetEnd(gf)-1;
2983
2984 /* print the name starting with the line */
2985 namestart = start;
2986 nameend = start + ajStrGetLen(namestr)-1;
2987
2988 /* shift long namestr back if longer than the line when printed */
2989 if(nameend > last+thys->margin)
2990 {
2991 if(ajStrGetLen(namestr) > end-pos+1)
2992 {
2993 namestart = pos;
2994 nameend = pos + ajStrGetLen(namestr) -1;
2995
2996 /*
2997 ** it is shifted back to the start of the display line
2998 ** is it still longer than the line? truncate it
2999 */
3000 if(nameend > thys->width-1+thys->margin)
3001 {
3002 ajStrTruncateLen(&namestr, thys->width-1+thys->margin);
3003 nameend = pos+thys->width-1+thys->margin;
3004 }
3005 }
3006 else
3007 {
3008 namestart = end - ajStrGetLen(namestr)+1;
3009 nameend = namestart + ajStrGetLen(namestr)-1;
3010 }
3011 }
3012
3013 /*
3014 ** add on any claim characters required to stake a claim to
3015 ** positions used by the line graphics
3016 */
3017 if(end > nameend)
3018 {
3019 ajStrAppendCountK(&namestr, *claimchar, end-nameend);
3020 nameend = end;
3021 }
3022
3023 /*
3024 ** add on a couple more claim characters to space out the
3025 ** features
3026 */
3027 ajStrAppendCountK(&namestr, *claimchar, 2);
3028 nameend += 2;
3029
3030 /* prepare line string */
3031 /* initial string of '='s */
3032 linestr = ajStrNew();
3033 ajStrAppendCountK(&linestr, '=', end-start+1 );
3034
3035 /* put in end position characters */
3036 if(ajFeatGetStart(gf)-1>=pos)
3037 ajStrPasteCountK(&linestr,0, '|', 1);
3038
3039 if(ajFeatGetEnd(gf)-1<=last)
3040 ajStrPasteCountK(&linestr, (end-start), '|', 1);
3041
3042
3043 /* work up list of lines */
3044 freespace = ajFalse;
3045
3046 /*
3047 ** iterate through list of existing lines to find no overlap
3048 ** with existing lines we will be potentially updating the
3049 ** nodes of linelist, so don't just iterate, use ajListstrPop
3050 ** and ajListstrPushApp to pop off the bottom and then push
3051 ** the altered node back on the top of the list
3052 */
3053 for(ln = (ajuint) ajListstrGetLength(linelist); ln>0; ln--)
3054 {
3055 /* get the linestr line */
3056 ajListstrPop(linelist, &line);
3057 /* get the namestr line */
3058 ajListstrPop(linelist, &line2);
3059
3060 /*
3061 ** if not yet written the name in this set of
3062 ** iterations, see if it can be done now
3063 */
3064 if(!freespace)
3065 {
3066 /* if name space is clear, write namestr and sitestr */
3067 if(showLineIsClear(&line2, start-pos, end-pos) &&
3068 showLineIsClear(&line2, namestart-pos, nameend-pos))
3069 {
3070 showOverPrint(&line, start-pos, linestr);
3071 showOverPrint(&line2, namestart-pos, namestr);
3072 /* flag to show name written */
3073 freespace = ajTrue;
3074 }
3075 }
3076
3077 ajListstrPushAppend(linelist, line);
3078 ajListstrPushAppend(linelist, line2);
3079 line = NULL;
3080 line2 = NULL;
3081 /* end 'iteration' through lines */
3082 }
3083
3084 /*
3085 ** if didn't find a clear region to print in, append two new
3086 ** strings and print in them
3087 */
3088 if(!freespace)
3089 {
3090 line=ajStrNew();
3091 /* fill with spaces */
3092 ajStrAppendCountK(&line, ' ', width);
3093 line2=ajStrNew();
3094 /* fill with spaces */
3095 ajStrAppendCountK(&line2, ' ', width);
3096
3097 showOverPrint(&line, start-pos, linestr);
3098 showOverPrint(&line2, namestart-pos, namestr);
3099 ajListstrPushAppend(linelist, line);
3100 ajListstrPushAppend(linelist, line2);
3101 line = NULL;
3102 line2 = NULL;
3103 }
3104
3105 ajStrDel(&namestr);
3106 ajStrDel(&linestr);
3107 }
3108 ajListIterDel(&iter);
3109 }
3110
3111 /* iterate through the lines and print them */
3112 liter = ajListIterNewread(linelist);
3113 while((line = ajListIterGet(liter)) != NULL)
3114 {
3115 /*
3116 ** convert claim characters in the line to spaces as these were
3117 ** used to stake a claim to the space
3118 */
3119 ajStrExchangeSetCC(&line, claimchar, " ");
3120
3121 /* remove trailing spaces - these can be very long */
3122 ajStrTrimEndC(&line, " ");
3123
3124 /*
3125 ** output to the lines list
3126 ** variable width margin at left
3127 */
3128 showMargin(thys, lines);
3129
3130 /*
3131 ** with optional number in it
3132 ** put the translation line on the output list
3133 */
3134 ajListstrPushAppend(lines, line);
3135 line = NULL;
3136 /* end output line */
3137 ajListstrPushAppend(lines, ajFmtStr("\n"));
3138 }
3139
3140 ajListIterDel(&liter);
3141
3142
3143 while(ajListPop(linelist,&sajb));
3144
3145 ajListstrFree(&linelist);
3146
3147 return;
3148 }
3149
3150
3151
3152
3153 /* @funcstatic showFillNote ***************************************************
3154 **
3155 ** Add this line's worth of user annotation to the lines list
3156 **
3157 ** @param [r] thys [const EmbPShow] Show sequence object
3158 ** @param [u] lines [AjPList] list of lines to add to
3159 ** @param [r] info [const EmbPShowNote] data on how to display the annotation
3160 ** @param [r] pos [ajuint] current printing position in the sequence
3161 ** @param [r] last [ajuint] last printing position in the sequence
3162 ** @return [void]
3163 **
3164 ** @release 2.1.0
3165 ** @@
3166 ******************************************************************************/
showFillNote(const EmbPShow thys,AjPList lines,const EmbPShowNote info,ajuint pos,ajuint last)3167 static void showFillNote(const EmbPShow thys,
3168 AjPList lines, const EmbPShowNote info,
3169 ajuint pos, ajuint last)
3170 {
3171
3172 AjPStr line = NULL;
3173 AjPStr line2 = NULL;
3174 AjPList linelist = NULL; /* list of lines to fill */
3175 ajuint start;
3176 ajuint end; /* start and end position of linestr */
3177 ajuint namestart;
3178 ajuint nameend; /* start and end position of namestr */
3179 AjIList liter; /* iterator for linelist */
3180 AjPStr namestr = NULL; /* name of feature to insert into line */
3181 AjPStr linestr = NULL; /* line graphics to insert */
3182 const char *claimchar = "*"; /* char used to stake a claim to */
3183 /* that position in the string */
3184 AjBool freespace; /* flag for found a free space to print in */
3185 ajint ln;
3186 void* sajb = NULL;
3187
3188 ajuint count; /* count of annotation region */
3189 ajuint rstart;
3190 ajuint rend; /* region start and end */
3191 ajuint width;
3192
3193 width = last - pos + 1;
3194
3195 ajDebug("showFillFT\n");
3196 linelist = ajListstrNew();
3197
3198 /* count through the annotation regions */
3199 if(info->regions && ajRangeGetSize(info->regions))
3200 {
3201 for(count = 0; count < ajRangeGetSize(info->regions); count++)
3202 {
3203 ajRangeElementGetValues(info->regions, count, &rstart, &rend);
3204
3205 /*
3206 ** check that the region is within the line to display
3207 */
3208 if(pos >= rend || last <= rstart)
3209 continue;
3210
3211 /* get annotation string */
3212 ajRangeElementGetText(info->regions, count, &namestr);
3213
3214 /*
3215 ** note the start and end positions of the name and line
3216 ** graphics
3217 */
3218 start = (rstart-1<pos) ? pos : rstart-1;
3219 end = (rend-1>last) ? last :
3220 rend-1;
3221
3222 /* print the name starting with the line */
3223 namestart = start;
3224 nameend = start + ajStrGetLen(namestr)-1;
3225
3226 /* shift long namestr back if longer than the line when printed */
3227 if(nameend >last+thys->margin)
3228 {
3229 if(ajStrGetLen(namestr) > end-pos+1)
3230 {
3231 namestart = pos;
3232 nameend = pos + ajStrGetLen(namestr) -1;
3233
3234 /*
3235 ** it is shifted back to the start of the display line
3236 ** is it still longer than the line? truncate it
3237 */
3238 if(nameend > width-1+thys->margin)
3239 {
3240 ajStrTruncateLen(&namestr, width-1+thys->margin);
3241 nameend = last+thys->margin;
3242 }
3243 }
3244 else
3245 {
3246 namestart = end - ajStrGetLen(namestr)+1;
3247 nameend = namestart + ajStrGetLen(namestr)-1;
3248 }
3249 }
3250
3251 /*
3252 ** add on any claim characters required to stake a claim to
3253 ** positions used by the line graphics
3254 */
3255 if(end > nameend)
3256 {
3257 ajStrAppendCountK(&namestr, *claimchar, end-nameend);
3258 nameend = end;
3259 }
3260
3261 /*
3262 ** add on a couple more claim characters to space out the
3263 ** features
3264 */
3265 ajStrAppendCountK(&namestr, *claimchar, 2);
3266 nameend += 2;
3267
3268 /*
3269 ** prepare line string
3270 ** initial string of '-'s
3271 */
3272 linestr = ajStrNew();
3273 ajStrAppendCountK(&linestr, '-', end-start+1 );
3274
3275 /* put in end position characters */
3276 if(rstart-1>=pos)
3277 ajStrPasteCountK(&linestr, 0, '|', 1);
3278
3279 if(rend-1<=last)
3280 ajStrPasteCountK(&linestr, (end-start), '|', 1);
3281
3282 /* work up list of lines */
3283 freespace = ajFalse;
3284
3285 /*
3286 ** iterate through list of existing lines to find no overlap
3287 ** with existing lines we will be potentially updating the
3288 ** nodes of linelist, so don't just iterate, use ajListstrPop
3289 ** and ajListstrPushApp to pop off the bottom and then push
3290 ** the altered node back on the top of the list
3291 */
3292 for(ln = (ajuint) ajListstrGetLength(linelist); ln>0; ln--)
3293 {
3294 /* linestr line */
3295 ajListstrPop(linelist, &line);
3296 /* namestr line */
3297 ajListstrPop(linelist, &line2);
3298
3299 /*
3300 * if not yet written the name in this set of
3301 * iterations, see if it can be done now
3302 */
3303 if(!freespace)
3304 {
3305 /* if name space is clear, write namestr and sitestr */
3306 if(showLineIsClear(&line2, start-pos, end-pos) &&
3307 showLineIsClear(&line2, namestart-pos, nameend-pos))
3308 {
3309 showOverPrint(&line, start-pos, linestr);
3310 showOverPrint(&line2, namestart-pos, namestr);
3311
3312 /* flag to show name written */
3313 freespace = ajTrue;
3314 }
3315 }
3316
3317 ajListstrPushAppend(linelist, line);
3318 ajListstrPushAppend(linelist, line2);
3319 line = NULL;
3320 line2 = NULL;
3321 /* end 'iteration' through lines */
3322 }
3323
3324 /*
3325 ** if we didn't find a clear region to print in, append two new
3326 ** strings and print in them
3327 */
3328 if(!freespace)
3329 {
3330 line=ajStrNew();
3331 /* fill with spaces */
3332 ajStrAppendCountK(&line, ' ', width);
3333 line2=ajStrNew();
3334
3335 /* fill with spaces */
3336 ajStrAppendCountK(&line2, ' ', width);
3337
3338 showOverPrint(&line, start-pos, linestr);
3339
3340 showOverPrint(&line2, namestart-pos, namestr);
3341 ajListstrPushAppend(linelist, line);
3342 ajListstrPushAppend(linelist, line2);
3343 line = NULL;
3344 line2 = NULL;
3345 }
3346
3347 ajStrDel(&namestr);
3348 ajStrDel(&linestr);
3349 }
3350 }
3351
3352 /* iterate through the lines and print them */
3353 liter = ajListIterNewread(linelist);
3354
3355 while((line = ajListIterGet(liter)) != NULL)
3356 {
3357 /* convert claim characters in the line to spaces as these were
3358 ** used to stake a claim to the space
3359 */
3360 ajStrExchangeSetCC(&line, claimchar, " ");
3361
3362 /* remove trailing spaces - these can be very long */
3363 ajStrTrimEndC(&line, " ");
3364
3365 /*
3366 ** output to the lines list
3367 ** variable width margin at left
3368 */
3369 showMargin(thys, lines);
3370
3371 /*
3372 ** with optional number in it
3373 ** put the translation line on the output list
3374 */
3375 ajListstrPushAppend(lines, line);
3376 line = NULL;
3377 /* end output line */
3378 ajListstrPushAppend(lines, ajFmtStr("\n"));
3379 }
3380 ajListIterDel(&liter);
3381
3382
3383 while(ajListPop(linelist,&sajb));
3384
3385 ajListstrFree(&linelist);
3386
3387 return;
3388 }
3389
3390
3391
3392
3393 /* @funcstatic showOverPrint **************************************************
3394 **
3395 ** Overwrite (appending if necessary) a portion of a string with another
3396 **
3397 ** @param [u] target [AjPStr *] target string to overwrite
3398 ** @param [r] start [ajint] start position in target to begin overwriting at
3399 ** @param [u] insert [AjPStr] string to overwrite with
3400 ** @return [void]
3401 **
3402 ** @release 1.0.0
3403 ** @@
3404 ******************************************************************************/
3405
showOverPrint(AjPStr * target,ajint start,AjPStr insert)3406 static void showOverPrint(AjPStr *target, ajint start, AjPStr insert)
3407 {
3408 /*
3409 ** if start position of insert is less than length of target, pad it out
3410 ** with space characters to get the required length
3411 */
3412
3413 if(ajStrGetLen(*target) < start+ajStrGetLen(insert))
3414 ajStrAppendCountK(target, ' ',
3415 start+ajStrGetLen(insert) - ajStrGetLen(*target));
3416
3417 /* overwrite the remaining characters */
3418 ajStrPasteS(target, start, insert);
3419
3420 return;
3421 }
3422
3423
3424
3425
3426 /* @funcstatic showLineIsClear ************************************************
3427 **
3428 ** Checks that a section of a string is clear to print in (only has blanks in)
3429 **
3430 ** @param [u] line [AjPStr *] target string to check
3431 ** @param [r] start [ajint] start position in target to begin checking at
3432 ** @param [r] end [ajint] end position in target to check
3433 ** @return [AjBool] ajTrue on success
3434 **
3435 ** @release 1.0.0
3436 ** @@
3437 ******************************************************************************/
3438
showLineIsClear(AjPStr * line,ajint start,ajint end)3439 static AjBool showLineIsClear(AjPStr *line, ajint start, ajint end)
3440 {
3441 ajint i;
3442 ajint len;
3443
3444 len = ajStrGetLen(*line)-1;
3445
3446 if(len < end)
3447 ajStrAppendCountK(line, ' ', end-len);
3448
3449 for(i=start; i<=end; i++)
3450 if(ajStrGetCharPos(*line,i) != ' ')
3451 return ajFalse;
3452
3453 return ajTrue;
3454 }
3455
3456
3457
3458
3459 /* @funcstatic showAddTags ****************************************************
3460 **
3461 ** writes feature tags to the tagsout string
3462 **
3463 ** @param [w] tagsout [AjPStr*] tags out string
3464 ** @param [r] feat [const AjPFeature] Feature to be processed
3465 ** @param [r] values [AjBool] display values of tags (currently ignored)
3466 **
3467 ** @return [void]
3468 **
3469 ** @release 2.0.0
3470 ** @@
3471 ******************************************************************************/
3472
showAddTags(AjPStr * tagsout,const AjPFeature feat,AjBool values)3473 static void showAddTags(AjPStr *tagsout, const AjPFeature feat, AjBool values)
3474 {
3475
3476 AjPStr tagnam = NULL;
3477 AjPStr tagval = NULL;
3478 AjIList titer;
3479
3480 /*
3481 ** iterate through the tags and test for match to patterns
3482 */
3483
3484 (void) values; /* make it used */
3485
3486 tagval = ajStrNew();
3487 tagnam = ajStrNew();
3488
3489 titer = ajFeatTagIter(feat);
3490
3491 /* don't display the translation tag - it is far too long */
3492 while(ajFeatTagval(titer, &tagnam, &tagval))
3493 if(ajStrCmpC(tagnam, "translation"))
3494 {
3495 if(ajStrGetLen(tagval))
3496 ajFmtPrintAppS(tagsout, " %S=\"%S\"", tagnam, tagval);
3497 else
3498 ajFmtPrintAppS(tagsout, " %S", tagnam);
3499 }
3500
3501 ajListIterDel(&titer);
3502
3503 ajStrDel(&tagval);
3504 ajStrDel(&tagnam);
3505
3506 return;
3507 }
3508