diff --git a/.clang-format b/.clang-format new file mode 100755 index 00000000..27de441f --- /dev/null +++ b/.clang-format @@ -0,0 +1,115 @@ +--- +Language: Cpp +# BasedOnStyle: GNU +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: All +AlwaysBreakAfterReturnType: AllDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 140 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +AlignOperands: true +RawStringFormats: + - Language: TextProto + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... + diff --git a/.gitignore b/.gitignore index 1c4a1b0a..d389ccb0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ # Build /examples/build/* +.idea/ +build/ +cmake-build-debug/ # vim temp files *.sw* diff --git a/examples/animation.cpp b/examples/animation.cpp index d9794300..7cdc3b93 100644 --- a/examples/animation.cpp +++ b/examples/animation.cpp @@ -1,36 +1,39 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" +#include namespace plt = matplotlibcpp; -int main() +int +main() { - int n = 1000; - std::vector x, y, z; + int n = 1000; + std::vector x, y, z; - for(int i=0; i #include -#include "../matplotlibcpp.h" namespace plt = matplotlibcpp; -int main(int argc, char **argv) { - std::vector test_data; - for (int i = 0; i < 20; i++) { - test_data.push_back(i); - } - - plt::bar(test_data); - plt::show(); +int +main(int argc, char **argv) +{ + std::vector test_data; + for(int i = 0; i < 20; i++) + { + test_data.push_back(i); + } + plt::rcparams({ { "font.size", "55" } }); + plt::bar(test_data); + plt::show(); + plt::save("bar_size.png"); - return (0); + return (0); } diff --git a/examples/basic.cpp b/examples/basic.cpp index 2dc34c74..3f5e3074 100644 --- a/examples/basic.cpp +++ b/examples/basic.cpp @@ -1,44 +1,47 @@ #define _USE_MATH_DEFINES -#include -#include #include "../matplotlibcpp.h" +#include +#include namespace plt = matplotlibcpp; -int main() +int +main() { - // Prepare data. - int n = 5000; - std::vector x(n), y(n), z(n), w(n,2); - for(int i=0; i x(n), y(n), z(n), w(n, 2); + for(int i = 0; i < n; ++i) + { + x.at(i) = i * i; + y.at(i) = sin(2 * M_PI * i / 360.0); + z.at(i) = log(i); + } + + // Set the size of output image = 1200x780 pixels + plt::figure_size(1200, 780); + + // Plot line from given x and y data. Color is selected automatically. + plt::plot(x, y); + + // Plot a red dashed line from given x and y data. + plt::plot(x, w, "r--"); + + // Plot a line whose name will show up as "log(x)" in the legend. + plt::named_plot("log(x)", x, z); + + // Set x-axis to interval [0,1000000] + plt::xlim(0, 1000 * 1000); + + // Add graph title + plt::title("Sample figure"); + + // Enable legend. + plt::legend(); + + // save figure + const char *filename = "./basic.png"; + std::cout << "Saving result to " << filename << std::endl; + ; + plt::save(filename); } diff --git a/examples/colorbar.cpp b/examples/colorbar.cpp index f53e01da..3374ffc9 100644 --- a/examples/colorbar.cpp +++ b/examples/colorbar.cpp @@ -1,32 +1,35 @@ #define _USE_MATH_DEFINES +#include "../matplotlibcpp.h" #include #include -#include "../matplotlibcpp.h" using namespace std; namespace plt = matplotlibcpp; -int main() +int +main() { - // Prepare data - int ncols = 500, nrows = 300; - std::vector z(ncols * nrows); - for (int j=0; j z(ncols * nrows); + for(int j = 0; j < nrows; ++j) + { + for(int i = 0; i < ncols; ++i) + { + z.at(ncols * j + i) = std::sin(std::hypot(i - ncols / 2, j - nrows / 2)); } + } - const float* zptr = &(z[0]); - const int colors = 1; + const float *zptr = &(z[0]); + const int colors = 1; - plt::title("My matrix"); - PyObject* mat; - plt::imshow(zptr, nrows, ncols, colors, {}, &mat); - plt::colorbar(mat); + plt::title("My matrix"); + PyObject *mat; + plt::imshow(zptr, nrows, ncols, colors, {}, &mat); + plt::colorbar(mat); - // Show plots - plt::show(); - plt::close(); - Py_DECREF(mat); + // Show plots + plt::show(); + plt::close(); + Py_DECREF(mat); } diff --git a/examples/contour.cpp b/examples/contour.cpp index 9289d0a0..771e4133 100644 --- a/examples/contour.cpp +++ b/examples/contour.cpp @@ -4,21 +4,24 @@ namespace plt = matplotlibcpp; -int main() +int +main() { - std::vector> x, y, z; - for (double i = -5; i <= 5; i += 0.25) { - std::vector x_row, y_row, z_row; - for (double j = -5; j <= 5; j += 0.25) { - x_row.push_back(i); - y_row.push_back(j); - z_row.push_back(::std::sin(::std::hypot(i, j))); - } - x.push_back(x_row); - y.push_back(y_row); - z.push_back(z_row); + std::vector> x, y, z; + for(double i = -5; i <= 5; i += 0.25) + { + std::vector x_row, y_row, z_row; + for(double j = -5; j <= 5; j += 0.25) + { + x_row.push_back(i); + y_row.push_back(j); + z_row.push_back(::std::sin(::std::hypot(i, j))); } + x.push_back(x_row); + y.push_back(y_row); + z.push_back(z_row); + } - plt::contour(x, y, z); - plt::show(); + plt::contour(x, y, z); + plt::show(); } diff --git a/examples/fill.cpp b/examples/fill.cpp index 6059b475..884d2768 100644 --- a/examples/fill.cpp +++ b/examples/fill.cpp @@ -7,29 +7,32 @@ namespace plt = matplotlibcpp; // Example fill plot taken from: // https://matplotlib.org/gallery/misc/fill_spiral.html -int main() { - // Prepare data. - vector theta; - for (double d = 0; d < 8 * M_PI; d += 0.1) - theta.push_back(d); +int +main() +{ + // Prepare data. + vector theta; + for(double d = 0; d < 8 * M_PI; d += 0.1) theta.push_back(d); - const int a = 1; - const double b = 0.2; + const int a = 1; + const double b = 0.2; - for (double dt = 0; dt < 2 * M_PI; dt += M_PI/2.0) { - vector x1, y1, x2, y2; - for (double th : theta) { - x1.push_back( a*cos(th + dt) * exp(b*th) ); - y1.push_back( a*sin(th + dt) * exp(b*th) ); + for(double dt = 0; dt < 2 * M_PI; dt += M_PI / 2.0) + { + vector x1, y1, x2, y2; + for(double th : theta) + { + x1.push_back(a * cos(th + dt) * exp(b * th)); + y1.push_back(a * sin(th + dt) * exp(b * th)); - x2.push_back( a*cos(th + dt + M_PI/4.0) * exp(b*th) ); - y2.push_back( a*sin(th + dt + M_PI/4.0) * exp(b*th) ); - } + x2.push_back(a * cos(th + dt + M_PI / 4.0) * exp(b * th)); + y2.push_back(a * sin(th + dt + M_PI / 4.0) * exp(b * th)); + } - x1.insert(x1.end(), x2.rbegin(), x2.rend()); - y1.insert(y1.end(), y2.rbegin(), y2.rend()); + x1.insert(x1.end(), x2.rbegin(), x2.rend()); + y1.insert(y1.end(), y2.rbegin(), y2.rend()); - plt::fill(x1, y1, {}); - } - plt::show(); + plt::fill(x1, y1, {}); + } + plt::show(); } diff --git a/examples/fill_inbetween.cpp b/examples/fill_inbetween.cpp index 788d0086..2493e96a 100644 --- a/examples/fill_inbetween.cpp +++ b/examples/fill_inbetween.cpp @@ -6,11 +6,14 @@ using namespace std; namespace plt = matplotlibcpp; -int main() { +int +main() +{ // Prepare data. int n = 5000; std::vector x(n), y(n), z(n), w(n, 2); - for (int i = 0; i < n; ++i) { + for(int i = 0; i < n; ++i) + { x.at(i) = i * i; y.at(i) = sin(2 * M_PI * i / 360.0); z.at(i) = log(i); diff --git a/examples/imshow.cpp b/examples/imshow.cpp index b11661e4..5b81eb1e 100644 --- a/examples/imshow.cpp +++ b/examples/imshow.cpp @@ -1,29 +1,32 @@ #define _USE_MATH_DEFINES +#include "../matplotlibcpp.h" #include #include -#include "../matplotlibcpp.h" using namespace std; namespace plt = matplotlibcpp; -int main() +int +main() { - // Prepare data - int ncols = 500, nrows = 300; - std::vector z(ncols * nrows); - for (int j=0; j z(ncols * nrows); + for(int j = 0; j < nrows; ++j) + { + for(int i = 0; i < ncols; ++i) + { + z.at(ncols * j + i) = std::sin(std::hypot(i - ncols / 2, j - nrows / 2)); } + } - const float* zptr = &(z[0]); - const int colors = 1; + const float *zptr = &(z[0]); + const int colors = 1; - plt::title("My matrix"); - plt::imshow(zptr, nrows, ncols, colors); + plt::title("My matrix"); + plt::imshow(zptr, nrows, ncols, colors); - // Show plots - plt::save("imshow.png"); - std::cout << "Result saved to 'imshow.png'.\n"; + // Show plots + plt::save("imshow.png"); + std::cout << "Result saved to 'imshow.png'.\n"; } diff --git a/examples/lines3d.cpp b/examples/lines3d.cpp index fd4610d2..25acb355 100644 --- a/examples/lines3d.cpp +++ b/examples/lines3d.cpp @@ -4,27 +4,30 @@ namespace plt = matplotlibcpp; -int main() +int +main() { - std::vector x, y, z; - double theta, r; - double z_inc = 4.0/99.0; double theta_inc = (8.0 * M_PI)/99.0; - - for (double i = 0; i < 100; i += 1) { - theta = -4.0 * M_PI + theta_inc*i; - z.push_back(-2.0 + z_inc*i); - r = z[i]*z[i] + 1; - x.push_back(r * sin(theta)); - y.push_back(r * cos(theta)); - } + std::vector x, y, z; + double theta, r; + double z_inc = 4.0 / 99.0; + double theta_inc = (8.0 * M_PI) / 99.0; - std::map keywords; - keywords.insert(std::pair("label", "parametric curve") ); + for(double i = 0; i < 100; i += 1) + { + theta = -4.0 * M_PI + theta_inc * i; + z.push_back(-2.0 + z_inc * i); + r = z[i] * z[i] + 1; + x.push_back(r * sin(theta)); + y.push_back(r * cos(theta)); + } - plt::plot3(x, y, z, keywords); - plt::xlabel("x label"); - plt::ylabel("y label"); - plt::set_zlabel("z label"); // set_zlabel rather than just zlabel, in accordance with the Axes3D method - plt::legend(); - plt::show(); + std::map keywords; + keywords.insert(std::pair("label", "parametric curve")); + + plt::plot3(x, y, z, keywords); + plt::xlabel("x label"); + plt::ylabel("y label"); + plt::set_zlabel("z label"); // set_zlabel rather than just zlabel, in accordance with the Axes3D method + plt::legend(); + plt::show(); } diff --git a/examples/minimal.cpp b/examples/minimal.cpp index fbe1e1cd..2bfb73bd 100644 --- a/examples/minimal.cpp +++ b/examples/minimal.cpp @@ -2,7 +2,9 @@ namespace plt = matplotlibcpp; -int main() { - plt::plot({1,3,2,4}); - plt::show(); +int +main() +{ + plt::plot({ 1, 3, 2, 4 }); + plt::show(); } diff --git a/examples/modern.cpp b/examples/modern.cpp index 871ef2b0..534b1a7c 100644 --- a/examples/modern.cpp +++ b/examples/modern.cpp @@ -1,33 +1,57 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" +#include using namespace std; namespace plt = matplotlibcpp; -int main() +int +main() { - // plot(y) - the x-coordinates are implicitly set to [0,1,...,n) - //plt::plot({1,2,3,4}); - - // Prepare data for parametric plot. - int n = 5000; // number of data points - vector x(n),y(n); - for(int i=0; i x(n),y(n); + // for(int i=0; i x(n), y(n); + x[0] = 0; + x[1] = 20; + y[0] = 0; + y[1] = 20; + // plt::plot(x, y, "r-", x, [](double d) { return 12.5+abs(sin(d)); }, "k-"); + // plt::plot(x, y, "r", alpha); + // plt::xlim(0, 20); + // plt::ylim(0, 20); + // //plt::set_aspect(0.5); + //// plt::set_aspect_equal(); + // + // + // + // // show plots + // plt::show(); - // show plots - plt::show(); + plt::figure_size(1200, 500); + plt::title("Bias Distribution compared to HSPICE."); + // + "\nOP(" + std::to_string(op_[0]) + "V/" + std::to_string(op_[1]) + "°C)"); + plt::rcparams({ { "lines.markersize", "10" } }); + plt::plot(x, y, "ko-"); + plt::scatter(x, y, 1.0, { { "color", "r" }, { "label", "FinFET-SLS" } }); + y[1] = 40; + plt::scatter(x, y, 1.0, { { "color", "g" }, { "label", "Fin-SLS" } }); + // plt::xlim(-400.0f, 400.0f); + // plt::xlim(-400.0f, 400.0f); + // plt::ylim(-0.3, static_cast(op_[0]) + 0.3); + plt::legend(); + plt::show(); } diff --git a/examples/nonblock.cpp b/examples/nonblock.cpp index 327d96c7..06997a55 100644 --- a/examples/nonblock.cpp +++ b/examples/nonblock.cpp @@ -1,46 +1,47 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" +#include namespace plt = matplotlibcpp; - using namespace matplotlibcpp; using namespace std; -int main() +int +main() { - // Prepare data. - int n = 5000; - std::vector x(n), y(n), z(n), w(n,2); - for(int i=0; i x(n), y(n), z(n), w(n, 2); + for(int i = 0; i < n; ++i) + { + x.at(i) = i * i; + y.at(i) = sin(2 * M_PI * i / 360.0); + z.at(i) = log(i); + } + + // Plot line from given x and y data. Color is selected automatically. + plt::subplot(2, 2, 1); + plt::plot(x, y); + + // Plot a red dashed line from given x and y data. + plt::subplot(2, 2, 2); + plt::plot(x, w, "r--"); + + // Plot a line whose name will show up as "log(x)" in the legend. + plt::subplot(2, 2, 3); + plt::named_plot("log(x)", x, z); + + // Set x-axis to interval [0,1000000] + plt::xlim(0, 1000 * 1000); + + // Add graph title + plt::title("Sample figure"); + // Enable legend. + plt::legend(); + + plt::show(false); + + cout << "matplotlibcpp::show() is working in an non-blocking mode" << endl; + getchar(); } diff --git a/examples/quiver.cpp b/examples/quiver.cpp index ea3c3eca..56913c0b 100644 --- a/examples/quiver.cpp +++ b/examples/quiver.cpp @@ -2,19 +2,22 @@ namespace plt = matplotlibcpp; -int main() +int +main() { - // u and v are respectively the x and y components of the arrows we're plotting - std::vector x, y, u, v; - for (int i = -5; i <= 5; i++) { - for (int j = -5; j <= 5; j++) { - x.push_back(i); - u.push_back(-i); - y.push_back(j); - v.push_back(-j); - } + // u and v are respectively the x and y components of the arrows we're plotting + std::vector x, y, u, v; + for(int i = -5; i <= 5; i++) + { + for(int j = -5; j <= 5; j++) + { + x.push_back(i); + u.push_back(-i); + y.push_back(j); + v.push_back(-j); } + } - plt::quiver(x, y, u, v); - plt::show(); + plt::quiver(x, y, u, v); + plt::show(); } \ No newline at end of file diff --git a/examples/spy.cpp b/examples/spy.cpp index 6027a487..7968c91d 100644 --- a/examples/spy.cpp +++ b/examples/spy.cpp @@ -5,26 +5,29 @@ namespace plt = matplotlibcpp; -int main() +int +main() { - const int n = 20; - std::vector> matrix; + const int n = 20; + std::vector> matrix; - for (int i = 0; i < n; ++i) { - std::vector row; - for (int j = 0; j < n; ++j) { - if (i == j) - row.push_back(-2); - else if (j == i - 1 || j == i + 1) - row.push_back(1); - else - row.push_back(0); - } - matrix.push_back(row); + for(int i = 0; i < n; ++i) + { + std::vector row; + for(int j = 0; j < n; ++j) + { + if(i == j) + row.push_back(-2); + else if(j == i - 1 || j == i + 1) + row.push_back(1); + else + row.push_back(0); } + matrix.push_back(row); + } - plt::spy(matrix, 5, {{"marker", "o"}}); - plt::show(); + plt::spy(matrix, 5, { { "marker", "o" } }); + plt::show(); - return 0; + return 0; } diff --git a/examples/subplot.cpp b/examples/subplot.cpp index bee322e0..82ca096a 100644 --- a/examples/subplot.cpp +++ b/examples/subplot.cpp @@ -1,31 +1,32 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" +#include using namespace std; namespace plt = matplotlibcpp; -int main() +int +main() { - // Prepare data - int n = 500; - std::vector x(n), y(n), z(n), w(n,2); - for(int i=0; i x(n), y(n), z(n), w(n, 2); + for(int i = 0; i < n; ++i) + { + x.at(i) = i; + y.at(i) = sin(2 * M_PI * i / 360.0); + z.at(i) = 100.0 / i; + } + // Set the "super title" + plt::suptitle("My plot"); + plt::subplot(1, 2, 1); + plt::plot(x, y, "r-"); + plt::subplot(1, 2, 2); + plt::plot(x, z, "k-"); + // Add some text to the plot + plt::text(100, 90, "Hello!"); - // Show plots - plt::show(); + // Show plots + plt::show(); } diff --git a/examples/subplot2grid.cpp b/examples/subplot2grid.cpp index f590e51c..befe4f65 100644 --- a/examples/subplot2grid.cpp +++ b/examples/subplot2grid.cpp @@ -1,44 +1,45 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" +#include using namespace std; namespace plt = matplotlibcpp; -int main() +int +main() { - // Prepare data - int n = 500; - std::vector x(n), u(n), v(n), w(n); - for(int i=0; i x(n), u(n), v(n), w(n); + for(int i = 0; i < n; ++i) + { + x.at(i) = i; + u.at(i) = sin(2 * M_PI * i / 500.0); + v.at(i) = 100.0 / i; + w.at(i) = sin(2 * M_PI * i / 1000.0); + } + + // Set the "super title" + plt::suptitle("My plot"); + + const long nrows = 3, ncols = 3; + long row = 2, col = 2; + + plt::subplot2grid(nrows, ncols, row, col); + plt::plot(x, w, "g-"); + + long spanr = 1, spanc = 2; + col = 0; + plt::subplot2grid(nrows, ncols, row, col, spanr, spanc); + plt::plot(x, v, "r-"); + + spanr = 2, spanc = 3; + row = 0, col = 0; + plt::subplot2grid(nrows, ncols, row, col, spanr, spanc); + plt::plot(x, u, "b-"); + // Add some text to the plot + plt::text(100., -0.5, "Hello!"); + + // Show plots + plt::show(); } diff --git a/examples/surface.cpp b/examples/surface.cpp index 4865f061..f6d71158 100644 --- a/examples/surface.cpp +++ b/examples/surface.cpp @@ -4,21 +4,24 @@ namespace plt = matplotlibcpp; -int main() +int +main() { - std::vector> x, y, z; - for (double i = -5; i <= 5; i += 0.25) { - std::vector x_row, y_row, z_row; - for (double j = -5; j <= 5; j += 0.25) { - x_row.push_back(i); - y_row.push_back(j); - z_row.push_back(::std::sin(::std::hypot(i, j))); - } - x.push_back(x_row); - y.push_back(y_row); - z.push_back(z_row); + std::vector> x, y, z; + for(double i = -5; i <= 5; i += 0.25) + { + std::vector x_row, y_row, z_row; + for(double j = -5; j <= 5; j += 0.25) + { + x_row.push_back(i); + y_row.push_back(j); + z_row.push_back(::std::sin(::std::hypot(i, j))); } + x.push_back(x_row); + y.push_back(y_row); + z.push_back(z_row); + } - plt::plot_surface(x, y, z); - plt::show(); + plt::plot_surface(x, y, z); + plt::show(); } diff --git a/examples/update.cpp b/examples/update.cpp index 64f49067..4c8813bc 100644 --- a/examples/update.cpp +++ b/examples/update.cpp @@ -1,60 +1,63 @@ #define _USE_MATH_DEFINES -#include #include "../matplotlibcpp.h" #include +#include namespace plt = matplotlibcpp; -void update_window(const double x, const double y, const double t, - std::vector &xt, std::vector &yt) +void +update_window(const double x, const double y, const double t, std::vector &xt, std::vector &yt) { - const double target_length = 300; - const double half_win = (target_length/(2.*sqrt(1.+t*t))); + const double target_length = 300; + const double half_win = (target_length / (2. * sqrt(1. + t * t))); - xt[0] = x - half_win; - xt[1] = x + half_win; - yt[0] = y - half_win*t; - yt[1] = y + half_win*t; + xt[0] = x - half_win; + xt[1] = x + half_win; + yt[0] = y - half_win * t; + yt[1] = y + half_win * t; } - -int main() +int +main() { - size_t n = 1000; - std::vector x, y; + size_t n = 1000; + std::vector x, y; - const double w = 0.05; - const double a = n/2; + const double w = 0.05; + const double a = n / 2; - for (size_t i=0; i xt(2), yt(2); + std::vector xt(2), yt(2); - plt::title("Tangent of a sine curve"); - plt::xlim(x.front(), x.back()); - plt::ylim(-a, a); - plt::axis("equal"); + plt::title("Tangent of a sine curve"); + plt::xlim(x.front(), x.back()); + plt::ylim(-a, a); + plt::axis("equal"); - // Plot sin once and for all. - plt::named_plot("sin", x, y); + // Plot sin once and for all. + plt::named_plot("sin", x, y); - // Prepare plotting the tangent. - plt::Plot plot("tangent"); + // Prepare plotting the tangent. + plt::Plot plot("tangent"); - plt::legend(); + plt::legend(); - for (size_t i=0; i #include "../matplotlibcpp.h" +#include #include namespace plt = matplotlibcpp; -int main() { - std::vector t(1000); - std::vector x(t.size()); +int +main() +{ + std::vector t(1000); + std::vector x(t.size()); - for(size_t i = 0; i < t.size(); i++) { - t[i] = i / 100.0; - x[i] = sin(2.0 * M_PI * 1.0 * t[i]); - } + for(size_t i = 0; i < t.size(); i++) + { + t[i] = i / 100.0; + x[i] = sin(2.0 * M_PI * 1.0 * t[i]); + } - plt::xkcd(); - plt::plot(t, x); - plt::title("AN ORDINARY SIN WAVE"); - plt::show(); + plt::xkcd(); + plt::plot(t, x); + plt::title("AN ORDINARY SIN WAVE"); + plt::show(); } - diff --git a/format.sh b/format.sh new file mode 100755 index 00000000..5bf18336 --- /dev/null +++ b/format.sh @@ -0,0 +1,3 @@ +#!/bin/bash +find -regex '.*[c,h]pp' | xargs clang-format --style=file:.clang-format -i --verbose +find -regex '.*cu' | xargs clang-format --style=file:.clang-format -i --verbose \ No newline at end of file diff --git a/matplotlibcpp.h b/matplotlibcpp.h index d95d46ad..8d9392c3 100644 --- a/matplotlibcpp.h +++ b/matplotlibcpp.h @@ -14,7 +14,7 @@ #include // requires c++11 support #include #include // std::stod - +#define PY_MAJOR_VERSION 3 #ifndef WITHOUT_NUMPY # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION # include @@ -67,6 +67,7 @@ struct _interpreter { PyObject *s_python_function_scatter; PyObject *s_python_function_boxplot; PyObject *s_python_function_subplot; + PyObject *s_python_function_subplots; PyObject *s_python_function_subplot2grid; PyObject *s_python_function_legend; PyObject *s_python_function_xlim; @@ -164,13 +165,13 @@ struct _interpreter { #endif _interpreter() { - // optional but recommended #if PY_MAJOR_VERSION >= 3 wchar_t name[] = L"plotting"; #else char name[] = "plotting"; #endif +#if PY_MINOR_VERSION < 11 Py_SetProgramName(name); Py_Initialize(); @@ -178,6 +179,31 @@ struct _interpreter { wchar_t const **argv = dummy_args; int argc = sizeof(dummy_args)/sizeof(dummy_args[0])-1; +#else + PyStatus status; + PyConfig config; + PyConfig_InitPythonConfig(&config); + wchar_t const* dummy_args[] = { L"Python", NULL }; // const is needed because literals must not be modified + wchar_t* const* argv = const_cast(dummy_args); + int argc = sizeof(dummy_args) / sizeof(dummy_args[0]) - 1; + if (argc && argv) { + status = PyConfig_SetString(&config, &config.program_name, name); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + } + status = PyConfig_SetArgv(&config, argc, argv); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + } + } + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + } + PyConfig_Clear(&config); +#endif + + #if PY_MAJOR_VERSION >= 3 PySys_SetArgv(argc, const_cast(argv)); #else @@ -243,6 +269,7 @@ struct _interpreter { s_python_function_scatter = safe_import(pymod,"scatter"); s_python_function_boxplot = safe_import(pymod,"boxplot"); s_python_function_subplot = safe_import(pymod, "subplot"); + s_python_function_subplots = safe_import(pymod, "subplots"); s_python_function_subplot2grid = safe_import(pymod, "subplot2grid"); s_python_function_legend = safe_import(pymod, "legend"); s_python_function_xlim = safe_import(pymod, "xlim"); @@ -439,7 +466,7 @@ PyObject* get_listlist(const std::vector>& ll) /// /// See: https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.plot.html template -bool plot(const std::vector &x, const std::vector &y, const std::map& keywords) +bool plot(const std::vector &x, const std::vector &y, const std::map& keywords)//, double alpha=1.0) { assert(x.size() == y.size()); @@ -460,6 +487,7 @@ bool plot(const std::vector &x, const std::vector &y, const st { PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); } +// PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha)); PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs); @@ -1355,7 +1383,7 @@ bool named_hist(std::string label,const std::vector& y, long bins=10, s } template -bool plot(const std::vector& x, const std::vector& y, const std::string& s = "") +bool plot(const std::vector& x, const std::vector& y, const std::string& s = "", double alpha=1.0f) { assert(x.size() == y.size()); @@ -1371,8 +1399,12 @@ bool plot(const std::vector& x, const std::vector& y, const PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha)); + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -1672,7 +1704,34 @@ bool errorbar(const std::vector &x, const std::vector &y, co return res; } +template +bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::map& keywords = {}) +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + for (const auto& keyword : keywords) + { + PyDict_SetItemString(kwargs, keyword.first.c_str(), PyString_FromString(keyword.second.c_str())); + } + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + PyObject* plot_args = PyTuple_New(2); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res != nullptr; +} template bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "") { @@ -1951,22 +2010,31 @@ inline void legend() Py_DECREF(res); } -inline void legend(const std::map& keywords) +inline void legend(const std::map& keywords, const std::map>& tuple_keywords = {}) { - detail::_interpreter::get(); + detail::_interpreter::get(); - // construct keyword args - PyObject* kwargs = PyDict_New(); - for(std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) - { - PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); - } + // construct keyword args + PyObject* kwargs = PyDict_New(); + for(auto it = keywords.begin(); it != keywords.end(); ++it) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple, kwargs); - if(!res) throw std::runtime_error("Call to legend() failed."); + for(auto it = tuple_keywords.begin(); it != tuple_keywords.end(); ++it) + { + PyObject* tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, PyFloat_FromDouble(it->second.first)); + PyTuple_SetItem(tuple, 1, PyFloat_FromDouble(it->second.second)); + PyDict_SetItemString(kwargs, it->first.c_str(), tuple); + Py_DECREF(tuple); + } - Py_DECREF(kwargs); - Py_DECREF(res); + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple, kwargs); + if(!res) throw std::runtime_error("Call to legend() failed."); + + Py_DECREF(kwargs); + Py_DECREF(res); } template @@ -2248,16 +2316,63 @@ inline void tick_params(const std::map& keywords, cons Py_DECREF(res); } +inline std::pair subplots(long nrows=1, long ncols=1, bool sharex=false) +{ + // Ensure the Python interpreter is loaded + matplotlibcpp::detail::_interpreter::get(); + // Prepare arguments + PyObject* args = PyTuple_New(0); + PyObject* kwargs = PyDict_New(); + + // Set "nrows" and "ncols" + PyDict_SetItemString(kwargs, "nrows", PyLong_FromLong(nrows)); + PyDict_SetItemString(kwargs, "ncols", PyLong_FromLong(ncols)); + + // If we want sharex, pass True + if (sharex) { + PyDict_SetItemString(kwargs, "sharex", Py_True); + } + + // Call Python’s subplots(nrows=..., ncols=..., sharex=...). Returns (fig, axes). + PyObject* res = PyObject_Call(matplotlibcpp::detail::_interpreter::get().s_python_function_subplots, + args, kwargs); + if (!res) { + Py_DECREF(args); + Py_DECREF(kwargs); + throw std::runtime_error("Call to subplots() failed."); + } + + // Clean up + Py_DECREF(args); + Py_DECREF(kwargs); + + // Make sure we got a (fig, axes) tuple + if (!PyTuple_Check(res) || PyTuple_Size(res) != 2) { + Py_DECREF(res); + throw std::runtime_error("Expected subplots() to return (fig, axes)."); + } + + // Extract the figure and axes, increment reference counts + PyObject* fig = PyTuple_GetItem(res, 0); + PyObject* axes = PyTuple_GetItem(res, 1); + Py_INCREF(fig); + Py_INCREF(axes); + + // We no longer need `res`, so decrement its reference + Py_DECREF(res); + + return {fig, axes}; +} inline void subplot(long nrows, long ncols, long plot_number) { detail::_interpreter::get(); // construct positional args PyObject* args = PyTuple_New(3); - PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows)); - PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols)); - PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number)); + PyTuple_SetItem(args, 0, PyLong_FromLong(nrows)); + PyTuple_SetItem(args, 1, PyLong_FromLong(ncols)); + PyTuple_SetItem(args, 2, PyLong_FromLong(plot_number)); PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args); if(!res) throw std::runtime_error("Call to subplot() failed."); @@ -2651,9 +2766,18 @@ inline void rcparams(const std::map& keywords = {}) { PyObject* args = PyTuple_New(0); PyObject* kwargs = PyDict_New(); for (auto it = keywords.begin(); it != keywords.end(); ++it) { - if ("text.usetex" == it->first) - PyDict_SetItemString(kwargs, it->first.c_str(), PyLong_FromLong(std::stoi(it->second.c_str()))); - else PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + if ("text.usetex" == it->first or "font.size" == it->first) + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyLong_FromLong(std::stoi(it->second.c_str()))); + + } + else if ("lines.markersize" == it->first) + { + PyDict_SetItemString(kwargs, "lines.markersize", PyFloat_FromDouble(std::stoi(it->second.c_str()))); + }else + { + PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); + } } PyObject * update = PyObject_GetAttrString(detail::_interpreter::get().s_python_function_rcparams, "update"); @@ -2984,3 +3108,4 @@ class Plot }; } // end namespace matplotlibcpp +