Commit 5ae8457a authored by Ludovic Courtès's avatar Ludovic Courtès

core: 'data' aggregates 'parameters' instead of inheriting from it.

Suggested by Romain Pacanowski.
parent 9173d803
/* 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,58 @@ 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;
}
void data::setMin(const vec& min)
{
#ifdef DEBUG
assert(min.size() == _nX) ;
#endif
_min = min ;
}
void data::setMax(const vec& max)
{
#ifdef DEBUG
assert(max.size() == _nX) ;
#endif
_max = max ;
}
......@@ -34,36 +34,28 @@ namespace alta {
/*! \brief A data object. Allows to load data from files.
* \ingroup core
*/
class data : public parametrized
class data
{
public: // methods
public: // methods
data() : parametrized()
{}
data() {}
data( unsigned int dim_X, unsigned int dim_Y)
: parametrized( dim_X, dim_Y )
{
}
data(unsigned int dim_X, unsigned int dim_Y)
: _parameters(dim_X, dim_Y)
{}
data(params::input in_param, params::output out_param)
: parametrized( in_param, out_param)
{
// Virtual destructor
virtual ~data() {}
}
// 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;
// Load data from a file
virtual void load(const std::string& filename) = 0 ;
virtual void load(const std::string& filename, const arguments& args) = 0 ;
// 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,24 +66,51 @@ 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
virtual void set(const vec& x) = 0;
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
virtual int size() const = 0 ;
//! \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);
friend void load_data_from_binary(std::istream& in, const alta::arguments& header,
alta::data& data);
const parameters& parametrization() const {
return _parameters;
}
void setParametrization(const parameters& p) {
_parameters = p;
}
/* Maximum values of the data */
//! \brief Set the minimum value the input can take
void setMin(const vec& min) ;
//! \brief Set the maximum value the input can take
void setMax(const vec& max) ;
//! \brief Get the minimum value the input can take
// FIXME: Return a reference.
vec min() const { return _min; };
//! \brief Get the maximum value the input can take
vec max() const { return _max; };
protected: // data
protected: // data
parameters _parameters;
vec _min, _max;
} ;
/*! \brief Change the parametrization of data to fit the parametrization of the
......@@ -103,88 +122,88 @@ 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
};
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)
{
_parameters.setParametrization(new_param);
_parameters.setParametrization(d->parametrization().output_parametrization());
_parameters.setDimX(params::dimension(new_param));
_parameters.setDimY(d->parametrization().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;
};
}
......
This diff is collapsed.
......@@ -178,9 +178,11 @@ double function::L2_distance(const ptr<data>& d) const
}
else
{
params::convert(&dat[0], d->input_parametrization(), input_parametrization(), &x[0]);
params::convert(&dat[0],
d->parametrization().input_parametrization(),
input_parametrization(), &x[0]);
}
memcpy(&y[0], &dat[d->dimX()], dimY()*sizeof(double));
memcpy(&y[0], &dat[d->parametrization().dimX()], dimY()*sizeof(double));
l2_dist += std::pow(norm(y-value(x)), 2);
}
......@@ -215,16 +217,19 @@ double function::Linf_distance(const ptr<data>& d) const
}
else
{
params::convert(&dat[0], d->input_parametrization(), input_parametrization(), &x[0]);
params::convert(&dat[0],
d->parametrization().input_parametrization(),
input_parametrization(), &x[0]);
}
// Copy the value part of the data vector in a vector to perform vector
// operations on it (used in the computation of the mean).
memcpy(&y[0], &dat[d->dimX()], d->dimY()*sizeof(double));
memcpy(&y[0], &dat[d->parametrization().dimX()],
d->parametrization().dimY() * sizeof(double));
// Take the componentwise-max of the two vectors.
const vec v = value(x);
for(int j=0; j<d->dimY(); ++j)
for(int j=0; j<d->parametrization().dimY(); ++j)
{
linf_dist = std::max<double>(linf_dist, std::abs(y[j]-v[j]));
}
......@@ -237,7 +242,7 @@ double function::Linf_distance(const ptr<data>& d) const
for(int i=0; i<d->size(); ++i)
{
vec dat = d->get(i);
vec x(dimX()), y(d->dimY()), val(dimY());
vec x(dimX()), y(d->parametrization().dimY()), val(dimY());
// Convert the position of the data sample to the parametrization
// of the function.
......@@ -247,17 +252,20 @@ double function::Linf_distance(const ptr<data>& d) const
}
else
{
params::convert(&dat[0], d->input_parametrization(), input_parametrization(), &x[0]);
params::convert(&dat[0],
d->parametrization().input_parametrization(),
input_parametrization(),
&x[0]);
}
// Copy the value part of the data vector in a vector to perform vector
// operations on it (used in the computation of the mean).
memcpy(&y[0], &dat[d->dimX()], dimY()*sizeof(double));
memcpy(&y[0], &dat[d->parametrization().dimX()], dimY()*sizeof(double));
val = value(x);
for(int j=0; j<d->dimY(); ++j)
for(int j=0; j<d->parametrization().dimY(); ++j)
{
y[j] = dat[d->dimX()+j];
y[j] = dat[d->parametrization().dimX()+j];
var[j] += pow(mean[j] - (val[j]-y[j]), 2) / double(d->size());
}
}
......@@ -400,7 +408,8 @@ vec compound_function::value(const vec& x) const
for(unsigned int i=0; i<fs.size(); ++i)
{
vec temp_x(fs[i]->dimX());
params::convert(&x[0], input_parametrization(), fs[i]->input_parametrization(), &temp_x[0]);
params::convert(&x[0], input_parametrization(),
fs[i]->input_parametrization(), &temp_x[0]);
res = res + fs[i]->value(temp_x);
}
return res;
......@@ -424,7 +433,8 @@ vec compound_function::parametersJacobian(const vec& x) const
{
vec temp_x(func->dimX());
params::convert(&x[0], input_parametrization(), func->input_parametrization(), &temp_x[0]);
params::convert(&x[0], input_parametrization(),
func->input_parametrization(), &temp_x[0]);
vec func_jac = func->parametersJacobian(temp_x);
for(int i=0; i<nb_f_params; ++i)
......
......@@ -8,8 +8,8 @@ void errors::compute(const data* in, const data* ref,
const int size = checkMaskSize(ref, mask);
//Here we go new way and faster because we evaluate the function just once
Eigen::MatrixXd ref_y = Eigen::MatrixXd::Zero(size, ref->dimY());
Eigen::MatrixXd inp_y = Eigen::MatrixXd::Zero(size, ref->dimY()) ;
Eigen::MatrixXd ref_y = Eigen::MatrixXd::Zero(size, ref->parametrization().dimY());
Eigen::MatrixXd inp_y = Eigen::MatrixXd::Zero(size, ref->parametrization().dimY()) ;
#ifdef DEBUG
timer t;
......@@ -23,12 +23,12 @@ void errors::compute(const data* in, const data* ref,
#endif
// Ouput norms
Eigen::VectorXd L1_norm = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd L2_norm = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd L3_norm = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd LInf_norm = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd mse = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd rmse = Eigen::VectorXd::Zero(ref->dimY());
Eigen::VectorXd L1_norm = Eigen::VectorXd::Zero(ref->parametrization().dimY());
Eigen::VectorXd L2_norm = Eigen::VectorXd::Zero(ref->parametrization().dimY());
Eigen::VectorXd L3_norm = Eigen::VectorXd::Zero(ref->parametrization().dimY());
Eigen::VectorXd LInf_norm = Eigen::VectorXd::Zero(ref->parametrization().dimY());
Eigen::VectorXd mse = Eigen::VectorXd::Zero(ref->parametrization().dimY());
Eigen::VectorXd rmse = Eigen::VectorXd::Zero(ref->parametrization().dimY());
#ifdef DEBUG
t.start();
......@@ -78,14 +78,14 @@ void errors::evaluate(const data* inp,
Eigen::MatrixXd& ref_y) {
// Temp variables
vec ref_xy = vec::Zero(ref->dimX() + ref->dimY());
vec ref_x = vec::Zero(ref->dimX());
vec dat_x = vec::Zero(inp->dimX());
vec ref_xy = vec::Zero(ref->parametrization().dimX() + ref->parametrization().dimY());
vec ref_x = vec::Zero(ref->parametrization().dimX());
vec dat_x = vec::Zero(inp->parametrization().dimX());
vec cart = vec::Zero(6);
// Constants
const auto nY = ref->dimY();
const auto nX = ref->dimX();
const auto nY = ref->parametrization().dimY();
const auto nX = ref->parametrization().dimX();
// Is there a mask function to be applied
const bool has_mask = mask != nullptr;
......@@ -102,7 +102,7 @@ void errors::evaluate(const data* inp,
ref_x = ref_xy.head(nX);
params::convert(ref_x.data(),
ref->input_parametrization(),
ref->parametrization().input_parametrization(),
params::CARTESIAN,
cart.data());
......@@ -114,7 +114,7 @@ void errors::evaluate(const data* inp,
// Convert to the query data `dat` parametrization
params::convert(cart.data(),
params::CARTESIAN,
inp->input_parametrization(),
inp->parametrization().input_parametrization(),
dat_x.data());
ref_y.row(i) = ref_xy.tail(nY);
......@@ -122,9 +122,9 @@ void errors::evaluate(const data* inp,
/*
params::convert(inp->value(dat_x).data(),
inp->output_parametrization(),
inp->dimY(),
inp->parametrization().dimY(),
ref->output_parametrization(),
ref->dimY(),
ref->parametrization().dimY(),
inp_y.row(i).data());
*/
} else {
......
/* 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.
......@@ -831,27 +831,3 @@ void params::print_input_params()
std::cout << it->second.info << std::endl;
}
}
// Acces to the domain of definition of the function
void parametrized::setMin(const vec& min)
{
#ifdef DEBUG
assert(min.size() == _nX) ;
#endif
_min = min ;
}
void parametrized::setMax(const vec& max)
{
#ifdef DEBUG
assert(max.size() == _nX) ;
#endif
_max = max ;
}
vec parametrized::min() const
{
return _min ;
}
vec parametrized::max() const
{
return _max ;
}
This diff is collapsed.
This diff is collapsed.
......@@ -44,7 +44,7 @@ vertical_segment::initializeToZero( unsigned int number_of_data_elements )
{
_data.clear();
unsigned int const size_of_one_element = dimX() + 3*dimY();
unsigned int const size_of_one_element = _parameters.dimX() + 3*_parameters.dimY();
for( unsigned int i=0; i < number_of_data_elements; i++)
{
......@@ -103,25 +103,25 @@ void vertical_segment::get(int i, vec& x, vec& yl, vec& yu) const
#ifdef DEBUG
assert(i >= 0 && i < _data.size());
#endif
x.resize(dimX()); yl.resize(dimY()) ; yu.resize(dimY()) ;
for(int j=0; j<dimX(); ++j)
x.resize(_parameters.dimX()); yl.resize(_parameters.dimY()) ; yu.resize(_parameters.dimY()) ;
for(int j=0; j<_parameters.dimX(); ++j)
{
x[j] = _data[i][j];
}
for(int j=0; j<dimY(); ++j)
for(int j=0; j<_parameters.dimY(); ++j)
{
yl[j] = _data[i][dimX() + 1*dimY() + j];
yu[j] = _data[i][dimX() + 2*dimY() + j];
yl[j] = _data[i][_parameters.dimX() + 1*_parameters.dimY() + j];
yu[j] = _data[i][_parameters.dimX() + 2*_parameters.dimY() + j];
}
}
void vertical_segment::get(int i, vec& yl, vec& yu) const
{
yl.resize(dimY()) ; yu.resize(dimY()) ;
for(int j=0; j<dimY(); ++j)
yl.resize(_parameters.dimY()) ; yu.resize(_parameters.dimY()) ;
for(int j=0; j<_parameters.dimY(); ++j)
{
yl[j] = _data[i][dimX() + dimY() + j] ;
yu[j] = _data[i][dimX() + 2*dimY() + j] ;
yl[j] = _data[i][_parameters.dimX() + _parameters.dimY() + j] ;
yu[j] = _data[i][_parameters.dimX() + 2*_parameters.dimY() + j] ;
}
}
......@@ -129,7 +129,7 @@ vec vertical_segment::get(int i) const
{
//SLOW !!!!! and useless
// call _data[i]
const int n = dimX() + dimY();
const int n = _parameters.dimX() + _parameters.dimY();
vec res = _data[i].head(n);
return res ;
......@@ -141,10 +141,10 @@ void vertical_segment::set(const vec& x)
{
// Check if the input data 'x' has the size of a vertical segment (i.e. dimX+3*dimY),
// if it only has the size of a single value, then create the segment.
if(x.size() == dimX() + 3*dimY()) {
if(x.size() == _parameters.dimX() + 3*_parameters.dimY()) {
_data.push_back(x);
} else if(x.size() == dimX() + dimY()) {
} else if(x.size() == _parameters.dimX() + _parameters.dimY()) {
_data.push_back(vs(x));
} else {
......@@ -157,10 +157,10 @@ void vertical_segment::set(int i, const vec& x)
{
// Check if the input data 'x' has the size of a vertical segment (i.e. dimX+3*dimY),
// if it only has the size of a single value, then create the segment.
if(x.size() == dimX() + 3*dimY()) {
if(x.size() == _parameters.dimX() + 3*_parameters.dimY()) {
_data[i] = x;
} else if(x.size() == dimX() + dimY()) {
} else if(x.size() == _parameters.dimX() + _parameters.dimY()) {
_data[i] = vs(x);
} else {
......@@ -175,19 +175,19 @@ int vertical_segment::size() const
}
vec vertical_segment::vs(const vec& x) const {
vec y(dimX() + 3*dimY());
vec y(_parameters.dimX() + 3*_parameters.dimY());
// Copy the head of each vector
y.head(dimX() + dimY()) = x.head(dimX() + dimY());
y.head(_parameters.dimX() + _parameters.dimY()) = x.head(_parameters.dimX() + _parameters.dimY());
for(unsigned int i=0; i<dimY(); ++i) {
const double val = x[i + dimX()];
for(unsigned int i=0; i<_parameters.dimY(); ++i) {
const double val = x[i + _parameters.dimX()];
if(_is_absolute) {
y[i + dimX()+1*dimY()] = val - _dt;
y[i + dimX()+2*dimY()] = val + _dt;
y[i + _parameters.dimX()+1*_parameters.dimY()] = val - _dt;
y[i + _parameters.dimX()+2*_parameters.dimY()] = val + _dt;
} else {
y[i + dimX()+1*dimY()] = val * (1.0 - _dt);
y[i + dimX()+2*dimY()] = val * (1.0 + _dt);
y[i + _parameters.dimX()+1*_parameters.dimY()] = val * (1.0 - _dt);
y[i + _parameters.dimX()+2*_parameters.dimY()] = val * (1.0 + _dt);
}
}
......