@senx/warpview
Version:
WarpView Elements
1,420 lines (1,410 loc) • 947 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Injectable, Component, ViewEncapsulation, ViewChild, Input, Output, Directive, HostListener, NgModule } from '@angular/core';
import * as i4 from '@angular/common';
import { CommonModule } from '@angular/common';
import moment from 'moment-timezone';
import { Subject, BehaviorSubject, forkJoin } from 'rxjs';
import { debounceTime, throttleTime, tap, catchError } from 'rxjs/operators';
import * as Plotlyjs from 'plotly.js-dist';
import { Plots } from 'plotly.js-dist';
import { of } from 'rxjs/internal/observable/of';
import * as i1 from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
import Leaflet from 'leaflet';
import 'leaflet.heat';
import 'leaflet.markercluster';
import deepEqual from 'deep-equal';
import { antPath } from 'leaflet-ant-path';
import moment$1 from 'moment';
import * as noUiSlider from 'nouislider';
import * as i5 from 'angular-resize-event';
import { AngularResizeEventModule } from 'angular-resize-event';
import * as i7 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import fitty from 'fitty';
import * as d3 from 'd3';
import { max, scaleBand, scaleLinear, easeLinear, timeDays, sum, range } from 'd3';
import { select, event } from 'd3-selection';
import eventDrops from 'event-drops';
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class DataModel {
}
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/* tslint:disable:no-console */
class Logger {
constructor(className, isDebug = false) {
this.isDebug = false;
this.className = className.name;
this.isDebug = isDebug;
}
setDebug(debug) {
this.isDebug = debug;
}
log(level, methods, args) {
let logChain = [];
logChain.push(`[${new Date().toISOString()} - [${this.className}] ${methods.join(' - ')}`);
logChain = logChain.concat(args);
switch (level) {
case LEVEL.DEBUG: {
if (this.isDebug) {
console.debug(...logChain);
}
break;
}
case LEVEL.ERROR: {
console.error(...logChain);
break;
}
case LEVEL.INFO: {
console.log(...logChain);
break;
}
case LEVEL.WARN: {
console.warn(...logChain);
break;
}
default: {
if (this.isDebug) {
console.log(...logChain);
}
}
}
}
debug(methods, ...args) {
this.log(LEVEL.DEBUG, methods, args);
}
error(methods, ...args) {
this.log(LEVEL.ERROR, methods, args);
}
warn(methods, ...args) {
this.log(LEVEL.WARN, methods, args);
}
info(methods, ...args) {
this.log(LEVEL.INFO, methods, args);
}
}
var LEVEL;
(function (LEVEL) {
LEVEL[LEVEL["DEBUG"] = 0] = "DEBUG";
LEVEL[LEVEL["ERROR"] = 1] = "ERROR";
LEVEL[LEVEL["WARN"] = 2] = "WARN";
LEVEL[LEVEL["INFO"] = 3] = "INFO";
})(LEVEL || (LEVEL = {}));
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// adapted from Canop's JSON,parseMore https://github.com/Canop/JSON.parseMore/
class JsonLib {
constructor() {
this.escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
};
}
error(m) {
throw {
name: 'SyntaxError',
message: m,
at: this.at,
text: this.text
};
}
next() {
return this.ch = this.text.charAt(this.at++);
}
check(c) {
if (c !== this.ch) {
this.error('Expected \'' + c + '\' instead of \'' + this.ch + '\'');
}
this.ch = this.text.charAt(this.at++);
}
number() {
let string = '';
if (this.ch === '-') {
string = '-';
this.check('-');
}
if (this.ch === 'I') {
this.check('I');
this.check('n');
this.check('f');
this.check('i');
this.check('n');
this.check('i');
this.check('t');
this.check('y');
return -Infinity;
}
while (this.ch >= '0' && this.ch <= '9') {
string += this.ch;
this.next();
}
if (this.ch === '.') {
string += '.';
while (this.next() && this.ch >= '0' && this.ch <= '9') {
string += this.ch;
}
}
if (this.ch === 'e' || this.ch === 'E') {
string += this.ch;
this.next();
if (this.ch === '-' || this.ch === '+') {
string += this.ch;
this.next();
}
while (this.ch >= '0' && this.ch <= '9') {
string += this.ch;
this.next();
}
}
return +string;
}
string() {
let hex;
let string = '';
let uffff;
if (this.ch === '"') {
while (this.next()) {
if (this.ch === '"') {
this.next();
return string;
}
if (this.ch === '\\') {
this.next();
if (this.ch === 'u') {
uffff = 0;
for (let i = 0; i < 4; i++) {
hex = parseInt(this.next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
}
else if (this.escapee[this.ch]) {
string += this.escapee[this.ch];
}
else {
break;
}
}
else {
string += this.ch;
}
}
}
this.error('Bad string');
}
white() {
while (this.ch && this.ch <= ' ') {
this.next();
}
}
word() {
switch (this.ch) {
case 't':
this.check('t');
this.check('r');
this.check('u');
this.check('e');
return true;
case 'f':
this.check('f');
this.check('a');
this.check('l');
this.check('s');
this.check('e');
return false;
case 'n':
this.check('n');
this.check('u');
this.check('l');
this.check('l');
return null;
case 'N':
this.check('N');
this.check('a');
this.check('N');
return NaN;
case 'I':
this.check('I');
this.check('n');
this.check('f');
this.check('i');
this.check('n');
this.check('i');
this.check('t');
this.check('y');
return Infinity;
}
this.error('Unexpected \'' + this.ch + '\'');
}
array() {
const array = [];
if (this.ch === '[') {
this.check('[');
this.white();
if (this.ch === ']') {
this.check(']');
return array; // empty array
}
while (this.ch) {
array.push(this.value());
this.white();
if (this.ch === ']') {
this.check(']');
return array;
}
this.check(',');
this.white();
}
}
this.error('Bad array');
}
object() {
let key;
const object = {};
if (this.ch === '{') {
this.check('{');
this.white();
if (this.ch === '}') {
this.check('}');
return object; // empty object
}
while (this.ch) {
key = this.string();
this.white();
this.check(':');
if (Object.hasOwnProperty.call(object, key)) {
this.error('Duplicate key "' + key + '"');
}
object[key] = this.value();
this.white();
if (this.ch === '}') {
this.check('}');
return object;
}
this.check(',');
this.white();
}
}
this.error('Bad object');
}
value() {
this.white();
switch (this.ch) {
case '{':
return this.object();
case '[':
return this.array();
case '"':
return this.string();
case '-':
return this.number();
default:
return this.ch >= '0' && this.ch <= '9' ? this.number() : this.word();
}
}
parse(source, reviver) {
let result;
this.text = source;
this.at = 0;
this.ch = ' ';
result = this.value();
this.white();
if (this.ch) {
this.error('Syntax error');
}
return typeof reviver === 'function'
? (function walk(holder, key) {
let k;
let v;
const value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
}
else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}({ '': result }, ''))
: result;
}
}
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// @dynamic
class GTSLib {
static cleanArray(actual) {
return actual.filter((i) => !!i);
}
static unique(arr) {
const u = {};
const a = [];
for (let i = 0, l = arr.length; i < l; ++i) {
if (!u.hasOwnProperty(arr[i])) {
a.push(arr[i]);
u[arr[i]] = 1;
}
}
return a;
}
static isArray(value) {
return value && typeof value === 'object' && value instanceof Array && typeof value.length === 'number'
&& typeof value.splice === 'function' && !(value.propertyIsEnumerable('length'));
}
static formatElapsedTime(elapsed) {
if (elapsed < 1000) {
return elapsed.toFixed(3) + ' ns';
}
if (elapsed < 1000000) {
return (elapsed / 1000).toFixed(3) + ' μs';
}
if (elapsed < 1000000000) {
return (elapsed / 1000000).toFixed(3) + ' ms';
}
if (elapsed < 1000000000000) {
return (elapsed / 1000000000).toFixed(3) + ' s ';
}
// Max exec time for nice output: 999.999 minutes (should be OK, timeout should happen before that).
return (elapsed / 60000000000).toFixed(3) + ' m ';
}
static isValidResponse(data) {
let response;
try {
response = new JsonLib().parse(data);
}
catch (e) {
this.LOG.error(['isValidResponse'], 'Response non JSON compliant', data);
return false;
}
if (!GTSLib.isArray(response)) {
this.LOG.error(['isValidResponse'], 'Response isn\'t an Array', response);
return false;
}
return true;
}
static isEmbeddedImage(item) {
return !(typeof item !== 'string' || !/^data:image/.test(item));
}
static isEmbeddedImageObject(item) {
return !((item === null) || (item.image === null) ||
(item.caption === null) || !GTSLib.isEmbeddedImage(item.image));
}
static isPositionArray(item) {
if (!item || !item.positions) {
return false;
}
if (GTSLib.isPositionsArrayWithValues(item) || GTSLib.isPositionsArrayWithTwoValues(item)) {
return true;
}
(item.positions || []).forEach(p => {
if (p.length < 2 || p.length > 3) {
return false;
}
for (const j in p) {
if (typeof p[j] !== 'number') {
return false;
}
}
});
return true;
}
static isPositionsArrayWithValues(item) {
if ((item === null) || (item.positions === null)) {
return false;
}
(item.positions || []).forEach(p => {
if (p.length !== 3) {
return false;
}
for (const j in p) {
if (typeof p[j] !== 'number') {
return false;
}
}
});
return true;
}
static isPositionsArrayWithTwoValues(item) {
if ((item === null) || (item.positions === null)) {
return false;
}
(item.positions || []).forEach(p => {
if (p.length !== 4) {
return false;
}
for (const j in p) {
if (typeof p[j] !== 'number') {
return false;
}
}
});
return true;
}
static gtsFromJSON(json, id) {
return { gts: { c: json.c, l: json.l, a: json.a, v: json.v, id } };
}
static uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
// tslint:disable-next-line:no-bitwise
const r = Math.random() * 16 | 0;
// tslint:disable-next-line:no-bitwise
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
static gtsFromJSONList(jsonList, prefixId) {
const gtsList = [];
let id;
(jsonList || []).forEach((item, i) => {
let gts = item;
if (item.gts) {
gts = item.gts;
}
if ((prefixId !== undefined) && (prefixId !== '')) {
id = prefixId + '-' + i;
}
else {
id = i;
}
if (GTSLib.isArray(gts)) {
gtsList.push(GTSLib.gtsFromJSONList(gts, id));
}
if (GTSLib.isGts(gts)) {
gtsList.push(GTSLib.gtsFromJSON(gts, id));
}
if (GTSLib.isEmbeddedImage(gts)) {
gtsList.push({ image: gts, caption: 'Image', id });
}
if (GTSLib.isEmbeddedImageObject(gts)) {
gtsList.push({ image: gts.image, caption: gts.caption, id });
}
});
return {
content: gtsList || [],
};
}
static flatDeep(arrays) {
const result = [];
if (!GTSLib.isArray(arrays)) {
arrays = [arrays];
}
GTSLib.flatten(arrays, result);
return result;
}
static flatten(arr, result = []) {
const size = arr.length;
for (let i = 0; i < size; i++) {
const value = arr[i];
if (Array.isArray(value)) {
GTSLib.flatten(value, result);
}
else {
result.push(value);
}
}
return result;
}
static flattenGtsIdArray(a, r) {
const res = [];
if (GTSLib.isGts(a)) {
a = [a];
}
(a || []).forEach(d => {
if (GTSLib.isArray(d)) {
const walk = GTSLib.flattenGtsIdArray(d, r);
res.push(walk.res);
r = walk.r;
}
else if (d && d.v) {
d.id = r;
res.push(d);
r++;
}
});
return { res, r };
}
static sanitizeNames(input) {
return (input || '').replace(/{/g, '{')
.replace(/}/g, '}')
.replace(/,/g, ',')
.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
static serializeGtsMetadata(gts) {
const serializedLabels = [];
const serializedAttributes = [];
if (gts.l) {
Object.keys(gts.l).forEach((key) => {
serializedLabels.push(this.sanitizeNames(key + '=' + gts.l[key]));
});
}
if (gts.a) {
Object.keys(gts.a).forEach((key) => {
serializedAttributes.push(this.sanitizeNames(key + '=' + gts.a[key]));
});
}
// tslint:disable-next-line:max-line-length
return `${this.sanitizeNames(gts.c)}{${serializedLabels.join(',')}${serializedAttributes.length > 0 ? ',' : ''}${serializedAttributes.join(',')}}`;
}
static isGts(item) {
return !!item && (item.c === '' || !!item.c) && !!item.v && GTSLib.isArray(item.v);
}
static isGtsToPlot(gts) {
if (!GTSLib.isGts(gts) || gts.v.length === 0) {
return false;
}
// We look at the first non-null value, if it's a String or Boolean it's an annotation GTS,
// if it's a number it's a GTS to plot
return (gts.v || []).some(v => {
// noinspection JSPotentiallyInvalidConstructorUsage
return typeof v[v.length - 1] === 'number' || !!v[v.length - 1].constructor.prototype.toFixed;
});
}
static isGtsToPlotOnMap(gts) {
if (!GTSLib.isGts(gts) || gts.v.length === 0) {
return false;
}
// We look at the first non-null value, if it's a String or Boolean it's an annotation GTS,
// if it's a number it's a GTS to plot
return (gts.v || []).some(v => {
return v.length >= 3;
});
}
static isSingletonGTS(gts) {
if (!GTSLib.isGts(gts) || gts.v.length === 0) {
return false;
}
return (gts.v || []).length === 1;
}
static isGtsToAnnotate(gts) {
if (!GTSLib.isGts(gts) || gts.v.length === 0) {
return false;
}
// We look at the first non-null value, if it's a String or Boolean it's an annotation GTS,
// if it's a number it's a GTS to plot
return (gts.v || []).some(v => {
if (v[v.length - 1] !== null) {
// noinspection JSPotentiallyInvalidConstructorUsage
return typeof (v[v.length - 1]) !== 'number' &&
(!!v[v.length - 1].constructor && v[v.length - 1].constructor.name !== 'Big') &&
v[v.length - 1].constructor.prototype.toFixed === undefined;
}
});
}
static gtsSort(gts) {
if (gts.isSorted) {
return;
}
gts.v = gts.v.sort((a, b) => a[0] - b[0]);
gts.isSorted = true;
}
static getData(data) {
if (typeof data === 'string') {
if (data.startsWith('[') || data.startsWith('{')) {
return GTSLib.getData(new JsonLib().parse(data));
}
else {
return { data: new JsonLib().parse(`[${data}]`) };
}
}
else if (data && data.hasOwnProperty('data')) {
if (!GTSLib.isArray(data.data)) {
data.data = [data.data];
}
return data;
}
else if (GTSLib.isArray(data) && data.length > 0 && data[0].data) {
return data[0];
}
else if (GTSLib.isArray(data)) {
return { data: data };
}
return new DataModel();
}
static getDivider(timeUnit) {
let timestampDivider = 1000; // default for µs timeunit
if (timeUnit === 'ms') {
timestampDivider = 1;
}
if (timeUnit === 'ns') {
timestampDivider = 1000000;
}
return timestampDivider;
}
static formatLabel(data) {
const serializedGTS = data.split('{');
let display = `<span class="gtsInfo"><span class='gts-classname'>${serializedGTS[0]}</span>`;
if (serializedGTS.length > 1) {
display += `<span class='gts-separator'>{</span>`;
const labels = serializedGTS[1].substr(0, serializedGTS[1].length - 1).split(',');
if (labels.length > 0) {
labels.forEach((l, i) => {
const label = l.split('=');
if (l.length > 1) {
display += `<span><span class='gts-labelname'>${label[0]}</span>
<span class='gts-separator'>=</span><span class='gts-labelvalue'>${label[1]}</span>`;
if (i !== labels.length - 1) {
display += `<span>, </span>`;
}
}
});
}
display += `<span class='gts-separator'>}</span>`;
}
if (serializedGTS.length > 2) {
display += `<span class='gts-separator'>{</span>`;
const labels = serializedGTS[2].substr(0, serializedGTS[2].length - 1).split(',');
if (labels.length > 0) {
labels.forEach((l, i) => {
const label = l.split('=');
if (l.length > 1) {
display += `<span><span class='gts-attrname'>${label[0]}</span>
<span class='gts-separator'>=</span><span class='gts-attrvalue'>${label[1]}</span>`;
if (i !== labels.length - 1) {
display += `<span>, </span>`;
}
}
});
}
display += `<span class='gts-separator'>}</span>`;
}
display += '</span>';
return display;
}
static toISOString(timestamp, divider, timeZone) {
if (timeZone !== 'UTC') {
return moment.tz(timestamp / divider, timeZone).format();
}
else {
return moment.utc(timestamp / divider).toISOString();
}
}
static toTimestamp(date, divider, timeZone) {
if (timeZone !== 'UTC') {
return moment.tz(date, timeZone).utc().valueOf() * divider;
}
else {
return moment.utc(date).valueOf() * divider;
}
}
}
GTSLib.LOG = new Logger(GTSLib);
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class ChartBounds {
constructor() {
this.tsmin = 0;
this.tsmax = 0;
this.msmin = '';
this.msmax = '';
this.marginLeft = 0;
}
}
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var Colors;
(function (Colors) {
Colors["COHESIVE"] = "COHESIVE";
Colors["COHESIVE_2"] = "COHESIVE_2";
Colors["BELIZE"] = "BELIZE";
Colors["VIRIDIS"] = "VIRIDIS";
Colors["MAGMA"] = "MAGMA";
Colors["INFERNO"] = "INFERNO";
Colors["PLASMA"] = "PLASMA";
Colors["YL_OR_RD"] = "YL_OR_RD";
Colors["YL_GN_BU"] = "YL_GN_BU";
Colors["BU_GN"] = "BU_GN";
Colors["WARP10"] = "WARP10";
Colors["NINETEEN_EIGHTY_FOUR"] = "NINETEEN_EIGHTY_FOUR";
Colors["ATLANTIS"] = "ATLANTIS";
Colors["DO_ANDROIDS_DREAM"] = "DO_ANDROIDS_DREAM";
Colors["DELOREAN"] = "DELOREAN";
Colors["CTHULHU"] = "CTHULHU";
Colors["ECTOPLASM"] = "ECTOPLASM";
Colors["T_MAX_400_FILM"] = "T_MAX_400_FILM";
})(Colors || (Colors = {}));
class ColorLib {
static getColor(i, scheme) {
if (!ColorLib.color[scheme]) {
scheme = 'WARP10';
}
return ColorLib.color[scheme][i % 2 === 0
? i % ColorLib.color[scheme].length
: ColorLib.color[scheme].length - i % ColorLib.color[scheme].length];
}
static getColorGradient(id, scheme) {
return [
[0, ColorLib.transparentize(ColorLib.getColor(id, scheme), 0)],
[1, ColorLib.transparentize(ColorLib.getColor(id, scheme), 0.7)]
];
}
static getBlendedColorGradient(id, scheme, bg = '#000000') {
return [
[0, ColorLib.blend_colors(bg, ColorLib.getColor(id, scheme), 0)],
[1, ColorLib.blend_colors(bg, ColorLib.getColor(id, scheme), 1)]
];
}
static hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
] : null;
}
static transparentize(color, alpha = 0.5) {
return 'rgba(' + ColorLib.hexToRgb(color).concat(alpha).join(',') + ')';
}
static generateTransparentColors(num, scheme) {
const color = [];
for (let i = 0; i < num; i++) {
color.push(ColorLib.transparentize(ColorLib.getColor(i, scheme)));
}
return color;
}
static hsvGradientFromRgbColors(c1, c2, steps) {
const c1hsv = ColorLib.rgb2hsv(c1.r, c1.g, c1.b);
const c2hsv = ColorLib.rgb2hsv(c2.r, c2.g, c2.b);
c1.h = c1hsv[0];
c1.s = c1hsv[1];
c1.v = c1hsv[2];
c2.h = c2hsv[0];
c2.s = c2hsv[1];
c2.v = c2hsv[2];
const gradient = ColorLib.hsvGradient(c1, c2, steps);
for (const i in gradient) {
if (gradient[i]) {
gradient[i].rgb = ColorLib.hsv2rgb(gradient[i].h, gradient[i].s, gradient[i].v);
gradient[i].r = Math.floor(gradient[i].rgb[0]);
gradient[i].g = Math.floor(gradient[i].rgb[1]);
gradient[i].b = Math.floor(gradient[i].rgb[2]);
}
}
return gradient;
}
static rgb2hsv(r, g, b) {
// Normalize
const normR = r / 255.0;
const normG = g / 255.0;
const normB = b / 255.0;
const M = Math.max(normR, normG, normB);
const m = Math.min(normR, normG, normB);
const d = M - m;
let h;
let s;
let v;
v = M;
if (d === 0) {
h = 0;
s = 0;
}
else {
s = d / v;
switch (M) {
case normR:
h = ((normG - normB) + d * (normG < normB ? 6 : 0)) / 6 * d;
break;
case normG:
h = ((normB - normR) + d * 2) / 6 * d;
break;
case normB:
h = ((normR - normG) + d * 4) / 6 * d;
break;
}
}
return [h, s, v];
}
static hsvGradient(c1, c2, steps) {
const gradient = new Array(steps);
// determine clockwise and counter-clockwise distance between hues
const distCCW = (c1.h >= c2.h) ? c1.h - c2.h : 1 + c1.h - c2.h;
const distCW = (c1.h >= c2.h) ? 1 + c2.h - c1.h : c2.h - c1.h;
// make gradient for this part
for (let i = 0; i < steps; i++) {
// interpolate h, s, b
let h = (distCW <= distCCW) ? c1.h + (distCW * i / (steps - 1)) : c1.h - (distCCW * i / (steps - 1));
if (h < 0) {
h = 1 + h;
}
if (h > 1) {
h = h - 1;
}
const s = (1 - i / (steps - 1)) * c1.s + i / (steps - 1) * c2.s;
const v = (1 - i / (steps - 1)) * c1.v + i / (steps - 1) * c2.v;
// add to gradient array
gradient[i] = { h, s, v };
}
return gradient;
}
static hsv2rgb(h, s, v) {
let r;
let g;
let b;
const i = Math.floor(h * 6);
const f = h * 6 - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return [r * 255, g * 255, b * 255];
}
static rgb2hex(r, g, b) {
function componentToHex(c) {
const hex = c.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}
return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
static blend_colors(color1, color2, percentage) {
// check input
color1 = color1 || '#000000';
color2 = color2 || '#ffffff';
percentage = percentage || 0.5;
// 1: validate input, make sure we have provided a valid hex
if (color1.length !== 4 && color1.length !== 7) {
throw new Error('colors must be provided as hexes');
}
if (color2.length !== 4 && color2.length !== 7) {
throw new Error('colors must be provided as hexes');
}
if (percentage > 1 || percentage < 0) {
throw new Error('percentage must be between 0 and 1');
}
// 2: check to see if we need to convert 3 char hex to 6 char hex, else slice off hash
// the three character hex is just a representation of the 6 hex where each character is repeated
// ie: #060 => #006600 (green)
if (color1.length === 4) {
color1 = color1[1] + color1[1] + color1[2] + color1[2] + color1[3] + color1[3];
}
else {
color1 = color1.substring(1);
}
if (color2.length === 4) {
color2 = color2[1] + color2[1] + color2[2] + color2[2] + color2[3] + color2[3];
}
else {
color2 = color2.substring(1);
}
// 3: we have valid input, convert colors to rgb
color1 = [parseInt(color1[0] + color1[1], 16), parseInt(color1[2] + color1[3], 16), parseInt(color1[4] + color1[5], 16)];
color2 = [parseInt(color2[0] + color2[1], 16), parseInt(color2[2] + color2[3], 16), parseInt(color2[4] + color2[5], 16)];
// 4: blend
const color3 = [
(1 - percentage) * color1[0] + percentage * color2[0],
(1 - percentage) * color1[1] + percentage * color2[1],
(1 - percentage) * color1[2] + percentage * color2[2]
];
// return hex
return '#' + ColorLib.int_to_hex(color3[0]) + ColorLib.int_to_hex(color3[1]) + ColorLib.int_to_hex(color3[2]);
}
/*
convert a Number to a two character hex string
must round, or we will end up with more digits than expected (2)
note: can also result in single digit, which will need to be padded with a 0 to the left
@param: num => the number to conver to hex
@returns: string => the hex representation of the provided number
*/
static int_to_hex(num) {
let hex = Math.round(num).toString(16);
if (hex.length === 1) {
hex = '0' + hex;
}
return hex;
}
}
ColorLib.color = {
COHESIVE: ['#F2D354', '#E4612F', '#D32C2E', '#6D2627', '#6C7F55', '#934FC6', '#F07A5D', '#ED8371', '#94E751',
'#C457F7', '#973AF7', '#B6FF7A', '#C7FFD5', '#90E4D0', '#E09234', '#D2FF91', '#17B201'],
COHESIVE_2: ['#6F694E', '#65D0B2', '#D8F546', '#FF724B', '#D6523E', '#F9F470', '#F4BC78', '#B1D637', '#FFCFC8',
'#56CDAB', '#CFDD22', '#B3F5D2', '#97DB29', '#9DC5EE', '#CFC0F5', '#EDEA29', '#5EC027', '#386C94'],
BELIZE: ['#5899DA', '#E8743B', '#19A979', '#ED4A7B', '#945ECF', '#13A4B4', '#525DF4', '#BF399E', '#6C8893',
'#EE6868', '#2F6497'],
VIRIDIS: ['#440154', '#481f70', '#443983', '#3b528b', '#31688e', '#287c8e', '#21918c', '#20a486', '#35b779',
'#5ec962', '#90d743', '#c8e020'],
MAGMA: ['#000004', '#100b2d', '#2c115f', '#51127c', '#721f81', '#932b80', '#b73779', '#d8456c', '#f1605d',
'#fc8961', '#feb078', '#fed799'],
INFERNO: ['#000004', '#110a30', '#320a5e', '#57106e', '#781c6d', '#9a2865', '#bc3754', '#d84c3e', '#ed6925',
'#f98e09', '#fbb61a', '#f4df53'],
PLASMA: ['#0d0887', '#3a049a', '#5c01a6', '#7e03a8', '#9c179e', '#b52f8c', '#cc4778', '#de5f65', '#ed7953',
'#f89540', '#fdb42f', '#fbd524'],
YL_OR_RD: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],
YL_GN_BU: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'],
BU_GN: ['#f7fcfd', '#ebf7fa', '#dcf2f2', '#c8eae4', '#aadfd2', '#88d1bc', '#68c2a3', '#4eb485', '#37a266',
'#228c49', '#0d7635', '#025f27'],
WARP10: [
'#ff9900', '#E53935', '#F4511E', '#D81B60',
'#00ACC1', '#1E88E5', '#43A047', '#FFB300',
'#6D4C41', '#FDD835', '#00897B', '#3949AB',
'#5E35B1', '#8E24AA', '#C0CA33', '#039BE5',
'#7CB342', '#004eff'
],
NINETEEN_EIGHTY_FOUR: ['#fc9ca2', '#fb747d', '#fa4c58', '#f92432', '#e30613', '#c70512', '#9f040e', '#77030b', '#500207'],
ATLANTIS: ['#edf2fb', '#e2eafc', '#d7e3fc', '#ccdbfd', '#c1d3fe', '#b6ccfe', '#abc4ff'],
DO_ANDROIDS_DREAM: ['#d8f3dc', '#b7e4c7', '#95d5b2', '#74c69d', '#52b788', '#40916c', '#2d6a4f', '#1b4332',
'#081c15'],
DELOREAN: ['#b98b73', '#cb997e', '#ddbea9', '#ffe8d6', '#d4c7b0', '#b7b7a4', '#a5a58d', '#6b705c', '#3f4238'],
CTHULHU: ['#004c6d', '#006083', '#007599', '#008bad', '#00a1c1', '#00b8d3', '#00cfe3', '#00e7f2', '#00ffff'],
ECTOPLASM: ['#006466', '#065a60', '#0b525b', '#144552', '#1b3a4b', '#212f45', '#272640', '#312244', '#3e1f47', '#4d194d'],
T_MAX_400_FILM: ['#f8f9fa', '#e9ecef', '#dee2e6', '#ced4da', '#adb5bd', '#6c757d', '#495057', '#343a40', '#212529'],
MATRIX: ['#025f27', '#025f27', '#0d7635', '#228c49', '#37a266', '#4eb485', '#68c2a3', '#88d1bc'],
CHARTANA: ['#77BE69', '#FADE2B', '#F24865', '#5694F2',
'#FF9830', '#B876D9'],
};
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// @dynamic
class ChartLib {
static mergeDeep(base, ext) {
const obj = { ...base };
const extended = { ...ext };
for (const prop in extended || {}) {
// If property is an object, merge properties
if (Object.prototype.toString.call(extended[prop]) === '[object Object]') {
obj[prop] = ChartLib.mergeDeep(obj[prop], extended[prop]);
}
else {
obj[prop] = extended[prop];
}
}
return obj;
}
static fraction2r(rl0, rl1, v) {
return v * (rl1 - rl0);
}
}
ChartLib.DEFAULT_WIDTH = 640;
ChartLib.DEFAULT_HEIGHT = 480;
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class Param {
constructor() {
this.scheme = 'WARP10';
this.showlegend = false;
this.horizontal = false;
this.stacked = false;
this.showControls = true;
this.showErrors = true;
this.showStatus = false;
this.expandAnnotation = false;
this.showDots = false;
this.timeUnit = 'us';
this.timeZone = 'UTC';
this.map = {
tiles: [],
showTimeSlider: false,
showTimeRange: false,
timeSliderMode: 'timestamp'
};
this.bounds = {};
}
}
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class Size {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
class SizeService {
constructor() {
this.debouncer = new Subject();
this.sizeChanged$ = new EventEmitter();
this.debouncer
.pipe(debounceTime(100))
.subscribe((value) => this.sizeChanged$.emit(value));
}
change(size) {
this.debouncer.next(size);
}
}
SizeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: SizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
SizeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: SizeService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: SizeService, decorators: [{
type: Injectable
}], ctorParameters: function () { return []; } });
/*
* Copyright 2021 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class PlotlyComponent {
constructor(iterableDiffers, el, keyValueDiffers) {
this.iterableDiffers = iterableDiffers;
this.el = el;
this.keyValueDiffers = keyValueDiffers;
this.defaultClassName = 'js-plotly-plot';
this._debug = false;
this.revision = 0;
this.useResizeHandler = false;
this.updateOnLayoutChange = true;
this.updateOnDataChange = true;
this.updateOnlyWithRevision = true;
this.initialized = new EventEmitter();
this.update = new EventEmitter();
this.purge = new EventEmitter();
// tslint:disable-next-line:no-output-native
this.error = new EventEmitter();
this.afterExport = new EventEmitter();
this.afterPlot = new EventEmitter();
this.animated = new EventEmitter();
this.animatingFrame = new EventEmitter();
this.animationInterrupted = new EventEmitter();
this.autoSize = new EventEmitter();
this.beforeExport = new EventEmitter();
this.buttonClicked = new EventEmitter();
// tslint:disable-next-line:no-output-native
this.click = new EventEmitter();
this.plotly_click = new EventEmitter();
this.clickAnnotation = new EventEmitter();
this.deselect = new EventEmitter();
this.doubleClick = new EventEmitter();
this.framework = new EventEmitter();
this.hover = new EventEmitter();
this.legendClick = new EventEmitter();
this.legendDoubleClick = new EventEmitter();
this.relayout = new EventEmitter();
this.restyle = new EventEmitter();
this.redraw = new EventEmitter();
this.selected = new EventEmitter();
this.selecting = new EventEmitter();
this.sliderChange = new EventEmitter();
this.sliderEnd = new EventEmitter();
this.sliderStart = new EventEmitter();
this.transitioning = new EventEmitter();
this.transitionInterrupted = new EventEmitter();
this.unhover = new EventEmitter();
this.relayouting = new EventEmitter();
this.eventNames = [
// 'afterExport',
// 'afterPlot', // 'animated', 'animatingFrame', 'animationInterrupted', 'autoSize',
// 'beforeExport', 'buttonClicked', 'clickAnnotation', 'deselect', 'doubleClick', 'framework',
'hover', 'unhover',
// 'legendClick', 'legendDoubleClick',
'relayout',
// 'restyle', 'redraw', 'selected', 'selecting', 'sliderChange',
// 'sliderEnd', 'sliderStart', 'transitioning', 'transitionInterrupted', 'relayouting'
];
this.LOG = new Logger(PlotlyComponent, this._debug);
}
set data(data) {
this._data = data;
this.LOG.debug(['PlotlyComponent'], data);
this.updatePlot();
this.LOG.debug(['PlotlyComponent'], 'after updatePlot');
this.updateWindowResizeHandler();
this.LOG.debug(['PlotlyComponent'], 'after updateWindowResizeHandler');
}
get data() {
return this._data;
}
set layout(layout) {
this._layout = { ...layout };
if (!!this._data && !!this.plotEl.nativeElement) {
try {
Plotlyjs.relayout(this.plotEl.nativeElement, this._layout);
this.updateWindowResizeHandler();
}
catch (e) {
//
}
}
}
get layout() {
return this._layout;
}
set config(config) {
this._config = config;
this.updatePlot();
this.updateWindowResizeHandler();
}
get config() {
return this._config;
}
set debug(debug) {
if (typeof debug === 'string') {
debug = 'true' === debug;
}
this._debug = debug;
this.LOG.setDebug(debug);
}
get debug() {
return this._debug;
}
ngOnInit() {
this.createPlot().then(() => {
const figure = this.createFigure();
this.LOG.debug(['figure'], figure);
this.initialized.emit(this.plotlyInstance);
});
}
ngOnDestroy() {
if (typeof this.resizeHandler === 'function') {
this.getWindow().removeEventListener('resize', this.resizeHandler);
this.resizeHandler = undefined;
}
const figure = this.createFigure();
this.purge.emit(figure);
this.remove(this.plotlyInstance);
}
ngDoCheck() {
if (this.updateOnlyWithRevision) {
return false;
}
let shouldUpdate = false;
if (this.updateOnLayoutChange) {
if (this.layoutDiffer) {
const layoutHasDiff = this.layoutDiffer.diff(this._layout);
if (layoutHasDiff) {
shouldUpdate = true;
}
}
else if (this._layout) {
this.layoutDiffer = this.keyValueDiffers.find(this._layout).create();
}
else {
this.layoutDiffer = undefined;
}
}
if (this.updateOnDataChange) {
if (this.dataDiffer) {
const dataHasDiff = this.dataDiffer.diff(this._data);
if (dataHasDiff) {
shouldUpdate = true;
}
}
else if (Array.isArray(this._data)) {
this.dataDiffer = this.iterableDiffers.find(this._data).create(this.dataDifferTrackBy);
}
else {
this.dataDiffer = undefined;
}
}
if (shouldUpdate && this.plotlyInstance) {
this.updatePlot();
}
}
getWindow() {
return window;
}
getBoundingClientRect() {
return this.rect;
}
getClassName() {
let classes = [this.defaultClassName];
if (Array.isArray(this.className)) {
classes = classes.concat(this.className);
}
else if (!!this.className) {
classes.push(this.className);
}
return classes.join(' ');
}
restyleChart(properties, curves) {
Plotlyjs.restyle(this.plotlyInstance, properties, curves);
}
createPlot() {
this.LOG.debug(['createPlot']);
return Plotlyjs.react(this.plotEl.nativeElement, this._data, this._layout, this._config)
.then(plotlyInstance => {
this.LOG.debug(['plotlyInstance'], plotlyInstance);
this.rect = this.el.nativeElement.getBoundingClientRect();
this.plotlyInstance = plotlyInstance;
this.getWindow().gd = this._debug ? plotlyInstance : undefined;
this.eventNames.forEach(name => {
const eventName = `plotly_${name.toLowerCase()}`;
// @ts-ignore
plotlyInstance.on(eventName, (data) => {
this.LOG.debug(['plotlyEvent', eventName], data);
this[name].emit(data);
});
});
plotlyInstance.on('plotly_click', (data) => {
this.