/// <summary> /// Generates and assigns abbreviations to a molecule. Abbreviations are first /// generated with <see cref="Generate(IAtomContainer)"/> and the filtered based on /// the coverage. Currently only abbreviations that cover 100%, or < 40% of the /// atoms are assigned. /// </summary> /// <param name="mol">molecule</param> /// <returns>number of new abbreviations</returns> /// <seealso cref="Generate(IAtomContainer)"/> public int Apply(IAtomContainer mol) { var newSgroups = Generate(mol); var sgroups = mol.GetCtabSgroups(); if (sgroups == null) { sgroups = new List <Sgroup>(); } else { sgroups = new List <Sgroup>(sgroups); } var prev = sgroups.Count; foreach (var sgroup in newSgroups) { var coverage = sgroup.Atoms.Count / (double)mol.Atoms.Count; // update xml comment if changed! if (!sgroup.Bonds.Any() || coverage < 0.4d) { sgroups.Add(sgroup); } } mol.SetCtabSgroups(sgroups); return(sgroups.Count - prev); }
public void TestSgroupAtomListWrapping() { IAtomContainer mol = TestMoleculeFactory.MakeEthylPropylPhenantren(); Sgroup sgroup = new Sgroup(); foreach (var atom in mol.Atoms) { sgroup.Atoms.Add(atom); } mol.SetCtabSgroups(new[] { sgroup }); StringWriter sw = new StringWriter(); using (MDLV2000Writer mdlw = new MDLV2000Writer(sw)) { mdlw.Write(mol); string output = sw.ToString(); Assert.IsTrue(output.Contains("M SAL 1 15")); Assert.IsTrue(output.Contains("M SAL 1 4")); } }
/// <summary> /// Reads the bond atoms, order and stereo configuration. /// </summary> public void ReadBondBlock(IAtomContainer readData) { Trace.TraceInformation("Reading BOND block"); bool foundEND = false; while (!foundEND) { string command = ReadCommand(ReadLine()); if (string.Equals("END BOND", command, StringComparison.Ordinal)) { foundEND = true; } else { Debug.WriteLine($"Parsing bond from: {command}"); var tokenizer = Strings.Tokenize(command).GetEnumerator(); IBond bond = readData.Builder.NewBond(); // parse the index try { tokenizer.MoveNext(); string indexString = tokenizer.Current; bond.Id = indexString; } catch (Exception exception) { string error = "Error while parsing bond index"; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } // parse the order try { tokenizer.MoveNext(); string orderString = tokenizer.Current; int order = int.Parse(orderString, NumberFormatInfo.InvariantInfo); if (order >= 4) { Trace.TraceWarning("Query order types are not supported (yet). File a bug if you need it"); } else { bond.Order = BondManipulator.CreateBondOrder((double)order); } } catch (Exception exception) { string error = "Error while parsing bond index"; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } // parse index atom 1 try { tokenizer.MoveNext(); string indexAtom1String = tokenizer.Current; int indexAtom1 = int.Parse(indexAtom1String, NumberFormatInfo.InvariantInfo); IAtom atom1 = readData.Atoms[indexAtom1 - 1]; bond.Atoms.Add(atom1); // bond.Atoms[0] } catch (Exception exception) { string error = "Error while parsing index atom 1 in bond"; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } // parse index atom 2 try { tokenizer.MoveNext(); string indexAtom2String = tokenizer.Current; int indexAtom2 = int.Parse(indexAtom2String, NumberFormatInfo.InvariantInfo); IAtom atom2 = readData.Atoms[indexAtom2 - 1]; bond.Atoms.Add(atom2); // bond.Atoms[1] } catch (Exception exception) { string error = "Error while parsing index atom 2 in bond"; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } var endpts = new List <IAtom>(); string attach = null; // the rest are key=value fields if (command.IndexOf('=') != -1) { var options = ParseOptions(ExhaustStringTokenizer(tokenizer)); foreach (var key in options.Keys) { string value = options[key]; try { switch (key) { case "CFG": int configuration = int.Parse(value, NumberFormatInfo.InvariantInfo); if (configuration == 0) { bond.Stereo = BondStereo.None; } else if (configuration == 1) { bond.Stereo = BondStereo.Up; } else if (configuration == 2) { bond.Stereo = BondStereo.None; } else if (configuration == 3) { bond.Stereo = BondStereo.Down; } break; case "ENDPTS": string[] endptStr = value.Split(' '); // skip first value that is count for (int i = 1; i < endptStr.Length; i++) { endpts.Add(readData.Atoms[int.Parse(endptStr[i], NumberFormatInfo.InvariantInfo) - 1]); } break; case "ATTACH": attach = value; break; default: Trace.TraceWarning("Not parsing key: " + key); break; } } catch (Exception exception) { string error = "Error while parsing key/value " + key + "=" + value + ": " + exception.Message; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } } } // storing bond readData.Bonds.Add(bond); // storing positional variation if (string.Equals("ANY", attach, StringComparison.Ordinal)) { Sgroup sgroup = new Sgroup { Type = SgroupType.ExtMulticenter }; sgroup.Atoms.Add(bond.Begin); // could be other end? sgroup.Bonds.Add(bond); foreach (var endpt in endpts) { sgroup.Atoms.Add(endpt); } var sgroups = readData.GetCtabSgroups(); if (sgroups == null) { readData.SetCtabSgroups(sgroups = new List <Sgroup>(4)); } sgroups.Add(sgroup); } Debug.WriteLine($"Added bond: {bond}"); } } }