/** * Check for the other atoms nearby in the fragment. * * @param candidateOxygen * the candidate oxygen atom * @param frag * the frag * @param proton * the proton * * @return true, if successful * @throws CloneNotSupportedException * @throws CDKException */ private IAtomContainer checkForCompleteNeutralLoss(IAtomContainer frag, IAtom candidateAtom, double neutralLossMass) { IAtomContainer ret = new AtomContainer(); // create a copy from the original fragment var part = new List<IBond>(); part = traverse(frag, candidateAtom, part); var fragCopy = makeAtomContainer(candidateAtom, part); // set properties again var properties = frag.getProperties(); fragCopy.setProperties(properties); // now get the other atoms from the neutral loss var atomsToFind = new List<string>(); var addHydrogen = false; // one hydrogen is lost with the neutral loss if (neutralLoss[neutralLossMass].HydrogenDifference == -1) { foreach (var isotope in neutralLoss[neutralLossMass].ElementalComposition.isotopes().ToWindowsEnumerable<IIsotope>()) { var c = neutralLoss[neutralLossMass].ElementalComposition.getIsotopeCount(isotope); for (var i = 0; i < c; i++) { atomsToFind.Add(isotope.getSymbol()); } } } else { foreach (var isotope in neutralLoss[neutralLossMass].TopoFragment.isotopes().ToWindowsEnumerable<IIsotope>()) { var c = neutralLoss[neutralLossMass].ElementalComposition.getIsotopeCount(isotope); for (var i = 0; i < c; i++) { atomsToFind.Add(isotope.getSymbol()); } addHydrogen = true; } } // at most 2 bonds between the oxygen and other atoms (at most 1 H and 2 // C) var count = neutralLoss[neutralLossMass].Distance; // list storing all atoms to be removed later on if complete neutral // loss was found var foundAtoms = new List<IAtom>(); // list storing all bonds to remove var foundBonds = new List<IBond>(); // list storing all bonds already checked var checkedBonds = new List<IBond>(); // list storing all checked atoms var checkedAtoms = new List<IAtom>(); // queue storing all bonds to check for a particular distance var bondQueue = new List<IBond>(); // List storing all bonds to be checked for the next distance var bondsFurther = new List<IBond>(); // get all bonds from this atom distance = 1 var bondList = fragCopy.getConnectedBondsList(candidateAtom); foreach (var bond in bondList.ToWindowsEnumerable<IBond>()) { if (bond != null) { bondQueue.Add(bond); } } var hydrogenStartAtom = neutralLoss[neutralLossMass].HydrogenOnStartAtom; var firstBonds = true; while (count > 0) { IBond currentBond = null; if (bondQueue.Count > 0) { currentBond = bondQueue[bondQueue.Count - 1]; bondQueue.RemoveAt(bondQueue.Count - 1); } // check for already tried bonds if (checkedBonds.Contains(currentBond) && currentBond != null) { continue; } else if (currentBond != null) { checkedBonds.Add(currentBond); } if (currentBond != null) { foreach (var atom in currentBond.atoms().ToWindowsEnumerable<IAtom>()) { // check for already tried atoms if (checkedAtoms.Contains(atom)) { continue; } else { checkedAtoms.Add(atom); } if (firstBonds && atom.getSymbol().Equals("H")) { hydrogenStartAtom--; } // thats the starting atom if (atom.getSymbol().Equals(candidateAtom.getSymbol())) { var removed = atomsToFind.Remove(candidateAtom.getSymbol()); if (removed) { foundAtoms.Add(atom); // remove bond if (!foundBonds.Contains(currentBond)) { foundBonds.Add(currentBond); } } // this bond has to be removed else if (!foundBonds.Contains(currentBond) && atomsToFind.Contains(atom.getSymbol())) { foundBonds.Add(currentBond); } continue; } // found atom...remove it from the atoms to find list // do not remove atoms from ring if (atomsToFind.Contains(atom.getSymbol()) && !allRings.contains(atom) && atomsToFind.Count > 0) { var removed = atomsToFind.Remove(atom.getSymbol()); if (removed) { foundAtoms.Add(atom); } else { continue; } if (!foundBonds.Contains(currentBond)) { foundBonds.Add(currentBond); } continue; } // only walk along C-Atoms! if (!atom.getSymbol().Equals("C")) { continue; } // get new bonds var bondsToAddTemp = fragCopy.getConnectedBondsList(atom); foreach (var bond in bondsToAddTemp.ToWindowsEnumerable<IBond>()) { if (bond != null) { bondsFurther.Add(bond); } } } } // break condition if (currentBond == null && bondQueue.Count == 0 && bondsFurther.Count == 0) { break; } // now check if the queue is empty...checked all bonds in this // distance if (bondQueue.Count == 0) { count--; // set new queue data foreach (var bond in bondsFurther) { if (bond != null) { bondQueue.Add(bond); } } // reinitialize bondsFurther = new List<IBond>(); // the initially connected bonds are all checked! firstBonds = false; } } // found complete neutral loss if (atomsToFind.Count == 0) { foreach (var atom in foundAtoms) { fragCopy.removeAtomAndConnectedElectronContainers(atom); } // TODO add hydrogen somewhere if (addHydrogen) { var props = fragCopy.getProperties(); props.put("hydrogenAddFromNL", "1"); fragCopy.setProperties(props); } // add fragment to return if enough H were connected and fragment is // still connected if (hydrogenStartAtom <= 0) { ret.add(fragCopy); } } return ret; }