This method calculates the protonation affinity of an atom.

@param  atom              The IAtom to protonate
@param  container         Parameter is the IAtomContainer.
@return                   The protonation affinity. Not possible the ionization.
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);

    }
796143
public IAtom getFarthestAtom(Point3d refAtomPoint, IAtomContainer ac) {
        double distance = 0;
        IAtom atom = null;
        for (int i = 0; i < ac.getAtomCount(); i++) {
            if (ac.getAtom(i).getPoint3d() != null) {
                if (Math.abs(refAtomPoint.distance(ac.getAtom(i).getPoint3d())) > distance) {
                    atom = ac.getAtom(i);
                    distance = Math.abs(refAtomPoint.distance(ac.getAtom(i).getPoint3d()));
                }
            }
        }
        return atom;
    }
146883
@Override
    public DescriptorValue calculate(IAtom atom, IAtomContainer container) {
        String symbol = atom.getSymbol();
        double vdwradius = PeriodicTable.getVdwRadius(symbol);
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(),
                new DoubleResult(vdwradius), NAMES);

    }
1016248
private int determineCharge(IAtomContainer mol, IAtom atom) {
        Integer q = atom.getFormalCharge();
        if (q == null)
            q = 0;
        switch (q) {
            case -3: return 7;
            case -2: return 6;
            case -1: return 5;
            case 0:
                if (mol.getConnectedSingleElectronsCount(atom) == 1)
                    return 4;
                return 0;
            case +1:  return 3;
            case +2:  return 2;
            case +3:  return 1;
        }
        return 0;
    }
465459
public IAtomContainer assignInductivePartialCharges(IAtomContainer ac) throws Exception {
        if (factory == null) {
            factory = AtomTypeFactory
                    .getInstance("org/openscience/cdk/config/data/jmol_atomtypes.txt", ac.getBuilder());
        }

        int stepsLimit = 9;
        IAtom[] atoms = AtomContainerManipulator.getAtomArray(ac);
        double[] pChInch = new double[atoms.length * (stepsLimit + 1)];
        double[] ElEn = new double[atoms.length * (stepsLimit + 1)];
        double[] pCh = new double[atoms.length * (stepsLimit + 1)];
        double[] startEE = getPaulingElectronegativities(ac, true);
        for (int e = 0; e < atoms.length; e++) {
            ElEn[e] = startEE[e];
            //logger.debug("INDU: initial EE "+startEE[e]);
        }
        //double tmp1 = 0;
        //double tmp2 = 0;
        for (int s = 1; s < 10; s++) {
            for (int a = 0; a < atoms.length; a++) {
                pChInch[a + (s * atoms.length)] = getAtomicChargeIncrement(ac, a, ElEn, s);
                pCh[a + (s * atoms.length)] = pChInch[a + (s * atoms.length)] + pCh[a + ((s - 1) * atoms.length)];
                ElEn[a + (s * atoms.length)] = ElEn[a + ((s - 1) * atoms.length)]
                        + (pChInch[a + (s * atoms.length)] / getAtomicSoftnessCore(ac, a));
                if (s == 9) {
                    atoms[a].setProperty("InductivePartialCharge", new Double(pCh[a + (s * atoms.length)]));
                    atoms[a].setProperty("EffectiveAtomicElectronegativity", new Double(ElEn[a + (s * atoms.length)]));
                }
                //tmp1 = pCh[a + (s * atoms.length)];
                //tmp2 = ElEn[a + (s * atoms.length)];
                //logger.debug("DONE step " + s + ", atom " + atoms[a].getSymbol() + ", ch " + tmp1 + ", ee " + tmp2);
            }
        }
        return ac;
    }
