def testGridFSAssetstore(self): from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) # We should be able to read the metadata source = ImageItem().tileSource(item) metadata = source.getMetadata() self.assertEqual(metadata['sizeX'], 58368) self.assertEqual(metadata['sizeY'], 12288) self.assertEqual(metadata['levels'], 9)
def testGetSingleTile(self): from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) sourceRegion = { 'width': 0.7, 'height': 0.6, 'left': 0.15, 'top': 0.2, 'units': 'fraction' } sourceScale = {'magnification': 5} targetScale = {'magnification': 2.5} tile = source.getSingleTile(region=sourceRegion, scale=sourceScale, tile_position=25) self.assertEqual(tile['tile_position']['position'], 25) self.assertEqual(tile['tile_position']['level_x'], 8) self.assertEqual(tile['tile_position']['level_y'], 2) self.assertEqual(tile['tile_position']['region_x'], 4) self.assertEqual(tile['tile_position']['region_y'], 1) self.assertEqual(tile['iterator_range']['level_x_min'], 4) self.assertEqual(tile['iterator_range']['level_y_min'], 1) self.assertEqual(tile['iterator_range']['level_x_max'], 25) self.assertEqual(tile['iterator_range']['level_y_max'], 5) self.assertEqual(tile['iterator_range']['region_x_max'], 21) self.assertEqual(tile['iterator_range']['region_y_max'], 4) self.assertEqual(tile['iterator_range']['position'], 84) tile = source.getSingleTileAtAnotherScale(sourceRegion, sourceScale, targetScale, tile_position=25) self.assertEqual(tile['tile_position']['position'], 25) self.assertEqual(tile['tile_position']['level_x'], 5) self.assertEqual(tile['tile_position']['level_y'], 2) self.assertEqual(tile['tile_position']['region_x'], 3) self.assertEqual(tile['tile_position']['region_y'], 2) self.assertEqual(tile['iterator_range']['level_x_min'], 2) self.assertEqual(tile['iterator_range']['level_y_min'], 0) self.assertEqual(tile['iterator_range']['level_x_max'], 13) self.assertEqual(tile['iterator_range']['level_y_max'], 3) self.assertEqual(tile['iterator_range']['region_x_max'], 11) self.assertEqual(tile['iterator_range']['region_y_max'], 3) self.assertEqual(tile['iterator_range']['position'], 33)
def _getBound(self, item): minervaMeta = item['meta']['minerva'] if 'dataset_type' not in minervaMeta: return if (minervaMeta['dataset_type'] == 'geojson' or minervaMeta['dataset_type'] == 'geojson-timeseries'): geometry = None if minervaMeta['dataset_type'] == 'geojson': geometry = self.downloadDataset(item) if minervaMeta['dataset_type'] == 'geojson-timeseries': geometries = self.downloadDataset(item) geometry = geometries[0]['geojson'] geometry = unwrapFeature(geometry) geom = shape(geometry) return { 'lrx': geom.bounds[2], 'lry': geom.bounds[1], 'ulx': geom.bounds[0], 'uly': geom.bounds[3] } elif minervaMeta['dataset_type'] == 'geotiff': info = ImageItem().tileSource(item).getMetadata() bounds = info['bounds'] return { 'lrx': bounds['xmax'], 'lry': bounds['ymin'], 'ulx': bounds['xmin'], 'uly': bounds['ymax'] }
def testFilesystemAssetstore(self): from girder.plugins.large_image.models.image_item import ImageItem from girder.plugins.large_image.cache_util import cachesClear file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) file = File().load(item['largeImage']['fileId'], force=True) # With a second file, large image would prefer to use the Girder mount, # if available File().createLinkFile('second', item, 'item', 'http://nourl.com', self.admin) cachesClear() source = ImageItem().tileSource(item) # The file path should just be the local path self.assertEqual(source._getLargeImagePath(), File().getLocalFilePath(file))
def thumbnail(self, image, params): width = int(params.get('width', 256)) height = int(params.get('height', 256)) thumbData, thumbMime = ImageItem().getThumbnail(image, width=width, height=height) # Only setRawResponse now, as this handler may return a JSON error # earlier setRawResponse() setResponseHeader('Content-Type', thumbMime) return thumbData
def _generateLargeimage(self, image, originalFile): user = User().load(image['creatorId'], force=True, exc=True) # Use admin user, to ensure that worker always has access token = Token().createToken( user=getAdminUser(), days=1, scope=[TokenScope.DATA_READ, TokenScope.DATA_WRITE]) job = ImageItem().createImageItem(image, originalFile, user, token) return job
def testGridFSAssetstore(self): from girder.plugins.large_image.models.image_item import ImageItem from girder.plugins.large_image.tilesource import TileSourceException file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) # We should get an error that this isn't a large image with six.assertRaisesRegex(self, TileSourceException, 'No large image file in this item'): ImageItem().tileSource(item)
def getTile(self, image, z, x, y, params): try: x, y, z = int(x), int(y), int(z) except ValueError: raise RestException('x, y, and z must be integers') if x < 0 or y < 0 or z < 0: raise RestException('x, y, and z must be positive integers') try: tileData, tileMime = ImageItem().getTile(image, x, y, z) except TileGeneralException as e: raise RestException(e.message, code=404) setResponseHeader('Content-Type', tileMime) setRawResponse() return tileData
def testGetPixel(self): from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join( os.environ['LARGE_IMAGE_DATA'], 'sample_jp2k_33003_TCGA-CV-7242-' '11A-01-TS1.1838afb1-9eee-4a70-9ae3-50e3ab45e242.svs')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) pixel = source.getPixel(region={'left': 12125, 'top': 10640}) self.assertEqual(pixel, {'r': 156, 'g': 98, 'b': 138, 'a': 255}) pixel = source.getPixel(region={ 'left': 3.0555, 'top': 2.68128, 'units': 'mm' }) self.assertEqual(pixel, {'r': 156, 'g': 98, 'b': 138, 'a': 255}) pixel = source.getPixel(region={ 'top': 10640, 'right': 12126, 'bottom': 12000 }) self.assertEqual(pixel, {'r': 156, 'g': 98, 'b': 138, 'a': 255}) pixel = source.getPixel(region={ 'left': 12125, 'top': 10640, 'right': 13000 }) self.assertEqual(pixel, {'r': 156, 'g': 98, 'b': 138, 'a': 255}) pixel = source.getPixel(region={ 'left': 12125, 'top': 10640 }, includeTileRecord=True) self.assertIn('tile', pixel)
def testGetRegion(self): from girder.plugins.large_image import tilesource from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join( os.environ['LARGE_IMAGE_DATA'], 'sample_jp2k_33003_TCGA-CV-7242-' '11A-01-TS1.1838afb1-9eee-4a70-9ae3-50e3ab45e242.svs')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) # By default, getRegion gets an image image, mimeType = source.getRegion(scale={'magnification': 2.5}) self.assertEqual(mimeType, 'image/jpeg') self.assertEqual(image[:len(common.JPEGHeader)], common.JPEGHeader) # Adding a tile position request should be ignored image2, imageFormat = source.getRegion(scale={'magnification': 2.5}, tile_position=1) self.assertEqual(image, image2) # We should be able to get a NUMPY array instead image, imageFormat = source.getRegion( scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_NUMPY) self.assertEqual(imageFormat, tilesource.TILE_FORMAT_NUMPY) self.assertTrue(isinstance(image, numpy.ndarray)) self.assertEqual(image.shape, (1447, 1438, 4)) # We should be able to get a PIL image image, imageFormat = source.getRegion( scale={'magnification': 2.5}, format=(tilesource.TILE_FORMAT_PIL, tilesource.TILE_FORMAT_NUMPY)) self.assertEqual(imageFormat, tilesource.TILE_FORMAT_PIL) self.assertEqual(image.width, 1438) self.assertEqual(image.height, 1447)
def testConvertRegionScale(self): from girder.plugins.large_image import tilesource from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join( os.environ['LARGE_IMAGE_DATA'], 'sample_jp2k_33003_TCGA-CV-7242-' '11A-01-TS1.1838afb1-9eee-4a70-9ae3-50e3ab45e242.svs')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) # If we aren't using pixels as our units and don't specify a target # unit, this should do nothing. This source image is 23021 x 23162 sourceRegion = {'width': 0.8, 'height': 0.7, 'units': 'fraction'} targetRegion = source.convertRegionScale(sourceRegion) self.assertEqual(sourceRegion, targetRegion) # Units must be valid with six.assertRaisesRegex(self, ValueError, 'Invalid units'): source.convertRegionScale({'units': 'unknown'}) with six.assertRaisesRegex(self, ValueError, 'Invalid units'): source.convertRegionScale(sourceRegion, targetUnits='unknown') # We can convert to pixels targetRegion = source.convertRegionScale( sourceRegion, targetScale={'magnification': 2.5}, targetUnits='pixels') self.assertEqual(int(targetRegion['width']), 1151) self.assertEqual(int(targetRegion['height']), 1013) self.assertEqual(targetRegion['units'], 'mag_pixels') # Now use that to convert to a different magnification sourceRegion = targetRegion sourceScale = {'magnification': 2.5} # Test other conversions targetScale = {'magnification': 1.25} targetRegion = source.convertRegionScale(sourceRegion, sourceScale, targetScale) self.assertEqual(int(targetRegion['width']), 18417) self.assertEqual(int(targetRegion['height']), 16213) self.assertEqual(targetRegion['units'], 'base_pixels') targetRegion = source.convertRegionScale(sourceRegion, sourceScale, targetScale, targetUnits='fraction') self.assertAlmostEqual(targetRegion['width'], 0.8, places=4) self.assertAlmostEqual(targetRegion['height'], 0.7, places=4) self.assertEqual(targetRegion['units'], 'fraction') targetRegion = source.convertRegionScale(sourceRegion, sourceScale, targetScale, targetUnits='mm') self.assertAlmostEqual(targetRegion['width'], 4.6411, places=3) self.assertAlmostEqual(targetRegion['height'], 4.0857, places=3) self.assertEqual(targetRegion['units'], 'mm') targetRegion = source.convertRegionScale(sourceRegion, sourceScale, None, targetUnits='mm') self.assertAlmostEqual(targetRegion['width'], 4.6411, places=3) self.assertAlmostEqual(targetRegion['height'], 4.0857, places=3) self.assertEqual(targetRegion['units'], 'mm') # with six.assertRaisesRegex(self, ValueError, 'No mm_x'): # source.convertRegionScale( # sourceRegion, sourceScale, None, targetUnits='mm') targetRegion = source.convertRegionScale(sourceRegion, sourceScale, targetScale, targetUnits='pixels') self.assertEqual(int(targetRegion['width']), 575) self.assertEqual(int(targetRegion['height']), 506) self.assertEqual(targetRegion['units'], 'mag_pixels') # test getRegionAtAnotherScale image, imageFormat = source.getRegionAtAnotherScale( sourceRegion, sourceScale, targetScale, format=tilesource.TILE_FORMAT_NUMPY) self.assertEqual(imageFormat, tilesource.TILE_FORMAT_NUMPY) self.assertTrue(isinstance(image, numpy.ndarray)) self.assertEqual(image.shape, (506, 575, 4)) with six.assertRaisesRegex(self, TypeError, 'unexpected keyword'): source.getRegionAtAnotherScale(sourceRegion, sourceScale, region=sourceRegion, format=tilesource.TILE_FORMAT_NUMPY) # test tileIteratorAtAnotherScale tileCount = 0 for tile in source.tileIteratorAtAnotherScale( sourceRegion, sourceScale, targetScale, format=tilesource.TILE_FORMAT_NUMPY): tileCount += 1 self.assertEqual(tileCount, 72) with six.assertRaisesRegex(self, TypeError, 'unexpected keyword'): for tile in source.tileIteratorAtAnotherScale( sourceRegion, sourceScale, region=sourceRegion, format=tilesource.TILE_FORMAT_NUMPY): tileCount += 1
def getTileInfo(self, image, params): # These endpoints should guarantee that large_image functionality works, so a # TileGeneralException can be treated as an internal server error and not get caught return ImageItem().getMetadata(image)
def testThumbnailFileJob(self): from girder.plugins.large_image.models.image_item import ImageItem # Create files via a job file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) # We should report zero thumbnails item = Item().load(itemId, user=self.admin) present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 0) # Test PUT thumbnails resp = self.request(method='PUT', path='/large_image/thumbnails', user=self.user) self.assertStatus(resp, 403) resp = self.request(method='PUT', path='/large_image/thumbnails', user=self.admin) self.assertStatus(resp, 400) self.assertIn('spec', resp.json['message']) self.assertIn('is required', resp.json['message']) resp = self.request(method='PUT', path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps({})}) self.assertStatus(resp, 400) self.assertIn('must be a JSON list', resp.json['message']) # Run a job to create two sizes of thumbnails self.assertTrue( self._createThumbnails([{ 'width': 160, 'height': 100 }, { 'encoding': 'PNG' }])) # We should report two thumbnails present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 2) # Run a job to create two sizes of thumbnails, one different than # before self.assertTrue( self._createThumbnails([ { 'width': 160, 'height': 100 }, { 'width': 160, 'height': 160 }, ])) # We should report three thumbnails present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 3) # Asking for a bad thumbnail specification should just do nothing self.assertFalse(self._createThumbnails(['not a dictionary'])) present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 3) # Test GET thumbnails resp = self.request(path='/large_image/thumbnails', user=self.user) self.assertStatus(resp, 403) resp = self.request(path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps({})}) self.assertStatus(resp, 400) self.assertIn('must be a JSON list', resp.json['message']) resp = self.request(path='/large_image/thumbnails', user=self.admin) self.assertStatusOk(resp) self.assertEqual(resp.json, 3) resp = self.request( path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps([{ 'width': 160, 'height': 100 }])}) self.assertStatusOk(resp) self.assertEqual(resp.json, 1) # Test DELETE thumbnails resp = self.request(method='DELETE', path='/large_image/thumbnails', user=self.user) self.assertStatus(resp, 403) resp = self.request(method='DELETE', path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps({})}) self.assertStatus(resp, 400) self.assertIn('must be a JSON list', resp.json['message']) # Delete one set of thumbnails resp = self.request(method='DELETE', path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps([{ 'encoding': 'PNG' }])}) self.assertStatusOk(resp) present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 2) # Try to delete some that don't exist resp = self.request( method='DELETE', path='/large_image/thumbnails', user=self.admin, params={'spec': json.dumps([{ 'width': 200, 'height': 200 }])}) self.assertStatusOk(resp) present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 2) # Delete them all resp = self.request(method='DELETE', path='/large_image/thumbnails', user=self.admin) self.assertStatusOk(resp) present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertEqual(present, 0) # We should be able to cancel a job slowList = [ { 'width': 1600, 'height': 1000 }, { 'width': 3200, 'height': 2000 }, { 'width': 1600, 'height': 1002 }, { 'width': 1600, 'height': 1003 }, { 'width': 1600, 'height': 1004 }, ] self.assertEqual(self._createThumbnails(slowList, cancel=True), 'canceled') present, removed = ImageItem().removeThumbnailFiles(item, keep=10) self.assertLess(present, 3 + len(slowList))
def testTileIterator(self): from girder.plugins.large_image import tilesource from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join( os.environ['LARGE_IMAGE_DATA'], 'sample_jp2k_33003_TCGA-CV-7242-' '11A-01-TS1.1838afb1-9eee-4a70-9ae3-50e3ab45e242.svs')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) tileCount = 0 visited = {} for tile in source.tileIterator(format=tilesource.TILE_FORMAT_PIL, scale={'magnification': 5}): # Check that we haven't loaded the tile's image yet self.assertFalse(getattr(tile, 'loaded', None)) visited.setdefault(tile['level_x'], {})[tile['level_y']] = True tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 256 if tile['level_x'] < 11 else 61) self.assertEqual(tile['height'], 256 if tile['level_y'] < 11 else 79) # Check that we have loaded the tile's image self.assertTrue(getattr(tile, 'loaded', None)) self.assertEqual(tileCount, 144) self.assertEqual(len(visited), 12) self.assertEqual(len(visited[0]), 12) # Check with a non-native magnfication with exact=True tileCount = 0 for tile in source.tileIterator(scale={ 'magnification': 4, 'exact': True }): tileCount += 1 self.assertEqual(tileCount, 0) # Check with a non-native (but factor of 2) magnfication with exact=True for tile in source.tileIterator(scale={ 'magnification': 2.5, 'exact': True }): tileCount += 1 self.assertEqual(tileCount, 0) # Check with a native magnfication with exact=True for tile in source.tileIterator(scale={ 'magnification': 5, 'exact': True }): tileCount += 1 self.assertEqual(tileCount, 144) # Check with a non-native magnfication without resampling tileCount = 0 for tile in source.tileIterator(format=tilesource.TILE_FORMAT_PIL, scale={'magnification': 2}): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 256 if tile['level_x'] < 11 else 61) self.assertEqual(tile['height'], 256 if tile['level_y'] < 11 else 79) self.assertEqual(tileCount, 144) # Check with a non-native magnfication with resampling tileCount = 0 for tile in source.tileIterator(format=tilesource.TILE_FORMAT_PIL, scale={'magnification': 2}, resample=True): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 256 if tile['level_x'] < 4 else 126) self.assertEqual(tile['height'], 256 if tile['level_y'] < 4 else 134) self.assertEqual(tileCount, 25) # Ask for numpy array as results tileCount = 0 for tile in source.tileIterator(scale={'magnification': 5}): tileCount += 1 self.assertTrue(isinstance(tile['tile'], numpy.ndarray)) self.assertEqual(tile['tile'].shape, (256 if tile['level_y'] < 11 else 79, 256 if tile['level_x'] < 11 else 61, 4)) self.assertEqual(tile['tile'].dtype, numpy.dtype('uint8')) self.assertEqual(tileCount, 144) # Ask for either PIL or IMAGE data, we should get PIL data tileCount = 0 for tile in source.tileIterator(scale={'magnification': 5}, format=(tilesource.TILE_FORMAT_PIL, tilesource.TILE_FORMAT_IMAGE), encoding='JPEG'): tileCount += 1 self.assertTrue(isinstance(tile['tile'], PIL.Image.Image)) self.assertEqual(tileCount, 144) # Ask for PNGs tileCount = 0 for tile in source.tileIterator(scale={'magnification': 5}, format=tilesource.TILE_FORMAT_IMAGE, encoding='PNG'): tileCount += 1 self.assertFalse(isinstance(tile['tile'], PIL.Image.Image)) self.assertEqual(tile['tile'][:len(common.PNGHeader)], common.PNGHeader) self.assertEqual(tileCount, 144) # Use a ptif to test getting tiles as images file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) # Ask for either PIL or IMAGE data, we should get image data tileCount = 0 jpegTileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=(tilesource.TILE_FORMAT_PIL, tilesource.TILE_FORMAT_IMAGE), encoding='JPEG'): tileCount += 1 if not isinstance(tile['tile'], PIL.Image.Image): self.assertEqual(tile['tile'][:len(common.JPEGHeader)], common.JPEGHeader) jpegTileCount += 1 self.assertEqual(tileCount, 45) self.assertGreater(jpegTileCount, 0) # Ask for PNGs tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_IMAGE, encoding='PNG'): tileCount += 1 self.assertEqual(tile['tile'][:len(common.PNGHeader)], common.PNGHeader) self.assertEqual(tileCount, 45) # Ask for TIFFs tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_IMAGE, encoding='TIFF'): tileCount += 1 self.assertEqual(tile['tile'][:len(common.TIFFHeader)], common.TIFFHeader) self.assertEqual(tileCount, 45) # Test some internal properties self.assertEqual(len(source._tiffDirectories), 9) info = source._tiffDirectories[-1]._tiffInfo self.assertEqual(info['bitspersample'], 8) self.assertEqual(info['compression'], 7) self.assertEqual(info['imagelength'], 12288) self.assertEqual(info['imagewidth'], 58368) self.assertEqual(info['istiled'], 1) self.assertEqual(info['jpegcolormode'], 0) self.assertEqual(info['jpegquality'], 75) self.assertEqual(info['jpegtablesmode'], 3) self.assertEqual(info['orientation'], 1) self.assertEqual(info['photometric'], 6) self.assertEqual(info['planarconfig'], 1) self.assertEqual(info['samplesperpixel'], 3) self.assertEqual(info['tilelength'], 256) self.assertEqual(info['tilewidth'], 256)
def _updateMinervaMetadata(self, item): minerva_metadata = { 'source_type': 'item' } for file in self.model('item').childFiles(item=item, limit=0): # Check the first few k of a file to see if this might be a # geojson timeseries. Crudely, we expect this to be a json array # which contains objects, each of which has at least a geojson # element. This test will fail if there are other elements in the # first object that push the geojson element beyond the tested # header length. It could give a false positive, too. The correct # way would be to download and parse the whole file, but that would # be more expensive in memory and time. headerLen = 2048 fileHeader = '' for headerData in self.model('file').download(file, headers=False, endByte=headerLen)(): fileHeader = (fileHeader + headerData)[:headerLen] if len(fileHeader) >= headerLen: break if (fileHeader.lstrip()[:1] == '[' and fileHeader.lstrip()[1:].lstrip()[:1] == '{' and '"geojson"' in fileHeader): minerva_metadata['original_type'] = 'geojson-timeseries' minerva_metadata['dataset_type'] = 'geojson-timeseries' minerva_metadata['original_files'] = [{ 'name': file['name'], '_id': file['_id']}] minerva_metadata['geojson_file'] = { 'name': file['name'], '_id': file['_id']} minerva_metadata['source'] = { 'layer_source': 'GeoJSON'} break # TODO This switching based on which file is found first is # fairly brittle and should only be called after first upload. if 'geojson' in file['exts']: # we found a geojson, assume this is geojson original minerva_metadata['original_type'] = 'geojson' minerva_metadata['dataset_type'] = 'geojson' minerva_metadata['original_files'] = [{ 'name': file['name'], '_id': file['_id']}] minerva_metadata['geojson_file'] = { 'name': file['name'], '_id': file['_id']} minerva_metadata['source'] = { 'layer_source': 'GeoJSON'} break elif 'json' in file['exts']: minerva_metadata['original_type'] = 'json' minerva_metadata['dataset_type'] = 'json' minerva_metadata['original_files'] = [{ 'name': file['name'], '_id': file['_id']}] break elif 'csv' in file['exts']: minerva_metadata['original_type'] = 'csv' minerva_metadata['dataset_type'] = 'csv' minerva_metadata['original_files'] = [{ 'name': file['name'], '_id': file['_id']}] break elif ({'tif', 'tiff'}.intersection(file['exts']) and file['mimeType'] == 'image/tiff'): info = ImageItem().tileSource(item).getMetadata() if 'srs' in info['sourceBounds'] and info['sourceBounds']['srs']: minerva_metadata['original_type'] = 'tiff' minerva_metadata['dataset_type'] = 'geotiff' minerva_metadata['original_files'] = [{ 'name': file['name'], '_id': file['_id']}] minerva_metadata['source'] = { 'layer_source': 'Tiff'} break updateMinervaMetadata(item, minerva_metadata) return minerva_metadata
def testTileIteratorRetiling(self): from girder.plugins.large_image import tilesource from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) # Test retiling to 500 x 400 tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_PIL, tile_size={ 'width': 500, 'height': 400 }): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 500 if tile['level_x'] < 7 else 148) self.assertEqual(tile['height'], 400 if tile['level_y'] < 1 else 368) self.assertEqual(tileCount, 16) # Test retiling to 300 x 275 with 50 x 40 pixels overlap with trimmed # edges tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_PIL, tile_size={ 'width': 300, 'height': 275 }, tile_overlap={ 'x': 50, 'y': 40, 'edges': True }): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual( tile['width'], 275 if not tile['level_x'] else 300 if tile['level_x'] < 14 else 173) self.assertEqual( tile['height'], 255 if not tile['level_y'] else 275 if tile['level_y'] < 3 else 83) self.assertEqual(tile['tile_overlap']['left'], 0 if not tile['level_x'] else 25) self.assertEqual(tile['tile_overlap']['right'], 25 if tile['level_x'] < 14 else 0) self.assertEqual(tile['tile_overlap']['top'], 0 if not tile['level_y'] else 20) self.assertEqual(tile['tile_overlap']['bottom'], 20 if tile['level_y'] < 3 else 0) self.assertEqual(tileCount, 60) # Test retiling to 300 x 275 with 50 x 40 pixels overlap without # trimmed edges tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_PIL, tile_size={ 'width': 300, 'height': 275 }, tile_overlap={ 'x': 50, 'y': 40 }): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 300 if tile['level_x'] < 14 else 148) self.assertEqual(tile['height'], 275 if tile['level_y'] < 3 else 63) self.assertEqual(tile['tile_overlap']['left'], 0 if not tile['level_x'] else 25) self.assertEqual(tile['tile_overlap']['right'], 25 if tile['level_x'] < 14 else 0) self.assertEqual(tile['tile_overlap']['top'], 0 if not tile['level_y'] else 20) self.assertEqual(tile['tile_overlap']['bottom'], 20 if tile['level_y'] < 3 else 0) self.assertEqual(tileCount, 60) # Test retiling to 300 x 275 with 51 x 41 pixels overlap with trimmed # edges tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_PIL, tile_size={ 'width': 300, 'height': 275 }, tile_overlap={ 'x': 51, 'y': 41, 'edges': True }): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual( tile['width'], 275 if not tile['level_x'] else 300 if tile['level_x'] < 14 else 187) self.assertEqual( tile['height'], 255 if not tile['level_y'] else 275 if tile['level_y'] < 3 else 86) self.assertEqual(tile['tile_overlap']['left'], 0 if not tile['level_x'] else 25) self.assertEqual(tile['tile_overlap']['right'], 26 if tile['level_x'] < 14 else 0) self.assertEqual(tile['tile_overlap']['top'], 0 if not tile['level_y'] else 20) self.assertEqual(tile['tile_overlap']['bottom'], 21 if tile['level_y'] < 3 else 0) self.assertEqual(tileCount, 60) # Test retiling to 300 x 275 with 51 x 41 pixels overlap without # trimmed edges tileCount = 0 for tile in source.tileIterator(scale={'magnification': 2.5}, format=tilesource.TILE_FORMAT_PIL, tile_size={ 'width': 300, 'height': 275 }, tile_overlap={ 'x': 51, 'y': 41 }): tileCount += 1 self.assertEqual(tile['tile'].size, (tile['width'], tile['height'])) self.assertEqual(tile['width'], 300 if tile['level_x'] < 14 else 162) self.assertEqual(tile['height'], 275 if tile['level_y'] < 3 else 66) self.assertEqual(tile['tile_overlap']['left'], 0 if not tile['level_x'] else 25) self.assertEqual(tile['tile_overlap']['right'], 26 if tile['level_x'] < 14 else 0) self.assertEqual(tile['tile_overlap']['top'], 0 if not tile['level_y'] else 20) self.assertEqual(tile['tile_overlap']['bottom'], 21 if tile['level_y'] < 3 else 0) self.assertEqual(tileCount, 60)
def testTileIteratorSingleTile(self): from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join(os.environ['LARGE_IMAGE_DATA'], 'sample_image.ptif')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) # Test getting a single tile sourceRegion = { 'width': 0.7, 'height': 0.6, 'left': 0.15, 'top': 0.2, 'units': 'fraction' } tileCount = 0 for tile in source.tileIterator(region=sourceRegion, scale={'magnification': 5}, tile_position=25): tileCount += 1 self.assertEqual(tile['tile_position']['position'], 25) self.assertEqual(tile['tile_position']['level_x'], 8) self.assertEqual(tile['tile_position']['level_y'], 2) self.assertEqual(tile['tile_position']['region_x'], 4) self.assertEqual(tile['tile_position']['region_y'], 1) self.assertEqual(tile['iterator_range']['level_x_min'], 4) self.assertEqual(tile['iterator_range']['level_y_min'], 1) self.assertEqual(tile['iterator_range']['level_x_max'], 25) self.assertEqual(tile['iterator_range']['level_y_max'], 5) self.assertEqual(tile['iterator_range']['region_x_max'], 21) self.assertEqual(tile['iterator_range']['region_y_max'], 4) self.assertEqual(tile['iterator_range']['position'], 84) self.assertEqual(tileCount, 1) tiles = list( source.tileIterator(region=sourceRegion, scale={'magnification': 5}, tile_position={'position': 25})) self.assertEqual(len(tiles), 1) self.assertEqual(tiles[0]['tile_position']['position'], 25) tiles = list( source.tileIterator(region=sourceRegion, scale={'magnification': 5}, tile_position={ 'level_x': 8, 'level_y': 2 })) self.assertEqual(len(tiles), 1) self.assertEqual(tiles[0]['tile_position']['position'], 25) tiles = list( source.tileIterator(region=sourceRegion, scale={'magnification': 5}, tile_position={ 'region_x': 4, 'region_y': 1 })) self.assertEqual(len(tiles), 1) self.assertEqual(tiles[0]['tile_position']['position'], 25) tiles = list( source.tileIterator(region=sourceRegion, scale={'magnification': 5}, tile_position={'position': 90})) self.assertEqual(len(tiles), 0)
def testMagnification(self): from girder.plugins.large_image.models.image_item import ImageItem file = self._uploadFile( os.path.join( os.environ['LARGE_IMAGE_DATA'], 'sample_jp2k_33003_TCGA-CV-7242-' '11A-01-TS1.1838afb1-9eee-4a70-9ae3-50e3ab45e242.svs')) itemId = str(file['itemId']) item = Item().load(itemId, user=self.admin) source = ImageItem().tileSource(item) mag = source.getNativeMagnification() self.assertEqual(mag['magnification'], 40.0) self.assertEqual(mag['mm_x'], 0.000252) self.assertEqual(mag['mm_y'], 0.000252) mag = source.getMagnificationForLevel() self.assertEqual(mag['magnification'], 40.0) self.assertEqual(mag['mm_x'], 0.000252) self.assertEqual(mag['mm_y'], 0.000252) self.assertEqual(mag['level'], 7) self.assertEqual(mag['scale'], 1.0) mag = source.getMagnificationForLevel(0) self.assertEqual(mag['magnification'], 0.3125) self.assertEqual(mag['mm_x'], 0.032256) self.assertEqual(mag['mm_y'], 0.032256) self.assertEqual(mag['level'], 0) self.assertEqual(mag['scale'], 128.0) self.assertEqual(source.getLevelForMagnification(), 7) self.assertEqual(source.getLevelForMagnification(exact=True), 7) self.assertEqual(source.getLevelForMagnification(40), 7) self.assertEqual(source.getLevelForMagnification(20), 6) self.assertEqual(source.getLevelForMagnification(0.3125), 0) self.assertEqual(source.getLevelForMagnification(15), 6) self.assertEqual(source.getLevelForMagnification(25), 6) self.assertEqual(source.getLevelForMagnification(15, rounding='ceil'), 6) self.assertEqual(source.getLevelForMagnification(25, rounding='ceil'), 7) self.assertEqual(source.getLevelForMagnification(15, rounding=False), 5.585) self.assertEqual(source.getLevelForMagnification(25, rounding=False), 6.3219) self.assertEqual(source.getLevelForMagnification(45, rounding=False), 7) self.assertEqual(source.getLevelForMagnification(15, rounding=None), 5.585) self.assertEqual(source.getLevelForMagnification(25, rounding=None), 6.3219) self.assertEqual(source.getLevelForMagnification(45, rounding=None), 7.1699) self.assertEqual(source.getLevelForMagnification(mm_x=0.0005), 6) self.assertEqual( source.getLevelForMagnification(mm_x=0.0005, mm_y=0.002), 5) self.assertEqual( source.getLevelForMagnification(mm_x=0.0005, exact=True), None) self.assertEqual( source.getLevelForMagnification(mm_x=0.000504, exact=True), 6) self.assertEqual(source.getLevelForMagnification(80), 7) self.assertEqual(source.getLevelForMagnification(80, exact=True), None) self.assertEqual(source.getLevelForMagnification(0.1), 0)