PDF Functiontype 2 exponential interpolation equation - function

I'm modifying an application that does PDF manipulation. The function written to interpret functiontype 2s seems to produce a negative value far too frequently. The equation found in the PDF spec is:
yj = C0j + x^N × (C1j − C0j), for 0 ≤ j < n.
Now, I'm getting negative values when I process a function with C0=1 and C1=0. I'm wondering if this is because I'm setting my own x value. What is the x value supposed to be?

The function is computed like this:
1. Input value is cut to function domain:
input = input > domainMax ? domainMax : (input < domainMin ? domainMin : input)
2. Compute inputN = input^N
3. Compute each component of the output value (1 component in your situation) using the formula:
output[j] = C0[j] + inputN * (C1[j] − C0[j]), for 0 ≤ j < n.
4. Cut each output component to function range:
output = output > rangeMax ? rangeMax : (output < rangeMin ? rangeMin : output)
Your function is a linear function (indeed can be used to define a gradient) and returns 0 when input is 1 and 1 when input is 0. Input values greater than 1 are invalid and they are cut to 1 before using them in calculation because the domain is [0, 1].
The application that parses spot color percentages might have to divide that percentage by 100 before feeding it to the function.

Related

How to plot a 2d Function in MATLAB

I am trying to plot a simple equation in MATLAB.
The equation is
z = x^2 - y^2, for -3 <= x <= 3, -3 <= y <= 3.
The current code that I have is
x = -3:3;
y = -3:3;
z = (x.^2) - (y.^2);
plot(z)
The result is
Please help me in this case because I am not sure if the code and graph is correct. Thank you very much.
This is not a piecewise function. A Piecewise Function is a function defined by multiple sub-functions, where each sub-function applies to a different interval in the domain. There is only one function here that takes two arrays of the same length. The calculations yield a vector of zeros, due to the input arrays. If you change either one of the vectors, that is "x" or "y", you will see a nonzero plot. Your code works as expected.
There is a lot going wrong here: Let's start at the beginning:
x = -3:3;
y = -3:3;
If we evaluate these they both will return an vector of integers:
x =
-3 -2 -1 0 1 2 3
This means that the grid on which the function is evaluated is going to be very coarse. To alleviate this you can define a step size, e.g. x = 3:0.1:3 or use linspace, in which case you set the number of samples, so e.g. x = linspace(-3, 3, 500). Now consider the next line:
z = (x.^2) - (y.^2);
If we evaluate this we get
z =
0 0 0 0 0 0 0
and you plot this vector with the 2d-plotting function
plot(z)
which perfectly explains why you get a straight line. This is because the automatic broadcasting of the arithmetic operators like minuse (-) just subtracts values entry-wise. You however want to evaluate z for each possible pair of values of x and y. To do this and to get a nice plot later you should use meshgrid, and use a plotting function like mesh to plot it. So I'd recommend using
[X,Y] = meshgrid(x,y);
to create the grid and then evaluate the function on the grid as follows
Z = X.^2 - Y.^2;
and finally plot your function with
mesh(X,Y,Z);

Convert from one range to another

