示例#1
0
    def draw_svg(self, drawing: svgwrite.Drawing, g):

        glane = drawing.g()
        glane.attribs["class"] = "lane"

        cp1 = self.control_points[0]
        cp2 = self.control_points[-1]
        rel = relative_pose(cp1.as_SE2(), cp2.as_SE2())
        _, theta = geo.translation_angle_from_SE2(rel)

        delta = int(np.sign(theta))
        fill = {-1: "#577094", 0: "#709457", 1: "#947057"}[delta]

        points = self.lane_profile(points_per_segment=10)
        p = drawing.polygon(points=points, fill=fill, fill_opacity=0.5)

        glane.add(p)

        center_points = self.center_line_points(points_per_segment=10)
        center_points = [
            geo.translation_angle_from_SE2(_)[0] for _ in center_points
        ]
        p = drawing.polyline(
            points=center_points,
            stroke=fill,
            fill="none",
            stroke_dasharray="0.02",
            stroke_width=0.01,
        )
        glane.add(p)

        g.add(glane)

        for x in self.control_points:
            q = x.asmatrix2d().m
            p1, _ = geo.translation_angle_from_SE2(q)
            delta_arrow = np.array([self.width / 4, 0])
            p2 = SE2_apply_R2(q, delta_arrow)
            gp = drawing.g()
            gp.attribs["class"] = "control-point"
            l = drawing.line(
                start=p1.tolist(),
                end=p2.tolist(),
                stroke="black",
                stroke_width=self.width / 20.0,
            )
            gp.add(l)
            c = drawing.circle(
                center=p1.tolist(),
                r=self.width / 8,
                fill="white",
                stroke="black",
                stroke_width=self.width / 20.0,
            )
            gp.add(c)
            g.add(gp)
示例#2
0
def draw_calendar(x: int, y: int, dwg: svgwrite.Drawing,
                  lines: List[str]):
    shapes = dwg.add(dwg.g())

    shapes.add(dwg.rect(insert=(x, y), size=(460 * px, 330 * px),
                        fill='white', stroke='black', stroke_width=1))

    offset = 35
    for line in lines:
        date_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
        date_text.add(dwg.text(line, (10 + x, offset + y)))
        offset += 40
示例#3
0
    def render(self, dwg: Drawing) -> Group:
        g = dwg.g()

        leg = dwg.path(fill=self.leg_color)
        leg.push("M 0 0")
        leg.push("L 0 %f" % self.leg_length)
        leg.push("l %f 0" % self.thickness_foot)
        leg.push("L %f 0" % self.thickness_thigh)
        leg.push("Z")

        g.add(leg)

        boot_start = .7
        boot_height = self.boot_height
        foot_length = self.foot_length

        boot = dwg.path(fill=self.foot_color)
        boot.push("M 0 %f" % (self.leg_length * boot_start))
        boot.push("L 0 %f" % (self.leg_length + boot_height))
        boot.push("l %f 0" % foot_length)
        boot.push(
            "a %f %f 0 0 0 %f %f" %
            (min(boot_height, abs(foot_length - self.thickness_foot)),
             boot_height, -min(boot_height, foot_length - self.thickness_foot),
             -boot_height))
        boot.push("L %f %f" %
                  (self.thickness_thigh -
                   (self.thickness_thigh - self.thickness_foot) * boot_start +
                   1, self.leg_length * boot_start))

        g.add(boot)

        return g
示例#4
0
 def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
          offset: XY) -> None:
     """For each track, draw it on the poster."""
     if self.poster.tracks is None:
         raise PosterError("No tracks to draw.")
     cell_size, counts = utils.compute_grid(len(self.poster.tracks), size)
     if cell_size is None or counts is None:
         raise PosterError("Unable to compute grid.")
     count_x, count_y = counts[0], counts[1]
     spacing_x = 0 if count_x <= 1 else (size.x - cell_size * count_x) / (
         count_x - 1)
     spacing_y = 0 if count_y <= 1 else (size.y - cell_size * count_y) / (
         count_y - 1)
     offset.x += (size.x - count_x * cell_size -
                  (count_x - 1) * spacing_x) / 2
     offset.y += (size.y - count_y * cell_size -
                  (count_y - 1) * spacing_y) / 2
     year_groups: typing.Dict[int, svgwrite.container.Group] = {}
     for (index, tr) in enumerate(self.poster.tracks):
         year = tr.start_time().year
         if year not in year_groups:
             g_year = dr.g(id=f"year{year}")
             g.add(g_year)
             year_groups[year] = g_year
         else:
             g_year = year_groups[year]
         p = XY(index % count_x, index // count_x) * XY(
             cell_size + spacing_x, cell_size + spacing_y)
         self._draw_track(
             dr,
             g_year,
             tr,
             0.9 * XY(cell_size, cell_size),
             offset + 0.05 * XY(cell_size, cell_size) + p,
         )
示例#5
0
    def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
             offset: XY) -> None:
        """Draw the circular Poster using distances broken down by time"""
        if self.poster.tracks is None:
            raise PosterError("No tracks to draw.")
        if self.poster.length_range_by_date is None:
            return

        years = self.poster.years.count()
        _, counts = utils.compute_grid(years, size)
        if counts is None:
            raise PosterError("Unable to compute grid.")
        count_x, count_y = counts[0], counts[1]
        x, y = 0, 0
        cell_size = size * XY(1 / count_x, 1 / count_y)
        margin = XY(4, 4)
        if count_x <= 1:
            margin.x = 0
        if count_y <= 1:
            margin.y = 0
        sub_size = cell_size - 2 * margin
        for year in self.poster.years.iter():
            g_year = dr.g(id=f"year{year}")
            g.add(g_year)
            self._draw_year(dr, g_year, sub_size,
                            offset + margin + cell_size * XY(x, y), year)
            x += 1
            if x >= count_x:
                x = 0
                y += 1
