ObjectMolecule2.cpp (pymol-v1.8.6.0.tar.bz2) | : | ObjectMolecule2.cpp (pymol-v2.1.0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 2801 | skipping to change at line 2801 | |||
p = ncopy(cc, p, 2); | p = ncopy(cc, p, 2); | |||
if(!sscanf(cc, "%s", ai->elem)) | if(!sscanf(cc, "%s", ai->elem)) | |||
ai->elem[0] = 0; | ai->elem[0] = 0; | |||
else if(!((((ai->elem[0] >= 'a') && (ai->elem[0] <= 'z')) || /* don't get confused by PDB misuse */ | else if(!((((ai->elem[0] >= 'a') && (ai->elem[0] <= 'z')) || /* don't get confused by PDB misuse */ | |||
((ai->elem[0] >= 'A') && (ai->elem[0] <= 'Z'))) && | ((ai->elem[0] >= 'A') && (ai->elem[0] <= 'Z'))) && | |||
(((ai->elem[1] == 0) || | (((ai->elem[1] == 0) || | |||
((ai->elem[1] >= 'a') && (ai->elem[1] <= 'z')) || | ((ai->elem[1] >= 'a') && (ai->elem[1] <= 'z')) || | |||
((ai->elem[1] >= 'A') && (ai->elem[1] <= 'Z')))))) | ((ai->elem[1] >= 'A') && (ai->elem[1] <= 'Z')))))) | |||
ai->elem[0] = 0; | ai->elem[0] = 0; | |||
else if (info->variant == PDB_VARIANT_PDBQT) { | ||||
if (strcmp(ai->elem, "A") == 0) { | ||||
// aromatic carbon | ||||
ai->elem[0] = 'C'; | ||||
} else if (isupper(ai->elem[1])) { | ||||
// h-bond donor or acceptor | ||||
ai->elem[1] = 0; | ||||
} | ||||
} | ||||
if(!ai->elem[0]) { | if(!ai->elem[0]) { | |||
if(((literal_name[0] == ' ') || ((literal_name[0] >= '0') && (literal_ name[0] <= '9'))) && (literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) { /* infer element from name column */ | if(((literal_name[0] == ' ') || ((literal_name[0] >= '0') && (literal_ name[0] <= '9'))) && (literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) { /* infer element from name column */ | |||
ai->elem[0] = literal_name[1]; | ai->elem[0] = literal_name[1]; | |||
ai->elem[1] = 0; | ai->elem[1] = 0; | |||
} else if(((literal_name[0] >= 'A') && (literal_name[0] <= 'Z')) && (( (literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) || ((literal_name[1] >= 'a ') && (literal_name[1] <= 'z')))) { /* infer element from name column */ | } else if(((literal_name[0] >= 'A') && (literal_name[0] <= 'Z')) && (( (literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) || ((literal_name[1] >= 'a ') && (literal_name[1] <= 'z')))) { /* infer element from name column */ | |||
ai->elem[0] = literal_name[0]; | ai->elem[0] = literal_name[0]; | |||
ai->elem[2] = 0; | ai->elem[2] = 0; | |||
if((literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) { /* secon d letter is capitalized */ | if((literal_name[1] >= 'A') && (literal_name[1] <= 'Z')) { /* secon d letter is capitalized */ | |||
if(bogus_name_alignment) { | if(bogus_name_alignment) { | |||
skipping to change at line 3875 | skipping to change at line 3884 | |||
PyList_SetItem(result, 8, PyInt_FromLong(I->DiscreteFlag)); | PyList_SetItem(result, 8, PyInt_FromLong(I->DiscreteFlag)); | |||
PyList_SetItem(result, 9, PyInt_FromLong(I->DiscreteFlag ? I->NAtom : 0 /* NDi screte */)); | PyList_SetItem(result, 9, PyInt_FromLong(I->DiscreteFlag ? I->NAtom : 0 /* NDi screte */)); | |||
PyList_SetItem(result, 10, SymmetryAsPyList(I->Symmetry)); | PyList_SetItem(result, 10, SymmetryAsPyList(I->Symmetry)); | |||
PyList_SetItem(result, 11, PyInt_FromLong(I->CurCSet)); | PyList_SetItem(result, 11, PyInt_FromLong(I->CurCSet)); | |||
PyList_SetItem(result, 12, PyInt_FromLong(I->BondCounter)); | PyList_SetItem(result, 12, PyInt_FromLong(I->BondCounter)); | |||
PyList_SetItem(result, 13, PyInt_FromLong(I->AtomCounter)); | PyList_SetItem(result, 13, PyInt_FromLong(I->AtomCounter)); | |||
float pse_export_version = SettingGetGlobal_f(I->Obj.G, cSetting_pse_export_ve rsion); | float pse_export_version = SettingGetGlobal_f(I->Obj.G, cSetting_pse_export_ve rsion); | |||
if(I->DiscreteFlag | if(I->DiscreteFlag | |||
&& !SettingGetGlobal_b(I->Obj.G, cSetting_pse_binary_dump) | && (pse_export_version || !SettingGetGlobal_b(I->Obj.G, cSetting_pse_binar y_dump)) | |||
&& pse_export_version < 1.7699) { | && pse_export_version < 1.7699) { | |||
int *dcs; | int *dcs; | |||
int a; | int a; | |||
CoordSet *cs; | CoordSet *cs; | |||
/* get coordinate set indices */ | /* get coordinate set indices */ | |||
for(a = 0; a < I->NCSet; a++) { | for(a = 0; a < I->NCSet; a++) { | |||
cs = I->CSet[a]; | cs = I->CSet[a]; | |||
if(cs) { | if(cs) { | |||
skipping to change at line 3912 | skipping to change at line 3921 | |||
FreeP(dcs); | FreeP(dcs); | |||
} else { | } else { | |||
PyList_SetItem(result, 14, PConvAutoNone(NULL)); | PyList_SetItem(result, 14, PConvAutoNone(NULL)); | |||
PyList_SetItem(result, 15, PConvAutoNone(NULL)); | PyList_SetItem(result, 15, PConvAutoNone(NULL)); | |||
} | } | |||
return (PConvAutoNone(result)); | return (PConvAutoNone(result)); | |||
} | } | |||
/*========================================================================*/ | /*========================================================================*/ | |||
static | ||||
float connect_cutoff_adjustment( | ||||
const AtomInfoType * ai1, | ||||
const AtomInfoType * ai2) | ||||
{ | ||||
if (ai1->isHydrogen() || ai2->isHydrogen()) | ||||
return -0.2f; | ||||
if (ai1->protons == cAN_S || ai2->protons == cAN_S) | ||||
return 0.2f; | ||||
return 0.f; | ||||
} | ||||
/* | ||||
* True if two atoms should be bonded | ||||
*/ | ||||
static | ||||
bool is_distance_bonded( | ||||
PyMOLGlobals * G, | ||||
const CoordSet * cs, | ||||
const AtomInfoType * ai1, | ||||
const AtomInfoType * ai2, | ||||
const float * v1, | ||||
const float * v2, | ||||
float cutoff, | ||||
int connect_mode, | ||||
int discrete_chains, | ||||
bool connect_bonded, | ||||
bool unbond_cations) | ||||
{ | ||||
auto dst = (float) diff3f(v1, v2); | ||||
dst -= (ai1->vdw + ai2->vdw) / 2; | ||||
cutoff += connect_cutoff_adjustment(ai1, ai2); | ||||
if (dst > cutoff) | ||||
return false; | ||||
if (ai1->isHydrogen() && ai2->isHydrogen()) | ||||
return false; | ||||
if (discrete_chains > 0 && ai1->chain != ai2->chain) | ||||
return false; | ||||
if (!connect_bonded && ai1->bonded && ai2->bonded) | ||||
return false; | ||||
bool water_flag = ( | ||||
AtomInfoKnownWaterResName(G, LexStr(G, ai1->resn)) || | ||||
AtomInfoKnownWaterResName(G, LexStr(G, ai2->resn))); | ||||
if (connect_mode != 3 && | ||||
cs->TmpBond && /* connectivity information present in file */ | ||||
ai1->hetatm && | ||||
ai2->hetatm && | ||||
!water_flag && | ||||
!(AtomInfoKnownPolymerResName(LexStr(G, ai1->resn)) && | ||||
AtomInfoKnownPolymerResName(LexStr(G, ai2->resn)))) | ||||
return false; | ||||
// don't connect water atoms in different residues | ||||
if (water_flag && !AtomInfoSameResidue(G, ai1, ai2)) | ||||
return false; | ||||
// don't connect atoms with different, non-NULL alternate conformations | ||||
if (ai1->alt[0] != ai2->alt[0] && ai1->alt[0] && ai2->alt[0]) | ||||
return false; | ||||
// if either is a cation, unbond is user wants | ||||
if (unbond_cations && | ||||
(AtomInfoIsFreeCation(G, ai1) || | ||||
AtomInfoIsFreeCation(G, ai2))) | ||||
return false; | ||||
return true; | ||||
} | ||||
/*========================================================================*/ | ||||
int ObjectMoleculeConnect(ObjectMolecule * I, int *nbond, BondType ** bond, Atom InfoType * ai, | int ObjectMoleculeConnect(ObjectMolecule * I, int *nbond, BondType ** bond, Atom InfoType * ai, | |||
struct CoordSet *cs, int bondSearchMode, | struct CoordSet *cs, int bondSearchMode, | |||
int connectModeOverride) | int connectModeOverride) | |||
{ | { | |||
#define cMULT 1 | #define cMULT 1 | |||
PyMOLGlobals *G = I->Obj.G; | PyMOLGlobals *G = I->Obj.G; | |||
int a, b, c, d, e, f, i, j; | int a, b, c, d, e, f, i, j; | |||
int a1, a2; | int a1, a2; | |||
float *v1, *v2, dst; | float *v1, *v2, dst; | |||
int maxBond; | int maxBond; | |||
MapType *map; | MapType *map; | |||
int nBond; | int nBond; | |||
BondType *ii1, *ii2; | BondType *ii1, *ii2; | |||
int flag; | int flag; | |||
int order; | int order; | |||
AtomInfoType *ai1, *ai2; | AtomInfoType *ai1, *ai2; | |||
/* Sulfur cutoff */ | /* Sulfur cutoff */ | |||
float cutoff_s; | float cutoff_s; | |||
/* Hydrogen cutoff */ | ||||
float cutoff_h; | ||||
float cutoff_v; | float cutoff_v; | |||
float cutoff; | ||||
float max_cutoff; | float max_cutoff; | |||
int water_flag; | ||||
int repeat = true; | int repeat = true; | |||
int discrete_chains = SettingGetGlobal_i(G, cSetting_pdb_discrete_chains); | int discrete_chains = SettingGetGlobal_i(G, cSetting_pdb_discrete_chains); | |||
int connect_bonded = SettingGetGlobal_b(G, cSetting_connect_bonded); | int connect_bonded = SettingGetGlobal_b(G, cSetting_connect_bonded); | |||
int connect_mode = SettingGetGlobal_i(G, cSetting_connect_mode); | int connect_mode = SettingGetGlobal_i(G, cSetting_connect_mode); | |||
int unbond_cations = SettingGetGlobal_i(G, cSetting_pdb_unbond_cations); | int unbond_cations = SettingGetGlobal_i(G, cSetting_pdb_unbond_cations); | |||
int ok = true; | int ok = true; | |||
cutoff_v = SettingGetGlobal_f(G, cSetting_connect_cutoff); | cutoff_v = SettingGetGlobal_f(G, cSetting_connect_cutoff); | |||
cutoff_s = cutoff_v + 0.2F; | cutoff_s = cutoff_v + 0.2F; | |||
cutoff_h = cutoff_v - 0.2F; | ||||
max_cutoff = cutoff_s; | max_cutoff = cutoff_s; | |||
if(connectModeOverride >= 0) | if(connectModeOverride >= 0) | |||
connect_mode = connectModeOverride; | connect_mode = connectModeOverride; | |||
if(connect_mode == 2) { /* force use of distance-based connectivity, | if(connect_mode == 2) { /* force use of distance-based connectivity, | |||
ignoring that provided with file */ | ignoring that provided with file */ | |||
bondSearchMode = true; | bondSearchMode = true; | |||
cs->NTmpBond = 0; | cs->NTmpBond = 0; | |||
VLAFreeP(cs->TmpBond); | VLAFreeP(cs->TmpBond); | |||
skipping to change at line 4035 | skipping to change at line 4119 | |||
for(d = a - 1; ok && d <= a + 1; d++) { | for(d = a - 1; ok && d <= a + 1; d++) { | |||
int *j_ptr1 = map->Head + d * dim12 + (b - 1) * dim2; | int *j_ptr1 = map->Head + d * dim12 + (b - 1) * dim2; | |||
/* e = [b-1, b, b+1] */ | /* e = [b-1, b, b+1] */ | |||
for(e = b - 1; ok && e <= b + 1; e++) { | for(e = b - 1; ok && e <= b + 1; e++) { | |||
int *j_ptr2 = j_ptr1 + c - 1; | int *j_ptr2 = j_ptr1 + c - 1; | |||
j_ptr1 += dim2; | j_ptr1 += dim2; | |||
/* f = [c-1, c, c+1] */ | /* f = [c-1, c, c+1] */ | |||
for(f = c - 1; ok && f <= c + 1; f++) { | for(f = c - 1; ok && f <= c + 1; f++) { | |||
j = *(j_ptr2++); /* *MapFirst(map,d,e,f)); */ | j = *(j_ptr2++); /* *MapFirst(map,d,e,f)); */ | |||
while(ok && j >= 0) { | while(ok && j >= 0) { | |||
if(i < j) { | if(i < j) { | |||
/* position in space for atom 2 */ | /* position in space for atom 2 */ | |||
v2 = cs->Coord + (3 * j); | v2 = cs->Coord + (3 * j); | |||
dst = (float) diff3f(v1, v2); | ||||
a2 = cs->IdxToAtm[j]; | a2 = cs->IdxToAtm[j]; | |||
ai2 = ai + a2; | ai2 = ai + a2; | |||
dst -= ((ai1->vdw + ai2->vdw) / 2); | flag = is_distance_bonded(G, cs, ai1, ai2, v1, v2, | |||
cutoff_v, connect_mode, discrete_chains, | ||||
/* quick hack for water detection. | connect_bonded, unbond_cations); | |||
they don't usually don't have CONECT records | ||||
and may not be HETATMs though they are supposed to be | ||||
... | ||||
This checks whether either atom in the bond | ||||
is a known wter. | ||||
*/ | ||||
water_flag = false; | ||||
if(AtomInfoKnownWaterResName(G, LexStr(G, ai1->resn))) | ||||
water_flag = true; | ||||
else if(AtomInfoKnownWaterResName(G, LexStr(G, ai2->resn | ||||
))) | ||||
water_flag = true; | ||||
/* workaround for hydrogens and sulfurs... */ | ||||
if(ai1->isHydrogen() || ai2->isHydrogen()) | { | |||
cutoff = cutoff_h; | ||||
else if(((ai1->elem[0] == 'S') && (!ai1->elem[1])) || | ||||
((ai2->elem[0] == 'S') && (!ai2->elem[1]))) | ||||
cutoff = cutoff_s; | ||||
else | ||||
cutoff = cutoff_v; | ||||
/* here's our complex atomic connectivity allow / disallo | ||||
w */ | ||||
if((dst <= cutoff) && /* too close to be non-covalent, A | ||||
ND*/ | ||||
(!(ai1->isHydrogen() && ai2->isHydrogen())) && /* not | ||||
both hydrogen (what about H2?), AND */ | ||||
(water_flag || /* known to be a water */ | ||||
(!cs->TmpBond) || /* or no connectivity information | ||||
present in file */ | ||||
((!(ai1->hetatm && ai2->hetatm) || /* or not both PD | ||||
B HETATMS */ | ||||
(connect_mode == 3))) || | ||||
((ai1->hetatm && ai2->hetatm) && /* both hetatms, an | ||||
d both recognized polymer residue? */ | ||||
AtomInfoKnownPolymerResName(LexStr(G, ai1->resn)) & | ||||
& /* (new PDB rule allows these to be HETATMs */ | ||||
AtomInfoKnownPolymerResName(LexStr(G, ai2->resn))) | ||||
) && /* or we're no excluding HETATM -> HETATM bonds | ||||
, AND*/ | ||||
((discrete_chains < 1) || /* we allow intra-chain bon | ||||
ds */ | ||||
(ai1->chain == ai2->chain)) && /* or atoms are in th | ||||
e same chain, AND */ | ||||
(connect_bonded || /* we're allowing explicitly bonde | ||||
d atoms to be auto-connected */ | ||||
(!(ai1->bonded && ai2->bonded))) /* or neither atom | ||||
was previously bonded */ | ||||
) { | ||||
/* WE THINK WE HAVE A BOND */ | ||||
flag = true; | ||||
/* unbond edge cases */ | ||||
/* atoms in same water molecule or different? */ | ||||
if(water_flag) | ||||
if(!AtomInfoSameResidue(G, ai1, ai2)) /* don't conne | ||||
ct water atoms in different residues */ | ||||
flag = false; | ||||
/* atoms have same alt. conformations? from same molecu | ||||
le? */ | ||||
if(flag) { | ||||
if(ai1->alt[0] != ai2->alt[0]) { /* handle altern | ||||
ate conformers */ | ||||
if(ai1->alt[0] && ai2->alt[0]) | ||||
flag = false; /* don't connect atoms with diff | ||||
erent, non-NULL | ||||
alternate conformations */ | ||||
} else if(ai1->alt[0] && ai2->alt[0]) | ||||
if(!AtomInfoSameResidue(G, ai1, ai2)) | ||||
if(ai1->alt[0] != ai2->alt[0]) | ||||
flag = false; /* don't connect different, non- | ||||
NULL | ||||
alt conformations in | ||||
different residues */ | ||||
} | ||||
/* do not bond different water molecules, even if their | ||||
alt. confs. match */ | ||||
if(flag) { | ||||
if(ai1->alt[0] || ai2->alt[0]) | ||||
if(water_flag) /* hack to clean up water bonds | ||||
*/ | ||||
if(!AtomInfoSameResidue(G, ai1, ai2)) | ||||
flag = false; | ||||
} | ||||
/* if either is a cation, unbond is user wants */ | ||||
if(flag && unbond_cations) { | ||||
if(AtomInfoIsFreeCation(G, ai1)) | ||||
flag = false; | ||||
else if(AtomInfoIsFreeCation(G, ai2)) | ||||
flag = false; | ||||
} | ||||
/* we have a bond, now process it */ | /* we have a bond, now process it */ | |||
if(flag) { | if(flag) { | |||
VLACheck((*bond), BondType, nBond); | VLACheck((*bond), BondType, nBond); | |||
CHECKOK(ok, (*bond)); | CHECKOK(ok, (*bond)); | |||
if (ok){ | if (ok){ | |||
(*bond)[nBond].index[0] = a1; | (*bond)[nBond].index[0] = a1; | |||
(*bond)[nBond].index[1] = a2; | (*bond)[nBond].index[1] = a2; | |||
(*bond)[nBond].stereo = 0; | (*bond)[nBond].stereo = 0; | |||
order = 1; | order = 1; | |||
skipping to change at line 4166 | skipping to change at line 4162 | |||
if(violations > (cs->NIndex >> 3)) { | if(violations > (cs->NIndex >> 3)) { | |||
/* if more than 12% of the structure has excessi ve #'s of bonds... */ | /* if more than 12% of the structure has excessi ve #'s of bonds... */ | |||
PRINTFB(G, FB_ObjectMolecule, FB_Blather) | PRINTFB(G, FB_ObjectMolecule, FB_Blather) | |||
" ObjectMoleculeConnect: Assuming chains are d iscrete...\n" | " ObjectMoleculeConnect: Assuming chains are d iscrete...\n" | |||
ENDFB(G); | ENDFB(G); | |||
discrete_chains = 1; | discrete_chains = 1; | |||
repeat = true; | repeat = true; | |||
goto do_it_again; | goto do_it_again; | |||
} | } | |||
} | } | |||
/* selenomethionine; double-bond the carbonyl if pres | ||||
ent */ | if(!ai1->hetatm || ai1->resn == G->lex_const.MSE) { | |||
if(ai1->hetatm) { /* common HETATMs we should | ||||
know about... */ | ||||
if (ai1->resn == G->lex_const.MSE) { | ||||
if ((ai1->name == G->lex_const.C && ai2->name == | ||||
G->lex_const.O) || | ||||
(ai1->name == G->lex_const.O && ai2->name == | ||||
G->lex_const.C)) { | ||||
/* if carbonyl in same residue, double bond it | ||||
*/ | ||||
if(AtomInfoSameResidue(G, ai1, ai2)) { | ||||
order = 2; | ||||
} | ||||
} | ||||
} | ||||
} else { | ||||
if(AtomInfoSameResidue(I->Obj.G, ai1, ai2)) { | if(AtomInfoSameResidue(I->Obj.G, ai1, ai2)) { | |||
/* hookup standard disconnected PDB residue */ | /* hookup standard disconnected PDB residue */ | |||
assign_pdb_known_residue(G, ai1, ai2, &order); | assign_pdb_known_residue(G, ai1, ai2, &order); | |||
} | } | |||
} | } | |||
(*bond)[nBond].order = -order; /* store tentati ve valence as negative */ | (*bond)[nBond].order = -order; /* store tentati ve valence as negative */ | |||
nBond++; | nBond++; | |||
} | } | |||
} | } | |||
} | } | |||
End of changes. 12 change blocks. | ||||
136 lines changed or deleted | 96 lines changed or added |