* changed unit test json

Signed-off-by: Chinmay Singh <chsingh@microsoft.com>

* updated domain

Signed-off-by: Chinmay Singh <chsingh@microsoft.com>

* custom animation for sum

Signed-off-by: Chinmay Singh <chsingh@microsoft.com>

* stacked layout

Signed-off-by: Chinmay Singh <chsingh@microsoft.com>

* adjust y-axis encoding

Signed-off-by: Chinmay Singh <chsingh@microsoft.com>

* automatic tasks

* use existing elements for timing

* grid specs for sum
This commit is contained in:
Chinmay Singh 2022-07-03 23:43:02 -04:00 коммит произвёл GitHub
Родитель 586939acb3
Коммит 459ded6441
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 2972 добавлений и 51 удалений

62
.vscode/launch.json поставляемый
Просмотреть файл

@ -1,30 +1,34 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Mocha Tests",
"cwd": "${workspaceFolder}/inst/htmlwidgets/js/src/",
"program": "${workspaceFolder}/inst/htmlwidgets/js/src/node_modules/mocha/bin/_mocha",
"args": [
"--reporter",
"dot",
"--require",
"esm",
"--require",
"@babel/register",
"--colors",
"${workspaceFolder}/inst/htmlwidgets/js/src/test/**/*.js",
],
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Edge",
"request": "launch",
"type": "msedge",
"url": "http://localhost:3000/inst/htmlwidgets/dev-app/",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "Mocha Tests",
"cwd": "${workspaceFolder}/inst/htmlwidgets/js/src/",
"program": "${workspaceFolder}/inst/htmlwidgets/js/src/node_modules/mocha/bin/_mocha",
"args": [
"--reporter",
"dot",
"--require",
"esm",
"--require",
"@babel/register",
"--colors",
"${workspaceFolder}/inst/htmlwidgets/js/src/test/**/*.js"
],
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": ["<node_internals>/**"]
}
]
}

13
.vscode/tasks.json поставляемый
Просмотреть файл

@ -21,6 +21,19 @@
"problemMatcher": [],
"label": "npm: test - inst/htmlwidgets/js/src",
"detail": "mocha"
},
{
"type": "npm",
"script": "dev",
"path": "inst/htmlwidgets/js/src",
"problemMatcher": [],
"label": "npm: dev - inst/htmlwidgets/js/src",
"detail": "rollup -c -w",
"presentation": {
"clear": true,
"panel": "dedicated"
},
"runOptions": { "runOn": "folderOpen" }
}
]
}

Просмотреть файл

@ -67,16 +67,16 @@
<script src="../js/src/dist/datamations.min.js"></script>
<script>
const animationType = "mean";
const animationType = "sum";
const base = "../../../sandbox/custom_animations/";
let app = null;
d3.json(
`${base}/custom-animations-${animationType}-R.json`
`${base}/custom-animations-${animationType}-manual.json`
// 'https://raw.githubusercontent.com/microsoft/datamations/specs_mutate/sandbox/mutations/mutation_specs_multiple_variables-R.json'
).then(
(specs) => {
app = datamations.App("app", { specs, frameDur: 3000 });
app = datamations.App("app", { specs, frameDur: 3000, autoPlay: true});
}
);
</script>

Просмотреть файл

@ -18741,7 +18741,7 @@
const newData = step.nextData.tick;
const joinKey = joinKeyGen("tick");
const timings = computeTiming(
currData,
ticks.data(),
newData,
step.timing,
joinKey,
@ -18925,7 +18925,7 @@
const newData = step.nextData.label;
const joinKey = joinKeyGen("label");
const timings = computeTiming(
currData,
labels.data(),
newData,
step.timing,
joinKey,
@ -19132,7 +19132,7 @@
const newData = step.nextData.grid;
const joinKey = joinKeyGen("grid");
const timings = computeTiming(
currData,
grids.data(),
newData,
step.timing,
joinKey,

1201
inst/htmlwidgets/js/src/package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,7 +7,7 @@
"scripts": {
"test": "mocha",
"build": "rollup -c",
"dev": "rollup -c -w"
"dev": "serve ../../../../ | rollup -c -w"
},
"keywords": [],
"author": "Giorgi Ghviniashvili",
@ -33,7 +33,8 @@
"rollup": "^2.70.1",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^7.0.2"
"rollup-plugin-terser": "^7.0.2",
"serve": "^13.0.2"
},
"files": [
"dist"

Просмотреть файл

@ -76,6 +76,69 @@ export const getCountStep = (source, target, shrink = false) => {
}
}
/**
* Generates a spec for sum animation
* @param {Object} source source spec
* @param {Object} target target spec
* @param {Object} shrink if truthy, circles will be pulled up
* @returns a vega lite spec
*/
export const getSumStep = (source, target, shrink = false) => {
const { width, height } = target.spec || target
let values = source.data.values.slice()
const sourceMeta = source.meta
// generate rules layer
const rules = sourceMeta.rules.map((d, i) => {
const n = sourceMeta.rules.length
return {
transform: [{ filter: d.filter }],
name: `rule-${i + 1}`,
mark: {
type: 'rule',
x: { expr: `${i + 1} * (width / ${n + 1}) - 5` },
x2: { expr: `${i + 1} * (width / ${n + 1}) + 5` }
},
encoding: {
y: {
field: CONF.Y_FIELD,
type: 'quantitative',
aggregate: 'max'
// axis: null,
}
}
}
})
if (shrink) {
values = values.map((d, i) => {
const y = target.data.values[i][CONF.Y_FIELD]
return {
...d,
[CONF.Y_FIELD]: y
}
})
}
return {
$schema: CONF.SCHEME,
width,
height,
data: {
name: 'source',
values
},
layer: [
{
name: 'main',
mark: source.mark,
encoding: source.encoding
},
...rules
]
}
}
/**
* Generates a spec for median and quantile animations
* @param {Object} source source spec
@ -662,6 +725,22 @@ export const CustomAnimations = {
const pullUp = getCountStep(rawSource, target, true)
return [stacks, rules, pullUp, target]
},
/**
* steps:
* 1) stack sets
* 2) put rules (lines) using aggregate sum
* 3) replace with sum bubbles (aggregate sum) (basically target spec)
* @param {Object} rawSource source spec
* @param {Object} target target spec
* @returns an array of vega-lite specs
*/
sum: async (rawSource, target) => {
const stacks = await getGridSpec(rawSource, 10, true)
delete stacks.encoding.y.axis
const rules = getSumStep(rawSource, target, false)
const pullUp = getSumStep(rawSource, target, true)
return [stacks, rules, pullUp, target]
},
/**
* min animation steps:
* 1) source spec

Просмотреть файл

@ -445,6 +445,10 @@ function prep_specs_groupby (states, groupby, summarize) {
spec = generate_vega_specs(data, meta, spec_encoding, facet_encoding, facet_dims)
specs_list.push(spec)
if ((operation === 'count') && groupby.length === 1) {
specs_list.push(spec)
}
}
return specs_list
}
@ -692,7 +696,9 @@ function prep_specs_summarize (states, groupby, summarize, output) {
spec_encoding = { x: x_encoding, y: y_encoding, color, tooltip }
}
let spec = generate_vega_specs(data, meta, spec_encoding, facet_encoding, facet_dims)
specs_list.push(spec)
if (!((operation === 'count') && groupby.length === 1)) {
specs_list.push(spec)
}
min = states[0]
.map((item) => {
@ -718,7 +724,7 @@ function prep_specs_summarize (states, groupby, summarize, output) {
meta = {
axes: groupby.length > 1,
description: 'Plot ' + operation + ' ' + y_axis + ' of each group'
description: 'Plot ' + operation + ((operation === 'count' || operation === 'sum') && groupby.length === 1 ? '' : ' ' + y_axis) + ' of each group'
}
y_encoding = {
@ -818,8 +824,22 @@ function prep_specs_summarize (states, groupby, summarize, output) {
if (['mean', 'median', 'min', 'max'].includes(operation)) {
meta.custom_animation = operation
}
else if (operation === 'count') {
y_encoding.title = [operation + ' of', y_axis]
else if (operation === 'count' || operation === 'sum') {
if (groupby.length === 1) {
min = data.map((item) => { return item.datamations_y }).reduce((prev, current) => {
return Math.min(prev, current)
})
max = data.map((item) => { return item.datamations_y }).reduce((prev, current) => {
return Math.max(prev, current)
})
meta.custom_animation = operation
y_encoding.scale.domain = [_.round(min, 13), _.round(max, 13)]
delete tooltip[0].title
delete y_encoding.title
}
else {
y_encoding.title = [operation + ' of', y_axis]
}
}
spec_encoding = { x: x_encoding, y: y_encoding, tooltip }
@ -1069,7 +1089,9 @@ function prep_specs_summarize (states, groupby, summarize, output) {
spec_encoding = { x: x_encoding, y: y_encoding, tooltip }
if (groupby.length > 1) spec_encoding = { x: x_encoding, y: y_encoding, color, tooltip }
spec = generate_vega_specs(data, meta, spec_encoding, facet_encoding, facet_dims, operation === 'mean')
specs_list.push(spec)
if (!((operation === 'count' || operation === 'sum') && groupby.length === 1)) {
specs_list.push(spec)
}
return specs_list
}

Просмотреть файл

@ -108,7 +108,8 @@ export function generateGrid (spec, rows = 10, stacked = false) {
specWidth = specWidth / grouped.length
}
const maxCols = Math.ceil(d3.max(specValues, d => d.n) / rows)
const maxCols = specValues[0].n ? Math.ceil(d3.max(specValues, d => d.n) / rows) : specValues.length / rows
let splitOptions = []
if (splitField) {
@ -118,6 +119,7 @@ export function generateGrid (spec, rows = 10, stacked = false) {
}
let counter = 1
var sum = {}
const reduce = (v) => {
const arr = []
@ -167,6 +169,27 @@ export function generateGrid (spec, rows = 10, stacked = false) {
counter++
}
// use sum as the y value
if (!d.n) {
const x = d[CONF.X_FIELD]
const y = d[CONF.Y_FIELD]
if (sum[x]) {
sum[x] = sum[x] + y
}
else {
sum[x] = y
}
arr.push({
...datum,
// ...colorFieldObj,
gemini_id: d.gemini_ids ? d.gemini_ids[i] : counter,
[CONF.X_FIELD]: stacked ? xCenter : x,
[CONF.Y_FIELD]: stacked ? sum[x] : y,
[CONF.Y_FIELD + '_tooltip']: stacked ? sum[x] : y
})
counter++
}
})
return arr

Просмотреть файл

@ -305,7 +305,7 @@ describe('small salary', function () {
fs.readFile('../../../../inst/specs/max_specs_two_columns.json', 'utf8', function (err, fileContents) {
if (err) throw err
max_spec_two_column = JSON.parse(fileContents)
fs.readFile('../../../../inst/specs/sum_specs.json', 'utf8', function (err, fileContents) {
fs.readFile('../../../../sandbox/custom_animations/custom-animations-sum-manual.json', 'utf8', function (err, fileContents) {
if (err) throw err
sum_specs = JSON.parse(fileContents)
fs.readFile('../../../../inst/specs/sum_specs_two_columns.json', 'utf8', function (err, fileContents) {
@ -317,7 +317,7 @@ describe('small salary', function () {
fs.readFile('../../../../inst/specs/prod_specs_two_columns.json', 'utf8', function (err, fileContents) {
if (err) throw err
prod_specs_two_columns = JSON.parse(fileContents)
fs.readFile('../../../../inst/specs/count_specs_one_column.json', 'utf8', function (err, fileContents) {
fs.readFile('../../../../sandbox/custom_animations/custom-animations-count-R.json', 'utf8', function (err, fileContents) {
if (err) throw err
count_spec = JSON.parse(fileContents)
fs.readFile('../../../../inst/specs/count_specs_two_columns.json', 'utf8', function (err, fileContents) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу