Skip to content

Commit

Permalink
release v0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
lucalianas committed Mar 22, 2016
2 parents acfa026 + f4ff3b0 commit e3b45f5
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 152 deletions.
18 changes: 11 additions & 7 deletions images_cache/cache_interface.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from ome_seadragon import settings

from abc import ABCMeta, abstractmethod


Expand All @@ -10,13 +12,15 @@ def _get_tile_key(self, image_id, level, column, row, tile_size, image_format,
image_quality=None):
if image_quality:
image_format = '%s%s' % (image_format, image_quality)
return 'TILE::IMG_%s|L_%s|C_%s-R_%s|S_%spx|F_%s' % (image_id, level, column, row,
tile_size, image_format.upper())
return 'TILE::IMG_%s|L_%s|C_%s-R_%s|S_%spx|F_%s|E_%s' % (image_id, level, column, row,
tile_size, image_format.upper(),
settings.TILES_RENDERING_ENGINE)

@abstractmethod
def _get_thumbnail_key(self, image_id, image_width, image_height, image_format):
return 'THUMB::IMG_%s|W_%spx-H_%spx|F_%s' % (image_id, image_width, image_height,
image_format.upper())
def _get_thumbnail_key(self, image_id, thumbnail_size, image_format):
return 'THUMB::IMG_%s|S_%spx|F_%s|E_%s' % (image_id, thumbnail_size,
image_format.upper(),
settings.THUMBNAILS_RENDERING_ENGINE)

