| 515 | + if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); } |
| 516 | + |
| 517 | + axis3dmod = PyImport_Import(axis3d); |
| 518 | + Py_DECREF(axis3d); |
| 519 | + if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); } |
| 520 | + } |
| 521 | + |
| 522 | + assert(x.size() == y.size()); |
| 523 | + assert(y.size() == z.size()); |
| 524 | + |
| 525 | + PyObject *xarray = get_array(x); |
| 526 | + PyObject *yarray = get_array(y); |
| 527 | + PyObject *zarray = get_array(z); |
| 528 | + |
| 529 | + // construct positional args |
| 530 | + PyObject *args = PyTuple_New(3); |
| 531 | + PyTuple_SetItem(args, 0, xarray); |
| 532 | + PyTuple_SetItem(args, 1, yarray); |
| 533 | + PyTuple_SetItem(args, 2, zarray); |
| 534 | + |
| 535 | + // Build up the kw args. |
| 536 | + PyObject *kwargs = PyDict_New(); |
| 537 | + |
| 538 | + for (std::map<std::string, std::string>::const_iterator it = keywords.begin(); |
| 539 | + it != keywords.end(); ++it) { |
| 540 | + PyDict_SetItemString(kwargs, it->first.c_str(), |
| 541 | + PyString_FromString(it->second.c_str())); |
| 542 | + } |
| 543 | + |
| 544 | + PyObject *fig = |
| 545 | + PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, |
| 546 | + detail::_interpreter::get().s_python_empty_tuple); |
| 547 | + if (!fig) throw std::runtime_error("Call to figure() failed."); |
| 548 | + |
| 549 | + PyObject *gca_kwargs = PyDict_New(); |
| 550 | + PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d")); |
| 551 | + |
| 552 | + PyObject *gca = PyObject_GetAttrString(fig, "gca"); |
| 553 | + if (!gca) throw std::runtime_error("No gca"); |
| 554 | + Py_INCREF(gca); |
| 555 | + PyObject *axis = PyObject_Call( |
| 556 | + gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs); |
| 557 | + |
| 558 | + if (!axis) throw std::runtime_error("No axis"); |
| 559 | + Py_INCREF(axis); |
| 560 | + |
| 561 | + Py_DECREF(gca); |
| 562 | + Py_DECREF(gca_kwargs); |
| 563 | + |
| 564 | + PyObject *plot3 = PyObject_GetAttrString(axis, "plot"); |
| 565 | + if (!plot3) throw std::runtime_error("No 3D line plot"); |
| 566 | + Py_INCREF(plot3); |
| 567 | + PyObject *res = PyObject_Call(plot3, args, kwargs); |
| 568 | + if (!res) throw std::runtime_error("Failed 3D line plot"); |
| 569 | + Py_DECREF(plot3); |
| 570 | + |
| 571 | + Py_DECREF(axis); |
| 572 | + Py_DECREF(args); |
| 573 | + Py_DECREF(kwargs); |
| 574 | + if (res) Py_DECREF(res); |
| 575 | +} |
492 | 576 |
|
493 | 577 | template<typename Numeric>
|
494 | 578 | bool stem(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
|
@@ -1662,6 +1746,57 @@ inline void ylabel(const std::string &str, const std::map<std::string, std::stri
|
1662 | 1746 | Py_DECREF(res);
|
1663 | 1747 | }
|
1664 | 1748 |
|
| 1749 | +inline void set_zlabel(const std::string &str, const std::map<std::string, std::string>& keywords = {}) { |
| 1750 | + // Same as with plot_surface: We lazily load the modules here the first time |
| 1751 | + // this function is called because I'm not sure that we can assume "matplotlib |
| 1752 | + // installed" implies "mpl_toolkits installed" on all platforms, and we don't |
| 1753 | + // want to require it for people who don't need 3d plots. |
| 1754 | + static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr; |
| 1755 | + if (!mpl_toolkitsmod) { |
| 1756 | + detail::_interpreter::get(); |
| 1757 | + |
| 1758 | + PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits"); |
| 1759 | + PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d"); |
| 1760 | + if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); } |
| 1761 | + |
| 1762 | + mpl_toolkitsmod = PyImport_Import(mpl_toolkits); |
| 1763 | + Py_DECREF(mpl_toolkits); |
| 1764 | + if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); } |
| 1765 | + |
| 1766 | + axis3dmod = PyImport_Import(axis3d); |
| 1767 | + Py_DECREF(axis3d); |
| 1768 | + if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); } |
| 1769 | + } |
| 1770 | + |
| 1771 | + PyObject* pystr = PyString_FromString(str.c_str()); |
| 1772 | + PyObject* args = PyTuple_New(1); |
| 1773 | + PyTuple_SetItem(args, 0, pystr); |
| 1774 | + |
| 1775 | + PyObject* kwargs = PyDict_New(); |
| 1776 | + for (auto it = keywords.begin(); it != keywords.end(); ++it) { |
| 1777 | + PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); |
| 1778 | + } |
| 1779 | + |
| 1780 | + PyObject *ax = |
| 1781 | + PyObject_CallObject(detail::_interpreter::get().s_python_function_gca, |
| 1782 | + detail::_interpreter::get().s_python_empty_tuple); |
| 1783 | + if (!ax) throw std::runtime_error("Call to gca() failed."); |
| 1784 | + Py_INCREF(ax); |
| 1785 | + |
| 1786 | + PyObject *zlabel = PyObject_GetAttrString(ax, "set_zlabel"); |
| 1787 | + if (!zlabel) throw std::runtime_error("Attribute set_zlabel not found."); |
| 1788 | + Py_INCREF(zlabel); |
| 1789 | + |
| 1790 | + PyObject *res = PyObject_Call(zlabel, args, kwargs); |
| 1791 | + if (!res) throw std::runtime_error("Call to set_zlabel() failed."); |
| 1792 | + Py_DECREF(zlabel); |
| 1793 | + |
| 1794 | + Py_DECREF(ax); |
| 1795 | + Py_DECREF(args); |
| 1796 | + Py_DECREF(kwargs); |
| 1797 | + if (res) Py_DECREF(res); |
| 1798 | +} |
| 1799 | + |
1665 | 1800 | inline void grid(bool flag)
|
1666 | 1801 | {
|
1667 | 1802 | PyObject* pyflag = flag ? Py_True : Py_False;
|
|
0 commit comments