Setting up lineage in linux for OBIEE

We have Oracle Business Intelligence Enterprise Edition running on Linux. I was asked to install lineage, but while it is supported to run on Linux, it appears the install is only supported on Windows. Of course we are not licensed to run it on Windows and Oracle would not allow us to install and copy across – you need to be licensed.

However with the help of someone from Oracle I found that you can install it on linux using the following procedure.

Prepare the companion CD

Download the ODI companion CD from oracle edelivery, and unzip the whole thing as an oracle home. Go to misc/biee-lineage and unzip odiobilineage.zip

For version 11.1.1.7 we found we had to apply patch 17008493. Follow the instructions in the readme, but install OPatch in the home, and apply the patch using:

$ opatch apply -jre /path/to/jre

Merge the rpd file

The RPD needs to be merged with the lineage rpd. This is done by converting it to UDML and uploading. Create a temporary directory and copy in odi_repository_archive_11g.rpd from the ODI companion CD under misc/biee-lineage/artifacts/11g. Then run:

ORACLE_HOME=/path/to/middleware_home
. $ORACLE_HOME/instances/$inst/bifoundation/OracleBIApplication/coreapplication/setup/bi-init.sh
$ORACLE_HOME/Oracle_BI1/bifoundation/server/bin/nqudmlgen \
       -P Admin123 \
       -R ./odi_repository_archive_11g.rpd -O lineage.udml \
       -N -Q

Now copy in the RPD file and merge in the lineage UDML using:

 $ORACLE_HOME/Oracle_BI1/bifoundation/server/bin/nqudmlexec\
       -P Password \
       -I lineage.udml \
       -B original.rpd \
       -O updated.rpd

---------------lineage.udml---------------

      ---------------Complete Success!!---------------

Where Password is the password of the rpd file. Copy the RPD file to windows, and update the connection pool as per Oracles lineage documentation.

Find the ORACLE_ODI_REPOSITORY. Edit the connection pool to match the ODI Work repository.

  • Expand the ORACLE_ODI_REPOSITORY database in the OBIEE Physical Layer, double-click the Connection Pool node, and edit the Connection Pool to match your ODI work repository configuration:
    • Update the Data source name, Username and Password fields.
    • Click OK.
    • Right-click the Physical schema and rename it to match the schema of the ODI Work Repository.
    • Click OK to save your changes.
  • Expand the renamed schema and test this updated connection as follows:
    • Right-click one of the tables of this physical schema and updating the row count.
    • Right-click the same table again and select View data to view data with the updated row count.

This completes thework with the RPD file. It can now be uploaded back to the server.

Copy the resources

Now we need to copy the resources from the CD to the correct location on the server. Under the CD change to misc/biee-lineage/artifacts/images and copy the two images to $ORACLE_HOME/user_projects/domains/bifoundation_domain/servers/bi_server1/tmp/_WL_user/analytics_11.1.1/7dezjl/war/res

Web catalog

I did it manually. The manual process needs to be run on  the server because the client version had missing libraries that are required.

Make sure that X is working (Run xclock to check) and run:

cd $ORACLE_HOME/instances/$instance/bifoundation/OracleBIPresentationServicesComponent/coreapplication_obips1/catalogmanager
./runcat.sh

This brings up the catalogue manager. Select “Open Catalog” from the File menu. Select offline, then browse to the catalogue location which is:

$ORACLE_HOME/instances/$INSTANCE/bifoundation/OracleBIPresentationServicesComponent/coreapplication_obips1/catalog/SampleAppLite

You should see your developers directories under here. Using the online catalogue also works. Click OK.

Extract the web catalog using file->Unarchive and select

$ODI_COMPANION/misc/biee-lineage/artifacts/11g/odi_catalog_archive_11g.cat

Export the web catalog report using Tools->Create Report.

The report type should be analysis. Add the following fields to the report in the following order: “Owner”, “Folder”, “Name” ,”Subject Area” ,”Formula” ,”Table”, “Column”

Save the report

It should be possible to script this step as follows:

