protected synchronized BitSet getStructureKeyBits(IAtomContainer ac) {
    // quick workaround for aromatic compounds, to avoid matching non-aromatic keys
    // TODO remove this when isoTester/keys processing is fixed
    // isoTester is fixed, but CDK isomorphism tester still needs the workaround, should be fixed in
    // CDK nightly Mar 2010
    for (IBond bond : ac.bonds())
      if (bond.getFlag(CDKConstants.ISAROMATIC)) {
        for (IAtom a : bond.atoms()) a.setFlag(CDKConstants.ISAROMATIC, true);
        // in e.g. triazole the atoms are not set as aromatics, but bonds are!
        if (cleanKekuleBonds) bond.setOrder(Order.SINGLE);
      }
    // end of the workaround

    BitSet keys = new BitSet(nKeys);
    boolean res;
    for (int i = 0; i < nKeys; i++) {
      isoTester.setSequence(smartsQueries.get(i), sequences.get(i));
      res = isoTester.hasIsomorphism(ac);
      keys.set(i, res);
    }
    return (keys);
  }
Exemple #2
0
  /** Recursive function to produce valid configurations for {@link #getAllConfigurations()}. */
  private void findConfigurationsRecursively(
      List<Integer> rGroupNumbers,
      List<List<Integer>> occurrences,
      List<Integer> occurIndexes,
      List<Integer[]> distributions,
      List<List<RGroup>> substitutes,
      int level,
      List<IAtomContainer> result)
      throws CDKException {

    if (level == rGroupNumbers.size()) {

      if (!checkIfThenConditionsMet(rGroupNumbers, distributions)) return;

      // Clone the root to get a scaffold to plug the substitutes into.
      IAtomContainer root = this.getRootStructure();
      IAtomContainer rootClone = null;
      try {
        rootClone = (IAtomContainer) root.clone();
      } catch (CloneNotSupportedException e) {
        // Abort with CDK exception
        throw new CDKException("clone() failed; could not perform R-group substitution.");
      }

      for (int rgpIdx = 0; rgpIdx < rGroupNumbers.size(); rgpIdx++) {

        int rNum = rGroupNumbers.get(rgpIdx);
        int pos = 0;

        List<RGroup> mapped = substitutes.get(rgpIdx);
        for (RGroup substitute : mapped) {
          IAtom rAtom = this.getRgroupQueryAtoms(rNum).get(pos);
          if (substitute != null) {

            IAtomContainer rgrpClone = null;
            try {
              rgrpClone = (IAtomContainer) (substitute.getGroup().clone());
            } catch (CloneNotSupportedException e) {
              throw new CDKException("clone() failed; could not perform R-group substitution.");
            }

            // root cloned, substitute cloned. These now need to be attached to each other..
            rootClone.add(rgrpClone);

            Map<Integer, IBond> rAttachmentPoints = this.getRootAttachmentPoints().get(rAtom);
            if (rAttachmentPoints != null) {
              // Loop over attachment points of the R# atom
              for (int apo = 0; apo < rAttachmentPoints.size(); apo++) {
                IBond bond = rAttachmentPoints.get(apo + 1);
                // Check how R# is attached to bond
                int whichAtomInBond = 0;
                if (bond.getAtom(1).equals(rAtom)) whichAtomInBond = 1;
                IAtom subsAt = null;
                if (apo == 0) subsAt = substitute.getFirstAttachmentPoint();
                else subsAt = substitute.getSecondAttachmentPoint();

                // Do substitution with the clones
                IBond cloneBond = rootClone.getBond(getBondPosition(bond, root));
                if (subsAt != null) {
                  IAtom subsCloneAtom =
                      rgrpClone.getAtom(getAtomPosition(subsAt, substitute.getGroup()));
                  cloneBond.setAtom(subsCloneAtom, whichAtomInBond);
                }
              }
            }

            // Optional: shift substitutes 2D for easier visual checking
            if (rAtom.getPoint2d() != null
                && substitute != null
                && substitute.getFirstAttachmentPoint() != null
                && substitute.getFirstAttachmentPoint().getPoint2d() != null) {
              Point2d pointR = rAtom.getPoint2d();
              Point2d pointC = substitute.getFirstAttachmentPoint().getPoint2d();
              double xDiff = pointC.x - pointR.x;
              double yDiff = pointC.y - pointR.y;
              for (IAtom subAt : rgrpClone.atoms()) {
                if (subAt.getPoint2d() != null) {
                  subAt.getPoint2d().x -= xDiff;
                  subAt.getPoint2d().y -= yDiff;
                }
              }
            }
          } else {
            // Distribution flag is 0, this means the R# group will not be substituted.
            // Any atom connected to this group should be given the defined RestH value.
            IAtom discarded = rootClone.getAtom(getAtomPosition(rAtom, root));
            for (IBond r0Bond : rootClone.bonds()) {
              if (r0Bond.contains(discarded)) {
                for (IAtom atInBond : r0Bond.atoms()) {
                  atInBond.setProperty(
                      CDKConstants.REST_H, this.getRGroupDefinitions().get(rNum).isRestH());
                }
              }
            }
          }

          pos++;
        }
      }

      // Remove R# remnants from the clone, bonds and atoms that may linger.
      boolean confHasRGroupBonds = true;
      while (confHasRGroupBonds) {
        for (IBond cloneBond : rootClone.bonds()) {
          boolean removeBond = false;
          if (cloneBond.getAtom(0) instanceof IPseudoAtom
              && isValidRgroupQueryLabel(((IPseudoAtom) cloneBond.getAtom(0)).getLabel()))
            removeBond = true;
          else if (cloneBond.getAtom(1) instanceof IPseudoAtom
              && isValidRgroupQueryLabel(((IPseudoAtom) cloneBond.getAtom(1)).getLabel()))
            removeBond = true;

          if (removeBond) {
            rootClone.removeBond(cloneBond);
            confHasRGroupBonds = true;
            break;
          }
          confHasRGroupBonds = false;
        }
      }
      boolean confHasRGroupAtoms = true;
      while (confHasRGroupAtoms) {
        for (IAtom cloneAt : rootClone.atoms()) {
          if (cloneAt instanceof IPseudoAtom)
            if (isValidRgroupQueryLabel(((IPseudoAtom) cloneAt).getLabel())) {
              rootClone.removeAtom(cloneAt);
              confHasRGroupAtoms = true;
              break;
            }
          confHasRGroupAtoms = false;
        }
      }
      // Add to result list
      result.add(rootClone);

    } else {
      for (int idx = 0; idx < occurrences.get(level).size(); idx++) {
        occurIndexes.set(level, idx);
        // With an occurrence picked 0..n for this level's R-group, now find
        // all possible distributions (positional alternatives).
        int occurrence = occurrences.get(level).get(idx);
        int positions = this.getRgroupQueryAtoms(rGroupNumbers.get(level)).size();
        Integer[] candidate = new Integer[positions];
        for (int j = 0; j < candidate.length; j++) {
          candidate[j] = 0;
        }
        List<Integer[]> rgrpDistributions = new ArrayList<Integer[]>();
        findDistributions(occurrence, candidate, rgrpDistributions, 0);

        for (Integer[] distribution : rgrpDistributions) {
          distributions.set(level, distribution);

          RGroup[] mapping = new RGroup[distribution.length];
          List<List<RGroup>> mappedSubstitutes = new ArrayList<List<RGroup>>();
          mapSubstitutes(
              this.getRGroupDefinitions().get(rGroupNumbers.get(level)),
              0,
              distribution,
              mapping,
              mappedSubstitutes);

          for (List<RGroup> mappings : mappedSubstitutes) {
            substitutes.set(level, mappings);
            findConfigurationsRecursively(
                rGroupNumbers,
                occurrences,
                occurIndexes,
                distributions,
                substitutes,
                level + 1,
                result);
          }
        }
      }
    }
  }