Anonymise the provided container to single-bonded carbon atoms. No
information other then the connectivity from the original container is
retrained.

@param src an atom container
@return anonymised container
502659
public static IAtomContainer anonymise(IAtomContainer src) {

        IChemObjectBuilder builder = src.getBuilder();

        IAtom[] atoms = new IAtom[src.getAtomCount()];
        IBond[] bonds = new IBond[src.getBondCount()];

        for (int i = 0; i < atoms.length; i++) {
            atoms[i] = builder.newAtom();
            atoms[i].setAtomicNumber(6);
            atoms[i].setSymbol("C");
            atoms[i].setImplicitHydrogenCount(0);
            IAtom srcAtom = src.getAtom(i);
            if (srcAtom.getPoint2d() != null)
                atoms[i].setPoint2d(new Point2d(srcAtom.getPoint2d()));
            if (srcAtom.getPoint3d() != null)
                atoms[i].setPoint3d(new Point3d(srcAtom.getPoint3d()));
        }
        for (int i = 0; i < bonds.length; i++) {
            IBond bond = src.getBond(i);
            int u = src.indexOf(bond.getBegin());
            int v = src.indexOf(bond.getEnd());
            bonds[i] = builder.newInstance(IBond.class, atoms[u], atoms[v]);
        }

        IAtomContainer dest = builder.newInstance(IAtomContainer.class, 0, 0, 0, 0);
        dest.setAtoms(atoms);
        dest.setBonds(bonds);
        return dest;
    }
322141
private IAtomContainer getUnplacedAtoms(IAtom atom) {
        IAtomContainer unplacedAtoms = atom.getBuilder().newInstance(IAtomContainer.class);
        List bonds = molecule.getConnectedBondsList(atom);
        IAtom connectedAtom;
        for (int f = 0; f < bonds.size(); f++) {
            connectedAtom = ((IBond) bonds.get(f)).getOther(atom);
            if (!connectedAtom.getFlag(CDKConstants.ISPLACED)) {
                unplacedAtoms.addAtom(connectedAtom);
            }
        }
        return unplacedAtoms;
    }
1353011
public IAtomContainer proposeStructure() {
        logger.debug("RandomGenerator->proposeStructure() Start");
        do {
            try {
                trial = molecule.clone();
            } catch (CloneNotSupportedException e) {
                throw new IllegalStateException("Could not clone IAtomContainer!" + e.getMessage());
            }
            mutate(trial);
            if (logger.isDebugEnabled()) {
                String s = "BondCounts:    ";
                for (int f = 0; f < trial.getAtomCount(); f++) {
                    s += trial.getConnectedBondsCount(trial.getAtom(f)) + " ";
                }
                logger.debug(s);
                s = "BondOrderSums: ";
                for (int f = 0; f < trial.getAtomCount(); f++) {
                    s += trial.getBondOrderSum(trial.getAtom(f)) + " ";
                }
                logger.debug(s);
            }
        } while (trial == null || !ConnectivityChecker.isConnected(trial));
        proposedStructure = trial;

        return proposedStructure;
    }
827879
public static Object deepCopy(Object src) throws InstantiationException, IllegalAccessException
	{
		Class<?> clazz = src.getClass();

		// Just check if the object is mutable.
		// We assume the object that is final is likely immutable. 
		// It's true for String, Integer and other data types.
		if(Modifier.isFinal(clazz.getModifiers()))
		{
          return src; 
		}

		Object dst = clazz.newInstance();
		if(src instanceof Calendar)
		{
			((Calendar)dst).setTimeInMillis(((Calendar)src).getTimeInMillis());
			return dst;
		}
		
		Field[] fields = clazz.getFields();
		for(int i=0; i<fields.length; i++)
		{
			Object fObj = fields[i].get(src);
			if(fObj == null)
			{
				continue;
			}
			Class<?> fRealType = fObj.getClass();
			if((!fRealType.isPrimitive()) 
			  || (!fRealType.isEnum())
			  || fRealType.getPackage() != JAVA_LANG_PKG)
			{
				if(fRealType.isArray())
				{
					Object[] items = (Object[]) fObj;
					fObj = Array.newInstance(fRealType.getComponentType(), items.length);
					for(int j=0; j<items.length; j++)
					{
						Array.set(fObj, j, deepCopy(items[j]));
					}
				}
				else
				{
					fObj = deepCopy(fObj);
				}
			}
			fields[i].set(dst, fObj);
		}
		
		return dst;
	}
