"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "layer3/MoleculeExporter.cpp" between
pymol-open-source-2.2.0.tar.gz and pymol-open-source-2.3.0.tar.gz

About: PyMOL is a Python-enhanced molecular graphics tool. It excels at 3D visualization of proteins, small molecules, density, surfaces, and trajectories. It also includes molecular editing, ray tracing, and movies. Open Source version.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)