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 #include <stdio.h>
00030
00031 #include "MolFilePlugin.h"
00032 #include "Molecule.h"
00033 #include "AtomSel.h"
00034 #include "Timestep.h"
00035 #include "Inform.h"
00036 #include "Scene.h"
00037 #include "molfile_plugin.h"
00038 #include "PeriodicTable.h"
00039 #include "VolumetricData.h"
00040 #include "MoleculeGraphics.h"
00041 #include "QMData.h"
00042 #include "QMTimestep.h"
00043
00044 #if defined(VMDTKCON)
00045 #include "vmdconsole.h"
00046 #endif
00047
00048 #define MINSIZEOF(a, b) \
00049 ((sizeof(a) < sizeof(b)) ? sizeof(a) : sizeof(b))
00050
00051 #define SAFESTRNCPY(a, b) \
00052 (strncpy(a, b, MINSIZEOF(a, b)))
00053
00054 MolFilePlugin::MolFilePlugin(vmdplugin_t *p)
00055 : plugin((molfile_plugin_t *)p) {
00056 rv = wv = NULL;
00057 numatoms = 0;
00058 _filename = NULL;
00059 #if vmdplugin_ABIVERSION > 13
00060 qm_data = NULL;
00061 #if defined(VMDTKCON)
00062 plugin->cons_fputs = &vmdcon_fputs;
00063 #else
00064 plugin->cons_fputs = NULL;
00065 #endif
00066 #endif
00067 }
00068
00069 MolFilePlugin::~MolFilePlugin() {
00070 close();
00071 delete [] _filename;
00072 }
00073
00074 int MolFilePlugin::read_structure(Molecule *m, int filebonds, int autobonds) {
00075 if (!rv) return MOLFILE_ERROR;
00076 if (!can_read_structure()) return MOLFILE_ERROR;
00077 if (!m->init_atoms(numatoms)) return MOLFILE_ERROR;
00078
00079 molfile_atom_t *atoms =
00080 (molfile_atom_t *) calloc(1, numatoms*sizeof(molfile_atom_t));
00081
00082 int rc, i;
00083 int optflags = MOLFILE_BADOPTIONS;
00084 if ((rc = plugin->read_structure(rv, &optflags, atoms))) {
00085 free(atoms);
00086 return rc;
00087 }
00088 if (optflags == MOLFILE_BADOPTIONS) {
00089 free(atoms);
00090 msgErr << "MolFilePlugin: plugin didn't initialize optional data flags" << sendmsg;
00091 msgErr << "MolFilePlugin: file load aborted" << sendmsg;
00092 return MOLFILE_ERROR;
00093 }
00094
00095
00096 float *charge = m->charge();
00097 float *mass = m->mass();
00098 float *radius = m->radius();
00099 float *beta = m->beta();
00100 float *occupancy = m->occupancy();
00101
00102
00103 if (optflags & MOLFILE_INSERTION)
00104 m->set_dataset_flag(BaseMolecule::INSERTION);
00105 if (optflags & MOLFILE_OCCUPANCY)
00106 m->set_dataset_flag(BaseMolecule::OCCUPANCY);
00107 if (optflags & MOLFILE_BFACTOR)
00108 m->set_dataset_flag(BaseMolecule::BFACTOR);
00109 if (optflags & MOLFILE_MASS)
00110 m->set_dataset_flag(BaseMolecule::MASS);
00111 if (optflags & MOLFILE_CHARGE)
00112 m->set_dataset_flag(BaseMolecule::CHARGE);
00113 if (optflags & MOLFILE_RADIUS)
00114 m->set_dataset_flag(BaseMolecule::RADIUS);
00115 if (optflags & MOLFILE_ALTLOC)
00116 m->set_dataset_flag(BaseMolecule::ALTLOC);
00117 if (optflags & MOLFILE_ATOMICNUMBER)
00118 m->set_dataset_flag(BaseMolecule::ATOMICNUMBER);
00119
00120
00121 if (optflags & MOLFILE_RADIUS)
00122 m->set_radii_changed();
00123
00124 for (i=0; i<numatoms; i++) {
00125 molfile_atom_t &atom = atoms[i];
00126 int atomicnumber = (optflags & MOLFILE_ATOMICNUMBER) ?
00127 atom.atomicnumber : -1;
00128 charge[i] = (optflags & MOLFILE_CHARGE) ?
00129 atom.charge : m->default_charge(atom.name);
00130
00131
00132
00133
00134
00135 mass[i] = (optflags & MOLFILE_MASS) ?
00136 atom.mass : ((atomicnumber > 0) ?
00137 get_pte_mass(atomicnumber) : m->default_mass(atom.name));
00138
00139
00140
00141
00142
00143 radius[i] = (optflags & MOLFILE_RADIUS) ?
00144 atom.radius : ((atomicnumber > 0) ?
00145 get_pte_vdw_radius(atomicnumber) : m->default_radius(atom.name));
00146
00147 beta[i] = (optflags & MOLFILE_BFACTOR) ?
00148 atom.bfactor : m->default_beta();
00149 occupancy[i] = (optflags & MOLFILE_OCCUPANCY) ?
00150 atom.occupancy : m->default_occup();
00151 const char *insertion = (optflags & MOLFILE_INSERTION) ?
00152 atom.insertion : " ";
00153 const char *altloc = (optflags & MOLFILE_ALTLOC) ?
00154 atom.altloc : "";
00155 if (0 > m->add_atom(atom.name, atom.type, atomicnumber,
00156 atom.resname, atom.resid,
00157 atom.chain, atom.segid, (char *)insertion, altloc)) {
00158
00159
00160
00161 msgErr << "MolFilePlugin: file load aborted" << sendmsg;
00162 free(atoms);
00163 return MOLFILE_ERROR;
00164 }
00165 }
00166 free(atoms);
00167
00168 if (filebonds && can_read_bonds()) {
00169 int nbonds, *from, *to, nbondtypes, *bondtype;
00170 float *bondorder;
00171 char **bondtypename;
00172
00173
00174
00175 nbondtypes = 0;
00176 bondtype = NULL;
00177 bondtypename = NULL;
00178
00179 #if vmdplugin_ABIVERSION >= 15
00180 if (plugin->read_bonds(rv, &nbonds, &from, &to, &bondorder, &bondtype,
00181 &nbondtypes, &bondtypename))
00182 #else
00183 if (plugin->read_bonds(rv, &nbonds, &from, &to, &bondorder))
00184 #endif
00185 {
00186
00187 msgErr << "Error reading bond information." << sendmsg;
00188 if (autobonds)
00189 m->find_bonds_from_timestep();
00190 } else {
00191
00192
00193
00194 if (nbonds == 0 && from == NULL && to == NULL) {
00195 if (autobonds)
00196 m->find_bonds_from_timestep();
00197 } else if (nbonds > 0) {
00198
00199
00200 if (bondtypename != NULL)
00201 for (i=0; i < nbondtypes; i++)
00202 m->bondTypeNames.add_name(bondtypename[i], i);
00203
00204
00205
00206
00207
00208 if (optflags & MOLFILE_BONDSSPECIAL) {
00209 if (autobonds) {
00210 m->find_unique_bonds_from_timestep();
00211 }
00212
00213
00214 m->set_dataset_flag(BaseMolecule::BONDS);
00215 if (bondorder != NULL)
00216 m->set_dataset_flag(BaseMolecule::BONDORDERS);
00217 if (bondtype != NULL)
00218 m->set_dataset_flag(BaseMolecule::BONDTYPES);
00219
00220
00221 for (i=0; i<nbonds; i++) {
00222 float bo = 1;
00223 int bt = -1;
00224 if (bondorder != NULL)
00225 bo = bondorder[i];
00226 if (bondtype != NULL) {
00227 if (bondtypename != NULL) {
00228 bt = m->bondTypeNames.typecode(bondtypename[bondtype[i]]);
00229 } else {
00230 bt = bondtype[i];
00231 }
00232 }
00233 m->add_bond_dupcheck(from[i]-1, to[i]-1, bo, bt);
00234 }
00235 } else {
00236
00237
00238 m->set_dataset_flag(BaseMolecule::BONDS);
00239 if (bondorder != NULL)
00240 m->set_dataset_flag(BaseMolecule::BONDORDERS);
00241 if (bondtype != NULL)
00242 m->set_dataset_flag(BaseMolecule::BONDTYPES);
00243
00244
00245 for (i=0; i<nbonds; i++) {
00246 float bo = 1;
00247 int bt = -1;
00248 if (bondorder != NULL) bo = bondorder[i];
00249 if (bondtype != NULL) bt = bondtype[i];
00250 m->add_bond(from[i]-1, to[i]-1, bo, bt);
00251 }
00252 }
00253 }
00254 }
00255 } else {
00256 if (autobonds)
00257 m->find_bonds_from_timestep();
00258 }
00259
00260
00261
00262 #if vmdplugin_ABIVERSION > 9
00263 if (can_read_angles()) {
00264 int numangles, *angles, *angletypes, numangletypes;
00265 int numdihedrals, *dihedrals, *dihedraltypes, numdihedraltypes;
00266 int numimpropers, *impropers, *impropertypes, numimpropertypes;
00267 int numcterms, *cterms, ctermcols, ctermrows;
00268 char **angletypenames, **dihedraltypenames, **impropertypenames;
00269 double *angleforces, *dihedralforces, *improperforces, *ctermforces;
00270
00271
00272 angletypes = dihedraltypes = impropertypes = NULL;
00273 numangletypes = numdihedraltypes = numimpropertypes = 0;
00274 angletypenames = dihedraltypenames = impropertypenames = NULL;
00275 angleforces = dihedralforces = improperforces = ctermforces = NULL;
00276
00277 #if vmdplugin_ABIVERSION >= 16
00278 if (plugin->read_angles(rv, &numangles, &angles, &angletypes,
00279 &numangletypes, &angletypenames, &numdihedrals,
00280 &dihedrals, &dihedraltypes, &numdihedraltypes,
00281 &dihedraltypenames, &numimpropers, &impropers,
00282 &impropertypes, &numimpropertypes,
00283 &impropertypenames, &numcterms, &cterms,
00284 &ctermcols, &ctermrows))
00285
00286 #else
00287 if (plugin->read_angles(rv,
00288 &numangles, &angles, &angleforces,
00289 &numdihedrals, &dihedrals, &dihedralforces,
00290 &numimpropers, &impropers, &improperforces,
00291 &numcterms, &cterms, &ctermcols, &ctermrows,
00292 &ctermforces))
00293 #endif
00294 {
00295 msgErr << "Error reading angle and cross-term information." << sendmsg;
00296 } else {
00297
00298
00299
00300 if ( (angletypes != NULL) || (dihedraltypes != NULL)
00301 || (impropertypes != NULL) )
00302 m->set_dataset_flag(BaseMolecule::ANGLETYPES);
00303
00304
00305
00306 if (angletypenames != NULL)
00307 for (i=0; i < numangletypes; i++)
00308 m->angleTypeNames.add_name(angletypenames[i], i);
00309
00310 if (dihedraltypenames != NULL)
00311 for (i=0; i < numdihedraltypes; i++)
00312 m->dihedralTypeNames.add_name(dihedraltypenames[i], i);
00313
00314 if (impropertypenames != NULL)
00315 for (i=0; i < numimpropertypes; i++)
00316 m->improperTypeNames.add_name(impropertypenames[i], i);
00317
00318
00319
00320
00321
00322
00323 if (numangles > 0 || numdihedrals > 0 || numimpropers > 0) {
00324 m->set_dataset_flag(BaseMolecule::ANGLES);
00325 m->clear_angles();
00326 if (angletypes != NULL) {
00327 int type;
00328
00329 for (i=0; i<numangles; i++) {
00330 type = angletypes[i];
00331 if (angletypenames != NULL)
00332 type = m->angleTypeNames.typecode(angletypenames[type]);
00333
00334 m->add_angle(angles[3*i]-1, angles[3*i+1]-1, angles[3*i+2]-1, type);
00335 }
00336 } else {
00337 for (i=0; i<numangles; i++) {
00338 m->add_angle(angles[3*i]-1, angles[3*i+1]-1, angles[3*i+2]-1);
00339 }
00340 }
00341
00342 m->clear_dihedrals();
00343 if (dihedraltypes != NULL) {
00344 int type;
00345
00346 for (i=0; i<numdihedrals; i++) {
00347 type = dihedraltypes[i];
00348 if (dihedraltypenames != NULL)
00349 type = m->dihedralTypeNames.typecode(dihedraltypenames[type]);
00350
00351 m->add_dihedral(dihedrals[4*i]-1, dihedrals[4*i+1]-1,
00352 dihedrals[4*i+2]-1, dihedrals[4*i+3]-1, type);
00353 }
00354 } else {
00355 for (i=0; i<numdihedrals; i++) {
00356 m->add_dihedral(dihedrals[4*i]-1, dihedrals[4*i+1]-1,
00357 dihedrals[4*i+2]-1, dihedrals[4*i+3]-1);
00358 }
00359 }
00360
00361 m->clear_impropers();
00362 if (impropertypes != NULL) {
00363 int type;
00364
00365 for (i=0; i<numimpropers; i++) {
00366 type = impropertypes[i];
00367 if (impropertypenames != NULL)
00368 type = m->improperTypeNames.typecode(impropertypenames[type]);
00369
00370 m->add_improper(impropers[4*i]-1, impropers[4*i+1]-1,
00371 impropers[4*i+2]-1, impropers[4*i+3]-1, type);
00372 }
00373 } else {
00374 for (i=0; i<numimpropers; i++) {
00375 m->add_improper(impropers[4*i]-1, impropers[4*i+1]-1,
00376 impropers[4*i+2]-1, impropers[4*i+3]-1);
00377 }
00378 }
00379 }
00380
00381
00382 if (numcterms > 0) {
00383 m->set_dataset_flag(BaseMolecule::CTERMS);
00384 for (i=0; i<numcterms; i++)
00385 m->add_cterm(cterms[8*i]-1, cterms[8*i+1]-1, cterms[8*i+2]-1,
00386 cterms[8*i+3]-1, cterms[8*i+4]-1, cterms[8*i+5]-1,
00387 cterms[8*i+6]-1, cterms[8*i+7]-1);
00388 }
00389 }
00390 }
00391 #endif
00392 return MOLFILE_SUCCESS;
00393 }
00394
00395
00396 int MolFilePlugin::read_optional_structure(Molecule *m, int filebonds) {
00397 if (!rv) return MOLFILE_ERROR;
00398 if (!can_read_structure()) return MOLFILE_ERROR;
00399 if (numatoms != m->nAtoms) return MOLFILE_ERROR;
00400
00401 molfile_atom_t *atoms = (molfile_atom_t *) calloc(1, numatoms*sizeof(molfile_atom_t));
00402
00403 int rc, i;
00404 int optflags = MOLFILE_BADOPTIONS;
00405 if ((rc = plugin->read_structure(rv, &optflags, atoms))) {
00406 free(atoms);
00407 return rc;
00408 }
00409 if (optflags == MOLFILE_BADOPTIONS) {
00410 free(atoms);
00411 msgErr << "MolFilePlugin: plugin didn't initialize optional data flags" << sendmsg;
00412 msgErr << "MolFilePlugin: file load aborted" << sendmsg;
00413 return MOLFILE_ERROR;
00414 }
00415
00416
00417 if (optflags & MOLFILE_OCCUPANCY)
00418 m->set_dataset_flag(BaseMolecule::OCCUPANCY);
00419 if (optflags & MOLFILE_BFACTOR)
00420 m->set_dataset_flag(BaseMolecule::BFACTOR);
00421 if (optflags & MOLFILE_MASS)
00422 m->set_dataset_flag(BaseMolecule::MASS);
00423 if (optflags & MOLFILE_CHARGE)
00424 m->set_dataset_flag(BaseMolecule::CHARGE);
00425 if (optflags & MOLFILE_RADIUS)
00426 m->set_dataset_flag(BaseMolecule::RADIUS);
00427 if (optflags & MOLFILE_ATOMICNUMBER)
00428 m->set_dataset_flag(BaseMolecule::ATOMICNUMBER);
00429
00430
00431 if (optflags & MOLFILE_RADIUS)
00432 m->set_radii_changed();
00433
00434 float *charge = m->charge();
00435 float *mass = m->mass();
00436 float *radius = m->radius();
00437 float *beta = m->beta();
00438 float *occupancy = m->occupancy();
00439 for (i=0; i<numatoms; i++) {
00440 if (optflags & MOLFILE_OCCUPANCY) {
00441 occupancy[i] = atoms[i].occupancy;
00442 }
00443
00444 if (optflags & MOLFILE_BFACTOR) {
00445 beta[i] = atoms[i].bfactor;
00446 }
00447
00448 if (optflags & MOLFILE_MASS) {
00449 mass[i] = atoms[i].mass;
00450 }
00451
00452 if (optflags & MOLFILE_CHARGE) {
00453 charge[i] = atoms[i].charge;
00454 }
00455
00456 if (optflags & MOLFILE_RADIUS) {
00457 radius[i] = atoms[i].radius;
00458 }
00459
00460 if (optflags & MOLFILE_ATOMICNUMBER) {
00461 m->atom(i)->atomicnumber = atoms[i].atomicnumber;
00462 }
00463 }
00464 free(atoms);
00465
00466
00467 if (!can_read_bonds())
00468 return MOLFILE_SUCCESS;
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 if (!(optflags & MOLFILE_BONDSSPECIAL) && filebonds) {
00479 int nbonds, *from, *to, nbondtypes, *bondtype;
00480 float *bondorder;
00481 char **bondtypename;
00482
00483
00484
00485 nbondtypes = 0;
00486 bondtype = NULL;
00487 bondtypename = NULL;
00488
00489 #if vmdplugin_ABIVERSION >= 15
00490 if (plugin->read_bonds(rv, &nbonds, &from, &to, &bondorder, &bondtype,
00491 &nbondtypes, &bondtypename))
00492 return MOLFILE_SUCCESS;
00493 #else
00494 if (plugin->read_bonds(rv, &nbonds, &from, &to, &bondorder))
00495 return MOLFILE_SUCCESS;
00496 #endif
00497
00498
00499
00500 if (bondtypename != NULL)
00501 for (i=0; i < nbondtypes; i++)
00502 m->bondTypeNames.add_name(bondtypename[i], i);
00503
00504 if (nbonds == 0)
00505 return MOLFILE_SUCCESS;
00506
00507 for (i=0; i<numatoms; i++)
00508 m->atom(i)->bonds = 0;
00509
00510 m->set_dataset_flag(BaseMolecule::BONDS);
00511 if (bondorder != NULL)
00512 m->set_dataset_flag(BaseMolecule::BONDORDERS);
00513 if (bondtype != NULL)
00514 m->set_dataset_flag(BaseMolecule::BONDTYPES);
00515
00516 for (i=0; i<nbonds; i++) {
00517 float bo = 1;
00518 int bt = -1;
00519
00520 if (bondorder != NULL)
00521 bo = bondorder[i];
00522 if (bondtype != NULL) {
00523 if (bondtypename != NULL) {
00524 bt = m->bondTypeNames.typecode(bondtypename[bondtype[i]]);
00525 } else {
00526 bt = bondtype[i];
00527 }
00528 }
00529
00530 m->add_bond(from[i]-1, to[i]-1, bo, bt);
00531 }
00532 } else {
00533
00534 return MOLFILE_SUCCESS;
00535 }
00536
00537
00538
00539 #if vmdplugin_ABIVERSION > 9
00540 if (can_read_angles()) {
00541 int numangles, *angles, *angletypes, numangletypes;
00542 int numdihedrals, *dihedrals, *dihedraltypes, numdihedraltypes;
00543 int numimpropers, *impropers, *impropertypes, numimpropertypes;
00544 int numcterms, *cterms, ctermcols, ctermrows;
00545 char **angletypenames, **dihedraltypenames, **impropertypenames;
00546 double *angleforces, *dihedralforces, *improperforces, *ctermforces;
00547
00548
00549 angletypes = dihedraltypes = impropertypes = NULL;
00550 numangletypes = numdihedraltypes = numimpropertypes = 0;
00551 angletypenames = dihedraltypenames = impropertypenames = NULL;
00552 angleforces = dihedralforces = improperforces = ctermforces = NULL;
00553
00554 #if vmdplugin_ABIVERSION >= 16
00555 if (plugin->read_angles(rv, &numangles, &angles, &angletypes,
00556 &numangletypes, &angletypenames, &numdihedrals,
00557 &dihedrals, &dihedraltypes, &numdihedraltypes,
00558 &dihedraltypenames, &numimpropers, &impropers,
00559 &impropertypes, &numimpropertypes,
00560 &impropertypenames, &numcterms, &cterms,
00561 &ctermcols, &ctermrows))
00562
00563 #else
00564 if (plugin->read_angles(rv,
00565 &numangles, &angles, &angleforces,
00566 &numdihedrals, &dihedrals, &dihedralforces,
00567 &numimpropers, &impropers, &improperforces,
00568 &numcterms, &cterms, &ctermcols, &ctermrows,
00569 &ctermforces))
00570 #endif
00571 {
00572 msgErr << "Error reading angle and cross-term information." << sendmsg;
00573 } else {
00574
00575
00576
00577 if ( (angletypes != NULL) || (dihedraltypes != NULL)
00578 || (impropertypes != NULL) )
00579 m->set_dataset_flag(BaseMolecule::ANGLETYPES);
00580
00581
00582
00583 if (angletypenames != NULL)
00584 for (i=0; i < numangletypes; i++)
00585 m->angleTypeNames.add_name(angletypenames[i], i);
00586
00587 if (dihedraltypenames != NULL)
00588 for (i=0; i < numdihedraltypes; i++)
00589 m->dihedralTypeNames.add_name(dihedraltypenames[i], i);
00590
00591 if (impropertypenames != NULL)
00592 for (i=0; i < numimpropertypes; i++)
00593 m->improperTypeNames.add_name(impropertypenames[i], i);
00594
00595
00596
00597
00598
00599
00600 if (numangles > 0 || numdihedrals > 0 || numimpropers > 0) {
00601 m->set_dataset_flag(BaseMolecule::ANGLES);
00602 m->clear_angles();
00603 if (angletypes != NULL) {
00604 int type;
00605
00606 for (i=0; i<numangles; i++) {
00607 type = angletypes[i];
00608 if (angletypenames != NULL)
00609 type = m->angleTypeNames.typecode(angletypenames[type]);
00610
00611 m->add_angle(angles[3*i]-1, angles[3*i+1]-1, angles[3*i+2]-1, type);
00612 }
00613 } else {
00614 for (i=0; i<numangles; i++) {
00615 m->add_angle(angles[3*i]-1, angles[3*i+1]-1, angles[3*i+2]-1);
00616 }
00617 }
00618
00619 m->clear_dihedrals();
00620 if (dihedraltypes != NULL) {
00621 int type;
00622
00623 for (i=0; i<numdihedrals; i++) {
00624 type = dihedraltypes[i];
00625 if (dihedraltypenames != NULL)
00626 type = m->dihedralTypeNames.typecode(dihedraltypenames[type]);
00627
00628 m->add_dihedral(dihedrals[4*i]-1, dihedrals[4*i+1]-1,
00629 dihedrals[4*i+2]-1, dihedrals[4*i+3]-1, type);
00630 }
00631 } else {
00632 for (i=0; i<numdihedrals; i++) {
00633 m->add_dihedral(dihedrals[4*i]-1, dihedrals[4*i+1]-1,
00634 dihedrals[4*i+2]-1, dihedrals[4*i+3]-1);
00635 }
00636 }
00637
00638 m->clear_impropers();
00639 if (impropertypes != NULL) {
00640 int type;
00641
00642 for (i=0; i<numimpropers; i++) {
00643 type = impropertypes[i];
00644 if (impropertypenames != NULL)
00645 type = m->improperTypeNames.typecode(impropertypenames[type]);
00646
00647 m->add_improper(impropers[4*i]-1, impropers[4*i+1]-1,
00648 impropers[4*i+2]-1, impropers[4*i+3]-1, type);
00649 }
00650 } else {
00651 for (i=0; i<numimpropers; i++) {
00652 m->add_improper(impropers[4*i]-1, impropers[4*i+1]-1,
00653 impropers[4*i+2]-1, impropers[4*i+3]-1);
00654 }
00655 }
00656 }
00657
00658
00659 if (numcterms > 0) {
00660 m->set_dataset_flag(BaseMolecule::CTERMS);
00661 for (i=0; i<numcterms; i++)
00662 m->add_cterm(cterms[8*i]-1, cterms[8*i+1]-1, cterms[8*i+2]-1,
00663 cterms[8*i+3]-1, cterms[8*i+4]-1, cterms[8*i+5]-1,
00664 cterms[8*i+6]-1, cterms[8*i+7]-1);
00665 }
00666 }
00667 }
00668 #endif
00669
00670
00671
00672 m->analyze();
00673
00674
00675 m->force_recalc(DrawMolItem::COL_REGEN | DrawMolItem::SEL_REGEN);
00676
00677
00678 m->invalidate_ss();
00679
00680 return MOLFILE_SUCCESS;
00681 }
00682
00683 void MolFilePlugin::set_natoms(int n) {
00684 numatoms = n;
00685 }
00686
00687 int MolFilePlugin::init_read(const char *file) {
00688 rv = NULL;
00689 if (can_read_structure() || can_read_timesteps() || can_read_graphics() ||
00690 can_read_volumetric() || can_read_metadata() || can_read_qm()) {
00691 rv = plugin->open_file_read(file, plugin->name, &numatoms);
00692 }
00693 if (!rv) return MOLFILE_ERROR;
00694 delete [] _filename;
00695 _filename = stringdup(file);
00696 return MOLFILE_SUCCESS;
00697 }
00698
00699 Timestep *MolFilePlugin::next(Molecule *m) {
00700 if (!rv) return NULL;
00701 if (numatoms <= 0) return NULL;
00702 if (!(can_read_timesteps() || can_read_qm_timestep())) return NULL;
00703 molfile_timestep_t timestep;
00704 memset(×tep, 0, sizeof(molfile_timestep_t));
00705
00706
00707
00708
00709 float *velocities = NULL;
00710
00711
00712
00713 #if vmdplugin_ABIVERSION > 10
00714 molfile_timestep_metadata_t meta;
00715 if (can_read_timestep_metadata()) {
00716 memset(&meta, 0, sizeof(molfile_timestep_metadata));
00717 plugin->read_timestep_metadata(rv, &meta);
00718 if (meta.has_velocities) {
00719 velocities = new float[3*numatoms];
00720 }
00721 }
00722 #endif
00723
00724 #if vmdplugin_ABIVERSION > 11
00725
00726
00727
00728 molfile_qm_timestep_metadata_t qmmeta;
00729 if (can_read_qm_timestep_metadata()) {
00730 memset(&qmmeta, 0, sizeof(molfile_qm_timestep_metadata));
00731
00732
00733
00734 plugin->read_qm_timestep_metadata(rv, &qmmeta);
00735 }
00736 #endif
00737
00738
00739
00740
00741
00742 timestep.A = timestep.B = timestep.C = 0.0f;
00743
00744
00745 timestep.alpha = timestep.beta = timestep.gamma = 90.0f;
00746
00747 Timestep *ts = new Timestep(numatoms);
00748 timestep.coords = ts->pos;
00749 #if vmdplugin_ABIVERSION > 10
00750 timestep.velocities = velocities;
00751 #endif
00752 ts->vel = velocities;
00753
00754 int rc = 0;
00755 #if vmdplugin_ABIVERSION > 11
00756 molfile_qm_metadata_t *qm_metadata = NULL;
00757 molfile_qm_timestep_t qm_timestep;
00758 memset(&qm_timestep, 0, sizeof(molfile_qm_timestep_t));
00759 #endif
00760
00761
00762
00763 if (can_read_qm_timestep()) {
00764 #if vmdplugin_ABIVERSION > 11
00765 qm_timestep.scfenergies = new double[qmmeta.num_scfiter];
00766 qm_timestep.wave = new molfile_qm_wavefunction_t[qmmeta.num_wavef];
00767 memset(qm_timestep.wave, 0, qmmeta.num_wavef*sizeof(molfile_qm_wavefunction_t));
00768 int i;
00769 for (i=0; (i<MOLFILE_MAXWAVEPERTS && i<qmmeta.num_wavef); i++) {
00770 qm_timestep.wave[i].wave_coeffs =
00771 new float[qmmeta.num_orbitals_per_wavef[i]*qmmeta.wavef_size];
00772 if (qmmeta.has_orben_per_wavef[i]) {
00773 qm_timestep.wave[i].orbital_energies =
00774 new float[qmmeta.num_orbitals_per_wavef[i]];
00775 }
00776 if (qmmeta.has_occup_per_wavef[i]) {
00777 qm_timestep.wave[i].occupancies =
00778 new float[qmmeta.num_orbitals_per_wavef[i]];
00779 }
00780 }
00781 if (qmmeta.has_gradient) {
00782 qm_timestep.gradient = new float[3*numatoms];
00783 }
00784 if (qmmeta.num_charge_sets) {
00785 qm_timestep.charges = new double[numatoms*qmmeta.num_charge_sets];
00786 qm_timestep.charge_types = new int[qmmeta.num_charge_sets];
00787 }
00788 rc = plugin->read_timestep(rv, numatoms, ×tep, qm_metadata, &qm_timestep);
00789 #endif
00790 } else {
00791 rc = plugin->read_next_timestep(rv, numatoms, ×tep);
00792 }
00793
00794 if (rc) {
00795 #if vmdplugin_ABIVERSION > 11
00796 if (can_read_qm_timestep()) {
00797 delete [] qm_timestep.scfenergies;
00798 if (qm_timestep.gradient) delete [] qm_timestep.gradient;
00799 if (qm_timestep.charges) delete [] qm_timestep.charges;
00800 if (qm_timestep.charge_types) delete [] qm_timestep.charge_types;
00801 int i;
00802 for (i=0; i<qmmeta.num_wavef; i++) {
00803 delete [] qm_timestep.wave[i].wave_coeffs;
00804 delete [] qm_timestep.wave[i].orbital_energies;
00805 }
00806 delete [] qm_timestep.wave;
00807 }
00808 #endif
00809 delete ts;
00810 ts = NULL;
00811 } else {
00812 ts->a_length = timestep.A;
00813 ts->b_length = timestep.B;
00814 ts->c_length = timestep.C;
00815 ts->alpha = timestep.alpha;
00816 ts->beta = timestep.beta;
00817 ts->gamma = timestep.gamma;
00818 #if vmdplugin_ABIVERSION > 10
00819 ts->physical_time = timestep.physical_time;
00820 #endif
00821 #if vmdplugin_ABIVERSION > 11
00822 if (can_read_qm_timestep()) {
00823 int i;
00824 int *chargetypes = new int[qmmeta.num_charge_sets];
00825 for (i=0; i<qmmeta.num_charge_sets; i++) {
00826 switch (qm_timestep.charge_types[i]) {
00827 case MOLFILE_QMCHARGE_MULLIKEN:
00828 chargetypes[i] = QMCHARGE_MULLIKEN;
00829 break;
00830 case MOLFILE_QMCHARGE_LOWDIN:
00831 chargetypes[i] = QMCHARGE_LOWDIN;
00832 break;
00833 case MOLFILE_QMCHARGE_ESP:
00834 chargetypes[i] = QMCHARGE_ESP;
00835 break;
00836 case MOLFILE_QMCHARGE_NPA:
00837 chargetypes[i] = QMCHARGE_NPA;
00838 break;
00839 default:
00840 chargetypes[i] = QMCHARGE_UNKNOWN;
00841 }
00842 }
00843
00844 ts->qm_timestep = new QMTimestep(numatoms);
00845 ts->qm_timestep->set_charges(qm_timestep.charges,
00846 chargetypes,
00847 numatoms, qmmeta.num_charge_sets);
00848 delete [] chargetypes;
00849
00850 ts->qm_timestep->set_scfenergies(qm_timestep.scfenergies,
00851 qmmeta.num_scfiter);
00852
00853
00854
00855
00856 int num_signa_ts = 0;
00857 wavef_signa_t *signa_ts = NULL;
00858 for (i=0; i<qmmeta.num_wavef; i++) {
00859
00860
00861
00862
00863 int wavef_type;
00864 switch (qm_timestep.wave[i].type) {
00865 case MOLFILE_WAVE_CANON:
00866 wavef_type = WAVE_CANON;
00867 break;
00868 case MOLFILE_WAVE_CINATUR:
00869 wavef_type = WAVE_CINATUR;
00870 break;
00871 case MOLFILE_WAVE_GEMINAL:
00872 wavef_type = WAVE_GEMINAL;
00873 break;
00874 case MOLFILE_WAVE_BOYS:
00875 wavef_type = WAVE_BOYS;
00876 break;
00877 case MOLFILE_WAVE_RUEDEN:
00878 wavef_type = WAVE_RUEDEN;
00879 break;
00880 case MOLFILE_WAVE_PIPEK:
00881 wavef_type = WAVE_PIPEK;
00882 break;
00883 case MOLFILE_WAVE_MCSCFOPT:
00884 wavef_type = WAVE_MCSCFOPT;
00885 break;
00886 case MOLFILE_WAVE_MCSCFNAT:
00887 wavef_type = WAVE_MCSCFNAT;
00888 break;
00889 default:
00890 wavef_type = WAVE_UNKNOWN;
00891 }
00892
00893
00894 ts->qm_timestep->add_wavefunction(qm_data,
00895 qmmeta.wavef_size,
00896 qmmeta.num_orbitals_per_wavef[i],
00897 qm_timestep.wave[i].wave_coeffs,
00898 qm_timestep.wave[i].orbital_energies,
00899 qm_timestep.wave[i].occupancies,
00900 qm_timestep.wave[i].orbital_ids,
00901 qm_timestep.wave[i].energy,
00902 wavef_type,
00903 qm_timestep.wave[i].spin,
00904 qm_timestep.wave[i].excitation,
00905 qm_timestep.wave[i].multiplicity,
00906 qm_timestep.wave[i].info,
00907 signa_ts, num_signa_ts);
00908 }
00909 free(signa_ts);
00910
00911 ts->qm_timestep->set_gradients(qm_timestep.gradient, numatoms);
00912
00913 delete [] qm_timestep.scfenergies;
00914 if (qm_timestep.gradient) delete [] qm_timestep.gradient;
00915 if (qm_timestep.charges) delete [] qm_timestep.charges;
00916 if (qm_timestep.charge_types) delete [] qm_timestep.charge_types;
00917
00918 for (i=0; i<qmmeta.num_wavef; i++) {
00919 delete [] qm_timestep.wave[i].wave_coeffs;
00920 delete [] qm_timestep.wave[i].orbital_energies;
00921 delete [] qm_timestep.wave[i].occupancies;
00922 }
00923 delete [] qm_timestep.wave;
00924 #if 0
00925
00926
00927
00928
00929
00930 if (m->numframes()>0) {
00931
00932 Timestep *prevts = m->get_frame(m->numframes()-1);
00933
00934 msgInfo << "sort frame " << m->numframes() << sendmsg;
00935
00936
00937
00938 ts->qm_timestep->sort_orbitals(prevts->qm_timestep);
00939 } else {
00940 msgInfo << "ignore frame " << m->numframes() << sendmsg;
00941 }
00942 #endif
00943 }
00944 #endif
00945 }
00946 return ts;
00947 }
00948
00949 int MolFilePlugin::skip(Molecule *m) {
00950 if (!rv) return MOLFILE_ERROR;
00951 if (!can_read_timesteps()) return MOLFILE_ERROR;
00952 return plugin->read_next_timestep(rv, numatoms, 0);
00953 }
00954
00955 void MolFilePlugin::close() {
00956 if (rv && (can_read_structure() || can_read_timesteps() ||
00957 can_read_graphics() || can_read_volumetric() ||
00958 can_read_metadata() || can_read_bonds())) {
00959 plugin->close_file_read(rv);
00960 rv = NULL;
00961 }
00962 if (wv && (can_write_structure() || can_write_timesteps() ||
00963 can_write_bonds())) {
00964 plugin->close_file_write(wv);
00965 wv = NULL;
00966 }
00967 }
00968
00969 int MolFilePlugin::init_write(const char *file, int natoms) {
00970 wv = NULL;
00971 if (can_write_structure() || can_write_timesteps()
00972 #if vmdplugin_ABIVERSION > 9
00973 || can_write_volumetric()
00974 #endif
00975 ) {
00976 wv = plugin->open_file_write(file, plugin->name, natoms);
00977 }
00978 if (!wv) return MOLFILE_ERROR;
00979 delete [] _filename;
00980 _filename = stringdup(file);
00981
00982
00983
00984
00985 numatoms = natoms;
00986
00987 return MOLFILE_SUCCESS;
00988 }
00989
00990
00991 int MolFilePlugin::write_structure(Molecule *m, const int *on) {
00992 if (!wv) return MOLFILE_ERROR;
00993 if (!can_write_structure()) return MOLFILE_ERROR;
00994 if (!m->has_structure()) {
00995 msgErr << "Molecule's structure has not been initialized." << sendmsg;
00996 return MOLFILE_ERROR;
00997 }
00998
00999 int i, j, k;
01000 molfile_atom_t *atoms = (molfile_atom_t *) calloc(1, numatoms*sizeof(molfile_atom_t));
01001 int *atomindexmap = (int *) calloc(1, m->nAtoms*sizeof(int));
01002
01003
01004
01005 for (i=0; i<m->nAtoms; i++)
01006 atomindexmap[i] = -1;
01007
01008 const float *charge = m->charge();
01009 const float *mass = m->mass();
01010 const float *radius = m->radius();
01011 const float *beta = m->beta();
01012 const float *occupancy = m->occupancy();
01013
01014 int mangleatomnames = 1;
01015 if (getenv("VMDNOMANGLEATOMNAMES")) {
01016 mangleatomnames = 0;
01017 }
01018
01019
01020 for (i=0, j=0; i<m->nAtoms; i++) {
01021
01022 if (on && !on[i])
01023 continue;
01024
01025
01026
01027
01028 if (j >= numatoms) {
01029 msgErr <<
01030 "MolFilePlugin: Internal error, selection size exceeds numatoms ("
01031 << numatoms << ")" << sendmsg;
01032 free(atoms);
01033 free(atomindexmap);
01034 return MOLFILE_ERROR;
01035 }
01036
01037 const MolAtom *atom = m->atom(i);
01038 molfile_atom_t &atm = atoms[j];
01039
01040 if (mangleatomnames) {
01041
01042
01043
01044 char name[6], *nameptr;
01045 name[0] = ' ';
01046 strncpy(name+1, (m->atomNames).name(atom->nameindex), 4);
01047 name[5] = '\0';
01048
01049 if(strlen(name) == 5) {
01050 nameptr = name + 1;
01051 } else {
01052 nameptr = name;
01053 int p;
01054 while((p = strlen(name)) < 4) {
01055 name[p] = ' ';
01056 name[p+1] = '\0';
01057 }
01058 }
01059 strcpy(atm.name, nameptr);
01060 } else {
01061 strncpy(atm.name, m->atomNames.name(atom->nameindex), sizeof(atm.name));
01062 }
01063
01064 strcpy(atm.type, m->atomTypes.name(atom->typeindex));
01065 strcpy(atm.resname, m->resNames.name(atom->resnameindex));
01066 atm.resid = atom->resid;
01067 strcpy(atm.chain, m->chainNames.name(atom->chainindex));
01068 strcpy(atm.segid, m->segNames.name(atom->segnameindex));
01069 strcpy(atm.insertion, atom->insertionstr);
01070 strcpy(atm.altloc, m->altlocNames.name(atom->altlocindex));
01071 atm.atomicnumber = atom->atomicnumber;
01072 atm.occupancy = occupancy[i];
01073 atm.bfactor = beta[i];
01074 atm.mass = mass[i];
01075 atm.charge = charge[i];
01076 atm.radius = radius[i];
01077
01078 atomindexmap[i] = j;
01079
01080 j++;
01081 }
01082
01083
01084 if (j != numatoms) {
01085 msgErr
01086 << "MolFilePlugin: Internal error, selection size (" << j
01087 << ") doesn't match numatoms (" << numatoms << ")" << sendmsg;
01088 free (atoms);
01089 return MOLFILE_ERROR;
01090 }
01091
01092
01093 int optflags = MOLFILE_NOOPTIONS;
01094
01095 if (m->test_dataset_flag(BaseMolecule::INSERTION))
01096 optflags |= MOLFILE_INSERTION;
01097
01098 if (m->test_dataset_flag(BaseMolecule::OCCUPANCY))
01099 optflags |= MOLFILE_OCCUPANCY;
01100
01101 if (m->test_dataset_flag(BaseMolecule::BFACTOR))
01102 optflags |= MOLFILE_BFACTOR;
01103
01104 if (m->test_dataset_flag(BaseMolecule::MASS))
01105 optflags |= MOLFILE_MASS;
01106
01107 if (m->test_dataset_flag(BaseMolecule::CHARGE))
01108 optflags |= MOLFILE_CHARGE;
01109
01110 if (m->test_dataset_flag(BaseMolecule::RADIUS))
01111 optflags |= MOLFILE_RADIUS;
01112
01113 if (m->test_dataset_flag(BaseMolecule::ALTLOC))
01114 optflags |= MOLFILE_ALTLOC;
01115
01116 if (m->test_dataset_flag(BaseMolecule::ATOMICNUMBER))
01117 optflags |= MOLFILE_ATOMICNUMBER;
01118
01119
01120
01121
01122
01123
01124
01125 if (can_write_bonds() &&
01126 (m->test_dataset_flag(BaseMolecule::BONDS) ||
01127 m->test_dataset_flag(BaseMolecule::BONDORDERS) ||
01128 m->test_dataset_flag(BaseMolecule::BONDTYPES))) {
01129 ResizeArray<int> bondfrom, bondto;
01130 ResizeArray<float> bondorder;
01131 ResizeArray<int> bondtype;
01132 ResizeArray<char *>bondtypename;
01133
01134 float *bondorderptr=NULL;
01135 int *bondtypeptr=NULL;
01136 char **bondtypenameptr=NULL;
01137 int numbondtypes=0;
01138
01139 for (i=0; i<m->nAtoms; i++) {
01140 const MolAtom *atom = m->atom(i);
01141 int bfmap = atomindexmap[i] + 1;
01142
01143 for (k=0; k<atom->bonds; k++) {
01144 int bto = atom->bondTo[k];
01145 int btmap = atomindexmap[bto] + 1;
01146
01147
01148 if (bfmap > 0 && btmap > bfmap) {
01149 bondfrom.append(bfmap);
01150 bondto.append(btmap);
01151 bondorder.append(m->getbondorder(i, k));
01152 bondtype.append(m->getbondtype(i, k));
01153 }
01154 }
01155 }
01156
01157
01158
01159 if (m->test_dataset_flag(BaseMolecule::BONDORDERS))
01160 bondorderptr=&bondorder[0];
01161 else
01162 bondorderptr=NULL;
01163
01164 numbondtypes = m->bondTypeNames.num();
01165 for (i=0; i < numbondtypes; i++) {
01166 bondtypename.append((char *)m->bondTypeNames.name(i));
01167 }
01168 if (numbondtypes > 0)
01169 bondtypenameptr = &bondtypename[0];
01170 else
01171 bondtypenameptr = NULL;
01172
01173
01174
01175 if (m->test_dataset_flag(BaseMolecule::BONDTYPES))
01176 bondtypeptr= &bondtype[0];
01177 else
01178 bondtypeptr=NULL;
01179
01180 #if vmdplugin_ABIVERSION >= 15
01181 if (plugin->write_bonds(wv, bondfrom.num(), &bondfrom[0], &bondto[0],
01182 bondorderptr, bondtypeptr,
01183 numbondtypes, bondtypenameptr)) {
01184 #else
01185 if (plugin->write_bonds(wv, bondfrom.num(), &bondfrom[0], &bondto[0],
01186 bondorderptr)) {
01187 #endif
01188 free(atoms);
01189 free(atomindexmap);
01190 return MOLFILE_ERROR;
01191 }
01192 }
01193
01194 #if vmdplugin_ABIVERSION > 9
01195
01196
01197
01198
01199 if (can_write_angles() && m->test_dataset_flag(BaseMolecule::ANGLES)) {
01200 ResizeArray<int> angles;
01201 ResizeArray<int> angleTypes;
01202 ResizeArray<const char *>angleTypeNames;
01203 ResizeArray<int> dihedrals;
01204 ResizeArray<int> dihedralTypes;
01205 ResizeArray<const char *>dihedralTypeNames;
01206 ResizeArray<int> impropers;
01207 ResizeArray<int> improperTypes;
01208 ResizeArray<const char *>improperTypeNames;
01209 ResizeArray<int> cterms;
01210
01211 int numangles = m->num_angles();
01212 int numdihedrals = m->num_dihedrals();
01213 int numimpropers = m->num_impropers();
01214
01215
01216 for (i=0; i<numangles; i++) {
01217 int idx0 = atomindexmap[m->angles[i*3 ]];
01218 int idx1 = atomindexmap[m->angles[i*3 + 1]];
01219 int idx2 = atomindexmap[m->angles[i*3 + 2]];
01220 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0)) {
01221 angles.append(idx0+1);
01222 angles.append(idx1+1);
01223 angles.append(idx2+1);
01224 #if vmdplugin_ABIVERSION >= 16
01225 if (m->test_dataset_flag(BaseMolecule::ANGLETYPES)) {
01226 angleTypes.append(m->get_angletype(i));
01227 }
01228 #endif
01229 }
01230 }
01231 for (i=0; i<numdihedrals; i++) {
01232 int idx0 = atomindexmap[m->dihedrals[i*4 ]];
01233 int idx1 = atomindexmap[m->dihedrals[i*4 + 1]];
01234 int idx2 = atomindexmap[m->dihedrals[i*4 + 2]];
01235 int idx3 = atomindexmap[m->dihedrals[i*4 + 3]];
01236 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0) && (idx3 >= 0)) {
01237 dihedrals.append(idx0+1);
01238 dihedrals.append(idx1+1);
01239 dihedrals.append(idx2+1);
01240 dihedrals.append(idx3+1);
01241 #if vmdplugin_ABIVERSION >= 16
01242 if (m->test_dataset_flag(BaseMolecule::ANGLETYPES)) {
01243 dihedralTypes.append(m->get_dihedraltype(i));
01244 }
01245 #endif
01246 }
01247 }
01248 for (i=0; i<numimpropers; i++) {
01249 int idx0 = atomindexmap[m->impropers[i*4 ]];
01250 int idx1 = atomindexmap[m->impropers[i*4 + 1]];
01251 int idx2 = atomindexmap[m->impropers[i*4 + 2]];
01252 int idx3 = atomindexmap[m->impropers[i*4 + 3]];
01253 if ((idx0 >= 0) && (idx1 >= 0) && (idx2 >= 0) && (idx3 >= 0)) {
01254 impropers.append(idx0+1);
01255 impropers.append(idx1+1);
01256 impropers.append(idx2+1);
01257 impropers.append(idx3+1);
01258 #if vmdplugin_ABIVERSION >= 16
01259 if (m->test_dataset_flag(BaseMolecule::ANGLETYPES)) {
01260 improperTypes.append(m->get_impropertype(i));
01261 }
01262 #endif
01263 }
01264 }
01265
01266 int ctermcnt=0;
01267 int *ctermlist=NULL;
01268 if (m->test_dataset_flag(BaseMolecule::CTERMS)) {
01269 int numcterms = m->num_cterms();
01270 for (i=0; i<numcterms; i++) {
01271 int goodcount=0;
01272 for (j=0; j<8; j++) {
01273 if (atomindexmap[m->cterms[i*8 + j]] >= 0)
01274 goodcount++;
01275 }
01276 if (goodcount == 8) {
01277 ctermcnt++;
01278 for (j=0; j<8; j++) {
01279
01280 cterms.append(atomindexmap[m->cterms[i*8 + j]]+1);
01281 }
01282 }
01283 }
01284 if (ctermcnt > 0)
01285 ctermlist = &cterms[0];
01286 }
01287
01288 #if vmdplugin_ABIVERSION >= 16
01289
01290 if (m->test_dataset_flag(BaseMolecule::ANGLETYPES)) {
01291 for (i=0; i < m->angleTypeNames.num(); i++)
01292 angleTypeNames.append(m->angleTypeNames.name(i));
01293 for (i=0; i < m->dihedralTypeNames.num(); i++)
01294 dihedralTypeNames.append(m->dihedralTypeNames.name(i));
01295 for (i=0; i < m->improperTypeNames.num(); i++)
01296 improperTypeNames.append(m->improperTypeNames.name(i));
01297 }
01298 #endif
01299
01300 int anglescnt = angles.num()/3;
01301 int *anglelist = (anglescnt > 0) ? &angles[0] : NULL;
01302 #if vmdplugin_ABIVERSION >= 16
01303 int *angletypelist = (angleTypes.num() > 0) ? &angleTypes[0] : NULL;
01304 int angletypecnt = angleTypeNames.num();
01305 const char **anglenmlist = (angletypecnt>0) ? &angleTypeNames[0] : NULL;
01306 #endif
01307
01308 int dihedralscnt = dihedrals.num()/4;
01309 int *dihedrallist = (dihedralscnt > 0) ? &dihedrals[0] : NULL;
01310 #if vmdplugin_ABIVERSION >= 16
01311 int *dihedraltypelist = (dihedralTypes.num() > 0) ? &dihedralTypes[0] : NULL;
01312 int dihedraltypecnt = dihedralTypeNames.num();
01313 const char **dihedralnmlist = (dihedraltypecnt>0) ? &dihedralTypeNames[0] : NULL;
01314 #endif
01315
01316 int improperscnt = impropers.num()/4;
01317 int *improperlist = (improperscnt > 0) ? &impropers[0] : NULL;
01318 #if vmdplugin_ABIVERSION >= 16
01319 int *impropertypelist = (improperTypes.num() > 0) ? &improperTypes[0] : NULL;
01320 int impropertypecnt = improperTypeNames.num();
01321 const char **impropernmlist = (impropertypecnt>0) ? &improperTypeNames[0] : NULL;
01322 if (plugin->write_angles(wv, anglescnt, anglelist, angletypelist, angletypecnt,
01323 anglenmlist, dihedralscnt, dihedrallist, dihedraltypelist,
01324 dihedraltypecnt, dihedralnmlist, improperscnt,
01325 improperlist, impropertypelist, impropertypecnt,
01326 impropernmlist, ctermcnt, ctermlist, 0, 0)) {
01327 free(atoms);
01328 free(atomindexmap);
01329 return MOLFILE_ERROR;
01330 }
01331 #else
01332 if (plugin->write_angles(wv, anglescnt, anglelist, NULL,
01333 dihedralscnt, dihedrallist, NULL,
01334 improperscnt, improperlist, NULL,
01335 ctermcnt, ctermlist, 0, 0, NULL)) {
01336 free(atoms);
01337 free(atomindexmap);
01338 return MOLFILE_ERROR;
01339 }
01340 #endif
01341 }
01342 #endif
01343
01344
01345 if (plugin->write_structure(wv, optflags, atoms)) {
01346 free(atoms);
01347 free(atomindexmap);
01348 return MOLFILE_ERROR;
01349 }
01350
01351 free(atoms);
01352 free(atomindexmap);
01353
01354 return MOLFILE_SUCCESS;
01355 }
01356
01357 int MolFilePlugin::write_timestep(const Timestep *ts, const int *on) {
01358
01359 if (!can_write_timesteps())
01360 return MOLFILE_SUCCESS;
01361
01362 molfile_timestep_t mol_ts;
01363 memset(&mol_ts, 0, sizeof(molfile_timestep_t));
01364 mol_ts.A = ts->a_length;
01365 mol_ts.B = ts->b_length;
01366 mol_ts.C = ts->c_length;
01367 mol_ts.alpha = ts->alpha;
01368 mol_ts.beta = ts->beta;
01369 mol_ts.gamma = ts->gamma;
01370 #if vmdplugin_ABIVERSION > 10
01371 mol_ts.physical_time = ts->physical_time;
01372 #endif
01373 if (!on) {
01374 mol_ts.coords = ts->pos;
01375 mol_ts.velocities = ts->vel;
01376 return plugin->write_timestep(wv, &mol_ts);
01377 }
01378 float *coords = new float[3*numatoms];
01379 float *vel = NULL;
01380 if (ts->vel) vel = new float[3*numatoms];
01381 int j=0;
01382 for (int i=0; i<ts->num; i++) {
01383 if (on[i]) {
01384 if (on && !on[i]) continue;
01385
01386 if (j >= 3*numatoms) {
01387 msgErr << "MolFilePlugin::write_timestep: Internal error" << sendmsg;
01388 msgErr << "Selection size exceeds numatoms (" << numatoms << ")"
01389 << sendmsg;
01390 delete [] coords;
01391 delete vel;
01392 return MOLFILE_ERROR;
01393 }
01394 coords[j ] = ts->pos[3*i];
01395 coords[j+1] = ts->pos[3*i+1];
01396 coords[j+2] = ts->pos[3*i+2];
01397 if (ts->vel) {
01398 vel[j ] = ts->vel[3*i ];
01399 vel[j+1] = ts->vel[3*i+1];
01400 vel[j+2] = ts->vel[3*i+2];
01401 }
01402 j += 3;
01403 }
01404 }
01405
01406 if (j != 3*numatoms) {
01407 msgErr << "MolFilePlugin::write_timestep: Internal error" << sendmsg;
01408 msgErr << "selection size (" << j << ") doesn't match numatoms ("
01409 << numatoms << ")" << sendmsg;
01410 delete [] coords;
01411 return MOLFILE_ERROR;
01412 }
01413 mol_ts.coords = coords;
01414 mol_ts.velocities = vel;
01415 int rc = plugin->write_timestep(wv, &mol_ts);
01416 delete [] coords;
01417 delete vel;
01418 return rc;
01419 }
01420
01421 int MolFilePlugin::read_rawgraphics(Molecule *m, Scene *sc) {
01422 if (!rv || !can_read_graphics()) return MOLFILE_ERROR;
01423 const molfile_graphics_t *graphics = NULL;
01424 int nelem = -1;
01425 if (plugin->read_rawgraphics(rv, &nelem, &graphics)) return MOLFILE_ERROR;
01426 msgInfo << "Reading " << nelem << " graphics elements..." << sendmsg;
01427 MoleculeGraphics *mg = m->moleculeGraphics();
01428 for (int i=0; i<nelem; i++) {
01429 const float *data = graphics[i].data;
01430 switch (graphics[i].type) {
01431 case MOLFILE_POINT:
01432 mg->add_point(data);
01433 break;
01434 case MOLFILE_TRIANGLE:
01435 mg->add_triangle(data, data+3, data+6);
01436 break;
01437 case MOLFILE_TRINORM:
01438 {
01439 const float *ndata;
01440
01441 if (i+1 >= nelem || graphics[i+1].type != MOLFILE_NORMS) {
01442 msgErr << "Invalid rawgraphics: NORMS must follow TRINORM."
01443 << sendmsg;
01444 return MOLFILE_ERROR;
01445 }
01446 ++i;
01447 ndata = graphics[i].data;
01448 mg->add_trinorm(data, data+3, data+6, ndata, ndata+3, ndata+6);
01449 }
01450 break;
01451 case MOLFILE_TRICOLOR:
01452 {
01453 const float *ndata, *cdata;
01454
01455 if (i+1 >= nelem || graphics[i+1].type != MOLFILE_NORMS) {
01456 msgErr << "Invalid rawgraphics: NORMS must follow TRINORM."
01457 << sendmsg;
01458 return MOLFILE_ERROR;
01459 }
01460 ++i;
01461 ndata = graphics[i].data;
01462
01463 if (i+1 >= nelem || graphics[i+1].type != MOLFILE_COLOR) {
01464 msgErr << "Invalid rawgraphics: NORMS and COLOR must fullow TRICOLOR."
01465 << sendmsg;
01466 return MOLFILE_ERROR;
01467 }
01468 ++i;
01469 cdata = graphics[i].data;
01470 mg->add_tricolor(data, data+3, data+6, ndata, ndata+3, ndata+6,
01471 sc->nearest_index(cdata[0], cdata[1], cdata[2]),
01472 sc->nearest_index(cdata[3], cdata[4], cdata[5]),
01473 sc->nearest_index(cdata[6], cdata[7], cdata[8]));
01474 }
01475 break;
01476 case MOLFILE_LINE:
01477 mg->add_line(data, data+3, graphics[i].style, (int)graphics[i].size);
01478 break;
01479 case MOLFILE_CYLINDER:
01480 mg->add_cylinder(data, data+3, graphics[i].size, graphics[i].style, 0);
01481 break;
01482 case MOLFILE_CAPCYL:
01483 mg->add_cylinder(data, data+3, graphics[i].size, graphics[i].style, 1);
01484 break;
01485 case MOLFILE_CONE:
01486 mg->add_cone(data, data+3, graphics[i].size, data[6], graphics[i].style);
01487 break;
01488 case MOLFILE_SPHERE:
01489 mg->add_sphere(data, graphics[i].size, graphics[i].style);
01490 break;
01491 case MOLFILE_TEXT:
01492 {
01493 char text[24];
01494 strncpy(text, (char *)data+3, 24);
01495 text[23] = '\0';
01496 mg->add_text(data, text, graphics[i].size, 1.0f);
01497 }
01498 break;
01499 case MOLFILE_COLOR:
01500 mg->use_color(sc->nearest_index(data[0], data[1], data[2]));
01501 break;
01502 case MOLFILE_NORMS:
01503 msgErr << "Invalid rawgraphics: NORMS must follow TRINORM." << sendmsg;
01504 return MOLFILE_ERROR;
01505 break;
01506 default:
01507 msgErr << "Invalid rawgraphics: unknown type " << graphics[i].type
01508 << sendmsg;
01509 }
01510 }
01511
01512 return MOLFILE_SUCCESS;
01513 }
01514
01515
01516 int MolFilePlugin::read_volumetric(Molecule *m, int nsets,
01517 const int *setids) {
01518
01519
01520 molfile_volumetric_t *metadata;
01521 int setsinfile = 0;
01522 plugin->read_volumetric_metadata(rv, &setsinfile, &metadata);
01523
01524
01525 int n;
01526 int *sets;
01527 if (nsets < 0) {
01528 n = setsinfile;
01529 sets = new int[n];
01530 for (int i=0; i<n; i++) sets[i] = i;
01531 } else {
01532 n = nsets;
01533 sets = new int [n];
01534 for (int i=0; i<n; i++) sets[i] = setids[i];
01535 }
01536
01537 for (int i=0; i< n; i++) {
01538 if (sets[i] < 0 || sets[i] >= setsinfile) {
01539 msgErr << "Bogus setid passed to read_volumetric: " << sets[i]
01540 << sendmsg;
01541 continue;
01542 }
01543 const molfile_volumetric_t *v = metadata+sets[i];
01544 float *datablock = NULL, *colorblock = NULL;
01545 size_t size = v->xsize * v->ysize * v->zsize;
01546 datablock = new float[size];
01547 if (v->has_color)
01548 colorblock = new float[3*size];
01549 if (plugin->read_volumetric_data(rv, sets[i], datablock, colorblock)) {
01550 msgErr << "Error reading volumetric data set " << sets[i]+1 << sendmsg;
01551 delete [] datablock;
01552 delete [] colorblock;
01553 continue;
01554 }
01555 char *dataname = stringdup(v->dataname);
01556 if (_filename) {
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 char sep =
01568 #ifdef WIN32
01569 '\\'
01570 #else
01571 '/'
01572 #endif
01573 ;
01574 const char *basename = strrchr(_filename, sep);
01575 if (!basename) {
01576 basename = _filename;
01577 } else {
01578 basename++;
01579 }
01580 char *tmp = new char[strlen(dataname)+5+strlen(basename)];
01581 sprintf(tmp, "%s : %s", basename, dataname);
01582 delete [] dataname;
01583 dataname = tmp;
01584 }
01585 m->add_volume_data(dataname, v->origin,
01586 v->xaxis, v->yaxis, v->zaxis, v->xsize, v->ysize, v->zsize,
01587 datablock);
01588 delete [] dataname;
01589 delete [] colorblock;
01590 }
01591 delete [] sets;
01592
01593 return MOLFILE_SUCCESS;
01594 }
01595
01596
01597 int MolFilePlugin::read_metadata(Molecule *m) {
01598
01599 molfile_metadata_t *metadata;
01600
01601 plugin->read_molecule_metadata(rv, &metadata);
01602
01603 m->record_database(metadata->database, metadata->accession);
01604 if (metadata->remarks != NULL)
01605 m->record_remarks(metadata->remarks);
01606 else
01607 m->record_remarks("");
01608
01609 return MOLFILE_SUCCESS;
01610 }
01611
01612
01613 #if vmdplugin_ABIVERSION > 9
01614 int MolFilePlugin::read_qm_data(Molecule *mol) {
01615
01616
01617
01618
01619 molfile_qm_metadata_t metadata;
01620
01621
01622
01623 if (plugin->read_qm_metadata(rv, &metadata) != MOLFILE_SUCCESS)
01624 return MOLFILE_ERROR;
01625
01626 #if vmdplugin_ABIVERSION > 11
01627
01628
01629
01630
01631
01632
01633
01634 if (!numatoms) numatoms = mol->nAtoms;
01635 mol->qm_data = new QMData(numatoms,
01636 metadata.num_basis_funcs,
01637 metadata.num_shells,
01638 metadata.wavef_size);
01639
01640
01641
01642
01643
01644 qm_data = mol->qm_data;
01645 #endif
01646
01647 molfile_qm_t *qmdata = (molfile_qm_t *) calloc(1, sizeof(molfile_qm_t));
01648
01649 #if vmdplugin_ABIVERSION > 11
01650
01651 if (metadata.num_basis_atoms) {
01652 qmdata->basis.num_shells_per_atom = new int[metadata.num_basis_atoms];
01653 qmdata->basis.atomic_number = new int[metadata.num_basis_atoms];
01654 qmdata->basis.num_prim_per_shell = new int[metadata.num_shells];
01655 qmdata->basis.basis = new float[2*metadata.num_basis_funcs];
01656 qmdata->basis.shell_types = new int[metadata.num_shells];
01657 qmdata->basis.angular_momentum = new int[3*metadata.wavef_size];
01658 }
01659
01660 if (metadata.nimag)
01661 qmdata->hess.imag_modes = new int[metadata.nimag];
01662
01663 if (metadata.have_normalmodes) {
01664 qmdata->hess.normalmodes = new float[metadata.ncart*metadata.ncart];
01665 qmdata->hess.wavenumbers = new float[metadata.ncart];
01666 qmdata->hess.intensities = new float[metadata.ncart];
01667 }
01668
01669 if (metadata.have_carthessian)
01670 qmdata->hess.carthessian = new double[metadata.ncart*metadata.ncart];
01671
01672 if (metadata.have_inthessian)
01673 qmdata->hess.inthessian = new double[metadata.nintcoords*metadata.nintcoords];
01674
01675
01676
01677
01678
01679
01680 #endif
01681
01682
01683
01684 plugin->read_qm_rundata(rv, qmdata);
01685
01686 #if vmdplugin_ABIVERSION > 11
01687
01688
01689 if (metadata.have_sysinfo) {
01690
01691
01692 mol->qm_data->nproc = qmdata->run.nproc;
01693 #if vmdplugin_ABIVERSION > 12
01694 mol->qm_data->memory = qmdata->run.memory;
01695 #else
01696 mol->qm_data->memory = 0;
01697 #endif
01698
01699
01700
01701
01702
01703 switch (qmdata->run.scftype) {
01704 case MOLFILE_SCFTYPE_NONE:
01705 mol->qm_data->scftype = SCFTYPE_NONE;
01706 break;
01707 case MOLFILE_SCFTYPE_RHF:
01708 mol->qm_data->scftype = SCFTYPE_RHF;
01709 break;
01710 case MOLFILE_SCFTYPE_UHF:
01711 mol->qm_data->scftype = SCFTYPE_UHF;
01712 break;
01713 case MOLFILE_SCFTYPE_ROHF:
01714 mol->qm_data->scftype = SCFTYPE_ROHF;
01715 break;
01716 case MOLFILE_SCFTYPE_GVB:
01717 mol->qm_data->scftype = SCFTYPE_GVB;
01718 break;
01719 case MOLFILE_SCFTYPE_MCSCF:
01720 mol->qm_data->scftype = SCFTYPE_MCSCF;
01721 break;
01722 case MOLFILE_SCFTYPE_FF:
01723 mol->qm_data->scftype = SCFTYPE_FF;
01724 break;
01725 default:
01726 mol->qm_data->scftype = SCFTYPE_UNKNOWN;
01727 }
01728
01729 switch (qmdata->run.runtype) {
01730 case MOLFILE_RUNTYPE_ENERGY:
01731 mol->qm_data->runtype = RUNTYPE_ENERGY;
01732 break;
01733 case MOLFILE_RUNTYPE_OPTIMIZE:
01734 mol->qm_data->runtype = RUNTYPE_OPTIMIZE;
01735 break;
01736 case MOLFILE_RUNTYPE_SADPOINT:
01737 mol->qm_data->runtype = RUNTYPE_SADPOINT;
01738 break;
01739 case MOLFILE_RUNTYPE_HESSIAN:
01740 mol->qm_data->runtype = RUNTYPE_HESSIAN;
01741 break;
01742 case MOLFILE_RUNTYPE_SURFACE:
01743 mol->qm_data->runtype = RUNTYPE_SURFACE;
01744 break;
01745 case MOLFILE_RUNTYPE_GRADIENT:
01746 mol->qm_data->runtype = RUNTYPE_GRADIENT;
01747 break;
01748 case MOLFILE_RUNTYPE_MEX:
01749 mol->qm_data->runtype = RUNTYPE_MEX;
01750 break;
01751 case MOLFILE_RUNTYPE_DYNAMICS:
01752 mol->qm_data->runtype = RUNTYPE_DYNAMICS;
01753 break;
01754 case MOLFILE_RUNTYPE_PROPERTIES:
01755 mol->qm_data->runtype = RUNTYPE_PROPERTIES;
01756 break;
01757 default:
01758 mol->qm_data->runtype = RUNTYPE_UNKNOWN;
01759 }
01760
01761 switch (qmdata->run.status) {
01762 case MOLFILE_QMSTATUS_OPT_CONV:
01763 mol->qm_data->status = QMSTATUS_OPT_CONV;
01764 break;
01765 case MOLFILE_QMSTATUS_OPT_NOT_CONV:
01766 mol->qm_data->status = QMSTATUS_OPT_NOT_CONV;
01767 break;
01768 case MOLFILE_QMSTATUS_SCF_NOT_CONV:
01769 mol->qm_data->status = QMSTATUS_SCF_NOT_CONV;
01770 break;
01771 case MOLFILE_QMSTATUS_FILE_TRUNCATED:
01772 mol->qm_data->status = QMSTATUS_FILE_TRUNCATED;
01773 break;
01774 default:
01775 mol->qm_data->status = QMSTATUS_UNKNOWN;
01776 }
01777
01778
01779 SAFESTRNCPY(mol->qm_data->version_string, qmdata->run.version_string);
01780 SAFESTRNCPY(mol->qm_data->runtitle, qmdata->run.runtitle);
01781 SAFESTRNCPY(mol->qm_data->geometry, qmdata->run.geometry);
01782 }
01783
01784 if (metadata.have_sysinfo) {
01785
01786
01787
01788
01789 mol->qm_data->init_electrons(mol, qmdata->run.totalcharge);
01790 }
01791
01792
01793
01794 if (!mol->qm_data->init_basis(mol, metadata.num_basis_atoms,
01795 qmdata->run.basis_string,
01796 qmdata->basis.basis,
01797 qmdata->basis.atomic_number,
01798 qmdata->basis.num_shells_per_atom,
01799 qmdata->basis.num_prim_per_shell,
01800 qmdata->basis.shell_types)) {
01801 msgWarn << "Incomplete basis set info in QM data."
01802 << sendmsg;
01803 }
01804
01805
01806 if (metadata.wavef_size) {
01807 mol->qm_data->set_angular_momenta(qmdata->basis.angular_momentum);
01808 }
01809
01810
01811
01812 if (metadata.have_carthessian) {
01813 mol->qm_data->set_carthessian(metadata.ncart, qmdata->hess.carthessian);
01814 }
01815
01816 if (metadata.have_inthessian) {
01817 mol->qm_data->set_inthessian(metadata.nintcoords, qmdata->hess.inthessian);
01818 }
01819
01820 if (metadata.have_normalmodes) {
01821 mol->qm_data->set_normalmodes(metadata.ncart, qmdata->hess.normalmodes);
01822 mol->qm_data->set_wavenumbers(metadata.ncart, qmdata->hess.wavenumbers);
01823 mol->qm_data->set_intensities(metadata.ncart, qmdata->hess.intensities);
01824 }
01825
01826 if (metadata.nimag) {
01827 mol->qm_data->set_imagmodes(metadata.nimag, qmdata->hess.imag_modes);
01828 }
01829
01830
01831 if (metadata.num_basis_atoms) {
01832 delete [] qmdata->basis.num_shells_per_atom;
01833 delete [] qmdata->basis.atomic_number;
01834 delete [] qmdata->basis.num_prim_per_shell;
01835 delete [] qmdata->basis.basis;
01836 delete [] qmdata->basis.shell_types;
01837 delete [] qmdata->basis.angular_momentum;
01838 }
01839 delete [] qmdata->hess.carthessian;
01840 delete [] qmdata->hess.inthessian;
01841 delete [] qmdata->hess.normalmodes;
01842 delete [] qmdata->hess.wavenumbers;
01843 delete [] qmdata->hess.intensities;
01844 delete [] qmdata->hess.imag_modes;
01845 free(qmdata);
01846 #endif
01847
01848 return MOLFILE_SUCCESS;
01849 }
01850
01851
01852 int MolFilePlugin::write_volumetric(Molecule *m, int set) {
01853 if (set < 0 || set > m->num_volume_data()) {
01854 msgErr << "Bogus setid passed to write_volumetric: " << set
01855 << sendmsg;
01856 return MOLFILE_SUCCESS;
01857 }
01858
01859 const VolumetricData *v = m->get_volume_data(set);
01860
01861 molfile_volumetric_t volmeta;
01862
01863
01864 int n = ((sizeof(volmeta.dataname) < strlen(v->name)+1) ?
01865 sizeof(volmeta.dataname) : strlen(v->name)+1);
01866 strncpy(volmeta.dataname, v->name, n);
01867
01868 for (int i=0; i<3; i++) {
01869 volmeta.origin[i] = (float)v->origin[i];
01870 volmeta.xaxis[i] = (float)v->xaxis[i];
01871 volmeta.yaxis[i] = (float)v->yaxis[i];
01872 volmeta.zaxis[i] = (float)v->zaxis[i];
01873 }
01874 volmeta.xsize = v->xsize;
01875 volmeta.ysize = v->ysize;
01876 volmeta.zsize = v->zsize;
01877 volmeta.has_color = 0;
01878
01879 float *datablock = v->data;
01880 float *colorblock = NULL;
01881
01882 plugin->write_volumetric_data(wv, &volmeta, datablock, colorblock);
01883
01884 return MOLFILE_SUCCESS;
01885 }
01886 #endif
01887