MRArbGrad 2.0.1__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0/MRArbGrad.egg-info}/PKG-INFO +9 -6
- {mrarbgrad-2.0.1/MRArbGrad.egg-info → mrarbgrad-2.1.0}/PKG-INFO +9 -6
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/README.md +8 -5
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/example/example_BuiltInTraj.py +4 -2
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/example/example_ExternalFunction2D.py +15 -14
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/example/example_ExternalSamples2D.py +11 -10
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/example/example_ExternalSamples3D.py +11 -10
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/Utility.py +41 -1
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/__init__.py +1 -1
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/mag/Mag.cpp +16 -16
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/mag/Mag.h +5 -5
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/main.cpp +1 -1
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/MrTraj.h +12 -12
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/TrajFunc.h +1 -1
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/pyproject.toml +2 -2
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/LICENSE +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/MANIFEST.in +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/MRArbGrad.egg-info/SOURCES.txt +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/MRArbGrad.egg-info/dependency_links.txt +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/MRArbGrad.egg-info/requires.txt +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/MRArbGrad.egg-info/top_level.txt +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/Function.py +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/TrajFunc.py +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/mag/GradGen.cpp +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/mag/GradGen.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Cones.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/MrTraj_2D.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Rosette.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Seiffert.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Shell3d.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Spiral.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/VarDenSpiral.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/traj/Yarnball.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/Intp.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/LinIntp.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/SplineIntp.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/global.cpp +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/global.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/v3.cpp +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/ext/utility/v3.h +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/trajfunc/__init__.py +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/mrarbgrad_src/trajfunc/main.py +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/setup.cfg +0 -0
- {mrarbgrad-2.0.1 → mrarbgrad-2.1.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MRArbGrad
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Gradient waveform design tool for arbitrary k-space trajectories.
|
|
5
5
|
Author-email: Ryan <ryan_shanghaitech@proton.me>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,18 +22,21 @@ This toolbox is a pip package with C++ backend. The pip package can be called vi
|
|
|
22
22
|
```bash
|
|
23
23
|
$ conda create -n magtest -y
|
|
24
24
|
$ conda activate magtest
|
|
25
|
-
$ conda install python==3.
|
|
25
|
+
$ conda install python==3.12 -y
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
This package is **NOT** restricted to use `Python 3.
|
|
28
|
+
This package is **NOT** restricted to use `Python 3.12`. Feel free to adjust at your convenience, just if the package works.
|
|
29
29
|
|
|
30
|
-
To install the pip package of the proposed algorithm (including the trajectory library built on it)
|
|
30
|
+
To install the pip package of the proposed algorithm (including the trajectory library built on it):
|
|
31
31
|
```bash
|
|
32
|
-
$ pip install -r requirements.txt
|
|
33
32
|
$ bash install.bash
|
|
34
33
|
```
|
|
34
|
+
or
|
|
35
|
+
```bash
|
|
36
|
+
$ pip install mrarbgrad
|
|
37
|
+
```
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
You can also install via `pip install .` but remember to delete `*.egg-info` or pip will run into bug when uninstalling this package in current folder (see comments in `install.bash`).
|
|
37
40
|
|
|
38
41
|
## Examples & Usages
|
|
39
42
|
Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MRArbGrad
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Gradient waveform design tool for arbitrary k-space trajectories.
|
|
5
5
|
Author-email: Ryan <ryan_shanghaitech@proton.me>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,18 +22,21 @@ This toolbox is a pip package with C++ backend. The pip package can be called vi
|
|
|
22
22
|
```bash
|
|
23
23
|
$ conda create -n magtest -y
|
|
24
24
|
$ conda activate magtest
|
|
25
|
-
$ conda install python==3.
|
|
25
|
+
$ conda install python==3.12 -y
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
This package is **NOT** restricted to use `Python 3.
|
|
28
|
+
This package is **NOT** restricted to use `Python 3.12`. Feel free to adjust at your convenience, just if the package works.
|
|
29
29
|
|
|
30
|
-
To install the pip package of the proposed algorithm (including the trajectory library built on it)
|
|
30
|
+
To install the pip package of the proposed algorithm (including the trajectory library built on it):
|
|
31
31
|
```bash
|
|
32
|
-
$ pip install -r requirements.txt
|
|
33
32
|
$ bash install.bash
|
|
34
33
|
```
|
|
34
|
+
or
|
|
35
|
+
```bash
|
|
36
|
+
$ pip install mrarbgrad
|
|
37
|
+
```
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
You can also install via `pip install .` but remember to delete `*.egg-info` or pip will run into bug when uninstalling this package in current folder (see comments in `install.bash`).
|
|
37
40
|
|
|
38
41
|
## Examples & Usages
|
|
39
42
|
Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
|
|
@@ -8,18 +8,21 @@ This toolbox is a pip package with C++ backend. The pip package can be called vi
|
|
|
8
8
|
```bash
|
|
9
9
|
$ conda create -n magtest -y
|
|
10
10
|
$ conda activate magtest
|
|
11
|
-
$ conda install python==3.
|
|
11
|
+
$ conda install python==3.12 -y
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
This package is **NOT** restricted to use `Python 3.
|
|
14
|
+
This package is **NOT** restricted to use `Python 3.12`. Feel free to adjust at your convenience, just if the package works.
|
|
15
15
|
|
|
16
|
-
To install the pip package of the proposed algorithm (including the trajectory library built on it)
|
|
16
|
+
To install the pip package of the proposed algorithm (including the trajectory library built on it):
|
|
17
17
|
```bash
|
|
18
|
-
$ pip install -r requirements.txt
|
|
19
18
|
$ bash install.bash
|
|
20
19
|
```
|
|
20
|
+
or
|
|
21
|
+
```bash
|
|
22
|
+
$ pip install mrarbgrad
|
|
23
|
+
```
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
You can also install via `pip install .` but remember to delete `*.egg-info` or pip will run into bug when uninstalling this package in current folder (see comments in `install.bash`).
|
|
23
26
|
|
|
24
27
|
## Examples & Usages
|
|
25
28
|
Examples for generating gradient waveforms for either built-in trajectory (trajectory library) or external trajectory (expressed by trajectory function or trajectory samples) can be found in the `example` folder.
|
|
@@ -28,14 +28,16 @@ mag.setDbgPrint(1) # enable debug info (for benchmark purpose)
|
|
|
28
28
|
# calculate gradient
|
|
29
29
|
# lstArrK0, lstArrGrad = mag.getG_Spiral(is3D=0, **argCom); nAx = 2
|
|
30
30
|
# lstArrK0, lstArrGrad = mag.getG_VarDenSpiral(is3D=0, **argCom); nAx = 2
|
|
31
|
-
lstArrK0, lstArrGrad = mag.getG_VarDenSpiral_RT(is3D=0, **argCom); nAx = 2
|
|
32
|
-
|
|
31
|
+
# lstArrK0, lstArrGrad = mag.getG_VarDenSpiral_RT(is3D=0, **argCom); nAx = 2
|
|
32
|
+
lstArrK0, lstArrGrad = mag.getG_Rosette(is3D=0, **argCom); nAx = 2
|
|
33
33
|
# lstArrK0, lstArrGrad = mag.getG_Rosette_Trad(**argCom); nAx = 2
|
|
34
34
|
# lstArrK0, lstArrGrad = mag.getG_Shell3d(**argCom); nAx = 3
|
|
35
35
|
# lstArrK0, lstArrGrad = mag.getG_Yarnball(**argCom); nAx = 3
|
|
36
36
|
# lstArrK0, lstArrGrad = mag.getG_Seiffert(**argCom); nAx = 3
|
|
37
37
|
# lstArrK0, lstArrGrad = mag.getG_Cones(**argCom); nAx = 3
|
|
38
38
|
|
|
39
|
+
# lstArrGrad = mag.gradClip(lstArrGrad, dtGrad, sLim, gLim) # clip slew/grad amp with hardware constraint
|
|
40
|
+
|
|
39
41
|
print("")
|
|
40
42
|
print(f"Intlea Num.: {len(lstArrGrad)}")
|
|
41
43
|
nRO_Max = amax([arrG.shape[0] for arrG in lstArrGrad])
|
|
@@ -6,16 +6,16 @@ import mrarbgrad as mag
|
|
|
6
6
|
gamma = 42.5756e6
|
|
7
7
|
fov = 0.256
|
|
8
8
|
nPix = 256
|
|
9
|
-
dtGrad = 10e-6
|
|
10
|
-
dtADC = 2.5e-6
|
|
9
|
+
dtGrad = 10e-6 * 1e-1
|
|
10
|
+
dtADC = 2.5e-6 * 1e-1
|
|
11
11
|
sLim = 50 * gamma * fov/nPix
|
|
12
12
|
gLim = 20e-3 * gamma * fov/nPix
|
|
13
13
|
# gLim = 1/nPix/dtADC
|
|
14
14
|
|
|
15
15
|
# Rosette
|
|
16
16
|
nAx = 2
|
|
17
|
-
om1 =
|
|
18
|
-
om2 =
|
|
17
|
+
om1 = 19*pi
|
|
18
|
+
om2 = 17*pi
|
|
19
19
|
def Rosette(t):
|
|
20
20
|
rho = 0.5*sin(om1*t)
|
|
21
21
|
return array\
|
|
@@ -28,13 +28,14 @@ def Rosette(t):
|
|
|
28
28
|
pLim = [0,1]
|
|
29
29
|
|
|
30
30
|
# derive slew-rate constrained trajectory
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
arrGrad = mag.calGrad4ExFunc(False, fov, nPix, sLim, gLim, dtGrad, Rosette, None, None, pLim[0], pLim[1])[0]
|
|
32
|
+
# arrGrad = mag.gradClip(arrGrad, dtGrad, sLim, gLim) # clip slew/grad amp with hardware constraint
|
|
33
|
+
nRO = arrGrad.shape[0]
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
print(f"sMax: {max(norm(
|
|
35
|
+
arrSlew = diff(arrGrad, axis=0)/dtGrad
|
|
36
|
+
print(f"sMax: {max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov)}")
|
|
36
37
|
|
|
37
|
-
arrK
|
|
38
|
+
arrK = mag.cvtGrad2Traj(arrGrad, dtGrad, dtADC, 0.5)[0]
|
|
38
39
|
|
|
39
40
|
# derive reference trajectory
|
|
40
41
|
arrP_Ref = linspace(pLim[0], pLim[1], int(1e4))
|
|
@@ -57,21 +58,21 @@ title("k-Space")
|
|
|
57
58
|
|
|
58
59
|
subplot(222)
|
|
59
60
|
for iAx in range(nAx):
|
|
60
|
-
plot(
|
|
61
|
+
plot(arrGrad[:,iAx]/(42.58e6)*(nPix/fov), ".-")
|
|
61
62
|
grid("on")
|
|
62
63
|
title("Gradient")
|
|
63
64
|
|
|
64
65
|
subplot(223, projection=None if nAx==2 else "3d")
|
|
65
|
-
if nAx==2: plot(
|
|
66
|
-
if nAx==3: plot(
|
|
66
|
+
if nAx==2: plot(arrGrad[:,0], arrGrad[:,1], ".-")
|
|
67
|
+
if nAx==3: plot(arrGrad[:,0], arrGrad[:,1], arrGrad[:,2], ".-")
|
|
67
68
|
axis("equal")
|
|
68
69
|
grid("on")
|
|
69
70
|
title("g-Space")
|
|
70
71
|
|
|
71
72
|
subplot(224)
|
|
72
|
-
plot(norm(
|
|
73
|
+
plot(norm(arrSlew,axis=-1)/(42.58e6)*(nPix/fov), ".-")
|
|
73
74
|
ylim(sLim/(42.58e6)*(nPix/fov)*0.9, sLim/(42.58e6)*(nPix/fov)*1.1)
|
|
74
75
|
grid("on")
|
|
75
|
-
title(f"Slewrate, max:{max(norm(
|
|
76
|
+
title(f"Slewrate, max:{max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov):.3f}")
|
|
76
77
|
|
|
77
78
|
show()
|
|
@@ -32,13 +32,14 @@ nAx = 2
|
|
|
32
32
|
|
|
33
33
|
# derive slew-rate constrained trajectory
|
|
34
34
|
for i in range(1):
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
arrGrad = mag.calGrad4ExSamp(False, fov, nPix, sLim, gLim, dtGrad, arrK)[0]
|
|
36
|
+
# arrGrad = mag.gradClip(arrGrad, dtGrad, sLim, gLim) # clip slew/grad amp with hardware constraint
|
|
37
|
+
nRO = arrGrad.shape[0]
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
print(f"sMax: {max(norm(
|
|
39
|
+
arrSlew = diff(arrGrad, axis=0)/dtGrad
|
|
40
|
+
print(f"sMax: {max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov)}")
|
|
40
41
|
|
|
41
|
-
arrK, _ = mag.cvtGrad2Traj(
|
|
42
|
+
arrK, _ = mag.cvtGrad2Traj(arrGrad, dtGrad, dtADC, 0.5)
|
|
42
43
|
arrK += TrajFunc(pLim[0])
|
|
43
44
|
print(f"Err: {norm(arrK[-1,:]-TrajFunc(pLim[1])):.1e}")
|
|
44
45
|
|
|
@@ -63,21 +64,21 @@ title("k-Space")
|
|
|
63
64
|
|
|
64
65
|
subplot(222)
|
|
65
66
|
for iAx in range(nAx):
|
|
66
|
-
plot(
|
|
67
|
+
plot(arrGrad[:,iAx]/(42.58e6)*(nPix/fov), ".-")
|
|
67
68
|
grid("on")
|
|
68
69
|
title("Gradient")
|
|
69
70
|
|
|
70
71
|
subplot(223, projection=None if nAx==2 else "3d")
|
|
71
|
-
if nAx==2: plot(
|
|
72
|
-
if nAx==3: plot(
|
|
72
|
+
if nAx==2: plot(arrGrad[:,0], arrGrad[:,1], ".-")
|
|
73
|
+
if nAx==3: plot(arrGrad[:,0], arrGrad[:,1], arrGrad[:,2], ".-")
|
|
73
74
|
axis("equal")
|
|
74
75
|
grid("on")
|
|
75
76
|
title("g-Space")
|
|
76
77
|
|
|
77
78
|
subplot(224)
|
|
78
|
-
plot(norm(
|
|
79
|
+
plot(norm(arrSlew,axis=-1)/(42.58e6)*(nPix/fov), ".-")
|
|
79
80
|
ylim(sLim/(42.58e6)*(nPix/fov)*0.9, sLim/(42.58e6)*(nPix/fov)*1.1)
|
|
80
81
|
grid("on")
|
|
81
|
-
title(f"Slewrate, max:{max(norm(
|
|
82
|
+
title(f"Slewrate, max:{max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov):.3f}")
|
|
82
83
|
|
|
83
84
|
show()
|
|
@@ -24,13 +24,14 @@ arrK = Yarnball(arrP)
|
|
|
24
24
|
|
|
25
25
|
# derive slew-rate constrained trajectory
|
|
26
26
|
mag.setDbgPrint(1)
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
arrGrad = mag.calGrad4ExSamp(True, fov, nPix, sLim, gLim, dtGrad, arrK)[0]
|
|
28
|
+
# arrGrad = mag.gradClip(arrGrad, dtGrad, sLim, gLim) # clip slew/grad amp with hardware constraint
|
|
29
|
+
nRO = arrGrad.shape[0]
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
print(f"sMax: {max(norm(
|
|
31
|
+
arrSlew = diff(arrGrad, axis=0)/dtGrad
|
|
32
|
+
print(f"sMax: {max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov)}")
|
|
32
33
|
|
|
33
|
-
arrK, _ = mag.cvtGrad2Traj(
|
|
34
|
+
arrK, _ = mag.cvtGrad2Traj(arrGrad, dtGrad, dtADC, 0.5)
|
|
34
35
|
|
|
35
36
|
# derive reference trajectory
|
|
36
37
|
arrP_Ref = linspace(pLim[0], pLim[1], int(1e4))
|
|
@@ -51,21 +52,21 @@ title("k-Space")
|
|
|
51
52
|
|
|
52
53
|
subplot(222)
|
|
53
54
|
for iAx in range(nAx):
|
|
54
|
-
plot(
|
|
55
|
+
plot(arrGrad[:,iAx]/(42.58e6)*(nPix/fov), ".-")
|
|
55
56
|
grid("on")
|
|
56
57
|
title("Gradient")
|
|
57
58
|
|
|
58
59
|
subplot(223, projection=None if nAx==2 else "3d")
|
|
59
|
-
if nAx==2: plot(
|
|
60
|
-
if nAx==3: plot(
|
|
60
|
+
if nAx==2: plot(arrGrad[:,0], arrGrad[:,1], ".-")
|
|
61
|
+
if nAx==3: plot(arrGrad[:,0], arrGrad[:,1], arrGrad[:,2], ".-")
|
|
61
62
|
axis("equal")
|
|
62
63
|
grid("on")
|
|
63
64
|
title("g-Space")
|
|
64
65
|
|
|
65
66
|
subplot(224)
|
|
66
|
-
plot(norm(
|
|
67
|
+
plot(norm(arrSlew,axis=-1)/(42.58e6)*(nPix/fov), ".-")
|
|
67
68
|
ylim(sLim/(42.58e6)*(nPix/fov)*0.9, sLim/(42.58e6)*(nPix/fov)*1.1)
|
|
68
69
|
grid("on")
|
|
69
|
-
title(f"Slewrate, max:{max(norm(
|
|
70
|
+
title(f"Slewrate, max:{max(norm(arrSlew,axis=-1))/(42.58e6)*(nPix/fov):.3f}")
|
|
70
71
|
|
|
71
72
|
show()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from numpy import *
|
|
2
|
+
from numpy.linalg import norm
|
|
2
3
|
from numpy.typing import *
|
|
3
|
-
from matplotlib.pyplot import *
|
|
4
4
|
|
|
5
5
|
goldrat = (1+sqrt(5))/2
|
|
6
6
|
goldang = (2*pi)/(1+goldrat)
|
|
@@ -8,6 +8,46 @@ goldang = (2*pi)/(1+goldrat)
|
|
|
8
8
|
getGoldrat = lambda: goldrat
|
|
9
9
|
getGoldang = lambda: goldang
|
|
10
10
|
|
|
11
|
+
def gradClip(lstArrGrad:list[NDArray]|NDArray, dt:float, sLim:float, gLim:float) -> list[NDArray]|NDArray:
|
|
12
|
+
"""
|
|
13
|
+
Clip the slewrate and gradient amlitude of a list of gradient waveforms
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
lstArrGrad: list of gradient waveforms
|
|
17
|
+
sLim: slewrate amplitude limit
|
|
18
|
+
gLim: gradient amplitude limit
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Clipped gradient waveforms
|
|
22
|
+
"""
|
|
23
|
+
if isinstance(lstArrGrad, ndarray): _lstArrGrad = [lstArrGrad.copy()]
|
|
24
|
+
else: _lstArrGrad = lstArrGrad.copy()
|
|
25
|
+
nPE = len(_lstArrGrad)
|
|
26
|
+
for iPE in range(nPE):
|
|
27
|
+
# slew-rate clipping
|
|
28
|
+
arrGrad = _lstArrGrad[iPE]
|
|
29
|
+
arrSlew = diff(arrGrad, 1, 0)/dt
|
|
30
|
+
arrSlewNorm = norm(arrSlew, axis=-1)
|
|
31
|
+
arrSlewNorm[where(arrSlewNorm==0)] += 1e-6
|
|
32
|
+
arrSlewUnit = arrSlew/arrSlewNorm[:,newaxis]
|
|
33
|
+
clip(arrSlewNorm, None, sLim, out=arrSlewNorm)
|
|
34
|
+
arrSlew = arrSlewUnit*arrSlewNorm[:,newaxis]
|
|
35
|
+
# gradient clipping
|
|
36
|
+
arrGrad[:,:] = arrGrad[0,:]
|
|
37
|
+
arrGrad[1:,:] += cumsum(arrSlew*dt, axis=0)
|
|
38
|
+
arrGradNorm = norm(arrGrad, axis=-1)
|
|
39
|
+
arrGradNorm[where(arrGradNorm==0)] += 1e-6
|
|
40
|
+
arrGradUnit = arrGrad/arrGradNorm[:,newaxis]
|
|
41
|
+
clip(arrGradNorm, None, gLim, out=arrGradNorm)
|
|
42
|
+
arrGrad = arrGradUnit*arrGradNorm[:,newaxis]
|
|
43
|
+
#
|
|
44
|
+
_lstArrGrad[iPE] = arrGrad
|
|
45
|
+
|
|
46
|
+
if isinstance(lstArrGrad, ndarray):
|
|
47
|
+
return _lstArrGrad[0]
|
|
48
|
+
else:
|
|
49
|
+
return _lstArrGrad
|
|
50
|
+
|
|
11
51
|
def rand3d(i:int|NDArray, nAx:int=3, kx=sqrt(2), ky=sqrt(3), kz=sqrt(7)) -> NDArray:
|
|
12
52
|
return (hstack if size(i)==1 else vstack)\
|
|
13
53
|
([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .Function import calGrad4ExFunc, calGrad4ExSamp
|
|
2
2
|
from .Function import getG_Cones, getG_Rosette, getG_Rosette_Trad, getG_Seiffert, getG_Shell3d, getG_Spiral, getG_VarDenSpiral, getG_VarDenSpiral_RT, getG_Yarnball
|
|
3
3
|
from .Function import setSolverMtg, setTrajRev, setGoldAng, setShuf, setMaxG0, setMaxG1, setExGEnd, setMagOverSamp, setMagSFS, setMagGradRep, setMagTrajRep, setDbgPrint
|
|
4
|
-
from .Utility import _calDiaphony, rotate, _calJacElip, _calCompElipInt, _calSphFibPt, cvtGrad2Traj, getGoldang, getGoldrat, rand3d
|
|
4
|
+
from .Utility import _calDiaphony, rotate, _calJacElip, _calCompElipInt, _calSphFibPt, cvtGrad2Traj, getGoldang, getGoldrat, rand3d, gradClip
|
|
5
5
|
|
|
6
6
|
from . import trajfunc
|
|
@@ -12,7 +12,7 @@ bool gMag_enGradRep = true; // Gradient Reparameterization
|
|
|
12
12
|
bool gMag_enTrajRep = true; // use trajectory reparameterization for MAG solver
|
|
13
13
|
i64 gMag_nTrajSamp = 1000; // num. of samp. when doing Traj. Rep.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Mag::Mag()
|
|
16
16
|
{
|
|
17
17
|
m_dt = 10e-6; m_oversamp = 8;
|
|
18
18
|
i64 nSampReserve = i64(100e-3/m_dt*m_oversamp); // reserve for 100ms
|
|
@@ -25,7 +25,7 @@ MagSolver::MagSolver()
|
|
|
25
25
|
m_vv3G_For.reserve(nSampReserve);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
bool
|
|
28
|
+
bool Mag::setup
|
|
29
29
|
(
|
|
30
30
|
TrajFunc* ptTraj,
|
|
31
31
|
f64 sLim, f64 gLim,
|
|
@@ -61,7 +61,7 @@ bool MagSolver::setup
|
|
|
61
61
|
return true;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
bool
|
|
64
|
+
bool Mag::setup
|
|
65
65
|
(
|
|
66
66
|
const vv3& vv3TrajSamp,
|
|
67
67
|
f64 sLim, f64 gLim,
|
|
@@ -81,10 +81,10 @@ bool MagSolver::setup
|
|
|
81
81
|
return true;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Mag::~Mag()
|
|
85
85
|
{}
|
|
86
86
|
|
|
87
|
-
bool
|
|
87
|
+
bool Mag::sovQDE(f64* psol0, f64* psol1, f64 a, f64 b, f64 c)
|
|
88
88
|
{
|
|
89
89
|
f64 delta = b*b - 4e0*a*c;
|
|
90
90
|
if (psol0) *psol0 = (-b-(delta<0?0:std::sqrt(delta)))/(2*a);
|
|
@@ -92,7 +92,7 @@ bool MagSolver::sovQDE(f64* psol0, f64* psol1, f64 a, f64 b, f64 c)
|
|
|
92
92
|
return delta>=0;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
f64
|
|
95
|
+
f64 Mag::getCurRad(f64 p)
|
|
96
96
|
{
|
|
97
97
|
v3 dkdp; m_ptfTraj->getDkDp(&dkdp, p);
|
|
98
98
|
v3 d2kdp2; m_ptfTraj->getD2kDp2(&d2kdp2, p);
|
|
@@ -103,7 +103,7 @@ f64 MagSolver::getCurRad(f64 p)
|
|
|
103
103
|
|
|
104
104
|
#if 1
|
|
105
105
|
|
|
106
|
-
f64
|
|
106
|
+
f64 Mag::getDp(const v3& v3GPrev, const v3& v3GThis, f64 dt, f64 pPrev, f64 pThis, f64 signDp)
|
|
107
107
|
{
|
|
108
108
|
// solve `ΔP` by RK2
|
|
109
109
|
f64 l = v3::norm(v3GThis)*dt;
|
|
@@ -127,7 +127,7 @@ f64 MagSolver::getDp(const v3& v3GPrev, const v3& v3GThis, f64 dt, f64 pPrev, f6
|
|
|
127
127
|
|
|
128
128
|
#else // less accurate due to estimation of PNext
|
|
129
129
|
|
|
130
|
-
f64
|
|
130
|
+
f64 Mag::getDp(const v3& v3GPrev, const v3& v3GThis, f64 dt, f64 pPrev, f64 pThis, f64 signDp)
|
|
131
131
|
{
|
|
132
132
|
// solve `ΔP` by RK2
|
|
133
133
|
f64 l = v3::norm(v3GThis)*dt;
|
|
@@ -140,7 +140,7 @@ f64 MagSolver::getDp(const v3& v3GPrev, const v3& v3GThis, f64 dt, f64 pPrev, f6
|
|
|
140
140
|
|
|
141
141
|
#endif
|
|
142
142
|
|
|
143
|
-
bool
|
|
143
|
+
bool Mag::step(v3* gUnit, f64* gNormMin, f64* gNormMax, f64 p, f64 signDp, const v3& g, f64 sLim, f64 dt)
|
|
144
144
|
{
|
|
145
145
|
// current gradient direction
|
|
146
146
|
v3 dkdp; m_ptfTraj->getDkDp(&dkdp, p);
|
|
@@ -161,7 +161,7 @@ bool MagSolver::step(v3* gUnit, f64* gNormMin, f64* gNormMax, f64 p, f64 signDp,
|
|
|
161
161
|
return isQDESucc;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
bool
|
|
164
|
+
bool Mag::solve(vv3* pvv3G, vf64* pvf64P)
|
|
165
165
|
{
|
|
166
166
|
bool ret = true;
|
|
167
167
|
f64 p0 = m_ptfTraj->getP0();
|
|
@@ -327,7 +327,7 @@ bool MagSolver::compute(vv3* pvv3G, vf64* pvf64P)
|
|
|
327
327
|
return ret;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
bool
|
|
330
|
+
bool Mag::ramp_front(vv3* pvv3GRamp, const v3& g0, const v3& g0Des, f64 sLim, f64 dt)
|
|
331
331
|
{
|
|
332
332
|
v3 dg = g0Des - g0;
|
|
333
333
|
v3 dgUnit = v3::norm(dg)!=0 ? dg/v3::norm(dg) : v3(0,0,0);
|
|
@@ -347,7 +347,7 @@ bool MagSolver::ramp_front(vv3* pvv3GRamp, const v3& g0, const v3& g0Des, f64 sL
|
|
|
347
347
|
return true;
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
f64
|
|
350
|
+
f64 Mag::ramp_front(vv3* pvv3GRamp, const v3& g0, const v3& g0Des, i64 nSamp, f64 dt)
|
|
351
351
|
{
|
|
352
352
|
v3 dg = g0Des - g0;
|
|
353
353
|
v3 dgUnit = v3::norm(dg)!=0 ? dg/v3::norm(dg) : v3(0,0,0);
|
|
@@ -367,7 +367,7 @@ f64 MagSolver::ramp_front(vv3* pvv3GRamp, const v3& g0, const v3& g0Des, i64 nSa
|
|
|
367
367
|
return sLim;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
bool
|
|
370
|
+
bool Mag::ramp_back(vv3* pvv3GRamp, const v3& g1, const v3& g1Des, f64 sLim, f64 dt)
|
|
371
371
|
{
|
|
372
372
|
v3 dg = g1Des - g1;
|
|
373
373
|
v3 dgUnit = v3::norm(dg)!=0 ? dg/v3::norm(dg) : v3(0,0,0);
|
|
@@ -387,7 +387,7 @@ bool MagSolver::ramp_back(vv3* pvv3GRamp, const v3& g1, const v3& g1Des, f64 sLi
|
|
|
387
387
|
return true;
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
f64
|
|
390
|
+
f64 Mag::ramp_back(vv3* pvv3GRamp, const v3& g1, const v3& g1Des, i64 nSamp, f64 dt)
|
|
391
391
|
{
|
|
392
392
|
v3 dg = g1Des - g1;
|
|
393
393
|
v3 dgUnit = v3::norm(dg)!=0 ? dg/v3::norm(dg) : v3(0,0,0);
|
|
@@ -407,7 +407,7 @@ f64 MagSolver::ramp_back(vv3* pvv3GRamp, const v3& g1, const v3& g1Des, i64 nSam
|
|
|
407
407
|
return sLim;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
bool
|
|
410
|
+
bool Mag::revGrad(v3* pv3M0Dst, vv3* pvv3Dst, const v3& v3M0Src, const vv3& vv3Src, f64 dt)
|
|
411
411
|
{
|
|
412
412
|
bool ret = true;
|
|
413
413
|
|
|
@@ -426,7 +426,7 @@ bool MagSolver::revGrad(v3* pv3M0Dst, vv3* pvv3Dst, const v3& v3M0Src, const vv3
|
|
|
426
426
|
return ret;
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
v3
|
|
429
|
+
v3 Mag::calM0(const vv3& vv3G, f64 dt)
|
|
430
430
|
{
|
|
431
431
|
v3 M0 = v3(0,0,0);
|
|
432
432
|
for (int64_t i = 1; i < (i64)vv3G.size(); ++i)
|
|
@@ -84,7 +84,7 @@ protected:
|
|
|
84
84
|
SplineIntp m_intpX, m_intpY, m_intpZ;
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
class
|
|
87
|
+
class Mag
|
|
88
88
|
{
|
|
89
89
|
public:
|
|
90
90
|
typedef std::vector<i64> vi64;
|
|
@@ -97,7 +97,7 @@ public:
|
|
|
97
97
|
typedef std::list<v3> lv3;
|
|
98
98
|
typedef std::list<vv3> lvv3;
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
Mag();
|
|
101
101
|
bool setup
|
|
102
102
|
(
|
|
103
103
|
TrajFunc* ptTraj,
|
|
@@ -112,8 +112,8 @@ public:
|
|
|
112
112
|
f64 dt=10e-6, i64 oversamp=10,
|
|
113
113
|
f64 dG0Norm=0e0, f64 dG1Norm=0e0
|
|
114
114
|
);
|
|
115
|
-
~
|
|
116
|
-
bool
|
|
115
|
+
~Mag();
|
|
116
|
+
bool solve(vv3* plv3G, vf64* pvf64P=NULL);
|
|
117
117
|
template <typename dtype, typename cv3>
|
|
118
118
|
static bool decomp
|
|
119
119
|
(
|
|
@@ -154,7 +154,7 @@ private:
|
|
|
154
154
|
|
|
155
155
|
// definition must be in `.h` file (compiler limitation)
|
|
156
156
|
template <typename dtype, typename cv3>
|
|
157
|
-
bool
|
|
157
|
+
bool Mag::decomp
|
|
158
158
|
(
|
|
159
159
|
std::vector<dtype>* pvfGx,
|
|
160
160
|
std::vector<dtype>* pvfGy,
|
|
@@ -410,7 +410,7 @@ bool getG(MrTraj* pmt, vv3* pvv3M0PE, vvv3* pvvv3GRO)
|
|
|
410
410
|
v3 v3M0PE; ret &= pmt->getM0PE(&v3M0PE, _i);
|
|
411
411
|
|
|
412
412
|
// reverse gradient if needed
|
|
413
|
-
if (gMain_enTrajRev) ret &=
|
|
413
|
+
if (gMain_enTrajRev) ret &= Mag::revGrad(&v3M0PE, &vv3GRO, v3M0PE, vv3GRO, dt);
|
|
414
414
|
|
|
415
415
|
pvv3M0PE->at(i) = v3M0PE;
|
|
416
416
|
pvvv3GRO->at(i) = vv3GRO;
|
|
@@ -58,7 +58,7 @@ public:
|
|
|
58
58
|
m_sGradPara(m_sGradPara),
|
|
59
59
|
m_nAcq(m_nAcq),
|
|
60
60
|
m_nSampMax(m_nSampMax)
|
|
61
|
-
{
|
|
61
|
+
{ mag = Mag(); }
|
|
62
62
|
|
|
63
63
|
virtual ~MrTraj()
|
|
64
64
|
{}
|
|
@@ -122,13 +122,13 @@ public:
|
|
|
122
122
|
{ vi64SeqIdx.push_back(i); }
|
|
123
123
|
|
|
124
124
|
// decide step size, make step size and num of idx coprime
|
|
125
|
-
i64
|
|
126
|
-
while (gcd(
|
|
127
|
-
{ ++
|
|
125
|
+
i64 inc = (i64)(num*(GOLDRAT-1));
|
|
126
|
+
while (gcd(inc, num)!=1)
|
|
127
|
+
{ ++inc; }
|
|
128
128
|
|
|
129
129
|
// generate random index
|
|
130
130
|
for(i64 i = 0; i < num; ++i)
|
|
131
|
-
{ pvi64Idx->push_back(i*
|
|
131
|
+
{ pvi64Idx->push_back(i*inc%num); }
|
|
132
132
|
|
|
133
133
|
return true;
|
|
134
134
|
}
|
|
@@ -167,7 +167,7 @@ protected:
|
|
|
167
167
|
i64 m_nSampMax;
|
|
168
168
|
|
|
169
169
|
// solver settings
|
|
170
|
-
|
|
170
|
+
Mag mag;
|
|
171
171
|
|
|
172
172
|
// calculate required num. of rot. to satisfy Nyquist sampling (for spiral only)
|
|
173
173
|
static i64 calNRot(f64 kRhoPhi, i64 nPix)
|
|
@@ -232,8 +232,8 @@ protected:
|
|
|
232
232
|
const f64& gLim = sGradPara.gLim;
|
|
233
233
|
const f64& dt = sGradPara.dt;
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
ret &=
|
|
235
|
+
mag.setup(&tf, sLim, gLim, dt, oversamp, gMrTraj_g0Norm, gMrTraj_g1Norm);
|
|
236
|
+
ret &= mag.solve(pvv3G, pvf64P);
|
|
237
237
|
|
|
238
238
|
return ret;
|
|
239
239
|
}
|
|
@@ -245,8 +245,8 @@ protected:
|
|
|
245
245
|
const f64& gLim = sGradPara.gLim;
|
|
246
246
|
const f64& dt = sGradPara.dt;
|
|
247
247
|
|
|
248
|
-
|
|
249
|
-
ret &=
|
|
248
|
+
mag.setup(vv3TrajSamp, sLim, gLim, dt, oversamp, gMrTraj_g0Norm, gMrTraj_g1Norm);
|
|
249
|
+
ret &= mag.solve(pvv3G, pvf64P);
|
|
250
250
|
|
|
251
251
|
return ret;
|
|
252
252
|
}
|
|
@@ -384,7 +384,7 @@ protected:
|
|
|
384
384
|
{
|
|
385
385
|
// add ramp gradient to satisfy desired Gstart and Gfinal
|
|
386
386
|
vv3 vv3GRampFront;
|
|
387
|
-
ret &=
|
|
387
|
+
ret &= Mag::ramp_front(&vv3GRampFront, pvv3GRO->front(), v3(), sLim, dt);
|
|
388
388
|
pvv3GRO->insert(pvv3GRO->begin(), vv3GRampFront.begin(), vv3GRampFront.end());
|
|
389
389
|
|
|
390
390
|
// corresponding parameter sequence
|
|
@@ -398,7 +398,7 @@ protected:
|
|
|
398
398
|
{
|
|
399
399
|
// add ramp gradient to satisfy desired Gstart and Gfinal
|
|
400
400
|
vv3 vv3GRampBack;
|
|
401
|
-
ret &=
|
|
401
|
+
ret &= Mag::ramp_back(&vv3GRampBack, pvv3GRO->back(), v3(), sLim, dt);
|
|
402
402
|
pvv3GRO->insert(pvv3GRO->end(), vv3GRampBack.begin(), vv3GRampBack.end());
|
|
403
403
|
|
|
404
404
|
// corresponding parameter sequence
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MRArbGrad"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
dependencies = ["numpy"]
|
|
9
9
|
|
|
10
10
|
description = "Gradient waveform design tool for arbitrary k-space trajectories."
|
|
@@ -17,4 +17,4 @@ readme = "README.md"
|
|
|
17
17
|
|
|
18
18
|
[project.urls]
|
|
19
19
|
Repository = "https://github.com/RyanShanghaitech/MRArbGrad"
|
|
20
|
-
Examples = "https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example"
|
|
20
|
+
Examples = "https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|