I'm having trouble trying to display my results after the program is finished. I'm expecting to see a velocity vs position graph, but for some reason, it's not showing up. Is there something wrong with my code.
import numpy
from matplotlib import pyplot
import time,sys
#specifying parameters
nx=41 # number of space steps
nt=25 #number of time steps
dt=0.025 #width between time intervals
dx=2/(nx-1) #width between space intervals
c=1 # the speed of the initial wave
#boundary conditions
u = numpy.ones(nx)
u[int(0.5/dx):int(1/(dx+1))] = 2
un = numpy.ones(nx)
#initializing the velocity function
for i in range(nt):
un= u.copy()
for i in range(1,nx):
u[i]= un[i] -c*(dt/dx)*(u[i]-u[i-1])
pyplot.xlabel('Position')
pyplot.ylabel('Velocity')
pyplot.plot(numpy.linspace(0,2,nx),u)
There are a few things going on here
You don't need to write out the full name of the packages you are importing. You can just use aliasing to call those packages and use them with those aliases later on. This, for example.
import numpy as np
Your dx value initalization will give you 0 beause you are dividing 2 by 40 which will give you a zero. You can initialize the value of dx by making one of the values in that expression a float, so something like this.
dx=float(2)/(nx-1) #width between space intervals
As Meowcolm Law in the comments suggested in the comments, add pyplot.show() to
show the graph. This is what the edited version of your code will like
import numpy as np
import matplotlib.pyplot as plt
import time,sys
#specifying parameters
nx=41 # number of space steps
nt=25 #number of time steps
dt=0.025 #width between time intervals
dx=float(2)/(nx-1) #width between space intervals
c=1 # the speed of the initial wave
#boundary conditions
u = np.ones(nx)
u[int(0.5/dx):int(1/(dx+1))] = 2
un = np.ones(nx)
#initializing the velocity function
for i in range(nt):
un= u.copy()
for i in range(1,nx):
u[i]= un[i] -c*(dt/dx)*(u[i]-u[i-1])
plt.xlabel('Position')
plt.ylabel('Velocity')
plt.plot(np.linspace(0,2,nx),u)
plt.show()
You can add
%matplotlib inline
in order to view the plot inside the notebook. I missed this step following the same guide.
Related
I was trying to simulate a square wave with a duty cycle but something went wrong and i've been spending the last 3 hours understandig why.
Here are the pictures of what the function i have to use (1), what i should get (2), what I get (3) and the script (4).
https://imgur.com/a/mcbwoyS
δ varies from o to 1 (in my plot it was 0.6)
Here is my code
#libraries
import numpy as np
from matplotlib import pyplot as plt
#function
R=3290
C=1.1693*10**(-6)
f=1000
ft=10
tau=(ft*2*np.pi)**-1
delta=tau*f
D=0.6
x=np.linspace(-2/f,2/f, 4999)
k=np.zeros(5000)
i=0
k[0]=1
while i<5000:
k[i]=2*i+1
i+=1
ck = (2/(np.pi*k))*np.sin(k*np.pi*D)
omegak=(2*np.pi)*k*f
Ak=1/(np.sqrt(1+(k*f/ft)**2))
Dphik=np.arctan(-k*f/ft)
g=np.zeros(4999)
for j in range(0,4999):
g[j]=np.sum(ck*np.cos(omegak*x[j]))
#plot
plt.figure(figsize=(10,5))
plt.plot(x, g)
plt.xlabel('t[T]')
plt.ylabel('g(t)')
plt.show()
As you can see from the pictures i doesn't really work that well and i dont know why.
I hope I explain this correctly.
I'm looking for a way to better visualise underwater noise.
I'm not after a solution (well, maybe I am) but more interested in what the perfect start would be, considering speed is of essence (so pretty much your opinion of Q1 to Q3).
I’m trying perform calculations and visualisations of a body of water.
For this I want basically import the bathymetry (csv containing x,y,z) of a substantial area (lets say 50kmx50km).
Q1: do I use a pandas dataframe or numpy array.
Q2: do you envision this as a mesh, where the column names are x and row names are y and the elevation(z) are the fields?
As z can be positive or negative, the landmass starts when z>0, which will always vary depending on tide. I want to be able to increase or decrease the low and high tide on the ‘fly’
The actual seafloor bottom is also important depending on the surface, salinity, water temperature per meter ect.
Q3: is this where I should go 3D (in mesh?)
For now I was just focussing on importing the bathymetry and visualise what I imported in a graphical way (and failing a bit).
So far my code looks like below, sorry about the lack of comments.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
import pandas as pd
import tkinter as tk
from tkinter import filedialog
import scipy
from scipy import interpolate
# min_? is minimum bound, max_? is maximum bound,
# dim_? is the granularity in that direction
filename = filedialog.askopenfilename()
df = pd.read_csv(filename, delimiter=',',names=["X", "Y", "Z"])
df.sort_values(by=["X"])
mat = df.to_numpy()
min_x = np.array(df['X'].values.tolist()).min(axis=0)
max_x = np.array(df['X'].values.tolist()).max(axis=0)
min_y = np.array(df['Y'].values.tolist()).min(axis=0)
max_y = np.array(df['Y'].values.tolist()).max(axis=0)
min_Z = np.array(df['Z'].values.tolist()).min(axis=0)
max_z = np.array(df['Z'].values.tolist()).max(axis=0)
dim_x = np.array(df['X'].count())
dim_y = np.array(df['Y'].count())
x=df.columns[0:]
y=df.columns[1:]
z=df.columns[2:]
x = np.linspace(min_x, max_x, dim_x)
y = np.linspace(min_y, max_y, dim_y)
X,Y = np.meshgrid(x, y)
# Interpolate (x,y,z) points [mat] over a normal (x,y) grid [X,Y]
# Depending on your "error", you may be able to use other methods
Z = scipy.interpolate.griddata((mat[:,0], mat[:,1]), mat[:,2], (X,Y),method='linear')
plt.pcolormesh(X,Y,Z)
plt.show()
In my work I have the task to read in a CSV file and do calculations with it. The CSV file consists of 9 different columns and about 150 lines with different values acquired from sensors. First the horizontal acceleration was determined, from which the distance was derived by double integration. This represents the lower plot of the two plots in the picture. The upper plot represents the so-called force data. The orange graph shows the plot over the 9th column of the CSV file and the blue graph shows the plot over the 7th column of the CSV file.
As you can see I have drawn two vertical lines in the lower plot in the picture. These lines represent the x-value, which in the upper plot is the global minimum of the orange function and the intersection with the blue function. Now I want to do the following, but I need some help: While I want the intersection point between the first vertical line and the graph to be (0,0), i.e. the function has to be moved down. How do I achieve this? Furthermore, the piece of the function before this first intersection point (shown in purple) should be omitted, so that the function really only starts at this point. How can I do this?
In the following picture I try to demonstrate how I would like to do that:
If you need my code, here you can see it:
import numpy as np
import matplotlib.pyplot as plt
import math as m
import loaddataa as ld
import scipy.integrate as inte
from scipy.signal import find_peaks
import pandas as pd
import os
# Loading of the values
print(os.path.realpath(__file__))
a,b = os.path.split(os.path.realpath(__file__))
print(os.chdir(a))
print(os.chdir('..'))
print(os.chdir('..'))
path=os.getcwd()
path=path+"\\Data\\1 Fabienne\\Test1\\left foot\\50cm"
print(path)
dataListStride = ld.loadData(path)
indexStrideData = 0
strideData = dataListStride[indexStrideData]
#%%Calculation of the horizontal acceleration
def horizontal(yAngle, yAcceleration, xAcceleration):
a = ((m.cos(m.radians(yAngle)))*yAcceleration)-((m.sin(m.radians(yAngle)))*xAcceleration)
return a
resultsHorizontal = list()
for i in range (len(strideData)):
strideData_yAngle = strideData.to_numpy()[i, 2]
strideData_xAcceleration = strideData.to_numpy()[i, 4]
strideData_yAcceleration = strideData.to_numpy()[i, 5]
resultsHorizontal.append(horizontal(strideData_yAngle, strideData_yAcceleration, strideData_xAcceleration))
resultsHorizontal.insert(0, 0)
#plt.plot(x_values, resultsHorizontal)
#%%
#x-axis "convert" into time: 100 Hertz makes 0.01 seconds
scale_factor = 0.01
x_values = np.arange(len(resultsHorizontal)) * scale_factor
#Calculation of the global high and low points
heel_one=pd.Series(strideData.iloc[:,7])
plt.scatter(heel_one.idxmax()*scale_factor,heel_one.max(), color='red')
plt.scatter(heel_one.idxmin()*scale_factor,heel_one.min(), color='blue')
heel_two=pd.Series(strideData.iloc[:,9])
plt.scatter(heel_two.idxmax()*scale_factor,heel_two.max(), color='orange')
plt.scatter(heel_two.idxmin()*scale_factor,heel_two.min(), color='green')#!
#Plot of force data
plt.plot(x_values[:-1],strideData.iloc[:,7]) #force heel
plt.plot(x_values[:-1],strideData.iloc[:,9]) #force toe
# while - loop to calculate the point of intersection with the blue function
i = heel_one.idxmax()
while strideData.iloc[i,7] > strideData.iloc[i,9]:
i = i-1
# Length calculation between global minimum orange function and intersection with blue function
laenge=(i-heel_two.idxmin())*scale_factor
print(laenge)
#%% Integration of horizontal acceleration
velocity = inte.cumtrapz(resultsHorizontal,x_values)
plt.plot(x_values[:-1], velocity)
#%% Integration of the velocity
s = inte.cumtrapz(velocity, x_values[:-1])
plt.plot(x_values[:-2],s)
I hope it's clear what I want to do. Thanks for helping me!
I didn't dig all the way through your code, but the following tricks may be useful.
Say you have x and y values:
x = np.linspace(0,3,100)
y = x**2
Now, you only want the values corresponding to, say, .5 < x < 1.5. First, create a boolean mask for the arrays as follows:
mask = np.logical_and(.5 < x, x < 1.5)
(If this seems magical, then run x < 1.5 in your interpreter and observe the results).
Then use this mask to select your desired x and y values:
x_masked = x[mask]
y_masked = y[mask]
Then, you can translate all these values so that the first x,y pair is at the origin:
x_translated = x_masked - x_masked[0]
y_translated = y_masked - y_masked[0]
Is this the type of thing you were looking for?
I want to plot the frequency version of planck's law. I first tried to do this independently:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
%matplotlib inline
# Planck's Law
# Constants
h = 6.62607015*(10**-34) # J*s
c = 299792458 # m * s
k = 1.38064852*(10**-23) # J/K
T = 20 # K
frequency_range = np.linspace(10**-19,10**19,1000000)
def plancks_law(nu):
a = (2*h*nu**3) / (c**2)
e_term = np.exp(h*nu/(k*T))
brightness = a /(e_term - 1)
return brightness
plt.plot(frequency_range,plancks_law(frequency_range))
plt.gca().set_xlim([1*10**-16 ,1*10**16 ])
plt.gca().invert_xaxis()
This did not work, I have an issue with scaling somehow. My next idea was to attempt to use this person's code from this question: Plancks Formula for Blackbody spectrum
import matplotlib.pyplot as plt
import numpy as np
h = 6.626e-34
c = 3.0e+8
k = 1.38e-23
def planck_f(freq, T):
a = 2.0*h*(freq**3)
b = h*freq/(k*T)
intensity = a/( (c**2 * (np.exp(b) - 1.0) ))
return intensity
# generate x-axis in increments from 1nm to 3 micrometer in 1 nm increments
# starting at 1 nm to avoid wav = 0, which would result in division by zero.
wavelengths = np.arange(1e-9, 3e-6, 1e-9)
frequencies = np.arange(3e14, 3e17, 1e14, dtype=np.float64)
intensity4000 = planck_f(frequencies, 4000.)
plt.gca().invert_xaxis()
This didn't work, because I got a divide by zero error. Except that I don't see where there is a division by zero, the denominator shouldn't ever be zero since the exponential term shouldn't ever be equal to one. I chose the frequencies to be the conversions of the wavelength values from the example code.
Can anyone help fix the problem or explain how I can get planck's law for frequency instead of wavelength?
You can not safely handle such large numbers; even for comparably "small" values of b = h*freq/(k*T) your float64 will overflow, e.g np.exp(709.)=8.218407461554972e+307 is ok, but np.exp(710.)=inf. You'll have to adjust your units (exponents) accordingly to avoid this!
Note that this is also the case in the other question you linked to, if you insert print( np.exp(b)[:10] ) within the definition of planck(), you can examine the first ten evaluated b's and you'll see the overflow in the first few occurrences. In any case, simply use the answer posted within the other question, but convert the x-axis in plt.plot(wavelengths, intensity) to frequency (i hope you know how to get from one to the other) :-)
I wrote the following code,
import numpy as np
from random import gauss
from random import seed
from pandas import Series
import matplotlib.pyplot as plt
import math
###variable declaration
R=0.000001 #radiaus of particle
beta=0.23 # shape factor
Ad=9.2#characteristic nanoscale defect area
gamma=4*10**-2 #surface tension
tau=.0001 #line tension
phi=-(math.pi/2)#spatial perturbation
lamda=((Ad)/(2*3.14*R)) #averge contcat line position
mu=0.001#viscosity of liquid
lamda_m=10**-9# characteristic size of adsorption site
KbT=(1.38**-24)*293 # boltzman constant with tempartaure
nu=0.001#moleculer volume in liquid phase 1
khi=3 #scaling factor
#deltaF=(beta*gamma*Ad)#surface energy perturbation
deltaF=19*KbT
# seed random number generator
seed(0)
# create white noise series
series = [gauss(0.0, 1.0) for i in range(1)]
series = Series(series)
#########################################
Z=0.0000001 #particle position
time=1
dt=1
for time in np.arange(1, 100, dt):
#####simulation loop#######
theta=np.arccos(-Z/R) #contact angle
theta_e=((math.pi*110)/180) #equilibrium contact angle
Z_e=-R*np.cos(theta_e)#equilibrium position of particle
C=3.14*gamma*(R-Z_e) #additive constant
Fsz= (gamma*math.pi*(Z-Z_e)**2)+(tau*2*math.pi*math.sqrt(R**2-Z**2))+C
Fz=Fsz+(0.5*deltaF*np.sin((2*math.pi/lamda)*(Z-Z_e)-phi))#surface force
#dFz=(((gamma*Ad)/2)*np.sin(2*math.pi/lamda))+((Z-Z_e)*(2*gamma*math.pi))-((tau*2*math.pi*Z)/(math.sqrt(R**2-Z**2)))
dFz=(deltaF*np.sin(2*math.pi/lamda))+((Z-Z_e)*(2*gamma*math.pi))-((tau*2*math.pi*Z)/(math.sqrt(R**2-Z**2)))
w_a=gamma*lamda_m**2*(1-np.cos(theta_e)) #work of adhesion
epsilon_z=2*math.pi*R*np.sin(theta)*mu*(nu/(lamda_m**3))*np.exp(w_a/KbT)#transitional drag
epsilon_s=khi*mu*((4*math.pi**2*R**2)/math.sqrt(Ad))*(1-(Z/R)**2)
epsilon=epsilon_z+epsilon_s
Ft=math.sqrt(2*KbT*epsilon)*series #thermal force
v=(dFz+Ft)/epsilon ##new velocity
Z=Z+v*dt #new position
print('z=',Z)
print('v=',v)
print('Fz=',Fz)
print('dFz',dFz)
print('time',time)
plt.plot(Z,time)
plt.show()
According to my code I suppose to have 99 values for everything (Fz, Z, v , time). While I print , I can see all the values but while I was trying to plot them with different parameters with respect to each other for analyzing, I never get any graph. Can anyone tell me, what is missing from my code with explanation?
#AnttiA's answer is basically correct, but can be easily misunderstood, as can be seen from the OP's comment. Therefore here the complete code altered such that a plot is actually produced. Instead of making Z a list, define another variable as list, say Z_all = [], and then append the updated Z-values to that list. The same can be done for the time variable, i.e. time_all = np.arange(1,100,dt). Finally, take the plot command out of the loop and plot the entire data series at once.
Note that in your example you don't really have a series of random numbers, you pull one fixed number for one fixed seed, thus the plot is not really meaningful (it appears to be producing a straight line). Trying to interpret your intentions correctly, you probably want a series of random numbers that is as long as your time series. This is most easily done using np.random.normal
There are a lot of other ways that your code could be optimised. For instance, all mathematical functions from the math module are also found in numpy, so you could just not import math at all. The same goes for pandas. Also, you define some constant values inside the for-loop, which could be computed once before the loop. Lastly, #AnttiA is probably right, that you want time on the x axis and Z on the y axis. I therefore generate two plots -- on the left time over Z and on the right Z over time. Now finally the altered code:
import numpy as np
#from random import gauss
#from random import seed
#from pandas import Series
import matplotlib.pyplot as plt
#import math
###variable declaration
R=0.000001 #radiaus of particle
beta=0.23 # shape factor
Ad=9.2#characteristic nanoscale defect area
gamma=4*10**-2 #surface tension
tau=.0001 #line tension
phi=-(np.pi/2)#spatial perturbation
lamda=((Ad)/(2*3.14*R)) #averge contcat line position
mu=0.001#viscosity of liquid
lamda_m=10**-9# characteristic size of adsorption site
KbT=(1.38**-24)*293 # boltzman constant with tempartaure
nu=0.001#moleculer volume in liquid phase 1
khi=3 #scaling factor
#deltaF=(beta*gamma*Ad)#surface energy perturbation
deltaF=19*KbT
##quantities moved out of the for-loop:
theta_e=((np.pi*110)/180) #equilibrium contact angle
Z_e=-R*np.cos(theta_e)#equilibrium position of particle
C=3.14*gamma*(R-Z_e) #additive constant
w_a=gamma*lamda_m**2*(1-np.cos(theta_e)) #work of adhesion
#########################################
Z=0.0000001 #particle position
##time=1
dt=1
Z_all = []
time_all = np.arange(1, 100, dt)
# seed random number generator
# seed(0)
np.random.seed(0)
# create white noise series
##series = [gauss(0.0, 1.0) for i in range(1)]
##series = Series(series)
series = np.random.normal(0.0, 1.0, len(time_all))
for time, S in zip(time_all,series):
#####simulation loop#######
Z_all.append(Z)
theta=np.arccos(-Z/R) #contact angle
Fsz= (gamma*np.pi*(Z-Z_e)**2)+(tau*2*np.pi*np.sqrt(R**2-Z**2))+C
Fz=Fsz+(0.5*deltaF*np.sin((2*np.pi/lamda)*(Z-Z_e)-phi))#surface force
#dFz=(((gamma*Ad)/2)*np.sin(2*np.pi/lamda))+((Z-Z_e)*(2*gamma*np.pi))-((tau*2*np.pi*Z)/(np.sqrt(R**2-Z**2)))
dFz=(deltaF*np.sin(2*np.pi/lamda))+((Z-Z_e)*(2*gamma*np.pi))-((tau*2*np.pi*Z)/(np.sqrt(R**2-Z**2)))
epsilon_z=2*np.pi*R*np.sin(theta)*mu*(nu/(lamda_m**3))*np.exp(w_a/KbT)#transitional drag
epsilon_s=khi*mu*((4*np.pi**2*R**2)/np.sqrt(Ad))*(1-(Z/R)**2)
epsilon=epsilon_z+epsilon_s
Ft=np.sqrt(2*KbT*epsilon)*S #series #thermal force
v=(dFz+Ft)/epsilon ##new velocity
Z=Z+v*dt #new position
print('z=',Z)
print('v=',v)
print('Fz=',Fz)
print('dFz',dFz)
print('time',time)
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(8,4))
axes[0].plot(Z_all,time_all)
axes[0].set_xlabel('Z')
axes[0].set_ylabel('t')
axes[1].plot(time_all, Z_all)
axes[1].set_xlabel('t')
axes[1].set_ylabel('Z')
fig.tight_layout()
plt.show()
The result looks like this:
I suppose, you will get plot anyway, y-values are probably from 94 to 104.
Now you are plotting line with one point. Its length is zero, that's why you cannot see it, try: plt.plot(Z,time,'*').
Now you should get graph with an asterix in the middle.
As Thomas suggested, you should use arrays instead of using last calculated value. If you prefer loops (sometimes they are easier to modify), modify the lines...
Before loop:
Z = [0.0000001] # Initialize Z for time 0
time_vec = np.arange(1, 100, dt)
Inside loop:
Z.append(Z[-1] + v*dt) # new position
After loop:
plt.plot(Z[1:], time_vec)
Have no time to test it, hopefully works...
Note that first argument in plot command is x-axis values and second y-axis, I'd prefer time in x-axis.