private SdfState ReadCtabFooter(StreamReader reader) { SdfState result = SdfState.Error; while (!reader.EndOfStream) { string line = SdFileConverter.GetNextLine(reader); if (!string.IsNullOrEmpty(line)) { if (line.StartsWith(MDLConstants.M_CHG) || line.StartsWith(MDLConstants.M_ISO) || line.StartsWith(MDLConstants.M_RAD)) { ReadAtomPropertyLine(line); } if (line.Equals(MDLConstants.M_END)) { result = SdfState.EndOfCtab; break; } } } return(result); }
public override SdfState ImportFromStream(StreamReader reader, Molecule molecule, out string message) { message = null; _molecule = molecule; SdfState result = SdfState.Null; try { bool isFormula = false; string internalName = ""; while (!reader.EndOfStream) { string line = SdFileConverter.GetNextLine(reader); //reader.ReadLine();; if (!string.IsNullOrEmpty(line)) { if (line.Equals(MDLConstants.SDF_END)) { // End of SDF Section result = SdfState.EndOfData; break; } if (line.StartsWith(">")) { // Clear existing Property Name internalName = string.Empty; // See if we can find the property in our translation table foreach (var property in _propertyTypes) { if (line.Equals(property.ExternalName)) { isFormula = property.IsFormula; internalName = property.InternalName; break; } } } else { // Property Data if (!string.IsNullOrEmpty(internalName)) { if (isFormula) { var formula = new TextualProperty(); formula.FullType = internalName; formula.Value = line; _molecule.Formulas.Add(formula); } else { var name = new TextualProperty(); name.FullType = internalName; name.Value = line; _molecule.Names.Add(name); } } } } else { internalName = string.Empty; } } } catch (System.Exception ex) { Debug.WriteLine(ex.Message); result = SdfState.Error; } return(result); }
private MDLCounts ReadCtabHeader(StreamReader reader) { MDLCounts result = new MDLCounts(); // Read Line #1 - Title string title = SdFileConverter.GetNextLine(reader); if (!string.IsNullOrEmpty(title)) { if (title.ToUpper().StartsWith("$MDL")) { _molecule.Errors.Add("RGFiles are currently not supported"); throw new InvalidDataException("RGFiles are currently not supported"); } if (title.ToUpper().StartsWith("$RXN")) { _molecule.Errors.Add("RXNFiles are currently not supported"); throw new InvalidDataException("RXNFiles are currently not supported"); } if (title.ToUpper().StartsWith("$RDFILE")) { _molecule.Errors.Add("RDFiles are currently not supported"); throw new InvalidDataException("RDFiles are currently not supported"); } if (title.ToUpper().StartsWith("<XDFILE>")) { _molecule.Errors.Add("XDFiles are currently not supported"); throw new InvalidDataException("XDFiles are currently not supported"); } } // Read and discard Line #2 - Header SdFileConverter.GetNextLine(reader); // Read and discard Line #3 - Comment SdFileConverter.GetNextLine(reader); // Read Line #4 - Counts string counts = SdFileConverter.GetNextLine(reader); if (counts.ToLower().Contains("v2000")) { try { result.Atoms = ParseInteger(counts, 0, 3); result.Bonds = ParseInteger(counts, 3, 3); result.Version = GetSubString(counts, 34, 5).ToUpper(); } catch (Exception ex) { _molecule.Errors.Add($"Exception {ex.Message}"); result.Message = $"Exception {ex.Message}"; Debug.WriteLine(ex.Message); } } else { result.Message = "Line containing atom and bond counts not found!"; } return(result); }
private void ReadBonds(StreamReader reader, int bonds) { int idx = 0; while (!reader.EndOfStream && idx < bonds) { string line = SdFileConverter.GetNextLine(reader); if (!string.IsNullOrEmpty(line)) { // create bond int atomNumber1 = ParseInteger(line, 0, 3); Atom atom1 = atomByNumber[atomNumber1]; if (atom1 == null) { _molecule.Warnings.Add($"Cannot resolve atomNumber {atomNumber1} at line {SdFileConverter.LineNumber}"); _molecule.Warnings.Add($"{line}"); } int atomNumber2 = ParseInteger(line, 3, 3); Atom atom2 = atomByNumber[atomNumber2]; if (atom2 == null) { _molecule.Warnings.Add($"Cannot resolve atomNumber {atomNumber2} at line {SdFileConverter.LineNumber}"); _molecule.Warnings.Add($"{line}"); } idx++; Bond thisBond = new Bond(); thisBond.StartAtomInternalId = atom1?.InternalId; thisBond.EndAtomInternalId = atom2?.InternalId; // Bond Order string order = GetSubString(line, 6, 3); if (!string.IsNullOrEmpty(order)) { int bondOrder = ParseInteger(order); if (bondOrder <= 4) { thisBond.Order = BondOrder(bondOrder); } else { thisBond.Order = BondOrder(bondOrder); _molecule.Warnings.Add($"Unsupported Bond Type of {order} at Line {SdFileConverter.LineNumber}"); } } // stereo string stereo = GetSubString(line, 9, 3); if (!string.IsNullOrEmpty(stereo)) { thisBond.Stereo = BondStereoFromMolfile(ParseInteger(stereo)); } // add bond to molecule _molecule.AddBond(thisBond); thisBond.Parent = _molecule; bondByNumber.Add(idx, thisBond); } } }
private void ReadAtoms(StreamReader reader, int atoms) { int idx = 0; while (!reader.EndOfStream && idx < atoms) { string line = SdFileConverter.GetNextLine(reader); if (!string.IsNullOrEmpty(line)) { // create atom Atom thisAtom = new Atom(); double x = Double.Parse(GetSubString(line, 0, 9), CultureInfo.InvariantCulture); double y = Double.Parse(GetSubString(line, 10, 9), CultureInfo.InvariantCulture); double z = Double.Parse(GetSubString(line, 20, 9), CultureInfo.InvariantCulture); // Inverting Y co-ordinate to make it the right way up. thisAtom.Position = new Point(x, 0 - y); // element type string elType = GetSubString(line, 31, 3); ElementBase eb; var ok = AtomHelpers.TryParse(elType, out eb); if (ok) { if (eb is Element element) { thisAtom.Element = element; } if (eb is FunctionalGroup functionalGroup) { thisAtom.Element = functionalGroup; // Fix Invalid data; Force internal FG to prime Element if (functionalGroup.Internal) { AtomHelpers.TryParse(functionalGroup.Components[0].Component, out eb); if (eb is Element chemicalElement) { thisAtom.Element = chemicalElement; } } } } else { _molecule.Errors.Add($"{elType} at Line {SdFileConverter.LineNumber} is not a valid Element"); _molecule.Errors.Add($"{line}"); } // isotope int delta = ParseInteger(line, 34, 2); if (delta != 0) { thisAtom.IsotopeNumber = delta; } // charge int ch = ParseInteger(line, 36, 3); thisAtom.FormalCharge = FormalChargeFromMolfile(ch); thisAtom.DoubletRadical = DoubletRadicalFromMolfile(ch); // field 3 is atom parity (a *write-only* field, so not used) // int parity = ParseInteger(line, 39, 3) // field 4 hydrogen count // int hCount = ParseInteger(line, 42, 3) // field 5 stereoCareBox // int field5 = ParseInteger(line, 45, 3) // field 6 valency/oxidation state // int oxState = ParseInteger(line, 48, 3) // field 7 H0 designator // int hZero = ParseInteger(line, 51, 3) // atom-atom mapping int atomMap = ParseInteger(line, 60, 3); if (atomMap != 0) { // ToDo: What to do here ??? } // inversion/retention flag // int hZero = ParseInteger(line, 63, 3) // exact change flag // int hZero = ParseInteger(line, 66, 3) idx++; // Add atom to molecule thisAtom.Id = $"a{idx}"; _molecule.AddAtom(thisAtom); thisAtom.Parent = _molecule; atomByNumber.Add(idx, thisAtom); } } }