I have two sets of ranges that I need to be translated from one to the other.
The first range is -100 ↔ 100 with 0 being default.
The second range is 0.0 ↔ 10.0 with 1 being default.
I am working in AS3 with the first range and the second range is a python class and I need these numbers to line up.
I am adjusting brightness of a video in realtime with a slider. The video filter accepts values between -100 ↔ 100. I need to then take that value and pass it to a python script but it only accepts values from 0.0 ↔ 10.0
I tried this function I found on the net, but it doesn't translate the values correctly in this particular case.
private function convertRange(originalStart:Number,originalEnd:Number,newStart:Number,newEnd:Number,value:Number):Number
{
var originalRange:Number = originalEnd - originalStart;
var newRange:Number = newEnd - newStart;
var ratio:Number = newRange / originalRange;
var newValue:Number = value * ratio;
var finalValue:Number = newValue + newStart;
return finalValue;
}
Is this even possible? Hopefully my question is clear, please let me know if it needs clarification.
This is the python class I am referring to: https://github.com/dubhater/vapoursynth-adjust It uses the second range whereas AS3 uses the first range.
Why not trying something like this :
function from_AS_to_PY(as_value:Number): Number // as_value : -100 ----- 0 ----- 100
{
var py_value:Number = (as_value / 100);
py_value = (py_value <= 0 ? py_value : py_value * 9) + 1;
return py_value;
}
function from_PY_to_AS(py_value:Number): Number // py_value : 0 - 1 --------- 10
{
var as_value:Number = (py_value <= 1 ? py_value - 1 : ((py_value - 1) / 9)) * 100;
return as_value;
}
trace(from_AS_to_PY(-100)); // gives : 0
trace(from_AS_to_PY(-99)); // gives : 0.01
trace(from_AS_to_PY(-1)); // gives : 0.99
trace(from_AS_to_PY(0)); // gives : 1
trace(from_AS_to_PY(1)); // gives : 1.09
trace(from_AS_to_PY(99)); // gives : 9.91
trace(from_AS_to_PY(100)); // gives : 10
//---------------------------------------------------
trace(from_PY_to_AS(0)); // gives : -100
trace(from_PY_to_AS(0.01)); // gives : -99
trace(from_PY_to_AS(0.99)); // gives : -1
trace(from_PY_to_AS(1)); // gives : 0
trace(from_PY_to_AS(1.09)); // gives : 1
trace(from_PY_to_AS(9.91)); // gives : 99
trace(from_PY_to_AS(10)); // gives : 100
Hope that can help.
There is a fundamental difficulty with the problem. You are trying to fit three point of one range onto another range. If you were just interested in matching the two end points that would be easy you can use a linear interpolation y = 10 * (x+100) /200 or simply y = (x+100)/20 or equivalently y=x/20+5. The problem is it this does not match the default value and x=0 -> 5.
This might be the solution you want. However if it is important that he default values match you need to use a non-linear solution. There are many possible solutions. You can use a piecewise-linear solution like akmozo solution, which needs an if statement. if x<0 then y = x/100+1 else y = 1 + 9 x /100. The problem with this one is that you do not get a smooth response. Consider adjusting the slider from min to max, you see a very slow increase in brightness to start with and then it starts to increase much faster once you pass zero.
The big difference between the first half of the range and the second half suggests an exponential type solution. y = A exp(b x). Taking y = exp(x * ln(10)/100) matches the center point and the top end, the bottom end is just a little bit high at 0.1, rather than zero. This might be fine, if not you could find an exponential solution y = A exp(b x)-c which matches all three points.
Another possibility is using a power. An equation like y = A pow(x,n). A bit of calculation shows y=10 pow(x/200+0.5),3.321928095) matches all three points. The constant 3.321928095 = ln(0.1)/ln(0.5).
In the diagram the black curve is a simple linear solution. The red curve is the piecewise linear one, the green is the exponential one then the blue is the power.

How to generate random numbers from log-normal distribution with a given mean and SD in SAS?

