/// <summary> /// RemovePseudoAtoms /// </summary> /// <param name="mol"></param> /// <returns>Pseudo atom count</returns> public static int RemovePseudoAtoms(IAtomContainer mol) { List <IAtom> pseudoAtoms = new List <IAtom>(); for (int ai = 0; ai < mol.getAtomCount(); ai++) { IAtom atom = mol.getAtom(ai); if (atom is IPseudoAtom) { pseudoAtoms.Add(atom); } } if (pseudoAtoms.Count == 0) { return(0); } foreach (IAtom atom in pseudoAtoms) { mol.removeAtomAndConnectedElectronContainers(atom); } AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(mol); mol = AtomContainerManipulator.suppressHydrogens(mol); GetHydrogenAdder().addImplicitHydrogens(mol); return(pseudoAtoms.Count); }
/// <summary> /// MolfileV3000ToAtomContainer /// </summary> /// <param name="molfile"></param> /// <returns></returns> public static IAtomContainer MolfileV3000ToAtomContainer(string molfile) { // Extract any mass info before conversion to avoid losing our custom info in conversion Dictionary <int, int> map = new Dictionary <int, int>(); if (molfile.Contains(" MASS=")) { map = ExtractMassAttributes(ref molfile); } cdk.io.DefaultChemObjectReader cor; java.io.StringReader sr = new java.io.StringReader(molfile); cor = new MDLV3000Reader(sr); cor.setReaderMode(IChemObjectReader.Mode.RELAXED); IAtomContainer mol = (IAtomContainer)cor.read(new AtomContainer()); cor.close(); for (int ai = 0; ai < mol.getAtomCount(); ai++) { IAtom a = mol.getAtom(ai); if (map.ContainsKey(ai + 1)) { a.setMassNumber(new java.lang.Integer(map[ai + 1])); } else { a.setMassNumber(null); } } ConfigureAtomContainer(mol); return(mol); }
public static string CanonicalizeSmiles( string smiles, SmilesGeneratorType smiGenFlags) { IAtomContainer mol = SmilesToAtomContainer(smiles); if (mol.getAtomCount() == 0) { return(""); } else { string smiles2 = AtomContainerToSmiles(mol, smiGenFlags); return(smiles2); } }
/// <summary> /// Remove the following features from a molecule /// - Atom non-standard mass /// - Stereo chemistry /// - explicit hydrogens /// </summary> /// <param name="src"></param> /// <returns>Modified mol</returns> public static IAtomContainer RemoveIsotopesStereoExplicitHydrogens( IAtomContainer src) { IAtom[] atoms = new IAtom[src.getAtomCount()]; IBond[] bonds = new IBond[src.getBondCount()]; IChemObjectBuilder builder = src.getBuilder(); for (int i = 0; i < atoms.Length; i++) { IAtom atom = src.getAtom(i); IAtom atom2 = (IAtom)builder.newInstance(typeof(IAtom), atom.getSymbol()); SetImplicitHydrogenCount(atom2, GetImplicitHydrogenCount(atom)); atom2.setPoint2d(atom.getPoint2d()); atoms[i] = atom2; } for (int i = 0; i < bonds.Length; i++) { IBond bond = src.getBond(i); int u = src.getAtomNumber(bond.getAtom(0)); int v = src.getAtomNumber(bond.getAtom(1)); IBond bond2 = (IBond)builder.newInstance(typeof(IBond), atoms[u], atoms[v]); bond2.setIsAromatic(bond.isAromatic()); bond2.setIsInRing(bond.isInRing()); bond2.setOrder(bond.getOrder()); bond2.setFlag(CDKConstants.ISAROMATIC, bond.getFlag(CDKConstants.ISAROMATIC)); bond2.setFlag(CDKConstants.SINGLE_OR_DOUBLE, bond.getFlag(CDKConstants.SINGLE_OR_DOUBLE)); bonds[i] = bond2; } IAtomContainer dest = (IAtomContainer)builder.newInstance(typeof(IAtomContainer)); dest.setAtoms(atoms); dest.setBonds(bonds); AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(dest); dest = AtomContainerManipulator.suppressHydrogens(dest); GetHydrogenAdder().addImplicitHydrogens(dest); return(dest); }
/// <summary> /// Convert molfile to Smiles /// </summary> /// <param name="molfile"></param> /// <returns></returns> public string MolfileStringToSmilesString(string molfile) { if (Lex.IsUndefined(molfile)) { return(""); } IAtomContainer mol = MolfileToAtomContainer(molfile); if (mol.getAtomCount() == 0) { return(""); } string smiles = AtomContainerToSmiles(mol); return(smiles); }
/// <summary> /// Convert SmilesToMolfile /// </summary> /// <param name="smiles"></param> /// <returns></returns> public string SmilesStringToMolfileString(string smiles) { if (Lex.IsUndefined(smiles)) { return(""); } IAtomContainer mol = SmilesToAtomContainer(smiles); if (mol.getAtomCount() == 0) { return(""); } string molfile = AtomContainerToMolfile(mol); return(molfile); }
static List <IAtom> GetAttachmentAtoms( IAtomContainer mol, int attachmentNo) { List <IAtom> atoms = new List <IAtom>(); for (int ai = 0; ai < mol.getAtomCount(); ai++) { IAtom atom = mol.getAtom(ai); int massNo = Math.Abs(GetMassNumber(atom)); if (massNo == attachmentNo || massNo == 12 || massNo == 21) // 12 & 21 values occur at atoms with two attachments { //SetMassNumber(atom, 0); // clear attachment number (isotope) (can't may need later, e.g.12 value for two attachements to same atom) atoms.Add(atom); } } return(atoms); }
/// <summary> /// Fragment a molecule /// </summary> /// <param name="mol"></param> /// <returns></returns> public static List <KeyValuePair <string, IAtomContainer> > FragmentMoleculeAndCanonicalizeSmiles( IAtomContainer mol, bool filterOutCommonCounterIons) { int aci, fi, i1; KeyValuePair <string, IAtomContainer> kvp; List <KeyValuePair <string, IAtomContainer> > frags = new List <KeyValuePair <string, IAtomContainer> >(); AtomContainerSet acs = (AtomContainerSet)ConnectivityChecker.partitionIntoMolecules(mol); int acc = acs.getAtomContainerCount(); for (aci = 0; aci < acc; aci++) { IAtomContainer fragMol = acs.getAtomContainer(aci); string fragSmiles = AtomContainerToSmiles(fragMol); if (filterOutCommonCounterIons) { if (CommonSmallFragments.Contains(fragSmiles) || GetHeavyAtomCount(fragMol) <= 6) { continue; } } kvp = new KeyValuePair <string, IAtomContainer>(fragSmiles, fragMol); int ac = fragMol.getAtomCount(); for (fi = frags.Count - 1; fi >= 0; fi--) // insert into list so that fragments are ordered largest to smallest { if (frags[fi].Value.getAtomCount() >= ac) { break; } } frags.Insert(fi + 1, kvp); } return(frags); }
/// <summary> /// GetHeavyAtomCount /// </summary> /// <param name="mol"></param> /// <returns></returns> public static int GetHeavyAtomCount(IAtomContainer mol) { int haCnt = 0; for (int ai = 0; ai < mol.getAtomCount(); ai++) { IAtom atom = mol.getAtom(ai); if (atom.getAtomicNumber().intValue() == 1 || // do not count hydrogens atom.getSymbol().Equals("H")) { continue; } else { haCnt++; } } return(haCnt); }
/** * Very quick and easy isomorphism check. * * @param molecule1 the molecule1 * @param fragsToCompare the frags to compare * * @return true, if successful */ private bool identicalAtoms(IAtomContainer molecule1, List<IAtomContainer> fragsToCompare) { var molFormula = MolecularFormulaTools.GetMolecularFormula(molecule1); var molFormulaString = MolecularFormulaTools.GetString(molFormula); for (var i = 0; i < fragsToCompare.Count; i++) { //no match if (molecule1.getBondCount() != fragsToCompare[i].getBondCount() && molecule1.getAtomCount() != fragsToCompare[i].getAtomCount()) { continue; } //Molecular Formula redundancy check var molFormulaFrag = MolecularFormulaTools.GetMolecularFormula(fragsToCompare[i]); var molFormulaFragString = MolecularFormulaTools.GetString(molFormulaFrag); if (molFormulaString.Equals(molFormulaFragString)) { return true; } } //no match found return false; }
public IAtomContainer markAllBonds(IAtomContainer original) { MoleculeTools.MoleculeNumbering(original); atomsContained = original.getAtomCount(); return original; }
private IEnumerable<IAtomContainer> splitMolecule(IAtomContainer atomContainer, IBond bond, IDictionary<IAtom, IList<IBond>> atomBonds) { //if this bond is in a ring we have to split another bond in this ring where at least one //bond is in between. Otherwise we wont have two fragments. Else normal split. var ret = new List<IAtomContainer>(); //get bond energy for splitting this bond var currentBondEnergy = BondEnergies.Lookup(bond); //bond is in a ring....so we have to split up another bond to break it var rings = allRings.getRings(bond); if (rings.getAtomContainerCount() != 0) { foreach (var bondInRing in rings.getAtomContainer(0).bonds().ToWindowsEnumerable<IBond>()) { //if the bonds are the same...this wont split up the ring if (bondInRing == bond) { continue; } //check for already tried bonds var check = new BondPair(bond, bondInRing); if (knownBonds.Contains(check)) { continue; } knownBonds.Add(new BondPair(bond, bondInRing)); var set = new List<IAtomContainer>(); var bondListList = new List<List<IBond>>(); var fragWeightList = new List<Double>(); foreach (var currentAtom in bond.atoms().ToWindowsEnumerable<IAtom>()) { //List with bonds in Ring var partRing = new List<IBond>(); //reset the weight because it is computed inside the traverse currentFragWeight = 0.0; //initialize new atom list atomList = new List<IAtom>(); //clone current atom because a single electron is being added...homolytic cleavage partRing = traverse(atomBonds, currentAtom, partRing, bond, bondInRing); bondListList.Add(partRing); fragWeightList.Add(currentFragWeight); var temp = makeAtomContainer(currentAtom, partRing); //set the properties again! var properties = atomContainer.getProperties(); temp.setProperties(properties); //********************************************************* //BOND ENERGY CALCULATION //calculate bond energy var currentBondEnergyRing = BondEnergies.Lookup(bondInRing); //********************************************************* //now set property temp = setBondEnergy(temp, (currentBondEnergyRing + currentBondEnergy)); set.Add(temp); } //now maybe add the fragments to the list for (var j = 0; j < set.Count; j++) { //Render.Draw(set.getAtomContainer(j), ""); if (set[j].getAtomCount() > 0 && set[j].getBondCount() > 0 && set[j].getAtomCount() != atomContainer.getAtomCount()) { //now check the current mass var fragMass = getFragmentMass(set[j], fragWeightList[j]); //check the weight of the current fragment if (!isHeavyEnough(fragMass)) { continue; } //returns true if isomorph //set the current sum formula var fragmentFormula = MolecularFormulaTools.GetMolecularFormula(set[j]); var currentSumFormula = MolecularFormulaTools.GetString(fragmentFormula); if (isIdentical(set[j], currentSumFormula)) { continue; } //add the fragment to the return list ret.Add(set[j]); } } } } else { var set = new List<IAtomContainer>(); var bondListList = new List<List<IBond>>(); var fragWeightList = new List<Double>(); //get the atoms from the splitting bond --> create 2 fragments foreach (var currentAtom in bond.atoms().ToWindowsEnumerable<IAtom>()) { var part = new List<IBond>(); //reset the weight because it is computed inside the traverse currentFragWeight = 0.0; //initialize new atom list atomList = new List<IAtom>(); part = traverse(atomBonds, currentAtom, part, bond); bondListList.Add(part); //create Atomcontainer out of bondList var temp = makeAtomContainer(currentAtom, part); //set the properties again! var properties = atomContainer.getProperties(); temp.setProperties(properties); //now calculate the correct weight subtrating the possible neutral loss mass fragWeightList.Add(currentFragWeight); //now set property: BondEnergy! temp = setBondEnergy(temp, currentBondEnergy); set.Add(temp); } //at most 2 new molecules for (var i = 0; i < set.Count; i++) { if (set[i].getAtomCount() > 0 && set[i].getBondCount() > 0 && set[i].getAtomCount() != atomContainer.getAtomCount()) { //now check the current mass var fragMass = getFragmentMass(set[i], fragWeightList[i]); //check the weight of the current fragment if (!isHeavyEnough(fragMass)) { continue; } //set the current sum formula var fragmentFormula = MolecularFormulaTools.GetMolecularFormula(set[i]); var currentSumFormula = MolecularFormulaTools.GetString(fragmentFormula); //returns true if isomorph (fast isomorph check) if (isIdentical(set[i], currentSumFormula)) { continue; } ret.Add(set[i]); } } } return ret; }
/// <summary> /// (Converted from Java to C# for possible later modification) /// Suppress any explicit hydrogens in the provided container. Only hydrogens /// that can be represented as a hydrogen count value on the atom are /// suppressed. The container is updated and no elements are copied, please /// use either <seealso cref="#copyAndSuppressedHydrogens"/> if you would to preserve /// the old instance. /// </summary> /// <param name="org"> the container from which to remove hydrogens </param> /// <returns> the input for convenience </returns> /// <seealso cref= #copyAndSuppressedHydrogens </seealso> public IAtomContainer suppressHydrogens(IAtomContainer org) { bool anyHydrogenPresent = false; for (int ai = 0; ai < org.getAtomCount(); ai++) { IAtom atom = org.getAtom(ai); if ("H".Equals(atom.getSymbol())) { anyHydrogenPresent = true; break; } } if (!anyHydrogenPresent) { return(org); } // we need fast adjacency checks (to check for suppression and // update hydrogen counts) int[][] graph = GraphUtil.toAdjList(org); int nOrgAtoms = org.getAtomCount(); int nOrgBonds = org.getBondCount(); int nCpyAtoms = 0; int nCpyBonds = 0; ISet <IAtom> hydrogens = new HashSet <IAtom>(); IAtom[] cpyAtoms = new IAtom[nOrgAtoms]; // filter the original container atoms for those that can/can't // be suppressed for (int v = 0; v < nOrgAtoms; v++) { IAtom atom = org.getAtom(v); if (suppressibleHydrogen(org, graph, v)) { hydrogens.Add(atom); incrementImplHydrogenCount(org.getAtom(graph[v][0])); } else { cpyAtoms[nCpyAtoms++] = atom; } } // none of the hydrogens could be suppressed - no changes need to be made if (hydrogens.Count == 0) { return(org); } org.setAtoms(cpyAtoms); // we now update the bonds - we have auxiliary variable remaining that // bypasses the set membership checks if all suppressed bonds are found IBond[] cpyBonds = new IBond[nOrgBonds - hydrogens.Count]; int remaining = hydrogens.Count; for (int bi = 0; bi < org.getBondCount(); bi++) { IBond bond = org.getBond(bi); if (remaining > 0 && (hydrogens.Contains(bond.getAtom(0)) || hydrogens.Contains(bond.getAtom(1)))) { remaining--; continue; } cpyBonds[nCpyBonds++] = bond; } // we know how many hydrogens we removed and we should have removed the // same number of bonds otherwise the container is strange if (nCpyBonds != cpyBonds.Length) { throw new System.ArgumentException("number of removed bonds was less than the number of removed hydrogens"); } org.setBonds(cpyBonds); return(org); }
/// <summary> /// Convert isotope labels to hilighting. /// </summary> /// <param name="mol"></param> /// <returns></returns> public string ConvertIsotopeValuesToHilighting( IAtomContainer mol) { bool hilight; string molfile2 = ""; bool clearAttachmentPointLabels = true; bool hilightAttachmentBond = true; List <int> atomSet = new List <int>(); List <int> bondSet = new List <int>(); for (int bi = 0; bi < mol.getBondCount(); bi++) { IBond b = mol.getBond(bi); if (b.getAtomCount() != 2) { continue; } IAtom a1 = b.getAtom(0); IAtom a2 = b.getAtom(1); if (hilightAttachmentBond) { hilight = (GetMassNumber(a1) != 0 && GetMassNumber(a2) != 0); } else { hilight = (GetMassNumber(a1) < 0 && GetMassNumber(a2) < 0); } if (hilight) { bondSet.Add(bi); } } //String posMap = ""; // debug (note that hydrogens can get repositioned) for (int ai = 0; ai < mol.getAtomCount(); ai++) // scan atoms for hilighting and reset isotope values { IAtom a = mol.getAtom(ai); hilight = GetMassNumber(a) < 0; if (hilight) { atomSet.Add(ai); } //posMap += ai.ToString() + ", " + a.getSymbol() + ", " + hilight + "\r\n"; // debug int massNo = GetMassNumber(a); if (massNo == hilightIsotopeValue) { a.setMassNumber(null); // set back to original value } else if (massNo < 0) { if (clearAttachmentPointLabels) { a.setMassNumber(null); } else { SetMassNumber(a, -massNo); // set back to positive } } } //mol = GenerateCoordinates(mol); // (should already be done) try { molfile2 = AtomContainerToMolFileV3000(mol); } catch (Exception ex) { ex = ex; } if (Lex.IsUndefined(molfile2)) // couldn't convert to v3000, just return unhilighted v2000 file { molfile2 = AtomContainerToMolfile(mol); return(molfile2); } string txt = "MDLV30/HILITE"; if (atomSet.Count > 0) { txt += " " + BuildV3000KeywordList("ATOMS", atomSet); } if (bondSet.Count > 0) { txt += " " + BuildV3000KeywordList("BONDS", bondSet); } txt = BuildV3000Lines(txt); bool hasCollection = Lex.Contains(molfile2, "M V30 END COLLECTION"); if (hasCollection) // already have collection begin and end { txt = txt + "M V30 END COLLECTION"; molfile2 = Lex.Replace(molfile2, "M V30 END COLLECTION", txt); } else // add collection begin & end { txt = "M V30 BEGIN COLLECTION\n" + txt + "M V30 END COLLECTION\n" + "M V30 END CTAB"; molfile2 = Lex.Replace(molfile2, "M V30 END CTAB", txt); } return(molfile2); }
/// <summary> /// Remove explicit and implicit hydrogens bonded to positive nitrogens /// </summary> /// <param name="org"></param> /// <returns></returns> public int RemoveHydrogensBondedToPositiveNitrogens(IAtomContainer org) { int chg, impHydCnt; int implicitHydRemoved = 0; HashSet <IAtom> atomsToRemove = new HashSet <IAtom>(); HashSet <IBond> bondsToRemove = new HashSet <IBond>(); int nOrgAtoms = org.getAtomCount(); int nOrgBonds = org.getBondCount(); // Get H atoms and their bonds to pos-charged Nitrogen, adjusting charge for (int bi = 0; bi < org.getBondCount(); bi++) { IBond bond = org.getBond(bi); if (bond.getAtomCount() != 2) { continue; } IAtom a1 = bond.getAtom(0); IAtom a2 = bond.getAtom(1); if (a1.getSymbol() == "H" && a2.getSymbol() == "N" && GetFormalCharge(a2) > 0) { chg = GetFormalCharge(a2) - 1; SetFormalCharge(a2, chg); atomsToRemove.Add(a1); bondsToRemove.Add(bond); } else if (a2.getSymbol() == "H" && a1.getSymbol() == "N" && GetFormalCharge(a1) > 0) { chg = GetFormalCharge(a1) - 1; SetFormalCharge(a1, chg); atomsToRemove.Add(a2); bondsToRemove.Add(bond); } } // Check for implicit H attached to pos-charged N for (int ai = 0; ai < nOrgAtoms; ai++) { IAtom a = org.getAtom(ai); if (a.getSymbol() == "N" && GetFormalCharge(a) > 0 && GetImplicitHydrogenCount(a) > 0) { chg = GetFormalCharge(a) - 1; SetFormalCharge(a, chg); impHydCnt = GetImplicitHydrogenCount(a) - 1; SetImplicitHydrogenCount(a, impHydCnt); implicitHydRemoved++; } } if (implicitHydRemoved > 0) { implicitHydRemoved = implicitHydRemoved; // debug } if (atomsToRemove.Count == 0) { return(implicitHydRemoved); // just return if no explicit H to remove } // Get list of atoms to keep IAtom[] cpyAtoms = new IAtom[nOrgAtoms - atomsToRemove.Count]; int nCpyAtoms = 0; for (int ai = 0; ai < nOrgAtoms; ai++) { IAtom atom = org.getAtom(ai); if (!atomsToRemove.Contains(atom)) { cpyAtoms[nCpyAtoms++] = atom; } } org.setAtoms(cpyAtoms); // Get list of bonds to keep IBond[] cpyBonds = new IBond[nOrgBonds - bondsToRemove.Count]; int nCpyBonds = 0; for (int bi = 0; bi < org.getBondCount(); bi++) { IBond bond = org.getBond(bi); if (!bondsToRemove.Contains(bond)) { cpyBonds[nCpyBonds++] = bond; } } org.setBonds(cpyBonds); return(atomsToRemove.Count + implicitHydRemoved); }
static ICdkMol CdkMolUtil => StaticCdkMol.I; // static molecule shortcut for utility methods /// <summary> /// Build UniChem Data /// Note that this routine takes about 14 secs the first time it's called, faster thereafter. /// </summary> /// <param name="mol"></param> /// <returns></returns> public static UniChemData BuildUniChemData( IAtomContainer mol) { IAtomContainer mol2; InChIGenerator ig = null; string molSmiles, fragSmiles = "", molFile = ""; int acc, fi, ci; //if (Lex.StartsWith(molString, "InChI=")) //{ // sourceInchi = molString; // mol = CdkMol.InChIToAtomContainer(sourceInchi); //} //else // assume molfile otherwise //{ // molfile = molString; // mol = CdkMol.MolfileToAtomContainer(molfile); //} if (mol.getAtomCount() <= 1) { throw new Exception("Atom count <= 1"); } int pseudoCount = CdkMol.RemovePseudoAtoms(mol); mol = CdkMol.AtomContainerToSmilesAndBack(mol, out molSmiles); InChIGeneratorFactory igf = InChIGeneratorFactory.getInstance(); try { //string options = "/KET /15T"; // options to include keto-enol and 1,5-tautomerism (not recognized by CDK) ig = igf.getInChIGenerator(mol); //, options); } catch (Exception ex) // may fail for some complex mols (e.g. CorpId 12345, a MDL V3000 mol with a CF3 Sgroup/alias) { throw new Exception(ex.Message, ex); } //{ // try // try to simplify the molfile so that InChI can handle it // { // //if (Lex.IsUndefined(molfile)) throw ex; // string molfile2 = SimplifyMolfileForInChIGeneration(molile); // mol = CdkMol.MolfileToAtomContainer(molfile2); // mol = CdkMol.AtomContainerToSmilesAndBack(mol, out molSmiles); // ig = igf.getInChIGenerator(mol); // } // catch (Exception ex2) // { // throw new Exception(ex2.Message, ex); // } //} if (!IsAcceptableInchiStatus(ig)) { string errMsg = "InChI generation " + ig.getReturnStatus() + ": " + ig.getMessage(); molFile = CdkMol.AtomContainerToMolfile(mol); // debug throw new Exception(errMsg); } // Populate the UniChem object UniChemData icd = new UniChemData(); //icd.Molfile = molfile; icd.AtomContainer = mol; icd.InChIString = ig.getInchi(); icd.InChIKey = ig.getInchiKey(); icd.CanonSmiles = molSmiles; // Build and store fingerprint mol = CdkMol.InChIToAtomContainer(icd.InChIString); //int hydRemovedCnt = CdkMol.RemoveHydrogensBondedToPositiveNitrogens(mol); mol = CdkMol.RemoveIsotopesStereoExplicitHydrogens(mol); // additional normalization for fingerprint BitSetFingerprint fp = // generate a fingerprint CdkFingerprint.BuildBitSetFingerprint(mol, FingerprintType.MACCS, -1, -1); icd.Fingerprint = fp; if (ConnectivityChecker.isConnected(mol)) { return(icd); // single fragment } //string mf = CdkMol.GetMolecularFormula(mol); //AtomContainerSet acs = (AtomContainerSet)ConnectivityChecker.partitionIntoMolecules(mol); List <IAtomContainer> frags = CdkMol.FragmentMolecule(mol, true); // get fragments filtering out small and common frags for (fi = 0; fi < frags.Count; fi++) { mol2 = frags[fi]; int atomCnt = mol2.getAtomCount(); if (atomCnt <= 1) { continue; } try { mol2 = CdkMol.AtomContainerToSmilesAndBack(mol2, out fragSmiles); } catch (Exception ex) { AtomContainerToSmilesAndBackErrorCount++; // just count error and ignore } ig = igf.getInChIGenerator(mol2); if (!IsAcceptableInchiStatus(ig)) { continue; } string childInChIString = ig.getInchi(); string childInChIKey = ig.getInchiKey(); string childFIKHB = UniChemUtil.GetFIKHB(childInChIKey); mol2 = CdkMol.InChIToAtomContainer(childInChIString); // convert from inchi mol2 = CdkMol.RemoveIsotopesStereoExplicitHydrogens(mol2); // additional normalization for fingerprint fp = // generate a fingerprint for the fragment CdkFingerprint.BuildBitSetFingerprint(mol2, FingerprintType.MACCS, -1, -1); for (ci = 0; ci < icd.Children.Count; ci++) // see if a dup child { if (icd.Children[ci].ChildFIKHB == childFIKHB) { break; } } if (ci < icd.Children.Count) { continue; // skip if dup } UniChemFIKHBHierarchy icdChild = new UniChemFIKHBHierarchy(); icdChild.ParentFIKHB = icd.GetFIKHB(); icdChild.ChildFIKHB = childFIKHB; icdChild.InChIString = childInChIString; icdChild.CanonSmiles = fragSmiles; icdChild.Fingerprint = fp; icd.Children.Add(icdChild); } return(icd); }