| 2512 | | ###################################################################### |
|---|
| 2513 | | # # |
|---|
| 2514 | | # Graphics Primitives Factories -- construct GraphicPrimitives # |
|---|
| 2515 | | # # |
|---|
| 2516 | | ###################################################################### |
|---|
| 2517 | | # |
|---|
| 2518 | | # The current method of writing a new Graphic Primitive |
|---|
| 2519 | | # involves writing a specific Factory for a given |
|---|
| 2520 | | # primitive, for example, 'GraphicPrimitive_circle' for 'circle'. |
|---|
| 2521 | | # This class should inherit from GraphicPrimitiveFactory, |
|---|
| 2522 | | # which should define any general Graphic Primitive attributes. |
|---|
| 2523 | | # |
|---|
| 2524 | | # As of now, the Graphic Primitive Factories, have |
|---|
| 2525 | | # only a __call__ method that deals with setting kwargs |
|---|
| 2526 | | # and coercing data into a correct form to present to |
|---|
| 2527 | | # one of the matplotlib functions. |
|---|
| 2528 | | # |
|---|
| 2529 | | |
|---|
| 2530 | | class GraphicPrimitiveFactory: |
|---|
| 2531 | | def __init__(self): |
|---|
| 2532 | | # options for this specific graphics primitive. |
|---|
| 2533 | | self.reset() |
|---|
| 2534 | | |
|---|
| 2535 | | def reset(self): |
|---|
| 2536 | | # First the default options for all graphics primitives |
|---|
| 2537 | | self.options = {'alpha':1,'thickness':1,'rgbcolor':(0,0,1)} |
|---|
| 2538 | | self._reset() |
|---|
| 2539 | | |
|---|
| 2540 | | def _coerce(self, xdata, ydata): |
|---|
| 2541 | | return to_float_list(xdata), to_float_list(ydata) |
|---|
| 2542 | | |
|---|
| 2543 | | def _graphic3d(self, *args, **kwds): |
|---|
| 2544 | | """ |
|---|
| 2545 | | Return 3d version of this graphics primitive. |
|---|
| 2546 | | |
|---|
| 2547 | | We call this if the user tries to create a graphic but gives |
|---|
| 2548 | | points (etc) in 3-space instead of in the plane. |
|---|
| 2549 | | """ |
|---|
| 2550 | | raise NotImplementedError, "3d plotting of this primitive not yet implemented" |
|---|
| 2551 | | |
|---|
| 2552 | | |
|---|
| 2553 | | #class GraphicPrimitiveFactory_points(GraphicPrimitiveFactory): |
|---|
| 2554 | | # def __call__(self, xdata, ydata, **kwds): |
|---|
| 2555 | | # options = dict(self.options) |
|---|
| 2556 | | # for k, v in kwds.iteritems(): |
|---|
| 2557 | | # options[k] = v |
|---|
| 2558 | | # return self._from_xdata_ydata(xdata, ydata, options=options) |
|---|
| 2559 | | |
|---|
| 2560 | | # WARNING: The below GraphicPrimitiveFactory_from_point_list |
|---|
| 2561 | | # class can potentially be very slow for large point sets. |
|---|
| | 2504 | |
|---|
| | 2505 | # WARNING: The below function xydata_from_point_list |
|---|
| | 2506 | # can potentially be very slow for large point sets. |
|---|
| 2578 | | options = dict(self.options) |
|---|
| 2579 | | for k, v in kwds.iteritems(): |
|---|
| 2580 | | options[k] = v |
|---|
| 2581 | | |
|---|
| 2582 | | if not isinstance(points, (list,tuple)) or \ |
|---|
| 2583 | | (isinstance(points,(list,tuple)) and len(points) <= 3 \ |
|---|
| 2584 | | and len(points) > 0 \ |
|---|
| 2585 | | and not isinstance(points[0], (list,tuple))): |
|---|
| 2586 | | try: |
|---|
| 2587 | | points = [[float(z) for z in points]] |
|---|
| 2588 | | except TypeError: |
|---|
| 2589 | | pass |
|---|
| 2590 | | |
|---|
| 2591 | | try: |
|---|
| 2592 | | if len(points) > 0 and len(points[0]) == 3: |
|---|
| 2593 | | return self._graphic3d()(points, coerce=coerce, **kwds) |
|---|
| 2594 | | except (AttributeError, TypeError): |
|---|
| 2595 | | pass |
|---|
| 2596 | | xdata = [] |
|---|
| 2597 | | ydata = [] |
|---|
| 2598 | | if coerce: |
|---|
| 2599 | | xdata = [float(z[0]) for z in points] |
|---|
| 2600 | | ydata = [float(z[1]) for z in points] |
|---|
| 2601 | | else: |
|---|
| 2602 | | xdata = [z[0] for z in points] |
|---|
| 2603 | | ydata = [z[1] for z in points] |
|---|
| 2604 | | |
|---|
| 2605 | | return self._from_xdata_ydata(xdata, ydata, True, options=options) |
|---|
| 2606 | | |
|---|
| 2607 | | class ArrowFactory(GraphicPrimitiveFactory): |
|---|
| 2608 | | """ |
|---|
| 2609 | | |
|---|
| | 2526 | xdata = [float(z[0]) for z in points] |
|---|
| | 2527 | ydata = [float(z[1]) for z in points] |
|---|
| | 2528 | |
|---|
| | 2529 | return xdata, ydata |
|---|
| | 2530 | |
|---|
| | 2531 | def arrow(minpoint, maxpoint, **kwds): |
|---|
| | 2532 | """ |
|---|
| 2630 | | |
|---|
| 2631 | | """ |
|---|
| 2632 | | def __call__(self, minpoint, maxpoint, **kwds): |
|---|
| 2633 | | options = dict(self.options) |
|---|
| 2634 | | for k, v in kwds.iteritems(): |
|---|
| 2635 | | options[k] = v |
|---|
| 2636 | | xmin = float(minpoint[0]) |
|---|
| 2637 | | ymin = float(minpoint[1]) |
|---|
| 2638 | | xmax = float(maxpoint[0]) |
|---|
| 2639 | | ymax = float(maxpoint[1]) |
|---|
| 2640 | | |
|---|
| 2641 | | g = Graphics(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) |
|---|
| 2642 | | g._arrow(xmin, ymin, xmax, ymax, options=options) |
|---|
| 2643 | | return g |
|---|
| 2644 | | |
|---|
| 2645 | | def _reset(self): |
|---|
| 2646 | | self.options={'width':0.02,'rgbcolor':(0, 0, 1)} |
|---|
| 2647 | | |
|---|
| 2648 | | def __repr__(self): |
|---|
| 2649 | | """ |
|---|
| 2650 | | Returns a string representation of this ArrowFactory object. |
|---|
| 2651 | | |
|---|
| 2652 | | TESTS: |
|---|
| 2653 | | sage: arrow |
|---|
| 2654 | | type arrow? for help and examples |
|---|
| 2655 | | """ |
|---|
| 2656 | | return "type arrow? for help and examples" |
|---|
| 2657 | | |
|---|
| 2658 | | #an unique arrow instance |
|---|
| 2659 | | arrow = ArrowFactory() |
|---|
| 2660 | | |
|---|
| 2661 | | class BarChartFactory(GraphicPrimitiveFactory): |
|---|
| | 2553 | """ |
|---|
| | 2554 | |
|---|
| | 2555 | options = {'width':0.02,'rgbcolor':(0, 0, 1)} |
|---|
| | 2556 | options.update(kwds) |
|---|
| | 2557 | |
|---|
| | 2558 | #Get the x/y min/max data |
|---|
| | 2559 | xmin = float(minpoint[0]) |
|---|
| | 2560 | ymin = float(minpoint[1]) |
|---|
| | 2561 | xmax = float(maxpoint[0]) |
|---|
| | 2562 | ymax = float(maxpoint[1]) |
|---|
| | 2563 | |
|---|
| | 2564 | g = Graphics(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) |
|---|
| | 2565 | g._arrow(xmin, ymin, xmax, ymax, options=options) |
|---|
| | 2566 | return g |
|---|
| | 2567 | |
|---|
| | 2568 | def bar_chart(datalist, **kwds): |
|---|
| 2676 | | def __call__(self, datalist, **kwds): |
|---|
| 2677 | | options = dict(self.options) |
|---|
| 2678 | | for k, v in kwds.iteritems(): |
|---|
| 2679 | | options[k] = v |
|---|
| 2680 | | dl = len(datalist) |
|---|
| 2681 | | #if dl > 1: |
|---|
| 2682 | | # print "WARNING, currently only 1 data set allowed" |
|---|
| 2683 | | # datalist = datalist[0] |
|---|
| 2684 | | if dl == 3: |
|---|
| 2685 | | datalist = datalist+[0] |
|---|
| 2686 | | #bardata = [] |
|---|
| 2687 | | #cnt = 1 |
|---|
| 2688 | | #for pnts in datalist: |
|---|
| 2689 | | #ind = [i+cnt/dl for i in range(len(pnts))] |
|---|
| 2690 | | ind = range(len(datalist)) |
|---|
| 2691 | | xrange = (0, len(datalist)) |
|---|
| 2692 | | yrange = (min(datalist), max(datalist)) |
|---|
| 2693 | | #bardata.append([ind, pnts, xrange, yrange]) |
|---|
| 2694 | | #cnt += 1 |
|---|
| 2695 | | |
|---|
| 2696 | | g = Graphics() |
|---|
| 2697 | | #TODO: improve below for multiple data sets! |
|---|
| 2698 | | #cnt = 1 |
|---|
| 2699 | | #for ind, pnts, xrange, yrange in bardata: |
|---|
| 2700 | | #options={'rgbcolor':hue(cnt/dl),'width':0.5/dl} |
|---|
| 2701 | | # g._bar_chart(ind, pnts, xrange, yrange, options=options) |
|---|
| 2702 | | # cnt += 1 |
|---|
| 2703 | | #else: |
|---|
| 2704 | | g._bar_chart(ind, datalist, xrange, yrange, options=options) |
|---|
| 2705 | | return g |
|---|
| 2706 | | |
|---|
| 2707 | | def _reset(self): |
|---|
| 2708 | | self.options={'width':0.5,'rgbcolor':(0, 0, 1)} |
|---|
| 2709 | | |
|---|
| 2710 | | def __repr__(self): |
|---|
| 2711 | | """ |
|---|
| 2712 | | Returns a string representation of this BarChartFactory object. |
|---|
| 2713 | | |
|---|
| 2714 | | TESTS: |
|---|
| 2715 | | sage: bar_chart |
|---|
| 2716 | | type bar_chart? for help and examples |
|---|
| 2717 | | """ |
|---|
| 2718 | | return "type bar_chart? for help and examples" |
|---|
| 2719 | | |
|---|
| 2720 | | #an unique bar_chart instance |
|---|
| 2721 | | bar_chart = BarChartFactory() |
|---|
| 2722 | | |
|---|
| 2723 | | |
|---|
| 2724 | | class CircleFactory(GraphicPrimitiveFactory): |
|---|
| | 2583 | options = {'width':0.5,'rgbcolor':(0, 0, 1)} |
|---|
| | 2584 | options.update(kwds) |
|---|
| | 2585 | |
|---|
| | 2586 | dl = len(datalist) |
|---|
| | 2587 | #if dl > 1: |
|---|
| | 2588 | # print "WARNING, currently only 1 data set allowed" |
|---|
| | 2589 | # datalist = datalist[0] |
|---|
| | 2590 | if dl == 3: |
|---|
| | 2591 | datalist = datalist+[0] |
|---|
| | 2592 | #bardata = [] |
|---|
| | 2593 | #cnt = 1 |
|---|
| | 2594 | #for pnts in datalist: |
|---|
| | 2595 | #ind = [i+cnt/dl for i in range(len(pnts))] |
|---|
| | 2596 | ind = range(len(datalist)) |
|---|
| | 2597 | xrange = (0, len(datalist)) |
|---|
| | 2598 | yrange = (min(datalist), max(datalist)) |
|---|
| | 2599 | #bardata.append([ind, pnts, xrange, yrange]) |
|---|
| | 2600 | #cnt += 1 |
|---|
| | 2601 | |
|---|
| | 2602 | g = Graphics() |
|---|
| | 2603 | #TODO: improve below for multiple data sets! |
|---|
| | 2604 | #cnt = 1 |
|---|
| | 2605 | #for ind, pnts, xrange, yrange in bardata: |
|---|
| | 2606 | #options={'rgbcolor':hue(cnt/dl),'width':0.5/dl} |
|---|
| | 2607 | # g._bar_chart(ind, pnts, xrange, yrange, options=options) |
|---|
| | 2608 | # cnt += 1 |
|---|
| | 2609 | #else: |
|---|
| | 2610 | g._bar_chart(ind, datalist, xrange, yrange, options=options) |
|---|
| | 2611 | return g |
|---|
| | 2612 | |
|---|
| | 2613 | |
|---|
| | 2614 | def circle(point, radius, **kwds): |
|---|
| 2769 | | def __call__(self, point, radius, **kwds): |
|---|
| 2770 | | options = dict(self.options) |
|---|
| 2771 | | for k, v in kwds.iteritems(): |
|---|
| 2772 | | options[k] = v |
|---|
| 2773 | | |
|---|
| 2774 | | r = float(radius) |
|---|
| 2775 | | point = (float(point[0]), float(point[1])) |
|---|
| 2776 | | g = Graphics(xmin=point[0]-r, xmax=point[0]+r, ymin=point[1]-r, ymax=point[1]+r) |
|---|
| 2777 | | g._circle(point[0], point[1], r, options) |
|---|
| 2778 | | return g |
|---|
| 2779 | | |
|---|
| 2780 | | def _reset(self): |
|---|
| 2781 | | self.options={'alpha':1,'fill':False,'thickness':1,'rgbcolor':(0, 0, 1)} |
|---|
| 2782 | | |
|---|
| 2783 | | def __repr__(self): |
|---|
| 2784 | | """ |
|---|
| 2785 | | Returns a string representation of this CircleFactory object. |
|---|
| 2786 | | |
|---|
| 2787 | | TESTS: |
|---|
| 2788 | | sage: circle |
|---|
| 2789 | | type circle? for help and examples |
|---|
| 2790 | | """ |
|---|
| 2791 | | return "type circle? for help and examples" |
|---|
| 2792 | | |
|---|
| 2793 | | |
|---|
| 2794 | | #an unique circle instance |
|---|
| 2795 | | circle = CircleFactory() |
|---|
| 2796 | | |
|---|
| 2797 | | class ContourPlotFactory(GraphicPrimitiveFactory): |
|---|
| | 2659 | options={'alpha':1,'fill':False,'thickness':1,'rgbcolor':(0, 0, 1)} |
|---|
| | 2660 | for k, v in kwds.iteritems(): |
|---|
| | 2661 | options[k] = v |
|---|
| | 2662 | |
|---|
| | 2663 | r = float(radius) |
|---|
| | 2664 | point = (float(point[0]), float(point[1])) |
|---|
| | 2665 | g = Graphics(xmin=point[0]-r, xmax=point[0]+r, ymin=point[1]-r, ymax=point[1]+r) |
|---|
| | 2666 | g._circle(point[0], point[1], r, options) |
|---|
| | 2667 | return g |
|---|
| | 2668 | |
|---|
| | 2669 | def contour_plot(f, xrange, yrange, **kwds): |
|---|
| 2869 | | def __call__(self, f, xrange, yrange, **kwds): |
|---|
| 2870 | | options = dict(self.options) |
|---|
| 2871 | | for k, v in kwds.iteritems(): |
|---|
| 2872 | | options[k] = v |
|---|
| 2873 | | |
|---|
| 2874 | | g, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f], xrange, yrange, options['plot_points']) |
|---|
| 2875 | | g = g[0] |
|---|
| 2876 | | xy_data_array = [[g(x, y) for x in \ |
|---|
| 2877 | | sage.misc.misc.xsrange(xrange[0], xrange[1], xstep)] |
|---|
| 2878 | | for y in sage.misc.misc.xsrange(yrange[0], yrange[1], ystep)] |
|---|
| 2879 | | |
|---|
| 2880 | | g = Graphics(xmin=float(xrange[0]), xmax=float(xrange[1]), ymin=float(yrange[0]), ymax=float(yrange[1])) |
|---|
| 2881 | | g._contour_plot(xy_data_array, xrange, yrange, options) |
|---|
| 2882 | | return g |
|---|
| 2883 | | |
|---|
| 2884 | | def _reset(self): |
|---|
| 2885 | | self.options={'plot_points':25, 'fill':True, 'cmap':'gray', 'contours':None} |
|---|
| 2886 | | |
|---|
| 2887 | | def __repr__(self): |
|---|
| 2888 | | """ |
|---|
| 2889 | | Returns a string representation of this ContourPlotFactory object. |
|---|
| 2890 | | |
|---|
| 2891 | | TESTS: |
|---|
| 2892 | | sage: contour_plot |
|---|
| 2893 | | type contour_plot? for help and examples |
|---|
| 2894 | | """ |
|---|
| 2895 | | return "type contour_plot? for help and examples" |
|---|
| 2896 | | |
|---|
| 2897 | | |
|---|
| 2898 | | #unique contour_plot instance |
|---|
| 2899 | | contour_plot = ContourPlotFactory() |
|---|
| 2900 | | |
|---|
| 2901 | | class ImplicitPlotFactory(ContourPlotFactory): |
|---|
| | 2741 | options = {'plot_points':25, 'fill':True, 'cmap':'gray', 'contours':None} |
|---|
| | 2742 | for k, v in kwds.iteritems(): |
|---|
| | 2743 | options[k] = v |
|---|
| | 2744 | |
|---|
| | 2745 | g, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f], xrange, yrange, options['plot_points']) |
|---|
| | 2746 | g = g[0] |
|---|
| | 2747 | xy_data_array = [[g(x, y) for x in \ |
|---|
| | 2748 | sage.misc.misc.xsrange(xrange[0], xrange[1], xstep)] |
|---|
| | 2749 | for y in sage.misc.misc.xsrange(yrange[0], yrange[1], ystep)] |
|---|
| | 2750 | |
|---|
| | 2751 | g = Graphics(xmin=float(xrange[0]), xmax=float(xrange[1]), ymin=float(yrange[0]), ymax=float(yrange[1])) |
|---|
| | 2752 | g._contour_plot(xy_data_array, xrange, yrange, options) |
|---|
| | 2753 | return g |
|---|
| | 2754 | |
|---|
| | 2755 | def implicit_plot(f, xrange, yrange, **kwds): |
|---|
| 2943 | | def _reset(self): |
|---|
| 2944 | | """ |
|---|
| 2945 | | Sets the default options for this ImplicitPlotFactory object. |
|---|
| 2946 | | |
|---|
| 2947 | | TESTS: |
|---|
| 2948 | | sage: implicit_plot._reset() |
|---|
| 2949 | | sage: implicit_plot.options['contours'] |
|---|
| 2950 | | (0.0,) |
|---|
| 2951 | | """ |
|---|
| 2952 | | self.options={'plot_points':25, 'fill':False, 'cmap':'gray', 'contours':(0.0,)} |
|---|
| 2953 | | |
|---|
| 2954 | | def __repr__(self): |
|---|
| 2955 | | """ |
|---|
| 2956 | | Returns a string representation of this ImplicitPlotFactory object. |
|---|
| 2957 | | |
|---|
| 2958 | | TESTS: |
|---|
| 2959 | | sage: implicit_plot |
|---|
| 2960 | | type implicit_plot? for help and examples |
|---|
| 2961 | | """ |
|---|
| 2962 | | return "type implicit_plot? for help and examples" |
|---|
| 2963 | | |
|---|
| 2964 | | #unique implicit_plot instance |
|---|
| 2965 | | implicit_plot = ImplicitPlotFactory() |
|---|
| 2966 | | |
|---|
| 2967 | | class LineFactory(GraphicPrimitiveFactory_from_point_list): |
|---|
| | 2797 | options = {'plot_points':25, 'fill':False, 'cmap':'gray', 'contours':(0.0,)} |
|---|
| | 2798 | options.update(kwds) |
|---|
| | 2799 | return contour_plot(f, xrange, yrange, **kwds) |
|---|
| | 2800 | |
|---|
| | 2801 | def line(points, **kwds): |
|---|
| 3067 | | """ |
|---|
| 3068 | | def _reset(self): |
|---|
| 3069 | | self.options = {'alpha':1,'rgbcolor':(0,0,1),'thickness':1} |
|---|
| 3070 | | |
|---|
| 3071 | | def __repr__(self): |
|---|
| 3072 | | """ |
|---|
| 3073 | | Returns a string representation of this LineFactory object. |
|---|
| 3074 | | |
|---|
| 3075 | | TESTS: |
|---|
| 3076 | | sage: line |
|---|
| 3077 | | type line? for help and examples |
|---|
| 3078 | | """ |
|---|
| 3079 | | return "type line? for help and examples" |
|---|
| 3080 | | |
|---|
| 3081 | | def _from_xdata_ydata(self, xdata, ydata, coerce, options): |
|---|
| 3082 | | """ |
|---|
| 3083 | | TESTS: |
|---|
| 3084 | | We test to make sure that the x/y min/max data are set correctly. |
|---|
| 3085 | | sage: l = line([(100, 100), (120, 120)]) |
|---|
| 3086 | | sage: l.xmin() |
|---|
| 3087 | | 100.0 |
|---|
| 3088 | | sage: l.xmax() |
|---|
| 3089 | | 120.0 |
|---|
| 3090 | | """ |
|---|
| 3091 | | if coerce: |
|---|
| 3092 | | xdata, ydata = self._coerce(xdata, ydata) |
|---|
| 3093 | | |
|---|
| 3094 | | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| 3095 | | g._Graphics__objects.append(GraphicPrimitive_Line(xdata, ydata, options)) |
|---|
| 3096 | | return g |
|---|
| 3097 | | |
|---|
| 3098 | | def _graphic3d(self): |
|---|
| 3099 | | from sage.plot.plot3d.shapes2 import line3d |
|---|
| 3100 | | return line3d |
|---|
| 3101 | | |
|---|
| 3102 | | # unique line instance |
|---|
| 3103 | | line = LineFactory() |
|---|
| 3104 | | |
|---|
| 3105 | | class MatrixPlotFactory(GraphicPrimitiveFactory): |
|---|
| | 2901 | |
|---|
| | 2902 | TESTS: |
|---|
| | 2903 | We test to make sure that the x/y min/max data are set correctly. |
|---|
| | 2904 | sage: l = line([(100, 100), (120, 120)]) |
|---|
| | 2905 | sage: l.xmin() |
|---|
| | 2906 | 100.0 |
|---|
| | 2907 | sage: l.xmax() |
|---|
| | 2908 | 120.0 |
|---|
| | 2909 | |
|---|
| | 2910 | """ |
|---|
| | 2911 | options = {'alpha':1,'rgbcolor':(0,0,1),'thickness':1} |
|---|
| | 2912 | options.update(kwds) |
|---|
| | 2913 | |
|---|
| | 2914 | xdata, ydata = xydata_from_point_list(points) |
|---|
| | 2915 | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| | 2916 | g._Graphics__objects.append(GraphicPrimitive_Line(xdata, ydata, options)) |
|---|
| | 2917 | return g |
|---|
| | 2918 | |
|---|
| | 2919 | |
|---|
| | 2920 | def matrix_plot(mat, **kwds): |
|---|
| 3131 | | def __call__(self, mat, **kwds): |
|---|
| 3132 | | from sage.matrix.all import is_Matrix |
|---|
| 3133 | | from matplotlib.numerix import array |
|---|
| 3134 | | if not is_Matrix(mat) or (isinstance(mat, (list, tuple)) and isinstance(mat[0], (list, tuple))): |
|---|
| 3135 | | raise TypeError, "mat must be of type Matrix or a two dimensional array" |
|---|
| 3136 | | options = dict(self.options) |
|---|
| 3137 | | for k, v in kwds.iteritems(): |
|---|
| 3138 | | options[k] = v |
|---|
| 3139 | | if is_Matrix(mat): |
|---|
| 3140 | | xrange = (0, mat.ncols()) |
|---|
| 3141 | | yrange = (0, mat.nrows()) |
|---|
| 3142 | | else: |
|---|
| 3143 | | xrange = (0, len(mat[0])) |
|---|
| 3144 | | yrange = (0, len(mat)) |
|---|
| 3145 | | xy_data_array = [array(r, dtype=float) for r in mat] |
|---|
| 3146 | | |
|---|
| 3147 | | g = Graphics() |
|---|
| 3148 | | g._matrix_plot(xy_data_array, xrange, yrange, options) |
|---|
| 3149 | | return g |
|---|
| 3150 | | |
|---|
| 3151 | | def _reset(self): |
|---|
| 3152 | | self.options={'cmap':'gray'} |
|---|
| 3153 | | |
|---|
| 3154 | | def __repr__(self): |
|---|
| 3155 | | """ |
|---|
| 3156 | | Returns a string representation of this MatrixPlotFactory object. |
|---|
| 3157 | | |
|---|
| 3158 | | TESTS: |
|---|
| 3159 | | sage: matrix_plot |
|---|
| 3160 | | type matrix_plot? for help and examples |
|---|
| 3161 | | """ |
|---|
| 3162 | | return "type matrix_plot? for help and examples" |
|---|
| 3163 | | |
|---|
| 3164 | | |
|---|
| 3165 | | #unique matrix_plot instance |
|---|
| 3166 | | matrix_plot = MatrixPlotFactory() |
|---|
| | 2946 | options = {'cmap':'gray'} |
|---|
| | 2947 | options.update(kwds) |
|---|
| | 2948 | |
|---|
| | 2949 | from sage.matrix.all import is_Matrix |
|---|
| | 2950 | from matplotlib.numerix import array |
|---|
| | 2951 | if not is_Matrix(mat) or (isinstance(mat, (list, tuple)) and isinstance(mat[0], (list, tuple))): |
|---|
| | 2952 | raise TypeError, "mat must be of type Matrix or a two dimensional array" |
|---|
| | 2953 | |
|---|
| | 2954 | if is_Matrix(mat): |
|---|
| | 2955 | xrange = (0, mat.ncols()) |
|---|
| | 2956 | yrange = (0, mat.nrows()) |
|---|
| | 2957 | else: |
|---|
| | 2958 | xrange = (0, len(mat[0])) |
|---|
| | 2959 | yrange = (0, len(mat)) |
|---|
| | 2960 | xy_data_array = [array(r, dtype=float) for r in mat] |
|---|
| | 2961 | |
|---|
| | 2962 | g = Graphics() |
|---|
| | 2963 | g._matrix_plot(xy_data_array, xrange, yrange, options) |
|---|
| | 2964 | return g |
|---|
| | 2965 | |
|---|
| | 2966 | |
|---|
| 3202 | | def __call__(self, (f, g), xrange, yrange, **kwds): |
|---|
| 3203 | | options = dict(self.options) |
|---|
| 3204 | | for k, v in kwds.iteritems(): |
|---|
| 3205 | | options[k] = v |
|---|
| 3206 | | z, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f,g], xrange, yrange, options['plot_points']) |
|---|
| 3207 | | f,g = z |
|---|
| 3208 | | |
|---|
| 3209 | | xpos_array, ypos_array, xvec_array, yvec_array = [],[],[],[] |
|---|
| 3210 | | for x in sage.misc.misc.xsrange(xrange[0], xrange[1], xstep): |
|---|
| 3211 | | for y in sage.misc.misc.xsrange(yrange[0], yrange[1], ystep): |
|---|
| 3212 | | xpos_array.append(x) |
|---|
| 3213 | | ypos_array.append(y) |
|---|
| 3214 | | xvec_array.append(f(x,y)) |
|---|
| 3215 | | yvec_array.append(g(x,y)) |
|---|
| 3216 | | |
|---|
| 3217 | | import numpy |
|---|
| 3218 | | xvec_array = numpy.array(xvec_array, dtype=float) |
|---|
| 3219 | | yvec_array = numpy.array(yvec_array, dtype=float) |
|---|
| 3220 | | g = Graphics(xmin=xrange[0], xmax=xrange[1], ymin=yrange[0], ymax=yrange[1]) |
|---|
| 3221 | | g._plot_field(xpos_array, ypos_array, xvec_array, yvec_array, xrange, yrange, options) |
|---|
| 3222 | | return g |
|---|
| 3223 | | |
|---|
| 3224 | | def _reset(self): |
|---|
| 3225 | | self.options={'plot_points':20, 'cmap':'gray'} |
|---|
| 3226 | | |
|---|
| 3227 | | def _repr_(self): |
|---|
| 3228 | | return "type plot_vector_field? for help and examples" |
|---|
| 3229 | | |
|---|
| 3230 | | #unique plot_vector_field instance |
|---|
| 3231 | | plot_vector_field = PlotFieldFactory() |
|---|
| 3232 | | |
|---|
| 3233 | | |
|---|
| 3234 | | class DiskFactory(GraphicPrimitiveFactory): |
|---|
| | 3002 | options = {'plot_points':20, 'cmap':'gray'} |
|---|
| | 3003 | options.update(kwds) |
|---|
| | 3004 | |
|---|
| | 3005 | z, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f,g], xrange, yrange, options['plot_points']) |
|---|
| | 3006 | f,g = z |
|---|
| | 3007 | |
|---|
| | 3008 | xpos_array, ypos_array, xvec_array, yvec_array = [],[],[],[] |
|---|
| | 3009 | for x in sage.misc.misc.xsrange(xrange[0], xrange[1], xstep): |
|---|
| | 3010 | for y in sage.misc.misc.xsrange(yrange[0], yrange[1], ystep): |
|---|
| | 3011 | xpos_array.append(x) |
|---|
| | 3012 | ypos_array.append(y) |
|---|
| | 3013 | xvec_array.append(f(x,y)) |
|---|
| | 3014 | yvec_array.append(g(x,y)) |
|---|
| | 3015 | |
|---|
| | 3016 | import numpy |
|---|
| | 3017 | xvec_array = numpy.array(xvec_array, dtype=float) |
|---|
| | 3018 | yvec_array = numpy.array(yvec_array, dtype=float) |
|---|
| | 3019 | g = Graphics(xmin=xrange[0], xmax=xrange[1], ymin=yrange[0], ymax=yrange[1]) |
|---|
| | 3020 | g._plot_field(xpos_array, ypos_array, xvec_array, yvec_array, xrange, yrange, options) |
|---|
| | 3021 | return g |
|---|
| | 3022 | |
|---|
| | 3023 | |
|---|
| | 3024 | def disk(point, radius, angle, **kwds): |
|---|
| 3261 | | def __call__(self, point, radius, angle, **kwds): |
|---|
| 3262 | | options = dict(self.options) |
|---|
| 3263 | | for k, v in kwds.iteritems(): |
|---|
| 3264 | | options[k] = v |
|---|
| 3265 | | |
|---|
| 3266 | | r = float(radius) |
|---|
| 3267 | | point = (float(point[0]), float(point[1])) |
|---|
| 3268 | | angle = (float(angle[0]), float(angle[1])) |
|---|
| 3269 | | |
|---|
| 3270 | | xmin = point[0] - r |
|---|
| 3271 | | xmax = point[0] + r |
|---|
| 3272 | | ymin = point[1] - r |
|---|
| 3273 | | ymax = point[1] + r |
|---|
| 3274 | | g = Graphics(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) |
|---|
| 3275 | | g._disk(point, r, angle, options) |
|---|
| 3276 | | return g |
|---|
| 3277 | | |
|---|
| 3278 | | def _reset(self): |
|---|
| 3279 | | self.options={'alpha':1,'fill':True,'rgbcolor':(0,0,1),'thickness':0} |
|---|
| 3280 | | |
|---|
| 3281 | | def __repr__(self): |
|---|
| 3282 | | """ |
|---|
| 3283 | | Returns a string representation of this DiskFactory object. |
|---|
| 3284 | | |
|---|
| 3285 | | TESTS: |
|---|
| 3286 | | sage: disk |
|---|
| 3287 | | type disk? for help and examples |
|---|
| 3288 | | """ |
|---|
| 3289 | | return "type disk? for help and examples" |
|---|
| 3290 | | |
|---|
| 3291 | | #an unique disk instance |
|---|
| 3292 | | disk = DiskFactory() |
|---|
| 3293 | | |
|---|
| 3294 | | class PointFactory(GraphicPrimitiveFactory_from_point_list): |
|---|
| | 3051 | options = {'alpha':1,'fill':True,'rgbcolor':(0,0,1),'thickness':0} |
|---|
| | 3052 | options.update(kwds) |
|---|
| | 3053 | |
|---|
| | 3054 | r = float(radius) |
|---|
| | 3055 | point = (float(point[0]), float(point[1])) |
|---|
| | 3056 | angle = (float(angle[0]), float(angle[1])) |
|---|
| | 3057 | |
|---|
| | 3058 | xmin = point[0] - r |
|---|
| | 3059 | xmax = point[0] + r |
|---|
| | 3060 | ymin = point[1] - r |
|---|
| | 3061 | ymax = point[1] + r |
|---|
| | 3062 | g = Graphics(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) |
|---|
| | 3063 | g._disk(point, r, angle, options) |
|---|
| | 3064 | return g |
|---|
| | 3065 | |
|---|
| | 3066 | def point(points, **kwds): |
|---|
| 3317 | | def _reset(self): |
|---|
| 3318 | | self.options = {'alpha':1,'pointsize':10,'faceted':False,'rgbcolor':(0,0,1)} |
|---|
| 3319 | | |
|---|
| 3320 | | def __repr__(self): |
|---|
| 3321 | | """ |
|---|
| 3322 | | Returns a string representation of this PointFactory object. |
|---|
| 3323 | | |
|---|
| 3324 | | TESTS: |
|---|
| 3325 | | sage: point |
|---|
| 3326 | | type point? for help and examples |
|---|
| 3327 | | """ |
|---|
| 3328 | | return "type point? for help and examples" |
|---|
| 3329 | | |
|---|
| 3330 | | def _from_xdata_ydata(self, xdata, ydata, coerce, options): |
|---|
| 3331 | | if coerce: |
|---|
| 3332 | | xdata, ydata = self._coerce(xdata, ydata) |
|---|
| 3333 | | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| 3334 | | g._Graphics__objects.append(GraphicPrimitive_Point(xdata, ydata, options)) |
|---|
| 3335 | | return g |
|---|
| 3336 | | |
|---|
| 3337 | | # unique point instance |
|---|
| 3338 | | point = PointFactory() |
|---|
| | 3089 | options = {'alpha':1,'pointsize':10,'faceted':False,'rgbcolor':(0,0,1)} |
|---|
| | 3090 | options.update(kwds) |
|---|
| | 3091 | |
|---|
| | 3092 | xdata, ydata = xydata_from_point_list(points) |
|---|
| | 3093 | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| | 3094 | g._Graphics__objects.append(GraphicPrimitive_Point(xdata, ydata, options)) |
|---|
| | 3095 | return g |
|---|
| | 3096 | |
|---|
| 3412 | | def _reset(self): |
|---|
| 3413 | | self.options={'alpha':1,'rgbcolor':(0,0,1),'thickness':0} |
|---|
| 3414 | | |
|---|
| 3415 | | def __repr__(self): |
|---|
| 3416 | | """ |
|---|
| 3417 | | Returns a string representation of this PolygonFactory object. |
|---|
| 3418 | | |
|---|
| 3419 | | TESTS: |
|---|
| 3420 | | sage: polygon |
|---|
| 3421 | | Sage polygon; type polygon? for help and examples |
|---|
| 3422 | | """ |
|---|
| 3423 | | return "Sage polygon; type polygon? for help and examples" |
|---|
| 3424 | | |
|---|
| 3425 | | def _from_xdata_ydata(self, xdata, ydata, coerce, options): |
|---|
| 3426 | | if coerce: |
|---|
| 3427 | | xdata, ydata = self._coerce(xdata, ydata) |
|---|
| 3428 | | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| 3429 | | g._Graphics__objects.append(GraphicPrimitive_Polygon(xdata, ydata, options)) |
|---|
| 3430 | | return g |
|---|
| 3431 | | |
|---|
| 3432 | | # unique polygon instance |
|---|
| 3433 | | polygon = PolygonFactory() |
|---|
| 3434 | | |
|---|
| 3435 | | class PlotFactory(GraphicPrimitiveFactory): |
|---|
| | 3169 | options = {'alpha':1,'rgbcolor':(0,0,1),'thickness':0} |
|---|
| | 3170 | options.update(kwds) |
|---|
| | 3171 | |
|---|
| | 3172 | xdata, ydata = xydata_from_point_list(points) |
|---|
| | 3173 | g = Graphics(**minmax_data(xdata, ydata, dict=True)) |
|---|
| | 3174 | g._Graphics__objects.append(GraphicPrimitive_Polygon(xdata, ydata, options)) |
|---|
| | 3175 | return g |
|---|
| | 3176 | |
|---|
| | 3177 | def plot(funcs, *args, **kwds): |
|---|
| 3576 | | |
|---|
| 3577 | | """ |
|---|
| 3578 | | def _reset(self): |
|---|
| 3579 | | o = self.options |
|---|
| 3580 | | o['plot_points'] = 200 |
|---|
| 3581 | | o['plot_division'] = 1000 |
|---|
| 3582 | | o['max_bend'] = 0.1 |
|---|
| 3583 | | o['rgbcolor'] = (0,0,1) |
|---|
| 3584 | | |
|---|
| 3585 | | def __repr__(self): |
|---|
| 3586 | | """ |
|---|
| 3587 | | Returns a string representation of this PlotFactory object. |
|---|
| 3588 | | |
|---|
| 3589 | | TESTS: |
|---|
| 3590 | | sage: plot |
|---|
| 3591 | | type plot? for help and examples |
|---|
| 3592 | | """ |
|---|
| 3593 | | return "type plot? for help and examples" |
|---|
| 3594 | | |
|---|
| 3595 | | def __call__(self, funcs, *args, **kwds): |
|---|
| 3596 | | do_show = False |
|---|
| 3597 | | if kwds.has_key('show') and kwds['show']: |
|---|
| 3598 | | do_show = True |
|---|
| 3599 | | del kwds['show'] |
|---|
| 3600 | | if hasattr(funcs, 'plot'): |
|---|
| 3601 | | G = funcs.plot(*args, **kwds) |
|---|
| 3602 | | # if we are using the generic plotting method |
|---|
| 3603 | | else: |
|---|
| 3604 | | n = len(args) |
|---|
| 3605 | | # if there are no extra args, pick some silly default |
|---|
| 3606 | | if n == 0: |
|---|
| 3607 | | G = self._call(funcs, (-1, 1), *args, **kwds) |
|---|
| 3608 | | # if there is one extra arg, then it had better be a tuple |
|---|
| 3609 | | elif n == 1: |
|---|
| 3610 | | G = self._call(funcs, *args, **kwds) |
|---|
| 3611 | | elif n == 2: |
|---|
| 3612 | | # if there are two extra args, then pull them out and pass them as a tuple |
|---|
| 3613 | | xmin = args[0] |
|---|
| 3614 | | xmax = args[1] |
|---|
| 3615 | | args = args[2:] |
|---|
| 3616 | | G = self._call(funcs, (xmin, xmax), *args, **kwds) |
|---|
| 3617 | | else: |
|---|
| 3618 | | sage.misc.misc.verbose("there were %s extra arguments (besides %s)" % (n, funcs), level=0) |
|---|
| 3619 | | if do_show: |
|---|
| 3620 | | G.show() |
|---|
| 3621 | | return G |
|---|
| 3622 | | |
|---|
| 3623 | | def _call(self, funcs, xrange, parametric=False, |
|---|
| | 3318 | |
|---|
| | 3319 | We check to make sure that the x/y min/max data get set correctly |
|---|
| | 3320 | when there are multiple functions. |
|---|
| | 3321 | |
|---|
| | 3322 | sage: p = plot([sin(x), cos(x)], 100, 120) |
|---|
| | 3323 | sage: p.xmin() |
|---|
| | 3324 | 100.0 |
|---|
| | 3325 | sage: p.xmax() |
|---|
| | 3326 | 120.0 |
|---|
| | 3327 | """ |
|---|
| | 3328 | do_show = False |
|---|
| | 3329 | if kwds.has_key('show') and kwds['show']: |
|---|
| | 3330 | do_show = True |
|---|
| | 3331 | del kwds['show'] |
|---|
| | 3332 | if hasattr(funcs, 'plot'): |
|---|
| | 3333 | G = funcs.plot(*args, **kwds) |
|---|
| | 3334 | # if we are using the generic plotting method |
|---|
| | 3335 | else: |
|---|
| | 3336 | n = len(args) |
|---|
| | 3337 | # if there are no extra args, pick some silly default |
|---|
| | 3338 | if n == 0: |
|---|
| | 3339 | G = _plot(funcs, (-1, 1), *args, **kwds) |
|---|
| | 3340 | # if there is one extra arg, then it had better be a tuple |
|---|
| | 3341 | elif n == 1: |
|---|
| | 3342 | G = _plot(funcs, *args, **kwds) |
|---|
| | 3343 | elif n == 2: |
|---|
| | 3344 | # if there are two extra args, then pull them out and pass them as a tuple |
|---|
| | 3345 | xmin = args[0] |
|---|
| | 3346 | xmax = args[1] |
|---|
| | 3347 | args = args[2:] |
|---|
| | 3348 | G = _plot(funcs, (xmin, xmax), *args, **kwds) |
|---|
| | 3349 | else: |
|---|
| | 3350 | sage.misc.misc.verbose("there were %s extra arguments (besides %s)" % (n, funcs), level=0) |
|---|
| | 3351 | if do_show: |
|---|
| | 3352 | G.show() |
|---|
| | 3353 | return G |
|---|
| | 3354 | |
|---|
| | 3355 | def _plot(funcs, xrange, parametric=False, |
|---|
| 3625 | | options = dict(self.options) |
|---|
| 3626 | | """ |
|---|
| 3627 | | TESTS: |
|---|
| 3628 | | We check to make sure that the x/y min/max data get set correctly |
|---|
| 3629 | | when there are multiple functions. |
|---|
| 3630 | | |
|---|
| 3631 | | sage: p = plot([sin(x), cos(x)], 100, 120) |
|---|
| 3632 | | sage: p.xmin() |
|---|
| 3633 | | 100.0 |
|---|
| 3634 | | sage: p.xmax() |
|---|
| 3635 | | 120.0 |
|---|
| 3636 | | """ |
|---|
| 3637 | | if kwds.has_key('color') and not kwds.has_key('rgbcolor'): |
|---|
| 3638 | | kwds['rgbcolor'] = kwds['color'] |
|---|
| 3639 | | del kwds['color'] |
|---|
| 3640 | | for k, v in kwds.iteritems(): |
|---|
| 3641 | | options[k] = v |
|---|
| 3642 | | |
|---|
| 3643 | | #parametric_plot will be a list or tuple of two functions (f,g) |
|---|
| 3644 | | #and will plotted as (f(x), g(x)) for all x in the given range |
|---|
| 3645 | | if parametric: |
|---|
| 3646 | | if len(funcs) == 3: |
|---|
| 3647 | | raise ValueError, "use parametric_plot3d for parametric plots in 3d dimensions." |
|---|
| 3648 | | elif len(funcs) == 2: |
|---|
| 3649 | | # 2d |
|---|
| 3650 | | f,g = funcs |
|---|
| 3651 | | else: |
|---|
| 3652 | | raise ValueError, "parametric plots only implemented in 2 and 3 dimensions." |
|---|
| 3653 | | |
|---|
| 3654 | | #or we have only a single function to be plotted: |
|---|
| 3655 | | else: |
|---|
| 3656 | | f = funcs |
|---|
| 3657 | | |
|---|
| 3658 | | plot_points = int(options['plot_points']) |
|---|
| 3659 | | del options['plot_points'] |
|---|
| 3660 | | x, data = var_and_list_of_values(xrange, plot_points) |
|---|
| 3661 | | data = list(data) |
|---|
| 3662 | | xmin = data[0] |
|---|
| 3663 | | xmax = data[-1] |
|---|
| 3664 | | |
|---|
| 3665 | | #check to see if funcs is a list of functions that will |
|---|
| 3666 | | #be all plotted together. |
|---|
| 3667 | | if isinstance(funcs, (list, tuple)) and not parametric: |
|---|
| 3668 | | return reduce(operator.add, (plot(f, (xmin, xmax), polar=polar, **kwds) for f in funcs)) |
|---|
| 3669 | | |
|---|
| 3670 | | if len(data) >= 2: |
|---|
| 3671 | | delta = data[1]-data[0] |
|---|
| 3672 | | else: |
|---|
| 3673 | | delta = 0 |
|---|
| 3674 | | |
|---|
| 3675 | | random = current_randstate().python_random().random |
|---|
| 3676 | | exceptions = 0; msg='' |
|---|
| 3677 | | exception_indices = [] |
|---|
| 3678 | | for i in range(len(data)): |
|---|
| 3679 | | xi = data[i] |
|---|
| 3680 | | # Slightly randomize the interior sample points if |
|---|
| 3681 | | # randomize is true |
|---|
| 3682 | | if i > 0 and i < plot_points-1: |
|---|
| 3683 | | if randomize: |
|---|
| 3684 | | xi += delta*random() |
|---|
| 3685 | | if xi > xmax: |
|---|
| 3686 | | xi = xmax |
|---|
| 3687 | | elif i == plot_points-1: |
|---|
| 3688 | | xi = xmax # guarantee that we get the last point. |
|---|
| 3689 | | |
|---|
| 3690 | | try: |
|---|
| 3691 | | data[i] = (float(xi), float(f(xi))) |
|---|
| 3692 | | except (ZeroDivisionError, TypeError, ValueError, OverflowError), msg: |
|---|
| | 3357 | options = {'alpha':1,'thickness':1,'rgbcolor':(0,0,1), |
|---|
| | 3358 | 'plot_points':200, 'plot_division':1000, |
|---|
| | 3359 | 'max_bend': 0.1, 'rgbcolor': (0,0,1) } |
|---|
| | 3360 | |
|---|
| | 3361 | if kwds.has_key('color') and not kwds.has_key('rgbcolor'): |
|---|
| | 3362 | kwds['rgbcolor'] = kwds['color'] |
|---|
| | 3363 | del kwds['color'] |
|---|
| | 3364 | |
|---|
| | 3365 | options.update(kwds) |
|---|
| | 3366 | |
|---|
| | 3367 | #parametric_plot will be a list or tuple of two functions (f,g) |
|---|
| | 3368 | #and will plotted as (f(x), g(x)) for all x in the given range |
|---|
| | 3369 | if parametric: |
|---|
| | 3370 | if len(funcs) == 3: |
|---|
| | 3371 | raise ValueError, "use parametric_plot3d for parametric plots in 3d dimensions." |
|---|
| | 3372 | elif len(funcs) == 2: |
|---|
| | 3373 | # 2d |
|---|
| | 3374 | f,g = funcs |
|---|
| | 3375 | else: |
|---|
| | 3376 | raise ValueError, "parametric plots only implemented in 2 and 3 dimensions." |
|---|
| | 3377 | |
|---|
| | 3378 | #or we have only a single function to be plotted: |
|---|
| | 3379 | else: |
|---|
| | 3380 | f = funcs |
|---|
| | 3381 | |
|---|
| | 3382 | plot_points = int(options['plot_points']) |
|---|
| | 3383 | del options['plot_points'] |
|---|
| | 3384 | x, data = var_and_list_of_values(xrange, plot_points) |
|---|
| | 3385 | data = list(data) |
|---|
| | 3386 | xmin = data[0] |
|---|
| | 3387 | xmax = data[-1] |
|---|
| | 3388 | |
|---|
| | 3389 | #check to see if funcs is a list of functions that will |
|---|
| | 3390 | #be all plotted together. |
|---|
| | 3391 | if isinstance(funcs, (list, tuple)) and not parametric: |
|---|
| | 3392 | return reduce(operator.add, (plot(f, (xmin, xmax), polar=polar, **kwds) for f in funcs)) |
|---|
| | 3393 | |
|---|
| | 3394 | if len(data) >= 2: |
|---|
| | 3395 | delta = data[1]-data[0] |
|---|
| | 3396 | else: |
|---|
| | 3397 | delta = 0 |
|---|
| | 3398 | |
|---|
| | 3399 | random = current_randstate().python_random().random |
|---|
| | 3400 | exceptions = 0; msg='' |
|---|
| | 3401 | exception_indices = [] |
|---|
| | 3402 | for i in range(len(data)): |
|---|
| | 3403 | xi = data[i] |
|---|
| | 3404 | # Slightly randomize the interior sample points if |
|---|
| | 3405 | # randomize is true |
|---|
| | 3406 | if i > 0 and i < plot_points-1: |
|---|
| | 3407 | if randomize: |
|---|
| | 3408 | xi += delta*random() |
|---|
| | 3409 | if xi > xmax: |
|---|
| | 3410 | xi = xmax |
|---|
| | 3411 | elif i == plot_points-1: |
|---|
| | 3412 | xi = xmax # guarantee that we get the last point. |
|---|
| | 3413 | |
|---|
| | 3414 | try: |
|---|
| | 3415 | data[i] = (float(xi), float(f(xi))) |
|---|
| | 3416 | except (ZeroDivisionError, TypeError, ValueError, OverflowError), msg: |
|---|
| | 3417 | sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x),1) |
|---|
| | 3418 | exceptions += 1 |
|---|
| | 3419 | exception_indices.append(i) |
|---|
| | 3420 | |
|---|
| | 3421 | if str(data[i][1]) in ['nan', 'NaN']: |
|---|
| | 3422 | sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x),1) |
|---|
| | 3423 | exceptions += 1 |
|---|
| | 3424 | exception_indices.append(i) |
|---|
| | 3425 | |
|---|
| | 3426 | data = [data[i] for i in range(len(data)) if i not in exception_indices] |
|---|
| | 3427 | |
|---|
| | 3428 | # adaptive refinement |
|---|
| | 3429 | i, j = 0, 0 |
|---|
| | 3430 | max_bend = float(options['max_bend']) |
|---|
| | 3431 | del options['max_bend'] |
|---|
| | 3432 | plot_division = int(options['plot_division']) |
|---|
| | 3433 | del options['plot_division'] |
|---|
| | 3434 | while i < len(data) - 1: |
|---|
| | 3435 | if abs(data[i+1][1] - data[i][1]) > max_bend: |
|---|
| | 3436 | x = float((data[i+1][0] + data[i][0])/2) |
|---|
| | 3437 | try: |
|---|
| | 3438 | y = float(f(x)) |
|---|
| | 3439 | data.insert(i+1, (x, y)) |
|---|
| | 3440 | except (ZeroDivisionError, TypeError, ValueError), msg: |
|---|
| 3695 | | exception_indices.append(i) |
|---|
| 3696 | | |
|---|
| 3697 | | if str(data[i][1]) in ['nan', 'NaN']: |
|---|
| 3698 | | sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x),1) |
|---|
| 3699 | | exceptions += 1 |
|---|
| 3700 | | exception_indices.append(i) |
|---|
| 3701 | | |
|---|
| 3702 | | data = [data[i] for i in range(len(data)) if i not in exception_indices] |
|---|
| 3703 | | |
|---|
| 3704 | | # adaptive refinement |
|---|
| 3705 | | i, j = 0, 0 |
|---|
| 3706 | | max_bend = float(options['max_bend']) |
|---|
| 3707 | | del options['max_bend'] |
|---|
| 3708 | | plot_division = int(options['plot_division']) |
|---|
| 3709 | | del options['plot_division'] |
|---|
| 3710 | | while i < len(data) - 1: |
|---|
| 3711 | | if abs(data[i+1][1] - data[i][1]) > max_bend: |
|---|
| 3712 | | x = float((data[i+1][0] + data[i][0])/2) |
|---|
| 3713 | | try: |
|---|
| 3714 | | y = float(f(x)) |
|---|
| 3715 | | data.insert(i+1, (x, y)) |
|---|
| 3716 | | except (ZeroDivisionError, TypeError, ValueError), msg: |
|---|
| 3717 | | sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x),1) |
|---|
| 3718 | | exceptions += 1 |
|---|
| 3719 | | j += 1 |
|---|
| 3720 | | if j > plot_division: |
|---|
| 3721 | | break |
|---|
| 3722 | | else: |
|---|
| 3723 | | i += 1 |
|---|
| 3724 | | |
|---|
| 3725 | | if (len(data) == 0 and exceptions > 0) or exceptions > 10: |
|---|
| 3726 | | sage.misc.misc.verbose("WARNING: When plotting, failed to evaluate function at %s points."%exceptions, level=0) |
|---|
| 3727 | | sage.misc.misc.verbose("Last error message: '%s'"%msg, level=0) |
|---|
| 3728 | | if parametric: |
|---|
| 3729 | | data = [(fdata, g(x)) for x, fdata in data] |
|---|
| 3730 | | if polar: |
|---|
| 3731 | | data = [(y*cos(x), y*sin(x)) for x, y in data] |
|---|
| 3732 | | G = line(data, coerce=False, **options) |
|---|
| 3733 | | |
|---|
| 3734 | | # Label? |
|---|
| 3735 | | if label: |
|---|
| 3736 | | label = ' '+str(label) |
|---|
| 3737 | | G += text(label, data[-1], horizontal_alignment='left', |
|---|
| 3738 | | vertical_alignment='center') |
|---|
| 3739 | | |
|---|
| 3740 | | return G |
|---|
| 3741 | | |
|---|
| 3742 | | # unique plot instance |
|---|
| 3743 | | plot = PlotFactory() |
|---|
| 3744 | | |
|---|
| 3745 | | |
|---|
| 3746 | | class TextFactory(GraphicPrimitiveFactory): |
|---|
| | 3443 | j += 1 |
|---|
| | 3444 | if j > plot_division: |
|---|
| | 3445 | break |
|---|
| | 3446 | else: |
|---|
| | 3447 | i += 1 |
|---|
| | 3448 | |
|---|
| | 3449 | if (len(data) == 0 and exceptions > 0) or exceptions > 10: |
|---|
| | 3450 | sage.misc.misc.verbose("WARNING: When plotting, failed to evaluate function |
|---|