Esempio n. 1
0
    def __add_detail_features(self, layer, detail_layer, lowres_features):
        #=====================================================================
        extra_details = []
        for feature in lowres_features:
            self.__map_properties.update_feature_properties(feature)
            hires_layer_id = feature.get_property('details')
            hires_layer = self.__layer_dict.get(hires_layer_id)
            if hires_layer is None:
                log.warn("Cannot find details layer '{}'".format(
                    feature.get_property('details')))
                continue
            boundary_feature = hires_layer.boundary_feature
            if boundary_feature is None:
                raise KeyError("Cannot find boundary of '{}' layer".format(
                    hires_layer.id))

            # Calculate transformation to map source shapes to the destination

            # NOTE: We reorder the coordinates of the bounding rectangles so that the first
            #       coordinate is the top left-most one. This should ensure that the source
            #       and destination rectangles align as intended, without output features
            #       being rotated by some multiple of 90 degrees.
            src = np.array(normalised_coords(
                boundary_feature.geometry.minimum_rotated_rectangle),
                           dtype="float32")
            dst = np.array(normalised_coords(
                feature.geometry.minimum_rotated_rectangle),
                           dtype="float32")
            transform = Transform(cv2.getPerspectiveTransform(src, dst))

            minzoom = feature.get_property('maxzoom') + 1
            if feature.get_property('type') != 'nerve':
                # Set the feature's geometry to that of the high-resolution outline
                feature.geometry = transform.transform_geometry(
                    boundary_feature.geometry)
            else:  # nerve
                feature.del_property('maxzoom')

            if hires_layer.source.raster_source is not None:
                extent = transform.transform_extent(hires_layer.source.extent)
                layer.add_raster_layer('{}_{}'.format(detail_layer.id,
                                                      hires_layer.id),
                                       extent,
                                       hires_layer.source,
                                       minzoom,
                                       local_world_to_base=transform)

            # The detail layer gets a scaled copy of each high-resolution feature
            for hires_feature in hires_layer.features:
                new_feature = self.__new_detail_feature(
                    layer.id, detail_layer, minzoom,
                    transform.transform_geometry(hires_feature.geometry),
                    hires_feature.properties)
                if new_feature.has_property('details'):
                    extra_details.append(new_feature)

        # If hires features that we've just added also have details then add them
        # to the detail layer
        if extra_details:
            self.__add_detail_features(layer, detail_layer, extra_details)
Esempio n. 2
0
 def __init__(self, flatmap, id, source_path, base_layer=True):
     super().__init__(flatmap, id)
     self.__source_file = FilePath(source_path)
     self.__base_layer = base_layer
     self.__svg = etree.parse(self.__source_file.get_fp()).getroot()
     if 'viewBox' in self.__svg.attrib:
         (width, height) = tuple(
             float(x) for x in self.__svg.attrib['viewBox'].split()[2:])
     else:
         width = length_as_pixels(self.__svg.attrib['width'])
         height = length_as_pixels(self.__svg.attrib['height'])
     # Transform from SVG pixels to world coordinates
     self.__transform = Transform(
         [[WORLD_METRES_PER_PIXEL, 0, 0], [0, WORLD_METRES_PER_PIXEL, 0],
          [0, 0, 1]]) @ np.array([[1, 0, -width / 2.0],
                                  [0, -1, height / 2.0], [0, 0, 1.0]])
     top_left = self.__transform.transform_point((0, 0))
     bottom_right = self.__transform.transform_point((width, height))
     # southwest and northeast corners
     self.bounds = (top_left[0], bottom_right[1], bottom_right[0],
                    top_left[1])
     self.__layer = SVGLayer(id, self, base_layer)
     self.add_layer(self.__layer)
     self.__raster_source = None
     self.__boundary_geometry = None
