00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: BaseMolecule.h,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.151 $ $Date: 2020年10月28日 15:09:56 $ 00015 * 00016 ***************************************************************************/ 00027 #ifndef BASEMOLECULE_H 00028 #define BASEMOLECULE_H 00029 00030 #ifndef NAMELIST_TEMPLATE_H 00031 #include "NameList.h" 00032 #endif 00033 #ifndef RESIZEARRAY_TEMPLATE_H 00034 #include "ResizeArray.h" 00035 #endif 00036 #include "Atom.h" 00037 #include "Residue.h" 00038 #include "Timestep.h" 00039 #include "Fragment.h" 00040 #include "Matrix4.h" 00041 #include "intstack.h" 00042 00043 #ifdef VMDWITHCARBS 00044 #include "SmallRing.h" 00045 #include "SmallRingLinkages.h" 00046 #include "inthash.h" 00047 #endif 00048 00049 #if 0 00050 #define VMDFASTRIBBONS 00051 #endif 00052 00053 class VolumetricData; 00054 class QMData; 00055 00061 class BaseMolecule { 00062 public: 00063 // 00064 // public molecular structure data (for ease of access): 00065 // 00066 int nAtoms; 00067 int nResidues; 00068 int nWaters; 00069 int nSegments; 00070 int nFragments; 00071 int nProteinFragments; 00072 int nNucleicFragments; 00073 00074 NameList<int> atomNames; 00075 NameList<int> atomTypes; 00076 NameList<int> resNames; 00077 NameList<int> chainNames; 00078 NameList<int> segNames; 00079 NameList<int> altlocNames; 00080 00081 ResizeArray<Residue *> residueList; 00082 ResizeArray<Fragment *> fragList; 00083 00084 ResizeArray<Fragment *> pfragList; 00085 00086 ResizeArray<int> pfragCyclic; 00087 #if defined(VMDFASTRIBBONS) 00088 ResizeArray<int *> pfragCPList; 00089 00090 #endif 00091 00092 00093 ResizeArray<Fragment *> nfragList; 00094 ResizeArray<int> nfragCyclic; 00095 #if defined(VMDFASTRIBBONS) 00096 ResizeArray<int *> nfragCPList; 00097 00098 #endif 00099 00100 #ifdef VMDWITHCARBS 00101 ResizeArray<SmallRing *> smallringList; 00102 00103 SmallRingLinkages smallringLinkages; 00104 int currentMaxRingSize; 00105 int currentMaxPathLength; 00106 #endif 00107 00108 // Molecule instance transformation matrices, not including self 00109 ResizeArray<Matrix4> instances; 00110 00111 // Extra molecular dynamics structure info not normally needed for 00112 // anything but structure building tasks 00113 ResizeArray<int> angles; 00114 ResizeArray<int> dihedrals; 00115 ResizeArray<int> impropers; 00116 ResizeArray<int> cterms; 00117 00118 // Extra (optional) data for this molecule. 00119 // If the name is unassigned then the values can be taken to be zero. 00120 NameList<float *> extraflt; 00121 NameList<int *> extraint; 00122 NameList<unsigned char *> extraflg; 00123 00124 // more structure topology handling info. assign names to FF types. 00125 ResizeArray<int> angleTypes; 00126 ResizeArray<int> dihedralTypes; 00127 ResizeArray<int> improperTypes; 00128 NameList<int> bondTypeNames; 00129 NameList<int> angleTypeNames; 00130 NameList<int> dihedralTypeNames; 00131 NameList<int> improperTypeNames; 00132 00133 // Data related to quantum mechanics simulations. 00134 QMData *qm_data; 00135 00136 // Interface to standard extra data. These will exist and be initialized 00137 // to zero when init_atoms is called. 00138 00140 enum dataset_flag { 00141 NODATA=0x0000, 00142 INSERTION=0x0001, 00143 OCCUPANCY=0x0002, 00144 BFACTOR=0x0004, 00145 MASS=0x0008, 00146 CHARGE=0x0010, 00147 RADIUS=0x0020, 00148 ALTLOC=0x0040, 00149 ATOMICNUMBER=0x0080, 00150 BONDS=0x0100, 00151 BONDORDERS=0x0200, 00152 ANGLES=0x0400, 00153 CTERMS=0x0800, 00154 BONDTYPES=0x1000, 00155 ANGLETYPES=0x2000, 00156 ATOMFLAGS=0x4000 }; 00157 00158 int datasetflags; 00159 void set_dataset_flag(int flag) { 00160 datasetflags |= flag; 00161 } 00162 void unset_dataset_flag(int flag) { 00163 datasetflags &= (~flag); 00164 } 00165 int test_dataset_flag(int flag) { 00166 return (datasetflags & flag) != 0; 00167 } 00168 00170 float *radius() { return extraflt.data("radius"); } 00171 float *mass() { return extraflt.data("mass"); } 00172 float *charge() { return extraflt.data("charge"); } 00173 float *beta() { return extraflt.data("beta"); } 00174 float *occupancy() { return extraflt.data("occupancy"); } 00175 00176 // per-atom flags array 00177 unsigned char *flags() { return extraflg.data("flags"); } 00178 00181 int radii_minmax_need_update; 00182 float radii_min; 00183 float radii_max; 00184 void set_radii_changed() { radii_minmax_need_update = 1; } 00185 00186 void get_radii_minmax(float &min, float &max) { 00187 const float *r = NULL; 00188 if (radii_minmax_need_update && nAtoms > 0 && 00189 (r = extraflt.data("radius")) != NULL) { 00190 00191 #if 1 00192 // use fast 16-byte-aligned min/max routine 00193 minmax_1fv_aligned(r, nAtoms, &radii_min, &radii_max); 00194 #else 00195 // scalar min/max loop 00196 radii_min = r[0]; 00197 radii_max = r[0]; 00198 for (int i=0; i<nAtoms; i++) { 00199 if (r[i] < radii_min) radii_min = r[i]; 00200 if (r[i] > radii_max) radii_max = r[i]; 00201 } 00202 #endif 00203 radii_minmax_need_update = 0; 00204 } 00205 00206 min = radii_min; 00207 max = radii_max; 00208 } 00209 00211 float *bondorders() { return extraflt.data("bondorders"); } 00212 void setbondorder(int atom, int bond, float order); 00213 float getbondorder(int atom, int bond); 00214 00216 int *bondtypes() { return extraint.data("bondtypes"); } 00217 00219 void setbondtype(int atom, int bond, int type); 00220 00222 int getbondtype(int atom, int bond); 00223 00225 int has_structure() const { return cur_atom > 0; } 00226 00228 void clear_bonds(void); 00229 00231 int count_bonds(void); 00232 00233 #ifdef VMDWITHCARBS 00234 00235 void find_small_rings_and_links(int maxpathlength, int maxringsize); 00236 #endif 00237 00238 private: 00239 const int ID; 00240 00241 // 00242 // molecular structure data: 00243 // 00244 int cur_atom; 00245 MolAtom *atomList; 00246 int lastbonderratomid; 00247 int bonderrorcount; 00248 00249 // 00250 // routines to determine components of molecular structure 00251 // 00252 00260 int find_backbone(void); 00261 00262 // find the residues in the molecule; return number found. 00263 // I look for atoms with the same resid connected to 00264 // backbone atoms with the same resid (find enough backbone 00265 // atoms, then find atoms connected to them) 00266 int find_connected_backbone(IntStackHandle, int, int, int, int, int *); 00267 void clean_up_connection(IntStackHandle, int, int, int *); 00268 void find_connected_atoms_in_resid(IntStackHandle, int, int, 00269 int, int, int *); 00270 void find_and_mark(IntStackHandle, int, int, int, int *, int *); 00271 int make_uniq_resids(int *flgs); 00272 00279 int find_residues(void); 00280 00282 // This should take place after find_residues to keep 00283 // from mistaking a protein resname as a water resname, maybe 00284 void find_connected_waters(int i, char *tmp); 00285 int find_connected_waters2(void); 00286 00291 int find_waters(void); 00292 00298 void find_connected_residues(int num_residues); 00299 00301 int find_segments(void) { return segNames.num(); } 00302 00304 int find_connected_fragments(); 00305 00312 int find_fragments(void); 00313 00314 void find_subfragments_cyclic(ResizeArray<Fragment *> *subfragList, int restype); 00315 void find_cyclic_subfragments(ResizeArray<Fragment *> *subfragList, ResizeArray<int> *subfragCyclic); 00316 00318 void find_connected_subfragment(int resnum, int fragnum, char *flgs, 00319 int endatom, int altendatom, int alt2endatom, int alt3endatom, 00320 int restype, 00321 ResizeArray<Fragment *> *subfragList); 00322 00323 void find_subfragments(int startatom, int altstartatom, int alt2startatom, 00324 int endatom, int altendatom, int alt2endatom, int alt3endatom, 00325 int restype, ResizeArray<Fragment *> *subfragList); 00326 00327 void find_subfragments_topologically(int restype, ResizeArray<Fragment *> *subfragList, int endatom, int altendatom, int alt2endatom, int alt3endatom); 00328 00329 #if defined(VMDFASTRIBBONS) 00332 void calculate_ribbon_controlpoints(); 00333 #endif 00334 00335 #ifdef VMDWITHCARBS 00336 00337 int find_small_rings(int maxringsize); 00338 int find_back_edges(ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest); 00339 int find_connected_subgraph_back_edges(int atomid, ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest, 00340 int *intree_parents); 00341 int find_small_rings_from_back_edges(int maxringsize, ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest); 00342 int find_small_rings_from_partial(SmallRing *ring, int maxringsize, inthash_t *used_edges, inthash_t *used_atoms); 00343 int get_edge_key(int edge_src, int edge_dest); 00344 00345 // orientate small rings 00346 void orientate_small_rings(int maxringsize); 00347 void orientate_small_ring(SmallRing &ring,int maxringsize); 00348 00349 // find links between small rings 00350 int find_orientated_small_ring_linkages(int maxpathlength,int maxringsize); 00351 int find_linkages_for_ring_from_partial(LinkagePath &lp, int maxpathlength, inthash_t *atom_to_ring, inthash_t *multi_ring_atoms, inthash_t *used_atoms); 00352 #endif 00353 00354 00355 protected: 00356 char *moleculename; 00357 int need_find_bonds; 00358 00359 public: 00360 // constructor; just sets most things to null. Derived classes must put 00361 // in structure in 'create' routine. Typical sequence of creating a 00362 // molecule should be: 00363 // mol = new Molecule(....) 00364 // ( specify parameters for creation ) 00365 // mol->create(); ... return success 00366 // mol->analyze(); ... find information about the structure 00367 BaseMolecule(int); 00368 virtual ~BaseMolecule(void); 00369 00370 // 00371 // routines to develop molecular structure 00372 // 00373 00376 int init_atoms(int n); 00377 00379 void find_bonds_from_timestep() { need_find_bonds = 1; } 00380 void find_unique_bonds_from_timestep() { need_find_bonds = 2; } 00381 00383 int add_atoms(int natoms, 00384 const char *name, const char *type, int atomicnumber, 00385 const char *resname, int resid, 00386 const char *chainid, const char *segname, 00387 const char *insertion = (char *) " ", 00388 const char *altloc = ""); 00389 00391 int add_bond(int, int, float, int, int = ATOMNORMAL); 00392 00394 int add_bond_dupcheck(int, int, float, int); 00395 00397 void clear_angles(void) { angles.clear(); angleTypes.clear(); } 00398 00400 int num_angles() { return int(angles.num() / 3); } 00401 00404 int add_angle(int a, int b, int c, int type=-1); 00405 00407 int set_angletype(int a, int type); 00408 00410 int get_angletype(int a); 00411 00413 void clear_dihedrals(void) { dihedrals.clear(); dihedralTypes.clear(); } 00414 00416 int num_dihedrals() { return int(dihedrals.num() / 4); } 00417 00420 int add_dihedral(int a, int b, int c, int d, int type=-1); 00421 00423 int set_dihedraltype(int d, int type); 00424 00426 int get_dihedraltype(int d); 00427 00429 void clear_impropers(void) { impropers.clear(); improperTypes.clear(); } 00430 00432 int num_impropers() { return int(impropers.num() / 4); } 00433 00436 int add_improper(int a, int b, int c, int d, int type=-1); 00437 00439 int set_impropertype(int i, int type); 00441 int get_impropertype(int i); 00442 00444 void clear_cterms() {cterms.clear();} 00445 00447 int num_cterms() { return int(cterms.num() / 8); } 00448 00450 void add_cterm(int a, int b, int c, int d, 00451 int e, int f, int g, int h) { 00452 cterms.append(a); cterms.append(b); cterms.append(c); cterms.append(d); 00453 cterms.append(e); cterms.append(f); cterms.append(g); cterms.append(h); 00454 } 00455 00457 // (By this time, the molecule is on the MoleculeList!) 00458 void analyze(void); 00459 00460 // 00461 // interfaces to add/query/delete instance transformation matrices 00462 // 00463 void add_instance(Matrix4 & inst) { instances.append(inst); } 00464 int num_instances(void) { return int(instances.num()); } 00465 void clear_instances(void) { instances.clear(); } 00466 00467 00468 // 00469 // query info about the molecule 00470 // 00471 int id(void) const { return ID; } 00472 const char *molname() const {return moleculename; } 00473 00474 // Return the Nth atom, residue, and fragment. All assume correct index 00475 // and that the structure has been initialized (for speed). 00476 MolAtom *atom(int n) { return atomList+n; } 00477 Residue *residue(int); 00478 Fragment *fragment(int); 00479 00480 // return the residue or fragment in which the given atom is located. 00481 Residue *atom_residue(int); 00482 Fragment *atom_fragment(int); 00483 00485 00486 int find_atom_in_residue(int atomnameindex, int residue) { 00487 const ResizeArray<int> &atoms = residueList[residue]->atoms; 00488 int num = int(atoms.num()); 00489 for (int i=0; i<num; i++) { 00490 if (atom(atoms[i])->nameindex == atomnameindex) return atoms[i]; 00491 } 00492 return -3; 00493 } 00494 00495 int find_atom_in_residue(const char *atomname, int residue); 00497 00499 00500 float default_charge(const char *); 00501 float default_mass(const char *); 00502 float default_radius(const char *); 00503 float default_occup(void) { return 1.0; } 00504 float default_beta(void) { return 0.0; } 00506 00508 void add_volume_data(const char *name, const float *o, 00509 const float *xa, const float *ya, const float *za, int x, int y, int z, 00510 float *voldata, float *gradient=NULL, float *variance=NULL); 00511 00512 void add_volume_data(const char *name, const double *o, 00513 const double *xa, const double *ya, const double *za, int x, int y, int z, 00514 float *voldata); 00515 00517 void remove_volume_data(int idx); 00518 00519 int num_volume_data(); 00520 const VolumetricData *get_volume_data(int); 00521 VolumetricData *modify_volume_data(int); 00522 void compute_volume_gradient(VolumetricData *); 00523 00524 protected: 00525 ResizeArray<VolumetricData *> volumeList; 00526 }; 00527 00528 // Hydrogen atom name detection macro 00529 #define IS_HYDROGEN(s) (s[0] == 'H' || (isdigit(s[0]) && s[1] == 'H' )) 00530 00531 #endif 00532