generativepy.graph module
Categories: generativepy generative art
The graph module provides the ability to draw graphs of mathematical functions. It can also be used in conjunction with the movie and tween modules to create animated graphs that can be converted to gifs or videos.
To draw a graph you must first create an Axes
object that defines size, location, and scale of the graph axes. You can then create one or more Plot
objects to draw the plots on the axes.
Graph scaling
Graph are drawn in the current user space. The size and location of the axes are defined in current user parameters.
The text and gridlines of the axes are designed for graphs that are a few hundred units wide. If you use graphs that are significantly larger or smaller than that, you might find that the axes text looks too big or small, and the grid lines might look too thick or thin. There are two ways of fixing this:
- Use the axes
with_feature_scale
method. This scales all sizes and thicknesses up or down. So for example if your graph is 1000 units wide, you might want to apply a scale of around 2.0 to make the feature sizes proportionate to the graph size. - Alternatively, you can adjust all the features individually.
The second method allows you a great deal of control of the graph appearance. You can set the colours and styles of all the axis lines and text, and the background colour of the graph.
When you plot a curve:
- The curve line thickness, dash patterns etc are specified in user units.
- The curve points are mapped to the axis units (as you would expect, so that the curve appears in the right place on the graph).
Example
Here is an example graph drawn using the Axes
object, and adding 3 curves:
The code for this can be found on github as simplegraph.py:
from generativepy import graph
from generativepy.drawing import make_image, setup
from generativepy.color import Color
from generativepy.graph import Axes
'''
Create a simple graph
'''
def draw(ctx, width, height, frame_no, frame_count):
setup(ctx, width, height, background=Color(1))
# Creates a set of axes.
# Use the default size of 10 units, but offset the start toplace the origin inthe centre
axes = Axes(ctx, (50, 50), 500, 500).of_start((-5, -5))
axes.draw()
# Add various curves
axes.clip()
Plot(axes).of_function(lambda x: x * x).stroke(pattern=Color('red'))
Plot(axes).of_xy_function(lambda x: 1.5 ** x).stroke(pattern=Color('green'))
Plot(axes).of_polar_function(lambda x: 2 * x).stroke(pattern=Color('blue'))
axes.unclip()
make_image("/tmp/simplegraph.png", draw, 500, 500)
Notice that we surround the Plot
calls with axes.clip()
and axes.unclip()
to ensure that the curve is clipped to the area covered by the axes.
Axes
The Axes
class draws graph axes, including the main axes, divisions, subdivisions, origin marker and division values. You simply need to create an Axes
object then call draw
to draw the axes.
Axes constructor
Creates an Axes
object.
Axes(ctx, position, width, height)
Parameter | Type | Description |
---|---|---|
ctx | Context | The Pycairo Context to draw to |
position | (number, number) | A tuple of two numbers, giving the (x, y) position of the top left corner. |
width | number | The width. |
height | number | The height. |
Creates a set of axes for drawing a graph.
The position
gives the position of the top left of the axes in user coordinates. width
and height
give the size of the axes area, again in user coordinates.
of_start
Sets the start of the axes values.
of_start(start)
Parameter | Type | Description |
---|---|---|
start | 2-tuple | The (x, y) value of the bottom left corner of the graph in graph coordinates. |
Gives the start of the axes range. This represents the (x, y) value of the bottom left corner of the axes, in the coordinated of the graph itself.
If you wanted the graph to show x values in the range -1 to +5, and y values in the range -3 to +4, you would set a start
of (-1, -3).
of_extent
Sets the extent of the axes values.
of_extent(extent)
Parameter | Type | Description |
---|---|---|
extent | 2-tuple | The (x, y) of the axes in graph space. |
Gives the width and height of the axes range.
If you wanted the graph to show x values in the range -1 to +5, and y values in the range -3 to +3, you would set a extent
of (6, 7). That is because the x axis has a range of 6 (from -1 to +5), and the y axis has a range of 7 (from -3 to +4).
with_feature_scale
Scales the graph features.
with_feature_scale(scale)
Parameter | Type | Description |
---|---|---|
scale | number | The scale factor. |
Scales all the graph features by scale
. This affects all the visible elements of the axes:
- The axis, division and sub-division line thicknesses will be scaled.
- The axis text will be scaled.
- The size of the axis ticks and origin marker.
For example, a scale of 2 will make these features twice as big, 0.5 will make them half as big.
The scale factor is applied on top of any changes made by the axes styling functions below. For example if you set the axis line width to 3, and apply a scale factor of 2, the axis line width will be drawn as 6 units.
with_divisions
Sets the division spacing.
with_divisions(divisions)
Parameter | Type | Description |
---|---|---|
divisions | 2-tuple | The (x, y) division sizes. |
Sets the division spacing in the x and y directions. For example, (1, 5) will create an x division for every one unit in the axes space, and a y divison for every 5 units.
If this function isn't called, the divisions are set to (1, 1).
with_subdivisions
Sets the sub-division spacing.
with_subdivisions(divisions)
Parameter | Type | Description |
---|---|---|
factor | 2-tuple | The (x, y) sub-division factor. |
Calling this method enables sub-divisions and sets the sub-division factor.
A factor
of (5, 2) means that there will be 5 subdivisions per division on the x-axis, and y subdivisions per division on the y-axis.
If you do not call this function, no subdivisions will be shown.
background
Sets the background fill.
background(pattern)
Parameter | Type | Description |
---|---|---|
pattern | Color or Pattern | The graph background pattern/colour. |
Sets the colour or pattern of the entire graph background. See the pattern
parameter of the fill
method of Shape.
text_color
Sets the text fill.
text_color(pattern)
Parameter | Type | Description |
---|---|---|
pattern | Color or Pattern | The graph text pattern/colour. |
Sets the colour or pattern of the axis text. See the pattern
parameter of the fill
method of Shape.
If this function is not called, the text will be a dark grey colour.
text_style
Sets the text font and size for the axes text.
text_style(font="arial", weight=FONT_WEIGHT_BOLD, slant=FONT_SLANT_NORMAL, size=15)
Parameter | Type | Description |
---|---|---|
font | string | Name of the font to use. |
weight | enum | Font weight, default to normal. |
slant | enum | Font slant, defalts to normal. |
size | number | The size of the text. |
font
is the name of the font, such as 'arial'.
weight
is the font weight, either drawing.FONT_WEIGHT_NORMAL
or drawing.FONT_WEIGHT_BOLD
.
slant
is the font slant, either drawing.FONT_SLANT_NORMAL
, drawing.FONT_SLANT_ITALIC
, or drawing.FONT_SLANT_OBLIQUE
.
sizes
sets the font size. This is approximately equal to the height of the font in user units. See the size
method for Text objects.
If this method is not called, the font defaults to 'arial', bold, size 15.
axis_linestyle
Sets the line style of the graph axes.
axis_linestyle(pattern=Color(0), line_width=None, dash=None, cap=None, join=None, miter_limit=None)
Parameter | Type | Description |
---|---|---|
pattern | Color or Pattern | The stroke pattern/colour. |
line_width | number | The line width. |
dash | array of numbers | The dash style. |
cap | enum | The type of line cap. |
join | enum | The type of line join. |
miter_limit | number | The mitre limit. |
Sets the style of the main axis lines. See the stroke
method of Shape.
If this function is not called, the line will be dark grey with a width of 2.
division_linestyle
Sets the line style of the graph axes.
division_linestyle(pattern=Color(0), line_width=None, dash=None, cap=None, join=None, miter_limit=None)
Parameter | Type | Description |
---|---|---|
pattern | Color or Pattern | The stroke pattern/colour. |
line_width | number | The line width. |
dash | array of numbers | The dash style. |
cap | enum | The type of line cap. |
join | enum | The type of line join. |
miter_limit | number | The mitre limit. |
Sets the style of the division lines. See the stroke
method of Shape.
If this function is not called, the line will be light blue with a width of 2.
with_division_formatters
with_division_formatters(x_div_formatter=None, y_div_formatter=None)
Parameter | Type | Description |
---|---|---|
x_div_formatter | Function | Formatter function |
y_div_formatter | Function | Formatter function |
Override the text formatting for division labels and the x and y axes. For example:
- Instead of 1, 2, 3... you can override the labels to display π, 2π, 3π...
- Instead of -2, -1, 1, 2... you can override the labels to display [blank] -a, a, [blank]...
- Instead of 90, 180, 360... you can override the labels to display 90°, 180°, 270°...
The formatter function must have the signature:
formatter(value, div)
Here value
is the value of the division, and div
is the spacing between divisions. The function should return a string that will be displayed for that division. It can also be an empty string to display nothing for that division, which allows selected divisions to be unlabelled.
subdivision_linestyle
Sets the line style of the graph axes.
subdivision_linestyle(pattern=Color(0), line_width=None, dash=None, cap=None, join=None, miter_limit=None)
Parameter | Type | Description |
---|---|---|
pattern | Color or Pattern | The stroke pattern/colour. |
line_width | number | The line width. |
dash | array of numbers | The dash style. |
cap | enum | The type of line cap. |
join | enum | The type of line join. |
miter_limit | number | The mitre limit. |
Sets the style of the subdivision lines. See the stroke
method of Shape.
If this function is not called, the line will be very light blue with a width of 2.
transform_from_graph
transform_from_graph(point)
Parameter | Type | Description |
---|---|---|
point | (number, number) | Point in graph coordinates. |
Converts a point in graph coordinates to a point in user space coordinates. This is useful for placing text lables or other features relative to graph features.
Returns (x, y) coordinates in user space.
draw
Draws the axes using the Context supplied in the Axes
constructor.
draw()
clip
Establishes a clipping path that covers the area of the axes. Anything drawn while the clip path is active will be clipped to the axes area.
clip()
unclip
Removes a clipping path previously set up by clip()
.
unclip()
Plot
The Plot
class can draw various types of curve:
of_function
for plotting functions of the form y = f(x).of_xy_function
for plotting inverse functions of the form x = f(y).of_polar_function
for plotting polar functions of the form r = f(a).
A Plot
is a Shape
object.
To draw a plot:
- Create a
Plot
object. - Call
of_function
or one of the other plotting method to define the curve. - Call the
stroke
function to draw the curve.
In most cases you will probably wish to clip the plot to the area covered by the axes. This is not done automatically, but it can be achieved by calling axes.clip()
before using the Plot
object, then calling axes.unlcip()
after. See the example code above.
Plot constructor
Creates a Plot
object.
Plot(axes)
Parameter | Type | Description |
---|---|---|
axes | Axes | The Axes object the plot will be drawn against. |
of_function
Plots a function of the form y = f(x)
of_function(fn, extent=None, precision=100)
Parameter | Type | Description |
---|---|---|
fn | function | A Python function that takes a single number parameter and returns a number. |
extent | 2-tuple | The range of x values. |
precision | int | The number of points to plot. |
If the extent
is not supplied, the graph will be plotted for values of x that cover the full range of the axes
. The extent
can be used to limit the range to less than the full extent of the axes.
The precision determines how many points are used to draw the graph. If the number is set too low, the graph won't look smooth.
of_xy_function
Plots a function of the form x = f(y)
of_xy_function(fn, extent=None, precision=100)
Parameter | Type | Description |
---|---|---|
fn | function | A Python function that takes a single number parameter and returns a number. |
extent | 2-tuple | The range of y values. |
precision | int | The number of points to plot. |
If the extent
is not supplied, the graph will be plotted for values of y that cover the full range of the axes
. The extent
can be used to limit the range to less than the full extent of the axes.
The precision determines how many points are used to draw the graph. If the number is set too low, the graph won't look smooth.
of_polar_function
Plots a function of the form r = f(theta)
of_polar_function(fn, extent=None, precision=100)
Parameter | Type | Description |
---|---|---|
fn | function | A Python function that takes a single number parameter and returns a number. |
extent | 2-tuple | The range of theta values. |
precision | int | The number of points to plot. |
If the extent
is not supplied, the graph will be plotted for values of theta from 0 to 2*pi
. The extent
can be used to alter that range.
The precision determines how many points are used to draw the graph. If the number is set too low, the graph won't look smooth.
stroke
The stroke
method of Plot
has the same parameters as the stroke
method of Shape. It will draw the shape defined by the supplied function.
The default line_width
of the stroke for Plot
is 2 (rather than 1 that is the default for most shapes).
See also
- generativepy.analytics module
- generativepy.bitmap module
- generativepy.color module
- generativepy.drawing module
- generativepy.drawing3d module
- generativepy.formulas module
- generativepy.geometry module
- generativepy.geometry3d module
- generativepy.gif module
- generativepy.math module
- generativepy.movie module
- generativepy.nparray module
- generativepy.shape2d module
- generativepy.table module
- generativepy.tween module
- generativepy.utils module
Join the PythonInformer Newsletter
Sign up using this form to receive an email when new content is added:
Popular tags
2d arrays abstract data type alignment and angle animation arc array arrays bar chart bar style behavioural pattern bezier curve built-in function callable object chain circle classes clipping close closure cmyk colour combinations comparison operator comprehension context context manager conversion count creational pattern data science data types decorator design pattern device space dictionary drawing duck typing efficiency ellipse else encryption enumerate fill filter font font style for loop formula function function composition function plot functools game development generativepy tutorial generator geometry gif global variable gradient greyscale higher order function hsl html image image processing imagesurface immutable object in operator index inner function input installing iter iterable iterator itertools join l system lambda function latex len lerp line line plot line style linear gradient linspace list list comprehension logical operator lru_cache magic method mandelbrot mandelbrot set map marker style matplotlib monad mutability named parameter numeric python numpy object open operator optimisation optional parameter or pandas partial application path pattern permutations pie chart pil pillow polygon pong positional parameter print product programming paradigms programming techniques pure function python standard library radial gradient range recipes rectangle recursion reduce regular polygon repeat rgb rotation roundrect scaling scatter plot scipy sector segment sequence setup shape singleton slice slicing sound spirograph sprite square str stream string stroke structural pattern subpath symmetric encryption template tex text text metrics tinkerbell fractal transform translation transparency triangle truthy value tuple turtle unpacking user space vectorisation webserver website while loop zip zip_longest