Optimal 2D orientation

Optimal 2D orientation#

Portein uses some linear algebra (for Optimal rotation of 3D model for 2D projection and Rotating an object to maximize bounding box height) to find the best 2D projection for the input protein’s 3D coordinates.

import matplotlib.pyplot as plt
import numpy as np

import portein
pdb = portein.read_structure("../_data/7lc2.pdb")
old_coords = pdb[pdb.atom_name == "CA"].coord

pdb_oriented = portein.rotate_protein(pdb)
new_coords = pdb_oriented[pdb_oriented.atom_name == "CA"].coord
/home/runner/work/portein/portein/portein/rotate.py:23: NumbaPerformanceWarning: np.dot() is faster on contiguous arrays, called on (Array(float64, 1, 'A', False, aligned=True), Array(float64, 1, 'A', False, aligned=True))
  m = find_best_projection(coords)
/home/runner/work/portein/portein/portein/rotate.py:23: NumbaPerformanceWarning: np.dot() is faster on contiguous arrays, called on (Array(float64, 2, 'C', False, aligned=True), Array(float64, 1, 'A', False, aligned=True))
  m = find_best_projection(coords)
/home/runner/work/portein/portein/portein/rotate.py:28: NumbaPerformanceWarning: np.dot() is faster on contiguous arrays, called on (Array(float64, 2, 'A', False, aligned=True), Array(float64, 2, 'F', False, aligned=True))
  matrix = rotate_to_maximize_bb_height(coords[:, :2]) @ matrix

portein.find_size returns a figure size that preserves the structure’s aspect ratio given either a width or a height.

old_width, old_height = portein.find_size(old_coords, height=5)
new_width, new_height = portein.find_size(new_coords, height=5)

fig, ax = plt.subplots(
    1,
    2,
    figsize=(old_width + new_width, new_height),
    gridspec_kw={"width_ratios": [old_width, new_width]},
)
for axis, coords, title in [
    (ax[0], old_coords, "Before rotation"),
    (ax[1], new_coords, "After rotation"),
]:
    axis.plot(coords[:, 0], coords[:, 1], "-", c="black")
    axis.scatter(
        coords[:, 0],
        coords[:, 1],
        c=np.arange(coords.shape[0]),
        s=50,
        cmap="Blues",
        edgecolors="gray",
    )
    axis.set_title(title, fontsize=16)
    axis.axis("off")
plt.tight_layout()
../_images/99373754fcf44e1cf481d80452b73dfec0582083ee95232dda41ed228bb9a770.png

From the command line#

Save an oriented version of any structure with:

portein rotate 7lc2

It writes 7lc2_rotated.cif next to the input.