Esempio n. 3
0
    def __init__(self,
                 flatmap,
                 id,
                 source_href,
                 boundary_id=None,
                 exported=False):
        super().__init__(flatmap, id, source_href, 'image')
        self.__sparc_dataset = sparc_dataset(source_href)

        self.__boundary_id = boundary_id
        self.__boundary_geometry = None

        self.__layer = MapLayer(id, self, exported=exported)
        self.add_layer(self.__layer)

        self.__mbf = etree.parse(FilePath(source_href).get_fp()).getroot()
        self.__ns = self.__mbf.nsmap[None]

        sparcdata = self.__mbf.find(self.ns_tag('sparcdata'))
        self.__species = sparcdata.find(self.ns_tag('subject')).get('species')
        self.__organ = sparcdata.find(self.ns_tag('atlas')).get('rootid')

        image_element = self.__mbf.find('{}/{}'.format(self.ns_tag('images'),
                                                       self.ns_tag('image')))
        scale_element = image_element.find(self.ns_tag('scale'))
        scaling = (float(scale_element.get('x', 1.0)),
                   float(scale_element.get('y', 1.0)))  # um/px
        coord_element = image_element.find(self.ns_tag('coord'))
        offset = (float(coord_element.get('x', 0.0)),
                  float(coord_element.get('y', 0.0)))

        filename = image_element.find(self.ns_tag('filename')).text
        image_file = FilePath(urljoin(source_href, filename.split('\\')[-1]))
        image_array = np.frombuffer(image_file.get_data(), dtype=np.uint8)
        self.__image = cv2.imdecode(image_array, cv2.IMREAD_UNCHANGED)
        if self.__image.shape[2] == 3:
            self.__image = cv2.cvtColor(self.__image, cv2.COLOR_RGB2RGBA)
        image_size = (self.__image.shape[1], self.__image.shape[0])
        self.__image_to_world = (
            Transform([[scaling[0] * WORLD_METRES_PER_UM, 0, 0],
                       [0, -scaling[1] * WORLD_METRES_PER_UM, 0], [0, 0, 1]])
            @ np.array([[1, 0, -image_size[0] / 2.0],
                        [0, 1, -image_size[1] / 2.0], [0, 0, 1.0]]))
        self.__world_to_image = self.__image_to_world.inverse()
        (width, height) = (scaling[0] * image_size[0],
                           scaling[1] * image_size[1])  # um
        self.__um_to_world = (Transform([[
            WORLD_METRES_PER_UM, 0, 0
        ], [0, WORLD_METRES_PER_UM, 0], [0, 0, 1]]) @ np.array(
            [[1, 0, -width / 2.0], [0, 1, height / 2.0], [0, 0, 1.0]]))
        top_left = self.__um_to_world.transform_point((0, 0))
        bottom_right = self.__um_to_world.transform_point((width, -height))
        # southwest and northeast corners
        self.bounds = (top_left[0], bottom_right[1], bottom_right[0],
                       top_left[1])
Esempio n. 4
0
class SVGSource(MapSource):
    def __init__(self, flatmap, id, href, kind):  # maker v's flatmap (esp. id)
        super().__init__(flatmap, id, href, kind)
        self.__source_file = FilePath(href)
        self.__exported = (kind=='base')
        svg = etree.parse(self.__source_file.get_fp()).getroot()
        if 'viewBox' in svg.attrib:
            (width, height) = tuple(float(x) for x in svg.attrib['viewBox'].split()[2:])
        else:
            width = length_as_pixels(svg.attrib['width'])
            height = length_as_pixels(svg.attrib['height'])
        # Transform from SVG pixels to world coordinates
        self.__transform = Transform([[WORLD_METRES_PER_PIXEL,                      0, 0],
                                      [                     0, WORLD_METRES_PER_PIXEL, 0],
                                      [                     0,                         0, 1]])@np.array([[1,  0, -width/2.0],
                                                                                                         [0, -1,  height/2.0],
                                                                                                         [0,  0,         1.0]])
        top_left = self.__transform.transform_point((0, 0))
        bottom_right = self.__transform.transform_point((width, height))
        # southwest and northeast corners
        self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1])
        self.__layer = SVGLayer(id, self, svg, exported=self.__exported)
        self.add_layer(self.__layer)
        self.__boundary_geometry = None

    @property
    def boundary_geometry(self):
        return self.__boundary_geometry

    @property
    def transform(self):
        return self.__transform

    def process(self):
    #=================
        self.__layer.process()
        if self.__layer.boundary_feature is not None:
            self.__boundary_geometry = self.__layer.boundary_feature.geometry
        if self.__exported:
            # Save a cleaned copy of the SVG in the map's output directory
            cleaner = SVGCleaner(self.__source_file, self.flatmap.map_properties)
            cleaner.clean()
            with open(os.path.join(settings.get('output'),
                      self.flatmap.id,
                      '{}.svg'.format(self.flatmap.id)), 'wb') as fp:
                cleaner.save(fp)
        if settings.get('backgroundTiles', False):
            cleaner = SVGCleaner(self.__source_file, self.flatmap.map_properties, all_layers=False)
            cleaner.clean()
            cleaned_svg = io.BytesIO()
            cleaner.save(cleaned_svg)
            cleaned_svg.seek(0)
        else:
            cleaned_svg = None
        self.set_raster_source(RasterSource('svg', cleaned_svg, source=self.__source_file))
