Giving peak number to the plot - python

I have the following script which reads the ascii file of two columns and generates 1D plot. The graph has several peaks. What I want is to give all the peak a number like first peak 1, second peak 2 and so on. The peaks appear in an equidistant position in X axis. Can someone tell me how to do that in python. The code-
from pylab import*
# Read the file.
f2 = open('d012_SAXS-recomb.txt', 'r')
# read the whole file into a single variable, which is a list of every row of the file.
lines = f2.readlines()[2:-100]
f2.close()
# initialize some variable to be lists:
x1 = []
y1 = []
# scan the rows of the file stored in lines, and put the values into some variables:
for line in lines:
p = line.split()
x1.append(float(p[0]))
y1.append(float(p[1]))
x = np.array(x1)
y = np.array(y1)
xlim(0.0,4.0)
# now, plot the data:
#subplot(211)
plt.plot(x, y, color='orange',linewidth=2.0, linestyle='-', label='Arabic - LPP''\nRoman - SPP''\nAsterisk - CHOL')
legend(loc='upper right')
xlabel('q')
ylabel('Intensity')
plt.show()

Here's some example code that finds the first (highest) peak. (BTW, I'm using pylab here, so the plot and numpy modules are already imported).
x = linspace(0,10,501)
y = exp(-0.2*x)*sin(x)
k = y.argmax()
plot(x,y)
text(x[k],y[k],'Peak1')
Try that to get started.

Related

Matplotlib not plotting at all correctly, not seen anyone else have this issue

So, I'm trying to code with matplotlib, so that it plots coordinates of the majority of cities in the USA on a graph. As should be evident by the fact I'm asking this question, it isn't working. The code is just plotting all the points on a single diagonal line, shown below, and both axises are completely out of order (you can see it clearly on the y-axis). Below is both an image of the result, and the matplotlib code I'm using:
Image of multiple points on a single diagonal line with no order to either axises
Code:
def demand(places, distfact):
demandList = []
fig = plt.figure()
print(len(places))
for origin in places:
for destination in places:
if origin != destination:
dist = haversine(float(origin.lat), float(origin.lon), float(destination.lat),
float(destination.lon))
result = (int(origin.population) * int(destination.population)) / (dist * distfact)
line1 = [origin.name, destination.name, result,
[origin.lat, origin.lon], [destination.lat, destination.lon]]
line2 = [destination.name, origin.name, result,
[destination.lat, destination.lon], [origin.lat, origin.lon]]
if line2 not in demandList and result >= 75000000 and dist >= 30.0:
demandList.append(line1)
demandList.sort(key=lambda row: (row[2]), reverse=True)
for i in range(0, 20):
print(demandList[i][0], "->", demandList[i][1], ":", "{:,}".format(demandList[i][2]))
print("\n")
print(len(demandList) - 30, "routes")
print("\n")
for i in range(0,10):
ind = len(demandList) - i - 1
print(demandList[ind][0], "->", demandList[ind][1], ":", "{:,}".format(demandList[ind][2]))
for i in range(len(demandList)):
xpoints = np.array([demandList[i][3][0], demandList[i][4][0]])
ypoints = np.array([demandList[i][3][1], demandList[i][4][1]])
plt.plot(xpoints, ypoints, "o")
"places" is a list of objects. Each object contains a townID, name, population, latitude and longtitude. distfact is simply a number, in this example it's set to 5.
Just a guess as I can't see what's in your variables: try casting the values from your x_points and y_points variables to whatever makes sense in your case be it float or int. It seems to me that they are seen as strings by pyplot.
edit: Not a guess anymore, you're missing casts to float, when populating line1 with latitudes and longitudes. You do do it in your haversine computations but not three lines below.

How to plot in 3D with a double entry table - Matplotlib

