Capturing sudden changes of data plotted in Matlab - matlab

How can I capture big changes in graph like this:
It is clear that there are 3 sudden curves which can be seen by eyes.
Can anyone help me to determine the start of each of them?

Matlab has findpeaks function in signal toolbox (I think) doing exactly this.
Without that, a primitive solution can be done by finding the derivative of the signal and checking the zero crossings for local maximums and minimums. Obviously if your signal is noisy you need to smooth it or handle false positives afterwards.

Related

Matlab spectrograms giving imaginary-like numbers

I'm using MATLAB to work with some spectrograms. I'm new to this kind of thing and come from more of a CS background than a signals background, so I'm not sure what I'm missing here although it may turn out to be fairly basic.
I'm trying to compute spectral difference, which I conceptually am pretty sure I understand. I've got a signal, I can do the SFT on it with MATLAB's spectrogram() function. Then, I try to loop over the spectrogram for the entire signal and at each sampled point compute the difference from the previous point by looping over powers at each frequency and subtracting. I thought I had the concept down, but when I try to run it, I realize that the points returned when I write "MySpectrogram(n,k)" are complex numbers, or atleast look like that. They are formed such that the first part of the number is negative, and then after it there is a +Coefficient*I (-.07+0.0061i) for example. I tried to square these results. After squaring them, they still appear as complex numbers. Now I am totally lost. Can someone explain what's happening?
I'm calling s = spectrogram(x,window,noverlap,nfft).
Here's the documentation for spectrogram
If you need to access the power spectrum, use this:
[s,f,t,ps] = spectrogram(x,window,noverlap,f,fs)

Suggestions for defining limits of frequencies in Matlab Spectrogram function?

I am new to Matlab and signal processing. I am having an issue with defining the frequency range in which the spectrogram is processed. When I am plotting the spectrogram of .wav audio data, the y axis, frequency, spans from zero to around 23 kHz. The useful data I am looking for is in the range of 200-400 Hz. My code snippet is:
[samFa, fs] = audioread('samFa.wav'); %convert audio to numerical data
samFa = samFa(:,1); %take only one channel of numerical output
spectrogram(samFA,2205,1200,12800, fs,'yaxis','MinThreshold',-80);
I don't want to be some noobie that runs into a problem and instantly gives up and posts a duplicate question to stackoverflow, so I have done as much digging as I can, but am at my wit's end.
I scoured the documentation for parameters or ways to have Matlab only analyze a subset or range of the data, but found nothing. Additionally, in all of the examples the frequency range seems to automatically adapt to the data set.
I know it is possible to just calculate the spectrogram for the entire range of frequencies, and then remove all of the unnecessary data through truncating or manually changing the limits in the plot itself, but changing plotting limits does not help with the numerical data.
I went searching through many similar questions, and found an answer all the way from 2012 here: Can I adjust spectogram frequency axes?
where the suggested answer was to import a vector of specific frequencies for the spectrogram to analyze. I tried passing a vector of integer values between 200 and 400, and a few other test ranges, but got the error:
Error using welchparse>welch_options (line 297)
The sampling frequency must be a scalar.
I've tried passing the parameter in at different places in the function, with no avail, and don't see anything regarding this parameter in the documentation, leading me to believe that this functionality was possibly removed sometime between 2012 and now.
When plotting spectrogram without providing signal frequency, Matlab provides a normalized spectrogram, which only provides a much smaller data window, which I can visually assess to cover the data from 0:5kHz (an artifact of overtones in the audio), so I know that matlab is not finding any data above this range to make the frequency range go to 20kHz
I've been trying to learn some signal processing for this project, so I believe the Nyquist frequency should be the maximum frequency that a Fourier transform is able to analyze, to be half the sampling frequency. My recording frequency is sampling at 44,100 Hz, and the spectrogram is ranging to around 22 or 23 kHz, leading me to believe that it's Matlab is noticing my sampling frequency and assuming that it needs to analyze up to such a high range.
For my work I am doing I am needing to produce thousands of spectrograms to then be processed through much further analysis, so it is very time consuming for Matlab to be processing so much unecessary data, and I would expect there to be some functionality in Matlab somehow to get around this.
Sorry for the very long post, but I wanted to fully explain my problem and show that I have done as much work as I could to solve the problem before turning for help. Thank you very much.
Get the axis handle and set the visual range there:
spectrogram(samFA,2205,1200,12800, fs,'yaxis','MinThreshold',-80);
ax=gca;
ylim(ax, [0.2,0.4]); %kHz
And if you want to calculate specific frequencies range to save time you better use goertzel.
f = 200:10:400;
freq_indices = round(f/fs*N) + 1;
dft_data = goertzel(data,freq_indices);

Generating square wave using Matlab embeded function

I intend to generate a square wave which is applied on a DSP.
I have written these codes and put them in an embeded Matlab function.
function y = fcn(u)
%#eml
t=0:0.001:1
h = sign(sin(125600*t+u));
y= (h+1)/2
where, u is a constant value of 0.582 which is used for shifting the square wave.
The problem is at the output in the simulation, instead of getting a square wave, I see only two straight lines of y=o and y=1.
Please let me know where is the problem that I can not get the square wave?
Note that the frequency of square wave must be 20 kHz. Therefore, I adjust the sampling time as 1e-7 s. And also its amplitude is between 0 and 1 In addition, due to this signal must be transferred to a DSP board, in the "solver option" I chose the type: " Fixed-step" and for the Solver: "Discrete (no continues state)".
Thanks a lot.
This is wrong on many levels.
First of all, you never define the time vector inside a MATLAB Function, that's what the Simulink engine does. Pass time as an input to your MATLAB Function block and use a Clock block to generate the time input.
Second, the above is fine for simulation, but it sounds like you are generating C code from the Simulink model to run it (in real-time) on your DSP. This is not my area of expertise, but from memory, I think you need to enable "absolute time" or something similar for the above to work with code generation. However, I think this is target-dependent and so I'm not sure whether this will work on your DSP.
In you function type plot(t,y) at the end. You are generating a 20khz square wave (assuming you are sampling at 1e-7). Essentially your generating it is working.
Now, what is the DSP board you are using/any information that is relevant to your problem?
I don't know what you are referring to when you say "Solver" either.
Is the "simulation" an oscilloscope or a program? Either way perhaps it is not triggering correctly? Is there an edge trigger option?

phase spectrum of signal wrong generation matlab

I've got 129 samples of some signal. I have to discover what signal it is (what components it has) and try to reconstruct it.
so after I have done FFT i wanted to find phase of signal so i try:
phs=unwrap(angle(y));
pha_wek=(0:length(y)-1)'/length(y)*129;
plot(pha_wek,phs)
Result I've got it's not what I expected. Can you point me what is wrong ?
The plot looks exactly right to me, depending upon what the original signal is. The discontinuities in the phase angle are due to zero-crossings in the magnitude. However, the phase jumps are less than pi (which is what you might expect if the input signal were originally real and had been windowed when applying the FFT). So my guess is that this signal is some form of complex modulation with some discrete frequencies.
Generally viewing the phase tells you a lot less about the signal than its magnitude. It is essential for reconstructing the signal, but much harder to interpret (particularly as it is subject to dramatic changes with a simple shift in the time domain).
You might be better plotting the phase without using the unwrap command In this case, the issue is the unwrap command - its aim is to limit jumps in phase to be less than pi, which is why the final phase is around -4pi.
I'm not sure what your challenge is, but it isn't clear what you mean by reconstructing the samples. You've already got these, so what's the issue? (Are you being asked to reconstruct interpolated samples)?

how to make a smooth plot in matlab

I have about 100 data points which mostly satisfying a certain function (but some points are off). I would like to plot all those points in a smooth curve but the problem is the points are not uniformly distributed. So is that anyway to get the smooth curve? I am thinking to interpolate some points in between, but the only way that comes up to my mind is to linearly insert some artificial points between two data points. But that will show a pretty weird shape (like some sharp corner). So any better idea? Thanks.
If you know more or less what the actual curve should be, you can try to fit that curve to your points (e.g. using polyfit). Depending on how many points are off and how far, you can get by with least squares regression (which is fairly easy to get working). If you have too many outliers (or they are much too large/small), you can also try robust regression (e.g. least absolute deviation fitting) using the robustfit function.
If you can manually determine the outliers, you can also fit a curve through the other points to get better results or even use interpolation methods (e.g. interp1 in MATLAB) on those points to get a smoother curve.
If you know which function describes your data, robust fitting (using, e.g. ROBUSTFIT, or the new convenient functions LINEARMODEL and NONLINEARMODEL with the robust option) is a good way to go if there are outliers in your data.
If you don't know the function that describes your data, but want a smooth trendline that is little affected by outliers, SMOOTHN from the File Exchange does an excellent job in my experience.
Have you looked at the use of smoothing splines? Like interpolating splines, but with the knot points and coefficients chosen to minimise a least-squares error function. There is an excellent implementation available from Matlab central which I have used successfully.