Cookbook
Input/Output
Load CSV table (.py)
import csv
def loadTable(filePath, delimiter, quotechar):
with open(filePath, mode='r', encoding='utf-8') as csvFile:
tableReader = csv.reader(csvFile, delimiter=delimiter, quotechar=quotechar)
return list(tableReader)
if __name__ == '__main__':
table = loadTable('table.csv', '\t', '|')
# [['city', 'country'], ['Shanghai', 'China'], ['New York', 'United States'], ['Roma', 'Italy']]
Load CSV table with keys (.py)
import csv
def loadTableWithKeys(filePath, delimiter, quotechar):
with open(filePath, mode='r', encoding='utf-8') as csvFile:
tableReader = csv.DictReader(csvFile, delimiter=delimiter, quotechar=quotechar)
return list(tableReader)
if __name__ == '__main__':
table = loadTableWithKeys('table.csv', '\t', '|')
# [
# OrderedDict([('city', 'Shanghai'), ('country', 'China')]),
# OrderedDict([('city', 'New York'), ('country', 'United States')]),
# OrderedDict([('city', 'Roma'), ('country', 'Italy')])
# ]
Write csv table (.py)
import csv
def writeTable(data, fileName, delimiter):
with open(fileName, mode='w', encoding='utf-8') as csvFile:
tableWriter = csv.writer(csvFile, delimiter='\t')
tableWriter.writerows(data)
if __name__ == '__main__':
data = [
('city', 'country'),
('Shanghai', 'China'),
('New York', 'United States'),
('Roma', 'Italy')
]
writeTable(data, 'table.csv', delimiter='\t')
read lines from text file (.py)
def readStringsFromFile(fileName):
with open(fileName, mode='r', encoding='utf-8') as txtFile:
return [ll.rstrip() for ll in txtFile.readlines()]
if __name__ == '__main__':
words = readStringsFromFile('words.txt')
# ['immediatamente', 'realmente', 'estremamente', 'solennemente', 'precedentemente', 'sicuramente', 'magnificamente', 'geneticamente', 'originariamente', 'seriamente', 'ingiustamente', 'ovviamente', 'sessualmente', 'particolarmente', 'indipendentemente']
write lines to text file (.py)
def writeStringsToFile(fileName, strings):
with open(fileName, mode='w', encoding='utf-8') as txtFile:
for eachStr in strings:
txtFile.write(f'{eachStr}\n')
if __name__ == '__main__':
words = ['immediatamente', 'realmente', 'estremamente', 'solennemente', 'precedentemente', 'sicuramente', 'magnificamente', 'geneticamente', 'originariamente', 'seriamente', 'ingiustamente', 'ovviamente', 'sessualmente', 'particolarmente', 'indipendentemente']
writeStringsToFile('words.txt', words)
Collecting files from a folder (.py)
from os.path import join, isfile
from os import listdir
def collectFilesPaths(folder, extension=''):
"""hidden files (starting with a dot) are filtered out"""
paths = []
for eachFileName in [nn for nn in listdir(folder) if not nn.startswith('.')]:
eachPath = join(folder, eachFileName)
if isfile(eachPath) and eachPath.endswith(extension):
paths.append(eachPath)
return paths
if __name__ == '__main__':
filePaths = collectFilesPaths('someFolder')
Collecting folders from a folder (.py)
from os.path import join, isdir
from os import listdir
def collectSubFolders(folder):
return [join(folder, sub)
for sub in listdir(folder)
if isdir(join(folder, sub))]
if __name__ == '__main__':
subFolders = collectSubFolders('someFolder')
Cleaning a folder (.py)
from shutil import rmtree
from os import mkdir
from os.path import exists
def clean(folder):
if exists(folder):
rmtree(folder)
mkdir(folder)
if __name__ == '__main__':
clean('someFolder')
Deleting file with a specific extension from a folder (.py)
from os import remove, listdir
def deleteFilesFromFolder(folder, extension):
paths = [nn for nn in listdir(folder) if nn.endswith(extension)]
for eachP in paths:
remove(eachP)
if __name__ == '__main__':
deleteFilesFromFolder('someFolder', '.jpg')
Colors
Converting hexadecimal to RGB (255) (.py)
def HEX2RGB(hexColor):
offset = 1 if hexColor.startswith('#') else 0
rr = int(hexColor[offset:offset+2], 16)
gg = int(hexColor[offset+2:offset+4], 16)
bb = int(hexColor[offset+4:], 16)
return rr, gg, bb
if __name__ == '__main__':
rgbColor = HEX2RGB('#DC7814')
print(rgbColor)
Converting RGB (255) to hexadecimal (.py)
def RGB2HEX(rr, gg, bb):
return f'#{rr:0>2X}{gg:0>2X}{bb:0>2X}'
if __name__ == '__main__':
hexColor = RGB2HEX(220, 120, 20)
# '#DC7814'
Interpolating RGB colors (.py)
def lerp(aa, bb, factor):
return aa + (bb - aa) * factor
def lerpRGB(colorOne, colorTwo, factor):
rr = lerp(colorOne[0], colorTwo[0], factor)
gg = lerp(colorOne[1], colorTwo[1], factor)
bb = lerp(colorOne[2], colorTwo[2], factor)
return rr, gg, bb
if __name__ == '__main__':
red = 255, 0, 0
blue = 0, 0, 255
gradient = lerpRGB(red, blue, .5)
# (127.5, 0.0, 127.5)
red = 1, 0, 0
blue = 0, 0, 1
gradient = lerpRGB(red, blue, .5)
# (0.5, 0.0, 0.5)
Calculation
Interpolating single value (.py)
def lerp(aa, bb, factor):
return aa + (bb - aa) * factor
if __name__ == '__main__':
mid = lerp(10, 20, .5)
# 15.0
Extracting factor from extremes and inner value (.py)
def getFactor(aa, bb, innerValue):
return (innerValue-aa)/(bb-aa)
if __name__ == '__main__':
factor = getFactor(10, 20, 15)
# 0.5
Mapping value to a new range of extremes (.py)
def lerp(aa, bb, factor):
return aa + (bb - aa) * factor
def getFactor(aa, bb, innerValue):
return (innerValue-aa)/(bb-aa)
def remapValue(val, pMin, pMax, nMin, nMax):
factor = getFactor(pMin, pMax, val)
nVal = lerp(nMin, nMax, factor)
return nVal
if __name__ == '__main__':
newVal = remapValue(2, 0, 10, -1, +1)
# -0.6
UFO Data
flat kerning (.py)
### Modules
from fontParts.world import OpenFont
### Functions
if __name__ == '__main__':
ff = OpenFont('someFont.ufo')
flatKerning = ff.getFlatKerning()
print(flatKerning)
# {('A', 'V'): -80, ('Agrave', 'V'): -80, ('Aacute', 'V'): -80}
Geometry
Calc angle from two points (.py)
from math import atan2, degrees
def calcAngle(pt1, pt2, mode='degrees'):
assert mode == 'degrees' or mode == 'radians'
ang = atan2((pt2[1] - pt1[1]), (pt2[0] - pt1[0]))
if mode == 'radians':
return ang
else:
return degrees(ang)
if __name__ == '__main__':
angle = calcAngle((50, 50), (10, 80), mode='degrees')
# 143.13010235415598
angle = calcAngle((50, 50), (10, 80), mode='radians')
# 2.498091544796509
Calc distance between two points (.py)
from math import sqrt
def calcDistance(pt1, pt2):
return sqrt((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2)
if __name__ == '__main__':
dist = calcDistance((20, 30), (100, 80))
# 94.33981132056604

closest point (.py)
from math import sqrt
RADIUS = 5
def calcDistance(pt1, pt2):
return sqrt((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2)
def closestPoint(refPt, points):
return min(points, key=lambda x: calcDistance(refPt, x))
def drawPt(point):
oval(point[0]-RADIUS, point[1]-RADIUS, RADIUS*2, RADIUS*2)
if __name__ == '__main__':
points = [(311, 168), (204, 320), (134, 339), (185, 23), (0, 171), (227, 139), (172, 372), (388, 231), (142, 169), (167, 102), (368, 0), (40, 97), (166, 206), (263, 27), (157, 53), (5, 168), (285, 249), (34, 228), (174, 86), (55, 271), (350, 240), (238, 71), (56, 154), (116, 297), (165, 122), (297, 296), (392, 386), (124, 50), (193, 58), (389, 117), (387, 67), (353, 260), (245, 332), (133, 155), (73, 165), (231, 192), (89, 238), (300, 356), (31, 158), (100, 375), (12, 54), (358, 136), (179, 123), (293, 207), (59, 331), (377, 309), (50, 47), (277, 243), (117, 2), (18, 189)]
refPt = 95, 180
closest = closestPoint(refPt, points)
newPage(400, 400)
fill(0)
for eachPt in points:
if eachPt != closest:
drawPt(eachPt)
fill(1, 0, 0)
drawPt(closest)
fill(0, 1, 0)
drawPt(refPt)
Curves

oval (.py)
from math import sin, cos, radians
def ovalCurve(wdt, hgt):
points = []
for angle in range(360):
xx = sin(radians(angle)) * wdt/2
yy = cos(radians(angle)) * hgt/2
points.append((xx, yy))
return points
if __name__ == '__main__':
points = ovalCurve(400, 150)
newPage(500, 500)
translate(width()*.5, height()*.5)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=True)

lissajous (.py)
from math import pi, sin
def calcLissajous(ptsAmount, amps, angFreqs, angPhases):
ampX, ampY = amps
angFreqX, angFreqY = angFreqs
angPhaseX, angPhaseY = angPhases
points = []
for ii in range(0, ptsAmount):
tt = ii*pi*2/ptsAmount
xx = ampX * sin(angFreqX * tt + angPhaseX)
yy = ampY * sin(angFreqY * tt + angPhaseY)
points.append((xx, yy))
return points
if __name__ == '__main__':
pointsAmount = 500
ampX = ampY = 200
angFreqX = 3
angFreqY = 1
angPhaseX = pi
angPhaseY = pi/2
lissajousPoints = calcLissajous(pointsAmount, (ampX, ampY), (angFreqX, angFreqY), (angPhaseX, angPhaseY))
newPage(500, 500)
translate(width()/2, height()/2)
stroke(0)
strokeWidth(10)
fill(None)
polygon(*lissajousPoints)

welch (.py)
def welchCurve(aa, wdt):
points = []
for xx in range(-wdt//2, wdt//2+1):
yy = 1 - (xx**2 / aa**2)
points.append((xx, yy))
return points
if __name__ == '__main__':
points = welchCurve(5, 200)
newPage(500, 500)
translate(width()*.5, height()*.9)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)

bartlett (.py)
def bartlettCurve(aa, wdt):
points = []
for xx in range(-wdt//2, wdt//2):
yy = 1-(abs(xx))/aa
points.append((xx, yy))
return points
if __name__ == '__main__':
points = bartlettCurve(.5, 400)
newPage(500, 500)
translate(width()*.5, height()*.9)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)

sine (.py)
from math import sin, radians
def sineCurve(wdt, radius):
points = []
for xx in range(0, wdt):
yy = sin(radians(xx*(360/wdt))) * radius
points.append((xx, yy))
return points
if __name__ == '__main__':
points = sineCurve(450, 200)
newPage(500, 500)
translate(25, height()*.5)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)

