@abi-software/map-side-bar 2.10.0-beta.2 → 2.10.0-beta.4
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/map-side-bar.js +24 -10
- package/dist/map-side-bar.umd.cjs +21 -21
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ConnectivityExplorer.vue +4 -2
- package/src/components/SearchFilters.vue +1 -1
- package/src/components/SideBar.vue +18 -2
- package/src/services/flatmapKnowledge.js +0 -94
- package/src/services/flatmapQueries.js +0 -498
package/package.json
CHANGED
|
@@ -471,7 +471,6 @@ export default {
|
|
|
471
471
|
searchAndFilterUpdate: function () {
|
|
472
472
|
this.resetPageNavigation();
|
|
473
473
|
this.searchKnowledge(this.filter, this.searchInput);
|
|
474
|
-
this.$refs.filtersRef.setCascader(this.filter);
|
|
475
474
|
this.searchHistoryUpdate(this.filter, this.searchInput);
|
|
476
475
|
},
|
|
477
476
|
searchHistoryUpdate: function (filters, search) {
|
|
@@ -505,7 +504,10 @@ export default {
|
|
|
505
504
|
pageChange: function (page) {
|
|
506
505
|
this.start = (page - 1) * this.numberPerPage;
|
|
507
506
|
this.page = page;
|
|
508
|
-
this.
|
|
507
|
+
this.expanded = "";
|
|
508
|
+
this.expandedData = null;
|
|
509
|
+
this.scrollToTop();
|
|
510
|
+
// this.searchKnowledge(this.filter, this.searchInput);
|
|
509
511
|
},
|
|
510
512
|
scrollToTop: function () {
|
|
511
513
|
if (this.$refs.content) {
|
|
@@ -500,7 +500,7 @@ export default {
|
|
|
500
500
|
// If 'cascaderTags' has key 'Anatomical structure',
|
|
501
501
|
// it's value type will be Object (because it has nested facets),
|
|
502
502
|
// in this case 'push' action will not available.
|
|
503
|
-
if (term in this.cascaderTags &&
|
|
503
|
+
if (term in this.cascaderTags && !['Anatomical structure', 'Nerves'].includes(term)) {
|
|
504
504
|
this.cascaderTags[term].push(facetLabel)
|
|
505
505
|
// connectivity exploration mode tags
|
|
506
506
|
if (termId) {
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
:envVars="envVars"
|
|
51
51
|
:connectivityEntry="connectivityEntry"
|
|
52
52
|
:availableAnatomyFacets="availableAnatomyFacets"
|
|
53
|
-
@filter-visibility="$emit('filter-visibility', $event)"
|
|
54
53
|
:connectivityFilterOptions="filterOptions"
|
|
54
|
+
@filter-visibility="$emit('filter-visibility', $event)"
|
|
55
55
|
:showVisibilityFilter="showVisibilityFilter"
|
|
56
56
|
@search-changed="searchChanged(tab.id, $event)"
|
|
57
57
|
@hover-changed="hoverChanged(tab.id, $event)"
|
|
@@ -195,6 +195,8 @@ export default {
|
|
|
195
195
|
search: '',
|
|
196
196
|
filters: [],
|
|
197
197
|
},
|
|
198
|
+
connectivityEntry: this.connectivityEntry,
|
|
199
|
+
annotationEntry: this.annotationEntry,
|
|
198
200
|
},
|
|
199
201
|
}
|
|
200
202
|
},
|
|
@@ -414,15 +416,29 @@ export default {
|
|
|
414
416
|
this.state.dataset.filters = datasetExplorerTabRef.getFilters();
|
|
415
417
|
this.state.connectivity.search = connectivityExplorerTabRef.getSearch();
|
|
416
418
|
this.state.connectivity.filters = connectivityExplorerTabRef.getFilters();
|
|
419
|
+
this.state.connectivityEntry = this.connectivityEntry;
|
|
420
|
+
this.state.annotationEntry = this.annotationEntry;
|
|
417
421
|
},
|
|
422
|
+
/**
|
|
423
|
+
* This function returns the current state of the sidebar
|
|
424
|
+
* to store in the map state.
|
|
425
|
+
* @returns {Object} state
|
|
426
|
+
* @public
|
|
427
|
+
*/
|
|
418
428
|
getState: function () {
|
|
419
429
|
this.updateState();
|
|
420
430
|
return this.state;
|
|
421
431
|
},
|
|
432
|
+
/**
|
|
433
|
+
* This function restores the state of the sidebar
|
|
434
|
+
* from the provided state object.
|
|
435
|
+
* @param state {Object} state
|
|
436
|
+
* @public
|
|
437
|
+
*/
|
|
422
438
|
setState: function (state) {
|
|
423
439
|
// if state is not provided or formatted incorrectly, do nothing
|
|
424
440
|
if (!state || !state.dataset || !state.connectivity) return;
|
|
425
|
-
this.state = state;
|
|
441
|
+
this.state = JSON.parse(JSON.stringify(state)); // deep copy to avoid reference issues
|
|
426
442
|
this.openSearch(state.dataset.filters, state.dataset.search);
|
|
427
443
|
this.openConnectivitySearch(state.connectivity.filters, state.connectivity.search);
|
|
428
444
|
},
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
async function getReferenceConnectivitiesFromStorage(resource) {
|
|
2
|
-
const flatmapKnowledgeRaw = sessionStorage.getItem('flatmap-knowledge');
|
|
3
|
-
|
|
4
|
-
if (flatmapKnowledgeRaw) {
|
|
5
|
-
const flatmapKnowledge = JSON.parse(flatmapKnowledgeRaw);
|
|
6
|
-
const dataWithRefs = flatmapKnowledge.filter((x) => x.references && x.references.length);
|
|
7
|
-
const foundData = dataWithRefs.filter((x) => x.references.includes(resource));
|
|
8
|
-
|
|
9
|
-
if (foundData.length) {
|
|
10
|
-
const featureIds = foundData.map((x) => x.id);
|
|
11
|
-
return featureIds;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function getReferenceConnectivitiesByAPI(mapImp, resource, flatmapQueries) {
|
|
18
|
-
const knowledgeSource = getKnowledgeSource(mapImp);
|
|
19
|
-
const sql = `select knowledge from knowledge
|
|
20
|
-
where source="${knowledgeSource}" and
|
|
21
|
-
knowledge like "%${resource}%" order by source desc`;
|
|
22
|
-
console.log(sql)
|
|
23
|
-
const response = await flatmapQueries.flatmapQuery(sql);
|
|
24
|
-
const mappedData = response.values.map((x) => x[0]);
|
|
25
|
-
const parsedData = mappedData.map((x) => JSON.parse(x));
|
|
26
|
-
const featureIds = parsedData.map((x) => x.id);
|
|
27
|
-
return featureIds;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getKnowledgeSource(mapImp) {
|
|
31
|
-
let mapKnowledgeSource = '';
|
|
32
|
-
if (mapImp.provenance?.connectivity) {
|
|
33
|
-
const sckanProvenance = mapImp.provenance.connectivity;
|
|
34
|
-
if ('knowledge-source' in sckanProvenance) {
|
|
35
|
-
mapKnowledgeSource = sckanProvenance['knowledge-source'];
|
|
36
|
-
} else if ('npo' in sckanProvenance) {
|
|
37
|
-
mapKnowledgeSource = `${sckanProvenance.npo.release}-npo`;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return mapKnowledgeSource;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function loadAndStoreKnowledge(mapImp, flatmapQueries) {
|
|
45
|
-
const knowledgeSource = getKnowledgeSource(mapImp);
|
|
46
|
-
const sql = `select knowledge from knowledge
|
|
47
|
-
where source="${knowledgeSource}"
|
|
48
|
-
order by source desc`;
|
|
49
|
-
const flatmapKnowledge = sessionStorage.getItem('flatmap-knowledge');
|
|
50
|
-
|
|
51
|
-
if (!flatmapKnowledge) {
|
|
52
|
-
flatmapQueries.flatmapQuery(sql).then((response) => {
|
|
53
|
-
const mappedData = response.values.map(x => x[0]);
|
|
54
|
-
const parsedData = mappedData.map(x => JSON.parse(x));
|
|
55
|
-
sessionStorage.setItem('flatmap-knowledge', JSON.stringify(parsedData));
|
|
56
|
-
updateFlatmapKnowledgeCache();
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function updateFlatmapKnowledgeCache() {
|
|
62
|
-
const CACHE_LIFETIME = 24 * 60 * 60 * 1000; // One day
|
|
63
|
-
const now = new Date();
|
|
64
|
-
const expiry = now.getTime() + CACHE_LIFETIME;
|
|
65
|
-
|
|
66
|
-
sessionStorage.setItem('flatmap-knowledge-expiry', expiry);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function removeFlatmapKnowledgeCache() {
|
|
70
|
-
const keys = [
|
|
71
|
-
'flatmap-knowledge',
|
|
72
|
-
'flatmap-knowledge-expiry',
|
|
73
|
-
];
|
|
74
|
-
keys.forEach((key) => {
|
|
75
|
-
sessionStorage.removeItem(key);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function refreshFlatmapKnowledgeCache() {
|
|
80
|
-
const expiry = sessionStorage.getItem('flatmap-knowledge-expiry');
|
|
81
|
-
const now = new Date();
|
|
82
|
-
|
|
83
|
-
if (now.getTime() > expiry) {
|
|
84
|
-
removeFlatmapKnowledgeCache();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export {
|
|
89
|
-
getReferenceConnectivitiesFromStorage,
|
|
90
|
-
getReferenceConnectivitiesByAPI,
|
|
91
|
-
loadAndStoreKnowledge,
|
|
92
|
-
getKnowledgeSource,
|
|
93
|
-
refreshFlatmapKnowledgeCache,
|
|
94
|
-
}
|
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-alert, no-console */
|
|
2
|
-
// remove duplicates by stringifying the objects
|
|
3
|
-
const removeDuplicates = function (arrayOfAnything) {
|
|
4
|
-
if (!arrayOfAnything) return []
|
|
5
|
-
return [...new Set(arrayOfAnything.map((e) => JSON.stringify(e)))].map((e) =>
|
|
6
|
-
JSON.parse(e)
|
|
7
|
-
)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const cachedLabels = {}
|
|
11
|
-
const cachedTaxonLabels = [];
|
|
12
|
-
|
|
13
|
-
const findTaxonomyLabel = async function (flatmapAPI, taxonomy) {
|
|
14
|
-
if (cachedLabels && cachedLabels.hasOwnProperty(taxonomy)) {
|
|
15
|
-
return cachedLabels[taxonomy]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return new Promise((resolve) => {
|
|
19
|
-
fetch(`${flatmapAPI}knowledge/label/${taxonomy}`, {
|
|
20
|
-
method: 'GET',
|
|
21
|
-
})
|
|
22
|
-
.then((response) => response.json())
|
|
23
|
-
.then((data) => {
|
|
24
|
-
let label = data.label
|
|
25
|
-
if (label === 'Mammalia') {
|
|
26
|
-
label = 'Mammalia not otherwise specified'
|
|
27
|
-
}
|
|
28
|
-
cachedLabels[taxonomy] = label
|
|
29
|
-
resolve(label)
|
|
30
|
-
})
|
|
31
|
-
.catch((error) => {
|
|
32
|
-
console.error('Error:', error)
|
|
33
|
-
cachedLabels[taxonomy] = taxonomy
|
|
34
|
-
resolve(taxonomy)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const findTaxonomyLabels = async function (mapImp, taxonomies) {
|
|
40
|
-
const intersectionTaxonomies = taxonomies.filter((taxonomy) =>
|
|
41
|
-
cachedTaxonLabels.some((obj) => obj.taxon === taxonomy)
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const foundCachedTaxonLabels = cachedTaxonLabels.filter((obj) =>
|
|
45
|
-
intersectionTaxonomies.includes(obj.taxon)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const leftoverTaxonomies = taxonomies.filter((taxonomy) =>
|
|
49
|
-
!intersectionTaxonomies.includes(taxonomy)
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
if (!leftoverTaxonomies.length) {
|
|
53
|
-
return foundCachedTaxonLabels;
|
|
54
|
-
} else {
|
|
55
|
-
const entityLabels = await mapImp.queryLabels(leftoverTaxonomies);
|
|
56
|
-
if (entityLabels.length) {
|
|
57
|
-
entityLabels.forEach((entityLabel) => {
|
|
58
|
-
let { entity: taxon, label } = entityLabel;
|
|
59
|
-
if (label === 'Mammalia') {
|
|
60
|
-
label = 'Mammalia not otherwise specified'
|
|
61
|
-
}
|
|
62
|
-
const item = { taxon, label };
|
|
63
|
-
foundCachedTaxonLabels.push(item);
|
|
64
|
-
cachedTaxonLabels.push(item);
|
|
65
|
-
});
|
|
66
|
-
return foundCachedTaxonLabels;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const inArray = function (ar1, ar2) {
|
|
72
|
-
if (!ar1 || !ar2) return false
|
|
73
|
-
let as1 = JSON.stringify(ar1)
|
|
74
|
-
let as2 = JSON.stringify(ar2)
|
|
75
|
-
return as1.indexOf(as2) !== -1
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let FlatmapQueries = function () {
|
|
79
|
-
this.initialise = function (flatmapApi) {
|
|
80
|
-
this.flatmapApi = flatmapApi
|
|
81
|
-
this.destinations = []
|
|
82
|
-
this.origins = []
|
|
83
|
-
this.components = []
|
|
84
|
-
this.rawURLs = []
|
|
85
|
-
this.controller = undefined
|
|
86
|
-
this.uberons = []
|
|
87
|
-
this.lookUp = []
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.createTooltipData = async function (mapImp, eventData) {
|
|
91
|
-
let hyperlinks = []
|
|
92
|
-
if (
|
|
93
|
-
eventData.feature.hyperlinks &&
|
|
94
|
-
eventData.feature.hyperlinks.length > 0
|
|
95
|
-
) {
|
|
96
|
-
hyperlinks = eventData.feature.hyperlinks
|
|
97
|
-
} else {
|
|
98
|
-
hyperlinks = this.rawURLs;
|
|
99
|
-
}
|
|
100
|
-
let taxonomyLabel = undefined
|
|
101
|
-
if (eventData.provenanceTaxonomy) {
|
|
102
|
-
taxonomyLabel = []
|
|
103
|
-
const entityLabels = await findTaxonomyLabels(mapImp, eventData.provenanceTaxonomy);
|
|
104
|
-
if (entityLabels.length) {
|
|
105
|
-
entityLabels.forEach((entityLabel) => {
|
|
106
|
-
const { label } = entityLabel;
|
|
107
|
-
taxonomyLabel.push(label);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let tooltipData = {
|
|
113
|
-
destinations: this.destinations,
|
|
114
|
-
origins: this.origins,
|
|
115
|
-
components: this.components,
|
|
116
|
-
destinationsWithDatasets: this.destinationsWithDatasets,
|
|
117
|
-
originsWithDatasets: this.originsWithDatasets,
|
|
118
|
-
componentsWithDatasets: this.componentsWithDatasets,
|
|
119
|
-
title: eventData.label,
|
|
120
|
-
featureId: eventData.resource,
|
|
121
|
-
hyperlinks: hyperlinks,
|
|
122
|
-
provenanceTaxonomy: eventData.provenanceTaxonomy,
|
|
123
|
-
provenanceTaxonomyLabel: taxonomyLabel,
|
|
124
|
-
}
|
|
125
|
-
return tooltipData
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
this.createComponentsLabelList = function (components, lookUp) {
|
|
129
|
-
let labelList = []
|
|
130
|
-
components.forEach((n) => {
|
|
131
|
-
labelList.push(this.createLabelFromNeuralNode(n[0]), lookUp)
|
|
132
|
-
if (n.length === 2) {
|
|
133
|
-
labelList.push(this.createLabelFromNeuralNode(n[1]), lookUp)
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
return labelList
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
this.createLabelLookup = function (mapImp, uberons) {
|
|
140
|
-
return new Promise(async (resolve) => {
|
|
141
|
-
let uberonMap = {}
|
|
142
|
-
this.uberons = []
|
|
143
|
-
const entityLabels = await findTaxonomyLabels(mapImp, uberons);
|
|
144
|
-
if (entityLabels.length) {
|
|
145
|
-
entityLabels.forEach((entityLabel) => {
|
|
146
|
-
const { taxon: entity, label } = entityLabel;
|
|
147
|
-
uberonMap[entity] = label;
|
|
148
|
-
this.uberons.push({
|
|
149
|
-
id: entity,
|
|
150
|
-
name: label,
|
|
151
|
-
})
|
|
152
|
-
});
|
|
153
|
-
resolve(uberonMap)
|
|
154
|
-
}
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
this.buildConnectivitySqlStatement = function (keastIds) {
|
|
159
|
-
let sql = 'select knowledge from knowledge where entity in ('
|
|
160
|
-
if (keastIds.length === 1) {
|
|
161
|
-
sql += `'${keastIds[0]}')`
|
|
162
|
-
} else if (keastIds.length > 1) {
|
|
163
|
-
for (let i in keastIds) {
|
|
164
|
-
sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return sql
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
this.buildLabelSqlStatement = function (uberons) {
|
|
171
|
-
let sql = 'select entity, label from labels where entity in ('
|
|
172
|
-
if (uberons.length === 1) {
|
|
173
|
-
sql += `'${uberons[0]}')`
|
|
174
|
-
} else if (uberons.length > 1) {
|
|
175
|
-
for (let i in uberons) {
|
|
176
|
-
sql += `'${uberons[i]}'${i >= uberons.length - 1 ? ')' : ','} `
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return sql
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
this.findAllIdsFromConnectivity = function (connectivity) {
|
|
183
|
-
let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
|
|
184
|
-
let nodes = [...new Set(dnodes)] // remove duplicates
|
|
185
|
-
let found = []
|
|
186
|
-
nodes.forEach((n) => {
|
|
187
|
-
if (Array.isArray(n)) {
|
|
188
|
-
found.push(n.flat())
|
|
189
|
-
} else {
|
|
190
|
-
found.push(n)
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
return [...new Set(found.flat())]
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
this.flattenConntectivity = function (connectivity) {
|
|
197
|
-
let dnodes = connectivity.flat() // get nodes from edgelist
|
|
198
|
-
let nodes = [...new Set(dnodes)] // remove duplicates
|
|
199
|
-
let found = []
|
|
200
|
-
nodes.forEach((n) => {
|
|
201
|
-
if (Array.isArray(n)) {
|
|
202
|
-
found.push(n.flat())
|
|
203
|
-
} else {
|
|
204
|
-
found.push(n)
|
|
205
|
-
}
|
|
206
|
-
})
|
|
207
|
-
return found.flat()
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
this.findComponents = function (connectivity) {
|
|
211
|
-
let dnodes = connectivity.connectivity.flat() // get nodes from edgelist
|
|
212
|
-
let nodes = removeDuplicates(dnodes)
|
|
213
|
-
|
|
214
|
-
let found = []
|
|
215
|
-
let terminal = false
|
|
216
|
-
nodes.forEach((node) => {
|
|
217
|
-
terminal = false
|
|
218
|
-
// Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
|
|
219
|
-
if (inArray(connectivity.axons, node)) {
|
|
220
|
-
terminal = true
|
|
221
|
-
}
|
|
222
|
-
if (connectivity.somas && inArray(connectivity.somas, node)) {
|
|
223
|
-
terminal = true
|
|
224
|
-
}
|
|
225
|
-
if (inArray(connectivity.dendrites, node)) {
|
|
226
|
-
terminal = true
|
|
227
|
-
}
|
|
228
|
-
if (!terminal) {
|
|
229
|
-
found.push(node)
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
return found
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
this.retrieveFlatmapKnowledgeForEvent = async function (mapImp, eventData) {
|
|
237
|
-
// check if there is an existing query
|
|
238
|
-
if (this.controller) this.controller.abort()
|
|
239
|
-
|
|
240
|
-
// set up the abort controller
|
|
241
|
-
this.controller = new AbortController()
|
|
242
|
-
const signal = this.controller.signal
|
|
243
|
-
|
|
244
|
-
const keastIds = eventData.resource
|
|
245
|
-
this.destinations = []
|
|
246
|
-
this.origins = []
|
|
247
|
-
this.components = []
|
|
248
|
-
this.rawURLs = []
|
|
249
|
-
if (!keastIds || keastIds.length == 0 || !keastIds[0]) return
|
|
250
|
-
|
|
251
|
-
let prom1 = this.queryForConnectivityNew(mapImp, keastIds, signal) // This on returns a promise so dont need 'await'
|
|
252
|
-
let results = await Promise.all([prom1])
|
|
253
|
-
return results
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
this.queryForConnectivityNew = function (mapImp, keastIds, signal, processConnectivity=true) {
|
|
257
|
-
return new Promise((resolve) => {
|
|
258
|
-
mapImp.queryKnowledge(keastIds[0])
|
|
259
|
-
.then((response) => {
|
|
260
|
-
if (this.checkConnectivityExists(response)) {
|
|
261
|
-
let connectivity = response;
|
|
262
|
-
if (processConnectivity) {
|
|
263
|
-
this.processConnectivity(mapImp, connectivity).then((processedConnectivity) => {
|
|
264
|
-
// response.references is publication urls
|
|
265
|
-
if (response.references) {
|
|
266
|
-
// with publications from both PubMed and Others
|
|
267
|
-
this.rawURLs = [...response.references];
|
|
268
|
-
resolve(processedConnectivity)
|
|
269
|
-
} else {
|
|
270
|
-
// without publications
|
|
271
|
-
resolve(processedConnectivity)
|
|
272
|
-
}
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
else resolve(connectivity)
|
|
276
|
-
} else {
|
|
277
|
-
resolve(false)
|
|
278
|
-
}
|
|
279
|
-
})
|
|
280
|
-
.catch((error) => {
|
|
281
|
-
if (error.name === 'AbortError') {
|
|
282
|
-
// This error is from AbortController's abort method.
|
|
283
|
-
} else {
|
|
284
|
-
// console.error('Error:', error)
|
|
285
|
-
// TODO: to update after queryKnowledge method update
|
|
286
|
-
console.warn(`Unable to get the knowledge for the entity ${keastIds[0]}.`)
|
|
287
|
-
}
|
|
288
|
-
resolve(false)
|
|
289
|
-
})
|
|
290
|
-
})
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
this.queryForConnectivity = function (mapImp, keastIds, signal, processConnectivity=true) {
|
|
294
|
-
const data = { sql: this.buildConnectivitySqlStatement(keastIds) }
|
|
295
|
-
const headers = {
|
|
296
|
-
method: 'POST',
|
|
297
|
-
headers: {
|
|
298
|
-
'Content-Type': 'application/json',
|
|
299
|
-
},
|
|
300
|
-
body: JSON.stringify(data),
|
|
301
|
-
...(signal ? { signal: signal } : {}), // add signal to header if it exists
|
|
302
|
-
}
|
|
303
|
-
return new Promise((resolve) => {
|
|
304
|
-
fetch(`${this.flatmapApi}knowledge/query/`, headers)
|
|
305
|
-
.then((response) => response.json())
|
|
306
|
-
.then((data) => {
|
|
307
|
-
if (this.connectivityExists(data)) {
|
|
308
|
-
let connectivity = JSON.parse(data.values[0][0])
|
|
309
|
-
if (processConnectivity) {
|
|
310
|
-
this.processConnectivity(mapImp, connectivity).then((processedConnectivity) => {
|
|
311
|
-
resolve(processedConnectivity)
|
|
312
|
-
})
|
|
313
|
-
}
|
|
314
|
-
else resolve(connectivity)
|
|
315
|
-
} else {
|
|
316
|
-
resolve(false)
|
|
317
|
-
}
|
|
318
|
-
})
|
|
319
|
-
.catch((error) => {
|
|
320
|
-
if (error.name === 'AbortError') {
|
|
321
|
-
// This error is from AbortController's abort method.
|
|
322
|
-
} else {
|
|
323
|
-
console.error('Error:', error)
|
|
324
|
-
}
|
|
325
|
-
resolve(false)
|
|
326
|
-
})
|
|
327
|
-
})
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
this.checkConnectivityExists = function (data) {
|
|
331
|
-
return data && data.connectivity?.length;
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
this.connectivityExists = function (data) {
|
|
335
|
-
if (
|
|
336
|
-
data.values &&
|
|
337
|
-
data.values.length > 0 &&
|
|
338
|
-
JSON.parse(data.values[0][0]).connectivity &&
|
|
339
|
-
JSON.parse(data.values[0][0]).connectivity.length > 0
|
|
340
|
-
) {
|
|
341
|
-
return true
|
|
342
|
-
} else {
|
|
343
|
-
return false
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// This function is used to determine if a node is a single node or a node with multiple children
|
|
348
|
-
// Returns the id of the node if it is a single node, otherwise returns false
|
|
349
|
-
this.findIfNodeIsSingle = function (node) {
|
|
350
|
-
if (node.length === 1) { // If the node is in the form [id]
|
|
351
|
-
console.error("Server returns a single node", node)
|
|
352
|
-
return node[0]
|
|
353
|
-
} else {
|
|
354
|
-
if (node.length === 2 && node[1].length === 0) { // If the node is in the form [id, []]
|
|
355
|
-
return node[0]
|
|
356
|
-
} else {
|
|
357
|
-
return false // If the node is in the form [id, [id1, id2]]
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
this.createLabelFromNeuralNode = function (node, lookUp) {
|
|
363
|
-
|
|
364
|
-
// Check if the node is a single node or a node with multiple children
|
|
365
|
-
let nodeIsSingle = this.findIfNodeIsSingle(node)
|
|
366
|
-
|
|
367
|
-
// Case where node is in the form [id]
|
|
368
|
-
if (nodeIsSingle) {
|
|
369
|
-
return lookUp[nodeIsSingle]
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Case where node is in the form [id, [id1 (,id2)]]
|
|
373
|
-
let label = lookUp[node[0]]
|
|
374
|
-
if (node.length === 2 && node[1].length > 0) {
|
|
375
|
-
node[1].forEach((n) => {
|
|
376
|
-
if (lookUp[n] == undefined) {
|
|
377
|
-
label += `, ${n}`
|
|
378
|
-
} else {
|
|
379
|
-
label += `, ${lookUp[n]}`
|
|
380
|
-
}
|
|
381
|
-
})
|
|
382
|
-
}
|
|
383
|
-
return label
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
this.flattenAndFindDatasets = function (components, axons, dendrites) {
|
|
387
|
-
// process the nodes for finding datasets (Note this is not critical to the tooltip, only for the 'search on components' button)
|
|
388
|
-
let componentsFlat = this.flattenConntectivity(components)
|
|
389
|
-
let axonsFlat = this.flattenConntectivity(axons)
|
|
390
|
-
let dendritesFlat = this.flattenConntectivity(dendrites)
|
|
391
|
-
|
|
392
|
-
// Filter for the anatomy which is annotated on datasets
|
|
393
|
-
this.destinationsWithDatasets = this.uberons.filter(
|
|
394
|
-
(ub) => axonsFlat.indexOf(ub.id) !== -1
|
|
395
|
-
)
|
|
396
|
-
this.originsWithDatasets = this.uberons.filter(
|
|
397
|
-
(ub) => dendritesFlat.indexOf(ub.id) !== -1
|
|
398
|
-
)
|
|
399
|
-
this.componentsWithDatasets = this.uberons.filter(
|
|
400
|
-
(ub) => componentsFlat.indexOf(ub.id) !== -1
|
|
401
|
-
)
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
this.processConnectivity = function (mapImp, connectivity) {
|
|
405
|
-
return new Promise((resolve) => {
|
|
406
|
-
// Filter the origin and destinations from components
|
|
407
|
-
let components = this.findComponents(connectivity)
|
|
408
|
-
|
|
409
|
-
// Remove duplicates
|
|
410
|
-
let axons = removeDuplicates(connectivity.axons)
|
|
411
|
-
//Somas will become part of origins, support this for future proof
|
|
412
|
-
let dendrites = []
|
|
413
|
-
if (connectivity.somas && connectivity.somas.length > 0) {
|
|
414
|
-
dendrites.push(...connectivity.somas)
|
|
415
|
-
}
|
|
416
|
-
if (connectivity.dendrites && connectivity.dendrites.length > 0) {
|
|
417
|
-
dendrites.push(...connectivity.dendrites)
|
|
418
|
-
}
|
|
419
|
-
dendrites = removeDuplicates(dendrites)
|
|
420
|
-
|
|
421
|
-
// Create list of ids to get labels for
|
|
422
|
-
let conIds = this.findAllIdsFromConnectivity(connectivity)
|
|
423
|
-
|
|
424
|
-
// Create readable labels from the nodes. Setting this to 'this.origins' updates the display
|
|
425
|
-
this.createLabelLookup(mapImp, conIds).then((lookUp) => {
|
|
426
|
-
this.destinations = axons.map((a) =>
|
|
427
|
-
this.createLabelFromNeuralNode(a, lookUp)
|
|
428
|
-
)
|
|
429
|
-
this.origins = dendrites.map((d) =>
|
|
430
|
-
this.createLabelFromNeuralNode(d, lookUp)
|
|
431
|
-
)
|
|
432
|
-
this.components = components.map((c) =>
|
|
433
|
-
this.createLabelFromNeuralNode(c, lookUp)
|
|
434
|
-
)
|
|
435
|
-
this.flattenAndFindDatasets(components, axons, dendrites)
|
|
436
|
-
resolve({
|
|
437
|
-
ids: {
|
|
438
|
-
axons: axons,
|
|
439
|
-
dendrites: dendrites,
|
|
440
|
-
components: components,
|
|
441
|
-
},
|
|
442
|
-
labels: {
|
|
443
|
-
destinations: this.destinations,
|
|
444
|
-
origins: this.origins,
|
|
445
|
-
components: this.components,
|
|
446
|
-
}
|
|
447
|
-
})
|
|
448
|
-
})
|
|
449
|
-
})
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
this.flattenConntectivity = function (connectivity) {
|
|
453
|
-
let dnodes = connectivity.flat() // get nodes from edgelist
|
|
454
|
-
let nodes = [...new Set(dnodes)] // remove duplicates
|
|
455
|
-
let found = []
|
|
456
|
-
nodes.forEach((n) => {
|
|
457
|
-
if (Array.isArray(n)) {
|
|
458
|
-
found.push(n.flat())
|
|
459
|
-
} else {
|
|
460
|
-
found.push(n)
|
|
461
|
-
}
|
|
462
|
-
})
|
|
463
|
-
return found.flat()
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
this.buildPubmedSqlStatement = function (keastIds) {
|
|
467
|
-
let sql = 'select distinct publication from publications where entity in ('
|
|
468
|
-
if (keastIds.length === 1) {
|
|
469
|
-
sql += `'${keastIds[0]}')`
|
|
470
|
-
} else if (keastIds.length > 1) {
|
|
471
|
-
for (let i in keastIds) {
|
|
472
|
-
sql += `'${keastIds[i]}'${i >= keastIds.length - 1 ? ')' : ','} `
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
return sql
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
this.buildPubmedSqlStatementForModels = function (model) {
|
|
479
|
-
return `select distinct publication from publications where entity = '${model}'`
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
this.flatmapQuery = function (sql) {
|
|
483
|
-
const data = { sql: sql }
|
|
484
|
-
return fetch(`${this.flatmapApi}knowledge/query/`, {
|
|
485
|
-
method: 'POST',
|
|
486
|
-
headers: {
|
|
487
|
-
'Content-Type': 'application/json',
|
|
488
|
-
},
|
|
489
|
-
body: JSON.stringify(data),
|
|
490
|
-
})
|
|
491
|
-
.then((response) => response.json())
|
|
492
|
-
.catch((error) => {
|
|
493
|
-
console.error('Error:', error)
|
|
494
|
-
})
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
export { FlatmapQueries, findTaxonomyLabel, findTaxonomyLabels }
|