/* MACHINE GENERATED FILE, DO NOT EDIT! */ #define VMDPLUGIN molfile_carplugin #define STATIC_PLUGIN 1 /*************************************************************************** *cr *cr (C) Copyright 1995-2016 The Board of Trustees of the *cr University of Illinois *cr All Rights Reserved *cr ***************************************************************************/ /*************************************************************************** * RCS INFORMATION: * * $RCSfile: carplugin.c,v $ * $Author: johns $ $Locker: $ $State: Exp $ * $Revision: 1.18 $ $Date: 2016/11/28 05:01:53 $ * ***************************************************************************/ /* * Plugin for Insight II/Discover car (cartesian coordinate file) file format. * * TODO: * + 2D PBC info (probably just as a simplified 3D PBC) * + HELIX info (not sure how this will be handled) * * File Header: * !BIOSYM archive 3 * HELIX * (if HELIX information is present) * PBC=ON, PBC=OFF, PBC=2D * (one of these three choices must be present. PBC cannot be "ON" if * HELIX information is present.) * Coordinate Header: * Title (this line may be blank, but must be present) * 1-64 title for the system * 65-80 energy * ! DATE day month date time year * (day, month, date, time, year are optional) * PBC information if PBC=ON: * 1-3 PBC * 4-13 a cell vector a in angstroms * 14-23 b cell vector b in angstroms * 24-33 c cell vector c in angstroms * 34-43 alpha cell angle alpha in degrees * 44-53 beta cell angle beta in degrees * 54-63 gamma cell angle gamma in degrees * 64-80 space group name * PBC information if PBC=2D: * 1-3 PBC * 4-13 k plane vector k in angstroms * 14-23 l plane vector l in angstroms * 24-33 gamma plane angle gamma in degrees * 34-50 plane group name * Molecule Data: * If helix info is present: * 1-5 HELIX * 6-15 sigma in degrees * 16-25 d in angstroms * 26-35 kappa angle between l axis and helix axis in degrees * 36-45 lambda angle between k axis and helix axis in degrees * 46-55 Tk fractional position of helix axis along k axis * 56-65 Tl fractional position of helix axis along l axis * Atom data: * 1-5 atom name * 7-20 x Cartesian coordinate of atom in angstroms * 22-35 y Cartesian coordinate of atom in angstroms * 37-50 z Cartesian coordinate of atom in angstroms * 52-55 type of residue containing atom * 57-63 residue sequence name relative to beginning of current * molecule, left justified * 64-70 potential type of atom left justified * 72-73 element symbol * 75-80 partial charge on atom * Final line for a given molecule: * 1-3 end * Final line for the entire molecular system input: * 1-3 end * */ #include #include #include #include #include "molfile_plugin.h" #define LINESIZE 1024 /* possible values for pbc */ enum {PBC_ON, PBC_OFF, PBC_2D}; typedef struct { FILE *file; int numatoms, pbc, helix, eof; long coord_location; molfile_atom_t *atomlist; } cardata; /* Parse a line contianing atom data from a car file and store it in the * atom structure. Returns 1 on success, 0 on failure. */ static int read_car_structure_line(molfile_atom_t *atom, char *line) { char name[LINESIZE], type[LINESIZE]; int resid; float charge; if (sscanf(line, "%s %*f %*f %*f %*s %d %*s %s %f", name, &resid, type, &charge) != 4) return 0; /* check the length of the name and type strings before copying. */ if ( (strlen(name) >= 8) || (strlen(type) >= 8) ) return 0; strcpy(atom->name, name); strcpy(atom->type, type); /* Check that the resid won't overflow the resname string, then copy it * over */ if (resid > 9999999) atom->resname[0] = '\0'; else sprintf(atom->resname, "%d", resid); atom->resid = resid; atom->chain[0] = '\0'; atom->segid[0] = '\0'; atom->charge = charge; return 1; } /* Parse a line contianing atom coordinates from a car file and store them * in the array 'coords' in XYZ order. Returns 1 on success, 0 on failure. */ static int read_car_coordinates(float *coords, char *line) { float x, y, z; if (sscanf(line, "%*s %f %f %f %*s %*d %*s %*s %*f", &x, &y, &z) != 3) return 0; coords[0] = x; coords[1] = y; coords[2] = z; return 1; } static void *open_car_read(const char *filename, const char *filetype, int *natoms) { FILE *fd; cardata *data; char line[LINESIZE]; fd = fopen(filename, "rb"); if (!fd) return NULL; data = (cardata *)malloc(sizeof(cardata)); data->eof = 0; data->file = fd; /* First line: "!BIOSYM archive n", where n indicates the file format */ fgets(line, LINESIZE, fd); if (strncmp(line, "!BIOSYM archive", 15)) { fprintf(stderr, "ERROR) badly formatted/missing header.\n"); return NULL; } /* Second line: "HELIX" if helix information is present. Followed by PBC * info on the next line: "PBC=ON|OFF|2D". * If HELIX is present, PBC cannot be "ON": return an error if this happens. */ fgets(line, LINESIZE, fd); if (!strncmp(line, "HELIX", 5)) { data->helix = 1; fgets(line, LINESIZE, fd); fprintf(stdout, "WARNING) ignoring helix information.\n"); } else { data->helix = 0; } if (!strncmp(line, "PBC=ON", 6)) { data->pbc = PBC_ON; } else if (!strncmp(line, "PBC=OFF", 7)) { data->pbc = PBC_OFF; } else if (!strncmp(line, "PBC=2D", 6)) { data->pbc = PBC_2D; fprintf(stdout, "WARNING) ignoring 2D PBC information.\n"); } else { fprintf(stderr, "ERROR) badly formatted/missing PBC info.\n"); return NULL; } if (data->helix && (data->pbc == PBC_ON)) { fprintf(stderr, "ERROR) car file contains helix and 3D PBC information."); return NULL; } /* Next line: title/energy for the system. Skipped. */ fgets(line, LINESIZE, fd); /* Next line: "!DATE [day month date time year]". */ fgets(line, LINESIZE, fd); if (strncmp(line, "!DATE", 5)) { fprintf(stderr, "ERROR) badly formatted/missing date.\n"); return NULL; } /* Store the location of the beginning of the PBC/coordinate data. */ data->coord_location = ftell(fd); /* Skip the PBC and HELIX entries, if present */ if (data->pbc != PBC_OFF) fgets(line, LINESIZE, fd); if (data->helix) fgets(line, LINESIZE, fd); /* Count the atoms in all molecules*/ data->numatoms = 0; fgets(line, LINESIZE, fd); while(strncmp(line, "end", 3)) { while(strncmp(line, "end", 3)) { data->numatoms++; fgets(line, LINESIZE, fd); if (feof(fd)) { fprintf(stderr, "ERROR) unexpected end-of-file.\n"); return NULL; } if (ferror(fd)) { fprintf(stderr, "ERROR) error reading car file.\n"); return NULL; } } fgets(line, LINESIZE, fd); } *natoms = data->numatoms; return data; } static int read_car_structure(void *mydata, int *optflags, molfile_atom_t *atoms) { int mol_num; char line[LINESIZE]; molfile_atom_t *atom; cardata *data = (cardata *)mydata; *optflags = MOLFILE_CHARGE; /* car files contain partial charges */ /* move to the beginning of the atom data in the file, skipping any PBC or * HELIX information that may be present */ fseek(data->file, data->coord_location, SEEK_SET); if (data->pbc != PBC_OFF) fgets(line, LINESIZE, data->file); if (data->helix) fgets(line, LINESIZE, data->file); mol_num = 0; atom = atoms; fgets(line, LINESIZE, data->file); /* Loop through all molecules */ while(strncmp(line, "end", 3)) { /* Read the structure for each molecule */ while(strncmp(line, "end", 3)) { if (!read_car_structure_line(atom, line)) { fprintf(stderr, "ERROR) badly formatted structure line:\n%s\n", line); return MOLFILE_ERROR; } /* XXX - this code can easily create buffer overflows and cause data corruption or segfaults: XXX - use the chain name to identify different molecules sprintf(atom->chain, "%d", mol_num); we avoid the buffer overflow and use typical capital letters for the chain identifiers instead. */ sprintf(atom->chain, "%c", (char) (((int) 'A') + (mol_num % 26))); atom++; fgets(line, LINESIZE, data->file); if (feof(data->file)) { fprintf(stderr, "ERROR) unexpected end-of-file while reading structure.\n"); return MOLFILE_ERROR; } if (ferror(data->file)) { fprintf(stderr, "ERROR) error reading car file while reading structure.\n"); return MOLFILE_ERROR; } } fgets(line, LINESIZE, data->file); mol_num++; } return MOLFILE_SUCCESS; } static int read_car_timestep(void *mydata, int natoms, molfile_timestep_t *ts) { char line[LINESIZE]; cardata *data = (cardata *)mydata; float *coords = NULL; /* return if coordinates have been read */ if (data->eof) return MOLFILE_EOF; /* move to the beginning of the atom data in the file */ fseek(data->file, data->coord_location, SEEK_SET); /* read the PBC record if present */ if (data->pbc == PBC_ON) { fgets(line, LINESIZE, data->file); if (ts) { if ( sscanf(line, "PBC %f %f %f %f %f %f %*s", &ts->A, &ts->B, &ts->C, &ts->alpha, &ts->beta, &ts->gamma) != 6 ) { fprintf(stderr, "ERROR) badly formatted PBC line:\n%s\n", line); return MOLFILE_ERROR; } } } else if (data->pbc == PBC_2D) { /* XXX - Ignore 2D PBC information */ fgets(line, LINESIZE, data->file); } /* skip the helix record if present */ if (data->helix) fgets(line, LINESIZE, data->file); if (ts) coords = ts->coords; fgets(line, LINESIZE, data->file); /* Loop through all molecules */ while(strncmp(line, "end", 3)) { /* Read the coordinates for each molecule */ while(strncmp(line, "end", 3)) { /* only save coords if we're given a timestep pointer. */ if (ts) { if (!read_car_coordinates(coords, line)) { fprintf(stderr, "ERROR) badly formatted coordinate line:\n%s\n", line); return MOLFILE_ERROR; } coords += 3; } fgets(line, LINESIZE, data->file); if (feof(data->file)) { fprintf(stderr, "ERROR) unexpected end-of-file while reading coordinates.\n"); return MOLFILE_ERROR; } if (ferror(data->file)) { fprintf(stderr, "ERROR) file error while reading coordinates.\n"); return MOLFILE_ERROR; } } fgets(line, LINESIZE, data->file); } /* set eof since this file contians only one "timestep" */ data->eof = 1; return MOLFILE_SUCCESS; } static void close_car_read(void *mydata) { if (mydata) { cardata *data = (cardata *)mydata; fclose(data->file); free(data); } } /* registration stuff */ static molfile_plugin_t plugin; VMDPLUGIN_API int VMDPLUGIN_init() { memset(&plugin, 0, sizeof(molfile_plugin_t)); plugin.abiversion = vmdplugin_ABIVERSION; plugin.type = MOLFILE_PLUGIN_TYPE; plugin.name = "car"; plugin.prettyname = "InsightII car"; plugin.author = "Eamon Caddigan"; plugin.majorv = 0; plugin.minorv = 5; plugin.is_reentrant = VMDPLUGIN_THREADSAFE; plugin.filename_extension = "car"; plugin.open_file_read = open_car_read; plugin.read_structure = read_car_structure; plugin.read_next_timestep = read_car_timestep; plugin.close_file_read = close_car_read; return VMDPLUGIN_SUCCESS; } VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) { (*cb)(v, (vmdplugin_t *)&plugin); return VMDPLUGIN_SUCCESS; } VMDPLUGIN_API int VMDPLUGIN_fini() { return VMDPLUGIN_SUCCESS; }