diff --git a/CMakeLists.txt b/CMakeLists.txt index 95c60eb..d9bf794 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,15 @@ set(CMAKE_CXX_FLAGS "-Wall -Wextra") set(CMAKE_CXX_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_RELEASE "-O3") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + + +#find_package(Boost REQUIRED COMPONENTS iostreams system filesystem) +find_package(Boost REQUIRED COMPONENTS iostreams system filesystem) + +include_directories(${CMAKE_SOURCE_DIR}/gnuplot-iostream) + # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) # Instruct CMake to run moc automatically when needed @@ -58,3 +67,4 @@ add_executable(Rennbahn ${helloworld_SRCS}) # Use the Widgets module from Qt 5 target_link_libraries(Rennbahn Qt5::Widgets Qt5::Core Qt5::Sql) +target_link_libraries(Rennbahn ${Boost_LIBRARIES}) diff --git a/evaluation.cpp b/evaluation.cpp index 0efd254..bdc39f7 100644 --- a/evaluation.cpp +++ b/evaluation.cpp @@ -1,21 +1,51 @@ #include "evaluation.h" #include "result.h" #include "ui_evaluation.h" +#include +#include #include +#include +#include + +using std::cout; +using std::endl; Evaluation::Evaluation(DataBase * db, QWidget * parent) : QWidget(parent), ui(new Ui::Evaluation) { ui->setupUi(this); this->db = db; + + // connectsion + + QObject::connect(this->ui->pBClose, SIGNAL(clicked()), this, SLOT(close())); + + this->result = this->db->getData2("select date, id from Rennen", 2); + QStringList listOfDates; + for (vector str : result) { + listOfDates << str.at(0); + // this->ui->lWEvaluation->addItem(new QListWidgetItem(str.at(0))); + } + QStringListModel * model = new QStringListModel(); - QStringList list; - list << "datum 1" - << "datum 2" - << "datum 3"; - model->setStringList(list); - this->ui->lVEvaluation->setModel(model); - this->interfaceResult = new Result(this->db); + model->setStringList(listOfDates); + this->ui->lWEvaluation->setModel(model); + QObject::connect(this->ui->lWEvaluation, + SIGNAL(doubleClicked(const QModelIndex &)), this, + SLOT(listClick(const QModelIndex &))); + + // this->interfaceResult = new Result(this->db); + // this->interfaceResult->show(); +} + +void Evaluation::listClick(const QModelIndex & ind) { + cout << "list Click" << endl; + // get id to index + unsigned long index = static_cast(ind.row()); + int id = this->result.at(index).at(1).toInt(); + + this->interfaceResult = new Result(this->db, id); this->interfaceResult->show(); + } Evaluation::~Evaluation() { diff --git a/evaluation.h b/evaluation.h index 72dd90a..5c89172 100644 --- a/evaluation.h +++ b/evaluation.h @@ -3,7 +3,12 @@ #include "database.h" #include "result.h" +#include #include +#include +#include + +using std::vector; namespace Ui { class Evaluation; @@ -20,6 +25,10 @@ class Evaluation : public QWidget { Ui::Evaluation * ui; Result * interfaceResult; DataBase * db; + vector> result; + + public slots: + void listClick(const QModelIndex & index); }; #endif // EVALUATION_H diff --git a/evaluation.ui b/evaluation.ui index 3c0c9bc..861ad43 100644 --- a/evaluation.ui +++ b/evaluation.ui @@ -17,12 +17,12 @@ - + - + Schließen diff --git a/gnuplot-iostream/.gitignore b/gnuplot-iostream/.gitignore new file mode 100644 index 0000000..fdb8d7c --- /dev/null +++ b/gnuplot-iostream/.gitignore @@ -0,0 +1,23 @@ +# compiled stuff +example-data-1d +example-data-2d +example-interactive +example-misc +test-noncopyable +test-outputs +test-empty +*.error.txt +*.o +# Windows compiled stuff +*.exe +*.obj + +# cmake stuff +build +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake + +# output of example scripts and unit tests +my_graph_*.png +unittest-output/ diff --git a/gnuplot-iostream/ChangeLog b/gnuplot-iostream/ChangeLog new file mode 100644 index 0000000..c917941 --- /dev/null +++ b/gnuplot-iostream/ChangeLog @@ -0,0 +1,15 @@ +Updates happen via git with no regular release schedule or versioning. +However, I will bump up the GNUPLOT_IOSTREAM_VERSION macro whenever +something major changes (but note that prior to version 2 this macro is not +defined). + +Version 2: + * Major rewrite. + * Nearly every combination of container and tuple types is supported. + * Now you should use send1d() and send2d() rather than just send(). + * When the Gnuplot object is constructed with no arguments, an attempt is made to determine + the best gnuplot command and arguments for your operating system. + +Version 1: + * Original version. + * The GNUPLOT_IOSTREAM_VERSION macro is not defined prior to version 2. diff --git a/gnuplot-iostream/Makefile b/gnuplot-iostream/Makefile new file mode 100644 index 0000000..14e91ce --- /dev/null +++ b/gnuplot-iostream/Makefile @@ -0,0 +1,92 @@ +# Copyright (c) 2013 Daniel Stahlke +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +########################################################################### +# This Makefile is just for the demos and unit tests. You don't need to compile +# anything to install this package. Just copy the gnuplot-iostream.h header +# somewhere and you are good to go. +########################################################################### + +# The -O0 option speeds up the compile, which is good for testing. This should +# never be used for production since the generated code is extremely slow! +CXXFLAGS+=-Wall -Wextra -O0 -g -D_GLIBCXX_DEBUG +LDFLAGS+=-lutil -lboost_iostreams -lboost_system -lboost_filesystem + +# This makes the examples and tests more complete, but only works if you have the corresponding +# libraries installed. +#CXXFLAGS+=--std=c++11 -DUSE_ARMA=1 -DUSE_BLITZ=1 + +ALL_EXAMPLES=example-misc example-data-1d example-data-2d example-interactive +TEST_BINARIES=test-noncopyable test-outputs test-empty + +all: $(ALL_EXAMPLES) + +%.o: %.cc gnuplot-iostream.h + $(CXX) $(CXXFLAGS) -c $< -o $@ + +example-misc: example-misc.o + $(CXX) -o $@ $^ $(LDFLAGS) + +example-data-1d: example-data-1d.o + $(CXX) -o $@ $^ $(LDFLAGS) + +example-data-2d: example-data-2d.o + $(CXX) -o $@ $^ $(LDFLAGS) + +example-interactive: example-interactive.o + $(CXX) -o $@ $^ $(LDFLAGS) + +test-noncopyable: test-noncopyable.o + $(CXX) -o $@ $^ $(LDFLAGS) + +test-outputs: test-outputs.o + $(CXX) -o $@ $^ $(LDFLAGS) + +test-empty: test-empty.o + $(CXX) -o $@ $^ $(LDFLAGS) + +test-asserts: test-assert-depth.error.txt test-assert-depth-colmajor.error.txt + +%.error.txt: %.cc gnuplot-iostream.h + # These are programs that are supposed to *not* compile. + # The "!" causes "make" to throw an error if the compile succeeds. + ! $(CXX) $(CXXFLAGS) -c $< -o $<.o 2> $@ + grep -q 'container not deep enough\|boost::STATIC_ASSERTION_FAILURE' $@ + +test: $(TEST_BINARIES) test-asserts + mkdir -p unittest-output + rm -f unittest-output/* + ./test-outputs + diff -qr unittest-output unittest-output-good + +clean: + rm -f *.o + rm -f *.error.txt + rm -f $(ALL_EXAMPLES) $(TEST_BINARIES) + # Windows compilation + rm -f *.exe *.obj + # files created by demo scripts + rm -f my_graph_*.png external_binary.dat external_binary.gnu external_text.dat external_text.gnu inline_binary.gnu inline_text.gnu + +lint: + cpplint.py --filter=-whitespace,-readability/streams,-build/header_guard gnuplot-iostream.h + +cppcheck: + cppcheck *.cc *.h --template gcc --enable=all -q diff --git a/gnuplot-iostream/Makefile.VC b/gnuplot-iostream/Makefile.VC new file mode 100644 index 0000000..c4f600c --- /dev/null +++ b/gnuplot-iostream/Makefile.VC @@ -0,0 +1,62 @@ +# Copyright (c) 2013 Daniel Stahlke +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +########################################################################### +# This Makefile is just for my personal use, to test that things work in MSVC. +# It has paths hard-coded for my system. If you know how to make a proper, +# portable build file for Windows, and want to do so, then email me. +########################################################################### + +ALL_EXAMPLES=example-misc.exe example-data-1d.exe example-data-2d.exe +TEST_BINARIES=test-noncopyable.exe test-outputs.exe + +# Even the Nov 2012 CTP won't compile with C++11 support. +#EXTRA_FLAGS=/DGNUPLOT_ENABLE_CXX11 /DUSE_CXX + +#set PATH=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\bin;%PATH% +#set INCLUDE=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\include;%INCLUDE% + +all: $(ALL_EXAMPLES) + +%.exe: %.cc gnuplot-iostream.h + cl /W3 /EHsc $(EXTRA_FLAGS) /I "C:\Program Files\boost\boost_1_51" $< /link /LIBPATH:"e:\boost_libs_1_51\lib32" + +test-asserts: test-assert-depth.error.txt test-assert-depth-colmajor.error.txt + +%.error.txt: %.cc gnuplot-iostream.h + # These are programs that are supposed to *not* compile. + # The "!" causes "make" to throw an error if the compile succeeds. + ! cl /W3 /EHsc $(EXTRA_FLAGS) /I "C:\Program Files\boost\boost_1_51" $< /link /LIBPATH:"e:\boost_libs_1_51\lib32" > $@ + grep -q 'container not deep enough\|boost::STATIC_ASSERTION_FAILURE' $@ + +test: $(TEST_BINARIES) test-asserts + rm -f unittest-output/* + ./test-outputs.exe + dos2unix -q unittest-output/*.txt + diff -qr unittest-output unittest-output-good + +clean: + rm -f *.o + rm -f *.error.txt + rm -f $(ALL_EXAMPLES) $(TEST_BINARIES) + # Windows compilation + rm -f *.exe *.obj + # files created by demo scripts + rm -f my_graph_*.png external_binary.dat external_binary.gnu external_text.dat external_text.gnu inline_binary.gnu inline_text.gnu diff --git a/gnuplot-iostream/README b/gnuplot-iostream/README new file mode 100644 index 0000000..cf0cbae --- /dev/null +++ b/gnuplot-iostream/README @@ -0,0 +1,57 @@ +********************************************************** +*** Direct questions or suggestions to dan@stahlke.org *** +********************************************************** + + +Gnuplot-Iostream Interface +========================== + +This interface allows gnuplot to be controlled from C++ and is designed to +be the lowest hanging fruit. In other words, if you know how gnuplot works +it should only take 30 seconds to learn this library. Basically it is just +an iostream pipe to gnuplot with some extra functions for pushing data +arrays and getting mouse clicks. Data sources include STL containers (eg. +vector), Blitz++, and armadillo. You can use nested data types like +std::vector>> (as well as even more +exotic types). Support for custom data types is possible. + +This is a low level interface, and usage involves manually sending commands +to gnuplot using the "<<" operator (so you need to know gnuplot syntax). +This is in my opinion the easiest way to do it if you are already +comfortable with using gnuplot. If you would like a more high level interface +check out the gnuplot-cpp library (http://code.google.com/p/gnuplot-cpp). + +Documentation is available at http://www.stahlke.org/dan/gnuplot-iostream +but also you can look at the example programs (starting with +"example-misc.cc"). + + +Getting the source code +======================= + +git clone https://github.com/dstahlke/gnuplot-iostream.git + + +Usage +===== + +See the examples source code for a quick intro. Documentation is at +the project home page http://www.stahlke.org/dan/gnuplot-iostream . +To build examples just type 'make'. There is an option you can edit in the +Makefile to enable extra demos that require optional libraries. + + +Note for Windows users +====================== + +Windows support basically works, but there are some troubles. For hints, see: + https://github.com/dstahlke/gnuplot-iostream/wiki/Portability + +Contributors +============ + +Dan Stahlke (dan@stahlke.org) +Jens Mueller +Robbie Morrison +Daniel Di Marco +Sylwester Arabas diff --git a/gnuplot-iostream/example-data-1d.cc b/gnuplot-iostream/example-data-1d.cc new file mode 100644 index 0000000..dfce2f0 --- /dev/null +++ b/gnuplot-iostream/example-data-1d.cc @@ -0,0 +1,453 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// This demonstrates all sorts of data types that can be plotted using send1d(). It is not +// meant as a first tutorial; for that see example-misc.cc or the project wiki. + +#if (__cplusplus >= 201103) +#define USE_CXX +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef USE_ARMA +#include +#endif + +#ifdef USE_BLITZ +#include +#endif + +#include "gnuplot-iostream.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +const int num_steps = 100; + +double get_x(int step, double shift) { + double theta = 2.0*M_PI*step/(num_steps-1); + return std::cos(theta) * (1 + 0.3*std::cos(3.0*theta+2.0*M_PI*shift)); +} + +double get_y(int step, double shift) { + double theta = 2.0*M_PI*step/(num_steps-1); + return std::sin(theta) * (1 + 0.3*std::cos(3.0*theta+2.0*M_PI*shift)); +} + +double get_z(int step, double shift) { + double theta = 2.0*M_PI*step/(num_steps-1); + return 0.3*std::sin(3.0*theta+2.0*M_PI*shift); +} + +// This doesn't have to be a template. It's just a template to show that such things are +// possible. +template +struct MyTriple { + MyTriple() : x(0), y(0), z(0) { } + MyTriple(T _x, T _y, T _z) : x(_x), y(_y), z(_z) { } + + T x, y, z; +}; + +// Tells gnuplot-iostream how to print objects of class MyTriple. +namespace gnuplotio { + template + struct BinfmtSender > { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + BinfmtSender::send(stream); + BinfmtSender::send(stream); + } + }; + + template + struct BinarySender > { + static void send(std::ostream &stream, const MyTriple &v) { + BinarySender::send(stream, v.x); + BinarySender::send(stream, v.y); + BinarySender::send(stream, v.z); + } + }; + + // We don't use text mode in this demo. This is just here to show how it would go. + template + struct TextSender > { + static void send(std::ostream &stream, const MyTriple &v) { + TextSender::send(stream, v.x); + stream << " "; + TextSender::send(stream, v.y); + stream << " "; + TextSender::send(stream, v.z); + } + }; +} + +int main() { + Gnuplot gp; + // for debugging, prints to console + //Gnuplot gp(stdout); + + int num_examples = 11; +#ifdef USE_ARMA + num_examples += 4; +#endif +#ifdef USE_BLITZ + num_examples += 3; +#endif +#ifdef USE_CXX + num_examples += 3; +#endif + + double shift = 0; + + gp << "set zrange [-1:1]\n"; + + // I use temporary files rather than stdin because the syntax ends up being easier when + // plotting several datasets. With the stdin method you have to give the full plot + // command, then all the data. But I would rather give the portion of the plot command for + // the first dataset, then give the data, then the command for the second dataset, then the + // data, etc. + + gp << "splot "; + + { + std::vector, double> > pts; + for(int i=0; i, double> > pts; + for(int i=0; i(get_x(i, shift), get_y(i, shift)), get_z(i, shift))); + } + gp << gp.binFile1d(pts, "record") << "with lines title 'vector of pair of cplx and double'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + std::vector > pts; + for(int i=0; i x_pts, y_pts, z_pts; + for(int i=0; i > pts(num_steps); + for(int i=0; i > pts(num_steps); + for(int i=0; i > pts(3); + for(int i=0; i > pts; + for(int i=0; i(get_x(i, shift), get_y(i, shift), get_z(i, shift))); + } + gp << gp.binFile1d(pts, "record") << "with lines title 'vector of MyTriple'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + // Note: C style arrays seem to work, but are a bit fragile since they easily decay to + // pointers, causing them to forget their lengths. It is highly recommended that you + // use boost::array or std::array instead. These have the same size and efficiency of + // C style arrays, but act like STL containers. + double pts[num_steps][3]; + for(int i=0; i x_pts(num_steps); + arma::Col y_pts(num_steps); + arma::Col z_pts(num_steps); + for(int i=0; i > pts(num_steps); + for(int i=0; i, 1> pts(num_steps); + for(int i=0; i, 1>'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + blitz::Array pts(num_steps, 3); + for(int i=0; i(N*3)'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + blitz::Array pts(3, num_steps); + for(int i=0; i(3*N) (colmajor)'"; + } +#endif + +#ifdef USE_CXX + gp << ", "; + shift += 1.0/num_examples; + + { + std::function(int)> f = [&shift](int i) { + return boost::make_tuple(get_x(i, shift), get_y(i, shift), get_z(i, shift)); }; + + auto pts = boost::irange(0, num_steps) | boost::adaptors::transformed(f); + + gp << gp.binFile1d(pts, "record") << "with lines title 'boost transform to tuple'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + auto steps = boost::irange(0, num_steps); + + gp << gp.binFile1d(boost::make_tuple( + steps | boost::adaptors::transformed(boost::bind(get_x, _1, shift)), + steps | boost::adaptors::transformed(boost::bind(get_y, _1, shift)), + steps | boost::adaptors::transformed(boost::bind(get_z, _1, shift)) + ), "record") << "with lines title 'tuple of boost transform'"; + } + + gp << ", "; + shift += 1.0/num_examples; + + { + // Note: C style arrays seem to work, but are a bit fragile since they easily decay to + // pointers, causing them to forget their lengths. It is highly recommended that you + // use boost::array or std::array instead. These have the same size and efficiency of + // C style arrays, but act like STL containers. + double x_pts[num_steps]; + double y_pts[num_steps]; + double z_pts[num_steps]; + for(int i=0; i= 201103) + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef USE_ARMA +#include +#endif + +#ifdef USE_BLITZ +#include +#endif + +#include "gnuplot-iostream.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +// The number of axial points of the torus. +const int num_u = 10; +// The total number of longitudinal points of the torus. This is set at the beginning of +// main(). +int num_v_total; + +// This doesn't have to be a template. It's just a template to show that such things are +// possible. +template +struct MyTriple { + MyTriple() : x(0), y(0), z(0) { } + MyTriple(T _x, T _y, T _z) : x(_x), y(_y), z(_z) { } + + T x, y, z; +}; + +// Tells gnuplot-iostream how to print objects of class MyTriple. +namespace gnuplotio { + template + struct BinfmtSender > { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + BinfmtSender::send(stream); + BinfmtSender::send(stream); + } + }; + + template + struct BinarySender > { + static void send(std::ostream &stream, const MyTriple &v) { + BinarySender::send(stream, v.x); + BinarySender::send(stream, v.y); + BinarySender::send(stream, v.z); + } + }; + + // We don't use text mode in this demo. This is just here to show how it would go. + template + struct TextSender > { + static void send(std::ostream &stream, const MyTriple &v) { + TextSender::send(stream, v.x); + stream << " "; + TextSender::send(stream, v.y); + stream << " "; + TextSender::send(stream, v.z); + } + }; +} + +MyTriple get_point(int u, int v) { + double a = 2.0*M_PI*u/(num_u-1); + double b = 2.0*M_PI*v/(num_v_total-1); + double z = 0.3*std::cos(a); + double r = 1 + 0.3*std::sin(a); + double x = r * std::cos(b); + double y = r * std::sin(b); + return MyTriple(x, y, z); +} + +int main() { + Gnuplot gp; + // for debugging, prints to console + //Gnuplot gp(stdout); + + int num_examples = 7; +#ifdef USE_ARMA + num_examples += 3; +#endif +#ifdef USE_BLITZ + num_examples += 3; +#endif + + int num_v_each = 50 / num_examples + 1; + + num_v_total = (num_v_each-1) * num_examples + 1; + int shift = 0; + + gp << "set zrange [-1:1]\n"; + gp << "set hidden3d nooffset\n"; + + // I use temporary files rather than stdin because the syntax ends up being easier when + // plotting several datasets. With the stdin method you have to give the full plot + // command, then all the data. But I would rather give the portion of the plot command for + // the first dataset, then give the data, then the command for the second dataset, then the + // data, etc. + + gp << "splot "; + + { + std::vector > > pts(num_u); + for(int u=0; u > > pts(num_u); + for(int u=0; u > x_pts(num_u); + std::vector > y_pts(num_u); + std::vector > z_pts(num_u); + for(int u=0; u, + std::vector, + std::vector + > > pts; + for(int u=0; u x_pts(num_v_each); + std::vector y_pts(num_v_each); + std::vector z_pts(num_v_each); + for(int v=0; v > x_pts(num_u); + std::vector > > yz_pts(num_u); + for(int u=0; u > > pts(num_u); + for(int u=0; u > > pts(3); + for(int i=0; i<3; i++) pts[i].resize(num_u); + for(int u=0; u > pts(num_u, num_v_each); + for(int u=0; u, 2> pts(num_u, num_v_each); + for(int u=0; u, 2>'"; + } + + gp << ", "; + shift += num_v_each-1; + + { + blitz::Array pts(num_u, num_v_each, 3); + for(int u=0; u(U*V*3)'"; + } + + gp << ", "; + shift += num_v_each-1; + + { + blitz::Array pts(3, num_u, num_v_each); + for(int u=0; u(3*U*V) (colmajor)'"; + } +#endif + + gp << std::endl; + + std::cout << shift+num_v_each << "," << num_v_total << std::endl; + assert(shift+num_v_each == num_v_total); + +#ifdef _WIN32 + // For Windows, prompt for a keystroke before the Gnuplot object goes out of scope so that + // the gnuplot window doesn't get closed. + std::cout << "Press enter to exit." << std::endl; + std::cin.get(); +#endif + + return 0; +} diff --git a/gnuplot-iostream/example-interactive.cc b/gnuplot-iostream/example-interactive.cc new file mode 100644 index 0000000..e0ae3c9 --- /dev/null +++ b/gnuplot-iostream/example-interactive.cc @@ -0,0 +1,63 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include +#include + +#include + +// This must be defined before the first time that "gnuplot-iostream.h" is included. +#define GNUPLOT_ENABLE_PTY +#include "gnuplot-iostream.h" + +int main() { + Gnuplot gp; + + // Create field of arrows at random locations. + std::vector > arrows; + for(size_t i=0; i<100; i++) { + double x = rand() / double(RAND_MAX); + double y = rand() / double(RAND_MAX); + arrows.push_back(boost::make_tuple(x, y, 0, 0)); + } + + double mx=0.5, my=0.5; + int mb=1; + while(mb != 3 && mb >= 0) { + // Make the arrows point towards the mouse click. + for(size_t i=0; i(); + double y = arrows[i].get<1>(); + double dx = (mx-x) * 0.1; + double dy = (my-y) * 0.1; + arrows[i] = boost::make_tuple(x, y, dx, dy); + } + + gp << "plot '-' with vectors notitle\n"; + gp.send1d(arrows); + + gp.getMouse(mx, my, mb, "Left click to aim arrows, right click to exit."); + printf("You pressed mouse button %d at x=%f y=%f\n", mb, mx, my); + if(mb < 0) printf("The gnuplot window was closed.\n"); + } +} diff --git a/gnuplot-iostream/example-misc.cc b/gnuplot-iostream/example-misc.cc new file mode 100644 index 0000000..3d73798 --- /dev/null +++ b/gnuplot-iostream/example-misc.cc @@ -0,0 +1,437 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// Warn about use of deprecated functions. +#define GNUPLOT_DEPRECATE_WARN +#include "gnuplot-iostream.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +// http://stackoverflow.com/a/1658429 +#ifdef _WIN32 + #include + inline void mysleep(unsigned millis) { + ::Sleep(millis); + } +#else + #include + inline void mysleep(unsigned millis) { + ::usleep(millis * 1000); + } +#endif + +void pause_if_needed() { +#ifdef _WIN32 + // For Windows, prompt for a keystroke before the Gnuplot object goes out of scope so that + // the gnuplot window doesn't get closed. + std::cout << "Press enter to exit." << std::endl; + std::cin.get(); +#endif +} + +// Tell MSVC to not warn about using fopen. +// http://stackoverflow.com/a/4805353/1048959 +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#pragma warning(disable:4996) +#endif + +void demo_basic() { + Gnuplot gp; + // For debugging or manual editing of commands: + //Gnuplot gp(std::fopen("plot.gnu")); + // or + //Gnuplot gp("tee plot.gnu | gnuplot -persist"); + + std::vector > xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A.push_back(std::make_pair(x, y)); + } + + std::vector > xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B.push_back(std::make_pair(cos(theta), sin(theta))); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with lines title 'cubic', '-' with points title 'circle'\n"; + gp.send1d(xy_pts_A); + gp.send1d(xy_pts_B); + + pause_if_needed(); +} + +void demo_binary() { + Gnuplot gp; + + std::vector > xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A.push_back(std::make_pair(x, y)); + } + + std::vector > xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B.push_back(std::make_pair(cos(theta), sin(theta))); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' binary" << gp.binFmt1d(xy_pts_A, "record") << "with lines title 'cubic'," + << "'-' binary" << gp.binFmt1d(xy_pts_B, "record") << "with points title 'circle'\n"; + gp.sendBinary1d(xy_pts_A); + gp.sendBinary1d(xy_pts_B); + + pause_if_needed(); +} + +void demo_tmpfile() { + Gnuplot gp; + + std::vector > xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A.push_back(std::make_pair(x, y)); + } + + std::vector > xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B.push_back(std::make_pair(cos(theta), sin(theta))); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + // Data will be sent via a temporary file. These are erased when you call + // gp.clearTmpfiles() or when gp goes out of scope. If you pass a filename + // (i.e. "gp.file1d(pts, 'mydata.dat')"), then the named file will be created + // and won't be deleted. + // + // Note: you need std::endl here in order to flush the buffer. The send1d() + // function flushes automatically, but we're not using that here. + gp << "plot" << gp.file1d(xy_pts_A) << "with lines title 'cubic'," + << gp.file1d(xy_pts_B) << "with points title 'circle'" << std::endl; + + pause_if_needed(); +} + +void demo_png() { + Gnuplot gp; + + gp << "set terminal png\n"; + + std::vector y_pts; + for(int i=0; i<1000; i++) { + double y = (i/500.0-1) * (i/500.0-1); + y_pts.push_back(y); + } + + std::cout << "Creating my_graph_1.png" << std::endl; + gp << "set output 'my_graph_1.png'\n"; + gp << "plot '-' with lines, sin(x/200) with lines\n"; + gp.send1d(y_pts); + + std::vector > xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A.push_back(std::make_pair(x, y)); + } + + std::vector > xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B.push_back(std::make_pair(cos(theta), sin(theta))); + } + + std::cout << "Creating my_graph_2.png" << std::endl; + gp << "set output 'my_graph_2.png'\n"; + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with lines title 'cubic', '-' with points title 'circle'\n"; + gp.send1d(xy_pts_A); + gp.send1d(xy_pts_B); +} + +void demo_vectors() { + Gnuplot gp; + + std::vector > vecs; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + vecs.push_back(boost::make_tuple( + cos(theta), sin(theta), + -cos(theta)*0.1, -sin(theta)*0.1 + )); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with vectors title 'circle'\n"; + gp.send1d(vecs); + + pause_if_needed(); +} + +std::vector > get_trefoil() { + std::vector > vecs; + for(double alpha=0; alpha<1; alpha+=1.0/120.0) { + double theta = alpha*2.0*3.14159; + vecs.push_back(boost::make_tuple( + (2+cos(3*theta))*cos(2*theta), + (2+cos(3*theta))*sin(2*theta), + sin(3*theta) + )); + } + return vecs; +} + +void demo_inline_text() { + std::cout << "Creating inline_text.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(std::fopen("inline_text.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + gp << "splot '-' with lines notitle\n"; + gp.send1d(vecs); + + std::cout << "Now run 'gnuplot -persist inline_text.gnu'.\n"; +} + +void demo_inline_binary() { + std::cout << "Creating inline_binary.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(std::fopen("inline_binary.gnu", "wb")); + + std::vector > vecs = get_trefoil(); + + gp << "splot '-' binary" << gp.binFmt1d(vecs, "record") << "with lines notitle\n"; + gp.sendBinary1d(vecs); + + std::cout << "Now run 'gnuplot -persist inline_binary.gnu'.\n"; +} + +void demo_external_text() { + std::cout << "Creating external_text.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(std::fopen("external_text.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + std::cout << "Creating external_text.dat" << std::endl; + gp << "splot" << gp.file1d(vecs, "external_text.dat") << "with lines notitle\n"; + + std::cout << "Now run 'gnuplot -persist external_text.gnu'.\n"; +} + +void demo_external_binary() { + std::cout << "Creating external_binary.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(std::fopen("external_binary.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + std::cout << "Creating external_binary.dat" << std::endl; + gp << "splot" << gp.binFile1d(vecs, "record", "external_binary.dat") + << "with lines notitle\n"; + + std::cout << "Now run 'gnuplot -persist external_binary.gnu'.\n"; +} + +void demo_animation() { +#ifdef _WIN32 + // No animation demo for Windows. The problem is that every time the plot + // is updated, the gnuplot window grabs focus. So you can't ever focus the + // terminal window to press Ctrl-C. The only way to quit is to right-click + // the terminal window on the task bar and close it from there. Other than + // that, it seems to work. + std::cout << "Sorry, the animation demo doesn't work in Windows." << std::endl; + return; +#endif + + Gnuplot gp; + + std::cout << "Press Ctrl-C to quit (closing gnuplot window doesn't quit)." << std::endl; + + gp << "set yrange [-1:1]\n"; + + const int N = 1000; + std::vector pts(N); + + double theta = 0; + while(1) { + for(int i=0; i::quiet_NaN(); + + Gnuplot gp; + + std::vector > xy_pts; + for(int i=0; i<100; i++) { + double theta = double(i)/100*2*M_PI; + if((i/5)%2) { + xy_pts.push_back(std::make_pair( + std::cos(theta), std::sin(theta) + )); + } else { + xy_pts.push_back(std::make_pair(nan, nan)); + } + } + + // You need to tell gnuplot that 'nan' should be treated as missing data (otherwise it just + // gives an error). + gp << "set datafile missing 'nan'\n"; + gp << "plot '-' with linespoints\n"; + gp.send1d(xy_pts); + + // This works too. But the strange thing is that with text data the segments are joined by + // lines and with binary data the segments are not joined. + //gp << "plot '-' binary" << gp.binFmt1d(xy_pts, "record") << "with linespoints\n"; + //gp.sendBinary1d(xy_pts); + + pause_if_needed(); +} + +void demo_segments() { + // Demo of disconnected segments. Plot a circle with some pieces missing. + + Gnuplot gp; + + std::vector > > all_segments; + for(int j=0; j<10; j++) { + std::vector > segment; + for(int i=0; i<5; i++) { + double theta = double(j*10+i)/100*2*M_PI; + segment.push_back(std::make_pair( + std::cos(theta), std::sin(theta) + )); + } + all_segments.push_back(segment); + } + + gp << "plot '-' with linespoints\n"; + // NOTE: send2d is used here, rather than send1d. This puts a blank line between segments. + gp.send2d(all_segments); + + pause_if_needed(); +} + +void demo_image() { + // Example of plotting an image. Of course you are free (and encouraged) to + // use Blitz or Armadillo rather than std::vector in these situations. + + Gnuplot gp; + + std::vector > image; + for(int j=0; j<100; j++) { + std::vector row; + for(int i=0; i<100; i++) { + double x = (i-50.0)/5.0; + double y = (j-50.0)/5.0; + double z = std::cos(sqrt(x*x+y*y)); + row.push_back(z); + } + image.push_back(row); + } + + // It may seem counterintuitive that send1d should be used rather than + // send2d. The explanation is as follows. The "send2d" method puts each + // value on its own line, with blank lines between rows. This is what is + // expected by the splot command. The two "dimensions" here are the lines + // and the blank-line-delimited blocks. The "send1d" method doesn't group + // things into blocks. So the elements of each row are printed as columns, + // as expected by Gnuplot's "matrix with image" command. But images + // typically have lots of pixels, so sending as text is not the most + // efficient (although, it's not really that bad in the case of this + // example). See the binary version below. + // + //gp << "plot '-' matrix with image\n"; + //gp.send1d(image); + + // To be honest, Gnuplot's documentation for "binary" and for "image" are + // both unclear to me. The following example comes by trial-and-error. + gp << "plot '-' binary" << gp.binFmt2d(image, "array") << "with image\n"; + gp.sendBinary2d(image); + + pause_if_needed(); +} + +int main(int argc, char **argv) { + std::map demos; + + demos["basic"] = demo_basic; + demos["binary"] = demo_binary; + demos["tmpfile"] = demo_tmpfile; + demos["png"] = demo_png; + demos["vectors"] = demo_vectors; + demos["script_inline_text"] = demo_inline_text; + demos["script_inline_binary"] = demo_inline_binary; + demos["script_external_text"] = demo_external_text; + demos["script_external_binary"] = demo_external_binary; + demos["animation"] = demo_animation; + demos["nan"] = demo_NaN; + demos["segments"] = demo_segments; + demos["image"] = demo_image; + + if(argc < 2) { + printf("Usage: %s \n", argv[0]); + printf("Choose one of the following demos:\n"); + typedef std::pair demo_pair; + BOOST_FOREACH(const demo_pair &pair, demos) { + printf(" %s\n", pair.first.c_str()); + } + return 0; + } + + std::string arg(argv[1]); + if(!demos.count(arg)) { + printf("No such demo '%s'\n", arg.c_str()); + return 1; + } + + demos[arg](); +} diff --git a/gnuplot-iostream/gnuplot-iostream.h b/gnuplot-iostream/gnuplot-iostream.h new file mode 100644 index 0000000..69af409 --- /dev/null +++ b/gnuplot-iostream/gnuplot-iostream.h @@ -0,0 +1,2240 @@ +// vim:foldmethod=marker + +/* +Copyright (c) 2013 Daniel Stahlke (dan@stahlke.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* A C++ interface to gnuplot. + * Web page: http://www.stahlke.org/dan/gnuplot-iostream + * Documentation: https://github.com/dstahlke/gnuplot-iostream/wiki + * + * The whole library consists of this monolithic header file, for ease of installation (the + * Makefile and *.cc files are only for examples and tests). + * + * TODO: + * What version of boost is currently required? + * Callbacks via gnuplot's 'bind' function. This would allow triggering user functions when + * keys are pressed in the gnuplot window. However, it would require a PTY reader thread. + * Maybe temporary files read in a thread can replace PTY stuff. + */ + +#ifndef GNUPLOT_IOSTREAM_H +#define GNUPLOT_IOSTREAM_H + +// {{{1 Includes and defines + +#define GNUPLOT_IOSTREAM_VERSION 2 + +#ifndef GNUPLOT_ENABLE_CXX11 +# define GNUPLOT_ENABLE_CXX11 (__cplusplus >= 201103) +#endif + +// C system includes +#include +#ifdef GNUPLOT_ENABLE_PTY +# include +# include +#ifdef __APPLE__ +# include +#else +# include +#endif +#endif // GNUPLOT_ENABLE_PTY + +// C++ system includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if GNUPLOT_ENABLE_CXX11 +# include +#endif + +#include +#include +#include +#include +#include +#include +// This is the version of boost which has v3 of the filesystem libraries by default. +#if BOOST_VERSION >= 104600 +# define GNUPLOT_USE_TMPFILE +# include +#endif // BOOST_VERSION + +// This is used because VS2008 doesn't have stdint.h. +#include + +// Note: this is here for reverse compatibility. The new way to enable blitz support is to +// just include the gnuplot-iostream.h header after you include the blitz header (likewise for +// armadillo). +#ifdef GNUPLOT_ENABLE_BLITZ +# include +#endif + +#ifdef BOOST_STATIC_ASSERT_MSG +# define GNUPLOT_STATIC_ASSERT_MSG(cond, msg) BOOST_STATIC_ASSERT_MSG((cond), msg) +#else +# define GNUPLOT_STATIC_ASSERT_MSG(cond, msg) BOOST_STATIC_ASSERT((cond)) +#endif + +// If this is defined, warn about use of deprecated functions. +#ifdef GNUPLOT_DEPRECATE_WARN +# ifdef __GNUC__ +# define GNUPLOT_DEPRECATE(msg) __attribute__ ((deprecated(msg))) +# elif defined(_MSC_VER) +# define GNUPLOT_DEPRECATE(msg) __declspec(deprecated(msg)) +# else +# define GNUPLOT_DEPRECATE(msg) +# endif +#else +# define GNUPLOT_DEPRECATE(msg) +#endif + +// Patch for Windows by Damien Loison +#ifdef _WIN32 +# include +# define GNUPLOT_PCLOSE _pclose +# define GNUPLOT_POPEN _popen +# define GNUPLOT_FILENO _fileno +#else +# define GNUPLOT_PCLOSE pclose +# define GNUPLOT_POPEN popen +# define GNUPLOT_FILENO fileno +#endif + +#ifdef _WIN32 +# define GNUPLOT_ISNAN _isnan +#else +// cppreference.com says std::isnan is only for C++11. However, this seems to work on Linux +// and I am assuming that if isnan exists in math.h then std::isnan exists in cmath. +# define GNUPLOT_ISNAN std::isnan +#endif + +// MSVC gives a warning saying that fopen and getenv are not secure. But they are secure. +// Unfortunately their replacement functions are not simple drop-in replacements. The best +// solution is to just temporarily disable this warning whenever fopen or getenv is used. +// http://stackoverflow.com/a/4805353/1048959 +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define GNUPLOT_MSVC_WARNING_4996_PUSH \ + __pragma(warning(push)) \ + __pragma(warning(disable:4996)) +# define GNUPLOT_MSVC_WARNING_4996_POP \ + __pragma(warning(pop)) +#else +# define GNUPLOT_MSVC_WARNING_4996_PUSH +# define GNUPLOT_MSVC_WARNING_4996_POP +#endif + +#ifndef GNUPLOT_DEFAULT_COMMAND +#ifdef _WIN32 +// "pgnuplot" is considered deprecated according to the Internet. It may be faster. It +// doesn't seem to handle binary data though. +//# define GNUPLOT_DEFAULT_COMMAND "pgnuplot -persist" +// On Windows, gnuplot echos commands to stderr. So we forward its stderr to the bit bucket. +// Unfortunately, this means you will miss out on legitimate error messages. +# define GNUPLOT_DEFAULT_COMMAND "gnuplot -persist 2> NUL" +#else +# define GNUPLOT_DEFAULT_COMMAND "gnuplot -persist" +#endif +#endif + +// }}}1 + +namespace gnuplotio { + +// {{{1 Basic traits helpers +// +// The mechanisms constructed in this section enable us to detect what sort of datatype has +// been passed to a function. + +// This can be specialized as needed, in order to not use the STL interfaces for specific +// classes. +template +struct dont_treat_as_stl_container { + typedef boost::mpl::bool_ type; +}; + +BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator) + +template +struct is_like_stl_container { + typedef boost::mpl::and_< + typename has_value_type::type, + typename has_const_iterator::type, + boost::mpl::not_ > + > type; + static const bool value = type::value; +}; + +template +struct is_boost_tuple_nulltype { + static const bool value = false; + typedef boost::mpl::bool_ type; +}; + +template <> +struct is_boost_tuple_nulltype { + static const bool value = true; + typedef boost::mpl::bool_ type; +}; + +BOOST_MPL_HAS_XXX_TRAIT_DEF(head_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(tail_type) + +template +struct is_boost_tuple { + typedef boost::mpl::and_< + typename has_head_type::type, + typename has_tail_type::type + > type; + static const bool value = type::value; +}; + +// More fine-grained, but doesn't compile! +//template +//struct is_boost_tuple { +// typedef boost::mpl::and_< +// typename boost::is_class::type, +// typename boost::mpl::and_< +// typename has_head_type::type, +// typename boost::mpl::and_< +// typename has_tail_type::type, +// typename boost::mpl::or_< +// typename is_boost_tuple_nulltype::type, +// typename is_boost_tuple::type +// >::type +// >::type +// >::type +// > type; +//}; +// +//template <> +//struct is_boost_tuple { +// typedef boost::mpl::bool_ type; +//}; + +// }}}1 + +// {{{1 Tmpfile helper class +#ifdef GNUPLOT_USE_TMPFILE +// RAII temporary file. File is removed when this object goes out of scope. +class GnuplotTmpfile { +public: + GnuplotTmpfile() : + file(boost::filesystem::unique_path( + boost::filesystem::temp_directory_path() / + "tmp-gnuplot-%%%%-%%%%-%%%%-%%%%")) + { } + +private: + // noncopyable + GnuplotTmpfile(const GnuplotTmpfile &); + const GnuplotTmpfile& operator=(const GnuplotTmpfile &); + +public: + ~GnuplotTmpfile() { + // it is never good to throw exceptions from a destructor + try { + remove(file); + } catch(const std::exception &) { + std::cerr << "Failed to remove temporary file " << file << std::endl; + } + } + +public: + boost::filesystem::path file; +}; +#endif // GNUPLOT_USE_TMPFILE +// }}}1 + +// {{{1 Feedback helper classes +// +// Used for reading stuff sent from gnuplot via gnuplot's "print" function. +// +// For example, this is used for capturing mouse clicks in the gnuplot window. There are two +// implementations, only the first of which is complete. The first implementation allocates a +// PTY (pseudo terminal) which is written to by gnuplot and read by us. This only works in +// Linux. The second implementation creates a temporary file which is written to by gnuplot +// and read by us. However, this doesn't currently work since fscanf doesn't block. It would +// be possible to get this working using a more complicated mechanism (select or threads) but I +// haven't had the need for it. + +class GnuplotFeedback { +public: + GnuplotFeedback() { } + virtual ~GnuplotFeedback() { } + virtual std::string filename() const = 0; + virtual FILE *handle() const = 0; + +private: + // noncopyable + GnuplotFeedback(const GnuplotFeedback &); + const GnuplotFeedback& operator=(const GnuplotFeedback &); +}; + +#ifdef GNUPLOT_ENABLE_PTY +#define GNUPLOT_ENABLE_FEEDBACK +class GnuplotFeedbackPty : public GnuplotFeedback { +public: + explicit GnuplotFeedbackPty(bool debug_messages) : + pty_fn(), + pty_fh(NULL), + master_fd(-1), + slave_fd(-1) + { + // adapted from http://www.gnuplot.info/files/gpReadMouseTest.c + if(0 > openpty(&master_fd, &slave_fd, NULL, NULL, NULL)) { + perror("openpty"); + throw std::runtime_error("openpty failed"); + } + char pty_fn_buf[1024]; + if(ttyname_r(slave_fd, pty_fn_buf, 1024)) { + perror("ttyname_r"); + throw std::runtime_error("ttyname failed"); + } + pty_fn = std::string(pty_fn_buf); + if(debug_messages) { + std::cerr << "feedback_fn=" << pty_fn << std::endl; + } + + // disable echo + struct termios tios; + if(tcgetattr(slave_fd, &tios) < 0) { + perror("tcgetattr"); + throw std::runtime_error("tcgetattr failed"); + } + tios.c_lflag &= ~(ECHO | ECHONL); + if(tcsetattr(slave_fd, TCSAFLUSH, &tios) < 0) { + perror("tcsetattr"); + throw std::runtime_error("tcsetattr failed"); + } + + pty_fh = fdopen(master_fd, "r"); + if(!pty_fh) { + throw std::runtime_error("fdopen failed"); + } + } + +private: + // noncopyable + GnuplotFeedbackPty(const GnuplotFeedbackPty &); + const GnuplotFeedbackPty& operator=(const GnuplotFeedbackPty &); + +public: + ~GnuplotFeedbackPty() { + if(pty_fh) fclose(pty_fh); + if(master_fd > 0) ::close(master_fd); + if(slave_fd > 0) ::close(slave_fd); + } + + std::string filename() const { + return pty_fn; + } + + FILE *handle() const { + return pty_fh; + } + +private: + std::string pty_fn; + FILE *pty_fh; + int master_fd, slave_fd; +}; +//#elif defined GNUPLOT_USE_TMPFILE +//// Currently this doesn't work since fscanf doesn't block (need something like "tail -f") +//#define GNUPLOT_ENABLE_FEEDBACK +//class GnuplotFeedbackTmpfile : public GnuplotFeedback { +//public: +// explicit GnuplotFeedbackTmpfile(bool debug_messages) : +// tmp_file(), +// fh(NULL) +// { +// if(debug_messages) { +// std::cerr << "feedback_fn=" << filename() << std::endl; +// } +// GNUPLOT_MSVC_WARNING_4996_PUSH +// fh = std::fopen(filename().c_str(), "a"); +// GNUPLOT_MSVC_WARNING_4996_POP +// } +// +// ~GnuplotFeedbackTmpfile() { +// fclose(fh); +// } +// +//private: +// // noncopyable +// GnuplotFeedbackTmpfile(const GnuplotFeedbackTmpfile &); +// const GnuplotFeedbackTmpfile& operator=(const GnuplotFeedbackTmpfile &); +// +//public: +// std::string filename() const { +// return tmp_file.file.string(); +// } +// +// FILE *handle() const { +// return fh; +// } +// +//private: +// GnuplotTmpfile tmp_file; +// FILE *fh; +//}; +#endif // GNUPLOT_ENABLE_PTY, GNUPLOT_USE_TMPFILE +// }}}1 + +// {{{1 Traits and printers for entry datatypes +// +// This section contains the mechanisms for sending scalar and tuple data to gnuplot. Pairs +// and tuples are sent by appealing to the senders defined for their component scalar types. +// Senders for arrays are defined in a later section. +// +// There are three classes which need to be specialized for each supported datatype: +// 1. TextSender to send data as text. The default is to just send using the ostream's `<<` +// operator. +// 2. BinarySender to send data as binary, in a format which gnuplot can understand. There is +// no default implementation (unimplemented types raise a compile time error), however +// inheriting from FlatBinarySender will send the data literally as it is stored in memory. +// This suffices for most of the standard built-in types (e.g. uint32_t or double). +// 3. BinfmtSender sends a description of the data format to gnuplot (e.g. `%uint32`). Type +// `show datafile binary datasizes` in gnuplot to see a list of supported formats. + +// {{{2 Basic entry datatypes + +// Default TextSender, sends data using `<<` operator. +template +struct TextSender { + static void send(std::ostream &stream, const T &v) { + stream << v; + } +}; + +// Default BinarySender, raises a compile time error. +template +struct BinarySender { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "BinarySender class not specialized for this type"); + + // This is here to avoid further compilation errors, beyond what the assert prints. + static void send(std::ostream &stream, const T &v); +}; + +// This is a BinarySender implementation that just sends directly from memory. Data types +// which can be sent this way can have their BinarySender specialization inherit from this. +template +struct FlatBinarySender { + static void send(std::ostream &stream, const T &v) { + stream.write(reinterpret_cast(&v), sizeof(T)); + } +}; + +// Default BinfmtSender, raises a compile time error. +template +struct BinfmtSender { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "BinfmtSender class not specialized for this type"); + + // This is here to avoid further compilation errors, beyond what the assert prints. + static void send(std::ostream &); +}; + +// BinfmtSender implementations for basic data types supported by gnuplot. +// Types from boost/cstdint.hpp are used because VS2008 doesn't have stdint.h. +template<> struct BinfmtSender< float> { static void send(std::ostream &stream) { stream << "%float"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%double"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%int8"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%uint8"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%int16"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%uint16"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%int32"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%uint32"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%int64"; } }; +template<> struct BinfmtSender { static void send(std::ostream &stream) { stream << "%uint64"; } }; + +// BinarySender implementations for basic data types supported by gnuplot. These types can +// just be sent as stored in memory, so all these senders inherit from FlatBinarySender. +template<> struct BinarySender< float> : public FlatBinarySender< float> { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; +template<> struct BinarySender : public FlatBinarySender { }; + +// Make char types print as integers, not as characters. +template +struct CastIntTextSender { + static void send(std::ostream &stream, const T &v) { + stream << int(v); + } +}; +template<> struct TextSender< char> : public CastIntTextSender< char> { }; +template<> struct TextSender< signed char> : public CastIntTextSender< signed char> { }; +template<> struct TextSender< unsigned char> : public CastIntTextSender< unsigned char> { }; + +// Make sure that the same not-a-number string is printed on all platforms. +template +struct FloatTextSender { + static void send(std::ostream &stream, const T &v) { + if(GNUPLOT_ISNAN(v)) { stream << "nan"; } else { stream << v; } + } +}; +template<> struct TextSender< float> : FloatTextSender< float> { }; +template<> struct TextSender< double> : FloatTextSender< double> { }; +template<> struct TextSender : FloatTextSender { }; + +// }}}2 + +// {{{2 std::pair support + +template +struct TextSender > { + static void send(std::ostream &stream, const std::pair &v) { + TextSender::send(stream, v.first); + stream << " "; + TextSender::send(stream, v.second); + } +}; + +template +struct BinfmtSender > { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + BinfmtSender::send(stream); + } +}; + +template +struct BinarySender > { + static void send(std::ostream &stream, const std::pair &v) { + BinarySender::send(stream, v.first); + BinarySender::send(stream, v.second); + } +}; + +// }}}2 + +// {{{2 std::complex support + +template +struct TextSender > { + static void send(std::ostream &stream, const std::complex &v) { + TextSender::send(stream, v.real()); + stream << " "; + TextSender::send(stream, v.imag()); + } +}; + +template +struct BinfmtSender > { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + BinfmtSender::send(stream); + } +}; + +template +struct BinarySender > { + static void send(std::ostream &stream, const std::complex &v) { + BinarySender::send(stream, v.real()); + BinarySender::send(stream, v.imag()); + } +}; + +// }}}2 + +// {{{2 boost::tuple support + +template +struct TextSender, + boost::mpl::not_ > + > + >::type +> { + static void send(std::ostream &stream, const T &v) { + TextSender::send(stream, v.get_head()); + stream << " "; + TextSender::send(stream, v.get_tail()); + } +}; + +template +struct TextSender, + is_boost_tuple_nulltype + > + >::type +> { + static void send(std::ostream &stream, const T &v) { + TextSender::send(stream, v.get_head()); + } +}; + +template +struct BinfmtSender, + boost::mpl::not_ > + > + >::type +> { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + stream << " "; + BinfmtSender::send(stream); + } +}; + +template +struct BinfmtSender, + is_boost_tuple_nulltype + > + >::type +> { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + } +}; + +template +struct BinarySender, + boost::mpl::not_ > + > + >::type +> { + static void send(std::ostream &stream, const T &v) { + BinarySender::send(stream, v.get_head()); + BinarySender::send(stream, v.get_tail()); + } +}; + +template +struct BinarySender, + is_boost_tuple_nulltype + > + >::type +> { + static void send(std::ostream &stream, const T &v) { + BinarySender::send(stream, v.get_head()); + } +}; + +// }}}2 + +// {{{2 std::tuple support + +#if GNUPLOT_ENABLE_CXX11 + +// http://stackoverflow.com/questions/6245735/pretty-print-stdtuple + +template struct int_{}; // compile-time counter + +template +void std_tuple_formatcode_helper(std::ostream &stream, const Tuple *, int_) { + std_tuple_formatcode_helper(stream, (const Tuple *)(0), int_()); + stream << " "; + BinfmtSender::type>::send(stream); +} + +template +void std_tuple_formatcode_helper(std::ostream &stream, const Tuple *, int_<0>) { + BinfmtSender::type>::send(stream); +} + +template +struct BinfmtSender > { + typedef typename std::tuple Tuple; + + static void send(std::ostream &stream) { + std_tuple_formatcode_helper(stream, (const Tuple *)(0), int_()); + } +}; + +template +void std_tuple_textsend_helper(std::ostream &stream, const Tuple &v, int_) { + std_tuple_textsend_helper(stream, v, int_()); + stream << " "; + TextSender::type>::send(stream, std::get(v)); +} + +template +void std_tuple_textsend_helper(std::ostream &stream, const Tuple &v, int_<0>) { + TextSender::type>::send(stream, std::get<0>(v)); +} + +template +struct TextSender > { + typedef typename std::tuple Tuple; + + static void send(std::ostream &stream, const Tuple &v) { + std_tuple_textsend_helper(stream, v, int_()); + } +}; + +template +void std_tuple_binsend_helper(std::ostream &stream, const Tuple &v, int_) { + std_tuple_binsend_helper(stream, v, int_()); + BinarySender::type>::send(stream, std::get(v)); +} + +template +void std_tuple_binsend_helper(std::ostream &stream, const Tuple &v, int_<0>) { + BinarySender::type>::send(stream, std::get<0>(v)); +} + +template +struct BinarySender > { + typedef typename std::tuple Tuple; + + static void send(std::ostream &stream, const Tuple &v) { + std_tuple_binsend_helper(stream, v, int_()); + } +}; + +#endif // GNUPLOT_ENABLE_CXX11 + +// }}}2 + +// }}}1 + +// {{{1 ArrayTraits and Range classes +// +// This section handles sending of array data to gnuplot. It is rather complicated because of +// the diversity of storage schemes supported. For example, it treats a +// `std::pair, std::vector>` in the same way as a +// `std::vector>`, iterating through the two arrays in lockstep, and sending +// pairs to gnuplot as columns. In fact, any nested combination of pairs, tuples, STL +// containers, Blitz arrays, and Armadillo arrays is supported (with the caveat that, for +// instance, Blitz arrays should never be put into an STL container or you will suffer +// unpredictable results due the way Blitz handles assignment). Nested containers are +// considered to be multidimensional arrays. Although gnuplot only supports 1D and 2D arrays, +// our module is in principle not limited. +// +// The ArrayTraits class is specialized for every supported array or container type (the +// default, unspecialized, version of ArrayTraits exists only to tell you that something is +// *not* a container, via the is_container flag). ArrayTraits tells you the depth of a nested +// (or multidimensional) container, as well as the value type, and provides a specialized +// sort of iterator (a.k.a. "range"). Ranges are sort of like STL iterators, except that they +// have built-in knowledge of the end condition so you don't have to carry around both a +// begin() and an end() iterator like in STL. +// +// As an example of how this works, consider a std::pair of std::vectors. Ultimately this gets +// sent to gnuplot as two columns, so the two vectors need to be iterated in lockstep. +// The `value_type` of `std::pair, std::vector>` is then `std::pair` +// and this is what deferencing the range (iterator) gives. Internally, this range is built +// out of a pair of ranges (PairOfRange class), the `inc()` (advance to next element) +// method calls `inc()` on each of the children, and `deref()` calls `deref()` on each child +// and combines the results to return a `std::pair`. Tuples are handled as nested pairs. +// +// In addition to PairOfRange, there is also a VecOfRange class that can be used to treat the +// outermost part of a nested container as if it were a tuple. Since tuples are printed as +// columns, this is like treating a multidimensional array as if it were column-major. A +// VecOfRange is obtained by calling `get_columns_range`. This is used by, for instance, +// `send1d_colmajor`. The implementation is similar to that of PairOfRange. +// +// The range, accessed via `ArrayTraits::get_range`, will be of a different class depending +// on T, and this is defined by the ArrayTraits specialization for T. It will always have +// methods `inc()` to advance to the next element and `is_end()` for checking whether one has +// advanced past the final element. For nested containers, `deref_subiter()` returns a range +// iterator for the next nesting level. When at the innermost level of nesting, `deref()` +// returns the value of the entry the iterator points to (a scalar, pair, or tuple). +// Only one of `deref()` or `deref_subiter()` will be available, depending on whether there are +// deeper levels of nesting. The typedefs `value_type` and `subiter_type` tell the return +// types of these two methods. +// +// Support for standard C++ and boost containers and tuples of containers is provided in this +// section. Support for third party packages like Blitz and Armadillo is in a later section. + +// {{{2 ArrayTraits generic class and defaults + +// Error messages involving this stem from treating something that was not a container as if it +// was. This is only here to allow compiliation without errors in normal cases. +struct Error_WasNotContainer { + // This is just here to make VC++ happy. + // https://connect.microsoft.com/VisualStudio/feedback/details/777612/class-template-specialization-that-compiles-in-g-but-not-visual-c + typedef void subiter_type; +}; + +// Error messages involving this stem from calling deref instead of deref_subiter for a nested +// container. +struct Error_InappropriateDeref { }; + +// The unspecialized version of this class gives traits for things that are *not* arrays. +template +class ArrayTraits { +public: + // The value type of elements after all levels of nested containers have been dereferenced. + typedef Error_WasNotContainer value_type; + // The type of the range (a.k.a. iterator) that `get_range()` returns. + typedef Error_WasNotContainer range_type; + // Tells whether T is in fact a container type. + static const bool is_container = false; + // This flag supports the legacy behavior of automatically guessing whether the data should + // be treated as column major. This guessing happens when `send()` is called rather than + // `send1d()` or `send2d()`. This is deprecated, but is still supported for reverse + // compatibility. + static const bool allow_auto_unwrap = false; + // The number of levels of nesting, or the dimension of multidimensional arrays. + static const size_t depth = 0; + + // Returns the range (iterator) for an array. + static range_type get_range(const T &) { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T)==0), "argument was not a container"); + throw std::logic_error("static assert should have been triggered by this point"); + } +}; + +// Most specializations of ArrayTraits should inherit from this (with V set to the value type). +// It sets some default values. +template +class ArrayTraitsDefaults { +public: + typedef V value_type; + + static const bool is_container = true; + static const bool allow_auto_unwrap = true; + static const size_t depth = ArrayTraits::depth + 1; +}; + +// This handles reference types, such as are given with boost::tie. +// It also allows for instance "ArrayTraits" to match "ArrayTraits". +// I think this is okay to do... The alternative is to use remove_reference all over the place. +template +class ArrayTraits : public ArrayTraits { }; + +// FIXME - is this okay? +// It supports gp.send1d(std::forward_as_tuple(x, std::move(y))); +#if GNUPLOT_ENABLE_CXX11 +template +class ArrayTraits : public ArrayTraits { }; +#endif + +// }}}2 + +// {{{2 STL container support + +template +class IteratorRange { +public: + IteratorRange() { } + IteratorRange(const TI &_it, const TI &_end) : it(_it), end(_end) { } + + static const bool is_container = ArrayTraits::is_container; + typedef typename boost::mpl::if_c::type value_type; + typedef typename ArrayTraits::range_type subiter_type; + + bool is_end() const { return it == end; } + + void inc() { ++it; } + + value_type deref() const { + GNUPLOT_STATIC_ASSERT_MSG(sizeof(TV) && !is_container, + "deref called on nested container"); + if(is_end()) { + throw std::runtime_error("attepted to dereference past end of iterator"); + } + return *it; + } + + subiter_type deref_subiter() const { + GNUPLOT_STATIC_ASSERT_MSG(sizeof(TV) && is_container, + "deref_subiter called on non-nested container"); + if(is_end()) { + throw std::runtime_error("attepted to dereference past end of iterator"); + } + return ArrayTraits::get_range(*it); + } + +private: + TI it, end; +}; + +template +class ArrayTraits >::type +> : public ArrayTraitsDefaults { +public: + typedef IteratorRange range_type; + + static range_type get_range(const T &arg) { + return range_type(arg.begin(), arg.end()); + } +}; + +// }}}2 + +// {{{2 C style array support + +template +class ArrayTraits : public ArrayTraitsDefaults { +public: + typedef IteratorRange range_type; + + static range_type get_range(const T (&arg)[N]) { + return range_type(arg, arg+N); + } +}; + +// }}}2 + +// {{{2 std::pair support + +template +class PairOfRange { + template + friend void deref_and_print(std::ostream &, const PairOfRange &, PrintMode); + +public: + PairOfRange() { } + PairOfRange(const RT &_l, const RU &_r) : l(_l), r(_r) { } + + static const bool is_container = RT::is_container && RU::is_container; + + typedef std::pair value_type; + typedef PairOfRange subiter_type; + + bool is_end() const { + bool el = l.is_end(); + bool er = r.is_end(); + if(el != er) { + throw std::length_error("columns were different lengths"); + } + return el; + } + + void inc() { + l.inc(); + r.inc(); + } + + value_type deref() const { + return std::make_pair(l.deref(), r.deref()); + } + + subiter_type deref_subiter() const { + return subiter_type(l.deref_subiter(), r.deref_subiter()); + } + +private: + RT l; + RU r; +}; + +template +class ArrayTraits > { +public: + typedef PairOfRange::range_type, typename ArrayTraits::range_type> range_type; + typedef std::pair::value_type, typename ArrayTraits::value_type> value_type; + static const bool is_container = ArrayTraits::is_container && ArrayTraits::is_container; + // Don't allow colwrap since it's already wrapped. + static const bool allow_auto_unwrap = false; + // It is allowed for l_depth != r_depth, for example one column could be 'double' and the + // other column could be 'vector'. + static const size_t l_depth = ArrayTraits::depth; + static const size_t r_depth = ArrayTraits::depth; + static const size_t depth = (l_depth < r_depth) ? l_depth : r_depth; + + static range_type get_range(const std::pair &arg) { + return range_type( + ArrayTraits::get_range(arg.first), + ArrayTraits::get_range(arg.second) + ); + } +}; + +// }}}2 + +// {{{2 boost::tuple support + +template +class ArrayTraits, + boost::mpl::not_ > + > + >::type +> : public ArrayTraits< + typename std::pair< + typename T::head_type, + typename T::tail_type + > +> { +public: + typedef typename T::head_type HT; + typedef typename T::tail_type TT; + + typedef ArrayTraits > parent; + + static typename parent::range_type get_range(const T &arg) { + return typename parent::range_type( + ArrayTraits::get_range(arg.get_head()), + ArrayTraits::get_range(arg.get_tail()) + ); + } +}; + +template +class ArrayTraits, + is_boost_tuple_nulltype + > + >::type +> : public ArrayTraits< + typename T::head_type +> { + typedef typename T::head_type HT; + + typedef ArrayTraits parent; + +public: + static typename parent::range_type get_range(const T &arg) { + return parent::get_range(arg.get_head()); + } +}; + +// }}}2 + +// {{{2 std::tuple support + +#if GNUPLOT_ENABLE_CXX11 + +template +struct StdTupUnwinder { + typedef std::pair< + typename StdTupUnwinder::type, + typename std::tuple_element::type + > type; + + static typename ArrayTraits::range_type get_range(const Tuple &arg) { + return typename ArrayTraits::range_type( + StdTupUnwinder::get_range(arg), + ArrayTraits::type>::get_range(std::get(arg)) + ); + } +}; + +template +struct StdTupUnwinder { + typedef typename std::tuple_element<0, Tuple>::type type; + + static typename ArrayTraits::range_type get_range(const Tuple &arg) { + return ArrayTraits::get_range(std::get<0>(arg)); + } +}; + +template +class ArrayTraits > : + public ArrayTraits, sizeof...(Args)-1>::type> +{ + typedef std::tuple Tuple; + typedef ArrayTraits::type> parent; + +public: + static typename parent::range_type get_range(const Tuple &arg) { + return StdTupUnwinder, sizeof...(Args)-1>::get_range(arg); + } +}; + +#endif // GNUPLOT_ENABLE_CXX11 + +// }}}2 + +// {{{2 Support column unwrap of container (VecOfRange) +// +// VecOfRange (created via `get_columns_range()`) treats the outermost level of a nested +// container as if it were a tuple. Since tuples are sent to gnuplot as columns, this has the +// effect of addressing a multidimensional array in column major order. + +template +class VecOfRange { + template + friend void deref_and_print(std::ostream &, const VecOfRange &, PrintMode); + +public: + VecOfRange() { } + explicit VecOfRange(const std::vector &_rvec) : rvec(_rvec) { } + + static const bool is_container = RT::is_container; + // Don't allow colwrap since it's already wrapped. + static const bool allow_auto_unwrap = false; + + typedef std::vector value_type; + typedef VecOfRange subiter_type; + + bool is_end() const { + if(rvec.empty()) return true; + bool ret = rvec[0].is_end(); + for(size_t i=1; i subvec(rvec.size()); + for(size_t i=0; i rvec; +}; + +template +VecOfRange::range_type::subiter_type> +get_columns_range(const T &arg) { + typedef typename ArrayTraits::range_type::subiter_type U; + std::vector rvec; + typename ArrayTraits::range_type outer = ArrayTraits::get_range(arg); + while(!outer.is_end()) { + rvec.push_back(outer.deref_subiter()); + outer.inc(); + } + VecOfRange ret(rvec); + return ret; +} + +// }}}2 + +// }}}1 + +// {{{1 Array printing functions +// +// This section coordinates the sending of data to gnuplot. The ArrayTraits mechanism tells us +// about nested containers and provides iterators over them. Here we make use of this, +// deciding what dimensions should be treated as rows, columns, or blocks, telling gnuplot the +// size of the array if needed, and so on. + +// If this is set, then text-mode data will be sent in a format that is not compatible with +// gnuplot, but which helps the programmer tell what the library is thinking. Basically it +// puts brackets around groups of items and puts a message delineating blocks of data. +static bool debug_array_print = 0; + +// This is thrown when an empty container is being plotted. This exception should always +// be caught and should not propagate to the user. +class plotting_empty_container : public std::length_error { +public: + plotting_empty_container() : std::length_error("plotting empty container") { } +}; + +// {{{2 Tags (like enums for metaprogramming) + +// These tags define what our goal is, what sort of thing should ultimately be sent to the +// ostream. These tags are passed to the PrintMode template argument of the functions in this +// section. +// +// ModeText - Sends the data in an array in text format +// ModeBinary - Sends the data in an array in binary format +// ModeBinfmt - Sends the gnuplot format code for binary data (e.g. "%double%double") +// ModeSize - Sends the size of an array. Needed when sending binary data. +struct ModeText { static const bool is_text = 1; static const bool is_binfmt = 0; static const bool is_size = 0; }; +struct ModeBinary { static const bool is_text = 0; static const bool is_binfmt = 0; static const bool is_size = 0; }; +struct ModeBinfmt { static const bool is_text = 0; static const bool is_binfmt = 1; static const bool is_size = 0; }; +struct ModeSize { static const bool is_text = 0; static const bool is_binfmt = 0; static const bool is_size = 1; }; + +// Whether to treat the outermost level of a nested container as columns (column major mode). +struct ColUnwrapNo { }; +struct ColUnwrapYes { }; + +// The user must give a hint to describe how nested containers are to be interpreted. This is +// done by calling e.g. `send1d_colmajor()` or `send2d()`. This hint is then described by the +// following tags. This is passed to the OrganizationMode template argument. +struct Mode1D { static std::string class_name() { return "Mode1D" ; } }; +struct Mode2D { static std::string class_name() { return "Mode2D" ; } }; +struct Mode1DUnwrap { static std::string class_name() { return "Mode1DUnwrap"; } }; +struct Mode2DUnwrap { static std::string class_name() { return "Mode2DUnwrap"; } }; +// Support for the legacy behavior that guesses which of the above four modes should be used. +struct ModeAuto { static std::string class_name() { return "ModeAuto" ; } }; + +// }}}2 + +// {{{2 ModeAutoDecoder +// +// ModeAuto guesses which of Mode1D, Mode2D, Mode1DUnwrap, or Mode2DUnwrap should be used. +// This is provided for reverse compatibility; it is better to specify explicitly which mode to +// use. Since this is only for reverse compatibility, and shouldn't be used, I'm not going to +// spell out what the rules are. See below for details. + +template +struct ModeAutoDecoder { }; + +template +struct ModeAutoDecoder::depth == 1) + >::type> +{ + typedef Mode1D mode; +}; + +template +struct ModeAutoDecoder::depth == 2) && + !ArrayTraits::allow_auto_unwrap + >::type> +{ + typedef Mode2D mode; +}; + +template +struct ModeAutoDecoder::depth == 2) && + ArrayTraits::allow_auto_unwrap + >::type> +{ + typedef Mode1DUnwrap mode; +}; + +template +struct ModeAutoDecoder::depth > 2) && + ArrayTraits::allow_auto_unwrap + >::type> +{ + typedef Mode2DUnwrap mode; +}; + +template +struct ModeAutoDecoder::depth > 2) && + !ArrayTraits::allow_auto_unwrap + >::type> +{ + typedef Mode2D mode; +}; + +// }}}2 + +// The data is processed using several levels of functions that call each other in sequence, +// each defined in a subsection of code below. Because C++ wants you to declare a function +// before using it, we begin with the innermost function. So in order to see the sequence in +// which these are called, you should read the following subsections in reverse order. Nested +// arrays are formated into blocks (for 2D data) and lines (for 1D or 2D data), then further +// nesting levels are formatted into columns. Also tag dispatching is used in order to define +// various sorts of behavior. Each of these tasks is handled by one of the following +// subsections. + +// {{{2 send_scalar() +// +// Send a scalar in one of three possible ways: via TextSender, BinarySender, or BinfmtSender, +// depending on which PrintMode tag is passed to the function. + +template +void send_scalar(std::ostream &stream, const T &arg, ModeText) { + TextSender::send(stream, arg); +} + +template +void send_scalar(std::ostream &stream, const T &arg, ModeBinary) { + BinarySender::send(stream, arg); +} + +template +void send_scalar(std::ostream &stream, const T &, ModeBinfmt) { + BinfmtSender::send(stream); +} + +// }}}2 + +// {{{2 deref_and_print() +// +// Dereferences and prints the given range (iterator). At this point we are done with treating +// containers as blocks (for 2D data) and lines (for 1D or 2D data). Any further levels of +// nested containers will at this point be treated as columns. + +// If arg is not a container, then print it via send_scalar(). +template +typename boost::disable_if_c::type +deref_and_print(std::ostream &stream, const T &arg, PrintMode) { + const typename T::value_type &v = arg.deref(); + send_scalar(stream, v, PrintMode()); +} + +// If arg is a container (but not a PairOfRange or VecOfRange, which are handled below) then +// treat the contents as columns, iterating over the contents recursively. If outputting in +// text mode, put a space between columns. +template +typename boost::enable_if_c::type +deref_and_print(std::ostream &stream, const T &arg, PrintMode) { + if(arg.is_end()) throw plotting_empty_container(); + typename T::subiter_type subrange = arg.deref_subiter(); + if(PrintMode::is_binfmt && subrange.is_end()) throw plotting_empty_container(); + if(debug_array_print && PrintMode::is_text) stream << "{"; + bool first = true; + while(!subrange.is_end()) { + if(!first && PrintMode::is_text) stream << " "; + first = false; + deref_and_print(stream, subrange, PrintMode()); + subrange.inc(); + } + if(debug_array_print && PrintMode::is_text) stream << "}"; +} + +// PairOfRange is treated as columns. In text mode, put a space between columns. +template +void deref_and_print(std::ostream &stream, const PairOfRange &arg, PrintMode) { + deref_and_print(stream, arg.l, PrintMode()); + if(PrintMode::is_text) stream << " "; + deref_and_print(stream, arg.r, PrintMode()); +} + +// VecOfRange is treated as columns. In text mode, put a space between columns. +template +void deref_and_print(std::ostream &stream, const VecOfRange &arg, PrintMode) { + if(PrintMode::is_binfmt && arg.rvec.empty()) throw plotting_empty_container(); + for(size_t i=0; i +typename boost::enable_if_c<(Depth==1) && !PrintMode::is_size>::type +print_block(std::ostream &stream, T &arg, PrintMode) { + if(PrintMode::is_binfmt && arg.is_end()) throw plotting_empty_container(); + for(; !arg.is_end(); arg.inc()) { + //print_entry(arg.deref()); + deref_and_print(stream, arg, PrintMode()); + // If asked to print the binary format string, only the first element needs to be + // looked at. + if(PrintMode::is_binfmt) break; + if(PrintMode::is_text) stream << std::endl; + } +} + +// Depth>1 and we are not asked to print the size of the array. Loop over the range and +// recurse into print_block() with Depth -> Depth-1. +template +typename boost::enable_if_c<(Depth>1) && !PrintMode::is_size>::type +print_block(std::ostream &stream, T &arg, PrintMode) { + if(PrintMode::is_binfmt && arg.is_end()) throw plotting_empty_container(); + bool first = true; + for(; !arg.is_end(); arg.inc()) { + if(first) { + first = false; + } else { + if(PrintMode::is_text) stream << std::endl; + } + if(debug_array_print && PrintMode::is_text) stream << "" << std::endl; + if(arg.is_end()) throw plotting_empty_container(); + typename T::subiter_type sub = arg.deref_subiter(); + print_block(stream, sub, PrintMode()); + // If asked to print the binary format string, only the first element needs to be + // looked at. + if(PrintMode::is_binfmt) break; + } +} + +// Determine how many elements are in the given range. Used in the functions below. +template +size_t get_range_size(const T &arg) { + // FIXME - not the fastest way. Implement a size() method for range. + size_t ret = 0; + for(T i=arg; !i.is_end(); i.inc()) ++ret; + return ret; +} + +// Depth==1 and we are asked to print the size of the array. +template +typename boost::enable_if_c<(Depth==1) && PrintMode::is_size>::type +print_block(std::ostream &stream, T &arg, PrintMode) { + stream << get_range_size(arg); +} + +// Depth>1 and we are asked to print the size of the array. +template +typename boost::enable_if_c<(Depth>1) && PrintMode::is_size>::type +print_block(std::ostream &stream, T &arg, PrintMode) { + if(arg.is_end()) throw plotting_empty_container(); + // It seems that size for two dimensional arrays needs the fastest varying index first, + // contrary to intuition. The gnuplot documentation is not too clear on this point. + typename T::subiter_type sub = arg.deref_subiter(); + print_block(stream, sub, PrintMode()); + stream << "," << get_range_size(arg); +} + +// }}}2 + +// {{{2 handle_colunwrap_tag() +// +// If passed the ColUnwrapYes then treat the outermost nested container as columns by calling +// get_columns_range(). Otherwise just call get_range(). The range iterator is then passed to +// print_block() for further processing. + +template +void handle_colunwrap_tag(std::ostream &stream, const T &arg, ColUnwrapNo, PrintMode) { + GNUPLOT_STATIC_ASSERT_MSG(ArrayTraits::depth >= Depth, "container not deep enough"); + typename ArrayTraits::range_type range = ArrayTraits::get_range(arg); + print_block(stream, range, PrintMode()); +} + +template +void handle_colunwrap_tag(std::ostream &stream, const T &arg, ColUnwrapYes, PrintMode) { + GNUPLOT_STATIC_ASSERT_MSG(ArrayTraits::depth >= Depth+1, "container not deep enough"); + VecOfRange::range_type::subiter_type> cols = get_columns_range(arg); + print_block(stream, cols, PrintMode()); +} + +// }}}2 + +// {{{2 handle_organization_tag() +// +// Parse the OrganizationMode tag then forward to handle_colunwrap_tag() for further +// processing. If passed the Mode1D or Mode2D tags, then set Depth=1 or Depth=2. If passed +// Mode{1,2}DUnwrap then use the ColUnwrapYes tag. If passed ModeAuto (which is for legacy +// support) then use ModeAutoDecoder to guess which of Mode1D, Mode2D, etc. should be used. + +template +void handle_organization_tag(std::ostream &stream, const T &arg, Mode1D, PrintMode) { + handle_colunwrap_tag<1>(stream, arg, ColUnwrapNo(), PrintMode()); +} + +template +void handle_organization_tag(std::ostream &stream, const T &arg, Mode2D, PrintMode) { + handle_colunwrap_tag<2>(stream, arg, ColUnwrapNo(), PrintMode()); +} + +template +void handle_organization_tag(std::ostream &stream, const T &arg, Mode1DUnwrap, PrintMode) { + handle_colunwrap_tag<1>(stream, arg, ColUnwrapYes(), PrintMode()); +} + +template +void handle_organization_tag(std::ostream &stream, const T &arg, Mode2DUnwrap, PrintMode) { + handle_colunwrap_tag<2>(stream, arg, ColUnwrapYes(), PrintMode()); +} + +template +void handle_organization_tag(std::ostream &stream, const T &arg, ModeAuto, PrintMode) { + handle_organization_tag(stream, arg, typename ModeAutoDecoder::mode(), PrintMode()); +} + +// }}}2 + +// The entry point for the processing defined in this section. It just forwards immediately to +// handle_organization_tag(). This function is only here to give a sane name to the entry +// point. +// +// The allowed values for the OrganizationMode and PrintMode tags are defined in the beginning +// of this section. +template +void top_level_array_sender(std::ostream &stream, const T &arg, OrganizationMode, PrintMode) { + handle_organization_tag(stream, arg, OrganizationMode(), PrintMode()); +} + +// }}}1 + +// {{{1 FileHandleWrapper + +// This holds the file handle that gnuplot commands will be sent to. The purpose of this +// wrapper is twofold: +// 1. It allows storing the FILE* before it gets passed to the boost::iostreams::stream +// constructor (which is a base class of the main Gnuplot class). This is accomplished +// via multiple inheritance as described at http://stackoverflow.com/a/3821756/1048959 +// 2. It remembers whether the handle needs to be closed via fclose or pclose. +struct FileHandleWrapper { + FileHandleWrapper(std::FILE *_fh, bool _should_use_pclose) : + wrapped_fh(_fh), should_use_pclose(_should_use_pclose) { } + + void fh_close() { + if(should_use_pclose) { + if(GNUPLOT_PCLOSE(wrapped_fh)) { + std::cerr << "pclose returned error" << std::endl; + } + } else { + if(fclose(wrapped_fh)) { + std::cerr << "fclose returned error" << std::endl; + } + } + } + + int fh_fileno() { + return GNUPLOT_FILENO(wrapped_fh); + } + + std::FILE *wrapped_fh; + bool should_use_pclose; +}; + +// }}}1 + +// {{{1 Main class + +class Gnuplot : + // Some setup needs to be done before obtaining the file descriptor that gets passed to + // boost::iostreams::stream. This is accomplished by using a multiple inheritance trick, + // as described at http://stackoverflow.com/a/3821756/1048959 + private FileHandleWrapper, + public boost::iostreams::stream +{ +private: + static std::string get_default_cmd() { + GNUPLOT_MSVC_WARNING_4996_PUSH + char *from_env = std::getenv("GNUPLOT_IOSTREAM_CMD"); + GNUPLOT_MSVC_WARNING_4996_POP + if(from_env && from_env[0]) { + return from_env; + } else { + return GNUPLOT_DEFAULT_COMMAND; + } + } + + static FileHandleWrapper open_cmdline(const std::string &in) { + std::string cmd = in.empty() ? get_default_cmd() : in; + assert(!cmd.empty()); + if(cmd[0] == '>') { + std::string fn = cmd.substr(1); + GNUPLOT_MSVC_WARNING_4996_PUSH + FILE *fh = std::fopen(fn.c_str(), "w"); + GNUPLOT_MSVC_WARNING_4996_POP + if(!fh) throw(std::ios_base::failure("cannot open file "+fn)); + return FileHandleWrapper(fh, false); + } else { + FILE *fh = GNUPLOT_POPEN(cmd.c_str(), "w"); + if(!fh) throw(std::ios_base::failure("cannot open pipe "+cmd)); + return FileHandleWrapper(fh, true); + } + } + +public: + explicit Gnuplot(const std::string &_cmd="") : + FileHandleWrapper(open_cmdline(_cmd)), + boost::iostreams::stream( + fh_fileno(), +#if BOOST_VERSION >= 104400 + boost::iostreams::never_close_handle +#else + false +#endif + ), + feedback(NULL), + tmp_files(), + debug_messages(false) + { + *this << std::scientific << std::setprecision(18); // refer + } + + explicit Gnuplot(FILE *_fh) : + FileHandleWrapper(_fh, 0), + boost::iostreams::stream( + fh_fileno(), +#if BOOST_VERSION >= 104400 + boost::iostreams::never_close_handle +#else + false +#endif + ), + feedback(NULL), + tmp_files(), + debug_messages(false) + { + *this << std::scientific << std::setprecision(18); // refer + } + +private: + // noncopyable + Gnuplot(const Gnuplot &); + const Gnuplot& operator=(const Gnuplot &); + +public: + ~Gnuplot() { + if(debug_messages) { + std::cerr << "ending gnuplot session" << std::endl; + } + + // FIXME - boost's close method calls close() on the file descriptor, but we need to + // use sometimes use pclose instead. For now, just skip calling boost's close and use + // flush just in case. + do_flush(); + // Wish boost had a pclose method... + //close(); + + fh_close(); + + delete feedback; + } + + void clearTmpfiles() { + // destructors will cause deletion + tmp_files.clear(); + } + +private: + void do_flush() { + *this << std::flush; + fflush(wrapped_fh); + } + + std::string make_tmpfile() { +#ifdef GNUPLOT_USE_TMPFILE + boost::shared_ptr tmp_file(new GnuplotTmpfile()); + // The file will be removed once the pointer is removed from the + // tmp_files container. + tmp_files.push_back(tmp_file); + return tmp_file->file.string(); +#else + throw(std::logic_error("no filename given and temporary files not enabled")); +#endif // GNUPLOT_USE_TMPFILE + } + +public: +// {{{2 Generic sender routines. +// +// These are declared public, but are undocumented. It is recommended to use the functions in +// the next section, which serve as adapters that pass specific values for the OrganizationMode +// tag. + + template + Gnuplot &send(const T &arg, OrganizationMode) { + top_level_array_sender(*this, arg, OrganizationMode(), ModeText()); + *this << "e" << std::endl; // gnuplot's "end of array" token + do_flush(); // probably not really needed, but doesn't hurt + return *this; + } + + template + Gnuplot &sendBinary(const T &arg, OrganizationMode) { + top_level_array_sender(*this, arg, OrganizationMode(), ModeBinary()); + do_flush(); // probably not really needed, but doesn't hurt + return *this; + } + + template + std::string binfmt(const T &arg, const std::string &arr_or_rec, OrganizationMode) { + assert((arr_or_rec == "array") || (arr_or_rec == "record")); + std::string ret; + try { + std::ostringstream tmp; + tmp << " format='"; + top_level_array_sender(tmp, arg, OrganizationMode(), ModeBinfmt()); + tmp << "' " << arr_or_rec << "=("; + top_level_array_sender(tmp, arg, OrganizationMode(), ModeSize()); + tmp << ")"; + tmp << " "; + ret = tmp.str(); + } catch(const plotting_empty_container &) { + ret = std::string(" format='' ") + arr_or_rec + "=(0) "; + } + return ret; + } + + // NOTE: empty filename makes temporary file + template + std::string file(const T &arg, std::string filename, OrganizationMode) { + if(filename.empty()) filename = make_tmpfile(); + std::fstream tmp_stream(filename.c_str(), std::fstream::out); + top_level_array_sender(tmp_stream, arg, OrganizationMode(), ModeText()); + tmp_stream.close(); + + std::ostringstream cmdline; + // FIXME - hopefully filename doesn't contain quotes or such... + cmdline << " '" << filename << "' "; + return cmdline.str(); + } + + // NOTE: empty filename makes temporary file + template + std::string binaryFile(const T &arg, std::string filename, const std::string &arr_or_rec, OrganizationMode) { + if(filename.empty()) filename = make_tmpfile(); + std::fstream tmp_stream(filename.c_str(), std::fstream::out | std::fstream::binary); + top_level_array_sender(tmp_stream, arg, OrganizationMode(), ModeBinary()); + tmp_stream.close(); + + std::ostringstream cmdline; + // FIXME - hopefully filename doesn't contain quotes or such... + cmdline << " '" << filename << "' binary" << binfmt(arg, arr_or_rec, OrganizationMode()); + return cmdline.str(); + } + +// }}}2 + +// {{{2 Deprecated data sending interface that guesses an appropriate OrganizationMode. This is here +// for reverse compatibility. Don't use it. A warning will be printed if +// GNUPLOT_DEPRECATE_WARN is defined. + + template Gnuplot GNUPLOT_DEPRECATE("use send1d or send2d") + &send(const T &arg) { return send(arg, ModeAuto()); } + + template std::string GNUPLOT_DEPRECATE("use binfmt1d or binfmt2d") + binfmt(const T &arg, const std::string &arr_or_rec="array") + { return binfmt(arg, arr_or_rec, ModeAuto()); } + + template Gnuplot GNUPLOT_DEPRECATE("use sendBinary1d or sendBinary2d") + &sendBinary(const T &arg) { return sendBinary(arg, ModeAuto()); } + + template std::string GNUPLOT_DEPRECATE("use file1d or file2d") + file(const T &arg, const std::string &filename="") + { return file(arg, filename, ModeAuto()); } + + template std::string GNUPLOT_DEPRECATE("use binArr1d or binArr2d") + binaryFile(const T &arg, const std::string &filename="", const std::string &arr_or_rec="array") + { return binaryFile(arg, filename, arr_or_rec, ModeAuto()); } + +// }}}2 + +// {{{2 Public (documented) data sending interface. +// +// It seems odd to define 16 different functions, but I think this ends up being the most +// convenient in terms of usage by the end user. + + template Gnuplot &send1d (const T &arg) { return send(arg, Mode1D ()); } + template Gnuplot &send2d (const T &arg) { return send(arg, Mode2D ()); } + template Gnuplot &send1d_colmajor(const T &arg) { return send(arg, Mode1DUnwrap()); } + template Gnuplot &send2d_colmajor(const T &arg) { return send(arg, Mode2DUnwrap()); } + + template Gnuplot &sendBinary1d (const T &arg) { return sendBinary(arg, Mode1D ()); } + template Gnuplot &sendBinary2d (const T &arg) { return sendBinary(arg, Mode2D ()); } + template Gnuplot &sendBinary1d_colmajor(const T &arg) { return sendBinary(arg, Mode1DUnwrap()); } + template Gnuplot &sendBinary2d_colmajor(const T &arg) { return sendBinary(arg, Mode2DUnwrap()); } + + template std::string file1d (const T &arg, const std::string &filename="") { return file(arg, filename, Mode1D ()); } + template std::string file2d (const T &arg, const std::string &filename="") { return file(arg, filename, Mode2D ()); } + template std::string file1d_colmajor(const T &arg, const std::string &filename="") { return file(arg, filename, Mode1DUnwrap()); } + template std::string file2d_colmajor(const T &arg, const std::string &filename="") { return file(arg, filename, Mode2DUnwrap()); } + + template std::string binFmt1d (const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec, Mode1D ()); } + template std::string binFmt2d (const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec, Mode2D ()); } + template std::string binFmt1d_colmajor(const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec, Mode1DUnwrap()); } + template std::string binFmt2d_colmajor(const T &arg, const std::string &arr_or_rec) { return binfmt(arg, arr_or_rec, Mode2DUnwrap()); } + + template std::string binFile1d (const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec, Mode1D ()); } + template std::string binFile2d (const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec, Mode2D ()); } + template std::string binFile1d_colmajor(const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec, Mode1DUnwrap()); } + template std::string binFile2d_colmajor(const T &arg, const std::string &arr_or_rec, const std::string &filename="") { return binaryFile(arg, filename, arr_or_rec, Mode2DUnwrap()); } + +// }}}2 + +#ifdef GNUPLOT_ENABLE_FEEDBACK +public: + // Input variables are set to the mouse position and button. If the gnuplot + // window is closed, button -1 is returned. The msg parameter is the prompt + // that is printed to the console. + void getMouse( + double &mx, double &my, int &mb, + std::string msg="Click Mouse!" + ) { + allocFeedback(); + + *this << "set mouse" << std::endl; + *this << "pause mouse \"" << msg << "\\n\"" << std::endl; + *this << "if (exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_BUTTON; else print 0, 0, -1;" << std::endl; + if(debug_messages) { + std::cerr << "begin scanf" << std::endl; + } + if(3 != fscanf(feedback->handle(), "%50lf %50lf %50d", &mx, &my, &mb)) { + throw std::runtime_error("could not parse reply"); + } + if(debug_messages) { + std::cerr << "end scanf" << std::endl; + } + } + +private: + void allocFeedback() { + if(!feedback) { +#ifdef GNUPLOT_ENABLE_PTY + feedback = new GnuplotFeedbackPty(debug_messages); +//#elif defined GNUPLOT_USE_TMPFILE +//// Currently this doesn't work since fscanf doesn't block (need something like "tail -f") +// feedback = new GnuplotFeedbackTmpfile(debug_messages); +#else + // This shouldn't happen because we are in an `#ifdef GNUPLOT_ENABLE_FEEDBACK` + // block which should only be activated if GNUPLOT_ENABLE_PTY is defined. + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "No feedback mechanism defined."); +#endif + *this << "set print \"" << feedback->filename() << "\"" << std::endl; + } + } +#endif // GNUPLOT_ENABLE_FEEDBACK + +private: + GnuplotFeedback *feedback; +#ifdef GNUPLOT_USE_TMPFILE + std::vector > tmp_files; +#else + // just a placeholder + std::vector tmp_files; +#endif // GNUPLOT_USE_TMPFILE + +public: + bool debug_messages; +}; + +// }}}1 + +} // namespace gnuplotio + +// The first version of this library didn't use namespaces, and now this must be here forever +// for reverse compatibility. +using gnuplotio::Gnuplot; + +#endif // GNUPLOT_IOSTREAM_H + +// {{{1 Support for 3rd party array libraries + +// {{{2 Blitz support + +// This is outside of the main header guard so that it will be compiled when people do +// something like this: +// #include "gnuplot-iostream.h" +// #include +// #include "gnuplot-iostream.h" +// Note that it has its own header guard to avoid double inclusion. + +#ifdef BZ_BLITZ_H +#ifndef GNUPLOT_BLITZ_SUPPORT_LOADED +#define GNUPLOT_BLITZ_SUPPORT_LOADED +namespace gnuplotio { + +template +struct BinfmtSender > { + static void send(std::ostream &stream) { + for(int i=0; i::send(stream); + } + } +}; + +template +struct TextSender > { + static void send(std::ostream &stream, const blitz::TinyVector &v) { + for(int i=0; i::send(stream, v[i]); + } + } +}; + +template +struct BinarySender > { + static void send(std::ostream &stream, const blitz::TinyVector &v) { + for(int i=0; i::send(stream, v[i]); + } + } +}; + +class Error_WasBlitzPartialSlice { }; + +template +class BlitzIterator { +public: + BlitzIterator() : p(NULL) { } + BlitzIterator( + const blitz::Array *_p, + const blitz::TinyVector _idx + ) : p(_p), idx(_idx) { } + + typedef Error_WasBlitzPartialSlice value_type; + typedef BlitzIterator subiter_type; + static const bool is_container = true; + + // FIXME - it would be nice to also handle one-based arrays + bool is_end() const { + return idx[ArrayDim-SliceDim] == p->shape()[ArrayDim-SliceDim]; + } + + void inc() { + ++idx[ArrayDim-SliceDim]; + } + + value_type deref() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "cannot deref a blitz slice"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + subiter_type deref_subiter() const { + return BlitzIterator(p, idx); + } + +private: + const blitz::Array *p; + blitz::TinyVector idx; +}; + +template +class BlitzIterator { +public: + BlitzIterator() : p(NULL) { } + BlitzIterator( + const blitz::Array *_p, + const blitz::TinyVector _idx + ) : p(_p), idx(_idx) { } + + typedef T value_type; + typedef Error_WasNotContainer subiter_type; + static const bool is_container = false; + + // FIXME - it would be nice to also handle one-based arrays + bool is_end() const { + return idx[ArrayDim-1] == p->shape()[ArrayDim-1]; + } + + void inc() { + ++idx[ArrayDim-1]; + } + + value_type deref() const { + return (*p)(idx); + } + + subiter_type deref_subiter() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container"); + throw std::logic_error("static assert should have been triggered by this point"); + } + +private: + const blitz::Array *p; + blitz::TinyVector idx; +}; + +template +class ArrayTraits > : public ArrayTraitsDefaults { +public: + static const bool allow_auto_unwrap = false; + static const size_t depth = ArrayTraits::depth + ArrayDim; + + typedef BlitzIterator range_type; + + static range_type get_range(const blitz::Array &arg) { + blitz::TinyVector start_idx; + start_idx = 0; + return range_type(&arg, start_idx); + } +}; + +} // namespace gnuplotio +#endif // GNUPLOT_BLITZ_SUPPORT_LOADED +#endif // BZ_BLITZ_H + +// }}}2 + +// {{{2 Armadillo support + +// This is outside of the main header guard so that it will be compiled when people do +// something like this: +// #include "gnuplot-iostream.h" +// #include +// #include "gnuplot-iostream.h" +// Note that it has its own header guard to avoid double inclusion. + +#ifdef ARMA_INCLUDES +#ifndef GNUPLOT_ARMADILLO_SUPPORT_LOADED +#define GNUPLOT_ARMADILLO_SUPPORT_LOADED +namespace gnuplotio { + +template struct dont_treat_as_stl_container > { typedef boost::mpl::bool_ type; }; +template struct dont_treat_as_stl_container > { typedef boost::mpl::bool_ type; }; +template struct dont_treat_as_stl_container > { typedef boost::mpl::bool_ type; }; +template struct dont_treat_as_stl_container > { typedef boost::mpl::bool_ type; }; +template struct dont_treat_as_stl_container > { typedef boost::mpl::bool_ type; }; + +// {{{3 Cube + +template +class ArrayTraits > : public ArrayTraitsDefaults { + class SliceRange { + public: + SliceRange() : p(NULL), col(0), slice(0) { } + explicit SliceRange(const arma::Cube *_p, size_t _row, size_t _col) : + p(_p), row(_row), col(_col), slice(0) { } + + typedef T value_type; + typedef Error_WasNotContainer subiter_type; + static const bool is_container = false; + + bool is_end() const { return slice == p->n_slices; } + + void inc() { ++slice; } + + value_type deref() const { + return (*p)(row, col, slice); + } + + subiter_type deref_subiter() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + private: + const arma::Cube *p; + size_t row, col, slice; + }; + + class ColRange { + public: + ColRange() : p(NULL), row(0), col(0) { } + explicit ColRange(const arma::Cube *_p, size_t _row) : + p(_p), row(_row), col(0) { } + + typedef T value_type; + typedef SliceRange subiter_type; + static const bool is_container = true; + + bool is_end() const { return col == p->n_cols; } + + void inc() { ++col; } + + value_type deref() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo cube col"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + subiter_type deref_subiter() const { + return subiter_type(p, row, col); + } + + private: + const arma::Cube *p; + size_t row, col; + }; + + class RowRange { + public: + RowRange() : p(NULL), row(0) { } + explicit RowRange(const arma::Cube *_p) : p(_p), row(0) { } + + typedef T value_type; + typedef ColRange subiter_type; + static const bool is_container = true; + + bool is_end() const { return row == p->n_rows; } + + void inc() { ++row; } + + value_type deref() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo cube row"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + subiter_type deref_subiter() const { + return subiter_type(p, row); + } + + private: + const arma::Cube *p; + size_t row; + }; + +public: + static const bool allow_auto_unwrap = false; + static const size_t depth = ArrayTraits::depth + 3; + + typedef RowRange range_type; + + static range_type get_range(const arma::Cube &arg) { + //std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl; + return range_type(&arg); + } +}; + +// }}}3 + +// {{{3 Mat and Field + +template +class ArrayTraits_ArmaMatOrField : public ArrayTraitsDefaults { + class ColRange { + public: + ColRange() : p(NULL), row(0), col(0) { } + explicit ColRange(const RF *_p, size_t _row) : + p(_p), row(_row), col(0) { } + + typedef T value_type; + typedef Error_WasNotContainer subiter_type; + static const bool is_container = false; + + bool is_end() const { return col == p->n_cols; } + + void inc() { ++col; } + + value_type deref() const { + return (*p)(row, col); + } + + subiter_type deref_subiter() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "argument was not a container"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + private: + const RF *p; + size_t row, col; + }; + + class RowRange { + public: + RowRange() : p(NULL), row(0) { } + explicit RowRange(const RF *_p) : p(_p), row(0) { } + + typedef T value_type; + typedef ColRange subiter_type; + static const bool is_container = true; + + bool is_end() const { return row == p->n_rows; } + + void inc() { ++row; } + + value_type deref() const { + GNUPLOT_STATIC_ASSERT_MSG((sizeof(T) == 0), "can't call deref on an armadillo matrix row"); + throw std::logic_error("static assert should have been triggered by this point"); + } + + subiter_type deref_subiter() const { + return subiter_type(p, row); + } + + private: + const RF *p; + size_t row; + }; + +public: + static const bool allow_auto_unwrap = false; + static const size_t depth = ArrayTraits::depth + 2; + + typedef RowRange range_type; + + static range_type get_range(const RF &arg) { + //std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl; + return range_type(&arg); + } +}; + +template +class ArrayTraits > : public ArrayTraits_ArmaMatOrField, T> { }; + +template +class ArrayTraits > : public ArrayTraits_ArmaMatOrField, T> { }; + +// }}}3 + +// {{{3 Row + +template +class ArrayTraits > : public ArrayTraitsDefaults { +public: + static const bool allow_auto_unwrap = false; + + typedef IteratorRange::const_iterator, T> range_type; + + static range_type get_range(const arma::Row &arg) { + //std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl; + return range_type(arg.begin(), arg.end()); + } +}; + +// }}}3 + +// {{{3 Col + +template +class ArrayTraits > : public ArrayTraitsDefaults { +public: + static const bool allow_auto_unwrap = false; + + typedef IteratorRange::const_iterator, T> range_type; + + static range_type get_range(const arma::Col &arg) { + //std::cout << arg.n_elem << "," << arg.n_rows << "," << arg.n_cols << std::endl; + return range_type(arg.begin(), arg.end()); + } +}; + +// }}}3 + +} // namespace gnuplotio +#endif // GNUPLOT_ARMADILLO_SUPPORT_LOADED +#endif // ARMA_INCLUDES + +// }}}2 + +// }}}1 diff --git a/gnuplot-iostream/legacy/.gitignore b/gnuplot-iostream/legacy/.gitignore new file mode 100644 index 0000000..afb7058 --- /dev/null +++ b/gnuplot-iostream/legacy/.gitignore @@ -0,0 +1,5 @@ +# compiled stuff +examples +examples-blitz +examples-interactive +*.o diff --git a/gnuplot-iostream/legacy/Makefile b/gnuplot-iostream/legacy/Makefile new file mode 100644 index 0000000..1371a5b --- /dev/null +++ b/gnuplot-iostream/legacy/Makefile @@ -0,0 +1,36 @@ +CXXFLAGS+=-Wall -Wextra -I.. -O0 -g +# Don't warn about the fact that we use the deprecated send() function. +CXXFLAGS+=-Wno-deprecated-declarations +LDFLAGS+=-lutil -lboost_iostreams -lboost_system -lboost_filesystem + +EVERYTHING=examples examples-blitz examples-interactive + +all: examples + @echo "Now type 'make blitz' if you have blitz installed, and 'make interactive' if you system has PTY support." + +blitz: examples-blitz + +interactive: examples-interactive + +everything: $(EVERYTHING) + +%.o: %.cc gnuplot-iostream.h + $(CXX) $(CXXFLAGS) -c $< -o $@ + +examples: examples.o + $(CXX) -o $@ $^ $(LDFLAGS) + +examples-blitz: examples-blitz.o + $(CXX) -o $@ $^ $(LDFLAGS) + +examples-interactive: examples-interactive.o + $(CXX) -o $@ $^ $(LDFLAGS) + +clean: + rm -f *.o + rm -f *.error.txt + rm -f examples examples-blitz examples-interactive + # Windows compilation + rm -f *.exe *.obj + # files created by demo scripts + rm -f my_graph_*.png external_binary.dat external_binary.gnu external_text.dat external_text.gnu inline_binary.gnu inline_text.gnu diff --git a/gnuplot-iostream/legacy/README b/gnuplot-iostream/legacy/README new file mode 100644 index 0000000..dc7d7c7 --- /dev/null +++ b/gnuplot-iostream/legacy/README @@ -0,0 +1,2 @@ +These are examples that use the old send() function rather than send1d() and send2d(). They +are here just so I can make sure they still compile. diff --git a/gnuplot-iostream/legacy/examples-blitz.cc b/gnuplot-iostream/legacy/examples-blitz.cc new file mode 100644 index 0000000..c2b5226 --- /dev/null +++ b/gnuplot-iostream/legacy/examples-blitz.cc @@ -0,0 +1,122 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include +// This must be included before gnuplot-iostream.h in order to support plotting blitz arrays. +#include + +#include "gnuplot-iostream.h" + +// Yes, I'm including a *.cc file. It contains main(). +#include "examples-framework.cc" + +void demo_blitz_basic() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + + blitz::Array arr(100, 100); + { + blitz::firstIndex i; + blitz::secondIndex j; + arr = (i-50) * (j-50); + } + gp << "set pm3d map; set palette" << std::endl; + gp << "splot '-'" << std::endl; + gp.send(arr); +} + +void demo_blitz_waves_binary() { + Gnuplot gp("gnuplot -persist"); + + // example from Blitz manual: + int N = 64, cycles = 3; + double midpoint = (N-1)/2.; + double omega = 2.0 * M_PI * cycles / double(N); + double tau = - 10.0 / N; + blitz::Array F(N, N); + blitz::firstIndex i; + blitz::secondIndex j; + F = cos(omega * sqrt(pow2(i-midpoint) + pow2(j-midpoint))) + * exp(tau * sqrt(pow2(i-midpoint) + pow2(j-midpoint))); + + gp << "splot '-' binary" << gp.binfmt(F) << "dx=10 dy=10 origin=(5,5,0) with pm3d notitle" << std::endl; + gp.sendBinary(F); +} + +void demo_blitz_sierpinski_binary() { + Gnuplot gp("gnuplot -persist"); + + int N = 256; + blitz::Array, 2> F(N, N); + for(int i=0; i F(N, N); + blitz::firstIndex i; + blitz::secondIndex j; + F = cos(omega * sqrt(pow2(i-midpoint) + pow2(j-midpoint))) + * exp(tau * sqrt(pow2(i-midpoint) + pow2(j-midpoint))); + + gp << "splot" << gp.binaryFile(F) << "dx=10 dy=10 origin=(5,5,0) with pm3d notitle" << std::endl; +} + +void demo_blitz_sierpinski_binary_file() { + Gnuplot gp("gnuplot -persist"); + + int N = 256; + blitz::Array, 2> F(N, N); + for(int i=0; i +#include +#include + +std::map demos; + +void register_demo(const std::string &label, void (*fn)(void)) { + demos[label] = fn; +} + +void register_demos(); + +int main(int argc, char **argv) { + register_demos(); + + if(argc < 2) { + printf("Usage: %s \n", argv[0]); + printf("Choose one of the following demos:\n"); + typedef std::pair demo_pair; + BOOST_FOREACH(const demo_pair &pair, demos) { + printf(" %s\n", pair.first.c_str()); + } + return 0; + } + + std::string arg(argv[1]); + if(!demos.count(arg)) { + printf("No such demo '%s'\n", arg.c_str()); + return 1; + } + + demos[arg](); +} diff --git a/gnuplot-iostream/legacy/examples-interactive.cc b/gnuplot-iostream/legacy/examples-interactive.cc new file mode 100644 index 0000000..d9743cf --- /dev/null +++ b/gnuplot-iostream/legacy/examples-interactive.cc @@ -0,0 +1,84 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include + +#define GNUPLOT_ENABLE_PTY +#include "gnuplot-iostream.h" + +// Yes, I'm including a *.cc file. It contains main(). +#include "examples-framework.cc" + +void demo_basic() { + Gnuplot gp; + + double mx=0, my=0; + int mb=1; + while(mb != 3 && mb >= 0) { + std::vector > xy_pts; + xy_pts.push_back(std::make_pair(mx, my)); + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts.push_back(std::make_pair( + mx+cos(theta), my+sin(theta))); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with points title 'circle'\n"; + gp.send(xy_pts); + + gp.getMouse(mx, my, mb, "Left click to move circle, right click to exit."); + printf("You pressed mouse button %d at x=%f y=%f\n", mb, mx, my); + if(mb < 0) printf("The gnuplot window was closed.\n"); + } +} + +void demo_vectors() { + Gnuplot gp; + + double mx=0, my=0; + int mb=1; + while(mb != 3 && mb >= 0) { + std::vector > vecs(4); + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + vecs[0].push_back(mx+cos(theta)); + vecs[1].push_back(my+sin(theta)); + vecs[2].push_back(-cos(theta)*0.1); + vecs[3].push_back(-sin(theta)*0.1); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with vectors title 'circle'\n"; + gp.send(vecs); + + gp.getMouse(mx, my, mb, "Left click to move circle, right click to exit."); + printf("You pressed mouse button %d at x=%f y=%f\n", mb, mx, my); + if(mb < 0) printf("The gnuplot window was closed.\n"); + } +} + +void register_demos() { + register_demo("basic", demo_basic); + register_demo("vectors", demo_vectors); +} diff --git a/gnuplot-iostream/legacy/examples.cc b/gnuplot-iostream/legacy/examples.cc new file mode 100644 index 0000000..b7d5491 --- /dev/null +++ b/gnuplot-iostream/legacy/examples.cc @@ -0,0 +1,325 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include +#include + +#include "gnuplot-iostream.h" + +// Yes, I'm including a *.cc file. It contains main(). +#include "examples-framework.cc" + +// http://stackoverflow.com/a/1658429 +#ifdef _WIN32 + #include + inline void mysleep(unsigned millis) { + ::Sleep(millis); + } +#else + #include + inline void mysleep(unsigned millis) { + ::usleep(millis * 1000); + } +#endif + +void demo_basic() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + // For debugging or manual editing of commands: + //Gnuplot gp(fopen("plot.gnu")); + // or + //Gnuplot gp("tee plot.gnu | gnuplot -persist"); + + // NOTE: we can use map here because the X values are intended to be + // sorted. If this was not the case, vector> could be + // used instead. + + std::map xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A[x] = y; + } + + std::map xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B[cos(theta)] = sin(theta); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with lines title 'cubic', '-' with points title 'circle'\n"; + gp.send(xy_pts_A).send(xy_pts_B); +} + +void demo_array() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + + double arr[] = { 1, 3, 2 }; + + gp << "plot '-' with lines\n"; + gp.send(arr); +} + +namespace xyz { +template +struct MyTriple { + MyTriple( + T _x, + T _y, + T _z + ) : x(_x), y(_y), z(_z) { } + + T x, y, z; +}; +} +using xyz::MyTriple; + +namespace gnuplotio { + template + struct BinfmtSender > { + static void send(std::ostream &stream) { + BinfmtSender::send(stream); + BinfmtSender::send(stream); + BinfmtSender::send(stream); + } + }; + + template + struct BinarySender > { + static void send(std::ostream &stream, const MyTriple &v) { + BinarySender::send(stream, v.x); + BinarySender::send(stream, v.y); + BinarySender::send(stream, v.z); + } + }; + + template + struct TextSender > { + static void send(std::ostream &stream, const MyTriple &v) { + TextSender::send(stream, v.x); + stream << " "; + TextSender::send(stream, v.y); + stream << " "; + TextSender::send(stream, v.z); + } + }; +} + +void demo_tuple() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + + std::vector > pts; + for(double alpha=0; alpha<1; alpha+=1.0/120.0) { + double theta = alpha*2.0*3.14159; + double x = (2+cos(3*theta))*cos(2*theta); + double y = (2+cos(3*theta))*sin(2*theta); + double z = sin(3*theta); + pts.push_back(MyTriple (x, y, z)); + } + + gp << "splot '-' binary" << gp.binfmt(pts, "record") << "with lines notitle\n"; + gp.sendBinary(pts); +} + +void demo_tmpfile() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + + // NOTE: we can use map here because the X values are intended to be + // sorted. If this was not the case, vector> could be + // used instead. + + std::map xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A[x] = y; + } + + std::map xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B[cos(theta)] = sin(theta); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + // Data will be sent via a temporary file. These are erased when you call + // gp.clearTmpfiles() or when gp goes out of scope. If you pass a filename + // (i.e. "gp.file(pts, 'mydata.dat')"), then the named file will be created + // and won't be deleted. + gp << "plot" << gp.file(xy_pts_A) << "with lines title 'cubic'," + << gp.file(xy_pts_B) << "with points title 'circle'\n"; +} + +void demo_png() { + Gnuplot gp; + + gp << "set terminal png\n"; + + std::vector y_pts; + for(int i=0; i<1000; i++) { + double y = (i/500.0-1) * (i/500.0-1); + y_pts.push_back(y); + } + + std::cout << "Creating my_graph_1.png" << std::endl; + gp << "set output 'my_graph_1.png'\n"; + gp << "plot '-' with lines, sin(x/200) with lines\n"; + gp.send(y_pts); + + // NOTE: we can use map here because the X values are intended to be + // sorted. If this was not the case, vector> could be + // used instead. + + std::map xy_pts_A; + for(double x=-2; x<2; x+=0.01) { + double y = x*x*x; + xy_pts_A[x] = y; + } + + std::map xy_pts_B; + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + xy_pts_B[cos(theta)] = sin(theta); + } + + std::cout << "Creating my_graph_2.png" << std::endl; + gp << "set output 'my_graph_2.png'\n"; + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with lines title 'cubic', '-' with points title 'circle'\n"; + gp.send(xy_pts_A).send(xy_pts_B); +} + +void demo_vectors() { + // -persist option makes the window not disappear when your program exits + Gnuplot gp("gnuplot -persist"); + + std::vector > vecs(4); + for(double alpha=0; alpha<1; alpha+=1.0/24.0) { + double theta = alpha*2.0*3.14159; + vecs[0].push_back( cos(theta)); + vecs[1].push_back( sin(theta)); + vecs[2].push_back(-cos(theta)*0.1); + vecs[3].push_back(-sin(theta)*0.1); + } + + gp << "set xrange [-2:2]\nset yrange [-2:2]\n"; + gp << "plot '-' with vectors title 'circle'\n"; + gp.send(vecs); +} + +std::vector > get_trefoil() { + std::vector > vecs(3); + for(double alpha=0; alpha<1; alpha+=1.0/120.0) { + double theta = alpha*2.0*3.14159; + vecs[0].push_back((2+cos(3*theta))*cos(2*theta)); + vecs[1].push_back((2+cos(3*theta))*sin(2*theta)); + vecs[2].push_back(sin(3*theta)); + } + return vecs; +} + +void demo_inline_text() { + std::cout << "Creating inline_text.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(fopen("inline_text.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + gp << "splot '-' with lines notitle\n"; + gp.send(vecs); +} + +void demo_inline_binary() { + std::cout << "Creating inline_binary.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(fopen("inline_binary.gnu", "wb")); + + std::vector > vecs = get_trefoil(); + + gp << "splot '-' binary" << gp.binfmt(vecs, "record") << "with lines notitle\n"; + gp.sendBinary(vecs); +} + +void demo_external_text() { + std::cout << "Creating external_text.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(fopen("external_text.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + std::cout << "Creating external_text.dat" << std::endl; + gp << "splot" << gp.file(vecs, "external_text.dat") << "with lines notitle\n"; +} + +void demo_external_binary() { + std::cout << "Creating external_binary.gnu" << std::endl; + // This file handle will be closed automatically when gp goes out of scope. + Gnuplot gp(fopen("external_binary.gnu", "w")); + + std::vector > vecs = get_trefoil(); + + std::cout << "Creating external_binary.dat" << std::endl; + gp << "splot" << gp.binaryFile(vecs, "external_binary.dat", "record") << "with lines notitle\n"; +} + +void demo_animation() { + Gnuplot gp; + + std::cout << "Press Ctrl-C to quit (closing gnuplot window doesn't quit)." << std::endl; + + gp << "set yrange [-1:1]\n"; + + const int N = 1000; + std::vector pts(N); + + double theta = 0; + while(1) { + for(int i=0; i + +#include "gnuplot-iostream.h" + +int main() { + Gnuplot gp; + + std::vector > pts; + // These should be okay. + gp << gp.sendBinary1d(pts); + gp << gp.sendBinary1d_colmajor(pts); + gp << gp.sendBinary2d(pts); + // This should throw a compilation error. + gp << gp.sendBinary2d_colmajor(pts); + + return 0; +} diff --git a/gnuplot-iostream/test-assert-depth.cc b/gnuplot-iostream/test-assert-depth.cc new file mode 100644 index 0000000..5fa8cfc --- /dev/null +++ b/gnuplot-iostream/test-assert-depth.cc @@ -0,0 +1,37 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include + +#include "gnuplot-iostream.h" + +int main() { + Gnuplot gp; + + std::vector pts; + // This should be okay. + gp << gp.sendBinary1d(pts); + // This should throw a compilation error. + gp << gp.sendBinary2d(pts); + + return 0; +} diff --git a/gnuplot-iostream/test-empty.cc b/gnuplot-iostream/test-empty.cc new file mode 100644 index 0000000..7625622 --- /dev/null +++ b/gnuplot-iostream/test-empty.cc @@ -0,0 +1,76 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// FIXME - Currently this test is not being run and validated by the Makefile. +// I'm waiting to see the outcome of the following bug report: +// https://sourceforge.net/p/gnuplot/bugs/1500/ + +#include +#include +#if GNUPLOT_ENABLE_CXX11 +#include +#include +#endif + +#include + +#if USE_ARMA +#include +#endif + +#if USE_BLITZ +#include +#endif + +#include "gnuplot-iostream.h" + +using namespace gnuplotio; + +const std::string basedir = "unittest-output"; + +template +void go(Gnuplot &gp, const T &data) { + gp << "plot '-' binary" << gp.binFmt1d(data, "record") << std::endl; + gp.sendBinary1d(data); + gp << "plot '-' binary" << gp.binFmt2d(data, "record") << std::endl; + gp.sendBinary2d(data); + gp << "plot '-'\n" << std::endl; + gp.send1d(data); + gp << "plot '-'\n" << std::endl; + gp.send2d(data); +} + +int main() { + Gnuplot gp(std::fopen((basedir + "/test-empty.gnu").c_str(), "w")); + + std::vector > > > data; + go(gp, data); + + data.resize(1); + go(gp, data); + + data[0].resize(1); + go(gp, data); + + data[0][0].push_back(std::make_pair(0.0, 0)); + go(gp, data); +} diff --git a/gnuplot-iostream/test-noncopyable.cc b/gnuplot-iostream/test-noncopyable.cc new file mode 100644 index 0000000..ff85b06 --- /dev/null +++ b/gnuplot-iostream/test-noncopyable.cc @@ -0,0 +1,60 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include + +#include +#include + +#include "gnuplot-iostream.h" + +#define USE_CXX (__cplusplus >= 201103) + +template +class NonCopyable : boost::noncopyable, public std::vector { +public: + NonCopyable() { } +}; + +int main() { + Gnuplot gp; + NonCopyable nc_x, nc_y; + for(int i=0; i<100; i++) { + nc_x.push_back(-i); + nc_y.push_back(i*i); + } + gp << "plot '-', '-'\n"; + + // These don't work because they make copies. + //gp.send1d(std::make_pair(nc_x, nc_y)); + //gp.send1d(boost::make_tuple(nc_x, nc_y)); + // These work because they make references: +#if USE_CXX + std::cout << "using std::tie" << std::endl; + gp.send1d(std::tie(nc_y)); + gp.send1d(std::forward_as_tuple(nc_x, std::move(nc_y))); +#else + std::cout << "using boost::tie" << std::endl; + gp.send1d(nc_y); + gp.send1d(boost::tie(nc_x, nc_y)); +#endif +} diff --git a/gnuplot-iostream/test-outputs.cc b/gnuplot-iostream/test-outputs.cc new file mode 100644 index 0000000..1561c81 --- /dev/null +++ b/gnuplot-iostream/test-outputs.cc @@ -0,0 +1,275 @@ +/* +Copyright (c) 2013 Daniel Stahlke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Include this several times to test delayed loading of armadillo/blitz support. +#include "gnuplot-iostream.h" + +#include +#include +#if GNUPLOT_ENABLE_CXX11 +#include +#include +#endif + +#include + +#if USE_ARMA +#include +#endif + +#include "gnuplot-iostream.h" + +#if USE_BLITZ +#include +#endif + +#include "gnuplot-iostream.h" +#include "gnuplot-iostream.h" + +using namespace gnuplotio; + +Gnuplot gp; +const std::string basedir = "unittest-output"; + +template +void test_given_mode( + std::ostream &log_fh, std::string header, const T &arg, + ArrayMode, boost::mpl::true_ +) { + std::string modename = ArrayMode::class_name(); + std::string fn_prefix = basedir+"/"+header+"-"+modename; + log_fh << "* " << modename << " -> " + << gp.binaryFile(arg, fn_prefix+".bin", "record", ArrayMode()) << std::endl; + gp.file(arg, fn_prefix+".txt", ArrayMode()); +} + +template +void test_given_mode( + std::ostream &log_fh, std::string header, const T &arg, + ArrayMode, boost::mpl::false_ +) { + std::string modename = ArrayMode::class_name(); + std::string fn_prefix = basedir+"/"+header+"-"+modename; + log_fh << "* " << modename << " (skipped binary) " << std::endl; + gp.file(arg, fn_prefix+".txt", ArrayMode()); +} + +template +typename boost::enable_if_c<(ArrayTraits::depth == 1)>::type +runtest_inner(std::ostream &log_fh, std::string header, const T &arg) { + test_given_mode(log_fh, header, arg, Mode1D(), DoBinary()); +} + +template +typename boost::enable_if_c<(ArrayTraits::depth == 2)>::type +runtest_inner(std::ostream &log_fh, std::string header, const T &arg) { + test_given_mode(log_fh, header, arg, Mode2D(), DoBinary()); + test_given_mode(log_fh, header, arg, Mode1DUnwrap(), DoBinary()); +} + +template +typename boost::enable_if_c<(ArrayTraits::depth >= 3)>::type +runtest_inner(std::ostream &log_fh, std::string header, const T &arg) { + test_given_mode(log_fh, header, arg, Mode2D(), DoBinary()); + test_given_mode(log_fh, header, arg, Mode2DUnwrap(), DoBinary()); +} + +template +void runtest_maybe_dobin(std::string header, const T &arg) { + std::ofstream log_fh((basedir+"/"+header+"-log.txt").c_str()); + log_fh << "--- " << header << " -------------------------------------" << std::endl; + log_fh << "depth=" << ArrayTraits::depth << std::endl; + log_fh << "ModeAutoDecoder=" << ModeAutoDecoder::mode::class_name() << std::endl; + runtest_inner(log_fh, header, arg); +} + +template +void runtest(std::string header, const T &arg) { + runtest_maybe_dobin(header, arg); +} + +template +void runtest_nobin(std::string header, const T &arg) { + runtest_maybe_dobin(header, arg); +} + +template +void basic_datatype_test_integral(std::string name) { + std::vector v; + for(int i=0; i<4; i++) { + v.push_back(i); + } + runtest_maybe_dobin, DoBinary>(name, v); +} + +template +void basic_datatype_test_float(std::string name) { + std::vector v; + for(int i=0; i<4; i++) { + v.push_back(i + T(0.1234)); + } + v.push_back(std::numeric_limits::quiet_NaN()); + runtest_maybe_dobin, DoBinary>(name, v); +} + +int main() { + const int NX=3, NY=4, NZ=2; + std::vector vd; + std::vector vi; + std::vector vf; + std::vector > vvd(NX); + std::vector > vvi(NX); + std::vector > > vvvi(NX); + std::vector > > > vvvp(NX); + int ai[NX]; + boost::array bi; + std::vector > v_bt; +#if GNUPLOT_ENABLE_CXX11 + std::array si; + std::vector< std::tuple > v_st; +#endif + + for(int x=0; x tup; + tup.push_back(300+x*10+y); + tup.push_back(400+x*10+y); + vvvi[x].push_back(tup); + + std::vector > stuff; + for(int z=0; z("vi8"); + basic_datatype_test_integral("vu8"); + basic_datatype_test_integral("vi16"); + basic_datatype_test_integral("vu16"); + basic_datatype_test_integral("vi32"); + basic_datatype_test_integral("vu32"); + + // these should all print as integers + basic_datatype_test_integral("vpc"); + basic_datatype_test_integral("vsc"); + basic_datatype_test_integral("vuc"); + + basic_datatype_test_float("vf"); + basic_datatype_test_float("vd"); + basic_datatype_test_float("vld"); + + runtest("vd,vi,bi", std::make_pair(vd, std::make_pair(vi, bi))); + runtest("vvd", vvd); + runtest("vvd,vvi", std::make_pair(vvd, vvi)); + runtest("ai", ai); + runtest("bi", bi); +#if GNUPLOT_ENABLE_CXX11 + runtest("si", si); + runtest("tie{si,bi}", boost::tie(si, bi)); + runtest("pair{&si,&bi}", std::pair&, boost::array&>(si, bi)); +#endif + // Doesn't work because array gets cast to pointer + //runtest("pair{ai,bi}", std::make_pair(ai, bi)); + // However, these work: + runtest("boost_tie{ai,bi}", boost::tie(ai, bi)); +#if GNUPLOT_ENABLE_CXX11 + runtest("std_tie{ai,bi}", std::tie(ai, bi)); + runtest("std_fwd{ai,bi}", std::forward_as_tuple(ai, bi)); +#endif + + runtest("pair{ai,bi}", std::pair >(ai, bi)); + runtest("vvd,vvi,vvvi", std::make_pair(vvd, std::make_pair(vvi, vvvi))); + runtest("vvvp", vvvp); + +#if USE_ARMA + arma::vec armacol(NX); + arma::mat armamat(NX, NY); + + for(int x=0; x blitz1d(NX); + blitz::Array blitz2d(NX, NY); + { + blitz::firstIndex i; + blitz::secondIndex j; + blitz1d = i + 0.777; + blitz2d = 100 + i*10 + j; + } + blitz::Array, 2> blitz2d_tup(NX, NY); + for(int x=0; x 'unittest-output/ai-Mode1D.bin' binary format='%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/armacol-Mode1D.bin b/gnuplot-iostream/unittest-output-good/armacol-Mode1D.bin new file mode 100644 index 0000000..8754dba Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/armacol-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/armacol-Mode1D.txt b/gnuplot-iostream/unittest-output-good/armacol-Mode1D.txt new file mode 100644 index 0000000..9f6d75e --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/armacol-Mode1D.txt @@ -0,0 +1,3 @@ +0.123 +1.123 +2.123 diff --git a/gnuplot-iostream/unittest-output-good/armacol-log.txt b/gnuplot-iostream/unittest-output-good/armacol-log.txt new file mode 100644 index 0000000..2181af5 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/armacol-log.txt @@ -0,0 +1,4 @@ +--- armacol ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/armacol-Mode1D.bin' binary format='%double' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.bin new file mode 100644 index 0000000..96de8d6 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.txt new file mode 100644 index 0000000..1b3c195 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/armamat-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +0.123 10.123 20.123 +1.123 11.123 21.123 +2.123 12.123 22.123 +3.123 13.123 23.123 diff --git a/gnuplot-iostream/unittest-output-good/armamat-Mode2D.bin b/gnuplot-iostream/unittest-output-good/armamat-Mode2D.bin new file mode 100644 index 0000000..6d9e7dc Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/armamat-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/armamat-Mode2D.txt b/gnuplot-iostream/unittest-output-good/armamat-Mode2D.txt new file mode 100644 index 0000000..804f0ed --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/armamat-Mode2D.txt @@ -0,0 +1,14 @@ +0.123 +1.123 +2.123 +3.123 + +10.123 +11.123 +12.123 +13.123 + +20.123 +21.123 +22.123 +23.123 diff --git a/gnuplot-iostream/unittest-output-good/armamat-log.txt b/gnuplot-iostream/unittest-output-good/armamat-log.txt new file mode 100644 index 0000000..27190d6 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/armamat-log.txt @@ -0,0 +1,5 @@ +--- armamat ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/armamat-Mode2D.bin' binary format='%double' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/armamat-Mode1DUnwrap.bin' binary format='%double%double%double' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/bi-Mode1D.bin b/gnuplot-iostream/unittest-output-good/bi-Mode1D.bin new file mode 100644 index 0000000..46ae982 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/bi-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/bi-Mode1D.txt b/gnuplot-iostream/unittest-output-good/bi-Mode1D.txt new file mode 100644 index 0000000..d6e547a --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/bi-Mode1D.txt @@ -0,0 +1,3 @@ +70 +71 +72 diff --git a/gnuplot-iostream/unittest-output-good/bi-log.txt b/gnuplot-iostream/unittest-output-good/bi-log.txt new file mode 100644 index 0000000..9189316 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/bi-log.txt @@ -0,0 +1,4 @@ +--- bi ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/bi-Mode1D.bin' binary format='%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.bin b/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.bin new file mode 100644 index 0000000..1bfe21c Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.txt b/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.txt new file mode 100644 index 0000000..2110d4f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz1d,vd-Mode1D.txt @@ -0,0 +1,3 @@ +0.777 7.5 +1.777 8.5 +2.777 9.5 diff --git a/gnuplot-iostream/unittest-output-good/blitz1d,vd-log.txt b/gnuplot-iostream/unittest-output-good/blitz1d,vd-log.txt new file mode 100644 index 0000000..edf6acb --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz1d,vd-log.txt @@ -0,0 +1,4 @@ +--- blitz1d,vd ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/blitz1d,vd-Mode1D.bin' binary format='%double%double' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/blitz1d-Mode1D.bin b/gnuplot-iostream/unittest-output-good/blitz1d-Mode1D.bin new file mode 100644 index 0000000..d7e1d55 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz1d-Mode1D.bin @@ -0,0 +1 @@ +w/? 'unittest-output/blitz1d-Mode1D.bin' binary format='%double' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.bin new file mode 100644 index 0000000..75cb550 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.txt new file mode 100644 index 0000000..9a246fe --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 110 120 +101 111 121 +102 112 122 +103 113 123 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.bin b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.bin new file mode 100644 index 0000000..749bfa5 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.txt b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.txt new file mode 100644 index 0000000..71ba638 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d cols-Mode2D.txt @@ -0,0 +1,14 @@ +100 +101 +102 +103 + +110 +111 +112 +113 + +120 +121 +122 +123 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d cols-log.txt b/gnuplot-iostream/unittest-output-good/blitz2d cols-log.txt new file mode 100644 index 0000000..8f19d4b --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d cols-log.txt @@ -0,0 +1,5 @@ +--- blitz2d cols ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/blitz2d cols-Mode2D.bin' binary format='%double' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/blitz2d cols-Mode1DUnwrap.bin' binary format='%double%double%double' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.bin b/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.bin new file mode 100644 index 0000000..0188399 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.txt b/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.txt new file mode 100644 index 0000000..33bb3c5 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d,vd-Mode1D.txt @@ -0,0 +1,3 @@ +100 101 102 103 7.5 +110 111 112 113 8.5 +120 121 122 123 9.5 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vd-log.txt b/gnuplot-iostream/unittest-output-good/blitz2d,vd-log.txt new file mode 100644 index 0000000..781d8a1 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d,vd-log.txt @@ -0,0 +1,4 @@ +--- blitz2d,vd ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/blitz2d,vd-Mode1D.bin' binary format='%double%double%double%double%double' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.bin new file mode 100644 index 0000000..ad9b80e Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.txt new file mode 100644 index 0000000..d371fa8 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 200 110 210 120 220 +101 201 111 211 121 221 +102 202 112 212 122 222 +103 203 113 213 123 223 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.bin b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.bin new file mode 100644 index 0000000..8dbdd40 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.txt b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.txt new file mode 100644 index 0000000..39a6a7f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-Mode2D.txt @@ -0,0 +1,14 @@ +100 200 +101 201 +102 202 +103 203 + +110 210 +111 211 +112 212 +113 213 + +120 220 +121 221 +122 222 +123 223 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d,vvi-log.txt b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-log.txt new file mode 100644 index 0000000..e9507a3 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d,vvi-log.txt @@ -0,0 +1,5 @@ +--- blitz2d,vvi ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/blitz2d,vvi-Mode2D.bin' binary format='%double%int32' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/blitz2d,vvi-Mode1DUnwrap.bin' binary format='%double%int32%double%int32%double%int32' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.bin new file mode 100644 index 0000000..75cb550 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.txt new file mode 100644 index 0000000..9a246fe --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 110 120 +101 111 121 +102 112 122 +103 113 123 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.bin b/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.bin new file mode 100644 index 0000000..749bfa5 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.txt b/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.txt new file mode 100644 index 0000000..71ba638 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d-Mode2D.txt @@ -0,0 +1,14 @@ +100 +101 +102 +103 + +110 +111 +112 +113 + +120 +121 +122 +123 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d-log.txt b/gnuplot-iostream/unittest-output-good/blitz2d-log.txt new file mode 100644 index 0000000..104150f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d-log.txt @@ -0,0 +1,5 @@ +--- blitz2d ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/blitz2d-Mode2D.bin' binary format='%double' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/blitz2d-Mode1DUnwrap.bin' binary format='%double%double%double' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.bin new file mode 100644 index 0000000..88174c5 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.txt new file mode 100644 index 0000000..d371fa8 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 200 110 210 120 220 +101 201 111 211 121 221 +102 202 112 212 122 222 +103 203 113 213 123 223 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.bin b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.bin new file mode 100644 index 0000000..ebad42c Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.txt b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.txt new file mode 100644 index 0000000..39a6a7f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d_tup-Mode2D.txt @@ -0,0 +1,14 @@ +100 200 +101 201 +102 202 +103 203 + +110 210 +111 211 +112 212 +113 213 + +120 220 +121 221 +122 222 +123 223 diff --git a/gnuplot-iostream/unittest-output-good/blitz2d_tup-log.txt b/gnuplot-iostream/unittest-output-good/blitz2d_tup-log.txt new file mode 100644 index 0000000..bd9ad92 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/blitz2d_tup-log.txt @@ -0,0 +1,5 @@ +--- blitz2d_tup ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/blitz2d_tup-Mode2D.bin' binary format='%double%double' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/blitz2d_tup-Mode1DUnwrap.bin' binary format='%double%double%double%double%double%double' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.bin new file mode 100644 index 0000000..16d4319 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.txt new file mode 100644 index 0000000..b3dd2fd --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-Mode1D.txt @@ -0,0 +1,3 @@ +7 70 +8 71 +9 72 diff --git a/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-log.txt b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-log.txt new file mode 100644 index 0000000..64e3816 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/boost_tie{ai,bi}-log.txt @@ -0,0 +1,4 @@ +--- boost_tie{ai,bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/boost_tie{ai,bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.bin new file mode 100644 index 0000000..3d78b4d Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.txt new file mode 100644 index 0000000..529fdf2 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.txt @@ -0,0 +1,3 @@ +7.5 7 7.2 7 7.5 +8.5 8 8.2 8 8.5 +9.5 9 9.2 9 9.5 diff --git a/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-log.txt b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-log.txt new file mode 100644 index 0000000..3ae6715 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/btup{vd,stup{vi,btup{vf},vi},vd}-log.txt @@ -0,0 +1,4 @@ +--- btup{vd,stup{vi,btup{vf},vi},vd} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/btup{vd,stup{vi,btup{vf},vi},vd}-Mode1D.bin' binary format='%double%int32%float%int32%double' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.bin new file mode 100644 index 0000000..79d4b26 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.txt new file mode 100644 index 0000000..7dc3020 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-Mode1D.txt @@ -0,0 +1,3 @@ +90 70 +91 71 +92 72 diff --git a/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-log.txt b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-log.txt new file mode 100644 index 0000000..3c9c12c --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{&si,&bi}-log.txt @@ -0,0 +1,4 @@ +--- pair{&si,&bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/pair{&si,&bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.bin new file mode 100644 index 0000000..16d4319 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.txt new file mode 100644 index 0000000..b3dd2fd --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-Mode1D.txt @@ -0,0 +1,3 @@ +7 70 +8 71 +9 72 diff --git a/gnuplot-iostream/unittest-output-good/pair{ai,bi}-log.txt b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-log.txt new file mode 100644 index 0000000..76b2023 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{ai,bi}-log.txt @@ -0,0 +1,4 @@ +--- pair{ai,bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/pair{ai,bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.bin new file mode 100644 index 0000000..f6bf3aa Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.txt new file mode 100644 index 0000000..f69af1d --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.txt @@ -0,0 +1,3 @@ +7.2 7.5 7 7 7.2 +8.2 8.5 8 8 8.2 +9.2 9.5 9 9 9.2 diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-log.txt b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-log.txt new file mode 100644 index 0000000..d0790b1 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{vf,btup{vd,pair{vi,vi},vf}}-log.txt @@ -0,0 +1,4 @@ +--- pair{vf,btup{vd,pair{vi,vi},vf}} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/pair{vf,btup{vd,pair{vi,vi},vf}}-Mode1D.bin' binary format='%float%double%int32%int32%float' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.bin new file mode 100644 index 0000000..f6bf3aa Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.txt new file mode 100644 index 0000000..f69af1d --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.txt @@ -0,0 +1,3 @@ +7.2 7.5 7 7 7.2 +8.2 8.5 8 8 8.2 +9.2 9.5 9 9 9.2 diff --git a/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-log.txt b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-log.txt new file mode 100644 index 0000000..9016091 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/pair{vf,stup{vd,pair{vi,vi},vf}}-log.txt @@ -0,0 +1,4 @@ +--- pair{vf,stup{vd,pair{vi,vi},vf}} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/pair{vf,stup{vd,pair{vi,vi},vf}}-Mode1D.bin' binary format='%float%double%int32%int32%float' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/si-Mode1D.bin b/gnuplot-iostream/unittest-output-good/si-Mode1D.bin new file mode 100644 index 0000000..130627c Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/si-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/si-Mode1D.txt b/gnuplot-iostream/unittest-output-good/si-Mode1D.txt new file mode 100644 index 0000000..8da93af --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/si-Mode1D.txt @@ -0,0 +1,3 @@ +90 +91 +92 diff --git a/gnuplot-iostream/unittest-output-good/si-log.txt b/gnuplot-iostream/unittest-output-good/si-log.txt new file mode 100644 index 0000000..a7acdf4 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/si-log.txt @@ -0,0 +1,4 @@ +--- si ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/si-Mode1D.bin' binary format='%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.bin new file mode 100644 index 0000000..16d4319 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.txt new file mode 100644 index 0000000..b3dd2fd --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-Mode1D.txt @@ -0,0 +1,3 @@ +7 70 +8 71 +9 72 diff --git a/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-log.txt b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-log.txt new file mode 100644 index 0000000..4d07fc1 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/std_fwd{ai,bi}-log.txt @@ -0,0 +1,4 @@ +--- std_fwd{ai,bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/std_fwd{ai,bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.bin new file mode 100644 index 0000000..16d4319 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.txt new file mode 100644 index 0000000..b3dd2fd --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-Mode1D.txt @@ -0,0 +1,3 @@ +7 70 +8 71 +9 72 diff --git a/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-log.txt b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-log.txt new file mode 100644 index 0000000..011d459 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/std_tie{ai,bi}-log.txt @@ -0,0 +1,4 @@ +--- std_tie{ai,bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/std_tie{ai,bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.bin b/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.bin new file mode 100644 index 0000000..79d4b26 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.txt b/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.txt new file mode 100644 index 0000000..7dc3020 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/tie{si,bi}-Mode1D.txt @@ -0,0 +1,3 @@ +90 70 +91 71 +92 72 diff --git a/gnuplot-iostream/unittest-output-good/tie{si,bi}-log.txt b/gnuplot-iostream/unittest-output-good/tie{si,bi}-log.txt new file mode 100644 index 0000000..886884c --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/tie{si,bi}-log.txt @@ -0,0 +1,4 @@ +--- tie{si,bi} ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/tie{si,bi}-Mode1D.bin' binary format='%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.bin b/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.bin new file mode 100644 index 0000000..500f460 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.txt b/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.txt new file mode 100644 index 0000000..4f0523a --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/v_bt-Mode1D.txt @@ -0,0 +1,3 @@ +0.123 100 200 +1.123 101 201 +2.123 102 202 diff --git a/gnuplot-iostream/unittest-output-good/v_bt-log.txt b/gnuplot-iostream/unittest-output-good/v_bt-log.txt new file mode 100644 index 0000000..f9950ae --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/v_bt-log.txt @@ -0,0 +1,4 @@ +--- v_bt ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/v_bt-Mode1D.bin' binary format='%double %int32 %int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/v_st-Mode1D.bin b/gnuplot-iostream/unittest-output-good/v_st-Mode1D.bin new file mode 100644 index 0000000..500f460 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/v_st-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/v_st-Mode1D.txt b/gnuplot-iostream/unittest-output-good/v_st-Mode1D.txt new file mode 100644 index 0000000..4f0523a --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/v_st-Mode1D.txt @@ -0,0 +1,3 @@ +0.123 100 200 +1.123 101 201 +2.123 102 202 diff --git a/gnuplot-iostream/unittest-output-good/v_st-log.txt b/gnuplot-iostream/unittest-output-good/v_st-log.txt new file mode 100644 index 0000000..dcc1f2f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/v_st-log.txt @@ -0,0 +1,4 @@ +--- v_st ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/v_st-Mode1D.bin' binary format='%double %int32 %int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.bin new file mode 100644 index 0000000..a415784 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.txt new file mode 100644 index 0000000..d8fb861 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vd,vi,bi-Mode1D.txt @@ -0,0 +1,3 @@ +7.5 7 70 +8.5 8 71 +9.5 9 72 diff --git a/gnuplot-iostream/unittest-output-good/vd,vi,bi-log.txt b/gnuplot-iostream/unittest-output-good/vd,vi,bi-log.txt new file mode 100644 index 0000000..e4b8adc --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vd,vi,bi-log.txt @@ -0,0 +1,4 @@ +--- vd,vi,bi ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vd,vi,bi-Mode1D.bin' binary format='%double%int32%int32' record=(3) diff --git a/gnuplot-iostream/unittest-output-good/vd-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vd-Mode1D.bin new file mode 100644 index 0000000..1b4d55e Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vd-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vd-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vd-Mode1D.txt new file mode 100644 index 0000000..b7e003f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vd-Mode1D.txt @@ -0,0 +1,5 @@ +0.1234 +1.1234 +2.1234 +3.1234 +nan diff --git a/gnuplot-iostream/unittest-output-good/vd-log.txt b/gnuplot-iostream/unittest-output-good/vd-log.txt new file mode 100644 index 0000000..95b6d50 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vd-log.txt @@ -0,0 +1,4 @@ +--- vd ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vd-Mode1D.bin' binary format='%double' record=(5) diff --git a/gnuplot-iostream/unittest-output-good/vf-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vf-Mode1D.bin new file mode 100644 index 0000000..5d156f0 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vf-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vf-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vf-Mode1D.txt new file mode 100644 index 0000000..b7e003f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vf-Mode1D.txt @@ -0,0 +1,5 @@ +0.1234 +1.1234 +2.1234 +3.1234 +nan diff --git a/gnuplot-iostream/unittest-output-good/vf-log.txt b/gnuplot-iostream/unittest-output-good/vf-log.txt new file mode 100644 index 0000000..c96b01e --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vf-log.txt @@ -0,0 +1,4 @@ +--- vf ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vf-Mode1D.bin' binary format='%float' record=(5) diff --git a/gnuplot-iostream/unittest-output-good/vi16-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vi16-Mode1D.bin new file mode 100644 index 0000000..e909c4e Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vi16-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vi16-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vi16-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi16-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vi16-log.txt b/gnuplot-iostream/unittest-output-good/vi16-log.txt new file mode 100644 index 0000000..7d9b52d --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi16-log.txt @@ -0,0 +1,4 @@ +--- vi16 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vi16-Mode1D.bin' binary format='%int16' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vi32-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vi32-Mode1D.bin new file mode 100644 index 0000000..a4e969a Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vi32-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vi32-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vi32-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi32-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vi32-log.txt b/gnuplot-iostream/unittest-output-good/vi32-log.txt new file mode 100644 index 0000000..2427449 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi32-log.txt @@ -0,0 +1,4 @@ +--- vi32 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vi32-Mode1D.bin' binary format='%int32' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vi8-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vi8-Mode1D.bin new file mode 100644 index 0000000..eaf36c1 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vi8-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vi8-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vi8-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi8-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vi8-log.txt b/gnuplot-iostream/unittest-output-good/vi8-log.txt new file mode 100644 index 0000000..1f8ec13 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vi8-log.txt @@ -0,0 +1,4 @@ +--- vi8 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vi8-Mode1D.bin' binary format='%int8' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vld-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vld-Mode1D.txt new file mode 100644 index 0000000..b7e003f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vld-Mode1D.txt @@ -0,0 +1,5 @@ +0.1234 +1.1234 +2.1234 +3.1234 +nan diff --git a/gnuplot-iostream/unittest-output-good/vld-log.txt b/gnuplot-iostream/unittest-output-good/vld-log.txt new file mode 100644 index 0000000..58243b0 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vld-log.txt @@ -0,0 +1,4 @@ +--- vld ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D (skipped binary) diff --git a/gnuplot-iostream/unittest-output-good/vpc-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vpc-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vpc-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vpc-log.txt b/gnuplot-iostream/unittest-output-good/vpc-log.txt new file mode 100644 index 0000000..a9388d2 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vpc-log.txt @@ -0,0 +1,4 @@ +--- vpc ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D (skipped binary) diff --git a/gnuplot-iostream/unittest-output-good/vsc-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vsc-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vsc-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vsc-log.txt b/gnuplot-iostream/unittest-output-good/vsc-log.txt new file mode 100644 index 0000000..0ebdd4a --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vsc-log.txt @@ -0,0 +1,4 @@ +--- vsc ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D (skipped binary) diff --git a/gnuplot-iostream/unittest-output-good/vu16-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vu16-Mode1D.bin new file mode 100644 index 0000000..e909c4e Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vu16-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vu16-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vu16-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu16-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vu16-log.txt b/gnuplot-iostream/unittest-output-good/vu16-log.txt new file mode 100644 index 0000000..3124b80 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu16-log.txt @@ -0,0 +1,4 @@ +--- vu16 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vu16-Mode1D.bin' binary format='%uint16' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vu32-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vu32-Mode1D.bin new file mode 100644 index 0000000..a4e969a Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vu32-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vu32-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vu32-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu32-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vu32-log.txt b/gnuplot-iostream/unittest-output-good/vu32-log.txt new file mode 100644 index 0000000..35fd4b0 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu32-log.txt @@ -0,0 +1,4 @@ +--- vu32 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vu32-Mode1D.bin' binary format='%uint32' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vu8-Mode1D.bin b/gnuplot-iostream/unittest-output-good/vu8-Mode1D.bin new file mode 100644 index 0000000..eaf36c1 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vu8-Mode1D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vu8-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vu8-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu8-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vu8-log.txt b/gnuplot-iostream/unittest-output-good/vu8-log.txt new file mode 100644 index 0000000..775f31f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vu8-log.txt @@ -0,0 +1,4 @@ +--- vu8 ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D -> 'unittest-output/vu8-Mode1D.bin' binary format='%uint8' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vuc-Mode1D.txt b/gnuplot-iostream/unittest-output-good/vuc-Mode1D.txt new file mode 100644 index 0000000..bc856da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vuc-Mode1D.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/gnuplot-iostream/unittest-output-good/vuc-log.txt b/gnuplot-iostream/unittest-output-good/vuc-log.txt new file mode 100644 index 0000000..570f43a --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vuc-log.txt @@ -0,0 +1,4 @@ +--- vuc ------------------------------------- +depth=1 +ModeAutoDecoder=Mode1D +* Mode1D (skipped binary) diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.bin new file mode 100644 index 0000000..ecce2a0 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.txt new file mode 100644 index 0000000..208f6e2 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 200 300 400 110 210 310 410 120 220 320 420 +101 201 301 401 111 211 311 411 121 221 321 421 +102 202 302 402 112 212 312 412 122 222 322 422 +103 203 303 403 113 213 313 413 123 223 323 423 diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.bin b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.bin new file mode 100644 index 0000000..43f2caf Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.txt new file mode 100644 index 0000000..dbe2cb9 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-Mode2D.txt @@ -0,0 +1,14 @@ +100 200 300 400 +101 201 301 401 +102 202 302 402 +103 203 303 403 + +110 210 310 410 +111 211 311 411 +112 212 312 412 +113 213 313 413 + +120 220 320 420 +121 221 321 421 +122 222 322 422 +123 223 323 423 diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-log.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-log.txt new file mode 100644 index 0000000..d417028 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi,vvvi-log.txt @@ -0,0 +1,5 @@ +--- vvd,vvi,vvvi ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/vvd,vvi,vvvi-Mode2D.bin' binary format='%double%int32%int32%int32' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/vvd,vvi,vvvi-Mode1DUnwrap.bin' binary format='%double%int32%int32%int32%double%int32%int32%int32%double%int32%int32%int32' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.bin new file mode 100644 index 0000000..ad9b80e Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.txt new file mode 100644 index 0000000..d371fa8 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 200 110 210 120 220 +101 201 111 211 121 221 +102 202 112 212 122 222 +103 203 113 213 123 223 diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.bin b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.bin new file mode 100644 index 0000000..8dbdd40 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.txt new file mode 100644 index 0000000..39a6a7f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi-Mode2D.txt @@ -0,0 +1,14 @@ +100 200 +101 201 +102 202 +103 203 + +110 210 +111 211 +112 212 +113 213 + +120 220 +121 221 +122 222 +123 223 diff --git a/gnuplot-iostream/unittest-output-good/vvd,vvi-log.txt b/gnuplot-iostream/unittest-output-good/vvd,vvi-log.txt new file mode 100644 index 0000000..cbc3d7f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd,vvi-log.txt @@ -0,0 +1,5 @@ +--- vvd,vvi ------------------------------------- +depth=2 +ModeAutoDecoder=Mode2D +* Mode2D -> 'unittest-output/vvd,vvi-Mode2D.bin' binary format='%double%int32' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/vvd,vvi-Mode1DUnwrap.bin' binary format='%double%int32%double%int32%double%int32' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.bin b/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.bin new file mode 100644 index 0000000..75cb550 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.txt b/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.txt new file mode 100644 index 0000000..9a246fe --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd-Mode1DUnwrap.txt @@ -0,0 +1,4 @@ +100 110 120 +101 111 121 +102 112 122 +103 113 123 diff --git a/gnuplot-iostream/unittest-output-good/vvd-Mode2D.bin b/gnuplot-iostream/unittest-output-good/vvd-Mode2D.bin new file mode 100644 index 0000000..749bfa5 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvd-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvd-Mode2D.txt b/gnuplot-iostream/unittest-output-good/vvd-Mode2D.txt new file mode 100644 index 0000000..71ba638 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd-Mode2D.txt @@ -0,0 +1,14 @@ +100 +101 +102 +103 + +110 +111 +112 +113 + +120 +121 +122 +123 diff --git a/gnuplot-iostream/unittest-output-good/vvd-log.txt b/gnuplot-iostream/unittest-output-good/vvd-log.txt new file mode 100644 index 0000000..715b7da --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvd-log.txt @@ -0,0 +1,5 @@ +--- vvd ------------------------------------- +depth=2 +ModeAutoDecoder=Mode1DUnwrap +* Mode2D -> 'unittest-output/vvd-Mode2D.bin' binary format='%double' record=(4,3) +* Mode1DUnwrap -> 'unittest-output/vvd-Mode1DUnwrap.bin' binary format='%double%double%double' record=(4) diff --git a/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.bin b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.bin new file mode 100644 index 0000000..8adeaa6 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.txt b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.txt new file mode 100644 index 0000000..9e19aec --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2D.txt @@ -0,0 +1,14 @@ +300 400 +301 401 +302 402 +303 403 + +310 410 +311 411 +312 412 +313 413 + +320 420 +321 421 +322 422 +323 423 diff --git a/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.bin b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.bin new file mode 100644 index 0000000..229d729 Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.txt b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.txt new file mode 100644 index 0000000..098ce66 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvi cols-Mode2DUnwrap.txt @@ -0,0 +1,11 @@ +300 310 320 +400 410 420 + +301 311 321 +401 411 421 + +302 312 322 +402 412 422 + +303 313 323 +403 413 423 diff --git a/gnuplot-iostream/unittest-output-good/vvvi cols-log.txt b/gnuplot-iostream/unittest-output-good/vvvi cols-log.txt new file mode 100644 index 0000000..867bf9f --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvi cols-log.txt @@ -0,0 +1,5 @@ +--- vvvi cols ------------------------------------- +depth=3 +ModeAutoDecoder=Mode2DUnwrap +* Mode2D -> 'unittest-output/vvvi cols-Mode2D.bin' binary format='%int32%int32' record=(4,3) +* Mode2DUnwrap -> 'unittest-output/vvvi cols-Mode2DUnwrap.bin' binary format='%int32%int32%int32' record=(2,4) diff --git a/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.bin b/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.bin new file mode 100644 index 0000000..166426a Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.txt b/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.txt new file mode 100644 index 0000000..ff53abb --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvp-Mode2D.txt @@ -0,0 +1,14 @@ +0.5 0 1.5 1 +100.5 100 101.5 101 +200.5 200 201.5 201 +300.5 300 301.5 301 + +1000.5 1000 1001.5 1001 +1100.5 1100 1101.5 1101 +1200.5 1200 1201.5 1201 +1300.5 1300 1301.5 1301 + +2000.5 2000 2001.5 2001 +2100.5 2100 2101.5 2101 +2200.5 2200 2201.5 2201 +2300.5 2300 2301.5 2301 diff --git a/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.bin b/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.bin new file mode 100644 index 0000000..6d2eaaa Binary files /dev/null and b/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.bin differ diff --git a/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.txt b/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.txt new file mode 100644 index 0000000..5c0006b --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvp-Mode2DUnwrap.txt @@ -0,0 +1,11 @@ +0.5 0 1000.5 1000 2000.5 2000 +1.5 1 1001.5 1001 2001.5 2001 + +100.5 100 1100.5 1100 2100.5 2100 +101.5 101 1101.5 1101 2101.5 2101 + +200.5 200 1200.5 1200 2200.5 2200 +201.5 201 1201.5 1201 2201.5 2201 + +300.5 300 1300.5 1300 2300.5 2300 +301.5 301 1301.5 1301 2301.5 2301 diff --git a/gnuplot-iostream/unittest-output-good/vvvp-log.txt b/gnuplot-iostream/unittest-output-good/vvvp-log.txt new file mode 100644 index 0000000..e2e1ca9 --- /dev/null +++ b/gnuplot-iostream/unittest-output-good/vvvp-log.txt @@ -0,0 +1,5 @@ +--- vvvp ------------------------------------- +depth=3 +ModeAutoDecoder=Mode2DUnwrap +* Mode2D -> 'unittest-output/vvvp-Mode2D.bin' binary format='%double%int32%double%int32' record=(4,3) +* Mode2DUnwrap -> 'unittest-output/vvvp-Mode2DUnwrap.bin' binary format='%double%int32%double%int32%double%int32' record=(2,4) diff --git a/gnuplot-iostream/vc-path.bat b/gnuplot-iostream/vc-path.bat new file mode 100644 index 0000000..fb7d3d9 --- /dev/null +++ b/gnuplot-iostream/vc-path.bat @@ -0,0 +1,3 @@ +rem This is just here for my own tests. To be removed eventually. +set PATH=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\bin;%PATH% +set INCLUDE=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\include;%INCLUDE% diff --git a/result.cpp b/result.cpp index f15285f..b8c81ed 100644 --- a/result.cpp +++ b/result.cpp @@ -1,29 +1,39 @@ #include "result.h" +#include "gnuplot-iostream.h" #include "ui_result.h" #include #include +#include #include +#include #include // setprecision #include +#include #include #include #include #include +#define SHELL 1 +#define DEA 2 + using std::cout; using std::endl; using std::string; using std::vector; -Result::Result(DataBase * db, QWidget * parent) +Result::Result(DataBase * db, int rennid, QWidget * parent) : QWidget(parent), ui(new Ui::Result) { ui->setupUi(this); this->db = db; // prepare dummy data - vector header; + vector header; // dummy for now - this->rennid = 39; + // this->rennid = 39; + this->rennid = rennid; + + this->drawPlots(rennid); // test data header.push_back("Spalte 1"); @@ -137,9 +147,9 @@ Result::Result(DataBase * db, QWidget * parent) for (int fahrer : this->getFahrerIds(this->rennid)) { for (int car : this->getAutoIds(this->rennid)) { - int shellmin = this->getMinimum(fahrer, 1, this->rennid, car, + int shellmin = this->getMinimum(fahrer, SHELL, this->rennid, car, this->minimumTime); - int deamin = this->getMinimum(fahrer, 2, this->rennid, car, + int deamin = this->getMinimum(fahrer, DEA, this->rennid, car, this->minimumTime); subZeiten.push_back(static_cast(shellmin) / 1000); @@ -287,6 +297,86 @@ Result::Result(DataBase * db, QWidget * parent) this->ui->tWResult->horizontalHeader()->setStretchLastSection(true); } +void Result::drawPlots(int rennid) { + + // get drivers + vector driverIds = this->getFahrerIds(rennid); + vector drivers; + for_each(driverIds.begin(), driverIds.end(), [&drivers, this](int id) { + drivers.push_back(this->getFahrerName(id)); + }); + + vector carIds = this->getAutoIds(rennid); + + // get minimal time from race + std::stringstream statement; + statement << "select rennen.minimumRoundtime from Rennen where id like " + << boost::lexical_cast(rennid); + int minTimeRace = 2950; + + try { + minTimeRace = + this->db->getData2(statement.str(), 1).at(0).at(0).toInt(); + } catch (std::exception & e) { + Q_UNUSED(e); + cout << "minimal race time not readable from database" << endl; + cout << "min time set to: " << minTimeRace; + } + + vector times; + struct Times tempTimes; + int sumShell = 0; + int sumDea = 0; + for (int driverid : driverIds) { + sumShell = 0; + sumDea = 0; + for (int car : carIds) { + // shell + sumShell += + this->getMinimum(driverid, SHELL, rennid, car, minTimeRace); + + // dea + sumDea += this->getMinimum(driverid, DEA, rennid, car, minTimeRace); + } + tempTimes.shell = sumShell / static_cast(carIds.size()); + tempTimes.dea = sumDea / static_cast(carIds.size()); + + times.push_back(tempTimes); + } + + this->plotDrivers(drivers, times); + + // clean up + times.clear(); + + // calc cars + for (int carId : carIds) { + sumShell = 0; + sumDea = 0; + for (int driverId : driverIds) { + // shell + sumShell += + this->getMinimum(driverId, SHELL, rennid, carId, minTimeRace); + + // dea + sumDea += + this->getMinimum(driverId, DEA, rennid, carId, minTimeRace); + } + tempTimes.shell = sumShell / static_cast(driverIds.size()); + tempTimes.dea = sumDea / static_cast(driverIds.size()); + + times.push_back(tempTimes); + } + + // calc car names + vector carNames; + for_each(carIds.begin(), carIds.end(), [&carNames, this](int id) { + carNames.push_back(this->getAutoName(id)); + }); + + plotCars(carNames, times); +} + Result::~Result() { cout << "result closed" << endl; } @@ -308,7 +398,7 @@ template T Result::myMin(vector vec) { } template double Result::meanVal(vector vec) { - T sum = std::accumulate(vec.begin(), vec.end(), 0.0); + T sum = std::accumulate(vec.begin(), vec.end(), static_cast(0.0)); double mean = static_cast(sum) / vec.size(); return mean; } @@ -365,6 +455,7 @@ vector Result::getAutoIds(int rennid) { return vecToRet; } +// returns valid minimal time in milliseconds int Result::getMinimum(int fahrerId, int bahnId, int rennId, int autoid, int minTime) { std::stringstream statement; @@ -375,6 +466,7 @@ int Result::getMinimum(int fahrerId, int bahnId, int rennId, int autoid, << boost::lexical_cast(bahnId); try { + cout << statement.str() << endl; vector> res = this->db->getData2(statement.str(), 1); // filter impossible values vector validTimes; @@ -390,6 +482,7 @@ int Result::getMinimum(int fahrerId, int bahnId, int rennId, int autoid, return *result; } else { + cout << "no valid time found" << endl; return 9999; } @@ -419,6 +512,8 @@ float Result::getMean(int fahrerid, int bahnid, int rennid) { } return 9999; } + +// returns name of driver with id string Result::getFahrerName(int id) { std::stringstream statement; statement << "select name from fahrer where id like " @@ -469,3 +564,138 @@ string Result::getAutoName(int id) { return "name"; } + +double Result::getMinRangeTime(vector times) { + double min = 9999; + for (struct Times time : times) { + if (time.shell < min) { + min = time.shell; + } + if (time.dea < min) { + min = time.dea; + } + } + min -= 100; + cout << min << endl; + return min / 1000; +} + +double Result::getMaxRangeTime(vector times) { + double max = 0; + for (struct Times time : times) { + if (time.shell > max) { + max = time.shell; + } + if (time.dea > max) { + max = time.dea; + } + } + max += 200; + return max / 1000; +} + +void Result::plotCars(vector carNames, vector times) { + // structure of times: + Gnuplot gp; + std::stringstream xlabels; + xlabels << "set xtics("; + for (size_t i = 0; i < carNames.size(); i++) { + xlabels << "'" << carNames[i] << "' " + << boost::lexical_cast(i + 0.15); + if (i + 1 != carNames.size()) { + xlabels << ", "; + } + else { + xlabels << ")\n"; + } + } + cout << xlabels.str(); + gp << xlabels.str(); + + std::vector> xy_pts; + for (size_t i = 0; i < carNames.size(); i++) { + xy_pts.push_back(std::make_pair(i, (times.at(i).shell) / 1000.0)); + + // xy_pts.push_back(std::make_pair(i + 0.3, times.at(i).dea)); + } + double minRange = getMinRangeTime(times); + double maxRange = getMaxRangeTime(times); + + string strMinRange = boost::str(boost::format("%.2f") % minRange); + string strMaxRange = boost::str(boost::format("%.2f") % maxRange); + + gp << "set yrange [" << strMinRange << ":" << strMaxRange << "]\n"; + gp << "set boxwidth 0.3\nset style fill solid\n"; + gp << "set title 'Vergleich der Autos'\n"; + gp << "set ylabel 'Zeit in Sekunden'\n"; + gp << "set xlabel 'Autos'\n"; + gp << "show grid\nset grid ytics lc rgb '#bbbbbb' lw 1 lt 0\n"; + gp << "plot" << gp.file1d(xy_pts) + << "with boxes title 'Shell' lt rgb '#FF0000', '' u 1:($2 + " + "0.05):($2) with labels notitle" + << std::endl; + + xy_pts.clear(); + for (size_t i = 0; i < carNames.size(); i++) { + // xy_pts.push_back(std::make_pair(i, times.at(i).shell)); + xy_pts.push_back(std::make_pair(i + 0.3, (times.at(i).dea) / 1000.0)); + } + + gp << "replot" << gp.file1d(xy_pts) + << "with boxes title 'Dea' lt rgb '#00FF00', ''u 1:($2 + 0.05):($2) " + "with labels notitle" + << std::endl; +} + +void Result::plotDrivers(vector driverNames, + vector times) { + // structure of times: + Gnuplot gp; + std::stringstream xlabels; + xlabels << "set xtics("; + for (size_t i = 0; i < driverNames.size(); i++) { + xlabels << "'" << driverNames[i] << "' " + << boost::lexical_cast(i + 0.15); + if (i + 1 != driverNames.size()) { + xlabels << ", "; + } + else { + xlabels << ")\n"; + } + } + + gp << xlabels.str(); + + std::vector> xy_pts; + for (size_t i = 0; i < driverNames.size(); i++) { + xy_pts.push_back(std::make_pair(i, (times.at(i).shell) / 1000.0)); + // xy_pts.push_back(std::make_pair(i + 0.3, times.at(i).dea)); + } + double minRange = getMinRangeTime(times); + double maxRange = getMaxRangeTime(times); + + string strMinRange = boost::str(boost::format("%.2f") % minRange); + string strMaxRange = boost::str(boost::format("%.2f") % maxRange); + + gp << "set yrange [" << strMinRange << ":" << strMaxRange << "]\n"; + gp << "set boxwidth 0.3\nset style fill solid\n"; + gp << "set title 'Vergleich der Fahrer'\n"; + gp << "set ylabel 'Zeit in Sekunden'\n"; + gp << "set xlabel 'Fahrer'\n"; + gp << "show grid\nset grid ytics lc rgb '#bbbbbb' lw 1 lt 0\n"; + gp << "plot" << gp.file1d(xy_pts) + << "with boxes title 'Shell' lt rgb '#FF0000', '' u 1:($2 + " + "0.05):($2) with labels notitle" + << std::endl; + + xy_pts.clear(); + for (size_t i = 0; i < driverNames.size(); i++) { + // xy_pts.push_back(std::make_pair(i, times.at(i).shell)); + xy_pts.push_back(std::make_pair(i + 0.3, (times.at(i).dea) / 1000.0)); + } + + gp << "replot" << gp.file1d(xy_pts) + << "with boxes title 'Dea' lt rgb '#00FF00', ''u 1:($2 + 0.05):($2) " + "with labels notitle" + << std::endl; +} diff --git a/result.h b/result.h index 78bee4f..0bcd776 100644 --- a/result.h +++ b/result.h @@ -14,11 +14,16 @@ namespace Ui { class Result; } +struct Times { + int shell; + int dea; +}; + class Result : public QWidget { Q_OBJECT public: - explicit Result(DataBase * db, QWidget * parent = nullptr); + explicit Result(DataBase * db, int rennid, QWidget * parent = nullptr); ~Result(); public slots: void closeWindow(); @@ -34,6 +39,12 @@ class Result : public QWidget { string myRound(double, int); template double meanVal(vector vec); template T myMin(vector vec); + void plotCars(vector carNames, vector times); + void plotDrivers(vector driverNames, vector times); + double getMinRangeTime(vector times); + double getMaxRangeTime(vector times); + void drawPlots(int rennid); + Ui::Result * ui; ResultModel * model; DataBase * db;