Delete last while cycle from plt.plot - python

Im working in some Euler Equations about Draining a Conical Tank but I'm having problem when I plot the simulation.
My intention is reduce the radius of the tank while time increases. I want to delete the first blue line after the first cycle, but I don't know how :(
this is the code:
import matplotlib.pyplot as plt
import numpy as np
Hi=0.5
hf=0
r=0.003
ang=8*np.pi/180
teta=np.tan(ang)**2
dt=1
g=9.8
t=0
t1=0
h=Hi
h2=0
R=np.tan(ang)*h
R1=np.tan(ang)*
Vh=[h]
Vt=[t]
Rt=[R]
f1 = plt.figure(1)
plot1=plt.plot([R-r,0,2*R,R+r,R-r],[0,Hi,Hi,0,0],"k")
plot1=line=plt.plot([0,2*R],[h,h],"b")
plt.grid()
plt.ylabel("ALtura del agua")
while h>0 and R>0:
h=((5*((2*g)**(1/2))*r**2)/(-2*teta*((Hi**(3/2)))))*dt+h
R=(np.tan(ang)*h)
t=t+dt
plot1=line=plt.plot([R1-R,R1+R],[h,h],"b")
Vh.append(h)
Vt.append(t)
Rt.append(R)
line[0].set_ydata([h])
plt.pause(1/24)
plt.title("Tiempo = "+str(t))

Try this to delete the last line:
if h <= 0:
h = 0
Vh.append(h)
Vt.append(t)
Rt.append(R)
line[0].set_ydata([h])
plt.pause(1/24)
plt.title("Tiempo = " + str(t))
Tell me if it was useful.
Greetings

Related

how to change the color of subplot datafile in matplotlib

In Short:
I want to change the color of blue marker in the graph. So that I can do comparison with other plots easily.
You can download the data files and script from this link
Problem Explanation
I have two data files, full.dat and part.dat(Note: part.dat is also there in full.dat).
I got the plotting scripts from the internet, and it is working very well. But as a noob in Python and Matplotlib, I am facing difficulties in changing the color of part.dat.
Please see the graph first, then the following scripts.
Script-1: Function and definitions: let's say: "func.py"
# This was written by Levi Lentz for the Kolpak Group at MIT
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.gridspec as gs
import sys
#This function extracts the high symmetry points from the output of bandx.out
def Symmetries(fstring):
f = open(fstring,'r')
x = np.zeros(0)
for i in f:
if "high-symmetry" in i:
x = np.append(x,float(i.split()[-1]))
f.close()
return x
# This function takes in the datafile, the fermi energy, the symmetry file, a subplot, and the label
# It then extracts the band data, and plots the bands, the fermi energy in red, and the high symmetry points
def bndplot(datafile_full,datafile,fermi,symmetryfile,subplot,**kwargs):
if 'shift_fermi' in kwargs:
bool_shift_efermi = kwargs['shift_fermi']
else:
bool_shift_efermi = 0
if 'color' in kwargs:
color_bnd=kwargs['color']
else:
color_bnd='black'
if 'linestyle' in kwargs:
line_bnd=kwargs['linestyle']
else:
line_bnd='solid'
z = np.loadtxt(datafile_full) #This loads the full.dat file
x = np.unique(z[:,0]) #This is all the unique x-points
[a,b,w]=np.loadtxt(datafile,unpack=True) #Weight
bands = []
bndl = len(z[z[:,0]==x[1]]) #This gives the number of bands in the calculation
Fermi = float(fermi)
if bool_shift_efermi:
fermi_shift=Fermi
else:
fermi_shift=0
axis = [min(x),max(x)]
for i in range(0,bndl):
bands.append(np.zeros([len(x),2])) #This is where we storre the bands
for i in range(0,len(x)):
sel = z[z[:,0] == x[i]] #Here is the energies for a given x
test = []
for j in range(0,bndl): #This separates it out into a single band
bands[j][i][0] = x[i]
#bands[j][i][1] = np.multiply(sel[j][1],13.605698066)
bands[j][i][1] = sel[j][1]
#Here we plots the bands
for i in bands:
subplot.plot(i[:,0],i[:,1]-fermi_shift,color=color_bnd,linestyle=line_bnd, linewidth=0.7,alpha=0.5)
# plt.scatter(a,b-fermi_shift,c=w,cmap='viridis',alpha=0.5)
# plt.colorbar()
if 'legend' in kwargs:
#empty plot to generate legend
subplot.plot([None],[None],color=color_bnd,linestyle=line_bnd,label=kwargs['legend'])
temp = Symmetries(symmetryfile)
for j in temp: #This is the high symmetry lines
x1 = [j,j]
subplot.axvline(x=j,linestyle='dashed',color='black',alpha=0.75)
subplot.plot([min(x),max(x)],[Fermi-fermi_shift,Fermi-fermi_shift],color='red',linestyle='dotted')
subplot.set_xticks(temp)
subplot.set_xticklabels([])
if 'name_k_points' in kwargs:
if len(kwargs['name_k_points'])==len(temp):
subplot.set_xticklabels(kwargs['name_k_points'])
if 'range' in kwargs:
range_plot=kwargs['range']
subplot.set_ylim([range_plot[0],range_plot[1]])
subplot.set_xlim([axis[0],axis[1]])
subplot.set_xlabel('k')
subplot.set_ylabel('E-E$_f$')
plt.scatter(a,b-fermi_shift,s=70*np.array(w))
if 'legend' in kwargs:
plt.legend()
script-2 Plotting script: let's say: "plot.py"
#!/usr/bin/python3
from func import *
El='el'
orb='orb'
plt.rcParams["figure.figsize"]=(4,15)
datafile_full='bands.dat.gnu'
#datafile=El+'_'+orb+'.dat.all'
datafile=El+'_'+orb+'.dat.all'
fermi = 10.2382
symmetryfile='band.out'
bool_shift_efermi= True
fig, ax = plt.subplots()
#bndplot(datafile,fermi,symmetryfile,ax)
bndplot(datafile_full,datafile,fermi,symmetryfile,ax,shift_fermi=1,color='black',linestyle='solid',name_k_points=['K','G','M','K','H','A','L','H'], legend=El+', '+orb+'-orbital')
#ax.set_ylim(-5,5)
ax.set_ylim(-10,12)
fig.set_figheight(6)
fig.set_figwidth(4)
plt.rcParams.update({'font.size': 22})
fig.savefig("el-orb.eps")
plt.show()
In script-2, there is an option to change the color, however I want to change the color of blue marker/solid-circles(please see the graph) so that I can compare with other graphs.
Whenever I change the color, it changes the line color only.
Please help me out I am trying to understand Matplotlib uses and examples from past few hrs However as a noob I was not able to figure out how to do.

