Skip to content

Commit 24247d8

Browse files
committed
Add progress bar for histogram computation
1 parent cdd8085 commit 24247d8

File tree

4 files changed

+64
-22
lines changed

4 files changed

+64
-22
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"chartjs-plugin-datalabels": "^0.6.0",
1919
"chartjs-plugin-zoom": "^0.7.4",
2020
"copy-to-clipboard": "^3.0.8",
21-
"cytomine-client": "npm:cytomine-uliege-js-client@^1.1.0",
21+
"cytomine-client": "npm:cytomine-uliege-js-client@^1.1.2",
2222
"detect-browser": "^4.7.0",
2323
"filesize": "^4.1.2",
2424
"ifvisible": "^1.1.0",

src/components/viewer/panels/ColorManipulation.vue

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
<b-message v-if="error" type="is-danger" has-icon icon-size="is-small" size="is-small">
2222
<p> {{ $t('unexpected-error-info-message') }} </p>
2323
</b-message>
24-
<div class="histogram-actions" v-else-if="!loading && !hasHistograms">
24+
<div class="histogram-actions" v-else-if="!loadingHistograms && !hasSomeHistograms">
2525
<a class="button is-small is-fullwidth" @click="computeHistograms()">{{$t('button-compute-histogram')}}</a>
2626
</div>
27-
<b-tabs type="is-boxed" class="histogram" v-else-if="loading || hasHistograms">
28-
<b-loading :is-full-page="false" class="small" :active="loading" />
27+
<div class="histogram-actions" v-else-if="(loadingHistograms || hasSomeHistograms) && !hasAllHistograms">
28+
<progress class="progress is-info" :value="histogramProgress" max="100">
29+
{{histogramProgress}}%
30+
</progress>
31+
</div>
32+
<b-tabs type="is-boxed" class="histogram" v-else-if="hasAllHistograms">
2933
<b-tab-item v-for="sampleHisto in sampleHistograms" :key="`${sampleHisto.id}`">
3034
<template #header>
3135
<i class="fa fa-circle color-preview" :style="{color: sampleColor(sampleHisto.sample)}" />
@@ -74,15 +78,15 @@
7478
</div>
7579
<div class="actions">
7680
<div class="level">
77-
<template v-if="maxRank > 1 && hasHistograms">
81+
<template v-if="maxRank > 1 && hasAllHistograms">
7882
<button class="level-item button is-small" @click="adjustToImage()">{{$t('button-adjust-image')}}</button>
7983
<button class="level-item button is-small" @click="adjustToSlice()">{{$t('button-adjust-slice')}}</button>
8084
</template>
81-
<button v-else-if="hasHistograms" class="level-item button is-small" @click="adjustToImage()">{{$t('button-adjust')}}</button>
85+
<button v-else-if="hasAllHistograms" class="level-item button is-small" @click="adjustToImage()">{{$t('button-adjust')}}</button>
8286

