d4451a5be7275c141589ad1af01286dd51d8228b
[alexxy/gromacs.git] / src / gmxlib / vmdio.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
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  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * To help us fund GROMACS development, we humbly ask that you cite
13  * the research papers on the package. Check out http://www.gromacs.org
14  * 
15  * And Hey:
16  * Gnomes, ROck Monsters And Chili Sauce
17  */
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22
23
24 /* Derived from PluginMgr.C and catdcd.c */
25
26 /* PluginMgr.C: Copyright: */
27 /***************************************************************************
28  *cr
29  *cr            (C) Copyright 1995-2009 The Board of Trustees of the
30  *cr                        University of Illinois
31  *cr                         All Rights Reserved
32  *cr
33 Developed by:           Theoretical and Computational Biophysics Group
34                         University of Illinois at Urbana-Champaign
35                         http://www.ks.uiuc.edu/
36
37 Permission is hereby granted, free of charge, to any person obtaining a copy of
38 this software and associated documentation files (the Software), to deal with
39 the Software without restriction, including without limitation the rights to
40 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
41 of the Software, and to permit persons to whom the Software is furnished to
42 do so, subject to the following conditions:
43
44 Redistributions of source code must retain the above copyright notice,
45 this list of conditions and the following disclaimers.
46
47 Redistributions in binary form must reproduce the above copyright notice,
48 this list of conditions and the following disclaimers in the documentation
49 and/or other materials provided with the distribution.
50
51 Neither the names of Theoretical and Computational Biophysics Group,
52 University of Illinois at Urbana-Champaign, nor the names of its contributors
53 may be used to endorse or promote products derived from this Software without
54 specific prior written permission.
55
56 THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
59 THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
60 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
61 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
62 OTHER DEALINGS WITH THE SOFTWARE.
63  ***************************************************************************/
64
65 /* catdcd.c: Copyright: */
66 /*****************************************************************************/
67 /*                                                                           */
68 /* (C) Copyright 2001-2005 Justin Gullingsrud and the University of Illinois.*/
69 /*                                                                           */
70 /*****************************************************************************/
71
72 #include <stdlib.h>
73 #include <stdio.h>
74 #include <string.h>
75
76 /* 
77  * Plugin header files; get plugin source from www.ks.uiuc.edu/Research/vmd"
78  */
79 #include "molfile_plugin.h"
80 #include "vmddlopen.h"
81 #if !((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
82 #include "glob.h"
83 #else
84 #include <windows.h>
85 #include <shlobj.h>
86 #endif
87 #include "smalloc.h"
88 #include "futil.h"
89 #include "vmdio.h"
90
91
92 #include "types/simple.h"
93 #include "vec.h"
94 #include "gmxfio.h"
95
96
97 typedef int (*initfunc)(void);
98 typedef int (*regfunc)(void *, vmdplugin_register_cb);
99 typedef int (*finifunc)(void);
100
101
102
103 static int register_cb(void *v, vmdplugin_t *p) {
104     const char *key = p->name;
105     t_gmxvmdplugin *vmdplugin = (t_gmxvmdplugin*)v;
106
107     if (strcmp(key,vmdplugin->filetype)==0)
108     {
109         vmdplugin->api = (molfile_plugin_t *)p;
110     }
111     return VMDPLUGIN_SUCCESS;
112 }
113
114 static int load_sharedlibrary_plugins(const char *fullpath,t_gmxvmdplugin* vmdplugin) {
115     /* Open the dll; try to execute the init function. */
116     void *handle, *ifunc, *registerfunc; 
117     handle = vmddlopen(fullpath);
118     if (!handle) {
119         if (debug) fprintf(debug, "\nUnable to open dynamic library %s.\n%s\n",  fullpath, vmddlerror());  /*only to debug because of stdc++ erros */
120         return 0;
121     }
122
123     ifunc = vmddlsym(handle, "vmdplugin_init");
124     if (ifunc && ((initfunc)(ifunc))()) {
125         printf("\nvmdplugin_init() for %s returned an error; plugin(s) not loaded.\n", fullpath);
126         vmddlclose(handle);
127         return 0;
128     }
129
130     registerfunc = vmddlsym(handle, "vmdplugin_register");
131     if (!registerfunc) {
132         printf("\nDidn't find the register function in %s; plugin(s) not loaded.\n", fullpath);
133         vmddlclose(handle);
134         return 0;
135     } else {
136         /* Load plugins from the library.*/
137         ((regfunc)registerfunc)(vmdplugin, register_cb);
138     } 
139     
140     /* in case this library does not support the filetype, close it */
141     if (vmdplugin->api == NULL)
142     {
143         vmddlclose(handle);
144     }
145
146     return 1;
147 }
148
149 /*return: 1: success, 0: last frame, -1: error*/
150 bool read_next_vmd_frame(int status,t_trxframe *fr)
151 {
152     int rc,i;
153     rvec vec, angle;
154     molfile_timestep_t ts;
155
156
157     fr->bV = fr->vmdplugin.bV; 
158         
159 #ifdef GMX_DOUBLE
160     snew(ts.coords, fr->natoms*3);
161     if (fr->bV)
162     {
163         snew(ts.velocities, fr->natoms*3);
164     }
165 #else
166     ts.coords = (float*)fr->x;
167     if (fr->bV)
168     {
169         ts.velocities = (float*)fr->v;
170     }
171 #endif
172
173     rc = fr->vmdplugin.api->read_next_timestep(fr->vmdplugin.handle, fr->natoms, &ts);
174
175     if (rc < -1) {
176         fprintf(stderr, "\nError reading input file (error code %d)\n", rc);
177     }
178     if (rc < 0)
179     {
180         fr->vmdplugin.api->close_file_read(fr->vmdplugin.handle);
181         return 0;
182     }
183
184 #ifdef GMX_DOUBLE
185     for (i=0;i<fr->natoms;i++)
186     {
187         fr->x[i][0] = .1*ts.coords[i*3];
188         fr->x[i][1] = .1*ts.coords[i*3+1];
189         fr->x[i][2] = .1*ts.coords[i*3+2];
190         if (fr->bV)
191         {
192             fr->v[i][0] = .1*ts.velocities[i*3];
193             fr->v[i][1] = .1*ts.velocities[i*3+1];
194             fr->v[i][2] = .1*ts.velocities[i*3+2];
195         }
196     }
197     sfree(ts.coords);
198     if (fr->bV)
199     {
200         sfree(ts.velocities);
201     }
202 #else
203     for (i=0;i<fr->natoms;i++)
204     {
205         svmul(.1,fr->x[i],fr->x[i]);
206         if (fr->bV)
207         {
208             svmul(.1,fr->v[i],fr->v[i]);
209         }
210     }
211 #endif
212
213     fr->bX = 1;
214     vec[0] = .1*ts.A; vec[1] = .1*ts.B; vec[2] = .1*ts.B;
215     angle[0] = ts.alpha; angle[1] = ts.beta; angle[2] = ts.gamma; 
216     matrix_convert(fr->box,vec,angle);
217     fr->bTime = 1;
218     fr->time = ts.physical_time;
219
220
221
222     return 1;
223 }
224
225 int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin)
226 {
227     char pathname[GMX_PATH_MAX],filename[GMX_PATH_MAX];
228     const char *pathenv;
229     const char *err;
230     int i;
231     int ret=0;
232 #if !((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
233     glob_t globbuf;
234     const char *defpathenv = "/usr/local/lib/vmd/plugins/*/molfile";
235 #else
236     WIN32_FIND_DATA ffd;
237     HANDLE hFind = INVALID_HANDLE_VALUE;
238     char progfolder[GMX_PATH_MAX];
239     char defpathenv[GMX_PATH_MAX];
240     SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES,NULL,SHGFP_TYPE_CURRENT,progfolder);
241     sprintf(defpathenv,"%s\\University of Illinois\\VMD\\plugins\\WIN32\\molfile",progfolder);
242 #endif
243
244     vmdplugin->api = NULL;
245     vmdplugin->filetype = strrchr(fn,'.');
246     if (!vmdplugin->filetype)
247     {
248         return 0;
249     }
250     vmdplugin->filetype++;
251
252     pathenv = getenv("VMD_PLUGIN_PATH");
253     if (pathenv==NULL) 
254     {
255         printf("\nVMD_PLUGIN_PATH not set. ");
256         printf("Using default location:\n%s\n",defpathenv);
257         pathenv=defpathenv;
258     }
259     strncpy(pathname,pathenv,sizeof(pathname));
260 #if !((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
261     strcat(pathname,"/*.so");
262     glob(pathname, 0, NULL, &globbuf);
263     if (globbuf.gl_pathc == 0)
264     {
265         printf("\nNo VMD Plugins found\n"
266             "Set the environment variable VMD_PLUGIN_PATH to the molfile folder within the\n"
267             "VMD installation.\n"
268             "The architecture (e.g. 32bit versus 64bit) of Gromacs and VMD has to match.\n");
269         return 0;
270     }
271     for (i=0; i<globbuf.gl_pathc && vmdplugin->api == NULL; i++)
272     {
273         ret|=load_sharedlibrary_plugins(globbuf.gl_pathv[i],vmdplugin);
274     }
275     globfree(&globbuf);
276 #else
277     strcat(pathname,"\\*.so");
278     hFind = FindFirstFile(pathname, &ffd);
279     if (INVALID_HANDLE_VALUE == hFind) 
280     {
281         printf("\nNo VMD Plugins found\n");
282         return 0;
283     } 
284     do
285     {
286         sprintf(filename,"%s\\%s",pathenv,ffd.cFileName);
287         ret|=load_sharedlibrary_plugins(filename,vmdplugin);
288     }
289     while (FindNextFile(hFind, &ffd )  != 0 && vmdplugin->api == NULL );
290     FindClose(hFind);
291 #endif
292
293     if (!ret)
294     {
295         printf("\nCould not open any VMD library.\n");
296         err = vmddlerror();
297         if (!err) 
298         {
299             printf("Compiled with dlopen?\n");
300         }
301         else
302         {
303             printf("Last error:\n%s\n",err);
304         }
305         return 0;
306     }
307
308     if (vmdplugin->api == NULL)
309     {
310         printf("\nNo plugin for %s found\n",vmdplugin->filetype);
311         return 0;
312     }
313
314     printf("\nUsing VMD plugin: %s (%s)\n",vmdplugin->api->name,vmdplugin->api->prettyname);
315
316     return 1;
317
318 }
319
320 int read_first_vmd_frame(int *status,const char *fn,t_trxframe *fr,int flags)
321 {
322     molfile_timestep_metadata_t *metadata=NULL;
323     
324     if (!load_vmd_library(fn,&(fr->vmdplugin))) 
325     {
326         return 0;
327     }
328
329     fr->vmdplugin.handle = fr->vmdplugin.api->open_file_read(fn, fr->vmdplugin.filetype, &fr->natoms);
330
331     if (!fr->vmdplugin.handle) {
332         fprintf(stderr, "\nError: could not open file '%s' for reading.\n",
333                 fn);
334         return 0;
335     }
336
337     if (fr->natoms < 1) {
338         fprintf(stderr, "\nNo atoms found by VMD plugin in %s.\n"
339             "Or format does not record number of atoms.\n", fn );
340         return 0;
341     }
342     
343     snew(fr->x,fr->natoms);
344
345     fr->vmdplugin.bV = 0;
346     if (fr->vmdplugin.api->read_timestep_metadata) 
347     {
348         fr->vmdplugin.api->read_timestep_metadata(fr->vmdplugin.handle, metadata);
349         fr->vmdplugin.bV = metadata->has_velocities; 
350         if (fr->vmdplugin.bV)
351         {
352             snew(fr->v,fr->natoms);
353         }
354     }
355     return 1;
356
357 }
358
359
360