Skip to main content

Pero

The main motivation behind the pero library is to provide unified API for multiple drawing backends like PyQt5, PyQt6, PySide2, PySide6, wxPython, PyCairo, PyMuPDF, Py5, Pythonista (and possibly more), which is easy to understand and use. Beside the common drawing capabilities, numerous pre-build glyphs are available, as well as an easy-to-use path, matrix transformations etc. Depending on available backend libraries, drawings can be viewed directly or exported into various image formats.

Ever since I discovered the wonderful d3js JavaScript library, I wanted to have the same amazing concept of dynamic properties within Python drawings. In fact, this has been the trigger to start working on the pero library. Finally, it is now available.

Please see the examples folder or in-code documentation of classes and functions to learn more about the pero library capabilities.

Consider also checking a small derived library providing some basic plotting functionalities, like profiles, bars, pie charts and Venn diagrams, called perrot.

import pero

img = pero.Image(width=200, height=200)

img.line_cap = pero.ROUND
img.line_join = pero.ROUND

# fill
img.fill("w")

# body
img.line_width = 2
img.line_color = pero.colors.Orange.darker(.1)
img.fill_color = pero.colors.Orange
img.draw_circle(100, 100, 75)

# shadow
img.line_color = None
img.fill_color = pero.colors.White.darker(.1)
img.draw_ellipse(100, 185, 70, 10)

# eyes
img.fill_color = pero.colors.Black
img.draw_circle(70, 85, 15)
img.draw_circle(130, 85, 15)

# eyebrows
img.line_color = pero.colors.Black
img.fill_color = None
img.line_width = 3
img.draw_arc(70, 85, 23, pero.rads(-100), pero.rads(-20))
img.draw_arc(130, 85, 23, pero.rads(200), pero.rads(280))

# mouth
img.line_width = 5
img.draw_arc(100, 100, 50, pero.rads(40), pero.rads(80))

# highlight
img.line_color = pero.colors.Orange.lighter(.3)
img.draw_arc(100, 100, 68, pero.rads(220), pero.rads(260))

# hat
path = pero.Path(pero.WINDING)
path.ellipse(100, 27, 40, 10)
path.ellipse(100, 17, 30, 10)
path.rect(85, 17, 30, 10)

mat = pero.Matrix().rotate(pero.rads(20), 100, 100)
path.transform(mat)

img.line_color = None
img.fill_color = pero.colors.Black
img.draw_path(path)

# show image
img.show()

Final Image

Requirements

Supported Backends

Installation

The pero library is fully implemented in Python. No additional compiler is necessary. After downloading the source code just run the following command from the pero folder:

$ python setup.py install

or simply use pip

$ pip install pero

Disclaimer

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Please note that the pero library is still in an alpha state. Any changes in its API may occur.

Usage

Using default backend

If you just want to draw an image using whatever the default backend is (for requested format), or show the image directly (requires PyQt5, PyQt6, PySide2, PySide6, wxPython or Pythonista iOS App), just create an image and use it as any other pero canvas:

import pero

# init size
width = 200
height = 200

# init image
img = pero.Image(width=width, height=height)

# draw graphics
img.line_color = "b"
img.fill_color = "w"
img.fill()
img.draw_circle(100, 100, 75)

# save to file
img.export('image.png')

# show in viewer
img.show()

Using PyQt5, PyQt6, PySide2 or PySide6

Inside a QWidget you can create a QPainter and encapsulate it into the pero canvas:

import pero
from PyQt5.QtGui import QPainter

# init size
width = 200
height = 200

# init painter
qp = QPainter()
qp.begin(self)
qp.setRenderHint(QPainter.RenderHint.Antialiasing)

# init canvas
canvas = pero.qt.QtCanvas(qp, width=width, height=height)

# draw graphics
canvas.line_color = "b"
canvas.fill_color = "w"
canvas.fill()
canvas.draw_circle(100, 100, 75)

# end drawing
qp.end()

Using wxPython

Inside a wxApp you can use just about any wxDC you want and encapsulate it into the pero canvas:

import pero
import wx

# init size
width = 200
height = 200

# create DC
bitmap = wx.Bitmap(width, height)
dc = wx.MemoryDC()
dc.SelectObject(bitmap)

# use GCDC
if 'wxMac' not in wx.PlatformInfo:
    dc = wx.GCDC(dc)

# init canvas
canvas = pero.wx.WXCanvas(dc, width=width, height=height)

# draw graphics
canvas.line_color = "b"
canvas.fill_color = "w"
canvas.fill()
canvas.draw_circle(100, 100, 75)

Using PyCairo

Depending on the final image format, choose appropriate cairo surface, get the drawing context and encapsulate it into the pero canvas:

import pero
import cairo

# init size
width = 200
height = 200

# create cairo drawing context
surface = cairo.PSSurface('image.eps', width, height)
dc = cairo.Context(surface)

# init canvas
canvas = pero.cairo.CairoCanvas(dc, width=width, height=height)

