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