def drawCircle(self):
        colorList = self.dataSourceTableWithoutXcolumn.rowsColors
        xCenter = self.xCenter
        yCenter = self.yCenter
        # ========================================================================
        x = self.r / (len(self.dataSourceTableWithoutXcolumn.columns))
        r = self.r + x
        # ================================================================
        for column in self.dataSourceTableWithoutXcolumn.columns:
            if column.columnType == enums.ColumnDataType.Measures.value:
                if (column != self.xColumn):
                    r -= (x)
                    oldEndangle = 0
                    endAngle = 0
                    length = 0
                    b = 0
                    for cell, cell2, i in zip(
                            self.xColumn.cells, column.cells,
                            range(0, len(self.xColumn.cells))):
                        if (i != 0):
                            length += self.heightView / len(self.xColumn.cells)
                            startangle = oldEndangle
                            endAngle += self.getAngle(double(cell2.value),
                                                      column)
                            oldEndangle = endAngle
                            radiansconversion = np.pi / 180.
                            xstartpoint = xCenter + r * np.cos(
                                startangle * radiansconversion)
                            ystartpoint = yCenter - r * np.sin(
                                startangle * radiansconversion)
                            xendpoint = xCenter + r * np.cos(
                                endAngle * radiansconversion)
                            yendpoint = yCenter - r * np.sin(
                                endAngle * radiansconversion)
                            large_arc_flag = 0
                            if endAngle - startangle > 180: large_arc_flag = 1
                            M = ("M %s %s" % (xstartpoint, ystartpoint))
                            a = ("A %s %s 0 %s 0 %s %s" %
                                 (r, r, large_arc_flag, xendpoint, yendpoint))
                            L = ("L %s %s" % (xCenter, yCenter))
                            p = draw.Path(stroke_width=self.stroke,
                                          stroke="white",
                                          fill=colorList[i - 1],
                                          fill_opacity=1,
                                          d=M + a + L,
                                          Class=str(self.Index))
                            self.metaData.append(
                                str(self.xColumn.name + " : " +
                                    str(cell.value) + "->" + column.name +
                                    " : " + str(
                                        self.percentageOfValue(
                                            cell2.value, column)) + "%"))
                            self.Index += 1

                            p.Z()
                            self.d.append(p)
                            if (b == 0):
                                text = str(cell.value)
                                c = draw.Circle(self.widthView -
                                                self.widthView / 4.5,
                                                length,
                                                self.stroke * 2,
                                                fill=colorList[i - 1],
                                                fill_opacity=1,
                                                stroke_width=0)
                                t = draw.Text(
                                    text=str(text),
                                    fontSize=self.stroke * 4,
                                    style="font-size :" + str(self.stroke * 4),
                                    x=self.widthView - self.widthView / 6,
                                    y=length - length / 50)
                                if self.animation:
                                    t.appendAnim(
                                        draw.Animate(
                                            'x',
                                            str((length / 150) - 0.2) + 's',
                                            from_or_values=0,
                                            to=self.widthView -
                                            self.widthView / 6,
                                            repeatCount='1'))
                                    c.appendAnim(
                                        draw.Animate('cx',
                                                     str(length / 150) + 's',
                                                     from_or_values=0,
                                                     to=self.widthView -
                                                     self.widthView / 4.5,
                                                     repeatCount='1'))
                                    c.appendAnim(
                                        draw.Animate(
                                            'r',
                                            '3.2s',
                                            from_or_values=self.stroke * 2 * 5,
                                            to=abs(self.stroke * 2),
                                            repeatCount='1'))

                                self.d.append(t)
                                self.d.append(c)

                    b += 1
    draw.Lines(-80,
               -45,
               70,
               -49,
               95,
               49,
               -90,
               40,
               close=False,
               fill='#eeee00',
               stroke='black'))

d.append(draw.Rectangle(0, 0, 40, 50, fill='#1248ff'))
d.append(draw.Circle(-40, -10, 30, fill='red', stroke_width=2, stroke='black'))

p = draw.Path(stroke_width=2, stroke='green', fill='black', fill_opacity=0.5)
p.M(-30, 5)  # Start path at point (-30, 5)
p.l(60, 30)  # Draw line to (60, 30)
p.h(-70)  # Draw horizontal line to x=-70
p.Z()  # Draw line to start
d.append(p)

d.append(
    draw.ArcLine(60,
                 -20,
                 20,
                 60,
                 270,
                 stroke='red',
                 stroke_width=5,
                 fill='red',
Beispiel #3
0
def draw_bloch_sphere(d,
                      inner_proj=euclid3d.identity(3),
                      label='',
                      axis=None,
                      rot_proj=None,
                      rot_deg=180,
                      outer_labels=(),
                      inner_labels=(),
                      extra_opacity=1,
                      inner_opacity=1,
                      background='white'):
    spin = euclid3d.rotation(3, 0, 2, 2 * np.pi / 16 / 2 * 1.001)
    tilt = euclid3d.rotation(3, 1, 2, np.pi / 8)
    trans = tilt @ spin @ euclid3d.axis_swap((1, 2, 0))
    proj = euclid3d.perspective3d(np.pi / 8, view_size=4) @ trans
    zx = euclid3d.axis_swap((2, 0, 1))
    xy = euclid3d.identity(3)
    yz = euclid3d.axis_swap((1, 2, 0))
    proj_zx = proj @ zx
    proj_xy = proj @ xy
    proj_yz = proj @ yz

    if background:
        d.append(draw.Rectangle(-100, -100, 200, 200, fill=background))

    def draw_band(proj,
                  trans,
                  r_outer=1,
                  r_inner=0.9,
                  color='black',
                  z_mul=1,
                  opacity=1,
                  divs=4,
                  d=d,
                  **kwargs):
        color = (color *
                 divs)[:divs] if isinstance(color, list) else [color] * divs
        points = np.array([[-1, -1, 1, 1], [-1, 1, 1, -1]]).T
        sqr12 = 0.5**0.5
        overlap = np.pi / 500 * (divs != 4)
        start_end_points = [
            np.array([[
                np.cos(pr - 2 * np.pi / divs - overlap),
                np.sin(pr - 2 * np.pi / divs - overlap)
            ], [np.cos(pr + overlap),
                np.sin(pr + overlap)],
                      [np.cos(pr - np.pi / divs),
                       np.sin(pr - np.pi / divs)]])
            for pr in np.linspace(0, 2 * np.pi, num=divs, endpoint=False)
        ]
        for i in range(divs):
            p = draw.Path(fill=color[i],
                          stroke='none',
                          stroke_width=0.002,
                          **kwargs,
                          opacity=opacity)
            z = trans.project_point(
                (r_inner + r_outer) / 2 * start_end_points[i][2])[2]
            e = shapes.EllipseArc.fromBoundingQuad(
                *proj.project_list(points * r_outer)[:, :2].flatten(),
                *proj.project_list(start_end_points[i] *
                                   r_outer)[:, :2].flatten(),
            )
            if e: e.drawToPath(p)
            if r_inner > 0:
                e = shapes.EllipseArc.fromBoundingQuad(
                    *proj.project_list(points * r_inner)[:, :2].flatten(),
                    *proj.project_list(start_end_points[i] *
                                       r_inner)[:, :2].flatten(),
                )
                if e:
                    e.reversed().drawToPath(p, includeL=True)
            p.Z()
            d.append(p, z=z * z_mul)
            if False:
                d.draw(shapes.EllipseArc.fromBoundingQuad(
                    *proj.project_list(
                        (r_outer + r_inner) / 2 * points)[:, :2].flatten(),
                    *proj.project_list((r_outer + r_inner) / 2 *
                                       start_end_points[i])[:, :2].flatten(),
                ),
                       fill='none',
                       stroke_width=0.02,
                       stroke=color[i],
                       **kwargs,
                       z=z * z_mul)

    xycolors = ['#56e', '#239', '#56e', '#56e']
    yzcolors = ['#e1e144', '#909022', '#e1e144', '#e1e144']
    zxcolors = ['#9e2', '#6a1', '#9e2', '#9e2']

    draw_band(proj_xy, trans @ xy, 1, 0.925, z_mul=10, color=xycolors)
    draw_band(proj_yz, trans @ yz, 1, 0.925, z_mul=10, color=yzcolors)
    draw_band(proj_zx, trans @ zx, 1, 0.925, z_mul=10, color=zxcolors)

    # Inner
    g = draw.Group(opacity=inner_opacity)
    z_center = trans.project_point((0, 0, 0))[2]
    d.append(g, z=z_center)
    inner_xy = proj @ inner_proj @ xy
    # Darker colors: #34b, #a8a833, #7b2
    draw_band(proj @ inner_proj @ xy,
              trans @ inner_proj @ xy,
              0.8,
              0.7,
              color=xycolors,
              d=g)
    draw_band(proj @ inner_proj @ yz,
              trans @ inner_proj @ yz,
              0.8,
              0.7,
              color=yzcolors,
              divs=4,
              d=g)
    draw_band(proj @ inner_proj @ zx,
              trans @ inner_proj @ zx,
              0.8,
              0.7,
              color=zxcolors,
              divs=8 // 2,
              d=g)
    elevation_lines = False
    if elevation_lines:
        for elevation in (*np.linspace(0, np.pi / 2, 4, True)[1:-1],
                          *np.linspace(-np.pi / 2, 0, 3, False)[1:]):
            y = 0.75 * np.sin(elevation)
            r = 0.75 * np.cos(elevation)
            draw_band(proj @ inner_proj @ xy @ euclid3d.translation((0, 0, y)),
                      trans @ inner_proj @ xy @ euclid3d.translation(
                          (0, 0, y)),
                      r_outer=r - 0.01,
                      r_inner=r + 0.01,
                      color='#bbb',
                      opacity=1,
                      d=g)
    arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto')
    arrow.append(
        draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True))
    g.append(draw.Line(*inner_xy.p2(-0.65, 0, 0),
                       *inner_xy.p2(0.6, 0, 0),
                       stroke='black',
                       stroke_width=0.015,
                       marker_end=arrow),
             z=z_center)
    g.append(draw.Line(*inner_xy.p2(0, -0.65, 0),
                       *inner_xy.p2(0, 0.6, 0),
                       stroke='black',
                       stroke_width=0.015,
                       marker_end=arrow),
             z=z_center)
    g.append(draw.Line(*inner_xy.p2(0, 0, -0.65),
                       *inner_xy.p2(0, 0, 0.6),
                       stroke='black',
                       stroke_width=0.015,
                       marker_end=arrow),
             z=z_center)
    for pt, (x_off, y_off), elem in inner_labels:
        x, y = (proj @ inner_proj).p2(*pt)
        g.append(draw.Use(elem, x + x_off, y + y_off), z=10000)

    # Outer arrows and text
    arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=4, orient='auto')
    arrow.append(
        draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='black', close=True))
    d.append(draw.Line(*proj_xy.p2(1, 0, 0),
                       *proj_xy.p2(1.2, 0, 0),
                       stroke='black',
                       stroke_width=0.02,
                       marker_end=arrow),
             z=100)
    d.append(draw.Line(*proj_xy.p2(0, 1, 0),
                       *proj_xy.p2(0, 1.2, 0),
                       stroke='black',
                       stroke_width=0.02,
                       marker_end=arrow),
             z=100)
    d.append(draw.Line(*proj_xy.p2(0, 0, 1),
                       *proj_xy.p2(0, 0, 1.2),
                       stroke='black',
                       stroke_width=0.02,
                       marker_end=arrow),
             z=100)
    d.append(
        draw.Line(*proj_xy.p2(-1, 0, 0),
                  *proj_xy.p2(-1.2, 0, 0),
                  stroke='black',
                  stroke_width=0.02))
    d.append(
        draw.Line(*proj_xy.p2(0, -1, 0),
                  *proj_xy.p2(0, -1.2, 0),
                  stroke='black',
                  stroke_width=0.02))
    d.append(
        draw.Line(*proj_xy.p2(0, 0, -1),
                  *proj_xy.p2(0, 0, -1.2),
                  stroke='black',
                  stroke_width=0.02))
    d.append(draw.Text(['X'],
                       0.2,
                       *proj_xy.p2(1.7, 0, 0),
                       center=True,
                       fill='black'),
             z=100)
    d.append(draw.Text(['Y'],
                       0.2,
                       *proj_xy.p2(0, 1.35, 0),
                       center=True,
                       fill='black'),
             z=100)
    d.append(draw.Text(['Z'],
                       0.2,
                       *proj_xy.p2(0, 0, 1.4),
                       center=True,
                       fill='black'),
             z=100)
    for pt, (x_off, y_off), elem in outer_labels:
        x, y = proj.p2(*pt)
        d.append(draw.Use(elem, x + x_off, y + y_off), z=10000)

    # Extra annotations
    #label='', axis=None, rot_proj=None
    if label:
        d.append(
            draw.Text([label],
                      0.4,
                      -0.6,
                      1.2,
                      center=True,
                      fill='#c00',
                      text_anchor='end',
                      opacity=extra_opacity))
    if axis:
        g = draw.Group(opacity=extra_opacity)
        axis = np.array(axis, dtype=float)
        axis_len = 1.18
        axis /= np.linalg.norm(axis)
        arrow = draw.Marker(-0.1, -0.5, 0.9, 0.5, scale=3, orient='auto')
        arrow.append(
            draw.Lines(-0.1, -0.5, -0.1, 0.5, 0.9, 0, fill='#e00', close=True))
        z = 100  #10 * proj_xy.project_point(axis*1)[2]
        g.append(
            draw.Line(*proj_xy.p2(0, 0, 0),
                      *proj_xy.p2(*axis * axis_len),
                      stroke='#e00',
                      stroke_width=0.04,
                      marker_end=arrow))
        d.append(g, z=z)

    if rot_proj is not None:
        rot_proj = inner_proj @ rot_proj
        r_inner, r_outer = 0.1, 0.16
        points = np.array([[-1, -1, 1, 1], [-1, 1, 1, -1]]).T
        start_end_points = np.array([[1, 0], [-1, 0], [0, 1]])
        p = draw.Path(fill='orange',
                      fill_rule='nonzero',
                      opacity=extra_opacity)
        z = 9 * (trans @ rot_proj).project_point(start_end_points[2])[2]
        e = shapes.EllipseArc.fromBoundingQuad(
            *(proj @ rot_proj).project_list(points * r_outer)[:, :2].flatten(),
            *(proj @ rot_proj).project_list(start_end_points *
                                            r_outer)[:, :2].flatten(),
        )
        if e: e.reversed().drawToPath(p)
        e = shapes.EllipseArc.fromBoundingQuad(
            *(proj @ rot_proj).project_list(points * r_inner)[:, :2].flatten(),
            *(proj @ rot_proj).project_list(start_end_points *
                                            r_inner)[:, :2].flatten(),
        )
        if e:
            e.drawToPath(p, includeL=True)
        sa = 2.5 * (r_outer - r_inner)
        xa = -(r_inner + r_outer) / 2
        p.L(*(proj @ rot_proj).p2(xa, 0.3 * sa))
        p.L(*(proj @ rot_proj).p2(xa + 0.5 * sa, 0.3 * sa))
        p.L(*(proj @ rot_proj).p2(xa, -0.7 * sa))
        p.L(*(proj @ rot_proj).p2(xa - 0.5 * sa, 0.3 * sa))
        p.L(*(proj @ rot_proj).p2(xa, 0.3 * sa))
        p.Z()
        d.append(p, z=z)

    return d
