Logarithmic sampling - sampling

I am working with values between [minValue,maxValue] and I want to create a vector of values in between this range. But I want more values near to the minValue.
Example:
min = 1
max = 100
vector = [1,1.1,1.5,2,3,5,10,15,30,50,100];
Something like that.
The goal is to be more accurate around the minimum.
Is that possible to implement that?

You can start with by generating numbers from 0 to 1 with constant step (for example 0.1). Then power them with some exponent - the bigger exponent, the sharper curve. Then shift and multiply to get into your desired min-max range.
Pseudocode:
min = 1.0
max = 100.0
exponent = 2.0 // Sharpness
result = []
for(i = 0.0; i <= 1.0; i += 0.1) {
result.push(pow(i, exponent) * (max - min) + min)
}

I had the same problem. I wanted well spaced points, but with much more point near the minimal value. I used a logarithmic transformation. Firstly the code:
function SampleData (min, max, points) {
min = min || 1; // Minimum value
max = max || 1600; // Maximum value
points = points || 20; // data points between Min&Max
var step = (Math.log(max)-Math.log(min))/(points-1);
var data = [];
var D= 100; // max asy
var A= 0; // min asy
var C= 50; // inflectio
var B= 1; // Hills slope
for (i = Math.log(min); i <= Math.log(max); i=i+step) {
data.push ([Math.exp(i), math.eval (D+'+('+A+'-'+D+')/(1+('+math.exp(i)+'/'+C+')^'+B+')')]);
}
}
The trick I used is to compress the data range (here 1 to 1600) with the logarithmic function; thereby, I was able to use a linear constant step width. Before feeding the x value into the math function, you have to back transform (math.exp) the values.
The function in math.eval is a rather complicated 4 paramater logistic fit, you might of course use something else.
In the image you see a plot of above mentioned function once with linear step width (orange) and once with my logarithmic step width (red).
Visualisation of linear and logarithmic step width in data sampling.

Related

Fixed-point: out_Q15 = antilog( in_Q25 ) calculation, avoiding overflow?

I am using a 3rd-party fixed-point antilog() function to calculate magnitude from decibel out_mag = 10^( in_db/20 ). The antilog() takes Q6.25 format as input, and provides Q16.15 at output.
The problem is that antilog() quickly overflows for some higher dB valus, like 100 dB: 10^( 100/20 ) = 100000. The highest value Q16.15 format can have is 2^16-1=65535, so 100000 doesn't fit.
Is there a trick to avoid the overflow? Prescale input value somehow?
I managed to find a solution. It's a bit tricky.
First, a struct that will hold the output result is needed:
typedef struct
{
q15 v; // Value (within the [MIN, MAX] range for Q16.15).
int32 s; // Scalefactor.
} q15_t;
The idea is to provide result as Output with Scalefactor, where
Output = 10^y
Scale = 2^scalefactor
Final output is Output shifted left scalefactor times.
Here is the math.
Input Q31 format is dB value scaled to [-1,1] with scale being 2^scalefactor.
We need to calculate:
Out = 10^(2^scalefactor * in/20.0)
= 10^(p+y) // rewriting as sum
= 10^p * 10^y // to enable exponent multiplication
= 2^scalefactor * 10^y // making it power of 2 to be able to just shift
This way we are not limited with Q16.15 max value.
We already know 2^scalefactor, but need to find y:
2^scalefactor * in = p + y
10^p = 2^scalefactor => p = scalefactor*log(2) // rewrite as power of 2
2^scalefactor * in = scalefactor*log(2) + y // replace p
y = 2^scalefactor*in - scalefactor*log(2) // and find y
Calculate y, and feed it into antilog.
If input is 100 dB, then the output magnitude should be 100.000, which doesn't fit into Q16.15 format. Using the above solution, Output = 50.000 (this fits into Q16.15!) and scalefactor = 1, meaning, the final output is 50.000 shifted to left 1 place. This gives 100.000 as the final result. Depending on your implementation, you might get the same result as 25.000 with scalefactor = 2, etc. The idea is there.

How to scale a number/range of numbers in c

