2
Copyright (c) 1996,1997,1998,1999,2000,2001,2004,2006
3
Whitehead Institute for Biomedical Research, Steve Rozen
4
(http://jura.wi.mit.edu/rozen), and Helen Skaletsky
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
11
* Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
* Redistributions in binary form must reproduce the above
14
copyright notice, this list of conditions and the following disclaimer
15
in the documentation and/or other materials provided with the
17
* Neither the names of the copyright holders nor contributors may
18
be used to endorse or promote products derived from this software
19
without specific prior written permission.
21
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
#include "format_output.h"
37
#include "primer3_release.h"
42
static int lib_sim_specified(const primer_args *);
43
static void print_explain(FILE *, const primer_args *,
44
const seq_args *, int);
45
static void print_pair_info(FILE *, const primer_pair *,
47
static void print_oligo(FILE *, const char *, const seq_args *,
48
const primer_rec *, int, const primer_args *,
50
static void print_oligo_header(FILE *, const char *, const int);
51
static void print_pair_array(FILE *, const char*, int,
52
const interval_array_t,
53
const primer_args*, const seq_args*);
54
static void print_rest(FILE *, const primer_args *,
55
const seq_args *, const pair_array_t *);
56
static void print_seq(FILE *, const primer_args *, const seq_args *,
57
primer_rec *h, const pair_array_t *, int);
58
static void print_seq_lines(FILE *, const char *s, const char *n, int, int,
59
int, const primer_args *);
60
static void print_stat_line(FILE *, const char *, oligo_stats s, int);
61
static void print_summary(FILE *, const primer_args *,
62
const seq_args *, const pair_array_t *, int);
63
static void print_oligo_summary(FILE *, const primer_args *,
64
const seq_args *, primer_rec *,
69
format_pairs(f, pa, sa, best_pairs)
71
const primer_args *pa;
73
const pair_array_t *best_pairs;
76
int print_lib_sim = lib_sim_specified(pa);
80
PR_ASSERT(NULL != pa);
81
PR_ASSERT(NULL != sa);
84
if (NULL != sa->sequence_name)
85
fprintf(f, "PRIMER PICKING RESULTS FOR %s\n\n", sa->sequence_name);
87
if (sa->error.data != NULL)
88
fprintf(f, "INPUT PROBLEM: %s\n\n", sa->error.data);
90
if (pa->repeat_lib.repeat_file != NULL)
91
fprintf(f, "Using mispriming library %s\n",
92
pa->repeat_lib.repeat_file);
94
fprintf(f, "No mispriming library specified\n");
96
if ( pa->primer_task == 1) {
97
if (pa->io_mishyb_library.repeat_file != NULL)
98
fprintf(f, "Using internal oligo mishyb library %s\n",
99
pa->io_mishyb_library.repeat_file);
101
fprintf(f, "No internal oligo mishyb library specified\n");
104
fprintf(f, "Using %d-based sequence positions\n",
105
pa->first_base_index);
106
if (best_pairs->num_pairs == 0) fprintf(f, "NO PRIMERS FOUND\n\n");
107
if ((warning = pr_gather_warnings(sa, pa)) != NULL) {
108
fprintf(f, "WARNING: %s\n\n", warning);
111
print_summary(f, pa, sa, best_pairs, 0);
114
print_seq(f, pa, sa, h, best_pairs, 0);
115
if (best_pairs->num_pairs > 1 ) print_rest(f, pa, sa, best_pairs);
116
if (pa->explain_flag) print_explain(f, pa, sa, print_lib_sim);
118
if (fflush(f) == EOF) {
119
perror("fflush(f) failed");
126
print_summary(f, pa, sa, best_pairs, num)
128
const primer_args *pa;
130
const pair_array_t *best_pairs;
133
int seq_len = strlen(sa->sequence);
134
int print_lib_sim = lib_sim_specified(pa);
136
p = best_pairs->pairs + num;
137
if (best_pairs->num_pairs > 0) {
139
* If the following format changes, also change the format in
142
print_oligo_header(f, "OLIGO", print_lib_sim);
143
print_oligo(f, "LEFT PRIMER", sa, p->left, FORWARD, pa, pa->repeat_lib,
145
print_oligo(f, "RIGHT PRIMER", sa, p->right, REVERSE, pa, pa->repeat_lib,
147
if ( pa->primer_task == 1)
148
print_oligo(f, "INTERNAL OLIGO", sa, p->intl, FORWARD, pa, pa->io_mishyb_library,
151
fprintf(f, "SEQUENCE SIZE: %d\n", seq_len);
152
fprintf(f, "INCLUDED REGION SIZE: %d\n\n", sa->incl_l);
154
if (best_pairs->num_pairs > 0) print_pair_info(f, p, pa);
155
print_pair_array(f, "TARGETS", sa->num_targets, sa->tar, pa, sa);
156
print_pair_array(f, "EXCLUDED REGIONS", sa->num_excl, sa->excl, pa, sa);
157
print_pair_array(f, "INTERNAL OLIGO EXCLUDED REGIONS",
158
sa->num_internal_excl, sa->excl_internal, pa, sa);
161
/* Print column headers for lines printed by print_oligo(). */
163
print_oligo_header(f, s, print_lib_sim)
166
const int print_lib_sim;
169
"%-16s start len tm gc%% any 3' %sseq\n",
170
s, print_lib_sim ? " rep " : "");
174
print_oligo(f, title, sa, o, dir, pa, seqlib, print_lib_sim)
180
const primer_args *pa;
181
const seq_lib seqlib;
184
const char *format1 = "%-16s %5d %4d %7.2f %7.2f %5.2f %5.2f ";
185
char *seq = (FORWARD == dir)
186
? pr_oligo_sequence(sa, o) : pr_oligo_rev_c_sequence(sa, o);
189
title, o->start + sa->incl_s + pa->first_base_index,
190
o->length, o->temp, o->gc_content, 0.01 * o->self_any,
194
if (seqlib.repeat_file)
195
fprintf(f, "%5.2f ", 0.01 * o->repeat_sim.score[o->repeat_sim.max]);
197
fprintf(f, "%5s ", "");
199
fprintf(f, "%s\n", seq);
200
if (PR_DEFAULT_INSIDE_PENALTY != pa->inside_penalty
201
|| PR_DEFAULT_OUTSIDE_PENALTY != pa->outside_penalty)
202
fprintf(f, "POSITION PENALTY, QUALITY: %f, %f\n",
203
o->position_penalty, o->quality);
207
print_pair_array(f, title, num, array, pa, sa)
211
const interval_array_t array;
212
const primer_args *pa;
217
fprintf(f, "%s (start, len)*:", title);
218
for (j = 0; j < num; j++)
220
array[j][0] + pa->first_base_index + sa->incl_s,
226
#define VECTOR (1<<0)
227
#define LEFT_OLIGO (1<<1)
228
#define RIGHT_OLIGO (1<<2)
229
#define INTL_OLIGO (1<<3)
230
#define TARGET (1<<4)
231
#define EXCL_REGION (1<<5)
232
#define INTL_EXCL_REGION (1<<6)
235
print_seq(f, pa, sa, h, best_pairs, num)
237
const primer_args *pa;
240
const pair_array_t *best_pairs;
241
int num; /* The number of primer pair to print. */
243
int len, i, j, start;
244
int something_found = 0, vector_found = 0;
249
if(pa->primer_task == pick_pcr_primers ||
250
pa->primer_task == pick_pcr_primers_and_hyb_probe)
251
p = best_pairs->pairs + num;
252
len = strlen(sa->sequence);
253
notes = pr_safe_malloc(sizeof(*notes) * len);
254
memset(notes, 0, sizeof(*notes) * len);
255
notestr = pr_safe_malloc(len + 1);
256
memset(notestr, ' ', len);
259
for (i = 0; i < len; i++) {
260
if (i < sa->incl_s || i >= sa->incl_s + sa->incl_l)
263
if ((pa->primer_task == pick_pcr_primers ||
264
pa->primer_task == pick_pcr_primers_and_hyb_probe) &&
265
best_pairs->num_pairs > 0) {
266
if (i >= p->left->start + sa->incl_s
267
&& i < p->left->start + p->left->length + sa->incl_s)
268
notes[i] |= LEFT_OLIGO;
269
if (i >= p->right->start - p->right->length + 1 + sa->incl_s
270
&& i <= p->right->start + sa->incl_s)
271
notes[i] |= RIGHT_OLIGO;
272
if ( pa->primer_task == 1
273
&& i >= p->intl->start + sa->incl_s
274
&& i < p->intl->start + p->intl->length + sa->incl_s)
275
notes[i] |= INTL_OLIGO;
277
else if (h != NULL) {
278
if(pa->primer_task == pick_left_only &&
279
i < h->start + h->length + sa->incl_s &&
280
i >= h->start + sa->incl_s)
281
notes[i] |= LEFT_OLIGO;
282
else if(pa->primer_task == pick_right_only &&
283
i >= h->start - h->length + 1 + sa->incl_s
284
&& i <= h->start + sa->incl_s)
285
notes[i] |= RIGHT_OLIGO;
286
else if(pa->primer_task == pick_hyb_probe_only &&
287
i >= h->start + sa->incl_s &&
288
i < h->start + h->length + sa->incl_s)
289
notes[i] |= INTL_OLIGO;
292
for (j = 0; j < sa->num_targets; j++) {
293
start = sa->tar[j][0] + sa->incl_s;
294
if (i >= start && i < start + sa->tar[j][1])
297
for (j = 0; j < sa->num_excl; j++) {
298
start = sa->excl[j][0] + sa->incl_s;
299
if (i >= start && i < start + sa->excl[j][1])
300
notes[i] |= EXCL_REGION;
302
for (j = 0; j < sa->num_internal_excl; j++) {
303
start = sa->excl_internal[j][0] + sa->incl_s;
304
if (i >= start && i < start + sa->excl_internal[j][1])
305
notes[i] |= INTL_EXCL_REGION;
309
for (i = 0; i < len; i++) {
310
if (notes[i] & VECTOR) {
314
else if (notes[i] & EXCL_REGION)
316
else if (notes[i] & INTL_EXCL_REGION)
318
else if ((notes[i] & TARGET) && (notes[i] & LEFT_OLIGO))
320
else if ((notes[i] & TARGET) && (notes[i] & RIGHT_OLIGO))
322
else if (notes[i] & TARGET)
324
else if (notes[i] & LEFT_OLIGO)
326
else if (notes[i] & RIGHT_OLIGO)
328
else if (notes[i] & INTL_OLIGO)
331
if (notes[i] != 0) something_found = 1;
334
print_seq_lines(f, sa->sequence, notestr, len, 60, something_found, pa);
337
fprintf(f, "KEYS (in order of precedence):\n");
340
fprintf(f, "...... vector sequence\n");
342
if (sa->num_excl > 0)
343
fprintf(f, "XXXXXX excluded region\n");
345
if (pa->primer_task == 1
346
&& sa->num_internal_excl > 0)
347
fprintf(f, "xxxxxx excluded region for internal oligo\n");
349
if (sa->num_targets > 0)
350
fprintf(f, "****** target\n");
352
if ((pa->primer_task == pick_pcr_primers ||
353
pa->primer_task == pick_pcr_primers_and_hyb_probe) &&
354
best_pairs->num_pairs > 0) {
355
fprintf(f, ">>>>>> left primer\n");
356
fprintf(f, "<<<<<< right primer\n");
357
if ( pa->primer_task == 1)
358
fprintf(f, "^^^^^^ internal oligo\n");
360
else if (pa->primer_task == pick_left_only && h != NULL)
361
fprintf(f, ">>>>>> left primer\n");
362
else if (pa->primer_task == pick_right_only && h != NULL)
363
fprintf(f, "<<<<<< right primer\n");
364
else if (pa->primer_task == pick_hyb_probe_only && h != NULL)
365
fprintf(f, "^^^^^^ internal oligo\n");
367
if (something_found) fputc('\n', f);
373
print_seq_lines(f, s, n, seq_size, line_size, something_found, pa)
376
int seq_size, line_size, something_found;
377
const primer_args *pa;
380
while (seq_size > line_size) {
381
fprintf(f, "%5d ", i + pa->first_base_index);
382
fwrite(s, sizeof(*s), line_size, f);
384
if (something_found) {
386
fwrite(n, sizeof(*n), line_size, f);
389
seq_size -= line_size;
395
fprintf(f, "%5d %s\n %s\n\n", i + pa->first_base_index, s, n);
397
fprintf(f, "%5d %s\n\n", i + pa->first_base_index, s);
401
print_pair_info(f, p, pa)
403
const primer_pair *p;
404
const primer_args *pa;
406
fprintf(f, "PRODUCT SIZE: %d, ", p->product_size);
407
fprintf(f, "PAIR ANY COMPL: %.2f, PAIR 3' COMPL: %.2f\n",
408
0.01 * p->compl_any, 0.01 * p->compl_end);
410
if (pa->product_max_tm != PR_DEFAULT_PRODUCT_MAX_TM
411
|| pa->product_min_tm != PR_DEFAULT_PRODUCT_MIN_TM) {
412
printf("PRODUCT Tm: %.4f, ", p->product_tm);
413
printf("PRODUCT Tm - min(OLIGO Tm): %.4f\n",
414
p->product_tm_oligo_tm_diff);
419
print_rest(f, pa, sa, best_pairs)
421
const primer_args *pa;
423
const pair_array_t *best_pairs;
426
int print_lib_sim = lib_sim_specified(pa);
428
fprintf(f, "ADDITIONAL OLIGOS\n");
429
fprintf(f, " "); print_oligo_header(f, "", print_lib_sim);
430
for (i = 1; i < best_pairs->num_pairs; i++) {
431
fprintf(f, "\n%2d ", i);
432
print_oligo(f, "LEFT PRIMER", sa, best_pairs->pairs[i].left, FORWARD,
433
pa, pa->repeat_lib, print_lib_sim);
435
print_oligo(f, "RIGHT PRIMER", sa, best_pairs->pairs[i].right, REVERSE,
436
pa, pa->repeat_lib, print_lib_sim);
437
if ( pa->primer_task == 1) {
439
print_oligo(f, "INTERNAL OLIGO", sa, best_pairs->pairs[i].intl,
440
FORWARD, pa, pa->io_mishyb_library, print_lib_sim);
442
if (best_pairs->pairs[i].product_size > 0) {
444
print_pair_info(f, &best_pairs->pairs[i], pa);
449
/* This function does _not_ print out the no_orf statistic. */
451
print_explain(f, pa, sa, print_lib_sim)
453
const primer_args *pa;
458
const char *format = print_lib_sim
459
? "%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s\n"
460
: "%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s%6s\n";
462
fprintf(f, "\nStatistics\n");
465
|| !((pick_pcr_primers == pa->primer_task
466
&& sa->left_input && sa->right_input)
467
|| (pick_pcr_primers_and_hyb_probe == pa->primer_task
468
&& sa->left_input && sa->right_input && sa->internal_input)
469
|| (pick_left_only == pa->primer_task
471
|| (pick_right_only == pa->primer_task
473
|| (pick_hyb_probe_only == pa->primer_task
474
&& sa->internal_input))) {
478
"", "con", "too", "in", "in", "", "no",
479
"tm", "tm", "high", "high", "high",
482
"", "sid", "many", "tar", "excl", "bad","GC",
483
"too", "too", "any", "3'", "lib",
486
"", "ered","Ns", "get", "reg", "GC%", "clamp",
487
"low", "high","compl", "compl", "sim",
491
"", "con", "too", "in", "in", "", "no",
492
"tm", "tm", "high", "high",
495
"", "sid", "many", "tar", "excl", "bad","GC",
496
"too", "too", "any", "3'",
499
"", "ered","Ns", "get", "reg", "GC%", "clamp",
500
"low", "high","compl", "compl",
506
if ((pick_pcr_primers == pa->primer_task
507
|| pick_left_only == pa->primer_task
508
|| pick_pcr_primers_and_hyb_probe == pa->primer_task)
509
&& !(pa->pick_anyway && sa->left_input))
510
print_stat_line(f, "Left", sa->left_expl, print_lib_sim);
512
if ((pick_pcr_primers == pa->primer_task
513
|| pick_right_only == pa->primer_task
514
|| pick_pcr_primers_and_hyb_probe == pa->primer_task)
515
&& !(pa->pick_anyway && sa->right_input))
516
print_stat_line(f, "Right", sa->right_expl, print_lib_sim);
518
if ((pick_pcr_primers_and_hyb_probe == pa->primer_task
519
|| pick_hyb_probe_only == pa->primer_task)
520
&& !(pa->pick_anyway && sa->internal_input))
521
print_stat_line(f, "Intl", sa->intl_expl, print_lib_sim);
523
if (pick_pcr_primers == pa->primer_task
524
|| pick_pcr_primers_and_hyb_probe == pa->primer_task) {
525
fprintf(f, "Pair Stats:\n");
527
pr_print_pair_explain(f, sa);
529
fprintf(f, "%s\n", pr_release);
533
print_stat_line(f, t, s, print_lib_sim)
539
const char *format = print_lib_sim
540
? "%-6s%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d\n"
541
: "%-6s%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d\n";
545
t, s.considered, s.ns, s.target, s.excluded,
546
s.gc, s.gc_clamp, s.temp_min, s.temp_max,
547
s.compl_any, s.compl_end, s.repeat_score,
548
s.poly_x, s.stability, s.ok);
551
t, s.considered, s.ns, s.target, s.excluded,
552
s.gc, s.gc_clamp, s.temp_min, s.temp_max,
553
s.compl_any, s.compl_end, s.poly_x, s.stability, s.ok);
557
* Return true iff a check for library similarity has been specified for
558
* either the primer pair or the internal oligo.
562
lib_sim_specified(pa)
563
const primer_args *pa;
565
return (pa->repeat_lib.repeat_file || pa->io_mishyb_library.repeat_file);
568
void format_oligos(f, pa, sa, h, n, l)
570
const primer_args *pa;
577
int print_lib_sim = lib_sim_specified(pa);
579
pair_array_t *best_pairs;
583
PR_ASSERT(NULL != f);
584
PR_ASSERT(NULL != pa);
585
PR_ASSERT(NULL != sa);
588
if (NULL != sa->sequence_name)
589
fprintf(f, "PRIMER PICKING RESULTS FOR %s\n\n", sa->sequence_name);
591
if (sa->error.data != NULL)
592
fprintf(f, "INPUT PROBLEM: %s\n\n", sa->error.data);
595
if (pa->repeat_lib.repeat_file != NULL)
596
fprintf(f, "Using mispriming library %s\n",
597
pa->repeat_lib.repeat_file);
599
fprintf(f, "No mispriming library specified\n");
601
if ( pa->primer_task == 1) {
602
if (pa->io_mishyb_library.repeat_file != NULL)
603
fprintf(f, "Using internal oligo mishyb library %s\n",
604
pa->io_mishyb_library.repeat_file);
606
fprintf(f, "No internal oligo mishyb library specified\n");
610
if(l == OT_LEFT) strcpy(type, "LEFT_PRIMER");
611
else if(l == OT_RIGHT) strcpy(type, "RIGHT_PRIMER");
612
else strcpy(type, "INTERNAL_OLIGO");
614
fprintf(f, "Using %d-based sequence positions\n",
615
pa->first_base_index);
616
if (n == 0) fprintf(f, "NO OLIGOS FOUND\n\n");
617
if ((warning = pr_gather_warnings(sa, pa)) != NULL) {
618
fprintf(f, "WARNING: %s\n\n", warning);
622
if(n > 0) print_oligo_summary(f, pa, sa, h, l, 0);
624
print_seq(f, pa, sa, h, best_pairs, 0);
627
fprintf(f, "ADDITIONAL OLIGOS\n");
628
fprintf(f, " "); print_oligo_header(f, "", print_lib_sim);
629
for(i = 1; i < pa->num_return; i++) {
632
fprintf(f, "%2d ", i);
633
if(OT_LEFT == l || OT_INTL == l)
634
print_oligo(f, type, sa, p, FORWARD,pa, pa->repeat_lib, print_lib_sim);
635
else print_oligo(f, type, sa, p, REVERSE,pa, pa->repeat_lib, print_lib_sim);
638
if(pa->explain_flag) print_explain(f, pa, sa, print_lib_sim);
640
if (fflush(f) == EOF) {
641
perror("fflush(f) failed");
648
print_oligo_summary(f, pa, sa, h, l, num)
650
const primer_args *pa;
656
int seq_len = strlen(sa->sequence);
657
int print_lib_sim = lib_sim_specified(pa);
661
if(l == OT_LEFT) strcpy(type, "LEFT_PRIMER");
662
else if(l == OT_RIGHT) strcpy(type, "RIGHT_PRIMER");
663
else strcpy(type, "INTERNAL_OLIGO");
667
* If the following format changes, also change the format in
670
print_oligo_header(f, "OLIGO", print_lib_sim);
671
if(OT_LEFT == l || OT_INTL == l)
672
print_oligo(f, type, sa, p, FORWARD, pa, pa->repeat_lib,
674
else print_oligo(f, type, sa, p, REVERSE, pa, pa->repeat_lib,
677
fprintf(f, "SEQUENCE SIZE: %d\n", seq_len);
678
fprintf(f, "INCLUDED REGION SIZE: %d\n\n", sa->incl_l);
680
print_pair_array(f, "TARGETS", sa->num_targets, sa->tar, pa, sa);
681
print_pair_array(f, "EXCLUDED REGIONS", sa->num_excl, sa->excl, pa, sa);
682
print_pair_array(f, "INTERNAL OLIGO EXCLUDED REGIONS",
683
sa->num_internal_excl, sa->excl_internal, pa, sa);