@abi-software/map-utilities 1.5.0-beta.0 → 1.5.0-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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-utilities",
3
- "version": "1.5.0-beta.0",
3
+ "version": "1.5.0-beta.2",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
@@ -32,6 +32,7 @@
32
32
  "@abi-software/svg-sprite": "^1.0.1",
33
33
  "@element-plus/icons-vue": "^2.3.1",
34
34
  "cytoscape": "^3.30.2",
35
+ "cytoscape-dagre": "^2.5.0",
35
36
  "element-plus": "2.8.4",
36
37
  "mitt": "^3.0.1",
37
38
  "vue": "^3.4.21"
package/src/App.vue CHANGED
@@ -39,8 +39,16 @@ const drawnTypes = [
39
39
  { value: "None", label: "None" },
40
40
  ];
41
41
  const showConnectivityGraph = ref(false);
42
- const connectivityGraphEntry = "ilxtr:neuron-type-aacar-13";
43
- // const connectivityGraphEntry = "ilxtr:sparc-nlp/kidney/134";
42
+ const connectivityGraphEntry = ref("ilxtr:neuron-type-aacar-13");
43
+ const connectivityGraphEntries = [
44
+ "ilxtr:neuron-type-aacar-13",
45
+ "ilxtr:sparc-nlp/kidney/134",
46
+ "ilxtr:neuron-type-aacar-11",
47
+ "ilxtr:neuron-type-sstom-14",
48
+ "ilxtr:neuron-type-keast-6",
49
+ "ilxtr:neuron-type-aacar-4",
50
+ "ilxtr:neuron-type-aacar-12",
51
+ ];
44
52
  const mapServer = "https://mapcore-demo.org/curation/flatmap/";
45
53
  const sckanVersion = "sckan-2024-09-21-npo";
46
54
 
