Beispiel #1
1
class Gauge(object):
    config = {
        'id'                    : None,
        'title'                 : 'Title',
        'titleFontColor'        : '#999999',
        'value'                 : 0,
        'valueFontColor'        : '#010101',
        'min'                   : 0,
        'max'                   : 100,
        'showMinMax'            : True,
        'gaugeWidthScale'       : 1.0,
        'gaugeColor'            : '#edebeb',
        'label'                 : "",
        'showInnerShadow'       : True,
        'shadowOpacity'         : 0.2,
        'shadowSize'            : 5,
        'shadowVerticalOffset'  : 3,
        'levelColors'           : ["#a9d70b", "#f9c802", "#ff0000"],
        'levelColorsGradient'   : True,
        'labelFontColor'        : "#b3b3b3",
        'showNeedle'            : False,
        'needleColor'           : "#b3b3b3",
        'canvasWidth'           : 400,
        'canvasHeight'          : 300,
    }

    def __init__(self, *args, **kwargs):
        for param_name, param_value in kwargs.items():
            if self.config.has_key(param_name):
                self.config[param_name] = param_value

        # Overflow values
        if self.config['value'] > self.config['max']:
            self.config['value'] = self.config['max']
        if self.config['value'] < self.config['min']:
            self.config['value'] = self.config['min']
        self.originalValue = self.config['value']

        self.canvas = Drawing(size=(self.config['canvasWidth'],
                                    self.config['canvasHeight']))

        canvasW = self.config['canvasWidth']
        canvasH = self.config['canvasHeight']

        self.canvas.add(self.canvas.rect(insert=(0, 0),
                                         size=(canvasW, canvasH),
                                         stroke="none",
                                         fill="#ffffff"))

        # widget dimensions
        widgetW, widgetH = None, None
        if ((canvasW / canvasH) > 1.25):
            widgetW = 1.25 * canvasH
            widgetH = canvasH
        else:
            widgetW = canvasW
            widgetH = canvasW / 1.25

        # delta 
        dx = (canvasW - widgetW)/2
        dy = (canvasH - widgetH)/2

        # title 
        titleFontSize = ((widgetH / 8) > 10) and (widgetH / 10) or 10
        titleX = dx + widgetW / 2
        titleY = dy + widgetH / 6.5

        # value 
        valueFontSize = ((widgetH / 6.4) > 16) and (widgetH / 6.4) or 16
        valueX = dx + widgetW / 2
        valueY = dy + widgetH / 1.4

        # label 
        labelFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        labelX = dx + widgetW / 2
        labelY = valueY + valueFontSize / 2 + 6

        # min 
        minFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        minX = dx + (widgetW / 10) + (widgetW / 6.666666666666667 * self.config['gaugeWidthScale']) / 2
        minY = dy + widgetH / 1.126760563380282

        # max
        maxFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        maxX = dx + widgetW - (widgetW / 10) - (widgetW / 6.666666666666667 * self.config['gaugeWidthScale']) / 2
        maxY = dy + widgetH / 1.126760563380282

        # parameters
        self.params = {
            'canvasW'         : canvasW,
            'canvasH'         : canvasH,
            'widgetW'         : widgetW,
            'widgetH'         : widgetH,
            'dx'              : dx,
            'dy'              : dy,
            'titleFontSize'   : titleFontSize,
            'titleX'          : titleX,
            'titleY'          : titleY,
            'valueFontSize'   : valueFontSize,
            'valueX'          : valueX,
            'valueY'          : valueY,
            'labelFontSize'   : labelFontSize,
            'labelX'          : labelX,
            'labelY'          : labelY,
            'minFontSize'     : minFontSize,
            'minX'            : minX,
            'minY'            : minY,
            'maxFontSize'     : maxFontSize,
            'maxX'            : maxX,
            'maxY'            : maxY
        }

        # gauge
        self.gauge = self.gauge_path(self.config['max'], self.config['min'], self.config['max'],
                                     self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                     self.params['dy'], self.config['gaugeWidthScale'],
                                     stroke='none',
                                     fill=self.config['gaugeColor'])

        self.canvas.add(self.gauge)

        # level
        percent_value = (self.config['value'] - self.config['min']) / (self.config['max'] - self.config['min'])
        self.level = self.gauge_path(self.config['value'], self.config['min'], self.config['max'],
                                     self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                     self.params['dy'], self.config['gaugeWidthScale'],
                                     stroke='none',
                                     fill=self.get_color_for_value(percent_value,
                                                                   self.config['levelColors'],
                                                                   self.config['levelColorsGradient']))
        self.canvas.add(self.level)

        # needle
        if self.config['showNeedle']:
            self.needle = self.needle_path(self.config['value'], self.config['min'], self.config['max'],
                                           self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                           self.params['dy'], self.config['gaugeWidthScale'],
                                           stroke='none',
                                           fill=self.config['needleColor'])
            self.canvas.add(self.needle)

        # Value
        else:
            text_config = {
                "font-size"     : "%d" % self.params['valueFontSize'],
                "font-weight"   : "bold",
                "font-family"   : "Arial",
                "fill"          : self.config['valueFontColor'],
                "fill-opacity"  : "1",
                "text-anchor"  : 'middle'
            }
            value_text = self.canvas.text('',
                                          insert=('%d' % self.params['valueX'],
                                                  '%d' % self.params['valueY']),
                                          **text_config)
            value_tspan = self.canvas.tspan(self.originalValue,
                                            dy=[8])
            value_text.add(value_tspan)
            self.canvas.add(value_text)

        # Add min & max value
        self.show_minmax()


    def save(self, path):
        svg = self.canvas.tostring()
        svg2png = getattr(cairosvg, 'svg2png')
        png_byte = svg2png(bytestring=svg)
        f = open(path,'w')
        f.write(png_byte)
        f.close()


    def gauge_path(self, value, val_min, val_max, w, h, dx, dy, gws, **extra):
        alpha = (1 - (value - val_min) / (val_max - val_min)) * math.pi
        Ro = w / 2 - w / 10
        Ri = Ro - w / 6.666666666666667 * gws
        Cx = w / 2 + dx
        Cy = h / 1.25 + dy

        Xo = w / 2 + dx + Ro * math.cos(alpha)
        Yo = h - (h - Cy) + dy - Ro * math.sin(alpha)
        Xi = w / 2 + dx + Ri * math.cos(alpha)
        Yi = h - (h - Cy) + dy - Ri * math.sin(alpha)

        path = []
        path.append(u"M%d,%d " % ((Cx - Ri), Cy))
        path.append(u"L%d,%d " % ((Cx - Ro), Cy))
        path.append(u"A%d,%d 0 0,1 %d,%d " % (Ro, Ro, Xo, Yo))
        path.append(u"L%d,%d " % (Xi, Yi))
        path.append(u"A%d,%d 0 0,0 %d,%d " % (Ri, Ri, (Cx - Ri), Cy))
        path.append(u"z ")

        return Path(d=path, **extra)

    def needle_path(self, value, val_min, val_max, w, h, dx, dy, gws, **extra):
        xO = w / 2 + dx
        yO = h / 1.25 + dy

        Rext = w / 2 - w / 10
        Rint = Rext - w / 6.666666666666667 * gws

        x_offset = xO
        y_offset = h - (h - yO) + dy

        val = (value - val_min) / (val_max - val_min)

        angle_b = val<0.5 and val*math.pi or (math.pi - val*math.pi) # Angle de la pointe
        angle_a = math.pi/2 - angle_b
        angle_c = math.pi/2 - angle_b

        rayon_base = 7
        rayon_b = Rint + (Rext-Rint)*10/100

        xA = x_offset + -1 * rayon_base * math.cos(angle_a)
        yA = y_offset - (val<0.5 and -1 or 1) * rayon_base * math.sin(angle_a)

        xC = x_offset + 1 * rayon_base * math.cos(angle_c)
        yC = y_offset - (val<0.5 and 1 or -1) * rayon_base * math.sin(angle_c)

        xB = x_offset + (val<0.5 and -1 or 1) * rayon_b * math.cos(angle_b)
        yB = y_offset - rayon_b * math.sin(angle_b)

        path = []
        path.append(u"M%d,%d " % (xA, yA))
        path.append(u"L%d,%d " % (xB, yB))
        path.append(u"L%d,%d " % (xC, yC))
        path.append(u"A%d,%d 0 1,1 %d,%d " % (rayon_base, rayon_base, xA, yA))
        path.append(u"z ")

        return Path(d=path, **extra)

    def get_color_for_value(self, pct, color, grad):
        no = len(color);
        if no == 1: return color[0]

        HEX = r'[a-fA-F\d]{2}'
        HEX_COLOR = r'#(?P<red>%(hex)s)(?P<green>%(hex)s)(?P<blue>%(hex)s)' % {'hex': HEX}
        inc = grad and (1 / (no - 1)) or (1 / no)
        colors = []
        i = 0
        while i < no:
            percentage = (grad) and (inc * i) or (inc * (i + 1))
            parts = re.match(HEX_COLOR,color[i]).groupdict()

            rval = int(parts['red'], 16)
            gval = int(parts['green'], 16)
            bval = int(parts['blue'], 16)
            colors.append({
                'pct': percentage,
                'color': {
                    'r': rval,
                    'g': gval,
                    'b': bval
                 }
            })
            i+=1

        if pct == 0:
            return 'rgb(%d,%d,%d)' % (colors[0]['color']['r'],
                                      colors[0]['color']['g'],
                                      colors[0]['color']['b'])

        i = 0
        while i < len(colors):
            if pct <= colors[i]['pct']:
                if (grad == True):
                    lower = colors[i-1]
                    upper = colors[i]
                    _range = upper['pct'] - lower['pct']
                    rangePct = (pct - lower['pct']) / _range
                    pctLower = 1 - rangePct
                    pctUpper = rangePct
                    color = {
                      'r': math.floor(lower['color']['r'] * pctLower + upper['color']['r'] * pctUpper),
                      'g': math.floor(lower['color']['g'] * pctLower + upper['color']['g'] * pctUpper),
                      'b': math.floor(lower['color']['b'] * pctLower + upper['color']['b'] * pctUpper)
                    }
                    return 'rgb(%d,%d,%d)' % (color['r'], color['g'], color['b'])
                else:
                    return 'rgb(%d,%d,%d)' % (colors[i]['color']['r'],
                                              colors[i]['color']['g'],
                                              colors[i]['color']['b']) 
            i+=1

    def show_minmax(self):
        # min
        txtMin_config = {
            "font-size"    : '%d' % self.params['minFontSize'],
            "font-weight"  : "normal",
            "font-family"  : "Arial",
            "fill"         : self.config['labelFontColor'],
            "fill-opacity" : self.config['showMinMax'] and "1" or "0",
            "text-anchor"  : 'middle'
        }
        txtMin = self.canvas.text(self.config['min'],
                                  insert=(self.params['minX'],
                                          self.params['minY']),
                                  **txtMin_config)

        self.canvas.add(txtMin)

        # max
        txtMax_config = {
            "font-size"    : '%d' % self.params['maxFontSize'],
            "font-weight"  :"normal",
            "font-family"  :"Arial",
            "fill"         : self.config['labelFontColor'],   
            "fill-opacity" : self.config['showMinMax'] and "1" or "0",
            "text-anchor"  : 'middle'
        }
        txtMax = self.canvas.text(self.config['max'],
                                  insert=(self.params['maxX'],
                                          self.params['maxY']),
                                  **txtMax_config)
        self.canvas.add(txtMax)
