...
 
Commits (29)
os:
- Visual Studio 2015
- Visual Studio 2017
build:
verbosity: detailed
environment:
matrix:
- builder: cmake
- builder: scons
init:
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
install:
- SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- python --version
......@@ -12,10 +20,16 @@ install:
- pip install -U wheel
- pip install scons==2.4.1
- cinst nsis.portable
- hg clone https://bitbucket.org/eigen/eigen external\eigen3
- cd external\eigen3
- mkdir build & cd build
- cmake .. -DCMAKE_INSTALL_PREFIX="..\..\build" -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles"
- nmake install
- cd ..\..\..\
before_build:
# BOOST Python require x86 compilation
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
#- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
#- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
# Build script
......@@ -30,8 +44,10 @@ build_script:
#- dir C:\Python27\libs
#- dir C:\Libraries\boost_1_63_0
#- dir C:\Libraries\boost_1_63_0\lib64-msvc-14.0
- scons --cfg=./configs/scons/config-windows-appveyor.py
- appveyor PushArtifact config.log
- if "%builder%" == "scons" (
scons --cfg=./configs/scons/config-windows-appveyor.py &
appveyor PushArtifact config.log
)
# Install CERES
- cd external
......@@ -44,9 +60,16 @@ build_script:
- cd ..\..\..
# Rebuild with CERES and Python
- scons --cfg=./configs/scons/config-windows-appveyor.py
#- scons --cfg=./configs/scons/config-windows-appveyor.py python
- appveyor PushArtifact config.log
- if "%builder%" == "scons" (
scons --cfg=./configs/scons/config-windows-appveyor.py &
appveyor PushArtifact config.log
) else (
mkdir build &
cd build &
cmake .. -DEIGEN3_INCLUDE_DIR="external/build/include/eigen3" -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles" &
nmake &
cd ..
)
# Generate product
- makensis sources\scripts\installer.nsi
......@@ -57,11 +80,26 @@ build_script:
#
test_script:
- ./setpath.bat
- scons --cfg=./configs/scons/config-windows-appveyor.py tests
#- scons --cfg=./configs/scons/config-windows-appveyor.py python tests
- if "%builder%" == "scons" (
scons --cfg=./configs/scons/config-windows-appveyor.py tests
appveoyr PushArtifact build\sources\tests\*.log
) else
cd build &
nmake test &
appveyor PushArtifact Testing\Temporary\LastTest.log &
cd ..
)
# Outputed files
#
artifacts:
- path: sources\scripts\ALTA.exe
name: ALTA
- path: config.log
name: Log
name: SconsLog
- path: 'build\sources\tests\*.log'
name: SConsTestsLog
type: zip
- path: build\Testing\Temporary\LastTest.log
name: CMakeTestsLog
......@@ -4,3 +4,6 @@
[submodule "external/Catch"]
path = external/Catch
url = https://github.com/philsquared/Catch.git
[submodule "external/pybind11"]
path = external/pybind11
url = https://github.com/pybind/pybind11.git
language: cpp
matrix:
include:
- os: linux
dist: trusty
sudo: required
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- cmake
- libboost-python-dev
- os: osx
before_install:
- brew update
- brew install scons
env:
- builder=scons
- builder=cmake
os:
- linux
- osx
dist: trusty
sudo: required
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
- cmake
- libboost-python-dev
- libeigen3-dev
before_install:
- OMP_NUM_THREADS=2
- eval "${MATRIX_EVAL}"
#- sudo apt-get update -qq -y
#- sudo apt-get install -qq -y libopenexr-dev cmake libboost-python-dev libnlopt-dev coinor-libipopt-dev liblapack-dev libblas-dev libgfortran-4.8-dev
- echo "${builder}"
- if [ ${TRAVIS_OS_NAME} = 'osx' ]; then
brew update;
brew install scons eigen;
fi
script:
- git submodule init
- git submodule update
- scons
- scons tests
#- scons tests python -i
- if [ ${builder} = 'scons' ]; then
scons;
scons tests;
else
mkdir build;
cd build;
cmake ..;
make -i;
make test;
fi
after_failure:
- cat config.log
- if [ ${builder} = 'scons' ]; then
cat config.log;
else
cat Testing/Temporary/LastTest.log
fi
This diff is collapsed.
This diff is collapsed.
# Ceres Solver - A fast non-linear least squares minimizer
# Copyright 2015 Google Inc. All rights reserved.
# http://ceres-solver.org/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Author: pablo.speciale@gmail.com (Pablo Speciale)
#
# FIND_PACKAGE() searches for a <package>Config.cmake file and an associated
# <package>Version.cmake file, which it loads to check the version number.
#
# This file can be used with CONFIGURE_FILE() to generate such a file for a
# project with very basic logic.
#
# It sets PACKAGE_VERSION_EXACT if the current version string and the requested
# version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE
# if the current version is >= requested version.
set(PACKAGE_VERSION 1.14.0)
if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif ("${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
endif ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
# - Try to find Eigen3 lib
#
# This module supports requiring a minimum version, e.g. you can do
# find_package(Eigen3 3.1.2)
# to require version 3.1.2 or newer of Eigen3.
#
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib with correct version
# EIGEN3_INCLUDE_DIR - the eigen include directory
# EIGEN3_VERSION - eigen version
#
# This module reads hints about search locations from
# the following enviroment variables:
#
# EIGEN3_ROOT
# EIGEN3_ROOT_DIR
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@free.fr>
# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 2)
endif(NOT Eigen3_FIND_VERSION_MAJOR)
if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 91)
endif(NOT Eigen3_FIND_VERSION_MINOR)
if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0)
endif(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
endif(NOT Eigen3_FIND_VERSION)
macro(_eigen3_check_version)
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK FALSE)
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK TRUE)
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
if(NOT EIGEN3_VERSION_OK)
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
"but at least version ${Eigen3_FIND_VERSION} is required")
endif(NOT EIGEN3_VERSION_OK)
endmacro(_eigen3_check_version)
if (EIGEN3_INCLUDE_DIR)
# in cache already
_eigen3_check_version()
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
else (EIGEN3_INCLUDE_DIR)
# search first if an Eigen3Config.cmake is available in the system,
# if successful this would set EIGEN3_INCLUDE_DIR and the rest of
# the script will work as usual
find_package(Eigen3 ${Eigen3_FIND_VERSION} NO_MODULE QUIET)
if(NOT EIGEN3_INCLUDE_DIR)
find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
HINTS
ENV EIGEN3_ROOT
ENV EIGEN3_ROOT_DIR
PATHS
${CMAKE_INSTALL_PREFIX}/include
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen3 eigen
)
endif(NOT EIGEN3_INCLUDE_DIR)
if(EIGEN3_INCLUDE_DIR)
_eigen3_check_version()
endif(EIGEN3_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
mark_as_advanced(EIGEN3_INCLUDE_DIR)
endif(EIGEN3_INCLUDE_DIR)
# Copyright (c) 2011-2018, The DART development contributors
# All rights reserved.
#
# The list of contributors can be found at:
# https://github.com/dartsim/dart/blob/master/LICENSE
#
# This file is provided under the "BSD-style" License
# Find NLOPT
#
# This sets the following variables:
# NLOPT_FOUND
# NLOPT_INCLUDE_DIRS
# NLOPT_LIBRARIES
# NLOPT_DEFINITIONS
# NLOPT_VERSION
# 2018 : SMALL MODIFICATIONS FROM R.P. romain dot pacanowski @ institutoptique DOT fr
find_package(PkgConfig QUIET)
# Check to see if pkgconfig is installed.
pkg_check_modules(PC_NLOPT nlopt QUIET)
# Definitions
set(NLOPT_DEFINITIONS ${PC_NLOPT_CFLAGS_OTHER})
# Include directories
find_path(NLOPT_INCLUDE_DIRS
NAMES nlopt.h
HINTS ${PC_NLOPT_INCLUDEDIR}
PATHS "${CMAKE_INSTALL_PREFIX}/include" "C:/Program Files/NLOPT/include" )
# Libraries
find_library(NLOPT_LIBRARIES
NAMES nlopt nlopt_cxx
HINTS ${PC_NLOPT_LIBDIR} "C:/Program Files/NLOPT/lib")
# Version
set(NLOPT_VERSION ${PC_NLOPT_VERSION})
# Set (NAME)_FOUND if all the variables and the version are satisfied.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NLOPT
FAIL_MESSAGE DEFAULT_MSG
REQUIRED_VARS NLOPT_INCLUDE_DIRS NLOPT_LIBRARIES
VERSION_VAR NLOPT_VERSION)
\ No newline at end of file
Subproject commit f117a48ea2fd446d2865826a58d08027d4579cb3
......@@ -27,3 +27,4 @@ export ALTA_PLUGIN_PATH="$builddir/plugins"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$builddir/plugins:$external"
export PATH="$PATH:$builddir/softs:$scripts"
export PYTHONPATH="$PYTHONPATH:$builddir/python"
export JUPYTER_PATH="$JUPYTER_PATH:$builddir/python"
......@@ -24,7 +24,7 @@
using namespace alta;
//#define DEBUG
//#define DEBUG_CORE
//! Add dynamic library extension (.so or .dll) to a dynamic object as well as
......
......@@ -22,7 +22,7 @@
#include <cmath>
#include <utility>
using namespace alta;
namespace alta {
/*! \ingroup datas
* \ingroup plugins
......@@ -56,7 +56,7 @@ public: //methods
: vertical_segment(params, size, input_data)
{ }
ASTM(const parameters& params, size_t size)
ASTM(const alta::parameters& params, size_t size)
: vertical_segment(params, size)
{ }
};
......@@ -175,3 +175,5 @@ ALTA_DLL_EXPORT data* load_data(std::istream& input, const arguments& args)
return new ASTM(params, size, std::shared_ptr<double>(data));
}
}
......@@ -19,6 +19,7 @@
#include <core/data.h>
#include <core/args.h>
#include <core/common.h>
#include <core/params.h>
using namespace alta;
......
......@@ -19,15 +19,17 @@
#include <cmath>
#include <core/common.h>
#include <core/params.h>
using namespace alta;
ALTA_DLL_EXPORT function* provide_function(const parameters& params)
ALTA_DLL_EXPORT function* provide_function(const alta::parameters& params)
{
return new lafortune_function(params);
}
lafortune_function::lafortune_function(const parameters& params)
lafortune_function::lafortune_function(const alta::parameters& params) :
nonlinear_function(params)
{
auto nY = params.dimY();
......@@ -50,7 +52,8 @@ vec lafortune_function::operator()(const vec& x) const
}
vec lafortune_function::value(const vec& x) const
{
vec res(dimY());
const int nY = _parameters.dimY();
vec res(nY);
#ifdef ADAPT_TO_PARAM
vec y(6);
......@@ -69,7 +72,7 @@ vec lafortune_function::value(const vec& x) const
#endif
// For each color channel
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
// Start with the diffuse term
res[i] = _kd[i];
......@@ -97,7 +100,8 @@ vec lafortune_function::value(const vec& x, const vec& p)
assert(p.size() == nbParameters());
setParameters(p);
vec res(dimY());
const int nY = _parameters.dimY();
vec res(nY);
#ifdef ADAPT_TO_PARAM
vec y(6);
......@@ -116,7 +120,7 @@ vec lafortune_function::value(const vec& x, const vec& p)
#endif
// For each lobe and for each color channel
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
// Start with the diffuse
res[i] = _kd[i];
......@@ -140,6 +144,7 @@ vec lafortune_function::value(const vec& x, const vec& p)
void lafortune_function::setNbLobes(int N)
{
_n = N;
const int _nY = _parameters.dimY();
// Update the length of the vectors
if(_isotropic)
......@@ -152,47 +157,49 @@ void lafortune_function::setNbLobes(int N)
//! Number of parameters to this non-linear function
int lafortune_function::nbParameters() const
{
const int nY = _parameters.dimY();
#ifdef FIT_DIFFUSE
if(_isotropic)
return (3*_n+1)*dimY();
return (3*_n+1)*nY;
else
return (4*_n+1)*dimY();
return (4*_n+1)*nY;
#else
if(_isotropic)
return (3*_n)*dimY();
return (3*_n)*nY;
else
return (4*_n)*dimY();
return (4*_n)*nY;
#endif
}
//! Get the vector of parameters for the function
vec lafortune_function::parameters() const
{
const int nY = _parameters.dimY();
vec res(nbParameters());
for(int n=0; n<_n; ++n)
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
if(_isotropic)
{
res[(n*dimY() + i)*3 + 0] = _C[(n*dimY() + i)*2 + 0];
res[(n*dimY() + i)*3 + 1] = _C[(n*dimY() + i)*2 + 1];
res[(n*dimY() + i)*3 + 2] = _N[n*dimY() + i];
res[(n*nY + i)*3 + 0] = _C[(n*nY + i)*2 + 0];
res[(n*nY + i)*3 + 1] = _C[(n*nY + i)*2 + 1];
res[(n*nY + i)*3 + 2] = _N[n*nY + i];
}
else
{
res[(n*dimY() + i)*4 + 0] = _C[(n*dimY() + i)*3 + 0];
res[(n*dimY() + i)*4 + 1] = _C[(n*dimY() + i)*3 + 1];
res[(n*dimY() + i)*4 + 2] = _C[(n*dimY() + i)*3 + 2];
res[(n*dimY() + i)*4 + 3] = _N[n*dimY() + i];
res[(n*nY + i)*4 + 0] = _C[(n*nY + i)*3 + 0];
res[(n*nY + i)*4 + 1] = _C[(n*nY + i)*3 + 1];
res[(n*nY + i)*4 + 2] = _C[(n*nY + i)*3 + 2];
res[(n*nY + i)*4 + 3] = _N[n*nY + i];
}
}
#ifdef FIT_DIFFUSE
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
if(_isotropic)
{
res[3*_n*dimY() + i] = _kd[i];
res[3*_n*nY + i] = _kd[i];
}
}
#endif
......@@ -202,21 +209,22 @@ vec lafortune_function::parameters() const
//! Update the vector of parameters for the function
void lafortune_function::setParameters(const vec& p)
{
const int nY = _parameters.dimY();
// Safety check the number of parameters
assert(p.size() == nbParameters());
for(int n=0; n<_n; ++n)
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
_C[(n*dimY() + i)*3 + 0] = p[(n*dimY() + i)*4 + 0];
_C[(n*dimY() + i)*3 + 1] = p[(n*dimY() + i)*4 + 1];
_C[(n*dimY() + i)*3 + 2] = p[(n*dimY() + i)*4 + 2];
_N[n*dimY() + i] = p[(n*dimY() + i)*4 + 3];
_C[(n*nY + i)*3 + 0] = p[(n*nY + i)*4 + 0];
_C[(n*nY + i)*3 + 1] = p[(n*nY + i)*4 + 1];
_C[(n*nY + i)*3 + 2] = p[(n*nY + i)*4 + 2];
_N[n*nY + i] = p[(n*nY + i)*4 + 3];
}
#ifdef FIT_DIFFUSE
for(int i=0; i<dimY(); ++i)
for(int i=0; i<nY; ++i)
{
_kd[i] = p[4*_n*dimY() + i];
_kd[i] = p[4*_n*nY + i];
}
#endif
}
......@@ -225,6 +233,7 @@ void lafortune_function::setParameters(const vec& p)
//! parameters.
vec lafortune_function::parametersJacobian(const vec& x) const
{
const int nY = _parameters.dimY();
#ifdef ADAPT_TO_PARAM
vec y(6);
......@@ -242,14 +251,14 @@ vec lafortune_function::parametersJacobian(const vec& x) const
dz = x[2]*x[5];
#endif
vec jac(dimY()*nbParameters());
for(int i=0; i<dimY(); ++i)
vec jac(nY*nbParameters());
for(int i=0; i<nY; ++i)
{
for(int n=0; n<_n; ++n)
for(int j=0; j<dimY(); ++j)
for(int j=0; j<nY; ++j)
{
// index of the current monochromatic lobe
int index = i*nbParameters() + 4*(n*dimY() + j);
int index = i*nbParameters() + 4*(n*nY + j);
double Cx, Cy, Cz, N;
getCurrentLobe(n, j, Cx, Cy, Cz, N);
......@@ -283,10 +292,10 @@ vec lafortune_function::parametersJacobian(const vec& x) const
}
#ifdef FIT_DIFFUSE
for(int j=0; j<dimY(); ++j)
for(int j=0; j<nY; ++j)
{
// index of the current monochromatic lobe
int index = i*nbParameters() + 4*_n*dimY() + j;
int index = i*nbParameters() + 4*_n*nY + j;
jac[index] = 1.0;
}
......@@ -298,31 +307,33 @@ vec lafortune_function::parametersJacobian(const vec& x) const
void lafortune_function::bootstrap(const ptr<data> d, const arguments& args)
{
const int nY = _parameters.dimY();
// Check the arguments for the number of lobes
this->setNbLobes(args.get_int("lobes", 1));
// Set the diffuse component
vec x0 = d->get(0);
for(int i=0; i<d->dimY(); ++i)
_kd[i] = x0[d->dimX() + i];
for(int i=0; i<d->parametrization().dimY(); ++i)
_kd[i] = x0[d->parametrization().dimX() + i];
for(int i=1; i<d->size(); ++i)
{
vec xi = d->get(i);
for(int j=0; j<d->dimY(); ++j)
_kd[j] = std::min(xi[d->dimX() + j], _kd[j]);
for(int j=0; j<d->parametrization().dimY(); ++j)
_kd[j] = std::min(xi[d->parametrization().dimX() + j], _kd[j]);
}
// The remaining data will be equal to one
for(int n=0; n<_n; ++n)
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
double theta = 0.5 * M_PI * n / (double)_n;
_C[(n*dimY() + i)*3 + 0] = -sin(theta);
_C[(n*dimY() + i)*3 + 1] = -sin(theta);
_C[(n*dimY() + i)*3 + 2] = cos(theta);
_N[n*dimY() + i] = (double)_n;
_C[(n*nY + i)*3 + 0] = -sin(theta);
_C[(n*nY + i)*3 + 1] = -sin(theta);
_C[(n*nY + i)*3 + 2] = cos(theta);
_N[n*nY + i] = (double)_n;
}
}
......@@ -396,6 +407,7 @@ bool lafortune_function::load(std::istream& in)
setNbLobes(nb_lobes);
// Parse the lobe
const int _nY = _parameters.dimY();
for(int n=0; n<_n; ++n)
{
for(int i=0; i<_nY; ++i)
......@@ -418,6 +430,7 @@ void lafortune_function::save_call(std::ostream& out, const arguments& args) con
{
bool is_alta = !args.is_defined("export") || args["export"] == "alta";
const int _nY = _parameters.dimY();
if(is_alta)
{
out << "#FUNC nonlinear_function_lafortune" << std::endl ;
......
......@@ -21,6 +21,7 @@
#include <core/fitter.h>
#include <core/args.h>
#include <core/common.h>
#include <core/params.h>
using namespace alta;
......@@ -44,7 +45,7 @@ class lafortune_function : public nonlinear_function
public: // methods
lafortune_function(const parameters& params);
lafortune_function(const alta::parameters& params);
// Overload the function operator
virtual vec operator()(const vec& x) const ;
......@@ -103,6 +104,7 @@ class lafortune_function : public nonlinear_function
//! n for the color channel number c.
void getCurrentLobe(int n, int c, double& Cx, double& Cy, double& Cz, double& N) const
{
const int _nY = _parameters.dimY();
if(_isotropic)
{
Cx = _C[(n*_nY + c)*2 + 0];
......@@ -128,11 +130,5 @@ class lafortune_function : public nonlinear_function
//!\brief Flags to get an isotropic lobe
bool _isotropic;
lafortune_function()
: nonlinear_function(6, 0,
params::CARTESIAN, params::UNKNOWN_OUTPUT)
{
};
} ;
......@@ -22,18 +22,18 @@
using namespace alta;
ALTA_DLL_EXPORT function* provide_function(const parameters& params)
ALTA_DLL_EXPORT function* provide_function(const alta::parameters& params)
{
return new spherical_gaussian_function(params);
}
spherical_gaussian_function::spherical_gaussian_function(const parameters& params)
spherical_gaussian_function::spherical_gaussian_function(const alta::parameters& params)
: nonlinear_function(params.set_input(6, params::CARTESIAN)),
_non_a(1), _type(Mirror)
_a(1.0), _type(Mirror)
{
// Update the length of the vectors
_n.resize(_nY) ;
_ks.resize(_nY) ;
_n.resize(_parameters.dimY()) ;
_ks.resize(_parameters.dimY()) ;
}
// Overload the function operator
......@@ -43,10 +43,10 @@ vec spherical_gaussian_function::operator()(const vec& x) const
}
vec spherical_gaussian_function::value(const vec& x) const
{
vec res(dimY());
vec res(_parameters.dimY());
double dot = compute_dot(x);
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
res[i] = _ks[i] * std::exp(_n[i] * (dot-1));
}
......@@ -95,22 +95,23 @@ int spherical_gaussian_function::nbParameters() const
{
if(_type == Moment)
{
return 2*dimY()+1;
return 2*_parameters.dimY()+1;
}
else
{
return 2*dimY();
return 2*_parameters.dimY();
}
}
//! Get the vector of parameters for the function
vec spherical_gaussian_function::parameters() const
{
const int nY = _parameters.dimY();
if(_type == Moment)
{
vec res(2*dimY()+1);
res[2*dimY()] = _a;
for(int i=0; i<dimY(); ++i)
vec res(2*nY+1);
res[2*nY] = _a;
for(int i=0; i<nY; ++i)
{
res[i*2 + 0] = _ks[i];
res[i*2 + 1] = _n[i];
......@@ -120,8 +121,8 @@ vec spherical_gaussian_function::parameters() const
}
else
{
vec res(2*dimY());
for(int i=0; i<dimY(); ++i)
vec res(2*nY);
for(int i=0; i<nY; ++i)
{
res[i*2 + 0] = _ks[i];
res[i*2 + 1] = _n[i];
......@@ -133,11 +134,12 @@ vec spherical_gaussian_function::parameters() const
//! \brief get the min values for the parameters
vec spherical_gaussian_function::getParametersMin() const
{
const int nY = _parameters.dimY();
if(_type == Moment)
{
vec res(2*dimY()+1);
res[2*dimY()] = 0.0;
for(int i=0; i<dimY(); ++i)
vec res(2*nY+1);
res[2*nY] = 0.0;
for(int i=0; i<nY; ++i)
{
res[i*2 + 0] = 0.0;
res[i*2 + 1] = 0.0;
......@@ -147,8 +149,8 @@ vec spherical_gaussian_function::getParametersMin() const
}
else
{
vec res(2*dimY());
for(int i=0; i<dimY(); ++i)
vec res(2*nY);
for(int i=0; i<nY; ++i)
{
res[i*2 + 0] = 0.0;
res[i*2 + 1] = 0.0;
......@@ -163,10 +165,10 @@ void spherical_gaussian_function::setParameters(const vec& p)
{
if(_type == Moment)
{
_a = p[2*dimY()];
_a = p[2*_parameters.dimY()];
}
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
_ks[i] = p[i*2 + 0];
_n[i] = p[i*2 + 1];
......@@ -179,10 +181,10 @@ vec spherical_gaussian_function::parametersJacobian(const vec& x) const
{
double dot = compute_dot(x);
vec jac(dimY()*nbParameters());
for(int i=0; i<dimY(); ++i)
vec jac(_parameters.dimY()*nbParameters());
for(int i=0; i<_parameters.dimY(); ++i)
{
for(int j=0; j<dimY(); ++j)
for(int j=0; j<_parameters.dimY(); ++j)
{
if(i == j)
{
......@@ -221,7 +223,7 @@ vec spherical_gaussian_function::parametersJacobian(const vec& x) const
void spherical_gaussian_function::bootstrap(const ptr<data> d, const arguments& args)
{
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
_ks[i] = 1.0;
_n[i] = 1.0;
......@@ -287,7 +289,7 @@ bool spherical_gaussian_function::load(std::istream& in)
}
// Parse the lobe
for(int i=0; i<_nY; ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
in >> token >> _ks[i];
......@@ -309,11 +311,12 @@ void spherical_gaussian_function::save_call(std::ostream& out, const arguments&
{
bool is_alta = !args.is_defined("export") || args["export"] == "alta";
const int nY = _parameters.dimY();
if(is_alta)
{
out << "#FUNC nonlinear_function_spherical_gaussian" << std::endl ;
for(int i=0; i<_nY; ++i)
for(int i=0; i<nY; ++i)
{
out << "Ks " << _ks[i] << std::endl;
out << "N " << _n[i] << std::endl;
......@@ -329,17 +332,17 @@ void spherical_gaussian_function::save_call(std::ostream& out, const arguments&
else
{
out << "spherical_gaussian(L, V, N, X, Y, vec3(";
for(int i=0; i<_nY; ++i)
for(int i=0; i<nY; ++i)
{
out << _ks[i];
if(i < _nY-1) { out << ", "; }
if(i < nY-1) { out << ", "; }
}
out << "), vec3(";
for(int i=0; i<_nY; ++i)
for(int i=0; i<nY; ++i)
{
out << _n[i];
if(i < _nY-1) { out << ", "; }
if(i < nY-1) { out << ", "; }
}
out << "))";
......
......@@ -20,6 +20,7 @@
#include <core/fitter.h>
#include <core/args.h>
#include <core/common.h>
#include <core/params.h>
using namespace alta;
......@@ -56,7 +57,7 @@ class spherical_gaussian_function : public nonlinear_function
Moment
};
spherical_gaussian_function(const parameters& params);
spherical_gaussian_function(const alta::parameters& params);
// Overload the function operator
virtual vec operator()(const vec& x) const ;
......
......@@ -18,15 +18,16 @@
#include <cmath>
#include <core/common.h>
#include <core/params.h>
using namespace alta;
ALTA_DLL_EXPORT function* provide_function(const parameters& params)
ALTA_DLL_EXPORT function* provide_function(const alta::parameters& params)
{
return new schlick_masking(params);
}
schlick_masking::schlick_masking(const parameters& params)
schlick_masking::schlick_masking(const alta::parameters& params)
: nonlinear_function(params.set_input(6, params::CARTESIAN))
{
w.resize(params.dimY());
......@@ -66,7 +67,7 @@ bool schlick_masking::load(std::istream& in)
}
// R [double]
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
in >> token >> w[i];
}
......@@ -80,7 +81,7 @@ void schlick_masking::save_call(std::ostream& out, const arguments& args) const
if(is_alta)
{
out << "#FUNC nonlinear_masking_schlick" << std::endl ;
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
out << "K " << w[i] << std::endl;
}
......@@ -89,10 +90,10 @@ void schlick_masking::save_call(std::ostream& out, const arguments& args) const
else
{
out << "masking_schlick(L, V, N, X, Y, vec3";
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
out << w[i];
if(i < _nY-1) { out << ", "; }
if(i < _parameters.dimY()-1) { out << ", "; }
}
out << "))";
}
......@@ -122,11 +123,11 @@ void schlick_masking::save_body(std::ostream& out, const arguments& args) const
vec schlick_masking::value(const vec& x) const
{
vec res(dimY());
vec res(_parameters.dimY());
const double u = x[5];
const double v = x[2];
for(int i=0; i<dimY(); ++i)
for(int i=0; i<_parameters.dimY(); ++i)
{
const double Gu = u / (u + w[i] * (1.0 - u));
const double Gv = v / (v + w[i] * (1.0 - v));
......@@ -138,35 +139,35 @@ vec schlick_masking::value(const vec& x) const
//! \brief Number of parameters to this non-linear function
int schlick_masking::nbParameters() const
{
return dimY();
return _parameters.dimY();
}
vec schlick_masking::getParametersMin() const
{
vec m(dimY());
for(int i=0; i<dimY(); ++i) { m[i] = 0.0; }
vec m(_parameters.dimY());
for(int i=0; i<_parameters.dimY(); ++i) { m[i] = 0.0; }
return m;
}
//! \brief Get the vector of parameters for the function
vec schlick_masking::parameters() const
{
vec p(dimY());
for(int i=0; i<dimY(); ++i) { p[i] = w[i]; }
vec p(_parameters.dimY());
for(int i=0; i<_parameters.dimY(); ++i) { p[i] = w[i]; }
return p;
}
//! \brief Update the vector of parameters for the function
void schlick_masking::setParameters(const vec& p)
{
for(int i=0; i<dimY(); ++i) { w[i] = p[i]; }
for(int i=0; i<_parameters.dimY(); ++i) { w[i] = p[i]; }
}
//! \brief Obtain the derivatives of the function with respect to the
//! parameters.
vec schlick_masking::parametersJacobian(const vec& x) const
{
const int nY = dimY();
const int nY = _parameters.dimY();
vec jac(nY*nY);
const double u = x[5];
......@@ -184,11 +185,11 @@ vec schlick_masking::parametersJacobian(const vec& x) const
const double dGu = - u*(1.0 - u) / pow(u + w[i]*(1.0-u), 2);
const double dGv = - v*(1.0 - v) / pow(v + w[i]*(1.0-v), 2);
jac[j*dimY() + i] = Gu*dGv + Gv*dGu;
jac[j*_parameters.dimY() + i] = Gu*dGv + Gv*dGu;
}
else
{
jac[j*dimY() + i] = 0.0;
jac[j*_parameters.dimY() + i] = 0.0;
}
}
......@@ -199,5 +200,5 @@ vec schlick_masking::parametersJacobian(const vec& x) const
void schlick_masking::bootstrap(const ptr<data>, const arguments&)
{
// Start with a non occluding value for k
for(int i=0; i<dimY(); ++i) { w[i] = 0.0; }
for(int i=0; i<_parameters.dimY(); ++i) { w[i] = 0.0; }
}
......@@ -33,7 +33,7 @@ class schlick_masking : public nonlinear_function
public: // methods
schlick_masking(const parameters& params);
schlick_masking(const alta::parameters& params);
//! \brief Load function specific files
virtual bool load(std::istream& in) ;
......@@ -69,7 +69,6 @@ class schlick_masking : public nonlinear_function
private: // data
//! Fresnel reflectance at theta = 0
vec w;
schlick_masking() {};
vec w;
} ;
......@@ -66,8 +66,6 @@ class smith : public nonlinear_function//fresnel
//! Fresnel reflectance at theta = 0 ?
//! RP: I DOUBLT IT . Seems to be a brute copy and paste ???
//! RP: w^2 should be the mean-square surface slope
vec w;
smith() {};
vec w;
} ;
......@@ -5,29 +5,32 @@ Import('env', 'library_available')
env = env.Clone()
env.Prepend(LIBS = ['core'])
## Add pybind path
env.AppendUnique(CPPPATH = '#external/pybind11/include/')
## Building a test function for boost::python
##
bp_test_source = """
// STL and Boost includes
#include <memory>
#include <boost/python.hpp>
#include <pybind11/pybind11.h>
// ALTA includes
#include <core/common.h>
#include <core/ptr.h>
#include <core/function.h>
int main(int argc, char** argv) {
boost::python::class_<alta::function, alta::ptr<alta::function>, boost::noncopyable>("function", boost::python::no_init);
boost::python::register_ptr_to_python<alta::ptr<alta::function>>();
namespace py = pybind11;
return 0;
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("norm", &norm, "Compute the norm of vector 'v'", py::arg("v"));
}
"""
def CheckBoostPython(context):
context.Message('Checking boost::python using small example...')
result = context.TryLink(bp_test_source, '.cpp')
result = context.TryCompile(bp_test_source, '.cpp')
context.Result(result)
return result
......@@ -41,16 +44,6 @@ if library_available(env, pkgspec='python-2.7',
lib='PYTHON_LIB', header='Python.h'):
conf = Configure(env, custom_tests = {'CheckBoostPython' : CheckBoostPython})
# On GNU/Linux the '-mt' suffix is no longer used, but it is still
# used on some other platforms (see
# <http://stackoverflow.com/questions/2293962/boost-libraries-in-multithreading-aware-mode>.)
build_lib = conf.CheckLibWithHeader('boost_python-mt',
'boost/python.hpp', 'c++')
if not build_lib:
build_lib = conf.CheckLibWithHeader('boost_python',
'boost/python.hpp', 'c++')
build_lib = conf.CheckBoostPython();
env = conf.Finish()
......
<
......@@ -2,6 +2,7 @@
Copyright (C) 2014, 2015, 2016 Inria
Copyright (C) 2015 Université de Montréal
Copyright (C) 2018 Unity
This file is part of ALTA.
......@@ -9,8 +10,9 @@
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Boost includes
#include <boost/python.hpp>
// Pybind11 includes
#include <pybind11/pybind11.h>
namespace py = pybind11;
// ALTA include
#include <core/common.h>
......@@ -25,57 +27,13 @@
#include <iostream>
// Local includes
#include "wrapper_vec.hpp"
#define bp boost::python
#include "wrapper_args.h"
#include "wrapper_vec.h"
#include "wrapper_data.h"
using namespace alta;
/* This class is a wrapper to ALTA's arguments class to add Python specific
* behaviour such as dictionnary initialization.
*
* Right now it does not handle automatic conversion in function call for
* example. The following code is not possible:
*
* import alta
* alta.get_data('data_merl', {'params' : 'STARK_2D'})
*
* Instead, one has to construct the arguments object from the ALTA library
* to use it afterwards:
*
* import alta
* args = alta.arguments({'params' : 'STARK_2D'})
* alta.get_data('data_merl', args)
*/
struct python_arguments : public arguments {
python_arguments() : arguments() {}
python_arguments(bp::dict d) : arguments() {
bp::list keys = d.keys();
for(int i=0; i<bp::len(keys); ++i) {
const std::string s_key = bp::extract<std::string>(keys[i]);
const std::string s_val = bp::extract<std::string>(d[keys[i]]);
this->update(s_key, s_val);
}
}
};
/* Create a data object from a plugin's name and the data filename. This
* function is here to accelerate the loading of data file.
*/
static ptr<data> load_data(const std::string& plugin_name, const std::string& filename) {
ptr<data> d = plugins_manager::load_data(filename, plugin_name);
return d;
}
static ptr<data> get_data_with_args(const std::string& plugin_name,
size_t size,
const parameters& params,
const python_arguments& args) {
return plugins_manager::get_data(plugin_name, size, params, args);
}
static ptr<data> get_data(const std::string& plugin_name, size_t size,
const parameters& params) {
return plugins_manager::get_data(plugin_name, size, params);
}
/* Creating functions for the plugins_manager calls
*
......@@ -335,137 +293,110 @@ static void brdf2data(const ptr<function>& f, ptr<data>& d) {
/* Compute distance metric between 'in' and 'ref'.
*/
static bp::dict data2stats(const ptr<data>& in, const ptr<data>& ref) {
static py::dict data2stats(const ptr<data>& in, const ptr<data>& ref) {
// Compute the metrics
errors::metrics res;
errors::compute(in.get(), ref.get(), nullptr, res);
// Fill the resulting Python vector
bp::dict py_res;
py::dict py_res;
for(auto rpair : res) {
py_res.setdefault<std::string, vec>(rpair.first, rpair.second);
py_res[py::str(rpair.first)] = rpair.second;
}
return py_res;
}
inline void register_function(py::module& m) {
py::class_<function, ptr<function>>(m, "function")
.def("__add__", &add_function)
.def("__mul__", &mult_function)
.def("__rmul__", &mult_function)
.def("value", &function::value)
.def("load", &load_from_file)
.def("load", &load_from_file_with_args)
.def("save", &function::save)
.def("save", &save_function_without_args)
.def("set", &set_function_params)
.def("get", &get_function_params);
m.def("get_function", get_function, py::arg("name") = "nonlinear_diffuse",
py::arg("param") = parameters(6, 3, params::CARTESIAN, params::RGB_COLOR));
m.def("get_function", get_function_from_args);
m.def("load_function", load_function);
m.def("load_function", load_function_with_args);
}
inline void register_fitter(py::module& m) {
py::class_<fitter, ptr<fitter>>(m, "fitter")
.def("fit_data", &fit_data_with_args)
.def("fit_data", &fit_data_without_args);
m.def("get_fitter", plugins_manager::get_fitter);
}
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
/* Exporting the ALTA module
*/
BOOST_PYTHON_MODULE(alta)
{
// Argument class
//
bp::class_<arguments>("_arguments");
bp::class_<python_arguments, bp::bases<arguments>>("arguments")
.def(bp::init<>())
.def(bp::init<bp::dict>())
.def("__getitem__", &arguments::operator[])
.def("update", &arguments::update);
PYBIND11_MODULE(alta, m) {
m.doc() = "ALTA python bindinds";
m.def("norm", &norm, "Compute the norm of vector 'v'", py::arg("v"));
// Vec class
//
register_wrapper_vec();
// 'parameters' class.
bp::class_<parameters>("parameters")
.def(bp::init<unsigned int, unsigned int, params::input, params::output>());
// Parameterization enums.
/* Register the 'parameters' class and the enums */
py::class_<parameters>(m, "parameters")
.def(py::init<unsigned int, unsigned int, params::input, params::output>());
#define PARAM_VALUE(name) \
.value(STRINGIFY(name), params:: name)
bp::enum_<params::input>("input_parametrization")
PARAM_VALUE(RUSIN_TH_PH_TD_PD)
PARAM_VALUE(RUSIN_TH_PH_TD)
PARAM_VALUE(RUSIN_TH_TD_PD)
PARAM_VALUE(RUSIN_TH_TD)
PARAM_VALUE(RUSIN_VH_VD)
PARAM_VALUE(RUSIN_VH)
PARAM_VALUE(COS_TH_TD)
PARAM_VALUE(COS_TH)
PARAM_VALUE(SCHLICK_TK_PK)
PARAM_VALUE(SCHLICK_VK)
PARAM_VALUE(SCHLICK_TL_TK_PROJ_DPHI)
PARAM_VALUE(COS_TK)
PARAM_VALUE(RETRO_TL_TVL_PROJ_DPHI)
PARAM_VALUE(STEREOGRAPHIC)
PARAM_VALUE(SPHERICAL_TL_PL_TV_PV)
PARAM_VALUE(COS_TLV)
PARAM_VALUE(COS_TLR)
PARAM_VALUE(ISOTROPIC_TV_TL)
PARAM_VALUE(ISOTROPIC_TV_TL_DPHI)
PARAM_VALUE(ISOTROPIC_TV_PROJ_DPHI)
PARAM_VALUE(ISOTROPIC_TL_TV_PROJ_DPHI)
PARAM_VALUE(ISOTROPIC_TD_PD)
PARAM_VALUE(STARK_2D)
PARAM_VALUE(STARK_3D)
PARAM_VALUE(NEUMANN_2D)
PARAM_VALUE(NEUMANN_3D)
PARAM_VALUE(CARTESIAN)
PARAM_VALUE(UNKNOWN_INPUT);
bp::enum_<params::output>("output_parametrization")
PARAM_VALUE(INV_STERADIAN)
PARAM_VALUE(INV_STERADIAN_COSINE_FACTOR)
PARAM_VALUE(ENERGY)
PARAM_VALUE(RGB_COLOR)
PARAM_VALUE(XYZ_COLOR)
PARAM_VALUE(UNKNOWN_OUTPUT);
py::enum_<params::input>(m, "input_parametrization")
PARAM_VALUE(RUSIN_TH_PH_TD_PD)
PARAM_VALUE(RUSIN_TH_PH_TD)
PARAM_VALUE(RUSIN_TH_TD_PD)
PARAM_VALUE(RUSIN_TH_TD)
PARAM_VALUE(RUSIN_VH_VD)
PARAM_VALUE(RUSIN_VH)
PARAM_VALUE(COS_TH_TD)
PARAM_VALUE(COS_TH)
PARAM_VALUE(SCHLICK_TK_PK)
PARAM_VALUE(SCHLICK_VK)
PARAM_VALUE(SCHLICK_TL_TK_PROJ_DPHI)