示例#6
0
    def _draw_cell(self, drw: Drawing, cell, stone_size):
        from_grid_to_edge = stone_size / 2 + self._margin
        x = (from_grid_to_edge + (cell.x - 1) * stone_size)
        y = (from_grid_to_edge + (cell.y - 1) * stone_size)
        node = cell.node
        cell = drw.add(drw.g(id=f'cell{cell.x}-{cell.y}'))

        if node.stone is not None:
            self._put_stone(cell, x, y, node.stone, stone_size)

        if node.stone is None:
            half_size = 3 * stone_size / 8
            cell.add(
                Rect(
                    ((x - half_size) * self.unit, (y - half_size) * self.unit),
                    (2 * half_size * self.unit, 2 * half_size * self.unit),
                    fill="white"))

        fill = "white" if node.stone == Stone.Black else "black"
        if isinstance(node.marker, game.Label):
            self._put_label(cell, x, y, node.marker.label, fill, stone_size)
        elif isinstance(node.marker, game.Square):
            self._put_square(cell, fill, stone_size, x, y)
        elif isinstance(node.marker, game.Circle):
            self._put_circle(cell, x, y, fill, stone_size)
        elif isinstance(node.marker, game.Cross):
            self._put_cross(cell, x, y, fill, stone_size)
        elif isinstance(node.marker, game.Triangle):
            self._put_triangle(cell, x, y, fill, stone_size)
示例#7
0
    def plot(self, x, y, scale, **extra):

        assert isinstance(scale, (int, float))
        assert isinstance(x, (int, float))
        assert isinstance(y, (int, float))

        svg = Drawing()
        g = svg.g()

        p1 = [x, y]
        p2 = [x + max(self.ticks) * scale, y]

        g.add(svg.line(start=p1, end=p2, stroke="black", stroke_width=1))

        for i, tick in enumerate(self.ticks):
            p1 = [x + tick * scale, y - 5]
            p2 = [x + tick * scale, y + 0.5]

            g.add(svg.line(start=p1, end=p2, stroke="black", stroke_width=1))

            g.add(
                svg.text(text="%s" % self.labels[i],
                         insert=[x + tick * scale, y + 10],
                         font_size=8,
                         font_family="Arial"))

        return g
示例#8
0
    def _draw_tracks(self, d: svgwrite.Drawing, size: XY, offset: XY) -> None:
        assert self.tracks_drawer

        g = d.g(id="tracks")
        d.add(g)

        self.tracks_drawer.draw(d, g, size, offset)
    def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
             offset: XY) -> None:
        """Iterate through the Poster's years, creating a calendar for each."""
        if self.poster.tracks is None:
            raise PosterError("No tracks to draw.")
        years = self.poster.years.count()
        _, counts = utils.compute_grid(years, size)
        if counts is None:
            raise PosterError("Unable to compute grid.")
        count_x, count_y = counts[0], counts[1]
        x, y = 0, 0
        cell_size = size * XY(1 / count_x, 1 / count_y)
        margin = XY(4, 8)
        if count_x <= 1:
            margin.x = 0
        if count_y <= 1:
            margin.y = 0
        sub_size = cell_size - 2 * margin

        for year in self.poster.years.iter():
            g_year = dr.g(id=f"year{year}")
            g.add(g_year)
            self._draw(dr, g_year, sub_size,
                       offset + margin + cell_size * XY(x, y), year)
            x += 1
            if x >= count_x:
                x = 0
                y += 1
示例#10
0
 def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
          offset: XY) -> None:
     """Draw the heatmap based on tracks."""
     bbox = self._determine_bbox()
     year_groups: typing.Dict[int, svgwrite.container.Group] = {}
     for tr in self.poster.tracks:
         year = tr.start_time().year
         if year not in year_groups:
             g_year = dr.g(id=f"year{year}")
             g.add(g_year)
             year_groups[year] = g_year
         else:
             g_year = year_groups[year]
         color = self.color(self.poster.length_range, tr.length(),
                            tr.special)
         for line in utils.project(bbox, size, offset, tr.polylines):
             for opacity, width in [(0.1, 5.0), (0.2, 2.0), (1.0, 0.3)]:
                 g_year.add(
                     dr.polyline(
                         points=line,
                         stroke=color,
                         stroke_opacity=opacity,
                         fill="none",
                         stroke_width=width,
                         stroke_linejoin="round",
                         stroke_linecap="round",
                     ))
示例#11
0
    def _draw_header(self, d: svgwrite.Drawing) -> None:
        g = d.g(id="header")
        d.add(g)

        text_color = self.colors["text"]
        title_style = "font-size:12px; font-family:Arial; font-weight:bold;"
        assert self._title is not None
        g.add(d.text(self._title, insert=(10, 20), fill=text_color, style=title_style))
示例#12
0
def draw_small(x: int, y: int, dwg: svgwrite.Drawing, time: str, weather: WeatherForecast, icons_location: str):
    shapes = dwg.add(dwg.g())

    shapes.add(dwg.rect(insert=(x, y), size=(220 * px, 145 * px),
                        fill='white', stroke='black', stroke_width=1))

    date_text = dwg.add(dwg.g(font_size=35, font_family="Helvetica"))
    date_text.add(dwg.text(time, (10 + x, 35 + y)))

    paragraph = dwg.add(dwg.g(font_size=55))
    paragraph.add(dwg.text(f"{weather.temperature}°", (x + 135, y + 90), text_anchor="middle"))

    location = os.path.abspath(f"{icons_location}/{weather.summary.value}.svg")
    image = dwg.add(
        dwg.image(href=location,
                  insert=(10 + x, 45 + y), size=(55 * px, 55 * px)))

    pressure_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
    pressure_text.add(dwg.text(f"{int(weather.air_pressure)} hPa", (10 + x, 130 + y)))
示例#13
0
    def render(self, d: Drawing) -> Group:
        g = d.g()

        r = d.image(href=self.href)
        r["xlink:href"] = self.href
        r["width"] = "%dpx" % self.width
        r["height"] = "%dpx" % self.height

        g.add(r)
        return g
示例#14
0
    def render(self, dwg: Drawing) -> Group:
        g = dwg.g()

        p = dwg.path(stroke=self.color, fill_opacity=0, stroke_width=3)
        p.push("M %f %f" % (-self.width / 2, 0))
        p.push("Q %f %f %f %f" %
               (0, self.width * self.intensity, self.width / 2, 0))

        g.add(p)

        return g