Beispiel #2
0
def raster_to_vector(image, path):
    drawing = Drawing(path, profile='tiny')
    width, height = image.size
    pixels = image.load()

    start_x = start_y = 0
    last_pixel = pixels[0, 0]
    for close_y in range(height):
        for close_x in range(width):
            pixel = pixels[close_x, close_y]
            # If pixel has different color
            if pixel != last_pixel:
                color = _RGB.format(*last_pixel)
                _add_rectangles(drawing, width, color,
                                start_x, start_y,
                                close_x, close_y)
                # Reset values
                last_pixel = pixel
                start_x = close_x
                start_y = close_y

    _add_rectangles(drawing, width, color,
                    start_x, start_y,
                    close_x, close_y)
    # Save constructed SVG
    try:
        drawing.save()
    except FileNotFoundError:
        makedirs(dirname(path))
        drawing.save()
def generate_frame(i, j, k):
    filename = str(i)+str(j)+str(k)+".svg"
    dwg = Drawing(filename, size=(300, 300))
    dwg.add(dwg.text('i = %d, j = %d, k %d' % (i, j, k), insert=(0.5, 20),
                     fill='red'))
    dwg.add(dwg.line((0, 0), (10, 0), stroke=rgb(10, 10, 16, '%')))
    dwg.save()
    pixel_width = 300
    return convert(pixel_width, filename)
Beispiel #4
0
def create_empty_chart(full_file_name):
    """Creates a chart of the proper dimensions with a white background."""
    num_days_in_week = 7
    num_weeks = math.ceil(NUM_DAYS_TO_SHOW / 7.0)
    if date.today().weekday() + 1 < NUM_DAYS_TO_SHOW % 7:
        # We need to draw NUM_DAYS_TO_SHOW % 7 extra days, but on the last week
        # we have only space for date.today().weekday() + 1 days.
        num_weeks += 1

    width = 2 * MARGIN + num_weeks * DAY_BOX_SIZE + \
        (num_weeks - 1) * DAY_BOX_SEPARATION
    height = 2 * MARGIN + num_days_in_week * DAY_BOX_SIZE + \
        (num_days_in_week - 1) * DAY_BOX_SEPARATION

    chart = Drawing(full_file_name, size=(width, height))
    chart.add(chart.rect(insert=(0, 0), size=(width, height), fill='white'))
    return chart
Beispiel #5
0
def create_svg_image(styles, board_size, hexagons):
    """
    Creates SVG drawing.

    The drawing contains all given css styles, a board (background rectangle)
    of given size and all given hexagons. The board can be styled using '.board'.
    All hexagonal fields can be styled using '.hex-field'. Fields can be also
    styled using 'hex-field-X', where X is the type of the field.
    :param styles iterable of css styles (strings)
    :param board_size tuple representing board size (width, height)
    :param hexagons iterable of hexagons (tuples in a form of (vertices, type) )
    :returns SVG Drawing object
    """
    svg_image = Drawing()
    for style in styles:
        svg_image.add(svg_image.style(style))
    svg_image.add(svg_image.rect(size=board_size, class_="board"))
    for hexagon in hexagons:
        svg_image.add(svg_image.polygon(hexagon.vertices, class_="hex-field hex-field-%d" % hexagon.type))
    return svg_image
Beispiel #6
0
    def test_single_bp_ins_exon(self):
        transcript = fusion.FusionTranscript()
        transcript.position = Interval(401258, 408265)
        transcript.exons = [
            genomic.Exon(401258, 401461, transcript=transcript),
            genomic.Exon(404799,
                         405254,
                         intact_end_splice=False,
                         transcript=transcript),
            genomic.Exon(405255,
                         405255,
                         intact_start_splice=False,
                         intact_end_splice=False,
                         transcript=transcript),
            genomic.Exon(405256,
                         408265,
                         intact_start_splice=False,
                         transcript=transcript)
        ]

        cfg = DiagramSettings(width=1500)
        canvas = Drawing(size=(cfg.width, 1000))
        drawing_width = cfg.width - cfg.label_left_margin - cfg.left_margin - cfg.right_margin
        canvas.add(
            draw_ustranscript(cfg,
                              canvas,
                              transcript,
                              target_width=drawing_width))
        if OUTPUT_SVG:
            canvas.saveas('test_single_bp_ins_exon.svg')
    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)
Beispiel #8
0
def box_with_char(
    drawing: svgwrite.Drawing,
    text: str,
    x=0,
    y=0,
    width=BOX_SIZE,
    height=BOX_SIZE,
    border_width=BORDER_WIDTH,
    fill="#fff",
    border="#888",
    char_width=4,
    char_height=12,
):
    """Render a box with a single character inside of it"""
    drawing.add(
        drawing.rect(
            insert=(x, y),
            size=(width, height),
            fill=fill,
            stroke=border,
            stroke_width=border_width,
        ))
    text_x = x - char_width * len(str(text)) + width // 2
    text_y = y + height // 2 + char_height // 2
    drawing.add(
        drawing.text(text,
                     insert=(text_x, text_y),
                     fill=svgwrite.rgb(50, 50, 50)))
Beispiel #9
0
def _draw_classical_double_line(drawing: Drawing, x1_coord: int, y1_coord: int,
                                x2_coord: int, y2_coord: int) -> None:
    """Draw a double line between (x1_coord, y1_coord) and (x2_coord, y2_coord).

    :param drawing: Drawing that will be used to draw.
    :param x1_coord: x-coordinate of the first point.
    :param y1_coord: y-coordinate of the first point.
    :param x2_coord: x-coordinate of the second point.
    :param y2_coord: y-coordinate of the second point.
    :raise NotImplementedError: when x1_coord != x2_coord and
    y1_coord != y2_coord (i.e. when the line is neither horizontal
    nor vertical).
    """
    x_increment, y_increment = 0, 0
    if x1_coord == x2_coord:
        x_increment = _constants.DOUBLE_LINES_SEPARATION
    elif y1_coord == y2_coord:
        y_increment = _constants.DOUBLE_LINES_SEPARATION
    else:
        raise NotImplementedError("The drawn line should be either horizontal "
                                  "or vertical.")
    drawing.add(
        drawing.line(start=(x1_coord - x_increment, y1_coord - y_increment),
                     end=(x2_coord - x_increment, y2_coord - y_increment),
                     stroke=_constants.GATE_BORDER_COLOR,
                     stroke_width=_constants.STROKE_THICKNESS))
    drawing.add(
        drawing.line(start=(x1_coord + x_increment, y1_coord + y_increment),
                     end=(x2_coord + x_increment, y2_coord + y_increment),
                     stroke=_constants.GATE_BORDER_COLOR,
                     stroke_width=_constants.STROKE_THICKNESS))
