diff --git a/src/omero_cli_render.py b/src/omero_cli_render.py index 507694ae..852de192 100755 --- a/src/omero_cli_render.py +++ b/src/omero_cli_render.py @@ -39,7 +39,8 @@ from omero.model import Screen from omero.model import Dataset from omero.model import Project -from omero.rtypes import rint +from omero.model import StatsInfoI +from omero.rtypes import rint, rdouble from omero.util import pydict_text_io from omero import UnloadedEntityException @@ -97,6 +98,8 @@ label: Channel name start: Start of rendering window, optional (needs end) end: End of rendering window, optional (needs start) + min: Minimum pixel intensity, optional (needs max) + max: Maximum pixel intensity, optional (needs min) : ... greyscale: Greyscale rendering, optional @@ -123,9 +126,12 @@ # Omitted fields will keep their current values. # Omitted channels will not be disabled unless --disable is used. # If the file specifies to turn off a channel (active: False) then the - # other settings like min, max, and color which might be specified for + # other settings like start, end, and color which might be specified for # that channel in the same file will be ignored, however the channel # name (label) is still taken into account. + # If min and max have not been set on the channel (no StatsInfo on the + # channel) then you must set both. If max and min already set, each can + # be updated individually. """ TEST_HELP = """Test that underlying pixel data is available @@ -642,6 +648,7 @@ def _read_channels(self, data): cindices = [] rangelist = [] colourlist = [] + minmaxlist = [] for (i, c) in newchannels.items(): if c.label: namedict[i] = c.label @@ -651,15 +658,17 @@ def _read_channels(self, data): cindices.append(i) rangelist.append([c.start, c.end]) colourlist.append(c.color) - return (namedict, cindices, rangelist, colourlist) + minmaxlist.append([c.min, c.max]) + rv = (namedict, cindices, rangelist, colourlist, minmaxlist) + return rv @gateway_required def set(self, args): """ Implements the 'set' command """ data = self._load_rendering_settings( args.channels, session=self.client.getSession()) - (namedict, cindices, rangelist, colourlist) = self._read_channels( - data) + (namedict, cindices, rangelist, colourlist, minmaxlist) = \ + self._read_channels(data) greyscale = data.get('greyscale', None) if greyscale is not None: self.ctx.dbg('greyscale=%s' % greyscale) @@ -696,6 +705,22 @@ def set(self, args): if len(active_channels) > 0: img.set_active_channels(active_channels) + # Set statsInfo min & max + for minmax, ch in zip(minmaxlist, img.getChannels(noRE=True)): + if minmax[0] is None and minmax[1] is None: + continue + si = ch.getStatsInfo() + if si is None: + si = StatsInfoI() + else: + si = si._obj + if minmax[0] is not None: + si.globalMin = rdouble(minmax[0]) + if minmax[1] is not None: + si.globalMax = rdouble(minmax[1]) + ch._obj.statsInfo = si + ch.save() + if def_z: img.setDefaultZ(def_z - 1) if def_t: diff --git a/test/integration/clitest/test_render.py b/test/integration/clitest/test_render.py index 1fcff690..987bce5e 100644 --- a/test/integration/clitest/test_render.py +++ b/test/integration/clitest/test_render.py @@ -214,6 +214,11 @@ def assert_channel_rdef(self, channel, rdef, version=2): end = 'end' if version > 1 else 'max' assert channel.getWindowStart() == rdef.get(start, 0) assert channel.getWindowEnd() == rdef.get(end, 255) + if version > 1: + if rdef.get('min') is not None: + assert channel.getWindowMin() == rdef.get('min') + if rdef.get('max') is not None: + assert channel.getWindowMax() == rdef.get('max') def assert_image_rmodel(self, img, greyscale): assert img.isGreyscaleRenderingModel() == greyscale @@ -291,6 +296,26 @@ def test_set_windows(self, version, windows, tmpdir): self.cli.invoke(self.args, strict=True) self.assert_target_rdef(self.idonly, rd) + def test_set_minmax(self, tmpdir): + self.create_image() + rd = self.get_render_def(version=2) + # Need to set min AND max or neither (StatsInfo needs both)... + rd['channels'][1]['min'] = 50 + rd['channels'][1]['max'] = 200 + rd['channels'][2]['min'] = 0 + rd['channels'][2]['max'] = 500 + rdfile = tmpdir.join('render-test.json') + rdfile.write(json.dumps(rd)) + self.args += ["set", self.idonly, str(rdfile)] + self.cli.invoke(self.args, strict=True) + self.assert_target_rdef(self.idonly, rd) + # But it is possible to update min OR max alone + rd = self.get_render_def(version=2) + rd['channels'][1]['min'] = 25 + rdfile.write(json.dumps(rd)) + self.cli.invoke(self.args, strict=True) + self.assert_target_rdef(self.idonly, rd) + @pytest.mark.parametrize('target_name', sorted(SUPPORTED)) @pytest.mark.parametrize('sizec', [1, 2]) def test_set_target(self, target_name, sizec, tmpdir):