Skip to main content
Docs

Search guides and API endpoints, for example “Idempotency-Key” or “submit job”.

    Tools · Cheminformatics & Structure

    3D Shape Similarity

    Rank a 3D library by shape and pharmacophore overlap with a query molecule, and align the best matches onto it.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    3D Shape Similarity finds molecules that look like your query in three dimensions: similar shape and similar placement of features such as hydrogen-bond donors, acceptors, and rings. Because it compares 3D shape rather than 2D substructure, it finds scaffold hops: different cores that could fit the same binding site. It runs on CPU with RDKit.

    How it works

    1. Shortlist with USRCAT (Schreyer & Blundell, 2012), fast shape-and-pharmacophore moments computed for every conformer of every library molecule.
    2. Overlay the best align_top_n molecules (default 100, up to 500): every conformer is aligned onto the query with RDKit's Gaussian shape overlay, scoring shape overlap (shape_tanimoto) and, with use_color (on by default), pharmacophore-feature overlap (color_tanimoto).
    3. Rank by combo_score, the mean of the two (or shape alone without color), from 0 to 1, higher is more similar. Molecules that weren't overlaid follow, ranked by their USRCAT score.

    Inputs

    • query: one 3D molecule (SDF or MOL block).
    • input_data: up to 5,000 library molecules in 3D (SDF or MOL blocks). A molecule can carry several conformers; the best one is used. More conformers per molecule give better matches.

    SMILES aren't accepted: generate 3D conformers first with Conformer Ensemble Generator or Molecule Conversion.

    Outputs

    FileContents
    results.csvEvery library molecule ranked, with its best conformer, usrcat_score, shape_tanimoto, color_tanimoto, and combo_score
    hits.sdfThe top top_k molecules, aligned onto the query, in rank order
    query.sdfThe query, in the same frame as the hits
    manifest.csvHow each library molecule was read

    Library molecules that can't be read are listed as errors and skipped.

    For 2D similarity use Fingerprint Similarity & Clustering. The top hit can be the reference ligand for DrugFlow or SurfDock.

    Run it from the API

    Submit with Submit a job and the job_type below. Price it first with Estimate job reservation cost: submitting reserves that amount from your wallet, and the charge settles at the actual runtime.

    3D Shape Similarity shape-similarity

    Job type
    shape-similarity
    Hardware
    cpu (default)
    Typical runtime
    5 min on CPU

    Payload

    Payload fields
    FieldTypeDescription
    queryrequiredstring | object
    query_formatrequiredstring

    One of: "sdf", "molblock"

    input_data[]required(string | object)[]

    Limits: min items 1, max items 5000

    input_formatrequiredstring

    One of: "sdf", "molblock"

    align_top_ninteger

    Default: 100Limits: ≥ 1, ≤ 500

    top_kinteger

    Default: 50Limits: ≥ 1, ≤ 500

    use_colorboolean

    Default: true

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "query": "phenol\n     RDKit          3D\n\n  7  7  0  0  0  0  0  0  0  … (659 characters)",
        "query_format": "molblock",
        "input_data": [
            "aniline\n     RDKit          3D\n\n  7  7  0  0  0  0  0  0  0 … (660 characters)",
            "butan-1-ol\n     RDKit          3D\n\n  5  4  0  0  0  0  0  0 … (484 characters)",
        ],
        "input_format": "molblock",
        "align_top_n": 2,
        "top_k": 2,
        "use_color": True,
    }
    
    estimate = client.jobs.estimate(job_type="shape-similarity", payload=payload, resource="cpu")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-shape-similarity-run",
        job_type="shape-similarity",
        payload=payload,
        resource="cpu",
    )
    status = client.jobs.wait(job.process_id)
    if status.status == "completed":
        client.jobs.result(job.process_id, save_path=".")

    Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.

    Workflow inputs

    • Molecules (list)SDF, MOLBLOCK
    • MoleculesSDF, MOLBLOCK

    Workflow outputs

    • ArchiveZIP
    • MoleculesSDF
    • TableCSV