Skip to content

Pawansit/ibdc_toolkit_api

Repository files navigation

ibdc-toolkit

A pip-installable Python toolkit for protein structural and mutational analysis built around the IBDC ISDA REST API (https://ibdc.dbt.gov.in/isda/api).

Domain migration note: IBDC has moved from ibdc.dbtindia.gov.in to ibdc.dbt.gov.in and asks users to switch to the new domain.

  • Protein/sequence lookup (ibdc_toolkit.protein)
  • Structural (PDB) coverage details + ChimeraX mutation scripts (ibdc_toolkit.structure)
  • UniProt ⇄ PDB residue-numbering mapping (ibdc_toolkit.mapper)
  • Clinical + computational (AlphaMissense-style) mutation retrieval and analysis (ibdc_toolkit.mutation)
  • Per-residue SASA calculation via biotite (ibdc_toolkit.sasa)

Installation

Requires Python ≥ 3.9.

# From the extracted/cloned package directory:
cd ibdc_toolkit
pip install -e .

This installs the core dependencies (requests, pandas, numpy, matplotlib). The SASA module depends on biotite, which is kept optional:

pip install -e ".[sasa]"
# or just:
pip install biotite

To install without pyproject.toml/editable mode (e.g. into a plain venv):

pip install -r requirements.txt
pip install .

Quick start

import ibdc_toolkit as ibdc

# Protein-level metadata
details = ibdc.get_protein_details("P00533")   # EGFR
seq = ibdc.get_sequence("P00533")

# Structural coverage
coverage = ibdc.get_structure_details("P00533", include_pdb_records=True)

# UniProt <-> PDB residue mapping
residue_map = ibdc.get_residue_map("P00533", "1m17")

# Mutation retrieval + analysis
clinvar_df = ibdc.get_mutation_table("P00533", source="clinvar")
annotated = ibdc.analyze_mutation_properties(clinvar_df)
summary = ibdc.get_mutation_summary(clinvar_df)

# SASA (requires the `sasa` extra / biotite installed)
result = ibdc.calculate_sasa_for_chain("1l2y", "A")

Module reference

ibdc_toolkit.protein

Function Description
get_protein_details(uniprot_id) Organism, gene name(s)/synonyms, structural record count, sequence length
get_sequence(uniprot_id) Raw sequence string, length, molecular weight
mutate_sequence(sequence_record, mutations) Apply a Position/Alt_AA (3-letter code) mutation table to a sequence, returns the mutated sequence string
seq_record = ibdc.get_sequence("P00533")
muts = pd.DataFrame({"Alt_AA": ["Gly"], "Position": [12]})
mutated_seq = ibdc.mutate_sequence(seq_record, muts)

ibdc_toolkit.structure

Function Description
get_structure_details(uniprot_id, include_pdb_records=False) PDB/chain counts and the highest-coverage structure available for the given UniProt ID; pass include_pdb_records=True for the full per-PDB record list
generate_mutated_structure_script(mutation_table, pdb_id, auth_chain_id, output_dir=".") Writes a ChimeraX .cxc script that opens <pdb_id>.cif, applies swapaa mutations for the given chain, and saves <pdb_id>_mutated_structure.cif

ibdc_toolkit.mapper

Function Description
get_residue_map(uniprot_id, pdb_id) List of {unp_residue, pdb_residue, pdb_auth_chain, pdb_chain} dicts mapping UniProt numbering to PDB numbering for one PDB entry

ibdc_toolkit.mutation

Function Description
get_mutation_table(uniprot_id, source="clinvar", record_type="default", selection=None) Clinical mutation records with Ref_AA/Position/Alt_AA parsed from Variant AA Change. Avaialble source options are: clinvar, omim, cosmic, gnomad, uniprot. For more details output use the record_type full.
get_computational_mutations(uniprot_id, ranges=None, significance_type=None) AlphaMissense-style computational predictions.
filter_by_significance(df, pattern, case=False) Regex filter on Clinical Significance available in the Clinvar output only
analyze_mutation_properties(df, ...) Adds hydrophobic/hydrophilic property columns + change-type label
get_mutation_summary(df, top_n=10) Count, significance distribution, consequence-type distribution, top mutation hotspots
merge_mutations_with_pdb_map(mutation_df, residue_map_df) Joins a mutation table to get_residue_map output on residue position of given PDB ID
plot_mutation_matrix(df, ax=None) Position × Alt_AA heatmap of mutation counts

ibdc_toolkit.sasa

Function Description
calculate_sasa_for_chain(pdb_id, chain_id, probe_radius=1.4, local_pdb_path=None) Per-residue SASA via biotite; fetches from RCSB unless local_pdb_path is given. Returns a SASAResult(residue_ids, residue_names, sasa_per_residue) namedtuple, or None on error

ibdc_toolkit.visualize

Turns the outputs of the other modules into residue-position tracks — the kind of coverage/lollipop/profile views.

Function Description
plot_structural_coverage(pdb_records, sequence_length=None, max_entries=None, ax=None) Genome-browser-style track: one horizontal bar per (PDB, chain) spanning its UNIPROT_START..UNIPROT_END range. Input is get_structure_details(uniprot_id, include_pdb_records=True)["pdb_records"]
plot_mutation_lollipop(mutation_df, position_col="Position", significance_col="Clinical Significance", sequence_length=None, ax=None) Stem plot of mutation counts per position, colored red where any record at that position is flagged pathogenic. Input is get_mutation_table(...) or get_computational_mutations(...)
plot_sasa_profile(sasa_result, sequence_length=None, ax=None) Line/area plot of per-residue SASA. Input is calculate_sasa_for_chain(...)
plot_protein_overview(sequence_length=None, pdb_records=None, mutation_df=None, sasa_result=None, title=None) Stacks any subset of the three plots above on one shared residue-position x-axis — a single combined figure
import ibdc_toolkit as ibdc

uniprot_id = "P00533"  # EGFR
seq = ibdc.get_sequence(uniprot_id)
coverage = ibdc.get_structure_details(uniprot_id, include_pdb_records=True)
mutations = ibdc.get_mutation_table(uniprot_id)

fig = ibdc.plot_protein_overview(
    sequence_length=seq["length"],
    pdb_records=coverage["pdb_records"],
    mutation_df=mutations,
    title=f"{uniprot_id} structural + mutation overview",
)
fig.savefig("egfr_overview.png", dpi=150)
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 4))
ibdc.plot_structural_coverage(coverage["pdb_records"], sequence_length=seq["length"], ax=ax)