344614
public IAtomContainer getPlacedAtomsInAtomContainer(IAtom atom, IAtomContainer ac) {

        List bonds = ac.getConnectedBondsList(atom);
        IAtomContainer connectedAtoms = atom.getBuilder().newInstance(IAtomContainer.class);
        IAtom connectedAtom = null;
        for (int i = 0; i < bonds.size(); i++) {
            connectedAtom = ((IBond) bonds.get(i)).getOther(atom);
            if (connectedAtom.getFlag(CDKConstants.ISPLACED)) {
                connectedAtoms.addAtom(connectedAtom);
            }
        }
        return connectedAtoms;
    }
1119390
public void rebond(IAtomContainer container) throws CDKException {
        container.removeAllBonds();
        maxCovalentRadius = 0.0;
        // construct a new binary space partition tree
        bspt = new Bspt(3);
        Iterator<IAtom> atoms = container.atoms().iterator();
        while (atoms.hasNext()) {
            IAtom atom = atoms.next();
            double myCovalentRadius = atom.getCovalentRadius();
            if (myCovalentRadius == 0.0) {
                throw new CDKException("Atom(s) does not have covalentRadius defined.");
            }
            if (myCovalentRadius > maxCovalentRadius) maxCovalentRadius = myCovalentRadius;
            TupleAtom tupleAtom = new TupleAtom(atom);
            bspt.addTuple(tupleAtom);
        }
        // rebond all atoms
        atoms = container.atoms().iterator();
        while (atoms.hasNext()) {
            bondAtom(container, (IAtom) atoms.next());
        }
    }
40566
public static int getTotalFormalCharge(IAtomContainer atomContainer) {
        int chargeP = getTotalNegativeFormalCharge(atomContainer);
        int chargeN = getTotalPositiveFormalCharge(atomContainer);

        return chargeP + chargeN;
    }
555801
@Override
    public DescriptorValue calculate(IAtom first, IAtom second, IAtomContainer atomContainer) {
        IAtomContainer ac;
        try {
            ac = (IAtomContainer) atomContainer.clone();
        } catch (CloneNotSupportedException e) {
            return getDummyDescriptorValue(e);
        }
        IAtom clonedFirst = ac.getAtom(atomContainer.indexOf(first));
        IAtom clonedSecond = ac.getAtom(atomContainer.indexOf(first));

        IAtomContainer mol = ac.getBuilder().newInstance(IAtomContainer.class, ac);
        if (checkAromaticity) {
            try {
                AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(mol);
                Aromaticity.cdkLegacy().apply(mol);
            } catch (CDKException e) {
                return getDummyDescriptorValue(e);
            }
        }
        boolean piContact = false;
        int counter = 0;

        if (acold != ac) {
            acold = ac;
            acSet = ConjugatedPiSystemsDetector.detect(mol);
        }
        java.util.Iterator<IAtomContainer> detected = acSet.atomContainers().iterator();

        List<IAtom> neighboorsFirst = mol.getConnectedAtomsList(clonedFirst);
        List<IAtom> neighboorsSecond = mol.getConnectedAtomsList(clonedSecond);

        while (detected.hasNext()) {
            IAtomContainer detectedAC = detected.next();
            if (detectedAC.contains(clonedFirst) && detectedAC.contains(clonedSecond)) {
                counter += 1;
                break;
            }
            if (isANeighboorsInAnAtomContainer(neighboorsFirst, detectedAC)
                    && isANeighboorsInAnAtomContainer(neighboorsSecond, detectedAC)) {
                counter += 1;
                break;
            }
        }

        if (counter > 0) {
            piContact = true;
        }
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new BooleanResult(
                piContact), getDescriptorNames());
    }
288866
@Override
    public DescriptorValue calculate(IAtom atom, IAtomContainer container) {
        int period;
        String symbol = atom.getSymbol();
        period = periodicTable.get(symbol);
        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new IntegerResult(period),
                                   NAMES);
    }
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;
    }