I would like to plot in 3D with Pandas / MatplotLib (Wireframe or other, I do not care) but in a specific way..
I'm using RFID sensors and I'm trying to record the signal I receive at different distance + different angles. And I want to see the correlation between the rising of the distance and the angle.
So that's why I want to plot in 3D :
X Axis -> the Distance, Y Axis -> the Angle, Z Axis -> the signal received which means a float
My CSV file from where I generate my DataFrame is organized like this a double entry table :
Distance;0;23;45;90;120;180
0;-53.145;-53.08;-53.1;-53.035;-53.035;-53.035
5;-53.145;-53.145;-53.05;-53.145;-53.145;-53.145
15;-53.145;-53.145;-53.145;-53.145;-53.145;-53.145
25;-53.145;-52.145;-53.145;-53.002;-53.145;-53.145
40;-53.145;-53.002;-51.145;-53.145;-54.255;-53.145
60;-53.145;-53.145;-53.145;-53.145;-53.145;-53.145
80;-53.145;-53.145;-53.145;-53.145;-60;-53.145
100;-53.145;-52;-53.145;-54;-53.145;-53.145
120;-53.145;-53.145;-53.145;-53.145;-53.002;-53.145
140;-51.754;-53.145;-51.845;-53.145;-53.145;-53.145
160;-53.145;-53.145;-49;-53.145;-53.145;-53.145
180;-53.145;-53.145;-53.145;-53.145;-53.145;-53.002
200;-53.145;-53.145;-53.145;-53.145;-53.145;-53.145
On the first label row we've different angles : 0°, 23°, 45°, ...
And the index of the DataFrame is the distance : 0 cm, 15 cm...
And the matrix inside represents the signal, so, values of Z Axis...
But I do not know how to generate a 3D Scatter, WireFrame... because in every tutorial I see people that use specific columns as axis.
Indeed, in my CSV file on the first row I've the label of all columns
Distance;0 ;23 ;45 ;90 ;120;180
And I do not know how to generate a 3D plot with a double entry table.
Do you know how to do it ? Or, to generate my CSV file in a better way to see the same result at the end !
I would be grateful if you would help me about this !
Thank you !
maybe contour is enough
b = np.array([0,5,15,25,40,60,80,100,120,140,160,180,200])
a = np.array([0,23,45,90,120,180])
x, y = np.meshgrid(a, b)
z = np.random.randint(-50,-40, (x.shape))
scm = plt.contourf(x, y, z, cmap='inferno')
plt.colorbar(scm)
plt.xticks(a)
plt.yticks(b)
plt.xlabel('Distance')
plt.ylabel('Angle')
plt.show()
displays
You can get a contour plot with something like this (but for the data shown it is not very interesting since all the values are constant at -45):
df = pd.read_csv(sep=';')
df = df.set_index('Distance')
x = df.index
y = df.columns.astype(int)
z = df.values
X,Y = np.meshgrid(x,y)
Z = z.T
plt.contourf(X,Y,Z,cmap='jet')
plt.colorbar()
plt.show()
Welcome to stackoverflow, your question can be split into several steps:
Step 1 - read the data
I have stored your data in a file called data.txt.
I don't know Pandas very well but this can also be handled with the nice simple function of Numpy called loadtxt. Your data is a bit problematic because of the text 'Distance' value in the first column and first row. But don't panic we load the file as a matrix of strings:
raw_data = np.loadtxt('data.txt', delimiter=';', dtype=np.string_)
Step 2 - transform the raw data
To extract the wanted data from the raw data we can do the following:
angle = raw_data[0 , 1:].astype(float)
distance = raw_data[1:, 0 ].astype(float)
data = raw_data[1:, 1:].astype(float)
With indexing the raw data we select the data that we want and with astype we change the string values to numbers.
Intermediate step - making the data a bit fancier
Your data was a bit boring, only the value -45, i took the liberty to make it a bit fancier:
data = (50 + angle[np.newaxis,:]) / (10 + np.sqrt(distance[:,np.newaxis]))
Step 4 - make a wireframe plot
The example at matplotlib.org looks easy enough:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(X, Y, Z)
plt.show()
But the trick is to get the X, Y, Z parameters right...
Step 3 - make the X and Y data
The Z data is simply our data values:
Z = data
The X and Y should also be 2D array's such that plot_wireframe can find the x and y for each value of Z in the 2D arrays X an Y at the same array locations. There is a Numpy function to create these 2D array's:
X, Y = np.meshgrid(angle, distance)
Step 5 - fancing it up a bit
ax.set_xticks(angle)
ax.set_yticks(distance[::2])
ax.set_xlabel('angle')
ax.set_ylabel('distance')
Putting it together
All steps together in the right order:
# necessary includes...
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
raw_data = np.loadtxt('data.txt', delimiter=';', dtype=np.string_)
angle = raw_data[0 , 1:].astype(float)
distance = raw_data[1:, 0 ].astype(float)
data = raw_data[1:, 1:].astype(float)
# make the example data a bit more interesting...
data = (50 + angle[np.newaxis,:]) / (10 + np.sqrt(distance[:,np.newaxis]))
# setting up the plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# the trickey part creating the data that plot_wireframe wants
Z = data
X, Y = np.meshgrid(angle, distance)
ax.plot_wireframe(X, Y, Z)
# fancing it up a bit
ax.set_xticks(angle)
ax.set_yticks(distance[::2])
ax.set_xlabel('angle')
ax.set_ylabel('distance')
# and showing the plot ...
plt.show()

