Mask artefacts in RBMC particles?

Hi,

In some of the raw particle images after RBMC, I see what look suspiciously like mask-edge artifacts around the particle (see example below). Does anybody else see these, and are they something to be concerned about? Perhaps a softer mask needed? They are not this apparent in all the particles, but scanning through there are some with a distinct edge/halo around the particle…

Cheers
Oli

I think I see what you mean - the lighter halo around the particle? Haven’t noticed anything myself. I’ve got RBMC runs with and without a static mask applied, particles look reasonable and from a quick check of three runs none appear to have that halo.

How long did the run take (and how many particles?) Would be interesting to see if a maskless run didn’t show that halo. Is it a realistic check in terms of time/resources?

1 Like

yes that halo is what I mean! Good point - I will run the motion correct step without a mask (using the same hyperparameters) and see how it looks. Small particle though (55kDa) so not sure it will behave well without a mask - will try!

I tried without a mask, but in that case it autocalculates one… would need to explicitly provide a mask covering the entire box - will try that…

Ok tried with a cubic mask - can’t see the same artifacts, but would need to compare directly to the equivalent non-RBMC particle to be sure

1 Like

Hi @olibclarke. Very interesting, thanks for reporting this. We have not observed this ourselves, but we are very interested to hear your findings if/as you continue to investigate.
– Harris

1 Like

Hi @hsynder,

I would like to follow up on this by directly comparing RBMC and non-RBMC particles, but it is a little tricky, as the RBMC particle stacks are named thusly:

And these numbers do not seem to correspond to the UIDs of the parent images. How do I figure out which stack belongs to which micrograph? I guess I can just run RBMC on a single mic, now that I think about it - but it would be easier to check an existing job…

Cheers
Oli

Hi @olibclarke! If you’re wanting to find the mrc for each mic, you can use cs-tools. For example:

from cryosparc.tools import CryoSPARC, lowpass2
import json
import numpy as np
from pathlib import Path
import matplotlib.pyplot as plt

with open(Path('~/instance-info.json').expanduser(), 'r') as f:
    instance_info = json.load(f)

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

rbmc_uid = "J104"
rbmc_job = project.find_job(rbmc_uid)
rbmc_particles = rbmc_job.load_output("particles_0")

# arbitrarily picking the first mic here
mic_uid = rbmc_particles["location/micrograph_uid"][0] # 4693875069840635955
first_mic = rbmc_particles.query({"location/micrograph_uid": mic_uid})
print(np.unique(first_mic["blob/path"]))

# prints ['J104/reconstructed/4693875069840635955_particles.mrc']

(as an aside, in my case, the UID in the RBMC particles mrc matched the mic UID in “location/micrograph_uid” for all particles in the dataset)

Or, to compare images, you could do:

def get_images(particle_uid):
    particle_pmc = pmc_particles.query({"uid": particle_uid})[0]
    particle_rbmc = rbmc_particles.query({"uid": particle_uid})[0]

    # if you're comparing lots of particle images, you may want to save these
    # headers and images in a dictionary so that you're not downloading the same
    # one over and over again

    pmc_hdr, pmc_mrc = project.download_mrc(project.dir() / particle_pmc["blob/path"])
    pmc_im = pmc_mrc[particle_pmc["blob/idx"]]

    rbmc_hdr, rbmc_mrc = project.download_mrc(project.dir() / particle_rbmc["blob/path"])
    rbmc_im = rbmc_mrc[particle_rbmc["blob/idx"]]

    return (pmc_hdr, pmc_im, rbmc_hdr, rbmc_im)

def particle_imshow(im, hdr = None, ax = None, lowpass = 20):
    if ax is None:
        fig, ax = plt.subplots(1, 1, figsize = (2, 2), layout = "constrained")
    else:
        fig = ax.get_figure()

    if lowpass is not None:
        if hdr is None:
            raise ValueError("Must include particle image header if lowpass filtering")
        im = lowpass2(im, hdr.xlen / hdr.nx, lowpass)

    ax.imshow(
        im,
        cmap = "Greys_r",
        origin = "lower",
        interpolation = "nearest",
    )
    ax.set_aspect("equal")
    ax.axis("off")

    return fig, ax

def plot_compare(pmc_hdr, pmc_im, rbmc_hdr, rbmc_im, lowpass = 20):
    fig, axs = plt.subplots(1, 2, figsize = (4, 2), layout = "constrained")
    particle_imshow(pmc_im, pmc_hdr, ax = axs[0], lowpass = lowpass)
    particle_imshow(rbmc_im, rbmc_hdr, ax = axs[1], lowpass = lowpass)
    return fig, axs

particle_uid = pmc_particles["uid"][0]
plot_compare(*get_images(particle_uid))

which produces this plot:

2 Likes