@abi-software/flatmapvuer 1.8.1-beta.2 → 1.8.1-beta.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/flatmapvuer",
3
- "version": "1.8.1-beta.2",
3
+ "version": "1.8.1-beta.3",
4
4
  "license": "Apache-2.0",
5
5
  "files": [
6
6
  "dist/*",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@abi-software/flatmap-viewer": "3.2.13",
47
- "@abi-software/map-utilities": "^1.4.0",
47
+ "@abi-software/map-utilities": "^1.4.1-beta.1",
48
48
  "@abi-software/sparc-annotation": "0.3.2",
49
49
  "@abi-software/svg-sprite": "^1.0.1",
50
50
  "@element-plus/icons-vue": "^2.3.1",
@@ -1267,72 +1267,52 @@ export default {
1267
1267
  )
1268
1268
  }
1269
1269
  },
1270
- /**
1271
- * Function to highlight paths and features
1272
- * @param data
1273
- */
1274
- zoomToFeatures: function (data) {
1275
- if (this.mapImp) {
1276
- this.mapImp.zoomToFeatures(data)
1277
- }
1278
- },
1279
1270
  /**
1280
1271
  * @public
1281
1272
  * Function to highlight the connected paths
1282
- * by providing path model identifier, ``pathId`` or ``anatomicalId``.
1283
- * @arg {string} `pathId` or `anatomicalId`
1273
+ * by providing path model identifier, ``pathId``.
1274
+ * @arg {String} `pathId`
1284
1275
  */
