@@ -468,6 +468,103 @@ PyObject* get_listlist(const std::vector<std::vector<Numeric>>& ll)
468
468
469
469
} // namespace detail
470
470
471
+
472
+ #ifdef USE_VARIADIC_TEMPLATES_ARGS
473
+
474
+ // ---------------------------------------------
475
+ // Analyse des keywords dans un tuple
476
+ //
477
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const bool value) {
478
+ return {key, value ? Py_True : Py_False};
479
+ }
480
+
481
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const int value) {
482
+ return {key, PyLong_FromLong (value)};
483
+ }
484
+
485
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const long value) {
486
+ return {key, PyLong_FromLong (value)};
487
+ }
488
+
489
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const double value) {
490
+ return {key, PyFloat_FromDouble (value)};
491
+ }
492
+
493
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const char * value) {
494
+ return {key, PyString_FromString (value)};
495
+ }
496
+
497
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const std::string& value) {
498
+ PyObject* str_value = PyString_FromString (value.c_str ());
499
+ return {key, str_value};
500
+ }
501
+
502
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const std::vector<double >& value) {
503
+ // PyObject* py_levels = PyList_New(value.size());
504
+ // for (size_t i = 0; i < value.size(); ++i) {
505
+ // PyList_SetItem(py_levels, i, PyFloat_FromDouble(value.at(i)));
506
+ // }
507
+ return {key, get_array (value)};
508
+ }
509
+
510
+ std::pair<std::string, PyObject*> analyze_key_value (const char * key, const std::vector<int >& value) {
511
+ PyObject* args = PyTuple_New (value.size ());
512
+ for (size_t i = 0 ; i < value.size (); ++i) {
513
+ PyTuple_SetItem (args, i, PyLong_FromLong (value.at (i)));
514
+ }
515
+ return {key, get_array (value)};
516
+ }
517
+
518
+ template <class Tuple , std::size_t N>
519
+ struct AnalyzeKeywordsHelper {
520
+ static void analyze_keywords (const Tuple& kw, PyObject* keywords) {
521
+ AnalyzeKeywordsHelper<Tuple, N-2 >::analyze_keywords (kw, keywords);
522
+ std::string key;
523
+ PyObject* value;
524
+ std::tie (key, value) = analyze_key_value (std::get<N-2 >(kw), std::get<N-1 >(kw));
525
+ PyDict_SetItemString (keywords, key.c_str (), value);
526
+ Py_DECREF (value); // @TST
527
+ }
528
+ };
529
+
530
+ template <class Tuple >
531
+ struct AnalyzeKeywordsHelper <Tuple, 2 > {
532
+ static void analyze_keywords (const Tuple& kw, PyObject* keywords) {
533
+ std::string key;
534
+ PyObject* value;
535
+ std::tie (key, value) = analyze_key_value (std::get<0 >(kw), std::get<1 >(kw));
536
+ PyDict_SetItemString (keywords, key.c_str (), value);
537
+ Py_DECREF (value); // @TST
538
+ }
539
+ };
540
+
541
+ template <class ... Args>
542
+ PyObject* analyze_keywords (const std::tuple<Args...>& kw) {
543
+ // Inutile de vérifier que la longueur du tuple est un multiple de 2,
544
+ // car comme on avance de 2 en 2, l'instanciation du template ne peut pas se faire pour
545
+ // un tuple qui n'a pas un nombre pair d'items.
546
+ PyObject* keywords = PyDict_New ();
547
+ AnalyzeKeywordsHelper<decltype (kw), sizeof ...(Args)>::analyze_keywords (kw, keywords);
548
+ return keywords;
549
+ }
550
+
551
+ // ----------
552
+ // Identity type conversion to PyObject* (for functions `figure(Identity, tuple<Args...>&)` and `close(Identity)`)
553
+ //
554
+ PyObject* get_pyobject_from (const int value) {
555
+ return PyLong_FromLong (value);
556
+ }
557
+
558
+ PyObject* get_pyobject_from (const char * value) {
559
+ return PyString_FromString (value);
560
+ }
561
+
562
+ PyObject* get_pyobject_from (const std::string& value) {
563
+ return PyString_FromString (value.c_str ());
564
+ }
565
+ #endif // USE_VARIADIC_TEMPLATES_ARGS
566
+
567
+
471
568
// / Plot a line through the given x and y data points..
472
569
// /
473
570
// / See: https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.plot.html
@@ -894,36 +991,58 @@ void imshow(const cv::Mat &image, const std::map<std::string, std::string> &keyw
894
991
#endif // WITHOUT_NUMPY
895
992
896
993
template <typename NumericX, typename NumericY>
897
- bool scatter (const std::vector<NumericX>& x,
994
+ bool __scatter (const std::vector<NumericX>& x,
898
995
const std::vector<NumericY>& y,
899
- const double s=1.0 , // The marker size in points**2
900
- const std::map<std::string, std::string> & keywords = {})
996
+ PyObject* kwargs)
901
997
{
902
- detail::_interpreter::get ();
998
+ detail::_interpreter::get ();
999
+
1000
+ assert (x.size () == y.size ());
903
1001
904
- assert (x.size () == y.size ());
1002
+ PyObject* xarray = get_array (x);
1003
+ PyObject* yarray = get_array (y);
905
1004
906
- PyObject* xarray = detail::get_array (x);
907
- PyObject* yarray = detail::get_array (y);
1005
+ PyObject* args = PyTuple_New (2 );
1006
+ PyTuple_SetItem (args, 0 , xarray);
1007
+ PyTuple_SetItem (args, 1 , yarray);
1008
+
1009
+ PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_scatter , args, kwargs);
908
1010
1011
+ Py_DECREF (args);
1012
+ Py_DECREF (kwargs);
1013
+
1014
+ if (!res) {
1015
+ throw std::runtime_error (" Call to scatter(x, y [, marker]) failed." );
1016
+ }
1017
+
1018
+ Py_DECREF (res);
1019
+
1020
+ return res;
1021
+ }
1022
+
1023
+ // generic form
1024
+ template <typename Numeric, class ... Args>
1025
+ inline bool scatter (const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::tuple<Args...>& keywords)
1026
+ {
1027
+ PyObject* kwargs = analyze_keywords (keywords);
1028
+ return __scatter (x, y, kwargs);
1029
+ }
1030
+
1031
+ // specialized form
1032
+ template <typename NumericX, typename NumericY>
1033
+ bool scatter (const std::vector<NumericX>& x,
1034
+ const std::vector<NumericY>& y,
1035
+ const double s=1.0 , // The marker size in points**2
1036
+ const std::map<std::string, std::string> & keywords = {})
1037
+ {
909
1038
PyObject* kwargs = PyDict_New ();
910
1039
PyDict_SetItemString (kwargs, " s" , PyLong_FromLong (s));
911
1040
for (const auto & it : keywords)
912
1041
{
913
1042
PyDict_SetItemString (kwargs, it.first .c_str (), PyString_FromString (it.second .c_str ()));
914
1043
}
915
1044
916
- PyObject* plot_args = PyTuple_New (2 );
917
- PyTuple_SetItem (plot_args, 0 , xarray);
918
- PyTuple_SetItem (plot_args, 1 , yarray);
919
-
920
- PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_scatter , plot_args, kwargs);
921
-
922
- Py_DECREF (plot_args);
923
- Py_DECREF (kwargs);
924
- if (res) Py_DECREF (res);
925
-
926
- return res;
1045
+ return __scatter (x, y, kwargs);
927
1046
}
928
1047
929
1048
template <typename Numeric>
@@ -1523,6 +1642,36 @@ inline long figure(long number = -1)
1523
1642
return figureNumber;
1524
1643
}
1525
1644
1645
+ template <typename Identity, class ... Args>
1646
+ inline Identity figure (Identity number, const std::tuple<Args...>& keywords)
1647
+ {
1648
+ // Identity est de type int ou string
1649
+ PyObject* args = PyTuple_New (1 );
1650
+ PyTuple_SetItem (args, 0 , get_pyobject_from (number));
1651
+
1652
+ PyObject* kwargs = analyze_keywords (keywords);
1653
+
1654
+ PyObject* res = nullptr ;
1655
+ res = PyObject_Call (detail::_interpreter::get ().s_python_function_figure , args, kwargs);
1656
+
1657
+ Py_DECREF (args);
1658
+ Py_DECREF (kwargs);
1659
+
1660
+ if (!res) {
1661
+ PyErr_Print ();
1662
+ throw std::runtime_error (" Call to pyplot.figure(num) failed." );
1663
+ }
1664
+
1665
+ PyObject* num = PyObject_GetAttrString (res, " number" );
1666
+ if (!num) throw std::runtime_error (" Could not get number attribute of figure object" );
1667
+ auto figureNumber = static_cast <Identity>(PyLong_AsLong (num));
1668
+
1669
+ Py_DECREF (num);
1670
+ Py_DECREF (res);
1671
+
1672
+ return figureNumber;
1673
+ }
1674
+
1526
1675
inline bool fignum_exists (long number)
1527
1676
{
1528
1677
detail::_interpreter::get ();
@@ -2048,6 +2197,23 @@ inline void close()
2048
2197
Py_DECREF (res);
2049
2198
}
2050
2199
2200
+ template <typename Identity>
2201
+ inline void close (Identity num)
2202
+ {
2203
+ PyObject* args = PyTuple_New (1 );
2204
+ PyTuple_SetItem (args, 0 , get_pyobject_from (num));
2205
+
2206
+ PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_close , args);
2207
+
2208
+ Py_DECREF (args);
2209
+
2210
+ if (!res) {
2211
+ throw std::runtime_error (" Call to close(num) failed." );
2212
+ }
2213
+
2214
+ Py_DECREF (res);
2215
+ }
2216
+
2051
2217
inline void xkcd () {
2052
2218
detail::_interpreter::get ();
2053
2219
0 commit comments