{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ " # Shinnar-Le Roux RF Pulse Design with SigPy" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib notebook\n", "%load_ext autoreload\n", "%autoreload 2\n", "import numpy as np\n", "import sigpy as sp\n", "import sigpy.mri as mr\n", "import sigpy.mri.rf as rf\n", "import sigpy.plot as pl\n", "import scipy.signal as signal\n", "import matplotlib.pyplot as pyplot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " ## Parameters for a time-bandwidth 4, linear-phase excitation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tb = 8\n", "N = 128\n", "d1 = 0.01\n", "d2 = 0.01\n", "ptype = 'ex'\n", "ftype = 'ls'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " ## Design the excitation pulse" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pulse = rf.slr.dzrf(N, tb, ptype, ftype, d1, d2, False)\n", "pl.LinePlot(pulse, mode='r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulate the excitation pulse's Mxy profile" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[a, b] = rf.sim.abrm(pulse, np.arange(-2*tb, 2*tb, 0.01), True)\n", "Mxy = 2*np.multiply(np.conj(a), b)\n", "pl.LinePlot(Mxy)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Nfreqs = 2000\n", "mInit = np.repeat([[0, 0, 1]], Nfreqs, axis=0)\n", "f0 = np.linspace(-2*tb/(N),2*tb/(N),Nfreqs)\n", "t1 = np.full(Nfreqs, np.infty)\n", "t2 = np.full(Nfreqs, np.infty)\n", "dt = 1\n", "mFinal = mr.bloch_forward(mInit, pulse, f0, t1, t2, dt)\n", "pl.LinePlot(mFinal[:,0]+1j*mFinal[:,1],mode='m')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parameters for a time-bandwidth 8, minimum-phase inversion" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tb = 8\n", "N = 128\n", "d1 = 0.01\n", "d2 = 0.01\n", "ptype = 'inv'\n", "ftype = 'min'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Design the inversion pulse" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pulse = rf.slr.dzrf(N, tb, ptype, ftype, d1, d2)\n", "pl.LinePlot(pulse, mode='r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulate the inversion pulse's Mz profile" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[a, b] = rf.sim.abrm(pulse, np.arange(-2*tb, 2*tb, 0.01))\n", "Mz = 1-2*np.abs(b)**2\n", "pl.LinePlot(Mz.T, mode='r')\n", "print(np.shape(Mz))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "Nfreqs = 2000\n", "mInit = np.repeat([[0, 0, 1]], Nfreqs, axis=0)\n", "dt = 1\n", "f0 = np.linspace(-2*tb/(N), 2*tb/(N), Nfreqs)\n", "t1 = np.full(Nfreqs, np.infty)\n", "t2 = np.full(Nfreqs, np.infty)\n", "mFinal = mr.bloch_forward(mInit, pulse, f0, t1, t2, dt)\n", "pl.LinePlot(mFinal[:,2], mode='r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Design a root-flipped saturation pulse" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tb = 12\n", "N = 128\n", "d1 = 0.01\n", "d2 = 0.001\n", "ptype = 'sat'\n", "ftype = 'min'\n", "# conventional pulse\n", "pulse = rf.slr.dzrf(N, tb, ptype, ftype, d1, d2)\n", "pl.LinePlot(pulse, mode='r')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# root-flipped pulse\n", "tb = 12\n", "N = 128\n", "d1 = 0.01\n", "d2 = 0.001\n", "flip = np.pi/2\n", "ptype = 'sat'\n", "[bsf, d1, d2] = rf.slr.calc_ripples(ptype, d1, d2)\n", "b = bsf*rf.slr.dzmp(N, tb, d1, d2)\n", "b = b[::-1]\n", "[pulse, bRootFlipped] = rf.slr.root_flip(b, d1, flip, tb)\n", "\n", "pyplot.figure()\n", "pyplot.plot(np.abs(pulse))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Recursive Pulse Design for a 3-Segment FLEET EPI scan" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Design the pulses\n", "Nseg = 3 # number of EPI segments/RF Pulses\n", "tb = 4\n", "N = 2000\n", "seSeq = True\n", "tbRef = 8 # time-bandwidth of ref pulse\n", "[pulses, _] = rf.slr.dz_recursive_rf(Nseg, tb, N, seSeq, tbRef)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Plot them\n", "pl.LinePlot(pulses.T, mode = 'real')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Simulate them\n", "Mxy = np.zeros((np.size(np.arange(-4*tb, 4*tb, 0.01)), Nseg), dtype = complex)\n", "Mz = np.ones(np.size(np.arange(-4*tb, 4*tb, 0.01)))\n", "for ii in range(0, Nseg): \n", " [a, b] = rf.sim.abrm(pulses[:, ii], np.arange(-4*tb, 4*tb, 0.01), True)\n", " Mxy[:, ii] = 2*Mz*np.multiply(np.conj(a),b)\n", " Mz = Mz*(1 - 2*np.abs(b)**2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Plot Mxy profiles\n", "pl.LinePlot(Mxy.T)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }