Twenty things to do with a python script
With a deferential bow to Seymour Papert & Cynthia Solomon's Twenty Things to do with a computer (1971), here a selected listing of Python recipes that represent a range possible Media Design explorations that need not involve many lines of code.
Papert & Solomon were key figures as early as the 1970s in the development of school curricula for using computers in the classroom. Through the development of the programming language LOGO, and the concept of turtle graphics, they promoted a constructivist approach to using programming to teach other concepts. In this approach, the computer provides a means of making "microworlds" in which typically "abstract" concepts (such as geometry and differential equations) can be approached in a concrete and (virtually) hands-on way rather than as abstract principles typical of convention maths teaching.
The python programming language has been used for many years as part of the PZI Media Design curriculum. Echoing the constructivism of Papert & Solomon, programming is used in the course to get "hands on" experience with the substance of software and digital media.
<slidy theme="aa" />
Make a turtle
import turtle
import random
def Poly(n,x):
angle = 360/n
for i in range(n):
turtle.forward(x)
turtle.left(angle)
def makeFlower(p):
for i in range(12):
Poly(9,p)
turtle.left(30)
def makeTriple():
turtle.speed(44)
for i in range(3):
i = (i+1)*5
turtle.color(random.random(),random.random(),random.random())
makeFlower(i)
xa = -255
y = -244
numberColumns = 5
numberRows = 5
turtle.penup()
turtle.setpos(xa,y)
for i in range(numberRows):
for c in range(numberColumns):
c=(c+1)*100
makeTriple()
turtle.penup()
turtle.sety(y+c)
turtle.pendown()
i=(i+1)*100
turtle.penup()
turtle.setpos(xa+i,y)
turtle.pendown()
Source: Lidia Pereira, Turtle Graphics Exercises
Create an Inkscape plugin to draw turtle graphics
The same "turtle" code as above is now performed in the context of the SVG editor Inkscape. The "Seymour" python plugin code emulates the interface of the turtle graphics module rendering the same movements now as SVG paths and groups. The resulting graphic can be further manipulated (as points & paths) using Inkscape's full graphical interface and toolset.
See Seymour
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
Copyright 2013, Piet Zwart Institute, MA Media Design
http://pzwart3.wdka.hro.nl/wiki/
Released under a GPL3 license, see LICENSE
#XSS2qwXBUYv%s+<>dqw6wmq2om#HH$wac=:;==|i|nYUWQQW$WQQQWmBQmWBQWWBWQWWWmBBWWmQQQQ
Z2qpXooo2i+=|aaZW1n2vYwn###ovi>=||=;:;::+=|||{?VTSUQWWBBW#ZWWmmWmWmmWmWmBmW#QWQQ
ZoSXXX2!==>{av1XTTTYX#WTY+..."!""!<%|=========|*nSou3vSZVZXA#WWmBBWWWmmBWWBmWWQQ
W#oX2ov%%nnZX1|++<loG?.=;<_%|_,._,..+*~=i>==|==+;:==||{SYH$QWWBWWBWmWWWWmWBWWWQQ
#ZXXo{vnuvnvI+=::vnS(:i|v%;::::=====|=|===|||==+===::=={uwm#mWWWmmWWBWWmWWWmBQQQ
U2XYo2Iov%|i++:.=i%X:=|+: :;:;==v%lvvvvvvlvs%avv|=====+|YWBWWWWWWWWmQWmWBWWBWQQQ
#XoooIi>|=~-:+ ;:=v(:|---:===|ivvnoX2XoXSoXo1aaunvvsi==:=)3WWWWWBBBWmWBWWWWmQWQQ
#XSZ1>)}+=|=;:}"|=|>=;. .;=||ivnoXXXXXZZZXqomX2ouXS2Xo;==;=lXWBWWWWWBWBWWWWmQWQQ
mX1%**=::`:.__;=-=>:::.:==+<svoXZXXZZZSqw#XXnwXXd&SqXXS>::+={S##WWWBWWBWWBWWWWQQ
Wnz||is,=;=._|::_=- -::==+|iIo2XXXXmwmZZZYodXmXXSo#Y1i|||:==|{IXZ$WQBWWBWWWmWQQQ
1vs>>=:=|==||=ia+` .:==++vvvSoXXZX22Y1qu#XXXSoZX1l|+iivv>:=|={*mw#mWQmQWmWWWWQQ
|%iawu2!3e(v>"' -=|>|ivvSeXoZXXSXXXZ#XXwXX1|<ivdXXXXo>:;;iII####WWBWWWWBQQQ
<|2YI>+={1o+ _ .-..._==<v}1ou1XwoZZZXZZZZXZXXonowmZZZXXX#X,:;=|liYXXX#mWBWBWQQQ
|uni>>|=ii3;;+,._- .==|%{iv1uSSX2XZXXZXXXo2XoS2Xm#ZZZ1+{i*SX; ==|i%*YoX###WmWWQQ
Iiv>|<;=||<-:.:=.;;=<iii{%1SooSS2li|ivooXn2ooXX#Z#X2|==-%IISo,--=i=|=InXZ##WmQQQ
|=iii>+||+=::=::=;==|||%vv1****+=+|aommmmXoXXXZZ#SXioZaw|vo#Xo --==<||*A###WQQ
i|==||(=|=>-.-::-=;+||ii%|++++|vuoXZZ#Z#Z##ZZXXZooe+){suq##XXZo ...;;+<i%|?9$WWQ
l|||i=>|>|..:.:;::==|=i||+=|invoXSZZXXXoXnSnn32ZX1|IvvXXXXX#XZ#c .-:::=|3ns%>2AW
vi|i+|=<+:.:.:::;===|||>|ivno2X2***}|**I1ii|iinmXZwunoXX#XXXXXUZc :;:::<=%YoowzY
n}ii||>:;::.-::;:===|||i|lo2SS}|<%.-:=%"!+||ilnSX#Z##XXS22SXXZ#ZX;--:===i<=i3#Zo
os%|l+=:;==:-::::=;+|=|iivno2c|ioXaa%|i%Ii|ilvnSSXXXZZ#XmXXZ#U###m;:.::||i|l>i3$
1|}=>==;=:;:;.:.:;==||iiivno2%=+{*IvuXXoovnvvnooo2SXXZZZXZX#U###ZZc:-:;:||ovsvvv
1i>|==|==;.==;...::|+|i|Ilvnnvvno2XXXXX#XvnvononvooXXZZZ##Xu1XX##Zo;-.:.:+*1l3qv
1|==|++|;;:.::.: :-+|||ivvvoonooooXZZZX1ooo21IIIvnXXXX#XZ#2Il?SXZX(.: ;::iwwIXw
o%i=<==>::::: .: ...:=||ilvnn222XSXXXSnoS2SSo|<vvv2S2XXXmm#`--==<Xov;.:..:|*SlBh
pvi>=|=:==.....- .. -;=|ilvnnoSo2ooXSSSoSXZn>|oSXno2oXXZZ' ..:.:{1=-:.:=||SXQW
X|li>||=;=:..... - :+||lvnnn2o2SS2XXXXX2vii|!+---"!!+- ._...<l=-..-::)Y1#B
Xvii||===;:.=:... -=||ivvnno2oXXXXXXZ1|===. . ..._/====i|; .::=+nWW
mZs|v|+=|==::... . . :==Iivvnno2S2XXXX>==::.. -:=oe" :<vvi>:: . ;||ivd
Qm2vi%i|%;;;:;.: . :=|<vv1vvo2XSXX1==:. ._;=_:-"=...=vIni>:. ..:=)2v|
WWZzi|<v||=+:==.;.. . ..-:=||lIvvnno2n>=.. .:=|+'_:-;..;|invnv:. ` ..=%nIi
Qmwouc|vi<|+:<:: :. . . .-:=||iiInvI|:....;:..:====|ivnzi+|i;. .:-=;=|i|
QW#XS}ii%%||=|=:..-_ - ..-===+|ii||=:.:=i||||||ilIv}|` _i|:- ...;:==ivl=
Qmov%svvu%i==|=:: . : ..:-;=+|===:;:=|ivIvvIl|=+; =i==. ..:==||{nc;
QWmmZm#2n>|><<>=:. .::- -.:-:-:-::==<i|ivlii|>= ==:.. :==::=%o|*1>
QQ#mmWTon=Ivil==:. = . .-..- - :-++<|>|<=;:;: -=<|Inoai_
QQQQQeXeniIi|I==:. . : . -. . : :-::.-.:.- . .;+lXXQ#mB
QQQQQQWscs=|(>===: :.::.. . ..... -.. ... . ====iinodWm
QQQQQQk2oi|+i>><:.::=..<;_:.. . - - ..;: . . ..::+i|vwumQmW
QQQQQBdW#Xviii|=|<=_.:||%%===;;.. . -...:-, .:::...: :=;==|<vnmmQWWT
"""
import sys, os
if os.path.exists('/usr/share/inkscape/extensions'):
sys.path.append('/usr/share/inkscape/extensions') # or another path, as necessary
from simplestyle import *
import random, math, uuid
import inkex
defaultpathstyles = {
'fill':'none',
'fill-rule':'evenodd',
'stroke':'#000000',
'stroke-width':'1px',
'stroke-linecap':'butt',
'stroke-linejoin':'miter',
'stroke-opacity':'1'
}
#################################
def colorval (f):
if (type(f) == float):
if f>= 0 and f<1:
f = math.floor(256*f)
else:
f = math.floor(f)
return f
def rgb (r, g, b):
return '#%02x%02x%02x' % (colorval(r),colorval(g),colorval(b))
# <path style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="%s" />
def pointstodata (points):
try:
data = "M %0.6f,%0.6f" % points[0]
for p in points[1:]:
data += " L %0.6f,%0.6f" % p
return data
except IndexError:
return ""
def collecttext (elt):
ret = elt.text or ""
ret += "\n".join([collecttext(child) for child in elt])
return ret
#################################
class Turtle (object):
def __init__(self, x=0.0, y=0.0, heading=0.0, pendown=True, layer=None):
self.x = x
self.y = y
self.homex = x
self.homey = y
self.heading = heading
self._pendown = False
self.points = []
self.stack = []
self.lastpath = None
if layer is not None:
self.stack.append(layer)
self.styles = {}
if pendown:
self.pendown()
def forward (self, steps):
self.x += math.cos(self.heading) * steps
self.y -= math.sin(self.heading) * steps
if self._pendown:
self.points.append((self.x, self.y))
fd = forward
def backward (self, steps):
self.forward(-steps)
bk = backward
back = backward
def right (self, d):
d = (d/180.0)*math.pi
self.heading -= d
rt = right
def left (self, d):
d = (d/180.0)*math.pi
self.heading += d
lt = left
def goto(self, x, y):
self.x = x
self.y = y
setpos = goto
setposition = goto
def setx (self, x):
self.x = x
def sety (self, y):
self.y = y
def setheading(self, d):
self.heading = (d/180.0)*math.pi
seth = setheading
face = setheading
def home(self):
self.x = homex
self.y = homey
def circle(self, radius, extent=None, steps=None):
pass
def dot(self, size=None, *color):
pass
def stamp(self):
pass
def clearstamp(self, stampid):
pass
def clearstamps(self, n=None):
pass
def undo(self):
pass
def speed(self, speed=None):
pass
def pendown (self):
if not self._pendown:
self._pendown = True
self.points.append((self.x, self.y))
pd = pendown
def penup (self):
if self._pendown:
self._pendown = False
if len(self.points) and len(self.stack):
path = inkex.etree.Element(inkex.addNS('path', 'svg'))
# http://stackoverflow.com/questions/1551666/how-can-2-python-dictionaries-become-1/1551878#1551878
styles = dict(defaultpathstyles, **self.styles)
path.set('style', formatStyle(styles))
path.set('d', pointstodata(self.points))
self.stack[-1].append(path)
self.lastpath = path
self.points = []
pu = penup
def ensure_id (self, elt):
try:
ret = elt.attrib['id']
except KeyError:
ret = "seymour-"+uuid.uuid1().hex
elt.attrib['id'] = ret
return ret
def text (self, text):
if self.lastpath != None:
textelt = inkex.etree.Element(inkex.addNS('text', 'svg'))
textPath = inkex.etree.Element(inkex.addNS('textPath', 'svg'))
# assert False, str(self.lastpath.attrib.keys())
textPath.attrib[inkex.addNS('href', 'xlink')] = '#'+self.ensure_id(self.lastpath)
textPath.text = text
textelt.append(textPath)
self.stack[-1].append(textelt)
else:
textelt = inkex.etree.Element(inkex.addNS('text', 'svg'))
textelt.text = text
self.stack[-1].append(textelt)
def color (self, *args):
if len(args) == 3:
r, g, b = args
self.styles['stroke'] = rgb(r, g, b)
elif len(args) == 1:
r, g, b = args[0]
self.styles['stroke'] = rgb(r, g, b)
def startgroup (self, id=None):
""" special to SVG"""
g = inkex.etree.Element(inkex.addNS('g', 'svg'))
if id is not None:
g.set('id', str(id))
self.stack[-1].append(g)
self.stack.append(g)
def endgroup (self):
""" special to SVG"""
self.stack.pop()
def exitonclick (self):
self.penup()
pass
#########################################################
# The Inkscape Effect interface
class SeymourEffect(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
# http://docs.python.org/lib/module-optparse.html
self.OptionParser.add_option('-l', '--layer', action = 'store',
type = 'string', dest = 'layer', default = 'Seymour output',
help = 'name of layer for output')
def effect (self):
svg = self.document.getroot()
# svg = self.document.xpath('//svg:svg', namespace = inkex.NSS)[0]
for id, code in self.selected.iteritems():
try:
# code = self.document.xpath("//*[@id='%s']" % codeid)[0]
src = collecttext(code)
# print src
width = inkex.unittouu(svg.get('width'))
height = inkex.unittouu(svg.attrib['height'])
outputlayer = inkex.etree.SubElement(svg, 'g')
outputlayer.set(inkex.addNS('label', 'inkscape'), self.options.layer)
outputlayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
turtle = Turtle(x=width/2, y=height/2, layer=outputlayer)
d = {'turtle': turtle}
# turtle.export_to_dict(d)
# d['rgb'] = rgb
exec src in d
except IndexError:
pass
##############################################################################
# This file can be directly applied to an SVG on the commandline using:
# python seymour.py path/to/your.svg
if __name__ == "__main__":
effect = SeymourEffect()
effect.affect()
Generate an animation with "raw" images
Python is used to output the raw bytes of uncompressed images and assembled together to make an animation.
import struct, sys
width = 320
height = 240
xWhite = 0
header = struct.pack("<BBBHHBHHHHBB",0,0,2,0,0,8,0,0,width,height,32,1<<5)
totalframes = 25
for frame in xrange(totalframes):
frame = frame+1
out = open("frames/frame%02d.tga" % frame, "wb")
out.write(header)
for y in xrange(height):
for x in xrange(width):
xWhite = xWhite +1
if (frame != 1 and xWhite%frame == 0):
r = 255
g = 255
b = 255
a = 255
else:
r = 0
g = 0
b = 0
a = 255
out.write(struct.pack('B', b))
out.write(struct.pack('B', g))
out.write(struct.pack('B', r))
out.write(struct.pack('B', a))
out.close()
Sources: Mihail, Lucia, Tamas
Generate tactical hybrid texts
Facebook's Terms of Service is crossed with Jane Austen's Emma to produce a hybrid social protocol
Uses: NLTK
Source: Femke Snelting, EmmaWoodhouse.odt
Programmatically Manipulate Typefaces
Source: Eric Schrijver, http://i.liketightpants.net/and/programmatically-manipulating-typefaces
Spider texts and extract strategic search patterns
ective enforcement of intellectual property rights is critical to sustaining e or the enforcement of intellectual property rights , taking into account diffe procedures to enforce intellectual property rights do not themselves become ba em of infringement of intellectual property rights , including infringement ta ensive enforcement of intellectual property rights than is required by this Ag etween enforcement of intellectual property rights and enforcement of law in g lability and Scope of Intellectual property Rights 1 . This Agreement shall be , and maintenance of intellectual property rights . 2 . This Agreement does n ures where a right in intellectual property is not protected under its laws an rk for Enforcement of Intellectual property Rights ) are invoked ; ACTA / en 7 calendar days ; ( h ) intellectual property refers to all categories of intell to all categories of intellectual property that are the subject of Sections 1 rk for Enforcement of Intellectual property Rights ) are invoked ; ACTA / en 8 g to assert rights in intellectual property ; ( m ) territory , for the purpos rk for Enforcement of Intellectual property Rights ), means the customs territ - Related Aspects of Intellectual property Rights , contained in Annex 1C to RK FOR ENFORCEMENT OF INTELLECTUAL property RIGHTS SECTION 1 GENERAL OBLIGATIO ct of infringement of intellectual property rights covered by this Agreement , he enforcement of any intellectual property right as specified in this Section ng the enforcement of intellectual property rights , its judicial authorities he infringement of an intellectual property right from entering into the chann ng the enforcement of intellectual property rights , its judicial authorities s for infringement of intellectual property rights , a Party ' s judicial auth the right holder ' s intellectual property right in question and actually ass horization to use the intellectual property right in question . ACTA / en 14 A
The text of the proposed ACTA treaty is subjected to an algorithmic reading using NLTK's concordance function.
import nltk
nltk.download()
corpus_root='/path/to/your/texts'
wordlists=PlaintextCorpusReader(corpus_root,'.*')
acta=nltk.text.Text(wordlists.words('ACTA.txt'))
import sys, nltk
from nltk.corpus import PlaintextCorpusReader
corpus_root=sys.argv[1]
print corpus_root
corpus=PlaintextCorpusReader(corpus_root,'.*')
interesting=['property','intellectual','right','measure','protection']
for fileid in corpus.fileids():
text=nltk.text.Text(corpus.words(fileid))
text.concordance('ACTA')
Uses: NLTK
Source: Nicolas Malevé, http://vj13.constantvzw.org/live/deskcam/
python -m SimpleHTTPServer
In a time when the terms of "sharing" become increasingly contested and dictated by platforms vying for our personal data and attention, this simple one-liner, which shares the current directory (and potentially sub-directories) on one's local network takes on a political dimension. I share therefore I am!
Python 3 Version:
python -m http.server 8888 &
See Also: Serve.py
Permute the spellings of search terms
A course exercise using python to permute the letters of a text string is later developed into a browser plugin exploring strategic uses of misspellings used by various communities to evade censorship when using search engines.
Source: Linda Hilfling, the experiments were developed later into the Misspelling generator browser plugin & project
Create a pataphysical search engine
A Python CGI that applies an algorithm developed by Oulipo (Ouvroir de littérature potentielle; or "workshop of potential literature") practitioners to a search request producing a détournement of the search engine.
african africans afro afros aft afterbirth aftercare aftereffect
def getNewQuery (self, theQuery, theNounsFile) :
myNounsFile = open("nouns.txt", 'r')
myNounsList = []
for myLines in myNounsFile :
myNoun = myLines.strip()
myNounsList.append(myNoun)
myQuery = nltk.word_tokenize(theQuery)
myNewQuery = ""
for myWord in myQuery :
try :
myIndex = myNounsList.index(myWord.lower())
myNewQuery += " " + myNounsList[(myIndex + 7) % len(myNounsList)]
except :
myNewQuery += " " + myWord
myNewQuery = myNewQuery[1:]
myPattern = re.compile("\"\ ([^\"]+[.]?)\ \"")
myNewQuery = re.sub(myPattern, "\"\\1\"", myNewQuery)
return myNewQuery
Uses: NLTK
Source: Sebastian Schmieg & Silvio Lorusso
Create a Traceroute Map
Using the commandline traceroute command and a geoip database, python is used to translate the hops of a network transaction into a geographic journey that retraces an imperial history of telecommunications.
# imports the geoip database and the sys function
import pygeoip, sys, string
# creates a variable called "filename" that equals the first thing that
# has been put after the execution of "routetodot[dot]py"
filename = sys.argv[1]
#creates a variable of the geoip database from the file "GeoIP.dat"
GEOIP = pygeoip.Database('GeoIP.dat')
#create a variable called lastIp
lastNUM = None
# create a variable "line" from every line in the "filename"
# split this "line" into a variable called "data"
# check if "data" starts and ends with "(" ")"
# if so create a variable called "ip" that is "data" without "()"
# look up "ip" in the "GEOIP" variable
# checks if "a.country" returns none, it is then printed as "localhost"
# prints the variables "lastIp" and "ip"
# changes "lastIp" into "ip"
lineNUM = 0;
labels = "";
connections = "";
colorsbycountry = dict(US='blue',NL='orange',DE='grey',CN='red',localhost='pink',IE='green',FR='purple',GB='crimson', EU='sienna' )
colors = '"0.8396,0.4862,1.0" "0.8396,0.4862,0.8" "0.8396,0.4862,0.6" "0.8396,0.4862,0.4" "0.8396,0.4862,0.2" "0.8396,0.4862,0.0"'.split()
nodenamebyip = {}
nodenum=0
lastip = None
colorindex=0;
for line in open(filename):
parts = line.split()
NUM = parts[0]
lineNUM +=1
for data in parts:
#line[1]
if data.startswith("(") and data.endswith(")"):
ip= data.strip("()")
a= GEOIP.lookup(ip)
if a.country == None:
a.country = "localhost"
if a.country not in colorsbycountry:
colorsbycountry[a.country] = colors[colorindex]
colorindex+=1
labelcolor = colorsbycountry[a.country]
if ip not in nodenamebyip:
nodenum+=1
nodenamebyip[ip] = "node"+str(nodenum)
# first time, print label
nn = nodenamebyip[ip]
#labels+= nn +' [label="'+ip+' '+a.country+'" fontcolor="'+labelcolor+'" style="filled"]\n'
#labels+= str(lineNUM)+' [label="'+ip+' '+a.country+'" fontcolor='+labelcolor+' style=filled]\n'
labels+= str(lineNUM)+' [label="'+ip+' '+a.country+'" fillcolor='+labelcolor+']\n'
if lastNUM != None:
connections+= str(lastNUM)+"->"+str(lineNUM)+'\n'
# connections+= nodenamesbyip[lastip]+"->"+nodenamesbyip[ip]+'\n'
lastNUM = lineNUM
lastip = ip
graphname = filename;
if graphname.endswith(".txt"):
graphname = graphname.strip(".txt")
print "digraph iptrace {\n bgcolor = grey; \n node [shape=rect, fontname=Arial, fontcolor=white, style=filled] \n edge [style=dotted] \n"
print 'label=','"'+graphname+'"'
print labels
print connections
print "}"
Uses: pygeoip
Source: Roel Roscam Abbing, Documentation
Create an alternative social network based on scraping supermarket loyalty card data
An installation interface that creates an alternative social network based on scraping a major Grocery chain's customer loyalty website.
Source: Birgit Bachler, http://www.birgitbachler.com/portfolio/?p=506
Create a custom joystick sound recorder
A joystick and laptop become a custom recording and playback device for making and live mixing field recordings.
Uses: pygame
Source: Peter Westenberg, http://www.deschaarbeeksetaal.be/p/rugzak/
Slice & reorder an audio file by predominant frequency
Long format diary cassette recordings are sliced into 1/10th second intervals and sorted by predominant frequency. The resulting sorted pieces are reassembled producing a new recording that reveals aspects of the original recording through an algorithmic ordering.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys, argparse
parser = argparse.ArgumentParser(description="Dumps spectral analysis of audio using gstreamer")
parser.add_argument('--freq', default=44100, type=int, help="audio frequency")
parser.add_argument('--interval', default=0.1, type=float, help="interval duration (in seconds)")
parser.add_argument('--bands', default=128, type=int, help="number of bands to split the spectrum")
parser.add_argument('path', help="audio filename to analyze (wav format only)")
args = parser.parse_args()
inpath = args.path
AUDIOFREQ = args.freq # MAX FREQ OF ANALYSIS
INTERVAL_SECS = args.interval
INTERVAL = int(INTERVAL_SECS * 10**9) # DURATION OF "FRAMES" in nanoseconds / audio chunks to process
BANDS = args.bands # 128 # SPLIT THE SPECTRUM UP INTO THIS MANY BANDS
NANOS = float(10**9)
GST_MESSAGE_EOS = (1 << 0) # couldn't find this in gst package (wtf!)
import gst, pygst, struct, gobject
# alternative pipeline for live analysis
# listener_desc = 'autoaudiosrc ! spectrum interval={1} bands={2} ! fakesink'
listener_desc = 'filesrc location="{0}" ! wavparse ! spectrum interval={1} bands={2} ! fakesink'
listener_desc = listener_desc.format(inpath, INTERVAL, BANDS)
# (pmin, pmax) = (None, None)
def listener_on_message (bus, message, data):
global pmin, pmax
s = message.structure
if s:
msgname = s.get_name()
if msgname == "spectrum":
secs = s['timestamp'] / NANOS
# print ("%0.1f-%0.1f\t"%(secs, secs + INTERVAL_SECS)) + ("\t".join([str(x) for x in s['magnitude']]))
print '"{0}",{1:0.3f},{2:0.3f},'.format(args.path, secs, secs + INTERVAL_SECS) + (",".join(["{0:0.3f}".format(x) for x in s['magnitude']]))
else:
# print dir(message), message, message.type
if message.type & GST_MESSAGE_EOS:
listener.set_state(gst.STATE_NULL)
sys.exit(0)
return True
freqs = []
for i in range(BANDS):
freqs.append( ((AUDIOFREQ / 2.0) * i + AUDIOFREQ / 4.0) / BANDS )
# SIMPLE HEADERS
#print "source\tin\tout\t", "\t".join([str(x) for x in freqs])
# RANGE HEADERS
labels = []
for i in range(BANDS):
if i == 0:
fromfreq = 0.0
else:
fromfreq = freqs[i-1]
labels.append('"({0:0.0f}-{1:0.0f})"'.format(fromfreq, freqs[i]))
print '"source","in","out",'+(",".join(labels))
listener = gst.parse_launch(listener_desc)
listener.get_bus().add_watch(listener_on_message, None)
mainloop = gobject.MainLoop()
listener.set_state(gst.STATE_PLAYING)
try:
mainloop.run()
except: # an interruption from Ctrl-C
pass
Uses: gstreamer
Source: Nicolas Malevé and Michael Murtaugh, Full documentation & pipeline
3D Cloud computing with Blender
A mod of the above script...
# The following function is adapted from
# Nick Keeline "Cloud Generator" addNewObject
# from object_cloud_gen.py (an addon that comes with the Blender 2.6 package)
# from : http://bathatmedia.blogspot.be/
def duplicateObject(scene, name, copyobj):
# Create new mesh
mesh = bpy.data.meshes.new(name)
# Create new object associated with the mesh
ob_new = bpy.data.objects.new(name, mesh)
# Copy data block from the old object into the new object
ob_new.data = copyobj.data.copy()
ob_new.scale = copyobj.scale
ob_new.location = copyobj.location
ob_new.rotation_euler = copyobj.rotation_euler
# Link new object to the given scene and select it
scene.objects.link(ob_new)
ob_new.select = True
return ob_new
Source: Julien Deswaef, Brussels Blender Group
Create a dotcom index using letter permuations
Permutations are used to generate all possible short 2 and 3 letter domain names. The result is output as an HTML page with working links so that the names can be interactively tested and explored.
from itertools import product
chars = "abcdefghijklmnopqrstuvwxyz1234567890-"
for n in xrange(253):
for comb in product(chars, repeat=n):
i = ''.join(comb)
print 'http://www.'+i+'.com'
Source: User:Roelroscama, Documentation
Filter a subtitle file to highlight the unique words of a spoken text (Disappearance)
http://activearchives.org/wiki/Disappearance
A script processes the titles of an interview, transcribed using the SRT format. As words repeat, they become blanked out, providing a subtle visualisation contrasting the novel and repetitive aspects of a speaker's language.
#! /usr/bin/env python
# Copyright 2010 the Active Archives contributors.
# See the file AUTHORS for more details.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import re
from optparse import OptionParser
from textwrap import dedent
# inits usage and arguments
usage = "usage: %prog in.srt > out.srt"
parser = OptionParser(usage=usage)
(options, args) = parser.parse_args()
# checks the arguments length
if len(args) != 1:
parser.error("incorrect number of arguments")
# opens the subtitle file and reads its content
try:
f = open(args[0], 'r')
except IOError:
sys.exit(dedent("""\
Error: I can't open your subtitle file.
Are you sure it exists?\
"""))
else:
subtitles = f.read()
f.close()
pattern = re.compile(r'[a-zA-Z]+', re.UNICODE) # creates a pattern to search words
used_words = []
new_text = ""
previous_end = 0
# replaces all the occurrences of the words but the first one
for match in pattern.finditer(subtitles):
new_text += subtitles[previous_end:match.start()]
word = match.group()
if word.lower() in used_words:
#new_text += "*{w}*".format(w=word)
#new_text += "<del>{w}</del>".format(w=word)
#new_text += "--{w}--".format(w=word)
new_text += "{w}".format(w="".ljust(len(word), " "))
else:
new_text += word
used_words.append(word.lower())
previous_end = match.end()
new_text += subtitles[previous_end:len(subtitles)]
print(new_text)
Source: Alexandre Leray and Stéphanie_Vilayphiou
Create generative fugues
File:Fugue 01 20110608.oggFile:Fugue 04 20110530.oggFile:Fugue 01-octave4 20110608.ogg
#!/usr/bin/env python
import random
fugue = {}
fugue = {
"/l2/d4":["/l2/a4", "/l2/c+4"],
"/l2/a4": ["/l2/f4"],
"/l2/f4": ["/l2/d4", "/l8/f4"],
"/l2/c+4": ["/l4/d4"],
"/l4/d4": ["/l4/e4"],
"/l4/e4": ["/l2/f4"],
"/l8/f4": ["/l8/g4","/l8/e4"],
"/l8/g4": ["/l8/f4"],
"/l8/e4": ["/l2/d4"]
}
#here we print / place the timidity structure
print """
@head {
$time_sig 4/4
$tempo 220
}
@body {
@channel 1 {
$patch 1
$octave 4
$length 16
"""
tone = "/l2/d4"
for x in range(64):
print tone
#this new variable tone is overwriting the old tone! => variable as empty bowl symbolism
tone = random.choice(fugue[tone])
#here we print / place the timidity structure
print """
}
}
"""
Users: midge
Source: Natasa Siencnik User:Natasa_Siencnik/prototyping/markov
Use open clip art and a loop to make a book of patterns
print """<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
width="200px" height="50px"
viewBox="0 0 200 50"
zoomAndPan="disable" >"""
# vertical amount of elements
veramo = 20
# ydist increases the vertical distance
ydist = 10
for z in range(veramo):
transf = "transform=\"translate({0},{1})\">".format(0,z*ydist)
print "<g " + transf
# horizontal amount of elements
horamo = 20
# ydist2 increases the vertical distance
ydist2 = 10
# xdist increases the horizontal distance
xdist2 = 10
for x in range(horamo):
transf = "transform=\"translate({0},{1})\"".format(x*xdist,x*ydist2)
print "<rect " + transf + """ x="0" y="0" width="10" height="10" fill="black" />
print "</g>"
print "</svg>"
Source: Silvio Lorusso, A man of many parts
Generating Outline Fonts with 5 Lines of Code
import fontforge
font = fontforge.open('douar.sfd')
for glyph in font:
font[glyph].stroke('circular', 30, 'square', 'bevel', ('cleanup',))
font.generate('douar-new.ttf')
Uses: FontForge
Source: Ricardo Lafuente, http://blog.manufacturaindependente.org/2011/02/generating-outline-fonts-with-5-lines-of-code/
Create interactive vector graphics
http://www.stuartaxon.com/2013/03/20/natural-movement-in-python-part-3-particles/#more-331
Uses: Shoebot (http://shoebot.net/)
Source: Stuart Axon and Ricardo Lafuente
Other Modules to check out...
- Manipulate images with PIL
- use reportlab to generate a paginated PDF
- use subprocess to run FFMPEG and scrape audio/video info using a regular expression
- use html5lib to scrape HTML
- use glob to process a folder full of files
- use urllib2, urlparse and html5lib to spider HTML
- use json to parse results from web APIs
- use optparse to make a self-documenting command line utility
- use random to work with some noise
- use datetime to work easily with dates and intervals
- use OSC to talk to control other (realtime) programs
- use uuid to generate unique ids
- use zipfile
- use xml to read and extract data from an XML source
- generating an epub...