Skip to content

Commit

Permalink
Add ExprTK example fractal
Browse files Browse the repository at this point in the history
  • Loading branch information
texodus committed Oct 30, 2021
1 parent dac0443 commit 771dcb1
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 342 deletions.
3 changes: 2 additions & 1 deletion examples/blocks/gists.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"csv": "02d8fd10aef21b19d6165cf92e43e668",
"iex": "eb151fdd9f98bde987538cbc20e003f6",
"citibike": "bc8d7e6f72e09c9dbd7424b4332cacad",
"movies": "6b4dcebf65db4ebe4fe53a6de5ea0b48"
"movies": "6b4dcebf65db4ebe4fe53a6de5ea0b48",
"fractal": "5485f6b630b08d38218822e507f09f21"
}
2 changes: 2 additions & 0 deletions examples/blocks/src/fractal/.block
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
license: apache-2.0
height: 800
3 changes: 3 additions & 0 deletions examples/blocks/src/fractal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Demo of [Perspective](https://github.com/finos/perspective).

A classic [fractal](https://en.wikipedia.org/wiki/Mandelbrot_set) implemented entirely in ExprTK/Perspective.
107 changes: 107 additions & 0 deletions examples/blocks/src/fractal/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
perspective-viewer {
flex: 1;
margin: 24px;
overflow: visible;
--d3fc-positive--gradient: linear-gradient(
#94d0ff,
#8795e8,
#966bff,
#ad8cff,
#c774e8,
#c774a9,
#ff6ad5,
#ff6a8b,
#ff8b8b,
#ffa58b,
#ffde8b,
#cdde8b,
#8bde8b,
#20de8b
);
}

#app {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #f2f4f6;
}

#controls {
display: flex;
margin: 24px 24px 0px 40px;
}

.range {
position: relative;
display: inline-flex;
flex-direction: column;
margin-right: 24px;
}

span,
input,
button {
font-family: "Open Sans";
font-size: 12px;
background: none;
margin: 0px;
border-color: #ccc;
color: #666;
padding: 6px 12px 6px 0px;
}

input {
height: 14px;
border-width: 0px;
border-style: solid;
border-bottom-width: 1px;
color: inherit;
outline: none;
}

input[type="range"] {
margin-top: 2px;
}

input[type="number"] {
font-family: "Roboto Mono";
}

input:focus {
border-color: #1a7da1;
}

input::placeholder {
color: #ccc;
}

button {
border: 1px solid #ccc;
text-transform: uppercase;
text-align: center;
text-decoration: none;
display: inline-block;
padding-left: 12px;
height: 28px;
outline: none;
}

button:hover {
cursor: pointer;
}

#run {
justify-self: center;
margin-right: 24px;
height: 83px;
width: 80px;
}

#run:disabled {
opacity: 0.2;
}
42 changes: 42 additions & 0 deletions examples/blocks/src/fractal/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="https://cdn.jsdelivr.net/npm/webfontloader"></script>
<script>WebFont.load({google:{families:["Roboto Mono:200,400","Material Icons","Open Sans:300,400"]}})</script>
<script src="/node_modules/@finos/perspective/dist/umd/perspective.js"></script>
<script src="/node_modules/@finos/perspective-viewer/dist/umd/perspective-viewer.js"></script>
<script src="/node_modules/@finos/perspective-viewer-datagrid/dist/umd/perspective-viewer-datagrid.js"></script>
<script src="/node_modules/@finos/perspective-viewer-d3fc/dist/umd/perspective-viewer-d3fc.js"></script>
<link rel='stylesheet' href="/node_modules/@finos/perspective-viewer/dist/umd/material-dense.css">
<link rel='stylesheet' href="index.css">
</head>
<body>
<div id="app">
<div id="controls">
<button id="run" disabled>Run</button>
<div class="range">
<span>Size</span>
<input id="width" min="25" max="700" type="number" placeholder="Width" value="200"></input>
<input id="height" min="25" max="500" type="number" placeholder="Height" value="200"></input>
</div>
<div class="range">
<span id="xrange">X [-0.4 , -0.3]</span>
<input id="xmin" min="-2" max="1.0" step="0.1" value="-0.4" type="range"></input>
<input id="xmax" min="-2" max="1.0" step="0.1" value="-0.3" type="range"></input>
</div>
<div class="range">
<span id="yrange">Y [-0.7 , -0.6]</span>
<input id="ymin" min="-1" max="1.0" step="0.1" value="-0.7" type="range"></input>
<input id="ymax" min="-1" max="1.0" step="0.1" value="-0.6" type="range"></input>
</div>
<div class="range">
<span>Iterations</span>
<input id="iterations" min="1" max="1000" type="number" placeholder="Iterations" value="100"></input>
</div>
</div>
<perspective-viewer id="viewer"></perspective-viewer>
</div>
<script src="index.js"></script>
</body>
</html>
158 changes: 158 additions & 0 deletions examples/blocks/src/fractal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
function generate_mandelbrot(params) {
return `
// color
var height := ${params.height};
var width := ${params.width};
var xmin := ${params.xmin};
var xmax := ${params.xmax};
var ymin := ${params.ymin};
var ymax := ${params.ymax};
var iterations := ${params.iterations};
var x := floor("index" / height);
var y := "index" % height;
var c := iterations;
var cx := xmin + ((xmax - xmin) * x) / (width - 1);
var cy := ymin + ((ymax - ymin) * y) / (height - 1);
var vx := 0;
var vy := 0;
var vxx := 0;
var vyy := 0;
var vxy := 0;
for (var ii := 0; ii < iterations; ii += 1) {
if (vxx + vyy <= float(4)) {
vxy := vx * vy;
vxx := vx * vx;
vyy := vy * vy;
vx := vxx - vyy + cx;
vy := vxy + vxy + cy;
c -= 1;
}
};
c`;
}

