Skip to content

Commit ee78877

Browse files
committed
Don't consider negative domain as valid in log/sqrt scale
1 parent 2d5100f commit ee78877

File tree

5 files changed

+36
-45
lines changed

5 files changed

+36
-45
lines changed

packages/app/src/providers/mock/mock-file.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export function makeMockFile(): GroupWithChildren {
137137
valueId: 'twoD',
138138
attributes: [scalar('_FillValue', 400)],
139139
}),
140+
array('twoD_neg'),
140141
array('twoD_bigint'),
141142
array('twoD_cplx'),
142143
array('twoD_compound', {

packages/lib/src/vis/shared/ViewportCenterer.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ function ViewportCenterer() {
1717
});
1818

1919
useEffect(() => {
20+
// On resize, move camera to the latest saved viewport center coordinates
2021
if (viewportCenter.current) {
21-
// On resize, move camera to the latest saved viewport center coordinates
22-
moveCameraTo(dataToWorld(viewportCenter.current));
22+
const newPos = dataToWorld(viewportCenter.current);
23+
24+
// Ignore previous center if no longer valid with current scale
25+
if (Number.isFinite(newPos.x) && Number.isFinite(newPos.y)) {
26+
moveCameraTo(newPos);
27+
}
2328
}
2429
}, [viewportCenter, moveCameraTo, dataToWorld, camera]);
2530

packages/lib/src/vis/utils.test.ts

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,60 +39,44 @@ describe('getSizeToFit', () => {
3939

4040
describe('getDomain', () => {
4141
it('should return min and max values of data array', () => {
42-
const data = [2, 0, 10, 5, 2, -1];
43-
const domain = getDomain(data);
44-
expect(domain).toEqual([-1, 10]);
42+
expect(getDomain([2, 0, 10, 5, 2, -1])).toEqual([-1, 10]);
4543
});
4644

4745
it('should return `undefined` if data is empty', () => {
48-
const domain = getDomain([]);
49-
expect(domain).toBeUndefined();
46+
expect(getDomain([])).toBeUndefined();
5047
});
5148

5249
it('should ignore NaN and Infinity', () => {
53-
const domain = getDomain([2, NAN, 10, INFINITY, 2, -1]);
54-
expect(domain).toEqual([-1, 10]);
50+
expect(getDomain([2, NAN, 10, INFINITY, 2, -1])).toEqual([-1, 10]);
5551
});
5652

5753
it('should return `undefined` if data contains only NaN and Infinity', () => {
58-
const domain = getDomain([NAN, NAN, -INFINITY, INFINITY]);
59-
expect(domain).toBeUndefined();
54+
expect(getDomain([NAN, NAN, -INFINITY, INFINITY])).toBeUndefined();
6055
});
6156

6257
describe('with log scale', () => {
63-
it('should support negative domain', () => {
64-
const domain = getDomain([-2, -10, -5, -2, -1], ScaleType.Log);
65-
expect(domain).toEqual([-10, -1]);
66-
});
67-
68-
it('should clamp domain min to first strict positive value when domain crosses zero', () => {
69-
const domain = getDomain([2, 0, 10, 5, 2, -1], ScaleType.Log);
70-
expect(domain).toEqual([2, 10]);
58+
it('should clamp domain min to first strictly positive value when domain crosses zero', () => {
59+
expect(getDomain([2, 0, 10, -1], ScaleType.Log)).toEqual([2, 10]);
7160
});
7261

7362
it('should return `undefined` if domain is not supported', () => {
74-
const domain = getDomain([-2, 0, -10, -5, -2, -1], ScaleType.Log);
75-
expect(domain).toBeUndefined();
63+
expect(getDomain([-2, 0, -10], ScaleType.Log)).toBeUndefined();
64+
expect(getDomain([-2, -5, -10], ScaleType.Log)).toBeUndefined();
7665
});
7766
});
7867

7968
describe('with sqrt scale', () => {
80-
it('should support negative domain', () => {
81-
const domain = getDomain([-2, -10, -5, -2, -1], ScaleType.Sqrt);
82-
expect(domain).toEqual([-10, -1]);
83-
});
84-
85-
it('should support negative domain including 0', () => {
86-
const domain = getDomain([-2, 0, -10, -5, -2, -1], ScaleType.Sqrt);
87-
expect(domain).toEqual([-10, 0]);
69+
it('should support positive domain including 0', () => {
70+
expect(getDomain([1, 3, 0, 2], ScaleType.Sqrt)).toEqual([0, 3]);
8871
});
8972

9073
it('should clamp domain min to first positive value when domain crosses zero', () => {
91-
const domain = getDomain([2, 0, 10, 5, 2, -1], ScaleType.Sqrt);
92-
expect(domain).toEqual([0, 10]);
74+
expect(getDomain([2, 0, 10, -1], ScaleType.Sqrt)).toEqual([0, 10]);
75+
expect(getDomain([2, 5, 10, -1], ScaleType.Sqrt)).toEqual([2, 10]);
76+
});
9377

94-
const domain2 = getDomain([2, 10, 5, 2, -1], ScaleType.Sqrt);
95-
expect(domain2).toEqual([2, 10]);
78+
it('should return `undefined` if domain is fully negative', () => {
79+
expect(getDomain([-2, -10], ScaleType.Sqrt)).toBeUndefined();
9680
});
9781
});
9882
});
@@ -108,12 +92,11 @@ describe('getDomains', () => {
10892
});
10993

11094
it('should return domains of multiple arrays in log scale', () => {
111-
const arr1 = [-2, -10, -5, -2, -1];
112-
const arr2 = [2, 0, 10, 5, 2, -1];
113-
const arr3 = [-2, 0, -10, -5, -2, -1];
95+
const arr1 = [2, 0, 10, 5, 2, -1];
96+
const arr2 = [-2, 0, -10, -5, -2, -1];
11497

115-
const domain = getDomains([arr1, arr2, arr3], ScaleType.Log);
116-
expect(domain).toEqual([[-10, -1], [2, 10], undefined]);
98+
const domain = getDomains([arr1, arr2], ScaleType.Log);
99+
expect(domain).toEqual([[2, 10], undefined]);
117100
});
118101
});
119102

packages/shared/src/mock-values.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export const mockValues = {
174174
[20, 41],
175175
);
176176
},
177+
twoD_neg: () => ndarray(range(-10, 0), [1, 10]),
177178
threeD,
178179
threeD_cplx: () =>
179180
ndarray(

packages/shared/src/vis-utils.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,17 @@ export function getValidDomainForScale(
167167
}
168168

169169
const { min, max, positiveMin, strictPositiveMin } = bounds;
170-
if (scaleType === ScaleType.Log && min * max <= 0) {
171-
// Clamp domain minimum to first positive value,
172-
// or return `undefined` if domain is not unsupported: `[-x, 0]`
170+
171+
if (scaleType === ScaleType.Log && min <= 0) {
173172
return Number.isFinite(strictPositiveMin)
174-
? [strictPositiveMin, max]
175-
: undefined;
173+
? [strictPositiveMin, max] // clamp min to first strictly positive value, if any
174+
: undefined; // can't make valid domain - e.g. [-5, -2], [-10, 0]
176175
}
177176

178-
if (scaleType === ScaleType.Sqrt && min * max < 0) {
179-
return [positiveMin, max];
177+
if (scaleType === ScaleType.Sqrt && min < 0) {
178+
return Number.isFinite(positiveMin)
179+
? [positiveMin, max] // clamp min to first positive value, if any
180+
: undefined; // can't make valid domain - e.g. [-5, -2]
180181
}
181182

182183
return [min, max];

0 commit comments

Comments
 (0)