Esempio n. 5
0
 def __gradient_matrix(gradient, path):
 #=====================================
     if gradient.attrib.get('gradientUnits') == 'userSpaceOnUse':
         path_transform = Transform.Identity()
     else:                                    #  objectBoundingBox'
         bounds = path.getBounds()
         path_transform = Transform([[bounds.width(),               0, bounds.left()],
                                     [             0, bounds.height(), bounds.top()],
                                     [             0,               0,            1]])
     svg_transform = SVGTransform(gradient.attrib.get('gradientTransform'))
     return skia.Matrix(list((path_transform@svg_transform).flatten()))
Esempio n. 6
0
    def __init__(self, raster_layer, tile_set):
        self.__svg = etree.parse(raster_layer.source_data).getroot()
        if 'viewBox' in self.__svg.attrib:
            self.__size = tuple(
                float(x) for x in self.__svg.attrib['viewBox'].split()[2:])
        else:
            self.__size = (length_as_pixels(self.__svg.attrib['width']),
                           length_as_pixels(self.__svg.attrib['height']))
        self.__scaling = (tile_set.pixel_rect.width / self.__size[0],
                          tile_set.pixel_rect.height / self.__size[1])
        self.__definitions = DefinitionStore()
        defs = self.__svg.find(SVG_NS('defs'))
        if defs is not None:
            self.__definitions.add_definitions(defs)
        self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style')))
        self.__first_scan = True

        # Transform from SVG pixels to tile pixels
        transform = Transform([[self.__scaling[0], 0.0, 0.0],
                               [0.0, self.__scaling[1], 0.0], [0.0, 0.0, 1.0]])
        self.__path_list = []
        self.__draw_svg(transform, self.__path_list)

        # Transform from SVG pixels to world coordinates
        self.__image_to_world = (Transform([
            [WORLD_METRES_PER_PIXEL / self.__scaling[0], 0, 0],
            [0, WORLD_METRES_PER_PIXEL / self.__scaling[1], 0], [0, 0, 1]
        ]) @ np.array([[1, 0, -self.__scaling[0] * self.__size[0] / 2.0],
                       [0, -1, self.__scaling[1] * self.__size[1] / 2.0],
                       [0, 0, 1.0]]))

        self.__tile_size = tile_set.tile_size
        self.__tile_origin = tile_set.start_coords
        self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2]
        path_bounding_boxes = [(path, paint,
                                shapely.geometry.box(*tuple(path.getBounds())))
                               for (path, paint) in self.__path_list]
        self.__tile_paths = {}
        for tile in tile_set:
            tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y))
            x0 = (tile.x - self.__tile_origin[0]
                  ) * self.__tile_size[0] - self.__pixel_offset[0]
            y0 = (tile.y - self.__tile_origin[1]
                  ) * self.__tile_size[1] - self.__pixel_offset[1]
            tile_bbox = shapely.prepared.prep(
                shapely.geometry.box(x0, y0, x0 + self.__tile_size[0],
                                     y0 + self.__tile_size[0]))
            self.__tile_paths[mercantile.quadkey(tile)] = list(
                filter(lambda ppb: tile_bbox.intersects(ppb[2]),
                       path_bounding_boxes))
