JEMRIS  2.8.1
open-source MRI simulations
Running JEMRIS from the Command Line

The above introduced Matlab GUIs follow the same procedure: construct a valid XML file from the user input, then call the external JEMRIS executables to compute the data, and finally read and visualise the result. Of course it is possible to directly run the executables without running Matlab. For this, the XML configuration files might be directly manipulated to set up the numerical experiments.

This section presents example XML files and explains how to start the simulation from the command line:

Creating and editing XML configuration Files

There are three different types of XML files which configure a JEMRIS simulation:

The Sequence XML file

MRI sequences may be scripted directly in XML where the sequence and pulse modules are represented by XML elements. Their parameterization is done via attributes utilizing the observer mechanism. See section Sequence Building Modules for a list of available modules and their attributes. Section Analytical expressions describes the observer mechanism and symbolic attribute dependences.

This is an example of a 2D EPI sequence for 2D simulation (i.e. without slice selection).

<?xml version="1.0" encoding="utf-8"?>
<Parameters FOVx="256" FOVy="256" GradMaxAmpl="2" GradSlewRate="10" Name="P" Nx="64" Ny="64" TE="50" TR="100">
<ConcatSequence Name="C1">
<AtomicSequence Name="A1">
<HARDRFPULSE Axis="RF" Duration="0.1" FlipAngle="90" Name="P1"/>
<AtomicSequence Name="A2">
<TrapGradPulse Area="-0.5*abs(A)" Axis="GX" Name="P2" Observe="A=P4.Area"/>
<TrapGradPulse Area="KMY" Axis="GY" Name="P3" Observe="KMY=P.KMAXy"/>
<DelayAtomicSequence Delay="TE" DelayType="C2C" Name="D1" Observe="TE=P.TE" StartSeq="A1" StopSeq="C2"/>
<ConcatSequence Name="C2" Observe="NY=P.Ny" Repetitions="NY">
<AtomicSequence Name="A3">
<TrapGradPulse ADCs="NX" Axis="GX" FlatTopArea="2*KMX*(-1)^C" FlatTopTime="1"
Name="P4" Observe="KMX=P.KMAXx, C=C2.Counter, NX=P.Nx"/>
<AtomicSequence Name="A4">
<TrapGradPulse Area="ite(1+C,R,0,-DKY)" Axis="GY" Name="P5" Observe="DKY=P.DKy, C=C2.Counter, R=C2.Repetitions"/>
<DelayAtomicSequence Delay="TR" DelayType="B2E" Name="D2" Observe="TR=P.TR" StartSeq="A1"/>

The Coil Array XML file

As for the sequence, also coil array files can be directly scripted in XML. Elements represent the available coils (see section 'Coil array layout tool: JEMRIS_txrx' for a complete list and their parameterization). This is an example for an 8 channel phased array:

<?xml version="1.0" encoding="utf-8"?>
<BIOTSAVARTLOOP Azimuth="0" Dim="3" Extent="260" Name="C1" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="256" YPos="0" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="45" Dim="3" Extent="260" Name="C2" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="181.019" YPos="181.019" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="90" Dim="3" Extent="260" Name="C3" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="0" YPos="256" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="135" Dim="3" Extent="260" Name="C4" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="-181.019" YPos="181.019" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="180" Dim="3" Extent="260" Name="C5" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="-256" YPos="0" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="225" Dim="3" Extent="260" Name="C6" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="-181.019" YPos="-181.019" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="270" Dim="3" Extent="260" Name="C7" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="0" YPos="-256" ZPos="0"/>
<BIOTSAVARTLOOP Azimuth="315" Dim="3" Extent="260" Name="C8" Points="32" Polar="90" Radius="200" Scale="0.19" XPos="181.019" YPos="-181.019" ZPos="0"/>

The Simulation XML file

The simulation XML file contains elements for the XML file locations of the sequence, the coil arrays (transmit and receive), and the location of the sample HDF5-file (the object).
Examples of such samples as well as how to create user defined samples are described in section Object Properties.

Additionally, a few other parameters may be added via attributes of the "parameter" element which are documented in section 'Additional parameters' of the simulation GUI chapter.

This is an example for a simulation XML file generated by the MRI Simulation tool: JEMRIS_sim :

<?xml version="1.0" encoding="utf-8"?>
<simulate name="JEMRIS">
<sequence name="epi" uri="/data/mr_cluster/tstoecker/example/epi.xml"/>
<sample name="brain" uri="/data/mr_cluster/tstoecker/example/sample.h5"/>
<RXcoilarray uri="/usr/local/share/jemris/matlab/uniform.xml"/>
<TXcoilarray uri="/usr/local/share/jemris/matlab/uniform.xml"/>
<parameter ConcomitantFields="0" EvolutionPrefix="evol" EvolutionSteps="0" RandomNoise="0"/>
<model name="Bloch" type="CVODE"/>