OBIEE_WEBCAT=SampleAppLite
WIN_EXP_RPD_DIR="D:\tmp"
OBIEE_WEBCAT_MGR=$OBIEE_INSTANCE_HOME/instances/instance1/bifoundation/OracleBIPresentationServicesComponent/coreapplication_obips1/catalogmanager
OBIEE_WEBCAT_BASE=$OBIEE_INSTANCE_HOME/instances/instance1/bifoundation/OracleBIPresentationServicesComponent/coreapplication_obips1/catalog

$OBIEE_WEBCAT_MGR/runcat.sh -cmd report \
 -offline $OBIEE_WEBCAT_BASE/$OBIEE_WEBCAT \
 -forceOutputFile $ODL_TMP_DIR/webcat_doc.txt \
 -distinct \
 -folder /shared \
 -type Analysis "Owner" "Folder" "Name" "Subject Area" "Formula" "Table" "Column"bb

Export the RPD report

Open the RPD file in the OBIEE administration tool. Select Tools->Utilities. Select Repository Documentation and click execute. Save the file.

Run lineage

Gather the webcat extract file, and the RPD report into a directory. Create a file to refresh lineage that looks like this:

#Properties for ODI/OBIEE Lineage
#Fri Dec 13 09:45:15 EST 2013
ODI_MASTER_USER=ODI_REPO_M
ODI_MASTER_PASS=firtr33s
ODI_MASTER_DRIVER=oracle.jdbc.OracleDriver
ODI_MASTER_URL=jdbc\:oracle\:thin\:@palin\:1532\:BIPROD
ODI_SUPERVISOR_USER=SUPERVISOR
ODI_SUPERVISOR_PASS=firtr33s
ODI_SECU_WORK_REP=WORKREPDEV
OBIEE_VERSION=11g
OBIEE_WEBCAT_EXPORT_FILE=/path/to/webcat.txt
OBIEE_RPD_EXPORT_FILE=/path/to/repo.txt
MAPPING_FILE=/path/to/MappingData.csv
INSTALL_ODI_LINEAGE=no
EXPORT_OBIEE_METADATA=no

Create the mapping data file. The layout for these is on the companion CD at:

misc/biee-lineage/samples/MappingData.csv

The format is:

ORACLE_SID,DB_USERID,,nnnn

Where:

ORACLE_SID is the oracle_sid of the database (Well the TNS connection)

DB_USERID is  the username within the database (Probably DEV_BIPLATFORM)

nnnn is the ODI Model ID. This can be derived by opening the ODI tool and connecting to the master and work repository. Select the designer tab on the left, and open the model. The model id is under version.

Now it should be possible to refresh lineage. The script needs to be run from the bin directory as it has relative paths. Also JAVA_HOME needs to be set.

JAVA_HOME=/usr/java
cd $odi_companion/misc/biee-lineage/bin
./refreshlineage.sh -propertyFile=$LINDIR/lineage.properties \
                    -mappingFile=$LINDIR/MappingData.csv

All being well, lineage will be refreshed and everything will work. Presumably the catalogue extract and rpd file extract will need to be updated periodically as they change.

Posted in OBIEE, oracle | Leave a comment

Health check of an Oracle system

I like to do a healthcheck of my Oracle system on a quarterly basis. This is because the report is hard to generate, and it is the longest timespan I thought I could get away with Monthly would be better, but until I can automate the reports generation this would take too much time.

The reason for the report is to keep management informed about what we are doing. To ensure the system is healthy and to ensure we are applying best practices in maintaining the system. It also serves as a mechanism to alert management (and myself) to potential problems.

Management will not have time to read the report, so it is important to have a summary at the top giving an overview of the most important things that have happened over the last quarter, tasks in progress, risks and any other things you want them to see.

The full healthcheck should contain the following:

Service improvements – An overview of work done since the last report.

Patch levels – Have the latest critical patches been applied to all tiers, and if not why not.

Software levels. Is all software in premier support, and if not why not. When does premier support end, and what plans are there to upgrade.

Hardware – For each hardware tier, is the hardware sufficient to cope with  the application. Break this down into CPU, I/O, disc space, Memory usage, and network usage. Graphs are good here to show trends during the day, week, month year and over time.

Performance – Ideally include some measure of user visible performance. Again graphs showing trends are useful here.