Python: Get values of array which correspond to contour lines

Is there a way to extract the data from an array, which corresponds to a line of a contourplot in python? I.e. I have the following code:
n = 100
x, y = np.mgrid[0:1:n*1j, 0:1:n*1j]
plt.contour(x,y,values)
where values is a 2d array with data (I stored the data in a file but it seems not to be possible to upload it here). The picture below shows the corresponding contourplot. My question is, if it is possible to get exactly the data from values, which corresponds e.g. to the left contourline in the plot?
Worth noting here, since this post was the top hit when I had the same question, that this can be done with scikit-image much more simply than with matplotlib. I'd encourage you to check out skimage.measure.find_contours. A snippet of their example:
from skimage import measure
x, y = np.ogrid[-np.pi:np.pi:100j, -np.pi:np.pi:100j]
r = np.sin(np.exp((np.sin(x)**3 + np.cos(y)**2)))
contours = measure.find_contours(r, 0.8)
which can then be plotted/manipulated as you need. I like this more because you don't have to get into the deep weeds of matplotlib.
plt.contour returns a QuadContourSet. From that, we can access the individual lines using:
cs.collections[0].get_paths()
This returns all the individual paths. To access the actual x, y locations, we need to look at the vertices attribute of each path. The first contour drawn should be accessible using:
X, Y = cs.collections[0].get_paths()[0].vertices.T
See the example below to see how to access any of the given lines. In the example I only access the first one:
import matplotlib.pyplot as plt
import numpy as np
n = 100
x, y = np.mgrid[0:1:n*1j, 0:1:n*1j]
values = x**0.5 * y**0.5
fig1, ax1 = plt.subplots(1)
cs = plt.contour(x, y, values)
lines = []
for line in cs.collections[0].get_paths():
lines.append(line.vertices)
fig1.savefig('contours1.png')
fig2, ax2 = plt.subplots(1)
ax2.plot(lines[0][:, 0], lines[0][:, 1])
fig2.savefig('contours2.png')
contours1.png:
contours2.png:
plt.contour returns a QuadContourSet which holds the data you're after.
See Get coordinates from the contour in matplotlib? (which this question is probably a duplicate of...)

Extract XY lines of specific orientation python