Beispiel #10
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
Beispiel #11
0
    def draw(self, start=0, end=None, ext='svg', name=None):
        if end is None:
            end = os.path.getsize(self.source_path)
        if name is None:
            name = self.source_path.name
        name = f"{name}.{ext}"

        if ext == 'svg':
            from svgwrite        import Drawing
            from svgwrite.shapes import Rect
            dwg = Drawing(name, profile='tiny')

        elif ext == 'dxf':
            from dxfwrite import DXFEngine as dxf
            dwg = dxf.drawing(name)

        with open(self.source_path, 'rb') as source_file:
            for i, bit in enumerate(bits(source_file, start, end)):
                if bit == self.invert:
                    x = (i // self.height) * self.scale
                    y = (-i % self.height) * self.scale

                    params = {
                        'insert': (x, y),
                        'size': (self.scale, self.scale)
                    }
                    if ext == 'dxf':
                        rect = DxfRect(**params).to_face3d()
                    else:
                        rect = Rect(**params)
                    dwg.add(rect)
        dwg.save()
Beispiel #12
0
 def test_single_bp_dup(self):
     transcript = fusion.FusionTranscript()
     transcript.position = Interval(1, 500)
     transcript.exons = [
         genomic.Exon(1, 7, transcript=transcript, intact_end_splice=False),
         genomic.Exon(8,
                      8,
                      transcript=transcript,
                      intact_start_splice=False,
                      intact_end_splice=False),
         genomic.Exon(9,
                      100,
                      transcript=transcript,
                      intact_start_splice=False),
         genomic.Exon(200, 500, transcript=transcript)
     ]
     cfg = DiagramSettings(width=1500)
     canvas = Drawing(size=(cfg.width, 1000))
     drawing_width = cfg.width - cfg.label_left_margin - cfg.left_margin - cfg.right_margin
     canvas.add(
         draw_ustranscript(cfg,
                           canvas,
                           transcript,
                           target_width=drawing_width))
     if OUTPUT_SVG:
         canvas.saveas('test_single_bp_dup.svg')
Beispiel #13
0
def raster_to_vector(image, path):
    drawing = Drawing(path, profile='tiny')
    width, height = image.size
    pixels = image.load()

    start_x = start_y = 0
    last_pixel = pixels[0, 0]
    for close_y in range(height):
        for close_x in range(width):
            pixel = pixels[close_x, close_y]
            # If pixel has different color
            if pixel != last_pixel:
                color = _RGB.format(*last_pixel)
                _add_rectangles(drawing, width, color, start_x, start_y,
                                close_x, close_y)
                # Reset values
                last_pixel = pixel
                start_x = close_x
                start_y = close_y

    _add_rectangles(drawing, width, color, start_x, start_y, close_x, close_y)
    # Save constructed SVG
    try:
        drawing.save()
    except FileNotFoundError:
        makedirs(dirname(path))
        drawing.save()
Beispiel #14
0
 def _draw_rings(self, dr: svgwrite.Drawing, center: XY, radius_range: ValueRange):
     length_range = self.poster.length_range_by_date
     ring_distance = self._determine_ring_distance()
     if ring_distance is None:
         return
     distance = ring_distance
     while distance < length_range.upper():
         radius = (
             radius_range.lower()
             + radius_range.diameter() * distance / length_range.upper()
         )
         dr.add(
             dr.circle(
                 center=center.tuple(),
                 r=radius,
                 stroke=self._ring_color,
                 stroke_opacity="0.2",
                 fill="none",
                 stroke_width=0.3,
             )
         )
         distance += ring_distance
class Builder(object):
    
    def __init__(self, name, commits, configuration, deltax=50.0, width=700.0, y=40.0, sep=20.0, image_size=40.0):
        self.commits = commits
        self.authors = AuthorList()
        self.initial_last_dates(configuration)
        self.position_function()
        height = y + sep + (self.max_elements + 1) * (image_size + sep)
        self.dwg = Drawing(name, size=(width + 2 * deltax, height))
        
        self.deltax = deltax
        self.width = width
        self.y = y
        self.sep = sep
        self.image_size = image_size
        
    def initial_last_dates(self, configuration):
        self.initial = self.commits[0]["date"]
        self.last = self.commits[-1]["date"]
        self.max_elements = 0

        for date_tuple, elements in configuration.items():
            date = datetime(*date_tuple).replace(tzinfo=timezone.utc)
            self.last = max(self.last, date)
            self.initial = min(self.initial, date)
            self.max_elements = max(self.max_elements, len(elements))
            
    def position_function(self):
        size = self.last.timestamp() - self.initial.timestamp()
        def position(date, y, deltax=0, deltay=0):
            return (self.deltax + (date.timestamp() - self.initial.timestamp()) / size * self.width + deltax, y + deltay)
        self.position = position
        
    def add(self, element):
        for xml in element.draw(self):
            self.dwg.add(xml)
            
    def save(self):
        self.dwg.save()
 def __init__(self, name, commits, configuration, deltax=50.0, width=700.0, y=40.0, sep=20.0, image_size=40.0):
     self.commits = commits
     self.authors = AuthorList()
     self.initial_last_dates(configuration)
     self.position_function()
     height = y + sep + (self.max_elements + 1) * (image_size + sep)
     self.dwg = Drawing(name, size=(width + 2 * deltax, height))
     
     self.deltax = deltax
     self.width = width
     self.y = y
     self.sep = sep
     self.image_size = image_size
Beispiel #17
0
def slice_file(f=None, resolution=0.1):
    print("Status: Loading File.")

    model = STLModel(f)
    scale = 10
    stats = model.stats()

    sub_vertex = Vector3(stats['extents']['x']['lower'],
                         stats['extents']['y']['lower'],
                         stats['extents']['z']['lower'])
    add_vertex = Vector3(0.5, 0.5, 0.5)

    model.xmin = model.xmax = None
    model.ymin = model.ymax = None
    model.zmin = model.zmax = None

    print("Status: Scaling Triangles.")

    for triangle in model.triangles:
        triangle.vertices[0] -= sub_vertex
        triangle.vertices[1] -= sub_vertex
        triangle.vertices[2] -= sub_vertex

        # The lines above have no effect on the normal.

        triangle.vertices[0] = (triangle.vertices[0] * scale) + add_vertex
        triangle.vertices[1] = (triangle.vertices[1] * scale) + add_vertex
        triangle.vertices[2] = (triangle.vertices[2] * scale) + add_vertex

        # Recalculate the triangle normal

        u = model.triangles[0].vertices[1] - model.triangles[0].vertices[0]
        v = model.triangles[0].vertices[2] - model.triangles[0].vertices[0]

        triangle.n = Normal((u.y * v.z) - (u.z * v.y),
                            (u.z * v.x) - (u.x * v.z),
                            (u.x * v.y) - (u.y * v.x))
        model.update_extents(triangle)

    print("Status: Calculating Slices")

    interval = scale * resolution
    stats = model.stats()
    print(stats)

    for targetz in range(0, int(stats['extents']['z']['upper']),
                         int(interval)):
        dwg = Drawing('outputs/svg/' + str(targetz) + '.svg', profile='tiny')
        pairs = model.slice_at_z(targetz)
        for pair in pairs:
            dwg.add(dwg.line(pair[0], pair[1], stroke=rgb(0, 0, 0, "%")))
        dwg.save()

    print("Status: Finished Outputting Slices")
Beispiel #18
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
 def draw(self, dr: svgwrite.Drawing, size: XY, offset: XY):
     """Draw the heatmap based on tracks."""
     normal_lines = []
     special_lines = []
     bbox = self._determine_bbox()
     for tr in self.poster.tracks:
         for line in utils.project(bbox, size, offset, tr.polylines):
             if tr.special:
                 special_lines.append(line)
             else:
                 normal_lines.append(line)
     for lines, color in [(normal_lines, self.poster.colors['track']),
                          (special_lines, self.poster.colors['special'])]:
         for opacity, width in [(0.1, 5.0), (0.2, 2.0), (1.0, 0.3)]:
             for line in lines:
                 dr.add(
                     dr.polyline(points=line,
                                 stroke=color,
                                 stroke_opacity=opacity,
                                 fill='none',
                                 stroke_width=width,
                                 stroke_linejoin='round',
                                 stroke_linecap='round'))
Beispiel #20
0
    def test_draw_template(self):
        # def draw_template(self, canvas, template, target_width, height, labels=None, colors=None):
        d = DiagramSettings()
        canvas = Drawing(size=(1000, 50))
        t = genomic.Template('1',
                             1,
                             100000,
                             bands=[
                                 BioInterval(None, 1, 8000, 'p1'),
                                 BioInterval(None, 10000, 15000, 'p2')
                             ])
        g = draw_template(d, canvas, t, 1000)
        canvas.add(g)
        canvas.attribs['height'] = g.height
        canvas = Drawing(size=(1000, 50))

        g = draw_template(d, canvas, TEMPLATE_METADATA['1'], 1000)
        self.assertEqual(
            d.breakpoint_top_margin + d.breakpoint_bottom_margin +
            d.template_track_height, g.height)
        canvas.add(g)
        canvas.attribs['height'] = g.height
        self.assertEqual(2, len(canvas.elements))
Beispiel #21
0
def save_radial_tree_plot(filename, root_list, step_size):

    #  define some params
    white = "rgb(255, 255, 255)"
    black = "rgb(0, 0, 0)"

    #  create the drawing surface
    svg_drawing = Drawing(filename=filename,
                          size=(SVG_SIZE, SVG_SIZE),
                          debug=True)

    #  create defs, in this case, just a single gradient
    rad_grad = svg_drawing.radialGradient(("50%", "50%"),
                                          "100%", ("50%", "50%"),
                                          id="rad_grad")
    rad_grad.add_stop_color("0%", black, 255)
    rad_grad.add_stop_color("100%", white, 255)
    svg_drawing.defs.add(rad_grad)

    tree_plot = svg_drawing.mask(
        id='treeplot',
        style=
        'stroke: black; stroke-width: 3; fill: none; stroke-linecap: round; stroke-opacity: 0.5;'
    )

    tree_plot.add(svg_drawing.rect((0, 0), (SVG_SIZE, SVG_SIZE)).fill(white))

    for root in root_list:
        draw_radial_tree_node(svg_drawing, tree_plot, root, rad_grad,
                              step_size)

    base_rect = svg_drawing.rect((0, 0), (SVG_SIZE, SVG_SIZE),
                                 mask="url(#treeplot)").fill(black)
    svg_drawing.add(base_rect)
    svg_drawing.add(tree_plot)

    svg_drawing.save()
Beispiel #22
0
def make_x(wall: Wall, svg: Drawing):
    rngx = np.arange(2, 146 - 2, 0.25)

    waves = Polygon.Polygon()

    w2 = 0.85

    for y in np.arange(80, 100 + 120, 5.0):
        points = []
        for x in rngx:
            fxy = f(x + wall.x0, y / 1.66)
            points.append((x + wall.x0, y + fxy + w2))

        for x in reversed(rngx):
            fxy = f(x + wall.x0, y / 1.66)
            points.append((x + wall.x0, y + fxy - w2))

        p = Polygon.Polygon(points)
        waves += wall.window & p

    svg.save()

    waves &= wall.window
    wall.result = wall.wall - wall.window + waves
Beispiel #23
0
    def draw(self,
             svg: svgwrite.Drawing,
             point: np.array,
             color: Color,
             opacity=1.0,
             tags: Dict[str, Any] = None,
             outline: bool = False):
        """
        Draw icon shape into SVG file.

        :param svg: output SVG file
        :param point: icon position
        :param color: fill color
        :param opacity: icon opacity
        :param tags: tags to be displayed as hint
        :param outline: draw outline for the icon
        """
        point = np.array(list(map(int, point)))

        path: svgwrite.path.Path = self.get_path(svg, point)
        path.update({"fill": color.hex})
        if outline:
            opacity: float = 0.5

            path.update({
                "fill": color.hex,
                "stroke": color.hex,
                "stroke-width": 2.2,
                "stroke-linejoin": "round"
            })
        if opacity != 1.0:
            path.update({"opacity": opacity})
        if tags:
            title: str = "\n".join(map(lambda x: x + ": " + tags[x], tags))
            path.set_desc(title=title)
        svg.add(path)
Beispiel #24
0
def make_lines2(layer, drawing: svgwrite.Drawing, inpts):
    tail = inpts

    while len(tail) > 1:
        head, *tail = tail

        minpt = min(tail, key=lambda x: distance(x, head))
        if not in_circle(circle_radius, mid_point(
                head, minpt)) and distance(minpt, head) < 15:
            layer.add(
                drawing.line(head,
                             minpt,
                             stroke=svgwrite.rgb(255, 10, 16, '%'),
                             stroke_width=8,
                             stroke_linecap='round'))
Beispiel #25
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)
Beispiel #26
0
def make_y(wall: Wall, svg: Drawing):
    rngy = np.arange(wall.y0 - 2, wall.y1 + 2, 0.25)

    waves = Polygon.Polygon()

    w2 = 0.85

    for x in np.arange(wall.x0 - 20, wall.x1 + 20, 6.0):
        points = []
        for y in rngy:
            fxy = f(x, y / 1.66)
            points.append((x + fxy - w2, y))

        for y in reversed(rngy):
            fxy = f(x, y / 1.66)
            points.append((x + fxy + w2, y))

        p = Polygon.Polygon(points)
        waves += wall.window & p

    svg.save()

    waves &= wall.window
    wall.result = wall.wall - wall.window + waves
 def _draw_circle_segment(
     self,
     dr: svgwrite.Drawing,
     g: svgwrite.container.Group,
     tracks: typing.List[Track],
     a1: float,
     a2: float,
     rr: ValueRange,
     center: XY,
     values: str = "",
     key_times: str = "",
 ) -> None:
     length = sum([t.length() for t in tracks])
     has_special = len([t for t in tracks if t.special]) > 0
     color = self.color(self.poster.length_range_by_date, length,
                        has_special)
     max_length = self.poster.length_range_by_date.upper()
     if self._max_distance:
         max_length = self._max_distance.to_base_units()
     assert max_length is not None
     r1 = rr.lower()
     assert r1 is not None
     r2 = rr.interpolate((length / max_length).magnitude)
     sin_a1, cos_a1 = math.sin(a1), math.cos(a1)
     sin_a2, cos_a2 = math.sin(a2), math.cos(a2)
     path = dr.path(
         d=("M", center.x + r1 * sin_a1, center.y - r1 * cos_a1),
         fill=color,
         stroke="none",
     )
     path.push("l", (r2 - r1) * sin_a1, (r1 - r2) * cos_a1)
     path.push(
         f"a{r2},{r2} 0 0,0 {r2 * (sin_a2 - sin_a1)},{r2 * (cos_a1 - cos_a2)}"
     )
     path.push("l", (r1 - r2) * sin_a2, (r2 - r1) * cos_a2)
     date_title = str(tracks[0].start_time().date())
     str_length = utils.format_float(self.poster.m2u(length))
     path.set_desc(title=f"{date_title} {str_length} {self.poster.u()}")
     if self.poster.with_animation:
         path.add(
             svgwrite.animate.Animate(
                 "opacity",
                 dur=f"{self.poster.animation_time}s",
                 values=values,
                 keyTimes=key_times,
                 repeatCount="indefinite",
             ))
     g.add(path)
    def _draw_track(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, tr: Track, size: XY, offset: XY) -> None:
        color = self.color(self.poster.length_range, tr.length(), tr.special)
        str_length = utils.format_float(self.poster.m2u(tr.length()))

        date_title = str(tr.start_time.date()) if tr.start_time else "Unknown Date"
        for line in utils.project(tr.bbox(), size, offset, tr.polylines):
            polyline = dr.polyline(
                points=line,
                stroke=color,
                fill="none",
                stroke_width=0.5,
                stroke_linejoin="round",
                stroke_linecap="round",
            )
            polyline.set_desc(title=f"{date_title} {str_length} {self.poster.u()}")
            g.add(polyline)
