@Override
    public StereoEncoder create(IAtomContainer container, int[][] graph) {

        // XXX: this code isn't pretty, the current IAtomContainer
        // implementations are  slow for the queries (i.e. looking at connected
        // atoms/bonds) we need to ask to decide if something is a potential
        // tetrahedral centre. We can help out a little with the adjacency list
        // (int[][]) but this doesn't help with the bonds.

        int n = container.getAtomCount();

        List<StereoEncoder> encoders = new ArrayList<StereoEncoder>();
        Map<IAtom, Integer> elevation = new HashMap<IAtom, Integer>(10);

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

            int degree = graph[i].length;

            // ignore those which don't have 3 or 4 neighbors
            if (degree < 3 || degree > 4) continue;

            IAtom atom = container.getAtom(i);

            // only create encoders for SP3 hybridized atom. atom typing is
            // currently wrong for some atoms, in sulfoxide for example the atom
            // type sets SP2... but there we don't to fuss about with that here
            if (!sp3(atom)) continue;

            // avoid nitrogen-inversion
            if (Integer.valueOf(7).equals(atom.getAtomicNumber()) && degree == 3) continue;

            // TODO: we could be more strict with our selection, InChI uses C,
            // Si, Ge, P, As, B, Sn, N, P, S, Se but has preconditions for
            // certain cases. An atom or ion N, P, As, S or Se is not stereogenic
            // if it has a terminal H or two terminal neighbors -XHm, -XHn (n+m>0)
            // where X is O, S, Se, Te, or N

            // XXX: likely bottle neck
            List<IBond> bonds = container.getConnectedBondsList(atom);

            // try to create geometric parity
            GeometricParity geometric = geometric(elevation, bonds, i, graph[i], container);

            if (geometric != null) {
                // add a new encoder if a geometric parity
                encoders.add(new GeometryEncoder(i, new BasicPermutationParity(graph[i]), geometric));
            }
        }

        // no encoders, replace with the empty encoder
        return encoders.isEmpty() ? StereoEncoder.EMPTY : new MultiStereoEncoder(encoders);
    }
@ Override public StereoEncoder create ( IAtomContainer container , int [ ] [ ] graph ) { int n = container . getAtomCount ( ) ; List < StereoEncoder > encoders = new ArrayList < StereoEncoder > ( ) ; Map < IAtom , Integer > elevation = new HashMap < IAtom , Integer > ( 10 ) ; ATOMS : for ( int i = 0 ; i < n ; i ++ ) { int degree = graph [ i ] . length ; if ( degree < 3 || degree > 4 ) continue ; IAtom atom = container . getAtom ( i ) ; if ( ! sp3 ( atom ) ) continue ; if ( Integer . valueOf ( 7 ) . equals ( atom . getAtomicNumber ( ) ) && degree == 3 ) continue ; List < IBond > bonds = container . getConnectedBondsList ( atom ) ; GeometricParity geometric = geometric ( elevation , bonds , i , graph [ i ] , container ) ; if ( geometric != null ) { encoders . add ( new GeometryEncoder ( i , new BasicPermutationParity ( graph [ i ] ) , geometric ) ) ; } } return encoders . isEmpty ( ) ? StereoEncoder . EMPTY : new MultiStereoEncoder ( encoders ) ; }
Create a stereo encoder for all potential 2D and 3D tetrahedral
elements.

@param container an atom container
@param graph     adjacency list representation of the container
@return a new encoder for tetrahedral elements