public void WriteSRUs() { var mol = builder.NewAtomContainer(); mol.Atoms.Add(builder.NewAtom("C")); mol.Atoms.Add(builder.NewAtom("C")); mol.Atoms.Add(builder.NewAtom("O")); mol.Atoms.Add(builder.NewAtom("O")); mol.AddBond(mol.Atoms[0], mol.Atoms[1], BondOrder.Single); mol.AddBond(mol.Atoms[1], mol.Atoms[2], BondOrder.Single); mol.AddBond(mol.Atoms[2], mol.Atoms[3], BondOrder.Single); mol.Atoms[0].ImplicitHydrogenCount = 3; mol.Atoms[1].ImplicitHydrogenCount = 2; mol.Atoms[2].ImplicitHydrogenCount = 0; mol.Atoms[3].ImplicitHydrogenCount = 1; var sgroups = new List <Sgroup>(); Sgroup sgroup = new Sgroup(); sgroup.Atoms.Add(mol.Atoms[1]); sgroup.Atoms.Add(mol.Atoms[2]); sgroup.Bonds.Add(mol.Bonds[0]); sgroup.Bonds.Add(mol.Bonds[2]); sgroup.Type = SgroupType.CtabStructureRepeatUnit; sgroup.Subscript = "n"; sgroup.PutValue(SgroupKey.CtabConnectivity, "HH"); sgroups.Add(sgroup); mol.SetCtabSgroups(sgroups); string res = WriteToStr(mol); Assert.IsTrue(res.Contains("M V30 1 SRU 0 ATOMS=(2 2 3) XBONDS=(2 1 3) LABEL=n CONNECT=HH\n")); }
public void WriteMultipleGroup() { int repeatAtoms = 50; var mol = builder.NewAtomContainer(); mol.Atoms.Add(builder.NewAtom("C")); for (int i = 0; i < repeatAtoms; i++) { mol.Atoms.Add(builder.NewAtom("C")); } mol.Atoms.Add(builder.NewAtom("O")); mol.AddBond(mol.Atoms[0], mol.Atoms[1], BondOrder.Single); for (int i = 0; i < repeatAtoms; i++) { mol.AddBond(mol.Atoms[i + 1], mol.Atoms[i + 2], BondOrder.Single); } mol.Atoms[0].ImplicitHydrogenCount = 3; for (int i = 0; i < repeatAtoms; i++) { mol.Atoms[1 + i].ImplicitHydrogenCount = 2; } mol.Atoms[mol.Atoms.Count - 1].ImplicitHydrogenCount = 1; var sgroups = new List <Sgroup>(); var sgroup = new Sgroup(); for (int i = 0; i < repeatAtoms; i++) { sgroup.Atoms.Add(mol.Atoms[i + 1]); } sgroup.Bonds.Add(mol.Bonds[0]); sgroup.Bonds.Add(mol.Bonds[mol.Bonds.Count - 1]); sgroup.PutValue(SgroupKey.CtabParentAtomList, new[] { mol.Atoms[1] }); sgroup.Type = SgroupType.CtabMultipleGroup; sgroup.Subscript = repeatAtoms.ToString(); sgroups.Add(sgroup); mol.SetCtabSgroups(sgroups); var res = WriteToStr(mol); Assert.IsTrue(res.Contains("M V30 1 MUL 0 ATOMS=(50 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 2-\n" + "M V30 2 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 -\n" + "M V30 46 47 48 49 50 51) XBONDS=(2 1 51) MULT=50 PATOMS=(1 2)\n")); }
/// <summary> /// Transfers the CXSMILES state onto the CDK atom/molecule data-structures. /// </summary> /// <param name="bldr">chem-object builder</param> /// <param name="atoms">atoms parsed from the molecule or reaction. Reaction molecules are list left to right.</param> /// <param name="atomToMol">look-up of atoms to molecules when connectivity/sgroups need modification</param> /// <param name="cxstate">the CXSMILES state to read from</param> private void AssignCxSmilesInfo(IChemObjectBuilder bldr, IChemObject chemObj, List <IAtom> atoms, Dictionary <IAtom, IAtomContainer> atomToMol, CxSmilesState cxstate) { // atom-labels - must be done first as we replace atoms if (cxstate.atomLabels != null) { foreach (var e in cxstate.atomLabels) { // bounds check if (e.Key >= atoms.Count) { continue; } var old = atoms[e.Key]; var pseudo = bldr.NewPseudoAtom(); var val = e.Value; // specialised label handling if (val.EndsWith("_p", StringComparison.Ordinal)) // pseudo label { val = val.Substring(0, val.Length - 2); } else if (val.StartsWith("_AP", StringComparison.Ordinal)) // attachment point { pseudo.AttachPointNum = ParseIntSafe(val.Substring(3)); } pseudo.Label = val; pseudo.AtomicNumber = 0; pseudo.ImplicitHydrogenCount = 0; var mol = atomToMol[old]; AtomContainerManipulator.ReplaceAtomByAtom(mol, old, pseudo); atomToMol.Add(pseudo, mol); atoms[e.Key] = pseudo; } } // atom-values - set as comment, mirrors Molfile reading behavior if (cxstate.atomValues != null) { foreach (var e in cxstate.atomValues) { atoms[e.Key].SetProperty(CDKPropertyName.Comment, e.Value); } } // atom-coordinates if (cxstate.atomCoords != null) { var numAtoms = atoms.Count; var numCoords = cxstate.atomCoords.Count; var lim = Math.Min(numAtoms, numCoords); if (cxstate.coordFlag) { for (int i = 0; i < lim; i++) { atoms[i].Point3D = new Vector3( cxstate.atomCoords[i][0], cxstate.atomCoords[i][1], cxstate.atomCoords[i][2]); } } else { for (int i = 0; i < lim; i++) { atoms[i].Point2D = new Vector2( cxstate.atomCoords[i][0], cxstate.atomCoords[i][1]); } } } // atom radicals if (cxstate.atomRads != null) { foreach (var e in cxstate.atomRads) { // bounds check if (e.Key >= atoms.Count) { continue; } int count = 0; var aa = e.Value; switch (e.Value) { case CxSmilesState.Radical.Monovalent: count = 1; break; // no distinction in CDK between singled/triplet case CxSmilesState.Radical.Divalent: case CxSmilesState.Radical.DivalentSinglet: case CxSmilesState.Radical.DivalentTriplet: count = 2; break; // no distinction in CDK between doublet/quartet case CxSmilesState.Radical.Trivalent: case CxSmilesState.Radical.TrivalentDoublet: case CxSmilesState.Radical.TrivalentQuartet: count = 3; break; } var atom = atoms[e.Key]; var mol = atomToMol[atom]; while (count-- > 0) { mol.SingleElectrons.Add(bldr.NewSingleElectron(atom)); } } } var sgroupMap = new MultiDictionary <IAtomContainer, Sgroup>(); // positional-variation if (cxstate.positionVar != null) { foreach (var e in cxstate.positionVar) { var sgroup = new Sgroup { Type = SgroupType.ExtMulticenter }; var beg = atoms[e.Key]; var mol = atomToMol[beg]; var bonds = mol.GetConnectedBonds(beg); if (bonds.Count() == 0) { continue; // bad } sgroup.Add(beg); sgroup.Add(bonds.First()); foreach (var endpt in e.Value) { sgroup.Add(atoms[endpt]); } sgroupMap.Add(mol, sgroup); } } // data sgroups if (cxstate.dataSgroups != null) { foreach (var dsgroup in cxstate.dataSgroups) { if (dsgroup.Field != null && dsgroup.Field.StartsWith("cdk:", StringComparison.Ordinal)) { chemObj.SetProperty(dsgroup.Field, dsgroup.Value); } } } // polymer Sgroups if (cxstate.sgroups != null) { foreach (var psgroup in cxstate.sgroups) { var sgroup = new Sgroup(); var atomset = new HashSet <IAtom>(); IAtomContainer mol = null; foreach (var idx in psgroup.AtomSet) { if (idx >= atoms.Count) { continue; } var atom = atoms[idx]; var amol = atomToMol[atom]; if (mol == null) { mol = amol; } else if (amol != mol) { goto C_PolySgroup; } atomset.Add(atom); } if (mol == null) { continue; } foreach (var atom in atomset) { foreach (var bond in mol.GetConnectedBonds(atom)) { if (!atomset.Contains(bond.GetOther(atom))) { sgroup.Add(bond); } } sgroup.Add(atom); } sgroup.Subscript = psgroup.Subscript; sgroup.PutValue(SgroupKey.CtabConnectivity, psgroup.Supscript); switch (psgroup.Type) { case "n": sgroup.Type = SgroupType.CtabStructureRepeatUnit; break; case "mon": sgroup.Type = SgroupType.CtabMonomer; break; case "mer": sgroup.Type = SgroupType.CtabMer; break; case "co": sgroup.Type = SgroupType.CtabCopolymer; break; case "xl": sgroup.Type = SgroupType.CtabCrossLink; break; case "mod": sgroup.Type = SgroupType.CtabModified; break; case "mix": sgroup.Type = SgroupType.CtabMixture; break; case "f": sgroup.Type = SgroupType.CtabFormulation; break; case "any": sgroup.Type = SgroupType.CtabAnyPolymer; break; case "gen": sgroup.Type = SgroupType.CtabGeneric; break; case "c": sgroup.Type = SgroupType.CtabComponent; break; case "grf": sgroup.Type = SgroupType.CtabGraft; break; case "alt": sgroup.Type = SgroupType.CtabCopolymer; sgroup.PutValue(SgroupKey.CtabSubType, "ALT"); break; case "ran": sgroup.Type = SgroupType.CtabCopolymer; sgroup.PutValue(SgroupKey.CtabSubType, "RAN"); break; case "blk": sgroup.Type = SgroupType.CtabCopolymer; sgroup.PutValue(SgroupKey.CtabSubType, "BLO"); break; } sgroupMap.Add(mol, sgroup); C_PolySgroup: ; } } // assign Sgroups foreach (var e in sgroupMap) { e.Key.SetCtabSgroups(new List <Sgroup>(e.Value)); } }