Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / gmxlib / vmdio.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * This file is part of Gromacs        Copyright (c) 1991-2008
5  * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
6  * Copyright (c) 2012,2013, by the GROMACS development team, led by
7  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
8  * others, as listed in the AUTHORS file in the top-level source
9  * directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41
42
43 /* Derived from PluginMgr.C and catdcd.c */
44
45 /* PluginMgr.C: Copyright: */
46 /***************************************************************************
47  *cr
48  *cr            (C) Copyright 1995-2009 The Board of Trustees of the
49  *cr                        University of Illinois
50  *cr                         All Rights Reserved
51  *cr
52 Developed by:           Theoretical and Computational Biophysics Group
53                         University of Illinois at Urbana-Champaign
54                         http://www.ks.uiuc.edu/
55
56 Permission is hereby granted, free of charge, to any person obtaining a copy of
57 this software and associated documentation files (the Software), to deal with
58 the Software without restriction, including without limitation the rights to
59 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
60 of the Software, and to permit persons to whom the Software is furnished to
61 do so, subject to the following conditions:
62
63 Redistributions of source code must retain the above copyright notice,
64 this list of conditions and the following disclaimers.
65
66 Redistributions in binary form must reproduce the above copyright notice,
67 this list of conditions and the following disclaimers in the documentation
68 and/or other materials provided with the distribution.
69
70 Neither the names of Theoretical and Computational Biophysics Group,
71 University of Illinois at Urbana-Champaign, nor the names of its contributors
72 may be used to endorse or promote products derived from this Software without
73 specific prior written permission.
74
75 THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
78 THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
79 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
80 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
81 OTHER DEALINGS WITH THE SOFTWARE.
82  ***************************************************************************/
83
84 /* catdcd.c: Copyright: */
85 /*****************************************************************************/
86 /*                                                                           */
87 /* (C) Copyright 2001-2005 Justin Gullingsrud and the University of Illinois.*/
88 /*                                                                           */
89 /*****************************************************************************/
90
91 #include <stdlib.h>
92 #include <stdio.h>
93 #include <string.h>
94 #include <assert.h>
95
96 /* 
97  * Plugin header files; get plugin source from www.ks.uiuc.edu/Research/vmd"
98  */
99 #include "molfile_plugin.h"
100 #include "vmddlopen.h"
101 #ifndef GMX_NATIVE_WINDOWS
102 #include <glob.h>
103 #else
104 #include <windows.h>
105 #include <shlobj.h>
106 #endif
107 #include "smalloc.h"
108 #include "futil.h"
109 #include "vmdio.h"
110
111
112 #include "types/simple.h"
113 #include "vec.h"
114 #include "gmxfio.h"
115
116
117 typedef int (*initfunc)(void);
118 typedef int (*regfunc)(void *, vmdplugin_register_cb);
119 typedef int (*finifunc)(void);
120
121
122
123 static int register_cb(void *v, vmdplugin_t *p) {
124     const char *key = p->name;
125     t_gmxvmdplugin *vmdplugin = (t_gmxvmdplugin*)v;
126
127     if (strcmp(key,vmdplugin->filetype)==0)
128     {
129         vmdplugin->api = (molfile_plugin_t *)p;
130     }
131     return VMDPLUGIN_SUCCESS;
132 }
133
134 static int load_sharedlibrary_plugins(const char *fullpath,t_gmxvmdplugin* vmdplugin) {
135     /* Open the dll; try to execute the init function. */
136     void *handle, *ifunc, *registerfunc; 
137     handle = vmddlopen(fullpath);
138     if (!handle) {
139         if (debug) fprintf(debug, "\nUnable to open dynamic library %s.\n%s\n",  fullpath, vmddlerror());  /*only to debug because of stdc++ erros */
140         return 0;
141     }
142
143     ifunc = vmddlsym(handle, "vmdplugin_init");
144     if (!ifunc || ((initfunc)(ifunc))()) {
145         printf("\nvmdplugin_init() for %s returned an error; plugin(s) not loaded.\n", fullpath);
146         vmddlclose(handle);
147         return 0;
148     }
149
150     registerfunc = vmddlsym(handle, "vmdplugin_register");
151     if (!registerfunc) {
152         printf("\nDidn't find the register function in %s; plugin(s) not loaded.\n", fullpath);
153         vmddlclose(handle);
154         return 0;
155     } else {
156         /* Load plugins from the library.*/
157         ((regfunc)registerfunc)(vmdplugin, register_cb);
158     } 
159     
160     /* in case this library does not support the filetype, close it */
161     if (vmdplugin->api == NULL)
162     {
163         vmddlclose(handle);
164     }
165
166     return 1;
167 }
168
169 /*return: 1: success, 0: last frame, -1: error*/
170 gmx_bool read_next_vmd_frame(int status,t_trxframe *fr)
171 {
172     int rc,i;
173     rvec vec, angle;
174     molfile_timestep_t ts;
175
176
177     fr->bV = fr->vmdplugin->bV;
178         
179 #ifdef GMX_DOUBLE
180     snew(ts.coords, fr->natoms*3);
181     if (fr->bV)
182     {
183         snew(ts.velocities, fr->natoms*3);
184     }
185 #else
186     ts.coords = (float*)fr->x;
187     if (fr->bV)
188     {
189         ts.velocities = (float*)fr->v;
190     }
191 #endif
192
193     rc = fr->vmdplugin->api->read_next_timestep(fr->vmdplugin->handle, fr->natoms, &ts);
194
195     if (rc < -1) {
196         fprintf(stderr, "\nError reading input file (error code %d)\n", rc);
197     }
198     if (rc < 0)
199     {
200         fr->vmdplugin->api->close_file_read(fr->vmdplugin->handle);
201         return 0;
202     }
203
204 #ifdef GMX_DOUBLE
205     for (i=0;i<fr->natoms;i++)
206     {
207         fr->x[i][0] = .1*ts.coords[i*3];
208         fr->x[i][1] = .1*ts.coords[i*3+1];
209         fr->x[i][2] = .1*ts.coords[i*3+2];
210         if (fr->bV)
211         {
212             fr->v[i][0] = .1*ts.velocities[i*3];
213             fr->v[i][1] = .1*ts.velocities[i*3+1];
214             fr->v[i][2] = .1*ts.velocities[i*3+2];
215         }
216     }
217     sfree(ts.coords);
218     if (fr->bV)
219     {
220         sfree(ts.velocities);
221     }
222 #else
223     for (i=0;i<fr->natoms;i++)
224     {
225         svmul(.1,fr->x[i],fr->x[i]);
226         if (fr->bV)
227         {
228             svmul(.1,fr->v[i],fr->v[i]);
229         }
230     }
231 #endif
232
233     fr->bX = 1;
234     fr->bBox = 1;
235     vec[0] = .1*ts.A; vec[1] = .1*ts.B; vec[2] = .1*ts.C;
236     angle[0] = ts.alpha; angle[1] = ts.beta; angle[2] = ts.gamma; 
237     matrix_convert(fr->box,vec,angle);
238     if (fr->vmdplugin->api->abiversion>10)
239     {
240         fr->bTime = TRUE;
241         fr->time = ts.physical_time;
242     }
243     else
244     {
245         fr->bTime = FALSE;
246     }
247
248
249     return 1;
250 }
251
252 static int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin)
253 {
254     char pathname[GMX_PATH_MAX],filename[GMX_PATH_MAX];
255     const char *pathenv;
256     const char *err;
257     int i;
258     int ret=0;
259     char pathenv_buffer[GMX_PATH_MAX];
260 #ifndef GMX_NATIVE_WINDOWS
261     glob_t globbuf;
262     const char *defpath_suffix = "/plugins/*/molfile";
263     const char *defpathenv = GMX_VMD_PLUGIN_PATH;
264 #else
265     WIN32_FIND_DATA ffd;
266     HANDLE hFind = INVALID_HANDLE_VALUE;
267     char progfolder[GMX_PATH_MAX];
268     char defpathenv[GMX_PATH_MAX];
269     const char *defpath_suffix = "\\plugins\\WIN32\\molfile";
270     SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES,NULL,SHGFP_TYPE_CURRENT,progfolder);
271     sprintf(defpathenv,"%s\\University of Illinois\\VMD\\plugins\\WIN32\\molfile",progfolder);
272 #endif
273
274     vmdplugin->api = NULL;
275     vmdplugin->filetype = strrchr(fn,'.');
276     if (!vmdplugin->filetype)
277     {
278         return 0;
279     }
280     vmdplugin->filetype++;
281
282     /* First look for an explicit path given at run time for the
283      * plugins, then an implicit run-time path, and finally for one
284      * given at configure time. This last might be hard-coded to the
285      * default for VMD installs. */
286     pathenv = getenv("VMD_PLUGIN_PATH");
287     if (pathenv==NULL) 
288     {
289         pathenv = getenv("VMDDIR");
290         if (NULL == pathenv)
291         {
292             printf("\nNeither VMD_PLUGIN_PATH or VMDDIR set. ");
293             printf("Using default location:\n%s\n",defpathenv);
294             pathenv=defpathenv;
295         }
296         else
297         {
298             printf("\nVMD_PLUGIN_PATH no set, but VMDDIR is set. ");
299 #ifdef _MSC_VER
300             _snprintf_s(pathenv_buffer, sizeof(pathenv_buffer), _TRUNCATE, "%s%s", pathenv, defpath_suffix);
301 #else
302             snprintf(pathenv_buffer, sizeof(pathenv_buffer), "%s%s", pathenv, defpath_suffix);
303 #endif
304             printf("Using semi-default location:\n%s\n",pathenv_buffer);
305             pathenv = pathenv_buffer;
306         }
307     }
308     strncpy(pathname,pathenv,sizeof(pathname));
309 #ifndef GMX_NATIVE_WINDOWS
310     strcat(pathname,"/*.so");
311     glob(pathname, 0, NULL, &globbuf);
312     if (globbuf.gl_pathc == 0)
313     {
314         printf("\nNo VMD Plugins found\n"
315             "Set the environment variable VMD_PLUGIN_PATH to the molfile folder within the\n"
316             "VMD installation.\n"
317             "The architecture (e.g. 32bit versus 64bit) of Gromacs and VMD has to match.\n");
318         return 0;
319     }
320     for (i=0; i<globbuf.gl_pathc && vmdplugin->api == NULL; i++)
321     {
322         /* FIXME: Undefined which plugin is chosen if more than one plugin
323            can read a certain file ending. Requires some additional command
324            line option or enviroment variable to specify which plugin should
325            be picked.
326         */
327         ret|=load_sharedlibrary_plugins(globbuf.gl_pathv[i],vmdplugin);
328     }
329     globfree(&globbuf);
330 #else
331     strcat(pathname,"\\*.so");
332     hFind = FindFirstFile(pathname, &ffd);
333     if (INVALID_HANDLE_VALUE == hFind) 
334     {
335         printf("\nNo VMD Plugins found\n");
336         return 0;
337     } 
338     do
339     {
340         sprintf(filename,"%s\\%s",pathenv,ffd.cFileName);
341         ret|=load_sharedlibrary_plugins(filename,vmdplugin);
342     }
343     while (FindNextFile(hFind, &ffd )  != 0 && vmdplugin->api == NULL );
344     FindClose(hFind);
345 #endif
346
347     if (!ret)
348     {
349         printf("\nCould not open any VMD library.\n");
350         err = vmddlerror();
351         if (!err) 
352         {
353             printf("Compiled with dlopen?\n");
354         }
355         else
356         {
357             printf("Last error:\n%s\n",err);
358         }
359         return 0;
360     }
361
362     if (vmdplugin->api == NULL)
363     {
364         printf("\nNo plugin for %s found\n",vmdplugin->filetype);
365         return 0;
366     }
367
368     if (vmdplugin->api->abiversion < 10)
369     {
370         printf("\nPlugin and/or VMD is too old. At least VMD 1.8.6 is required.\n");
371         return 0;
372     }
373
374     printf("\nUsing VMD plugin: %s (%s)\n",vmdplugin->api->name,vmdplugin->api->prettyname);
375
376     return 1;
377
378 }
379
380 int read_first_vmd_frame(int *status,const char *fn,t_trxframe *fr,int flags)
381 {
382     molfile_timestep_metadata_t *metadata=NULL;
383     
384     snew(fr->vmdplugin,1);
385     if (!load_vmd_library(fn,fr->vmdplugin))
386     {
387         return 0;
388     }
389
390     fr->vmdplugin->handle = fr->vmdplugin->api->open_file_read(fn, fr->vmdplugin->filetype, &fr->natoms);
391
392     if (!fr->vmdplugin->handle) {
393         fprintf(stderr, "\nError: could not open file '%s' for reading.\n",
394                 fn);
395         return 0;
396     }
397
398     if (fr->natoms == MOLFILE_NUMATOMS_UNKNOWN) {
399         fprintf(stderr, "\nFormat of file %s does not record number of atoms.\n", fn);
400         return 0;
401     } else if (fr->natoms == MOLFILE_NUMATOMS_NONE) {
402         fprintf(stderr, "\nNo atoms found by VMD plugin in file %s.\n", fn );
403         return 0;
404     } else if (fr->natoms < 1) { /*should not be reached*/
405         fprintf(stderr, "\nUnknown number of atoms %d for VMD plugin opening file %s.\n",
406                 fr->natoms, fn );
407         return 0;
408     }
409     
410     snew(fr->x,fr->natoms);
411
412     fr->vmdplugin->bV = 0;
413     if (fr->vmdplugin->api->abiversion > 10 && fr->vmdplugin->api->read_timestep_metadata)
414     {
415         fr->vmdplugin->api->read_timestep_metadata(fr->vmdplugin->handle, metadata);
416         assert(metadata);
417         fr->vmdplugin->bV = metadata->has_velocities;
418         if (fr->vmdplugin->bV)
419         {
420             snew(fr->v,fr->natoms);
421         }
422     }
423     else
424     {
425         fprintf(stderr,
426                 "\nThis trajectory is being read with a VMD plug-in from before VMD"
427                 "\nversion 1.8, or from a trajectory that lacks time step metadata."
428                 "\nEither way, GROMACS cannot tell whether the trajectory has velocities.\n");
429     }
430     return 1;
431
432 }
433
434
435