@vitessce/biomarker-select 3.5.1 → 3.5.3

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.
@@ -20,6 +20,27 @@ export function autocompleteFeature({ queryClient }: {
20
20
  export function transformFeature({ queryClient }: {
21
21
  queryClient: QueryClient;
22
22
  }, node: KgNode, targetModality: TargetModalityType): Promise<KgNode[]>;
23
+ /**
24
+ * @satisfies {GetAlternativeTermsFunc}
25
+ * @param {object} ctx
26
+ * @param {QueryClient} ctx.queryClient
27
+ * @param {string} curie
28
+ * @returns {Promise<string[]>} A list of curie strings.
29
+ */
30
+ export function getAlternativeTerms({ queryClient }: {
31
+ queryClient: QueryClient;
32
+ }, curie: string): Promise<string[]>;
33
+ /**
34
+ * @satisfies {GetTermMappingFunc}
35
+ * @param {object} ctx
36
+ * @param {QueryClient} ctx.queryClient
37
+ * @param {string} keyCuriePrefix
38
+ * @param {string} valCuriePrefix
39
+ * @returns {Promise<Map<string, string>>} A mapping between curie strings.
40
+ */
41
+ export function getTermMapping({ queryClient }: {
42
+ queryClient: QueryClient;
43
+ }, keyCuriePrefix: string, valCuriePrefix: string): Promise<Map<string, string>>;
23
44
  import type { QueryClient } from '@tanstack/react-query';
24
45
  import type { TargetModalityType } from '@vitessce/types';
25
46
  import type { KgNode } from '@vitessce/types';
@@ -1 +1 @@
1
- {"version":3,"file":"default-async-functions.d.ts","sourceRoot":"","sources":["../src/default-async-functions.js"],"names":[],"mappings":"AA4GA;;;;;;;GAOG;AACH,qDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,WAAQ,MAAM,kBACN,IAAI,GAAG,kBAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiB7B;AAeD;;;;;;;GAOG;AACH,kDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,QAAQ,MAAM,kBACN,kBAAkB,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAkC7B;iCAlLsD,uBAAuB;wCADyB,iBAAiB;4BAAjB,iBAAiB"}
1
+ {"version":3,"file":"default-async-functions.d.ts","sourceRoot":"","sources":["../src/default-async-functions.js"],"names":[],"mappings":"AAqHA;;;;;;;GAOG;AACH,qDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,WAAQ,MAAM,kBACN,IAAI,GAAG,kBAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiB7B;AAeD;;;;;;;GAOG;AACH,kDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,QAAQ,MAAM,kBACN,kBAAkB,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAkC7B;AAED;;;;;;GAMG;AACH,qDAJG;IAAyB,WAAW,EAA5B,WAAW;CACnB,SAAQ,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CA2B7B;AAED;;;;;;;GAOG;AACH,gDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,kBAAQ,MAAM,kBACN,MAAM,GACJ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoBxC;iCAzPsD,uBAAuB;wCADsE,iBAAiB;4BAAjB,iBAAiB"}
@@ -4,9 +4,10 @@
4
4
  import { csvParse } from 'd3-dsv';
5
5
  // eslint-disable-next-line import/no-unresolved
6
6
  import Fuse from 'fuse.js/basic';
7
- /** @import { KgNode, KgEdge, TargetModalityType, AutocompleteFeatureFunc, TransformFeatureFunc } from '@vitessce/types' */
7
+ /** @import { KgNode, KgEdge, TargetModalityType, AutocompleteFeatureFunc, TransformFeatureFunc, GetAlternativeTermsFunc, GetTermMappingFunc } from '@vitessce/types' */
8
8
  /** @import { QueryClient, QueryFunctionContext } from '@tanstack/react-query' */
9
9
  const KG_BASE_URL = 'https://storage.googleapis.com/vitessce-demo-data/enrichr-kg-september-2023';
10
+ const ENSG_TO_GENE_SYMBOL_URL = 'https://vitessce-resources.s3.us-east-2.amazonaws.com/genes_filtered.json';
10
11
  /**
11
12
  * @returns {Promise<KgNode[]>}
12
13
  */
@@ -55,6 +56,13 @@ function loadPathwayNodes() {
55
56
  }));
56
57
  });
57
58
  }
59
+ /**
60
+ * @returns {Promise<Record<string,string>>}
61
+ */
62
+ function loadEnsgToGeneSymbolMapping() {
63
+ return fetch(ENSG_TO_GENE_SYMBOL_URL)
64
+ .then(res => res.json());
65
+ }
58
66
  // Parent app can pass in queryClient
59
67
  // (to every async function) so that functions can call .fetchQuery
60
68
  // Reference: https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientfetchquery
@@ -166,3 +174,58 @@ export async function transformFeature({ queryClient }, node, targetModality) {
166
174
  // TODO: handle other target modalities
167
175
  return [];
168
176
  }
177
+ /**
178
+ * @satisfies {GetAlternativeTermsFunc}
179
+ * @param {object} ctx
180
+ * @param {QueryClient} ctx.queryClient
181
+ * @param {string} curie
182
+ * @returns {Promise<string[]>} A list of curie strings.
183
+ */
184
+ export async function getAlternativeTerms({ queryClient }, curie) {
185
+ // Reference: https://registry.identifiers.org/registry/ensembl
186
+ // Currently, we only map Ensembl gene IDs to gene symbols,
187
+ // using our own JSON file.
188
+ // In the future, we can expand this functionality.
189
+ const inputIsEnsemblGeneId = curie.toUpperCase().startsWith('ENSEMBL:ENSG');
190
+ if (inputIsEnsemblGeneId) {
191
+ const idMapping = await queryClient.fetchQuery({
192
+ queryKey: ['ensgToGeneSymbolMapping'],
193
+ staleTime: Infinity,
194
+ queryFn: loadEnsgToGeneSymbolMapping,
195
+ });
196
+ // In our current JSON file, the ENSG IDs are not prefixed with 'ENSEMBL:'.
197
+ const ensemblId = curie.split(':')[1];
198
+ let geneSymbol = idMapping?.[ensemblId];
199
+ if (geneSymbol) {
200
+ if (!geneSymbol.toUpperCase().startsWith('HGNC:')) {
201
+ // In our current JSON file, the gene symbols are not prefixed with 'HGNC:'.
202
+ geneSymbol = `HGNC:${geneSymbol}`;
203
+ }
204
+ return [geneSymbol];
205
+ }
206
+ }
207
+ return [];
208
+ }
209
+ /**
210
+ * @satisfies {GetTermMappingFunc}
211
+ * @param {object} ctx
212
+ * @param {QueryClient} ctx.queryClient
213
+ * @param {string} keyCuriePrefix
214
+ * @param {string} valCuriePrefix
215
+ * @returns {Promise<Map<string, string>>} A mapping between curie strings.
216
+ */
217
+ export async function getTermMapping({ queryClient }, keyCuriePrefix, valCuriePrefix) {
218
+ if ((keyCuriePrefix.toUpperCase() === 'ENSEMBL' && valCuriePrefix.toUpperCase() === 'HGNC')
219
+ || (keyCuriePrefix.toUpperCase() === 'HGNC' && valCuriePrefix.toUpperCase() === 'ENSEMBL')) {
220
+ const idMapping = await queryClient.fetchQuery({
221
+ queryKey: ['ensgToGeneSymbolMapping'],
222
+ staleTime: Infinity,
223
+ queryFn: loadEnsgToGeneSymbolMapping,
224
+ });
225
+ const isReversed = (keyCuriePrefix.toUpperCase() === 'HGNC');
226
+ return new Map(Object.entries(idMapping).map(([key, value]) => (isReversed
227
+ ? ([`HGNC:${value}`, `ENSEMBL:${key}`])
228
+ : ([`ENSEMBL:${key}`, `HGNC:${value}`]))));
229
+ }
230
+ throw new Error(`Mapping between ${keyCuriePrefix} and ${valCuriePrefix} is not yet implemented.`);
231
+ }
@@ -1,3 +1,3 @@
1
1
  export { BiomarkerSelectSubscriber } from "./BiomarkerSelectSubscriber.js";
2
- export { autocompleteFeature, transformFeature } from "./default-async-functions.js";
2
+ export { autocompleteFeature, transformFeature, getAlternativeTerms, getTermMapping } from "./default-async-functions.js";
3
3
  //# sourceMappingURL=index.d.ts.map
package/dist-tsc/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { BiomarkerSelectSubscriber } from './BiomarkerSelectSubscriber.js';
2
- export { autocompleteFeature, transformFeature, } from './default-async-functions.js';
2
+ export { autocompleteFeature, transformFeature, getAlternativeTerms, getTermMapping, } from './default-async-functions.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitessce/biomarker-select",
3
- "version": "3.5.1",
3
+ "version": "3.5.3",
4
4
  "author": "Gehlenborg Lab",
5
5
  "homepage": "http://vitessce.io",