21342
public static IAtomContainer makePyrroleAnion() {
        IAtomContainer mol = new AtomContainer();
        IAtom nitrogenAnion = new Atom("N");
        nitrogenAnion.setFormalCharge(-1);
        mol.addAtom(new Atom("C")); // 0
        mol.addAtom(nitrogenAnion); // 1
        mol.addAtom(new Atom("C")); // 2
        mol.addAtom(new Atom("C")); // 3
        mol.addAtom(new Atom("C")); // 4

        mol.addBond(0, 1, IBond.Order.SINGLE); // 1
        mol.addBond(1, 2, IBond.Order.SINGLE); // 2
        mol.addBond(2, 3, IBond.Order.DOUBLE); // 3
        mol.addBond(3, 4, IBond.Order.SINGLE); // 4
        mol.addBond(4, 0, IBond.Order.DOUBLE); // 5

        return mol;
    }
558109
@Override
    public DescriptorValue calculate(IAtomContainer atomContainer) {
        double volume;
        try {
            // clone: don't mod original
            volume = VABCVolume.calculate(clone(atomContainer));
        } catch (CDKException exception) {
            return getDummyDescriptorValue(exception);
        }

        return new DescriptorValue(getSpecification(), getParameterNames(), getParameters(), new DoubleResult(volume),
                getDescriptorNames());
    }
1041369
public static int getSingleBondEquivalentSum(IAtomContainer container) {
        int sum = 0;
        for (IBond bond : container.bonds()) {
            IBond.Order order = bond.getOrder();
            if (order != null) {
                sum += order.numeric();
            }
        }
        return sum;
    }
810488
private static IAtom findPiBondedOxygen(IAtomContainer container, IAtom atom) {
        for (IBond bond : container.getConnectedBondsList(atom)) {
            if (bond.getOrder() == IBond.Order.DOUBLE) {
                IAtom neighbor = bond.getOther(atom);
                int charge = neighbor.getFormalCharge() == null ? 0 : neighbor.getFormalCharge();
                if (neighbor.getAtomicNumber() == 8 && charge == 0) return neighbor;
            }
        }
        return null;
    }
