From b42c1f45c0593958d3d75add785342712d684dbb Mon Sep 17 00:00:00 2001
From: Giovanni Bussi <giovanni.bussi@gmail.com>
Date: Tue, 14 Apr 2015 09:34:16 +0200
Subject: [PATCH] Added crd plugin

This allows reading crd files without linking external plugins
---
 regtest/basic/rt-molfile-4/config |   1 -
 regtest/basic/rt-molfile-5/config |   1 -
 src/molfile/crdplugin.cpp         | 259 ++++++++++++++++++++++++++++++
 src/molfile/libmolfile_plugin.h   |   6 +
 4 files changed, 265 insertions(+), 2 deletions(-)
 create mode 100644 src/molfile/crdplugin.cpp

diff --git a/regtest/basic/rt-molfile-4/config b/regtest/basic/rt-molfile-4/config
index b2e719f1e..1906c7544 100644
--- a/regtest/basic/rt-molfile-4/config
+++ b/regtest/basic/rt-molfile-4/config
@@ -1,3 +1,2 @@
 type=driver
-plumed_needs=external-molfile
 arg="--plumed plumed.dat --mf_crd test.crd --natoms 2257"
diff --git a/regtest/basic/rt-molfile-5/config b/regtest/basic/rt-molfile-5/config
index 23bc4f0b1..32ed95d5b 100644
--- a/regtest/basic/rt-molfile-5/config
+++ b/regtest/basic/rt-molfile-5/config
@@ -1,3 +1,2 @@
 type=driver
-plumed_needs=external-molfile
 arg="--plumed plumed.dat --mf_crdbox test.crd --natoms 9560"
