python: scatter does not display - python

I have some trouble using scatter in python. I have 2 vectors of size 100 of latitudes and longitudes, and a vector 100 of corresponding data of values between 1 and 2.
I am trying to display these data on a north polar stereographic projected map, but nothing appears on the figure. Here is my code:
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import colors as mpl_colors
from mpl_toolkits.basemap import Basemap`
lon=np.linspace(-180,180,num=100)
lat=np.linspace(75,75,num=100)
data=1+np.random.rand(100)
cmap = plt.cm.jet
norm_color = mpl_colors.Normalize(vmin=None, vmax=None, clip=False)
fig=plt.figure()
m = Basemap(projection='npstere',boundinglat=65,lon_0=310,resolution='l')
x,y = m(lon,lat)
m.scatter(x, y,marker='+',c=data,cmap=cmap, norm=norm_color,edgecolor='none')
plt.show()
When I just scatter the coordinates: m.scatter(x, y,marker='+') it works fine (I have "+" at the corresponding coordinates, i.e on the 75° latitude projected circle). But when I want to add the data, nothing is displayed.
Where am I not using scatter right ?

I found what was the problem.
It is the simultaneous use of the options marker='+' and edgecolor='None'.
The latter allows to change the color of the edge of the marker. With the marker '+', the edge is the marker itself: that is why it was not displayed.
In replacement of the line m.scatter(x, y,marker='+',c=data,cmap=cmap, norm=norm_color,edgecolor='none') the following work:
m.scatter(x, y,marker='+',c=data,cmap=cmap, norm=norm_color)
or
m.scatter(x, y,marker='o',c=data,cmap=cmap, norm=norm_color,edgecolor='none')

Related

Is there a python 3d topographical plot that works with Pandas?

I am processing x, y, and z data to have a floor map with high and lows. Z being a displacement sensor. I need to plot a topographical map with gradients. I currently have a 3D scatter plot and a contour plot using matplotlib widgets. Those work great, but a wireframe map or topgraphical map would work best. Either 2D or 3D work as well. Thank you in advance!
Current outputs:
3D Scatter
3D Contour
Example of what I am trying to achieve:
Bokeh surface 3D plot
2D plot
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import holoviews as hv
from bokeh.models import ColumnDataSource
from mpl_toolkits.mplot3d import Axes3D
from holoviews import opts
hv.extension('bokeh', 'matplotlib')
%matplotlib widget
%matplotlib inline
%matplotlib nbagg
%matplotlib ipympl
plt.style.use('seaborn-white')
#Extend width of Jupyter Notebook
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))
#Read CSV
df = pd.read_csv('Floor Scan.csv')
clean_df = df.dropna(axis = 0, how ='any')
print(clean_df)
print('')
z_offset = (clean_df['Displacement (in)'].min())
z_offset_abs = abs(z_offset)
print("Minimum Z:" + str(z_offset))
#3D SCATTER
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111, projection='3d')
x = clean_df['fActualPosition_X (-)']
y = clean_df['fActualPosition_Y (-)']
z = clean_df['Displacement (in)']
ax.scatter(x, y, (z + z_offset_abs), c='b', marker='^')
plt.xlabel("fActualPosition_X (-)")
plt.ylabel("fActualPosition_Y (-)")
plt.show()
plt.savefig('Floor_Map_Scatter_3D.svg')
#3D CONTOUR
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111, projection='3d')
X = clean_df['fActualPosition_X (-)'].astype(np.uint8)
Y = clean_df['fActualPosition_Y (-)'].astype(np.uint8)
Z = clean_df['Displacement (in)'].astype(np.uint8)
flatX = np.asarray(clean_df['fActualPosition_X (-)'])
flatY = np.asarray(clean_df['fActualPosition_Y (-)'])
flatZ = np.asarray(clean_df['Displacement (in)'])
# flatX, flatY = np.meshgrid(X, Y)
# flatZ = function(flatX, flatY, Z)
# print(flatX)
# print('')
# print(flatY)
# print('')
# print(flatZ)
# print('')
plt.tricontourf(flatX, flatY, (flatZ+z_offset_abs),20)
plt.show();
plt.savefig('Floor_Map_Contour_3D.svg')
It sounds like your original data is in the form of isolated points (from a range-measuring device like LIDAR?), and what you want is not simply to plot those points, but first to infer or interpolate a surface from those points and then plot that surface. The two desired examples both take an already calculated grid of values and plot them either as a surface or as an image, so first you need to make such a grid, which is not strictly a plotting problem but one of data processing.
One typical way of creating the grid is to aggregate the values into Cartesian coordinates, basically just counting the average value of the scatter points per grid cell. Another is to connect up all the points into a triangular mesh, which may or may not actually form a surface (a function mapping from x,y -> z).
You can use our library Datashader to aggregate just about any set of data into a regular grid, and can then display it as images or contours using hvPlot (https://hvplot.holoviz.org/user_guide/Gridded_Data.html) or as a surface or wireframe using HoloViews (http://holoviews.org/reference/elements/plotly/Surface.html#elements-plotly-gallery-surface).
If you want an unstructured grid, you can use scipy.spatial to compute a triangulation, then HoloViews to visualize it (http://holoviews.org/reference/elements/bokeh/TriMesh.html#elements-bokeh-gallery-trimesh).

Plotting over a background python basemap

How do you go about plotting data over a background image in Python?
For example if I had some gridded pressure data of shape [180,360] (lat,lon)
I could easily plot data by;
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
m = Basemap(projection='ortho',resolution='c',lat_0=45,lon_0=0)
lat = np.linspace(-90,90,180)
lon = np.linspace(-180,180,360)
lon,lat = np.meshgrid(lon,lat)
X, Y = m(lon, lat)
m.contourf(X,Y,Pressure)
plt.show()
etc etc. But if I add a background , e.g.
m.bluemarble()
I cant plot on top of this layer. I've heard of imshow, but how does that take into account gridded data? Not sure how to plot pressure on top of this. Or possibly the alpha attribute in plotting. Thanks!
For example setting alpha to 0.5 in the plt function, I get some horrible mix of colours (and white lines randomly appear);

How to set marker type for a specific point in a matplotlib scatter plot with colormap

I have a user case that, let's say I have three series data: x,y,z.
I would like to make a scatter plot using (x,y) as coordinates and z as the color of scatter points, using cmap keyword of plt.scatter. However, I would like to highlight some specific point by using a different marker type and size than other points.
​A minimum example is like below:
x,y,z = np.random.randn(3,10)
plt.scatter(x,y,c=z,cmap=matplotlib.cm.jet)
plt.colorbar()​
​If I want to use a different marker type for (x[5],y[5],z[5]), how could I do that?
The only way I can think of is to plot again for this point using plt.scatter([x[5],y[5]) but define the color by manually finding the colormap ​color corresponding to z[5]. However this is quite tedious. Is there a better way?
Each scatterplot has one single marker, you cannot by default use different markers in a single scatterplot. Hence, if you are happy to only change the markersize and leave the marker the same, you can supply an array of different sizes to the scatter's s argument.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(10)
x,y,z = np.random.randn(3,10)
sizes = [36]*len(x)
sizes[5] = 121
plt.scatter(x,y,c=z,s=sizes, cmap=plt.cm.jet)
plt.colorbar()
plt.show()
If you really need a different marker style, you can to plot a new scatter plot. You can then set the colorlimits of the second scatter to the ones from the first.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(10)
x,y,z = np.random.randn(3,10)
xs, ys, zs = [x[5]], [y[5]], [z[5]]
print xs, ys, zs
y[5] = np.nan
sc = plt.scatter(x,y,c=z,s=36, cmap=plt.cm.jet)
climx, climy = sc.get_clim()
plt.scatter(xs,ys,c=zs,s=121, marker="s", cmap=plt.cm.jet, vmin=climx, vmax=climy )
plt.colorbar()
plt.show()
Finally, a bit of a complicated solution to have several different markers in the same scatter plot would be given in this answer.

How do I use Matplotlib pyplot pcolor to provide distinct color to each grid in my plot

I have built some fairly simple logarithmic matplotlib scatter plots. I am happy with the results thus far, but I need to change the color of each grid area.
Current Plot:
I would like to understand how I could do the following:
I appreciate any help. Thanks.
Plot a small image underneath the scatter plot, with an integer indicating the tile color. You can then use pcolor to plot the image, with edgecolors to define the borders. The code below does this, with cell color defined as the maximum of cell index i, j, which happens to match your grid.
import numpy as np
import matplotlib.pyplot as plt
# define grid
nx, ny = 6, 5
x, y = np.arange(nx), np.arange(ny)
xx, yy = np.meshgrid(x, y)
z = np.maximum(xx, yy)
# create random points
npoints = 30
data_x = 10**(np.random.rand(npoints)*nx)
data_y = 10**(np.random.rand(npoints)*ny-1)
# plot grid then points
plt.pcolor(10.**x, 10.**(y-1), z, edgecolors='k')
plt.loglog(data_x, data_y, '.w')
plt.axis([1,10**5,0.1,10**3])
plt.show()
Note that you could also use zorder=n to force the scatter plot above the image.

weird contour plot with polar projections using matplotlib and basemap

I am making Polar Stereographic Projection maps of some climate model outputs. For some of these data, the plot looks weird. For example, in this figure:
only two color contours showed up while the actual data should span much wider range. Furthermore, a large portion of the region should be blank since the data are masked out by netcdf module already (they are undefined).
from netCDF4 import Dataset
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap
from pylab import *
fig_index=1
fig = plt.figure(num=fig_index, figsize=(12,7), facecolor='w')
fbot_levels = arange(0.05,1.0,0.05)
fname='alb.nc4'
ncfile = Dataset(fname, 'r', format='NETCDF4')
TS2=ncfile.variables['SIALB'][0]
LON=ncfile.variables['lon'][:]
LAT=ncfile.variables['lat'][:]
ncfile.close()
lon,lat=np.meshgrid(LON,LAT)
ax2 = plt.axes([0.2, 0.225, 0.6, 0.6])
meridians=[0,1,1,1]
m = Basemap(projection='spstere',lon_0=0,boundinglat=-45)
m.drawcoastlines()
x, y =m(lon,lat)
plt.contourf(x,y,TS2, fbot_levels, origin='lower')
m.drawparallels(np.arange(-90.,120.,15.),labels=[1,0,0,0]) # draw parallels
m.drawmeridians(np.arange(0.,420.,30.),labels=meridians) # draw meridians
coloraxis = [0.1, 0.1, 0.8, 0.035]
cx = fig.add_axes(coloraxis, label='m', title='K')
cbar=plt.colorbar(cax=cx,orientation='horizontal',ticks=list(fbot_levels))
plt.show()
You can find the dataset in netcdf format which is used to generate the figure here
https://dl.dropboxusercontent.com/u/45427012/alb.nc4
I am using basemap-1.0.6 with matplotlib-1.2.1 on py2.7.
Your Basemap object (m) also serves as the mpl axes. When plotting, you should use that instead of using plt.. So:
m.contourf(x,y,TS2, fbot_levels, origin='lower')
Stretching the levels between 0.5 and 0.9 highlights the different contours further.

Categories