891797
public IAtomContainer getUnsetAtomsInAtomContainer(IAtom atom, IAtomContainer ac) {
        List atoms = ac.getConnectedAtomsList(atom);
        IAtomContainer connectedAtoms = atom.getBuilder().newInstance(IAtomContainer.class);
        for (int i = 0; i < atoms.size(); i++) {
            IAtom curAtom = (IAtom) atoms.get(i);
            if (!curAtom.getFlag(CDKConstants.ISPLACED)) {//&& atoms[i].getPoint3d() == null) {
                connectedAtoms.addAtom(curAtom);
            }
        }
        return connectedAtoms;
    }
942037
public static IAtomContainer createNewMolecule(IChemModel chemModel) {
        // Add a new molecule either the set of molecules
        IAtomContainer molecule = chemModel.getBuilder().newInstance(IAtomContainer.class);
        if (chemModel.getMoleculeSet() != null) {
            IAtomContainerSet moleculeSet = chemModel.getMoleculeSet();
            for (int i = 0; i < moleculeSet.getAtomContainerCount(); i++) {
                if (moleculeSet.getAtomContainer(i).getAtomCount() == 0) {
                    moleculeSet.removeAtomContainer(i);
                    i--;
                }
            }
            moleculeSet.addAtomContainer(molecule);
        } else {
            IAtomContainerSet moleculeSet = chemModel.getBuilder().newInstance(IAtomContainerSet.class);
            moleculeSet.addAtomContainer(molecule);
            chemModel.setMoleculeSet(moleculeSet);
        }
        return molecule;
    }
19471
private IAtomContainer connectAtoms(String inputInchi, IAtomContainer inputMolecule,
            Map<Integer, IAtom> inchiAtomsByPosition) throws CDKException {
        String inchi = inputInchi;
        inchi = inchi.substring(inchi.indexOf('/') + 1);
        inchi = inchi.substring(inchi.indexOf('/') + 1);
        String connections = inchi.substring(1, inchi.indexOf('/'));
        Pattern connectionPattern = Pattern.compile("(-|\\(|\\)|,|([0-9])*)");
        Matcher match = connectionPattern.matcher(connections);
        Stack<IAtom> atomStack = new Stack<IAtom>();
        IAtomContainer inchiMolGraph = inputMolecule.getBuilder().newInstance(IAtomContainer.class);
        boolean pop = false;
        boolean push = true;
        while (match.find()) {
            String group = match.group();
            push = true;
            if (!group.isEmpty()) {
                if (group.matches("[0-9]*")) {
                    IAtom atom = inchiAtomsByPosition.get(Integer.valueOf(group));
                    if (!inchiMolGraph.contains(atom)) inchiMolGraph.addAtom(atom);
                    IAtom prevAtom = null;
                    if (atomStack.size() != 0) {
                        if (pop) {
                            prevAtom = atomStack.pop();
                        } else {
                            prevAtom = atomStack.get(atomStack.size() - 1);
                        }
                        IBond bond = inputMolecule.getBuilder().newInstance(IBond.class, prevAtom, atom,
                                IBond.Order.SINGLE);
                        inchiMolGraph.addBond(bond);
                    }
                    if (push) {
                        atomStack.push(atom);
                    }
                } else if (group.equals("-")) {
                    pop = true;
                    push = true;
                } else if (group.equals(",")) {
                    atomStack.pop();
                    pop = false;
                    push = false;
                } else if (group.equals("(")) {
                    pop = false;
                    push = true;
                } else if (group.equals(")")) {
                    atomStack.pop();
                    pop = true;
                    push = true;
                } else {
                    throw new CDKException("Unexpected token " + group + " in connection table encountered.");
                }
            }
        }
        //put any unconnected atoms in the output as well
        for (IAtom at : inchiAtomsByPosition.values()) {
            if (!inchiMolGraph.contains(at)) inchiMolGraph.addAtom(at);
        }
        return inchiMolGraph;
    }
