/** Tests if the electron count matches the Hückel 4n+2 rule. */
 private static boolean isHueckelValid(IAtomContainer singleRing) throws CDKException {
   int electronCount = 0;
   for (IAtom ringAtom : singleRing.atoms()) {
     if (ringAtom.getHybridization() != CDKConstants.UNSET
             && (ringAtom.getHybridization() == Hybridization.SP2)
         || ringAtom.getHybridization() == Hybridization.PLANAR3) {
       // for example, a carbon
       // note: the double bond is in the ring, that has been tested earlier
       // FIXME: this does assume bond orders to be resolved too, when detecting
       // sprouting double bonds
       if ("N.planar3".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("N.minus.planar3".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("N.amide".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("S.2".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("S.planar3".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("C.minus.planar".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("O.planar3".equals(ringAtom.getAtomTypeName())) {
         electronCount += 2;
       } else if ("N.sp2.3".equals(ringAtom.getAtomTypeName())) {
         electronCount += 1;
       } else {
         if (factory == null) {
           factory =
               AtomTypeFactory.getInstance(
                   "org/openscience/cdk/dict/data/cdk-atom-types.owl", ringAtom.getBuilder());
         }
         IAtomType type = factory.getAtomType(ringAtom.getAtomTypeName());
         Object property = type.getProperty(CDKConstants.PI_BOND_COUNT);
         if (property != null && property instanceof Integer) {
           electronCount += ((Integer) property).intValue();
         }
       }
     } else if (ringAtom.getHybridization() != null
         && ringAtom.getHybridization() == Hybridization.SP3
         && getLonePairCount(ringAtom) > 0) {
       // for example, a nitrogen or oxygen
       electronCount += 2;
     }
   }
   return (electronCount % 4 == 2) && (electronCount > 2);
 }
  /**
   * This method calculates the hybridization of an atom.
   *
   * @param atom The IAtom for which the DescriptorValue is requested
   * @param container Parameter is the atom container.
   * @return The hybridization
   */
  @TestMethod(value = "testCalculate_IAtomContainer")
  public DescriptorValue calculate(IAtom atom, IAtomContainer container) {
    IAtomType atomType;
    try {
      atomType =
          CDKAtomTypeMatcher.getInstance(atom.getBuilder()).findMatchingAtomType(container, atom);
    } catch (CDKException e) {
      return new DescriptorValue(
          getSpecification(),
          getParameterNames(),
          getParameters(),
          new IntegerResult((int) Double.NaN), // does that work??
          getDescriptorNames(),
          new CDKException("Atom type was null"));
    }
    if (atomType == null) {
      return new DescriptorValue(
          getSpecification(),
          getParameterNames(),
          getParameters(),
          new IntegerResult((int) Double.NaN), // does that work??
          getDescriptorNames(),
          new CDKException("Atom type was null"));
    }

    if (atomType.getHybridization() == null) {
      return new DescriptorValue(
          getSpecification(),
          getParameterNames(),
          getParameters(),
          new IntegerResult((int) Double.NaN), // does that work??
          getDescriptorNames(),
          new CDKException("Hybridization was null"));
    }
    int hybridizationCDK = atomType.getHybridization().ordinal();

    return new DescriptorValue(
        getSpecification(),
        getParameterNames(),
        getParameters(),
        new IntegerResult(hybridizationCDK),
        getDescriptorNames());
  }
    public String perceiveSybylAtomTypes(IMolecule mol)
                        throws InvocationTargetException {
        
        ICDKMolecule cdkmol;
        
        try {
            cdkmol = cdk.asCDKMolecule(mol);
        } 
        catch (BioclipseException e) {
            System.out.println("Error converting cdk10 to cdk");
            e.printStackTrace();
            throw new InvocationTargetException(e);
        }
        
        IAtomContainer ac = cdkmol.getAtomContainer();
        CDKAtomTypeMatcher cdkMatcher 
            = CDKAtomTypeMatcher.getInstance(ac.getBuilder());
        AtomTypeMapper mapper 
            = AtomTypeMapper.getInstance(
                 "org/openscience/cdk/dict/data/cdk-sybyl-mappings.owl" );

        IAtomType[] sybylTypes = new IAtomType[ac.getAtomCount()];
        
        int atomCounter = 0;
        int a=0;
        for (IAtom atom : ac.atoms()) {
            IAtomType type;
            try {
                type = cdkMatcher.findMatchingAtomType(ac, atom);
            } 
            catch (CDKException e) {
                type = null;
            }
            if (type==null) {
//                logger.debug("AT null for atom: " + atom);
                type = atom.getBuilder().newAtomType(atom.getSymbol());
                type.setAtomTypeName("X");
            }
            AtomTypeManipulator.configure(atom, type);
            a++;
        }
        try {
            CDKHueckelAromaticityDetector.detectAromaticity(ac);
//            System.out.println("Arom: " 
//                + CDKHueckelAromaticityDetector.detectAromaticity(ac) );
		    } 
        catch (CDKException e) {
			    logger.debug("Failed to perceive aromaticity: " + e.getMessage());
		    }
        for (IAtom atom : ac.atoms()) {
            String mappedType = mapper.mapAtomType(atom.getAtomTypeName());
            if ("C.2".equals(mappedType)
                    && atom.getFlag(CDKConstants.ISAROMATIC)) {
                mappedType = "C.ar";
            } 
            else if ("N.pl3".equals(mappedType)
                    && atom.getFlag(CDKConstants.ISAROMATIC)) {
                mappedType = "N.ar";
            }
            try {
                sybylTypes[atomCounter] = factory.getAtomType(mappedType);
		        } 
            catch (NoSuchAtomTypeException e) {
                // yes, setting null's here is important
                sybylTypes[atomCounter] = null; 
			      }
            atomCounter++;
        }
        StringBuffer result = new StringBuffer();
        // now that full perception is finished, we can set atom type names:
        for (int i = 0; i < sybylTypes.length; i++) {
            if (sybylTypes[i] != null) {
                ac.getAtom(i).setAtomTypeName(sybylTypes[i].getAtomTypeName());
            } 
            else {
                ac.getAtom(i).setAtomTypeName("X");
            }
            
            result.append(i).append(':').append(ac.getAtom(i).getAtomTypeName())
                  /*.append("\n")*/;

        }
        return result.toString();
    }