scigantic-bindingdb 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scigantic_bindingdb-0.2.2/src/scigantic_bindingdb.egg-info → scigantic_bindingdb-0.2.3}/PKG-INFO +1 -1
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/pyproject.toml +1 -1
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/chembl_bridge.py +12 -6
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/dti_pairs.py +7 -2
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3/src/scigantic_bindingdb.egg-info}/PKG-INFO +1 -1
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_chembl_bridge.py +24 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_dti_pairs.py +24 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/LICENSE +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/README.md +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/setup.cfg +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/__init__.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/__main__.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/_constants.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/cache.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/cli.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/connection.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/measurements.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/py.typed +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/releases.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/SOURCES.txt +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/dependency_links.txt +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/entry_points.txt +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/requires.txt +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/top_level.txt +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_cache.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_cli.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_connection.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_measurements.py +0 -0
- {scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/tests/test_releases.py +0 -0
{scigantic_bindingdb-0.2.2/src/scigantic_bindingdb.egg-info → scigantic_bindingdb-0.2.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scigantic-bindingdb
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Query BindingDB directly from a public S3 mirror with DuckDB, including a ChEMBL cross-reference bridge table and a ready drug-target-interaction training table.
|
|
5
5
|
Author: Scigantic
|
|
6
6
|
License: MIT-0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scigantic-bindingdb"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Query BindingDB directly from a public S3 mirror with DuckDB, including a ChEMBL cross-reference bridge table and a ready drug-target-interaction training table."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/chembl_bridge.py
RENAMED
|
@@ -49,10 +49,6 @@ def chembl_bridge(
|
|
|
49
49
|
con = connect(release)
|
|
50
50
|
try:
|
|
51
51
|
bridge_path = _resolve(f"{release}/derived/bindingdb_chembl_bridge.parquet")
|
|
52
|
-
con.execute(
|
|
53
|
-
"CREATE OR REPLACE VIEW chembl_bridge AS "
|
|
54
|
-
f"SELECT * FROM read_parquet('{bridge_path}')"
|
|
55
|
-
)
|
|
56
52
|
|
|
57
53
|
where: list[str] = []
|
|
58
54
|
params: list[str | int] = []
|
|
@@ -61,12 +57,22 @@ def chembl_bridge(
|
|
|
61
57
|
params.append(reactant_set_id)
|
|
62
58
|
clause = f"WHERE {' AND '.join(where)}" if where else ""
|
|
63
59
|
|
|
60
|
+
# read_parquet(bridge_path) inline rather than a named
|
|
61
|
+
# CREATE VIEW: connect() now hands out a cursor on a base
|
|
62
|
+
# connection shared across calls (see connection.py), and a
|
|
63
|
+
# named view is catalog state on that shared connection.
|
|
64
|
+
# Concurrent calls each doing CREATE OR REPLACE VIEW on the same
|
|
65
|
+
# name raced each other's DDL transaction: reproduced directly,
|
|
66
|
+
# concurrent chembl_bridge()/dti_pairs() calls from a thread pool
|
|
67
|
+
# mostly failed with DuckDB's "Catalog write-write conflict".
|
|
68
|
+
# Referencing the parquet file directly in the query has no
|
|
69
|
+
# catalog side effect at all, so there's nothing to conflict on.
|
|
64
70
|
if with_names:
|
|
65
71
|
mol_dict = f"s3://{CHEMBL_BUCKET}/{chembl_release}/parquet/molecule_dictionary.parquet"
|
|
66
72
|
sql = f"""
|
|
67
73
|
SELECT b.reactant_set_id, b.chembl_molregno, b.chembl_id, b.match_method,
|
|
68
74
|
m.ligand_smiles, d.pref_name AS chembl_pref_name
|
|
69
|
-
FROM
|
|
75
|
+
FROM read_parquet('{bridge_path}') b
|
|
70
76
|
JOIN measurements m ON m.reactant_set_id = b.reactant_set_id
|
|
71
77
|
LEFT JOIN read_parquet('{mol_dict}') d ON d.molregno = b.chembl_molregno
|
|
72
78
|
{clause}
|
|
@@ -75,7 +81,7 @@ def chembl_bridge(
|
|
|
75
81
|
sql = f"""
|
|
76
82
|
SELECT b.reactant_set_id, b.chembl_molregno, b.chembl_id, b.match_method,
|
|
77
83
|
m.ligand_smiles
|
|
78
|
-
FROM
|
|
84
|
+
FROM read_parquet('{bridge_path}') b
|
|
79
85
|
JOIN measurements m ON m.reactant_set_id = b.reactant_set_id
|
|
80
86
|
{clause}
|
|
81
87
|
"""
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/dti_pairs.py
RENAMED
|
@@ -54,7 +54,6 @@ def dti_pairs(
|
|
|
54
54
|
con = connect(release)
|
|
55
55
|
try:
|
|
56
56
|
path = _resolve(f"{release}/derived/dti_pairs.parquet")
|
|
57
|
-
con.execute(f"CREATE OR REPLACE VIEW dti_pairs AS SELECT * FROM read_parquet('{path}')")
|
|
58
57
|
|
|
59
58
|
where: list[str] = []
|
|
60
59
|
params: list[str | int] = []
|
|
@@ -68,7 +67,13 @@ def dti_pairs(
|
|
|
68
67
|
where.append("n_chains_declared = 1")
|
|
69
68
|
clause = f"WHERE {' AND '.join(where)}" if where else ""
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
# read_parquet(path) inline rather than a named CREATE VIEW: see
|
|
71
|
+
# chembl_bridge.py's comment on the same change. connect() now
|
|
72
|
+
# returns a cursor on a base connection shared across calls, and a
|
|
73
|
+
# named view is catalog state on that shared connection --
|
|
74
|
+
# concurrent calls racing CREATE OR REPLACE VIEW on the same name
|
|
75
|
+
# hit DuckDB's "Catalog write-write conflict", reproduced directly.
|
|
76
|
+
sql = f"SELECT * FROM read_parquet('{path}') {clause} ORDER BY p_affinity DESC"
|
|
72
77
|
if limit is not None:
|
|
73
78
|
sql += " LIMIT ?"
|
|
74
79
|
params.append(int(limit))
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3/src/scigantic_bindingdb.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scigantic-bindingdb
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Query BindingDB directly from a public S3 mirror with DuckDB, including a ChEMBL cross-reference bridge table and a ready drug-target-interaction training table.
|
|
5
5
|
Author: Scigantic
|
|
6
6
|
License: MIT-0
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
2
|
+
|
|
1
3
|
import scigantic_bindingdb as bindingdb
|
|
2
4
|
|
|
3
5
|
# A gefitinib measurement, verified against the live mirror to resolve
|
|
@@ -29,3 +31,25 @@ def test_bridge_total_row_count():
|
|
|
29
31
|
"'s3://scigantic-bindingdb/202608/derived/bindingdb_chembl_bridge.parquet')"
|
|
30
32
|
)
|
|
31
33
|
assert total["n"].iloc[0] == 2272063
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_concurrent_calls_do_not_conflict_on_catalog():
|
|
37
|
+
# Regression test for a real bug introduced by connect()'s move to a
|
|
38
|
+
# shared base connection (see connection.py): chembl_bridge() used to
|
|
39
|
+
# register its result as a named CREATE OR REPLACE VIEW, which is
|
|
40
|
+
# catalog-mutating DDL. Two calls racing that DDL on the same shared
|
|
41
|
+
# connection from different threads mostly failed with DuckDB's
|
|
42
|
+
# "Catalog write-write conflict", reproduced directly (46/48 calls
|
|
43
|
+
# failed in a 24-thread stress run) before this was fixed by
|
|
44
|
+
# referencing the parquet file inline instead of via a named view.
|
|
45
|
+
def call(i):
|
|
46
|
+
return bindingdb.chembl_bridge(
|
|
47
|
+
reactant_set_id=_GEFITINIB_REACTANT_SET_ID, with_names=(i % 2 == 0)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
with ThreadPoolExecutor(max_workers=16) as pool:
|
|
51
|
+
results = list(pool.map(call, range(16)))
|
|
52
|
+
|
|
53
|
+
for df in results:
|
|
54
|
+
assert len(df) == 1
|
|
55
|
+
assert df["chembl_id"].iloc[0] == "CHEMBL939"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import math
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
2
3
|
|
|
3
4
|
import scigantic_bindingdb as bindingdb
|
|
4
5
|
|
|
@@ -69,3 +70,26 @@ def test_uniprot_filter():
|
|
|
69
70
|
def test_sorted_most_potent_first():
|
|
70
71
|
df = bindingdb.dti_pairs(endpoint="ki", uniprot_id="P00533")
|
|
71
72
|
assert df["p_affinity"].is_monotonic_decreasing
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_concurrent_calls_do_not_conflict_on_catalog():
|
|
76
|
+
# Regression test for a real bug introduced by connect()'s move to a
|
|
77
|
+
# shared base connection (see connection.py): dti_pairs() used to
|
|
78
|
+
# register its result as a named CREATE OR REPLACE VIEW, which is
|
|
79
|
+
# catalog-mutating DDL. Two calls racing that DDL on the same shared
|
|
80
|
+
# connection from different threads mostly failed with DuckDB's
|
|
81
|
+
# "Catalog write-write conflict" (reproduced directly before this was
|
|
82
|
+
# fixed by referencing the parquet file inline instead of via a named
|
|
83
|
+
# view; see chembl_bridge.py's equivalent test).
|
|
84
|
+
endpoints = ("ki", "ic50", "kd", "ec50")
|
|
85
|
+
|
|
86
|
+
def call(i):
|
|
87
|
+
endpoint = endpoints[i % len(endpoints)]
|
|
88
|
+
return endpoint, bindingdb.dti_pairs(endpoint=endpoint, limit=50)
|
|
89
|
+
|
|
90
|
+
with ThreadPoolExecutor(max_workers=16) as pool:
|
|
91
|
+
results = list(pool.map(call, range(16)))
|
|
92
|
+
|
|
93
|
+
for endpoint, df in results:
|
|
94
|
+
assert len(df) == 50
|
|
95
|
+
assert (df["endpoint"] == endpoint).all()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/_constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/connection.py
RENAMED
|
File without changes
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb/measurements.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scigantic_bindingdb-0.2.2 → scigantic_bindingdb-0.2.3}/src/scigantic_bindingdb.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|