Polar Plot in Python - Repeat of peak looks like kaleidoscope - matplotlib

I'm trying to plot a polar plot in matplotlib. When I use normal, rectangular coordinates, I get the plot I want:
dir_mesh, f_mesh = np.meshgrid(dir,freq[indsf])
pl.pcolor(dir_mesh,f_mesh,S1)
correct plot
If I use a polar projection, multiple peaks are present!
ax = pl.subplot(111,projection = "polar")
ax.set_theta_zero_location("N")
ax.set_theta_direction(-1)
c = ax.pcolor(dir_mesh,f_mesh,S1)
kaleidoscope polar plot (wrong)

The units of a polar plot are radiants. If you supply your data in degrees, ranging from 0 to 360, the data will revolve 57 times around the polar plot and the result will look something like this:
import matplotlib.pyplot as plt
import numpy as np
theta = np.arange(0,361,10)
r = np.linspace(0.,0.8,len(theta) )
ax = plt.subplot(111,projection = "polar")
ax.plot(theta,r)
plt.show()
In order to get the desired result you need to scale your theta data to the range between 0 and 2π.
e.g. theta = theta/180.*np.pi.
import matplotlib.pyplot as plt
import numpy as np
theta = np.arange(0,361,10)
theta = theta/180.*np.pi
r = np.linspace(0.,0.8,len(theta) )
ax = plt.subplot(111,projection = "polar")
ax.plot(theta,r)
plt.show()

Related

imshow() extent limits not giving correct solution

