Flowcharts and Diagrams ======================= .. jupyter-execute:: :hide-code: %config InlineBackend.figure_format = 'svg' import schemdraw from schemdraw import flow Schemdraw provides basic symbols for flowcharting and state diagrams. The :py:mod:`schemdraw.flow.flow` module contains a set of functions for defining flowchart blocks and connecting lines that can be added to schemdraw Drawings. .. code-block:: python from schemdraw import flow Flowchart blocks: .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=10, unit=.5) d.add(flow.Start().label('Start').drop('E')) d.add(flow.Arrow()) d.add(flow.Ellipse().label('Ellipse')) d.add(flow.Arrow()) d.add(flow.Box(label='Box')) d.add(flow.Arrow()) d.add(flow.RoundBox(label='RoundBox').drop('S')) d.add(flow.Arrow().down()) d.add(flow.Subroutine(label='Subroutine').drop('W')) d.add(flow.Arrow().left()) d.add(flow.Data(label='Data')) d.add(flow.Arrow()) d.add(flow.Decision(label='Decision')) d.add(flow.Arrow()) d.add(flow.Connect(label='Connect')) d.draw() Some elements have been defined with multiple names, which can be used depending on the context or user preference: .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=10, unit=.5) d.add(flow.Terminal().label('Terminal').drop('E')) d.add(flow.Arrow()) d.add(flow.Process().label('Process')) d.add(flow.Arrow()) d.add(flow.RoundProcess().label('RoundProcess')) d.add(flow.Arrow()) d.add(flow.Circle(label='Circle')) d.add(flow.Arrow()) d.add(flow.State(label='State')) d.add(flow.Arrow()) d.add(flow.StateEnd(label='StateEnd')) d.draw() 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 :py:class:`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. .. jupyter-execute:: d = schemdraw.Drawing(fontsize=10, unit=.5) d += flow.Terminal().label('Start') d += flow.Arrow() d += flow.Process().label('Do something').drop('E') d += flow.Arrow().right() d += flow.Process().label('Do something\nelse') d.draw() 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. .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=12, unit=1) .. jupyter-execute:: d += (a := flow.State().label('A')) d += (b := flow.State(arrow='->').label('B').at((4, 0))) d += flow.Arc2(arrow='->').at(a.NE).to(b.NW).color('deeppink').label('Arc2') d += flow.Arc2(k=.2, arrow='<->').at(b.SW).to(a.SE).color('mediumblue').label('Arc2') .. jupyter-execute:: :hide-code: d.draw() ArcZ and ArcN ^^^^^^^^^^^^^ These draw symmetric cubic Bezier curves between the endpoints. The `ArcZ` curve approaches the endpoints horizontally, and `ArcN` approaches them vertically. .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=12, unit=1) .. jupyter-execute:: d += (a := flow.State().label('A')) d += (b := flow.State().label('B').at((4, 4))) d += (c := flow.State().label('C').at((8, 0))) d += flow.ArcN(arrow='<->').at(a.N).to(b.S).color('deeppink').label('ArcN') d += flow.ArcZ(arrow='<->').at(b.E).to(c.W).color('mediumblue').label('ArcZ') .. jupyter-execute:: :hide-code: d.draw() 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. .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=12, unit=1) .. jupyter-execute:: d += (a := flow.State().label('A')) d += (b := flow.State().label('B').at((3, 3))) d += flow.Arc3(th1=75, th2=-45, arrow='<->').at(a.N).to(b.SE).color('deeppink').label('Arc3') .. jupyter-execute:: :hide-code: d.draw() 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. .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=12, unit=1) .. jupyter-execute:: d += (a := flow.State().label('A')) d += flow.ArcLoop(arrow='<-').at(a.NW).to(a.NNE).color('mediumblue').label('ArcLoop', halign='center') .. jupyter-execute:: :hide-code: d.draw() Decisions --------- To label the decision branches, the :py:class:`schemdraw.flow.flow.Decision` element takes keyword arguments for each cardinal direction. For example: .. jupyter-execute:: :hide-code: d = schemdraw.Drawing(fontsize=12, unit=1) .. jupyter-execute:: decision = flow.Decision(W='Yes', E='No', S='Maybe').label('Question?') .. jupyter-execute:: :hide-code: dec = d.add(decision) d.add(flow.Line().at(dec.W).left()) d.add(flow.Line().at(dec.E).right()) d.add(flow.Line().at(dec.S).down()) d.draw() 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. .. jupyter-execute:: d = schemdraw.Drawing(fontsize=10, unit=.5) d += flow.Terminal().label('Start') d += flow.Arrow() d += flow.Process().label('Step 1') d += flow.Arrow() d += flow.Process().label('Step 2').drop('E') d += flow.Arrow().right() d += flow.Connect().label('Next') d += flow.Terminal().label('Start').at((4, 0)) d += flow.Arrow().theta(-45) d += flow.Process().label('Step 1') d += flow.Arrow() d += flow.Process().label('Step 2').drop('E') d += flow.Arrow().right() d += flow.Connect().label('Next') d.draw() See the :ref:`galleryflow` Gallery for more examples.