@jbrowse/plugin-rdf 2.6.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.
Files changed (38) hide show
  1. package/LICENSE +201 -0
  2. package/dist/SPARQLAdapter/SPARQLAdapter.d.ts +23 -0
  3. package/dist/SPARQLAdapter/SPARQLAdapter.js +178 -0
  4. package/dist/SPARQLAdapter/SPARQLAdapter.js.map +1 -0
  5. package/dist/SPARQLAdapter/configSchema.d.ts +31 -0
  6. package/dist/SPARQLAdapter/configSchema.js +34 -0
  7. package/dist/SPARQLAdapter/configSchema.js.map +1 -0
  8. package/dist/SPARQLAdapter/index.d.ts +2 -0
  9. package/dist/SPARQLAdapter/index.js +11 -0
  10. package/dist/SPARQLAdapter/index.js.map +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +39 -0
  13. package/dist/index.js.map +1 -0
  14. package/esm/SPARQLAdapter/SPARQLAdapter.d.ts +23 -0
  15. package/esm/SPARQLAdapter/SPARQLAdapter.js +172 -0
  16. package/esm/SPARQLAdapter/SPARQLAdapter.js.map +1 -0
  17. package/esm/SPARQLAdapter/configSchema.d.ts +31 -0
  18. package/esm/SPARQLAdapter/configSchema.js +32 -0
  19. package/esm/SPARQLAdapter/configSchema.js.map +1 -0
  20. package/esm/SPARQLAdapter/index.d.ts +2 -0
  21. package/esm/SPARQLAdapter/index.js +3 -0
  22. package/esm/SPARQLAdapter/index.js.map +1 -0
  23. package/esm/index.d.ts +6 -0
  24. package/esm/index.js +33 -0
  25. package/esm/index.js.map +1 -0
  26. package/package.json +56 -0
  27. package/src/SPARQLAdapter/README.md +115 -0
  28. package/src/SPARQLAdapter/SPARQLAdapter.test.ts +84 -0
  29. package/src/SPARQLAdapter/SPARQLAdapter.ts +257 -0
  30. package/src/SPARQLAdapter/__snapshots__/SPARQLAdapter.test.ts.snap +449 -0
  31. package/src/SPARQLAdapter/configSchema.ts +40 -0
  32. package/src/SPARQLAdapter/index.ts +2 -0
  33. package/src/SPARQLAdapter/test_data/emptyQueryResponse.json +30 -0
  34. package/src/SPARQLAdapter/test_data/queryResponse.json +3834 -0
  35. package/src/SPARQLAdapter/test_data/refNamesResponse.json +114 -0
  36. package/src/__snapshots__/index.test.ts.snap +3 -0
  37. package/src/index.test.ts +18 -0
  38. package/src/index.ts +46 -0
