Laboratory‎ > ‎

Python

CS 495-20 Script languages taken in Spring 2006 at Northwestern University. Inclusive scripts mostly involves Python. Source codes can be also downloaded from the links at the bottom of the page.



Statistics sampling 

This python code(netdisease.py) requires matplotlib 0.98, and numpy(svn co http://svn.scipy.org/svn/numpy/trunk numpy)

#!/usr/bin/env python
"""
Simulating Spread of Disease in Networks

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-04-10 (Mon, 10 Apr 2006) $"
__revision__ = "Homework 1"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#
#	 Note: Higher numbered nodes are more likely to die after their first cycle as infected,
#			while more likely to recover from infected state.

from networkx import *
import random

def netdisease(n,k,s,p,i):
	
	Infected=[]
	Dead=[]
	G=Graph()
	d=0.2			# sustain rate for infected
	r=0.05			# recovery rate for infected, the remainder survives without recovery
	for m in range(n):
		G.add_node(int(m))
		if ((m%100) == 0):
			Infected.append(int(m))
		for l in range(k):
			t=m+int(l*n*s/k)				# rewire proability calculated
			if t>n:
				t = t-n
			G.add_edge( (int(m),int(t)) )
	for j in range(i):
		for c in range(len(Infected)):
			if c < r*len(Infected):
				Infected.pop()
		Dead.extend(Infected)
		for c in range(len(Infected)):
			Infected.pop()
		for a in range(n):
			if a in Dead:
				B=G.degree(a)
				for b in range(B):
					newinfect = G[a][b]
					if b < p*B:
						if newinfect not in Infected:
							if newinfect not in Dead:
								Infected.append(int(newinfect))
		for c in range(len(Dead)):
			if c > d*len(Dead):				# clear dead list according to the death rate
				G.delete_node(Dead[len(Dead)-1])
				Dead.pop()

	S= G.number_of_nodes() * 100 / n
	print '--------------------------------------------------'
	print 'Disease spread Simulation by Seunghoon Kim(ski819)'
	print 'Percentage of Survivors = ', S,'%'
	print 'Recovery and sustain rate can be configured by' 
	print 'manually changing the value in netdisease.py'
	print '--------------------------------------------------'
	
	return G.number_of_nodes()

Image processing 

This python code(montager.pycreates mosaic of input images as part of montage process. (Requires ImageMagick)
#!/usr/bin/env python
"""
Processing Images

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-04-17 (Mon, 17 Apr 2006) $"
__revision__ = "Homework 2"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#
#	 Usage: ./montage.py (dirname) (number of pictures to montage)
#

import os, sys, re, string

if __name__ == '__main__':
	dirname, numpics = sys.argv[1], int(sys.argv[2])
	lspath = ["ls -R"] + [dirname] + ["> list"]
	os.system(string.join(lspath))
	list = open("list", 'r')
	ls = list.read()
	fnames = ls.split()
#	print fnames
	
	print dirname
#	os.chdir(dirname)
#	print os.system("pwd")

	montageset = []
	addpath = []
	addpath.append(dirname)
	addpath.append("/")
	print addpath

	picsatt = 0
	picindex = 0
	while picsatt < numpics:
		completepath = [fnames[picindex]]
		completepath = addpath + completepath
		temppath = string.join(completepath,'')
		completepath = ["identify"] + [temppath] + ["> id"]
		#completepath = string.join(addpath, fnames[i])
		#print completepath
		ident = 1									# for testing purpose
		ident = os.system(string.join(completepath))  # returns jpeg,png,gif
		#print "ident returns", ident
		iden = open("id", 'r')
		ide = iden.read()
		id = ide.split()
		if len(id):
			#print id
			if id[1] in ['JPEG','PNG','GIF']:
				montageset.append(temppath)
				picsatt += 1
				print "Collecting picture #", picsatt, "out of", numpics
		picindex += 1
	
	montageadd = ["montage"] + montageset + ["montage.png"]
	#print montageset
	#print montageadd
	montagecmd = string.join(montageadd)
	print "creating montage.png.......please wait"
	os.system(montagecmd)
	print "Done!!!"

Regular expression 

Regular expressions are a powerful and standardized way of searching, replacing, and parsing text with complex patterns of characters.
  • dupwords.py - finds duplicate words in the input string
#!/usr/bin/env python
"""
Regular Expression I

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-04-17 (Mon, 17 Apr 2006) $"
__revision__ = "Homework 2"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#

import sys
import re
import glob

for pat in sys.argv[1:]:
	for file in glob.glob(pat):
		for para in open(file).read().split('\n\n'):
			dups = re.findall(r'(?m)(^.*(\b\w+\b)\s*\b\2\b.*$)', para)
			if dups:
				for dup in dups:
					print 'Duplicate word "%s" found in sequence: ' % dup[1], dup[0]						  

  • urlizer.py - finds URL format in the string, and inserts HTML codes in the respective places
#!/usr/bin/env python
"""
Regular Expression II

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-04-17 (Mon, 17 Apr 2006) $"
__revision__ = "Homework 2"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#


import re, fileinput

pattern = re.compile(r'''(?x)( # verbose identify URLs within text
	(http|ftp|gopher|mailto|telnet|file|wais) # make sure we find a resource type
	:* # ...needs to be followed by colon-slash-slash
	[^ \n\r]+ # some stuff then space, newline, tab is URL
	(\w+\.?){2,} # at least two domain groups, e.g. (gnosis.)(cx)
	(?=[\s\.,]) # assert: followed by whitespace/period/comma
	) # end of match group
	''')

#for line in fileinput.input():
if __name__ == '__main__':
	for line in fileinput.input():
		print re.compile(pattern, re.M).sub("<a href=\"\g<0>\">\g<0></a>", line.rstrip())

Extending Python 

makefile 
#
#  Simple Makefile
#  For compiling C extension modules for 
#  python.
#

###################################################
#
# Basic Swig Procedure :~)
# 
# // First make the wrapper from the interface file
# swig -python utility.i
# // Then compile both the utility_wrap.c and the utility.c code.
# gcc -c utility.c utility_wrap.c -I/usr/include/python2.2
# // Then link :~)
# ld -shared utility.o utility_wrap.o -o _utility.so
#
##################################################

includes = -I/usr/include/python2.4 -I/usr/lib/python2.4
interface = *.i
source = *.c
objects = *.o
library = _example.so
junk = *.so *.o *_wrap.c *_wrap.doc
linkopts = -shared -o
ccopts = -c


${library} : ${objects} #pointer
	ld ${linkopts} ${library} ${objects}

${objects} : interface ${source} 
	gcc ${ccopts} ${source} ${includes}

interface : ${interface}
	swig -python ${interface}

clean :
	-rm ${junk}

setup.py
#!/usr/bin/env python
"""
Extension Setup File

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-04-17 (Mon, 17 Apr 2006) $"
__revision__ = "Homework 3"
#    A Script written by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#

from distutils.core import setup, Extension

module = Extension('rankorder', sources = ['rankorder.c'])

setup (name = 'rank_order',
	   version = '1.0',
	   description = 'CS495-20 MP3',
	   ext_modules = [module])
rankbag.py
#	Return a dictionary where
#	key = rank, ranked by number of occurrences
#	val = number of numbers at that rank
#	There may be more elegant ways to do this but
#	this is the most straightforward I could come up with.

import types

class RankBag(list):
	def __init__(self, list):
		self = list
		print self
	
	def rank(self):
		# Calculate the number of occurrences of a given number
		occurrences = {}
		for i in range(len(self)):
			occurrences[(self[i])] = occurrences.setdefault((self[i]), 0 ) + 1
		# Construct a decreasingly sorted sequence of
		# cnt, num pairs, first pair has rank 1
		self = [(cnt, num) for num, cnt in occurrences.items()]
		print self
		self.sort()
		print self
		self.reverse()
		print self
		return self
	
#	rank_counts = {}
#	current_rank = 1
#	current_cnt = pairs[0][0]
#	print current_cnt
	
	# Build the final dictionary, looking for transitions in
	# the counts for a number
#	for cnt, num in pairs:
#		print cnt, current_cnt
#		if cnt <> current_cnt:
#			current_rank = current_rank + 1
#			current_cnt = cnt
#		rank_counts[current_rank] = rank_counts.setdefault(current_rank, 0) + 1
		
#	print rank_counts
#	return rank_counts
rankorder.c
// CS495-20 Homework 3
# include <stdio.h>
# include <stdlib.h>
# include <string.h>


//static PyObject* rank_order(PyObject *self, PyObject *args)
int rank_order(int argc, char **argv)
{

	char* nums = argv[1];
	int occurrences[10];
	int i, j, num;
	for (i=0; i<10; i++)
		occurrences[i] = 0;		
	for (num=0; num<10; num++)
	{
		for (i=0; i<strlen(nums); i++)
		{
			if (nums[i] == num)
				occurrences[num]++;
		}
	}
	
	int pairs[10];
	int tempswap;
	for (i=0; i<10; i++)
	{
		for(j=i; j<10; j++)
		{
			if (pairs[i] < pairs[j])
			{
				tempswap = pairs[j];
				pairs[j] = pairs[i];
				pairs[i] = tempswap;
			}
		}
	}
	
	int currcnt = 0;
	int countvalue = pairs[0];
	for(i=0; i<10; i++)
	{
		if (countvalue != pairs[i])
		{
			currcnt++;
			countvalue = pairs[i];
		}
	}
	int rank_counts[currcnt];

	countvalue = pairs[0];
	for(i=0; i<currcnt; i++)
		rank_counts[i] = 0;
	currcnt = 0;
	for(i=0; i<10; i++)
	{
		if (countvalue != pairs[i])
		{
			rank_counts[currcnt]++;
			currcnt++;
			countvalue = pairs[i];
		}
	}
	
	printf("{");
	for(i=0; i<currcnt; i++)
		printf("%d: %d,", i, rank_counts);
	printf("}");
	return 1;
}	
rankorder.lua (LUA version)
function rank_order(nums)

--	Return a dictionary where
--	key = rank, ranked by number of occurrences
--	val = number of numbers at that rank
--	There may be more elegant ways to do this but
--	this is the most straightforward I could come up with.
	
--	Calculate the number of occurrences of a given number
	occurrences = {}
	for num,nums do	
		occurrences[num] = occurrences.setdefault(num, 0) + 1
	end
		
--	Construct a decreasingly sorted sequence of
--	cnt, num pairs, first pair has rank 1
	pairs = [(cnt, num) for num, cnt in occurrences,items()]
	pairs.sort()
	pairs.reverse()
	
	rank_counts = {}
	current_rank = 1
	current_cnt = pairs[0][0]
	
--	Build the final dictionary, looking for transitions in
--	the counts for a number
	for cnt, num in pairs:
		if cnt ~= currenct_cnt:
			current_cnt = current_rank + 1
			current_cnt = cnt
		rank_counts[current_rank] = rank_counts.setdefault(current_rank, 0 ) + 1
		
	return rank_counts
end

Application Controller 

This lesson is for Python scripts' use in controlling other applications using simple commands. Purpose of this lesson is to show how to pass in commands to control iTunes, and add in additional functionalities such as calculating average track length and a needle-drop which plays each track for few seconds. Appscript is a high-level, user-friendly Apple event bridge that allows you to control scriptable Mac OS X applications from Python, Ruby and Objective-C. Appscript makes these languages serious alternatives to Apple's own AppleScript language for automating your Mac. In order to operate the following python script, appscript needs to be installed (command: python setup.py build, python setup.py install)

nettunes.py
#!/usr/bin/env python
"""
Building a Remote iTunes Service

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-05-17 (Wed, 18 May 2006) $"
__revision__ = "Homework 4"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#
#	 Executing python nettunes.py will trigger both functions.
#	 In order to modify arguments for the two functions, modify the last 3 lines of this code.
#	 Default values are host="wolverine", port=8080, seconds=20

import mytunes
import time

def average_track_length(remote_host, port):
	itunes = mytunes.MyTunes()
	itunes.start()
	try:
		tracks = itunes.track_length()
		count = len(tracks)
		total = sum(tracks)
		result = total/count
		return result
	except:
		print "Error retrieving tracks"

def needle_drop(remote_host, port, seconds):
	itunes = mytunes.MyTunes()
	try:
		tracks = itunes.track_length()
		count = len(tracks)
		itunes.play_track(0)
		for i in range(count):
			time.sleep(seconds)
			itunes.next_track()
			print "Playing next track"
	except:
		print "Error executing needle_drop"

print "Average track length:", average_track_length("wolverine", 8080)
print "Executing needle drop, will sample for 20 seconds"
needle_drop("wolverine", 8080, 20)

mytunes.py this script calls reference to the following, in which iTunes functionalities are defined and ready for use
from appscript import *
import __builtin__

class MyTunes:
	def __init__(self):
		""" no arguments -> MyTunes handle
		creates a new MyTunes bridge object
		Save this value in a variable for future use, e.g.
		itunes = mytunes.MyTunes()
		"""
		self.__app = app('iTunes')
	
	def start(self):
		""" no arguments -> None
		starts iTunes playing"""
		try:
			self.__app.play()
		except:
			pass
		
	def pause(self):
		"""no arguments -> None
		pauses the currently  playing track
		"""
		try:
			self.__app.pause()
		except:
			pass
	
	def stop(self):
		"""no arguments -> None
		stops the currently playing track
		"""
		try:
			self.__app.stop()
		except:
			pass
	
	def next_track(self):
		""" no arguments -> None, 
		moves to the next track in the current playlist """
		try:
			self.__app.next_track()
		except:
			pass
	
	def previous_track(self):
		""" no arguments -> None
		moves to the previous track in the current playlist """
		try:
			self.__app.previous_track()
		except:
			pass
			
	def set_volume(self, value):
		"""integer between 0 and 100 -> None
		Sets the volume
		"""
		try:
			self.__app.sound_volume.set(value)
		except:
			print "Error setting volume. Skipping"
			pass
			
	def get_volume(self):
		"""no arguments -> integer
		Returns the current value of the volume setting
		"""
		try:
			return self.__app.sound_volume.get()
		except:
			return -1
		
	def play_playlist(self, pl_name):
		"""playlist_name -> None
		Starts playing the named playlist """
		try:
			pl = self.__app.playlists[pl_name]
			self.__app.play(pl)
		except:
			print "No such playlist %s" % pl_name
	
	def play_track(self, track_idx):
		"""track_name or number -> None
		Starts playing the indicated track, within the current playlist.
		"""
		try:
			tracks = self.__app.current_playlist.tracks.get()
			if track_idx >= len(tracks):
				print "Index out of bounds [0:%s)" % len(tracks)
				return
			track = tracks[track_idx]
			self.__app.play(track)
		except:
			print "No such track %s" % track_name
	
	def track_length(self):
		"""no arguments -> list of track_names, 
		Returns a list of strings for the currently playing playlist.
		"""
		try:
			tracks = self.__app.current_playlist.tracks.duration.get()
			return tracks
		except:
			print "Error retrieving tracks"
			
	def current_tracks(self):
		"""no arguments -> list of track_names, 
		Returns a list of strings for the currently playing playlist.
		"""
		try:
			tracks = self.__app.current_playlist.tracks.name.get()
			return tracks
		except:
			print "Error retrieving tracks"
			
	def current_track(self):
		"""no arguments -> dictionary
		Returns a dictionary of information
		regarding the current track
		"""
		
		track_fields = ['album', 'artist', 'bit_rate', 'bpm', 'comment',
				'compilation', 'composer', 'database_ID',
				'date_added', 'disc_count', 'disc_number',
				'duration', 'enabled', 'EQ', 'finish', 'genre',
				'grouping', 'kind', 'modification_date',
				'played_count', 'played_date',
				'rating', 'sample_rate', 'size', 'start',
				'time', 'track_count', 'track_number'
				'volume_adjustment', 'year',
				'name', 'location', 'container']
					
		try:
			result = {}
			track = self.__app.current_track.get()
			for field_name in track_fields:
				try:
					if hasattr(track, field_name):
						result[field_name] = getattr(track, field_name).get()
				except:
					pass
			return result
		except:
			print "Error getting track info."
			return result
	
	def track_info(self, track_name):
		"""track_name -> dictionary
		Returns dictionary of information regarding
		the named track if it exists, otherwise an empty dictionary
		"""
		
		try:
			track = self.__app.library_playlists.get()[0].tracks[track_name].get()
			track_fields = ['album', 'artist', 'bit_rate', 'bpm', 'comment',
				'compilation', 'composer', 'database_ID',
				'date_added', 'disc_count', 'disc_number',
				'duration', 'enabled', 'EQ', 'finish', 'genre',
				'grouping', 'kind', 'modification_date',
				'played_count', 'played_date',
				'rating', 'sample_rate', 'size', 'start',
				'time', 'track_count', 'track_number'
				'volume_adjustment', 'year',
				'name', 'location', 'container']
					
		
			result = {}
			for field_name in track_fields:
				try:
					if hasattr(track, field_name):
						result[field_name] = getattr(track, field_name).get()
				except:
					pass
			return result
		except Exception, e:
			print "Error getting track info"
			return {}
		
	def all_playlist_names(self):
		"""No arguments -> list of strings
		Returns a list of the names of all of the playlist
		names in the iTunes database."""
		
		try:
			return self.__app.sources['Library'].user_playlists.name.get()
		except:
			return []
			
	def all_track_names(self):
		"""No arguments -> list of strings, 
		Returns a list of the names of all of the track
		names in the iTunes database."""
		
		try:
			names = []
			for pl_name in self.all_playlist_names():
				tracks = self.__app.playlists[pl_name].tracks.get()
				if not tracks: continue
				names.extend(self.__app.playlists[pl_name].tracks.name.get())
			return names
		except Exception, e:
			print "Error", e
			return []
	
	def get_playlist(self, idx):
		"""playlist_name or playlist_number -> list of strings
		Returns a list of all the names in the named playlist, if the playlist exists.
		"""
		
		try:
			pl = self.__app.user_playlists[idx].get()
			results = []
			for track in pl.tracks.get():
				results.append(track.name.get())
			return results
		except:
			return []
			
	def __playlist_object(self, idx):
		try:
			playlists = self.__app.user_playlists.get()
			pl = None
			if isinstance(idx, str):
				pl = self.app.user_playlists[idx]
			elif isinstance(idx, int):
				if ((0 <= idx) and (idx < len(playlists))):
					pl = playlists[idx]		 
			return pl
		except:
			return
			
def help():
	for attr_name in dir(MyTunes):
		if attr_name[0] != "_":
			__builtin__.help(getattr(MyTunes, attr_name))


Embedding Python 

This code implements a simple turtle graphics style engine that’s used to render the result of Lindenmayer systems(L-system), a transformation process on strings.

Lsystem.cpp
#include "lsystem.h"
#include <Python.h>

LSystem::LSystem(const string& start_string)
  : start(start_string), cur_string(start_string)
{
}

void LSystem::reset() {
  cur_string = start;
}

string LSystem::iterate(int iterations) {
  string next_string;
  
  PyObject *pModule, *pFunc, *pValue;							// python extension parts
  Py_Initialize();  
  pModule = PyImport_ImportModule("LSYSTEM_FILE");
  pFunc = PyObject_GetAttrString(pModule, "generate");
  pValue = PyObject_CallObject(pFunc, NULL);
  cur_string = PyString_AsString(pValue);
  return cur_string;
  Py_Finalize();

}

lsystem_file.py
#!/usr/bin/env python
"""
L-systems file for RGS

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-06-11 (Sun, 11 Jun 2006) $"
__revision__ = "Homework 5"
#    A Script written by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#

import sys,re

start = "F"
iterations = 3
rules = {"F": "F+F--F+F"}
	
def generate():	
	pattern = start
	for i in range(iterations):
		pattern = re.sub(start, rules[start], pattern)	
#		print pattern
	return pattern	

Batterylife Simulation 

Part of CS495-20 Python programming project, as well as a battery life simulator used for my Power Deregulation paper. The following set of code was used to calculate how long a particular type of battery would last under various processor setups tested. The input data, power dissipation metrics (static/dynamic) were taken from M5 processor simulation results, while various battery-related literature provided battery capacity and dissipation trends for different types of batteries. Project Proposal and Project Report are also available.

bl-compute.py Battery life cycle simulation for embedded systems 
#!/usr/bin/env python
"""
Battery Life Simulation for each benchmarks
	for use in Power Deregulation research
"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-06-09 (Fri, 8 Jun 2006) $"
__revision__ = "Rev.2 Part of CS495-20 Project"
#    Written by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#	 Northwestern University
#
#	 Usage: ./bl-compute.py
#	

import powvolt
import battery

print "-------------------Battery Simulation--------------------\n"
benchmark = ['MPGdec', 'MPGenc', 'SpeechRec', 'ADPCMdec', 'ADPCMenc', 'epic', 'unepic', 'g721dec', 'g721enc']

for i in range(9):
	time_step = 1.0
	time = 0.0
	bat = battery.Li_MnO2_Battery()

	while bat.cap > 0.0:
		time += time_step
		power = powvolt.power_voltage(benchmark[i], bat.voltage())
		bat.deplete_capacity(power * time_step)
	print "Estimated battery lifetime for", benchmark[i], ":", time, "seconds"
print "\n---------------------------------------------------------"
battery.py Battery capacity information and discharging behaviour
default_capacity = 600.0 * 1E-3 * 60.0 * 60.0 * 4 # Ws


class Battery(object):
	def __init__(self, capacity_Ws = default_capacity):
		self.cap_init = capacity_Ws
		self.cap = self.cap_init

	def deplete_capacity(self, drain_Ws):
		self.cap = max(self.cap - drain_Ws, 0.0)

	def voltage(self):
		val = self.cap / self.cap_init
		if val <= 0:
			return 0.0
		else:
			for i in range(len(self.table)):
				if val <= self.table[i][0] and val >= self.table[i+1][0]:
					alpha = (val - self.table[i+1][0]) / (self.table[i][0] - self.table[i+1][0])
					return self.table[i][1] * alpha + self.table[i+1][1] * (1.0 - alpha)

class Li_MnO2_Battery(Battery):
	name = 'Li/MnO_2'
	table = [
		(1.0, 3.25),
		(0.95, 3.1),
		(0.875, 3.0),
		(0.84, 2.98),
		(0.75, 2.95),
		(0.50, 2.9),
		(0.28, 2.9),
		(0.25, 2.875),
		(0.2, 2.8),
		(0.0, 2.3)
	]

class NiMH_Battery(Battery):
	name = 'NiMH'
	table = [
		(1.0, 2 * 1.38),
		(0.9, 2 * 1.31),
		(0.8, 2 * 1.29),
		(0.6, 2 * 1.28),
		(0.4, 2 * 1.28),		
		(0.2, 2 * 1.26),		
		(0.1, 2 * 1.25),		
		(0.05, 2 * 1.16),
		(0.0, 2 * 0.92)
	]

types = [
	Li_MnO2_Battery,
	NiMH_Battery,
]


powvolt.py Power consumption for each application in relation to number of active processors
#!/usr/bin/env python
"""
Battery Life Simulation for each benchmarks
	for use in Power Deregulation research
"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-06-09 (Fri, 8 Jun 2006) $"
__revision__ = "Rev.2 Part of CS495-20 Project"
#    Written by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#	 Northwestern University
#
#	 To be used with bl-compute.py
#	

_bench_proc = { \
	'MPGdec': [(3.3, 1), (3.112, 2), (2.83, 3), (2.736, 4)], \
	'MPGenc': [(3.3, 1), (3.112, 2), (2.736, 3)], \
	'SpeechRec': [(3.3, 1), (3.112, 2), (2.736, 3)], \
	'ADPCMdec': [(3.3, 1), (3.112, 2), (2.83, 3)], \
	'ADPCMenc': [(3.3, 1), (3.112, 2), (2.736, 3)], \
	'epic': [(3.3, 1), (3.112, 2), (2.924, 3)], \
	'unepic': [(3.3, 1), (3.112, 2), (2.736, 3)], \
	'g721dec': [(3.3, 1), (3.112, 2), (2.83, 3)], \
	'g721enc': [(3.3, 1), (3.112, 2), (2.736, 3)] \
}

_power_cons = [(3.3, 3.3899), (3.206, 2.9031), (3.112, 2.4551), (3.018, 2.04677), 
		(2.924, 1.67705), (2.83, 1.3415), (2.736, 1.0408)]

def benchmark_proc(bench, voltage):
	v_to_proc_cnt = _bench_proc[bench]
	for v, numcpus in v_to_proc_cnt:
		if v < voltage:
			return numcpus
	return 1

def single_proc_p(voltage):
	v_to_power_cnt = _power_cons
	for v, power in v_to_power_cnt:
		if v > voltage:
			return power

def power_voltage(bench, voltage):
	numcpus = benchmark_proc(bench, voltage)		# Find out number of CPUs used at specific voltage level
#	single_proc_p(voltage)
	return (float(numcpus) * single_proc_p(voltage))

powercalc.py Initially used to calculate the total power consumption at particular processor setup and time period. Submitted as CS495-20 project, and later converged into bl-compute.py for specific use for publication
#!/usr/bin/env python
"""
Power Data Extraction and Calculation Script for M5 Statistics

"""
__author__ = """Seunghoon Kim (ski819)"""
__date__ = "$Date: 2006-06-08 (Thurs, 8 Jun 2006) $"
__revision__ = "Rev.2 Part of CS495-20 Project"
#    Copyright (C) 2006 by 
#    Seunghoon Kim <seunghoon@northwestern.edu>
#
#	 Usage: ./powercalc.py (filename) (# of processors[max:4]) (Vdd[in V])
#	

import re, sys, math

#for line in fileinput.input():
if __name__ == '__main__':
	fname, numcpus, voltage = sys.argv[1], int(sys.argv[2]), float(sys.argv[3])
	frequency = (300 * (voltage-2.736) / 0.564) + 200
	print frequency
	if numcpus > 4:
		numcpus = 4
	test = open(fname, 'r')
	string = test.read()
	str = string.split()
	#print numcpus
	#print str

	dynparamstart = ["system.cpu0.POWER.DYNAMIC:bpred_block_average", 
	"system.cpu1.POWER.DYNAMIC:bpred_block_average", 
	"system.cpu2.POWER.DYNAMIC:bpred_block_average", 
	"system.cpu3.POWER.DYNAMIC:bpred_block_average"]
	dynparamend = ["system.cpu0.POWER.DYNAMIC:lsq_block_average", 
	"system.cpu1.POWER.DYNAMIC:lsq_block_average", 
	"system.cpu2.POWER.DYNAMIC:lsq_block_average", 
	"system.cpu3.POWER.DYNAMIC:lsq_block_average"]
	staparamstart = ["system.cpu0.POWER.STATIC:bpred_block_average", 
	"system.cpu1.POWER.STATIC:bpred_block_average", 
	"system.cpu2.POWER.STATIC:bpred_block_average", 
	"system.cpu3.POWER.STATIC:bpred_block_average"]
	staparamend = ["system.cpu0.POWER.STATIC:lsq_block_average", 
	"system.cpu1.POWER.STATIC:lsq_block_average", 
	"system.cpu2.POWER.STATIC:lsq_block_average", 
	"system.cpu3.POWER.STATIC:lsq_block_average"]
	dynpower = [0.0,0.0,0.0,0.0]
	stapower = [0.0,0.0,0.0,0.0]		# Initialize an array in length of 4
	dyntotal = 0.0
	statotal = 0.0

	for i in range(numcpus):
		# first value to fetch is the one that comes after this pattern
		dynindex = str.index(dynparamstart[i]) + 1
		dynend = str.index(dynparamend[i]) + 1
		while dynindex < dynend:
			dynpower[i] += float(str[dynindex])
			dynindex =  dynindex + 4
		print "Dynamic Power for Processor", i, " sums upto: ", dynpower[i]
		dyntotal += dynpower[i]

		# Similarly for static power
		staindex = str.index(staparamstart[i]) + 1
		staend = str.index(staparamend[i]) + 1
		while staindex < staend:
			stapower[i] += float(str[staindex])
			staindex += 4	
		print "Static Power for Processor", i, " sums upto: ", stapower[i]
		statotal += stapower[i]
	
	print "Total Dynamic Power: ", dyntotal
	print "Scaled according to", voltage, "V and", frequency, "MHz:", (dyntotal*voltage*voltage*frequency/3.3/3.3/500)
	print "Total Static Power: ", statotal
	print "Scaled according to", voltage, "V:", (statotal*math.exp(3.3-voltage))
	totalpower = (dyntotal*voltage*voltage*frequency/3.3/3.3/500) + (statotal*math.exp(3.3-voltage))
	print "Overall Power Dissipation for", numcpus, "processors running at", voltage, "volts and", \
		frequency, "MHz:", totalpower, "W"

Reference: Dive into Python; A good walkthrough guidelines; used as primary reference source for academic purposes

wxPython

for GUI programming using python; a blending of the wxWidgets C++ class library with the Python programming language


Language Comparison: to C++

The main advantage for using scripting languages that were experienced while completing this programming assignment was Python’s flexibility. For implementing this type of module, Python was a better choice for being able to fully integrate outside modules, not defined data types, and simpler debugging process.

First, importing outside sources can be done with one line of command, whereas in C++, more restricted class and data type rules apply when outside header files are used. When using python, importing simply just involves figuring out what kinds of additional commands should be used; however, C++, in turn for being able to have more flexible types of operations, requires careful observation of source code sighted. That leads to another advantage for python, having non-defined data types. For C++ to have custom data types, it involves complex tree or multiple layer styled data structure that inhibits quick programming. In python, there is no need to define variables in advance, so even when mistakes are made, it can be quickly fixed. The favorite part about programming for this class is that being able to debug as I write the program. Being able to test each line of code as I plan out what to do or use puts me in so much calm state. C++ programming process is usually repetition of write a long lines of codes, test and fix the errors as I go, but for this assignment, whatever I type on .py file, I could test and check whether the expression is valid, which resulted more stable programming task and efficient time spending. As this was yet the first step for actually implementing a module using Python, I expect that the upcoming programming assignments will look more straight forward.


Language Comparison: to Lua

Basic Language Features

The primary purpose of Lua was for its usage in extension; therefore, it was made compact to fit on many different host platforms. Lua contains a single native data structure that maps out typical data structures including arrays, sets, lists and hash tables. All of these features are pretty much contained in Python. Its typical syntax can be briefly explained by the code below:

io.write("F ")
for c=c0,c0+10-1 do
	f=(9/5)*c+32
	io.write(string.format("%3.0f ",f))
end
io.write("\n\n")

Unlike Python, Lua only supports dynamic typing [4]. The language itself is simple, so that variables do not possess any other definition besides the value they hold. Lua treats functions as first class variables, explained by the example below:

local oldprint = print		-- store current print function as old print
print = function(s)		-- redefine print function
	if s == "foo" then 
      	oldprint("bar")
      else 
      	oldprint(s) 
      end
end

Scripting

In terms of text processing capabilities, Lua has string manipulation library that is similar to Python’s regular expression library, though its character pattern class does not seem as comprehensive as Python’s. Command invocation and file system manipulation are very similar to Python, their io, file, os, debug facilites [5].

local A
while 1 do
 local l=io.read()
 if l==nil then break end
 local _,_,a,b=string.find(l,'"?([_%w]+)"?%s*(.*)$')
 if a~=A then A=a io.write("\n",a,":") end
 io.write(" ",b)
end

Gluing

Some of the namespaces and objects can be created using Lua’s native data structure; however, Lua lacks one of the essential gluing capability introspection. IPC mechanisms and Coroutine support were added since version 4.1. Network support can be added on by installing a C extension[6].

Extending

Extensible semantics is a key feature of Lua; therefore, its extensibility is boundless with variety of foreign function codes. Its semantics can also be extended by using built-in functions in metatables, enabling its capability to compose an object-oriented program.

Bibliography

  1. Lua programming language - Wikipedia
  2. Python programming language - Wikipedia
  3. Introduction Material on Python
  4. Lua 5.1 Reference Manual
  5. Python Library Reference
  6. Lua Networking Extension Library & Lua Webserver
ċ
LSYSTEM_FILE.py
(0k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
Makefile
(1k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
battery.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
bl-compute.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
dupwords.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
lsystem.cpp
(1k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
montager.py
(2k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
mytunes.py
(6k)
Hoon Kim,
Feb 24, 2013, 4:30 PM
ċ
netdisease.py
(2k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
nettunes.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
powercalc.py
(3k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
powvolt.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
rankbag.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
rankorder.c
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
rankorder.lua
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
rankorder.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
setup.py
(0k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
ċ
urlizer.py
(1k)
Hoon Kim,
Feb 24, 2013, 4:31 PM
Comments