# draw graphics
canvas.line_color = "b"
canvas.fill_color = "w"
canvas.fill()
canvas.draw_circle(100, 100, 75)

# save to file
dc.show_page()

Using PyMuPDF

Create a document, add new page and encapsulate it into the pero canvas:

import pero
import fitz

# init size
width = 200
height = 200

# init document
doc = fitz.open()
page = doc.newPage(width=width, height=height)

# init canvas
canvas = pero.mupdf.MuPDFCanvas(page)

# draw graphics
canvas.line_color = "b"
canvas.fill_color = "w"
canvas.fill()
canvas.draw_circle(100, 100, 75)

# save to file
doc.save('image.pdf')
doc.close()

Using Py5

Create a Py5Graphics and encapsulate it into the pero canvas:

import py5
import pero
from pero.backends.py5 import Py5Canvas


def setup():
    
    # init py5 graphics
    py5.size(200, 200)
    pg = py5.create_graphics(200, 200)
    
    # init canvas
    canvas = Py5Canvas(pg)
    
    # draw graphics
    with pg.begin_draw():
        canvas.line_color = "b"
        canvas.fill_color = "w"
        canvas.fill()
        canvas.draw_circle(100, 100, 75)
        
    # finalize image
    py5.image(pg, 0, 0)

# show sketch
py5.run_sketch()

Using SVG

The pero library implements its own way to draw and save SVG files. Just create a pero canvas:

import pero

# init size
width = 200
height = 200

# init canvas
canvas = pero.svg.SVGCanvas(width=width, height=height)

# draw graphics
canvas.line_color = "b"
canvas.fill_color = "w"
canvas.fill()
canvas.draw_circle(100, 100, 75)

# save to file
with open('test.svg', 'w', encoding='utf-8') as f:
    f.write(canvas.get_xml())

Using Pythonista

Initialize a new ui.ImageContext and create a pero canvas:

import pero
import ui

# init size
width = 200
height = 200

# open context
with ui.ImageContext(width, height) as ctx:
    
    # init canvas
    canvas = pero.pythonista.UICanvas(width=width, height=height)
    
    # draw graphics
    canvas.line_color = "b"
    canvas.fill_color = "w"
    canvas.fill()
    canvas.draw_circle(100, 100, 75)
    
    # show image
    img = ctx.get_image()
    img.show()

Using glyphs and dynamic properties

Similar to d3js JavaScript library, most of the properties of pre-build pero.Glyphs objects can be specified as a function, to which given data source is automatically provided. Together with pero.scales (and maybe the pero.Axis) this can be used to make simple plots easily.

import pero
import numpy

# init size
width = 400
height = 300
padding = 50

# init data
x_data = numpy.linspace(-numpy.pi, numpy.pi, 50)
y_data = numpy.sin(x_data)

# init scales
x_scale = pero.LinScale(
    in_range = (min(x_data), max(x_data)),
    out_range = (padding, width-padding))

y_scale = pero.LinScale(
    in_range = (-1, 1),
    out_range = (height-padding, padding))

color_scale = pero.GradientScale(
    in_range = (-1, 1),
    out_range = pero.colors.Spectral)

# init marker
marker = pero.Circle(
    size = 8,
    x = lambda d: x_scale.scale(d[0]),
    y = lambda d: y_scale.scale(d[1]),
    line_color = lambda d: color_scale.scale(d[1]).darker(.2),
    fill_color = lambda d: color_scale.scale(d[1]))

# init image
image = pero.Image(width=width, height=height)

# fill
image.fill("w")

# draw points
for point in zip(x_data, y_data):
    marker.draw(image, point)

# show image
image.show()

Examples

In the examples folder you will find sample codes to generate and understand all the following images. Check the image name and find corresponding python draw file.

Metadata

Release files for pero 0.31.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pero 0.31.0
File Size Uploaded
pero-0.31.0.tar.gz 209.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pero 0.31.0
File Interpreter ABI Platform
pero-0.31.0-py3-none-any.whl Python 3 none any Details

Total release size: 497.5 kB

Release files / pero-0.31.0.tar.gz

Download URL pero-0.31.0.tar.gz
Size 209.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cdee2d7091c3013dad49b40756705f51ef8a8e26122438c68b799e11257cbcd6
BLAKE2b-256 checksum
How to use checksums
9c7c68353dfd09234bf344d79b2ffd26109cec16516ef90820eea02e93c3e93d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / pero-0.31.0-py3-none-any.whl

Download URL pero-0.31.0-py3-none-any.whl
Size 287.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
897fa28c8d207e405b98b4b3fd64ccc517f89a0a87c6bdfac73d25f9e45d1d9c
BLAKE2b-256 checksum
How to use checksums
dd8a20145537915302c347ec679a41c25af174f381d6d9190cd42bdce487e662
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

This release

0.31.0 This release

2 release files

0.30.0

2 release files

0.28.0

2 release files

0.27.0

2 release files

0.26.1

2 release files

0.26.0

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.0

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.18.0

2 release files

0.16.0

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page