Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sunburst charts #112

Merged
merged 1 commit into from
May 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions packages/perspective-jupyterlab/src/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const PSP_CONTAINER_CLASS = 'jp-PSPContainer';

interface PerspectiveSpec {
data: string,
schema: string,
layout: string,
config: string;
}
Expand All @@ -47,7 +46,6 @@ export class RenderedPSP extends Widget implements IRenderMime.IRenderer {
let psp = (<any>(this.node.querySelector('perspective-viewer')));

let layout = JSON.parse(this._lyt);

for(let key in layout){
if(layout[key]){
if(key !== 'view'){
Expand All @@ -58,13 +56,8 @@ export class RenderedPSP extends Widget implements IRenderMime.IRenderer {
}
}

if (this._schema !== '') {
let schema = JSON.parse(this._schema);
psp.load(schema);
}

if (this._datatype === 'static') {
psp.update(this._data);
psp.load(this._data);
} else if (this._datatype === 'ws' || this._datatype === 'wss') {
let config = JSON.parse(this._config);
let send = config.send || '';
Expand Down Expand Up @@ -118,9 +111,8 @@ export class RenderedPSP extends Widget implements IRenderMime.IRenderer {
}

renderModel(model: IRenderMime.IMimeModel): Promise<void> {
const {data, schema, layout, config} = model.data[MIME_TYPE] as any | PerspectiveSpec;
const {data, layout, config} = model.data[MIME_TYPE] as any | PerspectiveSpec;
this._lyt = layout;
this._schema = schema;

try {
this._data = JSON.parse(data) as object;
Expand Down Expand Up @@ -164,7 +156,6 @@ export class RenderedPSP extends Widget implements IRenderMime.IRenderer {
private _data: object;
private _datatype: string;
private _datasrc: string;
private _schema: string;
private _lyt: string; // not widget layout
private _config: string;
private _loaded: boolean;
Expand Down
36 changes: 36 additions & 0 deletions packages/perspective-viewer-highcharts/src/js/heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import highchartsMore from 'highcharts-more';
import heatmap from 'highcharts/modules/heatmap';
import boost from 'highcharts/modules/boost';
import treemap from 'highcharts/modules/treemap';
import sunburst from 'highcharts/modules/sunburst';
import grouped_categories from 'highcharts-grouped-categories';
import chroma from 'chroma-js';

Expand All @@ -29,6 +30,7 @@ let axisProto = Highcharts.Axis.prototype,
highchartsMore(highcharts);
heatmap(highcharts);
treemap(highcharts);
sunburst(highcharts);
grouped_categories(highcharts);
boost(highcharts);

Expand Down Expand Up @@ -75,6 +77,40 @@ Highcharts.setOptions({
axisTypes: ['xAxis', 'yAxis', 'colorAxis']
}));

// draw points and add setting colors
H.wrap(H.seriesTypes.sunburst.prototype, "translate", function(p, positions) {
p.call(this, positions);
this.translateColors();
});

// copy method from heatmap for color mixin
H.seriesTypes.sunburst.prototype.translateColors = function() {
var series = this,
nullColor = this.options.nullColor,
colorAxis = this.colorAxis,
colorKey = this.colorKey;

H.each(this.data, function(point) {
var value = point[colorKey],
color;

color = point.options.color ||
(!point.value ? // LINE CHANGED
nullColor :
(colorAxis && value !== undefined) ?
colorAxis.toColor(value, point) :
point.color || series.color
);

if (color) {
point.color = color;
}
});
}

// use "colorValue" to calculate color
H.seriesTypes.sunburst.prototype.colorKey = 'colorValue';

// Pushes part of grid to path
function addGridPart(path, d, width) {
// Based on crispLine from HC (#65)
Expand Down
16 changes: 15 additions & 1 deletion packages/perspective-viewer-highcharts/src/js/highcharts.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ export function draw(mode) {
type = 'column';
} else if (mode == 'treemap') {
type = 'treemap';
} else if (mode == 'sunburst') {
type = 'sunburst';
} else if (mode === 'scatter') {
if (aggregates.length <= 3) {
type = 'scatter';
Expand Down Expand Up @@ -589,7 +591,7 @@ export function draw(mode) {

color_axis.bind(this)(config, colorRange)
config.legend.floating = false;
} else if (mode === "treemap") {
} else if (mode === "treemap" || mode === "sunburst") {
let data = [];
let size = aggregates[0]['column'];
let color, colorAxis, colorRange;
Expand Down Expand Up @@ -868,6 +870,18 @@ global.registerPlugin("treemap", {
delete: function () {}
});

global.registerPlugin("sunburst", {
name: "Sunburst",
create: draw('sunburst'),
resize: resize,
initial: {
"type": "number",
"count": 2
},
selectMode: "toggle",
delete: function () {}
});

global.registerPlugin("heatmap", {
name: "Heatmap",
create: draw("heatmap"),
Expand Down
12 changes: 3 additions & 9 deletions packages/perspective/src/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,7 @@ make_table(
val j_data,
t_uint32 offset,
t_str index,
t_bool is_arrow,
t_bool is_delete
t_bool is_arrow
) {
// Create the input and port schemas
t_svec colnames = vecFromJSArray<std::string>(j_colnames);
Expand All @@ -519,13 +518,8 @@ make_table(
_fill_data(tbl, colnames, j_data, dtypes, offset, is_arrow);

// Set up pkey and op columns
if (is_delete) {
auto op_col = tbl->add_column("psp_op", DTYPE_UINT8, false);
op_col->raw_fill<t_uint8>(OP_DELETE);
} else {
auto op_col = tbl->add_column("psp_op", DTYPE_UINT8, false);
op_col->raw_fill<t_uint8>(OP_INSERT);
}
auto op_col = tbl->add_column("psp_op", DTYPE_UINT8, false);
op_col->raw_fill<t_uint8>(OP_INSERT);

if (index == "")
{
Expand Down
46 changes: 2 additions & 44 deletions packages/perspective/src/js/perspective.js
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ table.prototype.update = function (data) {
try {
tbl = __MODULE__.make_table(pdata.row_count || 0,
pdata.names, pdata.types, pdata.cdata,
this.gnode.get_table().size(), this.index || "", pdata.is_arrow, false);
this.gnode.get_table().size(), this.index || "", pdata.is_arrow);

// Add any computed columns
this._calculate_computed(tbl, this.computed);
Expand All @@ -1089,48 +1089,6 @@ table.prototype.update = function (data) {
}
}

/**
* Removes the rows of a {@link table}. Removed rows are pushed down to any
* derived {@link view} objects.
*
* @param {Array<Object>} data An array of primary keys to remove.
*
* @see {@link table}
*/
table.prototype.remove = function (data) {
let pdata;
let cols = this._columns();
let schema = this.gnode.get_tblschema();
let types = schema.types();

data = data.map(idx => ({[this.index]: idx}));

if (data instanceof ArrayBuffer) {
pdata = load_arrow_buffer(data, [this.index], types);
}
else {
pdata = parse_data(data, [this.index], types);
}

let tbl;
try {
tbl = __MODULE__.make_table(pdata.row_count || 0,
pdata.names, pdata.types, pdata.cdata,
this.gnode.get_table().size(), this.index || "", pdata.is_arrow, true);

__MODULE__.fill(this.pool, this.gnode, tbl);
this.initialized = true;
} catch (e) {
console.error(e);
} finally {
if (tbl) {
tbl.delete();
}
schema.delete();
types.delete();
}
}

/**
* Create a new table with the addition of new computed columns (defined as javascript functions)
*/
Expand Down Expand Up @@ -1445,7 +1403,7 @@ const perspective = {
// Fill t_table with data
tbl = __MODULE__.make_table(pdata.row_count || 0,
pdata.names, pdata.types, pdata.cdata,
0, options.index, pdata.is_arrow, false);
0, options.index, pdata.is_arrow);

gnode = __MODULE__.make_gnode(tbl);
pool.register_gnode(gnode);
Expand Down
2 changes: 0 additions & 2 deletions packages/perspective/src/js/perspective.parallel.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,6 @@ table.prototype.delete = async_queue('delete', "table_method");

table.prototype.on_delete = subscribe('on_delete', 'table_method', true);

table.prototype.remove = async_queue('remove', "table_method");

table.prototype.update = function(data) {
return new Promise( (resolve, reject) => {
this._worker.handlers[++this._worker.msg_id] = {resolve, reject};
Expand Down
24 changes: 0 additions & 24 deletions packages/perspective/test/js/updates.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,6 @@ var arrow_indexed_result = [

module.exports = (perspective) => {


describe("Removes", function() {

it("after an `update()`", async function () {
var table = perspective.table(meta, {index: "x"});
table.update(data);
var view = table.view();
table.remove([1, 2]);
let result = await view.to_json();
expect(result.length).toEqual(2);
expect(data.slice(2, 4)).toEqual(result);
});

it("after an regular data load`", async function () {
var table = perspective.table(data, {index: "x"});
var view = table.view();
table.remove([1, 2]);
let result = await view.to_json();
expect(result.length).toEqual(2);
expect(data.slice(2, 4)).toEqual(result);
});

});

describe("Updates", function() {

it("Meta constructor then `update()`", async function () {
Expand Down