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 MMFF Symbolic atom types. The symbolic type can be accessed with /// <see cref="IAtomType.AtomTypeName"/>. An atom of unknown type is assigned the /// symbolic type <c>"UNK"</c>. /// All atoms, including hydrogens must be explicitly represented. /// </summary> /// <param name="mol">molecule</param> /// <returns>all atoms had a type assigned</returns> public virtual bool AssignAtomTypes(IAtomContainer mol) { // preconditions need explicit hydrogens foreach (var atom in mol.Atoms) { if (atom.ImplicitHydrogenCount == null || atom.ImplicitHydrogenCount > 0) { throw new ArgumentException("Hydrogens must be explicit nodes, each must have a zero (non-null) impl H count."); } } // conversion to faster data structures var edgeMap = EdgeToBondMap.WithSpaceFor(mol); var adjList = GraphUtil.ToAdjList(mol, edgeMap); mol.SetProperty(MMFF_ADJLIST_CACHE, adjList); mol.SetProperty(MMFF_EDGEMAP_CACHE, edgeMap); var aromBonds = new HashSet <IBond>(); var oldArom = GetAromatics(mol); // note: for MMFF we need to remove current aromatic flags for type // assignment (they are restored after) foreach (var chemObj in oldArom) { chemObj.IsAromatic = false; } var atomTypes = mmffAtomTyper.SymbolicTypes(mol, adjList, edgeMap, aromBonds); bool hasUnkType = false; for (int i = 0; i < mol.Atoms.Count; i++) { if (atomTypes[i] == null) { mol.Atoms[i].AtomTypeName = "UNK"; hasUnkType = true; } else { mol.Atoms[i].AtomTypeName = atomTypes[i]; } } // restore aromatic flags and mark the MMFF aromatic bonds foreach (var chemObj in oldArom) { chemObj.IsAromatic = true; } foreach (var bond in aromBonds) { bond.SetProperty(MMFF_AROM, true); } return(!hasUnkType); }
public void TestPropertyOutput_none() { IAtomContainer adenine = TestMoleculeFactory.MakeAdenine(); StringWriter sw = new StringWriter(); SDFWriter sdf = new SDFWriter(sw, Array.Empty <string>()); adenine.SetProperty("one", "a"); adenine.SetProperty("two", "b"); sdf.Write(adenine); sdf.Close(); string output = sw.ToString(); Assert.IsFalse(output.Contains("> <two>")); Assert.IsFalse(output.Contains("> <one>")); }
public IAtomContainer ParseMolecule(XElement parser, IChemObjectBuilder builder) { IAtomContainer molecule = builder.NewAtomContainer(); // assume the current element is PC-Compound if (!parser.Name.Equals(Name_EL_PCCOMPOUND)) { return(null); } foreach (var elm in parser.Descendants(Name_EL_ATOMBLOCK)) { ParserAtomBlock(elm, molecule); } foreach (var elm in parser.Descendants(Name_EL_BONDBLOCK)) { ParserBondBlock(elm, molecule); } foreach (var elm in parser.Descendants(Name_EL_COORDINATESBLOCK)) { ParserCoordBlock(elm, molecule); } foreach (var elm in parser.Descendants(Name_EL_PROPS_INFODATA)) { ParserCompoundInfoData(elm, molecule); } foreach (var elm in parser.Descendants(Name_EL_PCCOMPOUND_ID)) { string cid = GetCID(elm); molecule.SetProperty("PubChem CID", cid); } return(molecule); }
/// <summary> /// </summary> /// <returns>Last line read</returns> /// <exception cref="CDKException">when no file content is detected</exception> public string ReadHeader(IAtomContainer readData) { // read four lines var line1 = ReadLine(); if (line1 == null) { throw new CDKException("Expected a header line, but found nothing."); } if (line1.Length > 0) { if (line1.StartsWith("M V30", StringComparison.Ordinal)) { // no header return(line1); } readData.Title = line1; } ReadLine(); var line3 = ReadLine(); if (line3.Length > 0) { readData.SetProperty(CDKPropertyName.Comment, line3); } var line4 = ReadLine(); if (!line4.Contains("3000")) { throw new CDKException("This file is not a MDL V3000 molfile."); } return(ReadLine()); }
private static void MakeReferencesExplicitForMolecule(IAtomContainer molecule) { int selfCounter = 0; molecule.SetProperty(prefix + ":self:" + selfCounter++, "chemical:molecularEntity"); // remark: this is not strictly true... the Compendium includes the ion // pair, which normally would not considered a CDK molecule }
void Main() { IAtomContainer query = null; IAtomContainer someTarget = null; Pattern somePattern = null; int[] grouping = null; #region // grouping is actually set by SMARTS parser but this shows how it's stored query.SetProperty(ComponentFilter.Key, grouping); IAtomContainer target = someTarget; Pattern pattern = somePattern; // create pattern for query // filter for mappings which respect component grouping in the query var filter = new ComponentFilter(query, target); pattern.MatchAll(target).Where(filter.Apply); #endregion }
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])); } }
/// <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 static void ParserCompoundInfoData(XElement parser, IAtomContainer molecule) { string urnLabel = null; string urnName = null; string sval = null; if (!Name_EL_PROPS_INFODATA.Equals(parser.Name)) { return; } foreach (var elm in parser.Descendants()) { if (Name_EL_PROPS_URNNAME.Equals(elm.Name)) { urnName = elm.Value; } else if (Name_EL_PROPS_URNLABEL.Equals(elm.Name)) { urnLabel = elm.Value; } else if (Name_EL_PROPS_SVAL.Equals(elm.Name)) { sval = elm.Value; } else if (Name_EL_PROPS_FVAL.Equals(elm.Name)) { sval = elm.Value; } else if (Name_EL_PROPS_BVAL.Equals(elm.Name)) { sval = elm.Value; } } if (urnLabel != null & sval != null) { string property = urnLabel + (urnName == null ? "" : " (" + urnName + ")"); molecule.SetProperty(property, sval); } }
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); } }
public static void SetCtabSgroups(this IAtomContainer o, IList <Sgroup> chirality) => o.SetProperty(CtabSgroupsPropertyKey, chirality);
/// <summary> /// Read a Molecule from a file in MDL sd format /// </summary> /// <returns>The Molecule that was read from the MDL file.</returns> private IAtomContainer ReadMolecule(IAtomContainer molecule) { Debug.WriteLine("Reading new molecule"); int linecount = 0; int atoms = 0; int bonds = 0; int atom1 = 0; int atom2 = 0; int order = 0; BondStereo stereo = BondStereo.None; int RGroupCounter = 1; int Rnumber = 0; double x = 0.0; double y = 0.0; double z = 0.0; double totalX = 0.0; double totalY = 0.0; double totalZ = 0.0; //int[][] conMat = Array.Empty<int>()[0]; //string help; IAtom atom; string line = ""; try { var isotopeFactory = CDK.IsotopeFactory; Trace.TraceInformation("Reading header"); line = input.ReadLine(); linecount++; if (line == null) { return(null); } Debug.WriteLine("Line " + linecount + ": " + line); if (line.StartsWith("$$$$", StringComparison.Ordinal)) { Debug.WriteLine("File is empty, returning empty molecule"); return(molecule); } if (line.Length > 0) { molecule.Title = line; } line = input.ReadLine(); linecount++; Debug.WriteLine("Line " + linecount + ": " + line); line = input.ReadLine(); linecount++; Debug.WriteLine("Line " + linecount + ": " + line); if (line.Length > 0) { molecule.SetProperty(CDKPropertyName.Remark, line); } Trace.TraceInformation("Reading rest of file"); line = input.ReadLine(); linecount++; Debug.WriteLine("Line " + linecount + ": " + line); if (ReaderMode == ChemObjectReaderMode.Strict) { if (line.Contains("V2000") || line.Contains("v2000")) { throw new CDKException("This file must be read with the MDLV2000Reader."); } if (line.Contains("V3000") || line.Contains("v3000")) { throw new CDKException("This file must be read with the MDLV3000Reader."); } } atoms = int.Parse(Strings.Substring(line, 0, 3).Trim(), NumberFormatInfo.InvariantInfo); Debug.WriteLine($"Atomcount: {atoms}"); bonds = int.Parse(Strings.Substring(line, 3, 3).Trim(), NumberFormatInfo.InvariantInfo); Debug.WriteLine($"Bondcount: {bonds}"); // read ATOM block Trace.TraceInformation("Reading atom block"); for (int f = 0; f < atoms; f++) { line = input.ReadLine(); linecount++; var trailingSpaceMatcher = TRAILING_SPACE.Match(line); if (trailingSpaceMatcher.Success) { HandleError("Trailing space found", linecount, trailingSpaceMatcher.Index, trailingSpaceMatcher.Index + trailingSpaceMatcher.Length); line = Strings.Substring(line, 0, trailingSpaceMatcher.Index); } x = double.Parse(Strings.Substring(line, 0, 10).Trim(), NumberFormatInfo.InvariantInfo); y = double.Parse(Strings.Substring(line, 10, 10).Trim(), NumberFormatInfo.InvariantInfo); z = double.Parse(Strings.Substring(line, 20, 10).Trim(), NumberFormatInfo.InvariantInfo); // *all* values should be zero, not just the sum totalX += Math.Abs(x); totalY += Math.Abs(y); totalZ += Math.Abs(z); Debug.WriteLine("Coordinates: " + x + "; " + y + "; " + z); string element = Strings.Substring(line, 31, 3).Trim(); if (line.Length < 34) { HandleError("Element atom type does not follow V2000 format type should of length three" + " and padded with space if required", linecount, 31, 34); } Debug.WriteLine($"Atom type: {element}"); if (isotopeFactory.IsElement(element)) { atom = isotopeFactory.Configure(molecule.Builder.NewAtom(element)); } else if (string.Equals("A", element, StringComparison.Ordinal)) { atom = molecule.Builder.NewPseudoAtom(element); } else if (string.Equals("Q", element, StringComparison.Ordinal)) { atom = molecule.Builder.NewPseudoAtom(element); } else if (string.Equals("*", element, StringComparison.Ordinal)) { atom = molecule.Builder.NewPseudoAtom(element); } else if (string.Equals("LP", element, StringComparison.Ordinal)) { atom = molecule.Builder.NewPseudoAtom(element); } else if (string.Equals("L", element, StringComparison.Ordinal)) { atom = molecule.Builder.NewPseudoAtom(element); } else if (element.Length > 0 && element[0] == 'R') { Debug.WriteLine("Atom ", element, " is not an regular element. Creating a PseudoAtom."); //check if the element is R string rn = element.Substring(1); if (int.TryParse(rn, out Rnumber)) { RGroupCounter = Rnumber; } else { Rnumber = RGroupCounter; RGroupCounter++; } element = "R" + Rnumber; atom = molecule.Builder.NewPseudoAtom(element); } else { if (ReaderMode == ChemObjectReaderMode.Strict) { throw new CDKException( "Invalid element type. Must be an existing element, or one in: A, Q, L, LP, *."); } atom = molecule.Builder.NewPseudoAtom(element); } // store as 3D for now, convert to 2D (if totalZ == 0.0) later atom.Point3D = new Vector3(x, y, z); // parse further fields if (line.Length >= 36) { string massDiffString = Strings.Substring(line, 34, 2).Trim(); Debug.WriteLine($"Mass difference: {massDiffString}"); if (!(atom is IPseudoAtom)) { try { int massDiff = int.Parse(massDiffString, NumberFormatInfo.InvariantInfo); if (massDiff != 0) { var major = CDK.IsotopeFactory.GetMajorIsotope(element); atom.AtomicNumber = major.AtomicNumber + massDiff; } } catch (Exception exception) { if (!(exception is FormatException || exception is IOException)) { throw; } Trace.TraceError("Could not parse mass difference field"); } } else { Trace.TraceError("Cannot set mass difference for a non-element!"); } } else { HandleError("Mass difference is missing", linecount, 34, 36); } if (line.Length >= 39) { string chargeCodeString = Strings.Substring(line, 36, 3).Trim(); Debug.WriteLine($"Atom charge code: {chargeCodeString}"); int chargeCode = int.Parse(chargeCodeString, NumberFormatInfo.InvariantInfo); if (chargeCode == 0) { // uncharged species } else if (chargeCode == 1) { atom.FormalCharge = +3; } else if (chargeCode == 2) { atom.FormalCharge = +2; } else if (chargeCode == 3) { atom.FormalCharge = +1; } else if (chargeCode == 4) { } else if (chargeCode == 5) { atom.FormalCharge = -1; } else if (chargeCode == 6) { atom.FormalCharge = -2; } else if (chargeCode == 7) { atom.FormalCharge = -3; } } else { HandleError("Atom charge count is empty", linecount, 35, 39); } if (line.Length >= 64) { // read the mmm field as position 61-63 string reactionAtomIDString = Strings.Substring(line, 60, 3).Trim(); Debug.WriteLine($"Parsing mapping id: {reactionAtomIDString}"); try { int reactionAtomID = int.Parse(reactionAtomIDString, NumberFormatInfo.InvariantInfo); if (reactionAtomID != 0) { atom.SetProperty(CDKPropertyName.AtomAtomMapping, reactionAtomID); } } catch (Exception exception) { Trace.TraceError("Mapping number ", reactionAtomIDString, " is not an integer."); Debug.WriteLine(exception); } } //shk3: This reads shifts from after the molecule. I don't think this is an official format, but I saw it frequently 80=>78 for alk if (line.Length >= 78) { double shift = double.Parse(Strings.Substring(line, 69, 11).Trim(), NumberFormatInfo.InvariantInfo); atom.SetProperty("first shift", shift); } if (line.Length >= 87) { double shift = double.Parse(Strings.Substring(line, 79, 8).Trim(), NumberFormatInfo.InvariantInfo); atom.SetProperty("second shift", shift); } molecule.Atoms.Add(atom); } // convert to 2D, if totalZ == 0 if (totalX == 0.0 && totalY == 0.0 && totalZ == 0.0) { Trace.TraceInformation("All coordinates are 0.0"); foreach (var atomToUpdate in molecule.Atoms) { atomToUpdate.Point3D = null; } } else if (totalZ == 0.0 && !forceReadAs3DCoords.IsSet) { Trace.TraceInformation("Total 3D Z is 0.0, interpreting it as a 2D structure"); IEnumerator <IAtom> atomsToUpdate = molecule.Atoms.GetEnumerator(); while (atomsToUpdate.MoveNext()) { IAtom atomToUpdate = (IAtom)atomsToUpdate.Current; Vector3?p3d = atomToUpdate.Point3D; atomToUpdate.Point2D = new Vector2(p3d.Value.X, p3d.Value.Y); atomToUpdate.Point3D = null; } } // read BOND block Trace.TraceInformation("Reading bond block"); for (int f = 0; f < bonds; f++) { line = input.ReadLine(); linecount++; atom1 = int.Parse(Strings.Substring(line, 0, 3).Trim(), NumberFormatInfo.InvariantInfo); atom2 = int.Parse(Strings.Substring(line, 3, 3).Trim(), NumberFormatInfo.InvariantInfo); order = int.Parse(Strings.Substring(line, 6, 3).Trim(), NumberFormatInfo.InvariantInfo); if (line.Length > 12) { int mdlStereo = int.Parse(Strings.Substring(line, 9, 3).Trim(), NumberFormatInfo.InvariantInfo); if (mdlStereo == 1) { // MDL up bond stereo = BondStereo.Up; } else if (mdlStereo == 6) { // MDL down bond stereo = BondStereo.Down; } else if (mdlStereo == 0) { // bond has no stereochemistry stereo = BondStereo.None; } else if (mdlStereo == 4) { //MDL up or down bond stereo = BondStereo.UpOrDown; } else if (mdlStereo == 3) { //MDL e or z undefined stereo = BondStereo.EOrZ; } } else { Trace.TraceWarning("Missing expected stereo field at line: " + line); } Debug.WriteLine("Bond: " + atom1 + " - " + atom2 + "; order " + order); // interpret CTfile's special bond orders IAtom a1 = molecule.Atoms[atom1 - 1]; IAtom a2 = molecule.Atoms[atom2 - 1]; IBond newBond = null; if (order >= 1 && order <= 3) { BondOrder cdkOrder = BondOrder.Single; if (order == 2) { cdkOrder = BondOrder.Double; } if (order == 3) { cdkOrder = BondOrder.Triple; } if (stereo != BondStereo.None) { newBond = molecule.Builder.NewBond(a1, a2, cdkOrder, stereo); } else { newBond = molecule.Builder.NewBond(a1, a2, cdkOrder); } } else if (order == 4) { // aromatic bond if (stereo != BondStereo.None) { newBond = molecule.Builder.NewBond(a1, a2, BondOrder.Single, stereo); } else { newBond = molecule.Builder.NewBond(a1, a2, BondOrder.Single); } // mark both atoms and the bond as aromatic newBond.IsAromatic = true; a1.IsAromatic = true; a2.IsAromatic = true; } molecule.Bonds.Add(newBond); } } catch (Exception exception) { if (!(exception is IOException | exception is CDKException | exception is ArgumentException)) { throw; } string error = "Error while parsing line " + linecount + ": " + line + " -> " + exception.Message; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } return(molecule); }
/// <summary> /// Read a ChemFile from a file in MDL SDF format. /// </summary> /// <returns>The ChemFile that was read from the MDL file.</returns> private IChemFile ReadChemFile(IChemFile chemFile) { IChemSequence chemSequence = chemFile.Builder.NewChemSequence(); IChemModel chemModel = chemFile.Builder.NewChemModel(); IChemObjectSet <IAtomContainer> setOfMolecules = chemFile.Builder.NewAtomContainerSet(); IAtomContainer m = ReadMolecule(chemFile.Builder.NewAtomContainer()); if (m != null) { setOfMolecules.Add(m); } chemModel.MoleculeSet = setOfMolecules; chemSequence.Add(chemModel); setOfMolecules = chemFile.Builder.NewAtomContainerSet(); chemModel = chemFile.Builder.NewChemModel(); string str; try { string line; while ((line = input.ReadLine()) != null) { Debug.WriteLine($"line: {line}"); // apparently, this is a SDF file, continue with // reading mol files str = line; if (string.Equals(line, "M END", StringComparison.Ordinal)) { continue; } if (string.Equals(str, "$$$$", StringComparison.Ordinal)) { m = ReadMolecule(chemFile.Builder.NewAtomContainer()); if (m != null) { setOfMolecules.Add(m); chemModel.MoleculeSet = setOfMolecules; chemSequence.Add(chemModel); setOfMolecules = chemFile.Builder.NewAtomContainerSet(); chemModel = chemFile.Builder.NewChemModel(); } } else { // here the stuff between 'M END' and '$$$$' if (m != null) { // ok, the first lines should start with '>' string fieldName = null; if (str.StartsWith("> ", StringComparison.Ordinal)) { // ok, should extract the field name int index = str.IndexOf('<', 2); if (index != -1) { int index2 = str.Substring(index).IndexOf('>'); if (index2 != -1) { fieldName = str.Substring(index + 1, index2 - 1); } } // end skip all other lines while ((line = input.ReadLine()) != null && line.StartsWithChar('>')) { Debug.WriteLine($"data header line: {line}"); } } if (line == null) { throw new CDKException("Expecting data line here, but found null!"); } string data = line; while ((line = input.ReadLine()) != null && line.Trim().Length > 0) { if (string.Equals(line, "$$$$", StringComparison.Ordinal)) { Trace.TraceError($"Expecting data line here, but found end of molecule: {line}"); break; } Debug.WriteLine($"data line: {line}"); data += line; // preserve newlines, unless the line is exactly 80 chars; in that case it // is assumed to continue on the next line. See MDL documentation. if (line.Length < 80) { data += "\n"; } } if (fieldName != null) { Trace.TraceInformation($"fieldName, data: {fieldName}, {data}"); m.SetProperty(fieldName, data); } } } } } catch (CDKException) { throw; } catch (Exception exception) { if (!(exception is IOException || exception is ArgumentException)) { throw; } string error = "Error while parsing SDF"; Trace.TraceError(error); Debug.WriteLine(exception); throw new CDKException(error, exception); } try { input.Close(); } catch (Exception exc) { string error = "Error while closing file: " + exc.Message; Trace.TraceError(error); throw new CDKException(error, exc); } chemFile.Add(chemSequence); return(chemFile); }
// 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); }