commit
e94ea7c70c
|
@ -85,4 +85,4 @@ make -j2 install
|
||||||
cd $GITHUB_WORKSPACE/build/python
|
cd $GITHUB_WORKSPACE/build/python
|
||||||
$PYTHON setup.py install --user --prefix=
|
$PYTHON setup.py install --user --prefix=
|
||||||
cd $GITHUB_WORKSPACE/python/gtsam/tests
|
cd $GITHUB_WORKSPACE/python/gtsam/tests
|
||||||
$PYTHON -m unittest discover
|
$PYTHON -m unittest discover -v
|
||||||
|
|
|
@ -40,9 +40,13 @@ class GTSAM_EXPORT FourierBasis : public Basis<FourierBasis> {
|
||||||
static Weights CalculateWeights(size_t N, double x) {
|
static Weights CalculateWeights(size_t N, double x) {
|
||||||
Weights b(N);
|
Weights b(N);
|
||||||
b[0] = 1;
|
b[0] = 1;
|
||||||
for (size_t i = 1, n = 1; i < N; i += 2, n++) {
|
for (size_t i = 1, n = 1; i < N; i++) {
|
||||||
b[i] = cos(n * x);
|
if (i % 2 == 1) {
|
||||||
b[i + 1] = sin(n * x);
|
b[i] = cos(n * x);
|
||||||
|
} else {
|
||||||
|
b[i] = sin(n * x);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,5 +166,6 @@ add_custom_target(
|
||||||
COMMAND
|
COMMAND
|
||||||
${CMAKE_COMMAND} -E env # add package to python path so no need to install
|
${CMAKE_COMMAND} -E env # add package to python path so no need to install
|
||||||
"PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}"
|
"PYTHONPATH=${GTSAM_PYTHON_BUILD_DIRECTORY}/$ENV{PYTHONPATH}"
|
||||||
${PYTHON_EXECUTABLE} -m unittest discover -s "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/tests"
|
${PYTHON_EXECUTABLE} -m unittest discover -v -s .
|
||||||
DEPENDS ${GTSAM_PYTHON_DEPENDENCIES})
|
DEPENDS ${GTSAM_PYTHON_DEPENDENCIES}
|
||||||
|
WORKING_DIRECTORY "${GTSAM_PYTHON_BUILD_DIRECTORY}/gtsam/tests")
|
||||||
|
|
|
@ -10,3 +10,5 @@
|
||||||
* Without this they will be automatically converted to a Python object, and all
|
* Without this they will be automatically converted to a Python object, and all
|
||||||
* mutations on Python side will not be reflected on C++.
|
* mutations on Python side will not be reflected on C++.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
"""
|
||||||
|
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||||
|
Atlanta, Georgia 30332-0415
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
See LICENSE for the license information
|
||||||
|
|
||||||
|
Basis unit tests.
|
||||||
|
Author: Frank Dellaert & Gerry Chen (Python)
|
||||||
|
"""
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import gtsam
|
||||||
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
from gtsam.symbol_shorthand import B
|
||||||
|
|
||||||
|
|
||||||
|
class TestBasis(GtsamTestCase):
|
||||||
|
"""
|
||||||
|
Tests FitBasis python binding for FourierBasis, Chebyshev1Basis, Chebyshev2Basis, and Chebyshev2.
|
||||||
|
|
||||||
|
It tests FitBasis by fitting to a ground-truth function that can be represented exactly in
|
||||||
|
the basis, then checking that the regression (fit result) matches the function. For the
|
||||||
|
Chebyshev bases, the line y=x is used to generate the data while for Fourier, 0.7*cos(x) is
|
||||||
|
used.
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
self.N = 2
|
||||||
|
self.x = [0., 0.5, 0.75]
|
||||||
|
self.interpx = np.linspace(0., 1., 10)
|
||||||
|
self.noise = gtsam.noiseModel.Unit.Create(1)
|
||||||
|
|
||||||
|
def evaluate(self, basis, fitparams, x):
|
||||||
|
"""
|
||||||
|
Until wrapper for Basis functors are ready,
|
||||||
|
this is how to evaluate a basis function.
|
||||||
|
"""
|
||||||
|
return basis.WeightMatrix(self.N, x) @ fitparams
|
||||||
|
|
||||||
|
def fit_basis_helper(self, fitter, basis, f=lambda x: x):
|
||||||
|
"""Helper method to fit data to a specified fitter using a specified basis."""
|
||||||
|
data = {x: f(x) for x in self.x}
|
||||||
|
fit = fitter(data, self.noise, self.N)
|
||||||
|
coeff = fit.parameters()
|
||||||
|
interpy = self.evaluate(basis, coeff, self.interpx)
|
||||||
|
return interpy
|
||||||
|
|
||||||
|
def test_fit_basis_fourier(self):
|
||||||
|
"""Fit a Fourier basis."""
|
||||||
|
|
||||||
|
f = lambda x: 0.7 * np.cos(x)
|
||||||
|
interpy = self.fit_basis_helper(gtsam.FitBasisFourierBasis,
|
||||||
|
gtsam.FourierBasis, f)
|
||||||
|
# test a basis by checking that the fit result matches the function at x-values interpx.
|
||||||
|
np.testing.assert_almost_equal(interpy,
|
||||||
|
np.array([f(x) for x in self.interpx]),
|
||||||
|
decimal=7)
|
||||||
|
|
||||||
|
def test_fit_basis_chebyshev1basis(self):
|
||||||
|
"""Fit a Chebyshev1 basis."""
|
||||||
|
|
||||||
|
f = lambda x: x
|
||||||
|
interpy = self.fit_basis_helper(gtsam.FitBasisChebyshev1Basis,
|
||||||
|
gtsam.Chebyshev1Basis, f)
|
||||||
|
# test a basis by checking that the fit result matches the function at x-values interpx.
|
||||||
|
np.testing.assert_almost_equal(interpy,
|
||||||
|
np.array([f(x) for x in self.interpx]),
|
||||||
|
decimal=7)
|
||||||
|
|
||||||
|
def test_fit_basis_chebyshev2basis(self):
|
||||||
|
"""Fit a Chebyshev2 basis."""
|
||||||
|
|
||||||
|
f = lambda x: x
|
||||||
|
interpy = self.fit_basis_helper(gtsam.FitBasisChebyshev2Basis,
|
||||||
|
gtsam.Chebyshev2Basis)
|
||||||
|
# test a basis by checking that the fit result matches the function at x-values interpx.
|
||||||
|
np.testing.assert_almost_equal(interpy,
|
||||||
|
np.array([f(x) for x in self.interpx]),
|
||||||
|
decimal=7)
|
||||||
|
|
||||||
|
def test_fit_basis_chebyshev2(self):
|
||||||
|
"""Fit a Chebyshev2 pseudospectral basis."""
|
||||||
|
|
||||||
|
f = lambda x: x
|
||||||
|
interpy = self.fit_basis_helper(gtsam.FitBasisChebyshev2,
|
||||||
|
gtsam.Chebyshev2)
|
||||||
|
# test a basis by checking that the fit result matches the function at x-values interpx.
|
||||||
|
np.testing.assert_almost_equal(interpy,
|
||||||
|
np.array([f(x) for x in self.interpx]),
|
||||||
|
decimal=7)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue