msl 1.3.0
Loading...
Searching...
No Matches
Chapter I — In which we create a sequence doing nothing

Getting msl

Create an empty directory named msl_tutorial, then download msl in this directory. This can be done three ways:

If you downloaded a zip or tar.gz archive, unzip its contents inside the msl_tutorial directory.

The Sequence object

Any MR sequence developed using msl is based on the msl::Sequence object. As we will see in the following parts, this object contains the structure of the sequence, known as the sequence graph, and common data shared by all parts, the registry. In the first part of this tutorial, we will create an empty shell, the basic scaffold on which the next parts will be built.

Start by creating a file name FLASH.h, with the following contents:

#ifndef FLASH_H
#define FLASH_H
#include <msl/Sequence.h>
class FLASH: public msl::Sequence
{
public:
FLASH();
NLSStatus initialize(SeqLim & limits) override;
NLSStatus prepare(
MrProt & protocol, SeqLim & limits, SeqExpo & exports) override;
};
#endif // FLASH_H
Graph-based sequence class.
Definition Sequence.h:37

A couple of functions will be added in later steps, but this file will remain very simple.

Create the FLASH.cpp file, call the interface-definition macro (SEQIF_DEFINE) and define the constructor of the FLASH class, which only needs to initialize the base class.

#include "FLASH.h"
#include <MrMeasSrv/SeqIF/csequence.h>
#include <MrMeasSrv/SeqIF/Sequence/sequmsg.h>
SEQIF_DEFINE(FLASH)
FLASH
::FLASH()
: msl::Sequence()
{
// Nothing else.
}
Top-level namespace of the msl library.
Definition acceleration.h:17

Define the initialize function, proudly describing what your sequence does:

NLSStatus
FLASH
::initialize(SeqLim & limits)
{
limits.setMyOrigFilename(__FILE__);
limits.setSequenceOwner("USER");
limits.setSequenceHintText(
"\n"
" A FLASH sequence, based on msl.\n"
" Version 1.0.0\n");
return MRI_SEQ_SEQU_NORMAL;
}

And add an empty prepare function:

NLSStatus
FLASH
::prepare(MrProt & protocol, SeqLim & limits, SeqExpo & exports)
{
return MRI_SEQ_SEQU_NORMAL;
}

Compilation

Create the makefile.trs file, with the following content, adapt the path to msl if needed.

NOSYNGO()
IF_WIN(DEBUGGER_CMD("$(OutDir)/SeqTestFrame.exe" "-s $(TargetPath)"))
CPPFLAGS(-D_CONSOLE)
CPPFLAGS(-DBUILD_SEQU)
CPPFLAGS(-DTRACE_COMPONENT_NAME=MrImaging)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/msl/src)
file(GLOB files ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE msl_files ${CMAKE_CURRENT_SOURCE_DIR}/msl/src/*.cpp)
list(APPEND files ${msl_files})
foreach(file ${files})
AddSources(${file})
endforeach()
foreach(
lib libCSL libGSL libKSpace libKSA libMath libSBB libSBBFW libSeqSysProp
libSeqUTIF libSeqUtil libSeqUtilFW libSL libUICtrl MeasNucleiBase
MeasNucleiIF MrGenericDC MrProt MrProtocolData MrTrace Reflection UTrace)
LDLIBS("${lib}")
endforeach()
IF_WIN(LDLIBS(libUILink))
LIB(msl_tutorial)

Set the tutorial sequence as active (cs command), and compile its host version (mc 1 for the debug version, mc 2 for the release version). Everything should go smoothely: you can prepare the sequence with a default protocol (mp) and look at its user interface in POET (where almost nothing will be shown). It is however not ready to run yet.

User Interface

Set the sequence "limits", thus populating the user interface in POET, by adding the following to the init function, before the return statement. You will also need to add two includes, MrImagingFW/libSeqSysProp/SysProperties.h and MrProtSrv/Domain/MrProtocol/libUICtrl/UICtrl.h

limits.setAllowedFrequency(1000, 1000000000);
limits.setGradients(SEQ::GRAD_FAST, SEQ::GRAD_NORMAL, SEQ::GRAD_WHISPER);
limits.setIntro(SEQ::ON, SEQ::OFF);
// Timing parameters
limits.setTR(0, 100, 5000000, 10, 20000);
limits.setTE(0, 100, 100000, 10, 10000);
limits.setBandWidthPerPixel(0, 80, 900, 10, 260);
// Excitation parameters
limits.setFlipAngle(10., 90., 1., 15.);
limits.setRFSpoiling(SEQ::ON);
// Geometry of k-space
limits.setDimension(SEQ::DIM_2, SEQ::DIM_3);
limits.setBaseResolution(64, 1024, SEQ::INC_16, 256);
limits.setPELines(32, 1024, 1, limits.getBaseResolution().getDef());
limits.setPhaseOversampling(0.0, 1.0, 0.01, 0.0);
limits.setPartition(8, 512, 2, 32);
limits.setSlices(1, K_NO_SLI_MAX, 1, 1);
// Geometry of image
limits.setReadoutFOV(20., SysProperties::getFoVMax(), 1., 300.);
limits.setPhaseFOV(
limits.getReadoutFOV().getMin(), limits.getReadoutFOV().getMax(),
limits.getReadoutFOV().getInc(), limits.getReadoutFOV().getDef());
limits.setImagesPerSlab(8, 512, 2, 32);
limits.setSlabThickness(5., 160.);
limits.set3DPartThickness(
0.1, 5., 0.01,
limits.getSlabThickness().getMax() / limits.getPartition().getDef());
limits.setSliceThickness(2., 10., 0.5, 5.);
// Acceleration
limits.setEllipticalScanning(SEQ::OFF, SEQ::ON);
limits.setPhasePartialFourierFactor(SEQ::PF_OFF, SEQ::PF_6_8, SEQ::PF_7_8);
limits.setSlicePartialFourierFactor(SEQ::PF_OFF, SEQ::PF_6_8, SEQ::PF_7_8);
limits.setMinSliceResolution(0.5);
limits.setPATMode(SEQ::PAT_MODE_NONE, SEQ::PAT_MODE_GRAPPA);
limits.setAccelFactorPE(1, 8, 1, 2);
limits.setRefLinesPE(1, 128, 1, 32);
limits.setRefScanMode(SEQ::PAT_REF_SCAN_INPLACE);
// Repetitions and averages
limits.setRepetitions(0, 511, 1, 0);
limits.setConcatenations(1, 1, 1, 1);
limits.setAverages(1, 512, 1, 1);
// NOTE: in the interface, INNER_LOOP is short-term, OUTER_LOOP is long-term
limits.setAveragingMode(SEQ::INNER_LOOP, SEQ::OUTER_LOOP);
// Reconstruction
limits.set2DInterpolation(SEQ::NO, SEQ::YES);
limits.setReconstructionMode(
SEQ::RECONMODE_MAGNITUDE, SEQ::RECONMODE_MAGN_PHASE);
#ifdef WIN32
fStdImagingInitPost(limits);
limits.setDefaultEVAProt(L"%SiemensEvaDefProt%\\Inline\\Inline.evp");
#endif

Check that you can prepare the default protocol (mp) and that the user interface in POET shows the usual fields.

Full Code

FLASH.h

FLASH.cpp

makefile.trs