Esempio n. 7
0
class PowerpointSource(MapSource):
    def __init__(self, flatmap, id, source_path, get_background=False):
        super().__init__(flatmap, id)
        self.__pptx = Presentation(FilePath(source_path).get_BytesIO())
        self.__slides = self.__pptx.slides

        (width, height) = (self.__pptx.slide_width, self.__pptx.slide_height)
        self.__transform = Transform([[WORLD_METRES_PER_EMU,                     0, 0],
                                      [                    0, -WORLD_METRES_PER_EMU, 0],
                                      [                    0,                     0, 1]])@np.array([[1, 0, -width/2.0],
                                                                                                    [0, 1, -height/2.0],
                                                                                                    [0, 0,         1.0]])
        top_left = self.__transform.transform_point((0, 0))
        bottom_right = self.__transform.transform_point((width, height))
        # southwest and northeast corners
        self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1])

        if get_background:
            pdf_source = FilePath('{}_cleaned.pdf'.format(os.path.splitext(source_path)[0]))
            self.__raster_source = RasterSource('pdf', pdf_source.get_data())
        else:
            self.__raster_source = None

    @property
    def raster_source(self):
        return self.__raster_source

    @property
    def transform(self):
        return self.__transform

    def process(self):
    #=================
        for n in range(len(self.__slides)):
            slide = self.__slides[n]
            slide_number = n + 1
            slide_layer = PowerpointSlide(self, slide, slide_number)
            log('Slide {}, {}'.format(slide_number, slide_layer.id))
            if settings.get('saveDrawML'):
                xml = open(os.path.join(self.flatmap.map_directory,
                                        '{}.xml'.format(slide_layer.id)), 'w')
                xml.write(slide.element.xml)
                xml.close()
            slide_layer.process()
            for error in self.errors:
                log.warn(error)
            else:
                self.add_layer(slide_layer)
Esempio n. 8
0
    def __init__(self, flatmap, id, source_href):
        super().__init__(flatmap, id, source_href, 'slides')
        self.__pptx = Presentation(FilePath(source_href).get_BytesIO())
        self.__slides = self.__pptx.slides

        (width, height) = (self.__pptx.slide_width, self.__pptx.slide_height)
        self.__transform = Transform([[WORLD_METRES_PER_EMU,                     0, 0],
                                      [                    0, -WORLD_METRES_PER_EMU, 0],
                                      [                    0,                     0, 1]])@np.array([[1, 0, -width/2.0],
                                                                                                    [0, 1, -height/2.0],
                                                                                                    [0, 0,         1.0]])
        top_left = self.__transform.transform_point((0, 0))
        bottom_right = self.__transform.transform_point((width, height))
        # southwest and northeast corners
        self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1])
        pdf_source = FilePath('{}_cleaned.pdf'.format(os.path.splitext(source_href)[0]))
        self.set_raster_source(RasterSource('pdf', pdf_source.get_data()))
Esempio n. 9
0
    def __init__(self, raster_layer, tile_set):
        self.__bbox = shapely.geometry.box(*extent_to_bounds(raster_layer.extent))
        self.__svg = etree.parse(raster_layer.source_data).getroot()
        self.__source = raster_layer.source_params.get('source')
        if 'viewBox' in self.__svg.attrib:
            self.__size = tuple(float(x)
                for x in self.__svg.attrib['viewBox'].split()[2:])
        else:
            self.__size = (length_as_pixels(self.__svg.attrib['width']),
                           length_as_pixels(self.__svg.attrib['height']))
        self.__scaling = (tile_set.pixel_rect.width/self.__size[0],
                          tile_set.pixel_rect.height/self.__size[1])
        self.__definitions = DefinitionStore()
        self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style')))
        self.__clip_paths = ObjectStore()

        # Transform from SVG pixels to tile pixels
        svg_to_tile_transform = Transform([[self.__scaling[0],               0.0, 0.0],
                                           [              0.0, self.__scaling[1], 0.0],
                                           [              0.0,               0.0, 1.0]])
        self.__svg_drawing = self.__draw_svg(svg_to_tile_transform)

        # Transform from SVG pixels to world coordinates
        self.__image_to_world = (Transform([
            [WORLD_METRES_PER_PIXEL/self.__scaling[0],                                        0, 0],
            [                                       0, WORLD_METRES_PER_PIXEL/self.__scaling[1], 0],
            [                                       0,                                        0, 1]])
           @np.array([[1,  0, -self.__scaling[0]*self.__size[0]/2.0],
                      [0, -1,  self.__scaling[1]*self.__size[1]/2.0],
                      [0,  0,                                               1.0]]))

        self.__tile_size = tile_set.tile_size
        self.__tile_origin = tile_set.start_coords
        self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2]

        self.__tile_bboxes = {}
        for tile in tile_set:
            tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y))
            x0 = (tile.x - self.__tile_origin[0])*self.__tile_size[0] - self.__pixel_offset[0]
            y0 = (tile.y - self.__tile_origin[1])*self.__tile_size[1] - self.__pixel_offset[1]
            tile_bbox = shapely.geometry.box(x0, y0,
                                                                   x0 + self.__tile_size[0],
                                                                   y0 + self.__tile_size[0])
            self.__tile_bboxes[mercantile.quadkey(tile)] = tile_bbox