diff --git a/src/molfile/crdplugin.cpp b/src/molfile/crdplugin.cpp
new file mode 100644
index 000000000..14eb5e218
--- /dev/null
+++ b/src/molfile/crdplugin.cpp
@@ -0,0 +1,259 @@
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+University of Illinois Open Source License
+Copyright 2003 Theoretical and Computational Biophysics Group, 
+All rights reserved.
+
+Developed by:		Theoretical and Computational Biophysics Group
+			University of Illinois at Urbana-Champaign
+			http://www.ks.uiuc.edu/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the Software), to deal with 
+the Software without restriction, including without limitation the rights to 
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to 
+do so, subject to the following conditions:
+
+Redistributions of source code must retain the above copyright notice, 
+this list of conditions and the following disclaimers.
+
+Redistributions in binary form must reproduce the above copyright notice, 
+this list of conditions and the following disclaimers in the documentation 
+and/or other materials provided with the distribution.
+
+Neither the names of Theoretical and Computational Biophysics Group, 
+University of Illinois at Urbana-Champaign, nor the names of its contributors 
+may be used to endorse or promote products derived from this Software without 
+specific prior written permission.
+
+THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
+THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
+OTHER DEALINGS WITH THE SOFTWARE.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/***************************************************************************
+ *cr
+ *cr            (C) Copyright 1995-2009 The Board of Trustees of the
+ *cr                        University of Illinois
+ *cr                         All Rights Reserved
+ *cr
+ ***************************************************************************/
+
+/***************************************************************************
+ * RCS INFORMATION:
+ *
+ *      $RCSfile: crdplugin.c,v $
+ *      $Author: johns $       $Locker:  $             $State: Exp $
+ *      $Revision: 1.39 $       $Date: 2013/04/13 03:29:48 $
+ *
+ ***************************************************************************/
+
+/*
+ * TODO: This plugin should probably be merged with the 'rst7' plugin, since
+ *       the differences between them are minor, and there's no logical reason
+ *       for them to be implemented completely independently as they are now.
+ *       The major differences in formatting are in regard to the 6F12.7 (rst7)
+ *       versus 10F8.3 (crd) ascii floating point conversion modes. 
+ */
+
+#include "largefiles.h"   /* platform dependent 64-bit file I/O defines */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "molfile_plugin.h"
+
+namespace PLMD{
+namespace molfile{
+
+typedef struct {
+  FILE *file;
+  int has_box;
+  int numatoms;
+} crddata;
+ 
+static void *open_crd_read(const char *filename, const char *filetype, 
+    int *natoms) {
+ 
+  FILE *fd;
+  crddata *data;
+ 
+  fd = fopen(filename, "rb");
+  if (!fd) return NULL;
+  
+  /* first line is title, so skip past it */
+  while (getc(fd) != '\n');
+
+  /* 
+   * CRD's don't store the number of atoms in the timestep, so we assume that
+   * the application will determine this for us.  
+   */
+  data = (crddata *)malloc(sizeof(crddata));
+  data->file = fd;
+  *natoms = MOLFILE_NUMATOMS_UNKNOWN;
+  /* filetype "crd" has no box; filetype "crdbox" does. */
+  data->has_box = strcmp(filetype, "crd"); 
+  return data;
+}
+
+/*
+ * CRD files with box info are indistinguishable from regular CRD's.  
+ * We regard CRD's with box info as a different file format.
+ * CRD's don't tell how many atoms there are in each frame.  We therefore
+ * rely on the numatoms field in the molfile_timestep_t parameter.
+ */
+static int read_crd_timestep(void *mydata, int natoms, molfile_timestep_t *ts) {
+  crddata *crd = (crddata *)mydata;
+  int i, j;
+  float x, y, z;
+  float a, b, c;
+
+  /* Read in the atom coordinates */
+  for (i=0; i<natoms; i++) {
+    j = fscanf(crd->file, "%f %f %f", &x, &y, &z);
+    if (j == EOF) {
+      return MOLFILE_ERROR;
+    } else if (j <= 0) {
+      fprintf(stderr, "Problem reading CRD file\n");
+      return MOLFILE_ERROR;
+    }
+
+    /* only save coords if we're given a valid ts pointer */ 
+    /* otherwise assume that VMD wants us to skip it.     */
+    if (ts != NULL) {
+      ts->coords[3*i  ] = x;
+      ts->coords[3*i+1] = y;
+      ts->coords[3*i+2] = z;
+    }
+  }
+
+
+  /* Read the PBC box info. */
+  if (crd->has_box) {
+    j = fscanf(crd->file, "%f %f %f", &a, &b, &c);
+    if (j == EOF) {
+      printf("EOF in box\n");
+      return MOLFILE_ERROR;
+    } else if (j <= 0) {
+      printf("Problem reading box part of CRD file, scanf returned %d\n",j);
+      return MOLFILE_ERROR;
+    }
+
+    /* only save coords if we're given a valid ts pointer */ 
+    /* otherwise assume that VMD wants us to skip it.     */
+    if (ts != NULL) {
+      ts->A = a;
+      ts->B = b;
+      ts->C = c;
+
+      /* XXX periodic cell angles are only stored in the PARM file */
+      /* we should probably retrieve these from the already-loaded */
+      /* molecule when possible.                                   */
+      ts->alpha = 90.0;
+      ts->beta  = 90.0;
+      ts->gamma = 90.0;
+    }
+  }
+
+  return MOLFILE_SUCCESS;
+}
+    
+static void close_crd_read(void *mydata) {
+  crddata *crd = (crddata *)mydata;
+  fclose(crd->file);
+  free(crd);
+}
+
+static void *open_crd_write(const char *path, const char *filetype,
+    int natoms) {
+  crddata *crd;
+  FILE *fd;
+
+  fd = fopen(path, "wb");
+  if (!fd) {
+    fprintf(stderr, "Could not open file %s for writing\n", path);
+    return NULL;
+  }
+  fprintf(fd, "TITLE : Created by VMD with %d atoms\n", natoms);
+  
+  crd = (crddata *)malloc(sizeof(crddata));
+  crd->file = fd;
+  crd->numatoms = natoms;
+  crd->has_box = strcmp(filetype, "crd"); 
+  return crd;
+}    
+  
+static int write_crd_timestep(void *v, const molfile_timestep_t *ts) {
+  crddata *crd = (crddata *)v;
+  int i;
+  int lfdone=0;
+  const int ndata = crd->numatoms * 3;
+
+  for (i=0; i<ndata; i++) {
+    lfdone = 0;
+    fprintf(crd->file, "%8.3f", ts->coords[i]);
+    if ((i+1) % 10 == 0) {
+      fprintf(crd->file, "\n"); 
+      lfdone = 1;
+    }
+  }
+  if (!lfdone)
+    fprintf(crd->file, "\n"); 
+    
+  if (crd->has_box) {
+    fprintf (crd->file, "%8.3f%8.3f%8.3f\n", ts->A, ts->B, ts->C);
+  }
+
+  return MOLFILE_SUCCESS;
+}
+
+static void close_crd_write(void *v) {
+  crddata *crd = (crddata *)v;
+  fclose(crd->file);
+  free(crd);
+}
+
+/* registration stuff */
+    
+static molfile_plugin_t plugin;
+static molfile_plugin_t crdboxplugin;
+
+VMDPLUGIN_API int VMDPLUGIN_init(void) { 
+  memset(&plugin, 0, sizeof(molfile_plugin_t));
+  plugin.abiversion = vmdplugin_ABIVERSION;
+  plugin.type = MOLFILE_PLUGIN_TYPE;
+  plugin.name = "crd";
+  plugin.prettyname = "AMBER Coordinates";
+  plugin.author = "Justin Gullingsrud, John Stone";
+  plugin.majorv = 0;
+  plugin.minorv = 9;
+  plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
+  plugin.filename_extension = "mdcrd,crd";
+  plugin.open_file_read = open_crd_read;
+  plugin.read_next_timestep = read_crd_timestep;
+  plugin.close_file_read = close_crd_read;
+  plugin.open_file_write = open_crd_write;
+  plugin.write_timestep = write_crd_timestep;
+  plugin.close_file_write = close_crd_write;
+
+  memcpy(&crdboxplugin, &plugin, sizeof(molfile_plugin_t));
+  crdboxplugin.name = "crdbox";
+  crdboxplugin.prettyname = "AMBER Coordinates with Periodic Box";
+
+  return VMDPLUGIN_SUCCESS; 
+}
+
+VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
+  (*cb)(v, (vmdplugin_t *)&plugin);
+  (*cb)(v, (vmdplugin_t *)&crdboxplugin);
+  return VMDPLUGIN_SUCCESS;
+}
+
+VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
+
+}
+}
+
diff --git a/src/molfile/libmolfile_plugin.h b/src/molfile/libmolfile_plugin.h
index decef25e1..cf78a7f4e 100644
--- a/src/molfile/libmolfile_plugin.h
+++ b/src/molfile/libmolfile_plugin.h
@@ -44,6 +44,9 @@ namespace molfile{
  int molfile_dcdplugin_init(void);
  int molfile_dcdplugin_register(void *, vmdplugin_register_cb);
  int molfile_dcdplugin_fini(void);
+ int molfile_crdplugin_init(void);
+ int molfile_crdplugin_register(void *, vmdplugin_register_cb);
+ int molfile_crdplugin_fini(void);
  int molfile_gromacsplugin_init(void);
  int molfile_gromacsplugin_register(void *, vmdplugin_register_cb);
  int molfile_gromacsplugin_fini(void);
@@ -53,16 +56,19 @@ namespace molfile{
 
 #define MOLFILE_INIT_ALL \
     molfile_dcdplugin_init(); \
+    molfile_crdplugin_init(); \
     molfile_gromacsplugin_init(); \
     molfile_pdbplugin_init(); \
 
 #define MOLFILE_REGISTER_ALL(v, cb) \
     molfile_dcdplugin_register(v, cb); \
+    molfile_crdplugin_register(v, cb); \
     molfile_gromacsplugin_register(v, cb); \
     molfile_pdbplugin_register(v, cb); \
 
 #define MOLFILE_FINI_ALL \
     molfile_dcdplugin_fini(); \
+    molfile_crdplugin_fini(); \
     molfile_gromacsplugin_fini(); \
     molfile_pdbplugin_fini(); \
 
-- 
GitLab