mirror of
https://gitlab.tugraz.at/ibi/projects/julia-pfitzer/esmrmb-educational.git
synced 2024-11-22 09:42:24 +00:00
1580 lines
47 KiB
Text
1580 lines
47 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ca29b946-be1d-4862-9e8d-7e89a0650348",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 1 Setup BART\n",
|
|
"This notebook is designed to run on a local system. It uses the python kernel, however, almost all commands use the `%%bash` cell magic to be executed in a `bash` subshell.\n",
|
|
"\n",
|
|
"We will use BART version 0.9.00. In particular, we will take advantage of the newly added looping feature. For more information check the announcement on our [mailing list](https://lists.eecs.berkeley.edu/sympa/arc/mrirecon/2023-12/msg00000.html).\n",
|
|
"\n",
|
|
"\n",
|
|
"This version has been archived at CERN as: \n",
|
|
"\n",
|
|
"BART: version 0.9.00 (2023) DOI:10.5281/zenodo.10277939"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7602584e-b4dc-44cc-b5fc-67d92a9eac2b",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1.1 Local Usage\n",
|
|
"- Install bart from its [github repository](https://github.com/mrirecon/bart)\n",
|
|
"- Set the `BART_TOOLBOX_PATH` to the BART directory and add it to the `PATH`\n",
|
|
"\n",
|
|
"```bash\n",
|
|
"export BART_TOOLBOX_PATH=/path/to/bart \n",
|
|
"export PATH=$BART_TOOLBOX_PATH:$PATH\n",
|
|
"```\n",
|
|
"\n",
|
|
"Although the simplest way to call the BART CLI tools is from a terminal, there are also wrapper functions that allow the tools to be used from Matlab and Python. These are located under the `$BART_TOOLBOX_PATH/matlab` and `$BART_TOOLBOX_PATH/python` directories."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "84076a2e-2983-44cb-81cc-0d50505ba1b2",
|
|
"metadata": {},
|
|
"source": [
|
|
"We will also use the [CFL viewer](https://github.com/mrirecon/view). Install it locally after configuring BART"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "d48523c5-e101-4589-94b6-4b7793572c97",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"os.environ['DEMO'] = '1'\n",
|
|
"os.environ['DEMO_INSTALL'] = '0'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f62d94b7-07e9-4ae0-a3d7-3fa2b565895c",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1.2 Clone and compile BART v0.9.00\n",
|
|
"We clone BART into the current working directory of this notebook and delete any previous installation in this directory."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "72bc4d27-375b-405f-9089-c08e1c531096",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"skipped .. DEMO_INSTALL=0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"# Clone Bart\n",
|
|
"if [ 1 -eq $DEMO_INSTALL ]; then\n",
|
|
"\n",
|
|
" [ -d bart ] && rm -r bart\n",
|
|
" git clone https://github.com/mrirecon/bart/ bart &> /dev/null\n",
|
|
"\n",
|
|
" cd bart\n",
|
|
"\n",
|
|
" make -j32 &> /dev/null\n",
|
|
"else\n",
|
|
" echo skipped .. DEMO_INSTALL=$DEMO_INSTALL\n",
|
|
"fi"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "76468f36-d2d6-4fdb-ac53-b51ffce3ab48",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1.3 Add BART to PATH variable\n",
|
|
"\n",
|
|
"We add the BART directory to the PATH variable and include the python wrapper for reading *.cfl files:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "a8854d78-bd89-4ea7-bc6f-eafa4a6f139e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"import sys\n",
|
|
"\n",
|
|
"os.environ['BART_TOOLBOX_PATH']=os.getcwd()+\"/bart/\"\n",
|
|
"os.environ['PATH'] = os.environ['BART_TOOLBOX_PATH'] + \":\" + os.environ['PATH']\n",
|
|
"sys.path.append(os.environ['BART_TOOLBOX_PATH'] + \"/python/\")\n",
|
|
"os.environ['DEBUG_LEVEL'] = '2'\n",
|
|
"os.environ['BART_DEBUG_LEVEL'] = '2'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3d494c56-88ab-4440-8484-1968acbcd1cb",
|
|
"metadata": {},
|
|
"source": [
|
|
"Check BART setup:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "5abe217f-02ba-4ca4-9de2-7862af2d0ce6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"# The BART used in this notebook:\n",
|
|
"/home/jpfitzer/git/bart/bart\n",
|
|
"# BART version: \n",
|
|
"v0.9.00-425-g169d805\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"echo \"# The BART used in this notebook:\"\n",
|
|
"which bart\n",
|
|
"echo \"# BART version: \"\n",
|
|
"bart version"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e6803f18-fc73-4abe-941c-9898bb640ce7",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1.4 Install Interactive CFL Viewer\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "4476e853-4eb7-4937-84fc-82ed6e80d0a6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"skipped .. DEMO_INSTALL=0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"# Clone View\n",
|
|
"if [ 1 -eq $DEMO_INSTALL ]; then\n",
|
|
"\n",
|
|
" [ -d view ] && rm -r view\n",
|
|
" git clone https://github.com/mrirecon/view/ view &> /dev/null\n",
|
|
"\n",
|
|
" cd view\n",
|
|
"\n",
|
|
" make &> /dev/null\n",
|
|
"\n",
|
|
"else\n",
|
|
" echo skipped .. DEMO_INSTALL=$DEMO_INSTALL\n",
|
|
"fi"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "c1721b60-7cb3-4cc1-bee0-065352f8d55a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"os.environ['VIEW_TOOLBOX_PATH']=os.getcwd()+\"/view/\"\n",
|
|
"os.environ['PATH'] = os.environ['VIEW_TOOLBOX_PATH'] + \":\" + os.environ['PATH']"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "79a7f963-a4fc-41d3-9998-5ba0a196a543",
|
|
"metadata": {},
|
|
"source": [
|
|
"Check view setup:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "c60a8e73-8a0b-4cb8-9724-891d860307e4",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"# The BART viewer used in this notebook:\n",
|
|
"/home/jpfitzer/git/view/view\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"echo \"# The BART viewer used in this notebook:\"\n",
|
|
"which view"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e691812f-83fa-48eb-96b4-65ca85d21dbf",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1.5 Python Data Writer"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "f7b7800e-8a4c-4852-b94c-2b47cd4a52de",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Copyright 2013-2015. The Regents of the University of California.\n",
|
|
"# Copyright 2021. Uecker Lab. University Center Göttingen.\n",
|
|
"# All rights reserved. Use of this source code is governed by\n",
|
|
"# a BSD-style license which can be found in the LICENSE file.\n",
|
|
"#\n",
|
|
"# Authors:\n",
|
|
"# 2013 Martin Uecker <uecker@eecs.berkeley.edu>\n",
|
|
"# 2015 Jonathan Tamir <jtamir@eecs.berkeley.edu>\n",
|
|
"\n",
|
|
"from __future__ import print_function\n",
|
|
"from __future__ import with_statement\n",
|
|
"\n",
|
|
"import numpy as np\n",
|
|
"import mmap\n",
|
|
"import os\n",
|
|
"\n",
|
|
"from IPython.display import Image\n",
|
|
"\n",
|
|
"\n",
|
|
"def readcfl(name):\n",
|
|
" # get dims from .hdr\n",
|
|
" with open(name + \".hdr\", \"rt\") as h:\n",
|
|
" h.readline() # skip\n",
|
|
" l = h.readline()\n",
|
|
" dims = [int(i) for i in l.split()]\n",
|
|
"\n",
|
|
" # remove singleton dimensions from the end\n",
|
|
" n = np.prod(dims)\n",
|
|
" dims_prod = np.cumprod(dims)\n",
|
|
" dims = dims[:np.searchsorted(dims_prod, n)+1]\n",
|
|
"\n",
|
|
" # load data and reshape into dims\n",
|
|
" with open(name + \".cfl\", \"rb\") as d:\n",
|
|
" a = np.fromfile(d, dtype=np.complex64, count=n);\n",
|
|
" return a.reshape(dims, order='F') # column-major\n",
|
|
"\n",
|
|
"def readmulticfl(name):\n",
|
|
" # get dims from .hdr\n",
|
|
" with open(name + \".hdr\", \"rt\") as h:\n",
|
|
" lines = h.read().splitlines()\n",
|
|
"\n",
|
|
" index_dim = 1 + lines.index('# Dimensions')\n",
|
|
" total_size = int(lines[index_dim])\n",
|
|
" index_sizes = 1 + lines.index('# SizesDimensions')\n",
|
|
" sizes = [int(i) for i in lines[index_sizes].split()]\n",
|
|
" index_dims = 1 + lines.index('# MultiDimensions')\n",
|
|
"\n",
|
|
" with open(name + \".cfl\", \"rb\") as d:\n",
|
|
" a = np.fromfile(d, dtype=np.complex64, count=total_size)\n",
|
|
"\n",
|
|
" offset = 0\n",
|
|
" result = []\n",
|
|
" for i in range(len(sizes)):\n",
|
|
" dims = ([int(i) for i in lines[index_dims + i].split()])\n",
|
|
" n = np.prod(dims)\n",
|
|
" result.append(a[offset:offset+n].reshape(dims, order='F'))\n",
|
|
" offset += n\n",
|
|
"\n",
|
|
" if total_size != offset:\n",
|
|
" print(\"Error\")\n",
|
|
"\n",
|
|
" return result\n",
|
|
"\n",
|
|
"\n",
|
|
"def writecfl(name, array):\n",
|
|
" with open(name + \".hdr\", \"wt\") as h:\n",
|
|
" h.write('# Dimensions\\n')\n",
|
|
" for i in (array.shape):\n",
|
|
" h.write(\"%d \" % i)\n",
|
|
" h.write('\\n')\n",
|
|
"\n",
|
|
" size = np.prod(array.shape) * np.dtype(np.complex64).itemsize\n",
|
|
"\n",
|
|
" with open(name + \".cfl\", \"a+b\") as d:\n",
|
|
" os.ftruncate(d.fileno(), size)\n",
|
|
" mm = mmap.mmap(d.fileno(), size, flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE)\n",
|
|
" if array.dtype != np.complex64:\n",
|
|
" array = array.astype(np.complex64)\n",
|
|
" mm.write(np.ascontiguousarray(array.T))\n",
|
|
" mm.close()\n",
|
|
" #with mmap.mmap(d.fileno(), size, flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE) as mm:\n",
|
|
" # mm.write(array.astype(np.complex64).tobytes(order='F'))\n",
|
|
"\n",
|
|
"def writemulticfl(name, arrays):\n",
|
|
" size = 0\n",
|
|
" dims = []\n",
|
|
"\n",
|
|
" for array in arrays:\n",
|
|
" size += array.size\n",
|
|
" dims.append(array.shape)\n",
|
|
"\n",
|
|
" with open(name + \".hdr\", \"wt\") as h:\n",
|
|
" h.write('# Dimensions\\n')\n",
|
|
" h.write(\"%d\\n\" % size)\n",
|
|
"\n",
|
|
" h.write('# SizesDimensions\\n')\n",
|
|
" for dim in dims:\n",
|
|
" h.write(\"%d \" % len(dim))\n",
|
|
" h.write('\\n')\n",
|
|
"\n",
|
|
" h.write('# MultiDimensions\\n')\n",
|
|
" for dim in dims:\n",
|
|
" for i in dim:\n",
|
|
" h.write(\"%d \" % i)\n",
|
|
" h.write('\\n')\n",
|
|
" \n",
|
|
" size = size * np.dtype(np.complex64).itemsize\n",
|
|
"\n",
|
|
" with open(name + \".cfl\", \"a+b\") as d:\n",
|
|
" os.ftruncate(d.fileno(), size)\n",
|
|
" mm = mmap.mmap(d.fileno(), size, flags=mmap.MAP_SHARED, prot=mmap.PROT_WRITE)\n",
|
|
" for array in arrays:\n",
|
|
" if array.dtype != np.complex64:\n",
|
|
" array = array.astype(np.complex64)\n",
|
|
" mm.write(np.ascontiguousarray(array.T))\n",
|
|
" mm.close()\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "77d0c22c-bb16-4a5d-916b-0d4263fc8c50",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 2. Reading in the data"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "f1883fa9-f260-47a3-9598-474905d10f89",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Echo train length: 20\n",
|
|
"Echo spacing: 10 ms\n",
|
|
"(16, 80, 80, 20)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import scipy.io as sio\n",
|
|
"\n",
|
|
"rawName = 'T2_CPMG.mat'\n",
|
|
"mat_data_0=sio.loadmat(rawName)\n",
|
|
"\n",
|
|
"# Format: sampled, # kSpace [kRd, kPh, kSl, kSpace_echo_1, kSpace_echo_2, ..., kSpace_echo_nETL] (102400, 23)\n",
|
|
"# So the first three are the coordinates of the kspace, and the rest are the echoes\n",
|
|
"\n",
|
|
"kSpaces3D = mat_data_0['kSpaces3D']\n",
|
|
"# self.mapVals['sampled'] = np.concatenate((kRD, kPH, kSL, dataAll_sampled), axis=1)\n",
|
|
"\n",
|
|
"# nReadout, nPhase, nSlice\n",
|
|
"nPoints = (80, 80, 16)\n",
|
|
"\n",
|
|
"echo_train_length = mat_data_0['kSpaces3D'].shape[1] - 3 # Because the first 3 are kRD, kPH, kSL -> should give 20\n",
|
|
"print(f\"Echo train length: {echo_train_length}\")\n",
|
|
"\n",
|
|
"echo_spacing = mat_data_0['echoSpacing'][0][0]\n",
|
|
"print(f\"Echo spacing: {echo_spacing} ms\")\n",
|
|
"\n",
|
|
"k_readout = kSpaces3D[:, 0]\n",
|
|
"k_phase = kSpaces3D[:, 1]\n",
|
|
"k_slice = kSpaces3D[:, 2]\n",
|
|
"\n",
|
|
"# The rest of the data is the echoes\n",
|
|
"echos = kSpaces3D[:, 3:]\n",
|
|
"\n",
|
|
"# Reshape the kspace data for bart\n",
|
|
"kSpace = echos.reshape(nPoints[2], nPoints[1], nPoints[0], echo_train_length)\n",
|
|
"\n",
|
|
"print(kSpace.shape)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "96b28fec-ff5a-44a3-8a0c-9b01b60cff0c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Write the cfl file\n",
|
|
"cfl = writecfl('data/kSpace', kSpace)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "150faf49-acd6-4ee3-ad36-3a745e8e88d9",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.1 Data Exploration"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "5f93fcca-48ab-4d42-9061-91361aadfb35",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"ksp:\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t16\t80\t80\t20\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"echo \"ksp:\"\n",
|
|
"bart show -m data/kSpace\n",
|
|
"\n",
|
|
"DIM_X=80\n",
|
|
"DIM_Y=80\n",
|
|
"DIM_Z=16"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "77d36186-04bb-422d-9ec3-a2032fcbceda",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Correct dimension\n",
|
|
"bart transpose 0 2 data/kSpace data/ksp\n",
|
|
"bart transpose 3 5 data/ksp data/ksp"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "188249e4-dbbb-4f7b-9d28-e28338de14c3",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.2 FFT\n",
|
|
"\n",
|
|
"We have three dimensional data so we perform the fft along the first three dimension. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 210,
|
|
"id": "c074e817-5989-4e83-a108-79834c7b0bdf",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"bart fft -i $(bart bitmask 0 1 2) data/kSpace data/fft"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 211,
|
|
"id": "fcfc949d-8046-4868-bdfe-810b5f27454c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"# view data/fft"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 212,
|
|
"id": "4c72186c-61e3-4e1d-9fe7-e95088ab8c38",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"# Put the echos on the fifth dimension:\n",
|
|
"bart transpose 3 5 data/fft data/fft_transposed\n",
|
|
"# Put the slices on the correct dimension\n",
|
|
"bart transpose 0 2 data/fft_transposed data/fft_transposed"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 213,
|
|
"id": "0a9648a7-6c94-489e-b637-c4338b8cf113",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"fft_transposed:\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t80\t80\t16\t1\t1\t20\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"echo \"fft_transposed:\"\n",
|
|
"bart show -m data/fft_transposed"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 214,
|
|
"id": "b9dade46-455d-4816-9b35-1bf6abf53dcc",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Create the echotimes file:\n",
|
|
"bart vec 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 data/echo_times\n",
|
|
"bart scale 0.001 data/echo_times data/echo_times_scaled\n",
|
|
"# Move the echo_times to the correct dimension:\n",
|
|
"bart transpose 0 5 data/echo_times_scaled data/echo_times_final"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 215,
|
|
"id": "a119e34e-8f2f-42e6-81f9-4023f753fe81",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Usage: mobafit [-T] [-I] [-L] [-G] [-D] [-m d] [-a] [-i d] [-g] [-B <file>] [--init [f:]*f] [--scale [f:]*f] [--min-flag d] [--max-flag d] [--max-mag-flag d] [--min [f:]*f] [--max [f:]*f] <enc> <echo/contrast images> [<coefficients>] \n",
|
|
"\n",
|
|
"Pixel-wise fitting of physical signal models.\n",
|
|
"\n",
|
|
"-T TSE\n",
|
|
"-I Inversion Recovery: f(M0, R1, c) = M0 * (1 - exp(-t * R1 + c))\n",
|
|
"-L Inversion Recovery Look-Locker\n",
|
|
"-G MGRE\n",
|
|
"-D diffusion\n",
|
|
"-m model Select the MGRE model from enum { WF = 0, WFR2S, WF2R2S, R2S, PHASEDIFF } [default: WFR2S]\n",
|
|
"-a fit magnitude of signal model to data\n",
|
|
"-i iter Number of IRGNM steps\n",
|
|
"-g use gpu\n",
|
|
"-B file temporal (or other) basis\n",
|
|
"--init [f:]*f Initial values of parameters in model-based reconstruction\n",
|
|
"--scale [f:]*f Scaling\n",
|
|
"--min-flag flags Apply minimum constraint on selected maps\n",
|
|
"--max-flag flags Apply maximum constraint on selected maps\n",
|
|
"--max-mag-flag flags Apply maximum magnitude constraint on selected maps\n",
|
|
"--min [f:]*f Min bound (map must be selected with \"min-flag\")\n",
|
|
"--max [f:]*f Max bound (map must be selected with \"max-flag\" or \"max-mag-flag\")\n",
|
|
"-h help\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart mobafit -h"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 216,
|
|
"id": "66f1afe4-7598-47c0-ae99-581beca68a11",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/fft_transposed data/fit"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 217,
|
|
"id": "c1f0ece5-2118-4bbc-80c2-e692a01b5f6b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit data/mask"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 218,
|
|
"id": "68fe0ec1-b8a8-453f-8eef-9c9645b7b064",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit data/mask data/fit_mask"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 219,
|
|
"id": "54dcbf68-b920-48d6-a072-fe25f52e712a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask data/R2_map"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 220,
|
|
"id": "5e159890-56b0-4629-89f8-abc33eba42c5",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map data/T2_map "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9b49f422-7373-4f2e-8994-872c4bcd1622",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 2.3 PICS Reco Fully Sampled Data"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a0a45c91-da70-4fdf-b1ab-a35b5d92b63c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f8d7d303-2747-4f41-bf5d-153bc83f2382",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 3.1 Undersampling Poisson ky - kz"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 221,
|
|
"id": "65569e35-233b-4ac9-baf4-6668fcc581a4",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"points: 448, grid size: 80x16x(pi/4) = 1005 (R = 2.243995)\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t1\t80\t16\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t80\t80\t16\t20\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"ACC_Y=2\n",
|
|
"ACC_Z=2\n",
|
|
"\n",
|
|
"bart poisson -Y 80 -Z 16 -y $ACC_Y -z $ACC_Z -C 16 -e data/vd_mask\n",
|
|
"\n",
|
|
"bart show -m data/vd_mask\n",
|
|
"\n",
|
|
"bart transpose 0 2 data/kSpace data/kSpace_transposed\n",
|
|
"\n",
|
|
"bart show -m data/kSpace_transposed"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 222,
|
|
"id": "822e7962-12d6-47a2-a33e-f3d31e34100b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Writing 1 image(s)...done.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAFAAAAAQCAIAAAAOK2+WAAABY0lEQVRIia1WS5YEIQgT73/nmoXTvHQIqFSzUrQIn4Bl46fyPI+Z0eLWyPqwNtuW+ebj8YnHo3Jv2m6ZGeZord8n0eUiYIJBV1Dj13puUVRoX4YtvSokrcOyKyl0pazhhUMBtPCEoPFOdj+tMGJI3hZKhzwOk6HRwtqSEnmEfVT486+PeDJPRfK228t4uche4RE6KNsSKfBoYsLcqG9pCNEIISfkaSNaCWdmVDSJi24Tpde1GadC3EaeLKNZqOhfTyj1A0oSlYUbsSnmSZUWBoadJXt8E6QdLXGYipaNa3rShirynvR4Yevi+0Edgyn6ljTFqadvIoz8bajfW6TArwZ1NimHoo8cLlHjrNTPaaxYXcOiGr0KZxDboy0jNnOlYKnMiISsIUjqnqI6y9ji0Zf9EyfqBpY345g9lHNmNdwbh//S1EjURbjAKdB+luQjPHKyXAH1n8pC5AA7FPlYXNWwlj8kWyUQianQ+gAAAABJRU5ErkJggg==",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 222,
|
|
"metadata": {
|
|
"image/png": {
|
|
"width": 1000
|
|
}
|
|
},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"!bart transpose 1 2 data/vd_mask data/img\n",
|
|
"!bart toimg -w 1.0 data/img fig/vd_mask.png\n",
|
|
"Image(\"fig/vd_mask.png\", width=1000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 223,
|
|
"id": "4693848f-fe88-42e5-9200-17d38dfe2765",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart fmac data/vd_mask data/kSpace_transposed data/kSpace_vd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 224,
|
|
"id": "10817602-2bd3-40a1-950f-2e9adc7ce97f",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Scaling: 0.349166\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# For nlinv the echos can't be in the coil dimension (3)\n",
|
|
"bart transpose 3 5 data/kSpace_vd data/kSpace_vd_transposed\n",
|
|
"# The scaling seems to help\n",
|
|
"bart nlinv -i 30 -x 80:80:16 -S data/kSpace_vd_transposed data/nlinv_vd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 225,
|
|
"id": "2448bf68-a7c0-43ee-a6b1-1c74e058308e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash \n",
|
|
"bart pattern data/kSpace_vd data/pattern_vd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 226,
|
|
"id": "41288837-b086-4ebb-9a71-0dbb7f722ef1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/nlinv_vd data/fit_vd\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_vd data/mask_vd\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_vd data/mask_vd data/fit_mask_vd\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_vd data/R2_map_vd\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_vd data/T2_map_vd "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6a1e8727-0677-4c9c-8e0e-e3622cef5c17",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3.2 Undersampling Poisson-Disc in-plane\n",
|
|
"This isn't useful for a real sequence because then you undersample in readout direction."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 227,
|
|
"id": "67334262-2ce1-4c36-8198-0235c7423a84",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"points: 1450, grid size: 80x80x(pi/4) = 5026 (R = 3.466585)\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t80\t80\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n",
|
|
"Type: complex float\n",
|
|
"Dimensions: 16\n",
|
|
"AoD:\t80\t80\t16\t20\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\t1\n",
|
|
"Scaling: 0.351537\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"\n",
|
|
"ACC_Y=2\n",
|
|
"ACC_Z=2\n",
|
|
"\n",
|
|
"bart poisson -Y 80 -Z 80 -y $ACC_Y -z $ACC_Z -C 16 -e data/ip_mask\n",
|
|
"\n",
|
|
"bart squeeze data/ip_mask data/ip_mask\n",
|
|
"\n",
|
|
"bart show -m data/ip_mask\n",
|
|
"\n",
|
|
"bart show -m data/kSpace_transposed\n",
|
|
"\n",
|
|
"bart fmac data/ip_mask data/kSpace_transposed data/kSpace_ip\n",
|
|
"\n",
|
|
"# For nlinv the echos can't be in the coil dimension (3)\n",
|
|
"bart transpose 3 5 data/kSpace_ip data/kSpace_ip_transposed\n",
|
|
"\n",
|
|
"bart nlinv -i 30 -x 80:80:16 -S data/kSpace_ip_transposed data/nlinv_ip\n",
|
|
"# bart fft -i $(bart bitmask 0 1 2) data/kSpace_ip data/fft_ip\n",
|
|
"\n",
|
|
"bart pattern data/kSpace_ip data/pattern_ip\n",
|
|
"\n",
|
|
"# bart transpose 3 5 data/fft_ip data/fft_ip_transposed\n",
|
|
"\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/nlinv_ip data/fit_ip\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_ip data/mask_ip\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_ip data/mask_ip data/fit_mask_ip\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_ip data/R2_map_ip\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_ip data/T2_map_ip "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 228,
|
|
"id": "d53121cd-a255-492b-a037-e6b9c6fbf6f2",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Writing 1 image(s)...done.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAIAAAABc2X6AAAEzklEQVR4nN1XSZLjMAxT/P8/ew5dpVFIAAQV25MeHrpsmQu4QekxHpfzPMPf9eF3S0jjP8kKyppbTnu2l336dmGTKdLOatnJtw88TA+2MetDJ47+0wKb4yDTbewW5SFxJnbdWF8tR/FLeYvkVNlfaGuqwZNHMy/DsEKUtjrtf3y95fEzk3F+cuQMhf6NmZfkyeaN8VmZUlkI6P9Kabk2N21jzkVNrxRR2vFeCwel9hb8+MN/gZTl7E5ULk15h5stvSBzwY1+G8vdhn50V8PzjdsbTvwRFZ+66wDjtm4NhclcJBZjb82E1XM3sA/CWUVn7HXTyuutUZqSReCnTEIQqEZfapoObxQTq0NdjKscAiud12kEiOYoOuO0d8202N5NdXMHPIfQp4brsK7AbKXA5tBEU0IUOZdw2QXWHTEsJUmK0uRXk8k1+m4Dd4ja+WryhMn2pS3jtnBSrwPjA5NgtTcx9kzH3B2ITQDDUsaAmoLDy/B7EfN5j71YyWEDHVpirtgrk+58tZxj6Oxwe5zM7vmDrfHEk3Kv2IJpuFbsykSPTDeQG1VDKYdN8J/Zk3L/hdsYomQ8p+Qa7iBz4SyIT04lqjHGK+i9Xi/9Og/Xr+unbMViY0DvPhmYAHsaZlTh8Fgxzc8iwE9KQXnVD05a2U5XATcMB2GvmOfzqnCsOQS9NR6znyfBak1+Q3IOIZ8ZcZ6HAo1U9B+FIzgN7Z1Tmn3NlEq22Mt2ykQIeSgPVGhMMHzLSjckqzkmnycMYWzDO0YaP0boeUXDLjCTjWzhTK0K+ZMJr3eVQ4U8veG8KwJAGQvavtFN9phXKDOzuCEY55kCLzZ4HUIYTHl+PQIsyMA/ZpClQ2nxFDUl346i6CFEWM/s6ghlgHBL12ue7FZsSWgU3M8ZDm5l6Nl8PqCjnAasKOQnSBitVEdqFEsm9zxMHECYJzMwx0i9ZR4Zpj3GYrGcQ+bkPM/6Fg3107dcVtjo84v8LDfjBuRBDj0D+VfLkJX+fIHXbYLMAinzlX4dh9+Of1GJ2Oc7Q7ZKnoH6ku8kFgiiElDH+t9SXqHMkGvsqcxuKVEInS0jkRwoc9tIjAu3PboWTKBfmUIR1RPhOY+uClRqsJLnV41JBGV1KZkZQgrPNLWySGX/tfkgJWjVQvhpiCheWU5HzdF3cnCGUfxVCPwZYycbAyJedQnaoncG6pTsNc+3V0NDgng2R1230QTU9TPVGPFqVyzVIqJmQvHJ5G2mUPLcfNaEF6zcbAUm7bFkqZKBmZqmPc049WznAKKugti2d1Vn1ZjYUkwqcjyUUyrK1yIO5tAFr8dpA5zQ1HuxYf55w4BfZ291LT5nMm2io1Ava28dZi7D6NZp8xaD9kZaiEnCI7VIEBvE57faH59CnN6WdS3b1fokgF3f0tKps7R6DgdKxlnma4jKd90iFWbVJbxwd5hgGqKpP0M0aVbPv0NCV/ZTe9+LJDZwPjsFur29TiT/DiunWjjXJldKq70l6+jqmDA2zNui2YWhEQMM1cx63Z6tFuc2cibzQ6q7S8rFZsrra+4kO4dOrszHF72Z2yunb6l/k63eTKHPuF3vsPD8tJjkVJqb598iedIgaTkr8O2pZgnzuf2z4fdlvorJzOvX3yqCch+WP60uH9jRdpH8AAAAAElFTkSuQmCC",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 228,
|
|
"metadata": {
|
|
"image/png": {
|
|
"width": 500
|
|
}
|
|
},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"!bart transpose 1 2 data/ip_mask data/img\n",
|
|
"!bart toimg -w 1.0 data/img fig/ip_mask.png\n",
|
|
"Image(\"fig/ip_mask.png\", width=500)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8da50e61-6996-44c9-85d0-e97cef04f4c3",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 3.3 Uniform Undersampling\n",
|
|
"Using bart upat - same pattern for every echo."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 229,
|
|
"id": "a9aa3845-2dc3-4e83-b68f-49b965af11ab",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"ACC_Y=2\n",
|
|
"ACC_Z=2\n",
|
|
"CENTER_SIZE=8\n",
|
|
"\n",
|
|
"bart upat -Y 80 -Z 16 -y $ACC_Y -z $ACC_Z -c $CENTER_SIZE data/upat"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 230,
|
|
"id": "ad44e09a-a74e-493e-bb3f-3cd3f7607eb6",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Scaling: 0.349421\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart fmac data/upat data/kSpace_transposed data/kSpace_upat\n",
|
|
"\n",
|
|
"# For nlinv the echos can't be in the coil dimension (3)\n",
|
|
"bart transpose 3 5 data/kSpace_upat data/kSpace_upat_transposed\n",
|
|
"\n",
|
|
"bart nlinv -i 30 -x 80:80:16 -S data/kSpace_upat_transposed data/nlinv_upat\n",
|
|
"# bart fft -i $(bart bitmask 0 1 2) data/kSpace_upat data/fft_upat\n",
|
|
"\n",
|
|
"# bart transpose 3 5 data/fft_upat data/fft_upat_transposed\n",
|
|
"\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/nlinv_upat data/fit_upat\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_upat data/mask_upat\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_upat data/mask_upat data/fit_mask_upat\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_upat data/R2_map_upat\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_upat data/T2_map_upat "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 231,
|
|
"id": "5132b2af-0e1d-44b9-90ba-d6031ca4d10a",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Writing 1 image(s)...done.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAFAAAAAQCAIAAAAOK2+WAAAARklEQVRIie3RIRIAMAgDwdD//5mKeqYiqemtwMJw6m5J/8xS3tl0qSp70nrz13sUNqNwAIUnFDajcACFJxQ2o3AAhScUNtsCZEIXIDnDpQAAAABJRU5ErkJggg==",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 231,
|
|
"metadata": {
|
|
"image/png": {
|
|
"width": 1000
|
|
}
|
|
},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"!bart transpose 1 2 data/upat data/img\n",
|
|
"!bart toimg -w 1.0 data/img fig/upat_mask.png\n",
|
|
"Image(\"fig/upat_mask.png\", width=1000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4c359bc3-c6e2-425b-acb7-52b5894ad654",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3.3.1 Uniform Undersampling\n",
|
|
"With varying patterns along the echos"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 32,
|
|
"id": "0882a788-ecd2-4968-9715-a57816d66e9c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Pattern creation completed. Output file: upat_combined\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Parameters\n",
|
|
"R=2 # Undersampling factor 4 leads to bad results\n",
|
|
"Y=80 # Dimension Y\n",
|
|
"Z=16 # Dimension Z\n",
|
|
"N_ECHO=20 # Number of ECHO shifts\n",
|
|
"CENTER_SIZE=16\n",
|
|
"\n",
|
|
"# Create the center \n",
|
|
"bart ones 2 $CENTER_SIZE $CENTER_SIZE data/mask_center\n",
|
|
"bart transpose 0 2 data/mask_center data/mask_center\n",
|
|
"\n",
|
|
"# Zero-pad the second (index 1) dimension to the full k-space dimension \n",
|
|
"bart resize -c 1 $Y 2 $Z data/mask_center data/mask_full\n",
|
|
"\n",
|
|
"# Create pattern with undersampling in phase direction by R=4\n",
|
|
"bart upat -Y $Y -Z $Z -y $R -z 1 -c 1 data/upat\n",
|
|
"\n",
|
|
"# Initialize the final combined pattern file\n",
|
|
"bart saxpy 1 data/mask_full data/upat data/upat_combined\n",
|
|
"\n",
|
|
"# Loop over N_ECHO times to apply shifts and join them\n",
|
|
"for ((i=1; i<N_ECHO; i++))\n",
|
|
"do\n",
|
|
" # Apply a circular shift of one along the phase direction\n",
|
|
" bart circshift 1 $i data/upat data/upat_shifted\n",
|
|
"\n",
|
|
" # Combine the center mask and the \n",
|
|
" bart saxpy 1 data/mask_full data/upat_shifted data/tmp\n",
|
|
"\n",
|
|
" # Join the shifted pattern along the 5th dimension \n",
|
|
" bart join 5 data/upat_combined data/tmp data/upat_combined\n",
|
|
"done\n",
|
|
"\n",
|
|
"# Threshold because some values can be 2 after saxpy\n",
|
|
"bart threshold -B 0.1 data/upat_combined data/upat_combined\n",
|
|
"\n",
|
|
"echo \"Pattern creation completed. Output file: upat_combined\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 33,
|
|
"id": "d14780bc-dd5a-4710-a52b-ef491caae213",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Scaling: 0.347030\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# For nlinv the echos can't be in the coil dimension (3) also to make it work with the upat_combined\n",
|
|
"bart transpose 3 5 data/kSpace_transposed data/kSpace_upat_combined_transposed\n",
|
|
"\n",
|
|
"bart fmac data/upat_combined data/kSpace_upat_combined_transposed data/kSpace_upat_combined\n",
|
|
"\n",
|
|
"# Compute pattern (just to check)\n",
|
|
"bart pattern data/kSpace_upat_combined data/calc_pattern\n",
|
|
"\n",
|
|
"bart nlinv -i 30 -x 80:80:16 -S data/kSpace_upat_combined data/nlinv_upat_combined data/nlinv_coilsens\n",
|
|
"# bart fft -i $(bart bitmask 0 1 2) data/kSpace_upat data/fft_upat\n",
|
|
"\n",
|
|
"# bart transpose 3 5 data/fft_upat data/fft_upat_transposed\n",
|
|
"\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/nlinv_upat_combined data/fit_upat_combined\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_upat_combined data/mask_upat_combined\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_upat_combined data/mask_upat_combined data/fit_mask_upat_combined\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_upat_combined data/R2_map_upat_combined\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_upat_combined data/T2_map_upat_combined"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 34,
|
|
"id": "821f937e-64ef-4ad3-9848-df50ee3faac3",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Writing 1 image(s)...done.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAFAAAAAQCAIAAAAOK2+WAAAANUlEQVRIie3PsREAMAzCQM7770xmcOFG0RfUKEna3u3W9Z/JZwymM5jOYDqD6QymM5jOYLoH3vuPj2BMzK0AAAAASUVORK5CYII=",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 34,
|
|
"metadata": {
|
|
"image/png": {
|
|
"width": 1000
|
|
}
|
|
},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"!bart transpose 1 2 data/upat_combined data/img\n",
|
|
"!bart slice 5 1 data/img data/img\n",
|
|
"!bart toimg -w 1.0 data/img fig/upat_combined_mask.png\n",
|
|
"Image(\"fig/upat_combined_mask.png\", width=1000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5c20ab89-d347-45ac-9833-7a5dd2c85fbf",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3.3.1 Uniform Undersampling PICS\n",
|
|
"Reco with pics"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 35,
|
|
"id": "3ea47c87-480b-434e-a451-f5dc246968c2",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Done.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart ecalib -m1 data/kSpace_upat_combined data/upat_coilsens"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 36,
|
|
"id": "5b6a3b3d-9bd1-4e2f-b4b1-fd33513f984c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Size: 2048000 Samples: 1228800 Acc: 1.67\n",
|
|
"l1 regularization: 0.030000\n",
|
|
"Regularization terms: 1, Supporting variables: 0\n",
|
|
"FISTA\n",
|
|
"Total Time: 6.242878\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart pics -RI:$(bart bitmask 5):3e-2 -i150 -S data/kSpace_upat_combined data/nlinv_coilsens data/pics2_upat \n",
|
|
"#bart pics -l1 -r 0.03 -i 150 -S data/kSpace_upat_combined data/nlinv_coilsens data/pics3_upat"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 37,
|
|
"id": "c28b7fa1-4acb-4cfc-98b3-d8af9cf21025",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/pics_upat data/fit_upat_pics\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_upat_pics data/mask_upat_pics\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_upat_pics data/mask_upat_pics data/fit_mask_upat_pics\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_upat_pics data/R2_map_upat_pics\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_upat_pics data/T2_map_upat_pics"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d6fd6361-4ff8-4fc8-9b59-c2ccc75aa997",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3.3.1 Uniform Undersampling (in-plane)\n",
|
|
"With varying patterns along the echos in-plane (kx ky)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 238,
|
|
"id": "b69cf32c-7712-4018-baa0-7f9646cb2502",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Pattern creation completed. Output file: upat_combined\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Parameters\n",
|
|
"R=4 # Undersampling factor\n",
|
|
"Y=80 # Dimension Y\n",
|
|
"X=80 # Dimension Z\n",
|
|
"N_ECHO=20 # Number of ECHO shifts\n",
|
|
"CENTER_SIZE=16\n",
|
|
"\n",
|
|
"# Create the center \n",
|
|
"bart ones 2 $Y $CENTER_SIZE data/mask_center\n",
|
|
"\n",
|
|
"# Zero-pad the second (index 1) dimension to the full k-space dimension \n",
|
|
"bart resize -c 1 $Y data/mask_center data/mask_full\n",
|
|
"\n",
|
|
"# Now the mask needs to be in x-y plane\n",
|
|
"#bart transpose 1 2 data/mask_full data/mask_full\n",
|
|
"#bart transpose 0 1 data/mask_full data/mask_full\n",
|
|
"\n",
|
|
"# Create pattern with undersampling in phase direction by R=4\n",
|
|
"bart upat -Y $Y -Z $X -y $R -z 1 -c 1 data/upat\n",
|
|
"\n",
|
|
"# Transpose this so it fits the bart dataformat\n",
|
|
"bart transpose 0 2 data/upat data/upat\n",
|
|
"\n",
|
|
"# Initialize the final combined pattern file\n",
|
|
"bart saxpy 1 data/mask_full data/upat data/upat_combined_ip\n",
|
|
"\n",
|
|
"# Loop over N_ECHO times to apply shifts and join them\n",
|
|
"for ((i=1; i<N_ECHO; i++))\n",
|
|
"do\n",
|
|
" # Apply a circular shift of one along the phase direction\n",
|
|
" bart circshift 1 $i data/upat data/upat_shifted\n",
|
|
"\n",
|
|
" # Combine the center mask and the \n",
|
|
" bart saxpy 1 data/mask_full data/upat_shifted data/tmp\n",
|
|
"\n",
|
|
" # Join the shifted pattern along the 5th dimension \n",
|
|
" bart join 5 data/upat_combined data/tmp data/upat_combined_ip\n",
|
|
"done\n",
|
|
"\n",
|
|
"bart threshold -B 0.1 data/upat_combined data/upat_combined_ip\n",
|
|
"\n",
|
|
"echo \"Pattern creation completed. Output file: upat_combined\"\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 240,
|
|
"id": "e8992b00-7216-45d8-8595-214884976703",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Writing 1 image(s)...done.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAIAAAABc2X6AAAAbklEQVR4nO3YwQ3AIBADQZL+ez56yCPIZqaCs8R+WOsyz8ycvgH4TsOQTcOQTcOQTcOQTcOQTcOQTcOUue5Jv6cP+JvB7QxuZ3A7g9sZ3M7gdgZT5roPACijYcimYcimYcimYcimYcimYcimYcps1lMy/ZHgArEAAAAASUVORK5CYII=",
|
|
"text/plain": [
|
|
"<IPython.core.display.Image object>"
|
|
]
|
|
},
|
|
"execution_count": 240,
|
|
"metadata": {
|
|
"image/png": {
|
|
"width": 500
|
|
}
|
|
},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"!bart transpose 0 1 data/upat_combined_ip data/img\n",
|
|
"!bart slice 5 1 data/img data/img\n",
|
|
"!bart toimg -w 1.0 data/img fig/upat_combined_mask_ip.png\n",
|
|
"Image(\"fig/upat_combined_mask_ip.png\", width=500)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 245,
|
|
"id": "fa611a8c-a923-4015-825a-71752aab022a",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Scaling: 0.348982\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# For nlinv the echos can't be in the coil dimension (3) also to make it work with the upat_combined\n",
|
|
"bart transpose 3 5 data/kSpace_transposed data/kSpace_upat_combined_transposed\n",
|
|
"\n",
|
|
"bart fmac data/upat_combined data/kSpace_upat_combined_transposed data/kSpace_upat_combined_ip\n",
|
|
"\n",
|
|
"# Compute pattern (just to check)\n",
|
|
"bart pattern data/kSpace_upat_combined_ip data/calc_pattern_ip\n",
|
|
"\n",
|
|
"bart nlinv -i 30 -x 80:80:16 -S data/kSpace_upat_combined_ip data/nlinv_upat_combined_ip\n",
|
|
"# bart fft -i $(bart bitmask 0 1 2) data/kSpace_upat data/fft_upat\n",
|
|
"\n",
|
|
"# bart transpose 3 5 data/fft_upat data/fft_upat_transposed\n",
|
|
"\n",
|
|
"# Fit the model:\n",
|
|
"bart mobafit -T data/echo_times_final data/nlinv_upat_combined_ip data/fit_upat_combined_ip\n",
|
|
"\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/fit_upat_combined_ip data/mask_upat_combined_ip\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/fit_upat_combined_ip data/mask_upat_combined_ip data/fit_mask_upat_combined_ip\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/fit_mask_upat_combined_ip data/R2_map_upat_combined_ip\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_map_upat_combined_ip data/T2_map_upat_combined_ip"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "16448609-399c-4967-896c-126819be8fec",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 4.0 Subspace Reco"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"id": "c74d227b-ff58-4ffb-a511-be3865c5618e",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Basis: [ 80 80 16 1 1 20 3 1 1 1 1 1 1 1 1 1 ]\n",
|
|
"Max: [ 80 80 16 1 1 1 3 1 1 1 1 1 1 1 1 1 ]\n",
|
|
"Size: 2048000 Samples: 2047999 Acc: 1.00\n",
|
|
"Regularization terms: 0, Supporting variables: 0\n",
|
|
"conjugate gradients\n",
|
|
"Total Time: 2.095993\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"bart signal -S -n20 -2 10e-3:0.5:1000 -e10e-3 data/sig\n",
|
|
"bart transpose 2 5 data/sig data/sig\n",
|
|
"bart squeeze data/sig data/sig\n",
|
|
"\n",
|
|
"bart svd -e data/sig data/U data/S data/V\n",
|
|
"\n",
|
|
"#Optionally view S so we can see how quickly we capture all information\n",
|
|
"# bart show data/S\n",
|
|
"\n",
|
|
"bart extract 1 0 3 data/U data/basis_tmp # Three coeffs are enough\n",
|
|
"bart transpose 1 6 data/basis_tmp data/basis_tmp\n",
|
|
"bart transpose 0 5 data/basis_tmp data/basis\n",
|
|
"\n",
|
|
"# Basis dim: AoD: 1 1 1 1 1 20 3 1 1 ... for pics\n",
|
|
"\n",
|
|
"# Now we get a coefficient map\n",
|
|
"# bart nlinv -B data/basis data/kSpace data/coeff data/sens\n",
|
|
"bart pics -B data/basis data/ksp data/nlinv_coilsens data/coeff\n",
|
|
"\n",
|
|
"# From the coefficients and the basis we can get the image\n",
|
|
"bart fmac -s $(bart bitmask 6) data/basis data/coeff data/imgs\n",
|
|
"\n",
|
|
"# We perform the T2 fit on the image\n",
|
|
"bart mobafit -T data/echo_times_final data/imgs data/t2"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"id": "bd942687-35f8-455f-a794-922bf19eb822",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Now some values will be very large so we can apply a threshold to obtain a mask\n",
|
|
"MAX_T2=1000\n",
|
|
"\n",
|
|
"bart threshold -M $MAX_T2 data/t2 data/t2_subreco\n",
|
|
"\n",
|
|
"# Multiply the fit with the mask\n",
|
|
"bart fmac data/t2 data/t2_subreco data/t2_fit_subreco\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/t2_fit_subreco data/R2_fit_subreco\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_fit_subreco data/T2_fit_subreco"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"id": "450ddbe5-dad6-4f34-89c1-58db4ca1968c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Basis: [ 80 80 16 1 1 20 3 1 1 1 1 1 1 1 1 1 ]\n",
|
|
"Max: [ 80 80 16 1 1 1 3 1 1 1 1 1 1 1 1 1 ]\n",
|
|
"Size: 2048000 Samples: 1228800 Acc: 1.67\n",
|
|
"Regularization terms: 0, Supporting variables: 0\n",
|
|
"conjugate gradients\n",
|
|
"Total Time: 2.317959\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"%%bash\n",
|
|
"# Now we get a coefficient map\n",
|
|
"# bart nlinv -B data/basis data/kSpace_upat_combined data/coeff_upat data/sens_upat\n",
|
|
"bart pics -B data/basis data/kSpace_upat_combined data/nlinv_coilsens data/coeff_upat\n",
|
|
"\n",
|
|
"## Coeffs are on dim 7\n",
|
|
"\n",
|
|
"# From the coefficients and the basis we can get the image\n",
|
|
"bart fmac -s $(bart bitmask 6) data/basis data/coeff_upat data/imgs_upat\n",
|
|
"\n",
|
|
"# We perform the T2 fit on the image \n",
|
|
"bart mobafit -T data/echo_times_final data/imgs_upat data/R2_fit_subreco_upat\n",
|
|
"\n",
|
|
"# Select slice\n",
|
|
"bart slice 6 1 data/R2_fit_subreco_upat data/R2_fit_subreco_upat\n",
|
|
"\n",
|
|
"# Invert the data to get T2\n",
|
|
"bart invert data/R2_fit_subreco_upat data/T2_fit_subreco_upat"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "cde1499e-4d97-4d21-b413-a2cccc21bd04",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"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.11.2"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|