@vitessce/vit-s 3.2.1 → 3.2.2
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/index.js +46 -4
- package/dist-tsc/VitessceGrid.d.ts.map +1 -1
- package/dist-tsc/VitessceGrid.js +4 -2
- package/dist-tsc/generate-alt-text.d.ts +19 -0
- package/dist-tsc/generate-alt-text.d.ts.map +1 -0
- package/dist-tsc/generate-alt-text.js +48 -0
- package/dist-tsc/generate-alt-text.test.d.ts +2 -0
- package/dist-tsc/generate-alt-text.test.d.ts.map +1 -0
- package/dist-tsc/generate-alt-text.test.js +67 -0
- package/package.json +5 -5
- package/src/VitessceGrid.js +7 -0
- package/src/generate-alt-text.js +51 -0
- package/src/generate-alt-text.test.js +73 -0
package/dist/index.js
CHANGED
|
@@ -35383,10 +35383,10 @@ const AUTO_INDEPENDENT_COORDINATION_TYPES = [
|
|
|
35383
35383
|
CoordinationType$1.EMBEDDING_OBS_OPACITY
|
|
35384
35384
|
];
|
|
35385
35385
|
const note = "This file is autogenerated by .changeset/post-changelog.mjs.";
|
|
35386
|
-
const version = "3.2.
|
|
35387
|
-
const date = "2023-09-
|
|
35386
|
+
const version = "3.2.2";
|
|
35387
|
+
const date = "2023-09-20";
|
|
35388
35388
|
const branch = "changeset-release/main";
|
|
35389
|
-
const hash = "
|
|
35389
|
+
const hash = "715881ca";
|
|
35390
35390
|
const META_VERSION = {
|
|
35391
35391
|
note,
|
|
35392
35392
|
version,
|
|
@@ -35632,7 +35632,13 @@ function buildConfigSchema(pluginFileTypes, pluginJointFileTypes, pluginCoordina
|
|
|
35632
35632
|
// Wrap each value schema in z.record()
|
|
35633
35633
|
fromEntries(pluginCoordinationTypes.map((ct) => [
|
|
35634
35634
|
ct.name,
|
|
35635
|
-
z.record(
|
|
35635
|
+
z.record(
|
|
35636
|
+
// For now, assume the key type is string (though it would be
|
|
35637
|
+
// slightly nicer if we could use the coordinationScopeName schema here).
|
|
35638
|
+
// Once https://github.com/colinhacks/zod/issues/2746 gets resolved
|
|
35639
|
+
// then we can try that approach again, but it should not be a big deal.
|
|
35640
|
+
ct.valueSchema.optional()
|
|
35641
|
+
).optional()
|
|
35636
35642
|
]))
|
|
35637
35643
|
).strict().describe("The coordination space stores the values for each scope of each coordination object.").optional(),
|
|
35638
35644
|
layout: z.array(z.object({
|
|
@@ -43699,6 +43705,38 @@ const useTitleStyles = makeStyles((theme) => ({
|
|
|
43699
43705
|
}
|
|
43700
43706
|
}
|
|
43701
43707
|
}));
|
|
43708
|
+
function arrayToString(arr) {
|
|
43709
|
+
const arrF = arr.filter((item) => item !== void 0);
|
|
43710
|
+
if (arrF.length === 0) {
|
|
43711
|
+
return "";
|
|
43712
|
+
}
|
|
43713
|
+
if (arrF.length === 1) {
|
|
43714
|
+
return arrF[0];
|
|
43715
|
+
}
|
|
43716
|
+
return `${arr.slice(0, -1).join(", ")} and ${arr.slice(-1)}`;
|
|
43717
|
+
}
|
|
43718
|
+
const ViewTypesToText = /* @__PURE__ */ new Map([
|
|
43719
|
+
[ViewType$1.DESCRIPTION, "description"],
|
|
43720
|
+
[ViewType$1.STATUS, "status view for debugging"],
|
|
43721
|
+
[ViewType$1.SCATTERPLOT, "scatterplot with embeddings"],
|
|
43722
|
+
[ViewType$1.SPATIAL, "spatial view"],
|
|
43723
|
+
[ViewType$1.SPATIAL_BETA, "spatial view"],
|
|
43724
|
+
[ViewType$1.HEATMAP, "cell by gene heatmap"],
|
|
43725
|
+
[ViewType$1.LAYER_CONTROLLER, "layer controller"],
|
|
43726
|
+
[ViewType$1.LAYER_CONTROLLER_BETA, "layer controller"],
|
|
43727
|
+
[ViewType$1.GENOMIC_PROFILES, "genome browser tracks with bar plots"],
|
|
43728
|
+
[ViewType$1.GATING, "scatterplot of gated gene expression data"],
|
|
43729
|
+
[ViewType$1.FEATURE_LIST, "interactive list of features"],
|
|
43730
|
+
[ViewType$1.OBS_SETS, "list of potential observation sets"],
|
|
43731
|
+
[ViewType$1.OBS_SET_SIZES, "sizes of selected observation sets"],
|
|
43732
|
+
[ViewType$1.OBS_SET_FEATURE_VALUE_DISTRIBUTION, "violin plot with values"],
|
|
43733
|
+
[ViewType$1.FEATURE_VALUE_HISTOGRAM, "distribution of values"]
|
|
43734
|
+
]);
|
|
43735
|
+
function getAltText(config2) {
|
|
43736
|
+
const componentList = config2.layout.map((c) => c.component);
|
|
43737
|
+
const altText = `Vitessce grid with ${componentList.length} views, including ${arrayToString(componentList.map((c) => ViewTypesToText.get(c) || "plugin view"))}.`;
|
|
43738
|
+
return altText;
|
|
43739
|
+
}
|
|
43702
43740
|
const padding = 10;
|
|
43703
43741
|
const margin = 5;
|
|
43704
43742
|
function VitessceGrid(props) {
|
|
@@ -43719,6 +43757,7 @@ function VitessceGrid(props) {
|
|
|
43719
43757
|
const [componentWidth] = useClosestVitessceContainerSize(containerRef);
|
|
43720
43758
|
const classes = useVitessceContainerStyles();
|
|
43721
43759
|
const titleClasses = useTitleStyles();
|
|
43760
|
+
const altText = useMemo(() => getAltText(config2), [configKey]);
|
|
43722
43761
|
useEffect(() => {
|
|
43723
43762
|
onResize();
|
|
43724
43763
|
}, [rowHeight, onResize]);
|
|
@@ -43753,9 +43792,12 @@ function VitessceGrid(props) {
|
|
|
43753
43792
|
{
|
|
43754
43793
|
ref: containerRef,
|
|
43755
43794
|
className: clsx(VITESSCE_CONTAINER, classes.vitessceContainer),
|
|
43795
|
+
role: "group",
|
|
43796
|
+
"aria-label": altText,
|
|
43756
43797
|
children: layout2 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
43757
43798
|
VitessceGridLayout,
|
|
43758
43799
|
{
|
|
43800
|
+
role: "group",
|
|
43759
43801
|
layout: layout2,
|
|
43760
43802
|
height: height2,
|
|
43761
43803
|
rowHeight,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VitessceGrid.d.ts","sourceRoot":"","sources":["../src/VitessceGrid.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VitessceGrid.d.ts","sourceRoot":"","sources":["../src/VitessceGrid.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;GAWG;AACH;IATyB,SAAS,EAAvB,MAAM;IACQ,MAAM,EAApB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,MAAM,EAApB,MAAM;IACU,MAAM;IACE,SAAS,EAAjC,gBAAgB;IACQ,SAAS,EAAjC,gBAAgB;IACgB,iBAAiB,EAAjD,wBAAwB;gBA4FlC"}
|
package/dist-tsc/VitessceGrid.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { useEffect, useCallback, } from 'react';
|
|
2
|
+
import React, { useEffect, useCallback, useMemo, } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { VITESSCE_CONTAINER } from './classNames.js';
|
|
5
5
|
import { VitessceGridLayout } from './vitessce-grid-layout/index.js';
|
|
@@ -8,6 +8,7 @@ import { useViewConfigStoreApi, useSetViewConfig, useSetLoaders, useEmitGridResi
|
|
|
8
8
|
import { useClosestVitessceContainerSize, } from './hooks.js';
|
|
9
9
|
import { useVitessceContainerStyles } from './shared-mui/container.js';
|
|
10
10
|
import { useTitleStyles } from './title-styles.js';
|
|
11
|
+
import { getAltText } from './generate-alt-text.js';
|
|
11
12
|
const padding = 10;
|
|
12
13
|
const margin = 5;
|
|
13
14
|
/**
|
|
@@ -29,6 +30,7 @@ export default function VitessceGrid(props) {
|
|
|
29
30
|
const [componentWidth] = useClosestVitessceContainerSize(containerRef);
|
|
30
31
|
const classes = useVitessceContainerStyles();
|
|
31
32
|
const titleClasses = useTitleStyles();
|
|
33
|
+
const altText = useMemo(() => getAltText(config), [configKey]);
|
|
32
34
|
// When the row height has changed, publish a GRID_RESIZE event.
|
|
33
35
|
useEffect(() => {
|
|
34
36
|
onResize();
|
|
@@ -59,5 +61,5 @@ export default function VitessceGrid(props) {
|
|
|
59
61
|
setLoaders(newLoaders);
|
|
60
62
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
63
|
}, [success, configKey]);
|
|
62
|
-
return (_jsx("div", { ref: containerRef, className: clsx(VITESSCE_CONTAINER, classes.vitessceContainer), children: layout ? (_jsx(VitessceGridLayout, { layout: layout, height: height, rowHeight: rowHeight, theme: theme, viewTypes: viewTypes, draggableHandle: titleClasses.title, margin: margin, padding: padding, onRemoveComponent: removeComponent, onLayoutChange: changeLayoutPostMount, isBounded: isBounded, onResize: onResize, onResizeStop: onResize })) : null }));
|
|
64
|
+
return (_jsx("div", { ref: containerRef, className: clsx(VITESSCE_CONTAINER, classes.vitessceContainer), role: "group", "aria-label": altText, children: layout ? (_jsx(VitessceGridLayout, { role: "group", layout: layout, height: height, rowHeight: rowHeight, theme: theme, viewTypes: viewTypes, draggableHandle: titleClasses.title, margin: margin, padding: padding, onRemoveComponent: removeComponent, onLayoutChange: changeLayoutPostMount, isBounded: isBounded, onResize: onResize, onResizeStop: onResize })) : null }));
|
|
63
65
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Method for converting an array with strings to a natural sentence,
|
|
3
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
4
|
+
* @param {Array} arr Array with text items.
|
|
5
|
+
* @returns {string} Natural language sentence in the form of 'a, b and c', where a/b/c are items.
|
|
6
|
+
*/
|
|
7
|
+
export function arrayToString(arr: any[]): string;
|
|
8
|
+
/**
|
|
9
|
+
* Method for converting an array with strings to a natural sentence,
|
|
10
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
11
|
+
* @param {Object} config Vitessce config.
|
|
12
|
+
* @returns {string} Natural language sentence describing config (alt-text).
|
|
13
|
+
*/
|
|
14
|
+
export function getAltText(config: Object): string;
|
|
15
|
+
/**
|
|
16
|
+
* Mapping of ViewType to natural language description of ViewType.
|
|
17
|
+
*/
|
|
18
|
+
export const ViewTypesToText: Map<string, string>;
|
|
19
|
+
//# sourceMappingURL=generate-alt-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-alt-text.d.ts","sourceRoot":"","sources":["../src/generate-alt-text.js"],"names":[],"mappings":"AAEA;;;;;KAKK;AACL,2CAFe,MAAM,CAWpB;AAuBD;;;;;KAKK;AACL,mCAHa,MAAM,GACJ,MAAM,CAMpB;AA/BD;;KAEK;AACL,kDAgBG"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ViewType } from '@vitessce/constants-internal';
|
|
2
|
+
/**
|
|
3
|
+
* Method for converting an array with strings to a natural sentence,
|
|
4
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
5
|
+
* @param {Array} arr Array with text items.
|
|
6
|
+
* @returns {string} Natural language sentence in the form of 'a, b and c', where a/b/c are items.
|
|
7
|
+
*/
|
|
8
|
+
export function arrayToString(arr) {
|
|
9
|
+
const arrF = arr.filter(item => item !== undefined);
|
|
10
|
+
if (arrF.length === 0) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
if (arrF.length === 1) {
|
|
14
|
+
return arrF[0];
|
|
15
|
+
}
|
|
16
|
+
return `${arr.slice(0, -1).join(', ')} and ${arr.slice(-1)}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Mapping of ViewType to natural language description of ViewType.
|
|
20
|
+
*/
|
|
21
|
+
export const ViewTypesToText = new Map([
|
|
22
|
+
[ViewType.DESCRIPTION, 'description'],
|
|
23
|
+
[ViewType.STATUS, 'status view for debugging'],
|
|
24
|
+
[ViewType.SCATTERPLOT, 'scatterplot with embeddings'],
|
|
25
|
+
[ViewType.SPATIAL, 'spatial view'],
|
|
26
|
+
[ViewType.SPATIAL_BETA, 'spatial view'],
|
|
27
|
+
[ViewType.HEATMAP, 'cell by gene heatmap'],
|
|
28
|
+
[ViewType.LAYER_CONTROLLER, 'layer controller'],
|
|
29
|
+
[ViewType.LAYER_CONTROLLER_BETA, 'layer controller'],
|
|
30
|
+
[ViewType.GENOMIC_PROFILES, 'genome browser tracks with bar plots'],
|
|
31
|
+
[ViewType.GATING, 'scatterplot of gated gene expression data'],
|
|
32
|
+
[ViewType.FEATURE_LIST, 'interactive list of features'],
|
|
33
|
+
[ViewType.OBS_SETS, 'list of potential observation sets'],
|
|
34
|
+
[ViewType.OBS_SET_SIZES, 'sizes of selected observation sets'],
|
|
35
|
+
[ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION, 'violin plot with values'],
|
|
36
|
+
[ViewType.FEATURE_VALUE_HISTOGRAM, 'distribution of values'],
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Method for converting an array with strings to a natural sentence,
|
|
40
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
41
|
+
* @param {Object} config Vitessce config.
|
|
42
|
+
* @returns {string} Natural language sentence describing config (alt-text).
|
|
43
|
+
*/
|
|
44
|
+
export function getAltText(config) {
|
|
45
|
+
const componentList = config.layout.map(c => c.component);
|
|
46
|
+
const altText = `Vitessce grid with ${componentList.length} views, including ${arrayToString(componentList.map(c => ViewTypesToText.get(c) || 'plugin view'))}.`;
|
|
47
|
+
return altText;
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-alt-text.test.d.ts","sourceRoot":"","sources":["../src/generate-alt-text.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ViewType } from '@vitessce/constants-internal';
|
|
3
|
+
import { arrayToString, ViewTypesToText, getAltText } from './generate-alt-text.js';
|
|
4
|
+
describe('Tests for generating an alt text from the vitessce config', () => {
|
|
5
|
+
describe('Tests for arrayToString', () => {
|
|
6
|
+
it('should return empty string for empty array', () => {
|
|
7
|
+
const arr = [];
|
|
8
|
+
const str = arrayToString(arr);
|
|
9
|
+
expect(str).toEqual('');
|
|
10
|
+
});
|
|
11
|
+
it('should return the element if the araay only has one element', () => {
|
|
12
|
+
const arr = ['one'];
|
|
13
|
+
const str = arrayToString(arr);
|
|
14
|
+
expect(str).toEqual('one');
|
|
15
|
+
});
|
|
16
|
+
it('should return the elements concatenated with "and" when the array has two elements', () => {
|
|
17
|
+
const arr = ['one', 'two'];
|
|
18
|
+
const str = arrayToString(arr);
|
|
19
|
+
expect(str).toEqual('one and two');
|
|
20
|
+
});
|
|
21
|
+
it('should return the elements concatenated with ", " and the last two elements with "and" when the array has more than two elements', () => {
|
|
22
|
+
const arr = ['one', 'two', 'three', 'four'];
|
|
23
|
+
const str = arrayToString(arr);
|
|
24
|
+
expect(str).toEqual('one, two, three and four');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('Tests for (const) ViewTypesToText', () => {
|
|
28
|
+
it('should have a natural language mapping for every defined viewtype', () => {
|
|
29
|
+
expect(ViewTypesToText.length).toEqual(ViewType.length);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('Tests for getAltTest', () => {
|
|
33
|
+
const config = {
|
|
34
|
+
coordinationSpace: {},
|
|
35
|
+
datasets: {},
|
|
36
|
+
description: 'Spatial organization of the somatosensory cortex revealed by osmFISH',
|
|
37
|
+
initStrategy: 'auto',
|
|
38
|
+
layout: [
|
|
39
|
+
{ component: 'description', props: { description: 'Codeluppi et al., Nature Methods 2018: Spatial organization of the somatosensory cortex revealed by osmFISH' }, x: 0, y: 0, w: 2 },
|
|
40
|
+
{ component: 'layerController', x: 0, y: 1, w: 2, h: 4 },
|
|
41
|
+
{ component: 'status', x: 0, y: 5, w: 2, h: 1 },
|
|
42
|
+
{ component: 'spatial', props: { channelNamesVisible: true }, x: 2, y: 0, w: 4 },
|
|
43
|
+
{ component: 'featureList', x: 9, y: 0, w: 3, h: 2 },
|
|
44
|
+
{ component: 'obsSets', x: 9, y: 3, w: 3, h: 2 },
|
|
45
|
+
{ component: 'heatmap', props: { transpose: true }, x: 2, y: 4, w: 5 },
|
|
46
|
+
{ component: 'obsSetFeatureValueDistribution', x: 7, y: 4, w: 5, h: 2 },
|
|
47
|
+
{ component: 'scatterplot', x: 6, y: 0, w: 3, h: 2 },
|
|
48
|
+
{ component: 'scatterplot', x: 6, y: 2, w: 3, h: 2 },
|
|
49
|
+
],
|
|
50
|
+
name: 'Codeluppi et al., Nature Methods 2018',
|
|
51
|
+
uid: 'A',
|
|
52
|
+
version: '1.0.16',
|
|
53
|
+
};
|
|
54
|
+
const altText = getAltText(config);
|
|
55
|
+
it('should return a string', () => {
|
|
56
|
+
expect(typeof altText).toEqual('string');
|
|
57
|
+
});
|
|
58
|
+
it('should contain the number of views', () => {
|
|
59
|
+
const hasNViews = altText.includes('10');
|
|
60
|
+
expect(hasNViews).toEqual(true);
|
|
61
|
+
});
|
|
62
|
+
it('should contain mappings', () => {
|
|
63
|
+
const hasHeatmap = altText.includes('heatmap') && altText.includes('spatial') && altText.includes('description') && altText.includes('scatterplot');
|
|
64
|
+
expect(hasHeatmap).toEqual(true);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/vit-s",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.2",
|
|
4
4
|
"author": "Gehlenborg Lab",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"uuid": "^9.0.0",
|
|
30
30
|
"zustand": "^3.5.10",
|
|
31
31
|
"react-aria": "^3.28.0",
|
|
32
|
-
"@vitessce/constants-internal": "3.2.
|
|
33
|
-
"@vitessce/
|
|
34
|
-
"@vitessce/
|
|
35
|
-
"@vitessce/utils": "3.2.
|
|
32
|
+
"@vitessce/constants-internal": "3.2.2",
|
|
33
|
+
"@vitessce/plugins": "3.2.2",
|
|
34
|
+
"@vitessce/schemas": "3.2.2",
|
|
35
|
+
"@vitessce/utils": "3.2.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@testing-library/jest-dom": "^5.16.4",
|
package/src/VitessceGrid.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, {
|
|
2
2
|
useEffect,
|
|
3
3
|
useCallback,
|
|
4
|
+
useMemo,
|
|
4
5
|
} from 'react';
|
|
5
6
|
import clsx from 'clsx';
|
|
6
7
|
import { VITESSCE_CONTAINER } from './classNames.js';
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
} from './hooks.js';
|
|
21
22
|
import { useVitessceContainerStyles } from './shared-mui/container.js';
|
|
22
23
|
import { useTitleStyles } from './title-styles.js';
|
|
24
|
+
import { getAltText } from './generate-alt-text.js';
|
|
23
25
|
|
|
24
26
|
const padding = 10;
|
|
25
27
|
const margin = 5;
|
|
@@ -58,6 +60,8 @@ export default function VitessceGrid(props) {
|
|
|
58
60
|
const classes = useVitessceContainerStyles();
|
|
59
61
|
const titleClasses = useTitleStyles();
|
|
60
62
|
|
|
63
|
+
const altText = useMemo(() => getAltText(config), [configKey]);
|
|
64
|
+
|
|
61
65
|
// When the row height has changed, publish a GRID_RESIZE event.
|
|
62
66
|
useEffect(() => {
|
|
63
67
|
onResize();
|
|
@@ -101,9 +105,12 @@ export default function VitessceGrid(props) {
|
|
|
101
105
|
<div
|
|
102
106
|
ref={containerRef}
|
|
103
107
|
className={clsx(VITESSCE_CONTAINER, classes.vitessceContainer)}
|
|
108
|
+
role="group"
|
|
109
|
+
aria-label={altText}
|
|
104
110
|
>
|
|
105
111
|
{layout ? (
|
|
106
112
|
<VitessceGridLayout
|
|
113
|
+
role="group"
|
|
107
114
|
layout={layout}
|
|
108
115
|
height={height}
|
|
109
116
|
rowHeight={rowHeight}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ViewType } from '@vitessce/constants-internal';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Method for converting an array with strings to a natural sentence,
|
|
5
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
6
|
+
* @param {Array} arr Array with text items.
|
|
7
|
+
* @returns {string} Natural language sentence in the form of 'a, b and c', where a/b/c are items.
|
|
8
|
+
*/
|
|
9
|
+
export function arrayToString(arr) {
|
|
10
|
+
const arrF = arr.filter(item => item !== undefined);
|
|
11
|
+
if (arrF.length === 0) {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
if (arrF.length === 1) {
|
|
15
|
+
return arrF[0];
|
|
16
|
+
}
|
|
17
|
+
return `${arr.slice(0, -1).join(', ')} and ${arr.slice(-1)}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Mapping of ViewType to natural language description of ViewType.
|
|
22
|
+
*/
|
|
23
|
+
export const ViewTypesToText = new Map([
|
|
24
|
+
[ViewType.DESCRIPTION, 'description'],
|
|
25
|
+
[ViewType.STATUS, 'status view for debugging'],
|
|
26
|
+
[ViewType.SCATTERPLOT, 'scatterplot with embeddings'],
|
|
27
|
+
[ViewType.SPATIAL, 'spatial view'],
|
|
28
|
+
[ViewType.SPATIAL_BETA, 'spatial view'],
|
|
29
|
+
[ViewType.HEATMAP, 'cell by gene heatmap'],
|
|
30
|
+
[ViewType.LAYER_CONTROLLER, 'layer controller'],
|
|
31
|
+
[ViewType.LAYER_CONTROLLER_BETA, 'layer controller'],
|
|
32
|
+
[ViewType.GENOMIC_PROFILES, 'genome browser tracks with bar plots'],
|
|
33
|
+
[ViewType.GATING, 'scatterplot of gated gene expression data'],
|
|
34
|
+
[ViewType.FEATURE_LIST, 'interactive list of features'],
|
|
35
|
+
[ViewType.OBS_SETS, 'list of potential observation sets'],
|
|
36
|
+
[ViewType.OBS_SET_SIZES, 'sizes of selected observation sets'],
|
|
37
|
+
[ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION, 'violin plot with values'],
|
|
38
|
+
[ViewType.FEATURE_VALUE_HISTOGRAM, 'distribution of values'],
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Method for converting an array with strings to a natural sentence,
|
|
43
|
+
* concatenating the items with commans, and the last item with 'and'.
|
|
44
|
+
* @param {Object} config Vitessce config.
|
|
45
|
+
* @returns {string} Natural language sentence describing config (alt-text).
|
|
46
|
+
*/
|
|
47
|
+
export function getAltText(config) {
|
|
48
|
+
const componentList = config.layout.map(c => c.component);
|
|
49
|
+
const altText = `Vitessce grid with ${componentList.length} views, including ${arrayToString(componentList.map(c => ViewTypesToText.get(c) || 'plugin view'))}.`;
|
|
50
|
+
return altText;
|
|
51
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ViewType } from '@vitessce/constants-internal';
|
|
3
|
+
import { arrayToString, ViewTypesToText, getAltText } from './generate-alt-text.js';
|
|
4
|
+
|
|
5
|
+
describe('Tests for generating an alt text from the vitessce config', () => {
|
|
6
|
+
describe('Tests for arrayToString', () => {
|
|
7
|
+
it('should return empty string for empty array', () => {
|
|
8
|
+
const arr = [];
|
|
9
|
+
const str = arrayToString(arr);
|
|
10
|
+
expect(str).toEqual('');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should return the element if the araay only has one element', () => {
|
|
14
|
+
const arr = ['one'];
|
|
15
|
+
const str = arrayToString(arr);
|
|
16
|
+
expect(str).toEqual('one');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return the elements concatenated with "and" when the array has two elements', () => {
|
|
20
|
+
const arr = ['one', 'two'];
|
|
21
|
+
const str = arrayToString(arr);
|
|
22
|
+
expect(str).toEqual('one and two');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return the elements concatenated with ", " and the last two elements with "and" when the array has more than two elements', () => {
|
|
26
|
+
const arr = ['one', 'two', 'three', 'four'];
|
|
27
|
+
const str = arrayToString(arr);
|
|
28
|
+
expect(str).toEqual('one, two, three and four');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('Tests for (const) ViewTypesToText', () => {
|
|
33
|
+
it('should have a natural language mapping for every defined viewtype', () => {
|
|
34
|
+
expect(ViewTypesToText.length).toEqual(ViewType.length);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('Tests for getAltTest', () => {
|
|
39
|
+
const config = {
|
|
40
|
+
coordinationSpace: {},
|
|
41
|
+
datasets: {},
|
|
42
|
+
description: 'Spatial organization of the somatosensory cortex revealed by osmFISH',
|
|
43
|
+
initStrategy: 'auto',
|
|
44
|
+
layout: [
|
|
45
|
+
{ component: 'description', props: { description: 'Codeluppi et al., Nature Methods 2018: Spatial organization of the somatosensory cortex revealed by osmFISH' }, x: 0, y: 0, w: 2 },
|
|
46
|
+
{ component: 'layerController', x: 0, y: 1, w: 2, h: 4 },
|
|
47
|
+
{ component: 'status', x: 0, y: 5, w: 2, h: 1 },
|
|
48
|
+
{ component: 'spatial', props: { channelNamesVisible: true }, x: 2, y: 0, w: 4 },
|
|
49
|
+
{ component: 'featureList', x: 9, y: 0, w: 3, h: 2 },
|
|
50
|
+
{ component: 'obsSets', x: 9, y: 3, w: 3, h: 2 },
|
|
51
|
+
{ component: 'heatmap', props: { transpose: true }, x: 2, y: 4, w: 5 },
|
|
52
|
+
{ component: 'obsSetFeatureValueDistribution', x: 7, y: 4, w: 5, h: 2 },
|
|
53
|
+
{ component: 'scatterplot', x: 6, y: 0, w: 3, h: 2 },
|
|
54
|
+
{ component: 'scatterplot', x: 6, y: 2, w: 3, h: 2 },
|
|
55
|
+
],
|
|
56
|
+
name: 'Codeluppi et al., Nature Methods 2018',
|
|
57
|
+
uid: 'A',
|
|
58
|
+
version: '1.0.16',
|
|
59
|
+
};
|
|
60
|
+
const altText = getAltText(config);
|
|
61
|
+
it('should return a string', () => {
|
|
62
|
+
expect(typeof altText).toEqual('string');
|
|
63
|
+
});
|
|
64
|
+
it('should contain the number of views', () => {
|
|
65
|
+
const hasNViews = altText.includes('10');
|
|
66
|
+
expect(hasNViews).toEqual(true);
|
|
67
|
+
});
|
|
68
|
+
it('should contain mappings', () => {
|
|
69
|
+
const hasHeatmap = altText.includes('heatmap') && altText.includes('spatial') && altText.includes('description') && altText.includes('scatterplot');
|
|
70
|
+
expect(hasHeatmap).toEqual(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|