-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* update urls * chore: remove comment * feat: add custom tooltip support * feat: clear tooltips * feat: pass keepColors and keepRepresentations flags * feat: allow changing visual style * chore: remove comments * chore: add query / reset typing * chore: add color typed dict * towards color for select and highlight setting * feat: add rainbow residues solara example * add tooltip example * tweak example notebook
- Loading branch information
Showing
6 changed files
with
271 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import statistics | ||
from dataclasses import asdict, dataclass | ||
from io import StringIO | ||
from pathlib import Path | ||
|
||
import requests | ||
import solara | ||
import solara.lab | ||
from Bio.PDB import PDBParser, Residue, Structure | ||
from ipymolstar import THEMES, PDBeMolstar | ||
from matplotlib import colormaps | ||
from matplotlib.colors import Normalize | ||
from solara.alias import rv | ||
|
||
AMINO_ACIDS = [ | ||
"ALA", | ||
"ARG", | ||
"ASN", | ||
"ASP", | ||
"CYS", | ||
"GLN", | ||
"GLU", | ||
"GLY", | ||
"HIS", | ||
"ILE", | ||
"LEU", | ||
"LYS", | ||
"MET", | ||
"PHE", | ||
"PRO", | ||
"PYL", | ||
"SEC", | ||
"SER", | ||
"THR", | ||
"TRP", | ||
"TYR", | ||
"VAL", | ||
] | ||
|
||
# %% | ||
|
||
root = Path(__file__).parent.parent | ||
pdb_path = root / "assets" / "1qyn.pdb" | ||
|
||
parser = PDBParser(QUIET=True) | ||
structure = parser.get_structure("1qyn", pdb_path) | ||
MAX_R = max(r.id[1] for r in structure.get_residues()) | ||
|
||
# %% | ||
|
||
custom_data = {"data": pdb_path.read_bytes(), "format": "pdb", "binary": False} | ||
|
||
|
||
# %% | ||
def color_residues( | ||
structure: Structure.Structure, auth: bool = False, phase: int = 0 | ||
) -> dict: | ||
_, resn, _ = zip( | ||
*[r.id for r in structure.get_residues() if r.get_resname() in AMINO_ACIDS] | ||
) | ||
|
||
rmin, rmax = min(resn), max(resn) | ||
# todo check for off by one errors | ||
norm = Normalize(vmin=rmin, vmax=rmax) | ||
auth_str = "_auth" if auth else "" | ||
|
||
cmap = colormaps["hsv"] | ||
data = [] | ||
for i in range(rmin, rmax + 1): | ||
range_size = rmax + 1 - rmin | ||
j = rmin + ((i - rmin + phase) % range_size) | ||
r, g, b, a = cmap(norm(i), bytes=True) | ||
color = {"r": int(r), "g": int(g), "b": int(b)} | ||
elem = { | ||
f"start{auth_str}_residue_number": j, | ||
f"end{auth_str}_residue_number": j, | ||
"color": color, | ||
"focus": False, | ||
} | ||
data.append(elem) | ||
|
||
color_data = {"data": data, "nonSelectedColor": None} | ||
return color_data | ||
|
||
|
||
@solara.component | ||
def Page(): | ||
phase = solara.use_reactive(0) | ||
color_data = color_residues(structure, auth=True, phase=phase.value) | ||
with solara.Card(): | ||
PDBeMolstar.element( | ||
custom_data=custom_data, hide_water=True, color_data=color_data | ||
) | ||
solara.FloatSlider(label="Phase", min=0, max=MAX_R, value=phase, step=1) | ||
|
||
|
||
Page() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
@import url('https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-3.1.3.css'); | ||
@import url('https://cdn.jsdelivr.net/npm/pdbe-molstar@3.2.0/build/pdbe-molstar.css'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
@import url('https://www.ebi.ac.uk/pdbe/pdb-component-library/css/pdbe-molstar-light-3.1.3.css'); | ||
@import url('https://cdn.jsdelivr.net/npm/[email protected]/build/pdbe-molstar-light.css'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
import * as myModule from "https://www.ebi.ac.uk/pdbe/pdb-component-library/js/pdbe-molstar-plugin-3.1.3.js"; | ||
// import * as myModule from "https://cdn.jsdelivr.net/npm/pdbe-molstar@latest/build/pdbe-molstar-plugin.js" | ||
import * as myModule from "https://cdn.jsdelivr.net/npm/[email protected]/build/pdbe-molstar-plugin.js" | ||
|
||
function standardize_color(str) { | ||
var ctx = document.createElement("canvas").getContext("2d"); | ||
|
@@ -168,6 +167,12 @@ function render({ model, el }) { | |
viewerInstance.visual.select(selectValue); | ||
} | ||
}, | ||
"change:tooltips": () => { | ||
const tooltipValue = model.get("tooltips"); | ||
if (tooltipValue !== null) { | ||
viewerInstance.visual.tooltips(tooltipValue); | ||
} | ||
}, | ||
}; | ||
|
||
let otherCallbacks = { | ||
|
@@ -177,6 +182,12 @@ function render({ model, el }) { | |
"change:custom_data": () => { | ||
viewerInstance.visual.update(getOptions(model), true); | ||
}, | ||
"change:visual_style": () => { | ||
viewerInstance.visual.update(getOptions(model), true); | ||
}, | ||
// "change:lighting": () => { | ||
// viewerInstance.visual.update(getOptions(model), true); | ||
// }, | ||
"change:bg_color": () => { | ||
viewerInstance.canvas.setBgColor(toRgb(model.get("bg_color"))); | ||
}, | ||
|
@@ -186,6 +197,9 @@ function render({ model, el }) { | |
viewerInstance.visual.reset(resetValue); | ||
} | ||
}, | ||
"change:_clear_tooltips": () => { | ||
viewerInstance.visual.clearTooltips(); | ||
} | ||
}; | ||
|
||
let combinedCallbacks = Object.assign( | ||
|
@@ -210,50 +224,6 @@ function render({ model, el }) { | |
model.save_changes(); | ||
}); | ||
|
||
// TODO return unsubscribe | ||
|
||
// these require re-render | ||
// model.on("change:visual_style", () => { | ||
// viewerInstance.visual.update({visualStyle: model.get('visual_style')}); | ||
// console.log(model.get('visual_style')); | ||
// }); | ||
|
||
// model.on("change:lighting", () => { | ||
// viewerInstance.visual.update({lighting: model.get('lighting')}); | ||
// }); | ||
|
||
// model.on("change:_focus", () => { | ||
// const focusValue = model.get("_focus"); | ||
// if (focusValue !== null) { | ||
// viewerInstance.visual.focus(focusValue); | ||
// } | ||
// }); | ||
// model.on("change:_highlight", () => { | ||
// const highlightValue = model.get("_highlight"); | ||
// if (highlightValue !== null) { | ||
// viewerInstance.visual.highlight(highlightValue); | ||
// } | ||
// }); | ||
// model.on("change:_clear_highlight", () => { | ||
// 1; | ||
// viewerInstance.visual.clearHighlight(); | ||
// }); | ||
// model.on("change:_clear_selection", () => { | ||
// viewerInstance.visual.clearSelection(model.get("_args")["number"]); | ||
// }); | ||
// }); | ||
// model.on("change:_update", () => { | ||
// const updateValue = model.get("_update"); | ||
// if (updateValue !== null) { | ||
// viewerInstance.visual.update(updateValue); | ||
// } | ||
|
||
// }); | ||
// model.on("change:hide_coarse", () => { | ||
// viewerInstance.visual.visibility({ water: !model.get("hide_coarse") }); | ||
// }); | ||
|
||
// this could be a loop? | ||
return () => { | ||
unsubscribes.forEach((unsubscribe) => unsubscribe()); | ||
}; | ||
|
Oops, something went wrong.