Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/jonbmartin/sigpy-rf
Browse files Browse the repository at this point in the history
  • Loading branch information
frankong committed Nov 5, 2019
2 parents b32bc2a + e789025 commit ef733ae
Show file tree
Hide file tree
Showing 86 changed files with 1,272 additions and 41 deletions.
Empty file modified .coveragerc
100644 → 100755
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/bug_report.md
100644 → 100755
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/feature_request.md
100644 → 100755
Empty file.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified .readthedocs.yml
100644 → 100755
Empty file.
Empty file modified .travis.yml
100644 → 100755
Empty file.
Empty file modified conda.recipe/bld.bat
100644 → 100755
Empty file.
Empty file modified conda.recipe/build.sh
100644 → 100755
Empty file.
Empty file modified conda.recipe/meta.yaml
100644 → 100755
Empty file.
Empty file modified docs/Makefile
100644 → 100755
Empty file.
Empty file modified docs/conf.py
100644 → 100755
Empty file.
Empty file modified docs/core.rst
100644 → 100755
Empty file.
Empty file modified docs/core_alg.rst
100644 → 100755
Empty file.
Empty file modified docs/core_app.rst
100644 → 100755
Empty file.
Empty file modified docs/core_linop.rst
100644 → 100755
Empty file.
Empty file modified docs/core_prox.rst
100644 → 100755
Empty file.
Empty file modified docs/guide_basic.rst
100644 → 100755
Empty file.
Empty file modified docs/guide_iter.rst
100644 → 100755
Empty file.
Empty file modified docs/guide_multi_devices.rst
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions docs/index.rst
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
mri
mri_linop
mri_app
mri_rf

.. toctree::
:hidden:
Expand Down
Empty file modified docs/learn.rst
100644 → 100755
Empty file.
Empty file modified docs/learn_app.rst
100644 → 100755
Empty file.
72 changes: 36 additions & 36 deletions docs/make.bat
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=sigpy

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%

:end
popd
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=sigpy

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%

:end
popd
1 change: 1 addition & 0 deletions docs/mri.rst
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Sampling Functions

sigpy.mri.poisson
sigpy.mri.radial
sigpy.mri.spiral

Simulation Functions
--------------------
Expand Down
Empty file modified docs/mri_app.rst
100644 → 100755
Empty file.
Empty file modified docs/mri_linop.rst
100644 → 100755
Empty file.
36 changes: 36 additions & 0 deletions docs/mri_rf.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
MRI RF Design (`sigpy.mri.rf`)
==============================

.. automodule::
sigpy.mri.rf

SLR Pulse Design
--------------------------
.. autosummary::
:toctree: generated
:nosignatures:

sigpy.mri.rf.slr.dzrf
sigpy.mri.rf.slr.root_flip
sigpy.mri.rf.slr.dz_gslider_rf
sigpy.mri.rf.slr.dz_gslider_b
sigpy.mri.rf.slr.dz_hadamard_b

RF Pulse Simulation
--------------------------
.. autosummary::
:toctree: generated
:nosignatures:

sigpy.mri.rf.sim.abrm
sigpy.mri.rf.sim.abrm_nd
sigpy.mri.rf.sim.abrm_hp

RF Utility
--------------------------
.. autosummary::
:toctree: generated
:nosignatures:

sigpy.mri.rf.util.dinf

Empty file modified docs/plot.rst
100644 → 100755
Empty file.
Empty file modified docs/requirements.txt
100644 → 100755
Empty file.
Empty file modified run_tests.sh
100755 → 100644
Empty file.
Empty file modified sigpy/__init__.py
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion sigpy/alg.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class ConjugateGradient(Alg):

def __init__(self, A, b, x, P=None, max_iter=100, tol=0):
self.A = A
self.b = b
self.P = P
self.x = x
self.tol = tol
Expand Down Expand Up @@ -552,7 +553,6 @@ def _update(self):
gradf_x = self.gradf(self.x)
p = -self.inv_hessf(self.x)(gradf_x)
self.lamda2 = -xp.real(xp.vdot(p, gradf_x)).item()

