/** * Create a pattern which can be used to find molecules which contain the * {@code query} structure. The default structure search implementation is * {@link VentoFoggia}. * * @param query the substructure to find * @return a pattern for finding the {@code query} * @see VentoFoggia */ public static Pattern findSubstructure(IAtomContainer query) { return VentoFoggia.findSubstructure(query); }
/** * Create a pattern which can be used to find molecules which are the same * as the {@code query} structure. The default structure search * implementation is {@link VentoFoggia}. * * @param query the substructure to find * @return a pattern for finding the {@code query} * @see VentoFoggia */ public static Pattern findIdentical(IAtomContainer query) { return VentoFoggia.findIdentical(query); } }
/** * Create a pattern which can be used to find molecules which are the same * as the {@code query} structure. * * @param query the substructure to find * @param atomMatcher how atoms are matched * @param bondMatcher how bonds are matched * @return a pattern for finding the {@code query} */ public static Pattern findIdentical(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher) { return new VentoFoggia(query, atomMatcher, bondMatcher, false); }
/**{@inheritDoc} */ @Override public int[] match(IAtomContainer target) { return matchAll(target).first(); }
/** * Non-public constructor for-now the atom/bond semantics are fixed. * * @param query the query structure * @param atomMatcher how atoms should be matched * @param bondMatcher how bonds should be matched * @param substructure substructure search */ private VentoFoggia(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher, boolean substructure) { this.query = query; this.atomMatcher = atomMatcher; this.bondMatcher = bondMatcher; this.bonds1 = EdgeToBondMap.withSpaceFor(query); this.g1 = GraphUtil.toAdjList(query, bonds1); this.subgraph = substructure; determineFilters(query); }
/**{@inheritDoc} */ @Override public Mappings matchAll(final IAtomContainer target) { final EdgeToBondMap bonds2; final int[][] g2; AdjListCache cached = target.getProperty(AdjListCache.class.getName()); if (cached == null || !cached.validate(target)) { cached = new AdjListCache(target); target.setProperty(AdjListCache.class.getName(), cached); } bonds2 = cached.bmap; g2 = cached.g; Iterable<int[]> iterable = new VFIterable(query, target, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher, subgraph); Mappings mappings = new Mappings(query, target, iterable); return filter(mappings, query, target); }
@Override Pattern create(IAtomContainer container) { return VentoFoggia.findSubstructure(container); } }
public IAtomContainer removeMolecule(IAtomContainer molecule) throws CDKException { for (int i = 0; i < templates.size(); i++) { if (VentoFoggia.findIdentical(templates.get(i), anonAtomMatcher, anonBondMatcher) .matches(molecule)) { elemPatterns.remove(i); anonPatterns.remove(i); return templates.remove(i); } } return null; }
/** * Create a pattern which can be used to find molecules which contain the * {@code query} structure. * * @param query the substructure to find * @param atomMatcher how atoms are matched * @param bondMatcher how bonds are matched * @return a pattern for finding the {@code query} */ public static Pattern findSubstructure(IAtomContainer query, AtomMatcher atomMatcher, BondMatcher bondMatcher) { return new VentoFoggia(query, atomMatcher, bondMatcher, true); }
/** * Adds a Molecule to the list of templates use by this TemplateHandler. * * @param molecule The molecule to be added to the TemplateHandler */ public void addMolecule(IAtomContainer molecule) { if (!GeometryUtil.has2DCoordinates(molecule)) throw new IllegalArgumentException("Template did not have 2D coordinates"); // we want a consistent scale! GeometryUtil.scaleMolecule(molecule, GeometryUtil.getScaleFactor(molecule, StructureDiagramGenerator.DEFAULT_BOND_LENGTH)); templates.add(molecule); anonPatterns.add(VentoFoggia.findSubstructure(molecule, anonAtomMatcher, anonBondMatcher)); elemPatterns.add(VentoFoggia.findSubstructure(molecule, elemAtomMatcher, anonBondMatcher)); }
public IAtomContainer removeMolecule(IAtomContainer molecule) throws CDKException { for (int i = 0; i < templates.size(); i++) { if (VentoFoggia.findIdentical(templates.get(i), anonAtomMatcher, anonBondMatcher) .matches(molecule)) { elemPatterns.remove(i); anonPatterns.remove(i); return templates.remove(i); } } return null; }
/** * Adds a Molecule to the list of templates use by this TemplateHandler. * * @param molecule The molecule to be added to the TemplateHandler */ public void addMolecule(IAtomContainer molecule) { if (!GeometryUtil.has2DCoordinates(molecule)) throw new IllegalArgumentException("Template did not have 2D coordinates"); // we want a consistent scale! GeometryUtil.scaleMolecule(molecule, GeometryUtil.getScaleFactor(molecule, StructureDiagramGenerator.DEFAULT_BOND_LENGTH)); templates.add(molecule); anonPatterns.add(VentoFoggia.findSubstructure(molecule, anonAtomMatcher, anonBondMatcher)); elemPatterns.add(VentoFoggia.findSubstructure(molecule, elemAtomMatcher, anonBondMatcher)); }
/** * Checks if one of the loaded templates is isomorph to the given * Molecule. If so, it assigns the coordinates from the template to the * respective atoms in the Molecule, and marks the atoms as ISPLACED. * * @param molecule The molecule to be check for potential templates * @return True if there was a possible mapping */ public boolean mapTemplateExact(IAtomContainer molecule) throws CDKException { for (IAtomContainer template : templates) { Mappings mappings = VentoFoggia.findIdentical(template, anonAtomMatcher, anonBondMatcher) .matchAll(molecule); for (Map<IAtom, IAtom> atoms : mappings.toAtomMap()) { for (Map.Entry<IAtom, IAtom> e : atoms.entrySet()) { e.getValue().setPoint2d(new Point2d(e.getKey().getPoint2d())); e.getValue().setFlag(CDKConstants.ISPLACED, true); } if (!atoms.isEmpty()) return true; } } return false; }
/** * Create a pattern which can be used to find molecules which contain the * {@code query} structure. * * @param query the substructure to find * @return a pattern for finding the {@code query} */ public static Pattern findSubstructure(IAtomContainer query) { boolean isQuery = query instanceof IQueryAtomContainer; return findSubstructure(query, isQuery ? AtomMatcher.forQuery() : AtomMatcher.forElement(), isQuery ? BondMatcher.forQuery() : BondMatcher.forOrder()); }
/** * Checks if one of the loaded templates is isomorph to the given * Molecule. If so, it assigns the coordinates from the template to the * respective atoms in the Molecule, and marks the atoms as ISPLACED. * * @param molecule The molecule to be check for potential templates * @return True if there was a possible mapping */ public boolean mapTemplateExact(IAtomContainer molecule) throws CDKException { for (IAtomContainer template : templates) { Mappings mappings = VentoFoggia.findIdentical(template, anonAtomMatcher, anonBondMatcher) .matchAll(molecule); for (Map<IAtom, IAtom> atoms : mappings.toAtomMap()) { for (Map.Entry<IAtom, IAtom> e : atoms.entrySet()) { e.getValue().setPoint2d(new Point2d(e.getKey().getPoint2d())); e.getValue().setFlag(CDKConstants.ISPLACED, true); } if (!atoms.isEmpty()) return true; } } return false; }
@Test public void uniqueBonds() throws Exception { IAtomContainer query = smi("C1CCC1"); IAtomContainer target = smi("C12C3C1C23"); Iterable<int[]> mappings = VentoFoggia.findSubstructure(query).matchAll(target); // using unique atoms we may think we only found 1 mapping assertThat(Iterables.size(Iterables.filter(mappings, new UniqueAtomMatches())), is(1)); // when in fact we found 4 different mappings assertThat(Iterables.size(Iterables.filter(mappings, new UniqueBondMatches(GraphUtil.toAdjList(query)))), is(3)); }
/** * Create a pattern which can be used to find molecules which are the same * as the {@code query} structure. * * @param query the substructure to find * @return a pattern for finding the {@code query} */ public static Pattern findIdentical(IAtomContainer query) { boolean isQuery = query instanceof IQueryAtomContainer; return findIdentical(query, isQuery ? AtomMatcher.forQuery() : AtomMatcher.forElement(), isQuery ? BondMatcher.forQuery() : BondMatcher.forOrder()); }
@Test public void napthaleneSubsearch() throws Exception { int[] match = VentoFoggia.findSubstructure(TestMoleculeFactory.makeNaphthalene()).match( TestMoleculeFactory.makeBenzene()); assertThat(match, is(new int[0])); int count = FluentIterable.from( VentoFoggia.findSubstructure(TestMoleculeFactory.makeNaphthalene()).matchAll( TestMoleculeFactory.makeBenzene())).size(); assertThat(count, is(0)); } }
@Test public void benzeneNonIdentical() throws Exception { int[] match = VentoFoggia.findIdentical(TestMoleculeFactory.makeBenzene()).match( TestMoleculeFactory.makeNaphthalene()); assertThat(match, is(new int[0])); int count = FluentIterable.from( VentoFoggia.findIdentical(TestMoleculeFactory.makeBenzene()).matchAll( TestMoleculeFactory.makeNaphthalene())).size(); assertThat(count, is(0)); }
@Test public void benzeneSubsearch() throws Exception { int[] match = VentoFoggia.findSubstructure(TestMoleculeFactory.makeBenzene()).match( TestMoleculeFactory.makeNaphthalene()); assertThat(match, is(new int[]{2, 7, 6, 5, 4, 3})); int count = FluentIterable.from( VentoFoggia.findSubstructure(TestMoleculeFactory.makeBenzene()).matchAll( TestMoleculeFactory.makeNaphthalene())).size(); assertThat(count, is(6)); // note: aromatic one would be 24 }