stream-charts 1.0.0 → 1.1.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.
- package/README.md +758 -345
- package/changes.md +10 -0
- package/dist/src/app/charts/Chart.d.ts +116 -87
- package/dist/src/app/charts/Chart.js +96 -101
- package/dist/src/app/charts/Chart.js.map +1 -1
- package/dist/src/app/charts/axes/AxesState.d.ts +64 -0
- package/dist/src/app/charts/axes/AxesState.js +97 -0
- package/dist/src/app/charts/axes/AxesState.js.map +1 -0
- package/dist/src/app/charts/axes/AxesState.test.js +30 -0
- package/dist/src/app/charts/axes/AxesState.test.js.map +1 -0
- package/dist/src/app/charts/axes/AxisInterval.d.ts +92 -0
- package/dist/src/app/charts/axes/AxisInterval.js +126 -0
- package/dist/src/app/charts/axes/AxisInterval.js.map +1 -0
- package/dist/src/app/charts/axes/AxisInterval.test.js +120 -0
- package/dist/src/app/charts/axes/AxisInterval.test.js.map +1 -0
- package/dist/src/app/charts/axes/BaseAxisRange.d.ts +83 -0
- package/dist/src/app/charts/axes/BaseAxisRange.js +58 -0
- package/dist/src/app/charts/axes/BaseAxisRange.js.map +1 -0
- package/dist/src/app/charts/axes/ContinuousAxis.d.ts +22 -0
- package/dist/src/app/charts/axes/ContinuousAxis.js +96 -0
- package/dist/src/app/charts/axes/ContinuousAxis.js.map +1 -0
- package/dist/src/app/charts/axes/ContinuousAxisRange.d.ts +59 -0
- package/dist/src/app/charts/axes/ContinuousAxisRange.js +84 -0
- package/dist/src/app/charts/axes/ContinuousAxisRange.js.map +1 -0
- package/dist/src/app/charts/axes/ContinuousAxisRange.test.js +47 -0
- package/dist/src/app/charts/axes/ContinuousAxisRange.test.js.map +1 -0
- package/dist/src/app/charts/axes/OrdinalAxis.d.ts +23 -0
- package/dist/src/app/charts/axes/OrdinalAxis.js +124 -0
- package/dist/src/app/charts/axes/OrdinalAxis.js.map +1 -0
- package/dist/src/app/charts/axes/OrdinalAxisRange.d.ts +69 -0
- package/dist/src/app/charts/axes/OrdinalAxisRange.js +100 -0
- package/dist/src/app/charts/axes/OrdinalAxisRange.js.map +1 -0
- package/dist/src/app/charts/axes/OrdinalAxisRange.test.js +48 -0
- package/dist/src/app/charts/axes/OrdinalAxisRange.test.js.map +1 -0
- package/dist/src/app/charts/axes/axes.d.ts +391 -0
- package/dist/src/app/charts/axes/axes.js +1046 -0
- package/dist/src/app/charts/axes/axes.js.map +1 -0
- package/dist/src/app/charts/d3types.d.ts +10 -10
- package/dist/src/app/charts/filters/regexFilter.d.ts +9 -0
- package/dist/src/app/charts/filters/regexFilter.js +18 -0
- package/dist/src/app/charts/filters/regexFilter.js.map +1 -0
- package/dist/src/app/charts/filters/regexFilter.test.d.ts +1 -0
- package/dist/src/app/charts/filters/regexFilter.test.js +11 -0
- package/dist/src/app/charts/filters/regexFilter.test.js.map +1 -0
- package/dist/src/app/charts/hooks/useAxes.d.ts +144 -0
- package/dist/src/app/charts/hooks/useAxes.js +187 -0
- package/dist/src/app/charts/hooks/useAxes.js.map +1 -0
- package/dist/src/app/charts/hooks/useChart.d.ts +30 -201
- package/dist/src/app/charts/hooks/useChart.js +33 -134
- package/dist/src/app/charts/hooks/useChart.js.map +1 -1
- package/dist/src/app/charts/hooks/useDataObservable.d.ts +74 -0
- package/dist/src/app/charts/hooks/useDataObservable.js +76 -0
- package/dist/src/app/charts/hooks/useDataObservable.js.map +1 -0
- package/dist/src/app/charts/hooks/useInitialData.d.ts +38 -0
- package/dist/src/app/charts/hooks/useInitialData.js +29 -0
- package/dist/src/app/charts/hooks/useInitialData.js.map +1 -0
- package/dist/src/app/charts/hooks/useMouse.d.ts +53 -0
- package/dist/src/app/charts/hooks/useMouse.js +65 -0
- package/dist/src/app/charts/hooks/useMouse.js.map +1 -0
- package/dist/src/app/charts/hooks/usePlotDimensions.d.ts +34 -0
- package/dist/src/app/charts/hooks/usePlotDimensions.js +73 -0
- package/dist/src/app/charts/hooks/usePlotDimensions.js.map +1 -0
- package/dist/src/app/charts/hooks/useTooltip.d.ts +64 -0
- package/dist/src/app/charts/hooks/useTooltip.js +52 -0
- package/dist/src/app/charts/hooks/useTooltip.js.map +1 -0
- package/dist/src/app/charts/observables/ChartData.d.ts +23 -0
- package/dist/src/app/charts/observables/ChartData.js +20 -0
- package/dist/src/app/charts/observables/ChartData.js.map +1 -0
- package/dist/src/app/charts/observables/iterates.d.ts +52 -0
- package/dist/src/app/charts/observables/iterates.js +121 -0
- package/dist/src/app/charts/observables/iterates.js.map +1 -0
- package/dist/src/app/charts/observables/iterates.test.d.ts +1 -0
- package/dist/src/app/charts/observables/iterates.test.js +180 -0
- package/dist/src/app/charts/observables/iterates.test.js.map +1 -0
- package/dist/src/app/charts/observables/ordinals.d.ts +75 -0
- package/dist/src/app/charts/observables/ordinals.js +141 -0
- package/dist/src/app/charts/observables/ordinals.js.map +1 -0
- package/dist/src/app/charts/observables/ordinals.test.d.ts +1 -0
- package/dist/src/app/charts/observables/ordinals.test.js +102 -0
- package/dist/src/app/charts/observables/ordinals.test.js.map +1 -0
- package/dist/src/app/charts/plots/BarPlot.d.ts +81 -0
- package/dist/src/app/charts/plots/BarPlot.js +557 -0
- package/dist/src/app/charts/plots/BarPlot.js.map +1 -0
- package/dist/src/app/charts/plots/PoincarePlot.d.ts +78 -0
- package/dist/src/app/charts/plots/PoincarePlot.js +504 -0
- package/dist/src/app/charts/plots/PoincarePlot.js.map +1 -0
- package/dist/src/app/charts/{RasterPlot.d.ts → plots/RasterPlot.d.ts} +1 -1
- package/dist/src/app/charts/{RasterPlot.js → plots/RasterPlot.js} +152 -133
- package/dist/src/app/charts/plots/RasterPlot.js.map +1 -0
- package/dist/src/app/charts/{ScatterPlot.d.ts → plots/ScatterPlot.d.ts} +10 -8
- package/dist/src/app/charts/plots/ScatterPlot.js +379 -0
- package/dist/src/app/charts/plots/ScatterPlot.js.map +1 -0
- package/dist/src/app/charts/{plot.d.ts → plots/plot.d.ts} +12 -14
- package/dist/src/app/charts/{plot.js → plots/plot.js} +19 -17
- package/dist/src/app/charts/plots/plot.js.map +1 -0
- package/dist/src/app/charts/series/baseSeries.d.ts +38 -0
- package/dist/src/app/charts/series/baseSeries.js +36 -0
- package/dist/src/app/charts/series/baseSeries.js.map +1 -0
- package/dist/src/app/charts/series/datumSeries.test.d.ts +1 -0
- package/dist/src/app/charts/series/datumSeries.test.js +50 -0
- package/dist/src/app/charts/series/datumSeries.test.js.map +1 -0
- package/dist/src/app/charts/series/iterateSeries.d.ts +42 -0
- package/dist/src/app/charts/series/iterateSeries.js +34 -0
- package/dist/src/app/charts/series/iterateSeries.js.map +1 -0
- package/dist/src/app/charts/series/ordinalSeries.d.ts +54 -0
- package/dist/src/app/charts/series/ordinalSeries.js +98 -0
- package/dist/src/app/charts/series/ordinalSeries.js.map +1 -0
- package/dist/src/app/charts/series/timeSeries.d.ts +30 -0
- package/dist/src/app/charts/series/timeSeries.js +19 -0
- package/dist/src/app/charts/series/timeSeries.js.map +1 -0
- package/dist/src/app/charts/{chartData.d.ts → series/timeSeriesChartData.d.ts} +11 -6
- package/dist/src/app/charts/series/timeSeriesChartData.js +32 -0
- package/dist/src/app/charts/series/timeSeriesChartData.js.map +1 -0
- package/dist/src/app/charts/styling/barPlotStyle.d.ts +41 -0
- package/dist/src/app/charts/styling/barPlotStyle.js +84 -0
- package/dist/src/app/charts/styling/barPlotStyle.js.map +1 -0
- package/dist/src/app/charts/{margins.d.ts → styling/margins.d.ts} +7 -5
- package/dist/src/app/charts/{margins.js → styling/margins.js} +19 -9
- package/dist/src/app/charts/styling/margins.js.map +1 -0
- package/dist/src/app/charts/styling/margins.test.d.ts +1 -0
- package/dist/src/app/charts/styling/margins.test.js +19 -0
- package/dist/src/app/charts/styling/margins.test.js.map +1 -0
- package/dist/src/app/charts/styling/svgStyle.d.ts +76 -0
- package/dist/src/app/charts/styling/svgStyle.js +84 -0
- package/dist/src/app/charts/styling/svgStyle.js.map +1 -0
- package/dist/src/app/charts/subscriptions/subscription.test.d.ts +1 -0
- package/dist/src/app/charts/subscriptions/subscription.test.js +395 -0
- package/dist/src/app/charts/subscriptions/subscription.test.js.map +1 -0
- package/dist/src/app/charts/subscriptions/subscriptions.d.ts +100 -0
- package/dist/src/app/charts/subscriptions/subscriptions.js +449 -0
- package/dist/src/app/charts/subscriptions/subscriptions.js.map +1 -0
- package/dist/src/app/charts/tooltips/BarPlotTooltipContent.d.ts +90 -0
- package/dist/src/app/charts/tooltips/BarPlotTooltipContent.js +302 -0
- package/dist/src/app/charts/tooltips/BarPlotTooltipContent.js.map +1 -0
- package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.d.ts +100 -0
- package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.js +190 -0
- package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.js.map +1 -0
- package/dist/src/app/charts/{RasterPlotTooltipContent.js → tooltips/RasterPlotTooltipContent.js} +40 -44
- package/dist/src/app/charts/tooltips/RasterPlotTooltipContent.js.map +1 -0
- package/dist/src/app/charts/tooltips/ScatterPlotTooltipContent.js +154 -0
- package/dist/src/app/charts/tooltips/ScatterPlotTooltipContent.js.map +1 -0
- package/dist/src/app/charts/{Tooltip.d.ts → tooltips/Tooltip.d.ts} +4 -2
- package/dist/src/app/charts/{Tooltip.js → tooltips/Tooltip.js} +23 -28
- package/dist/src/app/charts/tooltips/Tooltip.js.map +1 -0
- package/dist/src/app/charts/{tooltipUtils.d.ts → tooltips/tooltipUtils.d.ts} +17 -11
- package/dist/src/app/charts/{tooltipUtils.js → tooltips/tooltipUtils.js} +52 -25
- package/dist/src/app/charts/tooltips/tooltipUtils.js.map +1 -0
- package/dist/src/app/charts/{Tracker.d.ts → trackers/Tracker.d.ts} +6 -5
- package/dist/src/app/charts/trackers/Tracker.js +60 -0
- package/dist/src/app/charts/trackers/Tracker.js.map +1 -0
- package/dist/src/app/charts/{trackerUtils.d.ts → trackers/trackerUtils.d.ts} +13 -8
- package/dist/src/app/charts/trackers/trackerUtils.js +359 -0
- package/dist/src/app/charts/trackers/trackerUtils.js.map +1 -0
- package/dist/src/app/charts/utils.d.ts +22 -32
- package/dist/src/app/charts/utils.js +36 -37
- package/dist/src/app/charts/utils.js.map +1 -1
- package/dist/src/index.d.ts +48 -15
- package/dist/src/index.js +71 -15
- package/dist/src/index.js.map +1 -1
- package/package.json +30 -20
- package/src/app/charts/Chart.tsx +334 -0
- package/src/app/charts/axes/AxesState.test.ts +34 -0
- package/src/app/charts/axes/AxesState.ts +112 -0
- package/src/app/charts/axes/AxisInterval.test.ts +143 -0
- package/src/app/charts/axes/AxisInterval.ts +139 -0
- package/src/app/charts/axes/BaseAxisRange.ts +113 -0
- package/src/app/charts/axes/ContinuousAxis.tsx +192 -0
- package/src/app/charts/axes/ContinuousAxisRange.test.ts +55 -0
- package/src/app/charts/axes/ContinuousAxisRange.ts +96 -0
- package/src/app/charts/axes/OrdinalAxis.tsx +223 -0
- package/src/app/charts/axes/OrdinalAxisRange.test.ts +55 -0
- package/src/app/charts/axes/OrdinalAxisRange.ts +112 -0
- package/src/app/charts/axes/axes.ts +1569 -0
- package/src/app/charts/d3types.ts +16 -0
- package/src/app/charts/filters/regexFilter.test.ts +13 -0
- package/src/app/charts/filters/regexFilter.ts +17 -0
- package/src/app/charts/hooks/useAxes.tsx +341 -0
- package/src/app/charts/hooks/useChart.tsx +159 -0
- package/src/app/charts/hooks/useDataObservable.tsx +175 -0
- package/src/app/charts/hooks/useInitialData.tsx +65 -0
- package/src/app/charts/hooks/useMouse.tsx +125 -0
- package/src/app/charts/hooks/usePlotDimensions.tsx +120 -0
- package/src/app/charts/hooks/useTooltip.tsx +112 -0
- package/src/app/charts/observables/ChartData.ts +31 -0
- package/src/app/charts/observables/iterates.test.ts +201 -0
- package/src/app/charts/observables/iterates.ts +203 -0
- package/src/app/charts/observables/ordinals.test.ts +135 -0
- package/src/app/charts/observables/ordinals.ts +248 -0
- package/src/app/charts/plots/BarPlot.tsx +1088 -0
- package/src/app/charts/plots/PoincarePlot.tsx +832 -0
- package/src/app/charts/plots/RasterPlot.tsx +676 -0
- package/src/app/charts/plots/ScatterPlot.tsx +653 -0
- package/src/app/charts/plots/plot.ts +75 -0
- package/src/app/charts/series/baseSeries.ts +52 -0
- package/src/app/charts/series/datumSeries.test.ts +60 -0
- package/src/app/charts/series/iterateSeries.ts +56 -0
- package/src/app/charts/series/ordinalSeries.ts +164 -0
- package/src/app/charts/series/timeSeries.ts +40 -0
- package/src/app/charts/series/timeSeriesChartData.ts +68 -0
- package/src/app/charts/styling/barPlotStyle.ts +126 -0
- package/src/app/charts/styling/margins.test.ts +22 -0
- package/src/app/charts/styling/margins.ts +58 -0
- package/src/app/charts/styling/svgStyle.ts +118 -0
- package/src/app/charts/subscriptions/subscription.test.ts +499 -0
- package/src/app/charts/subscriptions/subscriptions.ts +635 -0
- package/src/app/charts/tooltips/BarPlotTooltipContent.tsx +440 -0
- package/src/app/charts/tooltips/PoincarePlotTooltipContent.tsx +352 -0
- package/src/app/charts/tooltips/RasterPlotTooltipContent.tsx +274 -0
- package/src/app/charts/tooltips/ScatterPlotTooltipContent.tsx +319 -0
- package/src/app/charts/tooltips/Tooltip.tsx +148 -0
- package/src/app/charts/tooltips/tooltipUtils.ts +216 -0
- package/src/app/charts/trackers/Tracker.tsx +129 -0
- package/src/app/charts/trackers/trackerUtils.ts +494 -0
- package/src/app/charts/utils.ts +109 -0
- package/dist/src/app/charts/CategoryAxis.d.ts +0 -20
- package/dist/src/app/charts/CategoryAxis.js +0 -112
- package/dist/src/app/charts/CategoryAxis.js.map +0 -1
- package/dist/src/app/charts/ContinuousAxis.d.ts +0 -16
- package/dist/src/app/charts/ContinuousAxis.js +0 -186
- package/dist/src/app/charts/ContinuousAxis.js.map +0 -1
- package/dist/src/app/charts/RasterPlot.js.map +0 -1
- package/dist/src/app/charts/RasterPlotTooltipContent.js.map +0 -1
- package/dist/src/app/charts/ScatterPlot.js +0 -351
- package/dist/src/app/charts/ScatterPlot.js.map +0 -1
- package/dist/src/app/charts/ScatterPlotTooltipContent.js +0 -163
- package/dist/src/app/charts/ScatterPlotTooltipContent.js.map +0 -1
- package/dist/src/app/charts/Tooltip.js.map +0 -1
- package/dist/src/app/charts/Tracker.js +0 -65
- package/dist/src/app/charts/Tracker.js.map +0 -1
- package/dist/src/app/charts/axes.d.ts +0 -132
- package/dist/src/app/charts/axes.js +0 -265
- package/dist/src/app/charts/axes.js.map +0 -1
- package/dist/src/app/charts/chartData.js +0 -32
- package/dist/src/app/charts/chartData.js.map +0 -1
- package/dist/src/app/charts/continuousAxisRangeFor.d.ts +0 -20
- package/dist/src/app/charts/continuousAxisRangeFor.js +0 -68
- package/dist/src/app/charts/continuousAxisRangeFor.js.map +0 -1
- package/dist/src/app/charts/datumSeries.d.ts +0 -59
- package/dist/src/app/charts/datumSeries.js +0 -55
- package/dist/src/app/charts/datumSeries.js.map +0 -1
- package/dist/src/app/charts/datumSeries.test.js +0 -50
- package/dist/src/app/charts/datumSeries.test.js.map +0 -1
- package/dist/src/app/charts/hooks/AxesState.d.ts +0 -37
- package/dist/src/app/charts/hooks/AxesState.js +0 -44
- package/dist/src/app/charts/hooks/AxesState.js.map +0 -1
- package/dist/src/app/charts/margins.js.map +0 -1
- package/dist/src/app/charts/margins.test.js +0 -14
- package/dist/src/app/charts/margins.test.js.map +0 -1
- package/dist/src/app/charts/plot.js.map +0 -1
- package/dist/src/app/charts/regexFilter.d.ts +0 -9
- package/dist/src/app/charts/regexFilter.js +0 -17
- package/dist/src/app/charts/regexFilter.js.map +0 -1
- package/dist/src/app/charts/regexFilter.test.js +0 -11
- package/dist/src/app/charts/regexFilter.test.js.map +0 -1
- package/dist/src/app/charts/subscriptions.d.ts +0 -43
- package/dist/src/app/charts/subscriptions.js +0 -213
- package/dist/src/app/charts/subscriptions.js.map +0 -1
- package/dist/src/app/charts/svgStyle.d.ts +0 -27
- package/dist/src/app/charts/svgStyle.js +0 -32
- package/dist/src/app/charts/svgStyle.js.map +0 -1
- package/dist/src/app/charts/timeRange.test.js +0 -54
- package/dist/src/app/charts/timeRange.test.js.map +0 -1
- package/dist/src/app/charts/tooltipUtils.js.map +0 -1
- package/dist/src/app/charts/trackerUtils.js +0 -130
- package/dist/src/app/charts/trackerUtils.js.map +0 -1
- /package/dist/src/app/charts/{datumSeries.test.d.ts → axes/AxesState.test.d.ts} +0 -0
- /package/dist/src/app/charts/{margins.test.d.ts → axes/AxisInterval.test.d.ts} +0 -0
- /package/dist/src/app/charts/{regexFilter.test.d.ts → axes/ContinuousAxisRange.test.d.ts} +0 -0
- /package/dist/src/app/charts/{timeRange.test.d.ts → axes/OrdinalAxisRange.test.d.ts} +0 -0
- /package/dist/src/app/charts/{RasterPlotTooltipContent.d.ts → tooltips/RasterPlotTooltipContent.d.ts} +0 -0
- /package/dist/src/app/charts/{ScatterPlotTooltipContent.d.ts → tooltips/ScatterPlotTooltipContent.d.ts} +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Margin information
|
|
3
|
+
*/
|
|
4
|
+
export interface Margin {
|
|
5
|
+
top: number
|
|
6
|
+
right: number
|
|
7
|
+
bottom: number
|
|
8
|
+
left: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function noMargins(): Margin {
|
|
12
|
+
return {top: 0, bottom: 0, left: 0, right: 0}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface Dimensions {
|
|
16
|
+
readonly width: number
|
|
17
|
+
readonly height: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Given the dimensions of the plot (width, height) based on the container's width and height,
|
|
22
|
+
* and the plot's margins. Calculates the dimensions of the actual plot by subtracting the margins.
|
|
23
|
+
* @param containerWidth The overall width of the container (plot and margins)
|
|
24
|
+
* @param containerHeight The overall height of the container (plot and margins)
|
|
25
|
+
* @param plotMargins The margins around the plot (top, bottom, left, right)
|
|
26
|
+
* @return The dimensions of the actual plots adjusted for the margins
|
|
27
|
+
* from the overall dimensions
|
|
28
|
+
* @see containerDimensionsFrom
|
|
29
|
+
*/
|
|
30
|
+
export function plotDimensionsFrom(containerWidth: number, containerHeight: number, plotMargins: Margin): Dimensions {
|
|
31
|
+
return {
|
|
32
|
+
width: containerWidth - plotMargins.left - plotMargins.right,
|
|
33
|
+
height: containerHeight - plotMargins.top - plotMargins.bottom
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Calculates the container's dimensions from the plot dimensions and the plot margin. The container
|
|
39
|
+
* dimensions are the plot dimensions plus the margins.
|
|
40
|
+
* @param plotDimensions The (width, height) of the plot
|
|
41
|
+
* @param plotMargin The margins around the plot
|
|
42
|
+
* @return The container dimensions.
|
|
43
|
+
* @see plotDimensionsFrom
|
|
44
|
+
*/
|
|
45
|
+
export function containerDimensionsFrom(plotDimensions: Dimensions, plotMargin: Margin): Dimensions {
|
|
46
|
+
return {
|
|
47
|
+
width: plotDimensions.width + plotMargin.left + plotMargin.right,
|
|
48
|
+
height: plotDimensions.height + plotMargin.top + plotMargin.bottom
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function dimensionsEqual(dimension1: Dimensions, dimension2: Dimensions) {
|
|
53
|
+
return dimension1.height === dimension2.height && dimension1.width === dimension2.width
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function dimensionsNotEqual(dimension1: Dimensions, dimension2: Dimensions) {
|
|
57
|
+
return !dimensionsEqual(dimension1, dimension2)
|
|
58
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as d3 from "d3";
|
|
2
|
+
import {BaseType} from "d3";
|
|
3
|
+
|
|
4
|
+
export interface SvgStyle {
|
|
5
|
+
height?: string | number;
|
|
6
|
+
width?: string | number;
|
|
7
|
+
outline?: string;
|
|
8
|
+
|
|
9
|
+
[propName: string]: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const initialSvgStyle: SvgStyle = {
|
|
13
|
+
width: '100%',
|
|
14
|
+
// display: "inline-block",
|
|
15
|
+
// position: "floating",
|
|
16
|
+
top: 0,
|
|
17
|
+
left: 0
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Grabs the client-width of the svg element, or 1 if the svg element hasn't yet
|
|
22
|
+
* been initialized. The client-width is a read-only property returns the width of
|
|
23
|
+
* the html element, including horizontal padding and borders, as an integer. The reason
|
|
24
|
+
* that we return 1 when the svg element hasn't yet been initialized, is so that the
|
|
25
|
+
* aspect (width / height) is 1.
|
|
26
|
+
* @param {SVGElement | null} svg The svg element
|
|
27
|
+
* @return {number} The client width of the svg
|
|
28
|
+
*/
|
|
29
|
+
export function grabWidth(svg: SVGElement | null): number {
|
|
30
|
+
return svg !== null ? svg.clientWidth : 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Grabs the client-height of the svg element, or 1 if the svg element hasn't yet
|
|
35
|
+
* been initialized. The client-height is a read-only property returns the height of
|
|
36
|
+
* the html element, including vertical padding and borders, as an integer. The reason
|
|
37
|
+
* that we return 1 when the svg element hasn't yet been initialized, is so that the
|
|
38
|
+
* aspect (width / height) is 1.
|
|
39
|
+
* @param {SVGElement | null} svg The svg element
|
|
40
|
+
* @return {number} The client height of the svg
|
|
41
|
+
*/
|
|
42
|
+
export function grabHeight(svg: SVGElement | null): number {
|
|
43
|
+
return svg !== null ? svg.clientHeight : 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
export const STROKE_COLOR: string = "stroke"
|
|
48
|
+
export const STROKE_WIDTH: string = "stroke-width"
|
|
49
|
+
export const STROKE_OPACITY: string = "stroke-opacity"
|
|
50
|
+
|
|
51
|
+
export interface SvgStrokeStyle {
|
|
52
|
+
readonly color: string
|
|
53
|
+
readonly width: number
|
|
54
|
+
readonly opacity: number
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function updateSvgStrokeColor(current: SvgStrokeStyle, color: string) {
|
|
58
|
+
return {...current, color};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function updateSvgStrokeWidth(current: SvgStrokeStyle, width: number) {
|
|
62
|
+
return {...current, width};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function updateSvgStrokeOpacity(current: SvgStrokeStyle, opacity: number) {
|
|
66
|
+
return {...current, opacity};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @param style
|
|
72
|
+
* @param selection
|
|
73
|
+
* @template E The SVG element (e.g. SVGRectElement, SVGLineElement, etc)
|
|
74
|
+
* @template D The datum type
|
|
75
|
+
* @template The SVG G element
|
|
76
|
+
*/
|
|
77
|
+
export function applyStrokeStylesTo<E extends BaseType, D, G extends BaseType = SVGGElement>(
|
|
78
|
+
selection: d3.Selection<E, D, G, any>,
|
|
79
|
+
style: Partial<SvgStrokeStyle>
|
|
80
|
+
): d3.Selection<E, D, G, any> {
|
|
81
|
+
if (style.color !== undefined) selection.style(STROKE_COLOR, style.color)
|
|
82
|
+
if (style.width !== undefined) selection.style(STROKE_WIDTH, style.width)
|
|
83
|
+
if (style.opacity !== undefined) selection.style(STROKE_OPACITY, style.opacity)
|
|
84
|
+
return selection
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const FILL_COLOR: string = "fill"
|
|
88
|
+
const FILL_OPACITY: string = "fill-opacity"
|
|
89
|
+
|
|
90
|
+
export interface SvgFillStyle {
|
|
91
|
+
readonly color: string
|
|
92
|
+
readonly opacity: number
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function updateSvgFillColor(current: SvgFillStyle, color: string): SvgFillStyle {
|
|
96
|
+
return {...current, color}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function updateSvgFillOpacity(current: SvgFillStyle, opacity: number): SvgFillStyle {
|
|
100
|
+
return {...current, opacity}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param style
|
|
106
|
+
* @param selection
|
|
107
|
+
* @template E The SVG element (e.g. SVGRectElement, SVGLineElement, etc)
|
|
108
|
+
* @template D The datum type
|
|
109
|
+
* @template The SVG G element
|
|
110
|
+
*/
|
|
111
|
+
export function applyFillStylesTo<E extends BaseType, D, G extends BaseType = SVGGElement>(
|
|
112
|
+
selection: d3.Selection<E, D, G, any>,
|
|
113
|
+
style: Partial<SvgFillStyle>
|
|
114
|
+
): d3.Selection<E, D, G, any> {
|
|
115
|
+
if (style.color !== undefined) selection.style(FILL_COLOR, style.color)
|
|
116
|
+
if (style.opacity !== undefined) selection.style(FILL_OPACITY, style.opacity)
|
|
117
|
+
return selection
|
|
118
|
+
}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import {filter, map, scan} from 'rxjs/operators';
|
|
2
|
+
import {Observable, range} from 'rxjs';
|
|
3
|
+
import {IterateChartData, iteratesObservable as iterateObservable} from '../observables/iterates'
|
|
4
|
+
import {TimeSeriesChartData} from "../series/timeSeriesChartData";
|
|
5
|
+
import {datumOf} from "../series/timeSeries";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
type Point = {
|
|
9
|
+
x: number
|
|
10
|
+
y: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const pointFrom = (x: number, y: number): Point => ({x, y})
|
|
14
|
+
const emptyPoint = (): Point => ({x: NaN, y: NaN})
|
|
15
|
+
const isEmptyPoint = (point?: Point): boolean => point === undefined || (isNaN(point.x) && isNaN(point.y))
|
|
16
|
+
const nonEmptyPoint = (point?: Point): boolean => !isEmptyPoint(point)
|
|
17
|
+
|
|
18
|
+
type Accumulate = {
|
|
19
|
+
// n-difference, which is the number of points between successive differences
|
|
20
|
+
n: number
|
|
21
|
+
// holds the previous n point (for successive-n differences)
|
|
22
|
+
previous: Array<Point>
|
|
23
|
+
// the current successive-n difference
|
|
24
|
+
difference?: Point
|
|
25
|
+
}
|
|
26
|
+
const initialAccumulate = (n: number = 1): Accumulate => ({n, previous: []})
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Source for {@link Point} data that generates `x`-values from a range of 1 to `numPoints` and
|
|
30
|
+
* creates the `y`-values by applying the `valueFn` to those `x`-values.
|
|
31
|
+
* @param numPoints The number of points to generate
|
|
32
|
+
* @param valueFn The function that maps `x` to `y` (i.e. the value function is `f(x)` in `y = f(x)`)
|
|
33
|
+
* @return an observable of {@link Point}
|
|
34
|
+
*/
|
|
35
|
+
function pointsObservable(numPoints: number = 10, valueFn: (x: number) => number): Observable<Point> {
|
|
36
|
+
return range(1, numPoints).pipe(map(value => pointFrom(value, valueFn(value))))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param n The number of points back from which to calculate the `n-difference`
|
|
42
|
+
* @param dataObservable Observable that is the source of the underlying data
|
|
43
|
+
* @param useStartX Whether to use the x-value from the beginning of the interval as the x-value
|
|
44
|
+
* for the difference (default), or whether to use the last x-value in the interval.
|
|
45
|
+
*/
|
|
46
|
+
function successiveDiffsObservable(
|
|
47
|
+
n: number = 1,
|
|
48
|
+
dataObservable: Observable<Point>,
|
|
49
|
+
useStartX: boolean = true
|
|
50
|
+
): Observable<Point> {
|
|
51
|
+
return dataObservable
|
|
52
|
+
.pipe(
|
|
53
|
+
scan(({n, previous,}, current) => {
|
|
54
|
+
// when we have accumulated enough previous values to cover the "n-difference",
|
|
55
|
+
// we can calculate an actual difference
|
|
56
|
+
if (previous.length >= n) {
|
|
57
|
+
// add the new point, and take the first point from the beginning
|
|
58
|
+
previous.push(current)
|
|
59
|
+
const first: Point = previous.shift() || emptyPoint()
|
|
60
|
+
|
|
61
|
+
// calculate the n-difference, using the x-value of the initial point (default)
|
|
62
|
+
// or the current point (end of current time-range
|
|
63
|
+
const difference = pointFrom(
|
|
64
|
+
useStartX ? first.x : current.x,
|
|
65
|
+
current.y - first.y
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return {n, previous, difference}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// not enough points yet, so just accumulate the current point
|
|
72
|
+
previous.push(current)
|
|
73
|
+
|
|
74
|
+
return {n, previous}
|
|
75
|
+
|
|
76
|
+
}, initialAccumulate(n)),
|
|
77
|
+
filter(accum => nonEmptyPoint(accum.difference)),
|
|
78
|
+
map(accum => accum.difference === undefined ? emptyPoint() : accum.difference)
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe('should be able to calculate successive differences', () => {
|
|
83
|
+
|
|
84
|
+
test('should be able to calc successive-diffs for x^2 where x is in 1..10', done => {
|
|
85
|
+
let results: Array<Point> = []
|
|
86
|
+
successiveDiffsObservable(1, pointsObservable(10, x => x * x), true).subscribe(point => results.push(point))
|
|
87
|
+
done()
|
|
88
|
+
expect(results).toHaveLength(9)
|
|
89
|
+
expect(results).toEqual([
|
|
90
|
+
{x: 1, y: 3},
|
|
91
|
+
{x: 2, y: 5},
|
|
92
|
+
{x: 3, y: 7},
|
|
93
|
+
{x: 4, y: 9},
|
|
94
|
+
{x: 5, y: 11},
|
|
95
|
+
{x: 6, y: 13},
|
|
96
|
+
{x: 7, y: 15},
|
|
97
|
+
{x: 8, y: 17},
|
|
98
|
+
{x: 9, y: 19},
|
|
99
|
+
])
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('should be able to calc successive-diffs for x^2 where x is in 1..10 using interval end', done => {
|
|
103
|
+
let results: Array<Point> = []
|
|
104
|
+
successiveDiffsObservable(1, pointsObservable(10, x => x * x), false).subscribe(point => results.push(point))
|
|
105
|
+
done()
|
|
106
|
+
expect(results).toHaveLength(9)
|
|
107
|
+
expect(results).toEqual([
|
|
108
|
+
{x: 2, y: 3},
|
|
109
|
+
{x: 3, y: 5},
|
|
110
|
+
{x: 4, y: 7},
|
|
111
|
+
{x: 5, y: 9},
|
|
112
|
+
{x: 6, y: 11},
|
|
113
|
+
{x: 7, y: 13},
|
|
114
|
+
{x: 8, y: 15},
|
|
115
|
+
{x: 9, y: 17},
|
|
116
|
+
{x: 10, y: 19},
|
|
117
|
+
])
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('should be able to calc 3-diffs for x^2 where x is in 1..10', done => {
|
|
121
|
+
let results: Array<Point> = []
|
|
122
|
+
successiveDiffsObservable(3, pointsObservable(10, x => x * x), true).subscribe(point => results.push(point))
|
|
123
|
+
done()
|
|
124
|
+
expect(results).toHaveLength(7)
|
|
125
|
+
expect(results).toEqual([
|
|
126
|
+
{x: 1, y: 15},
|
|
127
|
+
{x: 2, y: 21},
|
|
128
|
+
{x: 3, y: 27},
|
|
129
|
+
{x: 4, y: 33},
|
|
130
|
+
{x: 5, y: 39},
|
|
131
|
+
{x: 6, y: 45},
|
|
132
|
+
{x: 7, y: 51},
|
|
133
|
+
])
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('should be able to calc 3-diffs for x^2 where x is in 1..10 using interval end', done => {
|
|
137
|
+
let results: Array<Point> = []
|
|
138
|
+
successiveDiffsObservable(3, pointsObservable(10, x => x * x), false).subscribe(point => results.push(point))
|
|
139
|
+
done()
|
|
140
|
+
expect(results).toHaveLength(7)
|
|
141
|
+
expect(results).toEqual([
|
|
142
|
+
{x: 4, y: 15},
|
|
143
|
+
{x: 5, y: 21},
|
|
144
|
+
{x: 6, y: 27},
|
|
145
|
+
{x: 7, y: 33},
|
|
146
|
+
{x: 8, y: 39},
|
|
147
|
+
{x: 9, y: 45},
|
|
148
|
+
{x: 10, y: 51},
|
|
149
|
+
])
|
|
150
|
+
});
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Observable that converts data points into iterates for poincare plots where one plots x(j+n) vs x(j)
|
|
155
|
+
* @param n The n-th iterate for plotting x(j+n) vs x(j)
|
|
156
|
+
* @param dataObservable The observable with the point data
|
|
157
|
+
* @return an observable of a stream of {@link Point}s
|
|
158
|
+
*/
|
|
159
|
+
function iteratesObservable(n: number = 1, dataObservable: Observable<Point>): Observable<Point> {
|
|
160
|
+
return dataObservable
|
|
161
|
+
.pipe(
|
|
162
|
+
scan(({n, previous,}, current) => {
|
|
163
|
+
// when we have accumulated enough previous values to cover the "n-iterate",
|
|
164
|
+
// we can grab the y-value from the n-th point back
|
|
165
|
+
if (previous.length >= n) {
|
|
166
|
+
// add the new point, and take the first point from the beginning
|
|
167
|
+
previous.push(pointFrom(previous[previous.length - 1].y, current.y))
|
|
168
|
+
const first: Point = previous.shift() || emptyPoint()
|
|
169
|
+
|
|
170
|
+
// calculate the n-difference, using the x-value of the initial point (default)
|
|
171
|
+
// or the current point (end of current time-range
|
|
172
|
+
const iterate = pointFrom(first.y, current.y)
|
|
173
|
+
|
|
174
|
+
return {n, previous, difference: iterate}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// not enough points yet, so just accumulate the current point
|
|
178
|
+
previous.push(current)
|
|
179
|
+
|
|
180
|
+
return {n, previous}
|
|
181
|
+
|
|
182
|
+
}, initialAccumulate(n)),
|
|
183
|
+
filter(accum => nonEmptyPoint(accum.difference)),
|
|
184
|
+
map(accum => accum.difference === undefined ? emptyPoint() : accum.difference)
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function tentFn(x: number, mu: number = 1): number {
|
|
189
|
+
return x < 0.5 ? mu * x : mu * (1 - x)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
describe('should be able to calculate iterates', () => {
|
|
193
|
+
|
|
194
|
+
test('should be able to calc 1-iterates for x^2 where x is in 1..10', done => {
|
|
195
|
+
let results: Array<Point> = []
|
|
196
|
+
iteratesObservable(1, pointsObservable(10, x => 2 * x)).subscribe(point => results.push(point))
|
|
197
|
+
done()
|
|
198
|
+
expect(results).toHaveLength(9)
|
|
199
|
+
expect(results).toEqual([
|
|
200
|
+
{x: 2, y: 4},
|
|
201
|
+
{x: 4, y: 6},
|
|
202
|
+
{x: 6, y: 8},
|
|
203
|
+
{x: 8, y: 10},
|
|
204
|
+
{x: 10, y: 12},
|
|
205
|
+
{x: 12, y: 14},
|
|
206
|
+
{x: 14, y: 16},
|
|
207
|
+
{x: 16, y: 18},
|
|
208
|
+
{x: 18, y: 20}
|
|
209
|
+
])
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('should be able to calc 3-iterates for x^2 where x is in 1..10', done => {
|
|
213
|
+
let results: Array<Point> = []
|
|
214
|
+
iteratesObservable(3, pointsObservable(10, x => 2 * x)).subscribe(point => results.push(point))
|
|
215
|
+
done()
|
|
216
|
+
expect(results).toHaveLength(7)
|
|
217
|
+
expect(results).toEqual([
|
|
218
|
+
{x: 2, y: 8},
|
|
219
|
+
{x: 4, y: 10},
|
|
220
|
+
{x: 6, y: 12},
|
|
221
|
+
{x: 8, y: 14},
|
|
222
|
+
{x: 10, y: 16},
|
|
223
|
+
{x: 12, y: 18},
|
|
224
|
+
{x: 14, y: 20}
|
|
225
|
+
])
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
test('tent map should converge to (0, 0) for mu < 1', done => {
|
|
230
|
+
const numPoints = 100000
|
|
231
|
+
let lastPoint = emptyPoint()
|
|
232
|
+
|
|
233
|
+
iteratesObservable(1, range(0, numPoints).pipe(map(x => pointFrom(x, tentFn(x / numPoints, 0.15)))))
|
|
234
|
+
.subscribe(point => lastPoint = point)
|
|
235
|
+
|
|
236
|
+
done()
|
|
237
|
+
expect(lastPoint.y).toBeLessThan(1e-5)
|
|
238
|
+
expect(lastPoint.x).toBeLessThan(1e-5)
|
|
239
|
+
})
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
describe('when calculating tent-map iterates with one new data point for each event', () => {
|
|
243
|
+
|
|
244
|
+
test('should be able to calc 1-iterates for tent-map chart data, when 1 point is added at a time', done => {
|
|
245
|
+
const numPoints = 10
|
|
246
|
+
let results: Array<IterateChartData> = []
|
|
247
|
+
iterateObservable(
|
|
248
|
+
range(0, numPoints).pipe(
|
|
249
|
+
map(x => ({
|
|
250
|
+
maxTime: x,
|
|
251
|
+
maxTimes: new Map([['test1', x]]),
|
|
252
|
+
newPoints: new Map([['test1', [datumOf(x, tentFn(x / numPoints, 0.15))]]])
|
|
253
|
+
} as TimeSeriesChartData))
|
|
254
|
+
)).subscribe(point => results.push(point));
|
|
255
|
+
done()
|
|
256
|
+
expect(results).toHaveLength(9)
|
|
257
|
+
|
|
258
|
+
//
|
|
259
|
+
// check the first iterate datum
|
|
260
|
+
expect(results[0].minIterate.iterateN).toEqual(0)
|
|
261
|
+
expect(results[0].minIterate.iterateN_1).toEqual(0.015)
|
|
262
|
+
expect(results[0].maxIterate.iterateN).toEqual(0)
|
|
263
|
+
expect(results[0].maxIterate.iterateN_1).toEqual(0.015)
|
|
264
|
+
|
|
265
|
+
expect(results[0].minIterates.has("test1")).toBe(true)
|
|
266
|
+
expect(results[0].minIterates.size).toEqual(1)
|
|
267
|
+
expect(results[0].minIterates.get("test1")!.time).toEqual(0)
|
|
268
|
+
expect(results[0].minIterates.get("test1")!.iterateN).toEqual(0)
|
|
269
|
+
expect(results[0].minIterates.get("test1")!.iterateN_1).toEqual(0.015)
|
|
270
|
+
|
|
271
|
+
expect(results[0].maxIterates.has("test1")).toBe(true)
|
|
272
|
+
expect(results[0].maxIterates.size).toEqual(1)
|
|
273
|
+
expect(results[0].maxIterates.get("test1")!.time).toEqual(0)
|
|
274
|
+
expect(results[0].maxIterates.get("test1")!.iterateN).toBeCloseTo(0, 4)
|
|
275
|
+
expect(results[0].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
276
|
+
|
|
277
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
278
|
+
expect(results[0].newPoints.has("test1")).toBe(true)
|
|
279
|
+
expect(results[0].newPoints.get("test1")).toHaveLength(1)
|
|
280
|
+
expect(results[0].newPoints.get("test1")![0].time).toEqual(0)
|
|
281
|
+
expect(results[0].newPoints.get("test1")![0].iterateN).toEqual(0)
|
|
282
|
+
expect(results[0].newPoints.get("test1")![0].iterateN_1).toBeCloseTo(0.015, 4)
|
|
283
|
+
|
|
284
|
+
//
|
|
285
|
+
// check the last iterate datum
|
|
286
|
+
expect(results[8].minIterate.time).toEqual(8)
|
|
287
|
+
expect(results[8].minIterate.iterateN).toEqual(0)
|
|
288
|
+
expect(results[8].minIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
289
|
+
|
|
290
|
+
expect(results[8].maxIterate.time).toEqual(5)
|
|
291
|
+
expect(results[8].maxIterate.iterateN).toBeCloseTo(0.075, 4)
|
|
292
|
+
expect(results[8].maxIterate.iterateN_1).toBeCloseTo(0.075, 4)
|
|
293
|
+
|
|
294
|
+
expect(results[8].minIterates.has("test1")).toBe(true)
|
|
295
|
+
expect(results[8].minIterates.size).toEqual(1)
|
|
296
|
+
expect(results[8].minIterates.get("test1")!.time).toEqual(8)
|
|
297
|
+
expect(results[8].minIterates.get("test1")!.iterateN).toEqual(0)
|
|
298
|
+
expect(results[8].minIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
299
|
+
|
|
300
|
+
expect(results[8].maxIterates.has("test1")).toBe(true)
|
|
301
|
+
expect(results[8].maxIterates.size).toEqual(1)
|
|
302
|
+
expect(results[8].maxIterates.get("test1")!.time).toEqual(5)
|
|
303
|
+
expect(results[8].maxIterates.get("test1")!.iterateN).toBeCloseTo(0.075, 4)
|
|
304
|
+
expect(results[8].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.075, 4)
|
|
305
|
+
|
|
306
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
307
|
+
expect(results[8].newPoints.has("test1")).toBe(true)
|
|
308
|
+
expect(results[8].newPoints.get("test1")).toHaveLength(1)
|
|
309
|
+
expect(results[8].newPoints.get("test1")![0].time).toEqual(8)
|
|
310
|
+
expect(results[8].newPoints.get("test1")![0].iterateN).toBeCloseTo(0.03, 4)
|
|
311
|
+
expect(results[8].newPoints.get("test1")![0].iterateN_1).toBeCloseTo(0.015, 4)
|
|
312
|
+
});
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
describe('when calculating tent-map 1-iterates with two new data points for each event', () => {
|
|
316
|
+
|
|
317
|
+
test('should be able to calc iterates for tent-map chart data, when 2 points are added at a time', done => {
|
|
318
|
+
const numPoints = 5
|
|
319
|
+
let results: Array<IterateChartData> = []
|
|
320
|
+
iterateObservable(
|
|
321
|
+
range(0, numPoints)
|
|
322
|
+
.pipe(
|
|
323
|
+
map(x => ({
|
|
324
|
+
maxTime: 2 * x,
|
|
325
|
+
maxTimes: new Map([['test1', 2 * x]]),
|
|
326
|
+
newPoints: new Map([
|
|
327
|
+
['test1', [datumOf(2 * x, tentFn(2 * x / (2 * numPoints), 0.15)), datumOf(2 * x + 1, tentFn((2 * x + 1) / (2 * numPoints), 0.15))]],
|
|
328
|
+
])
|
|
329
|
+
} as TimeSeriesChartData))
|
|
330
|
+
))
|
|
331
|
+
.subscribe(result => results.push(result));
|
|
332
|
+
done()
|
|
333
|
+
expect(results).toHaveLength(5)
|
|
334
|
+
expect(results.reduce((count, result) => result.newPoints.get("test1")!.length + count, 0)).toEqual(9)
|
|
335
|
+
|
|
336
|
+
//
|
|
337
|
+
// check the first iterate datum
|
|
338
|
+
expect(results[0].minIterate.iterateN).toBeCloseTo(0, 4)
|
|
339
|
+
expect(results[0].minIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
340
|
+
expect(results[0].maxIterate.iterateN).toBeCloseTo(0, 4)
|
|
341
|
+
expect(results[0].maxIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
342
|
+
|
|
343
|
+
expect(results[0].minIterates.has("test1")).toBe(true)
|
|
344
|
+
expect(results[0].minIterates.size).toEqual(1)
|
|
345
|
+
expect(results[0].minIterates.get("test1")!.time).toBeCloseTo(0, 4)
|
|
346
|
+
expect(results[0].minIterates.get("test1")!.iterateN).toBeCloseTo(0, 4)
|
|
347
|
+
expect(results[0].minIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
348
|
+
|
|
349
|
+
expect(results[0].maxIterates.has("test1")).toBe(true)
|
|
350
|
+
expect(results[0].maxIterates.size).toEqual(1)
|
|
351
|
+
expect(results[0].maxIterates.get("test1")!.time).toEqual(0)
|
|
352
|
+
expect(results[0].maxIterates.get("test1")!.iterateN).toBeCloseTo(0, 4)
|
|
353
|
+
expect(results[0].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
354
|
+
|
|
355
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
356
|
+
expect(results[0].newPoints.has("test1")).toBe(true)
|
|
357
|
+
expect(results[0].newPoints.get("test1")).toHaveLength(1)
|
|
358
|
+
expect(results[0].newPoints.get("test1")![0].time).toEqual(0)
|
|
359
|
+
expect(results[0].newPoints.get("test1")![0].iterateN).toEqual(0)
|
|
360
|
+
expect(results[0].newPoints.get("test1")![0].iterateN_1).toBeCloseTo(0.015, 4)
|
|
361
|
+
|
|
362
|
+
//
|
|
363
|
+
// check the last iterate datum
|
|
364
|
+
expect(results[4].minIterate.time).toEqual(8)
|
|
365
|
+
expect(results[4].minIterate.iterateN).toEqual(0)
|
|
366
|
+
expect(results[4].minIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
367
|
+
|
|
368
|
+
expect(results[4].maxIterate.time).toEqual(5)
|
|
369
|
+
expect(results[4].maxIterate.iterateN).toBeCloseTo(0.075, 4)
|
|
370
|
+
expect(results[4].maxIterate.iterateN_1).toBeCloseTo(0.075, 4)
|
|
371
|
+
|
|
372
|
+
expect(results[4].minIterates.size).toEqual(1)
|
|
373
|
+
expect(results[4].minIterates.has("test1")).toBe(true)
|
|
374
|
+
expect(results[4].minIterates.get("test1")!.time).toEqual(8)
|
|
375
|
+
expect(results[4].minIterates.get("test1")!.iterateN).toEqual(0)
|
|
376
|
+
expect(results[4].minIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
377
|
+
|
|
378
|
+
expect(results[4].maxIterates.size).toEqual(1)
|
|
379
|
+
expect(results[4].maxIterates.has("test1")).toBe(true)
|
|
380
|
+
expect(results[4].maxIterates.get("test1")!.time).toEqual(5)
|
|
381
|
+
expect(results[4].maxIterates.get("test1")!.iterateN).toBeCloseTo(0.075, 4)
|
|
382
|
+
expect(results[4].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.075, 4)
|
|
383
|
+
|
|
384
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
385
|
+
expect(results[4].newPoints.has("test1")).toBe(true)
|
|
386
|
+
expect(results[4].newPoints.get("test1")).toHaveLength(2)
|
|
387
|
+
expect(results[4].newPoints.get("test1")![1].time).toEqual(8)
|
|
388
|
+
expect(results[4].newPoints.get("test1")![1].iterateN).toBeCloseTo(0.03, 4)
|
|
389
|
+
expect(results[4].newPoints.get("test1")![1].iterateN_1).toBeCloseTo(0.015, 4)
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test('should be able to calc iterates for tent-map chart data, when 2 points are added at a time, with 2 series', done => {
|
|
393
|
+
const numPoints = 5
|
|
394
|
+
let results: Array<IterateChartData> = []
|
|
395
|
+
iterateObservable(
|
|
396
|
+
range(0, numPoints)
|
|
397
|
+
.pipe(
|
|
398
|
+
map(x => ({
|
|
399
|
+
maxTime: 2 * x,
|
|
400
|
+
maxTimes: new Map([['test1', 2 * x]]),
|
|
401
|
+
newPoints: new Map([
|
|
402
|
+
['test1', [datumOf(2 * x, tentFn(2 * x / (2 * numPoints), 0.15)), datumOf(2 * x + 1, tentFn((2 * x + 1) / (2 * numPoints), 0.15))]],
|
|
403
|
+
['test2', [datumOf(2 * x, tentFn(2 * x / (2 * numPoints), 0.35)), datumOf(2 * x + 1, tentFn((2 * x + 1) / (2 * numPoints), 0.35))]],
|
|
404
|
+
])
|
|
405
|
+
} as TimeSeriesChartData))
|
|
406
|
+
))
|
|
407
|
+
.subscribe(result => results.push(result));
|
|
408
|
+
done()
|
|
409
|
+
expect(results).toHaveLength(5)
|
|
410
|
+
expect(results.reduce((count, result) => result.newPoints.get("test1")!.length + count, 0)).toEqual(9)
|
|
411
|
+
|
|
412
|
+
//
|
|
413
|
+
// check the first iterate datum
|
|
414
|
+
expect(results[0].minIterate.iterateN).toBeCloseTo(0, 4)
|
|
415
|
+
expect(results[0].minIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
416
|
+
expect(results[0].maxIterate.iterateN).toBeCloseTo(0, 4)
|
|
417
|
+
expect(results[0].maxIterate.iterateN_1).toBeCloseTo(0.035, 4)
|
|
418
|
+
|
|
419
|
+
expect(results[0].minIterates.size).toEqual(2)
|
|
420
|
+
expect(results[0].minIterates.has("test1")).toBe(true)
|
|
421
|
+
expect(results[0].minIterates.get("test1")!.time).toBeCloseTo(0, 4)
|
|
422
|
+
expect(results[0].minIterates.get("test1")!.iterateN).toBeCloseTo(0, 4)
|
|
423
|
+
expect(results[0].minIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
424
|
+
|
|
425
|
+
expect(results[0].minIterates.has("test2")).toBe(true)
|
|
426
|
+
expect(results[0].minIterates.get("test2")!.time).toBeCloseTo(0, 4)
|
|
427
|
+
expect(results[0].minIterates.get("test2")!.iterateN).toBeCloseTo(0, 4)
|
|
428
|
+
expect(results[0].minIterates.get("test2")!.iterateN_1).toBeCloseTo(0.035, 4)
|
|
429
|
+
|
|
430
|
+
expect(results[0].maxIterates.size).toEqual(2)
|
|
431
|
+
expect(results[0].maxIterates.has("test1")).toBe(true)
|
|
432
|
+
expect(results[0].maxIterates.get("test1")!.time).toEqual(0)
|
|
433
|
+
expect(results[0].maxIterates.get("test1")!.iterateN).toBeCloseTo(0, 4)
|
|
434
|
+
expect(results[0].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
435
|
+
|
|
436
|
+
expect(results[0].maxIterates.has("test2")).toBe(true)
|
|
437
|
+
expect(results[0].maxIterates.get("test2")!.time).toEqual(0)
|
|
438
|
+
expect(results[0].maxIterates.get("test2")!.iterateN).toBeCloseTo(0, 4)
|
|
439
|
+
expect(results[0].maxIterates.get("test2")!.iterateN_1).toBeCloseTo(0.035, 4)
|
|
440
|
+
|
|
441
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
442
|
+
expect(results[0].newPoints.has("test1")).toBe(true)
|
|
443
|
+
expect(results[0].newPoints.get("test1")).toHaveLength(1)
|
|
444
|
+
expect(results[0].newPoints.get("test1")![0].time).toEqual(0)
|
|
445
|
+
expect(results[0].newPoints.get("test1")![0].iterateN).toEqual(0)
|
|
446
|
+
expect(results[0].newPoints.get("test1")![0].iterateN_1).toBeCloseTo(0.015, 4)
|
|
447
|
+
|
|
448
|
+
expect(results[0].newPoints.has("test2")).toBe(true)
|
|
449
|
+
expect(results[0].newPoints.get("test2")).toHaveLength(1)
|
|
450
|
+
expect(results[0].newPoints.get("test2")![0].time).toEqual(0)
|
|
451
|
+
expect(results[0].newPoints.get("test2")![0].iterateN).toEqual(0)
|
|
452
|
+
expect(results[0].newPoints.get("test2")![0].iterateN_1).toBeCloseTo(0.035, 4)
|
|
453
|
+
|
|
454
|
+
//
|
|
455
|
+
// check the last iterate datum
|
|
456
|
+
expect(results[4].minIterate.time).toEqual(8)
|
|
457
|
+
expect(results[4].minIterate.iterateN).toEqual(0)
|
|
458
|
+
expect(results[4].minIterate.iterateN_1).toBeCloseTo(0.015, 4)
|
|
459
|
+
|
|
460
|
+
expect(results[4].maxIterate.time).toEqual(5)
|
|
461
|
+
expect(results[4].maxIterate.iterateN).toBeCloseTo(0.175, 4)
|
|
462
|
+
expect(results[4].maxIterate.iterateN_1).toBeCloseTo(0.175, 4)
|
|
463
|
+
|
|
464
|
+
expect(results[4].minIterates.size).toEqual(2)
|
|
465
|
+
expect(results[4].minIterates.has("test1")).toBe(true)
|
|
466
|
+
expect(results[4].minIterates.get("test1")!.time).toEqual(8)
|
|
467
|
+
expect(results[4].minIterates.get("test1")!.iterateN).toEqual(0)
|
|
468
|
+
expect(results[4].minIterates.get("test1")!.iterateN_1).toBeCloseTo(0.015, 4)
|
|
469
|
+
|
|
470
|
+
expect(results[4].minIterates.has("test2")).toBe(true)
|
|
471
|
+
expect(results[4].minIterates.get("test2")!.time).toEqual(8)
|
|
472
|
+
expect(results[4].minIterates.get("test2")!.iterateN).toEqual(0)
|
|
473
|
+
expect(results[4].minIterates.get("test2")!.iterateN_1).toBeCloseTo(0.035, 4)
|
|
474
|
+
|
|
475
|
+
expect(results[4].maxIterates.size).toEqual(2)
|
|
476
|
+
expect(results[4].maxIterates.has("test1")).toBe(true)
|
|
477
|
+
expect(results[4].maxIterates.get("test1")!.time).toEqual(5)
|
|
478
|
+
expect(results[4].maxIterates.get("test1")!.iterateN).toBeCloseTo(0.075, 4)
|
|
479
|
+
expect(results[4].maxIterates.get("test1")!.iterateN_1).toBeCloseTo(0.075, 4)
|
|
480
|
+
|
|
481
|
+
expect(results[4].maxIterates.has("test2")).toBe(true)
|
|
482
|
+
expect(results[4].maxIterates.get("test2")!.time).toEqual(5)
|
|
483
|
+
expect(results[4].maxIterates.get("test2")!.iterateN).toBeCloseTo(0.175, 4)
|
|
484
|
+
expect(results[4].maxIterates.get("test2")!.iterateN_1).toBeCloseTo(0.175, 4)
|
|
485
|
+
|
|
486
|
+
// check that the accumulator "newPoints" holds the previous "newPoints" for the iterate
|
|
487
|
+
expect(results[4].newPoints.has("test1")).toBe(true)
|
|
488
|
+
expect(results[4].newPoints.get("test1")).toHaveLength(2)
|
|
489
|
+
expect(results[4].newPoints.get("test1")![1].time).toEqual(8)
|
|
490
|
+
expect(results[4].newPoints.get("test1")![1].iterateN).toBeCloseTo(0.03, 4)
|
|
491
|
+
expect(results[4].newPoints.get("test1")![1].iterateN_1).toBeCloseTo(0.015, 4)
|
|
492
|
+
|
|
493
|
+
expect(results[4].newPoints.has("test2")).toBe(true)
|
|
494
|
+
expect(results[4].newPoints.get("test2")).toHaveLength(2)
|
|
495
|
+
expect(results[4].newPoints.get("test2")![1].time).toEqual(8)
|
|
496
|
+
expect(results[4].newPoints.get("test2")![1].iterateN).toBeCloseTo(0.07, 4)
|
|
497
|
+
expect(results[4].newPoints.get("test2")![1].iterateN_1).toBeCloseTo(0.035, 4)
|
|
498
|
+
});
|
|
499
|
+
})
|