I am a novice to python. I was trying to plot 2 D color plot using imshow(). Here, x axis is the time scale, yaxis is the energy and the colorbar z axis is the differential energy flux. When i plot somehow the y axis do not correspond to the actual value. I had tried using contourf as well as plotly heatmap. However I find though the results come correctly it does not have the same visual impact as imshow.
import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
import matplotlib.dates as mdates
from mpl_toolkits.axes_grid1 import make_axes_locatable
import datetime as dt
x_lims = list(map(dt.datetime.utcfromtimestamp, [1266050102.1784432, 1266054264.5317998]))
x_lims = mdates.date2num(x_lims)
y1 = [3.1209615e+04, 2.6360914e+04, 2.0025836e+04, 1.5213330e+04, 1.1557158e+04,
8.7796689e+03, 6.6698813e+03, 5.0668237e+03, 3.8490525e+03, 2.9246511e+03,
2.2212300e+03, 1.6873538e+03, 1.2815887e+03, 9.7440747e+02, 7.3961621e+02,
5.6149872e+02, 4.2719626e+02, 3.2432623e+02, 2.4669749e+02, 1.8716624e+02,
1.4239874e+02, 1.0858500e+02, 8.2391251e+01, 6.2388748e+01, 4.7625000e+01,
3.6195000e+01, 2.7622499e+01, 2.0478750e+01, 1.5716249e+01, 1.2382500e+01,
9.0487499e+00, 7.1437497e+00]
y = np.array(y1)
y_lims = [y.min(), y.max()]
extent_lims = [x_lims[0], x_lims[1], y_lims[0], y_lims[1]]
z = flux_elec.T
fig, ax = plt.subplots()
im = ax.imshow(z, interpolation='none', extent=extent_lims, cmap='jet', aspect='auto')
date_format = mdates.DateFormatter('%H:%M')
ax.set_yscale('log')
ax.xaxis.set_major_formatter(date_format)
ax.xaxis_date()
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax, label="diff. en. flux")
[enter image description here](https://i.stack.imgur.com/Op1X7.png)
In this the high energy flux (8) should finish before 100 but its extending till 5000. I am unable to locate the error.

Scatterplot with Cartopy and Matplotlib produces cut-off map

I am trying to do a scatterplot on a map with Robinson Projection. However, the produced map is cut off at the side and I cannot figure out why. I did not have any problems when doing contour plots on similar maps. The longitude and latitude for the points, I want to plot, are stored in two seperate lists with floats (lon, lat), like this:
lon = [2.906250000000000000e+02, 2.906250000000000000e+02, 2.906250000000000000e+02, ...]
lat = [-5.315959537001968016e+01, -5.129437713895114825e+01,-4.942915369712304852e+01, ...]
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
fig_scale = 2
fig = plt.figure(figsize=(4*fig_scale,3*fig_scale))
gs1 = plt.GridSpec(2, 1,height_ratios=[1, 0.05])
axes = plt.subplot(gs1[0,0], projection=ccrs.Robinson(central_longitude=0.0))
mappab = plt.scatter(x=lon, y=lat,
transform=ccrs.PlateCarree())
axes.coastlines(color='grey')
axes.gridlines()
plt.show()

Plotting Poly3DCollection using add_collection3d

I have tree arrays of the same size representing the spherical coordinates of points in space. I want to plot them transformed in cartesian coordinates. I am trying to produce a surface and I need to use the add_collection3d method instead of the plot_surface because of the dimensions of my arrays. The original arrays have different lengths in spherical coordinates and the transformation into cartesian is not linear.
A simplified example follows:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LightSource
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
phi_rad = np.linspace(0,360, 10)/180.0*np.pi
theta_rad = np.linspace(0,360, 10)/180.0*np.pi # cos(theta)
counts_str = np.linspace(0, 100, 10) # counts
# convertion to cartesian coordinates 1D arrays
x = counts_str * np.sin(theta_rad) * np.cos(phi_rad)
y = counts_str * np.sin(theta_rad) * np.sin(phi_rad)
z_str = counts_str * np.cos(theta_rad)
verts = [list(zip(x, y, z_str))]
fig = plt.figure()
ax = Axes3D(fig)
ax.add_collection3d(Poly3DCollection(verts, cmap="hot", alpha=0.9))
ls = LightSource(azdeg=225.0, altdeg=45.0)
ax.set_xlim3d(x.min(), x.max())
ax.set_ylim3d(y.min(), y.max())
ax.set_zlim3d(z_str.min(), z_str.max())
plt.show()
I would like to apply a cmap and a LightSource (don't affect the plot), as well as an antialiased because in my real data z is an array with 20000 elements.
Looking forward to hearing from your collective intelligence!
Solution: reshape all the three vectors and use surface plot!
Creating a 3D surface plot from three 1D arrays

Problem with ortho projection and pcolormesh in matplotlib-basemap

I have trouble with the ortho projection and pcolormesh.
It should plot a mesh of grid points. Instead, in the upper right portion of the sphere it plots strange lines instead of grid points. The mapping of the mesh looks off.
I tried the code below.
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
plt.clf()
dpp =1 # degrees per pixel
lons = np.arange(-180,180+dpp,dpp)
lats = -1*np.arange(-90,90+dpp,dpp)
m = Basemap(projection='ortho', lon_0=0, lat_0=-60, resolution='l')
data = np.random.random((np.size(lats), np.size(lons)))
lons, lats = np.meshgrid(lons, lats)
x, y = m(lons, lats)
im = m.pcolormesh(x, y, data, latlon=False, cmap='RdBu')
#im = m.pcolormesh(lons, lats, data, latlon=True, cmap='RdBu')
m.colorbar(im)
plt.show()
I obtain the following plot:
The random noise should be mapped onto the entire sphere, but there is clearly an error in the upper right of the ortho map.
Does anyone else get this error with the included code?
Since basemap would require you to manually filter out unwanted data (those that are "behind the globe"), here is how to do the same with cartopy.
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
proj = ccrs.Orthographic(central_longitude=0.0, central_latitude=-60.0)
plt.figure(figsize=(3, 3))
ax = plt.axes(projection=proj)
dpp =1
lons = np.arange(-180,180+dpp,dpp)
lats = 1*np.arange(-90,90+dpp,dpp)
data = np.random.random((np.size(lats), np.size(lons)))
lons, lats = np.meshgrid(lons, lats)
im = ax.pcolormesh(lons, lats, data, cmap='RdBu', transform=ccrs.PlateCarree())
ax.coastlines(resolution='110m')
ax.gridlines()
plt.show()
A fix to Basemap was suggested in the github basemap thread here

How can I plot function values on a sphere?

I have a Nx2 matrix of lat lon coordinate pairs, spatial_data, and I have an array of measurements at these coordinates.
I would like to plot this data on a globe, and I understand that Basemap can do this. I found this link which shows how to plot data if you have cartesian coordinates. Does there exist functionality to convert lat,lon to cartesian coordinates? Alternatively, is there a way to plot this data with only the lat,lon information?
You can use cartopy:
import numpy as np
import matplotlib.pyplot as plt
from cartopy import crs
# a grid for the longitudes and latitudes
lats = np.linspace(-90, 90, 50)
longs = np.linspace(-180, 180, 50)
lats, longs = np.meshgrid(lats, longs)
# some data
data = lats[1:] ** 2 + longs[1:] ** 2
fig = plt.figure()
# create a new axes with a cartopy.crs projection instance
ax = fig.add_subplot(1, 1, 1, projection=crs.Mollweide())
# plot the date
ax.pcolormesh(
longs, lats, data,
cmap='hot',
transform=crs.PlateCarree(), # this means that x, y are given as longitude and latitude in degrees
)
fig.tight_layout()
fig.savefig('cartopy.png', dpi=300)
Result: