allotaxonometer-ui 0.1.2 → 0.1.3
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.
- package/dist/index.js +997 -319
- package/dist/ssr/index.js +449 -205
- package/dist/style.css +2 -2
- package/package.json +15 -6
package/dist/index.js
CHANGED
|
@@ -1,67 +1,8 @@
|
|
|
1
1
|
import 'svelte/internal/disclose-version';
|
|
2
2
|
import * as $ from 'svelte/internal/client';
|
|
3
|
-
import { scaleLinear } from 'd3-scale';
|
|
4
|
-
import { range, extent } from 'd3-array';
|
|
5
3
|
import * as d3 from 'd3';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
var root_1$8 = $.from_svg(`<circle stroke="white" stroke-width="1"></circle>`);
|
|
9
|
-
var root$9 = $.from_svg(`<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg"><rect width="400" height="200" fill="#f8f9fa" stroke="#dee2e6"></rect><text x="200" y="25" text-anchor="middle" font-size="16" font-weight="bold"> </text><g class="chart"></g><line x1="20" y1="180" x2="380" y2="180" stroke="#666" stroke-width="1"></line><line x1="20" y1="20" x2="20" y2="180" stroke="#666" stroke-width="1"></line><text x="200" y="198" text-anchor="middle" font-size="12" fill="#666">X Axis</text><text x="12" y="100" text-anchor="middle" font-size="12" fill="#666" transform="rotate(-90, 12, 100)">Y Axis</text></svg>`);
|
|
10
|
-
|
|
11
|
-
function Test($$anchor, $$props) {
|
|
12
|
-
$.push($$props, true);
|
|
13
|
-
|
|
14
|
-
let message = $.prop($$props, 'message', 3, "Hello World"),
|
|
15
|
-
data = $.prop($$props, 'data', 19, () => []);
|
|
16
|
-
|
|
17
|
-
// If no data provided, generate some test data
|
|
18
|
-
let testData = data().length > 0
|
|
19
|
-
? data()
|
|
20
|
-
: range(10).map((i) => ({
|
|
21
|
-
x: i,
|
|
22
|
-
y: Math.sin(i / 2) * 20 + 50,
|
|
23
|
-
value: Math.random()
|
|
24
|
-
}));
|
|
25
|
-
// Pure D3 calculations - no DOM manipulation
|
|
26
|
-
let xScale = scaleLinear().domain(extent(testData, (d) => d.x)).range([20, 380]);
|
|
27
|
-
let yScale = scaleLinear().domain(extent(testData, (d) => d.y)).range([180, 20]);
|
|
28
|
-
|
|
29
|
-
// Calculate positions
|
|
30
|
-
let points = testData.map((d) => ({
|
|
31
|
-
cx: xScale(d.x),
|
|
32
|
-
cy: yScale(d.y),
|
|
33
|
-
r: 4 + d.value * 6,
|
|
34
|
-
fill: `hsl(${d.value * 360}, 70%, 50%)`
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
var svg = root$9();
|
|
38
|
-
var text = $.sibling($.child(svg));
|
|
39
|
-
var text_1 = $.child(text, true);
|
|
40
|
-
|
|
41
|
-
$.reset(text);
|
|
42
|
-
|
|
43
|
-
var g = $.sibling(text);
|
|
44
|
-
|
|
45
|
-
$.each(g, 21, () => points, $.index, ($$anchor, point) => {
|
|
46
|
-
var circle = root_1$8();
|
|
47
|
-
|
|
48
|
-
$.template_effect(() => {
|
|
49
|
-
$.set_attribute(circle, 'cx', $.get(point).cx);
|
|
50
|
-
$.set_attribute(circle, 'cy', $.get(point).cy);
|
|
51
|
-
$.set_attribute(circle, 'r', $.get(point).r);
|
|
52
|
-
$.set_attribute(circle, 'fill', $.get(point).fill);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
$.append($$anchor, circle);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
$.reset(g);
|
|
59
|
-
$.next(4);
|
|
60
|
-
$.reset(svg);
|
|
61
|
-
$.template_effect(() => $.set_text(text_1, message()));
|
|
62
|
-
$.append($$anchor, svg);
|
|
63
|
-
$.pop();
|
|
64
|
-
}
|
|
4
|
+
import { map, extent, InternSet, range, rollup, scaleLinear, scaleBand, rgb, interpolateInferno, scaleOrdinal, max, scaleLog } from 'd3';
|
|
5
|
+
import { descending, sum, group, extent as extent$1 } from 'd3-array';
|
|
65
6
|
|
|
66
7
|
var root_1$7 = $.from_svg(`<g class="xtick"><line x1="0" x2="0" y1="0" y2="6" stroke="hsla(212, 10%, 53%, 1)"></line></g><g class="tick-text"><text font-size="10" dx="13" dy="13"> </text></g>`, 1);
|
|
67
8
|
var root$8 = $.from_svg(`<g class="axis x"><!><g class="xlab svelte-1y8xk6i"><text dy="45">Rank r</text><text dy="63">for</text><text dy="80"> </text><text dy="60" fill="hsla(212, 10%, 53%, 1)" opacity="0.7">more →</text><text dy="75" fill="hsla(212, 10%, 53%, 1)" opacity="0.7">frequent</text><text dy="60" fill="hsla(212, 10%, 53%, 1)" opacity="0.7">← less</text><text dy="75" fill="hsla(212, 10%, 53%, 1)" opacity="0.7">frequent</text></g></g>`);
|
|
@@ -269,14 +210,14 @@ function Contours($$anchor, $$props) {
|
|
|
269
210
|
}
|
|
270
211
|
}
|
|
271
212
|
|
|
272
|
-
function make_grid(Ninset, tmpr1, tmpr2, alpha,
|
|
213
|
+
function make_grid(Ninset, tmpr1, tmpr2, alpha, divnorm) {
|
|
273
214
|
const deltamatrix = Array.from({ length: Ninset }, () => Array(Ninset).fill(0));
|
|
274
215
|
|
|
275
216
|
for (let i = 0; i < Ninset; i++) {
|
|
276
217
|
for (let j = 0; j < Ninset; j++) {
|
|
277
218
|
const divElem = alpha_norm_type2(1 / tmpr1[i], 1 / tmpr2[j], alpha);
|
|
278
219
|
|
|
279
|
-
deltamatrix[i][j] = divElem /
|
|
220
|
+
deltamatrix[i][j] = divElem / divnorm;
|
|
280
221
|
}
|
|
281
222
|
|
|
282
223
|
deltamatrix[i][i] = -1;
|
|
@@ -319,14 +260,14 @@ function Contours($$anchor, $$props) {
|
|
|
319
260
|
return out;
|
|
320
261
|
}
|
|
321
262
|
|
|
322
|
-
function get_contours(alpha, maxlog10,
|
|
263
|
+
function get_contours(alpha, maxlog10, divnorm) {
|
|
323
264
|
const Ninset = 10 ** 3;
|
|
324
265
|
const tmpr1 = d3.range(0, 1000).map((d) => Math.pow(10, d / 999 * 5));
|
|
325
266
|
const tmpr2 = d3.range(0, 1000).map((d) => Math.pow(10, d / 999 * 5));
|
|
326
267
|
const Ncontours = 10;
|
|
327
268
|
const scale = d3.scaleLinear().domain([0, Ncontours + 1]).range([1, tmpr1.length]);
|
|
328
269
|
const contour_indices = d3.range(Ncontours + 2).map((i) => Math.round(scale(i)));
|
|
329
|
-
const grid = make_grid(Ninset, tmpr1, tmpr2, alpha,
|
|
270
|
+
const grid = make_grid(Ninset, tmpr1, tmpr2, alpha, divnorm);
|
|
330
271
|
const indices = contour_indices.slice(1, -1);
|
|
331
272
|
const lastRow = grid[grid.length - 1];
|
|
332
273
|
const heights = indices.map((index) => lastRow[index]);
|
|
@@ -339,7 +280,7 @@ function Contours($$anchor, $$props) {
|
|
|
339
280
|
}
|
|
340
281
|
|
|
341
282
|
// Only calculate contours in browser
|
|
342
|
-
let mycontours = $.derived(() => get_contours($$props.alpha, $$props.maxlog10, $$props.
|
|
283
|
+
let mycontours = $.derived(() => get_contours($$props.alpha, $$props.maxlog10, $$props.divnorm));
|
|
343
284
|
const x = $.derived(() => d3.scaleLinear([0, $$props.maxlog10], [0, $$props.DiamondInnerHeight]));
|
|
344
285
|
const y = $.derived(() => d3.scaleLinear([$$props.maxlog10, 0], [$$props.DiamondInnerHeight, 0]));
|
|
345
286
|
const pathData = d3.line().x((d, i) => $.get(x)(d[0])).y((d, i) => $.get(y)(d[1]));
|
|
@@ -357,32 +298,39 @@ function Contours($$anchor, $$props) {
|
|
|
357
298
|
$.pop();
|
|
358
299
|
}
|
|
359
300
|
|
|
360
|
-
var root_1$3 = $.from_svg(`<rect stroke="black"
|
|
301
|
+
var root_1$3 = $.from_svg(`<rect stroke="black"></rect>`);
|
|
361
302
|
var root_2$3 = $.from_svg(`<g class="diamond-lab"><text dy="20" font-size="10"> </text></g>`);
|
|
362
303
|
var root$4 = $.from_svg(`<g class="diamond-chart"><polygon fill="#89CFF0" fill-opacity="0.2" stroke="black" stroke-width="0.5"></polygon><polygon fill="grey" fill-opacity="0.2" stroke="black" stroke-width="0.5"></polygon><!><!><!><!><!><!></g>`);
|
|
363
304
|
|
|
364
305
|
function Diamond($$anchor, $$props) {
|
|
365
306
|
$.push($$props, true);
|
|
366
307
|
|
|
308
|
+
let DiamondHeight = $.prop($$props, 'DiamondHeight', 3, 600),
|
|
309
|
+
marginInner = $.prop($$props, 'marginInner', 3, 160),
|
|
310
|
+
marginDiamond = $.prop($$props, 'marginDiamond', 3, 40);
|
|
311
|
+
|
|
312
|
+
// Extract data from dat object
|
|
313
|
+
let diamond_dat = $.derived(() => $$props.dat.counts);
|
|
314
|
+
$.derived(() => $$props.dat.deltas);
|
|
315
|
+
// Calculate derived dimensions (matching D3 version)
|
|
316
|
+
let innerHeight = $.derived(() => DiamondHeight() - marginInner());
|
|
317
|
+
let diamondHeight = $.derived(() => $.get(innerHeight) - marginDiamond());
|
|
318
|
+
|
|
367
319
|
function get_relevant_types(diamond_dat) {
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
const
|
|
320
|
+
// Use the logic from your D3 version instead
|
|
321
|
+
const ncells = d3.max(diamond_dat, (d) => d.x1);
|
|
322
|
+
const cumbin = d3.range(0, ncells, 1.5);
|
|
371
323
|
const relevant_types = [];
|
|
372
324
|
|
|
373
325
|
for (let sys of ["right", "left"]) {
|
|
374
|
-
for (let i = 1; i <
|
|
375
|
-
const filtered_dat = diamond_dat.filter((d) => d.value > 0 && d.which_sys == sys).filter((d) => d.coord_on_diag >=
|
|
326
|
+
for (let i = 1; i < cumbin.length; i++) {
|
|
327
|
+
const filtered_dat = diamond_dat.filter((d) => d.value > 0 && d.which_sys == sys).filter((d) => d.coord_on_diag >= cumbin[i - 1] && d.coord_on_diag < cumbin[i]);
|
|
376
328
|
|
|
377
329
|
if (filtered_dat.length > 0) {
|
|
378
330
|
const cos_dists = filtered_dat.map((d) => d.cos_dist);
|
|
379
|
-
|
|
380
|
-
const max_dist = cos_dists.reduce((a, b) => {
|
|
381
|
-
return Math.max(a, b);
|
|
382
|
-
});
|
|
383
|
-
|
|
331
|
+
const max_dist = cos_dists.reduce((a, b) => Math.max(a, b));
|
|
384
332
|
const max_dist_idx = cos_dists.indexOf(max_dist);
|
|
385
|
-
//
|
|
333
|
+
// SSR-safe random selection
|
|
386
334
|
const types = filtered_dat[max_dist_idx]['types'].split(",");
|
|
387
335
|
const name = types[Math.floor(Math.random() * types.length)];
|
|
388
336
|
|
|
@@ -395,44 +343,40 @@ function Diamond($$anchor, $$props) {
|
|
|
395
343
|
}
|
|
396
344
|
|
|
397
345
|
function rin(arr1, arr2) {
|
|
398
|
-
return Array.from(arr1, (x) =>
|
|
399
|
-
return arr2.indexOf(x) == -1 ? false : true;
|
|
400
|
-
});
|
|
346
|
+
return Array.from(arr1, (x) => arr2.indexOf(x) !== -1);
|
|
401
347
|
}
|
|
402
348
|
|
|
403
|
-
// Wrangling data
|
|
404
|
-
let relevant_types = $.derived(() => get_relevant_types(
|
|
405
|
-
|
|
406
|
-
let
|
|
407
|
-
let
|
|
408
|
-
let rounded_max_rank = $.derived(() => 10 ** Math.ceil(Math.max(Math.log10($.get(max_rank)))));
|
|
409
|
-
let ncells = $.derived(() => d3.max($.get(max_rank_raw)));
|
|
349
|
+
// Wrangling data - Fixed variable references
|
|
350
|
+
let relevant_types = $.derived(() => get_relevant_types($.get(diamond_dat)));
|
|
351
|
+
let ncells = $.derived(() => d3.max($.get(diamond_dat), (d) => d.x1));
|
|
352
|
+
let max_rank = $.derived(() => d3.max($.get(diamond_dat), (d) => d.rank_L[1]));
|
|
353
|
+
let rounded_max_rank = $.derived(() => 10 ** Math.ceil(Math.log10($.get(max_rank))));
|
|
410
354
|
let xyDomain = $.derived(() => [1, $.get(rounded_max_rank)]);
|
|
411
|
-
//
|
|
412
|
-
let
|
|
413
|
-
let
|
|
414
|
-
let
|
|
415
|
-
let
|
|
355
|
+
// Scales (matching D3 version dimensions)
|
|
356
|
+
let xy = $.derived(() => d3.scaleBand().domain($.get(diamond_dat).map((d) => d.y1)).range([0, $.get(diamondHeight)]));
|
|
357
|
+
let logScale = $.derived(() => d3.scaleLog().domain($.get(xyDomain)).range([0, $.get(innerHeight)]).nice());
|
|
358
|
+
let linScale = $.derived(() => d3.scaleLinear().domain([0, $.get(ncells) - 1]).range([0, $.get(innerHeight)]));
|
|
359
|
+
let wxy = $.derived(() => d3.scaleBand().domain(d3.range($.get(ncells))).range([0, $.get(innerHeight)]));
|
|
416
360
|
let color_scale = d3.scaleSequentialLog().domain([$.get(rounded_max_rank), 1]).interpolator(d3.interpolateInferno);
|
|
417
361
|
|
|
418
|
-
// Background
|
|
419
|
-
let blue_triangle = [
|
|
362
|
+
// Background triangles (using innerHeight like D3 version)
|
|
363
|
+
let blue_triangle = $.derived(() => [
|
|
420
364
|
[
|
|
421
|
-
|
|
422
|
-
|
|
365
|
+
$.get(innerHeight),
|
|
366
|
+
$.get(innerHeight)
|
|
423
367
|
],
|
|
424
368
|
[0, 0],
|
|
425
|
-
[0,
|
|
426
|
-
].join(" ");
|
|
369
|
+
[0, $.get(innerHeight)]
|
|
370
|
+
].join(" "));
|
|
427
371
|
|
|
428
|
-
let grey_triangle = [
|
|
372
|
+
let grey_triangle = $.derived(() => [
|
|
429
373
|
[
|
|
430
|
-
|
|
431
|
-
|
|
374
|
+
$.get(innerHeight),
|
|
375
|
+
$.get(innerHeight)
|
|
432
376
|
],
|
|
433
377
|
[0, 0],
|
|
434
|
-
[
|
|
435
|
-
].join(" ");
|
|
378
|
+
[$.get(innerHeight), 0]
|
|
379
|
+
].join(" "));
|
|
436
380
|
|
|
437
381
|
function filter_labs(d, relevant_types) {
|
|
438
382
|
return rin(relevant_types, d.types.split(",")).some((x) => x === true);
|
|
@@ -445,7 +389,7 @@ function Diamond($$anchor, $$props) {
|
|
|
445
389
|
|
|
446
390
|
AxisX(node, {
|
|
447
391
|
get height() {
|
|
448
|
-
return
|
|
392
|
+
return $.get(innerHeight);
|
|
449
393
|
},
|
|
450
394
|
get scale() {
|
|
451
395
|
return $.get(logScale);
|
|
@@ -459,7 +403,7 @@ function Diamond($$anchor, $$props) {
|
|
|
459
403
|
|
|
460
404
|
AxisY(node_1, {
|
|
461
405
|
get height() {
|
|
462
|
-
return
|
|
406
|
+
return $.get(innerHeight);
|
|
463
407
|
},
|
|
464
408
|
get scale() {
|
|
465
409
|
return $.get(logScale);
|
|
@@ -473,7 +417,7 @@ function Diamond($$anchor, $$props) {
|
|
|
473
417
|
|
|
474
418
|
Grid(node_2, {
|
|
475
419
|
get height() {
|
|
476
|
-
return
|
|
420
|
+
return $.get(innerHeight);
|
|
477
421
|
},
|
|
478
422
|
get wxy() {
|
|
479
423
|
return $.get(wxy);
|
|
@@ -488,7 +432,7 @@ function Diamond($$anchor, $$props) {
|
|
|
488
432
|
|
|
489
433
|
var node_3 = $.sibling(node_2);
|
|
490
434
|
|
|
491
|
-
$.each(node_3, 17, () =>
|
|
435
|
+
$.each(node_3, 17, () => $.get(diamond_dat), $.index, ($$anchor, d) => {
|
|
492
436
|
var rect = root_1$3();
|
|
493
437
|
|
|
494
438
|
$.template_effect(
|
|
@@ -498,7 +442,9 @@ function Diamond($$anchor, $$props) {
|
|
|
498
442
|
$.set_attribute(rect, 'width', $2);
|
|
499
443
|
$.set_attribute(rect, 'height', $3);
|
|
500
444
|
$.set_attribute(rect, 'fill', $4);
|
|
501
|
-
$.set_attribute(rect, 'opacity', $.get(d).value ===
|
|
445
|
+
$.set_attribute(rect, 'opacity', $.get(d).value === 0 ? 0 : 1);
|
|
446
|
+
$.set_attribute(rect, 'stroke-width', $.get(d).value === 0 ? 0 : 0.1);
|
|
447
|
+
$.set_attribute(rect, 'stroke-opacity', $.get(d).value === 0 ? 0 : 0.9);
|
|
502
448
|
},
|
|
503
449
|
[
|
|
504
450
|
() => $.get(xy)($.get(d).x1),
|
|
@@ -514,7 +460,7 @@ function Diamond($$anchor, $$props) {
|
|
|
514
460
|
|
|
515
461
|
var node_4 = $.sibling(node_3);
|
|
516
462
|
|
|
517
|
-
$.each(node_4, 17, () =>
|
|
463
|
+
$.each(node_4, 17, () => $.get(diamond_dat).filter((d) => filter_labs(d, $.get(relevant_types))), $.index, ($$anchor, d) => {
|
|
518
464
|
var g_1 = root_2$3();
|
|
519
465
|
var text = $.child(g_1);
|
|
520
466
|
var text_1 = $.child(text, true);
|
|
@@ -558,264 +504,325 @@ function Diamond($$anchor, $$props) {
|
|
|
558
504
|
get maxlog10() {
|
|
559
505
|
return $$props.maxlog10;
|
|
560
506
|
},
|
|
561
|
-
get
|
|
562
|
-
return $$props.
|
|
507
|
+
get divnorm() {
|
|
508
|
+
return $$props.divnorm;
|
|
563
509
|
},
|
|
564
510
|
get DiamondInnerHeight() {
|
|
565
|
-
return
|
|
511
|
+
return $.get(innerHeight);
|
|
566
512
|
}
|
|
567
513
|
});
|
|
568
514
|
|
|
569
515
|
$.reset(g);
|
|
570
516
|
|
|
571
517
|
$.template_effect(() => {
|
|
572
|
-
$.set_attribute(g, 'transform', `translate(360, 0) scale (-1,1) rotate(45) translate(${
|
|
573
|
-
$.set_attribute(polygon, 'points', blue_triangle);
|
|
574
|
-
$.set_attribute(polygon_1, 'points', grey_triangle);
|
|
518
|
+
$.set_attribute(g, 'transform', `translate(360, 0) scale (-1,1) rotate(45) translate(${$.get(innerHeight) / 4}, ${$.get(innerHeight) / 4})`);
|
|
519
|
+
$.set_attribute(polygon, 'points', $.get(blue_triangle));
|
|
520
|
+
$.set_attribute(polygon_1, 'points', $.get(grey_triangle));
|
|
575
521
|
});
|
|
576
522
|
|
|
577
523
|
$.append($$anchor, g);
|
|
578
524
|
$.pop();
|
|
579
525
|
}
|
|
580
526
|
|
|
581
|
-
var root_1$2 = $.from_svg(`<g class="tick"><line y1="0" stroke="
|
|
582
|
-
var root_2$2 = $.from_svg(`<rect></rect
|
|
583
|
-
var
|
|
527
|
+
var root_1$2 = $.from_svg(`<g class="tick"><line y1="0" stroke="currentColor" stroke-opacity="0.1"></line><text y="-12" font-size="0.8em" text-anchor="middle"> </text></g>`);
|
|
528
|
+
var root_2$2 = $.from_svg(`<rect></rect>`);
|
|
529
|
+
var root_3$2 = $.from_svg(`<text dy="0.35em" font-size="0.7em"> </text>`);
|
|
530
|
+
var root$3 = $.from_svg(`<g class="wordshift-container svelte-48jn79"><g class="axis x"><!><text y="-22" fill="currentColor" text-anchor="center" font-size="0.9em"> </text></g><!><g class="y-axis"></g></g>`);
|
|
584
531
|
|
|
585
532
|
function Wordshift($$anchor, $$props) {
|
|
586
533
|
$.push($$props, true);
|
|
587
534
|
|
|
588
|
-
let
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
535
|
+
let x = $.prop($$props, 'x', 3, (d) => d.metric),
|
|
536
|
+
y = $.prop($$props, 'y', 3, (d) => d.type),
|
|
537
|
+
marginTop = $.prop($$props, 'marginTop', 3, 30),
|
|
538
|
+
marginRight = $.prop($$props, 'marginRight', 3, 40),
|
|
539
|
+
marginBottom = $.prop($$props, 'marginBottom', 3, 10),
|
|
540
|
+
marginLeft = $.prop($$props, 'marginLeft', 3, 40),
|
|
541
|
+
width = $.prop($$props, 'width', 3, 300);
|
|
542
|
+
$.prop($$props, 'height', 3, 680);
|
|
543
|
+
let xFormat = $.prop($$props, 'xFormat', 3, '%'),
|
|
544
|
+
xLabel = $.prop($$props, 'xLabel', 3, '← System 1 · Divergence contribution · System 2 →'),
|
|
545
|
+
yPadding = $.prop($$props, 'yPadding', 3, 0.2),
|
|
546
|
+
colors = $.prop($$props, 'colors', 19, () => ['lightgrey', 'lightblue']);
|
|
547
|
+
|
|
548
|
+
// Compute values (matching D3 version)
|
|
549
|
+
let X = $.derived(() => d3.map($$props.barData, x()));
|
|
550
|
+
let Y = $.derived(() => d3.map($$props.barData, y()));
|
|
551
|
+
// Compute domains
|
|
552
|
+
let computedXDomain = $.derived(() => $$props.xDomain || d3.extent($.get(X)));
|
|
594
553
|
let yDomain = $.derived(() => new d3.InternSet($.get(Y)));
|
|
595
554
|
|
|
555
|
+
// Compute dimensions
|
|
596
556
|
let xRange = $.derived(() => [
|
|
597
|
-
|
|
598
|
-
|
|
557
|
+
marginLeft(),
|
|
558
|
+
width() - marginRight()
|
|
599
559
|
]);
|
|
600
560
|
|
|
561
|
+
let computedHeight = $.derived(() => Math.ceil(($.get(yDomain).size + yPadding()) * 25) + marginTop() + marginBottom());
|
|
562
|
+
|
|
601
563
|
let yRange = $.derived(() => [
|
|
602
|
-
|
|
603
|
-
|
|
564
|
+
marginTop(),
|
|
565
|
+
$.get(computedHeight) - marginBottom()
|
|
604
566
|
]);
|
|
605
567
|
|
|
606
|
-
|
|
607
|
-
let
|
|
608
|
-
let
|
|
609
|
-
|
|
568
|
+
// Filter indices and create lookup
|
|
569
|
+
let I = $.derived(() => d3.range($.get(X).length).filter((i) => $.get(yDomain).has($.get(Y)[i])));
|
|
570
|
+
let YX = $.derived(() => d3.rollup($.get(I), ([i]) => $.get(X)[i], (i) => $.get(Y)[i]));
|
|
571
|
+
// Scales
|
|
572
|
+
let xScale = $.derived(() => d3.scaleLinear($.get(computedXDomain), $.get(xRange)));
|
|
573
|
+
let yScale = $.derived(() => d3.scaleBand().domain($.get(yDomain)).range($.get(yRange)).padding(yPadding()));
|
|
574
|
+
let format = $.derived(() => $.get(xScale).tickFormat(100, xFormat()));
|
|
575
|
+
let xTicks = $.derived(() => $.get(xScale).ticks(width() / 80));
|
|
576
|
+
// Position the chart (matching your current positioning)
|
|
577
|
+
let chartX = $.derived(() => $$props.DashboardWidth - width() + marginLeft());
|
|
578
|
+
let chartY = $.derived(marginTop);
|
|
610
579
|
var g = root$3();
|
|
611
580
|
var g_1 = $.child(g);
|
|
581
|
+
var node = $.child(g_1);
|
|
612
582
|
|
|
613
|
-
$.each(
|
|
583
|
+
$.each(node, 17, () => $.get(xTicks), $.index, ($$anchor, tick) => {
|
|
614
584
|
var g_2 = root_1$2();
|
|
615
585
|
var line = $.child(g_2);
|
|
616
|
-
var text = $.
|
|
617
|
-
|
|
618
|
-
$.reset(line);
|
|
619
|
-
|
|
620
|
-
var text_1 = $.sibling(line);
|
|
621
|
-
var text_2 = $.child(text_1);
|
|
586
|
+
var text = $.sibling(line);
|
|
587
|
+
var text_1 = $.child(text, true);
|
|
622
588
|
|
|
623
|
-
$.reset(
|
|
589
|
+
$.reset(text);
|
|
624
590
|
$.reset(g_2);
|
|
625
591
|
|
|
626
592
|
$.template_effect(
|
|
627
|
-
($0, $1, $2) => {
|
|
593
|
+
($0, $1, $2, $3) => {
|
|
628
594
|
$.set_attribute(line, 'x1', $0);
|
|
629
595
|
$.set_attribute(line, 'x2', $1);
|
|
630
|
-
$.set_attribute(line, 'y2',
|
|
631
|
-
$.
|
|
632
|
-
$.
|
|
633
|
-
$.set_text(text_2, `${$.get(tick) * 100}%`);
|
|
596
|
+
$.set_attribute(line, 'y2', $.get(computedHeight) - marginTop() - marginBottom());
|
|
597
|
+
$.set_attribute(text, 'x', $2);
|
|
598
|
+
$.set_text(text_1, $3);
|
|
634
599
|
},
|
|
635
600
|
[
|
|
636
601
|
() => $.get(xScale)($.get(tick)),
|
|
637
602
|
() => $.get(xScale)($.get(tick)),
|
|
638
|
-
() => $.get(xScale)($.get(tick))
|
|
603
|
+
() => $.get(xScale)($.get(tick)),
|
|
604
|
+
() => $.get(format)($.get(tick))
|
|
639
605
|
]
|
|
640
606
|
);
|
|
641
607
|
|
|
642
608
|
$.append($$anchor, g_2);
|
|
643
609
|
});
|
|
644
610
|
|
|
645
|
-
$.
|
|
611
|
+
var text_2 = $.sibling(node);
|
|
612
|
+
var text_3 = $.child(text_2, true);
|
|
646
613
|
|
|
647
|
-
|
|
614
|
+
$.reset(text_2);
|
|
615
|
+
$.reset(g_1);
|
|
648
616
|
|
|
649
|
-
|
|
650
|
-
var fragment = root_2$2();
|
|
651
|
-
var rect = $.first_child(fragment);
|
|
652
|
-
var text_3 = $.sibling(rect);
|
|
653
|
-
var text_4 = $.child(text_3, true);
|
|
617
|
+
var node_1 = $.sibling(g_1);
|
|
654
618
|
|
|
655
|
-
|
|
619
|
+
$.each(node_1, 17, () => $.get(I), $.index, ($$anchor, i) => {
|
|
620
|
+
var rect = root_2$2();
|
|
656
621
|
|
|
657
622
|
$.template_effect(
|
|
658
|
-
($0, $1, $2, $3
|
|
623
|
+
($0, $1, $2, $3) => {
|
|
659
624
|
$.set_attribute(rect, 'x', $0);
|
|
660
625
|
$.set_attribute(rect, 'y', $1);
|
|
661
|
-
$.set_attribute(rect, 'fill', colors[$.get(
|
|
626
|
+
$.set_attribute(rect, 'fill', colors()[$.get(X)[$.get(i)] > 0 ? colors().length - 1 : 0]);
|
|
662
627
|
$.set_attribute(rect, 'width', $2);
|
|
663
628
|
$.set_attribute(rect, 'height', $3);
|
|
664
|
-
$.set_attribute(text_3, 'x', $4);
|
|
665
|
-
$.set_attribute(text_3, 'y', $5);
|
|
666
|
-
$.set_text(text_4, $.get(d).type);
|
|
667
629
|
},
|
|
668
630
|
[
|
|
669
|
-
() => Math.min($.get(xScale)(0), $.get(xScale)($.get(
|
|
670
|
-
() => $.get(yScale)($.get(
|
|
671
|
-
() => Math.abs($.get(xScale)($.get(
|
|
672
|
-
() => $.get(yScale).bandwidth()
|
|
673
|
-
() => Math.min($.get(xScale)(0), $.get(xScale)($.get(d).metric)),
|
|
674
|
-
() => $.get(yScale)($.get(d).type)
|
|
631
|
+
() => Math.min($.get(xScale)(0), $.get(xScale)($.get(X)[$.get(i)])),
|
|
632
|
+
() => $.get(yScale)($.get(Y)[$.get(i)]),
|
|
633
|
+
() => Math.abs($.get(xScale)($.get(X)[$.get(i)]) - $.get(xScale)(0)),
|
|
634
|
+
() => $.get(yScale).bandwidth()
|
|
675
635
|
]
|
|
676
636
|
);
|
|
677
637
|
|
|
678
|
-
$.append($$anchor,
|
|
638
|
+
$.append($$anchor, rect);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
var g_3 = $.sibling(node_1);
|
|
642
|
+
|
|
643
|
+
$.each(g_3, 21, () => $.get(yScale).domain(), $.index, ($$anchor, label) => {
|
|
644
|
+
var text_4 = root_3$2();
|
|
645
|
+
var text_5 = $.child(text_4, true);
|
|
646
|
+
|
|
647
|
+
$.reset(text_4);
|
|
648
|
+
|
|
649
|
+
$.template_effect(
|
|
650
|
+
($0, $1, $2) => {
|
|
651
|
+
$.set_attribute(text_4, 'x', $0);
|
|
652
|
+
$.set_attribute(text_4, 'y', $1);
|
|
653
|
+
$.set_attribute(text_4, 'text-anchor', $2);
|
|
654
|
+
$.set_text(text_5, $.get(label));
|
|
655
|
+
},
|
|
656
|
+
[
|
|
657
|
+
() => $.get(YX).get($.get(label)) > 0 ? 6 : -6,
|
|
658
|
+
() => $.get(yScale)($.get(label)) + $.get(yScale).bandwidth() / 2,
|
|
659
|
+
() => $.get(YX).get($.get(label)) > 0 ? "start" : "end"
|
|
660
|
+
]
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
$.append($$anchor, text_4);
|
|
679
664
|
});
|
|
680
665
|
|
|
666
|
+
$.reset(g_3);
|
|
681
667
|
$.reset(g);
|
|
682
|
-
|
|
668
|
+
|
|
669
|
+
$.template_effect(
|
|
670
|
+
($0, $1) => {
|
|
671
|
+
$.set_attribute(g, 'transform', `translate(${$.get(chartX) ?? ''}, ${$.get(chartY) ?? ''})`);
|
|
672
|
+
$.set_attribute(g_1, 'transform', `translate(0, ${marginTop() ?? ''})`);
|
|
673
|
+
$.set_attribute(text_2, 'x', $0);
|
|
674
|
+
$.set_text(text_3, xLabel());
|
|
675
|
+
$.set_attribute(g_3, 'transform', `translate(${$1 ?? ''}, 0)`);
|
|
676
|
+
},
|
|
677
|
+
[
|
|
678
|
+
() => $.get(xScale)(0),
|
|
679
|
+
() => $.get(xScale)(0)
|
|
680
|
+
]
|
|
681
|
+
);
|
|
682
|
+
|
|
683
683
|
$.append($$anchor, g);
|
|
684
684
|
$.pop();
|
|
685
685
|
}
|
|
686
686
|
|
|
687
|
-
var root_1$1 = $.from_svg(`<
|
|
688
|
-
var root_2$1 = $.from_svg(`<
|
|
689
|
-
var
|
|
687
|
+
var root_1$1 = $.from_svg(`<line y1="0" stroke="currentColor" stroke-opacity="0.1"></line>`);
|
|
688
|
+
var root_2$1 = $.from_svg(`<rect></rect><text opacity="0.5" dy="0.35em" font-size="10" font-family="sans-serif"> </text>`, 1);
|
|
689
|
+
var root_3$1 = $.from_svg(`<text x="0" dy="0.35em" font-size="10" font-family="sans-serif" text-anchor="middle"> </text>`);
|
|
690
|
+
var root$2 = $.from_svg(`<g class="balance-chart"><g class="grid"></g><!><g class="y-axis"></g></g>`);
|
|
690
691
|
|
|
691
692
|
function DivergingBarChart($$anchor, $$props) {
|
|
692
693
|
$.push($$props, true);
|
|
693
694
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
695
|
+
let x = $.prop($$props, 'x', 3, (d) => d.frequency),
|
|
696
|
+
y = $.prop($$props, 'y', 3, (d) => d.y_coord),
|
|
697
|
+
marginTop = $.prop($$props, 'marginTop', 3, 0),
|
|
698
|
+
marginRight = $.prop($$props, 'marginRight', 3, 40),
|
|
699
|
+
marginBottom = $.prop($$props, 'marginBottom', 3, 10),
|
|
700
|
+
marginLeft = $.prop($$props, 'marginLeft', 3, 40),
|
|
701
|
+
width = $.prop($$props, 'width', 3, 200),
|
|
702
|
+
yPadding = $.prop($$props, 'yPadding', 3, 0.5),
|
|
703
|
+
colors = $.prop($$props, 'colors', 19, () => ["lightgrey", "lightblue"]);
|
|
704
|
+
|
|
705
|
+
// Compute values (matching D3 version exactly)
|
|
706
|
+
let X = $.derived(() => map($$props.data, x()));
|
|
707
|
+
let Y = $.derived(() => map($$props.data, y()));
|
|
708
|
+
// Compute domains
|
|
709
|
+
let xDomain = $.derived(() => extent($.get(X)));
|
|
710
|
+
let yDomain = $.derived(() => new InternSet($.get(Y)));
|
|
704
711
|
|
|
705
|
-
|
|
706
|
-
|
|
712
|
+
// Compute dimensions
|
|
713
|
+
let xRange = $.derived(() => [
|
|
714
|
+
marginLeft(),
|
|
715
|
+
width() - marginRight()
|
|
716
|
+
]);
|
|
707
717
|
|
|
708
|
-
let
|
|
709
|
-
let types_2 = $.derived(() => $$props.test_elem_2.map((d) => d.types));
|
|
710
|
-
let union_types = $.derived(() => union($.get(types_1), $.get(types_2)));
|
|
711
|
-
let tot_types = $.derived(() => $.get(types_1).length + $.get(types_2).length);
|
|
712
|
-
let width = 200;
|
|
713
|
-
let margin = { right: 40, top: 30, left: 40, bottom: 10 };
|
|
714
|
-
let yPadding = 0.5;
|
|
715
|
-
let colors = ["lightgrey", "lightblue"];
|
|
718
|
+
let height = $.derived(() => Math.ceil(($.get(yDomain).size + yPadding()) * 25) + marginTop() + marginBottom());
|
|
716
719
|
|
|
717
|
-
let
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
frequency: +($.get(types_2).length / $.get(tot_types)).toFixed(3)
|
|
721
|
-
},
|
|
722
|
-
{
|
|
723
|
-
y_coord: "total count",
|
|
724
|
-
frequency: -($.get(types_1).length / $.get(tot_types)).toFixed(3)
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
y_coord: "all names",
|
|
728
|
-
frequency: +($.get(types_2).length / $.get(union_types).size).toFixed(3)
|
|
729
|
-
},
|
|
730
|
-
{
|
|
731
|
-
y_coord: "all names",
|
|
732
|
-
frequency: -($.get(types_1).length / $.get(union_types).size).toFixed(3)
|
|
733
|
-
},
|
|
734
|
-
{
|
|
735
|
-
y_coord: "exclusive names",
|
|
736
|
-
frequency: +(setdiff($.get(types_2), $.get(types_1)).size / $.get(types_2).length).toFixed(3)
|
|
737
|
-
},
|
|
738
|
-
{
|
|
739
|
-
y_coord: "exclusive names",
|
|
740
|
-
frequency: -(setdiff($.get(types_1), $.get(types_2)).size / $.get(types_1).length).toFixed(3)
|
|
741
|
-
}
|
|
720
|
+
let yRange = $.derived(() => [
|
|
721
|
+
marginTop(),
|
|
722
|
+
$.get(height) - marginBottom()
|
|
742
723
|
]);
|
|
743
724
|
|
|
744
|
-
|
|
745
|
-
let
|
|
746
|
-
let
|
|
747
|
-
|
|
748
|
-
let
|
|
749
|
-
let
|
|
750
|
-
let I = $.derived(() => range$1($.get(X).length).filter((i) => $.get(yDomain).has($.get(Y)[i])));
|
|
751
|
-
$.derived(() => rollup($.get(I), ([i]) => $.get(X)[i], (i) => $.get(Y)[i]));
|
|
752
|
-
let xScale = $.derived(() => scaleLinear$1($.get(xDomain), $.get(xRange)));
|
|
753
|
-
let yScale = $.derived(() => scaleBand().domain($.get(yDomain)).range([margin.top, $.get(height) - margin.bottom]).padding(yPadding));
|
|
725
|
+
// Filter indices and create lookup
|
|
726
|
+
let I = $.derived(() => range($.get(X).length).filter((i) => $.get(yDomain).has($.get(Y)[i])));
|
|
727
|
+
let YX = $.derived(() => rollup($.get(I), ([i]) => $.get(X)[i], (i) => $.get(Y)[i]));
|
|
728
|
+
// Scales
|
|
729
|
+
let xScale = $.derived(() => scaleLinear($.get(xDomain), $.get(xRange)));
|
|
730
|
+
let yScale = $.derived(() => scaleBand().domain($.get(yDomain)).range($.get(yRange)).padding(yPadding()));
|
|
754
731
|
let format = $.derived(() => $.get(xScale).tickFormat(100, "%"));
|
|
755
732
|
var g = root$2();
|
|
756
|
-
var
|
|
733
|
+
var g_1 = $.child(g);
|
|
734
|
+
|
|
735
|
+
$.each(g_1, 21, () => $.get(xScale).ticks(width() / 80), $.index, ($$anchor, tick) => {
|
|
736
|
+
var line = root_1$1();
|
|
737
|
+
|
|
738
|
+
$.template_effect(
|
|
739
|
+
($0, $1) => {
|
|
740
|
+
$.set_attribute(line, 'x1', $0);
|
|
741
|
+
$.set_attribute(line, 'x2', $1);
|
|
742
|
+
$.set_attribute(line, 'y2', $.get(height) - marginTop() - marginBottom());
|
|
743
|
+
},
|
|
744
|
+
[
|
|
745
|
+
() => $.get(xScale)($.get(tick)),
|
|
746
|
+
() => $.get(xScale)($.get(tick))
|
|
747
|
+
]
|
|
748
|
+
);
|
|
757
749
|
|
|
758
|
-
|
|
759
|
-
|
|
750
|
+
$.append($$anchor, line);
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
$.reset(g_1);
|
|
754
|
+
|
|
755
|
+
var node = $.sibling(g_1);
|
|
756
|
+
|
|
757
|
+
$.each(node, 17, () => $.get(I), $.index, ($$anchor, i) => {
|
|
758
|
+
var fragment = root_2$1();
|
|
760
759
|
var rect = $.first_child(fragment);
|
|
761
|
-
var
|
|
762
|
-
var
|
|
760
|
+
var text = $.sibling(rect);
|
|
761
|
+
var text_1 = $.child(text, true);
|
|
763
762
|
|
|
764
|
-
$.reset(
|
|
763
|
+
$.reset(text);
|
|
765
764
|
|
|
766
765
|
$.template_effect(
|
|
767
766
|
($0, $1, $2, $3, $4, $5, $6) => {
|
|
768
767
|
$.set_attribute(rect, 'x', $0);
|
|
769
768
|
$.set_attribute(rect, 'y', $1);
|
|
770
|
-
$.set_attribute(rect, 'fill', colors[$.get(X)[i] > 0 ? colors.length - 1 : 0]);
|
|
769
|
+
$.set_attribute(rect, 'fill', colors()[$.get(X)[$.get(i)] > 0 ? colors().length - 1 : 0]);
|
|
771
770
|
$.set_attribute(rect, 'width', $2);
|
|
772
771
|
$.set_attribute(rect, 'height', $3);
|
|
773
|
-
$.set_attribute(
|
|
774
|
-
$.set_attribute(
|
|
775
|
-
$.set_attribute(
|
|
776
|
-
$.set_text(
|
|
772
|
+
$.set_attribute(text, 'x', $4);
|
|
773
|
+
$.set_attribute(text, 'y', $5);
|
|
774
|
+
$.set_attribute(text, 'text-anchor', $.get(X)[$.get(i)] < 0 ? "end" : "start");
|
|
775
|
+
$.set_text(text_1, $6);
|
|
777
776
|
},
|
|
778
777
|
[
|
|
779
|
-
() => Math.min($.get(xScale)(0), $.get(xScale)($.get(
|
|
780
|
-
() => $.get(yScale)($.get(
|
|
781
|
-
() => Math.abs($.get(xScale)($.get(
|
|
778
|
+
() => Math.min($.get(xScale)(0), $.get(xScale)($.get(X)[$.get(i)])),
|
|
779
|
+
() => $.get(yScale)($.get(Y)[$.get(i)]),
|
|
780
|
+
() => Math.abs($.get(xScale)($.get(X)[$.get(i)]) - $.get(xScale)(0)),
|
|
782
781
|
() => $.get(yScale).bandwidth(),
|
|
783
|
-
() => $.get(xScale)($.get(X)[i]) + Math.sign($.get(X)[i] - 0) * 4,
|
|
784
|
-
() => $.get(yScale)($.get(Y)[i]) + $.get(yScale).bandwidth() / 2,
|
|
785
|
-
() => $.get(format)(Math.abs($.get(
|
|
782
|
+
() => $.get(xScale)($.get(X)[$.get(i)]) + Math.sign($.get(X)[$.get(i)] - 0) * 4,
|
|
783
|
+
() => $.get(yScale)($.get(Y)[$.get(i)]) + $.get(yScale).bandwidth() / 2,
|
|
784
|
+
() => $.get(format)(Math.abs($.get(X)[$.get(i)]))
|
|
786
785
|
]
|
|
787
786
|
);
|
|
788
787
|
|
|
789
788
|
$.append($$anchor, fragment);
|
|
790
789
|
});
|
|
791
790
|
|
|
792
|
-
var
|
|
791
|
+
var g_2 = $.sibling(node);
|
|
793
792
|
|
|
794
|
-
$.each(
|
|
795
|
-
var
|
|
796
|
-
var text_3 = $.child(
|
|
797
|
-
var text_4 = $.child(text_3, true);
|
|
793
|
+
$.each(g_2, 21, () => $.get(yScale).domain(), $.index, ($$anchor, label) => {
|
|
794
|
+
var text_2 = root_3$1();
|
|
795
|
+
var text_3 = $.child(text_2, true);
|
|
798
796
|
|
|
799
|
-
$.reset(
|
|
800
|
-
$.reset(g_1);
|
|
797
|
+
$.reset(text_2);
|
|
801
798
|
|
|
802
799
|
$.template_effect(
|
|
803
800
|
($0, $1) => {
|
|
804
|
-
$.set_attribute(
|
|
805
|
-
$.set_attribute(
|
|
806
|
-
$.set_text(
|
|
801
|
+
$.set_attribute(text_2, 'y', $0);
|
|
802
|
+
$.set_attribute(text_2, 'opacity', $1);
|
|
803
|
+
$.set_text(text_3, $.get(label));
|
|
807
804
|
},
|
|
808
805
|
[
|
|
809
|
-
() => $.get(
|
|
810
|
-
() => $.get(
|
|
806
|
+
() => $.get(yScale)($.get(label)) + $.get(yScale).bandwidth() / 2,
|
|
807
|
+
() => $.get(YX).get($.get(label)) ? "0.5" : "1"
|
|
811
808
|
]
|
|
812
809
|
);
|
|
813
810
|
|
|
814
|
-
$.append($$anchor,
|
|
811
|
+
$.append($$anchor, text_2);
|
|
815
812
|
});
|
|
816
813
|
|
|
814
|
+
$.reset(g_2);
|
|
817
815
|
$.reset(g);
|
|
818
|
-
|
|
816
|
+
|
|
817
|
+
$.template_effect(
|
|
818
|
+
($0) => {
|
|
819
|
+
$.set_attribute(g, 'transform', `translate(${$$props.DiamondWidth - 75}, ${$$props.DiamondHeight + 75})`);
|
|
820
|
+
$.set_attribute(g_1, 'transform', `translate(0,${marginTop() ?? ''})`);
|
|
821
|
+
$.set_attribute(g_2, 'transform', `translate(${$0 ?? ''},-12)`);
|
|
822
|
+
},
|
|
823
|
+
[() => $.get(xScale)(0)]
|
|
824
|
+
);
|
|
825
|
+
|
|
819
826
|
$.append($$anchor, g);
|
|
820
827
|
$.pop();
|
|
821
828
|
}
|
|
@@ -829,19 +836,16 @@ function Legend($$anchor, $$props) {
|
|
|
829
836
|
$.push($$props, true);
|
|
830
837
|
|
|
831
838
|
const N_CATEGO = 20;
|
|
832
|
-
const myramp = range
|
|
833
|
-
const color = scaleOrdinal(range
|
|
839
|
+
const myramp = range(N_CATEGO).map((i) => rgb(interpolateInferno(i / (N_CATEGO - 1))).hex());
|
|
840
|
+
const color = scaleOrdinal(range(N_CATEGO), myramp);
|
|
834
841
|
let height = 370;
|
|
835
842
|
const margin = { right: 40, top: 65, left: 10 };
|
|
836
843
|
let innerHeight = $.derived(() => height - margin.top - margin.right);
|
|
837
844
|
let max_rank = $.derived(() => max($$props.diamond_dat, (d) => d.rank_L[1]));
|
|
838
845
|
let y = $.derived(() => scaleBand().domain(color.domain().reverse()).rangeRound([0, $.get(innerHeight)]));
|
|
839
|
-
|
|
840
|
-
let
|
|
841
|
-
|
|
842
|
-
10 ** Math.ceil(Math.max(Math.log10($.get(max_rank))) - 1)
|
|
843
|
-
]).rangeRound([0, $.get(innerHeight)]).nice());
|
|
844
|
-
|
|
846
|
+
// Use max_count_log if provided, otherwise calculate from data
|
|
847
|
+
let logDomain = $.derived(() => $$props.max_count_log || 10 ** Math.ceil(Math.log10($.get(max_rank)) - 1));
|
|
848
|
+
let logY = $.derived(() => scaleLog().domain([1, $.get(logDomain)]).rangeRound([0, $.get(innerHeight)]).nice());
|
|
845
849
|
let logFormat10 = $.derived(() => $.get(logY).tickFormat());
|
|
846
850
|
let yTicks = $.derived(() => $.get(logY).ticks());
|
|
847
851
|
var fragment = root$1();
|
|
@@ -926,22 +930,25 @@ function Legend($$anchor, $$props) {
|
|
|
926
930
|
var root = $.from_html(`<div><svg id="allotaxonometer-svg" class="svelte-n6o6ey"><!><!><!><!></svg></div>`);
|
|
927
931
|
|
|
928
932
|
function Dashboard($$anchor, $$props) {
|
|
929
|
-
|
|
930
|
-
|
|
933
|
+
$.push($$props, true);
|
|
934
|
+
|
|
935
|
+
let dat = $.prop($$props, 'dat', 3, null),
|
|
936
|
+
alpha = $.prop($$props, 'alpha', 3, 0.58),
|
|
937
|
+
divnorm = $.prop($$props, 'divnorm', 3, 1),
|
|
931
938
|
barData = $.prop($$props, 'barData', 19, () => []),
|
|
932
|
-
|
|
933
|
-
|
|
939
|
+
balanceData = $.prop($$props, 'balanceData', 19, () => []),
|
|
940
|
+
xDomain = $.prop($$props, 'xDomain', 3, undefined),
|
|
941
|
+
title = $.prop($$props, 'title', 19, () => ['System 1', 'System 2']),
|
|
942
|
+
maxlog10 = $.prop($$props, 'maxlog10', 3, 0),
|
|
934
943
|
height = $.prop($$props, 'height', 3, 815),
|
|
935
944
|
width = $.prop($$props, 'width', 3, 1200),
|
|
945
|
+
DashboardHeight = $.prop($$props, 'DashboardHeight', 3, 815),
|
|
946
|
+
DashboardWidth = $.prop($$props, 'DashboardWidth', 3, 1200),
|
|
936
947
|
DiamondHeight = $.prop($$props, 'DiamondHeight', 3, 600),
|
|
937
948
|
DiamondWidth = $.prop($$props, 'DiamondWidth', 3, 600),
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
alpha = $.prop($$props, 'alpha', 3, 0.58),
|
|
942
|
-
maxlog10 = $.prop($$props, 'maxlog10', 3, 0),
|
|
943
|
-
rtd = $.prop($$props, 'rtd', 3, null),
|
|
944
|
-
title = $.prop($$props, 'title', 19, () => ['System 1', 'System 2']),
|
|
949
|
+
marginInner = $.prop($$props, 'marginInner', 3, 160),
|
|
950
|
+
marginDiamond = $.prop($$props, 'marginDiamond', 3, 40),
|
|
951
|
+
max_count_log = $.prop($$props, 'max_count_log', 3, undefined),
|
|
945
952
|
className = $.prop($$props, 'class', 3, ''),
|
|
946
953
|
style = $.prop($$props, 'style', 3, ''),
|
|
947
954
|
showDiamond = $.prop($$props, 'showDiamond', 3, true),
|
|
@@ -952,22 +959,23 @@ function Dashboard($$anchor, $$props) {
|
|
|
952
959
|
'$$slots',
|
|
953
960
|
'$$events',
|
|
954
961
|
'$$legacy',
|
|
955
|
-
'
|
|
956
|
-
'
|
|
962
|
+
'dat',
|
|
963
|
+
'alpha',
|
|
964
|
+
'divnorm',
|
|
957
965
|
'barData',
|
|
958
|
-
'
|
|
959
|
-
'
|
|
966
|
+
'balanceData',
|
|
967
|
+
'xDomain',
|
|
968
|
+
'title',
|
|
969
|
+
'maxlog10',
|
|
960
970
|
'height',
|
|
961
971
|
'width',
|
|
972
|
+
'DashboardHeight',
|
|
973
|
+
'DashboardWidth',
|
|
962
974
|
'DiamondHeight',
|
|
963
975
|
'DiamondWidth',
|
|
964
|
-
'
|
|
965
|
-
'
|
|
966
|
-
'
|
|
967
|
-
'alpha',
|
|
968
|
-
'maxlog10',
|
|
969
|
-
'rtd',
|
|
970
|
-
'title',
|
|
976
|
+
'marginInner',
|
|
977
|
+
'marginDiamond',
|
|
978
|
+
'max_count_log',
|
|
971
979
|
'class',
|
|
972
980
|
'style',
|
|
973
981
|
'showDiamond',
|
|
@@ -976,6 +984,13 @@ function Dashboard($$anchor, $$props) {
|
|
|
976
984
|
'showLegend'
|
|
977
985
|
]);
|
|
978
986
|
|
|
987
|
+
let max_shift = $.derived(() => barData().length > 0 ? Math.max(...barData().map((d) => Math.abs(d.metric))) : 1);
|
|
988
|
+
|
|
989
|
+
let wordshiftXDomain = $.derived(() => xDomain() || [
|
|
990
|
+
-$.get(max_shift) * 1.5,
|
|
991
|
+
$.get(max_shift) * 1.5
|
|
992
|
+
]);
|
|
993
|
+
|
|
979
994
|
var div = root();
|
|
980
995
|
|
|
981
996
|
$.attribute_effect(
|
|
@@ -995,38 +1010,35 @@ function Dashboard($$anchor, $$props) {
|
|
|
995
1010
|
{
|
|
996
1011
|
var consequent = ($$anchor) => {
|
|
997
1012
|
Diamond($$anchor, {
|
|
998
|
-
get
|
|
999
|
-
return
|
|
1000
|
-
},
|
|
1001
|
-
get diamond_dat() {
|
|
1002
|
-
return diamond_dat();
|
|
1003
|
-
},
|
|
1004
|
-
get DiamondInnerHeight() {
|
|
1005
|
-
return DiamondInnerHeight();
|
|
1006
|
-
},
|
|
1007
|
-
get margin() {
|
|
1008
|
-
return margin();
|
|
1009
|
-
},
|
|
1010
|
-
get trueDiamondHeight() {
|
|
1011
|
-
return trueDiamondHeight();
|
|
1013
|
+
get dat() {
|
|
1014
|
+
return dat();
|
|
1012
1015
|
},
|
|
1013
1016
|
get alpha() {
|
|
1014
1017
|
return alpha();
|
|
1015
1018
|
},
|
|
1019
|
+
get divnorm() {
|
|
1020
|
+
return divnorm();
|
|
1021
|
+
},
|
|
1022
|
+
get title() {
|
|
1023
|
+
return title();
|
|
1024
|
+
},
|
|
1016
1025
|
get maxlog10() {
|
|
1017
1026
|
return maxlog10();
|
|
1018
1027
|
},
|
|
1019
|
-
get
|
|
1020
|
-
return
|
|
1028
|
+
get DiamondHeight() {
|
|
1029
|
+
return DiamondHeight();
|
|
1030
|
+
},
|
|
1031
|
+
get marginInner() {
|
|
1032
|
+
return marginInner();
|
|
1021
1033
|
},
|
|
1022
|
-
get
|
|
1023
|
-
return
|
|
1034
|
+
get marginDiamond() {
|
|
1035
|
+
return marginDiamond();
|
|
1024
1036
|
}
|
|
1025
1037
|
});
|
|
1026
1038
|
};
|
|
1027
1039
|
|
|
1028
1040
|
$.if(node, ($$render) => {
|
|
1029
|
-
if (showDiamond()) $$render(consequent);
|
|
1041
|
+
if (showDiamond() && dat()) $$render(consequent);
|
|
1030
1042
|
});
|
|
1031
1043
|
}
|
|
1032
1044
|
|
|
@@ -1039,16 +1051,21 @@ function Dashboard($$anchor, $$props) {
|
|
|
1039
1051
|
return barData();
|
|
1040
1052
|
},
|
|
1041
1053
|
get DashboardHeight() {
|
|
1042
|
-
return
|
|
1054
|
+
return DashboardHeight();
|
|
1043
1055
|
},
|
|
1044
1056
|
get DashboardWidth() {
|
|
1045
|
-
return
|
|
1046
|
-
}
|
|
1057
|
+
return DashboardWidth();
|
|
1058
|
+
},
|
|
1059
|
+
get xDomain() {
|
|
1060
|
+
return $.get(wordshiftXDomain);
|
|
1061
|
+
},
|
|
1062
|
+
width: 640,
|
|
1063
|
+
marginLeft: 140
|
|
1047
1064
|
});
|
|
1048
1065
|
};
|
|
1049
1066
|
|
|
1050
1067
|
$.if(node_1, ($$render) => {
|
|
1051
|
-
if (showWordshift()) $$render(consequent_1);
|
|
1068
|
+
if (showWordshift() && barData().length > 0) $$render(consequent_1);
|
|
1052
1069
|
});
|
|
1053
1070
|
}
|
|
1054
1071
|
|
|
@@ -1057,11 +1074,8 @@ function Dashboard($$anchor, $$props) {
|
|
|
1057
1074
|
{
|
|
1058
1075
|
var consequent_2 = ($$anchor) => {
|
|
1059
1076
|
DivergingBarChart($$anchor, {
|
|
1060
|
-
get
|
|
1061
|
-
return
|
|
1062
|
-
},
|
|
1063
|
-
get test_elem_2() {
|
|
1064
|
-
return test_elem_2();
|
|
1077
|
+
get data() {
|
|
1078
|
+
return balanceData();
|
|
1065
1079
|
},
|
|
1066
1080
|
get DiamondHeight() {
|
|
1067
1081
|
return DiamondHeight();
|
|
@@ -1073,7 +1087,7 @@ function Dashboard($$anchor, $$props) {
|
|
|
1073
1087
|
};
|
|
1074
1088
|
|
|
1075
1089
|
$.if(node_2, ($$render) => {
|
|
1076
|
-
if (showDivergingBar()) $$render(consequent_2);
|
|
1090
|
+
if (showDivergingBar() && balanceData().length > 0) $$render(consequent_2);
|
|
1077
1091
|
});
|
|
1078
1092
|
}
|
|
1079
1093
|
|
|
@@ -1083,16 +1097,19 @@ function Dashboard($$anchor, $$props) {
|
|
|
1083
1097
|
var consequent_3 = ($$anchor) => {
|
|
1084
1098
|
Legend($$anchor, {
|
|
1085
1099
|
get diamond_dat() {
|
|
1086
|
-
return
|
|
1100
|
+
return dat().counts;
|
|
1087
1101
|
},
|
|
1088
1102
|
get DiamondHeight() {
|
|
1089
1103
|
return DiamondHeight();
|
|
1104
|
+
},
|
|
1105
|
+
get max_count_log() {
|
|
1106
|
+
return max_count_log();
|
|
1090
1107
|
}
|
|
1091
1108
|
});
|
|
1092
1109
|
};
|
|
1093
1110
|
|
|
1094
1111
|
$.if(node_3, ($$render) => {
|
|
1095
|
-
if (showLegend()) $$render(consequent_3);
|
|
1112
|
+
if (showLegend() && dat()) $$render(consequent_3);
|
|
1096
1113
|
});
|
|
1097
1114
|
}
|
|
1098
1115
|
|
|
@@ -1105,6 +1122,667 @@ function Dashboard($$anchor, $$props) {
|
|
|
1105
1122
|
});
|
|
1106
1123
|
|
|
1107
1124
|
$.append($$anchor, div);
|
|
1125
|
+
$.pop();
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// Takes arrays, returns a Set object containing the union of both arrays
|
|
1129
|
+
function getUnions(x,y) {
|
|
1130
|
+
let a = new Set(x); // convert array x to a Set object
|
|
1131
|
+
let b = new Set(y); // convert array y to a Set object
|
|
1132
|
+
return new Set([...a, ...b]); // return a new Set object containing the union of a and b
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// Takes arrays, returns a Set object
|
|
1136
|
+
function setdiff(x,y) {
|
|
1137
|
+
let a = new Set(x); // convert array x to a Set object
|
|
1138
|
+
let b = new Set(y); // convert array y to a Set object
|
|
1139
|
+
// return a new Set object containing elements in a that are not present in b
|
|
1140
|
+
return new Set(
|
|
1141
|
+
[...a].filter(x => !b.has(x)));
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
function which(x) {
|
|
1145
|
+
// Which indices are TRUE?
|
|
1146
|
+
// Description:
|
|
1147
|
+
// Give the ‘TRUE’ indices of a logical object, allowing for array indices.
|
|
1148
|
+
// Arguments:
|
|
1149
|
+
// x: a ‘logical’ vector or array.
|
|
1150
|
+
return x.reduce(
|
|
1151
|
+
(out, bool, index) => bool ? out.concat(index) : out,
|
|
1152
|
+
[]
|
|
1153
|
+
)
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
function matlab_sort(A, rev) {
|
|
1158
|
+
// Inspired by matlab, this functions keep track of the original indices of an array after sorting.
|
|
1159
|
+
// Returns both the sorted vector `v` and the original indices.
|
|
1160
|
+
//
|
|
1161
|
+
// examples
|
|
1162
|
+
// A = [5, 4, 1, 2, 3]
|
|
1163
|
+
// ([1, 2, 3, 3, 4, 5], [3, 4, 5, 6, 2, 1])
|
|
1164
|
+
|
|
1165
|
+
let sorted = rev ? A.slice().sort((a, b) => b - a) : A.slice().sort((a, b) => a - b);
|
|
1166
|
+
|
|
1167
|
+
const A_cp = A.slice();
|
|
1168
|
+
const orig_idx = [];
|
|
1169
|
+
for (let i = 0; i < A.length; ++i) {
|
|
1170
|
+
orig_idx.push(A_cp.indexOf(sorted[i]));
|
|
1171
|
+
delete A_cp[A_cp.indexOf(sorted[i])];
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
return {'value': sorted, 'orig_idx': orig_idx}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
function tiedrank(arr) {
|
|
1178
|
+
// tiedrank(X) computes the ranks of the values in the vector X. If any X values are tied, tiedrank computes their average rank. Same as in matlab.
|
|
1179
|
+
function getIndex(arr, val) {
|
|
1180
|
+
var indexes = [], i;
|
|
1181
|
+
for(i = 0; i < arr.length; i++)
|
|
1182
|
+
if (arr[i] === val)
|
|
1183
|
+
indexes.push(i+1);
|
|
1184
|
+
return indexes.reduce((a, b) => a + b) / indexes.length;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
const sorted = arr.slice().sort((a, b) => b - a);
|
|
1188
|
+
return arr.map(e => getIndex(sorted, e))
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
function rank_maxlog10(mixedelements) {
|
|
1192
|
+
// Get maximum of log10 ranks from both systems, then round up
|
|
1193
|
+
let logged_max = [
|
|
1194
|
+
Math.max(...mixedelements[[0]].ranks), Math.max(...mixedelements[[1]].ranks)
|
|
1195
|
+
].map(Math.log10);
|
|
1196
|
+
return Math.ceil(Math.max(...[logged_max[0], logged_max[1]]))
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
function rin(arr1, arr2) {
|
|
1200
|
+
// Find element arr1 presents in arr2, i.e. arr1 %in% arr2
|
|
1201
|
+
//
|
|
1202
|
+
// examples
|
|
1203
|
+
// A = ["bob", "george", "jesus"]
|
|
1204
|
+
// B = ["bob", "jesus", "terrence"]
|
|
1205
|
+
// rin(A, B)
|
|
1206
|
+
// [true, false, true]
|
|
1207
|
+
return Array.from(arr1, (x) => {
|
|
1208
|
+
return arr2.indexOf(x) == -1 ? false : true
|
|
1209
|
+
})
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
function zeros(length){
|
|
1213
|
+
// Create array of all zeros. Similar to matlab.
|
|
1214
|
+
function createArray(length) {
|
|
1215
|
+
var arr = new Array(length || 0),
|
|
1216
|
+
i = length;
|
|
1217
|
+
if (arguments.length > 1) {
|
|
1218
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
1219
|
+
while(i--) arr[length-1 - i] = createArray.apply(this, args);
|
|
1220
|
+
}
|
|
1221
|
+
return arr;
|
|
1222
|
+
}
|
|
1223
|
+
let empty_mat = createArray(length,length);
|
|
1224
|
+
return Array.from(empty_mat, arr => arr.fill(0))
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// Builds a mixed element array containing the union of types in elem1 and elem2
|
|
1228
|
+
function buildMixedElems(elem1, elem2) {
|
|
1229
|
+
const mixedelem = [[], []];
|
|
1230
|
+
const x = elem1.map(d=>d.types); // extract types from elem1
|
|
1231
|
+
const y = elem2.map(d=>d.types); // extract types from elem
|
|
1232
|
+
const union = Array.from(getUnions(x,y)); // get the union of x and y
|
|
1233
|
+
mixedelem[0]['types'] = union; // store union in mixedelem array for elem1
|
|
1234
|
+
mixedelem[1]['types'] = union; // store union in mixedelem array for elem2
|
|
1235
|
+
return mixedelem // return mixedelem array
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// Combine elements and return a combined array containing counts, ranks, probs, and totalunique
|
|
1239
|
+
function combElems(elem1, elem2) {
|
|
1240
|
+
const mixedelem = buildMixedElems(elem1, elem2); // build mixed elements array
|
|
1241
|
+
const enum_list = [elem1, elem2]; // list containing elem1 and elem2
|
|
1242
|
+
|
|
1243
|
+
for (let j=0; j < enum_list.length; j++) {
|
|
1244
|
+
const enumlist_types = enum_list[j].map(d => d.types); // extract types from enum_list[j]
|
|
1245
|
+
const counts = new Array(mixedelem[j]['types'].length); // initialize counts array
|
|
1246
|
+
const probs = new Array(mixedelem[j]['types'].length); // initialize probs array
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
// for each index in mixed elem[j], which is the union of both systems
|
|
1250
|
+
for (let i=0; i < mixedelem[j]['types'].length; i++) { // find the index of type mixedelem[j]['types'][i] in system 1 or 2
|
|
1251
|
+
// find the index of type mixedelem[j]['types'][i] in system 1 or 2
|
|
1252
|
+
let idx_type_enumlist_in_elem = enumlist_types.indexOf(mixedelem[j]['types'][i]);
|
|
1253
|
+
// if it exists, grabs counts and probs information else put a 0.
|
|
1254
|
+
counts[i] = idx_type_enumlist_in_elem === -1 ? 0 : enum_list[j][idx_type_enumlist_in_elem]["counts"];
|
|
1255
|
+
probs[i] = idx_type_enumlist_in_elem === -1 ? 0 : enum_list[j][idx_type_enumlist_in_elem]["probs"];
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
// store counts, ranks, probs, and totalunique in mixedelem array for elem1 or elem2
|
|
1260
|
+
mixedelem[j]['counts'] = counts;
|
|
1261
|
+
mixedelem[j]['ranks'] = tiedrank(mixedelem[j]['counts']);
|
|
1262
|
+
mixedelem[j]['probs'] = probs;
|
|
1263
|
+
mixedelem[j]['totalunique'] = getUnions().length;
|
|
1264
|
+
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
return mixedelem // return mixedelem array
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
// helpers to wrangle data for the balance plot
|
|
1271
|
+
function balanceDat(elem1, elem2) {
|
|
1272
|
+
const types_1 = elem1.map(d => d.types);
|
|
1273
|
+
const types_2 = elem2.map(d => d.types);
|
|
1274
|
+
|
|
1275
|
+
const union_types = getUnions(types_1, types_2);
|
|
1276
|
+
const tot_types = types_1.length+types_2.length;
|
|
1277
|
+
|
|
1278
|
+
return [
|
|
1279
|
+
{ y_coord: "total count", frequency: +(types_2.length / tot_types).toFixed(3) },
|
|
1280
|
+
{ y_coord: "total count", frequency: -(types_1.length / tot_types).toFixed(3) },
|
|
1281
|
+
{ y_coord: "all names", frequency: +(types_2.length / union_types.size).toFixed(3) },
|
|
1282
|
+
{ y_coord: "all names", frequency: -(types_1.length / union_types.size).toFixed(3) },
|
|
1283
|
+
{ y_coord: "exclusive names", frequency: +(setdiff(types_2, types_1).size / types_2.length).toFixed(3) },
|
|
1284
|
+
{ y_coord: "exclusive names", frequency: -(setdiff(types_1, types_2).size / types_1.length).toFixed(3) }
|
|
1285
|
+
]
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// helper to wrangle the data for the wordshift plot
|
|
1289
|
+
function wordShift_dat(me, dat) {
|
|
1290
|
+
const out = [];
|
|
1291
|
+
for (let i=0; i < me[0]['types'].length; i++) {
|
|
1292
|
+
const rank_diff = me[0]['ranks'][i]-me[1]['ranks'][i];
|
|
1293
|
+
out.push({
|
|
1294
|
+
'type': `${me[0]['types'][i]} (${me[0]['ranks'][i]} ⇋ ${me[1]['ranks'][i]})` ,
|
|
1295
|
+
'rank_diff': rank_diff,
|
|
1296
|
+
'metric': rank_diff < 0 ? -dat.deltas[i] : dat.deltas[i],
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
return out.slice().sort((a, b) => descending(Math.abs(a.metric), Math.abs(b.metric)))
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// This function calculates the divergence between two arrays of inverse ranks
|
|
1304
|
+
// based on the specified alpha value. If alpha is equal to infinity, it returns
|
|
1305
|
+
// an array with the maximum of each element in inv_r1 and inv_r2. If alpha is
|
|
1306
|
+
// equal to 0, it returns an array with the log of the ratio of the maximum and
|
|
1307
|
+
// minimum of 1/inv_r1 and 1/inv_r2 for each element. Otherwise, it returns an
|
|
1308
|
+
// array with the absolute value of (alpha + 1)/alpha * (inv_r1^alpha - inv_r2^alpha)^(1/(alpha + 1))
|
|
1309
|
+
// for each element.
|
|
1310
|
+
|
|
1311
|
+
function divElems(inv_r1, inv_r2, alpha) {
|
|
1312
|
+
if (alpha === Infinity) {
|
|
1313
|
+
return inv_r1.map((d,i) => inv_r1[i] == inv_r2[i] ? 0 : Math.max(inv_r1[i], inv_r2[i]))
|
|
1314
|
+
} else if (alpha == 0) {
|
|
1315
|
+
const x_max = inv_r1.map((d,i) => Math.max(1 / inv_r1[i], 1 / inv_r2[i]));
|
|
1316
|
+
const x_min = inv_r1.map((d,i) => Math.min(1 / inv_r1[i], 1 / inv_r2[i]));
|
|
1317
|
+
return inv_r1.map((d,i) => Math.log10(x_max[i] / x_min[i]))
|
|
1318
|
+
} else {
|
|
1319
|
+
return inv_r1.map((d,i) => (alpha+1) / alpha * Math.abs(inv_r1[i]**alpha - inv_r2[i]**alpha)**(1. / (alpha+1)))
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// This function calculates the normalization factor for the divergence between
|
|
1324
|
+
// two arrays of inverse ranks. It first extracts the counts from the mixedelements
|
|
1325
|
+
// parameter and finds the indices where the counts are greater than 0. It then
|
|
1326
|
+
// calculates the disjoint set for each array based on the number of non-zero
|
|
1327
|
+
// counts. If alpha is equal to infinity, it returns the sum of the elements in
|
|
1328
|
+
// inv_r1 and inv_r2 for the indices with non-zero counts. If alpha is equal to
|
|
1329
|
+
// 0, it returns the sum of the absolute value of the log of the ratio of each
|
|
1330
|
+
// element in inv_r1 and the disjoint set for inv_r2, and the absolute value of
|
|
1331
|
+
// the log of the ratio of each element in inv_r2 and the disjoint set for inv_r1.
|
|
1332
|
+
// Otherwise, it returns the sum of (alpha + 1)/alpha * (inv_r1^alpha - disjoint set^alpha)^(1/(alpha + 1))
|
|
1333
|
+
// for each element in inv_r1, and the same for inv_r2.
|
|
1334
|
+
|
|
1335
|
+
function norm_divElems(mixedelements, inv_r1, inv_r2, alpha) {
|
|
1336
|
+
const c1 = mixedelements[0]['counts'];
|
|
1337
|
+
const c2 = mixedelements[1]['counts'];
|
|
1338
|
+
|
|
1339
|
+
const indices1 = which(c1.map(d => d > 0));
|
|
1340
|
+
const indices2 = which(c2.map(d => d > 0));
|
|
1341
|
+
|
|
1342
|
+
const N1 = indices1.length;
|
|
1343
|
+
const N2 = indices2.length;
|
|
1344
|
+
|
|
1345
|
+
// This function calculates the disjoint set for a given array of inverse ranks
|
|
1346
|
+
// based on the number of non-zero counts in the array and the number of non-zero
|
|
1347
|
+
// counts in the other array. It returns 1/(number of non-zero counts in other array +
|
|
1348
|
+
// number of non-zero counts in this array/2)
|
|
1349
|
+
|
|
1350
|
+
function calc_disjoint(N1, N2) {
|
|
1351
|
+
return( 1 / (N2 + N1/2) )
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
const inv_r1_disjoint = calc_disjoint(N1, N2);
|
|
1355
|
+
const inv_r2_disjoint = calc_disjoint(N2, N1);
|
|
1356
|
+
|
|
1357
|
+
if (alpha === Infinity) {
|
|
1358
|
+
|
|
1359
|
+
return sum(indices1.map((i) => inv_r1[i])) + sum(indices2.map((i) => inv_r2[i]))
|
|
1360
|
+
|
|
1361
|
+
} else if (alpha === 0) {
|
|
1362
|
+
const term1 = sum(
|
|
1363
|
+
indices1.map((i) => Math.abs(Math.log(inv_r1[i] / inv_r2_disjoint)))
|
|
1364
|
+
);
|
|
1365
|
+
const term2 = sum(
|
|
1366
|
+
indices2.map((i) => Math.abs(Math.log(inv_r2[i] / inv_r1_disjoint)))
|
|
1367
|
+
);
|
|
1368
|
+
return term1 + term2
|
|
1369
|
+
} else {
|
|
1370
|
+
const term1 = (alpha+1)/alpha * sum(
|
|
1371
|
+
indices1.map((i) => inv_r1[i]).map( d => (Math.abs(d**alpha) - inv_r2_disjoint**alpha)**(1./(alpha+1) ))
|
|
1372
|
+
);
|
|
1373
|
+
const term2 = (alpha+1)/alpha * sum(
|
|
1374
|
+
indices2.map((i) => inv_r2[i]).map(d => Math.abs(inv_r1_disjoint**alpha - d**alpha)**(1. / (alpha+1)))
|
|
1375
|
+
);
|
|
1376
|
+
return term1 + term2
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// This function calculates the rank turbulence divergence for two arrays of mixed
|
|
1381
|
+
// elements, using the specified alpha value. It first calculates the arrays of
|
|
1382
|
+
// inverse ranks for each mixed element array and then calculates the divergence
|
|
1383
|
+
// and normalization factors using the divElems and norm_divElems functions. It
|
|
1384
|
+
// returns the divergence divided by the normalization.
|
|
1385
|
+
|
|
1386
|
+
function rank_turbulence_divergence(mixedelements, alpha) {
|
|
1387
|
+
|
|
1388
|
+
const inv_r1 = mixedelements[0]['ranks'].map(d => Math.pow(d, -1));
|
|
1389
|
+
const inv_r2 = mixedelements[1]['ranks'].map(d => Math.pow(d, -1));
|
|
1390
|
+
|
|
1391
|
+
const divergence_elements = divElems(inv_r1, inv_r2, alpha);
|
|
1392
|
+
const normalization = norm_divElems(mixedelements, inv_r1, inv_r2, alpha);
|
|
1393
|
+
|
|
1394
|
+
return { // the divergence used to wordshift dat to sort name in wordshift plot
|
|
1395
|
+
// is equal to the formula in the upperleft of the diamond plot. However
|
|
1396
|
+
// the formula is a proportionality and miss the normalization constant
|
|
1397
|
+
// shown here.
|
|
1398
|
+
// Example: for alpha = infinity, for the rank 1 names on both systems, the formula as written is equal to max(1/1, 1/former_rank) = 1/1 =1
|
|
1399
|
+
// this value of 1 is then divided by the normalization constant.
|
|
1400
|
+
// this constant of proportionality is the reason for the difference between the 1/1 that the written formula gives you
|
|
1401
|
+
// and the decimal value that wordshift_dat states and which is actuallly used to sort the types.
|
|
1402
|
+
'divergence_elements': divergence_elements.map(d => d / normalization),
|
|
1403
|
+
'normalization': normalization
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
const VOID = -1;
|
|
1408
|
+
const PRIMITIVE = 0;
|
|
1409
|
+
const ARRAY = 1;
|
|
1410
|
+
const OBJECT = 2;
|
|
1411
|
+
const DATE = 3;
|
|
1412
|
+
const REGEXP = 4;
|
|
1413
|
+
const MAP = 5;
|
|
1414
|
+
const SET = 6;
|
|
1415
|
+
const ERROR = 7;
|
|
1416
|
+
const BIGINT = 8;
|
|
1417
|
+
// export const SYMBOL = 9;
|
|
1418
|
+
|
|
1419
|
+
const env = typeof self === 'object' ? self : globalThis;
|
|
1420
|
+
|
|
1421
|
+
const deserializer = ($, _) => {
|
|
1422
|
+
const as = (out, index) => {
|
|
1423
|
+
$.set(index, out);
|
|
1424
|
+
return out;
|
|
1425
|
+
};
|
|
1426
|
+
|
|
1427
|
+
const unpair = index => {
|
|
1428
|
+
if ($.has(index))
|
|
1429
|
+
return $.get(index);
|
|
1430
|
+
|
|
1431
|
+
const [type, value] = _[index];
|
|
1432
|
+
switch (type) {
|
|
1433
|
+
case PRIMITIVE:
|
|
1434
|
+
case VOID:
|
|
1435
|
+
return as(value, index);
|
|
1436
|
+
case ARRAY: {
|
|
1437
|
+
const arr = as([], index);
|
|
1438
|
+
for (const index of value)
|
|
1439
|
+
arr.push(unpair(index));
|
|
1440
|
+
return arr;
|
|
1441
|
+
}
|
|
1442
|
+
case OBJECT: {
|
|
1443
|
+
const object = as({}, index);
|
|
1444
|
+
for (const [key, index] of value)
|
|
1445
|
+
object[unpair(key)] = unpair(index);
|
|
1446
|
+
return object;
|
|
1447
|
+
}
|
|
1448
|
+
case DATE:
|
|
1449
|
+
return as(new Date(value), index);
|
|
1450
|
+
case REGEXP: {
|
|
1451
|
+
const {source, flags} = value;
|
|
1452
|
+
return as(new RegExp(source, flags), index);
|
|
1453
|
+
}
|
|
1454
|
+
case MAP: {
|
|
1455
|
+
const map = as(new Map, index);
|
|
1456
|
+
for (const [key, index] of value)
|
|
1457
|
+
map.set(unpair(key), unpair(index));
|
|
1458
|
+
return map;
|
|
1459
|
+
}
|
|
1460
|
+
case SET: {
|
|
1461
|
+
const set = as(new Set, index);
|
|
1462
|
+
for (const index of value)
|
|
1463
|
+
set.add(unpair(index));
|
|
1464
|
+
return set;
|
|
1465
|
+
}
|
|
1466
|
+
case ERROR: {
|
|
1467
|
+
const {name, message} = value;
|
|
1468
|
+
return as(new env[name](message), index);
|
|
1469
|
+
}
|
|
1470
|
+
case BIGINT:
|
|
1471
|
+
return as(BigInt(value), index);
|
|
1472
|
+
case 'BigInt':
|
|
1473
|
+
return as(Object(BigInt(value)), index);
|
|
1474
|
+
case 'ArrayBuffer':
|
|
1475
|
+
return as(new Uint8Array(value).buffer, value);
|
|
1476
|
+
case 'DataView': {
|
|
1477
|
+
const { buffer } = new Uint8Array(value);
|
|
1478
|
+
return as(new DataView(buffer), value);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
return as(new env[type](value), index);
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
return unpair;
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
/**
|
|
1488
|
+
* @typedef {Array<string,any>} Record a type representation
|
|
1489
|
+
*/
|
|
1490
|
+
|
|
1491
|
+
/**
|
|
1492
|
+
* Returns a deserialized value from a serialized array of Records.
|
|
1493
|
+
* @param {Record[]} serialized a previously serialized value.
|
|
1494
|
+
* @returns {any}
|
|
1495
|
+
*/
|
|
1496
|
+
const deserialize = serialized => deserializer(new Map, serialized)(0);
|
|
1497
|
+
|
|
1498
|
+
const EMPTY = '';
|
|
1499
|
+
|
|
1500
|
+
const {toString} = {};
|
|
1501
|
+
const {keys} = Object;
|
|
1502
|
+
|
|
1503
|
+
const typeOf = value => {
|
|
1504
|
+
const type = typeof value;
|
|
1505
|
+
if (type !== 'object' || !value)
|
|
1506
|
+
return [PRIMITIVE, type];
|
|
1507
|
+
|
|
1508
|
+
const asString = toString.call(value).slice(8, -1);
|
|
1509
|
+
switch (asString) {
|
|
1510
|
+
case 'Array':
|
|
1511
|
+
return [ARRAY, EMPTY];
|
|
1512
|
+
case 'Object':
|
|
1513
|
+
return [OBJECT, EMPTY];
|
|
1514
|
+
case 'Date':
|
|
1515
|
+
return [DATE, EMPTY];
|
|
1516
|
+
case 'RegExp':
|
|
1517
|
+
return [REGEXP, EMPTY];
|
|
1518
|
+
case 'Map':
|
|
1519
|
+
return [MAP, EMPTY];
|
|
1520
|
+
case 'Set':
|
|
1521
|
+
return [SET, EMPTY];
|
|
1522
|
+
case 'DataView':
|
|
1523
|
+
return [ARRAY, asString];
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
if (asString.includes('Array'))
|
|
1527
|
+
return [ARRAY, asString];
|
|
1528
|
+
|
|
1529
|
+
if (asString.includes('Error'))
|
|
1530
|
+
return [ERROR, asString];
|
|
1531
|
+
|
|
1532
|
+
return [OBJECT, asString];
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
const shouldSkip = ([TYPE, type]) => (
|
|
1536
|
+
TYPE === PRIMITIVE &&
|
|
1537
|
+
(type === 'function' || type === 'symbol')
|
|
1538
|
+
);
|
|
1539
|
+
|
|
1540
|
+
const serializer = (strict, json, $, _) => {
|
|
1541
|
+
|
|
1542
|
+
const as = (out, value) => {
|
|
1543
|
+
const index = _.push(out) - 1;
|
|
1544
|
+
$.set(value, index);
|
|
1545
|
+
return index;
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
const pair = value => {
|
|
1549
|
+
if ($.has(value))
|
|
1550
|
+
return $.get(value);
|
|
1551
|
+
|
|
1552
|
+
let [TYPE, type] = typeOf(value);
|
|
1553
|
+
switch (TYPE) {
|
|
1554
|
+
case PRIMITIVE: {
|
|
1555
|
+
let entry = value;
|
|
1556
|
+
switch (type) {
|
|
1557
|
+
case 'bigint':
|
|
1558
|
+
TYPE = BIGINT;
|
|
1559
|
+
entry = value.toString();
|
|
1560
|
+
break;
|
|
1561
|
+
case 'function':
|
|
1562
|
+
case 'symbol':
|
|
1563
|
+
if (strict)
|
|
1564
|
+
throw new TypeError('unable to serialize ' + type);
|
|
1565
|
+
entry = null;
|
|
1566
|
+
break;
|
|
1567
|
+
case 'undefined':
|
|
1568
|
+
return as([VOID], value);
|
|
1569
|
+
}
|
|
1570
|
+
return as([TYPE, entry], value);
|
|
1571
|
+
}
|
|
1572
|
+
case ARRAY: {
|
|
1573
|
+
if (type) {
|
|
1574
|
+
let spread = value;
|
|
1575
|
+
if (type === 'DataView') {
|
|
1576
|
+
spread = new Uint8Array(value.buffer);
|
|
1577
|
+
}
|
|
1578
|
+
else if (type === 'ArrayBuffer') {
|
|
1579
|
+
spread = new Uint8Array(value);
|
|
1580
|
+
}
|
|
1581
|
+
return as([type, [...spread]], value);
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
const arr = [];
|
|
1585
|
+
const index = as([TYPE, arr], value);
|
|
1586
|
+
for (const entry of value)
|
|
1587
|
+
arr.push(pair(entry));
|
|
1588
|
+
return index;
|
|
1589
|
+
}
|
|
1590
|
+
case OBJECT: {
|
|
1591
|
+
if (type) {
|
|
1592
|
+
switch (type) {
|
|
1593
|
+
case 'BigInt':
|
|
1594
|
+
return as([type, value.toString()], value);
|
|
1595
|
+
case 'Boolean':
|
|
1596
|
+
case 'Number':
|
|
1597
|
+
case 'String':
|
|
1598
|
+
return as([type, value.valueOf()], value);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
if (json && ('toJSON' in value))
|
|
1603
|
+
return pair(value.toJSON());
|
|
1604
|
+
|
|
1605
|
+
const entries = [];
|
|
1606
|
+
const index = as([TYPE, entries], value);
|
|
1607
|
+
for (const key of keys(value)) {
|
|
1608
|
+
if (strict || !shouldSkip(typeOf(value[key])))
|
|
1609
|
+
entries.push([pair(key), pair(value[key])]);
|
|
1610
|
+
}
|
|
1611
|
+
return index;
|
|
1612
|
+
}
|
|
1613
|
+
case DATE:
|
|
1614
|
+
return as([TYPE, value.toISOString()], value);
|
|
1615
|
+
case REGEXP: {
|
|
1616
|
+
const {source, flags} = value;
|
|
1617
|
+
return as([TYPE, {source, flags}], value);
|
|
1618
|
+
}
|
|
1619
|
+
case MAP: {
|
|
1620
|
+
const entries = [];
|
|
1621
|
+
const index = as([TYPE, entries], value);
|
|
1622
|
+
for (const [key, entry] of value) {
|
|
1623
|
+
if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry))))
|
|
1624
|
+
entries.push([pair(key), pair(entry)]);
|
|
1625
|
+
}
|
|
1626
|
+
return index;
|
|
1627
|
+
}
|
|
1628
|
+
case SET: {
|
|
1629
|
+
const entries = [];
|
|
1630
|
+
const index = as([TYPE, entries], value);
|
|
1631
|
+
for (const entry of value) {
|
|
1632
|
+
if (strict || !shouldSkip(typeOf(entry)))
|
|
1633
|
+
entries.push(pair(entry));
|
|
1634
|
+
}
|
|
1635
|
+
return index;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
const {message} = value;
|
|
1640
|
+
return as([TYPE, {name: type, message}], value);
|
|
1641
|
+
};
|
|
1642
|
+
|
|
1643
|
+
return pair;
|
|
1644
|
+
};
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* @typedef {Array<string,any>} Record a type representation
|
|
1648
|
+
*/
|
|
1649
|
+
|
|
1650
|
+
/**
|
|
1651
|
+
* Returns an array of serialized Records.
|
|
1652
|
+
* @param {any} value a serializable value.
|
|
1653
|
+
* @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that,
|
|
1654
|
+
* if `true`, will not throw errors on incompatible types, and behave more
|
|
1655
|
+
* like JSON stringify would behave. Symbol and Function will be discarded.
|
|
1656
|
+
* @returns {Record[]}
|
|
1657
|
+
*/
|
|
1658
|
+
const serialize = (value, {json, lossy} = {}) => {
|
|
1659
|
+
const _ = [];
|
|
1660
|
+
return serializer(!(json || lossy), !!json, new Map, _)(value), _;
|
|
1661
|
+
};
|
|
1662
|
+
|
|
1663
|
+
/**
|
|
1664
|
+
* @typedef {Array<string,any>} Record a type representation
|
|
1665
|
+
*/
|
|
1666
|
+
|
|
1667
|
+
/**
|
|
1668
|
+
* Returns an array of serialized Records.
|
|
1669
|
+
* @param {any} any a serializable value.
|
|
1670
|
+
* @param {{transfer?: any[], json?: boolean, lossy?: boolean}?} options an object with
|
|
1671
|
+
* a transfer option (ignored when polyfilled) and/or non standard fields that
|
|
1672
|
+
* fallback to the polyfill if present.
|
|
1673
|
+
* @returns {Record[]}
|
|
1674
|
+
*/
|
|
1675
|
+
const structuredClone$1 = typeof structuredClone === "function" ?
|
|
1676
|
+
/* c8 ignore start */
|
|
1677
|
+
(any, options) => (
|
|
1678
|
+
options && ('json' in options || 'lossy' in options) ?
|
|
1679
|
+
deserialize(serialize(any, options)) : structuredClone(any)
|
|
1680
|
+
) :
|
|
1681
|
+
(any, options) => deserialize(serialize(any, options));
|
|
1682
|
+
|
|
1683
|
+
function rank2coord(rank) { return Math.floor(Math.log10(rank) / (1/15)) }
|
|
1684
|
+
|
|
1685
|
+
// Augment information already in `me` class with coordinates.
|
|
1686
|
+
function diamond_counts(mixedelements) {
|
|
1687
|
+
|
|
1688
|
+
let maxlog10 = rank_maxlog10(mixedelements); // max of values of me[system]['rank'] in logspace
|
|
1689
|
+
|
|
1690
|
+
if (maxlog10 < 1) {
|
|
1691
|
+
maxlog10 = 1;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
const CELL_LENGTH = 1/15;
|
|
1695
|
+
const Ncells = Math.floor(maxlog10/CELL_LENGTH) + 1;
|
|
1696
|
+
|
|
1697
|
+
// me = mixed elements which is of the form:
|
|
1698
|
+
// [array_from_system_L, array_from_system_R]
|
|
1699
|
+
// where each array is of the form [types:{types}, counts:{counts}, ranks:{ranks}, probs:{probs}, totalunique]
|
|
1700
|
+
// where types is in the order [rank1TypeFromL, rank1TypeFromR, ... rankMaxTypeFromL, rankMaxTypeFromR] and if there is a tie it goes ... ranknTypeFromL, ranknTypeFromR_1, ranknTypeFromR_2, ranknplus1TypeFromL ... Example 1880-2015 charlie and clarence tie from left
|
|
1701
|
+
// counts, ranks, and probs are correct corresponding to the types
|
|
1702
|
+
const x1s = mixedelements[0]['ranks'].map(r => rank2coord(r)); // Math.floor(Math.log10(rank) / (1/15))
|
|
1703
|
+
const y1s = mixedelements[1]['ranks'].map(r => rank2coord(r));
|
|
1704
|
+
|
|
1705
|
+
// all the combination of coords that exists. There are many duplicated coords.
|
|
1706
|
+
const existing_coords = Array.from(mixedelements[0]['ranks'], (d,i) => { return `(${x1s[i]}, ${y1s[i]})` }); // for i in range(len(me[0]['ranks'])), existing_coords.append('x1s[i], y1s[i]'). or alternatively existing_coords = [str(pair) for pair in zip(x1s, y1s)]
|
|
1707
|
+
// note we make this a tring so that indexOf works later. In python we would use a 2-tuple
|
|
1708
|
+
|
|
1709
|
+
// return existing_coords
|
|
1710
|
+
|
|
1711
|
+
const out = [];
|
|
1712
|
+
// iterate through each cell
|
|
1713
|
+
for (var i=0; i < Ncells; i++) { // Ncells is the length of the square matrix (note 1-d length not total number of cells)
|
|
1714
|
+
for (var j=0; j < Ncells; j++) {
|
|
1715
|
+
|
|
1716
|
+
// Does coords (i,j) are in existing_coords?
|
|
1717
|
+
if ( existing_coords.indexOf(`(${i}, ${j})`) === -1) {
|
|
1718
|
+
out.push({ types: "", x1: i, y1: j, rank1: "", rank2: "" }); // if it doesnt exist, thats a blank cell, make the data there blank
|
|
1719
|
+
} else { //if that coordinate is full of data
|
|
1720
|
+
const indices_coords_in_exist_coords = which(rin(existing_coords, `(${i}, ${j})`)); //rin(arr1, arr2) = [foo is in arr2 for foo in arr1]. rin([3, 4, 5], [3]) = [true, false, false], then the which is returning the indices of the elements which are true. So in the end this is getting all the indices where '${i}, ${j})' appears in existing_coords. When there are ties, the same coordinate appears multiple times in a row in exisiting_coords and so indices_coords_in_exist_coords will be an array with multiple indices
|
|
1721
|
+
|
|
1722
|
+
for (let z=0; z < indices_coords_in_exist_coords.length; z++ ) {
|
|
1723
|
+
out.push({
|
|
1724
|
+
types: mixedelements[0]['types'][indices_coords_in_exist_coords[z]],
|
|
1725
|
+
x1: i,
|
|
1726
|
+
y1: j,
|
|
1727
|
+
rank1: mixedelements[0]['ranks'][indices_coords_in_exist_coords[z]],
|
|
1728
|
+
rank2: mixedelements[1]['ranks'][indices_coords_in_exist_coords[z]]
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
// group data by unique coordinates
|
|
1735
|
+
const agg_dat = group(out, d => `${d.x1}, ${d.y1}`);
|
|
1736
|
+
|
|
1737
|
+
return Array.from(agg_dat , ([ key, value ]) => {
|
|
1738
|
+
const x1 = +key.split(", ")[1]; // 2
|
|
1739
|
+
const y1 = +key.split(", ")[0]; // 7
|
|
1740
|
+
return {
|
|
1741
|
+
x1: x1,
|
|
1742
|
+
y1: y1,
|
|
1743
|
+
coord_on_diag: (y1+x1)/2,
|
|
1744
|
+
cos_dist: (x1-y1)**2,
|
|
1745
|
+
rank: value.map(d => d.types)[0] === "" ? "" : value.map(d => `(${d.rank1}, ${d.rank2})`)[0],
|
|
1746
|
+
rank_L: value.map(d => d.types)[0] === "" ? "" : extent$1(value.map(d => d.rank1)),
|
|
1747
|
+
rank_R: value.map(d => d.types)[0] === "" ? "" : extent$1(value.map(d => d.rank2)),
|
|
1748
|
+
value: value.map(d => d.types)[0] === "" ? 0 : value.length,
|
|
1749
|
+
types: value.map(d => d.types).join(', '),
|
|
1750
|
+
which_sys: x1 - y1 <= 0 ? "right" : "left"
|
|
1751
|
+
}
|
|
1752
|
+
})
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
// we expect wordshift to be of the form { divergence_elements: [ length of type ], normalization: float }
|
|
1757
|
+
function diamond_count(mixedelements, wordshift) {
|
|
1758
|
+
|
|
1759
|
+
let deltas = wordshift["divergence_elements"];
|
|
1760
|
+
let sorted_div = matlab_sort(deltas, true);
|
|
1761
|
+
let indices_deltas = sorted_div.orig_idx;
|
|
1762
|
+
|
|
1763
|
+
deltas = indices_deltas.map(e => deltas[e]);
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
mixedelements[0]['types'] = indices_deltas.map(i => mixedelements[0]['types'][i]);
|
|
1767
|
+
mixedelements[0]['counts'] = indices_deltas.map(i => mixedelements[0]['counts'][i]);
|
|
1768
|
+
mixedelements[0]['ranks'] = indices_deltas.map(i => mixedelements[0]['ranks'][i]);
|
|
1769
|
+
mixedelements[0]['probs'] = indices_deltas.map(i => mixedelements[0]['probs'][i]);
|
|
1770
|
+
|
|
1771
|
+
mixedelements[1]['types'] = indices_deltas.map(i => mixedelements[1]['types'][i]);
|
|
1772
|
+
mixedelements[1]['counts'] = indices_deltas.map(i => mixedelements[1]['counts'][i]);
|
|
1773
|
+
mixedelements[1]['ranks'] = indices_deltas.map(i => mixedelements[1]['ranks'][i]);
|
|
1774
|
+
mixedelements[1]['probs'] = indices_deltas.map(i => mixedelements[1]['probs'][i]);
|
|
1775
|
+
|
|
1776
|
+
const deltas_loss = structuredClone$1(deltas);
|
|
1777
|
+
const deltas_gain = structuredClone$1(deltas);
|
|
1778
|
+
|
|
1779
|
+
which(mixedelements[0]['ranks'].map((d,i) => mixedelements[0]['ranks'][i] > mixedelements[1]['ranks'][i])).map(e => deltas_loss[e] = -1);
|
|
1780
|
+
which(mixedelements[0]['ranks'].map((d,i) => mixedelements[1]['ranks'][i] < mixedelements[1]['ranks'][i])).map(e => deltas_gain[e] = -1);
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
const counts = diamond_counts(mixedelements);
|
|
1784
|
+
|
|
1785
|
+
return({'counts': counts, 'deltas': deltas, 'max_delta_loss': Math.max(...deltas_loss)})
|
|
1108
1786
|
}
|
|
1109
1787
|
|
|
1110
|
-
export { Dashboard, Diamond, DivergingBarChart, Legend,
|
|
1788
|
+
export { Dashboard, Diamond, DivergingBarChart, Legend, Wordshift, balanceDat, combElems, diamond_count, matlab_sort, rank_maxlog10, rank_turbulence_divergence, rin, tiedrank, which, wordShift_dat, zeros };
|