Skip to content

Instantly share code, notes, and snippets.

@alisterburt
Created February 3, 2025 18:15
Show Gist options
  • Save alisterburt/e970ff7bdc3422bcc2fdbcb84eb974a3 to your computer and use it in GitHub Desktop.
Save alisterburt/e970ff7bdc3422bcc2fdbcb84eb974a3 to your computer and use it in GitHub Desktop.
standalone dynamo to warp particle metadata conversion, to run `uv run dynamo2warp.py`
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "dynamotable",
# "pandas",
# "scipy",
# "starfile",
# "typer",
# ]
# [tool.uv]
# exclude-newer = "2025-01-01T00:00:00Z"
# ///
import re
from pathlib import Path
import dynamotable
import pandas as pd
import starfile
import typer
from scipy.spatial.transform import Rotation as R
def cli(
input_table_file: Path = typer.Option(..., '--input', '--i', help='input table file'),
table_map_file: Path = typer.Option(..., '--table-map', '--tm', help='table map file'),
output_star_file: Path = typer.Option(..., '--output', '--o', help='output star file'),
):
# read table file
df = dynamotable.read(input_table_file, table_map_file=table_map_file)
# extract relevant metadata
positions = df[['x', 'y', 'z']].to_numpy()
shifts = df[['dx', 'dy', 'dz']].to_numpy()
dynamo_euler_angles = df[['tdrot', 'tilt', 'narot']].to_numpy()
# convert dynamo euler angles into rotation matrices in which the
# columns are the particle x/y/z vectors in the tomogram
particle_rotation_matrices = R.from_euler(
angles=dynamo_euler_angles, seq='zxz', degrees=True
).inv().as_matrix()
# construct particle metadata for RELION
positions += shifts
relion_euler_angles = R.from_matrix(particle_rotation_matrices).inv().as_euler(
seq='ZYZ', degrees=True
)
tomogram_files = df['tomo_file'].to_list()
tomostar_files = [
re.sub(pattern=r".mrc_\d+.\d+Apx.mrc", repl=".tomostar", string=tomogram_file)
for tomogram_file
in tomogram_files
]
# write out RELION style star file compatible with Warp
star_data = {
'rlnCoordinateX': positions[:, 0],
'rlnCoordinateY': positions[:, 1],
'rlnCoordinateZ': positions[:, 2],
'rlnAngleRot': relion_euler_angles[:, 0],
'rlnAngleTilt': relion_euler_angles[:, 1],
'rlnAnglePsi': relion_euler_angles[:, 2],
'rlnMicrographName': tomostar_files,
}
starfile.write(pd.DataFrame(star_data), output_star_file)
if __name__ == "__main__":
app = typer.Typer(add_completion=False)
app.command(no_args_is_help=True)(cli)
app()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment