Skip to content

Instantly share code, notes, and snippets.

@adamstrickland
Created January 23, 2013 19:31
Show Gist options
  • Save adamstrickland/4611957 to your computer and use it in GitHub Desktop.
Save adamstrickland/4611957 to your computer and use it in GitHub Desktop.
position plotting ***WORK IN PROGRESS***
ko.bindingHandlers.visualize = {
update: function (elem, acc, all, ctx, vm) {
vm.visualization.update();
},
init: function (elem, acc, all, ctx, vm) {
var _options = ko.utils.unwrapObservable(acc)();
var _data = (_options.data() || []);
var _height = _options.height || 250;
var _width = _options.width || 506;
var _default_color_scheme = 'cool'; // other options: 'spectrum14', 'colorwheel', 'spectrum2000', 'spectrum2001', 'classic9'
var _scheme = (_options.color_scheme || _default_color_scheme);
var _palette = new Rickshaw.Color.Palette({ scheme: _scheme });
var _container = $(elem).closest('.position-chart-container');
var _yaxis = _container.find('.position-chart-yaxis');
var _xaxis = _container.find('.position-chart-xaxis');
vm.visualization = new Rickshaw.Graph({
element: elem,
width: _width,
height: _height,
renderer: 'area',
stroke: true,
interpolation: true,
series: [{
color: _palette.color(),
// stroke: 'rgba(255, 255, 255, 0.75)',
data: _data,
name: 'Native'
}],
min: _.min([-10] + _data),
max: (_.max(_data) + 20)
});
var _he_formatter = function (t) {
var m = moment.utc(t).local();
if (m.hours() == 0 && m.minutes() == 0) {
return '2400';
}
else {
return m.format('HHmm')
}
};
vm.hover_detail = new Rickshaw.Graph.HoverDetail({
graph: vm.visualization,
formatter: function (series, x, y) {
var ms = (x * 1000); // the x value is in seconds, not milliseconds, which is what moment() expects
var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
var content = swatch + "HE" + _he_formatter(ms) + "<br/>" + parseFloat(y) + "MW " +series.name;
return content;
}
});
vm.x_axis = _.extend(new Rickshaw.Graph.Axis.Time({
graph: vm.visualization,
// element: _xaxis[0],
orientation: 'bottom'
}), {
render: function () {
var _self = this;
_.each(_self.elements, function (e) { e.parentNode.removeChild(e); });
_self.elements = _.map(_self.tickOffsets(), function (o) {
if (_self.graph.x(o.value) > _self.graph.x.range()[1]) return;
var element = document.createElement('div');
element.style.left = _self.graph.x(o.value) + 'px';
element.classList.add('x_tick');
element.classList.add(_self.ticksTreatment);
var title = document.createElement('div');
title.classList.add('title');
title.innerHTML = _he_formatter(moment(o.value * 1000));
element.appendChild(title);
_self.graph.element.appendChild(element);
return element;
});
}
});
vm.y_axis = _.extend(new Rickshaw.Graph.Axis.Y({
element: _yaxis[0],
// ticks: 10,
ticksTreatment: 'unplain',
graph: vm.visualization,
orientation: 'left'
}), {
render: function () {
var _self = this;
if (_self.graph.height !== _self._renderHeight) _self.setSize({ auto: true });
var axis = d3.svg.axis().scale(_self.graph.y).orient(_self.orientation);
axis.tickFormat(function(y) {
return y + "MW";
});
var berthRate = 0.10;
var berth = _self.height * berthRate;
var transform = 'translate(' + _self.width + ', ' + berth + ')';
if (_self.element) {
_self.vis.selectAll('*').remove();
}
var _tick_it = function (ts) {
var __ticks = axis.ticks(_self.ticks)
var __subs = __ticks.tickSubdivide(0)
var __tickSize = __subs.tickSize(ts);
return __tickSize;
};
_self.vis
.append("svg:g")
.attr("class", ["y_ticks", _self.ticksTreatment, "hhgttg"].join(" "))
.attr("transform", transform)
.call(_tick_it(_self.tickSize));
// .call(axis.ticks(_self.ticks).tickSubdivide(0).tickSize(_self.tickSize))
var gridSize = (_self.orientation == 'right' ? 1 : -1) * _self.graph.width;
_self.graph.vis
.append("svg:g")
.attr("class", "y_grid")
.call(_tick_it(gridSize));
// .call(axis.ticks(_self.ticks).tickSubdivide(0).tickSize(gridSize));
_self._renderHeight = _self.graph.height;
}
});
vm.visualization.render();
}
}
<div class="position list-item row-fluid" data-bind="attr: { 'data-id': _id }">
<div class="span12">
<div class="container-fluid">
<div class="row-fluid">
<div class="span6">
<a class="desc">
<span data-bind="text: mark"/>
</a>
<p class="detail">
<span data-bind="formatted: { target: tenor, format: 'MMMM D YYYY' }"/>
(updated <span data-bind="humanized: updated_at"/>)
</p>
</div>
</div>
<div class="row-fluid">
<div class="position-chart-container">
<div class="position-chart-yaxis"></div>
<div class="position-chart" data-bind="visualize: { data: interval_data }"></div>
<div class="position-chart-xaxis"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div data-bind="visible: !display_position_data()">
<a class="show-detail" data-bind="click: showPositionData">View Details</a>
</div>
<div data-bind="visible: display_position_data()">
<div class="detail-table-container">
<table class="detail">
<thead>
<tr>
<th scope="col">HE</th>
<th scope="col">Load</th>
<th scope="col">7x24</th>
<th scope="col">7x8</th>
<th scope="col">5x16</th>
<th scope="col">1x1</th>
<th scope="col">Unhedged</th>
</tr>
</thead>
<tbody data-bind="foreach: rows">
<tr>
<td><em data-bind="text: hour_ending"/></td>
<td><span class="pull-right" data-bind="text: native"/></td>
<td><span class="pull-right" data-bind="text: sum_7x24"/></td>
<td><span class="pull-right" data-bind="text: sum_7x8"/></td>
<td><span class="pull-right" data-bind="text: sum_5x16"/></td>
<td><span class="pull-right" data-bind="text: sum_1x1"/></td>
<td><span class="pull-right" data-bind="text: unhedged"/></td>
</tr>
</tbody>
</table>
</div>
<div>
<button class="btn btn-small btn-link hide-detail" data-bind="click: hidePositionData">Hide Detail</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
self._mapPosition = function (datum) {
var _item = datum;
_item.cols = ko.observableArray(_.map(_item.components, function (c) {
return c.name;
}));
var dataset = _.groupBy(_.flatten(_.map(_item.components, function (c) {
return _.map(c.intervals, function (i) {
return {
product: c.name,
interval: i.name,
value: i.value
};
});
})), function (d) {
return d.interval;
});
var _map_reduce = function (arr_of_dats, matcher) {
return _.foldl(_.filter(arr_of_dats, function (dat) {
return matcher.test(dat.product);
}), function (memo, dat) {
return memo + dat.value;
}, 0);
};
_item.rows = ko.observableArray(_.sortBy(_.map(dataset, function (vals, grp) {
var _native = _map_reduce(vals, /load/);
var _7x24 = _map_reduce(vals, /7x24/);
var _7x8 = _map_reduce(vals, /7x8/);
var _5x16 = _map_reduce(vals, /5x16/);
var _7x16 = _map_reduce(vals, /2x16/);
var _2x16 = _map_reduce(vals, /7x16/);
var _1x1 = _map_reduce(vals, /1x1/);
var _unhedged = _native - _.foldl([_1x1, _7x24, _5x16, _7x8, _2x16, _7x16], function (m, s) { return m + s; });
return {
hour_ending: grp,
'native': _native,
sum_7x24: _7x24,
sum_7x8: _7x8,
sum_5x16: _5x16,
sum_7x16: _7x16,
sum_2x16: _2x16,
sum_1x1: _1x1,
unhedged: _unhedged
};
}), function (row) {
return row.hour_ending;
}));
var _to_epoch = function (d, he) {
var hr = (parseInt(he) / 100);
var ts = moment(d).add('hours', hr);
return ts.unix();
};
var _interval_data = _.map(_item.rows(), function (row) {
return {
x: _to_epoch(_item.tenor, row.hour_ending),
y: row['native']
};
});
// var _interval_data = _.map(_item.intervals(), function (intvl, vals) {
// return {
// x: _to_epoch(_item.tenor, intvl),
// y: vals['native']
// };
// });
_item.interval_data = ko.observableArray(_interval_data);
_item.display_position_data = ko.observable(false);
_item.showPositionData = function () { _item.display_position_data(true); };
_item.hidePositionData = function () { _item.display_position_data(false); };
return _item;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment