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
{
public:
FLASH();
NLSStatus initialize(SeqLim & limits) override;
NLSStatus prepare(
MrProt & protocol, SeqLim & limits, SeqExpo & exports) override;
};
#endif
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()
{
}
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);
limits.setTR(0, 100, 5000000, 10, 20000);
limits.setTE(0, 100, 100000, 10, 10000);
limits.setBandWidthPerPixel(0, 80, 900, 10, 260);
limits.setFlipAngle(10., 90., 1., 15.);
limits.setRFSpoiling(SEQ::ON);
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);
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.);
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);
limits.setRepetitions(0, 511, 1, 0);
limits.setConcatenations(1, 1, 1, 1);
limits.setAverages(1, 512, 1, 1);
limits.setAveragingMode(SEQ::INNER_LOOP, SEQ::OUTER_LOOP);
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