Abbreviations implements Iterable<String> { public List<Sgroup> generate(final IAtomContainer mol) { Set<IAtom> usedAtoms = new HashSet<>(); List<Sgroup> sgroups = mol.getProperty(CDKConstants.CTAB_SGROUPS); if (sgroups != null) { for (Sgroup sgroup : sgroups) usedAtoms.addAll(sgroup.getAtoms()); } final List<Sgroup> newSgroups = new ArrayList<>(); if (usedAtoms.isEmpty()) { try { IAtomContainer copy = AtomContainerManipulator.copyAndSuppressedHydrogens(mol); String cansmi = usmigen.create(copy); String label = disconnectedAbbreviations.get(cansmi); if (label != null && !disabled.contains(label) && contractSingleFragments) { Sgroup sgroup = new Sgroup(); sgroup.setType(SgroupType.CtabAbbreviation); sgroup.setSubscript(label); for (IAtom atom : mol.atoms()) sgroup.addAtom(atom); return Collections.singletonList(sgroup); } else if (cansmi.contains(".")) { IAtomContainerSet parts = ConnectivityChecker.partitionIntoMolecules(mol); Sgroup best = null; for (int i = 0; i < parts.getAtomContainerCount(); i++) { IAtomContainer a = parts.getAtomContainer(i); IAtomContainer b = a.getBuilder().newAtomContainer(); for (int j = 0; j < parts.getAtomContainerCount(); j++) if (j != i) b.add(parts.getAtomContainer(j)); Sgroup sgroup1 = getAbbr(a); Sgroup sgroup2 = getAbbr(b); if (sgroup1 != null && sgroup2 != null && contractSingleFragments) { Sgroup combined = new Sgroup(); label = null; for (IAtom atom : sgroup1.getAtoms()) combined.addAtom(atom); for (IAtom atom : sgroup2.getAtoms()) combined.addAtom(atom); if (sgroup1.getSubscript().length() > sgroup2.getSubscript().length()) combined.setSubscript(sgroup1.getSubscript() + INTERPUNCT + sgroup2.getSubscript()); else combined.setSubscript(sgroup2.getSubscript() + INTERPUNCT + sgroup1.getSubscript()); combined.setType(SgroupType.CtabAbbreviation); return Collections.singletonList(combined); } if (sgroup1 != null && (best == null || sgroup1.getAtoms().size() > best.getAtoms().size())) best = sgroup1; if (sgroup2 != null && (best == null || sgroup2.getAtoms().size() < best.getAtoms().size())) best = sgroup2; } if (best != null) { newSgroups.add(best); usedAtoms.addAll(best.getAtoms()); } } } catch (CDKException ignored) { } } List<IAtomContainer> fragments = generateFragments(mol); Multimap<IAtom, Sgroup> sgroupAdjs = ArrayListMultimap.create(); for (IAtomContainer frag : fragments) { try { final String smi = usmigen.create(AtomContainerManipulator.copyAndSuppressedHydrogens(frag)); final String label = connectedAbbreviations.get(smi); if (label == null || disabled.contains(label)) continue; boolean overlap = false; int numAtoms = frag.getAtomCount(); int numBonds = frag.getBondCount(); for (int i = 1; i < numAtoms; i++) { if (usedAtoms.contains(frag.getAtom(i))) { overlap = true; break; } } if (overlap) continue; Sgroup sgroup = new Sgroup(); sgroup.setType(SgroupType.CtabAbbreviation); sgroup.setSubscript(label); IBond attachBond = frag.getBond(0).getProperty(CUT_BOND, IBond.class); IAtom attachAtom = null; sgroup.addBond(attachBond); for (int i = 1; i < numAtoms; i++) { IAtom atom = frag.getAtom(i); usedAtoms.add(atom); sgroup.addAtom(atom); if (attachBond.getBegin().equals(atom)) attachAtom = attachBond.getEnd(); else if (attachBond.getEnd().equals(atom)) attachAtom = attachBond.getBegin(); } if (attachAtom != null) sgroupAdjs.put(attachAtom, sgroup); newSgroups.add(sgroup); } catch (CDKException e) { } } if (!contractOnHetero) return newSgroups; collapse: for (IAtom attach : mol.atoms()) { if (usedAtoms.contains(attach)) continue; if ((attach.getFormalCharge() != null && attach.getFormalCharge() != 0) || attach.getMassNumber() != null || attach.getAtomicNumber() == 6 || attach.getAtomicNumber() < 2) continue; int hcount = attach.getImplicitHydrogenCount(); Set<IAtom> xatoms = new HashSet<>(); Set<IBond> xbonds = new HashSet<>(); Set<IBond> newbonds = new HashSet<>(); xatoms.add(attach); List<String> nbrSymbols = new ArrayList<>(); Set<Sgroup> todelete = new HashSet<>(); for (Sgroup sgroup : sgroupAdjs.get(attach)) { if (containsChargeChar(sgroup.getSubscript())) continue; if (sgroup.getBonds().size() != 1) continue; IBond xbond = sgroup.getBonds().iterator().next(); xbonds.add(xbond); xatoms.addAll(sgroup.getAtoms()); if (attach.getSymbol().length() == 1 && Character.isLowerCase(sgroup.getSubscript().charAt(0))) { if (Elements.ofString(attach.getSymbol() + sgroup.getSubscript().charAt(0)) != Elements.Unknown) continue collapse; } nbrSymbols.add(sgroup.getSubscript()); todelete.add(sgroup); } int numSGrpNbrs = nbrSymbols.size(); for (IBond bond : mol.getConnectedBondsList(attach)) { if (!xbonds.contains(bond)) { IAtom nbr = bond.getOther(attach); if (mol.getConnectedBondsCount(nbr) == 1) { if (nbr.getMassNumber() != null || (nbr.getFormalCharge() != null && nbr.getFormalCharge() != 0)) { newbonds.add(bond); } else if (nbr.getAtomicNumber() == 1) { hcount++; xatoms.add(nbr); } else if (nbr.getAtomicNumber() > 0){ nbrSymbols.add(newSymbol(nbr.getAtomicNumber(), nbr.getImplicitHydrogenCount(), false)); xatoms.add(nbr); } } else { newbonds.add(bond); } } } if (nbrSymbols.isEmpty() || newbonds.size() < 1 && (new HashSet<>(nbrSymbols).size() != 1) || newbonds.size() > 2) continue; StringBuilder sb = new StringBuilder(); sb.append(newSymbol(attach.getAtomicNumber(), hcount, newbonds.size() == 0)); String prev = null; int count = 0; Collections.sort(nbrSymbols, new Comparator<String>() { @Override public int compare(String o1, String o2) { int cmp = Integer.compare(o1.length(), o2.length()); if (cmp != 0) return cmp; return o1.compareTo(o2); } }); for (String nbrSymbol : nbrSymbols) { if (nbrSymbol.equals(prev)) { count++; } else { boolean useParen = count == 0 || countUpper(prev) > 1 || (prev != null && nbrSymbol.startsWith(prev)); appendGroup(sb, prev, count, useParen); prev = nbrSymbol; count = 1; } } appendGroup(sb, prev, count, false); newSgroups.removeAll(todelete); Sgroup newSgroup = new Sgroup(); newSgroup.setType(SgroupType.CtabAbbreviation); newSgroup.setSubscript(sb.toString()); for (IBond bond : newbonds) newSgroup.addBond(bond); for (IAtom atom : xatoms) newSgroup.addAtom(atom); newSgroups.add(newSgroup); usedAtoms.addAll(xatoms); } return newSgroups; } Abbreviations(); @Override Iterator<String> iterator(); boolean isEnabled(final String label); boolean setEnabled(String label, boolean enabled); void setContractOnHetero(boolean val); void setContractToSingleLabel(boolean val); List<Sgroup> generate(final IAtomContainer mol); int apply(final IAtomContainer mol); boolean add(String line); boolean add(IAtomContainer mol, String label); int loadFromFile(final String path);  }
@Test public void SnCl2() throws Exception { Abbreviations factory = new Abbreviations(); IAtomContainer mol = smi("Cl[Sn]Cl"); List<Sgroup> sgroups = factory.generate(mol); assertThat(sgroups.size(), is(1)); assertThat(sgroups.get(0).getSubscript(), is("SnCl2")); }
@Test public void HOOH() throws Exception { Abbreviations factory = new Abbreviations(); IAtomContainer mol = smi("OO"); List<Sgroup> sgroups = factory.generate(mol); assertThat(sgroups.size(), is(1)); assertThat(sgroups.get(0).getSubscript(), is("HOOH")); }