Krawleb-Book
by any other name — experiments in synonymous corruption
PDF (600 kb): ./wp-content/uploads/2016/10/krawleb-book.pdf
My book is a collection of 14 pieces of writing that have been transformed and corrupted through a synonym-swapping algorithm. The source text comes from monologues, song lyrics, and poems, each printed in its original form, then recursively synonym-swapped 5 times. The resulting text is a twisted, often out of context, but somewhat related derivative of the original concepts. Inspired by the famous Shakespeare passage “a rose by any other name would smell as sweet”, I explored what happened when we use ‘other names’ for things to the point of destruction.
The software pipeline for this project begins with a Python for Processing program that parses .txt files of both the original source content and a large .txt thesaurus. The program looks at each word, identifies words with synonyms in the thesaurus, and then replaces them. This data is then written to CSV, tagging each word that has been swapped each iteration, as well as tagging ends of lines to preserve the line breaks.
These CSVs are then fed into a Basil.js program that iterates over an array of CSV files, printing the text of each iteration on a new page, and italicizing each swapped word in each recursive iteration.
Ultimately, this project was an interesting experiment, but was a bit unpolished and buggy as I began to run out of time as the deadline approached. Some words are swapped into non-english synonyms, and some synonyms appear nonsensical or unrelated. However, in there chaos there are moments of beauty. Sometimes the text is morphed into new and humorous or beautiful new ideas through the process.
Additionally, the visual form is very minimal, which I would have liked to develop more, but the Basil.js workflow is rather unfriendly to rapid iteration, so I kept things as clean as possible for the final. That being said, I do like the austerity of the small undecorated text on otherwise blank pages.
Github here
Code below:
import random
from random import randrange
import re
import csv
import sys
textName = 'loveCallsUs'
source = open('texts/'+textName+'.txt', 'r')
ts = open('texts/synAntNoHyph.txt', 'r')
ts2 = open('texts/MobyTs.txt', 'r')
export = open('export.txt', 'w')
csvExport = open('exports/'+textName+'.csv', 'wb')
def setup():
size(100, 100)
rawTs = ts.readlines()
rawTs2 = ts2.readlines()
rawlines = source.readlines()
lines = []
iterations = []
numIterations = 5
for raw in range(len(rawlines)):
aLine = rawlines[raw].split()
lines.append(aLine)
#initialize csv with source
writer = csv.writer(csvExport)
writer.writerow( ('word', 'isNew', 'iteration', 'endLine') )
print lines
for x in range(len(lines)):
isEnd = 0 #is it the end of a line?
for y in range(len(lines[x])):
word = lines[x][y]
if y == len(lines[x])-1: #adjusted for index
isEnd = 1
writer.writerow( (word, '0' , '0' , isEnd ) )
#first, print original text
for line in lines:
joined = ' '.join(line)
print>>export, joined
print>>export, '\n'
for z in range(numIterations):
# Find Synonyms
for i in range(len(lines)): # loop over lines
for j in range(len(lines[i])): # loop through words
currentWord = re.sub(r'[^\w\s]','',lines[i][j]).title() #remove punctuation
# print currentWord
found = False #reset found (in first thesaurus)
for k in range(len(rawTs)): # loop through ts (first thesaurus)
if random.random() > 0.0:
if rawTs[k].startswith(currentWord+'.'): #if it's a period, grab the word right after
# print rawTs[k]
index = random.randint(1,len(rawTs[k].split())-1)
synonym = rawTs[k].split()[index]
synonym = str('_'+synonym)
found = True
if rawTs[k].startswith(currentWord+','): #if it's a comma, grab the second word
# print rawTs[k]
if len(rawTs[k].split())-1 >= 2:
index = random.randint(2,len(rawTs[k].split())-1)
else:
index = 1
synonym = rawTs[k].split()[index]
synonym = str('_'+synonym)
found = True
if found == True:
if j > 0:
synonym = synonym.lower()
synonym = re.sub(r'[^\w\s]','',synonym)
synonym = synonym.strip(';')
lines[i][j] = synonym
#write to CSV
print lines
for x in range(len(lines)):
for y in range(len(lines[x])):
isSyn = 0 #is it a synonym?
isEnd = 0 #is it the end of a line?
if lines[x][y].startswith('_'): #detect if its a synonym
lines[x][y] = lines[x][y][1:] #strip synonym identifier
isSyn = 1
if y == len(lines[x])-1: #adjusted for index
isEnd = 1
word = lines[x][y]
writer.writerow( (word, isSyn , (z+1) , isEnd) )
# print word
# print str(lines[x])
joined = ' '.join(lines[x])
print>>export, joined
print>>export, '\n'
iterations.append(lines)
noStroke()
fill(0,255,0)
ellipse(width/2,height/2,80,80)
csvExport.close()
Basil/InDesign code:
#includepath "~/Documents/;%USERPROFILE%Documents";
#include "../../../bundle/basil.js";
var csvArray = [
'rose.csv',
'hammy.csv',
'desire.csv',
'leisure.csv',
'enigmas.csv',
'israfil.csv',
'tooLate.csv',
'aRitual.csv',
'folkMeta.csv',
'sasquach.csv',
'souvenir.csv',
'gazzillion.csv',
'loveCallsUs.csv',
'spottieOttie.csv' ];
var csvData;
var genCover = false;
var reset = true;
//--------------------------------------------------------
function setup() {
// Clear the document at the very start.
if (reset == true){
b.clear (b.doc());
}
if (genCover == true){
// Make a title page.
b.fill(0,0,0);
b.textSize(24);
b.textFont("Helvetica","Light");
b.textAlign(Justification.LEFT_ALIGN);
b.text("By Any Other Name", 72,72,360,36);
b.text("Kaleb Crawford, Fall 2016", 72,108,360,36);
} //end Gen Cover
//72 points in an inch
var margin = 72
var titleX = 72;
var titleY = 72;
var titleW = 72;
var titleH = 72;
var passageX = margin + 18;
var passageY = margin * 2;
var passageW = margin * 3;
var passageH = b.height-margin*2;
var innerText;
var mainFrame;
var tempFrame;
//////////////////////CSV Array Loop//////////////////////
for (var texts = 0; texts < csvArray.length; texts++){
var csvString = b.loadString(csvArray[texts]);
csvData = b.CSV.decode( csvString );
b.println("Number of elements in CSV: "+csvData.length);
var totalIterations = parseInt(csvData[csvData.length-1].iteration);
var currentIteration = 0;
////////////////////// Iterations Loop////////////////////
for (var i = 0; i <= totalIterations; i++) {
b.addPage(); // Create the next page.
//Create the frame
b.fill(0);
b.textSize(8);
b.textFont("Garamond","Regular");
b.textAlign(Justification.LEFT_ALIGN, VerticalJustification.TOP_ALIGN );
mainFrame = b.text("", passageX, passageY, passageW, passageH);
currentIteration = i;
innerText = ''; //initialize inner text
////////////////////Word Loop///////////////////
for (var l = 0; l < csvData.length ; l ++ ){
if (csvData[l].iteration == currentIteration){
innerText = csvData[l].word+" ";
if (csvData[l].isNew == 1){
b.textFont("Garamond","Italic");
}
else{ b.textFont("Garamond","Regular"); }
if (csvData[l].endLine == 1){
innerText += "\n";
}
tempFrame = b.text(innerText, 0, 0, 100, 100);
// mainFrame.contents += tempFrame.contents;
tempFrame.paragraphs[0].move(LocationOptions.after,mainFrame.insertionPoints[-1]);
tempFrame.remove();
} //end if currentIteration check
} // end line loop
b.println('text '+(texts+1)+" iteration "+currentIteration);
} //end iteration loop
}//end csvArray loop
} // end setup
// This makes it all happen:
b.go();