RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
MolWriters.h
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2017 Greg Landrum, Rational Discovery LLC
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10
11#include <RDGeneral/export.h>
12#ifndef _RD_MOLWRITERS_H_
13#define _RD_MOLWRITERS_H_
14
15#include <RDGeneral/types.h>
16
17#include <memory>
18#include <string>
19
20
21#ifdef RDK_BUILD_MAEPARSER_SUPPORT
22#include <maeparser/Writer.hpp>
23#endif // RDK_BUILD_MAEPARSER_SUPPORT
24
25#include <GraphMol/ROMol.h>
26
27namespace RDKit {
28
29static int defaultConfId = -1;
30
32 public:
33 MolWriter() = default;
34 MolWriter(const MolWriter &) = delete;
35 MolWriter &operator=(const MolWriter &) = delete;
36 virtual ~MolWriter() {}
37 virtual void write(const ROMol &mol, int confId = defaultConfId) = 0;
38 virtual void flush() = 0;
39 virtual void close() = 0;
40 virtual void setProps(const STR_VECT &propNames) = 0;
41 virtual unsigned int numMols() const = 0;
42};
43
44//! The SmilesWriter is for writing molecules and properties to
45//! delimited text files.
47 /******************************************************************************
48 * A Smiles Table writer - this is how it is used
49 * - create a SmilesWriter with a output file name (or a ostream), a
50 *delimiter,
51 * and a list of properties that need to be written out
52 * - then a call is made to the write function for each molecule that needs
53 *to
54 * be written out
55 ******************************************************************************/
56 public:
57 /*!
58 \param fileName : filename to write to ("-" to write to stdout)
59 \param delimiter : delimiter to use in the text file
60 \param nameHeader : used to label the name column in the output. If this
61 is provided as the empty string, no names will be
62 written.
63 \param includeHeader : toggles inclusion of a header line in the output
64 \param isomericSmiles : toggles generation of isomeric SMILES
65 \param kekuleSmiles : toggles the generation of kekule SMILES
66
67 */
68 SmilesWriter(const std::string &fileName, const std::string &delimiter = " ",
69 const std::string &nameHeader = "Name",
70 bool includeHeader = true, bool isomericSmiles = true,
71 bool kekuleSmiles = false);
72 //! \overload
73 SmilesWriter(std::ostream *outStream, std::string delimiter = " ",
74 std::string nameHeader = "Name", bool includeHeader = true,
75 bool takeOwnership = false, bool isomericSmiles = true,
76 bool kekuleSmiles = false);
77
78 ~SmilesWriter() override;
79
80 //! \brief set a vector of property names that are need to be
81 //! written out for each molecule
82 void setProps(const STR_VECT &propNames) override;
83
84 //! \brief write a new molecule to the file
85 void write(const ROMol &mol, int confId = defaultConfId) override;
86
87 //! \brief flush the ostream
88 void flush() override {
89 PRECONDITION(dp_ostream, "no output stream");
90 try {
91 dp_ostream->flush();
92 } catch (...) {
93 try {
94 if (dp_ostream->good()) {
95 dp_ostream->setstate(std::ios::badbit);
96 }
97 } catch (const std::runtime_error &) {
98 }
99 }
100 }
101
102 //! \brief close our stream (the writer cannot be used again)
103 void close() override {
104 if (dp_ostream) {
105 flush();
106 }
107 if (df_owner) {
108 delete dp_ostream;
109 df_owner = false;
110 }
111 dp_ostream = nullptr;
112 }
113
114 //! \brief get the number of molecules written so far
115 unsigned int numMols() const override { return d_molid; }
116
117 private:
118 // local initialization
119 void init(const std::string &delimiter, const std::string &nameHeader,
120 bool includeHeader, bool isomericSmiles, bool kekuleSmiles);
121
122 // dumps a header line to the output stream
123 void dumpHeader() const;
124
125 std::ostream *dp_ostream;
126 bool df_owner;
127 bool df_includeHeader; // whether or not to include a title line
128 unsigned int d_molid; // the number of the molecules we wrote so far
129 std::string d_delim; // delimiter string between various records
130 std::string d_nameHeader; // header for the name column in the output file
131 STR_VECT d_props; // list of property name that need to be written out
132 bool df_isomericSmiles; // whether or not to do isomeric smiles
133 bool df_kekuleSmiles; // whether or not to do kekule smiles
134};
135
136//! The SDWriter is for writing molecules and properties to
137//! SD files
139 /**************************************************************************************
140 * A SD file ( or stream) writer - this is how it is used
141 * - create a SDWriter with a output file name (or a ostream),
142 * and a list of properties that need to be written out
143 * - then a call is made to the write function for each molecule that needs
144 *to be written out
145 **********************************************************************************************/
146 public:
147 /*!
148 \param fileName : filename to write to ("-" to write to stdout)
149 */
150 SDWriter(const std::string &fileName);
151 SDWriter(std::ostream *outStream, bool takeOwnership = false);
152
153 ~SDWriter() override;
154
155 //! \brief set a vector of property names that are need to be
156 //! written out for each molecule
157 void setProps(const STR_VECT &propNames) override;
158
159 //! \brief return the text that would be written to the file
160 static std::string getText(const ROMol &mol, int confId = defaultConfId,
161 bool kekulize = true, bool force_V3000 = false,
162 int molid = -1, STR_VECT *propNames = nullptr);
163
164 //! \brief write a new molecule to the file
165 void write(const ROMol &mol, int confId = defaultConfId) override;
166
167 //! \brief flush the ostream
168 void flush() override {
169 PRECONDITION(dp_ostream, "no output stream");
170 try {
171 dp_ostream->flush();
172 } catch (...) {
173 try {
174 if (dp_ostream->good()) {
175 dp_ostream->setstate(std::ios::badbit);
176 }
177 } catch (const std::runtime_error &) {
178 }
179 }
180 }
181
182 //! \brief close our stream (the writer cannot be used again)
183 void close() override {
184 if (dp_ostream) {
185 flush();
186 }
187 if (df_owner) {
188 delete dp_ostream;
189 df_owner = false;
190 }
191 dp_ostream = nullptr;
192 }
193
194 //! \brief get the number of molecules written so far
195 unsigned int numMols() const override { return d_molid; }
196
197 void setForceV3000(bool val) { df_forceV3000 = val; }
198 bool getForceV3000() const { return df_forceV3000; }
199
200 void setKekulize(bool val) { df_kekulize = val; }
201 bool getKekulize() const { return df_kekulize; }
202
203 private:
204 void writeProperty(const ROMol &mol, const std::string &name);
205
206 std::ostream *dp_ostream;
207 bool df_owner;
208 unsigned int d_molid; // the number of the molecules we wrote so far
209 STR_VECT d_props; // list of property name that need to be written out
210 bool df_forceV3000; // force writing the mol blocks as V3000
211 bool df_kekulize; // toggle kekulization of molecules on writing
212};
213
214//! The TDTWriter is for writing molecules and properties to
215//! TDT files
217 /**************************************************************************************
218 * A TDT file ( or stream) writer - this is how it is used
219 * - create a TDTWriter with a output file name (or a ostream),
220 * and a list of properties that need to be written out
221 * - then a call is made to the write function for each molecule that needs
222 *to be written out
223 **********************************************************************************************/
224 public:
225 /*!
226 \param fileName : filename to write to ("-" to write to stdout)
227 */
228 TDTWriter(const std::string &fileName);
229 TDTWriter(std::ostream *outStream, bool takeOwnership = false);
230
231 ~TDTWriter() override;
232
233 //! \brief set a vector of property names that are need to be
234 //! written out for each molecule
235 void setProps(const STR_VECT &propNames) override;
236
237 //! \brief write a new molecule to the file
238 void write(const ROMol &mol, int confId = defaultConfId) override;
239
240 //! \brief flush the ostream
241 void flush() override {
242 PRECONDITION(dp_ostream, "no output stream");
243 try {
244 dp_ostream->flush();
245 } catch (...) {
246 try {
247 if (dp_ostream->good()) {
248 dp_ostream->setstate(std::ios::badbit);
249 }
250 } catch (const std::runtime_error &) {
251 }
252 }
253 }
254
255 //! \brief close our stream (the writer cannot be used again)
256 void close() override {
257 if (dp_ostream) {
258 // if we've written any mols, finish with a "|" line
259 if (d_molid > 0) {
260 *dp_ostream << "|\n";
261 }
262 flush();
263 }
264 if (df_owner) {
265 delete dp_ostream;
266 df_owner = false;
267 }
268 dp_ostream = nullptr;
269 }
270
271 //! \brief get the number of molecules written so far
272 unsigned int numMols() const override { return d_molid; }
273
274 void setWrite2D(bool state = true) { df_write2D = state; }
275 bool getWrite2D() const { return df_write2D; }
276
277 void setWriteNames(bool state = true) { df_writeNames = state; }
278 bool getWriteNames() const { return df_writeNames; }
279
280 void setNumDigits(unsigned int numDigits) { d_numDigits = numDigits; }
281 unsigned int getNumDigits() const { return d_numDigits; }
282
283 private:
284 void writeProperty(const ROMol &mol, const std::string &name);
285
286 std::ostream *dp_ostream;
287 bool df_owner;
288 unsigned int d_molid; // the number of molecules we wrote so far
289 STR_VECT d_props; // list of property name that need to be written out
290 bool df_write2D; // write 2D coordinates instead of 3D
291 bool df_writeNames; // write a name record for each molecule
292 unsigned int
293 d_numDigits; // number of digits to use in our output of coordinates;
294};
295
296//! The PDBWriter is for writing molecules to Brookhaven Protein
297//! DataBank format files.
299 public:
300 PDBWriter(const std::string &fileName, unsigned int flavor = 0);
301 PDBWriter(std::ostream *outStream, bool takeOwnership = false,
302 unsigned int flavor = 0);
303 ~PDBWriter() override;
304
305 //! \brief write a new molecule to the file
306 void write(const ROMol &mol, int confId = defaultConfId) override;
307
308 void setProps(const STR_VECT &) override {}
309
310 //! \brief flush the ostream
311 void flush() override {
312 PRECONDITION(dp_ostream, "no output stream");
313 try {
314 dp_ostream->flush();
315 } catch (...) {
316 try {
317 if (dp_ostream->good()) {
318 dp_ostream->setstate(std::ios::badbit);
319 }
320 } catch (const std::runtime_error &) {
321 }
322 }
323 }
324
325 //! \brief close our stream (the writer cannot be used again)
326 void close() override {
327 if (dp_ostream) {
328 flush();
329 }
330 if (df_owner) {
331 delete dp_ostream;
332 df_owner = false;
333 }
334 dp_ostream = nullptr;
335 }
336
337 //! \brief get the number of molecules written so far
338 unsigned int numMols() const override { return d_count; }
339
340 private:
341 std::ostream *dp_ostream;
342 unsigned int d_flavor;
343 unsigned int d_count;
344 bool df_owner;
345};
346
347#ifdef RDK_BUILD_MAEPARSER_SUPPORT
348
349class RDKIT_FILEPARSERS_EXPORT MaeWriter : public MolWriter {
350 /**************************************************************************************
351 * A highly experimental Maestro file (or stream) writer. Many features are
352 * not supported yet, e.g. chirality and bond stereo, stereo groups, substance
353 * groups, isotopes or dummy atoms. Note that except for stereochemistry
354 * labels these aren't supported by the MaeMolSupplier either.
355 *
356 * Usage:
357 * - create a MaeWriter with an output file name (or a ostream),
358 * and a list of mol/atom/bond properties that need to be written out.
359 * If no property names are specified, all properties will be exported.
360 * Properties that are specified, but are not present will be ignored.
361 * - then, a call is made to the write function for each molecule
362 * that needs to be written out.
363 *
364 * Notes:
365 * - kekulization is mandatory, as the Maestro format does not
366 * have the concept of an aromatic bond.
367 * - Ownership of the output stream is mandatory, since it needs
368 * to be managed though a shared_ptr, as this is what maeparser
369 * writer takes.
370 ***************************************************************************************/
371 public:
372 /*!
373 \param fileName : filename to write to (stdout is *not* supported)
374 */
375 MaeWriter(const std::string &fileName);
376
377 /*!
378 \note Note that this takes ownership of the output stream.
379 */
380 MaeWriter(std::ostream *outStream);
381
382 MaeWriter(std::shared_ptr<std::ostream> outStream);
383
384 ~MaeWriter() override;
385
386 //! \brief set a vector of property names that are need to be
387 //! written out for each molecule
388 void setProps(const STR_VECT &propNames) override;
389
390 //! \brief return the text that would be written to the file
391 static std::string getText(const ROMol &mol, int confId = defaultConfId,
392 const STR_VECT &propNames = STR_VECT());
393
394 //! \brief write a new molecule to the file.
395 void write(const ROMol &mol, int confId = defaultConfId) override;
396
397 //! \brief flush the ostream
398 void flush() override;
399 //! \brief close our stream (the writer cannot be used again)
400 void close() override;
401
402 //! \brief get the number of molecules written so far
403 unsigned int numMols() const override { return d_molid; }
404
405 protected:
406 MaeWriter() = default; // used in the Python wrapper
407
408 std::shared_ptr<std::ostream> dp_ostream;
409
410 private:
411 void open();
412
413 std::unique_ptr<schrodinger::mae::Writer> dp_writer;
414 unsigned d_molid = 0; // the number of the molecules we wrote so far
415 STR_VECT d_props; // list of property name that need to be written out
416};
417
418#endif // RDK_BUILD_MAEPARSER_SUPPORT
419
420} // namespace RDKit
421
422#endif
#define PRECONDITION(expr, mess)
Definition Invariant.h:108
Defines the primary molecule class ROMol as well as associated typedefs.
virtual void flush()=0
virtual void write(const ROMol &mol, int confId=defaultConfId)=0
virtual ~MolWriter()
Definition MolWriters.h:36
MolWriter()=default
MolWriter & operator=(const MolWriter &)=delete
virtual void close()=0
virtual void setProps(const STR_VECT &propNames)=0
MolWriter(const MolWriter &)=delete
virtual unsigned int numMols() const =0
PDBWriter(const std::string &fileName, unsigned int flavor=0)
void write(const ROMol &mol, int confId=defaultConfId) override
write a new molecule to the file
void flush() override
flush the ostream
Definition MolWriters.h:311
PDBWriter(std::ostream *outStream, bool takeOwnership=false, unsigned int flavor=0)
void setProps(const STR_VECT &) override
Definition MolWriters.h:308
~PDBWriter() override
unsigned int numMols() const override
get the number of molecules written so far
Definition MolWriters.h:338
void close() override
close our stream (the writer cannot be used again)
Definition MolWriters.h:326
~SDWriter() override
bool getForceV3000() const
Definition MolWriters.h:198
unsigned int numMols() const override
get the number of molecules written so far
Definition MolWriters.h:195
SDWriter(std::ostream *outStream, bool takeOwnership=false)
bool getKekulize() const
Definition MolWriters.h:201
void flush() override
flush the ostream
Definition MolWriters.h:168
void setProps(const STR_VECT &propNames) override
set a vector of property names that are need to be written out for each molecule
void write(const ROMol &mol, int confId=defaultConfId) override
write a new molecule to the file
static std::string getText(const ROMol &mol, int confId=defaultConfId, bool kekulize=true, bool force_V3000=false, int molid=-1, STR_VECT *propNames=nullptr)
return the text that would be written to the file
void close() override
close our stream (the writer cannot be used again)
Definition MolWriters.h:183
void setForceV3000(bool val)
Definition MolWriters.h:197
SDWriter(const std::string &fileName)
void setKekulize(bool val)
Definition MolWriters.h:200
unsigned int numMols() const override
get the number of molecules written so far
Definition MolWriters.h:115
SmilesWriter(const std::string &fileName, const std::string &delimiter=" ", const std::string &nameHeader="Name", bool includeHeader=true, bool isomericSmiles=true, bool kekuleSmiles=false)
void write(const ROMol &mol, int confId=defaultConfId) override
write a new molecule to the file
~SmilesWriter() override
SmilesWriter(std::ostream *outStream, std::string delimiter=" ", std::string nameHeader="Name", bool includeHeader=true, bool takeOwnership=false, bool isomericSmiles=true, bool kekuleSmiles=false)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setProps(const STR_VECT &propNames) override
set a vector of property names that are need to be written out for each molecule
void close() override
close our stream (the writer cannot be used again)
Definition MolWriters.h:103
void flush() override
flush the ostream
Definition MolWriters.h:88
~TDTWriter() override
bool getWrite2D() const
Definition MolWriters.h:275
void setNumDigits(unsigned int numDigits)
Definition MolWriters.h:280
void setWrite2D(bool state=true)
Definition MolWriters.h:274
void setProps(const STR_VECT &propNames) override
set a vector of property names that are need to be written out for each molecule
unsigned int numMols() const override
get the number of molecules written so far
Definition MolWriters.h:272
unsigned int getNumDigits() const
Definition MolWriters.h:281
TDTWriter(std::ostream *outStream, bool takeOwnership=false)
void close() override
close our stream (the writer cannot be used again)
Definition MolWriters.h:256
TDTWriter(const std::string &fileName)
void write(const ROMol &mol, int confId=defaultConfId) override
write a new molecule to the file
void setWriteNames(bool state=true)
Definition MolWriters.h:277
void flush() override
flush the ostream
Definition MolWriters.h:241
bool getWriteNames() const
Definition MolWriters.h:278
#define RDKIT_FILEPARSERS_EXPORT
Definition export.h:221
Std stuff.
std::vector< std::string > STR_VECT
Definition Dict.h:29
static int defaultConfId
Definition MolWriters.h:29