For the database attach an AWR report or similar showing top SQL for each metric. I also include the top hot objects and the SQL updating them. We found a number of tuning targets this way. Database I/O has caused problems for us in the past, so I graph redo generation. I create a graph of the growth of the top 10 application tables, system tables, lobs and indexes. Again over time this can point to trends and help ask the business whether the audit data from 8 years ago is really required. I point to documentation for non standard parameters and why they are set.

Also take the opportunity to compare against some of Oracles health check/recommended practices documents. There are likely to be several to choose from, for security, recommended performance configuration etc. Document any deviations from the document and the reason for it. Equally be wary of changing  the application to match Oracles recommendation without thorough testing, or understanding the reason for the changes.

I find the health check is a very valuable process for everyone concerned. The document is a little tedious to write, but automating its creation too much would reduce its effectiveness.

Posted in oracle, peoplesoft | Leave a comment

Upgrading tuxedo

Applying a patch to tuxedo I got:

 

"Must specify the correct TUXDIR"

 

I think the patch installed, but I like to have a success message. I ran the uninstall and investigated.

It happened because the tuxedo directory was copied from another server. Oracle has set up a mini registry which the upgrade tries to edit, and if it can not, this error appears. The following files need to be copied:

When tuxedo is installed, you create an ORACLE_HOME directory to contain this registry information. In my installation, this was the parent directory of the TUXDIR. It contains a registrry.xml file and a log directory. These should also be copied from the same install as the TUXDIR was copied from, then edit the registry.xml file to update the host name.

 

Then install the patch again:

$ ./install
DIR=/psoft/bea_patches/11g_90/RP090
rpreleasenote =  SUSE LINUX Enterprise Server 10 (x86_64) x86 for AMD64, 64bits Tuxedo
portreleasenotes= SUSE LINUX Enterprise Server 10 (x86_64) x86 for AMD64, 64bits Tuxedo
Installing server and client files...
Enter owner for patch files:
psoft
Enter group for patch files:
psoft

The patch installation finished successfully.

Hooray!

Posted in Uncategorized | Tagged , | Leave a comment

Raspberry Pi Python introduction part 3 – Sharing nicely

When I run the last program on my laptop, pretty soon the fan starts whirring and it gets hot. On the raspberry pi the program uses all the CPU it can get, the CPU graph goes completely green. Another problem is that it will run differently on different CPUs. On a fast CPU it will run faster and on a slow CPU it will run slower. This is not a real problem for this program, but if it was a game it would be really annoying to play at 10 times the proper speed.

We should share the CPU nicely with other programs, and keep the program running at the correct speed. Pygame gives us a way to do this, using the clock object. Lets write another program to demonstrate this, and we can add a little interaction as well.

Looking at the program we wrote last time, we can strip away the parts that are special for that program and end up with a skeleton which we can build on for future projects. It looks like this:

import pygame, random, sys

# You have to call this to make it work.
pygame.init()

# Set up some variables containing the screeen size
sizeX=600
sizeY=600

# Start drawing from the middle of the window.
x=sizeX/2
y=sizeY/2

# Set the starting colour
colour = pygame.Color('#444444')

# Create the pygame window
window = pygame.display.set_mode([sizeX,sizeY])


# Create the clock object
clock = pygame.time.Clock()


# Put a name on the window.
pygame.display.set_caption("Random art")

# This will loop forever.
while True:
    #-- Program loop goes here.

    # Wait for the next tick.
    clock.tick(40)

    pygame.display.flip()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

I have added in the clock stuff. Just two lines. The first creates the clock object, and the second one makes the program wait. It makes the loop run no more than 40 times a second, which is plenty. This means that we shouldn’t make the loop run for more than 1/40th of a second. This seems like a terriby short amount of time, but processors are really quick these days. Even the raspberry pi with its relatively slow CPU runs about 1,000,000,000 (One thousand million) instructions per second, which, if we divide that by 40 gives us 25,000,000 (twenty five million instructions) for each time the loop runs. Of course this is talking about a machine code instruction, a python instruction takes a lot of machine code instructions. Even so, we will not need this many!

This time I decided to make a spirograph. Wikipedia shows us the equations we need. Don’t worry, I have typed them in below. We need a counter, which we should initialise to zero at the start of the loop. We will also create random values for k and l, which should be between 0 and 1. These determine the shape of the spirograph pattern. We should pick a value for R which makes the spirograph fill the screen.

