@deephaven/chart 0.43.0 → 0.44.0

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.
@@ -0,0 +1,571 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
3
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
6
+ /* eslint class-methods-use-this: "off" */
7
+ import memoize from 'memoizee';
8
+ import debounce from 'lodash.debounce';
9
+ import set from 'lodash.set';
10
+ import Log from '@deephaven/log';
11
+ import ChartModel from "./ChartModel.js";
12
+ import ChartUtils from "./ChartUtils.js";
13
+ import ChartTheme from "./ChartTheme.js";
14
+ var log = Log.module('FigureChartModel');
15
+
16
+ /**
17
+ * Takes a Figure object from a widget to make a model for a chart
18
+ */
19
+ class FigureChartModel extends ChartModel {
20
+ /**
21
+ * @param dh JSAPI instance
22
+ * @param figure The figure object created by the API
23
+ * @param settings Chart settings
24
+ */
25
+ constructor(dh, figure) {
26
+ var _this;
27
+ var settings = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
28
+ var theme = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ChartTheme;
29
+ super(dh);
30
+ _this = this;
31
+ _defineProperty(this, "chartUtils", void 0);
32
+ _defineProperty(this, "dh", void 0);
33
+ _defineProperty(this, "figure", void 0);
34
+ _defineProperty(this, "settings", void 0);
35
+ _defineProperty(this, "theme", void 0);
36
+ _defineProperty(this, "data", void 0);
37
+ _defineProperty(this, "layout", void 0);
38
+ _defineProperty(this, "seriesDataMap", void 0);
39
+ _defineProperty(this, "pendingSeries", void 0);
40
+ _defineProperty(this, "oneClicks", void 0);
41
+ _defineProperty(this, "filterColumnMap", void 0);
42
+ _defineProperty(this, "lastFilter", void 0);
43
+ _defineProperty(this, "isConnected", void 0);
44
+ _defineProperty(this, "seriesToProcess", void 0);
45
+ _defineProperty(this, "addPendingSeries", debounce(() => {
46
+ var axes = ChartUtils.getAllAxes(this.figure);
47
+ var {
48
+ pendingSeries
49
+ } = this;
50
+ var _loop = function _loop() {
51
+ var _chart$showLegend;
52
+ var series = pendingSeries[i];
53
+ var chart = _this.figure.charts.find(c => c.series.includes(series));
54
+ _this.addSeries(series, axes, (_chart$showLegend = chart === null || chart === void 0 ? void 0 : chart.showLegend) !== null && _chart$showLegend !== void 0 ? _chart$showLegend : null);
55
+ series.subscribe();
56
+ // We'll get an update with the data after subscribing
57
+ };
58
+ for (var i = 0; i < pendingSeries.length; i += 1) {
59
+ _loop();
60
+ }
61
+ this.pendingSeries = [];
62
+ }, FigureChartModel.ADD_SERIES_DEBOUNCE));
63
+ _defineProperty(this, "getTimeZone", memoize((columnType, formatter) => {
64
+ if (formatter != null) {
65
+ var dataFormatter = formatter.getColumnTypeFormatter(columnType);
66
+ if (dataFormatter != null) {
67
+ return dataFormatter.dhTimeZone;
68
+ }
69
+ }
70
+ return undefined;
71
+ }));
72
+ _defineProperty(this, "getValueTranslator", memoize((columnType, formatter) => {
73
+ var timeZone = this.getTimeZone(columnType, formatter);
74
+ return value => this.chartUtils.unwrapValue(value, timeZone);
75
+ }));
76
+ _defineProperty(this, "getValueParser", memoize((columnType, formatter) => {
77
+ var timeZone = this.getTimeZone(columnType, formatter);
78
+ return value => this.chartUtils.wrapValue(value, columnType, timeZone);
79
+ }));
80
+ _defineProperty(this, "getRangeParser", memoize((columnType, formatter) => range => {
81
+ var [rangeStart, rangeEnd] = range;
82
+ var valueParser = this.getValueParser(columnType, formatter);
83
+ rangeStart = valueParser(rangeStart);
84
+ rangeEnd = valueParser(rangeEnd);
85
+ return [rangeStart, rangeEnd];
86
+ }));
87
+ _defineProperty(this, "getAxisRangeParser", memoize((chart, formatter) => axis => {
88
+ var source = ChartUtils.getSourceForAxis(chart, axis);
89
+ if (source != null) {
90
+ return this.getRangeParser(source.columnType, formatter);
91
+ }
92
+ return range => range;
93
+ }));
94
+ this.handleFigureUpdated = this.handleFigureUpdated.bind(this);
95
+ this.handleFigureDisconnected = this.handleFigureDisconnected.bind(this);
96
+ this.handleFigureReconnected = this.handleFigureReconnected.bind(this);
97
+ this.handleFigureSeriesAdded = this.handleFigureSeriesAdded.bind(this);
98
+ this.handleDownsampleStart = this.handleDownsampleStart.bind(this);
99
+ this.handleDownsampleFinish = this.handleDownsampleFinish.bind(this);
100
+ this.handleDownsampleFail = this.handleDownsampleFail.bind(this);
101
+ this.handleDownsampleNeeded = this.handleDownsampleNeeded.bind(this);
102
+ this.handleRequestFailed = this.handleRequestFailed.bind(this);
103
+ this.dh = dh;
104
+ this.chartUtils = new ChartUtils(dh);
105
+ this.figure = figure;
106
+ this.settings = settings;
107
+ this.theme = theme;
108
+ this.data = [];
109
+ var template = {
110
+ data: {},
111
+ layout: this.chartUtils.makeDefaultLayout(theme)
112
+ };
113
+ this.layout = {
114
+ grid: {
115
+ rows: figure.rows,
116
+ columns: figure.cols,
117
+ pattern: 'independent'
118
+ },
119
+ template
120
+ };
121
+ this.seriesDataMap = new Map();
122
+ this.pendingSeries = [];
123
+ this.oneClicks = [];
124
+ this.filterColumnMap = new Map();
125
+ this.lastFilter = new Map();
126
+ this.isConnected = true; // Assume figure is connected to start
127
+ this.seriesToProcess = new Set();
128
+ this.setTitle(this.getDefaultTitle());
129
+ this.initAllSeries();
130
+ this.updateAxisPositions();
131
+ this.startListeningFigure();
132
+ }
133
+ close() {
134
+ this.figure.close();
135
+ this.addPendingSeries.cancel();
136
+ this.stopListeningFigure();
137
+ }
138
+ getDefaultTitle() {
139
+ if (this.figure.charts.length > 0) {
140
+ var chart = this.figure.charts[0];
141
+ return chart.title;
142
+ }
143
+ return '';
144
+ }
145
+ initAllSeries() {
146
+ this.oneClicks = [];
147
+ this.filterColumnMap.clear();
148
+ var {
149
+ charts
150
+ } = this.figure;
151
+ var axes = ChartUtils.getAllAxes(this.figure);
152
+ var activeSeriesNames = [];
153
+ for (var i = 0; i < charts.length; i += 1) {
154
+ var chart = charts[i];
155
+ for (var j = 0; j < chart.series.length; j += 1) {
156
+ var series = chart.series[j];
157
+ activeSeriesNames.push(series.name);
158
+ this.addSeries(series, axes, chart.showLegend);
159
+ }
160
+ }
161
+
162
+ // Remove any series that no longer exist
163
+ var allSeriesNames = [...this.seriesDataMap.keys()];
164
+ var inactiveSeriesNames = allSeriesNames.filter(seriesName => activeSeriesNames.indexOf(seriesName) < 0);
165
+ for (var _i = 0; _i < inactiveSeriesNames.length; _i += 1) {
166
+ var seriesName = inactiveSeriesNames[_i];
167
+ this.seriesDataMap.delete(seriesName);
168
+ }
169
+ this.seriesToProcess = new Set([...this.seriesDataMap.keys()]);
170
+ }
171
+
172
+ /**
173
+ * Add a series to the model
174
+ * @param series Series object to add
175
+ * @param axes All the axis in this figure
176
+ * @param showLegend Whether this series should show the legend or not
177
+ */
178
+ addSeries(series, axes, showLegend) {
179
+ var {
180
+ dh
181
+ } = this;
182
+ var axisTypeMap = ChartUtils.groupArray(axes, 'type');
183
+ var seriesData = this.chartUtils.makeSeriesDataFromSeries(series, axisTypeMap, ChartUtils.getSeriesVisibility(series.name, this.settings), showLegend, this.theme);
184
+ this.seriesDataMap.set(series.name, seriesData);
185
+ this.data = [...this.seriesDataMap.values()];
186
+ if (series.plotStyle === dh.plot.SeriesPlotStyle.STACKED_BAR) {
187
+ this.layout.barmode = 'stack';
188
+ } else if (series.plotStyle === dh.plot.SeriesPlotStyle.PIE) {
189
+ this.layout.hiddenlabels = ChartUtils.getHiddenLabels(this.settings);
190
+ }
191
+
192
+ // We only want to force hide the legend if there is only one series that is not a PIE
193
+ // Right now this means that if the user only has one series, they cannot explicitly show the legend until deephaven-core#3254 is implemented
194
+ // TODO: deephaven-core#3254, once done, this can be removed.
195
+ this.layout.showlegend = this.data.length > 1 || series.plotStyle === dh.plot.SeriesPlotStyle.PIE ? showLegend !== null && showLegend !== void 0 ? showLegend : undefined : false;
196
+ if (series.oneClick != null) {
197
+ var {
198
+ oneClick
199
+ } = series;
200
+ var {
201
+ columns
202
+ } = oneClick;
203
+ for (var i = 0; i < columns.length; i += 1) {
204
+ this.filterColumnMap.set(columns[i].name, columns[i]);
205
+ }
206
+ this.oneClicks.push(oneClick);
207
+ }
208
+ this.updateLayoutFormats();
209
+ }
210
+
211
+ // We need to debounce adding series so we subscribe to them all in the same tick
212
+ // This should no longer be necessary after IDS-5049 lands
213
+
214
+ subscribe(callback) {
215
+ super.subscribe(callback);
216
+ if (this.listeners.length === 1) {
217
+ // Need to initialize the series here as we may have missed some series when not subscribed
218
+ this.initAllSeries();
219
+ this.subscribeFigure();
220
+ }
221
+ }
222
+ unsubscribe(callback) {
223
+ super.unsubscribe(callback);
224
+ if (this.listeners.length === 0) {
225
+ this.unsubscribeFigure();
226
+ }
227
+ }
228
+ subscribeFigure() {
229
+ if (!this.isConnected) {
230
+ log.debug('Ignoring subscribe when figure in disconnected state');
231
+ return;
232
+ }
233
+ this.figure.subscribe(this.isDownsamplingDisabled ? this.dh.plot.DownsampleOptions.DISABLE : this.dh.plot.DownsampleOptions.DEFAULT);
234
+ }
235
+ unsubscribeFigure() {
236
+ this.figure.unsubscribe();
237
+ }
238
+ startListeningFigure() {
239
+ var {
240
+ dh
241
+ } = this;
242
+ this.figure.addEventListener(dh.plot.Figure.EVENT_UPDATED, this.handleFigureUpdated);
243
+ this.figure.addEventListener(dh.plot.Figure.EVENT_SERIES_ADDED, this.handleFigureSeriesAdded);
244
+ this.figure.addEventListener(dh.plot.Figure.EVENT_DISCONNECT, this.handleFigureDisconnected);
245
+ this.figure.addEventListener(dh.plot.Figure.EVENT_RECONNECT, this.handleFigureReconnected);
246
+ this.figure.addEventListener(dh.plot.Figure.EVENT_DOWNSAMPLESTARTED, this.handleDownsampleStart);
247
+ this.figure.addEventListener(dh.plot.Figure.EVENT_DOWNSAMPLEFINISHED, this.handleDownsampleFinish);
248
+ this.figure.addEventListener(dh.plot.Figure.EVENT_DOWNSAMPLEFAILED, this.handleDownsampleFail);
249
+ this.figure.addEventListener(dh.plot.Figure.EVENT_DOWNSAMPLENEEDED, this.handleDownsampleNeeded);
250
+ this.figure.addEventListener(dh.Client.EVENT_REQUEST_FAILED, this.handleRequestFailed);
251
+ }
252
+ stopListeningFigure() {
253
+ var {
254
+ dh
255
+ } = this;
256
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_UPDATED, this.handleFigureUpdated);
257
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_SERIES_ADDED, this.handleFigureSeriesAdded);
258
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_DISCONNECT, this.handleFigureDisconnected);
259
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_RECONNECT, this.handleFigureReconnected);
260
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_DOWNSAMPLESTARTED, this.handleDownsampleStart);
261
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_DOWNSAMPLEFINISHED, this.handleDownsampleFinish);
262
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_DOWNSAMPLEFAILED, this.handleDownsampleFail);
263
+ this.figure.removeEventListener(dh.plot.Figure.EVENT_DOWNSAMPLENEEDED, this.handleDownsampleNeeded);
264
+ this.figure.removeEventListener(dh.Client.EVENT_REQUEST_FAILED, this.handleRequestFailed);
265
+ }
266
+ handleDownsampleStart(event) {
267
+ log.debug('Downsample started', event);
268
+ this.fireDownsampleStart(event.detail);
269
+ }
270
+ handleDownsampleFinish(event) {
271
+ log.debug('Downsample finished', event);
272
+ this.fireDownsampleFinish(event.detail);
273
+ }
274
+ handleDownsampleFail(event) {
275
+ log.error('Downsample failed', event);
276
+ this.fireDownsampleFail(event.detail);
277
+ }
278
+ handleDownsampleNeeded(event) {
279
+ log.info('Downsample needed', event);
280
+ this.fireDownsampleNeeded(event.detail);
281
+ }
282
+ handleFigureUpdated(event) {
283
+ var {
284
+ detail: figureUpdateEvent
285
+ } = event;
286
+ var {
287
+ series: seriesArray
288
+ } = figureUpdateEvent;
289
+ log.debug2('handleFigureUpdated', seriesArray);
290
+ for (var i = 0; i < seriesArray.length; i += 1) {
291
+ var series = seriesArray[i];
292
+ log.debug2('handleFigureUpdated updating series', series.name);
293
+ var {
294
+ sources
295
+ } = series;
296
+ for (var j = 0; j < sources.length; j += 1) {
297
+ var source = sources[j];
298
+ var {
299
+ columnType,
300
+ type
301
+ } = source;
302
+ var valueTranslator = this.getValueTranslator(columnType, this.formatter);
303
+ var dataArray = figureUpdateEvent.getArray(series, type, valueTranslator);
304
+ this.setDataArrayForSeries(series, type, dataArray);
305
+ }
306
+ this.seriesToProcess.delete(series.name);
307
+ if (this.seriesToProcess.size === 0) {
308
+ this.fireLoadFinished();
309
+ }
310
+ this.cleanSeries(series);
311
+ }
312
+ var {
313
+ data
314
+ } = this;
315
+ this.fireUpdate(data);
316
+ }
317
+ handleRequestFailed(event) {
318
+ log.error('Request failed', event);
319
+ }
320
+
321
+ /**
322
+ * Resubscribe to the figure, should be done if settings change
323
+ */
324
+ resubscribe() {
325
+ if (this.listeners.length > 0) {
326
+ this.unsubscribeFigure();
327
+ this.subscribeFigure();
328
+ }
329
+ }
330
+ setFormatter(formatter) {
331
+ super.setFormatter(formatter);
332
+ this.updateLayoutFormats();
333
+
334
+ // Unsubscribe and resubscribe to trigger a data update
335
+ // Data may need to be translated again because of the new formatter
336
+ this.resubscribe();
337
+ }
338
+ setDownsamplingDisabled(isDownsamplingDisabled) {
339
+ super.setDownsamplingDisabled(isDownsamplingDisabled);
340
+ this.resubscribe();
341
+ }
342
+ handleFigureDisconnected(event) {
343
+ log.debug('Figure disconnected', event);
344
+ this.isConnected = false;
345
+ if (this.listeners.length > 0) {
346
+ this.unsubscribeFigure();
347
+ }
348
+ this.fireDisconnect();
349
+ }
350
+ handleFigureReconnected(event) {
351
+ log.debug('Figure reconnected', event);
352
+ this.isConnected = true;
353
+
354
+ // It's possible the series have changed completely, as the query could have been changed
355
+ this.initAllSeries();
356
+ this.fireReconnect();
357
+ if (this.listeners.length > 0) {
358
+ this.subscribeFigure();
359
+ }
360
+ }
361
+ handleFigureSeriesAdded(event) {
362
+ var {
363
+ detail: series
364
+ } = event;
365
+ log.debug('handleFigureSeriesAdded', series);
366
+ this.pendingSeries.push(series);
367
+ this.addPendingSeries();
368
+ }
369
+ setDimensions(rect) {
370
+ super.setDimensions(rect);
371
+ this.updateAxisPositions();
372
+ }
373
+ setTitle(title) {
374
+ var _match$length, _match;
375
+ super.setTitle(title);
376
+
377
+ // Need to recalculate the padding based on how many lines of text the title is
378
+ // Plotly doesn't handle positioning it correctly, and it's an undocumented feature
379
+ var subtitleCount = (_match$length = (_match = (title !== null && title !== void 0 ? title : '').match(/<br>/g)) === null || _match === void 0 ? void 0 : _match.length) !== null && _match$length !== void 0 ? _match$length : 0;
380
+ var margin = ChartUtils.DEFAULT_MARGIN.t + subtitleCount * ChartUtils.SUBTITLE_LINE_HEIGHT;
381
+ if (this.layout.margin) {
382
+ this.layout.margin.t = margin;
383
+ } else {
384
+ this.layout.margin = {
385
+ t: margin
386
+ };
387
+ }
388
+ if (typeof this.layout.title === 'string') {
389
+ this.layout.title = title;
390
+ } else {
391
+ this.layout.title = _objectSpread({}, this.layout.title);
392
+ this.layout.title.text = title;
393
+ this.layout.title.pad = _objectSpread({}, this.layout.title.pad);
394
+ this.layout.title.pad.t = ChartUtils.DEFAULT_TITLE_PADDING.t + subtitleCount * ChartUtils.SUBTITLE_LINE_HEIGHT * 0.5;
395
+ }
396
+ }
397
+ getPlotWidth() {
398
+ var _this$layout$margin$l, _this$layout$margin, _this$layout$margin$r, _this$layout$margin2;
399
+ if (!this.rect || !this.rect.width) {
400
+ return 0;
401
+ }
402
+ return Math.max(this.rect.width - ((_this$layout$margin$l = (_this$layout$margin = this.layout.margin) === null || _this$layout$margin === void 0 ? void 0 : _this$layout$margin.l) !== null && _this$layout$margin$l !== void 0 ? _this$layout$margin$l : 0) - ((_this$layout$margin$r = (_this$layout$margin2 = this.layout.margin) === null || _this$layout$margin2 === void 0 ? void 0 : _this$layout$margin2.r) !== null && _this$layout$margin$r !== void 0 ? _this$layout$margin$r : 0), 0);
403
+ }
404
+ getPlotHeight() {
405
+ var _this$layout$margin$t, _this$layout$margin3, _this$layout$margin$b, _this$layout$margin4;
406
+ if (!this.rect || !this.rect.height) {
407
+ return 0;
408
+ }
409
+ return Math.max(this.rect.height - ((_this$layout$margin$t = (_this$layout$margin3 = this.layout.margin) === null || _this$layout$margin3 === void 0 ? void 0 : _this$layout$margin3.t) !== null && _this$layout$margin$t !== void 0 ? _this$layout$margin$t : 0) - ((_this$layout$margin$b = (_this$layout$margin4 = this.layout.margin) === null || _this$layout$margin4 === void 0 ? void 0 : _this$layout$margin4.b) !== null && _this$layout$margin$b !== void 0 ? _this$layout$margin$b : 0), 0);
410
+ }
411
+ updateAxisPositions() {
412
+ var plotWidth = this.getPlotWidth();
413
+ var plotHeight = this.getPlotHeight();
414
+ this.chartUtils.updateFigureAxes(this.layout, this.figure, chart => this.getAxisRangeParser(chart, this.formatter), plotWidth, plotHeight, this.theme);
415
+ }
416
+
417
+ /**
418
+ * Updates the format patterns used
419
+ */
420
+ updateLayoutFormats() {
421
+ if (!this.formatter) {
422
+ return;
423
+ }
424
+ var axisFormats = this.chartUtils.getAxisFormats(this.figure, this.formatter);
425
+ axisFormats.forEach((axisFormat, axisLayoutProperty) => {
426
+ log.debug("Assigning ".concat(axisLayoutProperty), this.layout[axisLayoutProperty], axisFormat);
427
+ var props = this.layout[axisLayoutProperty];
428
+ if (props != null) {
429
+ Object.assign(props, axisFormat);
430
+ } else {
431
+ log.debug("Ignoring null layout.".concat(axisLayoutProperty));
432
+ }
433
+ });
434
+ }
435
+
436
+ /**
437
+ * Set a specific array for the array of series properties specified.
438
+ * @param series The series to set the data array for.
439
+ * @param sourceType The source type within that series to set the data for.
440
+ * @param dataArray The array to use for the data for this series source.
441
+ */
442
+ setDataArrayForSeries(series, sourceType, dataArray) {
443
+ var {
444
+ name,
445
+ plotStyle
446
+ } = series;
447
+ var seriesData = this.seriesDataMap.get(name);
448
+ var property = this.chartUtils.getPlotlyProperty(plotStyle, sourceType);
449
+ if (seriesData) {
450
+ set(seriesData, property, dataArray);
451
+ }
452
+ }
453
+
454
+ /**
455
+ * After setting all the data in the series data, we may need to adjust some other properties
456
+ * Eg. Calculating the width from the xLow/xHigh values; Plot.ly uses `width` instead of a low/high
457
+ * value for x.
458
+ * @param series The series to clean the data for
459
+ */
460
+ cleanSeries(series) {
461
+ var {
462
+ dh
463
+ } = this;
464
+ var {
465
+ name,
466
+ plotStyle
467
+ } = series;
468
+ var seriesData = this.seriesDataMap.get(name);
469
+ if (seriesData == null) {
470
+ return;
471
+ }
472
+ if (plotStyle === dh.plot.SeriesPlotStyle.HISTOGRAM) {
473
+ var {
474
+ xLow,
475
+ xHigh
476
+ } = seriesData;
477
+ if (xLow && xHigh && xLow.length === xHigh.length) {
478
+ var width = [];
479
+ for (var i = 0; i < xLow.length; i += 1) {
480
+ width.push(xHigh[i] - xLow[i]);
481
+ }
482
+ seriesData.width = width;
483
+ }
484
+ } else if (plotStyle === dh.plot.SeriesPlotStyle.LINE) {
485
+ var {
486
+ x,
487
+ xLow: _xLow,
488
+ xHigh: _xHigh,
489
+ y,
490
+ yLow,
491
+ yHigh
492
+ } = seriesData;
493
+ if (_xLow && _xHigh && _xLow !== x) {
494
+ seriesData.error_x = ChartUtils.getPlotlyErrorBars(x, _xLow, _xHigh);
495
+ }
496
+ if (yLow && yHigh && yLow !== y) {
497
+ seriesData.error_y = ChartUtils.getPlotlyErrorBars(y, yLow, yHigh);
498
+ }
499
+ } else if (plotStyle === dh.plot.SeriesPlotStyle.TREEMAP) {
500
+ var {
501
+ ids,
502
+ labels
503
+ } = seriesData;
504
+ if (ids !== undefined && labels === undefined) {
505
+ // If the user only provided IDs, we assign the IDs to the labels property as well automatically
506
+ // Plotly uses the labels primarily, which from our API perspective seems kind of backwards
507
+ seriesData.labels = ids;
508
+ }
509
+ }
510
+ }
511
+ getData() {
512
+ return this.data;
513
+ }
514
+ getLayout() {
515
+ return this.layout;
516
+ }
517
+ getFilterColumnMap() {
518
+ return new Map(this.filterColumnMap);
519
+ }
520
+ isFilterRequired() {
521
+ return this.oneClicks.find(oneClick => oneClick.requireAllFiltersToDisplay) != null;
522
+ }
523
+
524
+ /**
525
+ * Sets the filter on the model. Will only set the values that have changed.
526
+ * @param filterMap Map of filter column names to values
527
+ */
528
+ setFilter(filterMap) {
529
+ var _this2 = this;
530
+ if (this.oneClicks.length === 0) {
531
+ log.warn('Trying to set a filter, but no one click!');
532
+ return;
533
+ }
534
+ log.debug('setFilter', filterMap);
535
+ var _loop2 = function _loop2() {
536
+ var oneClick = _this2.oneClicks[i];
537
+ var {
538
+ columns
539
+ } = oneClick;
540
+ // Need to get all the keys in case a filter was removed
541
+ var keys = new Set([...filterMap.keys(), ..._this2.lastFilter.keys()]);
542
+ keys.forEach(key => {
543
+ var value = filterMap.get(key);
544
+ if (_this2.lastFilter.get(key) !== value && columns.find(column => column.name === key) != null) {
545
+ oneClick.setValueForColumn(key, value);
546
+ }
547
+ });
548
+ };
549
+ for (var i = 0; i < this.oneClicks.length; i += 1) {
550
+ _loop2();
551
+ }
552
+ this.lastFilter = new Map(filterMap);
553
+ }
554
+ setFigure(figure) {
555
+ this.close();
556
+ this.figure = figure;
557
+ this.setTitle(this.getDefaultTitle());
558
+ this.initAllSeries();
559
+ this.updateAxisPositions();
560
+ this.startListeningFigure();
561
+ if (this.listeners.length > 0) {
562
+ this.subscribeFigure();
563
+ }
564
+ }
565
+ updateSettings(settings) {
566
+ this.settings = settings;
567
+ }
568
+ }
569
+ _defineProperty(FigureChartModel, "ADD_SERIES_DEBOUNCE", 50);
570
+ export default FigureChartModel;
571
+ //# sourceMappingURL=FigureChartModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FigureChartModel.js","names":["memoize","debounce","set","Log","ChartModel","ChartUtils","ChartTheme","log","module","FigureChartModel","constructor","dh","figure","settings","theme","axes","getAllAxes","pendingSeries","series","i","chart","charts","find","c","includes","addSeries","showLegend","subscribe","length","ADD_SERIES_DEBOUNCE","columnType","formatter","dataFormatter","getColumnTypeFormatter","dhTimeZone","undefined","timeZone","getTimeZone","value","chartUtils","unwrapValue","wrapValue","range","rangeStart","rangeEnd","valueParser","getValueParser","axis","source","getSourceForAxis","getRangeParser","handleFigureUpdated","bind","handleFigureDisconnected","handleFigureReconnected","handleFigureSeriesAdded","handleDownsampleStart","handleDownsampleFinish","handleDownsampleFail","handleDownsampleNeeded","handleRequestFailed","data","template","layout","makeDefaultLayout","grid","rows","columns","cols","pattern","seriesDataMap","Map","oneClicks","filterColumnMap","lastFilter","isConnected","seriesToProcess","Set","setTitle","getDefaultTitle","initAllSeries","updateAxisPositions","startListeningFigure","close","addPendingSeries","cancel","stopListeningFigure","title","clear","activeSeriesNames","j","push","name","allSeriesNames","keys","inactiveSeriesNames","filter","seriesName","indexOf","delete","axisTypeMap","groupArray","seriesData","makeSeriesDataFromSeries","getSeriesVisibility","values","plotStyle","plot","SeriesPlotStyle","STACKED_BAR","barmode","PIE","hiddenlabels","getHiddenLabels","showlegend","oneClick","updateLayoutFormats","callback","listeners","subscribeFigure","unsubscribe","unsubscribeFigure","debug","isDownsamplingDisabled","DownsampleOptions","DISABLE","DEFAULT","addEventListener","Figure","EVENT_UPDATED","EVENT_SERIES_ADDED","EVENT_DISCONNECT","EVENT_RECONNECT","EVENT_DOWNSAMPLESTARTED","EVENT_DOWNSAMPLEFINISHED","EVENT_DOWNSAMPLEFAILED","EVENT_DOWNSAMPLENEEDED","Client","EVENT_REQUEST_FAILED","removeEventListener","event","fireDownsampleStart","detail","fireDownsampleFinish","error","fireDownsampleFail","info","fireDownsampleNeeded","figureUpdateEvent","seriesArray","debug2","sources","type","valueTranslator","getValueTranslator","dataArray","getArray","setDataArrayForSeries","size","fireLoadFinished","cleanSeries","fireUpdate","resubscribe","setFormatter","setDownsamplingDisabled","fireDisconnect","fireReconnect","setDimensions","rect","subtitleCount","match","margin","DEFAULT_MARGIN","t","SUBTITLE_LINE_HEIGHT","text","pad","DEFAULT_TITLE_PADDING","getPlotWidth","width","Math","max","l","r","getPlotHeight","height","b","plotWidth","plotHeight","updateFigureAxes","getAxisRangeParser","axisFormats","getAxisFormats","forEach","axisFormat","axisLayoutProperty","props","Object","assign","sourceType","get","property","getPlotlyProperty","HISTOGRAM","xLow","xHigh","LINE","x","y","yLow","yHigh","error_x","getPlotlyErrorBars","error_y","TREEMAP","ids","labels","getData","getLayout","getFilterColumnMap","isFilterRequired","requireAllFiltersToDisplay","setFilter","filterMap","warn","key","column","setValueForColumn","setFigure","updateSettings"],"sources":["../src/FigureChartModel.ts"],"sourcesContent":["/* eslint class-methods-use-this: \"off\" */\nimport memoize from 'memoizee';\nimport debounce from 'lodash.debounce';\nimport set from 'lodash.set';\nimport type {\n Axis,\n Chart,\n dh as DhType,\n Figure,\n OneClick,\n Series,\n SourceType,\n} from '@deephaven/jsapi-types';\nimport Log from '@deephaven/log';\nimport { Range } from '@deephaven/utils';\nimport type { Layout, Data, PlotData } from 'plotly.js';\nimport type {\n DateTimeColumnFormatter,\n Formatter,\n} from '@deephaven/jsapi-utils';\nimport ChartModel, { ChartEvent } from './ChartModel';\nimport ChartUtils, {\n AxisTypeMap,\n ChartModelSettings,\n FilterColumnMap,\n FilterMap,\n} from './ChartUtils';\nimport ChartTheme from './ChartTheme';\n\nconst log = Log.module('FigureChartModel');\n\n/**\n * Takes a Figure object from a widget to make a model for a chart\n */\nclass FigureChartModel extends ChartModel {\n static ADD_SERIES_DEBOUNCE = 50;\n\n /**\n * @param dh JSAPI instance\n * @param figure The figure object created by the API\n * @param settings Chart settings\n */\n constructor(\n dh: DhType,\n figure: Figure,\n settings: Partial<ChartModelSettings> = {},\n theme: typeof ChartTheme = ChartTheme\n ) {\n super(dh);\n\n this.handleFigureUpdated = this.handleFigureUpdated.bind(this);\n this.handleFigureDisconnected = this.handleFigureDisconnected.bind(this);\n this.handleFigureReconnected = this.handleFigureReconnected.bind(this);\n this.handleFigureSeriesAdded = this.handleFigureSeriesAdded.bind(this);\n this.handleDownsampleStart = this.handleDownsampleStart.bind(this);\n this.handleDownsampleFinish = this.handleDownsampleFinish.bind(this);\n this.handleDownsampleFail = this.handleDownsampleFail.bind(this);\n this.handleDownsampleNeeded = this.handleDownsampleNeeded.bind(this);\n this.handleRequestFailed = this.handleRequestFailed.bind(this);\n\n this.dh = dh;\n this.chartUtils = new ChartUtils(dh);\n this.figure = figure;\n this.settings = settings;\n this.theme = theme;\n this.data = [];\n const template = {\n data: {},\n layout: this.chartUtils.makeDefaultLayout(theme),\n };\n this.layout = {\n grid: {\n rows: figure.rows,\n columns: figure.cols,\n pattern: 'independent',\n },\n template,\n };\n this.seriesDataMap = new Map();\n this.pendingSeries = [];\n this.oneClicks = [];\n this.filterColumnMap = new Map();\n this.lastFilter = new Map();\n this.isConnected = true; // Assume figure is connected to start\n this.seriesToProcess = new Set();\n\n this.setTitle(this.getDefaultTitle());\n this.initAllSeries();\n this.updateAxisPositions();\n this.startListeningFigure();\n }\n\n chartUtils: ChartUtils;\n\n dh: DhType;\n\n figure: Figure;\n\n settings: Partial<ChartModelSettings>;\n\n theme: typeof ChartTheme;\n\n data: Partial<Data>[];\n\n layout: Partial<Layout>;\n\n seriesDataMap: Map<\n string,\n Partial<PlotData> & {\n xLow?: number[];\n xHigh?: number[];\n yLow?: number[];\n yHigh?: number[];\n }\n >;\n\n pendingSeries: Series[];\n\n oneClicks: OneClick[];\n\n filterColumnMap: FilterColumnMap;\n\n lastFilter: FilterMap;\n\n isConnected: boolean; // Assume figure is connected to start\n\n seriesToProcess;\n\n close(): void {\n this.figure.close();\n this.addPendingSeries.cancel();\n this.stopListeningFigure();\n }\n\n getDefaultTitle(): string {\n if (this.figure.charts.length > 0) {\n const chart = this.figure.charts[0];\n return chart.title;\n }\n\n return '';\n }\n\n initAllSeries(): void {\n this.oneClicks = [];\n this.filterColumnMap.clear();\n\n const { charts } = this.figure;\n const axes = ChartUtils.getAllAxes(this.figure);\n const activeSeriesNames: string[] = [];\n for (let i = 0; i < charts.length; i += 1) {\n const chart = charts[i];\n\n for (let j = 0; j < chart.series.length; j += 1) {\n const series = chart.series[j];\n activeSeriesNames.push(series.name);\n this.addSeries(series, axes, chart.showLegend);\n }\n }\n\n // Remove any series that no longer exist\n const allSeriesNames = [...this.seriesDataMap.keys()];\n const inactiveSeriesNames = allSeriesNames.filter(\n seriesName => activeSeriesNames.indexOf(seriesName) < 0\n );\n for (let i = 0; i < inactiveSeriesNames.length; i += 1) {\n const seriesName = inactiveSeriesNames[i];\n this.seriesDataMap.delete(seriesName);\n }\n this.seriesToProcess = new Set([...this.seriesDataMap.keys()]);\n }\n\n /**\n * Add a series to the model\n * @param series Series object to add\n * @param axes All the axis in this figure\n * @param showLegend Whether this series should show the legend or not\n */\n addSeries(series: Series, axes: Axis[], showLegend: boolean | null): void {\n const { dh } = this;\n const axisTypeMap: AxisTypeMap = ChartUtils.groupArray(axes, 'type');\n\n const seriesData = this.chartUtils.makeSeriesDataFromSeries(\n series,\n axisTypeMap,\n ChartUtils.getSeriesVisibility(series.name, this.settings),\n showLegend,\n this.theme\n );\n\n this.seriesDataMap.set(series.name, seriesData);\n\n this.data = [...this.seriesDataMap.values()];\n\n if (series.plotStyle === dh.plot.SeriesPlotStyle.STACKED_BAR) {\n this.layout.barmode = 'stack';\n } else if (series.plotStyle === dh.plot.SeriesPlotStyle.PIE) {\n this.layout.hiddenlabels = ChartUtils.getHiddenLabels(this.settings);\n }\n\n // We only want to force hide the legend if there is only one series that is not a PIE\n // Right now this means that if the user only has one series, they cannot explicitly show the legend until deephaven-core#3254 is implemented\n // TODO: deephaven-core#3254, once done, this can be removed.\n this.layout.showlegend =\n this.data.length > 1 || series.plotStyle === dh.plot.SeriesPlotStyle.PIE\n ? showLegend ?? undefined\n : false;\n\n if (series.oneClick != null) {\n const { oneClick } = series;\n const { columns } = oneClick;\n for (let i = 0; i < columns.length; i += 1) {\n this.filterColumnMap.set(columns[i].name, columns[i]);\n }\n\n this.oneClicks.push(oneClick);\n }\n\n this.updateLayoutFormats();\n }\n\n // We need to debounce adding series so we subscribe to them all in the same tick\n // This should no longer be necessary after IDS-5049 lands\n addPendingSeries = debounce(() => {\n const axes = ChartUtils.getAllAxes(this.figure);\n const { pendingSeries } = this;\n for (let i = 0; i < pendingSeries.length; i += 1) {\n const series = pendingSeries[i];\n const chart = this.figure.charts.find(c => c.series.includes(series));\n this.addSeries(series, axes, chart?.showLegend ?? null);\n\n series.subscribe();\n // We'll get an update with the data after subscribing\n }\n\n this.pendingSeries = [];\n }, FigureChartModel.ADD_SERIES_DEBOUNCE);\n\n subscribe(callback: (event: ChartEvent) => void): void {\n super.subscribe(callback);\n\n if (this.listeners.length === 1) {\n // Need to initialize the series here as we may have missed some series when not subscribed\n this.initAllSeries();\n this.subscribeFigure();\n }\n }\n\n unsubscribe(callback: (event: ChartEvent) => void): void {\n super.unsubscribe(callback);\n\n if (this.listeners.length === 0) {\n this.unsubscribeFigure();\n }\n }\n\n subscribeFigure(): void {\n if (!this.isConnected) {\n log.debug('Ignoring subscribe when figure in disconnected state');\n return;\n }\n\n this.figure.subscribe(\n this.isDownsamplingDisabled\n ? this.dh.plot.DownsampleOptions.DISABLE\n : this.dh.plot.DownsampleOptions.DEFAULT\n );\n }\n\n unsubscribeFigure(): void {\n this.figure.unsubscribe();\n }\n\n startListeningFigure(): void {\n const { dh } = this;\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_UPDATED,\n this.handleFigureUpdated\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_SERIES_ADDED,\n this.handleFigureSeriesAdded\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_DISCONNECT,\n this.handleFigureDisconnected\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_RECONNECT,\n this.handleFigureReconnected\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLESTARTED,\n this.handleDownsampleStart\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLEFINISHED,\n this.handleDownsampleFinish\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLEFAILED,\n this.handleDownsampleFail\n );\n this.figure.addEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLENEEDED,\n this.handleDownsampleNeeded\n );\n this.figure.addEventListener(\n dh.Client.EVENT_REQUEST_FAILED,\n this.handleRequestFailed\n );\n }\n\n stopListeningFigure(): void {\n const { dh } = this;\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_UPDATED,\n this.handleFigureUpdated\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_SERIES_ADDED,\n this.handleFigureSeriesAdded\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_DISCONNECT,\n this.handleFigureDisconnected\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_RECONNECT,\n this.handleFigureReconnected\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLESTARTED,\n this.handleDownsampleStart\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLEFINISHED,\n this.handleDownsampleFinish\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLEFAILED,\n this.handleDownsampleFail\n );\n this.figure.removeEventListener(\n dh.plot.Figure.EVENT_DOWNSAMPLENEEDED,\n this.handleDownsampleNeeded\n );\n this.figure.removeEventListener(\n dh.Client.EVENT_REQUEST_FAILED,\n this.handleRequestFailed\n );\n }\n\n getTimeZone = memoize(\n (columnType: string, formatter: Formatter | undefined) => {\n if (formatter != null) {\n const dataFormatter = formatter.getColumnTypeFormatter(columnType);\n if (dataFormatter != null) {\n return (dataFormatter as DateTimeColumnFormatter).dhTimeZone;\n }\n }\n return undefined;\n }\n );\n\n getValueTranslator = memoize(\n (columnType: string, formatter: Formatter | undefined) => {\n const timeZone = this.getTimeZone(columnType, formatter);\n return (value: unknown) => this.chartUtils.unwrapValue(value, timeZone);\n }\n );\n\n /** Gets the parser for a value with the provided column type */\n getValueParser = memoize(\n (columnType: string, formatter: Formatter | undefined) => {\n const timeZone = this.getTimeZone(columnType, formatter);\n return (value: unknown) =>\n this.chartUtils.wrapValue(value, columnType, timeZone);\n }\n );\n\n /**\n * Gets the range parser for a particular column type\n */\n getRangeParser = memoize(\n (columnType: string, formatter?: Formatter) => (range: Range) => {\n let [rangeStart, rangeEnd]: [unknown, unknown] = range;\n const valueParser = this.getValueParser(columnType, formatter);\n rangeStart = valueParser(rangeStart);\n rangeEnd = valueParser(rangeEnd);\n return [rangeStart, rangeEnd];\n }\n );\n\n /**\n * Gets the parser for parsing the range from an axis within the given chart\n */\n getAxisRangeParser = memoize(\n (chart: Chart, formatter?: Formatter) => (axis: Axis) => {\n const source = ChartUtils.getSourceForAxis(chart, axis);\n if (source != null) {\n return this.getRangeParser(source.columnType, formatter);\n }\n\n return (range: [unknown, unknown]) => range;\n }\n );\n\n handleDownsampleStart(event: ChartEvent): void {\n log.debug('Downsample started', event);\n\n this.fireDownsampleStart(event.detail);\n }\n\n handleDownsampleFinish(event: ChartEvent): void {\n log.debug('Downsample finished', event);\n\n this.fireDownsampleFinish(event.detail);\n }\n\n handleDownsampleFail(event: ChartEvent): void {\n log.error('Downsample failed', event);\n\n this.fireDownsampleFail(event.detail);\n }\n\n handleDownsampleNeeded(event: ChartEvent): void {\n log.info('Downsample needed', event);\n\n this.fireDownsampleNeeded(event.detail);\n }\n\n handleFigureUpdated(event: ChartEvent): void {\n const { detail: figureUpdateEvent } = event;\n const { series: seriesArray } = figureUpdateEvent;\n\n log.debug2('handleFigureUpdated', seriesArray);\n\n for (let i = 0; i < seriesArray.length; i += 1) {\n const series = seriesArray[i];\n\n log.debug2('handleFigureUpdated updating series', series.name);\n\n const { sources } = series;\n for (let j = 0; j < sources.length; j += 1) {\n const source = sources[j];\n const { columnType, type } = source;\n const valueTranslator = this.getValueTranslator(\n columnType,\n this.formatter\n );\n const dataArray = figureUpdateEvent.getArray(\n series,\n type,\n valueTranslator\n );\n this.setDataArrayForSeries(series, type, dataArray);\n }\n\n this.seriesToProcess.delete(series.name);\n if (this.seriesToProcess.size === 0) {\n this.fireLoadFinished();\n }\n\n this.cleanSeries(series);\n }\n\n const { data } = this;\n this.fireUpdate(data);\n }\n\n handleRequestFailed(event: ChartEvent): void {\n log.error('Request failed', event);\n }\n\n /**\n * Resubscribe to the figure, should be done if settings change\n */\n resubscribe(): void {\n if (this.listeners.length > 0) {\n this.unsubscribeFigure();\n this.subscribeFigure();\n }\n }\n\n setFormatter(formatter: Formatter): void {\n super.setFormatter(formatter);\n\n this.updateLayoutFormats();\n\n // Unsubscribe and resubscribe to trigger a data update\n // Data may need to be translated again because of the new formatter\n this.resubscribe();\n }\n\n setDownsamplingDisabled(isDownsamplingDisabled: boolean): void {\n super.setDownsamplingDisabled(isDownsamplingDisabled);\n\n this.resubscribe();\n }\n\n handleFigureDisconnected(event: CustomEvent): void {\n log.debug('Figure disconnected', event);\n\n this.isConnected = false;\n\n if (this.listeners.length > 0) {\n this.unsubscribeFigure();\n }\n\n this.fireDisconnect();\n }\n\n handleFigureReconnected(event: CustomEvent): void {\n log.debug('Figure reconnected', event);\n\n this.isConnected = true;\n\n // It's possible the series have changed completely, as the query could have been changed\n this.initAllSeries();\n\n this.fireReconnect();\n\n if (this.listeners.length > 0) {\n this.subscribeFigure();\n }\n }\n\n handleFigureSeriesAdded(event: { detail: Series }): void {\n const { detail: series } = event;\n log.debug('handleFigureSeriesAdded', series);\n\n this.pendingSeries.push(series);\n this.addPendingSeries();\n }\n\n setDimensions(rect: DOMRect): void {\n super.setDimensions(rect);\n\n this.updateAxisPositions();\n }\n\n setTitle(title: string): void {\n super.setTitle(title);\n\n // Need to recalculate the padding based on how many lines of text the title is\n // Plotly doesn't handle positioning it correctly, and it's an undocumented feature\n const subtitleCount = (title ?? '').match(/<br>/g)?.length ?? 0;\n const margin =\n ChartUtils.DEFAULT_MARGIN.t +\n subtitleCount * ChartUtils.SUBTITLE_LINE_HEIGHT;\n\n if (this.layout.margin) {\n this.layout.margin.t = margin;\n } else {\n this.layout.margin = { t: margin };\n }\n\n if (typeof this.layout.title === 'string') {\n this.layout.title = title;\n } else {\n this.layout.title = { ...this.layout.title };\n this.layout.title.text = title;\n this.layout.title.pad = { ...this.layout.title.pad };\n this.layout.title.pad.t =\n ChartUtils.DEFAULT_TITLE_PADDING.t +\n subtitleCount * ChartUtils.SUBTITLE_LINE_HEIGHT * 0.5;\n }\n }\n\n getPlotWidth(): number {\n if (!this.rect || !this.rect.width) {\n return 0;\n }\n\n return Math.max(\n this.rect.width -\n (this.layout.margin?.l ?? 0) -\n (this.layout.margin?.r ?? 0),\n 0\n );\n }\n\n getPlotHeight(): number {\n if (!this.rect || !this.rect.height) {\n return 0;\n }\n\n return Math.max(\n this.rect.height -\n (this.layout.margin?.t ?? 0) -\n (this.layout.margin?.b ?? 0),\n 0\n );\n }\n\n updateAxisPositions(): void {\n const plotWidth = this.getPlotWidth();\n const plotHeight = this.getPlotHeight();\n this.chartUtils.updateFigureAxes(\n this.layout,\n this.figure,\n chart => this.getAxisRangeParser(chart, this.formatter),\n plotWidth,\n plotHeight,\n this.theme\n );\n }\n\n /**\n * Updates the format patterns used\n */\n updateLayoutFormats(): void {\n if (!this.formatter) {\n return;\n }\n\n const axisFormats = this.chartUtils.getAxisFormats(\n this.figure,\n this.formatter\n );\n axisFormats.forEach((axisFormat, axisLayoutProperty) => {\n log.debug(\n `Assigning ${axisLayoutProperty}`,\n this.layout[axisLayoutProperty],\n axisFormat\n );\n\n const props = this.layout[axisLayoutProperty];\n if (props != null) {\n Object.assign(props, axisFormat);\n } else {\n log.debug(`Ignoring null layout.${axisLayoutProperty}`);\n }\n });\n }\n\n /**\n * Set a specific array for the array of series properties specified.\n * @param series The series to set the data array for.\n * @param sourceType The source type within that series to set the data for.\n * @param dataArray The array to use for the data for this series source.\n */\n setDataArrayForSeries(\n series: Series,\n sourceType: SourceType,\n dataArray: unknown[]\n ): void {\n const { name, plotStyle } = series;\n\n const seriesData = this.seriesDataMap.get(name);\n const property = this.chartUtils.getPlotlyProperty(plotStyle, sourceType);\n\n if (seriesData) {\n set(seriesData, property, dataArray);\n }\n }\n\n /**\n * After setting all the data in the series data, we may need to adjust some other properties\n * Eg. Calculating the width from the xLow/xHigh values; Plot.ly uses `width` instead of a low/high\n * value for x.\n * @param series The series to clean the data for\n */\n cleanSeries(series: Series): void {\n const { dh } = this;\n const { name, plotStyle } = series;\n const seriesData = this.seriesDataMap.get(name);\n if (seriesData == null) {\n return;\n }\n if (plotStyle === dh.plot.SeriesPlotStyle.HISTOGRAM) {\n const { xLow, xHigh } = seriesData;\n if (xLow && xHigh && xLow.length === xHigh.length) {\n const width = [];\n for (let i = 0; i < xLow.length; i += 1) {\n width.push(xHigh[i] - xLow[i]);\n }\n seriesData.width = width;\n }\n } else if (plotStyle === dh.plot.SeriesPlotStyle.LINE) {\n const { x, xLow, xHigh, y, yLow, yHigh } = seriesData;\n if (xLow && xHigh && xLow !== x) {\n seriesData.error_x = ChartUtils.getPlotlyErrorBars(\n x as number[],\n xLow,\n xHigh\n );\n }\n if (yLow && yHigh && yLow !== y) {\n seriesData.error_y = ChartUtils.getPlotlyErrorBars(\n y as number[],\n yLow,\n yHigh\n );\n }\n } else if (plotStyle === dh.plot.SeriesPlotStyle.TREEMAP) {\n const { ids, labels } = seriesData;\n if (ids !== undefined && labels === undefined) {\n // If the user only provided IDs, we assign the IDs to the labels property as well automatically\n // Plotly uses the labels primarily, which from our API perspective seems kind of backwards\n seriesData.labels = ids;\n }\n }\n }\n\n getData(): Partial<Data>[] {\n return this.data;\n }\n\n getLayout(): Partial<Layout> {\n return this.layout;\n }\n\n getFilterColumnMap(): FilterColumnMap {\n return new Map(this.filterColumnMap);\n }\n\n isFilterRequired(): boolean {\n return (\n this.oneClicks.find(oneClick => oneClick.requireAllFiltersToDisplay) !=\n null\n );\n }\n\n /**\n * Sets the filter on the model. Will only set the values that have changed.\n * @param filterMap Map of filter column names to values\n */\n setFilter(filterMap: FilterMap): void {\n if (this.oneClicks.length === 0) {\n log.warn('Trying to set a filter, but no one click!');\n return;\n }\n\n log.debug('setFilter', filterMap);\n\n for (let i = 0; i < this.oneClicks.length; i += 1) {\n const oneClick = this.oneClicks[i];\n const { columns } = oneClick;\n // Need to get all the keys in case a filter was removed\n const keys = new Set([...filterMap.keys(), ...this.lastFilter.keys()]);\n keys.forEach(key => {\n const value = filterMap.get(key);\n if (\n this.lastFilter.get(key) !== value &&\n columns.find(column => column.name === key) != null\n ) {\n oneClick.setValueForColumn(key, value);\n }\n });\n }\n\n this.lastFilter = new Map(filterMap);\n }\n\n setFigure(figure: Figure): void {\n this.close();\n\n this.figure = figure;\n\n this.setTitle(this.getDefaultTitle());\n this.initAllSeries();\n this.updateAxisPositions();\n this.startListeningFigure();\n if (this.listeners.length > 0) {\n this.subscribeFigure();\n }\n }\n\n updateSettings(settings: Partial<ChartModelSettings>): void {\n this.settings = settings;\n }\n}\n\nexport default FigureChartModel;\n"],"mappings":"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"}