Skip to content

Commit 489dbb9

Browse files
authored
Merge pull request #1738 from girder/jupyter-frame-selector
Jupyter Frame Selector component
2 parents 4b2b390 + 65596a4 commit 489dbb9

23 files changed

+712
-504
lines changed

Diff for: girder/girder_large_image/web_client/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
"jsonlint-mod": "^1.7.6",
2525
"sinon": "^2.1.0",
2626
"vue": "~2.6.14",
27-
"vue-color": "^2.8.1",
2827
"vue-loader": "~15.9.8",
2928
"vue-template-compiler": "~2.6.14",
3029
"webpack": "^3",
@@ -67,7 +66,8 @@
6766
"promise/no-return-in-finally": "error",
6867
"promise/no-return-wrap": "error",
6968
"vue/require-prop-types": "off",
70-
"vue/multiline-html-element-content-newline": "off"
69+
"vue/multiline-html-element-content-newline": "off",
70+
"vue/html-self-closing": "off"
7171
},
7272
"root": true
7373
},

Diff for: girder/girder_large_image/web_client/views/imageViewerSelectWidget.js

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
import $ from 'jquery';
22
import _ from 'underscore';
3+
import Vue from 'vue';
34

45
import {wrap} from '@girder/core/utilities/PluginUtils';
56
import eventStream from '@girder/core/utilities/EventStream';
67
import ItemView from '@girder/core/views/body/ItemView';
78
import View from '@girder/core/views/View';
89

10+
import {restRequest} from '@girder/core/rest';
11+
912
import largeImageConfig from './configView';
1013
import * as viewers from './imageViewerWidget';
1114

1215
import imageViewerSelectWidget from '../templates/imageViewerSelectWidget.pug';
1316
import '../stylesheets/imageViewerSelectWidget.styl';
14-
import FrameSelector from '../vue/components/FrameSelector.vue';
17+
18+
import FrameSelector from '../widgets/FrameSelector.vue';
19+
import DualInput from '../widgets/DualInput.vue';
20+
import CompositeLayers from '../widgets/CompositeLayers.vue';
21+
import HistogramEditor from '../widgets/HistogramEditor.vue';
22+
import colors from '../widgets/colors.json';
23+
import PresetsMenu from '../vue/components/PresetsMenu.vue';
1524