k=random.random()
l=random.random()
i=0
R=600

random.random() gives a random number between 0 and 1, which is exactly what we want.

The equations which need to go in the loop are taken from wikipedia:

    newx = R*( (1-k)*math.cos(t) + l*k*math.cos((1-k)*t/k) )
    newy = R*( (1-k)*math.sin(t) - l*k*math.sin((1-k)*t/k) )

Note that we are using the math module, so we need to add that to the import line at the start. When we look at the documentation for math, we see that math.sin and math.cos take an angle in radians. There are pi (3.14) radians in a circle, but 360 degrees. It would look better if we counted in degrees. The math module can convert degrees to radians for us. If we use i for the counter, we can create t as follows:

    t = math.radians(i)

This goes above the lines that calculate x and y above.

Then we need to draw the line, and set up x and y as before. We should set x and y to 0 at the start of the loop and not draw if they are both zero. This means the first time a line is drawn is on the second time through the loop, when we have two points to draw a line between. Otherwise we will get a line from the top left going to the start which will look ugly.

    if x==0 and y==0:
       pass
    else:
       pygame.draw.line(window,colour,(x,y),(newx,newy),2)
    x=newx
    y=newy

The double equals sign means check if it is equal to. The single equal sign means assign. These are two separate things and it is easy to get them confused. Fortunately python will not allow an assignment in an if statement, so it reminds you if you forget (Try it!)

And of course we must not forget to increment our counter.

   i=i+5

The more you increment i by, the faster the line will draw, but if you increment it by too much it will start to look jagged.

What the spirograph looks like now.If you managed to keep up, try running the program now. You will get a quarter of a spirograph like the picture on the right. This is because our window only shows values where x and y are both greater than zero.

To fix this is actually quite easy. First we should shrink the image so it can fit in the window. Change R from 600 to 300. Then in the draw line we just need to add 300 to each value like this:

       pygame.draw.line(window,colour,(x+R,y+R),(newx+R,newy+R),2)

This looks much better. A whole spirograph.The whole spirograph.

Next time it will be time to start adding some interaction into our program. It is more fun if you can make it do stuff!

That was quite complicated. In case you couldn’t follow everything above, here is the whole program.

Let me know if you think of a way to make my explanation clearer. Also there must be a way to make the lines eventually join up like a real spirograph. If you know what it is, leave a comment!

import pygame, random, sys, math

# You have to call this to make it work.
pygame.init()

# Set up some variables containing the screeen size
sizeX=600
sizeY=600

# Set the starting colour
colour = pygame.Color('#009900')

# Create the pygame window
window = pygame.display.set_mode([sizeX,sizeY])

# Create the clock object
clock = pygame.time.Clock()

# Put a name on the window.
pygame.display.set_caption("Spirograph")

# Initialise more variables
# k and l are numbers between 0 and 1.
# k is the ratio of the distance of the small circle from the big circle
l=random.random()

# l is the ratio of the small circles radius (to the hole with the pen in)
# to the distance from the centre of the large circle.
k=random.random()

# Counter - real number - not integer.
i=0.0

# Scaling factor (Radius of big circle)
R=300

x=0
y=0

# This will loop forever.
while True:
    t = math.radians(i)

    newx = R * ((1-k) * math.cos(t) + l*k*math.cos((1-k) * t / k ))
    newy = R * ((1-k) * math.sin(t) - l*k*math.sin((1-k) * t / k ))

    if (x==0 and y==0):
       pass
    else:
       pygame.draw.line(window,colour,(x+R,y+R),(newx+R,newy+R),2)
    x=newx
    y=newy

    i=i+5

    clock.tick(40)
    pygame.display.flip()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                sys.exit()
sys.exit()

Posted in Raspberry Pi | Leave a comment

Raspberry pi – The politics

I was wondering why has there not been a computer like the Raspberry Pi till now. The technology was there, so why didn’t someone put it together till now?

Companies exist to make money. They sell smart phones for £500. They do not sell computers for £30. How do you make money like that?