if self.lamda2 < 0:
raise ValueError(
'Direction is not descending. Got lamda2={}. '
Expand Down
Empty file modified sigpy/app.py
100644 → 100755
Empty file.
Empty file modified sigpy/backend.py
100644 → 100755
Empty file.
Empty file modified sigpy/block.py
100644 → 100755
Empty file.
Empty file modified sigpy/config.py
100644 → 100755
Empty file.
Empty file modified sigpy/conv.py
100644 → 100755
Empty file.
Empty file modified sigpy/fourier.py
100644 → 100755
Empty file.
Empty file modified sigpy/interp.py
100644 → 100755
Empty file.
Empty file modified sigpy/learn/__init__.py
100644 → 100755
Empty file.
Empty file modified sigpy/learn/app.py
100644 → 100755
Empty file.
Empty file modified sigpy/learn/util.py
100644 → 100755
Empty file.
Empty file modified sigpy/linop.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/__init__.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/app.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/bloch.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/dcf.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/linop.py
100644 → 100755
Empty file.
Empty file modified sigpy/mri/precond.py
100644 → 100755
Empty file.
23 changes: 23 additions & 0 deletions sigpy/mri/rf/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""This MRI submodule contains functions and classes for MRI pulse design.
It currently provides tools for SLR pulse design and RF pulse simulation.
Tools for designing pTx, adiabatic, and other types of rf pulses,
as well as gradient and trajectory designers will be added soon.
Explore RF design tutorials at `sigpy-rf-tutorials`_.
See in-progress features at `sigpy-rf`_.
.. _sigpy-rf-tutorials: https://github.com/jonbmartin/sigpy-rf-tutorials
.. _sigpy-rf: https://github.com/jonbmartin/sigpy-rf
"""
from sigpy.mri.rf import slr, sim, util
from sigpy.mri.rf.sim import * # noqa
from sigpy.mri.rf.slr import * # noqa
from sigpy.mri.rf.util import * # noqa

__all__ = []
__all__.extend(slr.__all__)
__all__.extend(sim.__all__)
__all__.extend(util.__all__)
163 changes: 163 additions & 0 deletions sigpy/mri/rf/sim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"""RF Pulse Simulation Functions.
"""
from sigpy import backend

__all__ = ['abrm', 'abrm_nd', 'abrm_hp']


def abrm(rf, x, balanced=False):
r"""1D RF pulse simulation, with simultaneous RF + gradient rotations.
Args:
rf (array): rf waveform input.
x (array): spatial locations.
balanced (bool): toggles application of rewinder.
Returns:
2-element tuple containing
- **a** (*array*): SLR alpha parameter.
- **b** (*array*): SLR beta parameter.
References:
Pauly, J., Le Roux, Patrick., Nishimura, D., and Macovski, A.(1991).
'Parameter Relations for the Shinnar-LeRoux Selective Excitation
Pulse Design Algorithm'.
IEEE Transactions on Medical Imaging, Vol 10, No 1, 53-65.
"""

device = backend.get_device(rf)
xp = device.xp
with device:
eps = 1e-16

g = xp.ones(xp.size(rf)) * 2 * xp.pi / xp.size(rf)

a = xp.ones(xp.size(x), dtype=complex)
b = xp.zeros(xp.size(x), dtype=complex)
for mm in range(xp.size(rf)):
om = x * g[mm]
phi = xp.sqrt(xp.abs(rf[mm]) ** 2 + om ** 2) + eps
n = xp.column_stack((xp.real(rf[mm]) / phi,
xp.imag(rf[mm]) / phi,
om / phi))
av = xp.cos(phi / 2) - 1j * n[:, 2] * xp.sin(phi / 2)
bv = -1j * (n[:, 0] + 1j * n[:, 1]) * xp.sin(phi / 2)
at = av * a - xp.conj(bv) * b
bt = bv * a + xp.conj(av) * b
a = at
b = bt

if balanced: # apply a rewinder
g = -2 * xp.pi / 2
om = x * g
phi = xp.abs(om) + eps
nz = om / phi
av = xp.cos(phi / 2) - 1j * nz * xp.sin(phi / 2)
a = av * a
b = xp.conj(av) * b

return a, b


def abrm_nd(rf, x, g):
r"""N-dim RF pulse simulation
Assumes that x has inverse spatial units of g, and g has gamma*dt applied.
Assumes dimensions x = [...,Ndim], g = [Ndim,Nt].
Args:
rf (array): rf waveform input.
x (array): spatial locations.
g (array): gradient array.
Returns:
2-element tuple containing
- **a** (*array*): SLR alpha parameter.
- **b** (*array*): SLR beta parameter.
References:
Pauly, J., Le Roux, Patrick., Nishimura, D., and Macovski, A.(1991).
'Parameter Relations for the Shinnar-LeRoux Selective Excitation
Pulse Design Algorithm'.
IEEE Transactions on Medical Imaging, Vol 10, No 1, 53-65.
"""

device = backend.get_device(rf)
xp = device.xp
with device:
eps = 1e-16

a = xp.ones(xp.shape(x)[0], dtype=complex)
b = xp.zeros(xp.shape(x)[0], dtype=complex)
for mm in range(xp.size(rf)):
om = x @ g[mm, :]
phi = xp.sqrt(xp.abs(rf[mm]) ** 2 + om ** 2)
n = xp.column_stack((xp.real(rf[mm]) / (phi + eps),
xp.imag(rf[mm]) / (phi + eps),
om / (phi + eps)))
av = xp.cos(phi / 2) - 1j * n[:, 2] * xp.sin(phi / 2)
bv = -1j * (n[:, 0] + 1j * n[:, 1]) * xp.sin(phi / 2)
at = av * a - xp.conj(bv) * b
bt = bv * a + xp.conj(av) * b
a = at
b = bt

return a, b


def abrm_hp(rf, gamgdt, xx, dom0dt=0):
r"""1D RF pulse simulation, with non-simultaneous RF + gradient rotations.
Args:
rf (array): rf pulse samples in radians.
gamdt (array): gradient samples in radians/(units of xx).
xx (array): spatial locations.
dom0dt (float): off-resonance phase in radians.
Returns:
2-element tuple containing
- **a** (*array*): SLR alpha parameter.
- **b** (*array*): SLR beta parameter.
References:
Pauly, J., Le Roux, Patrick., Nishimura, D., and Macovski, A.(1991).
'Parameter Relations for the Shinnar-LeRoux Selective Excitation
Pulse Design Algorithm'.
IEEE Transactions on Medical Imaging, Vol 10, No 1, 53-65.
"""

device = backend.get_device(rf)
xp = device.xp
with device:
Ns = xp.shape(xx)
Ns = Ns[0] # Ns: # of spatial locs
Nt = xp.shape(gamgdt)
Nt = Nt[0] # Nt: # time points

a = xp.ones((Ns,))
b = xp.zeros((Ns,))

for ii in xp.arange(Nt):
# apply phase accural
z = xp.exp(-1j * (xx * gamgdt[ii, ] + dom0dt))
b = b * z

# apply rf
C = xp.cos(xp.abs(rf[ii]) / 2)
S = 1j * xp.exp(1j * xp.angle(rf[ii])) * xp.sin(xp.abs(rf[ii]) / 2)
at = a * C - b * xp.conj(S)
bt = a * S + b * C

a = at
b = bt

z = xp.exp(1j / 2 * (xx * xp.sum(gamgdt, axis=0) + Nt * dom0dt))
a = a * z
b = b * z

return a, b

0 comments on commit ef733ae

Please sign in to comment.