<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def image_function(f='sin(5*x)*cos(5*y)', xmin=-1, xmax=1, ymin=-1, ymax=1, xsteps=100, ysteps=100, p='x,y', g=None, **kwargs):
 """ Plots a 2-d function over the specified range Parameters f='sin(5*x)*cos(5*y)' Takes two inputs and returns one value. Can also be a string function such as sin(x*y) xmin=-1, xmax=1, ymin=-1, ymax=1 Range over which to generate/plot the data xsteps=100, ysteps=100 How many points to plot on the specified range p='x,y' If using strings for functions, this is a string of parameters. g=None Optional additional globals. Try g=globals()! See spinmob.plot.image.data() for additional optional keyword arguments. """


    default_kwargs = dict(clabel=str(f), xlabel='x', ylabel='y')
    default_kwargs.update(kwargs)

    # aggregate globals
    if not g: g = {}
    for k in list(globals().keys()):
        if k not in g: g[k] = globals()[k]

    if type(f) == str:
        f = eval('lambda ' + p + ': ' + f, g)


    # generate the grid x and y coordinates
    xones = _n.linspace(1,1,ysteps)
    x     = _n.linspace(xmin, xmax, xsteps)
    xgrid = _n.outer(xones, x)

    yones = _n.linspace(1,1,xsteps)
    y     = _n.linspace(ymin, ymax, ysteps)
    ygrid = _n.outer(y, yones)

    # now get the z-grid
    try:
        # try it the fast numpy way. Add 0 to assure dimensions
        zgrid = f(xgrid, ygrid) + xgrid*0.0
    except:
        print("Notice: function is not rocking hardcore. Generating grid the slow way...")
        # manually loop over the data to generate the z-grid
        zgrid = []
        for ny in range(0, len(y)):
            zgrid.append([])
            for nx in range(0, len(x)):
                zgrid[ny].append(f(x[nx], y[ny]))

        zgrid = _n.array(zgrid)

    # now plot!
    image_data(zgrid.transpose(), x, y, **default_kwargs)