Skip to content
LBEM-CHPublic

About

No description, website, or topics provided.

Resources

Code of conduct

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rohlex

Roll your helix.

Interactive triage of helical-filament segments from a Dynamo or RELION 5 subtomogram-averaging project. It reconstructs the per-filament helical roll check (subunit roll vs. real position along the filament axis, compared to the known screw) and lets you mark bad segments for removal. Built to run over ssh -XY and stay responsive (PyQt6 + pyqtgraph, raster renderer, no OpenGL).

See docs/README.md for the full method.

What it does

For one tomogram it loads either input — the two refined_table_ref_00X_iteYYYY.tbl tables from a Dynamo averages folder, or a RELION 5 tomography particles .star — and for each filament:

  • fits the axis through the 3D coordinates (origin = centroid, the mean of all segments, not the middle one; direction = least-squares fit through every segment),
  • projects each segment onto the axis → real position (Å, via the pixel size),
  • reads the subunit roll about the axis,
  • compares to the screw model roll = (twist/rise)·pos + phase.

Inputs. Dynamo: concatenates and sorts the ref tables by tag, groups filaments by column 23, poses from the ZXZ-extrinsic Eulers. Point it at the project folder (…/abp_align_eo) and it auto-finds results/ite_*/averages/, uses the last real iteration as the working set (the empty N+1 placeholder is skipped), and keeps the earlier iterations for the per-segment convergence paths; a single averages/ folder also works (no paths). RELION: groups by _rlnHelicalTubeID, coordinates from _rlnCoordinateX/Y/Z, and converts the poses (_rlnTomoSubtomogram* combined with _rlnAngle*, or _rlnAngle*Prior when no refined angles exist) back to the Dynamo convention so both paths share one fit. The pixel size is read from the star optics block (override with --pixelsize). Point it at a Refine3D job folder (containing run_data.star + run_it*_data.star) and it reads run_data.star as the working set and the run_it* files as the per-iteration history (run_it000 = start); a single .star also works (no paths).

A segment whose alignment drifted lands at its true (wrong) position and visibly leaves the model line — that's what you mark.

Overview window

  • A scrollable grid of per-filament panels (roll vs position + dashed model).
  • The tomogram XY map on the right.
  • Hover a panel → that filament lights up on the map.
  • Click a panel → open its detail window.
  • Panels with marked segments turn red.

Detail window (one filament)

  • Three linked plots: roll vs position, residual to model, XY map.
  • Point at a segment in any plot → it highlights in all three, with a readout (tag, position, roll, delta).
  • Mark for removal: left-drag a rubber-band box to mark, right-drag to unmark, click Select all in filament, or click individual points to toggle. Clear filament unmarks the whole tube. Marks are red everywhere and saved immediately.
  • Iteration paths (Dynamo project folder, or RELION Refine3D job folder): a thin grey trail per segment showing how its roll moved from the starting value (grey dot, iteration 0 — Dynamo ite_0001/starting_values/, RELION run_it000_data.star) through each refinement iteration to the final pose (the colored dot). Intermediate iterations are line-only. The trail is drawn in the same unwrapped frame as the panel: each iteration's roll is placed on the turn nearest that segment's final value, so a trail always ends on its own dot and never wanders more than half a turn from it. A segment whose trail wanders never settled. Toggle it off in the toolbar; solid line (vs the dashed model), beneath the dots.

Iteration slider (overview)

An iteration slider under the toolbar scrubs every panel back through the refinement. Reading all the iterations takes a few seconds, so it is not done at startup: point the tool at the refinement job folder and press load iterations next to the slider (or launch with --iteration-paths to have it ready immediately). If the slider reads n/a with no load button, the path has no history — you are pointing at a single .star rather than the job folder that holds run_it*_data.star.

Drag it and the whole grid redraws as the rolls were at that iteration; the readout beside it reports the twist measured from the rolls on screen (the same robust per-filament slope vote the auto-fit uses), against iteration 0 and the final value — so you can watch, and quantify, the screw flattening as refinement proceeds. This is the intended way to see a measured twist decay across refinement. Two distinct causes produce that decay, and the job's note.txt tells you which one you have:

  • Symmetry applied (--helix without --ignore_helical_symmetry) — the case in Where the method does not apply (docs/README.md §13): rot is defined only modulo the screw operator, so the accumulated phase is folded and the slope is attenuated.
  • Symmetry ignored, rot unrestrained (--ignore_helical_symmetry with --sigma_rot 0) — nothing ties consecutive segments' rot to their position, so the screw present in the picking geometry simply washes out toward zero.

Either way the late-iteration twist is not the filament's twist; iteration 0 is the honest one.

Coordinates never move between iterations — only the poses — so positions, tags and the fitted axis are shared, and only the roll and its colouring change. Notes:

  • Marks apply to segments, not to iterations. auto-exclude and exclude bad tilt judge the iteration on screen, so marking at several iterations simply accumulates into the one remove list. That is expected and supported.
  • Flips are disabled off the final iteration — a flip rewrites the pose, which is only meaningful on the working set. Press final first. For the same reason, committed flips are shown only at the final iteration.
  • Opening a filament (clicking a panel) always shows the final iteration; the detail window's own Iteration paths trail is the per-segment view of the same history.

Live helix controls

Both windows carry twist / rise / pixel size spin boxes (rise in Å, pixel size in Å/px). Retune any of them and every model overlay refits instantly at real Å scale; the two windows stay in sync. Use this to dial the screw onto the data before triaging.

