Skip to content

Commit

Permalink
Merge pull request #762 from biotite-dev/interfaces
Browse files Browse the repository at this point in the history
Add `biotite.interface` subpackage
  • Loading branch information
padix-key authored Feb 27, 2025
2 parents b2e11e1 + 2e86497 commit ff5a7b4
Show file tree
Hide file tree
Showing 73 changed files with 5,460 additions and 570 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test_and_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ env:
--durations=50
--ignore={project}//tests//sequence//align//test_statistics.py
--ignore={project}//tests//application
--ignore={project}//tests//interface
--ignore={project}//tests//database
--ignore={project}//tests//test_doctest.py
--ignore={project}//tests//test_modname.py
Expand Down Expand Up @@ -223,6 +224,7 @@ jobs:
tests//test_modname.py
tests//database
tests//application
tests//interface
test-muscle5:
Expand Down
34 changes: 34 additions & 0 deletions doc/apidoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,40 @@
]
},

"biotite.interface.pymol" : {
"Launching and resetting": [
"launch_pymol",
"launch_interactive_pymol",
"reset",
"setup_parameters",
"DuplicatePyMOLError"
],
"Object handling" : [
"PyMOLObject"
],
"Structure conversion" : [
"to_model",
"from_model"
],
"Compiled Graphics Objects": [
"draw_cgo",
"get_cylinder_cgo",
"get_cone_cgo",
"get_sphere_cgo",
"get_point_cgo",
"get_line_cgo",
"get_multiline_cgo"
],
"Combined shapes": [
"draw_arrows",
"draw_box"
],
"Display": [
"show",
"play"
]
},

"biotite.database.entrez" : {
"Queries" : [
"Query",
Expand Down
13 changes: 11 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"sphinx.ext.doctest",
"sphinx.ext.mathjax",
"sphinx.ext.linkcode",
"sphinx.ext.intersphinx",
"sphinxcontrib.bibtex",
"sphinx_gallery.gen_gallery",
"sphinx_design",
Expand Down Expand Up @@ -111,6 +112,13 @@

notfound_urls_prefix = "/latest/"

intersphinx_mapping = {
"rdkit": ("https://www.rdkit.org/docs/", None),
"openmm": ("http://docs.openmm.org/latest/api-python/", None),
}
intersphinx_timeout = 60


#### HTML ####

html_theme = "pydata_sphinx_theme"
Expand Down Expand Up @@ -190,22 +198,23 @@
"within_subsection_order": FileNameSortKey,
# Do not run example scripts with a trailing '_noexec'
"filename_pattern": "^((?!_noexec).)*$",
"ignore_pattern": r"(.*ignore\.py)|(.*pymol\.py)",
"ignore_pattern": r"(.*ignore\.py)",
"download_all_examples": False,
# Never report run time
"min_reported_time": sys.maxsize,
"default_thumb_file": join(
DOC_PATH, "static/assets/general/biotite_icon_thumb.png"
),
"capture_repr": (),
"image_scrapers": (
"matplotlib",
scraper.static_image_scraper,
scraper.pymol_scraper,
),
"matplotlib_animations": True,
"image_srcset": ["2x"],
"backreferences_dir": "examples/backreferences",
"doc_module": ("biotite",),
# Set the NCBI API key
"reset_modules": (preamble.setup_script),
"remove_config_comments": True,
}
Expand Down
41 changes: 2 additions & 39 deletions doc/contribution/documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,8 @@ To build the documentation without the gallery and the tutorial, run
You may also ask the *Biotite* maintainers to run the example script and check
the generated page, if building the gallery on your device is not possible.

Static images and molecular visualizations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to *Matplotlib* plots, the *Biotite* example gallery can also
show molecular visualizations, via the *PyMOL* software, and static images.

Static images
^^^^^^^^^^^^^
Static images can be included by adding the following comment in the
corresponding code block:

Expand All @@ -96,40 +93,6 @@ corresponding code block:
The image file must be stored in the same directory as the example script.

|
To visualize images using *PyMOL*, the
`Ammolite <https://ammolite.biotite-python.org/>`_ package is required.
Please make sure to use open-source *PyMOL* to avoid licensing issues.

Let's assume you have an example script `<example_name>.py`.
The visualization is initiated by adding the comment line

.. code-block:: python
# sphinx_gallery_ammolite_script = <name_of_the_script>.py
in the code block where you want show the visualization.
Then the visualization script ``<name_of_the_script>.py`` is executed, which
can use the global variables from the example script and the special
``__image_destination__`` variable.
``__image_destination__`` is a string representing the path to the output image
file.
The PyMOL visualization can be saved to this file with e.g.

.. code-block:: python
ammolite.cmd.png(__image_destination__)
The rendered image is saved in the directory of the example script as
``<example_name>.png`` and is added to version control.
The visualization script is only executed, if the rendered image does not
exist, yet.
The traceback of errors in the visualization script are printed, if
``sphinx-build`` is run in verbose (``-v``) mode.
An example of this can be seen in the
``doc/examples/structure/contact_sites.py`` example.

Tutorial
--------
When adding new content for a broad audience, it is appreciated to update the
Expand Down
Binary file not shown.
17 changes: 15 additions & 2 deletions doc/examples/scripts/structure/alphabet/structure_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import numpy as np
import biotite
import biotite.database.rcsb as rcsb
import biotite.interface.pymol as pymol_interface
import biotite.sequence as seq
import biotite.sequence.align as align
import biotite.sequence.graphics as graphics
Expand Down Expand Up @@ -374,8 +375,20 @@ def filter_undefined_spans(sequence, min_length):
_, transform = struc.superimpose(query_anchors, target_anchors)
# Apply this transformation to full structure
target_chain = transform.apply(target_chain)
# Visualization with PyMOL...
# sphinx_gallery_ammolite_script = "structure_search_pymol.py"

# Visualization with PyMOL
pymol_interface.cmd.set("cartoon_rect_length", 1.0)
pymol_interface.cmd.set("depth_cue", 0)
pymol_interface.cmd.set("cartoon_cylindrical_helices", 1)
pymol_interface.cmd.set("cartoon_helix_radius", 1.5)
pymol_query = pymol_interface.PyMOLObject.from_structure(query_chain)
pymol_target = pymol_interface.PyMOLObject.from_structure(target_chain)
pymol_query.show_as("cartoon")
pymol_target.show_as("cartoon")
pymol_query.color("biotite_lightgreen")
pymol_target.color("biotite_lightorange")
pymol_query.orient()
pymol_interface.show((1500, 1000))
# sphinx_gallery_thumbnail_number = 3

########################################################################################
Expand Down
26 changes: 0 additions & 26 deletions doc/examples/scripts/structure/alphabet/structure_search_pymol.py

This file was deleted.

Binary file not shown.
44 changes: 41 additions & 3 deletions doc/examples/scripts/structure/contacts/contact_sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import numpy as np
import biotite.database.rcsb as rcsb
import biotite.interface.pymol as pymol_interface
import biotite.structure as struc
import biotite.structure.io.pdbx as pdbx

Expand All @@ -25,7 +26,8 @@

# Fetch and load structure
pdbx_file = pdbx.BinaryCIFFile.read(rcsb.fetch("2or1", "bcif"))
structure = pdbx.get_structure(pdbx_file, model=1)
structure = pdbx.get_structure(pdbx_file, model=1, include_bonds=True)
structure = structure[~struc.filter_solvent(structure)]


# Separate structure into the DNA and the two identical protein chains
Expand Down Expand Up @@ -70,5 +72,41 @@
res_name = protein_l.res_name[protein_l.res_id == res_id][0]
print(res_name.capitalize() + str(res_id))

# Visualization with PyMOL...
# sphinx_gallery_ammolite_script = "contact_sites_pymol.py"

# Visualization with PyMOL
pymol_obj = pymol_interface.PyMOLObject.from_structure(structure)
pymol_obj.color("gray", np.isin(structure.chain_id, ["A", "B"]))
pymol_obj.color("biotite_brightorange", structure.chain_id == "L")
pymol_obj.color("biotite_lightgreen", structure.chain_id == "R")
# Set view
pymol_interface.cmd.set_view(
(
-0.044524662,
0.767611504,
0.639355302,
0.998693943,
0.018437184,
0.047413416,
0.024606399,
0.640637815,
-0.767439663,
0.000000000,
0.000000000,
-115.614288330,
56.031833649,
23.317802429,
3.761308193,
73.517341614,
157.711288452,
-20.000000000,
)
)
# Highlight contacts
residue_mask = np.isin(structure.res_id, common_ids)
pymol_obj.show("sticks", np.isin(structure.chain_id, ["L", "R"]) & residue_mask)
for chain, color in zip(("L", "R"), ("biotite_dimorange", "biotite_darkgreen")):
pymol_obj.color(
color,
(structure.chain_id == chain) & (structure.atom_name != "CA") & residue_mask,
)
pymol_interface.show((1500, 800))
64 changes: 0 additions & 64 deletions doc/examples/scripts/structure/contacts/contact_sites_pymol.py

This file was deleted.

Binary file removed doc/examples/scripts/structure/contacts/leaflet.png
Binary file not shown.
32 changes: 29 additions & 3 deletions doc/examples/scripts/structure/contacts/leaflet.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from tempfile import NamedTemporaryFile
import networkx as nx
import numpy as np
import biotite.interface.pymol as pymol_interface
import biotite.structure as struc
import biotite.structure.io as strucio

Expand Down Expand Up @@ -111,7 +112,32 @@ def find_leaflets(structure, head_atom_mask, cutoff_distance=15.0, periodic=Fals
# Save marked lipids to structure file
temp = NamedTemporaryFile(suffix=".pdb")
strucio.save_structure(temp.name, structure)
# Visualization with PyMOL...
# sphinx_gallery_ammolite_script = "leaflet_pymol.py"

temp.close()


# Visualization with PyMOL
pymol_interface.cmd.set("sphere_scale", 1.5)
# Remove hydrogen and water
structure = structure[(structure.element != "H") & (structure.res_name != "TIP")]
structure.bonds = struc.connect_via_distances(structure)
pymol_obj = pymol_interface.PyMOLObject.from_structure(structure)
# Configure lipid tails
pymol_obj.color("biotite_lightgreen", structure.chain_id == "A")
pymol_obj.color("biotite_brightorange", structure.chain_id == "B")
pymol_obj.show("sticks", np.isin(structure.chain_id, ("A", "B")))
# Configure lipid heads
pymol_obj.color(
"biotite_darkgreen", (structure.chain_id == "A") & (structure.atom_name == "P")
)
pymol_obj.color(
"biotite_dimorange", (structure.chain_id == "B") & (structure.atom_name == "P")
)
pymol_obj.show(
"spheres", np.isin(structure.chain_id, ("A", "B")) & (structure.atom_name == "P")
)
# Adjust camera
pymol_obj.orient()
pymol_interface.cmd.turn("x", 90)
pymol_obj.zoom(buffer=-10)
# Display
pymol_interface.show((1500, 1000))
Loading

0 comments on commit ff5a7b4

Please sign in to comment.