Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6506808
add rmsd-coloring
Dec 18, 2024
9d54918
Fix chain visualization
Dec 19, 2024
bb0c791
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 19, 2024
327148d
Fix pre-commit-ci
Dec 19, 2024
218e340
Add the option to align struct directory and pdb file
Dec 19, 2024
5ff8680
Needed changes on seq_alignment
Dec 20, 2024
2089987
Implement fitness-alignment to align wrt fasta
Dec 20, 2024
2288c66
Add more options to struct-alignment
Jan 15, 2025
4f850f8
changes to fitness-alignment
Jan 16, 2025
ca6553e
Additions to align_seq_match
Jan 16, 2025
c549e26
Merge branch 'main' of github.com:asapdiscovery/asapdiscovery into sp…
Jan 16, 2025
600e031
Fix merge conflicts
Jan 16, 2025
2dee96d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 16, 2025
e6e328b
precommit ci fixes
Jan 16, 2025
dcbaa12
fix seq-align test
Jan 20, 2025
8bfe6bf
struct-alignment tests
Jan 21, 2025
f2719e2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 21, 2025
44c315a
Add structure alignment tests
Jan 21, 2025
08d0bd1
Fix struct-alignment cfold test
Jan 21, 2025
f01968d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 21, 2025
dc0f3de
Merge remote-tracking branch 'upstream/main' into spectrum-struct-cha…
hmacdope Jan 22, 2025
983150c
bump CI
hmacdope Jan 28, 2025
f104935
bump CI
hmacdope Feb 3, 2025
b27e9b3
Added a check for blast.csv file
May 20, 2025
5e8902a
Bump CI
ijpulidos May 20, 2025
7ce24c5
Merge branch 'pydantic_2' into spectrum-struct-changes
mariacm12 May 20, 2025
04900b8
TODO to fix test here with "hidden" error
ijpulidos May 20, 2025
43fc57b
Checking subprocess return code, print error
ijpulidos May 20, 2025
5071f09
added mafft dependancy
May 20, 2025
ad99f8d
add mafft to ubuntu yaml
May 20, 2025
62a87c5
remove macOS skips from tests
May 20, 2025
82f3bfd
Merge remote-tracking branch 'origin/pydantic_2' into remove-fitness-…
Jun 17, 2025
dc7de59
Remove fitness from docking workflows
Jun 17, 2025
d0971ec
Remove fitness from dataviz
Jun 17, 2025
0a4ac3a
Remove FINT scorer
Jun 17, 2025
56fddd4
Delete fitness file
Jun 17, 2025
fb4b818
Get rid of FINT environment vars
Jun 17, 2025
9b40c47
Fix errors in data-viz
Jun 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions asapdiscovery-data/asapdiscovery/data/metadata/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,27 +56,6 @@
TargetTags("EV-D68-Capsid").value: EV_D68_Capsid_SEQRES,
}

# Fitness data in JSON format
SARS_CoV_2_fitness_data = pkg_resources.resource_filename(
__name__, "aa_fitness_sars_cov_2.json"
)

ZIKV_NS2B_NS3pro_fitness_data = pkg_resources.resource_filename(
__name__, "aa_fitness_zikv_ns2b3.json"
)

ZIKV_RdRppro_fitness_data = pkg_resources.resource_filename(
__name__, "aa_fitness_zikv_rdrppro.json"
)

targets_with_fitness_data = [
TargetTags("SARS-CoV-2-Mpro"),
TargetTags("SARS-CoV-2-Mac1"),
TargetTags("SARS-CoV-2-N-protein"),
TargetTags("ZIKV-NS2B-NS3pro"),
TargetTags("ZIKV-RdRppro"),
]

