@abi-software/flatmapvuer 0.5.6 → 0.5.7-alpha

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 (36) hide show
  1. package/CHANGELOG.md +385 -385
  2. package/LICENSE +201 -201
  3. package/README.md +105 -105
  4. package/babel.config.js +14 -14
  5. package/dist/flatmapvuer.common.js +80 -74
  6. package/dist/flatmapvuer.common.js.map +1 -1
  7. package/dist/flatmapvuer.umd.js +80 -74
  8. package/dist/flatmapvuer.umd.js.map +1 -1
  9. package/dist/flatmapvuer.umd.min.js +2 -2
  10. package/dist/flatmapvuer.umd.min.js.map +1 -1
  11. package/package-lock.json +14390 -14390
  12. package/package.json +78 -78
  13. package/public/index.html +17 -17
  14. package/src/App.vue +226 -226
  15. package/src/assets/_variables.scss +43 -43
  16. package/src/assets/styles.scss +7 -7
  17. package/src/components/EventBus.js +2 -2
  18. package/src/components/ExternalResourceCard.vue +98 -98
  19. package/src/components/FlatmapVuer.vue +1837 -1837
  20. package/src/components/MultiFlatmapVuer.vue +523 -523
  21. package/src/components/SelectionsGroup.vue +249 -249
  22. package/src/components/Tooltip.vue +422 -422
  23. package/src/components/TreeControls.vue +231 -231
  24. package/src/components/index.js +9 -9
  25. package/src/components/legends/DynamicLegends.vue +112 -112
  26. package/src/components/legends/SvgLegends.vue +66 -66
  27. package/src/icons/fonts/mapicon-species.eot +0 -0
  28. package/src/icons/fonts/mapicon-species.svg +14 -14
  29. package/src/icons/fonts/mapicon-species.ttf +0 -0
  30. package/src/icons/fonts/mapicon-species.woff +0 -0
  31. package/src/icons/mapicon-species-style.css +42 -42
  32. package/src/legends/legend.svg +25 -25
  33. package/src/main.js +8 -8
  34. package/src/nerve-map.js +99 -0
  35. package/src/services/flatmapQueries.js +420 -412
  36. package/vue.config.js +31 -31
