@vitessce/spatial-utils 2.0.3 → 3.0.1
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/dist/{deflate.b31189ff.mjs → deflate-132dedf0.js} +2 -3
- package/dist/{index.75f0a489.mjs → index-ce1fad7e.js} +37344 -28760
- package/dist/{index.mjs → index.js} +7 -5
- package/dist/{jpeg.1d104fed.mjs → jpeg-258024ce.js} +1 -2
- package/dist/{lerc.95b793c7.mjs → lerc-279c1032.js} +76 -6
- package/dist/{lzw.ade1d376.mjs → lzw-d830df9b.js} +1 -2
- package/dist/{packbits.16b1394a.mjs → packbits-fe766b57.js} +1 -2
- package/dist/{pako.esm.4b234125.mjs → pako.esm-68f84e2a.js} +97 -15
- package/dist/{raw.c3b45ab1.mjs → raw-f15bab0d.js} +1 -2
- package/dist/{webimage.53b9bf75.mjs → webimage-03150187.js} +1 -2
- package/dist-tsc/index.d.ts +2 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +1 -1
- package/dist-tsc/layer-controller.d.ts +23 -0
- package/dist-tsc/layer-controller.d.ts.map +1 -0
- package/dist-tsc/layer-controller.js +109 -0
- package/dist-tsc/spatial.d.ts +87 -0
- package/dist-tsc/spatial.d.ts.map +1 -0
- package/dist-tsc/spatial.js +375 -0
- package/dist-tsc/spatial.test.d.ts +2 -0
- package/dist-tsc/spatial.test.d.ts.map +1 -0
- package/dist-tsc/spatial.test.js +44 -0
- package/package.json +16 -7
- package/src/index.js +4 -1
- package/src/spatial.js +102 -2
- package/src/spatial.test.js +38 -1
package/src/spatial.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import isEqual from 'lodash
|
|
1
|
+
import { isEqual } from 'lodash-es';
|
|
2
2
|
import { Matrix4 } from 'math.gl';
|
|
3
3
|
import { divide, compare, unit } from 'mathjs';
|
|
4
4
|
import { VIEWER_PALETTE } from '@vitessce/utils';
|
|
5
5
|
import { viv } from '@vitessce/gl';
|
|
6
|
-
import { getMultiSelectionStats } from './layer-controller';
|
|
6
|
+
import { getMultiSelectionStats } from './layer-controller.js';
|
|
7
7
|
|
|
8
8
|
export function square(x, y, r) {
|
|
9
9
|
return [[x, y + r], [x + r, y], [x, y - r], [x - r, y]];
|
|
@@ -117,6 +117,11 @@ function getMetaWithTransformMatrices(imageMeta, imageLoaders) {
|
|
|
117
117
|
}
|
|
118
118
|
// Find the ratio of the sizes to get the scaling factor.
|
|
119
119
|
const scale = sizes.map((i, k) => divide(i, minPhysicalSize[k]));
|
|
120
|
+
// sizes are special objects with own equals method - see `unit` in declaration
|
|
121
|
+
if (!sizes[0].equals(sizes[1])) {
|
|
122
|
+
// Handle scaling in the Y direction for non-square pixels
|
|
123
|
+
scale[1] = divide(sizes[1], sizes[0]);
|
|
124
|
+
}
|
|
120
125
|
// Add in z dimension needed for Matrix4 scale API.
|
|
121
126
|
if (!scale[2]) {
|
|
122
127
|
scale[2] = 1;
|
|
@@ -316,3 +321,98 @@ export async function initializeRasterLayersAndChannels(
|
|
|
316
321
|
const autoImageLayerDefs = await Promise.all(autoImageLayerDefPromises);
|
|
317
322
|
return [autoImageLayerDefs, nextImageLoaders, nextImageMetaAndLayers];
|
|
318
323
|
}
|
|
324
|
+
|
|
325
|
+
function getDefaultAxisType(name) {
|
|
326
|
+
if (name === 't') return 'time';
|
|
327
|
+
if (name === 'c') return 'channel';
|
|
328
|
+
return 'space';
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Reference: https://github.com/hms-dbmi/vizarr/blob/ade9d5d71bbedc8c20357c5310557ff9a0c59ac5/src/utils.ts#LL114-L142C2
|
|
332
|
+
export function getNgffAxes(firstMultiscalesAxes) {
|
|
333
|
+
// Returns axes in the latest v0.4+ format.
|
|
334
|
+
// defaults for v0.1 & v0.2
|
|
335
|
+
const defaultAxes = [
|
|
336
|
+
{ type: 'time', name: 't' },
|
|
337
|
+
{ type: 'channel', name: 'c' },
|
|
338
|
+
{ type: 'space', name: 'z' },
|
|
339
|
+
{ type: 'space', name: 'y' },
|
|
340
|
+
{ type: 'space', name: 'x' },
|
|
341
|
+
];
|
|
342
|
+
let axes = defaultAxes;
|
|
343
|
+
// v0.3 & v0.4+
|
|
344
|
+
if (firstMultiscalesAxes) {
|
|
345
|
+
axes = firstMultiscalesAxes.map((axis) => {
|
|
346
|
+
// axis may be string 'x' (v0.3) or object
|
|
347
|
+
if (typeof axis === 'string') {
|
|
348
|
+
return { name: axis, type: getDefaultAxisType(axis) };
|
|
349
|
+
}
|
|
350
|
+
const { name, type } = axis;
|
|
351
|
+
return { name, type: type ?? getDefaultAxisType(name) };
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return axes;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export function getNgffAxesForTiff(dimOrder) {
|
|
358
|
+
return dimOrder
|
|
359
|
+
.toLowerCase()
|
|
360
|
+
.split('')
|
|
361
|
+
.map(name => ({
|
|
362
|
+
name,
|
|
363
|
+
type: getDefaultAxisType(name),
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Convert an array of coordinateTransformations objects to a 16-element
|
|
369
|
+
* plain JS array using Matrix4 linear algebra transformation functions.
|
|
370
|
+
* @param {object[]} coordinateTransformations List of objects matching the
|
|
371
|
+
* OME-NGFF v0.4 coordinateTransformations spec.
|
|
372
|
+
* @param {object[]} axes Axes in OME-NGFF v0.4 format, objects
|
|
373
|
+
* with { type, name }.
|
|
374
|
+
* @returns {Array<number>} Array of 16 numbers representing the Matrix4.
|
|
375
|
+
*/
|
|
376
|
+
export function coordinateTransformationsToMatrix(coordinateTransformations, axes) {
|
|
377
|
+
let mat = (new Matrix4()).identity();
|
|
378
|
+
if (coordinateTransformations && axes) {
|
|
379
|
+
// Get the indices of the objects corresponding to X, Y, and Z from `axes`.
|
|
380
|
+
const xyzIndices = ['x', 'y', 'z'].map(name => axes.findIndex(axisObj => axisObj.type === 'space' && axisObj.name === name));
|
|
381
|
+
// Apply each transformation sequentially and in order according to the OME-NGFF v0.4 spec.
|
|
382
|
+
// Reference: https://ngff.openmicroscopy.org/0.4/#trafo-md
|
|
383
|
+
coordinateTransformations.forEach((transform) => {
|
|
384
|
+
if (transform.type === 'translation') {
|
|
385
|
+
const { translation: axisOrderedTranslation } = transform;
|
|
386
|
+
if (axisOrderedTranslation.length !== axes.length) {
|
|
387
|
+
throw new Error('Length of translation array was expected to match length of axes.');
|
|
388
|
+
}
|
|
389
|
+
const defaultValue = 0;
|
|
390
|
+
// Get the translation values for [x, y, z].
|
|
391
|
+
const xyzTranslation = xyzIndices.map(axisIndex => (
|
|
392
|
+
axisIndex >= 0
|
|
393
|
+
? axisOrderedTranslation[axisIndex]
|
|
394
|
+
: defaultValue
|
|
395
|
+
));
|
|
396
|
+
const nextMat = (new Matrix4()).translate(xyzTranslation);
|
|
397
|
+
mat = mat.multiplyLeft(nextMat);
|
|
398
|
+
}
|
|
399
|
+
if (transform.type === 'scale') {
|
|
400
|
+
const { scale: axisOrderedScale } = transform;
|
|
401
|
+
// Add in z dimension needed for Matrix4 scale API.
|
|
402
|
+
if (axisOrderedScale.length !== axes.length) {
|
|
403
|
+
throw new Error('Length of scale array was expected to match length of axes.');
|
|
404
|
+
}
|
|
405
|
+
const defaultValue = 1;
|
|
406
|
+
// Get the scale values for [x, y, z].
|
|
407
|
+
const xyzScale = xyzIndices.map(axisIndex => (
|
|
408
|
+
axisIndex >= 0
|
|
409
|
+
? axisOrderedScale[axisIndex]
|
|
410
|
+
: defaultValue
|
|
411
|
+
));
|
|
412
|
+
const nextMat = (new Matrix4()).scale(xyzScale);
|
|
413
|
+
mat = mat.multiplyLeft(nextMat);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return mat;
|
|
418
|
+
}
|
package/src/spatial.test.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { square, coordinateTransformationsToMatrix } from './spatial.js';
|
|
3
|
+
|
|
4
|
+
const defaultAxes = [
|
|
5
|
+
{ type: 'time', name: 't' },
|
|
6
|
+
{ type: 'channel', name: 'c' },
|
|
7
|
+
{ type: 'space', name: 'z' },
|
|
8
|
+
{ type: 'space', name: 'y' },
|
|
9
|
+
{ type: 'space', name: 'x' },
|
|
10
|
+
];
|
|
2
11
|
|
|
3
12
|
describe('Spatial.js', () => {
|
|
4
13
|
describe('square()', () => {
|
|
@@ -6,4 +15,32 @@ describe('Spatial.js', () => {
|
|
|
6
15
|
expect(square(0, 0, 50)).toEqual([[0, 50], [50, 0], [0, -50], [-50, 0]]);
|
|
7
16
|
});
|
|
8
17
|
});
|
|
18
|
+
describe('coordinateTransformationsToMatrix', () => {
|
|
19
|
+
it('returns an Array instance', () => {
|
|
20
|
+
const transformations = [
|
|
21
|
+
{
|
|
22
|
+
type: 'translation',
|
|
23
|
+
translation: [0, 0, 0, 1, 1],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'scale',
|
|
27
|
+
scale: [1, 1, 0.5, 0.5, 0.5],
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
expect(coordinateTransformationsToMatrix(transformations, defaultAxes)).toEqual([
|
|
31
|
+
0.5, 0, 0, 0,
|
|
32
|
+
0, 0.5, 0, 0,
|
|
33
|
+
0, 0, 0.5, 0,
|
|
34
|
+
0.5, 0.5, 0, 1,
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
it('returns Identity matrix when coordinateTransformations is null', () => {
|
|
38
|
+
expect(coordinateTransformationsToMatrix(null, defaultAxes)).toEqual([
|
|
39
|
+
1, 0, 0, 0,
|
|
40
|
+
0, 1, 0, 0,
|
|
41
|
+
0, 0, 1, 0,
|
|
42
|
+
0, 0, 0, 1,
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
9
46
|
});
|