Commit 5574a878 authored by Laurent Belcour's avatar Laurent Belcour

Merge branch 'gforge-master'

parents 896f5832 5d1b434b
......@@ -21,7 +21,6 @@ sys.path += [ top_srcdir + '/external' ]
## Add ALTA custom cmd configurations
##
AddOption('--cfg', help='Specify a configuration file')
AddOption('--no-externals', action="store_false", dest="obtain_externals", default=True, help='Do not download and build externals')
## Import configuration from a config file
......@@ -134,7 +133,6 @@ if len(envVars['PKG_CONFIG_PATH']) > 0:
envVars['PKG_CONFIG_PATH'] += ':'
envVars['PKG_CONFIG_PATH'] += os.path.abspath('external' + os.sep + 'build' + os.sep + 'lib' + os.sep + 'pkgconfig')
env = Environment(variables = vars, ENV = envVars)
env['DL_EXTERNALS'] = GetOption('obtain_externals')
# Generate help text for the build variables.
......
......@@ -54,10 +54,6 @@ Optional dependencies that will allow more plugins to be built include:
+ [MATLAB][matlab] with the Engine library, for some plugins.
For your convenience, some of these dependencies are shipped with ALTA,
as noted above. Others are automatically downloaded unless
<tt>--no-externals</tt> is passed to <tt>scons</tt> (see below.)
#### Note for Ceres installation for Debian/Ubuntu distribution
To improve the numerical stability of the different solvers, it is highly recommended to install the following packages:
+ <tt>libatlas-base-dev</tt>
......@@ -88,9 +84,9 @@ dependencies are met, and which of the optional dependencies are
available. All the compilation byproducts go to the
<tt>sources/build</tt> sub-directory.
Some of the missing dependencies, such as NlOpt, IpOpt, and CERES, are
automatically downloaded from upstream when they are not found. The
downloaded files are integrity-checked, and then the software is built
If Eigen could not be found, it is
automatically downloaded from upstream. The
downloaded file is integrity-checked, and then the software is built
and installed under the <tt>external/build</tt> sub-directory of the
source tree.
......
# ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
#
# Copyright (C) 2014, 2015 CNRS
# Copyright (C) 2013, 2014, 2015 Inria
# Copyright (C) 2013, 2014, 2015, 2016 Inria
# Copyright (C) 2015 Universite de Montreal
#
# This file is part of ALTA.
......@@ -25,11 +25,7 @@ if env.GetOption('clean'):
#shutil.rmtree('build', True)
# Removing the TP directories
#shutil.rmtree('ceres-solver-1.7.0', True)
#shutil.rmtree('eigen-eigen-ffa86ffb5570', True)
#shutil.rmtree('glog-0.3.3', True)
#shutil.rmtree('Ipopt-3.11.8', True)
#shutil.rmtree('nlopt-2.4.1', True)
else:
##
......@@ -45,47 +41,6 @@ else:
env['EIGEN_INC'] = [Dir('#external/build/include').abspath]
env = conf.Finish()
##
# The env variable is cloned for IpOpt, NlOpt and CERES to avoid
# propagating the link flags for them in the main build script.
##
##
# Check for optional dependencies, downloading them if they
# are not already available in the user's environment.
#
# At this point CCFLAGS and LINKFLAGS already contain the
# right flags if those dependencies if they found via
# 'pkg-config'. Check whether they are usable, and download
# them if not.
#
##
##
# IpOpt dependencies
##
env2 = env.Clone()
if not on_windows and not library_available(env2, pkgspec='ipopt', inc_var='IPOPT_INC', lib_var='IPOPT_DIR', lib='IPOPT_LIB', header='coin/IpTNLP.hpp') and env['DL_EXTERNALS']:
execfile('obtain_ipopt.py')
##
# NlOpt dependencies
##
env2 = env.Clone()
if not library_available(env2, pkgspec='nlopt', inc_var='NLOPT_INC', lib_var='NLOPT_DIR', lib='NLOPT_LIB', header='nlopt.h') and env['DL_EXTERNALS']:
execfile('obtain_nlopt.py')
##
# CERES dependencies
##
env2 = env.Clone()
if not library_available(env2, pkgspec='ceres', inc_var='CERES_INC', lib_var='CERES_DIR', lib='CERES_LIB', header='ceres/ceres.h') and env['DL_EXTERNALS']:
execfile('obtain_ceres.py')
C.progress_display("external libraries are built as shared libraries")
C.progress_display("please adjust the shared library search path \
before running ALTA")
##
# QuadProg++
# TODO: Change to the QuadProg v2 code
......
import obtain
import os
import sys
import shutil
import subprocess
import SCons.Warnings as W
import SCons.SConf as C
# Download GLOG
version = '0.3.3'
base = 'glog'
name = 'GLOG v' + version
directory = base + '-' + version
url = 'http://google-glog.googlecode.com/files/glog-' + version + '.tar.gz'
filename = 'glog-' + version + '.tar.gz'
sha256 = 'fbf90c2285ba0561db7a40f8a4eefb9aa963e7d399bd450363e959929fe849d0'
glog_obtained = False
glog_compiled = False
if os.name != 'nt':
glog_obtained = obtain.obtain(name, directory, url, filename, sha256)
glog_compiled = os.path.exists('.' + os.sep + 'build' + os.sep + 'include' + os.sep + 'glog')
if glog_obtained and not glog_compiled:
if sys.platform == 'darwin':
obtain.patch('glog-0.3.3/src/glog/stl_logging.h.in', 'glog.patch')
C.progress_display('configuring and building GLOG for CERES')
glog_compiled = obtain.configure_build(directory,
['--disable-shared',
'--enable-static', '--with-pic'])
# Download CERES. Assume Eigen is already available.
version = '1.9.0'
base = 'ceres-solver'
name = 'CERES v' + version
directory = base + '-' + version
url = 'http://ceres-solver.org/ceres-solver-' + version + '.tar.gz'
filename = 'ceres-solver-' + version + '.tar.gz'
sha256 = '30ac0729249f908afe80cb6fd06ae6d037f25a60d9fac54f61344389adab9c1a'
obtained = obtain.obtain(name, directory, url, filename, sha256)
## Test for the presence of already compiled ceres version in
## the $ALTA/external/build directory. Then test for the
## presence of cmake.
compile_test = not os.path.exists('.' + os.sep + 'build' + os.sep + 'include' + os.sep + 'ceres')
if obtained and compile_test:
C.progress_display('configuring and building ' + name)
# Build cmake script
build_dir = os.pardir + os.sep + 'build' + os.sep
options = ''
if glog_compiled:
options = '-DGLOG_LIBRARY=' + build_dir + 'lib' + os.sep + 'libglog.a' + ' -DGLOG_INCLUDE_DIR=' + build_dir + 'include' + ' -DMINIGLOG=OFF'
else:
options = '-DMINIGLOG=ON'
options = options + ' include -DGFLAGS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF'
# When Eigen was not found by pkg-config (i.e., it was built
# locally under externals/, or the user specified 'EIGEN_INC' in
# the config file), then we need to tell CMake where to find it.
if env['EIGEN_INC']:
options += '-DEIGEN_INCLUDE_DIR=' + env['EIGEN_INC'][0] + '/include'
if not sys.platform.startswith('win'):
# Build PIC so we can link it into our DSOs.
options = options + ' -DCMAKE_CXX_FLAGS=-fPIC'
if obtain.cmake_build(directory, options):
if not glog_compiled:
# When CERES builds miniglog, it installs its headers under
# $includedir/ceres/internal/miniglog. Move it to the right
# place.
includedir = Dir('#external/build/include').abspath
os.rename(includedir + '/ceres/internal/miniglog/glog',
includedir + '/glog')
# CERES's CMakeLists.txt chooses to install to lib64/ or lib/
# depending on the phase of the moon. Rectify that by moving
# things to lib/ if need be.
libdir = Dir('#external/build/lib').abspath
lib64dir = Dir('#external/build/lib64').abspath
if os.access(lib64dir, os.R_OK):
os.rename(lib64dir + '/libceres.a', libdir + '/libceres.a')
if not glog_compiled:
os.rename(lib64dir + '/libminiglog.a', libdir + '/libminiglog.a')
os.rmdir(lib64dir)
# When building miniglog, rename it to libglog.a, which is what the
# rest of the build system expects.
if not glog_compiled:
if not sys.platform.startswith('win'):
os.rename(libdir + '/libminiglog.a', libdir + '/libglog.a')
else:
os.rename(libdir + '/miniglog.lib', libdir + '/libglog.lib')
#end ifelse
#end if
#end if
else:
W.warn(obtain.AltaDependencyWarning,
'CERES already installed or cannot be installed automatically')
import obtain
import os
import sys
import shutil
import subprocess
import SCons.Warnings as W
import SCons.SConf as C
from subprocess import Popen, PIPE
def getThirdParty(name) :
path = os.getcwd()
third = path + os.sep + directory + os.sep + 'ThirdParty' + os.sep
os.chdir(third + name)
ret = Popen(['./get.' + name]).wait()
if(ret != 0):
C.progress_display('Failed to get IpOpt third party \'' + name + '\'')
os.chdir(path)
# Download IpOpt.
version = '3.12.4'
base = 'Ipopt'
name = 'IpOpt v' + version
directory = base + '-' + version
url = 'http://www.coin-or.org/download/source/Ipopt/Ipopt-' + version + '.tgz'
filename = 'Ipopt-' + version + '.tgz'
sha256 = '292afd952c25ec9fe6225041683dcbd3cb76e15a128764671927dbaf881c2e89'
obtained = obtain.obtain(name, directory, url, filename, sha256)
compiled = os.path.exists('.' + os.sep + 'build' + os.sep + 'include' + os.sep + 'coin/IpIpoptNLP.hpp')
if obtained and not compiled:
if os.name == 'nt':
W.warn(obtain.AltaDependencyWarning, 'sorry, no automatic installation of IpOpt')
else:
C.progress_display('configuring and building ' + name + ' and its dependencies')
getThirdParty('Blas')
getThirdParty('Lapack')
getThirdParty('ASL')
getThirdParty('Mumps')
obtain.configure_build(directory,
['--enable-static', '--with-pic',
'--enable-dependency-linking'])
else:
C.progress_display('IpOpt is already installed')
C.progress_display('if the plugins using IpOpt fail to build, check its installation')
import obtain
import os
import sys
import shutil
import SCons.SConf as C
# Download NlOpt.
version = '2.4.1'
base = 'nlopt'
name = 'NlOpt v' + version
directory = base + '-' + version
baseurl = 'http://ab-initio.mit.edu/nlopt/'
url = baseurl + 'nlopt-' + version + '.tar.gz'
filename = 'nlopt-' + version + '.tar.gz'
sha256 = 'fe9ade54ed79c87f682540c34ad4e610ff32c9a43c52c6ea78cef6adcd5c1319'
obtained = obtain.obtain(name, directory, url, filename, sha256)
compiled = os.path.exists('.' + os.sep + 'build' + os.sep + 'include' + os.sep + 'nlopt.hpp')
if obtained and not compiled:
C.progress_display('configuring and building ' + name)
if os.name == 'nt':
# Get the CMakeList file
obtain.download(baseurl + 'CMakeLists.txt', directory+os.sep+'CMakeLists.txt')
# Get the Additional CMake script
obtain.download(baseurl + 'config.cmake.h.in', directory+os.sep+'config.cmake.h.in')
# Build cmake script
obtain.cmake_build(directory)
else:
obtain.configure_build(directory,
['--enable-static', '--with-pic',
'--without-matlab',
'--without-octave', '--without-python',
'--without-guile'])
else:
print '<<INSTALL>> NlOpt already installed'
......@@ -10,15 +10,30 @@
:: This script can be launch using Administrator rights. In
:: this case, the different PATHS will be permanent.
::
:: It can happens that the PATH variable contain directory
:: with parenthesis in them. In that case, we cannot use
:: a parenthesis for the IF ELSE statement. I use goto instead.
::
:: Source:
:: http://www.blinnov.com/en/2010/06/04/microsoft-was-unexpected-at-this-time/
net session >nul 2>&1
if %ERRORLEVEL% equ 0 (
setx ALTA_DIR "%~dp0sources" /M
setx ALTA_PLUGIN_PATH "%~dp0build\plugins" /M
setx PATH "%PATH%;%~dp0build\softs" /M
setx PYTHONPATH "%PYTHONPATH%;%~dp0build\python" /M
) else (
set ALTA_DIR=%~dp0sources
set ALTA_PLUGIN_PATH=%~dp0build\plugins
set PATH=%PATH%;%~dp0build\softs
set PYTHONPATH=%PYTHONPATH%;%~dp0build\python
)
IF %ERRORLEVEL% EQU 0 GOTO superuser
set ALTA_DIR=%~dp0sources
set ALTA_PLUGIN_PATH=%~dp0build\plugins
set PATH=%PATH%;%~dp0build\softs
set PYTHONPATH=%PYTHONPATH%;%~dp0build\python
REM set ALTA_DIR=%CD%\sources
REM set ALTA_PLUGIN_PATH=%CD%\build\plugins
REM set PATH=%PATH%;%CD%\build\softs
REM set PYTHONPATH=%PYTHONPATH%;%CD%\build\python
GOTO:eof
:superuser
setx ALTA_DIR "%~dp0sources" /M
setx ALTA_PLUGIN_PATH "%~dp0build\plugins" /M
setx PATH "%PATH%;%~dp0build\softs" /M
setx PYTHONPATH "%PYTHONPATH%;%~dp0build\python" /M
GOTO:eof
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2014 CNRS
Copyright (C) 2013, 2014, 2015 Inria
Copyright (C) 2013, 2014, 2015, 2016 Inria
This file is part of ALTA.
......@@ -36,6 +36,8 @@
#include <Eigen/Core>
typedef Eigen::VectorXd vec;
typedef Eigen::Ref<vec> vecref;
typedef Eigen::Ref<const vec> const_vecref;
// Convenience functions.
static inline double norm(const vec& v)
......@@ -103,6 +105,13 @@ static bool close_to(const T a, const T b, const T epsilon = 1E-7)
}
/* Mark a type, class, method, function, or variable as deprecated. */
#ifdef __GNUC__
# define ALTA_DEPRECATED __attribute__((__deprecated__))
#else
# define ALTA_DEPRECATED
#endif
#ifdef _MSC_VER
#define NOT_IMPLEMENTED() \
std::cerr << "<<ERROR>> not implemented " << __FUNCDNAME__ << " in file " << __FILE__ \
......
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015 Inria
Copyright (C) 2013, 2014, 2015, 2016 Inria
This file is part of ALTA.
......@@ -17,41 +17,43 @@ using namespace alta;
void data::save(const std::string& filename) const
{
std::ofstream file;
std::ofstream file;
file.exceptions(std::ios_base::failbit);
file.open(filename.c_str(), std::ios_base::trunc);
file.exceptions(std::ios_base::goodbit);
file.exceptions(std::ios_base::failbit);
file.open(filename.c_str(), std::ios_base::trunc);
file.exceptions(std::ios_base::goodbit);
alta::save_data_as_text(file, *this);
file.close();
file.close();
}
bool data::equals(const data& data, double epsilon)
{
if (size() != data.size()
|| dimX() != data.dimX() || dimY() != data.dimY()
|| input_parametrization() != data.input_parametrization()
|| output_parametrization() != data.output_parametrization())
return false;
for(int i = 0; i < data.size(); i++)
{
vec other = data.get(i);
vec self = get(i);
if (self.size() != other.size()) // should not happen
return false;
for (int j = 0; j < self.size(); j++)
{
double diff = std::abs(self[j] - other[j]);
if (diff > epsilon)
return false;
}
}
return true;
if (size() != data.size()
|| _parameters.dimX() != data.parametrization().dimX()
|| _parameters.dimY() != data.parametrization().dimY()
|| (_parameters.input_parametrization()
!= data.parametrization().input_parametrization())
|| (_parameters.output_parametrization()
!= data.parametrization().output_parametrization()))
return false;
for(int i = 0; i < data.size(); i++)
{
vec other = data.get(i);
vec self = get(i);
if (self.size() != other.size()) // should not happen
return false;
for (int j = 0; j < self.size(); j++)
{
double diff = std::abs(self[j] - other[j]);
if (diff > epsilon)
return false;
}
}
return true;
}
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015 Inria
Copyright (C) 2013, 2014, 2015, 2016 Inria
This file is part of ALTA.
......@@ -16,6 +16,7 @@
#include <limits>
#include <fstream>
#include <cmath>
#include <cassert>
#include "common.h"
#include "args.h"
......@@ -24,46 +25,43 @@
#include "ptr.h"
//namespace alta {
// class data;
//}
//void load_data_from_binary(std::istream& in, const alta::arguments& header, alta::data& data);
namespace alta {
/*! \brief A data object. Allows to load data from files.
* \ingroup core
*/
class data : public parametrized
class data
{
public: // methods
data() : parametrized()
{}
public: // methods
data( unsigned int dim_X, unsigned int dim_Y)
: parametrized( dim_X, dim_Y )
{
}
data(const parameters &p, int size)
: _parameters(p), _size(size) {}
data(params::input in_param, params::output out_param)
: parametrized( in_param, out_param)
{
data(const parameters& p, int size, const vec& min, const vec& max)
: _parameters(p), _size(size), _min(min), _max(max)
{
assert(min.size() == p.dimX());
assert(max.size() == p.dimX());
}
}
/* TODO: Eventually mark the following constructors as deprecated. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
data() {}
// Virtual destructor
virtual ~data() {}
data(unsigned int dim_X, unsigned int dim_Y)
: _parameters(dim_X, dim_Y)
{}
#pragma GCC diagnostic pop
// Load data from a file
virtual void load(const std::string& filename) = 0 ;
virtual void load(const std::string& filename, const arguments& args) = 0 ;
// Virtual destructor
virtual ~data() {}
// Save the data to a file
virtual void save(const std::string& filename) const;
// Save the data to a file
virtual void save(const std::string& filename) const;
// Acces to data
virtual vec get(int i) const = 0 ;
// Acces to data
virtual vec get(int i) const = 0 ;
//! \brief Provide an evaluation of the data using interpolation. If
//! the data object does not provide an interpolation mechanism, it
......@@ -74,23 +72,41 @@ class data : public parametrized
//! match the total dimension: dimX + dimY.
virtual vec value(const vec& in) const = 0;
//! \brief Put the sample inside the data
virtual void set(const vec& x) = 0;
virtual void set(int i, const vec& x) = 0;
//! \brief Put the sample inside the data at index I.
virtual void set(int i, const vec& x) = 0;
// Get data size, e.g. the number of samples to fit
virtual int size() const = 0 ;
// Get data size, e.g. the number of samples to fit
int size() const { return _size; };
//! \brief Return true if this object is equal to DATA ±ε.
virtual bool equals(const data& data,
double epsilon =
//! \brief Return true if this object is equal to DATA ±ε.
virtual bool equals(const data& data,
double epsilon =
std::pow(1.0, -int(std::numeric_limits<double>::digits10 - 1)));
friend void load_data_from_binary(std::istream& in, const alta::arguments& header,
alta::data& data);
protected: // data
const parameters& parametrization() const {
return _parameters;
}
void setParametrization(const parameters& p) {
_parameters = p;
}
/* Maximum values of the data */
//! \brief Get the minimum value the input can take
const vec& min() const { return _min; };
//! \brief Get the maximum value the input can take
const vec& max() const { return _max; };
protected: // data
parameters _parameters;
int _size;
vec _min, _max;
} ;
/*! \brief Change the parametrization of data to fit the parametrization of the
......@@ -102,88 +118,62 @@ class data : public parametrized
*/
class data_params : public data
{
public: // structures
//! \brief when changing from a parametrization to another, you might
//! lose some dimensions. This list enumerate the different operators
//! that can be applied on the raw data to be clusterized.
//! \note by default we use <em>none</em>, but if the input space
//! dimension is reduced, the program will halt.
enum clustering
{
MEAN,
MEDIAN,
NONE
};
public: // methods
//! \brief contructor requires the definition of a base class that
//! has a parametrization, and a new parametrization.
data_params(const ptr<data> d, params::input new_param,
data_params::clustering method = data_params::NONE) :
_clustering_method(method)
{
setParametrization(new_param);
setParametrization(d->output_parametrization());
_nX = params::dimension(new_param);
_nY = d->dimY();
std::cout << "<<INFO>> Reparametrization of the data" << std::endl;
//TODO
//clustering<data>(d, _nY, d->parametrization(), new_param, _data);
std::cout << "<<INFO>> clustering left " << _data.size() << "/" << d->size() << " elements" << std::endl;
save(std::string("cluster.gnuplot"));
}
virtual vec value(const vec&) const
{
NOT_IMPLEMENTED();
}
// Load data from a file
virtual void load(const std::string&)
{
std::cerr << "<<ERROR>> this data type cannot load data" << std::endl;
throw;
}
virtual void load(const std::string&, const arguments&)
{
std::cerr << "<<ERROR>> this data type cannot load data" << std::endl;
throw;
}
// Acces to data
virtual vec get(int i) const
{
return _data[i];
}
//! \todo This should crash at execution.
virtual void set(const vec& x)
{
this->set(x);
}
virtual void set(int i, const vec& x)
{
this->set(i, x);
}
// Get data size, e.g. the number of samples to fit
virtual int size() const
{
return _data.size();
}
protected: // data
data_params::clustering _clustering_method;
std::vector<vec> _data;
public: // structures
//! \brief when changing from a parametrization to another, you might
//! lose some dimensions. This list enumerate the different operators
//! that can be applied on the raw data to be clusterized.
//! \note by default we use <em>none</em>, but if the input space
//! dimension is reduced, the program will halt.
enum clustering
{
MEAN,
MEDIAN,
NONE