I want to extract polar coordinates from the plot. There exists a matrix that has 10 rows and 2 columns a and b. This matrix has the numbers that created the polar plot.
But what I am looking for is a matrix that has the polar coordinates that are already plotted.
Example: the first row (meaning, information about the first point) would include the x,y,radius and theta/angle or any other useful information from the plot that were previously not there in the original matrix.
Think of polar plotting as a transformation that was implemented on the matrix in the for loop and I want to extract the new numbers resulted from the output polar plot.
import matplotlib.pyplot as plt
sample= [1,2,3,4,5,6,7,8,9,10]
fig = plt.figure()
fig.add_subplot(111, projection='polar')
data = sample
for i in data:
a=i+min(data)
b=i+max(data)
plt.polar(a,b, '.', c='black')
plt.show()
Even after your clarification I am a little confused by the code example. But I am pretty sure the code below answers your question.
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random((10,1)) # same as "a" in your example
y = np.random.random((10,1)) # same as "b" in your example
plt.plot(x,y)
plt.title("Rectangular coordinates")
plt.show()
th = np.arctan2(y,x)
r = np.sqrt(x**2 + y**2)
# Should show the same plot as above, just with different margins/aspect ratio/grid lines
plt.polar(th,r)
plt.title("Polar coordinates")
plt.show()
It's just as easy to go in reverse, getting the rectangular coordinates if you assume your random data is representing data in polar coordinates.
Related
I'm trying to generate a 3d plot from a few datapoints. My goal is it, to compare two different datasets and show how good they match at different points. Right now I'm working on the first surface and my supervisor is unhappy with the visualization.
I use the following code at the moment:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d
# Create the figure and axes objects
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Define the data for the first surface
x1 = [25,35,40,45,50,55,60]
y1 = [1300,4000,5000,5400]
z1 = [8.06,5.81,5.10,4.55,4.1,3.01,2.51,6.46,4.93,4.4,4.03,3.15,2.83,2.4,5.95,4.6,3.87,3.19,2.91,2.7,2.36,5.69,4.29,3.63,3.1,2.85,2.65,2.33]
# Convert the z1 data to 2D arrays
x, y = np.meshgrid(x1, y1)
z1 = np.array(z1).reshape(x.shape)
# Plot the first surface
ax.plot_surface(x, y, z1)
# Show the plot
plt.show()
And as a result the following plot is displayed:
enter image description here
My supervisor wants it to look something like this:
enter image description here
Note that this is a completly different diagram with a different dataset and also different axes.
I wonder if it is even possible to generate such a high resolution of a grid with so few datapoints.
Has is something to do with the way the points are connected in the diagram? In my diagram it looks like a linear interpolation. Is it possible to influence the interpolation?
I would be glad if anyone has an idea and is able to help me.
Thanks, and all the best!
I tried this but got an error that they are not the same size
x = np.linspace(0,501,num=50)
y = np.linspace(0,501,num=50)
for i in range(10,510,10):
plt.scatter(x,i,c='dimgrey')
ax = plt.gca()
ax.set_facecolor('darkgrey')
plt.xlim(0,501)
plt.ylim(0,501);
My overall goal is to have N amount of points plotted in a grid orientation in the scatter plot. I was tying to plot 2500 points like this.
All I could come up with was one row or column would equal 50 points,
and I made this loop.
I want to fill the plot like this: a line of points at y= 10 as I have here, then at 20,30,40... so on. I realize I could do this manually but is there an easier way I could incorporate it into the loop? I am planning on putting it into an animation later.
Here is an simple example, starting from your code.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,501,num=50)
for i in range(10,40,10):
y = i * np.ones(50)
plt.scatter(x,y)
This gives the following plot :
I am trying to superimpose a contour plot onto a basemap plot of coastlines. Right now it either plots both separately or just the basemap.
Xa = np.linspace(-93.6683,-93.2683,25)
Ya = np.linspace(29.005,29.405,25)
plt.figure()
m = Basemap(width=1200000,height=900000,projection='lcc',resolution='f',lat_1=29.205,lat_2=29.5,lat_0=29.205,lon_0=-93,4683)
m.drawcoastlines()
plt.contourf(Ya,Xa,Result.reshape(len(Xa),len(Ya)))
plt.colorbar()
plt.show()
The Result in the code are the concentrations that are plotted as a contour. I would add them, but there are 625 values for concentration from running my code.
Im wondering how I can write the plotting part of my code to be able to superimpose the two graphs. Thanks!
You would want to use basemap's contour function here. This has however some particularities.
It accepts only 2D arrays as input, meaning, you need to create a meshgrid of coordinates first.
and the input must be the mapped coordinates, x,y = m(X,Y)
Also pay attention to the dimensions. The first dimension of a numpy array is the y axis, the second dimension is the x axis.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
Xa = np.linspace(-93.6683,-93.2683,25)
Ya = np.linspace(29.005,29.405,25)
X,Y = np.meshgrid(Xa,Ya)
Result = np.random.rand(len(Ya)*len(Xa))
m = Basemap(width=1200000,height=900000,projection='lcc',resolution='c',
lat_1=29.205,lat_2=29.5,lat_0=29.205,lon_0=-93.4683)
m.drawcoastlines()
mx,my = m(X,Y)
m.contourf(mx,my,Result.reshape(len(Ya),len(Xa)))
plt.colorbar()
plt.show()
I want to change the the look of the mean in violinplots. I am using matplotlib. I could change the color of the means with the following code:
import matplotlib.pyplot as plt
fig,(axes1,axes2,axes3) = plt.subplots(nrows=3,ncols=1,figsize=(10,20))
r=axes2.violinplot(D,showmeans=True,showmedians=True)
r['cmeans'].set_color('red')
But now I want to change the look of the mean (currently a line, like the median) to a 'small circle'.
Can someone help me with this?
The idea can be to obtain the coordinates of the mean lines and plot a scatter plot at those coordinates.
Obtaining the coordinates can
either be done by looping over the mean lines' paths,
# loop over the paths of the mean lines
xy = [[l.vertices[:,0].mean(),l.vertices[0,1]] for l in r['cmeans'].get_paths()]
xy = np.array(xy)
or by reacalculating the mean from the input data.
#alternatively get the means from the data
y = data.mean(axis=0)
x = np.arange(1,len(y)+1)
xy=np.c_[x,y]
Complete code:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
data = np.random.normal(size=(50, 2))
fig,ax = plt.subplots()
r=ax.violinplot(data,showmeans=True)
# loop over the paths of the mean lines
xy = [[l.vertices[:,0].mean(),l.vertices[0,1]] for l in r['cmeans'].get_paths()]
xy = np.array(xy)
##alternatively get the means from the data
#y = data.mean(axis=0)
#x = np.arange(1,len(y)+1)
#xy=np.c_[x,y]
ax.scatter(xy[:,0], xy[:,1],s=121, c="crimson", marker="o", zorder=3)
# make lines invisible
r['cmeans'].set_visible(False)
plt.show()
I'd like to create an Argand Diagram from a set of complex numbers using matplotlib.
Are there any pre-built functions to help me do this?
Can anyone recommend an approach?
Image by LeonardoG, CC-SA-3.0
I'm not sure exactly what you're after here...you have a set of complex numbers, and want to map them to the plane by using their real part as the x coordinate and the imaginary part as y?
If so you can get the real part of any python imaginary number with number.real and the imaginary part with number.imag. If you're using numpy, it also provides a set of helper functions numpy.real and numpy.imag etc. which work on numpy arrays.
So for instance if you had an array of complex numbers stored something like this:
In [13]: a = n.arange(5) + 1j*n.arange(6,11)
In [14]: a
Out[14]: array([ 0. +6.j, 1. +7.j, 2. +8.j, 3. +9.j, 4.+10.j])
...you can just do
In [15]: fig,ax = subplots()
In [16]: ax.scatter(a.real,a.imag)
This plots dots on an argand diagram for each point.
edit: For the plotting part, you must of course have imported matplotlib.pyplot via from matplotlib.pyplot import * or (as I did) use the ipython shell in pylab mode.
To follow up #inclement's answer; the following function produces an argand plot that is centred around 0,0 and scaled to the maximum absolute value in the set of complex numbers.
I used the plot function and specified solid lines from (0,0). These can be removed by replacing ro- with ro.
def argand(a):
import matplotlib.pyplot as plt
import numpy as np
for x in range(len(a)):
plt.plot([0,a[x].real],[0,a[x].imag],'ro-',label='python')
limit=np.max(np.ceil(np.absolute(a))) # set limits for axis
plt.xlim((-limit,limit))
plt.ylim((-limit,limit))
plt.ylabel('Imaginary')
plt.xlabel('Real')
plt.show()
For example:
>>> a = n.arange(5) + 1j*n.arange(6,11)
>>> from argand import argand
>>> argand(a)
produces:
EDIT:
I have just realised there is also a polar plot function:
for x in a:
plt.polar([0,angle(x)],[0,abs(x)],marker='o')
If you prefer a plot like the one below
one type of plot
or this one second type of plot
you can do this simply by these two lines (as an example for the plots above):
z=[20+10j,15,-10-10j,5+15j] # array of complex values
complex_plane2(z,1) # function to be called
by using a simple jupyter code from here
https://github.com/osnove/other/blob/master/complex_plane.py
I have written it for my own purposes. Even better it it helps to others.
To get that:
You can use:
cmath.polar to convert a complex number to polar rho-theta coordinates. In the code below this function is first vectorized in order to process an array of complex numbers instead of a single number, this is just to prevent the use an explicit loop.
A pyplot axis with its projection type set to polar. Plot can be done using pyplot.stem or pyplot.scatter.
In order to plot horizontal and vertical lines for Cartesian coordinates there are two possibilities:
Add a Cartesian axis and plot Cartesian coordinates. This solution is described in this question. I don't think it's an easy solution as the Cartesian axis won't be centered, nor it will have the correct scaling factor.
Use the polar axis, and translate Cartesian coordinates for projections into polar coordinates. This is the solution I used to plot the graph above. To not clutter the graph I've shown only one point with its projected Cartesian coordinates.
Code used for the plot above:
from cmath import pi, e, polar
from numpy import linspace, vectorize, sin, cos
from numpy.random import rand
from matplotlib import pyplot as plt
# Arrays of evenly spaced angles, and random lengths
angles = linspace(0, 2*pi, 12, endpoint=False)
lengths = 3*rand(*angles.shape)
# Create an array of complex numbers in Cartesian form
z = lengths * e ** (1j*angles)
# Convert back to polar form
vect_polar = vectorize(polar)
rho_theta = vect_polar(z)
# Plot numbers on polar projection
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.stem(rho_theta[1], rho_theta[0])
# Get a number, find projections on axes
n = 11
rho, theta = rho_theta[0][n], rho_theta[1][n]
a = cos(theta)
b = sin(theta)
rho_h, theta_h = abs(a)*rho, 0 if a >= 0 else -pi
rho_v, theta_v = abs(b)*rho, pi/2 if b >= 0 else -pi/2
# Plot h/v lines on polar projection
ax.plot((theta_h, theta), (rho_h, rho), c='r', ls='--')
ax.plot((theta, theta_v), (rho, rho_v), c='g', ls='--')
import matplotlib.pyplot as plt
from numpy import *
'''
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
This draws the axis for argand diagram
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
'''
r = 1
Y = [r*exp(1j*theta) for theta in linspace(0,2*pi, 200)]
Y = array(Y)
plt.plot(real(Y), imag(Y), 'r')
plt.ylabel('Imaginary')
plt.xlabel('Real')
plt.axhline(y=0,color='black')
plt.axvline(x=0, color='black')
def argand(complex_number):
'''
This function takes a complex number.
'''
y = complex_number
x1,y1 = [0,real(y)], [0, imag(y)]
x2,y2 = [real(y), real(y)], [0, imag(y)]
plt.plot(x1,y1, 'r') # Draw the hypotenuse
plt.plot(x2,y2, 'r') # Draw the projection on real-axis
plt.plot(real(y), imag(y), 'bo')
[argand(r*exp(1j*theta)) for theta in linspace(0,2*pi,100)]
plt.show()
https://github.com/QuantumNovice/Matplotlib-Argand-Diagram/blob/master/argand.py