Ticket #7008: trac-7008-refactor-setup-eval-on-grid.patch

File trac-7008-refactor-setup-eval-on-grid.patch, 40.4 KB (added by jason, 10 years ago)
  • sage/plot/complex_plot.pyx

    # HG changeset patch
    # User Jason Grout <jason-sage@creativetrax.com>
    # Date 1253852050 18000
    # Node ID 568f58c1b652f1014deb5f3ac06abcf0f604695f
    # Parent  5519b8615ad3cbb913e8fd2f62d0e1a382995e14
    consolidate in plotting all extraction of variables, ranges, and fast_float setup
    
    Currently, code for extracting variables, dealing with ranges of variables, and making the functions fast_float is scattered throughout the plotting directory. There are multiple implementations, each having its own quirks.
    
    This patch consolidates all of this to two functions in sage.plot.misc and makes all the necessary changes to use this consolidated function.
    
    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/complex_plot.pyx
    a b  
    295295        sage: complex_plot(exp(x)-sin(x), (-10, 10), (-10, 10))
    296296
    297297    """
    298     from sage.plot.plot import Graphics, setup_for_eval_on_grid
     298    from sage.plot.plot import Graphics
     299    from sage.plot.misc import setup_for_eval_on_grid
    299300    from sage.ext.fast_callable import fast_callable
    300301    from sage.rings.complex_double import CDF
    301302
     
    305306        pass
    306307   
    307308    cdef double x, y
    308     ignore, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([], xrange, yrange, options['plot_points'])
    309     xmin, xmax = xrange
    310     ymin, ymax = yrange
    311     xrange_list = srange(xmin, xmax+xstep, xstep, universe=float)
    312     yrange_list = srange(ymin, ymax+ystep, ystep, universe=float)
     309    ignore, ranges = setup_for_eval_on_grid([], [xrange, yrange], options['plot_points'])
     310    xrange,yrange=[r[:2] for r in ranges]
    313311    _sig_on
    314     z_values = [[  f(new_CDF_element(x, y)) for x in xrange_list]
    315                                             for y in yrange_list]
     312    z_values = [[  f(new_CDF_element(x, y)) for x in srange(*ranges[0], include_endpoint=True)]
     313                                            for y in srange(*ranges[1], include_endpoint=True)]
    316314    _sig_off
    317315    g = Graphics()
    318316    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
  • sage/plot/contour_plot.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/contour_plot.py
    a b  
    265265        sage: x,y = var('x,y')
    266266        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,-2,0], fill=False)
    267267    """
    268     from sage.plot.plot import Graphics, setup_for_eval_on_grid
    269     g, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f], xrange, yrange, options['plot_points'])
     268    from sage.plot.plot import Graphics
     269    from sage.plot.misc import setup_for_eval_on_grid
     270    g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
    270271    g = g[0]
    271     xy_data_array = [[g(x, y) for x in xsrange(xrange[0], xrange[1], xstep, include_endpoint=True)]
    272                               for y in xsrange(yrange[0], yrange[1], ystep, include_endpoint=True)]
     272    xrange,yrange=[r[:2] for r in ranges]
     273   
     274    xy_data_array = [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
     275                              for y in xsrange(*ranges[1], include_endpoint=True)]
    273276
    274277    g = Graphics()
    275278    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
     
    437440        sage: region_plot([x^2+y^2<4, x>-1], (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray', plot_points=200).show(aspect_ratio=1) #long time
    438441    """
    439442
    440     from sage.plot.plot import Graphics, setup_for_eval_on_grid
     443    from sage.plot.plot import Graphics
     444    from sage.plot.misc import setup_for_eval_on_grid
     445
    441446    if not isinstance(f, (list, tuple)):
    442447        f = [f]
    443448
     
    445450
    446451    f = [equify(g, variables) for g in f]
    447452
    448     g, xstep, ystep, xrange, yrange = setup_for_eval_on_grid(f, xrange, yrange, plot_points)
     453    g, ranges = setup_for_eval_on_grid(f, [xrange, yrange], plot_points)
     454    xrange,yrange=[r[:2] for r in ranges]
    449455
    450     xy_data_arrays = map(lambda g: [[g(x, y) for x in xsrange(xrange[0], xrange[1], xstep, include_endpoint=True)]
    451                                              for y in xsrange(yrange[0], yrange[1], ystep, include_endpoint=True)], g)
     456    xy_data_arrays = map(lambda g: [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
     457                                             for y in xsrange(*ranges[1], include_endpoint=True)], g)
    452458
    453459    xy_data_array = map(lambda *rows: map(lambda *vals: mangle_neg(vals), *rows), *xy_data_arrays)
    454460
     
    461467   
    462468    g = Graphics()
    463469   
    464     g.add_primitive(ContourPlot(xy_data_array, xrange, yrange, dict(plot_points=plot_points,
     470    g.add_primitive(ContourPlot(xy_data_array, xrange,yrange, dict(plot_points=plot_points,
    465471                                                                    contours=[-1e307, 0, 1e307], cmap=cmap, fill=True)))
    466472
    467473    if bordercol is not None:
  • sage/plot/density_plot.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/density_plot.py
    a b  
    215215        sage: density_plot(log(x) + log(y), (x, 1, 10), (y, 1, 10), dpi=20)
    216216        sage: density_plot(log(x) + log(y), (x, 1, 10), (y, 1, 10)).show(dpi=20) # These are equivalent
    217217    """
    218     from sage.plot.plot import Graphics, setup_for_eval_on_grid
    219     g, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f], xrange, yrange, options['plot_points'])
     218    from sage.plot.plot import Graphics
     219    from sage.plot.misc import setup_for_eval_on_grid
     220    g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
    220221    g = g[0]
    221     xy_data_array = [[g(x, y) for x in xsrange(xrange[0], xrange[1], xstep, include_endpoint=True)]
    222                               for y in xsrange(yrange[0], yrange[1], ystep, include_endpoint=True)]
     222    xrange,yrange=[r[:2] for r in ranges]
     223
     224    xy_data_array = [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
     225                              for y in xsrange(*ranges[1], include_endpoint=True)]
    223226
    224227    g = Graphics()
    225228    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
  • sage/plot/misc.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/misc.py
    a b  
    1616
    1717from sage.misc.misc import verbose
    1818
     19from sage.ext.fast_eval import fast_float, fast_float_constant, is_fast_float
     20
     21
    1922def ensure_subs(f):
    2023    if not hasattr(f, 'subs'):
    2124        from sage.calculus.all import SR
     
    243246        wrapper._sage_src_ = lambda: sage_getsource(func)
    244247       
    245248        return wrapper
     249
     250
     251from sage.structure.element import is_Vector
     252
     253def setup_for_eval_on_grid(funcs, ranges, plot_points=None, return_vars=False):
     254    """
     255    Calculate the necessary parameters to construct a list of points,
     256    and make the functions fast_callable.
     257
     258    INPUT:
     259   
     260    -  ``funcs`` - a function, or a list, tuple, or vector of functions
     261   
     262    - ``ranges`` - a list of ranges.  A range can be a 2-tuple of
     263      numbers specifying the minimum and maximum, or a 3-tuple giving
     264      the variable explicitly.
     265
     266    - ``plot_points`` - a tuple of integers specifying the number of
     267      plot points for each range.  If a single number is specified, it
     268      will be the value for all ranges.  This defaults to 2.
     269     
     270    - ``return_vars`` - (default False) If True, return the variables,
     271      in order.
     272   
     273   
     274    OUTPUT:
     275   
     276   
     277    - ``fast_funcs`` - if only one function passed, then a fast
     278       callable function.  If funcs is a list or tuple, then a tuple
     279       of fast callable functions is returned.
     280
     281    - ``range_specs`` - a list of range_specs: for each range, a
     282       tuple is returned of the form (range_min, range_max,
     283       range_step) such that ``srange(range_min, range_max,
     284       range_step, include_endpoint=True)`` gives the correct points
     285       for evaluation.
     286   
     287    EXAMPLES::
     288   
     289        sage: x,y,z=var('x,y,z')
     290        sage: f(x,y)=x+y-z
     291        sage: g(x,y)=x+y
     292        sage: h(y)=-y
     293        sage: sage.plot.misc.setup_for_eval_on_grid(f, [(0, 2),(1,3),(-4,1)], plot_points=5)
     294        (<sage.ext...>, [(0.0, 2.0, 0.5), (1.0, 3.0, 0.5), (-4.0, 1.0, 1.25)])
     295        sage: sage.plot.misc.setup_for_eval_on_grid([g,h], [(0, 2),(-1,1)], plot_points=5)
     296        ((<sage.ext...>, <sage.ext...>), [(0.0, 2.0, 0.5), (-1.0, 1.0, 0.5)])
     297        sage: sage.plot.misc.setup_for_eval_on_grid([sin,cos], [(-1,1)], plot_points=9)
     298        ((<sage.ext...>, <sage.ext...>), [(-1.0, 1.0, 0.25)])
     299        sage: sage.plot.misc.setup_for_eval_on_grid([lambda x: x^2,cos], [(-1,1)], plot_points=9)
     300        ((<function <lambda> ...>, <sage.ext...>), [(-1.0, 1.0, 0.25)])
     301        sage: sage.plot.misc.setup_for_eval_on_grid([x+y], [(x,-1,1),(y,-2,2)])
     302        ((<sage.ext...>,), [(-1.0, 1.0, 2.0), (-2.0, 2.0, 4.0)])
     303        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9])
     304        (<sage.ext...>, [(-1.0, 1.0, 0.66666666666666663), (-1.0, 1.0, 0.25)])
     305        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,-1,1),(y,-1,1)], plot_points=[4,9,10])
     306        Traceback (most recent call last):
     307        ...
     308        ValueError: plot_points must be either an integer or a list of integers, one for each range
     309        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(1,-1),(y,-1,1)], plot_points=[4,9,10])
     310        Traceback (most recent call last):
     311        ...
     312        ValueError: Some variable ranges specify variables while others do not
     313        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(1,-1),(-1,1)], plot_points=5)
     314        doctest:...: DeprecationWarning: Unnamed ranges for more than one variable is deprecated and will be removed from a future release of Sage; you can used named ranges instead, like (x,0,2)
     315        (<sage.ext...>, [(1.0, -1.0, 0.5), (-1.0, 1.0, 0.5)])
     316        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], plot_points=5)
     317        (<sage.ext...>, [(1.0, -1.0, 0.5), (-1.0, 1.0, 0.5)])
     318        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(x,-1,1)], plot_points=5)
     319        Traceback (most recent call last):
     320        ...
     321        ValueError: range variables should be distinct, but there are duplicates   
     322        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(x,1,-1),(y,-1,1)], return_vars=True)
     323        (<sage.ext...>, [(1.0, -1.0, 2.0), (-1.0, 1.0, 2.0)], [x, y])
     324        sage: sage.plot.misc.setup_for_eval_on_grid(x+y, [(y,1,-1),(x,-1,1)], return_vars=True)
     325        (<sage.ext...>, [(1.0, -1.0, 2.0), (-1.0, 1.0, 2.0)], [y, x])
     326    """
     327    if max(len(r) for r in ranges)!=min(len(r) for r in ranges):
     328        raise ValueError, "Some variable ranges specify variables while others do not"
     329
     330    if len(ranges[0])==3:
     331        vars = [r[0] for r in ranges]
     332        ranges = [r[1:] for r in ranges]
     333        if len(set(vars))<len(vars):
     334            raise ValueError, "range variables should be distinct, but there are duplicates"
     335    else:
     336        vars, free_vars = unify_arguments(funcs)
     337        if len(free_vars)>1:
     338            from sage.misc.misc import deprecation
     339            deprecation("Unnamed ranges for more than one variable is deprecated and will be removed from a future release of Sage; you can used named ranges instead, like (x,0,2)")
     340
     341    # pad the variables if we don't have enough
     342    nargs = len(ranges)
     343    if len(vars)<nargs:
     344        vars += ('_',)*(nargs-len(vars))
     345
     346    ranges = [[float(z) for z in r] for r in ranges]
     347
     348    if plot_points is None:
     349        plot_points=2
     350
     351    if not isinstance(plot_points, (list, tuple)):
     352        plot_points = [plot_points]*len(ranges)
     353    elif len(plot_points)!=nargs:
     354        raise ValueError, "plot_points must be either an integer or a list of integers, one for each range"
     355       
     356    plot_points = [int(p) if p>=2 else 2 for p in plot_points]
     357    range_steps = [abs(range[1] - range[0])/(p-1) for range, p in zip(ranges, plot_points)]
     358   
     359    options={}
     360    if nargs==1:
     361        options['expect_one_var']=True
     362
     363    if is_Vector(funcs):
     364        funcs = list(funcs)
     365
     366    #TODO: raise an error if there is a function/method in funcs that takes more values than we have ranges
     367
     368    if return_vars:
     369        return fast_float(funcs, *vars,**options), [tuple(range+[range_step]) for range,range_step in zip(ranges, range_steps)], vars
     370    else:
     371        return fast_float(funcs, *vars,**options), [tuple(range+[range_step]) for range,range_step in zip(ranges, range_steps)]
     372       
     373
     374def unify_arguments(funcs):
     375    """
     376    Returns a tuple of variables of the functions, as well as the
     377    number of "free" variables (i.e., variables that defined in a
     378    callable function).
     379   
     380    INPUT:
     381   
     382    - ``funcs`` -- a list of functions; these can be symbolic
     383            expressions, polynomials, etc
     384   
     385    OUTPUT: functions, expected arguments
     386
     387    - A tuple of variables in the functions
     388
     389    - A tuple of variables that were "free" in the functions
     390
     391    EXAMPLES:
     392
     393        sage: x,y,z=var('x,y,z')
     394        sage: f(x,y)=x+y-z
     395        sage: g(x,y)=x+y
     396        sage: h(y)=-y
     397        sage: sage.plot.misc.unify_arguments((f,g,h))
     398        ((x, y, z), (z,))
     399        sage: sage.plot.misc.unify_arguments((g,h))
     400        ((x, y), ())
     401        sage: sage.plot.misc.unify_arguments((f,z))
     402        ((x, y, z), (z,))
     403        sage: sage.plot.misc.unify_arguments((h,z))
     404        ((y, z), (z,))
     405        sage: sage.plot.misc.unify_arguments((x+y,x-y))
     406        ((x, y), (x, y))
     407    """
     408    from sage.symbolic.callable import is_CallableSymbolicExpression
     409
     410    vars=set()
     411    free_variables=set()
     412    if not isinstance(funcs, (list, tuple)):
     413        funcs=[funcs]
     414
     415    for f in funcs:
     416        if is_CallableSymbolicExpression(f):
     417            f_args=set(f.arguments())
     418            vars.update(f_args)
     419        else:
     420            f_args=set()
     421           
     422        try:
     423            free_vars = set(f.variables()).difference(f_args)
     424            vars.update(free_vars)
     425            free_variables.update(free_vars)
     426        except AttributeError:
     427            # we probably have a constant
     428            pass
     429    return tuple(sorted(vars, key=lambda x: str(x))), tuple(sorted(free_variables, key=lambda x: str(x)))
  • sage/plot/plot.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/plot.py
    a b  
    288288EMBEDDED_MODE = False
    289289DOCTEST_MODE = False
    290290import sage.misc.misc
     291from sage.misc.misc import srange
    291292DOCTEST_MODE_FILE = sage.misc.misc.SAGE_TMP + '/test.png'
    292293SHOW_DEFAULT = True
    293294
     
    24392440
    24402441def _plot(funcs, xrange, parametric=False,
    24412442              polar=False, fill=None, label='', randomize=True, **options):
    2442     if not is_fast_float(funcs):
    2443         funcs =  fast_float(funcs, expect_one_var=True)
    24442443
     2444    from sage.plot.misc import setup_for_eval_on_grid
     2445    funcs, ranges = setup_for_eval_on_grid(funcs, [xrange], options['plot_points'])
     2446    xmin, xmax, delta = ranges[0]
     2447    xrange=ranges[0][:2]
    24452448    #parametric_plot will be a list or tuple of two functions (f,g)
    24462449    #and will plotted as (f(x), g(x)) for all x in the given range
    24472450    if parametric:
     
    24502453    else:
    24512454        f = funcs
    24522455
    2453     # xrange has to be either of the form (var, xmin, xmax) or (xmin, xmax)
    2454     if not isinstance(xrange, (tuple, list)):
    2455         raise TypeError, "xrange must be a tuple or list"
    2456     if len(xrange) == 3:
    2457         xmin, xmax = xrange[1], xrange[2]
    2458     elif len(xrange) == 2:
    2459         xmin, xmax = xrange[0], xrange[1]
    2460     else:
    2461         raise ValueError, "parametric value range must be a list or tuple of length 2 or 3."
    24622456
    24632457    #check to see if funcs is a list of functions that will
    24642458    #be all plotted together.
     
    24872481            if fillcolor_temp == 'automatic':
    24882482                fillcolor_temp = rainbow_colors[i]
    24892483
    2490             G += plot(h, (xmin, xmax), polar = polar, fill = fill_temp, \
     2484            G += plot(h, xrange, polar = polar, fill = fill_temp, \
    24912485                      fillcolor = fillcolor_temp, **options_temp)
    24922486        return G
    24932487
     
    26372631
    26382632    A filled Hypotrochoid::
    26392633   
    2640         sage: parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], 0, 8*pi, fill = True)
     2634        sage: parametric_plot([cos(x) + 2 * cos(x/4), sin(x) - 2 * sin(x/4)], (x,0, 8*pi), fill = True)
    26412635   
    26422636        sage: parametric_plot( (5*cos(x), 5*sin(x), x), (x,-12, 12), plot_points=150, color="red")
    26432637
     
    26532647        sage: parametric_plot((x, t^2), (x, -4, 4))
    26542648        Traceback (most recent call last):
    26552649        ...
    2656         ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
     2650        ValueError: there are more variables than variable ranges
    26572651   
    26582652        sage: parametric_plot((1, x+t), (x, -4, 4))
    26592653        Traceback (most recent call last):
    26602654        ...
    2661         ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
     2655        ValueError: there are more variables than variable ranges
    26622656
    26632657        sage: parametric_plot((-t, x+t), (x, -4, 4))
    26642658        Traceback (most recent call last):
    26652659        ...
    2666         ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
     2660        ValueError: there are more variables than variable ranges
    26672661
    26682662        sage: parametric_plot((1, x+t, y), (x, -4, 4), (t, -4, 4))
    26692663        Traceback (most recent call last):
    26702664        ...
    2671         ValueError: the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots
     2665        ValueError: there are more variables than variable ranges
    26722666
     2667        sage: parametric_plot((1, x, y), 0, 4)
     2668        Traceback (most recent call last):
     2669        ...
     2670        ValueError: there are more variables than variable ranges
    26732671    """
     2672    num_ranges=0
     2673    for i in args:
     2674        if isinstance(i, (list, tuple)):
     2675            num_ranges+=1
     2676        else:
     2677            break
     2678
     2679    if num_ranges==0 and len(args)>=2:
     2680        from sage.misc.misc import deprecation
     2681        deprecation("variable ranges to parametric_plot must be given as tuples, like (2,4) or (t,2,3)")
     2682        args=tuple(args)
     2683        num_ranges=1
     2684
    26742685    num_funcs = len(funcs)
    2675     var_list = [list(getattr(f, 'variables', lambda : [])()) for f in funcs]
    2676     num_vars = len(set(sum(var_list, [])))
    26772686
    2678     if num_funcs == 2 and num_vars <= 1:
     2687    num_vars=len(sage.plot.misc.unify_arguments(funcs)[0])
     2688    if num_vars>num_ranges:
     2689        raise ValueError, "there are more variables than variable ranges"
     2690
     2691    if num_funcs == 2 and num_ranges == 1:
    26792692        kwargs['parametric'] = True                   
    26802693        return plot(funcs, *args, **kwargs)
    2681     elif (num_funcs == 3 and num_vars <= 2):
     2694    elif (num_funcs == 3 and num_ranges <= 2):
    26822695        return sage.plot.plot3d.parametric_plot3d.parametric_plot3d(funcs, *args, **kwargs)
    26832696    else:
    2684         raise ValueError, "the number of functions and the number of free variables is not a possible combination for 2d or 3d parametric plots"
     2697        raise ValueError, "the number of functions and the number of variable ranges is not a supported combination for a 2d or 3d parametric plots"
    26852698
    26862699def polar_plot(funcs, *args, **kwds):
    26872700    r"""
     
    29973010        sage: f(x) = sin(x)
    29983011        sage: g(x) = sin(2*x)
    29993012        sage: h(x) = sin(4*x)
    3000         sage: p1 = plot(f,-2*pi,2*pi,color=hue(0.5))
    3001         sage: p2 = plot(g,-2*pi,2*pi,color=hue(0.9))
    3002         sage: p3 = parametric_plot((f,g),0,2*pi,color=hue(0.6))
    3003         sage: p4 = parametric_plot((f,h),0,2*pi,color=hue(1.0))
     3013        sage: p1 = plot(f,(-2*pi,2*pi),color=hue(0.5))
     3014        sage: p2 = plot(g,(-2*pi,2*pi),color=hue(0.9))
     3015        sage: p3 = parametric_plot((f,g),(0,2*pi),color=hue(0.6))
     3016        sage: p4 = parametric_plot((f,h),(0,2*pi),color=hue(1.0))
    30043017   
    30053018    Now make a graphics array out of the plots; then you can type
    30063019    either: ``ga.show()`` or ``ga.save()``.
     
    30113024   
    30123025    Here we give only one row::
    30133026   
    3014         sage: p1 = plot(sin,-4,4)
    3015         sage: p2 = plot(cos,-4,4)
     3027        sage: p1 = plot(sin,(-4,4))
     3028        sage: p2 = plot(cos,(-4,4))
    30163029        sage: g = graphics_array([p1, p2]); print g
    30173030        Graphics Array of size 1 x 2
    30183031        sage: g.show()
     
    30483061   
    30493062        sage: from sage.plot.plot import var_and_list_of_values
    30503063        sage: var_and_list_of_values((var('theta'), 2, 5),  5)
     3064        doctest:...: DeprecationWarning: var_and_list_of_values is deprecated.  Please use sage.plot.misc.setup_for_eval_on_grid; note that that function has slightly different calling and return conventions which make it more generally applicable
    30513065        (theta, [2.0, 2.75, 3.5, 4.25, 5.0])
    30523066        sage: var_and_list_of_values((2, 5),  5)
    30533067        (None, [2.0, 2.75, 3.5, 4.25, 5.0])
     
    30563070        sage: var_and_list_of_values((2, 5),  2)
    30573071        (None, [2.0, 5.0])
    30583072    """
     3073    from sage.misc.misc import deprecation
     3074    deprecation("var_and_list_of_values is deprecated.  Please use sage.plot.misc.setup_for_eval_on_grid; note that that function has slightly different calling and return conventions which make it more generally applicable")
    30593075    plot_points = int(plot_points)
    30603076    if plot_points < 2:
    30613077        raise ValueError, "plot_points must be greater than 1"
     
    31503166
    31513167def setup_for_eval_on_grid(v, xrange, yrange, plot_points):
    31523168    """
     3169    This function is deprecated.  Please use
     3170    sage.plot.misc.setup_for_eval_on_grid instead.  Please note that
     3171    that function has slightly different calling and return
     3172    conventions which make it more generally applicable.
     3173
    31533174    INPUT:
    31543175   
    31553176   
     
    31813202   
    31823203        sage: x,y = var('x,y')
    31833204        sage: sage.plot.plot.setup_for_eval_on_grid([x^2 + y^2], (x,0,5), (y,0,pi), 11)
     3205        doctest:...: DeprecationWarning: sage.plot.plot.setup_for_eval_on_grid is deprecated.  Please use sage.plot.misc.setup_for_eval_on_grid; note that that function has slightly different calling and return conventions which make it more generally applicable
    31843206        ([<sage.ext... object at ...>],
    31853207         0.5,
    31863208         0.31415926535897931,
     
    32003222
    32013223       
    32023224    """
    3203     if len(xrange) == 3:
    3204         xvar = xrange[0]
    3205         xrange = xrange[1:]
    3206         yvar = yrange[0]
    3207         yrange = yrange[1:]
    3208     else:
    3209         xvar = None
    3210     xrange = tuple([float(z) for z in xrange])
    3211     yrange = tuple([float(z) for z in yrange])       
    3212     plot_points = int(plot_points)
    3213     if plot_points <= 1:
    3214         plot_points = 2
    3215     xstep = abs(xrange[0] - xrange[1])/(plot_points-1)
    3216     ystep = abs(yrange[0] - yrange[1])/(plot_points-1)
     3225    from sage.misc.misc import deprecation
     3226    deprecation("sage.plot.plot.setup_for_eval_on_grid is deprecated.  Please use sage.plot.misc.setup_for_eval_on_grid; note that that function has slightly different calling and return conventions which make it more generally applicable")
    32173227
    3218     g = []
    3219     for f in v:
    3220         if isinstance(f, types.FunctionType):
    3221             g.append(f)
    3222         else:
    3223             # This code can be refactored at some point out of plot3d.
    3224             from sage.plot.plot3d.parametric_plot3d import adapt_to_callable
    3225             if xvar is None:
    3226                 k, _ = adapt_to_callable([f], 2)
    3227                 g.append(k[0])
    3228             else:
    3229                 g.append(fast_float(f, str(xvar), str(yvar)))
    3230            
    3231     return g, xstep, ystep, xrange, yrange
     3228    from sage.plot.misc import setup_for_eval_on_grid as setup
     3229    g, ranges=setup(v, [xrange, yrange], plot_points)
     3230    return list(g), ranges[0][2], ranges[1][2], ranges[0][:2], ranges[1][:2]
    32323231
    32333232
    32343233def minmax_data(xdata, ydata, dict=False):
     
    34163415        sage: [len(generate_plot_points(f, (-pi, pi), plot_points=16, adaptive_recursion=i, randomize=False)) for i in [5, 10, 15]]
    34173416        [97, 499, 2681]
    34183417    """
    3419     x, data = var_and_list_of_values(xrange, plot_points)
    3420     xmin = data[0]
    3421     xmax = data[-1]
    3422     delta = float(xmax-xmin) / float(plot_points-1)
     3418    from sage.plot.misc import setup_for_eval_on_grid
     3419    ignore, ranges = setup_for_eval_on_grid([], [xrange], plot_points)
     3420    xmin, xmax, delta = ranges[0]
     3421    data = srange(*ranges[0], include_endpoint=True)
    34233422
    34243423    random = current_randstate().python_random().random
    34253424    exceptions = 0; msg=''
  • sage/plot/plot3d/implicit_surface.pyx

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/plot3d/implicit_surface.pyx
    a b  
    8888from sage.plot.plot3d.base import RenderParams, default_texture
    8989from sage.plot.plot3d.index_face_set cimport IndexFaceSet
    9090from sage.rings.all import RDF
     91from sage.plot.misc import setup_for_eval_on_grid
    9192
    9293include '../../ext/cdefs.pxi'
    9394include '../../ext/stdsage.pxi'
     
    895896
    896897    return results
    897898
    898 def extract_vars_ranges_and_adapt(f, arity, *ranges):
    899     """
    900     Makes f into a fast callable function, while inferring its arguments and
    901     canonicalizing the provided ranges.
    902 
    903     INPUT:
    904 
    905     -  ``f`` - a symbolic expression or a python function
    906 
    907     -  ``arity`` - the arity of f
    908 
    909     -  ``ranges`` - A list of ranges, one for each argument, describing the domain
    910        of f. Ranges may be of the form (var, low, high) OR simply (low, high).
    911 
    912     OUTPUT:
    913        
    914         - fast callable function
    915 
    916         - tuple of expected arguments
    917 
    918         - list of canonicalized ranges of the form (low, high)
    919 
    920     EXAMPLES::
    921 
    922         sage: from sage.plot.plot3d.implicit_surface import extract_vars_ranges_and_adapt
    923         sage: x, y = var('x, y')
    924         sage: extract_vars_ranges_and_adapt(x + y, 2, (0, 1), (0, 1))
    925         (<...>, (x, y), [(0, 1), (0, 1)])
    926         sage: extract_vars_ranges_and_adapt(x + y, 2, (y, 0, 1), (x, 0, 1))
    927         (<...>, (y, x), [(0, 1), (0, 1)])
    928     """
    929     from sage.ext.fast_eval import fast_float, fast_float_constant
    930     if any([len(ranges[0]) != len(x) for x in ranges]):
    931         raise ValueError, "invalid range; be consistent when explicitly specifying a variable"
    932     vars = None
    933     f_type = "symbolic"
    934     if len(ranges[0]) == 3:
    935         vars = [x[0] for x in ranges]
    936         for unique_var in set(vars):
    937             if vars.count(unique_var) > 1:
    938                 raise ValueError, "plot variables should be distinct"
    939         vars = tuple(vars)
    940         ranges = [x[1:] for x in ranges]
    941     elif len(ranges[0]) == 2:
    942         if hasattr(f, "variables"):
    943            vars = f.variables()
    944         else:
    945             vars = ("_",) * arity
    946             f_type = "constant"
    947         ranges = list(ranges)
    948     else:
    949         raise ValueError, "invalid range; tuple should have 2 or 3 elements"
    950     from types import FunctionType
    951     if type(f) is FunctionType:
    952         f_type = "function"
    953     if len(vars) != arity:
    954         raise ValueError, "function should have arity %i" % arity
    955    
    956     f_result = None
    957     if f_type == "symbolic":
    958         f_result = fast_float(f, *vars)
    959     elif f_type == "constant":
    960         f_result = fast_float_constant(f)
    961     elif f_type == "function":
    962         f_result = f
    963     return f_result, vars, ranges
    964 
    965899cdef class ImplicitSurface(IndexFaceSet):
    966900    cdef readonly object f
    967901    cdef readonly object vars
     
    985919            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    986920            sage: var('x,y,z')
    987921            (x, y, z)
    988             sage: G = ImplicitSurface(x^2 + y^2 + z^2, (-2, 2), (-2, 2), (-2, 2), contour=4)
     922            sage: G = ImplicitSurface(x^2 + y^2 + z^2, (x,-2, 2), (y,-2, 2), (z,-2, 2), contour=4)
    989923            sage: show(G)
    990924        """
    991925        IndexFaceSet.__init__(self, [], [], **kwds)
    992926        from sage.ext.fast_eval import fast_float
    993927
    994928        orig_f = f
    995         self.f, self.vars, ranges = \
    996             extract_vars_ranges_and_adapt(f, 3, xrange, yrange, zrange)
    997         self.xrange = (float(ranges[0][0]), float(ranges[0][1]))
    998         self.yrange = (float(ranges[1][0]), float(ranges[1][1]))
    999         self.zrange = (float(ranges[2][0]), float(ranges[2][1]))
     929        self.f, ranges, self.vars = setup_for_eval_on_grid(f, [xrange, yrange, zrange], return_vars=True)
     930        self.xrange = ranges[0][:2]
     931        self.yrange = ranges[1][:2]
     932        self.zrange = ranges[1][:2]
    1000933        if isinstance(contour, (list, tuple)):
    1001934            contours = contour
    1002935        else:
     
    1060993            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    1061994            sage: var('x,y,z')
    1062995            (x, y, z)
    1063             sage: G = ImplicitSurface(x + y + z, (-1, 1), (-1, 1), (-1, 1))
     996            sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
    1064997            sage: obj = G.obj_repr(G.default_render_params())
    1065998            sage: vertices = obj[2]
    1066999
     
    10971030            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    10981031            sage: var('x,y,z')
    10991032            (x, y, z)
    1100             sage: G = ImplicitSurface(x + y + z, (-1, 1), (-1, 1), (-1, 1))
     1033            sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
    11011034            sage: G.tachyon_repr(G.default_render_params())[0].startswith('TRI')
    11021035            True
    11031036        """
     
    11141047            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    11151048            sage: var('x,y,z')
    11161049            (x, y, z)
    1117             sage: G = ImplicitSurface(x + y + z, (-1, 1), (-1, 1), (-1, 1))
     1050            sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
    11181051            sage: show(G, viewer='jmol')
    11191052        """
    11201053        self.triangulate()
     
    11291062            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    11301063            sage: var('x,y,z')
    11311064            (x, y, z)
    1132             sage: G = ImplicitSurface(x + y + z, (-1, 1), (-1, 1), (-1, 1))
     1065            sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
    11331066            sage: G.json_repr(G.default_render_params())[0].startswith('{vertices:')
    11341067            True
    11351068        """
     
    11501083            sage: from sage.plot.plot3d.implicit_surface import ImplicitSurface
    11511084            sage: var('x,y,z')
    11521085            (x, y, z)
    1153             sage: G = ImplicitSurface(x + y + z, (-1, 1), (-1, 1), (-1, 1))
     1086            sage: G = ImplicitSurface(x + y + z, (x,-1, 1), (y,-1, 1), (z,-1, 1))
    11541087            sage: len(G.vertex_list()), len(G.face_list())
    11551088            (0, 0)
    11561089            sage: G.triangulate()
  • sage/plot/plot3d/parametric_plot3d.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/plot3d/parametric_plot3d.py
    a b  
    66from shapes2 import line3d
    77from texture import Texture
    88from sage.plot.misc import ensure_subs
     9from sage.misc.misc import xsrange, srange
    910from sage.structure.element import is_Vector
    1011
    1112from sage.ext.fast_eval import fast_float, fast_float_constant, is_fast_float
     
    466467        sage: plot3d(u^2-v^2, (u, -1, 1), (u, -1, 1))
    467468        Traceback (most recent call last):
    468469        ...
    469         ValueError: plot variables should be distinct, but both are u.
     470        ValueError: range variables should be distinct, but there are duplicates
     471
    470472
    471473    From Trac #2858::
    472474   
     
    500502        f = tuple(f)
    501503
    502504    if isinstance(f, (list,tuple)) and len(f) > 0 and isinstance(f[0], (list,tuple)):
    503         return sum([parametric_plot3d(v, urange, vrange, plot_points, **kwds) for v in f])
     505        return sum([parametric_plot3d(v, urange, vrange, plot_points=plot_points, **kwds) for v in f])
    504506           
    505507    if not isinstance(f, (tuple, list)) or len(f) != 3:
    506508        raise ValueError, "f must be a list, tuple, or vector of length 3"
     
    508510    if vrange is None:
    509511        if plot_points == "automatic":
    510512            plot_points = 75
    511         G = _parametric_plot3d_curve(f, urange, plot_points, **kwds)
     513        G = _parametric_plot3d_curve(f, urange, plot_points=plot_points, **kwds)
    512514    else:
    513         if urange[0] is vrange[0]:
    514             raise ValueError, "plot variables should be distinct, but both are %s."%(urange[0],)
    515 
    516515        if plot_points == "automatic":
    517516            plot_points = [40,40]
    518         G = _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds)
     517        G = _parametric_plot3d_surface(f, urange, vrange, plot_points=plot_points, boundary_style=boundary_style, **kwds)
    519518    G._set_extra_kwds(kwds)
    520519    return G
    521520   
     
    524523    This function is used internally by the
    525524    ``parametric_plot3d`` command.
    526525    """
    527     from sage.plot.plot import var_and_list_of_values
    528     plot_points = int(plot_points)
    529     u, vals = var_and_list_of_values(urange, plot_points)
    530     w = []
    531     fail = 0
    532 
    533     if u is None:
    534         try:
    535             f, (u,) = adapt_to_callable(f, 1)
    536         except TypeError:
    537             pass
    538            
    539     else:
    540         f = fast_float(f, u)
    541 
    542     f_x, f_y, f_z = f
    543     if u is None or all(is_fast_float(f_i) for f_i in f):
    544         for t in vals:
    545             try:
    546                 w.append((float(f_x(t)), float(f_y(t)), float(f_z(t))))
    547             except TypeError:
    548                 fail += 1
    549 
    550     else:
    551         f_x, f_y, f_z = [ensure_subs(m) for m in f]
    552         for t in vals:
    553             try:
    554                 w.append((float(f_x.subs({u:t})), float(f_y.subs({u:t})),
    555                           float(f_z.subs({u:t}))))
    556             except TypeError:
    557                 fail += 1
    558                
    559     if fail > 0:
    560         print "WARNING: Failed to evaluate parametric plot at %s points"%fail
     526    from sage.plot.misc import setup_for_eval_on_grid
     527    g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)
     528    f_x,f_y,f_z = g
     529    w = [(f_x(u), f_y(u), f_z(u)) for u in xsrange(*ranges[0], include_endpoint=True)]
    561530    return line3d(w, **kwds)
    562531
    563532def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds):
     
    565534    This function is used internally by the
    566535    ``parametric_plot3d`` command.
    567536    """
    568     if not isinstance(plot_points, (list, tuple)) or len(plot_points) != 2:
    569         raise ValueError, "plot_points must be a tuple of length 2"
    570     points0, points1 = plot_points
    571 
    572     from sage.plot.plot import var_and_list_of_values
    573     u, u_vals = var_and_list_of_values(urange, int(points0))
    574     v, v_vals = var_and_list_of_values(vrange, int(points1))
    575 
    576     if u is None:
    577         if not v is None:
    578             raise ValueError, "both ranges must specify a variable or neither must"
    579            
    580         try:
    581             g, (u,v) = adapt_to_callable(f, 2)
    582         except TypeError:
    583             g = tuple(f)
    584 
    585     else:
    586         if v is None:
    587             raise ValueError, "both ranges must specify a variable or neither must"
    588        
    589         g = fast_float(f, str(u), str(v))
    590 
    591     G = ParametricSurface(g, (u_vals, v_vals), **kwds)
    592 
    593     # Canonicalize the urange and vrange for processing the boundary style
    594     urange = urange if len(urange) == 3 else (u,) + urange
    595     vrange = vrange if len(vrange) == 3 else (v,) + vrange
    596 
     537    from sage.plot.misc import setup_for_eval_on_grid
     538    g, ranges = setup_for_eval_on_grid(f, [urange,vrange], plot_points)
     539    urange = srange(*ranges[0], include_endpoint=True)
     540    vrange = srange(*ranges[1], include_endpoint=True)
     541    G = ParametricSurface(g, (urange, vrange), **kwds)
     542   
    597543    if boundary_style is not None:
    598         for (var, extrema, bounds) in [(u, urange[1], vrange), (u, urange[2], vrange),
    599                                        (v, vrange[1], urange), (v, vrange[2], urange)]:
    600                 f_prime = tuple(n.substitute({var: extrema}) for n in f)
    601                 G = G + parametric_plot3d(f_prime, bounds, **boundary_style)
    602    
     544        for u in (urange[0], urange[-1]):
     545            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style)
     546        for v in (vrange[0], vrange[-1]):
     547            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style)
    603548    return G
    604549
    605550
     
    643588   
    644589    OUTPUT: functions, expected arguments
    645590    """
     591    from sage.misc.misc import deprecation
     592    deprecation("adapt_to_callable is a deprecated function.  Please use functions from sage.misc.plot instead.")
     593   
    646594    try:
    647595        from sage.symbolic.callable import is_CallableSymbolicExpression
    648596        if sum([is_CallableSymbolicExpression(z) for z in f]):
  • sage/plot/plot3d/plot3d.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/plot3d/plot3d.py
    a b  
    170170        sage: plot3d( 4*x*exp(-x^2-y^2), (x,-2,2), (x,-2,2))
    171171        Traceback (most recent call last):
    172172        ...
    173         ValueError: plot variables should be distinct, but both are x.
     173        ValueError: range variables should be distinct, but there are duplicates
    174174    """
    175     if len(urange) == 2:
    176         try:
    177             f_list, (u,v) = parametric_plot3d.adapt_to_callable([f], 2)
    178             f = f_list[0]
    179             w = (u, v, f)
    180             urange = (u, urange[0], urange[1])
    181             vrange = (v, vrange[0], vrange[1])
    182         except TypeError:
    183              w = (fast_float_arg(0), fast_float_arg(1), f)
    184     else:
    185         u = urange[0]
    186         v = vrange[0]
    187         if u is v:
    188             raise ValueError, "plot variables should be distinct, but both are %s."%(u,)   
    189        
    190         w = (u, v, f)
    191 
    192175    if adaptive:
    193176        P = plot3d_adaptive(f, urange, vrange, **kwds)
    194177    else:
    195         P = parametric_plot3d.parametric_plot3d(w, urange, vrange, **kwds)
     178        u=fast_float_arg(0)
     179        v=fast_float_arg(1)
     180        P=parametric_plot3d.parametric_plot3d((u,v,f), urange, vrange, **kwds)
    196181    P.frame_aspect_ratio([1.0,1.0,0.5])
    197182    return P
    198183
     
    239224        sage: from sage.plot.plot3d.plot3d import plot3d_adaptive
    240225        sage: x,y=var('x,y'); plot3d_adaptive(sin(x*y), (x,-pi,pi), (y,-pi,pi), initial_depth=5)
    241226    """
    242     if not (isinstance(x_range, (tuple, list)) and isinstance(y_range,(tuple,list)) and len(x_range) == len(y_range) and len(x_range) in [2,3]):
    243         raise TypeError, "x_range and y_range must both be a 2 or 3-tuple"
    244     if len(x_range) == 3:
    245         # symbolic case
    246         x, xmin, xmax = x_range
    247         y, ymin, ymax = y_range
    248         def g(xx,yy):
    249             return float(f.subs({x:xx, y:yy}))
    250 
    251     else:
    252         xmin, xmax = x_range
    253         ymin, ymax = y_range
    254        
    255         g = f
    256        
    257227    if initial_depth >= max_depth:
    258228        max_depth = initial_depth
    259     xmin = float(xmin)
    260     xmax = float(xmax)
    261     ymin = float(ymin)
    262     ymax = float(ymax)
    263        
    264     # Check if g has a fast float evaluation
    265     #try:
    266     #    g = g.fast_float_function()
    267     #except AttributeError:
    268     #    # Nope -- no prob.
    269     #    pass
    270     if kwds.has_key('opacity'):
    271         opacity = kwds['opacity']
    272     else:
    273         opacity = 1
     229   
     230    from sage.plot.misc import setup_for_eval_on_grid
     231    g, ranges = setup_for_eval_on_grid(f, [x_range,y_range], plot_points=2)
     232    xmin,xmax = ranges[0][:2]
     233    ymin,ymax = ranges[1][:2]
     234
     235    opacity = kwds.get('opacity',1)
     236
    274237    if color == "automatic":
    275238        texture = rainbow(num_colors, 'rgbtuple')
    276239    else:
  • sage/plot/plot_field.py

    diff -r 5519b8615ad3 -r 568f58c1b652 sage/plot/plot_field.py
    a b  
    161161        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2), xmax=10)
    162162        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2)).show(xmax=10) # These are equivalent
    163163    """
    164     from sage.plot.plot import setup_for_eval_on_grid, Graphics
    165     z, xstep, ystep, xrange, yrange = setup_for_eval_on_grid([f,g], xrange, yrange, options['plot_points'])
     164    from sage.plot.plot import Graphics
     165    from sage.plot.misc import setup_for_eval_on_grid
     166    z, ranges = setup_for_eval_on_grid([f,g], [xrange, yrange], options['plot_points'])
    166167    f,g = z
    167168
    168169    xpos_array, ypos_array, xvec_array, yvec_array = [],[],[],[]
    169     for x in xsrange(xrange[0], xrange[1], xstep, include_endpoint=True):
    170         for y in xsrange(yrange[0], yrange[1], ystep, include_endpoint=True):
     170    for x in xsrange(*ranges[0], include_endpoint=True):
     171        for y in xsrange(*ranges[1], include_endpoint=True):
    171172            xpos_array.append(x)
    172173            ypos_array.append(y)
    173174            xvec_array.append(f(x,y))