6
6
  "repository": {
@@ -24,9 +24,9 @@
24
24
  "react-window": "^1.8.10",
25
25
  "fuse.js": "^7.0.0",
26
26
  "d3-dsv": "^1.1.1",
27
- "@vitessce/constants-internal": "3.5.1",
28
- "@vitessce/vit-s": "3.5.1",
29
- "@vitessce/types": "3.5.1"
27
+ "@vitessce/constants-internal": "3.5.3",
28
+ "@vitessce/vit-s": "3.5.3",
29
+ "@vitessce/types": "3.5.3"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@testing-library/jest-dom": "^5.16.4",
@@ -5,10 +5,11 @@ import { csvParse } from 'd3-dsv';
5
5
  // eslint-disable-next-line import/no-unresolved
6
6
  import Fuse from 'fuse.js/basic';
7
7
 
8
- /** @import { KgNode, KgEdge, TargetModalityType, AutocompleteFeatureFunc, TransformFeatureFunc } from '@vitessce/types' */
8
+ /** @import { KgNode, KgEdge, TargetModalityType, AutocompleteFeatureFunc, TransformFeatureFunc, GetAlternativeTermsFunc, GetTermMappingFunc } from '@vitessce/types' */
9
9
  /** @import { QueryClient, QueryFunctionContext } from '@tanstack/react-query' */
10
10
 
11
11
  const KG_BASE_URL = 'https://storage.googleapis.com/vitessce-demo-data/enrichr-kg-september-2023';
12
+ const ENSG_TO_GENE_SYMBOL_URL = 'https://vitessce-resources.s3.us-east-2.amazonaws.com/genes_filtered.json';
12
13
 
13
14
  /**
14
15
  * @returns {Promise<KgNode[]>}
@@ -61,6 +62,14 @@ function loadPathwayNodes() {
61
62
  });
62
63
  }
63
64
 
65
+ /**
66
+ * @returns {Promise<Record<string,string>>}
67
+ */
68
+ function loadEnsgToGeneSymbolMapping() {
69
+ return fetch(ENSG_TO_GENE_SYMBOL_URL)
70
+ .then(res => res.json());
71
+ }
72
+
64
73
  // Parent app can pass in queryClient
65
74
  // (to every async function) so that functions can call .fetchQuery
66
75
  // Reference: https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientfetchquery
@@ -185,3 +194,65 @@ export async function transformFeature({ queryClient }, node, targetModality) {
185
194
  // TODO: handle other target modalities
186
195
  return [];
187
196
  }
197
+
198
+ /**
199
+ * @satisfies {GetAlternativeTermsFunc}
200
+ * @param {object} ctx
201
+ * @param {QueryClient} ctx.queryClient
202
+ * @param {string} curie
203
+ * @returns {Promise<string[]>} A list of curie strings.
204
+ */
205
+ export async function getAlternativeTerms({ queryClient }, curie) {
206
+ // Reference: https://registry.identifiers.org/registry/ensembl
207
+ // Currently, we only map Ensembl gene IDs to gene symbols,
208
+ // using our own JSON file.
209
+ // In the future, we can expand this functionality.
210
+ const inputIsEnsemblGeneId = curie.toUpperCase().startsWith('ENSEMBL:ENSG');
211
+
212
+ if (inputIsEnsemblGeneId) {
213
+ const idMapping = await queryClient.fetchQuery({
214
+ queryKey: ['ensgToGeneSymbolMapping'],
215
+ staleTime: Infinity,
216
+ queryFn: loadEnsgToGeneSymbolMapping,
217
+ });
218
+ // In our current JSON file, the ENSG IDs are not prefixed with 'ENSEMBL:'.
219
+ const ensemblId = curie.split(':')[1];
220
+ let geneSymbol = idMapping?.[ensemblId];
221
+ if (geneSymbol) {
222
+ if (!geneSymbol.toUpperCase().startsWith('HGNC:')) {
223
+ // In our current JSON file, the gene symbols are not prefixed with 'HGNC:'.
224
+ geneSymbol = `HGNC:${geneSymbol}`;
225
+ }
226
+ return [geneSymbol];
227
+ }
228
+ }
229
+ return [];
230
+ }
231
+
232
+ /**
233
+ * @satisfies {GetTermMappingFunc}
234
+ * @param {object} ctx
235
+ * @param {QueryClient} ctx.queryClient
236
+ * @param {string} keyCuriePrefix
237
+ * @param {string} valCuriePrefix
238
+ * @returns {Promise<Map<string, string>>} A mapping between curie strings.
239
+ */
240
+ export async function getTermMapping({ queryClient }, keyCuriePrefix, valCuriePrefix) {
241
+ if (
242
+ (keyCuriePrefix.toUpperCase() === 'ENSEMBL' && valCuriePrefix.toUpperCase() === 'HGNC')
243
+ || (keyCuriePrefix.toUpperCase() === 'HGNC' && valCuriePrefix.toUpperCase() === 'ENSEMBL')
244
+ ) {
245
+ const idMapping = await queryClient.fetchQuery({
246
+ queryKey: ['ensgToGeneSymbolMapping'],
247
+ staleTime: Infinity,
248
+ queryFn: loadEnsgToGeneSymbolMapping,
249
+ });
250
+ const isReversed = (keyCuriePrefix.toUpperCase() === 'HGNC');
251
+ return new Map(Object.entries(idMapping).map(([key, value]) => (
252
+ isReversed
253
+ ? ([`HGNC:${value}`, `ENSEMBL:${key}`])
254
+ : ([`ENSEMBL:${key}`, `HGNC:${value}`])
255
+ )));
256
+ }
257
+ throw new Error(`Mapping between ${keyCuriePrefix} and ${valCuriePrefix} is not yet implemented.`);
258
+ }
package/src/index.js CHANGED
@@ -2,4 +2,6 @@ export { BiomarkerSelectSubscriber } from './BiomarkerSelectSubscriber.js';
2
2
  export {
3
3
  autocompleteFeature,
4
4
  transformFeature,
5
+ getAlternativeTerms,
6
+ getTermMapping,
5
7
  } from './default-async-functions.js';