Rohin Kumar
Rohin Kumar

Reputation: 810

flipping and rotating numpy arrays for contour plots

Short Version:

I have a 10x10 numpy array whose contour plot (plotted with pyplot.contourf) looks like this

contour plot of z

Now, I want it look something like this - assuming the plot is symmetric across X and Y axes.

anisotropic correlation function

Long version

I have a 10x10 numpy array z as a function of x and y. where x=y=np.arange(0.002,0.022,0.002). Here is what I tried

import numpy as np
import matplotlib.pyplot as plt
z=np.array([[ 2.08273679, -0.06591932, -1.14525488, -1.49923222, -1.74361248,
    -1.81418446, -1.90115591, -1.94329043, -1.93130228, -1.96064259],
   [ 0.20180514, -0.94522815, -1.34635828, -1.58844515, -1.7528935 ,
    -1.84438752, -1.86257547, -1.9439332 , -1.99009407, -1.94829146],
   [-1.09749238, -1.48234452, -1.64234357, -1.75344742, -1.83019763,
    -1.88547473, -1.92958533, -1.940775  , -1.95535063, -1.9629588 ],
   [-1.62892483, -1.70176401, -1.76263555, -1.84966414, -1.87139241,
    -1.91879916, -1.90796703, -1.96632612, -1.95794984, -1.94585536],
   [-1.71551518, -1.91806287, -1.86999609, -1.90800839, -1.92515012,
    -1.93386969, -1.96487487, -1.95405297, -1.97032435, -1.96087146],
   [-1.81904322, -1.94790171, -2.        , -1.96932249, -1.91842475,
    -1.98101775, -1.98521938, -1.97618539, -1.95892852, -2.01410874],
   [-1.8138236 , -1.90877811, -1.93966404, -1.98406259, -1.95253807,
    -1.95867436, -1.96679456, -2.01126218, -1.99885932, -1.99369292],
   [-1.9927308 , -1.97658099, -1.91586737, -1.96813381, -1.98416011,
    -1.98639893, -1.99997964, -1.99746813, -1.98126505, -1.97767361],
   [-1.96406473, -1.92609437, -1.99171257, -1.94687523, -1.9823819 ,
    -1.97786533, -2.02323228, -1.98559114, -1.99172681, -2.00881064],
   [-1.92470024, -1.99537152, -1.99419303, -1.97261023, -1.9673841 ,
    -1.98801505, -2.02412735, -2.01394008, -2.01956817, -2.04963448]])
x=y=np.arange(0.002,0.022,0.002)
#The following gives the plot I currently have
plt.figure()
plt.contourf(x,y,z)
plt.show()
#Tried to flip the matrix z using np.flipud and np.fliplr
plt.figure()
plt.contourf(x,y,z)
plt.contourf(-x,y,np.fliplr(z))
plt.contourf(x,-y,np.flipud(z))
plt.contourf(-x,-y,np.flipud(np.fliplr(z)))
plt.show()
#Also tried to rotate the matrix z using np.rot90
plt.figure()
plt.contourf(x,y,z)
plt.contourf(x,-y,np.rot90(z))
plt.contourf(-x,-y,np.rot90(z,2))
plt.contourf(-x,y,np.rot90(z,3))
plt.show()

I get the following plots with the above code

flipped

and

rotated

Ideally I would also like to fill the discontinuity at the origin by interpolation of the plot. But for starters, would like to get the orientation right. Any help is greatly appreciated.

Upvotes: 2

Views: 3664

Answers (2)

Serenity
Serenity

Reputation: 36695

Combine results of fliplr and flipud of your array z to a new double sized array zz then plot it. You have to skip x and y in interval (-0.002; +0.002) with nan values according to your first figure:

