Digital Trials pipeline configured for WES

Source-only snapshot of the cluster branch for WES execution. Large
reference files (HPA/MANE/ensemble FASTA, model weights, ~597 MB) are
omitted: they are baked into the container images at build time and
mounted from the dreamdock-data PVC at runtime, and exceed the Gitea
request size limit.

Pipeline entry point is main.nf, which orchestrates the biotransformer,
conplex and tissue modules as a single workflow. Ligand inputs are read
from the eureka workspace; protein_zarr and chembl_db come from the
dreamdock-data PVC.
This commit is contained in:
Olamide Isreal
2026-07-27 21:59:52 +01:00
commit 9e75f44f1a
86 changed files with 10142 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
# Custom Rust modules
import mol_fingerprint as mf
import bitexpand
import pandas as pd
import numpy as np
from pathlib import Path
from argparse import ArgumentParser
import zarr
from zarr.storage import LocalStore
from zarr.codecs import ZstdCodec
from sklearn.preprocessing import normalize
from parallelbar import progress_map
import onnxruntime as ort
print('CUDA available:', 'CUDAExecutionProvider' in ort.get_available_providers())
def parse_args():
parser = ArgumentParser()
parser.add_argument("-i","--input-tsv", type=Path, required=True, help="Input TSV file with molecules to screen. It must not have any labels and has only two columns, 1st molecule_label, 2nd molecule_smiles")
parser.add_argument("-z","--zarr-protein", type=Path, required=True, help="Input Zarr DB that holds the protein ids and their normalized projection vectors")
return parser
parser = parse_args()
args = parser.parse_args()
path_metabolites : Path = args.input_tsv
if not path_metabolites.is_file():
raise ValueError(f"{path_metabolites} IS MISSING OR NOT A FILE")
df_metabolite = pd.read_csv(
path_metabolites,
sep="\t",
header=None,
names=["smiles" ,"compound_id"]
)
path_zarr = args.zarr_protein
store_zarr = LocalStore(path_zarr, read_only=True)
group_zarr = zarr.open(store_zarr, mode="r")
protein_vecs = (group_zarr["normalized"][:])
path_onnx = Path("/app/drug_projector.onnx")
def load_model(model_path):
"""Load ONNX model with GPU support"""
model_path = Path(model_path)
# Set up providers for GPU execution
# providers = ['CUDAExecutionProvider', 'CPUExecutionProvider']
providers = ['CPUExecutionProvider']
# Create inference session
session = ort.InferenceSession(str(model_path), providers=providers)
# Verify GPU is being used
print(f"Available providers: {session.get_providers()}")
return session
session = load_model(path_onnx)
def run_inference(input_vector):
"""Run inference on the model"""
# Get input/output names
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name
# Run inference
outputs = session.run([output_name], {input_name: input_vector})
return outputs[0]
def normalize_vectors_sklearn(vectors):
"""Normalize using sklearn - often fastest for large arrays"""
return normalize(vectors, norm='l2', axis=1)
def project_drugs(smiles : list[str]) -> np.ndarray :
fps = bitexpand.expand_bits(np.array([
np.frombuffer(fp,dtype=np.uint8)
for fp in mf.generate_fingerprints(smiles)
]))
return normalize_vectors_sklearn(run_inference(fps))
pvecs = project_drugs(df_metabolite["smiles"].values.tolist())
my_results = np.dot(protein_vecs, pvecs.T)
pids = group_zarr["ids"][:]
# Create output zarr store
path_outdir = Path("./")
zarr_name = path_zarr.stem + "_results.zarr"
path_output_zarr = path_outdir / zarr_name
# Create zarr store
store_output = LocalStore(path_output_zarr, read_only=False)
group_output = zarr.open(store_output, mode="w")
out_compress =[
ZstdCodec( level=13 )
]
# Store the data
# Similarity matrix: (n_proteins, n_compounds)
z1 = group_output.create_array(
"scores",
dtype="float32",
shape=my_results.shape,
chunks=(min(1000, my_results.shape[0]), my_results.shape[1]),
compressors=out_compress
)
z1[:] = my_results
# Compound IDs
z2 = group_output.create_array(
"compound_ids",
dtype="str",
shape=(len(df_metabolite),),
compressors=out_compress
)
z2[:] = df_metabolite["compound_id"].values
# Protein IDs
z3 = group_output.create_array(
"protein_ids",
dtype="str",
shape=(len(pids),),
compressors=out_compress
)
z3[:] = pids
# Store metadata
group_output.attrs['n_proteins'] = my_results.shape[0]
group_output.attrs['n_compounds'] = my_results.shape[1]
group_output.attrs['source_zarr'] = str(path_zarr)
print(f"Results saved to {path_output_zarr}")
print(f"Shape: {my_results.shape[0]} proteins x {my_results.shape[1]} compounds")
print("PROCESS COMPLETED SUCCESSFULLY")