def testEditSingleC(self, targetName, greyscale, tmpdir): sizec = 1 # 1 channel so should default to greyscale model expected_greyscale = ((greyscale is None) or greyscale) self.create_image(sizec=sizec) rd = self.get_render_def(sizec=sizec, greyscale=greyscale) rdfile = tmpdir.join('render-test-editsinglec.json') # Should work with json and yaml, but yaml is an optional dependency rdfile.write(json.dumps(rd)) target = getattr(self, targetName) self.args += ["edit", target, str(rdfile)] self.cli.invoke(self.args, strict=True) iids = self.get_target_imageids(target) print 'Got %d images' % len(iids) gw = BlitzGateway(client_obj=self.client) for iid in iids: # Get the updated object img = gw.getObject('Image', iid) # Note: calling _prepareRE below does NOT suffice! img._prepareRenderingEngine() # Call *before* getChannels # Passing noRE to getChannels below also prevents leaking # the RenderingEngine but then Nones are returned later. channels = img.getChannels() assert len(channels) == sizec for c in xrange(len(channels)): self.assert_channel_rdef(channels[c], rd['channels'][c + 1]) self.assert_image_rmodel(img, expected_greyscale) img._closeRE() assert not gw._assert_unregistered("testEditSingleC")
def testEdit(self, targetName, tmpdir): sizec = 4 greyscale = None # 4 channels so should default to colour model expected_greyscale = False self.create_image(sizec=sizec) rd = self.get_render_def(sizec=sizec, greyscale=greyscale) rdfile = tmpdir.join('render-test-edit.json') # Should work with json and yaml, but yaml is an optional dependency rdfile.write(json.dumps(rd)) target = getattr(self, targetName) self.args += ["edit", target, str(rdfile)] self.cli.invoke(self.args, strict=True) iids = self.get_target_imageids(target) print 'Got %d images' % len(iids) gw = BlitzGateway(client_obj=self.client) for iid in iids: # Get the updated object img = gw.getObject('Image', iid) channels = img.getChannels() assert len(channels) == sizec for c in xrange(len(channels)): self.assert_channel_rdef(channels[c], rd['channels'][c + 1]) self.assert_image_rmodel(img, expected_greyscale) img._closeRE() assert not gw._assert_unregistered("testEdit")
def info(self, args): client = self.ctx.conn(args) gateway = BlitzGateway(client_obj=client) first = True for img in self.render_images(gateway, args.object, batch=1): ro = RenderObject(img) try: if args.style == 'plain': self.ctx.out(ro) else: if not first: self.ctx.die( 103, "Output styles not supported for multiple images") self.ctx.out(pydict_text_io.dump(ro.to_dict(), args.style)) first = False finally: ro.close() gateway._assert_unregistered("info")
def edit(self, args): client = self.ctx.conn(args) gateway = BlitzGateway(client_obj=client) newchannels = {} data = pydict_text_io.load( args.channels, session=client.getSession()) if 'channels' not in data: self.ctx.die(104, "ERROR: No channels found in %s" % args.channels) for chindex, chdict in data['channels'].iteritems(): try: cindex = int(chindex) except Exception as e: self.ctx.err('ERROR: %s' % e) self.ctx.die( 105, "Invalid channel index: %s" % chindex) try: cobj = ChannelObject(chdict) if (cobj.min is None) != (cobj.max is None): raise Exception('Both or neither of min and max required') newchannels[cindex] = cobj print '%d:%s' % (cindex, cobj) except Exception as e: self.ctx.err('ERROR: %s' % e) self.ctx.die( 105, "Invalid channel description: %s" % chdict) try: greyscale = data['greyscale'] except KeyError: greyscale = None namedict = {} cindices = [] rangelist = [] colourlist = [] for (i, c) in newchannels.iteritems(): if c.label: namedict[i] = c.label if not c.active: continue cindices.append(i) rangelist.append([c.min, c.max]) colourlist.append(c.color) iids = [] for img in self.render_images(gateway, args.object, batch=1): iids.append(img.id) try: img.setActiveChannels( cindices, windows=rangelist, colors=colourlist, noRE=True) if greyscale is not None: if greyscale: img.setGreyscaleRenderingModel() else: img.setColorRenderingModel() img.saveDefaults() self.ctx.dbg( "Updated rendering settings for Image:%s" % img.id) if not args.skipthumbs: self._generate_thumbs([img]) if args.copy: # Edit first image only, copy to rest # Don't close source image until outer # loop is done. self._copy_single(gateway, img, args.object, args.skipthumbs) break finally: img._closeRE() if namedict: self._update_channel_names(gateway, iids, namedict) gateway._assert_unregistered("edit")
def copy(self, args): client = self.ctx.conn(args) gateway = BlitzGateway(client_obj=client) self._copy(gateway, args.object, args.target, args.skipthumbs) gateway._assert_unregistered("copy")
class TestRender(CLITest): def setup_method(self, method): super(TestRender, self).setup_method(method) self.cli.register("render", RenderControl, "TEST") self.args += ["render"] def create_image(self, sizec=4): self.gw = BlitzGateway(client_obj=self.client) self.plates = [] for plate in self.import_plates(fields=2, sizeC=sizec, screens=1): self.plates.append(self.gw.getObject("Plate", plate.id.val)) # Now pick the first Image self.imgobj = list(self.plates[0].listChildren())[0].getImage(index=0) self.idonly = "%s" % self.imgobj.id self.imageid = "Image:%s" % self.imgobj.id self.plateid = "Plate:%s" % self.plates[0].id self.screenid = "Screen:%s" % self.plates[0].getParent().id # And another one as the source for copies self.source = list(self.plates[0].listChildren())[0].getImage(index=1) self.source = "Image:%s" % self.source.id # And for all the images, pre-load a thumbnail for p in self.plates: for w in p.listChildren(): for i in range(w.countWellSample()): img = w.getImage(index=i) img.getThumbnail( size=(96,), direct=False) img._closeRE() self.imgobj._closeRE() assert not self.gw._assert_unregistered("create_image") def get_target_imageids(self, target): if target in (self.idonly, self.imageid): return [self.idonly] if target == self.plateid: imgs = [] for w in self.plates[0].listChildren(): imgs.extend([w.getImage(0).id, w.getImage(1).id]) return imgs if target == self.screenid: imgs = [] for s in self.plates: for w in self.plates[0].listChildren(): imgs.extend([w.getImage(0).id, w.getImage(1).id]) return imgs raise Exception('Unknown target: %s' % target) def get_render_def(self, sizec=4, greyscale=None): channels = {} channels[1] = { 'label': self.uuid(), 'color': '123456', 'min': 11, 'max': 22, } channels[2] = { 'label': self.uuid(), 'color': '789ABC', 'min': 33, 'max': 44, } channels[3] = { 'label': self.uuid(), 'color': 'DEF012', 'min': 55, 'max': 66, } channels[4] = { 'label': self.uuid(), 'color': '345678', 'min': 77, 'max': 88, } for k in xrange(sizec, 4): del channels[k + 1] d = {'channels': channels} if greyscale is not None: d['greyscale'] = greyscale return d def assert_channel_rdef(self, channel, rdef): assert channel.getLabel() == rdef['label'] assert channel.getColor().getHtml() == rdef['color'] assert channel.getWindowStart() == rdef['min'] assert channel.getWindowEnd() == rdef['max'] def assert_image_rmodel(self, img, greyscale): assert img.isGreyscaleRenderingModel() == greyscale # rendering tests # ======================================================================== @pytest.mark.parametrize('targetName', sorted(SUPPORTED.keys())) def testNonExistingImage(self, targetName, tmpdir): target = SUPPORTED[targetName] self.args += ["info", target] with pytest.raises(NonZeroReturnCode): self.cli.invoke(self.args, strict=True) @pytest.mark.parametrize('targetName', sorted(SUPPORTED.keys())) def testInfo(self, targetName, tmpdir): self.create_image() target = getattr(self, targetName) self.args += ["info", target] self.cli.invoke(self.args, strict=True) @pytest.mark.parametrize('style', ['json', 'yaml']) def testInfoStyle(self, style): self.create_image() target = self.imageid self.args += ["info", target] self.args += ['--style', style] self.cli.invoke(self.args, strict=True) @pytest.mark.parametrize('targetName', sorted(SUPPORTED.keys())) def testCopy(self, targetName, tmpdir): self.create_image() target = getattr(self, targetName) self.args += ["copy", self.source, target] self.cli.invoke(self.args, strict=True) @pytest.mark.parametrize('targetName', sorted(SUPPORTED.keys())) @pytest.mark.broken( reason=('https://trello.com/c/lyyGuRow/' '657-incorrect-logical-channels-in-clitest-importplates')) @pytest.mark.xfail( reason=('https://trello.com/c/lyyGuRow/' '657-incorrect-logical-channels-in-clitest-importplates')) def testEdit(self, targetName, tmpdir): sizec = 4 greyscale = None # 4 channels so should default to colour model expected_greyscale = False self.create_image(sizec=sizec) rd = self.get_render_def(sizec=sizec, greyscale=greyscale) rdfile = tmpdir.join('render-test-edit.json') # Should work with json and yaml, but yaml is an optional dependency rdfile.write(json.dumps(rd)) target = getattr(self, targetName) self.args += ["edit", target, str(rdfile)] self.cli.invoke(self.args, strict=True) iids = self.get_target_imageids(target) print 'Got %d images' % len(iids) gw = BlitzGateway(client_obj=self.client) for iid in iids: # Get the updated object img = gw.getObject('Image', iid) channels = img.getChannels() assert len(channels) == sizec for c in xrange(len(channels)): self.assert_channel_rdef(channels[c], rd['channels'][c + 1]) self.assert_image_rmodel(img, expected_greyscale) img._closeRE() assert not gw._assert_unregistered("testEdit") # Once testEdit is no longer broken testEditSingleC could be merged into # it with sizec and greyscale parameters @pytest.mark.parametrize('targetName', sorted(SUPPORTED.keys())) @pytest.mark.parametrize('greyscale', [None, True, False]) def testEditSingleC(self, targetName, greyscale, tmpdir): sizec = 1 # 1 channel so should default to greyscale model expected_greyscale = ((greyscale is None) or greyscale) self.create_image(sizec=sizec) rd = self.get_render_def(sizec=sizec, greyscale=greyscale) rdfile = tmpdir.join('render-test-editsinglec.json') # Should work with json and yaml, but yaml is an optional dependency rdfile.write(json.dumps(rd)) target = getattr(self, targetName) self.args += ["edit", target, str(rdfile)] self.cli.invoke(self.args, strict=True) iids = self.get_target_imageids(target) print 'Got %d images' % len(iids) gw = BlitzGateway(client_obj=self.client) for iid in iids: # Get the updated object img = gw.getObject('Image', iid) # Note: calling _prepareRE below does NOT suffice! img._prepareRenderingEngine() # Call *before* getChannels # Passing noRE to getChannels below also prevents leaking # the RenderingEngine but then Nones are returned later. channels = img.getChannels() assert len(channels) == sizec for c in xrange(len(channels)): self.assert_channel_rdef(channels[c], rd['channels'][c + 1]) self.assert_image_rmodel(img, expected_greyscale) img._closeRE() assert not gw._assert_unregistered("testEditSingleC")