An average of all 3D bond length values is produced, using point3ds in atoms.
Atom's with no coordinates are disregarded.

@param  container  The AtomContainer for which the average bond length is to be
calculated
@return     the average bond length
434232
public static double getBondLengthAverage3D(IAtomContainer container) {
        double bondLengthSum = 0;
        int bondCounter = 0;
        for (IBond bond : container.bonds()) {
            IAtom atom1 = bond.getBegin();
            IAtom atom2 = bond.getEnd();
            if (atom1.getPoint3d() != null && atom2.getPoint3d() != null) {
                bondCounter++;
                bondLengthSum += atom1.getPoint3d().distance(atom2.getPoint3d());
            }
        }
        return bondLengthSum / bondCounter;
    }
1319384
public double getBondLength() {
        PharmacophoreAtom atom1 = PharmacophoreAtom.get(getAtom(0));
        PharmacophoreAtom atom2 = PharmacophoreAtom.get(getAtom(1));
        return atom1.getPoint3d().distance(atom2.getPoint3d());
    }
635231
@Override
    public DescriptorValue calculate(IAtomContainer container) {
        IAtomContainer local = AtomContainerManipulator.removeHydrogens(container);

        int natom = local.getAtomCount();
        int[][] admat = AdjacencyMatrix.getMatrix(local);
        int[][] distmat = PathTools.computeFloydAPSP(admat);

        int eccenindex = 0;
        for (int i = 0; i < natom; i++) {
            int max = -1;
            for (int j = 0; j < natom; j++) {
                if (distmat[i][j] > max) max = distmat[i][j];
            }
            int degree = local.getConnectedBondsCount(i);
            eccenindex += max * degree;
        }
        IntegerResult retval = new IntegerResult(eccenindex);
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                getDescriptorNames(), null);
    }
821827
@Override
    public DescriptorValue calculate(IAtomContainer container) {

        double bpol = 0;
        int atomicNumber0;
        int atomicNumber1;
        double difference;
        try {
            IsotopeFactory ifac = Isotopes.getInstance();
            IElement element0;
            IElement element1;

            String symbol0;
            String symbol1;
            for (IBond bond : container.bonds()) {
                IAtom atom0 = bond.getBegin();
                IAtom atom1 = bond.getEnd();

                symbol0 = atom0.getSymbol();
                symbol1 = atom1.getSymbol();
                element0 = ifac.getElement(symbol0);
                element1 = ifac.getElement(symbol1);
                atomicNumber0 = element0.getAtomicNumber();
                atomicNumber1 = element1.getAtomicNumber();
                difference = polarizabilities[atomicNumber0] - polarizabilities[atomicNumber1];
                bpol += Math.abs(difference);
            }

            // after going through the bonds, we go through the atoms and see if they have
            // implicit H's and if so, consider the associated "implicit" bonds. Note that
            // if the count is UNSET, we assume it is 0
            for (IAtom atom : container.atoms()) {
                int impH = atom.getImplicitHydrogenCount() == CDKConstants.UNSET ? 0 : atom.getImplicitHydrogenCount();
                IElement elem = ifac.getElement(atom.getSymbol());
                int atnum = elem.getAtomicNumber();
                difference = Math.abs(polarizabilities[atnum] - polarizabilities[1]) * impH;
                bpol += difference;
            }
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(),
                    new DoubleResult(bpol), getDescriptorNames());
        } catch (Exception ex1) {
            logger.debug(ex1);
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new DoubleResult(
                    Double.NaN), getDescriptorNames(), new CDKException("Problems with IsotopeFactory due to "
                    + ex1.toString(), ex1));
        }
    }
394538
private static int countAlignedBonds(IAtomContainer mol) {
        final double ref = Math.toRadians(30);
        final double diff = Math.toRadians(1);
        int count = 0;
        for (IBond bond : mol.bonds()) {
            Point2d beg = bond.getBegin().getPoint2d();
            Point2d end = bond.getEnd().getPoint2d();
            if (beg.x > end.x) {
                Point2d tmp = beg;
                beg = end;
                end = tmp;
            }
            Vector2d vec = new Vector2d(end.x - beg.x, end.y - beg.y);
            double angle = Math.atan2(vec.y, vec.x);

            if (Math.abs(angle) - ref < diff) {
                count++;
            }
        }
        return count;
    }