Beispiel #29
0
def square_in_grid(image: Drawing,
                   row: int,
                   column: int,
                   fill,
                   offsets=(),
                   title=None):
    x_offset = offsets[0] if len(offsets) else 0
    y_offset = offsets[1] if len(offsets) > 1 else 0
    left = grid_square_left(column, x_offset)
    top = grid_square_top(row, y_offset)
    rect = image.rect(insert=(left, top),
                      size=(GRID_SQUARE, GRID_SQUARE),
                      fill=fill)
    if title is not None:
        rect.set_desc(title=title)
    return rect
Beispiel #30
0
def test_translate():
    translate = shape.translate(-50, -50)
    xml = ElementTree.tostring(translate.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 50.000, 50.000 L 70.000, 90.000 '
                   'L 110.000, 50.000 Z" />')
    drawing_translate = Drawing(dirname.joinpath('translate.svg'),
                                size=(200, 200),
                                stroke='black',
                                stroke_width=1)
    drawing_translate.add(translate.get_svg())
    drawing_translate.save()
 def save(self):
     """Saves the illustration into :attr:`output_filename`."""
     drawing = Drawing(self.output_filename,
                       size=self.size,
                       stroke=self.stroke,
                       stroke_width=self.stroke_width,
                       font_size=self.font_size,
                       font_family=self.font_family)
     for region in self._regions:
         drawing.add(region.get_svg())
     drawing.save(pretty=True)
Beispiel #32
0
def test_flip():
    flip = shape.flip(90)
    xml = ElementTree.tostring(flip.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 80.000, 100.000 L 60.000, 140.000 '
                   'L 20.000, 100.000 Z" />')
    drawing_flip = Drawing(dirname.joinpath('flip.svg'),
                           size=(200, 200),
                           stroke='black',
                           stroke_width=1)
    drawing_flip.add(flip.get_svg())
    drawing_flip.save()
Beispiel #33
0
def test_scale():
    scale = shape.scale(0.5)
    xml = ElementTree.tostring(scale.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 50.000, 50.000 L 60.000, 70.000 '
                   'L 80.000, 50.000 Z" />')
    drawing_scale = Drawing(dirname.joinpath('scale.svg'),
                            size=(200, 200),
                            stroke='black',
                            stroke_width=1)
    drawing_scale.add(scale.get_svg())
    drawing_scale.save()