now I have a new dataset that the first 2 columns are X and Y points (in general they represent locations. the data file are pretty large, and for initial data analysis I need to extract specific lines (or close to line data) - is there any way to tell numpy (or python, or pandas) to extract this specific data set - attached is an example, which is simplified and the data are pretty rounded (which is not the case with the real data) but will clearly show what I need:
Example EDIT*
import os
import sys
import numpy as np
X = list(range(45))*3
Y = list(range(1, 91, 2)) + list(range(20, 65, 1)) + list(range(1, 136, 3))
XY = zip(X, Y)
XYarray = np.array(XY).reshape(135, 2)
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.plot(XYarray[:,0], XYarray[:,1], 'ro') #all data
plt.plot(XYarray[0:44,0], XYarray[0:44,1], 'b*') #first line to be teste
#plt.plot(XYarray[45:90,0], XYarray[45:90,1], 'g*') #other lines of interest
#plt.plot(XYarray[91:135,0], XYarray[91:135,1], 'gx') #otherline of ineters
fig.show()
all my data lie within an arbitrary XY array (surface spatial data) -I need to extract lines availlable; for example I want to extract only the uncommented blue star line - and then move the next ones (currently commented in the code
Keep in mind that my actual data are not that regular
Hope that helps

Getting a contour plot to use data from a CSV file

Hi experienced python community.
I often collect magnetic data as part of my job but I have to wait until I am back from the field to process the data to check it for quality. This data comes in this format:-
Time,F,Ef,FP,Easting,Northing,Height
21:51:02,53169.31,-14.3,-17.79,386330.362,7371876.155,540.939
This can be outputted in different formats such as txt, xls or in this case a csv. My aim is to be able to plot it quickly on a laptop and check that there is no contamination to the data.
Using Google lead me to stackoverflow and looking through various posts I have come up with the script which is below. Thank you to all for these posts.
My problems is that I can read the csv file but I can't understand how to then get that data into the plotting section and removing the unwanted numbers from line 27 onwards. I am sure you will find it rather simple but I have been going around in circles for the last 2 weeks due to my lack of experience. Thank you to all who reply.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as ml
f = open("filename.csv")
data = np.genfromtxt('filename.csv', dtype=[('Time',float),('F',float),('Ef',float),
('FP',float),('E',float),('N',float),('H',float)],
comments='"', delimiter=',')
#only here so that I can see the file is being
#read so will probably remove it later
for line in f:
print line
#below is copied from elsewhere in stackoverflow and trying to adapt
#to my needs so at the moment I get this a Duplicate Point Warning.
#So I need to call the above into what is below.
ndata = 100
ny, nx = 100, 200
xmin, xmax = 1, 50
ymin, ymax = 1, 50
x = np.random.randint(xmin, xmax, ndata)
y = np.random.randint(ymin, ymax, ndata)
z = np.random.random(ndata)
xi = np.linspace(xmin, xmax, nx) #
yi = np.linspace(ymin, ymax, ny) #
zi = ml.griddata(x, y, z, xi, yi) #
plt.contour(xi, yi, zi, 15, linewidths = 0.5, colors = 'k')
plt.pcolormesh(xi, yi, zi, cmap = plt.get_cmap('rainbow'))
plt.colorbar()
plt.scatter(x, y, marker = 'o', c = 'b', s = 5, zorder = 10)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.show()
Two things. First, you're doing a good deal more work than necessary when reading in the data. As long as you always have exactly one header line, you should just do something simple like
data = np.genfromtxt('filename.csv', skip_header=1, delimiter=',')
Here, the skip_header=1 just says to skip the first line. Note that your data will have nan in the first column. That's fine; it just says that numpy doesn't recognize your time string. But I assume you don't need that for plotting. Note that you don't need to do f = open("filename.csv") at all, and if you ever do want to, be sure to use f.close() once you're done with it.
Second, to plot, you need to reshape your data. The plt.contour function takes three main arguments. The first and second specify your x and y coordinates, while the third specifies the z values. If there are N_x and N_y coordinate values, then z has to have N_x * N_y values.
I'll have to assume that your CSV file is in some particular order. Here, I'll assume that it first goes through values of Easting, then repeats the values of Easting for different values of Northing. Then your data will be something like
x = data[:N_x,4]
y = data[::N_x,5]
z = data[:,6].reshape(N_y,N_x)
Here, data[:N_x,4] takes the first N_x values from the 5th column (which is number 4 when you start with 0), which should give you all the different x values. Then, data[::N_x,5] takes all the numbers from the 6th column, but skips N_x at a time, so that it gets the different y values. Finally, the reshape command takes your Height data, and makes it into a rectangular array for plotting. If you want something other than Height, use a value other than 6.
Then, you simply plot the data with something like
plt.contour(x,y,z)
plt.show()
Everything else in that lower section in your code is either to construct some random sample data, or to add other bells and whistles to the plot. It's probably best to play around with those only after you get something basic working.

Categories

Resources