├── .DS_Store
├── .gitattributes
├── .gitignore
├── .jshintrc
├── Gruntfile.js
├── README.md
├── app
├── 404.html
├── data
│ ├── Untitled-2.json
│ ├── default0.json
│ ├── default1.json
│ ├── default2.json
│ ├── default3.json
│ ├── default4.json
│ ├── default5.json
│ ├── editor.json
│ ├── enumerate.json
│ ├── fluctuation.json
│ ├── horizontal_unit_column.json
│ ├── maxfill_aspect.json
│ ├── mosaic.json
│ ├── size_sum_notShared.json
│ ├── size_sum_shared.json
│ ├── size_uniform_notShared.json
│ ├── size_uniform_shared.json
│ ├── square_aspect.json
│ ├── squarified.json
│ ├── titanic.csv
│ ├── titanic3.csv
│ ├── titanic_spec1.json
│ ├── titanic_spec2.json
│ ├── titanic_spec3.json
│ ├── titanic_spec4.json
│ ├── titanic_spec_packxy_hierarchy.json
│ ├── titanic_spec_packxy_isolated.json
│ ├── titanic_spec_packxy_mixed.json
│ ├── unit_column_chart.json
│ ├── unit_column_chart_shared.json
│ ├── unit_column_chart_shared_mark.json
│ ├── unit_small_multiple.json
│ └── violin.json
├── favicon.ico
├── images
│ ├── process.png
│ ├── vcd-mosaic.png
│ └── yeoman.png
├── index.html
├── robots.txt
├── scripts
│ ├── app.js
│ ├── controllers
│ │ ├── about.js
│ │ ├── enum.js
│ │ ├── example.js
│ │ ├── live.js
│ │ └── main.js
│ └── services
│ │ ├── treemap-squarify.js
│ │ └── unitchart.js
├── styles
│ └── main.css
└── views
│ ├── enum.html
│ ├── example.html
│ ├── live.html
│ └── main.html
├── bower.json
├── package-lock.json
├── package.json
├── python
├── .ipynb_checkpoints
│ └── data script-checkpoint.ipynb
├── data script.ipynb
└── untitled.txt
└── test
├── .jshintrc
├── karma.conf.js
└── spec
├── controllers
├── about.js
├── enum.js
├── example.js
├── live.js
└── main.js
└── services
└── unitchart.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.swp
3 | .tmp
4 | bower_components
5 | test/bower_components
6 | dist/
7 | .grunt
8 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // JSHint Default Configuration File (as on JSHint website)
3 | // See http://jshint.com/docs/ for more details
4 |
5 | "maxerr" : 50, // {int} Maximum error before stopping
6 |
7 | // Enforcing
8 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
9 | "camelcase" : false, // true: Identifiers must be in camelCase
10 | "curly" : true, // true: Require {} for every new block or scope
11 | "eqeqeq" : true, // true: Require triple equals (===) for comparison
12 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
13 | "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
14 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
15 | "latedef" : false, // true: Require variables/functions to be defined before being used
16 | "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
17 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
18 | "noempty" : true, // true: Prohibit use of empty blocks
19 | "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
20 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
21 | "plusplus" : false, // true: Prohibit use of `++` and `--`
22 | "quotmark" : false, // Quotation mark consistency:
23 | // false : do nothing (default)
24 | // true : ensure whatever is used is consistent
25 | // "single" : require single quotes
26 | // "double" : require double quotes
27 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
28 | "unused" : true, // Unused variables:
29 | // true : all variables, last function parameter
30 | // "vars" : all variables only
31 | // "strict" : all variables, all function parameters
32 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode
33 | "maxparams" : false, // {int} Max number of formal params allowed per function
34 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
35 | "maxstatements" : false, // {int} Max number statements per function
36 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
37 | "maxlen" : false, // {int} Max number of characters per line
38 | "varstmt" : false, // true: Disallow any var statements. Only `let` and `const` are allowed.
39 |
40 | // Relaxing
41 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
42 | "boss" : false, // true: Tolerate assignments where comparisons would be expected
43 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
44 | "eqnull" : false, // true: Tolerate use of `== null`
45 | "esversion" : 5, // {int} Specify the ECMAScript version to which the code must adhere.
46 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
47 | // (ex: `for each`, multiple try/catch, function expression…)
48 | "evil" : false, // true: Tolerate use of `eval` and `new Function()`
49 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
50 | "funcscope" : false, // true: Tolerate defining variables inside control statements
51 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
52 | "iterator" : false, // true: Tolerate using the `__iterator__` property
53 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
54 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
55 | "laxcomma" : false, // true: Tolerate comma-first style coding
56 | "loopfunc" : false, // true: Tolerate functions being defined in loops
57 | "multistr" : false, // true: Tolerate multi-line strings
58 | "noyield" : false, // true: Tolerate generator functions with no yield statement in them.
59 | "notypeof" : false, // true: Tolerate invalid typeof operator values
60 | "proto" : false, // true: Tolerate using the `__proto__` property
61 | "scripturl" : false, // true: Tolerate script-targeted URLs
62 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
63 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
64 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
65 | "validthis" : false, // true: Tolerate using this in a non-constructor function
66 |
67 | // Environments
68 | "browser" : true, // Web Browser (window, document, etc)
69 | "browserify" : false, // Browserify (node.js code in the browser)
70 | "couch" : false, // CouchDB
71 | "devel" : true, // Development/debugging (alert, confirm, etc)
72 | "dojo" : false, // Dojo Toolkit
73 | "jasmine" : false, // Jasmine
74 | "jquery" : false, // jQuery
75 | "mocha" : true, // Mocha
76 | "mootools" : false, // MooTools
77 | "node" : false, // Node.js
78 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
79 | "phantom" : false, // PhantomJS
80 | "prototypejs" : false, // Prototype and Scriptaculous
81 | "qunit" : false, // QUnit
82 | "rhino" : false, // Rhino
83 | "shelljs" : false, // ShellJS
84 | "typed" : false, // Globals for typed array constructions
85 | "worker" : false, // Web Workers
86 | "wsh" : false, // Windows Scripting Host
87 | "yui" : false, // Yahoo User Interface
88 |
89 | // Custom Globals
90 | "globals" : {} // additional predefined global variables
91 | }
92 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Generated on 2016-08-23 using generator-angular 0.15.1
2 | 'use strict';
3 |
4 | // # Globbing
5 | // for performance reasons we're only matching one level down:
6 | // 'test/spec/{,*/}*.js'
7 | // use this if you want to recursively match all subfolders:
8 | // 'test/spec/**/*.js'
9 |
10 | module.exports = function(grunt) {
11 |
12 | // Time how long tasks take. Can help when optimizing build times
13 | require('time-grunt')(grunt);
14 |
15 | // Automatically load required Grunt tasks
16 | require('jit-grunt')(grunt, {
17 | useminPrepare: 'grunt-usemin',
18 | ngtemplates: 'grunt-angular-templates',
19 | cdnify: 'grunt-google-cdn'
20 | });
21 |
22 | // grunt.loadNpmTasks('grunt-gh-pages');
23 |
24 | // Configurable paths for the application
25 | var appConfig = {
26 | app: require('./bower.json').appPath || 'app',
27 | dist: 'dist'
28 | };
29 |
30 | // Define the configuration for all the tasks
31 | grunt.initConfig({
32 |
33 | // Project settings
34 | yeoman: appConfig,
35 |
36 | // Watches files for changes and runs tasks based on the changed files
37 |
38 | 'gh-pages': {
39 | options: {
40 | base: 'dist'
41 | },
42 | src: ['**']
43 | },
44 | watch: {
45 | bower: {
46 | files: ['bower.json'],
47 | tasks: ['wiredep']
48 | },
49 | js: {
50 | files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
51 | tasks: ['newer:jshint:all', 'newer:jscs:all'],
52 | options: {
53 | livereload: '<%= connect.options.livereload %>'
54 | }
55 | },
56 | jsTest: {
57 | files: ['test/spec/{,*/}*.js'],
58 | tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
59 | },
60 | styles: {
61 | files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
62 | tasks: ['newer:copy:styles', 'postcss']
63 | },
64 | gruntfile: {
65 | files: ['Gruntfile.js']
66 | },
67 | livereload: {
68 | options: {
69 | livereload: '<%= connect.options.livereload %>'
70 | },
71 | files: [
72 | '<%= yeoman.app %>/{,*/}*.html',
73 | '.tmp/styles/{,*/}*.css',
74 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
75 | ]
76 | }
77 | },
78 | // The actual grunt server settings
79 | connect: {
80 | options: {
81 | port: 9000,
82 | // Change this to '0.0.0.0' to access the server from outside.
83 | hostname: 'localhost',
84 | livereload: 35729
85 | },
86 | livereload: {
87 | options: {
88 | open: true,
89 | middleware: function(connect) {
90 | return [
91 | connect.static('.tmp'),
92 | connect().use(
93 | '/bower_components',
94 | connect.static('./bower_components')
95 | ),
96 | connect().use(
97 | '/app/styles',
98 | connect.static('./app/styles')
99 | ),
100 | connect.static(appConfig.app)
101 | ];
102 | }
103 | }
104 | },
105 | test: {
106 | options: {
107 | port: 9001,
108 | middleware: function(connect) {
109 | return [
110 | connect.static('.tmp'),
111 | connect.static('test'),
112 | connect().use(
113 | '/bower_components',
114 | connect.static('./bower_components')
115 | ),
116 | connect.static(appConfig.app)
117 | ];
118 | }
119 | }
120 | },
121 | dist: {
122 | options: {
123 | open: true,
124 | base: '<%= yeoman.dist %>'
125 | }
126 | }
127 | },
128 |
129 | // Make sure there are no obvious mistakes
130 | jshint: {
131 | options: {
132 | jshintrc: '.jshintrc',
133 | reporter: require('jshint-stylish')
134 | },
135 | all: {
136 | src: [
137 | 'Gruntfile.js',
138 | '<%= yeoman.app %>/scripts/{,*/}*.js'
139 | ]
140 | },
141 | test: {
142 | options: {
143 | jshintrc: 'test/.jshintrc'
144 | },
145 | src: ['test/spec/{,*/}*.js']
146 | }
147 | },
148 |
149 | // Make sure code styles are up to par
150 | jscs: {
151 | options: {
152 | config: '.jscsrc',
153 | verbose: true
154 | },
155 | all: {
156 | src: [
157 | 'Gruntfile.js',
158 | '<%= yeoman.app %>/scripts/{,*/}*.js'
159 | ]
160 | },
161 | test: {
162 | src: ['test/spec/{,*/}*.js']
163 | }
164 | },
165 |
166 | // Empties folders to start fresh
167 | clean: {
168 | dist: {
169 | files: [{
170 | dot: true,
171 | src: [
172 | '.tmp',
173 | '<%= yeoman.dist %>/{,*/}*',
174 | '!<%= yeoman.dist %>/.git{,*/}*'
175 | ]
176 | }]
177 | },
178 | server: '.tmp'
179 | },
180 |
181 | // Add vendor prefixed styles
182 | postcss: {
183 | options: {
184 | processors: [
185 | require('autoprefixer-core')({
186 | browsers: ['last 1 version']
187 | })
188 | ]
189 | },
190 | server: {
191 | options: {
192 | map: true
193 | },
194 | files: [{
195 | expand: true,
196 | cwd: '.tmp/styles/',
197 | src: '{,*/}*.css',
198 | dest: '.tmp/styles/'
199 | }]
200 | },
201 | dist: {
202 | files: [{
203 | expand: true,
204 | cwd: '.tmp/styles/',
205 | src: '{,*/}*.css',
206 | dest: '.tmp/styles/'
207 | }]
208 | }
209 | },
210 |
211 | // Automatically inject Bower components into the app
212 | wiredep: {
213 | app: {
214 | src: ['<%= yeoman.app %>/index.html'],
215 | ignorePath: /\.\.\//
216 | },
217 | test: {
218 | devDependencies: true,
219 | src: '<%= karma.unit.configFile %>',
220 | ignorePath: /\.\.\//,
221 | fileTypes: {
222 | js: {
223 | block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
224 | detect: {
225 | js: /'(.*\.js)'/gi
226 | },
227 | replace: {
228 | js: '\'{{filePath}}\','
229 | }
230 | }
231 | }
232 | }
233 | },
234 |
235 | // Renames files for browser caching purposes
236 | filerev: {
237 | dist: {
238 | src: [
239 | '<%= yeoman.dist %>/scripts/{,*/}*.js',
240 | '<%= yeoman.dist %>/styles/{,*/}*.css',
241 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
242 | '<%= yeoman.dist %>/styles/fonts/*'
243 | ]
244 | }
245 | },
246 |
247 | // Reads HTML for usemin blocks to enable smart builds that automatically
248 | // concat, minify and revision files. Creates configurations in memory so
249 | // additional tasks can operate on them
250 | useminPrepare: {
251 | html: '<%= yeoman.app %>/index.html',
252 | options: {
253 | dest: '<%= yeoman.dist %>',
254 | flow: {
255 | html: {
256 | steps: {
257 | js: ['concat', 'uglifyjs'],
258 | css: ['cssmin']
259 | },
260 | post: {}
261 | }
262 | }
263 | }
264 | },
265 |
266 | // Performs rewrites based on filerev and the useminPrepare configuration
267 | usemin: {
268 | html: ['<%= yeoman.dist %>/{,*/}*.html'],
269 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
270 | js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
271 | options: {
272 | assetsDirs: [
273 | '<%= yeoman.dist %>',
274 | '<%= yeoman.dist %>/images',
275 | '<%= yeoman.dist %>/styles'
276 | ],
277 | patterns: {
278 | js: [
279 | [/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']
280 | ]
281 | }
282 | }
283 | },
284 |
285 | // The following *-min tasks will produce minified files in the dist folder
286 | // By default, your `index.html`'s will take care of
287 | // minification. These next options are pre-configured if you do not wish
288 | // to use the Usemin blocks.
289 | // cssmin: {
290 | // dist: {
291 | // files: {
292 | // '<%= yeoman.dist %>/styles/main.css': [
293 | // '.tmp/styles/{,*/}*.css'
294 | // ]
295 | // }
296 | // }
297 | // },
298 | // uglify: {
299 | // dist: {
300 | // files: {
301 | // '<%= yeoman.dist %>/scripts/scripts.js': [
302 | // '<%= yeoman.dist %>/scripts/scripts.js'
303 | // ]
304 | // }
305 | // }
306 | // },
307 | // concat: {
308 | // dist: {}
309 | // },
310 |
311 | imagemin: {
312 | dist: {
313 | files: [{
314 | expand: true,
315 | cwd: '<%= yeoman.app %>/images',
316 | src: '{,*/}*.{png,jpg,jpeg,gif}',
317 | dest: '<%= yeoman.dist %>/images'
318 | }]
319 | }
320 | },
321 |
322 | svgmin: {
323 | dist: {
324 | files: [{
325 | expand: true,
326 | cwd: '<%= yeoman.app %>/images',
327 | src: '{,*/}*.svg',
328 | dest: '<%= yeoman.dist %>/images'
329 | }]
330 | }
331 | },
332 |
333 | htmlmin: {
334 | dist: {
335 | options: {
336 | collapseWhitespace: true,
337 | conservativeCollapse: true,
338 | collapseBooleanAttributes: true,
339 | removeCommentsFromCDATA: true
340 | },
341 | files: [{
342 | expand: true,
343 | cwd: '<%= yeoman.dist %>',
344 | src: ['*.html'],
345 | dest: '<%= yeoman.dist %>'
346 | }]
347 | }
348 | },
349 |
350 | ngtemplates: {
351 | dist: {
352 | options: {
353 | module: 'unitApp',
354 | htmlmin: '<%= htmlmin.dist.options %>',
355 | usemin: 'scripts/scripts.js'
356 | },
357 | cwd: '<%= yeoman.app %>',
358 | src: 'views/{,*/}*.html',
359 | dest: '.tmp/templateCache.js'
360 | }
361 | },
362 |
363 | // ng-annotate tries to make the code safe for minification automatically
364 | // by using the Angular long form for dependency injection.
365 | ngAnnotate: {
366 | dist: {
367 | files: [{
368 | expand: true,
369 | cwd: '.tmp/concat/scripts',
370 | src: '*.js',
371 | dest: '.tmp/concat/scripts'
372 | }]
373 | }
374 | },
375 |
376 | // Replace Google CDN references
377 | cdnify: {
378 | dist: {
379 | html: ['<%= yeoman.dist %>/*.html']
380 | }
381 | },
382 |
383 | // Copies remaining files to places other tasks can use
384 | copy: {
385 | dist: {
386 | files: [{
387 | expand: true,
388 | dot: true,
389 | cwd: '<%= yeoman.app %>',
390 | dest: '<%= yeoman.dist %>',
391 | src: [
392 | '*.{ico,png,txt}',
393 | '*.html',
394 | 'images/{,*/}*.{webp}',
395 | 'styles/fonts/{,*/}*.*',
396 | 'data/{,*/}*.*'
397 | ]
398 | }, {
399 | expand: true,
400 | cwd: '.tmp/images',
401 | dest: '<%= yeoman.dist %>/images',
402 | src: ['generated/*']
403 | },{
404 | expand: true,
405 | cwd: 'bower_components/jsoneditor/dist',
406 | src: 'img/*',
407 | dest: '<%= yeoman.dist %>'
408 | },{
409 | expand: true,
410 | cwd: 'bower_components/jsoneditor/dist',
411 | src: 'img/*',
412 | dest: '<%= yeoman.dist %>/styles'
413 | },
414 | {
415 | expand: true,
416 | cwd: '.tmp/images',
417 | dest: '<%= yeoman.dist %>/images',
418 | src: ['generated/*']
419 | }, {
420 | expand: true,
421 | cwd: 'bower_components/bootstrap/dist',
422 | src: 'fonts/*',
423 | dest: '<%= yeoman.dist %>'
424 | }]
425 | },
426 | styles: {
427 | expand: true,
428 | cwd: '<%= yeoman.app %>/styles',
429 | dest: '.tmp/styles/',
430 | src: '{,*/}*.css'
431 | }
432 | },
433 |
434 | // Run some tasks in parallel to speed up the build process
435 | concurrent: {
436 | server: [
437 | 'copy:styles'
438 | ],
439 | test: [
440 | 'copy:styles'
441 | ],
442 | dist: [
443 | 'copy:styles',
444 | 'imagemin',
445 | 'svgmin'
446 | ]
447 | },
448 |
449 | // Test settings
450 | karma: {
451 | unit: {
452 | configFile: 'test/karma.conf.js',
453 | singleRun: true
454 | }
455 | }
456 | });
457 |
458 |
459 |
460 | grunt.registerTask('serve', 'Compile then start a connect web server', function(target) {
461 | if (target === 'dist') {
462 | return grunt.task.run(['build', 'connect:dist:keepalive']);
463 | }
464 |
465 | grunt.task.run([
466 | 'clean:server',
467 | 'wiredep',
468 | 'concurrent:server',
469 | 'postcss:server',
470 | 'connect:livereload',
471 | 'watch'
472 | ]);
473 | });
474 |
475 | grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function(target) {
476 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
477 | grunt.task.run(['serve:' + target]);
478 | });
479 |
480 | grunt.registerTask('test', [
481 | 'clean:server',
482 | 'wiredep',
483 | 'concurrent:test',
484 | 'postcss',
485 | 'connect:test',
486 | 'karma'
487 | ]);
488 |
489 | grunt.registerTask('build', [
490 | 'clean:dist',
491 | 'wiredep',
492 | 'useminPrepare',
493 | 'concurrent:dist',
494 | 'postcss',
495 | 'ngtemplates',
496 | 'concat',
497 | 'ngAnnotate',
498 | 'copy:dist',
499 | 'cdnify',
500 | 'cssmin',
501 | 'uglify',
502 | 'filerev',
503 | 'usemin',
504 | 'htmlmin'
505 | ]);
506 |
507 | grunt.registerTask('default', [
508 | //'newer:jshint',
509 | 'newer:jscs',
510 | 'test',
511 | 'build'
512 | ]);
513 | };
514 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # unit
2 |
3 | This project is generated with [yo angular generator](https://github.com/yeoman/generator-angular)
4 | version 0.15.1.
5 |
6 | ## Build & development
7 |
8 | Run `grunt` for building and `grunt serve` for preview.
9 |
10 | ## Testing
11 |
12 | Running `grunt test` will run the unit tests with karma.
13 |
--------------------------------------------------------------------------------
/app/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found :(
6 |
136 |
137 |
138 |
139 |
Not found :(
140 |
Sorry, but the page you were trying to view does not exist.
141 |
It looks like this was the result of either:
142 |
143 | a mistyped address
144 | an out-of-date link
145 |
146 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/app/data/Untitled-2.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://vega.github.io/schema/vega-lite/v2.json",
3 | "description": "A simple bar chart with embedded data.",
4 | "data": {
5 | "values": [
6 | {"a": "A","b": 28}, {"a": "B","b": 55}, {"a": "C","b": 43},
7 | {"a": "D","b": 91}, {"a": "E","b": 81}, {"a": "F","b": 53},
8 | {"a": "G","b": 19}, {"a": "H","b": 87}, {"a": "I","b": 52}
9 | ]
10 | },
11 | "mark": "bar",
12 | "encoding": {
13 | "x": {"field": "a", "type": "ordinal"},
14 | "y": {"field": "b", "type": "quantitative"}
15 | }
16 | }
--------------------------------------------------------------------------------
/app/data/default0.json:
--------------------------------------------------------------------------------
1 | {
2 | // This is an empty json spec.
3 | // For grammar is about specification.
4 | }
5 |
--------------------------------------------------------------------------------
/app/data/default1.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": "data/titanic3.csv",
3 | "layouts": [
4 | {
5 | "subgroup": {
6 | "type": "flatten"
7 | }
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/app/data/default2.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": "data/titanic3.csv",
3 | "layouts": [
4 | {
5 | "subgroup": {
6 | "type": "flatten"
7 | }
8 | }
9 | ],
10 | "mark": {
11 | "color": {
12 | "key": "survived_text",
13 | "type": "categorical"
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/app/data/default3.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": "data/titanic3.csv",
3 | "layouts": [
4 | {
5 | "subgroup": {
6 | "type": "groupby",
7 | "key": "pclass"
8 | },
9 | "aspect_ratio": "fillX"
10 | },
11 |
12 | {
13 | "subgroup": {
14 | "type": "flatten"
15 | },
16 | "aspect_ratio": "maxfill"
17 | }
18 | ],
19 | "mark": {
20 | "color": {
21 | "key": "survived_text",
22 | "type": "categorical"
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/app/data/default4.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": "data/titanic3.csv",
3 | "layouts": [
4 | {
5 | "subgroup": {
6 | "type": "groupby",
7 | "key": "pclass"
8 | },
9 | "aspect_ratio": "fillX"
10 | },
11 | {
12 | "subgroup": {
13 | "type": "bin",
14 | "key": "age",
15 | "numBin": 10
16 | },
17 | "aspect_ratio": "fillY"
18 | },
19 |
20 | {
21 | "subgroup": {
22 | "type": "flatten"
23 | },
24 | "aspect_ratio": "maxfill"
25 | }
26 | ],
27 | "mark": {
28 | "color": {
29 | "key": "survived_text",
30 | "type": "categorical"
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/data/default5.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": "data/titanic3.csv",
3 | "layouts": [{
4 | "subgroup": {
5 | "type": "groupby",
6 | "key": "pclass"
7 | },
8 | "aspect_ratio": "fillX"
9 | },
10 | {
11 | "subgroup": {
12 | "type": "bin",
13 | "key": "age",
14 | "numBin": 20
15 | },
16 | "aspect_ratio": "fillY"
17 | },
18 | {
19 | "subgroup": {
20 | "type": "passthrough"
21 | },
22 | "aspect_ratio": "fillX",
23 | "size": {
24 | "type": "count"
25 | },
26 | "align": "center"
27 | },
28 | {
29 | "subgroup": {
30 | "type": "flatten"
31 | },
32 | "aspect_ratio": "maxfill",
33 | "size": {
34 | "isShared": false
35 | }
36 | }
37 | ],
38 | "mark": {
39 | "color": {
40 | "key": "survived_text",
41 | "type": "categorical"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/data/editor.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 1000,
5 | "height": 320,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": true
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | },
45 | "sort": {
46 | "key": "pclass",
47 | "direction": "ascending"
48 | }
49 | }, {
50 | "name": "layout2",
51 | "type": "gridxy",
52 | "subgroup": {
53 | "type": "bin",
54 | "key": "age",
55 | "numBin": 19,
56 | "isShared": true
57 | },
58 | "aspect_ratio": "fillY",
59 | "size": {
60 | "type": "uniform",
61 | "isShared": true
62 | },
63 | "direction": "BT",
64 | "align": "bottom",
65 | "margin": {
66 | "top": 0,
67 | "left": 0,
68 | "bottom": 0,
69 | "right": 0
70 | },
71 | "padding": {
72 | "top": 0,
73 | "left": 0,
74 | "bottom": 0,
75 | "right": 0
76 | },
77 | "box": {
78 | "fill": "green",
79 | "stroke": "red",
80 | "stroke-width": 1,
81 | "opacity": 0.5
82 | },
83 | "sort": {
84 | "key": "age",
85 | "direction": "ascending"
86 | }
87 | }, {
88 | "name": "layout3",
89 | "type": "gridxy",
90 | "subgroup": {
91 | "type": "passthrough",
92 | "isShared": true
93 | },
94 | "aspect_ratio": "fillX",
95 | "size": {
96 | "type": "count",
97 | "isShared": true
98 | },
99 | "direction": "LR",
100 | "align": "center",
101 | "margin": {
102 | "top": 0,
103 | "left": 0,
104 | "bottom": 0,
105 | "right": 0
106 | },
107 | "padding": {
108 | "top": 0,
109 | "left": 0,
110 | "bottom": 0,
111 | "right": 0
112 | },
113 | "box": {
114 | "fill": "yellow",
115 | "stroke": "blue",
116 | "stroke-width": 1,
117 | "opacity": 0.5
118 | }
119 | }, {
120 | "name": "layout4",
121 | "type": "gridxy",
122 | "subgroup": {
123 | "type": "flatten"
124 | },
125 | "aspect_ratio": "maxfill",
126 | "size": {
127 | "type": "uniform",
128 | "isShared": false
129 | },
130 | "direction": "BTLR",
131 | "align": "LB",
132 | "margin": {
133 | "top": 0,
134 | "left": 0,
135 | "bottom": 0,
136 | "right": 0
137 | },
138 | "padding": {
139 | "top": 0,
140 | "left": 0,
141 | "bottom": 0,
142 | "right": 0
143 | },
144 | "box": {
145 | "fill": "yellow",
146 | "stroke": "red",
147 | "stroke-width": 0,
148 | "opacity": 0.5
149 | },
150 | "sort": {
151 | "type": "categorical",
152 | "key": "survived",
153 | "direction": "ascending"
154 | }
155 | }],
156 | "mark": {
157 | "shape": "circle",
158 | "color": {
159 | "key": "survived",
160 | "type": "categorical"
161 | },
162 | "size": {
163 | "type": "max",
164 | "isShared": false
165 | },
166 | "isColorScaleShared": true
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/app/data/enumerate.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 640,
5 | "height": 480,
6 | "padding": {
7 | "top": 0,
8 | "left": 0,
9 | "bottom": 0,
10 | "right": 0
11 | },
12 | "layouts": [],
13 | "mark": {
14 | "shape": "circle",
15 | "color": {
16 | "key": "survived",
17 | "type": "categorical",
18 | "isShared": true
19 | },
20 | "size": {
21 | "type": "max",
22 | "isShared": false
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/data/fluctuation.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 800,
5 | "height": 600,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "Sex",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 0,
29 | "left": 0,
30 | "bottom": 0,
31 | "right": 0
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "groupby",
44 | "key": "Class",
45 | "isShared": true
46 | },
47 | "aspect_ratio": "fillX",
48 | "size": {
49 | "type": "uniform",
50 | "isShared": true
51 | },
52 | "direction": "LRTB",
53 | "align": "LB",
54 | "margin": {
55 | "top": 5,
56 | "left": 5,
57 | "bottom": 5,
58 | "right": 5
59 | },
60 | "padding": {
61 | "top": 5,
62 | "left": 5,
63 | "bottom": 5,
64 | "right": 5
65 | }
66 | }, {
67 | "name": "layout3",
68 | "type": "gridxy",
69 | "subgroup": {
70 | "type": "passthrough",
71 | "isShared": true
72 | },
73 | "aspect_ratio": "square",
74 | "size": {
75 | "type": "count",
76 | "isShared": true
77 | },
78 | "direction": "LRBT",
79 | "align": "center",
80 | "margin": {
81 | "top": 1,
82 | "left": 1,
83 | "bottom": 1,
84 | "right": 1
85 | },
86 | "padding": {
87 | "top": 2,
88 | "left": 2,
89 | "bottom": 2,
90 | "right": 2
91 | },
92 | "box": {
93 | "fill": "none",
94 | "stroke": "black",
95 | "stroke-width": 0,
96 | "opacity": 0.3
97 | }
98 | },{
99 | "name": "layout4",
100 | "type": "gridxy",
101 | "subgroup": {
102 | "type": "flatten"
103 | },
104 | "aspect_ratio": "maxfill",
105 | "size": {
106 | "type": "uniform",
107 | "isShared": false
108 | },
109 | "direction": "LRBT",
110 | "align": "LB",
111 | "margin": {
112 | "top": 5,
113 | "left": 5,
114 | "bottom": 5,
115 | "right": 5
116 | },
117 | "padding": {
118 | "top": 5,
119 | "left": 5,
120 | "bottom": 5,
121 | "right": 5
122 | },
123 | "sort": {
124 | "key": "Survived"
125 | }
126 | }],
127 | "mark": {
128 | "shape": "circle",
129 | "color": {
130 | "key": "Survived",
131 | "type": "categorical"
132 | },
133 | "size": {
134 | "type": "max",
135 | "isShared": false
136 | },
137 | "isColorScaleShared": true
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/app/data/horizontal_unit_column.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type":"groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": true
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type":"flatten"
50 | },
51 | "aspect_ratio": "maxfill",
52 | "size": {
53 | "type": "uniform",
54 | "isShared": true
55 | },
56 | "direction": "BTLR",
57 | "align": "LT",
58 | "margin": {
59 | "top": 0,
60 | "left": 0,
61 | "bottom": 0,
62 | "right": 0
63 | },
64 | "padding": {
65 | "top": 0,
66 | "left": 0,
67 | "bottom": 0,
68 | "right": 0
69 | },
70 | "box": {
71 | "fill": "white",
72 | "stroke": "red",
73 | "stroke-width": 0,
74 | "opacity": 0.5
75 | },
76 | "sort":{
77 | "key":"survived"
78 | }
79 | }],
80 | "mark": {
81 | "shape": "circle",
82 | "color": {
83 | "key":"survived",
84 | "type":"categorical"
85 | },
86 | "size": {
87 | "type": "max",
88 | "isShared": false
89 | },
90 | "isColorScaleShared": true
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/data/maxfill_aspect.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 500,
5 | "height": 240,
6 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "subgroup": {
12 | "key": "age",
13 | "type": "bin",
14 | "numBin": 15,
15 | "isShared": false
16 | },
17 | "aspect_ratio":"parent",
18 | "size": {
19 | "type":"uniform",
20 | "isShared": false
21 | },
22 | "direction": "LRBT",
23 | "align": "LB",
24 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
25 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
26 | "box": {
27 | "fill": "none",
28 | "stroke": "black",
29 | "stroke-width": 0,
30 | "opacity":0.3
31 | }
32 | },
33 | {
34 | "name": "layout2",
35 | "type": "gridxy",
36 | "subgroup": {
37 | "type":"groupby",
38 | "key": "pclass",
39 | "isShared": false
40 | },
41 | "aspect_ratio":"fillX",
42 | "size": {
43 | "type": "uniform",
44 | "isShared": false
45 | },
46 | "direction": "LRTB",
47 | "align": "LB",
48 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
49 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
50 | "box": {
51 | "fill": "none",
52 | "stroke": "green",
53 | "stroke-width": 1,
54 | "opacity":1
55 | }
56 | },
57 | {
58 | "name": "layout3",
59 | "type": "gridxy",
60 | "subgroup": {
61 | "type":"flatten"
62 | },
63 | "aspect_ratio":"maxfill",
64 | "size": {
65 | "type":"uniform",
66 | "isShared": false
67 | },
68 | "direction": "LRBT",
69 | "align": "LB",
70 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
71 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
72 | "box": {
73 | "fill": "none",
74 | "stroke": "black",
75 | "stroke-width": 1,
76 | "opacity":1
77 | },
78 | "sort":{
79 | "key":"survived"
80 | }
81 | }],
82 | "mark": {
83 | "shape": "circle",
84 | "color": {
85 | "key":"survived",
86 | "type":"categorical"
87 | },
88 | "size": {
89 | "type": "max",
90 | "isShared": false
91 | },
92 | "isColorScaleShared": true
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/data/mosaic.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 840,
5 | "height": 840,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "count",
23 | "isShared": true
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 1,
29 | "left": 1,
30 | "bottom": 1,
31 | "right": 1
32 | },
33 | "padding": {
34 | "top": 2,
35 | "left": 2,
36 | "bottom": 2,
37 | "right": 2
38 | },
39 | "box": {
40 | "fill": "none",
41 | "stroke": "black",
42 | "stroke-width": 0,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type": "groupby",
50 | "key": "survived",
51 | "isShared": true
52 | },
53 | "aspect_ratio": "fillX",
54 | "size": {
55 | "type": "count",
56 | "isShared": false
57 | },
58 | "direction": "LRBT",
59 | "align": "LB",
60 | "margin": {
61 | "top": 1,
62 | "left": 1,
63 | "bottom": 1,
64 | "right": 1
65 | },
66 | "padding": {
67 | "top": 1,
68 | "left": 1,
69 | "bottom": 1,
70 | "right": 1
71 | },
72 | "box": {
73 | "fill": "none",
74 | "stroke": "black",
75 | "stroke-width": 0,
76 | "opacity": 0.3
77 | }
78 | }, {
79 | "name": "layout3",
80 | "type": "gridxy",
81 | "subgroup": {
82 | "type": "groupby",
83 | "key": "sex",
84 | "isShared": true
85 | },
86 | "aspect_ratio": "fillY",
87 | "size": {
88 | "type": "count",
89 | "isShared": false
90 | },
91 | "direction": "LRBT",
92 | "align": "LB",
93 | "margin": {
94 | "top": 3,
95 | "left": 3,
96 | "bottom": 3,
97 | "right": 3
98 | },
99 | "padding": {
100 | "top": 1,
101 | "left": 1,
102 | "bottom": 1,
103 | "right": 1
104 | },
105 | "box": {
106 | "fill": "blue",
107 | "stroke": "red",
108 | "stroke-width": 3,
109 | "opacity": 0.3
110 | }
111 | }, {
112 | "name": "layout4",
113 | "type": "gridxy",
114 | "subgroup": {
115 | "type": "flatten"
116 | },
117 | "aspect_ratio": "maxfill",
118 | "size": {
119 | "type": "uniform",
120 | "isShared": false
121 | },
122 | "direction": "LRBT",
123 | "align": "LT",
124 | "margin": {
125 | "top": 0,
126 | "left": 0,
127 | "bottom": 0,
128 | "right": 0
129 | },
130 | "padding": {
131 | "top": 0,
132 | "left": 0,
133 | "bottom": 0,
134 | "right": 0
135 | },
136 | "box": {
137 | "fill": "blue",
138 | "stroke": "red",
139 | "stroke-width": 0,
140 | "opacity": 0.01
141 | }
142 | }],
143 | "mark": {
144 | "shape": "circle",
145 | "color": {
146 | "key": "survived",
147 | "type": "categorical"
148 | },
149 | "size": {
150 | "type": "max",
151 | "isShared": false
152 | },
153 | "isColorScaleShared": true
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/app/data/size_sum_notShared.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type": "flatten"
50 | },
51 | "aspect_ratio": "fillY",
52 | "size": {
53 | "type": "sum",
54 | "key":"fare",
55 | "isShared": false
56 | },
57 | "direction": "LRTB",
58 | "align": "LB",
59 | "margin": {
60 | "top": 0,
61 | "left": 0,
62 | "bottom": 0,
63 | "right": 0
64 | },
65 | "padding": {
66 | "top": 0,
67 | "left": 0,
68 | "bottom": 0,
69 | "right": 0
70 | },
71 | "box": {
72 | "fill": "green",
73 | "stroke": "green",
74 | "stroke-width": 0,
75 | "opacity": 0.5
76 | },
77 | "sort": {
78 | "key":"fare",
79 | "type":"numerical"
80 | }
81 | }],
82 | "mark": {
83 | "shape": "circle",
84 | "color": {
85 | "key": "survived",
86 | "type": "categorical"
87 | },
88 | "size": {
89 | "type": "max",
90 | "isShared": false
91 | },
92 | "isColorScaleShared": true
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/data/size_sum_shared.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type": "flatten"
50 | },
51 | "aspect_ratio": "fillY",
52 | "size": {
53 | "type": "sum",
54 | "key":"fare",
55 | "isShared": true
56 | },
57 | "direction": "LRTB",
58 | "align": "LB",
59 | "margin": {
60 | "top": 0,
61 | "left": 0,
62 | "bottom": 0,
63 | "right": 0
64 | },
65 | "padding": {
66 | "top": 0,
67 | "left": 0,
68 | "bottom": 0,
69 | "right": 0
70 | },
71 | "box": {
72 | "fill": "green",
73 | "stroke": "green",
74 | "stroke-width": 0,
75 | "opacity": 0.5
76 | },
77 | "sort": {
78 | "key":"fare",
79 | "type":"numerical"
80 | }
81 | }],
82 | "mark": {
83 | "shape": "circle",
84 | "color": {
85 | "key": "survived",
86 | "type": "categorical"
87 | },
88 | "size": {
89 | "type": "max",
90 | "isShared": false
91 | },
92 | "isColorScaleShared": true
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/data/size_uniform_notShared.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type": "flatten"
50 | },
51 | "aspect_ratio": "fillY",
52 | "size": {
53 | "type": "uniform",
54 | "isShared": false
55 | },
56 | "direction": "LRTB",
57 | "align": "LB",
58 | "margin": {
59 | "top": 0,
60 | "left": 0,
61 | "bottom": 0,
62 | "right": 0
63 | },
64 | "padding": {
65 | "top": 0,
66 | "left": 0,
67 | "bottom": 0,
68 | "right": 0
69 | },
70 | "box": {
71 | "fill": "green",
72 | "stroke": "green",
73 | "stroke-width": 0,
74 | "opacity": 0.5
75 | },
76 | "sort": {
77 | "key":"fare",
78 | "type":"numerical"
79 | }
80 | }],
81 | "mark": {
82 | "shape": "circle",
83 | "color": {
84 | "key": "survived",
85 | "type": "categorical"
86 | },
87 | "size": {
88 | "type": "max",
89 | "isShared": false
90 | },
91 | "isColorScaleShared": true
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/data/size_uniform_shared.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "blue",
41 | "stroke": "black",
42 | "stroke-width": 1,
43 | "opacity": 0.3
44 | }
45 | }, {
46 | "name": "layout2",
47 | "type": "gridxy",
48 | "subgroup": {
49 | "type": "flatten"
50 | },
51 | "aspect_ratio": "fillY",
52 | "size": {
53 | "type": "uniform",
54 | "isShared": true
55 | },
56 | "direction": "LRTB",
57 | "align": "LB",
58 | "margin": {
59 | "top": 0,
60 | "left": 0,
61 | "bottom": 0,
62 | "right": 0
63 | },
64 | "padding": {
65 | "top": 0,
66 | "left": 0,
67 | "bottom": 0,
68 | "right": 0
69 | },
70 | "box": {
71 | "fill": "green",
72 | "stroke": "green",
73 | "stroke-width": 0,
74 | "opacity": 0.5
75 | },
76 | "sort": {
77 | "key":"fare",
78 | "type":"numerical"
79 | }
80 | }],
81 | "mark": {
82 | "shape": "circle",
83 | "color": {
84 | "key": "survived",
85 | "type": "categorical"
86 | },
87 | "size": {
88 | "type": "max",
89 | "isShared": false
90 | },
91 | "isColorScaleShared": true
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/data/square_aspect.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 500,
5 | "height": 240,
6 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "subgroup": {
12 | "key": "age",
13 | "type": "bin",
14 | "numBin": 15,
15 | "isShared": false
16 | },
17 | "aspect_ratio":"parent",
18 | "size": {
19 | "type":"uniform",
20 | "isShared": false
21 | },
22 | "direction": "LRBT",
23 | "align": "LB",
24 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
25 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
26 | "box": {
27 | "fill": "none",
28 | "stroke": "black",
29 | "stroke-width": 0,
30 | "opacity":0.3
31 | }
32 | },
33 | {
34 | "name": "layout2",
35 | "type": "gridxy",
36 | "subgroup": {
37 | "type":"groupby",
38 | "key": "pclass",
39 | "isShared": false
40 | },
41 | "aspect_ratio":"fillX",
42 | "size": {
43 | "type": "uniform",
44 | "isShared": false
45 | },
46 | "direction": "LRTB",
47 | "align": "LB",
48 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
49 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
50 | "box": {
51 | "fill": "none",
52 | "stroke": "green",
53 | "stroke-width": 1,
54 | "opacity":0.5
55 | }
56 | },
57 | {
58 | "name": "layout3",
59 | "type": "gridxy",
60 | "subgroup": {
61 | "type":"flatten"
62 | },
63 | "aspect_ratio":"square",
64 | "size": {
65 | "type":"uniform",
66 | "isShared": false
67 | },
68 | "direction": "LRBT",
69 | "align": "LB",
70 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
71 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
72 | "box": {
73 | "fill": "none",
74 | "stroke": "black",
75 | "stroke-width": 1,
76 | "opacity":1
77 | },
78 | "sort":{
79 | "key":"survived"
80 | }
81 | }],
82 | "mark": {
83 | "shape": "circle",
84 | "color": {
85 | "key":"survived",
86 | "type":"categorical"
87 | },
88 | "size": {
89 | "type": "max",
90 | "isShared": false
91 | },
92 | "isColorScaleShared": true
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/data/squarified.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 1000,
5 | "height": 320,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": true
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "white",
41 | "stroke": "black",
42 | "stroke-width": 0,
43 | "opacity": 0.3
44 | },
45 | "sort": {
46 | "key": "pclass",
47 | "direction": "ascending"
48 | }
49 | }, {
50 | "name": "layout2",
51 | "type": "gridxy",
52 | "subgroup": {
53 | "type": "passthrough",
54 | "isShared": true
55 | },
56 | "aspect_ratio": "fillY",
57 | "size": {
58 | "type": "sum",
59 | "key":"fare",
60 | "isShared": true
61 | },
62 | "direction": "BT",
63 | "align": "bottom",
64 | "margin": {
65 | "top": 0,
66 | "left": 0,
67 | "bottom": 0,
68 | "right": 0
69 | },
70 | "padding": {
71 | "top": 0,
72 | "left": 0,
73 | "bottom": 0,
74 | "right": 0
75 | },
76 | "box": {
77 | "fill": "white",
78 | "stroke": "black",
79 | "stroke-width": 0.5,
80 | "opacity": 0.5
81 | },
82 | "sort": {
83 | "key": "age",
84 | "direction": "ascending"
85 | }
86 | }, {
87 | "name": "layout4",
88 | "type": "gridxy",
89 | "subgroup": {
90 | "type": "flatten"
91 | },
92 | "aspect_ratio": "maxfill",
93 | "size": {
94 | "type": "sum",
95 | "key": "fare",
96 | "isShared": true
97 | },
98 | "direction": "LRBT",
99 | "align": "LB",
100 | "margin": {
101 | "top": 0,
102 | "left": 0,
103 | "bottom": 0,
104 | "right": 0
105 | },
106 | "padding": {
107 | "top": 0,
108 | "left": 0,
109 | "bottom": 0,
110 | "right": 0
111 | },
112 | "box": {
113 | "fill": "white",
114 | "stroke": "red",
115 | "stroke-width": 0,
116 | "opacity": 0.5
117 | },
118 | "sort": {
119 | "type": "categorical",
120 | "key": "survived",
121 | "direction": "ascending"
122 | }
123 | }],
124 | "mark": {
125 | "shape": "circle",
126 | "color": {
127 | "key": "survived_text",
128 | "type": "categorical"
129 | },
130 | "size": {
131 | "type": "max",
132 | "isShared": false
133 | },
134 | "isColorScaleShared": true
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/app/data/titanic_spec1.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 1000,
5 | "height": 480,
6 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "groupby": {
12 | "key": "Class",
13 | "isKeyShared": true
14 | },
15 | "aspect_ratio":"fillX",
16 | "size": {
17 | "type":"uniform",
18 | "isShared": false
19 | },
20 | "direction": "LRBT",
21 | "align": "LB",
22 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
23 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
24 | },
25 | {
26 | "name": "layout2",
27 | "type": "gridxy",
28 | "groupby": {
29 | "key": "Sex",
30 | "isKeyShared": true
31 | },
32 | "aspect_ratio":"fillY",
33 | "size": {
34 | "type": "uniform",
35 | "isShared": false
36 | },
37 | "direction": "LRBT",
38 | "align": "LB",
39 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
40 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
41 | },
42 | {
43 | "name": "layout3",
44 | "type": "gridxy",
45 | "groupby": {
46 | "key": "id",
47 | "isKeyShared": false
48 | },
49 | "aspect_ratio":"fillX",
50 | "size": {
51 | "type":"uniform",
52 | "isShare": false
53 | },
54 | "direction": "LRBT",
55 | "align": "LB",
56 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
57 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
58 | }],
59 | "mark": {
60 | "shape": "circle",
61 | "color": "survival",
62 | "size": {
63 | "type": "max",
64 | "isShared": false
65 | },
66 | "isColorScaleShared": true
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/data/titanic_spec2.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 1000,
5 | "height": 480,
6 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "groupby": {
12 | "key": "Class",
13 | "isKeyShared": true
14 | },
15 | "aspect_ratio":"fillX",
16 | "size": {
17 | "type":"uniform",
18 | "isShared": false
19 | },
20 | "direction": "LRBT",
21 | "align": "LB",
22 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
23 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
24 | },
25 | {
26 | "name": "layout2",
27 | "type": "gridxy",
28 | "groupby": {
29 | "key": "Sex",
30 | "isKeyShared": true
31 | },
32 | "aspect_ratio":"fillY",
33 | "size": {
34 | "type": "uniform",
35 | "isShared": false
36 | },
37 | "direction": "LRBT",
38 | "align": "LB",
39 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
40 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
41 | },
42 | {
43 | "name": "layout3",
44 | "type": "gridxy",
45 | "groupby": {
46 | "key": "id",
47 | "isKeyShared": false
48 | },
49 | "aspect_ratio":"fillX",
50 | "size": {
51 | "type":"uniform",
52 | "isShare": false
53 | },
54 | "direction": "LRBT",
55 | "align": "LB",
56 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
57 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
58 | }],
59 | "mark": {
60 | "shape": "circle",
61 | "color": "survival",
62 | "size": {
63 | "type": "max",
64 | "isShared": true
65 | },
66 | "isColorScaleShared": true
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/data/titanic_spec3.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 1000,
5 | "height": 480,
6 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "groupby": {
12 | "key": "Class",
13 | "isKeyShared": true
14 | },
15 | "aspect_ratio":"fillX",
16 | "size": {
17 | "type":"uniform",
18 | "isShared": false
19 | },
20 | "direction": "LRBT",
21 | "align": "LB",
22 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
23 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
24 | },
25 | {
26 | "name": "layout2",
27 | "type": "gridxy",
28 | "groupby": {
29 | "key": "Sex",
30 | "isKeyShared": true
31 | },
32 | "aspect_ratio":"fillY",
33 | "size": {
34 | "type": "uniform",
35 | "isShared": false
36 | },
37 | "direction": "LRTB",
38 | "align": "LB",
39 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
40 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
41 | },
42 | {
43 | "name": "layout3",
44 | "type": "gridxy",
45 | "groupby": {
46 | "key": "id",
47 | "isKeyShared": false
48 | },
49 | "aspect_ratio":"square",
50 | "size": {
51 | "type":"uniform",
52 | "isShared": false
53 | },
54 | "direction": "LRTB",
55 | "align": "LB",
56 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
57 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10}
58 | }],
59 | "mark": {
60 | "shape": "circle",
61 | "color": "survival",
62 | "size": {
63 | "type": "max",
64 | "isShared": false
65 | },
66 | "isColorScaleShared": true
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/data/titanic_spec4.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "Sex",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 0,
29 | "left": 0,
30 | "bottom": 0,
31 | "right": 0
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "groupby",
44 | "key": "Class",
45 | "isShared": true
46 | },
47 | "aspect_ratio": "fillX",
48 | "size": {
49 | "type": "uniform",
50 | "isShared": true
51 | },
52 | "direction": "LRTB",
53 | "align": "LB",
54 | "margin": {
55 | "top": 5,
56 | "left": 5,
57 | "bottom": 5,
58 | "right": 5
59 | },
60 | "padding": {
61 | "top": 5,
62 | "left": 5,
63 | "bottom": 5,
64 | "right": 5
65 | }
66 | }, {
67 | "name": "layout3",
68 | "type": "gridxy",
69 | "subgroup": {
70 | "type": "flatten"
71 | },
72 | "aspect_ratio": "maxfill",
73 | "size": {
74 | "type": "uniform",
75 | "isShared": false
76 | },
77 | "direction": "LRBT",
78 | "align": "LB",
79 | "margin": {
80 | "top": 5,
81 | "left": 5,
82 | "bottom": 5,
83 | "right": 5
84 | },
85 | "padding": {
86 | "top": 5,
87 | "left": 5,
88 | "bottom": 5,
89 | "right": 5
90 | },
91 | "sort": {
92 | "key": "Survived"
93 | }
94 | }],
95 | "mark": {
96 | "shape": "circle",
97 | "color": {
98 | "key": "Survived",
99 | "type": "categorical"
100 | },
101 | "size": {
102 | "type": "max",
103 | "isShared": false
104 | },
105 | "isColorScaleShared": true
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/data/titanic_spec_packxy_hierarchy.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "Sex",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 0,
29 | "left": 0,
30 | "bottom": 0,
31 | "right": 0
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "groupby",
44 | "key": "Class",
45 | "isShared": true
46 | },
47 | "aspect_ratio": "fillX",
48 | "size": {
49 | "type": "uniform",
50 | "isShared": false
51 | },
52 | "direction": "LRTB",
53 | "align": "LB",
54 | "margin": {
55 | "top": 5,
56 | "left": 5,
57 | "bottom": 5,
58 | "right": 5
59 | },
60 | "padding": {
61 | "top": 5,
62 | "left": 5,
63 | "bottom": 5,
64 | "right": 5
65 | }
66 | }, {
67 | "name": "layout3",
68 | "type": "gridxy",
69 | "subgroup": {
70 | "type": "flatten"
71 | },
72 | "aspect_ratio": "maxfill",
73 | "size": {
74 | "type": "uniform",
75 | "isShared": true
76 | },
77 | "direction": "LRBT",
78 | "align": "LB",
79 | "margin": {
80 | "top": 5,
81 | "left": 5,
82 | "bottom": 5,
83 | "right": 5
84 | },
85 | "padding": {
86 | "top": 5,
87 | "left": 5,
88 | "bottom": 5,
89 | "right": 5
90 | },
91 | "sort": {
92 | "key": "Survived"
93 | }
94 | }],
95 | "mark": {
96 | "shape": "circle",
97 | "color": {
98 | "key": "Survived",
99 | "type": "categorical"
100 | },
101 | "size": {
102 | "type": "max",
103 | "isShared": false
104 | },
105 | "isColorScaleShared": true
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/data/titanic_spec_packxy_isolated.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "Sex",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 0,
29 | "left": 0,
30 | "bottom": 0,
31 | "right": 0
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "groupby",
44 | "key": "Class",
45 | "isShared": true
46 | },
47 | "aspect_ratio": "fillX",
48 | "size": {
49 | "type": "uniform",
50 | "isShared": true
51 | },
52 | "direction": "LRTB",
53 | "align": "LB",
54 | "margin": {
55 | "top": 5,
56 | "left": 5,
57 | "bottom": 5,
58 | "right": 5
59 | },
60 | "padding": {
61 | "top": 5,
62 | "left": 5,
63 | "bottom": 5,
64 | "right": 5
65 | }
66 | }, {
67 | "name": "layout3",
68 | "type": "gridxy",
69 | "subgroup": {
70 | "type": "flatten"
71 | },
72 | "aspect_ratio": "maxfill",
73 | "size": {
74 | "type": "uniform",
75 | "isShared": true
76 | },
77 | "direction": "LRBT",
78 | "align": "LB",
79 | "margin": {
80 | "top": 5,
81 | "left": 5,
82 | "bottom": 5,
83 | "right": 5
84 | },
85 | "padding": {
86 | "top": 5,
87 | "left": 5,
88 | "bottom": 5,
89 | "right": 5
90 | },
91 | "sort": {
92 | "key": "Survived"
93 | }
94 | }],
95 | "mark": {
96 | "shape": "circle",
97 | "color": {
98 | "key": "Survived",
99 | "type": "categorical"
100 | },
101 | "size": {
102 | "type": "max",
103 | "isShared": false
104 | },
105 | "isColorScaleShared": true
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/data/titanic_spec_packxy_mixed.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "Sex",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillY",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 0,
29 | "left": 0,
30 | "bottom": 0,
31 | "right": 0
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "groupby",
44 | "key": "Class",
45 | "isShared": true
46 | },
47 | "aspect_ratio": "fillX",
48 | "size": {
49 | "type": "uniform",
50 | "isShared": false
51 | },
52 | "direction": "LRTB",
53 | "align": "LB",
54 | "margin": {
55 | "top": 5,
56 | "left": 5,
57 | "bottom": 5,
58 | "right": 5
59 | },
60 | "padding": {
61 | "top": 5,
62 | "left": 5,
63 | "bottom": 5,
64 | "right": 5
65 | }
66 | }, {
67 | "name": "layout3",
68 | "type": "gridxy",
69 | "subgroup": {
70 | "type": "flatten"
71 | },
72 | "aspect_ratio": "maxfill",
73 | "size": {
74 | "type": "uniform",
75 | "isShared": false
76 | },
77 | "direction": "LRBT",
78 | "align": "LB",
79 | "margin": {
80 | "top": 5,
81 | "left": 5,
82 | "bottom": 5,
83 | "right": 5
84 | },
85 | "padding": {
86 | "top": 5,
87 | "left": 5,
88 | "bottom": 5,
89 | "right": 5
90 | },
91 | "sort": {
92 | "key": "Survived"
93 | }
94 | }],
95 | "mark": {
96 | "shape": "circle",
97 | "color": {
98 | "key": "Survived",
99 | "type": "categorical"
100 | },
101 | "size": {
102 | "type": "max",
103 | "isShared": false
104 | },
105 | "isColorScaleShared": true
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/data/unit_column_chart.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 10,
8 | "left": 30,
9 | "bottom": 30,
10 | "right": 10
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 10,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 10
32 | },
33 | "padding": {
34 | "top": 10,
35 | "left": 30,
36 | "bottom": 30,
37 | "right": 10
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "flatten"
44 | },
45 | "aspect_ratio": "maxfill",
46 | "size": {
47 | "type": "uniform",
48 | "isShared": false
49 | },
50 | "direction": "LRBT",
51 | "align": "LB",
52 | "margin": {
53 | "top": 10,
54 | "left": 30,
55 | "bottom": 30,
56 | "right": 10
57 | },
58 | "padding": {
59 | "top": 10,
60 | "left": 30,
61 | "bottom": 30,
62 | "right": 10
63 | },
64 | "sort": {
65 | "key":"survived"
66 | }
67 | }],
68 | "mark": {
69 | "shape": "circle",
70 | "color": {
71 | "key": "survived",
72 | "type": "categorical"
73 | },
74 | "size": {
75 | "type": "max",
76 | "isShared": false
77 | },
78 | "isColorScaleShared": true
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/data/unit_column_chart_shared.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {
7 | "top": 10,
8 | "left": 30,
9 | "bottom": 30,
10 | "right": 10
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": false
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 0,
35 | "left": 0,
36 | "bottom": 0,
37 | "right": 0
38 | }
39 | }, {
40 | "name": "layout2",
41 | "type": "gridxy",
42 | "subgroup": {
43 | "type": "flatten"
44 | },
45 | "aspect_ratio": "maxfill",
46 | "size": {
47 | "type": "uniform",
48 | "isShared": true
49 | },
50 | "direction": "LRBT",
51 | "align": "LB",
52 | "margin": {
53 | "top": 0,
54 | "left": 0,
55 | "bottom": 0,
56 | "right": 0
57 | },
58 | "padding": {
59 | "top": 0,
60 | "left": 0,
61 | "bottom": 0,
62 | "right": 0
63 | },
64 | "sort": {
65 | "key": "survived"
66 | }
67 | }],
68 | "mark": {
69 | "shape": "circle",
70 | "color": {
71 | "key": "survived",
72 | "type": "categorical"
73 | },
74 | "size": {
75 | "type": "max",
76 | "isShared": false
77 | },
78 | "isColorScaleShared": true
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/data/unit_column_chart_shared_mark.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 320,
5 | "height": 240,
6 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "subgroup": {
12 | "type":"groupby",
13 | "key": "pclass",
14 | "isShared": false
15 | },
16 | "aspect_ratio":"fillX",
17 | "size": {
18 | "type":"uniform",
19 | "isShared": false
20 | },
21 | "direction": "LRBT",
22 | "align": "LB",
23 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
24 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5}
25 | },
26 | {
27 | "name": "layout2",
28 | "type": "gridxy",
29 | "subgroup": {
30 | "type":"flatten" },
31 | "aspect_ratio":"maxfill",
32 | "size": {
33 | "type":"uniform",
34 | "isShared": false
35 | },
36 | "direction": "LRBT",
37 | "align": "LB",
38 | "margin": {"top": 10, "left": 30, "bottom": 30, "right": 10},
39 | "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
40 | "sort":{
41 | "key":"survived"
42 | }
43 | }],
44 | "mark": {
45 | "shape": "rect",
46 | "color": {
47 | "key":"survived",
48 | "type":"categorical"
49 | },
50 | "size": {
51 | "type": "max",
52 | "isShared": true
53 | },
54 | "isColorScaleShared": true
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/data/unit_small_multiple.json:
--------------------------------------------------------------------------------
1 | {
2 | "title" : "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 500,
5 | "height": 240,
6 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
7 | "layouts": [
8 | {
9 | "name": "layout1",
10 | "type": "gridxy",
11 | "subgroup": {
12 | "key": "age",
13 | "type": "bin",
14 | "numBin": 15,
15 | "isShared": false
16 | },
17 | "aspect_ratio":"parent",
18 | "size": {
19 | "type":"uniform",
20 | "isShared": true
21 | },
22 | "direction": "LRBT",
23 | "align": "LB",
24 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
25 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
26 | "box": {
27 | "fill": "none",
28 | "stroke": "black",
29 | "stroke-width": 0,
30 | "opacity":0.3
31 | }
32 | },
33 | {
34 | "name": "layout2",
35 | "type": "gridxy",
36 | "subgroup": {
37 | "type":"groupby",
38 | "key": "pclass",
39 | "isShared": true
40 | },
41 | "aspect_ratio":"fillX",
42 | "size": {
43 | "type": "uniform",
44 | "isShared": true
45 | },
46 | "direction": "LRTB",
47 | "align": "LB",
48 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
49 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
50 | "box": {
51 | "fill": "none",
52 | "stroke": "green",
53 | "stroke-width": 1,
54 | "opacity":1
55 | }
56 | },
57 | {
58 | "name": "layout3",
59 | "type": "gridxy",
60 | "subgroup": {
61 | "type":"flatten"
62 | },
63 | "aspect_ratio":"maxfill",
64 | "size": {
65 | "type":"uniform",
66 | "isShared": true
67 | },
68 | "direction": "LRBT",
69 | "align": "LB",
70 | "margin": {"top": 5, "left": 5, "bottom": 5, "right": 5},
71 | "padding": {"top": 5, "left": 5, "bottom": 5, "right": 5},
72 | "box": {
73 | "fill": "none",
74 | "stroke": "black",
75 | "stroke-width": 0,
76 | "opacity":1
77 | },
78 | "sort":{
79 | "key":"survived"
80 | }
81 | }],
82 | "mark": {
83 | "shape": "circle",
84 | "color": {
85 | "key":"survived",
86 | "type":"categorical"
87 | },
88 | "size": {
89 | "type": "max",
90 | "isShared": false
91 | },
92 | "isColorScaleShared": true
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/data/violin.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Titanic",
3 | "data": "data/titanic3.csv",
4 | "width": 1000,
5 | "height": 320,
6 | "padding": {
7 | "top": 5,
8 | "left": 5,
9 | "bottom": 5,
10 | "right": 5
11 | },
12 | "layouts": [{
13 | "name": "layout1",
14 | "type": "gridxy",
15 | "subgroup": {
16 | "type": "groupby",
17 | "key": "pclass",
18 | "isShared": false
19 | },
20 | "aspect_ratio": "fillX",
21 | "size": {
22 | "type": "uniform",
23 | "isShared": true
24 | },
25 | "direction": "LRBT",
26 | "align": "LB",
27 | "margin": {
28 | "top": 5,
29 | "left": 5,
30 | "bottom": 5,
31 | "right": 5
32 | },
33 | "padding": {
34 | "top": 5,
35 | "left": 5,
36 | "bottom": 5,
37 | "right": 5
38 | },
39 | "box": {
40 | "fill": "white",
41 | "stroke": "black",
42 | "stroke-width": 0,
43 | "opacity": 0.3
44 | },
45 | "sort": {
46 | "key": "pclass",
47 | "direction": "ascending"
48 | }
49 | }, {
50 | "name": "layout2",
51 | "type": "gridxy",
52 | "subgroup": {
53 | "type": "bin",
54 | "key": "age",
55 | "numBin": 19,
56 | "isShared": true
57 | },
58 | "aspect_ratio": "fillY",
59 | "size": {
60 | "type": "uniform",
61 | "isShared": true
62 | },
63 | "direction": "BT",
64 | "align": "bottom",
65 | "margin": {
66 | "top": 0,
67 | "left": 0,
68 | "bottom": 0,
69 | "right": 0
70 | },
71 | "padding": {
72 | "top": 0,
73 | "left": 0,
74 | "bottom": 0,
75 | "right": 0
76 | },
77 | "box": {
78 | "fill": "white",
79 | "stroke": "black",
80 | "stroke-width": 0.5,
81 | "opacity": 0.5
82 | },
83 | "sort": {
84 | "key": "age",
85 | "direction": "ascending"
86 | }
87 | }, {
88 | "name": "layout3",
89 | "type": "gridxy",
90 | "subgroup": {
91 | "type": "passthrough",
92 | "isShared": true
93 | },
94 | "aspect_ratio": "fillX",
95 | "size": {
96 | "type": "count",
97 | "isShared": true
98 | },
99 | "direction": "LR",
100 | "align": "center",
101 | "margin": {
102 | "top": 0,
103 | "left": 0,
104 | "bottom": 0,
105 | "right": 0
106 | },
107 | "padding": {
108 | "top": 0,
109 | "left": 0,
110 | "bottom": 0,
111 | "right": 0
112 | },
113 | "box": {
114 | "fill": "white",
115 | "stroke": "blue",
116 | "stroke-width": 0,
117 | "opacity": 0.5
118 | }
119 | }, {
120 | "name": "layout4",
121 | "type": "gridxy",
122 | "subgroup": {
123 | "type": "flatten"
124 | },
125 | "aspect_ratio": "maxfill",
126 | "size": {
127 | "type": "uniform",
128 | "isShared": false
129 | },
130 | "direction": "BTLR",
131 | "align": "LB",
132 | "margin": {
133 | "top": 0,
134 | "left": 0,
135 | "bottom": 0,
136 | "right": 0
137 | },
138 | "padding": {
139 | "top": 0,
140 | "left": 0,
141 | "bottom": 0,
142 | "right": 0
143 | },
144 | "box": {
145 | "fill": "white",
146 | "stroke": "red",
147 | "stroke-width": 0,
148 | "opacity": 0.5
149 | },
150 | "sort": {
151 | "type": "categorical",
152 | "key": "survived",
153 | "direction": "ascending"
154 | }
155 | }],
156 | "mark": {
157 | "shape": "circle",
158 | "color": {
159 | "key": "survived_text",
160 | "type": "categorical"
161 | },
162 | "size": {
163 | "type": "max",
164 | "isShared": false
165 | },
166 | "isColorScaleShared": true
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/app/favicon.ico
--------------------------------------------------------------------------------
/app/images/process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/app/images/process.png
--------------------------------------------------------------------------------
/app/images/vcd-mosaic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/app/images/vcd-mosaic.png
--------------------------------------------------------------------------------
/app/images/yeoman.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/app/images/yeoman.png
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
53 |
54 | Fork me on GitHub
55 |
56 |
59 |
60 |
65 |
66 |
67 |
68 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org
2 |
3 | User-agent: *
4 | Disallow:
5 |
--------------------------------------------------------------------------------
/app/scripts/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc overview
5 | * @name unitApp
6 | * @description
7 | * # unitApp
8 | *
9 | * Main module of the application.
10 | */
11 | angular
12 | .module('unitApp', [
13 | 'ngAnimate',
14 | 'ngCookies',
15 | 'ngResource',
16 | 'ngRoute',
17 | 'ngSanitize',
18 | 'ngTouch'
19 | ])
20 | .config(function ($routeProvider) {
21 | $routeProvider
22 | .when('/', {
23 | templateUrl: 'views/main.html',
24 | controller: 'MainCtrl',
25 | controllerAs: 'main'
26 | })
27 | .when('/example', {
28 | templateUrl: 'views/example.html',
29 | controller: 'ExampleCtrl',
30 | controllerAs: 'example'
31 | })
32 | .when('/example', {
33 | templateUrl: 'views/example.html',
34 | controller: 'ExampleCtrl',
35 | controllerAs: 'example'
36 | })
37 | .when('/live', {
38 | templateUrl: 'views/live.html',
39 | controller: 'LiveCtrl',
40 | controllerAs: 'live'
41 | })
42 | .when('/enum', {
43 | templateUrl: 'views/enum.html',
44 | controller: 'EnumCtrl',
45 | controllerAs: 'enum'
46 | })
47 | .otherwise({
48 | redirectTo: '/'
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/app/scripts/controllers/about.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc function
5 | * @name unitApp.controller:AboutCtrl
6 | * @description
7 | * # AboutCtrl
8 | * Controller of the unitApp
9 | */
10 | angular.module('unitApp')
11 | .controller('AboutCtrl', function () {
12 | this.awesomeThings = [
13 | 'HTML5 Boilerplate',
14 | 'AngularJS',
15 | 'Karma'
16 | ];
17 | });
18 |
--------------------------------------------------------------------------------
/app/scripts/controllers/enum.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc function
5 | * @name unitApp.controller:EnumCtrl
6 | * @description
7 | * # EnumCtrl
8 | * Controller of the unitApp
9 | */
10 | angular.module('unitApp')
11 | .controller('EnumCtrl', function(unit) {
12 | //Enumeration
13 | d3.csv('./data/titanic3.csv', function(error, data) {
14 |
15 | var keys = Object.keys(data[0]);
16 |
17 | d3.select("#control_enumeration").selectAll("input")
18 | .data(keys)
19 | .enter()
20 | .append('label')
21 | .attr('for', function(d, i) {
22 | return 'a' + i;
23 | })
24 | .text(function(d) {
25 | return d;
26 | })
27 | .append('input')
28 | .property("checked", function(d, i) {
29 | return false;
30 | })
31 | .attr("type", "checkbox")
32 | .attr("id", function(d, i) {
33 | return 'a' + i;
34 | });
35 |
36 | });
37 |
38 | var update_enumeration_button = d3.select('#updatebutton_enumeration');
39 |
40 | update_enumeration_button.on('click', function() {
41 | var inputs = d3.select('#control_enumeration').selectAll("input");
42 | console.log(inputs);
43 | var selectedInputs = [];
44 | inputs.each(function(d, i) {
45 | if (d3.select(this).property("checked")) {
46 | selectedInputs.push(d);
47 | }
48 | });
49 | var numLayer = d3.select("#nLayer").property("value");
50 | numLayer = +numLayer;
51 | console.log(selectedInputs);
52 | enumerate(selectedInputs, numLayer, 'unit_enumerate');
53 | });
54 |
55 | var UnitChart = unit.UnitChart;
56 |
57 | var enumerate = function(selectedInputs, numLayer, divId) {
58 |
59 | d3.json('./data/enumerate.json', function(error, data) {
60 | var base = data;
61 | var flattenLayers, markPolicies;
62 | var specs = []
63 | switch (numLayer) {
64 | case 1:
65 | flattenLayers = getFlattenLayers(selectedInputs);
66 | markPolicies = getMarkPolicies(selectedInputs);
67 | specs = enumeratePolicyForSingleLayer(flattenLayers, markPolicies);
68 | break;
69 |
70 | case 2:
71 | var firstLayers = getFirstLayers(selectedInputs);
72 | flattenLayers = getFlattenLayers(selectedInputs);
73 | markPolicies = getMarkPolicies(selectedInputs);
74 | specs = enumeratePolicyForDoubleLayers(firstLayers, flattenLayers, markPolicies);
75 | break;
76 |
77 | default:
78 | var firstLayers = getFirstLayers(selectedInputs);
79 | var middleLayers = getMiddleLayers(selectedInputs, numLayer);
80 | flattenLayers = getFlattenLayers(selectedInputs);
81 | markPolicies = getMarkPolicies(selectedInputs);
82 | specs = enumeratePolicyForGeneralLayers(firstLayers,middleLayers, flattenLayers, markPolicies);
83 |
84 | }
85 | console.log("Number of Enumerations:", specs.length);
86 |
87 |
88 | d3.select('#num_enumeration').text(specs.length);
89 |
90 | if (!d3.select('#enumerate_draw').property("checked")) {
91 | drawSpecs(specs, divId);
92 |
93 | }
94 |
95 | });
96 |
97 | };
98 |
99 |
100 | function enumeratePolicyForDoubleLayers(firstLayers, flattenLayers, markPolicies) {
101 | var specs = [];
102 | firstLayers.forEach(function(aFirstLayer) {
103 | flattenLayers.forEach(function(aFlattenLayer) {
104 | markPolicies.forEach(function(aMarkPolicy) {
105 | var newFirstLayer = JSON.parse(JSON.stringify(aFirstLayer));
106 | var newFlattenLayer = JSON.parse(JSON.stringify(aFlattenLayer));
107 | var aSpec = {
108 | "title": "Titanic",
109 | "data": "data/titanic3.csv",
110 | "width": 1000,
111 | "height": 320,
112 | "padding": {
113 | "top": 5,
114 | "left": 5,
115 | "bottom": 5,
116 | "right": 5
117 | },
118 | "layouts": []
119 | };
120 | aSpec.layouts = [newFirstLayer, newFlattenLayer];
121 | aSpec.mark = aMarkPolicy;
122 | specs.push(aSpec);
123 | });
124 | });
125 | });
126 |
127 | return specs;
128 | }
129 |
130 | function enumeratePolicyForGeneralLayers(firstLayers, middleLayers, flattenLayers, markPolicies, numLayer) {
131 | var specs = [];
132 | firstLayers.forEach(function(aFirstLayer) {
133 | middleLayers.forEach(function(aMiddleLayer) {
134 | flattenLayers.forEach(function(aFlattenLayer) {
135 | markPolicies.forEach(function(aMarkPolicy) {
136 | var newFirstLayer = JSON.parse(JSON.stringify(aFirstLayer));
137 | var newFlattenLayer = JSON.parse(JSON.stringify(aFlattenLayer));
138 | var newMiddleLayer = JSON.parse(JSON.stringify(aMiddleLayer));
139 | var aSpec = {
140 | "title": "Titanic",
141 | "data": "data/titanic3.csv",
142 | "width": 1000,
143 | "height": 320,
144 | "padding": {
145 | "top": 5,
146 | "left": 5,
147 | "bottom": 5,
148 | "right": 5
149 | },
150 | "layouts": []
151 | };
152 | aSpec.layouts = [newFirstLayer];
153 | aSpec.layouts = aSpec.layouts.concat( newMiddleLayer);
154 | aSpec.layouts = aSpec.layouts.push( newMiddleLayer);
155 |
156 | aSpec.mark = aMarkPolicy;
157 | specs.push(aSpec);
158 | });
159 | });
160 | });
161 | });
162 |
163 | return specs;
164 | }
165 |
166 | function enumeratePolicyForSingleLayer(flattenLayers, markPolicies) {
167 | var specs = []
168 | flattenLayers.forEach(function(aFlattenLayer) {
169 | markPolicies.forEach(function(aMarkPolicy) {
170 | var aSpec = {
171 | "title": "Titanic",
172 | "data": "data/titanic3.csv",
173 | "width": 1000,
174 | "height": 320,
175 | "padding": {
176 | "top": 5,
177 | "left": 5,
178 | "bottom": 5,
179 | "right": 5
180 | },
181 | "layouts": []
182 | };
183 | aSpec.layouts.push(aFlattenLayer);
184 | aSpec.mark = aMarkPolicy;
185 | specs.push(aSpec);
186 | });
187 | });
188 | return specs;
189 |
190 | }
191 |
192 |
193 |
194 | function drawSpecs(specs, divId) {
195 | d3.select("#" + divId).selectAll("div")
196 | .data(specs)
197 | .enter()
198 | .append("div")
199 | .attr("id", function(d, i) {
200 | return "enum" + i;
201 | });
202 |
203 | specs.forEach(function(spec, i) {
204 | UnitChart('enum' + i, spec);
205 | })
206 | }
207 |
208 | function getFlattenLayers(selectedInputs) {
209 |
210 | var enum_aspect_ratio = ['fillX', 'fillY', 'maxfill', 'square', 'parent'];
211 | var enum_size_type = ['uniform'];
212 | var enum_size_isShared = [true, false];
213 | var enum_direction = ['LRTB'];
214 | var enum_align = ['LB'];
215 | var enum_sort_key = selectedInputs;
216 |
217 | var layers = [];
218 |
219 | enum_aspect_ratio.forEach(function(a_aspect_ratio) {
220 | enum_size_type.forEach(function(a_size_type) {
221 | enum_size_isShared.forEach(function(a_size_isShared) {
222 | enum_direction.forEach(function(a_direction) {
223 | enum_align.forEach(function(a_align) {
224 | enum_sort_key.forEach(function(a_sort_key) {
225 | var aLayer = {
226 | "name": "flattenLayer",
227 | "type": "gridxy",
228 | "subgroup": {
229 | "type": "flatten"
230 | },
231 | "aspect_ratio": a_aspect_ratio,
232 | "size": {
233 | "type": a_size_type,
234 | "isShared": a_size_isShared
235 | },
236 | "direction": a_direction,
237 | "align": a_align,
238 | "margin": {
239 | "top": 0,
240 | "left": 0,
241 | "bottom": 0,
242 | "right": 0
243 | },
244 | "padding": {
245 | "top": 0,
246 | "left": 0,
247 | "bottom": 0,
248 | "right": 0
249 | },
250 | "box": {
251 | "fill": "yellow",
252 | "stroke": "red",
253 | "stroke-width": 0,
254 | "opacity": 0.1
255 | },
256 | "sort": {
257 | "type": isCategorical(a_sort_key) ? "categorical" : "numerical",
258 | "key": a_sort_key
259 | }
260 | };
261 |
262 | layers.push(aLayer);
263 |
264 | });
265 | });
266 | });
267 | });
268 | });
269 | });
270 |
271 | return layers;
272 | }
273 |
274 | function getFirstLayers(selectedInputs) {
275 |
276 | var enum_aspect_ratio = ['fillX', 'fillY', 'maxfill', 'square', 'parent'];
277 | var enum_groupby_key = selectedInputs;
278 | var enum_groupby_isShared = [true]
279 | var enum_size_type = [{
280 | 'type': 'uniform'
281 | }, {
282 | 'type': 'count'
283 | }];
284 |
285 | enum_size_type = enum_size_type.concat(selectedInputs.map(function(d) {
286 | return {
287 | 'type': 'sum',
288 | 'key': d
289 | };
290 | }));
291 |
292 | var enum_size_sum_key = selectedInputs;
293 | var enum_size_isShared = [true];
294 | var enum_direction = ['LRTB'];
295 | var enum_align = ['LB'];
296 | var enum_sort_key = selectedInputs;
297 |
298 | var layers = [];
299 |
300 | enum_aspect_ratio.forEach(function(a_aspect_ratio, i) {
301 | enum_size_type.forEach(function(a_size_type) {
302 | enum_size_isShared.forEach(function(a_size_isShared) {
303 | enum_direction.forEach(function(a_direction) {
304 | enum_align.forEach(function(a_align) {
305 | enum_sort_key.forEach(function(a_sort_key) {
306 | enum_groupby_key.forEach(function(a_groupby_key) {
307 | enum_groupby_isShared.forEach(function(a_groupby_isShared) {
308 | var aLayer = {
309 | "name": "firstlayer",
310 | "type": "gridxy",
311 | "subgroup": {
312 | "type": "groupby",
313 | "key": a_groupby_key,
314 | "isShared": a_groupby_isShared
315 | },
316 | "aspect_ratio": a_aspect_ratio,
317 | "size": {
318 | "type": a_size_type.type,
319 | "isShared": a_size_isShared,
320 | "key": (a_size_type.type === 'sum') ? a_size_type.key : ''
321 | },
322 | "direction": a_direction,
323 | "align": a_align,
324 | "margin": {
325 | "top": 0,
326 | "left": 0,
327 | "bottom": 0,
328 | "right": 0
329 | },
330 | "padding": {
331 | "top": 0,
332 | "left": 0,
333 | "bottom": 0,
334 | "right": 0
335 | },
336 | "box": {
337 | "fill": "yellow",
338 | "stroke": "red",
339 | "stroke-width": 0,
340 | "opacity": 0.1
341 | },
342 | "sort": {
343 | "type": isCategorical(a_sort_key) ? "categorical" : "numerical",
344 | "key": a_sort_key
345 | }
346 | };
347 |
348 | layers.push(aLayer);
349 | });
350 | });
351 | });
352 | });
353 | });
354 | });
355 | });
356 | });
357 |
358 | return layers;
359 | }
360 |
361 | function getMiddleLayers(selectedInputs, numLayer) {
362 |
363 | var enum_aspect_ratio = ['fillX', 'fillY', 'maxfill', 'square', 'parent'];
364 | var enum_groupby_key = [{
365 | 'type': 'passthrough'
366 | }];
367 |
368 | enum_groupby_key = enum_groupby_key.concat(selectedInputs.map(function(d) {
369 | return {
370 | 'type': 'groupby',
371 | 'key': d
372 | }
373 | }));
374 |
375 | selectedInputs;
376 | var enum_groupby_isShared = [true]
377 | var enum_size_type = [{
378 | 'type': 'uniform'
379 | }, {
380 | 'type': 'count'
381 | }];
382 |
383 | enum_size_type = enum_size_type.concat(selectedInputs.map(function(d) {
384 | return {
385 | 'type': 'sum',
386 | 'key': d
387 | };
388 | }));
389 |
390 | var enum_size_sum_key = selectedInputs;
391 | var enum_size_isShared = [true];
392 | var enum_direction = ['LRTB'];
393 | var enum_align = ['LB'];
394 | var enum_sort_key = selectedInputs;
395 |
396 | var layers = [];
397 |
398 | enum_aspect_ratio.forEach(function(a_aspect_ratio, i) {
399 | enum_size_type.forEach(function(a_size_type) {
400 | enum_size_isShared.forEach(function(a_size_isShared) {
401 | enum_direction.forEach(function(a_direction) {
402 | enum_align.forEach(function(a_align) {
403 | enum_sort_key.forEach(function(a_sort_key) {
404 | enum_groupby_key.forEach(function(a_groupby_key) {
405 | enum_groupby_isShared.forEach(function(a_groupby_isShared) {
406 | var aLayer = {
407 | "name": "firstlayer",
408 | "type": "gridxy",
409 | "subgroup": {
410 | "type": a_groupby_key.type,
411 | "key": (a_groupby_key.type === 'groupby') ? a_groupby_key.key : '',
412 | "isShared": a_groupby_isShared
413 | },
414 | "aspect_ratio": a_aspect_ratio,
415 | "size": {
416 | "type": a_size_type.type,
417 | "isShared": a_size_isShared,
418 | "key": (a_size_type.type === 'sum') ? a_size_type.key : ''
419 | },
420 | "direction": a_direction,
421 | "align": a_align,
422 | "margin": {
423 | "top": 0,
424 | "left": 0,
425 | "bottom": 0,
426 | "right": 0
427 | },
428 | "padding": {
429 | "top": 0,
430 | "left": 0,
431 | "bottom": 0,
432 | "right": 0
433 | },
434 | "box": {
435 | "fill": "yellow",
436 | "stroke": "red",
437 | "stroke-width": 0,
438 | "opacity": 0.1
439 | },
440 | "sort": {
441 | "type": isCategorical(a_sort_key) ? "categorical" : "numerical",
442 | "key": a_sort_key
443 | }
444 | };
445 |
446 | layers.push(aLayer);
447 | });
448 | });
449 | });
450 | });
451 | });
452 | });
453 | });
454 | });
455 |
456 | layers = getCombi(layers, numLayer -2);
457 | return layers;
458 | }
459 |
460 | function getCombi(layers, depth) {
461 |
462 | if (depth == 1){
463 | return layers;
464 | } else {
465 | var newLayers = getCombi(layers, depth-1);
466 | var resultLayers = []
467 |
468 | layers.forEach(function(aLayer) {
469 | newLayers.forEach(function(aNewLayer) {
470 | aCopyLayer = JSON.parse(JSON.stringify(aLayer));
471 | var newArr = [aCopyLayer];
472 | aNewCopyLayer = JSON.parse(JSON.stringify(aNewLayer));
473 | newArr = newArr.concat(aNewCopyLayer);
474 |
475 | resultLayers.push(newArr);
476 | });
477 | });
478 |
479 | return resultLayers;
480 | }
481 | }
482 |
483 | function isCategorical(key) {
484 |
485 | var numericalVariables = ['age', 'fare'];
486 |
487 | if (numericalVariables.indexOf(key) == -1) {
488 | return true;
489 | } else {
490 | return false;
491 | }
492 | }
493 |
494 | function getMarkPolicies(keys) {
495 | var enum_color_key = keys;
496 | var enum_size_isShared = [true, false];
497 | var enum_color_isShared = [true];
498 | var enum_shape = ['circle', 'rect'];
499 | var marks = [];
500 |
501 | enum_color_key.forEach(function(a_color_key) {
502 | enum_size_isShared.forEach(function(a_size_isShared) {
503 | enum_color_isShared.forEach(function(a_color_isShared) {
504 | enum_shape.forEach(function(a_shape) {
505 | var aMark = {
506 | "shape": a_shape,
507 | "color": {
508 | "key": a_color_key,
509 | "type": (isCategorical(a_color_key)) ? "categorical" : "numerical",
510 | "isShared": a_color_isShared
511 | },
512 | "size": {
513 | "type": "max",
514 | "isShared": a_size_isShared
515 | },
516 | "isColorScaleShared": true
517 | };
518 | marks.push(aMark);
519 | });
520 | });
521 | });
522 | });
523 |
524 | return marks;
525 | }
526 |
527 | });
528 |
--------------------------------------------------------------------------------
/app/scripts/controllers/example.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc function
5 | * @name unitApp.controller:ExampleCtrl
6 | * @description
7 | * # ExampleCtrl
8 | * Controller of the unitApp
9 | */
10 | angular.module('unitApp')
11 | .controller('ExampleCtrl', ['unit', function (unit) {
12 |
13 | var UnitChart = unit.UnitChart;
14 |
15 | //Unit Column Chart
16 | d3.json('./data/unit_column_chart_shared.json', function(error,data){
17 | UnitChart('unit_column_chart_shared', data);
18 | });
19 | d3.json('./data/unit_column_chart.json', function(error,data){
20 | UnitChart('unit_column_chart', data);
21 | });
22 | d3.json('./data/unit_column_chart_shared_mark.json', function(error,data){
23 | UnitChart('unit_column_chart_shared_mark', data);
24 | });
25 | d3.json('./data/horizontal_unit_column.json', function(error,data){
26 | UnitChart('horizontal_unit_column', data);
27 | });
28 |
29 |
30 | //Hierarchy
31 | d3.json('./data/titanic_spec_packxy_hierarchy.json', function(error,data){
32 | UnitChart('packxy_hierarchy', data);
33 | });
34 | d3.json('./data/titanic_spec_packxy_isolated.json', function(error,data){
35 | UnitChart('packxy_isolated', data);
36 | });
37 | d3.json('./data/titanic_spec4.json', function(error,data){
38 | UnitChart('packxy2', data);
39 | });
40 | d3.json('./data/titanic_spec_packxy_mixed.json', function(error,data){
41 | UnitChart('packxy_mixed', data);
42 | });
43 |
44 | //Aspect ratio
45 | d3.json('./data/square_aspect.json', function(error,data){
46 | UnitChart('square_aspect', data);
47 | });
48 | d3.json('./data/maxfill_aspect.json', function(error,data){
49 | UnitChart('maxfill_aspect', data);
50 | });
51 | d3.json('./data/unit_small_multiple.json', function(error,data){
52 | UnitChart('unit_small_multiple', data);
53 | });
54 |
55 | //size
56 | d3.json('./data/size_uniform_notShared.json', function(error,data){
57 | UnitChart('size_uniform_notshared', data);
58 | });
59 | d3.json('./data/size_sum_notShared.json', function(error,data){
60 | UnitChart('size_sum_notshared', data);
61 | });
62 | d3.json('./data/size_uniform_shared.json', function(error,data){
63 | UnitChart('size_uniform_shared', data);
64 | });
65 | d3.json('./data/size_sum_shared.json', function(error,data){
66 | UnitChart('size_sum_shared', data);
67 | });
68 |
69 | //violin
70 | d3.json('./data/violin.json', function(error,data){
71 | UnitChart('violin', data);
72 | });
73 |
74 | //Squarified
75 | d3.json('./data/squarified.json', function(error,data){
76 | UnitChart('squarified', data);
77 | });
78 |
79 | //Fluctuation
80 | d3.json('./data/fluctuation.json', function(error,data){
81 | UnitChart('fluctuation', data);
82 | });
83 |
84 | //Mosaic
85 | d3.json('./data/mosaic.json', function(error,data){
86 | UnitChart('mosaic', data);
87 | });
88 |
89 |
90 | }]);
91 |
--------------------------------------------------------------------------------
/app/scripts/controllers/live.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc function
5 | * @name unitApp.controller:LiveCtrl
6 | * @description
7 | * # LiveCtrl
8 | * Controller of the unitApp
9 | */
10 | angular.module('unitApp')
11 | .controller('LiveCtrl', function(unit) {
12 | //editor
13 |
14 | var UnitChart = unit.UnitChart;
15 |
16 | d3.json('./data/default5.json',function(error, data) {
17 | UnitChart('editorchart', data);
18 | })
19 |
20 | var container = document.getElementById('jsoneditor');
21 | var options = {
22 | "mode": "code",
23 | "indentation": 2
24 | };
25 | var editor = new JSONEditor(container, options);
26 |
27 | d3.json('./data/default5.json', function(error, json) {
28 | editor.set(json);
29 | });
30 |
31 | var button = d3.select('#updatebutton');
32 |
33 | button.on('click', function() {
34 | var json = editor.get();
35 | console.log(json);
36 | d3.select('#editorchart').select('svg').remove();
37 | UnitChart('editorchart', json);
38 | });
39 |
40 | });
41 |
--------------------------------------------------------------------------------
/app/scripts/controllers/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @ngdoc function
5 | * @name unitApp.controller:MainCtrl
6 | * @description
7 | * # MainCtrl
8 | * Controller of the unitApp
9 | */
10 | angular.module('unitApp')
11 | .controller('MainCtrl', function () {
12 | this.awesomeThings = [
13 | 'HTML5 Boilerplate',
14 | 'AngularJS',
15 | 'Karma'
16 | ];
17 | });
18 |
--------------------------------------------------------------------------------
/app/scripts/services/treemap-squarify.js:
--------------------------------------------------------------------------------
1 | /*
2 | * treemap-squarify.js - open source implementation of squarified treemaps
3 | *
4 | * Treemap Squared 0.5 - Treemap Charting library
5 | *
6 | * https://github.com/imranghory/treemap-squared/
7 | *
8 | * Copyright (c) 2012 Imran Ghory (imranghory@gmail.com)
9 | * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
10 | *
11 | *
12 | * Implementation of the squarify treemap algorithm described in:
13 | *
14 | * Bruls, Mark; Huizing, Kees; van Wijk, Jarke J. (2000), "Squarified treemaps"
15 | * in de Leeuw, W.; van Liere, R., Data Visualization 2000:
16 | * Proc. Joint Eurographics and IEEE TCVG Symp. on Visualization, Springer-Verlag, pp. 33–42.
17 | *
18 | * Paper is available online at: http://www.win.tue.nl/~vanwijk/stm.pdf
19 | *
20 | * The code in this file is completeley decoupled from the drawing code so it should be trivial
21 | * to port it to any other vector drawing library. Given an array of datapoints this library returns
22 | * an array of cartesian coordinates that represent the rectangles that make up the treemap.
23 | *
24 | * The library also supports multidimensional data (nested treemaps) and performs normalization on the data.
25 | *
26 | * See the README file for more details.
27 | */
28 |
29 | var Treemap = {};
30 |
31 | (function() {
32 | "use strict";
33 | Treemap.generate = function(){
34 |
35 | function Container(xoffset, yoffset, width, height) {
36 | this.xoffset = xoffset; // offset from the the top left hand corner
37 | this.yoffset = yoffset; // ditto
38 | this.height = height;
39 | this.width = width;
40 |
41 | this.shortestEdge = function () {
42 | return Math.min(this.height, this.width);
43 | };
44 |
45 | // getCoordinates - for a row of boxes which we've placed
46 | // return an array of their cartesian coordinates
47 | this.getCoordinates = function (row) {
48 | var coordinates = [];
49 | var subxoffset = this.xoffset, subyoffset = this.yoffset; //our offset within the container
50 | var areawidth = sumArray(row) / this.height;
51 | var areaheight = sumArray(row) / this.width;
52 | var i;
53 |
54 | if (this.width >= this.height) {
55 | for (i = 0; i < row.length; i++) {
56 | coordinates.push([subxoffset, subyoffset, subxoffset + areawidth, subyoffset + row[i] / areawidth]);
57 | subyoffset = subyoffset + row[i] / areawidth;
58 | }
59 | } else {
60 | for (i = 0; i < row.length; i++) {
61 | coordinates.push([subxoffset, subyoffset, subxoffset + row[i] / areaheight, subyoffset + areaheight]);
62 | subxoffset = subxoffset + row[i] / areaheight;
63 | }
64 | }
65 | return coordinates;
66 | };
67 |
68 | // cutArea - once we've placed some boxes into an row we then need to identify the remaining area,
69 | // this function takes the area of the boxes we've placed and calculates the location and
70 | // dimensions of the remaining space and returns a container box defined by the remaining area
71 | this.cutArea = function (area) {
72 | var newcontainer;
73 |
74 | if (this.width >= this.height) {
75 | var areawidth = area / this.height;
76 | var newwidth = this.width - areawidth;
77 | newcontainer = new Container(this.xoffset + areawidth, this.yoffset, newwidth, this.height);
78 | } else {
79 | var areaheight = area / this.width;
80 | var newheight = this.height - areaheight;
81 | newcontainer = new Container(this.xoffset, this.yoffset + areaheight, this.width, newheight);
82 | }
83 | return newcontainer;
84 | };
85 | }
86 |
87 |
88 |
89 | // normalize - the Bruls algorithm assumes we're passing in areas that nicely fit into our
90 | // container box, this method takes our raw data and normalizes the data values into
91 | // area values so that this assumption is valid.
92 | function normalize(data, area) {
93 | var normalizeddata = [];
94 | var sum = sumArray(data);
95 | var multiplier = area / sum;
96 | var i;
97 |
98 | for (i = 0; i < data.length; i++) {
99 | normalizeddata[i] = data[i] * multiplier;
100 | }
101 | return normalizeddata;
102 | }
103 |
104 | // treemapMultidimensional - takes multidimensional data (aka [[23,11],[11,32]] - nested array)
105 | // and recursively calls itself using treemapSingledimensional
106 | // to create a patchwork of treemaps and merge them
107 | function treemapMultidimensional(data, width, height, xoffset, yoffset) {
108 | xoffset = (typeof xoffset === "undefined") ? 0 : xoffset;
109 | yoffset = (typeof yoffset === "undefined") ? 0 : yoffset;
110 |
111 | var mergeddata = [];
112 | var mergedtreemap;
113 | var results = [];
114 | var i;
115 |
116 | if(isArray(data[0])) { // if we've got more dimensions of depth
117 | for(i=0; i= newratio;
202 | }
203 |
204 | // calculateRatio - calculates the maximum width to height ratio of the
205 | // boxes in this row
206 | function calculateRatio(row, length) {
207 | var min = Math.min.apply(Math, row);
208 | var max = Math.max.apply(Math, row);
209 | var sum = sumArray(row);
210 | return Math.max(Math.pow(length, 2) * max / Math.pow(sum, 2), Math.pow(sum, 2) / (Math.pow(length, 2) * min));
211 | }
212 |
213 | // isArray - checks if arr is an array
214 | function isArray(arr) {
215 | return arr && arr.constructor === Array;
216 | }
217 |
218 | // sumArray - sums a single dimensional array
219 | function sumArray(arr) {
220 | var sum = 0;
221 | var i;
222 |
223 | for (i = 0; i < arr.length; i++) {
224 | sum += arr[i];
225 | }
226 | return sum;
227 | }
228 |
229 | // sumMultidimensionalArray - sums the values in a nested array (aka [[0,1],[[2,3]]])
230 | function sumMultidimensionalArray(arr) {
231 | var i, total = 0;
232 |
233 | if(isArray(arr[0])) {
234 | for(i=0; i 1) {
118 | var firstLayout = spec.layouts[0];
119 |
120 | firstLayout.margin = {
121 | "top": 5,
122 | "left": 5,
123 | "bottom": 5,
124 | "right": 5
125 | };
126 |
127 | firstLayout.padding = {
128 | "top": 5,
129 | "left": 5,
130 | "bottom": 5,
131 | "right": 5
132 | };
133 |
134 | }
135 |
136 | }
137 |
138 | applyDefault(spec);
139 |
140 | d3.csv(spec.data, function (error, csv_data) {
141 |
142 | try {
143 |
144 | console.log(JSON.stringify(spec));
145 |
146 | } catch (e) {
147 | console.log(e);
148 | }
149 | csv_data.forEach(function (d, i) {
150 | d.id = i;
151 | });
152 |
153 | var rootContainer = buildRootContainer(csv_data, spec);
154 | var layoutList = buildLayoutList(spec.layouts);
155 |
156 | var childContainers = [rootContainer];
157 | var currentLayout = layoutList.head;
158 |
159 | while (currentLayout !== 'EndOfLayout') {
160 | childContainers = applyLayout(childContainers, currentLayout);
161 | currentLayout = currentLayout.child;
162 | }
163 |
164 | drawUnit(rootContainer, spec, layoutList, divId);
165 | });
166 |
167 |
168 | };
169 |
170 | function applyLayout(containerList, layout) {
171 |
172 | var childContainers = [];
173 | var newSizeSharingAncestor;
174 | var oldSizeSharingAncestor = getSharingAncestorContainer(containerList[0], layout, 'size');
175 |
176 | containerList.forEach(function (container, i, all) {
177 |
178 | newSizeSharingAncestor = getSharingAncestorContainer(container, layout, 'size');
179 | if (newSizeSharingAncestor !== oldSizeSharingAncestor) {
180 | applySharedSize(layout);
181 | oldSizeSharingAncestor = newSizeSharingAncestor;
182 | }
183 |
184 | var newContainers = makeContainers(container, layout);
185 |
186 | if (newContainers.length > 0) {
187 | calcVisualSpace(container, newContainers, layout);
188 | }
189 | container.contents = newContainers;
190 | handleSharedSize(container, layout);
191 | childContainers = childContainers.concat(newContainers);
192 |
193 | });
194 |
195 | applySharedSize(layout);
196 |
197 | return childContainers;
198 | }
199 |
200 | function handleSharedSize(container, layout) {
201 |
202 | if (layout.size.isShared) {
203 | if (!layout.hasOwnProperty('sizeSharingGroup')) {
204 | layout.sizeSharingGroup = [];
205 | }
206 | layout.sizeSharingGroup = layout.sizeSharingGroup.concat(container.contents);
207 | }
208 | }
209 |
210 | var defaultSetting = {
211 | layout: {
212 | box: {
213 | 'fill': 'blue',
214 | 'stroke': 'black',
215 | 'stroke-width': 1,
216 | 'opacity': 0.03
217 | }
218 | }
219 | }
220 |
221 | function buildRootContainer(csv_data, spec) {
222 | var myContainer = {};
223 | myContainer.contents = csv_data;
224 | myContainer.label = 'root';
225 | if (!spec.hasOwnProperty('padding')) {
226 | spec.padding = {
227 | 'top': 10,
228 | 'left': 30,
229 | 'bottom': 30,
230 | 'right': 10
231 | };
232 | }
233 |
234 | myContainer.visualspace = {
235 | 'width': spec.width,
236 | 'height': spec.height,
237 | 'posX': 0,
238 | 'posY': 0,
239 | 'padding': spec.padding
240 | };
241 | myContainer.layout = 'StartOfLayout';
242 | myContainer.parent = 'RootContainer';
243 |
244 | return myContainer;
245 | }
246 |
247 | function buildLayoutList(layouts, rootLayout) {
248 |
249 | var layoutList = {};
250 |
251 | layoutList.head = layouts[0];
252 |
253 | layouts.forEach(function (layout, i, all) {
254 |
255 | if (i > 0) {
256 | layout.parent = all[i - 1];
257 | } else {
258 | layout.parent = 'StartOfLayout';
259 | }
260 | if (i < all.length - 1) {
261 | layout.child = all[i + 1];
262 | } else {
263 | layout.child = 'EndOfLayout';
264 | }
265 | });
266 | return layoutList;
267 | }
268 |
269 | function getKeys(data, groupby) {
270 | var myNest = d3.nest()
271 | .key(function (d) {
272 | return d[groupby]
273 | })
274 | .entries(data);
275 | return myNest.map(function (d) {
276 | return d.key;
277 | });
278 | }
279 |
280 | function emptyContainersFromKeys(data, groupby) {
281 |
282 | return getKeys(data, groupby)
283 | .map(function (key) {
284 | return {
285 | 'contents': [],
286 | 'label': key,
287 | 'visualspace': {}
288 | };
289 | });
290 | }
291 |
292 | function calcVisualSpace(parentContainer, childContainers, layout) {
293 |
294 | layout.containers = childContainers;
295 |
296 | switch (layout.type) {
297 | case 'gridxy':
298 | calcGridxyVisualSpace(parentContainer, childContainers, layout);
299 | break;
300 | default:
301 | console.log('Unsupported Layout type');
302 | break;
303 | }
304 | }
305 |
306 | function calcGridxyVisualSpace(parentContainer, childContainers, layout) {
307 | switch (layout.aspect_ratio) {
308 | case 'fillX':
309 | case 'fillY':
310 | calcFillGridxyVisualSpace(parentContainer, childContainers, layout);
311 | break;
312 | case 'square':
313 | case 'parent':
314 | case 'custom':
315 | calcPackGridxyVisualSpace(parentContainer, childContainers, layout);
316 | break;
317 | case 'maxfill':
318 | calcPackGridxyMaxFillVisualSpace(parentContainer, childContainers, layout);
319 | }
320 | }
321 |
322 | function calcPackGridxyMaxFillVisualSpace(parentContainer, childContainers, layout) {
323 | if (layout.size.type === 'uniform') {
324 | calcPackGridxyMaxFillVisualSpaceUniform(parentContainer, childContainers, layout);
325 | } else {
326 | calcPackGridxyMaxFillVisualSpaceFunction(parentContainer, childContainers, layout);
327 | }
328 | }
329 |
330 | function calcPackGridxyMaxFillVisualSpaceFunction(parentContainer, childContainers, layout) {
331 |
332 | childContainers = childContainers.filter(function (d) {
333 | return Number(d['contents'][0][layout.size.key] > 0);
334 | });
335 |
336 | childContainers.sort(function (c, d) {
337 | return d['contents'][0][layout.size.key] - c['contents'][0][layout.size.key];
338 | });
339 |
340 | var data = childContainers.map(function (d) {
341 | return Number(d['contents'][0][layout.size.key]);
342 | });
343 |
344 | var coord = Treemap.generate(data, parentContainer.visualspace.width, parentContainer.visualspace.height);
345 |
346 | childContainers.forEach(function (c, i, all) {
347 | var rect = coord[i];
348 | c.visualspace.width = rect[2] - rect[0];
349 | c.visualspace.height = rect[3] - rect[1];
350 | c.visualspace.posX = rect[0];
351 | c.visualspace.posY = rect[1]
352 | c.visualspace.padding = layout.padding;
353 | })
354 |
355 | }
356 | function calcPackGridxyMaxFillVisualSpaceUniform(parentContainer, childContainers, layout) {
357 |
358 | var edgeInfo = buildEdgeInfoForMaxFill(parentContainer, childContainers, layout);
359 |
360 | applyEdgeInfo(parentContainer, childContainers, layout, edgeInfo);
361 |
362 | }
363 |
364 | function buildEdgeInfoForMaxFill(parentContainer, childContainers, layout) {
365 |
366 | var combinations = getCombination(childContainers.length);
367 |
368 | var combinationForWidthAndHeight = combinations.map(function (d) {
369 | return {
370 | 'width': parentContainer.visualspace.width / d.a,
371 | 'height': parentContainer.visualspace.height / d.b,
372 | 'horizontalRepetitionCount': d.a,
373 | 'verticalRepetitionCount': d.b
374 | };
375 | });
376 |
377 | combinationForWidthAndHeight.forEach(function (d) {
378 | d.minEdge = (d.width > d.height) ? d.height : d.width;
379 | })
380 |
381 | var minCombi = d3.scan(combinationForWidthAndHeight, function (a, b) {
382 | return b.minEdge - a.minEdge;
383 | });
384 |
385 | var edgeInfo = combinationForWidthAndHeight[minCombi];
386 |
387 | return buildEdgeInfoByDirection(edgeInfo.horizontalRepetitionCount, edgeInfo.verticalRepetitionCount, edgeInfo.width, edgeInfo.height, layout);
388 |
389 | }
390 |
391 | function getCombination(n) {
392 | var combi = d3.range(1, n + 1);
393 |
394 | combi = combi.map(function (d) {
395 | return {
396 | 'a': d,
397 | 'b': Math.ceil(n / d)
398 | };
399 | });
400 |
401 | return combi;
402 | }
403 |
404 |
405 | function calcFillGridxyVisualSpace(parentContainer, childContainers, layout) {
406 |
407 | var availableSpace = getAvailableSpace(parentContainer, layout);
408 |
409 | var unitLength = getUnit(availableSpace, childContainers, layout);
410 |
411 | calcFillGridxyVisualSpaceWithUnitLength(parentContainer, childContainers, layout, unitLength);
412 |
413 | }
414 |
415 | function calcFillGridxyVisualSpaceWithUnitLength(parentContainer, childContainers, layout, unitLength) {
416 | var parentVisualSpace = parentContainer.visualspace;
417 |
418 | if (layout.aspect_ratio === 'fillX') {
419 |
420 | var unitWidth = unitLength;
421 |
422 | childContainers.forEach(function (c, i, all) {
423 | c.visualspace.width = unitWidth * getValue(c, layout) - layout.margin.left - layout.margin.right;
424 |
425 | c.visualspace.height = parentVisualSpace.height - parentVisualSpace.padding.top - parentVisualSpace.padding.bottom - layout.margin.top - layout.margin.bottom;
426 |
427 |
428 | c.visualspace.posY = parentVisualSpace.padding.top + layout.margin.top;
429 |
430 | c.visualspace.padding = layout.padding;
431 | });
432 |
433 | getPosXforFillX(parentVisualSpace, layout, childContainers);
434 |
435 | } else if (layout.aspect_ratio === 'fillY') {
436 |
437 | var unitHeight = unitLength;
438 |
439 | childContainers.forEach(function (c, i, all) {
440 | c.visualspace.height = unitHeight * getValue(c, layout) - layout.margin.top - layout.margin.bottom;
441 |
442 | c.visualspace.width = parentVisualSpace.width - parentVisualSpace.padding.left - parentVisualSpace.padding.right - layout.margin.left - layout.margin.right;
443 |
444 | c.visualspace.posX = parentVisualSpace.padding.left + layout.margin.left;
445 |
446 | c.visualspace.padding = layout.padding;
447 | });
448 |
449 | getPosYforFillY(parentVisualSpace, layout, childContainers);
450 |
451 | } else {
452 | console.log('TODO');
453 | }
454 |
455 | }
456 |
457 | function getPosXforFillX(parentVisualspace, layout, childContainers) {
458 |
459 | var start, direction, offset;
460 |
461 | switch (layout.direction) {
462 | case 'LRTB':
463 | case 'LRBT':
464 | case 'TBLR':
465 | case 'BTLR':
466 | case 'LR':
467 | start = 0;
468 | direction = 1;
469 | break;
470 | case 'RLBT':
471 | case 'RLTB':
472 | case 'BTRL':
473 | case 'TBRL':
474 | case 'RL':
475 | start = childContainers.length - 1;
476 | direction = -1;
477 | break;
478 | default:
479 | console.log('Unsupported Layout Direction', layout);
480 | }
481 |
482 | var totalwidth = d3.sum(childContainers, function (c) {
483 | return c.visualspace.width + layout.margin.left + layout.margin.right;
484 | });
485 |
486 | switch (layout.align) {
487 | case 'left':
488 | case 'LT':
489 | case 'LM':
490 | case 'LB':
491 | offset = parentVisualspace.padding.left;
492 | break;
493 | case 'center':
494 | case 'CT':
495 | case 'CM':
496 | case 'CB':
497 | offset = parentVisualspace.padding.left + (parentVisualspace.width - parentVisualspace.padding.left - parentVisualspace.padding.right) / 2 - totalwidth / 2;
498 | break;
499 | case 'right':
500 | case 'RT':
501 | case 'RM':
502 | case 'RB':
503 | offset = parentVisualspace.width - parentVisualspace.padding.right - totalwidth;
504 | break;
505 | }
506 |
507 | childContainers.forEach(function (c, i, all) {
508 | var index = start + direction * i;
509 | if (i === 0) {
510 | all[index].visualspace.posX = offset + layout.margin.left;
511 | } else {
512 | all[index].visualspace.posX = all[index - direction].visualspace.posX + all[index - direction].visualspace.width + layout.margin.right + layout.margin.left;
513 | }
514 | });
515 |
516 | }
517 |
518 |
519 | function getPosYforFillY(parentVisualspace, layout, childContainers) {
520 |
521 | var start, direction, offset;
522 |
523 | switch (layout.direction) {
524 | case 'LRTB':
525 | case 'RLTB':
526 | case 'TBLR':
527 | case 'TBRL':
528 | case 'TB':
529 | start = 0;
530 | direction = 1;
531 | break;
532 | case 'LRBT':
533 | case 'RLBT':
534 | case 'BTLR':
535 | case 'BTRL':
536 | case 'BT':
537 | start = childContainers.length - 1;
538 | direction = -1;
539 | break;
540 | default:
541 | console.log('Unsupported Layout Direction', layout);
542 | }
543 |
544 | var totalheight = d3.sum(childContainers, function (c) {
545 | return c.visualspace.height + layout.margin.top + layout.margin.bottom;
546 | });
547 |
548 | switch (layout.align) {
549 | case 'top':
550 | case 'RT':
551 | case 'CT':
552 | case 'LT':
553 | offset = parentVisualspace.padding.top;
554 | break;
555 | case 'middle':
556 | case 'LM':
557 | case 'RM':
558 | case 'CM':
559 | offset = parentVisualspace.padding.top + (parentVisualspace.height - parentVisualspace.padding.top - parentVisualspace.padding.bottom) / 2 - totalheight / 2;
560 | break;
561 | case 'bottom':
562 | case 'LB':
563 | case 'CB':
564 | case 'RB':
565 | offset = parentVisualspace.height - parentVisualspace.padding.bottom - totalheight;
566 | break;
567 | }
568 |
569 | childContainers.forEach(function (c, i, all) {
570 | var index = start + direction * i;
571 | if (i === 0) {
572 | all[index].visualspace.posY = offset + layout.margin.top;
573 | } else {
574 | all[index].visualspace.posY = all[index - direction].visualspace.posY + all[index - direction].visualspace.height + layout.margin.bottom + layout.margin.top;
575 | }
576 | });
577 |
578 | }
579 |
580 |
581 | function getUnit(availableSpace, childContainers, layout) {
582 |
583 | var sum = d3.sum(childContainers, function (d) {
584 | return getValue(d, layout);
585 | });
586 | return availableSpace / sum;
587 | }
588 |
589 | function getValue(container, layout) {
590 | switch (layout.size.type) {
591 | case 'uniform':
592 | return 1;
593 | break;
594 | case 'sum':
595 | return d3.sum(container.contents, function (d) {
596 | return d[layout.size.key];
597 | });
598 | break;
599 | case 'count':
600 | return container.contents.length;
601 | break;
602 | }
603 | }
604 |
605 | function calcPackGridxyVisualSpace(parentContainer, childContainers, layout) {
606 |
607 | var aspect_ratio;
608 |
609 | switch (layout.aspect_ratio) {
610 | case 'square':
611 | aspect_ratio = 1;
612 | break;
613 | case 'parent':
614 | aspect_ratio = (parentContainer.visualspace.width / parentContainer.visualspace.height);
615 | break;
616 | }
617 | var edgeInfo = calcEdgeInfo(parentContainer, childContainers, layout, aspect_ratio)
618 | applyEdgeInfo(parentContainer, childContainers, layout, edgeInfo);
619 | }
620 |
621 | function calcEdgeInfo(parentContainer, childContainers, layout, aspect_ratio) {
622 | if (isVerticalDirection(layout.direction)) {
623 | var edgeInfo = getRepetitionCountForFillingEdge(parentContainer.visualspace.width, parentContainer.visualspace.height, childContainers.length, aspect_ratio);
624 | } else {
625 | var edgeInfo = getRepetitionCountForFillingEdge(parentContainer.visualspace.height, parentContainer.visualspace.width, childContainers.length, 1 / aspect_ratio);
626 | }
627 | return edgeInfo;
628 | }
629 |
630 | function calcPackGridxyVisualSpaceWithUnitLength(parentContainer, childContainers, layout, unitLength) {
631 | switch (layout.aspect_ratio) {
632 | case 'square':
633 | childContainers.forEach(function (c, i, all) {
634 | c.visualspace.width = Math.sqrt(unitLength * getValue(c, layout));
635 | c.visualspace.height = Math.sqrt(unitLength * getValue(c, layout));
636 | c.visualspace.posX = parentContainer.visualspace.padding.left + layout.margin.left + 0.5 * (parentContainer.visualspace.width - c.visualspace.width - parentContainer.visualspace.padding.left - parentContainer.visualspace.padding.right);
637 | c.visualspace.posY = parentContainer.visualspace.padding.top + layout.margin.top + 0.5 * (parentContainer.visualspace.height - c.visualspace.height - parentContainer.visualspace.padding.top - parentContainer.visualspace.padding.right)
638 | });
639 |
640 | }
641 | }
642 |
643 | function applyEdgeInfo(parentContainer, childContainers, layout, edgeInfo) {
644 | if (isVerticalDirection(layout.direction)) {
645 | applyEdgeInfoVerticalDirection(parentContainer, childContainers, layout, edgeInfo);
646 | } else {
647 | applyEdgeInfoHorizontalDirection(parentContainer, childContainers, layout, edgeInfo);
648 | }
649 | }
650 |
651 | function applyEdgeInfoHorizontalDirection(parentContainer, childContainers, layout, edgeInfo) {
652 |
653 | var xOrig, yOrig, xInc, yInc, numVerticalElement, yOffset;
654 |
655 | switch (layout.direction) {
656 | case 'TBLR':
657 | xOrig = 0;
658 | yOrig = 0;
659 | xInc = edgeInfo.remainingEdgeSideUnitLength;
660 | yInc = edgeInfo.fillingEdgeSideUnitLength;
661 | numVerticalElement = edgeInfo.fillingEdgeRepetitionCount;
662 | break;
663 | case 'BTLR':
664 | xOrig = 0;
665 | yOrig = parentContainer.visualspace.height - edgeInfo.remainingEdgeSideUnitLength;
666 | xInc = edgeInfo.remainingEdgeSideUnitLength;
667 | yInc = (-1.0) * edgeInfo.fillingEdgeSideUnitLength;
668 | numVerticalElement = edgeInfo.fillingEdgeRepetitionCount;
669 | break;
670 | case 'TBRL':
671 | case 'BTRL':
672 | console.log('TODO');
673 | break;
674 | }
675 |
676 | childContainers.forEach(function (c, i, all) {
677 | c.visualspace.width = edgeInfo.remainingEdgeSideUnitLength;
678 | c.visualspace.height = edgeInfo.fillingEdgeSideUnitLength;
679 | c.visualspace.posX = xOrig + xInc * (Math.floor(i / numVerticalElement));
680 | c.visualspace.posY = yOrig + yInc * (i % numVerticalElement);
681 | c.visualspace.padding = layout.padding;
682 | })
683 | }
684 |
685 | function applyEdgeInfoVerticalDirection(parentContainer, childContainers, layout, edgeInfo) {
686 |
687 | var xOrig, yOrig, xInc, yInc, numHoriElement, yOffset;
688 |
689 | switch (layout.direction) {
690 | case 'LRTB':
691 | xOrig = 0;
692 | yOrig = 0;
693 | xInc = edgeInfo.fillingEdgeSideUnitLength;
694 | yInc = edgeInfo.remainingEdgeSideUnitLength;
695 | numHoriElement = edgeInfo.fillingEdgeRepetitionCount;
696 | break;
697 | case 'LRBT':
698 | xOrig = 0;
699 | yOrig = parentContainer.visualspace.height - edgeInfo.remainingEdgeSideUnitLength;
700 | xInc = edgeInfo.fillingEdgeSideUnitLength;
701 | yInc = (-1.0) * edgeInfo.remainingEdgeSideUnitLength;
702 | numHoriElement = edgeInfo.fillingEdgeRepetitionCount;
703 | break;
704 | case 'RLBT':
705 | case 'RLTB':
706 | console.log('TODO');
707 | break;
708 | }
709 |
710 | childContainers.forEach(function (c, i, all) {
711 | c.visualspace.width = edgeInfo.fillingEdgeSideUnitLength;
712 | c.visualspace.height = edgeInfo.remainingEdgeSideUnitLength;
713 | c.visualspace.posX = xOrig + xInc * (i % numHoriElement);
714 | c.visualspace.posY = yOrig + yInc * (Math.floor(i / numHoriElement));
715 | c.visualspace.padding = layout.padding;
716 | })
717 | }
718 |
719 | //Here ratio means the apect ratio of unit.
720 | //ratio = Filling Edge side divided by RemainingEdge side
721 |
722 | function getRepetitionCountForFillingEdge(fillingEdge, remainingEdge, numElement, ratio) {
723 |
724 | var fillingEdgeRepetitionCount = 0;
725 | var remainingEdgeSideUnitLength, remainingEdgeRepetitionCount, numPossibleContainers, fillingEdgeSideUnitLength;
726 |
727 | do {
728 |
729 | fillingEdgeRepetitionCount++;
730 | fillingEdgeSideUnitLength = 1.0 * fillingEdge / fillingEdgeRepetitionCount;
731 |
732 | remainingEdgeSideUnitLength = fillingEdgeSideUnitLength / ratio;
733 |
734 | remainingEdgeRepetitionCount = Math.floor(remainingEdge * fillingEdgeRepetitionCount * ratio / fillingEdge);
735 |
736 | numPossibleContainers = remainingEdgeRepetitionCount * fillingEdgeRepetitionCount;
737 |
738 | }
739 | while (numElement > numPossibleContainers);
740 |
741 | return {
742 | 'fillingEdgeRepetitionCount': fillingEdgeRepetitionCount,
743 | 'remainingEdgeRepetitionCount': remainingEdgeRepetitionCount,
744 | 'fillingEdgeSideUnitLength': fillingEdgeSideUnitLength,
745 | 'remainingEdgeSideUnitLength': remainingEdgeSideUnitLength
746 | };
747 |
748 | }
749 |
750 | function isVerticalDirection(direction) {
751 |
752 | switch (direction) {
753 | case 'LRBT':
754 | case 'LRTB':
755 | case 'RLBT':
756 | case 'RLTB':
757 | return true;
758 | break;
759 | case 'BTLR':
760 | case 'BTRL':
761 | case 'TBLR':
762 | case 'TBLR':
763 | return false;
764 | break;
765 | }
766 | }
767 |
768 | function getMinAmongContainers(layout) {
769 |
770 | var shared_containers = layout.sizeSharingGroup;
771 |
772 | var minSizeItemIndex;
773 |
774 | switch (layout.aspect_ratio) {
775 | case 'square':
776 | case 'parent':
777 | case 'custom':
778 | minSizeItemIndex = d3.scan(shared_containers, function (a, b) {
779 | return a.visualspace.width - b.visualspace.width;
780 | });
781 | return {
782 | 'width': shared_containers[minSizeItemIndex].visualspace.width,
783 | 'height': shared_containers[minSizeItemIndex].visualspace.height
784 | };
785 | break;
786 | case 'maxfill':
787 | var tempMinorSide = shared_containers.map(function (d) {
788 | return (d.visualspace.width > d.visualspace.height) ? d.visualspace.height : d.visualspace.width;
789 | });
790 | minSizeItemIndex = d3.scan(tempMinorSide, function (a, b) {
791 | return a - b;
792 | });
793 |
794 | var minContainer = shared_containers.reduce(function (pre, cur) {
795 |
796 | var minPre, maxPre, minCur, maxCur;
797 |
798 | if (pre.visualspace.height > pre.visualspace.width) {
799 | minPre = pre.visualspace.width;
800 | maxPre = pre.visualspace.height;
801 | } else {
802 | minPre = pre.visualspace.height;
803 | maxPre = pre.visualspace.width;
804 | }
805 |
806 | if (cur.visualspace.height > cur.visualspace.width) {
807 | minCur = cur.visualspace.width;
808 | maxCur = cur.visualspace.height;
809 | } else {
810 | minCur = cur.visualspace.height;
811 | maxCur = cur.visualspace.width;
812 | }
813 |
814 | if (minCur < minPre) {
815 | return cur;
816 | } else if (minCur == minPre) {
817 | if (maxCur < maxPre) {
818 | return cur;
819 | }
820 | }
821 | return pre;
822 | });
823 |
824 | return {
825 | 'width': minContainer.visualspace.width,
826 | 'height': minContainer.visualspace.height
827 | };
828 | }
829 |
830 | }
831 |
832 | function applySharedSizeOnContainers(minSize, layout) {
833 |
834 | var parentContainers = getParents(layout.sizeSharingGroup);
835 |
836 | parentContainers.forEach(function (c) {
837 |
838 | var edgeInfo = buildEdgeInfoFromMinSize(c, minSize, layout);
839 |
840 | applyEdgeInfo(c, c.contents, layout, edgeInfo);
841 | });
842 | }
843 |
844 | function getParents(containers) {
845 | var mySet = new Set();
846 |
847 | containers.forEach(function (d) {
848 | mySet.add(d.parent);
849 | });
850 |
851 | var myArr = [];
852 |
853 | mySet.forEach(function (d) { myArr.push(d); });
854 | return myArr;
855 | }
856 |
857 | function buildEdgeInfoFromMinSize(parentContainer, minSize, layout) {
858 | var horizontalRepetitionCount = Math.floor(parentContainer.visualspace.width / minSize.width);
859 | var verticalRepetitionCount = Math.floor(parentContainer.visualspace.height / minSize.height);
860 |
861 |
862 | return buildEdgeInfoByDirection(horizontalRepetitionCount, verticalRepetitionCount, minSize.width, minSize.height, layout);
863 | }
864 |
865 | function buildEdgeInfoByDirection(horizontalRepetitionCount, verticalRepetitionCount, width, height, layout) {
866 |
867 | var fillingEdgeRepetitionCount, remainingEdgeRepetitionCount, fillingEdgeSideUnitLength, remainingEdgeSideUnitLength;
868 |
869 | if (isVerticalDirection(layout.direction)) {
870 | fillingEdgeRepetitionCount = horizontalRepetitionCount;
871 | remainingEdgeRepetitionCount = verticalRepetitionCount;
872 | fillingEdgeSideUnitLength = width;
873 | remainingEdgeSideUnitLength = height;
874 | } else {
875 | fillingEdgeRepetitionCount = verticalRepetitionCount;
876 | remainingEdgeRepetitionCount = horizontalRepetitionCount;
877 | fillingEdgeSideUnitLength = height;
878 | remainingEdgeSideUnitLength = width;
879 | }
880 | return {
881 | 'fillingEdgeRepetitionCount': fillingEdgeRepetitionCount,
882 | 'remainingEdgeRepetitionCount': remainingEdgeRepetitionCount,
883 | 'fillingEdgeSideUnitLength': fillingEdgeSideUnitLength,
884 | 'remainingEdgeSideUnitLength': remainingEdgeSideUnitLength
885 | };
886 | }
887 |
888 | function applySharedSize(layout) {
889 |
890 | if (layout === 'EndOfLayout' || layout.size.isShared !== true) {
891 | return;
892 | }
893 |
894 | makeSharedSize(layout);
895 | layout.sizeSharingGroup = [];
896 | }
897 |
898 | function makeSharedSize(layout) {
899 | switch (layout.aspect_ratio) {
900 | case 'fillX':
901 | case 'fillY':
902 | makeSharedSizeFill(layout);
903 | break;
904 | case 'square':
905 | case 'parent':
906 | case 'custom':
907 | case 'maxfill':
908 | makeSharedSizePack(layout);
909 | break;
910 | }
911 | }
912 |
913 | function makeSharedSizeFill(layout) {
914 |
915 | var minUnit = getMinUnitAmongContainers(layout);
916 |
917 | applySharedUnitOnContainers(minUnit, layout);
918 |
919 | }
920 |
921 | function applySharedUnitOnContainers(minUnit, layout) {
922 |
923 | var parentContainers = getParents(layout.sizeSharingGroup);
924 |
925 | parentContainers.forEach(function (d) {
926 | switch (layout.aspect_ratio) {
927 | case 'fillX':
928 | case 'fillY':
929 | calcFillGridxyVisualSpaceWithUnitLength(d, d.contents, layout, minUnit);
930 | break;
931 | case 'square':
932 | case 'parent':
933 | case 'custom':
934 | case 'maxfill':
935 | calcPackGridxyVisualSpaceWithUnitLength(d, d.contents, layout, minUnit);
936 | }
937 | });
938 | }
939 |
940 | function getMinUnitAmongContainers(layout) {
941 | var parentContainers = getParents(layout.sizeSharingGroup);
942 |
943 | var minUnit = d3.min(parentContainers, function (d) {
944 | var availableSpace = getAvailableSpace(d, layout);
945 | var unit = getUnit(availableSpace, d.contents, layout);
946 | return unit;
947 | });
948 | return minUnit;
949 | }
950 |
951 | function getAvailableSpace(container, layout) {
952 | switch (layout.aspect_ratio) {
953 | case 'fillX':
954 | return container.visualspace.width - container.visualspace.padding.left - container.visualspace.padding.right;
955 | case 'fillY':
956 | return container.visualspace.height - container.visualspace.padding.top - container.visualspace.padding.bottom;
957 | case 'maxfill':
958 | case 'parent':
959 | var width = container.visualspace.width - container.visualspace.padding.left - container.visualspace.padding.right;
960 | var height = container.visualspace.height - container.visualspace.padding.top - container.visualspace.padding.bottom;
961 | return width * height;
962 | case 'square':
963 | var width = container.visualspace.width - container.visualspace.padding.left - container.visualspace.padding.right;
964 | var height = container.visualspace.height - container.visualspace.padding.top - container.visualspace.padding.bottom;
965 | return Math.pow(d3.min([width, height]), 2);
966 | }
967 | }
968 |
969 | function makeSharedSizePack(layout) {
970 | if (layout.size.type === 'uniform') {
971 | var minSize = getMinAmongContainers(layout);
972 | applySharedSizeOnContainers(minSize, layout);
973 | } else {
974 | var minUnit = getMinUnitAmongContainers(layout);
975 | applySharedUnitOnContainers(minUnit, layout);
976 | }
977 | }
978 |
979 | function makeContainers(container, layout) {
980 |
981 | var sharingAncestorContainer = getSharingAncestorContainer(container, layout, 'subgroup');
982 |
983 | var sharingDomain = getSharingDomain(sharingAncestorContainer);
984 | var childContainers;
985 |
986 | switch (layout.subgroup.type) {
987 | case 'groupby':
988 | childContainers = makeContainersForCategoricalVar(sharingDomain, container, layout);
989 | break;
990 | case 'bin':
991 | childContainers = makeContainersForNumericalVar(sharingDomain, container, layout);
992 | break;
993 | case 'passthrough':
994 | childContainers = makeContainersForPassthrough(container, layout);
995 | break;
996 | case 'flatten':
997 | childContainers = makeContainersForFlatten(container, layout);
998 | break;
999 | }
1000 |
1001 | return childContainers;
1002 | }
1003 |
1004 |
1005 |
1006 |
1007 | function makeContainersForPassthrough(container, layout) {
1008 | return [{
1009 | 'contents': container.contents,
1010 | 'label': container.label,
1011 | 'visualspace': {},
1012 | 'parent': container
1013 | }];
1014 | }
1015 |
1016 | function makeContainersForFlatten(container, layout) {
1017 | var leaves = container.contents.map(function (c, i) {
1018 | return {
1019 | 'contents': [c],
1020 | 'label': i,
1021 | 'visualspace': {},
1022 | 'parent': container
1023 | };
1024 | });
1025 |
1026 | if (layout.hasOwnProperty('sort')) {
1027 | leaves.sort(function (a, b) {
1028 | var Avalue = a.contents[0][layout.sort.key];
1029 | var Bvalue = b.contents[0][layout.sort.key];
1030 |
1031 | if (layout.sort.type === 'numerical') {
1032 | Avalue = Number(Avalue);
1033 | Bvalue = Number(Bvalue);
1034 | }
1035 |
1036 | var ascending = (layout.sort.direction === 'ascending') ? 1 : -1
1037 |
1038 | return (Avalue > Bvalue) ? ascending : -1 * ascending;
1039 | });
1040 | }
1041 |
1042 | return leaves;
1043 | }
1044 |
1045 | function makeContainersForCategoricalVar(sharingDomain, container, layout) {
1046 |
1047 | var newContainers = emptyContainersFromKeys(sharingDomain, layout.subgroup.key);
1048 |
1049 | newContainers.forEach(function (c, i, all) {
1050 | c.contents = container.contents.filter(function (d) {
1051 | return d[layout.subgroup.key] == c.label;
1052 | });
1053 | c.parent = container;
1054 | });
1055 | return newContainers;
1056 | }
1057 |
1058 | function makeContainersForNumericalVar(sharingDomain, container, layout) {
1059 |
1060 | var subgroup = layout.subgroup;
1061 |
1062 | var extent = d3.extent(sharingDomain, function (d) {
1063 | return +d[subgroup.key];
1064 | });
1065 |
1066 | var tempScale = d3.scaleLinear().domain([0, subgroup.numBin]).range(extent);
1067 | var tickArray = d3.range(subgroup.numBin + 1).map(tempScale);
1068 |
1069 |
1070 |
1071 | var nullGroup = container.contents.filter(function (d) {
1072 | return d[subgroup.key] == '';
1073 |
1074 | });
1075 |
1076 | var valueGroup = container.contents.filter(function (d) {
1077 | return d[subgroup.key] != '';
1078 | });
1079 |
1080 | var bins = d3.histogram()
1081 | .domain(extent)
1082 | .thresholds(tickArray)
1083 | .value(function (d) {
1084 | return +d[subgroup.key];
1085 | })(valueGroup);
1086 |
1087 | nullGroup = [nullGroup];
1088 | nullGroup.x0 = '';
1089 | nullGroup.x1 = '';
1090 |
1091 | var containers = nullGroup.concat(bins);
1092 |
1093 | containers = containers.map(function (d) {
1094 | return {
1095 | 'contents': d,
1096 | 'label': d.x0 + '-' + d.x1,
1097 | 'visualspace': {},
1098 | 'parent': container
1099 | }
1100 | });
1101 |
1102 | return containers;
1103 |
1104 | }
1105 |
1106 | function getSharingAncestorContainer(container, layout, item) {
1107 |
1108 | if (layout.type === 'flatten') {
1109 | return container;
1110 | }
1111 |
1112 | if (layout[item].isShared) {
1113 | if (container.parent !== 'RootContainer') {
1114 | return getSharingAncestorContainer(container.parent, layout.parent, item);
1115 | }
1116 | }
1117 | return container;
1118 | }
1119 |
1120 | function getSharingDomain(container) {
1121 |
1122 | if (isContainer(container)) {
1123 |
1124 | var leafs = [];
1125 | container.contents.forEach(function (c) {
1126 | var newLeaves = getSharingDomain(c);
1127 |
1128 | newLeaves.forEach(function (d) {
1129 | leafs.push(d);
1130 | });
1131 | });
1132 | return leafs;
1133 |
1134 | } else {
1135 | return [container];
1136 | }
1137 | }
1138 |
1139 |
1140 | function isContainer(container) {
1141 |
1142 | if (container.hasOwnProperty('contents') && container.hasOwnProperty('visualspace') && container.hasOwnProperty('parent')) {
1143 |
1144 | return true;
1145 | }
1146 | return false;
1147 | }
1148 |
1149 | function drawUnit(container, spec, layoutList, divId) {
1150 |
1151 | var layouts = spec.layouts;
1152 | var markPolicy = spec.mark;
1153 |
1154 | var svg = d3.select('#' + divId).append('svg')
1155 | .attr('width', spec.width)
1156 | .attr('height', spec.height);
1157 |
1158 | var rootGroup = svg.selectAll('.root')
1159 | .data([container])
1160 | .enter().append('g')
1161 | .attr('class', 'root')
1162 | .attr('transform', function (d) {
1163 | return 'translate(' + d.visualspace.posX + ', ' + d.visualspace.posY + ')';
1164 | })
1165 |
1166 | var currentGroup = rootGroup;
1167 | layouts.forEach(function (layout) {
1168 |
1169 | var tempGroup = currentGroup.selectAll('.' + layout.name)
1170 | .data(function (d) {
1171 | return d.contents;
1172 | })
1173 | .enter().append('g')
1174 | .attr('class', layout.name)
1175 | .attr('transform', function (d) {
1176 |
1177 | if (isNaN(d.visualspace.posX) || isNaN(d.visualspace.posY)) {
1178 | console.log('NaN happened');
1179 | console.log(spec);
1180 | }
1181 | return 'translate(' + d.visualspace.posX + ', ' + d.visualspace.posY + ')';
1182 | });
1183 |
1184 | tempGroup.append('rect')
1185 | .attr('x', 0)
1186 | .attr('y', 0)
1187 | .attr('width', function (d) {
1188 | return d.visualspace.width;
1189 | })
1190 | .attr('height', function (d) {
1191 | return d.visualspace.height;
1192 | })
1193 | .style('opacity', function (d) {
1194 | if (layout.hasOwnProperty('box') && layout.box.hasOwnProperty('opacity')) {
1195 | return layout.box.opacity;
1196 | } else {
1197 | return defaultSetting.layout.box.opacity;
1198 | }
1199 | })
1200 | .style('fill', function (d) {
1201 | if (layout.hasOwnProperty('box') && layout.box.hasOwnProperty('fill')) {
1202 | return layout.box.fill;
1203 | } else {
1204 | return defaultSetting.layout.box.fill;
1205 | }
1206 | })
1207 | .style('stroke', function (d) {
1208 | if (layout.hasOwnProperty('box') && layout.box.hasOwnProperty('stroke')) {
1209 | return layout.box.stroke;
1210 | } else {
1211 | return defaultSetting.layout.box.stroke;
1212 | }
1213 | })
1214 | .style('stroke-width', function (d) {
1215 | if (layout.hasOwnProperty('box') && layout.box.hasOwnProperty('stroke-width')) {
1216 | return layout.box['stroke-width'];
1217 | } else {
1218 | return defaultSetting.layout.box['stroke-width'];
1219 | }
1220 | });
1221 |
1222 | currentGroup = tempGroup;
1223 |
1224 | });
1225 |
1226 | switch (markPolicy.shape) {
1227 | case "circle":
1228 | var marks = currentGroup.append('circle')
1229 | .attr('cx', function (d) {
1230 | return d.visualspace.width / 2;
1231 | })
1232 | .attr('cy', function (d) {
1233 | return d.visualspace.height / 2;
1234 | })
1235 | .attr('r', function (d) {
1236 | return calcRadius(d, container, markPolicy, layoutList);
1237 | })
1238 | .style('fill', function (d) {
1239 | return 'purple'
1240 | });
1241 | break;
1242 |
1243 | case "rect":
1244 | var marks = currentGroup.append('rect')
1245 | .attr('x', function (d) {
1246 | return 0;
1247 | })
1248 | .attr('y', function (d) {
1249 | return 0;
1250 | })
1251 | .attr('width', function (d) {
1252 | return d.visualspace.width;
1253 | })
1254 | .attr('height', function (d) {
1255 | return d.visualspace.height;
1256 | })
1257 | .style('fill', function (d) {
1258 | return 'purple'
1259 | });;
1260 | break;
1261 | default:
1262 | var marks = currentGroup.append('circle')
1263 | .attr('cx', function (d) {
1264 | return d.visualspace.width / 2;
1265 | })
1266 | .attr('cy', function (d) {
1267 | return d.visualspace.height / 2;
1268 | })
1269 | .attr('r', function (d) {
1270 | return calcRadius(d, container, markPolicy, layoutList);
1271 | })
1272 | .style('fill', function (d) {
1273 | return 'purple'
1274 | });
1275 | break;
1276 |
1277 |
1278 | }
1279 |
1280 | setMarksColor(marks, container, markPolicy, layoutList);
1281 |
1282 | }
1283 |
1284 | function setMarksColor(marks, rootContainer, markPolicy, layoutList) {
1285 | var leafContainersArr = buildLeafContainersArr(rootContainer, layoutList.head);
1286 | var color;
1287 | color = d3.scaleOrdinal(d3.schemeCategory10);
1288 | if (markPolicy.color.type === 'categorical') {
1289 |
1290 | } else {
1291 | console.log('TODO');
1292 | }
1293 | if (markPolicy.color.key === 'survived_text') {
1294 | color("YES");
1295 | color("NO");
1296 | }
1297 | marks.style('fill', function (d) {
1298 | return color(d.contents[0][markPolicy.color.key]);
1299 | });
1300 | }
1301 |
1302 | function calcRadius(leafContainer, rootContainer, markPolicy, layoutList) {
1303 |
1304 | var radius;
1305 | if (markPolicy.size.isShared) {
1306 | radius = calcRadiusShared(leafContainer, rootContainer, markPolicy, layoutList);
1307 | } else {
1308 | radius = calcRadiusIsolated(leafContainer, markPolicy);
1309 | }
1310 | return radius;
1311 | }
1312 |
1313 | function calcRadiusIsolated(leafContainer, markPolicy) {
1314 |
1315 | var width = leafContainer.visualspace.width;
1316 | var height = leafContainer.visualspace.height;
1317 |
1318 | if (markPolicy.size.type === 'max') {
1319 | return width > height ? height / 2.0 : width / 2.0;
1320 | }
1321 | }
1322 |
1323 | function calcRadiusShared(leafContainer, rootContainer, markPolicy, layoutList) {
1324 |
1325 | var radius;
1326 | var leafContainersArr = buildLeafContainersArr(rootContainer, layoutList.head);
1327 |
1328 | return d3.min(leafContainersArr, function (d) {
1329 | return calcRadiusIsolated(d, markPolicy);
1330 | });
1331 | }
1332 |
1333 | function buildLeafContainersArr(container, layout) {
1334 |
1335 | if (layout.child !== 'EndOfLayout') {
1336 |
1337 | var leafs = [];
1338 | container.contents.forEach(function (c) {
1339 | var newLeaves = buildLeafContainersArr(c, layout.child);
1340 |
1341 | newLeaves.forEach(function (d) {
1342 | leafs.push(d);
1343 | });
1344 | });
1345 | return leafs;
1346 |
1347 | } else {
1348 | return container.contents;
1349 | }
1350 | }
1351 |
1352 | // Public API here
1353 | return {
1354 | UnitChart: UnitChart
1355 | };
1356 | });
1357 |
--------------------------------------------------------------------------------
/app/styles/main.css:
--------------------------------------------------------------------------------
1 | .browsehappy {
2 | margin: 0.2em 0;
3 | background: #ccc;
4 | color: #000;
5 | padding: 0.2em 0;
6 | }
7 |
8 | body {
9 | padding: 0;
10 | }
11 |
12 | /* Everything but the jumbotron gets side spacing for mobile first views */
13 | .header,
14 | .marketing,
15 | .footer {
16 | padding-left: 15px;
17 | padding-right: 15px;
18 | }
19 |
20 | /* Custom page header */
21 | .header {
22 | border-bottom: 1px solid #e5e5e5;
23 | margin-bottom: 10px;
24 | }
25 | /* Make the masthead heading the same height as the navigation */
26 | .header h3 {
27 | margin-top: 0;
28 | margin-bottom: 0;
29 | line-height: 40px;
30 | padding-bottom: 19px;
31 | }
32 |
33 | /* Custom page footer */
34 | .footer {
35 | padding-top: 19px;
36 | color: #777;
37 | border-top: 1px solid #e5e5e5;
38 | }
39 |
40 | .container-narrow > hr {
41 | margin: 30px 0;
42 | }
43 |
44 | /* Main marketing message and sign up button */
45 | .jumbotron {
46 | text-align: center;
47 | border-bottom: 1px solid #e5e5e5;
48 | }
49 | .jumbotron .btn {
50 | font-size: 21px;
51 | padding: 14px 24px;
52 | }
53 |
54 | /* Supporting marketing content */
55 | .marketing {
56 | margin: 40px 0;
57 | }
58 | .marketing p + h4 {
59 | margin-top: 28px;
60 | }
61 |
62 | /* Responsive: Portrait tablets and up */
63 | @media screen and (min-width: 768px) {
64 | .container {
65 | max-width: 730px;
66 | }
67 |
68 | /* Remove the padding we set earlier */
69 | .header,
70 | .marketing,
71 | .footer {
72 | padding-left: 0;
73 | padding-right: 0;
74 | }
75 | /* Space out the masthead */
76 | .header {
77 | margin-bottom: 30px;
78 | }
79 | /* Remove the bottom border on the jumbotron for visual effect */
80 | .jumbotron {
81 | border-bottom: 0;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/views/enum.html:
--------------------------------------------------------------------------------
1 | Enumeration Select variables you want to enumerate
2 |
3 |
4 |
5 |
6 | Number of Layers =
7 |
8 |
9 | Don't actually draw, just calculate
10 |
11 |
12 |
13 |
14 | Numer of enumeration:
15 |
16 |
--------------------------------------------------------------------------------
/app/views/example.html:
--------------------------------------------------------------------------------
1 |
2 | Unit Column Chart Layout1 class fillX
3 | Layout2 id packXY
4 |
5 | By setting the size.isShared for second pack layout, we can create absolute version and relative percentage version.
6 | JSON for Left
7 | JSON for Middle
8 | JSON for Right
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | And you can create horizontal unit column chart. In this case Layout1 is fillY and Layout2 is packxy ,direction=BTLR.
21 |
22 | JSON for chart
23 |
24 |
25 |
26 | Hierarchical Sharing Layout1 class fillX
27 | Layout2 gender fillY
28 | Layout3 id packXY
29 | These sharing settings are hierarchical meaning that each level can have its own sharing configuration on/off and these affect to what extent the domain is shared.
30 |
31 | JSON for Top Left (Layout2: True, Layout3: True )
32 |
33 | JSON for Top Right (Layout2: True, Layout3: False )
34 |
35 | JSON for Bottom Left (Layout2: False, Layout3: True)
36 |
37 | JSON for Bottom Right (Layout2: False, Layout3: False)
38 |
39 |
40 |
41 |
47 |
48 |
54 |
55 | Maxfill aspect_ratio Layout1 age PackXY
56 | Layout2 class fillX
57 | Layout3 packXY
58 |
59 | The square aspect_ratio can lead to the empty space. To resolve this, 'maxfill' aspect ratio try to find the an optimal aspect ratio that is close to square while removing empty space.
60 |
61 | JSON for Top (Layout3: aspect_ratio:square)
62 |
63 | JSON for middle (Layout3: aspect_ratio:maxfill )
64 |
65 | JSON for Bottom (Layout3: aspect_ratio:maxfill isShared is true for Layout2 and Layout3)
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Size by function Layout1 class fillX
78 | Layout2 fillY
79 |
80 | "size": { "type": ""sum", "key": "fare"", "isShared": true },
81 |
82 |
83 | Size can be function of the contents. In top left, size is uniform for layout2. In top right, size is a function of sum of fares. In both, case size is not shared
84 | These setting can be combined with "isShared" flag. In bottom left, size is uniform and shared, and in bottom right, size is function of sum of fares and is shared. You can use the following syntax. Here the type can be sum, count, or uniform.
85 | If it is sum, it can have additional "key" parameter which will determine the variables for sum.
86 |
87 | "size": { "type": ""sum", "key": "fare", "isShared": true },
88 |
89 |
90 | JSON for Top Left (Layout2: {"size": {"type":"uniform", "isShared":false}} )
91 |
92 | JSON for Top Right (Layout2: {"size": {"type":"sum", "key":"fare", "isShared":false}} )
93 |
94 | JSON for Bottom Left (Layout2: {"size": {"type":"uniform", "isShared":true}} )
95 |
96 | JSON for Bottom Right (Layout2: {"size": {"type":"sum", "key":"fare", "isShared":true}} )
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Violin Plot
115 | Layout1 class fillX
116 |
Layout2 fillY size uniform, isShared:true
117 |
Layout3 fillX size count, isShared:true
118 |
Layout4 maxfil size uniform, isShared:false
119 |
120 |
JSON for Unit Violin chart
121 |
122 |
123 |
124 | Squarified Bar Chart
125 | Layout1 class fillX
126 |
Layout2 fillX size uniform, isShared:true
127 |
Layout3 fillY size Sum of Fares, isShared:true
128 |
Layout4 maxfil size Sum of Fares, isShared:false
129 |
130 |
JSON for Squarified Bar chart
131 |
132 |
133 |
134 |
135 | Unit Fluctuation Chart
136 | Layout1 gender fillY
137 |
Layout2 class fillX size uniform, isShared:true
138 |
Layout3 passthrough size count, isShared:true
139 |
Layout4 maxfil size uniform, isShared:false
140 |
141 | JSON for Unit Fluctuation chart
142 |
143 |
144 |
145 | Mosaic Plot
146 | Layout1 class fillY, size:count
147 |
Layout2 survived fillX size:count, isShared:false
148 |
Layout3 sex fillY size count, isShared:false
149 |
Layout4 maxfill size uniform, isShared:false
150 |
151 | JSON for Mosaic plot
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/app/views/live.html:
--------------------------------------------------------------------------------
1 |
2 | Edit json and press update button
3 |
4 |
5 |
6 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/app/views/main.html:
--------------------------------------------------------------------------------
1 |
2 |
Unit Visualization Grammar
3 |
4 |
5 | Atom: Unit Visualization Grammar
6 |
7 |
8 |
9 |
10 |
Examples
11 |
Examples of Atom Grammar
12 |
13 |
Live Editor
14 |
Here you can change json specification in editor and see its effect
15 |
16 |
Enumerator
17 |
Calculate the number of enumeration given dataset
18 |
19 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "unit",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "angular": "^1.4.0",
6 | "bootstrap": "^3.2.0",
7 | "angular-animate": "^1.4.0",
8 | "angular-cookies": "^1.4.0",
9 | "angular-resource": "^1.4.0",
10 | "angular-route": "^1.4.0",
11 | "angular-sanitize": "^1.4.0",
12 | "angular-touch": "^1.4.0",
13 | "d3": "^4.2.2",
14 | "jsoneditor": "^5.5.7"
15 | },
16 | "devDependencies": {
17 | "angular-mocks": "^1.4.0"
18 | },
19 | "appPath": "app",
20 | "moduleName": "unitApp",
21 | "overrides": {
22 | "bootstrap": {
23 | "main": [
24 | "less/bootstrap.less",
25 | "dist/css/bootstrap.css",
26 | "dist/js/bootstrap.js"
27 | ]
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "unit",
3 | "private": true,
4 | "devDependencies": {
5 | "autoprefixer-core": "^5.2.1",
6 | "grunt": "^0.4.5",
7 | "grunt-angular-templates": "^0.5.7",
8 | "grunt-build-control": "^0.7.1",
9 | "grunt-concurrent": "^1.0.0",
10 | "grunt-contrib-clean": "^0.6.0",
11 | "grunt-contrib-concat": "^0.5.0",
12 | "grunt-contrib-connect": "^0.9.0",
13 | "grunt-contrib-copy": "^0.7.0",
14 | "grunt-contrib-cssmin": "^0.12.0",
15 | "grunt-contrib-htmlmin": "^0.4.0",
16 | "grunt-contrib-imagemin": "^1.0.0",
17 | "grunt-contrib-jshint": "^0.11.0",
18 | "grunt-contrib-uglify": "^0.7.0",
19 | "grunt-contrib-watch": "^0.6.1",
20 | "grunt-filerev": "^2.1.2",
21 | "grunt-gh-pages": "^2.0.0",
22 | "grunt-google-cdn": "^0.4.3",
23 | "grunt-jscs": "^1.8.0",
24 | "grunt-newer": "^1.1.0",
25 | "grunt-ng-annotate": "^0.9.2",
26 | "grunt-postcss": "^0.5.5",
27 | "grunt-svgmin": "^2.0.0",
28 | "grunt-usemin": "^3.0.0",
29 | "grunt-wiredep": "^2.0.0",
30 | "jasmine-core": "^2.4.1",
31 | "jit-grunt": "^0.9.1",
32 | "jshint-stylish": "^1.0.0",
33 | "karma": "^1.2.0",
34 | "karma-jasmine": "^1.0.2",
35 | "karma-phantomjs-launcher": "^1.0.1",
36 | "phantomjs-prebuilt": "^2.1.12",
37 | "time-grunt": "^1.0.0"
38 | },
39 | "engines": {
40 | "node": ">=0.10.0"
41 | },
42 | "scripts": {
43 | "test": "karma start test/karma.conf.js"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/python/.ipynb_checkpoints/data script-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [],
3 | "metadata": {},
4 | "nbformat": 4,
5 | "nbformat_minor": 0
6 | }
7 |
--------------------------------------------------------------------------------
/python/data script.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "Let's make arbitrary dataset. \n",
8 | "\n",
9 | "Number of Sedan is 2,000 and SUV is 1,000. \n",
10 | "Among sedans, 200 has mechanical and among SUV, 300 has mechanical issue. "
11 | ]
12 | },
13 | {
14 | "cell_type": "code",
15 | "execution_count": 1,
16 | "metadata": {
17 | "collapsed": true
18 | },
19 | "outputs": [],
20 | "source": [
21 | "numSedan = 2000\n",
22 | "numSedanMechanical = 200\n",
23 | "numSUV = 1000\n",
24 | "numSUVMechanical = 300"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "metadata": {
31 | "collapsed": true
32 | },
33 | "outputs": [],
34 | "source": []
35 | }
36 | ],
37 | "metadata": {
38 | "kernelspec": {
39 | "display_name": "Python 2",
40 | "language": "python",
41 | "name": "python2"
42 | },
43 | "language_info": {
44 | "codemirror_mode": {
45 | "name": "ipython",
46 | "version": 2
47 | },
48 | "file_extension": ".py",
49 | "mimetype": "text/x-python",
50 | "name": "python",
51 | "nbconvert_exporter": "python",
52 | "pygments_lexer": "ipython2",
53 | "version": "2.7.12"
54 | }
55 | },
56 | "nbformat": 4,
57 | "nbformat_minor": 0
58 | }
59 |
--------------------------------------------------------------------------------
/python/untitled.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intuinno/unit/186ed809d4a7bce0c1aba99da5de4d997e2d3fbe/python/untitled.txt
--------------------------------------------------------------------------------
/test/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "browser": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "esnext": true,
7 | "jasmine": true,
8 | "latedef": true,
9 | "noarg": true,
10 | "node": true,
11 | "strict": true,
12 | "undef": true,
13 | "unused": true,
14 | "globals": {
15 | "angular": false,
16 | "inject": false
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on 2016-08-23
3 |
4 | module.exports = function(config) {
5 | 'use strict';
6 |
7 | config.set({
8 | // enable / disable watching file and executing tests whenever any file changes
9 | autoWatch: true,
10 |
11 | // base path, that will be used to resolve files and exclude
12 | basePath: '../',
13 |
14 | // testing framework to use (jasmine/mocha/qunit/...)
15 | // as well as any additional frameworks (requirejs/chai/sinon/...)
16 | frameworks: [
17 | 'jasmine'
18 | ],
19 |
20 | // list of files / patterns to load in the browser
21 | files: [
22 | // bower:js
23 | 'bower_components/jquery/dist/jquery.js',
24 | 'bower_components/angular/angular.js',
25 | 'bower_components/bootstrap/dist/js/bootstrap.js',
26 | 'bower_components/angular-animate/angular-animate.js',
27 | 'bower_components/angular-cookies/angular-cookies.js',
28 | 'bower_components/angular-resource/angular-resource.js',
29 | 'bower_components/angular-route/angular-route.js',
30 | 'bower_components/angular-sanitize/angular-sanitize.js',
31 | 'bower_components/angular-touch/angular-touch.js',
32 | 'bower_components/d3/d3.js',
33 | 'bower_components/jsoneditor/dist/jsoneditor.min.js',
34 | 'bower_components/angular-mocks/angular-mocks.js',
35 | // endbower
36 | 'app/scripts/**/*.js',
37 | 'test/mock/**/*.js',
38 | 'test/spec/**/*.js'
39 | ],
40 |
41 | // list of files / patterns to exclude
42 | exclude: [
43 | ],
44 |
45 | // web server port
46 | port: 8080,
47 |
48 | // Start these browsers, currently available:
49 | // - Chrome
50 | // - ChromeCanary
51 | // - Firefox
52 | // - Opera
53 | // - Safari (only Mac)
54 | // - PhantomJS
55 | // - IE (only Windows)
56 | browsers: [
57 | 'PhantomJS'
58 | ],
59 |
60 | // Which plugins to enable
61 | plugins: [
62 | 'karma-phantomjs-launcher',
63 | 'karma-jasmine'
64 | ],
65 |
66 | // Continuous Integration mode
67 | // if true, it capture browsers, run tests and exit
68 | singleRun: false,
69 |
70 | colors: true,
71 |
72 | // level of logging
73 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
74 | logLevel: config.LOG_INFO,
75 |
76 | // Uncomment the following lines if you are using grunt's server to run the tests
77 | // proxies: {
78 | // '/': 'http://localhost:9000/'
79 | // },
80 | // URL root prevent conflicts with the site root
81 | // urlRoot: '_karma_'
82 | });
83 | };
84 |
--------------------------------------------------------------------------------
/test/spec/controllers/about.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: AboutCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('unitApp'));
7 |
8 | var AboutCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | AboutCtrl = $controller('AboutCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(AboutCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/spec/controllers/enum.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: EnumCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('unitApp'));
7 |
8 | var EnumCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | EnumCtrl = $controller('EnumCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(EnumCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/spec/controllers/example.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: ExampleCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('unitApp'));
7 |
8 | var ExampleCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | ExampleCtrl = $controller('ExampleCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(ExampleCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/spec/controllers/live.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: LiveCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('unitApp'));
7 |
8 | var LiveCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | LiveCtrl = $controller('LiveCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(LiveCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/spec/controllers/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Controller: MainCtrl', function () {
4 |
5 | // load the controller's module
6 | beforeEach(module('unitApp'));
7 |
8 | var MainCtrl,
9 | scope;
10 |
11 | // Initialize the controller and a mock scope
12 | beforeEach(inject(function ($controller, $rootScope) {
13 | scope = $rootScope.$new();
14 | MainCtrl = $controller('MainCtrl', {
15 | $scope: scope
16 | // place here mocked dependencies
17 | });
18 | }));
19 |
20 | it('should attach a list of awesomeThings to the scope', function () {
21 | expect(MainCtrl.awesomeThings.length).toBe(3);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/spec/services/unitchart.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Service: UnitChart', function () {
4 |
5 | // load the service's module
6 | beforeEach(module('unitApp'));
7 |
8 | // instantiate service
9 | var UnitChart;
10 | beforeEach(inject(function (_UnitChart_) {
11 | UnitChart = _UnitChart_;
12 | }));
13 |
14 | it('should do something', function () {
15 | expect(!!UnitChart).toBe(true);
16 | });
17 |
18 | });
19 |
--------------------------------------------------------------------------------