/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                              R E A D P D B . C                               *
*                                                                              *
*          Copyright (c) Joerg-R. Hill, Andrew Dalke, October 2003             *
*                                                                              *
********************************************************************************
*
* $Id: readpdb.c,v 1.3 2003/11/07 11:14:45 jrh Exp $
* $Log: readpdb.c,v $
* Revision 1.3  2003/11/07 11:14:45  jrh
* Release 2.4
*
* Revision 1.2  2000/12/10 15:37:08  jrh
* Release 2.3
*
* Revision 1.1  1999/05/24 01:29:21  jrh
* Initial revision
*
*/
#include<ctype.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

#define TRUE  1
#define FALSE 0
#define MAXLENLINE 132

int main(int, char **);
int get_pdb_fields(char *, char *, char *, char *, char *, char *, char *,
                   double *, double *, double *, double *, double *);
void get_pdb_coordinates(char *, double *, double *, double *, double *,
                         double *);

extern void eof(char *, char *, int);

int main(int argc, char **argv)
{
  FILE *file;
  double x, y, z, occup, beta;
  int first=TRUE;
  char line[MAXLENLINE], *word;
  char name[5], resname[5], chain[2], segname[5], resid[5], insertion[2];
  register int i;
  register char *p;

  if ((file=fopen(argv[1], "r")) == NULL) eof("noFile", argv[1], 1);

  while (fgets(line, MAXLENLINE, file) != NULL)
  {
    word=strtok(line, " \t");
    if (!strcmp(word, "COMPND"))
    {
	if ((word=strstr(&line[7], "MOLECULE")) != NULL)
	{
	  printf("$title\n");
	  word=strchr(word, ' ')+1;
	  if ((p=strchr(word, ';')) != NULL) *p='\0';
	  printf("%s\n", word);
	}
    }
    else if (!strcmp(word, "ATOM") || !strcmp(word, "HETATM"))
    {
	(void)get_pdb_fields(line, name, resname, chain, segname, resid,
				   insertion, &x, &y, &z, &occup, &beta);
	if (first)
	{
	  printf("$coord 1.0\n");
	  first=FALSE;
	}
	printf("%22.14f  %22.14f  %22.14f  %s\n", x, y, z, name);
    }
    else if (!strcmp(word, "CRYST1"))
    {
	printf("$unitcell ");
	i=0;
	while ((word=strtok(NULL, " \t")) != NULL && i < 6)
	{
	  printf("%s ", word);
	  i++;
      }
      printf("\n");
    }
  }
  printf("$end\n");
  fclose(file);
  exit(0);
} 

int get_pdb_fields(char *record, char *name, char *resname, char *chain,
                   char *segname, char *resid, char *insertion, double *x,
                   double *y, double *z, double *occup, double *beta)
{
/* Break a pdb ATOM record into its fields.  The user must provide the
   necessary space to store the atom name, residue name, and segment name.
   Character strings will be null-terminated.  Returns the atom serial number. */

  int i,len, num;

  /* get serial number */
  if (record[6] >= 'A' && record[6] <= 'Z') {
    /* If there are too many atoms, XPLOR uses 99998, 99999, A0000, 
       A0001, ... */
    int base = ((int)(record[6] - 'A') + 10) * 100000;
    sscanf(record + 6, "%d", &num);
    num += base;
  } else {
    sscanf(record + 6,"%d",&num);
  }

  /* get atom name */
  strncpy(name,record + 12, 2);
  name[2]='\0';
  if (name[0] == ' ' || isdigit(name[0]))
  {
    name[0]=name[1];
    name[1]='\0';
  }
  name[1]=tolower(name[1]);

  /* get residue name */
  strncpy(resname,record + 17, 4);
  resname[4] = '\0';
  while((len = strlen(resname)) > 0 && resname[len-1] == ' ')
    resname[len-1] = '\0';
  while(len > 0 && resname[0] == ' ') {
    for(i=0; i < len; i++)  resname[i] = resname[i+1];
    len--;
  }

  chain[0] = record[21];
  chain[1] = 0;

  /* get residue id number */
  strncpy(resid,record + 22, 4);
  resid[4] = '\0';
  while((len = strlen(resid)) > 0 && resid[len-1] == ' ')
    resid[len-1] = '\0';
  while(len > 0 && resid[0] == ' ') {
    for(i=0; i < len; i++)  resid[i] = resid[i+1];
    len--;
  }

  insertion[0] = record[26];
  insertion[1] = 0;

  /* get x, y, and z coordinates */
  get_pdb_coordinates(record, x, y, z, occup, beta);

  /* get segment name   */
  if(strlen(record) >= 73) {
    strncpy(segname, record + 72, 4);
    segname[4] = '\0';
    while((len = strlen(segname)) > 0 && segname[len-1] == ' ')
      segname[len-1] = '\0';
    while(len > 0 && segname[0] == ' ') {
      for(i=0; i < len; i++)  segname[i] = segname[i+1];
      len--;
    }
  } else {
    strcpy(segname,"");
  }
   
  return num;
}

void get_pdb_coordinates(char *record, double *x, double *y, double *z,
                         double *occup, double *beta)
{
/* Extract the x,y, and z coordinates from the given ATOM record. */
  char numstr[9];

  /* get X, Y, and Z */
  memset(numstr, 0, 9 * sizeof(char));
  strncpy(numstr, record + 30, 8);
  *x = atof(numstr);
  memset(numstr, 0, 9 * sizeof(char));
  strncpy(numstr, record + 38, 8);
  *y = atof(numstr);
  memset(numstr, 0, 9 * sizeof(char));
  strncpy(numstr, record + 46, 8);
  *z = atof(numstr);
  memset(numstr, 0, 9 * sizeof(char));
  strncpy(numstr, record + 54, 6);
  *occup = atof(numstr);
  memset(numstr, 0, 9 * sizeof(char));
  strncpy(numstr, record + 60, 6);
  *beta = atof(numstr);
}
