/// <summary> /// Main method which assigns Gasteiger partial pi charges. /// </summary> /// <param name="ac">AtomContainer</param> /// <param name="setCharge">currently unused</param> /// <returns>AtomContainer with partial charges</returns> public IAtomContainer AssignGasteigerPiPartialCharges(IAtomContainer ac, bool setCharge) { // we save the aromaticity flags for the input molecule so that // we can add them back before we return var oldBondAromaticity = new bool[ac.Bonds.Count]; var oldAtomAromaticity = new bool[ac.Atoms.Count]; for (int i = 0; i < ac.Atoms.Count; i++) { oldAtomAromaticity[i] = ac.Atoms[i].IsAromatic; } for (int i = 0; i < ac.Bonds.Count; i++) { oldBondAromaticity[i] = ac.Bonds[i].IsAromatic; } /* 0: remove charge, and possible flag ac */ for (int j = 0; j < ac.Atoms.Count; j++) { ac.Atoms[j].Charge = 0.0; ac.Atoms[j].IsPlaced = false; } for (int j = 0; j < ac.Bonds.Count; j++) { ac.Bonds[j].IsPlaced = false; } /* 1: detect resonance structure */ var gR1 = new StructureResonanceGenerator(); // according G. should be integrated the breaking bonding var reactionList1 = gR1.Reactions.ToList(); var paramList1 = new List <IParameterReaction>(); var param = new SetReactionCenter { IsSetParameter = true }; paramList1.Add(param); var reactionHCPB = new HeterolyticCleavagePBReaction { ParameterList = paramList1 }; reactionList1.Add(new SharingAnionReaction()); foreach (var reaction in reactionList1) { reaction.ParameterList = paramList1; } gR1.Reactions = reactionList1; // according G. should be integrated the breaking bonding var gR2 = new StructureResonanceGenerator { MaximalStructures = MaxResonanceStructures }; var reactionList2 = gR2.Reactions.ToList(); var paramList = new List <IParameterReaction>(); var paramA = new SetReactionCenter { IsSetParameter = true }; paramList.Add(paramA); reactionList2.Add(new HeterolyticCleavagePBReaction()); reactionList2.Add(new SharingAnionReaction()); foreach (var reaction in reactionList2) { reaction.ParameterList = paramList; } gR2.Reactions = reactionList2; /* find resonance containers, which eliminates the repetitions */ StructureResonanceGenerator gRN = new StructureResonanceGenerator(); // according G. should be integrated the breaking bonding var acSet = gRN.GetContainers(RemovingFlagsAromaticity(ac)); var iSet = ac.Builder.NewAtomContainerSet(); iSet.Add(ac); if (acSet != null) { foreach (var container in acSet) { ac = SetFlags(container, ac, true); // Aromatic don't break its double bond homolytically if (Aromaticity.CDKLegacy.Apply(ac)) { reactionList1.Remove(reactionHCPB); } else { reactionList1.Add(reactionHCPB); } var a = gR1.GetStructures(RemovingFlagsAromaticity(ac)); if (a.Count > 1) { for (int j = 1; j < a.Count; j++) { // the first is already added iSet.Add(a[j]); } } ac = SetFlags(container, ac, false); /* processing for bonds which are not in resonance */ for (int number = 0; number < ac.Bonds.Count; number++) { IAtomContainer aa = SetAntiFlags(container, ac, number, true); if (aa != null) { var ab = gR2.GetStructures(aa); if (ab.Count > 1) { for (int j = 1; j < ab.Count; j++) { // the first is already added iSet.Add(ab[j]); } } ac = SetAntiFlags(container, aa, number, false); } } } } /* detect hyperconjugation interactions */ var setHI = GetHyperconjugationInteractions(ac, iSet); if (setHI != null) { if (setHI.Count != 0) { iSet.AddRange(setHI); } Debug.WriteLine($"setHI: {iSet.Count}"); } if (iSet.Count < 2) { for (int i = 0; i < ac.Atoms.Count; i++) { ac.Atoms[i].IsAromatic = oldAtomAromaticity[i]; } for (int i = 0; i < ac.Bonds.Count; i++) { ac.Bonds[i].IsAromatic = oldBondAromaticity[i]; } return(ac); } /* 2: search whose atoms which don't keep their formal charge and set flags */ var sumCharges = Arrays.CreateJagged <double>(iSet.Count, ac.Atoms.Count); for (int i = 1; i < iSet.Count; i++) { var iac = iSet[i]; for (int j = 0; j < iac.Atoms.Count; j++) { sumCharges[i][j] = iac.Atoms[j].FormalCharge.Value; } } for (int i = 1; i < iSet.Count; i++) { var iac = iSet[i]; int count = 0; for (int j = 0; j < ac.Atoms.Count; j++) { if (count < 2) { if (sumCharges[i][j] != ac.Atoms[j].FormalCharge) { ac.Atoms[j].IsPlaced = true; iac.Atoms[j].IsPlaced = true; count++; /* TODO- error */ } } } } /* 3: set sigma charge (PEOE). Initial start point */ var peoe = new GasteigerMarsiliPartialCharges();; peoe.MaxGasteigerIterations = 6; IAtomContainer acCloned; var gasteigerFactors = AssignPiFactors(iSet);//a,b,c,deoc,chi,q /* 4: calculate topological weight factors Wt=fQ*fB*fA */ var Wt = new double[iSet.Count - 1]; for (int i = 1; i < iSet.Count; i++) { Wt[i - 1] = GetTopologicalFactors(iSet[i], ac); Debug.WriteLine($", W:{Wt[i - 1]}"); acCloned = (IAtomContainer)iSet[i].Clone(); acCloned = peoe.AssignGasteigerMarsiliSigmaPartialCharges(acCloned, true); for (int j = 0; j < acCloned.Atoms.Count; j++) { if (iSet[i].Atoms[j].IsPlaced) { gasteigerFactors[i][StepSize * j + j + 5] = acCloned.Atoms[j].Charge.Value; } } } // calculate electronegativity for changed atoms and make the difference // between whose atoms which change their formal charge for (int iter = 0; iter < MaxGasteigerIterations; iter++) { for (int k = 1; k < iSet.Count; k++) { IAtomContainer iac = iSet[k]; double[] electronegativity = new double[2]; int count = 0; int atom1 = 0; int atom2 = 0; for (int j = 0; j < iac.Atoms.Count; j++) { if (count == 2) // The change of sign is product of only two atoms, is not true { break; } if (iac.Atoms[j].IsPlaced) { Debug.WriteLine("Atom: " + j + ", S:" + iac.Atoms[j].Symbol + ", C:" + iac.Atoms[j].FormalCharge); if (count == 0) { atom1 = j; } else { atom2 = j; } double q1 = gasteigerFactors[k][StepSize * j + j + 5]; electronegativity[count] = gasteigerFactors[k][StepSize * j + j + 2] * q1 * q1 + gasteigerFactors[k][StepSize * j + j + 1] * q1 + gasteigerFactors[k][StepSize * j + j]; Debug.WriteLine("e:" + electronegativity[count] + ",q1: " + q1 + ", c:" + gasteigerFactors[k][StepSize * j + j + 2] + ", b:" + gasteigerFactors[k][StepSize * j + j + 1] + ", a:" + gasteigerFactors[k][StepSize * j + j]); count++; } } Debug.WriteLine("Atom1:" + atom1 + ",Atom2:" + atom2); /* difference of electronegativity 1 lower */ var max1 = Math.Max(electronegativity[0], electronegativity[1]); var min1 = Math.Min(electronegativity[0], electronegativity[1]); double DX = 1.0; if (electronegativity[0] < electronegativity[1]) { DX = gasteigerFactors[k][StepSize * atom1 + atom1 + 3]; } else { DX = gasteigerFactors[k][StepSize * atom2 + atom2 + 3]; } var Dq = (max1 - min1) / DX; Debug.WriteLine("Dq : " + Dq + " = (" + max1 + "-" + min1 + ")/" + DX); var epN1 = GetElectrostaticPotentialN(iac, atom1, gasteigerFactors[k]); var epN2 = GetElectrostaticPotentialN(iac, atom2, gasteigerFactors[k]); var SumQN = Math.Abs(epN1 - epN2); Debug.WriteLine("sum(" + SumQN + ") = (" + epN1 + ") - (" + epN2 + ")"); /* electronic weight */ var WE = Dq + fE * SumQN; Debug.WriteLine("WE : " + WE + " = Dq(" + Dq + ")+FE(" + fE + ")*SumQN(" + SumQN); var iTE = iter + 1; /* total topological */ var W = WE * Wt[k - 1] * fS / (iTE); Debug.WriteLine("W : " + W + " = WE(" + WE + ")*Wt(" + Wt[k - 1] + ")*FS(" + fS + ")/iter(" + iTE + "), atoms: " + atom1 + ", " + atom2); /* iac == new structure, ac == old structure */ /* atom1 */ if (iac.Atoms[atom1].FormalCharge == 0) { if (ac.Atoms[atom1].FormalCharge < 0) { gasteigerFactors[k][StepSize * atom1 + atom1 + 5] = -1 * W; } else { gasteigerFactors[k][StepSize * atom1 + atom1 + 5] = W; } } else if (iac.Atoms[atom1].FormalCharge > 0) { gasteigerFactors[k][StepSize * atom1 + atom1 + 5] = W; } else { gasteigerFactors[k][StepSize * atom1 + atom1 + 5] = -1 * W; } /* atom2 */ if (iac.Atoms[atom2].FormalCharge == 0) { if (ac.Atoms[atom2].FormalCharge < 0) { gasteigerFactors[k][StepSize * atom2 + atom2 + 5] = -1 * W; } else { gasteigerFactors[k][StepSize * atom2 + atom2 + 5] = W; } } else if (iac.Atoms[atom2].FormalCharge > 0) { gasteigerFactors[k][StepSize * atom2 + atom2 + 5] = W; } else { gasteigerFactors[k][StepSize * atom2 + atom2 + 5] = -1 * W; } } for (int k = 1; k < iSet.Count; k++) { for (int i = 0; i < ac.Atoms.Count; i++) { if (iSet[k].Atoms[i].IsPlaced) { var charge = ac.Atoms[i].Charge.Value; double chargeT = 0.0; chargeT = charge + gasteigerFactors[k][StepSize * i + i + 5]; Debug.WriteLine("i<|" + ac.Atoms[i].Symbol + ", " + chargeT + "=c:" + charge + "+g: " + gasteigerFactors[k][StepSize * i + i + 5]); ac.Atoms[i].Charge = chargeT; } } } }// iterations Debug.WriteLine("final"); // before getting back we should set back the aromatic flags for (int i = 0; i < ac.Atoms.Count; i++) { ac.Atoms[i].IsAromatic = oldAtomAromaticity[i]; } for (int i = 0; i < ac.Bonds.Count; i++) { ac.Bonds[i].IsAromatic = oldBondAromaticity[i]; } return(ac); }
/// <summary> /// calculate the stabilization of orbitals when they contain deficiency of charge. /// </summary> /// <param name="atomContainer">the molecule to be considered</param> /// <param name="atom">IAtom for which effective atom StabilizationCharges factor should be calculated</param> /// <returns>stabilizationValue</returns> public static double CalculatePositive(IAtomContainer atomContainer, IAtom atom) { /* restrictions */ // if(atomContainer.GetConnectedSingleElectronsCount(atom) > 0 || atom.FormalCharge != 1){ if (atom.FormalCharge != 1) { return(0.0); } // only must be generated all structures which stabilize the atom in question. StructureResonanceGenerator gRI = new StructureResonanceGenerator(); var reactionList = gRI.Reactions.ToList(); reactionList.Add(new HyperconjugationReaction()); gRI.Reactions = reactionList; var resonanceS = gRI.GetStructures(atomContainer); var containerS = gRI.GetContainers(atomContainer); if (resonanceS.Count < 2) // meaning it was not find any resonance structure { return(0.0); } int positionStart = atomContainer.Atoms.IndexOf(atom); var result1 = new List <double>(); var distance1 = new List <int>(); resonanceS.RemoveAt(0);// the first is the initial structure foreach (var resonance in resonanceS) { if (resonance.Atoms.Count < 2) // resonance with only one atom donnot have resonance { continue; } ShortestPaths shortestPaths = new ShortestPaths(resonance, resonance.Atoms[positionStart]); /* search positive charge */ PiElectronegativity electronegativity = new PiElectronegativity(); foreach (var atomP in resonance.Atoms) { IAtom atomR = atomContainer.Atoms[resonance.Atoms.IndexOf(atomP)]; if (containerS[0].Contains(atomR)) { electronegativity.MaxIterations = 6; double result = electronegativity.CalculatePiElectronegativity(resonance, atomP); result1.Add(result); int dis = shortestPaths.GetDistanceTo(atomP); distance1.Add(dis); } } } /* logarithm */ double value = 0.0; double sum = 0.0; var itDist = distance1.GetEnumerator(); foreach (var ee in result1) { double suM = ee; if (suM < 0) { suM = -1 * suM; } itDist.MoveNext(); sum += suM * Math.Pow(0.67, itDist.Current); } value = sum; return(value); }