Beispiel #34
0
def _draw_registers_names_and_lines(drawing: Drawing,
                                    circuit_width: int,
                                    json_circuit: str,
                                    show_clbits: bool) -> None:

    # First we draw the names of each register
    qubit_labels = json_circuit['header'].get('qubit_labels', [])
    clbit_labels = json_circuit['header'].get('clbit_labels', []) if show_clbits else []
    ## 1. Compute the font size that will be used to keep good dimensions
    font_size = _constants.REGISTER_NAME_FONT_SIZE
    for qubit_label in itertools.chain(qubit_labels, clbit_labels):
        qubit_text_name = "{}[{}]".format(*qubit_label)
        desired_width = (_constants.REGISTER_NAME_WIDTH
                         - _constants.REGISTER_NAME_LEFT_BORDER
                         - _constants.REGISTER_NAME_RIGHT_BORDER)
        adapted_font_size = _helpers.adapt_text_font_size(qubit_text_name,
                                                          desired_width,
                                                          _constants.MAX_REGISTER_NAME_HEIGHT)
        font_size = min(font_size, adapted_font_size)
    ## 2. Draw the bit names
    y_coord = _constants.VERTICAL_BORDER
    for bit_label in itertools.chain(qubit_labels, clbit_labels):
        qubit_text_name = "{}[{}]".format(*bit_label)
        drawing.add(
            drawing.text(
                qubit_text_name,
                insert=(_constants.REGISTER_NAME_WIDTH - _constants.REGISTER_NAME_RIGHT_BORDER,
                        y_coord + _constants.FONT_SIZE_CENTER_VERTICALLY_MULTIPLIER * font_size),
                text_anchor="end",
                font_size=font_size
            )
        )
        y_coord += _constants.REGISTER_LINES_VERTICAL_SPACING


    # Then we draw the register lines
    y_coord = _constants.VERTICAL_BORDER

    # Start with quantum registers
    quantum_register_number = json_circuit['header'].get('number_of_qubits', 0)
    for _ in range(quantum_register_number):
        drawing.add(drawing.line(start=(_constants.REGISTER_NAME_WIDTH, y_coord),
                                 end=(circuit_width, y_coord),
                                 stroke=_constants.GATE_BORDER_COLOR,
                                 stroke_width=_constants.STROKE_THICKNESS))
        y_coord += _constants.REGISTER_LINES_VERTICAL_SPACING

    # And see if we want to plot classical registers.
    if show_clbits:
        classical_register_number = json_circuit['header'].get('number_of_clbits', 0)
        for _ in range(classical_register_number):
            _draw_classical_double_line(drawing, _constants.REGISTER_NAME_WIDTH,
                                        y_coord, circuit_width, y_coord)
            y_coord += _constants.REGISTER_LINES_VERTICAL_SPACING
Beispiel #35
0
 def convert(self):
     c = canvas = Drawing()
     img = self._image
     mean, std = img[:,:,1].mean(), img[:,:,1].std()
     for x,y in product(xrange(self.width), xrange(self.height)):
         hue, lum, sat = self._pixelval(x,y)
         perimeter = self.peri(lum, mean, std)
         color = Color.from_hls(hue, lum, sat)
         if perimeter > self._size_threshold:
             shape = c.circle(
                     center = (
                         (self._size_of_pixel + self._d_pixel) * x,
                         (self._size_of_pixel + self._d_pixel) * y),
                     r      = self._size_of_pixel * perimeter / 2,
                     fill = rgb(*color.rgb8))
             canvas.add(shape)
     return canvas
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
Beispiel #37
0
 def draw_diagram(self) -> None:
     n_countries: int = self.model.rowCount()
     if n_countries > 0:
         style: SvgStyle = self.svg_style
         delta_angle: float = 2.0*math.pi/n_countries
         max_value: float = max(self.model.values)
         dwg = Drawing(self.temp_svg_file.fileName(), profile='tiny', viewBox='-250 -250 500 500')
         for idx, v in enumerate(self.model.values):
             x: float = style.line_length * v/max_value * math.sin(idx * delta_angle)
             y: float = -style.line_length * v/max_value * math.cos(idx * delta_angle)
             dwg.add(shapes.Line(start=(0, 0), end=(x, y),
                                 stroke=style.line_color, stroke_width=style.line_width))
             radius: float = style.circle_rad
             if style.circle_rad_normalization:
                 radius *= v/max_value
             dwg.add(shapes.Circle(center=(x, y), r=radius,
                                   stroke=style.circle_stroke_color, stroke_width=style.circle_stroke_width,
                                   fill=style.circle_fill_color))
         dwg.save(pretty=True)
         self.load_svg(self.temp_svg_file.fileName())
Beispiel #38
0
def export_svg_svgwrite(fn, paths, w, h, line_width=0.1):

  from svgwrite import Drawing
  w_str = "{}pt".format(w)
  h_str = "{}pt".format(h)

  dwg = Drawing(filename = fn,
                size = (w_str, h_str),
                viewBox=("0 0 {} {}".format(w,h)))

  for path in paths:
    if(len(path) > 1):
      str_list = []
      str_list.append("M {},{}".format(path[0,0],path[0,1]))
      for e in path[1:]:
        str_list.append(" L {},{}".format(e[0],e[1]))
      s = ''.join(str_list)
      dwg.add(dwg.path(s).stroke(color="rgb(0%,0%,0%)",width=line_width).fill("none"))

  dwg.save()
def create_svg(file, surface, controls_sequence = None, sn = None):
	min_x, max_x = None, None
	min_y, max_y = None, None
	
	for polygon in surface.polygons:
		for vertex in polygon.vertices:
			if min_x is None:
				min_x, max_x = vertex[0], vertex[0]
				min_y, max_y = vertex[1], vertex[1]
			else:
				min_x, max_x = min(vertex[0], min_x), max(vertex[0], max_x)
				min_y, max_y = min(vertex[1], min_y), max(vertex[1], max_y)
				
				
	a = (min_x, max_x, min_y, max_y)
	b = (max_x - min_x, max_y - min_y, 10.0)


	surface_view = Drawing(size = (max_x - min_x, max_y - min_y))
	
	
	def correct_vertex(vertex, surface_bounds, canvas_bounds):
		x_coordinate, y_coordinate                       = vertex
		left_bound, right_bound, bottom_bound, top_bound = surface_bounds
		canvas_width, canvas_height, canvas_padding      = canvas_bounds
		
		
		x_coordinate_scaling = \
			(canvas_width - 2.0 * canvas_padding) \
				/ (right_bound - left_bound)
				
		y_coordinate_scaling = \
			(canvas_height - 2.0 * canvas_padding) \
				/ (top_bound - bottom_bound)
				
				
		x_coordinate = \
			x_coordinate_scaling * (x_coordinate - left_bound) \
				+ canvas_padding
				
		y_coordinate = \
			y_coordinate_scaling * (y_coordinate - bottom_bound) \
				+ canvas_padding
				
		y_coordinate = canvas_height - y_coordinate
		
		
		return x_coordinate, y_coordinate
		
		
	for polygon in surface.polygons:
		vertices = \
			[correct_vertex((x_coordinate, y_coordinate), a, b) \
				for x_coordinate, y_coordinate, z_coordinate \
				in  polygon.vertices]
				
				
		if surface.maximal_impossibility - surface.minimal_impossibility > 0.0:
			relative_impossibility = \
				(polygon.impossibility - surface.minimal_impossibility) \
					/ (surface.maximal_impossibility - surface.minimal_impossibility)
		else:
			relative_impossibility = 0.0
			
		fill_color_red_component   = round(255.0 * relative_impossibility)
		fill_color_green_component = round(255.0 - 255.0 * relative_impossibility)
		fill_color_blue_component  = 0
		fill_color                 = \
			rgb(
				fill_color_red_component,
				fill_color_green_component,
				fill_color_blue_component
			)
			
		polygon_view = \
			Polygon(
				vertices,
				stroke_width = 1,
				stroke       = rgb(0, 0, 0),
				fill         = fill_color
			)
			
		surface_view.add(polygon_view)
		
		
	if sn is not None:
		for polygon_index, polygon in enumerate(surface.polygons):
			polygon_index_view = \
				Text(
					str(polygon_index),
					insert = \
						correct_vertex(
							(polygon.center[0], polygon.center[1]),
							a, b
						)
				)
				
			surface_view.add(polygon_index_view)
			
			
	# if sn is not None:
	# 	from svgwrite.text import Text
	# 	for state in sn:
	# 		polygon = state.polygon
	# 		polygon_number = sn[state]
			
	# 		polygon_center      = polygon.center[0], polygon.center[1]
	# 		q,w = correct_vertex(polygon_center, a, b)
	# 		polygon_center_view = \
	# 			Text(
	# 				str(polygon_number),
	# 				insert = (q+2,w+2),
	# 				style = "font-size: 50%; font-color: #808080"
	# 			)
				
	# 		surface_view.add(polygon_center_view)
			
			
	if controls_sequence is not None:
		last_state          = None
		last_polygon_center = None
		smoother            = Smoother(surface = surface, smoothing_depth = 1)
		
		
		for state in controls_sequence:
			polygon = state.polygons_sequence[-1]
			
			polygon_center      = polygon.center[0], polygon.center[1]
			polygon_center_view = \
				Circle(
					correct_vertex(polygon_center, a, b),
					2,
					stroke_width = 0,
					fill         = rgb(0, 0, 0),
				)
				
			surface_view.add(polygon_center_view)
			
			
			if last_state is not None:
				smoother.push_transfer(
					last_state.get_transfer(state)
				)
				
				first_transfer_point, second_transfer_point = \
					smoother.transfers_points_sequence[0]
					
					
				first_trek_view = \
					Line(
						correct_vertex(last_polygon_center, a, b),
						correct_vertex(
							(first_transfer_point.coordinates[0],
								first_transfer_point.coordinates[1]),
							a,
							b
						),
						stroke_width = 1,
						stroke       = rgb(0, 0, 0),
					)
					
				first_trek_end_view = \
					Circle(
						correct_vertex(
							(first_transfer_point.coordinates[0],
								first_transfer_point.coordinates[1]),
							a,
							b
						),
						2,
						stroke_width = 0,
						fill         = rgb(0, 0, 0),
					)
					
				second_trek_view = \
					Line(
						correct_vertex(
							(second_transfer_point.coordinates[0],
								second_transfer_point.coordinates[1]),
							a,
							b
						),
						correct_vertex(polygon_center, a, b),
						stroke_width = 1,
						stroke       = rgb(0, 0, 0),
					)
					
				second_trek_start_view = \
					Circle(
						correct_vertex(
							(second_transfer_point.coordinates[0],
								second_transfer_point.coordinates[1]),
							a,
							b
						),
						2,
						stroke_width = 0,
						fill         = rgb(0, 0, 0),
					)
					
					
				surface_view.add(first_trek_view)
				surface_view.add(first_trek_end_view)
				surface_view.add(second_trek_view)
				surface_view.add(second_trek_start_view)
				
				
			last_state          = state
			last_polygon_center = polygon_center
			
			
	surface_view.write(file)
	