Constraining a Random Walk in python, how to make it work?

Here is the code for a random walk I made which I attempted to constrain where -5 < y < 5:
import random
import numpy as np
import matplotlib.pyplot as plt
import math
import decimal
def dirs(x):
return np.array( [math.cos(x), math.sin(x)] )
def constrainedRandomWalk(x):
numSteps = x
locations = np.zeros( (numSteps, 2) )
for i in range(1, numSteps):
r = random.randrange(628318)/100000
move = dirs(r)
locations[i] = locations[i-1] + move
if -5<locations[i][1]<5:
continue
#return locations
plt.figure(figsize=(8,8))
plt.plot( locations[:,0], locations[:,1], alpha=0.7 );
plt.xlim([-20,20])
plt.ylim([-20,20])
I attempted to constrain the "walking character" by setting a condition on the loop that
if -5<locations[i][1]<5:
continue
However, as you can see here, the character leaves the -5<y<5 region:
Can anyone let me know how to actually constrain the random walk and why this method doesn't work? Thank you!
You're updating locations before you test if the move is valid:
import math
import random
import matplotlib.pyplot as plt
import numpy as np
def dirs(x):
return np.array([math.cos(x), math.sin(x)])
def constrained_random_walk(num_steps):
# Specify Start Point
locations = [np.array([0, 0])]
# Go Until locations is long enough
while len(locations) < num_steps:
r = random.randrange(628318) / 100000
move = dirs(r)
# Test if the new move is in bounds first
new_location = locations[-1] + move
if -5 < new_location[1] < 5:
locations.append(new_location)
locations = np.array(locations)
plt.figure(figsize=(8, 8))
plt.plot(locations[:, 0], locations[:, 1], alpha=0.7)
plt.xlim([-20, 20])
plt.ylim([-20, 20])
Sample Output on:
constrained_random_walk(2000)
Edit: Updated so all skipped values are not (0,0) but every value in locations is populated by a generated move. Except for the first, which is specified as the start point. (Currently (0,0))

Why is the graph changing on every run