I want to be able to display the altitude in ft ranging from 0ft to 20000ft on my LCD module. The numbers are read from a potentiometer that I can rotate to change the values. At the moment the potentiometer displays from 0 to 1023 but I need to scale these appropriately so they read from 0-20000ft. As well as this I want the line below to display a 'bar graph' to represent the altitude increasing. The LCD has 20 blocks per line so the bar graph can range from 1 block to 20 blocks.
sprintf(buf, "Altitude: %d ", DELVAL2); // display altitude level
lcd_putxy(1,0,buf);
for (delay = 0; delay < 50000; delay++); // introduce a delay
sprintf(buf, "*", DELVAL2 ); // display bar graph
lcd_putxy(2,0,buf);
for (delay = 0; delay < 50000; delay++); // introduce a delay
This is my code so far. It reads the value from the potentiometer DELVAL2 and displays it on the LCD. Can someone please explain a method of how I can scale the data appropriately to produce an altitude and bar graph.
If your DELVAL2 is in range 0-1023 you can scale it to 0-20000, but you cannot get bigger resolution than (1/1024) * 20000. Why? Minimum value (single bit) you can read is 1/1024. Your maximum value is 20000, so one bit change on DELVAL2 will result in 20000/1024 = 19,53 change on scaled value.
You can calculate how to scale it, it's already described on stackoverflow:
How to scale down a range of numbers with a known min and max value
You must keep in mind that you may fall into floating point operation and this is something that you may want to avoid. For example, you can do something like this
scaled = (DELVAL2 * 1953) / 1000;
instead of
scaled = DELVAL2 * 19.53;
Keep in mind that maximum value that you can get inside this computation will be 1024*1953 = 1999872, so you need 32 bit variable. Additional cast may be needed, depending on your architecture and compiler, eg
scaled = (DELVAL2 * (uint32_t)1953) / 1000;
About second question - bar graph - you are on good way. Calculate how many symbols do you need and draw them. It's scaling down instead of up. Simple division should be enough. When you know how many symbols you need, generate them in simple loop
for(int i = 0; i < num; i++)
buf[i] = '*';
buf[i] = 0; //last symbol is 0 to stop drawing
lcd_putxy(2,0,buf);
To scale [0...1023] to [0...20000] multiply by 20,000 and then divide by 1023.
int altitude = (int) ((potentiometer*20000L + 1023/2)/1023);
Code uses long multiplication as int may only be 16-bit on a micro-controller. Not necessary if INT_MAX == 0x7FFFFFFF.
The + 1023/2 is to provide a rounded conversion.
Presumably buf is a 16-bit integer, and contains the pot value. Presumably you can rely on it being limited to the values [0, 1023].
If you do
int scaledbuf;
scaledbuf = buf >> 5;
you'll get a value of scaledbuf in the range [0, 32736]. You could then do
if (scaledbuf > 20000) scaledbuf = 20000;
At the cost of sacrificing some of the range of your pot, this will give you a value in the range [0,20000] without doing any multiplications, only a left shift.
But, you're torching cycles in your delay loops anyway, so you can probably manage the cost of a multiplication by 20.
int scaledbuf;
scaledbuf = buf * 20;
if (scaledbuf > 20000) scaledbuf = 20000;
This preserves considerably more of your pot's range while keeping you in the realm of 16-bit arithmetic.

How to apply frequency filter on fftw output

I get the 2d FFTW output of an image using fftw_plan_dft_2d(). As I understand it, the output represents a 2D array (width x height) of complex numbers.
Can someone please explain to me how exactly I should interpret this array? What does each point represent? And what does the value of each point represent?
If I wanted to apply a high-pass filter, how would I do that? I tried the code below, but all I get is overlapped shifted image when I do reverse FFT.
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
xx = ABS(x - width / 2);
yy = ABS(y - height / 2);
if (sqrt(xx * xx + yy * yy) > width / 2)
{
fft[y * width + x][0] = 0;
fft[y * width + x][1] = 0;
}
}
What Does the FFT Compute?
The FFT converts an image in the spatial domain (x and y) to the frequency domain. In the spatial domain each point represents a pixel and its magnitude represents the colour of the pixel. Whereas, in the frequency domain each point represents a frequency and its magnitude is the contribution of that frequency to the image. The strength of the magnitude determines the strength of the contribution of that frequency.
Another way of looking at the FFT is that it decomposes an image into sine and cosine components of varying frequencies.
Result of fftw_plan_dft_2d()
When you apply the 2D FFT to an image with fftw_plan_dft_2d() and fftw_execute() the resulting output will be the frequency spectrum of the image. The DC component corresponding to 0Hz will be present in out[0] whilst the high frequency component will be present in out[N-1] where N = n x m and n is the number of pixels in the x-direction and m is the number of pixels in the y-direction.
The output of FFTW is in contrast to what would be typically graphed where the DC component (0Hz) is typically positioned at the center of the image, as below, and the frequencies increase radially as you travel away from the centre.
The typical method applied to the output of an FFT to center its DC component is to use a function called fftshift(). It is defined in MATLAB or Octave and has a discussion on converting it to C/C++ on StackOverflow.
Applying High Pass Filter to FFT Output
After applying fftshift() it becomes trivial to apply a high pass (or any other type of) filter to the FFT output. A high pass filter will only allow high frequencies through and can be implemented trivially with
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int index = i + j*m;
double x = i*dx;
double y = i*dy;
if (sqrt(x*x + y*y) < radius) { // All frequencies in radius deleted
fft[index][0] = 0;
fft[index][1] = 0;
}
}
}
Aside
FFTW computes an unnormalised FFT and IFFT so when you are performing the IFFT you need to multiply by a factor of 1/N to get back to the original image.

Calculate maclaurin series for sin using C

