Пример #1
0
        public string Export(Chem4Word.Model.Model model)
        {
            String segment   = "";
            int    atomCount = 0;

            if (model.Molecules.Select(m => m.Bonds.Count).Max() > 999)
            {
                throw new ArgumentOutOfRangeException("Model's bond count exceeds CTAB format limits");
            }

            if (model.Molecules.Select(m => m.Atoms.Count).Max() > 999)
            {
                throw new ArgumentOutOfRangeException("Model's atom count exceeds CTAB format limits");
            }

            int startAtom = 0, endAtom = 0;

            System.Text.StringBuilder SDFileContents = new StringBuilder();
            //However many molecues there are, shove them all in the output
            //Counts line
            //Atom count padded with spaces
            foreach (Molecule molecule in model.Molecules)
            {
                SDFileContents.Append(ExportMolecule(molecule, atomCount));
            }
            return(SDFileContents.ToString());
        }
Пример #2
0
        public Chem4Word.Model.Model Import(object data)
        {
            var jsonModel = JsonConvert.DeserializeObject <ModelJSON>(data as string);

            var newModel = new Chem4Word.Model.Model();

            if (jsonModel.m != null)
            {
                foreach (var molJson in jsonModel.m)
                {
                    AddMolecule(molJson, newModel);
                }
            }
            else
            {
                var jsonMol = JsonConvert.DeserializeObject <MolJSON>(data as string);
                AddMolecule(jsonMol, newModel);
            }

            return(newModel);
        }
Пример #3
0
        public string Export(Chem4Word.Model.Model model)
        {
            XDocument xd   = new XDocument();
            XElement  root = new XElement(CML.cml + "cml",
                                          new XAttribute(XNamespace.Xmlns + "conventions", CML.conventions),
                                          new XAttribute(XNamespace.Xmlns + "cml", CML.cml),
                                          new XAttribute(XNamespace.Xmlns + "cmlDict", CML.cmlDict),
                                          new XAttribute(XNamespace.Xmlns + "nameDict", CML.nameDict),
                                          new XAttribute(XNamespace.Xmlns + "c4w", CML.c4w),
                                          new XAttribute("conventions", "convention:molecular")
                                          );

            // Only export if set
            if (!string.IsNullOrEmpty(model.CustomXmlPartGuid))
            {
                XElement customXmlPartGuid = new XElement(CML.c4w + "customXmlPartGuid", model.CustomXmlPartGuid);
                root.Add(customXmlPartGuid);
            }

            bool relabelRequired = false;

            // Handle case where id's are null
            foreach (Molecule molecule in model.Molecules)
            {
                if (molecule.Id == null)
                {
                    relabelRequired = true;
                    break;
                }

                foreach (Atom atom in molecule.Atoms)
                {
                    if (atom.Id == null)
                    {
                        relabelRequired = true;
                        break;
                    }
                }

                foreach (Bond bond in molecule.Bonds)
                {
                    if (bond.Id == null)
                    {
                        relabelRequired = true;
                        break;
                    }
                }
            }

            if (relabelRequired)
            {
                model.Relabel(false);
            }

            foreach (Molecule molecule in model.Molecules)
            {
                root.Add(GetMoleculeElement(molecule));
            }
            xd.Add(root);

            return(xd.ToString());
        }