Beispiel #4
0
 def draw_band(proj,
               trans,
               r_outer=1,
               r_inner=0.9,
               color='black',
               z_mul=1,
               opacity=1,
               divs=4,
               d=d,
               **kwargs):
     color = (color *
              divs)[:divs] if isinstance(color, list) else [color] * divs
     points = np.array([[-1, -1, 1, 1], [-1, 1, 1, -1]]).T
     sqr12 = 0.5**0.5
     overlap = np.pi / 500 * (divs != 4)
     start_end_points = [
         np.array([[
             np.cos(pr - 2 * np.pi / divs - overlap),
             np.sin(pr - 2 * np.pi / divs - overlap)
         ], [np.cos(pr + overlap),
             np.sin(pr + overlap)],
                   [np.cos(pr - np.pi / divs),
                    np.sin(pr - np.pi / divs)]])
         for pr in np.linspace(0, 2 * np.pi, num=divs, endpoint=False)
     ]
     for i in range(divs):
         p = draw.Path(fill=color[i],
                       stroke='none',
                       stroke_width=0.002,
                       **kwargs,
                       opacity=opacity)
         z = trans.project_point(
             (r_inner + r_outer) / 2 * start_end_points[i][2])[2]
         e = shapes.EllipseArc.fromBoundingQuad(
             *proj.project_list(points * r_outer)[:, :2].flatten(),
             *proj.project_list(start_end_points[i] *
                                r_outer)[:, :2].flatten(),
         )
         if e: e.drawToPath(p)
         if r_inner > 0:
             e = shapes.EllipseArc.fromBoundingQuad(
                 *proj.project_list(points * r_inner)[:, :2].flatten(),
                 *proj.project_list(start_end_points[i] *
                                    r_inner)[:, :2].flatten(),
             )
             if e:
                 e.reversed().drawToPath(p, includeL=True)
         p.Z()
         d.append(p, z=z * z_mul)
         if False:
             d.draw(shapes.EllipseArc.fromBoundingQuad(
                 *proj.project_list(
                     (r_outer + r_inner) / 2 * points)[:, :2].flatten(),
                 *proj.project_list((r_outer + r_inner) / 2 *
                                    start_end_points[i])[:, :2].flatten(),
             ),
                    fill='none',
                    stroke_width=0.02,
                    stroke=color[i],
                    **kwargs,
                    z=z * z_mul)
