Python Matplotlib Streamplot providing start points - python

I am trying to add start points to a streamline plot. I found an example code using start points here; at this link a different issue is discussed but the start_points argument works. From here I grabbed the streamline example code (images_contours_and_fields example code: streamplot_demo_features.py). I don't understand why I can define start points in one code and not the other. I get the following error when I try to define start points in the example code (streamplot_demo_features.py):
Traceback (most recent call last):
File "<ipython-input-79-981cad64cff6>", line 1, in <module>
runfile('C:/Users/Admin/.spyder/StreamlineExample.py', wdir='C:/Users/Admin/.spyder')
File "C:\ProgramData\Anaconda2\lib\site-packages\spyder\utils\site\sitecustomize.py", line 866, in runfile
execfile(filename, namespace)
File "C:\ProgramData\Anaconda2\lib\site-packages\spyder\utils\site\sitecustomize.py", line 87, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "C:/Users/Admin/.spyder/StreamlineExample.py", line 28, in <module>
ax1.streamplot(X, Y, U, V,start_points=start_points)
File "C:\ProgramData\Anaconda2\lib\site-packages\matplotlib\__init__.py", line 1891, in inner
return func(ax, *args, **kwargs)
File "C:\ProgramData\Anaconda2\lib\site-packages\matplotlib\axes\_axes.py", line 4620, in streamplot
zorder=zorder)
File "C:\ProgramData\Anaconda2\lib\site-packages\matplotlib\streamplot.py", line 144, in streamplot
sp2[:, 0] += np.abs(x[0])
ValueError: non-broadcastable output operand with shape (1,) doesn't match the broadcast shape (100,)
I've notice there isn't much on the web in way of using start_points, so any additional information would be helpful.

The main difference between the example that successfully uses start_points and the example from the matplotlib page is that the first uses 1D arrays as x and y grid, whereas the official example uses 2D arrays.
Since the documentation explicitely states
x, y : 1d arrays, an evenly spaced grid.
we might stick to 1D arrays. It's unclear why the example contradicts the docsting, but we can simply ignore that.
Now, using 1D arrays as grid, start_points works as expected in that it takes a 2-column array (first column x-coords, second y-coords).
A complete example:
import numpy as np
import matplotlib.pyplot as plt
x,y = np.linspace(-3,3,100),np.linspace(-3,3,100)
X,Y = np.meshgrid(x,y)
U = -1 - X**2 + Y
V = 1 + X - Y**2
speed = np.sqrt(U*U + V*V)
start = [[0,0], [1,2]]
fig0, ax0 = plt.subplots()
strm = ax0.streamplot(x,y, U, V, color=(.75,.90,.93))
strmS = ax0.streamplot(x,y, U, V, start_points=start, color="crimson", linewidth=2)
plt.show()

Related

Python--calculate normalized probability of a value given a list of samples

So, as the title says, I'm trying to calculate the probability of a value given a list of samples, preferably normalized so the probability is 0<p<1. I found this answer on the topic from about 6 years ago, which seemed promising. To test it, I implemented the example used in the first reply (edited for brevity):
import numpy as np
from sklearn.neighbors import KernelDensity
from scipy.integrate import quad
# Generate random samples from a mixture of 2 Gaussians
# with modes at 5 and 10
data = np.concatenate((5 + np.random.randn(10, 1),
10 + np.random.randn(30, 1)))
x = np.linspace(0, 16, 1000)[:, np.newaxis]
# Do kernel density estimation
kd = KernelDensity(kernel='gaussian', bandwidth=0.75).fit(data)
# Get probability for range of values
start = 5 # Start of the range
end = 6 # End of the range
probability = quad(lambda x: np.exp(kd.score_samples(x)), start, end)[0]
However, this approach throws the following error:
Traceback (most recent call last):
File "prob test.py", line 44, in <module>
probability = quad(lambda x: np.exp(kd.score_samples(x)), start, end)[0]
File "/usr/lib/python3/dist-packages/scipy/integrate/quadpack.py", line 340, in quad
retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
File "/usr/lib/python3/dist-packages/scipy/integrate/quadpack.py", line 448, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "prob test.py", line 44, in <lambda>
probability = quad(lambda x: np.exp(kd.score_samples(x)), start, end)[0]
File "/usr/lib/python3/dist-packages/sklearn/neighbors/_kde.py", line 190, in score_samples
X = check_array(X, order='C', dtype=DTYPE)
File "/usr/lib/python3/dist-packages/sklearn/utils/validation.py", line 545, in check_array
raise ValueError(
ValueError: Expected 2D array, got scalar array instead:
array=5.5.
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
I'm not sure how to reshape the distribution when its already inside the lambda function, and, in any case, I'm guessing this is happening because Scikit-Learn has been updated in the 6 years since this answer was written. What's the best way to work around this issue to get the probability value?
Thanks!
As said in the library:
score_samples(X): X array-like of shape (n_samples, n_features)
Therefore, you should pass an array-like and not a scalar:
probability = quad(lambda x: np.exp(kd.score_samples(np.array([[x]]))), start, end)
or:
probability = quad(lambda x: np.exp(kd.score_samples(np.array([x]).reshape(-1,1))), start, end)

IndexError: too many indices for array while creating uniform particles

I have this function here designed to create uniform particles over given x and y ranges, which are going to be 1x2 matrices. However, when I try and run it, I get the error below. I feel that there is a slicker way to assign the x and y values into my particles matrix. How can I solve this?
def create_uniform_particles(x_range, y_range, N):
particles = np.empty((N, 2))
new_x = uniform(x_range[0], x_range[1], size=(N,1))
new_y = uniform(y_range[0], y_range[1], size=(N,1))
for i in range(N):
particles[i][0] = new_x[i]
particles[i][1] = new_y[i]
return particles
#Error:
Traceback (most recent call last):
File "/Users/scottdayton/PycharmProjects/Uncertainty Research/particle.py", line 83, in <module>
particle_filter(init, sigma, obs, n, trans, sigma0)
File "/Users/scottdayton/PycharmProjects/Uncertainty Research/particle.py", line 49, in particle_filter
particles = create_uniform_particles(new_x_range, new_y_range, n)
File "/Users/scottdayton/PycharmProjects/Uncertainty Research/particle.py", line 8, in create_uniform_particles
new_x = uniform(x_range[0], x_range[1], size=(N,1))
IndexError: too many indices for array
Your code for this function appears to be correct (at least, it works for me without any modifications) when I do:
create_uniform_particles([0,1],[2,3],5)
I recommend verifying that the variables in the function one level above create_uniform_particles (wherever you set up new_x_range and new_y_range) are the shapes you were expecting. Since this function you wrote works for inputs correctly passed in, it's probably happening somewhere around there.
In terms of assigning the x's and y's, you can use hstack to concatenate the new_x and new_y vectors together into an array. Give this below a try if you like it better. As a side note, the alternative to hstack is vstack, which will concatenate them after each other instead of "next to" each other in your case.
import numpy as np
from numpy.random import uniform
def create_uniform_particles(x_range, y_range, N):
particles = np.empty((N, 2))
new_x = uniform(x_range[0], x_range[1], size=(N,1))
new_y = uniform(y_range[0], y_range[1], size=(N,1))
return np.hstack([new_x,new_y])
create_uniform_particles([0,1],[2,3],5)

Python Plotting Combine 2 Plots

I am trying to plot streamlines in matplotlib over a contour plot by combining these two plots shown below but showing my code first:
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines(lw=1)
clevs = np.linspace(-3., 3., 13)
cnplot = plt.contourf(lon,lat,anomspeed,clevs,add_labels=True,cmap='jet')
cbar = plt.colorbar(cnplot)
cbar.set_label('Standard Deviations')
plt.title('~50m Wind Speed Anomaly {} 2020'.format(calendar.month_name[currm-1]))
diffu = (uwndc - uwnd); diffv = (vwndc - vwnd)
lonn, latt = np.meshgrid(lon, lat)
plt.streamplot(lonn[0,:], latt[:,0], diffu, diffv, density=(3.5,3.5),
color='k',linewidth=0.4,arrowsize=0.6)#x,y 1D and u,v are 2D
I am getting this error (full traceback shown) when i try and run the code shown below but I do not understand 'ravel' error. I suppose it has something to do with matching coordinates or related between the two plots..? thank you for any help!
Traceback (most recent call last):
File "C:\Users\U321103\.spyder-
py3\MonthlyReport_mapsNCEP_contour_monthly_wspdv2.py", line 85, in <module>
plt.streamplot(lonn[0,:], latt[:,0], diffu, diffv, density=(3.5,3.5),
color='k',linewidth=0.4,arrowsize=0.6)
File "C:\Users\U321103\AppData\Local\Continuum\anaconda3\envs\Maps\lib\site-
packages\matplotlib\pyplot.py", line 2906, in streamplot
if data is not None else {}))
File "C:\Users\U321103\AppData\Local\Continuum\anaconda3\envs\Maps\lib\site-
packages\cartopy\mpl\geoaxes.py", line 1897, in streamplot
target_extent=target_extent)
File "C:\Users\U321103\AppData\Local\Continuum\anaconda3\envs\Maps\lib\site-
packages\cartopy\vector_transform.py", line 146, in vector_scalar_to_grid
return _interpolate_to_grid(nx, ny, x, y, u, v, *scalars, **kwargs)
File "C:\Users\U321103\AppData\Local\Continuum\anaconda3\envs\Maps\lib\site-
packages\cartopy\vector_transform.py", line 67, in _interpolate_to_grid
s_grid_tuple += (griddata(points, s.ravel(), (x_grid, y_grid),
AttributeError: 'Variable' object has no attribute 'ravel'
I'm looking to solving this same problem and I found an answer to a similar question that help me plotting streamlines and contour togheter. Take a look at here.
In a nutshell, instead of:
plt.streamplot(lonn[0,:], latt[:,0], diffu, diffv, density=(3.5,3.5), color='k',linewidth=0.4,arrowsize=0.6)
You'd use
plt.streamplot(lonn[0,:], latt[:,0], np.array(diffu), np.array(diffv), density=(3.5,3.5), color='k',linewidth=0.4,arrowsize=0.6)
The use of np.array() solves the problem for me.
Best regards,
Mateus

Differing results summing Python arrays in terminal than in script

So I have two arrays defined as below:
particles=random.uniform(0,10, size=(100, 3))
displacement=random.uniform(-2, 2+1, size=(100, 3))
I want to redefine particles as their coordinate-wise sum. Simply typing
particles = particles + displacement
into the terminal gives me exactly what I want, but when I run my script, I get the error message:
ValueError: operands could not be broadcast together with shapes
(100,3) (1,300)
What is causing one of the arrays to change shape and why doesn't this happen in the terminal?
Edit: Here is the traceback:
File "<ipython-input-4-04059a7d3a12>", line 1, in <module>
runfile('C:/Users/Garaidh/Documents/Python Scripts/3D Brownian
Tree/3DBrownianTree_fork1.py', wdir='C:/Users/Garaidh/Documents/Python
Scripts/3D Brownian Tree')
File "C:\Users\Garaidh\Anaconda3\lib\site-
packages\spyder\utils\site\sitecustomize.py", line 880, in runfile
execfile(filename, namespace)
File "C:\Users\Garaidh\Anaconda3\lib\site-
packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Garaidh/Documents/Python Scripts/3D Brownian
Tree/3DBrownianTree_fork1.py", line 58, in <module>
particles=particles+displacement
"""
something keeps fucking up here, I get an
error that I don't get in the terminal
"""
ValueError: operands could not be broadcast together with shapes (100,3)
(1,300)
and here is the code:
import numpy as np
import numpy.random as random
from scipy.spatial import distance
t=0
patiencelevel=10000
region_length=100
seeds=[]
base_seed =[region_length/2,region_length/2,0];
seeds.append(base_seed)
particles=[]
numParticles=100
part_step=5
particle_Radius = 1
region_length=10
zero_array=np.zeros((numParticles, 3))
ceiling_array=np.full((numParticles, 3), region_length)
rad_array=np.full((numParticles, len(seeds)),particle_Radius)
particles=random.uniform(0,region_length, size=(numParticles, 3))
while len(particles)>0:
displacement=random.uniform(-part_step, part_step+1, size=
(numParticles,3))
particles=displacement+particles
"""
something keeps fucking up here, I get
an error that I do not get in the terminal
"""
particles=np.maximum(particles, zero_array)
particles=np.minimum(particles, ceiling_array)
particles=list(particles)
templist=[]
for j in range(0,len(seeds)): # for each seed
for i in range(0,len(particles)):
if distance.euclidean(particles[i],seeds[j])
<=2*particle_Radius:
templist.append(particles[i])
particles=[~np.in1d(particles,templist)]
for x in templist:
seeds.append(x)
if t > patiencelevel:
break

Problem regarding axis shape in 3d surface plot in python

This is my first attempt at 3d surface plotting. Spent hours on trying to get a plot to show but no luck yet. Here is my script to do a surface plot of z_ax with respect to x_ax and y_ax. The z_ax variable is generated from some other script, but i thats irrelevant, so i just copy pasted the array just for the sake of reproduction.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
import numpy as np
z_ax = np.array([[98.0952381 , 98.37627192, 98.22459584, 97.96470716, 97.97332409,
98.55658199, 97.59356635, 97.72653459],
[98.78787879, 99.56700585, 99.26385681, 99.41539461, 99.43703447,
99.37211316, 99.28240025, 99.30172134],
[99.43722944, 99.35050877, 99.35046189, 99.3287864 , 99.50632254,
99.3432448 , 99.39993814, 99.38291653],
[99.13419913, 99.52370643, 99.52367206, 99.44787269, 99.49766153,
99.51645497, 99.55459326, 99.51824185],
[99.48051948, 99.45875731, 99.58140878, 99.58861102, 99.50632254,
99.4154157 , 99.44324157, 99.51282884],
[99.61038961, 99.41545789, 99.53810624, 99.51282884, 99.4630175 ,
99.54532333, 99.51128982, 99.55613294],
[99.43722944, 99.52370643, 99.4948037 , 99.58861102, 99.51498354,
99.48036952, 99.51747603, 99.5398939 ],
[99.48051948, 99.58865555, 99.50923788, 99.49117679, 99.41971245,
99.52367206, 99.55459326, 99.5398939 ],
[99.65367965, 99.48040701, 99.66801386, 99.577785 , 99.44569548,
99.55254042, 99.57315187, 99.59402403],
[99.39393939, 99.67525438, 99.48036952, 99.59943705, 99.5756106 ,
99.52367206, 99.52366223, 99.51282884]])
x_ax = np.linspace(0.1,0.8,8) # the test size
y_ax = np.linspace(0.01,1,10) # zero class weight
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x_ax, y_ax, z_ax)
plt.show()
However, when i run the script, i get:
Traceback (most recent call last):
File "tmp.py", line 30, in <module>
ax.plot_surface(x_ax, y_ax, z_ax)
File "C:\Python27\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 1567, in plot_surface
X, Y, Z = np.broadcast_arrays(X, Y, Z)
File "C:\Python27\lib\site-packages\numpy\lib\stride_tricks.py", line 249,
in broadcast_arrays
shape = _broadcast_shape(*args)
File "C:\Python27\lib\site-packages\numpy\lib\stride_tricks.py", line 184,
in _broadcast_shape
b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape
I checked the shapes of the co-ordinates, they seem to match for the surface plot. So, i dont understand what i am getting wrong. Any help is highly appreciated.
All the arrays have to have the same shape. See the documentation. Try to use np.meshgrid

Categories

Resources