This example first generates a set of random points. Then the space is divided into squares and each square is colored proportional to the log of the minimum of residue for all lines passing through the square. Hovering over a square shows the line with minimum residue for all lines passing through the square.
Last active
August 29, 2015 14:14
-
-
Save NPashaP/ee144af18f0e307d6549 to your computer and use it in GitHub Desktop.
Linear Model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
circle{ | |
fill:#DE3D71; | |
} | |
rect{ | |
stroke:none; | |
} | |
line{ | |
stroke:#29342E; | |
stroke-width:3px; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var margin = {top: 0, right: 0, bottom: 0, left: 0}, | |
width = 960 - margin.left - margin.right, | |
height = 580 - margin.top - margin.bottom, | |
sqsz = 6 // square size in pxl | |
,rad = 3 // radius of dots | |
; | |
function getRandomPoints(){ // generate array of random points | |
var ret =[] | |
,n = 80 // number of points to generate | |
,m = -0.3 // slope of line for sampling | |
,b = 65 // intercept of line for sampling | |
,c = 0 // counter for points generated so far. | |
,w = 5 // perturbation scale | |
,xmax = width/sqsz -1 | |
,ymax = height/sqsz | |
; | |
do { | |
var x=Math.round(Math.random()*xmax), y=Math.round(m*x+b +(2*Math.random()-1)*w); | |
if( y>0 && y<ymax ){ | |
ret.push({x:x, y:y}); | |
} | |
c+=1; | |
}while(c<n); | |
return ret; | |
} | |
function res(x0, y0){ | |
var sx=d3.sum(points.map(function(d){ return (d.x-x0)*(d.x-x0) })) | |
,sy=d3.sum(points.map(function(d){ return (d.y-y0)*(d.x-x0) })) | |
,m = sy/sx | |
; | |
return { | |
m:m | |
,res:Math.log(d3.sum(points.map(function(d){ var r = d.y-y0 - m*(d.x - x0); return r*r; }))) | |
}; | |
} | |
var sq = []; | |
var points = getRandomPoints(); | |
for(var j=0; j< height/sqsz; j++){ | |
for(var i=0; i< width/sqsz; i++){ | |
sq.push({x:i, y:j, s:res(i, j)}); | |
} | |
} | |
function moveline(d){ | |
//console.log(d); | |
svg.select("line").attr("x1",0).attr("y1",d.y*sqsz+d.s.m*(0-d.x*sqsz)) | |
.attr("x2",width).attr("y2",d.y*sqsz+d.s.m*(width-d.x*sqsz)); | |
} | |
var max=d3.max(sq.map(function(s){ return s.s.res;})) | |
,min=d3.min(sq.map(function(s){ return s.s.res;})) | |
; | |
var color = d3.scale.linear().domain([min, max]).range(["#FFF","#4682b4"]); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom); | |
svg.selectAll("rect") | |
.data(sq) | |
.enter().append("rect") | |
.attr("x",function(d){return d.x*sqsz}).attr("y",function(d){return d.y*sqsz}) | |
.attr("width",sqsz).attr("height",sqsz) | |
.attr("res",function(d){ return d.s.res}) | |
.attr("m",function(d){ return d.s.m}) | |
.style("fill",function(d){ return color((d.s.res))}) | |
.on("mouseover",function(d){ return moveline(d);}); | |
svg.append("line").attr("x1",0).attr("y1",0).attr("x2",0).attr("y2",0); | |
svg.selectAll("circle") | |
.data(points) | |
.enter().append("circle") | |
.attr("cx",function(d){return (d.x+.5)*sqsz}).attr("cy",function(d){return (d.y+.5)*sqsz}) | |
.attr("r",rad); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment