Biquad to 4quad filter - filter

I have a BandPass Biquad filter which expression is:
Result = Nominator[0] * Input + FState[0];
State[0] = Nominator[1] * Input - Denominator[1] * Result + State[1];
State[1] = Nominator[2] * Input - Denominator[2] * Result;
How can I improve the order of this filter without making a ladder of two identical filters?
Can I save some calculations for that?
Thank you so much!

Although it is possible to do direct implementations of higher order filters, they tend to require extremely high-precision arithmetic, so most filter designers prefer to factor hi-order filters into series of biquads.
There is a good tutorial at https://ccrma.stanford.edu/~jos/filters/filters.html

Related

How do you ensure accuracy when dealing with ints and doubles within conditions?

Beginner here.
How does one ensure accuracy when dealing with small margins like this? one of my test cases results in 100.9 - which obviously isn't triggering the fee increase.
The floor division works for calculating the correct fee, but I'm not sure how to handle that preceding statement. Do I need to type cast every number to a double?
if ((Math.ceil(weightPerItemInOz * numberOfItems) / 16) > 100)
fee = fee * (Math.floor((double)(weightPerItemInOz * numberOfItems) / 1000)); ```

How to computer range from loss factor

I am trying to understand the following code given in MediumLimitCache.cc file to understand the formula of finding communication range using loss factor. I know for isotropic antenna, FSPL = Pt/Pr = (4*pi*d*f/c)^2. I could not understand how this formula is implemented in below code.
Would anyone please explain me the functions of the below code? Thank you.
m MediumLimitCache::computeMaxRange(W maxTransmissionPower, W minReceptionPower) const
{
// TODO: this is NaN by default
Hz centerFrequency = Hz(par("centerFrequency"));
**double loss = unit(minReceptionPower / maxTransmissionPower).get() / maxAntennaGain / maxAntennaGain;
return radioMedium->getPathLoss()->computeRange(radioMedium->getPropagation()->getPropagationSpeed(), centerFrequency, loss);**
}
The formula is NOT implemented in this code. This is MediumLimitCache i.e. this is just an optimization component that requires a maximum estimation.
You might find more info inside the computeRange() method.

Is there a more efficient way to oversample data than random.sample()?

I got a big unbalanced classification problem and want to address this issue by oversampling the minor classes. (N(class 1) = 8,5mio, N(class n) = 3000)
For that purpose I want to get 100.000 sample for each of the n classes by
data_oversampled = []
for data_class_filtered in data:
data_oversampled.append(data_class_filtered.sample(n=20000, replace=True))
where data is a list of class specific DataFrames and len(data)=10, data.shape=(9448788,97)
That works as expected but unfortunately takes literally forever. Is there a more efficient way to do the same thing?

Eigen Matrix Smart pointer move construction

Code as below:
// Generate the returns matrix
boost::shared_ptr<Eigen::MatrixXd> returns_m = boost::make_shared<Eigen::MatrixXd>(factor_size, num_of_obs_per_simulation);
//Generate covariance matrix
boost::shared_ptr<MatrixXd> corMatrix = boost::make_shared<MatrixXd>(factor_size, factor_size);
(*corMatrix) = (*returns_m) * (*returns_m).transpose() / (num_of_obs_per_simulation - 1);
The point is that I want to return the corMatrx as a pointer, not as an object, to be stored as a member of a result class for later use. Above code seems to make a copy of the big matrix, is there any better way to do it?
Thank you and best wishes...
Slight improvement to #ggael's answer, you can directly construct your corMatrix shared pointer from the expression:
boost::shared_ptr<MatrixXd> corMatrix
= boost::make_shared<MatrixXd>((*returns_m) * (*returns_m).transpose() * (1./(num_of_obs_per_simulation - 1));
Or, you can exploit the symmetry of the product using rankUpdate:
boost::shared_ptr<MatrixXd> corMatrix = boost::make_shared<MatrixXd>(MatrixXd::Zero(factor_size, factor_size));
corMatrix->selfadjointView<Eigen::Upper>().rankUpdate(*returns_m, 1.0 / (num_of_obs_per_simulation - 1));
// optionally copy upper half to lower half as well:
corMatrix->triangularView<Eigen::StrictlyLower>() = corMatrix->adjoint();
I don't understand your question as returning corMatrix as a shared_ptr will do exactly what you want, but regarding your product, you can save one temporary using noalias and * (1./x):
(*corMatrix).noalias() = (*returns_m) * (*returns_m).transpose() * (1./(num_of_obs_per_simulation - 1));
The whole expression will be turned as a single call to a gemm-like routine.
To complete the explanation:
Recall that Eigen is an expression template library, so when you do A = 2*B + C.transpose(); with A,B,C matrices, then everything happen in operator=, that is the right-hand-side expression is directly evaluated within A. For products, the story is slightly different because 1) to be efficient it needs to be directly evaluated within something, and 2) it is not possible to directly write to the destination if there is aliasing, e.g.: A = A*B. The noalias tells Eigen that the destination does not not alias and the product can be directly evaluated within it.

Build fixed interval dataset from random interval dataset using stale data

Update: I've provided a brief analysis of the three answers at the bottom of the question text and explained my choices.
My Question: What is the most efficient method of building a fixed interval dataset from a random interval dataset using stale data?
Some background: The above is a common problem in statistics. Frequently, one has a sequence of observations occurring at random times. Call it Input. But one wants a sequence of observations occurring say, every 5 minutes. Call it Output. One of the most common methods to build this dataset is using stale data, i.e. set each observation in Output equal to the most recently occurring observation in Input.
So, here is some code to build example datasets:
TInput = 100;
TOutput = 50;
InputTimeStamp = 730486 + cumsum(0.001 * rand(TInput, 1));
Input = [InputTimeStamp, randn(TInput, 1)];
OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001)';
Output = [OutputTimeStamp, NaN(TOutput, 1)];
Both datasets start at close to midnight at the turn of the millennium. However, the timestamps in Input occur at random intervals while the timestamps in Output occur at fixed intervals. For simplicity, I have ensured that the first observation in Input always occurs before the first observation in Output. Feel free to make this assumption in any answers.
Currently, I solve the problem like this:
sMax = size(Output, 1);
tMax = size(Input, 1);
s = 1;
t = 2;
%#Loop over input data
while t <= tMax
if Input(t, 1) > Output(s, 1)
%#If current obs in Input occurs after current obs in output then set current obs in output equal to previous obs in input
Output(s, 2:end) = Input(t-1, 2:end);
s = s + 1;
%#Check if we've filled out all observations in output
if s > sMax
break
end
%#This step is necessary in case we need to use the same input observation twice in a row
t = t - 1;
end
t = t + 1;
if t > tMax
%#If all remaining observations in output occur after last observation in input, then use last obs in input for all remaining obs in output
Output(s:end, 2:end) = Input(end, 2:end);
break
end
end
Surely there is a more efficient, or at least, more elegant way to solve this problem? As I mentioned, this is a common problem in statistics. Perhaps Matlab has some in-built function I'm not aware of? Any help would be much appreciated as I use this routine a LOT for some large datasets.
THE ANSWERS: Hi all, I've analyzed the three answers, and as they stand, Angainor's is the best.
ChthonicDaemon's answer, while clearly the easiest to implement, is really slow. This is true even when the conversion to a timeseries object is done outside of the speed test. I'm guessing the resample function has a lot of overhead at the moment. I am running 2011b, so it is possible Mathworks have improved it in the intervening time. Also, this method needs an additional line for the case where Output ends more than one observation after Input.
Rody's answer runs only slightly slower than Angainor's (unsurprising given they both employ the histc approach), however, it seems to have some problems. First, the method of assigning the last observation in Output is not robust to the last observation in Input occurring after the last observation in Output. This is an easy fix. But there is a second problem which I think stems from having InputTimeStamp as the first input to histc instead of the OutputTimeStamp adopted by Angainor. The problem emerges if you change OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001)'; to OutputTimeStamp = 730486.002 + (0:0.0001:TOutput * 0.0001 - 0.0001)'; when setting up the example inputs.
Angainor's appears robust to everything I threw at it, plus it was the fastest.
I did a lot of speed tests for different input specifications - the following numbers are fairly representative:
My naive loop: Elapsed time is 8.579535 seconds.
Angainor: Elapsed time is 0.661756 seconds.
Rody: Elapsed time is 0.913304 seconds.
ChthonicDaemon: Elapsed time is 22.916844 seconds.
I'm +1-ing Angainor's solution and marking the question solved.
This "stale data" approach is known as a zero order hold in signal and timeseries fields. Searching for this quickly brings up many solutions. If you have Matlab 2012b, this is all built in to the timeseries class by using the resample function, so you would simply do
TInput = 100;
TOutput = 50;
InputTimeStamp = 730486 + cumsum(0.001 * rand(TInput, 1));
InputData = randn(TInput, 1);
InputTimeSeries = timeseries(InputData, InputTimeStamp);
OutputTimeStamp = 730486.002 + (0:0.001:TOutput * 0.001 - 0.001);
OutputTimeSeries = resample(InputTimeSeries, OutputTimeStamp, 'zoh'); % zoh stands for zero order hold
Here is my take on the problem. histc is the way to go:
% find Output timestamps in Input bins
N = histc(Output(:,1), Input(:,1));
% find counts in the non-empty bins
counts = N(find(N));
% find Input signal value associated with every bin
val = Input(find(N),2);
% now, replicate every entry entry in val
% as many times as specified in counts
index = zeros(1,sum(counts));
index(cumsum([1 counts(1:end-1)'])) = 1;
index = cumsum(index);
val_rep = val(index)
% finish the signal with last entry from Input, as needed
val_rep(end+1:size(Output,1)) = Input(end,2);
% done
Output(:,2) = val_rep;
I checked against your procedure for a few different input models (I changed the number of Output timestamps) and the results are the same. However, I am still not sure I understood your problem, so if something is wrong here let me know.

Resources