Beispiel #40
0
tabpad = " "

fontsize = 12
titlefont = 16

w = width - 2*padding
h = height - 2*padding - titlefont - fontsize

line_width = 200


# styling for svg
css = 'text { font-family: "Georgia", Georgia, serif; }'

# 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())
def diode_svg_frame(illuminated, num_across=9, num_down=8, frame=0, single_route=-1):
    filename = "diode{:03d}.svg".format(frame)
    led_symbol = "resources/Symbol_LED.svg"
    image_width = 600
    image_height = 400
    right_margin = 30
    bottom_margin = 30
    dwg = Drawing(filename,
                  size=(image_width+right_margin, image_height+bottom_margin),
                  style="background-color:white")
    # create a white background rectangle
    dwg.add(dwg.rect(size=(image_width+right_margin, image_height+bottom_margin),
                     insert=(0, 0), fill="white"))

    LED_dimensions = [106.0, 71.0]
    LED_points = [[35, 68], [35, 31], [66, 50]]
    LED_entries = [[4, 50], [103, 50]]
    aspect_ratio = LED_dimensions[1]/LED_dimensions[0]
    new_width = image_width/num_across
    new_height = new_width*aspect_ratio
    LED_scale = 0.75
    LED_offsets = [new_width*LED_scale/2, new_height*LED_scale]
    junction_radius = 0.8
    elements = []
    for i in range(0, num_across):
        x_pos = new_width*(num_across-i-1)
        if illuminated[1] >= illuminated[0]:
            incoming_wire = illuminated[1] + 1
        else:
            incoming_wire = illuminated[1]
        if i == incoming_wire:
            connection = "+"
            text_fill = "red"
        elif i == illuminated[0]:
            connection = "-"
            text_fill = "black"
        else:
            connection = "NC"
            text_fill = "gray"
        wire_label = "{} {}".format(i+1, connection)
        # the input wire title
        dwg.add(dwg.text(wire_label, insert=(x_pos+new_width-10, 10),
                             fill=text_fill))
        for j in range(0, num_down):
            y_pos = (image_height/num_down)*j
            position = [x_pos+LED_offsets[0], y_pos+LED_offsets[1]]
            scale = [LED_scale*new_width/LED_dimensions[0],
                     LED_scale*new_height/LED_dimensions[1]]
            # the led svg
            dwg.add(dwg.image(led_symbol, insert=position,
                              size=(new_width*LED_scale, new_height*LED_scale)))
            if i == illuminated[0] and j == illuminated[1] and single_route == -1:
                points = []
                for point in LED_points:
                    points.append(transform_point(point, scale, position))
                # the illuminated svg box
                dwg.add(dwg.polygon(points=points, fill="yellow"))
                line_fill = "green"
                stroke_width = 1
                insert_pos = -1
            else:
                line_fill = "black"
                insert_pos = 0
                stroke_width = 0.5
            # for each LED, we want to generate a line going from the input
            # to its output
            entry_point = transform_point(LED_entries[0], scale, position)
            if i > j:
                incoming_line_points = [[new_width*(num_across-j)-LED_offsets[0], 0],
                                    [new_width*(num_across-j)-LED_offsets[0], y_pos+20],
                                    [entry_point[0], y_pos+20], entry_point]
            elif j > i:
                incoming_line_points = [
                    [new_width * (num_across - j - 1) - LED_offsets[0], 0],
                    [new_width * (num_across - j - 1) - LED_offsets[0],
                     entry_point[1] + LED_offsets[1]],
                    [entry_point[0], entry_point[1]+LED_offsets[1]], entry_point]
            elif i == j:
                incoming_line_points = [
                    [new_width * (num_across - j - 1) - LED_offsets[0], 0],
                    [new_width * (num_across - j - 1) - LED_offsets[0], entry_point[1]], entry_point]
            else:
                incoming_line_points = []
            elements.insert(insert_pos,
                            make_junction_line(dwg, incoming_line_points,
                                               junction_radius, line_fill,
                                               stroke_width))
            # outgoing line
            exit_point = transform_point(LED_entries[1], scale, position)
            outgoing_line_points = [exit_point,
                                    [x_pos+new_width-LED_offsets[0],
                                     exit_point[1]],
                                    [x_pos+new_width-LED_offsets[0], 0]]
            elements.insert(insert_pos,
                            make_junction_line(dwg, outgoing_line_points,
                                               junction_radius, line_fill,
                                               stroke_width))
            route_points = [[new_width * (num_across - j - 1) - LED_offsets[0],
                             0]]
            for point in range(0, single_route+1):
                if point < i:
                    route_points.append([new_width * (num_across - j - 1) - LED_offsets[0], 0])

            # now create the network
            nodes = []
            for i in range(0, num_across):
                for j in range(0, num_down):
                    nodes.append(entry_point)
                    nodes.append(exit_point)
    # flatten the elements structure
    elements = sum(elements, [])
    print(elements)
    # the lines should be drawn last so that they are layered on top of all
    # other elements
    #for element in elements:
    #    dwg.add(element)
    dwg.save()
    return convert(image_width, filename)
