Skip to content

Commit a5ef532

Browse files
committed
Lilly/CACTVS/NextMove support inequalities in expressions (e.g. D>1).
1 parent 78681bb commit a5ef532

File tree

2 files changed

+190
-24
lines changed

2 files changed

+190
-24
lines changed

tool/smarts/src/main/java/org/openscience/cdk/smarts/Smarts.java

Lines changed: 162 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,45 @@ private boolean parseRange(Expr expr) {
321321
return next() == '}';
322322
}
323323

324+
private boolean parseGt(Expr expr) {
325+
if (next() != '>')
326+
return false;
327+
int lo = nextUnsignedInt();
328+
Expr.Type type = expr.type();
329+
330+
// adjusted types
331+
switch (type) {
332+
case HAS_IMPLICIT_HYDROGEN:
333+
type = IMPL_H_COUNT;
334+
break;
335+
}
336+
337+
expr.setPrimitive(type, 0);
338+
expr.negate();
339+
for (int i = 1; i <= lo; i++)
340+
expr.and(new Expr(type, i).negate());
341+
return true;
342+
}
343+
344+
private boolean parseLt(Expr expr) {
345+
if (next() != '<')
346+
return false;
347+
int lo = nextUnsignedInt();
348+
Expr.Type type = expr.type();
349+
350+
// adjusted types
351+
switch (type) {
352+
case HAS_IMPLICIT_HYDROGEN:
353+
type = IMPL_H_COUNT;
354+
break;
355+
}
356+
357+
expr.setPrimitive(type, 0);
358+
for (int i = 1; i < lo; i++)
359+
expr.or(new Expr(type, i));
360+
return true;
361+
}
362+
324363
boolean parseAtomExpr(IAtom atom, Expr dest, char lastOp) {
325364
Expr expr = null;
326365
int num;
@@ -449,9 +488,23 @@ boolean parseAtomExpr(IAtom atom, Expr dest, char lastOp) {
449488
expr = new Expr(HEAVY_DEGREE, 1);
450489
else
451490
expr = new Expr(DEGREE, 1);
452-
// CACTVS style ranges D{0-2}
453-
if (peek() == '{' && !parseRange(expr))
454-
return false;
491+
switch (peek()) {
492+
case '{':
493+
// CACTVS style ranges D{0-2}
494+
if (!parseRange(expr))
495+
return false;
496+
break;
497+
case '>':
498+
// Lilly/CACTVS/NextMove inequalities
499+
if (!parseGt(expr))
500+
return false;
501+
break;
502+
case '<':
503+
// Lilly/CACTVS/NextMove inequalities
504+
if (!parseLt(expr))
505+
return false;
506+
break;
507+
}
455508
} else {
456509
if (isFlavor(FLAVOR_CDK_LEGACY))
457510
expr = new Expr(HEAVY_DEGREE, num);
@@ -543,9 +596,23 @@ else if (isFlavor(FLAVOR_CACTVS))
543596
num = nextUnsignedInt();
544597
if (num < 0) {
545598
expr = new Expr(TOTAL_H_COUNT, 1);
546-
// CACTVS style ranges H{0-2}
547-
if (peek() == '{' && !parseRange(expr))
548-
return false;
599+
switch (peek()) {
600+
case '{':
601+
// CACTVS style ranges H{0-2}
602+
if (!parseRange(expr))
603+
return false;
604+
break;
605+
case '>':
606+
// Lilly/CACTVS/NextMove inequalities
607+
if (!parseGt(expr))
608+
return false;
609+
break;
610+
case '<':
611+
// Lilly/CACTVS/NextMove inequalities
612+
if (!parseLt(expr))
613+
return false;
614+
break;
615+
}
549616
} else
550617
expr = new Expr(TOTAL_H_COUNT, num);
551618
break;
@@ -732,11 +799,25 @@ else if (isFlavor(FLAVOR_CACTVS))
732799
num = nextUnsignedInt();
733800
if (num < 0) {
734801
expr = new Expr(Expr.Type.IS_IN_RING);
735-
// CACTVS style ranges R{0-2}
736-
if (peek() == '{') {
737-
expr.setPrimitive(RING_COUNT, 0);
738-
if (!parseRange(expr))
739-
return false;
802+
switch (peek()) {
803+
case '{':
804+
// CACTVS style ranges H{0-2}
805+
expr.setPrimitive(RING_COUNT, 0);
806+
if (!parseRange(expr))
807+
return false;
808+
break;
809+
case '>':
810+
// Lilly/CACTVS/NextMove inequalities
811+
expr.setPrimitive(RING_COUNT, 0);
812+
if (!parseGt(expr))
813+
return false;
814+
break;
815+
case '<':
816+
// Lilly/CACTVS/NextMove inequalities
817+
expr.setPrimitive(RING_COUNT, 0);
818+
if (!parseLt(expr))
819+
return false;
820+
break;
740821
}
741822
}
742823
else if (num == 0)
@@ -847,9 +928,23 @@ else if (isFlavor(FLAVOR_OECHEM))
847928
num = nextUnsignedInt();
848929
if (num < 0) {
849930
expr = new Expr(TOTAL_DEGREE, 1);
850-
// CACTVS style ranges X{0-2}
851-
if (peek() == '{' && !parseRange(expr))
852-
return false;
931+
switch (peek()) {
932+
case '{':
933+
// CACTVS style ranges X{0-2}
934+
if (!parseRange(expr))
935+
return false;
936+
break;
937+
case '>':
938+
// Lilly/CACTVS/NextMove inequalities
939+
if (!parseGt(expr))
940+
return false;
941+
break;
942+
case '<':
943+
// Lilly/CACTVS/NextMove inequalities
944+
if (!parseLt(expr))
945+
return false;
946+
break;
947+
}
853948
} else
854949
expr = new Expr(TOTAL_DEGREE, num);
855950
break;
@@ -983,18 +1078,47 @@ else if (num > 2)
9831078
if (num < 0) {
9841079
expr = new Expr(Expr.Type.VALENCE, 1);
9851080
// CACTVS style ranges v{0-2}
986-
if (peek() == '{' && !parseRange(expr))
987-
return false;
1081+
switch (peek()) {
1082+
case '{':
1083+
// CACTVS style ranges v{0-2}
1084+
if (!parseRange(expr))
1085+
return false;
1086+
break;
1087+
case '>':
1088+
// Lilly/CACTVS/NextMove inequalities
1089+
if (!parseGt(expr))
1090+
return false;
1091+
break;
1092+
case '<':
1093+
// Lilly/CACTVS/NextMove inequalities
1094+
if (!parseLt(expr))
1095+
return false;
1096+
break;
1097+
}
9881098
} else
9891099
expr = new Expr(Expr.Type.VALENCE, num);
9901100
break;
9911101
case 'h':
9921102
num = nextUnsignedInt();
9931103
if (num < 0) {
9941104
expr = new Expr(Expr.Type.HAS_IMPLICIT_HYDROGEN);
995-
// CACTVS style ranges h{0-2}
996-
if (peek() == '{' && !parseRange(expr))
997-
return false;
1105+
switch (peek()) {
1106+
case '{':
1107+
// CACTVS style ranges h{0-2}
1108+
if (!parseRange(expr))
1109+
return false;
1110+
break;
1111+
case '>':
1112+
// Lilly/CACTVS/NextMove inequalities
1113+
if (!parseGt(expr))
1114+
return false;
1115+
break;
1116+
case '<':
1117+
// Lilly/CACTVS/NextMove inequalities
1118+
if (!parseLt(expr))
1119+
return false;
1120+
break;
1121+
}
9981122
}
9991123
else
10001124
expr = new Expr(Expr.Type.IMPL_H_COUNT, num);
@@ -1003,11 +1127,25 @@ else if (num > 2)
10031127
num = nextUnsignedInt();
10041128
if (num < 0) {
10051129
expr = new Expr(Expr.Type.IS_IN_RING);
1006-
// CACTVS style ranges D{0-2}
1007-
if (peek() == '{') {
1008-
expr.setPrimitive(RING_BOND_COUNT, 0);
1009-
if (!parseRange(expr))
1010-
return false;
1130+
switch (peek()) {
1131+
case '{':
1132+
// CACTVS style ranges x{0-2}
1133+
expr.setPrimitive(RING_BOND_COUNT, 0);
1134+
if (!parseRange(expr))
1135+
return false;
1136+
break;
1137+
case '>':
1138+
// Lilly/CACTVS/NextMove inequalities
1139+
expr.setPrimitive(RING_BOND_COUNT, 0);
1140+
if (!parseGt(expr))
1141+
return false;
1142+
break;
1143+
case '<':
1144+
// Lilly/CACTVS/NextMove inequalities
1145+
expr.setPrimitive(RING_BOND_COUNT, 0);
1146+
if (!parseLt(expr))
1147+
return false;
1148+
break;
10111149
}
10121150
}
10131151
else if (num == 0)

tool/smarts/src/test/java/org/openscience/cdk/smarts/SmartsExprReadTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,4 +949,32 @@ public void ringSmallestSizeCountRange() {
949949
or(expr(RING_SMALLEST, 6),
950950
expr(RING_SMALLEST, 7)))));
951951
}
952+
953+
@Test
954+
public void supportHGt() {
955+
Expr expr = getAtomExpr("[H>1]");
956+
assertThat(expr, is(and(expr(TOTAL_H_COUNT, 0).negate(),
957+
expr(TOTAL_H_COUNT, 1).negate())));
958+
}
959+
960+
@Test
961+
public void supportHLt() {
962+
Expr expr = getAtomExpr("[H<2]");
963+
assertThat(expr, is(or(expr(TOTAL_H_COUNT, 0),
964+
expr(TOTAL_H_COUNT, 1))));
965+
}
966+
967+
@Test
968+
public void supportDGt() {
969+
Expr expr = getAtomExpr("[D>1]");
970+
assertThat(expr, is(and(expr(DEGREE, 0).negate(),
971+
expr(DEGREE, 1).negate())));
972+
}
973+
974+
@Test
975+
public void supportDLt() {
976+
Expr expr = getAtomExpr("[D<2]");
977+
assertThat(expr, is(or(expr(DEGREE, 0),
978+
expr(DEGREE, 1))));
979+
}
952980
}

0 commit comments

Comments
 (0)