Invoking the JEMRIS executable

Executing jemris on the command line without arguments shows the possible options:

me@my_box:~$ jemris
jemris 2.8 (d55bf728)
1. jemris <xml-file>
The file could be either a a) Simulation, b) Sequence, or c) Coilarray file,
so that a) the simultion is performed, b) a sequence diagram is written,
or c) the sensitivity maps are dumped, respectively.
2. jemris modlist
Writes the file mod.xml containing a list of all available modules.
-o <output_dir>: Output directory
-f <filename>: Output filename (without extension)
-x: Output sequence file for execution
-d <def>=<val>: Define custom sequence variable

The special case 'modlist' is used by the Sequence development tool: JEMRIS_seq to generate the list of modules. Therefore, framework extensions will automatically appear in the GUI.

Generating the Pulse Sequence Diagram Data

Running jemris with the EPI sequence XML file results in

me@my_box:~$ jemris /usr/local/share/jemris/examples/epi.xml
JEMRIS 2.2 r1480M
dump of sequence tree
TYPE CLASS NAME duration ADCs TPOIs | module specific
----------------------------------------------------------------- | ---------------
sequence-root--------> CONCAT CONCATSEQUENCE C1 100.000 4096 4488 | Repetitions = 1
|_ child 1 ------> ATOM ATOMICSEQUENCE A1 0.100 0 1 |
|_ child 1 ----> PULSE HARDRFPULSE P1 0.100 0 1 | Axis = RF , (Flipangle,Phase,Bandwidth,Channel) = (90,0,1e+16,0)
|_ child 2 ------> ATOM ATOMICSEQUENCE A2 0.654 0 5 |
|_ child 1 ----> PULSE TRAPGRADPULSE P2 0.654 0 3 | Axis = GX , Area = -0.908768
|_ child 2 ----> PULSE TRAPGRADPULSE P3 0.593 0 3 | Axis = GY , Area = 0.785398
|_ child 3 ------> ATOM DELAYATOMICSEQUENCE D1 4.072 0 1 | DelayType = C2C , StartSeq = A1 , StopSeq = C2
|_ child 1 ----> PULSE EMPTYPULSE eP_D1 4.072 0 1 | Axis = none
|_ child 4 ------> CONCAT CONCATSEQUENCE C2 90.448 4096 4480 | Repetitions = 64
|_ child 1 ----> ATOM ATOMICSEQUENCE A3 1.314 64 68 |
|_ child 1 --> PULSE TRAPGRADPULSE P4 1.314 64 68 | Axis = GX , Area = -1.81754 , FlatTop: (Area,time)= (-1.5708,1)
|_ child 2 ----> ATOM ATOMICSEQUENCE A4 0.099 0 2 |
|_ child 1 --> PULSE TRAPGRADPULSE P5 0.099 0 3 | Axis = GY , Area = -0.0245437
|_ child 5 ------> ATOM DELAYATOMICSEQUENCE D2 4.726 0 1 | DelayType = B2E , StartSeq = A1
|_ child 1 ----> PULSE EMPTYPULSE eP_D2 4.726 0 1 | Axis = none

Additionally, a HDF5-:file "seq.h5" is written which is read by the Matlab GUI to plot the sequence diagram.

The output shows that this sequence has in total 4096 ADC points. The sequence diagram is non-equidistantly sampled: it consists of 4488 TPOIs ("time points of interest") which are the ADCs plus some additional important time points (for instance the ramps of trapezoidal gradients). In the above example the HDF5-file "seq.h5" contains 4888 sampling points. The data is stored in a dataspace "seqdiag" with names "T", "RXP", "TXM", "TXP", "GX", "GY", and "GZ", each of size $N \times 1$ (column vectors) where $N$ is the number of sampling points.

Reading the sequence diagram HDF5-file in Matlab:

T = h5read('seq.h5','/seqdiag/T'); % temporal sampling points
RXP = h5read('seq.h5','/seqdiag/RXP'); % RF Receiver phase; unit: radiants; if negative, the TPOI was not an ADC
TXM = h5read('seq.h5','/seqdiag/TXM'); % RF Transmitter magnitude
TXP = h5read('seq.h5','/seqdiag/TXP'); % RF Transmitter phase; unit: radiants
GX = h5read('seq.h5','/seqdiag/GX'); % physical X-Gradient
GY = h5read('seq.h5','/seqdiag/GY'); % physical Y-Gradient
GZ = h5read('seq.h5','/seqdiag/GZ'); % physical Z-Gradient

Generating the Coil Sensitiviy Maps

