/** * Performs the pharmacophore matching. * * @param atomContainer The target molecule. Must have 3D coordinates * @param initializeTarget If <i>true</i>, the target molecule specified in the first argument * will be analyzed to identify matching pharmacophore groups. If <i>false</i> this is not * performed. The latter case is only useful when dealing with conformers since for a given * molecule, all conformers will have the same pharmacophore groups and only the constraints * will change from one conformer to another. * @return true is the target molecule contains the query pharmacophore * @throws org.openscience.cdk.exception.CDKException if the query pharmacophore was not set or * the query is invalid or if the molecule does not have 3D coordinates */ public boolean matches(IAtomContainer atomContainer, boolean initializeTarget) throws CDKException { if (!GeometryUtil.has3DCoordinates(atomContainer)) throw new CDKException("Molecule must have 3D coordinates"); if (pharmacophoreQuery == null) throw new CDKException("Must set the query pharmacophore before matching"); if (!checkQuery(pharmacophoreQuery)) throw new CDKException( "A problem in the query. Make sure all pharmacophore groups of the same symbol have the same same SMARTS"); String title = (String) atomContainer.getProperty(CDKConstants.TITLE); if (initializeTarget) pharmacophoreMolecule = getPharmacophoreMolecule(atomContainer); else { // even though the atoms comprising the pcore groups are // constant, their coords will differ, so we need to make // sure we get the latest set of effective coordinates for (IAtom iAtom : pharmacophoreMolecule.atoms()) { PharmacophoreAtom patom = (PharmacophoreAtom) iAtom; List<Integer> tmpList = new ArrayList<Integer>(); for (int idx : patom.getMatchingAtoms()) tmpList.add(idx); Point3d coords = getEffectiveCoordinates(atomContainer, tmpList); patom.setPoint3d(coords); } } if (pharmacophoreMolecule.getAtomCount() < pharmacophoreQuery.getAtomCount()) { logger.debug("Target [" + title + "] did not match the query SMARTS. Skipping constraints"); return false; } mappings = Pattern.findSubstructure(pharmacophoreQuery).matchAll(pharmacophoreMolecule); // XXX: doing one search then discarding return mappings.atLeast(1); }
@Test public void testBug70() throws FileNotFoundException, CDKException { JPanelFixture jcppanel = applet.panel("appletframe"); JChemPaintPanel panel = (JChemPaintPanel) jcppanel.target; applet.button("hexagon").click(); applet.click(); Point2d point = getAtomPoint(panel, 0); applet .panel("renderpanel") .robot .click( applet.panel("renderpanel").component(), new Point((int) point.x, (int) point.y), MouseButton.RIGHT_BUTTON, 1); applet .panel("renderpanel") .robot .click( applet.panel("renderpanel").component(), new Point((int) point.x, (int) point.y), MouseButton.RIGHT_BUTTON, 1); applet.menuItem("showACProperties").click(); DialogFixture dialog = applet.dialog(); JTextComponent textfield = dialog.robot.finder().find(JTextComponentMatcher.withName("Title")); textfield.setText("aaa"); JButtonFixture okbutton = new JButtonFixture( dialog.robot, dialog.robot.finder().find(new ButtonTextComponentMatcher("OK"))); okbutton.click(); applet.menuItem("save").click(); dialog = applet.dialog(); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "test.mol"); if (file.exists()) file.delete(); JComboBox combobox = dialog .robot .finder() .find(new ComboBoxTextComponentMatcher("org.openscience.jchempaint.io.JCPFileFilter")); combobox.setSelectedItem(combobox.getItemAt(SAVE_AS_MOL_COMBOBOX_POS)); JTextComponentFixture text = dialog.textBox(); text.setText(file.toString()); JButtonFixture savebutton = new JButtonFixture( dialog.robot, dialog.robot.finder().find(new ButtonTextComponentMatcher("Save"))); savebutton.click(); MDLReader reader = new MDLReader(new FileInputStream(file)); IAtomContainer mol = (IAtomContainer) reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IAtomContainer.class)); Assert.assertEquals("aaa", (String) mol.getProperty(CDKConstants.TITLE)); }
private IRenderingElement generate(IAtomContainer molecule, RendererModel model, int atomNum) throws CDKException { // tag the atom and bond ids String molId = molecule.getProperty(MarkedElement.ID_KEY); if (molId != null) { int atomId = 0, bondid = 0; for (IAtom atom : molecule.atoms()) setIfMissing(atom, MarkedElement.ID_KEY, molId + "atm" + ++atomId); for (IBond bond : molecule.bonds()) setIfMissing(bond, MarkedElement.ID_KEY, molId + "bnd" + ++bondid); } if (annotateAtomNum) { for (IAtom atom : molecule.atoms()) { if (atom.getProperty(StandardGenerator.ANNOTATION_LABEL) != null) throw new UnsupportedOperationException("Multiple annotation labels are not supported."); atom.setProperty(StandardGenerator.ANNOTATION_LABEL, Integer.toString(atomNum++)); } } else if (annotateAtomVal) { for (IAtom atom : molecule.atoms()) { if (atom.getProperty(StandardGenerator.ANNOTATION_LABEL) != null) throw new UnsupportedOperationException("Multiple annotation labels are not supported."); atom.setProperty( StandardGenerator.ANNOTATION_LABEL, atom.getProperty(CDKConstants.COMMENT)); } } else if (annotateAtomMap) { for (IAtom atom : molecule.atoms()) { if (atom.getProperty(StandardGenerator.ANNOTATION_LABEL) != null) throw new UnsupportedOperationException("Multiple annotation labels are not supported."); int mapidx = accessAtomMap(atom); if (mapidx > 0) { atom.setProperty(StandardGenerator.ANNOTATION_LABEL, Integer.toString(mapidx)); } } } ElementGroup grp = new ElementGroup(); for (IGenerator<IAtomContainer> gen : gens) grp.add(gen.generate(molecule, model)); // cleanup if (annotateAtomNum || annotateAtomMap) { for (IAtom atom : molecule.atoms()) { atom.removeProperty(StandardGenerator.ANNOTATION_LABEL); } } return grp; }
/** * If the molecule has display shortcuts (abbreviations or multiple group sgroups) certain parts * of the structure are hidden from display. This method marks the parts to hide and in the case * of abbreviations, remaps atom symbols. Appart from additional property flags, the molecule is * unchanged by this method. * * @param container molecule input * @param symbolRemap a map that will hold symbol remapping */ static void prepareDisplayShortcuts(IAtomContainer container, Map<IAtom, String> symbolRemap) { List<Sgroup> sgroups = container.getProperty(CDKConstants.CTAB_SGROUPS); if (sgroups == null || sgroups.isEmpty()) return; // select abbreviations that should be contracted for (Sgroup sgroup : sgroups) { if (sgroup.getType() == SgroupType.CtabAbbreviation) { Boolean expansion = sgroup.getValue(SgroupKey.CtabExpansion); // abbreviation is displayed as expanded if (expansion != null && expansion == Boolean.TRUE) continue; // no or empty label, skip it if (sgroup.getSubscript() == null || sgroup.getSubscript().isEmpty()) continue; contractAbbreviation(container, symbolRemap, sgroup); } else if (sgroup.getType() == SgroupType.CtabMultipleGroup) { hideMultipleParts(container, sgroup); } } }
@Test public void checkUniqueMolecularDescriptorNames() throws Exception { DescriptorEngine engine = new DescriptorEngine(DescriptorEngine.MOLECULAR); List<DescriptorSpecification> specs = engine.getDescriptorSpecifications(); // we work with a simple molecule with 3D coordinates String filename = "data/mdl/lobtest2.sdf"; InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename); ISimpleChemObjectReader reader = new MDLV2000Reader(ins); ChemFile content = (ChemFile) reader.read(new ChemFile()); List cList = ChemFileManipulator.getAllAtomContainers(content); IAtomContainer ac = (IAtomContainer) cList.get(0); AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(ac); engine.process(ac); int ncalc = 0; List<String> descNames = new ArrayList<String>(); for (DescriptorSpecification spec : specs) { DescriptorValue value = (DescriptorValue) ac.getProperty(spec); if (value == null) continue; ncalc++; String[] names = value.getNames(); descNames.addAll(Arrays.asList(names)); } List<String> dups = new ArrayList<String>(); Set<String> uniqueNames = new HashSet<String>(); for (String name : descNames) { if (!uniqueNames.add(name)) dups.add(name); } Assert.assertEquals(specs.size(), ncalc); Assert.assertEquals(descNames.size(), uniqueNames.size()); if (dups.size() != 0) { System.out.println("Following names were duplicated"); for (String dup : dups) { System.out.println("dup = " + dup); } } }
/** * Generate the Sgroup elements for the provided atom contains. * * @param container molecule * @return Sgroup rendering elements */ IRenderingElement generateSgroups(IAtomContainer container) { ElementGroup result = new ElementGroup(); List<Sgroup> sgroups = container.getProperty(CDKConstants.CTAB_SGROUPS); if (sgroups == null || sgroups.isEmpty()) return result; for (Sgroup sgroup : sgroups) { switch (sgroup.getType()) { case CtabAbbreviation: result.add(generateAbbreviationSgroup(sgroup)); break; case CtabMultipleGroup: result.add(generateMultipleSgroup(sgroup)); break; case CtabAnyPolymer: case CtabMonomer: case CtabCrossLink: case CtabCopolymer: case CtabStructureRepeatUnit: case CtabMer: case CtabGraft: case CtabModified: result.add(generatePolymerSgroup(sgroup)); break; case CtabComponent: case CtabMixture: case CtabFormulation: result.add(generateMixtureSgroup(sgroup)); break; case CtabGeneric: // not strictly a polymer but okay to draw as one result.add(generatePolymerSgroup(sgroup)); break; } } return result; }
/** * Create a predicate to match components for the provided query and target. The target is * pre-converted to an adjacency list ({@link GraphUtil#toAdjList(IAtomContainer)}) and the query * components extracted from the property {@link #KEY} in the query. * * @param query query structure * @param target target structure */ public ComponentGrouping(IAtomContainer query, int[][] target) { this( query.getProperty(KEY, int[].class), query.getProperty(KEY) != null ? new ConnectedComponents(target) : null); }
/** * Convert the input into a pcore molecule. * * @param input the compound being converted from * @return pcore molecule * @throws CDKException match failed */ private IAtomContainer getPharmacophoreMolecule(IAtomContainer input) throws CDKException { // XXX: prepare query, to be moved prepareInput(input); IAtomContainer pharmacophoreMolecule = input.getBuilder().newInstance(IAtomContainer.class, 0, 0, 0, 0); final Set<String> matched = new HashSet<>(); final Set<PharmacophoreAtom> uniqueAtoms = new LinkedHashSet<>(); logger.debug("Converting [" + input.getProperty(CDKConstants.TITLE) + "] to a pcore molecule"); // lets loop over each pcore query atom for (IAtom atom : pharmacophoreQuery.atoms()) { final PharmacophoreQueryAtom qatom = (PharmacophoreQueryAtom) atom; final String smarts = qatom.getSmarts(); // a pcore query might have multiple instances of a given pcore atom (say // 2 hydrophobic groups separated by X unit). In such a case we want to find // the atoms matching the pgroup SMARTS just once, rather than redoing the // matching for each instance of the pcore query atom. if (!matched.add(qatom.getSymbol())) continue; // see if the smarts for this pcore query atom gets any matches // in our query molecule. If so, then collect each set of // matching atoms and for each set make a new pcore atom and // add it to the pcore atom container object int count = 0; for (final IQueryAtomContainer query : qatom.getCompiledSmarts()) { // create the lazy mappings iterator final Mappings mappings = Pattern.findSubstructure(query).matchAll(input).uniqueAtoms(); for (final int[] mapping : mappings) { uniqueAtoms.add(newPCoreAtom(input, qatom, smarts, mapping)); count++; } } logger.debug("\tFound " + count + " unique matches for " + smarts); } pharmacophoreMolecule.setAtoms(uniqueAtoms.toArray(new IAtom[uniqueAtoms.size()])); // now that we have added all the pcore atoms to the container // we need to join all atoms with pcore bonds (i.e. distance constraints) if (hasDistanceConstraints(pharmacophoreQuery)) { int npatom = pharmacophoreMolecule.getAtomCount(); for (int i = 0; i < npatom - 1; i++) { for (int j = i + 1; j < npatom; j++) { PharmacophoreAtom atom1 = (PharmacophoreAtom) pharmacophoreMolecule.getAtom(i); PharmacophoreAtom atom2 = (PharmacophoreAtom) pharmacophoreMolecule.getAtom(j); PharmacophoreBond bond = new PharmacophoreBond(atom1, atom2); pharmacophoreMolecule.addBond(bond); } } } // if we have angle constraints, generate only the valid // possible angle relationships, rather than all possible if (hasAngleConstraints(pharmacophoreQuery)) { int nangleDefs = 0; for (IBond bond : pharmacophoreQuery.bonds()) { if (!(bond instanceof PharmacophoreQueryAngleBond)) continue; IAtom startQAtom = bond.getAtom(0); IAtom middleQAtom = bond.getAtom(1); IAtom endQAtom = bond.getAtom(2); // make a list of the patoms in the target that match // each type of angle atom List<IAtom> startl = new ArrayList<IAtom>(); List<IAtom> middlel = new ArrayList<IAtom>(); List<IAtom> endl = new ArrayList<IAtom>(); for (IAtom tatom : pharmacophoreMolecule.atoms()) { if (tatom.getSymbol().equals(startQAtom.getSymbol())) startl.add(tatom); if (tatom.getSymbol().equals(middleQAtom.getSymbol())) middlel.add(tatom); if (tatom.getSymbol().equals(endQAtom.getSymbol())) endl.add(tatom); } // now we form the relevant angles, but we will // have reversed repeats List<IAtom[]> tmpl = new ArrayList<IAtom[]>(); for (IAtom middle : middlel) { for (IAtom start : startl) { if (middle.equals(start)) continue; for (IAtom end : endl) { if (start.equals(end) || middle.equals(end)) continue; tmpl.add(new IAtom[] {start, middle, end}); } } } // now clean up reversed repeats List<IAtom[]> unique = new ArrayList<IAtom[]>(); for (int i = 0; i < tmpl.size(); i++) { IAtom[] seq1 = tmpl.get(i); boolean isRepeat = false; for (int j = 0; j < unique.size(); j++) { if (i == j) continue; IAtom[] seq2 = unique.get(j); if (seq1[1] == seq2[1] && seq1[0] == seq2[2] && seq1[2] == seq2[0]) { isRepeat = true; } } if (!isRepeat) unique.add(seq1); } // finally we can add the unique angle to the target for (IAtom[] seq : unique) { PharmacophoreAngleBond pbond = new PharmacophoreAngleBond( (PharmacophoreAtom) seq[0], (PharmacophoreAtom) seq[1], (PharmacophoreAtom) seq[2]); pharmacophoreMolecule.addBond(pbond); nangleDefs++; } } logger.debug("Added " + nangleDefs + " defs to the target pcore molecule"); } return pharmacophoreMolecule; }
public static Object getProperty(IAtomContainer molecule, String key) { return molecule.getProperty(key); }