Beispiel #5
0
def toSVG(read_path, path, path2):
    pth = read_path.split("/")
    for i in pth[-1]:
        if i == '.':
            dotindx = pth[-1].index(".", 0)
            pth[-1] = pth[-1][0:dotindx]

    ############

    ####################
    # parsing the def file
    def_parser = DefParser(read_path)
    def_parser.parse()
    macro = ""
    for key, val in def_parser.components.comp_dict.items():
        x = str(val).split()
        macro = macro + " " + x[3] + " " + str(x[5]).strip("[,") + " " + str(
            x[6]).strip("]") + " " + str(x[7])
    nets = []
    for key, val in def_parser.nets.net_dict.items(
    ):  # extracting nets information and putting in list
        nets += str(val).split()
    # print(nets)

    def_scale = def_parser.scale  # scalling the def
    # print("DEF scale: ",def_scale)

    MACRO = macro.split()  # DEF INFO CARRIER
    # print(MACRO)
    # getting the die area of the circuit
    z = def_parser.diearea

    pos = re.split('[, ()]', str(z))

    # diearea coordinates in string
    x1 = pos[1]
    # diearea coordinates in string
    x2 = pos[3]
    # diearea coordinates in string
    x3 = pos[7]
    # diearea coordinates in string
    x4 = pos[9]

    dx0 = int(x1)  # diearea coordinates in int
    dy0 = int(x2)  # diearea coordinates in int
    dx1 = int(x3)  # diearea coordinates in int
    dy1 = int(x4)  # diearea coordinates in int

    width = int(x3) - int(
        x1)  # getting the width of the are lower left - upper right
    height = int(x4) - int(
        x2)  # getting the hihgt of the are lower left - upper right
    clip = draw.ClipPath()
    d = draw.Drawing(width, height, origin=(0, -height),
                     id="svgContainer")  # drawing of diearea
    d.append(
        draw.Rectangle(
            dx0,
            -(height + dy0),
            width,
            height,
            fill='#D8FEEA',
            fill_opacity=0.4,
        ))

    # parsing the lef file
    lef_parser = LefParser(path)  # getting the lef file path
    lef_parser.parse()

    x = ""
    for i in lef:  # putting lef infrmation in list
        x = x + i + " "
    lef_info = x.split()
    # print(lef_info)

    k = 0
    # g = ""

    counter = 0

    for i in range(0, len(MACRO)):  # for loop for drawing of components

        if k < len(MACRO):  # if we still have macro we keep drawing
            g = draw.Group()
            for j in range(
                    0, len(lef_info), 2
            ):  # loop on th size of the block in the LEF file on details of a macro
                if MACRO[k] == lef_info[j]:  # Matching macros from LEF / DEF
                    counter = counter + 1
                    # print(MACRO[k])
                    opacity = 0.6  # opacity of all rectangles, opacity only changes if OBS
                    xplacement = float(
                        MACRO[k + 1]
                    )  # extracting and storing placement and orientation of macro from DEF
                    yplacement = float(MACRO[k + 2])
                    orientation = MACRO[k + 3]
                    endindx = lef_info.index("END",
                                             j)  # Extracting macros's details
                    for m in range(j, endindx):
                        if (lef_info[m] == "Size"):
                            swidth = float(
                                lef_info[m + 1]) * 100  # width size of macro
                            sheight = float(lef_info[
                                m + 2]) * 100  # height width size of macrp
                            d.append(
                                draw.Rectangle(xplacement - dx0,
                                               -(height - (yplacement - dy0)),
                                               swidth,
                                               sheight,
                                               fill='#a877f2',
                                               stroke='#412f5c',
                                               stroke_width=10,
                                               fill_opacity=0.2,
                                               class_="cell",
                                               name=MACRO[k],
                                               id=MACRO[k] + "_c" +
                                               str(counter)))
                        elif (lef_info[m] == "Layer:" or lef_info[m] == "Layer"
                              or lef_info[m] == "LAYER"):  # Layer
                            met = lef_info[m + 1]
                            if (lef_info[m + 1] == "metal1"):
                                # COLOR CODE For each metal
                                color = "#7D5AB1"
                            elif (lef_info[m + 1] == "metal2"):
                                # COLOR CODE For each meta2
                                color = "#8C8E8E"
                            elif (lef_info[m + 1] == "metal3"):
                                # COLOR CODE For each meta3
                                color = "#FF839D"
                            elif (lef_info[m + 1] == "metal4"):
                                # COLOR CODE For each meta4
                                color = "#83C9FF"
                            elif (lef_info[m + 1] == "via1"):
                                # COLOR CODE For each via1
                                color = "#83FFC3"
                            elif (lef_info[m + 1] == "via2"):
                                # COLOR CODE For each via2
                                color = "#FFD683"
                            elif (lef_info[m + 1] == "via3"):
                                # COLOR CODE For each via3
                                color = "#83FFE1"
                        elif ((lef_info[m] == "PIN:")):
                            # metal info
                            met = lef_info[m + 1]
                            # pin info
                            pin = lef_info[m + 1]  # PIN NAME
                        elif ((lef_info[m] == "OBS"
                               )):  # setting different opacity for rectangles
                            met = lef_info[m + 1]
                            opacity = 0.6
                        elif (
                            (lef_info[m] == "RECT"
                             )):  # extracting dimensions of rectangles in LEF
                            # x left
                            x0 = float(lef_info[m + 1]) * 100
                            # y left
                            y0 = float(lef_info[m + 2]) * 100
                            # x right
                            x01 = float(lef_info[m + 3]) * 100
                            # y right
                            y01 = float(lef_info[m + 4]) * 100
                            # width of the rects
                            rwidth = x01 - x0  # width of rectangle
                            # height of the rects
                            rheight = y01 - y0  # height of rectangle
                            if (orientation == "N"):
                                g.append(
                                    draw.Rectangle(xplacement - dx0 + x0,
                                                   -(height -
                                                     (yplacement - dy0 + y0)),
                                                   rwidth,
                                                   rheight,
                                                   fill=color,
                                                   fill_opacity=opacity,
                                                   class_=met))
                                g.append(
                                    draw.Text(pin,
                                              20,
                                              xplacement - dx0 + x0,
                                              -(height -
                                                (yplacement - dy0 + y0)),
                                              centre='origin',
                                              class_=met))
                            elif (orientation == "FN"):
                                FNx = x0 + ((swidth / 2 - x0) * 2) - rwidth
                                g.append(
                                    draw.Rectangle(xplacement - dx0 + FNx,
                                                   -(height -
                                                     (yplacement - dy0 + y0)),
                                                   rwidth,
                                                   rheight,
                                                   fill=color,
                                                   fill_opacity=opacity,
                                                   class_=met))
                                g.append(
                                    draw.Text(pin,
                                              20,
                                              xplacement - dx0 + FNx,
                                              -(height -
                                                (yplacement - dy0 + y0)),
                                              centre='origin',
                                              class_=met))
                            elif (orientation == "FS"):
                                FSy = y0 + ((sheight / 2 - y0) * 2) - rheight
                                g.append(
                                    draw.Rectangle(xplacement - dx0 + x0,
                                                   -(height -
                                                     (yplacement - dy0 + FSy)),
                                                   rwidth,
                                                   rheight,
                                                   fill=color,
                                                   fill_opacity=opacity,
                                                   class_=met))
                                g.append(
                                    draw.Text(pin,
                                              20,
                                              xplacement - dx0 + x0,
                                              -(height -
                                                (yplacement - dy0 + FSy)),
                                              centre='origin',
                                              class_=met))
                            elif (orientation == "S"):
                                Sx = x0 + ((swidth / 2 - x0) * 2) - rwidth
                                Sy = y0 + ((sheight / 2 - y0) * 2) - rheight
                                g.append(
                                    draw.Rectangle(xplacement - dx0 + Sx,
                                                   -(height -
                                                     (yplacement - dy0 + Sy)),
                                                   rwidth,
                                                   rheight,
                                                   fill=color,
                                                   fill_opacity=opacity,
                                                   Class=met))
                                g.append(
                                    draw.Text(pin,
                                              35,
                                              xplacement - dx0 + Sx,
                                              -(height -
                                                (yplacement - dy0 + Sy)),
                                              centre='origin',
                                              class_=met))
            d.append(g)
            k = k + 4

    nx = ""
    ny = ""

    for i in range(0, len(nets)):  # for loop to draw vias
        if (nets[i] == "M2_M1" or nets[i] == "M3_M2" or nets[i] == "M4_M3"):
            ny = nets[i - 1]
            nx = nets[i - 2]
            nx = int(nx.strip("[],"))
            ny = int(ny.strip("[],"))
            opacity = 0.5
            NETstartindx = lef_info.index(nets[i])
            if (nets[i] == "M2_M1" or nets[i] == "M3_M2"):
                NETendindx = lef_info.index("VIA", NETstartindx)
            elif (nets[i] == "M4_M3"):
                NETendindx = lef_info.index("Macro", NETstartindx)

            for n in range(NETstartindx, NETendindx):
                if (lef_info[n] == "LAYER"):  # Layer
                    if (lef_info[n + 1] == "metal1"):
                        color = "#7D5AB1"  # COLOR CODE For each metal
                    elif (lef_info[n + 1] == "metal2"):
                        # COLOR CODE For each meta2
                        color = "#8C8E8E"
                    elif (lef_info[n + 1] == "metal3"):
                        # COLOR CODE For each meta3
                        color = "#FF839D"
                    elif (lef_info[n + 1] == "metal4"):
                        # COLOR CODE For each meta4
                        color = "#83C9FF"
                    elif (lef_info[n + 1] == "via1"):
                        # COLOR CODE For each via1
                        color = "#83FFC3"
                    elif (lef_info[n + 1] == "via2"):
                        # COLOR CODE For each via2
                        color = "#FFD683"
                    elif (lef_info[n + 1] == "via3"):
                        # COLOR CODE For each via3
                        color = "#83FFE1"
                elif ((lef_info[n] == "RECT"
                       )):  # extracting dimensions of rectangles in
                    # x left
                    x0 = float(lef_info[n + 1]) * 100
                    # y left
                    y0 = float(lef_info[n + 2]) * 100
                    # xright
                    x01 = float(lef_info[n + 3]) * 100
                    # y right
                    y01 = float(lef_info[n + 4]) * 100
                    rwidth = x01 - x0  # width of rectangle
                    rheight = y01 - y0  # height of rectangle
                    d.append(
                        draw.Rectangle(nx - dx0 + x0,
                                       -(height - (ny - dy0 + y0)),
                                       rwidth,
                                       rheight,
                                       fill=color,
                                       fill_opacity=opacity,
                                       class_=lef_info[n + 1]))

    i = 0
    RouteEnd = 0
    RouteStart = 0

    print(nets)
    for i in range(0, len(nets)):
        # checking that am at metal components
        if (nets[i] == "NET_DEF:"):
            net_ident = nets[i + 1]
            #g = draw.Group(fill="Black", Class="net", id=net_ident)
            net_ident = net_ident.replace('<', '')
            net_ident = net_ident.replace('>', '')
            g = draw.Group()

        if (nets[i] == "metal1" or nets[i] == "metal2" or nets[i] == "metal3"
                or nets[i] == "metal4" or nets[i] == "via1"
                or nets[i] == "via2" or nets[i] == "via3"):
            RouteStart = i

            if (nets[i] == "metal1"):
                met = nets[i]
                color = "#7D5AB1"  # COLOR CODE For each metal
                strokewidth = 0.6 * 100  # width of metal
            elif (nets[i] == "metal2"):
                # COLOR CODE For each meta2
                met = nets[i]
                color = "#8C8E8E"
                # width of meta2
                strokewidth = 0.6 * 100
            elif (nets[i] == "metal3"):
                met = nets[i]
                # COLOR CODE For each meta3
                color = "#FF839D"
                # width of meta3
                strokewidth = 0.6 * 100
            elif (nets[i] == "metal4"):
                met = nets[i]
                # COLOR CODE For each meta4
                color = "#83C9FF"
                # width of meta4
                strokewidth = 1.2 * 100
            elif (nets[i] == "via1"):
                # COLOR CODE For each via1
                met = nets[i]
                color = "#83FFC3"
                strokewidth = 0.6 * 100
            elif (nets[i] == "via2"):
                # COLOR CODE For each via2
                met = nets[i]
                color = "#FFD683"
                strokewidth = 0.6 * 100
            elif (nets[i] == "via3"):
                met = nets[i]
                # COLOR CODE For each via3
                color = "#83FFE1"
                strokewidth = 0.6 * 100

            # print(RouteStart)

            for j in range(i + 1, len(nets)):
                if (nets[j] == "M2_M1" or nets[j] == "M3_M2"
                        or nets[j] == "M4_M3" or nets[j] == "metal1"
                        or nets[j] == "metal2" or nets[j] == "metal3"
                        or nets[j] == "metal4" or nets[j] == ";"):
                    RouteEnd = j
                    # print(RouteEnd)
                    break
            no_of_pairs = int((RouteEnd - RouteStart - 1) /
                              2)  # number of pairs of coordinates (x,y)
            temp = RouteStart

            if (
                    no_of_pairs > 1
            ):  # if number of pairs=1 , then only via and it's already drawn in previous loop

                for k in range(
                        0, no_of_pairs - 1
                ):  # extracting placement of wires and drawing routing
                    route_wirex0 = int(nets[temp + 1].strip("[],"))
                    route_wirey0 = int(nets[temp + 2].strip("[],"))
                    route_wirex1 = int(nets[temp + 3].strip("[],"))
                    route_wirey1 = int(nets[temp + 4].strip("[],"))
                    rw = route_wirex1 - route_wirex0
                    rh = route_wirey1 - route_wirey0
                    p = draw.Path(stroke_width=strokewidth,
                                  stroke=color,
                                  stroke_opacity=0.7,
                                  fill_opacity=0)
                    # d.append(draw.Lines(route_wirex0,route_wirey1,stroke_width=strokewidth, stroke=color, stroke_opacity=0.7, fill_opacity=0))
                    p.M(route_wirex0 - dx0,
                        -(height -
                          (route_wirey0 - dy0)))  # Start path at point
                    p.l(rw, rh)  # Draw line to
                    g.append(p)
                    d.append(
                        draw.Rectangle(route_wirex0 - dx0,
                                       -(height - (route_wirey0 - dy0)),
                                       rh,
                                       strokewidth,
                                       fill=color,
                                       stroke_opacity=0.7,
                                       fill_opacity=0,
                                       class_=met))
                    #d.append(draw.Rectangle(route_wirex0 - dx0,-(height - (route_wirey0 - dy0)),abs(rw)+50 ,abs(rh)+50,stroke_width=strokewidth, stroke="#FFF300", stroke_opacity=0, fill_opacity=0.5, class_="net",id=net_ident+"_net"))
                    #d.append(draw.Lines(route_wirex0,route_wirey1,stroke_width=strokewidth, stroke=color, stroke_opacity=0.7, fill_opacity=0))

                    temp = temp + 2
            d.append(g)

    pin_info = []  # Contains the needed details to draw the pins
    splt = ""
    for keys, val in def_parser.pins.pin_dict.items():
        # print(keys)
        splt = str(val)
        # print(val)
        splt = splt.split()
        pin_info.append(splt[3])
        pin_info.append(splt[9].strip("[],"))
        pin_info.append(splt[10].strip("[],"))
        pin_info.append(splt[11].strip("[],"))
        pin_info.append(splt[12].strip("[],"))
        pin_info.append(splt[13].strip("[],"))
        pin_info.append(splt[15].strip("[],"))
        pin_info.append(splt[16].strip("[],"))
        pin_info.append(splt[17].strip("[],"))

    # print(pin_info)
    for b in range(0, len(pin_info)):
        if (pin_info[b] == "metal1" or pin_info[b] == "metal2"
                or pin_info[b] == "metal3" or pin_info[b] == "metal4"):
            pinx0 = int(pin_info[b + 1])
            piny0 = int(pin_info[b + 2])
            pinx1 = int(pin_info[b + 3])
            piny1 = int(pin_info[b + 4])
            pin_pos1 = int(pin_info[b + 5])
            pin_pos2 = int(pin_info[b + 6])
            pin_name = pin_info[b - 1]
            PINS = pin_name.replace('<', '')
            PINS = PINS.replace('>', '')
            d.append(
                draw.Rectangle(pin_pos1 - dx0,
                               -(height - (pin_pos2 - dy0)),
                               pinx1 - pinx0 + 200,
                               piny1 - piny0 + 200,
                               fill='#B1725A',
                               fill_opacity=0.6,
                               Class="PIN",
                               id=PINS))
            d.append(
                draw.Text(pin_name,
                          40,
                          pin_pos1 - dx0,
                          -(height - (pin_pos2 - dy0 - 20)),
                          centre='origin',
                          Class="PINNames"))

        #drc_parser=[]
        #read_path = input("Enter DRC file path: ") #ENTER DRC FILE PATH HERE!
        drc = DRC_parser(path2)
        drc.parse()
        # x = drc_parser.DRC_parser()

    SVG = str(pth[-1]) + ".html"
    d.saveSvg("templates/" + SVG)  # draw svg image and give it a file name

    with open('htmlHead.txt', 'r') as file:
        Head = file.read()
    with open('htmlTail.txt', 'r') as file:
        Tail = file.read()
    with open("templates/" + SVG, 'r+') as f:
        content = f.read()
        contentX = content.replace(str(height), "950", 1)
        contentX = contentX.replace(str(width), "950", 1)
        f.seek(0, 0)
        f.write(Head + contentX + Tail)

    return SVG