Running jemris with a coil array XML file results in

me@my_box:~$ jemris 8chheadcyl.xml
JEMRIS 2.2 r1509M
dumping sensitivity maps to sensmaps.h5 ...

The coil sensitivity HDF5-file contains dataspaces "/maps/magnitude/00" and "/maps/phase/00" which hold 2D or 3D coil maps according to the grid size which is specified in the coil array XML file. If the coil-array has multiple channels (coils), the maps of the second coil are stored in datspaces "/maps/magnitude/01", "/maps/phase/01", etc.

Example to read the complex sensitivity HDF5-file in Matlab, assuming 4 coils with 2D-sensitivities:

for i = 1:4
a = h5read ('sensmaps.h5', sprintf('/maps/magnitude/%02d',i-1));
p = h5read ('sensmaps.h5', sprintf('/maps/phase/%02d',i-1));

Executing MRI Simulations

Running jemris with a simulation XML file

me@my_box:~$ jemris simu.xml
JEMRIS 2.2 r1509M
Model : Bloch , solver = CVODE
Sample : 2D sphere , spins = 7825
TxArray : /usr/local/share/jemris/matlab/uniform.xml
RxArray : /usr/local/share/jemris/matlab/uniform.xml
Sequence : /data/mr_cluster/tstoecker/jemris_paper_ex/epi.xml
Simulating | ************************************************** | 100% done
Actual simulation took 3.61 seconds.

The simulation result is stored to the HDF5-file "signals.h5".

The signal file contains the HDF5 datspace "/signal/times" of size $N \times 1$, the time points of each ADC event of the sequence, and the datspace "/signal/channel/00" where the acoording signals of size $3 \times N$ are stored, i.e. the x,y, and z component of the net magnetization at every time point. If a receive coil with multiple channels was used, the signals of channels 2,3, etc. are stores in datspaces "/signal/channel/01", "/signal/channel/02", etc.

Example to read the signal HDF5-file in Matlab, assuming 8 receiver channels:

T = h5read('signals.h5','/signal/times');
S = zeros(3,numel(T),8);
for i = 1:8
S(:,:,i) = h5read('signals.h5', sprintf('/signal/channels/%02i',i-1));

Exporting a Sequence to an MRI Scanner

Running jemris with the -x option exports the sequence in Pulseq format ( for execution on a real MRI scanner,

me@my_box:~$ jemris -x -d id=1 -f epi /usr/local/share/jemris/examples/epi.xml
me@my_box:~$ head -n 20 epi.seq
# Pulseq sequence format
# Created by JEMRIS 2.8
id 1
Num_Blocks 132
Rot_Matrix 0 -1 -0 1 0 -0 0 0 1
# Format of blocks:
1 0 1 0 0 0 0 0 0 0
2 0 0 1 2 0 0 0 0 0
3 1 0 0 0 0 0 0 0 0
4 0 0 3 0 0 0 0 0 1
5 0 0 0 4 0 0 0 0 0
6 0 0 5 0 0 0 0 0 1
7 0 0 0 4 0 0 0 0 0
8 0 0 3 0 0 0 0 0 1
9 0 0 0 4 0 0 0 0 0

This creates a file suitable to run on a scanner. The -x option indicates export, -d allows for custom definitions (such as scan ID), and the .seq file is named according to the -f option.

Invoking the parallel version of JEMRIS

Running the parallel version requires a working MPI environment (see Installation).

The following command runs the parallel version with 5 parallel processes:

me@my_box:~$ mpirun -np 5 pjemris simu.xml
Model : Bloch , solver = CVODE
Sample : brain , spins = 25841
TxArray : /usr/local/share/jemris/matlab/uniform.xml
RxArray : /usr/local/share/jemris/matlab/uniform.xml
Sequence : /data/mr_cluster/tstoecker/example/epi.xml
nmrpc40 -> Master Process: send MR sample (25841 spins) to 4 slave(s)
Simulating | ************************************************** | 100% done
Actual simulation took 208.64 seconds.

The resulting signal file is the same as for sequential jemris simulations.

Additionally, the percent progress is written to the hidden file ".jemris_progress.out".

Note that spins are first distributed in small packets, then the packet size increases (and decreases at the end, to ). The program performs load balancing and first estimates the number of spins which are simulated in 5 seconds per process. Then, every 5 seconds checkpoints are stored to temporary hidden binary files the ".spins_state.dat" and ".tmp_sig01.bin" which are removed after successful completion. If however the simulation is unexpectedly stopped, a restart will continue at the last checkpoint. This is useful for huge simulations lasting several hours (or even days) where sudden crash e.g. due to power breakdown may occur.

-- last change 17.06.2016 | Tony Stoecker | Imprint --