public static IAtomContainer GetLargestMoleculeFragment( IAtomContainer mol, out int acc) { IAtomContainer mol2, molMain = null; acc = 0; if (mol == null) { return(null); } if (ConnectivityChecker.IsConnected(mol)) { acc = 1; return(mol); } IReadOnlyList <IAtomContainer> acs = ConnectivityChecker.PartitionIntoMolecules(mol); int largestAc = -1; acc = acs.Count; for (int aci = 0; aci < acc; aci++) { mol2 = acs[aci]; int ac2 = mol2.Atoms.Count; if (ac2 > largestAc) { largestAc = mol2.Atoms.Count; molMain = mol2; } } return(molMain); }
/// <summary> /// </summary> /// <param name="mol"></param> /// <param name="mcss"></param> /// <param name="shouldMatchBonds"></param> /// <returns>IMolecule Set</returns> /// <exception cref="CDKException"></exception> private static IChemObjectSet <IAtomContainer> GetUncommon(IAtomContainer mol, IAtomContainer mcss, bool shouldMatchBonds) { List <int> atomSerialsToDelete = new List <int>(); var matches = CDKMCS.GetSubgraphAtomsMaps(mol, mcss, shouldMatchBonds); var mapList = matches[0]; foreach (var o in mapList) { CDKRMap rmap = (CDKRMap)o; atomSerialsToDelete.Add(rmap.Id1); } // at this point we have the serial numbers of the bonds to delete // we should get the actual bonds rather than delete by serial numbers List <IAtom> atomsToDelete = new List <IAtom>(); foreach (var serial in atomSerialsToDelete) { atomsToDelete.Add(mol.Atoms[serial]); } // now lets get rid of the bonds themselves foreach (var atom in atomsToDelete) { mol.RemoveAtomAndConnectedElectronContainers(atom); } // now we probably have a set of disconnected components // so lets get a set of individual atom containers for // corresponding to each component return(ConnectivityChecker.PartitionIntoMolecules(mol)); }
public void TestTwentyRandomStructures() { var molecule = TestMoleculeFactory.MakeAlphaPinene(); var rg = new RandomGenerator(molecule); IAtomContainer result = null; for (int f = 0; f < 50; f++) { result = rg.ProposeStructure(); Assert.AreEqual(molecule.Atoms.Count, result.Atoms.Count); Assert.AreEqual(1, ConnectivityChecker.PartitionIntoMolecules(result).Count()); } }
/// <summary> /// Fragment a molecule /// </summary> /// <param name="mol"></param> /// <returns></returns> public static List <KeyValuePair <string, IAtomContainer> > FragmentMoleculeAndCanonicalizeSmiles( IAtomContainer mol, bool filterOutCommonCounterIons) { int aci, fi, i1; KeyValuePair <string, IAtomContainer> kvp; List <KeyValuePair <string, IAtomContainer> > frags = new List <KeyValuePair <string, IAtomContainer> >(); if (mol == null) { return(frags); } IReadOnlyList <IAtomContainer> acs = ConnectivityChecker.PartitionIntoMolecules(mol); int acc = acs.Count; for (aci = 0; aci < acc; aci++) { IAtomContainer fragMol = acs[aci]; string fragSmiles = AtomContainerToSmiles(fragMol); if (filterOutCommonCounterIons) { if (CommonSmallFragments.Contains(fragSmiles) || GetHeavyAtomCount(fragMol) <= 6) { continue; } } kvp = new KeyValuePair <string, IAtomContainer>(fragSmiles, fragMol); int ac = fragMol.Atoms.Count; for (fi = frags.Count - 1; fi >= 0; fi--) // insert into list so that fragments are ordered largest to smallest { if (frags[fi].Value.Atoms.Count >= ac) { break; } } frags.Insert(fi + 1, kvp); } return(frags); }
/// <summary> /// Modules for cleaning a molecule /// </summary> /// <param name="molecule"></param> /// <returns>cleaned AtomContainer</returns> public static IAtomContainer CheckAndCleanMolecule(IAtomContainer molecule) { bool isMarkush = false; foreach (var atom in molecule.Atoms) { if (atom.Symbol.Equals("R", StringComparison.Ordinal)) { isMarkush = true; break; } } if (isMarkush) { Console.Error.WriteLine("Skipping Markush structure for sanity check"); } // Check for salts and such if (!ConnectivityChecker.IsConnected(molecule)) { // lets see if we have just two parts if so, we assume its a salt and just work // on the larger part. Ideally we should have a check to ensure that the smaller // part is a metal/halogen etc. var fragments = ConnectivityChecker.PartitionIntoMolecules(molecule).ToReadOnlyList(); if (fragments.Count > 2) { Console.Error.WriteLine("More than 2 components. Skipped"); } else { var frag1 = fragments[0]; var frag2 = fragments[1]; if (frag1.Atoms.Count > frag2.Atoms.Count) { molecule = frag1; } else { molecule = frag2; } } } Configure(molecule); return(molecule); }
public static void RemoveElectronContainer(IChemObjectSet <IAtomContainer> set, IElectronContainer electrons) { foreach (var atomContainer in set) { if (atomContainer.Contains(electrons)) { atomContainer.Remove(electrons); var molecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer); if (molecules.Count > 1) { set.Remove(atomContainer); for (int k = 0; k < molecules.Count; k++) { set.Add(molecules[k]); } } return; } } }
private static int GetFragmentCount(IAtomContainer molecule) { bool fragmentFlag = true; var fragmentMolSet = ChemObjectBuilder.Instance.NewAtomContainerSet(); int countFrag = 0; if (molecule.Atoms.Count > 0) { fragmentFlag = ConnectivityChecker.IsConnected(molecule); if (!fragmentFlag) { fragmentMolSet.AddRange(ConnectivityChecker.PartitionIntoMolecules(molecule)); } else { fragmentMolSet.Add(molecule); } countFrag = fragmentMolSet.Count; } return(countFrag); }
/// <summary> /// Determine the ring set for this atom container. /// </summary> /// <param name="atomContainer">the atom container to find rings in.</param> /// <returns>the rings of the molecule</returns> protected virtual IRingSet GetRingSet(IAtomContainer atomContainer) { IRingSet ringSet = atomContainer.Builder.NewRingSet(); try { var molecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer); foreach (var mol in molecules) { ringSet.Add(Cycles.FindSSSR(mol).ToRingSet()); } return(ringSet); } catch (Exception exception) { Trace.TraceWarning("Could not partition molecule: " + exception.Message); Debug.WriteLine(exception); return(ringSet); } }
/// <summary> /// Generates a shortest path based BitArray fingerprint for the given AtomContainer. /// </summary> /// <param name="ac">The AtomContainer for which a fingerprint is generated</param> /// <exception cref="CDKException">if there error in aromaticity perception or other CDK functions</exception> /// <returns>A <see cref="BitArray"/> representing the fingerprint</returns> public override IBitFingerprint GetBitFingerprint(IAtomContainer ac) { IAtomContainer atomContainer = null; atomContainer = (IAtomContainer)ac.Clone(); Aromaticity.CDKLegacy.Apply(atomContainer); var bitSet = new BitArray(fingerprintLength); if (!ConnectivityChecker.IsConnected(atomContainer)) { var partitionedMolecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer); foreach (var container in partitionedMolecules) { AddUniquePath(container, bitSet); } } else { AddUniquePath(atomContainer, bitSet); } return(new BitSetFingerprint(bitSet)); }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList"> /// The list of atoms taking part in the mechanism. Only allowed two atoms. /// The first atom is the atom which contains the ISingleElectron and the second /// third is the atom which will be removed /// the first atom</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond. /// It is the bond which is moved</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("RadicalSiteIonizationMechanism only expects one IAtomContainer"); } if (atomList.Count != 3) { throw new CDKException("RadicalSiteIonizationMechanism expects three atoms in the List"); } if (bondList.Count != 2) { throw new CDKException("RadicalSiteIonizationMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom containing the ISingleElectron IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom2 = atomList[1]; // Atom IAtom atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; IAtom atom3 = atomList[2]; // Atom to be saved IAtom atom3C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)]; IBond bond1 = bondList[0]; // Bond to increase the order int posBond1 = molecule.Bonds.IndexOf(bond1); IBond bond2 = bondList[1]; // Bond to remove int posBond2 = molecule.Bonds.IndexOf(bond2); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]); reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]); var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C); reactantCloned.SingleElectrons.Remove(selectron.Last()); atom1C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } atom2C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } reactantCloned.SingleElectrons.Add(atom2C.Builder.NewSingleElectron(atom3C)); atom3C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = atom2C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom2C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); foreach (var moleculeP in moleculeSetP) { reaction.Products.Add(moleculeP); } return(reaction); }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed two atoms. The first atom receives the charge and the second the single electron</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDKAtomTypeMatcher.GetInstance(CDKAtomTypeMatcher.Mode.RequireExplicitHydrogens); if (atomContainerSet.Count != 1) { throw new CDKException("RemovingSEofBMechanism only expects one IAtomContainer"); } if (atomList.Count != 2) { throw new CDKException("RemovingSEofBMechanism expects two atoms in the List"); } if (bondList.Count != 1) { throw new CDKException("RemovingSEofBMechanism only expects one bond in the List"); } var molecule = atomContainerSet[0]; var reactantCloned = (IAtomContainer)molecule.Clone(); var atom1 = atomList[0]; var atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; var atom2 = atomList[1]; var atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; var bond1 = bondList[0]; var posBond1 = molecule.Bonds.IndexOf(bond1); if (bond1.Order == BondOrder.Single) { reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond1]); } else { BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond1]); } var charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge + 1; reactantCloned.SingleElectrons.Add(atom1C.Builder.NewSingleElectron(atom2C)); // check if resulting atom type is reasonable atom1C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); var type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } atom2C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } var reaction = atom1C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom1C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } if (bond1.Order != BondOrder.Single) { reaction.Products.Add(reactantCloned); } else { var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); foreach (var moleculeP in moleculeSetP) { reaction.Products.Add(moleculeP); } } return(reaction); }
/// <summary> /// Find all enabled abbreviations in the provided molecule. They are not /// added to the existing Sgroups and may need filtering. /// </summary> /// <param name="mol">molecule</param> /// <returns>list of new abbreviation Sgroups</returns> public IList <Sgroup> Generate(IAtomContainer mol) { // mark which atoms have already been abbreviated or are // part of an existing Sgroup var usedAtoms = new HashSet <IAtom>(); var sgroups = mol.GetCtabSgroups(); if (sgroups != null) { foreach (var sgroup in sgroups) { foreach (var atom in sgroup.Atoms) { usedAtoms.Add(atom); } } } var newSgroups = new List <Sgroup>(); // disconnected abbreviations, salts, common reagents, large compounds if (!usedAtoms.Any()) { try { var copy = AtomContainerManipulator.CopyAndSuppressedHydrogens(mol); string cansmi = usmigen.Create(copy); if (disconnectedAbbreviations.TryGetValue(cansmi, out string label) && !disabled.Contains(label) && ContractToSingleLabel) { var sgroup = new Sgroup { Type = SgroupType.CtabAbbreviation, Subscript = label }; foreach (var atom in mol.Atoms) { sgroup.Atoms.Add(atom); } return(new[] { sgroup }); } else if (cansmi.Contains(".")) { var parts = ConnectivityChecker.PartitionIntoMolecules(mol); // leave one out Sgroup best = null; for (int i = 0; i < parts.Count; i++) { var a = parts[i]; var b = a.Builder.NewAtomContainer(); for (int j = 0; j < parts.Count; j++) { if (j != i) { b.Add(parts[j]); } } var sgroup1 = GetAbbr(a); var sgroup2 = GetAbbr(b); if (sgroup1 != null && sgroup2 != null && ContractToSingleLabel) { var combined = new Sgroup(); label = null; foreach (var atom in sgroup1.Atoms) { combined.Atoms.Add(atom); } foreach (var atom in sgroup2.Atoms) { combined.Atoms.Add(atom); } if (sgroup1.Subscript.Length > sgroup2.Subscript.Length) { combined.Subscript = sgroup1.Subscript + String_Interpunct + sgroup2.Subscript; } else { combined.Subscript = sgroup2.Subscript + String_Interpunct + sgroup1.Subscript; } combined.Type = SgroupType.CtabAbbreviation; return(new[] { combined }); } if (sgroup1 != null && (best == null || sgroup1.Atoms.Count > best.Atoms.Count)) { best = sgroup1; } if (sgroup2 != null && (best == null || sgroup2.Atoms.Count < best.Atoms.Count)) { best = sgroup2; } } if (best != null) { newSgroups.Add(best); foreach (var atom in best.Atoms) { usedAtoms.Add(atom); } } } } catch (CDKException) { } } var fragments = GenerateFragments(mol); var sgroupAdjs = new MultiDictionary <IAtom, Sgroup>(); foreach (var frag in fragments) { try { var smi = usmigen.Create(AtomContainerManipulator.CopyAndSuppressedHydrogens(frag)); if (!connectedAbbreviations.TryGetValue(smi, out string label) || disabled.Contains(label)) { continue; } bool overlap = false; // note: first atom is '*' var numAtoms = frag.Atoms.Count; var numBonds = frag.Bonds.Count; for (int i = 1; i < numAtoms; i++) { if (usedAtoms.Contains(frag.Atoms[i])) { overlap = true; break; } } // overlaps with previous assignment if (overlap) { continue; } // create new abbreviation Sgroup var sgroup = new Sgroup { Type = SgroupType.CtabAbbreviation, Subscript = label }; var attachBond = frag.Bonds[0].GetProperty <IBond>(PropertyName_CutBond); IAtom attachAtom = null; sgroup.Bonds.Add(attachBond); for (int i = 1; i < numAtoms; i++) { var atom = frag.Atoms[i]; usedAtoms.Add(atom); sgroup.Atoms.Add(atom); if (attachBond.Begin.Equals(atom)) { attachAtom = attachBond.End; } else if (attachBond.End.Equals(atom)) { attachAtom = attachBond.Begin; } } if (attachAtom != null) { sgroupAdjs.Add(attachAtom, sgroup); } newSgroups.Add(sgroup); } catch (CDKException) { // ignore } } if (!ContractOnHetero) { return(newSgroups); } // now collapse foreach (var attach in mol.Atoms) { if (usedAtoms.Contains(attach)) { continue; } // skip charged or isotopic labelled, C or R/*, H, He if ((attach.FormalCharge != null && attach.FormalCharge != 0) || attach.MassNumber != null || attach.AtomicNumber == 6 || attach.AtomicNumber < 2) { continue; } var hcount = attach.ImplicitHydrogenCount.Value; var xatoms = new HashSet <IAtom>(); var xbonds = new HashSet <IBond>(); var newbonds = new HashSet <IBond>(); xatoms.Add(attach); var nbrSymbols = new List <string>(); var todelete = new HashSet <Sgroup>(); foreach (var sgroup in sgroupAdjs[attach]) { if (ContainsChargeChar(sgroup.Subscript)) { continue; } if (sgroup.Bonds.Count != 1) { continue; } var xbond = sgroup.Bonds.First(); xbonds.Add(xbond); foreach (var a in sgroup.Atoms) { xatoms.Add(a); } if (attach.Symbol.Length == 1 && char.IsLower(sgroup.Subscript[0])) { if (ChemicalElement.OfSymbol(attach.Symbol + sgroup.Subscript[0]) != ChemicalElement.R) { goto continue_collapse; } } nbrSymbols.Add(sgroup.Subscript); todelete.Add(sgroup); } int numSGrpNbrs = nbrSymbols.Count; foreach (var bond in mol.GetConnectedBonds(attach)) { if (!xbonds.Contains(bond)) { var nbr = bond.GetOther(attach); // contract terminal bonds if (mol.GetConnectedBonds(nbr).Count() == 1) { if (nbr.MassNumber != null || (nbr.FormalCharge != null && nbr.FormalCharge != 0)) { newbonds.Add(bond); } else if (nbr.AtomicNumber == 1) { hcount++; xatoms.Add(nbr); } else if (nbr.AtomicNumber > 0) { nbrSymbols.Add(NewSymbol(nbr.AtomicNumber, nbr.ImplicitHydrogenCount.Value, false)); xatoms.Add(nbr); } } else { newbonds.Add(bond); } } } // reject if no symbols // reject if no bonds (<1), except if all symbols are identical... (HashSet.size==1) // reject if more that 2 bonds if (!nbrSymbols.Any() || newbonds.Count < 1 && (new HashSet <string>(nbrSymbols).Count != 1) || newbonds.Count > 2) { continue; } // create the symbol var sb = new StringBuilder(); sb.Append(NewSymbol(attach.AtomicNumber, hcount, newbonds.Count == 0)); string prev = null; int count = 0; nbrSymbols.Sort((o1, o2) => { int cmp = o1.Length.CompareTo(o2.Length); if (cmp != 0) { return(cmp); } return(o1.CompareTo(o2)); }); foreach (string nbrSymbol in nbrSymbols) { if (nbrSymbol.Equals(prev)) { count++; } else { bool 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); // remove existing foreach (var e in todelete) { newSgroups.Remove(e); } // create new var newSgroup = new Sgroup { Type = SgroupType.CtabAbbreviation, Subscript = sb.ToString() }; foreach (var bond in newbonds) { newSgroup.Bonds.Add(bond); } foreach (var atom in xatoms) { newSgroup.Atoms.Add(atom); } newSgroups.Add(newSgroup); foreach (var a in xatoms) { usedAtoms.Add(a); } continue_collapse: ; } return(newSgroups); }
/// <summary> /// Performs the n point crossover of two <see cref="IAtomContainer"/>. /// </summary> /// <remarks> /// Precondition: The atoms in the molecules are ordered by properties to /// preserve (e. g. atom symbol). Due to its randomized nature, this method /// fails in around 3% of all cases. A <see cref="CDKException"/> with message "Could not /// mate these properly" will then be thrown. /// </remarks> /// <returns>The children.</returns> /// <exception cref="CDKException">if it was not possible to form off springs.</exception> public IReadOnlyList <IAtomContainer> DoCrossover(IAtomContainer dad, IAtomContainer mom) { int tries = 0; while (true) { int dim = dad.Atoms.Count; var redChild = new IAtomContainer[2]; var blueChild = new IAtomContainer[2]; var redAtoms = new List <int>(); var blueAtoms = new List <int>(); // randomly divide atoms into two parts: redAtoms and blueAtoms. if (splitMode == SplitMode.Random) { // better way to randomly divide atoms into two parts: redAtoms // and blueAtoms. for (int i = 0; i < dim; i++) { redAtoms.Add(i); } for (int i = 0; i < (dim - numatoms); i++) { int ranInt = RandomNumbersTool.RandomInt(0, redAtoms.Count - 1); redAtoms.RemoveAt(ranInt); blueAtoms.Add(ranInt); } } else { // split graph using depth/breadth first traverse var graph = new ChemGraph(dad) { NumAtoms = numatoms }; if (splitMode == SplitMode.DepthFirst) { redAtoms = graph.PickDFGraph().ToList(); } else { //this is SPLIT_MODE_BREADTH_FIRST redAtoms = graph.PickBFGraph().ToList(); } for (int i = 0; i < dim; i++) { int element = i; if (!(redAtoms.Contains(element))) { blueAtoms.Add(element); } } } /* * dividing over ** */ redChild[0] = dad.Builder.NewAtomContainer(dad); blueChild[0] = dad.Builder.NewAtomContainer(dad); redChild[1] = dad.Builder.NewAtomContainer(mom); blueChild[1] = dad.Builder.NewAtomContainer(mom); var blueAtomsInRedChild0 = new List <IAtom>(); for (int j = 0; j < blueAtoms.Count; j++) { blueAtomsInRedChild0.Add(redChild[0].Atoms[(int)blueAtoms[j]]); } for (int j = 0; j < blueAtomsInRedChild0.Count; j++) { redChild[0].RemoveAtom(blueAtomsInRedChild0[j]); } var blueAtomsInRedChild1 = new List <IAtom>(); for (int j = 0; j < blueAtoms.Count; j++) { blueAtomsInRedChild1.Add(redChild[1].Atoms[(int)blueAtoms[j]]); } for (int j = 0; j < blueAtomsInRedChild1.Count; j++) { redChild[1].RemoveAtom(blueAtomsInRedChild1[j]); } var redAtomsInBlueChild0 = new List <IAtom>(); for (int j = 0; j < redAtoms.Count; j++) { redAtomsInBlueChild0.Add(blueChild[0].Atoms[(int)redAtoms[j]]); } for (int j = 0; j < redAtomsInBlueChild0.Count; j++) { blueChild[0].RemoveAtom(redAtomsInBlueChild0[j]); } var redAtomsInBlueChild1 = new List <IAtom>(); for (int j = 0; j < redAtoms.Count; j++) { redAtomsInBlueChild1.Add(blueChild[1].Atoms[(int)redAtoms[j]]); } for (int j = 0; j < redAtomsInBlueChild1.Count; j++) { blueChild[1].RemoveAtom(redAtomsInBlueChild1[j]); } //if the two fragments of one and only one parent have an uneven number //of attachment points, we need to rearrange them var satCheck = CDK.SaturationChecker; double red1attachpoints = 0; for (int i = 0; i < redChild[0].Atoms.Count; i++) { red1attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[0].Atoms[i], redChild[0]); } double red2attachpoints = 0; for (int i = 0; i < redChild[1].Atoms.Count; i++) { red2attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[1].Atoms[i], redChild[1]); } bool isok = true; if (red1attachpoints % 2 == 1 ^ red2attachpoints % 2 == 1) { isok = false; var firstToBalance = redChild[1]; var secondToBalance = blueChild[0]; if (red1attachpoints % 2 == 1) { firstToBalance = redChild[0]; secondToBalance = blueChild[1]; } //we need an atom which has //- an uneven number of "attachment points" and //- an even number of outgoing bonds foreach (var atom in firstToBalance.Atoms) { if (satCheck.GetCurrentMaxBondOrder(atom, firstToBalance) % 2 == 1 && firstToBalance.GetBondOrderSum(atom) % 2 == 0) { //we remove this from it's current container and add it to the other one firstToBalance.RemoveAtom(atom); secondToBalance.Atoms.Add(atom); isok = true; break; } } } //if we have combinable fragments if (isok) { //combine the fragments crosswise var newstrucs = new IChemObjectSet <IAtomContainer> [2]; newstrucs[0] = dad.Builder.NewAtomContainerSet(); newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[0])); newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[1])); newstrucs[1] = dad.Builder.NewAtomContainerSet(); newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[1])); newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[0])); //and merge var children = new List <IAtomContainer>(2); for (int f = 0; f < 2; f++) { var structrue = pfsm.Generate2(newstrucs[f]); if (structrue != null) { //if children are not correct, the outer loop will repeat, //so we ignore this children.Add(structrue); } } if (children.Count == 2 && ConnectivityChecker.IsConnected(children[0]) && ConnectivityChecker.IsConnected(children[1])) { return(children); } } tries++; if (tries > 20) { throw new CDKException("Could not mate these properly"); } } }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed two three. /// The first atom is the atom which must contain the charge to be moved, the second /// is the atom which is in the middle and the third is the atom which acquires the new charge /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed two bond.</param> /// The first bond is the bond to increase the order and the second is the bond /// to decrease the order /// It is the bond which is moved</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("RearrangementChargeMechanism only expects one IAtomContainer"); } if (atomList.Count != 3) { throw new CDKException("RearrangementChargeMechanism expects three atoms in the List"); } if (bondList.Count != 2) { throw new CDKException("RearrangementChargeMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; // Atom with the charge IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom3 = atomList[2]; // Atom which acquires the charge IAtom atom3C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)]; IBond bond1 = bondList[0]; // Bond with single bond int posBond1 = molecule.Bonds.IndexOf(bond1); IBond bond2 = bondList[1]; // Bond with double bond int posBond2 = molecule.Bonds.IndexOf(bond2); BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]); if (bond2.Order == BondOrder.Single) { reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]); } else { BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond2]); } //Depending of the charge moving (radical, + or -) there is a different situation if (reactantCloned.GetConnectedSingleElectrons(atom1C).Any()) { var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C); reactantCloned.SingleElectrons.Remove(selectron.Last()); reactantCloned.SingleElectrons.Add(bond2.Builder.NewSingleElectron(atom3C)); } else if (atom1C.FormalCharge > 0) { int charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge - 1; charge = atom3C.FormalCharge.Value; atom3C.FormalCharge = charge + 1; } else if (atom1C.FormalCharge < 1) { int charge = atom1C.FormalCharge.Value; atom1C.FormalCharge = charge + 1; var ln = reactantCloned.GetConnectedLonePairs(atom1C); reactantCloned.LonePairs.Remove(ln.Last()); atom1C.IsAromatic = false; charge = atom3C.FormalCharge.Value; atom3C.FormalCharge = charge - 1; reactantCloned.LonePairs.Add(bond2.Builder.NewLonePair(atom3C)); atom3C.IsAromatic = false; } else { return(null); } atom1C.Hybridization = Hybridization.Unset; atom3C.Hybridization = Hybridization.Unset; AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = bond2.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = bond2.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } if (bond2.Order != BondOrder.Single) { reaction.Products.Add(reactantCloned); } else { IChemObjectSet <IAtomContainer> moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); for (int z = 0; z < moleculeSetP.Count(); z++) { reaction.Products.Add((IAtomContainer)moleculeSetP[z]); } } return(reaction); }
/// <summary> /// Parse a reaction SMILES. /// </summary> /// <param name="smiles">The SMILES string to parse</param> /// <returns>An instance of <see cref="IReaction"/></returns> /// <exception cref="InvalidSmilesException">if the string cannot be parsed</exception> /// <seealso cref="ParseSmiles(string)"/> public IReaction ParseReactionSmiles(string smiles) { if (!smiles.Contains(">")) { throw new InvalidSmilesException("Not a reaction SMILES: " + smiles); } var first = smiles.IndexOf('>'); var second = smiles.IndexOf('>', first + 1); if (second < 0) { throw new InvalidSmilesException("Invalid reaction SMILES:" + smiles); } var reactants = smiles.Substring(0, first); var agents = smiles.Substring(first + 1, second - (first + 1)); var products = smiles.Substring(second + 1, smiles.Length - (second + 1)); var reaction = builder.NewReaction(); // add reactants if (!(reactants.Count() == 0)) { var reactantContainer = ParseSmiles(reactants, true); var reactantSet = ConnectivityChecker.PartitionIntoMolecules(reactantContainer); foreach (var reactant in reactantSet) { reaction.Reactants.Add(reactant); } } // add agents if (!(agents.Count() == 0)) { var agentContainer = ParseSmiles(agents, true); var agentSet = ConnectivityChecker.PartitionIntoMolecules(agentContainer); foreach (var agent in agentSet) { reaction.Agents.Add(agent); } } string title = null; // add products if (!(products.Count() == 0)) { var productContainer = ParseSmiles(products, true); var productSet = ConnectivityChecker.PartitionIntoMolecules(productContainer); foreach (var product in productSet) { reaction.Products.Add(product); } reaction.SetProperty(CDKPropertyName.Title, title = productContainer.Title); } try { //CXSMILES layer ParseRxnCXSMILES(title, reaction); } catch (Exception e) { //e.StackTrace throw new InvalidSmilesException("Error parsing CXSMILES:" + e.Message); } return(reaction); }
/// <summary> /// Initiates the process for the given mechanism. The atoms to apply are mapped between /// reactants and products. /// </summary> /// <param name="atomContainerSet"></param> /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed two atoms. Both atoms acquire a ISingleElectron</param> /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond</param> /// <returns>The Reaction mechanism</returns> public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList) { var atMatcher = CDK.AtomTypeMatcher; if (atomContainerSet.Count != 1) { throw new CDKException("TautomerizationMechanism only expects one IAtomContainer"); } if (atomList.Count != 2) { throw new CDKException("HomolyticCleavageMechanism expects two atoms in the List"); } if (bondList.Count != 1) { throw new CDKException("HomolyticCleavageMechanism only expect one bond in the List"); } IAtomContainer molecule = atomContainerSet[0]; IAtomContainer reactantCloned; reactantCloned = (IAtomContainer)molecule.Clone(); IAtom atom1 = atomList[0]; IAtom atom1C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)]; IAtom atom2 = atomList[1]; IAtom atom2C = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)]; IBond bond1 = bondList[0]; int posBond1 = molecule.Bonds.IndexOf(bond1); if (bond1.Order == BondOrder.Single) { reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond1]); } else { BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond1]); } reactantCloned.SingleElectrons.Add(bond1.Builder.NewSingleElectron(atom1C)); reactantCloned.SingleElectrons.Add(bond1.Builder.NewSingleElectron(atom2C)); AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned); // check if resulting atom type is reasonable atom1C.Hybridization = Hybridization.Unset; IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } // check if resulting atom type is reasonable: an acceptor atom cannot be charged positive*/ atom2C.Hybridization = Hybridization.Unset; type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C); if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal)) { return(null); } IReaction reaction = atom2C.Builder.NewReaction(); reaction.Reactants.Add(molecule); /* mapping */ foreach (var atom in molecule.Atoms) { IMapping mapping = atom2C.Builder.NewMapping(atom, reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]); reaction.Mappings.Add(mapping); } if (bond1.Order != BondOrder.Single) { reaction.Products.Add(reactantCloned); } else { var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned); foreach (var moleculeP in moleculeSetP) { reaction.Products.Add(moleculeP); } } return(reaction); }
/// <summary> /// BuildFingerprints /// </summary> public static void BuildFingerprints( UniChemData icd) { IAtomContainer mol, mol2; InChIGenerator ig = null; int acc, aci, ci; icd.Children.Clear(); string parentFIKHB = icd.GetFIKHB(); DateTime t0 = DateTime.Now; mol = CdkMol.InChIToAtomContainer(icd.InChIString); icd.CanonSmiles = CdkMol.AtomContainerToSmiles(mol); InChIToAtomContainerTime += TimeOfDay.Delta(ref t0); BitSetFingerprint fp = // generate a fingerprint CdkFingerprint.BuildBitSetFingerprint(mol, FingerprintType.MACCS, -1, -1); BuildFinterprintTime1 += TimeOfDay.Delta(ref t0); icd.Fingerprint = fp; if (ConnectivityChecker.IsConnected(mol)) { return; // single fragment } InChIGeneratorFactory igf = InChIGeneratorFactory.Instance; AtomContainerSet acs = (AtomContainerSet)ConnectivityChecker.PartitionIntoMolecules(mol); PartitionIntoMoleculesTime += TimeOfDay.Delta(ref t0); acc = acs.Count; for (aci = 0; aci < acc; aci++) { mol2 = acs[aci]; GetAtomContainerTime += TimeOfDay.Delta(ref t0); ig = igf.GetInChIGenerator(mol2); if (!IsAcceptableInchiStatus(ig)) { continue; } string childKey = ig.GetInChIKey(); string childFIKHB = UniChemUtil.GetFIKHB(childKey); InChIGeneratorTime += TimeOfDay.Delta(ref t0); fp = // generate a fingerprint for the fragment CdkFingerprint.BuildBitSetFingerprint(mol2, FingerprintType.MACCS, -1, -1); BuildFinterprintTime2 += TimeOfDay.Delta(ref t0); for (ci = 0; ci < icd.Children.Count; ci++) // see if a dup child { if (icd.Children[ci].ChildFIKHB == childFIKHB) { break; } } if (ci < icd.Children.Count) { continue; // skip if dup } UniChemFIKHBHierarchy fikhbHier = new UniChemFIKHBHierarchy(); fikhbHier.ParentFIKHB = parentFIKHB; fikhbHier.ChildFIKHB = childFIKHB; fikhbHier.CanonSmiles = CdkMol.AtomContainerToSmiles(mol2); fikhbHier.Fingerprint = fp; icd.Children.Add(fikhbHier); } return; }