1625
wrap(ItemView, 'render', function (render) {
1726
// ItemView is a special case in which rendering is done asynchronously,
@@ -73,13 +82,32 @@ var ImageViewerSelectWidget = View.extend({
7382

7483
_createVue(imageMetadata, frameUpdate) {
7584
const el = this.$('#vue-container').get(0);
76-
const vm = new FrameSelector({
85+
const getFrameHistogram = (params) => {
86+
restRequest({
87+
type: 'GET',
88+
url: 'item/' + this.itemId + '/tiles/histogram',
89+
data: params
90+
}).then((response) => {
91+
const frameHistograms = this.vueApp._props.frameHistograms || {};
92+
frameHistograms[params.frame] = response;
93+
this.vueApp._props.frameHistograms = Object.assign({}, frameHistograms);
94+
return undefined;
95+
});
96+
};
97+
CompositeLayers.components = {HistogramEditor};
98+
FrameSelector.components = {DualInput, CompositeLayers, HistogramEditor, PresetsMenu};
99+
const Component = Vue.extend(FrameSelector);
100+
const vm = new Component({
77101
el,
78102
propsData: {
103+
currentFrame: 0,
79104
itemId: this.itemId,
80105
imageMetadata: imageMetadata,
81-
frameUpdate: frameUpdate,
82-
liConfig: this._liConfig
106+
frameUpdate,
107+
liConfig: this._liConfig,
108+
frameHistograms: undefined,
109+
getFrameHistogram,
110+
colors
83111
}
84112
});
85113
this.vueApp = vm;

Diff for: girder/girder_large_image/web_client/views/imageViewerWidget/geojs.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ var GeojsImageViewerWidget = ImageViewerWidget.extend({
154154
_postRender: function () {
155155
},
156156

157-
frameUpdate: function (frame, style) {
157+
frameUpdate: function ({frame, style}) {
158158
if (this._frame === undefined) {
159159
// don't set up layers until the we access the first non-zero frame
160160
if (frame === 0 && style === undefined) {
@@ -242,8 +242,8 @@ var GeojsImageViewerWidget = ImageViewerWidget.extend({
242242
this._layer2 = ltemp;
243243
this._updating = false;
244244
this.trigger('g:imageFrameChanged', this, frame);
245-
if (frame !== this._nextframe || style !== this._nextstyle) {
246-
this.frameUpdate(this._nextframe, this._nextstyle);
245+
if (frame !== this._nextframe || JSON.stringify(style) !== JSON.stringify(this._nextstyle)) {
246+
this.frameUpdate({frame: this._nextframe, style: this._nextstyle});
247247
}
248248
});
249249
});

Diff for: girder/girder_large_image/web_client/vue/components/PresetsMenu.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export default {
155155
},
156156
styleToAutoRange(band) {
157157
band = Object.assign({}, band); // new reference
158-
if (band.min && band.min.includes('min:')) {
158+
if (band.min && band.min.toString().includes('min:')) {
159159
band.autoRange = parseFloat(band.min.replace('min:', '')) * 100;
160160
delete band.min;
161161
delete band.max;

Diff for: girder/girder_large_image/web_client/vue/utils/clamp.js

-3
This file was deleted.

Diff for: girder/girder_large_image/web_client/vue/utils/colors.js

-86
This file was deleted.

Diff for: girder/girder_large_image/web_client/vue/utils/drag.js

-62
This file was deleted.

Diff for: girder/girder_large_image/web_client/widgets

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../large_image/widgets

Diff for: large_image/tilesource/base.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ def __rich_repr__(self) -> Iterator[Any]:
228228
def geospatial(self) -> bool:
229229
return False
230230

231+
@property
232+
def _unstyled(self) -> 'TileSource':
233+
return getattr(self, '_unstyledInstance', self)
234+
231235
def _setStyle(self, style: Any) -> None:
232236
"""
233237
Check and set the specified style from a json string or a dictionary.
@@ -304,13 +308,11 @@ def dtype(self) -> np.dtype:
304308
with self._sourceLock:
305309
if not self._dtype:
306310
self._dtype = 'check'
307-
sample, _ = cast(Tuple[np.ndarray, Any], getattr(
308-
self, '_unstyledInstance', self).getRegion(
309-
region=dict(left=0, top=0, width=1, height=1),
310-
format=TILE_FORMAT_NUMPY))
311+
sample, _ = cast(Tuple[np.ndarray, Any], self._unstyled.getRegion(
312+
region=dict(left=0, top=0, width=1, height=1),
313+
format=TILE_FORMAT_NUMPY))
311314
self._dtype = np.dtype(sample.dtype)
312-
self._bandCount = len(
313-
getattr(getattr(self, '_unstyledInstance', self), '_bandInfo', []))
315+
self._bandCount = len(getattr(self._unstyled, '_bandInfo', []))
314316
if not self._bandCount:
315317
self._bandCount = sample.shape[-1] if len(sample.shape) == 3 else 1
316318
return cast(np.dtype, self._dtype)
@@ -706,7 +708,7 @@ def _scanForMinMax(
706708
:param onlyMinMax: if True, only find the min and max. If False, get
707709
the entire histogram.
708710
"""
709-
self._bandRanges[frame] = getattr(self, '_unstyledInstance', self).histogram(
711+
self._bandRanges[frame] = self._unstyled.histogram(
710712
dtype=dtype,
711713
onlyMinMax=onlyMinMax,
712714
output={'maxWidth': min(self.sizeX, analysisSize),
@@ -1043,8 +1045,7 @@ def _applyStyle( # noqa
10431045
else:
10441046
frame = entry['frame'] if entry.get('frame') is not None else (
10451047
sc.mainFrame + entry['framedelta'])
1046-
image = getattr(self, '_unstyledInstance', self).getTile(
1047-
x, y, z, frame=frame, numpyAllowed=True)
1048+
image = self._unstyled.getTile(x, y, z, frame=frame, numpyAllowed=True)
10481049
image = image[:sc.mainImage.shape[0],
10491050
:sc.mainImage.shape[1],
10501051
:sc.mainImage.shape[2]]
@@ -1625,7 +1626,7 @@ def _getTileFromEmptyLevel(self, x: int, y: int, z: int, **kwargs) -> Tuple[
16251626
'Compositing tile from higher resolution tiles x=%d y=%d z=%d',
16261627
x * scale + newX, y * scale + newY, z)
16271628
lastlog = time.time()
1628-
subtile = getattr(self, '_unstyledInstance', self).getTile(
1629+
subtile = self._unstyled.getTile(
16291630
x * scale + newX, y * scale + newY, z,
16301631
pilImageAllowed=False, numpyAllowed='always',
16311632
sparseFallback=True, edge=False, frame=kwargs.get('frame'))
@@ -1649,7 +1650,7 @@ def _getTileFromEmptyLevel(self, x: int, y: int, z: int, **kwargs) -> Tuple[
16491650
'Compositing tile from higher resolution tiles x=%d y=%d z=%d',
16501651
x * scale + newX, y * scale + newY, z)
16511652
lastlog = time.time()
1652-
subtile = getattr(self, '_unstyledInstance', self).getTile(
1653+
subtile = self._unstyled.getTile(
16531654
x * scale + newX, y * scale + newY, z,
16541655
pilImageAllowed=True, numpyAllowed=False,
16551656
sparseFallback=True, edge=False, frame=kwargs.get('frame'))

0 commit comments

Comments
 (0)