Skip to content

Commit 03379a3

Browse files
committed
Add some options to the high-level SMILESWriter, like the SmilesGenerator we can now specify the flavour and also if we should add a title or not (true by default)
1 parent d03765c commit 03379a3

File tree

2 files changed

+125
-28
lines changed

2 files changed

+125
-28
lines changed

storage/smiles/src/main/java/org/openscience/cdk/io/SMILESWriter.java

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,40 +31,40 @@
3131
import org.openscience.cdk.io.formats.SMILESFormat;
3232
import org.openscience.cdk.io.setting.BooleanIOSetting;
3333
import org.openscience.cdk.io.setting.IOSetting;
34+
import org.openscience.cdk.io.setting.IntegerIOSetting;
35+
import org.openscience.cdk.smiles.SmiFlavor;
3436
import org.openscience.cdk.smiles.SmilesGenerator;
3537
import org.openscience.cdk.tools.ILoggingTool;
3638
import org.openscience.cdk.tools.LoggingToolFactory;
3739

38-
import java.io.BufferedWriter;
39-
import java.io.FileOutputStream;
40-
import java.io.IOException;
41-
import java.io.OutputStream;
42-
import java.io.OutputStreamWriter;
43-
import java.io.StringWriter;
44-
import java.io.Writer;
40+
import java.io.*;
4541