1285
- retrieveConnectedPaths: async function (payload, options = {}) {
1276
+ highlightConnectedPaths: async function (payload) {
1286
1277
  if (this.mapImp) {
1287
- let connectedPaths = [];
1288
- let connectedTarget = options.target?.length ? options.target : [];
1278
+ let paths = [...this.mapImp.pathModelNodes(payload)]
1279
+
1289
1280
  // The line below is to get the path features from the geojson ids
1290
- const nodeFeatureIds = [...this.mapImp.pathModelNodes(payload)];
1291
- const pathsOfEntities = await this.mapImp.queryPathsForFeatures(payload);
1292
- if (nodeFeatureIds.length) {
1293
- if (!connectedTarget.length) {
1294
- const connectedType = options.type?.length ? options.type : ["all"];
1295
- const connectivity = await this.flatmapQueries.queryForConnectivityNew(this.mapImp, payload);
1296
- const originsFlat = connectivity?.ids?.dendrites.flat(Infinity);
1297
- const componentsFlat = connectivity?.ids?.components.flat(Infinity);
1298
- const destinationsFlat = connectivity?.ids?.axons.flat(Infinity);
1299
- let connected = [];
1300
- if (connectedType.includes("origins")) connected.push(...originsFlat);
1301
- if (connectedType.includes("components")) connected.push(...componentsFlat);
1302
- if (connectedType.includes("destinations")) connected.push(...destinationsFlat);
1303
- if (connectedType.includes("all")) connected.push(...originsFlat, ...componentsFlat, ...destinationsFlat);
1304
- connectedTarget = [...new Set(connected)];
1305
- }
1306
- // Loop through the node features and check if we have certain nodes
1307
- nodeFeatureIds.forEach((featureId) => {
1308
- // Get the paths from each node feature
1309
- const pathsL2 = this.mapImp.nodePathModels(featureId);
1310
- pathsL2.forEach((path) => {
1311
- // nodes of the second level path
1312
- const nodeFeatureIdsL2 = this.mapImp.pathModelNodes(path);
1313
- const nodeModelsL2 = nodeFeatureIdsL2.map((featureIdL2) => {
1314
- return this.mapImp.featureProperties(featureIdL2).models;
1315
- });
1316
- const intersection = connectedTarget.filter(element => nodeModelsL2.includes(element));
1317
- if (intersection.length && !connectedPaths.includes(path)) connectedPaths.push(path);
1318
- });
1319
- });
1320
- } else if (pathsOfEntities.length) {
1321
- if (connectedTarget.length) {
1322
- pathsOfEntities.forEach((path) => {
1323
- const nodeFeatureIds = this.mapImp.pathModelNodes(path);
1324
- const nodeModels = nodeFeatureIds.map((featureId) => {
1325
- return this.mapImp.featureProperties(featureId).models;
1326
- });
1327
- const intersection = connectedTarget.filter(element => nodeModels.includes(element));
1328
- if (intersection.length && !connectedPaths.includes(path)) connectedPaths.push(path);
1329
- });
1330
- } else {
1331
- connectedPaths = pathsOfEntities;
1332
- }
1333
- }
1334
- connectedPaths = [...new Set([...connectedPaths, ...payload])];
1335
- return connectedPaths;
1281
+ let pathFeatures = paths.map((p) => this.mapImp.featureProperties(p))
1282
+
1283
+ // Query the flatmap knowledge graph for connectivity, we use this to grab the origins
1284
+ let connectivity = await this.flatmapQueries.queryForConnectivityNew(this.mapImp, payload)
1285
+
1286
+ // Check and flatten the origins node graph
1287
+ let originsFlat = connectivity?.ids?.dendrites?.flat().flat()
1288
+
1289
+ let toHighlight = []
1290
+ let highlight = false
1291
+
1292
+ // Loop through the path features and check if we have origin nodes
1293
+ pathFeatures.forEach((p) => {
1294
+
1295
+ // Get the nodes from each path feature
1296
+ this.mapImp.nodePathModels(p.featureId).forEach((f) => {
1297
+ highlight = true
1298
+ // s2 here is the second level paths
1299
+ let s2 = this.mapImp.pathModelNodes(f)
1300
+ s2.forEach((s) => {
1301
+ let s2Feature = this.mapImp.featureProperties([s]) // get the feature properties for s2
1302
+ if (originsFlat.includes(s2Feature.models)) {
1303
+ highlight = false // if we have an origin node, we don't want to highlight the path
1304
+ return
1305
+ }
1306
+ })
1307
+
1308
+ if (highlight) {
1309
+ toHighlight.push(f)
1310
+ }
1311
+ })
1312
+ })
1313
+
1314
+ // display connected paths
1315
+ this.mapImp.zoomToFeatures(toHighlight, { noZoomIn: true })
1336
1316
  }
1337
1317
  },
1338
1318
  resetMapFilter: function() {
@@ -1663,11 +1643,13 @@ export default {
1663
1643
  provenanceTaxonomy: taxons,
1664
1644
  }
1665
1645
  if (eventType === 'click') {
1646
+ this.setConnectivityDataSource(this.viewingMode, data);
1666
1647
  this.featuresAlert = data.alert
1648
+ //The following will be used to track either a feature is selected
1649
+ this.statesTracking.activeClick = true
1650
+ this.statesTracking.activeTerm = data?.models
1667
1651
  if (this.viewingMode === 'Neuron Connection') {
1668
- this.retrieveConnectedPaths([data.models]).then((paths) => {
1669
- this.zoomToFeatures(paths)
1670
- })
1652
+ this.highlightConnectedPaths([data.models])
1671
1653
  } else {
1672
1654
  this.currentActive = data.models ? data.models : ''
1673
1655
  // Drawing connectivity between features
@@ -1712,6 +1694,23 @@ export default {
1712
1694
  }
1713
1695
  }
1714
1696
  },
1697
+ /**
1698
+ * The data for connectivity data source is just a placeholder data
1699
+ * to check which part of the map is clicked, e.g., path or feture or empty area,
1700
+ * based on the viewing mode.
1701
+ * The "connectivity-info-close" event will be emitted based on this data
1702
+ * when there has a click event on map.
1703
+ * @param viewingMode
1704
+ * @param data
1705
+ */
1706
+ setConnectivityDataSource: function (viewingMode, data) {
1707
+ // for Exploration mode, only path click will be used as data source
1708
+ this.connectivityDataSource = data.source;
1709
+ // for other modes, it can be feature or path
1710
+ if (viewingMode === 'Neuron Connection' || viewingMode === 'Annotation') {
1711
+ this.connectivityDataSource = data.featureId;
1712
+ }
1713
+ },
1715
1714
  /**
1716
1715
  * @public
1717
1716
  * Function triggered by viewing mode change.
@@ -1939,8 +1938,6 @@ export default {
1939
1938
  this.resourceForTooltip = data.resource[0]
1940
1939
  data.resourceForTooltip = this.resourceForTooltip
1941
1940
  this.createTooltipFromNeuronCuration(data)
1942
- } else {
1943
- this.createTooltipFromEntityCuration(data)
1944
1941
  }
1945
1942
  }
1946
1943
  },
@@ -1984,41 +1981,6 @@ export default {
1984
1981
  this.tooltipEntry = await this.flatmapQueries.createTooltipData(this.mapImp, data)
1985
1982
  this.displayTooltip(data.resource[0])
1986
1983
  },
1987
- /**
1988
- * @public
1989
- * Function to create tooltip from Entity Curation ``data``.
1990
- * @arg {Object} `data`
1991
- */
1992
- createTooltipFromEntityCuration: async function (data) {
1993
- this.tooltipEntry = await this.flatmapQueries.createTooltipData(this.mapImp, data)
1994
- let featureIds = []
1995
- let destinations = []
1996
- let destinationsWithDatasets = []
1997
- const pathsOfEntities = await this.mapImp.queryPathsForFeatures(data.resource)
1998
- if (pathsOfEntities.length) {
1999
- pathsOfEntities.forEach((path) => {
2000
- featureIds.push(...this.mapImp.pathModelNodes(path))
2001
- })
2002
- featureIds = [...new Set(featureIds)].filter(id => id !== data.feature.featureId)
2003
- featureIds.forEach((id) => {
2004
- const feature = this.mapImp.featureProperties(id)
2005
- if (!destinations.includes(feature.label)) {
2006
- destinations.push(feature.label)
2007
- destinationsWithDatasets.push({ id: feature.models, name: feature.label })
2008
- }
2009
- })
2010
- this.tooltipEntry = {
2011
- ...this.tooltipEntry,
2012
- origins: [data.label],
2013
- originsWithDatasets: [{ id: data.resource[0], name: data.label }],
2014
- components: [],
2015
- componentsWithDatasets: [],
2016
- destinations: destinations,
2017
- destinationsWithDatasets: destinationsWithDatasets,
2018
- }
2019
- this.displayTooltip(data.resource[0])
2020
- }
2021
- },
2022
1984
  /**
2023
1985
  * @public
2024
1986
  * Function to show popup on map.
@@ -2241,6 +2203,10 @@ export default {
2241
2203
  // Get connectivity knowledge source | SCKAN release
2242
2204
  if (this.mapImp.provenance?.connectivity) {
2243
2205
  this.tooltipEntry['knowledge-source'] = getKnowledgeSource(this.mapImp);
2206
+
2207
+ // Map id and uuid to load connectivity information from the map
2208
+ this.tooltipEntry['mapId'] = this.mapImp.provenance.id;
2209
+ this.tooltipEntry['mapuuid'] = this.mapImp.provenance.uuid;
2244
2210
  }
2245
2211
  this.$emit('connectivity-info-open', this.tooltipEntry);
2246
2212
  }
@@ -2423,10 +2389,10 @@ export default {
2423
2389
  state['biologicalSex'] = identifier.biologicalSex
2424
2390
  if (identifier && identifier.uuid) state['uuid'] = identifier.uuid
2425
2391
  state['viewingMode'] = this.viewingMode
2426
- state['searchTerm'] = this.searchTerm
2392
+ state['searchTerm'] = this.statesTracking.activeTerm
2427
2393
  state['flightPath3D'] = this.flightPath3DRadio
2428
2394
  state['colour'] = this.colourRadio
2429
- state['outlines'] = this.outlinesRadio
2395
+ state['outlinesRadio'] = this.outlinesRadio
2430
2396
  state['background'] = this.currentBackground
2431
2397
  this.getVisibilityState(state)
2432
2398
  return state
@@ -2471,9 +2437,7 @@ export default {
2471
2437
  if (state.searchTerm) {
2472
2438
  const searchTerm = state.searchTerm
2473
2439
  if (state.viewingMode === "Neuron Connection") {
2474
- this.retrieveConnectedPaths([searchTerm]).then((paths) => {
2475
- this.zoomToFeatures(paths)
2476
- })
2440
+ this.highlightConnectedPaths([searchTerm])
2477
2441
  } else {
2478
2442
  this.searchAndShowResult(searchTerm, true)
2479
2443
  }
@@ -2626,6 +2590,7 @@ export default {
2626
2590
  if (this.mapImp.options?.style === 'functional') {
2627
2591
  this.isFC = true
2628
2592
  }
2593
+ console.log(this.mapImp)
2629
2594
  this.mapImp.setBackgroundOpacity(1)
2630
2595
  this.backgroundChangeCallback(this.currentBackground)
2631
2596
  this.pathways = this.mapImp.pathTypes()
@@ -2639,6 +2604,7 @@ export default {
2639
2604
  this.loading = false
2640
2605
  this.computePathControlsMaximumHeight()
2641
2606
  this.mapResize()
2607
+ this.handleMapClick();
2642
2608
  this.setInitMapState();
2643
2609
  /**
2644
2610
  * This is ``onFlatmapReady`` event.
@@ -2646,6 +2612,29 @@ export default {
2646
2612
  */
2647
2613
  this.$emit('ready', this)
2648
2614
  },
2615
+ /**
2616
+ * @public
2617
+ * Function to handle mouse click on map area
2618
+ * after the map is loaded.
2619
+ */
2620
+ handleMapClick: function () {
2621
+ const _map = this.mapImp._map;
2622
+ if (_map) {
2623
+ _map.on('click', (e) => {
2624
+ //A little logic to make sure we are keeping track
2625
+ //of selected term
2626
+ if (this.statesTracking.activeClick) {
2627
+ this.statesTracking.activeClick = false
2628
+ } else {
2629
+ this.statesTracking.activeTerm = ""
2630
+ }
2631
+ if (!this.connectivityDataSource) {
2632
+ this.$emit('connectivity-info-close');
2633
+ }
2634
+ this.connectivityDataSource = ''; // reset
2635
+ });
2636
+ }
2637
+ },
2649
2638
  /**
2650
2639
  * @public
2651
2640
  * Function to show or hide the minimap
@@ -2680,11 +2669,12 @@ export default {
2680
2669
  } else if (this.viewingMode === "Annotation") {
2681
2670
  this.manualAbortedOnClose()
2682
2671
  }
2683
- this.searchTerm = ""
2672
+ this.statesTracking.activeTerm = ""
2684
2673
  return true
2685
2674
  } else {
2686
2675
  const searchResults = this.mapImp.search(term)
2687
2676
  if (searchResults?.results?.length) {
2677
+ this.statesTracking.activeTerm = term
2688
2678
  this.mapImp.showSearchResults(searchResults)
2689
2679
  if (displayInfo) {
2690
2680
  let featureId = undefined;
@@ -2704,9 +2694,9 @@ export default {
2704
2694
  if (this.viewingMode === "Exploration" || this.viewingMode === "Annotation") {
2705
2695
  this.checkAndCreatePopups(data)
2706
2696
  } else if (this.viewingMode === 'Neuron Connection') {
2707
- this.retrieveConnectedPaths(data.resource).then((paths) => {
2708
- this.zoomToFeatures(paths)
2709
- })
2697
+ setTimeout(() => {
2698
+ this.highlightConnectedPaths(data.resource)
2699
+ }, 1000)
2710
2700
  }
2711
2701
  this.mapImp.showPopup(featureId, capitalise(feature.label), {
2712
2702
  className: 'custom-popup',
@@ -2715,7 +2705,6 @@ export default {
2715
2705
  })
2716
2706
  }
2717
2707
  }
2718
- this.searchTerm = term
2719
2708
  return true
2720
2709
  } else this.mapImp.clearSearchResults()
2721
2710
  }
@@ -3053,7 +3042,10 @@ export default {
3053
3042
  without: true,
3054
3043
  }
3055
3044
  }),
3056
- searchTerm: "",
3045
+ statesTracking: markRaw({
3046
+ activeClick: false,
3047
+ activeTerm: "",
3048
+ }),
3057
3049
  taxonLeaveDelay: undefined,
3058
3050
  }
3059
3051
  },
@@ -36,29 +36,25 @@ function getKnowledgeSource(mapImp) {
36
36
  mapKnowledgeSource = `${sckanProvenance.npo.release}-npo`;
37
37
  }
38
38
  }
39
+
39
40
  return mapKnowledgeSource;
40
41
  }
41
42
 
42
- async function loadAndStoreKnowledge(mapImp, flatmapQueries) {
43
+ function loadAndStoreKnowledge(mapImp, flatmapQueries) {
43
44
  const knowledgeSource = getKnowledgeSource(mapImp);
44
45
  const sql = `select knowledge from knowledge
45
- where source="${knowledgeSource}"
46
- order by source desc`;
47
-
48
- refreshFlatmapKnowledgeCache()
46
+ where source="${knowledgeSource}"
47
+ order by source desc`;
49
48
  const flatmapKnowledge = sessionStorage.getItem('flatmap-knowledge');
50
49
 
51
50
  if (!flatmapKnowledge) {
52
- const response = await flatmapQueries.flatmapQuery(sql);
53
- const mappedData = response.values.map(x => x[0]);
54
- const parsedData = mappedData.map(x => JSON.parse(x));
55
-
56
- sessionStorage.setItem('flatmap-knowledge', JSON.stringify(parsedData));
57
- updateFlatmapKnowledgeCache();
58
-
59
- return parsedData;
51
+ flatmapQueries.flatmapQuery(sql).then((response) => {
52
+ const mappedData = response.values.map(x => x[0]);
53
+ const parsedData = mappedData.map(x => JSON.parse(x));
54
+ sessionStorage.setItem('flatmap-knowledge', JSON.stringify(parsedData));
55
+ updateFlatmapKnowledgeCache();
56
+ });
60
57
  }
61
- return JSON.parse(flatmapKnowledge);
62
58
  }
63
59
 
64
60
  function updateFlatmapKnowledgeCache() {
@@ -74,7 +70,6 @@ function removeFlatmapKnowledgeCache() {
74
70
  'flatmap-knowledge',
75
71
  'flatmap-knowledge-expiry',
76
72
  ];
77
-
78
73
  keys.forEach((key) => {
79
74
  sessionStorage.removeItem(key);
80
75
  });