Wednesday, June 23, 2010

[Py] Work with multiple versions of Python

In Ubuntu 8.04, the default version of Python is 2.5, and I want to try Python 2.6 without messing up Python 2.5. I followed Andreas Bernauer's article but still had problems.

During the installation process, I found another useful article which gives also clear guidance:
Installing multiple versions of Python on Ubuntu from Source

After installing Python 2.6 successfully, I linked python command to Python 2.6, but got some problems. All the third-part packages (installed in the `site-packages' folder) cannot be seen by Python 2.6. I tried to link the folders but got no luck. Then I noticed the ``setuptools'' which claims:
Download, build, install, upgrade, and uninstall Python packages -- easily!
Then followed the steps which also given in Installing multiple versions of Python on Ubuntu from Source. Finally, set link to easy_install, for example:
$ sudo ln -s /opt/python2.6/bin/easy_install-2.6 /usr/bin/easy_install2.6
---
I installed numpy and matplotlib with easy_install:
$ sudo easy_install2.6 numpy
$ sudo easy_install2.6 matplotlib
The installation of matplotlib got an error message as below:
error: Setup script exited with error: command 'gcc' failed with exit status 1
I followed the method proposed here, and installed ``libpq-dev'' but it didn't work. Then I found the solution which is as follows:
$ sudo apt-get build-dep matplotlib
So far, one thing is still bothering me. I have no idea how to let IPython work with Python 2.6.

Wednesday, June 16, 2010

[Py] Use lambda expression for callback functions of widgets

Let's see a quotation about Tkinter callbacks:
A common beginner’s mistake is to call the callback function when constructing the widget. That is, instead of giving just the function’s name (e.g. “callback”), the programmer adds parentheses and argument values to the function
That's true. I just solved one problem of this kind in my code.

In short, we cannot use callbacks of widgets in the form of
Widget(text="some text", command=callback(argv)).pack()

The reason has been stated clearly in the first link of this post. To call the callbacks which have arguments, we need to utilize the lambda expression.

I have tried with 3 test programs. They are listed as follows.

1. from Tkinter import *
2.
3. def cb_test(i):
4. print i
5.
6. root = Tk()
7.
8. for i in range(5):
9. Button(root, text=str(i), command=cb_test(i)).pack() # test 1
9. Button(root, text=str(i), command=lambda:cb_test(i)).pack() # test 2
9. Button(root, text=str(i), command=lambda x=i:cb_test(x)).pack() # test 3
10. Button(root, text="Quit", command=root.quit).pack()
11.
12. root.mainloop()

If you would like to try with my codes, please note there are 3 lines denoted as line 9. Keep only one of them and delete the other two.

[Py] Add new attributes as static variables

One problem I have met when coding with Python is that there seems no static variables to apply. A straightforward approach is to use the global variables, but it is not such a safe way.

Several days ago, when I was writing my nth version of my low-pass/high-pass filtering functions, I found a nice method to keep some values of certain variables which would be used in recursive steps. This method is to create new attributes of the called function, and the created attributes could be used as static variables.

The original information has been given in Ref. and I would like to repeat it again but with my own understanding. The function which have to keep some local variables as static ones could be as follows.

1. def foo(argv):
2. if not "your_static_var" in dir(foo):
3. foo.your_static_var = certain initial values
4. do something with foo.your_static_var
5. return foo.your_static_var

In line 2, we check all the attributes of foo() by the built-in function dir(). If foo() is called for the first time, we could create new attributes with initializations as shown in line 3. I think this is the most brilliant part of the method.

Next time when you need ``local'' static variables for certain functions, this approach may help.

---
Ref: (see the post by Cameron Laird)
Python - Static Variables in Python?

Sunday, June 13, 2010

[SW] Color toggle -- Firefox plugin to swap foreground and background color

Many of us use browsers very often, and maybe some of you just don't like the default white color of many web pages. I don't like either.

I am used to work and view documents in black background with white fonts color, just like the appearance of command line terminals. So I began to search the method which can help me in reversing my browser's foreground and background colors.
The answer for Firefox is Color toggle by Nathan Baker. Color toggle is a simple plugin which is very easy to use for swapping or toggling colors between two color profiles. Therefore with this plugin, you can toggle your foreground and background colors in very quick key pressing (the default is Ctrl+Shift+u).

The original looking:

After toggling:

Friday, June 11, 2010

[QnA] Command line rocks!! Combine several data files...

I have several data files. Each of them has only one column which presents acceleration along one axis. I want to combine them into one single file so that I can read them into my Python program with opening only one file.

To illustrate the situation, here are some sample contents of the files:

ACC_X.txt
126
127
129
127
137

ACC_Y.txt
132
106
109
114
105

ACC_Z.txt
137
139
138
138
144

What I want is to combine them in columns within a single files as:
ACC.txt
126,132,137
127,106,139
129,109,138
127,114,138
137,105,144

The first thing came into my head is using awk. However, I am not familiar with awk script. With brief searching, I found two easy ways in the command line: paste and pr.

The command using paste could be:
$ paste -d, ACC_X.txt ACC_Y.txt ACC_Z.txt > ACC.txt

Or you can use pr like this:
$ pr -mts, ACC_X.txt ACC_Y.txt ACC_Z.txt > ACC.txt

The comma in the commands means I am using it as the delimiter or separator.

Simple and fast. Command line really rocks!

Sunday, June 06, 2010

[Py] To show or update images of label

To show or update images in a label, there is one thing important: You have to keep a reference for the image objects or they will be cleared so you won't see them on your label widgets.

I totally had no idea about this fact and tried for several hours until I read the following note:
Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

It's also true if you want to show images in sequence and then want to keep the last image when the update stops. Without the ``keep reference'' line, you will see the images updated sequentially and disappear after the last image being showed.

Saturday, June 05, 2010

[Py] Update label's content

I am writing a simple program in Python with Tkinter, and got troubles when I wanted to update the text showed in the label. I have a variable which has been changed in certain function and I want to show its latest value on a label of the root window.

Before I find the solutions, I think all I need are Label.config() and time.sleep(). However, they didn't make the program run as what I expected.

Finally, I found the key is the update() function. There are two ways to do what I want, but I don't know the differences between them. Let me just show the test programs I've written.

[label_test1.py]
from Tkinter import *
import time

class App:
def __init__(self, master):

frame = Frame(master).pack()
master.geometry("200x100")

var_text = StringVar()
counter = Label(frame)
counter.config(textvariable=var_text, font=("arial",60,"bold"), bg="green")
counter.pack(expand=YES, fill=BOTH)

for i in range(10):
time.sleep(1)
var_text.set(i)
master.update()

def main():
root = Tk()
app = App(root)
root.mainloop()

if __name__ == "__main__":
main()


[label_test2.py]
from Tkinter import *
import time

class App:
def __init__(self, master):

frame = Frame(master).pack()
master.geometry("200x100")

counter = Label(frame)
counter.config(font=("arial",60,"bold"), bg="green")
counter.pack(expand=YES, fill=BOTH)

for i in range(10):
time.sleep(1)
counter.config(text=i)
master.update()

def main():
root = Tk()
app = App(root)
root.mainloop()

if __name__ == "__main__":
main()

---
Ref:

[Py] Countdown counter

Here is a countdown counter which counts down in HH:MM:SS format. The original example has given by vegaseat, which counts increasingly. I modified it to be a countdown version as the follows.


"""
A ``countdown'' counter using Tkinter
Original version has given by vegaseat 17aug2007
http://www.daniweb.com/code/snippet216971.html

This version is modified from the original one
by thk 2010/06/05
"""

import Tkinter as tk
from itertools import count

def start_counter_down(label):
counter = count(0)
begin_time = 10 # sec.
def update_func():
left_time = begin_time - counter.next()
show_hr = left_time/3600
show_min = (left_time%3600)/60
show_sec = (left_time%3660)%60
label.config(text=\
str(show_hr).zfill(2)+':'+\
str(show_min).zfill(2)+':'+\
str(show_sec).zfill(2))
label.after(1000, update_func) # 1000ms
if left_time <= 0: label.config(text="Time's up!") update_func() root = tk.Tk() root.title("Counting Down") label = tk.Label(root, fg="red") label.pack() start_counter_down(label) button = tk.Button(root, text='Stop & Quit', width=30, command=root.destroy) button.pack() root.mainloop()

Tuesday, June 01, 2010

[Py] Canvas example (correction)

Here are some GUI examples of Python with Tkinter. One of the example shows how to draw lines in the canvas. However, the source code has some errors. I have tested and corrected the errors as the following lines:

21c21
< x =" 250"> y = 250 - (i * 40)
28c28
<> scaled.append((100 + 3*x, 250 - (4*y)/5))
33c33
< width="1,"> canvas.create_oval(xs-6,ys-6,xs+6,ys+6, width=1,