Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
### 1.0.0 - 11/04/2025

**Changes**:

- Added dot plots on top of bar plots for improved clarity in CASP15 results.

### 0.7.1 - 08/11/2025

**Changes**:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = "PoseBench"
author = "Alex Morehead"
release = "0.7.1"
release = "1.0.0"
copyright = f"{datetime.datetime.now().year}, {author}"

# -- General configuration ---------------------------------------------------
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
109 changes: 106 additions & 3 deletions notebooks/casp15_inference_results_plotting.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"import numpy as np\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"from matplotlib.ticker import FuncFormatter\n",
"\n",
"from posebench.analysis.inference_analysis_casp import (\n",
" CASP_BUST_TEST_COLUMNS,\n",
Expand Down Expand Up @@ -304,7 +305,18 @@
" :param method: Method name.\n",
" :return: Method category.\n",
" \"\"\"\n",
" return method_category_mapping.get(method, \"DL-based blind\")"
" return method_category_mapping.get(method, \"DL-based blind\")\n",
"\n",
"\n",
"def percent_angstrom_formatter(x, pos):\n",
" \"\"\"\n",
" Format function for percent/angstrom axis.\n",
"\n",
" :param x: Value.\n",
" :param pos: Position.\n",
" :return: Formatted string.\n",
" \"\"\"\n",
" return f\"{x:.0f}% / Å\""
]
},
{
Expand Down Expand Up @@ -799,17 +811,108 @@
" width=bar_width,\n",
" )\n",
"\n",
" # extract raw RMSD values for each method and condition\n",
" for method_idx, method in enumerate(method_mapping.values()):\n",
" # get unrelaxed RMSD values grouped by target\n",
" unrelaxed_rmsd_by_target = {}\n",
" relaxed_rmsd_by_target = {}\n",
"\n",
" for repeat_index in range(1, max_num_repeats_per_method + 1):\n",
" # unrelaxed data\n",
" casp15_unrelaxed = (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\n",
" (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\"dataset\"]\n",
" == \"CASP15 set\"\n",
" )\n",
" & (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\"post-processing\"]\n",
" == \"none\"\n",
" )\n",
" & (globals()[f\"scoring_results_table_{repeat_index}\"][\"method\"] == method)\n",
" ]\n",
" .groupby(\"target\")\n",
" .agg({\"rmsd\": \"mean\"})\n",
" )\n",
"\n",
" # relaxed data\n",
" casp15_relaxed = (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\n",
" (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\"dataset\"]\n",
" == \"CASP15 set\"\n",
" )\n",
" & (\n",
" globals()[f\"scoring_results_table_{repeat_index}\"][\"post-processing\"]\n",
" == \"energy minimization\"\n",
" )\n",
" & (globals()[f\"scoring_results_table_{repeat_index}\"][\"method\"] == method)\n",
" ]\n",
" .groupby(\"target\")\n",
" .agg({\"rmsd\": \"mean\"})\n",
" )\n",
"\n",
" # accumulate values by target\n",
" for target, rmsd_value in casp15_unrelaxed.iterrows():\n",
" if target not in unrelaxed_rmsd_by_target:\n",
" unrelaxed_rmsd_by_target[target] = []\n",
" unrelaxed_rmsd_by_target[target].append(rmsd_value[\"rmsd\"])\n",
"\n",
" for target, rmsd_value in casp15_relaxed.iterrows():\n",
" if target not in relaxed_rmsd_by_target:\n",
" relaxed_rmsd_by_target[target] = []\n",
" relaxed_rmsd_by_target[target].append(rmsd_value[\"rmsd\"])\n",
"\n",
" # calculate average RMSD across repeats for each target\n",
" unrelaxed_rmsd_averages = [\n",
" np.mean(values) for values in unrelaxed_rmsd_by_target.values()\n",
" ]\n",
" relaxed_rmsd_averages = [np.mean(values) for values in relaxed_rmsd_by_target.values()]\n",
"\n",
" # overlay unrelaxed RMSD points (averaged per target)\n",
" if len(unrelaxed_rmsd_averages) > 0:\n",
" # add small random jitter for better visibility when points overlap\n",
" x_positions = np.random.normal(r1[method_idx], 0.05, len(unrelaxed_rmsd_averages))\n",
" # clamp RMSD values at 100\n",
" clamped_rmsd = [min(val, 100) for val in unrelaxed_rmsd_averages]\n",
" axis.scatter(\n",
" x_positions,\n",
" clamped_rmsd,\n",
" alpha=0.6,\n",
" s=20,\n",
" color=\"darkred\",\n",
" edgecolors=\"black\",\n",
" linewidth=0.5,\n",
" zorder=10,\n",
" ) # higher zorder to appear on top\n",
"\n",
" # overlay relaxed RMSD points (averaged per target)\n",
" if len(relaxed_rmsd_averages) > 0:\n",
" x_positions = np.random.normal(r2[method_idx], 0.05, len(relaxed_rmsd_averages))\n",
" # clamp RMSD values at 100\n",
" clamped_rmsd = [min(val, 100) for val in relaxed_rmsd_averages]\n",
" axis.scatter(\n",
" x_positions,\n",
" clamped_rmsd,\n",
" alpha=0.6,\n",
" s=20,\n",
" color=\"purple\",\n",
" edgecolors=\"black\",\n",
" linewidth=0.5,\n",
" zorder=10,\n",
" )\n",
"\n",
" # add labels, titles, ticks, etc.\n",
" axis.set_xlabel(f\"{complex_type.title()}-ligand blind docking ({complex_license})\")\n",
" axis.set_ylabel(\"Percentage of predictions\")\n",
" axis.set_ylabel(\"Percentage of predictions / RMSD (Å)\")\n",
" axis.set_xlim(1, 23 + 0.1)\n",
" axis.set_ylim(0, 125)\n",
"\n",
" axis.bar_label(casp15_rmsd_lt2_bar, fmt=\"{:,.1f}\", label_type=\"center\")\n",
" axis.bar_label(casp15_relaxed_rmsd_lt_2_bar, fmt=\"{:,.1f}\", label_type=\"center\")\n",
" axis.bar_label(casp15_plif_wm_bar, fmt=\"{:,.1f}\", label_type=\"center\")\n",
"\n",
" axis.yaxis.set_major_formatter(mtick.PercentFormatter())\n",
" axis.yaxis.set_major_formatter(FuncFormatter(percent_angstrom_formatter))\n",
"\n",
" axis.set_yticks([0, 20, 40, 60, 80, 100])\n",
" axis.axhline(y=0, color=\"#EAEFF8\")\n",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "posebench"
version = "0.7.1"
version = "1.0.0"
description = "Comprehensive benchmarking of protein-ligand structure prediction methods"
authors = [
{ name = "Alex Morehead", email = "acmwhb@umsystem.edu" }
Expand Down
Loading