diff --git a/src/lib/gnuplot-gen.cpp b/src/lib/gnuplot-gen.cpp index 3c935a15f..fbec75297 100644 --- a/src/lib/gnuplot-gen.cpp +++ b/src/lib/gnuplot-gen.cpp @@ -43,9 +43,6 @@ using std::string; -using util::join; -using lib::diff::MakeRec; - namespace lib { namespace gnuplot_gen { @@ -153,31 +150,27 @@ plot $RunData using 1:3 with impulses linestyle 3, \ )~"; - template - inline string - renderCSV (IT& iter) - { - return join (iter, "\n"); - } }//(End)template and defaults definitions - /** */ + + /** + * @remark each column of the given data is featured as sequence + * over the first column interpreted as common abscissa. The name + * of the abscissa and the row names in the legend are extracted + * from the header names expected in the first row of CSV data. + */ string - dataPlot (CSVRowIter& rowIT) + dataPlot (ParamRecord params) { TextTemplate plot{GNUPLOT_BASIC_PLOT_DEF +GNUPLOT_SIMPLE_DATA_PLOT}; - auto config - = MakeRec() - .set ("CommonStyleDef", GNUPLOT_CommonStyleDef) + params.set ("CommonStyleDef", GNUPLOT_CommonStyleDef) .set ("AxisGridSetup", GNUPLOT_AxisGridSetup) - .set ("DiagramKind", "points") - .set ("CSVData", renderCSV(rowIT)) - .genNode(); - - return plot.render(config); + .set (KEY_DiagramKind, "points") + ; + return plot.render (params.genNode()); } }} // namespace lib::gnuplot_gen diff --git a/src/lib/gnuplot-gen.hpp b/src/lib/gnuplot-gen.hpp index 4905cc9af..7398d879f 100644 --- a/src/lib/gnuplot-gen.hpp +++ b/src/lib/gnuplot-gen.hpp @@ -47,29 +47,77 @@ #define LIB_GNUPLOT_GEN_H -//#include "lib/format-util.hpp" -#include "lib/iter-source.hpp" -//#include "lib/util.hpp" +#include "lib/stat/csv.hpp" +#include "lib/format-util.hpp" +#include "lib/diff/gen-node.hpp" -//#include -//#include #include -//#include +#include +#include +using std::string; namespace lib { namespace gnuplot_gen { ///< preconfigured setup for Gnuplot data visualisation -// using util::toString; -// using util::isnil; - using std::string; -// using std::move; - using CSVRowIter = lib::IterSource::iterator; + + /** + * Wrapper to simplify notation in tests. + * Accepts data suitable for representation as CSV + * - either as an std::initializer_list for pre-formatted rows + * - or a list of strings for the header, and then a list of data tuples, + * which will be rendered into data rows in CSV format + * Since this wrapper is-a `vector`, the rows can be retrieved + * directly and then rendered, or the \ref operator string() can be used + * to retrieve the complete data set in a single string of data lines. + */ + struct CSVData + : std::vector + { + CSVData (std::initializer_list lines) + : vector(lines) + { } + + template + CSVData (std::initializer_list header + ,std::initializer_list> data) + { + resize (data.size()+1); + string line; + for (string key : header) + stat::appendCsvField (line, key); + emplace_back (move(line)); + for (auto& row : data) + { + line = ""; + for (DAT const& val : row) + stat::appendCsvField (line, val); + emplace_back (move(line)); + } + } + + // standard copy operations acceptable + + + operator string() const + { + return util::join (*this, "\n"); + } + }; + + + using ParamRecord = diff::Rec::Mutator; + + const string KEY_CSVData = "CSVData"; + const string KEY_DiagramKind = "DiagramKind"; + + /** * Generate a Gnuplot diagram to visualise the given data points. */ - string dataPlot (CSVRowIter&); + string dataPlot (ParamRecord); + string dataPlot (string csvData) { return dataPlot (ParamRecord().set (KEY_CSVData, csvData)); } }} // namespace lib::gnuplot_gen diff --git a/tests/library/gnuplot-gen-test.cpp b/tests/library/gnuplot-gen-test.cpp index 6463390d9..5b65b9cfb 100644 --- a/tests/library/gnuplot-gen-test.cpp +++ b/tests/library/gnuplot-gen-test.cpp @@ -42,6 +42,8 @@ using std::array; namespace lib { namespace test { + using gnuplot_gen::CSVData; + /***************************************************************************//** * @test verify data visualisation by generated Gnuplot scripts @@ -73,18 +75,16 @@ namespace test { void simpeUsage() { - using CSVlines = std::initializer_list; - auto data = CSVlines{"x,y" - ,"0,1" - ,"1,1" - ,"2,2" - ,"3,3" - ,"4,5" - ,"5,8" - ,"6,13" - }; - auto csvIter = explore(data).asIterSource(); - string gnuplot = gnuplot_gen::dataPlot (csvIter); + string gnuplot = gnuplot_gen::dataPlot (CSVData{{"step","fib"} + ,{{0,1} + ,{1,1} + ,{2,2} + ,{3,3} + ,{4,5} + ,{5,8} + ,{6,13} + ,{7,21} + }}); cout << gnuplot < - - + + @@ -114306,8 +114306,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -114322,14 +114322,13 @@ std::cout << tmpl.render({"what", "World"}) << s watt soll der Jeitz

- - +
- - + + @@ -114340,8 +114339,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -114360,8 +114359,7 @@ std::cout << tmpl.render({"what", "World"}) << s ...wegen möglichen Style-Adjustments, die ggfs. eine spezielle Datenspalte auswerten könnten, um Entscheidungen zu treffen — allesamt Entscheidungen, die man notfalls auch hart-gecodet als Parameter durchgeben könnte

- - +
@@ -114371,8 +114369,7 @@ std::cout << tmpl.render({"what", "World"}) << s manches Problem kann man auch in Gnuplot lösen...

- -
+ @@ -114382,21 +114379,27 @@ std::cout << tmpl.render({"what", "World"}) << s
- - - - + + + + + - - + + + + + + + - - + + @@ -114450,8 +114453,11 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + + + + @@ -114474,8 +114480,14 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + + + + + + +