├── sample_project.vcxproj.user ├── gnuplot-cppConfig.cmake ├── sample_project.vcxproj.filters ├── Makefile ├── runPVS_Studio.sh ├── README.md ├── gnuplot-cpp.sln ├── sample_project.vcxproj ├── example.cc ├── doc └── Doxyfile └── gnuplot_i.hpp /sample_project.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gnuplot-cppConfig.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3.0) 2 | project("gnuplot-cpp") 3 | 4 | message(STATUS "Found gnuplot:${gnuplot-cpp_DIR}") 5 | 6 | set(gnuplot-cpp_INCLUDE_DIRS ${gnuplot-cpp_INCLUDE_DIRS} "${gnuplot-cpp_DIR}") 7 | -------------------------------------------------------------------------------- /sample_project.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -ggdb -Wall -Wextra -pedantic -Wconversion -Wsign-conversion -O3 2 | DEFINES = -DDEBUGGA 3 | INCLUDES = 4 | LIBS = -lstdc++ 5 | EXAMPLE = example.o 6 | CC=g++ 7 | 8 | .cc.o: 9 | $(CC) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $< 10 | 11 | all: example 12 | 13 | gnuplot_i.o: gnuplot_i.hpp 14 | example.o: example.cc 15 | 16 | example: $(EXAMPLE) 17 | $(CC) -o $@ $(CFLAGS) $(EXAMPLE) $(LIBS) 18 | 19 | clean: 20 | rm -f $(EXAMPLE) example 21 | rm -f *.orig 22 | 23 | style: 24 | /usr/bin/find . -regextype "posix-extended" -iregex '.*\.(c|cc|cxx|h|hh|hpp|cpp)' -type f -exec astyle --style=ansi -S -N -w -Y -p -C -c -j {} \; 25 | -------------------------------------------------------------------------------- /runPVS_Studio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script runs the PVS Studio analyzer 3 | # on gnuplot-cpp 4 | # 5 | # Usage: 6 | # sh runPVS_Studio.sh 7 | # 8 | # After the script has finished, take a look at p.tasks. 9 | # This file contains the checking results. 10 | # 11 | # References: 12 | # - How to run PVS-Studio on Linux: https://www.viva64.com/en/m/0036/#ID0E3DAC 13 | # - How to use PVS-Studio for Free: https://www.viva64.com/en/b/0457/ 14 | # - Download PVS-Studio for Linux: https://www.viva64.com/en/pvs-studio-download-linux/ 15 | # 16 | 17 | make clean # Cleanup previous build 18 | rm -fR result # Remove results 19 | rm -f p.log # Remove log file 20 | pvs-studio-analyzer trace -- make -j3 CFLAGS="" 21 | pvs-studio-analyzer analyze -o p.log 22 | plog-converter -a GA:1,2,3 -t fullhtml -o result p.log 23 | xdg-open result/index.html 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gnuplot-cpp 2 | C++ interface to Gnuplot via POSIX pipes 3 | 4 | This project was hosted on [google code](https://code.google.com/archive/p/gnuplot-cpp/). Since google dropped google code, this project was moved to github. 5 | 6 | Total alerts 7 | ![Code scanning - action](https://github.com/orbitcowboy/gnuplot-cpp/workflows/Code%20scanning%20-%20action/badge.svg) 8 | 9 | # Use with CMake Projects 10 | 11 | To use this interface within your CMake projects, you can use the gnuplot-cppConfig.cmake. Just make sure, that CMake is able to find the gnuplot-cpp directory, either by moving it to the CMake search path, or setting graybat-cpp_dir. 12 | 13 | To include it into your project just add: 14 | ``` 15 | find_package(gnuplot-cpp REQUIRED) 16 | include_directories(${gnuplot-cpp_INCLUDE_DIRS}) 17 | ``` 18 | -------------------------------------------------------------------------------- /gnuplot-cpp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2005 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_project", "sample_project.vcxproj", "{903BC4A3-AD97-4569-8B6A-6A5D58768601}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {903BC4A3-AD97-4569-8B6A-6A5D58768601}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {903BC4A3-AD97-4569-8B6A-6A5D58768601}.Debug|Win32.Build.0 = Debug|Win32 16 | {903BC4A3-AD97-4569-8B6A-6A5D58768601}.Release|Win32.ActiveCfg = Release|Win32 17 | {903BC4A3-AD97-4569-8B6A-6A5D58768601}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {BB6E9203-F689-4515-BCFD-047A8A3EDE0A} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /sample_project.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {903BC4A3-AD97-4569-8B6A-6A5D58768601} 21 | Win32Proj 22 | sample_project 23 | 8.1 24 | gnuplot-cpp 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | v141 32 | 33 | 34 | Application 35 | false 36 | true 37 | Unicode 38 | v141 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | false 52 | ..\bin\ 53 | $(Configuration)\$(ProjectName)\ 54 | AllRules.ruleset 55 | false 56 | 57 | 58 | false 59 | ..\bin\ 60 | $(Configuration)\$(ProjectName)\ 61 | AllRules.ruleset 62 | false 63 | 64 | 65 | 66 | 67 | 68 | Level4 69 | Disabled 70 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 71 | /FS %(AdditionalOptions) 72 | 73 | 74 | Console 75 | true 76 | Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 77 | 78 | 79 | 80 | 81 | Level4 82 | 83 | 84 | MaxSpeed 85 | true 86 | true 87 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 88 | /FS 89 | 90 | 91 | Console 92 | true 93 | true 94 | true 95 | Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /example.cc: -------------------------------------------------------------------------------- 1 | // This is an open source non-commercial project. Dear PVS-Studio, please check it. 2 | // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com 3 | 4 | // Example for C++ Interface to Gnuplot 5 | 6 | // requirements: 7 | // * gnuplot has to be installed (http://www.gnuplot.info/download.html) 8 | // * for Windows: set Path-Variable for Gnuplot path (e.g. C:/program files/gnuplot/bin) 9 | // or set Gnuplot path with: Gnuplot::set_GNUPlotPath(const std::string &path); 10 | 11 | 12 | #include 13 | #include "gnuplot_i.hpp" //Gnuplot class handles POSIX-Pipe-communication with Gnuplot 14 | 15 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 16 | #include //for getch(), needed in wait_for_key() 17 | #include //for Sleep() 18 | #endif 19 | 20 | 21 | #define NPOINTS 50 // length of array 22 | 23 | static void wait_for_key(void); // Program halts until keypress 24 | 25 | using std::cout; 26 | using std::endl; 27 | 28 | int main(void) 29 | { 30 | // if path-variable for gnuplot is not set, do it with: 31 | // Gnuplot::set_GNUPlotPath("C:/program files/gnuplot/bin/"); 32 | 33 | #if defined(__APPLE__) 34 | // set a special standard terminal for showonscreen (normally not needed), 35 | // e.g. Mac users who want to use x11 instead of aqua terminal: 36 | Gnuplot::set_terminal_std("x11"); 37 | #endif 38 | cout << "*** example of gnuplot control through C++ ***" << endl << endl; 39 | 40 | // 41 | // Using the GnuplotException class 42 | // 43 | try 44 | { 45 | Gnuplot g1("lines"); 46 | 47 | // 48 | // Slopes 49 | // 50 | cout << "*** plotting slopes" << endl; 51 | g1.set_title("Slopes\\nNew Line"); 52 | 53 | cout << "y = x" << endl; 54 | g1.plot_slope(1.0, 0.0, "y=x"); 55 | 56 | cout << "y = 2*x" << endl; 57 | g1.plot_slope(2.0, 0.0, "y=2x"); 58 | 59 | cout << "y = -x" << endl; 60 | g1.plot_slope(-1.0, 0.0, "y=-x"); 61 | g1.unset_title(); 62 | 63 | // 64 | // Equations 65 | // 66 | g1.reset_plot(); 67 | cout << endl << endl << "*** various equations" << endl; 68 | 69 | cout << "y = sin(x)" << endl; 70 | g1.plot_equation("sin(x)", "sine"); 71 | 72 | cout << "y = log(x)" << endl; 73 | g1.plot_equation("log(x)", "logarithm"); 74 | 75 | cout << "y = sin(x) * cos(2*x)" << endl; 76 | g1.plot_equation("sin(x)*cos(2*x)", "sine product"); 77 | 78 | // 79 | // Styles 80 | // 81 | g1.reset_plot(); 82 | cout << endl << endl << "*** showing styles" << endl; 83 | 84 | cout << "sine in points" << endl; 85 | g1.set_pointsize(0.8).set_style("points"); 86 | g1.plot_equation("sin(x)", "points"); 87 | 88 | cout << "sine in impulses" << endl; 89 | g1.set_style("impulses"); 90 | g1.plot_equation("sin(x)", "impulses"); 91 | 92 | cout << "sine in steps" << endl; 93 | g1.set_style("steps"); 94 | g1.plot_equation("sin(x)", "steps"); 95 | 96 | // 97 | // Save to ps 98 | // 99 | g1.reset_all(); 100 | cout << endl << endl << "*** save to ps " << endl; 101 | 102 | cout << "y = sin(x) saved to test_output.ps in working directory" << endl; 103 | // g1.savetops("test_output"); 104 | g1.savetofigure("test_output.ps", "postscript color"); 105 | g1.set_style("lines").set_samples(300).set_xrange(0, 5); 106 | g1.plot_equation("sin(12*x)*exp(-x)").plot_equation("exp(-x)"); 107 | 108 | g1.showonscreen(); // window output 109 | 110 | 111 | // 112 | // User defined 1d, 2d and 3d point sets 113 | // 114 | std::vector x; 115 | std::vector y; 116 | std::vector y2; 117 | std::vector dy; 118 | std::vector z; 119 | 120 | for (unsigned int i = 0; i < NPOINTS; ++i) // fill double arrays x, y, z 121 | { 122 | x.push_back((double)i); // x[i] = i 123 | y.push_back((double)i * (double)i); // y[i] = i^2 124 | z.push_back( x[i]*y[i] ); // z[i] = x[i]*y[i] = i^3 125 | dy.push_back((double)i * (double)i / (double) 10); // dy[i] = i^2 / 10 126 | } 127 | y2.push_back(0.00); 128 | y2.push_back(0.78); 129 | y2.push_back(0.97); 130 | y2.push_back(0.43); 131 | y2.push_back(-0.44); 132 | y2.push_back(-0.98); 133 | y2.push_back(-0.77); 134 | y2.push_back(0.02); 135 | 136 | 137 | g1.reset_all(); 138 | cout << endl << endl << "*** user-defined lists of doubles" << endl; 139 | g1.set_style("impulses").plot_x(y, "user-defined doubles"); 140 | 141 | g1.reset_plot(); 142 | cout << endl << endl << "*** user-defined lists of points (x,y)" << endl; 143 | g1.set_grid(); 144 | g1.set_style("points").plot_xy(x, y, "user-defined points 2d"); 145 | 146 | g1.reset_plot(); 147 | cout << endl << endl << "*** user-defined lists of points (x,y,z)" << endl; 148 | g1.unset_grid(); 149 | g1.plot_xyz(x, y, z, "user-defined points 3d"); 150 | 151 | g1.reset_plot(); 152 | cout << endl << endl << "*** user-defined lists of points (x,y,dy)" << endl; 153 | g1.plot_xy_err(x, y, dy, "user-defined points 2d with errorbars"); 154 | 155 | 156 | // 157 | // Multiple output screens 158 | // 159 | cout << endl << endl; 160 | cout << "*** multiple output windows" << endl; 161 | 162 | g1.reset_plot(); 163 | g1.set_style("lines"); 164 | cout << "window 1: sin(x)" << endl; 165 | g1.set_grid().set_samples(600).set_xrange(0, 300); 166 | g1.plot_equation("sin(x)+sin(x*1.1)"); 167 | 168 | (void)g1.set_xautoscale().replot(); 169 | 170 | Gnuplot g2; 171 | cout << "window 2: user defined points" << endl; 172 | g2.plot_x(y2, "points"); 173 | g2.set_smooth().plot_x(y2, "cspline"); 174 | g2.set_smooth("bezier").plot_x(y2, "bezier"); 175 | g2.unset_smooth(); 176 | 177 | Gnuplot g3("lines"); 178 | cout << "window 3: log(x)/x" << endl; 179 | g3.set_grid(); 180 | g3.plot_equation("log(x)/x", "log(x)/x"); 181 | 182 | Gnuplot g4("lines"); 183 | cout << "window 4: splot x*x+y*y" << endl; 184 | g4.set_zrange(0, 100); 185 | g4.set_xlabel("x-axis").set_ylabel("y-axis").set_zlabel("z-axis"); 186 | g4.plot_equation3d("x*x+y*y"); 187 | 188 | Gnuplot g5("lines"); 189 | cout << "window 5: splot with hidden3d" << endl; 190 | (void)g5.set_isosamples(25).set_hidden3d(); 191 | g5.plot_equation3d("x*y*y"); 192 | 193 | Gnuplot g6("lines"); 194 | cout << "window 6: splot with contour" << endl; 195 | g6.set_isosamples(60).set_contour(); 196 | g6.unset_surface().plot_equation3d("sin(x)*sin(y)+4"); 197 | 198 | (void)g6.set_surface().replot(); 199 | 200 | Gnuplot g7("lines"); 201 | cout << "window 7: set_samples" << endl; 202 | g7.set_xrange(-30, 20).set_samples(40); 203 | g7.plot_equation("besj0(x)*0.12e1").plot_equation("(x**besj0(x))-2.5"); 204 | 205 | (void)g7.set_samples(400).replot(); 206 | 207 | Gnuplot g8("filledcurves"); 208 | cout << "window 8: filledcurves" << endl; 209 | g8.set_legend("outside right top").set_xrange(-5, 5); 210 | g8.plot_equation("x*x").plot_equation("-x*x+4"); 211 | 212 | // 213 | // Plot an image 214 | // 215 | Gnuplot g9; 216 | cout << "window 9: plot_image" << endl; 217 | constexpr const int unsigned uiWidth = 255U; 218 | constexpr const int unsigned uiHeight = 255U; 219 | g9.set_xrange(0, uiWidth).set_yrange(0, uiHeight).set_cbrange(0, 255); 220 | g9.cmd("set palette gray"); 221 | unsigned char ucPicBuf[uiWidth * uiHeight]; 222 | // generate a greyscale image 223 | for(unsigned int uiIndex = 0; uiIndex < uiHeight * uiWidth; ++uiIndex) 224 | { 225 | ucPicBuf[uiIndex] = static_cast(uiIndex % 255U); 226 | } 227 | g9.plot_image(ucPicBuf, uiWidth, uiHeight, "greyscale"); 228 | 229 | g9.set_pointsize(0.6).unset_legend().plot_slope(0.8, 20); 230 | 231 | // 232 | // manual control 233 | // 234 | Gnuplot g10; 235 | cout << "window 10: manual control" << endl; 236 | g10.cmd("set samples 400").cmd("plot abs(x)/2"); // either with cmd() 237 | g10 << "replot sqrt(x)"; 238 | g10 << "replot sqrt(-x)"; 239 | 240 | wait_for_key(); 241 | } 242 | catch (GnuplotException &ge) 243 | { 244 | cout << ge.what() << endl; 245 | } 246 | 247 | 248 | cout << endl << "*** end of gnuplot example" << endl; 249 | 250 | return 0; 251 | } 252 | 253 | 254 | 255 | static void wait_for_key (void) 256 | { 257 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) // every keypress registered, also arrow keys 258 | std::cout << std::endl << "Press any key to continue..." << std::endl; 259 | 260 | FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); 261 | (void)_getch(); 262 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 263 | std::cout << std::endl << "Press ENTER to continue..." << std::endl; 264 | 265 | std::cin.clear(); 266 | std::cin.ignore(std::cin.rdbuf()->in_avail()); 267 | (void)std::cin.get(); 268 | #endif 269 | } 270 | -------------------------------------------------------------------------------- /doc/Doxyfile: -------------------------------------------------------------------------------- 1 | # Doxyfile 1.5.6 2 | 3 | #--------------------------------------------------------------------------- 4 | # Project related configuration options 5 | #--------------------------------------------------------------------------- 6 | DOXYFILE_ENCODING = UTF-8 7 | PROJECT_NAME = gnuplot-cpp 8 | PROJECT_NUMBER = 0.9 9 | OUTPUT_DIRECTORY = ./ 10 | CREATE_SUBDIRS = YES 11 | OUTPUT_LANGUAGE = English 12 | BRIEF_MEMBER_DESC = YES 13 | REPEAT_BRIEF = YES 14 | ABBREVIATE_BRIEF = 15 | ALWAYS_DETAILED_SEC = NO 16 | INLINE_INHERITED_MEMB = NO 17 | FULL_PATH_NAMES = NO 18 | STRIP_FROM_PATH = 19 | STRIP_FROM_INC_PATH = 20 | SHORT_NAMES = NO 21 | JAVADOC_AUTOBRIEF = NO 22 | QT_AUTOBRIEF = NO 23 | MULTILINE_CPP_IS_BRIEF = NO 24 | DETAILS_AT_TOP = NO 25 | INHERIT_DOCS = YES 26 | SEPARATE_MEMBER_PAGES = NO 27 | TAB_SIZE = 8 28 | ALIASES = 29 | OPTIMIZE_OUTPUT_FOR_C = NO 30 | OPTIMIZE_OUTPUT_JAVA = NO 31 | OPTIMIZE_FOR_FORTRAN = NO 32 | OPTIMIZE_OUTPUT_VHDL = NO 33 | BUILTIN_STL_SUPPORT = NO 34 | CPP_CLI_SUPPORT = NO 35 | SIP_SUPPORT = NO 36 | IDL_PROPERTY_SUPPORT = YES 37 | DISTRIBUTE_GROUP_DOC = NO 38 | SUBGROUPING = YES 39 | TYPEDEF_HIDES_STRUCT = NO 40 | #--------------------------------------------------------------------------- 41 | # Build related configuration options 42 | #--------------------------------------------------------------------------- 43 | EXTRACT_ALL = YES 44 | EXTRACT_PRIVATE = NO 45 | EXTRACT_STATIC = NO 46 | EXTRACT_LOCAL_CLASSES = YES 47 | EXTRACT_LOCAL_METHODS = NO 48 | EXTRACT_ANON_NSPACES = NO 49 | HIDE_UNDOC_MEMBERS = NO 50 | HIDE_UNDOC_CLASSES = NO 51 | HIDE_FRIEND_COMPOUNDS = NO 52 | HIDE_IN_BODY_DOCS = NO 53 | INTERNAL_DOCS = NO 54 | CASE_SENSE_NAMES = NO 55 | HIDE_SCOPE_NAMES = NO 56 | SHOW_INCLUDE_FILES = YES 57 | INLINE_INFO = YES 58 | SORT_MEMBER_DOCS = YES 59 | SORT_BRIEF_DOCS = NO 60 | SORT_GROUP_NAMES = NO 61 | SORT_BY_SCOPE_NAME = NO 62 | GENERATE_TODOLIST = YES 63 | GENERATE_TESTLIST = YES 64 | GENERATE_BUGLIST = YES 65 | GENERATE_DEPRECATEDLIST= YES 66 | ENABLED_SECTIONS = 67 | MAX_INITIALIZER_LINES = 30 68 | SHOW_USED_FILES = YES 69 | SHOW_DIRECTORIES = NO 70 | SHOW_FILES = YES 71 | SHOW_NAMESPACES = YES 72 | FILE_VERSION_FILTER = 73 | #--------------------------------------------------------------------------- 74 | # configuration options related to warning and progress messages 75 | #--------------------------------------------------------------------------- 76 | QUIET = NO 77 | WARNINGS = YES 78 | WARN_IF_UNDOCUMENTED = YES 79 | WARN_IF_DOC_ERROR = YES 80 | WARN_NO_PARAMDOC = NO 81 | WARN_FORMAT = "$file:$line: $text" 82 | WARN_LOGFILE = 83 | #--------------------------------------------------------------------------- 84 | # configuration options related to the input files 85 | #--------------------------------------------------------------------------- 86 | INPUT = ../ 87 | INPUT_ENCODING = UTF-8 88 | FILE_PATTERNS = 89 | RECURSIVE = NO 90 | EXCLUDE = 91 | EXCLUDE_SYMLINKS = NO 92 | EXCLUDE_PATTERNS = 93 | EXCLUDE_SYMBOLS = 94 | EXAMPLE_PATH = ../example.cc 95 | EXAMPLE_PATTERNS = 96 | EXAMPLE_RECURSIVE = NO 97 | IMAGE_PATH = 98 | INPUT_FILTER = 99 | FILTER_PATTERNS = 100 | FILTER_SOURCE_FILES = NO 101 | #--------------------------------------------------------------------------- 102 | # configuration options related to source browsing 103 | #--------------------------------------------------------------------------- 104 | SOURCE_BROWSER = YES 105 | INLINE_SOURCES = YES 106 | STRIP_CODE_COMMENTS = YES 107 | REFERENCED_BY_RELATION = YES 108 | REFERENCES_RELATION = YES 109 | REFERENCES_LINK_SOURCE = YES 110 | USE_HTAGS = NO 111 | VERBATIM_HEADERS = YES 112 | #--------------------------------------------------------------------------- 113 | # configuration options related to the alphabetical class index 114 | #--------------------------------------------------------------------------- 115 | ALPHABETICAL_INDEX = NO 116 | COLS_IN_ALPHA_INDEX = 5 117 | IGNORE_PREFIX = 118 | #--------------------------------------------------------------------------- 119 | # configuration options related to the HTML output 120 | #--------------------------------------------------------------------------- 121 | GENERATE_HTML = YES 122 | HTML_OUTPUT = html 123 | HTML_FILE_EXTENSION = .html 124 | HTML_HEADER = 125 | HTML_FOOTER = 126 | HTML_STYLESHEET = 127 | HTML_ALIGN_MEMBERS = YES 128 | GENERATE_HTMLHELP = NO 129 | GENERATE_DOCSET = NO 130 | DOCSET_FEEDNAME = "Doxygen generated docs" 131 | DOCSET_BUNDLE_ID = org.doxygen.Project 132 | HTML_DYNAMIC_SECTIONS = NO 133 | CHM_FILE = 134 | HHC_LOCATION = 135 | GENERATE_CHI = NO 136 | CHM_INDEX_ENCODING = 137 | BINARY_TOC = NO 138 | TOC_EXPAND = NO 139 | DISABLE_INDEX = NO 140 | ENUM_VALUES_PER_LINE = 4 141 | GENERATE_TREEVIEW = NO 142 | TREEVIEW_WIDTH = 250 143 | FORMULA_FONTSIZE = 10 144 | #--------------------------------------------------------------------------- 145 | # configuration options related to the LaTeX output 146 | #--------------------------------------------------------------------------- 147 | GENERATE_LATEX = YES 148 | LATEX_OUTPUT = latex 149 | LATEX_CMD_NAME = latex 150 | MAKEINDEX_CMD_NAME = makeindex 151 | COMPACT_LATEX = NO 152 | PAPER_TYPE = a4wide 153 | EXTRA_PACKAGES = 154 | LATEX_HEADER = 155 | PDF_HYPERLINKS = NO 156 | USE_PDFLATEX = YES 157 | LATEX_BATCHMODE = NO 158 | LATEX_HIDE_INDICES = NO 159 | #--------------------------------------------------------------------------- 160 | # configuration options related to the RTF output 161 | #--------------------------------------------------------------------------- 162 | GENERATE_RTF = NO 163 | RTF_OUTPUT = rtf 164 | COMPACT_RTF = NO 165 | RTF_HYPERLINKS = NO 166 | RTF_STYLESHEET_FILE = 167 | RTF_EXTENSIONS_FILE = 168 | #--------------------------------------------------------------------------- 169 | # configuration options related to the man page output 170 | #--------------------------------------------------------------------------- 171 | GENERATE_MAN = NO 172 | MAN_OUTPUT = man 173 | MAN_EXTENSION = .3 174 | MAN_LINKS = NO 175 | #--------------------------------------------------------------------------- 176 | # configuration options related to the XML output 177 | #--------------------------------------------------------------------------- 178 | GENERATE_XML = NO 179 | XML_OUTPUT = xml 180 | XML_SCHEMA = 181 | XML_DTD = 182 | XML_PROGRAMLISTING = YES 183 | #--------------------------------------------------------------------------- 184 | # configuration options for the AutoGen Definitions output 185 | #--------------------------------------------------------------------------- 186 | GENERATE_AUTOGEN_DEF = NO 187 | #--------------------------------------------------------------------------- 188 | # configuration options related to the Perl module output 189 | #--------------------------------------------------------------------------- 190 | GENERATE_PERLMOD = NO 191 | PERLMOD_LATEX = NO 192 | PERLMOD_PRETTY = YES 193 | PERLMOD_MAKEVAR_PREFIX = 194 | #--------------------------------------------------------------------------- 195 | # Configuration options related to the preprocessor 196 | #--------------------------------------------------------------------------- 197 | ENABLE_PREPROCESSING = YES 198 | MACRO_EXPANSION = NO 199 | EXPAND_ONLY_PREDEF = NO 200 | SEARCH_INCLUDES = YES 201 | INCLUDE_PATH = 202 | INCLUDE_FILE_PATTERNS = 203 | PREDEFINED = 204 | EXPAND_AS_DEFINED = 205 | SKIP_FUNCTION_MACROS = YES 206 | #--------------------------------------------------------------------------- 207 | # Configuration::additions related to external references 208 | #--------------------------------------------------------------------------- 209 | TAGFILES = 210 | GENERATE_TAGFILE = 211 | ALLEXTERNALS = NO 212 | EXTERNAL_GROUPS = YES 213 | PERL_PATH = /usr/bin/perl 214 | #--------------------------------------------------------------------------- 215 | # Configuration options related to the dot tool 216 | #--------------------------------------------------------------------------- 217 | CLASS_DIAGRAMS = YES 218 | MSCGEN_PATH = 219 | HIDE_UNDOC_RELATIONS = YES 220 | HAVE_DOT = NO 221 | DOT_FONTNAME = FreeSans 222 | DOT_FONTPATH = 223 | CLASS_GRAPH = YES 224 | COLLABORATION_GRAPH = YES 225 | GROUP_GRAPHS = YES 226 | UML_LOOK = NO 227 | TEMPLATE_RELATIONS = NO 228 | INCLUDE_GRAPH = YES 229 | INCLUDED_BY_GRAPH = YES 230 | CALL_GRAPH = NO 231 | CALLER_GRAPH = NO 232 | GRAPHICAL_HIERARCHY = YES 233 | DIRECTORY_GRAPH = YES 234 | DOT_IMAGE_FORMAT = png 235 | DOT_PATH = 236 | DOTFILE_DIRS = 237 | DOT_GRAPH_MAX_NODES = 50 238 | MAX_DOT_GRAPH_DEPTH = 0 239 | DOT_TRANSPARENT = YES 240 | DOT_MULTI_TARGETS = NO 241 | GENERATE_LEGEND = YES 242 | DOT_CLEANUP = YES 243 | #--------------------------------------------------------------------------- 244 | # Configuration::additions related to the search engine 245 | #--------------------------------------------------------------------------- 246 | SEARCHENGINE = NO 247 | -------------------------------------------------------------------------------- /gnuplot_i.hpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// \brief A C++ interface to gnuplot. 4 | /// 5 | /// 6 | /// The interface uses pipes and so won't run on a system that doesn't have 7 | /// POSIX pipe support Tested on Windows (MinGW and Visual C++) and Linux (GCC) 8 | /// 9 | /// Version history: 10 | /// 0. C interface 11 | /// by N. Devillard (27/01/03) 12 | /// 1. C++ interface: direct translation from the C interface 13 | /// by Rajarshi Guha (07/03/03) 14 | /// 2. corrections for Win32 compatibility 15 | /// by V. Chyzhdzenka (20/05/03) 16 | /// 3. some member functions added, corrections for Win32 and Linux 17 | /// compatibility 18 | /// by M. Burgis (10/03/08) 19 | /// 20 | /// Requirements: 21 | /// * gnuplot has to be installed (http://www.gnuplot.info/download.html) 22 | /// * for Windows: set Path-Variable for Gnuplot path 23 | /// (e.g. C:/program files/gnuplot/bin) 24 | /// or set Gnuplot path with: 25 | /// Gnuplot::set_GNUPlotPath(const std::string &path); 26 | /// 27 | //////////////////////////////////////////////////////////////////////////////// 28 | 29 | 30 | #ifndef GNUPLOT_I_HPP 31 | #define GNUPLOT_I_HPP 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include // for std::ostringstream 38 | #include 39 | #include // for getenv() 40 | #include // for std::list 41 | 42 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 43 | //defined for 32 and 64-bit environments 44 | #include // for _access(), _mktemp() 45 | #define GP_MAX_TMP_FILES 27 // 27 temporary files it's Microsoft restriction 46 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 47 | //all UNIX-like OSs (Linux, *BSD, MacOSX, Solaris, ...) 48 | #include // for access(), mkstemp() 49 | #define GP_MAX_TMP_FILES 64 50 | #else 51 | #error unsupported or unknown operating system 52 | #endif 53 | 54 | //declare classes in global namespace 55 | 56 | 57 | class GnuplotException : public std::runtime_error 58 | { 59 | public: 60 | explicit GnuplotException(const std::string &msg) : std::runtime_error(msg) {} 61 | }; 62 | 63 | 64 | 65 | class Gnuplot 66 | { 67 | //---------------------------------------------------------------------------------- 68 | // member data 69 | ///\brief pointer to the stream that can be used to write to the pipe 70 | FILE *gnucmd; 71 | ///\brief validation of gnuplot session 72 | bool valid; 73 | ///\brief true = 2d, false = 3d 74 | bool two_dim; 75 | ///\brief number of plots in session 76 | int nplots; 77 | ///\brief functions and data are displayed in a defined styles 78 | std::string pstyle; 79 | ///\brief interpolate and approximate data in defined styles (e.g. spline) 80 | std::string smooth; 81 | ///\brief list of created tmpfiles 82 | std::vector tmpfile_list; 83 | 84 | //---------------------------------------------------------------------------------- 85 | // static data 86 | ///\brief number of all tmpfiles (number of tmpfiles restricted) 87 | static int tmpfile_num; 88 | ///\brief name of executed GNUPlot file 89 | static std::string m_sGNUPlotFileName; 90 | ///\brief gnuplot path 91 | static std::string m_sGNUPlotPath; 92 | ///\brief standard terminal, used by showonscreen 93 | static std::string terminal_std; 94 | 95 | //---------------------------------------------------------------------------------- 96 | // member functions (auxiliary functions) 97 | // --------------------------------------------------- 98 | ///\brief get_program_path(); and popen(); 99 | // --------------------------------------------------- 100 | void init(void); 101 | // --------------------------------------------------- 102 | ///\brief creates tmpfile and returns its name 103 | /// 104 | /// \param tmp points to the tempfile 105 | /// 106 | /// \return the name of the tempfile 107 | // --------------------------------------------------- 108 | std::string create_tmpfile(std::ofstream &tmp); 109 | 110 | //---------------------------------------------------------------------------------- 111 | ///\brief gnuplot path found? 112 | /// 113 | /// \return found the gnuplot path (yes == true, no == false) 114 | // --------------------------------------------------------------------------------- 115 | static bool get_program_path(void); 116 | 117 | // --------------------------------------------------------------------------------- 118 | ///\brief checks if file is available 119 | /// 120 | /// \param filename the filename 121 | /// 122 | /// \return file exists (yes == true, no == false) 123 | // --------------------------------------------------------------------------------- 124 | static bool file_available(const std::string &filename); 125 | 126 | // --------------------------------------------------------------------------------- 127 | ///\brief checks if file exists 128 | /// 129 | /// \param filename the filename 130 | /// \param mode the mode [optional,default value = 0] 131 | /// 132 | /// \return file exists (yes == true, no == false) 133 | // --------------------------------------------------------------------------------- 134 | static bool file_exists(const std::string &filename, int mode = 0); 135 | 136 | public: 137 | 138 | // ---------------------------------------------------------------------------- 139 | /// \brief optional function: set Gnuplot path manual 140 | /// attention: for windows: path with slash '/' not backslash '\' 141 | /// 142 | /// \param path the gnuplot path 143 | /// 144 | /// \return true on success, false otherwise 145 | // ---------------------------------------------------------------------------- 146 | static bool set_GNUPlotPath(const std::string &path); 147 | 148 | 149 | // ---------------------------------------------------------------------------- 150 | /// optional: set standard terminal, used by showonscreen 151 | /// defaults: Windows - win, Linux - x11, Mac - aqua 152 | /// 153 | /// \param type the terminal type 154 | // ---------------------------------------------------------------------------- 155 | static void set_terminal_std(const std::string &type); 156 | 157 | //----------------------------------------------------------------------------- 158 | // constructors 159 | // ---------------------------------------------------------------------------- 160 | 161 | 162 | ///\brief set a style during construction 163 | explicit Gnuplot(const std::string &style = "points"); 164 | 165 | /// plot a single std::vector at one go 166 | explicit Gnuplot(const std::vector &x, 167 | const std::string &title = "", 168 | const std::string &style = "points", 169 | const std::string &labelx = "x", 170 | const std::string &labely = "y"); 171 | 172 | /// plot pairs std::vector at one go 173 | explicit Gnuplot(const std::vector &x, 174 | const std::vector &y, 175 | const std::string &title = "", 176 | const std::string &style = "points", 177 | const std::string &labelx = "x", 178 | const std::string &labely = "y"); 179 | 180 | /// plot triples std::vector at one go 181 | explicit Gnuplot(const std::vector &x, 182 | const std::vector &y, 183 | const std::vector &z, 184 | const std::string &title = "", 185 | const std::string &style = "points", 186 | const std::string &labelx = "x", 187 | const std::string &labely = "y", 188 | const std::string &labelz = "z"); 189 | 190 | /// destructor: needed to delete temporary files 191 | ~Gnuplot(void); 192 | 193 | 194 | //---------------------------------------------------------------------------------- 195 | 196 | /// send a command to gnuplot 197 | Gnuplot& cmd(const std::string &cmdstr); 198 | // ------------------------------------------------------------------------- 199 | ///\brief Sends a command to an active gnuplot session, identical to cmd() 200 | /// send a command to gnuplot using the << operator 201 | /// 202 | /// \param cmdstr the command string 203 | /// 204 | /// \return a reference to the gnuplot object 205 | // ------------------------------------------------------------------------- 206 | inline Gnuplot& operator<<(const std::string &cmdstr) 207 | { 208 | return cmd(cmdstr); 209 | } 210 | 211 | 212 | 213 | //-------------------------------------------------------------------------- 214 | // show on screen or write to file 215 | 216 | /// sets terminal type to terminal_std 217 | Gnuplot& showonscreen(void); // window output is set by default (win/x11/aqua) 218 | 219 | /// Saves a gnuplot to a file named filename. Defaults to saving pdf 220 | Gnuplot& savetofigure(const std::string &filename, 221 | const std::string &terminal = "ps"); 222 | 223 | //-------------------------------------------------------------------------- 224 | // set and unset 225 | 226 | /// set line style (some of these styles require additional information): 227 | /// lines, points, linespoints, impulses, dots, steps, fsteps, histeps, 228 | /// boxes, histograms, filledcurves 229 | Gnuplot& set_style(const std::string &stylestr = "points"); 230 | 231 | /// interpolation and approximation of data, arguments: 232 | /// csplines, bezier, acsplines (for data values > 0), sbezier, unique, frequency 233 | /// (works only with plot_x, plot_xy, plotfile_x, plotfile_xy 234 | /// (if smooth is set, set_style has no effect on data plotting) 235 | Gnuplot& set_smooth(const std::string &stylestr = "csplines"); 236 | 237 | // ---------------------------------------------------------------------- 238 | /// \brief unset smooth 239 | /// attention: smooth is not set by default 240 | /// 241 | /// \return a reference to a gnuplot object 242 | // ---------------------------------------------------------------------- 243 | inline Gnuplot& unset_smooth(void) 244 | { 245 | smooth.clear(); 246 | return *this; 247 | } 248 | 249 | /// scales the size of the points used in plots 250 | Gnuplot& set_pointsize(const double pointsize = 1.0); 251 | 252 | /// turns grid on/off 253 | inline Gnuplot& set_grid(void) 254 | { 255 | return cmd("set grid"); 256 | } 257 | /// grid is not set by default 258 | inline Gnuplot& unset_grid(void) 259 | { 260 | return cmd("unset grid"); 261 | } 262 | 263 | // ----------------------------------------------- 264 | /// set the multiplot mode 265 | /// 266 | /// \return reference to the gnuplot object 267 | // ----------------------------------------------- 268 | inline Gnuplot& set_multiplot(void) 269 | { 270 | return cmd("set multiplot"); 271 | } 272 | 273 | // ----------------------------------------------- 274 | /// unsets the multiplot mode 275 | /// 276 | /// \return reference to the gnuplot object 277 | // ----------------------------------------------- 278 | inline Gnuplot& unset_multiplot(void) 279 | { 280 | return cmd("unset multiplot"); 281 | } 282 | 283 | /// set sampling rate of functions, or for interpolating data 284 | Gnuplot& set_samples(const int samples = 100); 285 | /// set isoline density (grid) for plotting functions as surfaces (for 3d plots) 286 | Gnuplot& set_isosamples(const int isolines = 10); 287 | 288 | // -------------------------------------------------------------------------- 289 | /// enables/disables hidden line removal for surface plotting (for 3d plot) 290 | /// 291 | /// \return reference to the gnuplot object 292 | // -------------------------------------------------------------------------- 293 | Gnuplot& set_hidden3d(void) 294 | { 295 | return cmd("set hidden3d"); 296 | } 297 | 298 | // --------------------------------------------------------------------------- 299 | /// hidden3d is not set by default 300 | /// 301 | /// \return reference to the gnuplot object 302 | // --------------------------------------------------------------------------- 303 | inline Gnuplot& unset_hidden3d(void) 304 | { 305 | return cmd("unset hidden3d"); 306 | } 307 | 308 | /// enables/disables contour drawing for surfaces (for 3d plot) 309 | /// base, surface, both 310 | Gnuplot& set_contour(const std::string &position = "base"); 311 | // -------------------------------------------------------------------------- 312 | /// contour is not set by default, it disables contour drawing for surfaces 313 | /// 314 | /// \return reference to the gnuplot object 315 | // ------------------------------------------------------------------ 316 | inline Gnuplot& unset_contour(void) 317 | { 318 | return cmd("unset contour"); 319 | } 320 | 321 | // ------------------------------------------------------------ 322 | /// enables/disables the display of surfaces (for 3d plot) 323 | /// 324 | /// \return reference to the gnuplot object 325 | // ------------------------------------------------------------------ 326 | inline Gnuplot& set_surface(void) 327 | { 328 | return cmd("set surface"); 329 | } 330 | 331 | // ---------------------------------------------------------- 332 | /// surface is set by default, 333 | /// it disables the display of surfaces (for 3d plot) 334 | /// 335 | /// \return reference to the gnuplot object 336 | // ------------------------------------------------------------------ 337 | inline Gnuplot& unset_surface(void) 338 | { 339 | return cmd("unset surface"); 340 | } 341 | 342 | 343 | /// switches legend on/off 344 | /// position: inside/outside, left/center/right, top/center/bottom, nobox/box 345 | Gnuplot& set_legend(const std::string &position = "default"); 346 | 347 | // ------------------------------------------------------------------ 348 | /// \brief Switches legend off 349 | /// attention:legend is set by default 350 | /// 351 | /// \return reference to the gnuplot object 352 | // ------------------------------------------------------------------ 353 | inline Gnuplot& unset_legend(void) 354 | { 355 | return cmd("unset key"); 356 | } 357 | 358 | // ----------------------------------------------------------------------- 359 | /// \brief sets and clears the title of a gnuplot session 360 | /// 361 | /// \param title the title of the plot [optional, default == ""] 362 | /// 363 | /// \return reference to the gnuplot object 364 | // ----------------------------------------------------------------------- 365 | inline Gnuplot& set_title(const std::string &title = "") 366 | { 367 | const std::string cmdstr("set title \"" + title + "\""); 368 | *this << cmdstr; 369 | return *this; 370 | } 371 | 372 | //---------------------------------------------------------------------------------- 373 | ///\brief Clears the title of a gnuplot session 374 | /// The title is not set by default. 375 | /// 376 | /// \return reference to the gnuplot object 377 | // --------------------------------------------------------------------------------- 378 | inline Gnuplot& unset_title(void) 379 | { 380 | return this->set_title(); 381 | } 382 | 383 | 384 | /// set x axis label 385 | Gnuplot& set_ylabel(const std::string &label = "x"); 386 | /// set y axis label 387 | Gnuplot& set_xlabel(const std::string &label = "y"); 388 | /// set z axis label 389 | Gnuplot& set_zlabel(const std::string &label = "z"); 390 | 391 | /// set axis - ranges 392 | Gnuplot& set_xrange(const double iFrom, 393 | const double iTo); 394 | /// set y-axis - ranges 395 | Gnuplot& set_yrange(const double iFrom, 396 | const double iTo); 397 | /// set z-axis - ranges 398 | Gnuplot& set_zrange(const double iFrom, 399 | const double iTo); 400 | /// autoscale axis (set by default) of xaxis 401 | /// 402 | /// \return reference to the gnuplot object 403 | // ----------------------------------------------- 404 | inline Gnuplot& set_xautoscale(void) 405 | { 406 | (void)cmd("set xrange restore"); 407 | return cmd("set autoscale x"); 408 | } 409 | 410 | // ----------------------------------------------- 411 | /// autoscale axis (set by default) of yaxis 412 | /// 413 | /// \return reference to the gnuplot object 414 | // ----------------------------------------------- 415 | inline Gnuplot& set_yautoscale(void) 416 | { 417 | (void)cmd("set yrange restore"); 418 | return cmd("set autoscale y"); 419 | } 420 | 421 | // ----------------------------------------------- 422 | /// autoscale axis (set by default) of zaxis 423 | /// 424 | /// \return reference to the gnuplot object 425 | // ----------------------------------------------- 426 | inline Gnuplot& set_zautoscale(void) 427 | { 428 | (void)cmd("set zrange restore"); 429 | return cmd("set autoscale z"); 430 | } 431 | 432 | 433 | /// turns on/off log scaling for the specified xaxis (logscale is not set by default) 434 | Gnuplot& set_xlogscale(const double base = 10); 435 | /// turns on/off log scaling for the specified yaxis (logscale is not set by default) 436 | Gnuplot& set_ylogscale(const double base = 10); 437 | /// turns on/off log scaling for the specified zaxis (logscale is not set by default) 438 | Gnuplot& set_zlogscale(const double base = 10); 439 | 440 | // ----------------------------------------------- 441 | /// turns off log scaling for the x axis 442 | /// 443 | /// \return reference to the gnuplot object 444 | // ----------------------------------------------- 445 | inline Gnuplot& unset_xlogscale(void) 446 | { 447 | return cmd("unset logscale x"); 448 | } 449 | 450 | // ----------------------------------------------- 451 | /// turns off log scaling for the y axis 452 | /// 453 | /// \return reference to the gnuplot object 454 | // ----------------------------------------------- 455 | inline Gnuplot& unset_ylogscale(void) 456 | { 457 | return cmd("unset logscale y"); 458 | } 459 | 460 | // ----------------------------------------------- 461 | /// turns off log scaling for the z axis 462 | /// 463 | /// \return reference to the gnuplot object 464 | // ----------------------------------------------- 465 | inline Gnuplot& unset_zlogscale(void) 466 | { 467 | return cmd("unset logscale z"); 468 | } 469 | 470 | /// set palette range (autoscale by default) 471 | Gnuplot& set_cbrange(const double iFrom, const double iTo); 472 | 473 | 474 | //-------------------------------------------------------------------------- 475 | // plot 476 | 477 | /// plot a single std::vector: x 478 | /// from file 479 | Gnuplot& plotfile_x(const std::string &filename, 480 | const unsigned int column = 1, 481 | const std::string &title = ""); 482 | /// from std::vector 483 | template 484 | Gnuplot& plot_x(const X& x, const std::string &title = ""); 485 | 486 | 487 | /// plot x,y pairs: x y 488 | /// from file 489 | Gnuplot& plotfile_xy(const std::string &filename, 490 | const unsigned int column_x = 1, 491 | const unsigned int column_y = 2, 492 | const std::string &title = ""); 493 | /// from data 494 | template 495 | Gnuplot& plot_xy(const X& x, const Y& y, const std::string &title = ""); 496 | 497 | 498 | /// plot x,y pairs with dy errorbars: x y dy 499 | /// from file 500 | Gnuplot& plotfile_xy_err(const std::string &filename, 501 | const unsigned int column_x = 1, 502 | const unsigned int column_y = 2, 503 | const unsigned int column_dy = 3, 504 | const std::string &title = ""); 505 | /// from data 506 | template 507 | Gnuplot& plot_xy_err(const X &x, const Y &y, const E &dy, 508 | const std::string &title = ""); 509 | 510 | 511 | /// plot x,y,z triples: x y z 512 | /// from file 513 | Gnuplot& plotfile_xyz(const std::string &filename, 514 | const unsigned int column_x = 1, 515 | const unsigned int column_y = 2, 516 | const unsigned int column_z = 3, 517 | const std::string &title = ""); 518 | /// from std::vector 519 | template 520 | Gnuplot& plot_xyz(const X &x, 521 | const Y &y, 522 | const Z &z, 523 | const std::string &title = ""); 524 | 525 | 526 | 527 | /// plot an equation of the form: y = ax + b, you supply a and b 528 | Gnuplot& plot_slope(const double a, 529 | const double b, 530 | const std::string &title = ""); 531 | 532 | 533 | /// plot an equation supplied as a std::string y=f(x), write only the 534 | /// function f(x) not y the independent variable has to be x 535 | /// binary operators: ** exponentiation, * multiply, / divide, + add, - 536 | /// subtract, % modulo 537 | /// unary operators: - minus, ! factorial 538 | /// elementary functions: rand(x), abs(x), sgn(x), ceil(x), floor(x), 539 | /// int(x), imag(x), real(x), arg(x), sqrt(x), exp(x), log(x), log10(x), 540 | /// sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x), 541 | /// sinh(x), cosh(x), tanh(x), asinh(x), acosh(x), atanh(x) 542 | /// special functions: erf(x), erfc(x), inverf(x), gamma(x), igamma(a,x), 543 | /// lgamma(x), ibeta(p,q,x), besj0(x), besj1(x), besy0(x), besy1(x), 544 | /// lambertw(x) 545 | /// statistical functions: norm(x), invnorm(x) 546 | Gnuplot& plot_equation(const std::string &equation, 547 | const std::string &title = ""); 548 | 549 | /// plot an equation supplied as a std::string z=f(x,y), write only the 550 | /// function f(x,y) not z the independent variables have to be x and y 551 | Gnuplot& plot_equation3d(const std::string &equation, 552 | const std::string &title = ""); 553 | 554 | 555 | /// plot image 556 | Gnuplot& plot_image(const unsigned char *ucPicBuf, 557 | const unsigned int iWidth, 558 | const unsigned int iHeight, 559 | const std::string &title = ""); 560 | 561 | 562 | //-------------------------------------------------------------------------- 563 | ///\brief replot repeats the last plot or splot command. 564 | /// this can be useful for viewing a plot with different set options, 565 | /// or when generating the same plot for several devices (showonscreen, 566 | /// savetofigure) 567 | /// 568 | /// \return --- 569 | //-------------------------------------------------------------------------- 570 | inline Gnuplot& replot(void) 571 | { 572 | if (nplots > 0) 573 | { 574 | return cmd("replot"); 575 | } 576 | return *this; 577 | } 578 | 579 | /// resets a gnuplot session (next plot will erase previous ones) 580 | Gnuplot& reset_plot(void); 581 | 582 | /// resets a gnuplot session and sets all variables to default 583 | Gnuplot& reset_all(void); 584 | 585 | /// deletes temporary files 586 | void remove_tmpfiles(void); 587 | 588 | /// \brief Is the gnuplot session valid ?? 589 | /// 590 | /// \return true if valid, false if not 591 | inline bool is_valid(void) const 592 | { 593 | return valid; 594 | } 595 | }; 596 | 597 | //------------------------------------------------------------------------------ 598 | // 599 | // initialize static data 600 | // 601 | int Gnuplot::tmpfile_num = 0; 602 | 603 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 604 | std::string Gnuplot::m_sGNUPlotFileName = "pgnuplot.exe"; 605 | std::string Gnuplot::m_sGNUPlotPath = "C:/program files/gnuplot/bin/"; 606 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 607 | std::string Gnuplot::m_sGNUPlotFileName = "gnuplot"; 608 | std::string Gnuplot::m_sGNUPlotPath = "/usr/local/bin/"; 609 | #endif 610 | 611 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 612 | std::string Gnuplot::terminal_std = "windows"; 613 | #elif ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__) 614 | std::string Gnuplot::terminal_std = "x11"; 615 | #elif defined(__APPLE__) 616 | std::string Gnuplot::terminal_std = "aqua"; 617 | #endif 618 | 619 | //------------------------------------------------------------------------------ 620 | // 621 | // constructor: set a style during construction 622 | // 623 | inline Gnuplot::Gnuplot(const std::string &style) 624 | : gnucmd(nullptr) , valid(false) , two_dim(false) , nplots(0) 625 | 626 | { 627 | init(); 628 | (void)set_style(style); 629 | } 630 | 631 | //------------------------------------------------------------------------------ 632 | // 633 | // constructor: open a new session, plot a signal (x) 634 | // 635 | inline Gnuplot::Gnuplot(const std::vector &x, 636 | const std::string &title, 637 | const std::string &style, 638 | const std::string &labelx, 639 | const std::string &labely) 640 | : gnucmd(nullptr) , valid(false) , two_dim(false) , nplots(0) 641 | { 642 | init(); 643 | 644 | (void)set_style(style); 645 | (void)set_xlabel(labelx); 646 | (void)set_ylabel(labely); 647 | 648 | (void)plot_x(x, title); 649 | } 650 | 651 | 652 | // constructor: open a new session, plot a signal (x,y) 653 | inline Gnuplot::Gnuplot(const std::vector &x, 654 | const std::vector &y, 655 | const std::string &title, 656 | const std::string &style, 657 | const std::string &labelx, 658 | const std::string &labely) 659 | : gnucmd(nullptr) , valid(false) , two_dim(false) , nplots(0) 660 | { 661 | init(); 662 | 663 | (void)set_style(style); 664 | (void)set_xlabel(labelx); 665 | (void)set_ylabel(labely); 666 | 667 | (void)plot_xy(x, y, title); 668 | } 669 | 670 | // constructor: open a new session, plot a signal (x,y,z) 671 | inline Gnuplot::Gnuplot(const std::vector &x, 672 | const std::vector &y, 673 | const std::vector &z, 674 | const std::string &title, 675 | const std::string &style, 676 | const std::string &labelx, 677 | const std::string &labely, 678 | const std::string &labelz) 679 | : gnucmd(nullptr) , valid(false) , two_dim(false) , nplots(0) 680 | { 681 | init(); 682 | 683 | (void)set_style(style); 684 | (void)set_xlabel(labelx); 685 | (void)set_ylabel(labely); 686 | (void)set_zlabel(labelz); 687 | 688 | (void)plot_xyz(x, y, z, title); 689 | } 690 | 691 | /// Plots a 2d graph from a list of doubles: x 692 | template 693 | Gnuplot& Gnuplot::plot_x(const X& x, const std::string &title) 694 | { 695 | if (x.empty()) 696 | { 697 | throw GnuplotException("std::vector too small"); 698 | } 699 | 700 | std::ofstream tmp; 701 | std::string name = create_tmpfile(tmp); 702 | if (name.empty()) 703 | { 704 | return *this; 705 | } 706 | 707 | // 708 | // write the data to file 709 | // 710 | for (unsigned int i = 0; i < x.size(); ++i) 711 | { 712 | tmp << x[i] << std::endl; 713 | } 714 | 715 | tmp.flush(); 716 | tmp.close(); 717 | 718 | 719 | plotfile_x(name, 1, title); 720 | 721 | return *this; 722 | } 723 | 724 | 725 | /// Plots a 2d graph from a list of doubles: x y 726 | template 727 | Gnuplot& Gnuplot::plot_xy(const X& x, const Y& y, const std::string &title) 728 | { 729 | if (x.empty() || y.empty()) 730 | { 731 | throw GnuplotException("std::vectors too small"); 732 | } 733 | 734 | if (x.size() != y.size()) 735 | { 736 | throw GnuplotException("Length of the std::vectors differs"); 737 | } 738 | std::ofstream tmp; 739 | const std::string name = create_tmpfile(tmp); 740 | if (name.empty()) 741 | { 742 | throw GnuplotException("Unable to create tmp-file."); 743 | } 744 | // write the data to file 745 | for (std::size_t i = 0; i < x.size(); ++i) 746 | { 747 | tmp << x[i] << " " << y[i] << std::endl; 748 | } 749 | // Cleanup 750 | tmp.flush(); 751 | tmp.close(); 752 | // Plot 753 | plotfile_xy(name, 1, 2, title); 754 | 755 | return *this; 756 | } 757 | 758 | /// Plot x,y pairs with dy errorbars 759 | template 760 | Gnuplot& Gnuplot::plot_xy_err(const X &x, 761 | const Y &y, 762 | const E &dy, 763 | const std::string &title) 764 | { 765 | if (x.empty() || y.empty() || dy.empty()) 766 | { 767 | throw GnuplotException("std::vectors too small"); 768 | } 769 | 770 | if (x.size() != y.size() || y.size() != dy.size()) 771 | { 772 | throw GnuplotException("Length of the std::vectors differs"); 773 | } 774 | std::ofstream tmp; 775 | const std::string name = create_tmpfile(tmp); 776 | if (name.empty()) 777 | { 778 | throw GnuplotException("Unable to create tmp-file."); 779 | } 780 | // write the data to file 781 | for (std::size_t i = 0; i < x.size(); ++i) 782 | { 783 | tmp << x[i] << " " << y[i] << " " << dy[i] << std::endl; 784 | } 785 | // Cleanup 786 | tmp.flush(); 787 | tmp.close(); 788 | // Do the actual plot 789 | plotfile_xy_err(name, 1, 2, 3, title); 790 | 791 | return *this; 792 | } 793 | 794 | /// Plots a 3d graph from a list of doubles: x y z 795 | template 796 | Gnuplot& Gnuplot::plot_xyz(const X &x, 797 | const Y &y, 798 | const Z &z, 799 | const std::string &title) 800 | { 801 | if (x.empty() || y.empty() || z.empty()) 802 | { 803 | throw GnuplotException("std::vectors too small"); 804 | } 805 | if (x.size() != y.size() || x.size() != z.size()) 806 | { 807 | throw GnuplotException("Length of the std::vectors differs"); 808 | } 809 | std::ofstream tmp; 810 | const std::string name = create_tmpfile(tmp); 811 | if (name.empty()) 812 | { 813 | throw GnuplotException("Unable to create tmp-file."); 814 | } 815 | // write the data to file 816 | for (std::size_t i = 0; i < x.size(); ++i) 817 | { 818 | tmp << x[i] << " " << y[i] << " " << z[i] << std::endl; 819 | } 820 | // cleanup 821 | tmp.flush(); 822 | tmp.close(); 823 | // plot file 824 | plotfile_xyz(name, 1, 2, 3, title); 825 | 826 | return *this; 827 | } 828 | 829 | // define static member function: set Gnuplot path manual 830 | // for windows: path with slash '/' not backslash '\' 831 | // 832 | bool Gnuplot::set_GNUPlotPath(const std::string &path) 833 | { 834 | const std::string tmp = path + "/" + Gnuplot::m_sGNUPlotFileName; 835 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 836 | if ( Gnuplot::file_exists(tmp, 0) ) // check existence 837 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 838 | if ( Gnuplot::file_exists(tmp, 1) ) // check existence and execution permission 839 | #endif 840 | { 841 | Gnuplot::m_sGNUPlotPath = path; 842 | return true; 843 | } 844 | Gnuplot::m_sGNUPlotPath.clear(); 845 | return false; 846 | } 847 | 848 | //------------------------------------------------------------------------------ 849 | // 850 | // define static member function: set default terminal, used by showonscreen 851 | // defaults: Windows - win, Linux - x11, Mac - aqua 852 | // 853 | void Gnuplot::set_terminal_std(const std::string &type) 854 | { 855 | #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 856 | if (type.find("x11") != std::string::npos && getenv("DISPLAY") == nullptr) 857 | { 858 | throw GnuplotException("Can't find DISPLAY variable"); 859 | } 860 | #endif 861 | Gnuplot::terminal_std = type; 862 | } 863 | 864 | 865 | //------------------------------------------------------------------------------ 866 | // 867 | // A string tokenizer taken from http://www.sunsite.ualberta.ca/Documentation/ 868 | // /Gnu/libstdc++-2.90.8/html/21_strings/stringtok_std_h.txt 869 | // 870 | template 871 | void stringtok (Container &container, 872 | std::string const &in, 873 | const char * const delimiters = " \t\n") 874 | { 875 | const std::string::size_type len = in.length(); 876 | std::string::size_type i = 0; 877 | 878 | while ( i < len ) 879 | { 880 | // eat leading whitespace 881 | i = in.find_first_not_of (delimiters, i); 882 | 883 | if (i == std::string::npos) 884 | { 885 | return; // nothing left but white space 886 | } 887 | 888 | // find the end of the token 889 | const std::string::size_type j = in.find_first_of (delimiters, i); 890 | 891 | // push token 892 | if (j == std::string::npos) 893 | { 894 | container.push_back (in.substr(i)); 895 | return; 896 | } 897 | container.push_back (in.substr(i, j - i)); 898 | 899 | // set up for next loop 900 | i = j + 1; 901 | } 902 | 903 | return; 904 | } 905 | 906 | 907 | //------------------------------------------------------------------------------ 908 | // 909 | // Destructor: needed to delete temporary files 910 | // 911 | Gnuplot::~Gnuplot(void) 912 | { 913 | // remove_tmpfiles(); 914 | 915 | // A stream opened by popen() should be closed by pclose() 916 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 917 | if (_pclose(gnucmd) == -1) 918 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 919 | if (pclose(gnucmd) == -1) 920 | #endif 921 | { std::cerr << "Gnuplot::~Gnuplot: Problem closing communication to gnuplot" << std::endl; } 922 | } 923 | 924 | 925 | //------------------------------------------------------------------------------ 926 | // 927 | // Resets a gnuplot session (next plot will erase previous ones) 928 | // 929 | Gnuplot& Gnuplot::reset_plot(void) 930 | { 931 | // remove_tmpfiles(); 932 | 933 | nplots = 0; 934 | 935 | return *this; 936 | } 937 | 938 | 939 | //------------------------------------------------------------------------------ 940 | // 941 | // resets a gnuplot session and sets all variables to default 942 | // 943 | Gnuplot& Gnuplot::reset_all(void) 944 | { 945 | // remove_tmpfiles(); 946 | 947 | nplots = 0; 948 | (void)cmd("reset"); 949 | (void)cmd("clear"); 950 | pstyle = "points"; 951 | smooth.clear(); 952 | showonscreen(); 953 | 954 | return *this; 955 | } 956 | 957 | 958 | //------------------------------------------------------------------------------ 959 | // 960 | // Change the plotting style of a gnuplot session 961 | // 962 | Gnuplot& Gnuplot::set_style(const std::string &stylestr) 963 | { 964 | if( (pstyle != stylestr) && !stylestr.empty() ) 965 | { 966 | pstyle = stylestr; 967 | } 968 | return *this; 969 | } 970 | 971 | 972 | //------------------------------------------------------------------------------ 973 | // 974 | // smooth: interpolation and approximation of data 975 | // 976 | Gnuplot& Gnuplot::set_smooth(const std::string &stylestr) 977 | { 978 | if (stylestr.find("unique") == std::string::npos && 979 | stylestr.find("frequency") == std::string::npos && 980 | stylestr.find("csplines") == std::string::npos && 981 | stylestr.find("bezier") == std::string::npos ) 982 | { 983 | smooth.clear(); 984 | } 985 | else 986 | { 987 | smooth = stylestr; 988 | } 989 | 990 | return *this; 991 | } 992 | 993 | 994 | //------------------------------------------------------------------------------ 995 | // 996 | // sets terminal type to windows / x11 997 | // 998 | Gnuplot& Gnuplot::showonscreen(void) 999 | { 1000 | (void)cmd("set output"); 1001 | return cmd("set terminal " + Gnuplot::terminal_std); 1002 | } 1003 | 1004 | //------------------------------------------------------------------------------ 1005 | // 1006 | // saves a gnuplot session to a postscript file 1007 | // 1008 | Gnuplot& Gnuplot::savetofigure(const std::string &filename, 1009 | const std::string &terminal) 1010 | { 1011 | std::ostringstream cmdstr; 1012 | cmdstr << "set terminal " << terminal; 1013 | (void)cmd(cmdstr.str() ); 1014 | 1015 | cmdstr.str(""); // Clear cmdstr 1016 | cmdstr << "set output \"" << filename << "\""; 1017 | return cmd(cmdstr.str()); 1018 | } 1019 | 1020 | //------------------------------------------------------------------------------ 1021 | // 1022 | // Switches legend on 1023 | // 1024 | Gnuplot& Gnuplot::set_legend(const std::string &position) 1025 | { 1026 | std::ostringstream cmdstr; 1027 | cmdstr << "set key " << position; 1028 | 1029 | return cmd(cmdstr.str()); 1030 | } 1031 | 1032 | //------------------------------------------------------------------------------ 1033 | // 1034 | // turns on log scaling for the x axis 1035 | // 1036 | Gnuplot& Gnuplot::set_xlogscale(const double base) 1037 | { 1038 | std::ostringstream cmdstr; 1039 | 1040 | cmdstr << "set logscale x " << base; 1041 | return cmd(cmdstr.str()); 1042 | } 1043 | 1044 | //------------------------------------------------------------------------------ 1045 | // 1046 | // turns on log scaling for the y axis 1047 | // 1048 | Gnuplot& Gnuplot::set_ylogscale(const double base) 1049 | { 1050 | std::ostringstream cmdstr; 1051 | 1052 | cmdstr << "set logscale y " << base; 1053 | return cmd(cmdstr.str()); 1054 | } 1055 | 1056 | //------------------------------------------------------------------------------ 1057 | // 1058 | // turns on log scaling for the z axis 1059 | // 1060 | Gnuplot& Gnuplot::set_zlogscale(const double base) 1061 | { 1062 | std::ostringstream cmdstr; 1063 | 1064 | cmdstr << "set logscale z " << base; 1065 | return cmd(cmdstr.str()); 1066 | } 1067 | 1068 | //------------------------------------------------------------------------------ 1069 | // 1070 | // scales the size of the points used in plots 1071 | // 1072 | Gnuplot& Gnuplot::set_pointsize(const double pointsize) 1073 | { 1074 | std::ostringstream cmdstr; 1075 | 1076 | cmdstr << "set pointsize " << pointsize; 1077 | return cmd(cmdstr.str()); 1078 | } 1079 | 1080 | //------------------------------------------------------------------------------ 1081 | // 1082 | // set isoline density (grid) for plotting functions as surfaces 1083 | // 1084 | Gnuplot& Gnuplot::set_samples(const int samples) 1085 | { 1086 | std::ostringstream cmdstr; 1087 | cmdstr << "set samples " << samples; 1088 | return cmd(cmdstr.str()); 1089 | } 1090 | 1091 | 1092 | //------------------------------------------------------------------------------ 1093 | // 1094 | // set isoline density (grid) for plotting functions as surfaces 1095 | // 1096 | Gnuplot& Gnuplot::set_isosamples(const int isolines) 1097 | { 1098 | std::ostringstream cmdstr; 1099 | cmdstr << "set isosamples " << isolines; 1100 | return cmd(cmdstr.str()); 1101 | } 1102 | 1103 | 1104 | //------------------------------------------------------------------------------ 1105 | // 1106 | // enables contour drawing for surfaces set contour {base | surface | both} 1107 | // 1108 | 1109 | Gnuplot& Gnuplot::set_contour(const std::string &position) 1110 | { 1111 | if (position.find("base") == std::string::npos && 1112 | position.find("surface") == std::string::npos && 1113 | position.find("both") == std::string::npos ) 1114 | { 1115 | return cmd("set contour base"); 1116 | } 1117 | 1118 | return cmd("set contour " + position); 1119 | } 1120 | 1121 | //------------------------------------------------------------------------------ 1122 | // 1123 | // set labels 1124 | // 1125 | // set the xlabel 1126 | Gnuplot& Gnuplot::set_xlabel(const std::string &label) 1127 | { 1128 | std::ostringstream cmdstr; 1129 | 1130 | cmdstr << "set xlabel \"" << label << "\""; 1131 | return cmd(cmdstr.str()); 1132 | } 1133 | 1134 | //------------------------------------------------------------------------------ 1135 | // set the ylabel 1136 | // 1137 | Gnuplot& Gnuplot::set_ylabel(const std::string &label) 1138 | { 1139 | std::ostringstream cmdstr; 1140 | 1141 | cmdstr << "set ylabel \"" << label << "\""; 1142 | return cmd(cmdstr.str()); 1143 | } 1144 | 1145 | //------------------------------------------------------------------------------ 1146 | // set the zlabel 1147 | // 1148 | Gnuplot& Gnuplot::set_zlabel(const std::string &label) 1149 | { 1150 | std::ostringstream cmdstr; 1151 | 1152 | cmdstr << "set zlabel \"" << label << "\""; 1153 | return cmd(cmdstr.str()); 1154 | } 1155 | 1156 | //------------------------------------------------------------------------------ 1157 | // 1158 | // set range 1159 | // 1160 | // set the xrange 1161 | Gnuplot& Gnuplot::set_xrange(const double iFrom, 1162 | const double iTo) 1163 | { 1164 | std::ostringstream cmdstr; 1165 | 1166 | cmdstr << "set xrange[" << iFrom << ":" << iTo << "]"; 1167 | return cmd(cmdstr.str()); 1168 | } 1169 | 1170 | //------------------------------------------------------------------------------ 1171 | // set the yrange 1172 | // 1173 | Gnuplot& Gnuplot::set_yrange(const double iFrom, 1174 | const double iTo) 1175 | { 1176 | std::ostringstream cmdstr; 1177 | 1178 | cmdstr << "set yrange[" << iFrom << ":" << iTo << "]"; 1179 | return cmd(cmdstr.str()); 1180 | } 1181 | 1182 | //------------------------------------------------------------------------------ 1183 | // set the zrange 1184 | // 1185 | Gnuplot& Gnuplot::set_zrange(const double iFrom, 1186 | const double iTo) 1187 | { 1188 | std::ostringstream cmdstr; 1189 | 1190 | cmdstr << "set zrange[" << iFrom << ":" << iTo << "]"; 1191 | return cmd(cmdstr.str()); 1192 | } 1193 | 1194 | //------------------------------------------------------------------------------ 1195 | // 1196 | // set the palette range 1197 | // 1198 | Gnuplot& Gnuplot::set_cbrange(const double iFrom, 1199 | const double iTo) 1200 | { 1201 | std::ostringstream cmdstr; 1202 | 1203 | cmdstr << "set cbrange[" << iFrom << ":" << iTo << "]"; 1204 | return cmd(cmdstr.str()); 1205 | } 1206 | 1207 | //------------------------------------------------------------------------------ 1208 | // 1209 | // Plots a linear equation y=ax+b (where you supply the 1210 | // slope a and intercept b) 1211 | // 1212 | Gnuplot& Gnuplot::plot_slope(const double a, 1213 | const double b, 1214 | const std::string &title) 1215 | { 1216 | std::ostringstream cmdstr; 1217 | // 1218 | // command to be sent to gnuplot 1219 | // 1220 | if (nplots > 0 && two_dim == true) 1221 | { 1222 | cmdstr << "replot "; 1223 | } 1224 | else 1225 | { 1226 | cmdstr << "plot "; 1227 | } 1228 | 1229 | cmdstr << a << " * x + " << b << " title \""; 1230 | 1231 | if (title.empty()) 1232 | { 1233 | cmdstr << "f(x) = " << a << " * x + " << b; 1234 | } 1235 | else 1236 | { 1237 | cmdstr << title; 1238 | } 1239 | 1240 | cmdstr << "\" with " << pstyle; 1241 | 1242 | // 1243 | // Do the actual plot 1244 | // 1245 | return cmd(cmdstr.str()); 1246 | } 1247 | 1248 | //------------------------------------------------------------------------------ 1249 | // 1250 | // Plot an equation supplied as a std::string y=f(x) (only f(x) expected) 1251 | // 1252 | Gnuplot& Gnuplot::plot_equation(const std::string &equation, 1253 | const std::string &title) 1254 | { 1255 | std::ostringstream cmdstr; 1256 | // 1257 | // command to be sent to gnuplot 1258 | // 1259 | if (nplots > 0 && two_dim == true) 1260 | { 1261 | cmdstr << "replot "; 1262 | } 1263 | else 1264 | { 1265 | cmdstr << "plot "; 1266 | } 1267 | 1268 | cmdstr << equation; 1269 | 1270 | if (title.empty()) 1271 | { 1272 | cmdstr << " notitle"; 1273 | } 1274 | else 1275 | { 1276 | cmdstr << " title \"" << title << "\""; 1277 | } 1278 | 1279 | cmdstr << " with " << pstyle; 1280 | 1281 | // 1282 | // Do the actual plot 1283 | // 1284 | return cmd(cmdstr.str()); 1285 | } 1286 | 1287 | //------------------------------------------------------------------------------ 1288 | // 1289 | // plot an equation supplied as a std::string y=(x) 1290 | // 1291 | Gnuplot& Gnuplot::plot_equation3d(const std::string &equation, 1292 | const std::string &title) 1293 | { 1294 | std::ostringstream cmdstr; 1295 | // 1296 | // command to be sent to gnuplot 1297 | // 1298 | if (nplots > 0 && two_dim == false) 1299 | { 1300 | cmdstr << "replot "; 1301 | } 1302 | else 1303 | { 1304 | cmdstr << "splot "; 1305 | } 1306 | 1307 | cmdstr << equation << " title \""; 1308 | 1309 | if (title.empty()) 1310 | { 1311 | cmdstr << "f(x,y) = " << equation; 1312 | } 1313 | else 1314 | { 1315 | cmdstr << title; 1316 | } 1317 | 1318 | cmdstr << "\" with " << pstyle; 1319 | 1320 | // 1321 | // Do the actual plot 1322 | // 1323 | return cmd(cmdstr.str()); 1324 | } 1325 | 1326 | 1327 | //------------------------------------------------------------------------------ 1328 | // 1329 | // Plots a 2d graph from a list of doubles (x) saved in a file 1330 | // 1331 | Gnuplot& Gnuplot::plotfile_x(const std::string &filename, 1332 | const unsigned int column, 1333 | const std::string &title) 1334 | { 1335 | // 1336 | // check if file exists 1337 | // 1338 | file_available(filename); 1339 | 1340 | std::ostringstream cmdstr; 1341 | // 1342 | // command to be sent to gnuplot 1343 | // 1344 | if (nplots > 0 && two_dim == true) 1345 | { 1346 | cmdstr << "replot "; 1347 | } 1348 | else 1349 | { 1350 | cmdstr << "plot "; 1351 | } 1352 | 1353 | cmdstr << "\"" << filename << "\" using " << column; 1354 | 1355 | if (title.empty()) 1356 | { 1357 | cmdstr << " notitle "; 1358 | } 1359 | else 1360 | { 1361 | cmdstr << " title \"" << title << "\" "; 1362 | } 1363 | 1364 | if(smooth.empty()) 1365 | { 1366 | cmdstr << "with " << pstyle; 1367 | } 1368 | else 1369 | { 1370 | cmdstr << "smooth " << smooth; 1371 | } 1372 | 1373 | // 1374 | // Do the actual plot 1375 | // 1376 | return cmd(cmdstr.str()); //nplots++; two_dim = true; already in cmd(); 1377 | } 1378 | 1379 | 1380 | 1381 | //------------------------------------------------------------------------------ 1382 | // 1383 | // Plots a 2d graph from a list of doubles (x y) saved in a file 1384 | // 1385 | Gnuplot& Gnuplot::plotfile_xy(const std::string &filename, 1386 | const unsigned int column_x, 1387 | const unsigned int column_y, 1388 | const std::string &title) 1389 | { 1390 | // 1391 | // check if file exists 1392 | // 1393 | file_available(filename); 1394 | 1395 | std::ostringstream cmdstr; 1396 | // 1397 | // command to be sent to gnuplot 1398 | // 1399 | if (nplots > 0 && two_dim == true) 1400 | { 1401 | cmdstr << "replot "; 1402 | } 1403 | else 1404 | { 1405 | cmdstr << "plot "; 1406 | } 1407 | 1408 | cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y; 1409 | 1410 | if (title.empty()) 1411 | { 1412 | cmdstr << " notitle "; 1413 | } 1414 | else 1415 | { 1416 | cmdstr << " title \"" << title << "\" "; 1417 | } 1418 | 1419 | if(smooth.empty()) 1420 | { 1421 | cmdstr << "with " << pstyle; 1422 | } 1423 | else 1424 | { 1425 | cmdstr << "smooth " << smooth; 1426 | } 1427 | 1428 | // 1429 | // Do the actual plot 1430 | // 1431 | return cmd(cmdstr.str()); 1432 | } 1433 | 1434 | 1435 | //------------------------------------------------------------------------------ 1436 | // 1437 | // Plots a 2d graph with errorbars from a list of doubles (x y dy) in a file 1438 | // 1439 | Gnuplot& Gnuplot::plotfile_xy_err(const std::string &filename, 1440 | const unsigned int column_x, 1441 | const unsigned int column_y, 1442 | const unsigned int column_dy, 1443 | const std::string &title) 1444 | { 1445 | // 1446 | // check if file exists 1447 | // 1448 | file_available(filename); 1449 | 1450 | std::ostringstream cmdstr; 1451 | // 1452 | // command to be sent to gnuplot 1453 | // 1454 | if (nplots > 0 && two_dim == true) 1455 | { 1456 | cmdstr << "replot "; 1457 | } 1458 | else 1459 | { 1460 | cmdstr << "plot "; 1461 | } 1462 | 1463 | cmdstr << "\"" << filename << "\" using " 1464 | << column_x << ":" << column_y << ":" << column_dy 1465 | << " with errorbars "; 1466 | 1467 | if (title.empty()) 1468 | { 1469 | cmdstr << " notitle "; 1470 | } 1471 | else 1472 | { 1473 | cmdstr << " title \"" << title << "\" "; 1474 | } 1475 | 1476 | // 1477 | // Do the actual plot 1478 | // 1479 | return cmd(cmdstr.str()); 1480 | } 1481 | 1482 | 1483 | //------------------------------------------------------------------------------ 1484 | // 1485 | // Plots a 3d graph from a list of doubles (x y z) saved in a file 1486 | // 1487 | Gnuplot& Gnuplot::plotfile_xyz(const std::string &filename, 1488 | const unsigned int column_x, 1489 | const unsigned int column_y, 1490 | const unsigned int column_z, 1491 | const std::string &title) 1492 | { 1493 | // 1494 | // check if file exists 1495 | // 1496 | file_available(filename); 1497 | 1498 | std::ostringstream cmdstr; 1499 | // 1500 | // command to be sent to gnuplot 1501 | // 1502 | if (nplots > 0 && two_dim == false) 1503 | { 1504 | cmdstr << "replot "; 1505 | } 1506 | else 1507 | { 1508 | cmdstr << "splot "; 1509 | } 1510 | 1511 | cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y 1512 | << ":" << column_z; 1513 | 1514 | if (title.empty()) 1515 | { 1516 | cmdstr << " notitle with " << pstyle; 1517 | } 1518 | else 1519 | { 1520 | cmdstr << " title \"" << title << "\" with " << pstyle; 1521 | } 1522 | 1523 | // 1524 | // Do the actual plot 1525 | // 1526 | return cmd(cmdstr.str()); 1527 | } 1528 | 1529 | 1530 | 1531 | //------------------------------------------------------------------------------ 1532 | // 1533 | /// * note that this function is not valid for versions of GNUPlot below 4.2 1534 | // 1535 | Gnuplot& Gnuplot::plot_image(const unsigned char * ucPicBuf, 1536 | const unsigned int iWidth, 1537 | const unsigned int iHeight, 1538 | const std::string &title) 1539 | { 1540 | std::ofstream tmp; 1541 | std::string name = create_tmpfile(tmp); 1542 | if (name.empty()) 1543 | { 1544 | return *this; 1545 | } 1546 | 1547 | // 1548 | // write the data to file 1549 | // 1550 | int iIndex = 0; 1551 | for(unsigned int iRow = 0; iRow < iHeight; ++iRow) 1552 | { 1553 | for(unsigned int iColumn = 0; iColumn < iWidth; ++iColumn) 1554 | { 1555 | tmp << iColumn << " " << iRow << " " 1556 | << static_cast(ucPicBuf[iIndex++]) << std::endl; 1557 | } 1558 | } 1559 | 1560 | tmp.flush(); 1561 | tmp.close(); 1562 | 1563 | std::ostringstream cmdstr; 1564 | // 1565 | // command to be sent to gnuplot 1566 | // 1567 | if (nplots > 0 && two_dim == true) 1568 | { 1569 | cmdstr << "replot "; 1570 | } 1571 | else 1572 | { 1573 | cmdstr << "plot "; 1574 | } 1575 | 1576 | if (title.empty()) 1577 | { 1578 | cmdstr << "\"" << name << "\" with image"; 1579 | } 1580 | else 1581 | { 1582 | cmdstr << "\"" << name << "\" title \"" << title << "\" with image"; 1583 | } 1584 | 1585 | // 1586 | // Do the actual plot 1587 | // 1588 | return cmd(cmdstr.str()); 1589 | } 1590 | 1591 | 1592 | 1593 | //------------------------------------------------------------------------------ 1594 | // 1595 | // Sends a command to an active gnuplot session 1596 | // 1597 | Gnuplot& Gnuplot::cmd(const std::string &cmdstr) 1598 | { 1599 | if( !(valid) ) 1600 | { 1601 | return *this; 1602 | } 1603 | 1604 | 1605 | // int fputs ( const char * str, FILE * stream ); 1606 | // writes the string str to the stream. 1607 | // The function begins copying from the address specified (str) until it 1608 | // reaches the terminating null character ('\0'). This final 1609 | // null-character is not copied to the stream. 1610 | fputs( (cmdstr + "\n").c_str(), gnucmd ); 1611 | 1612 | // int fflush ( FILE * stream ); 1613 | // If the given stream was open for writing and the last i/o operation was 1614 | // an output operation, any unwritten data in the output buffer is written 1615 | // to the file. If the argument is a null pointer, all open files are 1616 | // flushed. The stream remains open after this call. 1617 | fflush(gnucmd); 1618 | 1619 | if( cmdstr.find("splot") != std::string::npos ) 1620 | { 1621 | two_dim = false; 1622 | ++nplots; 1623 | return *this; 1624 | } 1625 | else if( cmdstr.find("plot") != std::string::npos ) 1626 | { 1627 | two_dim = true; 1628 | ++nplots; 1629 | return *this; 1630 | } 1631 | else 1632 | { 1633 | return *this; 1634 | } 1635 | } 1636 | 1637 | //------------------------------------------------------------------------------ 1638 | // 1639 | // Opens up a gnuplot session, ready to receive commands 1640 | // 1641 | void Gnuplot::init(void) 1642 | { 1643 | // char * getenv ( const char * name ); get value of environment variable 1644 | // Retrieves a C string containing the value of the environment variable 1645 | // whose name is specified as argument. If the requested variable is not 1646 | // part of the environment list, the function returns a NULL pointer. 1647 | #if ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__) 1648 | if (getenv("DISPLAY") == nullptr) 1649 | { 1650 | valid = false; 1651 | throw GnuplotException("Can't find DISPLAY variable"); 1652 | } 1653 | #endif 1654 | 1655 | // if gnuplot not available 1656 | if (!Gnuplot::get_program_path()) 1657 | { 1658 | valid = false; 1659 | throw GnuplotException("Can't find gnuplot"); 1660 | } 1661 | 1662 | // open pipe 1663 | std::string tmp = Gnuplot::m_sGNUPlotPath + "/" + 1664 | Gnuplot::m_sGNUPlotFileName; 1665 | 1666 | // FILE *popen(const char *command, const char *mode); 1667 | // The popen() function shall execute the command specified by the string 1668 | // command, create a pipe between the calling program and the executed 1669 | // command, and return a pointer to a stream that can be used to either read 1670 | // from or write to the pipe. 1671 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1672 | gnucmd = _popen(tmp.c_str(), "w"); 1673 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1674 | gnucmd = popen(tmp.c_str(), "w"); 1675 | #endif 1676 | 1677 | // popen() shall return a pointer to an open stream that can be used to read 1678 | // or write to the pipe. Otherwise, it shall return a null pointer and may 1679 | // set errno to indicate the error. 1680 | if (!gnucmd) 1681 | { 1682 | valid = false; 1683 | throw GnuplotException("Couldn't open connection to gnuplot"); 1684 | } 1685 | 1686 | nplots = 0; 1687 | valid = true; 1688 | smooth.clear(); 1689 | 1690 | //set terminal type 1691 | showonscreen(); 1692 | 1693 | return; 1694 | } 1695 | 1696 | 1697 | //------------------------------------------------------------------------------ 1698 | // 1699 | // Find out if a command lives in m_sGNUPlotPath or in PATH 1700 | // 1701 | bool Gnuplot::get_program_path(void) 1702 | { 1703 | // 1704 | // first look in m_sGNUPlotPath for Gnuplot 1705 | // 1706 | std::string tmp = Gnuplot::m_sGNUPlotPath + "/" + 1707 | Gnuplot::m_sGNUPlotFileName; 1708 | 1709 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1710 | if ( Gnuplot::file_exists(tmp, 0) ) // check existence 1711 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1712 | if ( Gnuplot::file_exists(tmp, 1) ) // check existence and execution permission 1713 | #endif 1714 | { 1715 | return true; 1716 | } 1717 | 1718 | 1719 | // 1720 | // second look in PATH for Gnuplot 1721 | // Retrieves a C string containing the value of environment variable PATH 1722 | const char * const path = getenv("PATH"); 1723 | 1724 | if (path == nullptr) 1725 | { 1726 | throw GnuplotException("Path is not set"); 1727 | } 1728 | std::list ls; 1729 | 1730 | //split path (one long string) into list ls of strings 1731 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1732 | stringtok(ls, path, ";"); 1733 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1734 | stringtok(ls, path, ":"); 1735 | #endif 1736 | 1737 | // scan list for Gnuplot program files 1738 | for (std::list::const_iterator i = ls.cbegin(); 1739 | i != ls.cend(); ++i) 1740 | { 1741 | tmp = (*i) + "/" + Gnuplot::m_sGNUPlotFileName; 1742 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1743 | if ( Gnuplot::file_exists(tmp, 0) ) // check existence 1744 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1745 | if ( Gnuplot::file_exists(tmp, 1) ) // check existence and execution permission 1746 | #endif 1747 | { 1748 | Gnuplot::m_sGNUPlotPath = *i; // set m_sGNUPlotPath 1749 | return true; 1750 | } 1751 | } 1752 | 1753 | tmp = "Can't find gnuplot neither in PATH nor in \"" + 1754 | Gnuplot::m_sGNUPlotPath + "\""; 1755 | throw GnuplotException(tmp); 1756 | } 1757 | 1758 | //------------------------------------------------------------------------------ 1759 | // 1760 | // check if file exists 1761 | // 1762 | bool Gnuplot::file_exists(const std::string &filename, int mode) 1763 | { 1764 | if ( mode < 0 || mode > 7) 1765 | { 1766 | throw std::runtime_error("In function \"Gnuplot::file_exists\": mode\ 1767 | has to be an integer between 0 and 7"); 1768 | } 1769 | 1770 | // int _access(const char *path, int mode); 1771 | // returns 0 if the file has the given mode, 1772 | // it returns -1 if the named file does not exist or is not accessible in 1773 | // the given mode 1774 | // mode = 0 (F_OK) (default): checks file for existence only 1775 | // mode = 1 (X_OK): execution permission 1776 | // mode = 2 (W_OK): write permission 1777 | // mode = 4 (R_OK): read permission 1778 | // mode = 6 : read and write permission 1779 | // mode = 7 : read, write and execution permission 1780 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1781 | return (_access(filename.c_str(), mode) == 0); 1782 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1783 | return (access(filename.c_str(), mode) == 0); 1784 | #endif 1785 | } 1786 | 1787 | bool Gnuplot::file_available(const std::string &filename) 1788 | { 1789 | std::ostringstream except; 1790 | if( Gnuplot::file_exists(filename, 0) ) // check existence 1791 | { 1792 | if( !(Gnuplot::file_exists(filename, 4)) ) // check read permission 1793 | { 1794 | except << "No read permission for File \"" << filename << "\""; 1795 | throw GnuplotException( except.str() ); 1796 | } 1797 | return true; 1798 | } 1799 | except << "File \"" << filename << "\" does not exist"; 1800 | throw GnuplotException( except.str() ); 1801 | } 1802 | 1803 | 1804 | 1805 | //------------------------------------------------------------------------------ 1806 | // 1807 | // Opens a temporary file 1808 | // 1809 | std::string Gnuplot::create_tmpfile(std::ofstream &tmp) 1810 | { 1811 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1812 | char name[15] = {'g', 'n', 'u', 'p', 'l', 'o', 't', 'i', 'X', 'X', 'X', 'X', 'X', 'X', '\0'}; //tmp file in working directory 1813 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1814 | char name[20] = {'/', 't', 'm', 'p', '/', 'g', 'n', 'u', 'p', 'l', 'o', 't', 'i', 'X', 'X', 'X', 'X', 'X', 'X', '\0'}; // tmp file in /tmp 1815 | #endif 1816 | 1817 | // 1818 | // check if maximum number of temporary files reached 1819 | // 1820 | if (Gnuplot::tmpfile_num == GP_MAX_TMP_FILES - 1) 1821 | { 1822 | std::ostringstream except; 1823 | except << "Maximum number of temporary files reached (" 1824 | << GP_MAX_TMP_FILES << "): cannot open more files" << std::endl; 1825 | 1826 | throw GnuplotException( except.str() ); 1827 | } 1828 | 1829 | // int mkstemp(char *name); 1830 | // shall replace the contents of the string pointed to by "name" by a unique 1831 | // filename, and return a file descriptor for the file open for reading and 1832 | // writing. Otherwise, -1 shall be returned if no suitable file could be 1833 | // created. The string in template should look like a filename with six 1834 | // trailing 'X' s; mkstemp() replaces each 'X' with a character from the 1835 | // portable filename character set. The characters are chosen such that the 1836 | // resulting name does not duplicate the name of an existing file at the 1837 | // time of a call to mkstemp() 1838 | 1839 | 1840 | // 1841 | // open temporary files for output 1842 | // 1843 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) 1844 | if (_mktemp(name) == nullptr) 1845 | #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1846 | int tmpfd; 1847 | if ((tmpfd = mkstemp(name)) == -1) 1848 | #endif 1849 | { 1850 | std::ostringstream except; 1851 | except << "Cannot create temporary file \"" << name << "\""; 1852 | throw GnuplotException(except.str()); 1853 | } 1854 | #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) 1855 | (void)close(tmpfd); 1856 | #endif 1857 | 1858 | tmp.open(name); 1859 | if (tmp.bad()) 1860 | { 1861 | std::ostringstream except; 1862 | except << "Cannot create temporary file \"" << name << "\""; 1863 | throw GnuplotException(except.str()); 1864 | } 1865 | 1866 | // 1867 | // Save the temporary filename 1868 | // 1869 | tmpfile_list.push_back(name); 1870 | Gnuplot::tmpfile_num++; 1871 | 1872 | return name; 1873 | } 1874 | 1875 | void Gnuplot::remove_tmpfiles(void) 1876 | { 1877 | if ((tmpfile_list).size() > 0) 1878 | { 1879 | for (unsigned int i = 0U; i < tmpfile_list.size(); ++i) 1880 | { 1881 | 1882 | if( remove( tmpfile_list[i].c_str() ) != 0 ) 1883 | { 1884 | std::ostringstream except; 1885 | except << "Cannot remove temporary file \"" << tmpfile_list[i] << "\""; 1886 | throw GnuplotException(except.str()); 1887 | } 1888 | } 1889 | 1890 | Gnuplot::tmpfile_num -= static_cast(tmpfile_list.size()); 1891 | } 1892 | } 1893 | #endif // GNUPLOT_I_HPP 1894 | --------------------------------------------------------------------------------