@@ -47,6 +47,7 @@ struct _interpreter {
4747 PyObject *s_python_function_legend;
4848 PyObject *s_python_function_xlim;
4949 PyObject *s_python_function_ion;
50+ PyObject *s_python_function_ginput;
5051 PyObject *s_python_function_ylim;
5152 PyObject *s_python_function_title;
5253 PyObject *s_python_function_axis;
@@ -160,6 +161,7 @@ struct _interpreter {
160161 s_python_function_grid = PyObject_GetAttrString (pymod, " grid" );
161162 s_python_function_xlim = PyObject_GetAttrString (pymod, " xlim" );
162163 s_python_function_ion = PyObject_GetAttrString (pymod, " ion" );
164+ s_python_function_ginput = PyObject_GetAttrString (pymod, " ginput" );
163165 s_python_function_save = PyObject_GetAttrString (pylabmod, " savefig" );
164166 s_python_function_annotate = PyObject_GetAttrString (pymod," annotate" );
165167 s_python_function_clf = PyObject_GetAttrString (pymod, " clf" );
@@ -191,6 +193,7 @@ struct _interpreter {
191193 || !s_python_function_grid
192194 || !s_python_function_xlim
193195 || !s_python_function_ion
196+ || !s_python_function_ginput
194197 || !s_python_function_save
195198 || !s_python_function_clf
196199 || !s_python_function_annotate
@@ -225,6 +228,7 @@ struct _interpreter {
225228 || !PyFunction_Check (s_python_function_grid)
226229 || !PyFunction_Check (s_python_function_xlim)
227230 || !PyFunction_Check (s_python_function_ion)
231+ || !PyFunction_Check (s_python_function_ginput)
228232 || !PyFunction_Check (s_python_function_save)
229233 || !PyFunction_Check (s_python_function_clf)
230234 || !PyFunction_Check (s_python_function_tight_layout)
@@ -1214,6 +1218,40 @@ inline void clf() {
12141218 Py_DECREF (res);
12151219}
12161220
1221+ inline std::vector<std::array<double , 2 >> ginput (const int numClicks = 1 , const std::map<std::string, std::string>& keywords = {})
1222+ {
1223+ PyObject *args = PyTuple_New (1 );
1224+ PyTuple_SetItem (args, 0 , PyLong_FromLong (numClicks));
1225+
1226+ // construct keyword args
1227+ PyObject* kwargs = PyDict_New ();
1228+ for (std::map<std::string, std::string>::const_iterator it = keywords.begin (); it != keywords.end (); ++it)
1229+ {
1230+ PyDict_SetItemString (kwargs, it->first .c_str (), PyUnicode_FromString (it->second .c_str ()));
1231+ }
1232+
1233+ PyObject* res = PyObject_Call (
1234+ detail::_interpreter::get ().s_python_function_ginput , args, kwargs);
1235+
1236+ Py_DECREF (kwargs);
1237+ Py_DECREF (args);
1238+ if (!res) throw std::runtime_error (" Call to ginput() failed." );
1239+
1240+ const size_t len = PyList_Size (res);
1241+ std::vector<std::array<double , 2 >> out;
1242+ out.reserve (len);
1243+ for (size_t i = 0 ; i < len; i++) {
1244+ PyObject *current = PyList_GetItem (res, i);
1245+ std::array<double , 2 > position;
1246+ position[0 ] = PyFloat_AsDouble (PyTuple_GetItem (current, 0 ));
1247+ position[1 ] = PyFloat_AsDouble (PyTuple_GetItem (current, 1 ));
1248+ out.push_back (position);
1249+ }
1250+ Py_DECREF (res);
1251+
1252+ return out;
1253+ }
1254+
12171255// Actually, is there any reason not to call this automatically for every plot?
12181256inline void tight_layout () {
12191257 PyObject *res = PyObject_CallObject (
0 commit comments