@abstractmethod
def tile_to_cache(self, image_id, image_obj, level, column, row, tile_size, image_format,
Expand All @@ -29,9 +33,9 @@ def tile_from_cache(self, image_id, level, column, row, tile_size, image_format,
pass

@abstractmethod
def thumbnail_to_cache(self, image_id, image_obj, image_width, image_height, image_format):
def thumbnail_to_cache(self, image_id, image_obj, thumbnail_size, image_format):
pass

@abstractmethod
def thumbnail_from_cache(self, image_id, image_width, image_height, image_format):
def thumbnail_from_cache(self, image_id, thumbnail_size, image_format):
pass
6 changes: 3 additions & 3 deletions images_cache/fake_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def _get_tile_key(self, image_id, level, column, row, tile_size, image_format,
image_quality=None):
pass

def _get_thumbnail_key(self, image_id, image_width, image_height, image_format):
def _get_thumbnail_key(self, image_id, thumbnail_size, image_format):
pass

def tile_to_cache(self, image_id, image_obj, level, column, row, tile_size, image_format,
Expand All @@ -21,8 +21,8 @@ def tile_from_cache(self, image_id, level, column, row, tile_size, image_format,
image_quality=None):
return None

def thumbnail_to_cache(self, image_id, image_obj, image_width, image_height, image_format):
def thumbnail_to_cache(self, image_id, image_obj, thumbnail_size, image_format):
pass

def thumbnail_from_cache(self, image_id, image_width, image_height, image_format):
def thumbnail_from_cache(self, image_id, thumbnail_size, image_format):
return None
14 changes: 6 additions & 8 deletions images_cache/redis_img_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ def _get_tile_key(self, image_id, level, column, row, tile_size, image_format,
tile_size, image_format,
image_quality)

def _get_thumbnail_key(self, image_id, image_width, image_height, image_format):
return super(RedisCache, self)._get_thumbnail_key(image_id, image_width,
image_height, image_format)
def _get_thumbnail_key(self, image_id, thumbnail_size, image_format):
return super(RedisCache, self)._get_thumbnail_key(image_id, thumbnail_size, image_format)

def tile_to_cache(self, image_id, image_obj, level, column, row, tile_size, image_format,
image_quality=None):
Expand Down Expand Up @@ -49,16 +48,15 @@ def tile_from_cache(self, image_id, level, column, row, tile_size, image_format,
self.logger.info('No tile')
return None

def thumbnail_to_cache(self, image_id, image_obj, image_width, image_height, image_format):
def thumbnail_to_cache(self, image_id, image_obj, thumbnail_size, image_format):
out_buffer = StringIO()
image_obj.save(out_buffer, image_format)
th_key = self._get_thumbnail_key(image_id, image_width,
image_height, image_format)
th_key = self._get_thumbnail_key(image_id, thumbnail_size, image_format)
self.client.set(th_key, out_buffer.getvalue())
self._set_expire_time(th_key)

def thumbnail_from_cache(self, image_id, image_width, image_height, image_format):
th_key = self._get_thumbnail_key(image_id, image_width, image_height, image_format)
def thumbnail_from_cache(self, image_id, thumbnail_size, image_format):
th_key = self._get_thumbnail_key(image_id, thumbnail_size, image_format)
self.logger.info('Thumbnail from cache: %s' % th_key)
img_str = self.client.get(th_key)
if img_str:
Expand Down
35 changes: 25 additions & 10 deletions ome_data/projects_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,19 @@ def _get_image_resolution(image_object):
return image_object.getSizeX() * image_object.getSizeY()


def _project_to_json(project_object, datasets_map=None):
def get_fileset_highest_resolution(image_object, connection):
fs = connection.getObject('Fileset', image_object.getFileset().getId())
big_image = None
for tmp_img in fs.copyImages():
if big_image is None:
big_image = tmp_img
else:
if (tmp_img.getSizeX() * tmp_img.getSizeY()) > (big_image.getSizeX() * big_image.getSizeY()):
big_image = tmp_img
return big_image


def _project_to_json(project_object, connection, datasets_map=None):
prj_json = {
'id': project_object.getId(),
'name': project_object.getName(),
Expand All @@ -22,11 +34,11 @@ def _project_to_json(project_object, datasets_map=None):
}
if datasets_map is not None:
for dset, imgs in datasets_map:
prj_json['datasets'].append(_dataset_to_json(dset, imgs))
prj_json['datasets'].append(_dataset_to_json(dset, connection, imgs))
return prj_json


def _dataset_to_json(dataset_object, image_objects=None):
def _dataset_to_json(dataset_object, connection, image_objects=None):
dset_obj = {
'id': dataset_object.getId(),
'type': dataset_object.OMERO_CLASS,
Expand All @@ -37,11 +49,11 @@ def _dataset_to_json(dataset_object, image_objects=None):
}
if image_objects is not None:
for img_obj in image_objects:
dset_obj['images'].append(_image_to_json(img_obj))
dset_obj['images'].append(_image_to_json(img_obj, connection))
return dset_obj


def _image_to_json(image_object, full_info=False, roi_objects=None):
def _image_to_json(image_object, connection, full_info=False, roi_objects=None):
img_obj = {
'id': image_object.getId(),
'type': 'image',
Expand All @@ -53,7 +65,8 @@ def _image_to_json(image_object, full_info=False, roi_objects=None):
'creationTime': _date_to_timestamp(image_object.getDate()),
'importTime': _date_to_timestamp(image_object.creationEventDate()),
'lastUpdate': _date_to_timestamp(image_object.updateEventDate()),
'rois': []
'rois': [],
'high_resolution_image': get_fileset_highest_resolution(image_object, connection).getId()
}
if full_info:
img_obj.update({
Expand Down Expand Up @@ -101,7 +114,8 @@ def get_projects(connection, fetch_datasets=False):
datasets = list(proj.listChildren())
else:
datasets = []
projects_json.append(_project_to_json(proj, ((d, []) for d in datasets)))
projects_json.append(_project_to_json(proj, connection=connection,
datasets_map=((d, []) for d in datasets)))
return projects_json


Expand All @@ -119,7 +133,8 @@ def get_project(connection, project_id, fetch_datasets=False, fetch_images=False
else:
images = []
datasets_map.append((ds, images))
return _project_to_json(project, datasets_map)
return _project_to_json(project, datasets_map=datasets_map,
connection=connection)
return None


Expand All @@ -131,7 +146,7 @@ def get_dataset(connection, dataset_id, fetch_images=False, expand_img_series=Fa
images = _get_images_for_dataset(dataset, not expand_img_series)
else:
images = []
return _dataset_to_json(dataset, images)
return _dataset_to_json(dataset, connection=connection, image_objects=images)
return None


Expand All @@ -145,5 +160,5 @@ def get_image(connection, image_id, fetch_rois=False):
rois = list(results.rois)
else:
rois = []
return _image_to_json(img, True, rois)
return _image_to_json(img, connection, True, rois)
return None
2 changes: 1 addition & 1 deletion ome_data/tags_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _get_images_by_tag(tag_id, connection):
imgs_generator = connection.getObjectsByAnnotations('Image', [tag_id])
images = list()
for img in imgs_generator:
images.append(_image_to_json(img))
images.append(_image_to_json(img, connection))
return images


Expand Down
4 changes: 4 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def time_dict_to_seconds(value):
# <ome_home>/bin/omero config set omero.web.ome_seadragon.repository $(<ome_home>/bin/omero config get omero.data.dir)
'omero.web.ome_seadragon.repository': ['IMGS_REPOSITORY', None, identity, None],
'omero.web.ome_seadragon.images_folder': ['IMGS_FOLDER', 'ManagedRepository', identity, None],
# default rendering engine
'omero.web.ome_seadragon.tiles.rendering_engine': ['TILES_RENDERING_ENGINE', 'openslide', identity, None],
'omero.web.ome_seadragon.thumbnails.rendering_engine': ['THUMBNAILS_RENDERING_ENGINE', 'omero',
identity, None],
# deepzoom properties
'omero.web.ome_seadragon.deepzoom.overlap': ['DEEPZOOM_OVERLAP', 1, identity, None],
'omero.web.ome_seadragon.deepzoom.format': ['DEEPZOOM_FORMAT', 'jpeg', identity, None],
Expand Down
133 changes: 25 additions & 108 deletions slides_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -1,121 +1,38 @@
import logging
import os
import openslide
from openslide import OpenSlide, OpenSlideError
from openslide.deepzoom import DeepZoomGenerator
from cStringIO import StringIO
from PIL import Image

from ome_seadragon import settings
from ome_seadragon.images_cache import CacheDriverFactory


logger = logging.getLogger(__name__)


def _get_image_path(image_id, conn):
img = conn.getObject("Image", image_id)
if img is None:
return None
else:
return os.path.join(settings.IMGS_REPOSITORY, settings.IMGS_FOLDER,
img.getImportedImageFilePaths()['server_paths'][0])

class UnknownRenderingEngine(Exception):
pass

def _get_deepzoom_slide_config():
return {
'tile_size': settings.DEEPZOOM_TILE_SIZE,
'overlap': settings.DEEPZOOM_OVERLAP,
'limit_bounds': settings.DEEPZOOM_LIMIT_BOUNDS
}

class RenderingEngineFactory(object):

def _get_slide(image_path):
oslide_ref = OpenSlide(image_path)
slide = DeepZoomGenerator(oslide_ref, **_get_deepzoom_slide_config())
try:
mpp_x = oslide_ref.properties[openslide.PROPERTY_NAME_MPP_X]
mpp_y = oslide_ref.properties[openslide.PROPERTY_NAME_MPP_Y]
slide.mpp = (float(mpp_x) + float(mpp_y)) / 2
except (KeyError, ValueError):
slide.mpp = 0
return slide
def __init__(self):
self.tiles_rendering_engine = settings.TILES_RENDERING_ENGINE
self.thumbnails_rendering_engine = settings.THUMBNAILS_RENDERING_ENGINE

def _get_openslide_engine(self, image_id, connection):
from openslide_engine import OpenSlideEngine

def get_deepzoom_metadata(image_id, conn):
image_path = _get_image_path(image_id, conn)
if image_path:
slide = _get_slide(image_path)
return slide, settings.DEEPZOOM_FORMAT
else:
return None, settings.DEEPZOOM_FORMAT
return OpenSlideEngine(image_id, connection)

def _get_omero_engine(self, image_id, connection):
from ome_engine import OmeEngine

def get_image_mpp(image_id, conn):
image_path = _get_image_path(image_id, conn)
if image_path:
slide = OpenSlide(image_path)
try:
mpp_x = slide.properties[openslide.PROPERTY_NAME_MPP_X]
mpp_y = slide.properties[openslide.PROPERTY_NAME_MPP_Y]
return (float(mpp_x) + float(mpp_y)) / 2
except (KeyError, ValueError):
return 0
return OmeEngine(image_id, connection)


def get_thumbnail(image_id, width, height, conn):
cache_factory = CacheDriverFactory()
cache = cache_factory.get_cache()
# get thumbnail from cache
thumbnail = cache.thumbnail_from_cache(image_id, width, height,
settings.DEEPZOOM_FORMAT)
# if thumbnail is not in cache build it...
if thumbnail is None:
logger.info('No item loaded from cache, building it')
image_path = _get_image_path(image_id, conn)
if image_path:
slide = OpenSlide(image_path)
thumbnail = slide.get_thumbnail((width, height))
# ... and store it to cache
cache.thumbnail_to_cache(image_id, thumbnail, width, height,
settings.DEEPZOOM_FORMAT)
def get_tiles_rendering_engine(self, image_id, connection):
if self.tiles_rendering_engine == 'openslide':
return self._get_openslide_engine(image_id, connection)
if self.tiles_rendering_engine == 'omero':
return self._get_omero_engine(image_id, connection)
else:
thumbnail = None
else:
logger.info('Thumbnail loaded from cache')
return thumbnail, settings.DEEPZOOM_FORMAT

raise UnknownRenderingEngine('%s is not a valid rendering engine' % self.tiles_rendering_engine)

def get_tile(image_id, level, column, row, conn):
cache_factory = CacheDriverFactory()
cache = cache_factory.get_cache()
# configure cache callback
cache_callback_params = {
'image_id': image_id,
'level': level,
'column': column,
'row': row,
'tile_size': settings.DEEPZOOM_TILE_SIZE,
'image_format': settings.DEEPZOOM_FORMAT
}
if settings.DEEPZOOM_FORMAT.lower() == 'jpeg':
cache_callback_params['image_quality'] = settings.DEEPZOOM_JPEG_QUALITY
image = cache.tile_from_cache(**cache_callback_params)
# if tile is not in cache build it...
if image is None:
image_path = _get_image_path(image_id, conn)
if image_path:
slide = _get_slide(image_path)
tile = slide.get_tile(level, (column, row))
img_buffer = StringIO()
tile_conf = {
'format': settings.DEEPZOOM_FORMAT
}
if settings.DEEPZOOM_FORMAT == 'jpeg':
tile_conf['quality'] = settings.DEEPZOOM_JPEG_QUALITY
tile.save(img_buffer, **tile_conf)
image = Image.open(img_buffer)
# ... and store it to cache
cache_callback_params['image_obj'] = image
cache.tile_to_cache(**cache_callback_params)
return image, settings.DEEPZOOM_FORMAT
def get_thumbnails_rendering_engine(self, image_id, connection):
if self.thumbnails_rendering_engine == 'openslide':
return self._get_openslide_engine(image_id, connection)
if self.thumbnails_rendering_engine == 'omero':
return self._get_omero_engine(image_id, connection)
else:
raise UnknownRenderingEngine('%s is not a valid rendering engine' % self.thumbnails_rendering_engine)
Loading

0 comments on commit e3b45f5

Please sign in to comment.