So it took some inspired public minded people to create the computer. But what about the software? You can’t install Microsoft Windows 7 on an ARM chip. Anyway, how much would Microsoft be able to charge for it? What they needed is an operating system that already worked on an ARM chip. Ideally one that was being given away for free. Fortunately there are some inspired public minded people called Debian who make a complete operating system, together with the programs you can run on it.

At the moment, the two have only just come together. This means there are some gaps where they join. Some work still need to be done to get them working well together. People will do this work and give it away. Over the next few months

Debian only exists because of other groups of public minded people wrote software and gave it away for free. In itself, that would not be useful, because programs that run on desktops will not work on ARM chips. You need the source code.

In the 1980s a man called Richard Stallman created an organisation called the Free Software Foundation. Their goal was to create a complete operating system, and give it away complete with the source. This was almost done. They even had a name for it – GNU, but they were having one problem. It was the kernel, the central part of the operating system which talks to the hardware. Amazingly another public minded individual had created something of a group around a kernel he was writing. He was Linus Torvalds, and the kernel was called Linux.

Computers were getting graphical interfaces around that time. Fortunately the Massachusetts Institute of Technology (MIT) was giving away its X windows system.

So we have the Raspberry Pi foundation providing the computer. Linus Torvalds and his group provided the kernel. The free software foundation provided the GNU operating system, MIT providing the windows system, thousands of other people writing programs, and Debian putting them all together.

We owe these people a debt of gratitude for what they have done for us, particularly Richard Stallman for his vision to write software, and give it away under the condition that anyone who receives it and passes it on, also passes on all the rights they got. Some people call it share and share alike.

I hope this inspires you to give something back. When you write programs, put them under a free software license. Consider the GNU Affero General Public License – but read it first, so you see what it means.

Posted in Uncategorized | Leave a comment

Its arrived – how to get started

Hooray! My raspberry pi arrived. I plugged it in, powered it up, and it didn’t work. It seems that the power supply was not powerful enough. So I got a more powerful one, and it worked.

Here is what I did. I downloaded the debian image from the raspberry pi downloads page, and wrote it to an SD card as suggested on the downloads page.

The first time I booted the system it did some configuration and seemed to hang. The messages said it was OK to reboot if it hung so I did. Then it booted to a text prompt.


Debian GNU/Linux 6.0 raspberrypi tty1

raspberrypi login:

I logged in following the instructions on the download page. It is a standard bash prompt which is really simple to use if you know the commands. Maybe that is a tutorial for another day. This time all I did was type:


startx

This brings up a user interface like computers used to have in 1999. This computer is probably about as powerful as a computer of that era though it uses much less electricity and can drive a 1080p monitor.

Screenshot of task bar.

The first thing that strikes you is the picture of the raspberry pi logo on the background. Apart from that you can see a line along the bottom of the screen which is the menu, task bar and system tray.

From the right to the left we have:

1. The off button You can log out to get back to the text prompt, or shut down or reboot the computer.

2. The screen lock button which can be used to lock the screen and keyboard.

3. The clock

4. The CPU monitor which is the green graph. This will spend a lot of time at 100%, but thanks to the power of the Linux kernel the raspberry pi will still feel responsive.

5. Further left filling the main area is a space for icons of running applications.

6. Next is the virtual desktop switcher. This is a really nice feature which lets you have one group of programs running on one virtual desktop and another group on another. You can switch between them at a click. I tend to have a web browser on one and four terminals on the other which I use for development. You can arrange them however you like.

7. Next is the show desktop button, which minimises all the open windows.

8. The next two icons are launchers for frequently used applications. This is the midori web browser.

9. This is the launcher for the file manager.

10. At the far left is the menu itself.

This can be modified as you wish. Right click on the bar for a menu.

I expected to see the python development environment idle in the menu of applications, but it was not there. Instead SPE is installed which looks similar and I assume has more features. Other programming environments are scratch which looks good for getting kids started in programming and squeak which I was not able to get started. Leaf pad is a lightweight editor if you prefer that to using an integrated development environment.

To update the system open a terminal window, and type:


sudo aptitude

This brings up a program which can be used to manage software. Type u to update the package list. You will see it download some files, then it will read the package lists and go back to the main screen. Then type U (Upper case this time) to mark the packages that can be upgraded. Lastly type g to actually upgrade.

