예제 #1
0
 def process(self):
     #=================
     self.__layer.process(self.__svg)
     if self.__layer.boundary_id is not None:
         self.__boundary_geometry = self.__layer.features_by_id.get(
             self.__layer.boundary_id).geometry
     if self.__base_layer:
         # 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)
         self.__raster_source = RasterSource('svg', cleaned_svg)
예제 #2
0
 def __init__(self):
     database = os.path.join(settings.get('output'), 'labels.sqlite')
     if settings.get('refreshLabels', False):
         try:
             os.remove(database)
         except FileNotFoundError:
             pass
     new_db = not os.path.exists(database)
     self.__db = sqlite3.connect(database)
     self.__cursor = self.__db.cursor()
     if new_db:
         self.__cursor.execute(
             'CREATE TABLE labels (entity text, label text)')
         self.__db.commit()
예제 #3
0
 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(settings.get('output'),
                                     self.flatmap.id,
                                     '{}.xml'.format(slide_layer.id)), 'w')
             xml.write(slide.element.xml)
             xml.close()
         slide_layer.process()
         self.add_layer(slide_layer)
예제 #4
0
    def process(self):
    #=================
        boundary_geometry = None
        for contour in self.__mbf.findall(self.ns_tag('contour')):
            label = contour.get('name')
            association = contour.xpath('ns:property[@name="TraceAssociation"]/ns:s', namespaces={'ns': self.__ns})
            anatomical_id = association[0].text if len(association) else None
            points = []
            for point in contour.findall(self.ns_tag('point')):
                x = float(point.get('x'))
                y = float(point.get('y'))
                points.append(self.__um_to_world.transform_point((x, y)))

            if contour.get('closed'):
                if (points[0] != points[-1]).all():
                    points.append(points[-1])
                geometry = shapely.geometry.Polygon((points))
            else:
                geometry = shapely.geometry.LineString(points)

            properties = {'tile-layer': 'features'}
            if label is not None:
                properties['label'] = label
            if anatomical_id is not None:
                properties['models'] = anatomical_id
            feature = self.flatmap.new_feature(geometry, properties)
            self.__layer.add_feature(feature)
            if anatomical_id == self.__boundary_id:
                boundary_geometry = feature.geometry
                self.__layer.boundary_id = feature.feature_id

        if settings.get('backgroundTiles', False):
            self.__set_raster_source(boundary_geometry)
예제 #5
0
 def __init__(self, path_id, route_graph, centreline_scaffold=None):
     self.__path_id = path_id
     self.__graph = route_graph
     self.__centreline_scaffold = centreline_scaffold
     self.__path_layout = settings.get('pathLayout', 'automatic')
     self.__node_set = {
         node
         for node, data in route_graph.nodes(data=True)
         if not data.get('exclude', False)
     }
     self.__source_nodes = {
         node
         for node, data in route_graph.nodes(data=True)
         if data.get('type') == 'source'
     }
     self.__target_nodes = {
         node
         for node, data in route_graph.nodes(data=True)
         if data.get('type') == 'target'
     }
     if self.__path_layout == 'automatic':
         ## The sheath scaffold is a network property and should be set
         ## from the `centreline_scaffold` parameter
         self.__sheath = Sheath(route_graph, path_id)
         self.__sheath.build(self.__source_nodes, self.__target_nodes)
     else:
         self.__sheath = None
예제 #6
0
def parse_markup(markup):
    properties = {'markup': markup}
    deprecated = []
    try:
        parsed = SHAPE_MARKUP.parseString(markup, parseAll=True)
        for prop in parsed[1:]:
            if prop[0] in DEPRECATED_MARKUP:
                deprecated.append(prop[0])
            if (FEATURE_FLAGS.matches(prop[0])
                    or SHAPE_FLAGS.matches(prop[0])):
                properties[prop[0]] = True
            elif prop[0] == 'details':
                properties[prop[0]] = prop[1]
                properties['maxzoom'] = int(prop[2]) - 1
            else:
                properties[prop[0]] = prop[1]
    except ParseException:
        properties['error'] = 'Syntax error'
    if len(deprecated) and settings.get('showDeprecated', False):
        properties['warning'] = "Deprecated '{}'".format(
            "', '".join(deprecated))
    if ('styling' in properties
            and ('id' in properties or 'class' in properties)):
        properties[
            'error'] = "'styling' element can't have an 'id' nor 'class'"
    return properties
예제 #7
0
 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)
예제 #8
0
    def entity_knowledge(self, entity):
        #==================================
        # Optionally refresh local connectivity knowledge from SciCrunch
        if (settings.get('cleanConnectivity', False)
                and (entity.startswith(APINATOMY_MODEL_PREFIX)
                     or entity.split(':')[0] in CONNECTIVITY_ONTOLOGIES)):
            self.db.execute('delete from knowledge where entity=?', (entity, ))
        else:
            # Check local cache
            knowledge = self.__entity_knowledge.get(entity, {})
            if len(knowledge): return knowledge

        # Now check our database
        row = self.db.execute('select knowledge from knowledge where entity=?',
                              (entity, )).fetchone()
        if row is not None:
            knowledge = json.loads(row[0])
        else:
            # Consult SciCrunch if we don't know about the entity
            knowledge = self.__scicrunch.get_knowledge(entity)
            if len(knowledge) > 0:
                # Save knowledge in our database
                self.db.execute('replace into knowledge values (?, ?)',
                                (entity, json.dumps(knowledge)))
                # Save label and publications in their own tables
                if 'label' in knowledge:
                    self.db.execute('replace into labels values (?, ?)',
                                    (entity, knowledge['label']))
                if 'publications' in knowledge:
                    self.update_publications(entity,
                                             knowledge.pop('publications', []))
        # Use the entity's value as its label if none is defined
        if 'label' not in knowledge:
            knowledge['label'] = entity
        # Cache local knowledge
        self.__entity_knowledge[entity] = knowledge
        return knowledge
예제 #9
0
 def create_geometry(self, feature_map):
     #======================================
     self.__feature_map = feature_map
     for edge in self.__centreline_graph.edges(
             data='id'):  # Returns triples: (node, node, id)
         for node_id in edge[0:2]:
             self.__set_node_properties(
                 self.__centreline_graph.nodes[node_id], node_id)
         feature = self.__find_feature(edge[2])
         if feature is not None:
             bezier_path = feature.get_property('bezier-path')
             if bezier_path is None:
                 log.warn('Centreline {} has no Bezier path'.format(
                     feature.id))
             else:
                 bezier_start = bezier_path.pointAtTime(0)
                 start_point = shapely.geometry.Point(
                     bezier_start.x, bezier_start.y)
                 end_node_0 = self.__centreline_graph.nodes[edge[0]].get(
                     'geometry')
                 end_node_1 = self.__centreline_graph.nodes[edge[1]].get(
                     'geometry')
                 if end_node_0 is not None and end_node_1 is not None:
                     self.__centreline_graph.edges[
                         edge[0:2]]['geometry'] = bezier_path
                     if start_point.distance(
                             end_node_0) < start_point.distance(end_node_1):
                         self.__centreline_graph.edges[
                             edge[0:2]]['start-node'] = edge[0]
                     else:
                         self.__centreline_graph.edges[
                             edge[0:2]]['start-node'] = edge[1]
     if settings.get('pathLayout', 'automatic') == 'automatic':
         # Construct the centreline scaffold for the network
         ##self.__centreline_scaffold = Sheath(self.__id, self.__graph)
         pass
