@abi-software/map-utilities 1.6.1-beta.0 → 1.6.1-beta.2
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/package.json
CHANGED
|
@@ -171,10 +171,112 @@ async function queryPathsByDestination(flatmapAPI, knowledgeSource, featureId) {
|
|
|
171
171
|
return [];
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
function extractFeatureIds(inputArray) {
|
|
175
|
+
const result = [];
|
|
176
|
+
|
|
177
|
+
for (const itemString of inputArray) {
|
|
178
|
+
const item = JSON.parse(itemString);
|
|
179
|
+
|
|
180
|
+
if (Array.isArray(item) && item.length >= 2) {
|
|
181
|
+
if (Array.isArray(item[1]) && item[1].length === 0) {
|
|
182
|
+
result.push(item[0]);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Neuron populations from origin to destination, via
|
|
190
|
+
// Query 24: Neuron populations that have source, via, and destination nodes
|
|
191
|
+
// Query 25: Neuron populations that have source, via, and destination locations
|
|
192
|
+
async function queryPathsByRoute({ flatmapAPI, knowledgeSource, origins, destinations, vias }) {
|
|
193
|
+
const originFeatureIds = extractFeatureIds(origins);
|
|
194
|
+
const destinationFeatureIds = extractFeatureIds(destinations);
|
|
195
|
+
const viaFeatureIds = extractFeatureIds(vias);
|
|
196
|
+
|
|
197
|
+
const paramsF = [
|
|
198
|
+
{
|
|
199
|
+
column: 'source_feature_id',
|
|
200
|
+
value: originFeatureIds,
|
|
201
|
+
...(originFeatureIds.length === 0 && { negate: true })
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
column: 'via_feature_id',
|
|
205
|
+
value: viaFeatureIds,
|
|
206
|
+
...(viaFeatureIds.length === 0 && { negate: true })
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
column: 'dest_feature_id',
|
|
210
|
+
value: destinationFeatureIds,
|
|
211
|
+
...(destinationFeatureIds.length === 0 && { negate: true })
|
|
212
|
+
}
|
|
213
|
+
];
|
|
214
|
+
|
|
215
|
+
const params = [
|
|
216
|
+
{
|
|
217
|
+
column: 'source_node_id',
|
|
218
|
+
value: origins,
|
|
219
|
+
...(origins.length === 0 && { negate: true })
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
column: 'via_node_id',
|
|
223
|
+
value: vias,
|
|
224
|
+
...(vias.length === 0 && { negate: true })
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
column: 'dest_node_id',
|
|
228
|
+
value: destinations,
|
|
229
|
+
...(destinations.length === 0 && { negate: true })
|
|
230
|
+
}
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
const shouldCallDataF = paramsF.some(param =>
|
|
234
|
+
Array.isArray(param.value) && param.value.length > 0);
|
|
235
|
+
|
|
236
|
+
const promises = [
|
|
237
|
+
competencyQuery({
|
|
238
|
+
flatmapAPI,
|
|
239
|
+
knowledgeSource,
|
|
240
|
+
queryId: 24,
|
|
241
|
+
parameters: params
|
|
242
|
+
})
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
if (shouldCallDataF) {
|
|
246
|
+
promises.push(
|
|
247
|
+
competencyQuery({
|
|
248
|
+
flatmapAPI,
|
|
249
|
+
knowledgeSource,
|
|
250
|
+
queryId: 25,
|
|
251
|
+
parameters: paramsF
|
|
252
|
+
})
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const results = await Promise.all(promises);
|
|
257
|
+
|
|
258
|
+
let pathsF = [];
|
|
259
|
+
let data;
|
|
260
|
+
if (shouldCallDataF) {
|
|
261
|
+
const dataF = results[0];
|
|
262
|
+
data = results[1];
|
|
263
|
+
// value => [ 'source_id', 'path_id', 'axon_terminal']
|
|
264
|
+
pathsF = dataF?.results?.values?.map(value => value[1]) || [];
|
|
265
|
+
} else {
|
|
266
|
+
data = results[0];
|
|
267
|
+
}
|
|
268
|
+
// value => [ 'source_id', 'path_id', 'axon_terminal']
|
|
269
|
+
const paths = data?.results?.values?.map(value => value[1]) || [];
|
|
270
|
+
const combined = [...new Set([...pathsF, ...paths])];
|
|
271
|
+
|
|
272
|
+
return combined;
|
|
273
|
+
}
|
|
274
|
+
|
|
174
275
|
export {
|
|
175
276
|
competencyQuery,
|
|
176
277
|
queryAllConnectedPaths,
|
|
177
278
|
queryPathsByOrigin,
|
|
178
279
|
queryPathsByViaLocation,
|
|
179
280
|
queryPathsByDestination,
|
|
281
|
+
queryPathsByRoute,
|
|
180
282
|
};
|
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
// destinations = ilxtr:hasAxonPresynapticElementIn, ilxtr:hasAxonSensorySubcellularElementIn
|
|
3
3
|
// via = ilxtr:hasAxonLeadingToSensorySubcellularElementIn, ilxtr:hasAxonLocatedIn
|
|
4
4
|
|
|
5
|
+
async function query(flatmapAPI, sql, params) {
|
|
6
|
+
const url = `${flatmapAPI}knowledge/query/`;
|
|
7
|
+
const query = { sql, params };
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const response = await fetch(url, {
|
|
11
|
+
method: 'POST',
|
|
12
|
+
headers: {
|
|
13
|
+
"Accept": "application/json; charset=utf-8",
|
|
14
|
+
"Content-Type": "application/json"
|
|
15
|
+
},
|
|
16
|
+
body: JSON.stringify(query)
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`Cannot access ${url}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return await response.json();
|
|
24
|
+
} catch {
|
|
25
|
+
return {
|
|
26
|
+
values: []
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function fetchLabels(flatmapAPI, labelledTerms) {
|
|
32
|
+
if (!labelledTerms.length) return [];
|
|
33
|
+
|
|
34
|
+
const data = await query(
|
|
35
|
+
flatmapAPI,
|
|
36
|
+
`select entity, knowledge from knowledge
|
|
37
|
+
where entity in (?${', ?'.repeat(labelledTerms.length - 1)})
|
|
38
|
+
order by source desc`,
|
|
39
|
+
[...labelledTerms]
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return await data.values;
|
|
43
|
+
}
|
|
44
|
+
|
|
5
45
|
function filterOrigins(item) {
|
|
6
46
|
const soma = item["node-phenotypes"]?.["ilxtr:hasSomaLocatedIn"];
|
|
7
47
|
return Array.isArray(item.connectivity) &&
|
|
@@ -66,7 +106,52 @@ function getPhenotypeItems(obj, prop) {
|
|
|
66
106
|
return arr;
|
|
67
107
|
}
|
|
68
108
|
|
|
69
|
-
function
|
|
109
|
+
async function transformResults(flatmapAPI, knowledgeSource, results) {
|
|
110
|
+
const baseResults = Array.from(
|
|
111
|
+
new Map(results.map(item => [JSON.stringify(item), item])).values()
|
|
112
|
+
);
|
|
113
|
+
const terms = baseResults.flat(Infinity);
|
|
114
|
+
const uniqueTerms = [...new Set(terms)];
|
|
115
|
+
const fetchResults = await fetchLabels(flatmapAPI, uniqueTerms);
|
|
116
|
+
// const objectResults = fetchResults.map((item) => JSON.parse(item[1]));
|
|
117
|
+
const objectResults = fetchResults.reduce((arr, item) => {
|
|
118
|
+
const id = item[0];
|
|
119
|
+
const valObj = JSON.parse(item[1]);
|
|
120
|
+
if (valObj.source === knowledgeSource) {
|
|
121
|
+
arr.push({ id, label: valObj.label });
|
|
122
|
+
}
|
|
123
|
+
return arr;
|
|
124
|
+
}, []);
|
|
125
|
+
const nodes = [];
|
|
126
|
+
const formattedResults = baseResults.map((item) => {
|
|
127
|
+
const itemPair = item.flat();
|
|
128
|
+
const labels = [];
|
|
129
|
+
for (let i = 0; i < itemPair.length; i++) {
|
|
130
|
+
const foundObj = objectResults.find((obj) => obj.id === itemPair[i])
|
|
131
|
+
if (foundObj) {
|
|
132
|
+
labels.push(foundObj.label);
|
|
133
|
+
if (i > 0) {
|
|
134
|
+
nodes.push({
|
|
135
|
+
key: [itemPair[i], []],
|
|
136
|
+
label: foundObj.label,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
key: item,
|
|
143
|
+
label: labels.join(', '),
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
// unique results by combining formattedResults and nodes
|
|
147
|
+
// but filter out duplicates based on the labels
|
|
148
|
+
const uniqueResults = [...formattedResults, ...nodes].filter((result, index, self) =>
|
|
149
|
+
index === self.findIndex((r) => r.label === result.label)
|
|
150
|
+
);
|
|
151
|
+
return uniqueResults;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function extractOriginItems(flatmapAPI, knowledgeSource, knowledge) {
|
|
70
155
|
const results = [];
|
|
71
156
|
knowledge.forEach(obj => {
|
|
72
157
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
|
|
@@ -76,12 +161,10 @@ function extractOriginItems(knowledge) {
|
|
|
76
161
|
if (connectivityItems.has(stringifyItem)) results.push(item);
|
|
77
162
|
});
|
|
78
163
|
});
|
|
79
|
-
return
|
|
80
|
-
new Map(results.map(item => [JSON.stringify(item), item])).values()
|
|
81
|
-
);
|
|
164
|
+
return await transformResults(flatmapAPI, knowledgeSource, results);
|
|
82
165
|
}
|
|
83
166
|
|
|
84
|
-
function extractDestinationItems(knowledge) {
|
|
167
|
+
async function extractDestinationItems(flatmapAPI, knowledgeSource, knowledge) {
|
|
85
168
|
const results = [];
|
|
86
169
|
knowledge.forEach(obj => {
|
|
87
170
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
|
|
@@ -94,12 +177,10 @@ function extractDestinationItems(knowledge) {
|
|
|
94
177
|
if (connectivityItems.has(stringifyItem)) results.push(item);
|
|
95
178
|
});
|
|
96
179
|
});
|
|
97
|
-
return
|
|
98
|
-
new Map(results.map(item => [JSON.stringify(item), item])).values()
|
|
99
|
-
);
|
|
180
|
+
return await transformResults(flatmapAPI, knowledgeSource, results);
|
|
100
181
|
}
|
|
101
182
|
|
|
102
|
-
function extractViaItems(knowledge) {
|
|
183
|
+
async function extractViaItems(flatmapAPI, knowledgeSource, knowledge) {
|
|
103
184
|
const results = [];
|
|
104
185
|
knowledge.forEach(obj => {
|
|
105
186
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
|
|
@@ -112,41 +193,55 @@ function extractViaItems(knowledge) {
|
|
|
112
193
|
if (connectivityItems.has(stringifyItem)) results.push(item);
|
|
113
194
|
});
|
|
114
195
|
});
|
|
115
|
-
return
|
|
116
|
-
new Map(results.map(item => [JSON.stringify(item), item])).values()
|
|
117
|
-
);
|
|
196
|
+
return await transformResults(flatmapAPI, knowledgeSource, results);
|
|
118
197
|
}
|
|
119
198
|
|
|
120
|
-
function findPathsByOriginItem(knowledge,
|
|
199
|
+
function findPathsByOriginItem(knowledge, originItems) {
|
|
121
200
|
return knowledge.filter(obj => {
|
|
122
201
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
|
|
123
202
|
const origins = getPhenotypeItems(obj, "ilxtr:hasSomaLocatedIn");
|
|
124
|
-
return origins.some(item => JSON.stringify(
|
|
203
|
+
return origins.some(item => originItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
|
|
125
204
|
});
|
|
126
205
|
}
|
|
127
206
|
|
|
128
|
-
function findPathsByDestinationItem(knowledge,
|
|
207
|
+
function findPathsByDestinationItem(knowledge, destinationItems) {
|
|
129
208
|
return knowledge.filter(obj => {
|
|
130
209
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
|
|
131
210
|
const destinations = [
|
|
132
211
|
...getPhenotypeItems(obj, "ilxtr:hasAxonPresynapticElementIn"),
|
|
133
212
|
...getPhenotypeItems(obj, "ilxtr:hasAxonSensorySubcellularElementIn")
|
|
134
213
|
];
|
|
135
|
-
return destinations.some(item => JSON.stringify(
|
|
214
|
+
return destinations.some(item => destinationItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
|
|
136
215
|
});
|
|
137
216
|
}
|
|
138
217
|
|
|
139
|
-
function findPathsByViaItem(knowledge,
|
|
218
|
+
function findPathsByViaItem(knowledge, viaItems) {
|
|
140
219
|
return knowledge.filter(obj => {
|
|
141
220
|
if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
|
|
142
221
|
const vias = [
|
|
143
222
|
...getPhenotypeItems(obj, "ilxtr:hasAxonLeadingToSensorySubcellularElementIn"),
|
|
144
223
|
...getPhenotypeItems(obj, "ilxtr:hasAxonLocatedIn")
|
|
145
224
|
];
|
|
146
|
-
return vias.some(item => JSON.stringify(
|
|
225
|
+
return vias.some(item => viaItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
|
|
147
226
|
});
|
|
148
227
|
}
|
|
149
228
|
|
|
229
|
+
async function queryPathsByRouteFromKnowledge({ knowledge, origins, destinations, vias }) {
|
|
230
|
+
let results = knowledge;
|
|
231
|
+
|
|
232
|
+
if (origins.length) {
|
|
233
|
+
results = findPathsByOriginItem(results, origins);
|
|
234
|
+
}
|
|
235
|
+
if (destinations.length) {
|
|
236
|
+
results = findPathsByDestinationItem(results, destinations);
|
|
237
|
+
}
|
|
238
|
+
if (vias.length) {
|
|
239
|
+
results = findPathsByViaItem(results, vias);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return results;
|
|
243
|
+
}
|
|
244
|
+
|
|
150
245
|
export {
|
|
151
246
|
filterOrigins,
|
|
152
247
|
filterDestinations,
|
|
@@ -157,4 +252,6 @@ export {
|
|
|
157
252
|
findPathsByOriginItem,
|
|
158
253
|
findPathsByDestinationItem,
|
|
159
254
|
findPathsByViaItem,
|
|
255
|
+
queryPathsByRouteFromKnowledge,
|
|
256
|
+
fetchLabels,
|
|
160
257
|
}
|
package/src/components/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
queryPathsByOrigin,
|
|
15
15
|
queryPathsByViaLocation,
|
|
16
16
|
queryPathsByDestination,
|
|
17
|
+
queryPathsByRoute,
|
|
17
18
|
} from "./CompetencyQueries/CompetencyQueries.js";
|
|
18
19
|
import {
|
|
19
20
|
filterOrigins,
|
|
@@ -25,6 +26,8 @@ import {
|
|
|
25
26
|
findPathsByOriginItem,
|
|
26
27
|
findPathsByDestinationItem,
|
|
27
28
|
findPathsByViaItem,
|
|
29
|
+
queryPathsByRouteFromKnowledge,
|
|
30
|
+
fetchLabels,
|
|
28
31
|
} from "./CompetencyQueries/knowledgeQueries.js";
|
|
29
32
|
|
|
30
33
|
export {
|
|
@@ -43,6 +46,7 @@ export {
|
|
|
43
46
|
queryPathsByOrigin,
|
|
44
47
|
queryPathsByViaLocation,
|
|
45
48
|
queryPathsByDestination,
|
|
49
|
+
queryPathsByRoute,
|
|
46
50
|
filterOrigins,
|
|
47
51
|
filterDestinations,
|
|
48
52
|
filterViaLocations,
|
|
@@ -52,4 +56,6 @@ export {
|
|
|
52
56
|
findPathsByOriginItem,
|
|
53
57
|
findPathsByDestinationItem,
|
|
54
58
|
findPathsByViaItem,
|
|
59
|
+
queryPathsByRouteFromKnowledge,
|
|
60
|
+
fetchLabels,
|
|
55
61
|
};
|