@abi-software/scaffoldvuer 1.10.0-beta.1 → 1.11.0-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/dist/scaffoldvuer.js +11231 -10324
- package/dist/scaffoldvuer.umd.cjs +167 -167
- package/dist/style.css +1 -1
- package/mapped_fma_nerves.json +10914 -0
- package/nerve_mapping.js +10917 -0
- package/package.json +3 -3
- package/src/components/ScaffoldTooltip.vue +1 -1
- package/src/components/ScaffoldTreeControls.vue +37 -3
- package/src/components/ScaffoldVuer.vue +156 -25
- package/src/scripts/MappedNerves.js +901 -0
- package/src/scripts/RendererModule.js +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abi-software/scaffoldvuer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"*.js"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@abi-software/map-utilities": "^1.6.0
|
|
44
|
+
"@abi-software/map-utilities": "^1.6.0",
|
|
45
45
|
"@abi-software/sparc-annotation": "^0.3.2",
|
|
46
46
|
"@abi-software/svg-sprite": "^1.0.1",
|
|
47
47
|
"@element-plus/icons-vue": "^2.3.1",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vue": "^3.4.21",
|
|
55
55
|
"vue-router": "^4.2.5",
|
|
56
56
|
"vue3-component-svg-sprite": "^0.0.1",
|
|
57
|
-
"zincjs": "^1.14.
|
|
57
|
+
"zincjs": "^1.14.3"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@vitejs/plugin-vue": "^4.6.2",
|
|
@@ -77,6 +77,7 @@ export default {
|
|
|
77
77
|
drawerOpen: true,
|
|
78
78
|
nodeNumbers: 0,
|
|
79
79
|
module: undefined,
|
|
80
|
+
//checkedRegions: [],
|
|
80
81
|
};
|
|
81
82
|
},
|
|
82
83
|
computed: {
|
|
@@ -91,9 +92,21 @@ export default {
|
|
|
91
92
|
if (this.isReady) {
|
|
92
93
|
// Updated colour when scaffold is ready
|
|
93
94
|
this.setColourField(data);
|
|
95
|
+
// _helper is unchecked by default
|
|
96
|
+
//this.checkedRegions = data.filter(region => region.label !== '_helper');
|
|
94
97
|
}
|
|
95
98
|
},
|
|
96
99
|
},
|
|
100
|
+
/*
|
|
101
|
+
checkedRegions: {
|
|
102
|
+
deep: true,
|
|
103
|
+
handler: function (data) {
|
|
104
|
+
if (this.isReady) {
|
|
105
|
+
this.$emit('checked-regions', data);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
*/
|
|
97
110
|
},
|
|
98
111
|
methods: {
|
|
99
112
|
addTreeItem: function (parentContainer, item, object) {
|
|
@@ -221,7 +234,13 @@ export default {
|
|
|
221
234
|
.getRootRegion()
|
|
222
235
|
.findChildFromPath(node.regionPath);
|
|
223
236
|
if (isRegion) {
|
|
224
|
-
|
|
237
|
+
if (isChecked) {
|
|
238
|
+
region.showAllPrimitives();
|
|
239
|
+
//this.checkedRegions.push(node);
|
|
240
|
+
} else {
|
|
241
|
+
region.hideAllPrimitives();
|
|
242
|
+
//this.checkedRegions = this.checkedRegions.filter(region => region.label !== node.label);
|
|
243
|
+
}
|
|
225
244
|
}
|
|
226
245
|
if (isPrimitives) {
|
|
227
246
|
const primitives = region.findObjectsWithGroupName(node.label);
|
|
@@ -514,13 +533,28 @@ export default {
|
|
|
514
533
|
});
|
|
515
534
|
}
|
|
516
535
|
},
|
|
517
|
-
|
|
536
|
+
setCheckedKeys: function (ids, clear) {
|
|
537
|
+
this.$nextTick(() => {
|
|
538
|
+
if (clear) {
|
|
539
|
+
this.$refs.treeControls.$refs.regionTree.setCheckedKeys([]); // Clear previous checked keys
|
|
540
|
+
}
|
|
541
|
+
// this will be faster as it only requires region node ids only
|
|
542
|
+
// the number will be much less than all node ids
|
|
543
|
+
ids.forEach((id) => {
|
|
544
|
+
this.$refs.treeControls.$refs.regionTree.setChecked(id, true, true); // Set new checked keys
|
|
545
|
+
})
|
|
546
|
+
});
|
|
547
|
+
},
|
|
548
|
+
checkAllKeys: function (ignore = []) {
|
|
518
549
|
const keysList = [];
|
|
519
550
|
const ids = [];
|
|
520
551
|
extractAllFullPaths(this.treeData[0], keysList);
|
|
552
|
+
const modifiedKeysList = keysList.filter((key) => {
|
|
553
|
+
return !ignore.some(item => key.includes(item));
|
|
554
|
+
});
|
|
521
555
|
this.setTreeVisibilityWithFullPaths(
|
|
522
556
|
this.treeData[0],
|
|
523
|
-
|
|
557
|
+
modifiedKeysList,
|
|
524
558
|
ids,
|
|
525
559
|
true
|
|
526
560
|
);
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
</el-popover>
|
|
110
110
|
<div class="primitive-controls-box">
|
|
111
111
|
<primitive-controls
|
|
112
|
+
v-show="viewingMode === 'Exploration' || viewingMode === 'Annotation'"
|
|
112
113
|
ref="primitiveControls"
|
|
113
114
|
:createData="createData"
|
|
114
115
|
@primitivesUpdated="primitivesUpdated"
|
|
@@ -288,7 +289,7 @@
|
|
|
288
289
|
ref="backgroundPopover"
|
|
289
290
|
:virtual-ref="backgroundIconRef"
|
|
290
291
|
placement="top-start"
|
|
291
|
-
width="
|
|
292
|
+
width="320"
|
|
292
293
|
:teleported="false"
|
|
293
294
|
trigger="click"
|
|
294
295
|
popper-class="background-popper non-selectable h-auto"
|
|
@@ -323,7 +324,7 @@
|
|
|
323
324
|
<el-radio-group
|
|
324
325
|
v-model="colourRadio"
|
|
325
326
|
class="scaffold-radio"
|
|
326
|
-
@change="setColour"
|
|
327
|
+
@change="setColour(colourRadio, true)"
|
|
327
328
|
>
|
|
328
329
|
<el-radio :value="true">Colour</el-radio>
|
|
329
330
|
<el-radio :value="false">Greyscale</el-radio>
|
|
@@ -335,7 +336,7 @@
|
|
|
335
336
|
<el-radio-group
|
|
336
337
|
v-model="outlinesRadio"
|
|
337
338
|
class="scaffold-radio"
|
|
338
|
-
@change="setOutlines"
|
|
339
|
+
@change="setOutlines(outlinesRadio, true)"
|
|
339
340
|
>
|
|
340
341
|
<el-radio :value="true">Show</el-radio>
|
|
341
342
|
<el-radio :value="false">Hide</el-radio>
|
|
@@ -437,7 +438,6 @@ import {
|
|
|
437
438
|
findObjectsWithNames,
|
|
438
439
|
updateBoundingBox,
|
|
439
440
|
} from "../scripts/Utilities.js";
|
|
440
|
-
|
|
441
441
|
import {
|
|
442
442
|
ElButton as Button,
|
|
443
443
|
ElCol as Col,
|
|
@@ -458,6 +458,9 @@ import { OrgansViewer } from "../scripts/OrgansRenderer.js";
|
|
|
458
458
|
import { SearchIndex } from "../scripts/Search.js";
|
|
459
459
|
import { mapState } from 'pinia';
|
|
460
460
|
import { useMainStore } from "@/store/index";
|
|
461
|
+
import { getNerveMaps } from "../scripts/MappedNerves.js";
|
|
462
|
+
const nervesMap = getNerveMaps();
|
|
463
|
+
let totalNerves = 0, foundNerves = 0;
|
|
461
464
|
|
|
462
465
|
/**
|
|
463
466
|
* A vue component of the scaffold viewer.
|
|
@@ -860,6 +863,7 @@ export default {
|
|
|
860
863
|
viewingMode: "Exploration",
|
|
861
864
|
viewingModes: {
|
|
862
865
|
"Exploration": "View and explore detailed visualization of 3D scaffolds",
|
|
866
|
+
"Neuron Connection": "Discover nerve connections by selecting a nerve and viewing its associated connections",
|
|
863
867
|
"Annotation": ['View feature annotations', 'Add, comment on and view feature annotations'],
|
|
864
868
|
},
|
|
865
869
|
openMapRef: undefined,
|
|
@@ -885,7 +889,8 @@ export default {
|
|
|
885
889
|
region: "",
|
|
886
890
|
group: "",
|
|
887
891
|
isSearch: false,
|
|
888
|
-
})
|
|
892
|
+
}),
|
|
893
|
+
//checkedRegions: []
|
|
889
894
|
};
|
|
890
895
|
},
|
|
891
896
|
watch: {
|
|
@@ -1033,6 +1038,91 @@ export default {
|
|
|
1033
1038
|
},
|
|
1034
1039
|
},
|
|
1035
1040
|
methods: {
|
|
1041
|
+
/*
|
|
1042
|
+
setCheckedRegions: function (data) {
|
|
1043
|
+
this.checkedRegions = data;
|
|
1044
|
+
},
|
|
1045
|
+
*/
|
|
1046
|
+
/**
|
|
1047
|
+
*
|
|
1048
|
+
* @param nerves array of nerve names, show all nerves if empty
|
|
1049
|
+
* @param processed boolean, whether unselect all checkboxes
|
|
1050
|
+
*/
|
|
1051
|
+
zoomToNerves: function (nerves, processed = false) {
|
|
1052
|
+
if (this.$module.scene) {
|
|
1053
|
+
const nervesList = [];
|
|
1054
|
+
let nervesUUID = undefined;
|
|
1055
|
+
const regions = this.$module.scene.getRootRegion().getChildRegions();
|
|
1056
|
+
regions.forEach((region) => {
|
|
1057
|
+
const regionName = region.getName();
|
|
1058
|
+
if (processed) {
|
|
1059
|
+
if (regionName === 'Nerves') {
|
|
1060
|
+
if (nerves.length) {
|
|
1061
|
+
const ids = nerves.forEach((nerve) => {
|
|
1062
|
+
const primitives = this.findObjectsWithGroupName(nerve)
|
|
1063
|
+
nervesList.push(...primitives);
|
|
1064
|
+
primitives.forEach((primitive) => {
|
|
1065
|
+
primitive.setVisibility(true);
|
|
1066
|
+
nervesList.push(primitive);
|
|
1067
|
+
if (!nervesUUID) nervesUUID = primitive.region.uuid;
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
});
|
|
1074
|
+
if (nervesList.length) {
|
|
1075
|
+
let box = this.$module.scene.getBoundingBoxOfZincObjects(nervesList);
|
|
1076
|
+
if (box) this.$module.scene.viewAllWithBoundingBox(box);
|
|
1077
|
+
}
|
|
1078
|
+
if (nervesUUID) {
|
|
1079
|
+
this.$refs.scaffoldTreeControls.setCheckedKeys([nervesUUID], false);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
//The following hide all the other primitives
|
|
1084
|
+
/*
|
|
1085
|
+
if (this.$module.scene) {
|
|
1086
|
+
const idsList = [];
|
|
1087
|
+
const regions = this.$module.scene.getRootRegion().getChildRegions();
|
|
1088
|
+
regions.forEach((region) => {
|
|
1089
|
+
const regionName = region.getName();
|
|
1090
|
+
if (processed) {
|
|
1091
|
+
region.hideAllPrimitives();
|
|
1092
|
+
if (regionName === 'Nerves') {
|
|
1093
|
+
if (nerves.length) {
|
|
1094
|
+
const ids = nerves.reduce((acc, nerve) => {
|
|
1095
|
+
const primitives = this.findObjectsWithGroupName(nerve)
|
|
1096
|
+
const ids = primitives.map((object) => {
|
|
1097
|
+
object.setVisibility(true);
|
|
1098
|
+
return `${object.region.uuid}/${object.uuid}`;
|
|
1099
|
+
});
|
|
1100
|
+
acc.push(...ids);
|
|
1101
|
+
return acc;
|
|
1102
|
+
}, []);
|
|
1103
|
+
idsList.push(...ids)
|
|
1104
|
+
} else {
|
|
1105
|
+
region.showAllPrimitives();
|
|
1106
|
+
idsList.push(region.uuid)
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
} else {
|
|
1110
|
+
// if the checkboxes are checked previously, restore them
|
|
1111
|
+
const isChecked = this.checkedRegions.find(item => item.label === regionName);
|
|
1112
|
+
if (isChecked) {
|
|
1113
|
+
region.showAllPrimitives();
|
|
1114
|
+
idsList.push(region.uuid);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
});
|
|
1119
|
+
if (nerves.length) {
|
|
1120
|
+
this.fitWindow();
|
|
1121
|
+
}
|
|
1122
|
+
this.$refs.scaffoldTreeControls.setCheckedKeys(idsList, processed);
|
|
1123
|
+
}
|
|
1124
|
+
*/
|
|
1125
|
+
},
|
|
1036
1126
|
enableAxisDisplay: function (enable, miniaxes) {
|
|
1037
1127
|
if (this.$module.scene) {
|
|
1038
1128
|
this.$module.scene.enableAxisDisplay(enable, miniaxes);
|
|
@@ -1072,10 +1162,17 @@ export default {
|
|
|
1072
1162
|
for (let i = 0; i < regions.length; i++) {
|
|
1073
1163
|
if (regionPath.includes(regions[i].toLowerCase())) {
|
|
1074
1164
|
zincObject.userData.isNerves = true;
|
|
1165
|
+
const groupName = zincObject.groupName.toLowerCase();
|
|
1166
|
+
if (groupName in nervesMap) {
|
|
1167
|
+
foundNerves++;
|
|
1168
|
+
zincObject.setAnatomicalId(nervesMap[groupName]);
|
|
1169
|
+
//console.log(groupName, zincObject.anatomicalId, zincObject.uuid)
|
|
1170
|
+
}
|
|
1075
1171
|
} else {
|
|
1076
1172
|
zincObject.userData.isNerves = false;
|
|
1077
1173
|
}
|
|
1078
1174
|
}
|
|
1175
|
+
|
|
1079
1176
|
}
|
|
1080
1177
|
/**
|
|
1081
1178
|
* Emit when a new object is added to the scene
|
|
@@ -1779,11 +1876,13 @@ export default {
|
|
|
1779
1876
|
* @arg objects objects to be set for the selected
|
|
1780
1877
|
*/
|
|
1781
1878
|
updatePrimitiveControls: function (objects) {
|
|
1782
|
-
this.
|
|
1783
|
-
|
|
1784
|
-
this
|
|
1785
|
-
|
|
1786
|
-
|
|
1879
|
+
if (this.viewingMode === 'Exploration' || this.viewingMode === 'Annotation') {
|
|
1880
|
+
this.selectedObjects = objects;
|
|
1881
|
+
if (this.selectedObjects && this.selectedObjects.length > 0) {
|
|
1882
|
+
this.$refs.primitiveControls.setObject(this.selectedObjects[0]);
|
|
1883
|
+
} else {
|
|
1884
|
+
this.$refs.primitiveControls.setObject(undefined);
|
|
1885
|
+
}
|
|
1787
1886
|
}
|
|
1788
1887
|
},
|
|
1789
1888
|
/**
|
|
@@ -2125,6 +2224,7 @@ export default {
|
|
|
2125
2224
|
* Optional, can be used to update the view mode.
|
|
2126
2225
|
*/
|
|
2127
2226
|
changeViewingMode: function (modeName) {
|
|
2227
|
+
let nonNervesIsPickable = true;
|
|
2128
2228
|
if (this.$module) {
|
|
2129
2229
|
if (modeName) {
|
|
2130
2230
|
this.viewingMode = modeName;
|
|
@@ -2144,12 +2244,12 @@ export default {
|
|
|
2144
2244
|
this.addAnnotationFeature();
|
|
2145
2245
|
this.loading = false;
|
|
2146
2246
|
});
|
|
2147
|
-
} else {
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2247
|
+
} else if (this.viewingMode === "Exploration") {
|
|
2248
|
+
this.activeDrawTool = undefined;
|
|
2249
|
+
this.activeDrawMode = undefined;
|
|
2250
|
+
this.createData.shape = "";
|
|
2251
|
+
} else if (this.viewingMode === "Neuron Connection") {
|
|
2252
|
+
nonNervesIsPickable = false;
|
|
2153
2253
|
}
|
|
2154
2254
|
if ((this.viewingMode === "Exploration") ||
|
|
2155
2255
|
(this.viewingMode === "Annotation") &&
|
|
@@ -2159,6 +2259,9 @@ export default {
|
|
|
2159
2259
|
this.$module.selectObjectOnPick = false;
|
|
2160
2260
|
}
|
|
2161
2261
|
this.cancelCreate();
|
|
2262
|
+
if (modeName) {
|
|
2263
|
+
this.setNonNervesIsPickable(nonNervesIsPickable);
|
|
2264
|
+
}
|
|
2162
2265
|
}
|
|
2163
2266
|
},
|
|
2164
2267
|
/**
|
|
@@ -2183,24 +2286,50 @@ export default {
|
|
|
2183
2286
|
this.tData.visible = false;
|
|
2184
2287
|
this.tData.region = undefined;
|
|
2185
2288
|
},
|
|
2289
|
+
/**
|
|
2290
|
+
* Currently will only apply to non-nerve object
|
|
2291
|
+
* @param flag boolean to control whether objects pickable
|
|
2292
|
+
*/
|
|
2293
|
+
setNonNervesIsPickable: function (flag) {
|
|
2294
|
+
const objects = this.$module.scene.getRootRegion().getAllObjects(true);
|
|
2295
|
+
objects.forEach((zincObject) => {
|
|
2296
|
+
if (!zincObject.userData.isNerves) zincObject.setIsPickable(flag);
|
|
2297
|
+
});
|
|
2298
|
+
},
|
|
2299
|
+
/**
|
|
2300
|
+
*
|
|
2301
|
+
* @param flag boolean
|
|
2302
|
+
* @param nerves array of nerve names
|
|
2303
|
+
*/
|
|
2304
|
+
setGreyScale: function (flag, nerves = []) {
|
|
2305
|
+
const objects = this.$module.scene.getRootRegion().getAllObjects(true);
|
|
2306
|
+
objects.forEach((zincObject) => {
|
|
2307
|
+
if (nerves.length) {
|
|
2308
|
+
const groupName = zincObject.groupName.toLowerCase();
|
|
2309
|
+
if (zincObject.userData.isNerves) {
|
|
2310
|
+
if (!nerves.includes(groupName)) zincObject.setGreyScale(flag);
|
|
2311
|
+
}
|
|
2312
|
+
} else {
|
|
2313
|
+
if (!zincObject.userData.isNerves) zincObject.setGreyScale(flag);
|
|
2314
|
+
}
|
|
2315
|
+
});
|
|
2316
|
+
this.$refs.scaffoldTreeControls.updateAllNodeColours();
|
|
2317
|
+
},
|
|
2186
2318
|
/**
|
|
2187
2319
|
* @public
|
|
2188
2320
|
* Function to toggle colour/greyscale of primitives.
|
|
2189
2321
|
* The parameter ``flag`` is a boolean, ``true`` (colour) and ``false`` (greyscale).
|
|
2190
2322
|
* @arg {Boolean} `flag`
|
|
2191
2323
|
*/
|
|
2192
|
-
|
|
2324
|
+
setColour: function (flag, forced = false) {
|
|
2193
2325
|
if (this.isReady && this.$module.scene &&
|
|
2194
|
-
|
|
2326
|
+
typeof flag === "boolean" &&
|
|
2327
|
+
(forced || flag !== this.colourRadio)) {
|
|
2195
2328
|
this.loading = true;
|
|
2196
2329
|
//This can take sometime to finish , nextTick does not bring out
|
|
2197
2330
|
//the loading screen so I opt for timeout loop here.
|
|
2198
2331
|
setTimeout(() => {
|
|
2199
|
-
|
|
2200
|
-
objects.forEach((zincObject) => {
|
|
2201
|
-
if (!zincObject.userData.isNerves) zincObject.setGreyScale(!flag);
|
|
2202
|
-
});
|
|
2203
|
-
this.$refs.scaffoldTreeControls.updateAllNodeColours();
|
|
2332
|
+
this.setGreyScale(!flag)
|
|
2204
2333
|
this.loading = false;
|
|
2205
2334
|
this.colourRadio = flag;
|
|
2206
2335
|
}, 100);
|
|
@@ -2212,9 +2341,10 @@ export default {
|
|
|
2212
2341
|
* The parameter ``flag`` is a boolean, ``true`` to show lines, ``false`` to hide them.
|
|
2213
2342
|
* @arg {Boolean} `flag`
|
|
2214
2343
|
*/
|
|
2215
|
-
setOutlines: function (flag) {
|
|
2344
|
+
setOutlines: function (flag, forced = false) {
|
|
2216
2345
|
if (this.isReady && this.$module.scene &&
|
|
2217
|
-
|
|
2346
|
+
typeof flag === "boolean" &&
|
|
2347
|
+
(forced || flag !== this.outlinesRadio)) {
|
|
2218
2348
|
this.outlinesRadio = flag;
|
|
2219
2349
|
this.$nextTick(() => this.$refs.scaffoldTreeControls.setOutlines(flag));
|
|
2220
2350
|
}
|
|
@@ -2431,6 +2561,7 @@ export default {
|
|
|
2431
2561
|
//this.$module.scene.createAxisDisplay(false);
|
|
2432
2562
|
//this.$module.scene.enableAxisDisplay(true, true);
|
|
2433
2563
|
this.isReady = true;
|
|
2564
|
+
//console.log(`Total ${totalNerves}, found ${foundNerves}`);
|
|
2434
2565
|
this.$nextTick(() => {
|
|
2435
2566
|
this.restoreSettings(options);
|
|
2436
2567
|
this.$emit("on-ready");
|