/** * Fixes Aromaticity of the molecule i.e. need to find rings and aromaticity again since added H's * * @param mol */ @TestMethod("testFixAromaticity") public static void configure(IAtomContainer mol) { // need to find rings and aromaticity again since added H's IRingSet ringSet = null; try { AllRingsFinder arf = new AllRingsFinder(); ringSet = arf.findAllRings(mol); } catch (Exception e) { e.printStackTrace(); } try { // figure out which atoms are in aromatic rings: CDKHydrogenAdder cdk = CDKHydrogenAdder.getInstance(DefaultChemObjectBuilder.getInstance()); cdk.addImplicitHydrogens(mol); ExtAtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(mol); CDKHueckelAromaticityDetector.detectAromaticity(mol); // figure out which rings are aromatic: RingSetManipulator.markAromaticRings(ringSet); // figure out which simple (non cycles) rings are aromatic: // only atoms in 6 membered rings are aromatic // determine largest ring that each atom is a part of for (int i = 0; i < mol.getAtomCount(); i++) { mol.getAtom(i).setFlag(CDKConstants.ISAROMATIC, false); jloop: for (int j = 0; j < ringSet.getAtomContainerCount(); j++) { // logger.debug(i+"\t"+j); IRing ring = (IRing) ringSet.getAtomContainer(j); if (!ring.getFlag(CDKConstants.ISAROMATIC)) { continue jloop; } boolean haveatom = ring.contains(mol.getAtom(i)); // logger.debug("haveatom="+haveatom); if (haveatom && ring.getAtomCount() == 6) { mol.getAtom(i).setFlag(CDKConstants.ISAROMATIC, true); } } } } catch (Exception e) { e.printStackTrace(); } }
/** * Get all paths of lengths 0 to the specified length. * * <p>This method will find all paths upto length N starting from each atom in the molecule and * return the unique set of such paths. * * @param container The molecule to search * @return A map of path strings, keyed on themselves */ private Integer[] findPaths(IAtomContainer container) { ShortestPathWalker walker = new ShortestPathWalker(container); // convert paths to hashes List<Integer> paths = new ArrayList<Integer>(); int patternIndex = 0; for (String s : walker.paths()) { int toHashCode = s.hashCode(); paths.add(patternIndex, toHashCode); patternIndex++; } /* * Add ring information */ IRingSet sssr = Cycles.essential(container).toRingSet(); RingSetManipulator.sort(sssr); for (Iterator<IAtomContainer> it = sssr.atomContainers().iterator(); it.hasNext(); ) { IAtomContainer ring = it.next(); int toHashCode = String.valueOf(ring.getAtomCount()).hashCode(); paths.add(patternIndex, toHashCode); patternIndex++; } /* * Check for the charges */ List<String> l = new ArrayList<String>(); for (Iterator<IAtom> it = container.atoms().iterator(); it.hasNext(); ) { IAtom atom = it.next(); int charge = atom.getFormalCharge() == null ? 0 : atom.getFormalCharge(); if (charge != 0) { l.add(atom.getSymbol().concat(String.valueOf(charge))); } } Collections.sort(l); int toHashCode = l.hashCode(); paths.add(patternIndex, toHashCode); patternIndex++; l = new ArrayList<String>(); /* * atom stereo parity */ for (Iterator<IAtom> it = container.atoms().iterator(); it.hasNext(); ) { IAtom atom = it.next(); int st = atom.getStereoParity() == null ? 0 : atom.getStereoParity(); if (st != 0) { l.add(atom.getSymbol().concat(String.valueOf(st))); } } Collections.sort(l); toHashCode = l.hashCode(); paths.add(patternIndex, toHashCode); patternIndex++; if (container.getSingleElectronCount() > 0) { StringBuilder radicalInformation = new StringBuilder(); radicalInformation.append("RAD: ").append(String.valueOf(container.getSingleElectronCount())); paths.add(patternIndex, radicalInformation.toString().hashCode()); patternIndex++; } if (container.getLonePairCount() > 0) { StringBuilder lpInformation = new StringBuilder(); lpInformation.append("LP: ").append(String.valueOf(container.getLonePairCount())); paths.add(patternIndex, lpInformation.toString().hashCode()); patternIndex++; } return paths.toArray(new Integer[paths.size()]); }
/** * Finds the Smallest Set of Smallest Rings. * * @param mol the molecule to be searched for rings * @return a RingSet containing the rings in molecule */ public IRingSet findSSSR(IAtomContainer mol) { IBond brokenBond = null; IChemObjectBuilder builder = mol.getBuilder(); IRingSet sssr = builder.newInstance(IRingSet.class); IAtomContainer molecule = builder.newInstance(IAtomContainer.class); molecule.add(mol); IAtom smallest; int smallestDegree, nodesToBreakCounter, degree; IAtom[] rememberNodes; IRing ring; // Two Vectors - as defined in the article. One to hold the // full set of atoms in the structure and on to store the numbers // of the nodes that have been trimmed away. // Furhter there is a Vector nodesN2 to store the number of N2 nodes List<IAtom> fullSet = new ArrayList<IAtom>(); List<IAtom> trimSet = new ArrayList<IAtom>(); List<IAtom> nodesN2 = new ArrayList<IAtom>(); initPath(molecule); logger.debug("molecule.getAtomCount(): " + molecule.getAtomCount()); // load fullSet with the numbers of our atoms for (int f = 0; f < molecule.getAtomCount(); f++) { fullSet.add(molecule.getAtom(f)); } logger.debug("fullSet.size(): " + fullSet.size()); do { // Add nodes of degree zero to trimset. // Also add nodes of degree 2 to nodesN2. // In the same run, check, which node has the lowest degree // greater than zero. smallestDegree = 7; smallest = null; nodesN2.clear(); for (int f = 0; f < molecule.getAtomCount(); f++) { IAtom atom = molecule.getAtom(f); degree = molecule.getConnectedBondsCount(atom); if (degree == 0) { if (!trimSet.contains(atom)) { logger.debug("Atom of degree 0"); trimSet.add(atom); } } if (degree == 2) { nodesN2.add(atom); } if (degree < smallestDegree && degree > 0) { smallest = atom; smallestDegree = degree; } } if (smallest == null) break; // If there are nodes of degree 1, trim them away if (smallestDegree == 1) { trimCounter++; trim(smallest, molecule); trimSet.add(smallest); } // if there are nodes of degree 2, find out of which rings // they are part of. else if (smallestDegree == 2) { rememberNodes = new IAtom[nodesN2.size()]; nodesToBreakCounter = 0; for (int f = 0; f < nodesN2.size(); f++) { ring = getRing((IAtom) nodesN2.get(f), molecule); if (ring != null) { // check, if this ring already is in SSSR if (!RingSetManipulator.ringAlreadyInSet(ring, sssr)) { sssr.addAtomContainer(ring); rememberNodes[nodesToBreakCounter] = (IAtom) nodesN2.get(f); nodesToBreakCounter++; } } } if (nodesToBreakCounter == 0) { nodesToBreakCounter = 1; rememberNodes[0] = (IAtom) nodesN2.get(0); } for (int f = 0; f < nodesToBreakCounter; f++) { breakBond(rememberNodes[f], molecule); } if (brokenBond != null) { molecule.addBond(brokenBond); brokenBond = null; } } // if there are nodes of degree 3 else if (smallestDegree == 3) { ring = getRing(smallest, molecule); if (ring != null) { // check, if this ring already is in SSSR if (!RingSetManipulator.ringAlreadyInSet(ring, sssr)) { sssr.addAtomContainer(ring); } brokenBond = checkEdges(ring, molecule); molecule.removeElectronContainer(brokenBond); } } } while (trimSet.size() < fullSet.size()); logger.debug("fullSet.size(): " + fullSet.size()); logger.debug("trimSet.size(): " + trimSet.size()); logger.debug("trimCounter: " + trimCounter); // molecule.setProperty(CDKConstants.SMALLEST_RINGS, sssr); return sssr; }