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