def cacheMissXY ( self, res, xtile, ytile, zslice ): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) xstart = xtile*self.tilesz ystart = ytile*self.tilesz xend = min ((xtile+1)*self.tilesz,self.proj.datasetcfg.imageSize(res)[0][0]) yend = min ((ytile+1)*self.tilesz,self.proj.datasetcfg.imageSize(res)[0][1]) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(res, xstart, xend, ystart, yend, zslice, zslice+1) tiledata = None for index, channel_name in enumerate(self.channel_list): ch = self.proj.getChannelObj(channel_name) cutout = ocpcarest.cutout(imageargs, ch, self.proj, self.db) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros((len(self.channel_list), cutout.data.shape[0], self.tilesz, self.tilesz), dtype=cutout.data.dtype) tiledata[index, 0, 0:((yend-1)%self.tilesz+1), 0:((xend-1)%self.tilesz+1)] = cutout.data[0, :, :] tiledata[index,:] = ocpcarest.window(tiledata[index,:], ch) # We have an compound array. Now color it. return mcfc.mcfcPNG (tiledata.reshape((tiledata.shape[0],tiledata.shape[2],tiledata.shape[3])), self.colors)
def cacheMissXZ ( self, res, xtile, yslice, ztile ): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) xstart = xtile * self.tilesz xend = min ((xtile+1) * self.tilesz, self.proj.datasetcfg.imageSize(res)[0][0]) # z cutouts need to get rescaled # we'll map to the closest pixel range and tolerate one pixel error at the boundary scalefactor = self.proj.datasetcfg.getScale()[res]['xz'] zoffset = self.proj.datasetcfg.getOffset()[res][2] ztilestart = int((ztile*self.tilesz)/scalefactor) + zoffset zstart = max ( ztilestart, zoffset ) ztileend = int(math.ceil(((ztile+1)*self.tilesz)/scalefactor)) + zoffset zend = min ( ztileend, self.proj.datasetcfg.imageSize(res)[0][2] ) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(res, xstart, xend, yslice, yslice+1, zstart, zend) tiledata = None for index,channel_name in enumerate(self.channel_list): ch = self.proj.getChannelObj(channel_name) cutout = ocpcarest.cutout(imageargs, ch, self.proj, self.db) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros((len(self.channel_list), zend-zstart, cutout.data.shape[1], self.tilesz), dtype=cutout.data.dtype) tiledata[index, 0:zend-zstart, 0, 0:((xend-1)%self.tilesz+1)] = cutout.data[:, 0, :] tiledata = ocpcarest.window(tiledata, ch) # We have an compound array. Now color it. img = mcfc.mcfcPNG (tiledata.reshape((tiledata.shape[0],tiledata.shape[1],tiledata.shape[3])), self.colors) return img.resize ((self.tilesz,self.tilesz))
def cacheMissXY(self, res, xtile, ytile, zslice): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) xstart = xtile * self.tilesz ystart = ytile * self.tilesz xend = min((xtile + 1) * self.tilesz, self.proj.datasetcfg.imageSize(res)[0][0]) yend = min((ytile + 1) * self.tilesz, self.proj.datasetcfg.imageSize(res)[0][1]) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(res, xstart, xend, ystart, yend, zslice, zslice + 1) tiledata = None for index, channel_name in enumerate(self.channel_list): ch = self.proj.getChannelObj(channel_name) cutout = ocpcarest.cutout(imageargs, ch, self.proj, self.db) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros( (len(self.channel_list), cutout.data.shape[0], self.tilesz, self.tilesz), dtype=cutout.data.dtype) tiledata[index, 0, 0:((yend - 1) % self.tilesz + 1), 0:((xend - 1) % self.tilesz + 1)] = cutout.data[0, :, :] tiledata[index, :] = ocpcarest.window(tiledata[index, :], ch) # We have an compound array. Now color it. return mcfc.mcfcPNG( tiledata.reshape( (tiledata.shape[0], tiledata.shape[2], tiledata.shape[3])), self.colors)
def tile2WebPNG(self, xdim, ydim, tile): """Create PNG Images and write to cache for the specified tile""" # Check if it is mcfc tile if self.colors is not None: return mcfcPNG(tile, self.colors, enhancement=4.0) # If it is not a mcfc tile else: ch = self.ds.getChannelObj(self.channels[0]) # write it as a png file if ch.getChannelType() in IMAGE_CHANNELS + TIMESERIES_CHANNELS: if ch.getChannelDataType() in DTYPE_uint8: return Image.frombuffer ( 'L', [xdim,ydim], tile.flatten(), 'raw', 'L', 0, 1 ) elif ch.getChannelDataType() in DTYPE_uint16: if ch.getWindowRange() != [0,0]: tile = np.uint8(tile) return Image.frombuffer ( 'L', [xdim,ydim], tile.flatten(), 'raw', 'L', 0, 1 ) else: outimage = Image.frombuffer ( 'I;16', [xdim,ydim], tile.flatten(), 'raw', 'I;16', 0, 1) return outimage.point(lambda i:i*(1./256)).convert('L') elif ch.getChannelDataType() in DTYPE_uint32 : return Image.fromarray( tile[0,:,:], 'RGBA') elif ch.getChannelType() in ANNOTATION_CHANNELS: tile = tile[0,:] ndlib.recolor_ctype(tile, tile) return Image.frombuffer ( 'RGBA', [xdim,ydim], tile.flatten(), 'raw', 'RGBA', 0, 1 ) else : logger.warning("Datatype not yet supported".format(ch.channel_type))
def cacheMissXY ( self, resolution, xtile, ytile, zslice ): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) xstart = xtile*self.tilesz ystart = ytile*self.tilesz xend = min ((xtile+1)*self.tilesz,self.proj.datasetcfg.imagesz[resolution][0]) yend = min ((ytile+1)*self.tilesz,self.proj.datasetcfg.imagesz[resolution][1]) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(resolution,xstart,xend,ystart,yend,zslice,zslice+1) tiledata = None for i in range(len(self.channels)): cutout = ocpcarest.cutout ( imageargs, self.proj, self.db, self.channels[i] ) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros((len(self.channels), cutout.data.shape[0],self.tilesz,self.tilesz), dtype=cutout.data.dtype) tiledata[i,0,0:((yend-1)%self.tilesz+1),0:((xend-1)%self.tilesz+1)] = cutout.data[0,:,:] # reduction factor. How to scale data. 16 bit->8bit, or windowed (startwindow,endwindow) = self.proj.datasetcfg.windowrange if self.proj.getDBType() == ocpcaproj.CHANNELS_16bit and ( startwindow == endwindow == 0): tiledata = np.uint8(tiledata * 1.0/256) elif self.proj.getDBType() == ocpcaproj.CHANNELS_16bit and ( endwindow!=0 ): from windowcutout import windowCutout windowCutout ( tiledata, (startwindow, endwindow) ) # We have an compound array. Now color it. colors = ('C','M','Y','R','G','B') return mcfc.mcfcPNG ( tiledata.reshape((tiledata.shape[0],tiledata.shape[2],tiledata.shape[3])), colors )
def cacheMissYZ(self, res, xtile, ytile, ztile): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) ystart = ytile * self.tilesz yend = min((ytile + 1) * self.tilesz, self.proj.datasetcfg.imageSize(res)[0][1]) # z cutouts need to get rescaled # we'll map to the closest pixel range and tolerate one pixel error at the boundary scalefactor = self.proj.datasetcfg.getScale()[res]['yz'] zoffset = self.proj.datasetcfg.getOffset()[res][2] ztilestart = int((ztile * self.tilesz) / scalefactor) + zoffset zstart = max(ztilestart, zoffset) ztileend = int(math.ceil( ((ztile + 1) * self.tilesz) / scalefactor)) + zoffset zend = min(ztileend, self.proj.datasetcfg.imageSize(res)[0][2]) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(res, xtile, xtile + 1, ystart, yend, zstart, zend) tiledata = None for index, channel_name in enumerate(self.channel_list): ch = self.proj.getChannelObj(channel_name) cutout = ocpcarest.cutout(imageargs, ch, self.proj, self.db) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros( (len(self.channel_list), ztileend - ztilestart, self.tilesz, cutout.data.shape[2]), dtype=cutout.data.dtype) tiledata[index, 0:zend - zstart, 0:((yend - 1) % self.tilesz + 1), 0] = cutout.data[:, :, 0] tiledata = ocpcarest.window(tiledata, ch) # We have an compound array. Now color it. img = mcfc.mcfcPNG( tiledata.reshape( (tiledata.shape[0], tiledata.shape[1], tiledata.shape[2])), self.colors) return img.resize((self.tilesz, self.tilesz))
def cacheMissXZ ( self, resolution, xtile, yslice, ztile ): """On a miss. Cutout, return the image and load the cache in a background thread""" # figure out the cutout (limit to max image size) xstart = xtile*self.tilesz xend = min ((xtile+1)*self.tilesz,self.proj.datasetcfg.imagesz[resolution][0]) # z cutouts need to get rescaled # we'll map to the closest pixel range and tolerate one pixel error at the boundary scalefactor = self.proj.datasetcfg.zscale[resolution] zoffset = self.proj.datasetcfg.slicerange[0] ztilestart = int((ztile*self.tilesz)/scalefactor) + zoffset zstart = max ( ztilestart, zoffset ) ztileend = int(math.ceil(((ztile+1)*self.tilesz)/scalefactor)) + zoffset zend = min ( ztileend, self.proj.datasetcfg.slicerange[1] ) # call the mcfc interface imageargs = '{}/{},{}/{},{}/{},{}/'.format(resolution,xstart,xend,yslice,yslice+1,zstart,zend) tiledata = None for i in range(len(self.channels)): cutout = ocpcarest.cutout ( imageargs, self.proj, self.db, self.channels[i] ) # initialize the tiledata by type if tiledata == None: tiledata = np.zeros((len(self.channels), zend-zstart, cutout.data.shape[1],self.tilesz), dtype=cutout.data.dtype) tiledata[i,0:zend-zstart,0,0:((xend-1)%self.tilesz+1)] = cutout.data[:,0,:] # reduction factor. How to scale data. 16 bit->8bit, or windowed (startwindow,endwindow) = self.proj.datasetcfg.windowrange if self.proj.getDBType() == ocpcaproj.CHANNELS_16bit and ( startwindow == endwindow == 0): tiledata = np.uint8(tiledata * 1.0/256) elif self.proj.getDBType() == ocpcaproj.CHANNELS_16bit and ( endwindow!=0 ): from windowcutout import windowCutout windowCutout ( tiledata, (startwindow, endwindow) ) # We have an compound array. Now color it. colors = ('C','M','Y','R','G','B') img = mcfc.mcfcPNG ( tiledata.reshape((tiledata.shape[0],tiledata.shape[1],tiledata.shape[3])), colors ) return img.resize ((self.tilesz,self.tilesz))
def fetch (self): """Retrieve the tile from the cache or load the cache and return""" try: # open file and return f = open(self.filename) self.db.touch (self.tkey) return f.read() except IOError: pass try: self.initForFetch() except OOBException: logger.warning("OOB request. Returning black tile. url={}".format(self.tile_url)) img = Image.new("L", (settings.TILESIZE, settings.TILESIZE)) fileobj = cStringIO.StringIO() img.save(fileobj, "PNG") fileobj.seek(0) return fileobj.read() from tasks import fetchcube # check if there is S3 backend and do the calls accordingly if self.ds.getS3Backend(): s3_backend = s3io.S3IO(self.ds, self.channels) cubedata = s3_backend.getCutout(self.cuboid_url) tile_data = cubedata[:, self.zslab_offset, : ,:] # fetchcube(self.token, self.slice_type, self.channels, self.colors, self.cuboid_url, cubedata) fetchcube.delay (self.token, self.slice_type, self.channels, self.colors, self.cuboid_url, cubedata) ch = self.ds.getChannelObj(self.channels[0]) # checking the channel type to process the data correctly if self.colors: img = mcfc.mcfcPNG (tile_data, self.colors) elif ch.getChannelType() in IMAGE_CHANNELS + TIMESERIES_CHANNELS: if ch.getChannelDataType() in DTYPE_uint8: img = Image.frombuffer('L', tile_data.shape[1:][::-1], tile_data.flatten(), 'raw', 'L', 0, 1) elif ch.getChannelDataType() in DTYPE_uint16: if ch.getWindowRange() != [0,0]: tile_data = np.uint8(tile_data) img = Image.frombuffer('L', tile_data.shape[1:][::-1], tile_data.flatten(), 'raw', 'L', 0, 1) else: img = Image.frombuffer ( 'I;16', tile_data.shape[1:][::-1], tile_data.flatten(), 'raw', 'I;16', 0, 1) img.point(lambda i:i*(1./256)).convert('L') elif ch.getChannelDataType() in DTYPE_uint32 : img = Image.fromarray( tile_data[0,:,:], 'RGBA') elif ch.getChannelType() in ANNOTATION_CHANNELS: tile_data = tile_data[0,:] ndlib.recolor_ctype(tile_data, tile_data) img = Image.frombuffer('RGBA', tile_data.shape[1:][::-1], tile_data.flatten(), 'raw', 'RGBA', 0, 1) fileobj = cStringIO.StringIO() img.save ( fileobj, "PNG" ) fileobj.seek(0) return fileobj.read() else: # call the celery process to fetch the url #fetchurl (self.token, self.slice_type, self.channels, self.colors, self.cuboid_url) fetchcube.delay (self.token, self.slice_type, self.channels, self.colors, self.cuboid_url) # fetchcube (self.token, self.slice_type, self.channels, self.colors, self.cuboid_url) logger.warning("Tile fetch {}".format(self.tile_url)) return getURL(self.tile_url).read()