277936
public double[] calculate(IAtomContainer container, IAtom atom) {
        int length = (int) ((cutoff - startCutoff) / resolution) + 1;
        logger.debug("Creating RDF of length ", length);

        // the next we need for Gaussian smoothing
        int binsToFillOnEachSide = (int) (peakWidth * 3.0 / resolution);
        double sigmaSquare = Math.pow(peakWidth, 2.0);
        // factors is only half a Gaussian, taking advantage of being symmetrical!
        double[] factors = new double[binsToFillOnEachSide];
        double totalArea = 0.0;
        if (factors.length > 0) {
            factors[0] = 1;
            for (int binCounter = 1; binCounter < factors.length; binCounter++) {
                double height = Math.exp(-1.0 * (Math.pow(((double) binCounter) * resolution, 2.0)) / sigmaSquare);
                factors[binCounter] = height;
                totalArea += height;
            }
            // normalize the Gaussian to unit area
            for (int binCounter = 0; binCounter < factors.length; binCounter++) {
                factors[binCounter] = factors[binCounter] / totalArea;
            }
        }

        // this we need always
        double[] rdf = new double[length];
        double distance = 0.0;
        int index = 0;

        Point3d atomPoint = atom.getPoint3d();
        Iterator<IAtom> atomsInContainer = container.atoms().iterator();
        while (atomsInContainer.hasNext()) {
            IAtom atomInContainer = (IAtom) atomsInContainer.next();
            if (atomInContainer.equals(atom)) continue; // don't include the central atom
            distance = atomPoint.distance(atomInContainer.getPoint3d());
            index = (int) ((distance - startCutoff) / this.resolution);
            double weight = 1.0;
            if (weightFunction != null) {
                weight = weightFunction.calculate(atom, atomInContainer);
            }
            if (factors.length > 0) {
                // apply Gaussian smoothing
                rdf[index] += weight * factors[0];
                for (int binCounter = 1; binCounter < factors.length; binCounter++) {
                    double diff = weight * factors[binCounter];
                    if ((index - binCounter) >= 0) {
                        rdf[index - binCounter] += diff;
                    }
                    if ((index + binCounter) < length) {
                        rdf[index + binCounter] += diff;
                    }
                }
            } else {
                rdf[index] += weight; // unweighted
            }
        }
        return rdf;
    }
1168875
@Override
    public DescriptorValue calculate(IAtomContainer atomContainer) {
        wienerNumbers = new DoubleArrayResult(2);
        double wienerPathNumber = 0; //wienerPath
        double wienerPolarityNumber = 0; //wienerPol

        matr = ConnectionMatrix.getMatrix(AtomContainerManipulator.removeHydrogens(atomContainer));
        int[][] distances = PathTools.computeFloydAPSP(matr);

        int partial;
        for (int i = 0; i < distances.length; i++) {
            for (int j = 0; j < distances.length; j++) {
                partial = distances[i][j];
                wienerPathNumber += partial;
                if (partial == 3) {
                    wienerPolarityNumber += 1;
                }
            }
        }
        wienerPathNumber = wienerPathNumber / 2;
        wienerPolarityNumber = wienerPolarityNumber / 2;

        wienerNumbers.add(wienerPathNumber);
        wienerNumbers.add(wienerPolarityNumber);
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), wienerNumbers,
                getDescriptorNames());
    }
566148
private void buildSpanningTree(IAtomContainer atomContainer) {
        disconnected = false;
        molecule = atomContainer;

        totalVertexCount = atomContainer.getAtomCount();
        totalEdgeCount = atomContainer.getBondCount();

        sptSize = 0;
        edrSize = 0;
        fastFindInit(totalVertexCount);
        for (int i = 0; i < totalVertexCount; i++) {
            (atomContainer.getAtom(i)).setProperty(ATOM_NUMBER, Integer.toString(i + 1));
        }
        IBond bond;
        int vertex1, vertex2;
        bondsInTree = new boolean[totalEdgeCount];

        for (int b = 0; b < totalEdgeCount; b++) {
            bondsInTree[b] = false;
            bond = atomContainer.getBond(b);
            vertex1 = Integer.parseInt((bond.getBegin()).getProperty(ATOM_NUMBER).toString());
            vertex2 = Integer.parseInt((bond.getEnd()).getProperty(ATOM_NUMBER).toString());
            //this below is a little bit  slower
            //v1 = atomContainer.indexOf(bond.getAtomAt(0))+1;
            //v2 = atomContainer.indexOf(bond.getAtomAt(1))+1;
            if (fastfind(vertex1, vertex2, true)) {
                bondsInTree[b] = true;
                sptSize++;
                //logger.debug("ST : includes bond between atoms "+v1+","+v2);
            }
            if (sptSize >= (totalVertexCount - 1)) break;

        }
        // if atomcontainer is connected then the number of bonds in the spanning tree = (No atoms-1)
        //i.e.  edgesRings = new Bond[E-V+1];
        //but to hold all bonds if atomContainer was disconnected then  edgesRings = new Bond[E-sptSize];
        if (sptSize != (totalVertexCount - 1)) disconnected = true;
        for (int b = 0; b < totalEdgeCount; b++)
            if (!bondsInTree[b]) {
                //			edgesRings[edrSize] = atomContainer.getBondAt(b);
                edrSize++;
            }
        cb = new int[edrSize][totalEdgeCount];
        for (int i = 0; i < edrSize; i++)
            for (int a = 0; a < totalEdgeCount; a++)
                cb[i][a] = 0;

        // remove ATOM_NUMBER props again
        for (IAtom atom : atomContainer.atoms())
            atom.removeProperty(ATOM_NUMBER);
    }
