@abi-software/map-utilities 1.6.1-beta.0 → 1.6.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-utilities",
3
- "version": "1.6.1-beta.0",
3
+ "version": "1.6.1-beta.1",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
@@ -171,10 +171,56 @@ async function queryPathsByDestination(flatmapAPI, knowledgeSource, featureId) {
171
171
  return [];
172
172
  }
173
173
 
174
+ // Neuron populations from origin node(s) to destination node(s), via node(s)
175
+ // API Label: Neuron populations that have source, via, and destination nodes
176
+ async function queryPathsByRoute({ flatmapAPI, knowledgeSource, origins, destinations, vias }) {
177
+ const originParam = {
178
+ column: 'source_node_id',
179
+ value: origins
180
+ };
181
+ const viaParam = {
182
+ column: 'via_node_id',
183
+ value: vias
184
+ };
185
+ const destinationParam = {
186
+ column: 'dest_node_id',
187
+ value: destinations
188
+ };
189
+ if (!origins.length) {
190
+ originParam['negate'] = true;
191
+ }
192
+ if (!vias.length) {
193
+ viaParam['negate'] = true;
194
+ }
195
+ if (!destinations.length) {
196
+ destinationParam['negate'] = true;
197
+ }
198
+ const data = await competencyQuery({
199
+ flatmapAPI: flatmapAPI,
200
+ knowledgeSource: knowledgeSource,
201
+ queryId: 24,
202
+ parameters: [
203
+ originParam,
204
+ viaParam,
205
+ destinationParam,
206
+ ]
207
+ });
208
+ if (data?.results?.values) {
209
+ const paths = data.results.values.map((value) => {
210
+ // value => [ 'source_id', 'path_id', 'axon_terminal']
211
+ return value[1];
212
+ });
213
+ // remove duplicates
214
+ return [...new Set(paths)];
215
+ }
216
+ return [];
217
+ }
218
+
174
219
  export {
175
220
  competencyQuery,
176
221
  queryAllConnectedPaths,
177
222
  queryPathsByOrigin,
178
223
  queryPathsByViaLocation,
179
224
  queryPathsByDestination,
225
+ queryPathsByRoute,
180
226
  };
@@ -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,32 @@ function getPhenotypeItems(obj, prop) {
66
106
  return arr;
67
107
  }
68
108
 
69
- function extractOriginItems(knowledge) {
109
+ async function transformResults(flatmapAPI, 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 formattedResults = baseResults.map((item) => {
118
+ const itemPair = item.flat();
119
+ const labels = [];
120
+ for (let i = 0; i < itemPair.length; i++) {
121
+ const foundObj = objectResults.find((obj) => obj.id === itemPair[i])
122
+ if (foundObj) {
123
+ labels.push(foundObj.label);
124
+ }
125
+ }
126
+ return {
127
+ key: item,
128
+ label: labels.join(', '),
129
+ };
130
+ });
131
+ return formattedResults;
132
+ }
133
+
134
+ async function extractOriginItems(flatmapAPI, knowledge) {
70
135
  const results = [];
71
136
  knowledge.forEach(obj => {
72
137
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
@@ -76,12 +141,10 @@ function extractOriginItems(knowledge) {
76
141
  if (connectivityItems.has(stringifyItem)) results.push(item);
77
142
  });
78
143
  });
79
- return Array.from(
80
- new Map(results.map(item => [JSON.stringify(item), item])).values()
81
- );
144
+ return await transformResults(flatmapAPI, results);
82
145
  }
83
146
 
84
- function extractDestinationItems(knowledge) {
147
+ async function extractDestinationItems(flatmapAPI, knowledge) {
85
148
  const results = [];
86
149
  knowledge.forEach(obj => {
87
150
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
@@ -94,12 +157,10 @@ function extractDestinationItems(knowledge) {
94
157
  if (connectivityItems.has(stringifyItem)) results.push(item);
95
158
  });
96
159
  });
97
- return Array.from(
98
- new Map(results.map(item => [JSON.stringify(item), item])).values()
99
- );
160
+ return await transformResults(flatmapAPI, results);
100
161
  }
101
162
 
102
- function extractViaItems(knowledge) {
163
+ async function extractViaItems(flatmapAPI, knowledge) {
103
164
  const results = [];
104
165
  knowledge.forEach(obj => {
105
166
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return;
@@ -112,41 +173,55 @@ function extractViaItems(knowledge) {
112
173
  if (connectivityItems.has(stringifyItem)) results.push(item);
113
174
  });
114
175
  });
115
- return Array.from(
116
- new Map(results.map(item => [JSON.stringify(item), item])).values()
117
- );
176
+ return await transformResults(flatmapAPI, results);
118
177
  }
119
178
 
120
- function findPathsByOriginItem(knowledge, originItem) {
179
+ function findPathsByOriginItem(knowledge, originItems) {
121
180
  return knowledge.filter(obj => {
122
181
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
123
182
  const origins = getPhenotypeItems(obj, "ilxtr:hasSomaLocatedIn");
124
- return origins.some(item => JSON.stringify(item) === JSON.stringify(originItem));
183
+ return origins.some(item => originItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
125
184
  });
126
185
  }
127
186
 
128
- function findPathsByDestinationItem(knowledge, destinationItem) {
187
+ function findPathsByDestinationItem(knowledge, destinationItems) {
129
188
  return knowledge.filter(obj => {
130
189
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
131
190
  const destinations = [
132
191
  ...getPhenotypeItems(obj, "ilxtr:hasAxonPresynapticElementIn"),
133
192
  ...getPhenotypeItems(obj, "ilxtr:hasAxonSensorySubcellularElementIn")
134
193
  ];
135
- return destinations.some(item => JSON.stringify(item) === JSON.stringify(destinationItem));
194
+ return destinations.some(item => destinationItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
136
195
  });
137
196
  }
138
197
 
139
- function findPathsByViaItem(knowledge, viaItem) {
198
+ function findPathsByViaItem(knowledge, viaItems) {
140
199
  return knowledge.filter(obj => {
141
200
  if (!Array.isArray(obj.connectivity) || obj.connectivity.length === 0) return false;
142
201
  const vias = [
143
202
  ...getPhenotypeItems(obj, "ilxtr:hasAxonLeadingToSensorySubcellularElementIn"),
144
203
  ...getPhenotypeItems(obj, "ilxtr:hasAxonLocatedIn")
145
204
  ];
146
- return vias.some(item => JSON.stringify(item) === JSON.stringify(viaItem));
205
+ return vias.some(item => viaItems.map(i => JSON.stringify(i)).includes(JSON.stringify(item)));
147
206
  });
148
207
  }
149
208
 
209
+ async function queryPathsByRouteFromKnowledge({ knowledge, origins, destinations, vias }) {
210
+ let results = knowledge;
211
+
212
+ if (origins.length) {
213
+ results = findPathsByOriginItem(results, origins);
214
+ }
215
+ if (destinations.length) {
216
+ results = findPathsByDestinationItem(results, destinations);
217
+ }
218
+ if (vias.length) {
219
+ results = findPathsByViaItem(results, vias);
220
+ }
221
+
222
+ return results;
223
+ }
224
+
150
225
  export {
151
226
  filterOrigins,
152
227
  filterDestinations,
@@ -157,4 +232,6 @@ export {
157
232
  findPathsByOriginItem,
158
233
  findPathsByDestinationItem,
159
234
  findPathsByViaItem,
235
+ queryPathsByRouteFromKnowledge,
236
+ fetchLabels,
160
237
  }
@@ -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
  };