Skip to content

Instantly share code, notes, and snippets.

@dannyko
Last active August 29, 2015 14:07
Show Gist options
  • Select an option

  • Save dannyko/ed7e970977ff1cb7d098 to your computer and use it in GitHub Desktop.

Select an option

Save dannyko/ed7e970977ff1cb7d098 to your computer and use it in GitHub Desktop.

Revisions

  1. dannyko revised this gist Oct 21, 2014. 1 changed file with 14 additions and 2 deletions.
    16 changes: 14 additions & 2 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -351,7 +351,13 @@ var scrolling = false ;
    var scroll = function() {
    if(scrolling) return ;
    scrolling = true ;
    var delta = d3.event.wheelDelta / Math.abs(d3.event.wheelDelta) ;
    console.log(d3.event)
    if(d3.event.wheelDelta !== undefined) {
    var delta = d3.event.wheelDelta / Math.abs(d3.event.wheelDelta) ;
    }
    if(d3.event.detail !== undefined) {
    var delta = -d3.event.detail / Math.abs(d3.event.detail) ;
    }
    var step = .2 ;
    if(delta < 0) {
    step = 1 + step ;
    @@ -369,4 +375,10 @@ var scroll = function() {
    scrolling = false ;
    } ;

    canvas.on("mousewheel", scroll) // default scroll wheel listener
    canvas
    .on("mousewheel.zoom", null)
    .on("DOMMouseScroll.zoom", null) // disables older versions of Firefox
    .on("wheel.zoom", null) // disables newer versions of Firefox

    canvas.on("mousewheel", scroll) // default scroll wheel listener
    canvas.on("DOMMouseScroll.zoom", scroll) ;
  2. dannyko revised this gist Oct 21, 2014. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -2,23 +2,23 @@

    This is an example of interactive or "visual" optimization.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Sliding the slider above the heatmap adjusts the color scale.
    Sliding the slider above the heatmap adjusts the color-map scale for the heatmap display, relative to the current best computed value.

    The sliders on the right control which pair of coordinates is plotted using the heatmap.

    Click on the heatmap to update the current position along the 2 coordinates shown in the heat map.

    Use the scroll-wheel while hovering over the heatmap to zoom in and out.

    Dark green color shows the lowest known function value.

    Click on the heatmap to update the current position along the 2 coordinates shown in the heat map.
    Clicking on dark green points until all pairs directions are in low-energy regions moves towards lower function values.

    Iteratively scanning through the pairs of dimensions and zooming in/out to find new low-energy positions optimizes the objective function.
    The colormap continually updates to show dark green as the current lowest known value.

    Clicking on dark green points until all pairs directions are in low-energy regions moves towards lower function values.
    Scanning through all dimension-pairs before making a move updates the color scale according to the current lowest known value.

    The colormap continually updates to show dark green as the current best known energy.
    Iteratevly Zooming in and shifting the colormap scale slider to the left refines optimal positions.

    For this example, a four-particle [Lennard-Jones cluster problem](http://pubs.acs.org/doi/abs/10.1021/jp970984n) was used, with a known global minimum function value of -6.0 as shown in the thumbnail:

  3. dannyko revised this gist Oct 21, 2014. 2 changed files with 21 additions and 3 deletions.
    24 changes: 21 additions & 3 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,7 @@ var fscaleSlider = d3.select("#fscaleSlider")
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ; // , rmin, rmin, rmin
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    @@ -297,7 +297,7 @@ var update_text = function() {
    }

    var update_ttext = function() {
    d3.select('#temperatureText').text('f(x) = ' + objective_function(r0).toPrecision(4)) ;
    d3.select('#temperatureText').text('f(x) = ' + objective_function(r0).toPrecision(6)) ;
    }

    var update_xtext = function() {
    @@ -324,7 +324,25 @@ canvas.on('click', function() {
    xy[1] *= height ;
    xy[0] = Math.floor(xy[0]) ;
    xy[1] = Math.floor(xy[1]) ;
    update_position(xval[xy[0]][xy[1]], yval[xy[0]][xy[1]], xI, yI) ;
    console.log(xy)
    Npix = 3 ; // for local search to "snap" to the minimum pixel close to where the user clicked
    var minf = f[xy[1]][xy[0]] ;
    var mini = xy[1] ;
    var minj = xy[0] ;
    var iStart = Math.max(0, xy[0] - Npix) ;
    var iEnd = Math.min(width - 1, xy[0] + Npix) ;
    var jStart = Math.max(0, xy[1] - Npix) ;
    var jEnd = Math.min(height - 1, xy[1] + Npix) ;
    for (var i = iStart ; i <= iEnd ; i++) {
    for (var j = jStart ; j <= jEnd ; j++) {
    if(f[i][j] < minf) {
    minf = f[i][j] ;
    mini = i ;
    minj = j ;
    }
    }
    }
    update_position(xval[mini][minj], yval[mini][minj], xI, yI) ;
    }
    ) ;

    Binary file modified thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  4. dannyko revised this gist Oct 21, 2014. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion iopt.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    var copyPosition = function() {
    copyToClipboard(r0.toString());
    }

    var copyToClipboard = function(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
    } ;
    @@ -47,7 +51,7 @@ var td = d3.select('#svg_td') ;
    var copyButton = td.append('input')
    .attr('type', 'button')
    .attr('value', 'current position')
    .attr('onClick', 'copyToClipboard("' + r0.toString() + '"); return false;') ;
    .attr('onClick', 'copyPosition() ; return false ;') ;

    td.append('br')

  5. dannyko revised this gist Oct 21, 2014. 1 changed file with 14 additions and 7 deletions.
    21 changes: 14 additions & 7 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -2,20 +2,27 @@

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.
    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.
    Sliding the slider above the heatmap adjusts the color scale.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.
    The sliders on the right control which pair of coordinates is plotted using the heatmap.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.
    Use the scroll-wheel while hovering over the heatmap to zoom in and out.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.
    Dark green color shows the lowest known function value.

    Sliding the slider above the heatmap adjusts the color scale.
    Click on the heatmap to update the current position along the 2 coordinates shown in the heat map.

    Iteratively scanning through the pairs of dimensions and zooming in/out to find new low-energy positions optimizes the objective function.

    Clicking on dark green points until all pairs directions are in low-energy regions moves towards lower function values.

    The colormap continually updates to show dark green as the current best known energy.

    For this example, a four-particle [Lennard-Jones cluster problem](http://pubs.acs.org/doi/abs/10.1021/jp970984n) was used, with a known global minimum function value of -6.0 as shown in the thumbnail:

    [thumbnail](https://gist.github.com/dannyko/ed7e970977ff1cb7d098/raw/3924843f7080e07294394e5a0346745adb1d6a93/thumbnail.png)

    In principle, almost any objective function could be used, even one whose global minimum is not known.
    In principle, almost any objective function could be used, even one whose global minimum is not known.

  6. dannyko revised this gist Oct 21, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -14,8 +14,8 @@ Clicking on the heatmap image moves the current position vector along the 2 coor

    Sliding the slider above the heatmap adjusts the color scale.

    For this example, a four-particle Lennard-Jones cluster problem was used, with a known global minimum function value of -6.0 as shown in the thumbnail:
    For this example, a four-particle [Lennard-Jones cluster problem](http://pubs.acs.org/doi/abs/10.1021/jp970984n) was used, with a known global minimum function value of -6.0 as shown in the thumbnail:

    ![globally optimal solution](https://gist.github.com/dannyko/ed7e970977ff1cb7d098/raw/3924843f7080e07294394e5a0346745adb1d6a93/thumbnail.png)
    [thumbnail](https://gist.github.com/dannyko/ed7e970977ff1cb7d098/raw/3924843f7080e07294394e5a0346745adb1d6a93/thumbnail.png)

    In principle, almost any objective function could be used, even one whose global minimum is not known.
  7. dannyko revised this gist Oct 21, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion Readme.md
    Original file line number Diff line number Diff line change
    @@ -14,6 +14,8 @@ Clicking on the heatmap image moves the current position vector along the 2 coor

    Sliding the slider above the heatmap adjusts the color scale.

    For this example, a four-particle Lennard-Jones cluster problem was used, with a known global minimum function value of -6.0 as shown in the thumbnail.
    For this example, a four-particle Lennard-Jones cluster problem was used, with a known global minimum function value of -6.0 as shown in the thumbnail:

    ![globally optimal solution](https://gist.github.com/dannyko/ed7e970977ff1cb7d098/raw/3924843f7080e07294394e5a0346745adb1d6a93/thumbnail.png)

    In principle, almost any objective function could be used, even one whose global minimum is not known.
  8. dannyko revised this gist Oct 21, 2014. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion Readme.md
    Original file line number Diff line number Diff line change
    @@ -12,4 +12,8 @@ Clicking a circle on the right displays the projection of the objective function

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Sliding the slider above the heatmap adjusts the color scale.
    Sliding the slider above the heatmap adjusts the color scale.

    For this example, a four-particle Lennard-Jones cluster problem was used, with a known global minimum function value of -6.0 as shown in the thumbnail.

    In principle, almost any objective function could be used, even one whose global minimum is not known.
  9. dannyko revised this gist Oct 21, 2014. 3 changed files with 107 additions and 108 deletions.
    28 changes: 14 additions & 14 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,15 @@
    *Visual Optimization*

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    *Visual Optimization*

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Sliding the slider above the heatmap adjusts the color scale.
    184 changes: 92 additions & 92 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,93 +1,93 @@
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="10" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="10" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    </html>
    3 changes: 1 addition & 2 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -347,5 +347,4 @@ var scroll = function() {
    scrolling = false ;
    } ;

    canvas.on("mousewheel", scroll) // default scroll wheel listener

    canvas.on("mousewheel", scroll) // default scroll wheel listener
  10. dannyko revised this gist Oct 21, 2014. 2 changed files with 30 additions and 19 deletions.
    49 changes: 30 additions & 19 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    var copyToClipboard = function(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
    } ;

    var fscale = 3 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    @@ -9,6 +13,19 @@ var fscaleSlider = d3.select("#fscaleSlider")
    redraw() ;
    }) ;

    /// *******************
    ///
    /// initialize position:
    ///
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var canvas = d3.select('#canvas_1') ;
    var size = 127 ;

    @@ -27,18 +44,12 @@ var height = element.height ;
    var body = d3.select(document.body) ;
    var td = d3.select('#svg_td') ;

    /// *******************
    ///
    /// initialize position:
    ///
    /// *******************
    var copyButton = td.append('input')
    .attr('type', 'button')
    .attr('value', 'current position')
    .attr('onClick', 'copyToClipboard("' + r0.toString() + '"); return false;') ;

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom
    td.append('br')

    var dimSelect = [] ;
    var Ndsel = 2 ;
    @@ -56,15 +67,15 @@ var Ndsel = 2 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    dselOut1.html('i = ' + (xI + 1)) ;
    dselOut2.html('j = ' + (yI + 1)) ;
    update_figure(true) ;
    }) ;

    var dselOut1 = td.append('output')
    .attr('id', 'dimSelect1out')
    .attr('for', 'dimSelect1')
    .html(xI + 1) ;
    .html('i = ' + (xI + 1)) ;

    td.append('br') ;

    @@ -81,15 +92,15 @@ var Ndsel = 2 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    dselOut1.html('i = ' + (xI + 1)) ;
    dselOut2.html('j = ' + (yI + 1)) ;
    update_figure(true) ;
    }) ;

    var dselOut2 = td.append('output')
    .attr('id', 'dimSelect2out')
    .attr('for', 'dimSelect2')
    .html(yI + 1) ;
    .html('j = ' + (yI + 1)) ;

    function setPixel(imageData, x, y, r, g, b, a) {
    var index = (x + y * imageData.width) * 4 ;
    @@ -122,7 +133,7 @@ set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 55, 111)", "rgb(0, 88, 155)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;
    var zrange = ["rgb(0, 88, 11)", "rgb(0, 255, 33)", "rgb(0, 3, 33)", "rgb(0, 11, 55)", "rgb(0, 88, 155)", "rgb(0, 88, 155)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    @@ -212,7 +223,7 @@ function update_image() {
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain = [fmin, fmin + .01 * fscale, fmin + .1 * fscale, fmin + 0.2 * fscale, fmin + 0.4 * fscale, fmin + .8 * fscale, fmin + 1.6 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    Binary file modified thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  11. dannyko revised this gist Oct 21, 2014. 3 changed files with 446 additions and 446 deletions.
    28 changes: 14 additions & 14 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,15 @@
    *Visual Optimization*

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    *Visual Optimization*

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Sliding the slider above the heatmap adjusts the color scale.
    184 changes: 92 additions & 92 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,93 +1,93 @@
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="10" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="10" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    </html>
    680 changes: 340 additions & 340 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -1,340 +1,340 @@
    var fscale = 3 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    .attr('value', fscale)
    .on("input", function() {
    fscale = +this.value;
    set_zscale() ;
    z_range() ;
    redraw() ;
    }) ;

    var canvas = d3.select('#canvas_1') ;
    var size = 127 ;

    canvas
    .attr('width', size)
    .attr('height', size)


    var element = document.getElementById("canvas_1") ;
    var c = element.getContext("2d") ;

    // read the width and height of the canvas
    var width = element.width ;
    var height = element.height ;

    var body = d3.select(document.body) ;
    var td = d3.select('#svg_td') ;

    /// *******************
    ///
    /// initialize position:
    ///
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var dimSelect = [] ;
    var Ndsel = 2 ;

    dimSelect1 = td.append('input')
    .attr('id', 'dimSelect1')
    .attr('type', 'range')
    .attr('value', 1)
    .attr('min', 1)
    .attr('max', Ndim - 1)
    .attr('step', 1)
    .on('input', function() {
    if(Number(this.value) >= Number(dimSelect2.node().value)) {
    dimSelect2.node().value = Number(this.value) + 1 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;

    var dselOut1 = td.append('output')
    .attr('id', 'dimSelect1out')
    .attr('for', 'dimSelect1')
    .html(xI + 1) ;

    td.append('br') ;

    dimSelect2 = td.append('input')
    .attr('id', 'dimSelect2')
    .attr('type', 'range')
    .attr('value', 2)
    .attr('min', 2)
    .attr('max', Ndim)
    .attr('step', 1)
    .on('input', function() {
    if(Number(this.value) <= Number(dimSelect1.node().value)) {
    dimSelect1.node().value = Number(this.value) - 1 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;

    var dselOut2 = td.append('output')
    .attr('id', 'dimSelect2out')
    .attr('for', 'dimSelect2')
    .html(yI + 1) ;

    function setPixel(imageData, x, y, r, g, b, a) {
    var 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 ;
    }

    // create a new pixel array
    var imageData = c.createImageData(width, height) ;

    var xRange = [-2.5, 2.5] ;
    var yRange = [-2.5, 2.5] ;

    var xscale ;
    var yscale ;

    var set_scale = function() {
    xscale = d3.scale.linear()
    .domain([0, width])
    .range(xRange) ;

    yscale = d3.scale.linear()
    .domain([0, height])
    .range(yRange) ;
    } ;

    set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 55, 111)", "rgb(0, 88, 155)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    var fmin = Infinity, fmax = -Infinity ;

    var lennard_jones = function(d) { // Lennard-Jones term
    var V = Math.pow(d, -6) ;
    V = V * V - V ;
    return V ;
    }

    var objective_function = function(r) {
    var V = 0 ;
    for(var i = 0 ; i < N - 1 ; i++) {
    for(var j = i + 1 ; j < N ; j++) {
    var d2 = 0 ;
    for(k = 0 ; k < 3 ; k++) {
    var drk = r[i * 3 + k] - r[j * 3 + k] ; // 3 dimensions per particle: (x, y, z)
    d2 += drk * drk ;
    }
    var d = Math.sqrt(d2) ; // the distance between the spheres
    V += lennard_jones(d) ;
    }
    }
    V *= 4 ; // so each perfect contact scores a -1 energy
    return V ;
    }

    var stepSize = 0.00001 ; // for numerical gradient (secant)

    var gradient_function = function(r) {
    var g = [] ;
    for(var i = 0 ; i < r.length ; i++) {
    var r1 = r.slice(0) ;
    r1[i] += stepSize ;
    fp = objective_function(r1) ;
    r1[i] -= 2 * stepSize ;
    fm = objective_function(r1) ;
    g[i] = (fp - fm) / (2 * stepSize) ;
    }
    // console.log('grad', g, r.length)
    return g ;
    } ;

    var xval = [] ;
    var yval = [] ;

    function update_image() {
    var count = 0 ;

    for (var i = 0 ; i < height ; i++) {
    f[i] = [] ;
    xval[i] = [] ;
    yval[i] = [] ;
    for(var j = 0 ; j < width ; j++) {
    var x = xRange[0] + (i / width) * (xRange[1] - xRange[0]) ;
    var y = yRange[0] + (j / width) * (yRange[1] - yRange[0]) ;
    var r = r0.slice(0) ;
    for (k = 0 ; k < r0.length ; k++) {
    if(k == xI) r[xI] = x + r0[xI] ;
    if(k == yI) r[yI] = y + r0[yI] ;
    }
    f[i][j] = objective_function(r) ;
    xval[i][j] = x ;
    yval[i][j] = y ;
    // console.log('x', x, 'y', y, 'r', r, 'f', f[i][j])
    if(f[i][j] < fmin) {
    fmin = f[i][j] ;
    ropt = r.slice(0) ;
    }
    if(f[i][j] > fmax) fmax = f[i][j] ;
    fvec[count] = f[i][j] ;
    count++ ;
    }
    }

    var fmid = 0.5 * (fmin + fmax) ;
    var fsort = fvec.slice(0).sort(d3.ascending)
    var fmed = d3.quantile(fsort, 0.5) ;
    var fran = fmed - fmin ;


    // zdomain = [fmin, d3.quantile(fsort, 1/3), d3.quantile(fsort, 2/3), Infinity] ;
    set_zscale() ;
    //.domain([fmin, d3.quantile(fvec, 0.1), d3.quantile(fvec, 0.45), d3.quantile(fvec, 0.5), d3.quantile(fvec, 0.75), d3.quantile(fvec, 0.95), fmax])
    //.range(["rgb(0, 0, 44)", "rgb(11, 33, 121)", "rgb(22, 88, 121)", "rgb(111, 111, 111)", "rgb(121, 88, 22)", "rgb(111, 11, 0)", "rgb(44, 0, 0)"]);
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    var redraw = function() {
    for (var i = 0 ; i < height ; i++) {
    for(var j = 0 ; j < width ; j++) {
    var r = d3.rgb(zscale(f[i][j])).r ;
    var g = d3.rgb(zscale(f[i][j])).g ;
    var b = d3.rgb(zscale(f[i][j])).b ;
    if(i == Math.ceil(height / 2) && j == Math.ceil(width / 2)) {
    r = 255 ;
    g = 255 ;
    b = 0 ;

    }
    setPixel(imageData, i, j, r, g, b, 255) ; // 255 opaque
    }
    }
    // copy the image data back onto the canvas
    c.putImageData(imageData, 0, 0) ; // at coords 0,0
    }

    var update_figure = function (scaleSwitch) {
    update_image() ;
    if(scaleSwitch) {
    set_scale() ;
    z_range() ;
    }
    redraw() ;
    update_text() ;
    }

    var updating = false ;

    var update_position = function(dx, dy, i, j) {
    if(updating) return ;
    updating = true ;
    var Nstep = 4 ;
    var kstep = 0 ;

    // console.log('upos', 'r0', r0, dx, dy)

    var step = function() {
    if(kstep < Nstep) {
    r0[i] += dx / Nstep ;
    r0[j] += dy / Nstep ;
    update_figure() ;
    kstep++ ;
    var delay = 16 ;
    setTimeout(step, delay) ;
    // console.log('stepping', kstep)
    } else {
    // console.log('done stepping', kstep, 'r0', r0)
    z_range() ;
    redraw() ;
    update_text() ;
    updating = false ;
    }
    }
    step() ;
    }

    var update_text = function() {
    update_xtext() ;
    update_ytext() ;
    update_ttext() ;
    }

    var update_ttext = function() {
    d3.select('#temperatureText').text('f(x) = ' + objective_function(r0).toPrecision(4)) ;
    }

    var update_xtext = function() {
    d3.select('#xlabel').html('x<sub>' + (xI + 1) + '</sub> = ' + r0[xI].toPrecision(8)) ;
    }

    var update_ytext = function() {
    d3.select('#ylabel').html('x<sub>' + (yI + 1) + '</sub> = ' + r0[yI].toPrecision(8)) ;
    }

    var z_range = function() {
    zscale
    .domain(zdomain)
    .range(zrange) ;
    }

    update_position(0, 0, xI, yI) ;

    canvas.on('click', function() {
    var xy = d3.mouse(canvas.node()) ;
    xy[0] /= canvas.node().clientWidth ;
    xy[1] /= canvas.node().clientHeight ;
    xy[0] *= width ;
    xy[1] *= height ;
    xy[0] = Math.floor(xy[0]) ;
    xy[1] = Math.floor(xy[1]) ;
    update_position(xval[xy[0]][xy[1]], yval[xy[0]][xy[1]], xI, yI) ;
    }
    ) ;

    var scrolling = false ;

    var scroll = function() {
    if(scrolling) return ;
    scrolling = true ;
    var delta = d3.event.wheelDelta / Math.abs(d3.event.wheelDelta) ;
    var step = .2 ;
    if(delta < 0) {
    step = 1 + step ;
    } else {
    step = 1 - step ;
    }
    xRange[0] = step * xRange[0] ;
    xRange[1] = step * xRange[1] ;
    yRange[0] = step * yRange[0] ;
    yRange[1] = step * yRange[1] ;
    set_scale()
    update_image() ;
    z_range() ;
    redraw() ;
    scrolling = false ;
    } ;

    canvas.on("mousewheel", scroll) // default scroll wheel listener
    var fscale = 3 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    .attr('value', fscale)
    .on("input", function() {
    fscale = +this.value;
    set_zscale() ;
    z_range() ;
    redraw() ;
    }) ;

    var canvas = d3.select('#canvas_1') ;
    var size = 127 ;

    canvas
    .attr('width', size)
    .attr('height', size)


    var element = document.getElementById("canvas_1") ;
    var c = element.getContext("2d") ;

    // read the width and height of the canvas
    var width = element.width ;
    var height = element.height ;

    var body = d3.select(document.body) ;
    var td = d3.select('#svg_td') ;

    /// *******************
    ///
    /// initialize position:
    ///
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var dimSelect = [] ;
    var Ndsel = 2 ;

    dimSelect1 = td.append('input')
    .attr('id', 'dimSelect1')
    .attr('type', 'range')
    .attr('value', 1)
    .attr('min', 1)
    .attr('max', Ndim - 1)
    .attr('step', 1)
    .on('input', function() {
    if(Number(this.value) >= Number(dimSelect2.node().value)) {
    dimSelect2.node().value = Number(this.value) + 1 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;

    var dselOut1 = td.append('output')
    .attr('id', 'dimSelect1out')
    .attr('for', 'dimSelect1')
    .html(xI + 1) ;

    td.append('br') ;

    dimSelect2 = td.append('input')
    .attr('id', 'dimSelect2')
    .attr('type', 'range')
    .attr('value', 2)
    .attr('min', 2)
    .attr('max', Ndim)
    .attr('step', 1)
    .on('input', function() {
    if(Number(this.value) <= Number(dimSelect1.node().value)) {
    dimSelect1.node().value = Number(this.value) - 1 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;

    var dselOut2 = td.append('output')
    .attr('id', 'dimSelect2out')
    .attr('for', 'dimSelect2')
    .html(yI + 1) ;

    function setPixel(imageData, x, y, r, g, b, a) {
    var 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 ;
    }

    // create a new pixel array
    var imageData = c.createImageData(width, height) ;

    var xRange = [-2.5, 2.5] ;
    var yRange = [-2.5, 2.5] ;

    var xscale ;
    var yscale ;

    var set_scale = function() {
    xscale = d3.scale.linear()
    .domain([0, width])
    .range(xRange) ;

    yscale = d3.scale.linear()
    .domain([0, height])
    .range(yRange) ;
    } ;

    set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 55, 111)", "rgb(0, 88, 155)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    var fmin = Infinity, fmax = -Infinity ;

    var lennard_jones = function(d) { // Lennard-Jones term
    var V = Math.pow(d, -6) ;
    V = V * V - V ;
    return V ;
    }

    var objective_function = function(r) {
    var V = 0 ;
    for(var i = 0 ; i < N - 1 ; i++) {
    for(var j = i + 1 ; j < N ; j++) {
    var d2 = 0 ;
    for(k = 0 ; k < 3 ; k++) {
    var drk = r[i * 3 + k] - r[j * 3 + k] ; // 3 dimensions per particle: (x, y, z)
    d2 += drk * drk ;
    }
    var d = Math.sqrt(d2) ; // the distance between the spheres
    V += lennard_jones(d) ;
    }
    }
    V *= 4 ; // so each perfect contact scores a -1 energy
    return V ;
    }

    var stepSize = 0.00001 ; // for numerical gradient (secant)

    var gradient_function = function(r) {
    var g = [] ;
    for(var i = 0 ; i < r.length ; i++) {
    var r1 = r.slice(0) ;
    r1[i] += stepSize ;
    fp = objective_function(r1) ;
    r1[i] -= 2 * stepSize ;
    fm = objective_function(r1) ;
    g[i] = (fp - fm) / (2 * stepSize) ;
    }
    // console.log('grad', g, r.length)
    return g ;
    } ;

    var xval = [] ;
    var yval = [] ;

    function update_image() {
    var count = 0 ;

    for (var i = 0 ; i < height ; i++) {
    f[i] = [] ;
    xval[i] = [] ;
    yval[i] = [] ;
    for(var j = 0 ; j < width ; j++) {
    var x = xRange[0] + (i / width) * (xRange[1] - xRange[0]) ;
    var y = yRange[0] + (j / width) * (yRange[1] - yRange[0]) ;
    var r = r0.slice(0) ;
    for (k = 0 ; k < r0.length ; k++) {
    if(k == xI) r[xI] = x + r0[xI] ;
    if(k == yI) r[yI] = y + r0[yI] ;
    }
    f[i][j] = objective_function(r) ;
    xval[i][j] = x ;
    yval[i][j] = y ;
    // console.log('x', x, 'y', y, 'r', r, 'f', f[i][j])
    if(f[i][j] < fmin) {
    fmin = f[i][j] ;
    ropt = r.slice(0) ;
    }
    if(f[i][j] > fmax) fmax = f[i][j] ;
    fvec[count] = f[i][j] ;
    count++ ;
    }
    }

    var fmid = 0.5 * (fmin + fmax) ;
    var fsort = fvec.slice(0).sort(d3.ascending)
    var fmed = d3.quantile(fsort, 0.5) ;
    var fran = fmed - fmin ;


    // zdomain = [fmin, d3.quantile(fsort, 1/3), d3.quantile(fsort, 2/3), Infinity] ;
    set_zscale() ;
    //.domain([fmin, d3.quantile(fvec, 0.1), d3.quantile(fvec, 0.45), d3.quantile(fvec, 0.5), d3.quantile(fvec, 0.75), d3.quantile(fvec, 0.95), fmax])
    //.range(["rgb(0, 0, 44)", "rgb(11, 33, 121)", "rgb(22, 88, 121)", "rgb(111, 111, 111)", "rgb(121, 88, 22)", "rgb(111, 11, 0)", "rgb(44, 0, 0)"]);
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    var redraw = function() {
    for (var i = 0 ; i < height ; i++) {
    for(var j = 0 ; j < width ; j++) {
    var r = d3.rgb(zscale(f[i][j])).r ;
    var g = d3.rgb(zscale(f[i][j])).g ;
    var b = d3.rgb(zscale(f[i][j])).b ;
    if(i == Math.ceil(height / 2) && j == Math.ceil(width / 2)) {
    r = 255 ;
    g = 255 ;
    b = 0 ;

    }
    setPixel(imageData, i, j, r, g, b, 255) ; // 255 opaque
    }
    }
    // copy the image data back onto the canvas
    c.putImageData(imageData, 0, 0) ; // at coords 0,0
    }

    var update_figure = function (scaleSwitch) {
    update_image() ;
    if(scaleSwitch) {
    set_scale() ;
    z_range() ;
    }
    redraw() ;
    update_text() ;
    }

    var updating = false ;

    var update_position = function(dx, dy, i, j) {
    if(updating) return ;
    updating = true ;
    var Nstep = 4 ;
    var kstep = 0 ;

    // console.log('upos', 'r0', r0, dx, dy)

    var step = function() {
    if(kstep < Nstep) {
    r0[i] += dx / Nstep ;
    r0[j] += dy / Nstep ;
    update_figure() ;
    kstep++ ;
    var delay = 16 ;
    setTimeout(step, delay) ;
    // console.log('stepping', kstep)
    } else {
    // console.log('done stepping', kstep, 'r0', r0)
    z_range() ;
    redraw() ;
    update_text() ;
    updating = false ;
    }
    }
    step() ;
    }

    var update_text = function() {
    update_xtext() ;
    update_ytext() ;
    update_ttext() ;
    }

    var update_ttext = function() {
    d3.select('#temperatureText').text('f(x) = ' + objective_function(r0).toPrecision(4)) ;
    }

    var update_xtext = function() {
    d3.select('#xlabel').html('x<sub>' + (xI + 1) + '</sub> = ' + r0[xI].toPrecision(8)) ;
    }

    var update_ytext = function() {
    d3.select('#ylabel').html('x<sub>' + (yI + 1) + '</sub> = ' + r0[yI].toPrecision(8)) ;
    }

    var z_range = function() {
    zscale
    .domain(zdomain)
    .range(zrange) ;
    }

    update_position(0, 0, xI, yI) ;

    canvas.on('click', function() {
    var xy = d3.mouse(canvas.node()) ;
    xy[0] /= canvas.node().clientWidth ;
    xy[1] /= canvas.node().clientHeight ;
    xy[0] *= width ;
    xy[1] *= height ;
    xy[0] = Math.floor(xy[0]) ;
    xy[1] = Math.floor(xy[1]) ;
    update_position(xval[xy[0]][xy[1]], yval[xy[0]][xy[1]], xI, yI) ;
    }
    ) ;

    var scrolling = false ;

    var scroll = function() {
    if(scrolling) return ;
    scrolling = true ;
    var delta = d3.event.wheelDelta / Math.abs(d3.event.wheelDelta) ;
    var step = .2 ;
    if(delta < 0) {
    step = 1 + step ;
    } else {
    step = 1 - step ;
    }
    xRange[0] = step * xRange[0] ;
    xRange[1] = step * xRange[1] ;
    yRange[0] = step * yRange[0] ;
    yRange[1] = step * yRange[1] ;
    set_scale()
    update_image() ;
    z_range() ;
    redraw() ;
    scrolling = false ;
    } ;

    canvas.on("mousewheel", scroll) // default scroll wheel listener

  12. dannyko revised this gist Oct 21, 2014. 3 changed files with 53 additions and 166 deletions.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,7 @@
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="2" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    <input min=".1" max="10" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    217 changes: 52 additions & 165 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    var fscale = 0.7 ;
    var fscale = 3 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    .attr('value', fscale)
    @@ -27,70 +27,69 @@ var height = element.height ;
    var body = d3.select(document.body) ;
    var td = d3.select('#svg_td') ;

    //// *******************
    ////
    /// *******************
    ///
    /// initialize position:
    ///
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 2, 2, 2] ;
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 0, 0, rmin] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var dimSelect = [] ;
    var Ndsel = Math.min(5, r0.length) ;

    var radar = [] ;

    for(var i = 0 ; i < Ndsel ; i++) {
    radar[i] = i ; // initialize
    dimSelect[i] = td.append('input')
    .attr('type', 'number')
    .attr('value', i + 1)
    .attr('min', i + 1)
    .attr('max', Ndim - Ndsel + i + 1)
    var Ndsel = 2 ;

    dimSelect1 = td.append('input')
    .attr('id', 'dimSelect1')
    .attr('type', 'range')
    .attr('value', 1)
    .attr('min', 1)
    .attr('max', Ndim - 1)
    .attr('step', 1)
    .on('input', function() {
    for(var k = 0 ; k < Ndsel ; k++) {
    if(k + 1 == this.min) {
    continue
    }
    if(this.value == dimSelect[k].node().value) {
    if(k + 1 > this.min) {
    this.value = Number(dimSelect[k].node().value) - 1 ;
    } else {
    this.value = Number(dimSelect[k].node().value) + 1 ;
    }
    break
    }
    }
    for(var k = 0 ; k < Ndsel ; k++) {
    radar[k] = Number(dimSelect[k].node().value) - 1 ;
    }
    if(radar.indexOf(xI) == -1 || radar.indexOf(yI) == -1) {
    xI = radar[0] ;
    yI = radar[1] ;
    set_zscale() ;
    z_range() ;
    update_figure() ;
    if(Number(this.value) >= Number(dimSelect2.node().value)) {
    dimSelect2.node().value = Number(this.value) + 1 ;
    }
    radar_init() ;
    update_dots() ;
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;
    }

    td.append('br') ;
    var dselOut1 = td.append('output')
    .attr('id', 'dimSelect1out')
    .attr('for', 'dimSelect1')
    .html(xI + 1) ;

    var svg = td.insert('svg')
    .attr("viewBox", '0 0 ' + width + ' ' + height)
    .attr("preserveAspectRatio", "xMinYMin meet") ;
    td.append('br') ;

    svg
    .attr('width', '100%')
    .attr('height', '90%') ;
    dimSelect2 = td.append('input')
    .attr('id', 'dimSelect2')
    .attr('type', 'range')
    .attr('value', 2)
    .attr('min', 2)
    .attr('max', Ndim)
    .attr('step', 1)
    .on('input', function() {
    if(Number(this.value) <= Number(dimSelect1.node().value)) {
    dimSelect1.node().value = Number(this.value) - 1 ;
    }
    xI = Number(dimSelect1.node().value) - 1 ;
    yI = Number(dimSelect2.node().value) - 1 ;
    dselOut1.html(xI) ;
    dselOut2.html(yI) ;
    update_figure(true) ;
    }) ;

    var dselOut2 = td.append('output')
    .attr('id', 'dimSelect2out')
    .attr('for', 'dimSelect2')
    .html(yI + 1) ;

    function setPixel(imageData, x, y, r, g, b, a) {
    var index = (x + y * imageData.width) * 4 ;
    @@ -123,7 +122,7 @@ set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 55, 3), rgb(0, 3, 33)", "rgb(0, 11, 55)", "rgb(0, 55, 111)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 55, 111)", "rgb(0, 88, 155)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    @@ -148,6 +147,7 @@ var objective_function = function(r) {
    V += lennard_jones(d) ;
    }
    }
    V *= 4 ; // so each perfect contact scores a -1 energy
    return V ;
    }

    @@ -212,24 +212,16 @@ function update_image() {
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin - 0.01 * fscale, fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    var ftol = 1e-4 ;

    var redraw = function() {
    for (var i = 0 ; i < height ; i++) {
    for(var j = 0 ; j < width ; j++) {
    if( ( Math.abs(f[i][j] - fmin) / Math.abs(fmin) ) > ftol) {
    var r = d3.rgb(zscale(f[i][j])).r ;
    var g = d3.rgb(zscale(f[i][j])).g ;
    var b = d3.rgb(zscale(f[i][j])).b ;
    } else {
    var r = 0 ;
    var g = 0 ;
    var b = 25 ;
    }
    var r = d3.rgb(zscale(f[i][j])).r ;
    var g = d3.rgb(zscale(f[i][j])).g ;
    var b = d3.rgb(zscale(f[i][j])).b ;
    if(i == Math.ceil(height / 2) && j == Math.ceil(width / 2)) {
    r = 255 ;
    g = 255 ;
    @@ -241,7 +233,6 @@ var redraw = function() {
    }
    // copy the image data back onto the canvas
    c.putImageData(imageData, 0, 0) ; // at coords 0,0
    update_dots() ;
    }

    var update_figure = function (scaleSwitch) {
    @@ -254,110 +245,6 @@ var update_figure = function (scaleSwitch) {
    update_text() ;
    }

    var g = svg.append('g') ;

    var rect = g
    .append('rect')
    .attr('width', size)
    .attr('height', size)
    .attr('fill', '#999')
    .attr('stroke', 'none') ;

    var grad ;
    // (grad) ;

    var gradx = [] ;
    var grady = [] ;
    var kI = [] ;
    var kJ = [] ;
    var count = 0 ;
    for(var i = 0 ; i < Ndim ; i++) {
    for(var j = i + 1 ; j < Ndim ; j++) {
    kI[count] = i ;
    kJ[count] = j ;
    count++ ;
    }
    }

    var gxscale ;
    var gyscale ;

    var gxscale = d3.scale.linear()
    .domain([0, 1])
    .range([0, size]) ;
    var gyscale = d3.scale.linear()
    .domain([0, 1])
    .range([size, 0]) ;


    var update_grad = function() {
    grad = gradient_function(r0) ;
    var count = 0 ;
    var scale = 1 ;
    for(var i = 0 ; i < Ndim ; i++) {
    for(var j = i + 1 ; j < Ndim ; j++) {
    gradx[count] = 1 - Math.exp(-scale * Math.abs(grad[i])) ;
    grady[count] = 1 - Math.exp(-scale * Math.abs(grad[j])) ;
    count++ ;
    }
    }
    var gxmax = d3.max(gradx) ;
    var gymax = d3.max(grady) ;
    }

    var dimvec = [] ;
    for (var i = 0 ; i < r0.length ; i++) {
    dimvec[i] = i ;
    }

    var radius = 3 ;
    var dotColor = d3.scale.category10();

    var circ ;

    var radar_init = function() {

    circ = d3.selectAll('.dot').remove() ;

    var count = 0 ;

    for(var k = kI.length - 1 ; k >= 0 ; k--) {
    if(radar.indexOf(kI[k]) == -1 || radar.indexOf(kJ[k]) == -1) {
    continue
    }
    // console.log(dotColor(k))
    var circk = g.append('circle')
    .datum({i: kI[k], j: kJ[k], k: k})
    .attr('r', radius)
    .attr('fill', dotColor(count))
    .attr('stroke', 'black')
    .attr('class', 'dot')
    .on('click', function(d) {
    xI = d.i ;
    yI = d.j ;
    circ.attr('data-selected', 'false')
    d3.select(this).attr('data-selected', 'true') ;
    update_figure(true) ;
    }) ;
    if(xI == kI[k] && yI == kJ[k]) {
    circk.attr('data-selected', 'true') ;
    }
    count++ ;
    }

    circ = d3.selectAll('.dot') ;

    }

    radar_init() ;

    var update_dots = function() {
    update_grad() ;
    circ
    .attr('cx', function(d) { return gxscale(gradx[d.k]) })
    .attr('cy', function(d) { return gyscale(grady[d.k]) }) ;
    }

    var updating = false ;

    var update_position = function(dx, dy, i, j) {
    Binary file modified thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  13. dannyko revised this gist Oct 21, 2014. 1 changed file with 14 additions and 14 deletions.
    28 changes: 14 additions & 14 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    var fscale = 0.5 ;
    var fscale = 0.7 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    .attr('value', fscale)
    @@ -34,14 +34,14 @@ var td = d3.select('#svg_td') ;
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0] ;
    var N = 3 ; // number of L-J particles
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0, 2, 2, 2] ;
    var N = r0.length / 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var dimSelect = [] ;
    var Ndsel = 5 ;
    var Ndsel = Math.min(5, r0.length) ;

    var radar = [] ;

    @@ -123,7 +123,7 @@ set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 11, 55)", "rgb(0, 55, 111)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;
    var zrange = ["rgb(0, 55, 3), rgb(0, 3, 33)", "rgb(0, 11, 55)", "rgb(0, 55, 111)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    @@ -137,11 +137,11 @@ var lennard_jones = function(d) { // Lennard-Jones term

    var objective_function = function(r) {
    var V = 0 ;
    for(var i = 0 ; i < N ; i++) {
    for(var i = 0 ; i < N - 1 ; i++) {
    for(var j = i + 1 ; j < N ; j++) {
    var d2 = 0 ;
    for(k = 0 ; k < 3 ; k++) {
    var drk = r[i * N + k] - r[j * N + k] ;
    var drk = r[i * 3 + k] - r[j * 3 + k] ; // 3 dimensions per particle: (x, y, z)
    d2 += drk * drk ;
    }
    var d = Math.sqrt(d2) ; // the distance between the spheres
    @@ -212,7 +212,7 @@ function update_image() {
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain = [fmin - 0.01 * fscale, fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    @@ -231,7 +231,7 @@ var redraw = function() {
    var b = 25 ;
    }
    if(i == Math.ceil(height / 2) && j == Math.ceil(width / 2)) {
    r = 0 ;
    r = 255 ;
    g = 255 ;
    b = 0 ;

    @@ -246,7 +246,7 @@ var redraw = function() {

    var update_figure = function (scaleSwitch) {
    update_image() ;
    if(scaleSwitch === true) {
    if(scaleSwitch) {
    set_scale() ;
    z_range() ;
    }
    @@ -310,7 +310,7 @@ for (var i = 0 ; i < r0.length ; i++) {
    dimvec[i] = i ;
    }

    var radius = 6 ;
    var radius = 3 ;
    var dotColor = d3.scale.category10();

    var circ ;
    @@ -328,7 +328,7 @@ var radar_init = function() {
    // console.log(dotColor(k))
    var circk = g.append('circle')
    .datum({i: kI[k], j: kJ[k], k: k})
    .attr('r', ((Ndsel * (Ndsel - 1)) * 0.5 - count) * radius + radius)
    .attr('r', radius)
    .attr('fill', dotColor(count))
    .attr('stroke', 'black')
    .attr('class', 'dot')
    @@ -399,11 +399,11 @@ var update_ttext = function() {
    }

    var update_xtext = function() {
    d3.select('#xlabel').html('x<sub>' + (xI + 1).toPrecision(1) + '</sub> = ' + r0[xI].toPrecision(8)) ;
    d3.select('#xlabel').html('x<sub>' + (xI + 1) + '</sub> = ' + r0[xI].toPrecision(8)) ;
    }

    var update_ytext = function() {
    d3.select('#ylabel').html('x<sub>' + (yI + 1).toPrecision(1) + '</sub> = ' + r0[yI].toPrecision(8)) ;
    d3.select('#ylabel').html('x<sub>' + (yI + 1) + '</sub> = ' + r0[yI].toPrecision(8)) ;
    }

    var z_range = function() {
  14. dannyko revised this gist Oct 20, 2014. 4 changed files with 560 additions and 92 deletions.
    15 changes: 15 additions & 0 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    *Visual Optimization*

    This is an example of interactive or "visual" optimization.

    The number inputs on the right choose which dimensions/coordinate indices are represented by the circles below.

    Each colored circle on the right represents a pair of the 5 dimensions or coordinates listed in the numeric inputs above.

    The (x, y)-values of the circle's center are correlated with the magnitude of the slope or gradient along that direction.

    Clicking a circle on the right displays the projection of the objective function onto the corresponding two dimensions as a heatmap on the left.

    Clicking on the heatmap image moves the current position vector along the 2 coordinates selected.

    Sliding the slider above the heatmap adjusts the color scale.
    184 changes: 92 additions & 92 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -1,93 +1,93 @@
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="2" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="2" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    </html>
    453 changes: 453 additions & 0 deletions iopt.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,453 @@
    var fscale = 0.5 ;

    var fscaleSlider = d3.select("#fscaleSlider")
    .attr('value', fscale)
    .on("input", function() {
    fscale = +this.value;
    set_zscale() ;
    z_range() ;
    redraw() ;
    }) ;

    var canvas = d3.select('#canvas_1') ;
    var size = 127 ;

    canvas
    .attr('width', size)
    .attr('height', size)


    var element = document.getElementById("canvas_1") ;
    var c = element.getContext("2d") ;

    // read the width and height of the canvas
    var width = element.width ;
    var height = element.height ;

    var body = d3.select(document.body) ;
    var td = d3.select('#svg_td') ;

    //// *******************
    ////
    /// initialize position:
    ///
    /// *******************

    var rmin = Math.pow(2, 1/6) ; // the minimizer of the lennard-jones potential
    var r0 = [0, 0, 0, rmin, 0, 0, 0, rmin, 0] ;
    var N = 3 ; // number of L-J particles
    var xI = 0 ;
    var yI = 1 ;
    var Ndim = r0.length ; // number of free dimensions / degrees of freedom

    var dimSelect = [] ;
    var Ndsel = 5 ;

    var radar = [] ;

    for(var i = 0 ; i < Ndsel ; i++) {
    radar[i] = i ; // initialize
    dimSelect[i] = td.append('input')
    .attr('type', 'number')
    .attr('value', i + 1)
    .attr('min', i + 1)
    .attr('max', Ndim - Ndsel + i + 1)
    .attr('step', 1)
    .on('input', function() {
    for(var k = 0 ; k < Ndsel ; k++) {
    if(k + 1 == this.min) {
    continue
    }
    if(this.value == dimSelect[k].node().value) {
    if(k + 1 > this.min) {
    this.value = Number(dimSelect[k].node().value) - 1 ;
    } else {
    this.value = Number(dimSelect[k].node().value) + 1 ;
    }
    break
    }
    }
    for(var k = 0 ; k < Ndsel ; k++) {
    radar[k] = Number(dimSelect[k].node().value) - 1 ;
    }
    if(radar.indexOf(xI) == -1 || radar.indexOf(yI) == -1) {
    xI = radar[0] ;
    yI = radar[1] ;
    set_zscale() ;
    z_range() ;
    update_figure() ;
    }
    radar_init() ;
    update_dots() ;
    }) ;
    }

    td.append('br') ;

    var svg = td.insert('svg')
    .attr("viewBox", '0 0 ' + width + ' ' + height)
    .attr("preserveAspectRatio", "xMinYMin meet") ;

    svg
    .attr('width', '100%')
    .attr('height', '90%') ;

    function setPixel(imageData, x, y, r, g, b, a) {
    var 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 ;
    }

    // create a new pixel array
    var imageData = c.createImageData(width, height) ;

    var xRange = [-2.5, 2.5] ;
    var yRange = [-2.5, 2.5] ;

    var xscale ;
    var yscale ;

    var set_scale = function() {
    xscale = d3.scale.linear()
    .domain([0, width])
    .range(xRange) ;

    yscale = d3.scale.linear()
    .domain([0, height])
    .range(yRange) ;
    } ;

    set_scale() ;

    var zscale = d3.scale.linear() ;
    var zdomain ;
    var zrange = ["rgb(0, 3, 33)", "rgb(0, 11, 55)", "rgb(0, 55, 111)", "rgb(111, 0, 33)", "rgb(122, 0, 33)", "rgb(155, 0, 88)"] ;

    var f = [] ;
    var fvec = [] ;
    var fmin = Infinity, fmax = -Infinity ;

    var lennard_jones = function(d) { // Lennard-Jones term
    var V = Math.pow(d, -6) ;
    V = V * V - V ;
    return V ;
    }

    var objective_function = function(r) {
    var V = 0 ;
    for(var i = 0 ; i < N ; i++) {
    for(var j = i + 1 ; j < N ; j++) {
    var d2 = 0 ;
    for(k = 0 ; k < 3 ; k++) {
    var drk = r[i * N + k] - r[j * N + k] ;
    d2 += drk * drk ;
    }
    var d = Math.sqrt(d2) ; // the distance between the spheres
    V += lennard_jones(d) ;
    }
    }
    return V ;
    }

    var stepSize = 0.00001 ; // for numerical gradient (secant)

    var gradient_function = function(r) {
    var g = [] ;
    for(var i = 0 ; i < r.length ; i++) {
    var r1 = r.slice(0) ;
    r1[i] += stepSize ;
    fp = objective_function(r1) ;
    r1[i] -= 2 * stepSize ;
    fm = objective_function(r1) ;
    g[i] = (fp - fm) / (2 * stepSize) ;
    }
    // console.log('grad', g, r.length)
    return g ;
    } ;

    var xval = [] ;
    var yval = [] ;

    function update_image() {
    var count = 0 ;

    for (var i = 0 ; i < height ; i++) {
    f[i] = [] ;
    xval[i] = [] ;
    yval[i] = [] ;
    for(var j = 0 ; j < width ; j++) {
    var x = xRange[0] + (i / width) * (xRange[1] - xRange[0]) ;
    var y = yRange[0] + (j / width) * (yRange[1] - yRange[0]) ;
    var r = r0.slice(0) ;
    for (k = 0 ; k < r0.length ; k++) {
    if(k == xI) r[xI] = x + r0[xI] ;
    if(k == yI) r[yI] = y + r0[yI] ;
    }
    f[i][j] = objective_function(r) ;
    xval[i][j] = x ;
    yval[i][j] = y ;
    // console.log('x', x, 'y', y, 'r', r, 'f', f[i][j])
    if(f[i][j] < fmin) {
    fmin = f[i][j] ;
    ropt = r.slice(0) ;
    }
    if(f[i][j] > fmax) fmax = f[i][j] ;
    fvec[count] = f[i][j] ;
    count++ ;
    }
    }

    var fmid = 0.5 * (fmin + fmax) ;
    var fsort = fvec.slice(0).sort(d3.ascending)
    var fmed = d3.quantile(fsort, 0.5) ;
    var fran = fmed - fmin ;


    // zdomain = [fmin, d3.quantile(fsort, 1/3), d3.quantile(fsort, 2/3), Infinity] ;
    set_zscale() ;
    //.domain([fmin, d3.quantile(fvec, 0.1), d3.quantile(fvec, 0.45), d3.quantile(fvec, 0.5), d3.quantile(fvec, 0.75), d3.quantile(fvec, 0.95), fmax])
    //.range(["rgb(0, 0, 44)", "rgb(11, 33, 121)", "rgb(22, 88, 121)", "rgb(111, 111, 111)", "rgb(121, 88, 22)", "rgb(111, 11, 0)", "rgb(44, 0, 0)"]);
    } ; // end update_image

    var set_zscale = function() {
    zdomain = [fmin, fmin + 0.01 * fscale, fmin + .5 * fscale, fmin + 1.5 * fscale, fmax * 0.1 * fscale, Infinity] ;
    zdomain.sort(d3.ascending) ;
    }

    var ftol = 1e-4 ;

    var redraw = function() {
    for (var i = 0 ; i < height ; i++) {
    for(var j = 0 ; j < width ; j++) {
    if( ( Math.abs(f[i][j] - fmin) / Math.abs(fmin) ) > ftol) {
    var r = d3.rgb(zscale(f[i][j])).r ;
    var g = d3.rgb(zscale(f[i][j])).g ;
    var b = d3.rgb(zscale(f[i][j])).b ;
    } else {
    var r = 0 ;
    var g = 0 ;
    var b = 25 ;
    }
    if(i == Math.ceil(height / 2) && j == Math.ceil(width / 2)) {
    r = 0 ;
    g = 255 ;
    b = 0 ;

    }
    setPixel(imageData, i, j, r, g, b, 255) ; // 255 opaque
    }
    }
    // copy the image data back onto the canvas
    c.putImageData(imageData, 0, 0) ; // at coords 0,0
    update_dots() ;
    }

    var update_figure = function (scaleSwitch) {
    update_image() ;
    if(scaleSwitch === true) {
    set_scale() ;
    z_range() ;
    }
    redraw() ;
    update_text() ;
    }

    var g = svg.append('g') ;

    var rect = g
    .append('rect')
    .attr('width', size)
    .attr('height', size)
    .attr('fill', '#999')
    .attr('stroke', 'none') ;

    var grad ;
    // (grad) ;

    var gradx = [] ;
    var grady = [] ;
    var kI = [] ;
    var kJ = [] ;
    var count = 0 ;
    for(var i = 0 ; i < Ndim ; i++) {
    for(var j = i + 1 ; j < Ndim ; j++) {
    kI[count] = i ;
    kJ[count] = j ;
    count++ ;
    }
    }

    var gxscale ;
    var gyscale ;

    var gxscale = d3.scale.linear()
    .domain([0, 1])
    .range([0, size]) ;
    var gyscale = d3.scale.linear()
    .domain([0, 1])
    .range([size, 0]) ;


    var update_grad = function() {
    grad = gradient_function(r0) ;
    var count = 0 ;
    var scale = 1 ;
    for(var i = 0 ; i < Ndim ; i++) {
    for(var j = i + 1 ; j < Ndim ; j++) {
    gradx[count] = 1 - Math.exp(-scale * Math.abs(grad[i])) ;
    grady[count] = 1 - Math.exp(-scale * Math.abs(grad[j])) ;
    count++ ;
    }
    }
    var gxmax = d3.max(gradx) ;
    var gymax = d3.max(grady) ;
    }

    var dimvec = [] ;
    for (var i = 0 ; i < r0.length ; i++) {
    dimvec[i] = i ;
    }

    var radius = 6 ;
    var dotColor = d3.scale.category10();

    var circ ;

    var radar_init = function() {

    circ = d3.selectAll('.dot').remove() ;

    var count = 0 ;

    for(var k = kI.length - 1 ; k >= 0 ; k--) {
    if(radar.indexOf(kI[k]) == -1 || radar.indexOf(kJ[k]) == -1) {
    continue
    }
    // console.log(dotColor(k))
    var circk = g.append('circle')
    .datum({i: kI[k], j: kJ[k], k: k})
    .attr('r', ((Ndsel * (Ndsel - 1)) * 0.5 - count) * radius + radius)
    .attr('fill', dotColor(count))
    .attr('stroke', 'black')
    .attr('class', 'dot')
    .on('click', function(d) {
    xI = d.i ;
    yI = d.j ;
    circ.attr('data-selected', 'false')
    d3.select(this).attr('data-selected', 'true') ;
    update_figure(true) ;
    }) ;
    if(xI == kI[k] && yI == kJ[k]) {
    circk.attr('data-selected', 'true') ;
    }
    count++ ;
    }

    circ = d3.selectAll('.dot') ;

    }

    radar_init() ;

    var update_dots = function() {
    update_grad() ;
    circ
    .attr('cx', function(d) { return gxscale(gradx[d.k]) })
    .attr('cy', function(d) { return gyscale(grady[d.k]) }) ;
    }

    var updating = false ;

    var update_position = function(dx, dy, i, j) {
    if(updating) return ;
    updating = true ;
    var Nstep = 4 ;
    var kstep = 0 ;

    // console.log('upos', 'r0', r0, dx, dy)

    var step = function() {
    if(kstep < Nstep) {
    r0[i] += dx / Nstep ;
    r0[j] += dy / Nstep ;
    update_figure() ;
    kstep++ ;
    var delay = 16 ;
    setTimeout(step, delay) ;
    // console.log('stepping', kstep)
    } else {
    // console.log('done stepping', kstep, 'r0', r0)
    z_range() ;
    redraw() ;
    update_text() ;
    updating = false ;
    }
    }
    step() ;
    }

    var update_text = function() {
    update_xtext() ;
    update_ytext() ;
    update_ttext() ;
    }

    var update_ttext = function() {
    d3.select('#temperatureText').text('f(x) = ' + objective_function(r0).toPrecision(4)) ;
    }

    var update_xtext = function() {
    d3.select('#xlabel').html('x<sub>' + (xI + 1).toPrecision(1) + '</sub> = ' + r0[xI].toPrecision(8)) ;
    }

    var update_ytext = function() {
    d3.select('#ylabel').html('x<sub>' + (yI + 1).toPrecision(1) + '</sub> = ' + r0[yI].toPrecision(8)) ;
    }

    var z_range = function() {
    zscale
    .domain(zdomain)
    .range(zrange) ;
    }

    update_position(0, 0, xI, yI) ;

    canvas.on('click', function() {
    var xy = d3.mouse(canvas.node()) ;
    xy[0] /= canvas.node().clientWidth ;
    xy[1] /= canvas.node().clientHeight ;
    xy[0] *= width ;
    xy[1] *= height ;
    xy[0] = Math.floor(xy[0]) ;
    xy[1] = Math.floor(xy[1]) ;
    update_position(xval[xy[0]][xy[1]], yval[xy[0]][xy[1]], xI, yI) ;
    }
    ) ;

    var scrolling = false ;

    var scroll = function() {
    if(scrolling) return ;
    scrolling = true ;
    var delta = d3.event.wheelDelta / Math.abs(d3.event.wheelDelta) ;
    var step = .2 ;
    if(delta < 0) {
    step = 1 + step ;
    } else {
    step = 1 - step ;
    }
    xRange[0] = step * xRange[0] ;
    xRange[1] = step * xRange[1] ;
    yRange[0] = step * yRange[0] ;
    yRange[1] = step * yRange[1] ;
    set_scale()
    update_image() ;
    z_range() ;
    redraw() ;
    scrolling = false ;
    } ;

    canvas.on("mousewheel", scroll) // default scroll wheel listener

    Binary file added thumbnail.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  15. dannyko created this gist Oct 20, 2014.
    93 changes: 93 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,93 @@
    <!doctype html>
    <html>
    <head>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
    body {
    font: 18pt courier;
    font-weight: bold;
    }

    table {
    padding: 0;
    border: 0;
    margin: 0;
    margin-left: 60px;
    }

    td {
    /*white-space:nowrap; */
    }

    canvas {
    width: 80vmin;
    height: 80vmin;
    image-rendering: optimizeSpeed;
    image-rendering: -moz-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    }

    [data-selected="true"] {
    fill: #FFF ;
    }

    #ylabel {
    position:absolute;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -webkit-transform-origin: left center;
    -moz-transform-origin: left center;
    -ms-transform-origin: left center;
    -o-transform-origin: left center;
    transform-origin: left center;
    left: 50px;
    top: 65% ;
    </style>
    </head>
    <body>
    <table>
    <tbody>
    <tr>
    <td colspan="2" align="center">
    <span id="temperatureText">
    </span>
    <br/>
    <input min=".1" max="2" step=".01" type="range" id="fscaleSlider" value="1" title="colormap scale" autocomplete="off">
    </td>
    <td id="scanner">
    </td>
    </tr>
    <tr>
    <td>
    <span id="ylabel">
    </span>
    </td>
    <td id="canvas_td">
    <canvas id="canvas_1">
    Please use a modern browser
    </canvas>
    </td>
    <td id="svg_td">
    </td>
    </tr>
    <tr>
    <td>
    </td>
    <td align="center">
    <span id="xlabel">
    </span>
    </td>
    <td>
    </td>
    </tr>
    </tbody>
    </table>

    <script type="text/javascript" src="iopt.js"></script>
    </body>
    </html>