wiki:soc/2007/VisualizationOfContainers

Version 28 (modified by jakevoytko, 15 years ago) ( diff )

--

Introduction

This project is focused on using STL containers in order to graph data on a one-dimensional and two-dimensional (and if time allows, 3D!) plot. The plot would be written in an svg image, compliant with the W3C standard. The goals of the project are as follows:

  • To let users produce a simple plot with minimal intervention by using sane defaults
  • To demonstrate how to incorporate SVG images into Boost documentation
  • To allow users to easily customize graphs to their heart's content
  • To allow the user to talk with the svg_graph class using coordinate units instead of pixels or other arbitrary measures

I have only a student's grasp of C++, so if you have a suggestion to help me with design or implementation, either leave them here or email me at jakevoytko [at] gmail [dot] com

This page will hold examples of what I have implemented thus far, and what my program will be capable of in the future. More complete documentation will be live in a few days on my personal website.

What can it do?

Example

Potential example

svg_plot my_plot;

// size/scale settings
my_plot.set_image_size(500, 350)
       .set_x_scale(-2, 10);
    
// command settings
my_plot.set_axis(true)
       .set_legend(true);

// color settings
my_plot.set_background_color(lightgray)
       .set_legend_background_color(whitesmoke);

// drawing
plot_range(my_plot, data2.begin(), data2.end(), "Lions",  blue);
plot_range(my_plot, data1.begin(), data1.end(), "Tigers", limegreen);

// write to file. NOTE: Will change to write(filename) soon
my_plot.write("D:\\1d_simple.svg");

produces the following output:

http://www.tcnj.edu/~voytko2/svg_simple.htm

Complex example

Because Boost.Array supports an iterator-like interface, (my_arr.begin(), my_arr.end()), Boost.Array can freely be used with the program. This example shows what a completely customized graph might look like. The colors were suggested by Sarah Braun to match the Unified Look and Feel project

    vector<double> data1;
    deque<double> data2;
    boost::array<double, 10> data3;

    svg_plot my_plot;

    // size/scale settings
    my_plot.set_image_size(500, 350)
           .set_x_scale(-3, 10);

    // Text settings
    my_plot.set_title("Oh My!")
           .set_title_font_size(29)
           .set_x_label_text("Time in Months");

    // command settings
    my_plot.set_axis(true)
           .set_legend(true)
           .set_plot_window(true)
           .set_x_label(true)
           .set_x_major_labels(true);

    // color settings
    my_plot.set_background_color(svg_color(67, 111, 69))
           .set_legend_background_color(svg_color(207, 202,167))
           .set_plot_background_color(svg_color(136, 188, 126))
           .set_title_color(white)
           .set_x_axis_color(black)
           .set_x_major_tick_color(black)
           .set_legend_border_color(svg_color(102, 102, 84))
           .set_x_minor_tick_color(black);

    //axis settings
    my_plot.set_x_major_tick(2)
           .set_x_num_minor_ticks(3)
           .set_x_major_tick_length(14)
           .set_x_minor_tick_length(7)
           .set_x_major_tick_width(1)
           .set_x_minor_tick_width(1);

    //legend settings
    my_plot.set_legend_title_font_size(15);

    plot_range(my_plot, data2.begin(), data2.end(), "Lions",  blue);
    plot_range(my_plot, data1.begin(), data1.end(), "Tigers", purple);
    plot_range(my_plot, data3.begin(), data3.end(), "Bears",  red);

    my_plot.write("D:/1d_complex.svg");

Produces the following file: http://www.tcnj.edu/~voytko2/svg_complex.htm

Simple 2D Example

