matlab spectrum returns more FRAME than expected - matlab

I'm using the following code to get specgram2D from np array:
specgram2D, freq, time = mlab.specgram(samples, Fs=11025, NFFT=1024, window=mlab.window_hanning, noverlap=int(1024 * 0.5))
Then I print out specgram2D like
print len(specgram2D) # returns 513
I got 513 instead of expected 512 which is half the window size.
What am I doing wrong?
Can I just ignore specgram2D[512]?

I got 513 instead of expected 512 which is half the window size.
What am I doing wrong?
For a real-valued signal, the frequency spectrum obtained from the Discrete Fourier Transform (DFT) is symmetric and hence only half of the spectrum is necessary to describe the entire spectrum (since the other half can be obtained from symmetry). That is probably why you are expecting the size to be exactly half the input window size of 1024.
The problem is that with even sized inputs, the midpoint of the spectrum falls exactly on a frequency bin. As a result, that frequency bin is its own symmetry. To illustrate this, the symmetry can be seen from the following graph:
frequency: 0 fs/N ... fs/2 ... fs
bin number: 0 1 ... 511 512 513 ... 1023 1024
^ ^ ^ ^ ^ ^ ^ ^
| | | |-| | | |
| | | | | |
| | |--------| | |
| | | |
| |----------------------------| |
| |
|--------------------------------------|
Where N is the size of the FFT (as determined by the NFFT=1024 parameter) and fs is the sampling frequency. As you can see the spectrum is fully specified by taking bins 0 to 512, inclusive. Correspondingly you should be expecting the size to be floor(N/2)+1 (simply N/2 + 1 with integer division, but I included the floor to emphasis the round down operation), or 513 in your case.
Can I just ignore specgram2D[512]?
As previously shown it is an integral part of the spectrum, but many applications do not specifically require every single frequency bins (i.e. ignoring that bin depends on whether your application is mostly interested in other frequency components).

Related

How to change the rounding mode for floating point operations in MATLAB?

I want to change the rounding mode for floating point operations in MATLAB. According to IEEE 754-2008, there are 5 strategies for rounding:
round to nearest, ties to even
round to nearest, ties away from zero
round toward zero
round up (toward positive infinity)
round down (toward negative infinity)
Does MATLAB supports these 5 strategies? How to change the rounding mode for floating point operations in MATLAB?
Answer
Kind of. There is an undocumented feature('setround') function call that you can use to get or set the rounding mode used by Matlab.
So, it can be done, but you shouldn’t do it. :)
WARNING: This is an undocumented, unsupported feature! Use at your own peril!
This feature('setround') supports 4 of the 5 IEEE-754 rounding modes: there’s only one “nearest” mode, and I don't know if it’s “ties to even” or “ties away from zero”.
Supported modes:
feature('setround') – Get current rounding mode
feature('setround', 0.5) – Round toward nearest (don’t know if it’s ties to even or away from zero)
feature('setround', Inf) – Round up (towards +Inf)
feature('setround', 0) – Round toward zero
feature('setround', -Inf) – Round down (towards -Inf)
Note on testing: The IEEE-754 rounding mode does not affect round() and its relatives. Rather, it governs how arithmetic operations behave around the limits of floating-point precision.
Demonstration
%ROUNDINGEXAMPLE Demonstrates IEEE-754 Rounding Mode control
%
% This uses a completely undocumented and unsupported feature!
% Not for production use!
%% Setup
clear; clc
n = 2000;
X = ones(n)*1E-30; % matrix with n^2 elements
defaultRoundingMode = feature('setround'); % store default rounding mode
%%
feature('setround',0.5);
r1 = prettyPrint('Nearest', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001110101010000011110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001110101010000011110 = 4e-24
%}
%%
feature('setround',-Inf);
r2 = prettyPrint('To -Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',Inf);
r3 = prettyPrint('To Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010100011101100100001
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010100011101100100001 = 4e-24
%}
%%
feature('setround',0);
r4 = prettyPrint('To zero', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',defaultRoundingMode);
r5 = prettyPrint('No accumulated roundoff error', 4e-24);
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010001000111010100111
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010001000111010100111 = 4e-24
%}
%% Helper function
function r = prettyPrint(s, r)
fprintf('%s:\n%65.60f\n\n', s, r);
end
I get:
Nearest:
0.000000000000000000000003999999999966490758963870373537264729
To -Infinity:
0.000000000000000000000003999999999789077070014108839608005726
To Infinity:
0.000000000000000000000004000000000118618095059505975310731249
To zero:
0.000000000000000000000003999999999789077070014108839608005726
No accumulated roundoff error:
0.000000000000000000000003999999999999999694801998206811298525
Acknowledgments
Thanks to Ryan Klots at MathWorks Technical Support for setting me straight on this and providing the nice demo code!
#HYF: I found that feature('setround', 0.5) leads to round to even.
I checked the following:
a=1+2^-52
This means that mantissa looks like so: 1.0...01 where the last 1 is still in the mantissa. The leading 1 is not stored in IIIE754 format.
( I checked that 1+2^-52 == 1 but not 1+2^-53 == 1)
Then I computed b = a + 2^-53.
Without rounding it is 1.0...01|1 where the last digit is to be rounded away.
I found the following true: b==1+2^-51
We have b == 1.0...010.
We have several rounding modes submodes of round to nearest:
This can be round to inf, round away from 0 or round to even.
Next we check -b==-1-2^-51 to be true which excludes round to inf
still allowing round away from 0 or round to even.
Then I checked 1.5==1.5+2^-53.
Of course 1.5 = 1.10...0 binary and
and 1.5+2^-53 = 1.10...0|1 without rounding, the last digit to be rounded away.
Rounding away from 0 would be 1.10...01
and rounding to even is 1.10...0.
So the latter is the case.

