// $Id$ // // Copyright (C) 2005-2010 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 #include #include #include #include "MolWriters.h" #include "FileParsers.h" #include #include #include #include #include #include namespace RDKit { TDTWriter::TDTWriter(const std::string &fileName) { if (fileName != "-") { auto *tmpStream = new std::ofstream(fileName.c_str()); if (!tmpStream || !(*tmpStream) || (tmpStream->bad())) { std::ostringstream errout; errout << "Bad output file " << fileName; throw BadFileException(errout.str()); } dp_ostream = static_cast(tmpStream); df_owner = true; } else { dp_ostream = static_cast(&std::cout); df_owner = false; } d_molid = 0; d_numDigits = 4; df_write2D = false; df_writeNames = true; } TDTWriter::TDTWriter(std::ostream *outStream, bool takeOwnership) { PRECONDITION(outStream, "null stream"); if (outStream->bad()) { throw FileParseException("Bad output stream"); } dp_ostream = outStream; df_owner = takeOwnership; d_molid = 0; d_numDigits = 4; df_write2D = false; df_writeNames = true; } TDTWriter::~TDTWriter() { // if we've written any mols, finish with a "|" line if (d_molid > 0) { CHECK_INVARIANT(dp_ostream, "null outstream even though molecules were written"); (*dp_ostream) << "|\n"; } if (df_owner) { delete dp_ostream; } } void TDTWriter::setProps(const STR_VECT &propNames) { if (d_molid > 0) { BOOST_LOG(rdWarningLog) << "WARNING: Setting property list after a few " "molecules have been written\n"; } d_props = propNames; } void TDTWriter::write(const ROMol &mol, int confId) { CHECK_INVARIANT(dp_ostream, "no output stream"); // start by writing a "|" line unless this is the first line if (d_molid > 0) { (*dp_ostream) << "|\n"; } // write the molecule (*dp_ostream) << "$SMI<" << MolToSmiles(mol) << ">\n"; std::string name; if (df_writeNames && mol.getPropIfPresent(common_properties::_Name, name)) { (*dp_ostream) << "NAME<" << name << ">\n"; } // do we need to write coordinates? if (mol.getNumConformers()) { // get the ordering of the atoms in the output SMILES: std::vector atomOrdering; mol.getProp(common_properties::_smilesAtomOutputOrder, atomOrdering); const Conformer &conf = mol.getConformer(confId); if (df_write2D) { (*dp_ostream) << "2D<"; } else { (*dp_ostream) << "3D<"; } const RDGeom::POINT3D_VECT &coords = conf.getPositions(); int nAts = atomOrdering.size(); for (int i = 0; i < nAts; i++) { (*dp_ostream) << std::setprecision(d_numDigits) << coords[atomOrdering[i]].x << ","; (*dp_ostream) << std::setprecision(d_numDigits) << coords[atomOrdering[i]].y; if (!df_write2D) { (*dp_ostream) << "," << std::setprecision(d_numDigits) << coords[atomOrdering[i]].z; } if (i != nAts - 1) (*dp_ostream) << ","; } (*dp_ostream) << ";>\n"; } // now write the properties STR_VECT_CI pi; if (d_props.size() > 0) { // check if we have any properties the user specified to write out // in which loop over them and write them out for (pi = d_props.begin(); pi != d_props.end(); pi++) { if (mol.hasProp(*pi)) { writeProperty(mol, (*pi)); } } } else { // if use did not specify any properties, write all non computed properties // out to the file STR_VECT properties = mol.getPropList(); STR_VECT compLst; mol.getPropIfPresent(RDKit::detail::computedPropName, compLst); STR_VECT_CI pi; for (pi = properties.begin(); pi != properties.end(); pi++) { // ignore any of the following properties if (((*pi) == RDKit::detail::computedPropName) || ((*pi) == common_properties::_Name) || ((*pi) == "_MolFileInfo") || ((*pi) == "_MolFileComments") || ((*pi) == common_properties::_MolFileChiralFlag)) { continue; } // check if this property is not computed if (std::find(compLst.begin(), compLst.end(), (*pi)) == compLst.end()) { writeProperty(mol, (*pi)); } } } d_molid++; } void TDTWriter::writeProperty(const ROMol &mol, const std::string &name) { PRECONDITION(dp_ostream, "no output stream"); (*dp_ostream) << name << "<"; // write the property value // FIX: we will assume for now that the desired property value is // catable to a string std::string pval; // we need to remove any line breaks in the output, replace them with spaces mol.getProp(name, pval); boost::replace_all(pval, "\n", " "); (*dp_ostream) << pval << ">\n"; } }