ObjectMolecule2.cpp (pymol-v2.1.0.tar.bz2) | : | ObjectMolecule2.cpp (pymol-open-source-2.2.0) | ||
---|---|---|---|---|
skipping to change at line 35 | skipping to change at line 35 | |||
#include"Base.h" | #include"Base.h" | |||
#include"Debug.h" | #include"Debug.h" | |||
#include"Parse.h" | #include"Parse.h" | |||
#include"OOMac.h" | #include"OOMac.h" | |||
#include"Vector.h" | #include"Vector.h" | |||
#include"PConv.h" | #include"PConv.h" | |||
#include"ObjectMolecule.h" | #include"ObjectMolecule.h" | |||
#include"Feedback.h" | #include"Feedback.h" | |||
#include"Util.h" | #include"Util.h" | |||
#include"Util2.h" | ||||
#include"AtomInfo.h" | #include"AtomInfo.h" | |||
#include"Selector.h" | #include"Selector.h" | |||
#include"ObjectDist.h" | #include"ObjectDist.h" | |||
#include"Executive.h" | #include"Executive.h" | |||
#include"P.h" | #include"P.h" | |||
#include"ObjectCGO.h" | #include"ObjectCGO.h" | |||
#include"Scene.h" | #include"Scene.h" | |||
#include "Lex.h" | #include "Lex.h" | |||
#include"AtomInfoHistory.h" | #include"AtomInfoHistory.h" | |||
skipping to change at line 64 | skipping to change at line 65 | |||
#define ntrim ParseNTrim | #define ntrim ParseNTrim | |||
#define nextline ParseNextLine | #define nextline ParseNextLine | |||
#define ncopy ParseNCopy | #define ncopy ParseNCopy | |||
#define nskip ParseNSkip | #define nskip ParseNSkip | |||
#define cResvMask 0x7FFF | #define cResvMask 0x7FFF | |||
#define cMaxOther 6 | #define cMaxOther 6 | |||
static int strstartswith(const char * s, const char * prefix) { | #define strstartswith p_strstartswith | |||
while(*prefix) | ||||
if(*s++ != *prefix++) | ||||
return false; | ||||
return true; | ||||
} | ||||
static int strstartswithword(const char * s, const char * word) { | static int strstartswithword(const char * s, const char * word) { | |||
while(*word) | while(*word) | |||
if(*s++ != *word++) | if(*s++ != *word++) | |||
return false; | return false; | |||
switch(*s) { | switch(*s) { | |||
case ' ': | case ' ': | |||
case '\t': | case '\t': | |||
case '\r': | case '\r': | |||
case '\n': | case '\n': | |||
skipping to change at line 605 | skipping to change at line 601 | |||
test = diffsq3f(v, point); | test = diffsq3f(v, point); | |||
if(sub_vdw) { | if(sub_vdw) { | |||
test = sqrt1f(test); | test = sqrt1f(test); | |||
test -= I->AtomInfo[cs->IdxToAtm[j]].vdw; | test -= I->AtomInfo[cs->IdxToAtm[j]].vdw; | |||
if(test < 0.0F) | if(test < 0.0F) | |||
test = 0.0F; | test = 0.0F; | |||
test = test * test; | test = test * test; | |||
} | } | |||
if(test < cutoff2) { | if(test < cutoff2) { | |||
float weight = cutoff - sqrt1f(test); | float weight = cutoff - sqrt1f(test); | |||
float *at_col = ColorGet(I->Obj.G, I->AtomInfo[cs->IdxToAtm[j] ].color); | const float *at_col = ColorGet(I->Obj.G, I->AtomInfo[cs->IdxTo Atm[j]].color); | |||
color[0] += at_col[0] * weight; | color[0] += at_col[0] * weight; | |||
color[1] += at_col[1] * weight; | color[1] += at_col[1] * weight; | |||
color[2] += at_col[2] * weight; | color[2] += at_col[2] * weight; | |||
tot_weight += weight; | tot_weight += weight; | |||
} | } | |||
if(test <= nearest) { | if(test <= nearest) { | |||
result = j; | result = j; | |||
nearest = test; | nearest = test; | |||
} | } | |||
j = MapNext(map, j); | j = MapNext(map, j); | |||
skipping to change at line 632 | skipping to change at line 628 | |||
test = diffsq3f(v, point); | test = diffsq3f(v, point); | |||
if(sub_vdw) { | if(sub_vdw) { | |||
test = sqrt1f(test); | test = sqrt1f(test); | |||
test -= I->AtomInfo[cs->IdxToAtm[j]].vdw; | test -= I->AtomInfo[cs->IdxToAtm[j]].vdw; | |||
if(test < 0.0F) | if(test < 0.0F) | |||
test = 0.0F; | test = 0.0F; | |||
test = test * test; | test = test * test; | |||
} | } | |||
if(test < cutoff2) { | if(test < cutoff2) { | |||
float weight = cutoff - sqrt1f(test); | float weight = cutoff - sqrt1f(test); | |||
float *color = ColorGet(I->Obj.G, I->AtomInfo[cs->IdxToAtm[j]].color | const float *at_col = ColorGet(I->Obj.G, I->AtomInfo[cs->IdxToAtm[j] | |||
); | ].color); | |||
color[0] += color[0] * weight; | color[0] += at_col[0] * weight; | |||
color[1] += color[1] * weight; | color[1] += at_col[1] * weight; | |||
color[2] += color[2] * weight; | color[2] += at_col[2] * weight; | |||
tot_weight += weight; | tot_weight += weight; | |||
} | } | |||
if(test <= nearest) { | if(test <= nearest) { | |||
result = j; | result = j; | |||
nearest = test; | nearest = test; | |||
} | } | |||
v += 3; | v += 3; | |||
} | } | |||
} | } | |||
if(result >= 0) | if(result >= 0) | |||
skipping to change at line 1661 | skipping to change at line 1657 | |||
static void ObjectMoleculePDBStr2CoordSetPASS1(PyMOLGlobals * G, int *ok, | static void ObjectMoleculePDBStr2CoordSetPASS1(PyMOLGlobals * G, int *ok, | |||
const char **restart_model, const char *p, int n_tags, const char* const* ta g_start, | const char **restart_model, const char *p, int n_tags, const char* const* ta g_start, | |||
int *nAtom, char cc[], int quiet, int *bogus_name_alignment, | int *nAtom, char cc[], int quiet, int *bogus_name_alignment, | |||
int *ssFlag, const char **next_pdb, PDBInfoRec *info, int only_read_one_mode l, | int *ssFlag, const char **next_pdb, PDBInfoRec *info, int only_read_one_mode l, | |||
int *ignore_conect, int *bondFlag, M4XAnnoType * m4x, int *have_bond_order) { | int *ignore_conect, int *bondFlag, M4XAnnoType * m4x, int *have_bond_order) { | |||
int seen_end_of_atoms = false; | int seen_end_of_atoms = false; | |||
*restart_model = NULL; | *restart_model = NULL; | |||
while(*ok && *p) { | while(*ok && *p) { | |||
AddOrthoOutputIfMatchesTags(G, n_tags, *nAtom, tag_start, p, cc, quiet); | AddOrthoOutputIfMatchesTags(G, n_tags, *nAtom, tag_start, p, cc, quiet); | |||
if((strstartswith(p, "ATOM ") || | if((strstartswith(p, "ATOM ") || | |||
strstartswith(p, "HETATM")) && (!*restart_model)) { | strstartswith(p, "HETATM")) && (!*restart_model)) { | |||
if(!seen_end_of_atoms) | if(!seen_end_of_atoms) | |||
(*nAtom)++; | (*nAtom)++; | |||
if(*bogus_name_alignment) { | if(*bogus_name_alignment) { | |||
ncopy(cc, nskip(p, 12), 4); /* copy the atom field */ | ncopy(cc, nskip(p, 12), 4); /* copy the atom field */ | |||
if((cc[0] == 32) && (cc[1] != 32)) { /* check to see if indentation was followed correctly, 32 - space */ | if((cc[0] == 32) && (cc[1] != 32)) { /* check to see if indentation was followed correctly, 32 - space */ | |||
*bogus_name_alignment = false; | *bogus_name_alignment = false; | |||
} | } | |||
} | } | |||
} else if(strstartswith(p, "HELIX ")){ | } else if(strstartswith(p, "HELIX ")){ | |||
skipping to change at line 1944 | skipping to change at line 1940 | |||
&& (ai->resv != sst->resv2 || ai->inscode <= sst->inscode2)) | && (ai->resv != sst->resv2 || ai->inscode <= sst->inscode2)) | |||
{ | { | |||
ai->ssType[0] = sst->type; | ai->ssType[0] = sst->type; | |||
return; | return; | |||
} | } | |||
ssi = sst->next; | ssi = sst->next; | |||
} | } | |||
} | } | |||
} | } | |||
/* | ||||
* PQR atom line parsing | ||||
* | ||||
* Try to parse columns white space delimited (10 columns with optional | ||||
* chain, 9 without). | ||||
* | ||||
* Where PQR files come from: | ||||
* | ||||
* pdb2pqr -> writes PDB-like fixed colums. APBS will fail to read those files | ||||
* if columns are too wide. | ||||
* | ||||
* pdb2pqr --whitespace -> puts extra whitespace, starting at column 2, but | ||||
* not between chain and resi! PyMOL <= 2.1 fails to read those files. | ||||
* | ||||
* APBS Tools Plugin by Michael Lerner adds extra whitespace before negative | ||||
* coordinates (assuming -100.0 is the most likely source of error). | ||||
* | ||||
* @param[in,out] p Pointer to parse from, points after the ATOM field. | ||||
* Will move the pointer to the end of the line if | ||||
* parsing was successful. | ||||
* @param[out] ai Atom to populate with data | ||||
* @param[out] coord Coordinates to populate | ||||
* @return true on success, false otherwise. | ||||
*/ | ||||
static bool parse_pqr_atom_line(PyMOLGlobals * G, | ||||
const char * &p, | ||||
AtomInfoType * ai, | ||||
float * coord) | ||||
{ | ||||
auto p_eol = nskip(p, 999); // end of line pointer | ||||
std::string cc(p, p_eol); // line (starting after ATOM field) | ||||
// whitespace splitting | ||||
auto columns = strsplit(cc); | ||||
// insert chain column if missing | ||||
if (columns.size() == 9) { | ||||
columns.insert(columns.begin() + 3, ""); | ||||
// check for concatenated chain + resi | ||||
if (columns[4].size() > 4 && !isdigit(columns[4][0])) { | ||||
columns[3] = columns[4].substr(0, 1); | ||||
columns[4] = columns[4].substr(1); | ||||
} | ||||
} | ||||
// for validation: if number parsing consumes the entire string, then dummy | ||||
// will never be populated (sscanf(...) == 1, not 2) | ||||
char dummy[2]; | ||||
// validate numeric fields and populate atom info and coordinates | ||||
if (columns.size() == 10 && | ||||
sscanf(columns[0].c_str(), "%d%1s", &ai->id, dummy) == 1 && | ||||
sscanf(columns[5].c_str(), "%f%1s", coord + 0, dummy) == 1 && | ||||
sscanf(columns[6].c_str(), "%f%1s", coord + 1, dummy) == 1 && | ||||
sscanf(columns[7].c_str(), "%f%1s", coord + 2, dummy) == 1 && | ||||
sscanf(columns[8].c_str(), "%f%1s", &ai->partialCharge, dummy) == 1 && | ||||
sscanf(columns[9].c_str(), "%f%1s", &ai->elec_radius, dummy) == 1) { | ||||
LexAssign(G, ai->name, columns[1].c_str()); | ||||
LexAssign(G, ai->resn, columns[2].c_str()); | ||||
LexAssign(G, ai->chain, columns[3].c_str()); | ||||
ai->setResi(columns[4].c_str()); | ||||
// move parser to next line | ||||
p = p_eol; | ||||
return true; | ||||
} | ||||
return false; | ||||
} | ||||
CoordSet *ObjectMoleculePDBStr2CoordSet(PyMOLGlobals * G, | CoordSet *ObjectMoleculePDBStr2CoordSet(PyMOLGlobals * G, | |||
const char *buffer, | const char *buffer, | |||
AtomInfoType ** atInfoPtr, | AtomInfoType ** atInfoPtr, | |||
const char **restart_model, | const char **restart_model, | |||
char *segi_override, | char *segi_override, | |||
M4XAnnoType * m4x, | M4XAnnoType * m4x, | |||
char *pdb_name, | char *pdb_name, | |||
const char **next_pdb, | const char **next_pdb, | |||
PDBInfoRec * info, int quiet, int *model _number) | PDBInfoRec * info, int quiet, int *model _number) | |||
{ | { | |||
skipping to change at line 2095 | skipping to change at line 2163 | |||
a = 0; /* WATCHOUT */ | a = 0; /* WATCHOUT */ | |||
atomCount = 0; | atomCount = 0; | |||
/* PASS 2 */ | /* PASS 2 */ | |||
seen_model = false; | seen_model = false; | |||
while(ok && *p) { | while(ok && *p) { | |||
/* printf("%c%c%c%c%c%c\n",p[0],p[1],p[2],p[3],p[4],p[5]); */ | /* printf("%c%c%c%c%c%c\n",p[0],p[1],p[2],p[3],p[4],p[5]); */ | |||
AFlag = false; | AFlag = false; | |||
SSCode = 0; | SSCode = 0; | |||
if(strstartswith(p, "ATOM")) | if(strstartswith(p, "ATOM ")) | |||
AFlag = 1; | AFlag = 1; | |||
else if(strstartswith(p, "HETATM")) | else if(strstartswith(p, "HETATM")) | |||
AFlag = 2; | AFlag = 2; | |||
else if(strstartswith(p, "HEADER")) { | else if(strstartswith(p, "HEADER")) { | |||
if(pdb_name) { | if(pdb_name) { | |||
if(atomCount > 0) { | if(atomCount > 0) { | |||
/* have we already read atoms? then this is probably a new PDB file * / | /* have we already read atoms? then this is probably a new PDB file * / | |||
(*next_pdb) = p; /* found another PDB file after this one... */ | (*next_pdb) = p; /* found another PDB file after this one... */ | |||
break; | break; | |||
skipping to change at line 2632 | skipping to change at line 2700 | |||
if(ok && SSCode) { | if(ok && SSCode) { | |||
ss_found = sshash_register_rec(ss_hash, | ss_found = sshash_register_rec(ss_hash, | |||
ss_chain1, ss_resv1, ss_inscode1, | ss_chain1, ss_resv1, ss_inscode1, | |||
ss_chain2, ss_resv2, ss_inscode2, SSCode); | ss_chain2, ss_resv2, ss_inscode2, SSCode); | |||
} | } | |||
/* Atom records */ | /* Atom records */ | |||
if(ok && AFlag && (!*restart_model)) { | if(ok && AFlag && (!*restart_model)) { | |||
ai = atInfo + atomCount; | ai = atInfo + atomCount; | |||
p = nskip(p, 6); | p = nskip(p, 6); | |||
ai->rank = atomCount; | ||||
if(info && info->is_pqr_file()) { | ||||
if (parse_pqr_atom_line(G, p, ai, coord + a)) { | ||||
goto pqr_done; | ||||
} | ||||
} | ||||
p = ncopy(cc, p, 5); | p = ncopy(cc, p, 5); | |||
if(!sscanf(cc, "%d", &ai->id)) | if(!sscanf(cc, "%d", &ai->id)) | |||
ai->id = 0; | ai->id = 0; | |||
ai->rank = atomCount; | ||||
p = nskip(p, 1); /* to 12 */ | p = nskip(p, 1); /* to 12 */ | |||
p = ncopy(literal_name, p, 4); | p = ncopy(literal_name, p, 4); | |||
if(literal_names) { | if(literal_names) { | |||
LexAssign(G, ai->name, literal_name); | LexAssign(G, ai->name, literal_name); | |||
} else { | } else { | |||
ParseNTrim(cc, literal_name, 4); | ParseNTrim(cc, literal_name, 4); | |||
LexAssign(G, ai->name, cc); | LexAssign(G, ai->name, cc); | |||
} | } | |||
skipping to change at line 2724 | skipping to change at line 2800 | |||
break; | break; | |||
case 4: /* simply read trim and write back out with 3-let ter names starting from the | case 4: /* simply read trim and write back out with 3-let ter names starting from the | |||
second column, and four-letter names starting in the first */ | second column, and four-letter names starting in the first */ | |||
ntrim(cc, ai_name, 4); | ntrim(cc, ai_name, 4); | |||
LexAssign(G, ai->name, cc); | LexAssign(G, ai->name, cc); | |||
break; | break; | |||
} | } | |||
} | } | |||
p = ncopy(cc, p, 1); | p = ncopy(cc, p, 1); | |||
if (ai->chain){ | ||||
LexDec(G, ai->chain); | ||||
} | ||||
if(*cc == ' ') { | if(*cc == ' ') { | |||
ss_chain1 = 0; | ss_chain1 = 0; | |||
ai->chain = 0; | ai->chain = 0; | |||
} else { | } else { | |||
ss_chain1 = *cc; | ss_chain1 = *cc; | |||
ai->chain = LexIdx(G, cc); | ai->chain = LexIdx(G, cc); | |||
} | } | |||
p = ncopy(cc, p, 4); | p = ncopy(cc, p, 4); | |||
if(!sscanf(cc, "%d", &ai->resv)) | if(!sscanf(cc, "%d", &ai->resv)) | |||
ai->resv = 0; | ai->resv = 0; | |||
ai->setInscode(*p); | ai->setInscode(*p); | |||
p = nskip(p, 1); | p = nskip(p, 1); | |||
if(ssFlag) { /* get secondary structure information (if avail ) */ | if(ssFlag) { /* get secondary structure information (if avail ) */ | |||
sshash_lookup(ss_hash, ai, ss_chain1); | sshash_lookup(ss_hash, ai, ss_chain1); | |||
} else { | } else { | |||
ai->cartoon = cCartoon_tube; | ai->cartoon = cCartoon_tube; | |||
} | } | |||
if((!info) || (!info->is_pqr_file())) { /* standard PDB file */ | ||||
{ | ||||
p = nskip(p, 3); | p = nskip(p, 3); | |||
p = ncopy(cc, p, 8); | p = ncopy(cc, p, 8); | |||
sscanf(cc, "%f", coord + a); | sscanf(cc, "%f", coord + a); | |||
p = ncopy(cc, p, 8); | p = ncopy(cc, p, 8); | |||
sscanf(cc, "%f", coord + (a + 1)); | sscanf(cc, "%f", coord + (a + 1)); | |||
p = ncopy(cc, p, 8); | p = ncopy(cc, p, 8); | |||
sscanf(cc, "%f", coord + (a + 2)); | sscanf(cc, "%f", coord + (a + 2)); | |||
} | ||||
if((!info) || (!info->is_pqr_file())) { /* standard PDB file */ | ||||
p = ncopy(cc, p, 6); | p = ncopy(cc, p, 6); | |||
if(!sscanf(cc, "%f", &ai->q)) | if(!sscanf(cc, "%f", &ai->q)) | |||
ai->q = 1.0; | ai->q = 1.0; | |||
p = ncopy(cc, p, 6); | p = ncopy(cc, p, 6); | |||
if(!sscanf(cc, "%f", &ai->b)) | if(!sscanf(cc, "%f", &ai->b)) | |||
ai->b = 0.0; | ai->b = 0.0; | |||
if (info->variant == PDB_VARIANT_PDBQT) { | if (info->variant == PDB_VARIANT_PDBQT) { | |||
ignore_pdb_segi = true; | ignore_pdb_segi = true; | |||
skipping to change at line 2846 | skipping to change at line 2927 | |||
/* only read formal charge when sign is present */ | /* only read formal charge when sign is present */ | |||
char ctmp = cc[0]; | char ctmp = cc[0]; | |||
cc[0] = cc[1]; | cc[0] = cc[1]; | |||
cc[1] = ctmp; | cc[1] = ctmp; | |||
if(!sscanf(cc, "%hhi", &ai->formalCharge)) | if(!sscanf(cc, "%hhi", &ai->formalCharge)) | |||
ai->formalCharge = 0; | ai->formalCharge = 0; | |||
} | } | |||
/* end normal PDB */ | /* end normal PDB */ | |||
} else if(info && info->is_pqr_file()) { | } else if(info && info->is_pqr_file()) { | |||
/* PQR file format...not well defined, but basically PDB | ||||
with charge and radius instead of B and Q. Right now, | ||||
we insist on PDB column format through the chain ID, | ||||
and then switch over to whitespace delimited parsing | ||||
for the coordinates, charge, and radius */ | ||||
p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | ||||
sscanf(cc, "%f", coord + a); | ||||
p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | ||||
sscanf(cc, "%f", coord + (a + 1)); | ||||
p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | ||||
sscanf(cc, "%f", coord + (a + 2)); | ||||
p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | |||
if(!sscanf(cc, "%f", &ai->partialCharge)) | if(!sscanf(cc, "%f", &ai->partialCharge)) | |||
ai->partialCharge = 0.0F; | ai->partialCharge = 0.0F; | |||
p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | p = ParseWordNumberCopy(cc, p, MAXLINELEN - 1); | |||
if(sscanf(cc, "%f", &ai->elec_radius) != 1) | if(sscanf(cc, "%f", &ai->elec_radius) != 1) | |||
ai->elec_radius = 0.0F; | ai->elec_radius = 0.0F; | |||
} | } | |||
pqr_done: | ||||
ai->visRep = auto_show; | ai->visRep = auto_show; | |||
if(AFlag == 1) | if(AFlag == 1) | |||
ai->hetatm = 0; | ai->hetatm = 0; | |||
else { | else { | |||
ai->hetatm = 1; | ai->hetatm = 1; | |||
ai->flags = cAtomFlag_ignore; | ai->flags = cAtomFlag_ignore; | |||
} | } | |||
AtomInfoAssignParameters(G, ai); | AtomInfoAssignParameters(G, ai); | |||
End of changes. 16 change blocks. | ||||
29 lines changed or deleted | 99 lines changed or added |