/** * Internal - makes a map of the highlights for reaction mapping. * * @param reactants reaction reactants * @param products reaction products * @return the highlight map */ private Map<IChemObject, Color> makeHighlightAtomMap( List<IAtomContainer> reactants, List<IAtomContainer> products) { Map<IChemObject, Color> colorMap = new HashMap<>(); Map<Integer, Color> mapToColor = new HashMap<>(); int colorIdx = -1; for (IAtomContainer mol : reactants) { int prevPalletIdx = colorIdx; for (IAtom atom : mol.atoms()) { int mapidx = accessAtomMap(atom); if (mapidx > 0) { if (prevPalletIdx == colorIdx) { colorIdx++; // select next color if (colorIdx >= atomMapColors.length) throw new IllegalArgumentException( "Not enough colors to highlight atom mapping, please provide mode"); } Color color = atomMapColors[colorIdx]; colorMap.put(atom, color); mapToColor.put(mapidx, color); } } if (colorIdx > prevPalletIdx) { for (IBond bond : mol.bonds()) { IAtom a1 = bond.getAtom(0); IAtom a2 = bond.getAtom(1); Color c1 = colorMap.get(a1); Color c2 = colorMap.get(a2); if (c1 != null && c1 == c2) colorMap.put(bond, c1); } } } for (IAtomContainer mol : products) { for (IAtom atom : mol.atoms()) { int mapidx = accessAtomMap(atom); if (mapidx > 0) { colorMap.put(atom, mapToColor.get(mapidx)); } } for (IBond bond : mol.bonds()) { IAtom a1 = bond.getAtom(0); IAtom a2 = bond.getAtom(1); Color c1 = colorMap.get(a1); Color c2 = colorMap.get(a2); if (c1 != null && c1 == c2) colorMap.put(bond, c1); } } return colorMap; }
/** * Hide the atoms and bonds of a contracted abbreviation. If the abbreviations is attached we * remap the attachment symbol to display the name. If there are no attachments the symbol we be * added later ({@see #generateSgroups}). * * @param container molecule * @param sgroup abbreviation group display shortcut */ private static void contractAbbreviation( IAtomContainer container, Map<IAtom, String> symbolRemap, Sgroup sgroup) { final Set<IBond> crossing = sgroup.getBonds(); final Set<IAtom> atoms = sgroup.getAtoms(); // only do 0,1 attachments for now if (crossing.size() > 1) return; for (IAtom atom : atoms) { StandardGenerator.hide(atom); } for (IBond bond : container.bonds()) { if (atoms.contains(bond.getAtom(0)) || atoms.contains(bond.getAtom(1))) StandardGenerator.hide(bond); } for (IBond bond : crossing) { StandardGenerator.unhide(bond); IAtom a1 = bond.getAtom(0); IAtom a2 = bond.getAtom(1); StandardGenerator.unhide(a1); if (atoms.contains(a1)) symbolRemap.put(a1, sgroup.getSubscript()); StandardGenerator.unhide(a2); if (atoms.contains(a2)) symbolRemap.put(a2, sgroup.getSubscript()); } }
private double caclModelScale(Collection<IAtomContainer> mols) { List<IBond> bonds = new ArrayList<>(); for (IAtomContainer mol : mols) { for (IBond bond : mol.bonds()) { bonds.add(bond); } } return calcModelScaleForBondLength(medianBondLength(bonds)); }
/** * Eliminates one bond of this atom from the molecule * * @param atom The atom one bond is eliminated of * @param molecule The molecule that contains the atom */ private void breakBond(IAtom atom, IAtomContainer molecule) { Iterator<IBond> bonds = molecule.bonds().iterator(); while (bonds.hasNext()) { IBond bond = (IBond) bonds.next(); if (bond.contains(atom)) { molecule.removeElectronContainer(bond); break; } } }
/** * This method calculate the number of bonds of a given type in an atomContainer * * @param container AtomContainer * @return The number of bonds of a certain type. */ @Override public DescriptorValue calculate(IAtomContainer container) { if (order.equals("")) { int bondCount = 0; for (IBond bond : container.bonds()) { boolean hasHydrogen = false; for (int i = 0; i < bond.getAtomCount(); i++) { if (bond.getAtom(i).getSymbol().equals("H")) { hasHydrogen = true; break; } } if (!hasHydrogen) bondCount++; } return new DescriptorValue( getSpecification(), getParameterNames(), getParameters(), new IntegerResult(bondCount), getDescriptorNames(), null); } int bondCount = 0; for (IBond bond : container.bonds()) { if (bondMatch(bond.getOrder(), order)) { bondCount += 1; } } return new DescriptorValue( getSpecification(), getParameterNames(), getParameters(), new IntegerResult(bondCount), getDescriptorNames()); }
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; }
private boolean checkForNullBonds(IAtomContainer mol) { for (IBond b : mol.bonds()) { if (b == null) { LOGGER.info("Null bonds for: " + mol.getID()); return true; } if (b.getAtomCount() < 2) { LOGGER.info("bond with less than two atoms: " + mol.getID()); return true; } if (b.getAtom(0) == null || b.getAtom(1) == null) { LOGGER.info("Bond with one or two atoms null: " + mol.getID()); return true; } } return false; }
/** * Hide the repeated atoms and bonds of a multiple group. We hide al atoms that belong to the * group unless they are defined in the parent atom list. Any bond to those atoms that is not a * crossing bond or one connecting atoms in the parent list is hidden. * * @param container molecule * @param sgroup multiple group display shortcut */ private static void hideMultipleParts(IAtomContainer container, Sgroup sgroup) { final Set<IBond> crossing = sgroup.getBonds(); final Set<IAtom> atoms = sgroup.getAtoms(); final Set<IAtom> parentAtoms = sgroup.getValue(SgroupKey.CtabParentAtomList); for (IBond bond : container.bonds()) { if (parentAtoms.contains(bond.getAtom(0)) && parentAtoms.contains(bond.getAtom(1))) continue; if (atoms.contains(bond.getAtom(0)) || atoms.contains(bond.getAtom(1))) StandardGenerator.hide(bond); } for (IAtom atom : atoms) { if (!parentAtoms.contains(atom)) StandardGenerator.hide(atom); } for (IBond bond : crossing) { StandardGenerator.unhide(bond); } }
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); }
/** @throws BioclipseException */ private void calculateInchi() throws BioclipseException { try { IAtomContainer clone = (IAtomContainer) getAtomContainer().clone(); // remove aromaticity flags for (IAtom atom : clone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false); for (IBond bond : clone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false); if (factory == null) { factory = InChIGeneratorFactory.getInstance(); } InChIGenerator gen = factory.getInChIGenerator(clone); INCHI_RET status = gen.getReturnStatus(); if (status == INCHI_RET.OKAY || status == INCHI_RET.WARNING) { InChI inchi = new InChI(); inchi.setValue(gen.getInchi()); inchi.setKey(gen.getInchiKey()); cachedInchi = inchi; } else { throw new InvalidParameterException( "Error while generating InChI (" + status + "): " + gen.getMessage()); } } catch (Exception e) { throw new BioclipseException("Could not create InChI: " + e.getMessage(), e); } }
/** * Prepare the target molecule for analysis. * * <p>We perform ring perception and aromaticity detection and set up the appropriate properties. * Right now, this function is called each time we need to do a query and this is inefficient. * * @throws CDKException if there is a problem in ring perception or aromaticity detection, which * is usually related to a timeout in the ring finding code. */ private void initializeMolecule() throws CDKException { // Code copied from // org.openscience.cdk.qsar.descriptors.atomic.AtomValenceDescriptor; Map<String, Integer> valencesTable = new HashMap<String, Integer>(); valencesTable.put("H", 1); valencesTable.put("Li", 1); valencesTable.put("Be", 2); valencesTable.put("B", 3); valencesTable.put("C", 4); valencesTable.put("N", 5); valencesTable.put("O", 6); valencesTable.put("F", 7); valencesTable.put("Na", 1); valencesTable.put("Mg", 2); valencesTable.put("Al", 3); valencesTable.put("Si", 4); valencesTable.put("P", 5); valencesTable.put("S", 6); valencesTable.put("Cl", 7); valencesTable.put("K", 1); valencesTable.put("Ca", 2); valencesTable.put("Ga", 3); valencesTable.put("Ge", 4); valencesTable.put("As", 5); valencesTable.put("Se", 6); valencesTable.put("Br", 7); valencesTable.put("Rb", 1); valencesTable.put("Sr", 2); valencesTable.put("In", 3); valencesTable.put("Sn", 4); valencesTable.put("Sb", 5); valencesTable.put("Te", 6); valencesTable.put("I", 7); valencesTable.put("Cs", 1); valencesTable.put("Ba", 2); valencesTable.put("Tl", 3); valencesTable.put("Pb", 4); valencesTable.put("Bi", 5); valencesTable.put("Po", 6); valencesTable.put("At", 7); valencesTable.put("Fr", 1); valencesTable.put("Ra", 2); valencesTable.put("Cu", 2); valencesTable.put("Mn", 2); valencesTable.put("Co", 2); // do all ring perception AllRingsFinder arf = new AllRingsFinder(); IRingSet allRings; try { allRings = arf.findAllRings(atomContainer); } catch (CDKException e) { logger.debug(e.toString()); throw new CDKException(e.toString(), e); } // sets SSSR information SSSRFinder finder = new SSSRFinder(atomContainer); IRingSet sssr = finder.findEssentialRings(); for (IAtom atom : atomContainer.atoms()) { // add a property to each ring atom that will be an array of // Integers, indicating what size ring the given atom belongs to // Add SSSR ring counts if (allRings.contains(atom)) { // it's in a ring atom.setFlag(CDKConstants.ISINRING, true); // lets find which ring sets it is a part of List<Integer> ringsizes = new ArrayList<Integer>(); IRingSet currentRings = allRings.getRings(atom); int min = 0; for (int i = 0; i < currentRings.getAtomContainerCount(); i++) { int size = currentRings.getAtomContainer(i).getAtomCount(); if (min > size) min = size; ringsizes.add(size); } atom.setProperty(CDKConstants.RING_SIZES, ringsizes); atom.setProperty(CDKConstants.SMALLEST_RINGS, sssr.getRings(atom)); } else { atom.setFlag(CDKConstants.ISINRING, false); } // determine how many rings bonds each atom is a part of int hCount; if (atom.getImplicitHydrogenCount() == CDKConstants.UNSET) hCount = 0; else hCount = atom.getImplicitHydrogenCount(); List<IAtom> connectedAtoms = atomContainer.getConnectedAtomsList(atom); int total = hCount + connectedAtoms.size(); for (IAtom connectedAtom : connectedAtoms) { if (connectedAtom.getSymbol().equals("H")) { hCount++; } } atom.setProperty(CDKConstants.TOTAL_CONNECTIONS, total); atom.setProperty(CDKConstants.TOTAL_H_COUNT, hCount); if (valencesTable.get(atom.getSymbol()) != null) { int formalCharge = atom.getFormalCharge() == CDKConstants.UNSET ? 0 : atom.getFormalCharge(); atom.setValency(valencesTable.get(atom.getSymbol()) - formalCharge); } } for (IBond bond : atomContainer.bonds()) { if (allRings.getRings(bond).getAtomContainerCount() > 0) { bond.setFlag(CDKConstants.ISINRING, true); } } for (IAtom atom : atomContainer.atoms()) { List<IAtom> connectedAtoms = atomContainer.getConnectedAtomsList(atom); int counter = 0; IAtom any; for (IAtom connectedAtom : connectedAtoms) { any = connectedAtom; if (any.getFlag(CDKConstants.ISINRING)) { counter++; } } atom.setProperty(CDKConstants.RING_CONNECTIONS, counter); } // check for atomaticity try { AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(atomContainer); CDKHueckelAromaticityDetector.detectAromaticity(atomContainer); } catch (CDKException e) { logger.debug(e.toString()); throw new CDKException(e.toString(), e); } }
/** * Create a stereo encoder for cumulative double bonds. * * @param container the container * @param graph adjacency list representation of the container * @return a stereo encoder */ @Override public StereoEncoder create(IAtomContainer container, int[][] graph) { int n = container.getAtomCount(); BondMap map = new BondMap(n); List<StereoEncoder> encoders = new ArrayList<StereoEncoder>(1); // index double bonds by their atoms for (IBond bond : container.bonds()) { if (isDoubleBond(bond)) map.add(bond); } Set<IAtom> visited = new HashSet<IAtom>(n); // find atoms which are connected between two double bonds for (IAtom a : map.atoms()) { List<IBond> bonds = map.bonds(a); if (bonds.size() == 2) { // (s)tart/(e)nd of cumulated system: -s=a=e- IAtom s = bonds.get(0).getConnectedAtom(a); IAtom e = bonds.get(1).getConnectedAtom(a); // need the parents to re-use the double bond encoder IAtom sParent = a; IAtom eParent = a; visited.add(a); visited.add(s); visited.add(e); int size = 2; // expand out from 'l' while (s != null && map.cumulated(s)) { IAtom p = map.bonds(s).get(0).getConnectedAtom(s); IAtom q = map.bonds(s).get(1).getConnectedAtom(s); sParent = s; s = visited.add(p) ? p : visited.add(q) ? q : null; size++; } // expand from 'r' while (e != null && map.cumulated(e)) { IAtom p = map.bonds(e).get(0).getConnectedAtom(e); IAtom q = map.bonds(e).get(1).getConnectedAtom(e); eParent = e; e = visited.add(p) ? p : visited.add(q) ? q : null; size++; } // s and e are null if we had a cumulative cycle... if (s != null && e != null) { // system has now be expanded, size is the number of double // bonds. For odd numbers we use E/Z whilst for even are // axial M/P. // \ / // s = = = = e // / \ if (isOdd(size)) { StereoEncoder encoder = GeometricDoubleBondEncoderFactory.newEncoder( container, s, sParent, e, eParent, graph); if (encoder != null) { encoders.add(encoder); } } else { StereoEncoder encoder = axialEncoder(container, s, e); if (encoder != null) { encoders.add(encoder); } } } } } return encoders.isEmpty() ? StereoEncoder.EMPTY : new MultiStereoEncoder(encoders); }
private static void markRingAtomsAndBondsAromatic(IAtomContainer container) { for (IAtom atom : container.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, true); for (IBond bond : container.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, true); }
/** 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); } } } } }
/** Checks whether all bonds have exactly two atoms. */ public static boolean hasGraphRepresentation(IAtomContainer molecule) { for (IBond bond : molecule.bonds()) if (bond.getAtomCount() != 2) return false; return true; }
@TestMethod("testDetectAromaticity_IAtomContainer") public static boolean detectAromaticity(IAtomContainer atomContainer) throws CDKException { SpanningTree spanningTree = new SpanningTree(atomContainer); IAtomContainer ringSystems = spanningTree.getCyclicFragmentsContainer(); if (ringSystems.getAtomCount() == 0) { // If there are no rings, then there cannot be any aromaticity return false; } // disregard all atoms we know that cannot be aromatic anyway for (IAtom atom : ringSystems.atoms()) if (!atomIsPotentiallyAromatic(atom)) ringSystems.removeAtomAndConnectedElectronContainers(atom); // FIXME: should not really mark them here Iterator<IAtom> atoms = ringSystems.atoms().iterator(); while (atoms.hasNext()) atoms.next().setFlag(CDKConstants.ISINRING, true); Iterator<IBond> bonds = ringSystems.bonds().iterator(); while (bonds.hasNext()) bonds.next().setFlag(CDKConstants.ISINRING, true); boolean foundSomeAromaticity = false; Iterator<IAtomContainer> isolatedRingSystems = ConnectivityChecker.partitionIntoMolecules(ringSystems).atomContainers().iterator(); while (isolatedRingSystems.hasNext()) { IAtomContainer isolatedSystem = isolatedRingSystems.next(); IRingSet singleRings = new SSSRFinder(isolatedSystem).findSSSR(); Iterator<IAtomContainer> singleRingsIterator = singleRings.atomContainers().iterator(); int maxRingSize = 20; boolean atLeastOneRingIsSprouted = false; boolean allRingsAreAromatic = true; // test single rings in SSSR while (singleRingsIterator.hasNext()) { IAtomContainer singleRing = singleRingsIterator.next(); if (singleRing.getAtomCount() > maxRingSize) maxRingSize = singleRing.getAtomCount(); if (isRingSystemSproutedWithNonRingDoubleBonds(atomContainer, singleRing)) { // OK, this ring is not aromatic atLeastOneRingIsSprouted = true; allRingsAreAromatic = false; } else { // possibly aromatic boolean ringIsAromatic = isHueckelValid(singleRing); foundSomeAromaticity |= ringIsAromatic; allRingsAreAromatic &= ringIsAromatic; if (ringIsAromatic) markRingAtomsAndBondsAromatic(singleRing); } } // OK, what about the one larger ring (if no aromaticity found in SSSR)? if (!allRingsAreAromatic && !atLeastOneRingIsSprouted && singleRings.getAtomContainerCount() <= 3) { // every ring system consisting of more than two rings is too difficult Iterator<IAtomContainer> allRingsIterator = new AllRingsFinder() .findAllRingsInIsolatedRingSystem(isolatedSystem) .atomContainers() .iterator(); while (allRingsIterator.hasNext()) { // there should be exactly three rings, of which only one has a size larger // than the two previous ones IAtomContainer ring = allRingsIterator.next(); if (ring.getAtomCount() <= maxRingSize) { // possibly aromatic boolean ringIsAromatic = isHueckelValid(ring); foundSomeAromaticity |= ringIsAromatic; if (ringIsAromatic) markRingAtomsAndBondsAromatic(ring); } } } } return foundSomeAromaticity; }
/** * Search if the setOfAtomContainer contains the atomContainer * * @param set ISetOfAtomContainer object where to search * @param atomContainer IAtomContainer to search * @return True, if the atomContainer is contained */ private boolean existAC(IAtomContainerSet set, IAtomContainer atomContainer) { IAtomContainer acClone = null; try { acClone = (IMolecule) atomContainer.clone(); if (!lookingSymmetry) { /*remove all aromatic flags*/ for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false); for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false); } } catch (CloneNotSupportedException e1) { e1.printStackTrace(); } for (int i = 0; i < acClone.getAtomCount(); i++) // if(acClone.getAtom(i).getID() == null) acClone.getAtom(i).setID("" + acClone.getAtomNumber(acClone.getAtom(i))); if (lookingSymmetry) { try { CDKHueckelAromaticityDetector.detectAromaticity(acClone); } catch (CDKException e) { e.printStackTrace(); } } else { if (!lookingSymmetry) { /*remove all aromatic flags*/ for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false); for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false); } } for (int i = 0; i < set.getAtomContainerCount(); i++) { IAtomContainer ss = set.getAtomContainer(i); for (int j = 0; j < ss.getAtomCount(); j++) // if(ss.getAtom(j).getID() == null) ss.getAtom(j).setID("" + ss.getAtomNumber(ss.getAtom(j))); try { if (!lookingSymmetry) { QueryAtomContainer qAC = QueryAtomContainerCreator.createSymbolChargeIDQueryContainer(acClone); if (UniversalIsomorphismTester.isIsomorph(ss, qAC)) { QueryAtomContainer qAC2 = QueryAtomContainerCreator.createSymbolAndBondOrderQueryContainer(acClone); if (UniversalIsomorphismTester.isIsomorph(ss, qAC2)) return true; } } else { QueryAtomContainer qAC = QueryAtomContainerCreator.createSymbolAndChargeQueryContainer(acClone); CDKHueckelAromaticityDetector.detectAromaticity(ss); if (UniversalIsomorphismTester.isIsomorph(ss, qAC)) return true; } } catch (CDKException e1) { System.err.println(e1); logger.error(e1.getMessage()); logger.debug(e1); } } return false; }
@Test public void unionMolecules() throws IOException, CDKException { SmilesParser sp = new SmilesParser(DefaultChemObjectBuilder.getInstance()); IAtomContainer mol1 = sp.parseSmiles("OOC1=CC=CC=C1"); IAtomContainer mol2 = sp.parseSmiles("c1ccc(cc1)c2ccccc2"); int i = 0; for (IAtom atom1 : mol1.atoms()) { atom1.setID(String.valueOf((i++))); } int j = 0; for (IAtom atom2 : mol2.atoms()) { atom2.setID(String.valueOf((j++))); } MoleculeSanityCheck.aromatizeMolecule(mol1); MoleculeSanityCheck.aromatizeMolecule(mol2); Isomorphism isomorphism = new Isomorphism(mol1, mol2, Algorithm.DEFAULT, true, false, false); isomorphism.setChemFilters(false, false, false); int combinations = 1; List<String> acSet = new ArrayList<String>(); if (isomorphism.getFirstAtomMapping() != null) { for (AtomAtomMapping mapping : isomorphism.getAllAtomMapping()) { IAtomContainer union = new AtomContainer(); for (IAtom atom : mol1.atoms()) { union.addAtom(atom); } for (IBond bond : mol1.bonds()) { union.addBond(bond); } for (IBond bond : mol2.bonds()) { IAtom a1 = bond.getAtom(0); IAtom a2 = bond.getAtom(1); if (!mapping.getMappingsByAtoms().containsValue(a1) && !mapping.getMappingsByAtoms().containsValue(a2)) { if (!union.contains(a1)) { union.addAtom(a1); } if (!union.contains(a2)) { union.addAtom(a2); } union.addBond(bond); } else if (mapping.getMappingsByAtoms().containsValue(a1) && !mapping.getMappingsByAtoms().containsValue(a2)) { if (!union.contains(a2)) { union.addAtom(a2); } union.addBond( new Bond( a2, getKey(a1, mapping.getMappingsByAtoms()), bond.getOrder(), bond.getStereo())); } else if (!mapping.getMappingsByAtoms().containsValue(a1) && mapping.getMappingsByAtoms().containsValue(a2)) { if (!union.contains(a1)) { union.addAtom(a1); } union.addBond( new Bond( a1, getKey(a2, mapping.getMappingsByAtoms()), bond.getOrder(), bond.getStereo())); } } /*check if this combination is chemically valid*/ if (isChemicallyValid(union)) { String molSMILES = getSMILES(union).toString(); if (!acSet.contains(molSMILES)) { acSet.add(molSMILES); } } } } // for (String container : acSet) { // System.out.println("\n-------------" + " Combination " + combinations++ + // "--------------------"); // System.out.println("Query SMILES " + getSMILES(mol1).toString() + ", count " + // mol1.getAtomCount()); // System.out.println("Target SMILES " + getSMILES(mol2).toString() + ", count " + // mol2.getAtomCount()); // System.out.println("Union SMILES " + container + ", count " + // sp.parseSmiles(container).getAtomCount()); // } }
@TestMethod(value = "testCalculate_IAtomContainer") public DescriptorValue calculate( IAtom atom, IAtomContainer atomContainer, IRingSet precalculatedringset) { IAtomContainer varAtomContainer; try { varAtomContainer = (IAtomContainer) atomContainer.clone(); } catch (CloneNotSupportedException e) { return getDummyDescriptorValue(e); } int atomPosition = atomContainer.getAtomNumber(atom); IAtom clonedAtom = varAtomContainer.getAtom(atomPosition); DoubleArrayResult rdfProtonCalculatedValues = new DoubleArrayResult(gsr_desc_length); if (!atom.getSymbol().equals("H")) { return getDummyDescriptorValue(new CDKException("Invalid atom specified")); } ///////////////////////// FIRST SECTION OF MAIN METHOD: DEFINITION OF MAIN VARIABLES ///////////////////////// AND AROMATICITY AND PI-SYSTEM AND RINGS DETECTION Molecule mol = new Molecule(varAtomContainer); if (varAtomContainer != acold) { acold = varAtomContainer; // DETECTION OF pi SYSTEMS varAtomContainerSet = ConjugatedPiSystemsDetector.detect(mol); if (precalculatedringset == null) try { varRingSet = (new AllRingsFinder()).findAllRings(varAtomContainer); } catch (CDKException e) { return getDummyDescriptorValue(e); } else varRingSet = precalculatedringset; try { GasteigerMarsiliPartialCharges peoe = new GasteigerMarsiliPartialCharges(); peoe.assignGasteigerMarsiliSigmaPartialCharges(mol, true); } catch (Exception ex1) { return getDummyDescriptorValue(ex1); } } if (checkAromaticity) { try { AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(varAtomContainer); CDKHueckelAromaticityDetector.detectAromaticity(varAtomContainer); } catch (CDKException e) { return getDummyDescriptorValue(e); } } IRingSet rsAtom; Ring ring; IRingSet ringsWithThisBond; // SET ISINRING FLAGS FOR BONDS Iterator<IBond> bondsInContainer = varAtomContainer.bonds().iterator(); while (bondsInContainer.hasNext()) { IBond bond = bondsInContainer.next(); ringsWithThisBond = varRingSet.getRings(bond); if (ringsWithThisBond.getAtomContainerCount() > 0) { bond.setFlag(CDKConstants.ISINRING, true); } } // SET ISINRING FLAGS FOR ATOMS IRingSet ringsWithThisAtom; for (int w = 0; w < varAtomContainer.getAtomCount(); w++) { ringsWithThisAtom = varRingSet.getRings(varAtomContainer.getAtom(w)); if (ringsWithThisAtom.getAtomContainerCount() > 0) { varAtomContainer.getAtom(w).setFlag(CDKConstants.ISINRING, true); } } IAtomContainer detected = varAtomContainerSet.getAtomContainer(0); // neighboors[0] is the atom joined to the target proton: List<IAtom> neighboors = mol.getConnectedAtomsList(clonedAtom); IAtom neighbour0 = neighboors.get(0); // 2', 3', 4', 5', 6', and 7' atoms up to the target are detected: List<IAtom> atomsInSecondSphere = mol.getConnectedAtomsList(neighbour0); List<IAtom> atomsInThirdSphere; List<IAtom> atomsInFourthSphere; List<IAtom> atomsInFifthSphere; List<IAtom> atomsInSixthSphere; List<IAtom> atomsInSeventhSphere; // SOME LISTS ARE CREATED FOR STORING OF INTERESTING ATOMS AND BONDS DURING DETECTION ArrayList<Integer> singles = new ArrayList<Integer>(); // list of any bond not rotatable ArrayList<Integer> doubles = new ArrayList<Integer>(); // list with only double bonds ArrayList<Integer> atoms = new ArrayList<Integer>(); // list with all the atoms in spheres // atoms.add( Integer.valueOf( mol.getAtomNumber(neighboors[0]) ) ); ArrayList<Integer> bondsInCycloex = new ArrayList<Integer>(); // list for bonds in cycloexane-like rings // 2', 3', 4', 5', 6', and 7' bonds up to the target are detected: IBond secondBond; // (remember that first bond is proton bond) IBond thirdBond; // IBond fourthBond; // IBond fifthBond; // IBond sixthBond; // IBond seventhBond; // // definition of some variables used in the main FOR loop for detection of interesting atoms and // bonds: boolean theBondIsInA6MemberedRing; // this is like a flag for bonds which are in cycloexane-like // rings (rings with more than 4 at.) IBond.Order bondOrder; int bondNumber; int sphere; // THIS MAIN FOR LOOP DETECT RIGID BONDS IN 7 SPHERES: for (IAtom curAtomSecond : atomsInSecondSphere) { secondBond = mol.getBond(neighbour0, curAtomSecond); if (mol.getAtomNumber(curAtomSecond) != atomPosition && getIfBondIsNotRotatable(mol, secondBond, detected)) { sphere = 2; bondOrder = secondBond.getOrder(); bondNumber = mol.getBondNumber(secondBond); theBondIsInA6MemberedRing = false; checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomSecond), atoms, sphere, theBondIsInA6MemberedRing); atomsInThirdSphere = mol.getConnectedAtomsList(curAtomSecond); if (atomsInThirdSphere.size() > 0) { for (IAtom curAtomThird : atomsInThirdSphere) { thirdBond = mol.getBond(curAtomThird, curAtomSecond); // IF THE ATOMS IS IN THE THIRD SPHERE AND IN A CYCLOEXANE-LIKE RING, IT IS STORED IN // THE PROPER LIST: if (mol.getAtomNumber(curAtomThird) != atomPosition && getIfBondIsNotRotatable(mol, thirdBond, detected)) { sphere = 3; bondOrder = thirdBond.getOrder(); bondNumber = mol.getBondNumber(thirdBond); theBondIsInA6MemberedRing = false; // if the bond is in a cyclohexane-like ring (a ring with 5 or more atoms, not // aromatic) // the boolean "theBondIsInA6MemberedRing" is set to true if (!thirdBond.getFlag(CDKConstants.ISAROMATIC)) { if (!curAtomThird.equals(neighbour0)) { rsAtom = varRingSet.getRings(thirdBond); for (int f = 0; f < rsAtom.getAtomContainerCount(); f++) { ring = (Ring) rsAtom.getAtomContainer(f); if (ring.getRingSize() > 4 && ring.contains(thirdBond)) { theBondIsInA6MemberedRing = true; } } } } checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomThird), atoms, sphere, theBondIsInA6MemberedRing); theBondIsInA6MemberedRing = false; atomsInFourthSphere = mol.getConnectedAtomsList(curAtomThird); if (atomsInFourthSphere.size() > 0) { for (IAtom curAtomFourth : atomsInFourthSphere) { fourthBond = mol.getBond(curAtomThird, curAtomFourth); if (mol.getAtomNumber(curAtomFourth) != atomPosition && getIfBondIsNotRotatable(mol, fourthBond, detected)) { sphere = 4; bondOrder = fourthBond.getOrder(); bondNumber = mol.getBondNumber(fourthBond); theBondIsInA6MemberedRing = false; checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomFourth), atoms, sphere, theBondIsInA6MemberedRing); atomsInFifthSphere = mol.getConnectedAtomsList(curAtomFourth); if (atomsInFifthSphere.size() > 0) { for (IAtom curAtomFifth : atomsInFifthSphere) { fifthBond = mol.getBond(curAtomFifth, curAtomFourth); if (mol.getAtomNumber(curAtomFifth) != atomPosition && getIfBondIsNotRotatable(mol, fifthBond, detected)) { sphere = 5; bondOrder = fifthBond.getOrder(); bondNumber = mol.getBondNumber(fifthBond); theBondIsInA6MemberedRing = false; checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomFifth), atoms, sphere, theBondIsInA6MemberedRing); atomsInSixthSphere = mol.getConnectedAtomsList(curAtomFifth); if (atomsInSixthSphere.size() > 0) { for (IAtom curAtomSixth : atomsInSixthSphere) { sixthBond = mol.getBond(curAtomFifth, curAtomSixth); if (mol.getAtomNumber(curAtomSixth) != atomPosition && getIfBondIsNotRotatable(mol, sixthBond, detected)) { sphere = 6; bondOrder = sixthBond.getOrder(); bondNumber = mol.getBondNumber(sixthBond); theBondIsInA6MemberedRing = false; checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomSixth), atoms, sphere, theBondIsInA6MemberedRing); atomsInSeventhSphere = mol.getConnectedAtomsList(curAtomSixth); if (atomsInSeventhSphere.size() > 0) { for (IAtom curAtomSeventh : atomsInSeventhSphere) { seventhBond = mol.getBond(curAtomSeventh, curAtomSixth); if (mol.getAtomNumber(curAtomSeventh) != atomPosition && getIfBondIsNotRotatable(mol, seventhBond, detected)) { sphere = 7; bondOrder = seventhBond.getOrder(); bondNumber = mol.getBondNumber(seventhBond); theBondIsInA6MemberedRing = false; checkAndStore( bondNumber, bondOrder, singles, doubles, bondsInCycloex, mol.getAtomNumber(curAtomSeventh), atoms, sphere, theBondIsInA6MemberedRing); } } } } } } } } } } } } } } } } } // Variables double[] values; // for storage of results of other methods double distance; double sum; double smooth = -20; double partial; int position; double limitInf; double limitSup; double step; //////////////////////// THE FOUTH DESCRIPTOR IS gS(r), WHICH TAKES INTO ACCOUNT SINGLE BONDS IN // RIGID SYSTEMS Vector3d a_a = new Vector3d(); Vector3d a_b = new Vector3d(); Vector3d b_a = new Vector3d(); Vector3d b_b = new Vector3d(); Point3d middlePoint = new Point3d(); double angle = 0; if (singles.size() > 0) { double dist0; double dist1; IAtom singleBondAtom0; IAtom singleBondAtom1; distance = 0; position = 0; IBond theSingleBond = null; limitInf = 0; limitSup = Math.PI / 2; step = (limitSup - limitInf) / 7; smooth = -1.15; int counter = 0; for (double ghs = 0; ghs < limitSup; ghs = ghs + step) { sum = 0; for (int sing = 0; sing < singles.size(); sing++) { angle = 0; partial = 0; Integer thisSingleBond = singles.get(sing); position = thisSingleBond; theSingleBond = mol.getBond(position); middlePoint = theSingleBond.get3DCenter(); singleBondAtom0 = theSingleBond.getAtom(0); singleBondAtom1 = theSingleBond.getAtom(1); dist0 = calculateDistanceBetweenTwoAtoms(singleBondAtom0, atom); dist1 = calculateDistanceBetweenTwoAtoms(singleBondAtom1, atom); a_a.set(middlePoint.x, middlePoint.y, middlePoint.z); if (dist1 > dist0) a_b.set( singleBondAtom0.getPoint3d().x, singleBondAtom0.getPoint3d().y, singleBondAtom0.getPoint3d().z); else a_b.set( singleBondAtom1.getPoint3d().x, singleBondAtom1.getPoint3d().y, singleBondAtom1.getPoint3d().z); b_a.set(middlePoint.x, middlePoint.y, middlePoint.z); b_b.set(atom.getPoint3d().x, atom.getPoint3d().y, atom.getPoint3d().z); values = calculateDistanceBetweenAtomAndBond(atom, theSingleBond); angle = calculateAngleBetweenTwoLines(a_a, a_b, b_a, b_b); // System.out.println("ANGLe: "+angle+ " "+ mol.getAtomNumber(atomsInSingleBond[0]) +" " // +mol.getAtomNumber(atomsInSingleBond[1])); partial = (1 / (Math.pow(values[0], 2))) * Math.exp(smooth * (Math.pow((ghs - angle), 2))); sum += partial; } // gSr_function.add(new Double(sum)); rdfProtonCalculatedValues.add(sum); logger.debug("RDF gSr prob.: " + sum + " at distance " + ghs); counter++; } } else { return getDummyDescriptorValue(new CDKException("Some error occurred. Please report")); } return new DescriptorValue( getSpecification(), getParameterNames(), getParameters(), rdfProtonCalculatedValues, getDescriptorNames()); }
/** * This makes atom map1 of matching atoms out of atom map1 of matching bonds as produced by the * get(Subgraph|Ismorphism)Map methods. Added by Asad since CDK one doesn't pick up the correct * changes * * @param list The list produced by the getMap method. * @param sourceGraph first molecule. Must not be an IQueryAtomContainer. * @param targetGraph second molecule. May be an IQueryAtomContainer. * @return The mapping found projected on sourceGraph. This is atom List of CDKRMap objects * containing Ids of matching atoms. */ private synchronized List<List<CDKRMap>> makeAtomsMapOfBondsMapSingleBond( List<CDKRMap> list, IAtomContainer sourceGraph, IAtomContainer targetGraph) { if (list == null) { return null; } Map<IBond, IBond> bondMap = new HashMap<IBond, IBond>(list.size()); for (CDKRMap solBondMap : list) { int id1 = solBondMap.getId1(); int id2 = solBondMap.getId2(); IBond qBond = sourceGraph.getBond(id1); IBond tBond = targetGraph.getBond(id2); bondMap.put(qBond, tBond); } List<CDKRMap> result1 = new ArrayList<CDKRMap>(); List<CDKRMap> result2 = new ArrayList<CDKRMap>(); for (IBond qbond : sourceGraph.bonds()) { if (bondMap.containsKey(qbond)) { IBond tbond = bondMap.get(qbond); CDKRMap map00 = null; CDKRMap map01 = null; CDKRMap map10 = null; CDKRMap map11 = null; if ((qbond.getAtom(0).getSymbol().equals(tbond.getAtom(0).getSymbol())) && (qbond.getAtom(1).getSymbol().equals(tbond.getAtom(1).getSymbol()))) { map00 = new CDKRMap( sourceGraph.getAtomNumber(qbond.getAtom(0)), targetGraph.getAtomNumber(tbond.getAtom(0))); map11 = new CDKRMap( sourceGraph.getAtomNumber(qbond.getAtom(1)), targetGraph.getAtomNumber(tbond.getAtom(1))); if (!result1.contains(map00)) { result1.add(map00); } if (!result1.contains(map11)) { result1.add(map11); } } if ((qbond.getAtom(0).getSymbol().equals(tbond.getAtom(1).getSymbol())) && (qbond.getAtom(1).getSymbol().equals(tbond.getAtom(0).getSymbol()))) { map01 = new CDKRMap( sourceGraph.getAtomNumber(qbond.getAtom(0)), targetGraph.getAtomNumber(tbond.getAtom(1))); map10 = new CDKRMap( sourceGraph.getAtomNumber(qbond.getAtom(1)), targetGraph.getAtomNumber(tbond.getAtom(0))); if (!result2.contains(map01)) { result2.add(map01); } if (!result2.contains(map10)) { result2.add(map10); } } } } List<List<CDKRMap>> result = new ArrayList<List<CDKRMap>>(); if (result1.size() == result2.size()) { result.add(result1); result.add(result2); } else if (result1.size() > result2.size()) { result.add(result1); } else { result.add(result2); } return result; }