there. So I build a Kmean cluster program; however, each time I run the program the plot changes. I dont know why its happening and if anyone could help that would be very appreciate.
import numpy as np
import matplotlib.pyplot as plt
import random
def cal_centroids(clusters, cluster_array,k):
new_centroids= []
for c in range(k):
x= 0
y=0
count=0
for i in range(len(clusters)):
if clusters[i]==c:
x+=cluster_array[i][0]
y+=cluster_array[i][1]
count+=1
x/=count
y/=count
new_centroids.append([x,y])
return new_centroids
def assign_clusters(centroids,cluster_array):
clusters=[]
for i in range(cluster_array.shape[0]):
distances=[]
for centroid in centroids:
distances.append(calc_distance(centroid,cluster_array[i]))
cluster=[z for z, val in enumerate(distances) if val==min(distances)]
clusters.append(cluster[0])
return clusters
def calc_distance(x1,x2):
return (sum((x1-x2)**2))**0.5
#from here on its mostly storing data, initializing centroids and assigning cluster label to data
def kmean(data,no_clusters,iterations):
s= random.sample(range(data.shape[0]),no_clusters)
centroids= []
for i in s:
centroids.append(data[i,:])
clusters= assign_clusters(centroids,data)
initial_centroids= [i for i in centroids]
for i in range(0,iterations):
centroids= cal_centroids(clusters,data,no_clusters)
cluster= assign_clusters(centroids,data)
dict_centroids= {}
for i in range(no_clusters):
dict_centroids[i]=[]
for i in range(no_clusters):
for j in range(data.shape[0]):
if(clusters[j]==i):
dict_centroids[i].append(data[j,:])
return dict_centroids,centroids,clusters
def extract_file(file_name):
file = open(file_name,'r')
lines = [list(map(int, line.strip("\n").split(","))) for line in file]
x= np.array(lines)
return x
data= extract_file("backyard.txt")
dict_centroids,centroids,clusters= kmean(data,2,8)
x= data[:,0]
y= data[:,1]
fig=plt.figure()
scatter= plt.scatter(x,y,c=clusters,s=40)
for i,j in centroids:
plt.scatter(i,j,s=50,c='red',marker= '+')
plt.xlabel("Vitamin C")
plt.ylabel("GLA")
plt.title("File backyard 2 groups Displayed")
fig.show()
the backyard list is this:
40,40
10,10
200,200
230,231
40,43
15,45
220,190
I haven't run your code, however, if the graph changes on every run there is nothing to worry about. K-means is an algorithm that uses a random start (which I'm assuming you did in your code with this line: s= random.sample(range(data.shape[0]),no_clusters)). There is no guarantee that K-means will converge to a global minimum, but it will converge to a local minimum depending on the random start.
You could maybe try to fix your random start by setting a random seed with NumPy: numpy.random.seed(42)

How to display a set of files with MatPlotLib in a loop

