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.intoibdc.dbt.gov.inand 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)
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 biotiteTo install without pyproject.toml/editable mode (e.g. into a plain venv):
pip install -r requirements.txt
pip install .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")| 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)| 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 |
| 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 |
| 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 |
| 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 |
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.
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()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.WARNINGBy default (no basicConfig call), the package stays silent — it attaches
a NullHandler so it won't print anything unless you opt in.
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.
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.
MIT — see LICENSE.