Пример #4
0
        public Chem4Word.Model.Model Import(object data)
        {
            string line;
            int    atomsUnread = 0, bondsUnread = 0;
            bool   countsRead = false, endRead = false;
            double minY = 0, maxY = 0;
            bool   firstY = true;

            Chem4Word.Model.Model         newModel    = new Chem4Word.Model.Model();
            Chem4Word.Model.Molecule      newMolecule = new Chem4Word.Model.Molecule();
            Chem4Word.Model.PeriodicTable pt          = new Chem4Word.Model.PeriodicTable();
            //Element ce = new Element();

            Dictionary <string, Chem4Word.Model.Atom> atomsDict = new Dictionary <string, Chem4Word.Model.Atom>();
            Dictionary <string, Chem4Word.Model.Bond> bondsDict = new Dictionary <string, Chem4Word.Model.Bond>();
            int atomNumber = 0, bondNumber = 0;
            int lineNumber = 0;

            using (StringReader reader = new StringReader(data.ToString()))
            {
                while ((line = reader.ReadLine()) != null)
                {
                    if (CountsLine.IsMatch(line))
                    {
                        if (lineNumber == 3)
                        {
                            Match m         = CountsLine.Match(line);
                            var   atomCount = m.Groups["atoms"].Captures[0];
                            var   bondCount = m.Groups["bonds"].Captures[0];
                            int.TryParse(atomCount.ToString(), out atomsUnread);
                            int.TryParse(bondCount.ToString(), out bondsUnread);
                            countsRead = true;
                        }
                        else
                        {
                            throw new FileFormatException("Counts line misplaced");
                        }
                    }
                    else
                    {
                        if (countsRead)
                        {
                            if (AtomLine.IsMatch(line))
                            {
                                Match   m = AtomLine.Match(line);
                                Capture xCoord, yCoord, zCoord, element, isotope = null, charge = null, stereo, hydrogens;
                                //read the atom details
                                xCoord  = m.Groups["x"].Captures[0];
                                yCoord  = m.Groups["y"].Captures[0];
                                zCoord  = m.Groups["z"].Captures[0];          //not used
                                element = m.Groups["element"].Captures[0];
                                if (m.Groups["isotope"].Success)
                                {
                                    isotope = m.Groups["isotope"].Captures[0];
                                }
                                if (m.Groups["charge"].Success)
                                {
                                    charge = m.Groups["charge"].Captures[0];
                                }
                                if (m.Groups["stereo"].Success)
                                {
                                    stereo = m.Groups["stereo"].Captures[0];
                                }
                                if (m.Groups["hydrogens"].Success)
                                {
                                    hydrogens = m.Groups["hydrogens"].Captures[0];
                                }

                                //Create a new atom instance, set its properties and add it to our collection
                                Atom atom = new Atom();
                                atom.Position = Point.Parse($"{xCoord.Value},{yCoord.Value}");

                                //Keep track of the maximum and minimum Y coordinate values so we can invert them later
                                if (firstY)
                                {
                                    minY   = atom.Position.Y;
                                    maxY   = atom.Position.Y;
                                    firstY = false;
                                }
                                else
                                {
                                    if (minY > atom.Position.Y)
                                    {
                                        minY = atom.Position.Y;
                                    }
                                    if (maxY < atom.Position.Y)
                                    {
                                        maxY = atom.Position.Y;
                                    }
                                }

                                atom.Element = Globals.PeriodicTable.Elements[element.ToString().Trim()]; //need to make sure this is the element name

                                //Isotope offset. Do we need to add the most common or default isotope mass to get the right thing here?
                                //CD- leave the isotopes for now;
                                int tempIso = 0;
                                int.TryParse(isotope.ToString(), out tempIso);
                                if (tempIso > 0)
                                {
                                    atom.IsotopeNumber = tempIso;
                                }
                                //it is awkward that we cannot pass the property into TryParse....
                                //we could write a function but then we would need a different one for every type.

                                //Charge
                                int tempCharge = 0;
                                int.TryParse(charge.ToString(), out tempCharge);
                                //Translate the Molfile charge/radical enumeration to atom formal charge and doublet radical properties
                                atom.FormalCharge   = FormalChargeFromMolfile(tempCharge);
                                atom.DoubletRadical = DoubletRadicalFromMolfile(tempCharge);

                                //Stereo - ignore for now??

                                //Hydrogens - ignore for now - saturation property mops this up in the model??

                                //Number the atom by incrementing the previous atom's number, add the atom to the dictionary
                                //keyed using the number converted to a string (why?)
                                atomNumber++;
                                atom.Id = atomNumber.ToString();
                                atomsDict.Add(atom.Id, atom);

                                //decrement the count of atom rows still to be read
                                atomsUnread--;
                            }
                            else
                            {
                                if (atomsUnread == 0)
                                {
                                    if (BondLine.IsMatch(line))
                                    {
                                        Match m = BondLine.Match(line);
                                        //read the bond details
                                        var atom1  = m.Groups["atom1"].Captures[0];
                                        var atom2  = m.Groups["atom2"].Captures[0];
                                        var order  = m.Groups["order"].Captures[0];
                                        var stereo = m.Groups["stereo"].Captures[0];
                                        //var topochain = m.Groups["topochain"].Captures[0];
                                        //var toporing = m.Groups["toporing"].Captures[0];
                                        //parse into object values and add

                                        //Create a new bond instance, set its properties and add it to our collection
                                        Bond bond = new Bond();

                                        //Get start and end atoms, and bond order
                                        int atom1id = 0, atom2id = 0, orderId = 0;
                                        int.TryParse(atom1.ToString(), out atom1id);
                                        int.TryParse(atom2.ToString(), out atom2id);
                                        int.TryParse(order.ToString(), out orderId);

                                        bond.StartAtom = atomsDict[atom1id.ToString()];
                                        bond.EndAtom   = atomsDict[atom2id.ToString()];
                                        bond.Order     = Bond.OrderValueToOrder(orderId);

                                        //bond stereo
                                        int bondStereo = 0;
                                        int.TryParse(stereo.ToString(), out bondStereo);
                                        if (bond.Order == Bond.OrderSingle)
                                        {
                                            bond.Stereo = BondStereoFromMolfile(bondStereo);
                                        }

                                        /* we don't care about this we always use the coordinates I think??
                                         * else
                                         * {
                                         *  if (bond.Order == Enums.BondOrder.Double)
                                         *  {
                                         *      //0 is use x- y- z- coordinates from ataom block to determine Z or E
                                         *      //3 means either Z or E
                                         *  }
                                         * }
                                         */

                                        //So... what about allenes??
                                        //CD - um...err....
                                        //topochain - ignore for now because the ring detection sorts it out??
                                        //CD- Yup
                                        //toporing - ignore for now because the ring detection sorts it out??
                                        //CD- Likewise
                                        //Number the bond by incrementing the previous bond's number, add the bond to the dictionary
                                        //keyed using the number converted to a string (why?)
                                        //CD - you could always try Dictionary<int, Chem4Word.Model.Atom> bondsDict and see what happens
                                        bondNumber++;
                                        bond.Id = bondNumber.ToString();
                                        bondsDict.Add(bond.Id, bond);

                                        //decrement the count of bond rows still to be read
                                        bondsUnread--;
                                    }

                                    //if bonds line
                                } //if all atoms read
                            }     //if atoms line
                        }         //if counts read line
                    }             //if counts line
                    endRead = EndLine.IsMatch(line);
                    if (endRead)
                    {
                        lineNumber = 0;
                        break;
                    }

                    lineNumber++;
                } //while
                  //Values of > 0 for the integer variable atomsUnread or bondsUnread would indicate not enough rows in the molfile.
                  //Values of false for readCounts or endRead would also be bad now we have run out of string
            } //using

            //Check that everything read consistently
            if (!countsRead)
            {
                //What kind of exception do we want to raise, or error to log
                throw new System.FormatException("Counts line missing.");
            }

            if (!endRead)
            {
                //What kind of exception do we want to raise, or error to log
                throw new System.FormatException("End of Molfile line not found.");
            }

            if (atomsUnread != 0)
            {
                //What kind of exception do we want to raise, or error to log
                throw new System.FormatException("Number of atom lines inconsistent with counts line.");
            }

            if (bondsUnread != 0)
            {
                //What kind of exception do we want to raise, or error to log
                throw new System.FormatException("Number of bond lines inconsistent with counts line.");
            }
            if (atomsDict.Count == 0)
            {
                //Something is wrong if there are no atoms. Having no bonds is conceivably intentional.
                throw new System.FormatException("No atoms were read from the Molfile during import.");
            }

            //Sum the minumum and maximum Y coordinates and later subtract each atom's Y coordinate from this value
            double yReversal = minY + maxY;

            //Add all the atoms and bonds to a new molecule, doing this outside the loop that reads them from the file
            Molecule newMol = new Chem4Word.Model.Molecule();

            //Can we really just chuck them in like this or will it fail validation checks??
            foreach (Atom atom in atomsDict.Values)
            {
                //Set the atom's coordinates to the same existing x value, but y subtracted from the sum of the maximum and minumum y values
                atom.Position = Point.Parse($"{atom.Position.X},{yReversal - atom.Position.Y}");

                //Add the atom to the model
                newMol.Atoms.Add(atom);
            }
            foreach (Bond bond in bondsDict.Values)
            {
                newMol.Bonds.Add(bond);
            }
            //Add the molecule to the model
            newModel.Molecules.Add(newMol);

            //Make sure it is valid
            newModel.RebuildMolecules();

            return(newModel);
        }