@abi-software/map-utilities 1.4.1-beta.1 → 1.4.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.4.1-beta.1",
3
+ "version": "1.4.2",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
@@ -30,11 +30,6 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@abi-software/svg-sprite": "^1.0.1",
33
- "@citation-js/core": "^0.7.14",
34
- "@citation-js/plugin-bibtex": "^0.7.17",
35
- "@citation-js/plugin-csl": "^0.7.14",
36
- "@citation-js/plugin-doi": "^0.7.16",
37
- "@citation-js/plugin-pubmed": "^0.3.0",
38
33
  "@element-plus/icons-vue": "^2.3.1",
39
34
  "cytoscape": "^3.30.2",
40
35
  "element-plus": "2.8.4",
@@ -160,10 +160,6 @@ export default {
160
160
  type: Array,
161
161
  default: [],
162
162
  },
163
- connectivityFromMap: {
164
- type: Object,
165
- default: () => null,
166
- },
167
163
  },
168
164
  data: function () {
169
165
  return {
@@ -188,19 +184,26 @@ export default {
188
184
  connectivityGraphContainer: null,
189
185
  };
190
186
  },
191
- watch: {
192
- connectivityFromMap: function (oldVal, newVal) {
193
- if (oldVal != newVal) {
194
- this.start();
195
- }
196
- }
197
- },
198
187
  mounted() {
199
188
  this.showSpinner();
200
189
  this.updateTooltipContainer();
201
190
  this.refreshCache();
202
191
  this.loadCacheData();
203
- this.start();
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
207
  },
205
208
  methods: {
206
209
  updateTooltipContainer: function () {
@@ -272,23 +275,6 @@ export default {
272
275
 
273
276
  sessionStorage.setItem('connectivity-graph-expiry', expiry);
274
277
  },
275
- start: function () {
276
- this.run()
277
- .then((res) => {
278
- if (res?.success) {
279
- this.showGraph(this.entry);
280
- } else if (res?.error) {
281
- this.loadingError = res.error;
282
- } else {
283
- this.loadingError = 'Loading error!';
284
- }
285
- this.hideSpinner();
286
- })
287
- .catch((error) => {
288
- this.loadingError = 'Loading error!';
289
- this.hideSpinner();
290
- });
291
- },
292
278
  run: async function () {
293
279
  if (!this.schemaVersion) {
294
280
  this.schemaVersion = await this.getSchemaVersion();
@@ -319,24 +305,8 @@ export default {
319
305
  showGraph: async function (neuronPath) {
320
306
  const graphCanvas = this.$refs.graphCanvas;
321
307
 
322
- // Update label data
323
- if (this.connectivityFromMap) {
324
- this.cacheLabels(this.connectivityFromMap);
325
- await this.getCachedTermLabels();
326
- }
327
-
328
308
  this.connectivityGraph = new ConnectivityGraph(this.labelCache, graphCanvas);
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);
309
+ await this.connectivityGraph.addConnectivity(this.knowledgeByPath.get(neuronPath));
340
310
 
341
311
  this.connectivityGraph.showConnectivity(graphCanvas);
342
312
 
@@ -25,6 +25,43 @@ import cytoscape from 'cytoscape'
25
25
 
26
26
  //==============================================================================
27
27
 
28
+ const inArray = function (ar1, ar2) {
29
+ if (!ar1 || !ar2) return false
30
+ let as1 = JSON.stringify(ar1)
31
+ let as2 = JSON.stringify(ar2)
32
+ return as1.indexOf(as2) !== -1
33
+ }
34
+
35
+ const removeDuplicates = function (arrayOfAnything) {
36
+ if (!arrayOfAnything) return []
37
+ return [...new Set(arrayOfAnything.map((e) => JSON.stringify(e)))].map((e) =>
38
+ JSON.parse(e)
39
+ )
40
+ }
41
+
42
+ const findComponents = function (knowledge, axons, dendrites) {
43
+ let dnodes = knowledge.connectivity.flat() // get nodes from edgelist
44
+ let nodes = removeDuplicates(dnodes)
45
+
46
+ let found = []
47
+ let terminal = false
48
+ nodes.forEach((node) => {
49
+ terminal = false
50
+ // Check if the node is an destination or origin (note that they are labelled dendrite and axon as opposed to origin and destination)
51
+ if (inArray(axons, node)) {
52
+ terminal = true
53
+ }
54
+ if (inArray(dendrites, node)) {
55
+ terminal = true
56
+ }
57
+ if (!terminal) {
58
+ found.push(node)
59
+ }
60
+ })
61
+
62
+ return found
63
+ }
64
+
28
65
  export class ConnectivityGraph extends EventTarget
29
66
  {
30
67
  cyg = null
@@ -35,6 +72,7 @@ export class ConnectivityGraph extends EventTarget
35
72
  somas = []
36
73
  labelCache = new Map()
37
74
  graphCanvas = null
75
+ hasPhenotypes = false
38
76
 
39
77
  constructor(labelCache, graphCanvas)
40
78
  {
@@ -46,10 +84,32 @@ export class ConnectivityGraph extends EventTarget
46
84
  async addConnectivity(knowledge)
47
85
  //=====================================================
48
86
  {
49
- this.axons = knowledge.axons.map(node => JSON.stringify(node))
50
- this.dendrites = knowledge.dendrites.map(node => JSON.stringify(node))
51
- if (knowledge.somas?.length) {
52
- this.somas = knowledge.somas.map(node => JSON.stringify(node))
87
+ if (knowledge && knowledge["node-phenotypes"]) {
88
+ const sourceKey = ["ilxtr:hasSomaLocatedIn"]
89
+ const destinationKey = ["ilxtr:hasAxonPresynapticElementIn", "ilxtr:hasAxonSensorySubcellularElementIn"]
90
+
91
+ const source = []
92
+ const destination = []
93
+ sourceKey.forEach((key)=>{
94
+ source.push(...knowledge["node-phenotypes"][key])
95
+ })
96
+ destinationKey.forEach((key)=>{
97
+ destination.push(...knowledge["node-phenotypes"][key])
98
+ })
99
+ const via = findComponents(knowledge, source, destination)
100
+ this.dendrites = source.map(node => JSON.stringify(node))
101
+ this.axons = destination.map(node => JSON.stringify(node))
102
+ if (via?.length) {
103
+ this.somas = via.map(node => JSON.stringify(node))
104
+ }
105
+ this.hasPhenotypes = true
106
+ } else {
107
+ this.axons = knowledge.axons.map(node => JSON.stringify(node))
108
+ this.dendrites = knowledge.dendrites.map(node => JSON.stringify(node))
109
+ if (knowledge.somas?.length) {
110
+ this.somas = knowledge.somas.map(node => JSON.stringify(node))
111
+ }
112
+ this.hasPhenotypes = false
53
113
  }
54
114
  if (knowledge.connectivity.length) {
55
115
  for (const edge of knowledge.connectivity) {
@@ -158,10 +218,17 @@ export class ConnectivityGraph extends EventTarget
158
218
  get roots()
159
219
  //===================
160
220
  {
161
- return [
162
- ...this.dendrites,
163
- ...this.somas
164
- ]
221
+ if (this.hasPhenotypes) {
222
+ return [
223
+ ...this.dendrites,
224
+ ]
225
+ } else {
226
+ return [
227
+ ...this.dendrites,
228
+ ...this.somas
229
+ ]
230
+ }
231
+
165
232
  }
166
233
 
167
234
  async graphNode(node)
@@ -180,15 +247,25 @@ export class ConnectivityGraph extends EventTarget
180
247
  id,
181
248
  label: label.join('\n')
182
249
  }
183
- if (this.axons.includes(id)) {
184
- if (this.dendrites.includes(id) || this.somas.includes(id)) {
185
- result['both-a-d'] = true
186
- } else {
250
+ if (this.hasPhenotypes) {
251
+ if (this.axons.includes(id)) {
187
252
  result['axon'] = true
253
+ } else if (this.dendrites.includes(id)) {
254
+ result['dendrite'] = true
255
+ } else {
256
+ result['somas'] = true
257
+ }
258
+ } else {
259
+ if (this.axons.includes(id)) {
260
+ if (this.dendrites.includes(id) || this.somas.includes(id)) {
261
+ result['somas'] = true
262
+ } else {
263
+ result['axon'] = true
264
+ }
265
+ } else if (this.dendrites.includes(id) || this.somas.includes(id)) {
266
+ result['dendrite'] = true
267
+
188
268
  }
189
- } else if (this.dendrites.includes(id) || this.somas.includes(id)) {
190
- result['dendrite'] = true
191
-
192
269
  }
193
270
  return result
194
271
  }
@@ -241,7 +318,7 @@ const GRAPH_STYLE = [
241
318
  }
242
319
  },
243
320
  {
244
- 'selector': 'node[both-a-d]',
321
+ 'selector': 'node[somas]',
245
322
  'style': {
246
323
  // 'background-color': 'gray',
247
324
  'shape': 'round-rectangle',
@@ -6,7 +6,7 @@
6
6
  <CopyToClipboard label="Copy list to clipboard" :content="referecesListContent" />
7
7
  </div>
8
8
  </div>
9
- <div class="citation-tabs" v-if="useDOIFormatter ? referencesWithDOI : pubMedReferences.length">
9
+ <div class="citation-tabs" v-if="referencesWithDOI">
10
10
  <el-button
11
11
  link
12
12
  v-for="citationOption of citationOptions"
@@ -102,7 +102,7 @@
102
102
 
103
103
  <script>
104
104
  import CopyToClipboard from '../CopyToClipboard/CopyToClipboard.vue';
105
- import { delay, getCitationById } from '../utilities';
105
+ import { delay } from '../utilities';
106
106
 
107
107
  const CROSSCITE_API_HOST = 'https://citation.doi.org';
108
108
  const CITATION_OPTIONS = [
@@ -128,18 +128,11 @@ const LOADING_DELAY = 600;
128
128
 
129
129
  export default {
130
130
  name: "ExternalResourceCard",
131
- components: {
132
- CopyToClipboard,
133
- },
134
131
  props: {
135
132
  resources: {
136
133
  type: Array,
137
134
  default: () => [],
138
135
  },
139
- useDOIFormatter: {
140
- type: Boolean,
141
- default: true,
142
- }
143
136
  },
144
137
  data: function () {
145
138
  return {
@@ -345,14 +338,7 @@ export default {
345
338
 
346
339
  if (type === 'doi' || doi) {
347
340
  const doiID = type === 'doi' ? id : doi;
348
- const fetchCitationFromAPI = this.useDOIFormatter ?
349
- this.getCitationTextByDOI(doiID) :
350
- getCitationById(doiID, {
351
- type: 'doi',
352
- format: citationType
353
- });
354
-
355
- fetchCitationFromAPI.then((text) => {
341
+ this.getCitationTextByDOI(doiID).then((text) => {
356
342
  const formattedText = this.replaceLinkInText(text);
357
343
  reference.citation[citationType] = formattedText;
358
344
  this.updateCopyContents();
@@ -363,61 +349,45 @@ export default {
363
349
  };
364
350
  });
365
351
  } else if (type === 'pmid') {
366
- if (this.useDOIFormatter) {
367
- this.getDOIFromPubMedID(id).then((data) => {
368
- if (data?.result) {
369
- const resultObj = data.result[id];
370
- const articleIDs = resultObj?.articleids || [];
371
- const doiObj = articleIDs.find((item) => item.idtype === 'doi');
372
- const doiID = doiObj?.value;
373
-
374
- if (doiID) {
375
- reference['doi'] = doiID;
376
- this.getCitationTextByDOI(doiID).then((text) => {
377
- const formattedText = this.replaceLinkInText(text);
378
- reference.citation[citationType] = formattedText;
379
- this.updateCopyContents();
380
- }).catch((error) => {
381
- reference.citation['error'] = {
382
- type: citationType,
383
- ref: 'doi',
384
- };
385
- });
386
- } else {
387
- // If there has no doi in PubMed
388
- const { title, pubdate, authors } = resultObj;
389
- const authorNames = authors ? authors.map((author) => author.name) : [];
390
- const formattedText = this.formatCopyReference({
391
- title: title || '',
392
- date: pubdate || '',
393
- authors: authorNames,
394
- url: `https://pubmed.ncbi.nlm.nih.gov/${id}`,
395
- });
352
+ this.getDOIFromPubMedID(id).then((data) => {
353
+ if (data?.result) {
354
+ const resultObj = data.result[id];
355
+ const articleIDs = resultObj?.articleids || [];
356
+ const doiObj = articleIDs.find((item) => item.idtype === 'doi');
357
+ const doiID = doiObj?.value;
358
+
359
+ if (doiID) {
360
+ reference['doi'] = doiID;
361
+ this.getCitationTextByDOI(doiID).then((text) => {
362
+ const formattedText = this.replaceLinkInText(text);
396
363
  reference.citation[citationType] = formattedText;
397
364
  this.updateCopyContents();
398
- }
365
+ }).catch((error) => {
366
+ reference.citation['error'] = {
367
+ type: citationType,
368
+ ref: 'doi',
369
+ };
370
+ });
371
+ } else {
372
+ // If there has no doi in PubMed
373
+ const { title, pubdate, authors } = resultObj;
374
+ const authorNames = authors ? authors.map((author) => author.name) : [];
375
+ const formattedText = this.formatCopyReference({
376
+ title: title || '',
377
+ date: pubdate || '',
378
+ authors: authorNames,
379
+ url: `https://pubmed.ncbi.nlm.nih.gov/${id}`,
380
+ });
381
+ reference.citation[citationType] = formattedText;
382
+ this.updateCopyContents();
399
383
  }
400
- }).catch((error) => {
401
- reference.citation['error'] = {
402
- type: citationType,
403
- ref: 'pubmed',
404
- };
405
- });
406
- } else {
407
- getCitationById(id, {
408
- type: 'pmid',
409
- format: citationType
410
- }).then((text) => {
411
- const formattedText = this.replaceLinkInText(text);
412
- reference.citation[citationType] = formattedText;
413
- this.updateCopyContents();
414
- }).catch((error) => {
415
- reference.citation['error'] = {
416
- type: citationType,
417
- ref: 'pubmed',
418
- };
419
- });
420
- }
384
+ }
385
+ }).catch((error) => {
386
+ reference.citation['error'] = {
387
+ type: citationType,
388
+ ref: 'pubmed',
389
+ };
390
+ });
421
391
  }
422
392
  }
423
393
  },
@@ -171,11 +171,6 @@
171
171
  </template>
172
172
 
173
173
  <script>
174
- import {
175
- ArrowUp as ElIconArrowUp,
176
- ArrowDown as ElIconArrowDown,
177
- Warning as ElIconWarning,
178
- } from '@element-plus/icons-vue'
179
174
  import EventBus from "../EventBus.js";
180
175
 
181
176
  const titleCase = (str) => {
@@ -191,11 +186,6 @@ const capitalise = function (str) {
191
186
 
192
187
  export default {
193
188
  name: "ProvenancePopup",
194
- components: {
195
- ElIconArrowUp,
196
- ElIconArrowDown,
197
- ElIconWarning,
198
- },
199
189
  props: {
200
190
  tooltipEntry: {
201
191
  type: Object,
@@ -1,7 +1,6 @@
1
1
  import AnnotationPopup from "./Tooltip/AnnotationPopup.vue";
2
2
  import CreateTooltipContent from "./Tooltip/CreateTooltipContent.vue";
3
3
  import ConnectivityGraph from "./ConnectivityGraph/ConnectivityGraph.vue";
4
- import ConnectivityList from "./ConnectivityList/ConnectivityList.vue";
5
4
  import CopyToClipboard from "./CopyToClipboard/CopyToClipboard.vue";
6
5
  import DrawToolbar from "./DrawToolbar/DrawToolbar.vue";
7
6
  import HelpModeDialog from "./HelpModeDialog/HelpModeDialog.vue";
@@ -13,7 +12,6 @@ export {
13
12
  AnnotationPopup,
14
13
  CreateTooltipContent,
15
14
  ConnectivityGraph,
16
- ConnectivityList,
17
15
  CopyToClipboard,
18
16
  DrawToolbar,
19
17
  HelpModeDialog,
@@ -1,9 +1,3 @@
1
- import { Cite, plugins } from '@citation-js/core';
2
- import '@citation-js/plugin-doi';
3
- import '@citation-js/plugin-csl';
4
- import '@citation-js/plugin-bibtex';
5
- import '@citation-js/plugin-pubmed';
6
-
7
1
  const capitalise = term => {
8
2
  if (term)
9
3
  return term.charAt(0).toUpperCase() + term.slice(1);
@@ -54,42 +48,8 @@ const delay = (ms) => {
54
48
  return new Promise(resolve => setTimeout(resolve, ms));
55
49
  };
56
50
 
57
- /**
58
- * @param {id} id - DOI or PMID
59
- * @param {options:type} type - type of the ID, e.g., 'pmid'
60
- * @param {options:format} format - 'apa' (default), 'chicago', 'ieee', 'bibtex', etc.
61
- * @returns {citation} formatted citation text
62
- */
63
- const getCitationById = async (id, { type, format }) => {
64
- // because 'chicago' and 'ieee' are not in citation.js default styles
65
- if ((format !== 'bibtex') && (format !== 'apa')) {
66
- const xml = `https://raw.githubusercontent.com/citation-style-language/styles/refs/heads/master/${format}.csl`;
67
- const response = await fetch(xml);
68
- const template = await response.text();
69
- let config = plugins.config.get('@csl');
70
- config.templates.add(format, template);
71
- }
72
-
73
- const option = {};
74
-
75
- if (type === 'pmid') {
76
- option['forceType'] = '@pubmed/id';
77
- }
78
-
79
- const cite = await Cite.async(id, option);
80
- const citation = (format === 'bibtex') ?
81
- cite.format(format) :
82
- cite.format('bibliography', {
83
- format: 'html',
84
- template: format || 'apa', // default as 'apa' style
85
- lang: 'en-US'
86
- })
87
- return citation;
88
- };
89
-
90
51
  export {
91
52
  capitalise,
92
53
  xmlToJSON,
93
54
  delay,
94
- getCitationById,
95
55
  };
@@ -10,7 +10,6 @@ declare module 'vue' {
10
10
  AnnotationPopup: typeof import('./components/Tooltip/AnnotationPopup.vue')['default']
11
11
  ConnectionDialog: typeof import('./components/DrawToolbar/ConnectionDialog.vue')['default']
12
12
  ConnectivityGraph: typeof import('./components/ConnectivityGraph/ConnectivityGraph.vue')['default']
13
- ConnectivityList: typeof import('./components/ConnectivityList/ConnectivityList.vue')['default']
14
13
  CopyToClipboard: typeof import('./components/CopyToClipboard/CopyToClipboard.vue')['default']
15
14
  CreateTooltipContent: typeof import('./components/Tooltip/CreateTooltipContent.vue')['default']
16
15
  DrawToolbar: typeof import('./components/DrawToolbar/DrawToolbar.vue')['default']