So looking around the system, not many programs are installed. The brilliant thing about debian is that they have packaged a massive amount of software which is really easy to install. You can use aptiutude to search – use CTRL+T to bring up the menu. You can search for packages, mark them for install and install them. If you want a graphical program to administer it, I recommend using synaptic. To install it, open a terminal and type:

sudo aptitude install synaptic

After some messages scroll past the screen and it checks if you really want to install the software, it is installed. Then you can find the program in the menu, run it and look through all the software that can be installed.

Alternatively you can use the command line. It is easier than using the GUI really. The aptutude manual is on the debian wiki. So to upgrade, you do:


sudo aptitude update
sudp aptitude safe-upgrade

To search for a program you can use


apt-cache search minesweeper

And to install a program you can use


sudo aptitude install xdemineur

The program will tell you if it is installing any other dependencies (Libraries and programs) and if so will ask for confirmation. It will say how much space is expected to be used, and how much data will be downloaded. Who needs a graphical interface!

Next time I will post a few thoughts on the Raspberry Pi, and then I will go back to the introduction to python.

Posted in Raspberry Pi | Leave a comment

Raspberry Pi Python introduction part 2

So, the last tutorial was very nice, but not very pretty. How do we get some graphics?

Here is a really simple python graphical demo. I hope you get some enjoyment from typing it in, making it run, and changing it to make it better. The idea is to get a line wandering around the screen, changing colour. I think it actually looks rather nice!

Screenshot of random art produced

So, first of all we need to tell python which modules we are going to use. If you don’t know, a module is a collection of program fragments which have already been written. We use these building blocks to make our lives much simpler. If you are writing a program, rather than writing your own physics simulator, statistics package, music player or whatever, you should check and see if anyone has written a module rather than reinvent the wheel.

In this program we will need pygame for the graphics, sys for the operating system code to exit the program, and random to get random numbers.

When you start pygame, you have to run pygame.init() to make it work properly, so I do that here.


import pygame, random, sys
pygame.init()

Next create some variables to store the size of the window the program will create. I have picked a 600 pixel square window. I do it this way so that if you have a different size screen you can easily change the program to cope with the new size. I use these variables to set two new variables, x and y, for the starting point of the line. I put it in the middle of the window.


sizeX=600
sizeY=600

x=sizeX/2
y=sizeY/2

Here is the first time we use pygame. We create a colour. In pygame a colour is an object. An object is like a supercharged variable. It actually contains a number of variables, and methods, which is code you can call to control the object. We will be doing this later, but all we are doing now is calling the constructor which creates the object and puts it in the colour variable.

The colour does not really matter, it just needs to be set to something to start. I picked gray. You could pick any of the allowed colours which are listed in the x11 colour names article at wikipedia.


colour = pygame.Colour('Gray')