function generate_layout(params) {
return {
plugin: "Heatmap",
settings: true,
row_pivots: [`floor("index" / ${params.height})`],
column_pivots: [`"index" % ${params.height}`],
columns: ["color"],
expressions: [
generate_mandelbrot(params).trim(),
`floor("index" / ${params.height})`,
`"index" % ${params.height}`,
],
};
}

async function generate_data(table) {
const run = document.getElementById("run");
let json = new Array(width * height);
for (let x = 0; x < width; ++x) {
for (let y = 0; y < height; ++y) {
const index = x * height + y;
json[index] = {
index,
};
}
}

await table.replace(json);
run.innerHTML = `Run`;
}

// GUI

function get_gui_params() {
return [
"xmin",
"xmax",
"ymin",
"ymax",
"width",
"height",
"iterations",
].reduce((acc, x) => {
acc[x] = window[x].valueAsNumber;
return acc;
}, {});
}

function make_range(x, y, range, name) {
const title = () =>
name +
" [" +
x.valueAsNumber.toFixed(1) +
", " +
y.valueAsNumber.toFixed(1) +
"]";

x.addEventListener("input", () => {
window.run.disabled = false;
x.value = Math.min(x.valueAsNumber, y.valueAsNumber - 0.1);
range.innerHTML = title();
});

y.addEventListener("input", () => {
window.run.disabled = false;
y.value = Math.max(x.valueAsNumber + 0.1, y.valueAsNumber);
range.innerHTML = title();
});
}

const make_run_click_callback = (worker, state) => async () => {
if (window.run.innerHTML.trim() !== "Run") {
window.run.innerHTML = "Run";
return;
}

window.run.disabled = true;
if (!state.table) {
state.table = await worker.table({
index: "integer",
});
window.viewer.load(Promise.resolve(state.table));
}

const run = document.getElementById("run");
const params = get_gui_params();
const new_size = params.width * params.height;
if (!state.size || state.size !== new_size) {
let json = {index: new Array(new_size)};
for (let x = 0; x < new_size; ++x) {
json.index[x] = x;
}

state.table.replace(json);
}

state.size = new_size;
run.innerHTML = `Run`;
window.viewer.restore(generate_layout(params));
};

function set_runnable() {
window.run.disabled = false;
}

window.addEventListener("DOMContentLoaded", async function () {
const heatmap_plugin = await window.viewer.getPlugin("Heatmap");
heatmap_plugin.max_cells = 100000;
make_range(xmin, xmax, xrange, "X");
make_range(ymin, ymax, yrange, "Y");
window.width.addEventListener("input", set_runnable);
window.height.addEventListener("input", set_runnable);
window.iterations.addEventListener("input", set_runnable);

run.addEventListener(
"click",
make_run_click_callback(window.perspective.worker(), {})
);
run.dispatchEvent(new Event("click"));
});
Loading

0 comments on commit 771dcb1

Please sign in to comment.