Hi everyone,

  I'm confused about how to get the count information from the AtomPairs2D 
fingerprint in CDK and wondered if anyone here could help.

Once I get the fingerprint, how do I get the feature index and associated count?

When I try it out with my test case, below, I find there are 11 populated bins 
but I can only pull out 7 hashes (the other indices raise an exception), while 
I can get all 11 counts.

I don't know if this is an error in the CDK implementation, or I simply don't 
know how to get the data.

Assuming the code is working correctly, my two ideas for how to map hash to 
count are:

1)  use fp.getHash(i), fp.getCount(i) when fp.getHash(i) does not throw an 
exception

   (I think this is the correct one as fp.getCount(i) matches 
fp.getCountForHash(fp.getHash(i)))

2)  use fp.getHash(i), fp.getCount(j) where j is the j^th fp.getHash(i) which 
does not throw an exception


Here is my reproducible, which is in Python accessing cdk-2.13.jar via the 
JPype Java/Python bridge, which I set up in my chemfp package for working with 
cheminformatics fingerprints.

====
# This does the work to initialize the Java/Python bridge
from chemfp import cdk_types

from org.openscience import cdk
from org.openscience.cdk.fingerprint import AtomPairs2DFingerprinter

fingerprinter = AtomPairs2DFingerprinter()
# prints:
#  fingerprinter.getSize()=780
print(f"{fingerprinter.getSize()=}")

from org.openscience.cdk.smiles import SmilesParser
parser = SmilesParser(cdk.silent.SilentChemObjectBuilder.getInstance())
mol = parser.parseSmiles("c1ccccc1O")

fp = fingerprinter.getCountFingerprint(mol)
# prints:
#  fp.size()=780
print(f"{fp.size()=}")

# prints:
#  fp.numOfPopulatedbins()=11
print(f"{fp.numOfPopulatedbins()=}")

# I expected to get the feature indices as getHash(i) for 0 <= i < 11,
# but if I do that manually I get failures for getHash(2) and a few others

# >>> fp.getHash(0)
# 236
# >>> fp.getHash(1)
# 156
# >>> fp.getHash(2)
# Traceback (most recent call last):
#   File "AtomPairs2DFingerprinter.java", line 216, in 
org.openscience.cdk.fingerprint.AtomPairs2DFingerprinter$1.getHash
# Exception: Java Exception
# 
# The above exception was the direct cause of the following exception:
# 
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# java.lang.java.lang.NullPointerException: java.lang.NullPointerException: 
Cannot invoke "java.lang.Integer.intValue()" because the return value of 
"java.util.Map.get(Object)" is null

# Instead, I'll scan all of the indices 0 <= i < 780 and get
# the sparse index of (i, value) for both the hashes and counts

def get_hashes_and_counts(fp):
  hashes = []
  counts = []
  for i in range(780):
    try:
      hashes.append((i, fp.getHash(i)))
    except Exception:
      pass
    try:
      counts.append((i, fp.getCount(i)))
    except Exception:
      pass
    
  return hashes, counts

hashes, counts = get_hashes_and_counts(fp)

# prints:
#  hashes=[(0, 236), (1, 156), (3, 78), (4, 0), (5, 80),
#          (7, 2), (10, 158)]
print(f"{hashes=}")

# prints:
#  counts=[(0, 1), (1, 6), (2, 1), (3, 12), (4, 12), (5, 2),
#          (6, 2), (7, 1), (8, 1), (9, 2), (10, 2)]
print(f"{counts=}")

# I can see three interpretations:

## == Option 1 ==
# use (fp.GetHash(i), fp.GetCount(i) if GetHash(i) is valid

def get_sparse_features1(fp):
    features = []
    for i in range(fp.numOfPopulatedbins()):
        try:
            feature_idx = fp.getHash(i)
        except Exception:
            continue
        # Or use fp.getCountForHash(feature_idx)
        features.append((feature_idx, fp.getCount(i)))
    return features

# prints:
#  get_sparse_features1(fp)=[(236, 1), (156, 6), (78, 12), (0, 12),
#                            (80, 2), (2, 1), (158, 2)]
print(f"{get_sparse_features1(fp)=}")

## == Option 2 ==
# use (fp.GetHash(i), fp.GetCount(j) for the j-th valid GetHash(i)

def get_sparse_features2(fp):
    features = []
    j = 0
    for i in range(fp.numOfPopulatedbins()):
        try:
            feature_idx = fp.getHash(i)
        except Exception:
            continue
        features.append((feature_idx, fp.getCount(j)))
        j += 1
    return features

# prints:
#     get_sparse_features2(fp)=[(236, 1), (156, 6), (78, 1), (0, 12),
#                               (80, 12), (2, 2), (158, 2)]
print(f"{get_sparse_features2(fp)=}")

# (These give different counts than option 1, because of the
# different way of using getCount)

## == Option 3 ==
# Something is wrong with the implementation

def get_sparse_features3(fp):
    raise NotImplementedError("It is not possible to get the count features")


                                Andrew
                                [email protected]





_______________________________________________
Cdk-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cdk-user

Reply via email to