import numpy as np
import matplotlib.pyplot as plt
z=np.array([[ 2.08273679, -0.06591932, -1.14525488, -1.49923222, -1.74361248,
    -1.81418446, -1.90115591, -1.94329043, -1.93130228, -1.96064259],
   [ 0.20180514, -0.94522815, -1.34635828, -1.58844515, -1.7528935 ,
    -1.84438752, -1.86257547, -1.9439332 , -1.99009407, -1.94829146],
   [-1.09749238, -1.48234452, -1.64234357, -1.75344742, -1.83019763,
    -1.88547473, -1.92958533, -1.940775  , -1.95535063, -1.9629588 ],
   [-1.62892483, -1.70176401, -1.76263555, -1.84966414, -1.87139241,
    -1.91879916, -1.90796703, -1.96632612, -1.95794984, -1.94585536],
   [-1.71551518, -1.91806287, -1.86999609, -1.90800839, -1.92515012,
    -1.93386969, -1.96487487, -1.95405297, -1.97032435, -1.96087146],
   [-1.81904322, -1.94790171, -2.        , -1.96932249, -1.91842475,
    -1.98101775, -1.98521938, -1.97618539, -1.95892852, -2.01410874],
   [-1.8138236 , -1.90877811, -1.93966404, -1.98406259, -1.95253807,
    -1.95867436, -1.96679456, -2.01126218, -1.99885932, -1.99369292],
   [-1.9927308 , -1.97658099, -1.91586737, -1.96813381, -1.98416011,
    -1.98639893, -1.99997964, -1.99746813, -1.98126505, -1.97767361],
   [-1.96406473, -1.92609437, -1.99171257, -1.94687523, -1.9823819 ,
    -1.97786533, -2.02323228, -1.98559114, -1.99172681, -2.00881064],
   [-1.92470024, -1.99537152, -1.99419303, -1.97261023, -1.9673841 ,
    -1.98801505, -2.02412735, -2.01394008, -2.01956817, -2.04963448]])
x=y=np.linspace(-0.020,0.020,21)

zz = np.empty((21,21)); zz[:,:] = np.nan
zz[11:,11:] = z
zz[11:,:10] = np.fliplr(z)
zz[:10,:] = np.flipud(zz[11:,:])

plt.figure()
plt.contourf(x,y,zz)
plt.show()

enter image description here To fill the gap skip one point of coordinate arrays:

...
x=y=np.linspace(-0.020,0.020,20)
zz = np.empty((20,20)); zz[:,:] = np.nan
zz[10:,10:] = z
zz[10:,:10] = np.fliplr(z)
zz[:10,:] = np.flipud(zz[10:,:])
...

enter image description here

Upvotes: 2

Thomas Kühn
Thomas Kühn

Reputation: 9830

Your problem is that, even though you negate x and y, their order stays the same, so with negative x, you go from -0.002 to -0.022, which means that the flipped z gets flipped back during the plotting. To achieve what you want, you can do the following:

#either don't flip z
plt.figure()
plt.contourf(x,y,z)
plt.contourf(-x,y,z)
plt.contourf(x,-y,z)
plt.contourf(-x,-y,z)
plt.show()

#or reverse also -x and -y:
plt.figure()
plt.contourf(x,y,z)
plt.contourf(-x[::-1],y,np.fliplr(z))
plt.contourf(x,-y[::-1],np.flipud(z))
plt.contourf(-x[::-1],-y[::-1],np.flipud(np.fliplr(z)))
plt.show()

If you would have just concatenated z and the flipped z, everything would have worked as expected. plt.contourf takes care of the interpolation itself.

ztotal = np.concatenate([np.fliplr(z),z],axis=1)
ztotal = np.concatenate([np.flipud(ztotal),ztotal],axis=0)
xtotal = np.concatenate([-x[::-1],x],axis=0)
ytotal = np.concatenate([-y[::-1],y],axis=0)

plt.figure()
plt.contourf(xtotal,ytotal,ztotal)
plt.show()

final plot

Upvotes: 3

Related Questions