guidepost 0.2.14__tar.gz → 0.2.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- guidepost-0.2.15/MANIFEST.in +2 -0
- {guidepost-0.2.14/guidepost.egg-info → guidepost-0.2.15}/PKG-INFO +4 -3
- {guidepost-0.2.14 → guidepost-0.2.15}/README.md +1 -1
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost/guidepost.js +307 -110
- guidepost-0.2.15/guidepost/version.py +2 -0
- {guidepost-0.2.14 → guidepost-0.2.15/guidepost.egg-info}/PKG-INFO +4 -3
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost.egg-info/SOURCES.txt +1 -2
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost.egg-info/top_level.txt +0 -1
- {guidepost-0.2.14 → guidepost-0.2.15}/setup.py +1 -1
- guidepost-0.2.14/figs/guidepost_tutorial_info.png +0 -0
- guidepost-0.2.14/guidepost/version.py +0 -2
- guidepost-0.2.14/tutorials/__init__.py +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/LICENSE +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost/__init__.py +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost/guidepost.py +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost.egg-info/dependency_links.txt +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/guidepost.egg-info/requires.txt +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/pyproject.toml +0 -0
- {guidepost-0.2.14 → guidepost-0.2.15}/setup.cfg +0 -0
- {guidepost-0.2.14/figs → guidepost-0.2.15/tutorials}/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: guidepost
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
4
4
|
Summary: Guidepost. An overview visualization for understanding supercomputer queue data.
|
|
5
5
|
Home-page: https://github.com/cscully-allison/guidepost
|
|
6
6
|
Author: Connor Scully-Allison
|
|
@@ -22,6 +22,7 @@ Dynamic: classifier
|
|
|
22
22
|
Dynamic: description
|
|
23
23
|
Dynamic: description-content-type
|
|
24
24
|
Dynamic: home-page
|
|
25
|
+
Dynamic: license-file
|
|
25
26
|
Dynamic: requires-dist
|
|
26
27
|
Dynamic: requires-python
|
|
27
28
|
Dynamic: summary
|
|
@@ -212,7 +213,7 @@ Guidepost is licensed under the MIT License. See the `LICENSE` file for details.
|
|
|
212
213
|
|
|
213
214
|
## Acknowledgments
|
|
214
215
|
|
|
215
|
-
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL).
|
|
216
|
+
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL), the National Science Foundation under NSF IIS-1844573 and IIS-2324465, and the Department of Energy under DE-SC0022044 and DE-SC0024635.
|
|
216
217
|
|
|
217
218
|
---
|
|
218
219
|
|
|
@@ -184,7 +184,7 @@ Guidepost is licensed under the MIT License. See the `LICENSE` file for details.
|
|
|
184
184
|
|
|
185
185
|
## Acknowledgments
|
|
186
186
|
|
|
187
|
-
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL).
|
|
187
|
+
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL), the National Science Foundation under NSF IIS-1844573 and IIS-2324465, and the Department of Energy under DE-SC0022044 and DE-SC0024635.
|
|
188
188
|
|
|
189
189
|
---
|
|
190
190
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as d3 from "https://esm.sh/d3@7";
|
|
2
|
+
// import * as d3 from "d3";
|
|
3
|
+
|
|
4
|
+
|
|
2
5
|
//layout vars
|
|
3
6
|
const FACET_LAYOUT = {
|
|
4
7
|
outer_margin: 30
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
const OVERVIEW_LAYOUT = {
|
|
8
|
-
width:
|
|
11
|
+
width: 1000,
|
|
9
12
|
height: 300,
|
|
10
13
|
outer_margin: 10,
|
|
11
14
|
inner_padding: 30
|
|
@@ -54,6 +57,8 @@ const num_cols = 150;
|
|
|
54
57
|
|
|
55
58
|
const MIN_BAR_WIDTH = 45;
|
|
56
59
|
|
|
60
|
+
const SHARED_X_SCALE = false
|
|
61
|
+
|
|
57
62
|
// COLORS
|
|
58
63
|
const BLUE = 'rgba(32, 61, 192, 0.7)';
|
|
59
64
|
const RICH_BLUE = 'rgb(32, 61, 192)';
|
|
@@ -377,8 +382,11 @@ class JSModel{
|
|
|
377
382
|
let current_bins = this.faceted_bins[fac].column;
|
|
378
383
|
let sum_stats = this.faceted_sum_stats[fac];
|
|
379
384
|
|
|
385
|
+
// console.log("CALC BOX METRICS: ", fac, current_bins, x_axis_thresholds, y_axis_thresholds);
|
|
386
|
+
|
|
380
387
|
// Iterate over the columns that divide the data along the x axis
|
|
381
388
|
for(let bin in current_bins){
|
|
389
|
+
|
|
382
390
|
let filtered_bin;
|
|
383
391
|
|
|
384
392
|
//Do not filter if no filter is specified currently
|
|
@@ -400,34 +408,72 @@ class JSModel{
|
|
|
400
408
|
temp_box_stats.bins = [];
|
|
401
409
|
|
|
402
410
|
//box bins for this column
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
411
|
+
function binValues(values, thresholds, accessor) {
|
|
412
|
+
const bins = [];
|
|
413
|
+
// Create an empty bin for each interval between consecutive thresholds
|
|
414
|
+
for (let i = 0; i < thresholds.length - 1; i++) {
|
|
415
|
+
bins.push([]);
|
|
416
|
+
}
|
|
417
|
+
// Place each value in the appropriate bin
|
|
418
|
+
values.forEach(d => {
|
|
419
|
+
const val = accessor(d);
|
|
420
|
+
for (let i = 0; i < thresholds.length - 1; i++) {
|
|
421
|
+
// For the last bin, include values equal to the upper bound
|
|
422
|
+
if (val >= thresholds[i] && (i === thresholds.length - 2 || val < thresholds[i + 1])) {
|
|
423
|
+
bins[i].push(d);
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
return bins;
|
|
429
|
+
}
|
|
406
430
|
|
|
431
|
+
const customBins = binValues(filtered_bin, y_axis_thresholds, d => d[this.vars.y]);
|
|
432
|
+
|
|
433
|
+
// Process each bin's summary statistics and update color scale range
|
|
434
|
+
temp_box_stats.bins = customBins.map((bin, index) => {
|
|
435
|
+
const stats = this.get_summary_stats(bin, this.vars.color);
|
|
436
|
+
stats.values = bin;
|
|
437
|
+
stats.std_ratio = stats.std / this.faceted_sum_stats[fac].color.std;
|
|
438
|
+
stats.threshold = y_axis_thresholds[index];
|
|
439
|
+
this.color_scale_range[0] = Math.min(this.color_scale_range[0], stats[this.vars.color_agg]);
|
|
440
|
+
this.color_scale_range[1] = Math.max(this.color_scale_range[1], stats[this.vars.color_agg]);
|
|
441
|
+
return stats;
|
|
442
|
+
});
|
|
407
443
|
|
|
408
|
-
//clamps down last bin(s) if more are produced than desired
|
|
409
|
-
// idk why but d3 produces too many bins sometimes
|
|
410
|
-
if(row_bins.length > y_axis_thresholds.length-1){
|
|
411
|
-
let diff = (y_axis_thresholds.length-1)-row_bins.length;
|
|
412
|
-
let head = row_bins.slice(0, diff);
|
|
413
444
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
row_bins = head;
|
|
418
|
-
}
|
|
445
|
+
// let row_bins = d3.bin()
|
|
446
|
+
// .value(d => d[this.vars.y])
|
|
447
|
+
// .domain([sum_stats.y.min, sum_stats.y.max]).thresholds(y_axis_thresholds)(filtered_bin);
|
|
419
448
|
|
|
420
|
-
//
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
449
|
+
// // console.log("ROW BINS BEFORE CLAMP: ", row_bins.length, y_axis_thresholds.length);
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
// //clamps down last bin(s) if more are produced than desired
|
|
453
|
+
// // idk why but d3 produces too many bins sometimes
|
|
454
|
+
// if(row_bins.length > y_axis_thresholds.length-1){
|
|
455
|
+
// let diff = (y_axis_thresholds.length-1)-row_bins.length;
|
|
456
|
+
// let head = row_bins.slice(0, diff);
|
|
457
|
+
|
|
458
|
+
// for(let i = row_bins.length-1; i > y_axis_thresholds.length-2; i--){
|
|
459
|
+
// head[head.length-1] = head[head.length-1].concat(row_bins[i]);
|
|
460
|
+
// }
|
|
461
|
+
// row_bins = head;
|
|
462
|
+
// }
|
|
463
|
+
|
|
464
|
+
// // console.log("ROW BINS AFTER CLAMP: ", row_bins.length, y_axis_thresholds.length);
|
|
465
|
+
|
|
466
|
+
// //load individual boxes of values with summary statistics describing them
|
|
467
|
+
// for(let index in row_bins){
|
|
468
|
+
// let row = row_bins[index];
|
|
469
|
+
// let sum_stats = this.get_summary_stats(row, this.vars.color);
|
|
470
|
+
// sum_stats.values = row;
|
|
471
|
+
// sum_stats['std_ratio'] = sum_stats.std/this.faceted_sum_stats[fac].color.std;
|
|
472
|
+
// sum_stats.threshold = y_axis_thresholds[index];
|
|
473
|
+
// temp_box_stats.bins.push(sum_stats);
|
|
474
|
+
// this.color_scale_range[0] = Math.min(this.color_scale_range[0], sum_stats[this.vars.color_agg]);
|
|
475
|
+
// this.color_scale_range[1] = Math.max(this.color_scale_range[1], sum_stats[this.vars.color_agg]);
|
|
476
|
+
// }
|
|
431
477
|
|
|
432
478
|
temp_box_stats.column_values = filtered_bin;
|
|
433
479
|
this.faceted_bins[fac].column[bin] = temp_box_stats;
|
|
@@ -443,7 +489,21 @@ class JSModel{
|
|
|
443
489
|
* @returns {Array} - The sanitized and initialized data.
|
|
444
490
|
*/
|
|
445
491
|
sanitize_and_intialize_data(data){
|
|
446
|
-
this.global_sum_stats = {
|
|
492
|
+
this.global_sum_stats = {
|
|
493
|
+
x:{
|
|
494
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
495
|
+
min: Number.MAX_SAFE_INTEGER
|
|
496
|
+
},
|
|
497
|
+
y:{
|
|
498
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
499
|
+
min: Number.MAX_SAFE_INTEGER
|
|
500
|
+
},
|
|
501
|
+
color:{
|
|
502
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
503
|
+
min: Number.MAX_SAFE_INTEGER
|
|
504
|
+
},
|
|
505
|
+
num_cols: 0
|
|
506
|
+
};
|
|
447
507
|
for(let fac of this.facets){
|
|
448
508
|
//store data about what types of scales x and y are
|
|
449
509
|
this.scale_types[fac] = {
|
|
@@ -466,14 +526,6 @@ class JSModel{
|
|
|
466
526
|
}
|
|
467
527
|
|
|
468
528
|
|
|
469
|
-
// this.global_sum_stats.x.max = Math.max(this.faceted_sum_stats[fac].x.max, this.global_sum_stats.x.max);
|
|
470
|
-
// this.global_sum_stats.y.max = Math.max(this.faceted_sum_stats[fac].y.max, this.global_sum_stats.y.max);
|
|
471
|
-
// this.global_sum_stats.color.max = Math.max(this.faceted_sum_stats[fac].color.max, this.global_sum_stats.color.max);
|
|
472
|
-
|
|
473
|
-
// this.global_sum_stats.x.min = Math.min(this.faceted_sum_stats[fac].x.min, this.global_sum_stats.x.min);
|
|
474
|
-
// this.global_sum_stats.y.min = Math.min(this.faceted_sum_stats[fac].y.min, this.global_sum_stats.y.min);
|
|
475
|
-
// this.global_sum_stats.color.min = Math.min(this.faceted_sum_stats[fac].color.min, this.global_sum_stats.color.max);
|
|
476
|
-
|
|
477
529
|
|
|
478
530
|
data[fac] = this.sanitize_data_for_log(data[fac], this.vars.y);
|
|
479
531
|
|
|
@@ -484,9 +536,20 @@ class JSModel{
|
|
|
484
536
|
|
|
485
537
|
let sum_stats = this.faceted_sum_stats[fac];
|
|
486
538
|
|
|
539
|
+
this.global_sum_stats.x.max = Math.max(this.faceted_sum_stats[fac].x.max, this.global_sum_stats.x.max);
|
|
540
|
+
this.global_sum_stats.y.max = Math.max(this.faceted_sum_stats[fac].y.max, this.global_sum_stats.y.max);
|
|
541
|
+
this.global_sum_stats.color.max = Math.max(this.faceted_sum_stats[fac].color.max, this.global_sum_stats.color.max);
|
|
542
|
+
|
|
543
|
+
this.global_sum_stats.x.min = Math.min(this.faceted_sum_stats[fac].x.min, this.global_sum_stats.x.min);
|
|
544
|
+
this.global_sum_stats.y.min = Math.min(this.faceted_sum_stats[fac].y.min, this.global_sum_stats.y.min);
|
|
545
|
+
this.global_sum_stats.color.min = Math.min(this.faceted_sum_stats[fac].color.min, this.global_sum_stats.color.max);
|
|
546
|
+
|
|
487
547
|
|
|
488
548
|
this.faceted_bins[fac] = {}
|
|
489
549
|
|
|
550
|
+
|
|
551
|
+
console.log("SUM STATS: ", fac, sum_stats);
|
|
552
|
+
|
|
490
553
|
//conditional x axis thresholds based on time or numbers
|
|
491
554
|
// important for calculating the scales which layout the columns
|
|
492
555
|
// of the "heatmap"
|
|
@@ -503,7 +566,7 @@ class JSModel{
|
|
|
503
566
|
// just do linerats if not
|
|
504
567
|
if(this.is_more_than_n_orders_of_magnitude(sum_stats.x.min, sum_stats.x.max, 3)){
|
|
505
568
|
this.scale_types[fac].x.log = true;
|
|
506
|
-
this.x_axis_thresholds[fac] = this.logScale(this.log_values_floor, sum_stats.x.max, num_cols);
|
|
569
|
+
this.x_axis_thresholds[fac] = this.logScale(this.log_values_floor, sum_stats.x.max+1, num_cols-1);
|
|
507
570
|
this.faceted_bins[fac].column = d3.bin()
|
|
508
571
|
.value(d => d[this.vars.x])
|
|
509
572
|
.domain([this.log_values_floor, sum_stats.x.max])
|
|
@@ -512,7 +575,7 @@ class JSModel{
|
|
|
512
575
|
}
|
|
513
576
|
else{
|
|
514
577
|
this.scale_types[fac].x.linear = true;
|
|
515
|
-
this.x_axis_thresholds[fac] = this.linearScale(sum_stats.x.min, sum_stats.x.max,
|
|
578
|
+
this.x_axis_thresholds[fac] = this.linearScale(sum_stats.x.min, sum_stats.x.max+1, num_cols-1);
|
|
516
579
|
this.faceted_bins[fac].column = d3.bin()
|
|
517
580
|
.value(d => d[this.vars.x])
|
|
518
581
|
.domain([sum_stats.x.min, sum_stats.x.max])
|
|
@@ -524,9 +587,11 @@ class JSModel{
|
|
|
524
587
|
if(this.is_more_than_n_orders_of_magnitude(sum_stats.y.min, sum_stats.y.max, 3)){
|
|
525
588
|
this.scale_types[fac].y.log = true;
|
|
526
589
|
this.y_axis_thresholds[fac] = this.logScale(this.log_values_floor, sum_stats.y.max, num_rows);
|
|
590
|
+
console.log("Y AXIS THRESHOLDS LOG: ", fac, this.y_axis_thresholds[fac].length);
|
|
527
591
|
} else {
|
|
528
592
|
this.scale_types[fac].y.linear = true;
|
|
529
593
|
this.y_axis_thresholds[fac] = this.linearScale(sum_stats.y.min, sum_stats.y.max, num_rows);
|
|
594
|
+
console.log("Y AXIS THRESHOLDS LINEAR: ", fac, this.y_axis_thresholds[fac].length);
|
|
530
595
|
}
|
|
531
596
|
|
|
532
597
|
sum_stats.col_counts = {
|
|
@@ -539,6 +604,9 @@ class JSModel{
|
|
|
539
604
|
sum_stats.col_counts.min = Math.min(sum_stats.col_counts.min, bin.length);
|
|
540
605
|
}
|
|
541
606
|
|
|
607
|
+
|
|
608
|
+
this.global_sum_stats.num_cols = Math.max(this.faceted_bins[fac].column.length, this.global_sum_stats.num_cols);
|
|
609
|
+
|
|
542
610
|
// temporary as Y AXIS IS FIXED LOG
|
|
543
611
|
this.calculate_box_metrics(fac, this.x_axis_thresholds[fac], this.y_axis_thresholds[fac]);
|
|
544
612
|
this.calc_row_major_counts(fac);
|
|
@@ -554,6 +622,7 @@ class JSModel{
|
|
|
554
622
|
this.categorical_bins[fac] = Object.keys(cat_counts).map((key) => { return {"key": key, "val":cat_counts[key]} }).sort((a, b) => b['val'] - a['val']);
|
|
555
623
|
}
|
|
556
624
|
|
|
625
|
+
|
|
557
626
|
return data;
|
|
558
627
|
}
|
|
559
628
|
|
|
@@ -582,8 +651,6 @@ class JSModel{
|
|
|
582
651
|
*/
|
|
583
652
|
filter_data_by_category(filter, facet, source, targets){
|
|
584
653
|
|
|
585
|
-
console.log("DATA FILTERS: ", filter)
|
|
586
|
-
|
|
587
654
|
this.faceted_states[facet].filter = filter;
|
|
588
655
|
|
|
589
656
|
// is anything pinned
|
|
@@ -635,9 +702,6 @@ class JSModel{
|
|
|
635
702
|
|
|
636
703
|
}
|
|
637
704
|
|
|
638
|
-
console.log(this.brushed_ranges[facet].x_range, this.brushed_ranges[facet].y_range);
|
|
639
|
-
|
|
640
|
-
|
|
641
705
|
|
|
642
706
|
if(this.brushed_ranges[facet].x_range.length != 0){
|
|
643
707
|
for(let bin of this.faceted_bins[facet].column){
|
|
@@ -683,8 +747,6 @@ class JSModel{
|
|
|
683
747
|
}
|
|
684
748
|
}
|
|
685
749
|
|
|
686
|
-
console.log("TEST", test);
|
|
687
|
-
|
|
688
750
|
this.anywidget_model.set("selected_records", JSON.stringify(return_ids));
|
|
689
751
|
this.anywidget_model.save_changes();
|
|
690
752
|
|
|
@@ -815,7 +877,7 @@ class SmartScale {
|
|
|
815
877
|
if(this.model.is_more_than_n_orders_of_magnitude(this.domain[0], this.domain[1], 3)){
|
|
816
878
|
return d3.scaleLog().domain([this.model.log_values_floor, this.domain[1]]).range(this.range);
|
|
817
879
|
} else {
|
|
818
|
-
return d3.scaleLinear().domain(
|
|
880
|
+
return d3.scaleLinear().domain(this.domain).range(this.range);
|
|
819
881
|
}
|
|
820
882
|
} else {
|
|
821
883
|
throw new Error("Unsupported domain type");
|
|
@@ -894,16 +956,23 @@ class Heatmap{
|
|
|
894
956
|
// .domain(this.model.faceted_bins[this.facet].column.keys())
|
|
895
957
|
// .range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width - OVERVIEW_LAYOUT.inner_padding]);
|
|
896
958
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
959
|
+
|
|
960
|
+
if(SHARED_X_SCALE){
|
|
961
|
+
this.scale_x = new SmartScale([this.model.global_sum_stats.x.min, this.model.global_sum_stats.x.max],
|
|
962
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
963
|
+
this.model);
|
|
964
|
+
}
|
|
965
|
+
else{
|
|
966
|
+
this.scale_x = new SmartScale([sum_stats.x.min, sum_stats.x.max],
|
|
967
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
968
|
+
this.model);
|
|
969
|
+
|
|
970
|
+
}
|
|
971
|
+
|
|
903
972
|
|
|
904
973
|
//Determine if y scale is log or linear based on input data
|
|
905
|
-
console.log(this.model.scale_types[this.facet]);
|
|
906
974
|
if(this.model.scale_types[this.facet].y.log){
|
|
975
|
+
|
|
907
976
|
this.scale_y = d3.scaleLog()
|
|
908
977
|
.domain([this.model.log_values_floor, sum_stats.y.max])
|
|
909
978
|
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
@@ -1043,19 +1112,24 @@ class Heatmap{
|
|
|
1043
1112
|
* Raises and zooms on a column slightly
|
|
1044
1113
|
*/
|
|
1045
1114
|
focus_col(update_element){
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1115
|
+
let self = this;
|
|
1116
|
+
let base_width;
|
|
1117
|
+
if(SHARED_X_SCALE){
|
|
1118
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1119
|
+
}
|
|
1120
|
+
else{
|
|
1121
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
self.scale_y_blocks.range([OVERVIEW_LAYOUT.inner_padding-(zoom_factor_v/2), OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding + (zoom_factor_v/2)]);
|
|
1051
1125
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
update_element.selectAll('.row')
|
|
1055
|
-
.attr('width', ()=>{return base_width + zoom_factor_h})
|
|
1056
|
-
.attr('height', ()=>{return ( (OVERVIEW_LAYOUT.height + zoom_factor_v) - 2*OVERVIEW_LAYOUT.inner_padding) / self.model.faceted_bins[self.facet].column[0].bins.length})
|
|
1057
|
-
.attr('y', (d, i)=>{return self.scale_y_blocks(i) - OVERVIEW_LAYOUT.inner_padding});
|
|
1126
|
+
update_element.raise();
|
|
1058
1127
|
|
|
1128
|
+
update_element.selectAll('.row')
|
|
1129
|
+
.attr('width', ()=>{return base_width + zoom_factor_h})
|
|
1130
|
+
.attr('height', ()=>{return ( (OVERVIEW_LAYOUT.height + zoom_factor_v) - 2*OVERVIEW_LAYOUT.inner_padding) / self.model.faceted_bins[self.facet].column[0].bins.length})
|
|
1131
|
+
.attr('y', (d, i)=>{return self.scale_y_blocks(i) - OVERVIEW_LAYOUT.inner_padding});
|
|
1132
|
+
|
|
1059
1133
|
update_element.selectAll('.col-bg')
|
|
1060
1134
|
.attr('width', ()=>{return base_width + zoom_factor_h})
|
|
1061
1135
|
.attr('height', ()=>{return ( (OVERVIEW_LAYOUT.height + zoom_factor_v) - 2*OVERVIEW_LAYOUT.inner_padding)})
|
|
@@ -1075,9 +1149,14 @@ class Heatmap{
|
|
|
1075
1149
|
*/
|
|
1076
1150
|
unfocus_col(update_element){
|
|
1077
1151
|
let self = this;
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1152
|
+
let base_width;
|
|
1153
|
+
if(SHARED_X_SCALE){
|
|
1154
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1155
|
+
}
|
|
1156
|
+
else{
|
|
1157
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1081
1160
|
self.scale_y_blocks.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1082
1161
|
|
|
1083
1162
|
|
|
@@ -1130,9 +1209,16 @@ class Heatmap{
|
|
|
1130
1209
|
render(){
|
|
1131
1210
|
const self = this;
|
|
1132
1211
|
|
|
1133
|
-
console.log(this.model.faceted_bins[this.facet].column);
|
|
1134
1212
|
|
|
1135
|
-
let base_width =
|
|
1213
|
+
let base_width = 0;
|
|
1214
|
+
if(SHARED_X_SCALE){
|
|
1215
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1216
|
+
}
|
|
1217
|
+
else{
|
|
1218
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
|
|
1136
1222
|
|
|
1137
1223
|
if(self.model.row_major_counts[self.facet].length < 2){
|
|
1138
1224
|
this.view
|
|
@@ -1142,6 +1228,7 @@ class Heatmap{
|
|
|
1142
1228
|
.attr('transform', `translate(${draw_width/2},${draw_height/2})`)
|
|
1143
1229
|
}
|
|
1144
1230
|
else{
|
|
1231
|
+
|
|
1145
1232
|
this.view
|
|
1146
1233
|
.selectAll('.column')
|
|
1147
1234
|
.data(this.model.faceted_bins[this.facet].column)
|
|
@@ -1214,6 +1301,9 @@ class Heatmap{
|
|
|
1214
1301
|
)
|
|
1215
1302
|
col.on('mouseenter', function (e, d){
|
|
1216
1303
|
delete self.cached_bins['hover'];
|
|
1304
|
+
|
|
1305
|
+
console.log("HOVERING OVER: ", d);
|
|
1306
|
+
|
|
1217
1307
|
self.focus_col(d3.select(e.target));
|
|
1218
1308
|
if(!Object.keys(self.cached_bins).includes(String(d.threshold))){
|
|
1219
1309
|
let dt_text_selection = d3.select(e.target).select('.text-field');
|
|
@@ -1364,10 +1454,17 @@ class Histogram{
|
|
|
1364
1454
|
let y_offset = Y_VARIABLE_OFFSET + OVERVIEW_LAYOUT.height + HISTOGRAM_LAYOUT.outer_margin;
|
|
1365
1455
|
|
|
1366
1456
|
|
|
1457
|
+
|
|
1367
1458
|
//create the histograms
|
|
1368
1459
|
let h_hist = this.parent.append('g')
|
|
1369
1460
|
.attr('class', 'faceted-h-hist')
|
|
1370
1461
|
.attr('transform', `translate(${x_offset},${y_offset})`);
|
|
1462
|
+
|
|
1463
|
+
h_hist.append('rect')
|
|
1464
|
+
.attr('width', this.width - 2*HISTOGRAM_LAYOUT.inner_padding)
|
|
1465
|
+
.attr('height', this.height - HISTOGRAM_LAYOUT.inner_padding)
|
|
1466
|
+
.attr('fill', 'rgba(240,240,240)')
|
|
1467
|
+
.attr('transform', `translate(${HISTOGRAM_LAYOUT.inner_padding},${0})`);;
|
|
1371
1468
|
|
|
1372
1469
|
h_hist.append('g')
|
|
1373
1470
|
.attr('class', 'left-axis')
|
|
@@ -1389,7 +1486,12 @@ class Histogram{
|
|
|
1389
1486
|
.attr('text-anchor', 'middle')
|
|
1390
1487
|
.attr('transform', `translate(${this.width/2},${this.height})`);
|
|
1391
1488
|
|
|
1489
|
+
|
|
1490
|
+
h_hist.append("g")
|
|
1491
|
+
.attr('class', 'bars');
|
|
1492
|
+
|
|
1392
1493
|
this.view = h_hist;
|
|
1494
|
+
|
|
1393
1495
|
|
|
1394
1496
|
this.brush = d3.brushX()
|
|
1395
1497
|
.extent([[OVERVIEW_LAYOUT.inner_padding, 0], [OVERVIEW_LAYOUT.width - OVERVIEW_LAYOUT.inner_padding, this.height-HISTOGRAM_LAYOUT.inner_padding]])
|
|
@@ -1400,9 +1502,8 @@ class Histogram{
|
|
|
1400
1502
|
select = selection.map(self.scale_x.scale.invert, self.scale_x.scale).map(d3.utcDay.round);
|
|
1401
1503
|
}
|
|
1402
1504
|
if(self.model.scale_types[self.facet]['x']['log'] || self.model.scale_types[self.facet]['x']['linear']){
|
|
1403
|
-
select = selection.map(self.scale_x.scale.invert, self.scale_x.scale).map((d)=>{return
|
|
1505
|
+
select = selection.map(self.scale_x.scale.invert, self.scale_x.scale).map((d)=>{return d});
|
|
1404
1506
|
}
|
|
1405
|
-
console.log(select);
|
|
1406
1507
|
}else{
|
|
1407
1508
|
select = [];
|
|
1408
1509
|
}
|
|
@@ -1410,46 +1511,62 @@ class Histogram{
|
|
|
1410
1511
|
});
|
|
1411
1512
|
|
|
1412
1513
|
h_hist.append("g")
|
|
1514
|
+
.attr('class', 'h-brush')
|
|
1413
1515
|
.call(this.brush);
|
|
1414
1516
|
}
|
|
1415
1517
|
|
|
1416
1518
|
|
|
1417
1519
|
else if(this.orientation == 'right'){
|
|
1418
1520
|
|
|
1419
|
-
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width;
|
|
1521
|
+
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width - 5;
|
|
1420
1522
|
let y_offset = Y_VARIABLE_OFFSET + VERT_HISTOGRAM_LAYOUT.outer_margin;
|
|
1421
1523
|
|
|
1422
1524
|
let v_hist = this.parent.append('g')
|
|
1423
1525
|
.attr('class', 'faceted-v-hist')
|
|
1424
1526
|
.attr('transform', `translate(${x_offset},${y_offset})`);
|
|
1425
1527
|
|
|
1528
|
+
v_hist.append('rect')
|
|
1529
|
+
.attr('width', this.width)
|
|
1530
|
+
.attr('height', this.height - 2*HISTOGRAM_LAYOUT.inner_padding)
|
|
1531
|
+
.attr('fill', 'rgba(240,240,240)')
|
|
1532
|
+
.attr('transform', `translate(${0},${HISTOGRAM_LAYOUT.inner_padding})`);
|
|
1533
|
+
;
|
|
1534
|
+
|
|
1426
1535
|
v_hist.append('g')
|
|
1427
1536
|
.attr('class', 'bot-axis')
|
|
1428
1537
|
.call(d3.axisBottom().scale(this.scale_x).ticks(5))
|
|
1429
1538
|
.attr('transform', `translate(${VERT_HISTOGRAM_LAYOUT.inner_padding*4},${VERT_HISTOGRAM_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding})`);
|
|
1430
1539
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1540
|
+
v_hist.append('g')
|
|
1541
|
+
.attr('class', 'left-axis')
|
|
1542
|
+
.call(d3.axisRight().scale(this.axis_scale_y_inverse))
|
|
1543
|
+
.attr('transform', `translate(${self.width-VERT_HISTOGRAM_LAYOUT.inner_padding},${0})`);
|
|
1435
1544
|
|
|
1436
1545
|
this.brush = d3.brushY()
|
|
1437
1546
|
.extent([[0, HISTOGRAM_LAYOUT.inner_padding], [this.width, this.height - OVERVIEW_LAYOUT.inner_padding]])
|
|
1438
1547
|
.on("end", function({selection}){
|
|
1439
1548
|
let select;
|
|
1440
1549
|
if(selection){
|
|
1441
|
-
select = selection.map(self.scale_y.invert, self.scale_y).map((d)=>{return
|
|
1550
|
+
select = selection.map(self.scale_y.invert, self.scale_y).map((d)=>{return d+0.1})
|
|
1442
1551
|
}else{
|
|
1443
1552
|
select = [];
|
|
1444
1553
|
}
|
|
1445
1554
|
self.model.update_subselected_data(self.facet, [`${self.facet}_heatmap`, `${self.facet}_legend`], select, "y");
|
|
1446
1555
|
});
|
|
1447
1556
|
|
|
1557
|
+
|
|
1558
|
+
v_hist.append("g")
|
|
1559
|
+
.attr('class', 'bars');
|
|
1560
|
+
|
|
1448
1561
|
v_hist.append("g")
|
|
1562
|
+
.attr('class', 'v-brush')
|
|
1449
1563
|
.call(this.brush);
|
|
1450
1564
|
|
|
1451
1565
|
this.view = v_hist;
|
|
1452
1566
|
}
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1453
1570
|
}
|
|
1454
1571
|
|
|
1455
1572
|
/**
|
|
@@ -1469,20 +1586,56 @@ class Histogram{
|
|
|
1469
1586
|
|
|
1470
1587
|
//references OVERVIEW LAYOUT SIZES
|
|
1471
1588
|
//BE CAREFUL
|
|
1472
|
-
|
|
1589
|
+
if(SHARED_X_SCALE){
|
|
1590
|
+
this.scale_x = new SmartScale([this.model.global_sum_stats.x.min, this.model.global_sum_stats.x.max],
|
|
1473
1591
|
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
1474
1592
|
this.model);
|
|
1593
|
+
}
|
|
1594
|
+
else{
|
|
1595
|
+
this.scale_x = new SmartScale([sum_stats.x.min, sum_stats.x.max],
|
|
1596
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
1597
|
+
this.model);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1475
1600
|
}
|
|
1476
1601
|
|
|
1477
1602
|
else if(this.orientation == 'right'){
|
|
1478
1603
|
|
|
1479
|
-
this.
|
|
1604
|
+
if(this.model.is_more_than_n_orders_of_magnitude(0, Math.max(...this.model.row_major_counts[this.facet]), 3)){
|
|
1605
|
+
let local_log_floor = 0.3
|
|
1606
|
+
this.scale_x = d3.scaleLog()
|
|
1607
|
+
.domain([local_log_floor, Math.max(...this.model.row_major_counts[this.facet])])
|
|
1608
|
+
.range([0, VERT_HISTOGRAM_LAYOUT.width - VERT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1609
|
+
}else{
|
|
1610
|
+
this.scale_x = d3.scaleLinear()
|
|
1611
|
+
.domain([0, Math.max(...this.model.row_major_counts[this.facet])])
|
|
1612
|
+
.range([0, VERT_HISTOGRAM_LAYOUT.width - VERT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
if(this.model.scale_types[this.facet].y.log){
|
|
1617
|
+
this.axis_scale_y = d3.scaleLog()
|
|
1618
|
+
.domain([this.model.log_values_floor, sum_stats.y.max])
|
|
1619
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1620
|
+
|
|
1621
|
+
this.axis_scale_y_inverse = d3.scaleLog()
|
|
1622
|
+
.domain([sum_stats.y.max, this.model.log_values_floor])
|
|
1623
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1624
|
+
}
|
|
1625
|
+
else if(this.model.scale_types[this.facet].y.linear){
|
|
1626
|
+
this.axis_scale_y = d3.scaleLinear()
|
|
1627
|
+
.domain([sum_stats.y.min, sum_stats.y.max])
|
|
1628
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1629
|
+
|
|
1630
|
+
this.axis_scale_y_inverse = d3.scaleLinear()
|
|
1631
|
+
.domain([sum_stats.y.max, sum_stats.y.min])
|
|
1632
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
this.scale_y = d3.scaleLinear()
|
|
1480
1636
|
.domain([num_rows-2, -1])
|
|
1481
1637
|
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1482
1638
|
|
|
1483
|
-
this.scale_x = d3.scaleLinear()
|
|
1484
|
-
.domain([0, Math.max(...this.model.row_major_counts[this.facet])])
|
|
1485
|
-
.range([0, VERT_HISTOGRAM_LAYOUT.width - VERT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1486
1639
|
}
|
|
1487
1640
|
}
|
|
1488
1641
|
|
|
@@ -1491,12 +1644,21 @@ class Histogram{
|
|
|
1491
1644
|
*/
|
|
1492
1645
|
render(){
|
|
1493
1646
|
const self = this;
|
|
1494
|
-
let bar_width =
|
|
1647
|
+
let bar_width = 0;
|
|
1648
|
+
if(SHARED_X_SCALE){
|
|
1649
|
+
bar_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1650
|
+
}
|
|
1651
|
+
else{
|
|
1652
|
+
bar_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
let bar_layer = this.view.select('.bars');
|
|
1495
1656
|
|
|
1657
|
+
|
|
1496
1658
|
if(self.model.row_major_counts[self.facet].length > 2){
|
|
1497
1659
|
if(this.orientation == 'bottom'){
|
|
1498
|
-
|
|
1499
|
-
.data(self.model.faceted_bins[self.facet].column, function(
|
|
1660
|
+
bar_layer.selectAll('.column')
|
|
1661
|
+
.data(self.model.faceted_bins[self.facet].column, function(){return this.id} )
|
|
1500
1662
|
.join(
|
|
1501
1663
|
function(enter){
|
|
1502
1664
|
let col = enter.append('g')
|
|
@@ -1524,8 +1686,7 @@ class Histogram{
|
|
|
1524
1686
|
}
|
|
1525
1687
|
|
|
1526
1688
|
if(this.orientation == "right"){
|
|
1527
|
-
|
|
1528
|
-
.selectAll('.row')
|
|
1689
|
+
bar_layer.selectAll('.row')
|
|
1529
1690
|
.data(self.model.row_major_counts[self.facet])
|
|
1530
1691
|
.join(
|
|
1531
1692
|
function(enter){
|
|
@@ -1535,7 +1696,9 @@ class Histogram{
|
|
|
1535
1696
|
|
|
1536
1697
|
row.append('rect')
|
|
1537
1698
|
.attr('class', 'bar')
|
|
1538
|
-
.attr('width', (d)=>{
|
|
1699
|
+
.attr('width', (d)=>{
|
|
1700
|
+
return self.scale_x(d) ? self.scale_x(d) : 0;
|
|
1701
|
+
})
|
|
1539
1702
|
.attr('height', (d)=>{return draw_height / self.model.faceted_bins[self.facet].column[0].bins.length})
|
|
1540
1703
|
.attr('fill', TAN);
|
|
1541
1704
|
|
|
@@ -1544,7 +1707,9 @@ class Histogram{
|
|
|
1544
1707
|
function(update){
|
|
1545
1708
|
update.select('.bar')
|
|
1546
1709
|
.transition()
|
|
1547
|
-
.attr('width', (d)=>{
|
|
1710
|
+
.attr('width', (d)=>{
|
|
1711
|
+
return self.scale_x(d) ? self.scale_x(d) : 0;
|
|
1712
|
+
});
|
|
1548
1713
|
},
|
|
1549
1714
|
function(exit){
|
|
1550
1715
|
exit.remove();
|
|
@@ -1552,6 +1717,7 @@ class Histogram{
|
|
|
1552
1717
|
)
|
|
1553
1718
|
}
|
|
1554
1719
|
}
|
|
1720
|
+
|
|
1555
1721
|
}
|
|
1556
1722
|
}
|
|
1557
1723
|
|
|
@@ -1586,8 +1752,8 @@ class CategoricalBarChart{
|
|
|
1586
1752
|
|
|
1587
1753
|
//create the histograms
|
|
1588
1754
|
|
|
1589
|
-
let x_offset = X_VARIABLE_OFFSET +
|
|
1590
|
-
let y_offset = Y_VARIABLE_OFFSET +
|
|
1755
|
+
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width;
|
|
1756
|
+
let y_offset = Y_VARIABLE_OFFSET + HISTOGRAM_LAYOUT.outer_margin + OVERVIEW_LAYOUT.height ;
|
|
1591
1757
|
|
|
1592
1758
|
let h_hist = this.parent.append('g')
|
|
1593
1759
|
.attr('class', 'faceted-h-hist')
|
|
@@ -1648,15 +1814,31 @@ class CategoricalBarChart{
|
|
|
1648
1814
|
setup_scales(){
|
|
1649
1815
|
this.n = Math.min(this.model.categorical_bins[this.facet].length, this.n);
|
|
1650
1816
|
let top_n_cats = this.model.categorical_bins[this.facet].slice(0,this.n);
|
|
1817
|
+
|
|
1818
|
+
this.max_bar_width = 30;
|
|
1819
|
+
this.drawable_width = (this.width-2*CAT_HISTOGRAM_LAYOUT.inner_padding);
|
|
1820
|
+
this.calc_bar_width = Math.min(this.max_bar_width, this.drawable_width/this.n);
|
|
1651
1821
|
|
|
1652
1822
|
if(this.orientation == 'bottom'){
|
|
1653
|
-
this.
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1823
|
+
if(this.model.is_more_than_n_orders_of_magnitude(0, top_n_cats[0].val, 3)){
|
|
1824
|
+
let local_log_floor = 0.3
|
|
1825
|
+
this.scale_y = d3.scaleLog()
|
|
1826
|
+
.domain([local_log_floor, top_n_cats[0].val])
|
|
1827
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1828
|
+
|
|
1829
|
+
this.scale_y_inverse = d3.scaleLog()
|
|
1830
|
+
.domain([top_n_cats[0].val, local_log_floor])
|
|
1831
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1832
|
+
}
|
|
1833
|
+
else{
|
|
1834
|
+
this.scale_y = d3.scaleLinear()
|
|
1835
|
+
.domain([0, top_n_cats[0].val])
|
|
1836
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1837
|
+
|
|
1838
|
+
this.scale_y_inverse = d3.scaleLinear()
|
|
1839
|
+
.domain([top_n_cats[0].val, 0])
|
|
1840
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1841
|
+
}
|
|
1660
1842
|
|
|
1661
1843
|
//references OVERVIEW LAYOUT SIZES
|
|
1662
1844
|
//BE CAREFUL
|
|
@@ -1664,7 +1846,8 @@ class CategoricalBarChart{
|
|
|
1664
1846
|
.domain(top_n_cats.map((obj)=>{
|
|
1665
1847
|
return obj.key;
|
|
1666
1848
|
}))
|
|
1667
|
-
.range([CAT_HISTOGRAM_LAYOUT.inner_padding, this.width - CAT_HISTOGRAM_LAYOUT.inner_padding])
|
|
1849
|
+
.range([CAT_HISTOGRAM_LAYOUT.inner_padding, this.width - CAT_HISTOGRAM_LAYOUT.inner_padding])
|
|
1850
|
+
.padding(0.1);
|
|
1668
1851
|
}
|
|
1669
1852
|
|
|
1670
1853
|
else if(this.orientation == 'right'){
|
|
@@ -1684,11 +1867,10 @@ class CategoricalBarChart{
|
|
|
1684
1867
|
*/
|
|
1685
1868
|
render(){
|
|
1686
1869
|
|
|
1870
|
+
const self = this;
|
|
1687
1871
|
let top_n_cats = this.model.categorical_bins[this.facet].slice(0,this.n);
|
|
1688
1872
|
let update_targets = [`${this.facet}_heatmap`, `${this.facet}_right_histogram`, `${this.facet}_bottom_histogram`, `${this.facet}_legend`];
|
|
1689
1873
|
|
|
1690
|
-
const self = this;
|
|
1691
|
-
|
|
1692
1874
|
if(self.model.row_major_counts[self.facet].length > 2){
|
|
1693
1875
|
|
|
1694
1876
|
if(this.orientation == 'bottom'){
|
|
@@ -1705,17 +1887,18 @@ class CategoricalBarChart{
|
|
|
1705
1887
|
let col = enter.append('g')
|
|
1706
1888
|
.attr('class', 'column')
|
|
1707
1889
|
.attr('transform', (d, i)=>{
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1890
|
+
const tickPos = self.scale_x(d.key);
|
|
1891
|
+
const bandWidth = self.scale_x.bandwidth();
|
|
1892
|
+
// Center bar if calc_bar_width < bandWidth
|
|
1893
|
+
const offset = (bandWidth - self.calc_bar_width) / 2;
|
|
1894
|
+
return `translate(${tickPos + offset}, ${CAT_HISTOGRAM_LAYOUT.inner_padding})`;
|
|
1712
1895
|
});
|
|
1713
1896
|
|
|
1714
1897
|
col.append('rect')
|
|
1715
1898
|
.attr('class', 'bar')
|
|
1716
1899
|
.attr('height', (d)=>{return self.scale_y(d.val)})
|
|
1717
1900
|
// .attr('width', (d)=>{return ((HISTOGRAM_LAYOUT.width - 2*HISTOGRAM_LAYOUT.inner_padding) / faceted_bins[d.facet].x.length)})
|
|
1718
|
-
.attr('width',
|
|
1901
|
+
.attr('width', self.calc_bar_width)
|
|
1719
1902
|
.attr('fill', TAN)
|
|
1720
1903
|
.attr(`transform`, (d)=>{return `translate(${0}, ${(CAT_HISTOGRAM_LAYOUT.height- self.scale_y(d.val))-2*CAT_HISTOGRAM_LAYOUT.inner_padding})`})
|
|
1721
1904
|
.on('mouseover', function (e,d){
|
|
@@ -1910,7 +2093,6 @@ class Validator{
|
|
|
1910
2093
|
*/
|
|
1911
2094
|
isValidDate(dateString) {
|
|
1912
2095
|
const date_time = new Date(dateString);
|
|
1913
|
-
console.log("AAAAA", date_time.getTime());
|
|
1914
2096
|
return !isNaN(date_time.getTime());
|
|
1915
2097
|
}
|
|
1916
2098
|
|
|
@@ -2002,6 +2184,15 @@ class Validator{
|
|
|
2002
2184
|
return missing;
|
|
2003
2185
|
}
|
|
2004
2186
|
|
|
2187
|
+
|
|
2188
|
+
// Function to coerce an entire column’s values to strings
|
|
2189
|
+
coerceColumnToString(columnData) {
|
|
2190
|
+
return Object.keys(columnData).reduce((result, key) => {
|
|
2191
|
+
result[key] = String(columnData[key]);
|
|
2192
|
+
return result;
|
|
2193
|
+
}, {});
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2005
2196
|
/**
|
|
2006
2197
|
* Ensures that all values in this.var_specs are logically appropriate
|
|
2007
2198
|
* @param {Object} this.var_specs - The variable specifications.
|
|
@@ -2023,11 +2214,11 @@ class Validator{
|
|
|
2023
2214
|
if (typeof test_val !== 'number'){
|
|
2024
2215
|
if(typeof test_val == 'string'){
|
|
2025
2216
|
if(!this.isValidDate(test_val)){
|
|
2026
|
-
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis
|
|
2217
|
+
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis only supports floats, integers and dates. Please specify a different variable or verify that the datetime is properly formatted.' });
|
|
2027
2218
|
}
|
|
2028
2219
|
}
|
|
2029
2220
|
else {
|
|
2030
|
-
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis
|
|
2221
|
+
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis only supports floats, integers and dates. Please specify a different variable or verify that the datetime is properly formatted.' });
|
|
2031
2222
|
}
|
|
2032
2223
|
}
|
|
2033
2224
|
}
|
|
@@ -2045,8 +2236,15 @@ class Validator{
|
|
|
2045
2236
|
}
|
|
2046
2237
|
else if (key === 'categorical'){
|
|
2047
2238
|
let test_val = this.data[this.var_specs[key]][Object.keys(this.data[this.var_specs[key]])[0]];
|
|
2239
|
+
// For categorical variables, coerce data to strings if necessary.
|
|
2048
2240
|
if(typeof test_val !== 'string'){
|
|
2049
|
-
|
|
2241
|
+
// Coerce the column data at this.data[this.var_specs[key]]
|
|
2242
|
+
this.data[this.var_specs[key]] = coerceColumnToString(this.data[this.var_specs[key]]);
|
|
2243
|
+
// Re-check the data type after coercion
|
|
2244
|
+
test_val = this.data[this.var_specs[key]][Object.keys(this.data[this.var_specs[key]])[0]];
|
|
2245
|
+
if(typeof test_val !== 'string'){
|
|
2246
|
+
incorrect.push({ key: key, value: this.var_specs[key], message: 'The categorical view only supports categorical variables formatted as strings. Please specify a different column on your dataset or reformat an existing column.' });
|
|
2247
|
+
}
|
|
2050
2248
|
}
|
|
2051
2249
|
}
|
|
2052
2250
|
}
|
|
@@ -2144,7 +2342,6 @@ function render({model, el}){
|
|
|
2144
2342
|
|
|
2145
2343
|
validator.data = data;
|
|
2146
2344
|
is_valid = validator.validate();
|
|
2147
|
-
console.log()
|
|
2148
2345
|
|
|
2149
2346
|
if(is_valid){
|
|
2150
2347
|
let jsmodel = new JSModel(data, var_specs, model);
|
|
@@ -2157,4 +2354,4 @@ function render({model, el}){
|
|
|
2157
2354
|
|
|
2158
2355
|
|
|
2159
2356
|
|
|
2160
|
-
export default{ render }
|
|
2357
|
+
export default{ render };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: guidepost
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
4
4
|
Summary: Guidepost. An overview visualization for understanding supercomputer queue data.
|
|
5
5
|
Home-page: https://github.com/cscully-allison/guidepost
|
|
6
6
|
Author: Connor Scully-Allison
|
|
@@ -22,6 +22,7 @@ Dynamic: classifier
|
|
|
22
22
|
Dynamic: description
|
|
23
23
|
Dynamic: description-content-type
|
|
24
24
|
Dynamic: home-page
|
|
25
|
+
Dynamic: license-file
|
|
25
26
|
Dynamic: requires-dist
|
|
26
27
|
Dynamic: requires-python
|
|
27
28
|
Dynamic: summary
|
|
@@ -212,7 +213,7 @@ Guidepost is licensed under the MIT License. See the `LICENSE` file for details.
|
|
|
212
213
|
|
|
213
214
|
## Acknowledgments
|
|
214
215
|
|
|
215
|
-
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL).
|
|
216
|
+
Guidepost was developed under the auspices and with funding provided by the National Renewable Energy Laboratory (NREL), the National Science Foundation under NSF IIS-1844573 and IIS-2324465, and the Department of Energy under DE-SC0022044 and DE-SC0024635.
|
|
216
217
|
|
|
217
218
|
---
|
|
218
219
|
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|