3D view (per filament)

The View 3D button lives in the per-filament detail window (click a panel first), so the 3D scene is always scoped to one filament — which keeps it fast, since only that filament's density is ever built. It shows the filament's particles as points colored by position (marked-for-removal in red, live), the 3D backbone, and a pose triad per particle so you can see the orientations screw along the axis. If you pass a refined average map (--map run_class001.mrc, or load one from the 3D window's "Load map…"), its isosurface is placed and oriented at every particle of that filament, with a threshold slider and a convention toggle (as-is vs inverse) to confirm the placement looks continuous.

The app launches in 2D; 3D is opened on demand from a filament. It needs OpenGL (PyOpenGL), which the 2D windows avoid. Forwarded X (ssh -XY) usually has no usable GLX, and Qt would otherwise abort at startup trying to initialize it — so over SSH the app disables the xcb GLX integration (2D runs fine) and greys out the View 3D button. To use 3D, run locally, or force it with --gl (e.g. under VirtualGL / vglrun); --no-gl forces it off. The OpenGL/mrc packages are imported only when you actually open the 3D view.

Output / resume

Marked segments are written continuously to a plain text file (default <dir>/remove_list.txt), one id per line, sorted — the Dynamo tag (column 1) for Dynamo, or the _rlnTomoParticleId for RELION. This file is:

  • the resume list — reloaded automatically on the next launch, and
  • the export — feed it to your own .tbl / .star cleanup (the app does not edit the input).

For Dynamo it also writes temp.tbl (the sorted working rows for the chosen tomogram), matching the notebook; disable with --no-temp.

Install

Dependencies (both methods below install all of them):

packages needed for
core numpy, scipy, PyQt6, pyqtgraph the 2D app
RELION eulerangles --relion (RELION→Dynamo pose conversion)
3D view PyOpenGL, mrcfile the per-filament "View 3D" (OpenGL + reading the map)

PyQt6 comes from PyPI (conda-forge ships only PyQt5), so the GUI stack is pip-installed on every route — including inside the conda env.

Simplest: pip (macOS, Windows, Linux-with-libs)

cd rohlex
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt          # PyQt6 + pyqtgraph + scipy/numpy + eulerangles + PyOpenGL + mrcfile

On macOS (incl. Apple Silicon) and Windows this just works — native windowing + OpenGL, no extra system libraries. On Linux it relies on libxcb-cursor0 (PyQt6 ≥ 6.5) and libGL/GLX being present — see the fallback below if launching errors out.

Linux, no root: conda for the system libraries

On a shared Linux cluster where you can't sudo apt install, let conda supply the missing system libraries (the Qt binding still comes via pip per environment.yml):

cd ~/LBEM/rohlex
conda env create -f environment.yml             # python + numpy/scipy (conda), Qt stack (pip)
conda activate rohlex
conda install -c conda-forge xcb-util-cursor    # provides libxcb-cursor.so.0 (Linux only)

If a pip-venv launch fails with "xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin", either sudo apt install libxcb-cursor0 (one-time, all users), or — with no root — drop the single library into your home dir and point LD_LIBRARY_PATH at it:

cd /tmp && apt-get download libxcb-cursor0 && dpkg -x libxcb-cursor0_*.deb x
mkdir -p ~/.local/lib && cp x/usr/lib/*/libxcb-cursor.so.0* ~/.local/lib/
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH

The bundled run.sh sets that LD_LIBRARY_PATH for you and runs the venv Python. None of this applies on macOS/Windows. The 2D app needs no OpenGL — the 3D extras are only touched when you click View 3D — so a missing OpenGL stack never blocks 2D triage.

Run

The GUI needs a display, so connect with X11 forwarding first:

ssh -XY user@cluster
conda activate rohlex          # or: source .venv/bin/activate
cd ~/LBEM/rohlex

# Dynamo project folder (auto-finds results/ite_*/averages, shows iteration paths)
python rohlex.py \
  /mnt/.../dynamo_project_b4/abp_align_eo \
  --tomo 1 --twist -1.4 --rise 4.75 --pixelsize 7.92

# RELION 5 (auto-detected from the .star extension)
python rohlex.py \
  /mnt/.../warp/relion_b4_clean/particles_new_relion5.star \
  --twist -1.4 --rise 4.75 --out ~/relion_remove_list.txt

With the pip venv (no conda) on this cluster, swap the launch line for ./run.sh <path> [options], which adds the local libxcb-cursor shim automatically.

The format is inferred from path (.star → RELION, folder → Dynamo); force it with --dynamo / --relion.

Options: --tomo (Dynamo col-20 id or RELION _rlnTomoName; else only/first or a chooser), --twist (°/subunit), --rise (Å/subunit), --pixelsize (Å/px; RELION default from the star optics, Dynamo default 7.92), --map (reference average .mrc/.em for the 3D density overlay), --cols (overview columns), --out (remove-list path; point it somewhere writable if the input sits on read-only storage), --no-temp, --iteration-paths (read every iteration up front; enables the overview iteration slider and the detail-window convergence trails). Twist, rise and pixel size are also live in the GUI.

Requires Python 3.9+. --relion additionally needs the eulerangles package (included in both environment.yml and requirements.txt).

About

No description, website, or topics provided.

Resources

Code of conduct

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages