/// <summary> /// Loads the CML data into the in-memory model /// </summary> /// <param name="data">Object variable containing well-formed and compliant CML</param> /// <returns></returns> public Model Import(object data) { Model newModel = new Model(); if (data != null) { XDocument modelDoc = XDocument.Parse((string)data); var root = modelDoc.Root; // Only import if not null var customXmlPartGuid = CML.GetCustomXmlPartGuid(root); if (customXmlPartGuid != null && !string.IsNullOrEmpty(customXmlPartGuid.Value)) { newModel.CustomXmlPartGuid = customXmlPartGuid.Value; } var moleculeElements = CML.GetMolecules(root); foreach (XElement meElement in moleculeElements) { newModel.Molecules.Add(CreateMolecule(meElement)); } // Can't use RebuildMolecules() as it trashes the formulae and labels //newModel.RebuildMolecules(); newModel.RefreshMolecules(); foreach (Molecule molecule in newModel.Molecules) { molecule.RebuildRings(); // Ensure ConciseFormula has been calculated if (string.IsNullOrEmpty(molecule.ConciseFormula)) { molecule.ConciseFormula = molecule.CalculatedFormula(); } } newModel.Relabel(true); } return(newModel); }
/// <summary> /// Creates a bond from the CML /// </summary> /// <param name="cmlElement"></param> /// <returns></returns> public Bond CreateBond(XElement cmlElement) { Bond newBond = new Bond(); BondDirection?dir = null; var dirAttr = cmlElement.Attribute(CML.c4w + "placement"); if (dirAttr != null) { BondDirection temp; if (Enum.TryParse(dirAttr.Value, out temp)) { dir = temp; } } newBond.Id = cmlElement.Attribute("id")?.Value; newBond.Order = cmlElement.Attribute("order")?.Value; if (dir != null) { newBond.Placement = dir.Value; } var stereoElems = CML.GetStereo(cmlElement); if (stereoElems.Any()) { var stereo = stereoElems[0].Value; switch (stereo) { case "N": newBond.Stereo = BondStereo.None; break; case "W": newBond.Stereo = BondStereo.Wedge; break; case "H": newBond.Stereo = BondStereo.Hatch; break; case "S": newBond.Stereo = BondStereo.Indeterminate; break; case "C": newBond.Stereo = BondStereo.Cis; break; case "T": newBond.Stereo = BondStereo.Trans; break; default: newBond.Stereo = BondStereo.None; break; } } return(newBond); }
/// <summary> /// Creates a molecule from a CML representation /// </summary> /// <param name="cmlElement">CML containing the molecule representation</param> /// <returns>Molecule object</returns> private Molecule CreateMolecule(XElement cmlElement) { var m = new Molecule(); m.Id = cmlElement.Attribute("id")?.Value; var childMolecules = CML.GetMolecules(cmlElement); var atomElements = CML.GetAtoms(cmlElement); var bondElements = CML.GetBonds(cmlElement); var nameElements = GetNames(cmlElement); var formulaElements = GetFormulas(cmlElement); Dictionary <string, Atom> newAtoms = new Dictionary <string, Atom>(); foreach (XElement childElement in childMolecules) { var newMol = CreateMolecule(childElement); m.Molecules.Add(newMol); } foreach (XElement atomElement in atomElements) { var newAtom = CreateAtom(atomElement); newAtoms[newAtom.Id] = newAtom; //store the reference to help us build bonds m.Atoms.Add(newAtom); } foreach (XElement bondElement in bondElements) { var newBond = CreateBond(bondElement); string[] atomRefs = bondElement.Attribute("atomRefs2")?.Value.Split(' '); if (atomRefs?.Length == 2) { newBond.StartAtom = newAtoms[atomRefs[0]]; newBond.EndAtom = newAtoms[atomRefs[1]]; m.Bonds.Add(newBond); } } foreach (XElement nameElement in nameElements) { var newName = XmlToName(nameElement); m.ChemicalNames.Add(newName); } foreach (XElement formulaElement in formulaElements) { // Only import Concise Once if (string.IsNullOrEmpty(m.ConciseFormula)) { m.ConciseFormula = XmlToConsiseFormula(formulaElement); } var formula = XmlToFormula(formulaElement); if (formula.IsValid) { m.Formulas.Add(formula); } } return(m); }
/// <summary> /// Creates a molecule from a CML representation /// </summary> /// <param name="cmlElement">CML containing the molecule representation</param> /// <returns>Molecule object</returns> private Molecule CreateMolecule(XElement cmlElement) { var m = new Molecule(); m.Id = cmlElement.Attribute("id")?.Value; var childMolecules = CML.GetMolecules(cmlElement); var atomElements = CML.GetAtoms(cmlElement); var bondElements = CML.GetBonds(cmlElement); var nameElements = GetNames(cmlElement); var formulaElements = GetFormulas(cmlElement); Dictionary <string, Atom> newAtoms = new Dictionary <string, Atom>(); foreach (XElement childElement in childMolecules) { var newMol = CreateMolecule(childElement); m.Molecules.Add(newMol); } foreach (XElement atomElement in atomElements) { List <string> messages = new List <string>(); var newAtom = CreateAtom(atomElement, out messages); if (messages.Count > 0) { m.Errors.AddRange(messages); } if (newAtom != null) { newAtoms[newAtom.Id] = newAtom; //store the reference to help us build bonds m.Atoms.Add(newAtom); } } foreach (XElement bondElement in bondElements) { string message = ""; var newBond = CreateBond(bondElement, out message); if (!string.IsNullOrEmpty(message)) { m.Errors.Add(message); } string[] atomRefs = bondElement.Attribute("atomRefs2")?.Value.Split(' '); if (atomRefs?.Length == 2) { Atom startAtom = null; if (newAtoms.ContainsKey(atomRefs[0])) { startAtom = newAtoms[atomRefs[0]]; } else { m.Errors.Add($"Can't find atom '{atomRefs[0]}' of {bondElement}"); } Atom endAtom = null; if (newAtoms.ContainsKey(atomRefs[1])) { endAtom = newAtoms[atomRefs[1]]; } else { m.Errors.Add($"Can't find atom '{atomRefs[1]}' of {bondElement}"); } if (startAtom != null && endAtom != null) { newBond.StartAtom = startAtom; newBond.EndAtom = endAtom; m.Bonds.Add(newBond); } } } foreach (XElement nameElement in nameElements) { var newName = XmlToName(nameElement); m.ChemicalNames.Add(newName); } foreach (XElement formulaElement in formulaElements) { // Only import Concise Once if (string.IsNullOrEmpty(m.ConciseFormula)) { m.ConciseFormula = XmlToConsiseFormula(formulaElement); } var formula = XmlToFormula(formulaElement); if (formula.IsValid) { m.Formulas.Add(formula); } } return(m); }