Escriu per cercar…

PyVista

Àtoms, cinta i superfície d'una proteïna: cada representació, una crida.

Introducció

A Panda3D vas dibuixar una proteïna a mà: una esfera per àtom i una línia entre carbonis alfa. Va sortir, i sobretot vas veure que no hi havia cap màgia.

Ara la faràs amb l’eina que faria servir algú que s’hi dedica.

De PyVista ja en saps el Plotter, el PolyData i el glyph. Resulta que les tres peces que et van costar feina amb el motor de jocs — repetir una esfera a milers de posicions, passar un tub suau per una corba, i treure la superfície d’un núvol de punts — VTK les porta fetes.

Aquí les faràs servir amb l’hemoglobina, la proteïna que transporta l’oxigen a la sang. Cada representació et costarà unes deu línies.

Entorn de treball

Fes servir el projecte amb PyVista que ja tens, o fes-ne un de nou amb uv add pyvista.

Baixa’t l’hemoglobina del Protein Data Bank. El seu codi és 1A3N:

ps
iwr https://files.rcsb.org/download/1A3N.pdb -OutFile 1a3n.pdb

El lector de fitxers PDB

El protein.py que vas escriure a Panda3D et serveix igual: llegeix les línies ATOM i en treu un diccionari per àtom. Copia’l al projecte nou.

Comprova que l’hemoglobina hi entra bé:

python
from protein import read_atoms
atoms = read_atoms("1a3n.pdb")
len(atoms)
4370
sorted({atom["chain"] for atom in atoms})
['A', 'B', 'C', 'D']

Quatre cadenes, tal com toca: l’hemoglobina són dues cadenes α i dues β.

Els àtoms

Ja saps que un PolyData amb glyph reparteix la mateixa esfera per tots els punts d’un cop. Amb una proteïna, això és el que et treu el problema que tenies: no fas 4.370 esferes, en fas una i la repeteixes.

El que és nou aquí és que en fas un núvol per element, perquè cada element vol el seu color.

python
atoms.py
import pyvista as pv

from protein import read_atoms

COLORS = {
    "C": "#3f3f3f",
    "N": "#3355ee",
    "O": "#dd2222",
    "S": "#ddbb22",
}

atoms = read_atoms("1a3n.pdb")
plotter = pv.Plotter()
plotter.set_background("white")

for element, color in COLORS.items():
    coords = [[a["x"], a["y"], a["z"]] for a in atoms if a["element"] == element]
    cloud = pv.PolyData(coords)
    spheres = cloud.glyph(geom=pv.Sphere(radius=0.6), orient=False)
    plotter.add_mesh(spheres, color=color, smooth_shading=True)

plotter.show()

Estàs llegint una vista prèvia.

Inicia sessió amb Google per llegir la pàgina completa.

Inicia sessió amb Google

Amb qualsevol compte de Google. Només et demanarem que acceptis les condicions del servei.