[Edit - This does not work in debian - I get:


Traceback (most recent call last):
File "", line 1, in
ValueError: invalid color name

It looks like you can't use colour names. Instead, use:


colour = pygame.Colour(#444444')

I will also update the program below.

Edit end]

Next we use pygame to create the window the size we decided earlier. The window is another object. We need to assign it to a variable so we can draw on it later. Next we set the title on top of the window.


window = pygame.display.set_mode([sizeX,sizeY])
pygame.display.set_caption("Random art")

Now we have everything ready. We have a colour, a starting point and a window to draw in. Now we can start drawing. We do this in a loop, we want to keep running the same instructions over and over again. We use a while loop, which keeps on executing while the expression is true. Since True is always true, the loop will keep going forever unless we make another way to stop it.


while True:

Now, everything in the loop needs to be indented, and by the same amount, so that python knows to keep it in the loop. If you forget to indent a line python will think it is outside the loop, so it will run once the loop has finished (Which is never in this case). I have chosen to indent by four spaces. I never use tabs, because 8 spaces looks the same as 1 tab, but it is different to python, so it can get confusing.

The first thing to do in the loop is to pick a colour. The nice thing about the colour object is that there are several ways of manipulating it. I like thinking about a colour as a mixture of the three primary colours of light – red, green and blue. I want to choose a colour that looks similar to the last one. So I add or subtract a number between 0-3. I use randint from the random module which we imported earlier to choose a number between -3 and 3, and add it to the previous brightness. The problem is that the brightness can only be between 0 and 255. We can keep it below 255 by dividing the number by 255 and taking the remainder. This is what the %255 bit does. I do this three times, once for each of the primary colours.

    colour.r = (colour.r+random.randint(-3,3)) % 255
    colour.g = (colour.g+random.randint(-3,3)) % 255
    colour.b = (colour.b+random.randint(-3,3)) % 255

Next, pick a new point to draw to. We can do the same thing here as we did with the colours, just add a random number to the point. the new point would not appear on the window, I will just move it to the closest point on the window, otherwise the line might go wandering off past the edge of the window and we would never see it again.

    newx=x+random.randint(-3,3)
    newy=y+random.randint(-3,3)

    if newx > sizeX:
       newx = sizeX
    if newy > sizeY:
       newy = sizeY
    if newx < 0:
       newx = 0
    if newy < 0:
       newy = 0

If I used the same trick as I did with the colours, we would get a line across the screen where it goes from the window size to zero. Why don’t you try it? In that case we could remember this had happened and not draw the line on that occasion. but that is for you to try. What I need to do next is actually draw the line. We use pygame for that.

    pygame.draw.line(window,colour,(x,y),(newx,newy),2)
    pygame.display.flip()

In the first line we draw a line on to our window, using the colour we picked earlier, starting from point (x,y) and ending at point (newx,newy) and we make the line 2 pixels thick. You can experiment with the line thickness. You can read the documentation for pygame.draw on the pygame site. What is the display.flip? The thing is that we didn’t really draw the line on the screen. We drew it in memory and flipping the display copies the contents of the memory to the screen. This will be useful for more complex programs because it means we can make sure we have drawn exactly what we want before putting it on the screen. Also, writing to the screen is a complicated business. The computer has to do the work at the right instant to make sure it is not drawing during a refresh, so only half the picture gets on the screen. Again the pygame site tells you all about the display object.

The next time the loop is run, I want the line to carry on from the end of the line that was just drawn. To do that we have to tell the computer to do that, and I do it like this:

    x=newx
    y=newy

That is everything! If you run the program it will work now! There are a number of problems with it though. The main one is that we have not provided a way to quit the program. Remember the loop will run for ever unless we arrange another way to break out of it, and we have not. Lets add one now.

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

So, what this does is tells pygame to look at the events it has received. We will talk more about events in a later tutorial, but an event is basically anything that happens on the computer, like the mouse moving, a button clicking or keys being pressed on the keyboard. We only look at events we are interested in. This event is pygame.QUIT, which means the operating system is telling us that it wants the program to quit. This happens if the user clicks the X on the top corner of the window. So, if the user clicks X, we want to exit. This is where we use exit which is provided by the sys module, which we imported at the top.

Next time we will do another similar program, but address some of the problems in this program, and add a few more features such as some simple user interaction.

Please use the comments box below if you spot any mistakes in the tutorial. If you are using this to learn python, then please let me know how you are getting on, and whether it was helpful.

Last of all, here is the full program:

import pygame, random, sys

# You have to call this to make it work.
pygame.init()

# Set up some variables containing the screeen size
sizeX=600
sizeY=600


# Start drawing from the middle of the window.
x=sizeX/2
y=sizeY/2

# Set the starting colour
colour = pygame.Color('#444444')

# Create the pygame window
window = pygame.display.set_mode([sizeX,sizeY])

# Put a name on the window.
pygame.display.set_caption("Random art")

# This will loop forever.
while True:
    colour.r = (colour.r+random.randint(-3,3)) % 255
    colour.g = (colour.g+random.randint(-3,3)) % 255
    colour.b = (colour.b+random.randint(-3,3)) % 255

    newx=x+random.randint(-3,3)
    newy=y+random.randint(-3,3)

   # Make sure the new point is visible
    if newx > sizeX:
       newx = sizeX
    if newy > sizeY:
       newy = sizeY
    if newx < 0:
       newx = 0
    if newy < 0:
       newy = 0

    pygame.draw.line(window,colour,(x,y),(newx,newy),2)
    x=newx
    y=newy
    pygame.display.flip()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

Posted in Raspberry Pi | Leave a comment