Commit f6a17078 authored by incardon's avatar incardon

Added CSV and VTK writer

parent d4b71c57
/*
* 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>
#include "common.hpp"
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include "Point_test.hpp"
#include "csv_multiarray.hpp"
#include "util.hpp"
/*! \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
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;
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
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;
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
for (int i = 0 ; i < v_pos::value_type::dims ; i++)
{
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
*
*/
std::string get_csv_data(v_pos & vp, v_prp & vpr)
{
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
for (size_t i = 0 ; i < vp.size() ; i++)
{
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
typename v_prp::value_type obj = vpr.get(i);
csv_prp<typename v_prp::value_type> c_prp(str,obj);
// 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
*
*/
bool write(std::string file, v_pos & v , v_prp & prp)
{
// 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
point_data = get_csv_data(v,prp);
// 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_ */
#ifndef CSVWRITER_UNIT_TESTS_HPP_
#define CSVWRITER_UNIT_TESTS_HPP_
#include "CSVWriter.hpp"
#include "Vector/vector_test_util.hpp"
BOOST_AUTO_TEST_SUITE( csv_writer_test )
BOOST_AUTO_TEST_CASE( csv_writer_particles )
{
// Allocate a property vector
auto v_prp = allocate_openfpm(16);
// Vector of position
openfpm::vector<Point<3,float>> v_pos;
// create a positional vector
for (size_t i = 0 ; i < v_prp.size() ; i++)
{
Point<3,float> p({1.0,2.0,3.0});
v_pos.add(p);
}
// CSVWriter test
CSVWriter<openfpm::vector<Point<3,float>>, openfpm::vector<Point_test<float>> > csv_writer;
// Write the CSV
csv_writer.write("csv_out.csv",v_pos,v_prp);
bool test = compare("csv_out.csv","csv_out_test.csv");
BOOST_REQUIRE_EQUAL(true,test);
}
BOOST_AUTO_TEST_SUITE_END()
#endif
#ifndef GRAPHML_WRITER_HPP
#define GRAPHML_WRITER_HPP
#include "map_graph.hpp"
#include "Graph/map_graph.hpp"
#include <iostream>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <fstream>
#include "common.hpp"
......@@ -425,7 +423,7 @@ struct edge_node
void end_node()
{
// close a node
e_node += "</node>\n";
e_node += "</edge>\n";
}
//! It call the functor for each member
......@@ -478,7 +476,7 @@ class GraphMLWriter
std::string get_vertex_properties_list()
{
//! vertex property output string
std::string v_out("<key id=\"d0\" for=\"node\" yfiles.type=\"nodegraphics\"/>\n");
std::string v_out("");
// create a vertex property functor
vertex_prop<Graph> vp(v_out);
......@@ -633,7 +631,7 @@ public:
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
// Graph header to define an header
graph_header = "<graph id=\"" + graph_name + "\" edgedefault=\"directed\">\n";
graph_header = "<graph id=\"" + graph_name + "\" edgedefault=\"undirected\">\n";
// Graph header end
graph_header_end = "</graph>\n";
......
......@@ -13,6 +13,7 @@
#include "GraphMLWriter.hpp"
#include "VTKWriter.hpp"
#include "Graph/CartesianGraphFactory.hpp"
#include "util.hpp"
BOOST_AUTO_TEST_SUITE( graphml_writer_test )
......@@ -81,34 +82,35 @@ BOOST_AUTO_TEST_CASE( graphml_writer_use)
g_csr2.addEdge(2,0);
g_csr2.addEdge(3,2);
VTKWriter<Graph_CSR<ne_cp,ne_cp>> gv2(g_csr2);
// Create a graph ML
GraphMLWriter<Graph_CSR<ne_cp,ne_cp>> gv2(g_csr2);
gv2.write("test_graph2.graphml");
gv2.write("test_graph2.vtk");
// check that match
bool test = compare("test_graph2.graphml","test_graph2_test.graphml");
BOOST_REQUIRE_EQUAL(true,test);
//! Create a graph
CartesianGraphFactory<3,Graph_CSR<ne_cp,ne_cp>> g_factory;
// Cartesian grid
std::vector<size_t> sz;
sz.push_back(GS_SIZE);
sz.push_back(GS_SIZE);
sz.push_back(GS_SIZE);
size_t sz[] = {GS_SIZE,GS_SIZE,GS_SIZE};
// Box
Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
Graph_CSR<ne_cp,ne_cp> g_csr = g_factory.construct<5,float,2,ne_cp::x,ne_cp::y,ne_cp::z>(sz,box);
// Create a graph ML
GraphMLWriter<Graph_CSR<ne_cp,ne_cp>> gw(g_csr);
gw.write("test_graph.graphml");
// std::cout << std::is_class<ne_cp::attributes>;
gw.write("test_graph.gml");
VTKWriter<Graph_CSR<ne_cp,ne_cp>> gv(g_csr);
gv.write("test_graph.vtk");
// check that match
test = compare("test_graph.graphml","test_graph_test.graphml");
BOOST_REQUIRE_EQUAL(true,test);
}
BOOST_AUTO_TEST_SUITE_END()
......
/*
* VTKWriter.hpp
*
* Created on: Dec 15, 2014
* Author: Pietro Incardona
*/
#ifndef VTKWRITER_HPP_
#define VTKWRITER_HPP_
#include "Graph/map_graph.hpp"
#include <iostream>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <fstream>
#include "common.hpp"
/*! \brief Get the type
*
* It convert T to a string identify the corrispondent type in VTK format
*
*/
template <typename T> std::string getType()
{
// Create a property string based on the type of the property
if (typeid(T) == typeid(float))
return "float";
else if (typeid(T) == typeid(double))
return "double";
else if (typeid(T) == typeid(char))
return "char";
else if (typeid(T) == typeid(unsigned char))
return "unsigned_char";
else if (typeid(T) == typeid(short))
return "short";
else if (typeid(T) == typeid(unsigned short))
return "unsigned_short";
else if (typeid(T) == typeid(int))
return "int";
else if (typeid(T) == typeid(unsigned int))
return "unsigned_int";
else if (typeid(T) == typeid(long int))
return "long";
else if (typeid(T) == typeid(unsigned long int))
return "unsigned_long";
else if (typeid(T) == typeid(bool))
return "bit";
return "";
}
/*! \brief Set a conversion map between A and B
*
* Convert A to B
*
* \tparam B destination type
* \tparam A source type
*
*/
template<typename A>
class convert
{
public:
template<typename B> static B to(const A & data)
{
return static_cast<B>(data);
}
};
/*! \brief Partial specialization when A is a string
*
*
*/
template<>
class convert<std::string>
{
public:
template<typename B> static B to(const std::string & data)
{
return atof(data.c_str());
}
};
/*! \brief It specify the VTK output file type
*
*/
enum file_type
{
BINARY,
ASCII
};
/*! \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
*
* \tparam G graph type
* \tparam attr has the vertex attributes
*
*/
template<typename G, bool attr>
struct vtk_vertex_node
{
// Vertex spatial type information
typedef typename G::V_type::s_type s_type;
s_type (& x)[3];
// Vertex object container
typename G::V_container & vo;
// vertex node string
std::string & v_node;
/*! \brief Constructor
*
* Create a vertex properties list
*
* \param v_node std::string that is filled with the graph properties in the GraphML format
* \param n_obj object container to access its properties for example encapc<...>
*
*/
vtk_vertex_node(std::string & v_node, typename G::V_container & n_obj, s_type (&x)[3])
:x(x),vo(n_obj),v_node(v_node)
{
};
//! \brief Write collected information
void write()
{
v_node += std::to_string(x[0]) + " " + std::to_string(x[1]) + " " + std::to_string(x[2]) + "\n";
}
//! It call the functor for each member
template<typename T>
void operator()(T& t)
{
// if the attribute name is x y or z, create a string with the value of the properties and store it
if (G::V_type::attributes::name[T::value] == "x"){x[0] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());}
else if (G::V_type::attributes::name[T::value] == "y"){x[1] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());}
else if (G::V_type::attributes::name[T::value] == "z"){x[2] = convert<typename boost::remove_reference<decltype(vo.template get<T::value>())>::type>::template to<s_type>(vo.template get<T::value>());}
}
};
/*! \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 G>
struct vtk_vertex_node<G,false>
{
// Vertex object container
typename G::V_container & vo;
// vertex node string
std::string & v_node;
/*! \brief Constructor
*
* Create a vertex properties list
*
* \param v_node std::string that is filled with the graph properties in the GraphML format
* \param n_obj object container to access its properties for example encapc<...>
*
*/
vtk_vertex_node(std::string & v_node, typename G::V_container & n_obj)
:vo(n_obj),v_node(v_node)
{
};
//! It call the functor for each member
template<typename T>
void operator()(T& t)
{
v_node += "0 0 0\n";
}
};
/*! \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 edge
* properties
*
*/
template<typename G>
struct vtk_edge_node
{
// Vertex object container
typename G::E_container & vo;
// edge node string
std::string & e_node;
/*! \brief Constructor
*
* Create an edge node
*
* \param e_node std::string that is filled with the graph properties in the GraphML format
* \param n_obj object container to access the object properties for example encapc<...>
* \param n_prop number of properties
*
*/
vtk_edge_node(std::string & e_node, typename G::E_container & n_obj)
:vo(n_obj),e_node(e_node)
{
};
/*! \brief Create a new node
*
* \param vc node number
*
*/
void new_node(size_t v_c, size_t s, size_t d)
{
// start a new node
e_node += "2 " + std::to_string(s) + " " + std::to_string(d) + "\n";
}
};
#define GRAPH 1
#define VECTOR_BOX 2
template <typename Graph, unsigned int imp>
class VTKWriter
{
};
#include "VTKWriter_graph.hpp"
#include "VTKWriter_vector_box.hpp"
#endif /* VTKWRITER_HPP_ */
This diff is collapsed.