# Reference PDB files to align targets to for consistent dataviz
master_structures = {
"SARS-CoV-2-Mpro": pkg_resources.resource_filename(
Expand Down Expand Up @@ -137,7 +116,3 @@
"EV-D68-Capsid": "A",
}


FINTSCORE_PARAMETERS = pkg_resources.resource_filename(
__name__, "fintscore_parameters.yaml"
)
5 changes: 0 additions & 5 deletions asapdiscovery-dataviz/asapdiscovery/dataviz/_html_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,4 @@ def get_orient(cls) -> str:
protein.removeAllRepresentations();
protein.addRepresentation( 'surface', {color: pocket_scheme, sele: 'not ligand', opacity: 0.8, side: 'front', surfaceType: 'av'} );
protein.addRepresentation( 'ball+stick', {sele: 'ligand', opacity: 1, multipleBond: 'symmetric'} );
"""
color_method_fitness = """\
protein.removeAllRepresentations();
protein.addRepresentation( 'surface', {color: pocket_scheme, sele: 'not ligand', opacity: 1, side: 'front', surfaceType: 'av'} );
protein.addRepresentation( 'ball+stick', {sele: 'ligand', opacity: 1, multipleBond: 'symmetric'} );
"""
2 changes: 1 addition & 1 deletion asapdiscovery-dataviz/asapdiscovery/dataviz/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def visualization():
"--colour-method",
default="subpockets",
help="Coloring method",
type=click.Choice(["subpockets", "fitness"]),
type=str,
)
@click.option("--align", is_flag=True, help="Align the protein to reference structure")
@target
Expand Down
307 changes: 49 additions & 258 deletions asapdiscovery-dataviz/asapdiscovery/dataviz/html_viz.py

Large diffs are not rendered by default.

166 changes: 3 additions & 163 deletions asapdiscovery-dataviz/asapdiscovery/dataviz/plip.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
oechem,
save_openeye_pdb,
)
from asapdiscovery.data.metadata.resources import FINTSCORE_PARAMETERS
from asapdiscovery.data.services.postera.manifold_data_validation import TargetTags
from asapdiscovery.dataviz._gif_blocks import GIFBlockData
from asapdiscovery.spectrum.fitness import parse_fitness_json, target_has_fitness_data

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -56,55 +53,6 @@ def make_color_res_subpockets(protein, target) -> dict[str, str]:
return color_res_dict


def make_color_res_fitness(protein, target) -> dict[str, str]:
"""
Based on fitness coloring, creates a dict where keys are colors, values are residue numbers.
"""

# get a list of all residue numbers of the protein.
protein_residues = [
oechem.OEAtomGetResidue(atom).GetResidueNumber() for atom in protein.GetAtoms()
]
protein_chainIDs = [
oechem.OEAtomGetResidue(atom).GetChainID() for atom in protein.GetAtoms()
]

hex_color_codes = [
"#ffffff",
"#ff9e83",
"#ff8a6c",
"#ff7454",
"#ff5c3d",
"#ff3f25",
"#ff0707",
]

color_res_dict = {}
json_data = parse_fitness_json(target)
for res_num, chain in set(zip(protein_residues, protein_chainIDs)):
try:
# color residue white->red depending on fitness value.
color_index_to_grab = json_data[f"{res_num}_{chain}"]
try:
color = hex_color_codes[color_index_to_grab]
except IndexError:
# insane residue that has tons of fit mutants; just assign the darkest red.
color = hex_color_codes[-1]
if color not in color_res_dict:
color_res_dict[color] = [f"{res_num}_{chain}"]
else:
color_res_dict[color].append(f"{res_num}_{chain}")
except KeyError:
# fitness data is missing for this residue, color blue instead.
color = "#642df0"
if color not in color_res_dict:
color_res_dict[color] = [f"{res_num}_{chain}"]
else:
color_res_dict[color].append(f"{res_num}_{chain}")

return color_res_dict


def get_interaction_color(intn_type) -> str:
"""
Generated using PLIP docs; colors match PyMol interaction colors. See
Expand Down Expand Up @@ -161,43 +109,15 @@ def is_backbone_residue(protein, x, y, z) -> bool:
return False


def get_interaction_fitness_color(plip_xml_dict, protein, target) -> str:
"""
Get fitness color for a residue. If the interaction is with a backbone atom on
the residue, color it green.
"""
# first get the fitness color of the residue the interaction hits, this
# can be white->red or blue if fitness data is missing.
intn_color = None
for fitness_color, res_ids in make_color_res_fitness(protein, target).items():
if f"{plip_xml_dict['resnr']}_{plip_xml_dict['reschain']}" in res_ids:
intn_color = fitness_color
break

# overwrite the interaction as green if it hits a backbone atom.
if is_backbone_residue(
protein,
plip_xml_dict["protcoo"]["x"],
plip_xml_dict["protcoo"]["y"],
plip_xml_dict["protcoo"]["z"],
):
intn_color = "#008000"

return intn_color


def build_interaction_dict(
plip_xml_dict, intn_counter, intn_type, color_method, protein, target
plip_xml_dict, intn_counter, intn_type,
):
"""
Parses a PLIP interaction dict and builds the dict key values needed for 3DMol.
"""
k = f"{intn_counter}_{plip_xml_dict['restype']}{plip_xml_dict['resnr']}.{plip_xml_dict['reschain']}"

if color_method == "fitness":
intn_color = get_interaction_fitness_color(plip_xml_dict, protein, target)
else:
intn_color = get_interaction_color(intn_type)
intn_color = get_interaction_color(intn_type)
v = {
"lig_at_x": plip_xml_dict["ligcoo"]["x"],
"lig_at_y": plip_xml_dict["ligcoo"]["y"],
Expand All @@ -211,7 +131,7 @@ def build_interaction_dict(
return k, v


def get_interactions_plip(protein, pose, color_method, target) -> dict:
def get_interactions_plip(protein, pose) -> dict:
"""
Get protein-ligand interactions according to PLIP.

Expand Down Expand Up @@ -261,9 +181,6 @@ def get_interactions_plip(protein, pose, color_method, target) -> dict:
intn_data_i,
intn_counter,
intn_type,
color_method,
protein,
target,
)
intn_dict[k] = v
intn_counter += 1
Expand All @@ -273,85 +190,8 @@ def get_interactions_plip(protein, pose, color_method, target) -> dict:
intn_data,
intn_counter,
intn_type,
color_method,
protein,
target,
)
intn_dict[k] = v
intn_counter += 1

return intn_dict


# this should be placed around that area as well, but FINTscore should be added to docking scores by default
def compute_fint_score(
protein: oechem.OEMol, pose: oechem.OEMol, target: TargetTags
) -> tuple[float, float]:
"""
Compute the Fitness Interaction Score (FINTscore) given a dict with interactions generated by PLIP.

Parameters
----------
protein: oechem.OEMol
Protein molecule
pose: oechem.OEMol
Pose molecule
target: str
Target name


Returns
----------
intn_score: float
Score based purely on interactions, without penalties applied
fint_score: float
FINTscore which is computed as the `intn_score` with penalties applied
"""
if not target_has_fitness_data(target):
raise ValueError(
f"Target {target} does not have fitness data, cannot compute FINTscore."
)

# read YAML file that contains settings for rewards/penalties of interaction types.
fintscore_parameters = yaml.safe_load(Path(FINTSCORE_PARAMETERS).read_text())

# set empty parameters to add to when iterating over interactions.
penalty_multipliers = 1
reward_multipliers = 1
intn_score_bucket = []

# iterate over each interaction that was found.
intn_dict = get_interactions_plip(protein, pose, "fitness", target)

for _, data in intn_dict.items():
# if the interaction is with backbone, add a reward to the score.
if data["color"] == "#008000":
reward_multipliers += 1

# if the interaction is with a residue that is shown to be able to mutate, add a penalty to the score.
if data["color"] in fintscore_parameters.keys():
penalty_multipliers += fintscore_parameters[data["color"]]

# compute this interaction's score (set in metadata yaml).
intn_score_bucket.append(fintscore_parameters[data["type"]])

# simply compute the mean score, will end up being between 0.5 and 1.0, typically.
# we need to take the mean because we don't want a compound with many interactions being favored by this score.
intn_score = np.mean(intn_score_bucket)

# now compute the FINTscore by applying the reward/penalty correction terms.
# this follows FINT_{score} = INT_{score} * (REWARD*N_{backbone}) * PENALTY^{N_{mutable}},
# where PENALTY <= 1.0 <= REWARD.
fint_score = (
intn_score
* reward_multipliers
* fintscore_parameters["backbone_reward_multiplier"]
* fintscore_parameters["mutating_intn_penalty_multiplier"]
** penalty_multipliers
)

# finally, in some cases with lots of reward the FINTscore can shoot over 1.0; then just set as 1.0.
if fint_score > 1.0:
fint_score = 1.0

return intn_score, fint_score
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ def click_success(result):


@pytest.mark.parametrize("use_dask", [True, False])
@pytest.mark.parametrize("color_method", ["subpockets", "fitness"])
@pytest.mark.parametrize("align", [True, False])
def test_viz_cli(tmp_path, pose, protein, use_dask, color_method, align):
runner = CliRunner()
args = [
"pose-html",
"--colour-method",
color_method,
"subpockets",
"--target",
"SARS-CoV-2-Mpro",
"--ligands",
Expand Down

This file was deleted.

25 changes: 2 additions & 23 deletions asapdiscovery-dataviz/asapdiscovery/dataviz/tests/test_html_viz.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,16 @@ def test_html_viz_subpockets_in_mem(
assert len(vizs) == 1


@pytest.mark.parametrize("use_dask", [True, False])
@pytest.mark.parametrize("align", [True, False])
@pytest.mark.parametrize("write_to_disk", [True, False])
def test_html_viz_fitness_in_mem(
docking_results_in_memory, use_dask, align, write_to_disk, tmp_path
):
html_viz = HTMLVisualizer(
target="SARS-CoV-2-Mpro",
output_dir=tmp_path,
colour_method="fitness",
align=align,
write_to_disk=write_to_disk,
)
vizs = html_viz.visualize(
inputs=docking_results_in_memory, use_dask=use_dask, backend="in-memory"
)
assert len(vizs) == 1


@pytest.mark.parametrize("use_dask", [True, False])
@pytest.mark.parametrize("write_to_disk", [True, False])
@pytest.mark.parametrize("align", [True, False])
@pytest.mark.parametrize("color_method", ["fitness", "subpockets"])
def test_html_viz_from_pdb_file(
use_dask, tmp_path, protein, write_to_disk, align, color_method
):
html_viz = HTMLVisualizer(
target="SARS-CoV-2-Mpro",
output_dir=tmp_path,
color_method=color_method,
color_method="subpockets",
align=align,
write_to_disk=write_to_disk,
)
Expand All @@ -75,15 +55,14 @@ def test_html_viz_from_pdb_file(
@pytest.mark.parametrize("use_dask", [True, False])
@pytest.mark.parametrize("write_to_disk", [True, False])
@pytest.mark.parametrize("align", [True, False])
@pytest.mark.parametrize("color_method", ["fitness", "subpockets"])
@pytest.mark.parametrize("outpaths", [["my_sub_path/viz.html"], None])
def test_html_viz_from_complex(
use_dask, tmp_path, protein, write_to_disk, align, color_method, outpaths
):
html_viz = HTMLVisualizer(
target="SARS-CoV-2-Mpro",
output_dir=tmp_path,
color_method=color_method,
color_method="subpockets",
align=align,
write_to_disk=write_to_disk,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class DockingResultCols(str, Enum):
DOCKING_CONFIDENCE_POSIT = "docking-confidence-POSIT" # postera
DOCKING_SCORE_POSIT = "docking-score-POSIT" # postera
DOCKING_STRUCTURE_POSIT = "docking-structure-POSIT" # postera
FITNESS_SCORE_FINT = "fitness-score-FINT" # postera
DOCKING_HIT = "docking-hit" # postera
SMILES = "SMILES" # postera
INCHIKEY = "INCHIKEY" # postera
Expand All @@ -18,7 +17,6 @@ class DockingResultCols(str, Enum):
LIGAND_ID = "ligand_id"
TARGET_ID = "target_id"
HTML_PATH_POSE = "html_path_pose"
HTML_PATH_FITNESS = "html_path_fitness"
GIF_PATH = "gif_path"
MD_PATH_TRAJ = "md_path_traj"
MD_PATH_MIN_PDB = "md_path_min_pdb"
Expand Down
Loading
Loading