From b5cc0d523d6485761d64f8704ac2ea5260e941b0 Mon Sep 17 00:00:00 2001 From: Daviti Gogshelidze Date: Tue, 14 Feb 2023 13:03:04 +0100 Subject: [PATCH 1/4] Enable custom resolution --- app/src/components/LayerControlBody.vue | 91 ++++++++++++++++++++++++- app/src/store/dataSelectionStore.js | 26 ++++++- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/app/src/components/LayerControlBody.vue b/app/src/components/LayerControlBody.vue index 41c4c357..6e01966a 100644 --- a/app/src/components/LayerControlBody.vue +++ b/app/src/components/LayerControlBody.vue @@ -155,6 +155,43 @@ + +
+
+ +
+ + + + + +
+ +
state.incVolTranslationLock ? 'lock' : 'lock-open', @@ -328,6 +370,7 @@ export default { return this.testScale[0] }, set: function (value) { + this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolution[0]) this.scaleEvent({ axis: 'x', value @@ -339,6 +382,7 @@ export default { return this.testScale[1] }, set: function (value) { + this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolution[1]) this.scaleEvent({ axis: 'y', value @@ -350,6 +394,7 @@ export default { return this.testScale[2] }, set: function (value) { + this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolution[2]) this.scaleEvent({ axis: 'z', value @@ -478,6 +523,9 @@ export default { if (flag) { this.isotropicScaleEvent({ value: this.testScaleX }) } + }, + selectedIncomingVolumeResolution: function (flag) { + this.resetResolution() } }, methods: { @@ -511,6 +559,13 @@ export default { collapse: `scaleBySliderIsotropic` }) + this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolution[0]) + this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolution[1]) + this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolution[2]) + + this.setIsotropicScale(value) + }, + setIsotropicScale: function(value) { this.setScaleInc({ axis: 'x', value @@ -610,7 +665,37 @@ export default { name: `flip on axis ${axis}` }) this.flipAxis({ axis }) + }, + setResolution: function () { + const isotropic = +this.selectedResolutionX === +this.selectedResolutionY && +this.selectedResolutionY === +this.selectedResolutionZ + + if (isotropic) { + this.setIsotropicScale(+this.selectedResolutionX/this.selectedIncomingVolumeResolution[0]) + } else { + this.isotropic = false + const scaleX = +this.selectedResolutionX/this.selectedIncomingVolumeResolution[0] + const scaleY = +this.selectedResolutionY/this.selectedIncomingVolumeResolution[1] + const scaleZ = +this.selectedResolutionZ/this.selectedIncomingVolumeResolution[2] + + this.scaleEvent({axis: 'x', value: scaleX}) + this.scaleEvent({axis: 'y', value: scaleY}) + this.scaleEvent({axis: 'z', value: scaleZ}) + } + }, + + + resetResolution: function () { + this.testScaleX = 1 + this.testScaleY = 1 + this.testScaleZ = 1 + this.selectedResolutionX = this.selectedIncomingVolumeResolution[0] + this.selectedResolutionY = this.selectedIncomingVolumeResolution[1] + this.selectedResolutionZ = this.selectedIncomingVolumeResolution[2] + this.isotropic = this.testScaleX === this.testScaleY && this.testScaleY === this.testScaleZ } + }, + created: function () { + this.resetResolution() } } diff --git a/app/src/store/dataSelectionStore.js b/app/src/store/dataSelectionStore.js index e9434281..a68cb58c 100644 --- a/app/src/store/dataSelectionStore.js +++ b/app/src/store/dataSelectionStore.js @@ -21,6 +21,7 @@ const dataSelectionStore = { ], selectedIncomingVolumeId: null, + selectedIncomingVolumeResolution: null, incomingVolumes: DEFAULT_BUNDLED_INCOMING_VOLUMES, }, @@ -34,6 +35,9 @@ const dataSelectionStore = { setSelectedIncomingVolumeId (state, id) { state.selectedIncomingVolumeId = id }, + setSelectedIncomingVolumeResolution (state, resolution) { + state.selectedIncomingVolumeResolution = resolution + }, setIncomingVolumes (state, { volumes }) { state.incomingVolumes = volumes }, @@ -43,7 +47,7 @@ const dataSelectionStore = { const vol = state.referenceVolumes.find(({ id: _id }) => _id === id) if (vol) commit('setSelectedReferenceVolumeWithId', id) }, - selectIncomingVolumeWithId ({ commit, state }, id) { + selectIncomingVolumeWithId ({ commit, state, dispatch }, id) { const vol = state.incomingVolumes.find(({ id: _id }) => _id === id) if (vol) { if (vol.extra && vol.extra.neuroglancer && vol.extra.neuroglancer.transform) { @@ -56,11 +60,31 @@ const dataSelectionStore = { { matrix }, { root: true }) } + + dispatch('setIncomingVolumeResolution', id) + commit('setSelectedIncomingVolumeId', id) const { shaderScaleFactor } = vol commit('viewerPreferenceStore/setShaderScaleFactor', shaderScaleFactor || 1, { root: true }) } }, + + async ['setIncomingVolumeResolution'] ({ commit, state, dispatch, rootGetters }, id) { + try { + const vol = state.incomingVolumes.find(({ id: _id }) => _id === id) + const authHeader= rootGetters['authStore/authHeader'] + const config = {headers: {...authHeader}} + const { data } = await axios(`${vol.imageSource.substring(14)}/info`, config) + const resolution = data.scales[0].resolution + + commit('setSelectedIncomingVolumeResolution', resolution); + } catch (error) { + dispatch('updateIncVolumesResult', { + error: error ? error : null + }) + } + }, + updateIncVolumesResult (store, {error, message}) { /** * required for subscribe action From 028180f34f2d9b7db4f348648db20e9edb2990d6 Mon Sep 17 00:00:00 2001 From: Daviti Gogshelidze Date: Mon, 13 Mar 2023 16:03:45 +0100 Subject: [PATCH 2/4] Enable physical resolution --- app/src/components/LayerControlBody.vue | 153 ++++++++++++++++-------- app/src/store/dataSelectionStore.js | 17 +-- 2 files changed, 112 insertions(+), 58 deletions(-) diff --git a/app/src/components/LayerControlBody.vue b/app/src/components/LayerControlBody.vue index 6e01966a..bdc69cea 100644 --- a/app/src/components/LayerControlBody.vue +++ b/app/src/components/LayerControlBody.vue @@ -85,6 +85,62 @@
+ + +
+
+ +
+ + + + + +
@@ -155,42 +211,6 @@
- -
-
- -
- - - - - -
-
@@ -338,6 +358,7 @@ export default { selectedResolutionX: 0, selectedResolutionY: 0, selectedResolutionZ: 0, + voxelSpace: true } }, computed: { @@ -355,7 +376,8 @@ export default { ]), ...mapState('dataSelectionStore', [ 'incomingVolumes', - 'selectedIncomingVolumeResolution' + 'selectedIncomingVolumeResolution', + 'selectedIncomingVolumeSize' ]), ...mapState('nehubaStore', { lockIconTranslation: state => state.incVolTranslationLock ? 'lock' : 'lock-open', @@ -370,7 +392,7 @@ export default { return this.testScale[0] }, set: function (value) { - this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolution[0]) + this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolutionX) this.scaleEvent({ axis: 'x', value @@ -382,7 +404,9 @@ export default { return this.testScale[1] }, set: function (value) { - this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolution[1]) + this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolutionY + + ) this.scaleEvent({ axis: 'y', value @@ -394,7 +418,7 @@ export default { return this.testScale[2] }, set: function (value) { - this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolution[2]) + this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolutionZ) this.scaleEvent({ axis: 'z', value @@ -516,7 +540,22 @@ export default { }, renderedIncomingVolumes: function () { return [this.dummyIncomingTemplate].concat(this.$store.state.incomingVolumes) - } + }, + selectedIncomingVolumeResolutionX: { + get: function () { + return this.voxelSpace? +this.selectedIncomingVolumeResolution[0].toFixed(0) : +(this.voxelToReal(this.selectedIncomingVolumeResolution[0], 0)).toFixed(2) + } + }, + selectedIncomingVolumeResolutionY: { + get: function () { + return this.voxelSpace? +this.selectedIncomingVolumeResolution[1].toFixed(0) : +(this.voxelToReal(this.selectedIncomingVolumeResolution[1], 1)).toFixed(2) + } + }, + selectedIncomingVolumeResolutionZ: { + get: function () { + return this.voxelSpace? +this.selectedIncomingVolumeResolution[2].toFixed(0) : +(this.voxelToReal(this.selectedIncomingVolumeResolution[2], 2)).toFixed(2) + } + }, }, watch: { isotropic: function (flag) { @@ -526,6 +565,11 @@ export default { }, selectedIncomingVolumeResolution: function (flag) { this.resetResolution() + }, + voxelSpace: function (voxel) { + this.selectedResolutionX = voxel ? this.realToVoxel(this.selectedResolutionX, 0) : this.voxelToReal(this.selectedResolutionX, 0) + this.selectedResolutionY = voxel ? this.realToVoxel(this.selectedResolutionY, 1) : this.voxelToReal(this.selectedResolutionY, 1) + this.selectedResolutionZ = voxel ? this.realToVoxel(this.selectedResolutionZ, 2) : this.voxelToReal(this.selectedResolutionZ, 2) } }, methods: { @@ -559,9 +603,10 @@ export default { collapse: `scaleBySliderIsotropic` }) - this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolution[0]) - this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolution[1]) - this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolution[2]) + + this.selectedResolutionX = Math.round(+this.testScaleX * this.selectedIncomingVolumeResolutionX) + this.selectedResolutionY = Math.round(+this.testScaleY * this.selectedIncomingVolumeResolutionY) + this.selectedResolutionZ = Math.round(+this.testScaleZ * this.selectedIncomingVolumeResolutionZ) this.setIsotropicScale(value) }, @@ -670,12 +715,12 @@ export default { const isotropic = +this.selectedResolutionX === +this.selectedResolutionY && +this.selectedResolutionY === +this.selectedResolutionZ if (isotropic) { - this.setIsotropicScale(+this.selectedResolutionX/this.selectedIncomingVolumeResolution[0]) + this.setIsotropicScale(+this.selectedResolutionX/this.selectedIncomingVolumeResolutionX) } else { this.isotropic = false - const scaleX = +this.selectedResolutionX/this.selectedIncomingVolumeResolution[0] - const scaleY = +this.selectedResolutionY/this.selectedIncomingVolumeResolution[1] - const scaleZ = +this.selectedResolutionZ/this.selectedIncomingVolumeResolution[2] + const scaleX = +this.selectedResolutionX/this.selectedIncomingVolumeResolutionX + const scaleY = +this.selectedResolutionY/this.selectedIncomingVolumeResolutionY + const scaleZ = +this.selectedResolutionZ/this.selectedIncomingVolumeResolutionZ this.scaleEvent({axis: 'x', value: scaleX}) this.scaleEvent({axis: 'y', value: scaleY}) @@ -688,10 +733,16 @@ export default { this.testScaleX = 1 this.testScaleY = 1 this.testScaleZ = 1 - this.selectedResolutionX = this.selectedIncomingVolumeResolution[0] - this.selectedResolutionY = this.selectedIncomingVolumeResolution[1] - this.selectedResolutionZ = this.selectedIncomingVolumeResolution[2] + this.selectedResolutionX = this.selectedIncomingVolumeResolutionX + this.selectedResolutionY = this.selectedIncomingVolumeResolutionY + this.selectedResolutionZ = this.selectedIncomingVolumeResolutionZ this.isotropic = this.testScaleX === this.testScaleY && this.testScaleY === this.testScaleZ + }, + voxelToReal: function (num, index) { + return +((num * this.selectedIncomingVolumeSize[index])/1e6).toFixed(2) + }, + realToVoxel: function (num, index) { + return +((num / this.selectedIncomingVolumeSize[index])*1e6).toFixed(0) } }, created: function () { diff --git a/app/src/store/dataSelectionStore.js b/app/src/store/dataSelectionStore.js index a68cb58c..51480682 100644 --- a/app/src/store/dataSelectionStore.js +++ b/app/src/store/dataSelectionStore.js @@ -22,6 +22,7 @@ const dataSelectionStore = { selectedIncomingVolumeId: null, selectedIncomingVolumeResolution: null, + selectedIncomingVolumeSize: null, incomingVolumes: DEFAULT_BUNDLED_INCOMING_VOLUMES, }, @@ -35,8 +36,9 @@ const dataSelectionStore = { setSelectedIncomingVolumeId (state, id) { state.selectedIncomingVolumeId = id }, - setSelectedIncomingVolumeResolution (state, resolution) { - state.selectedIncomingVolumeResolution = resolution + setSelectedIncomingVolumeResolution (state, data) { + state.selectedIncomingVolumeResolution = data.resolution + state.selectedIncomingVolumeSize = data.size }, setIncomingVolumes (state, { volumes }) { state.incomingVolumes = volumes @@ -72,12 +74,13 @@ const dataSelectionStore = { async ['setIncomingVolumeResolution'] ({ commit, state, dispatch, rootGetters }, id) { try { const vol = state.incomingVolumes.find(({ id: _id }) => _id === id) - const authHeader= rootGetters['authStore/authHeader'] - const config = {headers: {...authHeader}} - const { data } = await axios(`${vol.imageSource.substring(14)}/info`, config) + const { data } = await axios(`${vol.imageSource.substring(14)}/info`) const resolution = data.scales[0].resolution - - commit('setSelectedIncomingVolumeResolution', resolution); + const size = data.scales[0].size + // const resolution = {} + // resolution.voxel = data.scales[0].resolution + // resolution.real = data.scales[0].resolution.map((r, i) => r * data.scales[0].size[i]) + commit('setSelectedIncomingVolumeResolution', {resolution, size}) } catch (error) { dispatch('updateIncVolumesResult', { error: error ? error : null From 59f9767330d6618df9486a88dc690103b2f1e38b Mon Sep 17 00:00:00 2001 From: Daviti Gogshelidze Date: Fri, 17 Mar 2023 14:02:30 +0100 Subject: [PATCH 3/4] Add resolution units --- app/src/components/LayerControlBody.vue | 89 +++++++++++++++---------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/app/src/components/LayerControlBody.vue b/app/src/components/LayerControlBody.vue index bdc69cea..bfe8671d 100644 --- a/app/src/components/LayerControlBody.vue +++ b/app/src/components/LayerControlBody.vue @@ -101,17 +101,20 @@