MoleculeExporter.cpp (pymol-open-source-2.2.0) | : | MoleculeExporter.cpp (pymol-open-source-2.3.0) | ||
---|---|---|---|---|
skipping to change at line 12 | skipping to change at line 12 | |||
* Molecular file formats export | * Molecular file formats export | |||
* | * | |||
* (c) 2016 Schrodinger, Inc. | * (c) 2016 Schrodinger, Inc. | |||
*/ | */ | |||
#include <vector> | #include <vector> | |||
#include <map> | #include <map> | |||
#include <algorithm> | #include <algorithm> | |||
#include <cstdarg> | #include <cstdarg> | |||
#include <clocale> | #include <clocale> | |||
#include <memory> | ||||
#ifndef _PYMOL_NO_MSGPACKC | ||||
#include <mmtf.hpp> | ||||
#include <mmtf/export_helpers.hpp> | ||||
#endif | ||||
#include "os_std.h" | #include "os_std.h" | |||
#include "MoleculeExporter.h" | #include "MoleculeExporter.h" | |||
#include "Selector.h" | #include "Selector.h" | |||
#include "SelectorDef.h" | #include "SelectorDef.h" | |||
#include "Executive.h" | #include "Executive.h" | |||
#include "Vector.h" | #include "Vector.h" | |||
#include "ObjectMolecule.h" | #include "ObjectMolecule.h" | |||
#include "CoordSet.h" | #include "CoordSet.h" | |||
#include "Mol2Typing.h" | #include "Mol2Typing.h" | |||
#include "MmodTyping.h" | #include "MmodTyping.h" | |||
#include "Color.h" | #include "Color.h" | |||
#include "Util.h" | #include "Util.h" | |||
#include "Lex.h" | #include "Lex.h" | |||
#include "P.h" | #include "P.h" | |||
#include "PConv.h" | #include "PConv.h" | |||
#include "CifDataValueFormatter.h" | #include "CifDataValueFormatter.h" | |||
#include "MaeExportHelpers.h" | #include "MaeExportHelpers.h" | |||
#ifdef _PYMOL_IP_EXTRAS | #ifdef _PYMOL_IP_PROPERTIES | |||
#include "Property.h" | #include "Property.h" | |||
#endif | #endif | |||
#ifdef _PYMOL_NO_CXX11 | ||||
#define emplace_back push_back | ||||
#endif | ||||
/* | /* | |||
* Get the capitalized element symbol. Assume that ai->elem is either all | * Get the capitalized element symbol. Assume that ai->elem is either all | |||
* caps (e.g. loaded from PDB) or capitalized. | * caps (e.g. loaded from PDB) or capitalized. | |||
*/ | */ | |||
class ElemCanonicalizer { | class ElemCanonicalizer { | |||
ElemName m_buffer; | ElemName m_buffer; | |||
public: | public: | |||
const char * operator() (const AtomInfoType * ai) { | const char * operator() (const AtomInfoType * ai) { | |||
const char * elem = ai->elem; | const char * elem = ai->elem; | |||
if (ai->protons < 1 || !elem[0] || !elem[1] || islower(elem[1])) | if (ai->protons < 1 || !elem[0] || !elem[1] || islower(elem[1])) | |||
skipping to change at line 64 | skipping to change at line 66 | |||
} | } | |||
}; | }; | |||
/* | /* | |||
* "sprintf" into VLA string buffer. Will grow (and reallocate) the VLA if | * "sprintf" into VLA string buffer. Will grow (and reallocate) the VLA if | |||
* needed. | * needed. | |||
* | * | |||
* Returns the number of characters written (excluding the null byte). | * Returns the number of characters written (excluding the null byte). | |||
*/ | */ | |||
static | static | |||
int VLAprintf(char *&vla, int offset, const char * format, ...) { | int VLAprintf(pymol::vla<char>& vla, int offset, const char * format, ...) { | |||
int n, size = VLAGetSize(vla) - offset; | int n, size = vla.size() - offset; | |||
va_list ap; | va_list ap; | |||
va_start(ap, format); | va_start(ap, format); | |||
n = vsnprintf(vla + offset, std::max(0, size), format, ap); | n = vsnprintf(vla + offset, std::max(0, size), format, ap); | |||
va_end(ap); | va_end(ap); | |||
#ifdef WIN32 | #ifdef WIN32 | |||
// Windows API: If len > count, then count characters are stored in buffer, | // Windows API: If len > count, then count characters are stored in buffer, | |||
// no null-terminator is appended, and a negative value is returned. | // no null-terminator is appended, and a negative value is returned. | |||
if (n < 0) { | if (n < 0) { | |||
va_start(ap, format); | va_start(ap, format); | |||
n = _vscprintf(format, ap); | n = _vscprintf(format, ap); | |||
va_end(ap); | va_end(ap); | |||
} | } | |||
#endif | #endif | |||
// C99 standard: a return value of size or more means that the output was | // C99 standard: a return value of size or more means that the output was | |||
// truncated (glibc since 2.1; not on Windows) | // truncated (glibc since 2.1; not on Windows) | |||
if (n >= size) { | if (n >= size) { | |||
VLACheck(vla, char, offset + n); | vla.check(offset + n); | |||
va_start(ap, format); | va_start(ap, format); | |||
vsprintf(vla + offset, format, ap); | vsprintf(vla + offset, format, ap); | |||
va_end(ap); | va_end(ap); | |||
} | } | |||
return n; | return n; | |||
} | } | |||
// for "multisave" behavior | // for "multisave" behavior | |||
enum { | enum { | |||
skipping to change at line 118 | skipping to change at line 120 | |||
struct AtomRef { | struct AtomRef { | |||
AtomInfoType * ref; | AtomInfoType * ref; | |||
float coord[3]; | float coord[3]; | |||
int id; | int id; | |||
}; | }; | |||
/* | /* | |||
* Abstract base class for exporting molecular selections | * Abstract base class for exporting molecular selections | |||
*/ | */ | |||
struct MoleculeExporter { | struct MoleculeExporter { | |||
char* m_buffer; // out | pymol::vla<char> m_buffer; // out | |||
int m_offset; | ||||
protected: | protected: | |||
int m_offset; | ||||
CoordSet * m_last_cs; | CoordSet * m_last_cs; | |||
ObjectMolecule * m_last_obj; | ObjectMolecule * m_last_obj; | |||
int m_last_state; | int m_last_state; | |||
PyMOLGlobals * G; | PyMOLGlobals * G; | |||
SeleCoordIterator m_iter; | SeleCoordIterator m_iter; | |||
bool m_retain_ids; | bool m_retain_ids; | |||
int m_id; | int m_id; | |||
skipping to change at line 156 | skipping to change at line 158 | |||
int m_multi; | int m_multi; | |||
std::vector<BondRef> m_bonds; | std::vector<BondRef> m_bonds; | |||
std::vector<int> m_tmpids; | std::vector<int> m_tmpids; | |||
public: | public: | |||
// quasi constructor (easier to inherit than a real constructor) | // quasi constructor (easier to inherit than a real constructor) | |||
virtual void init(PyMOLGlobals * G_) { | virtual void init(PyMOLGlobals * G_) { | |||
G = G_; | G = G_; | |||
m_buffer = VLAlloc(char, 1280); | m_buffer.resize(1280); | |||
m_buffer[0] = '\0'; | m_buffer[0] = '\0'; | |||
m_mat_ref.ptr = NULL; | m_mat_ref.ptr = nullptr; | |||
m_offset = 0; | m_offset = 0; | |||
m_last_cs = NULL; | m_last_cs = nullptr; | |||
m_last_obj = NULL; | m_last_obj = nullptr; | |||
m_last_state = -1; | m_last_state = -1; | |||
m_retain_ids = false; | m_retain_ids = false; | |||
m_id = 0; | m_id = 0; | |||
setMulti(getMultiDefault()); | setMulti(getMultiDefault()); | |||
} | } | |||
// destructor | // destructor | |||
virtual ~MoleculeExporter() { | virtual ~MoleculeExporter() = default; | |||
VLAFreeP(m_buffer); | ||||
} | ||||
/* | /* | |||
* Do the export (e.g. populate "m_buffer" with file contents) | * Do the export (e.g. populate "m_buffer" with file contents) | |||
*/ | */ | |||
void execute(int sele, int state); | void execute(int sele, int state); | |||
/* | /* | |||
* how to handle selections which span multiple objects | * how to handle selections which span multiple objects | |||
*/ | */ | |||
void setMulti(int multi) { | void setMulti(int multi) { | |||
skipping to change at line 360 | skipping to change at line 360 | |||
endCoordSet(); | endCoordSet(); | |||
if (m_last_obj) | if (m_last_obj) | |||
endObject(); | endObject(); | |||
else if (m_multi == cMolExportGlobal) | else if (m_multi == cMolExportGlobal) | |||
// empty selection | // empty selection | |||
beginMolecule(); | beginMolecule(); | |||
if (m_multi == cMolExportGlobal) { | if (m_multi == cMolExportGlobal) { | |||
writeBonds(); | writeBonds(); | |||
} | } | |||
m_buffer.resize(m_offset); | ||||
} | } | |||
void MoleculeExporter::setRefObject(const char * ref_object, int ref_state) { | void MoleculeExporter::setRefObject(const char * ref_object, int ref_state) { | |||
double matrix[16]; | double matrix[16]; | |||
m_mat_ref.ptr = NULL; | m_mat_ref.ptr = nullptr; | |||
if (!ref_object || !ref_object[0]) | if (!ref_object || !ref_object[0]) | |||
return; | return; | |||
auto base = ExecutiveFindObjectByName(G, ref_object); | auto base = ExecutiveFindObjectByName(G, ref_object); | |||
if (!base) | if (!base) | |||
return; | return; | |||
if(ref_state < 0) { | if(ref_state < 0) { | |||
ref_state = ObjectGetCurrentState(base, true); | ref_state = ObjectGetCurrentState(base, true); | |||
skipping to change at line 428 | skipping to change at line 430 | |||
m_bonds.emplace_back(BondRef { bond, id1, id2 }); | m_bonds.emplace_back(BondRef { bond, id1, id2 }); | |||
} | } | |||
} | } | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterPDB : public MoleculeExporter { | struct MoleculeExporterPDB : public MoleculeExporter { | |||
bool m_conect_all; | bool m_conect_all; | |||
bool m_conect_nodup; | bool m_conect_nodup; | |||
bool m_mdl_written; | bool m_mdl_written; | |||
bool m_use_ter_records; | ||||
const AtomInfoType * m_pre_ter = nullptr; | ||||
PDBInfoRec m_pdb_info; | PDBInfoRec m_pdb_info; | |||
// quasi constructor | // quasi constructor | |||
void init(PyMOLGlobals * G_) { | void init(PyMOLGlobals * G_) override { | |||
MoleculeExporter::init(G_); | MoleculeExporter::init(G_); | |||
UtilZeroMem((void *) &m_pdb_info, sizeof(PDBInfoRec)); | UtilZeroMem((void *) &m_pdb_info, sizeof(PDBInfoRec)); | |||
m_conect_all = false; | m_conect_all = false; | |||
m_mdl_written = false; | m_mdl_written = false; | |||
m_conect_nodup = SettingGetGlobal_b(G, cSetting_pdb_conect_nodup); | m_conect_nodup = SettingGetGlobal_b(G, cSetting_pdb_conect_nodup); | |||
m_retain_ids = SettingGetGlobal_b(G, cSetting_pdb_retain_ids); | m_retain_ids = SettingGetGlobal_b(G, cSetting_pdb_retain_ids); | |||
m_use_ter_records = SettingGetGlobal_b(G, cSetting_pdb_use_ter_records); | ||||
} | } | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// single entry format by default, but we also support writing multiple | // single entry format by default, but we also support writing multiple | |||
// entries by writing a HEADER record for every object (1) or state (2) | // entries by writing a HEADER record for every object (1) or state (2) | |||
return cMolExportGlobal; | return cMolExportGlobal; | |||
} | } | |||
void writeENDMDL() { | void writeENDMDL() { | |||
if (m_mdl_written) { | if (m_mdl_written) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "ENDMDL\n"); | m_offset += VLAprintf(m_buffer, m_offset, "ENDMDL\n"); | |||
m_mdl_written = false; | m_mdl_written = false; | |||
} | } | |||
} | } | |||
void writeEND() { | void writeEND() { | |||
if (!SettingGetGlobal_b(G, cSetting_pdb_no_end_record)) { | if (!SettingGetGlobal_b(G, cSetting_pdb_no_end_record)) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "END\n"); | m_offset += VLAprintf(m_buffer, m_offset, "END\n"); | |||
} | } | |||
} | } | |||
void writeAtom() { | /* | |||
* Write a TER record if the previous atom was polymer and `ai` | ||||
* is NULL, non-polymer, or has a different chain identifier. | ||||
*/ | ||||
void writeTER(const AtomInfoType* ai) { | ||||
if (!m_use_ter_records) | ||||
return; | ||||
if (ai && !(ai->flags & cAtomFlag_polymer)) { | ||||
ai = nullptr; | ||||
} | ||||
if (m_pre_ter && !(ai && ai->chain == m_pre_ter->chain)) { | ||||
m_offset += VLAprintf(m_buffer, m_offset, "TER \n"); | ||||
} | ||||
m_pre_ter = ai; | ||||
} | ||||
void writeAtom() override { | ||||
writeTER(m_iter.getAtomInfo()); | ||||
CoordSetAtomToPDBStrVLA(G, &m_buffer, &m_offset, m_iter.getAtomInfo(), | CoordSetAtomToPDBStrVLA(G, &m_buffer, &m_offset, m_iter.getAtomInfo(), | |||
m_coord, getTmpID() - 1, &m_pdb_info, m_mat_full.ptr); | m_coord, getTmpID() - 1, &m_pdb_info, m_mat_full.ptr); | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
writeENDMDL(); | writeENDMDL(); | |||
std::map<int, std::vector<int>> conect; | std::map<int, std::vector<int>> conect; | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) { | for (auto& bond : m_bonds) { | |||
auto& bond = *bond_it; | ||||
int order = m_conect_nodup ? 1 : bond.ref->order; | int order = m_conect_nodup ? 1 : bond.ref->order; | |||
for (int i = 0; i < 2; ++i) { | for (int i = 0; i < 2; ++i) { | |||
for (int d = 0; d < order; ++d) { | for (int d = 0; d < order; ++d) { | |||
conect[bond.id1].push_back(bond.id2); | conect[bond.id1].push_back(bond.id2); | |||
} | } | |||
std::swap(bond.id1, bond.id2); | std::swap(bond.id1, bond.id2); | |||
} | } | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
for (auto rec_it = conect.begin(); rec_it != conect.end(); ++rec_it) { | for (auto& rec : conect) { | |||
const auto& rec = *rec_it; | ||||
for (int i = 0, i_end = rec.second.size(); i != i_end;) { | for (int i = 0, i_end = rec.second.size(); i != i_end;) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "CONECT%5d", rec.first); | m_offset += VLAprintf(m_buffer, m_offset, "CONECT%5d", rec.first); | |||
// up to 4 bonds per record | // up to 4 bonds per record | |||
for (int j = std::min(i + 4, i_end); i != j; ++i) { | for (int j = std::min(i + 4, i_end); i != j; ++i) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "%5d", rec.second[i]); | m_offset += VLAprintf(m_buffer, m_offset, "%5d", rec.second[i]); | |||
} | } | |||
m_offset += VLAprintf(m_buffer, m_offset, "\n"); | m_offset += VLAprintf(m_buffer, m_offset, "\n"); | |||
} | } | |||
} | } | |||
skipping to change at line 512 | skipping to change at line 536 | |||
if (sym && sym->Crystal) { | if (sym && sym->Crystal) { | |||
const auto& dim = sym->Crystal->Dim; | const auto& dim = sym->Crystal->Dim; | |||
const auto& angle = sym->Crystal->Angle; | const auto& angle = sym->Crystal->Angle; | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s%4d\n", | "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s%4d\n", | |||
dim[0], dim[1], dim[2], angle[0], angle[1], angle[2], | dim[0], dim[1], dim[2], angle[0], angle[1], angle[2], | |||
sym->SpaceGroup, sym->PDBZValue); | sym->SpaceGroup, sym->PDBZValue); | |||
} | } | |||
} | } | |||
void beginObject() { | void beginObject() override { | |||
MoleculeExporter::beginObject(); | MoleculeExporter::beginObject(); | |||
m_conect_all = SettingGet_b(G, m_iter.obj->Obj.Setting, NULL, cSetting_pdb_c onect_all); | m_conect_all = SettingGet_b(G, m_iter.obj->Obj.Setting, nullptr, cSetting_pd b_conect_all); | |||
if (m_multi == cMolExportByObject) { | if (m_multi == cMolExportByObject) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "HEADER %.40s\n", m_iter.obj- >Obj.Name); | m_offset += VLAprintf(m_buffer, m_offset, "HEADER %.40s\n", m_iter.obj- >Obj.Name); | |||
writeCryst1(); | writeCryst1(); | |||
} | } | |||
} | } | |||
void beginCoordSet() { | void beginCoordSet() override { | |||
MoleculeExporter::beginCoordSet(); | MoleculeExporter::beginCoordSet(); | |||
if (m_multi == cMolExportByCoordSet) { | if (m_multi == cMolExportByCoordSet) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "HEADER %.40s\n", getTitleOrN ame()); | m_offset += VLAprintf(m_buffer, m_offset, "HEADER %.40s\n", getTitleOrN ame()); | |||
writeCryst1(); | writeCryst1(); | |||
} | } | |||
if (m_iter.isMultistate() | if (m_iter.isMultistate() | |||
&& (m_iter.isPerObject() || m_iter.state != m_last_state)) { | && (m_iter.isPerObject() || m_iter.state != m_last_state)) { | |||
m_offset += VLAprintf(m_buffer, m_offset, "MODEL %4d\n", m_iter.state + 1); | m_offset += VLAprintf(m_buffer, m_offset, "MODEL %4d\n", m_iter.state + 1); | |||
m_last_state = m_iter.state; | m_last_state = m_iter.state; | |||
m_mdl_written = true; | m_mdl_written = true; | |||
} | } | |||
} | } | |||
void endCoordSet() { | void endCoordSet() override { | |||
writeTER(nullptr); | ||||
MoleculeExporter::endCoordSet(); | MoleculeExporter::endCoordSet(); | |||
if (m_iter.isPerObject() || m_iter.state != m_last_state) { | if (m_iter.isPerObject() || m_iter.state != m_last_state) { | |||
writeENDMDL(); | writeENDMDL(); | |||
} | } | |||
} | } | |||
bool isExcludedBond(int atm1, int atm2) { | bool isExcludedBond(int atm1, int atm2) override { | |||
const auto& atInfo = m_last_obj->AtomInfo; | const auto& atInfo = m_last_obj->AtomInfo; | |||
return !(m_conect_all || atInfo[atm1].hetatm || atInfo[atm2].hetatm); | return !(m_conect_all || atInfo[atm1].hetatm || atInfo[atm2].hetatm); | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterPQR: public MoleculeExporterPDB { | struct MoleculeExporterPQR: public MoleculeExporterPDB { | |||
// quasi constructor | // quasi constructor | |||
void init(PyMOLGlobals * G_) { | void init(PyMOLGlobals * G_) override { | |||
MoleculeExporterPDB::init(G_); | MoleculeExporterPDB::init(G_); | |||
m_pdb_info.variant = PDB_VARIANT_PQR; | m_pdb_info.variant = PDB_VARIANT_PQR; | |||
m_pdb_info.pqr_workarounds = SettingGetGlobal_b(G, cSetting_pqr_workarounds) ; | m_pdb_info.pqr_workarounds = SettingGetGlobal_b(G, cSetting_pqr_workarounds) ; | |||
} | } | |||
bool isExcludedBond(int atm1, int atm2) { | bool isExcludedBond(int atm1, int atm2) override { | |||
// no bonds for PQR format | // no bonds for PQR format | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterCIF : public MoleculeExporter { | struct MoleculeExporterCIF : public MoleculeExporter { | |||
const char * m_molecule_name; | const char * m_molecule_name; | |||
CifDataValueFormatter cifrepr; | CifDataValueFormatter cifrepr; | |||
// quasi constructor | // quasi constructor | |||
void init(PyMOLGlobals * G_) { | void init(PyMOLGlobals * G_) override { | |||
MoleculeExporter::init(G_); | MoleculeExporter::init(G_); | |||
// The formatter uses a circular buffer of the given size. The size | // The formatter uses a circular buffer of the given size. The size | |||
// must be at least equal to the maximum number of invocations of `cifrepr` | // must be at least equal to the maximum number of invocations of `cifrepr` | |||
// in any member function (count two for each call with type `char`). | // in any member function (count two for each call with type `char`). | |||
cifrepr.m_buf.resize(10); | cifrepr.m_buf.resize(10); | |||
m_retain_ids = SettingGetGlobal_b(G, cSetting_pdb_retain_ids); | m_retain_ids = SettingGetGlobal_b(G, cSetting_pdb_retain_ids); | |||
m_molecule_name = "multi"; | m_molecule_name = "multi"; | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"# generated by PyMOL " _PyMOL_VERSION "\n"); | "# generated by PyMOL " _PyMOL_VERSION "\n"); | |||
} | } | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
return cMolExportByObject; | return cMolExportByObject; | |||
} | } | |||
void writeCellSymmetry() { | void writeCellSymmetry() { | |||
const auto& sym = m_iter.cs->Symmetry ? m_iter.cs->Symmetry : m_iter.obj->Sy mmetry; | const auto& sym = m_iter.cs->Symmetry ? m_iter.cs->Symmetry : m_iter.obj->Sy mmetry; | |||
if (sym && sym->Crystal) { | if (sym && sym->Crystal) { | |||
const auto& dim = sym->Crystal->Dim; | const auto& dim = sym->Crystal->Dim; | |||
const auto& angle = sym->Crystal->Angle; | const auto& angle = sym->Crystal->Angle; | |||
m_offset += VLAprintf(m_buffer, m_offset, "#\n" | m_offset += VLAprintf(m_buffer, m_offset, "#\n" | |||
skipping to change at line 619 | skipping to change at line 645 | |||
"_cell.angle_gamma %.2f\n" | "_cell.angle_gamma %.2f\n" | |||
"_symmetry.entry_id %s\n" | "_symmetry.entry_id %s\n" | |||
"_symmetry.space_group_name_H-M %s\n", | "_symmetry.space_group_name_H-M %s\n", | |||
cifrepr(m_molecule_name), | cifrepr(m_molecule_name), | |||
dim[0], dim[1], dim[2], angle[0], angle[1], angle[2], | dim[0], dim[1], dim[2], angle[0], angle[1], angle[2], | |||
cifrepr(m_molecule_name), | cifrepr(m_molecule_name), | |||
cifrepr(sym->SpaceGroup)); | cifrepr(sym->SpaceGroup)); | |||
} | } | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
switch (m_multi) { | switch (m_multi) { | |||
case cMolExportByObject: m_molecule_name = m_iter.obj->Obj.Name; break; | case cMolExportByObject: m_molecule_name = m_iter.obj->Obj.Name; break; | |||
case cMolExportByCoordSet: m_molecule_name = getTitleOrName(); break; | case cMolExportByCoordSet: m_molecule_name = getTitleOrName(); break; | |||
} | } | |||
// data header | // data header | |||
m_offset += VLAprintf(m_buffer, m_offset, "#\n" | m_offset += VLAprintf(m_buffer, m_offset, "#\n" | |||
"data_%s\n_entry.id %s\n", m_molecule_name, | "data_%s\n_entry.id %s\n", m_molecule_name, | |||
skipping to change at line 658 | skipping to change at line 684 | |||
"_atom_site.Cartn_x\n" | "_atom_site.Cartn_x\n" | |||
"_atom_site.Cartn_y\n" | "_atom_site.Cartn_y\n" | |||
"_atom_site.Cartn_z\n" | "_atom_site.Cartn_z\n" | |||
"_atom_site.occupancy\n" | "_atom_site.occupancy\n" | |||
"_atom_site.B_iso_or_equiv\n" | "_atom_site.B_iso_or_equiv\n" | |||
"_atom_site.pdbx_formal_charge\n" | "_atom_site.pdbx_formal_charge\n" | |||
"_atom_site.auth_asym_id\n" | "_atom_site.auth_asym_id\n" | |||
"_atom_site.pdbx_PDB_model_num\n"); | "_atom_site.pdbx_PDB_model_num\n"); | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
const AtomInfoType * ai = m_iter.getAtomInfo(); | const AtomInfoType * ai = m_iter.getAtomInfo(); | |||
const char * entity_id = NULL; | const char * entity_id = nullptr; | |||
#ifdef _PYMOL_IP_EXTRAS | #ifdef _PYMOL_IP_PROPERTIES | |||
char entity_id_buf[16]; | char entity_id_buf[16]; | |||
if (ai->prop_id) { | if (ai->prop_id) { | |||
entity_id = PropertyGetAsString(G, ai->prop_id, "entity_id", entity_id_buf ); | entity_id = PropertyGetAsString(G, ai->prop_id, "entity_id", entity_id_buf ); | |||
} | } | |||
#endif | #endif | |||
if (!entity_id) { | if (!entity_id) { | |||
entity_id = LexStr(G, ai->custom); | entity_id = LexStr(G, ai->custom); | |||
} | } | |||
skipping to change at line 694 | skipping to change at line 720 | |||
cifrepr(LexStr(G, ai->segi)), | cifrepr(LexStr(G, ai->segi)), | |||
cifrepr(entity_id), | cifrepr(entity_id), | |||
ai->resv, | ai->resv, | |||
cifrepr(ai->inscode, "?"), | cifrepr(ai->inscode, "?"), | |||
m_coord[0], m_coord[1], m_coord[2], | m_coord[0], m_coord[1], m_coord[2], | |||
ai->q, ai->b, ai->formalCharge, | ai->q, ai->b, ai->formalCharge, | |||
cifrepr(LexStr(G, ai->chain)), | cifrepr(LexStr(G, ai->chain)), | |||
m_iter.state + 1); | m_iter.state + 1); | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
// TODO | // TODO | |||
// Bond categories: | // Bond categories: | |||
// 1) within residue -> _chem_comp_bond | // 1) within residue -> _chem_comp_bond | |||
// 2) polymer links -> implicit | // 2) polymer links -> implicit | |||
// 3) others -> _struct_conn | // 3) others -> _struct_conn | |||
m_bonds.clear(); | m_bonds.clear(); | |||
} | } | |||
bool isExcludedBond(int atm1, int atm2) { | bool isExcludedBond(int atm1, int atm2) override { | |||
// TODO | // TODO | |||
// polymer links | // polymer links | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
/* | /* | |||
* Experimental PyMOL style annotated mmCIF. Exports colors, representation, | * Experimental PyMOL style annotated mmCIF. Exports colors, representation, | |||
* and secondary structure. | * and secondary structure. | |||
*/ | */ | |||
struct MoleculeExporterPMCIF : public MoleculeExporterCIF { | struct MoleculeExporterPMCIF : public MoleculeExporterCIF { | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporterCIF::beginMolecule(); | MoleculeExporterCIF::beginMolecule(); | |||
m_offset += VLAprintf(m_buffer, m_offset, "#\n" | m_offset += VLAprintf(m_buffer, m_offset, "#\n" | |||
"_atom_site.pymol_color\n" | "_atom_site.pymol_color\n" | |||
"_atom_site.pymol_reps\n" | "_atom_site.pymol_reps\n" | |||
"_atom_site.pymol_ss\n"); | "_atom_site.pymol_ss\n"); | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
MoleculeExporterCIF::writeAtom(); | MoleculeExporterCIF::writeAtom(); | |||
const AtomInfoType * ai = m_iter.getAtomInfo(); | const AtomInfoType * ai = m_iter.getAtomInfo(); | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"%d %d %s\n", | "%d %d %s\n", | |||
ai->color, | ai->color, | |||
ai->visRep, | ai->visRep, | |||
cifrepr(ai->ssType)); | cifrepr(ai->ssType)); | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
if (m_bonds.empty()) | if (m_bonds.empty()) | |||
return; | return; | |||
m_offset += VLAprintf(m_buffer, m_offset, "#\n" | m_offset += VLAprintf(m_buffer, m_offset, "#\n" | |||
"loop_\n" | "loop_\n" | |||
"_pymol_bond.atom_site_id_1\n" | "_pymol_bond.atom_site_id_1\n" | |||
"_pymol_bond.atom_site_id_2\n" | "_pymol_bond.atom_site_id_2\n" | |||
"_pymol_bond.order\n"); | "_pymol_bond.order\n"); | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) { | for (auto& bond : m_bonds) { | |||
const auto& bond = *bond_it; | ||||
m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d\n", | m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d\n", | |||
bond.id1, bond.id2, bond.ref->order); | bond.id1, bond.id2, bond.ref->order); | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
} | } | |||
bool isExcludedBond(int atm1, int atm2) { | bool isExcludedBond(int atm1, int atm2) override { | |||
return false; | return false; | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterMOL : public MoleculeExporter { | struct MoleculeExporterMOL : public MoleculeExporter { | |||
int m_chiral_flag; | int m_chiral_flag; | |||
std::vector<AtomRef> m_atoms; | std::vector<AtomRef> m_atoms; | |||
ElemCanonicalizer elemGetter; | ElemCanonicalizer elemGetter; | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// single entry format | // single entry format | |||
return cMolExportGlobal; | return cMolExportGlobal; | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
const auto ai = m_iter.getAtomInfo(); | const auto ai = m_iter.getAtomInfo(); | |||
if (ai->stereo) | if (ai->stereo) | |||
m_chiral_flag = 1; | m_chiral_flag = 1; | |||
m_atoms.emplace_back(AtomRef { ai, { m_coord[0], m_coord[1], m_coord[2] }, g etTmpID() }); | m_atoms.emplace_back(AtomRef { ai, { m_coord[0], m_coord[1], m_coord[2] }, g etTmpID() }); | |||
} | } | |||
void writeCTabV3000() { | void writeCTabV3000() { | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
" 0 0 0 0 0 0 0 0 0 0999 V3000\n" | " 0 0 0 0 0 0 0 0 0 0999 V3000\n" | |||
"M V30 BEGIN CTAB\n" | "M V30 BEGIN CTAB\n" | |||
"M V30 COUNTS %d %d 0 0 %d\n" | "M V30 COUNTS %d %d 0 0 %d\n" | |||
"M V30 BEGIN ATOM\n", | "M V30 BEGIN ATOM\n", | |||
m_atoms.size(), m_bonds.size(), m_chiral_flag); | m_atoms.size(), m_bonds.size(), m_chiral_flag); | |||
// write atoms | // write atoms | |||
for (auto atom_it = m_atoms.begin(); atom_it != m_atoms.end(); ++atom_it) { | for (auto& atom : m_atoms) { | |||
const auto& atom = *atom_it; | ||||
auto ai = atom.ref; | auto ai = atom.ref; | |||
m_offset += VLAprintf(m_buffer, m_offset, "M V30 %d %s %.4f %.4f %.4f 0", | m_offset += VLAprintf(m_buffer, m_offset, "M V30 %d %s %.4f %.4f %.4f 0", | |||
atom.id, elemGetter(ai), atom.coord[0], atom.coord[1], atom.coord[2]); | atom.id, elemGetter(ai), atom.coord[0], atom.coord[1], atom.coord[2]); | |||
if (ai->formalCharge) | if (ai->formalCharge) | |||
m_offset += VLAprintf(m_buffer, m_offset, " CHG=%d", ai->formalCharge); | m_offset += VLAprintf(m_buffer, m_offset, " CHG=%d", ai->formalCharge); | |||
if (ai->stereo) | if (ai->stereo) | |||
m_offset += VLAprintf(m_buffer, m_offset, " CFG=%d", ai->stereo); | m_offset += VLAprintf(m_buffer, m_offset, " CFG=%d", ai->stereo); | |||
skipping to change at line 816 | skipping to change at line 840 | |||
} | } | |||
m_atoms.clear(); | m_atoms.clear(); | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"M V30 END ATOM\n" | "M V30 END ATOM\n" | |||
"M V30 BEGIN BOND\n"); | "M V30 BEGIN BOND\n"); | |||
// write bonds | // write bonds | |||
int n_bonds = 0; | int n_bonds = 0; | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) { | for (auto& bond : m_bonds) { | |||
const auto& bond = *bond_it; | ||||
m_offset += VLAprintf(m_buffer, m_offset, "M V30 %d %d %d %d\n", | m_offset += VLAprintf(m_buffer, m_offset, "M V30 %d %d %d %d\n", | |||
++n_bonds, bond.ref->order, bond.id1, bond.id2); | ++n_bonds, bond.ref->order, bond.id1, bond.id2); | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
// end | // end | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"M V30 END BOND\n" | "M V30 END BOND\n" | |||
"M V30 END CTAB\n" | "M V30 END CTAB\n" | |||
"M END\n"); | "M END\n"); | |||
} | } | |||
void writeCTabV2000() { | void writeCTabV2000() { | |||
// counts line | // counts line | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"%3d%3d 0 0%3d 0 0 0 0 0999 V2000\n", | "%3d%3d 0 0%3d 0 0 0 0 0999 V2000\n", | |||
(int) m_atoms.size(), (int) m_bonds.size(), m_chiral_flag); | (int) m_atoms.size(), (int) m_bonds.size(), m_chiral_flag); | |||
// write atoms | // write atoms | |||
for (auto atom_it = m_atoms.begin(); atom_it != m_atoms.end(); ++atom_it) { | for (auto& atom : m_atoms) { | |||
const auto& atom = *atom_it; | ||||
auto ai = atom.ref; | auto ai = atom.ref; | |||
int chg = ai->formalCharge; | int chg = ai->formalCharge; | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"%10.4f%10.4f%10.4f %-3s 0 %1d %1d 0 0 0 0 0 0 0 0 0\n", | "%10.4f%10.4f%10.4f %-3s 0 %1d %1d 0 0 0 0 0 0 0 0 0\n", | |||
atom.coord[0], atom.coord[1], atom.coord[2], | atom.coord[0], atom.coord[1], atom.coord[2], | |||
elemGetter(ai), chg ? (4 - chg) : 0, (int) ai->stereo); | elemGetter(ai), chg ? (4 - chg) : 0, (int) ai->stereo); | |||
} | } | |||
m_atoms.clear(); | m_atoms.clear(); | |||
// write bonds | // write bonds | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) { | for (auto& bond : m_bonds) { | |||
const auto& bond = *bond_it; | ||||
m_offset += VLAprintf(m_buffer, m_offset, "%3d%3d%3d%3d 0 0 0\n", | m_offset += VLAprintf(m_buffer, m_offset, "%3d%3d%3d%3d 0 0 0\n", | |||
bond.id1, bond.id2, bond.ref->order, (int) bond.ref->stereo); | bond.id1, bond.id2, bond.ref->order, (int) bond.ref->stereo); | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
// end | // end | |||
m_offset += VLAprintf(m_buffer, m_offset, "M END\n"); | m_offset += VLAprintf(m_buffer, m_offset, "M END\n"); | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
if (m_atoms.size() > 999 || m_bonds.size() > 999) { | if (m_atoms.size() > 999 || m_bonds.size() > 999) { | |||
PRINTFB(G, FB_ObjectMolecule, FB_Warnings) | PRINTFB(G, FB_ObjectMolecule, FB_Warnings) | |||
" Warning: MOL/SDF 999 atom/bond limit reached, using V3000\n" ENDFB(G); | " Warning: MOL/SDF 999 atom/bond limit reached, using V3000\n" ENDFB(G); | |||
writeCTabV3000(); | writeCTabV3000(); | |||
} else { | } else { | |||
writeCTabV2000(); | writeCTabV2000(); | |||
} | } | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"%s\n PyMOL%3.3s 3D 0\n\n", | "%s\n PyMOL%3.3s 3D 0\n\n", | |||
getTitleOrName(), _PyMOL_VERSION); | getTitleOrName(), _PyMOL_VERSION); | |||
m_chiral_flag = 0; | m_chiral_flag = 0; | |||
} | } | |||
bool isExcludedBond(const BondType * bond) { | bool isExcludedBond(const BondType * bond) override { | |||
// MOL format doesn't know zero order bonds. Writing them as order "0" | // MOL format doesn't know zero order bonds. Writing them as order "0" | |||
// will produce a nonstandard file which may be rejected by other | // will produce a nonstandard file which may be rejected by other | |||
// applications (e.g. RDKit). | // applications (e.g. RDKit). | |||
if (bond->order == 0) { | if (bond->order == 0) { | |||
return !SettingGetGlobal_b(G, cSetting_sdf_write_zero_order_bonds); | return !SettingGetGlobal_b(G, cSetting_sdf_write_zero_order_bonds); | |||
} | } | |||
return false; | return false; | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterSDF : public MoleculeExporterMOL { | struct MoleculeExporterSDF : public MoleculeExporterMOL { | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// multi-entry format | // multi-entry format | |||
return cMolExportByCoordSet; | return cMolExportByCoordSet; | |||
} | } | |||
void writeProperties() { | void writeProperties() { | |||
#ifdef _PYMOL_IP_EXTRAS | #ifdef _PYMOL_IP_PROPERTIES | |||
#endif | #endif | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
MoleculeExporterMOL::writeBonds(); | MoleculeExporterMOL::writeBonds(); | |||
writeProperties(); | writeProperties(); | |||
m_offset += VLAprintf(m_buffer, m_offset, "$$$$\n"); | m_offset += VLAprintf(m_buffer, m_offset, "$$$$\n"); | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MOL2_SubSt { | struct MOL2_SubSt { | |||
skipping to change at line 934 | skipping to change at line 955 | |||
static const char MOL2_bondTypes[][3] = { | static const char MOL2_bondTypes[][3] = { | |||
"nc", "1", "2", "3", "ar" | "nc", "1", "2", "3", "ar" | |||
}; | }; | |||
struct MoleculeExporterMOL2 : public MoleculeExporter { | struct MoleculeExporterMOL2 : public MoleculeExporter { | |||
int m_n_atoms; // atom count | int m_n_atoms; // atom count | |||
int m_counts_offset; // offset for deferred counts writing | int m_counts_offset; // offset for deferred counts writing | |||
std::vector<MOL2_SubSt> m_substs; // substructures | std::vector<MOL2_SubSt> m_substs; // substructures | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// multi-entry format | // multi-entry format | |||
return cMolExportByCoordSet; | return cMolExportByCoordSet; | |||
} | } | |||
void beginFile() { | void beginFile() override { | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"# created with PyMOL " _PyMOL_VERSION "\n"); | "# created with PyMOL " _PyMOL_VERSION "\n"); | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
// RTI MOLECULE | // RTI MOLECULE | |||
m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>MOLECULE\n" | m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>MOLECULE\n" | |||
"%s\n", getTitleOrName()); | "%s\n", getTitleOrName()); | |||
// defer until number of substructures known | // defer until number of substructures known | |||
m_counts_offset = m_offset; | m_counts_offset = m_offset; | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"X X X \n" // deferred | "X X X \n" // deferred | |||
"SMALL\n" | "SMALL\n" | |||
"USER_CHARGES\n" | "USER_CHARGES\n" | |||
"@<TRIPOS>ATOM\n"); | "@<TRIPOS>ATOM\n"); | |||
m_n_atoms = 0; | m_n_atoms = 0; | |||
} | } | |||
void beginObject() { | void beginObject() override { | |||
MoleculeExporter::beginObject(); | MoleculeExporter::beginObject(); | |||
ObjectMoleculeVerifyChemistry(m_iter.obj, m_iter.state); | ObjectMoleculeVerifyChemistry(m_iter.obj, m_iter.state); | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
const auto ai = m_iter.getAtomInfo(); | const auto ai = m_iter.getAtomInfo(); | |||
if (m_substs.empty() || | if (m_substs.empty() || | |||
!AtomInfoSameResidue(G, ai, m_substs.back().ai)) { | !AtomInfoSameResidue(G, ai, m_substs.back().ai)) { | |||
m_substs.emplace_back(MOL2_SubSt { ai, getTmpID(), | m_substs.emplace_back(MOL2_SubSt { ai, getTmpID(), | |||
ai->resn ? LexStr(G, ai->resn) : "UNK" }); | ai->resn ? LexStr(G, ai->resn) : "UNK" }); | |||
} | } | |||
// RTI ATOM | // RTI ATOM | |||
// atom_id atom_name x y z atom_type [subst_id | // atom_id atom_name x y z atom_type [subst_id | |||
skipping to change at line 993 | skipping to change at line 1014 | |||
m_coord[0], m_coord[1], m_coord[2], | m_coord[0], m_coord[1], m_coord[2], | |||
getMOL2Type(m_iter.obj, m_iter.getAtm()), | getMOL2Type(m_iter.obj, m_iter.getAtm()), | |||
m_substs.size(), | m_substs.size(), | |||
m_substs.back().resn, ai->resv, &ai->inscode, // subst_name | m_substs.back().resn, ai->resv, &ai->inscode, // subst_name | |||
ai->partialCharge, | ai->partialCharge, | |||
(ai->flags & cAtomFlag_solvent) ? "WATER" : ""); | (ai->flags & cAtomFlag_solvent) ? "WATER" : ""); | |||
++m_n_atoms; | ++m_n_atoms; | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
// atom count | // atom count | |||
m_counts_offset += sprintf(m_buffer + m_counts_offset, "%d %d %d", | m_counts_offset += sprintf(m_buffer + m_counts_offset, "%d %d %d", | |||
m_n_atoms, (int) m_bonds.size(), (int) m_substs.size()); | m_n_atoms, (int) m_bonds.size(), (int) m_substs.size()); | |||
m_buffer[m_counts_offset] = ' '; // overwrite terminator | m_buffer[m_counts_offset] = ' '; // overwrite terminator | |||
// RTI BOND | // RTI BOND | |||
// bond_id origin_atom_id target_atom_id bond_type [status_bits] | // bond_id origin_atom_id target_atom_id bond_type [status_bits] | |||
m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>BOND\n"); | m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>BOND\n"); | |||
int bond_id = 0; | int bond_id = 0; | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) { | for (auto& bond : m_bonds) { | |||
const auto& bond = *bond_it; | ||||
m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d %s\n", | m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d %s\n", | |||
++bond_id, | ++bond_id, | |||
bond.id1, | bond.id1, | |||
bond.id2, | bond.id2, | |||
MOL2_bondTypes[bond.ref->order % 5]); | MOL2_bondTypes[bond.ref->order % 5]); | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
// RTI SUBSTRUCTURE | // RTI SUBSTRUCTURE | |||
// subst_id subst_name root_atom [subst_type [dict_type | // subst_id subst_name root_atom [subst_type [dict_type | |||
// [chain [sub_type [inter_bonds [status [comment]]]]]]] | // [chain [sub_type [inter_bonds [status [comment]]]]]]] | |||
m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>SUBSTRUCTURE\n"); | m_offset += VLAprintf(m_buffer, m_offset, "@<TRIPOS>SUBSTRUCTURE\n"); | |||
int subst_id = 0; | int subst_id = 0; | |||
for (auto subst_it = m_substs.begin(); subst_it != m_substs.end(); ++subst_i | for (auto& subst : m_substs) { | |||
t) { | ||||
const auto& subst = *subst_it; | ||||
const auto& ai = subst.ai; | const auto& ai = subst.ai; | |||
m_offset += VLAprintf(m_buffer, m_offset, "%d\t%s%d%.1s\t%d\t%s\t1 %s\t%s\ n", | m_offset += VLAprintf(m_buffer, m_offset, "%d\t%s%d%.1s\t%d\t%s\t1 %s\t%s\ n", | |||
++subst_id, | ++subst_id, | |||
subst.resn, ai->resv, &ai->inscode, // subst_name | subst.resn, ai->resv, &ai->inscode, // subst_name | |||
subst.root_id, // root_atom | subst.root_id, // root_atom | |||
(ai->flags & cAtomFlag_polymer) ? "RESIDUE" : "GROUP", | (ai->flags & cAtomFlag_polymer) ? "RESIDUE" : "GROUP", | |||
ai->chain ? LexStr(G, ai->chain) : ai->segi ? LexStr(G, ai->segi) : "* ***", | ai->chain ? LexStr(G, ai->chain) : ai->segi ? LexStr(G, ai->segi) : "* ***", | |||
subst.resn); | subst.resn); | |||
} | } | |||
skipping to change at line 1049 | skipping to change at line 1068 | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterMAE : public MoleculeExporter { | struct MoleculeExporterMAE : public MoleculeExporter { | |||
int m_n_atoms; | int m_n_atoms; | |||
int m_n_atoms_offset; | int m_n_atoms_offset; | |||
int m_n_arom_bonds; | int m_n_arom_bonds; | |||
std::map<int, const AtomInfoType *> m_atoms; | std::map<int, const AtomInfoType *> m_atoms; | |||
// quasi constructor | // quasi constructor | |||
void init(PyMOLGlobals * G_) { | void init(PyMOLGlobals * G_) override { | |||
MoleculeExporter::init(G_); | MoleculeExporter::init(G_); | |||
m_n_arom_bonds = 0; | m_n_arom_bonds = 0; | |||
} | } | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// multi-entry format | // multi-entry format | |||
return cMolExportByCoordSet; | return cMolExportByCoordSet; | |||
} | } | |||
void beginFile() { | void beginFile() override { | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"{ s_m_m2io_version ::: 2.0.0 }\n" | "{ s_m_m2io_version ::: 2.0.0 }\n" | |||
"# created with PyMOL " _PyMOL_VERSION " #\n"); | "# created with PyMOL " _PyMOL_VERSION " #\n"); | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
std::string groupid = MaeExportGetSubGroupId(G, reinterpret_cast<CObject*>(m _iter.obj)); | std::string groupid = MaeExportGetSubGroupId(G, reinterpret_cast<CObject*>(m _iter.obj)); | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"\nf_m_ct {\n" | "\nf_m_ct {\n" | |||
"s_m_subgroupid\n" | "s_m_subgroupid\n" | |||
"s_m_title\n" | "s_m_title\n" | |||
":::\n" | ":::\n" | |||
"\"%s\"\n" | "\"%s\"\n" | |||
skipping to change at line 1115 | skipping to change at line 1134 | |||
"i_m_ribbon_color\n" | "i_m_ribbon_color\n" | |||
"s_m_ribbon_color_rgb\n" | "s_m_ribbon_color_rgb\n" | |||
"s_m_label_format\n" | "s_m_label_format\n" | |||
"i_m_label_color\n" | "i_m_label_color\n" | |||
"s_m_label_user_text\n" | "s_m_label_user_text\n" | |||
":::\n"); | ":::\n"); | |||
m_n_atoms = 0; | m_n_atoms = 0; | |||
} | } | |||
void beginObject() { | void beginObject() override { | |||
MoleculeExporter::beginObject(); | MoleculeExporter::beginObject(); | |||
ObjectMoleculeVerifyChemistry(m_iter.obj, m_iter.state); | ObjectMoleculeVerifyChemistry(m_iter.obj, m_iter.state); | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
const auto ai = m_iter.getAtomInfo(); | const auto ai = m_iter.getAtomInfo(); | |||
const float * rgb = ColorGet(G, ai->color); | const float * rgb = ColorGet(G, ai->color); | |||
char inscode[3] = { ai->inscode, 0 }; | char inscode[3] = { ai->inscode, 0 }; | |||
if (!inscode[0]) { | if (!inscode[0]) { | |||
strcpy(inscode, "<>"); | strcpy(inscode, "<>"); | |||
} | } | |||
ResName resn = ""; | ResName resn = ""; | |||
AtomName name = "X"; | AtomName name = "X"; | |||
skipping to change at line 1174 | skipping to change at line 1193 | |||
ribbon_color_rgb[0] == '<' ? 3 /* calphaatom */ : 0 /* constant */, | ribbon_color_rgb[0] == '<' ? 3 /* calphaatom */ : 0 /* constant */, | |||
ribbon_color_rgb, | ribbon_color_rgb, | |||
label_user_text.empty() ? "" : "%UT", | label_user_text.empty() ? "" : "%UT", | |||
label_user_text.c_str()); | label_user_text.c_str()); | |||
m_atoms[getTmpID()] = ai; | m_atoms[getTmpID()] = ai; | |||
++m_n_atoms; | ++m_n_atoms; | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
// atom count | // atom count | |||
m_n_atoms_offset += sprintf(m_buffer + m_n_atoms_offset, "m_atom[%d]", m_n_a toms); | m_n_atoms_offset += sprintf(m_buffer + m_n_atoms_offset, "m_atom[%d]", m_n_a toms); | |||
m_buffer[m_n_atoms_offset] = ' '; // overwrite terminator | m_buffer[m_n_atoms_offset] = ' '; // overwrite terminator | |||
if (!m_bonds.empty()) { | if (!m_bonds.empty()) { | |||
// table with zero rows not allowed | // table with zero rows not allowed | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
":::\n" | ":::\n" | |||
"}\n" // end atoms table | "}\n" // end atoms table | |||
"m_bond[%d] {\n" | "m_bond[%d] {\n" | |||
"# First column is bond index #\n" | "# First column is bond index #\n" | |||
"i_m_from\n" | "i_m_from\n" | |||
"i_m_to\n" | "i_m_to\n" | |||
"i_m_order\n" | "i_m_order\n" | |||
"i_m_from_rep\n" | "i_m_from_rep\n" | |||
"i_m_to_rep\n" | "i_m_to_rep\n" | |||
":::\n", (int) m_bonds.size()); | ":::\n", (int) m_bonds.size()); | |||
int b = 0; | int b = 0; | |||
for (auto bond_it = m_bonds.begin(); bond_it != m_bonds.end(); ++bond_it) | for (auto& bond : m_bonds) { | |||
{ | ||||
const auto& bond = *bond_it; | ||||
int order = bond.ref->order; | int order = bond.ref->order; | |||
if (order > 3) { | if (order > 3) { | |||
++m_n_arom_bonds; | ++m_n_arom_bonds; | |||
order = 1; // aromatic bonds not supported | order = 1; // aromatic bonds not supported | |||
} | } | |||
m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d %d\n", ++b, | m_offset += VLAprintf(m_buffer, m_offset, "%d %d %d %d\n", ++b, | |||
bond.id1, | bond.id1, | |||
bond.id2, | bond.id2, | |||
order); | order); | |||
skipping to change at line 1236 | skipping to change at line 1254 | |||
} | } | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- ----- // | // ----------------------------------------------------------------------------- ----- // | |||
struct MoleculeExporterXYZ : public MoleculeExporter { | struct MoleculeExporterXYZ : public MoleculeExporter { | |||
int m_n_atoms; | int m_n_atoms; | |||
int m_n_atoms_offset; | int m_n_atoms_offset; | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// multi-entry format | // multi-entry format | |||
return cMolExportByCoordSet; | return cMolExportByCoordSet; | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
// defer until number of atoms known | // defer until number of atoms known | |||
m_n_atoms = 0; | m_n_atoms = 0; | |||
m_n_atoms_offset = m_offset; | m_n_atoms_offset = m_offset; | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"X \n" // natoms (deferred) | "X \n" // natoms (deferred) | |||
"%s\n", // comment | "%s\n", // comment | |||
getTitleOrName()); | getTitleOrName()); | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
const auto ai = m_iter.getAtomInfo(); | const auto ai = m_iter.getAtomInfo(); | |||
m_offset += VLAprintf(m_buffer, m_offset, | m_offset += VLAprintf(m_buffer, m_offset, | |||
"%s %f %f %f\n", ai->elem, m_coord[0], m_coord[1], m_coord[2]); | "%s %f %f %f\n", ai->elem, m_coord[0], m_coord[1], m_coord[2]); | |||
++m_n_atoms; | ++m_n_atoms; | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
// atom count | // atom count | |||
m_n_atoms_offset += sprintf(m_buffer + m_n_atoms_offset, "%d", m_n_atoms); | m_n_atoms_offset += sprintf(m_buffer + m_n_atoms_offset, "%d", m_n_atoms); | |||
m_buffer[m_n_atoms_offset] = ' '; // overwrite terminator | m_buffer[m_n_atoms_offset] = ' '; // overwrite terminator | |||
} | } | |||
bool isExcludedBond(int atm1, int atm2) { | bool isExcludedBond(int atm1, int atm2) override { | |||
// no bonds for XYZ format | // no bonds for XYZ format | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
// ----------------------------------------------------------------------------- | ||||
----- // | ||||
#ifndef _PYMOL_NO_MSGPACKC | ||||
class MoleculeExporterMMTF : public MoleculeExporter { | ||||
mmtf::StructureData m_raw; | ||||
mmtf::GroupType * m_residue = nullptr; | ||||
const AtomInfoType * m_last_ai = nullptr; | ||||
ElemCanonicalizer m_elemGetter; | ||||
std::vector<int32_t> colorList; | ||||
std::vector<int32_t> repsList; | ||||
public: | ||||
int getMultiDefault() const override { | ||||
return cMolExportGlobal; | ||||
} | ||||
void beginCoordSet() override { | ||||
m_raw.chainsPerModel.emplace_back(0); | ||||
m_last_ai = nullptr; | ||||
} | ||||
void writeAtom() override { | ||||
const AtomInfoType * ai = m_iter.getAtomInfo(); | ||||
m_raw.xCoordList.emplace_back(m_coord[0]); | ||||
m_raw.yCoordList.emplace_back(m_coord[1]); | ||||
m_raw.zCoordList.emplace_back(m_coord[2]); | ||||
// PyMOL customs | ||||
colorList.emplace_back(ai->color); | ||||
repsList.emplace_back(ai->visRep); | ||||
bool is_same_residue = false; | ||||
bool is_same_chain = AtomInfoSameChainP(G, ai, m_last_ai); | ||||
if (!is_same_chain) { | ||||
m_raw.chainsPerModel.back() += 1; | ||||
m_raw.groupsPerChain.emplace_back(0); // increment with every group | ||||
m_raw.chainIdList.emplace_back(LexStr(G, ai->segi)); | ||||
m_raw.chainNameList.emplace_back(LexStr(G, ai->chain)); | ||||
} else { | ||||
is_same_residue = AtomInfoSameResidueP(G, ai, m_last_ai); | ||||
} | ||||
if (!is_same_residue) { | ||||
m_raw.groupsPerChain.back() += 1; | ||||
m_raw.groupTypeList.emplace_back(m_raw.groupList.size()); | ||||
m_raw.groupIdList.emplace_back(ai->resv); | ||||
m_raw.insCodeList.emplace_back(ai->inscode); | ||||
m_raw.secStructList.emplace_back( | ||||
ai->ssType[0] == 'H' ? 2 : | ||||
ai->ssType[0] == 'S' ? 3 : -1); | ||||
m_raw.groupList.emplace_back(); | ||||
m_residue = &m_raw.groupList.back(); | ||||
m_residue->groupName = LexStr(G, ai->resn); | ||||
} | ||||
m_residue->formalChargeList.emplace_back(ai->formalCharge); | ||||
m_residue->atomNameList.emplace_back(LexStr(G, ai->name)); | ||||
m_residue->elementList.emplace_back(m_elemGetter(ai)); | ||||
m_raw.bFactorList.emplace_back(ai->b); | ||||
m_raw.occupancyList.emplace_back(ai->q); | ||||
m_raw.altLocList.emplace_back(ai->alt[0]); | ||||
m_last_ai = ai; | ||||
} | ||||
void writeBonds() override { | ||||
m_raw.numAtoms = m_raw.xCoordList.size(); | ||||
m_raw.numGroups = m_raw.groupIdList.size(); | ||||
m_raw.numChains = m_raw.chainIdList.size(); | ||||
m_raw.numModels = m_raw.chainsPerModel.size(); | ||||
mmtf::BondAdder bondadder(m_raw); | ||||
for (const auto &bond : m_bonds) { | ||||
bondadder(bond.id1 - 1, bond.id2 - 1, bond.ref->order); | ||||
} | ||||
mmtf::compressGroupList(m_raw); | ||||
packMsgpack(); | ||||
} | ||||
void packMsgpack() { | ||||
msgpack::zone _zone; | ||||
auto data_map = mmtf::encodeToMap(m_raw, _zone); | ||||
data_map["pymolColorList"] = msgpack::object(colorList, _zone); | ||||
data_map["pymolRepsList"] = msgpack::object(repsList, _zone); | ||||
std::stringstream stream; | ||||
msgpack::pack(stream, data_map); | ||||
auto buffer = stream.str(); | ||||
auto bufferSize = buffer.size(); | ||||
m_buffer.resize(bufferSize); | ||||
std::memcpy(m_buffer, buffer.data(), bufferSize); | ||||
m_offset = bufferSize; | ||||
} | ||||
}; | ||||
#endif | ||||
/*========================================================================*/ | /*========================================================================*/ | |||
/* | /* | |||
* Export the given selection to a molecular file format. | * Export the given selection to a molecular file format. | |||
* | * | |||
* Return the file contents as a VLA (must be VLAFree'd by caller) or | * Return the file contents as a VLA (must be VLAFree'd by caller) or | |||
* NULL if the format is not known. | * NULL if the format is not known. | |||
* | * | |||
* format: pdb, sdf, ... | * format: pdb, sdf, ... | |||
* selection: atom selection expression | * selection: atom selection expression | |||
* state: object state (-1 for all, -2/-3 for current) | * state: object state (-1 for all, -2/-3 for current) | |||
* ref_object: name of a reference object which defines the frame of | * ref_object: name of a reference object which defines the frame of | |||
* reference for exported coordinates | * reference for exported coordinates | |||
* ref_state: reference object state | * ref_state: reference object state | |||
* multi: defines how to handle selections which span multiple objects | * multi: defines how to handle selections which span multiple objects | |||
* -1: use format-specific default | * -1: use format-specific default | |||
* 0: one global "molecule" (default for PDB) | * 0: one global "molecule" (default for PDB) | |||
* 1: molecules per objects | * 1: molecules per objects | |||
* 2: molecules per states (default for sdf, mol2) | * 2: molecules per states (default for sdf, mol2) | |||
*/ | */ | |||
unique_vla_ptr<char> MoleculeExporterGetStr(PyMOLGlobals * G, | pymol::vla<char> MoleculeExporterGetStr(PyMOLGlobals * G, | |||
const char *format, | const char *format, | |||
const char *selection, | const char *selection, | |||
int state, | int state, | |||
const char *ref_object, | const char *ref_object, | |||
int ref_state, | int ref_state, | |||
int multi, | int multi, | |||
bool quiet) | bool quiet) | |||
{ | { | |||
SelectorTmp tmpsele1(G, selection); | SelectorTmp tmpsele1(G, selection); | |||
int sele = tmpsele1.getIndex(); | int sele = tmpsele1.getIndex(); | |||
if (sele < 0) | if (sele < 0) | |||
return NULL; | return nullptr; | |||
MoleculeExporter * exporter = NULL; | std::unique_ptr<MoleculeExporter> exporter; | |||
if (ref_state < -1) | if (ref_state < -1) | |||
ref_state = state; | ref_state = state; | |||
// do "effective" current states | // do "effective" current states | |||
if (state == -2) | if (state == -2) | |||
state = -3; | state = -3; | |||
if (strcmp(format, "pdb") == 0) { | if (strcmp(format, "pdb") == 0) { | |||
exporter = new MoleculeExporterPDB; | exporter.reset(new MoleculeExporterPDB); | |||
} else if (strcmp(format, "pmcif") == 0) { | } else if (strcmp(format, "pmcif") == 0) { | |||
exporter = new MoleculeExporterPMCIF; | exporter.reset(new MoleculeExporterPMCIF); | |||
} else if (strcmp(format, "cif") == 0) { | } else if (strcmp(format, "cif") == 0) { | |||
exporter = new MoleculeExporterCIF; | exporter.reset(new MoleculeExporterCIF); | |||
} else if (strcmp(format, "sdf") == 0) { | } else if (strcmp(format, "sdf") == 0) { | |||
exporter = new MoleculeExporterSDF; | exporter.reset(new MoleculeExporterSDF); | |||
} else if (strcmp(format, "pqr") == 0) { | } else if (strcmp(format, "pqr") == 0) { | |||
exporter = new MoleculeExporterPQR; | exporter.reset(new MoleculeExporterPQR); | |||
} else if (strcmp(format, "mol2") == 0) { | } else if (strcmp(format, "mol2") == 0) { | |||
exporter = new MoleculeExporterMOL2; | exporter.reset(new MoleculeExporterMOL2); | |||
} else if (strcmp(format, "mol") == 0) { | } else if (strcmp(format, "mol") == 0) { | |||
exporter = new MoleculeExporterMOL; | exporter.reset(new MoleculeExporterMOL); | |||
} else if (strcmp(format, "xyz") == 0) { | } else if (strcmp(format, "xyz") == 0) { | |||
exporter = new MoleculeExporterXYZ; | exporter.reset(new MoleculeExporterXYZ); | |||
} else if (strcmp(format, "mae") == 0) { | } else if (strcmp(format, "mae") == 0) { | |||
exporter = new MoleculeExporterMAE; | exporter.reset(new MoleculeExporterMAE); | |||
} else if (strcmp(format, "mmtf") == 0) { | ||||
#ifndef _PYMOL_NO_MSGPACKC | ||||
exporter.reset(new MoleculeExporterMMTF); | ||||
#else | ||||
PRINTFB(G, FB_ObjectMolecule, FB_Errors) | ||||
" Error: This build has no fast MMTF support.\n" ENDFB(G); | ||||
return nullptr; | ||||
#endif | ||||
} else { | } else { | |||
PRINTFB(G, FB_ObjectMolecule, FB_Errors) | PRINTFB(G, FB_ObjectMolecule, FB_Errors) | |||
" Error: unknown format: '%s'\n", format ENDFB(G); | " Error: unknown format: '%s'\n", format ENDFB(G); | |||
return NULL; | return nullptr; | |||
} | } | |||
// Ensure "." decimal point in printf. It's possible to change this from | // Ensure "." decimal point in printf. It's possible to change this from | |||
// Python, so don't rely on a persistent global value. | // Python, so don't rely on a persistent global value. | |||
std::setlocale(LC_NUMERIC, "C"); | std::setlocale(LC_NUMERIC, "C"); | |||
exporter->init(G); | exporter->init(G); | |||
exporter->setMulti(multi); | exporter->setMulti(multi); | |||
exporter->setRefObject(ref_object, ref_state); | exporter->setRefObject(ref_object, ref_state); | |||
exporter->execute(sele, state); | exporter->execute(sele, state); | |||
char * charVLA = NULL; | return std::move(exporter->m_buffer); | |||
std::swap(charVLA, exporter->m_buffer); | ||||
delete exporter; | ||||
return charVLA; | ||||
} | } | |||
/*========================================================================*/ | /*========================================================================*/ | |||
#ifndef _PYMOL_NOPY | #ifndef _PYMOL_NOPY | |||
/* | /* | |||
* See MoleculeExporterGetPyBonds | * See MoleculeExporterGetPyBonds | |||
*/ | */ | |||
struct MoleculeExporterPyBonds : public MoleculeExporter { | struct MoleculeExporterPyBonds : public MoleculeExporter { | |||
PyObject *m_bond_list; // out | PyObject *m_bond_list; // out | |||
protected: | protected: | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// single-entry format | // single-entry format | |||
return cMolExportGlobal; | return cMolExportGlobal; | |||
} | } | |||
void writeAtom() {} | void writeAtom() override {} | |||
void writeBonds() { | void writeBonds() override { | |||
size_t nBond = m_bonds.size(); | size_t nBond = m_bonds.size(); | |||
m_bond_list = PyList_New(nBond); | m_bond_list = PyList_New(nBond); | |||
for (size_t b = 0; b < nBond; ++b) { | for (size_t b = 0; b < nBond; ++b) { | |||
const auto& bond = m_bonds[b]; | const auto& bond = m_bonds[b]; | |||
PyList_SetItem(m_bond_list, b, Py_BuildValue("iii", | PyList_SetItem(m_bond_list, b, Py_BuildValue("iii", | |||
bond.id1 - 1, bond.id2 - 1, bond.ref->order)); | bond.id1 - 1, bond.id2 - 1, bond.ref->order)); | |||
} | } | |||
m_bonds.clear(); | m_bonds.clear(); | |||
skipping to change at line 1407 | skipping to change at line 1533 | |||
* the 0-based atom indices within the selection. | * the 0-based atom indices within the selection. | |||
* | * | |||
* Return value: New reference | * Return value: New reference | |||
*/ | */ | |||
PyObject *MoleculeExporterGetPyBonds(PyMOLGlobals * G, | PyObject *MoleculeExporterGetPyBonds(PyMOLGlobals * G, | |||
const char *selection, int state) | const char *selection, int state) | |||
{ | { | |||
SelectorTmp tmpsele1(G, selection); | SelectorTmp tmpsele1(G, selection); | |||
int sele = tmpsele1.getIndex(); | int sele = tmpsele1.getIndex(); | |||
if (sele < 0) | if (sele < 0) | |||
return NULL; | return nullptr; | |||
int unblock = PAutoBlock(G); | int unblock = PAutoBlock(G); | |||
MoleculeExporterPyBonds exporter; | MoleculeExporterPyBonds exporter; | |||
exporter.init(G); | exporter.init(G); | |||
exporter.execute(sele, state); | exporter.execute(sele, state); | |||
if (PyErr_Occurred()) | if (PyErr_Occurred()) | |||
PyErr_Print(); | PyErr_Print(); | |||
skipping to change at line 1442 | skipping to change at line 1568 | |||
struct MoleculeExporterChemPy : public MoleculeExporter { | struct MoleculeExporterChemPy : public MoleculeExporter { | |||
PyObject *m_model; // out | PyObject *m_model; // out | |||
protected: | protected: | |||
int m_n_cs; // number of coordinate sets | int m_n_cs; // number of coordinate sets | |||
float m_ref_tmp[3]; | float m_ref_tmp[3]; | |||
PyObject *m_atom_list; | PyObject *m_atom_list; | |||
public: | public: | |||
// quasi constructor | // quasi constructor | |||
void init(PyMOLGlobals * G_) { | void init(PyMOLGlobals * G_) override { | |||
MoleculeExporter::init(G_); | MoleculeExporter::init(G_); | |||
m_model = NULL; | m_model = nullptr; | |||
m_n_cs = 0; | m_n_cs = 0; | |||
m_atom_list = NULL; | m_atom_list = nullptr; | |||
} | } | |||
protected: | protected: | |||
int getMultiDefault() const { | int getMultiDefault() const override { | |||
// single-entry format | // single-entry format | |||
return cMolExportGlobal; | return cMolExportGlobal; | |||
} | } | |||
void beginMolecule() { | void beginMolecule() override { | |||
MoleculeExporter::beginMolecule(); | MoleculeExporter::beginMolecule(); | |||
m_model = PYOBJECT_CALLMETHOD(P_models, "Indexed", ""); | m_model = PYOBJECT_CALLMETHOD(P_models, "Indexed", ""); | |||
if (m_model) { | if (m_model) { | |||
m_atom_list = PyList_New(0); | m_atom_list = PyList_New(0); | |||
PyObject_SetAttrString(m_model, "atom", m_atom_list); | PyObject_SetAttrString(m_model, "atom", m_atom_list); | |||
Py_DECREF(m_atom_list); | Py_DECREF(m_atom_list); | |||
} | } | |||
} | } | |||
void beginCoordSet() { | void beginCoordSet() override { | |||
MoleculeExporter::beginCoordSet(); | MoleculeExporter::beginCoordSet(); | |||
++m_n_cs; | ++m_n_cs; | |||
} | } | |||
const float * getRefPtr() { | const float * getRefPtr() { | |||
RefPosType * ref_pos = m_iter.cs->RefPos; | RefPosType * ref_pos = m_iter.cs->RefPos; | |||
const float * ref_ptr = NULL; | const float * ref_ptr = nullptr; | |||
if (ref_pos) { | if (ref_pos) { | |||
ref_pos += m_iter.getIdx(); | ref_pos += m_iter.getIdx(); | |||
if (ref_pos->specified) { | if (ref_pos->specified) { | |||
ref_ptr = ref_pos->coord; | ref_ptr = ref_pos->coord; | |||
if (m_mat_move.ptr) { | if (m_mat_move.ptr) { | |||
transform44d3f(m_mat_move.ptr, ref_ptr, m_ref_tmp); | transform44d3f(m_mat_move.ptr, ref_ptr, m_ref_tmp); | |||
ref_ptr = m_ref_tmp; | ref_ptr = m_ref_tmp; | |||
} | } | |||
} | } | |||
} | } | |||
return ref_ptr; | return ref_ptr; | |||
} | } | |||
void writeAtom() { | void writeAtom() override { | |||
PyObject *atom = CoordSetAtomToChemPyAtom(G, | PyObject *atom = CoordSetAtomToChemPyAtom(G, | |||
m_iter.getAtomInfo(), m_coord, getRefPtr(), | m_iter.getAtomInfo(), m_coord, getRefPtr(), | |||
m_iter.getAtm(), m_mat_full.ptr); | m_iter.getAtm(), m_mat_full.ptr); | |||
if (atom) { | if (atom) { | |||
PyList_Append(m_atom_list, atom); | PyList_Append(m_atom_list, atom); | |||
Py_DECREF(atom); | Py_DECREF(atom); | |||
} | } | |||
} | } | |||
skipping to change at line 1519 | skipping to change at line 1645 | |||
// title | // title | |||
if (m_last_cs->Name[0]) { | if (m_last_cs->Name[0]) { | |||
PyObject *molecule = PyObject_GetAttrString(m_model, "molecule"); | PyObject *molecule = PyObject_GetAttrString(m_model, "molecule"); | |||
if (molecule) { | if (molecule) { | |||
PyObject_SetAttrString(molecule, "title", PyString_FromString(m_last_cs- >Name)); | PyObject_SetAttrString(molecule, "title", PyString_FromString(m_last_cs- >Name)); | |||
Py_DECREF(molecule); | Py_DECREF(molecule); | |||
} | } | |||
} | } | |||
// properties | // properties | |||
#ifdef _PYMOL_IP_EXTRAS | #ifdef _PYMOL_IP_PROPERTIES | |||
#endif | #endif | |||
} | } | |||
void writeBonds() { | void writeBonds() override { | |||
if (!m_model) | if (!m_model) | |||
return; | return; | |||
bool error = false; | bool error = false; | |||
size_t nBond = m_bonds.size(); | size_t nBond = m_bonds.size(); | |||
PyObject *bond_list = PyList_New(nBond); | PyObject *bond_list = PyList_New(nBond); | |||
for (size_t b = 0; b < nBond; ++b) { | for (size_t b = 0; b < nBond; ++b) { | |||
PyObject *bnd = PYOBJECT_CALLMETHOD(P_chempy, "Bond", ""); | PyObject *bnd = PYOBJECT_CALLMETHOD(P_chempy, "Bond", ""); | |||
if (!bnd) { | if (!bnd) { | |||
skipping to change at line 1572 | skipping to change at line 1698 | |||
const char *ref_object, int ref_state) | const char *ref_object, int ref_state) | |||
{ | { | |||
if (state == -1) | if (state == -1) | |||
state = 0; // no multi-state support | state = 0; // no multi-state support | |||
if (ref_state < -1) | if (ref_state < -1) | |||
ref_state = state; | ref_state = state; | |||
int sele = SelectorIndexByName(G, s1); | int sele = SelectorIndexByName(G, s1); | |||
if (sele < 0) | if (sele < 0) | |||
return NULL; | return nullptr; | |||
int unblock = PAutoBlock(G); | int unblock = PAutoBlock(G); | |||
MoleculeExporterChemPy exporter; | MoleculeExporterChemPy exporter; | |||
exporter.init(G); | exporter.init(G); | |||
exporter.setRefObject(ref_object, ref_state); | exporter.setRefObject(ref_object, ref_state); | |||
exporter.execute(sele, state); | exporter.execute(sele, state); | |||
if (PyErr_Occurred()) | if (PyErr_Occurred()) | |||
PyErr_Print(); | PyErr_Print(); | |||
End of changes. 104 change blocks. | ||||
123 lines changed or deleted | 248 lines changed or added |