/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions Copyright (C) 2013, 2014, 2015 Inria This file is part of ALTA. This Source Code Form is subject to the terms of the Mozilla Public 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/. */ #include "data.h" #include "data_storage.h" #include "vertical_segment.h" #include #include #include #ifdef __GLIBC__ # include #endif void vertical_segment::load_data_from_text(std::istream& input, const header& header, vertical_segment& result, const arguments& args) { vec min, max ; vec ymin, ymax; result._nX = 0 ; result._nY = 0 ; std::pair dim = header["DIM"]; result._nX = dim.first; result._nY = dim.second; result._min.resize(result.dimX()) ; result._max.resize(result.dimX()) ; min = args.get_vec("min", result._nX, -std::numeric_limits::max()) ; max = args.get_vec("max", result._nX, std::numeric_limits::max()) ; #ifdef DEBUG std::cout << "<> data will remove outside of " << min << " -> " << max << " x-interval" << std::endl; #endif ymin = args.get_vec("ymin", result._nY, -std::numeric_limits::max()) ; ymax = args.get_vec("ymax", result._nY, std::numeric_limits::max()) ; #ifdef DEBUG std::cout << "<> data will remove outside of " << ymin << " -> " << ymax << " y-interval" << std::endl; #endif for(int k=0; k::max() ; result._max[k] = -std::numeric_limits::max() ; } result._in_param = params::parse_input(header["PARAM_IN"]); result._out_param = params::parse_output(header["PARAM_OUT"]); int vs_value = header["VS"]; // Now read the body. while(input.good()) { std::string line ; std::getline(input, line) ; std::stringstream linestream(line) ; // Discard comments and empty lines. if(line.empty() || linestream.peek() == '#') { continue ; } else { // Read the data point x and y coordinates vec v = vec::Zero(result.dimX() + 3*result.dimY()) ; for(int i=0; i> v[i] ; } // If data is not in the interval of fit bool is_in = true ; for(int i=0; i max[i]) { is_in = false ; } } for(int i=0; i ymax[i]) { is_in = false ; } } if(!is_in) { continue ; } // /* // Correction of the data by 1/cosine(theta_L) double factor = 1.0; if(args.is_defined("data-correct-cosine")) { double cart[6]; params::convert(&v[0], result.input_parametrization(), params::CARTESIAN, cart); if(cart[5] > 0.0 && cart[2] > 0.0) { factor = 1.0/cart[5]*cart[2]; for(int i=0; i> min_dt ; linestream >> max_dt ; min_dt = min_dt-v[result.dimX()+i]; max_dt = max_dt-v[result.dimX()+i]; } else if(i == 0 && vs_value == 1) { double dt ; linestream >> dt ; min_dt = -dt; max_dt = dt; } else { double dt = args.get_float("dt", 0.1f); min_dt = -dt; max_dt = dt; } if(args.is_defined("dt-relative")) { v[result.dimX() + result.dimY()+i] = v[result.dimX() + i] * (1.0 + min_dt) ; v[result.dimX() + 2*result.dimY()+i] = v[result.dimX() + i] * (1.0 + max_dt) ; } else if(args.is_defined("dt-max")) { v[result.dimX() + result.dimY()+i] = v[result.dimX() + i] + std::max(v[result.dimX() + i] * min_dt, min_dt); v[result.dimX() + 2*result.dimY()+i] = v[result.dimX() + i] + std::max(v[result.dimX() + i] * max_dt, max_dt); } else { v[result.dimX() + result.dimY()+i] = v[result.dimX() + i] + min_dt ; v[result.dimX() + 2*result.dimY()+i] = v[result.dimX() + i] + max_dt ; } // You can enforce the vertical segment to stay in the positive // region using the --data-positive command line argument. Note // that the data point is also clamped to zero if negative. if(args.is_defined("dt-positive")) { v[result.dimX() + i] = std::max(v[result.dimX() + i], 0.0); v[result.dimX() + result.dimY()+i] = std::max(v[result.dimX() + result.dimY()+i], 0.0); v[result.dimX() + 2*result.dimY()+i] = std::max(v[result.dimX() + 2*result.dimY()+i], 0.0); } #ifdef DEBUG std::cout << "<> vs = [" << v[result.dimX() + result.dimY()+i] << ", " << v[result.dimX() + 2*result.dimY()+i] << "]" << std::endl; #endif } result._data.push_back(v) ; // Update min and max for(int k=0; k> loaded input stream" << std::endl ; std::cout << "<> data inside " << result._min << " ... " << result._max << std::endl ; std::cout << "<> loading data input of R^" << result.dimX() << " -> R^" << result.dimY() << std::endl ; std::cout << "<> " << result._data.size() << " elements to fit" << std::endl ; } void save_data_as_text(std::ostream& out, const data &data) { out << "#DIM " << data.dimX() << " " << data.dimY() << std::endl; out << "#PARAM_IN " << params::get_name(data.input_parametrization()) << std::endl; out << "#PARAM_OUT " << params::get_name(data.output_parametrization()) << std::endl; for(int i=0; i < data.size(); ++i) { vec x = data.get(i); for(int j=0; j< data.dimX() + data.dimY(); ++j) { out << x[j] << "\t"; } out << std::endl; } } void save_data_as_binary(std::ostream &out, const data& data) { out << "#DIM " << data.dimX() << " " << data.dimY() << std::endl; out << "#PARAM_IN " << params::get_name(data.input_parametrization()) << std::endl; out << "#PARAM_OUT " << params::get_name(data.output_parametrization()) << std::endl; out << "#FORMAT binary" << std::endl; out << "#VERSION 0" << std::endl; out << "#PRECISION ieee754-double" << std::endl; out << "#SAMPLE_COUNT " << data.size() << std::endl; // FIXME: Note: on non-glibc systems, both macros may be undefined, so // the conditional is equivalent to "#if 0 == 0", which is usually what // we want. #if __BYTE_ORDER == __LITTLE_ENDIAN out << "#ENDIAN little" << std::endl; #else out << "#ENDIAN big" << std::endl; #endif out << "#BEGIN_STREAM" << std::endl; for(int i=0; i < data.size(); ++i) { vec sample = data.get(i); const double *numbers = sample.data(); assert(sample.size() == data.dimX() + data.dimY()); out.write((const char *)numbers, sample.size() * sizeof(*numbers)); } out << std::endl << "#END_STREAM" << std::endl; } void load_data_from_binary(std::istream& in, const header& header, data& data) { // FIXME: For now we make a number of assumptions. assert(header["FORMAT"].string() == "binary"); assert(header["VERSION"] == 0); assert(header["PRECISION"].string() == "ieee754-double"); #if __BYTE_ORDER == __LITTLE_ENDIAN assert(header["ENDIAN"].string() == "little"); #else assert(header["ENDIAN"].string() == "big"); #endif std::pair dim = header["DIM"]; data.setDimX(dim.first); data.setDimY(dim.second); data._min.resize(dim.first); data._max.resize(dim.first); data.setParametrizations(params::parse_input(header["PARAM_IN"]), params::parse_output(header["PARAM_OUT"])); in.exceptions(std::ios_base::failbit); int sample_count = header["SAMPLE_COUNT"]; // TODO: Arrage to use mmap and make it zero-alloc and zero-copy. for (int i = 0; i < sample_count; i++) { vec row = vec::Zero(data.dimX() + data.dimY()); std::streamsize expected = row.size() * sizeof(double); for (std::streamsize total = 0; total < expected && !in.eof(); total += in.gcount()) { in.read((char *)row.data() + total, expected); } data.set(row); } }