public void TestMultipleDataFields() { var filename = "NCDK.Data.MDL.bug1587283.mol"; var ins = ResourceLoader.GetAsStream(filename); var reader = new MDLV2000Reader(ins); IChemFile fileContents = (IChemFile)reader.Read(builder.NewChemFile()); reader.Close(); Assert.AreEqual(1, fileContents.Count); IChemSequence sequence = fileContents[0]; Assert.IsNotNull(sequence); Assert.AreEqual(1, sequence.Count); var model = sequence[0]; Assert.IsNotNull(model); var som = model.MoleculeSet; Assert.IsNotNull(som); Assert.AreEqual(1, som.Count); IAtomContainer m = som[0]; Assert.IsNotNull(m); Assert.AreEqual("B02", m.GetProperty <string>("id_no")); Assert.AreEqual("2-2", m.GetProperty <string>("eductkey")); Assert.AreEqual("1", m.GetProperty <string>("Step")); Assert.AreEqual("2", m.GetProperty <string>("Pos")); Assert.AreEqual("B02", m.GetProperty <string>("Tag")); }
public void TestDataFromSDFReading() { var filename = "NCDK.Data.MDL.test.sdf"; // a multi molecule SDF file var ins = ResourceLoader.GetAsStream(filename); var reader = new MDLV2000Reader(ins); var fileContents = reader.Read(builder.NewChemFile()); reader.Close(); Assert.AreEqual(1, fileContents.Count); var sequence = fileContents[0]; Assert.IsNotNull(sequence); Assert.AreEqual(9, sequence.Count); var model = sequence[0]; Assert.IsNotNull(model); var som = model.MoleculeSet; Assert.IsNotNull(som); Assert.AreEqual(1, som.Count); IAtomContainer m = som[0]; Assert.IsNotNull(m); Assert.AreEqual("1", m.GetProperty <string>("E_NSC")); Assert.AreEqual("553-97-9", m.GetProperty <string>("E_CAS")); }
private static void CalcHomoLumo(IAtomContainer mol) { var eigenProp = mol.GetProperty <string>(eigenvalues); if (eigenProp == null) { return; } //mol.GetProperties().Remove(eigenvalues); var filledLevelsProp = mol.GetProperty <string>(filledLevels); //mol.GetProperties().Remove(filledLevels); if (filledLevelsProp == null) { return; } int nFilledLevels = 0; try { nFilledLevels = int.Parse(filledLevelsProp, NumberFormatInfo.InvariantInfo); } catch (FormatException) { return; } var eigenVals = Strings.Tokenize(eigenProp); int levelCounter = 0; foreach (var eigenVal in eigenVals) { if (string.IsNullOrWhiteSpace(eigenVal)) { continue; } else { try { // check if the value is an proper double: double.Parse(eigenVal, NumberFormatInfo.InvariantInfo); levelCounter++; if (levelCounter == nFilledLevels) { mol.SetProperty("EHOMO", eigenVal); } else if (levelCounter == (nFilledLevels + 1)) { mol.SetProperty("ELUMO", eigenVal); } } catch (FormatException) { return; } } } }
/// <summary> /// Assign the partial charges, all existing charges are cleared. /// Atom types must be assigned first. /// </summary> /// <param name="mol">molecule</param> /// <returns>charges were assigned</returns> /// <seealso cref="PartialCharges(IAtomContainer)"/> /// <seealso cref="AssignAtomTypes(IAtomContainer)"/> public virtual bool PartialCharges(IAtomContainer mol) { var adjList = mol.GetProperty <int[][]>(MMFF_ADJLIST_CACHE); var edgeMap = mol.GetProperty <EdgeToBondMap>(MMFF_EDGEMAP_CACHE); if (adjList == null || edgeMap == null) { throw new ArgumentException("Invoke assignAtomTypes first."); } EffectiveCharges(mol); for (int v = 0; v < mol.Atoms.Count; v++) { var atom = mol.Atoms[v]; var symbType = atom.AtomTypeName; int thisType = mmffParamSet.IntType(symbType); // unknown if (thisType == 0) { continue; } double pbci = (double)mmffParamSet.GetPartialBondChargeIncrement(thisType); foreach (var w in adjList[v]) { int otherType = mmffParamSet.IntType(mol.Atoms[w].AtomTypeName); // unknown if (otherType == 0) { continue; } var bond = edgeMap[v, w]; int bondCls = mmffParamSet.GetBondCls(thisType, otherType, bond.Order.Numeric(), bond.GetProperty(MMFF_AROM, false)); var bci = mmffParamSet.GetBondChargeIncrement(bondCls, thisType, otherType); if (bci != null) { atom.Charge = atom.Charge.Value - (double)bci; } else { // empirical BCI atom.Charge = atom.Charge + (pbci - (double)mmffParamSet.GetPartialBondChargeIncrement(otherType)); } } } return(true); }
/// <summary> /// Assign the effective formal charges used by MMFF in calculating the /// final partial charge values. Atom types must be assigned first. All /// existing charges are cleared. /// </summary> /// <param name="mol">molecule</param> /// <returns>charges were assigned</returns> /// <seealso cref="PartialCharges(IAtomContainer)"/> /// <seealso cref="AssignAtomTypes(IAtomContainer)"/> public virtual bool EffectiveCharges(IAtomContainer mol) { var adjList = mol.GetProperty <int[][]>(MMFF_ADJLIST_CACHE); var edgeMap = mol.GetProperty <EdgeToBondMap>(MMFF_EDGEMAP_CACHE); if (adjList == null || edgeMap == null) { throw new ArgumentException("Invoke assignAtomTypes first."); } PrimaryCharges(mol, adjList, edgeMap); EffectiveCharges(mol, adjList); return(true); }
public void TestMultipleEntryFields() { var filename = "NCDK.Data.MDL.test.sdf"; var ins = ResourceLoader.GetAsStream(filename); using (var reader = new EnumerableSDFReader(ins, CDK.Builder)) { var tor = reader.GetEnumerator(); tor.MoveNext(); IAtomContainer m = (IAtomContainer)tor.Current; Assert.AreEqual("553-97-9", m.GetProperty <string>("E_CAS")); tor.MoveNext(); m = tor.Current; Assert.AreEqual("120-78-5", m.GetProperty <string>("E_CAS")); } }
internal void DetermineFilters(IAtomContainer query) { hasStereo = query.StereoElements.Any(); hasComponentGrouping = query.GetProperty <int[]>(ComponentFilter.Key) != null; foreach (var atom in query.Atoms) { var compId = atom.GetProperty <int?>(CDKPropertyName.ReactionGroup); var mapIdx = atom.GetProperty <int?>(CDKPropertyName.AtomAtomMapping); if (mapIdx != null && mapIdx != 0) { hasReactionMap = true; } if (compId != null && compId != 0) { hasComponentGrouping = true; } if (atom is IQueryAtom) { hasQueryStereo = true; } if (hasReactionMap && hasComponentGrouping && hasQueryStereo) { break; } } }
public void TestEmptyEntryIteratingReader() { var filename = "NCDK.Data.MDL.emptyStructures.sdf"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); EnumerableSDFReader reader = new EnumerableSDFReader(ins, CDK.Builder); int molCount = 0; foreach (var obj in reader) { Assert.IsNotNull(obj); Assert.IsTrue(obj is IAtomContainer); molCount++; if (molCount == 2) { IAtomContainer mol = (IAtomContainer)obj; string s = mol.GetProperty <string>("Species"); Assert.AreEqual("rat", s); } } Assert.AreEqual(2, molCount); reader.Close(); }
public void TestSDFFile6() { var filename = "NCDK.Data.MDL.test6.sdf"; // a multi molecule SDF file var ins = ResourceLoader.GetAsStream(filename); var reader = new MDLV2000Reader(ins); var fileContents = reader.Read(builder.NewChemFile()); reader.Close(); Assert.AreEqual(1, fileContents.Count); var sequence = fileContents[0]; Assert.IsNotNull(sequence); Assert.AreEqual(3, sequence.Count); for (int i = 0; i < sequence.Count; i++) { Assert.IsNotNull(sequence[i]); } var model = sequence[0]; Assert.IsNotNull(model); var som = model.MoleculeSet; Assert.IsNotNull(som); Assert.AreEqual(1, som.Count); IAtomContainer m = som[0]; Assert.IsNotNull(m); Assert.AreEqual("ola11", m.GetProperty <string>("STRUCTURE ID")); }
public void TestDescriptorValue() { IAtomContainer molecule = TestMoleculeFactory.MakeBenzene(); string[] propertyName = { "testKey1", "testKey2" }; string[] propertyValue = { "testValue1", "testValue2" }; for (int i = 0; i < propertyName.Length; i++) { molecule.SetProperty(propertyName[i], propertyValue[i]); } IAtomContainer roundTrippedMol = CMLRoundTripTool.RoundTripMolecule(convertor, molecule); for (int i = 0; i < propertyName.Length; i++) { Assert.IsNotNull(roundTrippedMol.GetProperty <string>(propertyName[i])); Assert.AreEqual(propertyValue[i], roundTrippedMol.GetProperty <string>(propertyName[i])); } }
public void TestReadDataItems() { var filename = "NCDK.Data.MDL.test.sdf"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); EnumerableSDFReader reader = new EnumerableSDFReader(ins, CDK.Builder); var etor = reader.GetEnumerator(); Assert.IsTrue(etor.MoveNext()); object obj = etor.Current; Assert.IsNotNull(obj); Assert.IsTrue(obj is IAtomContainer); IAtomContainer m = (IAtomContainer)obj; Assert.AreEqual("1", m.GetProperty <string>("E_NSC")); Assert.AreEqual("553-97-9", m.GetProperty <string>("E_CAS")); reader.Close(); }
public void TestReadingSmiFile_2() { var filename = "NCDK.Data.Smiles.smiles.smi"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); SMILESReader reader = new SMILESReader(ins); IChemObjectSet <IAtomContainer> som = reader.Read(new ChemObjectSet <IAtomContainer>()); IAtomContainer thisMol = som[1]; Assert.IsNull(thisMol.GetProperty <object>("SMIdbNAME")); }
public void TestList() { var filename = "NCDK.Data.ASN.PubChem.aceticAcids38.xml"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); var reader = new EnumerablePCCompoundXMLReader(new StreamReader(ins), ChemObjectBuilder.Instance); int molCount = 0; var set = ChemObjectBuilder.Instance.NewAtomContainerSet(); foreach (var obj in reader) { // Console.Out.WriteLine("next molecule found"); Assert.IsNotNull(obj); Assert.IsTrue(obj is IAtomContainer); set.Add((IAtomContainer)obj); molCount++; } Assert.AreEqual(3, molCount); IAtomContainer first = set[0]; Assert.AreEqual(8, first.Atoms.Count); Assert.AreEqual(7, first.Bonds.Count); Assert.IsNotNull(first.GetProperty <string>("IUPAC Name (Traditional)")); Assert.AreEqual("acetic acid", first.GetProperty <string>("IUPAC Name (Traditional)")); Assert.IsNotNull(first.GetProperty <string>("InChI")); Assert.AreEqual("InChI=1/C2H4O2/c1-2(3)4/h1H3,(H,3,4)/f/h3H", first.GetProperty <string>("InChI")); Assert.IsNotNull(first.GetProperty <string>("InChI")); Assert.AreEqual("176", first.GetProperty <string>("PubChem CID")); }
public void TestInChI() { var mol = new AtomContainer(); string inchi = "InChI=1/CH2O2/c2-1-3/h1H,(H,2,3)"; mol.SetProperty(CDKPropertyName.InChI, inchi); IAtomContainer roundTrippedMol = CMLRoundTripTool.RoundTripMolecule(convertor, mol); Assert.IsNotNull(roundTrippedMol); Assert.AreEqual(inchi, roundTrippedMol.GetProperty <string>(CDKPropertyName.InChI)); }
public void TestReadingSmiFile_1() { var filename = "NCDK.Data.Smiles.smiles.smi"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); SMILESReader reader = new SMILESReader(ins); IChemObjectSet <IAtomContainer> som = reader.Read(new ChemObjectSet <IAtomContainer>()); string name = null; IAtomContainer thisMol = som[0]; name = (thisMol.GetProperty <string>("SMIdbNAME")).ToString(); Assert.AreEqual("benzene", name); }
public void TestReading() { var filename = "NCDK.Data.ASN.PubChem.cid1.asn"; Trace.TraceInformation("Testing: " + filename); var ins = ResourceLoader.GetAsStream(filename); PCCompoundASNReader reader = new PCCompoundASNReader(ins); IChemFile cFile = (IChemFile)reader.Read(builder.NewChemFile()); reader.Close(); var containers = ChemFileManipulator.GetAllAtomContainers(cFile).ToReadOnlyList(); Assert.AreEqual(1, containers.Count); Assert.IsTrue(containers[0] is IAtomContainer); IAtomContainer molecule = containers[0]; Assert.IsNotNull(molecule); // check atom stuff Assert.AreEqual(31, molecule.Atoms.Count); Assert.IsNotNull(molecule.Atoms[3]); Assert.AreEqual("O", molecule.Atoms[3].Symbol); Assert.IsNotNull(molecule.Atoms[4]); Assert.AreEqual("N", molecule.Atoms[4].Symbol); // check bond stuff Assert.AreEqual(30, molecule.Bonds.Count); Assert.IsNotNull(molecule.Bonds[3]); Assert.AreEqual(molecule.Atoms[2], molecule.Bonds[3].Begin); Assert.AreEqual(molecule.Atoms[11], molecule.Bonds[3].End); // some extracted props Assert.AreEqual("InChI=1/C9H17NO4/c1-7(11)14-8(5-9(12)13)6-10(2,3)4/h8H,5-6H2,1-4H3", molecule.GetProperty <string>(CDKPropertyName.InChI)); Assert.AreEqual("CC(=O)OC(CC(=O)[O-])C[N+](C)(C)C", molecule.GetProperty <string>(CDKPropertyName.SMILES)); }
/// <inheritdoc/> public override Mappings MatchAll(IAtomContainer target) { EdgeToBondMap bonds2; int[][] g2; var cached = target.GetProperty <AdjListCache>(typeof(AdjListCache).FullName); if (cached == null || !cached.Validate(target)) { cached = new AdjListCache(target); target.SetProperty(typeof(AdjListCache).FullName, cached); } bonds2 = cached.bmap; g2 = cached.g; var iterable = new VFIterable(query, target, g1, g2, bonds1, bonds2, atomMatcher, bondMatcher, subgraph); var mappings = new Mappings(query, target, iterable); return(Filter(mappings, query, target)); }
public void TestBug2911300() { var filename = "NCDK.Data.MDL.bug2911300.sdf"; var ins = ResourceLoader.GetAsStream(filename); var reader = new MDLV2000Reader(ins); IChemFile fileContents = (IChemFile)reader.Read(builder.NewChemFile()); reader.Close(); Assert.AreEqual(1, fileContents.Count); IChemSequence sequence = fileContents[0]; var model = sequence[0]; Assert.IsNotNull(model); var som = model.MoleculeSet; Assert.IsNotNull(som); Assert.AreEqual(1, som.Count); IAtomContainer m = som[0]; Assert.IsNotNull(m); Assert.AreEqual(">1", m.GetProperty <string>("IC50_uM")); }
public void TestMoleculeProperty() { string[] key = { "customMoleculeProperty1", "customMoleculeProperty2" }; string[] value = { "true", "false" }; IAtomContainer mol = TestMoleculeFactory.MakeAdenine(); for (int i = 0; i < key.Length; i++) { mol.SetProperty(key[i], value[i]); } IAtomContainer roundTrippedMol = CMLRoundTripTool.RoundTripMolecule(convertor, mol); //Assert.AreEqual(convertor.CDKMoleculeToCMLMolecule(mol).ToXML(), // convertor.CDKMoleculeToCMLMolecule(roundTrippedMol).ToXML()); for (int i = 0; i < key.Length; i++) { var actual = roundTrippedMol.GetProperty <object>(key[i]); Assert.IsNotNull(actual); Assert.AreEqual(value[i], actual); } }
/// <summary> /// Write the three line header of the MDL format: title, version/timestamp, remark. /// </summary> /// <param name="mol">molecule being output</param> /// <exception cref="IOException">low-level IO error</exception> private void WriteHeader(IAtomContainer mol) { var title = mol.Title; if (title != null) { writer.WriteDirect(title.Substring(0, Math.Min(80, title.Length))); } writer.WriteDirect('\n'); // From CTX spec This line has the format: // IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR (FORTRAN: // A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) User's first // and last initials (l), program name (P), date/time (M/D/Y,H:m), // dimensional codes (d), scaling factors (S, s), energy (E) if modeling // program input, internal registry number (R) if input through MDL // form. A blank line can be substituted for line 2. writer.Write(" "); writer.Write(GetProgName()); writer.WriteDirect(DateTime.UtcNow.ToString("MMddyyHHmm", DateTimeFormatInfo.InvariantInfo)); var dim = GetNumberOfDimensions(mol); if (dim != 0) { writer.WriteDirect(dim.ToString(NumberFormatInfo.InvariantInfo)); writer.WriteDirect('D'); } writer.WriteDirect('\n'); var comment = mol.GetProperty <string>(CDKPropertyName.Remark); if (comment != null) { writer.WriteDirect(comment.Substring(0, Math.Min(80, comment.Length - 80))); } writer.WriteDirect('\n'); writer.WriteDirect(" 0 0 0 0 0 999 V3000\n"); }
public void ProblemSmiles() { TextReader reader = new StringReader(" okay\nn1cccc1 bad\n okay"); var smis = new EnumerableSMILESReader(reader, CDK.Builder).GetEnumerator(); Assert.IsTrue(smis.MoveNext()); IAtomContainer m1 = smis.Current; Assert.AreEqual(0, m1.Atoms.Count); Assert.AreEqual("okay", m1.Title); Assert.IsTrue(smis.MoveNext()); IAtomContainer m2 = smis.Current; Assert.AreEqual(0, m2.Atoms.Count); Assert.AreEqual("bad", m2.Title); Assert.AreEqual("n1cccc1 bad", m2.GetProperty <string>(EnumerableSMILESReader.BadSmilesInput)); smis.MoveNext(); IAtomContainer m3 = smis.Current; Assert.AreEqual(0, m3.Atoms.Count); Assert.AreEqual("okay", m3.Title); Assert.IsFalse(smis.MoveNext()); }
/// <summary> /// Create a predicate to match components for the provided query and target. /// The target is converted to an adjacency list (<see cref="GraphUtil.ToAdjList(IAtomContainer)"/> /// ) and the query components extracted /// from the property <see cref="Key"/> in the query. /// </summary> /// <param name="query">query structure</param> /// <param name="target">target structure</param> public ComponentFilter(IAtomContainer query, IAtomContainer target) : this(query.GetProperty <int[]>(Key) ?? DetermineComponents(query, false), DetermineComponents(target, true)) { }
public static IList <Sgroup> GetCtabSgroups(this IAtomContainer o) => o.GetProperty <IList <Sgroup> >(CtabSgroupsPropertyKey);
private IRenderingElement Generate(IAtomContainer molecule, RendererModel model, int atomNum) { // tag the atom and bond ids string molId = molecule.GetProperty <string>(MarkedElement.IdKey); if (molId != null) { int atomId = 0, bondid = 0; foreach (var atom in molecule.Atoms) { SetIfMissing(atom, MarkedElement.IdKey, molId + "atm" + ++atomId); } foreach (var bond in molecule.Bonds) { SetIfMissing(bond, MarkedElement.IdKey, molId + "bnd" + ++bondid); } } if (annotateAtomNumbers) { foreach (var atom in molecule.Atoms) { if (atom.GetProperty <string>(StandardGenerator.AnnotationLabelKey) != null) { throw new InvalidOperationException("Multiple annotation labels are not supported."); } atom.SetProperty(StandardGenerator.AnnotationLabelKey, (atomNum++).ToString()); } } else if (annotateAtomValues) { foreach (var atom in molecule.Atoms) { if (atom.GetProperty <string>(StandardGenerator.AnnotationLabelKey) != null) { throw new NotSupportedException("Multiple annotation labels are not supported."); } atom.SetProperty(StandardGenerator.AnnotationLabelKey, atom.GetProperty <string>(CDKPropertyName.Comment)); } } else if (annotateAtomMapNumbers) { foreach (var atom in molecule.Atoms) { if (atom.GetProperty <string>(StandardGenerator.AnnotationLabelKey) != null) { throw new InvalidOperationException("Multiple annotation labels are not supported."); } int mapidx = AccessAtomMap(atom); if (mapidx > 0) { atom.SetProperty(StandardGenerator.AnnotationLabelKey, mapidx.ToString()); } } } var grp = new ElementGroup(); foreach (var gen in generators) { grp.Add(gen.Generate(molecule, model)); } // cleanup if (annotateAtomNumbers || annotateAtomMapNumbers) { foreach (var atom in molecule.Atoms) { atom.RemoveProperty(StandardGenerator.AnnotationLabelKey); } } return(grp); }
// private procedures /// <summary> /// Private method that actually parses the input to read a <see cref="IChemFile"/> object. /// </summary> /// <returns>A ChemFile containing the data parsed from input.</returns> private IChemFile ReadChemFile(IChemFile file) { IChemSequence chemSequence = file.Builder.NewChemSequence(); int number_of_atoms = 0; try { string line; while ((line = input.ReadLine()) != null) { // parse frame by frame string token = line.Split('\t', ' ', ',', ';')[0]; number_of_atoms = int.Parse(token, NumberFormatInfo.InvariantInfo); string info = input.ReadLine(); IChemModel chemModel = file.Builder.NewChemModel(); var setOfMolecules = file.Builder.NewAtomContainerSet(); IAtomContainer m = file.Builder.NewAtomContainer(); m.Title = info; for (int i = 0; i < number_of_atoms; i++) { line = input.ReadLine(); if (line == null) { break; } if (line.StartsWithChar('#') && line.Length > 1) { var comment = m.GetProperty(CDKPropertyName.Comment, ""); comment = comment + line.Substring(1).Trim(); m.SetProperty(CDKPropertyName.Comment, comment); Debug.WriteLine($"Found and set comment: {comment}"); i--; // a comment line does not count as an atom } else { double x = 0.0f, y = 0.0f, z = 0.0f; double charge = 0.0f; var tokenizer = Strings.Tokenize(line, '\t', ' ', ',', ';'); int fields = tokenizer.Count; if (fields < 4) { // this is an error but cannot throw exception } else { string atomtype = tokenizer[0]; x = double.Parse(tokenizer[1], NumberFormatInfo.InvariantInfo); y = double.Parse(tokenizer[2], NumberFormatInfo.InvariantInfo); z = double.Parse(tokenizer[3], NumberFormatInfo.InvariantInfo); if (fields == 8) { charge = double.Parse(tokenizer[4], NumberFormatInfo.InvariantInfo); } IAtom atom = file.Builder.NewAtom(atomtype, new Vector3(x, y, z)); atom.Charge = charge; m.Atoms.Add(atom); } } } setOfMolecules.Add(m); chemModel.MoleculeSet = setOfMolecules; chemSequence.Add(chemModel); line = input.ReadLine(); } file.Add(chemSequence); } catch (IOException e) { // should make some noise now file = null; Trace.TraceError($"Error while reading file: {e.Message}"); Debug.WriteLine(e); } return(file); }
private CMLMolecule CDKAtomContainerToCMLMolecule(IAtomContainer structure, bool setIDs, bool isRef) { var cmlMolecule = new CMLMolecule(); if (useCMLIDs && setIDs) { IDCreator.CreateIDs(structure); } this.CheckPrefix(cmlMolecule); if (!string.IsNullOrEmpty(structure.Id)) { if (!isRef) { cmlMolecule.Id = structure.Id; } else { cmlMolecule.Ref = structure.Id; } } if (structure.Title != null) { cmlMolecule.Title = structure.Title; } if (structure.GetProperty <string>(CDKPropertyName.InChI) != null) { var ident = new CMLIdentifier { Convention = "iupac:inchi" }; ident.SetAttributeValue(CMLElement.Attribute_value, structure.GetProperty <string>(CDKPropertyName.InChI)); cmlMolecule.Add(ident); } if (!isRef) { for (int i = 0; i < structure.Atoms.Count; i++) { var cdkAtom = structure.Atoms[i]; var cmlAtom = CDKAtomToCMLAtom(structure, cdkAtom); if (structure.GetConnectedSingleElectrons(cdkAtom).Count() > 0) { cmlAtom.SpinMultiplicity = structure.GetConnectedSingleElectrons(cdkAtom).Count() + 1; } cmlMolecule.Add(cmlAtom); } for (int i = 0; i < structure.Bonds.Count; i++) { var cmlBond = CDKJBondToCMLBond(structure.Bonds[i]); cmlMolecule.Add(cmlBond); } } // ok, output molecular properties, but not TITLE, INCHI, or DictRef's var props = structure.GetProperties(); foreach (var propKey in props.Keys) { if (propKey is string key) { // but only if a string if (!isRef) { object value = props[key]; switch (key) { case CDKPropertyName.Title: case CDKPropertyName.InChI: break; default: // ok, should output this var scalar = new CMLScalar(); this.CheckPrefix(scalar); scalar.DictRef = "cdk:molecularProperty"; scalar.Title = (string)key; scalar.SetValue(value.ToString()); cmlMolecule.Add(scalar); break; } } // FIXME: At the moment the order writing the formula is into properties // but it should be that IMolecularFormula is a extension of IAtomContainer if (!isRef && string.Equals(key, CDKPropertyName.Formula, StringComparison.Ordinal)) { switch (props[key]) { case IMolecularFormula cdkFormula: { var cmlFormula = new CMLFormula(); var isotopesList = MolecularFormulaManipulator.PutInOrder(MolecularFormulaManipulator.OrderEle, cdkFormula); foreach (var isotope in isotopesList) { cmlFormula.Add(isotope.Symbol, cdkFormula.GetCount(isotope)); } cmlMolecule.Add(cmlFormula); } break; case IMolecularFormulaSet cdkFormulaSet: foreach (var cdkFormula in cdkFormulaSet) { var isotopesList = MolecularFormulaManipulator.PutInOrder(MolecularFormulaManipulator.OrderEle, cdkFormula); var cmlFormula = new CMLFormula { DictRef = "cdk:possibleMachts" }; foreach (var isotope in isotopesList) { cmlFormula.Add(isotope.Symbol, cdkFormula.GetCount(isotope)); } cmlMolecule.Add(cmlFormula); } break; } } } } foreach (var element in customizers.Keys) { var customizer = customizers[element]; try { customizer.Customize(structure, cmlMolecule); } catch (Exception exception) { Trace.TraceError($"Error while customizing CML output with customizer: {customizer.GetType().Name}"); Debug.WriteLine(exception); } } return(cmlMolecule); }