13618
private boolean getPresenceOfNitro(IAtomContainer ac, IAtom atom) {
        List neighbours = ac.getConnectedAtomsList(atom);
        List second = null;
        IBond bond = null;
        //int counter = 0;
        for (int i = 0; i < neighbours.size(); i++) {
            IAtom neighbour = (IAtom) neighbours.get(i);
            if (neighbour.getSymbol().equals("N")) {
                second = ac.getConnectedAtomsList(neighbour);
                for (int b = 0; b < second.size(); b++) {
                    IAtom conAtom = (IAtom) second.get(b);
                    if (conAtom.getSymbol().equals("O")) {
                        bond = ac.getBond(neighbour, conAtom);
                        if (bond.getOrder() == IBond.Order.DOUBLE) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
360034
public double[] prepareNode(IAtomContainer atomContainer) {
        double nodeSequence[] = new double[atomContainer.getAtomCount()];
        int i = 0;
        for (IAtom atom : atomContainer.atoms()) {
            String symbol = atom.getSymbol();

            List<IBond> bonds = atomContainer.getConnectedBondsList(atom);
            if (bonds.size() == 1) {
                IBond bond0 = bonds.get(0);
                IBond.Order order = bond0.getOrder();
                if (symbol.equals("C")) {
                    if (order == IBond.Order.SINGLE)
                        nodeSequence[i] = 1;// CH3-
                    else if (order == IBond.Order.DOUBLE)
                        nodeSequence[i] = 3;// CH2=
                    else if (order == IBond.Order.TRIPLE) nodeSequence[i] = 6;// CH#
                } else if (symbol.equals("O")) {
                    if (order == IBond.Order.SINGLE)
                        nodeSequence[i] = 14;// HO-
                    else if (order == IBond.Order.DOUBLE) nodeSequence[i] = 16;// O=
                    // missing the case of an aromatic double bond
                } else if (symbol.equals("N")) {
                    if (order == IBond.Order.SINGLE)
                        nodeSequence[i] = 18;// NH2-
                    else if (order == IBond.Order.DOUBLE) {
                        if (atom.getCharge() == -1.0)
                            nodeSequence[i] = 27;// N= contains -1 charge
                        else
                            nodeSequence[i] = 20;// NH=
                    } else if (order == IBond.Order.TRIPLE) nodeSequence[i] = 23;// N#
                } else if (symbol.equals("S")) {
                    if (order == IBond.Order.SINGLE)
                        nodeSequence[i] = 31;// HS-
                    else if (order == IBond.Order.DOUBLE) nodeSequence[i] = 33;// S=
                } else if (symbol.equals("P"))
                    nodeSequence[i] = 38;// PH2-
                else if (symbol.equals("F"))
                    nodeSequence[i] = 42;// F-
                else if (symbol.equals("Cl"))
                    nodeSequence[i] = 43;// Cl-
                else if (symbol.equals("Br"))
                    nodeSequence[i] = 44;// Br-
                else if (symbol.equals("I"))
                    nodeSequence[i] = 45;// I-
                else {
                    logger.debug("in case of a new node, please " + "report this bug to cdk-devel@lists.sf.net.");
                }
            } else if (bonds.size() == 2) {
                IBond bond0 = (IBond) bonds.get(0);
                IBond bond1 = (IBond) bonds.get(1);
                IBond.Order order0 = bond0.getOrder();
                IBond.Order order1 = bond1.getOrder();
                if (symbol.equals("C")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE)
                        nodeSequence[i] = 2;// -CH2-
                    else if (order0 == IBond.Order.DOUBLE && order1 == IBond.Order.DOUBLE)
                        nodeSequence[i] = 10;// =C=
                    else if ((order0 == IBond.Order.SINGLE || bond1.getOrder() == IBond.Order.SINGLE)
                            && (order0 == IBond.Order.DOUBLE || bond1.getOrder() == IBond.Order.DOUBLE))
                        nodeSequence[i] = 5;// -CH=
                    else if ((order0 == IBond.Order.SINGLE || bond1.getOrder() == IBond.Order.TRIPLE)
                            && (order0 == IBond.Order.TRIPLE || bond1.getOrder() == IBond.Order.TRIPLE))
                        nodeSequence[i] = 9;// -C#
                    // case 3 would not allow to reach this statement as there
                    // is no aromatic bond order
                    if (bond0.getFlag(CDKConstants.ISAROMATIC) && bond1.getFlag(CDKConstants.ISAROMATIC))
                        nodeSequence[i] = 11;// ArCH
                } else if (symbol.equals("N")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE)
                        nodeSequence[i] = 19;// -NH-
                    else if (order0 == IBond.Order.DOUBLE && order1 == IBond.Order.DOUBLE)
                        nodeSequence[i] = 28;// =N= with charge=-1
                    else if ((order0 == IBond.Order.SINGLE || bond1.getOrder() == IBond.Order.SINGLE)
                            && (order0 == IBond.Order.DOUBLE || bond1.getOrder() == IBond.Order.DOUBLE))
                        nodeSequence[i] = 22;// -N=
                    else if ((order0 == IBond.Order.DOUBLE || bond1.getOrder() == IBond.Order.DOUBLE)
                            && (order0 == IBond.Order.TRIPLE || bond1.getOrder() == IBond.Order.TRIPLE))
                        nodeSequence[i] = 26;// =N#
                    else if ((order0 == IBond.Order.SINGLE || bond1.getOrder() == IBond.Order.SINGLE)
                            && (order0 == IBond.Order.TRIPLE || bond1.getOrder() == IBond.Order.TRIPLE))
                        nodeSequence[i] = 29;// -N# with charge=+1
                    // case 3 would not allow to reach this statement as there
                    // is no aromatic bond order
                    if (bond0.getFlag(CDKConstants.ISAROMATIC) && bond1.getFlag(CDKConstants.ISAROMATIC))
                        nodeSequence[i] = 30;// ArN
                    // there is no way to distinguish between ArNH and ArN as
                    // bonds to protons are not considered
                } else if (symbol.equals("O")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE)
                        nodeSequence[i] = 15;// -O-
                    else if (bond0.getFlag(CDKConstants.ISAROMATIC) && bond1.getFlag(CDKConstants.ISAROMATIC))
                        nodeSequence[i] = 17;// ArO
                } else if (symbol.equals("S")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE)
                        nodeSequence[i] = 32;// -S-
                    else if (order0 == IBond.Order.DOUBLE && order1 == IBond.Order.DOUBLE)
                        nodeSequence[i] = 35;// =S=
                    else if (bond0.getFlag(CDKConstants.ISAROMATIC) && bond1.getFlag(CDKConstants.ISAROMATIC))
                        nodeSequence[i] = 37;// ArS
                } else if (symbol.equals("P")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE) nodeSequence[i] = 39;// -PH-
                } else {
                    logger.debug("in case of a new node, " + "please report this bug to cdk-devel@lists.sf.net.");
                }
            } else if (bonds.size() == 3) {
                IBond bond0 = (IBond) bonds.get(0);
                IBond bond1 = (IBond) bonds.get(1);
                IBond bond2 = (IBond) bonds.get(2);
                IBond.Order order0 = bond0.getOrder();
                IBond.Order order1 = bond1.getOrder();
                IBond.Order order2 = bond2.getOrder();

                if (symbol.equals("C")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE && order2 == IBond.Order.SINGLE)
                        nodeSequence[i] = 4;// >C-
                    else if (order0 == IBond.Order.DOUBLE || order1 == IBond.Order.DOUBLE
                            || order2 == IBond.Order.DOUBLE) nodeSequence[i] = 8;// >C=
                    // case 2 would not allow to reach this statement because
                    // there is always a double bond (pi system) around an
                    // aromatic atom
                    if ((bond0.getFlag(CDKConstants.ISAROMATIC) || bond1.getFlag(CDKConstants.ISAROMATIC) || bond2
                            .getFlag(CDKConstants.ISAROMATIC))
                            && (order0 == IBond.Order.SINGLE || order1 == IBond.Order.SINGLE || bond2.getOrder() == IBond.Order.SINGLE))
                        nodeSequence[i] = 12;// ArC-
                    // case 3 would not allow to reach this statement
                    if (bond0.getFlag(CDKConstants.ISAROMATIC) && bond1.getFlag(CDKConstants.ISAROMATIC)
                            && bond2.getFlag(CDKConstants.ISAROMATIC)) nodeSequence[i] = 13;// ArC
                } else if (symbol.equals("N")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE && order2 == IBond.Order.SINGLE)
                        nodeSequence[i] = 21;// >N-
                    else if (order0 == IBond.Order.SINGLE || order1 == IBond.Order.SINGLE
                            || order2 == IBond.Order.SINGLE) nodeSequence[i] = 25;// -N(=)=
                } else if (symbol.equals("S")) {
                    if (order0 == IBond.Order.DOUBLE || order1 == IBond.Order.DOUBLE || order2 == IBond.Order.DOUBLE)
                        nodeSequence[i] = 34;// >S=
                } else if (symbol.equals("P")) {
                    if (order0 == IBond.Order.SINGLE && order1 == IBond.Order.SINGLE && order2 == IBond.Order.SINGLE)
                        nodeSequence[i] = 40;// >P-
                } else {
                    logger.debug("in case of a new node, " + "please report this bug to cdk-devel@lists.sf.net.");
                }
            } else if (bonds.size() == 4) {
                if (atom.getSymbol().equals("C"))
                    nodeSequence[i] = 7;// >C<
                else if (atom.getSymbol().equals("N"))
                    nodeSequence[i] = 24;// >N(=)-
                else if (atom.getSymbol().equals("S"))
                    nodeSequence[i] = 36;// >S(=)=
                else if (atom.getSymbol().equals("P"))
                    nodeSequence[i] = 41;// =P<-
                else {
                    logger.debug("in case of a new node, " + "please report this bug to cdk-devel@lists.sf.net.");
                }
            }
            i++;
        }
        return nodeSequence;
    }