ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/dnacgr/dnacgr.c
Revision: 1.3
Committed: Sun Apr 22 17:54:01 2001 UTC (18 years, 7 months ago) by indraneel
Branch: MAIN
CVS Tags: HEAD_NEW, HEAD
Changes since 1.2: +1 -1 lines
Log Message:
oops, forgot to change the maintainer email address

Line User Rev File contents
1 indraneel 1.3 /* Copyright (C) 2000 by Indraneel Majumdar<indraneel@indialine.org> */
2 indraneel 1.1
3     /* GNU LESSER GENERAL PUBLIC LICENSE
4     Version 2.1, February 1999
5    
6     You should have received a copy of the GNU Lesser General Public
7     License along with this library; if not, write to the Free Software
8     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9     */
10     /* Program to plot Chaos Game Representation of a DNA or RNA sequence. */
11    
12    
13     /* this file should be linked with
14     -lreadline -lncurses -lm -lvgagl -lvga -lpng -lz */
15    
16     #include<stdio.h>
17     #include<stdlib.h>
18     #include<vgagl.h>
19     #include<vga.h>
20     #include<math.h>
21     #include<readline/readline.h>
22     #include<png.h>
23    
24     #define VGAMODE 12 /* 1024 x 768 at 256 colors */
25     #define TEXT 0 /* text mode */
26    
27     /* initialise buffers for svgalib */
28     GraphicsContext *physicalscreen;
29     GraphicsContext *templatescreen, *fileplotscreen, *randomplotscreen;
30    
31     /* stores probability data */
32     struct P_ATGC
33     {
34     double a, t, g, c;
35     }
36     P;
37    
38     struct point
39     {
40     double x, y;
41     }
42     A, T, G, C;
43    
44     /* stores input file name */
45     struct file_identity
46     {
47     char name[105]; /* filepath and name has to be < 100 characters */
48     int flag; /* set this 0 for random plot */
49     }
50     seqfile, outfile;
51    
52     /* global flags for user choice */
53     struct all_flags
54     {
55     int file, prob, cycles, grid, seq, reload, counts, refresh, print;
56     }
57     flags;
58    
59     char sequence_table[16][16][5]; /* stores sequence chart */
60     int probability_table[16][16]; /* stores counts of bases per 10000 */
61     long int CYCLES, CYCLES_FIRST, CYCLES_LAST; /* iterations */
62    
63     /* user input for probabilities for random plot */
64     void
65     get_atgc_probabilities ()
66     {
67     vga_setmode (TEXT);
68     P.a = P.t = P.g = P.c = 1.000000;
69     while ((P.a + P.t + P.g) > 1.000001)
70     {
71     printf ("\nEnter probabilities for A, T, G\n"
72     "(probability for C is calculated automagically)\n"
73     "Probabilities=>");
74     scanf ("%lf,%lf,%lf", &P.a, &P.t, &P.g);
75     getchar (); /* discard the entered newline character */
76     }
77     P.c = 1.000001 - (P.a + P.t + P.g);
78     flags.prob = 1 - flags.prob; /* reverse global flag */
79     vga_setmode (VGAMODE);
80     }
81    
82     /* user input for iterations */
83     int
84     get_cycles ()
85     {
86     long int cycles;
87     cycles = CYCLES_FIRST = 0;
88     vga_setmode (TEXT);
89     if (seqfile.flag == 0)
90     {
91     printf ("\nEnter number of points to plot\n" "Points to plot=>");
92     scanf ("%d", &cycles);
93     }
94     else
95     {
96     do
97     { /* filter user's input for errors, discard -ve numbers */
98     printf ("\nEnter start point for plot\n" "First base=>");
99     scanf ("%d", &CYCLES_FIRST);
100     printf ("\nEnter end point for plot\n"
101     "(enter '0' for entire file)\n" "Last base=>");
102     scanf ("%d", &cycles);
103     }
104     while ((cycles != 0) && ((cycles < 0) || (cycles < CYCLES_FIRST)));
105     if ((cycles == 0) || (CYCLES_FIRST < 1))
106     CYCLES_FIRST = 1; /*so display looks better */
107     }
108     getchar (); /* discard newline character */
109     vga_setmode (VGAMODE);
110     flags.cycles = 1 - flags.cycles; /* reverse global flag */
111     return (cycles); /* return end point of loop */
112     }
113    
114     /* user's input for sequence input file */
115     void
116     get_seqfile ()
117     {
118     FILE *fopen (), *file_pointer; /* to check if file exists */
119     char *filename_pointer, *malloc (); /*readline requires this */
120     int length;
121     filename_pointer = malloc (100); /* length of filename<100 */
122     vga_setmode (TEXT);
123     file_pointer = 0; /* initialise pointer to NULL */
124     seqfile.flag = 1;
125     while ((file_pointer == 0) && (seqfile.flag == 1))
126     {
127     printf ("\nEnter full path of DNA sequence file\n"
128     "(enter '*' for random number plot)\n");
129     filename_pointer = readline ("Filename=> "); /* makes it easy to locate files */
130     strncpy (seqfile.name, filename_pointer, 100);
131     if (seqfile.name[0] == '*')
132     {
133     sprintf (seqfile.name, "RANDOM NUMBER PLOT"); /* give a title to the plot */
134     seqfile.flag = 0; /* set flag for plot type */
135     }
136     else
137     {
138     length = strlen (seqfile.name);
139     if (seqfile.name[length - 1] == ' ')
140     seqfile.name[length - 1] = '\0'; /* discard last blank which maybe entered by readline input */
141     seqfile.flag = 1; /* set flag that disk file is being used */
142     file_pointer = fopen (seqfile.name, "r"); /* check if file exists */
143     }
144     }
145     if (seqfile.flag == 1)
146     fclose (file_pointer); /* close file if exists */
147     free (filename_pointer);
148     flags.file = 1 - flags.file; /* reverse global flag */
149     vga_setmode (VGAMODE);
150     }
151    
152     /* generate (x,y) random point from 0 to 1 */
153     struct point
154     get_random_point ()
155     {
156     struct point p;
157     p.x = ((double) rand () / RAND_MAX);
158     p.y = ((double) rand () / RAND_MAX);
159     return (p);
160     }
161    
162     /* make border of plot and print filename */
163     void
164     draw_border ()
165     {
166     gl_line (A.x, A.y, T.x, T.y, 3);
167     gl_line (T.x, T.y, G.x, G.y, 3);
168     gl_line (G.x, G.y, C.x, C.y, 3);
169     gl_line (C.x, C.y, A.x, A.y, 3);
170     gl_setfontcolors (0, 32);
171     gl_write (A.x - 25, A.y - 25, "DNA base 'A'");
172     gl_write (T.x - 25, T.y + 30, "DNA base 'T'");
173     gl_write (G.x - 50, G.y + 30, "DNA base 'G'");
174     gl_write (C.x - 50, C.y - 25, "DNA base 'C'");
175     gl_setfontcolors (0, 42); /*same color as file data */
176     gl_printf (A.x + 100, T.y + 50, "%s", seqfile.name);
177     }
178    
179     /* draw the grid (lines are 37.5 pixels apart) */
180     void
181     draw_grid ()
182     {
183     int num;
184     float x, y, loopx, loopy = 0;
185     x = C.x;
186     y = T.y;
187     loopx = A.x;
188     loopy = A.y;
189     num = 0;
190     gl_setfontcolors (0, 52);
191     gl_write (500, A.y - 20, "sequence resolution = 9 bp"); /* for a 600x600 pixel plot difference in base in any of last 9 bases gives different points (advertise this) */
192     while (loopx <= x)
193     {
194     gl_line (loopx, A.y - 10, loopx, y + 10, 8);
195     gl_printf (loopx, y + 15, "%d", num); /* grid number */
196     loopx = loopx + 37.5;
197     num++;
198     }
199     num = 0;
200     while (loopy <= y)
201     {
202     gl_line (A.x - 10, loopy, x + 10, loopy, 8);
203     gl_printf (x + 15, loopy, "%d", num); /* grid number */
204     loopy = loopy + 37.5;
205     num++;
206     }
207     flags.grid = 1 - flags.grid; /* reverse global flag */
208     }
209    
210     /* plot random plot to virtual screen and copy to real screen (this makes plot and refresh faster)*/
211     void
212     plot_random_sequence (long int cycles)
213     {
214     long int loop;
215     double a, t, g, c;
216     struct point p, pix;
217     gl_setcontext (templatescreen); /*change to template virtual screen */
218     gl_copyscreen (randomplotscreen); /*copy template to working virtual screen ie randomplotscreen */
219     gl_setcontext (randomplotscreen); /* change to working virtual screen */
220     a = P.a;
221     t = a + P.t;
222     g = t + P.g;
223     c = g + P.c; /* convert user input to 0 to 1 */
224     loop = 0;
225     pix.x = 600;
226     pix.y = 350;
227     while (loop < cycles)
228     {
229     p = get_random_point ();
230     /* test against user input probability and scale pixel to fit within borders. point is located midway between previous point and corner for chosen base. This is the CGR */
231     if (p.x <= a)
232     {
233     pix.x = (pix.x + A.x) / 2;
234     pix.y = (pix.y + A.y) / 2;
235     }
236     else if (p.x <= t)
237     {
238     pix.x = (pix.x + T.x) / 2;
239     pix.y = (pix.y + T.y) / 2;
240     }
241     else if (p.x <= g)
242     {
243     pix.x = (pix.x + G.x) / 2;
244     pix.y = (pix.y + G.y) / 2;
245     }
246     else if (p.x <= c)
247     {
248     pix.x = (pix.x + C.x) / 2;
249     pix.y = (pix.y + C.y) / 2;
250     }
251     gl_setpixel (pix.x, pix.y, 44); /*plot the pixel */
252     loop++;
253     }
254     gl_copyscreen (physicalscreen); /* copy to monitor or stdout */
255     gl_setcontext (physicalscreen); /* change working screen to real screen */
256     CYCLES = loop; /* record actual number of points plotted */
257     }
258    
259     /* plots CGR from disk file sequence to virtual screen and copies to real screen (makes plotting and refresh faster)*/
260     void
261     plot_file_sequence (long int cycles)
262     {
263     long int loop, base_count, first_base;
264     int base, array_row, array_col, array_box, stop;
265     int a, t, g, c;
266     struct point pix;
267     char file_header[200]; /* non sequence lines at start of file */
268     FILE *fopen (), *file_pointer;
269     gl_setcontext (templatescreen); /* change to template virtual screen */
270     gl_copyscreen (fileplotscreen); /* copy template to working screen */
271     gl_setcontext (fileplotscreen); /* change to working virtual screen */
272     loop = stop = base_count = base = 0;
273     first_base = CYCLES_FIRST - 1;
274     a = t = g = c = 0;
275     /* initialise the counts table for each new plot */
276     for (array_row = 0; array_row < 16; array_row++)
277     {
278     for (array_col = 0; array_col < 16; array_col++)
279     {
280     probability_table[array_row][array_col] = 0;
281     }
282     }
283     pix.x = 600;
284     pix.y = 350;
285     file_pointer = fopen (seqfile.name, "r"); /* open file for reading */
286     fgets (file_header, 200, file_pointer); /* first line is not checked for sequence (assumed to contain file information and is shown on display */
287     gl_setfontcolors (0, 42);
288     gl_write (50, T.y + 60, "File data:");
289     gl_printf (50, T.y + 80, "%s", file_header); /* show first line */
290     base = getc (file_pointer); /* get first base of next line */
291     base = tolower (base); /* convert to lowercase */
292     /* sequence description must start with a,t,u,g,c, or blank (fasta format), please write checkpoints for other sequence formats and add here */
293     while ((base != 'a') && (base != 't') && (base != 'u') && (base != 'g')
294     && (base != 'c') && (base != ' '))
295     {
296     ungetc (base, file_pointer); /* move back */
297     fgets (file_header, 200, file_pointer); /* remove the whole line */
298     base = getc (file_pointer); /* get first base of next line */
299     base = tolower (base);
300     }
301     ungetc (base, file_pointer); /* move back if sequence has started */
302     /* check for EOF and whether last base to plot has been reached */
303     while ((stop == 0) && ((base = getc (file_pointer)) != EOF))
304     {
305     base = tolower (base);
306     if ((base == 'a') || (base == 't') || (base == 'u') || (base == 'g')
307     || (base == 'c'))
308     {
309     /* check whether base is to be plotted (user input for start and end points) */
310     if ((cycles == 0) || ((loop >= first_base) && (loop < cycles)))
311     {
312     /* set pixel according to CGR theory (point is halfway between previous point and corner of current chosen base) */
313     if (base == 'a')
314     {
315     pix.x = (pix.x + A.x) / 2;
316     pix.y = (pix.y + A.y) / 2;
317     a++;
318     }
319     else if ((base == 't') || (base == 'u'))
320     {
321     pix.x = (pix.x + T.x) / 2;
322     pix.y = (pix.y + T.y) / 2;
323     t++;
324     }
325     else if (base == 'g')
326     {
327     pix.x = (pix.x + G.x) / 2;
328     pix.y = (pix.y + G.y) / 2;
329     g++;
330     }
331     else if (base == 'c')
332     {
333     pix.x = (pix.x + C.x) / 2;
334     pix.y = (pix.y + C.y) / 2;
335     c++;
336     }
337     gl_setpixel (pix.x, pix.y, 44); /* plot the pixel */
338     array_row = (pix.x - 300) / 37.5;
339     array_col = (pix.y - 50) / 37.5; /* scale the pixel location and update the counts table */
340     probability_table[array_row][array_col]++;
341     base = 'x'; /* make base non atugc blank */
342     base_count++; /* update count of actual points plotted */
343     }
344     loop++; /* increment counter for bases checked */
345     if ((cycles != 0) && (loop == cycles))
346     stop = 1; /* check for end point */
347     } /* no counter increments for non atugc even if not plotted */
348     }
349     fclose (file_pointer);
350     CYCLES = base_count; /* record actual points plotted */
351     CYCLES_LAST = loop; /* record actual last base checked */
352     if (base_count == 0)
353     CYCLES_FIRST = base_count = 1; /* if user input for first base was > total bases in file */
354     /* calculate probability of atgc based on total points plotted */
355     P.a = (double) a / base_count;
356     P.t = (double) t / base_count;
357     P.g = (double) g / base_count;
358     P.c = (double) c / base_count;
359     /* prepare counts table to show counts out of 10000 */
360     for (array_row = 0; array_row < 16; array_row++)
361     {
362     for (array_col = 0; array_col < 16; array_col++)
363     {
364     /* convert display to integer */
365     array_box =
366     (probability_table[array_row][array_col] * 10000) / base_count;
367     /* update table */
368     probability_table[array_row][array_col] = array_box;
369     }
370     }
371     gl_copyscreen (physicalscreen); /* copy working screen to monitor or stdout */
372     gl_setcontext (physicalscreen); /* change working screen to real screen */
373     }
374    
375     /* to show the sequence chart at the drop of a finger */
376     void
377     make_sequence_table ()
378     {
379     int row, col, position;
380     int base;
381     row = col = position = 0;
382     /* pass all calculations to helper for all 1024 positions */
383     while (position < 4)
384     { /* no place to print more than 4 bases */
385     while (col < 16)
386     {
387     while (row < 16)
388     {
389     base = help_sequence_table (col, row, position);
390     sequence_table[row][col][position] = base;
391     row++;
392     }
393     col++;
394     row = 0;
395     }
396     position++;
397     col = 0;
398     }
399     /* add a blank to all ends so they can be printed as strings */
400     row = col = 0;
401     while (col < 16)
402     {
403     while (row < 16)
404     {
405     sequence_table[row][col][4] = '\0';
406     row++;
407     }
408     col++;
409     row = 0;
410     }
411     }
412    
413     /* this returns value of a base at any position of any table */
414     /* (first position is position 0 and so on..) */
415     int
416     help_sequence_table (int row, int col, int position)
417     {
418     int base;
419     int divisor, checkx, checky; /*checkxy - even is 0, odd is 1 */
420     divisor = pow (2, position); /* convert divisor to position power of 2 */
421     row = row / divisor;
422     col = col / divisor; /* now it is easier to handle as everything becomes odd or even */
423     checkx = checky = 1;
424     /* check odd or even */
425     if ((row % 2) == 0)
426     checkx = 0;
427     if ((col % 2) == 0)
428     checky = 0;
429     /* the bottom is true when ATGC represents a square */
430     if ((checkx == 0) && (checky == 0))
431     base = 'A';
432     else if ((checkx == 1) && (checky == 0))
433     base = 'T';
434     else if ((checkx == 1) && (checky == 1))
435     base = 'G';
436     else if ((checkx == 0) && (checky == 1))
437     base = 'C';
438     return (base); /* done */
439     }
440    
441     /* display the table when asked */
442     void
443     display_sequence_table ()
444     {
445     int row, col, startx, starty;
446     gl_setfontcolors (0, 92);
447     gl_printf (20, 200, "(sequence ending for point)");
448     startx = 302;
449     starty = 53;
450     row = col = 0;
451     while (col < 16)
452     {
453     while (row < 16)
454     {
455     /* print the table as strings of 4 chars */
456     gl_write (startx + row * 37.5, starty + col * 37.5,
457     sequence_table[row][col]);
458     /* oops, must have goofed up somewhere, interchange row and col for correct output */
459     row++;
460     }
461     col++;
462     row = 0;
463     }
464     }
465    
466     /* display the counts table */
467     void
468     display_probability_table ()
469     {
470     int row, col, startx, starty;
471     gl_setfontcolors (0, 40);
472     gl_printf (20, 220, "(counts per 10'000 total points)");
473     gl_setfontcolors (31, 40); /* change background to white to see better */
474     startx = 302;
475     starty = 63;
476     row = col = 0;
477     while (col < 16)
478     {
479     while (row < 16)
480     {
481     gl_printf (startx + row * 37.5, starty + col * 37.5, "%d",
482     probability_table[row][col]);
483     row++;
484     }
485     col++;
486     row = 0;
487     }
488     }
489    
490     /* display total probability, points plotted, user's input of first base, lase base checked */
491     void
492     display_parameters ()
493     {
494     gl_setfontcolors (0, 48);
495     gl_write (50, 60, "Probabilities are:");
496     gl_printf (20, 80, "A = %6.4f", P.a);
497     gl_printf (20, 100, "T = %6.4f", P.t);
498     gl_printf (150, 100, "G = %6.4f", P.g);
499     gl_printf (150, 80, "C = %6.4f", P.c);
500     gl_printf (50, 120, "Total points: %d", CYCLES); /* total points plotted */
501     /* only if disk file is read */
502     if (seqfile.flag == 1)
503     {
504     gl_printf (20, 140, "First base: %d", CYCLES_FIRST); /* user's input echoed with minor changes in case of wrong input */
505     gl_printf (20, 160, "Last base: %d", CYCLES_LAST); /* display last base actually checked */
506     }
507     }
508    
509     /*keep template for use by fileplotscreen and randomplotscreen for fresh plots*/
510     void
511     make_templatescreen ()
512     {
513     gl_setcontext (templatescreen); /*change to virtual screen */
514     gl_clearscreen (0);
515     gl_setfontcolors (0, 44);
516     gl_printf (5, 5,
517     " HELP MENU: file iterations probability counts grid sequence refresh Print Reload about quit");
518     gl_setfontcolors (0, vga_white ());
519     gl_printf (50, 650, "dnacgr-0.2");
520     draw_grid ();
521     draw_border ();
522     gl_setcontext (physicalscreen); /*change to real screen */
523     }
524    
525     /* prepare virtual screens randomplotscreen and fileplot screen and show on real screen */
526     void
527     make_display (long int cycles)
528     {
529     make_templatescreen ();
530     if (seqfile.flag == 0)
531     {
532     plot_random_sequence (cycles);
533     }
534     else
535     plot_file_sequence (cycles);
536     display_parameters ();
537     flags.reload = 1 - flags.reload; /* reverse global flag */
538     }
539    
540     /* to save time just refresh the screen, do not replot any data */
541     void
542     display_refresh (int input_grid)
543     {
544     if (seqfile.flag == 0)
545     {
546     gl_setcontext (randomplotscreen);
547     gl_copyscreen (physicalscreen);
548     gl_setcontext (physicalscreen);
549     }
550     else
551     {
552     gl_setcontext (fileplotscreen);
553     gl_copyscreen (physicalscreen);
554     gl_setcontext (physicalscreen);
555     }
556     if (input_grid == 1)
557     {
558     draw_grid ();
559     draw_border ();
560     } /* draw grid if required */
561     display_parameters (); /* parameters are always displayed */
562     flags.refresh = 1 - flags.refresh; /* reverse global flag */
563     }
564    
565     /* save the color table to file for use with screen memory dump */
566     /* unused code */
567     void
568     save_color_table ()
569     {
570     FILE *fopen (), *file_pointer;
571     int color, r, g, b;
572     color = 0;
573     file_pointer = fopen ("clrtbl.dnacgr", "w");
574     for (color = 0; color < 256; color++)
575     {
576     gl_getpalettecolor (color, &r, &g, &b);
577     fprintf (file_pointer, "%d\t%d\t%d\t%d\n", color, r * 4, g * 4, b * 4);
578     }
579     fclose (file_pointer);
580     }
581    
582     /* ask user for output filename. .png extension is added automatically */
583     void
584     get_output_filename ()
585     {
586     char *filename_pointer, *malloc ();
587     vga_setmode (TEXT);
588     filename_pointer = malloc (100);
589     printf ("\nEnter new filename for saving image file\n");
590     filename_pointer = readline ("Filename=> ");
591     strncpy (outfile.name, filename_pointer, 100);
592     strcat (outfile.name, ".png");
593     free (filename_pointer);
594     vga_setmode (VGAMODE);
595     }
596    
597     /* this just dumps screen memory to file, you need color tables to use this dump */
598     /* unused code */
599     void
600     print_file ()
601     {
602     FILE *fopen (), *file_pointer;
603     char *saved_screen_ptr, *malloc ();
604     saved_screen_ptr = malloc (1024 * 768);
605     gl_getbox (0, 0, 1024, 768, saved_screen_ptr);
606     file_pointer = fopen (outfile.name, "w");
607     fwrite (saved_screen_ptr, 1, 1024 * 768, file_pointer);
608     fclose (file_pointer);
609     free (saved_screen_ptr);
610     flags.print = 1 - flags.print;
611     }
612    
613     /* print to png file. modified from code donated by Sergio Masci <sergio@titan.demon.co.uk> */
614     void
615     print_png_file ()
616     {
617     FILE *fopen (), *fp;
618     char *malloc ();
619     int xred, xgreen, xblue;
620     int adj, bits_per_colour, j;
621     char *rp;
622     png_struct *png_ptr;
623     png_info *info_ptr;
624     png_colorp palette;
625    
626     fp = fopen (outfile.name, "wb");
627    
628     // allocate the necessary structures
629     png_ptr = (png_struct *) malloc (sizeof (png_struct));
630    
631     info_ptr = (png_info *) malloc (sizeof (png_info));
632    
633     // initialize the structures
634     png_info_init (info_ptr);
635     png_write_init (png_ptr);
636    
637     // set up the output control
638     png_init_io (png_ptr, fp);
639    
640     // set the file information here
641     info_ptr->width = 1024;
642     info_ptr->height = 768;
643     info_ptr->bit_depth = 8;
644     info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
645    
646     //----------------------
647    
648     // set the palette
649     info_ptr->valid |= PNG_INFO_PLTE;
650     info_ptr->palette = (png_color *) malloc (256 * sizeof (png_color));
651     info_ptr->num_palette = 256;
652    
653    
654    
655     bits_per_colour = 6;
656    
657     adj = 8 - bits_per_colour;
658    
659    
660     for (j = 0; j < 256; j++)
661     {
662     vga_getpalette (j, &xred, &xgreen, &xblue);
663    
664     info_ptr->palette[j].red = xred << adj;
665     info_ptr->palette[j].green = xgreen << adj;
666     info_ptr->palette[j].blue = xblue << adj;
667     }
668    
669     // write the file information
670     png_write_info (png_ptr, info_ptr);
671    
672     rp = malloc (1024);
673    
674     for (j = 0; j < 768; j++)
675     {
676     gl_getbox (0, j, 1024, 1, rp);
677    
678     // Write a row at a time.
679     png_write_rows (png_ptr, &rp, 1);
680     }
681    
682     free (rp);
683    
684     //----------------------
685    
686     // write the rest of the file
687     png_write_end (png_ptr, NULL);
688    
689     // clean up after the write, and free any memory allocated
690     png_write_destroy (png_ptr);
691    
692     if (info_ptr->palette)
693     { // a palette was used, so free it
694     free (info_ptr->palette);
695     }
696    
697     // free the structures
698     free (png_ptr);
699     free (info_ptr);
700    
701     fclose (fp);
702     }
703    
704    
705     /* add your name here if you add a significant functionality to this code */
706     /* do not change the copyright notice */
707     void
708     show_about_screen ()
709     {
710     int key;
711     vga_setmode (VGAMODE);
712     gl_clearscreen (31);
713     gl_setfontcolors (31, 0);
714     gl_printf (360, 250,
715 indraneel 1.2 " DNA-CGR (version 0.2)\nProgram to visualise patterns in DNA\n\n Copyright (C) 2000\n\n by\n\n Indraneel Majumdar\n\n <indraneel@123india.com>\n\n\n Copyright Policy - GNU-LGPL\n\n (see file LGPL-2.1 for details)\n\n (press 'L' to show License)");
716 indraneel 1.1 key = getchar ();
717     if (key == 'L')
718     {
719     vga_setmode (TEXT);
720 indraneel 1.2 system ("/usr/bin/less /usr/share/common-licenses/LGPL-2.1");
721 indraneel 1.1 vga_setmode (VGAMODE);
722     }
723     }
724    
725     /* background process to handle all keypresses */
726     void
727     user_request_handler ()
728     {
729     long int cycles;
730     int user_key;
731     struct all_flags input;
732     /* set initial values of local flags for first run */
733     input.file = 0;
734     input.prob = 1;
735     input.cycles = 0;
736     input.grid = 0;
737     input.seq = 0;
738     input.reload = 0;
739     input.counts = 0;
740     input.refresh = 1;
741     input.print = 1;
742     user_key = 'x';
743     while (user_key != 'q')
744     {
745     switch (user_key)
746     {
747     case 'f':
748     input.file = 1 - input.file;
749     input.reload = 1 - input.reload; /* reload file (replot) */
750     break;
751     case 'p':
752     if (seqfile.flag == 0)
753     {
754     input.prob = 1 - input.prob;
755     input.reload = 1 - input.reload; /* replot */
756     }
757     break;
758     case 'i':
759     input.cycles = 1 - input.cycles;
760     input.reload = 1 - input.reload; /* replot from file */
761     break;
762     case 'g':
763     input.grid = 1 - input.grid;
764     if (input.grid == 1)
765     {
766     draw_grid ();
767     draw_border ();
768     }
769     else
770     input.refresh = 1 - input.refresh; /* just refresh screen */
771     break;
772     case 's':
773     input.seq = 1 - input.seq;
774     if (input.seq == 0)
775     input.refresh = 1 - input.refresh; /*just refresh screen */
776     break;
777     case 'R':
778     input.reload = 1 - input.reload; /* user's request to reload file */
779     break;
780     case 'c':
781     if (seqfile.flag == 1)
782     input.counts = 1 - input.counts;
783     /* switch off counts display (refresh screen) */
784     if ((seqfile.flag == 1) && (input.counts == 0))
785     input.refresh = 1 - input.refresh;
786     break;
787     case 'r':
788     input.refresh = 1 - input.refresh; /* refresh screen */
789     break;
790     case 'P':
791     get_output_filename ();
792     input.refresh = 1 - input.refresh;
793     input.print = 1 - input.print;
794     break;
795     case 'a':
796     show_about_screen (); /* version, names of author(s), copyright */
797     input.refresh = 1 - input.refresh;
798     break;
799     default:
800     break;
801     }
802     user_key = 'x';
803     /* do not change the sequence below (the sequence of operations is required at least for first run) */
804     if (input.file == flags.file)
805     get_seqfile ();
806     /* next step explicitly checks for probabilities on first run (probabilities are required only for random number plot) */
807     if (
808     ((seqfile.flag == 0) && ((P.a + P.t + P.g + P.c) == 0)
809     && (input.prob = 1 - input.prob)) || ((seqfile.flag == 0)
810     && (input.prob ==
811     flags.
812     prob)))
813     get_atgc_probabilities ();
814     if (input.cycles == flags.cycles)
815     cycles = get_cycles (); /* iterations */
816     if (input.reload == flags.reload)
817     make_display (cycles); /* replot */
818     if (input.refresh == flags.refresh)
819     display_refresh (input.grid); /*just refresh */
820     if (input.seq == 1)
821     display_sequence_table ();
822     /* counts table displayed only if sequence file is used */
823     if ((seqfile.flag == 1) && (input.counts == 1))
824     display_probability_table ();
825     user_key = vga_getkey (); /* read key without waiting */
826     if (input.print == flags.print)
827     print_png_file ();
828     }
829     }
830    
831     int
832     main ()
833     {
834     int x, y;
835     x = y = 0;
836     vga_init (); /* initialise display for svgalib */
837     if (vga_hasmode (VGAMODE) == 0)
838     exit (1); /* check if mode 12 is supported */
839     /* set corner points of border */
840     A.x = 300;
841     A.y = 50;
842     T.x = 300;
843     T.y = 650;
844     G.x = 900;
845     G.y = 650;
846     C.x = 900;
847     C.y = 50;
848     srand (time (0)); /* initialise random number generator */
849    
850     vga_setmode (VGAMODE); /* set 1024x768 at 256 colors */
851    
852     /* define fileplotscreen as virtual screen */
853     gl_setcontextvgavirtual (VGAMODE);
854     fileplotscreen = gl_allocatecontext ();
855     gl_getcontext (fileplotscreen);
856    
857     /* define randomplotscreen as virtual screen */
858     gl_setcontextvgavirtual (VGAMODE);
859     randomplotscreen = gl_allocatecontext ();
860     gl_getcontext (randomplotscreen);
861    
862     /* define templatescreen as virtual screen */
863     gl_setcontextvgavirtual (VGAMODE);
864     templatescreen = gl_allocatecontext ();
865     gl_getcontext (templatescreen);
866    
867     /* define physicalscreen as real screen */
868     gl_setcontextvga (VGAMODE);
869     physicalscreen = gl_allocatecontext ();
870     gl_getcontext (physicalscreen);
871    
872     gl_setcontext (physicalscreen); /* change to physicalscreen */
873     /* save_color_table(); output to file clrtbl.dnacgr */
874    
875     /* define fonts globally */
876     gl_setfont (8, 8, gl_font8x8);
877     gl_setwritemode (FONT_COMPRESSED + WRITEMODE_OVERWRITE);
878     show_about_screen (); /* whom you can't flame if you lose your job */
879     make_sequence_table (); /* this is not modified later */
880     user_request_handler (); /* main loop */
881    
882     /* free all memory */
883     gl_freecontext (fileplotscreen);
884     gl_freecontext (randomplotscreen);
885     gl_freecontext (templatescreen);
886     vga_setmode (TEXT); /* just to be safe */
887     }