Beispiel #6
0
def main(svg_file):

    print('Parsing file:', svg_file)

    doc = minidom.parse(svg_file)
    g = doc.getElementsByTagName('g')[0]
    transform = g.getAttribute('transform')
    if not transform == '':
        if len(transform.split(')')) > 2:
            print('Only support translation on the whole SVG at the moment.')
        if not transform.split('(')[0] == 'translate':
            print('Only supports translation on the whole SVG at the moment.')
        coords = transform.split('(')[1][:-1]
        dx = float(coords.split(',')[0])
        dy = float(coords.split(',')[1])
    else:
        dx = 0
        dy = 0

    print('Extracting path strings.')
    path_strings = [(path.getAttribute('style'), path.getAttribute('d'),
                     path.getAttribute('transform'))
                    for path in g.getElementsByTagName('path')]

    print('Extracting text strings.')
    text_strings = []
    for text in g.getElementsByTagName('text'):
        sty = text.getAttribute('style')
        x = float(text.getAttribute('x'))
        y = -1 * (float(text.getAttribute('y')))
        if not text.firstChild.firstChild == None:
            string = text.firstChild.firstChild.nodeValue
            text_strings.append((sty, x, y, string))

    width = doc.getElementsByTagName('svg')[0].getAttribute('width')
    height = doc.getElementsByTagName('svg')[0].getAttribute('height')
    if width.endswith('mm'):
        width = round(float(width[:-2]), 0)
    else:
        print('unknown width unit')
        sys.exit(0)

    if height.endswith('mm'):
        height = round(float(height[:-2]), 0)
    else:
        print('unknown height unit')
        sys.exit(0)

    doc.unlink()

    path_styles = []
    paths = []
    transforms = []
    for (s, p, t) in path_strings:
        style_map = dict()
        styles = s.split(';')
        for s_string in styles:
            spl = s_string.split(':')
            style_map[spl[0]] = spl[1]
        path_styles.append(style_map)
        paths.append(p)
        transforms.append(t)

    print('Parsing transforms.')
    transforms, orderings = parse_transforms_strings(transforms)

    print('Extracting red segment paths.')
    red_paths = extract_paths(paths, path_styles, '#ff0000', transforms,
                              orderings)
    print('Splitting overlapping red paths.')
    red_lines = split_paths(red_paths)
    red_lines = red_lines + [(l[1], l[0]) for l in red_lines]

    print('Creating red segment polygons.')
    polygons = []
    for line in red_lines:
        found = False
        current_polygon = [line]
        used_lines = [line, (line[1], line[0])]
        current_line = line

        while not found:
            # first get all lines that connect to point 2
            current_line = current_polygon[-1]
            line_start = current_line[0]
            line_end = current_line[1]
            line_vec = (line_end[0] - line_start[0],
                        line_end[1] - line_start[1])
            connecting_lines = [
                l for l in red_lines
                if (app_eq(l[0], line_end) or app_eq(l[1], line_end))
                and not l in used_lines
            ]
            #print(connecting_lines)
            max_angle = -10000
            chosen_line = None
            for cl in connecting_lines:
                cl_end = cl[0] if app_eq(line_end, cl[1]) else cl[1]
                cl_start = cl[1] if app_eq(line_end, cl[1]) else cl[0]
                new_cl = (cl_start, cl_end)
                cl_vec = (cl_end[0] - cl_start[0], cl_end[1] - cl_start[1])
                angle = angle_between(line_vec, cl_vec)
                if angle > max_angle:
                    max_angle = angle
                    chosen_line = new_cl

            current_polygon.append(chosen_line)
            used_lines.append(chosen_line)
            used_lines.append((chosen_line[1], chosen_line[0]))

            if app_eq(chosen_line[1], current_polygon[0][0]):
                found = True
                polygons.append(current_polygon)

    print('Filtering duplicate segments.')
    unique_polygons = [polygons[0]]
    for i, p in enumerate(polygons):
        same = False
        for j, q in enumerate(unique_polygons):
            if check_same_lines(p, q):
                same = True
        if same == False:
            unique_polygons.append(p)

    print('Extracting aligment marker paths.')
    blue_paths = extract_paths(paths, path_styles, '#0000ff', transforms,
                               orderings)
    print('Extracting all black paths.')
    black_paths = extract_paths(paths, path_styles, '#000000', transforms,
                                orderings)
    print('Splitting overlapping black paths.')
    black_lines = split_paths(black_paths)

    print('Extracting fill area paths.')
    fill_paths, fill_path_styles = extract_paths(paths, path_styles, 'none',
                                                 transforms, orderings, True)

    print('Converting all paths to Shapely lines or polygons.')
    black_ls = []
    for line in black_lines:
        black_ls.append(
            LineString(
                [Point(line[0][0], line[0][1]),
                 Point(line[1][0], line[1][1])]))

    blue_ls = []
    for line in blue_paths:
        blue_ls.append(
            LineString(
                [Point(line[0][0], line[0][1]),
                 Point(line[1][0], line[1][1])]))

    text_points = []
    for ts in text_strings:
        # (style,x,y,value)
        text_points.append(Point(ts[1], ts[2]))

    fill_polys = []
    for points in fill_paths:
        fill_polys.append(Polygon([Point(x, y) for (x, y) in points]))

    shapely_polys = []
    for polygon in unique_polygons:
        poly_points = []
        for i, line in enumerate(polygon):
            if len(poly_points) == 0:
                poly_points.append(Point(line[0][0], line[0][1]))
            if i < len(polygon) - 1:
                poly_points.append(Point(line[1][0], line[1][1]))
        poly_points.append(Point(polygon[0][0][0], polygon[0][0][1]))
        lr = Polygon(poly_points)
        shapely_polys.append(lr)

    svgs = []

    print('Drawing each segment, lines and fill, and converting to SVG.')
    for q, polygon in enumerate(shapely_polys):
        outset = 6
        origin = (-dx - outset, -(height + outset + 1) + dy)
        d = draw.Drawing(width + 1 + 2 * outset,
                         height + 2 + 2 * outset,
                         origin=origin)
        d.setRenderSize(
            str(width + (2 * 6.35)) + 'mm',
            str(height + (2 * 6.35)) + 'mm')

        lr = polygon
        expand_lr = lr.buffer(1.5, resolution=16, join_style=2,
                              mitre_limit=30).exterior
        expand_lr = Polygon(expand_lr.coords)

        # compute seam allowance, dist 6 == 1/4 inch
        outset = lr.buffer(6, resolution=16, join_style=2,
                           mitre_limit=45).exterior
        outset = [(l[0], l[1]) for l in outset.coords]

        biggest = True
        for r, other_poly in enumerate(shapely_polys):
            if not expand_lr.contains(other_poly):
                biggest = False
        if biggest:
            continue

        #plt.plot(*lr.exterior.xy,c='b')
        #plt.plot(*expand_lr.xy,c='r')
        within_idxs = []
        for i, bl in enumerate(black_ls):
            if expand_lr.contains(bl):
                within_idxs.append(i)

        within_lines = [
            x for i, x in enumerate(black_lines) if i in within_idxs
        ]

        marker_idxs = []
        for i, bl in enumerate(blue_ls):
            if lr.intersects(bl):
                marker_idxs.append(i)

        align_lines = [x for i, x in enumerate(blue_paths) if i in marker_idxs]

        text_idxs = []
        for i, tp in enumerate(text_points):
            if lr.contains(tp):
                text_idxs.append(i)
        text_locations = [
            x for i, x in enumerate(text_strings) if i in text_idxs
        ]

        fill_idxs = []
        for i, fp in enumerate(fill_polys):
            if expand_lr.contains(fp):
                fill_idxs.append(i)

        fill_poly_paths = [
            x for i, x in enumerate(fill_paths) if i in fill_idxs
        ]
        fill_poly_styles = [
            x for i, x in enumerate(fill_path_styles) if i in fill_idxs
        ]

        for i, points in enumerate(fill_poly_paths):
            colour = fill_poly_styles[i]['fill']
            p = draw.Path(stroke_width=0, fill=colour, fill_opacity=1)
            p.M(points[0][0], points[0][1])
            for point in points[1:]:
                p.L(point[0], point[1])
            d.append(p)
        for points in unique_polygons[q]:
            p = draw.Path(stroke_width=3,
                          stroke='red',
                          fill_opacity=0,
                          opacity=0.3)
            p.M(points[0][0], points[0][1])
            for point in points[1:]:
                p.L(point[0], point[1])
            d.append(p)
        for points in within_lines:
            p = draw.Path(stroke_width=1, stroke='black', fill_opacity=0)
            p.M(points[0][0], points[0][1])
            for point in points[1:]:
                p.L(point[0], point[1])
            d.append(p)
        for points in align_lines:
            p = draw.Path(stroke_width=1, stroke='blue', fill_opacity=0)
            p.M(points[0][0], points[0][1])
            for point in points[1:]:
                p.L(point[0], point[1])
            d.append(p)
        for ts in text_locations:
            size = float([
                x.split(':')[1] for x in ts[0].split(';')
                if x.split(':')[0] == 'font-size'
            ][0][:-2])
            colour = [
                x.split(':')[1] for x in ts[0].split(';')
                if x.split(':')[0] == 'fill'
            ][0]
            p = draw.Text(ts[3], size, float(ts[1]), float(ts[2]), fill=colour)
            if ts[3].isalpha():
                letter = ts[3]
            d.append(p)

        # add seam allowance
        p = draw.Path(stroke='black',
                      stroke_dasharray=3,
                      fill_opacity=0,
                      opacity=1)
        p.M(outset[0][0], outset[0][1])
        for point in outset[1:]:
            p.L(point[0], point[1])
        d.append(p)
        svgs.append((d, letter))

    print("Saving generated segment SVG's to file.")
    directory = svg_file[:-4]
    if not os.path.exists(directory):
        os.mkdir(directory)
    for svg, letter in svgs:
        svg.saveSvg(directory + '/' + letter + '.svg')

    print('Done.')
