I am still getting my feet with python, so apologies if this is a very simple question.
I have an output file which contains 5 columns, as follows:
Depth Data#1 Data#2 Data#3 Standard_deviation
These columns contain 500 values, if this makes any difference.
What I am trying to do is simply plot data#1, data#2, and data#3 (on the x axis) against depth (on the y axis). I would like data#1 to be blue, and data#2 and data#3 to each be red.
The figsize I would like is (14,6).
I don't want the column containing standard deviation to be plotted here. If it is simpler, I can simply remove that column from the output.
Thanks in advance for any help!
With nearly everything with matplotlib, the way I go about it if i don't know how to do it already, is to just scan through the Gallery to find something that looks similar to what i want to do, and then alter the code there already.
This one has most of what you want in it:
http://matplotlib.org/examples/style_sheets/plot_fivethirtyeight.html
"""
This shows an example of the "fivethirtyeight" styling, which
tries to replicate the styles from FiveThirtyEight.com.
"""
from matplotlib import pyplot as plt
import numpy as np
x = np.linspace(0, 10)
with plt.style.context('fivethirtyeight'):
plt.plot(x, np.sin(x) + x + np.random.randn(50))
plt.plot(x, np.sin(x) + 0.5 * x + np.random.randn(50))
plt.plot(x, np.sin(x) + 2 * x + np.random.randn(50))
plt.show()
It does unfortunately have a load of extra stuff in it you don't want, but the part you should pick up on is that plt.plot(...) can just be called multiple times to plot multiple lines.
Then it's just a case of applying this;
from matplotlib import pyplot
#Make some data
depth = range(500)
allData = zip(*[[x, 2*x, 3*x] for x in depth])
#Set out colours
colours = ["blue", "red", "red"]
for data, colour in zip(allData, colours):
pyplot.plot(depth, data, color=colour)
pyplot.show()
its matplotlibs basics:
import pylab as pl
data = pl.loadtxt("myfile.txt")
pl.figure(figsize=(14,6))
pl.plot(data[:,1], data[:,0], "b")
pl.plot(data[:,2], data[:,0], "r")
pl.plot(data[:,3], data[:,0], "r")
pl.show()
As the question only regard plotting I am assuming you know how to read the data from the file. As for the plotting what you need is the following:
import matplotlib.pyplot as plt
#Create a figure with a certain size
plt.figure(figsize = (14, 6))
#Plot x versus y
plt.plot(data1, depth, color = "blue")
plt.plot(data2, depth, color = "red")
plt.plot(data3, depth, color = "red")
#Save the figure
plt.savefig("figure.png", dpi = 300, bbox_inches = "tight")
#Show the figure
plt.show()
The option bbox_inches = "tight" in savefig results in removing all the excess white boundaries of the figure.
Related
I'm trying to get the text in my legend to match the color of the lines from the plot. There is a nice summary of how to do this by Dan, over here: Matplotlib: Color-coded text in legend instead of a line
However, it does not seem to work for errorbar plot types. Does anyone have an idea of what handle I should use to make this change?
Here's some example code that shows how it works with the plot type element, but doesn't work with the errorbar type element:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.1,4,0.5)
y1 = np.exp(-x)
y2 = np.exp(-x)*1.2+0.25
plot = plt.figure()
ax = plot.add_axes([0,0,1,1])
ax.plot(x,y1,color="red",label="Y1")
ax.errorbar(x,y2,yerr=0.1,color="blue",marker='*',capsize=4,label="Y2")
leg = ax.legend();
for line, text in zip(leg.get_lines(), leg.get_texts()):
text.set_color(line.get_color())
And here's an example of how that plot looks:
Code will change text color of plot types but not errorbar types
Thanks for any advice!
The .get_lines() method gives you the lines in the legend.
[h for h in self.legendHandles if isinstance(h, Line2D)]
The errorbar is not a Line2D. So in principle you could instead iterate over leg.legendHandles. The problem is then that colors are not well specified. They may be names or arrays. This needs to be taken care of such that the solution becomes a bit more complicated.
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.1,4,0.5)
y1 = np.exp(-x)
y2 = np.exp(-x)*1.2+0.25
plot = plt.figure()
ax = plot.add_axes([0,0,1,1])
ax.plot(x,y1,color="red",label="Y1")
ax.errorbar(x,y2,yerr=0.1,color="blue",marker='*',capsize=4,label="Y2")
leg = ax.legend();
for artist, text in zip(leg.legendHandles, leg.get_texts()):
col = artist.get_color()
if isinstance(col, np.ndarray):
col = col[0]
text.set_color(col)
plt.show()
I read a waveform from an oscilloscope. The waveform is divided into 10 segments as a function of time. I want to plot the complete waveform, one segment above (or under) another, 'with a vertical offset', so to speak. Additionally, a color map is necessary to show the signal intensity. I've only been able to get the following plot:
As you can see, all the curves are superimposed, which is unacceptable. One could add an offset to the y data but this is not how I would like to do it. Surely there is a much neater way of plotting my data? I've tried a few things to solve this issue using pylab but I am not even sure how to proceed and if this is the right way to go.
Any help will be appreciated.
import readTrc #helps read binary data from an oscilloscope
import matplotlib.pyplot as plt
fName = r"...trc"
datX, datY, m = readTrc.readTrc(fName)
segments = m['SUBARRAY_COUNT'] #number of segments
x, y = [], []
for i in range(segments+1):
x.append(datX[segments*i:segments*(i+1)])
y.append(datY[segments*i:segments*(i+1)])
plt.plot(x,y)
plt.show()
A plot with a vertical offset sounds like a frequency trail.
Here's one approach that does just adjust the y value.
Frequency Trail in MatPlotLib
The same plot has also been coined a joyplot/ridgeline plot. Seaborn has an implementation that creates a series of plots (FacetGrid), and then adjusts the offset between them for a similar effect.
https://seaborn.pydata.org/examples/kde_joyplot.html
An example using a line plot might look like:
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
segments = 10
points_per_segment = 100
#your data preparation will vary
x = np.tile(np.arange(points_per_segment), segments)
z = np.floor(np.arange(points_per_segment * segments)/points_per_segment)
y = np.sin(x * (1 + z))
df = pd.DataFrame({'x': x, 'y': y, 'z': z})
pal = sns.color_palette()
g = sns.FacetGrid(df, row="z", hue="z", aspect=15, height=.5, palette=pal)
g.map(plt.plot, 'x', 'y')
g.map(plt.axhline, y=0, lw=2, clip_on=False)
# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.00)
g.set_titles("")
g.set(yticks=[])
g.despine(bottom=True, left=True)
plt.show()
Out:
I use the functions plot() and hist() from pyplot (without any color definition) to generate the following graphic:
There will be even more data sets included. That's why I want to use the same color for fit curve and the related histogram, to keep it somewhat distinguishable.
I couldn't find anything related to it.
to make sure the plot and the histogram have the same colour, my suggestion is that you fix the colour for the plot and for the best fit line.
If you look at the example here http://matplotlib.org/1.2.1/examples/pylab_examples/histogram_demo.html
and then at the python documentation for pyplot http://matplotlib.org/1.2.1/api/pyplot_api.html?highlight=hist#matplotlib.pyplot.hist
the matplotlib.pyplot.hist method has a kwarg color that allows you to choose the colour you want for the histogram. In the example they set facecolor='green'
Then for the best fit line, you can choose to plot it in the same colour. I would need to see the code to give more precise indications. However if we go back to the example here the line properties are set:
l = plt.plot(bins, y, 'r--', linewidth=1)
so if we wanted the fit line to be green like the rest of the histogram we would use:
l = plt.plot(bins, y, 'r--', linewidth=1, color = 'green')
Hope this helps, can't give you more specific tips if you don't post any lines of code.
I found a solution using
plt.gca().set_color_cycle(None)
Thanks to Reset color cycle in Matplotlib
The following code should work out of the box to complete my question regarding gaussian fit with same color as bars of histogram
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import numpy as np
list_of_lists = []
for i in range(2):
list = np.random.normal(0, 1, 100)
list = list.tolist()
list_of_lists.append(list)
plt.figure()
plt.hist(list_of_lists, bins = 10, normed=True)
numb_lists = len(list_of_lists)
plt.gca().set_color_cycle(None)
for i in range(0, numb_lists):
list = list_of_lists[i][:]
mean = np.mean(list)
variance = np.var(list)
sigma = np.sqrt(variance)
x = np.linspace(min(list), max(list), 100)
plt.plot(x, mlab.normpdf(x, mean, sigma))
I import a fits file and basically want to plot it as a contourplot. The problem arises with the aspect ratio. The image has 320x240 dimensions and since I don't want the picture to be stretched, I want the ratio of the image to be 320/240 also.
Python, however, forces it to a square like thing, which is why I used plt.axis('equal')
This however creates white areas in the plotting area and I don't know how to get rid off them...
Any ideas?
Thanks a lot!!
import numpy
import math
from astropy.io import fits
import matplotlib.pyplot as plt
scidatafile=fits.open('24-02-2015-PSF-OD00-iris15-30pin.fits')
scidata=scidatafile[0].data
oneframe=scidata[0]
oneframe[oneframe<0]=0
yvec=numpy.linspace(0,240,240)
xvec=numpy.linspace(0,320,320)
X,Y=numpy.meshgrid(xvec,yvec)
There it goes
plt.contourf(X,Y,oneframe)
plt.axis('equal')
plt.savefig('this.pdf')
plt.show()
First you should post a minimal working example. As you use data not made available, I just used some own dummy data.
Basically the problem is setting the aspect ratio before any data is in the axis. I don't know why and if it was me, I would mark this as bug not a feature. So instead set the aspect ratio after calling contourf.
I also don't understand why aspect=1 doesn't work for contourf, while it works for imshow.
from numpy import *
from matplotlib.pyplot import *
# dummy data preparations
x = linspace( -3.0, 3.0, 100 )
y = linspace( -2.0, 2.0, 100 )
def V( x, y=None ):
if y == None:
return 1.0/x
xv,yv = meshgrid( x, y, sparse=False, indexing='xy' )
return 1.0 / sqrt(xv**2+yv**2)
rlev = sqrt(18.) / 2.**linspace( 0,4,10 )
pic = V(x,y)
# your try to plot it which results in white borders
fig = figure()
title('old version')
contourf( x, y, pic, levels=V(rlev) )
axis('equal')
tight_layout()
savefig('old.png')
Need 10 rep to post picture: 'old.png'
# method without white borders
fig = figure()
title('new version')
ax = subplot(1,1,1)
contourf( x, y, pic, levels=V(rlev) )
ax.set_aspect('equal')
tight_layout()
savefig('new.png')
show()
Need 10 rep to post picture: 'new.png'
Using pylab, you can do it like this:
import pylab as pl
import numpy as np
yvec=np.linspace(0,240,240)
xvec=np.linspace(0,320,320)
X,Y=np.meshgrid(xvec,yvec)
Z = X**2 + Y**2 # function to plot
sx = 8
sy = sx*float(yvec.size)/float(xvec.size) # reset y-scale to match array dimensions
fig, ax = pl.subplots(figsize=(sx, sy))
ax.contourf(X,Y,Z)
In plain matplotlib, I think you can get the same effect using gcf() to manipulate the figure.
I want to color the line in a plot based on the following of a data set on the y axis.
if data > 0:
color = 'r'
if data = 0:
color = 'g'
if data < 0:
color = 'b'
Unfortunately I only know how to color the entire data set one color. I also couldn't find anything on the web. I'm assuming there is a way to do this without breaking up the dataset for every time the color changes.
Below is an example of plotting the data with just one color.
import matplotlib.pyplot as plt
import numpy as np
# Simple data
x = np.linspace(0, 2 * np.pi, 400)
data = np.sin(x ** 2)
#plot
f, ax = plt.subplots()
ax.plot(x, data, color='r')
plt.show()
The color parameter actually can take a list as an argument. For example, here's a simple bit of code that sets up a list of colors based on whether the data is positive or negative:
colors = []
for item in data:
if item < 0:
colors.append('r')
else:
colors.append('g')
then simply:
ax.bar(x, data, color=colors)
Edit: So I tested it, and it appears that my answer is only applicable for bar graphs. I couldn't find anything in the matplotlib documentation that seemed to indicate that coloring a line plot with multiple colors was possible. I did, however find this site, which I believe has the information you want. The guy there defines his own function to achieve it.
Using the file at my link, here is an equivalent version for a line graph:
cmap = ListedColormap(['r', 'g']) # use the colors red and green
norm = BoundaryNorm([-1000,0,1000], cmap.N) # map red to negative and green to positive
# this may work with just 0 in the list
fig, axes = plt.subplots()
colorline(x, data, data, cmap=cmap, norm=norm)
plt.xlim(x.min(), x.max())
plt.ylim(data.min(), data.max())
plt.show()
The last three arguments of colorline here tell it the color data and how to map it.