I have a set of .txt named "occupancyGrid_i", i being a number from 0-100.
What I'd like to do is to open every one of them and show them for 3 seconds. The data of the .txt is a [N x M] matrix.
import numpy
import matplotlib.pyplot as plt
import time
while True:
matrix = numpy.loadtxt('res/matrix_' + str(i) + '.txt')
plt.clf()
plt.imshow(matrix)
plt.show()
time.sleep(3)
i=i+1
What I have done so far doesn't seem to be enough. What am I doing wrong?
You can try something like this, adapting the code suggested in this answer:
import os
import numpy as np
import pylab as plt
N_IMAGES = 100
VMIN, VMAX = 0, 1 # range of values in matrices
i = 0
while True:
if i < N_IMAGES:
path = 'res/matrix_' + str(i) + '.txt'
if os.path.exists(path): # check if file exists
matrix = np.loadtxt('matrices/matrix_' + str(i) + '.txt')
plt.imshow(matrix, vmin=VMIN, vmax=VMAX)
plt.title("Matrix {}".format(i))
plt.pause(3)
i += 1
else:
# terminate you program or start from the beginning
break
# i = 0
# continue
I dont know what exactly your goal is. But to display text in matplotlib you can use text from pyplot.
`
import numpy
import matplotlib.pyplot as plt
import time
for i in range(1,5):
s = ''
with open(str(i)+'.txt','r') as f:
s=f.read()
plt.text(0.5, 0.67,s,transform=plt.gca().transAxes)
plt.show()
time.sleep(3)
First 2 argument (0.5 ,0.67) are cordinate of displayed text.
I think you should find some other way of displaying text. Just print them on your console, plotting them is not the best way to represent text data.

Plot really big file in python (5GB) with x axis offset

I am trying to plot a very big file (~5 GB) using python and matplotlib. I am able to load the whole file in memory (the total available in the machine is 16 GB) but when I plot it using simple imshow I get a segmentation fault. This is most probable to the ulimit which I have set to 15000 but I cannot set higher. I have come to the conclusion that I need to plot my array in batches and therefore made a simple code to do that. My main isue is that when I plot a batch of the big array the x coordinates start always from 0 and there is no way I can overlay the images to create a final big one. If you have any suggestion please let me know. Also I am not able to install new packages like "Image" on this machine due to administrative rights. Here is a sample of the code that reads the first 12 lines of my array and make 3 plots.
import os
import sys
import scipy
import numpy as np
import pylab as pl
import matplotlib as mpl
import matplotlib.cm as cm
from optparse import OptionParser
from scipy import fftpack
from scipy.fftpack import *
from cmath import *
from pylab import *
import pp
import fileinput
import matplotlib.pylab as plt
import pickle
def readalllines(file1,rows,freqs):
file = open(file1,'r')
sizer = int(rows*freqs)
i = 0
q = np.zeros(sizer,'float')
for i in range(rows*freqs):
s =file.readline()
s = s.split()
#print s[4],q[i]
q[i] = float(s[4])
if i%262144 == 0:
print '\r ',int(i*100.0/(337*262144)),' percent complete',
i += 1
file.close()
return q
parser = OptionParser()
parser.add_option('-f',dest="filename",help="Read dynamic spectrum from FILE",metavar="FILE")
parser.add_option('-t',dest="dtime",help="The time integration used in seconds, default 10",default=10)
parser.add_option('-n',dest="dfreq",help="The bandwidth of each frequency channel in Hz",default=11.92092896)
parser.add_option('-w',dest="reduce",help="The chuncker divider in frequency channels, integer default 16",default=16)
(opts,args) = parser.parse_args()
rows=12
freqs = 262144
file1 = opts.filename
s = readalllines(file1,rows,freqs)
s = np.reshape(s,(rows,freqs))
s = s.T
print s.shape
#raw_input()
#s_shift = scipy.fftpack.fftshift(s)
#fig = plt.figure()
#fig.patch.set_alpha(0.0)
#axes = plt.axes()
#axes.patch.set_alpha(0.0)
###plt.ylim(0,8)
plt.ion()
i = 0
for o in range(0,rows,4):
fig = plt.figure()
#plt.clf()
plt.imshow(s[:,o:o+4],interpolation='nearest',aspect='auto', cmap=cm.gray_r, origin='lower')
if o == 0:
axis([0,rows,0,freqs])
fdf, fdff = xticks()
print fdf
xticks(fdf+o)
print xticks()
#axis([o,o+4,0,freqs])
plt.draw()
#w, h = fig.canvas.get_width_height()
#buf = np.fromstring(fig.canvas.tostring_argb(), dtype=np.uint8)
#buf.shape = (w,h,4)
#buf = np.rol(buf, 3, axis=2)
#w,h,_ = buf.shape
#img = Image.fromstring("RGBA", (w,h),buf.tostring())
#if prev:
# prev.paste(img)
# del prev
#prev = img
i += 1
pl.colorbar()
pl.show()
If you plot any array with more than ~2k pixels across something in your graphics chain will down sample the image in some way to display it on your monitor. I would recommend down sampling in a controlled way, something like
data = convert_raw_data_to_fft(args) # make sure data is row major
def ds_decimate(row,step = 100):
return row[::step]
def ds_sum(row,step):
return np.sum(row[:step*(len(row)//step)].reshape(-1,step),1)
# as per suggestion from tom10 in comments
def ds_max(row,step):
return np.max(row[:step*(len(row)//step)].reshape(-1,step),1)
data_plotable = [ds_sum(d) for d in data] # plug in which ever function you want
or interpolation.
Matplotlib is pretty memory-inefficient when plotting images. It creates several full-resolution intermediate arrays, which is probably why your program is crashing.
One solution is to downsample the image before feeding it into matplotlib, as #tcaswell suggests.
I also wrote some wrapper code to do this downsampling automatically, based on your screen resolution. It's at https://github.com/ChrisBeaumont/mpl-modest-image, if it's useful. It also has the advantage that the image is resampled on the fly, so you can still pan and zoom without sacrificing resolution where you need it.
I think you're just missing the extent=(left, right, bottom, top) keyword argument in plt.imshow.
x = np.random.randn(2, 10)
y = np.ones((4, 10))
x[0] = 0 # To make it clear which side is up, etc
y[0] = -1
plt.imshow(x, extent=(0, 10, 0, 2))
plt.imshow(y, extent=(0, 10, 2, 6))
# This is necessary, else the plot gets scaled and only shows the last array
plt.ylim(0, 6)
plt.colorbar()
plt.show()

Categories