@@ -0,0 +1,172 @@
1
+ import { BaseFeatureDataAdapter, } from '@jbrowse/core/data_adapters/BaseAdapter';
2
+ import { ObservableCreate } from '@jbrowse/core/util/rxjs';
3
+ import SimpleFeature from '@jbrowse/core/util/simpleFeature';
4
+ import format from 'string-template';
5
+ import { readConfObject } from '@jbrowse/core/configuration';
6
+ export default class SPARQLAdapter extends BaseFeatureDataAdapter {
7
+ constructor(config, getSubAdapter, pluginManager) {
8
+ super(config, getSubAdapter, pluginManager);
9
+ this.endpoint = readConfObject(config, 'endpoint').uri;
10
+ this.queryTemplate = readConfObject(config, 'queryTemplate');
11
+ this.additionalQueryParams = readConfObject(config, 'additionalQueryParams');
12
+ this.refNamesQueryTemplate = readConfObject(config, 'refNamesQueryTemplate');
13
+ this.configRefNames = readConfObject(config, 'refNames');
14
+ }
15
+ async getRefNames(opts = {}) {
16
+ if (this.refNames) {
17
+ return this.refNames;
18
+ }
19
+ let refNames = [];
20
+ if (this.refNamesQueryTemplate) {
21
+ const queryTemplate = encodeURIComponent(this.refNamesQueryTemplate);
22
+ const results = await this.querySparql(queryTemplate, opts);
23
+ refNames = this.resultsToRefNames(results);
24
+ }
25
+ else if (this.configRefNames) {
26
+ refNames = this.configRefNames;
27
+ }
28
+ this.refNames = refNames;
29
+ return refNames;
30
+ }
31
+ getFeatures(query, opts = {}) {
32
+ return ObservableCreate(async (observer) => {
33
+ const filledTemplate = encodeURIComponent(format(this.queryTemplate, query));
34
+ const { refName } = query;
35
+ const results = await this.querySparql(filledTemplate, opts);
36
+ this.resultsToFeatures(results, refName).forEach(feature => {
37
+ observer.next(feature);
38
+ });
39
+ observer.complete();
40
+ }, opts.signal);
41
+ }
42
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
+ async querySparql(query, opts) {
44
+ let additionalQueryParams = '';
45
+ if (this.additionalQueryParams.length) {
46
+ additionalQueryParams = `&${this.additionalQueryParams.join('&')}`;
47
+ }
48
+ const signal = opts && opts.signal;
49
+ const response = await fetch(`${this.endpoint}?query=${query}${additionalQueryParams}`, {
50
+ headers: { accept: 'application/json,application/sparql-results+json' },
51
+ signal,
52
+ });
53
+ return response.json();
54
+ }
55
+ resultsToRefNames(response) {
56
+ const rows = ((response || {}).results || {}).bindings || [];
57
+ if (!rows.length) {
58
+ return [];
59
+ }
60
+ const fields = response.head.vars;
61
+ if (!fields.includes('refName')) {
62
+ throw new Error('"refName" not found in refNamesQueryTemplate response');
63
+ }
64
+ return rows.map(row => row.refName.value);
65
+ }
66
+ resultsToFeatures(results, refName) {
67
+ const rows = ((results || {}).results || {}).bindings || [];
68
+ if (!rows.length) {
69
+ return [];
70
+ }
71
+ const fields = results.head.vars;
72
+ const requiredFields = ['start', 'end', 'uniqueId'];
73
+ requiredFields.forEach(requiredField => {
74
+ if (!fields.includes(requiredField)) {
75
+ console.error(`Required field ${requiredField} missing from feature data`);
76
+ }
77
+ });
78
+ const seenFeatures = {};
79
+ rows.forEach(row => {
80
+ const rawData = [{}];
81
+ fields.forEach(field => {
82
+ if (field in row) {
83
+ const { value } = row[field];
84
+ let idx = 0;
85
+ while (field.startsWith('sub_')) {
86
+ field = field.slice(4);
87
+ idx += 1;
88
+ }
89
+ while (idx > rawData.length - 1) {
90
+ rawData.push({});
91
+ }
92
+ rawData[idx][field] = value;
93
+ }
94
+ });
95
+ rawData.forEach((rd, idx) => {
96
+ const { uniqueId } = rd;
97
+ if (idx < rawData.length - 1) {
98
+ rawData[idx + 1].parentUniqueId = uniqueId;
99
+ }
100
+ seenFeatures[uniqueId] = {
101
+ data: {
102
+ ...rd,
103
+ uniqueId,
104
+ refName,
105
+ start: parseInt(rd.start, 10),
106
+ end: parseInt(rd.end, 10),
107
+ strand: parseInt(rd.strand, 10) || 0,
108
+ },
109
+ };
110
+ });
111
+ });
112
+ // resolve subfeatures, keeping only top-level features in seenFeatures
113
+ for (const [uniqueId, f] of Object.entries(seenFeatures)) {
114
+ const pid = f.data.parentUniqueId;
115
+ delete f.data.parentUniqueId;
116
+ if (pid) {
117
+ const p = seenFeatures[pid];
118
+ if (p) {
119
+ if (!p.data.subfeatures) {
120
+ p.data.subfeatures = [];
121
+ }
122
+ p.data.subfeatures.push({
123
+ ...f.data,
124
+ uniqueId,
125
+ });
126
+ delete seenFeatures[uniqueId];
127
+ }
128
+ else {
129
+ const subfeatures = Object.values(seenFeatures)
130
+ .map(sf => sf.data.subfeatures)
131
+ .filter(sf => !!sf)
132
+ .flat();
133
+ let found = false;
134
+ for (const subfeature of subfeatures) {
135
+ if (subfeature && subfeature.uniqueId === pid) {
136
+ if (!subfeature.subfeatures) {
137
+ subfeature.subfeatures = [];
138
+ }
139
+ subfeature.subfeatures.push({
140
+ ...f.data,
141
+ uniqueId,
142
+ });
143
+ delete seenFeatures[uniqueId];
144
+ found = true;
145
+ break;
146
+ }
147
+ else if (subfeature && subfeature.subfeatures) {
148
+ subfeatures.push(...subfeature.subfeatures);
149
+ }
150
+ }
151
+ if (!found) {
152
+ console.error(`Could not find parentID ${pid}`);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ return Object.keys(seenFeatures).map(seenFeature => new SimpleFeature({
158
+ ...seenFeatures[seenFeature].data,
159
+ uniqueId: seenFeature,
160
+ subfeatures: seenFeatures[seenFeature].data.subfeatures,
161
+ }));
162
+ }
163
+ async hasDataForRefName(refName, opts = {}) {
164
+ const refNames = await this.getRefNames(opts);
165
+ if (refNames.length && !refNames.includes(refName)) {
166
+ return false;
167
+ }
168
+ return true;
169
+ }
170
+ freeResources( /* { region } */) { }
171
+ }
172
+ //# sourceMappingURL=SPARQLAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SPARQLAdapter.js","sourceRoot":"","sources":["../../src/SPARQLAdapter/SPARQLAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ declare const _default: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
+ endpoint: {
3
+ type: string;
4
+ defaultValue: {
5
+ uri: string;
6
+ locationType: string;
7
+ };
8
+ description: string;
9
+ };
10
+ queryTemplate: {
11
+ type: string;
12
+ defaultValue: string;
13
+ description: string;
14
+ };
15
+ refNamesQueryTemplate: {
16
+ type: string;
17
+ defaultValue: string;
18
+ description: string;
19
+ };
20
+ refNames: {
21
+ type: string;
22
+ defaultValue: never[];
23
+ description: string;
24
+ };
25
+ additionalQueryParams: {
26
+ type: string;
27
+ defaultValue: never[];
28
+ description: string;
29
+ };
30
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
31
+ export default _default;
@@ -0,0 +1,32 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration';
2
+ export default ConfigurationSchema('SPARQLAdapter', {
3
+ endpoint: {
4
+ type: 'fileLocation',
5
+ defaultValue: {
6
+ uri: 'https://somesite.com/sparql',
7
+ locationType: 'UriLocation',
8
+ },
9
+ description: 'URL of the SPARQL endpoint',
10
+ },
11
+ queryTemplate: {
12
+ type: 'text',
13
+ defaultValue: '',
14
+ description: 'SPARQL query where {start} {end} and {refName} will get replaced for each call',
15
+ },
16
+ refNamesQueryTemplate: {
17
+ type: 'text',
18
+ defaultValue: '',
19
+ description: 'SPARQL query that returns the possible refNames in a ?refName column',
20
+ },
21
+ refNames: {
22
+ type: 'stringArray',
23
+ defaultValue: [],
24
+ description: 'Possible refNames used by the SPARQL endpoint (ignored if "refNamesQueryTemplate" is provided)',
25
+ },
26
+ additionalQueryParams: {
27
+ type: 'stringArray',
28
+ defaultValue: [],
29
+ description: 'Additional parameters to add to the query, e.g. "format=JSON"',
30
+ },
31
+ }, { explicitlyTyped: true });
32
+ //# sourceMappingURL=configSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configSchema.js","sourceRoot":"","sources":["../../src/SPARQLAdapter/configSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,eAAe,mBAAmB,CAChC,eAAe,EACf;IACE,QAAQ,EAAE;QACR,IAAI,EAAE,cAAc;QACpB,YAAY,EAAE;YACZ,GAAG,EAAE,6BAA6B;YAClC,YAAY,EAAE,aAAa;SAC5B;QACD,WAAW,EAAE,4BAA4B;KAC1C;IACD,aAAa,EAAE;QACb,IAAI,EAAE,MAAM;QACZ,YAAY,EAAE,EAAE;QAChB,WAAW,EACT,gFAAgF;KACnF;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,MAAM;QACZ,YAAY,EAAE,EAAE;QAChB,WAAW,EACT,sEAAsE;KACzE;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,aAAa;QACnB,YAAY,EAAE,EAAE;QAChB,WAAW,EACT,gGAAgG;KACnG;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,aAAa;QACnB,YAAY,EAAE,EAAE;QAChB,WAAW,EACT,+DAA+D;KAClE;CACF,EACD,EAAE,eAAe,EAAE,IAAI,EAAE,CAC1B,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { default as AdapterClass } from './SPARQLAdapter';
2
+ export { default as configSchema } from './configSchema';
@@ -0,0 +1,3 @@
1
+ export { default as AdapterClass } from './SPARQLAdapter';
2
+ export { default as configSchema } from './configSchema';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/SPARQLAdapter/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
package/esm/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import Plugin from '@jbrowse/core/Plugin';
2
+ import PluginManager from '@jbrowse/core/PluginManager';
3
+ export default class RdfPlugin extends Plugin {
4
+ name: string;
5
+ install(pluginManager: PluginManager): void;
6
+ }
package/esm/index.js ADDED
@@ -0,0 +1,33 @@
1
+ import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType';
2
+ import Plugin from '@jbrowse/core/Plugin';
3
+ import { AdapterClass as SPARQLAdapterClass, configSchema as sparqlAdapterConfigSchema, } from './SPARQLAdapter';
4
+ import { getFileName } from '@jbrowse/core/util/tracks';
5
+ export default class RdfPlugin extends Plugin {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.name = 'RdfPlugin';
9
+ }
10
+ install(pluginManager) {
11
+ pluginManager.addAdapterType(() => new AdapterType({
12
+ name: 'SPARQLAdapter',
13
+ displayName: 'SPARQL adapter',
14
+ configSchema: sparqlAdapterConfigSchema,
15
+ AdapterClass: SPARQLAdapterClass,
16
+ }));
17
+ pluginManager.addToExtensionPoint('Core-guessAdapterForLocation', (adapterGuesser) => {
18
+ return (file, index, adapterHint) => {
19
+ const regexGuess = /\/sparql$/i;
20
+ const adapterName = 'SPARQLAdapter';
21
+ const fileName = getFileName(file);
22
+ if (regexGuess.test(fileName) || adapterHint === adapterName) {
23
+ return {
24
+ type: adapterName,
25
+ endpoint: file,
26
+ };
27
+ }
28
+ return adapterGuesser(file, index, adapterHint);
29
+ };
30
+ });
31
+ }
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,iDAAiD,CAAA;AACzE,OAAO,MAAM,MAAM,sBAAsB,CAAA;AAGzC,OAAO,EACL,YAAY,IAAI,kBAAkB,EAClC,YAAY,IAAI,yBAAyB,GAC1C,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAkB,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,MAAM;IAA7C;;QACE,SAAI,GAAG,WAAW,CAAA;IAkCpB,CAAC;IAhCC,OAAO,CAAC,aAA4B;QAClC,aAAa,CAAC,cAAc,CAC1B,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;YACd,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,gBAAgB;YAC7B,YAAY,EAAE,yBAAyB;YACvC,YAAY,EAAE,kBAAkB;SACjC,CAAC,CACL,CAAA;QACD,aAAa,CAAC,mBAAmB,CAC/B,8BAA8B,EAC9B,CAAC,cAA8B,EAAE,EAAE;YACjC,OAAO,CACL,IAAkB,EAClB,KAAoB,EACpB,WAAoB,EACpB,EAAE;gBACF,MAAM,UAAU,GAAG,YAAY,CAAA;gBAC/B,MAAM,WAAW,GAAG,eAAe,CAAA;gBACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;gBAClC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,WAAW,KAAK,WAAW,EAAE;oBAC5D,OAAO;wBACL,IAAI,EAAE,WAAW;wBACjB,QAAQ,EAAE,IAAI;qBACf,CAAA;iBACF;gBACD,OAAO,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;YACjD,CAAC,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@jbrowse/plugin-rdf",
3
+ "version": "2.6.1",
4
+ "description": "JBrowse 2 RDF resources",
5
+ "keywords": [
6
+ "jbrowse",
7
+ "jbrowse2"
8
+ ],
9
+ "license": "Apache-2.0",
10
+ "homepage": "https://jbrowse.org",
11
+ "bugs": "https://github.com/GMOD/jbrowse-components/issues",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/GMOD/jbrowse-components.git",
15
+ "directory": "plugins/rdf"
16
+ },
17
+ "author": "JBrowse Team",
18
+ "distMain": "dist/index.js",
19
+ "srcMain": "src/index.ts",
20
+ "main": "dist/index.js",
21
+ "files": [
22
+ "dist",
23
+ "src",
24
+ "esm"
25
+ ],
26
+ "scripts": {
27
+ "build": "npm-run-all build:*",
28
+ "test": "cd ../..; jest plugins/rdf",
29
+ "prepublishOnly": "yarn test",
30
+ "prepack": "yarn build && yarn useDist",
31
+ "postpack": "yarn useSrc",
32
+ "useDist": "node ../../scripts/useDist.js",
33
+ "useSrc": "node ../../scripts/useSrc.js",
34
+ "prebuild": "npm run clean",
35
+ "build:esm": "tsc --build tsconfig.build.esm.json",
36
+ "build:es5": "tsc --build tsconfig.build.es5.json",
37
+ "clean": "rimraf dist esm *.tsbuildinfo"
38
+ },
39
+ "dependencies": {
40
+ "string-template": "^1.0.0"
41
+ },
42
+ "peerDependencies": {
43
+ "@jbrowse/core": "^2.0.0",
44
+ "mobx": "^6.0.0",
45
+ "mobx-react": "^7.0.0",
46
+ "mobx-state-tree": "^5.0.0",
47
+ "rxjs": "^7.0.0"
48
+ },
49
+ "distModule": "esm/index.js",
50
+ "srcModule": "src/index.ts",
51
+ "module": "esm/index.js",
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "gitHead": "1cbe7ba097fb2d2763c776e5e429e4670cdd583c"
56
+ }
@@ -0,0 +1,115 @@
1
+ # SPARQL Adapter
2
+
3
+ JBrowse can display genomic information stored in RDF data stores by accessing
4
+ them via a SPARQL endpoint. This is done by configuring a SPARQL adapter.
5
+
6
+ ## Query template
7
+
8
+ The most basic configuration starts with a SPARQL query that returns features in
9
+ a genomic range, i.e. on a particular chromosome/contig and between a start and
10
+ end position. In such a query, replace the chromosome/contig name with
11
+ `{refName}` and the start and end with `{start}` and `{end}`. For example
12
+
13
+ ```sparql
14
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
15
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
16
+ PREFIX faldo: <http://biohackathon.org/resource/faldo#>
17
+ PREFIX dc: <http://purl.org/dc/elements/1.1/>
18
+
19
+ SELECT DISTINCT ?gene (?id AS ?uniqueId) (?label AS ?name) (?desc AS ?note) ?strand ?start ?end
20
+ WHERE
21
+ { VALUES ?location_type { faldo:ForwardStrandPosition faldo:ReverseStrandPosition faldo:BothStrandsPosition }
22
+ ?location faldo:begin _:b0 .
23
+ _:b0 rdf:type ?location_type ;
24
+ faldo:position ?faldo_begin .
25
+ ?location faldo:end _:b1 .
26
+ _:b1 rdf:type ?location_type ;
27
+ faldo:position ?faldo_end .
28
+ ?location faldo:reference <http://rdf.ebi.ac.uk/resource/ensembl/97/homo_sapiens/GRCh38/{refName}> .
29
+ ?gene rdf:type ?type ;
30
+ rdfs:label ?label ;
31
+ dc:description ?desc ;
32
+ dc:identifier ?id ;
33
+ faldo:location ?location
34
+ BIND(if(( ?location_type = faldo:ForwardStrandPosition ), 1, if(( ?location_type = faldo:ReverseStrandPosition ), -1, 0)) AS ?strand)
35
+ BIND(if(( ?strand = -1 ), ?faldo_end, ?faldo_begin) AS ?start)
36
+ BIND(if(( ?strand = -1 ), ?faldo_begin, ?faldo_end) AS ?end)
37
+ FILTER ( ( ?start >= {start} ) && ( ?end <= {end} ) )
38
+ }
39
+ ```
40
+
41
+ The SELECT in the the query must provide at least the variables `?start`,
42
+ `?end`, and `?uniqueId`. Any other variables will be added to the feature data.
43
+
44
+ ## Adding a track
45
+
46
+ From a JBrowse track selector, click the "+" icon and choose "Add track". When
47
+ asked for the location of the data source, enter the SPARQL endpoint. If the
48
+ endpoint ends with `/sparql`, JBrowse will automatically choose the SPARQL
49
+ adapter. If not, choose "SPARQL adapter" in the resulting dialog. (You can use
50
+ https://www.ebi.ac.uk/rdf/services/sparql as the endpoint to demonstrate the
51
+ above example.)
52
+
53
+ You will then be able to choose a track name and type as well as the assembly to
54
+ which the track should be added. BasicTrack is suggested for most
55
+ configurations, and using other track types is covered below. Click the "Add"
56
+ button to add the track.
57
+
58
+ Next, in the track selector click the settings icon next to the track which was
59
+ just added. Paste the query template (see above) in the "queryTemplate" section.
60
+ You can also configure other aspects of the track such as a description,
61
+ category, etc.
62
+
63
+ ## Advanced configuration
64
+
65
+ ### Subfeatures
66
+
67
+ There are two ways to provide subfeature information. The first is to include a
68
+ `?parentUniqueId` variable with a feature. It will be created as a subfeature of
69
+ the feature with a matching `?uniqueId`.
70
+
71
+ The second way is useful if a single query response line contains information
72
+ for more than one feature, e.g. gene, transcript, and exon information on a
73
+ single line. For this type of data prefix all variables for the subfeature with
74
+ `sub_`, which will allow you to define multiple features from the same line. It
75
+ also works for deeper nested features, too, by using `sub_sub_`, etc. Parent
76
+ features that are duplicated across lines will be resolved into a single
77
+ feature. For example, take the following SPARQL query result lines:
78
+
79
+ | uniqueId | type | start | end | sub_uniqueId | sub_type | sub_start | sub_end | sub_sub_uniqueId | sub_sub_type | sub_sub_start | sub_sub_end |
80
+ | ---------- | ---- | -------- | -------- | ---------------- | ---------- | --------- | -------- | ---------------- | ------------ | ------------- | ----------- |
81
+ | geneId0001 | gene | 10430102 | 10452003 | transcriptId0001 | transcript | 10430518 | 10442405 | exonId0001 | exon | 10430518 | 10430568 |
82
+ | geneId0001 | gene | 10430102 | 10452003 | transcriptId0001 | transcript | 10430518 | 10442405 | exonId0002 | exon | 10432568 | 10433965 |
83
+
84
+ These two lines will resolve into a singe feature "geneId0001" with one child
85
+ feature "transcriptId0001", which will then itself have two child features
86
+ "exonId0001" and "exonId0002".
87
+
88
+ ### Additional query parameters
89
+
90
+ JBrowse will automatically send a header stating that it expects responses to be
91
+ in the `application/json` or `application/sparql-results+json` format. Some
92
+ SPARQL endpoints, however, require additional query parameters to be passed in
93
+ order for the results be returned in JSON format, for example `format=json`.
94
+ These can be added to the "additionalQueryParams" section and will be appended
95
+ to each SPARQL request.
96
+
97
+ ### Reference sequence renaming
98
+
99
+ In order for the track to take advantage of JBrowse's reference name aliasing,
100
+ it must know what reference name the SPARQL store uses. These can be entered in
101
+ one of two ways. The first is by entering a SPARQL query in the
102
+ "refNamesQueryTemplate" config section. This query should return a line for each
103
+ reference name in a `refName` column.
104
+
105
+ The second option is to enumerate the reference names explicitly in the
106
+ "refNames" config section. These will be ignored if a "refNamesQueryTemplate" is
107
+ defined.
108
+
109
+ ### Other track types
110
+
111
+ BasicTracks are flexible because they don't require any additional information,
112
+ any any additional info provided in the query is just added to the feature. You
113
+ can use other tracks as well, though, as long as you make sure the SPARQL query
114
+ provides any info the track requires. For example, if you want to use a
115
+ VariantTrack, the SPARQL query must provide REF, ALT, QUAL, etc.
@@ -0,0 +1,84 @@
1
+ import { toArray } from 'rxjs/operators'
2
+ import 'whatwg-fetch'
3
+ import Adapter from './SPARQLAdapter'
4
+ import emptyQueryResponse from './test_data/emptyQueryResponse.json'
5
+ import queryResponse from './test_data/queryResponse.json'
6
+ import refNamesResponse from './test_data/refNamesResponse.json'
7
+
8
+ import configSchema from './configSchema'
9
+
10
+ // window.fetch = jest.fn(url => new Promise(resolve => resolve()))
11
+
12
+ test('adapter can fetch variants from volvox.vcf.gz', async () => {
13
+ function mockFetch(url: RequestInfo | URL) {
14
+ let response = {}
15
+ if (`${url}`.includes('chr1')) {
16
+ response = queryResponse
17
+ }
18
+ if (`${url}`.includes('chr80')) {
19
+ response = emptyQueryResponse
20
+ } else if (`${url}`.includes('fakeRefNamesQuery')) {
21
+ response = refNamesResponse
22
+ }
23
+
24
+ return Promise.resolve(new Response(JSON.stringify(response)))
25
+ }
26
+
27
+ const spy = jest.spyOn(global, 'fetch')
28
+ spy.mockImplementation(mockFetch)
29
+ const adapter = new Adapter(
30
+ configSchema.create({
31
+ endpoint: {
32
+ uri: 'http://somesite.com/sparql',
33
+ locationType: 'UriLocation',
34
+ },
35
+ queryTemplate: 'fakeSPARQLQuery-start{start}-end{end}-{refName}',
36
+ refNamesQueryTemplate: 'fakeRefNamesQuery',
37
+ additionalQueryParams: ['format=json'],
38
+ refNames: [],
39
+ }),
40
+ )
41
+
42
+ const refNames = await adapter.getRefNames()
43
+ expect(spy).toHaveBeenLastCalledWith(
44
+ 'http://somesite.com/sparql?query=fakeRefNamesQuery&format=json',
45
+ {
46
+ headers: { accept: 'application/json,application/sparql-results+json' },
47
+ signal: undefined,
48
+ },
49
+ )
50
+ expect(refNames.length).toBe(17)
51
+ expect(refNames[0]).toBe('NC_004353.4')
52
+
53
+ const features = adapter.getFeatures({
54
+ refName: 'chr1',
55
+ start: 0,
56
+ end: 20000,
57
+ })
58
+ const featuresArray = await features.pipe(toArray()).toPromise()
59
+ expect(featuresArray).toMatchSnapshot()
60
+ expect(spy).toHaveBeenLastCalledWith(
61
+ 'http://somesite.com/sparql?query=fakeSPARQLQuery-start0-end20000-chr1&format=json',
62
+ {
63
+ headers: { accept: 'application/json,application/sparql-results+json' },
64
+ signal: undefined,
65
+ },
66
+ )
67
+
68
+ const featuresNonExist = adapter.getFeatures({
69
+ refName: 'chr80',
70
+ start: 0,
71
+ end: 20000,
72
+ })
73
+ const featuresArrayNonExist = await featuresNonExist
74
+ .pipe(toArray())
75
+ .toPromise()
76
+ expect(featuresArrayNonExist).toEqual([])
77
+ expect(spy).toHaveBeenLastCalledWith(
78
+ 'http://somesite.com/sparql?query=fakeSPARQLQuery-start0-end20000-chr80&format=json',
79
+ {
80
+ headers: { accept: 'application/json,application/sparql-results+json' },
81
+ signal: undefined,
82
+ },
83
+ )
84
+ })