Ive been making little videos of the Lorenz attractor recently by plotting various steps in the Lorenz attractor trace in python, saving the plots as images then combining the images into a video. By default, a saved plot in python doesnt really have good resolution so I have been trying to boost the resolution by using the 'dpi=' argument in plt.savefig, but recently the resolution hasnt been increasing and has been staying the default value for some videos, but for others it comes out crisp and clear. Can anyone tell me where im going wrong? Here is the code im using along with a youtube link showing the low resolution even after using a high dpi argument. And no, its not just youtube compressing the video, it looked like that before uploading as well.
Youtube video showing problem: https://www.youtube.com/watch?v=0TpxeMxYs5A
Code:
# lorenzAttractorTrace() takes in the amount of frames you want to video to be along with the system paramters s, r and b. Default value is just a known value that gives a known result to use as sanity checks
# Will save images to target directory where you will then have to run ffmpeg through the command line to use. Ffmpeg comand is given in the next line
# ffmpeg -start_number 0 -framerate 60 -i graph%01d.png video.webm
def lorenzAttractorTrace(frames, s=10, r=28, b=2.667, clean=False, rotation=False):
#Empty the target directory
clearDirectory()
#Calculate the array of points according to the lorenz system
#Do this outside the main loop so that we only calculate it once rather than a bazillion times and annihilate memory
dt = 0.01
numSteps = frames
xyzs = np.empty((numSteps+1, 3)) # Need one more for the initial values
xyzs[0] = (0., 1., 1.05) # Set initial values
for i in range(numSteps):
xyzs[i + 1] = xyzs[i] + lorenz(xyzs[i],s,r,b) * dt
# Checking if the attractor is clean or not to determine what the first frame should look like
if clean == True:
#plot the first frame outside of the main loop, same idea as initial conditions just with a frame
ax = plt.figure().add_subplot(projection='3d')
ax.plot(*xyzs[0].T, lw=0.5)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
ax.grid(None)
ax.axis('off')
plt.savefig('./Images for simulation/graph'+str(0)+'.png')
plt.close('all')
else:
#plot the first frame outside of the main loop, same idea as initial conditions just with a frame
ax = plt.figure().add_subplot(projection='3d')
ax.plot(*xyzs[0].T, lw=0.5)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
ax.set_title("Lorenz Attractor")
plt.savefig('./Images for simulation/graph'+str(0)+'.png')
plt.close('all')
#Non-rotation video
if rotation == False:
#Initialize frame to 1 so that our indexing for xyzs in the main loop prints from 0-frame. If frame was 0 then we would be plotting xysz from xyzs[0] ot xyzs[0] which we cant do. We need atleast xyzs[0] to xyzs[1]
frame = 1
while frame < numSteps:
ax = plt.figure().add_subplot(projection='3d')
ax.plot(*xyzs[:frame].T, lw=0.5) #Recall this [:frame] notion means we plot the array from xyzs[0] to xyzs[frame]
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
plt.xlim((-25,25))
plt.ylim((-30,35))
ax.set_zlim(0,60)
if clean == True:
ax.grid(None)
ax.axis('off')
else:
ax.set_title("Lorenz Attractor")
pass
plt.savefig('./Images for simulation/graph'+str(frame)+'.png', dpi=300) # dpi argument increases resolution
plt.close('all')
frame = frame + 1
#Rotation video, add in the ax.view_init() function which takes in spherical coordinate
else:
#Initialize frame to 1 so that our indexing for xyzs in the main loop prints from 0-frame. If frame was 0 then we would be plotting xysz from xyzs[0] ot xyzs[0] which we cant do. We need atleast xyzs[0] to xyzs[1]
frame = 1
angle = 0
while frame < numSteps:
ax = plt.figure().add_subplot(projection='3d')
ax.plot(*xyzs[:frame].T, lw=0.5) #Recall this [:frame] notion means we plot the array from xyzs[0] to xyzs[frame]
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
plt.xlim((-25,25))
plt.ylim((-30,35))
ax.set_zlim(0,60)
ax.view_init(30,angle)
if clean == True:
ax.grid(None)
ax.axis('off')
else:
ax.set_title("Lorenz Attractor")
pass
plt.savefig('./Images for simulation/graph'+str(frame)+'.png', dpi=300) # dpi argument increases resolution
plt.close('all')
frame = frame + 1
angle = angle + 1