|
24 | 24 |
|
25 | 25 |
|
26 | 26 | namespace matplotlibcpp { |
27 | | -template<typename NumericX, typename NumericY> |
28 | | -bool plot(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "") |
29 | | -{ |
30 | | - assert(x.size() == y.size()); |
31 | | - |
32 | | - PyObject* xarray = get_array(x); |
33 | | - PyObject* yarray = get_array(y); |
34 | | - |
35 | | - PyObject* pystring = PyString_FromString(s.c_str()); |
36 | | - |
37 | | - PyObject* plot_args = PyTuple_New(3); |
38 | | - PyTuple_SetItem(plot_args, 0, xarray); |
39 | | - PyTuple_SetItem(plot_args, 1, yarray); |
40 | | - PyTuple_SetItem(plot_args, 2, pystring); |
41 | | - |
42 | | - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); |
43 | | - |
44 | | - Py_DECREF(plot_args); |
45 | | - if(res != nullptr) Py_DECREF(res); |
46 | | - |
47 | | - return res != nullptr; |
48 | | -} |
49 | | - |
50 | 27 | template<typename NumericX, typename NumericY> |
51 | 28 | bool stem(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "") |
52 | 29 | { |
@@ -173,55 +150,6 @@ bool errorbar(const std::vector<NumericX> &x, const std::vector<NumericY> &y, co |
173 | 150 | return res != nullptr; |
174 | 151 | } |
175 | 152 |
|
176 | | -template<typename Numeric> |
177 | | -bool named_plot(const std::string& name, const std::vector<Numeric>& y, const std::string& format = "") |
178 | | -{ |
179 | | - PyObject* kwargs = PyDict_New(); |
180 | | - PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); |
181 | | - |
182 | | - PyObject* yarray = get_array(y); |
183 | | - |
184 | | - PyObject* pystring = PyString_FromString(format.c_str()); |
185 | | - |
186 | | - PyObject* plot_args = PyTuple_New(2); |
187 | | - |
188 | | - PyTuple_SetItem(plot_args, 0, yarray); |
189 | | - PyTuple_SetItem(plot_args, 1, pystring); |
190 | | - |
191 | | - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); |
192 | | - |
193 | | - Py_DECREF(kwargs); |
194 | | - Py_DECREF(plot_args); |
195 | | - if (res != nullptr) Py_DECREF(res); |
196 | | - |
197 | | - return res != nullptr; |
198 | | -} |
199 | | - |
200 | | -template<typename Numeric> |
201 | | -bool named_plot(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "") |
202 | | -{ |
203 | | - PyObject* kwargs = PyDict_New(); |
204 | | - PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); |
205 | | - |
206 | | - PyObject* xarray = get_array(x); |
207 | | - PyObject* yarray = get_array(y); |
208 | | - |
209 | | - PyObject* pystring = PyString_FromString(format.c_str()); |
210 | | - |
211 | | - PyObject* plot_args = PyTuple_New(3); |
212 | | - PyTuple_SetItem(plot_args, 0, xarray); |
213 | | - PyTuple_SetItem(plot_args, 1, yarray); |
214 | | - PyTuple_SetItem(plot_args, 2, pystring); |
215 | | - |
216 | | - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); |
217 | | - |
218 | | - Py_DECREF(kwargs); |
219 | | - Py_DECREF(plot_args); |
220 | | - if (res != nullptr) Py_DECREF(res); |
221 | | - |
222 | | - return res != nullptr; |
223 | | -} |
224 | | - |
225 | 153 | template<typename Numeric> |
226 | 154 | bool named_semilogx(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "") |
227 | 155 | { |
@@ -297,14 +225,6 @@ bool named_loglog(const std::string& name, const std::vector<Numeric>& x, const |
297 | 225 | return res != nullptr; |
298 | 226 | } |
299 | 227 |
|
300 | | -template<typename Numeric> |
301 | | -bool plot(const std::vector<Numeric>& y, const std::string& format = "") |
302 | | -{ |
303 | | - std::vector<Numeric> x(y.size()); |
304 | | - for(size_t i=0; i<x.size(); ++i) x.at(i) = static_cast<Numeric>(i); |
305 | | - return plot(x,y,format); |
306 | | -} |
307 | | - |
308 | 228 | template<typename Numeric> |
309 | 229 | bool stem(const std::vector<Numeric>& y, const std::string& format = "") |
310 | 230 | { |
@@ -599,136 +519,4 @@ inline void tight_layout() { |
599 | 519 | Py_DECREF(res); |
600 | 520 | } |
601 | 521 |
|
602 | | -#if __cplusplus > 199711L || _MSC_VER > 1800 |
603 | | -// C++11-exclusive content starts here (variadic plot() and initializer list support) |
604 | | - |
605 | | -namespace detail { |
606 | | - |
607 | | -template<typename T> |
608 | | -using is_function = typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type; |
609 | | - |
610 | | -template<bool obj, typename T> |
611 | | -struct is_callable_impl; |
612 | | - |
613 | | -template<typename T> |
614 | | -struct is_callable_impl<false, T> |
615 | | -{ |
616 | | - typedef is_function<T> type; |
617 | | -}; // a non-object is callable iff it is a function |
618 | | - |
619 | | -template<typename T> |
620 | | -struct is_callable_impl<true, T> |
621 | | -{ |
622 | | - struct Fallback { void operator()(); }; |
623 | | - struct Derived : T, Fallback { }; |
624 | | - |
625 | | - template<typename U, U> struct Check; |
626 | | - |
627 | | - template<typename U> |
628 | | - static std::true_type test( ... ); // use a variadic function to make sure (1) it accepts everything and (2) its always the worst match |
629 | | - |
630 | | - template<typename U> |
631 | | - static std::false_type test( Check<void(Fallback::*)(), &U::operator()>* ); |
632 | | - |
633 | | -public: |
634 | | - typedef decltype(test<Derived>(nullptr)) type; |
635 | | - typedef decltype(&Fallback::operator()) dtype; |
636 | | - static constexpr bool value = type::value; |
637 | | -}; // an object is callable iff it defines operator() |
638 | | - |
639 | | -template<typename T> |
640 | | -struct is_callable |
641 | | -{ |
642 | | - // dispatch to is_callable_impl<true, T> or is_callable_impl<false, T> depending on whether T is of class type or not |
643 | | - typedef typename is_callable_impl<std::is_class<T>::value, T>::type type; |
644 | | -}; |
645 | | - |
646 | | -template<typename IsYDataCallable> |
647 | | -struct plot_impl { }; |
648 | | - |
649 | | -template<> |
650 | | -struct plot_impl<std::false_type> |
651 | | -{ |
652 | | - template<typename IterableX, typename IterableY> |
653 | | - bool operator()(const IterableX& x, const IterableY& y, const std::string& format) |
654 | | - { |
655 | | - // 2-phase lookup for distance, begin, end |
656 | | - using std::distance; |
657 | | - using std::begin; |
658 | | - using std::end; |
659 | | - |
660 | | - auto xs = distance(begin(x), end(x)); |
661 | | - auto ys = distance(begin(y), end(y)); |
662 | | - assert(xs == ys && "x and y data must have the same number of elements!"); |
663 | | - |
664 | | - PyObject* xlist = PyList_New(xs); |
665 | | - PyObject* ylist = PyList_New(ys); |
666 | | - PyObject* pystring = PyString_FromString(format.c_str()); |
667 | | - |
668 | | - auto itx = begin(x), ity = begin(y); |
669 | | - for(size_t i = 0; i < static_cast<size_t>(xs); ++i) { |
670 | | - PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++)); |
671 | | - PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++)); |
672 | | - } |
673 | | - |
674 | | - PyObject* plot_args = PyTuple_New(3); |
675 | | - PyTuple_SetItem(plot_args, 0, xlist); |
676 | | - PyTuple_SetItem(plot_args, 1, ylist); |
677 | | - PyTuple_SetItem(plot_args, 2, pystring); |
678 | | - |
679 | | - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); |
680 | | - |
681 | | - Py_DECREF(plot_args); |
682 | | - if(res != nullptr) Py_DECREF(res); |
683 | | - |
684 | | - return res != nullptr; |
685 | | - } |
686 | | -}; |
687 | | - |
688 | | -template<> |
689 | | -struct plot_impl<std::true_type> |
690 | | -{ |
691 | | - template<typename Iterable, typename Callable> |
692 | | - bool operator()(const Iterable& ticks, const Callable& f, const std::string& format) |
693 | | - { |
694 | | - if(begin(ticks) == end(ticks)) return true; |
695 | | - |
696 | | - // We could use additional meta-programming to deduce the correct element type of y, |
697 | | - // but all values have to be convertible to double anyways |
698 | | - std::vector<double> y; |
699 | | - for(auto x : ticks) y.push_back(f(x)); |
700 | | - return plot_impl<std::false_type>()(ticks,y,format); |
701 | | - } |
702 | | -}; |
703 | | - |
704 | | -} // end namespace detail |
705 | | - |
706 | | -// recursion stop for the above |
707 | | -template<typename... Args> |
708 | | -bool plot() { return true; } |
709 | | - |
710 | | -template<typename A, typename B, typename... Args> |
711 | | -bool plot(const A& a, const B& b, const std::string& format, Args... args) |
712 | | -{ |
713 | | - return detail::plot_impl<typename detail::is_callable<B>::type>()(a,b,format) && plot(args...); |
714 | | -} |
715 | | - |
716 | | -/* |
717 | | - * This group of plot() functions is needed to support initializer lists, i.e. calling |
718 | | - * plot( {1,2,3,4} ) |
719 | | - */ |
720 | | -inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::string& format = "") { |
721 | | - return plot<double,double>(x,y,format); |
722 | | -} |
723 | | - |
724 | | -inline bool plot(const std::vector<double>& y, const std::string& format = "") { |
725 | | - return plot<double>(y,format); |
726 | | -} |
727 | | - |
728 | | -inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::map<std::string, std::string>& keywords) { |
729 | | - return plot<double>(x,y,keywords); |
730 | | -} |
731 | | - |
732 | | -#endif |
733 | | - |
734 | 522 | } // end namespace matplotlibcpp |
0 commit comments