Skip to content

Commit

Permalink
Deployment Improvements (#3)
Browse files Browse the repository at this point in the history
* Simplify deployment, build JS into a directory that is served from the server to allow for automatic URL fill-in

* Refactored client logic into the backend

* Finished refactoring to support deployment changes

* Removed unused functions

* Migrated web server to tornado, made plotly use CDMS

* Converted to tornado for websocket as well; need to remove numpy stuff to basically eliminate the total effort

* Highly optimized websocket rendering in place

* Fixed resizing issues, now have fairly performant autoscaling

* Added 3d demo, click code

* Added clear function

* Added start/end events and made sure each plot call returns a promise

* Added some missing dependencies

* fixed more dependencies

* Cleaned up dependencies and wrapped up a few loose ends

* Fixes bug with closing connections

* Actually add close function to backends

* And maybe without syntax errors
  • Loading branch information
chaosphere2112 authored Jan 11, 2017
1 parent e593f12 commit 592d30a
Show file tree
Hide file tree
Showing 26 changed files with 859 additions and 565 deletions.
100 changes: 99 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ tags
.LSOverride

# Icon must end with two \r
Icon
Icon


# Thumbnails
._*
Expand Down Expand Up @@ -92,3 +93,100 @@ Makefile
cmake_install.cmake
install_manifest.txt
CTestTestfile.cmake


# Created by https://www.gitignore.io/api/python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# IPython Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject

vcs_server/js/*.js
vcs_server/js/*.js.map
1 change: 0 additions & 1 deletion config/webpack.loaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ module.exports = [
test: /\.js$/,
include: [
/src/,
/node_modules\/paraviewweb/,
],
loader: 'babel?presets[]=es2015-nostrict',
},
Expand Down
1 change: 0 additions & 1 deletion config/webpack.resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ module.exports = {
alias: {
vcs: path.resolve('./src'),
plotly: path.resolve('./node_modules/plotly.js/dist/plotly'),
ParaViewWeb: path.resolve('./node_modules/paraviewweb/src'),
},
};
15 changes: 12 additions & 3 deletions demo/demo.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
.plot {
height: 600px;
width: 800px;
body, html {
width:100%;
height:100%;
}

* {
box-sizing: border-box;
}

div.plot {
width: 50%;
height: 50%;
float: left;
}
118 changes: 23 additions & 95 deletions demo/demo.js
Original file line number Diff line number Diff line change
@@ -1,118 +1,46 @@
var sessionPromise;

$(function () {
// Ordinarily this would be a URL string of a rest
// interface for generating a new server side connection.
// Here we short circuit that code to generate a simulated
// session connecting to pregenerated files through
// Girder's rest interface.
var url = 'ws://localhost:9000/ws';
(function () {

var variables = {
"clt": {
"id": "clt",
"derivation":
[
{"type": "file", "uri": "clt.nc"},
{"parents": [0], "operation": {"type": "get", "id": "clt"}, "type": "variable"},
{"parents": [1], "operation": {"squeeze": 0, "type": "subset", "axes": {"longitude": [-180, 180], "latitude": [-90, 90]}}, "type": "variable"}
]
},
"clt": {"id": "clt", "derivation": [{"type": "file", "uri": "clt.nc"}, {"parents": [0], "operation": {"type": "get", "id": "clt"}, "type": "variable"}]},
"u": {"id": "u", "derivation": [{"type": "file", "uri": "clt.nc"}, {"parents": [0], "operation": {"type": "get", "id": "u"}, "type": "variable"}]},
"v": {"id": "v", "derivation": [{"type": "file", "uri": "clt.nc"}, {"parents": [0], "operation": {"type": "get", "id": "v"}, "type": "variable"}]}
}

var boxfill = {"fillareaopacity": [], "datawc_timeunits": "days since 2000", "projection": "linear", "xticlabels1": "*", "xticlabels2": "*", "ymtics1": "", "ymtics2": "", "datawc_x1": 1e+20, "datawc_x2": 1e+20, "boxfill_type": "linear", "xmtics1": "", "fillareacolors": null, "xmtics2": "", "color_2": 255, "datawc_calendar": 135441, "fillareaindices": [1], "color_1": 0, "colormap": null, "missing": [0.0, 0.0, 0.0, 100.0], "xaxisconvert": "linear", "level_2": 1e+20, "ext_1": false, "ext_2": false, "datawc_y2": 1e+20, "datawc_y1": 1e+20, "yaxisconvert": "linear", "legend": null, "name": "__boxfill_717978942019492", "yticlabels1": "*", "yticlabels2": "*", "fillareastyle": "solid", "levels": [1e+20, 1e+20], "g_name": "Gfb", "level_1": 1e+20};
var boxfill = {"fillareaopacity": [], "datawc_timeunits": "days since 2000", "projection": "linear", "xticlabels1": "*", "xticlabels2": "*", "ymtics1": "", "ymtics2": "", "datawc_x1": 1e+20, "datawc_x2": 1e+20, "boxfill_type": "linear", "xmtics1": "", "fillareacolors": null, "xmtics2": "", "color_2": 255, "datawc_calendar": 135441, "fillareaindices": [1], "color_1": 0, "colormap": null, "missing": [0.0, 0.0, 0.0, 100.0], "xaxisconvert": "linear", "level_2": 1e+20, "ext_1": false, "ext_2": false, "datawc_y2": 1e+20, "datawc_y1": 1e+20, "yaxisconvert": "linear", "legend": null, "color_2": 255, "datawc_calendar": 135441, "fillareaindices": [1], "color_1": 0, "colormap": null, "missing": [0.0, 0.0, 0.0, 100.0], "xaxisconvert": "linear", "level_2": 1e+20, "ext_1": false, "ext_2": false, "datawc_y2": 1e+20, "datawc_y1": 1e+20, "yaxisconvert": "linear", "legend": null, "name": "__boxfill_717978942019492", "yticlabels1": "*", "yticlabels2": "*", "fillareastyle": "solid", "levels": [1e+20, 1e+20], "g_name": "Gfb", "level_1": 1e+20};
var vector = {"datawc_timeunits": "days since 2000", "projection": "linear", "reference": 1e+20, "xticlabels1": "*", "xticlabels2": "*", "linecolor": null, "ymtics1": "", "ymtics2": "", "linewidth": null, "datawc_x1": 1e+20, "datawc_x2": 1e+20, "xmtics1": "", "xmtics2": "", "datawc_calendar": 135441, "alignment": "center", "type": "arrows", "colormap": null, "xaxisconvert": "linear", "scale": 1.0, "linetype": null, "datawc_y2": 1e+20, "datawc_y1": 1e+20, "yaxisconvert": "linear", "name": "vector_full", "yticlabels1": "*", "yticlabels2": "*", "scalerange": [0.1, 1.0], "scaleoptions": ["off", "constant", "normalize", "linear", "constantNNormalize", "constantNLinear"], "g_name": "Gv", "scaletype": "constantNNormalize"};
var vector_subview = {"datawc_timeunits": "days since 2000", "projection": "linear", "reference": 1e+20, "xticlabels1": "*", "xticlabels2": "*", "linecolor": null, "ymtics1": "", "ymtics2": "", "linewidth": null, "datawc_x1": 60, "datawc_x2": 180, "xmtics1": "", "xmtics2": "", "datawc_calendar": 135441, "alignment": "center", "type": "arrows", "colormap": null, "xaxisconvert": "linear", "scale": 1.0, "linetype": null, "datawc_y2": 90, "datawc_y1": 0, "yaxisconvert": "linear", "name": "subset_vector", "yticlabels1": "*", "yticlabels2": "*", "scalerange": [0.1, 1.0], "scaleoptions": ["off", "constant", "normalize", "linear", "constantNNormalize", "constantNLinear"], "g_name": "Gv", "scaletype": "constantNNormalize"};
var isofill = {"g_name": "Gfi"};
var dv3d = {ScaleColormap: null, ScaleOpacity: null, BasemapOpacity: null, Camera: "{}", ZSlider: null, YSlider: null, ToggleVolumePlot: null, PointSize: null, Configure: null, XSlider: null, SliceThickness: null, axes: "xyz", plot_attributes: {name: "3d_scalar", template: "default"}, IsosurfaceValue: null, VerticalScaling: null, ChooseColormap: null, ToggleSurfacePlot: null, Colorbar: null, ncores: 8, ScaleTransferFunction: null, name: "default", ToggleClipping: null, Animation: null, g_name: "3d_scalar" };

// create the session
sessionPromise = vcs.createSession(url);
var b = document.getElementById('vcs-boxfill');
var canvas = vcs.init(b);

sessionPromise.catch(() => {
console.log('Could not connect to ' + url);
b.addEventListener('vcsPlotStart', function() {
console.log("Began plotting boxfill");
});

var canvasPromise = sessionPromise.then(function (session) {
return session.init(document.getElementById('vcs-isofill'));
b.addEventListener('vcsPlotEnd', function() {
console.log("Finished plotting boxfill");
});

// generate the plot when all of the promises resolve
canvasPromise.then(function (canvas) {
var dataSpec = variables.clt;
canvas.plot(dataSpec, 'no_legend', boxfill, 'server');
var dataSpec = variables.clt;
canvas.plot(dataSpec, boxfill, 'no_legend').then(function(){
console.log("Promise completed.");
});

// generate another plot using client side rendering
// we don't have an api for getting data yet, so we'll
// just use an ajax request to data.kitware.com
var cltPromise = $.ajax('https://data.kitware.com/api/v1/file/576aa3c08d777f1ecd6701ae/download');
var latPromise = $.ajax('https://data.kitware.com/api/v1/item/576aa3c08d777f1ecd6701b0/download');
var lonPromise = $.ajax('https://data.kitware.com/api/v1/item/576aa3c08d777f1ecd6701b9/download');
var canvasPromise2 = sessionPromise.then(function (session) {
return session.init(document.getElementById('plotly-isofill'));
});


// This is all very rough, likely much of this should be wrapped inside the api
Promise.all([
canvasPromise2, cltPromise, latPromise, lonPromise
]).then(function (arg) {
console.log("1")
var canvas = arg[0];
console.log("2")
var clt = arg[1];
console.log("3")
var lat = arg[2];
console.log("4")
var lon = arg[3];
console.log("5")
var timestep = 0;
console.log("6")

var data = {
x: lon.data,
y: lat.data
};
console.log("7")
var canvas2 = vcs.init(document.getElementById('plotly-isofill'), 'client');
canvas2.plot(dataSpec, isofill);

function draw() {
console.log("8")
data.z = ndarray(clt.data, clt.shape).pick(timestep, null, null);
console.log("9")
canvas.plot(data, 'default', { "g_type": "Gfi" }, 'client');
console.log("10")
timestep = (timestep + 1) % clt.shape[0];
}
console.log("11")
// call again for the next time step
draw();
});

var canvasPromise3 = sessionPromise.then(function (session) {
return session.init(document.getElementById('vcs-vector'));
});
var canvas3 = vcs.init(document.getElementById('vcs-vector'));
// generate the plot when all of the promises resolve
canvasPromise3.then(function (canvas) {
var dataSpec = [variables.u, variables.v];
canvas.plot(dataSpec, 'default', vector, 'server');
});

var canvasPromise4 = sessionPromise.then(function (session) {
return session.init(document.getElementById('vcs-vector-subset'));
});
var dataSpec = [variables.u, variables.v];
canvas3.plot(dataSpec, vector_subview);

// generate the plot when all of the promises resolve
canvasPromise4.then(function (canvas) {
var dataSpec = [variables.u, variables.v];
canvas.plot(dataSpec, 'default', vector_subview, 'server');
});

$(window).on('beforeunload', function() {
canvasPromise.then((canvas) => canvas.close());
canvasPromise3.then((canvas) => canvas.close());
canvasPromise4.then((canvas) => canvas.close());
return 'Your own message goes here...';
});
});
var canvas4 = vcs.init(document.getElementById('vcs-vector-subset'));
var dataSpec = variables.clt;
canvas4.plot(dataSpec, dv3d);

})();
40 changes: 13 additions & 27 deletions demo/index.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset = UTF-8">
<link rel="stylesheet" type="text/css" href="demo.css">
</head>
<body>
<table>
<tr>
<td><div class="plot" id="vcs-isofill"></div></td>
<td><div class="plot" id="plotly-isofill"></div></td>
</tr>
<tr>
<td><div class="plot" id="vcs-vector"></div></td>
<td><div class="plot" id="vcs-vector-subset"></div></td>
</tr>
</table>
<script type="text/javascript" src="../dist/vcs.js"></script>
<script type="text/javascript" src="demo.js"></script>

<ul>
<!-- Need a 3D variable for this: <li><a onclick="cdat.create_plot('http://test.opendap.org/opendap/data/nc/coads_climatology.nc', 'AIRT', '3d_scalar', 'default', 'default')" href="javascript:void(0)">Volume example</a></li> -->
<li><a onclick="print_variables('coads_climatology.nc')" href="javascript:void(0)">Rectilinear grid variables example</a></li>
<li><a onclick="print_variables('clt.nc')" href="javascript:void(0)">clt.nc variables example</a></li>
<li><a onclick="print_variables('sampleCurveGrid4.nc')" href="javascript:void(0)">Curvilinear grid variable example</a></li>
<li><a onclick="print_variables('sampleGenGrid3.nc')" href="javascript:void(0)">Generic grid variable example</a></li>
</body>

<head>
<meta http-equiv="Content-Type" content="text/html; charset = UTF-8">
<link rel="stylesheet" type="text/css" href="demo.css">
</head>
<body>
<div class="plot" id="vcs-boxfill"></div>
<div class="plot" id="plotly-isofill"></div>
<div class="plot" id="vcs-vector"></div>
<div class="plot" id="vcs-vector-subset"></div>
<script type="text/javascript" src="http://localhost:8888/scripts/vcs.js"></script>
<script type="text/javascript" src="demo.js"></script>
<ul>
</body>
</html>
21 changes: 16 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Javascript interface for vcs.",
"main": "dist/vcs.js",
"scripts": {
"build": "webpack --progress --colors --optimize-minimize --optimize-dedupe",
"build": "webpack --progress --colors",
"lint": "eslint --cache .",
"karma": "karma start --single-run",
"test": "npm run lint && npm run karma",
Expand All @@ -15,13 +15,23 @@
"author": "",
"license": "Apache-2.0",
"devDependencies": {
"babel-cli": "^6.16.0",
"babel-core": "^6",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015-nostrict": "^6.6.2",
"bluebird": "^3.4.6",
"chai": "^3.5.0",
"chai-as-promised": "^5.3.0",
"eslint": "^3.6.0",
"eslint-config-airbnb": "^12.0.0",
"eslint-import-resolver-webpack": "^0.3.1",
"eslint-loader": "^1.6.0",
"eslint-plugin-chai-expect": "^1.1.1",
"eslint-plugin-import": "^1.16.0",
"eslint-plugin-jsx-a11y": "^2.2.2",
"eslint-plugin-react": "^6.3.0",
"expose-loader": "^0.7.1",
"inject-loader": "^2.0.1",
"isparta": "^4.0.0",
"isparta-loader": "^2.0.0",
Expand All @@ -39,17 +49,18 @@
"kw-web-suite": "^2.0.1",
"mocha": "^2.5.3",
"phantomjs-prebuilt": "^2.1.7",
"sinon": "*",
"webpack": "^1.3.0",
"webpack-dev-server": "^1.14.1"
},
"dependencies": {
"autobahn": "github:crossbario/autobahn-js-built#v0.10.1",
"axios": "^0.15.1",
"css-element-queries": "^0.3.2",
"hammerjs": "^2.0.8",
"isndarray": "^1.0.0",
"jquery": "^3.0.0",
"monologue.js": "^0.3.5",
"mout": "^1.0.0",
"paraviewweb": "^1.10.0",
"ndarray": "^1.0.18",
"isndarray": "^1.0.0",
"ndarray-pack": "^1.2.0",
"ndarray-unpack": "^1.0.0",
"plotly.js": "^1.14.0"
Expand Down
Loading

0 comments on commit 592d30a

Please sign in to comment.