827816
static IAtomContainer apply(IAtomContainer container) {

        int n = container.getAtomCount();

        int[] valences = new int[n];

        Map<IAtom, Integer> atomToIndex = Maps.newHashMapWithExpectedSize(n);
        for (IAtom atom : container.atoms())
            atomToIndex.put(atom, atomToIndex.size());

        // compute the bond order sums
        for (IBond bond : container.bonds()) {
            int u = atomToIndex.get(bond.getBegin());
            int v = atomToIndex.get(bond.getEnd());

            int bondOrder = bond.getOrder().numeric();

            valences[u] += bondOrder;
            valences[v] += bondOrder;
        }

        for (int i = 0; i < n; i++) {

            IAtom atom = container.getAtom(i);
            Integer charge = atom.getFormalCharge();
            Integer element = atom.getAtomicNumber();

            if (element == null) continue;

            // unset = 0 in this case
            charge = charge == null ? 0 : charge;

            int explicit = valences[i];

            // if there was a valence read from the mol file use that otherwise
            // use the default value from the valence model to set the correct
            // number of implied hydrogens
            if (atom.getValency() != null) {
                atom.setImplicitHydrogenCount(atom.getValency() - explicit);
            } else {
                int implicit = implicitValence(element, charge, valences[i]);
                atom.setImplicitHydrogenCount(implicit - explicit);
                atom.setValency(implicit);
            }
        }

        return container;
    }
740035
private int getConnectivity(IAtom atom, IAtomContainer container) {
        int connectivity = 0;
        for (IBond bond : container.bonds()) {
            if (bond.contains(atom)) {
                switch (bond.getOrder()) {
                    case SINGLE:
                        connectivity++;
                        break;
                    case DOUBLE:
                        connectivity += 2;
                        break;
                    case TRIPLE:
                        connectivity += 3;
                        break;
                    case QUADRUPLE:
                        connectivity += 4;
                        break;
                    default:
                        connectivity += 10;
                }
            }
        }
        return connectivity;
    }
675992
public static int[][] getMatrix(IAtomContainer container) {
        IBond bond;
        int indexAtom1;
        int indexAtom2;
        int[][] conMat = new int[container.getAtomCount()][container.getAtomCount()];
        for (int f = 0; f < container.getBondCount(); f++) {
            bond = container.getBond(f);
            indexAtom1 = container.indexOf(bond.getBegin());
            indexAtom2 = container.indexOf(bond.getEnd());
            conMat[indexAtom1][indexAtom2] = 1;
            conMat[indexAtom2][indexAtom1] = 1;
        }
        return conMat;
    }
1269548
public static IAtomContainer makeDeepCopy(IAtomContainer container) {

        IAtomContainer newAtomContainer = container.getBuilder().newInstance(IAtomContainer.class);
        //      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")
                    || container.getAtom(index).getSymbol().equalsIgnoreCase("A")) {
                newAtomContainer.addLonePair(container.getBuilder().newInstance(ILonePair.class,
                        container.getAtom(index)));
            } else {
                newAtomContainer.addLonePair(index);
            }
        }

        for (int index = 0; index < container.getSingleElectronCount(); index++) {
            newAtomContainer.addSingleElectron(index);
        }
        newAtomContainer.addProperties(container.getProperties());
        newAtomContainer.setFlags(container.getFlags());
        newAtomContainer.setID(container.getID());
        newAtomContainer.notifyChanged();

        return newAtomContainer;
    }
