Files
rdkit/Code/GraphMol/MolPickler.h
Ricardo Rodriguez e3f2e4651e Refactor iostreams includes (#8846)
* refactor iostreams includes

* restore ostream to MonomerInfo.cpp
2025-10-31 13:42:16 +01:00

330 lines
11 KiB
C++

///
// Copyright (C) 2001-2021 Greg Landrum and Rational Discovery LLC
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
#include <RDGeneral/export.h>
#ifndef RD_MOLPICKLE_H
#define RD_MOLPICKLE_H
#include <Geometry/point.h>
#include <GraphMol/Atom.h>
#include <GraphMol/QueryAtom.h>
#include <GraphMol/Bond.h>
#include <GraphMol/QueryBond.h>
#include <RDGeneral/StreamOps.h>
#include <boost/utility/binary.hpp>
#include <boost/variant.hpp>
#include <Query/QueryObjects.h>
// Std stuff
#include <string>
#include <sstream>
#include <exception>
#ifdef WIN32
#include <ios>
#endif
#include <cstdint>
#include <RDGeneral/BetterEnums.h>
namespace RDKit {
class ROMol;
class RingInfo;
//! used to indicate exceptions whilst pickling (serializing) molecules
class RDKIT_GRAPHMOL_EXPORT MolPicklerException : public std::exception {
public:
MolPicklerException(const char *msg) : _msg(msg) {}
MolPicklerException(const std::string msg) : _msg(msg) {}
const char *what() const noexcept override { return _msg.c_str(); }
~MolPicklerException() noexcept override = default;
private:
std::string _msg;
};
namespace PicklerOps {
BETTER_ENUM(
PropertyPickleOptions, unsigned int,
NoProps = 0, // no data pickled (default pickling, single-precision coords)
MolProps = 0x1, // only public non computed properties
AtomProps = 0x2, BondProps = 0x4,
QueryAtomData =
0x2, // n.b. DEPRECATED and set to AtomProps (does the same work)
PrivateProps = 0x10, ComputedProps = 0x20,
AllProps = 0x0000FFFF, // all data pickled
CoordsAsDouble = 0x00010000, // save coordinates in double precision
NoConformers =
0x00020000 // do not include conformers or associated properties
);
} // namespace PicklerOps
//! handles pickling (serializing) molecules
class RDKIT_GRAPHMOL_EXPORT MolPickler {
public:
static const std::int32_t versionMajor; //!< mark the pickle major version
static const std::int32_t versionMinor; //!< mark the pickle minor version
static const std::int32_t versionPatch; //!< mark the pickle patch version
static const std::int32_t endianId; //!< mark the endian-ness of the pickle
//! the pickle format is tagged using these tags:
//! NOTE: if you add to this list, be sure to put new entries AT THE BOTTOM,
/// otherwise
//! you will break old pickles.
typedef enum {
VERSION = 0,
BEGINATOM,
ATOM_INDEX,
ATOM_NUMBER,
ATOM_POS,
ATOM_CHARGE,
ATOM_NEXPLICIT,
ATOM_CHIRALTAG,
ATOM_MASS,
ATOM_ISAROMATIC,
ENDATOM,
BEGINBOND,
BOND_INDEX,
BOND_BEGATOMIDX,
BOND_ENDATOMIDX,
BOND_TYPE,
BOND_DIR,
ENDBOND,
BEGINPROPS,
ENDPROPS,
BEGINSSSR,
ENDSSSR,
ENDMOL,
BEGINCONFS,
ATOM_MAPNUMBER,
BEGINQUERY,
QUERY_VALUE,
QUERY_ISNEGATED,
QUERY_NUMCHILDREN,
QUERY_BOOL,
QUERY_AND,
QUERY_OR,
QUERY_XOR,
QUERY_EQUALS,
QUERY_GREATER,
QUERY_GREATEREQUAL,
QUERY_LESS,
QUERY_LESSEQUAL,
QUERY_RANGE,
QUERY_SET,
QUERY_NULL,
QUERY_ATOMRING,
QUERY_RECURSIVE,
ENDQUERY,
ATOM_DUMMYLABEL,
BEGIN_ATOM_MONOMER,
ATOM_PDB_RESIDUE_SERIALNUMBER,
ATOM_PDB_RESIDUE_ALTLOC,
ATOM_PDB_RESIDUE_RESIDUENAME,
ATOM_PDB_RESIDUE_CHAINID,
ATOM_PDB_RESIDUE_INSERTIONCODE,
ATOM_PDB_RESIDUE_OCCUPANCY,
ATOM_PDB_RESIDUE_TEMPFACTOR,
ATOM_PDB_RESIDUE_ISHETEROATOM,
ATOM_PDB_RESIDUE_SECONDARYSTRUCTURE,
ATOM_PDB_RESIDUE_RESIDUENUMBER,
ATOM_PDB_RESIDUE_SEGMENTNUMBER,
END_ATOM_MONOMER,
BEGINATOMPROPS,
BEGINBONDPROPS,
BEGINQUERYATOMDATA,
BEGINSGROUP,
BEGINSTEREOGROUP,
BEGINCONFPROPS,
BEGINCONFS_DOUBLE,
QUERY_TYPELABEL,
BEGINSYMMSSSR,
BEGINFASTFIND,
BEGINFINDOTHERORUNKNOWN,
QUERY_PROPERTY,
QUERY_PROPERTY_WITH_VALUE,
// add new entries above here
INVALID_TAG = 255
} Tags;
static unsigned int getDefaultPickleProperties();
static void setDefaultPickleProperties(unsigned int);
static const CustomPropHandlerVec &getCustomPropHandlers();
static void addCustomPropHandler(const CustomPropHandler &handler);
//! pickles a molecule and sends the results to stream \c ss
static void pickleMol(const ROMol *mol, std::ostream &ss);
static void pickleMol(const ROMol *mol, std::ostream &ss,
unsigned int propertyFlags);
static void pickleMol(const ROMol &mol, std::ostream &ss);
static void pickleMol(const ROMol &mol, std::ostream &ss,
unsigned int propertyFlags) {
MolPickler::pickleMol(&mol, ss, propertyFlags);
}
//! pickles a molecule and adds the results to string \c res
static void pickleMol(const ROMol *mol, std::string &res);
static void pickleMol(const ROMol *mol, std::string &res,
unsigned int propertyFlags);
static void pickleMol(const ROMol &mol, std::string &res);
static void pickleMol(const ROMol &mol, std::string &res,
unsigned int propertyFlags) {
MolPickler::pickleMol(&mol, res, propertyFlags);
}
//! constructs a molecule from a pickle stored in a string
static void molFromPickle(const std::string &pickle, ROMol *mol,
unsigned int propertyFlags);
static void molFromPickle(const std::string &pickle, ROMol &mol,
unsigned int propertyFlags) {
MolPickler::molFromPickle(pickle, &mol, propertyFlags);
}
static void molFromPickle(const std::string &pickle, ROMol *mol) {
MolPickler::molFromPickle(pickle, mol,
PicklerOps::PropertyPickleOptions::AllProps);
}
static void molFromPickle(const std::string &pickle, ROMol &mol) {
MolPickler::molFromPickle(pickle, &mol,
PicklerOps::PropertyPickleOptions::AllProps);
}
//! constructs a molecule from a pickle stored in a stream
static void molFromPickle(std::istream &ss, ROMol *mol,
unsigned int propertyFlags);
static void molFromPickle(std::istream &ss, ROMol &mol,
unsigned int propertyFlags) {
MolPickler::molFromPickle(ss, &mol, propertyFlags);
}
static void molFromPickle(std::istream &ss, ROMol *mol) {
MolPickler::molFromPickle(ss, mol,
PicklerOps::PropertyPickleOptions::AllProps);
}
static void molFromPickle(std::istream &ss, ROMol &mol) {
MolPickler::molFromPickle(ss, &mol,
PicklerOps::PropertyPickleOptions::AllProps);
}
private:
//! Pickle nonquery atom data
static std::int32_t _pickleAtomData(std::ostream &tss, const Atom *atom);
//! depickle nonquery atom data
static void _unpickleAtomData(std::istream &tss, Atom *atom, int version);
static void _pickleQueryAtomData(std::ostream &tss, const Atom *atom);
//! do the actual work of pickling a molecule
template <typename T>
static void _pickle(const ROMol *mol, std::ostream &ss,
unsigned int propertyFlags);
//! do the actual work of pickling an Atom
template <typename T>
static void _pickleAtom(std::ostream &ss, const Atom *atom);
//! do the actual work of pickling a Bond
template <typename T>
static void _pickleBond(std::ostream &ss, const Bond *bond,
std::map<int, int> &atomIdxMap);
//! do the actual work of pickling an SSSR structure
template <typename T>
static void _pickleSSSR(std::ostream &ss, const RingInfo *ringInfo,
std::map<int, int> &atomIdxMap);
//! do the actual work of pickling a SubstanceGroup
template <typename T>
static void _pickleSubstanceGroup(std::ostream &ss,
const SubstanceGroup &sgroup,
std::map<int, int> &atomIdxMap,
std::map<int, int> &bondIdxMap);
//! do the actual work of pickling Stereo Group data
template <typename T>
static void _pickleStereo(std::ostream &ss, std::vector<StereoGroup> groups,
std::map<int, int> &atomIdxMap,
std::map<int, int> &bondIdxMap);
//! do the actual work of pickling a Conformer
template <typename T, typename C>
static void _pickleConformer(std::ostream &ss, const Conformer *conf);
//! do the actual work of de-pickling a molecule
template <typename T>
static void _depickle(std::istream &ss, ROMol *mol, int version, int numAtoms,
unsigned int propertyFlags);
//! extract atomic data from a pickle and add the resulting Atom to the
/// molecule
template <typename T>
static Atom *_addAtomFromPickle(std::istream &ss, ROMol *mol,
RDGeom::Point3D &pos, int version,
bool directMap = false);
//! extract bond data from a pickle and add the resulting Bond to the molecule
template <typename T>
static Bond *_addBondFromPickle(std::istream &ss, ROMol *mol, int version,
bool directMap = false);
//! extract ring info from a pickle and add the resulting RingInfo to the
/// molecule
template <typename T>
static void _addRingInfoFromPickle(
std::istream &ss, ROMol *mol, int version, bool directMap = false,
FIND_RING_TYPE ringType =
FIND_RING_TYPE::FIND_RING_TYPE_OTHER_OR_UNKNOWN);
//! extract a SubstanceGroup from a pickle
template <typename T>
static SubstanceGroup _getSubstanceGroupFromPickle(std::istream &ss,
ROMol *mol, int version);
template <typename T>
static void _depickleStereo(std::istream &ss, ROMol *mol, int version);
//! extract a conformation from a pickle
template <typename T, typename C>
static Conformer *_conformerFromPickle(std::istream &ss, int version);
//! pickle standard properties
static void _pickleProperties(std::ostream &ss, const RDProps &props,
unsigned int pickleFlags);
//! unpickle standard properties
static void _unpickleProperties(std::istream &ss, RDProps &props,
int version);
//! backwards compatibility
static void _pickleV1(const ROMol *mol, std::ostream &ss);
//! backwards compatibility
static void _depickleV1(std::istream &ss, ROMol *mol);
//! backwards compatibility
static void _addAtomFromPickleV1(std::istream &ss, ROMol *mol);
//! backwards compatibility
static void _addBondFromPickleV1(std::istream &ss, ROMol *mol);
};
namespace PicklerOps {
// clang-format off
using QueryDetails = boost::variant<
MolPickler::Tags, std::tuple<MolPickler::Tags, int32_t>,
std::tuple<MolPickler::Tags, int32_t, int32_t>,
std::tuple<MolPickler::Tags, int32_t, int32_t, int32_t, char>,
std::tuple<MolPickler::Tags, std::set<int32_t>>,
std::tuple<MolPickler::Tags, std::string>,
std::tuple<MolPickler::Tags, PairHolder, double>>;
// clang-format on
template <class T>
QueryDetails getQueryDetails(const Queries::Query<int, T const *, true> *query);
} // namespace PicklerOps
}; // namespace RDKit
#endif