@@ -1,412 +1,420 @@
1
- /* eslint-disable no-alert, no-console */
2
- // remove duplicates by stringifying the objects
3
- const removeDuplicates = function(arrayOfAnything){
4
- return [...new Set(arrayOfAnything.map(e => JSON.stringify(e)))].map(e => JSON.parse(e))
5
- }
6
-
7
- const cachedLabels = {};
8
-
9
- const findTaxonomyLabel = async function(flatmapAPI, taxonomy){
10
- if (cachedLabels && cachedLabels.hasOwnProperty(taxonomy)) {
11
- return cachedLabels[taxonomy];
12
- }
13
-
14
- return new Promise(resolve=>{
15
- fetch(`${flatmapAPI}knowledge/label/${taxonomy}`, {
16
- method: 'GET',
17
- })
18
- .then(response => response.json())
19
- .then(data => {
20
- let label = data.label;
21
- if (label === "Mammalia") {
22
- label = "Mammalia not otherwise specified";
23
- }
24
- cachedLabels[taxonomy] = label;
25
- resolve(label);
26
- })
27
- .catch((error) => {
28
- console.error('Error:', error);
29
- cachedLabels[taxonomy] = taxonomy;
30
- resolve(taxonomy);
31
- })
32
- });
33
- }
34
-
35
- const inArray = function(ar1, ar2){
36
- let as1 = JSON.stringify(ar1)
37
- let as2 = JSON.stringify(ar2)
38
- return as1.indexOf(as2) !== -1
39
- }
40
-
41
- let FlatmapQueries = function(){
42
-
43
- this.initialise = function(flatmapApi){
44
- this.flatmapApi = flatmapApi
45
- this.destinations = []
46
- this.origins = []
47
- this.components = []
48
- this.uberons = []
49
- this.urls = []
50
- this.controller = undefined
51
- this.uberons = []
52
- this.lookUp = []
53
- }
54
-
55
- this.createTooltipData = async function (eventData) {
56
- let hyperlinks = []
57
- if (eventData.feature.hyperlinks && eventData.feature.hyperlinks.length > 0) {
58
- hyperlinks = eventData.feature.hyperlinks
59
- } else {
60
- hyperlinks = this.urls.map(url=>({url: url, id: "pubmed"}))
61
- }
62
- let taxonomyLabel = undefined;
63
- if (eventData.provenanceTaxonomy) {
64
- taxonomyLabel = [];
65
- for (let i = 0; eventData.provenanceTaxonomy.length > i; i++) {
66
- taxonomyLabel.push(await findTaxonomyLabel(this.flatmapAPI, eventData.provenanceTaxonomy[i]))
67
- }
68
- }
69
-
70
- let tooltipData = {
71
- destinations: this.destinations,
72
- origins: this.origins,
73
- components: this.components,
74
- destinationsWithDatasets: this.destinationsWithDatasets,
75
- originsWithDatasets: this.originsWithDatasets,
76
- componentsWithDatasets: this.componentsWithDatasets,
77
- title: eventData.label,
78
- featureId: eventData.resource,
79
- hyperlinks: hyperlinks,
80
- provenanceTaxonomy: eventData.provenanceTaxonomy,
81
- provenanceTaxonomyLabel: taxonomyLabel
82
- }
83
- return tooltipData
84
- }
85
-
86
- this.createComponentsLabelList = function(components, lookUp){
87
- let labelList = []
88
- components.forEach(n=>{
89
- labelList.push(this.createLabelFromNeuralNode(n[0]), lookUp)
90
- if (n.length === 2){
91
- labelList.push(this.createLabelFromNeuralNode(n[1]), lookUp)
92
- }
93
- })
94
- return labelList
95
- }
96
-
97
- this.createLabelLookup = function(uberons) {
98
- return new Promise(resolve=> {
99
- let uberonMap = {}
100
- const data = { sql: this.buildLabelSqlStatement(uberons)}
101
- fetch(`${this.flatmapApi}knowledge/query/`, {
102
- method: 'POST',
103
- headers: {
104
- 'Content-Type': 'application/json',
105
- },
106
- body: JSON.stringify(data),
107
- })
108
- .then(response => response.json())
109
- .then(payload => {
110
- const entity = payload.keys.indexOf("entity");
111
- const label = payload.keys.indexOf("label");
112
- if (entity > -1 && label > -1) {
113
- payload.values.forEach(pair => {
114
- uberonMap[pair[entity]] = pair[label];
115
- });
116
- }
117
- resolve(uberonMap)
118
- })
119
- })
120
- }
121
-
122
- this.buildConnectivitySqlStatement = function (keastIds) {
123
- let sql = 'select knowledge from knowledge where entity in ('
124
- if (keastIds.length === 1) {
125
- sql += `'${keastIds[0]}')`
126
- } else if (keastIds.length > 1) {
127
- for (let i in keastIds) {
128
- sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
129
- }
130
- }
131
- return sql
132
- }
133
-
134
- this.buildLabelSqlStatement = function (uberons) {
135
- let sql = 'select entity, label from labels where entity in ('
136
- if (uberons.length === 1) {
137
- sql += `'${uberons[0]}')`
138
- } else if (uberons.length > 1) {
139
- for (let i in uberons) {
140
- sql += `'${uberons[i]}'${i >= uberons.length - 1 ? ')' : ','} `
141
- }
142
- }
143
- return sql
144
- }
145
-
146
- this.findAllIdsFromConnectivity = function (connectivity) {
147
- let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
148
- let nodes = [...new Set(dnodes)] // remove duplicates
149
- let found = []
150
- nodes.forEach(n => {
151
- if (Array.isArray(n)) {
152
- found.push(n.flat())
153
- } else {
154
- found.push(n)
155
- }
156
- })
157
- this.uberons = [... new Set(found.flat())]
158
- return this.uberons
159
- }
160
-
161
- this.flattenConntectivity = function (connectivity) {
162
- let dnodes = connectivity.flat() // get nodes from edgelist
163
- let nodes = [...new Set(dnodes)] // remove duplicates
164
- let found = []
165
- nodes.forEach(n => {
166
- if (Array.isArray(n)) {
167
- found.push(n.flat())
168
- } else {
169
- found.push(n)
170
- }
171
- })
172
- return found.flat()
173
- }
174
-
175
- this.findComponents = function (connectivity) {
176
- let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
177
- let nodes = removeDuplicates(dnodes)
178
-
179
- let found = []
180
- let terminal = false
181
- nodes.forEach(node => {
182
- terminal = false
183
- // Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
184
- if (inArray(connectivity.axons, node)) {
185
- terminal = true
186
- }
187
- if (inArray(connectivity.dendrites, node)) {
188
- terminal = true
189
- }
190
- if (!terminal) {
191
- found.push(node)
192
- }
193
- })
194
-
195
- return found
196
- }
197
-
198
- this.retrieveFlatmapKnowledgeForEvent = async function(eventData){
199
- // check if there is an existing query
200
- if (this.controller) this.controller.abort();
201
-
202
- // set up the abort controller
203
- this.controller = new AbortController();
204
- const signal = this.controller.signal;
205
-
206
- const keastIds = eventData.resource
207
- this.destinations = []
208
- this.origins = []
209
- this.components = []
210
- if (!keastIds || keastIds.length == 0) return
211
- const data = { sql: this.buildConnectivitySqlStatement(keastIds)};
212
- let prom1 = new Promise(resolve=>{
213
- fetch(`${this.flatmapApi}knowledge/query/`, {
214
- method: 'POST',
215
- headers: {
216
- 'Content-Type': 'application/json',
217
- },
218
- body: JSON.stringify(data),
219
- signal: signal
220
- })
221
- .then(response => response.json())
222
- .then(data => {
223
- if(this.connectivityExists(data)){
224
- let connectivity = JSON.parse(data.values[0][0])
225
- this.processConnectivity(connectivity).then(()=>{
226
- resolve(true)
227
- })
228
- } else {
229
- resolve(false)
230
- }
231
- })
232
- .catch((error) => {
233
- console.error('Error:', error);
234
- resolve(false)
235
- })
236
- })
237
- let prom2 = await this.pubmedQueryOnIds(eventData)
238
- let results = await Promise.all([prom1, prom2])
239
- return results
240
- }
241
-
242
- this.connectivityExists = function(data){
243
- if (data.values && data.values.length > 0 && JSON.parse(data.values[0][0]).connectivity && JSON.parse(data.values[0][0]).connectivity.length > 0) {
244
- return true
245
- } else {
246
- return false
247
- }
248
- }
249
-
250
- this.createLabelFromNeuralNode = function(node, lookUp){
251
- let label = lookUp[node[0]]
252
- if (node.length === 2 && node[1].length > 0){
253
- node[1].forEach(n=>{
254
- if (lookUp[n] == undefined){
255
- label += `, ${n}`
256
- } else {
257
- label += `, ${lookUp[n]}`
258
- }
259
- })
260
- }
261
- return label
262
- }
263
-
264
- this.flattenAndFindDatasets = function(components, axons, dendrites){
265
-
266
- // process the nodes for finding datasets (Note this is not critical to the tooltip, only for the 'search on components' button)
267
- let componentsFlat = this.flattenConntectivity(components)
268
- let axonsFlat = this.flattenConntectivity(axons)
269
- let dendritesFlat = this.flattenConntectivity(dendrites)
270
-
271
- // Filter for the anatomy which is annotated on datasets
272
- this.destinationsWithDatasets = this.uberons.filter(ub => axonsFlat.indexOf(ub.id) !== -1)
273
- this.originsWithDatasets = this.uberons.filter(ub => dendritesFlat.indexOf(ub.id) !== -1)
274
- this.componentsWithDatasets = this.uberons.filter(ub => componentsFlat.indexOf(ub.id) !== -1)
275
- }
276
-
277
- this.processConnectivity = function(connectivity){
278
- return new Promise (resolve=>{
279
- // Filter the origin and destinations from components
280
- let components = this.findComponents(connectivity)
281
-
282
- // Remove duplicates
283
- let axons = removeDuplicates(connectivity.axons)
284
- let dendrites = removeDuplicates(connectivity.dendrites)
285
-
286
- // Create list of ids to get labels for
287
- let conIds = this.findAllIdsFromConnectivity(connectivity)
288
-
289
- // Create readable labels from the nodes. Setting this to 'this.origins' updates the display
290
- this.createLabelLookup(conIds).then(lookUp=>{
291
- this.destinations = axons.map(a=>this.createLabelFromNeuralNode(a,lookUp))
292
- this.origins = dendrites.map(d=>this.createLabelFromNeuralNode(d,lookUp))
293
- this.components = components.map(c=>this.createLabelFromNeuralNode(c, lookUp))
294
- this.flattenAndFindDatasets(components, axons, dendrites)
295
- resolve(true)
296
- })
297
- })
298
- }
299
-
300
- this.flattenConntectivity = function(connectivity){
301
- let dnodes = connectivity.flat() // get nodes from edgelist
302
- let nodes = [...new Set(dnodes)] // remove duplicates
303
- let found = []
304
- nodes.forEach(n=>{
305
- if (Array.isArray(n)){
306
- found.push(n.flat())
307
- } else {
308
- found.push(n)
309
- }
310
- })
311
- return found.flat()
312
- }
313
-
314
- this.findComponents = function(connectivity){
315
- let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
316
- let nodes = removeDuplicates(dnodes)
317
-
318
- let found = []
319
- let terminal = false
320
- nodes.forEach(node=>{
321
- terminal = false
322
- // Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
323
- if(inArray(connectivity.axons,node)){
324
- terminal = true
325
- }
326
- if(inArray(connectivity.dendrites, node)){
327
- terminal = true
328
- }
329
- if (!terminal){
330
- found.push(node)
331
- }
332
- })
333
-
334
- return found
335
- }
336
-
337
- this.stripPMIDPrefix = function (pubmedId){
338
- return pubmedId.split(':')[1]
339
- }
340
-
341
- this.buildPubmedSqlStatement = function(keastIds) {
342
- let sql = 'select distinct publication from publications where entity in ('
343
- if (keastIds.length === 1) {
344
- sql += `'${keastIds[0]}')`
345
- } else if (keastIds.length > 1) {
346
- for (let i in keastIds) {
347
- sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
348
- }
349
- }
350
- return sql
351
- }
352
-
353
- this.buildPubmedSqlStatementForModels = function(model) {
354
- return `select distinct publication from publications where entity = '${model}'`
355
- }
356
-
357
- this.flatmapQuery = function(sql){
358
- const data = { sql: sql}
359
- return fetch(`${this.flatmapApi}knowledge/query/`, {
360
- method: 'POST',
361
- headers: {
362
- 'Content-Type': 'application/json',
363
- },
364
- body: JSON.stringify(data),
365
- })
366
- .then(response => response.json())
367
- .catch((error) => {
368
- console.error('Error:', error)
369
- })
370
- }
371
- // Note that this functin WILL run to the end, as it doesn not catch the second level of promises
372
- this.pubmedQueryOnIds = function(eventData){
373
- return new Promise(resolve=>{
374
- const keastIds = eventData.resource
375
- const source = eventData.feature.source
376
- if(!keastIds || keastIds.length === 0) return
377
- const sql = this.buildPubmedSqlStatement(keastIds)
378
- this.flatmapQuery(sql).then(data=>{
379
- // Create pubmed url on paths if we have them
380
- if (data.values.length > 0){
381
- this.urls = [this.pubmedSearchUrl(data.values.map(id=>this.stripPMIDPrefix(id[0])))]
382
- resolve(true)
383
- } else { // Create pubmed url on models
384
- this.pubmedQueryOnModels(source).then(result=>{
385
- resolve(result)
386
- })
387
- }
388
- })
389
- })
390
- }
391
-
392
- this.pubmedQueryOnModels = function(source){
393
- return this.flatmapQuery(this.buildPubmedSqlStatementForModels(source)).then(data=>{
394
- if (Array.isArray(data.values) && data.values.length > 0){
395
- this.urls = [this.pubmedSearchUrl(data.values.map(id=>this.stripPMIDPrefix(id[0])))]
396
- return true
397
- } else {
398
- this.urls = [] // Clears the pubmed search button
399
- }
400
- return false
401
- })
402
- }
403
-
404
- this.pubmedSearchUrl = function(ids) {
405
- let url = 'https://pubmed.ncbi.nlm.nih.gov/?'
406
- let params = new URLSearchParams()
407
- params.append('term', ids)
408
- return url + params.toString()
409
- }
410
- }
411
-
412
- export {FlatmapQueries, findTaxonomyLabel}
1
+ /* eslint-disable no-alert, no-console */
2
+ // remove duplicates by stringifying the objects
3
+ const removeDuplicates = function(arrayOfAnything){
4
+ return [...new Set(arrayOfAnything.map(e => JSON.stringify(e)))].map(e => JSON.parse(e))
5
+ }
6
+
7
+ const cachedLabels = {};
8
+
9
+ const findTaxonomyLabel = async function(flatmapAPI, taxonomy){
10
+ if (cachedLabels && cachedLabels.hasOwnProperty(taxonomy)) {
11
+ return cachedLabels[taxonomy];
12
+ }
13
+
14
+ return new Promise(resolve=>{
15
+ fetch(`${flatmapAPI}knowledge/label/${taxonomy}`, {
16
+ method: 'GET',
17
+ })
18
+ .then(response => response.json())
19
+ .then(data => {
20
+ let label = data.label;
21
+ if (label === "Mammalia") {
22
+ label = "Mammalia not otherwise specified";
23
+ }
24
+ cachedLabels[taxonomy] = label;
25
+ resolve(label);
26
+ })
27
+ .catch((error) => {
28
+ console.error('Error:', error);
29
+ cachedLabels[taxonomy] = taxonomy;
30
+ resolve(taxonomy);
31
+ })
32
+ });
33
+ }
34
+
35
+ const inArray = function(ar1, ar2){
36
+ let as1 = JSON.stringify(ar1)
37
+ let as2 = JSON.stringify(ar2)
38
+ return as1.indexOf(as2) !== -1
39
+ }
40
+
41
+ let FlatmapQueries = function(){
42
+
43
+ this.initialise = function(flatmapApi){
44
+ this.flatmapApi = flatmapApi
45
+ this.destinations = []
46
+ this.origins = []
47
+ this.components = []
48
+ this.uberons = []
49
+ this.urls = []
50
+ this.controller = undefined
51
+ this.uberons = []
52
+ this.lookUp = []
53
+ }
54
+
55
+ this.createTooltipData = async function (eventData) {
56
+ let hyperlinks = []
57
+ if (eventData.feature.hyperlinks && eventData.feature.hyperlinks.length > 0) {
58
+ hyperlinks = eventData.feature.hyperlinks
59
+ } else {
60
+ hyperlinks = this.urls.map(url=>({url: url, id: "pubmed"}))
61
+ }
62
+ let taxonomyLabel = undefined;
63
+ if (eventData.provenanceTaxonomy) {
64
+ taxonomyLabel = [];
65
+ for (let i = 0; eventData.provenanceTaxonomy.length > i; i++) {
66
+ taxonomyLabel.push(await findTaxonomyLabel(this.flatmapAPI, eventData.provenanceTaxonomy[i]))
67
+ }
68
+ }
69
+
70
+ let tooltipData = {
71
+ destinations: this.destinations,
72
+ origins: this.origins,
73
+ components: this.components,
74
+ destinationsWithDatasets: this.destinationsWithDatasets,
75
+ originsWithDatasets: this.originsWithDatasets,
76
+ componentsWithDatasets: this.componentsWithDatasets,
77
+ title: eventData.label,
78
+ featureId: eventData.resource,
79
+ hyperlinks: hyperlinks,
80
+ provenanceTaxonomy: eventData.provenanceTaxonomy,
81
+ provenanceTaxonomyLabel: taxonomyLabel
82
+ }
83
+ return tooltipData
84
+ }
85
+
86
+ this.createComponentsLabelList = function(components, lookUp){
87
+ let labelList = []
88
+ components.forEach(n=>{
89
+ labelList.push(this.createLabelFromNeuralNode(n[0]), lookUp)
90
+ if (n.length === 2){
91
+ labelList.push(this.createLabelFromNeuralNode(n[1]), lookUp)
92
+ }
93
+ })
94
+ return labelList
95
+ }
96
+
97
+ this.createLabelLookup = function(uberons) {
98
+ return new Promise(resolve=> {
99
+ let uberonMap = {}
100
+ const data = { sql: this.buildLabelSqlStatement(uberons)}
101
+ fetch(`${this.flatmapApi}knowledge/query/`, {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json',
105
+ },
106
+ body: JSON.stringify(data),
107
+ })
108
+ .then(response => response.json())
109
+ .then(payload => {
110
+ const entity = payload.keys.indexOf("entity");
111
+ const label = payload.keys.indexOf("label");
112
+ if (entity > -1 && label > -1) {
113
+ payload.values.forEach(pair => {
114
+ uberonMap[pair[entity]] = pair[label];
115
+ });
116
+ }
117
+ resolve(uberonMap)
118
+ })
119
+ })
120
+ }
121
+
122
+ this.buildConnectivitySqlStatement = function (keastIds) {
123
+ let sql = 'select knowledge from knowledge where entity in ('
124
+ if (keastIds.length === 1) {
125
+ sql += `'${keastIds[0]}')`
126
+ } else if (keastIds.length > 1) {
127
+ for (let i in keastIds) {
128
+ sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
129
+ }
130
+ }
131
+ return sql
132
+ }
133
+
134
+ this.buildLabelSqlStatement = function (uberons) {
135
+ let sql = 'select entity, label from labels where entity in ('
136
+ if (uberons.length === 1) {
137
+ sql += `'${uberons[0]}')`
138
+ } else if (uberons.length > 1) {
139
+ for (let i in uberons) {
140
+ sql += `'${uberons[i]}'${i >= uberons.length - 1 ? ')' : ','} `
141
+ }
142
+ }
143
+ return sql
144
+ }
145
+
146
+ this.findAllIdsFromConnectivity = function (connectivity) {
147
+ let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
148
+ let nodes = [...new Set(dnodes)] // remove duplicates
149
+ let found = []
150
+ nodes.forEach(n => {
151
+ if (Array.isArray(n)) {
152
+ found.push(n.flat())
153
+ } else {
154
+ found.push(n)
155
+ }
156
+ })
157
+ this.uberons = [... new Set(found.flat())]
158
+ return this.uberons
159
+ }
160
+
161
+ this.flattenConntectivity = function (connectivity) {
162
+ let dnodes = connectivity.flat() // get nodes from edgelist
163
+ let nodes = [...new Set(dnodes)] // remove duplicates
164
+ let found = []
165
+ nodes.forEach(n => {
166
+ if (Array.isArray(n)) {
167
+ found.push(n.flat())
168
+ } else {
169
+ found.push(n)
170
+ }
171
+ })
172
+ return found.flat()
173
+ }
174
+
175
+ this.findComponents = function (connectivity) {
176
+ let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
177
+ let nodes = removeDuplicates(dnodes)
178
+
179
+ let found = []
180
+ let terminal = false
181
+ nodes.forEach(node => {
182
+ terminal = false
183
+ // Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
184
+ if (inArray(connectivity.axons, node)) {
185
+ terminal = true
186
+ }
187
+ if (inArray(connectivity.dendrites, node)) {
188
+ terminal = true
189
+ }
190
+ if (!terminal) {
191
+ found.push(node)
192
+ }
193
+ })
194
+
195
+ return found
196
+ }
197
+
198
+ this.retrieveFlatmapKnowledgeForEvent = async function(eventData){
199
+ // check if there is an existing query
200
+ if (this.controller) this.controller.abort();
201
+
202
+ // set up the abort controller
203
+ this.controller = new AbortController();
204
+ const signal = this.controller.signal;
205
+
206
+ const keastIds = eventData.resource
207
+ this.destinations = []
208
+ this.origins = []
209
+ this.components = []
210
+ if (!keastIds || keastIds.length == 0) return
211
+ const data = { sql: this.buildConnectivitySqlStatement(keastIds)};
212
+ let prom1 = new Promise(resolve=>{
213
+ fetch(`${this.flatmapApi}knowledge/query/`, {
214
+ method: 'POST',
215
+ headers: {
216
+ 'Content-Type': 'application/json',
217
+ },
218
+ body: JSON.stringify(data),
219
+ signal: signal
220
+ })
221
+ .then(response => response.json())
222
+ .then(data => {
223
+ if(this.connectivityExists(data)){
224
+ let connectivity = JSON.parse(data.values[0][0])
225
+ this.processConnectivity(connectivity).then(()=>{
226
+ resolve(true)
227
+ })
228
+ } else {
229
+ resolve(false)
230
+ }
231
+ })
232
+ .catch((error) => {
233
+ console.error('Error:', error);
234
+ resolve(false)
235
+ })
236
+ })
237
+ let prom2 = await this.pubmedQueryOnIds(eventData)
238
+ let results = await Promise.all([prom1, prom2])
239
+ return results
240
+ }
241
+
242
+ this.connectivityExists = function(data){
243
+ if (data.values && data.values.length > 0 && JSON.parse(data.values[0][0]).connectivity && JSON.parse(data.values[0][0]).connectivity.length > 0) {
244
+ return true
245
+ } else {
246
+ return false
247
+ }
248
+ }
249
+
250
+ this.createLabelFromNeuralNode = function(node, lookUp){
251
+ let label = lookUp[node[0]]
252
+ if (node.length === 2 && node[1].length > 0){
253
+ node[1].forEach(n=>{
254
+ if (lookUp[n] == undefined){
255
+ label += `, ${n}`
256
+ } else {
257
+ label += `, ${lookUp[n]}`
258
+ }
259
+ })
260
+ }
261
+ return label
262
+ }
263
+
264
+ this.flattenAndFindDatasets = function(components, axons, dendrites){
265
+
266
+ // process the nodes for finding datasets (Note this is not critical to the tooltip, only for the 'search on components' button)
267
+ let componentsFlat = this.flattenConntectivity(components)
268
+ let axonsFlat = this.flattenConntectivity(axons)
269
+ let dendritesFlat = this.flattenConntectivity(dendrites)
270
+
271
+ console.log("uber in flattehn find datasets", this.uberons)
272
+
273
+ window.uberons = this.uberons
274
+ window.componentsFlat = componentsFlat
275
+
276
+ // Filter for the anatomy which is annotated on datasets
277
+ this.destinationsWithDatasets = this.uberons.filter(ub => axonsFlat.indexOf(ub) !== -1)
278
+ this.originsWithDatasets = this.uberons.filter(ub => dendritesFlat.indexOf(ub) !== -1)
279
+ this.componentsWithDatasets = this.uberons.filter(ub => componentsFlat.indexOf(ub) !== -1)
280
+ }
281
+
282
+ this.processConnectivity = function(connectivity){
283
+ return new Promise (resolve=>{
284
+ console.log(connectivity)
285
+ // Filter the origin and destinations from components
286
+ let components = this.findComponents(connectivity)
287
+
288
+ // Remove duplicates
289
+ let axons = removeDuplicates(connectivity.axons)
290
+ let dendrites = removeDuplicates(connectivity.dendrites)
291
+
292
+ // Create list of ids to get labels for
293
+ let conIds = this.findAllIdsFromConnectivity(connectivity)
294
+ console.log(conIds)
295
+
296
+ // Create readable labels from the nodes. Setting this to 'this.origins' updates the display
297
+ this.createLabelLookup(conIds).then(lookUp=>{
298
+ console.log("after label lookup", this.uberons)
299
+ this.destinations = axons.map(a=>this.createLabelFromNeuralNode(a,lookUp))
300
+ this.origins = dendrites.map(d=>this.createLabelFromNeuralNode(d,lookUp))
301
+ this.components = components.map(c=>this.createLabelFromNeuralNode(c, lookUp))
302
+ this.flattenAndFindDatasets(components, axons, dendrites)
303
+ resolve(true)
304
+ })
305
+ })
306
+ }
307
+
308
+ this.flattenConntectivity = function(connectivity){
309
+ let dnodes = connectivity.flat() // get nodes from edgelist
310
+ let nodes = [...new Set(dnodes)] // remove duplicates
311
+ let found = []
312
+ nodes.forEach(n=>{
313
+ if (Array.isArray(n)){
314
+ found.push(n.flat())
315
+ } else {
316
+ found.push(n)
317
+ }
318
+ })
319
+ return found.flat()
320
+ }
321
+
322
+ this.findComponents = function(connectivity){
323
+ let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
324
+ let nodes = removeDuplicates(dnodes)
325
+
326
+ let found = []
327
+ let terminal = false
328
+ nodes.forEach(node=>{
329
+ terminal = false
330
+ // Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
331
+ if(inArray(connectivity.axons,node)){
332
+ terminal = true
333
+ }
334
+ if(inArray(connectivity.dendrites, node)){
335
+ terminal = true
336
+ }
337
+ if (!terminal){
338
+ found.push(node)
339
+ }
340
+ })
341
+
342
+ return found
343
+ }
344
+
345
+ this.stripPMIDPrefix = function (pubmedId){
346
+ return pubmedId.split(':')[1]
347
+ }
348
+
349
+ this.buildPubmedSqlStatement = function(keastIds) {
350
+ let sql = 'select distinct publication from publications where entity in ('
351
+ if (keastIds.length === 1) {
352
+ sql += `'${keastIds[0]}')`
353
+ } else if (keastIds.length > 1) {
354
+ for (let i in keastIds) {
355
+ sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
356
+ }
357
+ }
358
+ return sql
359
+ }
360
+
361
+ this.buildPubmedSqlStatementForModels = function(model) {
362
+ return `select distinct publication from publications where entity = '${model}'`
363
+ }
364
+
365
+ this.flatmapQuery = function(sql){
366
+ const data = { sql: sql}
367
+ return fetch(`${this.flatmapApi}knowledge/query/`, {
368
+ method: 'POST',
369
+ headers: {
370
+ 'Content-Type': 'application/json',
371
+ },
372
+ body: JSON.stringify(data),
373
+ })
374
+ .then(response => response.json())
375
+ .catch((error) => {
376
+ console.error('Error:', error)
377
+ })
378
+ }
379
+ // Note that this functin WILL run to the end, as it doesn not catch the second level of promises
380
+ this.pubmedQueryOnIds = function(eventData){
381
+ return new Promise(resolve=>{
382
+ const keastIds = eventData.resource
383
+ const source = eventData.feature.source
384
+ if(!keastIds || keastIds.length === 0) return
385
+ const sql = this.buildPubmedSqlStatement(keastIds)
386
+ this.flatmapQuery(sql).then(data=>{
387
+ // Create pubmed url on paths if we have them
388
+ if (data.values.length > 0){
389
+ this.urls = [this.pubmedSearchUrl(data.values.map(id=>this.stripPMIDPrefix(id[0])))]
390
+ resolve(true)
391
+ } else { // Create pubmed url on models
392
+ this.pubmedQueryOnModels(source).then(result=>{
393
+ resolve(result)
394
+ })
395
+ }
396
+ })
397
+ })
398
+ }
399
+
400
+ this.pubmedQueryOnModels = function(source){
401
+ return this.flatmapQuery(this.buildPubmedSqlStatementForModels(source)).then(data=>{
402
+ if (Array.isArray(data.values) && data.values.length > 0){
403
+ this.urls = [this.pubmedSearchUrl(data.values.map(id=>this.stripPMIDPrefix(id[0])))]
404
+ return true
405
+ } else {
406
+ this.urls = [] // Clears the pubmed search button
407
+ }
408
+ return false
409
+ })
410
+ }
411
+
412
+ this.pubmedSearchUrl = function(ids) {
413
+ let url = 'https://pubmed.ncbi.nlm.nih.gov/?'
414
+ let params = new URLSearchParams()
415
+ params.append('term', ids)
416
+ return url + params.toString()
417
+ }
418
+ }
419
+
420
+ export {FlatmapQueries, findTaxonomyLabel}