4642
/**
4743
* Writes the SMILES strings to a plain text file.
4844
*
49-
* @cdk.module smiles
45+
* @cdk.module smiles
5046
* @cdk.githash
5147
* @cdk.iooptions
52-
*
5348
* @cdk.keyword file format, SMILES
5449
*/
5550
public class SMILESWriter extends DefaultChemObjectWriter {
5651

5752
private static ILoggingTool logger = LoggingToolFactory.createLoggingTool(SMILESWriter.class);
58-
private BufferedWriter writer;
59-
60-
private BooleanIOSetting useAromaticityFlag;
53+
private BufferedWriter writer;
54+
private BooleanIOSetting aromSetting;
55+
private BooleanIOSetting titleSetting;
56+
private IntegerIOSetting flavorSetting;
57+
private int flav = SmiFlavor.Default;
58+
private SmilesGenerator smigen = new SmilesGenerator(flav);
59+
private StringBuilder buffer = new StringBuilder();
6160

6261
/**
6362
* Constructs a new SMILESWriter that can write a list of SMILES to a Writer
6463
*
65-
* @param out The Writer to write to
64+
* @param out The Writer to write to
6665
*/
6766
public SMILESWriter(Writer out) {
67+
ByteArrayOutputStream bout;
6868
try {
6969
if (out instanceof BufferedWriter) {
7070
writer = (BufferedWriter) out;
@@ -84,6 +84,24 @@ public SMILESWriter() {
8484
this(new StringWriter());
8585
}
8686

87+
public void setFlavor(int flav) {
88+
try {
89+
flavorSetting.setSetting(Integer.toBinaryString(flav));
90+
} catch (CDKException e) {
91+
// ignored
92+
}
93+
customizeJob();
94+
}
95+
96+
public void setWriteTitle(boolean val) {
97+
try {
98+
titleSetting.setSetting(Boolean.toString(val));
99+
} catch (CDKException e) {
100+
// ignored
101+
}
102+
customizeJob();
103+
}
104+
87105
@Override
88106
public IResourceFormat getFormat() {
89107
return SMILESFormat.getInstance();
@@ -106,7 +124,7 @@ public void setWriter(OutputStream output) throws CDKException {
106124
/**
107125
* Constructs a new SMILESWriter that can write an list of SMILES to a given OutputStream
108126
*
109-
* @param out The OutputStream to write to
127+
* @param out The OutputStream to write to
110128
*/
111129
public SMILESWriter(FileOutputStream out) {
112130
this(new OutputStreamWriter(out));
@@ -138,7 +156,7 @@ public boolean accepts(Class<? extends IChemObject> classObject) {
138156
/**
139157
* Writes the content from object to output.
140158
*
141-
* @param object IChemObject of which the data is given as output.
159+
* @param object IChemObject of which the data is given as output.
142160
*/
143161
@Override
144162
public void write(IChemObject object) throws CDKException {
@@ -154,7 +172,7 @@ public void write(IChemObject object) throws CDKException {
154172
/**
155173
* Writes a list of molecules to an OutputStream.
156174
*
157-
* @param som MoleculeSet that is written to an OutputStream
175+
* @param som MoleculeSet that is written to an OutputStream
158176
*/
159177
public void writeAtomContainerSet(IAtomContainerSet som) {
160178
writeAtomContainer(som.getAtomContainer(0));
@@ -169,32 +187,41 @@ public void writeAtomContainerSet(IAtomContainerSet som) {
169187
/**
170188
* Writes the content from molecule to output.
171189
*
172-
* @param molecule Molecule of which the data is given as output.
190+
* @param molecule Molecule of which the data is given as output.
173191
*/
174192
public void writeAtomContainer(IAtomContainer molecule) {
175-
SmilesGenerator sg = new SmilesGenerator();
176-
if (useAromaticityFlag.isSet()) sg = sg.aromatic();
177-
String smiles = "";
178193
try {
179-
smiles = sg.create(molecule);
180-
logger.debug("Generated SMILES: " + smiles);
181-
writer.write(smiles);
182-
writer.write('\n');
194+
buffer.setLength(0);
195+
buffer.append(smigen.create(molecule));
196+
if (titleSetting.isSet() && molecule.getTitle() != null)
197+
buffer.append('\t').append(molecule.getTitle());
198+
buffer.append('\n');
199+
writer.write(buffer.toString());
183200
writer.flush();
184-
logger.debug("file flushed...");
185201
} catch (CDKException | IOException exc) {
186202
logger.error("Error while writing Molecule: ", exc.getMessage());
187203
logger.debug(exc);
188204
}
189205
}
190206

207+
191208
private void initIOSettings() {
192-
useAromaticityFlag = addSetting(new BooleanIOSetting("UseAromaticity", IOSetting.Importance.LOW,
209+
flavorSetting = addSetting(new IntegerIOSetting("SmilesFlavor", IOSetting.Importance.HIGH,
210+
"Output SMILES flavor, binary option", Integer.toString(SmiFlavor.Default)));
211+
titleSetting = addSetting(new BooleanIOSetting("WriteTitle", IOSetting.Importance.HIGH,
212+
"Write the molecule title after the SMILES", "true"));
213+
aromSetting = addSetting(new BooleanIOSetting("UseAromaticity", IOSetting.Importance.LOW,
193214
"Should aromaticity information be stored in the SMILES?", "false"));
194215
}
195216

196217
public void customizeJob() {
197-
fireIOSettingQuestion(useAromaticityFlag);
218+
fireIOSettingQuestion(flavorSetting);
219+
fireIOSettingQuestion(titleSetting);
220+
fireIOSettingQuestion(aromSetting);
221+
int flav = flavorSetting.getSettingValue();
222+
if (aromSetting.isSet())
223+
flav |= SmiFlavor.UseAromaticSymbols;
224+
smigen = new SmilesGenerator(flav);
198225
}
199226

200227
}

storage/smiles/src/test/java/org/openscience/cdk/io/SMILESWriterTest.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
package org.openscience.cdk.io;
2424

2525
import java.io.StringWriter;
26+
import java.util.Arrays;
27+
import java.util.HashSet;
2628
import java.util.Properties;
2729

2830
import org.junit.Assert;
@@ -33,14 +35,19 @@
3335
import org.openscience.cdk.aromaticity.Aromaticity;
3436
import org.openscience.cdk.interfaces.IAtomContainer;
3537
import org.openscience.cdk.io.listener.PropertiesListener;
38+
import org.openscience.cdk.silent.SilentChemObjectBuilder;
39+
import org.openscience.cdk.smiles.SmiFlavor;
40+
import org.openscience.cdk.smiles.SmilesParser;
3641
import org.openscience.cdk.templates.TestMoleculeFactory;
3742
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
3843

44+
import static org.hamcrest.CoreMatchers.*;
45+
import static org.hamcrest.MatcherAssert.assertThat;
46+
3947
/**
4048
* TestCase for the writer for SMILES files.
4149
*
4250
* @cdk.module test-smiles
43-
*
4451
* @see org.openscience.cdk.io.SMILESWriter
4552
*/
4653
public class SMILESWriterTest extends ChemObjectIOTest {
@@ -86,4 +93,67 @@ public void testWriteAromatic() throws Exception {
8693
Assert.assertFalse(stringWriter.toString().contains("C=C"));
8794
Assert.assertTrue(stringWriter.toString().contains("ccc"));
8895
}
96+
97+
@Test
98+
public void testWriteNonCanon() throws Exception {
99+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
100+
IAtomContainer mol1 = smipar.parseSmiles("CCO");
101+
IAtomContainer mol2 = smipar.parseSmiles("OCC");
102+
StringWriter wtr = new StringWriter();
103+
try (SMILESWriter smigen = new SMILESWriter(wtr)) {
104+
smigen.write(mol1);
105+
smigen.write(mol2);
106+
}
107+
String[] lines = wtr.toString().split("\n");
108+
assertThat(lines.length, is(2));
109+
assertThat(new HashSet<>(Arrays.asList(lines)).size(), is(2));
110+
}
111+
112+
@Test
113+
public void testWriteCanon() throws Exception {
114+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
115+
IAtomContainer mol1 = smipar.parseSmiles("CCO");
116+
IAtomContainer mol2 = smipar.parseSmiles("OCC");
117+
StringWriter wtr = new StringWriter();
118+
try (SMILESWriter smigen = new SMILESWriter(wtr)) {
119+
smigen.setFlavor(SmiFlavor.Canonical);
120+
smigen.write(mol1);
121+
smigen.write(mol2);
122+
}
123+
String[] lines = wtr.toString().split("\n");
124+
assertThat(lines.length, is(2));
125+
assertThat(new HashSet<>(Arrays.asList(lines)).size(), is(1));
126+
}
127+
128+
@Test
129+
public void testWriteWithTitle() throws Exception {
130+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
131+
IAtomContainer mol1 = smipar.parseSmiles("CCO mol 1");
132+
IAtomContainer mol2 = smipar.parseSmiles("OCC mol 2");
133+
StringWriter wtr = new StringWriter();
134+
try (SMILESWriter smigen = new SMILESWriter(wtr)) {
135+
smigen.setFlavor(SmiFlavor.Canonical);
136+
smigen.setWriteTitle(true);
137+
smigen.write(mol1);
138+
smigen.write(mol2);
139+
}
140+
assertThat(wtr.toString(), containsString("mol 1"));
141+
assertThat(wtr.toString(), containsString("mol 2"));
142+
}
143+
144+
@Test
145+
public void testWriteWithoutTitle() throws Exception {
146+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
147+
IAtomContainer mol1 = smipar.parseSmiles("CCO mol 1");
148+
IAtomContainer mol2 = smipar.parseSmiles("OCC mol 2");
149+
StringWriter wtr = new StringWriter();
150+
try (SMILESWriter smigen = new SMILESWriter(wtr)) {
151+
smigen.setFlavor(SmiFlavor.Canonical);
152+
smigen.setWriteTitle(false);
153+
smigen.write(mol1);
154+
smigen.write(mol2);
155+
}
156+
assertThat(wtr.toString(), not(containsString("mol 1")));
157+
assertThat(wtr.toString(), not(containsString("mol 2")));
158+
}
89159
}

0 commit comments

Comments
 (0)