示例#15
0
    def render(self, dwg: Drawing) -> Group:
        g = dwg.g()

        p = dwg.path(fill="black", stroke_width=0)
        p.push("M %f %f" % (-self.width / 2, 0))
        p.push("Q %f %f %f %f" %
               (0, self.width * self.intensity, self.width / 2, 0))
        p.push("Z")

        g.add(p)

        return g
示例#16
0
    def render(self, d: Drawing) -> Group:
        g = d.g()
        href = "data:image/jpeg;base64,%s" % base64.b64encode(
            self.data).decode()

        r = d.image(href=href)
        r["xlink:href"] = href
        r["width"] = "%dpx" % self.width
        r["height"] = "%dpx" % self.height

        g.add(r)
        return g
示例#17
0
    def generate_tiling(self):
        dwg = Drawing("{}/tiling2.svg".format(self.output_folder),
                      profile="tiny")

        current_color = 0
        row_spacing = self.pent_height * 2 + self.bottom_length

        for y in range(self.num_down):
            transform = "translate({}, {})".format(0, self.rep_spacing * y)
            dgroup = dwg.add(dwg.g(transform=transform))
            for x in range(self.num_across):
                # if x is odd, point 1 of pent 1 needs to be attached to point 3 of pent 2
                if x % 2 == 1:
                    dx = int(
                        x / 2
                    ) * self.rep_spacing + self.pent_width * 2 + self.column_offset.real
                    transform = "translate({}, {})".format(
                        dx, self.column_offset.imag)
                else:
                    transform = "translate({}, {})".format(
                        int(x / 2) * self.rep_spacing, 0)
                group = dgroup.add(dwg.g(transform=transform))
                for pent in self.cairo_group:
                    group.add(
                        dwg.path(
                            **{
                                'd':
                                pent.d(),
                                'fill':
                                self._colors[current_color %
                                             len(self._colors)],
                                'stroke-width':
                                4,
                                'stroke':
                                rgb(0, 0, 0)
                            }))
                    current_color += 1

        dwg.viewbox(*self.pattern_viewbox)
        dwg.save(pretty=True)
示例#18
0
def draw_big(x: int, y: int, dwg: svgwrite.Drawing, weather: WeatherForecast, air_quality: AirQuality,
             icons_location: str):
    shapes = dwg.add(dwg.g(id='shapes'))

    shapes.add(dwg.rect(insert=(x, y), size=(360 * px, 300 * px),
                        fill='white', stroke='black', stroke_width=1))

    paragraph = dwg.add(dwg.g(font_size=120))
    paragraph.add(dwg.text(f"{weather.temperature}°", (x + 240, y + 110), text_anchor="middle"))

    location = os.path.abspath(f"{icons_location}/{weather.summary.value}.svg")
    image = dwg.add(
        dwg.image(href=location, insert=(x + 5, y + 5),
                  size=(120 * px, 120 * px)))

    feels_like_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
    feels_like_text.add(dwg.text(f"Air quality: {air_quality}", (x + 10, y + 165)))

    wind_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
    wind_text.add(dwg.text(f"{weather.wind_name} {weather.wind_mps} m/s", (x + 10, y + 205), textLength=340))

    precipitation_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
    precipitation_text.add(dwg.text(f"{weather.precip_name} {weather.precip_mm} mm/h", (x + 10, y + 245)))

    pressure_text = dwg.add(dwg.g(font_size=36, font_family="Helvetica"))
    pressure_text.add(dwg.text(f"{int(weather.air_pressure)} hPa", (x + 10, y + 285)))
示例#19
0
def display_svg():
    dwg = Drawing()
    hlines = dwg.add(dwg.g(id="hlines", stroke="green"))
    for y in range(20):
        hlines.add(
            dwg.line(start=(2 * cm, (2 + y) * cm),
                     end=(18 * cm, (2 + y) * cm)))
    vlines = dwg.add(dwg.g(id="vline", stroke="blue"))
    for x in range(17):
        vlines.add(
            dwg.line(start=((2 + x) * cm, 2 * cm),
                     end=((2 + x) * cm, 21 * cm)))
    shapes = dwg.add(dwg.g(id="shapes", fill="red"))

    # set presentation attributes at object creation as SVG-Attributes
    circle = dwg.circle(center=(15 * cm, 8 * cm),
                        r="2.5cm",
                        stroke="blue",
                        stroke_width=3)
    circle["class"] = "class1 class2"
    shapes.add(circle)

    # override the 'fill' attribute of the parent group 'shapes'
    shapes.add(
        dwg.rect(
            insert=(5 * cm, 5 * cm),
            size=(45 * mm, 45 * mm),
            fill="blue",
            stroke="red",
            stroke_width=3,
        ))

    # or set presentation attributes by helper functions of the Presentation-Mixin
    ellipse = shapes.add(
        dwg.ellipse(center=(10 * cm, 15 * cm), r=("5cm", "10mm")))
    ellipse.fill("green", opacity=0.5).stroke("black",
                                              width=5).dasharray([20, 20])

    return Response(dwg.tostring(), mimetype="image/svg+xml")
示例#20
0
    def render(self, dwg: Drawing) -> Group:
        r = dwg.rect(insert=(0, 0),
                     size=(self.width, self.height),
                     fill=self.color)
        g = dwg.g()
        g.add(r)

        star_count = int(self.width * self.height * .001)
        for i in range(star_count):
            s = dwg.circle(center=(self.prng.randint(0, self.width),
                                   self.prng.randint(0, self.height)),
                           r=max(2, self.prng.gauss(1, 1)),
                           fill="white")
            g.add(s)

        return g