Numbering caveat: structural coverage and clinical mutation positions are UniProt-numbered, while a SASA profile from calculate_sasa_for_chain is numbered per the PDB chain itself — these usually track closely but aren't guaranteed identical. For an exact residue-by-residue overlay, translate one numbering scheme to the other first with get_residue_map.

ibdc_toolkit.interactive — HTML/Plotly versions

Same data inputs as visualize, rendered as zoomable/pannable HTML with hover tooltips instead of a static image.

Requires the interactive extra:

pip install -e ".[interactive]"   # installs plotly
Function Description
plot_structural_coverage_html(pdb_records, sequence_length=None, title=None) Coverage track as plot_structural_coverage, but zoomable/pannable with an x-axis range slider and hover tooltips giving the exact PDB ID, chain, and UniProt range
plot_mutation_lollipop_html(mutation_df, ...) Same as plot_mutation_lollipop; hovering a point shows position, mutation count, and the set of significance labels at that position
plot_sasa_profile_html(sasa_result, ...) Same as plot_sasa_profile; hover shows exact residue id, name, and SASA value
plot_protein_overview_html(...) Combined figure with synced x-axes across panels — zoom/pan one panel and the others follow
save_html(fig, path, standalone=True) Writes any of the above to a self-contained .html file. standalone=True (default) embeds the Plotly JS so the file works fully offline (~4-5 MB); standalone=False loads it from a CDN instead (much smaller file, needs internet to view)
import ibdc_toolkit as ibdc

uniprot_id = "P00533"
seq = ibdc.get_sequence(uniprot_id)
coverage = ibdc.get_structure_details(uniprot_id, include_pdb_records=True)
mutations = ibdc.get_mutation_table(uniprot_id)

fig = ibdc.plot_protein_overview_html(
    sequence_length=seq["length"],
    pdb_records=coverage["pdb_records"],
    mutation_df=mutations,
    title=f"{uniprot_id} interactive overview",
)
ibdc.save_html(fig, "egfr_overview.html")   # open in any browser
# or, in a notebook:
# fig.show()

Logging

All modules log through the "ibdc_toolkit" logger instead of print(). Enable it in your own scripts/notebooks with:

import logging
logging.basicConfig(level=logging.INFO)  # or logging.WARNING

By default (no basicConfig call), the package stays silent — it attaches a NullHandler so it won't print anything unless you opt in.

Error handling

Every network-backed function follows the same contract: on request failure (timeout, connection error, HTTP error, bad JSON) it logs a warning and returns None — it never raises. Internally, request failures are raised as ibdc_toolkit.ISDARequestError and caught at each public function's boundary, so if you're extending the package yourself you can catch that exception directly instead of parsing log output.


Testing

pip install pytest
pytest tests/

tests/test_offline.py covers all pure-Python logic (sequence mutation, mutation property analysis, summary stats, residue-map merging, ChimeraX script generation) without requiring network access. Functions that call the live ISDA API (get_protein_details, get_structure_details, get_residue_map, get_mutation_table, get_computational_mutations) are not covered by automated tests here since they depend on network access to ibdc.dbtindia.gov.in; verify those against the live API in an environment with access to it.


License

MIT — see LICENSE.