Calculating Mean Square Displacement for a single particle in 1d [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a particle trajectory in 1D, j=[] and for the time=np.arange(0, 10 + dt, dt) where dt is the time step. I have calculate the MSD according to this article.
I have searched in google as well as here for 1d MSD in python but did not find any suitable one as my python knowledge is very beginner level. I have written one code and it is working without any error but I am not sure that it represent the same thing according to the given article. Here is my code,
j_i = np.array(j)
MSD=[]
diff_i=[]
tau_i=[]
for l in range(0,len(time)):
tau=l*dt
tau_i.append(tau)
for i in range(0,(len(time)-l)):
diff=(j_i[l+i]-j_i[i])**2
diff_i.append(diff)
MSD_j=np.sum(diff_i)/np.max(time)
MSD.append(MSD_j)
Can anyone please check verify the code and give suggestion if it is wrong.

The code is mostly correct, here is a modified version where:
I simplified some expressions (e.g. range)
I corrected the average, directly using np.mean because the MSD is a squared displacement [L^2], not a ratio [L^2] / [T].
Final code:
j_i = np.array(j)
MSD = []
diff_i = []
tau_i = []
for l in range(len(time)):
tau = l*dt
tau_i.append(tau)
for i in range(len(time)-l):
diff = (j_i[l+i]-j_i[i])**2
diff_i.append(diff)
MSD_j = np.mean(diff_i)
MSD.append(MSD_j)
EDIT: I realized I forgot to mention it because I was focusing on the code, but the ensemble average denoted by <.> in the paper should, as the name implies, be performed over several particles, preferentially comparing the initial position of each particle with its new position after a time tau, and not as you did with a kind of time-running average
EDIT 2: here is a code that shows how to do a proper ensemble average to implement exactly the formula in the article
js = # an array of shape (N, M), with N the number of particles and
# M the number of time points
MSD_i = np.zeros((N, M))
taus = []
for l in range(len(time)):
taus.append(l*dt) # store the values of tau
# compute all squared displacements at current tau
MSD_i[:, l] = np.square(js[:, 0] - js[:, l])
# then, compute the ensemble average for each tau (over the N particles)
MSD = np.mean(MSD_i, axis=0)
And now you can plot MSD versus taus and Bob's your uncle

Related

Equations of motion in python [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
Hello I am starting a mathematics projects about the motion of billiard balls on different domains, I am choosing to write a python code to describe the free motion of a ball on a polynomial domain:
Imagine bouncing a particle on the inside of a curve described by f(x) = x^4 for example;
I am struggling to put this into code and would appreciate any help you could give me.
Some useful information:
We take a ball with initial condition (x_0,v_0) where x_0 is the initial x position and v_0 is the slope at which we shoot the billiard.
The free motion of the billiard is described by the equations:
f(x_(j+1)) - f(x_j) = v_j(x_(j+1) - x_j) &
v_(j+1) = 2f'(x_(j+1)) - v_j,
This should give a polynomial in x which one can solve and then use the value of x to solve for v
I need to write a code that takes an initial condition, a function to describe a curve and its derivative that will spit out the values for x and v as the ball carries on along its path.
Please could anyone give me some tips on how to get started as my python skills are extremely limited and I'm struggling a lot more than I thought!
I will list my attempt below and the error it gave:
#equations of free motion
import numpy as np
def f(x): #function
return x^2
def df(x): #derivative of function
h = 1e-10
return (f(x+h) - f(x))/(2*h)
def free_motion(f,df,x0,v0):
x_j = x0
v_j = v0 #less than f'(x0)
f(x_jj) - (v_jj * (x_jj)) = f(x_j) - (v_j * (x_j)) #gives polynomial in x_jj
return x_jj,v_jj
Input In [11]
f(x_jj) - (v_jj * (x_jj)) = f(x_j) - (v_j * (x0)) #gives polynomial in x_jj
^
SyntaxError: cannot assign to operator

Why does FFT size equals the numbers of samples in the time domain? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
Improve this question
My question is simple. I think I kind of understand FFT and DFT. what I dont understand is why, in Python or matlab, do we use FFT size as the number of samples? why does every sample taken in the time domain corresponds to a frequency bin in the frequency domain.
For example the Scipy's fft pack, in order to plot the spectrum of a .wav file signal we use:
FFT = abs(scipy.fftpack.fft(time_domain_signal));
Frequency_Vector = fftpack.fftfreq(len(FFT_out), (1/Sampling_rate))
Now if I type the len(FFT_out)
it is the the same as the number of samples (ie sampling freq * time of the audio signal) and since ffreq is the frequency vector that contains the frequency bins, therefore Len(fft) = number of frequency bins.
A simple explanation would be appreciated.
Mathematically a key property of the fourier transform is that it is linear and invertible. The latter means that if two signals have the same fourier transform they are equal, and that for any spectrum there is a signal with that spectrum.
For implementations with a finite collection of samples of a signal the first property means that the fourier tramsform can be represented by a N x M matrix where N is the number of time samples and M the number of frequency samples. The second property means that the matrix must be invertible, and so square, ie we must have M == N.
You say that time bins and frequency correspond, and that is true in the sense that there are the same number of them. However the value in each frequency bin will depend on all time values.

Curve fitting of Hyperbola and finding its parameters associated [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Assuming General formula of hyperbola to be y = 1 / (a*x + b), and we are provided with 100 data points out of which 99 points exactly fits a hyperbola and one data point is doesn't fits in it (unknown), from this information we need to find approximate values of a and b parameters for the hyperbola that will be formed from correct data points which are provided.
The approach which I took was by using scipy.optimize.curve_fit method as "parameters, _ = optimize.curve_fit(test, x_data ,y_data) "
where my "test" function was "def test(x, a, b): return 1 / (a*x + b)" using this method provides me perfect solution is my data points are all in first quadrant but if the data is distributed in more than one quadrant then this approach fails and I get wrong values of a and b.
Code:
import numpy as np
from scipy import optimize
x_data = np.linspace(-5,1, num=99)
y_data = 1 / (5 * x_data + 4) # value of original value of a = 5 & b = 4
np.random.seed(0)
# adding wrong point at 36th position
x_data = np.insert(x_data, 36 , 7)
y_data = np.insert(y_data, 36, 5)
def test(x, a, b):
return 1 / (a*x + b)
parameters, _ = optimize.curve_fit(test, x_data ,y_data)
[a,b] = parameters
a = 146.83956808191303
b = 148.78257639384725
# which is too wrong
Solution for above will certainly be appreciated.
Your problem is easy if the given points "exactly fit the hyperbola," and you need only two data points.
Your equation y = 1 / (ax + b) can be transformed into
(x*y) * a + (y) * b = 1
That is a linear equation in a and b. Use two data points to find the corresponding values of x * y and y and you end up with two linear equations in two variables (though in a and b rather than x and y). Then solve those two linear equations. This can easily be automated. This also does not depend on the quadrants of your two given points.
This does not work if your given points only approximate a hyperbola, of course.
In your last edit, you added the statement that only 99 of the points fit on the hyperbola, and one does not. This can be handled by choosing three pairs of your points (six distinct points), and finding the hyperbola that goes through each pair of points. That means calculating three hyperbolas (equivalently, calculating three values of a and b). If those three pairs of a and b all agree with small precision, the non-matching point was not in the chosen sample of three pairs of points and you have your hyperbola. If only two of them agree within precision, use that hyperbola. If no pair of the hyperbolas agree, some mistake was made and you should raise an exception.

Eigenvectors of a Hermitian matrix [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
A Hermitian matrix is a complex square matrix which is equal to its conjugate transpose. Its matrix elements fulfil following condition:
Everytime, I compute eigenvectors of a Hermitian matrix using Python, the first coefficient of the eigenvector is a pure real number. Is this an attribute of Hermitian matrices?
I attach a code snippet to generate a Hermitian matrix, compute its eigenvectors and print the eigenvector corresponding to the lowest eigenvalue.
import numpy as np
from numpy import linalg as LA
N = 5 # Set size of a matrix
# Generate real part of the matrix at first
real_matrix = np.random.uniform(-1.0, 1.0, size=(N,N))
real_matrix = (real_matrix + real_matrix.T)/2
# Generate imaginary part of the matrix
imaginary_matrix = np.random.uniform(-1.0, 1.0, size=(N,N))
imaginary_matrix = (imaginary_matrix + imaginary_matrix.T)/2
imaginary_matrix = imaginary_matrix.astype(complex) * 1j
for row in range(N):
for column in range(row,N):
if row == column:
imaginary_matrix[row][column] = 0.0
else:
imaginary_matrix[row][column] *= -1
# Combine real and imaginary part
matrix = real_matrix + imaginary_matrix
# Compute and print eigenvector
eigenvalues, eigenvectors = LA.eigh(matrix)
print(eigenvectors[:,0])
I think it's a python question rather than a mathematics question.
You have some ambiguity when performing an eigenvalue decomposition: if u is a unitary eigenvector for the eigenvalue lambda, then exp(i theta) * u is also a unitary eigenvector (for any real theta) for the same eigenvalue.
To fix this indetermination, some implementation impose that the first coefficient of each eigenvector is real.
You get the same thing when doing an eigendecomposition of a real matrix: if u is an eigenvector, - u also is. To make the eigendecomposition deterministic, some implementation (for example sklearn's PCA, see this related question) impose that the greatest coefficient of u in magnitude be positive.

Filter design to find energy at specific audio frequencies [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm adapting and extending the Matlab "Chroma Toolbox" by Meinard Müller and Sebastien Ewert to python. It aims to detect what musical pitches are present at each analysis frame for an audio recording.
The first step is to determine the tuning of the music, and the Chroma Toolbox tests whether the music is tuned at the standard A=440Hz, or down a quarter, third, half, two-thirds, or three-quarters of a semitone. That's ok, but in my application, I need more resolution in the tuning detection.
Once the tuning is selected from one of those choices, a corresponding filterbank is chosen, which is used to find how much energy there is at each musical pitch over the range of the piano. (Also, the waveform is resampled to 22050, 4410, and 882 Hz)
The coefficients for the filterbanks are stored in .mat files, given by the Chroma Toolbox. For example, the coefficients for detecting energy at standard-tuned middle C (261.63 Hz) are b = [ 1., -7.43749873, 24.72954997, -47.94740681, 59.25189976,
-47.77885707, 24.55599193, -7.35933913, 0.98601284] and a = [0.00314443, -0.02341175, 0.07794208, -0.15134062, 0.18733283, -0.15134062, 0.07794208, -0.02341175, 0.00314443], and the sample rate for middle C is 4410 Hz.
These coefficients are used in a call to filtfilt: I use scipy.signal.filtfilt(b, a, x) where x is the waveform at an appropriate sampling frequency, low for the low notes, high for the higher ones. This step is done in the file "audio_to_pitch_via_FB.m".
the question:
Because I want to allow for different tuning levels than those designed into the Chroma Toolbox, I need to make my own filterbanks, and so need to know how to compute the filter coefficients. To do so, I need a function coeffs(freq, fs) that will find the right coefficients to find the energy at a given frequency freq, for a signal at sample frequency fs. How do I do it?
Here's the name of one of the .mat files, in case it contains a useful clue. "MIDI_FB_ellip_pitch_60_96_22050_Q25_minusQuarter.mat"
The code that generates the filters is in generateMultiratePitchFilterbank.m file. The ellip function returns a and b the other way round, but otherwise it's more or less the same.
The following recipe reproduces the numbers you quoted:
import numpy as np
import scipy.signal as ss
def coeffs(pitch, fs, Q=25, stop=2, Rp=1, Rs=50):
"""Calculate filter coeffs for a given pitch and sampling rate, fs.
See their source code for description of Q, stop, Rp, Rs"""
nyq = fs/2. # Nyquist frequency
pass_rel = 1/(2.*Q)
stop_rel = pass_rel * stop
# The min-max edges of the pass band
Wp = np.array([pitch - pass_rel*pitch, pitch+pass_rel*pitch])/nyq
# And the stop band(s)
Ws = np.array([pitch - stop_rel*pitch, pitch+stop_rel*pitch])/nyq
# Get the order, natural freq
n, Wn = ss.ellipord(Wp, Ws, Rp, Rs)
# Get a and b:
a, b = ss.ellip(n, Rp, Rs, Wn, btype="bandpass")
return a, b

Categories

Resources