cosine (.py)
from math import cos, radians
def cosineCurve(wdt, radius):
points = []
for xx in range(0, wdt):
yy = cos(radians(xx*(360/wdt))) * radius
points.append((xx, yy))
return points
if __name__ == '__main__':
points = cosineCurve(450, 200)
newPage(500, 500)
translate(25, height()*.5)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)

square root (.py)
from math import sqrt
def sqRootCurve(wdt, yScale):
points = []
for xx in range(0, wdt):
yy = sqrt(xx)
points.append((xx, yy*yScale))
return points
if __name__ == '__main__':
points = sqRootCurve(wdt=450, yScale=12)
newPage(500, 500)
translate(25, 100)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)

quadratic (.py)
def quadraticCurve(wdt, aa, bb):
points = []
for xx in range(-wdt//2, wdt//2):
yy = (aa*xx)**2 + bb*xx
points.append((xx, yy))
return points
if __name__ == '__main__':
points = quadraticCurve(wdt=300, aa=.13, bb=0)
newPage(500, 500)
translate(width()/2, 50)
stroke(0)
fill(None)
strokeWidth(10)
polygon(*points, close=False)
Drawing
Draw a UFO Glyph Object (.py)
import fontParts.world as fp
def drawGlyph(glyph):
"""
from https://gist.github.com/roberto-arista/e916e3c9c0ab445b2bfb714af80dab6b#gistcomment-2828756
thanks Frederik!
"""
glyphPath = BezierPath(glyphSet=glyph.layer)
glyph.draw(glyphPath)
drawPath(glyphPath)
if __name__ == '__main__':
myFont = fp.OpenFont('someFont.ufo')
drawGlyph(myFont['a'])

Draw a regular polygon (.py)
from math import cos, sin, radians
def regularPolygon(sides, radius):
vertices = []
sliceAngle = 360/sides
for ii in range(sides):
xx = cos(radians(ii*sliceAngle)) * radius
yy = sin(radians(ii*sliceAngle)) * radius
vertices.append((xx, yy))
polygon(*vertices)
if __name__ == '__main__':
newPage(500, 500)
translate(width()/2, height()/2)
stroke(0)
fill(None)
strokeWidth(10)
regularPolygon(sides=8, radius=200)

Draw a grid (.py)
def drawGrid(hElems, vElems, cellSize):
"""
hElems = horizontal elements
vElems = vertical elements
"""
for jj in range(vElems):
with savedState():
for ii in range(hElems):
rect(0, 0, cellSize, cellSize)
translate(cellSize, 0)
translate(0, cellSize)
if __name__ == '__main__':
newPage(400, 400)
stroke(0)
strokeWidth(10)
fill(None)
translate(60, 60)
drawGrid(8, 8, 30)

background (.py)
WHITE = 1, 1, 1
def background(clr=WHITE):
fill(*clr)
rect(0, 0, width(), height())
if __name__ == '__main__':
newPage(400, 400)
pink = 255/255, 51/255, 102/255
background(clr=pink)
Text
retrieve name from unicode database (.py)
import unicodedata
def getUnicodeName(char):
"""Provide a character and I will return a description
if available in the Unicode database"""
try:
return unicodedata.name(char)
except ValueError:
return ''
if __name__ == '__main__':
name = getUnicodeName('ü')
# LATIN SMALL LETTER U WITH DIAERESIS