MRArbGrad 4.4.0__tar.gz → 5.0.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-4.4.0 → mrarbgrad-5.0.0}/LICENSE +1 -1
- mrarbgrad-5.0.0/MANIFEST.in +1 -0
- mrarbgrad-5.0.0/MRArbGrad.egg-info/PKG-INFO +52 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/MRArbGrad.egg-info/SOURCES.txt +12 -16
- mrarbgrad-5.0.0/PKG-INFO +52 -0
- mrarbgrad-5.0.0/README.md +37 -0
- mrarbgrad-5.0.0/mrarbgrad_src/__init__.py +5 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/mag/Mag.cpp +305 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/mag/Mag.h +88 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/main.cpp +372 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/Cones.h +81 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/Rosette.h +129 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/ScanPlan.cpp +143 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/ScanPlan.h +37 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/Spiral.h +141 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/SplineFunc.h +81 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/TrajFunc.h +93 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/Yarnball.h +78 -0
- {mrarbgrad-4.4.0/mrarbgrad_src/ext/traj → mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/future}/MrTraj_2D.h +2 -2
- {mrarbgrad-4.4.0/mrarbgrad_src/ext/traj → mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/future}/Seiffert.h +2 -2
- {mrarbgrad-4.4.0/mrarbgrad_src/ext/traj → mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/future}/Shell3d.h +3 -3
- {mrarbgrad-4.4.0/mrarbgrad_src/ext/traj → mrarbgrad-5.0.0/mrarbgrad_src/ext/traj/future}/Spiral.h +11 -11
- mrarbgrad-5.0.0/mrarbgrad_src/ext/utility/Intp.h +88 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/utility/LinIntp.h +76 -0
- mrarbgrad-5.0.0/mrarbgrad_src/ext/utility/SplineIntp.h +137 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/mrarbgrad_src/ext/utility/global.h +2 -2
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/mrarbgrad_src/ext/utility/v3.cpp +134 -111
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/mrarbgrad_src/ext/utility/v3.h +22 -21
- mrarbgrad-5.0.0/mrarbgrad_src/main.py +119 -0
- mrarbgrad-5.0.0/mrarbgrad_src/trajfunc.py +206 -0
- mrarbgrad-5.0.0/mrarbgrad_src/utility.py +240 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/pyproject.toml +5 -4
- mrarbgrad-5.0.0/setup.py +27 -0
- mrarbgrad-4.4.0/MANIFEST.in +0 -1
- mrarbgrad-4.4.0/MRArbGrad.egg-info/PKG-INFO +0 -48
- mrarbgrad-4.4.0/PKG-INFO +0 -48
- mrarbgrad-4.4.0/README.md +0 -34
- mrarbgrad-4.4.0/example/example_BuiltInTraj.py +0 -105
- mrarbgrad-4.4.0/example/example_ExternalFunction2D.py +0 -80
- mrarbgrad-4.4.0/example/example_ExternalSamples2D.py +0 -84
- mrarbgrad-4.4.0/example/example_ExternalSamples3D.py +0 -72
- mrarbgrad-4.4.0/mrarbgrad_src/Function.py +0 -570
- mrarbgrad-4.4.0/mrarbgrad_src/Utility.py +0 -330
- mrarbgrad-4.4.0/mrarbgrad_src/__init__.py +0 -6
- mrarbgrad-4.4.0/mrarbgrad_src/ext/mag/Mag.cpp +0 -446
- mrarbgrad-4.4.0/mrarbgrad_src/ext/mag/Mag.h +0 -197
- mrarbgrad-4.4.0/mrarbgrad_src/ext/main.cpp +0 -871
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/Cones.h +0 -141
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/MrTraj.h +0 -414
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/Rosette.h +0 -105
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/TrajFunc.h +0 -90
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/VDSpiral.h +0 -113
- mrarbgrad-4.4.0/mrarbgrad_src/ext/traj/Yarnball.h +0 -146
- mrarbgrad-4.4.0/mrarbgrad_src/ext/utility/Intp.h +0 -90
- mrarbgrad-4.4.0/mrarbgrad_src/ext/utility/LinIntp.h +0 -71
- mrarbgrad-4.4.0/mrarbgrad_src/ext/utility/SplineIntp.h +0 -134
- mrarbgrad-4.4.0/mrarbgrad_src/ext/utility/global.cpp +0 -1
- mrarbgrad-4.4.0/mrarbgrad_src/trajfunc/__init__.py +0 -1
- mrarbgrad-4.4.0/mrarbgrad_src/trajfunc/main.py +0 -38
- mrarbgrad-4.4.0/setup.py +0 -62
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/MRArbGrad.egg-info/dependency_links.txt +0 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/MRArbGrad.egg-info/requires.txt +0 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/MRArbGrad.egg-info/top_level.txt +0 -0
- {mrarbgrad-4.4.0 → mrarbgrad-5.0.0}/setup.cfg +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright
|
|
1
|
+
Copyright 2026 Rui Luo
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include mrarbgrad_src/ext/ *.cpp *.h
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MRArbGrad
|
|
3
|
+
Version: 5.0.0
|
|
4
|
+
Summary: Gradient waveform design tool for arbitrary k-space trajectories.
|
|
5
|
+
Author-email: Rui <Rui.1002@proton.me>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/RyanShanghaitech/MRArbGrad
|
|
8
|
+
Project-URL: Examples, https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example
|
|
9
|
+
Keywords: mri,pulse-sequence,gradient-waveform,trajectory,non-Cartesian,real-time
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: numpy
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Magnetic Resonance Arbitrary Gradient Toolbox (MRArbGrad)
|
|
17
|
+
|
|
18
|
+
Python library for solving gradient waveforms for arbitrary MRI trajectories. Trajectories can be specified as a Python function, or as a set of k-space points. A trajectory library is also provided. The underlying C/C++ code can be ported to compatible pulse sequence projects for fast gradient waveform design.
|
|
19
|
+
|
|
20
|
+
## How to use
|
|
21
|
+
### Install
|
|
22
|
+
```bash
|
|
23
|
+
$ pip install mrarbgrad
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Import Libraries
|
|
27
|
+
```python
|
|
28
|
+
from numpy import *
|
|
29
|
+
import mrarbgrad as mag
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Define Your Trajectory Function
|
|
33
|
+
```python
|
|
34
|
+
def Rosette(t):
|
|
35
|
+
rho = 0.5 * sin(5*pi*t)
|
|
36
|
+
phi = 3*pi*t
|
|
37
|
+
return rho*array([cos(phi), sin(phi)])
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Solve for the Gradient Waveform
|
|
41
|
+
```python
|
|
42
|
+
grad = mag.solve(Rosette, pmin=0, pmax=1)
|
|
43
|
+
```
|
|
44
|
+
`pmin` and `pmax` define the bounds of function argument `t`. `grad[:,0]`, `grad[:,1]`, and `grad[:,2]` are the x-, y-, and z-axis gradient waveforms, respectively.
|
|
45
|
+
|
|
46
|
+
*For more usages such as specifying the hardware constraints, use of trajectory library and other utilities, please refer to [Examples](https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example).*
|
|
47
|
+
|
|
48
|
+
## Acknowledgements
|
|
49
|
+
The algorithm in this library is proposed in:
|
|
50
|
+
|
|
51
|
+
[1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026 Oct;73(10):3491-502. doi:10.1109/TBME.2026.3654117
|
|
52
|
+
|
|
@@ -5,39 +5,35 @@ pyproject.toml
|
|
|
5
5
|
setup.py
|
|
6
6
|
./mrarbgrad_src/ext/main.cpp
|
|
7
7
|
./mrarbgrad_src/ext/mag/Mag.cpp
|
|
8
|
-
./mrarbgrad_src/ext/
|
|
8
|
+
./mrarbgrad_src/ext/traj/ScanPlan.cpp
|
|
9
9
|
./mrarbgrad_src/ext/utility/v3.cpp
|
|
10
10
|
MRArbGrad.egg-info/PKG-INFO
|
|
11
11
|
MRArbGrad.egg-info/SOURCES.txt
|
|
12
12
|
MRArbGrad.egg-info/dependency_links.txt
|
|
13
13
|
MRArbGrad.egg-info/requires.txt
|
|
14
14
|
MRArbGrad.egg-info/top_level.txt
|
|
15
|
-
example/example_BuiltInTraj.py
|
|
16
|
-
example/example_ExternalFunction2D.py
|
|
17
|
-
example/example_ExternalSamples2D.py
|
|
18
|
-
example/example_ExternalSamples3D.py
|
|
19
|
-
mrarbgrad_src/Function.py
|
|
20
|
-
mrarbgrad_src/Utility.py
|
|
21
15
|
mrarbgrad_src/__init__.py
|
|
16
|
+
mrarbgrad_src/main.py
|
|
17
|
+
mrarbgrad_src/trajfunc.py
|
|
18
|
+
mrarbgrad_src/utility.py
|
|
22
19
|
mrarbgrad_src/ext/main.cpp
|
|
23
20
|
mrarbgrad_src/ext/mag/Mag.cpp
|
|
24
21
|
mrarbgrad_src/ext/mag/Mag.h
|
|
25
22
|
mrarbgrad_src/ext/traj/Cones.h
|
|
26
|
-
mrarbgrad_src/ext/traj/MrTraj.h
|
|
27
|
-
mrarbgrad_src/ext/traj/MrTraj_2D.h
|
|
28
23
|
mrarbgrad_src/ext/traj/Rosette.h
|
|
29
|
-
mrarbgrad_src/ext/traj/
|
|
30
|
-
mrarbgrad_src/ext/traj/
|
|
24
|
+
mrarbgrad_src/ext/traj/ScanPlan.cpp
|
|
25
|
+
mrarbgrad_src/ext/traj/ScanPlan.h
|
|
31
26
|
mrarbgrad_src/ext/traj/Spiral.h
|
|
27
|
+
mrarbgrad_src/ext/traj/SplineFunc.h
|
|
32
28
|
mrarbgrad_src/ext/traj/TrajFunc.h
|
|
33
|
-
mrarbgrad_src/ext/traj/VDSpiral.h
|
|
34
29
|
mrarbgrad_src/ext/traj/Yarnball.h
|
|
30
|
+
mrarbgrad_src/ext/traj/future/MrTraj_2D.h
|
|
31
|
+
mrarbgrad_src/ext/traj/future/Seiffert.h
|
|
32
|
+
mrarbgrad_src/ext/traj/future/Shell3d.h
|
|
33
|
+
mrarbgrad_src/ext/traj/future/Spiral.h
|
|
35
34
|
mrarbgrad_src/ext/utility/Intp.h
|
|
36
35
|
mrarbgrad_src/ext/utility/LinIntp.h
|
|
37
36
|
mrarbgrad_src/ext/utility/SplineIntp.h
|
|
38
|
-
mrarbgrad_src/ext/utility/global.cpp
|
|
39
37
|
mrarbgrad_src/ext/utility/global.h
|
|
40
38
|
mrarbgrad_src/ext/utility/v3.cpp
|
|
41
|
-
mrarbgrad_src/ext/utility/v3.h
|
|
42
|
-
mrarbgrad_src/trajfunc/__init__.py
|
|
43
|
-
mrarbgrad_src/trajfunc/main.py
|
|
39
|
+
mrarbgrad_src/ext/utility/v3.h
|
mrarbgrad-5.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MRArbGrad
|
|
3
|
+
Version: 5.0.0
|
|
4
|
+
Summary: Gradient waveform design tool for arbitrary k-space trajectories.
|
|
5
|
+
Author-email: Rui <Rui.1002@proton.me>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/RyanShanghaitech/MRArbGrad
|
|
8
|
+
Project-URL: Examples, https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example
|
|
9
|
+
Keywords: mri,pulse-sequence,gradient-waveform,trajectory,non-Cartesian,real-time
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: numpy
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Magnetic Resonance Arbitrary Gradient Toolbox (MRArbGrad)
|
|
17
|
+
|
|
18
|
+
Python library for solving gradient waveforms for arbitrary MRI trajectories. Trajectories can be specified as a Python function, or as a set of k-space points. A trajectory library is also provided. The underlying C/C++ code can be ported to compatible pulse sequence projects for fast gradient waveform design.
|
|
19
|
+
|
|
20
|
+
## How to use
|
|
21
|
+
### Install
|
|
22
|
+
```bash
|
|
23
|
+
$ pip install mrarbgrad
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Import Libraries
|
|
27
|
+
```python
|
|
28
|
+
from numpy import *
|
|
29
|
+
import mrarbgrad as mag
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Define Your Trajectory Function
|
|
33
|
+
```python
|
|
34
|
+
def Rosette(t):
|
|
35
|
+
rho = 0.5 * sin(5*pi*t)
|
|
36
|
+
phi = 3*pi*t
|
|
37
|
+
return rho*array([cos(phi), sin(phi)])
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Solve for the Gradient Waveform
|
|
41
|
+
```python
|
|
42
|
+
grad = mag.solve(Rosette, pmin=0, pmax=1)
|
|
43
|
+
```
|
|
44
|
+
`pmin` and `pmax` define the bounds of function argument `t`. `grad[:,0]`, `grad[:,1]`, and `grad[:,2]` are the x-, y-, and z-axis gradient waveforms, respectively.
|
|
45
|
+
|
|
46
|
+
*For more usages such as specifying the hardware constraints, use of trajectory library and other utilities, please refer to [Examples](https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example).*
|
|
47
|
+
|
|
48
|
+
## Acknowledgements
|
|
49
|
+
The algorithm in this library is proposed in:
|
|
50
|
+
|
|
51
|
+
[1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026 Oct;73(10):3491-502. doi:10.1109/TBME.2026.3654117
|
|
52
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Magnetic Resonance Arbitrary Gradient Toolbox (MRArbGrad)
|
|
2
|
+
|
|
3
|
+
Python library for solving gradient waveforms for arbitrary MRI trajectories. Trajectories can be specified as a Python function, or as a set of k-space points. A trajectory library is also provided. The underlying C/C++ code can be ported to compatible pulse sequence projects for fast gradient waveform design.
|
|
4
|
+
|
|
5
|
+
## How to use
|
|
6
|
+
### Install
|
|
7
|
+
```bash
|
|
8
|
+
$ pip install mrarbgrad
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Import Libraries
|
|
12
|
+
```python
|
|
13
|
+
from numpy import *
|
|
14
|
+
import mrarbgrad as mag
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Define Your Trajectory Function
|
|
18
|
+
```python
|
|
19
|
+
def Rosette(t):
|
|
20
|
+
rho = 0.5 * sin(5*pi*t)
|
|
21
|
+
phi = 3*pi*t
|
|
22
|
+
return rho*array([cos(phi), sin(phi)])
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Solve for the Gradient Waveform
|
|
26
|
+
```python
|
|
27
|
+
grad = mag.solve(Rosette, pmin=0, pmax=1)
|
|
28
|
+
```
|
|
29
|
+
`pmin` and `pmax` define the bounds of function argument `t`. `grad[:,0]`, `grad[:,1]`, and `grad[:,2]` are the x-, y-, and z-axis gradient waveforms, respectively.
|
|
30
|
+
|
|
31
|
+
*For more usages such as specifying the hardware constraints, use of trajectory library and other utilities, please refer to [Examples](https://github.com/RyanShanghaitech/MRArbGrad/tree/main/example).*
|
|
32
|
+
|
|
33
|
+
## Acknowledgements
|
|
34
|
+
The algorithm in this library is proposed in:
|
|
35
|
+
|
|
36
|
+
[1] Luo R, Huang H, Miao Q, Xu J, Hu P, Qi H. Real-Time Gradient Waveform Design for Arbitrary k-Space Trajectories. IEEE Transactions on Biomedical Engineering. 2026 Oct;73(10):3491-502. doi:10.1109/TBME.2026.3654117
|
|
37
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from .main import solve, scan, config, saveF64, loadF64, saveF32, loadF32
|
|
2
|
+
from .utility import getGoldAng, getGoldRat, tm2hzpx, hzpx2tm, getK_Cartesian, getK_Radial, clip, integrate, delay, rotate
|
|
3
|
+
from .trajfunc import VDSpiral, Spiral, DDSpiral, Rosette, Yarnball, Cones
|
|
4
|
+
|
|
5
|
+
config() # use default settings
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
#include <cassert>
|
|
2
|
+
#include <algorithm>
|
|
3
|
+
#include <cstdio>
|
|
4
|
+
#include "../utility/global.h"
|
|
5
|
+
#include "Mag.h"
|
|
6
|
+
|
|
7
|
+
f64 Mag::dt = 10e-6; i64 Mag::ovsp = 4; // raster time, oversamp ratio
|
|
8
|
+
f64 Mag::sLim = 50 * 42.5756e6 * 1e-3; // slew. limit (Hz/px/s)
|
|
9
|
+
f64 Mag::gLim = 30e-3 * 42.5756e6 * 1e-3; // grad. limit (Hz/px)
|
|
10
|
+
f64 Mag::g0Norm = 0.0, Mag::g1Norm = 0.0; // start and stop grad. amp.
|
|
11
|
+
bool Mag::enTrajRep = true; // trajectory reparameterization
|
|
12
|
+
bool Mag::enGradRep = true; // gradient reparameterization
|
|
13
|
+
i64 Mag::lenTrajRsv = int(1e4), Mag::lenGradRsv = int(1e5);
|
|
14
|
+
|
|
15
|
+
Mag::Mag()
|
|
16
|
+
{
|
|
17
|
+
// for solver
|
|
18
|
+
this->paraBwd.reserve(Mag::lenGradRsv);
|
|
19
|
+
this->gradBwd.reserve(Mag::lenGradRsv);
|
|
20
|
+
this->gradBwdNorm.reserve(Mag::lenGradRsv);
|
|
21
|
+
|
|
22
|
+
this->paraFwd.reserve(Mag::lenGradRsv);
|
|
23
|
+
this->gradFwd.reserve(Mag::lenGradRsv);
|
|
24
|
+
|
|
25
|
+
this->para.reserve(Mag::lenGradRsv/Mag::ovsp);
|
|
26
|
+
this->grad.reserve(Mag::lenGradRsv/Mag::ovsp);
|
|
27
|
+
|
|
28
|
+
this->intp.init(Mag::lenGradRsv);
|
|
29
|
+
this->intp.eSearchMode = Intp::ECached;
|
|
30
|
+
|
|
31
|
+
// for trajectory reparameterization
|
|
32
|
+
this->trajSamp.resize(Mag::lenTrajRsv);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
bool Mag::setTraj(const TrajFunc& func)
|
|
36
|
+
{
|
|
37
|
+
bool ret = true;
|
|
38
|
+
if (Mag::enTrajRep)
|
|
39
|
+
{
|
|
40
|
+
f64 p0 = func.getP0();
|
|
41
|
+
f64 p1 = func.getP1();
|
|
42
|
+
i64 n = this->trajSamp.size();
|
|
43
|
+
for (i64 i = 0; i < n; ++i)
|
|
44
|
+
{
|
|
45
|
+
f64 p = p0 + (p1-p0) * (i)/f64(n-1);
|
|
46
|
+
ret &= func.getK(&this->trajSamp[i], p);
|
|
47
|
+
}
|
|
48
|
+
this->spTrajFunc = SplineFunc(this->trajSamp);
|
|
49
|
+
this->trajFuncPtr = &this->spTrajFunc;
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
{
|
|
53
|
+
this->trajFuncPtr = &func;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return ret;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
bool Mag::setTraj(const vv3& samp)
|
|
60
|
+
{
|
|
61
|
+
this->spTrajFunc = SplineFunc(samp);
|
|
62
|
+
this->trajFuncPtr = &this->spTrajFunc;
|
|
63
|
+
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
bool Mag::sovQDE(f64* x0, f64* x1, f64 a, f64 b, f64 c)
|
|
68
|
+
{
|
|
69
|
+
f64 delta = b*b - 4e0*a*c;
|
|
70
|
+
if (x0) *x0 = (-b-(delta<0?0:std::sqrt(delta)))/(2*a);
|
|
71
|
+
if (x1) *x1 = (-b+(delta<0?0:std::sqrt(delta)))/(2*a);
|
|
72
|
+
return delta>=0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
f64 Mag::curvature(f64 p)
|
|
76
|
+
{
|
|
77
|
+
#define EPS (1e-15)
|
|
78
|
+
v3 dkdp; this->trajFuncPtr->getDkDp(&dkdp, p);
|
|
79
|
+
v3 d2kdp2; this->trajFuncPtr->getD2kDp2(&d2kdp2, p);
|
|
80
|
+
f64 nume = v3::norm(v3::cross(dkdp, d2kdp2));
|
|
81
|
+
f64 deno = pow(v3::norm(dkdp), 3e0);
|
|
82
|
+
if (nume<EPS) nume = EPS;
|
|
83
|
+
if (deno<EPS) deno = EPS;
|
|
84
|
+
return nume/deno;
|
|
85
|
+
#undef EPS
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#if 1
|
|
89
|
+
|
|
90
|
+
f64 Mag::getDp(const v3& gPrev, const v3& gThis, f64 dt, f64 pPrev, f64 pThis, f64 signDp)
|
|
91
|
+
{
|
|
92
|
+
// solve `ΔP` by RK2
|
|
93
|
+
f64 l = v3::norm(gThis)*dt;
|
|
94
|
+
// k1
|
|
95
|
+
f64 k1;
|
|
96
|
+
{
|
|
97
|
+
v3 dkdp; this->trajFuncPtr->getDkDp(&dkdp, pThis);
|
|
98
|
+
f64 dldp = v3::norm(dkdp)*signDp;
|
|
99
|
+
k1 = 1e0/dldp;
|
|
100
|
+
}
|
|
101
|
+
// k2
|
|
102
|
+
f64 k2;
|
|
103
|
+
{
|
|
104
|
+
v3 dkdp; this->trajFuncPtr->getDkDp(&dkdp, pThis+k1*l);
|
|
105
|
+
f64 dldp = v3::norm(dkdp)*signDp;
|
|
106
|
+
k2 = 1e0/dldp;
|
|
107
|
+
}
|
|
108
|
+
f64 dp = l*(0.5*k1 + 0.5*k2);
|
|
109
|
+
return dp;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#else // less accurate due to estimation of PNext
|
|
113
|
+
|
|
114
|
+
f64 Mag::getDp(const v3& v3GPrev, const v3& v3GThis, f64 dt, f64 pPrev, f64 pThis, f64 signDp)
|
|
115
|
+
{
|
|
116
|
+
// solve `ΔP` by RK2
|
|
117
|
+
f64 l = v3::norm(v3GThis)*dt;
|
|
118
|
+
v3 dkdp0; ptfTraj->getDkDp(&dkdp0, pThis);
|
|
119
|
+
v3 dkdp1; ptfTraj->getDkDp(&dkdp1, pThis*2e0-pPrev);
|
|
120
|
+
f64 dldp0 = v3::norm(dkdp0)*signDp;
|
|
121
|
+
f64 dldp1 = v3::norm(dkdp1)*signDp;
|
|
122
|
+
return l*(1e0/dldp0 + 1e0/dldp1)/2e0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
#endif
|
|
126
|
+
|
|
127
|
+
bool Mag::step(v3* gUnit, f64* gNormMin, f64* gNormMax, f64 p, f64 signDp, const v3& g, f64 sLim, f64 dt)
|
|
128
|
+
{
|
|
129
|
+
// current gradient direction
|
|
130
|
+
v3 dkdp; this->trajFuncPtr->getDkDp(&dkdp, p);
|
|
131
|
+
f64 dldp = v3::norm(dkdp)*signDp;
|
|
132
|
+
if (gUnit) *gUnit = dkdp/dldp;
|
|
133
|
+
|
|
134
|
+
// current gradient magnitude
|
|
135
|
+
bool isQDESucc = sovQDE
|
|
136
|
+
(
|
|
137
|
+
gNormMin, gNormMax,
|
|
138
|
+
1e0,
|
|
139
|
+
-2e0*v3::inner(g, *gUnit),
|
|
140
|
+
v3::inner(g, g) - std::pow(sLim*dt, 2e0)
|
|
141
|
+
);
|
|
142
|
+
if (gNormMin) *gNormMin = fabs(*gNormMin);
|
|
143
|
+
if (gNormMax) *gNormMax = fabs(*gNormMax);
|
|
144
|
+
|
|
145
|
+
return isQDESucc;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
bool Mag::solve(vv3* grad, vf64* para)
|
|
149
|
+
{
|
|
150
|
+
bool ret = true;
|
|
151
|
+
f64 p0 = this->trajFuncPtr->getP0();
|
|
152
|
+
f64 p1 = this->trajFuncPtr->getP1();
|
|
153
|
+
f64 tStep = Mag::dt / Mag::ovsp;
|
|
154
|
+
bool isQDESucc = true; (void)isQDESucc;
|
|
155
|
+
|
|
156
|
+
// backward
|
|
157
|
+
v3 g1Unit; ret &= this->trajFuncPtr->getDkDp(&g1Unit, p1);
|
|
158
|
+
g1Unit = g1Unit * (p0>p1?1e0:-1e0);
|
|
159
|
+
g1Unit = g1Unit / v3::norm(g1Unit);
|
|
160
|
+
f64 g1Norm = Mag::g1Norm;
|
|
161
|
+
g1Norm = std::min(g1Norm, Mag::gLim);
|
|
162
|
+
g1Norm = std::min(g1Norm, std::sqrt(Mag::sLim/curvature(p1)));
|
|
163
|
+
v3 g1 = g1Unit * g1Norm;
|
|
164
|
+
|
|
165
|
+
this->paraBwd.clear(); this->paraBwd.push_back(p1);
|
|
166
|
+
this->gradBwd.clear(); this->gradBwd.push_back(g1);
|
|
167
|
+
this->gradBwdNorm.clear(); this->gradBwdNorm.push_back(v3::norm(g1));
|
|
168
|
+
while (1)
|
|
169
|
+
{
|
|
170
|
+
f64 p = this->paraBwd.back();
|
|
171
|
+
v3 g = this->gradBwd.back();
|
|
172
|
+
|
|
173
|
+
// update grad
|
|
174
|
+
v3 gUnit; f64 gNorm;
|
|
175
|
+
isQDESucc = step(&gUnit, NULL, &gNorm, p, (p0-p1)/fabs(p0-p1), g, Mag::sLim, tStep);
|
|
176
|
+
gNorm = std::min(gNorm, Mag::gLim);
|
|
177
|
+
gNorm = std::min(gNorm, std::sqrt(Mag::sLim/curvature(p)));
|
|
178
|
+
g = gUnit*gNorm;
|
|
179
|
+
|
|
180
|
+
// update para
|
|
181
|
+
p += getDp(this->gradBwd.back(), g, tStep, this->paraBwd.back(), p, (p0-p1)/fabs(p0-p1));
|
|
182
|
+
|
|
183
|
+
// stop or append
|
|
184
|
+
if (fabs(p - p1) >= (1-1e-6)*fabs(p0 - p1))
|
|
185
|
+
{
|
|
186
|
+
// printf("bac: dP/dP1 = %lf/%lf\n", dP, dP1); // test
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
else
|
|
190
|
+
{
|
|
191
|
+
// printf("bac: dP = %lf\n", dP); // test
|
|
192
|
+
this->paraBwd.push_back(p);
|
|
193
|
+
this->gradBwd.push_back(g);
|
|
194
|
+
this->gradBwdNorm.push_back(v3::norm(g));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
std::reverse(this->paraBwd.begin(), this->paraBwd.end());
|
|
199
|
+
std::reverse(this->gradBwdNorm.begin(), this->gradBwdNorm.end());
|
|
200
|
+
|
|
201
|
+
this->intp.fit(this->paraBwd, this->gradBwdNorm);
|
|
202
|
+
|
|
203
|
+
// forward
|
|
204
|
+
v3 g0Unit; ret &= this->trajFuncPtr->getDkDp(&g0Unit, p0);
|
|
205
|
+
g0Unit = g0Unit * (p1>p0?1e0:-1e0);
|
|
206
|
+
g0Unit = g0Unit / v3::norm(g0Unit);
|
|
207
|
+
f64 g0Norm = Mag::g0Norm;
|
|
208
|
+
g0Norm = std::min(g0Norm, Mag::gLim);
|
|
209
|
+
g0Norm = std::min(g0Norm, std::sqrt(Mag::sLim/curvature(p0)));
|
|
210
|
+
g0Norm = std::min(g0Norm, this->intp.eval(p0));
|
|
211
|
+
v3 g0 = g0Unit * g0Norm;
|
|
212
|
+
|
|
213
|
+
this->paraFwd.clear(); this->paraFwd.push_back(p0);
|
|
214
|
+
this->gradFwd.clear(); this->gradFwd.push_back(g0);
|
|
215
|
+
while (1)
|
|
216
|
+
{
|
|
217
|
+
f64 p = this->paraFwd.back();
|
|
218
|
+
v3 g = this->gradFwd.back();
|
|
219
|
+
|
|
220
|
+
// update grad
|
|
221
|
+
v3 gUnit; f64 gNorm;
|
|
222
|
+
isQDESucc = step(&gUnit, NULL, &gNorm, p, (p1-p0)/fabs(p1-p0), g, Mag::sLim, tStep);
|
|
223
|
+
|
|
224
|
+
f64 gNormBwd = this->intp.eval(p);
|
|
225
|
+
gNorm = std::min(gNorm, gNormBwd);
|
|
226
|
+
g = gUnit*gNorm;
|
|
227
|
+
|
|
228
|
+
// update para
|
|
229
|
+
p += getDp(this->gradFwd.back(), g, tStep, this->paraFwd.back(), p, (p1-p0)/fabs(p1-p0));
|
|
230
|
+
|
|
231
|
+
// stop or append
|
|
232
|
+
if (fabs(p - p0) >= (1-1e-6)*fabs(p1 - p0)) // || dGNorm <= 0)
|
|
233
|
+
{
|
|
234
|
+
// printf("for: dP/dP1 = %lf/%lf\n", dP, dP1); // test
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
else
|
|
238
|
+
{
|
|
239
|
+
// printf("for: dP = %lf\n", dP); // test
|
|
240
|
+
this->paraFwd.push_back(p);
|
|
241
|
+
this->gradFwd.push_back(g);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// deoversamp the para. vec.
|
|
246
|
+
if (!para) para = &this->para;
|
|
247
|
+
if (!grad) grad = &this->grad;
|
|
248
|
+
{
|
|
249
|
+
i64 n = this->paraFwd.size();
|
|
250
|
+
para->clear(); para->reserve(n/Mag::ovsp+1);
|
|
251
|
+
grad->clear(); grad->reserve(n/Mag::ovsp+1);
|
|
252
|
+
for (i64 i = 0; i < n; ++i)
|
|
253
|
+
{
|
|
254
|
+
if (i%Mag::ovsp==Mag::ovsp/2)
|
|
255
|
+
{
|
|
256
|
+
para->push_back(this->paraFwd[i]);
|
|
257
|
+
grad->push_back(this->gradFwd[i]);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// derive gradient
|
|
263
|
+
if (Mag::enGradRep)
|
|
264
|
+
{
|
|
265
|
+
v3 k1, k0;
|
|
266
|
+
vf64::iterator ivf64P = std::next(para->begin());
|
|
267
|
+
vf64::iterator ivf64PPrev = para->begin();
|
|
268
|
+
i64 n = para->size();
|
|
269
|
+
grad->clear();
|
|
270
|
+
for (i64 i = 1; i < n; ++i)
|
|
271
|
+
{
|
|
272
|
+
ret &= this->trajFuncPtr->getK(&k1, *ivf64P);
|
|
273
|
+
ret &= this->trajFuncPtr->getK(&k0, *ivf64PPrev);
|
|
274
|
+
grad->push_back((k1 - k0)/Mag::dt);
|
|
275
|
+
*ivf64PPrev = *ivf64P; // ensure the consistent length
|
|
276
|
+
++ivf64P, ++ivf64PPrev;
|
|
277
|
+
}
|
|
278
|
+
para->resize(n-1);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// extrapolate
|
|
282
|
+
i64 nExtp; vv3 piece;
|
|
283
|
+
|
|
284
|
+
nExtp = (i64)std::ceil(v3::norm(grad->front() - g0) / (Mag::sLim*Mag::dt));
|
|
285
|
+
piece = v3::linspace(g0, grad->front(), nExtp, false);
|
|
286
|
+
grad->insert(grad->begin(), piece.begin(), piece.end());
|
|
287
|
+
para->insert(para->begin(), nExtp, para->front());
|
|
288
|
+
|
|
289
|
+
nExtp = (i64)std::ceil(v3::norm(grad->back() - g1) / (Mag::sLim*Mag::dt));
|
|
290
|
+
piece = v3::linspace(g1, grad->back(), nExtp, false);
|
|
291
|
+
grad->insert(grad->end(), piece.rbegin(), piece.rend());
|
|
292
|
+
para->insert(para->end(), nExtp, para->back());
|
|
293
|
+
|
|
294
|
+
return ret;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
v3 Mag::calM0(const vv3& grad, f64 dt)
|
|
298
|
+
{
|
|
299
|
+
v3 m0 = v3(0,0,0);
|
|
300
|
+
for (int64_t i = 1; i < (i64)grad.size(); ++i)
|
|
301
|
+
{ m0 += (grad[i] + grad[i-1]) * dt/2e0; }
|
|
302
|
+
|
|
303
|
+
return m0;
|
|
304
|
+
}
|
|
305
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <list>
|
|
5
|
+
#include <tuple>
|
|
6
|
+
#include <cmath>
|
|
7
|
+
#include <stdexcept>
|
|
8
|
+
#include <algorithm>
|
|
9
|
+
#include "../utility/global.h"
|
|
10
|
+
#include "../utility/v3.h"
|
|
11
|
+
#include "../traj/TrajFunc.h"
|
|
12
|
+
#include "../traj/SplineFunc.h"
|
|
13
|
+
#include "../utility/LinIntp.h"
|
|
14
|
+
|
|
15
|
+
class Mag
|
|
16
|
+
{
|
|
17
|
+
public:
|
|
18
|
+
static f64 dt; static i64 ovsp;
|
|
19
|
+
static f64 sLim, gLim, g0Norm, g1Norm;
|
|
20
|
+
static bool enTrajRep, enGradRep;
|
|
21
|
+
static i64 lenTrajRsv, lenGradRsv;
|
|
22
|
+
|
|
23
|
+
Mag();
|
|
24
|
+
bool setTraj(const TrajFunc& func);
|
|
25
|
+
bool setTraj(const vv3& samp);
|
|
26
|
+
bool solve(vv3* grad, vf64* para=NULL);
|
|
27
|
+
template <typename dtype, typename xv3>
|
|
28
|
+
static bool decomp
|
|
29
|
+
(
|
|
30
|
+
std::vector<dtype>* gx,
|
|
31
|
+
std::vector<dtype>* gy,
|
|
32
|
+
std::vector<dtype>* gz,
|
|
33
|
+
const xv3& grad
|
|
34
|
+
);
|
|
35
|
+
static v3 calM0(const vv3& grad, f64 dt);
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
// reserved vector for faster computation
|
|
39
|
+
SplineFunc spTrajFunc;
|
|
40
|
+
const TrajFunc* trajFuncPtr;
|
|
41
|
+
vv3 trajSamp;
|
|
42
|
+
|
|
43
|
+
vf64 paraBwd;
|
|
44
|
+
vv3 gradBwd;
|
|
45
|
+
vf64 gradBwdNorm;
|
|
46
|
+
vf64 paraFwd;
|
|
47
|
+
vv3 gradFwd;
|
|
48
|
+
vf64 para;
|
|
49
|
+
vv3 grad;
|
|
50
|
+
|
|
51
|
+
LinIntp intp;
|
|
52
|
+
|
|
53
|
+
f64 curvature(f64 p);
|
|
54
|
+
f64 getDp(const v3& gPrev, const v3& gThis, f64 dt, f64 pPrev, f64 pThis, f64 signDp);
|
|
55
|
+
bool step(v3* gUnit, f64* gNormMin, f64* gNormMax, f64 p, f64 signDp, const v3& g, f64 sLim, f64 dt);
|
|
56
|
+
static bool sovQDE(f64* x0, f64* x1, f64 a, f64 b, f64 c);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// definition must be in `.h` file (compiler limitation)
|
|
60
|
+
template <typename dtype, typename xv3>
|
|
61
|
+
bool Mag::decomp
|
|
62
|
+
(
|
|
63
|
+
std::vector<dtype>* pGx,
|
|
64
|
+
std::vector<dtype>* pGy,
|
|
65
|
+
std::vector<dtype>* pGz,
|
|
66
|
+
const xv3& grad
|
|
67
|
+
)
|
|
68
|
+
{
|
|
69
|
+
bool ret = true;
|
|
70
|
+
|
|
71
|
+
std::fill(pGx->begin(), pGx->end(), (dtype)0);
|
|
72
|
+
std::fill(pGy->begin(), pGy->end(), (dtype)0);
|
|
73
|
+
std::fill(pGz->begin(), pGz->end(), (dtype)0);
|
|
74
|
+
|
|
75
|
+
typename std::vector<dtype>::iterator iGx = pGx->begin();
|
|
76
|
+
typename std::vector<dtype>::iterator iGy = pGy->begin();
|
|
77
|
+
typename std::vector<dtype>::iterator iGz = pGz->begin();
|
|
78
|
+
typename xv3::const_iterator iGrad = grad.begin();
|
|
79
|
+
while (iGrad != grad.end())
|
|
80
|
+
{
|
|
81
|
+
*(iGx++) = dtype(iGrad->x);
|
|
82
|
+
*(iGy++) = dtype(iGrad->y);
|
|
83
|
+
*(iGz++) = dtype(iGrad->z);
|
|
84
|
+
++iGrad;
|
|
85
|
+
}
|
|
86
|
+
return ret;
|
|
87
|
+
}
|
|
88
|
+
|