8387
<button class="level-item button is-small" @click="reset()">{{$t('button-reset')}}</button>
8488
</div>
85-
<a class="is-fullwidth button is-small" @click="switchHistogramScale()" v-if="hasHistograms">{{switchHistogramScaleLabel}}</a>
89+
<a class="is-fullwidth button is-small" @click="switchHistogramScale()" v-if="hasAllHistograms">{{switchHistogramScaleLabel}}</a>
8690
</div>
8791
</div>
8892
</template>
@@ -92,6 +96,7 @@ import {get} from '@/utils/store-helpers';
9296
import CytomineSlider from '@/components/form/CytomineSlider';
9397
import {ImageFilterProjectCollection, SampleHistogramCollection} from 'cytomine-client';
9498
import SampleHistogram from '@/components/viewer/panels/SampleHistogram';
99+
import constants from '@/utils/constants';
95100
96101
export default {
97102
name: 'color-manipulation',
@@ -103,7 +108,10 @@ export default {
103108
return {
104109
filters: null,
105110
sampleHistograms: null,
106-
loading: false,
111+
loadingHistograms: false,
112+
nbHistograms: 0,
113+
refreshInterval: constants.HISTOGRAM_REFRESH_INTERVAL,
114+
timeout: null,
107115
error: false,
108116
revisionBrightnessContrast: 0,
109117
};
@@ -137,12 +145,21 @@ export default {
137145
maxValue() {
138146
return Math.pow(2, this.image.bitPerSample);
139147
},
140-
hasHistograms() {
141-
return this.sampleHistograms && this.sampleHistograms.length > 0;
148+
expectedNbHistograms() {
149+
return this.image.depth * this.image.duration * this.image.channels * this.image.samplePerPixel;
150+
},
151+
hasAllHistograms() {
152+
return this.nbHistograms === this.expectedNbHistograms;
153+
},
154+
hasSomeHistograms() {
155+
return this.nbHistograms > 0;
142156
},
143157
canComputeHistogram() {
144158
return this.image.bitPerSample && this.image.samplePerPixel;
145159
},
160+
histogramProgress() {
161+
return this.nbHistograms / this.expectedNbHistograms * 100;
162+
},
146163
147164
selectedFilter: {
148165
get() {
@@ -193,7 +210,7 @@ export default {
193210
},
194211
watch: {
195212
slice() {
196-
this.fetchSampleHistograms();
213+
this.refresh();
197214
}
198215
},
199216
methods: {
@@ -234,6 +251,29 @@ export default {
234251
235252
return 'grey';
236253
},
254+
async refresh() {
255+
await this.fetchImageHistogramsCount();
256+
clearTimeout(this.timeout);
257+
if (this.nbHistograms < this.expectedNbHistograms && (this.nbHistograms > 0 || this.loadingHistograms)) {
258+
this.timeout = setTimeout(this.refresh, this.refreshInterval);
259+
}
260+
else if (this.nbHistograms === this.expectedNbHistograms) {
261+
if (!this.sampleHistograms) {
262+
await this.$store.dispatch(this.imageModule + 'refreshDefaultMinMax', {image: this.image});
263+
}
264+
await this.fetchSampleHistograms();
265+
this.loadingHistograms = false;
266+
}
267+
},
268+
async fetchImageHistogramsCount() {
269+
try {
270+
this.nbHistograms = await this.image.fetchNbSampleHistograms();
271+
}
272+
catch(error) {
273+
console.log(error);
274+
this.error = true;
275+
}
276+
},
237277
async fetchSampleHistograms() {
238278
try {
239279
this.sampleHistograms = (await SampleHistogramCollection.fetchAll({filterKey: 'sliceinstance', filterValue: this.slice.id})).array;
@@ -243,18 +283,16 @@ export default {
243283
this.error = true;
244284
}
245285
},
246-
async computeHistograms() {
247-
this.loading = true;
286+
computeHistograms() {
287+
this.loadingHistograms = true;
248288
try {
249-
await this.image.extractHistogram();
250-
await this.$store.dispatch(this.imageModule + 'refreshDefaultMinMax', {image: this.image});
251-
await this.fetchSampleHistograms();
289+
this.image.extractHistogram();
290+
this.refresh();
252291
}
253292
catch(error) {
254293
console.log(error);
255294
this.error = true;
256295
}
257-
this.loading = false;
258296
}
259297
},
260298
async created() {
@@ -269,11 +307,14 @@ export default {
269307
}
270308
this.filters = filters;
271309
272-
this.fetchSampleHistograms();
310+
this.refresh();
273311
}
274312
catch(error) {
275313
console.log(error);
276314
}
315+
},
316+
beforeDestroy() {
317+
clearTimeout(this.timeout);
277318
}
278319
};
279320
</script>

src/utils/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default {
3232
SAVE_POSITION_IN_IMAGE_INTERVAL: 5000, // position also stored each time the user moves in the image
3333
BROADCASTING_USERS_REFRESH_INTERVAL: 10000,
3434
TRACKING_REFRESH_INTERVAL: 500,
35+
HISTOGRAM_REFRESH_INTERVAL: 3000,
3536
// ---
3637
IDLE_DURATION: 120, // if the user does not move his mouse on the page during this duration, he is considered as inactive - no more ping (expressed in seconds)
3738
CONFIG_KEY_WELCOME: 'WELCOME',

0 commit comments

Comments
 (0)