AtomInfo.cpp (pymol-v1.8.6.0.tar.bz2) | : | AtomInfo.cpp (pymol-v2.1.0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 587 | skipping to change at line 587 | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
return false; | return false; | |||
} | } | |||
int AtomInfoKnownPolymerResName(const char *resn) | int AtomInfoKnownPolymerResName(const char *resn) | |||
{ | { | |||
return AtomInfoKnownProteinResName(resn) || | ||||
AtomInfoKnownNucleicResName(resn); | ||||
} | ||||
int AtomInfoKnownNucleicResName(const char *resn) | ||||
{ | ||||
if (resn[0] == 'D') { | ||||
// Deoxy ribonucleotide | ||||
++resn; | ||||
} | ||||
switch (resn[0]) { | ||||
case 'A': | ||||
case 'C': | ||||
case 'G': | ||||
case 'I': | ||||
case 'T': | ||||
case 'U': | ||||
if (!resn[1]) | ||||
return true; | ||||
} | ||||
return false; | ||||
} | ||||
int AtomInfoKnownProteinResName(const char *resn) | ||||
{ | ||||
switch (resn[0]) { | switch (resn[0]) { | |||
case 'A': | case 'A': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 0: /* A*/ | ||||
return true; | ||||
break; | ||||
case 'L': | case 'L': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'A': /* ALA */ | case 'A': /* ALA */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'R': | case 'R': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'G': /* ARG */ | case 'G': /* ARG */ | |||
skipping to change at line 621 | skipping to change at line 645 | |||
break; | break; | |||
case 'N': /* ASN */ | case 'N': /* ASN */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'C': | case 'C': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 0: /* C */ | ||||
return true; | ||||
case 'Y': | case 'Y': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'S': /* CYS */ | case 'S': /* CYS */ | |||
case 'X': /* CYX */ | case 'X': /* CYX */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'D': | ||||
switch (resn[1]) { | ||||
case 'G': /* DG */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
case 'C': /* DC */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
case 'T': /* DT */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
case 'A': /* DA */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
case 'U': /* DU */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
case 'I': /* DI */ | ||||
switch (resn[2]) { | ||||
case 0: | ||||
return true; | ||||
break; | ||||
} | ||||
} | ||||
break; | ||||
case 'G': | case 'G': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 0: /* G */ | ||||
return true; | ||||
break; | ||||
case 'L': | case 'L': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'N': /* GLN */ | case 'N': /* GLN */ | |||
return true; | return true; | |||
break; | break; | |||
case 'U': /* GLU */ | case 'U': /* GLU */ | |||
return true; | return true; | |||
break; | break; | |||
case 'Y': /* GLY */ | case 'Y': /* GLY */ | |||
return true; | return true; | |||
skipping to change at line 705 | skipping to change at line 684 | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'S': /* HIS */ | case 'S': /* HIS */ | |||
case 'D': /* HID */ | case 'D': /* HID */ | |||
case 'E': /* HIE */ | case 'E': /* HIE */ | |||
case 'P': /* HIP */ | case 'P': /* HIP */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | ||||
case 'I': | case 'I': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 'L': | case 'L': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'E': /* ILE */ | case 'E': /* ILE */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
} | } | |||
break; | break; | |||
skipping to change at line 787 | skipping to change at line 767 | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'R': /* SER */ | case 'R': /* SER */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'T': | case 'T': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 0: /* T */ | ||||
return true; | ||||
case 'H': | case 'H': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'R': /* THR */ | case 'R': /* THR */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'R': | case 'R': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'P': /* TRP */ | case 'P': /* TRP */ | |||
skipping to change at line 812 | skipping to change at line 790 | |||
break; | break; | |||
case 'Y': | case 'Y': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'R': /* TYR */ | case 'R': /* TYR */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
break; | break; | |||
case 'U': | ||||
switch (resn[1]) { | ||||
case 0: /* U */ | ||||
return true; | ||||
break; | ||||
} | ||||
break; | ||||
case 'V': | case 'V': | |||
switch (resn[1]) { | switch (resn[1]) { | |||
case 'A': | case 'A': | |||
switch (resn[2]) { | switch (resn[2]) { | |||
case 'L': /* VAL */ | case 'L': /* VAL */ | |||
return true; | return true; | |||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
skipping to change at line 853 | skipping to change at line 824 | |||
// return false if buffer too small | // return false if buffer too small | |||
bool AtomResiFromResv(char *resi, size_t size, int resv, char inscode) { | bool AtomResiFromResv(char *resi, size_t size, int resv, char inscode) { | |||
if (inscode > ' ') | if (inscode > ' ') | |||
return snprintf(resi, size, "%d%c", resv, inscode) < size; | return snprintf(resi, size, "%d%c", resv, inscode) < size; | |||
return snprintf(resi, size, "%d", resv) < size; | return snprintf(resi, size, "%d", resv) < size; | |||
} | } | |||
/*========================================================================*/ | /*========================================================================*/ | |||
PyObject *AtomInfoAsPyList(PyMOLGlobals * G, const AtomInfoType * I) | PyObject *AtomInfoAsPyList(PyMOLGlobals * G, const AtomInfoType * I) | |||
{ | { | |||
#ifdef _PYMOL_NOPY | ||||
return NULL; | ||||
#else | ||||
PyObject *result = NULL; | PyObject *result = NULL; | |||
result = PyList_New(48); | result = PyList_New(48); | |||
int version = SettingGetGlobal_f(G, cSetting_pse_export_version) * 1000; | int version = SettingGetGlobal_f(G, cSetting_pse_export_version) * 1000; | |||
char resi[8]; | char resi[8]; | |||
// at some point, change this to !version || ... | // at some point, change this to !version || ... | |||
if (version >= 1810) { | if (version >= 1810) { | |||
resi[0] = I->inscode; | resi[0] = I->inscode; | |||
skipping to change at line 922 | skipping to change at line 890 | |||
const float anisou_stack[] {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; | const float anisou_stack[] {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; | |||
const float * anisou = I->anisou ? I->anisou : anisou_stack; | const float * anisou = I->anisou ? I->anisou : anisou_stack; | |||
for (int i = 0; i < 6; ++i) { | for (int i = 0; i < 6; ++i) { | |||
PyList_SetItem(result, 41 + i, PyFloat_FromDouble(anisou[i])); | PyList_SetItem(result, 41 + i, PyFloat_FromDouble(anisou[i])); | |||
} | } | |||
PyList_SetItem(result, 47, PyString_FromString(LexStr(G, I->custom))); | PyList_SetItem(result, 47, PyString_FromString(LexStr(G, I->custom))); | |||
return (PConvAutoNone(result)); | return (PConvAutoNone(result)); | |||
#endif | ||||
} | } | |||
int AtomInfoFromPyList(PyMOLGlobals * G, AtomInfoType * I, PyObject * list) | int AtomInfoFromPyList(PyMOLGlobals * G, AtomInfoType * I, PyObject * list) | |||
{ | { | |||
#ifdef _PYMOL_NOPY | ||||
return 0; | ||||
#else | ||||
int ok = true; | int ok = true; | |||
int tmp_int; | int tmp_int; | |||
ov_size ll = 0; | ov_size ll = 0; | |||
OrthoLineType temp = ""; | OrthoLineType temp = ""; | |||
#define PCONVPYSTRTOLEXIDX(i, n) { \ | #define PCONVPYSTRTOLEXIDX(i, n) { \ | |||
ok = CPythonVal_PConvPyStrToStr_From_List(G, list, i, temp, sizeof(OrthoLineTy pe)); \ | ok = CPythonVal_PConvPyStrToStr_From_List(G, list, i, temp, sizeof(OrthoLineTy pe)); \ | |||
n = LexIdx(G, temp); } | n = LexIdx(G, temp); } | |||
if(ok) | if(ok) | |||
skipping to change at line 1060 | skipping to change at line 1024 | |||
float u[6]; | float u[6]; | |||
for (int i = 0; ok && i < 6; ++i) | for (int i = 0; ok && i < 6; ++i) | |||
ok = CPythonVal_PConvPyFloatToFloat_From_List(G, list, 41 + i, u + i); | ok = CPythonVal_PConvPyFloatToFloat_From_List(G, list, 41 + i, u + i); | |||
if(ok && (u[0] || u[1] || u[2] || u[3] || u[4] || u[5])) | if(ok && (u[0] || u[1] || u[2] || u[3] || u[4] || u[5])) | |||
memcpy(I->get_anisou(), u, 6 * sizeof(float)); | memcpy(I->get_anisou(), u, 6 * sizeof(float)); | |||
} | } | |||
if(ok && (ll > 47)) { | if(ok && (ll > 47)) { | |||
PCONVPYSTRTOLEXIDX(47, I->custom); | PCONVPYSTRTOLEXIDX(47, I->custom); | |||
} | } | |||
return (ok); | return (ok); | |||
#endif | ||||
} | } | |||
void AtomInfoCopy(PyMOLGlobals * G, const AtomInfoType * src, AtomInfoType * dst , int copy_properties) | void AtomInfoCopy(PyMOLGlobals * G, const AtomInfoType * src, AtomInfoType * dst , int copy_properties) | |||
{ | { | |||
/* copy, handling resource management issues... */ | /* copy, handling resource management issues... */ | |||
*dst = *src; | *dst = *src; | |||
dst->selEntry = 0; | dst->selEntry = 0; | |||
if(src->unique_id && src->has_setting) { | if(src->unique_id && src->has_setting) { | |||
dst->unique_id = AtomInfoGetNewUniqueID(G); | dst->unique_id = AtomInfoGetNewUniqueID(G); | |||
skipping to change at line 1288 | skipping to change at line 1251 | |||
if(matchFlag && ((!flag1) || flag1[ai1 - atInfo1])) { | if(matchFlag && ((!flag1) || flag1[ai1 - atInfo1])) { | |||
if(c < 100) { | if(c < 100) { | |||
if((c < 10) && ai1->elem[1]) /* try to keep halogens 3 or under */ | if((c < 10) && ai1->elem[1]) /* try to keep halogens 3 or under */ | |||
sprintf(name, "%2s%1d", ai1->elem, c); | sprintf(name, "%2s%1d", ai1->elem, c); | |||
else | else | |||
sprintf(name, "%1s%02d", ai1->elem, c); | sprintf(name, "%1s%02d", ai1->elem, c); | |||
} else { | } else { | |||
sprintf(name, "%1d%1s%02d", c / 100, ai1->elem, c % 100); | sprintf(name, "%1d%1s%02d", c / 100, ai1->elem, c % 100); | |||
} | } | |||
name[4] = 0; /* just is case we go over */ | ||||
LexAssign(G, ai1->name, name); | LexAssign(G, ai1->name, name); | |||
result++; | result++; | |||
c = c + 1; | c = c + 1; | |||
} else { | } else { | |||
ai1++; | ai1++; | |||
b++; | b++; | |||
} | } | |||
} | } | |||
return result; | return result; | |||
} | } | |||
skipping to change at line 1903 | skipping to change at line 1865 | |||
{"lawrencium", "Lr", 1.80, 262.110000}, | {"lawrencium", "Lr", 1.80, 262.110000}, | |||
{"rutherfordium", "Rf", 1.80, 261.110000}, | {"rutherfordium", "Rf", 1.80, 261.110000}, | |||
{"dubnium", "Db", 1.80, 262.110000}, | {"dubnium", "Db", 1.80, 262.110000}, | |||
{"seaborgium", "Sg", 1.80, 266.120000}, | {"seaborgium", "Sg", 1.80, 266.120000}, | |||
{"bohrium", "Bh", 1.80, 264.120000}, | {"bohrium", "Bh", 1.80, 264.120000}, | |||
{"hassium", "Hs", 1.80, 269.130000}, | {"hassium", "Hs", 1.80, 269.130000}, | |||
{"meitnerium", "Mt", 1.80, 268.140000}, | {"meitnerium", "Mt", 1.80, 268.140000}, | |||
{"darmstadtium", "Ds", 1.80, 281.000000}, | {"darmstadtium", "Ds", 1.80, 281.000000}, | |||
{"roentgenium", "Rg", 1.80, 281.000000}, | {"roentgenium", "Rg", 1.80, 281.000000}, | |||
{"copernicium", "Cn", 1.80, 285.000000}, | {"copernicium", "Cn", 1.80, 285.000000}, | |||
{"nihonium", "Nh", 1.80, 286.000000}, | ||||
{"flerovium", "Fl", 1.80, 289.000000}, | ||||
{"moscovium", "Mc", 1.80, 290.000000}, | ||||
{"livermorium", "Lv", 1.80, 293.000000}, | ||||
{"tennessine", "Ts", 1.80, 294.000000}, | ||||
{"oganesson", "Og", 1.80, 294.000000}, | ||||
{NULL, NULL, 0.00, 0.000000} | {NULL, NULL, 0.00, 0.000000} | |||
}; | }; | |||
const int ElementTableSize = sizeof(ElementTable) / sizeof(ElementTable[0]) - 1; | const int ElementTableSize = sizeof(ElementTable) / sizeof(ElementTable[0]) - 1; | |||
/* | /* | |||
* Assign atomic color, or G->AtomInfo->CColor in case of carbon. | * Assign atomic color, or G->AtomInfo->CColor in case of carbon. | |||
*/ | */ | |||
void AtomInfoAssignColors(PyMOLGlobals * G, AtomInfoType * at1) | void AtomInfoAssignColors(PyMOLGlobals * G, AtomInfoType * at1) | |||
{ | { | |||
skipping to change at line 2072 | skipping to change at line 2040 | |||
if ((wc = WordCompare(G, at1->resn, at2->resn, true))) return wc; | if ((wc = WordCompare(G, at1->resn, at2->resn, true))) return wc; | |||
if (at1->discrete_state != at2->discrete_state) return (at1->discrete_state < at2->discrete_state) ? -1 : 1; | if (at1->discrete_state != at2->discrete_state) return (at1->discrete_state < at2->discrete_state) ? -1 : 1; | |||
// if this looks like a "bulk" het group with no residue number, then don't | // if this looks like a "bulk" het group with no residue number, then don't | |||
// compare by name/alt/priority (affects mmCIF with cif_use_auth=0) | // compare by name/alt/priority (affects mmCIF with cif_use_auth=0) | |||
if (!ignore_rank && !at1->resv && at1->hetatm) | if (!ignore_rank && !at1->resv && at1->hetatm) | |||
goto rank_compare; | goto rank_compare; | |||
if (at1->priority != at2->priority) return (at1->priority < at2->priority) ? - 1 : 1; | if (at1->priority != at2->priority) return (at1->priority < at2->priority) ? - 1 : 1; | |||
// empty alt code goes last: 'A' < 'B' < '' | // Changed (PyMOL 2.1): name before alt | |||
if ((wc = AtomInfoNameCompare(G, at1->name, at2->name))) return wc; | ||||
// Changed (PyMOL 2.1): empty alt goes first: '' < 'A' < 'B' | ||||
if (at1->alt[0] != at2->alt[0]) { | if (at1->alt[0] != at2->alt[0]) { | |||
if (!at2->alt[0]) return -1; | ||||
if (!at1->alt[0]) return 1; | ||||
return (at1->alt[0] < at2->alt[0]) ? -1 : 1; | return (at1->alt[0] < at2->alt[0]) ? -1 : 1; | |||
} | } | |||
if ((wc = AtomInfoNameCompare(G, at1->name, at2->name))) return wc; | ||||
rank_compare: | rank_compare: | |||
if (!ignore_rank && at1->rank != at2->rank) return (at1->rank < at2->rank) ? - 1 : 1; | if (!ignore_rank && at1->rank != at2->rank) return (at1->rank < at2->rank) ? - 1 : 1; | |||
return 0; | return 0; | |||
} | } | |||
int AtomInfoCompare(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfoTy pe * at2) | int AtomInfoCompare(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfoTy pe * at2) | |||
{ | { | |||
return AtomInfoCompare(G, at1, at2, false, false); | return AtomInfoCompare(G, at1, at2, false, false); | |||
} | } | |||
skipping to change at line 2107 | skipping to change at line 2074 | |||
int AtomInfoCompareIgnoreRank(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfoType * at2) | int AtomInfoCompareIgnoreRank(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfoType * at2) | |||
{ | { | |||
return AtomInfoCompare(G, at1, at2, false, true); | return AtomInfoCompare(G, at1, at2, false, true); | |||
} | } | |||
int AtomInfoCompareIgnoreHet(PyMOLGlobals * G, const AtomInfoType * at1, const A tomInfoType * at2) | int AtomInfoCompareIgnoreHet(PyMOLGlobals * G, const AtomInfoType * at1, const A tomInfoType * at2) | |||
{ | { | |||
return AtomInfoCompare(G, at1, at2, true, false); | return AtomInfoCompare(G, at1, at2, true, false); | |||
} | } | |||
/* | ||||
* Function only used for matching atoms of two aligned residues. | ||||
* | ||||
* Changed (PyMOL 2.1): | ||||
* Consider alt codes to be equal if at least one is empty. | ||||
* Otherwise, alt-code (C-alpha) atoms can't be aligned to non-alt atoms | ||||
* (also affects morphing). | ||||
*/ | ||||
int AtomInfoNameOrder(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfo Type * at2) | int AtomInfoNameOrder(PyMOLGlobals * G, const AtomInfoType * at1, const AtomInfo Type * at2) | |||
{ | { | |||
int result; | int result; | |||
if(at1->alt[0] == at2->alt[0]) { | if(at1->alt[0] == at2->alt[0] || !at1->alt[0] || !at2->alt[0]) { | |||
if(at1->priority == at2->priority) { | if(at1->priority == at2->priority) { | |||
result = AtomInfoNameCompare(G, at1->name, at2->name); | result = AtomInfoNameCompare(G, at1->name, at2->name); | |||
} else if(at1->priority < at2->priority) { | } else if(at1->priority < at2->priority) { | |||
result = -1; | result = -1; | |||
} else { | } else { | |||
result = 1; | result = 1; | |||
} | } | |||
} else if((!at2->alt[0]) || (at1->alt[0] && ((at1->alt[0] < at2->alt[0])))) { | } else if(at1->alt[0] < at2->alt[0]) { | |||
result = -1; | result = -1; | |||
} else { | } else { | |||
result = 1; | result = 1; | |||
} | } | |||
return (result); | return (result); | |||
} | } | |||
int AtomInfoSameResidue(PyMOLGlobals * G, const AtomInfoType * at1, const AtomIn foType * at2) | int AtomInfoSameResidue(PyMOLGlobals * G, const AtomInfoType * at1, const AtomIn foType * at2) | |||
{ | { | |||
return ( | return ( | |||
skipping to change at line 2371 | skipping to change at line 2346 | |||
if (lookup.empty()) { | if (lookup.empty()) { | |||
for (int i = 0; i < ElementTableSize; i++) | for (int i = 0; i < ElementTableSize; i++) | |||
lookup[ElementTable[i].symbol] = i; | lookup[ElementTable[i].symbol] = i; | |||
lookup["Q"] = cAN_H; | lookup["Q"] = cAN_H; | |||
lookup["D"] = cAN_H; | lookup["D"] = cAN_H; | |||
} | } | |||
// check second letter for lower case | // check second letter for lower case | |||
if (isupper(symbol[1])) { | if (isupper(symbol[1]) && strcmp(symbol, "LP") != 0) { | |||
UtilNCopy(titleized, symbol, 4); | UtilNCopy(titleized, symbol, 4); | |||
titleized[1] = tolower(symbol[1]); | titleized[1] = tolower(symbol[1]); | |||
symbol = titleized; | symbol = titleized; | |||
} | } | |||
// find in lookup dictionary | // find in lookup dictionary | |||
auto it = lookup.find(symbol); | auto it = lookup.find(symbol); | |||
if (it != lookup.end()) { | if (it != lookup.end()) { | |||
return it->second; | return it->second; | |||
skipping to change at line 2439 | skipping to change at line 2414 | |||
// elem from protons (except for LP, assume protons=0 if uninitialized) | // elem from protons (except for LP, assume protons=0 if uninitialized) | |||
if(!*e && I->protons > 0) { | if(!*e && I->protons > 0) { | |||
atomicnumber2elem(e, I->protons); | atomicnumber2elem(e, I->protons); | |||
} | } | |||
// elem from name | // elem from name | |||
if(!*e) { /* try to guess atomic type from name */ | if(!*e) { /* try to guess atomic type from name */ | |||
n = LexStr(G, I->name); | n = LexStr(G, I->name); | |||
while(((*n) >= '0') && ((*n) <= '9') && (*(n + 1))) | while(((*n) >= '0') && ((*n) <= '9') && (*(n + 1))) | |||
n++; | n++; | |||
while((((*n) >= 'A') && ((*n) <= 'Z')) || (((*n) >= 'a') && ((*n) <= 'z'))) | strncpy(e, n, cElemNameLen); | |||
{ | ||||
*(e++) = *(n++); | ||||
} | ||||
*e = 0; | ||||
e = I->elem; | ||||
switch (*e) { | switch (*e) { | |||
case '\0': | ||||
break; | ||||
case 'C': | case 'C': | |||
if(*(e + 1) == 'A') { | if(*(e + 1) == 'A') { | |||
if(!WordMatchExact(G, G->lex_const.CA, I->resn, true) | if(!WordMatchExact(G, G->lex_const.CA, I->resn, true) | |||
&& (!WordMatchExact(G, "CA+", LexStr(G, I->resn), true))) | && (!WordMatchExact(G, "CA+", LexStr(G, I->resn), true))) | |||
/* CA intpreted as carbon, not calcium */ | ||||
*(e + 1) = 0; | *(e + 1) = 0; | |||
} else if(!((*(e + 1) == 'a') || /* CA intpreted as carbon, not calcium * / | } else if(!((*(e + 1) == 'a') || /* CA intpreted as carbon, not calcium * / | |||
(*(e + 1) == 'l') || (*(e + 1) == 'L') || | (*(e + 1) == 'l') || (*(e + 1) == 'L') || | |||
(*(e + 1) == 'u') || (*(e + 1) == 'U') || | (*(e + 1) == 'u') || (*(e + 1) == 'U') || | |||
(*(e + 1) == 'o') || (*(e + 1) == 'O') || | (*(e + 1) == 'o') || (*(e + 1) == 'O') || | |||
(*(e + 1) == 's') || (*(e + 1) == 'S') || | (*(e + 1) == 's') || (*(e + 1) == 'S') || | |||
(*(e + 1) == 'r') || (*(e + 1) == 'R') | (*(e + 1) == 'r') || (*(e + 1) == 'R') | |||
)) | )) | |||
*(e + 1) = 0; | *(e + 1) = 0; | |||
break; | break; | |||
skipping to change at line 2490 | skipping to change at line 2464 | |||
*(e + 1) = 0; | *(e + 1) = 0; | |||
break; | break; | |||
case 'O': | case 'O': | |||
if(!((*(e + 1) == 's'))) | if(!((*(e + 1) == 's'))) | |||
*(e + 1) = 0; | *(e + 1) = 0; | |||
break; | break; | |||
case 'Q': | case 'Q': | |||
*(e + 1) = 0; | *(e + 1) = 0; | |||
break; | break; | |||
default: | ||||
break; | ||||
} | } | |||
if(*(e + 1)) | if(*(e + 1) && (e[1] != 'P' || e[0] != 'L')) | |||
*(e + 1) = tolower(*(e + 1)); | *(e + 1) = tolower(*(e + 1)); | |||
} | } | |||
// priority | // priority | |||
n = LexStr(G, I->name); | n = LexStr(G, I->name); | |||
while((*n >= '0') && (*n <= '9') && (*(n + 1))) | while((*n >= '0') && (*n <= '9') && (*(n + 1))) | |||
n++; | n++; | |||
if(toupper(*n) != I->elem[0]) { | if(toupper(*n) != I->elem[0]) { | |||
pri = 1000; /* unconventional atom name -- make no assignmen ts */ | pri = 1000; /* unconventional atom name -- make no assignmen ts */ | |||
} else if(SettingGetGlobal_b(G, cSetting_pdb_standard_order)) { | } else if(SettingGetGlobal_b(G, cSetting_pdb_standard_order)) { | |||
skipping to change at line 2825 | skipping to change at line 2797 | |||
bt1->id != bt2->id || | bt1->id != bt2->id || | |||
bt1->unique_id != bt2->unique_id || | bt1->unique_id != bt2->unique_id || | |||
bt1->stereo != bt2->stereo || | bt1->stereo != bt2->stereo || | |||
bt1->has_setting != bt2->has_setting); | bt1->has_setting != bt2->has_setting); | |||
} | } | |||
void atomicnumber2elem(char * dst, int protons) { | void atomicnumber2elem(char * dst, int protons) { | |||
if (protons > -1 && protons < ElementTableSize) | if (protons > -1 && protons < ElementTableSize) | |||
strncpy(dst, ElementTable[protons].symbol, cElemNameLen); | strncpy(dst, ElementTable[protons].symbol, cElemNameLen); | |||
} | } | |||
/* | ||||
* Get a string representation of the stereo configuration. Either | ||||
* R/S chirality, if set, or the SDF odd/even parity, if set. | ||||
*/ | ||||
const char * AtomInfoGetStereoAsStr(const AtomInfoType * ai) { | ||||
switch (ai->mmstereo) { | ||||
case 1 /* MMSTEREO_CHIRALITY_R */: return "R"; | ||||
case 2 /* MMSTEREO_CHIRALITY_S */: return "S"; | ||||
} | ||||
switch (ai->stereo) { | ||||
case SDF_CHIRALITY_ODD: return "odd"; | ||||
case SDF_CHIRALITY_EVEN: return "even"; | ||||
} | ||||
if (ai->mmstereo || ai->stereo) { | ||||
return "?"; | ||||
} | ||||
return ""; | ||||
} | ||||
/* | ||||
* Set stereochemistry. Valid are: R, S, N[one], E[ven], O[dd] | ||||
*/ | ||||
void AtomInfoSetStereo(AtomInfoType * ai, const char * stereo) { | ||||
switch (toupper(stereo[0])) { | ||||
case 'R': ai->mmstereo = 1; ai->stereo = 0; break; // MMSTEREO_CHIRALITY_R | ||||
case 'S': ai->mmstereo = 2; ai->stereo = 0; break; // MMSTEREO_CHIRALITY_S | ||||
case 'E': ai->mmstereo = 0; ai->stereo = SDF_CHIRALITY_EVEN; break; | ||||
case 'O': ai->mmstereo = 0; ai->stereo = SDF_CHIRALITY_ODD; break; | ||||
case 'N': case 0: ai->mmstereo = ai->stereo = 0; break; | ||||
default: ai->mmstereo = ai->stereo = 3; break; | ||||
} | ||||
} | ||||
/* | ||||
* Get column aligned (left space padded) PDB residue name | ||||
* | ||||
* resn: output buffer | ||||
*/ | ||||
void AtomInfoGetAlignedPDBResidueName(PyMOLGlobals * G, | ||||
const AtomInfoType * ai, | ||||
ResName & resn) | ||||
{ | ||||
sprintf(resn, "%3.4s", LexStr(G, ai->resn)); | ||||
if(SettingGetGlobal_b(G, cSetting_pdb_truncate_residue_name)) { | ||||
resn[3] = 0; /* enforce 3-letter residue name in PDB files */ | ||||
} | ||||
} | ||||
/* | ||||
* Get column aligned (left space padded) PDB atom name | ||||
* | ||||
* resn: space padded residue name | ||||
* name: output buffer | ||||
*/ | ||||
void AtomInfoGetAlignedPDBAtomName(PyMOLGlobals * G, | ||||
const AtomInfoType * ai, | ||||
const ResName & resn, | ||||
AtomName & name) | ||||
{ | ||||
int literal = SettingGetGlobal_b(G, cSetting_pdb_literal_names); | ||||
int reformat = SettingGetGlobal_i(G, cSetting_pdb_reformat_names_mode); | ||||
// default is "literal=0" and "reformat=0" (no reformatting) | ||||
const char * ai_name = LexStr(G, ai->name); | ||||
auto ai_name_len = strlen(ai_name); | ||||
bool start_column_1 = false; | ||||
UtilNCopy(name, ai_name, 5); | ||||
if(!ai->name) { | ||||
if(!ai->elem[1]) | ||||
sprintf(name, " %s", ai->elem); | ||||
else | ||||
sprintf(name, "%s", ai->elem); | ||||
} else if(!literal) { | ||||
if(ai_name_len < 4) { /* atom name less than length 4 */ | ||||
if(!isdigit(name[0])) { /* doesn't start with a number */ | ||||
if((toupper(ai->elem[0]) == toupper(name[0])) && ((!ai->elem[1]) || /* s | ||||
ymbol len = 1 */ | ||||
(toupper(ai->elem[1]) == toupper(name[1])))) { /* matched l | ||||
en 2 */ | ||||
/* starts with corrent atomic symbol, so */ | ||||
if(!ai->elem[1]) { /* symbol len = 1 */ | ||||
switch (reformat) { | ||||
case 1: /* pdb with internal pdb */ | ||||
case 3: /* pdb with internal iupac */ | ||||
if((ai->elem[0] == 'H') && ai_name_len > 2) { | ||||
AtomInfoGetPDB3LetHydroName(G, resn, ai_name, name); | ||||
break; | ||||
} | ||||
default: /* otherwise, start in column 1 */ | ||||
start_column_1 = true; | ||||
break; | ||||
} | ||||
} | ||||
} else { /* name doesn't start with atomic symbol */ | ||||
/* then just place it in column 1 as usual */ | ||||
start_column_1 = true; | ||||
} | ||||
} else { /* name starts with a number */ | ||||
switch (reformat) { | ||||
case 2: /* make Amber compliant */ | ||||
if((ai->elem[0] == name[1]) && | ||||
((!ai->elem[1]) || (toupper(ai->elem[1]) == toupper(name[2])))) { | ||||
/* rotate the name to place atom symbol in column 0 to comply with A | ||||
mber PDB format */ | ||||
name[3] = name[0]; | ||||
name[0] = ' '; | ||||
} | ||||
break; | ||||
} | ||||
} /* just stick it in column 0 and hope for the be | ||||
st */ | ||||
} else { /* if name is length 4 */ | ||||
if((ai->elem[0] == name[0]) && ((!ai->elem[1]) || /* symbol len = 1 */ | ||||
(toupper(ai->elem[1]) == toupper(name[ | ||||
1])))) { /* matched len 2 */ | ||||
/* name starts with the atomic symbol */ | ||||
if((!ai->elem[1]) && (ai->elem[0])) { /* but if element is one letter. | ||||
.. */ | ||||
switch (reformat) { | ||||
case 1: /* retaining PDB compliance throughout, or */ | ||||
case 3: /* saving as PDB compliant, but use IUPAC within | ||||
PyMOL */ | ||||
if(isdigit(name[3])) { /* and last character is a number */ | ||||
/* rotate the name to place atom symbol in column 1 to comply with | ||||
PDB format */ | ||||
name[0] = ai_name[3]; | ||||
name[1] = ai_name[0]; | ||||
name[2] = ai_name[1]; | ||||
name[3] = ai_name[2]; | ||||
name[4] = 0; | ||||
} | ||||
break; | ||||
} | ||||
} | ||||
} else { /* name does not start with the symbol... */ | ||||
if(reformat == 2) { /* AMBER compliance mode */ | ||||
if(isdigit(name[0])) { | ||||
if((ai->elem[0] == name[1]) && | ||||
((!(ai->elem[1])) || (toupper(ai->elem[1]) == toupper(name[2])))) | ||||
{ | ||||
/* rotate the name to place atom symbol in column 0 to comply with | ||||
Amber PDB format */ | ||||
name[0] = ai_name[1]; | ||||
name[1] = ai_name[2]; | ||||
name[2] = ai_name[3]; | ||||
name[3] = ai_name[0]; | ||||
name[4] = 0; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} else { /* LITERAL mode: preserve what was in the origin | ||||
al PDB as best PyMOL can | ||||
this should enable people to open and save am | ||||
ber pdb files without issues */ | ||||
if (ai_name_len < 4 && !(ai->elem[1] && /* elem len = 2 */ | ||||
toupper(ai->elem[0]) == toupper(name[0]) && | ||||
toupper(ai->elem[1]) == toupper(name[1]))) { | ||||
start_column_1 = true; | ||||
} | ||||
} | ||||
if (start_column_1) { | ||||
name[0] = ' '; | ||||
UtilNCopy(name + 1, ai_name, 4); | ||||
} | ||||
name[4] = 0; | ||||
} | ||||
End of changes. 27 change blocks. | ||||
83 lines changed or deleted | 54 lines changed or added |