Example #1
0
  /**
   * 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);
  }
Example #2
0
  /**
   * 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;
  }