RBMC and symmetry expansion


I am aware of the problems of running RBMC on symmetry expanded particles, so Ithought I try it in another way. This is the rough workflow for a particle with ~C6 symmetry:

  • Consensus refine (1,369,446 particles)
  • C6 Symmetry expand (8,216,676 particles)
  • (extensive) classification without alignment with mask on region of interest
  • local refinement with mask on region of interest (233,953 particles (from the symmetry-expanded set, so some original particles are used more than once))

I would now like to finalize this map. I thought it should be possible to run RBMC on the particle set from the Consensus refine and then connect the blob output group to re-run the local refinement (i.e. it should take the RBMC polished particles). However, I can see from the particle number in this local refinement (51547) that the particles are only used once, while it should be used between 1-6 times (depending on how many symmetry-expanded poses survived the classification).

Has anybody found a way around that? I thought about using csparc2star to hack it myself (make star file, then replace paths to polished particles, re-import), but the particles are renumbered and renamed during RBMC, making this approach quite tricky. I guess I could fine which particle is which by a combination of what movie it originated from and the X/Y coordinates, but that’s pretty cumbersome…

Would appreciate some input!


Hi @Moritz!

When we replace fields using the low-level interface, we use the particles’ UID to determine which value should go where. Symmetry-expanded particles get their own UID, so the RBMC blobs will only match a single copy of the symmetry-expanded particles (those with an unchanged pose and UID).

Unfortunately, there’s no way around this in the CryoSPARC GUI. You could use CryoSPARC tools to replace the relevant fields in each symmetry-expanded particle by matching the symmetry-expanded particle’s sym_expand/src_uid to the uid of the RBMC job, like so:

from cryosparc.tools import CryoSPARC
import json
from pathlib import Path
with open(Path('~/instance-info.json').expanduser(), 'r') as f:
    instance_info = json.load(f)

cs = CryoSPARC(**instance_info)
assert cs.test_connection()

project_number = "P337"
workspace_number = "W7"
project = cs.find_project(project_number)

# this should be the job ID for your local refined, sym-expanded particles
sym_exp_job_id = "J47"
sym_exp_job = project.find_job(sym_exp_job_id)
sym_exp_p = sym_exp_job.load_output("particles")

rbmc_job_id = "J48"
rbmc_job = project.find_job(rbmc_job_id)
rbmc_p = rbmc_job.load_output("particles_0")

uid_to_blob = {}
blob_fields = [f for f in sym_copy.fields() if f.split('/')[0] == 'blob']
for row in rbmc_p.rows():
    uid = row['uid']
    uid_to_blob[uid] = {f: row[f] for f in blob_fields}

sym_copy = sym_exp_p.copy()
# RBMC excludes particles which moved off the edge of the micrograph,
# so we should keep only particles which are still in the RBMC job
sym_copy = sym_copy.query({'sym_expand/src_uid': rbmc_p['uid']})
for row in sym_copy.rows():
    for f in blob_fields:
        row[f] = uid_to_blob[row['sym_expand/src_uid']][f]

    workspace_uid = workspace_number,
    dataset = sym_copy,
    type = 'particle',
    slots = ['blob'],
    passthrough = (sym_exp_job_id, 'particles'),
    title = 'Symmetry expanded RBMC particles'


thanks a lot, I got it to run with this! I adjusted the script slightly (moved the definition of ‘sym_copy’ up a couple of lines). Had a bunch of errors at first, but @rposert pointed out to me that my cryosparc-tools version was not up-to-date and hence not the same as my cryoSPARC version. Updated to 4.4.1 and it works like a charm. Thanks for the help!