I wrote a code for calculating sin using its maclaurin series and it works but when I try to calculate it for large x values and try to offset it by giving a large order N (the length of the sum) - eventually it overflows and doesn't give me correct results. This is the code and I would like to know is there an additional way to optimize it so it works for large x values too (it already works great for small x values and really big N values).
Here is the code:
long double calcMaclaurinPolynom(double x, int N){
long double result = 0;
long double atzeretCounter = 2;
int sign = 1;
long double fraction = x;
for (int i = 0; i <= N; i++)
{
result += sign*fraction;
sign = sign*(-1);
fraction = fraction*((x*x) / ((atzeretCounter)*(atzeretCounter + 1)));
atzeretCounter += 2;
}
return result;
}
The major issue is using the series outside its range where it well converges.
As OP said "converted x to radX = (x*PI)/180" indicates the OP is starting with degrees rather than radians, the OP is in luck. The first step in finding my_sin(x) is range reduction. When starting with degrees, the reduction is exact. So reduce the range before converting to radians.
long double calcMaclaurinPolynom(double x /* degrees */, int N){
// Reduce to range -360 to 360
// This reduction is exact, no round-off error
x = fmod(x, 360);
// Reduce to range -180 to 180
if (x >= 180) {
x -= 180;
x = -x;
} else if (x <= -180) {
x += 180;
x = -x;
}
// Reduce to range -90 to 90
if (x >= 90) {
x = 180 - x;
} else if (x <= -90) {
x = -180 - x;
}
//now convert to radians.
x = x*PI/180;
// continue with regular code
Alternative, if using C11, use remquo(). Search SO for sample code.
As #user3386109 commented above, no need to "convert back to degrees".
[Edit]
With typical summation series, summing the least significant terms first improves the precision of the answer. With OP's code this can be done with
for (int i = N; i >= 0; i--)
Alternatively, rather than iterating a fixed number of times, loop until the term has no significance to the sum. The following uses recursion to sum the least significant terms first. With range reduction in the -90 to 90 range, the number of iterations is not excessive.
static double sin_d_helper(double term, double xx, unsigned i) {
if (1.0 + term == 1.0)
return term;
return term - sin_d_helper(term * xx / ((i + 1) * (i + 2)), xx, i + 2);
}
#include <math.h>
double sin_d(double x_degrees) {
// range reduction and d --> r conversion from above
double x_radians = ...
return x_radians * sin_d_helper(1.0, x_radians * x_radians, 1);
}
You can avoid the sign variable by incorporating it into the fraction update as in (-x*x).
With your algorithm you do not have problems with integer overflow in the factorials.
As soon as x*x < (2*k)*(2*k+1) the error - assuming exact evaluation - is bounded by abs(fraction), i.e., the size of the next term in the series.
For large x the biggest source for errors is truncation resp. floating point errors that are magnified via cancellation of the terms of the alternating series. For k about x/2 the terms around the k-th term have the biggest size and have to be offset by other big terms.
Halving-and-Squaring
One easy method to deal with large x without using the value of pi is to employ the trigonometric theorems where
sin(2*x)=2*sin(x)*cos(x)
cos(2*x)=2*cos(x)^2-1=cos(x)^2-sin(x)^2
and first reduce x by halving, simultaneously evaluating the Maclaurin series for sin(x/2^n) and cos(x/2^n) and then employ trigonometric squaring (literal squaring as complex numbers cos(x)+i*sin(x)) to recover the values for the original argument.
cos(x/2^(n-1)) = cos(x/2^n)^2-sin(x/2^n)^2
sin(x/2^(n-1)) = 2*sin(x/2^n)*cos(x/2^n)
then
cos(x/2^(n-2)) = cos(x/2^(n-1))^2-sin(x/2^(n-1))^2
sin(x/2^(n-2)) = 2*sin(x/2^(n-1))*cos(x/2^(n-1))
etc.
See https://stackoverflow.com/a/22791396/3088138 for the simultaneous computation of sin and cos values, then encapsulate it with
def CosSinForLargerX(x,n):
k=0
while abs(x)>1:
k+=1; x/=2
c,s = getCosSin(x,n)
r2=0
for i in range(k):
s2=s*s; c2=c*c; r2=s2+c2
s = 2*c*s
c = c2-s2
return c/r2,s/r2

EXIF fraction calculation

I am modifying jpeg EXIF data. Some data requires to be defined as a fractions.
Here, I have two problems:
1.) Which is the correct fraction "format"? For instance when I have an exposure time ("ExposureTime") of 30000µs and store it as 30000/1000000 the EXIF viewer shows the wrong exposure. Storing as "1/30" returns the correct result. Do all fractions have to be "1/x"?
2.) How can I calculate the fraction fast? The method I am using now (similar to "Dec2Frac" in [1]) is very slow.
Regards,
[1] Calculating EXIF exposure time as a fraction (Delphi)
This is the code I have used in C# for calculating a fraction for EXIF GPS data. The method returns an array of two integers - one being the numerator and one the denominator.
public static int[] GetFraction(Decimal value)
{
int denominator = 1;
int numeratorMultiplier = 1;
Decimal numerator = value * numeratorMultiplier;
int failSafe = 0;
while (Decimal.Remainder(numerator, 1m) != 0m && failSafe < 20 && ((long)numerator * 10) < Int32.MaxValue)
{
denominator *= 10;
numeratorMultiplier *= 10;
numerator = value * numeratorMultiplier;
failSafe++;
}
return new int[] {Decimal.ToInt32(numerator), denominator};
}

Resources