I am trying to plot some wind vectors on maps using cartopy. However, the winds look strange so I did a simple tests using wind vectors at a ring of points at 75N. The wind vectors should points 45 degree away from both lat/lon grids because u-winds and v-winds are of the same magnitude under the stereographic projection, which should preserve the angle.
from matplotlib import pyplot as plt
import numpy as np
import cartopy.crs as ccrs
pcproj = ccrs.PlateCarree()
lon0 = -150
mapproj = ccrs.Stereographic(
central_longitude=lon0,central_latitude=75,
true_scale_latitude=75,
)
XLIM = 300e3; YLIM=300e3
dm =5; dp=1
fig = plt.figure(0,(7,7))
ax = fig.add_axes([0.1,0.1,0.85,0.9],projection=mapproj)
ax.set_extent([-XLIM,XLIM,-YLIM,YLIM],crs=mapproj)
ax.coastlines(resolution='50m',color='.5',linewidth=1.5)
lon_grid = np.arange(-180,181,dm)
lat_grid = np.arange(-80,86,dp)
gl = ax.gridlines(draw_labels=True,
xlocs=lon_grid,ylocs=lat_grid,
x_inline=False,y_inline=False,
color='k',linestyle='dotted')
# --- draw 45 degree winds at 75N
lon = np.linspace(0,360,73)
lat = np.ones(len(lon))*75
uu = np.ones(len(lon))*10
vv = uu*1.
pts = mapproj.transform_points(pcproj,lon,lat)
xx = pts[...,0]; yy = pts[...,1]
ux,vx = mapproj.transform_vectors(pcproj,lon,lat,uu,vv)
ax.quiver(xx,yy,ux,vx,transform=mapproj)
It is clear that the wind vectors does not point 45 degrees from lat/lon grids.
I check the ux, vx at 150W and 75N, the center of the projection. The wind here should be the same as in lat/lon grid but it is (3.54,13.7) rather than (10,10).
The wind vectors looks the same as using this line
ax.quiver(lon,lat,uu,vv,transform=pcproj)
This may not be a surprise because I think quiver uses transform_vector and transform_points under the hood.
I tried winds along lat/lon grid directions, they are transformed correctly.
Is this a bug in transform_vectors or am I using it incorrectly?
UPDATE:
As suggested by #swatchai, right now, u-wind should be divided by cos(lat) before being fed in to transform_vectors. I doubt this is the intended behavior but this normalization should be used until a future cartopy update changed the behavior. They may choose just to update the docstring. Still, something to be caution about in future cartopy updates.
When (lat, long) in degrees are used, a small angular distance ds on spherical surface has 2 components:
`R*dlat` in NS direction
`R*dlon*cos(lat)` in EW direction
where R is the earth radius,
the second component varies with latitude of the location considered,
with this in mind, the computation of ux, vx at latitude 75 degrees should be
rho = np.pi/180.
ux,vx = mapproj.transform_vectors(pcproj,lon,lat, uu/np.cos(75*rho), vv)
Related
I am programming in Python 3 and I have data structured like this:
coordinates = [(0.15,0.25),(0.35,0.25),(0.55,0.45),(0.65,0.10),(0.15,0.25)]
These are coordinates. Within each pair, the first number is the x coordinate and the second one the y coordinate. Some of the coordinates repeat themselves. I want to plot these data like this:
The coordinates that are most frequently found should appear either as higher intensity (i.e., brighter) points or as points with a different color (for example, red for very frequent coordinates and blue for very infrequent coordinates). Don't worry about the circle and semicircle. That's irrelevant. Is there a matplotlib plot that can do this? Scatter plots do not work because they do not report on the frequency with which each coordinate is found. They just create a cloud.
The answer is:
import matplotlib.pyplot as plt
from scipy.stats import kde
import numpy as np
xvalues = np.random.normal(loc=0.5,scale=0.01,size=50000)
yvalues = np.random.normal(loc=0.25,scale=0.1,size=50000)
nbins=300
k = kde.gaussian_kde([xvalues,yvalues])
xi, yi = np.mgrid[0:1:nbins*1j,0:1:nbins*1j]
zi = k(np.vstack([xi.flatten(),yi.flatten()]))
fig, ax = plt.subplots()
ax.pcolormesh(xi, yi, zi.reshape(xi.shape), shading='auto', cmap=plt.cm.hot)
x = np.arange(0.0,1.01,0.01,dtype=np.float64)
y = np.sqrt((0.5*0.5)-((x-0.5)*(x-0.5)))
ax.axis([0,1,0,0.55])
ax.set_ylabel('S', fontsize=16)
ax.set_xlabel('G', fontsize=16)
ax.tick_params(labelsize=12, width=3)
ax.plot(x,y,'w--')
plt.show()
I have a point cloud from different parts of the human body, like an eye and I want to do a mesh. I tried to use Mayavi and Delaunay but I don't get a good mesh. The points of the cloud are in total disorder.
I have my point cloud in .npz file
Using Mayavi
Then I want to save my model in an obj or stl file, but first I want to generate the mesh.
What do you recommend me to use, do I need a special library?
You can use pyvista to do the 3D interpolation. You need however to manually play with the alpha parameter that controls the distance under which two points are linked.
import numpy as np
import pyvista as pv
# points is a 3D numpy array (n_points, 3) coordinates of a sphere
cloud = pv.PolyData(points)
cloud.plot()
volume = cloud.delaunay_3d(alpha=2.)
shell = volume.extract_geometry()
shell.plot()
Data
Let's use the capitals of Europe. We read them in from Excel with Pandas:
import pandas as pd
dg0 = pd.read_excel('psc_StaedteEuropa_coord.xlsx') # ,header=None
dg0.head()
City Inhabit xK yK
0 Andorra 24574.0 42.506939 1.521247
1 Athen 664046.0 37.984149 23.727984
2 Belgrad 1373651.0 44.817813 20.456897
3 Berlin 3538652.0 52.517037 13.388860
4 Bern 122658.0 46.948271 7.451451
Grid by triangulation
We use Scipy for that. For a 3-dim example see HERE and HERE or here (CGAL has a Python wrapper)
import numpy as np
from scipy.spatial import Delaunay
yk, xk, city = np.array(dg0['xK']), np.array(dg0['yK']), np.array(dg0['City'])
X1 = np.vstack((xk,yk)).T
tri = Delaunay(X1)
Graphics
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
#--- grafics -------
figX = 25; figY = 18
fig1 = plt.figure(figsize=(figX, figY), facecolor='white')
myProjection = ccrs.PlateCarree()
ax = plt.axes(projection=myProjection)
ax.stock_img()
ax.set_extent([-25, 40, 35, 65], crs=myProjection)
plt.triplot(X1[:,0], X1[:,1], tri.simplices.copy(), color='r', linestyle='-',lw=2)
plt.plot(X1[:,0], X1[:,1], 's', color='w')
plt.scatter(xk,yk,s=1000,c='w')
for i, txt in enumerate(city):
ax.annotate(txt, (X1[i,0], X1[i,1]), color='k', fontweight='bold')
plt.savefig('Europe_A.png')
plt.show()
If your points are "are in total disorder", and if you want to generate a mesh, then you need some interpolation from the cloud of points to the somehow structured grid points of the mesh..
In the 2-dimensional case matplotlib's triangulation can be a help:
matplotlib's triangulation 2dim.
In the 3-dimensional case there are 2 options. Depending on the data, you might want to interpolate them to a 3-dimensional surface. Then matplotlib's trisurf3d can be a help.
If you need a 3-dimensional volume grid then you have probably to look for a FEM (finite element) grid, e.g. FEnics
An example of interpolating a 3-dimensional field with scipy for contouring can be found here
Have you tried this example? https://docs.enthought.com/mayavi/mayavi/auto/example_surface_from_irregular_data.html
The relevant part is here
# Visualize the points
pts = mlab.points3d(x, y, z, z, scale_mode='none', scale_factor=0.2)
# Create and visualize the mesh
mesh = mlab.pipeline.delaunay2d(pts)
surf = mlab.pipeline.surface(mesh)
I am currently doing my internship program in a company and my educational background is actually Petroleum Geoscience, nothing related to programming. So I apologize for any mistakes that I have made or I am about to make.
I was tasked by my supervisor to produce a polar contour plot just like the example below. The example below was generated from the OriginPro (Trial), after the trial period expires I couldn't use the commercial software anymore to produce polar contour plots so I really need help in producing the exactly the same plot in python with different set of data in the future.
The data imported for this plot are from an excel spreadsheet, there is no problem in importing data from the spreadsheet and plot heat map and contour map, the problem only arises when I attempted to produce a polar contour plot from the data given. From what I read, it is because for heat map and contour map it is projected on Cartesian plane which makes it pretty straight forward, but for polar plots you need a certain form of calculation to change from Cartesian coordination to polar coordination? please correct me if I'm wrong.
This is what happened when i tried in python, it should be looking like the example ive given above
]2
and this is the script that I used for the failed plotting
import numpy as np
import matplotlib.pyplot as plt
x = df_ODD.loc[:, 'Azimuth'].values.reshape(19,74)
y = df_ODD.loc[:, 'Inclination'].values.reshape(19,74)
z = df_ODD.loc[:, 'Values'].values.reshape(19,74)
f, ax = plt.subplots(subplot_kw=dict(projection='polar'))
plt.contour(x,y,z)
ax.set_theta_zero_location("N")
ax.set_theta_direction(-1)
cb = fig.colorbar(cax)
cax = ax.contourf(theta, r, values, 30)
cb.set_label("Normalized deviatoric stress")
plt.show()
Below is the form of data imported from the excel spreadsheet if you are wondering, only the columns labelled as "X" , "Y" and "Z", ignore the column labelled as "β, Azimuth". The rows of data stretches down until 1400++ rows.
]3
I really need help in solving this problem, I hope any of you could give me a hand. Thanks
Below is the plot i get after changing the degrees to radians.
and here is the script, i added the mathematical function of converting degrees to radians
import numpy as np
import matplotlib.pyplot as plt
import math
x = df_ODD.loc[:, 'Azimuth'].values.reshape(19,74)
y = df_ODD.loc[:, 'Inclination'].values.reshape(19,74)
z = df_ODD.loc[:, 'Values'].values.reshape(19,74)
xi = x * math.pi/180
yi = y * math.pi/180
zi = z * math.pi/180
f, ax = plt.subplots(subplot_kw=dict(projection='polar'))
plt.contour(xi,yi,zi) # choose 20 contour levels, just to show how good its interpolation is
#ax[1].plot(x,y, 'ko ')
ax.set_theta_zero_location("N")
ax.set_theta_direction(-1)
cb = fig.colorbar(cax)
cb.set_label("Normalized deviatoric stress")
#plt.savefig('attempt polar contour.png')
plt.show()
I was hoping to create an equidistant grid over Manhattan map (say 200m by 200m) projection using latitudes and longitudes not degrees. I was using basemap but couldn't figure out a way to proceed with the task. This the projection code.
m = Basemap(projection='mill',
llcrnrlat= 40.6968,
llcrnrlon= -74.0224,
urcrnrlat= 40.8964,
urcrnrlon= -73.8927,
resolution='h')
What will be the best way to do the above, I also need to store lat,long values of each grid vertex points.
From the basemap documentation:
In order to plot data on a map, the coordinates of the data must be
given in map projection coordinates. Calling a Basemap class instance
with the arguments lon, lat will convert lon/lat (in degrees) to x/y
map projection coordinates (in meters). The inverse transformation is
done if the optional keyword inverse is set to True.
There is also an example in the documentation page. To adept this example to your use case, I converted the lower left corners into meters, produced a regular grid with 2000 m spacing (200 m was a bit too dense) and converted the grid back into lon/lat coordinates, which can then be used by drawparallels() and drawmeridians.
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
fig, ax = plt.subplots()
lon0 = -74.0224
lat0 = 40.6968
m = Basemap(
projection='mill',
llcrnrlat= 40.6968,
llcrnrlon= -74.0224,
urcrnrlat= 40.8964,
urcrnrlon= -73.8927,
resolution='h',
ax = ax,
)
x0, y0 = m(lon0, lat0)
x = np.arange(20)*2000+x0
y = np.arange(20)*2000+y0
lons, lats = m(x,y,inverse=True)
m.drawcoastlines()
m.drawcountries()
m.drawstates()
m.drawmeridians(lons)
m.drawparallels(lats)
plt.show()
The result looks like this:
Hope this helps.
I'm struggling to draw a power law graph for Facebook Data that I found online. I'm using Networkx and I've found how to draw a Degree Histogram and a degree rank. The problem that I'm having is I want the y axis to be a probability so I'm assuming I need to sum up each y value and divide by the total number of nodes? Can anyone please help me do this? Once I've got this I'd like to draw a log-log graph to see if I can obtain a straight line. I'd really appreciate it if anyone could help! Here's my code:
import collections
import networkx as nx
import matplotlib.pyplot as plt
from networkx.algorithms import community
import math
import pylab as plt
g = nx.read_edgelist("/Users/Michael/Desktop/anaconda3/facebook_combined.txt","r")
nx.info(g)
degree_sequence = sorted([d for n, d in g.degree()], reverse=True)
degreeCount = collections.Counter(degree_sequence)
deg, cnt = zip(*degreeCount.items())
fig, ax = plt.subplots()
plt.bar(deg, cnt, width=0.80, color='b')
plt.title("Degree Histogram for Facebook Data")
plt.ylabel("Count")
plt.xlabel("Degree")
ax.set_xticks([d + 0.4 for d in deg])
ax.set_xticklabels(deg)
plt.show()
plt.loglog(degree_sequence, 'b-', marker='o')
plt.title("Degree rank plot")
plt.ylabel("Degree")
plt.xlabel("Rank")
plt.show()
You seem to be on the right tracks, but some simplifications will likely help you. The code below uses only 2 libraries.
Without access your graph, we can use some graph generators instead. I've chosen 2 qualitatively different types here, and deliberately chosen different sizes so that the normalization of the histogram is needed.
import networkx as nx
import matplotlib.pyplot as plt
g1 = nx.scale_free_graph(1000, )
g2 = nx.watts_strogatz_graph(2000, 6, p=0.8)
# we don't need to sort the values since the histogram will handle it for us
deg_g1 = nx.degree(g1).values()
deg_g2 = nx.degree(g2).values()
# there are smarter ways to choose bin locations, but since
# degrees must be discrete, we can be lazy...
max_degree = max(deg_g1 + deg_g2)
# plot different styles to see both
fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(deg_g1, bins=xrange(0, max_degree), density=True, histtype='bar', rwidth=0.8)
ax.hist(deg_g2, bins=xrange(0, max_degree), density=True, histtype='step', lw=3)
# setup the axes to be log/log scaled
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xlabel('degree')
ax.set_ylabel('relative density')
ax.legend()
plt.show()
This produces an output plot like this (both g1,g2 are randomised so won't be identical):
Here we can see that g1 has an approximately straight line decay in the degree distribution -- as expected for scale-free distributions on log-log axes. Conversely, g2 does not have a scale-free degree distribution.
To say anything more formal, you could look at the toolboxes from Aaron Clauset: http://tuvalu.santafe.edu/~aaronc/powerlaws/ which implement model fitting and statistical testing of power-law distributions.