public static bool pairwiseangle(OBMol mol, ref double pangle) { VectorVecInt mapping = new VectorVecInt(); if (findcarboxylates(mol, ref mapping)) { double sum = 0; List <double> angles = new List <double>(); if (mapping.Count > 1) { OBAtom c1 = mol.GetAtom(mapping[0][1]); OBAtom a1 = mol.GetAtom(mapping[0][3]); OBAtom c2 = mol.GetAtom(mapping[1][1]); OBAtom a2 = mol.GetAtom(mapping[1][3]); pangle = pairwiseangle(c1, a1, c2, a2); return(true); } else { return(false); } } else { return(false); } }
/// <summary> /// Calculate the angle between 2 carboxylates /// </summary> public static double CalAngle(OBMol mol) { var mapping = OBFunctions.findcarboxylates(mol); var carbA = mol.GetAtom(mapping[0][1]); // carbon in carboxylate var aA = mol.GetAtom(mapping[0][3]); // atom that the carbon connects to var carbB = mol.GetAtom(mapping[1][1]); var aB = mol.GetAtom(mapping[1][3]); var pAngle = OBFunctions.pairwiseangle(carbA, aA, carbB, aB); // angle between carboxylates return(pAngle); }
public static OBMol molecule_merge(OBMol mol1, OBAtom a, OBMol mol2, OBAtom b) { //takes two molecules and two atoms in each molecule and //assuming atoms are in the same place, delete one atom and copy bond to the other //a //foreach(OBBond bond in b.Bonds()) //{ //} int keepid = Convert.ToInt32(a.GetIdx()); int todeleteid = Convert.ToInt32(b.GetIdx()); //var bonds = b.Bonds(); List <OBBond> bondlist = new List <OBBond>(); foreach (OBBond bon in b.Bonds()) { bondlist.Add(bon); } OBBond bond = bondlist[0]; int connectid = (int)bond.GetNbrAtomIdx(b); int prevatms = (int)mol1.NumAtoms(); //number of atoms before we combine things //OBMol mol3 = new OBMol (); mol1 = addmol(mol2, mol1); mol1.BeginModify(); OBAtom keep = mol1.GetAtom(keepid); OBAtom todelete = mol1.GetAtom(todeleteid + prevatms); OBAtom toconnect = mol1.GetAtom(connectid + prevatms); OBBond newbond = new OBBond(); newbond.SetBegin(keep); newbond.SetEnd(toconnect); newbond.SetBO(1); mol1.AddBond(newbond); mol1.DeleteAtom(todelete); //OBAtom= atom1 //var a = map2[0]; //int c1 = (int)(map1[1]); //int c2 = (int)(map2[1] + prevatms); //int h1 = (int)(map1[0]); ///int h2 = (int)(map2[0] + prevatms); //OBAtom carbon1 = mol1.GetAtom(c1); //OBAtom carbon2 = mol1.GetAtom(c2); //OBAtom hydrogen1 = mol1.GetAtom(h1); ///OBAtom hydrogen2 = mol1.GetAtom(h2); //OBBuilder.Connect(mol1, c1, c2);//connect fragments //mol1.DeleteAtom(hydrogen1); //mol1.DeleteAtom(hydrogen2); mol1.EndModify(); return(mol1); }
public static OBMol addmol2(OBMol source, OBMol dest) { //combines two OBMols into one molecule // this is designed to do the same thing as the += operator in mol.cpp, in other words this implements functionality present in openbabel, but not in the C# api //modifies atom and bond indices in the process //dest.BeginModify(); uint prevatms = dest.NumAtoms(); uint nextatms = source.NumAtoms(); uint acount = prevatms; uint bcount = dest.NumBonds(); // First, handle atoms and bonds foreach (OBAtom atom in source.Atoms()) { atom.SetId(acount); ////Need to remove ID which relates to source mol rather than this mol// But in the C++ it had a NoId thing I couldn't figure out dest.AddAtom(atom); acount++; //var foooo = dest.Atoms (); } //writeatominfotoscreen (dest); foreach (OBBond bond in source.Bonds()) { bond.SetId(bcount); OBBond b = new OBBond(); //b.SetBegin(dest.GetAtom((int)(bond.GetBeginAtomIdx() + prevatms))); //b.SetEnd(dest.GetAtom((int)(bond.GetEndAtomIdx() + prevatms))); b.Set(0, dest.GetAtom((int)(bond.GetBeginAtomIdx() + prevatms)), dest.GetAtom((int)(bond.GetEndAtomIdx() + prevatms)), (int)bond.GetBO(), (int)bond.GetFlags()); if (bond.HasData("trueBO")) { b.CloneData(bond.GetData("trueBO")); //clone true bond order so we can eventually do MOF-UFF } dest.AddBond(b); //dest.AddBond( (int)bond.GetBO(), (int)bond.GetFlags()); bcount++; } //don't really understand what they mean by residues //I think it's an amino acid or nucleotide so you can build up proteins and stuff? //don't think I'm going to use them either, but it might be useful //dest.EndModify(); this tends to mangle up all the atom ids, which is bad return(dest); }
/// <summary> /// Whether the candidate has enough carboxylates and conforms to angle- and carboxylate-blocking constraints. /// </summary> public static bool CanCalculateReward(OBMol mol) { var mapping = OBFunctions.findcarboxylates(mol); if (mapping.Count < 2) { return(false); } var carbA = mol.GetAtom(mapping[0][1]); // carbon in carboxylate var aA = mol.GetAtom(mapping[0][3]); // atom that the carbon connects to var carbB = mol.GetAtom(mapping[1][1]); var aB = mol.GetAtom(mapping[1][3]); var pAngle = OBFunctions.pairwiseangle(carbA, aA, carbB, aB); // angle between carboxylates return(!OBFunctions.carboxylatesBlocked(mol, aA, carbA, aB, carbB) && pAngle >= AngleFloor); }
public static bool averagepairwiseangle(OBMol mol, ref double avgangle) { VectorVecInt mapping = new VectorVecInt(); if (findcarboxylates(mol, ref mapping)) { double sum = 0; List <double> angles = new List <double>(); if (mapping.Count > 1) { OBAtom c1 = mol.GetAtom(mapping[0][1]); OBAtom a1 = mol.GetAtom(mapping[0][3]); OBAtom c2 = mol.GetAtom(mapping[1][1]); OBAtom a2 = mol.GetAtom(mapping[1][3]); double pangle = pairwiseangle(c1, a1, c2, a2); angles.Add(pangle); sum += pangle; OBForceField MMFF94 = OBForceField.FindForceField("MMFF94"); MMFF94.Setup(mol); for (int i = 0; i < 300; i++) { MMFF94.MolecularDynamicsTakeNSteps(1, 300, 1.2, 1); MMFF94.GetCoordinates(mol); pangle = pairwiseangle(c1, a1, c2, a2); //this function is sufficiently fast that it does not need to be optimized, molecular dynamics takes about 15 milliseconds per step, this take practically nothing angles.Add(pangle); sum += pangle; } avgangle = sum / angles.Count; return(true); } else { return(false); } } else { return(false); } }
public static bool updatexyz(OBMol mol, double[,] xyz) { //OBMol newmol = new OBMol(mol); for (int i = 0; i < mol.NumAtoms(); i++) { OBAtom a = mol.GetAtom(i + 1); a.SetVector(xyz[i, 0], xyz[i, 1], xyz[i, 2]); //OBVector3 vec = OpenBabelFunctions.OBFunctions.dubs2obvec(xyz[i]); //a.SetVector(vec); } return(true); }
public static OBMol merge_atoms_at_same_location(OBMol mol) { double radius = 0.1; //when we make a unit_cell by copy and pasting base cases we end up with atoms at the same location that need to be merged //assumes only two atoms overlap at a time Dictionary <int, int> tomerge = new Dictionary <int, int>(); foreach (OBAtom a in mol.Atoms()) { if (!tomerge.ContainsKey((int)a.GetIdx())) { foreach (OBAtom b in mol.Atoms()) { if (a.GetIdx() == b.GetIdx()) { continue; } else { double len = Math.Round(StarMath.norm2(obvec2dubs(OBVector3.Sub(a.GetVector(), b.GetVector()))), 7); //gets length if (len <= radius) { tomerge.Add((int)b.GetIdx(), (int)a.GetIdx()); } } } } } int atomsdeleted = 0; foreach (int key in tomerge.Keys) { mol = molecule_merge(mol, mol.GetAtom(key - atomsdeleted), mol.GetAtom(tomerge[key] - atomsdeleted)); atomsdeleted++; } return(mol); }
/// <summary> /// Calculates the approximate surface area contributions for each atom /// </summary> /// <param name="mol"></param> /// <param name="includeHydrogens">Include hydrogens in calculation</param> /// <returns></returns> public static double[] LabuteASAContributions(this OBMol mol, bool includeHydrogens = true) { var numAtoms = mol.NumAtoms(); var Vi = new double[numAtoms + 1].Zero().ToArray(); var rads = new double[numAtoms + 1].Zero().ToArray(); rads[0] = AtomicConstants.GetRBO(1); double Ri, Rj, Bij, Dij; // OpenBabel atom numbering is 1-based for (var i = 1; i <= numAtoms; i++) { rads[i] = AtomicConstants.GetRBO(mol.GetAtom(i).GetAtomicNum()); } foreach (var bond in mol.Bonds()) { var beginAtom = bond.GetBeginAtomIdx(); var endAtom = bond.GetEndAtomIdx(); Ri = rads[beginAtom]; Rj = rads[endAtom]; var bondOrder = bond.GetBondOrder(); Bij = !bond.IsAromatic() ? Ri + Rj - BondConstants.BondScaleFactors[bondOrder] : Ri + Rj - BondConstants.BondScaleFactors[0]; Dij = Math.Min(Math.Max(Math.Abs(Ri - Rj), Bij), Ri + Rj); Vi[beginAtom] += Rj * Rj - Math.Pow((Ri - Dij), 2) / Dij; Vi[endAtom] += Ri * Ri - Math.Pow((Rj - Dij), 2) / Dij; } if (includeHydrogens) { Rj = rads[0]; for (var i = 1; i <= numAtoms; i++) { Ri = rads[i]; Bij = Ri + Rj; Dij = Math.Min(Math.Max(Math.Abs(Ri - Rj), Bij), Ri + Rj); Vi[i] += Rj * Rj - Math.Pow((Ri - Dij), 2) / Dij; Vi[0] += Ri * Ri - Math.Pow((Rj - Dij), 2) / Dij; } } for (var i = 0; i <= numAtoms; i++) { Ri = rads[i]; Vi[i] = 4 * Math.PI * Math.Pow(Ri, 2) - Math.PI * Ri * Vi[i]; } return(Vi); }
public static designGraph updatepositions(designGraph graph, OBMol mol) { int count = graph.nodes.Count; for (int i = 0; i <= count - 1; i++) { OBAtom a = mol.GetAtom(i + 1); //a.GetVector node n = graph.nodes[i]; n.X = a.GetX() / scale; n.Y = a.GetY() / scale; n.Z = a.GetZ() / scale; } return(graph); }
/// <summary> /// Calculates the Hk deltas for the molecule /// </summary> /// <param name="mol"></param> /// <param name="skipHydrogens"></param> /// <returns></returns> public static double[] HkDeltas(this OBMol mol, bool skipHydrogens = true) { var numAtoms = mol.NumAtoms(); var result = new double[numAtoms]; for (var i = 1; i <= numAtoms; i++) { var atom = mol.GetAtom(i); var atomicNumber = atom.GetAtomicNum(); if (atomicNumber > 1) { result[i - 1] = atomicNumber <= 10 ? (double)atom.ValenceNumber() : (double)(atom.ValenceNumber() / (atomicNumber - atom.NOuterShellElectrons() - 1)); } else if (!skipHydrogens) { result[i - 1] = 0d; } } return(result); }
public void parsePDB() { // for determining hydrogen bonds List <Vector3> hBondAcceptors = new List <Vector3> (); List <Vector3> hBondDonors = new List <Vector3> (); parseMol: // iteration start if multiple input files are used BezierSpline[] ribbonSplineList = new BezierSpline[30]; //for drawing protein lines (30 is max number of chains) int numAtoms = (int)mol.NumAtoms() + 1; atoms = new GameObject[numAtoms]; int maxHelix = 500; radius = new float[maxHelix, numAtoms]; int ribbonChainIndex = 0; OBElementTable table = new OBElementTable(); int currentChain = -1; OBAtom[] alphaCarbons = new OBAtom[numAtoms / 4]; int alphaCarbonCount = 0; List <Vector3> atomPositions = new List <Vector3> (); List <string> atomElements = new List <string> (); for (int i = 1; i < numAtoms; i++) { OBAtom atom = mol.GetAtom(i); string tag; OBResidue res = atom.GetResidue(); Vector3 position = new Vector3((float)atom.GetX(), (float)atom.GetY(), (float)atom.GetZ()); string elem = table.GetSymbol((int)atom.GetAtomicNum()).ToUpper(); //checks for pharmacophore labels if (res.GetName() == "ACC" || res.GetName() == "FOB" || res.GetName() == "POS" || res.GetName() == "NEG" || res.GetName() == "RNG" || res.GetName() == "DON") { if (atom.IsHydrogen()) //added hydrogens gets the same resName and has to be ignored { continue; } renderPharmacophore = true; } else { renderPharmacophore = false; } // pharmacophores if (res.GetName() == "EXC") { if (atom.IsHydrogen()) //added hydrogens gets the same resName and has to be ignored { continue; } renderEXC = true; renderPharmacophore = true; } else { renderEXC = false; } //creates the atom object atoms[i] = createAtomType(elem, position); int n; if (int.TryParse(res.GetName(), out n)) { if (CollectionOfLigands == null) { CollectionOfLigands = new List <List <GameObject> >(); CollectionOfLigands.Add(new List <GameObject>()); } while (n + 1 > CollectionOfLigands.Count) { CollectionOfLigands.Add(new List <GameObject>()); } CollectionOfLigands[n].Add(atoms[i]); } if (res.GetResidueProperty(9)) //water { tag = "water"; } else if (res.GetAtomProperty(atom, 4) || (atom.IsHydrogen() && !res.GetResidueProperty(5))) //ligand { if (res.GetResidueProperty(5)) //ion (should be 3 but a bug in openbabel labels ions as protein, thats why the check has to be done inside the ligand check) { tag = "ion"; } else { TextMesh lText = atoms [i].transform.Find("Text").GetComponent <TextMesh> (); lText.color = textColor; if (renderPharmacophore) { tag = "hetatms"; //make sure pharmacophores always show lText.text = res.GetName() + ":" + res.GetIdx(); lText.fontSize = labelFontSize; } else { tag = "hetatmbs"; if (ligandText) { lText.text = elem + ":" + i.ToString(); lText.fontSize = labelFontSize; } } if (sphere) { atoms [i].transform.localScale *= 4; } if (atom.IsHbondAcceptor()) { foreach (Vector3 candidatePos in hBondDonors) { checkHBond(candidatePos, position); } } if (atom.IsHbondDonor()) { foreach (Vector3 candidatePos in hBondAcceptors) { checkHBond(candidatePos, position); } } } } else //protein { tag = "balls"; atomPositions.Add(position); atomElements.Add(elem); if (atom.IsHbondAcceptor()) { hBondAcceptors.Add(position); } else { hBondDonors.Add(position); } if (res.GetAtomProperty(atom, 0)) //alpha carbon { alphaCarbons[alphaCarbonCount] = atom; if (alphaCarbonCount > 6) //check if the ribbon is alpha helix using torsion angles { double torsion = mol.GetTorsion(atom, alphaCarbons[alphaCarbonCount - 1], alphaCarbons[alphaCarbonCount - 2], alphaCarbons[alphaCarbonCount - 3]); double prevTorsion = mol.GetTorsion(alphaCarbons[alphaCarbonCount - 4], alphaCarbons[alphaCarbonCount - 5], alphaCarbons[alphaCarbonCount - 6], alphaCarbons[alphaCarbonCount - 7]); double torsionSum = torsion + prevTorsion; if (torsionSum > 99 && torsionSum < 111) { for (int j = ribbonChainIndex - 7; j <= ribbonChainIndex; j++) { radius [currentChain, j] = 1.5f; //alpha helix } } else { radius [currentChain, ribbonChainIndex] = 0.5f; } } alphaCarbonCount++; if (proteinText) //only displays text on alpha carbons { TextMesh pText = atoms [i].transform.Find("Text").GetComponent <TextMesh> (); pText.color = textColor; pText.text = res.GetName() + " -" + res.GetNumString(); pText.fontSize = labelFontSize; } int tempChain = (int)res.GetChainNum(); if (tempChain != currentChain) { currentChain = tempChain; ribbonChainIndex = 0; } //add points for ribbon rendering addBezierPoint(ribbonSplineList, currentChain, ribbonChainIndex, position); ribbonChainIndex++; } } atoms[i].transform.tag = tag; centerPos += position; centerCount++; } //createSurface (atomPositions,atomElements); Debug.Log(hBondAcceptors.Count + " " + hBondDonors.Count); //evaluate bonds for (int i = 0; i < mol.NumBonds(); i++) { OBBond bond = mol.GetBond(i); OBAtom atom = mol.GetAtom((int)bond.GetBeginAtomIdx()); OBResidue res = atom.GetResidue(); bool ligand = res.GetAtomProperty(atom, 4) || (atom.IsHydrogen() && !res.GetResidueProperty(5)); if (ligand && sphere) //no ligand bonds if display mode is CPK sphere { continue; } try { connect(atoms[bond.GetBeginAtomIdx()], atoms[bond.GetEndAtomIdx()], bond); } catch (System.Exception e) { Debug.Log(e); } } //handle pharmacophore vectors if (mol.HasData("VECTOR")) { string[] vectors = mol.GetData("VECTOR").GetValue().Split(new string[] { "\n" }, StringSplitOptions.None); foreach (string vector in vectors) { string[] idx = vector.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); try { Vector3 pos = new Vector3(float.Parse(idx[1]), float.Parse(idx[2]), float.Parse(idx[3])); int id = int.Parse(idx[0]); drawVector(atoms[id], pos, mol.GetAtom(id).GetResidue().GetName()); } catch (System.Exception e) { Debug.Log(e); } } } //render protein ribbons drawRibbons(ribbonSplineList, "ribbons"); //must be before alpha due to indexing drawRibbons(ribbonSplineList, "alpha"); // check for separate ligand file if (file.Contains("protein")) { file = file.Replace("protein", "ligand"); string file1 = file.Replace("." + extension, ".sdf"); // .+extension incase the format would also appear in the file name string file2 = file.Replace("." + extension, ".mol2"); if (File.Exists(file1)) { readMol(file); goto parseMol; } else if (File.Exists(file2)) { readMol(file); goto parseMol; } } center = createObject(new GameObject(), centerPos / centerCount); //the center of the pdb show(); }
public static OBMol addmol(OBMol source, OBMol dest) { //combines two OBMols into one molecule // this is designed to do the same thing as the += operator in mol.cpp, in other words this implements functionality present in openbabel, but not in the C# api dest.BeginModify(); uint prevatms = dest.NumAtoms(); uint nextatms = source.NumAtoms(); // First, handle atoms and bonds foreach (OBAtom atom in source.Atoms()) { atom.SetId(0); ////Need to remove ID which relates to source mol rather than this mol// But in the C++ it had a NoId thing I couldn't figure out dest.AddAtom(atom); //var foooo = dest.Atoms (); } //writeatominfotoscreen (dest); foreach (OBBond bond in source.Bonds()) { bond.SetId(0); dest.AddBond((int)(bond.GetBeginAtomIdx() + prevatms), (int)(bond.GetEndAtomIdx() + prevatms), (int)bond.GetBO(), (int)bond.GetFlags()); } //don't really understand what they mean by residues //I think it's an amino acid or nucleotide so you can build up proteins and stuff? //don't think I'm going to use them either, but it might be useful foreach (OBResidue residue in source.Residues()) { OBResidue newres = new OBResidue(); dest.AddResidue(newres); OBResidueAtomIter ai = new OBResidueAtomIter(residue); //dammit why didn't they implement a residue.atoms sort of thing? I don't want to play with enumerators ////#define FOR_ATOMS_OF_RESIDUE(a,r) for( OBResidueAtomIter a(r); a; ++a ) while (ai.MoveNext()) { OBAtom resatom = new OBAtom(); resatom = ai.Current; // This is the equivalent atom in our combined molecule OBAtom atom = dest.GetAtom((int)(resatom.GetIdx() + prevatms)); // So we add this to the last-added residue // (i.e., what we just copied) //[dest.NumResidues () - 1] var res = dest.Residues().GetEnumerator(); while (!res.MoveNext()) { } //move to the last residue res.Current.AddAtom(atom); //var item = dest.Cast<RMSRequestProcessor.RMSMedia> ().ElementAt (1); } //for(OBAtom resatom in ) } dest.EndModify(); return(dest); }
public MolStat GetMolStat() { /* 统计原子 */ uint _numAtoms = mol.NumAtoms(); //所有原子总数 uint _numHvyAtoms = mol.NumHvyAtoms(); //所有除去氢原子的原子总数 int _totalCharge = mol.GetTotalCharge(); //总电荷数 int n_C = 0; // number of carbon atoms 碳原子总数 int n_C1 = 0; // number of carbon atoms with sp1 hybridization sp1杂化的碳原子数 int n_C2 = 0; // number of carbon atoms with sp1 hybridization sp2杂化的碳原子数 int n_CHB1p = 0; // number of carbon atoms with at least 1 bond to a hetero atom 至少连接一个杂原子的碳原子数 int n_CHB2p = 0; // number of carbon atoms with at least 2 bonds to a hetero atom 至少连接两个个杂原子的碳原子数 int n_CHB3p = 0; // number of carbon atoms with at least 3 bonds to a hetero atom 至少连接三个杂原子的碳原子数 int n_CHB4 = 0; // number of carbon atoms with 4 bonds to a hetero atom 连接了4个杂原子的碳原子数 int n_O = 0; // number of oxygen atoms 氧原子数 int n_O2 = 0; // number of sp2-hybridized oxygen atoms sp2杂化的氧原子数 int n_O3 = 0; // number of sp3-hybridized oxygen atoms sp3杂化的氧原子数 int n_N = 0; // number of nitrogen atoms 氮原子数 int n_N1 = 0; // number of sp-hybridized nitrogen atoms sp杂化的氮原子数 int n_N2 = 0; // number of sp2-hybridized nitrogen atoms sp2杂化的氮原子数 int n_N3 = 0; // number of sp3-hybridized nitrogen atoms sp3杂化的氮原子数 int n_S = 0; // number of sulfur atoms 硫原子数 int n_SeTe = 0; // total number of selenium and tellurium atoms 硒和碲原子的数目 int n_F = 0; // number of fluorine atoms 氟原子的数目 int n_Cl = 0; // number of chlorine atoms 氯原子的数目 int n_Br = 0; // number of bromine atoms 溴原子的数目 int n_I = 0; // number of iodine atoms 碘原子的数目 int n_P = 0; // number of phosphorus atoms 磷原子的数目 int n_B = 0; // number of boron atoms 硼原子的数目 int n_Met = 0; // total number of metal atoms 金属原子的数目 int n_X = 0; // total number of "other" atoms (not listed above) and halogens 其他原子的数目,除了以上列出的之外。 for (int i = 1; i <= _numAtoms; i++) { OBAtom _atom = mol.GetAtom(i); uint _AtomicNum = _atom.GetAtomicNum(); //原子种类,周期表序号 uint _hyb = _atom.GetHyb(); //原子的杂化形态,1 for sp1, 2 for sp2, 3 for sp3 uint _HeteroValence = _atom.GetHeteroValence(); //连接在这个原子上杂(非氢,碳)原子的数目 //uint _HeteroValence = _atom.GetHeteroDegree(); //For openbabel 3.0 if (_AtomicNum == 6) //碳原子 { n_C++; switch (_hyb) { case 1: n_C1++; break; case 2: n_C2++; break; default: break; } if (_HeteroValence >= 4) { n_CHB4++; } if (_HeteroValence >= 3) { n_CHB3p++; } if (_HeteroValence >= 2) { n_CHB2p++; } if (_HeteroValence >= 1) { n_CHB1p++; } } else if (_AtomicNum == 8) { n_O++; switch (_hyb) { case 2: n_O2++; break; case 3: n_O3++; break; default: break; } } else if (_AtomicNum == 7) { n_N++; switch (_hyb) { case 1: n_N1++; break; case 2: n_N2++; break; case 3: n_N3++; break; default: break; } } else if (_AtomicNum == 16) { n_S++; } else if (_AtomicNum == 34 || _AtomicNum == 52) { n_SeTe++; } else if (_AtomicNum == 9) { n_F++; } else if (_AtomicNum == 17) { n_Cl++; } else if (_AtomicNum == 35) { n_Br++; } else if (_AtomicNum == 53) { n_I++; } else if (_AtomicNum == 15) { n_P++; } else if (_AtomicNum == 5) { n_B++; } else if ((_AtomicNum >= 3 && _AtomicNum <= 4) || (_AtomicNum >= 11 && _AtomicNum <= 13) || (_AtomicNum >= 19 && _AtomicNum <= 32) || (_AtomicNum >= 37 && _AtomicNum <= 51) || (_AtomicNum >= 55 && _AtomicNum <= 84) || (_AtomicNum >= 87)) { n_Met++; } } n_X = (int)_numHvyAtoms - n_B - n_C - n_Met - n_N - n_O - n_P - n_S - n_SeTe; /* 统计化学键 */ uint _numBonds = mol.NumBonds(); //所有化学键的总数 int n_b1 = 0; // number of single bonds 单键的个数 int n_b1_NoH = 0; // number of none C-H single bonds 不含氢的单键个数 int n_b2 = 0; // number of double bonds 双键的个数 int n_b3 = 0; // number of triple bonds 三键的个数 int n_bar = 0; // number of aromatic bonds 芳香键的个数 int n_C1O = 0; // number of C-O single bonds 碳-氧单键的个数 int n_C2O = 0; // number of C=O double bonds 碳=氧双键的个数 int n_CN = 0; // number of C/N bonds (any type) 任何类型的碳氮键的个数 int n_XY = 0; // number of heteroatom/heteroatom bonds (any type) 任何类型的杂原子之间化学健的个数 for (int i = 0; i < _numBonds; i++) { OBBond _bond = mol.GetBond(i); OBAtom _beginAtom = _bond.GetBeginAtom(); OBAtom _endAtom = _bond.GetEndAtom(); uint _beginAtomAtomicNum = _beginAtom.GetAtomicNum(); uint _endAtomAtomicNum = _endAtom.GetAtomicNum(); if (_bond.IsSingle()) //Replace IsSingle() method in Openbabel 3.0 { n_b1++; if (_beginAtomAtomicNum != 1 && _endAtomAtomicNum != 1) { n_b1_NoH++; } } else if (_bond.IsDouble()) // Replace IsDouble() method in Openbabel 3.0 { n_b2++; } else if (_bond.IsTriple()) // Replace IsTriple() method in Openbabel 3.0 { n_b3++; } else if (_bond.IsAromatic()) { n_bar++; } if ((_beginAtomAtomicNum == 6 && _endAtomAtomicNum == 8) || (_beginAtomAtomicNum == 8 && _endAtomAtomicNum == 6)) { uint _bondOrder = _bond.GetBondOrder(); if (_bondOrder == 1) { n_C1O++; } else if (_bondOrder == 2) { n_C2O++; } } else if ((_beginAtomAtomicNum == 6 && _endAtomAtomicNum == 7) || (_beginAtomAtomicNum == 7 && _endAtomAtomicNum == 6)) { n_CN++; } else if (_beginAtomAtomicNum != 6 && _endAtomAtomicNum != 6) { n_XY++; } } /* 统计环 */ #region 统计环 VectorpRing _SSSR = mol.GetSSSR(); int n_r3 = 0; // number of 3-membered rings 3元环个数 int n_r4 = 0; // number of 4-membered rings 4元环个数 int n_r5 = 0; // number of 5-membered rings 5元环个数 int n_r6 = 0; // number of 6-membered rings 6元环个数 int n_r7 = 0; // number of 7-membered rings 7元环个数 int n_r8 = 0; // number of 8-membered rings 8元环个数 int n_r9 = 0; // number of 9-membered rings 9元环个数 int n_r10 = 0; // number of 10-membered rings 10元环个数 int n_r11 = 0; // number of 11-membered rings 11元环个数 int n_r12 = 0; // number of 12-membered rings 12元环个数 int n_r13p = 0; // number of 13-membered or larger rings 13元环或者更大的环的个数 int n_rN = 0; // number of rings containing nitrogen (any number) 含氮环的个数 int n_rN1 = 0; // number of rings containing 1 nitrogen atom 含一个氮原子的环的个数 int n_rN2 = 0; // number of rings containing 2 nitrogen atoms 含两个个氮原子的环的个数 int n_rN3p = 0; // number of rings containing 3 or more nitrogen atoms 含三个或以上个氮原子的环的个数 int n_rO = 0; // number of rings containing oxygen (any number) 含氧环的个数 int n_rO1 = 0; // number of rings containing 1 oxygen atom 含一个氧原子的环的个数 int n_rO2p = 0; // number of rings containing 2 or more oxygen atoms 含三个或以上个氧原子的环的个数 int n_rS = 0; // number of rings containing sulfur (any number) 含硫环的个数 int n_rX = 0; // number of heterocycles (any type) 杂环的个数 int n_rar = 0; // number of aromatic rings (any type) 芳香环的个数 if (_SSSR.Count != 0 || _SSSR != null) { foreach (OBRing _ring in _SSSR) { uint _ringSize = _ring.Size(); if (_ringSize == 3) { n_r3++; } else if (_ringSize == 4) { n_r4++; } else if (_ringSize == 5) { n_r5++; } else if (_ringSize == 6) { n_r6++; } else if (_ringSize == 7) { n_r7++; } else if (_ringSize == 8) { n_r8++; } else if (_ringSize == 9) { n_r9++; } else if (_ringSize == 10) { n_r10++; } else if (_ringSize == 11) { n_r11++; } else if (_ringSize == 12) { n_r12++; } else if (_ringSize >= 13) { n_r13p++; } if (_ring.IsAromatic()) { n_rar++; } VectorInt _pathes = _ring._path; int _ct_N = 0; int _ct_O = 0; int _ct_S = 0; bool _isRingX = false; foreach (int _p in _pathes) { OBAtom _atom = mol.GetAtom(_p); uint _AtomicNum = _atom.GetAtomicNum(); if (_AtomicNum == 7) //N原子 { _ct_N++; } else if (_AtomicNum == 8) //O原子 { _ct_O++; } else if (_AtomicNum == 16) //S原子 { _ct_S++; } if (_AtomicNum != 6) { _isRingX = true; } } if (_ct_N == 1) { n_rN1++; } else if (_ct_N == 2) { n_rN2++; } else if (_ct_N >= 3) { n_rN3p++; } n_rN = n_rN1 + n_rN2 + n_rN3p; if (_ct_O == 1) { n_rO1++; } else if (_ct_O >= 2) { n_rO2p++; } n_rO = n_rO1 + n_rO2p; if (_ct_S >= 1) { n_rS++; } if (_isRingX) { n_rX++; } } } #endregion // 统计数字映射成MolStat对象 MolStat stat = new MolStat { // General info AtomsCount = (int)_numAtoms, HeavyAtomsCount = (int)_numHvyAtoms, TotalCharge = _totalCharge, // Atoms info N_B = n_B, N_Br = n_Br, N_C = n_C, N_C1 = n_C1, N_C2 = n_C2, N_CHB1p = n_CHB1p, N_CHB2p = n_CHB2p, N_CHB3p = n_CHB3p, N_CHB4 = n_CHB4, N_Cl = n_Cl, N_F = n_F, N_I = n_I, N_Met = n_Met, N_N = n_N, N_N1 = n_N1, N_N2 = n_N2, N_N3 = n_N3, N_O = n_O, N_O2 = n_O2, N_O3 = n_O3, N_P = n_P, N_S = n_S, N_SeTe = n_SeTe, N_X = n_X, // Bonds info BondsCount = (int)_numBonds, N_b1 = n_b1, N_b1_NoH = n_b1_NoH, N_b2 = n_b2, N_b3 = n_b3, N_bar = n_bar, N_C1O = n_C1O, N_C2O = n_C2O, N_CN = n_CN, N_XY = n_XY, // Rings info RingsCount = _SSSR.Count, N_r10 = n_r10, N_r11 = n_r11, N_r12 = n_r12, N_r13p = n_r13p, N_r3 = n_r3, N_r4 = n_r4, N_r5 = n_r5, N_r6 = n_r6, N_r7 = n_r7, N_r8 = n_r8, N_r9 = n_r9, N_rar = n_rar, N_rN = n_rN, N_rN1 = n_rN1, N_rN2 = n_rN2, N_rN3p = n_rN3p, N_rO = n_rO, N_rO1 = n_rO1, N_rO2p = n_rO2p, N_rS = n_rS, N_rX = n_rX }; return(stat); }