Exemple #1
0
        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;
                    }
                }
            }
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        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);
        }
Exemple #5
0
        /// <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());
        }
Exemple #6
0
        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
        }
Exemple #7
0
        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
        }
Exemple #8
0
        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]));
            }
        }
Exemple #9
0
        /// <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);
            }
        }
Exemple #11
0
        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);
            }
        }
Exemple #12
0
 public static void SetCtabSgroups(this IAtomContainer o, IList <Sgroup> chirality)
 => o.SetProperty(CtabSgroupsPropertyKey, chirality);
Exemple #13
0
        /// <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);
        }
Exemple #14
0
        /// <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);
        }
Exemple #15
0
        // 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);
        }