Version 1.0.5
Cloud MRI simulation with an MRzeroCore-compatible Python API. mr0.simulate() talks to the modal HTTP backend (same as MATLAB).
# from GitHub: https://github.com/mrx-org/MRzeroCloud
pip install git+https://github.com/mrx-org/MRzeroCloud.git
# from PyPI
pip install MRzeroCloud
# from a local clone
pip install -e .Requires Python 3.9+, pypulseq for sequence building, and network access to a Modal HTTP endpoint.
The server runs pulseq_rs, so .seq files are validated locally
before upload: Pulseq version ≤ 1.5.0, ≤ 20 000 lines. Signal follows the
MRzeroCore 1.0 sign convention, so Cartesian recon uses ifft, not fft.
import MRzeroCloud as mr0
signal, ktraj_adc = mr0.simulate("gre.seq")
image = mr0.reco_pynufft(
signal,
ktraj_adc,
resolution=(64, 64, 1),
FOV=(0.256, 0.256, 0.003),
)
mr0.imshow(image)simulate, simulate_async, imshow, and stop_simulation are also
available under mr0.util for backwards compatibility.
Examples:
examples/load_gre_sim_recon_nufft.py— this quick start (examples/gre.seq,reco_pynufft)examples/load_gre_sim_recon_fft.py— samegre.seq, iFFT reconexamples/load_gre_sim_recon_bifti.py— bifti phantom by id (user/numerical_brain_cropped_bifti_2)examples/load_gre_sim_recon_pyodide.html— same GRE in the browser (Pyodide)
Upload a .seq file, poll a job, download (signal, ktraj) as NPZ.
The default gateway is already configured, so no setup is needed. simulate() runs MRzeroCore execute_graph there.
import MRzeroCloud as mr0
signal, ktraj = mr0.simulate("gre.seq")
# optional GPU tier (cpu, t4, a10g, a100); default t4
signal, ktraj = mr0.simulate("gre.seq", worker="a10g")accuracy is a client argument (default 1e-3), the same knob as MRzeroCore.util.simulate. It is not a Modal job field. The client sends min_emitted_signal and min_latent_signal equal to accuracy, and a fixed prepass of min_state_mag=1e-5, max_state_count=2000.
Local dev or your own deployment — point the backend somewhere else:
modal deploy modal_app.py
# use the printed gateway URL, e.g.
# https://YOUR-WORKSPACE--tool-mr0sim-modal-http-gateway.modal.runmr0.api.configure(urls={"modal": "http://127.0.0.1:8080"})With no config, simulation uses the cached bifti phantom
user/numerical_brain_cropped_bifti on the t4 worker pool, with res/affine
matching that phantom's native grid — identical to mr0.defaultConfig() in the
MATLAB package. The gateway reslices bifti phantoms server-side and requires both
res and affine on every job, so override them together via
config["phantom_bifti"], config["res"], and config["affine"].
backend="mcp" simulates through the MRX MCP gateway instead:
rapisim for the signal and trajex for the k-space trajectory. Authenticate with a personal
API key. Create it at https://mrx-org--mcp-gateway-func.modal.run/keys (GitHub login).
The key acts as your GitHub user, so uploads land in your files.
import MRzeroCloud as mr0
mr0.api.configure(mcp_token="mrx_...") # or set MRX_API_KEY
signal, ktraj = mr0.simulate("gre.seq", backend="mcp", min_mag=1e-4)
# or select the backend through the config
config = mr0.api.default_mcp_config()
config["phantom_bifti"] = "endres-bifti_demo-001/subj42-3T.json" # collection/file_name
config["res"] = [64, 64, 1] # optional, together with
config["affine"] = [[3.4375, 0, 0, -110], [0, 3.4375, 0, -110], [0, 0, 8, 0]] # affine (mm)
signal, ktraj = mr0.simulate("gre.seq", config=config)- Phantoms come from the bifti registry, given as
collection/file_name, or as the sha256 of a bifti zip already in your files. Withoutres/affinethe phantom's own grid is used. With them, the client rewrites the bifti'sreslice_to, uploads the result and simulates on that grid. The upload is cached per process. min_magis the precision knob for rapisim and trajex.accuracy,workeranduse_gpudo not apply. trajex simulates one voxel witht1/t2(default 1 s / 0.1 s) to find the trajectory.config["sampler"](direct,fft,fft_modulated) andconfig["kernel_size"]go to rapisim.- The trajectory is
(N, 4): kx, ky, kz in 1/m, plus t in s. - No progress or abort yet.
Generated protocol artifacts can register AnyField metadata:
import MRzeroCloud as mr0
config = mr0.api.load_config(_anyfield_json)
signal, ktraj = mr0.simulate(seq, config=config)
image = mr0.reco_pynufft(signal, ktraj, resolution=config["recon_matrix"], FOV=fov)Override the modal endpoint:
mr0.api.configure(urls={"modal": "http://127.0.0.1:8080"})Progress reporting:
mr0.api.configure(on_message=lambda msg: print(msg) or True)
mr0.api.configure(verbose=False) # silence built-in progress outputconfigure only applies the arguments you pass, and url overrides accumulate across
calls. Use mr0.api.reset_configuration() to go back to the built-in defaults.
See MRzerocloud_m for a MATLAB package with the same modal HTTP workflow (mr0.simulate, mr0.configure, mr0.loadConfig).
| MRzeroCore | MRzeroCloud | |
|---|---|---|
| Import | import MRzeroCore as mr0 |
import MRzeroCloud as mr0 |
| Simulate | Local Bloch graph | Modal HTTP |
| Phantom | VoxelGridPhantom / .mat |
bifti registry |
| Recon | mr0.reco_adjoint |
mr0.reco_adjoint (same API); mr0.reco_pynufft for NUFFT |
- New
backend="mcp"for the MRX MCP gateway (rapisim + trajex). It authenticates with anmrx_API key (configure(mcp_token=…)orMRX_API_KEY) and takes its defaults frommr0.api.default_mcp_config(). simulate()also picks the backend fromconfig["backend"].
accuracystays onsimulate()(default1e-3, matchingMRzeroCore.util.simulate). It is no longer sent as a job field. The client sendsmin_emitted_signalandmin_latent_signalfromaccuracy, plus a fixed prepass (min_state_mag=1e-5,max_state_count=2000).
Drop Fly ToolAPI so Python matches MATLAB (modal HTTP only).
- Remove
toolapiand the Fly chain (conseq,phantomlib,trajex,mr0sim) simulate()only supportsbackend="modal"- Remove
load_phantom; pick a phantom withconfig["phantom_bifti"] mr0.api.default_config()is now the modal defaults (same as MATLABmr0.defaultConfig())configure(urls=…)only overrides the modal HTTP URL
simulate()defaults to the modal HTTP backend- Install from GitHub:
pip install git+https://github.com/mrx-org/MRzeroCloud.git - Examples:
examples/load_gre_sim_recon_nufft.py(reco_pynufft),examples/load_gre_sim_recon_fft.py(iFFT), andexamples/load_gre_sim_recon_bifti.py(bifti id), bundledexamples/gre.seq mr0.reco_adjointmatches the MRzeroCore API (dense adjoint DFT)
Package version tracks the MRzeroCore version on mr0-cloud.
- Fly ToolAPI (
mr0sim) and Modal HTTP simulation simulate,simulate.start/simulate_async,load_phantom,reco_pynufft,imshow- Modal defaults: cached bifti
user/numerical_brain_cropped_biftion the t4 worker - Pre-flight
.seqchecks: Pulseq version ≤ 1.5.0, file ≤ 20 000 lines - Cartesian recon uses ifft for the MRzeroCore 1.0 signal sign convention