00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <math.h>
00035 #include <tng/tng_io.h>
00036 #include "molfile_plugin.h"
00037
00038 #define TNG_PLUGIN_MAJOR_VERSION 1
00039 #define TNG_PLUGIN_MINOR_VERSION 0
00040
00041 #ifndef M_PI_2
00042 #define M_PI_2 1.57079632679489661922
00043 #endif
00044
00045 typedef struct {
00046 tng_trajectory_t tng_traj;
00047 int natoms;
00048 int step;
00049
00050 int64_t n_frames;
00051 int coord_exponential;
00052
00053 double time_per_frame;
00054 int has_velocities;
00055 } tngdata;
00056
00057 static void convert_tng_box_shape_to_vmd(float *box_shape, float *vmd_box)
00058 {
00059 float A, B, C;
00060
00061 A = sqrt(box_shape[0]*box_shape[0] +
00062 box_shape[1]*box_shape[1] +
00063 box_shape[2]*box_shape[2]);
00064 B = sqrt(box_shape[3]*box_shape[3] +
00065 box_shape[4]*box_shape[4] +
00066 box_shape[5]*box_shape[5]);
00067 C = sqrt(box_shape[6]*box_shape[6] +
00068 box_shape[7]*box_shape[7] +
00069 box_shape[8]*box_shape[8]);
00070
00071 if ((A<=0) || (B<=0) || (C<=0))
00072 {
00073 vmd_box[0] = vmd_box[1] = vmd_box[2] = 0;
00074 vmd_box[3] = vmd_box[4] = vmd_box[5] = 90;
00075 }
00076 else
00077 {
00078 vmd_box[0] = A;
00079 vmd_box[1] = B;
00080 vmd_box[2] = C;
00081 vmd_box[3] = acos( (box_shape[3]*box_shape[6]+
00082 box_shape[4]*box_shape[7]+
00083 box_shape[5]*box_shape[8])/(B*C) ) * 90.0/M_PI_2;
00084 vmd_box[4] = acos( (box_shape[0]*box_shape[6]+
00085 box_shape[1]*box_shape[7]+
00086 box_shape[2]*box_shape[8])/(A*C) ) * 90.0/M_PI_2;
00087 vmd_box[5] = acos( (box_shape[0]*box_shape[3]+
00088 box_shape[1]*box_shape[4]+
00089 box_shape[2]*box_shape[5])/(A*B) ) * 90.0/M_PI_2;
00090 }
00091 }
00092
00093 static void convert_vmd_box_shape_to_tng(const molfile_timestep_t *ts, float *box_shape)
00094 {
00095
00096 const float ca = cos((double)ts->alpha/180.0*M_PI);
00097 const float cb = cos((double)ts->beta/180.0*M_PI);
00098 const float cg = cos((double)ts->gamma/180.0*M_PI);
00099 const float sg = sin((double)ts->gamma/180.0*M_PI);
00100
00101 box_shape[0] = ts->A;
00102 box_shape[1] = 0.0;
00103 box_shape[2] = 0.0;
00104 box_shape[3] = ts->B*cg;
00105 box_shape[4] = ts->B*sg;
00106 box_shape[5] = 0.0;
00107 box_shape[6] = ts->C*cb;
00108 box_shape[7] = ts->C*(ca - cb*cg)/sg;
00109 box_shape[8] = ts->C*sqrt((double)(1.0 + 2.0*ca*cb*cg
00110 - ca*ca - cb*cb - cg*cg)/(1.0 - cg*cg));
00111 }
00112
00113 static void *open_tng_read(const char *filename, const char*,
00114 int *natoms)
00115 {
00116 tngdata *tng;
00117 tng_function_status stat;
00118 int64_t n, exp;
00119
00120 tng = new tngdata;
00121
00122 stat = tng_util_trajectory_open(filename, 'r', &tng->tng_traj);
00123 if(stat != TNG_SUCCESS)
00124 {
00125 fprintf(stderr, "tngplugin) Cannot open file '%s'\n", filename);
00126 return NULL;
00127 }
00128
00129 tng_num_particles_get(tng->tng_traj, &n);
00130 *natoms = (int)n;
00131 tng->natoms = (int)n;
00132 tng->step = 0;
00133 tng_num_frames_get(tng->tng_traj, &n);
00134 tng->n_frames = n;
00135 tng->has_velocities = 0;
00136
00137 tng_distance_unit_exponential_get(tng->tng_traj, &exp);
00138 tng->coord_exponential = (int) exp;
00139
00140
00141 return tng;
00142 }
00143
00144 static int read_tng_structure(void *v, int *optflags,
00145 molfile_atom_t *atoms)
00146 {
00147 tngdata *tng = (tngdata *)v;
00148 char long_name[16], short_name[2];
00149 int64_t id;
00150
00151 *optflags = MOLFILE_NOOPTIONS;
00152 for(int i = 0; i < tng->natoms; i++)
00153 {
00154 molfile_atom_t *atom = atoms+i;
00155 tng_atom_name_of_particle_nr_get(tng->tng_traj, i, long_name, 16);
00156 strcpy(atom->name, long_name);
00157 tng_atom_type_of_particle_nr_get(tng->tng_traj, i, long_name, 16);
00158 strcpy(atom->type, long_name);
00159 tng_residue_name_of_particle_nr_get(tng->tng_traj, i, long_name, 16);
00160 strcpy(atom->resname, long_name);
00161 tng_global_residue_id_of_particle_nr_get(tng->tng_traj, i, &id);
00162 atom->resid = (int)id;
00163
00164 tng_chain_name_of_particle_nr_get(tng->tng_traj, i, short_name, 2);
00165 strcpy(atom->chain, short_name);
00166 atom->segid[0] = '\0';
00167 }
00168
00169 return MOLFILE_SUCCESS;
00170 }
00171
00172 #if vmdplugin_ABIVERSION > 14
00173 static int read_tng_bonds(void *v, int *nbonds, int **fromptr, int **toptr,
00174 float **bondorderptr, int **bondtypeptr,
00175 int *nbondtypes, char ***bondtypename)
00176 #else
00177 static int read_tng_bonds(void *v, int *nbonds, int **fromptr, int **toptr,
00178 float **bondorderptr)
00179 #endif
00180 {
00181 int64_t *from_atoms = 0, *to_atoms = 0, bond_cnt, i;
00182 tng_function_status stat;
00183
00184 tngdata *tng = (tngdata *)v;
00185
00186 stat = tng_molsystem_bonds_get(tng->tng_traj, &bond_cnt, &from_atoms,
00187 &to_atoms);
00188 if(stat != TNG_SUCCESS)
00189 {
00190 return MOLFILE_ERROR;
00191 }
00192
00193 if(bond_cnt <= 0)
00194 {
00195 fprintf(stderr, "tngplugin) No bonds found in molsystem\n");
00196 *nbonds = 0;
00197 *fromptr = 0;
00198 *toptr = 0;
00199 return MOLFILE_SUCCESS;
00200 }
00201
00202
00203
00204
00205 *nbonds = (int) bond_cnt;
00206 *fromptr = (int *)malloc((*nbonds) * sizeof(int));
00207 *toptr = (int *)malloc((*nbonds) * sizeof(int));
00208 *bondorderptr = 0;
00209
00210 #if vmdplugin_ABIVERSION > 14
00211 *bondtypeptr = 0;
00212 *nbondtypes = 0;
00213 *bondtypename = 0;
00214 #endif
00215
00216 for(i = 0; i < *nbonds; i++)
00217 {
00218 (*fromptr)[i] = (int)from_atoms[i] + 1;
00219 (*toptr)[i] = (int)to_atoms[i] + 1;
00220
00221 }
00222
00223 return MOLFILE_SUCCESS;
00224 }
00225
00226 static void convert_to_float(void *from, float *to, const float fact, const int natoms, const int nvalues, const char datatype)
00227 {
00228 int i, j;
00229
00230 switch(datatype)
00231 {
00232 case TNG_FLOAT_DATA:
00233 if(fact == 1)
00234 {
00235 memcpy(to, from, nvalues * sizeof(float) * natoms);
00236 }
00237 else
00238 {
00239 for(i = 0; i < natoms; i++)
00240 {
00241 for(j = 0; j < nvalues; j++)
00242 {
00243 to[i*3+j] = (float)((float *)from)[i*3+j] * fact;
00244 }
00245 }
00246 }
00247 break;
00248 case TNG_INT_DATA:
00249 for(i = 0; i < natoms; i++)
00250 {
00251 for(j = 0; j < nvalues; j++)
00252 {
00253 to[i*3+j] = (float)((int64_t *)from)[i*3+j] * fact;
00254 }
00255 }
00256 break;
00257 case TNG_DOUBLE_DATA:
00258 for(i = 0; i < natoms; i++)
00259 {
00260 for(j = 0; j < nvalues; j++)
00261 {
00262 to[i*3+j] = (float)((double *)from)[i*3+j] * fact;
00263 }
00264 }
00265 break;
00266 default:
00267 fprintf(stderr, "tngplugin) Cannot cast data\n");
00268 }
00269 return;
00270 }
00271
00272 static int read_tng_timestep(void *v, int natoms, molfile_timestep_t *ts)
00273 {
00274
00275 void *values = 0;
00276 char datatype;
00277 float box_shape[9], vmd_box[6];
00278 float fact = 1;
00279 int64_t frame, n, temp, temp2;
00280 tng_function_status stat;
00281 tngdata *tng = (tngdata *)v;
00282
00283 if(!ts)
00284 {
00285 return MOLFILE_ERROR;
00286 }
00287
00288
00289
00290 stat = tng_util_particle_data_next_frame_read(tng->tng_traj, TNG_TRAJ_POSITIONS, &values,
00291 &datatype, &frame, &ts->physical_time);
00292 if(stat != TNG_SUCCESS)
00293 {
00294 return MOLFILE_ERROR;
00295 }
00296
00297
00298
00299
00300
00301 tng_num_particles_get(tng->tng_traj, &n);
00302 if(n != natoms)
00303 {
00304 fprintf(stderr, "tngplugin) Timestep in file contains wrong number of atoms\n");
00305 fprintf(stderr, "tngplugin) Found %d, expected %d\n", (int)n, natoms);
00306 return MOLFILE_ERROR;
00307 }
00308
00309 if(tng->coord_exponential != -10)
00310 {
00311 fact = pow(10.0, tng->coord_exponential + 10);
00312 }
00313
00314 convert_to_float(values, ts->coords, fact, natoms, 3, datatype);
00315
00316 if(ts->velocities)
00317 {
00318
00319 stat = tng_particle_data_vector_interval_get(tng->tng_traj, TNG_TRAJ_VELOCITIES, frame,
00320 frame, TNG_USE_HASH, &values,
00321 &n, &temp, &temp2, &datatype);
00322 if(stat == TNG_CRITICAL)
00323 {
00324 return MOLFILE_ERROR;
00325 }
00326 if(stat == TNG_SUCCESS)
00327 {
00328 convert_to_float(values, ts->velocities, fact, natoms, 3, datatype);
00329 }
00330 }
00331
00332 stat = tng_data_vector_interval_get(tng->tng_traj, TNG_TRAJ_BOX_SHAPE,
00333 frame, frame, TNG_USE_HASH, &values,
00334 &temp, &temp2, &datatype);
00335 if(stat == TNG_CRITICAL)
00336 {
00337 return MOLFILE_ERROR;
00338 }
00339 if(stat == TNG_SUCCESS)
00340 {
00341 convert_to_float(values, box_shape, fact, 1, 9, datatype);
00342
00343 convert_tng_box_shape_to_vmd(box_shape, vmd_box);
00344 if(ts)
00345 {
00346 ts->A = vmd_box[0];
00347 ts->B = vmd_box[1];
00348 ts->C = vmd_box[2];
00349 ts->alpha = vmd_box[3];
00350 ts->beta = vmd_box[4];
00351 ts->gamma = vmd_box[5];
00352 }
00353 }
00354
00355 ++tng->step;
00356 if(values)
00357 {
00358 free(values);
00359 }
00360
00361 return MOLFILE_SUCCESS;
00362 }
00363
00364 static int read_timestep_metadata(void *v, molfile_timestep_metadata_t *metadata)
00365 {
00366 tng_function_status stat;
00367 tngdata *tng = (tngdata *)v;
00368
00369
00370 if(tng->has_velocities == 0)
00371 {
00372 stat = tng_frame_set_read_current_only_data_from_block_id(tng->tng_traj, TNG_SKIP_HASH, TNG_TRAJ_VELOCITIES);
00373
00374 if(stat == TNG_CRITICAL)
00375 {
00376 metadata->has_velocities = 0;
00377 return MOLFILE_ERROR;
00378 }
00379 else if(stat == TNG_SUCCESS)
00380 {
00381 fprintf(stderr, "tngplugin) Trajectory contains velocities\n");
00382 tng->has_velocities = 1;
00383 }
00384 else
00385 {
00386 fprintf(stderr, "tngplugin) Trajectory does not contain velocities\n");
00387 tng->has_velocities = -1;
00388 }
00389 }
00390 if(tng->has_velocities == 1)
00391 {
00392 metadata->has_velocities = 1;
00393 }
00394 else
00395 {
00396 metadata->has_velocities = 0;
00397 }
00398
00399 return MOLFILE_SUCCESS;
00400 }
00401
00402 static void close_tng(void *v)
00403 {
00404 tngdata *tng = (tngdata *)v;
00405 tng_util_trajectory_close(&tng->tng_traj);
00406 delete tng;
00407 }
00408
00409 static void *open_tng_write(const char *filename, const char*,
00410 int natoms)
00411 {
00412 tngdata *tng;
00413 tng_function_status stat;
00414
00415
00416 tng = new tngdata;
00417
00418 stat = tng_util_trajectory_open(filename, 'w', &tng->tng_traj);
00419 if(stat != TNG_SUCCESS)
00420 {
00421 fprintf(stderr, "tngplugin) Cannot open file '%s'\n", filename);
00422 return NULL;
00423 }
00424
00425 tng->natoms = natoms;
00426 tng->step = 0;
00427 tng->coord_exponential = -10;
00428 tng_distance_unit_exponential_set(tng->tng_traj, -10);
00429
00430 tng->time_per_frame = -1;
00431
00432 return tng;
00433 }
00434
00435 static int write_tng_structure(void *v, int optflags, const molfile_atom_t *atoms)
00436 {
00437
00438
00439 tng_molecule_t tng_mol = 0;
00440 tng_chain_t tng_chain = 0;
00441 tng_residue_t tng_residue = 0;
00442 tng_atom_t tng_atom;
00443 int prev_resid = -1;
00444 char new_chain_name[4] = "X_A";
00445
00446 tngdata *tng = (tngdata *)v;
00447
00448
00449 if(tng_molecule_find(tng->tng_traj, "MOL", -1, &tng_mol) != TNG_SUCCESS)
00450 {
00451 tng_molecule_add(tng->tng_traj, "MOL", &tng_mol);
00452 }
00453
00454 for(int i = 0; i < tng->natoms; i++)
00455 {
00456 if(tng_chain == 0)
00457 {
00458 if(tng_molecule_chain_find(tng->tng_traj, tng_mol, atoms[i].chain, -1, &tng_chain) !=
00459 TNG_SUCCESS)
00460 {
00461 tng_molecule_chain_add(tng->tng_traj, tng_mol, atoms[i].chain, &tng_chain);
00462 }
00463 }
00464 else if(tng_residue != 0)
00465 {
00466 if(prev_resid >= 0)
00467 {
00468 if(prev_resid > atoms[i].resid)
00469 {
00470 new_chain_name[0] = atoms[i].chain[0];
00471 ++new_chain_name[2];
00472 tng_molecule_chain_add(tng->tng_traj, tng_mol, new_chain_name, &tng_chain);
00473 }
00474 }
00475 }
00476
00477 if (tng_chain_residue_find(tng->tng_traj, tng_chain, atoms[i].resname,
00478 atoms[i].resid, &tng_residue) != TNG_SUCCESS)
00479 {
00480 tng_chain_residue_w_id_add(tng->tng_traj, tng_chain, atoms[i].resname,
00481 atoms[i].resid, &tng_residue);
00482 prev_resid = atoms[i].resid;
00483 }
00484 tng_residue_atom_add(tng->tng_traj, tng_residue, atoms[i].name, atoms[i].type, &tng_atom);
00485 }
00486 tng_molecule_cnt_set(tng->tng_traj, tng_mol, 1);
00487
00488 return MOLFILE_SUCCESS;
00489 }
00490
00491 #if vmdplugin_ABIVERSION > 14
00492 static int write_tng_bonds(void *v, int nbonds, int *from, int *to,
00493 float *bondorder, int *bondtype,
00494 int nbondtypes, char **bondtypename)
00495 #else
00496 static int write_tng_bonds(void *v, int nbonds, int *from, int *to,
00497 float *bondorder)
00498 #endif
00499 {
00500 tng_molecule_t tng_mol;
00501 tng_bond_t tng_bond;
00502 int i;
00503
00504 if(nbonds == 0)
00505 {
00506 return MOLFILE_SUCCESS;
00507 }
00508
00509 tngdata *tng = (tngdata *)v;
00510
00511
00512 if(tng_molecule_find(tng->tng_traj, "MOL", -1, &tng_mol) != TNG_SUCCESS)
00513 {
00514 tng_molecule_add(tng->tng_traj, "MOL", &tng_mol);
00515 }
00516
00517 for (i = 0; i < nbonds; i++)
00518 {
00519 if(tng_molecule_bond_add(tng->tng_traj, tng_mol, from[i]-1, to[i]-1, &tng_bond) != TNG_SUCCESS)
00520 {
00521 fprintf(stderr, "tngplugin) Error adding bond %d (from %d to %d).\n", i, from[i], to[i]);
00522 return MOLFILE_ERROR;
00523 }
00524 }
00525 return MOLFILE_SUCCESS;
00526 }
00527
00528 static int write_tng_timestep(void *v, const molfile_timestep_t *ts)
00529 {
00530 float box_shape[9];
00531 tngdata *tng = (tngdata *)v;
00532
00533
00534
00535
00536 tng_implicit_num_particles_set(tng->tng_traj, tng->natoms);
00537
00538 if(!ts)
00539 {
00540 return MOLFILE_ERROR;
00541 }
00542
00543 convert_vmd_box_shape_to_tng(ts, box_shape);
00544 if(tng->step == 1 && ts->physical_time != 0)
00545 {
00546 tng->time_per_frame = ts->physical_time;
00547 tng_time_per_frame_set(tng->tng_traj, tng->time_per_frame);
00548 }
00549 if(tng->time_per_frame < 0)
00550 {
00551
00552 tng_util_box_shape_write(tng->tng_traj, tng->step, box_shape);
00553 tng_util_pos_write(tng->tng_traj, tng->step, ts->coords);
00554 }
00555 else
00556 {
00557
00558 tng_util_box_shape_with_time_write(tng->tng_traj, tng->step, ts->physical_time,
00559 box_shape);
00560 tng_util_pos_with_time_write(tng->tng_traj, tng->step, ts->physical_time,
00561 ts->coords);
00562 }
00563 if(tng->step == 0)
00564 {
00565 tng_util_pos_write_interval_set(tng->tng_traj, 1);
00566 tng_util_box_shape_write_interval_set(tng->tng_traj, 1);
00567 }
00568 if(ts->velocities)
00569 {
00570
00571 if(tng->time_per_frame < 0)
00572 {
00573 tng_util_vel_write(tng->tng_traj, tng->step, ts->velocities);
00574 }
00575 else
00576 {
00577 tng_util_vel_with_time_write(tng->tng_traj, tng->step, ts->physical_time,
00578 ts->velocities);
00579 }
00580 if(tng->step == 0)
00581 {
00582 tng_util_vel_write_interval_set(tng->tng_traj, 1);
00583 }
00584 }
00585
00586 tng->step++;
00587
00588 return MOLFILE_SUCCESS;
00589 }
00590
00591 static molfile_plugin_t tng_plugin;
00592
00593 VMDPLUGIN_API int VMDPLUGIN_init() {
00594
00595 memset(&tng_plugin, 0, sizeof(molfile_plugin_t));
00596 tng_plugin.abiversion = vmdplugin_ABIVERSION;
00597 tng_plugin.type = MOLFILE_PLUGIN_TYPE;
00598 tng_plugin.name = "tng";
00599 tng_plugin.prettyname = "TNG: Trajectory Next Generation (testing)";
00600 tng_plugin.author = "Magnus Lundborg";
00601 tng_plugin.majorv = TNG_PLUGIN_MAJOR_VERSION;
00602 tng_plugin.minorv = TNG_PLUGIN_MINOR_VERSION;
00603 tng_plugin.is_reentrant = VMDPLUGIN_THREADUNSAFE;
00604 tng_plugin.filename_extension = "tng";
00605 tng_plugin.open_file_read = open_tng_read;
00606 tng_plugin.read_structure = read_tng_structure;
00607 tng_plugin.read_bonds = read_tng_bonds;
00608 tng_plugin.read_next_timestep = read_tng_timestep;
00609 tng_plugin.close_file_read = close_tng;
00610 tng_plugin.open_file_write = open_tng_write;
00611 tng_plugin.write_structure = write_tng_structure;
00612 tng_plugin.write_timestep = write_tng_timestep;
00613 tng_plugin.close_file_write = close_tng;
00614 tng_plugin.write_bonds = write_tng_bonds;
00615 tng_plugin.read_timestep_metadata = read_timestep_metadata;
00616
00617 return VMDPLUGIN_SUCCESS;
00618 }
00619
00620 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00621 (*cb)(v, (vmdplugin_t *)&tng_plugin);
00622 return VMDPLUGIN_SUCCESS;
00623 }
00624
00625 VMDPLUGIN_API int VMDPLUGIN_fini() {
00626 return VMDPLUGIN_SUCCESS;
00627 }
00628
00629