I'm trying to find out the peak frequencies hidden in my data using the fft() method in R. While preparing the data, a more experienced user recommends to create a "mask" (more after explaining the details), that does give me the exact diagram I'm looking for. The problem is, I don't understand what it does or why it's needed.
To give some context, I'm working with .txt files with around 12000 entries each. It's voltage vs. time information, and the expected result is just a sinusoidal wave with a clear peak frequency that should be close to 1-2 Hz. This is an example of what one of those files look like:
I've been trying to use the Fast Fourier Transform method fft() implemented in R to find the peak frequencies and get a diagram that reflected them clearly. At first, I calculate some things that I understand are going to be useful, like the Nyquist frequency and the range of frequencies I'll show in the final graph:
n = length(variable)
dt = time[5]-time[4]
df = 1/(max(time)) #Find out the "unit" frequency
fnyquist = 1/(2*dt) #The Nyquist frequency
f = seq(-fnyquist, fnyquist-df, by=df) #These are the frequencies I'll plot
But when I plot the absolute value of what fft(data) calculates vs. the range of frequencies, I get this:
The peak frequency seems to be close to 50 Hz, but I know that's not the case. It should be close to 1 Hz. I'm a complete newbie in R and in Fourier analysis, so after researching a little, I found in a Swiss page that this can be solved by creating a "mask", which is actually just a vector with a repeatting patern (1, -1, 1, -1...) with the same length as my data vector itself:
mask=rep(c(1, -1),length.out=n)
Then if I multiply my data vector by this mask and plot the results:
results = mask*data
plot(f,abs(fft(results)),type="h")
I get what I was looking for. (This is the graph after limiting the x-axis to a reasonable scale).
So, what's the mask actually doing? I undestand it's changing my data point signs in an alternate manner, but I don't get why it would take the infered peak frequencies from ~50 Hz to the correct result of ~1 Hz.
Thanks in advance!
Your "mask" is one of two methods of performing an fftshift, which is commonly done to center the 0 Hz output of an FFT in the middle of a graph or plot (instead of at the left edge, with the negative frequencies wrapping around to the right edge).
To perform an fftshift, you can hetrodyne or modulate your data (by Fs/2) before the FFT, or simply do a circular shift by 50% after the FFT. Both produce the same result. They are the same due to the shift property of the DFT.
I am tying to achieve sine wave gradually changing from 8Hz to 2Hz over 5 seconds:
This waveform was produced in Cool Edit. I gave it a start frequency of 8Hz, an end frequency of 2Hz and a duration of 5 seconds. The sine wave gradually changes from one frequency to the other over the given time.
My question is, how can I accurately find the start time of each cycle (highlighted with a red dot), using a FOR loop?
Pseudo code:
time = 5 //Duration
freq1 = 8 //Start frequency
freq2 = 2 //End frequency
cycles = ( (freq1 + freq2) / 2 ) * time //Total number of cycles
for(i = 0; i < cycles; i++) {
/* Formula to find start time of each cycle */
}
That is backward thinking for this problem which leads to madness in the program. Not to mention the individual waves will not be a sin wave because the frequency is changing (they will be slightly distorted) which you will not achieve with your generator and also there is very slight chance the ending signal will stop on zero after 5sec. Instead do a continuous sin wave with variable frequency:
First compute actual frequency
linear interpolation will suffice (unless you need different change)
f=f0+(f1-f0)*t/T
where:
f0=8 [Hz] start frequency
f1=2 [Hz] stop frequency
T =5 [s] change time
t =<0,T> is actual time in [s]
compute the sin wave data
for (t=0.0,angle=0.0;t<=T;t+=dt)
{
f=f0+((f1-f0)*t/T); // actual frequency
signal=Amplitude*sin(angle); // your signal put it in a array or output somewhere ...
angle+=6.283185307179586476925286766559*dt*f; // update phase
while (angle>6.283185307179586476925286766559) // cut just to avoid floating rounding problems
angle-=6.283185307179586476925286766559;
}
Where dt [s] is a time step you want to sample your signal with. If you are generating this in Real Time and outputting to real HW you can use a timer or measure the time directly (with performance counters on Windows or by RDTSC or whatever you have at disposal)
If you got predefined number of samples n for this then
dt=T/double(n-1);
Here sample output (n=image width):
If you also need the number of periods then add counter increment inside the angle cut while loop And also there is your zero point too (but if samplerate is too small or you need high precision you need to interpolate the real zero position).
I have the mathematical formula. But I have doubt whether one can calculate entropy for Color Images ( normally i have seen for Black and White Images only).
H ( m ) = ∑ - P ( m ) log P ( m )
How should I calculate The value of P( m )
Secondly, I also have the formula for Correlation Analysis but don't really know how to find it out. I have the co relation formula
r (xy) = cov( x , y ) / squareroot(D ( x ) D ( y ))
It is said that x and y are greyscale values. what do you mean by greyscale values and how do I calculate those?
Question 1:
To calculate the entropy, you need to estimate the probability of each RGB value - i.e. the count of pixels with that value divided by the number of pixel in the image. Than you operate the formula over all positive probabilities. There are two possible implementations of holding the RGB counts:
Simple histogram - 3-dimensional array 256X256X256, slow and memory consuming
Sparse histogram - hold a hash table with RGB as key and count as value.
The first choice may be better for very large images.
Note however that for rather small images, the probability estimation might be very inaccurate, as small noise may spread a single color to multiple bin. In the worse case all counts will be 1. To handle that problem, you may consider using larger bins - e.g. divide the RGB values by 4, so you only have 64^3 bins.
Question 2: You're talking about the correlation coefficient, AKA normalize correlation http://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation
Gray-scale is just the common term for the value of pixel in a gray-scale image, usually in the 0-255 range.
I want to apply heat transfer ( heat conduction and convection) for a hemisphere. It is a transient homogeneous heat transfer in spherical coordinates. There is no heat generation. Boundary conditions of hemisphere is in the beginning at Tinitial= 20 degree room temperature. External-enviromental temperature is -22 degree. You can imagine that hemisphere is a solid material. Also, it is a non-linear model, because thermal conductivity is changing after material is frozen, and this is going to change the temperature profile.
I want to find the temperature profile of this solid during a certain time until center temperature reach to -22 degree.
In this case, Temperature depends on 3 parameters : T(r,theta,t). radius, angle, and time.
1/α(∂T(r,θ,t))/∂t =1/r^2*∂/∂r(r^2(∂T(r,θ,t))/∂r)+ 1/(r^2*sinθ )∂/∂θ(sinθ(∂T(r,θ,t))/∂θ)
I applied finite difference method using matlab, However, boundary conditions have issues. There are convection on surface of the hemisphere, and conduction in the inner nodes, bottom of the hemisphere has constant temperature which is air temperature (-22). You can see the scripts which i am using for BCs in the matlab file.
% Temperature at surface of hemisphere solid boundary node
for i=nodes
for j=1:1:(nodes-1)
Qcd_ot(i,j)= ((k(i,j)+ k(i-1,j))/2)*A(i-1,j)*(( Told(i,j)-Told(i-1,j))/dr); % heat conduction out of node
Qcv(i,j) = h*(Tair-Told(i,j))*A(i,j); % heat transfer through convectioin on surface
Tnew(i,j) = ((Qcv(i,j)-Qcd_ot(i,j))/(mass(i,j)*cp(i,j))/2)*dt + Told(i,j);
end % end of for loop
end
% Temperature at inner nodes
for i=2:1:(nodes-1)
for j=2:1:(nodes-1)
Qcd_in(i,j)= ((k(i,j)+ k(i+1,j))/2)*A(i,j) *((2/R)*(( Told(i+1,j)-Told(i,j))/(2*dr)) + ((Told(i+1,j)-2*Told(i,j)+Told(i-1,j))/(dr^2)) + ((cot(y)/(R^2))*((Told(i,j+1)-Told(i,j-1))/(2*dy))) + (1/(R^2))*(Told(i,j+1)-2*Told(i,j)+ Told(i,j-1))/(dy^2));
Qcd_out(i,j)= ((k(i,j)+ k(i-1,j))/2)*A(i-1,j)*((2/R)*(( Told(i,j)-Told(i-1,j))/(2*dr)) +((Told(i+1,j)-2*Told(i,j)+Told(i-1,j))/(dr^2)) + ((cot(y)/(R^2))*((Told(i,j+1)-Told(i,j-1))/(2*dy))) + (1/(R^2))*(Told(i,j+1)-2*Told(i,j)+ Told(i,j-1))/(dy^2));
Tnew(i,j) = ((Qcd_in(i,j)-Qcd_out(i,j))/(mass(i,j)*cp(i,j)))*dt + Told(i,j);
end %end for loop
end % end for loop
%Temperature for at center line nodes
for i=2:1:(nodes-1)
for j=1
Qcd_line(i,j)=((k(i,j)+ k(i+1,j))/2)*A(i,j)*(Told(i+1,j)-Told(i,j))/dr;
Qcd_lineout(i,j)=((k(i,j)+ k(i-1,j))/2)*A(i-1,j)*(Told(i,j)-Told(i-1,j))/dr;
Tnew(i,j)= ((Qcd_line(i,j)-Qcd_lineout(i,j))/(mass(i,j)*cp(i,j)))*dt + Told(i,j);
end
end
% Temperature at bottom point (center) of the hemisphere solid
for i=1
for j=1:1:(nodes-1)
Qcd_center(i,j)=(((k(i,j)+k(i+1,j))/2)*A(i,j)*(Told(i+1,j)-Tair)/dr);
Tnew(i,j)= ((Qcd_center(i,j))/(mass(i,j)*cp(i,j)))*dt + Told(i,j);
end
end
% Temperature at all bottom points of the hemisphere
Tnew(:,nodes)=-22;
Told=Tnew;
t=t+dt;
Tnew temperatures values are getting bigger exponentially after program is run, and then becoming NaN. It supposed to show me cooling and freezing temperature profile of solid until it reaches to Tair temperature. I could not figure out the reasons why it is changing like that.
I would like to hear your suggestions for BCs implementation to this program, or how should i change them according to this conditions. Thanks in advance !!
Your code is too long to read and understand completely, but it looks like you are using a simple forward Euler scheme, is that correct? If so, try to reduce the time-step dt, maybe by a lot, since this method can become numerically unstable if dt is too big. This might slow down the speed of the computation (again by a lot), but that is the price you pay for such a simple algorithm. There are alternatives methods that do not suffer from instability, but they are much harder to implement, since you need to solve a system of equations.
I did some thermal simulations using this simple scheme a long time ago. I found that the stability criteria was dt < (dx)^2 * c_p * rho / (6 * k), which should be valid for a simulation on a 3D cartesian grid, where dx is the spatial step, c_p is the specific heat, rho the density and k the thermal conductivity of the material. I don't know how to convert this to your case with spherical coordinates. The thing I learned then was to choose small time-steps, but more importantly as large dx as possible: when you reduce dx by a factor 2, you also need to reduce dt by a factor 4 to keep things stable. At the same time, for a 3D problem, the number of elements will increase by a factor 8. So the total simulation time scales with 1 / (dx)^5!!!
I'm trying to filter a time/position data series to produce a smoothed plot. I am measuring depth vs time (mechanical system) where the velocity is changing. I calculate velocity from the measured depth/time values and can plot velocity vs. depth, but at low speeds, the noise is excessive (for various reasons). The trend at low speeds is correct, but I'd like to be able to apply a filter that will use an adaptive smoothing routine, i.e. for low speeds (where I have many data points) I need to use a larger smoothing window, and for high speeds (few data points) I need to use a smaller window.
I've looked a bit and have figured out a solution using rollapply() but was wondering if there are other approaches. In particular, I'm not clear on how to "vectorise" an operation. I'm a relatively new coder so I'm sorry if my code is a bit amateurish. My solution is below:
adapt<-function(x,wmin,wmax) {
# adapt takes a vector of calculated velocities (x), a minimum window size (wmin),
# and a maximum window size (wmax). It returns a vector of filtered velocities
#
x<-ifelse(is.na(x),0,x) # check for na values
x<-ifelse(is.infinite(1/x),1/wmax,x) # check for infinite values
x<-runmed(x,11) # smooth raw velocities using 11 point window
wins<-ceiling(ifelse(is.infinite(1/x),wmin,1+wmax/(1+x)^15)) # set window widths
wins<-ifelse(wins<=wmin,wmin,wins) # set min windows
wins<-ifelse(wins>wmax,wmax,wins) # set max windows
out<-rollapply(x,width=wins,median) # apply filter to each element
out[length(x)]<-0 # set last value to zero
return(out)
}