I am trying to make a 3d plot as using 3 2d arrays. I get the plot just fine but I want to truncate the axes using ax.set_xlim()
This is the original plot I have:
I want to remove the long tails for each curve. I use ax.set_xlim(0,30) and this is the result:
I want to get rid of the extra part that is flowing out of the graph area. If I reduce the limits futher with ax.set_xlim(0,25), I get something even more weird:
Ideally, I would want the x-axis to only show points until 25. How can I get rid of the extra parts?
Thanks in advance!
The code (the arrays are being read from a file):
fig = plt.figure()
ax = plt.axes(projection = '3d')
for i in range(5):
ax.plot(E[:,i], freq[:,i], DF[:,i])
ax.set_zlabel(filename + "$\ [eV^{-1} cm^{-3}]$")
ax.set_xlabel("$\epsilon [eV]$")
ax.set_ylabel("f [MHz]")
ax.set_xlim(0,25)
ax.set_yticks(freq[0])
fig.savefig(filename+"3d.png", dpi = 1500, bbox_inches='tight')
Data file from where the data is being read: File
Related
So I am trying to create a 3D scatter plot of radar data, where each point is assigned an alpha value based on the amplitude of the corresponding pixel.
I have done this looping through all x,y,z points and building the scatter plot point by point assigning the alpha values on each iteration. But once the scatter plot is created it is very slow and unable to manipulate the graph without considerable time spent waiting for the plot to update.
Points is a normalised (0 to 1) array.
Here is a link to my data
Data
File preparation:
def normalise0to1(data):
normalised = (data - np.min(data)) / (np.max(data) - np.min(data))
return normalised
Data = np.loadtxt('filepath.txt')
points2D = normalise0to1(Data) #Is (101,400) size
points3D = np.reshape(points2D,(101,20,20)) #Is (101,20,20) size
And the first attempt at creating the 3D scatter plot:
def Scatter_Plot1(points3D):
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
for x in range(0,points3D[1]):
for y in range(0,points3D[2]):
for z in range(0,points3D[0]):
val = points3D[z,x,y]
ax.scatter(x, y, z, alpha=val,c='black',s=1)
plt.show()
This takes a long time to run and is very slow once created.
In 2D, I can do something like this. Bear in mind this is the same array as the 3D 'points' array, but the (20x20) has been flattened to 400. I have provided an image of the flattened array, you can see how it creates an image where intensity is scaled to the alpha value.
def Scatter_Plot2(points2D):
fig = plt.figure()
ax = fig.add_subplot()
x_=np.linspace(0,points2D.shape[1]-1,points2D.shape[1])
y_=np.linspace(0,points2D.shape[0]-1,points2D.shape[0])
x,y = np.meshgrid(x_,y_)
ax.scatter(x,y,alpha=points2D.flatten(),s=1,c='black')
plt.show()
This image is the flattened version of the 3D plot I want to create, where instead of 400 length, it would be (20x20) and overall the 3D shape is (101,20,20).
The problem comes when trying to assign the alpha to a 3D plot, in 2D it seems happy enough when I provide a flattened array to the alpha parameter.
I would like something like this, but whether that's possible is another question..
def Scatter_Plot3(points3D):
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
x_=np.linspace(0,points3D.shape[2]-1,points3D.shape[2])
y_=np.linspace(0,points3D.shape[1]-1,points3D.shape[1])
z_=np.linspace(0,points3D.shape[0]-1,points3D.shape[0])
x,y,z = np.meshgrid(x_,y_,z_)
ax.scatter(x,y,z,alpha=points3D,s=1,c='black')
plt.show()
Results in this image, which seems a bit random in terms of how the alpha is assigned. You would expect to see the dark horizontal lines as in the first picture. What I want may not be possible, I'm open to using another package, perhaps pyqtgraph or mayavi etc. But matplotlib would be preferable.
Thank you!
Edit:
I have achieved something similar to what I would like, though not exactly. I have used the c and cmap inputs. This isn't ideal as I am dealing with a 3D cube and viewing the centre is still difficult but it has correctly mapped a variation to the data. But it doesn't work when I use the alpha parameter.
Notice the 2 main horizontal bands and the dark bit in the centre which is hard to see.
What I need is the same mapping but rather opacity than colour.
c = (points2D.T.flatten())
ax.scatter(x,y,z,s=1,c=c,cmap='viridis_r')
optional context feel free to skip: I'm currently using cartopy and matplotlib to read in and plot weather model data on a map. I have three different fields I'm plotting: temperature, wind, and surface pressure. I'm using contourf, barbs, and contour respectively to plot each field. I want one image for each field, and then I'd like one image that contains all three fields overlaid on a single map. Currently I'm doing this by plotting each field individually, saving each of the individual images, then replotting all three fields on a single ax and a new fig, and saving that fig. Since the data takes a while to plot, I would like to be able to plot each of the single fields, then combine the axes into one final image.
I'd like to be able to combine multiple matplotlib axes without replotting the data on the axes. I'm not sure if this is possible, but doing so would be a pretty major time and performance saver. An example of what I'm talking about:
from matplotlib import pyplot as plt
import numpy as np
x1 = np.linspace(0, 2*np.pi, 100)
x2 = x1 + 5
y = np.sin(x1)
firstFig = plt.figure()
firstAx = firstFig.gca()
firstAx.scatter(x1, y, 1, "red")
firstAx.set_xlim([0, 12])
secondFig = plt.figure()
secondAx = secondFig.gca()
secondAx.scatter(x2, y, 1, "blue")
secondAx.set_xlim([0, 12])
firstFig.savefig("1.png")
secondFig.savefig("2.png")
This generates two images, 1.png and 2.png.
Is it possible to save a third file, 3.png that would look something like the following, but without calling scatter again, because for my dataset, the actual plotting takes a long time?
If you just want to save images of your plots and you don't intend to further use the Figure objects, you can use the following after saving "2.png".
# get the scatter object from the first figure
scatter = firstAx.get_children()[0]
# remove it from this collection so you can assign it to a new axis
# the axis reassignment will raise an error if it already belongs to another axis
scatter.remove()
scatter.axes = secondAx
# now you can add it to your new axis
secondAx.add_artist(scatter)
secondFig.savefig("3.png")
This modifies both figures, as it removes a scatter from one and adds it to another. If for some reason you want to preserve them, you can copy the contents of secondFig to a new one and then add the scatter to that. However, this will still modify the first plot as you have to remove the scatter from there.
This is a bit of an odd problem I've encountered. I'm trying to read data from a CSV file in Python, and have the two resulting lines be inside of the same box, with different scales so they're both clear to read.
The CSV file looks like this:
Date,difference,current
11/19/20, 0, 606771
11/20/20, 14612, 621383
and the code looks like this:
data = pd.read_csv('data.csv')
time = data['Time']
ycurr = data['current']
ydif = data['difference']
fig, ax = plt.subplots()
line1, = ax.plot(time, ycurr, label='Current total')
line1.set_dashes([2, 2, 10, 2]) # 2pt line, 2pt break, 10pt line, 2pt break
line2, = ax.twinx().plot(time, ydif, dashes=[6, 2], label='Difference')
ax.legend()
plt.show()
I can display the graphs with the X-axis having Date values and Y-axis having difference values or current values just fine.
However, when I attempt to use subplots() and use the twinx() attribute with the second line, I can only see one of two lines.
I initially thought this might be a formatting issue in my code, so I updated the code to have the second line be ax2 = ax1.twin(x) and call upon the second line using this, but the result stayed the same. I suspect that this might be an issue with reading in the CSV data? I tried to do read in x = np.linspace(0, 10, 500) y = np.sin(x) y2 = np.sin(x-0.05) instead and that worked:
Everything is working as expected but probably not how you want it to work!
So each line only consists of two data points which in the end will give you a linear curve. Both of these curves share the same x-coordinates while the y-axis is scaled for each plot. And here comes the problem, both axes are scaled to display the data in the same way. This means, the curves lie perfectly on top of each other. It is difficult to see because both lines are dashed.
You can see what is going on by changing the colors of the line. For example add color='C1' to one of the curves.
By the way, what do you want to show with your plot? A curve consisting of two data points mostly doesn't show much and you are better of if you just show their values directly instead.
So I have a line plot, and I want to add markers on only some of the points along the plot (I have detected the peaks in the plot and want to mark them). When I plot without the peaks labelled it works as it should, and when I plot the peaks alone it seems to plot them properly, but when I try to plot them on the same plot, the line plot disappears over most of the graph and seems to maybe have become compressed to the side of the plot, if that makes any sense?
Here is my code without the peaks plotted and the resulting graph:
def plotPeaks(file):
indices, powerSums, times=detectPeaks(file)
plt.figure(figsize=(100, 10))
plt.plot(times, powerSums)
Plot without peaks marked
Then when I add the code that should show the peaks, which occur at x-values corresponding to the values stored in the indices, I get this:
def plotPeaks(file):
indices, powerSums, times=detectPeaks(file)
plt.figure(figsize=(100, 10))
plt.plot(times, powerSums)
for i in indices:
plt.scatter(i, powerSums[i], marker='o')
Plot with peaks marked
Am I missing something obvious, or is this a glitch that someone has a solution for?
Assuming indices stores indices of times, this should be the last line.
plt.scatter(times[i], powerSums[i], marker='o')
I need to save a figure (with 8 subplots on it) generated from matpolotlib in python3.2. I need to same save the figure on one pdf page.
Each subplot nmay have 240k to 400k data points.
My code:
from matplotlib.backends.backend_pdf import PdfPages
plt.show(block=False)
pp = PdfPages('multipage.pdf')
fig = plt.figure()
fig.savefig('figure_1.pdf', dpi = fig.dpi)
pp.close()
But, only an empty pdf file was created and no figures on it.
Any help would be appreciated.
UPDATE
This is a demo code:
def plot_pdf_example():
fig = plt.figure()
# I create subplots here
#x = np.random.rand(50)
#y = np.random.rand(50)
plt.plot(x, y, '.')
fig.savefig('figure_b.pdf')
if __name__ == '__main__':
r = plot_pdf_example()
# the return value of r is not 0 for my case
print("donne")
If I used plt.show() to get the figure in pop-up window, there are some titles and legends overlaps between subplots. How to adjuse the pop-up figure so that I can get all subplots without any overlaps and also keep all subplots as square. keeping them as square uis very important for me.
Your code does save the single and empty figure fig to the file figure_1.pdf, without making any use of PdfPages. It is also normal that the pdf file is empty, since you are not plotting anything in fig. Below is a MWE that shows how to save only one figure to a single pdf file. I've removed all the stuff with PdfPages that was not necessary.
Update (2015-07-27): When there is some problem saving a fig to pdf because there is too much data to render or in the cases of complex and detailed colormaps, it may be a good idea to rasterize some of the elements of the plot that are problematic. The MWE below has been updated to reflect that.
import matplotlib.pyplot as plt
import numpy as np
import time
plt.close("all")
fig = plt.figure()
N = 400000
x = np.random.rand(400000)
y = np.random.rand(400000)
colors = np.random.rand(400000)
area = 3
ax0 = fig.add_axes([0.1, 0.1, 0.85, 0.85])
scater = ax0.scatter(x, y, s=area, c=colors)
scater.set_rasterized(True)
plt.show(block=False)
ts = time.clock()
fig.savefig('figure_1.pdf')
te = time.clock()
print('t = %f sec' % (te-ts))
On my machine, the code above took about 6.5 sec to save the pdf when rasterized was set to true for scater, while it took 61.5 sec when it was set to False.
By default, when saving in pdf, the figure is saved in vectorial format. This means that every point is saved as a set of parameters (colors, size, position, etc). This is a lot of information to store when there is a lot of data (8 * 400k in the case of the OP). When converting some elements of the plot to a raster format, the number of points plotted does not matter because the image is saved as a fixed number of pixels instead (like in a png). By only rasterizing the scater, the rest of the figure (axes, labels, text, legend, etc.) still remains in vectorial format. So overall, the loss in quality is not that much noticeable for some type of graph (like colormaps or scatter plots), but it will be for graphs with sharp lines.