1032256
@Override
    public DescriptorValue calculate(IAtomContainer container) {
        IAtomContainer local = AtomContainerManipulator.removeHydrogens(container);
        int natom = local.getAtomCount();
        DoubleArrayResult retval = new DoubleArrayResult();

        ArrayList<List<?>> pathList = new ArrayList<List<?>>();

        // unique paths
        for (int i = 0; i < natom - 1; i++) {
            IAtom a = local.getAtom(i);
            for (int j = i + 1; j < natom; j++) {
                IAtom b = local.getAtom(j);
                pathList.addAll(PathTools.getAllPaths(local, a, b));
            }
        }

        // heteroatoms
        double[] pathWts = getPathWeights(pathList, local);
        double mid = 0.0;
        for (double pathWt3 : pathWts)
            mid += pathWt3;
        mid += natom; // since we don't calculate paths of length 0 above

        retval.add(mid);
        retval.add(mid / (double) natom);

        pathList.clear();
        int count = 0;
        for (int i = 0; i < natom; i++) {
            IAtom a = local.getAtom(i);
            if (a.getSymbol().equalsIgnoreCase("C")) continue;
            count++;
            for (int j = 0; j < natom; j++) {
                IAtom b = local.getAtom(j);
                if (a.equals(b)) continue;
                pathList.addAll(PathTools.getAllPaths(local, a, b));
            }
        }
        pathWts = getPathWeights(pathList, local);
        mid = 0.0;
        for (double pathWt2 : pathWts)
            mid += pathWt2;
        mid += count;
        retval.add(mid);

        // oxygens
        pathList.clear();
        count = 0;
        for (int i = 0; i < natom; i++) {
            IAtom a = local.getAtom(i);
            if (!a.getSymbol().equalsIgnoreCase("O")) continue;
            count++;
            for (int j = 0; j < natom; j++) {
                IAtom b = local.getAtom(j);
                if (a.equals(b)) continue;
                pathList.addAll(PathTools.getAllPaths(local, a, b));
            }
        }
        pathWts = getPathWeights(pathList, local);
        mid = 0.0;
        for (double pathWt1 : pathWts)
            mid += pathWt1;
        mid += count;
        retval.add(mid);

        // nitrogens
        pathList.clear();
        count = 0;
        for (int i = 0; i < natom; i++) {
            IAtom a = local.getAtom(i);
            if (!a.getSymbol().equalsIgnoreCase("N")) continue;
            count++;
            for (int j = 0; j < natom; j++) {
                IAtom b = local.getAtom(j);
                if (a.equals(b)) continue;
                pathList.addAll(PathTools.getAllPaths(local, a, b));
            }
        }
        pathWts = getPathWeights(pathList, local);
        mid = 0.0;
        for (double pathWt : pathWts)
            mid += pathWt;
        mid += count;
        retval.add(mid);

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                getDescriptorNames());
    }
428430
@Override
    public DescriptorValue calculate(IAtom atom, IAtomContainer container) {
        double value;

        try {
            int i = container.indexOf(atom);
            if (i < 0) throw new CDKException("atom was not a memeber of the provided container");

            // don't modify the original
            container = container.clone();
            atom = container.getAtom(i);

            AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(container);
            LonePairElectronChecker lpcheck = new LonePairElectronChecker();
            lpcheck.saturate(container);
        } catch (CDKException | CloneNotSupportedException e) {
            return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new DoubleResult(
                    Double.NaN), NAMES, null);
        }

        value = db.extractAffinity(container, atom);
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new DoubleResult(value),
                                   NAMES);

    }
654835
public static int getVertexCountAtDistance(IAtomContainer atomContainer, int distance) {
        int natom = atomContainer.getAtomCount();

        int[][] admat = AdjacencyMatrix.getMatrix(atomContainer);
        int[][] distanceMatrix = computeFloydAPSP(admat);

        int matches = 0;

        for (int i = 0; i < natom; i++) {
            for (int j = 0; j < natom; j++) {
                if (distanceMatrix[i][j] == distance) matches++;
            }
        }
        return matches / 2;
    }
