Ticket #3853: trac_3853.patch

File trac_3853.patch, 40.1 kB (added by mhansen, 5 months ago)
  • a/sage/calculus/desolvers.py

    old new  
    3535########################################################################## 
    3636 
    3737from sage.interfaces.maxima import MaximaElement, Maxima 
    38 from sage.plot.plot import LineFactory 
    39 line = LineFactory() 
     38from sage.plot.plot import line 
    4039 
    4140maxima = Maxima() 
    4241 
  • a/sage/groups/perm_gps/cubegroup.py

    old new  
    7777from sage.rings.finite_field import FiniteField as GF 
    7878from sage.rings.arith import factor 
    7979from sage.groups.abelian_gps.abelian_group import AbelianGroup 
    80 from sage.plot.plot import PolygonFactory, TextFactory 
    81 polygon = PolygonFactory() 
    82 text = TextFactory() 
     80from sage.plot.plot import polygon, text 
    8381from sage.calculus.calculus import sin, cos 
    8482pi = RDF.pi() 
    8583 
  • a/sage/gsl/dft.py

    old new  
    5353########################################################################## 
    5454 
    5555from sage.rings.number_field.number_field import CyclotomicField 
    56 from sage.plot.plot import PolygonFactory, line 
     56from sage.plot.plot import polygon, line 
    5757from sage.plot.plot import (Graphics, polygon) 
    5858from sage.groups.abelian_gps.dual_abelian_group import DualAbelianGroup 
    5959from sage.groups.abelian_gps.abelian_group import AbelianGroup 
  • a/sage/plot/plot.py

    old new  
    901901        g.__aspect_ratio = max(self.__aspect_ratio, other.__aspect_ratio) 
    902902        return g 
    903903   
     904    def add_primitive(self, primitive): 
     905        """ 
     906        Adds a primitive to this graphics object. 
     907        """ 
     908        self.__objects.append(primitive) 
     909 
    904910    def _arrow(self, xmin, ymin, xmax, ymax, options): 
    905911        """ 
    906912        Add an arrow with given bounding box to this graphics object. 
     
    9961002        ymax = point[1] + r 
    9971003        self.__objects.append(GraphicPrimitive_Disk(point, r, angle, options)) 
    9981004        self._extend_axes(xmin, xmax, ymin, ymax) 
    999  
    1000     def _line(self, xdata, ydata, options): 
    1001         """ 
    1002         Add a line to this graphics object. 
    1003  
    1004         (For internal use -- you should just use addition.) 
    1005  
    1006         INPUT: 
    1007             xdata -- list of floats; the x coordinates of points in the data 
    1008             ydata -- list of floats; the y coordinates of points in the data 
    1009             options -- dictionary of options 
    1010         """ 
    1011         self.__objects.append(GraphicPrimitive_Line(xdata, ydata, options)) 
    1012         self._extend_axes(*minmax_data(xdata, ydata)) 
    10131005 
    10141006      
    10151007    def _matrix_plot(self, xy_data_array, xrange, yrange, options): 
     
    25092501                    labels[v] = str(v) 
    25102502                NX.draw_networkx_labels(self.__nxg, self.__pos, labels=labels, ax=subplot) 
    25112503 
    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. 
    25622507# 
    25632508# It exists because it provides the following functionality: 
    25642509# Allows user to give as input to the function 'point' 
     
    25692514# x-values in one list and all the y-values in another list. 
    25702515# This is needed to be done because that is how the input is 
    25712516# taken in the matplotlib function 'scatter'. 
    2572 class GraphicPrimitiveFactory_from_point_list(GraphicPrimitiveFactory): 
    2573     def __call__(self, points, coerce=True, **kwds): 
    2574         try: 
    2575             return points.plot(**kwds) 
    2576         except AttributeError: 
     2517def xydata_from_point_list(points): 
     2518    if not isinstance(points, (list,tuple)) or \ 
     2519       (isinstance(points,(list,tuple)) and len(points) <= 3 \ 
     2520        and len(points) > 0 \ 
     2521        and not isinstance(points[0], (list,tuple))): 
     2522        try: 
     2523            points = [[float(z) for z in points]] 
     2524        except TypeError: 
    25772525            pass 
    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 
     2531def arrow(minpoint, maxpoint, **kwds): 
     2532    """ 
    26102533    An arrow from (xmin, ymin) to (xmax, ymax). 
    26112534 
    26122535    EXAMPLES: 
     
    26272550        1.0 
    26282551        sage: a.xmax() 
    26292552        5.0 
    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 
     2568def bar_chart(datalist, **kwds): 
    26622569    """ 
    26632570    A bar chart of (currently) one list of numerical data. 
    26642571    Support for more datalists in progress. 
     
    26732580    A bar_chart with negative values and red bars: 
    26742581        sage: bar_chart([-3,5,-6,11], rgbcolor=(1,0,0)) 
    26752582    """ 
    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 
     2614def circle(point, radius, **kwds): 
    27252615    """ 
    27262616    Return a circle at a point = $(x,y)$ with radius = $r$. 
    27272617    Type \code{circle.options} to see all options 
     
    27662656        sage: p.ymin() 
    27672657        2.0 
    27682658    """ 
    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 
     2669def contour_plot(f, xrange, yrange, **kwds): 
    27982670    r""" 
    27992671     
    28002672    \code{contour_plot} takes a function of two variables, $f(x,y)$ 
     
    28662738        sage: p.ymin() 
    28672739        3.0 
    28682740    """ 
    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 
     2755def implicit_plot(f, xrange, yrange, **kwds): 
    29022756    r""" 
    29032757    \code{implicit_plot} takes a function of two variables, $f(x,y)$ 
    29042758    and plots the curve $f(x,y)=0$ over the specified  
     
    29402794    (plot_points=200 looks even better, but it's about 16 times slower.) 
    29412795        sage: implicit_plot(mandel(7), (-0.3, 0.05), (-1.15, -0.9),plot_points=50).show(aspect_ratio=1) 
    29422796    """ 
    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 
     2801def line(points, **kwds): 
    29682802    r""" 
    29692803    Create the line through the given list of points. 
    29702804     
     
    30642898    A line with no points or one point: 
    30652899        sage: line([]) 
    30662900        sage: line([(1,1)]) 
    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 
     2920def matrix_plot(mat, **kwds): 
    31062921    r""" 
    31072922    A plot of a given matrix or 2D array. 
    31082923     
     
    31282943        sage: matrix_plot(random_matrix(GF(389), 10), cmap='Oranges') 
    31292944 
    31302945    """ 
    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 
    31672967 
    31682968 
    31692969# Below is the base class that is used to make 'plot_vector_field'. 
    31702970# Its implementation is motivated by 'PlotVectorField'. 
    31712971# TODO: make class similiar to this one to implement:  
    31722972# 'plot_gradient_field' and 'plot_hamiltonian_field' 
    3173 class PlotFieldFactory(GraphicPrimitiveFactory): 
     2973def plot_vector_field((f, g), xrange, yrange, **kwds): 
    31742974    r""" 
    31752975     
    31762976    \code{plot_vector_field} takes two functions of two variables, $(f(x,y), g(x,y))$ 
     
    31992999        10.0 
    32003000 
    32013001    """ 
    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 
     3024def disk(point, radius, angle, **kwds): 
    32353025    r""" 
    32363026     
    32373027    A disk at a point = $(x,y)$ with radius = $r$  
     
    32583048        sage: d.xmax() 
    32593049        6.0 
    32603050    """ 
    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 
     3066def point(points, **kwds): 
    32953067    r""" 
    32963068     
    32973069    A point of size `pointsize' defined by point = $(x,y)$. 
     
    33143086        3.0 
    33153087 
    33163088    """ 
    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 
    33393097points = point 
    33403098 
    3341  
    3342 class PolygonFactory(GraphicPrimitiveFactory_from_point_list): 
     3099def polygon(points, **kwds): 
    33433100    r""" 
    33443101    Type \code{polygon.options} for a dictionary of the default 
    33453102    options for polygons.  You can change this to change 
     
    34093166        -- David Joyner (2006-04-14): the long list of examples above. 
    34103167     
    34113168    """ 
    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     
     3177def plot(funcs, *args, **kwds): 
    34363178    r""" 
    34373179    Use plot by writing  
    34383180     
     
    35733315        True 
    35743316        sage: p[0].xdata[-1] == 1 
    35753317        True 
    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 
     3355def _plot(funcs, xrange, parametric=False, 
    36243356              polar=False, label='', randomize=True, **kwds): 
    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: 
    36933441                sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x),1) 
    36943442                exceptions += 1 
    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