Skip to content

Commit f37f053

Browse files
committed
Update Beam and SmilesParser to be more relaxed on double bond stereo issues. Beam changes
- allowing strict/relaxed parsing from external API - better reporting of double bond stereo errors - ignore double bond stereo errors if in relaxed mode
1 parent 22e5230 commit f37f053

File tree

4 files changed

+55
-6
lines changed

4 files changed

+55
-6
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,12 @@
415415
<dependency>
416416
<groupId>uk.ac.ebi.beam</groupId>
417417
<artifactId>beam-core</artifactId>
418-
<version>1.2</version>
418+
<version>1.3.1</version>
419419
</dependency>
420420
<dependency>
421421
<groupId>uk.ac.ebi.beam</groupId>
422422
<artifactId>beam-func</artifactId>
423-
<version>1.2</version>
423+
<version>1.3.1</version>
424424
</dependency>
425425
<dependency>
426426
<groupId>com.google.guava</groupId>

storage/smiles/src/main/java/org/openscience/cdk/smiles/BeamToCDK.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,17 @@ private Edge findDirectionalEdge(Graph g, int u) {
420420
List<Edge> edges = g.edges(u);
421421
if (edges.size() == 1)
422422
return null;
423+
Edge first = null;
423424
for (Edge e : edges) {
424425
Bond b = e.bond();
425-
if (b == Bond.UP || b == Bond.DOWN) return e;
426+
if (b == Bond.UP || b == Bond.DOWN) {
427+
if (first == null)
428+
first = e;
429+
else if (((first.either() == e.either()) == (first.bond() == b)))
430+
return null;
431+
}
426432
}
427-
return null;
433+
return first;
428434
}
429435

430436
/**

storage/smiles/src/main/java/org/openscience/cdk/smiles/SmilesParser.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import org.openscience.cdk.sgroup.SgroupType;
4444
import org.openscience.cdk.smiles.CxSmilesState.DataSgroup;
4545
import org.openscience.cdk.smiles.CxSmilesState.PolymerSgroup;
46+
import org.openscience.cdk.tools.ILoggingTool;
47+
import org.openscience.cdk.tools.LoggingToolFactory;
4648
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
4749
import uk.ac.ebi.beam.Graph;
4850

@@ -130,6 +132,8 @@
130132
*/
131133
public final class SmilesParser {
132134

135+
private ILoggingTool logger = LoggingToolFactory.createLoggingTool(SmilesParser.class);
136+
133137
/**
134138
* The builder determines which CDK domain objects to create.
135139
*/
@@ -149,6 +153,11 @@ public final class SmilesParser {
149153
*/
150154
private boolean kekulise = true;
151155

156+
/**
157+
* Whether the parser is in strict mode or not.
158+
*/
159+
private boolean strict = false;
160+
152161
/**
153162
* Create a new SMILES parser which will create {@link IAtomContainer}s with
154163
* the specified builder.
@@ -160,6 +169,16 @@ public SmilesParser(final IChemObjectBuilder builder) {
160169
this.beamToCDK = new BeamToCDK(builder);
161170
}
162171

172+
/**
173+
* Sets whether the parser is in strict mode. In non-strict mode (default)
174+
* recoverable issues with SMILES are reported as warnings.
175+
*
176+
* @param strict strict mode true/false.
177+
*/
178+
public void setStrict(boolean strict) {
179+
this.strict = strict;
180+
}
181+
163182
/**
164183
* Parse a reaction SMILES.
165184
*
@@ -239,8 +258,11 @@ public IAtomContainer parseSmiles(String smiles) throws InvalidSmilesException {
239258

240259
private IAtomContainer parseSmiles(String smiles, boolean isRxnPart) throws InvalidSmilesException {
241260
try {
242-
// create the Beam object from the SMILES
243-
Graph g = Graph.fromSmiles(smiles);
261+
// create the Beam object from parsing the SMILES
262+
Set<String> warnings = new HashSet<>();
263+
Graph g = Graph.parse(smiles, strict, warnings);
264+
for (String warning : warnings)
265+
logger.warn(warning);
244266

245267
// convert the Beam object model to the CDK - note exception thrown
246268
// if a kekule structure could not be assigned.

storage/smiles/src/test/java/org/openscience/cdk/smiles/SmilesParserTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,6 +2663,27 @@ public void notExtendedCis() throws Exception {
26632663
assertFalse(mol.stereoElements().iterator().hasNext());
26642664
}
26652665

2666+
@Test
2667+
public void warnOnDirectionalBonds() throws InvalidSmilesException {
2668+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
2669+
IAtomContainer mol = smipar.parseSmiles("C/C=C/1.C/1");
2670+
}
2671+
2672+
@Test(expected = InvalidSmilesException.class)
2673+
public void failOnDirectionalBondsWhenStrict() throws InvalidSmilesException {
2674+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
2675+
smipar.setStrict(true);
2676+
IAtomContainer mol = smipar.parseSmiles("C/C=C/1.C/1");
2677+
}
2678+
2679+
@Test
2680+
public void ignoreDoubleBond() throws InvalidSmilesException {
2681+
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
2682+
IAtomContainer mol = smipar.parseSmiles("C/C=C(/F)/C");
2683+
assertThat(mol.stereoElements().iterator().hasNext(),
2684+
is(false));
2685+
}
2686+
26662687
@Test public void extendedTetrahedral7() throws InvalidSmilesException {
26672688
IAtomContainer mol = load("CC=C=C=[C@]=C=C=CC");
26682689
for (IStereoElement se : mol.stereoElements()) {

0 commit comments

Comments
 (0)