Connect to CryoSPARC¶

In [1]:
%%bash
# find the licence id for your instance
cat /sw/cryosparc/cryosparc_worker/config.sh | grep -oP 'CRYOSPARC_LICENSE_ID="\K[^"]+'
[REDACTED]
In [2]:
from cryosparc.tools import CryoSPARC

cs = CryoSPARC(host="localhost", 
               base_port=39000, 
               license="[REDACTED]", # licence id above
               email="participant@noreply.com",
               password="Cryo-EMWorkshop2025"
              )
assert cs.test_connection()
Connection succeeded to CryoSPARC command_core at http://localhost:39002
Connection succeeded to CryoSPARC command_vis at http://localhost:39003
Connection succeeded to CryoSPARC command_rtp at http://localhost:39005

Load particles from flex train¶

In [3]:
# fill out as appropriate for your project!
project = cs.find_project("P2")
workspace = project.find_workspace("W1")
job_flextrain = project.find_job("J20")
In [4]:
particle_dataset = job_flextrain.load_output("particles")
particle_dataset
# components_mode_0/value and components_mode_1/value are the Flex latents at the current checkpoint
# once the job is complete, this dataset will include all passed through information (ctf, alignments3D, etc.)
Out[4]:
uid components_mode_0/component components_mode_0/value components_mode_1/component components_mode_1/value
0 1779700710537823949 0 -0.5173333883285522 1 0.3893333375453949
1 9029280422963986132 0 0.8266666531562805 1 -0.005333326291292906
2 5511921049727446425 0 0.5386666655540466 1 1.4346667528152466
3 18049292750063892067 0 -0.9120000004768372 1 -0.2720000147819519
4 10552935038128461132 0 0.06933334469795227 1 -0.36800000071525574
... ... ... ... ... ...
137996 16003989330585177938 0 1.2640000581741333 1 -0.24000000953674316
137997 7494929393788351034 0 -0.42133334279060364 1 1.2106666564941406
137998 17203334619651482593 0 -0.6666666865348816 1 0.4533333480358124
137999 7348860851528375692 0 0.2613333463668823 1 -0.35733333230018616

Inspect latents¶

In [5]:
import numpy as n
import matplotlib.pyplot as plt
In [6]:
latent_x = particle_dataset["components_mode_0/value"][::10]
latent_y = particle_dataset["components_mode_1/value"][::10]
plt.clf()
plt.scatter(latent_x, latent_y, s= 0.2)
plt.xlabel('3DFlex Latent 0')
plt.ylabel('3DFlex Latent 1')
plt.grid()
plt.show()
No description has been provided for this image

GUI for selecting a custom latent trajectory¶

In [7]:
%matplotlib widget

fig = plt.figure(figsize=(5, 5))
def do_plot():
    plt.plot(latent_x, latent_y, ".", alpha=0.5, color="gray")
    plt.grid()
do_plot()
pts = []
def onclick(event):
    fig.clf()
    do_plot()
    pts.append([event.xdata, event.ydata])
    apts = n.array(pts)
    plt.plot(apts[0, 0], apts[0, 1], "xk")
    plt.plot(apts[:, 0], apts[:, 1], ".-r")

cid = plt.gcf().canvas.mpl_connect("button_press_event", onclick)
Figure
No description has been provided for this image
In [13]:
# this is the latent trajectory!
traj_pts = n.array(pts)
traj_pts
Out[13]:
array([[-0.027456  ,  0.97922359],
       [ 0.54700801,  0.91120074],
       [ 1.12147203,  0.57108644],
       [ 1.10457603, -0.16015929],
       [ 0.82579202, -0.6363193 ],
       [ 0.32736001, -0.84889073],
       [-0.60192001, -0.73835359],
       [-1.20172803, -0.42374787],
       [-1.11724803,  0.21396643],
       [-0.83001602,  0.72413787],
       [-0.34003201,  1.00473217],
       [-0.0528    ,  1.00473217]])

Save this trajectory as an output of an external CryoSPARC job¶

In [14]:
# save latent trajectory into an external job
job_traj = project.create_external_job(workspace.uid, "Custom Latents")
In [15]:
num_components = 2

slot_spec = [{"dtype": "components", 
              "prefix": f"components_mode_{k}", 
              "required": True} for k in range(num_components)]

job_traj.connect("particles", job_flextrain.uid, "particles")
Out[15]:
True
In [16]:
latents_dset = job_traj.add_output(
    type="particle",
    name="latents",
    slots=slot_spec,
    title="Latents",
    alloc=len(traj_pts),
)
In [17]:
for k in range(num_components):
    latents_dset[f"components_mode_{k}/component"] = k
    latents_dset[f"components_mode_{k}/value"] = traj_pts[:, k]
In [18]:
latents_dset
Out[18]:
uid components_mode_0/component components_mode_0/value components_mode_1/component components_mode_1/value
0 9198829713535165130 0 -0.027456000447273254 1 0.9792236089706421
1 1298556455980385392 0 0.5470080375671387 1 0.911200761795044
2 1529880111780437420 0 1.1214720010757446 1 0.5710864663124084
3 1205321613982979386 0 1.1045759916305542 1 -0.16015928983688354
4 5644573043028253354 0 0.8257920145988464 1 -0.6363192796707153
... ... ... ... ... ...
8 4847364479645166273 0 -1.1172480583190918 1 0.21396642923355103
9 14866076990203045904 0 -0.830016016960144 1 0.7241379022598267
10 13078576875432255908 0 -0.34003201127052307 1 1.0047321319580078
11 414831365467218665 0 -0.052799999713897705 1 1.0047321319580078
In [19]:
# add our figure to the job event log
job_traj.log_plot(fig, text="Custom Latent Trajectory")
Out[19]:
'683f1550890bef441f8d3af3'
In [20]:
# run and save the output
with job_traj.run():
    job_traj.save_output("latents", latents_dset)
In [ ]: