Files
PlantAI-dev/tools/pymol-open-source/contrib/uiuc/plugins/molfile_plugin/src/carplugin.c
T
2026-08-03 18:42:47 +08:00

421 lines
12 KiB
C

/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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;
}