Create Low Pass Filter by Octave - fft

Though I had an example of low pass filter coded in Octave and I'm sure it works, I can't understand.
How dose this work? and How can I know cut-off frequency of this filter?
The original_data is a column of water quality data I obtained with 1Hz.
l = rows(original_data);
a = fft(original_data);
for i = (1:l);
if i >9
a(i) = 0;
endif
endfor
b = fft(original_data);
for i = (1:l)
if i > 1
b(i) = 0;
endif
endfor
c = real(ifft(a));
c(1);
d = real(ifft(a))*2-c(1);
If you have any idea, please help me.

I agree with the comment, there are plenty of functions to allow you to design a low-pass filter correctly (see http://octave.sourceforge.net/signal/overview.html, in particular the IIR and FIR filter design sections). Once you have designed your filter you can apply it using the function filter or filtfilt.
As an example, a simple way to go about this would be:
[b,a] = butter(n, Wc) % low pass Butterworth filter with cutoff pi*Wc radians - choose the order of the filter n and cut-off frequency Wc to suit
filtered_data = filter(b,a,original_data);

Firstly is important know that works in frequency domain is not the best way to filter a signal, time domain methods can work nicely !
Do you want know the cut-off frequency? you need know the sample rate and the length of your FFT to calculate the frequency of correspondent bin of your FFT.
sample rate = FS, first do you need calculate the Nyquist.
Nyquist = FS / 2;
Now find the frequency resolution, in this case your fft size is the same of your original_data.
Resolution=Nyquist / (length(original_data) / 2);
OK almost ther, you are placing the value 0 in the first eight(8) bins of your FFT, then now you need find the frequency of correspondent bin!
round(1 * Resolution)
round(2 * Resolution)
round(3 * Resolution)
.
.
round(8 * Resolution)
The results are the cut-off frequency, this means that you will be cutting the frequencies between the first and eighth bin

Related

Solving a steady flow in a subdomain of a mesh using FiPy

I'm fairly new to FiPy and I'm currently facing an issue of which I am sure can be solved easily: I want to solve a 3D steady flow of the form:
eq = ( DiffusionTerm(var=u) == -(1/mu) * dP + g_acc * (rho/mu) * ymax )
Where velocity u is in the y-direction and where du/dy = 0.
I would like to let the PDE solve within a subdomain of the entire 3D mesh, meaning that:
0 <= X < Boundary_1, u=0.
Boundary_1 <= X < Boundary_2, u = PDE solution
Boundary_2 <= X < Lx, u = 0.
Currently I have tried the following:
mesh = Grid3D(dx=dx, dy=dy, dz=dz, Lx=(Lx-0), Ly =(ymax-ymin), Lz=(zmax-zmin))
u = CellVariable(name = "velocity", mesh = mesh)
X, Y, Z = mesh.cellCenters
LeftWall = (X <= xBoundary_left)
RightWall = (X > xBoundary_right)
FrontWall = (mesh.facesFront)
BackWall = (mesh.facesBack)
u.constrain(0., where=LeftWall)
u.constrain(0., where=RightWall)
u.constrain(0., where=FrontWall)
u.constrain(0., where=BackWall)
Which leads to a solution of image 1 (see attached image). The boundary conditions for the X variable are not taken into account as I would like, as you can see in the example in image 2, where only the PDE domain is shown.
What I am looking for is a way to define the boundary conditions at the faces of the subdomain in such a way that it does not 'crop' the solution, but rather only solves the PDE for that subdomain. If it is possible to 'stitch' meshes together that include a Cellvariable u that has value 0 for two meshes and the value of the solved PDE for one mesh, that would be great as well!
I have tried working with inner boundary conditions in the form of an Implicit source, but that ended up in different errors.
Any help would be much appreciated!
FiPy constraints do not work on internal faces.
In our own work, rather than only solving an equation in a subdomain, we modify the coefficients to cause different behaviors to dominate in different subdomains. Conservation of momentum and conservation of mass don't suddenly stop being true; rather different conditions lead to, e.g., different Reynolds numbers.
It is possible to solve different equations on different meshes and communicate between them. See, e.g.,
https://www.mail-archive.com/search?q=how+to+set+up+data+transfer+between+two+adjacent+nonuniform+meshs&l=fipy%40nist.gov
How to extract a plane from a 3D variable in FiPy (3D to 2D)
https://www.mail-archive.com/search?l=fipy%40nist.gov&q=How+to+combine+scipy.interpolate.interp2d+with+fipy+variables&x=0&y=0
https://www.mail-archive.com/search?l=fipy%40nist.gov&q=Spline+interpolation+and+fipy+variable&x=18&y=9

Store 2 previous array to implement Leapfrog numerical Scheme

In the context of advection numerical solving, I try to implement the following recurrence formula in a time loop:
As you can see, I need the second previous time value for (j-1) and previous (j) value to compute the (j+1) time value.
I don't know how to implement this recurrence formula. Here below my attempt in Python where u represents the array of values T for each iteration:
l = 1
# Time loop
for i in range(1,nt+1):
# Leapfrog scheme
# Store (i-1) value for scheme formula
if (l < 2):
atemp = copy(u)
l = l+1
elif (l == 2):
btemp = copy(atemp)
l = 1
u[1:nx-1] = btemp[1:nx-1] - cfl*(u[2:nx] - u[0:nx-2])
t=t+dt
Coefficient cfl is equal to s.
But the results of simulation don't give fully good results. I think my way to do is not correct.
How can I implement this recurrence? i.e mostly how to store the (j-1) value in time to inject it into formula for computing (j+1) ?
Update
In the formula:
the time index j has to start from j=1since we have the term T_(i,j-1).
So for the first iteration, we have :
T_i,2 = T_i,0 - s (T_(i+1),1 - T_(i-1),1)
Then, if In only use time loop (and not spatial loop such that way, I can't compute dudx[i]=T[i+1]-T[i-1]), how can I compute (T_(i+1),1 - T_(i-1),1), I mean, without precalculating dudx[i] = T_(i+1),1 - T_(i-1),1 ?
That was the trick I try to implement in my original question. The main problem is that I am imposed to use only time loop.
The code would be simpler if I could use 2D array with T[i][j] element, ifor spatial and jfor time but I am not allowed to use 2D array in my examination.
There are few problems I see in your code. First is notation. From the numerical scheme you posted it looks like you are discretizing time with j and space with i using central differences in both. But in your code it looks like the time loop is written in terms of i and this is confusing. I will use j for space and n for time here.
Second, this line
u[1:nx-1] = btemp[1:nx-1] - cfl*(u[2:nx] - u[0:nx-2])
is not correct since for the spatial derivatve du/dx you need to apply the central difference scheme at every spatial point of u. Hence, u[2:nx] - u[0:nx-2] is doing nothing like this, it is just subtracting what seems to be the solution including boundary points on the left from the solution including boundary points on the right. You need to properly calculate this spatial derivative.
Finally, the Leapfrog method which indeed takes into account the n-1 solution is usually implemented by keeping a copy of the previous time step in another variable such as u_prev. So if you use the Leapfrog time scheme plus central difference spatial scheme, in the end you should have something like
u_prev = u_init
u = u_prev
for n in time...:
u_new = u_prev - cfl*(dudx)
u_prev = u
u = u_new
Note that u on the LHS is to compute time n+1, u_prev is at time n-1 and dudx uses u at the current time n. Also, you can compute dudx with
for j in space...:
dudx[j] = u[j+1]-u[j-1]

Finding the smallest distance in a set of points from the origin

I am to find the smallest distance between a given set of points and the origin. I have a matrix with 2 columns and 10 rows. Each row represents coordinates. One point consists of two coordinates and I would like to calculate the smallest distance between each point and to the origin. I would also like to determine which point gave this smallest distance.
In Octave, I calculate this distance by using norm and for each point in my set, I have a distance associated with them and the smallest distance is obviously the one I'm looking for. However, the code I wrote below isn't working the way it should.
function [dist,koor] = bonus4(S)
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
for i=1:size(S)
L=norm(S(i, :))
dist=norm(S(9, :));
koor=S(9, :) ;
end
i = 9 is the correct answer, but I need Octave to put that number in. How do I tell Octave that this is the number I want? Specifically:
dist=norm(S(9, :));
koor=S(9, :);
I cannot use any packages. I found the geometry package online but I am to solve the task without additional packages.
I'll work off of your original code. Firstly, you want to compute the norm of all of the points and store them as individual elements in an array. Your current code isn't doing that and is overwriting the variable L which is a single value at each iteration of the loop.
You'll want to make L an array and store the norms at each iteration of the loop. Once you do this, you'll want to find the location as well as the minimum distance itself. That can be done with one call to min where the first output gives you the minimum distance and the second output gives you the location of the minimum. You can use the second output to slice into your S array to retrieve the actual point.
Last but not least, you need to define S first before calling this function. You are defining S inside the function and that will probably give you unintended results if you want to change the input into this function at each invocation. Therefore, define S first, then call the function:
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
function [dist,koor] = bonus4(S)
%// New - Create an array to store the distances
L = zeros(size(S,1), 1);
%// Change to iterate over number of rows
for i=1:size(S,1)
L(i)=norm(S(i, :)); %// Change
end
[dist,ind] = min(L); %// Find the minimum distance
koor = S(ind,:); %// Get the actual point
end
Or, make sure you save the above function in a file called bonus4.m, then do this in the Octave command prompt:
octave:1> S= [-6.8667, -44.7967;
> -38.0136, -35.5284;
> 14.4552, -27.1413;
> 8.4996, 31.7294;
> -17.2183, 28.4815;
> -37.5100, 14.1941;
> -4.2664, -24.4428;
> -18.6655, 26.9427;
> -15.8828, 18.0170;
> 17.8440, -22.9164];
octave:2> [dist,koor] = bonus4(S);
Though this code works, I'll debate that it's slow as you're using a for loop. A faster way would be to do this completely vectorized. Because using norm for matrices is different than with vectors, you'll have to compute the distance yourself. Because you are measuring the distance from the origin, you can simply square each of the columns individually then add the columns of each row.
Therefore, you can just do this:
S= [-6.8667, -44.7967;
-38.0136, -35.5284;
14.4552, -27.1413;
8.4996, 31.7294;
-17.2183, 28.4815;
-37.5100, 14.1941;
-4.2664, -24.4428;
-18.6655, 26.9427;
-15.8828, 18.0170;
17.8440, -22.9164];
function [dist,koor] = bonus4(S)
%// New - Computes the norm of each point
L = sqrt(sum(S.^2, 2));
[dist,ind] = min(L); %// Find the minimum distance
koor = S(ind,:); %// Get the actual point
end
The function sum can be used to sum over a dimension independently. As such, by doing S.^2, you are squaring each term in the points matrix, then by using sum with the second parameter as 2, you are summing over all of the columns for each row. Taking the square root of this result computes the distance of each point to the origin, exactly the way the for loop functions. However, this (at least to me) is more readable and I daresay faster for larger sizes of points.

How to "zero-phase-adjust" DFT output?

I understand the complex output of a DFT contains both "amplitude" and "phase" information at discrete frequencies.
Amplitude[n] = sqrt((r[n]*r[n]) + (i[n]*i[n]))
Phase[n] = (atan2(i[n],r[n]))
Frequency[n] = n * (sample_rate / (fft_input_length / 2))
It seems that I should be able to use the frequency, amplitude, and phase information to calculate the amplitude of each output bin as if the input at the corresponding frequency had a zero-phase alignment in the FFT input. But I am drawing a blank.
Hmm, digging deeper into my problem I discovered that the imaginary potion of the FFT output is always 0.0 regardless of the input. So I am guessing my code is flawed or the algorithm is not what I need.
If you want to rotate all DFT result bins to a phase of zero with reference to the start (sample 0): set r[n] = amplitude[n], i[n] = 0; make sure r[n] is symmetric over the full DFT length if you want strictly real data; and compute the IDFT if needed.

any rules of thumb how to smooth FFT spectrum to prevent artifacts when hand-tweaking?

I've got a FFT magnitude spectrum and I want to create a filter from it that selectively passes periodic noise sources (e.g. sinewave spurs) and zero's out the frequency bins associated with the random background noise. I understand sharp transitions in the freq domain will create ringing artifacts once this filter is IFFT back to the time domain... and so I'm wondering if there are any rules of thumb how to smooth the transitions in such a filter to avoid such ringing.
For example, if the FFT has 1M frequency bins, and there are five spurs poking out of the background noise floor, I'd like to zero all bins except the peak bin associated with each of the five spurs. The question is how to handle the neighboring spur bins to prevent artifacts in the time domain. For example, should the the bin on each side of a spur bin be set to 50% amplitude? Should two bins on either side of a spur bin be used (the closest one at 50%, and the next closest at 25%, etc.)? Any thoughts greatly appreciated. Thanks!
I like the following method:
Create the ideal magnitude spectrum (remembering to make it symmetrical about DC)
Inverse transform to the time domain
Rotate the block by half the blocksize
Apply a Hann window
I find it creates reasonably smooth frequency domain results, although I've never tried it on something as sharp as you're suggesting. You can probably make a sharper filter by using a Kaiser-Bessel window, but you have to pick the parameters appropriately. By sharper, I'm guessing maybe you can reduce the sidelobes by 6 dB or so.
Here's some sample Matlab/Octave code. To test the results, I used freqz(h, 1, length(h)*10);.
function [ht, htrot, htwin] = ArbBandPass(N, freqs)
%# N = desired filter length
%# freqs = array of frequencies, normalized by pi, to turn into passbands
%# returns raw, rotated, and rotated+windowed coeffs in time domain
if any(freqs >= 1) || any(freqs <= 0)
error('0 < passband frequency < 1.0 required to fit within (DC,pi)')
end
hf = zeros(N,1); %# magnitude spectrum from DC to 2*pi is intialized to 0
%# In Matlabs FFT, idx 1 -> DC, idx 2 -> bin 1, idx N/2 -> Fs/2 - 1, idx N/2 + 1 -> Fs/2, idx N -> bin -1
idxs = round(freqs * N/2)+1; %# indeces of passband freqs between DC and pi
hf(idxs) = 1; %# set desired positive frequencies to 1
hf(N - (idxs-2)) = 1; %# make sure 2-sided spectrum is symmetric, guarantees real filter coeffs in time domain
ht = ifft(hf); %# this will have a small imaginary part due to numerical error
if any(abs(imag(ht)) > 2*eps(max(abs(real(ht)))))
warning('Imaginary part of time domain signal surprisingly large - is the spectrum symmetric?')
end
ht = real(ht); %# discard tiny imag part from numerical error
htrot = [ht((N/2 + 1):end) ; ht(1:(N/2))]; %# circularly rotate time domain block by N/2 points
win = hann(N, 'periodic'); %# might want to use a window with a flatter mainlobe
htwin = htrot .* win;
htwin = htwin .* (N/sum(win)); %# normalize peak amplitude by compensating for width of window lineshape