How do I convert probability into z-score - javascript
Javascript>
If you are in the data science industry, you would be bothered if you don't have normal distribution table. I came across the article in Stackoverflow that converts z-score to probability in JavaScript. What I really want to know is the reverse calculation of this function.
/**
* #param {number} z - Number of standard deviations from the mean.
*/
function GetZPercent(z) {
// If z is greater than 6.5 standard deviations from the mean
// the number of significant digits will be outside of a reasonable
// range.
if (z < -6.5)
return 0.0;
if (z > 6.5)
return 1.0;
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while (Math.abs(term) > loopStop) {
term = 0.3989422804 * Math.pow(-1, k) * Math.pow(z, k) / (2 * k + 1) /
Math.pow(2, k) * Math.pow(z, k + 1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return sum;
}
I have a sense of how to convert z-score into the probability. But, I have no idea how to calculate the z-score(Standard deviation) from corresponding probability in javascript. For example, If I put in 0.95 (or 95%), I can expect to get 2.25 standard deviation. Above code gives me 95%, if I enter 2.25.
I found that this code also works. Use critz(p) to convert probability to z-score. For example we can expect 1.65 from critz(0.95) as 95% corresponds to 1.65 standard deviation in z-score.
/* The following JavaScript functions for calculating normal and
chi-square probabilities and critical values were adapted by
John Walker from C implementations
written by Gary Perlman of Wang Institute, Tyngsboro, MA
01879. Both the original C code and this JavaScript edition
are in the public domain. */
/* POZ -- probability of normal z value
Adapted from a polynomial approximation in:
Ibbetson D, Algorithm 209
Collected Algorithms of the CACM 1963 p. 616
Note:
This routine has six digit accuracy, so it is only useful for absolute
z values <= 6. For z values > to 6.0, poz() returns 0.0.
*/
var Z_MAX = 6;
function poz(z) {
var y, x, w;
if (z == 0.0) {
x = 0.0;
} else {
y = 0.5 * Math.abs(z);
if (y > (Z_MAX * 0.5)) {
x = 1.0;
} else if (y < 1.0) {
w = y * y;
x = ((((((((0.000124818987 * w
- 0.001075204047) * w + 0.005198775019) * w
- 0.019198292004) * w + 0.059054035642) * w
- 0.151968751364) * w + 0.319152932694) * w
- 0.531923007300) * w + 0.797884560593) * y * 2.0;
} else {
y -= 2.0;
x = (((((((((((((-0.000045255659 * y
+ 0.000152529290) * y - 0.000019538132) * y
- 0.000676904986) * y + 0.001390604284) * y
- 0.000794620820) * y - 0.002034254874) * y
+ 0.006549791214) * y - 0.010557625006) * y
+ 0.011630447319) * y - 0.009279453341) * y
+ 0.005353579108) * y - 0.002141268741) * y
+ 0.000535310849) * y + 0.999936657524;
}
}
return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5);
}
/* CRITZ -- Compute critical normal z value to
produce given p. We just do a bisection
search for a value within CHI_EPSILON,
relying on the monotonicity of pochisq(). */
function critz(p) {
var Z_EPSILON = 0.000001; /* Accuracy of z approximation */
var minz = -Z_MAX;
var maxz = Z_MAX;
var zval = 0.0;
var pval;
if( p < 0.0 ) p = 0.0;
if( p > 1.0 ) p = 1.0;
while ((maxz - minz) > Z_EPSILON) {
pval = poz(zval);
if (pval > p) {
maxz = zval;
} else {
minz = zval;
}
zval = (maxz + minz) * 0.5;
}
return(zval);
}
Here is a function that does an opposite calculation (probability to z-score). This snippet allows you to input the probability and the the corresponding z-score is displayed:
function percentile_z(p) {
if (p < 0.5) return -percentile_z(1-p);
if (p > 0.92) {
if (p == 1) return Infinity;
let r = Math.sqrt(-Math.log(1-p));
return (((2.3212128*r+4.8501413)*r-2.2979648)*r-2.7871893)/
((1.6370678*r+3.5438892)*r+1);
}
p -= 0.5;
let r = p*p;
return p*(((-25.4410605*r+41.3911977)*r-18.6150006)*r+2.5066282)/
((((3.1308291*r-21.0622410)*r+23.0833674)*r-8.4735109)*r+1);
}
// I/O handling
function calc() {
var p = +document.getElementById("prob").value;
var z = percentile_z(p);
document.getElementById("z").textContent = z.toFixed(4);
}
calc();
input { width: 5em }
Probability (between 0 and 1):
<input type="number" id="prob" step="0.0001" min="0" max="1" value="0.9500" oninput="calc()"><p>
Z Score: <span id="z"></span>
For a probability of 0.95 it returns a z-score of 1.6449. See also this table as reference.
Derived from easycalculation.com
Related
Color quantization using euclidean distance gives jumpy results
I'm working on an art project which converts pixels of live video feed into corporate logos based on the distance (in RGB) between the colors of the two. While this functions, it gives a jittery result. Seem like some points in the color space teeter in a sort of superposition between two "closest" points. I'm attempting a sort of naive clustering solution right now because I believe any proper one will be too slow for live video. I'm wondering if anyone has any good ideas to solve this problem? I'll include my code and an example of the result. Thank you! (imgs array is the logos) current result: https://gifyu.com/image/fk2y function distance(r1, g1, b1, bright1, r2, g2, b2, bright2) { d = ((r2 - r1) * 0.3) ** 2 + ((g2 - g1) * 0.59) ** 2 + ((b2 - b1) * 0.11) ** 2 + ((bright2 - bright1) * 0.75) ** 2; return Math.round(d); } function draw() { if (x > 100 && z == true) { video.loadPixels(); for (var y = 0; y < video.height; y++) { for (var x = 0; x < video.width; x++) { var index = (video.width - x - 1 + y * video.width) * 4; var r = video.pixels[index]; var g = video.pixels[index + 1]; var b = video.pixels[index + 2]; var bright = (r + g + b) / 3; let least = 9999999; for (var i = 0; i < imgs.length; i++) { if ( distance( imgs[i].r, imgs[i].g, imgs[i].b, imgs[i].bright, r, g, b, bright ) < least ) { least = distance( imgs[i].r, imgs[i].g, imgs[i].b, imgs[i].bright, r, g, b, bright ); place = imgs[i].img; } } image(place, round(x * vScale), y * vScale, vScale, vScale); } } } }
How to increase brightness with OpenCV.js?
I found a way to do it, but it's very heavy and makes everything laggy (mainly because I'm re-creating the mat pixel by pixel). for (let x = 0; x < src.cols; x++) { for (let y = 0; y < src.rows; y++) { for (let c = 0; c < 4; c++) { if(c != 3){ if((src.data[y * src.cols * src.channels() + x * src.channels() + c]+lum_val) < 255){ dst.data[y * dst.cols * dst.channels() + x * dst.channels() + c] = (src.data[y * src.cols * src.channels() + x * src.channels() + c]+lum_val); }else{ dst.data[y * dst.cols * dst.channels() + x * dst.channels() + c] = 255; } }else{ dst.data[y * dst.cols * dst.channels() + x * dst.channels() + c] = (src.data[y * src.cols * src.channels() + x * src.channels() + c]); } } } } Is there a function that does the same thing more efficiently ? Or maybe a simpler way which leads to the same result ?
Just follow OpenCV Tutorial: Changing the contrast and brightness of an image! convertScaleAbs(src, dst, alpha, beta) Scales, calculates absolute values, and converts the result to 8-bit. On each element of the input array, the function convertScaleAbs performs three operations sequentially: scaling, taking an absolute value, conversion to an unsigned 8-bit type Parameters: src input array dst output array alpha optional scale factor beta optional delta added to the scaled values
How can I calculate my odds of x happening?
What is the percent change of this code reaching the number 200, 500 and 1000? I created this code for 200 to be 50% but it keeps rolling numbers above 200, someone please help me if you understand :D. var mainMultplier = 100; var numerator = 99; var denominator = 100; for(;;) { var randomInt = random.real(0, 1.0); if ( numerator/denominator > randomInt ) { numerator = numerator + 1; denominator = denominator + 1; mainMultplier = mainMultplier + 1; } else { break; } }
Edit Based on the code you have posted, we can see these two base rules: P(100) = 1 - 0.99 = 0.01 P(101) = (1 - P(100)) * (1 - (100 / 101)) = P(101) = (1 - P(100)) * (1 / 101) The second rule can be generalized for any number X after 100: P(X) = (1 - P(X - 1)) * (1 / X) Now, I did learn how to do proofs by induction at Uni, which I'm sure would help my explanation here, but I can't remember it anymore :(. So instead, I've written some code to generate a lookup table p, from 100 to 1000: var p = []; p[100] = 0.01; for (var x = 101; x <= 1000; x++) p[x] = (1 - p[x - 1]) * (1 / x); Edit 2 And that's as far as my help can go. You may want to post the generalized algorithm on the Software Engineering page.
Why is Firefox 30 times slower than Chrome, when calculating Perlin noise?
I have written a map generator in javascript, using classical perlin noise scripts I have found in various places, to get the functionality I want. I have been working in chrome, and have not experienced any problems with the map. However, when I tested it in firefox, it was incredibly slow - almost hanging my system. It fared better in the nightly build, but still 30 times slower than Chrome. You can find a test page of it here: http://jsfiddle.net/7Gq3s/ Here is the html code: <!DOCTYPE html> <html> <head> <title>PerlinMapTest</title> </head> <body> <canvas id="map" width="100" height="100" style="border: 1px solid red">My Canvas</canvas> <script src="//code.jquery.com/jquery-2.0.0.min.js"></script> <script> $(document).ready(function(){ //Log time in two ways var startTime = new Date().getTime(); console.time("Map generated in: "); var canvas = $("#map")[0]; var ctx = canvas.getContext("2d"); var id = ctx.createImageData(canvas.width, canvas.height); var noiseMap = new PerlinNoise(500); var startx = 0; var starty = 0; var value = 0; for(var i = startx; i < canvas.width; i++){ for(var j = starty; j < canvas.height; j++){ value = noiseMap.noise(i,j, 0, 42); value = linear(value,-1,1,0,255); setPixel(id, i, j, 0,0,0,value); } } ctx.putImageData(id,0,0); var endTime = new Date().getTime(); console.timeEnd("Map generated in: "); alert("Map generated in: " + (endTime - startTime) + "milliseconds"); }); function setPixel(imageData, x, y, r, g, b, a) { index = (x + y * imageData.width) * 4; imageData.data[index+0] = r; imageData.data[index+1] = g; imageData.data[index+2] = b; imageData.data[index+3] = a; } //This is a port of Ken Perlin's "Improved Noise" //http://mrl.nyu.edu/~perlin/noise/ //Originally from http://therandomuniverse.blogspot.com/2007/01/perlin-noise-your-new-best-friend.html //but the site appears to be down, so here is a mirror of it //Converted from php to javascript by Christian Moe //Patched the errors with code from here: http://asserttrue.blogspot.fi/2011/12/perlin-noise-in-javascript_31.html var PerlinNoise = function(seed) { this._default_size = 64; this.seed = seed; //Initialize the permutation array. this.p = new Array(512); this.permutation = [ 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ]; for (var i=0; i < 256 ; i++) { this.p[256+i] = this.p[i] = this.permutation[i]; } }; PerlinNoise.prototype.noise = function(x,y,z,size) { if (size == undefined) { size = this._default_size; } //Set the initial value and initial size var value = 0.0; var initialSize = size; //Add finer and finer hues of smoothed noise together while(size >= 1) { value += this.smoothNoise(x / size, y / size, z / size) * size; size /= 2.0; } //Return the result over the initial size return value / initialSize; }; //This function determines what cube the point passed resides in //and determines its value. PerlinNoise.prototype.smoothNoise = function(x, y, z){ //Offset each coordinate by the seed value x += this.seed; y += this.seed; z += this.seed; var orig_x = x; var orig_y = y; var orig_z = z; var X = Math.floor(x) & 255, // FIND UNIT CUBE THAT Y = Math.floor(y) & 255, // CONTAINS POINT. Z = Math.floor(z) & 255; x -= Math.floor(x); // FIND RELATIVE X,Y,Z y -= Math.floor(y); // OF POINT IN CUBE. z -= Math.floor(z); var u = this.fade(x), // COMPUTE FADE CURVES v = this.fade(y), // FOR EACH OF X,Y,Z. w = this.fade(z); var A = this.p[X ]+Y, AA = this.p[A]+Z, AB = this.p[A+1]+Z, // HASH COORDINATES OF B = this.p[X+1]+Y, BA = this.p[B]+Z, BB = this.p[B+1]+Z; // THE 8 CUBE CORNERS, return this.lerp(w, this.lerp(v, this.lerp(u, this.grad(this.p[AA ], x , y , z ), // AND ADD this.grad(this.p[BA ], x-1, y , z )), // BLENDED this.lerp(u, this.grad(this.p[AB ], x , y-1, z ), // RESULTS this.grad(this.p[BB ], x-1, y-1, z ))),// FROM 8 this.lerp(v, this.lerp(u, this.grad(this.p[AA+1], x , y , z-1 ), // CORNERS this.grad(this.p[BA+1], x-1, y , z-1 )), // OF CUBE this.lerp(u, this.grad(this.p[AB+1], x , y-1, z-1 ), this.grad(this.p[BB+1], x-1, y-1, z-1 )))); }; PerlinNoise.prototype.fade = function(t) { return t * t * t * ( ( t * ( (t * 6) - 15) ) + 10); }; PerlinNoise.prototype.lerp = function(t, a, b) { //Make a weighted interpolaton between points return a + t * (b - a); }; PerlinNoise.prototype.grad = function(hash, x, y, z) { h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE u = h<8 ? x : y; // INTO 12 GRADIENT DIRECTIONS. v = h<4 ? y : (h==12||h==14 ? x : z); return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); }; PerlinNoise.prototype.scale = function(n) { return (1 + n)/2; }; function linear(int, s1, s2, t1, t2) { t = [t1, t2]; s = [s1, s2]; rangeS = s1 - s2; rangeT = t1 - t2; if((s1 < s2 && t1 > t2) || (s1>s2 && t1<t2)) { interpolated = ((int - s1) / rangeS*rangeT) + t1; } else { interpolated = ((int - s1) / rangeS)*rangeT + t1; } if(interpolated > Math.max.apply(Math, t)) { interpolated = Math.max.apply(Math, t); } if(interpolated < Math.min.apply(Math, t)) { interpolated = Math.min.apply(Math, t); } return interpolated; } </script> </body> </html> I get 33 ms on Chrome, and 1051ms on Firefox 24 Nightly The results are inconsistent though. Sometimes the Nightly results is as fast as chrome... Do you know why there is so much variation in this particular instance? I don't know enough about the theory of perlin noise to try optimizing the code, so don't know what to do.
I have found the culprit. The slowdown occurs when I have Firebug enabled. That extension must weigh it down.
I need a function that outputs a hexadecimal value for a given floating point number that belongs to a range
I'm sorry for the bad title (edit if you wish), but I don't know how to put this request. I attached an image from Photoshop that illustrates things a little bit better. The request itself is quite simple: You have a numeric range from 10.0 to 0.0. 10 stands for the color #00ff00 (deep green) and 0.0 for the color #ff0000 (deep red). Now, when you hand over the number 10.0 it will output #00ff00. When you give it something like 8.2 it would output something like #00cc33 so that you have a floating gradient all the way down but always float from #00ff00 over orange #ff9900 to #ff0000 (orange in the middle could also be omitted).
One way is to think of the colours like a segment of a circle and then make use of Math.cos or Math.sin. function toColour(x) { var pad = function (x) { x = x.toString(16); if (x.length === 1) { return '0' + x; } return x; }, r, g, b; r = ~~(255 * Math.cos(Math.PI * x / 20)); // cos(0) = 1, cos(π/2) = 0 g = ~~(255 * Math.sin(Math.PI * x / 20)); // sin(0) = 0, sin(π/2) = 1 b = 0; return '#' + pad(r) + pad(g) + pad(b); } // test the gradient produced for (var i = 0; i <= 10; ++i) { document.body.appendChild( document.createElement('div') ).setAttribute('style', 'width: 400px;height: 5px;background: '+toColour(i)+';'); } See this fiddle for test results (thanks to MikeM)
Just for fun: function toHex( n ) { var r = 255 - ( n / 10 * 255 | 0 ); g = n / 10 * 255 | 0; return '#' + ( r ? ( r = r.toString(16), r.length == 2 ? r : '0' + r ) : '00' ) + ( g ? ( g = g.toString(16), g.length == 2 ? g : '0' + g ) : '00' ) + '00' } See it here (for what its worth): http://jsfiddle.net/xD6Uf/ Update Inspired by Samuel Edwin Ward's use of HSL, the following function adapts hslToRgb from Brian Grinstead's MIT Licensed tinycolor.js: Note: this function is not intended to be the finished article or represent good practice, it is a proof of concept only. There is no bounds checking and few concessions to readability. n is a value from 0 to 10, and start, middle and end are each a hue value from 0 - 360. See Mother-effing hsl to select hue, saturation and lightness values to experiment with. function toHex( n ) { var r, g, b, p, q, start = 0, // 0 - 360 (red 0) middle = 36, // 0 - 360 (orange 36, use 0 or null for no middle) end = 120, // 0 - 360 (green 120) saturation = 1, // 0 - 1 lightness = 0.5, // 0 - 1 hue = ( middle ? n > 5 ? ( n -= 5, n / 5 * ( end - middle ) ) + middle : ( n / 5 * ( middle - start ) ) + start : ( n / 10 * ( end - start ) ) + start ) / 360; function hue2hex( p, q, h ){ if ( h < 0 ) h++; else if ( h > 1 ) h--; h = ( h < 1/6 ? p + ( q - p ) * 6 * h : h < 1/2 ? q : h < 2/3 ? p + ( q - p ) * ( 2/3 - h ) * 6 : p ) * 255 | 0; return h ? ( h = h.toString(16), h.length > 1 ? h : '0' + h ) : '00'; } if ( saturation === 0 ) { n = lightness * 255 | 0; r = g = b = n ? ( n = n.toString(16), n.length > 1 ? n : '0' + n ) : '00'; } else { q = lightness < 0.5 ? lightness * ( 1 + saturation ) : lightness + saturation - lightness * saturation; p = 2 * lightness - q; r = hue2hex( p, q, hue + 1/3 ); g = hue2hex( p, q, hue ); b = hue2hex( p, q, hue - 1/3 ); } return '#' + r + g + b; } Example toHex(0); // "#ff0000" toHex(5); // "#ff9900" toHex(10); // "#00ff00" jsfiddle
It looks like you want to interpolate between colors. You could just take the color values to be numbers and do an interpolation between them, but I think the results would be very odd. You'll probably want to convert your colors from RGB to another color space and scale the hue component(s). HSL would be a nice choice because CSS3 supports specifying colors in that space. I put code for both approaches up on jsfiddle. These are the important parts: /* numeric interpolation */ for (var value = 0; value < 10; value += 10/40) { var color = (10-value)/10*(0xff0000-0xff00)+(0x00ff00), hex = Math.floor(color).toString(16); while (hex.length < 6) { hex = "0" + hex; } /* hex now holds the hex code */ } /* hue interpolation */ for (var value = 0; value < 10; value += 10/40) { var hue = value/10*120, /* red is 0; green is 120 */ color = 'hsl(' + hue + ', 100%, 50%)'; /* hsl now holds the hsl color specification */ } If you like you can use a fancier approach to interpolating the values than the simple linear formula I used (where x is the input scale and y is the output scale): y = (x - minX) / (maxX - minX) * (maxY-minY) + minY
So basically you have some range in hex with two variables: var startHex = "0x00ff00"; var endHex = "0xff0000" int startInt = parseInt(startHex, 16); int endInt = parseInt(endHex, 16); int newInt = startInt + (endInt-startInt)/100 * floatValue; // floatValue is number between 10.0 and 0.0 var newHex = newDec.ToString(16); I am assuming you intended for 100 increments possible between start and end. This could be done much more cleanly, but for illustration I broke it all out. In practice I would write this in 1-2 lines.
If you want to rely on the browser's rendering engine, you could use HTML5's canvas and createLinearGradient. One advantage of this approach is the ability to use color stops (though you could do this mathematically if you really wanted also). var canvas = document.createElement('canvas'), context = canvas.getContext('2d'); canvas.height = 100; canvas.width = 1; var gradient = context.createLinearGradient(0,0,0,100); // color stops gradient.addColorStop(0, '#00ff00'); gradient.addColorStop(0.5, '#ff9900'); gradient.addColorStop(1, '#ff0000'); context.fillStyle = gradient; context.fillRect(0,0,1,100); var point = 10.0, colorData = context.getImageData(0, parseInt(point*canvas.height*.1, 10), 1, 1).data; // rgba ( colorData[0], colorData[1], colorData[2], colorData[3] ) You can find the exact rgba coordinates of the color in colorData[0] (red), colorData[1] (blue), colorData[2] (green) and then easily convert those to hex values. If you end up using this solution, set point to a number in the range of 0 to 9.9.