Skip to content

Commit

Permalink
Published 1st version
Browse files Browse the repository at this point in the history
  • Loading branch information
dabosch committed Dec 6, 2023
0 parents commit 86cc5a3
Show file tree
Hide file tree
Showing 17 changed files with 3,066 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
myEnv/
**/__pycache__
*.mat
*.ini
*.png
env/
data/
*.dat

**/.ipynb_checkpoints
**/.virtual_documents

Readme.pdf
41 changes: 41 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# FastPtx: a python pTx pulse design tool for freely optimizing RF and gradient pulses with autodifferentiation

## Author:

Dario Bosch \<[email protected]>

## Other Contributors:

- Qi Wang \<[email protected]>
- helped with porting the bloch simulation code from C++ to Python
- helped with pytorch support
- Alexander Loktyushin \<[email protected]>
- gave valueable input on optimization with pytorch
- helped working out bugs

# How to use

The following steps describe using Python Virtual Environments.
If you prefer using Anaconda you can try adapting those steps. I don't see why it shouldn't work

1. Open a terminal in the projects' main directory
1. Create a python virtual environment:
`python -m venv ./env`
1. Activate the environment:
`source ./env/bin/activate`
1. Install the necessary python packages
- `pip install -r ./requirements.txt`
1. Get the example data and put it into the directory ./data/ by running the downloadFiles.sh script
- `./downloadFiles.sh`
1. open either `spyder` or `jupyter lab` from the active shell
1. modify and run `calc_smallFA_paper.py`
- the line `dev = torch.device('cuda')` sets the calculation to happen on a GPU. If you don't have a CUDA-enabled GPU, set it to `cpu` instead.
- `do_UP = False` switches between tailored and universal pulses
- Flip angle, pulse duration, etc can also be controlled by changing the settings in the beginning of the file.
- Run by either executing the `calc_smallFA_paper.ipynb` notebook in jupyter or by running the `calc_smallFA_paper.py` script directly
1. You can create an animation (gif) for an optimized pulse using the `animatePulse.ipynb` notebook

# Citing
If you use this code, please cite the corresponding paper:

Bosch, D.; Scheffler, K.: FastPtx: A Versatile Toolbox for Rapid, Joint Design of pTx RF and Gradient Pulses Using Pytorch's Autodifferentiation. Magnetic Resonance Materials in Physics, Biology and Medicine
116 changes: 116 additions & 0 deletions animatePulse.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "79067cb5-631f-4bd6-884f-e637bcac1431",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# %load animatePulse.py\n",
"#!/usr/bin/env python3\n",
"\"\"\"\n",
"Created on Sun Mar 20 23:52:57 2022\n",
"\n",
"@author: dario\n",
"\"\"\"\n",
"\n",
"from tools.io import readData, combineData, vectorizeData, \\\n",
" writePulse, readVOPfile, interpData, addLocalB0data, readPulse\n",
" \n",
"from tools.bloch import bloch\n",
"\n",
"from matplotlib import pyplot as plt\n",
"import os\n",
"from tqdm.auto import tqdm\n",
"\n",
"fname = './data/dbase/GHAF-HEY2.mat'\n",
"maskName = 'brainMask'\n",
"dat = readData(fname,maskName=maskName)\n",
"\n",
"dat_v = vectorizeData(dat)\n",
"\n",
"[p,g] = readPulse('./UP_20deg_500us_16Tx31Rx.ini',orientation='unity')\n",
"p *= 10\n",
"nSteps = p.shape[0];\n",
"lim = bloch.getLimits()\n",
"lim['plotscale'] = 12\n",
"lim['maxRF'] = p.abs().max()\n",
"\n",
"f = bloch.plotVec(p,g,dat_v,10e-6,lim)\n",
"filename = f'img/test.png'\n",
"f.savefig(filename)\n",
"\n",
"os.system('rm ./img/anim_*.png')\n",
"\n",
"for i in tqdm(range(nSteps)):\n",
" mp = p.clone();\n",
" mg = g.clone();\n",
" mp[i+1:,:] = 0\n",
" mg[:,i+1:] = 0\n",
" f = bloch.plotVec(mp,mg,dat_v,10e-6,lim,save=True)\n",
" filename = f'img/anim_{i:03}.png'\n",
" #f = plt.gcf()\n",
" f.savefig(filename)\n",
" plt.close();\n",
"# pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "14800445-b449-4c56-94ba-590de8bfe5d9",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"os.system('pwd')\n",
"os.system(f'bash -c \"convert -crop 1160x1070+00+60 +repage -delay 20 -loop 0 ./img/anim_{{000..{nSteps-2:003}}}.png ./img/animated.gif\"')\n",
"os.system(f'convert -crop 1160x1070+00+60 +repage img/anim_{nSteps-1:03}.png ./img/temp.png')\n",
"os.system(f'convert ./img/animated.gif -delay 300 -loop 0 img/temp.png ./img/animated.gif')\n",
"os.system('convert ./img/animated.gif ./img/animated.mp4')\n",
"# for i in tqdm(range(nSteps)):\n",
"# os.system(f'convert -crop 1160x0+00+60 +repage img/anim_{i:03}.png /tmp/temp.png')\n",
"# if i==0:\n",
"# os.system(f'convert -delay 20 -loop 0 /tmp/temp.png /tmp/animated.gif')\n",
"# elif i==nSteps-1:\n",
"# os.system(f'convert /tmp/animated.gif -delay 300 -loop 0 -crop 1160x0+00+60 +repage img/anim_{i:03}.png /tmp/animated.gif')\n",
"# else:\n",
"# os.system(f'convert /tmp/animated.gif -delay 20 -loop 0 /tmp/temp.png /tmp/animated.gif')\n",
"# os.system('mv /tmp/animated.gif ./img/animated.gif')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c7b1c9a2-61c3-4601-bd0f-35e26b7a288c",
"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.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
43 changes: 43 additions & 0 deletions calc_HF_pulse.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "601628c8-9cf1-41f1-b963-b1244909e981",
"metadata": {},
"outputs": [],
"source": [
"%run calc_HF_pulse.py"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a3fc916-3b63-41ba-b652-43b9f8bb81ed",
"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.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit 86cc5a3

Please sign in to comment.