Search code examples
pythonarraysnumpyscipyraster

Using a linear equation to create a radially interpolated circle


Given a linear equation, I want to use the slope to create a circle of values around a given point, defined by the slope of the linear equation if possible

Im currently a bit far away - can only make the radial plot but do not know how to connect this with an input equation. My first thought would be to change the opacity using import matplotlib.animation as animation and looping matplotlib's alpha argument to become gradually more and more opaque. However the alpha doesnt seem to change opacity.

Code:

# lenth of radius
distance = 200

# create radius 
radialVals = np.linspace(0,distance)

# 2 pi radians = full circle
azm = np.linspace(0, 2 * np.pi)
r, th = np.meshgrid(radialVals, azm)
z = (r ** 2.0) / 4.0

# creates circle
plt.subplot(projection="polar")

# add color gradient
plt.pcolormesh(th, r, z)

plt.plot(azm, r,alpha=1, ls='', drawstyle = 'steps') 

#gridlines
# plt.grid()

plt.show()

enter image description here


Solution

  • Here is one way to solve it, the idea is to create a mesh, calculate the colors with a function then use imshow to visualize the mesh.

    from matplotlib import pyplot as plt 
    import numpy as np
    
    
    def create_mesh(slope,center,radius,t_x,t_y,ax,xlim,ylim):
        """
        slope: the slope of the linear function
        center: the center of the circle
        raadius: the radius of the circle 
        t_x: the number of grids in x direction 
        t_y: the number of grids in y direction 
        ax: the canvas 
        xlim,ylim: the lims of the ax
        """
        def cart2pol(x,y):
            rho = np.sqrt(x**2 + y**2)
            phi = np.arctan2(y,x)
            return rho,phi
        
        def linear_func(slope):
            # initialize a patch and grids  
            patch = np.empty((t_x,t_y))
            patch[:,:] = np.nan
            x = np.linspace(xlim[0],xlim[1],t_x)
            y = np.linspace(ylim[0],ylim[1],t_y)
            x_grid,y_grid = np.meshgrid(x, y)
            
            # centered grid
            xc = np.linspace(xlim[0]-center[0],xlim[1]-center[0],t_x)
            yc = np.linspace(ylim[0]-center[1],ylim[1]-center[1],t_y)
            xc_grid,yc_grid = np.meshgrid(xc, yc)
            rho,phi = cart2pol(xc_grid,yc_grid)
            linear_values = slope * rho
            
            # threshold controls the size of the gaussian 
            circle_mask = (x_grid-center[0])**2 + (y_grid-center[1])**2 < radius
            patch[circle_mask] = linear_values[circle_mask]
        
            return patch
    
        # modify the patch
        patch = linear_func(slope)
        extent = xlim[0],xlim[1],ylim[0],ylim[1]
        ax.imshow(patch,alpha=.6,interpolation='bilinear',extent=extent,
                  cmap=plt.cm.YlGn,vmin=v_min,vmax=v_max)
            
            
    fig,ax = plt.subplots(nrows=1,ncols=2,figsize=(12,6))
    slopes = [40,30]
    centroids = [[2,2],[4,3]]
    radii = [1,4]
    
    for item in ax:item.set_xlim(0,8);item.set_ylim(0,8)
    v_max,v_min = max(slopes),0
    
    create_mesh(slopes[0],centroids[0],radii[0],t_x=300,t_y=300,ax=ax[0],xlim=(0,8),ylim=(0,8))
    create_mesh(slopes[1],centroids[1],radii[1],t_x=300,t_y=300,ax=ax[1],xlim=(0,8),ylim=(0,8))
    
    plt.show()
    

    The output of this code is

    output

    As you can see, the color gradient of the figure on the left is not as sharp as the figure on the right because of the different slopes ([40,30]).

    Also note that, these two lines of code

    v_max,v_min = max(slopes),0
    
    ax.imshow(patch,alpha=.6,interpolation='bilinear',extent=extent,
              cmap=plt.cm.YlGn,vmin=v_min,vmax=v_max)
    

    are added in order to let the two subplots share the same colormap.