Note: Because one of this week's tasks is to make sane defaults, the sample program here will likely be shorter

    multimap<double, double> data;

    svg_2d_plot my_plot;

    for(double i=0; i<10; ++i)
    {
        data.insert(std::pair<double,double>(i,f(i)));
    }

    // size/scale settings
    my_plot.set_image_size(500, 350)
           .set_x_scale(-1, 10)
           .set_y_scale(-1, 5);

    // Text settings
    my_plot.set_title("2D Graph Test")
           .set_title_font_size(29);

    // command settings
    my_plot.set_axis(true)
           .set_legend(true)
           .set_plot_window(true)
           .set_x_major_labels(true)
           .set_y_major_labels(true);

    // color settings
      my_plot.set_background_color(darkgray)
             .set_legend_background_color(white)
             .set_plot_background_color(white);

    //axis settings
    my_plot.set_x_major_tick(2)
           .set_x_num_minor_ticks(1)
           .set_x_major_tick_length(14)
           .set_x_minor_tick_length(7)
           .set_x_major_tick_width(2)
           .set_x_minor_tick_width(1)

           .set_y_major_tick(2)
           .set_y_num_minor_ticks(1)
           .set_y_major_tick_length(20)
           .set_y_minor_tick_length(10)
           .set_y_major_tick_width(2)
           .set_y_minor_tick_width(1);

    //legend settings
    my_plot.set_legend_title_font_size(15);

    plot_range(my_plot, data.begin(), data.end(), "sqrt(x)",  black);

    my_plot.write("D:/test.svg");

Produces the following file: http://www.tcnj.edu/~voytko2/svg_2d.htm

To-Do List

For next week

  • Better/more complete Documentation
  • Fewer bugs
  • As many suggestions finished as I can

Suggestions

By Matias Capeletto:

  • Be able to choose a log scale for either the X or the Y axis
  • Allow the user to import/export XML data that represents style information
  • Proposal to include a plugable extractor to plot_range()

In general, containers will store other things than double. Starting simple, I want to be able to plot std::vector<int>. This is very easy to support. Add a function:

template<class Iter, class DoubleExtractor >
plot& plot_range( Iter start, Iter end, DoubleExtractor double_extractor)
{
    return your_old_plot_range(
       boost::make_transform_iterator(start, double_extractor),
       boost::make_transform_iterator(end  , double_extractor)
    );
}

This have other implications, for example if we have list<Human> hl, and struct get_age_functor { ... }; We can:

plot_range(svg, hl.begin(), hl.end(), get_age_functor() ); // fun stuff :)

By Paul Bristow

  • Customize background color of plot Completed
  • Customize the background border color
  • Customize the "axis area" background color Completed
  • Title
    • Customize font
    • Customize font color
    • Customize font size Completed
  • Axis
    • Customize line colors Completed
    • Customize line thickness Completed
    • Define labels for axis Completed
    • Major ticks width, length, color Completed
    • Minor ticks width, length, color Completed
    • Reasonable defaults for ticks
    • Axis marker labels Completed for major ticks
    • Consider the axis for data where the origin is not in the view window
    • Consider auto-scaling
    • Grid lines
  • Data representation
    • Allow different data representation points
    • Allow appropriate customization of data points
    • Consider labels for data points (combined with exploration of hover-text features of SVG mentioned above) Completed in legend
    • Consider how to concisely represent the scale of data points
    • Multiple data series Completed
  • Legend
    • color Partially Completed
    • position
    • border thickness
    • border color
    • background colors Completed
  • Unicode strings

By Cédric Venet

  • Keep an eye towards being extensible towards multiple image formats in the future

4. Bugs D:

  • Changing or setting the x_scale after calling my_graph.draw_axis() makes the axis not be drawn.
    • This is caused because I store points after setting the graph. I will fix this by storing infinity as +NaN in the point, and when outputting, writing it at a location far off the graph

5. Acknowledgments

In no particular order, I'd like to thank Joaquín López Muñoz, Paul Bristow, Sarah Braun, John Maddock, Matias Capeletto, and anyone who's taken the time to comment on my progress / offer suggestions.

Note: See TracWiki for help on using the wiki.