Homepage#
pulserver orchestrates MR acquisitions with Pulseq sequences on clinical scanners: sequence design, scanner preparation and reconstruction. It resolves the protocol an operator edits in the scanner UI against a pypulseqpp sequence function, converts the design into the segmented representation a scanner interpreter plays, and routes the raw data of each series, enriched from the sequence that acquired it, to a reconstruction, normally bartorch. Vendor-specific playout belongs to the scanner interpreters, which call pulserver’s services. Passing the checks pypulseqpp provides does not establish scanner or patient safety.
Try the virtual scanner in your browser: https://pulserver.github.io/MaRGE/.
Features#
Protocol resolution: the echo time, repetition time and bandwidth a design achieves, the scan time, and the design error for an infeasible prescription.
Stateless design calls for every interpreter host process of a scanner, one command per call or through a warm server, and a store of immutable designs named by their content.
Segmentation of a
NextSequencechain into a binary IR cache, read by an ANSI C library linked into the interpreter, with the prescribed field-of-view offset applied to the logical-frame design as RF and ADC frequency and phase.MRD enrichment: encoding counters, flags, encoding spaces and trajectories from the sequence.
Reconstruction plugins run in isolated worker processes, over a live MRD stream, an ISMRMRD file or an assembled acquisition bucket.
Quick start#
pip install pulserver bartorch
A sequence plugin binds a pypulseqpp sequence function, a function that returns the designed sequences, to the scanner protocol, and a reconstruction plugin reconstructs the series it acquires. The client of a scan chooses the reconstruction, independently of the sequence. The plugin below evaluates a protocol by designing the sequence, which states the scan time and refuses a prescription the design cannot realize:
# sequences/gre.py
from pypulseqpp import sequences
from pypulseqpp.sequences.sequence.gre2D_sequence import gre2d
from pulserver.design import Evaluation, SequencePlugin, TimeParam, UIParam
class Gre(SequencePlugin):
app = gre2d
protocol = {UIParam.TE: TimeParam("te", range_min=3000, range_max=20000)} # µs
def evaluate(self, system, protocol):
scan = self.app(system, **protocol.arguments)
return Evaluation(protocol, sequences.duration(scan))
# recon/gre.py
import torch
import bartorch.tools as bt
from bartorch import apps, priors
from pulserver import recon
class Pics(recon.ReconPlugin):
def recon(self, context, branch, data):
kspace = torch.from_numpy(data.data.kspace) # (coils, y, x)
maps = bt.ecalib(kspace, maps=1)
image = apps.pics(kspace, maps, regularizers=priors.Wavelet((-1, -2), 0.005))
return recon.ReconResult(image.abs().numpy())
PLUGIN = Pics()
Scan a phantom on the virtual scanner and reconstruct it:
printf '[Limits]\nB0: 3.0\n[Limits End]\n' > limits.txt
pulserver proxy --store designs --port 9002 --plugins recon &
pulserver scan --plugins sequences --plugin gre --reconstruction gre \
--limits limits.txt --store designs --recon 127.0.0.1:9002 --output images
The shipped sequences and reconstructions are found by name after the given
directories, so --plugin gre_radial2d or --reconstruction pics needs no file
of its own. A scan of a shipped sequence that names no reconstruction uses the
shipped reconstruction paired with it. On a scanner, the interpreter makes the
same design calls, and the reconstruction client streams to the same proxy and
names its reconstruction in its config.
Documentation#
The user guide covers installation and support, running the two services, and writing scanner-sequence and reconstruction plugins. The explanations describe the architecture, protocol resolution, the design store, the scanner representation, the virtual scanner and raw-data enrichment, and the examples are a course from a protocol to a reconstructed image, followed by Tours of specialised workflows, each executed when the documentation is built. Every version of the documentation is published at https://pulserver.github.io/pulserver/.
Citation#
pulserver has no project publication. Cite the formats it is built on in work that uses it:
@article{layton2017pulseq,
title = {Pulseq: a rapid and hardware-independent pulse sequence prototyping framework},
author = {Layton, Kelvin J and Kroboth, Stefan and Jia, Feng and Littin, Sebastian
and Yu, Huijun and Leupold, Jochen and Nielsen, Jon-Fredrik
and St{\"o}cker, Tony and Zaitsev, Maxim},
journal = {Magnetic Resonance in Medicine},
volume = {77},
number = {4},
pages = {1544--1552},
year = {2017},
doi = {10.1002/mrm.26235}
}
@article{inati2017ismrmrd,
title = {{ISMRM} Raw data format: A proposed standard for {MRI} raw datasets},
author = {Inati, Souheil J and Naegele, Joseph D and Zwart, Nicholas R
and Roopchansingh, Vinai and Lizak, Martin J and Hansen, David C
and Liu, Chia-Ying and Atkinson, David and Kellman, Peter
and Kozerke, Sebastian and Xue, Hui and Campbell-Washburn, Adrienne E
and S{\o}rensen, Thomas S and Hansen, Michael S},
journal = {Magnetic Resonance in Medicine},
volume = {77},
number = {1},
pages = {411--421},
year = {2017},
doi = {10.1002/mrm.26089}
}
License#
MIT. See License and notices.