345542
public AtomHashGenerator atomic() {

        if (depth < 0) throw new IllegalArgumentException("no depth specified, use .depth(int)");

        List<AtomEncoder> encoders = new ArrayList<AtomEncoder>();

        // set is ordered
        for (AtomEncoder encoder : encoderSet) {
            encoders.add(encoder);
        }
        encoders.addAll(this.customEncoders);

        // check if suppression of atoms is wanted - if not use a default value
        // we also use the 'Basic' generator (see below)
        boolean suppress = suppression != AtomSuppression.unsuppressed();

        AtomEncoder encoder = new ConjugatedAtomEncoder(encoders);
        SeedGenerator seeds = new SeedGenerator(encoder, suppression);

        AbstractAtomHashGenerator simple = suppress ? new SuppressedAtomHashGenerator(seeds, new Xorshift(),
                makeStereoEncoderFactory(), suppression, depth) : new BasicAtomHashGenerator(seeds, new Xorshift(),
                makeStereoEncoderFactory(), depth);

        // if there is a finder for checking equivalent vertices then the user
        // wants to 'perturb' the hashed
        if (equivSetFinder != null) {
            return new PerturbedAtomHashGenerator(seeds, simple, new Xorshift(), makeStereoEncoderFactory(),
                    equivSetFinder, suppression);
        } else {
            // no equivalence set finder - just use the simple hash
            return simple;
        }
    }
1125206
public static IAtomContainer project(List<CDKRMap> rMapList, IAtomContainer graph, int key) {
        IAtomContainer atomContainer = graph.getBuilder().newInstance(IAtomContainer.class);

        Map<IAtom, IAtom> table = new HashMap<IAtom, IAtom>();
        IAtom atom1;
        IAtom atom2;
        IAtom atom;
        IBond bond;

        for (Iterator<CDKRMap> i = rMapList.iterator(); i.hasNext();) {
            CDKRMap rMap = i.next();
            if (key == CDKMCS.ID1) {
                bond = graph.getBond(rMap.getId1());
            } else {
                bond = graph.getBond(rMap.getId2());
            }

            atom = bond.getBegin();
            atom1 = table.get(atom);

            if (atom1 == null) {
                try {
                    atom1 = (IAtom) atom.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                atomContainer.addAtom(atom1);
                table.put(atom, atom1);
            }

            atom = bond.getEnd();
            atom2 = table.get(atom);

            if (atom2 == null) {
                try {
                    atom2 = (IAtom) atom.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                atomContainer.addAtom(atom2);
                table.put(atom, atom2);
            }
            IBond newBond = graph.getBuilder().newInstance(IBond.class, atom1, atom2, bond.getOrder());
            newBond.setFlag(CDKConstants.ISAROMATIC, bond.getFlag(CDKConstants.ISAROMATIC));
            atomContainer.addBond(newBond);
        }
        return atomContainer;
    }
1138899
public IAtomContainer fixAromaticBondOrders(IAtomContainer atomContainer) throws CDKException {

        // preset all bond orders to single
        for (IBond bond : atomContainer.bonds()) {
            if (bond.isAromatic() && bond.getOrder() == IBond.Order.UNSET)
                bond.setOrder(IBond.Order.SINGLE);
        }

        // OK, we take advantage here from the fact that this class does not take
        // into account rings larger than 7 atoms. See fixAromaticBondOrders().
        IRingSet rs = allRingsFinder.findAllRings(atomContainer, 7);
        storeRingSystem(atomContainer, rs);

        IRingSet ringSet;

        // TODO remove rings with nonsp2 carbons(?) and rings larger than 7 atoms
        ringSet = removeExtraRings(atomContainer);

        if (ringSet == null) throw new CDKException("failure in AllRingsFinder.findAllRings");

        List<List<List<String>>> MasterList = new ArrayList<List<List<String>>>();

        //this.counter=0;// counter which keeps track of all current possibilities for placing double bonds

        this.FixPyridineNOxides(atomContainer, ringSet);

        for (int i = 0; i <= ringSet.getAtomContainerCount() - 1; i++) {

            IRing ring = (IRing) ringSet.getAtomContainer(i);

            // only takes into account rings up to 7 atoms... if that changes,
            // make sure to update the findAllRings() calls too!
            if (ring.getAtomCount() == 5) {
                fiveMemberedRingPossibilities(atomContainer, ring, MasterList);
            } else if (ring.getAtomCount() == 6) {
                sixMemberedRingPossibilities(atomContainer, ring, MasterList);
            } else if (ring.getAtomCount() == 7) {
                sevenMemberedRingPossibilities(atomContainer, ring, MasterList);
                //TODO- add code for all 7 membered aromatic ring possibilities not just 3 bonds
            } else {
                //TODO: what about other rings systems?
                logger.debug("Found ring of size: " + ring.getAtomCount());
            }
        }

        IAtomContainerSet som = atomContainer.getBuilder().newInstance(IAtomContainerSet.class);

        //		int number=1; // total number of possibilities
        //
        //		for (int ii=0;ii<=MasterList.size()-1;ii++) {
        //		ArrayList ringlist=(ArrayList)MasterList.get(ii);
        //		number*=ringlist.size();
        //		}
        //		logger.debug("number= "+number);

        int[] choices;

        //if (number> 1000000) return null;

        choices = new int[MasterList.size()];

        if (MasterList.size() > 0) {
            IAtomContainer iAtomContainer = loop(System.currentTimeMillis(), atomContainer, 0, MasterList, choices, som);
            if (iAtomContainer != null) return iAtomContainer;
        }

        int mincount = 99999999;

        int best = -1; // one with minimum number of bad atoms

        // minimize number of potentially bad nitrogens among AtomContainers in the set

        for (int i = 0; i <= som.getAtomContainerCount() - 1; i++) {

            IAtomContainer mol = som.getAtomContainer(i);

            ringSet = removeExtraRings(mol);

            if (ringSet == null) continue;

            int count = getBadCount(mol, ringSet);

            //logger.debug(i + "\t" + count);

            if (count < mincount) {
                mincount = count;
                best = i;
            }

        }

        if (som.getAtomContainerCount() > 0) return som.getAtomContainer(best);
        return atomContainer;
    }
288699
public static <T> T boxAllAs(Object src, Class<T> type) {
        return (T) boxAll(type, src, 0, -1);
    }
1145732
public IAtomContainer getCyclicFragmentsContainer() {
        IAtomContainer fragContainer = this.molecule.getBuilder().newInstance(IAtomContainer.class);
        IAtomContainer spt = getSpanningTree();

        for (int i = 0; i < totalEdgeCount; i++)
            if (!bondsInTree[i]) {
                IRing ring = getRing(spt, molecule.getBond(i));
                for (int b = 0; b < ring.getBondCount(); b++) {
                    IBond ringBond = ring.getBond(b);
                    if (!fragContainer.contains(ringBond)) {
                        for (int atomCount = 0; atomCount < ringBond.getAtomCount(); atomCount++) {
                            IAtom atom = ringBond.getAtom(atomCount);
                            if (!fragContainer.contains(atom)) {
                                atom.setFlag(CDKConstants.ISINRING, true);
                                fragContainer.addAtom(atom);
                            }
                        }
                        fragContainer.addBond(ringBond);
                    }
                }
            }
        return fragContainer;
    }
1358705
public Partition getAutomorphismPartition(IAtomContainer atomContainer) {
        setup(atomContainer);
        super.refine(refinable.getInitialPartition());
        return super.getAutomorphismPartition();
    }
375166
public static IAtomContainer makeDeepCopy(IAtomContainer container) {

        IAtomContainer newAtomContainer = DefaultChemObjectBuilder.getInstance().newInstance(IAtomContainer.class);

        int lonePairCount = container.getLonePairCount();
        int singleElectronCount = container.getSingleElectronCount();

        ILonePair[] lonePairs = new ILonePair[lonePairCount];
        ISingleElectron[] singleElectrons = new ISingleElectron[singleElectronCount];

        //      Deep copy of the Atoms
        IAtom[] atoms = copyAtoms(container, newAtomContainer);

        //      Deep copy of the bonds
        copyBonds(atoms, container, newAtomContainer);

        //      Deep copy of the LonePairs
        for (int index = 0; index < container.getLonePairCount(); index++) {

            if (container.getAtom(index).getSymbol().equalsIgnoreCase("R")) {
                lonePairs[index] = DefaultChemObjectBuilder.getInstance().newInstance(ILonePair.class,
                        container.getAtom(index));
            }
            newAtomContainer.addLonePair(lonePairs[index]);
        }

        for (int index = 0; index < container.getSingleElectronCount(); index++) {
            singleElectrons[index] = DefaultChemObjectBuilder.getInstance().newInstance(ISingleElectron.class,
                    container.getAtom(index));
            newAtomContainer.addSingleElectron(singleElectrons[index]);

        }
        newAtomContainer.addProperties(container.getProperties());
        newAtomContainer.setFlags(container.getFlags());

        newAtomContainer.setID(container.getID());

        newAtomContainer.notifyChanged();
        return newAtomContainer;

    }
938849
@Override
    public DescriptorValue calculate(IAtomContainer atomContainer) {
        DoubleArrayResult retval = new DoubleArrayResult();

        if (!GeometryUtil.has3DCoordinates(atomContainer)) {
            for (int i = 0; i < 29; i++)
                retval.add(Double.NaN);
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                    getDescriptorNames(), new CDKException("Molecule must have 3D coordinates"));
        }

        IAtomContainer container;
        try {
            container = (IAtomContainer) atomContainer.clone();
        } catch (CloneNotSupportedException e) {
            logger.debug("Error during clone");
            for (int i = 0; i < 29; i++)
                retval.add(Double.NaN);
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                    getDescriptorNames(), new CDKException("Error during clone" + e.getMessage()));
        }

        //        IsotopeFactory factory = null;
        //        try {
        //            factory = IsotopeFactory.getInstance(container.getNewBuilder());
        //        } catch (Exception e) {
        //            logger.debug(e);
        //        }

        GasteigerMarsiliPartialCharges peoe;
        try {
            peoe = new GasteigerMarsiliPartialCharges();
            peoe.assignGasteigerMarsiliSigmaPartialCharges(container, true);
        } catch (Exception e) {
            logger.debug("Error in assigning Gasteiger-Marsilli charges");
            for (int i = 0; i < 29; i++)
                retval.add(Double.NaN);
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                    getDescriptorNames(), new CDKException("Error in getting G-M charges"));
        }

        NumericalSurface surface;
        try {
            surface = new NumericalSurface(container);
            surface.calculateSurface();
        } catch (NullPointerException npe) {
            logger.debug("Error in surface area calculation");
            for (int i = 0; i < 29; i++)
                retval.add(Double.NaN);
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                    getDescriptorNames(), new CDKException("Error in surface area calculation"));
        }

        //double molecularWeight = mfa.getMass();
        double[] atomSurfaces = surface.getAllSurfaceAreas();
        double totalSA = surface.getTotalSurfaceArea();

        double ppsa1 = 0.0;
        double ppsa3 = 0.0;
        double pnsa1 = 0.0;
        double pnsa3 = 0.0;
        double totpcharge = 0.0;
        double totncharge = 0.0;
        for (int i = 0; i < container.getAtomCount(); i++) {
            if (container.getAtom(i).getCharge() > 0) {
                ppsa1 += atomSurfaces[i];
                ppsa3 += container.getAtom(i).getCharge() * atomSurfaces[i];
                totpcharge += container.getAtom(i).getCharge();
            } else {
                pnsa1 += atomSurfaces[i];
                pnsa3 += container.getAtom(i).getCharge() * atomSurfaces[i];
                totncharge += container.getAtom(i).getCharge();
            }
        }

        double ppsa2 = ppsa1 * totpcharge;
        double pnsa2 = pnsa1 * totncharge;

        // fractional +ve & -ve SA
        double fpsa1 = ppsa1 / totalSA;
        double fpsa2 = ppsa2 / totalSA;
        double fpsa3 = ppsa3 / totalSA;
        double fnsa1 = pnsa1 / totalSA;
        double fnsa2 = pnsa2 / totalSA;
        double fnsa3 = pnsa3 / totalSA;

        // surface wtd +ve & -ve SA
        double wpsa1 = ppsa1 * totalSA / 1000;
        double wpsa2 = ppsa2 * totalSA / 1000;
        double wpsa3 = ppsa3 * totalSA / 1000;
        double wnsa1 = pnsa1 * totalSA / 1000;
        double wnsa2 = pnsa2 * totalSA / 1000;
        double wnsa3 = pnsa3 * totalSA / 1000;

        // hydrophobic and poalr surface area
        double phobic = 0.0;
        double polar = 0.0;
        for (int i = 0; i < container.getAtomCount(); i++) {
            if (Math.abs(container.getAtom(i).getCharge()) < 0.2) {
                phobic += atomSurfaces[i];
            } else {
                polar += atomSurfaces[i];
            }
        }
        double thsa = phobic;
        double tpsa = polar;
        double rhsa = phobic / totalSA;
        double rpsa = polar / totalSA;

        // differential +ve & -ve SA
        double dpsa1 = ppsa1 - pnsa1;
        double dpsa2 = ppsa2 - pnsa2;
        double dpsa3 = ppsa3 - pnsa3;

        double maxpcharge = 0.0;
        double maxncharge = 0.0;
        int pidx = 0;
        int nidx = 0;
        for (int i = 0; i < container.getAtomCount(); i++) {
            double charge = container.getAtom(i).getCharge();
            if (charge > maxpcharge) {
                maxpcharge = charge;
                pidx = i;
            }
            if (charge < maxncharge) {
                maxncharge = charge;
                nidx = i;
            }
        }

        // relative descriptors
        double rpcg = maxpcharge / totpcharge;
        double rncg = maxncharge / totncharge;
        double rpcs = atomSurfaces[pidx] * rpcg;
        double rncs = atomSurfaces[nidx] * rncg;

        // fill in the values
        retval.add(ppsa1);
        retval.add(ppsa2);
        retval.add(ppsa3);
        retval.add(pnsa1);
        retval.add(pnsa2);
        retval.add(pnsa3);

        retval.add(dpsa1);
        retval.add(dpsa2);
        retval.add(dpsa3);

        retval.add(fpsa1);
        retval.add(fpsa2);
        retval.add(fpsa3);
        retval.add(fnsa1);
        retval.add(fnsa2);
        retval.add(fnsa3);

        retval.add(wpsa1);
        retval.add(wpsa2);
        retval.add(wpsa3);
        retval.add(wnsa1);
        retval.add(wnsa2);
        retval.add(wnsa3);

        retval.add(rpcg);
        retval.add(rncg);
        retval.add(rpcs);
        retval.add(rncs);

        retval.add(thsa);
        retval.add(tpsa);
        retval.add(rhsa);
        retval.add(rpsa);

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                getDescriptorNames());
    }
607453
public static String escape(String src) {
        // first pass to determine the length of the buffer so we only allocate once
        int length = 0;
        for (int i = 0; i < src.length(); i++) {
            char c = src.charAt(i);
            String escape = getEscape(c);
            if (escape != null) {
                length += escape.length();
            } else {
                length += 1;
            }
        }

        // skip copy if no escaping is needed
        if (length == src.length()) {
            return src;
        }

        // second pass to build the escaped string
        StringBuilder buf = new StringBuilder(length);
        for (int i = 0; i < src.length(); i++) {
            char c = src.charAt(i);
            String escape = getEscape(c);
            if (escape != null) {
                buf.append(escape);
            } else {
                buf.append(c);
            }
        }
        return buf.toString();
    }
534844
public void unsaturate(IAtomContainer atomContainer) {
        for (IBond bond : atomContainer.bonds())
            bond.setOrder(Order.SINGLE);
    }