@@ -130,7 +138,7 @@ function onActionClick(value) {
130
138
  * Tooltip
131
139
  */
132
140
  const tooltipDisplay = ref(false);
133
- const tooltipEntry = ref({});
141
+ const tooltipEntry = ref([]);
134
142
  const featuresAlert = ref(undefined);
135
143
  const annotationDisplay = ref(false);
136
144
  const annotationEntry = ref({});
@@ -141,33 +149,90 @@ provide(/* key */ "userApiKey", /* value */ undefined);
141
149
 
142
150
  function addTooltipEntry() {
143
151
  tooltipDisplay.value = true;
144
- tooltipEntry.value = {
145
- destinations: [null],
146
- origins: [null],
147
- components: ["pudendal nerve"],
148
- destinationsWithDatasets: [
149
- { id: "UBERON:0004917", name: "urethral sphincter" },
150
- ],
151
- originsWithDatasets: [
152
- { id: "UBERON:0022278", name: "nucleus of pudendal nerve" },
153
- ],
154
- componentsWithDatasets: [{ id: "UBERON:0011390", name: "pudendal nerve" }],
155
- title:
156
- "Nucleus of the pudendal nerve to urethral sphincter via pudendal nerve",
157
- featureId: ["ilxtr:sparc-nlp/mmset1/1"],
158
- hyperlinks: [
159
- {
160
- url: "https://pubmed.ncbi.nlm.nih.gov/?term=%2F%2Fdoi.org%2F10.1155%252F2012%252F816274",
161
- id: "pubmed",
162
- },
163
- ],
164
- provenanceTaxonomy: ["NCBITaxon:9606"],
165
- provenanceTaxonomyLabel: ["Homo sapiens"],
166
- };
152
+ tooltipEntry.value = [
153
+ {
154
+ destinations: ["eccrine sweat gland of the trunk"],
155
+ origins: [
156
+ "Sixth thoracic ganglion",
157
+ "Twelfth thoracic ganglion",
158
+ "Fifth thoracic ganglion",
159
+ "Ninth thoracic ganglion",
160
+ "Seventh thoracic ganglion",
161
+ "Eighth thoracic ganglion",
162
+ "Fourth thoracic ganglion",
163
+ "Tenth thoracic ganglion",
164
+ "Eleventh thoracic ganglion",
165
+ ],
166
+ components: ["nerve"],
167
+ destinationsWithDatasets: [
168
+ { id: "ILX:0795061", name: "eccrine sweat gland of the trunk" },
169
+ ],
170
+ originsWithDatasets: [
171
+ { id: "ILX:0784378", name: "Ninth thoracic ganglion" },
172
+ { id: "ILX:0784569", name: "Tenth thoracic ganglion" },
173
+ { id: "ILX:0784721", name: "Eighth thoracic ganglion" },
174
+ { id: "ILX:0786141", name: "Fifth thoracic ganglion" },
175
+ { id: "ILX:0786272", name: "Fourth thoracic ganglion" },
176
+ { id: "ILX:0787009", name: "Twelfth thoracic ganglion" },
177
+ { id: "ILX:0787015", name: "Eleventh thoracic ganglion" },
178
+ { id: "ILX:0789947", name: "Sixth thoracic ganglion" },
179
+ { id: "ILX:0790482", name: "Seventh thoracic ganglion" },
180
+ ],
181
+ componentsWithDatasets: [{ id: "UBERON:0001021", name: "nerve" }],
182
+ title: "neuron type swglnd 161",
183
+ featureId: ["ilxtr:sparc-nlp/swglnd/161"],
184
+ hyperlinks: [
185
+ "https://doi.org/10.1007/s10286-015-0282-1",
186
+ "https://doi.org/10.1111/bjd.15808",
187
+ "https://doi.org/10.1159/000060678",
188
+ ],
189
+ provenanceTaxonomy: ["NCBITaxon:9606"],
190
+ provenanceTaxonomyLabel: ["Homo sapiens"],
191
+ knowledgeSource: "sckan-2024-09-21-npo",
192
+ mapId: "rat-flatmap",
193
+ mapuuid: "b4ae1699-5690-5640-97b7-d711ae02dcb9",
194
+ },
195
+ {
196
+ destinations: ["intramural ganglion of the kidney"],
197
+ origins: ["dorsal motor nucleus of vagus nerve"],
198
+ components: [
199
+ "renal nerve plexus",
200
+ "aortic plexus",
201
+ "esophageal vagus trunk",
202
+ "vagus X nerve trunk",
203
+ "vagus nerve",
204
+ ],
205
+ destinationsWithDatasets: [
206
+ { id: "ILX:0795056", name: "intramural ganglion of the kidney" },
207
+ ],
208
+ originsWithDatasets: [
209
+ { id: "UBERON:0002870", name: "dorsal motor nucleus of vagus nerve" },
210
+ ],
211
+ componentsWithDatasets: [
212
+ { id: "ILX:0794853", name: "esophageal vagus trunk" },
213
+ { id: "UBERON:0001759", name: "vagus nerve" },
214
+ { id: "UBERON:0003535", name: "vagus X nerve trunk" },
215
+ { id: "UBERON:0018676", name: "renal nerve plexus" },
216
+ { id: "UBERON:0035772", name: "aortic plexus" },
217
+ ],
218
+ title:
219
+ "dorsal motor nucleus of vagus nerve to intramural ganglia of the kidney via vagus nerve via esophageal vagus trunk via vagal trunks via aortic plexus via renal plexus",
220
+ featureId: ["ilxtr:sparc-nlp/kidney/135"],
221
+ hyperlinks: [
222
+ "https://uilx.org/tgbugs/u/r/isbn-13/978-0323680424",
223
+ "https://doi.org/10.1016/j.aanat.2015.11.004",
224
+ ],
225
+ provenanceTaxonomy: ["NCBITaxon:9606"],
226
+ provenanceTaxonomyLabel: ["Homo sapiens"],
227
+ knowledgeSource: "sckan-2024-09-21-npo",
228
+ mapId: "rat-flatmap",
229
+ mapuuid: "b4ae1699-5690-5640-97b7-d711ae02dcb9",
230
+ },
231
+ ];
167
232
  }
168
233
  function removeTooltipEntry() {
169
234
  tooltipDisplay.value = false;
170
- tooltipEntry.value = {};
235
+ tooltipEntry.value = [];
171
236
  }
172
237
  function addAnnotationEntry() {
173
238
  tooltipDisplay.value = true;
@@ -234,7 +299,7 @@ function setColourField(treeData, nodeData, activeColour) {
234
299
  function setColour(nodeData, value) {
235
300
  if (nodeData && nodeData.isPrimitives) {
236
301
  const activeColour = value ? value : nodeData.defaultColour;
237
- setColourField(treeDataEntry.value, nodeData, activeColour)
302
+ setColourField(treeDataEntry.value, nodeData, activeColour);
238
303
  }
239
304
  }
240
305
  function checkAll(value) {
@@ -263,7 +328,7 @@ const createData = ref({
263
328
  editingIndex: -1,
264
329
  faceIndex: -1,
265
330
  toBeDeleted: false,
266
- })
331
+ });
267
332
  function cancelCreate() {
268
333
  console.log("🚀 ~ CreateTooltipContent : cancelCreate");
269
334
  }
@@ -422,14 +487,14 @@ function confirmCreate(value) {
422
487
  Add Tooltip Entry
423
488
  </el-button>
424
489
  <el-button
425
- v-show="Object.keys(tooltipEntry).length > 0"
490
+ v-show="tooltipEntry.length > 0"
426
491
  @click="removeTooltipEntry"
427
492
  size="small"
428
493
  >
429
494
  Remove Tooltip Entry
430
495
  </el-button>
431
496
  <el-button
432
- v-show="!Object.keys(tooltipEntry).length > 0"
497
+ v-show="tooltipEntry.length === 0"
433
498
  @click="addAnnotationEntry"
434
499
  size="small"
435
500
  >
@@ -449,10 +514,18 @@ function confirmCreate(value) {
449
514
  <h3>TreeControls - {{ mapType }}</h3>
450
515
  </el-col>
451
516
  <el-col>
452
- <el-button v-show="mapType==='scaffold'" @click="switchTreeEntry('flatmap')" size="small">
517
+ <el-button
518
+ v-show="mapType === 'scaffold'"
519
+ @click="switchTreeEntry('flatmap')"
520
+ size="small"
521
+ >
453
522
  Display Flatmap Tree
454
523
  </el-button>
455
- <el-button v-show="mapType==='flatmap'" @click="switchTreeEntry('scaffold')" size="small">
524
+ <el-button
525
+ v-show="mapType === 'flatmap'"
526
+ @click="switchTreeEntry('scaffold')"
527
+ size="small"
528
+ >
456
529
  Display Scaffold Tree
457
530
  </el-button>
458
531
  </el-col>
@@ -462,18 +535,34 @@ function confirmCreate(value) {
462
535
  <h3>Connectivity Graph</h3>
463
536
  </el-col>
464
537
  <el-col>
465
- <el-button
466
- @click="showConnectivityGraph = true"
467
- size="small"
468
- >
538
+ <el-button @click="showConnectivityGraph = true" size="small">
469
539
  Show connectivity graph
470
540
  </el-button>
471
- <el-button
472
- @click="showConnectivityGraph = false"
473
- size="small"
474
- >
541
+ <el-button @click="showConnectivityGraph = false" size="small">
475
542
  Hide connectivity graph
476
543
  </el-button>
544
+ <el-select
545
+ v-model="connectivityGraphEntry"
546
+ placeholder="Select featureId"
547
+ style="width: 180px"
548
+ size="small"
549
+ >
550
+ <el-option
551
+ v-for="item in connectivityGraphEntries"
552
+ :key="item"
553
+ :label="item"
554
+ :value="item"
555
+ />
556
+ </el-select>
557
+ </el-col>
558
+ <el-col>
559
+ <ConnectivityGraph
560
+ v-if="showConnectivityGraph"
561
+ :key="connectivityGraphEntry"
562
+ :entry="connectivityGraphEntry"
563
+ :map-server="mapServer"
564
+ :sckanVersion="sckanVersion"
565
+ />
477
566
  </el-col>
478
567
  </el-row>
479
568
 
@@ -545,12 +634,6 @@ function confirmCreate(value) {
545
634
  @setColour="setColour"
546
635
  @checkChanged="checkChanged"
547
636
  />
548
- <ConnectivityGraph
549
- v-if="showConnectivityGraph"
550
- :entry="connectivityGraphEntry"
551
- :map-server="mapServer"
552
- :sckanVersion="sckanVersion"
553
- />
554
637
  </div>
555
638
  </template>
556
639
 
@@ -568,9 +651,9 @@ function confirmCreate(value) {
568
651
  top: calc(50% - 100px);
569
652
  left: calc(50% - 200px);
570
653
  }
571
- .annotation-popup{
654
+ .annotation-popup {
572
655
  margin-top: 8px;
573
- width:400px;
656
+ width: 400px;
574
657
  border-style: solid;
575
658
  border-width: 1px;
576
659
  border-color: black;
@@ -584,4 +667,7 @@ function confirmCreate(value) {
584
667
  height: 600px;
585
668
  margin-top: 1rem;
586
669
  }
670
+ .el-button + .el-select {
671
+ margin-left: 12px;
672
+ }
587
673
  </style>
@@ -160,6 +160,10 @@ export default {
160
160
  type: Array,
161
161
  default: [],
162
162
  },
163
+ connectivityFromMap: {
164
+ type: Object,
165
+ default: () => null,
166
+ },
163
167
  },
164
168
  data: function () {
165
169
  return {
@@ -184,26 +188,20 @@ export default {
184
188
  connectivityGraphContainer: null,
185
189
  };
186
190
  },
191
+ watch: {
192
+ connectivityFromMap: function (oldVal, newVal) {
193
+ if (oldVal != newVal) {
194
+ this.showSpinner();
195
+ this.start();
196
+ }
197
+ }
198
+ },
187
199
  mounted() {
188
200
  this.showSpinner();
189
201
  this.updateTooltipContainer();
190
202
  this.refreshCache();
191
203
  this.loadCacheData();
192
- this.run()
193
- .then((res) => {
194
- if (res?.success) {
195
- this.showGraph(this.entry);
196
- } else if (res?.error) {
197
- this.loadingError = res.error;
198
- } else {
199
- this.loadingError = 'Loading error!';
200
- }
201
- this.hideSpinner();
202
- })
203
- .catch((error) => {
204
- this.loadingError = 'Loading error!';
205
- this.hideSpinner();
206
- });
204
+ this.start();
207
205
  },
208
206
  methods: {
209
207
  updateTooltipContainer: function () {
@@ -275,6 +273,22 @@ export default {
275
273
 
276
274
  sessionStorage.setItem('connectivity-graph-expiry', expiry);
277
275
  },
276
+ start: function () {
277
+ this.run()
278
+ .then((res) => {
279
+ if (res?.success) {
280
+ this.showGraph(this.entry);
281
+ } else if (res?.error) {
282
+ this.loadingError = res.error;
283
+ } else {
284
+ this.loadingError = 'Loading error!';
285
+ }
286
+ })
287
+ .catch((error) => {
288
+ this.loadingError = 'Loading error!';
289
+ this.hideSpinner();
290
+ });
291
+ },
278
292
  run: async function () {
279
293
  if (!this.schemaVersion) {
280
294
  this.schemaVersion = await this.getSchemaVersion();
@@ -305,8 +319,24 @@ export default {
305
319
  showGraph: async function (neuronPath) {
306
320
  const graphCanvas = this.$refs.graphCanvas;
307
321
 
322
+ // Update label data
323
+ if (this.connectivityFromMap) {
324
+ this.cacheLabels(this.connectivityFromMap);
325
+ await this.getCachedTermLabels();
326
+ }
327
+
308
328
  this.connectivityGraph = new ConnectivityGraph(this.labelCache, graphCanvas);
309
- await this.connectivityGraph.addConnectivity(this.knowledgeByPath.get(neuronPath));
329
+ const connectivityInfo = this.knowledgeByPath.get(neuronPath);
330
+
331
+ // Update connectivity
332
+ if (this.connectivityFromMap) {
333
+ connectivityInfo.axons = this.connectivityFromMap.axons;
334
+ connectivityInfo.connectivity = this.connectivityFromMap.connectivity;
335
+ connectivityInfo.dendrites = this.connectivityFromMap.dendrites;
336
+ connectivityInfo.somas = this.connectivityFromMap.somas;
337
+ }
338
+
339
+ await this.connectivityGraph.addConnectivity(connectivityInfo);
310
340
 
311
341
  this.connectivityGraph.showConnectivity(graphCanvas);
312
342
 
@@ -322,6 +352,8 @@ export default {
322
352
  */
323
353
  this.$emit('tap-node', data);
324
354
  });
355
+
356
+ this.hideSpinner();
325
357
  },
326
358
  query: async function (sql, params) {
327
359
  const url = `${this.mapServer}knowledge/query/`;
@@ -19,6 +19,8 @@ limitations under the License.
19
19
  ==============================================================================*/
20
20
 
21
21
  import cytoscape from 'cytoscape'
22
+ import dagre from 'cytoscape-dagre'
23
+ cytoscape.use( dagre );
22
24
 
23
25
  //==============================================================================
24
26
 
@@ -264,7 +266,7 @@ export class ConnectivityGraph extends EventTarget
264
266
  }
265
267
  } else if (this.dendrites.includes(id) || this.somas.includes(id)) {
266
268
  result['dendrite'] = true
267
-
269
+
268
270
  }
269
271
  }
270
272
  return result
@@ -406,11 +408,13 @@ class CytoscapeGraph extends EventTarget
406
408
  container: graphCanvas,
407
409
  elements: connectivityGraph.elements,
408
410
  layout: {
409
- name: 'breadthfirst',
410
- circle: false,
411
- roots: connectivityGraph.roots
411
+ name: 'dagre',
412
+ nodeSep: 150,
413
+ edgeSep: 50,
414
+ rankSep: 100,
415
+ rankDir: 'TB',
416
+ roots: connectivityGraph.roots.length ? connectivityGraph.roots : undefined,
412
417
  },
413
- directed: true,
414
418
  style: GRAPH_STYLE,
415
419
  minZoom: 0.1,
416
420
  maxZoom: 10,