Beispiel #42
0
def export_workflow(workflow, store, size=None):
    """Construct a SVG description for a workflow.

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

    Returns:
        (str) - SVG description of workflow
    """
    # check that each node has a position
    for node in workflow['nodes']:
        if 'x' not in node or 'y' not in node:
            raise UserWarning("need to position workflow first")

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

    # draw
    paper = Drawing("workflow.svg", size, id="repr")

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

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="bg_failed")
    lg.add_stop_color(0, color='#ff8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    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)

    for i, link in enumerate(workflow['links']):
        draw_link(paper, workflow, store, link, i)

    bbs = []
    for i, node in enumerate(workflow['nodes']):
        bb = draw_node(paper, workflow, store, node, i)
        bbs.append(bb)

    # reformat whole drawing to fit screen
    xmin = min(bb[0] for bb in bbs) - draw_padding
    xmax = max(bb[2] for bb in bbs) + draw_padding
    ymin = min(bb[1] for bb in bbs) - draw_padding
    ymax = max(bb[3] for bb in bbs) + draw_padding

    w = float(size[0])
    h = float(size[1])
    xratio = (xmax - xmin) / w
    yratio = (ymax - ymin) / h
    if xratio > yratio:
        xsize = int(xratio * w)
        ysize = int(xratio * h)
        ymin -= (ysize - (ymax - ymin)) / 2
    else:
        xsize = int(yratio * w)
        ysize = int(yratio * h)
        xmin -= (xsize - (xmax - xmin)) / 2

    paper.viewbox(xmin, ymin, xsize, ysize)

    return paper.tostring(), (xmin, ymin, xsize, ysize)
Beispiel #43
0
def draw():
	drawing = Drawing(drawing_file_name, drawing_size)
	
	
	first_circle_view = \
		Circle(
			center       = first_circle_center,
			r            = first_circle_radius,
			fill_opacity = 0,
			stroke       = rgb(0, 0, 0),
			stroke_width = 1
		)
		
	first_circle_center_view = \
		Circle(
			center       = first_circle_center,
			r            = 3,
			fill         = rgb(0, 0, 0),
			stroke_width = 0
		)
		
	drawing.add(first_circle_view)
	drawing.add(first_circle_center_view)
	
	
	second_circle_view = \
		Circle(
			center       = second_circle_center,
			r            = second_circle_radius,
			fill_opacity = 0,
			stroke       = rgb(0, 0, 0),
			stroke_width = 1
		)
		
	second_circle_center_view = \
		Circle(
			center       = second_circle_center,
			r            = 3,
			fill         = rgb(0, 0, 0),
			stroke_width = 0
		)
		
	drawing.add(second_circle_view)
	drawing.add(second_circle_center_view)
	
	
	drawing.save()
Beispiel #44
0
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
Beispiel #45
0
	def visualize(self, trajectory, output_file):
		drawing = Drawing()
		
		
		
		# Определение параметров образов состояний аппарата
		machine_view_length, machine_view_width = self.__machine_view_size
		
		coordinates_scaling = machine_view_length / self.__machine_length
		
		machine_diameter = \
			((machine_view_length * 2.0) ** 2.0 + machine_view_width ** 2.0) \
				** 0.5
				
		machine_radius = machine_diameter / 2.0
		
		
		
		# Создание последовательности записываемых состояний аппарата
		def generate_states_sequence():
			spawn_time = 0.0
			
			for trajectory_time, state in trajectory:
				if trajectory_time >= spawn_time:
					spawn_time += self.__time_interval
					
					yield state
					
					
		states_sequence = generate_states_sequence()
		
		
		
		# Запись последовательности состояний аппарата
		is_view_box_initialized                = False
		view_box_minimal_x, view_box_minimal_y = 0.0, 0.0
		view_box_maximal_x, view_box_maximal_y = 0.0, 0.0
		
		
		for state in states_sequence:
			# Создание образа состояния аппарата
			state_view_angle  = - state.coordinates[2] / math.pi * 180.0
			state_view_center = \
				state.coordinates[0] * coordinates_scaling, \
					- state.coordinates[1] * coordinates_scaling
					
			state_view_position = \
				state_view_center[0], \
					state_view_center[1] - machine_view_width / 2.0
					
			state_view = \
				Rect(
					insert       = state_view_position,
					size         = self.__machine_view_size,
					fill         = rgb(255, 255, 255),
					stroke       = rgb(0, 0, 0),
					stroke_width = 1
				)
				
			state_view.rotate(
				state_view_angle,
				center = state_view_center
			)
			
			
			# Добавление образа состояния аппарата к образу траектории
			drawing.add(state_view)
			
			if is_view_box_initialized:
				view_box_minimal_x, view_box_minimal_y = \
					min(state_view_center[0], view_box_minimal_x), \
						min(state_view_center[1], view_box_minimal_y)
						
				view_box_maximal_x, view_box_maximal_y = \
					max(state_view_center[0], view_box_maximal_x), \
						max(state_view_center[1], view_box_maximal_y)
			else:
				is_view_box_initialized = True
				
				view_box_minimal_x, view_box_minimal_y = \
					state_view_center[0], \
						state_view_center[1]
						
				view_box_maximal_x, view_box_maximal_y = \
					state_view_center[0], \
						state_view_center[1]
						
						
						
		# Настройка отображения образа траектории
		drawing.viewbox(
			minx   = view_box_minimal_x - machine_radius,
			miny   = view_box_minimal_y - machine_radius,
			width  = view_box_maximal_x - view_box_minimal_x + machine_diameter,
			height = view_box_maximal_y - view_box_minimal_y + machine_diameter
		)
		
		
		
		# Запись образа траектории в файл
		try:
			drawing.write(output_file)
		except:
			raise Exception() #!!!!! Генерировать хорошие исключения
"""
Figure built manually in SVG.

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
Beispiel #47
0
def disvg(paths=None, colors=None,
          filename=os_path.join(getcwd(), 'disvg_output.svg'),
          stroke_widths=None, nodes=None, node_colors=None, node_radii=None,
          openinbrowser=True, timestamp=False,
          margin_size=0.1, mindim=600, dimensions=None,
          viewbox=None, text=None, text_path=None, font_size=None,
          attributes=None, svg_attributes=None, svgwrite_debug=False, paths2Drawing=False):
    """Takes in a list of paths and creates an SVG file containing said paths.
    REQUIRED INPUTS:
        :param paths - a list of paths

    OPTIONAL INPUT:
        :param colors - specifies the path stroke color.  By default all paths
        will be black (#000000).  This paramater can be input in a few ways
        1) a list of strings that will be input into the path elements stroke
            attribute (so anything that is understood by the svg viewer).
        2) a string of single character colors -- e.g. setting colors='rrr' is
            equivalent to setting colors=['red', 'red', 'red'] (see the
            'color_dict' dictionary above for a list of possibilities).
        3) a list of rgb 3-tuples -- e.g. colors = [(255, 0, 0), ...].

        :param filename - the desired location/filename of the SVG file
        created (by default the SVG will be stored in the current working
        directory and named 'disvg_output.svg').

        :param stroke_widths - a list of stroke_widths to use for paths
        (default is 0.5% of the SVG's width or length)

        :param nodes - a list of points to draw as filled-in circles

        :param node_colors - a list of colors to use for the nodes (by default
        nodes will be red)

        :param node_radii - a list of radii to use for the nodes (by default
        nodes will be radius will be 1 percent of the svg's width/length)

        :param text - string or list of strings to be displayed

        :param text_path - if text is a list, then this should be a list of
        path (or path segments of the same length.  Note: the path must be
        long enough to display the text or the text will be cropped by the svg
        viewer.

        :param font_size - a single float of list of floats.

        :param openinbrowser -  Set to True to automatically open the created
        SVG in the user's default web browser.

        :param timestamp - if True, then the a timestamp will be appended to
        the output SVG's filename.  This will fix issues with rapidly opening
        multiple SVGs in your browser.

        :param margin_size - The min margin (empty area framing the collection
        of paths) size used for creating the canvas and background of the SVG.

        :param mindim - The minimum dimension (height or width) of the output
        SVG (default is 600).

        :param dimensions - The (x,y) display dimensions of the output SVG.
        I.e. this specifies the `width` and `height` SVG attributes. Note that 
        these also can be used to specify units other than pixels. Using this 
        will override the `mindim` parameter.

        :param viewbox - This specifies the coordinated system used in the svg.
        The SVG `viewBox` attribute works together with the the `height` and 
        `width` attrinutes.  Using these three attributes allows for shifting 
        and scaling of the SVG canvas without changing the any values other 
        than those in `viewBox`, `height`, and `width`.  `viewbox` should be 
        input as a 4-tuple, (min_x, min_y, width, height), or a string 
        "min_x min_y width height".  Using this will override the `mindim` 
        parameter.

        :param attributes - a list of dictionaries of attributes for the input
        paths.  Note: This will override any other conflicting settings.

        :param svg_attributes - a dictionary of attributes for output svg.
        
        :param svgwrite_debug - This parameter turns on/off `svgwrite`'s 
        debugging mode.  By default svgwrite_debug=False.  This increases 
        speed and also prevents `svgwrite` from raising of an error when not 
        all `svg_attributes` key-value pairs are understood.
        
        :param paths2Drawing - If true, an `svgwrite.Drawing` object is 
        returned and no file is written.  This `Drawing` can later be saved 
        using the `svgwrite.Drawing.save()` method.

    NOTES:
        * The `svg_attributes` parameter will override any other conflicting 
        settings.

        * Any `extra` parameters that `svgwrite.Drawing()` accepts can be 
        controlled by passing them in through `svg_attributes`.

        * The unit of length here is assumed to be pixels in all variables.

        * If this function is used multiple times in quick succession to
        display multiple SVGs (all using the default filename), the
        svgviewer/browser will likely fail to load some of the SVGs in time.
        To fix this, use the timestamp attribute, or give the files unique
        names, or use a pause command (e.g. time.sleep(1)) between uses.
    """


    _default_relative_node_radius = 5e-3
    _default_relative_stroke_width = 1e-3
    _default_path_color = '#000000'  # black
    _default_node_color = '#ff0000'  # red
    _default_font_size = 12


    # append directory to filename (if not included)
    if os_path.dirname(filename) == '':
        filename = os_path.join(getcwd(), filename)

    # append time stamp to filename
    if timestamp:
        fbname, fext = os_path.splitext(filename)
        dirname = os_path.dirname(filename)
        tstamp = str(time()).replace('.', '')
        stfilename = os_path.split(fbname)[1] + '_' + tstamp + fext
        filename = os_path.join(dirname, stfilename)

    # check paths and colors are set
    if isinstance(paths, Path) or is_path_segment(paths):
        paths = [paths]
    if paths:
        if not colors:
            colors = [_default_path_color] * len(paths)
        else:
            assert len(colors) == len(paths)
            if isinstance(colors, str):
                colors = str2colorlist(colors,
                                       default_color=_default_path_color)
            elif isinstance(colors, list):
                for idx, c in enumerate(colors):
                    if is3tuple(c):
                        colors[idx] = "rgb" + str(c)

    # check nodes and nodes_colors are set (node_radii are set later)
    if nodes:
        if not node_colors:
            node_colors = [_default_node_color] * len(nodes)
        else:
            assert len(node_colors) == len(nodes)
            if isinstance(node_colors, str):
                node_colors = str2colorlist(node_colors,
                                            default_color=_default_node_color)
            elif isinstance(node_colors, list):
                for idx, c in enumerate(node_colors):
                    if is3tuple(c):
                        node_colors[idx] = "rgb" + str(c)

    # set up the viewBox and display dimensions of the output SVG
    # along the way, set stroke_widths and node_radii if not provided
    assert paths or nodes
    stuff2bound = []
    if viewbox:
        if not isinstance(viewbox, str):
            viewbox = '%s %s %s %s' % viewbox
        if dimensions is None:
            dimensions = viewbox.split(' ')[2:4]
    elif dimensions:
        dimensions = tuple(map(str, dimensions))
        def strip_units(s):
            return re.search(r'\d*\.?\d*', s.strip()).group()
        viewbox = '0 0 %s %s' % tuple(map(strip_units, dimensions))
    else:
        if paths:
            stuff2bound += paths
        if nodes:
            stuff2bound += nodes
        if text_path:
            stuff2bound += text_path
        xmin, xmax, ymin, ymax = big_bounding_box(stuff2bound)
        dx = xmax - xmin
        dy = ymax - ymin

        if dx == 0:
            dx = 1
        if dy == 0:
            dy = 1

        # determine stroke_widths to use (if not provided) and max_stroke_width
        if paths:
            if not stroke_widths:
                sw = max(dx, dy) * _default_relative_stroke_width
                stroke_widths = [sw]*len(paths)
                max_stroke_width = sw
            else:
                assert len(paths) == len(stroke_widths)
                max_stroke_width = max(stroke_widths)
        else:
            max_stroke_width = 0

        # determine node_radii to use (if not provided) and max_node_diameter
        if nodes:
            if not node_radii:
                r = max(dx, dy) * _default_relative_node_radius
                node_radii = [r]*len(nodes)
                max_node_diameter = 2*r
            else:
                assert len(nodes) == len(node_radii)
                max_node_diameter = 2*max(node_radii)
        else:
            max_node_diameter = 0

        extra_space_for_style = max(max_stroke_width, max_node_diameter)
        xmin -= margin_size*dx + extra_space_for_style/2
        ymin -= margin_size*dy + extra_space_for_style/2
        dx += 2*margin_size*dx + extra_space_for_style
        dy += 2*margin_size*dy + extra_space_for_style
        viewbox = "%s %s %s %s" % (xmin, ymin, dx, dy)

        if dx > dy:
            szx = str(mindim) + 'px'
            szy = str(int(ceil(mindim * dy / dx))) + 'px'
        else:
            szx = str(int(ceil(mindim * dx / dy))) + 'px'
            szy = str(mindim) + 'px'
        dimensions = szx, szy

    # Create an SVG file
    if svg_attributes is not None:
        dimensions = (svg_attributes.get("width", dimensions[0]),
                      svg_attributes.get("height", dimensions[1]))
        debug = svg_attributes.get("debug", svgwrite_debug)
        dwg = Drawing(filename=filename, size=dimensions, debug=debug,
                      **svg_attributes)
    else:
        dwg = Drawing(filename=filename, size=dimensions, debug=svgwrite_debug,
                      viewBox=viewbox)

    # add paths
    if paths:
        for i, p in enumerate(paths):
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            if attributes:
                good_attribs = {'d': ps}
                for key in attributes[i]:
                    val = attributes[i][key]
                    if key != 'd':
                        try:
                            dwg.path(ps, **{key: val})
                            good_attribs.update({key: val})
                        except Exception as e:
                            warn(str(e))

                dwg.add(dwg.path(**good_attribs))
            else:
                dwg.add(dwg.path(ps, stroke=colors[i],
                                 stroke_width=str(stroke_widths[i]),
                                 fill='none'))

    # add nodes (filled in circles)
    if nodes:
        for i_pt, pt in enumerate([(z.real, z.imag) for z in nodes]):
            dwg.add(dwg.circle(pt, node_radii[i_pt], fill=node_colors[i_pt]))

    # add texts
    if text:
        assert isinstance(text, str) or (isinstance(text, list) and
                                         isinstance(text_path, list) and
                                         len(text_path) == len(text))
        if isinstance(text, str):
            text = [text]
            if not font_size:
                font_size = [_default_font_size]
            if not text_path:
                pos = complex(xmin + margin_size*dx, ymin + margin_size*dy)
                text_path = [Line(pos, pos + 1).d()]
        else:
            if font_size:
                if isinstance(font_size, list):
                    assert len(font_size) == len(text)
                else:
                    font_size = [font_size] * len(text)
            else:
                font_size = [_default_font_size] * len(text)
        for idx, s in enumerate(text):
            p = text_path[idx]
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            # paragraph = dwg.add(dwg.g(font_size=font_size[idx]))
            # paragraph.add(dwg.textPath(ps, s))
            pathid = 'tp' + str(idx)
            dwg.defs.add(dwg.path(d=ps, id=pathid))
            txter = dwg.add(dwg.text('', font_size=font_size[idx]))
            txter.add(txt.TextPath('#'+pathid, s))

    if paths2Drawing:
        return dwg
      
    # save svg
    if not os_path.exists(os_path.dirname(filename)):
        makedirs(os_path.dirname(filename))
    dwg.save()

    # re-open the svg, make the xml pretty, and save it again
    xmlstring = md_xml_parse(filename).toprettyxml()
    with open(filename, 'w') as f:
        f.write(xmlstring)

    # try to open in web browser
    if openinbrowser:
        try:
            open_in_browser(filename)
        except:
            print("Failed to open output SVG in browser.  SVG saved to:")
            print(filename)
Beispiel #48
0
    def __init__(self, *args, **kwargs):
        for param_name, param_value in kwargs.items():
            if self.config.has_key(param_name):
                self.config[param_name] = param_value

        # Overflow values
        if self.config['value'] > self.config['max']:
            self.config['value'] = self.config['max']
        if self.config['value'] < self.config['min']:
            self.config['value'] = self.config['min']
        self.originalValue = self.config['value']

        self.canvas = Drawing(size=(self.config['canvasWidth'],
                                    self.config['canvasHeight']))

        canvasW = self.config['canvasWidth']
        canvasH = self.config['canvasHeight']

        self.canvas.add(self.canvas.rect(insert=(0, 0),
                                         size=(canvasW, canvasH),
                                         stroke="none",
                                         fill="#ffffff"))

        # widget dimensions
        widgetW, widgetH = None, None
        if ((canvasW / canvasH) > 1.25):
            widgetW = 1.25 * canvasH
            widgetH = canvasH
        else:
            widgetW = canvasW
            widgetH = canvasW / 1.25

        # delta 
        dx = (canvasW - widgetW)/2
        dy = (canvasH - widgetH)/2

        # title 
        titleFontSize = ((widgetH / 8) > 10) and (widgetH / 10) or 10
        titleX = dx + widgetW / 2
        titleY = dy + widgetH / 6.5

        # value 
        valueFontSize = ((widgetH / 6.4) > 16) and (widgetH / 6.4) or 16
        valueX = dx + widgetW / 2
        valueY = dy + widgetH / 1.4

        # label 
        labelFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        labelX = dx + widgetW / 2
        labelY = valueY + valueFontSize / 2 + 6

        # min 
        minFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        minX = dx + (widgetW / 10) + (widgetW / 6.666666666666667 * self.config['gaugeWidthScale']) / 2
        minY = dy + widgetH / 1.126760563380282

        # max
        maxFontSize = ((widgetH / 16) > 10) and (widgetH / 16) or 10
        maxX = dx + widgetW - (widgetW / 10) - (widgetW / 6.666666666666667 * self.config['gaugeWidthScale']) / 2
        maxY = dy + widgetH / 1.126760563380282

        # parameters
        self.params = {
            'canvasW'         : canvasW,
            'canvasH'         : canvasH,
            'widgetW'         : widgetW,
            'widgetH'         : widgetH,
            'dx'              : dx,
            'dy'              : dy,
            'titleFontSize'   : titleFontSize,
            'titleX'          : titleX,
            'titleY'          : titleY,
            'valueFontSize'   : valueFontSize,
            'valueX'          : valueX,
            'valueY'          : valueY,
            'labelFontSize'   : labelFontSize,
            'labelX'          : labelX,
            'labelY'          : labelY,
            'minFontSize'     : minFontSize,
            'minX'            : minX,
            'minY'            : minY,
            'maxFontSize'     : maxFontSize,
            'maxX'            : maxX,
            'maxY'            : maxY
        }

        # gauge
        self.gauge = self.gauge_path(self.config['max'], self.config['min'], self.config['max'],
                                     self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                     self.params['dy'], self.config['gaugeWidthScale'],
                                     stroke='none',
                                     fill=self.config['gaugeColor'])

        self.canvas.add(self.gauge)

        # level
        percent_value = (self.config['value'] - self.config['min']) / (self.config['max'] - self.config['min'])
        self.level = self.gauge_path(self.config['value'], self.config['min'], self.config['max'],
                                     self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                     self.params['dy'], self.config['gaugeWidthScale'],
                                     stroke='none',
                                     fill=self.get_color_for_value(percent_value,
                                                                   self.config['levelColors'],
                                                                   self.config['levelColorsGradient']))
        self.canvas.add(self.level)

        # needle
        if self.config['showNeedle']:
            self.needle = self.needle_path(self.config['value'], self.config['min'], self.config['max'],
                                           self.params['widgetW'], self.params['widgetH'], self.params['dx'],
                                           self.params['dy'], self.config['gaugeWidthScale'],
                                           stroke='none',
                                           fill=self.config['needleColor'])
            self.canvas.add(self.needle)

        # Value
        else:
            text_config = {
                "font-size"     : "%d" % self.params['valueFontSize'],
                "font-weight"   : "bold",
                "font-family"   : "Arial",
                "fill"          : self.config['valueFontColor'],
                "fill-opacity"  : "1",
                "text-anchor"  : 'middle'
            }
            value_text = self.canvas.text('',
                                          insert=('%d' % self.params['valueX'],
                                                  '%d' % self.params['valueY']),
                                          **text_config)
            value_tspan = self.canvas.tspan(self.originalValue,
                                            dy=[8])
            value_text.add(value_tspan)
            self.canvas.add(value_text)

        # Add min & max value
        self.show_minmax()