示例#21
0
    def plot(self, shape="rect", scale=0, strand=True, **extra):

        svg = Drawing()
        g = svg.g()

        previous = None

        for feature in self.features:

            if not previous:
                previous = feature
                continue

            x1, y1 = previous.position
            x2, y2 = feature.position

            y1 += (2 + previous.strand) * previous.height + previous.height / 2

            y2 += (feature.strand - 1) * feature.height - previous.height / 2

            p1 = [x1, y1]
            p2 = [x1 + previous.length * scale, y1]
            p3 = [x2 + feature.length * scale, y2]
            p4 = [x2, y2]

            if shape == "rect":
                g.add(
                    svg.polygon(points=[p1, p2, p3, p4],
                                fill=self.color,
                                fill_opacity=0.6))

            if shape == "line":
                g.add(
                    svg.polyline([
                        ((p1[0] + p2[0]) / 2, y1 - previous.height / 2),
                        ((p1[0] + p2[0]) / 2, y1),
                        ((p3[0] + p4[0]) / 2, y2),
                        ((p3[0] + p4[0]) / 2, y2 + feature.height / 2),
                    ],
                                 fill_opacity=0,
                                 stroke=self.color,
                                 stroke_width=2))

            previous = feature

        return g
示例#22
0
    def render(self, dwg: Drawing) -> Group:
        width, height, scale, x_translate, y_translate = self.random_configuration()

        image_url = "/assets/%s" % self.img
        if self.local_paths:
            image_url = "file://%s" % os.path.join(ASSET_DIR, self.img)

        g = dwg.g()
        r = dwg.image(href=self.img)
        r["xlink:href"] = image_url
        r["width"] = "%dpx" % width
        r["height"] = "%dpx" % height

        r.scale(scale)
        r.translate(- x_translate, - y_translate)

        g.add(r)

        return g
示例#23
0
    def render(self, dwg: Drawing) -> Group:
        g = dwg.g()

        eye = dwg.circle(center=(0, 0),
                         r=self.radius,
                         fill="white",
                         stroke_width=0)
        g.add(eye)

        pupil_radius = self.radius * self.pupil_radius

        pupil_rho = min(self.radius * self.pupil_rho,
                        self.radius * (1 - self.pupil_radius))

        pupil_coords = (pupil_rho * math.cos(self.pupil_phi),
                        pupil_rho * math.sin(self.pupil_phi))

        pupil = dwg.circle(center=pupil_coords,
                           r=pupil_radius,
                           fill="black",
                           stroke_width=0)
        g.add(pupil)

        reflection_radius = pupil_radius * .2
        reflection_rho = pupil_radius * .6
        reflection_phi = 1.75 * math.pi
        reflection_coords = (pupil_coords[0] +
                             reflection_rho * math.cos(reflection_phi),
                             pupil_coords[1] +
                             reflection_rho * math.sin(reflection_phi))

        reflection = dwg.circle(center=reflection_coords,
                                r=reflection_radius,
                                fill="white")

        g.add(reflection)

        return g
示例#24
0
    def draw_path_clip(self):
        path_filename = "{}/path_clip_{}.svg".format(
            self.output_folder,
            basename(self.filename).replace(".svg", ""))
        dwg = Drawing(path_filename)
        image_bbox = calc_overall_bbox(self.tile_paths)

        dx = self.pent_x - min(image_bbox[0], image_bbox[1])
        dy = self.pent_y - min(image_bbox[2], image_bbox[3])
        dwg.add(
            dwg.path(
                **{
                    "d": self.new_pentagon().d(),
                    "fill": "none",
                    'stroke-width': 4,
                    'stroke': rgb(0, 0, 0)
                }))
        neg_transform = "translate({}, {})".format(-dx, -dy)
        transform = "translate({}, {})".format(dx, dy)
        clip_path = dwg.defs.add(
            dwg.clipPath(id="pent_path", transform=neg_transform))
        clip_path.add(dwg.path(d=self.new_pentagon().d()))
        group = dwg.add(
            dwg.g(clip_path="url(#pent_path)",
                  transform=transform,
                  id="clippedpath"))
        for i, path in enumerate(self.tile_paths):
            group.add(
                dwg.path(d=path.d(),
                         style=self.tile_attributes[i].get('style'),
                         id=self.tile_attributes[i]['id']))
        dwg.add(dwg.use("#clippedpath", transform="transform(100, 100)"))

        dwg.viewbox(self.pent_x, self.pent_y, self.pent_width,
                    self.pent_height)
        dwg.save()
        xml = xml.dom.minidom.parse(path_filename)
        open(path_filename, "w").write(xml.toprettyxml())
示例#25
0
# create svg
dwg = Drawing("test.svg", size=(width,height))
dwg.defs.add(dwg.style(css))

data = read_csv(indata)
labels = data.iloc[:,0]
cols = data.iloc[:,1:]

ncols = cols.shape[1]
nlines = ncols - 1
colspace = h - nlines*200
colwidth = colspace / float(ncols)
collocs = (arange(ncols) + 1)*colwidth

# pad
g = dwg.add(dwg.g(transform="translate(%i,%i)" % (padding,padding)))
title = g.add(dwg.g())

for i in range(ncols):
    if i==0:
        title.add(dwg.text(cols.columns[i], insert=(collocs[i],0), text_anchor='end', font_size='%ipx' % titlefont))
    elif i==ncols-1:
        title.add(dwg.text(cols.columns[i], insert=(collocs[i],0), font_size='%ipx' % titlefont))

g = g.add(dwg.g(transform="translate(0,%i)" % (titlefont+fontsize)))
# loop over and add labels
vmin = min(cols.values)
vmax = max(cols.values)

def scale(val, src=(vmin, vmax), dst=(0, h)):
    return ((float(val) - src[0]) / (src[1]-src[0])) * (dst[1]-dst[0]) + dst[0]
