Commit c966a9f5 authored by Laurent Belcour's avatar Laurent Belcour

Fixing plugins one at a time

parent 76cbec45
......@@ -5,7 +5,7 @@
#include <string>
// Interface
//#include <QObject>
#include <QObject>
#include "function.h"
#include "data.h"
#include "fitter.h"
......@@ -47,14 +47,14 @@ class rational_function : public function
void save_rational_function(const std::string& filename) const ;
void save_gnuplot(const std::string& filename, const data* d, const arguments& args) const ;
private: // functions
protected: // functions
// Convert an index in N to a vector of degree for a
// multinomial coeffcient. The resulting vector v should
// be used as prod_k x[k]^v[k]
std::vector<int> index2degree(int i) const ;
private: // data
protected: // data
// Store the coefficients for the moment, I assume
// the functions to be polynomials.
......
TEMPLATE = subdirs
SUBDIRS = rational_function \
rational_data \
SUBDIRS = \
# rational_function \
rational_fitter_cgal \
rational_fitter_quadprog \
rational_fitter_quadproge \
rational_fitter_eigen \
rational_fitter_matlab
rational_fitter_cgal.depends = rational_function rational_data
rational_fitter_quadprog.depends = rational_function rational_data
rational_fitter_quadproge.depends = rational_function rational_data
rational_fitter_eigen.depends = rational_function rational_data
rational_fitter_matlab.depends = rational_function rational_data
#include "rational_data.h"
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>
void rational_data::load(const std::string& filename)
{
arguments args ;
load(filename, args) ;
}
void rational_data::load(const std::string& filename, const arguments& args)
{
std::ifstream file(filename.c_str()) ;
if(!file.is_open())
{
std::cerr << "<<ERROR>> unable to open file \"" << filename << "\"" << std::endl ;
}
double min, max ;
min = args.get_float("min", -std::numeric_limits<double>::max()) ;
max = args.get_float("max", std::numeric_limits<double>::max()) ;
_nX = 0 ; _nY = 0 ;
std::vector<int> vs ; int current_vs = 0 ;
double x, y, dy ;
while(file.good())
{
std::string line ;
std::getline(file, line) ;
std::stringstream linestream(line) ;
// Discard incorrect lines
if(linestream.peek() == '#')
{
linestream.ignore(1) ;
std::string comment ;
linestream >> comment ;
if(comment == std::string("DIM"))
{
linestream >> _nX >> _nY ;
vs.assign(dimY(), 0) ;
for(int k=0; k<dimY(); ++k)
{
vs[k] = 0 ;
}
_min.resize(dimX()) ;
_max.resize(dimX()) ;
for(int k=0; k<dimX(); ++k)
{
_min[k] = std::numeric_limits<double>::max() ;
_max[k] = -std::numeric_limits<double>::max() ;
}
}
else if(comment == std::string("VS"))
{
int t ;
linestream >> t ;
vs[current_vs] = t ; ++current_vs ;
}
continue ;
}
else if(line.empty()/*!boost::regex_match(line,e)*/)
{
continue ;
}
vec v ;
v.resize(dimX() + 3*dimY()) ;
for(int i=0; i<dimX(); ++i)
linestream >> v[i] ;
for(int i=0; i<dimY(); ++i)
linestream >> v[dimX() + i] ;
for(int i=0; i<dimY(); ++i)
{
// TODO, the firts case does not account for the
// dimension of the ouput vector
if(vs[i] == 2)
{
linestream >> v[dimX() + dimY()+i] ;
linestream >> v[dimX() + 2*dimY()+i] ;
}
else if(vs[i] == 1)
{
double dt ;
linestream >> dt ;
v[dimX() + dimY()+i] = v[dimX() + i] * (1.0f - dt) ;
v[dimX() + 2*dimY()+i] = v[dimX() + i] * (1.0f + dt) ;
}
else
{
// TODO Specify the delta in case
// Handle multiple dim
float dt = args.get_float("dt", 0.1);
v[dimX() + dimY()+i] = v[dimX() + i] * (1.0f - dt) ;
v[dimX() + 2*dimY()+i] = v[dimX() + i] * (1.0f + dt) ;
}
}
// If data is not in the interval of fit
// TODO: Update to more dims
bool is_in = true ;
for(int i=0; i<dimX(); ++i)
{
if(v[i] < min || v[i] > max)
{
is_in = false ;
}
}
if(!is_in)
{
continue ;
}
_data.push_back(v) ;
// Update min and max
for(int k=0; k<dimX(); ++k)
{
_min[k] = std::min(_min[k], v[k]) ;
_max[k] = std::max(_max[k], v[k]) ;
}
}
//TODO Test for small data
/* std::vector<std::vector<double> > temp ;
std::ofstream temp_out("temp.gnuplot", std::ios_base::trunc) ;
for(int i=0; i<20; ++i)
{
int k = (i * _data.size()) / 20 ;
temp_out << _data[k][0] << "\t" << _data[k][1] << "\t" << 0.5*(_data[k][2] - _data[k][1]) << std::endl ;
temp.push_back(_data[k]) ;
}
_data = temp ;
*/
// Sort the vector
// std::sort(_data.begin(), _data.end(), [](const std::vector<double>& a, const std::vector<double>& b){return (a[0]<b[0]);});
std::cout << "<<INFO>> loaded file \"" << filename << "\"" << std::endl ;
std::cout << "<<INFO>> data inside " << _min << " ... " << _max << std::endl ;
std::cout << "<<INFO>> loading data file of R^" << dimX() << " -> R^" << dimY() << std::endl ;
std::cout << "<<INFO>> " << _data.size() << " elements to fit" << std::endl ;
}
bool rational_data::get(int i, double& x, double& yl, double& yu) const
{
if(i >= (int)_data.size())
{
return false ;
}
x = _data[i][0] ;
yl = _data[i][1] ;
yu = _data[i][2] ;
return true ;
}
void rational_data::get(int i, vec& yl, vec& yu) const
{
yl.resize(dimY()) ; yu.resize(dimY()) ;
for(int j=0; j<dimY(); ++j)
{
yl[j] = _data[i][dimX() + dimY() + j] ;
yu[j] = _data[i][dimX() + 2*dimY() + j] ;
}
}
const vec& rational_data::operator[](int i) const
{
return _data[i] ;
}
const vec& rational_data::get(int i) const
{
return _data[i] ;
}
int rational_data::size() const
{
return _data.size() ;
}
vec rational_data::min() const
{
return _min ;
}
vec rational_data::max() const
{
return _max ;
}
//Q_EXPORT_PLUGIN2(rational_data, rational_data)
#pragma once
// Include STL
#include <vector>
#include <string>
// Interface
//#include <QObject>
#include <core/function.h>
#include <core/data.h>
#include <core/fitter.h>
#include <core/args.h>
class rational_data : /*public QObject,*/ public data
{
/*
Q_OBJECT
Q_INTERFACES(data)
*/
public: // methods
// Load data from a file
virtual void load(const std::string& filename) ;
virtual void load(const std::string& filename, const arguments& args) ;
// Acces to data
virtual bool get(int i, double& x, double& yl, double& yu) const ;
virtual const vec& get(int i) const ;
virtual void get(int i, vec& yl, vec& yu) const ;
virtual const vec& operator[](int i) const ;
// Get data size
virtual int size() const ;
// Get min and max input parameters
virtual vec min() const ;
virtual vec max() const ;
private: // data
// Store for each point of data, the upper
// and lower value
std::vector<vec> _data ;
// Store the min and max value on the input
// domain
vec _min, _max ;
} ;
TEMPLATE = lib
CONFIG *= static \
qt \
DESTDIR = ../../build
INCLUDEPATH += ../..
HEADERS = rational_data.h
SOURCES = rational_data.cpp
#QMAKE_CXXFLAGS += -frounding-math -fPIC
......@@ -153,12 +153,7 @@ bool rational_fitter_cgal::fit_data(const vertical_segment* d, int np, int nq, i
double a1_norm = 0.0 ;
vec xi = d->get(i) ;
/*
for(int k=0; k<d->dimX(); ++k)
{
xi[k] /= dmax[k] ;
}
*/
// A row of the constraint matrix has this
// form: [p_{0}(x_i), .., p_{np}(x_i), -f(x_i) q_{0}(x_i), .., -f(x_i) q_{nq}(x_i)]
// For the lower constraint and negated for
......
......@@ -13,12 +13,10 @@
#include <QTime>
#include <rational_function.h>
#include <rational_data.h>
data* rational_fitter_quadprog::provide_data() const
{
return new rational_data() ;
return new vertical_segment() ;
}
function* rational_fitter_quadprog::provide_function() const
......@@ -36,7 +34,7 @@ rational_fitter_quadprog::~rational_fitter_quadprog()
bool rational_fitter_quadprog::fit_data(const data* dat, function* fit)
{
rational_function* r = dynamic_cast<rational_function*>(fit) ;
const rational_data* d = dynamic_cast<const rational_data*>(dat) ;
const vertical_segment* d = dynamic_cast<const vertical_segment*>(dat) ;
if(r == NULL || d == NULL)
{
std::cerr << "<<ERROR>> not passing the correct class to the fitter" << std::endl ;
......@@ -97,7 +95,7 @@ void rational_fitter_quadprog::set_parameters(const arguments& args)
}
bool rational_fitter_quadprog::fit_data(const rational_data* d, int np, int nq, rational_function* r)
bool rational_fitter_quadprog::fit_data(const vertical_segment* d, int np, int nq, rational_function* r)
{
// Multidimensional coefficients
......@@ -121,10 +119,10 @@ bool rational_fitter_quadprog::fit_data(const rational_data* d, int np, int nq,
// np and nq are the degree of the RP to fit to the data
// y is the dimension to fit on the y-data (e.g. R, G or B for RGB signals)
// the function return a ration BRDF function and a boolean
bool rational_fitter_quadprog::fit_data(const rational_data* dat, int np, int nq, int ny, rational_function* rf)
bool rational_fitter_quadprog::fit_data(const vertical_segment* dat, int np, int nq, int ny, rational_function* rf)
{
rational_function* r = dynamic_cast<rational_function*>(rf) ;
const rational_data* d = dynamic_cast<const rational_data*>(dat) ;
const vertical_segment* d = dynamic_cast<const vertical_segment*>(dat) ;
if(r == NULL || d == NULL)
{
std::cerr << "<<ERROR>> not passing the correct class to the fitter" << std::endl ;
......
......@@ -7,13 +7,12 @@
// Interface
#include <QObject>
#include <core/function.h>
#include <core/rational_function.h>
#include <core/data.h>
#include <core/vertical_segment.h>
#include <core/fitter.h>
#include <core/args.h>
#include <rational_function.h>
#include <rational_data.h>
class rational_fitter_quadprog : public QObject, public fitter
{
......@@ -42,8 +41,8 @@ class rational_fitter_quadprog : public QObject, public fitter
// Fitting a data object using np elements in the numerator and nq
// elements in the denominator
virtual bool fit_data(const rational_data* d, int np, int nq, rational_function* fit) ;
virtual bool fit_data(const rational_data* dat, int np, int nq, int ny, rational_function* fit) ;
virtual bool fit_data(const vertical_segment* d, int np, int nq, rational_function* fit) ;
virtual bool fit_data(const vertical_segment* dat, int np, int nq, int ny, rational_function* fit) ;
// min and Max usable np and nq values for the fitting
int _max_np, _max_nq ;
......
......@@ -7,104 +7,20 @@
#include <algorithm>
#include <cmath>
rational_function::rational_function() : a(), b()
rational_function_chebychev::rational_function_chebychev() : rational_function()
{
}
rational_function::rational_function(const std::vector<double>& a,
const std::vector<double>& b) :
a(a), b(b)
rational_function_chebychev::rational_function_chebychev(const std::vector<double>& a,
const std::vector<double>& b) : rational_function(a, b)
{
}
rational_function::~rational_function()
rational_function_chebychev::~rational_function_chebychev()
{
}
void rational_function::update(const std::vector<double>& in_a,
const std::vector<double>& in_b)
{
a.reserve(in_a.size()) ;
b.reserve(in_b.size()) ;
a = in_a ;
b = in_b ;
}
// Overload the function operator
vec rational_function::value(const vec& x) const
{
vec res(_nY) ;
unsigned int const np = a.size() / _nY ;
unsigned int const nq = b.size() / _nY ;
for(int k=0; k<_nY; ++k)
{
double p = 0.0f ;
double q = 0.0f ;
for(unsigned int i=0; i<np; ++i)
{
p += a[k*_nY + i]*this->p(x, i) ;
}
for(unsigned int i=0; i<nq; ++i)
{
q += b[k*_nY + i]*this->q(x, i) ;
}
res[k] = p/q ;
}
return res ;
}
void populate(std::vector<int>& vec, int N, int k, int j)
{
vec[0] = k ;
if(j == 0)
return ;
int tj = j ;
while(tj != 0)
{
// First non null index
int nn_index = 0; while(vec[nn_index] == 0) { nn_index = (nn_index+1) % N ; }
// Index of the place where to append
int ap_index = (nn_index + 1) % N ; while(vec[ap_index] == k) { ap_index = (ap_index+1) % N ; }
vec[nn_index] -= 1;
vec[ap_index] += 1;
--tj;
}
}
std::vector<int> rational_function::index2degree(int i) const
{
std::vector<int> deg ; deg.assign(dimX(), 0) ;
if(i == 0)
return deg ;
// Calculate the power (number of elements to put in
// the vector) at which the index is definite.
int Nk = 1 ;
int nk = dimX() ;
int k = 1 ;
while(!(i >= Nk && i < Nk+nk))
{
Nk += nk ;
nk *= dimX() ;
++k ;
}
// Populate the vector from front to back
int j = i-Nk ;
populate(deg, dimX(), k, j) ;
return deg ;
}
double legendre(double x, int i)
double chebychev(double x, int i)
{
if(i == 0)
{
......@@ -116,126 +32,33 @@ double legendre(double x, int i)
}
else
{
return ((2*i-1)*x*legendre(x, i-1) - (i-1)*legendre(x, i-2)) / (double)i ;
return 2.0*x*chebychev(x, i-1) - chebychev(x, i-2) ;
}
}
// Get the p_i and q_j function
double rational_function::p(const vec& x, int i) const
double rational_function_chebychev::p(const vec& x, int i) const
{
std::vector<int> deg = index2degree(i);
double res = 1.0;
for(int k=0; k<dimX(); ++k)
{
#ifdef POLYNOMIALS
res *= pow(x[k], deg[k]) ;
#else // LEGENDRE
res *= legendre(x[k], deg[k]);
#endif
res *= chebychev(x[k], deg[k]);
}
return res ;
}
double rational_function::q(const vec& x, int i) const
double rational_function_chebychev::q(const vec& x, int i) const
{
std::vector<int> deg = index2degree(i);
double res = 1.0;
for(int k=0; k<dimX(); ++k)
{
#ifdef POLYNOMIALS
res *= pow(x[k], deg[k]) ;
#else // LEGENDRE
res *= legendre(x[k], deg[k]);
#endif
res *= chebychev(x[k], deg[k]);
}
return res ;
}
// IO function to text files
void rational_function::load(const std::string& filename)
{
}
void rational_function::save(const std::string& filename, const arguments& args) const
{
save_rational_function(filename) ;
}
void rational_function::save_gnuplot(const std::string& filename, const data* d, const arguments& args) const
{
std::ofstream file(filename.c_str(), std::ios_base::trunc);
for(int i=0; i<d->size(); ++i)
{
vec v = d->get(i) ;
// vec y1 ; y1.assign(d->dimY(), 0.0) ;
// for(int k=0; k<d->dimY(); ++k) { y1[k] = v[d->dimX() + k] ; }
vec y2 = value(v) ;
for(int u=0; u<d->dimX(); ++u)
file << v[u] << "\t" ;
for(int u=0; u<d->dimY(); ++u)
file << y2[u] << "\t" ;
file << std::endl ;
}
}
void rational_function::save_rational_function(const std::string& filename) const
{
std::ofstream file(filename.c_str(), std::ios_base::trunc);
file << "#DIM " << _nX << " " << _nY << std::endl ;
file << "#NP " << a.size() / _nY << std::endl ;
file << "#NQ " << b.size() / _nY << std::endl ;
file << "#BASIS poly" << std::endl ;
for(unsigned int i=0; i<a.size() / _nY; ++i)
{
std::vector<int> index = index2degree(i) ;
for(unsigned int j=0; j<index.size(); ++j)
{
file << index[j] << "\t" ;
}
file << a[i] << std::endl ;
}
for(unsigned int i=0; i<b.size(); ++i)
{
std::vector<int> index = index2degree(i) ;
for(unsigned int j=0; j<index.size() / _nY; ++j)
{
file << index[j] << "\t" ;
}
file << b[i] << std::endl ;
}
}
std::ostream& operator<< (std::ostream& out, const rational_function& r)
{
std::cout << "p = [" ;
for(unsigned int i=0; i<r.a.size(); ++i)