예제 #10
0
    def __get_geometry(self, shape, properties, transform):
        #======================================================
        ##
        ## Returns shape's geometry as `shapely` object.
        ##
        coordinates = []
        bezier_segments = []
        pptx_geometry = Geometry(shape)
        for path in pptx_geometry.path_list:
            bbox = (shape.width,
                    shape.height) if path.w is None or path.h is None else (
                        path.w, path.h)
            T = transform @ DrawMLTransform(shape, bbox)

            moved = False
            first_point = None
            current_point = None
            closed = False

            for c in path.getchildren():
                if c.tag == DML('arcTo'):
                    (wR, hR) = ((pptx_geometry.attrib_value(c, 'wR'),
                                 pptx_geometry.attrib_value(c, 'hR')))
                    stAng = radians(pptx_geometry.attrib_value(c, 'stAng'))
                    swAng = radians(pptx_geometry.attrib_value(c, 'swAng'))
                    p1 = ellipse_point(wR, hR, stAng)
                    p2 = ellipse_point(wR, hR, stAng + swAng)
                    pt = (current_point[0] - p1[0] + p2[0],
                          current_point[1] - p1[1] + p2[1])
                    large_arc_flag = 1 if swAng >= math.pi else 0
                    paths = bezier_paths_from_arc_endpoints(
                        tuple2(wR, hR), 0, large_arc_flag, 1,
                        tuple2(*current_point), tuple2(*pt), T)
                    bezier_segments.extend(paths.asSegments())
                    coordinates.extend(bezier_sample(paths))
                    current_point = pt

                elif c.tag == DML('close'):
                    if first_point is not None and current_point != first_point:
                        coordinates.append(T.transform_point(first_point))
                    closed = True
                    first_point = None
                    # Close current pptx_geometry and start a new one...

                elif c.tag == DML('cubicBezTo'):
                    coords = [BezierPoint(*T.transform_point(current_point))]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*T.transform_point(pt)))
                        current_point = pt
                    bz = CubicBezier(*coords)
                    bezier_segments.append(bz)
                    coordinates.extend(bezier_sample(bz))

                elif c.tag == DML('lnTo'):
                    pt = pptx_geometry.point(c.pt)
                    if moved:
                        coordinates.append(T.transform_point(current_point))
                        moved = False
                    coordinates.append(T.transform_point(pt))
                    current_point = pt

                elif c.tag == DML('moveTo'):
                    pt = pptx_geometry.point(c.pt)
                    if first_point is None:
                        first_point = pt
                    current_point = pt
                    moved = True

                elif c.tag == DML('quadBezTo'):
                    coords = [BezierPoint(*T.transform_point(current_point))]
                    for p in c.getchildren():
                        pt = pptx_geometry.point(p)
                        coords.append(BezierPoint(*T.transform_point(pt)))
                        current_point = pt
                    bz = QuadraticBezier(*coords)
                    bezier_segments.append(bz)
                    coordinates.extend(bezier_sample(bz))

                else:
                    print('Unknown path element: {}'.format(c.tag))

        if settings.get('saveBeziers', False) and len(bezier_segments) > 0:
            properties['bezier-segments'] = [
                repr(bz) for bz in bezier_segments
            ]

        if closed:
            geometry = shapely.geometry.Polygon(coordinates)
        else:
            geometry = shapely.geometry.LineString(coordinates)
            if properties.get('closed', False):
                # Return a polygon if flagged as `closed`
                coordinates.append(coordinates[0])
                return shapely.geometry.Polygon(coordinates)
        return geometry
예제 #11
0
 def __init__(self, *args, show=True, **kwargs):
     if show and settings.get('verbose', False):
         self.__progress_bar = tqdm.tqdm(*args, **kwargs)
     else:
         self.__progress_bar = None
