CSVWriter.hpp 5.94 KB
Newer Older
incardon's avatar
incardon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * CSVWriter.hpp
 *
 *  Created on: Dec 15, 2014
 *      Author: Pietro Incardona
 */

#ifndef CSVWRITER_HPP_
#define CSVWRITER_HPP_

#include <iostream>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <fstream>
incardon's avatar
incardon committed
15
#include "util/common.hpp"
incardon's avatar
incardon committed
16 17 18 19 20
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include "csv_multiarray.hpp"
#include "util.hpp"

Pietro Incardona's avatar
Pietro Incardona committed
21 22
#define CSV_WRITER 0x30000

incardon's avatar
incardon committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
/*! \brief this class is a functor for "for_each" algorithm
 *
 * For each element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the properties of the object
 *
 * \tparam Tobj object
 *
 */

template<typename Tobj>
struct csv_prp
{
	// String
	std::stringstream & str;

	// Object to write
	Tobj & obj;

	/*! \brief Constructor
	 *
	 * Create a vertex properties list
	 *
	 * \param str streamstring
	 * \param obj object to write
	 *
	 */
	csv_prp(std::stringstream & str, Tobj & obj)
	:str(str),obj(obj)
	{
	};

	//! It call the functor for each member
    template<typename T>
    void operator()(T& t)
    {
		// This is the type of the csv column
Pietro Incardona's avatar
Pietro Incardona committed
59
		typedef decltype(obj.template get<T::value>()) col_type;
incardon's avatar
incardon committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91

		// Remove the reference from the column type
		typedef typename boost::remove_reference<col_type>::type col_rtype;

    	csv_value_str<col_rtype>(obj.template get<T::value>(),str);
    }
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * For each element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the properties of the object
 *
 * \tparam T object
 *
 */

template<typename Tobj, bool attr>
struct csv_col
{
	std::stringstream & str;

	csv_col(std::stringstream & str)
	:str(str)
	{
	};

	//! It call the functor for each member
    template<typename T>
    void operator()(T& t)
    {
		// This is the type of the csv column
Pietro Incardona's avatar
Pietro Incardona committed
92
		typedef decltype(std::declval<Tobj>.template get<T::value>()) col_type;
incardon's avatar
incardon committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

		// Remove the reference from the column type
		typedef typename boost::remove_reference<col_type>::type col_rtype;

    	csv_col_str<col_rtype>(std::string(Tobj::attributes::name[T::value]),str);
    }
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to create a string containing all the vertex
 * properties
 *
 * Specialization when we do not have vertex attributes
 *
 * \tparam G graph type
 *
 */

template<typename Tobj>
struct csv_col<Tobj,false>
{
	std::stringstream & str;

	csv_col(std::stringstream & str)
	:str(str)
	{
	};

	//! It call the functor for each member
    template<typename T>
    void operator()(T& t)
    {
		// This is the type of the csv column
		typedef typename boost::fusion::result_of::at_c<typename Tobj::type,T::value>::type col_type;

		// Remove the reference from the column type
		typedef typename boost::remove_reference<col_type>::type col_rtype;

		std::stringstream str2;
		str2 << "column_" << T::value;

		csv_col_str<col_rtype>(str2.str(),str);
    }
};

#define VECTOR 1

/*! \brief CSV Writer
 *
 * It write in CSV format vector of objects living into an N-dimensional space
 *
 * \tparam v_pos Positional vector
 * \tparam v_prp Property vector
 *
 */
template <typename v_pos, typename v_prp, unsigned int impl = VECTOR>
class CSVWriter
{
	/*! \brief Get the colums name (also the positional name)
	 *
	 */
	std::string get_csv_colums()
	{
		std::stringstream str;

		// write positional columns
incardon's avatar
incardon committed
162
		for (size_t i = 0 ; i < v_pos::value_type::dims ; i++)
incardon's avatar
incardon committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		{
			if (i == 0)
				str << "x[" << i << "]";
			else
				str << "," << "x[" << i << "]";
		}

		// write positional information

		csv_col<typename v_prp::value_type,has_attributes<typename v_prp::value_type>::value> col(str);

		// Iterate through all the vertex and create the vertex list
		boost::mpl::for_each< boost::mpl::range_c<int,0,v_prp::value_type::max_prop> >(col);

		str << "\n";

		return str.str();
	}

	/*! \brief Get the csv data section
	 *
	 * \param v_pos vector that contain the positional information
	 * \param v_prp vector that contain the property information
Pietro Incardona's avatar
Pietro Incardona committed
186
	 * \param offset from where to start
incardon's avatar
incardon committed
187 188
	 *
	 */
Pietro Incardona's avatar
Pietro Incardona committed
189
	std::string get_csv_data(v_pos & vp, v_prp & vpr, size_t offset)
incardon's avatar
incardon committed
190 191 192 193 194 195 196 197 198 199 200
	{
		std::stringstream str;

		// The position and property vector size must match
		if (vp.size() != vpr.size())
		{
			std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " position vector and property vector must have the same size \n";
			return std::string("");
		}

		// Write the data
Pietro Incardona's avatar
Pietro Incardona committed
201
		for (size_t i = offset ; i < vp.size() ; i++)
incardon's avatar
incardon committed
202 203 204 205 206 207 208 209 210 211
		{
			for (size_t j = 0 ; j < v_pos::value_type::dims ; j++)
			{
				if (j == 0)
					str << vp.template get<0>(i)[j];
				else
					str << "," << vp.template get<0>(i)[j];
			}

			// Object to write
Pietro Incardona's avatar
Pietro Incardona committed
212
			auto obj = vpr.get(i);
incardon's avatar
incardon committed
213

Pietro Incardona's avatar
Pietro Incardona committed
214
			csv_prp<decltype(obj)> c_prp(str,obj);
incardon's avatar
incardon committed
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

			// write the properties to the stream string
			boost::mpl::for_each< boost::mpl::range_c<int,0,v_prp::value_type::max_prop> >(c_prp);

			str << "\n";
		}

		return str.str();
	}

public:

	/*! \brief It write a CSV file
	 *
	 * \tparam prp which properties to output [default = -1 (all)]
	 *
	 * \param file path where to write
	 * \param v_pos positional vector
	 * \param v_prp properties vector
Pietro Incardona's avatar
Pietro Incardona committed
234
	 * \param offset from where to start to write
incardon's avatar
incardon committed
235 236 237
	 *
	 */

Pietro Incardona's avatar
Pietro Incardona committed
238
	bool write(std::string file, v_pos & v , v_prp & prp, size_t offset=0)
incardon's avatar
incardon committed
239 240 241 242 243 244 245 246 247 248
	{
		// Header for csv (colums name)
		std::string csv_header;
		// Data point
		std::string point_data;

		// Get csv columns
		csv_header = get_csv_colums();

		// For each property in the vertex type produce a point data
Pietro Incardona's avatar
Pietro Incardona committed
249
		point_data = get_csv_data(v,prp,offset);
incardon's avatar
incardon committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

		// write the file
		std::ofstream ofs(file);

		// Check if the file is open
		if (ofs.is_open() == false)
		{std::cerr << "Error cannot create the CSV file: " + file;}

		ofs << csv_header << point_data;

		// Close the file

		ofs.close();

		// Completed succefully
		return true;
	}
};


#endif /* CSVWRITER_HPP_ */