示例#26
0
文件: svg.py 项目: openalea/wlformat
def export_node(node, store, size=None):
    """Construct a SVG description for a workflow node.

    Args:
        node (NodeDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow node
    """
    pfs = port_font_size

    # node size
    pr = port_radius
    pspace = pr * 9
    nw = compute_node_width(node, node['name'], pspace)
    nh = label_font_size + 2 * pr + 2 * pfs + 2 + (2 * node_padding)

    # draw
    if size is None:
        size = (600, 600)

    paper = Drawing("workflow_node.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    # body
    g = paper.add(paper.g())

    # background
    lg = paper.linearGradient((0.5, 0), (0.5, 1.))
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    bg = paper.rect((-nw / 2, -nh / 2), (nw, nh),
                    rx=node_padding,
                    ry=node_padding,
                    stroke_width=1)
    bg.stroke('#808080')
    bg.fill(lg)
    g.add(bg)

    # label
    style = ('font-size: %dpx; font-family: %s; '
             'text-anchor: middle' % (label_font_size, label_font))
    frag = paper.tspan(node['name'], dy=[label_font_size // 3])
    label = paper.text("", style=style, fill='#000000')
    label.add(frag)
    g.add(label)

    # ports
    port_style = ('font-size: %dpx; ' % pfs + 'font-family: %s; ' % label_font)
    onstyle = port_style + 'text-anchor: end'
    instyle = port_style + 'text-anchor: start'
    istyle = port_style + 'text-anchor: middle'
    nb = len(node['inputs'])
    py = -nh / 2
    for i, pdef in enumerate(node['inputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#in_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[-2 * pr])
        label = paper.text("", style=instyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[pr + pfs])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    nb = len(node['outputs'])
    py = nh / 2
    for i, pdef in enumerate(node['outputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#out_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[2 * pr + pfs // 2])
        label = paper.text("", style=onstyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[-pr - 2])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    # reformat whole drawing to fit screen
    xmin = -nw / 2 - draw_padding / 10.
    xmax = +nw / 2 + draw_padding / 10.
    if len(node['inputs']) == 0:
        inames_extend = 0
    else:
        inames = [(len(pdef['name']), pdef['name']) for pdef in node['inputs']]
        inames_extend = string_size(sorted(inames)[-1][1], pfs) * 0.7 + pfs
    ymin = -nh / 2 - pr - inames_extend - draw_padding / 10.
    if len(node['outputs']) == 0:
        onames_extend = 0
    else:
        onames = [(len(pdef['name']), pdef['name'])
                  for pdef in node['outputs']]
        onames_extend = string_size(sorted(onames)[-1][1], pfs) * 0.7 + pfs
    ymax = +nh / 2 + pr + onames_extend + draw_padding / 10.

    w = float(size[0])
    h = float(size[1])
    ratio = max((xmax - xmin) / w, (ymax - ymin) / h)
    xsize = ratio * w
    ysize = ratio * h

    bb = (xmin * xsize / (xmax - xmin), ymin * ysize / (ymax - ymin), xsize,
          ysize)

    paper.viewbox(*bb)
    return paper.tostring(), bb
示例#27
0
Figure built manually in SVG.

Note, these require the svgwrite package (and optionally, the svglib package to convert to pdf).
"""
import subprocess

from svgwrite import Drawing

filename = 'scaling_compute_totals_gmres.svg'
color_phys = '#85C1E9'
color_scaled = '#EC7063'
main_font_size = 20

dwg = Drawing(filename, (2500, 2000), debug=True)

top_text = dwg.add(dwg.g(font_size=main_font_size,
                         style="font-family: arial;"))

locs = [
    'NL Inputs', 'NL Outputs', 'NL Residuals', 'LN Inputs', 'LN Outputs',
    'LN Residuals', 'Jacobian'
]

x = 650
y = 50
delta_x = 180
vertical_locs = []
for loc in locs:
    top_text.add(dwg.text(loc, (x - len(loc) * 4, y)))
    vertical_locs.append(x)
    x += delta_x
示例#28
0
    def _draw_footer(self, d: svgwrite.Drawing) -> None:
        g = d.g(id="footer")
        d.add(g)

        text_color = self.colors["text"]
        header_style = "font-size:4px; font-family:Arial"
        value_style = "font-size:9px; font-family:Arial"
        small_value_style = "font-size:3px; font-family:Arial"

        (
            total_length,
            average_length,
            length_range,
            weeks,
        ) = self._compute_track_statistics()

        g.add(
            d.text(
                self.translate("ATHLETE"),
                insert=(10, self.height - 20),
                fill=text_color,
                style=header_style,
            )
        )
        g.add(
            d.text(
                self._athlete,
                insert=(10, self.height - 10),
                fill=text_color,
                style=value_style,
            )
        )
        g.add(
            d.text(
                self.translate("STATISTICS"),
                insert=(120, self.height - 20),
                fill=text_color,
                style=header_style,
            )
        )
        g.add(
            d.text(
                self.translate("Number") + f": {len(self.tracks)}",
                insert=(120, self.height - 15),
                fill=text_color,
                style=small_value_style,
            )
        )
        g.add(
            d.text(
                self.translate("Weekly") + ": " + format_float(len(self.tracks) / weeks),
                insert=(120, self.height - 10),
                fill=text_color,
                style=small_value_style,
            )
        )
        g.add(
            d.text(
                self.translate("Total") + ": " + self.format_distance(total_length),
                insert=(141, self.height - 15),
                fill=text_color,
                style=small_value_style,
            )
        )
        g.add(
            d.text(
                self.translate("Avg") + ": " + self.format_distance(average_length),
                insert=(141, self.height - 10),
                fill=text_color,
                style=small_value_style,
            )
        )
        if length_range.is_valid():
            min_length = length_range.lower()
            max_length = length_range.upper()
            assert min_length is not None
            assert max_length is not None
        else:
            min_length = 0.0
            max_length = 0.0
        g.add(
            d.text(
                self.translate("Min") + ": " + self.format_distance(min_length),
                insert=(167, self.height - 15),
                fill=text_color,
                style=small_value_style,
            )
        )
        g.add(
            d.text(
                self.translate("Max") + ": " + self.format_distance(max_length),
                insert=(167, self.height - 10),
                fill=text_color,
                style=small_value_style,
            )
        )
示例#29
0
文件: svg.py 项目: openalea/wlformat
def export_node(node, store, size=None):
    """Construct a SVG description for a workflow node.

    Args:
        node (NodeDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow node
    """
    pfs = port_font_size

    # node size
    pr = port_radius
    pspace = pr * 9
    nw = compute_node_width(node, node['name'], pspace)
    nh = label_font_size + 2 * pr + 2 * pfs + 2 + (2 * node_padding)

    # draw
    if size is None:
        size = (600, 600)

    paper = Drawing("workflow_node.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    # body
    g = paper.add(paper.g())

    # background
    lg = paper.linearGradient((0.5, 0), (0.5, 1.))
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    bg = paper.rect((-nw / 2, -nh / 2), (nw, nh),
                    rx=node_padding, ry=node_padding,
                    stroke_width=1)
    bg.stroke('#808080')
    bg.fill(lg)
    g.add(bg)

    # label
    style = ('font-size: %dpx; font-family: %s; '
             'text-anchor: middle' % (label_font_size, label_font))
    frag = paper.tspan(node['name'], dy=[label_font_size // 3])
    label = paper.text("", style=style, fill='#000000')
    label.add(frag)
    g.add(label)

    # ports
    port_style = ('font-size: %dpx; ' % pfs +
                  'font-family: %s; ' % label_font)
    onstyle = port_style + 'text-anchor: end'
    instyle = port_style + 'text-anchor: start'
    istyle = port_style + 'text-anchor: middle'
    nb = len(node['inputs'])
    py = -nh / 2
    for i, pdef in enumerate(node['inputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#in_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[-2 * pr])
        label = paper.text("", style=instyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[pr + pfs])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    nb = len(node['outputs'])
    py = nh / 2
    for i, pdef in enumerate(node['outputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#out_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[2 * pr + pfs // 2])
        label = paper.text("", style=onstyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[- pr - 2])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    # reformat whole drawing to fit screen
    xmin = - nw / 2 - draw_padding / 10.
    xmax = + nw / 2 + draw_padding / 10.
    if len(node['inputs']) == 0:
        inames_extend = 0
    else:
        inames = [(len(pdef['name']), pdef['name']) for pdef in node['inputs']]
        inames_extend = string_size(sorted(inames)[-1][1], pfs) * 0.7 + pfs
    ymin = - nh / 2 - pr - inames_extend - draw_padding / 10.
    if len(node['outputs']) == 0:
        onames_extend = 0
    else:
        onames = [(len(pdef['name']), pdef['name']) for pdef in node['outputs']]
        onames_extend = string_size(sorted(onames)[-1][1], pfs) * 0.7 + pfs
    ymax = + nh / 2 + pr + onames_extend + draw_padding / 10.

    w = float(size[0])
    h = float(size[1])
    ratio = max((xmax - xmin) / w, (ymax - ymin) / h)
    xsize = ratio * w
    ysize = ratio * h

    bb = (xmin * xsize / (xmax - xmin),
          ymin * ysize / (ymax - ymin),
          xsize,
          ysize)

    paper.viewbox(*bb)
    return paper.tostring(), bb
示例#30
0
文件: diagram.py 项目: shenjia1/mavis
def draw_multi_transcript_overlay(config,
                                  gene,
                                  vmarkers=None,
                                  window_buffer=0,
                                  plots=None,
                                  log=devnull):
    vmarkers = [] if vmarkers is None else vmarkers
    plots = [] if plots is None else plots

    canvas = Drawing(
        size=(config.width,
              1000))  # just set the height for now and change later
    width = config.width - config.left_margin - config.right_margin - config.overlay_left_label - config.padding
    labels = LabelMapping()  # keep labels consistent within the drawing

    all_exons = set()
    colors = dict()
    for us_tx in gene.transcripts:
        for ex in us_tx.exons:
            all_exons.add(ex)
            colors[
                ex] = config.exon1_color if us_tx.is_best_transcript else config.exon2_color

        for spl_tx in us_tx.transcripts:
            for translation in spl_tx.translations:
                for dom in translation.domains:
                    labels.set_key(dom.name, dom.name)
    genomic_min = min([max([gene.start - window_buffer, 1])] +
                      [m.start
                       for m in vmarkers] + [p.xmin for p in plots if p.xmin])
    genomic_max = max([gene.end + window_buffer] + [m.end for m in vmarkers] +
                      [p.xmax for p in plots if p.xmax])

    mapping = generate_interval_mapping(all_exons,
                                        width,
                                        config.exon_intron_ratio,
                                        config.exon_min_width,
                                        min_inter_width=config.min_width,
                                        start=genomic_min,
                                        end=genomic_max)
    main_group = canvas.g(class_='overlay')

    x = config.overlay_left_label + config.padding
    y = config.marker_top_margin

    for plot in plots:
        if plot.points:
            plot_group = draw_scatter(config, canvas, plot, mapping, log=log)
            main_group.add(plot_group)
            plot_group.translate(x, y)
            y += plot.height + config.padding * 2

    regular_transcripts = sorted(
        [us_tx for us_tx in gene.transcripts if not us_tx.is_best_transcript],
        key=lambda x: x.name)
    for us_tx in regular_transcripts:
        group_element = draw_exon_track(config,
                                        canvas,
                                        us_tx,
                                        mapping,
                                        colors=colors,
                                        genomic_min=genomic_min,
                                        genomic_max=genomic_max)
        main_group.add(group_element)
        group_element.translate(x, y)

        text_element = canvas.text(
            us_tx.name,
            insert=(x - config.padding, y + config.track_height / 2 +
                    config.font_central_shift_ratio * config.label_font_size),
            fill=config.label_color,
            style=config.font_style.format(font_size=config.label_font_size,
                                           text_anchor='end'),
            class_='label')
        main_group.add(text_element)
        y += config.padding + config.track_height

    best_transcripts = sorted(
        [us_tx for us_tx in gene.transcripts if us_tx.is_best_transcript],
        key=lambda x: x.name)
    for us_tx in best_transcripts:
        for spl_tx in us_tx.transcripts:
            labels[us_tx.name] = spl_tx

        group_element = draw_ustranscript(config,
                                          canvas,
                                          us_tx,
                                          mapping=mapping,
                                          colors=colors,
                                          labels=labels)
        main_group.add(group_element)
        group_element.translate(x, y)

        y += config.padding + group_element.height

    y += config.marker_bottom_margin
    # now draw the breakpoints overtop
    for marker in sorted(vmarkers):
        px_itvl = Interval(
            mapping.convert_ratioed_pos(marker.start).start,
            mapping.convert_ratioed_pos(marker.end).end)
        group_element = draw_vmarker(config,
                                     canvas,
                                     marker,
                                     px_itvl.length(),
                                     y,
                                     label=marker.name)
        group_element.translate(x + px_itvl.start, 0)
        main_group.add(group_element)

    main_group.translate(config.left_margin, config.top_margin)
    y += config.bottom_margin
    canvas.add(main_group)
    canvas.attribs['height'] = y
    return canvas
示例#31
0
    def render(self, dwg: Drawing) -> Group:
        g = dwg.g()

        head = self.head.render(dwg)

        socket_relative_width = 1.2

        socket_radius = (self.head_size * socket_relative_width, self.head_size*0.3)
        socket_relative_height = .3

        socket_left = (-self.head_size * socket_relative_width, self.head_size * .5)
        socket_left_bottom = (socket_left[0], socket_left[1] + self.head_size * socket_relative_height)
        socket_right: Tuple[float, float] = (self.head_size * socket_relative_width, self.head_size * .5)
        socket_right_bottom: Tuple[float, float] = (socket_right[0], socket_right[1] + self.head_size * socket_relative_height)

        size_factor = self.head_size / 50.0

        arm_length = 50 * size_factor
        arm_params = {
            "arm_length": arm_length,
            "arm_color": self.body_color,
            "hand_color": helper.colors.lighten_hex(self.body_color, 2),
            "thickness_shoulder": 30 * size_factor
        }
        arm_params.update(self.arm_params)

        for i in range(self.arm_count):
            left_arm = ArmWithHand(**arm_params) # type: ignore
            left_arm_g = left_arm.render(dwg)

            left_arm_x = socket_right_bottom[0] - left_arm.thickness_shoulder / 2 - (socket_right_bottom[0] - self.head_size * self.body_fatness) / (self.head_size * self.body_height) * i * left_arm.thickness_shoulder * 1.2

            left_arm_g.translate(left_arm_x, socket_right_bottom[1] + left_arm.thickness_shoulder / 2 + i * left_arm.thickness_shoulder * .8)
            left_arm_g.rotate(self.body_left_arm_angle / (math.pi) * 180 + (i * 20))

            g.add(left_arm_g)

            right_arm = ArmWithHand(reverse_shadow=True, **arm_params) # type: ignore
            right_arm_g = right_arm.render(dwg)

            right_arm_x = socket_left_bottom[0] + right_arm.thickness_shoulder / 2 + (-self.head_size * self.body_fatness - socket_left_bottom[0]) / (self.head_size * self.body_height) * i * right_arm.thickness_shoulder * 1.2

            right_arm_g.translate(right_arm_x, socket_left_bottom[1] + right_arm.thickness_shoulder / 2 + i * right_arm.thickness_shoulder * .8)
            right_arm_g.rotate(-self.body_right_arm_angle / (math.pi) * 180 - (i * 20))
            right_arm_g.scale(-1, 1)

            g.add(right_arm_g)

        leg_thickness_thigh = self.body_fatness * self.head_size
        leg_thickness_foot = leg_thickness_thigh * .7

        leg_length = self.head_size * 1

        boot_height = leg_length * .5
        foot_length = leg_length

        left_leg = LegWithFoot(leg_length=leg_length, # type: ignore
                               leg_color=self.body_color,
                               thickness_thigh=leg_thickness_thigh,
                               thickness_foot=leg_thickness_foot,
                               foot_color=helper.colors.lighten_hex(self.body_color, 2),
                               boot_height=boot_height,
                               foot_length=foot_length,
                               **self.leg_params)
        left_leg_g = left_leg.render(dwg)
        left_leg_g.translate(0, self.head_size * self.body_height)
        left_leg_g.rotate(-20)

        g.add(left_leg_g)

        right_leg = LegWithFoot(leg_length=leg_length, # type: ignore
                                leg_color=self.body_color,
                                thickness_thigh=leg_thickness_thigh,
                                thickness_foot=leg_thickness_foot,
                                foot_color=helper.colors.lighten_hex(self.body_color, 2),
                                boot_height=boot_height,
                                foot_length=foot_length,
                                **self.leg_params)
        right_leg_g = right_leg.render(dwg)
        right_leg_g.translate(0, self.head_size * self.body_height)
        right_leg_g.rotate(20)
        right_leg_g.scale(-1, 1)

        g.add(right_leg_g)

        body = dwg.path(fill=self.body_color)
        body.push("M %f %f" % (socket_right_bottom[0], socket_right_bottom[1]))
        body.push("L %f %f" % (self.head_size * self.body_fatness, self.head_size * self.body_height))
        body.push("L %f %f" % (self.head_size * (self.body_fatness - .2), self.head_size * (self.body_height + .2)))
        body.push("L %f %f" % (-self.head_size * (self.body_fatness - .2), self.head_size * (self.body_height + .2)))
        body.push("L %f %f" % (-self.head_size * self.body_fatness, self.head_size * self.body_height))
        body.push("L %f %f" % (socket_left_bottom[0], socket_left_bottom[1]))

        g.add(body)

        socket_background_color = helper.colors.darken_hex(self.socket_color)
        socket_background = dwg.ellipse(fill=socket_background_color, center=(0, self.head_size * .5), r=socket_radius)
        
        socket_foreground = dwg.path(fill=self.socket_color)
        socket_foreground.push("M %f %f" % socket_left)
        socket_foreground.push("A %f %f 0 0 0 %f %f" % (socket_radius[0], socket_radius[1], socket_right[0], socket_right[1]))
        socket_foreground.push("l 0 %f" % (self.head_size * .3))
        socket_foreground.push("A %f %f 0 0 1 %f %f" % (socket_radius[0], socket_radius[1], - self.head_size * socket_relative_width, self.head_size * .8))

        g.add(socket_background)
        g.add(head)
        g.add(socket_foreground)

        dome = dwg.path(fill="white", fill_opacity=.3)
        dome.push("M %f %f" % socket_left)
        dome.push("C %f %f %f %f %f %f" % (-self.head_size * (socket_relative_width + 1),
                                           -self.head_size * 3,
                                           self.head_size * (socket_relative_width + 1),
                                           -self.head_size * 3,
                                           socket_right[0],
                                           socket_right[1]))
        dome.push("A %f %f 0 0 1 %f %f" % (socket_radius[0], socket_radius[1], socket_left[0], socket_left[1]))

        refl_mask = dwg.defs.add(dwg.mask((self.head_size * -1.5, self.head_size * -2.5),
                                          (self.head_size * 3, self.head_size * 5),
                                          id="%s-dome-refl-mask" % self.id))
        refl_mask.add(dwg.rect((self.head_size * -1.5, self.head_size * -2.5),
                                          (self.head_size * 3, self.head_size * 5), fill="white"))
        refl_mask.add(dwg.circle((self.head_size * .3, -self.head_size * .25), r=self.head_size * 1.75, fill="black"))

        dome_reflection = dwg.path(fill="white", fill_opacity=.3, mask="url(#%s-dome-refl-mask)" % self.id)
        dome_reflection.push("M %f %f" % socket_left)
        dome_reflection.push("C %f %f %f %f %f %f" % (-self.head_size * (socket_relative_width + 1),
                                           -self.head_size * 3,
                                           self.head_size * (socket_relative_width + 1),
                                           -self.head_size * 3,
                                           socket_right[0],
                                           socket_right[1]))
        dome_reflection.push("A %f %f 0 0 1 %f %f" % (socket_radius[0], socket_radius[1], socket_left[0], socket_left[1]))
        dome_reflection.scale(.9)

        g.add(dome)
        g.add(dome_reflection)

        return g
Note, these require the svgwrite package (and optionally, the svglib package to convert to pdf).
"""
from __future__ import print_function
import subprocess

from svgwrite import Drawing

filename = 'scaling_run_model.svg'
color_phys = '#85C1E9'
color_scaled = '#EC7063'
main_font_size = 24

dwg = Drawing(filename, (2500, 2000), debug=True)

top_text = dwg.add(dwg.g(font_size=main_font_size, style="font-family: arial;"))

locs = ['NL Inputs',
        'NL Outputs',
        'NL Residuals']

x = 900
y = 50
delta_x = 400
vertical_locs = []
for loc in locs:
    top_text.add(dwg.text(loc, (x - len(loc)*4, y)))
    vertical_locs.append(x)
    x += delta_x

legend_text = dwg.add(dwg.g(font_size=main_font_size, style="font-family: arial;"))
示例#33
0
    def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
             offset: XY) -> None:
        if self.poster.tracks is None:
            raise PosterError("No tracks to draw")
        year_size = 200 * 4.0 / 80.0
        year_style = f"font-size:{year_size}px; font-family:Arial;"
        year_length_style = f"font-size:{110 * 3.0 / 80.0}px; font-family:Arial;"
        month_names_style = "font-size:2.5px; font-family:Arial"
        total_length_year_dict = self.poster.total_length_year_dict
        for year in self.poster.years.iter():
            g_year = dr.g(id=f"year{year}")
            g.add(g_year)

            start_date_weekday, _ = calendar.monthrange(year, 1)
            github_rect_first_day = datetime.date(year, 1, 1)
            # Github profile the first day start from the last Monday of the last year or the first Monday of this year
            # It depands on if the first day of this year is Monday or not.
            github_rect_day = github_rect_first_day + datetime.timedelta(
                -start_date_weekday)
            year_length = total_length_year_dict.get(year, 0)
            year_length_str = utils.format_float(self.poster.m2u(year_length))
            month_names = [
                locale.nl_langinfo(day)[:3]  # Get only first three letters
                for day in [
                    locale.MON_1,
                    locale.MON_2,
                    locale.MON_3,
                    locale.MON_4,
                    locale.MON_5,
                    locale.MON_6,
                    locale.MON_7,
                    locale.MON_8,
                    locale.MON_9,
                    locale.MON_10,
                    locale.MON_11,
                    locale.MON_12,
                ]
            ]
            km_or_mi = self.poster.u()
            g_year.add(
                dr.text(
                    f"{year}",
                    insert=offset.tuple(),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=year_style,
                ))

            g_year.add(
                dr.text(
                    f"{year_length_str} {km_or_mi}",
                    insert=(offset.tuple()[0] + 165, offset.tuple()[1] + 2),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=year_length_style,
                ))
            # add month name up to the poster one by one because of svg text auto trim the spaces.
            for num, name in enumerate(month_names):
                g_year.add(
                    dr.text(
                        f"{name}",
                        insert=(offset.tuple()[0] + 15.5 * num,
                                offset.tuple()[1] + 14),
                        fill=self.poster.colors["text"],
                        style=month_names_style,
                    ))

            rect_x = 10.0
            dom = (2.6, 2.6)
            # add every day of this year for 53 weeks and per week has 7 days
            for _i in range(54):
                rect_y = offset.y + year_size + 2
                for _j in range(7):
                    if int(github_rect_day.year) > year:
                        break
                    rect_y += 3.5
                    color = "#444444"
                    date_title = str(github_rect_day)
                    if date_title in self.poster.tracks_by_date:
                        tracks = self.poster.tracks_by_date[date_title]
                        length = sum([t.length() for t in tracks])
                        distance1 = self.poster.special_distance[
                            "special_distance"]
                        distance2 = self.poster.special_distance[
                            "special_distance2"]
                        has_special = distance1 < length < distance2
                        color = self.color(self.poster.length_range_by_date,
                                           length, has_special)
                        if length >= distance2:
                            special_color = self.poster.colors.get(
                                "special2") or self.poster.colors.get(
                                    "special")
                            if special_color is not None:
                                color = special_color
                        str_length = utils.format_float(
                            self.poster.m2u(length))
                        date_title = f"{date_title} {str_length} {km_or_mi}"

                    rect = dr.rect((rect_x, rect_y), dom, fill=color)
                    rect.set_desc(title=date_title)
                    g_year.add(rect)
                    github_rect_day += datetime.timedelta(1)
                rect_x += 3.5
            offset.y += 3.5 * 9 + year_size + 1.5