Flowcharts and Diagrams

Schemdraw provides basic symbols for flowcharting and state diagrams. The schemdraw.flow.flow module contains a set of functions for defining flowchart blocks and connecting lines that can be added to schemdraw Drawings.

from schemdraw import flow

Flowchart blocks:

../_images/flow_1_0.svg

Some elements have been defined with multiple names, which can be used depending on the context or user preference:

../_images/flow_2_0.svg

All flowchart symbols have 16 anchor positions named for the compass directions: ‘N’, ‘S’, ‘E’, ‘W’, ‘NE’, ‘SE, ‘NNE’, etc., plus a ‘center’ anchor.

The schemdraw.elements.intcircuits.Ic element can be used with the flowchart elements to create blocks with other inputs/outputs per side if needed.

The size of each block must be specified manually using w and h or r parameters to size each block to fit any labels.

Connecting Lines

Typical flowcharts will use Line or Arrow elements to connect the boxes. The line and arrow elements have been included in the flow module for convenience.

with schemdraw.Drawing() as d:
    d.config(fontsize=10, unit=.5)
    flow.Terminal().label('Start')
    flow.Arrow()
    flow.Process().label('Do something').drop('E')
    flow.Arrow().right()
    flow.Process().label('Do something\nelse')
../_images/flow_3_0.svg

Some flow diagrams, such as State Machine diagrams, often use curved connectors between states. Several Arc connectors are available. Each Arc element takes an arrow parameter, which may be ‘->’, ‘<-’, or ‘<->’, to define the end(s) on which to draw arrowheads.

Arc2

Arc2 draws a symmetric quadratic Bezier curve between the endpoints, with curvature controlled by parameter k. Endpoints of the arc should be specified using at() and to() methods.

with schemdraw.Drawing(fontsize=12, unit=1):
    a = flow.State().label('A')
    b = flow.State(arrow='->').label('B').at((4, 0))
    flow.Arc2(arrow='->').at(a.NE).to(b.NW).color('deeppink').label('Arc2')
    flow.Arc2(k=.2, arrow='<->').at(b.SW).to(a.SE).color('mediumblue').label('Arc2')
../_images/flow_4_0.svg

ArcZ and ArcN

These draw symmetric cubic Bezier curves between the endpoints. The ArcZ curve approaches the endpoints horizontally, and ArcN approaches them vertically.

with schemdraw.Drawing(fontsize=12, unit=1):
    a = flow.State().label('A')
    b = flow.State().label('B').at((4, 4))
    c = flow.State().label('C').at((8, 0))
    flow.ArcN(arrow='<->').at(a.N).to(b.S).color('deeppink').label('ArcN')
    flow.ArcZ(arrow='<->').at(b.E).to(c.W).color('mediumblue').label('ArcZ')
../_images/flow_5_0.svg

Arc3

The Arc3 curve is an arbitrary cubic Bezier curve, defined by endpoints and angle of approach to each endpoint. ArcZ and ArcN are simply Arc3 defined with the angles as 0 and 180, or 90 and 270, respectively.

with schemdraw.Drawing(fontsize=12, unit=1):
    a = flow.State().label('A')
    b = flow.State().label('B').at((3, 3))
    flow.Arc3(th1=75, th2=-45, arrow='<->').at(a.N).to(b.SE).color('deeppink').label('Arc3')
../_images/flow_6_0.svg

ArcLoop

The ArcLoop curve draws a partial circle that intersects the two endpoints, with the given radius. Often used in state machine diagrams to indicate cases where the state does not change.

with schemdraw.Drawing(fontsize=12, unit=1):
    a = flow.State().label('A')
    flow.ArcLoop(arrow='<-').at(a.NW).to(a.NNE).color('mediumblue').label('ArcLoop', halign='center')
../_images/flow_7_0.svg

Decisions

To label the decision branches, the schemdraw.flow.flow.Decision element takes keyword arguments for each cardinal direction. For example:

decision = flow.Decision(W='Yes', E='No', S='Maybe').label('Question?')
../_images/flow_10_0.svg

Layout and Flow

Without any directions specified, boxes flow top to bottom (see left image). If a direction is specified (right image), the flow will continue in that direction, starting the next arrow at an appropriate anchor. Otherwise, the drop method is useful for specifing where to begin the next arrow.

with schemdraw.Drawing() as d:
    d.config(fontsize=10, unit=.5)
    flow.Terminal().label('Start')
    flow.Arrow()
    flow.Process().label('Step 1')
    flow.Arrow()
    flow.Process().label('Step 2').drop('E')
    flow.Arrow().right()
    flow.Connect().label('Next')

    flow.Terminal().label('Start').at((4, 0))
    flow.Arrow().theta(-45)
    flow.Process().label('Step 1')
    flow.Arrow()
    flow.Process().label('Step 2').drop('E')
    flow.Arrow().right()
    flow.Connect().label('Next')
../_images/flow_11_0.svg

Containers

Use schemdraw.Drawing.container() as a context manager to add elements to be enclosed in a box. The elements in the container are added to the outer drawing too; the container just draws the box around them when it exits the with.

with schemdraw.Drawing(unit=1) as d:
    flow.Start().label('Start')
    flow.Arrow().down().length(1.5)
    with d.container() as c:
        flow.Box().label('Step 1').drop('E')
        flow.Arrow().right()
        flow.Box().label('Step 2')
        c.color('red')
        c.label('Subprocess', loc='N', halign='center', valign='top')
    flow.Arrow().right()
    flow.Start().label('End').anchor('W')
../_images/flow_12_0.svg

Containers may be nested, calling container() on either a Drawing, or another Container.

Examples

See the Flowcharting Gallery for more examples.