Plotting pi...............................
Mihalis Tsoukalos plots pi in various languages, starting with Python, before displaying it as a coloured collection of random looking pixels…
Mihalis Tsoukalos plots pi in various languages, starting with Python, before displaying it as a coloured collection of random-looking pixels…
This month’s Python exploration is all about the plotting of the digits of pi as an image, in this case in PNG format. However, this isn’t as simple as it seems, because you’ll need to know how to read and write to files, as well as how to specify the colour of a pixel in an image.
To make things even more interesting, this tutorial will present full code examples in Python 3, Perl and Go. Additionally, you’ll see Julia and R code that enables you to read a text file character by character so that you can understand the differences between general-purpose languages and programming languages that were made with scientific computing in mind.
Pi is an irrational number, which means that its digits never end. Although there are many ways to calculate pi, this tutorial will enable you to display pi using a Python 3 module without the need to carry out any complex calculations. A forthcoming Linux Format article will talk about calculating pi on your own with the accuracy that you desire.
Saving Private pi
The most handy, general-purpose and straightforward solution is to save pi in a text file, which will be used each time you want to read the digits of pi. So, a small Python 3 script, called savePi.py, will do exactly this.
Bear in mind that the savePi.py script will utilise just one parameter, which will be the number of digits you want to obtain. It will print its output on the screen. Therefore, in order to save it, you’ll need to redirect the standard output to a text file.
As Python 3 comes with a whole range of scientific packages, it would be wise to use one of them in order to produce a manageable version of pi. In this case, the preferred package will be mpmath. Note that if mpmath isn’t already installed on your Linux system, you can install it as follows from the root account: # pip3 install mpmath
With mpmath installed, it’s easy to obtain pi – the Python 3 code of savePi.py is the next step: #!/usr/bin/env python3 import sys from mpmath import mp if len(sys.argv) == 1: print("Not enough arguments!") sys.exit(0) if sys.argv[1].isdigit():
accuracy = sys.argv[1] mp.dps = accuracy print(mp.pi)
The desired accuracy is set by defining the mp.dps property. Apart from that, you only have to print mp.pi. Executing savePi.py and saving its output is as easy as executing the following command: $ ./savePi.py 1000000 > pi1M.txt
All the implementations will need to read the generated text file character by character or, more accurately, digit by digit. The Perl, Python 3 and Go programs will require four command line arguments: the two dimensions of the output image, the name of the output image and the filename of the text file with the digits of pi. The R and Julia implementations won’t require any command line parameters for reasons of simplicity.
Figure 1 ( left) shows the output of savePi.py when calculating pi with a relatively small accuracy as well as the output of the time() command when savePi.py computes pi with 1,000,000 (1M) and 10,000,000 (10M) digits on a relatively slow machine. As you can see, the latter calculation took about 150 minutes...
Enough digits?
Well, the number of digits you’ll plot will directly affect the size of the plot. Generally speaking, there’s no point in plotting just 10 or even 100 digits of pi – you’ll need more in order to generate a good image/
So, for an image with 800x600 pixels, you’ll need 480,000 digits of pi—it’s clear that you shouldn’t underestimate the usefulness of the mpmath package. Finally, the Python 3 and Perl implementations will use an array with 10 elements, and each element will be a different colour that will be used during the plotting phase. If you want to change the colours in the output image, you’ll need to edit that array.
The main problem that each implementation should solve is defining an image with the desired dimensions and colouring each pixel of the image with the desired colour before saving the image on the disk. Each programming language has its own approach and needs its own packages to perform the task, and this is what makes the task of creating many implementations particularly interesting.
Each pixel has two coordinates, x and y. The value of the x coordinate is the quotient of the integer division between the number of the digits you’ve processed so far and the height of the image. In order to find the value of the y coordinate, you’ll need to find the remainder of the integer division between the number of the digits you’ve processed so far and the height of the image.
Using Python 3
The name of the file with the Python 3 implementation will be pPi.py. But first you’ll learn how to create PNG images in Python 3 using the PIL module. The following Python 3 code, saved as tenten.py, shows how to create your own 10x10 image using the colours you want in Python 3 in order to better understand how pPi.py will work: #!/usr/bin/env python3 from PIL import Image n = 10 m = 10 filename = “test.png” image = Image.new('RGB’, (n, m)) image.save(filename, “PNG") img = Image.open(filename) pix = img.load() print(img.size) print(pix[5,5]) for x in range(1,10): for y in range(1,10):
pix[x, y] = x*y*x img.save("test.png")
The pix[x, y] statement defines the coordinates of the pixel that interests you, whereas the value of x*y*x defines the colour of the pixel, which in this case is a random colour. Once you have the code of tenten.py, you’ll only need to solve two more problems to be able to finish the task. The first one is reading the digits of pi from a text file one by one, and the other one is assigning the appropriate colour to each pixel based on the current digit. The most important code of pPi.py is the one that reads the text file with the value of pi digit by digit: f = open(textPi, ‘r')