JPRED-2 Add sources of all binaries (except alscript) to Git
[jpred.git] / sources / multicoil / scio.c
1 /*  Bonnie Berger, David Wilson and Theodore Tonchev 1992  */
2 /*  Modified by Ethan Wolf 1995 */
3 /*       C Code File       */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "sc.h"
9 #include "scio.h"
10 #include "scsystem.h"
11 #include "scconst.h"
12 #include <sys/types.h>
13 #include <netinet/in.h>
14 #include <unistd.h>
15
16 #include <pwd.h>   /*  For finding location of a ~usr directory. */
17
18 /* Amino Acid IDs */
19 /* char aaname[] = "LIVMFYGAKRHEDQNSTCWPX"; */
20 char aaname[]= "LIVMFYGAKRHEDQNSTCWPXBZ.";
21
22 /* Position IDs */
23 char posname[] = "abcdefg";
24
25 /* Array Sizes */
26 #define SIZEOFGTS  1
27 #define SIZEOFGFS  AANUM
28 #define SIZEOFGTP  POSNUM
29 #define SIZEOFGFP  (AANUM*AANUM*POSNUM)
30
31 #define SIZEOFPTS  POSNUM
32 #define SIZEOFPFS  (AANUM*POSNUM)
33 #define SIZEOFPTP  (POSNUM*POSNUM)
34 #define SIZEOFPFP  (AANUM*AANUM*POSNUM*POSNUM)
35
36 /* Magic Numbers */
37 #define GENFREQ_MAGIC "GenFreq 1 + 20 + 7 + 20x20x7 long\n"
38 #define POSFREQ_MAGIC "PosFreq 7 + 20x7 + 7x7 + 20x20x7x7 long\n"
39
40 #ifndef ERROR
41 #define ERROR(STR) error(FOPEN_ERR, (STR))
42 #endif
43 #define NULLERR(X) if (!(X)) error(FOPEN_ERR, name)
44 static fd_set _popened_files;
45 static fd_set *popened_files=NULL;
46
47 void open_file (FILE** fl, char* name, char* ops)
48 {
49   int str_len;
50   char cmd[256];
51
52   /* Initialize set of popened files */
53   if (!popened_files) {
54     popened_files = &_popened_files;
55     FD_ZERO(popened_files);
56   }
57   /* If we aren't reading, do the usual thing */
58   if (strcmp(ops,"r")) {
59     NULLERR(*fl = fopen(name, ops));
60     return; }
61   
62   /* If we're reading a .Z file, use zcat */
63   str_len = strlen(name);
64   if (str_len>256-8)
65     error(FOPEN_ERR,"file name too long for internal buffer");
66   strcpy(cmd,"zcat ");
67   strcat(cmd,name);
68   if (name[str_len-2]=='.' && name[str_len-1]=='Z') {
69     NULLERR(*fl = popen(cmd, "r"));
70     FD_SET(fileno(*fl),popened_files);
71     return; }
72
73   /* Otherwise, if the file exists, read it normally */
74   if (!access(name,F_OK)) {
75     NULLERR(*fl = fopen(name, ops));
76     return; }
77
78   /* And if the file doesn't exist, try adding .Z */
79   strcat(cmd,".Z");
80   if (!access(&(cmd[5]),F_OK)) {
81     NULLERR(*fl = popen(cmd, "r"));
82     FD_SET(fileno(*fl),popened_files);
83     return; }
84
85   /* The file does not exist. */
86   error(FOPEN_ERR,name);
87 }
88 void close_file (FILE *fl)
89 {
90   if (FD_ISSET(fileno(fl),popened_files)) {
91     FD_CLR(fileno(fl),popened_files);
92     pclose(fl);
93   }
94   else
95     fclose(fl);
96 }
97
98 void htonla();
99 void ntohla();
100
101
102
103 void writegenfreq(FILE* fl, 
104                   long totals[], long freqs[AANUM], 
105                   long totalp[POSNUM], long freqp[AANUM][AANUM][POSNUM],
106                   FILE* flog)
107 {
108   int i;
109
110   fputs("Writing Gen Frequences.\n", flog);
111
112   fputs(GENFREQ_MAGIC, fl);
113
114   htonla(totals, SIZEOFGTS);
115   if (fwrite(totals, sizeof(long), SIZEOFGTS, fl) != SIZEOFGTS)
116     error(FWRITE_ERR, "<GenFreq> file");
117
118   htonla(freqs, SIZEOFGFS);
119   if (fwrite(freqs, sizeof(long), SIZEOFGFS, fl) != SIZEOFGFS)
120     error(FWRITE_ERR, "<GenFreq> file");
121
122   htonla(totalp, SIZEOFGTP);
123   if (fwrite(totalp, sizeof(long), SIZEOFGTP, fl) != SIZEOFGTP)
124     error(FWRITE_ERR, "<GenFreq> file");
125
126   htonla(freqp, SIZEOFGFP);
127   if (fwrite(freqp, sizeof(long), SIZEOFGFP, fl) != SIZEOFGFP)
128     error(FWRITE_ERR, "<GenFreq> file");
129 }
130
131 void readgenfreq(FILE* fl, 
132                  long totals[], long freqs[AANUM], 
133                  long totalp[POSNUM], long freqp[AANUM*AANUM*POSNUM],
134                  FILE* flog)
135 {
136   char line[MAXLINE];
137   int i;
138
139   fputs("Reading Gen Frequences.\n", flog);
140
141   if (strlen(GENFREQ_MAGIC) > 0) {
142     fgets(line, MAXLINE, fl);
143     if (strcmp(line, GENFREQ_MAGIC))
144       error(MAGIC_ERR, "<GenFreq> file");
145   }
146
147 /*
148   if (fread(totals, sizeof(long), SIZEOFGTS, fl) != SIZEOFGTS)
149     error(FREAD_ERR, "<GenFreq> file");
150   ntohla(totals, SIZEOFGTS);
151
152   if (fread(freqs, sizeof(long), SIZEOFGFS, fl) != SIZEOFGFS)
153     error(FREAD_ERR, "<GenFreq> file");
154   ntohla(freqs, SIZEOFGFS);
155
156   if (fread(totalp, sizeof(long), SIZEOFGTP, fl) != SIZEOFGTP)
157     error(FREAD_ERR, "<GenFreq> file");
158   ntohla(totalp, SIZEOFGTP);
159
160   if (fread(freqp, sizeof(long), SIZEOFGFP, fl) != SIZEOFGFP)
161     error(FREAD_ERR, "<GenFreq> file");
162   ntohla(freqp, SIZEOFGFP);
163 */
164
165   for (i = 0; i < SIZEOFGTS; i++) {
166     fscanf(fl, "%ld", &totals[i]);
167   }
168   for (i = 0; i < SIZEOFGFS; i++) {
169     fscanf(fl, "%ld", &freqs[i]);
170   }
171   for (i = 0; i < SIZEOFGTP; i++) {
172     fscanf(fl, "%ld", &totalp[i]);
173   }
174   for (i = 0; i < SIZEOFGFP; i++) {
175     fscanf(fl, "%ld", &freqp[i]);
176   }
177
178 /*
179   printf("gtotals\n");
180   for (i = 0; i < SIZEOFGTS; i++) {
181     printf("%ld\n", totals[i]);
182   }
183   printf("gfreqs\n");
184   for (i = 0; i < SIZEOFGFS; i++) {
185     printf("%ld\n", freqs[i]);
186   }
187   printf("gtotalp\n");
188   for (i = 0; i < SIZEOFGTP; i++) {
189     printf("%ld\n", totalp[i]);
190   }
191   printf("gfreqp\n");
192   for (i = 0; i < SIZEOFGFP; i++) {
193     printf("%ld\n", freqp[i]);
194   }
195 */
196 }
197
198
199 void writeposfreq(FILE* fl,
200                   long totals[POSNUM], long freqs[AANUM][POSNUM],
201                   long totalp[POSNUM][POSNUM], 
202                   long freqp[AANUM][AANUM][POSNUM][POSNUM],
203                   FILE* flog)
204 {
205   int i,j;
206
207   fputs("Writing Position Frequences.\n", flog);
208
209   fputs(POSFREQ_MAGIC, fl);
210
211   htonla(totals, SIZEOFPTS);
212   if (fwrite(totals, sizeof(long), SIZEOFPTS, fl) != SIZEOFPTS)
213     error(FWRITE_ERR, "<PosFreq> file");
214
215   htonla(freqs, SIZEOFPFS);
216   if (fwrite(freqs, sizeof(long), SIZEOFPFS, fl) != SIZEOFPFS)
217     error(FWRITE_ERR, "<PosFreq> file");
218
219   htonla(totalp, SIZEOFPTP);
220   if (fwrite(totalp, sizeof(long), SIZEOFPTP, fl) != SIZEOFPTP)
221     error(FWRITE_ERR, "<PosFreq> file");
222
223   htonla(freqp, SIZEOFPFP);
224   if (fwrite(freqp, sizeof(long), SIZEOFPFP, fl) != SIZEOFPFP)
225     error(FWRITE_ERR, "<PosFreq> file");
226 }
227
228 void readposfreq(FILE* fl,
229                  long totals[POSNUM], long freqs[AANUM*POSNUM],
230                  long totalp[POSNUM*POSNUM], 
231                  long freqp[AANUM*AANUM*POSNUM*POSNUM],
232                  FILE* flog)
233 {
234   char line[MAXLINE];
235   int i;
236
237   fprintf(flog, "Reading Position Frequences.\n");
238
239   if (strlen(POSFREQ_MAGIC) > 0) {
240     fgets(line, MAXLINE, fl);
241     if (strcmp(line, POSFREQ_MAGIC))
242       error(MAGIC_ERR, "<PosFreq> file");
243   }
244 /*
245   if (fread(totals, sizeof(long), SIZEOFPTS, fl) != SIZEOFPTS)
246     error(FREAD_ERR, "<PosFreq> file");
247   ntohla(totals, SIZEOFPTS);
248
249   if (fread(freqs, sizeof(long), SIZEOFPFS, fl) != SIZEOFPFS)
250     error(FREAD_ERR, "<PosFreq> file");
251   ntohla(freqs, SIZEOFPFS);
252
253   if (fread(totalp, sizeof(long), SIZEOFPTP, fl) != SIZEOFPTP)
254     error(FREAD_ERR, "<PosFreq> file");
255   ntohla(totalp, SIZEOFPTP);
256
257   if (fread(freqp, sizeof(long), SIZEOFPFP, fl) != SIZEOFPFP)
258     error(FREAD_ERR, "<PosFreq> file");
259   ntohla(freqp, SIZEOFPFP);
260 */
261
262   for (i = 0; i < SIZEOFPTS; i++) {
263     fscanf(fl, "%ld", &totals[i]);
264   }
265   for (i = 0; i < SIZEOFPFS; i++) {
266     fscanf(fl, "%ld", &freqs[i]);
267   }
268   for (i = 0; i < SIZEOFPTP; i++) {
269     fscanf(fl, "%ld", &totalp[i]);
270   }
271   for (i = 0; i < SIZEOFPFP; i++) {
272     fscanf(fl, "%ld", &freqp[i]);
273   }
274
275
276 /*
277   for (i = 0; i < SIZEOFPTS; i++) {
278     printf("%d\n", totals[i]);
279   }
280   for (i = 0; i < SIZEOFPFS; i++) {
281     printf("%d\n", freqs[i]);
282   }
283   for (i = 0; i < SIZEOFPTP; i++) {
284     printf("%d\n", totalp[i]);
285   }
286   for (i = 0; i < SIZEOFPFP; i++) {
287     printf("%d\n", freqp[i]);
288   }
289 */
290 }
291
292 void htonla(long arr[], int size)
293 {
294   int i;
295   
296   for (i = 0; i < size; i++) 
297     arr[i] = htonl(arr[i]);
298 }
299
300 void ntohla(long arr[], int size)
301 {
302   int i;
303   
304   for (i = 0; i < size; i++) 
305     arr[i] = ntohl(arr[i]);
306 }
307
308
309 int getseq(FILE* fl, char seq[MAXSEQLEN], int* offset, int* seqlen,
310            char *title)
311 {
312   char line[MAXLINE];
313   char ch;
314   int i;
315   
316   if (title) *title = 0;
317   *seqlen = 0;
318   *offset = POSNUM;
319   while (1) {
320     if (! (fgets (line, MAXLINE, fl)) )
321       return 0;
322     if (!strncmp("OFFSET", line, 6) || line[0] == '>' || 
323         !strncmp("  ..", line+strlen(line)-5, 4)) {
324       if (line[0] == '>') 
325         if (title) {
326           fgets (title, MAXLINE, fl); /* skips label */
327           title[strlen(title)-1] = 0;
328         }
329         else
330           fgets (line, MAXLINE, fl); /* skips label */
331       if (!strncmp("OFFSET", line, 6))
332         if (line[6] && line[7] >= '0' && line[7] <= '6')
333           *offset = line[7] - '0'; 
334         else *offset = DEFOFFSET;
335       while (1) {
336         if (! (fgets (line, MAXLINE, fl)) )
337           return 1;
338         for (i=0; line[i]; i++)
339           if ((ch = aanum(line[i])) != -1)
340             seq[(*seqlen)++] = ch;
341           else if (line[i] == '*' || 
342                    (line[i] == '/' && line[i+1] == '/'))
343             return 1;
344       }
345     }
346   }
347 }
348
349
350 int getseq2 (FILE* fl, Sequence *sequence)
351 {
352   char line[MAXLINE];
353   char *res = sequence->seq, *tmp;
354   int i, j, cc;
355   int posr=0;
356   
357   sequence->title[0] = 0;
358   while (fgets(line, MAXLINE, fl)) {
359     if (line[0] == '>') {
360   /* Copy the line - ">" into the code */
361       strcpy(sequence->code,&(line[1]));
362
363   /*  We make tmp point to the first space, \t or \n in the line.  We then */
364   /*  change that space, \t or \n to a 0, and make tmp point to the next   */
365   /*  non space, \t or \n  character.  If there is none (i.e. the line had */
366   /*  ended so there are no more characters), then tmp[0]=0 still.  In this*/
367   /*  case, the next line holds the title.  Otherwise, the next series of  */
368   /*  characters in the line are the title.                                */
369
370       tmp = &(sequence->code[strcspn(sequence->code," \t\n")]);
371       tmp[0]=0;
372       tmp = &(tmp[strspn(&tmp[1]," \t\n") + 1]);
373       
374       if (tmp[0]) /* Read more characters after the code, so probably FASTA. */
375         strcpy(sequence->title,tmp); 
376       else
377         fgets (sequence->title, MAXLINE, fl);
378       sequence->title[strlen(sequence->title)-1] = 0;  /* Remove the newline.*/
379
380
381       while (1) {
382         cc=fgetc(fl);   /** We want to check the first character of the    */
383                         /** next line without reading in the whole line.   */
384         ungetc(cc,fl);  /** Put the character back onto the next line.     */ 
385
386         if ((cc != EOF) && (cc != '>')) {  
387           /** If we are not starting the next sequence:     */
388           fgets(line, MAXLINE, fl); 
389           for (i=0; line[i] && ( (res-sequence->seq) < MAXSEQLEN); i++)
390             switch (toupper(line[i])) {
391             case 'L': *(res++) = Leucine; break;
392             case 'I': *(res++) = Isoleucine; break;
393             case 'V': *(res++) = Valine; break;
394             case 'M': *(res++) = Methionine; break;
395             case 'F': *(res++) = Phenylalanine; break;
396             case 'Y': *(res++) = Tyrosine; break;
397             case 'G': *(res++) = Glycine; break;
398             case 'A': *(res++) = Alanine; break;
399             case 'K': *(res++) = Lysine; break;
400             case 'R': *(res++) = Arginine; break;
401             case 'H': *(res++) = Histidine; break;
402             case 'E': *(res++) = GlutamicAcid; break;
403             case 'D': *(res++) = AsparticAcid; break;
404             case 'Q': *(res++) = Glutamine; break;
405             case 'N': *(res++) = Asparagine; break;
406             case 'S': *(res++) = Serine; break;
407             case 'T': *(res++) = Threonine; break;
408             case 'C': *(res++) = Cysteine; break;
409             case 'W': *(res++) = Tryptophan; break;
410             case 'P': *(res++) = Proline; break;
411             case 'X': *(res++) = AnyRes; break;
412             case 'B': *(res++) = Asparagix; break;
413             case 'Z': *(res++) = Glutamix; break;
414 /*            fprintf(stderr,"Warning, not dealing with B or Z.\n"); 
415               *(res++) = AnyRes; break;
416 */
417             case '(':
418             case ')':
419             case '=':
420             case '/':
421             case '.':
422             case ',':
423               /* fprintf(stderr,"Warning, not dealing with punctuation.\n"); */
424               break;
425
426
427             case '*':
428               sequence->seqlen = (res-sequence->seq);
429
430           /* Get the register info if any */
431               while (1) {
432                 switch (cc=getc(fl)) {
433                 case '>':       /* Next sequence */
434                   ungetc(cc,fl); 
435                   if (posr==0) {sequence->reg = NULL; return 1;}
436                   if (posr==sequence->seqlen) return 1;
437                   fprintf(stderr, "Erroneous .pos file!\n"); exit(-1);
438                   break;
439                 case EOF:
440                   if (posr==0) {sequence->reg = NULL; return 1;}
441                   if (posr==sequence->seqlen) return 1;
442                   fprintf(stderr, "Erroneous .pos file!\n"); exit(-1);
443                   break;
444                 default:
445                   ungetc(cc,fl);
446                 }
447
448                 fgets(line, MAXLINE, fl);
449                 for (j=0; line[j]; j++) {
450                   switch (cc = line[j]) {
451                   case 'a':
452                   case 'b':
453                   case 'c':
454                   case 'd':
455                   case 'e':
456                   case 'f':
457                   case 'g':
458                     sequence->reg[posr++] = cc-'a';
459                     break;
460                   case '.':
461                     sequence->reg[posr++] = '.'; 
462                                           /* not 'genbank', but unspecified */
463                     break;
464                   case '*':
465                     if (posr==sequence->seqlen) return 1;
466                     if (posr ==0) {sequence->reg = NULL; return 1;}
467                                               /* A 2nd * indicates not pos. */
468                     fprintf(stderr, "Erroneous .pos file!\n"); exit(-1);
469                   case ' ':
470                   case '\n':
471                   case '\t':
472                     break;
473                   default:
474                     fprintf(stderr,"Unable to parse input.\n");
475                     exit(-1);
476                   }
477                 }
478               }
479               return 1;    /*** A '*' signals the end of the input seq for */
480                           /*** non-FASTA format.                          */
481             case ' ':
482             case '\n':
483             case '\t':
484               break;
485             default:
486               printf("Unable to parse input %c.\n", line[i]);
487               exit(-1);
488             }   /* Ends the switch and the for loop */
489
490           if ( (res-sequence->seq)==MAXSEQLEN) { /* couldn't read whole seq. */
491             sequence->seqlen=MAXSEQLEN;
492             fprintf(stderr,"\nSequence %s was to long to read all of.",
493                     sequence->code);
494           }
495         }
496         else {
497           sequence->seqlen = (res-sequence->seq);
498           return 1;  /*  If we read a 2nd > or and EOF then we have finished */
499                      /*  reading the seq. */
500         }
501       }
502       printf("Unexpected end of input.\n");
503       exit(-1);
504     }
505   }
506   return 0;
507 }
508
509 char aanum(char ch)
510 {
511   int i;
512
513   ch = toupper(ch);
514   for (i = 0; aaname[i]; i++)
515     if (ch == aaname[i])
516       return i;
517   return -1;
518 }
519
520
521
522 char numaa(char ch)
523 {
524   if (ch >= 0 && ch < strlen(aaname))
525     return aaname[ch];
526   else 
527     return 0;
528 }
529
530 char posnum(char ch)
531 {
532   int i;
533   for (i = 0; posname[i]; i++)
534     if (ch == posname[i])
535       return i;
536   return -1;
537 }
538
539 char numpos(char ch)
540 {
541   if (ch >= 0 && ch < strlen(posname))
542     return posname[ch];
543   else
544     return 0;
545 }
546
547 FILE *sopen (char* name, char* ops)
548 {
549   FILE *fl;
550   int str_len;
551   char cmd[256];
552   char temp_name[500];
553   char usr_name[50];
554   int i;
555   
556   /* Initialize set of popened files */
557   if (!popened_files) {
558     popened_files = &_popened_files;
559     FD_ZERO(popened_files);
560   }
561   /* Is name valid? */
562   if (!name) return NULL;
563
564   /* Maybe we user wants stdin or stdout */
565   if (!strcmp(name,"-")) {
566     if (!strcmp(ops,"r"))
567       return stdin;
568     if (!strcmp(ops,"w"))
569       return stdout;
570     ERROR(name);
571   }
572   /* If writing and filename starts with "|", use popen */
573   if (!strcmp(ops,"w") && name[0]=='|') {
574     NULLERR(fl = popen(&(name[1]), ops));
575     FD_SET(fileno(fl),popened_files);
576     return fl; }
577
578   if (name[0]=='~') 
579     if (name[1]=='/') {   /* Manually find the home dir. */
580       strcpy(temp_name,getenv("HOME"));       /* Get home directory. */
581       strcat(temp_name, &name[1]);            /* Put it in place of ~ */
582       name= temp_name;
583     } 
584     else {          /*  Convert ~usr into /location/usr */
585       strncpy(usr_name, &name[1], strcspn(&name[1],"/"));  
586              /*  Figures out length of usr name (between ~ and /)  */
587              /*  and copies the usrname into usr_name.  Then we need */
588              /*  to add end of string character.                     */
589       usr_name[strcspn(&name[1],"/")] = 0;  /*  End of string. */
590
591       strcpy(temp_name, getpwnam(usr_name)->pw_dir);  
592                                /* copies name of usr login dir to temp_name */
593
594       strcat(temp_name, &name[strcspn(name,"/")]);  /*  Replaces ~ with */
595                                                     /*  /location       */
596       name= temp_name;
597     }
598
599      
600    
601   /* If we aren't reading, do the usual thing */
602   if (strcmp(ops,"r")) {
603     NULLERR(fl = fopen(name, ops));
604     return fl; }
605   
606   /* If we're reading a .Z file, use zcat */
607   str_len = strlen(name);
608   if (str_len>256-16)
609     ERROR("file name too long for internal buffer");
610
611   if (name[str_len-2]=='.' && name[str_len-1]=='Z') {
612     strcpy(cmd,"zcat ");
613     strcat(cmd,name);
614     NULLERR(fl = popen(cmd, "r"));
615     FD_SET(fileno(fl),popened_files);
616     return fl; }
617
618   /* Otherwise, if the file exists, read it normally */
619   if (!access(name,F_OK)) {
620     NULLERR(fl = fopen(name, ops));
621     return fl; }
622
623   /* And if the file doesn't exist, try adding .Z */
624   strcpy(cmd,"zcat ");
625   strcat(cmd,name);
626   strcat(cmd,".Z");
627   if (!access(&(cmd[5]),F_OK)) {
628     NULLERR(fl = popen(cmd, "r"));
629     FD_SET(fileno(fl),popened_files);
630     return fl; }
631
632   /* The file does not exist. */
633   ERROR(name);
634 }
635
636 void sclose (FILE *fl)
637 {
638   if (FD_ISSET(fileno(fl),popened_files)) {
639     FD_CLR(fileno(fl),popened_files);
640     pclose(fl);
641   }
642   else
643     fclose(fl);
644 }
645
646 /*       End of Code       */