diff --git a/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py b/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py index fd96861..dfe664a 100755 --- a/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py +++ b/desuto-slideproperties/slideviewer-openslide-properties-service/slide-properties-service.py @@ -1,105 +1,111 @@ import web import urllib from slide import Slide from web.wsgiserver import CherryPyWSGIServer urls = ( '/slide_properties/microns_pixel_x/(.*)', 'mppx', '/slide_properties/microns_pixel_y/(.*)', 'mppy', '/slide_properties/pixels_mm/(.*)', 'pmm', '/slide_properties/pixels_m/(.*)', 'pm', '/slide_properties/bounds/(.*)', 'bounds', '/slide_properties/nbr_levels/(.*)', 'nbrlevels', '/slide_properties/level_downsamples/(.*)', 'leveldownsamples', '/slide_properties/level_dimensions/(.*)', 'leveldimensions', '/slide_properties/best_level_for_downsample/(.*)/(.*)', 'bestleveldownsample', '/slide_properties/common_info/(.*)', 'commoninfo', '/slide_properties/magnification/(.*)', 'magnification' ) app = web.application(urls, globals()) def corshook(): web.header('Access-Control-Allow-Origin', '*') web.header('Access-Control-Allow-Credentials', 'true') +def contentType(): + web.header('Content-Type', 'text/plain') + app.add_processor(web.loadhook(corshook)) +app.add_processor(web.loadhook(contentType)) class commoninfo: def GET(self, imagepath): + web.header('Content-Type', 'application/json') imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.common_info() class magnification: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.magnification() class mppx: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.mpp_x() class mppy: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.mpp_y() class pmm: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.px_mm() class pm: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.px_m() class vendor: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.vendor() class bounds: def GET(self, imagepath): + web.header('Content-Type', 'application/json') imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.bounds() class nbrlevels: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.nbr_levels() class leveldownsamples: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.level_downsamples() class leveldimensions: def GET(self, imagepath): imagepath = urllib.unquote(imagepath) slide = Slide(imagepath) return slide.level_dimensions() class bestleveldownsample: def GET(self, imagepath, downsample): imagepath = urllib.unquote(imagepath) print(imagepath) print(downsample) slide = Slide(imagepath) return slide.best_level_for_downsample(downsample) if __name__ == "__main__": app.run() diff --git a/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py b/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py index 1384312..5692d55 100755 --- a/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py +++ b/desuto-slideproperties/slideviewer-openslide-properties-service/slide.py @@ -1,91 +1,97 @@ import openslide from openslide import OpenSlide, OpenSlideError import os import json + class Slide: def __init__(self, imagepath): - self.osr = OpenSlide(imagepath); + self.osr = OpenSlide(imagepath) # Microns per pixel y def mpp_y(self): return self.osr.properties.get(openslide.PROPERTY_NAME_MPP_X) # Microns per pixel x def mpp_x(self): return self.osr.properties.get(openslide.PROPERTY_NAME_MPP_Y) # Pixels mer milimeter def px_mm(self): - return 1/(((float(self.mpp_x())+float(self.mpp_y()))/2)/1000) + if self.mpp_x() is not None and self.mpp_y() is not None: + return 1 / (((float(self.mpp_x()) + float(self.mpp_y())) / 2) / 1000) + else: + return None # Pixels mer milimeter def px_m(self): - return self.px_mm()*1000; + if self.px_mm() is not None: + return self.px_mm() * 1000 + else: + return None # Vendor def vendor(self): return self.osr.properties.get(openslide.PROPERTY_NAME_VENDOR) # X coordinate of the rectangle bounding the non-empty region of the slide, if available def bounds_x(self): return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_X) # X coordinate of the rectangle bounding the non-empty region of the slide, if available def bounds_y(self): return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_Y) # width of the rectangle bounding the non-empty region of the slide, if available. def bounds_width(self): return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_WIDTH) # Height of the rectangle bounding the non-empty region of the slide, if available. def bounds_height(self): return self.osr.properties.get(openslide.PROPERTY_NAME_BOUNDS_HEIGHT) # x, y and rectangle width & height bounding the non-empty region of the slide, if available. JSON def bounds(self): info = {} - info['x'] = self.bounds_x() + info['x'] = self.bounds_x() info['y'] = self.bounds_y() info['width'] = self.bounds_width() info['height'] = self.bounds_height() return json.dumps(info) # Number of magnification levels def nbr_levels(self): return self.osr.level_count # A list of downsample factors for each level of the slide. level_downsamples[k] is the downsample factor of level k. def level_downsamples(self): return self.osr.level_downsamples # A list of (width, height) tuples, one for each level of the slide. level_dimensions[k] are the dimensions of level k. def level_dimensions(self): return self.osr.level_dimensions # Best level for displaying the given downsample. def best_level_for_downsample(self, downsample): return self.osr.get_best_level_for_downsample(float(downsample)) # Magnification level def magnification(self): return self.osr.properties.get(openslide.PROPERTY_NAME_OBJECTIVE_POWER) def common_info(self): info = {} info['pmm'] = self.px_mm() info['pm'] = self.px_m() info['nbrlevels'] = self.nbr_levels() info['leveldownsamples'] = self.level_downsamples() info['leveldimensions'] = self.level_dimensions() - info['bounds'] = {} - info['bounds']['x'] = self.bounds_x() + info['bounds']['x'] = self.bounds_x() info['bounds']['y'] = self.bounds_y() info['bounds']['width'] = self.bounds_width() info['bounds']['height'] = self.bounds_height() - return json.dumps(info); + return json.dumps(info)