Wenping (Wendy) Zhang points out
that the SAS RAND function "basically gives "standard" distribution".
The author describes an interesting SAS %rndnmb macro to generate data from “non-standard” distributions. Unfortunately the code in unavailable. So, I dared to do it by myself.
If I understand correctly the Wikipedia says that y is from the log-normal distribution if
y = exp^(mu + sigma * Z).
The following formulas connect the mean and variance of the non-logarithmized sample values:
mu = ln((mean^2)/(sqrt(variance + mean^2))
and
sigma = sqrt(ln(1 + (variance)/(mean^2))).
If that correct, my y will be drawn from log-normal distribution when
Z is from standard normal distribution Z with mu' = 0, sigma' = 1.
Finally, is it correct that y is from lognormal distribution with mean and variance if
y = exp^(ln((mean^2)/(sqrt(variance + mean^2)) + sqrt(ln(1 + (variance)/(mean^2))) * Z)
?
My SAS code is:
/*I use StdDev^2 notation instead of variance here. */
DATA nonStLogNorm;
nonStLN = exp(1)**(log((mean**2)/(sqrt(StdDev^2 + mean**2)) +
sqrt(log(1 + (StdDev^2)/(mean**2))) * rand('UNIFORM'));
RUN;
References:
RAND function by Rick Wicklin:
http://blogs.sas.com/content/iml/2013/07/10/stop-using-ranuni/
http://blogs.sas.com/content/iml/2011/08/24/how-to-generate-random-numbers-in-sas/
What you need is the inverse cumulative distribution function. This is the function that is the inverse of the normalized integral of the distribution over the entire domain. So at 0% is your most negative possible value and 100% is your most positive. Practically though you would calmp to something like 0.01% and 99.99% or something like that as otherwise you'll end up at infinite for a lot of distributions.
Then from there you only need to random a number in a range (0,1) and plug that into the function. Remember to clamp it!
double CDF = 0.5 + 0.5*erf((ln(x) - center)/(sqrt(2)*sigma))
so
double x = exp(inverf((CDF - 0.5)*2.0)*sqrt(2)*sigma + center);
should give you the requested distribution. inverf is the inverse of the erf function. It is a common function but not in math.h typically.
Did a SIMD based random number generator that needed to do distributions. This worked fine, the above will work assuming I didn't flub up something while typing.
As requested how to clamp:
//This is how I do it with my Random class where the first argument
//is the min value and the second is the max
double CDF = Random::Range(0.0001,0.9999); //Depends on what you are using to random
//How you get there from Random Ints
unsigned int RandomNumber = rand();
//Conver number to range [0,1]
double CDF = (double)RandomNumber/(double)RAND_MAX;
//now clamp it to a min, max of your choosing
CDF = CDF*(max - min) + min;
If you want Z to be drawn from the standard normal distribution, shouldn't you obtain it by calling RAND('NORMAL') rather than RAND('UNIFORM')?

How to set Nodata value into zero

I have a question. How can I set null value into 0 on an image. Is there any way to do this in matlab. The image type is float-point, 32 bit, tif format. Null value (Nodata) of this image is -3.4028234663e+038. So the number is out of range of float-point. So I wanna replace those values with 0.
Generally speaking, you can find all the elements to replace by:
idx = (I == x); % # x is the "null" value
where I is your image and x is the desired value to replace (in your case, that is the "null" value). However, a more practical syntax would be using a certain threshold value instead of the exact value:
idx = (I > y); % # y is a value much lower than x
Now idx holds the logical indices of the elements you want to zero out. After you obtain idx, just do:
I(idx) = 0;
P.S
In practice, you can do achieve the same result without creating a temporary variable idx, like so:
I(I > y) = 0;

Interpreting jTransform FFT results

Merged with Power Spectral Density from jTransforms DoubleFFT_1D.
I'm using Jtransforms java library to perform analysis on a give dataset.
An example of the data is as follows:
980,988,1160,1080,928,1068,1156,1152,1176,1264
I'm using the DoubleFFT_1D funtion in jTransforms. The data output is as follows:
10952, -152, 80.052, 379.936, -307.691, 12.734, -224.052, 427.607, -48.308, 81.472
I'm having trouble interpreting the output. I understand that the first element in the output array is the total of the 10 inputs (10952). It's the other elements of the output array that i don't understand. Ultimately, I want to plot the Power Spectral Density of the input data on a graph and find amounts between 0 and .5 Hz.
The documentation for the jTransform functions states:
(where a is the data set)
.....................
realForward
public void realForward(double[] a)Computes 1D forward DFT of real data leaving the result in a . The physical layout of the output data is as follows:
if n is even then
a[2*k] = Re[k], 0 <= k < n / 2
a[2*k+1] = Im[k], 0 < k < n / 2
a[1] = Re[n/2]
if n is odd then
a[2*k] = Re[k], 0 <= k < (n+1)/2
a[2*k+1] = Im[k], 0 < k< (n-1)/2
a[1] = Im[(n-1)/2]
This method computes only half of the elements of the real transform. The other half satisfies the symmetry condition. If you want the full real forward transform, use realForwardFull. To get back the original data, use realInverse on the output of this method.
Parameters:
a - data to transform
..................................
So what are the output numbers? What do the values mean?
Any help is appreciated.