예제 #12
0
    def __get_geometry(self, element, properties, transform):
        #=======================================================
        ##
        ## Returns path element as a `shapely` object.
        ##
        coordinates = []
        bezier_segments = []
        moved = False
        first_point = None
        current_point = None
        closed = False

        T = transform @ SVGTransform(element.attrib.get('transform'))
        if element.tag == SVG_NS('path'):
            path_tokens = re.sub('.', SVGLayer.__path_matcher,
                                 element.attrib.get('d', '')).split()

        elif element.tag == SVG_NS('rect'):
            x = length_as_pixels(element.attrib.get('x', 0))
            y = length_as_pixels(element.attrib.get('y', 0))
            width = length_as_pixels(element.attrib.get('width', 0))
            height = length_as_pixels(element.attrib.get('height', 0))
            rx = length_as_pixels(element.attrib.get('rx'))
            ry = length_as_pixels(element.attrib.get('ry'))
            if width == 0 or height == 0: return None

            if rx is None and ry is None:
                rx = ry = 0
            elif ry is None:
                ry = rx
            elif rx is None:
                rx = ry
            rx = min(rx, width / 2)
            ry = min(ry, height / 2)
            if rx == 0 and ry == 0:
                path_tokens = [
                    'M', x, y, 'H', x + width, 'V', y + height, 'H', x, 'V', y,
                    'Z'
                ]
            else:
                path_tokens = [
                    'M', x + rx, y, 'H', x + width - rx, 'A', rx, ry, 0, 0, 1,
                    x + width, y + ry, 'V', y + height - ry, 'A', rx, ry, 0, 0,
                    1, x + width - rx, y + height, 'H', x + rx, 'A', rx, ry, 0,
                    0, 1, x, y + height - ry, 'V', y + ry, 'A', rx, ry, 0, 0,
                    1, x + rx, y, 'Z'
                ]

        elif element.tag == SVG_NS('line'):
            x1 = length_as_pixels(element.attrib.get('x1', 0))
            y1 = length_as_pixels(element.attrib.get('y1', 0))
            x2 = length_as_pixels(element.attrib.get('x2', 0))
            y2 = length_as_pixels(element.attrib.get('y2', 0))
            path_tokens = ['M', x1, y1, x2, y2]

        elif element.tag == SVG_NS('polyline'):
            points = element.attrib.get('points', '').replace(',', ' ').split()
            path_tokens = ['M'] + points

        elif element.tag == SVG_NS('polygon'):
            points = element.attrib.get('points', '').replace(',', ' ').split()
            path_tokens = ['M'] + points + ['Z']

        elif element.tag == SVG_NS('circle'):
            cx = length_as_pixels(element.attrib.get('cx', 0))
            cy = length_as_pixels(element.attrib.get('cy', 0))
            r = length_as_pixels(element.attrib.get('r', 0))
            if r == 0: return None
            path_tokens = [
                'M', cx + r, cy, 'A', r, r, 0, 0, 0, cx, cy - r, 'A', r, r, 0,
                0, 0, cx - r, cy, 'A', r, r, 0, 0, 0, cx, cy + r, 'A', r, r, 0,
                0, 0, cx + r, cy, 'Z'
            ]

        elif element.tag == SVG_NS('ellipse'):
            cx = length_as_pixels(element.attrib.get('cx', 0))
            cy = length_as_pixels(element.attrib.get('cy', 0))
            rx = length_as_pixels(element.attrib.get('rx', 0))
            ry = length_as_pixels(element.attrib.get('ry', 0))
            if rx == 0 or ry == 0: return None
            path_tokens = [
                'M', cx + rx, cy, 'A', rx, ry, 0, 0, 0, cx, cy - ry, 'A', rx,
                ry, 0, 0, 0, cx - rx, cy, 'A', rx, ry, 0, 0, 0, cx, cy + ry,
                'A', rx, ry, 0, 0, 0, cx + rx, cy, 'Z'
            ]

        pos = 0
        while pos < len(path_tokens):
            if isinstance(path_tokens[pos],
                          str) and path_tokens[pos].isalpha():
                cmd = path_tokens[pos]
                pos += 1
            # Else repeat previous command with new coordinates
            # with `moveTo` becoming `lineTo`
            elif cmd == 'M':
                cmd = 'L'
            elif cmd == 'm':
                cmd = 'l'

            if cmd not in ['s', 'S']:
                second_cubic_control = None
            if cmd not in ['t', 'T']:
                second_quad_control = None

            if cmd in ['a', 'A']:
                params = [float(x) for x in path_tokens[pos:pos + 7]]
                pos += 7
                pt = params[5:7]
                if cmd == 'a':
                    pt[0] += current_point[0]
                    pt[1] += current_point[1]
                phi = radians(params[2])
                paths = bezier_paths_from_arc_endpoints(
                    tuple2(*params[0:2]), phi, *params[3:5],
                    tuple2(*current_point), tuple2(*pt), T)
                bezier_segments.extend(paths.asSegments())
                coordinates.extend(bezier_sample(paths))
                current_point = pt

            elif cmd in ['c', 'C', 's', 'S']:
                coords = [BezierPoint(*T.transform_point(current_point))]
                if cmd in ['c', 'C']:
                    n_params = 6
                else:
                    n_params = 4
                    if second_cubic_control is None:
                        coords.append(
                            BezierPoint(*T.transform_point(current_point)))
                    else:
                        coords.append(
                            BezierPoint(*T.transform_point(
                                reflect_point(second_cubic_control,
                                              current_point))))
                params = [float(x) for x in path_tokens[pos:pos + n_params]]
                pos += n_params
                for n in range(0, n_params, 2):
                    pt = params[n:n + 2]
                    if cmd.islower():
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                    if n == (n_params - 4):
                        second_cubic_control = pt
                    coords.append(BezierPoint(*T.transform_point(pt)))
                bz = CubicBezier(*coords)
                bezier_segments.append(bz)
                coordinates.extend(bezier_sample(bz))
                current_point = pt

            elif cmd in ['l', 'L', 'h', 'H', 'v', 'V']:
                if cmd in ['l', 'L']:
                    params = [float(x) for x in path_tokens[pos:pos + 2]]
                    pos += 2
                    pt = params[0:2]
                    if cmd == 'l':
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                else:
                    param = float(path_tokens[pos])
                    pos += 1
                    if cmd == 'h':
                        param += current_point[0]
                    elif cmd == 'v':
                        param += current_point[1]
                    if cmd in ['h', 'H']:
                        pt = [param, current_point[1]]
                    else:
                        pt = [current_point[0], param]
                if moved:
                    coordinates.append(T.transform_point(current_point))
                    moved = False
                coordinates.append(T.transform_point(pt))
                current_point = pt

            elif cmd in ['m', 'M']:
                params = [float(x) for x in path_tokens[pos:pos + 2]]
                pos += 2
                pt = params[0:2]
                if first_point is None:
                    # First `m` in a path is treated as `M`
                    first_point = pt
                else:
                    if cmd == 'm':
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                current_point = pt
                moved = True

            elif cmd in ['q', 'Q', 't', 'T']:
                coords = [BezierPoint(*T.transform_point(current_point))]
                if cmd in ['q', 'Q']:
                    n_params = 4
                else:
                    n_params = 2
                    if second_quad_control is None:
                        coords.append(
                            BezierPoint(*T.transform_point(current_point)))
                    else:
                        coords.append(
                            BezierPoint(*T.transform_point(
                                reflect_point(second_quad_control,
                                              current_point))))
                params = [float(x) for x in path_tokens[pos:pos + n_params]]
                pos += n_params
                for n in range(0, n_params, 2):
                    pt = params[n:n + 2]
                    if cmd.islower():
                        pt[0] += current_point[0]
                        pt[1] += current_point[1]
                    if n == (n_params - 4):
                        second_quad_control = pt
                    coords.append(BezierPoint(*T.transform_point(pt)))
                bz = QuadraticBezier(*coords)
                bezier_segments.append(bz)
                coordinates.extend(bezier_sample(bz))
                current_point = pt

            elif cmd in ['z', 'Z']:
                if first_point is not None and current_point != first_point:
                    coordinates.append(T.transform_point(first_point))
                closed = True
                first_point = None

            else:
                print('Unknown path command: {}'.format(cmd))

        if settings.get('saveBeziers', False) and len(bezier_segments) > 0:
            properties['bezier-segments'] = [
                repr(bz) for bz in bezier_segments
            ]

        if closed:
            geometry = shapely.geometry.Polygon(coordinates)
        else:
            geometry = shapely.geometry.LineString(coordinates)
            if properties.get('closed', False):
                # Return a polygon if flagged as `closed`
                coordinates.append(coordinates[0])
                return shapely.geometry.Polygon(coordinates)
        return geometry