How does the Graphite summarize function with avg work?

I'm trying to figure out how the Graphite summarize function works. I've the following data points, where X-axis represents time, and Y-axis duration in ms.
+-------+------+
| X | Y |
+-------+------+
| 10:20 | 0 |
| 10:30 | 1585 |
| 10:40 | 356 |
| 10:50 | 0 |
+-------+------+
When I pick any time window on Grafana more than or equal to 2 hours (why?), and apply summarize('1h', avg, false), I get a triangle starting at (9:00, 0) and ending at (11:00, 0), with the peak at (10:00, 324).
A formula that a colleague came up with to explain the above observation is as follows.
Let:
a = Number of data points for a peak, in this case 4.
b = Number of non-zero data points, in this case 2.
Then avg = sum / (a + b). It produces (1585+356) / 6 = 324 but doesn't match with the definition of any mean I know of. What is the math behind this?
Your data is at 10 minute intervals, so there are 6 points in each 1hr period. Graphite will simply take the sum of the non-null values in each period divided by the count (standard average). If you look at the raw series you'll likely find that there are also zero values at 10:00 and 10:10

Postgresql Geometric Line - Finding the Y intercept

I have an model that can be represented by multiple linear segments as below:
Y
| _/_________\_
| / \
| / \
| / \
|/ \
|
|________________________ X
I would need to find the value of Y for a given value of X
My initial though was to store each segment as a relational line type {A, B, C}. However I'm not sure what would that buy me in terms of finding a proper query to retrieve the Y value.
Since you are working with linear segments, you should use the lseg data type (the line data type represents a line of infinite length). Once you have your data in that format you can find the intersection of the segments with a vertical line of infinite length at the desired value of X and extract the Y value of the intersection.
CREATE TABLE segments (id int, seg lseg);
INSERT INTO segments VALUES
(1, '[(4,3), (12,15)]'), -- positively inclined line segment
(2, '[(2,19), (24,-4)]'), -- negatively inclined line segment
(3, '[(4,3), (12,3)]'), -- horizontal line segment
(4, '[(5,3), (5,15)]'), -- vertical line segment, collinear at X=5
(5, '[(4,3), (4,15)]'); -- vertical line segment, no intersection at X=5
and then:
test=# SELECT id, 5 AS x, (seg # '((5,-999999999), (5,999999999))'::lseg)[1] AS y
test-# FROM segments;
id | x | y
----+---+------------------
1 | 5 | 4.5
2 | 5 | 15.8636363636364
3 | 5 | 3
4 | 5 |
5 | 5 |
(5 rows)
As is obvious from the above, collinear line segments (i.e. vertical line segments with the same value for X) and segments without intersection return NULL for Y.

Simulation of custom probability distribution in Matlab

I'm trying to simulate the following distribution:
a | 0 | 1 | 7 | 11 | 13
-----------------------------------------
p(a) | 0.34 | 0.02 | 0.24 | 0.29 | 0.11
I already simulated a similar problem: four type of balls with chances of 0.3, 0.1, 0.4 and 0.2. I created a vector F = [0 0.3 0.4 0.8 1] and used repmat to grow it by 1000 rows. Then I compared it with a columnvector of 1000 random numbers grown with 5 columns using the same repmat approach. I compared those two, calculated the sumvector of the matrix, and calculated the difference to get the frequences (e.g. [301 117 386 196]). .
But with the current distribution I don't know how to create the initial matrix F and whether I can use the same approach I used before at all.
I need the answer to be "vectorised", so no (for, while or if) loops.
This question on math.stackexchange
What if you create the following arrays:
largeNumber = 1000000;
a=repmat( [0], 1, largeNumber*0.34 );
b=repmat( [1], 1, largeNumber*0.02 );
% ...
e=repmat( [13], 1, largeNumber*0.11 );
Then you concatenate all of these arrays (to get a single array where your entries are represented with their corresponding probabilities), shuffle them, and extract the first N elements to get an N-dimensional vector drawn from your distribution.
EDIT: of course this answer is the way to go.

Fast way for solving symbolic system of equations in Matlab

I have a system of equations with 100001 variables (x1 through x100000 and alpha) and exactly that many equations. Is there a computationally efficient way, in Matlab or otherwise, to solve this system of equations. I know of the solve() command, but I'm wondering if there is something that will run faster. The equations are of the form:
1.) -x1 + alpha * (x4 + x872 + x9932) = 0
.
.
.
100000.) -x100000 + alpha * (x38772 + x95) = 0
In other words, the i^th equation has variable xi with coefficient -1 added to alpha * (sum of some other variables) equals 0. The final equation is just that x1 + ... + x100000 = 1.
The Math Part
This system may be always brought to the eigen[value/vector] equation canonical form:
**A***x* = λx
where A is your system's matrix, and x = [x1; x2; ...; x100000]. Taking the example from this question, the system may be written down as:
/ \ / \ / \
| 0 1 0 0 0 | | x1 | | x1 |
| 0 0 1 0 1 | | x2 | | x2 |
| 1 0 0 0 0 | x | x3 | = (1/alpha) | x3 |
| 0 0 1 0 0 | | x4 | | x4 |
| 0 1 0 1 0 | | x5 | | x5 |
\ / \ / \ /
This means that your eigenvalues λ = 1/α. Of course, you should beware of complex eigenvalues (unless you really want to take them into account).
The Matlab part
Well this is much to your taste and skills. You can always find the eigenvalues of a matrix with eig(). Better to use sparse matrices (memory economy):
N = 100000;
A = sparse(N,N);
% Here's your code to set A's values
A_lambda = eig(A);
ieps= 0e-6; % below this threshold imaginary part is considered null
alpha = real(1 ./ (A_lambda(arrayfun(#(x) imag(x)<ieps, A_lambda)))); % Chose Real. Choose Life. Choose a job. Choose a career. Choose a family. Choose a f****** big television, choose washing machines, cars, compact disc players and electrical tin openers. Choose good health, low cholesterol, and dental insurance. Choose fixed interest mortgage repayments. Choose a starter home. Choose your friends. Choose leisurewear and matching luggage. Choose a three-piece suit on hire purchase in a range of f****** fabrics. Choose DIY and wondering who the f*** you are on a Sunday morning. Choose sitting on that couch watching mind-numbing, spirit-crushing game shows, stuffing f****** junk food into your mouth. Choose rotting away at the end of it all, pissing your last in a miserable home, nothing more than an embarrassment to the selfish, f***** up brats you spawned to replace yourself. Chose life.
% Now do your stuff with alpha here
But, mind this: numerically solving large eigenvalue equations might give you complex values where real are expected. Tweak your ieps to sensible values, if you don't find anything in the beginning.
To find the eigenvectors, just take one out of the system and solve for the rest by means of Cramer's rule. The norm them to one if you wish so.