@@ -12,6 +12,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
See the License for the specific language governing permissions and
13
13
limitations under the License.
14
14
==============================================================================*/
15
+ import * as d3 from '../../third_party/d3' ;
15
16
import {
16
17
DataSeries ,
17
18
DataSeriesMetadataMap ,
@@ -22,44 +23,50 @@ import {isWebGl2Supported} from './lib/utils';
22
23
/**
23
24
* Returns extent, min and max values of each dimensions, of all data series points.
24
25
*
25
- * Note that it excludes auxillary data points and invisible data series.
26
+ * When ignoreYOutliers is true, it will calculate extent using values within 5th and 95th
27
+ * quantiles.
26
28
*
27
- * TODO(stephanwlee): add support for ignoreOutlier .
29
+ * Note that it excludes auxillary data points and invisible data series .
28
30
*/
29
31
export function computeDataSeriesExtent (
30
32
data : DataSeries [ ] ,
31
- metadataMap : DataSeriesMetadataMap
33
+ metadataMap : DataSeriesMetadataMap ,
34
+ ignoreYOutliers : boolean
32
35
) : { x : [ number , number ] | undefined ; y : [ number , number ] | undefined } {
33
- let xMin = Infinity ;
34
- let xMax = - Infinity ;
35
- let yMin = Infinity ;
36
- let yMax = - Infinity ;
37
-
38
- let xExtentChanged = false ;
39
- let yExtentChanged = false ;
36
+ let xMin : number | null = null ;
37
+ let xMax : number | null = null ;
38
+ let yPoints : number [ ] = [ ] ;
40
39
40
+ let pointIndex = 0 ;
41
41
for ( const { id, points} of data ) {
42
42
const meta = metadataMap [ id ] ;
43
43
if ( ! meta || meta . aux || ! meta . visible ) continue ;
44
44
45
45
for ( let index = 0 ; index < points . length ; index ++ ) {
46
46
const { x, y} = points [ index ] ;
47
- if ( ! Number . isNaN ( x ) ) {
48
- xMin = Math . min ( xMin , x ) ;
49
- xMax = Math . max ( xMax , x ) ;
50
- xExtentChanged = true ;
47
+ if ( Number . isFinite ( x ) ) {
48
+ xMin = xMin === null || x < xMin ? x : xMin ;
49
+ xMax = xMax === null || x > xMax ? x : xMax ;
51
50
}
52
- if ( ! Number . isNaN ( y ) ) {
53
- yMin = Math . min ( yMin , y ) ;
54
- yMax = Math . max ( yMax , y ) ;
55
- yExtentChanged = true ;
51
+ if ( Number . isFinite ( y ) ) {
52
+ yPoints . push ( y ) ;
56
53
}
54
+ pointIndex ++ ;
57
55
}
58
56
}
59
57
58
+ yPoints . sort ( d3 . ascending ) ;
59
+ let yMin = yPoints [ 0 ] ;
60
+ let yMax = yPoints [ yPoints . length - 1 ] ;
61
+
62
+ if ( ignoreYOutliers && yPoints . length > 2 ) {
63
+ yMin = yPoints [ Math . ceil ( ( yPoints . length - 1 ) * 0.05 ) ] ;
64
+ yMax = yPoints [ Math . floor ( ( yPoints . length - 1 ) * 0.95 ) ] ;
65
+ }
66
+
60
67
return {
61
- x : xExtentChanged ? [ xMin , xMax ] : undefined ,
62
- y : yExtentChanged ? [ yMin , yMax ] : undefined ,
68
+ x : xMin !== null && xMax !== null ? [ xMin , xMax ] : undefined ,
69
+ y : yMin !== undefined && yMax !== undefined ? [ yMin , yMax ] : undefined ,
63
70
} ;
64
71
}
65
72
0 commit comments