Beispiel #7
0
def draw_share_progress():
    goal = int(getattr(settings, "SHARE_PROGRESS_GOAL", "10") or "10")
    offset = int(getattr(settings, "SHARE_PROGRESS_OFFSET", "0") or "0")
    baseline = int(getattr(settings, "SHARE_PROGRESS_BASELINE", "0") or "0")
    baseline_progress = baseline / goal
    ordered = Share.objects.filter(
        cancelled_date__isnull=True).count() + offset
    ordered_progress = ordered / goal
    paid = Share.objects.filter(cancelled_date__isnull=True,
                                paid_date__isnull=False).count() + offset
    paid_progress = paid / goal

    d = draw.Drawing(1.8, 1.6, origin='center')

    arrow = draw.Marker(-0.2, -0.5, 0.9, 0.5, scale=20, orient='auto')
    arrow.append(
        draw.Lines(-0.2,
                   -0.5,
                   0,
                   0,
                   -0.2,
                   0.5,
                   0.9,
                   0,
                   fill='black',
                   close=True))

    arc = draw.Path(stroke='black',
                    stroke_width=0.002,
                    fill_opacity=0,
                    marker_end=arrow)
    arc.arc(0, 0, 0.6, 89, 94, cw=True)
    d.append(arc)

    d.append(draw.Text(f'{goal}', **on_arc(0.63, 0.99)))

    d.append(progress_arc(ordered_progress, fill_opacity=0.5))
    d.append(progress_arc(paid_progress))
    if baseline > 0:
        d.append(progress_arc(baseline_progress, fill='#083c00'))

    # text center
    if goal > ordered:
        d.append(draw.Text('Noch', 0.1, 0, 0.3, center=True))
        d.append(
            draw.Text(str(goal - ordered),
                      0.3,
                      0,
                      0.12,
                      center=True,
                      font_weight='bold'))
        d.append(draw.Text('Anteilscheine', 0.09, 0, -0.1, center=True))
        # labels
        d.append(
            draw.Text(f'{ordered-baseline} neue\nbestellt',
                      **on_arc(0.7, ordered_progress)))
        d.append(
            draw.Text(f'{paid-baseline} neue\nbezahlt',
                      **on_arc(0.5, paid_progress, 'inner')))
        if baseline > 0:
            d.append(
                draw.Text(f'{baseline}\nbisher',
                          fill='white',
                          **on_arc(0.5, baseline_progress - 0.025)))
    else:
        d.append(draw.Text('Wir haben es', 0.09, 0, 0.14, center=True))
        d.append(
            draw.Text('Geschafft!',
                      0.18,
                      0,
                      0,
                      center=True,
                      font_weight='bold'))

    # Display
    d.setRenderSize(w='100%', h='100%')
    svg = d.asSvg()
    return svg[:-6] + """<style type="text/css">
Beispiel #8
0
    def drawSVG(self,
                path=None,
                target='TARGET_0000000001__64__MNXC3',
                subplot_size=[200,200],
                #reac_size=[20,60],
                reac_fill_color='#ddd',
                reac_stroke_color='black',
                reac_stroke_width=2,
                arrow_stroke_color='black',
                arrow_stroke_width=2,
                font_family='sans-serif',
                font_size=10,
                font_color='black',
                plot_only_central=True,
                filter_cofactors=True,
                filter_sink_species=False):
        """Generate a reaction SVG image from the rpgraph object.

        :param rpgraph: rpGraph object to draw the SVG from
        :param target: source node to calculate the hierarchy tree organisation of the reaction (should be TARGET)
        :param suboplot_size: The size in pixels of the subplot boxes used to draw the SVG  (default: [200, 200])
        :param reac_fill_color: Hex (or name) color code to fill of the reaction box (default: '#ddd')
        :param reac_stroke_color: Hex (or name) color code of the reaction box stroke (default: 'black')
        :param reac_stroke_width: Size of the reaction rectangle stroke width (default: 2)
        :param arrow_stroke_color: Hex (or name) color code of the reaction arrows (default: 'black')
        :param arrow_stroke_width: Size of the reaction arrows (default: 2)
        :param font_family: The font of the cofactors (default: 'sans-serif'
        :param font_size: The font size of the cofactors (default: 10)
        :param font_color: The font color of the cofactors (default: 'black')
        :param plot_only_central: Do not draw the chemical structure of the non-central species (default: True)
        :param filter_cofactors: Do not draw the chemical structire of the identified cofactors (see: data/mnx_cofactors.json) (default: True)
        :param filter_sink_species: Do not draw the chemical structure of sink species (default: False)

        :type rpgraph: rpGraph
        :type target: str
        :type suboplot_size: list
        :type reac_fill_color: str
        :type reac_stroke_color: str
        :type reac_stroke_width: int
        :type arrow_stroke_color: str
        :type arrow_stroke_width: int
        :type font_family: str
        :type font_size: int
        :type font_color: str
        :type plot_only_central: bool
        :type filter_cofactors: bool
        :type filter_sink_species: bool

        :returns: tuple (svg, resG, mod_pos, reac_cofactors_name)
            - svg - SVG as string
            - regG - Result networkx object with the cofactors removed
            - mod_pos - The calculates positions for the objects
            - reac_cofactors_name - Dictionnary of reactions with the subtrates and products ID's

        :rtype: tuple
        """
        if not self.G:
            self.logger.error('The G needs to be initialised')
            return False
        #TODO: Check this one: /Users/melchior/Downloads/rpglobalscore_77/rp_109_2.sbml.xml
        reac_size = [subplot_size[0]/8, subplot_size[1]/2]
        #gather all the inchis and convert to svg
        resG, pos, reac_cofactors_id = self.hierarchyPos(self.G,
                                                         target,
                                                         plot_only_central=plot_only_central,
                                                         filter_cofactors=filter_cofactors,
                                                         filter_sink_species=filter_sink_species)
        self.logger.debug('+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=')
        ######## convert the id's to string name #####
        reac_cofactors_name = {}
        for reac_id in reac_cofactors_id:
            if not reac_id in reac_cofactors_name:
                reac_cofactors_name[reac_id] = {'substrates': [], 'products': []}
            for sub in reac_cofactors_id[reac_id]['substrates']:
                try:
                    name = self.G.node.get(sub)['name']
                except KeyError:
                    name = sub
                if name=='':
                    name = sub
                reac_cofactors_name[reac_id]['substrates'].append(name)
            for pro in reac_cofactors_id[reac_id]['products']:
                try:
                    name = self.G.node.get(pro)['name']
                except KeyError:
                    name = pro
                if name=='':
                    name = pro
                reac_cofactors_name[reac_id]['products'].append(name)
        ############# Calculate the size of the image ##### 
        id_inchi = {}
        self.logger.debug('positions: '+str(pos))
        for node in list(resG.nodes):
            if resG.node.get(node)['type']=='species':
                id_inchi[node] = resG.node.get(node)['brsynth']['inchi']
        id_svg = self.drawChemicalList(id_inchi, subplot_size)
        self.logger.debug('============================')
        a = {}
        for n in pos:
            if not pos[n][0] in a:
                a[pos[n][0]] = []
            a[pos[n][0]].append(pos[n][1])
        self.logger.debug('a: '+str(a))
        largest_y = 0
        for i in a:
            if len(a[i])>largest_y:
                largest_y = len(a[i])
        if largest_y==0:
            largest_y = 1
        self.logger.debug('largest_y: '+str(largest_y))
        u_x_layers = sorted(list(set([pos[i][0] for i in pos])))
        u_y_layers = sorted(list(set([pos[i][1] for i in pos])))
        self.logger.debug('u_x_layers: '+str(u_x_layers))
        self.logger.debug('u_y_layers: '+str(u_y_layers))
        background_len_x = subplot_size[0]*len(u_x_layers)
        background_len_y = subplot_size[1]*largest_y
        self.logger.debug('background_len_x: '+str(background_len_x))
        self.logger.debug('background_len_y: '+str(background_len_y))
        mod_pos = {}
        #adjust the x axis lications for the boxes to be close to each other
        #TODO: readjust to equidistant on the y-axis nodes that are not
        for node in pos:
            mod_pos[node] = (pos[node][0]*(subplot_size[0]*(len(u_x_layers)-1)), #not sure why I have to correct that
                             (pos[node][1]*background_len_y))
        self.logger.debug('============================')
        self.logger.debug('mod_pos: '+str(mod_pos))
        ########### draw the background #############
        len_fig_x = background_len_x
        len_fig_y = background_len_y
        self.logger.debug('len_fig_x: '+str(len_fig_x))
        self.logger.debug('len_fig_y: '+str(len_fig_y))
        fig = sg.SVGFigure(str(len_fig_x),
                           str(len_fig_y))
        background_white = draw.Drawing(len_fig_x, len_fig_y, origin=(0,0))
        background_white.append(draw.Rectangle(0, 0, len_fig_x, len_fig_y, fill='#ffffff'))
        a = sg.fromstring(background_white.asSvg())
        b_w = a.getroot()
        b_w.moveto(0, background_len_y)#WARNING: not sure why I have to + subpot
        fig.append(b_w)
        nodes_attach_locs = {}
        for node_id in mod_pos:
            node = self.G.node.get(node_id)
            self.logger.debug('\tSpecies: '+str(node_id))
            if node['type']=='species':
                self.logger.debug('\tNode pos: '+str(mod_pos[node_id]))
                self.logger.debug('\tx: '+str(mod_pos[node_id][0]))
                self.logger.debug('\ty: '+str(mod_pos[node_id][1]))
                move_x = mod_pos[node_id][0]
                # because of the nature of the x y locations, need to reverse them here
                if mod_pos[node_id][1]==0.0:
                    y_coord = mod_pos[node_id][1]+subplot_size[1]/2
                    move_y = len_fig_y-mod_pos[node_id][1]-subplot_size[1]
                elif mod_pos[node_id][1]==len_fig_y:
                    y_coord = mod_pos[node_id][1]-subplot_size[1]/2
                    move_y = len_fig_y-mod_pos[node_id][1]
                else:
                    y_coord = mod_pos[node_id][1]
                    move_y = len_fig_y-mod_pos[node_id][1]-subplot_size[1]/2
                self.logger.debug('\tmove_x: '+str(move_x))
                self.logger.debug('\tmove_y: '+str(move_y))
                f = sg.fromstring(id_svg[node_id])
                p = f.getroot()
                #Rememeber that you are moving the object on the x and y axis while the coordinates are coordinates so its reversed
                p.moveto(move_x, move_y)
                fig.append(p)
                nodes_attach_locs[node_id] = {'left': (mod_pos[node_id][0], y_coord),
                                              'right': (mod_pos[node_id][0]+subplot_size[0], y_coord)}
            elif node['type']=='reaction':
                d = draw.Drawing(subplot_size[0], subplot_size[1], origin=(0,0))
                d.append(draw.Rectangle(0, 0, subplot_size[0], subplot_size[1], fill='#FFFFFF'))
                edge_x = subplot_size[0]/2-reac_size[1]/2
                edge_y = subplot_size[1]/2-reac_size[0]/2
                self.logger.debug('\tedge_x: '+str(edge_x))
                self.logger.debug('\tedge_y: '+str(edge_y))
                self.logger.debug('\tx: '+str(mod_pos[node_id][0]))
                self.logger.debug('\ty: '+str(mod_pos[node_id][1]+subplot_size[1]))
                if reac_cofactors_name[node_id]['substrates']:
                    d.append(draw.Line(subplot_size[0]/2, edge_y-reac_size[0],
                                       subplot_size[0]/2, edge_y-self.arrowhead_comp_x,
                                       stroke=arrow_stroke_color, stroke_width=arrow_stroke_width, fill='none', marker_end=self.arrowhead))
                if reac_cofactors_name[node_id]['products']:
                    d.append(draw.Line(subplot_size[0]/2, edge_y+reac_size[0],
                                       subplot_size[0]/2, (subplot_size[1]/2)+reac_size[1]/3,
                                       stroke=arrow_stroke_color, stroke_width=arrow_stroke_width, fill='none', marker_end=self.arrowhead))
                y_shift = 0.0
                for sub in reac_cofactors_name[node_id]['substrates']:
                    self.logger.debug(sub)
                    d.append(draw.Text(sub, font_size,
                                       subplot_size[0]/2, ((subplot_size[1]/2)-reac_size[1]/3)-y_shift-font_size,
                                       font_family=font_family, center=True, fill=font_color))
                    y_shift += font_size
                y_shift = 0.0
                for pro in reac_cofactors_name[node_id]['products']:
                    self.logger.debug(pro)
                    d.append(draw.Text(pro, font_size,
                                       subplot_size[0]/2, ((subplot_size[1]/2)+reac_size[1]/3)+y_shift+font_size+self.arrowhead_comp_x,
                                       font_family=font_family, center=True, fill=font_color))
                    y_shift += font_size
                d.append(draw.Rectangle(edge_x, edge_y,
                                        reac_size[1], reac_size[0],
                                        fill=reac_fill_color,
                                        stroke_width=reac_stroke_width,
                                        stroke=reac_stroke_color))
                a = sg.fromstring(d.asSvg())
                a_r = a.getroot()
                move_x = mod_pos[node_id][0]
                if mod_pos[node_id][1]==0.0:
                    move_y = len_fig_y-mod_pos[node_id][1]
                elif mod_pos[node_id][1]==len_fig_y:
                    move_y = len_fig_y-mod_pos[node_id][1]+subplot_size[1]
                else:
                    move_y = len_fig_y-mod_pos[node_id][1]-subplot_size[1]/2+subplot_size[1]
                self.logger.debug('\tmove_x: '+str(move_x))
                self.logger.debug('\tmove_y: '+str(move_y))
                a_r.moveto(move_x, move_y)
                fig.append(a_r)
                nodes_attach_locs[node_id] = {'left': (move_x+edge_x,
                                                       move_y-subplot_size[1]/2),
                                              'right': (move_x+subplot_size[0]-edge_x+reac_stroke_width/2,
                                                        move_y-subplot_size[1]/2)}
            self.logger.debug('\t-------------------------------')
        self.logger.debug('nodes_attach_locs: '+str(nodes_attach_locs))
        self.logger.debug(list(resG.edges))
        arrow_box = draw.Drawing(len_fig_x, len_fig_y, origin=(0,0))
        ################ Add the arrowhead depending on edge direction #######
        #depending on the directions of the node, switch the source and the target
        #and calculate the center pocitions of the arrows
        edge_pos = {}
        strict_edge_pos = {}
        for edge in list(resG.edges):
            #left to right
            if pos[edge[0]][0]>pos[edge[1]][0]:
                source_x = nodes_attach_locs[edge[0]]['left'][0]
                source_y = nodes_attach_locs[edge[0]]['left'][1]
                target_x = nodes_attach_locs[edge[1]]['right'][0]
                target_y = nodes_attach_locs[edge[1]]['right'][1]
                edge_pos[edge] = {'source': (round(source_x, 2), round(source_y, 2)),
                                  'L1': (round(source_x+(target_x-source_x)/2, 2), round(source_y, 2)),
                                  'L2': (round(source_x+(target_x-source_x)/2, 2), round(target_y, 2)),
                                  'target': (round(target_x+self.arrowhead_comp_x, 2), round(target_y, 2)),
                                  'arrow_direction': self.rev_arrowhead_flat}
                strict_edge_pos[edge] = {'source': (int(round(source_x, 0)), int(round(source_y, 0))),
                                  'L1': (int(round(source_x+(target_x-source_x)/2, 0)), int(round(source_y, 0))),
                                  'L2': (int(round(source_x+(target_x-source_x)/2, 0)), int(round(target_y, 0))),
                                  'target': (int(round(target_x, 0)), int(round(target_y, 0))),
                                  'arrow_direction': self.rev_arrowhead_flat}
                '''
                edge_pos[edge] = {'source': [source_x, source_y],
                                  'L1': [source_x+(target_x-source_x)/2+self.arrowhead_comp_y/2, source_y],
                                  'L2': [source_x+(target_x-source_x)/2+self.arrowhead_comp_y/2, target_y],
                                  'target': [target_x+self.arrowhead_comp_x, target_y],
                                  'arrow_direction': self.rev_arrowhead_flat}
                '''
            #right to left
            elif pos[edge[0]][0]<pos[edge[1]][0]:
                source_x = nodes_attach_locs[edge[0]]['right'][0]
                source_y = nodes_attach_locs[edge[0]]['right'][1]
                target_x = nodes_attach_locs[edge[1]]['left'][0]
                target_y = nodes_attach_locs[edge[1]]['left'][1]
                edge_pos[edge] = {'source': (round(source_x, 2), round(source_y, 2)),
                                  'L1': (round(source_x+(target_x-source_x)/2, 2), round(source_y, 2)),
                                  'L2': (round(source_x+(target_x-source_x)/2, 2), round(target_y, 2)),
                                  'target': (round(target_x-self.arrowhead_comp_x, 2), round(target_y, 2)),
                                  'arrow_direction': self.arrowhead_flat}
                strict_edge_pos[edge] = {'source': (int(round(source_x, 0)), int(round(source_y, 0))),
                                  'L1': (int(round(source_x+(target_x-source_x)/2, 0)), int(round(source_y, 0))),
                                  'L2': (int(round(source_x+(target_x-source_x)/2, 0)), int(round(target_y, 0))),
                                  'target': (int(round(target_x, 0)), int(round(target_y, 0))),
                                  'arrow_direction': self.arrowhead_flat}
                '''
                edge_pos[edge] = {'source': [source_x, source_y],
                                  'L1': [source_x+(target_x-source_x)/2-self.arrowhead_comp_y/2, source_y],
                                  'L2': [source_x+(target_x-source_x)/2-self.arrowhead_comp_y/2, target_y],
                                  'target': [target_x-self.arrowhead_comp_x, target_y],
                                  'arrow_direction': self.arrowhead_flat}
                '''
            else:
                self.logger.error('Cannot connect same y-axi')
        #calculate the center positions of the arrows
        self.logger.debug('edge_pos: '+str(edge_pos))
        self.logger.debug('strict_edge_pos: '+str(strict_edge_pos))
        ############# Calculate the overlaps ##########
        #find the edges that have the same source/target locations - if more than that do not go in the same direction
        # then create a input/output location and update the positions
        #NOTE: have to make strings from the edge locations to be able to be
        overlaps_arrow = {'node': {}, 'L': {}}
        #overlaps_edge = {'node': {}, 'L': {}}
        for edge in strict_edge_pos:
            source_id = str(strict_edge_pos[edge]['source'][0])+'-'+str(strict_edge_pos[edge]['source'][1])
            target_id = str(strict_edge_pos[edge]['target'][0])+'-'+str(strict_edge_pos[edge]['target'][1])
            l1_id = str(strict_edge_pos[edge]['L1'][0])+'-'+str(strict_edge_pos[edge]['L1'][1])
            l2_id = str(strict_edge_pos[edge]['L2'][0])+'-'+str(strict_edge_pos[edge]['L1'][1])
            ####### make the nodes and arrow overlaps_arrow #######
            if not source_id in overlaps_arrow['node']:
                overlaps_arrow['node'][source_id] = [strict_edge_pos[edge]['arrow_direction']]
            else:
                overlaps_arrow['node'][source_id].append(strict_edge_pos[edge]['arrow_direction'])
            if not target_id in overlaps_arrow['node']:
                overlaps_arrow['node'][target_id] = [strict_edge_pos[edge]['arrow_direction']]
            else:
                overlaps_arrow['node'][target_id].append(strict_edge_pos[edge]['arrow_direction'])
            if not l1_id in overlaps_arrow['L']:
                overlaps_arrow['L'][l1_id] = [strict_edge_pos[edge]['arrow_direction']]
            else:
                overlaps_arrow['L'][l1_id].append(strict_edge_pos[edge]['arrow_direction'])
            if not l2_id in overlaps_arrow['L']:
                overlaps_arrow['L'][l2_id] = [strict_edge_pos[edge]['arrow_direction']]
            else:
                overlaps_arrow['L'][l2_id].append(strict_edge_pos[edge]['arrow_direction'])
            ##### make the overlap edge ####
            """
            if not source_id in overlaps_edge['node']:
                overlaps_edge['node'][source_id] = [edge]
            else:
                overlaps_edge['node'][source_id].append(edge)
            if not target_id in overlaps_edge['node']:
                overlaps_edge['node'][target_id] = [edge]
            else:
                overlaps_edge['node'][target_id].append(edge)
            if not l1_id in overlaps_edge['L']:
                overlaps_edge['L'][l1_id] = [edge]
            else:
                overlaps_edge['L'][l1_id].append(edge)
            if not l2_id in overlaps_edge['L']:
                overlaps_edge['L'][l2_id] = [edge]
            else:
                overlaps_edge['L'][l2_id].append(edge)
            """
        ########## Add entry/exit of node if same side node has multiple types #######
        #adjust the perpendecular arrows if there is overlap with reversed directions
        #TODO: adjust arrows that overlap in the same direction but do not have the same destination
        self.logger.debug('overlaps_arrow: '+str(overlaps_arrow))
        #self.logger.debug('overlaps_edge: '+str(overlaps_edge))
        for pos_id in overlaps_arrow['node']:
            #if the direction of the node locations are not the same then you need seperate the input/output
            if len(overlaps_arrow['node'][pos_id])>1:
                if not overlaps_arrow['node'][pos_id].count(self.arrowhead_flat)==len(overlaps_arrow['node'][pos_id]) or overlaps_arrow['node'][pos_id].count(self.rev_arrowhead_flat)==len(overlaps_arrow['node'][pos_id]):
                    for edge in strict_edge_pos:
                        source_id = str(strict_edge_pos[edge]['source'][0])+'-'+str(strict_edge_pos[edge]['source'][1])
                        target_id = str(strict_edge_pos[edge]['target'][0])+'-'+str(strict_edge_pos[edge]['target'][1])
                        if source_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.arrowhead_flat:
                            edge_pos[edge]['source'] = (edge_pos[edge]['source'][0], edge_pos[edge]['source'][1]-self.arrowhead_comp_y/2)
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0], edge_pos[edge]['L1'][1]-self.arrowhead_comp_y/2)
                        elif source_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.rev_arrowhead_flat:
                            edge_pos[edge]['source'] = (edge_pos[edge]['source'][0], edge_pos[edge]['source'][1]+self.arrowhead_comp_y/2)
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0], edge_pos[edge]['L1'][1]+self.arrowhead_comp_y/2)
                        if target_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.arrowhead_flat:
                            edge_pos[edge]['target'] = (edge_pos[edge]['target'][0], edge_pos[edge]['target'][1]-self.arrowhead_comp_y/2)
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0], edge_pos[edge]['L2'][1]-self.arrowhead_comp_y/2)
                        elif target_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.rev_arrowhead_flat:
                            edge_pos[edge]['target'] = (edge_pos[edge]['target'][0], edge_pos[edge]['target'][1]+self.arrowhead_comp_y/2)
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0], edge_pos[edge]['L2'][1]+self.arrowhead_comp_y/2)
        #TODO: problem of overlap of arrows
        #1) loop through all the arrows in the same layer
        #2) for each node and each entry/exit, record the perpendicular locations
        #3) if two overlap when they should not then add y_shift
        #           - if they are entry/exit
        #           - if they are entry or exit that overlap with other entry/exit from another reaction
        #do the same for the the perpendicular
        '''
        for pos_id in overlaps_arrow['edge']:
        for edge in strict_edge_pos:
            source_id = str(strict_edge_pos[edge]['source'][0])+'-'+str(strict_edge_pos[edge]['source'][1])
            target_id = str(strict_edge_pos[edge]['target'][0])+'-'+str(strict_edge_pos[edge]['target'][1])
        '''
        #calculate the perpendicular overlaps
        '''
        for edge in edge_pos:
            perpendicular_layers = []
            for comp_edge in edge_pos:
                #if edge_pos[comp_edge]['L1']==edge_pos[edge]['L1']:
                x, y = lineIntersection(edge_pos[comp_edge]['L1'][0], edge_pos[comp_edge]['L1'][1], edge_pos[edge]['L1'][0], edge_pos[edge]['L1'][1])
                if not x==None and y==None:
                    perpendicular_layers.append(comp_edge)
            if len(perpendicular_layers)>1:
                pass
                #cases to ignore:
                #   - when they overlap but go in the same direction and the same target or source
                #case when overlap but they go to the same direction and not the same target
                #case when 
        '''

        for pos_id in overlaps_arrow['L']:
            if len(overlaps_arrow['L'][pos_id])>1:
                #TODO: need a better overlap algo that takes into consideration if they do not overlap
                #example /Users/melchior/Downloads/rpglobalscore_101/rp_1_1.sbml.xml
                #BUG: /Users/melchior/Downloads/rpglobalscore_101/rp_3_2.sbml.xml --> line not detected to be moved
                #BUG: three perpendicular lines drawn: /Users/melchior/Downloads/rpglobalscore_101/rp_2_2.sbml.xml
                #BUG: HO being shown, should be cofactor: /Users/melchior/Downloads/rpglobalscore_91/rp_2_1.sbml.xml
                #BUG: this one should not shift perpendivular lines: /Users/melchior/Downloads/rpglobalscore_101/rp_12_1.sbml.xml
                if not overlaps_arrow['L'][pos_id].count(self.arrowhead_flat)==len(overlaps_arrow['L'][pos_id]) or overlaps_arrow['L'][pos_id].count(self.rev_arrowhead_flat)==len(overlaps_arrow['L'][pos_id]):
                    '''Close but removes some that should have seperated
                    #ignore cases where there are only 2 that go in opposite direction and actually never meet
                    if len(overlaps_arrow['L'][pos_id])==2:
                        if not strict_edge_pos[overlaps_edge['L'][pos_id][0]]['L1'][1]-strict_edge_pos[overlaps_edge['L'][pos_id][0]]['L2'][1]>0 and not strict_edge_pos[overlaps_edge['L'][pos_id][1]]['L1'][1]-strict_edge_pos[overlaps_edge['L'][pos_id][1]]['L2'][1]>0:
                            continue
                        if not strict_edge_pos[overlaps_edge['L'][pos_id][0]]['L1'][1]-strict_edge_pos[overlaps_edge['L'][pos_id][0]]['L2'][1]<0 and not strict_edge_pos[overlaps_edge['L'][pos_id][1]]['L1'][1]-strict_edge_pos[overlaps_edge['L'][pos_id][1]]['L2'][1]<0:
                            continue
                    '''
                    #TODO: need to detect if there are any criss-cross of perpendecular arrows at their target of source to seperate in either direction
                    for edge in strict_edge_pos:
                        l1_id = str(strict_edge_pos[edge]['L1'][0])+'-'+str(strict_edge_pos[edge]['L1'][1])
                        l2_id = str(strict_edge_pos[edge]['L2'][0])+'-'+str(strict_edge_pos[edge]['L1'][1])
                        if l1_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.arrowhead_flat:
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                        elif l1_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.rev_arrowhead_flat:
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                        if l2_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.arrowhead_flat:
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                        elif l2_id==pos_id and strict_edge_pos[edge]['arrow_direction']==self.rev_arrowhead_flat:
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]+self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
                            '''
                            edge_pos[edge]['L1'] = (edge_pos[edge]['L1'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L1'][1])
                            edge_pos[edge]['L2'] = (edge_pos[edge]['L2'][0]-self.arrowhead_comp_y/2, edge_pos[edge]['L2'][1])
        ############## Finally draw ##################
        for edge in edge_pos:
            p = draw.Path(stroke=arrow_stroke_color,
                          stroke_width=arrow_stroke_width,
                          fill='none',
                          marker_end=edge_pos[edge]['arrow_direction'])
            p.M(edge_pos[edge]['source'][0], edge_pos[edge]['source'][1]).L(edge_pos[edge]['L1'][0], edge_pos[edge]['L1'][1]).L(edge_pos[edge]['L2'][0], edge_pos[edge]['L2'][1]).L(edge_pos[edge]['target'][0], edge_pos[edge]['target'][1])
            arrow_box.append(p)
        a = sg.fromstring(arrow_box.asSvg())
        a_b = a.getroot()
        a_b.moveto(0, background_len_y)#WARNING: not sure why I have to + subpot
        fig.append(a_b)
        svg = fig.to_str().decode("utf-8")
        if path:
            open(path, 'w').write(svg)
        return svg, resG, mod_pos, reac_cofactors_name, nodes_attach_locs
Beispiel #9
0
def genSVG(nodes,
           spacing,
           node_size,
           width=None,
           height=None,
           minValue=1,
           maxValue=10,
           node_scaling="linear",
           connection_type="semi-curved",
           color_startEnd=True,
           color_categories=True,
           nodes_color="gray",
           start_node_color="green",
           end_node_color="red",
           palette=None,
           show_labels=True,
           label_text="item",
           label_font="sans-serif",
           label_color="black",
           label_size=5,
           label_shortening="clip",
           label_position="nodes",
           line_opacity=0.5,
           line_stroke_color="white",
           line_stroke_width=0.5,
           line_stroke_thick=0.5,
           legend=True):
    """
    Generates an SVG from data loaded via the read functions.

    Parameters:
    nodes (list): The output of nodify(), a list containingg information about the nodes for the graph
    spacing (int): the space between the nodes, defaults to 50
    node_size (int): default node size, defauults to 10
    width (int): width of the visualization, defaults to None, if None they are generated from the size of the nodes, if they are specified the nodes will be rescaled to fit the space
    height (int): height of the visualization, defaults to None, if None they are generated from the size of the nodes, if they are specified the nodes will be rescaled to fit the space
    minValue (int): min size of a node , defaults to 1
    maxValue (int): max size of a node, defaults to 10
    node_scaling (str): "linear" or ... " ", defaults to "linear"
    connection_type (str): "semi-curved" or "curved" or "linear", defaults to "semi-curved"
    color_startEnd (bool) : if True it marks the colors of the first and last appearence of a category, defaults to True
    color_categories (bool): if True the nodes and the lines are colored depending by the subcategory, deafults to True
    nodes_color (str): the color of the nodes if the previous two options are false, defaults to "gray", used also for the lines and for the middle nodes in case of startEnd option
    start_node_color (str): Defaults to "green"
    end_node_color (str): Defaults to "red"
    palette (tuple): a tuple with the name of the matplotlib palette and the number of colors ("viridis",12), defaults to None
    show_labels (bool): Defaults to True
    label_text (str): "item" shows the category, defaults to "item", "item_count" shows the category and the frequency, "item_category" shows the category and the subcategory
    label_font (str): Defaults to "sans-serif"
    label_color (str): Defaults to "black"
    label_size (int): Defaults to 5
    label_shortening (str): defaults to "clip", "clip" cuts the text when it overlaps the margin, "resize" changes the size of the font to fit the available space, "new_line" wraps the text when it overlaps the margin and it rescale the size if the two lines overlaps the bottom margin
    label_position (str): defaults to "nodes", "nodes" shows a label for each node, "start_end" shows a label for the first and last node of a sequence
    line_opacity (float): Defaults to 0.5
    line_stroke_color (str): Defaults to "white"
    line_stroke_width (float): Defaults to 0.5
    line_stroke_thick (float): Defaults to 0.5
    legend (bool): If True a Legend is included, defaults to True

    Returns:
    (drawSvg.drawing.Drawing): The finished graph
    """
    headers = nodes[0]
    nodes2 = copy.deepcopy(nodes[1])
    sequence = nodes[2]

    if start_node_color == "green":
        start_node_color = "#4BA167"
    if end_node_color == "red":
        end_node_color = "#A04B83"
    if nodes_color == "gray":
        nodes_color = "#EAEBEE"

    # Resizing of the nodes in relation to the canvas size and to the scaling option
    m = max([v.value for v in nodes[1]])
    new_nodes = []
    if width is not None:
        dx = (width - (spacing * 2)) / len(headers)
        spacing2 = 2 * (dx / 3)
        node_size = dx / 3
    else:
        spacing2 = spacing
    if height is not None:
        l_col_index = [x.col_index for x in nodes2]
        l_col_index_max = max([l_col_index.count(y.col_index) for y in nodes2])
        sum_values = sum([
            x.value for x in nodes2
            if l_col_index.count(x.col_index) == l_col_index_max
        ])
        max_values = max([
            x.value for x in nodes2
            if l_col_index.count(x.col_index) == l_col_index_max
        ])
        if node_scaling == "linear":
            dy = ((height - (spacing * 2) -
                   (spacing / 5)) * max_values) / (sum_values + (
                       (maxValue / 2) * l_col_index_max))
        else:
            dy = ((height - (spacing * 2) -
                   (spacing / 5)) * max_values) / (sum_values + (
                       (max_values / 2) * l_col_index_max))
        spacingy = dy / 3
        maxValue = 2 * (dy / 3)
    else:
        spacingy = spacing / 5

    node_x = 0
    for n in nodes2:
        n.width = node_size
        if n.col_index != nodes2[n.index - 1].col_index and n.index > 0:
            node_x += node_size
        n.x += node_x

        if node_scaling == "linear":
            n.size = (((n.value + 1) * maxValue) / m) + minValue
        elif node_scaling == "log":
            n.size = (((maxValue - minValue) / math.log(m)) *
                      math.log(n.value)) + minValue

        new_nodes.append(n)

    # positioning of the nodes on the canvas (x,y)
    n_x_spacing = spacing
    n_y_spacing = spacing + spacingy
    points = []
    for n in new_nodes:

        if n.index > 0 and n.col_index == new_nodes[n.index - 1].col_index:
            n_y_spacing += spacingy + n.size
        else:
            n_y_spacing = spacing + spacingy + n.size
        if n.index > 0 and n.col_index != new_nodes[n.index - 1].col_index:
            n_x_spacing += spacing2

        points.append(
            pcf.Node(n.index, n.col_index, n.x + n_x_spacing,
                     n.y + n_y_spacing, n.size, n.value, n.width, n.label,
                     n.category))

    # sizing of the canvas
    if width is None and height is None:
        width = spacing * 4 + max([x.x for x in points])
        height = spacing * 4 + max([x.y for x in points]) + (
            (sum([x.size for x in points]) / len(points)) *
            len(set([x.category for x in points])))
    elif height is None:
        height = spacing * 4 + max([x.y for x in points]) + (
            (sum([x.size for x in points]) / len(points)) *
            len(set([x.category for x in points])))
    elif width is None:
        width = spacing * 4 + max([x.x for x in points])

    # COLORS
    if palette is not None:
        palette = cm.get_cmap(palette[0], palette[1]).colors
        count = 0
        category_colors = {}
        for e in set([n.category for n in points]):
            if count < len(palette):
                count += 1
            category_colors[e] = colors.to_hex(palette[count])
    else:
        # DEFAULT PALETTE: the number of colors is set in relation to the length of the category list
        palette = cm.get_cmap("tab20c",
                              len(set([n.category
                                       for n in points])) + 1).colors
        count = 0
        category_colors = {}
        for e in set([n.category for n in points]):
            if count < len(palette) - 1:
                count += 1
            category_colors[e] = colors.to_hex(palette[count])

    d = draw.Drawing(width, height, displayInline=True)
    r = draw.Rectangle(0,
                       0,
                       width,
                       height,
                       stroke_width=2,
                       stroke='black',
                       fill="white")
    d.append(r)

    # headers
    h_x_shift = [points[0].x]

    for x in points:
        if x.x != points[x.index - 1].x and x.index > 0:
            h_x_shift.append(x.x)

    n2 = h_x_shift[1] - h_x_shift[0]

    for h, x in zip(headers, h_x_shift):
        l = label_size
        if label_shortening == "resize":
            while len(h) * (l / 2) > n2 + points[0].size - (n2 / 8) and l > 1:
                if x != max(h_x_shift):
                    l -= 1
                else:
                    break
            d.append(
                draw.Text(h,
                          x=x,
                          y=height - spacing,
                          fontSize=l,
                          font_family=label_font,
                          fill=label_color))
        elif label_shortening == "clip":
            clip = draw.ClipPath()
            clip.append(draw.Rectangle(x, height - spacing, n2, label_size))
            d.append(
                draw.Text(h,
                          x=x,
                          y=height - spacing,
                          fontSize=l,
                          font_family=label_font,
                          clip_path=clip,
                          fill=label_color))
        elif label_shortening == "new_line":
            if len(h) * (label_size / 2) > n2 + points[0].size - (n2 / 8):
                margin = int(
                    (n2 + points[0].size - (n2 / 8)) / (label_size / 2))
                txt = [h[x:x + margin] for x in range(0, len(h), margin)]
                while len(txt) * l > (l + n2 / 5) and l > 1:
                    l -= 1
            else:
                txt = h
            d.append(
                draw.Text(txt,
                          x=x,
                          y=height - spacing,
                          fontSize=l,
                          font_family=label_font,
                          fill=label_color))

    # lines
    for n in sequence.items():
        if len(n[1]) > 1:
            for k in n[1][:-1]:
                if color_categories:
                    color = category_colors[points[k].category]
                else:
                    color = nodes_color
                if connection_type.lower() == "semi-curved":
                    p = draw.Path(fill=color,
                                  stroke=line_stroke_color,
                                  opacity=line_opacity,
                                  stroke_width=line_stroke_width)
                    p.M(points[k].x + points[k].width, height - points[k].y)
                    p.L(points[k].x + points[k].width,
                        height - points[k].y + points[k].size)

                    if points[k].y == points[n[1][n[1].index(k) + 1]].y:
                        p.L(points[n[1][n[1].index(k) + 1]].x,
                            height - points[k].y + points[k].size)
                        p.L(points[n[1][n[1].index(k) + 1]].x,
                            height - points[k].y)

                    else:
                        xMedium = ((points[n[1][n[1].index(k) + 1]].x -
                                    (points[k].x + points[k].width)) /
                                   2) + (points[k].x + points[k].width)
                        yMedium = (
                            ((height - points[k].y + points[k].size) -
                             (height - points[n[1][n[1].index(k) + 1]].y +
                              points[k].size)) /
                            2) + (height - points[n[1][n[1].index(k) + 1]].y)
                        yMedium2 = (
                            ((height - points[k].y) -
                             (height - points[n[1][n[1].index(k) + 1]].y)) /
                            2) + (height - points[n[1][n[1].index(k) + 1]].y)
                        p.Q(points[k].x + points[k].width + (spacing / 2),
                            height - points[k].y + points[k].size,
                            xMedium + line_stroke_thick,
                            yMedium + points[k].size)
                        p.T(
                            points[n[1][n[1].index(k) + 1]].x,
                            height - points[n[1][n[1].index(k) + 1]].y +
                            points[n[1][n[1].index(k) + 1]].size)
                        p.L(points[n[1][n[1].index(k) + 1]].x,
                            height - points[n[1][n[1].index(k) + 1]].y)
                        p.Q(points[n[1][n[1].index(k) + 1]].x - (spacing / 2),
                            height - points[n[1][n[1].index(k) + 1]].y,
                            xMedium - line_stroke_thick, yMedium2)
                        p.T(points[k].x + points[k].width,
                            height - points[k].y)

                    p.Z()
                    d.append(p)
                elif connection_type.lower() == 'curved':
                    p = draw.Path(fill=color,
                                  stroke=line_stroke_color,
                                  opacity=line_opacity,
                                  stroke_width=line_stroke_width)

                    size_start = points[k].size
                    size_end = points[n[1][n[1].index(k) + 1]].size

                    x1_start = points[k].x + points[k].width
                    y1_start = height - points[k].y + size_start

                    x1_end = points[n[1][n[1].index(k) + 1]].x
                    y1_end = height - points[n[1][n[1].index(k) +
                                                  1]].y + size_end

                    x2_start = x1_start
                    y2_start = y1_start - size_start

                    x2_end = x1_end
                    y2_end = y1_end - size_end

                    x_diff = x1_end - x1_start
                    y_diff = y2_start - y1_end
                    height_factor = 2
                    width_factor = 0

                    if points[k].y == points[n[1][n[1].index(k) + 1]].y:
                        p.M(x1_start, y1_start)
                        p.L(x2_start, y2_start)
                        p.L(x2_end, y2_end)
                        p.L(x1_end, y1_end)
                        p.Z()
                        d.append(p)
                        pass

                    else:
                        p.M(x1_start, y1_start)
                        cx1 = x1_end - (x_diff / 4 * 3)
                        cy1 = y1_start
                        ex1 = x1_end - (x_diff / 2)
                        ey1 = y1_end + (y_diff / 2)
                        p.Q(cx1, cy1, ex1, ey1)

                        cx2 = x1_start + (x_diff / 4 * 3)
                        cy2 = y1_end - (size_end / height_factor)
                        p.Q(cx2, cy2, x1_end, y1_end)

                        p.L(x2_end, y2_end)

                        cx3 = (x2_end - (x_diff / 4))
                        cy3 = (y2_end - (size_end / height_factor))
                        ex3 = (x2_end + ((x1_start - x1_end) / 2) -
                               width_factor)
                        ey3 = (y2_end + (((y1_start - y1_end) / 2) - ((
                            (size_start + size_end) / 2)) / height_factor))
                        p.Q(cx3, cy3, ex3, ey3)

                        cx4 = x2_start + (x_diff / 4)
                        cy4 = y2_start
                        p.Q(cx4, cy4, x2_start, y2_start)

                        p.Z()
                        d.append(p)

                elif connection_type.lower() == 'straight':
                    p = draw.Path(fill=color,
                                  stroke=line_stroke_color,
                                  opacity=line_opacity,
                                  stroke_width=line_stroke_width)
                    size_start = points[k].size
                    size_end = points[n[1][n[1].index(k) + 1]].size

                    x1_start = points[k].x + points[k].width
                    y1_start = height - points[k].y

                    x1_end = points[n[1][n[1].index(k) + 1]].x
                    y1_end = height - points[n[1][n[1].index(k) + 1]].y

                    x2_start = x1_start
                    y2_start = y1_start + size_start

                    x2_end = x1_end
                    y2_end = y1_end + size_end

                    p.M(x1_start, y1_start)
                    p.L(x2_start, y2_start)
                    p.L(x2_end, y2_end)
                    p.L(x1_end, y1_end)

                    p.Z()
                    d.append(p)

                else:
                    print('This connection type is not implemented.')
                    raise KeyError

    # nodes
    # return points
    col_index_max = 0
    for node in points:
        if node.col_index > col_index_max:
            col_index_max = node.col_index

    for node in points:
        if color_startEnd == True and color_categories == True:
            if node.label not in [n.label for n in points][:node.index]:
                color = start_node_color
            elif node.label not in [
                    n.label for n in points
            ][node.index +
              1:] and node.col_index < col_index_max:  #and node.index<len(points):
                color = end_node_color
            else:
                color = category_colors[node.category]
        elif color_startEnd and not color_categories:
            if node.label not in [n.label for n in points][:node.index]:
                color = start_node_color
            elif node.label not in [
                    n.label for n in points
            ][node.index +
              1:] and node.col_index < col_index_max:  #and node.index<len(points):
                color = end_node_color
            else:
                color = nodes_color
        elif not color_startEnd and color_categories:
            color = category_colors[node.category]
        elif not color_startEnd and not color_categories:
            color = nodes_color
        if node.label != '':
            r = draw.Rectangle(node.x,
                               height - node.y,
                               node.width,
                               node.size,
                               fill=color,
                               stroke=color)  #stroke="black"
            d.append(r)

        if show_labels:
            if label_text == "item":
                txt = node.label
            elif label_text == "item_count":
                txt = node.label + ' (' + str(node.value) + ')'
            elif label_text == "item_category":
                txt = node.label + ' (' + str(node.category) + ')'

            l = label_size
            if label_shortening == "resize":
                while len(txt) * (l / 2) > spacing - (spacing / 8):
                    if node.x != max([n.x for n in points]) and l > 1:
                        l -= 1
                    else:
                        break
            elif label_shortening == "clip":
                clip = draw.ClipPath()
                clip.append(
                    draw.Rectangle(node.x, height - node.y - (spacing / 5),
                                   n2 - (n2 / 8),
                                   node.size + 2 * (spacing / 5)))
            elif label_shortening == "new_line":
                if len(txt) * (label_size / 2) > n2 - 2 * (n2 / 8):
                    margin = int((n2 - 2 * (n2 / 8)) / (label_size / 2))
                    txt = [
                        txt[x:x + margin] for x in range(0, len(txt), margin)
                    ]
                    while len(txt) * l > node.size + 2 * (spacing /
                                                          8) and l > 1:
                        l -= 1

            label_pos_y = height - node.y + (node.size / 2) - (l / 2)
            if label_position == "start_end":
                if node.label not in [
                        n.label for n in points
                ][:node.index] or node.label not in [
                        n.label for n in points
                ][node.index +
                  1:] and node.index < len(points) and node.x != max(
                      [n.x for n in points]):
                    if label_shortening == "clip":
                        label = draw.Text(txt,
                                          x=node.x + node.width + (n2 / 8),
                                          y=label_pos_y,
                                          fontSize=l,
                                          font_family=label_font,
                                          fill=label_color,
                                          clip_path=clip)
                    else:
                        label = draw.Text(txt,
                                          x=node.x - (n2 / 8),
                                          y=label_pos_y,
                                          fontSize=l,
                                          font_family=label_font,
                                          fill=label_color,
                                          text_anchor="end")

            elif label_position == "nodes":
                if label_shortening == "clip":
                    label = draw.Text(txt,
                                      x=node.x + node.width + (n2 / 8),
                                      y=label_pos_y,
                                      fontSize=l,
                                      font_family=label_font,
                                      fill=label_color,
                                      clip_path=clip)
                else:
                    label = draw.Text(txt,
                                      x=node.x + node.width + (n2 / 8),
                                      y=label_pos_y,
                                      fontSize=l,
                                      font_family=label_font,
                                      fill=label_color)
            d.append(label)

    # Add legend to canvas
    if color_categories and legend:
        offset = 5  # Alternative: offset = spacing
        spacing_bottom = 5  # Alternative: spacing_bottom = spacing
        symbol_size = sum([x.size for x in points]) / len(points)

        legend_height = (symbol_size + offset) * len(category_colors)
        legend_header_y = legend_height + symbol_size + spacing_bottom + (
            offset)
        legend_header = draw.Text("Legend",
                                  x=points[0].x,
                                  y=legend_header_y,
                                  fontSize=label_size,
                                  font_family=label_font,
                                  fill=label_color)

        if debug_legend:
            print('Legend Title')
            print('legend_height: {}'.format(legend_height))
            print('legend_header_y: {}'.format(legend_header_y))
            print('points[0].x: {}'.format(points[0].x))
            print('legend_header_y'.format(legend_header_y))
            print()

        d.append(legend_header)
        symbol_y_shift = 0
        for e in category_colors.items():

            legend_label_y = spacing_bottom + legend_height + (
                symbol_size / 2) - (label_size / 2) - offset - symbol_y_shift

            symbol = draw.Rectangle(points[0].x,
                                    spacing_bottom + legend_height - offset -
                                    symbol_y_shift,
                                    points[0].width,
                                    symbol_size,
                                    fill=e[1],
                                    stroke=e[1])  #stroke="black"

            if debug_legend:
                print(e)
                print('points[0].x: {}'.format(points[0].x))
                print('spacing_bottom+legend_height-offset-symbol_y_shift: {}'.
                      format(spacing_bottom + legend_height - offset -
                             symbol_y_shift))
                print('points[0].width: {}'.format(points[0].width))
                print('symbol_size: {}'.format(symbol_size))
                print()

            name = draw.Text(e[0],
                             x=points[0].x + node.width + (n2 / 12),
                             y=legend_label_y,
                             fontSize=label_size,
                             fill=label_color)
            d.append(symbol)
            d.append(name)
            if spacing_bottom + legend_height - (
                    offset) - symbol_y_shift > spacing_bottom:
                symbol_y_shift += offset + symbol_size
            else:
                symbol_y_shift = 0

    return d
Beispiel #10
0
    def draw(self, save=False, retEls=False, off=(0, 0)):
        els = []

        d = draw.Drawing(1.2 * self.width,
                         1.2 * self.height,
                         origin=self.origin)

        self.dim_sorted()

        hstep = self.width / len(self.dims)

        for i in range(len(self.dims)):

            l = draw.Line(off[0] + self.width - i * hstep,
                          off[1] + 0,
                          off[0] + self.width - i * hstep,
                          off[1] + self.height,
                          stroke="black",
                          stroke_width=2,
                          fill=None)

            els.append(l)

        for dim, count in self.dims.items():
            for i in range(count):
                vstep = self.height / count
                c = draw.Circle(off[0] + self.width - dim * hstep,
                                off[1] + vstep * i,
                                self.diam,
                                fill="blue",
                                stroke_width=2,
                                stroke="black")
                els.append(c)

        for dif in self.diff:
            base = dif["0"]
            coefs = dif["coefs"]
            vstep = self.height / self.dims[base[0]]
            baseCoor = (off[0] + self.width - base[0] * hstep,
                        off[1] + vstep * base[1])

            middle = lambda x, y: (x[0] / 2 + y[0] / 2, x[1] / 2 + y[1] / 2 +
                                   10)

            for gen, coef in coefs.items():
                vstep = self.height / self.dims[base[0] - 1]
                endCoor = (off[0] + self.width - (base[0] - 1) * hstep,
                           off[1] + vstep * gen)
                l = draw.Line(*baseCoor,
                              *endCoor,
                              stroke="grey",
                              stroke_width=1,
                              fill=None)

                els.append(l)

                p = draw.Path(stroke_width=2,
                              stroke='lime',
                              fill='black',
                              fill_opacity=0.2)
                p.M(*baseCoor)  # Start path at point (-10, 20)
                p.L(*endCoor)  # Draw a curve to (70, 20)

                if coef != 1:
                    text = draw.Text(str(coef),
                                     12,
                                     *middle(baseCoor, endCoor),
                                     text_anchor='start',
                                     valign='middle')

                    els.append(text)

        if retEls:
            return els
        else:
            for el in els:
                d.append(el)
        return d
Beispiel #11
0
        current_wall = map_file.walls[sector.wall_pointer]

        for _ in range(sector.wall_number):
            bounds.extend((current_wall.x, current_wall.y))
            current_wall = map_file.walls[current_wall.point2]

    print(bounds)

    d = drawSvg.Drawing(65000, 65000, origin='center')

    for sector in map_file.sectors:
        current_wall = map_file.walls[sector.wall_pointer]
        current_point = current_wall.x, current_wall.y
        first_point = current_point

        p = drawSvg.Path(stroke_width=4, stroke='black')
        p.M(*current_point)

        for _ in range(sector.wall_number):
            next_wall = map_file.walls[current_wall.point2]
            next_point = next_wall.x, next_wall.y
            p.L(*next_point)
            current_wall = next_wall

        p.L(*first_point)
        p.Z()
        d.append(p)

    d.saveSvg('/Users/Joshua/Desktop/e1l1.svg')

sys.exit(0)