1013232
@Override
    public DescriptorValue calculate(IAtomContainer container) {
        if (!GeometryUtil.has3DCoordinates(container))
            return getDummyDescriptorValue(new CDKException("Molecule must have 3D coordinates"));

        IAtomContainer clone;
        IsotopeFactory factory;
        try {
            clone = (IAtomContainer) container.clone();
            factory = Isotopes.getInstance();
            factory.configureAtoms(clone);
        } catch (CloneNotSupportedException | IOException e) {
            logger.debug(e);
            return getDummyDescriptorValue(e);
        }

        DoubleArrayResult retval = new DoubleArrayResult(7);

        double ccf = 1.000138;
        double eps = 1e-5;

        double[][] imat = new double[3][3];
        Point3d centerOfMass = GeometryUtil.get3DCentreOfMass(clone);

        double xdif;
        double ydif;
        double zdif;
        double xsq;
        double ysq;
        double zsq;
        for (int i = 0; i < clone.getAtomCount(); i++) {
            IAtom currentAtom = clone.getAtom(i);

            Double mass = factory.getMajorIsotope(currentAtom.getSymbol()).getExactMass();
            if (mass == null)
                mass = factory.getNaturalMass(currentAtom);

            xdif = currentAtom.getPoint3d().x - centerOfMass.x;
            ydif = currentAtom.getPoint3d().y - centerOfMass.y;
            zdif = currentAtom.getPoint3d().z - centerOfMass.z;
            xsq = xdif * xdif;
            ysq = ydif * ydif;
            zsq = zdif * zdif;

            imat[0][0] += mass * (ysq + zsq);
            imat[1][1] += mass * (xsq + zsq);
            imat[2][2] += mass * (xsq + ysq);

            imat[1][0] += -1 * mass * ydif * xdif;
            imat[0][1] = imat[1][0];

            imat[2][0] += -1 * mass * xdif * zdif;
            imat[0][2] = imat[2][0];

            imat[2][1] += -1 * mass * ydif * zdif;
            imat[1][2] = imat[2][1];
        }

        // diagonalize the MI tensor
        Matrix tmp = new Matrix(imat);
        EigenvalueDecomposition eigenDecomp = tmp.eig();
        double[] eval = eigenDecomp.getRealEigenvalues();

        retval.add(eval[2]);
        retval.add(eval[1]);
        retval.add(eval[0]);

        double etmp = eval[0];
        eval[0] = eval[2];
        eval[2] = etmp;

        if (Math.abs(eval[1]) > 1e-3)
            retval.add(eval[0] / eval[1]);
        else
            retval.add(1000);

        if (Math.abs(eval[2]) > 1e-3) {
            retval.add(eval[0] / eval[2]);
            retval.add(eval[1] / eval[2]);
        } else {
            retval.add(1000);
            retval.add(1000);
        }

        // finally get the radius of gyration
        double pri;
        IMolecularFormula formula = MolecularFormulaManipulator.getMolecularFormula(clone);
        if (Math.abs(eval[2]) > eps)
            pri = Math.pow(eval[0] * eval[1] * eval[2], 1.0 / 3.0);
        else
            pri = Math.sqrt(eval[0] * ccf / MolecularFormulaManipulator.getTotalExactMass(formula));
        retval.add(Math.sqrt(Math.PI * 2 * pri * ccf / MolecularFormulaManipulator.getTotalExactMass(formula)));

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), retval,
                getDescriptorNames());
    }
340793
@Override
    public DescriptorValue calculate(IAtomContainer container) {
        IRingSet rs;
        try {
            AllRingsFinder arf = new AllRingsFinder();
            rs = arf.findAllRings(container);
        } catch (Exception e) {
            return getDummyDescriptorValue(new CDKException("Could not find all rings: " + e.getMessage()));
        }

        String[] fragment = new String[container.getAtomCount()];
        EStateAtomTypeMatcher eStateMatcher = new EStateAtomTypeMatcher();
        eStateMatcher.setRingSet(rs);

        for (IAtomContainer ring : rs.atomContainers()) {
            boolean arom = true;
            for (IBond bond : ring.bonds()) {
                if (!bond.isAromatic()) {
                    arom = false;
                    break;
                }
            }
            ring.setFlag(CDKConstants.ISAROMATIC, arom);
        }

        for (int i = 0; i < container.getAtomCount(); i++) {
            IAtomType atomType = eStateMatcher.findMatchingAtomType(container, container.getAtom(i));
            if (atomType == null) {
                fragment[i] = null;
            } else {
                fragment[i] = atomType.getAtomTypeName();
            }
        }

        double[] ret = new double[0];
        try {
            ret = calculate(container, fragment, rs);
        } catch (CDKException e) {
            e.printStackTrace();
            return getDummyDescriptorValue(new CDKException(e.getMessage()));
        }

        DoubleArrayResult results = new DoubleArrayResult();
        results.add(ret[0]);
        results.add(ret[1]);
        results.add(ret[2]);

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), results,
                getDescriptorNames());
    }