![]() |
JEMRIS 2.9.2
open-source MRI simulations
|
JEMRIS sequence development does not require any programming. The sequence is determined through an XML tree structure. A dedicated GUI allows to construct the tree structure for arbitrary complex MRI sequences.
Introduction to the sequence GUI JEMRIS_seq
The MRI sequence is specified utilizing a tree structure. As a simple example, the EPI sequence below is eqivalently described by left-right ordered tree structure. This is very suitable and efficient for computer-aided design and access of the pulse sequence: The MRI simulator JEMRIS utilizes such a tree structure to represent the MRI sequence. The MatLab tool JEMRIS_seq is used to design the sequences.
Change to the directory in which the sequence xml-files are located and type JEMRIS_seq to start the sequence GUI. The following picture shows a screenshot of the GUI with the EPI sequence loaded into it:
The Sequence GUI allows to interactively build the sequence tree. The tools for this are given in the top panel. The "File" dialog allows to load and save sequences (XML format), and to export sequences to Pulseq format for execution on a real MR-scanner (cf. Exporting a Sequence to an MRI Scanner with Pulseq). The "write XML" button overwrites the current sequence file according to the changes made.
Further, this button executes a run through the sequence and draws the sequence diagram. Possible error output during sequence execution is thrown to the "jemris tree dump" at the bottom. Instead, the "read XML" button discards all changes made to the sequence tree and rereads the current sequence from its XML file. To view the sequence diagram, i.e. the ADC, RF, and gradient events, use the "Sequence Diagram" check box. There are several features to visualize the sequence diagram:
By clicking on a module, its individual attributes are displayed in the upper half of the GUI and may be edited. The attribute values can not only be actual numbers, analytical expressions are also accepted (see section Analytical expressions ). Often attribute values from other modules are needed for an analytical expression, e.g. the area under a previous gradient pulse or the duration of a previous pulse. This is handled using the "observe" attribute (see also section Analytical expressions ).
This section briefly summarizes all sequence building modules and its attributes. The interaction of these modules is explained in the next section Analytical expressions.
The parameter module (orange circle) is always present in a sequence. It is not a part of the sequence tree but exists only once. The module contains global attributes such as field of view 
So far, there exist five modules which are of type sequence:
The ConcatSequence module (yellow circle) represents a loop which can be controlled by its attribute "repetitions" (default value is 1). It may contain other ConcatSequences, AtomicSequences or DelayAtomicSequences, but no pulses. A ConcatSequence also has Hidden Attributes, which are not set by the user but in runtime:
The attributes "aux1,aux2,aux3" define auxiliary variables. These values are not used in the calculation of the ConcatSequence. However they can be observed by other modules, thus lengthy expressions can be displayed in a more structured way. The attribute "LoopFlag" defines the function of this loop. This information might be needed for image reconstruction and is stored to ISMRMD output. It is not required for JEMRIS-internal functionality. Possible values are:
0 : no specific functionality (default) 1 : slice loop 2 : phase-encoding loop 4 : partition loop 8 : set loop (various purposes) 16 : contrast loop 32 : averaging loop A loop can have multiple functionalities by providing the sum of the above flags. A phase-encoding loop flag (2) is required to initiate image reconstruction from ISMRMRD raw data. The slice, set, or contrast flags (1,8,16) are required for the reconstruction of multiple images.
The AtomicSequence module (purple circles) contains the actual pulses. Each AtomicSequence can contain multiple pulses which are then applied simultaneously. Additionally, the attributes "Inclination", "Azimut", "RotAngle" define the rotation matrix for gradient pulses inside this AtomicSequence, e.g. for oblique slices or radial imaging. As the ConcatSequence, the AtomicSequence has auxiliary attributes for convenience, and a hidden attribute specifying its duration. Note: it is possible to insert one AtomicSequence into the Parameter module. This is a "static atom" which acts throughout the complete sequence lifetime. Its pulses, however, need to be prepared accordingly, similar as for pulses within the sequence.
The DelayAtomicSequence (green circles) is a specialised AtomicSequence to define delays. It can either be defined as a simple delay by setting the parameter: "delay = 30", which will simple wait for 30ms. However, for e.g. a echo time delay, the echo time is defined from the center of "A_RF" to the center of "A_G_RO". The needed dead-time is TE minus the duration of "A_G_DP" and half the durations of "A_RF" and "A_G_RO". This can be automatically inserted by the DelayAtom. The required parameters for a TE of 30ms are then: "delay = 30 ", "StartSeq = A_RF", "StopSeq = A_G_RO", "DelayType = C2C ". Apart from the "center-to-center" ( "C2C") delay type, following other delay types are defined:
"C2E" (center-to-end) "B2C" (beginning-to-center) "B2E" (beginning-to-end; default, if no delaytype is specified)
"Filename" specifies the xml-file of the ContainerSequence. Further, the Container has the following additional attributes: "Imp1,...,Imp8" Eight attributes which can be used to import information into the ContainerSequence. "Exp1,Exp2,Exp3" Three hidden attributes for export. They are defined by the ContainerSequence (see below) and passed to the Container. "Exp1,Exp2,Imp3" Three attributes which can be used for export from the ContainerSequence. "Imp1,...,Imp8" Eight hidden attributes for import. They are defined by the Container (see above) and passed to the ContainerSequence. "Info_Imp1,...,Info_Imp8" Eight (unobservable) attributes with no specific purpose, but may be used to provide information about any possible usage of the import attributes. "Info_Exp1,Info_Exp2,Info_Exp3" Three (unobservable) attributes with no specific purpose, but may be used to provide information about any possible usage of the export attributes. "/usr/local/share/jemris/example") for the sample sequence "epi_modular.xml" utlizing the Container and ContainerSequence.
There exist several pulses which may be inserted into an AtomicSequence. All pulses have several attributes in common:
Duration: Every pulse has a duration, which is either explicitly set or calculated from other attributes.InitialDelay: A pulse may start at a later time within the atom, e.g. an RF pulse may wait for the ramp-up time of a gradient pulse.ADCs: The ADCs specify the number of readout events. These events are equidistantly distributed over the length of the pulse. The simulator will save the acquired signal at each of these time points.ADCFlag: defines the ISMRMD datatype for image reconstruction. An ADCFlag>0 has no JEMRIS-internal functionality. Possible values are (the colors in brackets are used for plotting these ADC events in the GUI): 0 : no ADC. (Sometimes useful for visualiztion, see below.) 1 : a standard ADC. This is the default, if the ADCFlag is not set. (black) 2 : an imaging ADC - these events define k-space (red) 4 : an auto-calibration scan (ACS) for parallel imaging. (blue) 8 : a phase correction scan. (cyan) 16 : a noise scan. (magenta) ADCFlag=0 instead.Phaselock: Locks the phase of the ADCs inside the module to the phase of the last RF pulse. Can be 1 (true) or 0 (false).The most simple pulse-shape module is the
EmptyPulse: It represents a dead-time according its specified duration in which, if ADCs are present, simulated data is acquired. (The above introduced DelayAtomicSequence is a special implementation of an AtomicSequence which has a single EmptyPulse as a child.) The EmptyPulse has one new attribute "Shape" An analytic expression to specify non-equidistant ADC sampling during the pulse length. See Exceptional Attributes for explanation. The analytic expression is automatically scaled over the total length of the pulse. All other pulses subdived into two main pulse classes, RF Pulses and Gradient Pulses, respectively.
The following RF pulse Modules are defined in JEMRIS:
HardRFPulse: A nonselective rectangular RF pulse. It has the following specific attributes
"FlipAngle" The applied flip angle "InitialPhase" The constant phase during the duration of the pulse (the rotation axis) "Channel" An optional channel number, in case of parallel RF transmit. GaussianRFPulse: A Gaussian-shaped RF pulse. It has all the attributes of the HardRFPulse, and additionally
"Bandwidth" The bandwidth of the Gaussian "Frequency" The frequency-shift applied for this RF pulse SincRFPulse: A sinc-shaped ( 
"Zeros" The number of positive zero-crossings (or side lobes) of the sinc function (default 3) "Apodization" The apodization factor of the Hanning window (default 0.5) AnalyticRFPulse: An arbitrary RF pulse specified through an analytic expression. It has all the attributes of the GaussianRFPulse, and additionally
"Shape" The analytic expression for the RF pulse shape, using the time variable "T". The expression can be complex to define the magnitude and phase of the RF-pulse. Use "I" as imaginary unit, e.g. "Shape=sech(T)^(1.0+I)" generates a hyperbolic secant pulse. "Diff" If set to 1, then the actual pulse shape is defined by the first derivative of the analytic expression. In this case, the flip angle is set via the analytic expression rather than numerical integration. "Constants" A comma-sparated list of floating point numbers, which may be used as variables "c1,c2,..." in the Shape expression. ExternalRFPulse: An arbitrary RF pulse specified through an external file. It has all the attributes of the GaussianRFPulse, and additionally
"Filename" A HDF5-file with a single dataset "extpulse" of size 
"Scale" An optional scale of the amplitudes (default 1) "Interpolate" if true, linear interpolation is performed, otherwise nearest neighbor look-up. Can be 1 (true) or 0 (false). Note, that such external HDF5-files are easily constructed with the GUI: generate a global matlab variable of size 
"Filename". The GUI will automatically construct the necessary HDF5-file for JEMRIS.
Note that in terms of numerical efficiency the built-in RF pulses (HardRFPulse,GaussianRFPulse,SincRFPulse) perform best, the evaluation of an AnalyticRFPulse is slower, and an ExternalRFPulse is slowest, if it is specified through many data points.
There exist several modules to define gradient events in JEMRIS. All gradients can induce eddy currents, for which three additional attributes are in common for these pulses:
EddyCurrents: An analytic expression, similar to the Shape attribute of AnalyticGradPulse (see section Exceptional Attributes). It specifies the shape of the eddy current, e.g. "EddyCurrent=01.*exp(-5*T)". The expression then gets compiled in runtime for fast evaluation of the eddy currents. EddyConvLength: The number of points to compute the convolution integral for the actual eddy current. Note that eddy currents are computationally expensive, therefore a short convolution length increases simulation speed. Eddy currents are displayed in the GUI, thus you can visually check if the length is sufficient. Hide: A boolean to hide the gradient event itself, but not its eddy current. If "Hide=1" the actual gradient is not played out. Thus, by copying a gradient and hiding the copies, it is possible to individually specify arbirtrary eddy current cross terms.Eddy currents are implemented in a very flexible way: the eddy currents will adapt automatically, if the gradient module changes its shape during the sequence runtime (e.g. a phase-encoding gradient). Note, that Eddy currents can be combined with nonlinear gradient fields Further, eddy currents typically last longer than the gradient event itself, i.e. beyond the AtomicSequence in which it was originated. In this case the transients are taken over to the next AtomicSequence. Caution: the latter may fail in a loop, if the remaining eddy current overlaps with the same AtomicSequence in which it was orginally generated. Then, only original eddy current is played out and the remaining eddy current is lost. In order to correctly simulate such long lasting eddy currents, the loop structure must be changed accordingly.
Further, each gradient can define a non-linear spatial field dependence, instead of the default linear gradient fields.
"NLG_field": an analytical expression for non-linear gradient field can be specified to every gradient module. Use "X,Y,Z" as space variables, and "G" as the gradient value, e.g. "NLG_field=X*G+0.001*G*X^2" will simulate a linear x-gradient field with a small quadratic term. Take into account that "NLG_field=G" i.e. omit any spatial dependence in the analytical expression. The following gradient pulse modules exist in JEMRIS:
TrapGradPulse: A trapezoidal-shaped gradient pulse, which is the by far most used gradient pulse in JEMRIS. If no duration is specified, the pulse prepares in shortest possbile time according to the hardware limits.
The TrapGradPulse has several attributes inherited from the basic GradientPulse class, i.e. these attributes are common for all gradient pulses:
"Slewrate" and "MaxAmplitude": Hardware limits, specific only for the particular gradient. If not set, the limits from the Parameter module are used. "Axis" The spatial axis of the gradient pulse; one of "GX", "GY", or "GZ". "Area" The area of the pulse shape, i.e. the total k-space encoding. "NLG_field" An optional attribute specifying an analytic expression for nonlinear gradients. See Exceptional Attributes for explanation. Further, the TrapGradPulse has attributes specific to its trapezoidal shape:
"FlatTopArea" Instead of specifying the area, only the area under the flat top may be specified. "FlatTopTime" Defines the duration of the flat top. In this case, ADCs are automatically set under the flat top (readout gradient). Therefore, the "FlatTopTime" is in case of ADCs the reciprocal of the readout bandwidth. "Asymetric" Ratio of the slew rates between the ramp up and the ramp down. Note that the default ADCFlag is 2 (imaging scan) for a TrapGradPulse. Finally, the TrapGradPulse has several hidden attributes which may provide important information to other modules: "Amplitude", "RampUpTime", "RampDnTime", "EndOfFlatTop".
ConstantGradPulse: A constant gradient, for which the attribute, "Amplidue" needs to be specified.
TriangleGradPulse: A ramp-up or down gradient, for which the attributes, "Amplidue" and "TriangleType" (can be either "UP" or "DN") need to be specified.
AnalyticGradPulse: An arbitrary gradient pulse specified through an analytic expression. It has similar functionality as the AnalyticRFPulse. By setting the attribute "Diff=1", the attribute Shape directly allows specification of the k-space trajectory (analytic differentiation of the Shape).
SpiralGradPulse: A priliminary very simple spiral gradient, only intended for usage on the "GX" and the "GY" axis. It has two attributes, "pitch" and "alpha" for scaling and spiral denisity, respecitvely.
ExternalGradPulse: An arbitrary Gradient pulse specified through an external HDF5-file, again simliar to the definition of the ExternalRFPulse. Here, the HDF5-file has a single dataset "extpulse" of size 


Note, that such external HDF5-files are easily constructed by the GUI: generate a global matlab variable of size 
"Filename". The GUI will automatically construct the necessary HDF5-file for JEMRIS.
As mentioned above, instead of being numbers module attributes values can also be analytical expressions. For that variables are needed which contain the attribute values of other modules. Consider a gradient pulse with name "P1" which is dependent on the area of another gradient pulse "P2". To have access to this value, the pulse "P1" needs the special attribute Observe="A=P2.Area". Now the area of pulse "P2" can be accessed in every attribute definition of "P1" with the variable "A". For instance, "P1" sets its area to minus half the area of "P2" through Area="-0.5*A". Multiple attributes can be observed separated by commas, e.g.: Observe="A=P4.Area, NX=P.Nx, NY=P.Ny, C=C2.Repetitions" . Then, the observed attributes are accessed with the user-defined variables "A", "NX", "NY", "C", etc. The variable names can be freely chosen. It is recommended to use only uppercase letters to prevent undesired string replacements in formulas. Further the letters "I", and "P" should not be used as variables as this might conflict with other pre-defined epxressions (see below). (It is valid to use this letters within a variable name, e.g. Observe="C.Counter=INDEX" or Observe="P.FOVx=PFOVX")
Observer syntax in older versions of JEMRIS
As explained above, the current JEMRIS version requires an observer definition of the form: Observe="KEY1=Module1.Attribute1, KEY2=Module2.Attribute2, ...". Then the user-defined keywords "KEY1", "KEY2" can be used in analytic formulas. Older JEMRIS versions (<2.8.1) used a different syntax: Observe="Module1,Attribute1/Module2,Attribute2/...", then the according variables were automatically named "a1", "a2", etc. This syntax has the disadvantage that the user has to keep track which variable (a1,a2,...) belongs to which observed attribute. Therefore, the new syntax with user-defined keywords was introduced. The old syntax is still supported. (And used in some examples in the documentation.)
Each module can have so-called hidden attributes which cannot be edited. Instead, these attributes are calculated from supplied values at runtime. The ConcatSequence, for example, not only has the attribute "Repetitions", it also has a hidden attribute "Counter" which gives the current loop-number. A hidden attribute can be observed by other modules. A list of all hidden attributes can be displayed using the pull-down menu in each module. Some frequently used hidden attributes are listed here:
"Dx", "Dy", "Dz" (pixel size in image space); "DKx", "DKy", "DKz" (increment in k-space); "KMAXx", "KMAXy", "KMAXz" (boundaries of k-space)."Counter" (loop counter); "Duration" Hint: "Counter" is the most often observed attribute since it introduces the dynamic to the sequence. Attributes which observe a loop counter change their value in run time. (If these attributes are further observed by other attributes, the latter of course will also dynamically change their values accordingly.)
The symbolic expression syntax is similar to scalar computation syntax in Matlab. For instance, if a gradient observes three attributes, e.g. Observe="KMX=P.KMAXx, KMY=P.KMAXy, C=C.Repetitions", then a valid formula for its area would be Area="sqrt(KMX^2+KMY^2)*(-1)^C"
Several predefined mathematical expressions may be used:
| Pi | area of a unit circle |
| abs(x) | absolute value |
| step(x) | step function |
| I | imaginary unit |
| csgn(x) | complex sign |
| conjugate(x) | complex conjugation |
| real_part(x) | real part |
| imag_part(x) | imaginary part |
| sqrt(x) | square root |
| sin(x) | sine |
| cos(x) | cosine |
| tan(x) | tangent |
| asin(x) | inverse sine |
| acos(x) | inverse cosine |
| atan(x) | inverse tangent |
| atan2(y,x) | inverse tangent with two arguments |
| sinh(x) | hyperbolic sine |
| cosh(x) | hyperbolic cosine |
| tanh(x) | hyperbolic tangent |
| asinh(x) | inverse hyperbolic sine |
| acosh(x) | inverse hyperbolic cosine |
| atanh(x) | inverse hyperbolic tangent |
| exp(x) | exponential function |
| log(x) | natural logarithm |
| floor(x) | round to integer |
| mod(x,y) | Modulo |
| equal(x,y) | returns 1, if x equals y, otherwise returns zero |
| gt(x,y) | returns 1, if x is greater than y, otherwise returns zero |
| lt(x,y) | returns 1, if x is less than y, otherwise returns zero |
| ite(x,y,a,b) | returns a, if x equals y, otherwise returns b |
There are further, less comonly used, mathematical functions. Please check the GiNaC documentation .
Every Module has its attributes which will have its internal special meaning. However, for the observer mechanism all these "standard attributes" may be arbitrarily linked to each other. For instance, the flip angle of an RF pulse may set its value through observation of the area of a gradient. However, there are some exceptional attributes for which this general behaviour does not work, i.e. these attributes can not be observed by other modules! These exceptions are listed below:
"Observe": Of course the Observe attribute itself can not be observed."Vector": Every pulse has the attribute "Vector". It is a space-separated list of floating point values which can be accessed by another attribute of this pulse. The values can be addressed by observation of loop counters, for instance an RF pulse may set Observe="C=C1.Counter" and FlipAngle="Vector(C)". Thus, the flip angle will loop through the vector as the loop-counter of the ConcatSequence increases. Note that in the Matlab GUI, "Vector" can also take any Matlab expression which results in a vector as input such as e.g. "rand(10,1)"."Shape": For analytical RF / gradient pulses, this attribute defines the shape of the pulse"NLG_field": the analytical expression for non-linear gradient fields
-- last change 03.01.2025 |
Tony Stoecker |
Imprint |
Data Protection --