guidepost 0.2.14__tar.gz → 0.2.16__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.16/MANIFEST.in +2 -0
- {guidepost-0.2.14/guidepost.egg-info → guidepost-0.2.16}/PKG-INFO +4 -3
- {guidepost-0.2.14 → guidepost-0.2.16}/README.md +1 -1
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost/guidepost.js +304 -124
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost/guidepost.py +4 -0
- guidepost-0.2.16/guidepost/version.py +2 -0
- {guidepost-0.2.14 → guidepost-0.2.16/guidepost.egg-info}/PKG-INFO +4 -3
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost.egg-info/SOURCES.txt +1 -2
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost.egg-info/top_level.txt +0 -1
- {guidepost-0.2.14 → guidepost-0.2.16}/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.16}/LICENSE +0 -0
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost/__init__.py +0 -0
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost.egg-info/dependency_links.txt +0 -0
- {guidepost-0.2.14 → guidepost-0.2.16}/guidepost.egg-info/requires.txt +0 -0
- {guidepost-0.2.14 → guidepost-0.2.16}/pyproject.toml +0 -0
- {guidepost-0.2.14 → guidepost-0.2.16}/setup.cfg +0 -0
- {guidepost-0.2.14/figs → guidepost-0.2.16/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.16
|
|
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)';
|
|
@@ -231,7 +236,7 @@ class JSModel{
|
|
|
231
236
|
* @param {string} col - The column to get summary statistics for.
|
|
232
237
|
* @returns {Object} - The summary statistics for the column.
|
|
233
238
|
*/
|
|
234
|
-
get_summary_stats(data, col){
|
|
239
|
+
get_summary_stats(data, col, index){
|
|
235
240
|
let sum_stats = {};
|
|
236
241
|
|
|
237
242
|
if(data.length > 0){
|
|
@@ -266,6 +271,7 @@ class JSModel{
|
|
|
266
271
|
sum_stats.var = sum_stats.variance;
|
|
267
272
|
sum_stats.average = sum_stats.avg;
|
|
268
273
|
sum_stats.mean = sum_stats.avg;
|
|
274
|
+
sum_stats.count = data.length;
|
|
269
275
|
}
|
|
270
276
|
else{
|
|
271
277
|
sum_stats.sum = 0;
|
|
@@ -278,8 +284,12 @@ class JSModel{
|
|
|
278
284
|
sum_stats.std = 0;
|
|
279
285
|
sum_stats.median = 0;
|
|
280
286
|
sum_stats.med = 0;
|
|
287
|
+
sum_stats.count = 0;
|
|
281
288
|
}
|
|
282
289
|
|
|
290
|
+
|
|
291
|
+
sum_stats.index = index;
|
|
292
|
+
|
|
283
293
|
|
|
284
294
|
return sum_stats;
|
|
285
295
|
}
|
|
@@ -366,6 +376,29 @@ class JSModel{
|
|
|
366
376
|
return Math.log10(max) - Math.log10(min) > order;
|
|
367
377
|
}
|
|
368
378
|
|
|
379
|
+
|
|
380
|
+
//box bins for a column
|
|
381
|
+
binValues(values, thresholds, accessor) {
|
|
382
|
+
const bins = [];
|
|
383
|
+
// Create an empty bin for each interval between consecutive thresholds
|
|
384
|
+
for (let i = 0; i < thresholds.length - 1; i++) {
|
|
385
|
+
bins.push([]);
|
|
386
|
+
}
|
|
387
|
+
// Place each value in the appropriate bin
|
|
388
|
+
values.forEach(d => {
|
|
389
|
+
const val = accessor(d);
|
|
390
|
+
for (let i = 0; i < thresholds.length - 1; i++) {
|
|
391
|
+
// For the last bin, include values equal to the upper bound
|
|
392
|
+
if (val >= thresholds[i] && (i === thresholds.length - 2 || val < thresholds[i + 1])) {
|
|
393
|
+
bins[i].push(d);
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
return bins;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
|
|
369
402
|
/**
|
|
370
403
|
* Calculates metrics for the rectangles of the summary view for a specified facet. Bins come into this function already oragnized
|
|
371
404
|
* into columns delinated by the x_axis_thresholds. It's a user specified datetime variable.
|
|
@@ -377,7 +410,11 @@ class JSModel{
|
|
|
377
410
|
let current_bins = this.faceted_bins[fac].column;
|
|
378
411
|
let sum_stats = this.faceted_sum_stats[fac];
|
|
379
412
|
|
|
413
|
+
// console.log("CALC BOX METRICS: ", fac, current_bins, x_axis_thresholds, y_axis_thresholds);
|
|
414
|
+
|
|
380
415
|
// Iterate over the columns that divide the data along the x axis
|
|
416
|
+
|
|
417
|
+
let col_indx = 0;
|
|
381
418
|
for(let bin in current_bins){
|
|
382
419
|
let filtered_bin;
|
|
383
420
|
|
|
@@ -393,48 +430,31 @@ class JSModel{
|
|
|
393
430
|
}
|
|
394
431
|
}
|
|
395
432
|
|
|
396
|
-
|
|
397
|
-
|
|
433
|
+
// Get summary statistics for the entire column of data before it is split into rows
|
|
434
|
+
let temp_box_stats = this.get_summary_stats(filtered_bin, this.vars.y, col_indx);
|
|
398
435
|
temp_box_stats.threshold = x_axis_thresholds[bin];
|
|
399
436
|
|
|
400
437
|
temp_box_stats.bins = [];
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
for(let i = row_bins.length-1; i > y_axis_thresholds.length-2; i--){
|
|
415
|
-
head[head.length-1] = head[head.length-1].concat(row_bins[i]);
|
|
416
|
-
}
|
|
417
|
-
row_bins = head;
|
|
418
|
-
}
|
|
438
|
+
|
|
439
|
+
const customBins = this.binValues(filtered_bin, y_axis_thresholds, d => d[this.vars.y]);
|
|
440
|
+
|
|
441
|
+
// Process each bin's summary statistics and update color scale range
|
|
442
|
+
temp_box_stats.bins = customBins.map((bin, index) => {
|
|
443
|
+
const stats = this.get_summary_stats(bin, this.vars.color);
|
|
444
|
+
stats.values = bin;
|
|
445
|
+
stats.std_ratio = stats.std / this.faceted_sum_stats[fac].color.std;
|
|
446
|
+
stats.threshold = y_axis_thresholds[index];
|
|
447
|
+
this.color_scale_range[0] = Math.min(this.color_scale_range[0], stats[this.vars.color_agg] ? stats[this.vars.color_agg] : this.color_scale_range[0]);
|
|
448
|
+
this.color_scale_range[1] = Math.max(this.color_scale_range[1], stats[this.vars.color_agg]);
|
|
449
|
+
return stats;
|
|
450
|
+
});
|
|
419
451
|
|
|
420
|
-
//load individual boxes of values with summary statistics describing them
|
|
421
|
-
for(let index in row_bins){
|
|
422
|
-
let row = row_bins[index];
|
|
423
|
-
let sum_stats = this.get_summary_stats(row, this.vars.color);
|
|
424
|
-
sum_stats.values = row;
|
|
425
|
-
sum_stats['std_ratio'] = sum_stats.std/this.faceted_sum_stats[fac].color.std;
|
|
426
|
-
sum_stats.threshold = y_axis_thresholds[index];
|
|
427
|
-
temp_box_stats.bins.push(sum_stats);
|
|
428
|
-
this.color_scale_range[0] = Math.min(this.color_scale_range[0], sum_stats[this.vars.color_agg]);
|
|
429
|
-
this.color_scale_range[1] = Math.max(this.color_scale_range[1], sum_stats[this.vars.color_agg]);
|
|
430
|
-
}
|
|
431
452
|
|
|
432
453
|
temp_box_stats.column_values = filtered_bin;
|
|
433
454
|
this.faceted_bins[fac].column[bin] = temp_box_stats;
|
|
455
|
+
col_indx += 1;
|
|
434
456
|
}
|
|
435
457
|
|
|
436
|
-
// console.log("THE BINS END OF CALC BOX METRICS: ", this.faceted_bins[fac].column);
|
|
437
|
-
|
|
438
458
|
}
|
|
439
459
|
|
|
440
460
|
/**
|
|
@@ -443,7 +463,21 @@ class JSModel{
|
|
|
443
463
|
* @returns {Array} - The sanitized and initialized data.
|
|
444
464
|
*/
|
|
445
465
|
sanitize_and_intialize_data(data){
|
|
446
|
-
this.global_sum_stats = {
|
|
466
|
+
this.global_sum_stats = {
|
|
467
|
+
x:{
|
|
468
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
469
|
+
min: Number.MAX_SAFE_INTEGER
|
|
470
|
+
},
|
|
471
|
+
y:{
|
|
472
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
473
|
+
min: Number.MAX_SAFE_INTEGER
|
|
474
|
+
},
|
|
475
|
+
color:{
|
|
476
|
+
max: Number.MIN_SAFE_INTEGER,
|
|
477
|
+
min: Number.MAX_SAFE_INTEGER
|
|
478
|
+
},
|
|
479
|
+
num_cols: 0
|
|
480
|
+
};
|
|
447
481
|
for(let fac of this.facets){
|
|
448
482
|
//store data about what types of scales x and y are
|
|
449
483
|
this.scale_types[fac] = {
|
|
@@ -466,14 +500,6 @@ class JSModel{
|
|
|
466
500
|
}
|
|
467
501
|
|
|
468
502
|
|
|
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
503
|
|
|
478
504
|
data[fac] = this.sanitize_data_for_log(data[fac], this.vars.y);
|
|
479
505
|
|
|
@@ -484,9 +510,21 @@ class JSModel{
|
|
|
484
510
|
|
|
485
511
|
let sum_stats = this.faceted_sum_stats[fac];
|
|
486
512
|
|
|
513
|
+
this.global_sum_stats.x.max = Math.max(this.faceted_sum_stats[fac].x.max, this.global_sum_stats.x.max);
|
|
514
|
+
this.global_sum_stats.y.max = Math.max(this.faceted_sum_stats[fac].y.max, this.global_sum_stats.y.max);
|
|
515
|
+
this.global_sum_stats.color.max = Math.max(this.faceted_sum_stats[fac].color.max, this.global_sum_stats.color.max);
|
|
516
|
+
|
|
517
|
+
this.global_sum_stats.x.min = Math.min(this.faceted_sum_stats[fac].x.min, this.global_sum_stats.x.min);
|
|
518
|
+
this.global_sum_stats.y.min = Math.min(this.faceted_sum_stats[fac].y.min, this.global_sum_stats.y.min);
|
|
519
|
+
this.global_sum_stats.color.min = Math.min(this.faceted_sum_stats[fac].color.min, this.global_sum_stats.color.max);
|
|
520
|
+
|
|
487
521
|
|
|
488
522
|
this.faceted_bins[fac] = {}
|
|
489
523
|
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
// console.log("SUM STATS: ", fac, sum_stats, "blahaj");
|
|
527
|
+
|
|
490
528
|
//conditional x axis thresholds based on time or numbers
|
|
491
529
|
// important for calculating the scales which layout the columns
|
|
492
530
|
// of the "heatmap"
|
|
@@ -503,7 +541,7 @@ class JSModel{
|
|
|
503
541
|
// just do linerats if not
|
|
504
542
|
if(this.is_more_than_n_orders_of_magnitude(sum_stats.x.min, sum_stats.x.max, 3)){
|
|
505
543
|
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);
|
|
544
|
+
this.x_axis_thresholds[fac] = this.logScale(this.log_values_floor, sum_stats.x.max+1, num_cols-1);
|
|
507
545
|
this.faceted_bins[fac].column = d3.bin()
|
|
508
546
|
.value(d => d[this.vars.x])
|
|
509
547
|
.domain([this.log_values_floor, sum_stats.x.max])
|
|
@@ -512,7 +550,7 @@ class JSModel{
|
|
|
512
550
|
}
|
|
513
551
|
else{
|
|
514
552
|
this.scale_types[fac].x.linear = true;
|
|
515
|
-
this.x_axis_thresholds[fac] = this.linearScale(sum_stats.x.min, sum_stats.x.max,
|
|
553
|
+
this.x_axis_thresholds[fac] = this.linearScale(sum_stats.x.min, sum_stats.x.max+1, num_cols-1);
|
|
516
554
|
this.faceted_bins[fac].column = d3.bin()
|
|
517
555
|
.value(d => d[this.vars.x])
|
|
518
556
|
.domain([sum_stats.x.min, sum_stats.x.max])
|
|
@@ -538,8 +576,9 @@ class JSModel{
|
|
|
538
576
|
sum_stats.col_counts.max = Math.max(sum_stats.col_counts.max, bin.length);
|
|
539
577
|
sum_stats.col_counts.min = Math.min(sum_stats.col_counts.min, bin.length);
|
|
540
578
|
}
|
|
579
|
+
|
|
580
|
+
this.global_sum_stats.num_cols = Math.max(this.faceted_bins[fac].column.length, this.global_sum_stats.num_cols);
|
|
541
581
|
|
|
542
|
-
// temporary as Y AXIS IS FIXED LOG
|
|
543
582
|
this.calculate_box_metrics(fac, this.x_axis_thresholds[fac], this.y_axis_thresholds[fac]);
|
|
544
583
|
this.calc_row_major_counts(fac);
|
|
545
584
|
|
|
@@ -554,6 +593,7 @@ class JSModel{
|
|
|
554
593
|
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
594
|
}
|
|
556
595
|
|
|
596
|
+
|
|
557
597
|
return data;
|
|
558
598
|
}
|
|
559
599
|
|
|
@@ -582,8 +622,6 @@ class JSModel{
|
|
|
582
622
|
*/
|
|
583
623
|
filter_data_by_category(filter, facet, source, targets){
|
|
584
624
|
|
|
585
|
-
console.log("DATA FILTERS: ", filter)
|
|
586
|
-
|
|
587
625
|
this.faceted_states[facet].filter = filter;
|
|
588
626
|
|
|
589
627
|
// is anything pinned
|
|
@@ -635,9 +673,6 @@ class JSModel{
|
|
|
635
673
|
|
|
636
674
|
}
|
|
637
675
|
|
|
638
|
-
console.log(this.brushed_ranges[facet].x_range, this.brushed_ranges[facet].y_range);
|
|
639
|
-
|
|
640
|
-
|
|
641
676
|
|
|
642
677
|
if(this.brushed_ranges[facet].x_range.length != 0){
|
|
643
678
|
for(let bin of this.faceted_bins[facet].column){
|
|
@@ -683,8 +718,6 @@ class JSModel{
|
|
|
683
718
|
}
|
|
684
719
|
}
|
|
685
720
|
|
|
686
|
-
console.log("TEST", test);
|
|
687
|
-
|
|
688
721
|
this.anywidget_model.set("selected_records", JSON.stringify(return_ids));
|
|
689
722
|
this.anywidget_model.save_changes();
|
|
690
723
|
|
|
@@ -815,7 +848,7 @@ class SmartScale {
|
|
|
815
848
|
if(this.model.is_more_than_n_orders_of_magnitude(this.domain[0], this.domain[1], 3)){
|
|
816
849
|
return d3.scaleLog().domain([this.model.log_values_floor, this.domain[1]]).range(this.range);
|
|
817
850
|
} else {
|
|
818
|
-
return d3.scaleLinear().domain(
|
|
851
|
+
return d3.scaleLinear().domain(this.domain).range(this.range);
|
|
819
852
|
}
|
|
820
853
|
} else {
|
|
821
854
|
throw new Error("Unsupported domain type");
|
|
@@ -894,16 +927,23 @@ class Heatmap{
|
|
|
894
927
|
// .domain(this.model.faceted_bins[this.facet].column.keys())
|
|
895
928
|
// .range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width - OVERVIEW_LAYOUT.inner_padding]);
|
|
896
929
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
930
|
+
|
|
931
|
+
if(SHARED_X_SCALE){
|
|
932
|
+
this.scale_x = new SmartScale([this.model.global_sum_stats.x.min, this.model.global_sum_stats.x.max],
|
|
933
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
934
|
+
this.model);
|
|
935
|
+
}
|
|
936
|
+
else{
|
|
937
|
+
this.scale_x = new SmartScale([sum_stats.x.min, sum_stats.x.max],
|
|
938
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
939
|
+
this.model);
|
|
940
|
+
|
|
941
|
+
}
|
|
942
|
+
|
|
903
943
|
|
|
904
944
|
//Determine if y scale is log or linear based on input data
|
|
905
|
-
console.log(this.model.scale_types[this.facet]);
|
|
906
945
|
if(this.model.scale_types[this.facet].y.log){
|
|
946
|
+
|
|
907
947
|
this.scale_y = d3.scaleLog()
|
|
908
948
|
.domain([this.model.log_values_floor, sum_stats.y.max])
|
|
909
949
|
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
@@ -956,9 +996,14 @@ class Heatmap{
|
|
|
956
996
|
.attr('height', this.height);
|
|
957
997
|
|
|
958
998
|
|
|
999
|
+
let axis_left = d3.axisLeft().scale(this.scale_y_inverse);
|
|
1000
|
+
if(this.model.scale_types[this.facet].y.linear){
|
|
1001
|
+
axis_left.tickFormat(d3.format(".2s"));
|
|
1002
|
+
}
|
|
1003
|
+
|
|
959
1004
|
view.append('g')
|
|
960
1005
|
.attr('class', 'left-axis')
|
|
961
|
-
.call(
|
|
1006
|
+
.call(axis_left)
|
|
962
1007
|
.attr('transform', `translate(${OVERVIEW_LAYOUT.inner_padding},${0})`);
|
|
963
1008
|
|
|
964
1009
|
view.append('g')
|
|
@@ -1043,19 +1088,24 @@ class Heatmap{
|
|
|
1043
1088
|
* Raises and zooms on a column slightly
|
|
1044
1089
|
*/
|
|
1045
1090
|
focus_col(update_element){
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1091
|
+
let self = this;
|
|
1092
|
+
let base_width;
|
|
1093
|
+
if(SHARED_X_SCALE){
|
|
1094
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1095
|
+
}
|
|
1096
|
+
else{
|
|
1097
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
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
1101
|
|
|
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});
|
|
1102
|
+
update_element.raise();
|
|
1058
1103
|
|
|
1104
|
+
update_element.selectAll('.row')
|
|
1105
|
+
.attr('width', ()=>{return base_width + zoom_factor_h})
|
|
1106
|
+
.attr('height', ()=>{return ( (OVERVIEW_LAYOUT.height + zoom_factor_v) - 2*OVERVIEW_LAYOUT.inner_padding) / self.model.faceted_bins[self.facet].column[0].bins.length})
|
|
1107
|
+
.attr('y', (d, i)=>{return self.scale_y_blocks(i) - OVERVIEW_LAYOUT.inner_padding});
|
|
1108
|
+
|
|
1059
1109
|
update_element.selectAll('.col-bg')
|
|
1060
1110
|
.attr('width', ()=>{return base_width + zoom_factor_h})
|
|
1061
1111
|
.attr('height', ()=>{return ( (OVERVIEW_LAYOUT.height + zoom_factor_v) - 2*OVERVIEW_LAYOUT.inner_padding)})
|
|
@@ -1075,9 +1125,14 @@ class Heatmap{
|
|
|
1075
1125
|
*/
|
|
1076
1126
|
unfocus_col(update_element){
|
|
1077
1127
|
let self = this;
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1128
|
+
let base_width;
|
|
1129
|
+
if(SHARED_X_SCALE){
|
|
1130
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1131
|
+
}
|
|
1132
|
+
else{
|
|
1133
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1081
1136
|
self.scale_y_blocks.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1082
1137
|
|
|
1083
1138
|
|
|
@@ -1130,9 +1185,16 @@ class Heatmap{
|
|
|
1130
1185
|
render(){
|
|
1131
1186
|
const self = this;
|
|
1132
1187
|
|
|
1133
|
-
console.log(this.model.faceted_bins[this.facet].column);
|
|
1134
1188
|
|
|
1135
|
-
let base_width =
|
|
1189
|
+
let base_width = 0;
|
|
1190
|
+
if(SHARED_X_SCALE){
|
|
1191
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1192
|
+
}
|
|
1193
|
+
else{
|
|
1194
|
+
base_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
|
|
1136
1198
|
|
|
1137
1199
|
if(self.model.row_major_counts[self.facet].length < 2){
|
|
1138
1200
|
this.view
|
|
@@ -1142,6 +1204,7 @@ class Heatmap{
|
|
|
1142
1204
|
.attr('transform', `translate(${draw_width/2},${draw_height/2})`)
|
|
1143
1205
|
}
|
|
1144
1206
|
else{
|
|
1207
|
+
|
|
1145
1208
|
this.view
|
|
1146
1209
|
.selectAll('.column')
|
|
1147
1210
|
.data(this.model.faceted_bins[this.facet].column)
|
|
@@ -1214,6 +1277,9 @@ class Heatmap{
|
|
|
1214
1277
|
)
|
|
1215
1278
|
col.on('mouseenter', function (e, d){
|
|
1216
1279
|
delete self.cached_bins['hover'];
|
|
1280
|
+
|
|
1281
|
+
console.log("HOVERING OVER: ", d);
|
|
1282
|
+
|
|
1217
1283
|
self.focus_col(d3.select(e.target));
|
|
1218
1284
|
if(!Object.keys(self.cached_bins).includes(String(d.threshold))){
|
|
1219
1285
|
let dt_text_selection = d3.select(e.target).select('.text-field');
|
|
@@ -1364,10 +1430,21 @@ class Histogram{
|
|
|
1364
1430
|
let y_offset = Y_VARIABLE_OFFSET + OVERVIEW_LAYOUT.height + HISTOGRAM_LAYOUT.outer_margin;
|
|
1365
1431
|
|
|
1366
1432
|
|
|
1433
|
+
|
|
1367
1434
|
//create the histograms
|
|
1368
1435
|
let h_hist = this.parent.append('g')
|
|
1369
1436
|
.attr('class', 'faceted-h-hist')
|
|
1370
1437
|
.attr('transform', `translate(${x_offset},${y_offset})`);
|
|
1438
|
+
|
|
1439
|
+
h_hist.append('rect')
|
|
1440
|
+
.attr('width', this.width - 2*HISTOGRAM_LAYOUT.inner_padding)
|
|
1441
|
+
.attr('height', this.height - HISTOGRAM_LAYOUT.inner_padding)
|
|
1442
|
+
.attr('fill', 'rgba(240,240,240)')
|
|
1443
|
+
.attr('transform', `translate(${HISTOGRAM_LAYOUT.inner_padding},${0})`);
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
h_hist.append("g")
|
|
1447
|
+
.attr('class', 'bars');
|
|
1371
1448
|
|
|
1372
1449
|
h_hist.append('g')
|
|
1373
1450
|
.attr('class', 'left-axis')
|
|
@@ -1389,7 +1466,10 @@ class Histogram{
|
|
|
1389
1466
|
.attr('text-anchor', 'middle')
|
|
1390
1467
|
.attr('transform', `translate(${this.width/2},${this.height})`);
|
|
1391
1468
|
|
|
1469
|
+
|
|
1470
|
+
|
|
1392
1471
|
this.view = h_hist;
|
|
1472
|
+
|
|
1393
1473
|
|
|
1394
1474
|
this.brush = d3.brushX()
|
|
1395
1475
|
.extent([[OVERVIEW_LAYOUT.inner_padding, 0], [OVERVIEW_LAYOUT.width - OVERVIEW_LAYOUT.inner_padding, this.height-HISTOGRAM_LAYOUT.inner_padding]])
|
|
@@ -1400,9 +1480,8 @@ class Histogram{
|
|
|
1400
1480
|
select = selection.map(self.scale_x.scale.invert, self.scale_x.scale).map(d3.utcDay.round);
|
|
1401
1481
|
}
|
|
1402
1482
|
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
|
|
1483
|
+
select = selection.map(self.scale_x.scale.invert, self.scale_x.scale).map((d)=>{return d});
|
|
1404
1484
|
}
|
|
1405
|
-
console.log(select);
|
|
1406
1485
|
}else{
|
|
1407
1486
|
select = [];
|
|
1408
1487
|
}
|
|
@@ -1410,46 +1489,62 @@ class Histogram{
|
|
|
1410
1489
|
});
|
|
1411
1490
|
|
|
1412
1491
|
h_hist.append("g")
|
|
1492
|
+
.attr('class', 'h-brush')
|
|
1413
1493
|
.call(this.brush);
|
|
1414
1494
|
}
|
|
1415
1495
|
|
|
1416
1496
|
|
|
1417
1497
|
else if(this.orientation == 'right'){
|
|
1418
1498
|
|
|
1419
|
-
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width;
|
|
1499
|
+
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width - 5;
|
|
1420
1500
|
let y_offset = Y_VARIABLE_OFFSET + VERT_HISTOGRAM_LAYOUT.outer_margin;
|
|
1421
1501
|
|
|
1422
1502
|
let v_hist = this.parent.append('g')
|
|
1423
1503
|
.attr('class', 'faceted-v-hist')
|
|
1424
1504
|
.attr('transform', `translate(${x_offset},${y_offset})`);
|
|
1425
1505
|
|
|
1506
|
+
v_hist.append('rect')
|
|
1507
|
+
.attr('width', this.width)
|
|
1508
|
+
.attr('height', this.height - 2*HISTOGRAM_LAYOUT.inner_padding)
|
|
1509
|
+
.attr('fill', 'rgba(240,240,240)')
|
|
1510
|
+
.attr('transform', `translate(${0},${HISTOGRAM_LAYOUT.inner_padding})`);
|
|
1511
|
+
;
|
|
1512
|
+
|
|
1426
1513
|
v_hist.append('g')
|
|
1427
1514
|
.attr('class', 'bot-axis')
|
|
1428
1515
|
.call(d3.axisBottom().scale(this.scale_x).ticks(5))
|
|
1429
1516
|
.attr('transform', `translate(${VERT_HISTOGRAM_LAYOUT.inner_padding*4},${VERT_HISTOGRAM_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding})`);
|
|
1430
1517
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1518
|
+
v_hist.append('g')
|
|
1519
|
+
.attr('class', 'left-axis')
|
|
1520
|
+
.call(d3.axisRight().scale(this.axis_scale_y_inverse))
|
|
1521
|
+
.attr('transform', `translate(${self.width-VERT_HISTOGRAM_LAYOUT.inner_padding},${0})`);
|
|
1435
1522
|
|
|
1436
1523
|
this.brush = d3.brushY()
|
|
1437
1524
|
.extent([[0, HISTOGRAM_LAYOUT.inner_padding], [this.width, this.height - OVERVIEW_LAYOUT.inner_padding]])
|
|
1438
1525
|
.on("end", function({selection}){
|
|
1439
1526
|
let select;
|
|
1440
1527
|
if(selection){
|
|
1441
|
-
select = selection.map(self.scale_y.invert, self.scale_y).map((d)=>{return
|
|
1528
|
+
select = selection.map(self.scale_y.invert, self.scale_y).map((d)=>{return d+0.1})
|
|
1442
1529
|
}else{
|
|
1443
1530
|
select = [];
|
|
1444
1531
|
}
|
|
1445
1532
|
self.model.update_subselected_data(self.facet, [`${self.facet}_heatmap`, `${self.facet}_legend`], select, "y");
|
|
1446
1533
|
});
|
|
1447
1534
|
|
|
1535
|
+
|
|
1448
1536
|
v_hist.append("g")
|
|
1537
|
+
.attr('class', 'bars');
|
|
1538
|
+
|
|
1539
|
+
v_hist.append("g")
|
|
1540
|
+
.attr('class', 'v-brush')
|
|
1449
1541
|
.call(this.brush);
|
|
1450
1542
|
|
|
1451
1543
|
this.view = v_hist;
|
|
1452
1544
|
}
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
|
|
1453
1548
|
}
|
|
1454
1549
|
|
|
1455
1550
|
/**
|
|
@@ -1469,20 +1564,56 @@ class Histogram{
|
|
|
1469
1564
|
|
|
1470
1565
|
//references OVERVIEW LAYOUT SIZES
|
|
1471
1566
|
//BE CAREFUL
|
|
1472
|
-
|
|
1567
|
+
if(SHARED_X_SCALE){
|
|
1568
|
+
this.scale_x = new SmartScale([this.model.global_sum_stats.x.min, this.model.global_sum_stats.x.max],
|
|
1569
|
+
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
1570
|
+
this.model);
|
|
1571
|
+
}
|
|
1572
|
+
else{
|
|
1573
|
+
this.scale_x = new SmartScale([sum_stats.x.min, sum_stats.x.max],
|
|
1473
1574
|
[OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.width-OVERVIEW_LAYOUT.inner_padding],
|
|
1474
1575
|
this.model);
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1475
1578
|
}
|
|
1476
1579
|
|
|
1477
1580
|
else if(this.orientation == 'right'){
|
|
1478
1581
|
|
|
1479
|
-
this.
|
|
1582
|
+
if(this.model.is_more_than_n_orders_of_magnitude(0, Math.max(...this.model.row_major_counts[this.facet]), 3)){
|
|
1583
|
+
let local_log_floor = 0.3
|
|
1584
|
+
this.scale_x = d3.scaleLog()
|
|
1585
|
+
.domain([local_log_floor, Math.max(...this.model.row_major_counts[this.facet])])
|
|
1586
|
+
.range([0, VERT_HISTOGRAM_LAYOUT.width - VERT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1587
|
+
}else{
|
|
1588
|
+
this.scale_x = d3.scaleLinear()
|
|
1589
|
+
.domain([0, Math.max(...this.model.row_major_counts[this.facet])])
|
|
1590
|
+
.range([0, VERT_HISTOGRAM_LAYOUT.width - VERT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
if(this.model.scale_types[this.facet].y.log){
|
|
1595
|
+
this.axis_scale_y = d3.scaleLog()
|
|
1596
|
+
.domain([this.model.log_values_floor, sum_stats.y.max])
|
|
1597
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1598
|
+
|
|
1599
|
+
this.axis_scale_y_inverse = d3.scaleLog()
|
|
1600
|
+
.domain([sum_stats.y.max, this.model.log_values_floor])
|
|
1601
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1602
|
+
}
|
|
1603
|
+
else if(this.model.scale_types[this.facet].y.linear){
|
|
1604
|
+
this.axis_scale_y = d3.scaleLinear()
|
|
1605
|
+
.domain([sum_stats.y.min, sum_stats.y.max])
|
|
1606
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1607
|
+
|
|
1608
|
+
this.axis_scale_y_inverse = d3.scaleLinear()
|
|
1609
|
+
.domain([sum_stats.y.max, sum_stats.y.min])
|
|
1610
|
+
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
this.scale_y = d3.scaleLinear()
|
|
1480
1614
|
.domain([num_rows-2, -1])
|
|
1481
1615
|
.range([OVERVIEW_LAYOUT.inner_padding, OVERVIEW_LAYOUT.height - OVERVIEW_LAYOUT.inner_padding]);
|
|
1482
1616
|
|
|
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
1617
|
}
|
|
1487
1618
|
}
|
|
1488
1619
|
|
|
@@ -1491,12 +1622,23 @@ class Histogram{
|
|
|
1491
1622
|
*/
|
|
1492
1623
|
render(){
|
|
1493
1624
|
const self = this;
|
|
1494
|
-
let bar_width =
|
|
1625
|
+
let bar_width = 0;
|
|
1626
|
+
let axis_height = 1;
|
|
1495
1627
|
|
|
1628
|
+
if(SHARED_X_SCALE){
|
|
1629
|
+
bar_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.global_sum_stats.num_cols))
|
|
1630
|
+
}
|
|
1631
|
+
else{
|
|
1632
|
+
bar_width = Math.min(MIN_BAR_WIDTH, (draw_width / self.model.faceted_bins[self.facet].column.length))
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
let bar_layer = this.view.select('.bars');
|
|
1636
|
+
|
|
1637
|
+
|
|
1496
1638
|
if(self.model.row_major_counts[self.facet].length > 2){
|
|
1497
1639
|
if(this.orientation == 'bottom'){
|
|
1498
|
-
|
|
1499
|
-
.data(self.model.faceted_bins[self.facet].column, function(d){return
|
|
1640
|
+
bar_layer.selectAll('.column')
|
|
1641
|
+
.data(self.model.faceted_bins[self.facet].column, function(d){console.log("INDEX", d.index); return d.index} )
|
|
1500
1642
|
.join(
|
|
1501
1643
|
function(enter){
|
|
1502
1644
|
let col = enter.append('g')
|
|
@@ -1513,19 +1655,20 @@ class Histogram{
|
|
|
1513
1655
|
.attr('height', (d)=>{return self.scale_y(d.column_values.length)})
|
|
1514
1656
|
.attr('width', bar_width)
|
|
1515
1657
|
.attr('fill', TAN)
|
|
1516
|
-
.attr(`transform`, (d)=>{return `translate(${0}, ${(HISTOGRAM_LAYOUT.height- self.scale_y(d.column_values.length))-2*HISTOGRAM_LAYOUT.inner_padding})`});
|
|
1658
|
+
.attr(`transform`, (d)=>{return `translate(${0}, ${(HISTOGRAM_LAYOUT.height- self.scale_y(d.column_values.length))-2*HISTOGRAM_LAYOUT.inner_padding - axis_height})`});
|
|
1517
1659
|
},
|
|
1518
1660
|
function(update){
|
|
1519
|
-
update.
|
|
1661
|
+
update.select('.bar')
|
|
1520
1662
|
.transition()
|
|
1663
|
+
.duration(500)
|
|
1521
1664
|
.attr('height', (d,i)=>{return self.scale_y(self.model.faceted_bins[self.facet].column[i].column_values.length)})
|
|
1665
|
+
.attr(`transform`, (d, i)=>{return `translate(${0}, ${(HISTOGRAM_LAYOUT.height- self.scale_y(self.model.faceted_bins[self.facet].column[i].column_values.length))-2*HISTOGRAM_LAYOUT.inner_padding - axis_height})`});
|
|
1522
1666
|
}
|
|
1523
1667
|
);
|
|
1524
1668
|
}
|
|
1525
1669
|
|
|
1526
1670
|
if(this.orientation == "right"){
|
|
1527
|
-
|
|
1528
|
-
.selectAll('.row')
|
|
1671
|
+
bar_layer.selectAll('.row')
|
|
1529
1672
|
.data(self.model.row_major_counts[self.facet])
|
|
1530
1673
|
.join(
|
|
1531
1674
|
function(enter){
|
|
@@ -1535,7 +1678,9 @@ class Histogram{
|
|
|
1535
1678
|
|
|
1536
1679
|
row.append('rect')
|
|
1537
1680
|
.attr('class', 'bar')
|
|
1538
|
-
.attr('width', (d)=>{
|
|
1681
|
+
.attr('width', (d)=>{
|
|
1682
|
+
return self.scale_x(d) ? self.scale_x(d) : 0;
|
|
1683
|
+
})
|
|
1539
1684
|
.attr('height', (d)=>{return draw_height / self.model.faceted_bins[self.facet].column[0].bins.length})
|
|
1540
1685
|
.attr('fill', TAN);
|
|
1541
1686
|
|
|
@@ -1544,7 +1689,9 @@ class Histogram{
|
|
|
1544
1689
|
function(update){
|
|
1545
1690
|
update.select('.bar')
|
|
1546
1691
|
.transition()
|
|
1547
|
-
.attr('width', (d)=>{
|
|
1692
|
+
.attr('width', (d)=>{
|
|
1693
|
+
return self.scale_x(d) ? self.scale_x(d) : 0;
|
|
1694
|
+
});
|
|
1548
1695
|
},
|
|
1549
1696
|
function(exit){
|
|
1550
1697
|
exit.remove();
|
|
@@ -1552,6 +1699,7 @@ class Histogram{
|
|
|
1552
1699
|
)
|
|
1553
1700
|
}
|
|
1554
1701
|
}
|
|
1702
|
+
|
|
1555
1703
|
}
|
|
1556
1704
|
}
|
|
1557
1705
|
|
|
@@ -1586,8 +1734,8 @@ class CategoricalBarChart{
|
|
|
1586
1734
|
|
|
1587
1735
|
//create the histograms
|
|
1588
1736
|
|
|
1589
|
-
let x_offset = X_VARIABLE_OFFSET +
|
|
1590
|
-
let y_offset = Y_VARIABLE_OFFSET +
|
|
1737
|
+
let x_offset = X_VARIABLE_OFFSET + OVERVIEW_LAYOUT.width;
|
|
1738
|
+
let y_offset = Y_VARIABLE_OFFSET + HISTOGRAM_LAYOUT.outer_margin + OVERVIEW_LAYOUT.height ;
|
|
1591
1739
|
|
|
1592
1740
|
let h_hist = this.parent.append('g')
|
|
1593
1741
|
.attr('class', 'faceted-h-hist')
|
|
@@ -1648,15 +1796,31 @@ class CategoricalBarChart{
|
|
|
1648
1796
|
setup_scales(){
|
|
1649
1797
|
this.n = Math.min(this.model.categorical_bins[this.facet].length, this.n);
|
|
1650
1798
|
let top_n_cats = this.model.categorical_bins[this.facet].slice(0,this.n);
|
|
1799
|
+
|
|
1800
|
+
this.max_bar_width = 30;
|
|
1801
|
+
this.drawable_width = (this.width-2*CAT_HISTOGRAM_LAYOUT.inner_padding);
|
|
1802
|
+
this.calc_bar_width = Math.min(this.max_bar_width, this.drawable_width/this.n);
|
|
1651
1803
|
|
|
1652
1804
|
if(this.orientation == 'bottom'){
|
|
1653
|
-
this.
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1805
|
+
if(this.model.is_more_than_n_orders_of_magnitude(0, top_n_cats[0].val, 3)){
|
|
1806
|
+
let local_log_floor = 0.3
|
|
1807
|
+
this.scale_y = d3.scaleLog()
|
|
1808
|
+
.domain([local_log_floor, top_n_cats[0].val])
|
|
1809
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1810
|
+
|
|
1811
|
+
this.scale_y_inverse = d3.scaleLog()
|
|
1812
|
+
.domain([top_n_cats[0].val, local_log_floor])
|
|
1813
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1814
|
+
}
|
|
1815
|
+
else{
|
|
1816
|
+
this.scale_y = d3.scaleLinear()
|
|
1817
|
+
.domain([0, top_n_cats[0].val])
|
|
1818
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1819
|
+
|
|
1820
|
+
this.scale_y_inverse = d3.scaleLinear()
|
|
1821
|
+
.domain([top_n_cats[0].val, 0])
|
|
1822
|
+
.range([0, this.height - CAT_HISTOGRAM_LAYOUT.inner_padding]);
|
|
1823
|
+
}
|
|
1660
1824
|
|
|
1661
1825
|
//references OVERVIEW LAYOUT SIZES
|
|
1662
1826
|
//BE CAREFUL
|
|
@@ -1664,7 +1828,8 @@ class CategoricalBarChart{
|
|
|
1664
1828
|
.domain(top_n_cats.map((obj)=>{
|
|
1665
1829
|
return obj.key;
|
|
1666
1830
|
}))
|
|
1667
|
-
.range([CAT_HISTOGRAM_LAYOUT.inner_padding, this.width - CAT_HISTOGRAM_LAYOUT.inner_padding])
|
|
1831
|
+
.range([CAT_HISTOGRAM_LAYOUT.inner_padding, this.width - CAT_HISTOGRAM_LAYOUT.inner_padding])
|
|
1832
|
+
.padding(0.1);
|
|
1668
1833
|
}
|
|
1669
1834
|
|
|
1670
1835
|
else if(this.orientation == 'right'){
|
|
@@ -1684,11 +1849,10 @@ class CategoricalBarChart{
|
|
|
1684
1849
|
*/
|
|
1685
1850
|
render(){
|
|
1686
1851
|
|
|
1852
|
+
const self = this;
|
|
1687
1853
|
let top_n_cats = this.model.categorical_bins[this.facet].slice(0,this.n);
|
|
1688
1854
|
let update_targets = [`${this.facet}_heatmap`, `${this.facet}_right_histogram`, `${this.facet}_bottom_histogram`, `${this.facet}_legend`];
|
|
1689
1855
|
|
|
1690
|
-
const self = this;
|
|
1691
|
-
|
|
1692
1856
|
if(self.model.row_major_counts[self.facet].length > 2){
|
|
1693
1857
|
|
|
1694
1858
|
if(this.orientation == 'bottom'){
|
|
@@ -1705,17 +1869,18 @@ class CategoricalBarChart{
|
|
|
1705
1869
|
let col = enter.append('g')
|
|
1706
1870
|
.attr('class', 'column')
|
|
1707
1871
|
.attr('transform', (d, i)=>{
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1872
|
+
const tickPos = self.scale_x(d.key);
|
|
1873
|
+
const bandWidth = self.scale_x.bandwidth();
|
|
1874
|
+
// Center bar if calc_bar_width < bandWidth
|
|
1875
|
+
const offset = (bandWidth - self.calc_bar_width) / 2;
|
|
1876
|
+
return `translate(${tickPos + offset}, ${CAT_HISTOGRAM_LAYOUT.inner_padding})`;
|
|
1712
1877
|
});
|
|
1713
1878
|
|
|
1714
1879
|
col.append('rect')
|
|
1715
1880
|
.attr('class', 'bar')
|
|
1716
1881
|
.attr('height', (d)=>{return self.scale_y(d.val)})
|
|
1717
1882
|
// .attr('width', (d)=>{return ((HISTOGRAM_LAYOUT.width - 2*HISTOGRAM_LAYOUT.inner_padding) / faceted_bins[d.facet].x.length)})
|
|
1718
|
-
.attr('width',
|
|
1883
|
+
.attr('width', self.calc_bar_width)
|
|
1719
1884
|
.attr('fill', TAN)
|
|
1720
1885
|
.attr(`transform`, (d)=>{return `translate(${0}, ${(CAT_HISTOGRAM_LAYOUT.height- self.scale_y(d.val))-2*CAT_HISTOGRAM_LAYOUT.inner_padding})`})
|
|
1721
1886
|
.on('mouseover', function (e,d){
|
|
@@ -1786,6 +1951,7 @@ class Legend {
|
|
|
1786
1951
|
if(color_scale.domain().length > 2){
|
|
1787
1952
|
this.ticks_scale = d3.scaleDiverging().domain(color_scale.domain().reverse()).range([0, this.bar_height/2, this.bar_height]);
|
|
1788
1953
|
} else{
|
|
1954
|
+
console.log("DOMAIN at LEGEND CREATE", color_scale.domain());
|
|
1789
1955
|
if(color_scale.domain()[1] > 2){
|
|
1790
1956
|
this.ticks_scale = d3.scaleSymlog().domain([color_scale.domain()[0]+1, color_scale.domain()[1]].reverse()).range([0, this.bar_height]);
|
|
1791
1957
|
}
|
|
@@ -1910,7 +2076,6 @@ class Validator{
|
|
|
1910
2076
|
*/
|
|
1911
2077
|
isValidDate(dateString) {
|
|
1912
2078
|
const date_time = new Date(dateString);
|
|
1913
|
-
console.log("AAAAA", date_time.getTime());
|
|
1914
2079
|
return !isNaN(date_time.getTime());
|
|
1915
2080
|
}
|
|
1916
2081
|
|
|
@@ -2002,6 +2167,15 @@ class Validator{
|
|
|
2002
2167
|
return missing;
|
|
2003
2168
|
}
|
|
2004
2169
|
|
|
2170
|
+
|
|
2171
|
+
// Function to coerce an entire column’s values to strings
|
|
2172
|
+
coerceColumnToString(columnData) {
|
|
2173
|
+
return Object.keys(columnData).reduce((result, key) => {
|
|
2174
|
+
result[key] = String(columnData[key]);
|
|
2175
|
+
return result;
|
|
2176
|
+
}, {});
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2005
2179
|
/**
|
|
2006
2180
|
* Ensures that all values in this.var_specs are logically appropriate
|
|
2007
2181
|
* @param {Object} this.var_specs - The variable specifications.
|
|
@@ -2023,11 +2197,11 @@ class Validator{
|
|
|
2023
2197
|
if (typeof test_val !== 'number'){
|
|
2024
2198
|
if(typeof test_val == 'string'){
|
|
2025
2199
|
if(!this.isValidDate(test_val)){
|
|
2026
|
-
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis
|
|
2200
|
+
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
2201
|
}
|
|
2028
2202
|
}
|
|
2029
2203
|
else {
|
|
2030
|
-
incorrect.push({ key: key, value: this.var_specs[key], message: 'The x-axis
|
|
2204
|
+
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
2205
|
}
|
|
2032
2206
|
}
|
|
2033
2207
|
}
|
|
@@ -2045,8 +2219,15 @@ class Validator{
|
|
|
2045
2219
|
}
|
|
2046
2220
|
else if (key === 'categorical'){
|
|
2047
2221
|
let test_val = this.data[this.var_specs[key]][Object.keys(this.data[this.var_specs[key]])[0]];
|
|
2222
|
+
// For categorical variables, coerce data to strings if necessary.
|
|
2048
2223
|
if(typeof test_val !== 'string'){
|
|
2049
|
-
|
|
2224
|
+
// Coerce the column data at this.data[this.var_specs[key]]
|
|
2225
|
+
this.data[this.var_specs[key]] = coerceColumnToString(this.data[this.var_specs[key]]);
|
|
2226
|
+
// Re-check the data type after coercion
|
|
2227
|
+
test_val = this.data[this.var_specs[key]][Object.keys(this.data[this.var_specs[key]])[0]];
|
|
2228
|
+
if(typeof test_val !== 'string'){
|
|
2229
|
+
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.' });
|
|
2230
|
+
}
|
|
2050
2231
|
}
|
|
2051
2232
|
}
|
|
2052
2233
|
}
|
|
@@ -2144,7 +2325,6 @@ function render({model, el}){
|
|
|
2144
2325
|
|
|
2145
2326
|
validator.data = data;
|
|
2146
2327
|
is_valid = validator.validate();
|
|
2147
|
-
console.log()
|
|
2148
2328
|
|
|
2149
2329
|
if(is_valid){
|
|
2150
2330
|
let jsmodel = new JSModel(data, var_specs, model);
|
|
@@ -2157,4 +2337,4 @@ function render({model, el}){
|
|
|
2157
2337
|
|
|
2158
2338
|
|
|
2159
2339
|
|
|
2160
|
-
export default{ render }
|
|
2340
|
+
export default{ render };
|
|
@@ -5,6 +5,7 @@ import numpy as np
|
|
|
5
5
|
import warnings
|
|
6
6
|
import json
|
|
7
7
|
import os
|
|
8
|
+
import sys
|
|
8
9
|
|
|
9
10
|
class Guidepost(anywidget.AnyWidget):
|
|
10
11
|
_esm = os.path.join(os.path.dirname(__file__), "guidepost.js")
|
|
@@ -24,6 +25,9 @@ class Guidepost(anywidget.AnyWidget):
|
|
|
24
25
|
in_cpy.insert(0, 'gp_idx', range(0, len(in_cpy)))
|
|
25
26
|
self.cached_records_df = in_cpy
|
|
26
27
|
|
|
28
|
+
if sys.version_info.major < 3 or sys.version_info.minor < 12:
|
|
29
|
+
raise EnvironmentError("Python 3.12 or greater is required to run this library.")
|
|
30
|
+
|
|
27
31
|
_warn_skips = (os.path.dirname('.'),)
|
|
28
32
|
original_cols = in_cpy.columns
|
|
29
33
|
o_df = in_cpy.dropna(axis=1, how='all')
|
|
@@ -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.16
|
|
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
|