Browse Source

updating the cross-reader for the CG exhibition in Eindhoven (only English, some layout changes, seperate 'about' pages, added TF/IDF/TF-IDF value inspection lists)

master
manetta 5 years ago
parent
commit
be4f979e91
  1. 7
      README.md
  2. 46978
      index.json
  3. 45
      readings.py
  4. 52
      start.py
  5. 399
      static/css/stylesheet.css
  6. 20
      static/html/1912_The-Manifesto-of-Futurist-Woman_Valentine-de-Saintpoint.html
  7. 29
      static/html/1967_SCUM_Manifesto.html
  8. BIN
      static/images/epson.png
  9. 170
      templates/en/about.html
  10. 85
      templates/en/base.html
  11. 61
      templates/en/colophon.html
  12. 185
      templates/en/cross-readings.html
  13. 31
      templates/en/index.html
  14. 11
      templates/en/list.html
  15. 2
      templates/en/manifesto.html
  16. 14
      templates/en/mapping.html
  17. 59
      templates/en/mappings-name.html
  18. 17
      templates/en/mappings.html
  19. 27
      templates/en/ordered.html
  20. 103
      templates/en/results.html
  21. 170
      templates/fr/about.html
  22. 96
      templates/fr/base.html
  23. 41
      templates/fr/index.html
  24. 17
      templates/fr/manifesto.html
  25. 58
      templates/fr/mappings-name.html
  26. 27
      templates/fr/ordered.html
  27. 125
      templates/fr/results.html
  28. 26
      tfidf.py
  29. 52
      words.txt

7
README.md

@ -2,12 +2,9 @@
<https://cross.virtualprivateserver.space>
This is the code for a cyber/technofeminist cross-reader, developed in the context of the exhibition Computer Grrrls in Paris (March - July 2019). - <https://gaite-lyrique.net/evenement/computer-grrrls>
*A cross-reading allows for a specific type of reading that does not follow a linear order, but follows a self-chosen path. Reading becomes an act of creating relations and threading connections, reading across different domains.*
*This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool. Reading across a collection of manifestos, while reading the algorithm that is used to do so.*
This is the code for a cyber/technofeminist cross-reader, developed in the context of the exhibition Computer Grrrls in Paris (March - July 2019) — <https://gaite-lyrique.net/evenement/computer-grrrls> — and on display again during the Computer Grrrls exhibition in Eindhoven (July - October 2019) — <http://mu.nl/nl/exhibitions/computer-grrrls> —.
*This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool.*
## Installation

46978
index.json

File diff suppressed because it is too large

45
readings.py

@ -14,7 +14,6 @@ import tfidf
# TF-IDF visualisation multiplier
multiplier = 25000
def load_index():
if os.path.isfile('index.json') == False:
tfidf.create_index()
@ -45,7 +44,6 @@ def request_mappings_all():
words.append([tfidf, word])
words.sort(reverse=True)
mappings[manifesto] = words
# pp.pprint(mappings)
return mappings
def request_mappings(name):
@ -62,7 +60,6 @@ def request_mappings(name):
words.append([word, tfidf])
sentences.append(words)
mappings[manifesto] = sentences
# pp.pprint(mappings)
return mappings, filenames
def insert_query_highlight(query, sentence, r, g, b):
@ -73,27 +70,13 @@ def insert_query_highlight(query, sentence, r, g, b):
sentence = re.sub(pattern, ' <strong class="query" style="color:rgba({r},{g},{b},1); background-image: radial-gradient(ellipse, rgba({r},{g},{b},0.4), rgba({r},{g},{b},0.2), transparent, transparent);">{match}</strong> '.format(match=match, r=r, b=b, g=g), sentence, flags=re.IGNORECASE)
return sentence
def insert_suggestion_links(query, sentence):
# insert further reading links
for suggestion in open('words.txt','r').readlines():
suggestion = suggestion.replace('\n', '').strip()
if suggestion:
if suggestion != query:
pattern = r'[\s\W\_]'+suggestion+r'[\s\W\_]|^'+suggestion+'|'+suggestion+'$'
match = re.search(pattern, sentence, flags=re.IGNORECASE)
if match:
match = match.group()
match = match.replace(suggestion, '<a href="?q={0}">{0}</a>'.format(suggestion))
sentence = re.sub(pattern, '<strong>{}</strong>'.format(match), sentence, flags=re.IGNORECASE)
return sentence
def generate_analytics(query, results, index):
analytics = {}
mappings = request_mappings_all()
for manifesto, items in mappings.items():
if manifesto == results[0]['filename']:
analytics['mappings'] = mappings[manifesto]
if results:
manifesto_of_first_result = results[0]['filename']
tfidf_results = index[manifesto_of_first_result]['tfidf']
analytics['suggestions'] = sorted(tfidf_results.items(), key=lambda kv: kv[1], reverse=True)
# Stemmer (very similar words)
analytics['stemmer'] = []
@ -102,23 +85,20 @@ def generate_analytics(query, results, index):
for manifesto, _ in index.items():
words = index[manifesto]['tfidf'].keys()
bases = [[porter.stem(word), word] for word in words]
# print('Stemmer bases', bases)
for base, word in bases:
if base == basequery:
analytics['stemmer'].append(word)
analytics['stemmer'] = set(analytics['stemmer'])
if query in analytics['stemmer']:
analytics['stemmer'].remove(query)
# print('Stemmer:', matches)
print('*analytics information returned*')
# pp.pprint(analytics)
return analytics
def request_results(query):
print('\n*results request started*')
query = query.strip().lower()
print('Query:', query)
print('\n*results request started*')
index = load_index()
filenames = [document for document, _ in index.items()]
@ -147,14 +127,12 @@ def request_results(query):
order.append(match)
break
order.sort(reverse=True)
# print('Order:', order)
# Loop through the sorted matches
# and add all the data that is needed
# (sentences, tfidf value, manifesto name)
x = 0
for tfidf, manifesto in order:
# print('\n---', manifesto, '---')
results[x] = {}
results[x]['name'] = index[manifesto]['name'] # nicely readable name
results[x]['filename'] = manifesto
@ -176,7 +154,6 @@ def request_results(query):
# Append sentence to final set of matching results
results[x]['matches'].append(sentence)
# print('Matching sentence:', sentence.replace('\n', ' '))
# Transform sentence into an HTML elements
html = insert_query_highlight(query, sentence, r, g, b)
@ -187,14 +164,10 @@ def request_results(query):
break # Append sentence only once
x += 1
# pp.pprint(results)
print('\n*results returned*')
# Add analytics
if results.keys():
analytics = generate_analytics(query, results, index)
else:
analytics = False
# pp.pprint(analytics)
analytics = generate_analytics(query, results, index)
return results, filenames, analytics
if __name__ == '__main__':
request_results('personal')

52
start.py

@ -26,7 +26,7 @@ APP.jinja_env.globals.update(get_random=get_random)
@APP.route('/', methods=['GET', 'POST'])
def index():
return redirect('/fr/')
return redirect('/en/')
@APP.route('/<lang>/', methods=['GET', 'POST'])
def index_lang(lang):
@ -45,7 +45,7 @@ def index_lang(lang):
if printer.connected == True:
connection = 'connected'
else:
connection = 'connected'
connection = 'disconnected'
if request.args.get('q', ''):
results, filenames, analytics = readings.request_results(query)
@ -60,24 +60,28 @@ def index_lang(lang):
else:
index = readings.load_index()
filenames = [manifesto for manifesto, _ in index.items()]
suggestions = open('words.txt', 'r').readlines()
mappings_top = open('tfidf.top50.txt', 'r').readlines()
return flask.render_template(lang+'/index.html', filenames=filenames, suggestions=suggestions, mappings=mappings_top, lang=lang)
return flask.render_template(lang+'/index.html', filenames=filenames, mappings=mappings_top, lang=lang)
@APP.route('/<lang>/about', methods=['GET', 'POST'])
def about(lang):
@APP.route('/<lang>/cross-readings', methods=['GET', 'POST'])
def crossreadings(lang):
"""
Displays the about page accessible at '/<lang>/about'.
Displays the cross-readings page accessible at '/<lang>/cross-readings'.
"""
index = readings.load_index()
filenames = sorted([manifesto for manifesto, _ in index.items()])
return flask.render_template(lang+'/about.html', filenames=filenames, lang=lang)
return flask.render_template(lang+'/cross-readings.html', lang=lang)
@APP.route('/<lang>/colophon', methods=['GET', 'POST'])
def colophon(lang):
"""
Displays the colophon page accessible at '/<lang>/colophon'.
"""
return flask.render_template(lang+'/colophon.html', lang=lang)
@APP.route('/<lang>/manifesto/<name>', methods=['GET', 'POST'])
def manifesto(lang, name):
"""
Displays the page accessible at '/<lang>/manifesto/<name>'.
Here, an iframe is shown with the manifesto in its own context.
It shows the original text of the manifesto in plain text.
"""
index = readings.load_index()
filenames = sorted([manifesto for manifesto, _ in index.items()])
@ -85,24 +89,24 @@ def manifesto(lang, name):
link = manifestos[name]
return flask.render_template(lang+'/manifesto.html', filenames=filenames, name=name, manifesto=manifesto, link=link, lang=lang)
@APP.route('/<lang>/mappings', methods=['GET', 'POST'])
def contrast_mappings(lang):
"""
Displays the page accessible at '/<lang>/mappings'.
A TF-IDF visualisation is displayed,
using the TF-IDF values as font-size.
"""
mappings, filenames = readings.request_mappings_all()
return flask.render_template(lang+'/mappings.html', filenames=filenames, mappings=mappings, lang=lang)
@APP.route('/<lang>/mappings/<name>', methods=['GET', 'POST'])
@APP.route('/<lang>/mapping/<name>', methods=['GET', 'POST'])
def contrast_mappings_name(lang, name):
"""
Displays the page accessible at '/<lang>/mappings/<name>'.
A TF-IDF visualisation is displayed from the specific manifesto, using the TF-IDF values as font-size.
"""
mappings, filenames = readings.request_mappings(name)
return flask.render_template(lang+'/mappings-name.html', filenames=filenames, mappings=mappings[name], manifesto=name, lang=lang)
return flask.render_template(lang+'/mapping.html', filenames=filenames, mappings=mappings[name], manifesto=name, lang=lang)
@APP.route('/<lang>/list/<list_type>/<filename>', methods=['GET', 'POST'])
def render_list_for_document(lang, list_type, filename):
"""
Show list of (TF / IDF / TF-IDF) values of one document.
"""
index = readings.load_index()
filenames = sorted([document for document, _ in index.items()])
values_list = [(value, word) for word, value in index[filename][list_type].items()]
return flask.render_template(lang+'/list.html', filenames=filenames, list=values_list, list_type=list_type, filename=filename, lang=lang)
@APP.route('/favicon.ico')
def favicon():
@ -111,5 +115,5 @@ def favicon():
if __name__ == '__main__':
if not 'index.json' in os.listdir('.'):
tfidf.create_index()
APP.debug=True
# APP.debug=True
APP.run()

399
static/css/stylesheet.css

@ -16,6 +16,12 @@
font-style: normal;
font-weight: normal;
}
@font-face{
font-family: 'fluxisch';
src:url('fonts/FluxischElse-Bold.woff');
font-style: normal;
font-weight: normal;
}
/* animations */
@keyframes blink {
@ -36,6 +42,18 @@ body{
overflow-x: hidden;
z-index: -1;
}
body.black,
body.black a{
background-color: rgb(5,5,5);
color:white;
}
body.black #logo a{
-webkit-text-stroke: 2px white;
}
body.black #txt-list{
display: none;
}
h1, h2, h3{
font-size: 16px;
font-weight: normal;
@ -55,7 +73,7 @@ a, a:active, a:hover{
margin:0;
}
sup, small{
font-size: 100%;
/*font-size: 100%;*/
}
p{
margin:0;
@ -88,83 +106,146 @@ i{
font-size: 85%;
}
/* txt list on the right */
#txt-list{
position: absolute;
width:170px;
right: 0px;
top:-12px;
margin:0 20px 20px 20px;
font-size: 16px;
line-height: 1.4;
z-index: -1;
}
#txt-list ul{
margin:1em 0 0 0;
padding:0;
}
#txt-list ul li{
margin:0;
padding:0 0 10px 0;
text-indent: -50px;
list-style: none;
}
#txt-list ul li small{
margin-right: -0.35em;
}
#txt-list li a.contrast,
a.contrast{
border: 0;
}
#wrapper{
position: absolute;
z-index: -1;
width: calc(100% - 400px);
min-width: 600px;
margin:10px 0 20px 0;
margin:0 0 20px 0;
font-family: mono, sans-serif;
font-size: 16px;
line-height: 1.65;
letter-spacing: -0.01em;
}
#nav-wrapper{
position: relative;
width: 100%;
left:50px;
z-index: 0;
margin:0;
#notes{
position: fixed;
width: calc(100% - 150px);
top:0;
left:0;
padding:3px 75px 7px;
color:white;
background-color: black;
}
#nav{
display: inline-block;
}
#logo a{
font-family: 'script';
font-size: 64px;
/*font-weight: bold;*/
-webkit-text-stroke: 2px black;
line-height: 1;
letter-spacing: -0.035em;
border: 0;
}
#search{
width: 250px;
position: relative;
margin:20px 20px 20px 0;
line-height: 72px;
vertical-align: top;
}
#search input#query{
width: 100%;
height: 40px;
padding:0px 10px;
border:1px dotted;
font-family: 'mono';
font-size: 16px;
background-color: #f2f2f3;
}
#search #submit{
position: absolute;
width: 103px;
height: 42px;
right: -140px;
top: 15px;
font-family: 'mono';
font-size: 16px;
text-align: center;
}
#search #submit:hover{
cursor: pointer;
}
#colophon_button{
position: absolute;
top:-1em;
right: -3em;
}
#print img{
#notes #close{
position: fixed;
top: 100px;
right: 300px;
width:100px;
height: auto;
top:0px;
left:10px;
width: auto;
}
#notes a{
color: white;
}
#print.connected{
display: block;
}
#print.disconnected{
display: none;
}
#nav{
position: absolute;
top:0;
right:0;
}
#nav .page-button{
display: inline-block;
padding-right: 5px;
}
#logo a,
#search {
position: relative;
left:50px;
}
#logo a {
border: 0;
font-family: 'script';
font-size: 64px;
-webkit-text-stroke: 2px black;
line-height: 1;
letter-spacing: -0.035em;
}
#search{
position: relative;
display: inline-block;
margin:50px 0;
}
#search input#query{
width: 250px;
height: 40px;
padding:0px 10px;
font-family: 'mono';
font-size: 16px;
}
#search button#submit{
position: relative;
display: inline-block;
padding:0 10px;
}
#search button#submit:after{
content:"search";
}
#search button#submit.searching:after{
content:"searching ...";
}
#search #submit,
#print button {
height: 42px;
font-family: 'mono';
font-size: 16px;
text-align: center;
}
#search #submit:hover,
#print button:hover {
cursor: pointer;
}
#print{
position: relative;
display: inline-block;
margin-left: 50px;
}
#print a{
border:0;
}
#print button:after{
content: "print";
}
#print button.printing:after{
content:"printing ...";
}
#print.connected{
display: inline-block;
}
#print.disconnected{
display: none;
}
#content{
width:100%;
margin:10px 0 10px 0;
@ -172,9 +253,8 @@ i{
strong, strong.query, strong.word, .result{
font-family: 'script';
font-size: 22px;
line-height: 1.5;
line-height: 1.3;
font-weight: bold;
/*-webkit-text-stroke: 1px;*/
letter-spacing: 0em;
}
@ -182,59 +262,54 @@ strong, strong.query, strong.word, .result{
max-width: 600px;
margin:2em 0 4em 10px;
}
.guides li{
margin-bottom: 0.5em;
}
.guides li{
margin-bottom: 0.5em;
}
/* crossing TEXT */
.cross{
position: relative;
max-width: 1000px;
margin-top: 4em;
padding-right: 2em;
clear: both;
}
p.tfidf, p.techfem, .cross p{
position: relative;
margin: 0 0 1.2em 0;
p.tfidf, p.techfem, .cross p{
position: relative;
margin: 0 0 1.2em 0;
}
p.tfidf, p.techfem{
width: calc(50% - 1em);
display: inline-block;
}
p.techfem {
float: left;
margin-right: 2em;
}
p.techfem.sync{
display: block;
clear: both;
}
p.techfem:before{
content:' ◕';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.tfidf{
}
p.tfidf.sync{
display: block;
float: right;
clear: both;
}
p.tfidf, p.techfem{
width: calc(50% - 1em);
display: inline-block;
}
p.techfem {
float: left;
margin-right: 2em;
}
p.techfem.sync{
display: block;
clear: both;
}
p.techfem:before{
content:' ◕';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.tfidf{
}
p.tfidf.sync{
display: block;
float: right;
clear: both;
}
p.tfidf:before{
content:'◧';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.note{
width: 100%;
text-align: center;
padding-bottom: 1em;
}
.cross strong{
line-height: 0;
p.tfidf:before{
content:'◧';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.note{
width: 100%;
text-align: center;
padding-bottom: 1em;
}
.cross strong{
line-height: 0;
}
/* make sure that these blocks don't flow into the cross text blocks*/
#results, #notused, #suggestions, #conditionals, #analytics ,.analytics, .mappings, #colophon{
@ -245,80 +320,34 @@ strong, strong.query, strong.word, .result{
column-gap:10px;
scroll-behavior: smooth;
}
.result{
display: inline-block;
width: 190px;
margin:0;
page-break-inside: avoid;
padding: 0 20px 0 20px;
transition: all 0.2s ease-in-out;
text-align:center;
z-index: 2;
}
.result strong.query{
display: block;
width: 100%;
height: 12em;
padding: 10em 6em 0;
margin:-9.7em 0 -10.5em -6em;
text-align: center;
}
.result .title, .result .ascii{
font-family: 'mono';
font-size: 16px;
font-weight: normal;
-webkit-text-stroke: 0;
}
.result .title{
padding:10px;
margin:3em 0 10px 0;
}
#txt-list{
position: absolute;
width:170px;
right: 0px;
top:-7px;
margin:20px;
font-size: 16px;
line-height: 1.4;
.result{
display: inline-block;
width: 190px;
margin:0;
page-break-inside: avoid;
padding: 0 20px 0 20px;
transition: all 0.2s ease-in-out;
text-align:center;
z-index: 2;
}
#txt-list ul{
margin:1em 0 0 0;
padding:0;
}
#txt-list ul li{
margin:0;
padding:0 0 1em 0;
text-indent: -3.2em;
list-style: none;
}
#txt-list li a.contrast, a.contrast{
border: 0;
}
#colophon{
.result strong.query{
display: block;
width: 100%;
margin: 5em 0;
height: 12em;
padding: 10em 6em 0;
margin:-9.7em 0 -10.5em -6em;
text-align: center;
}
#manifesto_content_wrapper{
position: absolute;
left:0;
width: calc(100% - 100px);
margin:10px 0 0 10px;
padding:20px 0 40px 40px;
.result .title{
font-family: 'mono';
font-size: 16px;
font-weight: normal;
-webkit-text-stroke: 0;
padding:10px;
margin:3em 0 10px 0;
}
.result .title a.contrast{
display: block;
margin-top: 15px;
}
#manifesto_content{
display: block;
position: relative;
overflow-y: auto;
}
iframe#manifesto_content {
width: 100%;
height: calc(100vh - 300px);
border:1px dotted;
background-color: white;
}

20
static/html/1912_The-Manifesto-of-Futurist-Woman_Valentine-de-Saintpoint.html

@ -1,20 +0,0 @@
<h1>The Manifesto of Futurist Woman</h1>
<div>Valentine de Saintpoint</div>
<div>1912</div>
<img src="http://www.arengario.it/wp-content/uploads/2013/02/12-0500-saintpont-0712-donn.jpg">
<!-- https://upload.wikimedia.org/wikipedia/commons/1/14/Valentine_de_Saint-Point_1914_%281%29.jpg -->
<iframe src="https://www.wired.com/2008/11/the-manifesto-1/"></iframe>
<!--
<div>Read the manifesto ...
<br><br>
... in <strong>English</strong>: <a href="https://www.wired.com/2008/11/the-manifesto-1/">https://www.wired.com/2008/11/the-manifesto-1/</a><br>
... en <strong>Francais</strong>: ...
</div> -->

29
static/html/1967_SCUM_Manifesto.html

@ -1,29 +0,0 @@
<h1>SCUM Manifesto</h1>
<div>Valerie Solanas</div>
<div>1967</div>
<iframe src="https://scumwillcorrode.files.wordpress.com/2016/11/scum-1977.pdf"></iframe>
<small>[1977 published version, PDF/EN]</small>
<br><br>
<iframe src="https://web.archive.org/web/20050831003435/http://www.emf.net:80/~estephen/manifesto/aum00110.html"></iframe>
<iframe src="http://1libertaire.free.fr/fem-scum.html"></iframe>
<!--
<div>Read the manifesto ...
<br><br>
... in <strong>English</strong>: <a href="https://web.archive.org/web/20050831003435/http://www.emf.net:80/~estephen/manifesto/aum00110.html">https://web.archive.org/web/20050831003435/http://www.emf.net:80/~estephen/manifesto/aum00110.html</a><br>
... en <strong>Francais</strong>: ... <a href="http://1libertaire.free.fr/fem-scum.html">http://1libertaire.free.fr/fem-scum.html</a>
</div>
-->
<hr>
<div>
Other Links:
<br><br>
A geocities website about Valerie Solanas: <a href="https://web.archive.org/web/20050817015943/http://geocities.com/WestHollywood/Village/6982/solanas.html">https://web.archive.org/web/20050817015943/http://geocities.com/WestHollywood/Village/6982/solanas.html</a>
</div>

BIN
static/images/epson.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

170
templates/en/about.html

@ -1,170 +0,0 @@
{% extends "en/base.html" %}
{% block title %}{% endblock %}
{% block search %}
{% endblock %}
{% block content %}
<br>
<br>
<div id="intro" class="cross">
<p>A cross-reading allows for a specific type of reading that does not follow a linear order, but follows a self-chosen path. Reading becomes an act of creating relations and threading connections, reading across different domains. </p>
<p>This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool. Reading across a collection of manifestos, while reading the algorithm that is used to do so.</p>
<p>These cross-readings connect ...</p>
<p class="tfidf">... the <em>Term Frequency Inverse Document Frequency</em> algorithm, or <em>TF-IDF</em> in short</p>
<p class="techfem">... a collection of <em>cyber- and technofeminist manifestos</em></p>
<p class="tfidf">The TF-IDF is a commonly used algorithm to find the most important words of a document. The algorithm is (partly) written by the female computer scientist Karen Spärck Jones in the 1970s and has become one of the important algorithms of many search tools online, such as digital library systems or corporate search engines like Yandex or Google. The algorithm turns written documents into a sorted lists of search results, using a specific relative and inversed way of counting, that is sensitive for contrast in written documents. </p>
<p class="techfem">The cyber/technofeminist manifestos connect feminist thinking to technology, introducing feminist servers, cyborg figures, cyberwitches, or pleas for the glitch as cultural digital artefact. This collection, which is obviously incomplete, brings a diverse set of technofeminist documents together that are published between 1912 and 2019. The manifestos speak about very different concerns and questions, but they connect in terms of energy level. Urging to make a statement, ready to activate.
<br><br>
An interesting note to mention: Karen Spärck Jones was an advocate for the position of women in computing. <em>“I’ve been trying to think a little bit—but it’s very dispiriting!—about how to try to get more women into computer science. On the whole, everybody who thinks about this is depressed, because we’re going backwards rather than forwards.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>These two axes, the algorithm and the manifestos, interoperate. They support and strengthen eachother as the X and Y of this cross-reading tool. </p>
<p>The TF-IDF algorithm, while responding to a search request, creates cross-readings through the manifestos. It outputs a list of search results around the subject of search, creating a field of statements, questions and concerns around one single word. Meanwhile, the algorithm starts to interoperate with the manifesto as a format. Sensitive as it is for bulletpointed writing, repetition and unique words -- elements that are used a lot in these statement driven documents. The algorithm prioritizes higher contrastful language over academic writing, repetition over very diverse vocabularies and the use of unique words over the use of common ones.</p>
<p>See this cross-reading tool as an exercise in reading, across a field of technofeminist thinking and a tool for algorithmic sorting.</p>
<!-- <p>Reading the TF-IDF algorithm by itself only results in a technical understanding of this old artefact.</p> -->
<!-- <p>This algorithm thereby connects a discrete procedure (that of computing) to a very vivid and strong document format: the manifesto.</p> -->
</div>
<div id="colophon">
<h1>Colophon</h1>
<p>
The <em>cyber/technofeminist cross-reader</em> is developed by <a href="http://manettaberends.nl/">Manetta Berends</a><br />
in the context of the exhibition <em>Computer Grrrls</em> in Paris (March - July 2019).<br>
</p>
<br>
<p>
Commissioned by:<br />
Inke Arns (Hartware Medien Kunst Verein, Dortmund)<br />
Marie Lechner (La Gaîté Lyrique, Paris)<br />
<br />
Cyber/technofeminist manifesto collection:<br />
Inke Arns<br>
Marie Lechner<br />
</p>
<br>
<p>Translation to French:<br />
Julie Boschat-Thorez</p>
<p><br />
Fonts:<br />
Go-Mono<br />
Liberation Sans Narrow Bold<br />
<br />
Software:<br />
Flask<br />
NLTK<br />
<br />
Copyleft:<br>
The <em>cyber/technofeminist cross-reader</em> is a free work, <br>
you can copy, distribute, and modify it under the terms <br>
of the <a href="http://artlibre.org/licence/lal/en/">Free Art License</a>.
<br>
<br>
Code:<br>
<a href="https://git.vvvvvvaria.org/mb/cross-reader">https://git.vvvvvvaria.org/mb/cross-reader</a><br />
<br>
This project is made possible with the support of the DICRéAM fund, Paris.
</p>
</div>
<div class="cross">
<p class="note">[Note on context]</p>
<p class="techfem">
The collection of cyber/technofeminist manifestos includes the following documents:
<br><br>
<em>Manifeste de la Femme Futuriste</em> [FR]<br>
<em>The Manifesto of Futurist Woman</em> [EN] <br>
written by Valentine de Saintpoint (1912)<br><br>
<em>S.C.U.M manifesto</em> [EN, FR]<br>
written by Valerie Solanas (1967)<br><br>
<em>A Cyborg Manifesto</em> [EN] <br>
<em>Manifeste Cyborg</em> [FR] <br>
written by Donna Haraway (1984)<br><br>
<em>RIOT GRRRL MANIFESTO</em> [EN] <br>
published in Bikini Zine (1989)<br><br>
<em>Cyberfeminist manifesto for the 21st century</em> [EN, FR] <br>
written by VNS Matrix (1991)<br><br>
<em>Bitch Mutant Manifesto</em> [EN] <br>
written by VNS Matrix (1996)<br><br>
<em>Cyberfeminism is not</em> [EN, DE, NL, FR] <br>
written by Old Boys Network (OBN) (1997)<br><br>
<em>Refugia</em> [EN] <br>
written by SubRosa (2002)<br><br>
<em>Glitch Manifesto </em>[EN] <br>
written by Rosa Menkman (2009)<br><br>
<em>Glitch Feminism Manifesto</em> [EN] <br>
written by Legacy Russell (2012)<br><br>
<em>The Mundane Afrofuturist Manifesto</em> [EN] <br>
written by Martine Syms (2013)<br><br>
<em>Wages for Facebook</em> [EN] <br>
written by Laurel Ptak (2013)<br><br>
<em>A Feminist Server Manifesto </em>[EN] <br>
published by Constant (2014)<br><br>
<em>Gynepunk Manifesto</em> [EN, ES, FR] <br>
written by Gynepunk (2014)<br><br>
<em>tRANShACKfEMINISta</em> [EN, ES, IT] <br>
written by Pechblenda Lab (2014)<br><br>
<em>Manifesto for the Gynecene</em> [EN] <br>
written by Alexandra Pirici and Raluca Voinea (2015)<br><br>
<em>The 3D Additivist Manifesto</em> [EN] + other languages available<br>
written by Morehshin Allahyari and Daniel Rourke (2015)<br><br>
<em>Xenofeminist manifesto</em> [EN, FR] + other languages available<br>
written by Laboria Cuboniks (2015)<br><br>
<em>Feminist Principles of the Internet </em>[EN] <br>
collective authorship, organized by Association for Progressive Communications (APC) (2016)<br><br>
<em>Hackers of Resistance Manifesto</em> [EN] <br>
written by HORS (2018)<br><br>
<em>Purple Noise Manifesto</em> [EN] <br>
written by Cornelia Sollfrank (2018)<br><br>
<em>The Call for Feminist Data</em> [EN] <br>
written by Caroline Sinders (2018)<br><br>
<em>Cyberwitches Manifesto </em>[EN, FR] <br>
written by Lucile Haute (2019)<br>
<br>
</p>
<p class="tfidf">The algorithm introduces the idea of a <em>context specific way</em> of counting words.
<br />
<br />
Karen's IDF part of the TF-IDF algorithm creates an ecosystem where the resulting numbers heavily depend on the presence of the other words. The deletion or addition of a document would change all the interrelations in the dataset, as the calculations fully depend on each other. Altough the practice of algorithmic text processing is inherently pretty brutal, as language is regarded as nothing but a <em>bag-of-words</em>, the TF-IDF algorithm and its algorithmic character, give us a way of counting that creates situated datasets where values are determined by their self-created context.
</p>
<hr>
<div>
User Notice for Copyrighted Materials in this collection
<br><br>
Some of the manifestos in this collection are protected by copyright law, where the copyright is owned by third parties. Fair use permits only certain limited uses of the content. The author of this project is using the third-party content under a fair use doctrine, making a navigational cross-reading tool available to you. The third-party content is used to create an access-point, to read, explore and study them.
</div>
<br>
<br>
</div>
</div>
{% endblock %}

85
templates/en/base.html

@ -1,19 +1,22 @@
<!DOCTYPE html>
<html lang='en'>
<html lang='{{ lang }}'>
<head>
<meta charset="utf-8" />
<title>{% block title %}cyber/technofeminist cross-readings{% endblock %}</title>
<title>cyber/technofeminist cross-readings {% block title %}{% endblock %}</title>
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/stylesheet.css')}}" />
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery-3.3.1.min.js')}}"></script>
</head>
<body>
<body class="{% block view %}{% endblock %}">
<div id="txt-list">
<p>List of manifestos:</p>
<ul>
{% for filename in filenames | sort %}
{% for txt in filenames|sort %}
{% set name = txt.replace('.txt','') %}
<li>
<a href="/{{ lang }}/manifesto/{{ filename | replace('.txt','') }}">{{ filename | prettyfilename }}</a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"><i></i></a>
<a href="/{{ lang }}/manifesto/{{ name }}">{{ txt.replace('_', ' ') }}</a><br>
<a class="contrast" href="/{{ lang }}/mapping/{{ name }}"></a>
<small><a href="/{{ lang }}/list/tf/{{ name }}">TF</a></small>
<small><a href="/{{ lang }}/list/idf/{{ name }}">IDF</a></small>
<small><a href="/{{ lang }}/list/tfidf/{{ name }}">TF-IDF</a></small>
</li>
{% endfor %}
<ul>
@ -21,43 +24,43 @@
{% endblock %}
</div>
<div id="wrapper">
<div id="nav-wrapper">
<div id="colophon_button">
EN / <a href="/fr">FR</a>
&nbsp;
<a href="/{{ lang }}/about">about</a>
<div id="nav">
<div class="page-button">
<a href="/{{ lang }}/cross-readings">cross-readings</a>
</div>
<div id="logo">
<a href="/{{ lang }}/">cyber/technofeminist <br>cross-readings</a>
<div class="page-button">
<a href="/{{ lang }}/colophon">colophon</a>
</div>
{% block search %}
<div id="search">
<form id="submitform" action="" method="GET" onsubmit="this.setAttribute('isSubmitting', 'true');">
<input id="query" name="q" value="{{query}}"/>
<input id="submit" type="submit" value="search"/>
</form>
<script>
(function () {
var searching = false,
button = document.querySelector('#search #submit'),
submitting = document.querySelector('#submitform').getAttribute('isSubmitting');
</div>
<div id="logo">
<a href="/{{ lang }}/">cyber/technofeminist <br>cross-readings</a>
</div>
{% block search %}
<div id="search">
<form id="submitform" action="" method="GET" onsubmit="this.setAttribute('isSubmitting', 'true');">
<input id="query" name="q" value="{{query}}"/>
<button id="submit" type="submit"></button>
</form>
<script>
(function () {
var searching = false,
button = document.querySelector('#search #submit'),
submitting = document.querySelector('#submitform').getAttribute('isSubmitting');
button.addEventListener('click', function (e) {
if (!searching) {
searching = true;
}
else {
e.preventDefault();
alert('Already searching ...');
}
})
})();
</script>
</div>
{% endblock %}
{% block nav %}
{% endblock %}
button.addEventListener('click', function (e) {
if (!searching) {
searching = true;
button.classList.add('searching');
}
else {
e.preventDefault();
alert('Already searching ...');
}
})
})();
</script>
</div>
{% endblock %}
<div id="content">
{% block content %}
{% endblock %}
@ -79,7 +82,7 @@
function refresh() {
if(new Date().getTime() - time >= 300000){
console.log('refresh!');
window.location.href = '/fr/';
window.location.href = '/en/';
} else {
setTimeout(refresh, 300000);
}

61
templates/en/colophon.html

@ -0,0 +1,61 @@
{% extends "en/base.html" %}
{% block view %}black{% endblock %}
{% block title %}- colophon{% endblock %}
{% block search %}
{% endblock %}
{% block content %}
<div id="colophon">
<br>
<br>
<p class="note">[colophon]</p>
<br>
<br>
<p>
The <em>cyber/technofeminist cross-reader</em> is developed by <a target="_blank" href="http://manettaberends.nl/">Manetta Berends</a><br />
in the context of the exhibition <em>Computer Grrrls</em> in Paris (March - July 2019).<br>
</p>
<br>
<p>
Commissioned by:<br />
Inke Arns (Hartware Medien Kunst Verein, Dortmund)<br />
Marie Lechner (La Gaîté Lyrique, Paris)<br />
<br />
Cyber/technofeminist manifesto collection:<br />
Inke Arns<br>
Marie Lechner<br />
</p>
<!-- <br> -->
<!-- <p>Translation to French:<br /> -->
<!-- Julie Boschat-Thorez</p> -->
<p><br />
Fonts:<br />
Go-Mono<br />
Liberation Sans Narrow Bold<br />
<br />
Software:<br />
Flask<br />
NLTK<br />
<br />
Copyleft:<br>
The <em>cyber/technofeminist cross-reader</em> is a free work, <br>
you can copy, distribute, and modify it under the terms <br>
of the <a href="http://artlibre.org/licence/lal/en/">Free Art License</a>.
<br>
<br>
Code:<br>
<a href="https://git.vvvvvvaria.org/mb/cross-reader">https://git.vvvvvvaria.org/mb/cross-reader</a><br />
<br>
This project is made possible with the support of the DICRéAM fund, Paris.
</p>
<br>
<br>
<hr>
<div>
User Notice for Copyrighted Materials in this collection
<br><br>
Some of the manifestos in this collection are protected by copyright law, where the copyright is owned by third parties. Fair use permits only certain limited uses of the content. The author of this project is using the third-party content under a fair use doctrine, making a navigational cross-reading tool available to you. The third-party content is used to create an access-point, to read, explore and study them.
</div>
</div>
{% endblock %}

185
templates/en/cross-readings.html

@ -0,0 +1,185 @@
{% extends "en/base.html" %}
{% block view %}black{% endblock %}
{% block title %}- cross-readings{% endblock %}
{% block search %}
{% endblock %}
{% block content %}
<div id="howto">
<br>
<br>
<p class="note">[How to use this cross-reader?]</p>
<br>
<blockquote>
This tool allows for cross-readings through a collection <br>
of <em>cyber/technofeminist manifestos</em> and the <em>TF-IDF algorithm</em>.
</blockquote>
<div class="guides">
<ol>
<li>
SEARCH — You can search through these manifestos by typing a keyword in the search bar or by clicking on the list of suggested keywords.
</li>
<li>
READ — You can simply browse through the list of manifestos (see right-hand column) and read them in their entirety and in their original web environment.
</li>
<li>
CROSS-READ — If you click on the ◐ icon, you can read the manifesto through the prism of the TD-IDF algorithm. This algorithm identifies the most specific words within a document. It was developed in part by British computer scientist Karen Spärck Jones and has been a crucial algorithm for a large number of online search engines.
</li>
<li>
INSPECT — Next to this icon, you can click on the <small><a href="">TF</a></small>, <small><a href="">IDF</a></small> and <small><a href="">TF-IDF</a></small> buttons to inspect the values of the TF-IDF algorithm for each manifesto.
</li>
</ol>
</div>
</div>
<div id="about">
<div id="intro" class="cross">
<br>
<p class="note">[cross-readings]</p>
<br>
<p>This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool.</p>
<p>These cross-readings connect ...</p>
<p class="tfidf">... the <em>Term Frequency Inverse Document Frequency</em> algorithm, or <em>TF-IDF</em> in short</p>
<p class="techfem">... a collection of <em>cyber- and technofeminist manifestos</em></p>
<p class="tfidf">The TF-IDF is a commonly used algorithm to find the most important words of a document. The algorithm is (partly) written by the female computer scientist Karen Spärck Jones in the 1970s and has become one of the important algorithms of many search tools online, such as digital library systems or corporate search engines like Yandex or Google. The algorithm turns written documents into a sorted lists of search results, using a specific relative and inversed way of counting, that is sensitive for contrast in written documents. </p>
<p class="techfem">The cyber/technofeminist manifestos connect feminist thinking to technology, introducing feminist servers, cyborg figures, cyberwitches, or pleas for the glitch as cultural digital artefact. This collection, which is obviously incomplete, brings a diverse set of technofeminist documents together that are published between 1912 and 2019. The manifestos speak about very different concerns and questions, but they connect in terms of energy level. Urging to make a statement, ready to activate.
<br><br>
An interesting note to mention: Karen Spärck Jones was an advocate for the position of women in computing. <em>“I’ve been trying to think a little bit—but it’s very dispiriting!—about how to try to get more women into computer science. On the whole, everybody who thinks about this is depressed, because we’re going backwards rather than forwards.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>These two axes, the algorithm and the manifestos, interoperate. They support and strengthen eachother as the X and Y of this cross-reading tool. </p>
<p>The TF-IDF algorithm, while responding to a search request, creates cross-readings through the manifestos. It outputs a list of search results around the subject of search, creating a field of statements, questions and concerns around one single word. Meanwhile, the algorithm starts to interoperate with the manifesto as a format. Sensitive as it is for bulletpointed writing, repetition and unique words -- elements that are used a lot in these statement driven documents. The algorithm prioritizes higher contrastful language over academic writing, repetition over very diverse vocabularies and the use of unique words over the use of common ones.</p>
<p>See this cross-reading tool as an exercise in reading, across a field of technofeminist thinking and a tool for algorithmic sorting.</p>
<!-- <p>Reading the TF-IDF algorithm by itself only results in a technical understanding of this old artefact.</p> -->
<!-- <p>This algorithm thereby connects a discrete procedure (that of computing) to a very vivid and strong document format: the manifesto.</p> -->
</div>
<div class="cross">
<br><br>
<p class="note">[TF-IDF algorithm]</p>
<br>
<p class="tfidf" style="float: right;margin-left:1em;">
<code>
def tfidf(query, words, corpus):<br /><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Term Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for word in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query == word:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf = tf_count/len(words)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Inverse Document Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for words in corpus:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tfidf_value = tf * idf<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return tf_count, tf_count, tfidf_value
</code>
<br><br>
The TF-IDF algorithm, shown above in the programming language Python, weaves a layer of contrast into the text. Not literally, but in the form of numbers. The most contrastful words are those that the algorithm consideres as the most specific words for that text.
<br><br>
The TF-IDF values are calculated in two steps. The algorithm first counts the <em>Term Frequency</em> (TF) by counting the appearance of a word in the text, relatively to the total number of words in the document. This way of relative frequency counting makes it possible to compare wordcounts between documents with variating lengths. This makes it possible to compare Donna Harraway's long essay <em><em>A Cyborg Manifesto</em></em> (1984) with the relatively short text of <em><em>The Call for Feminist Data</em></em> written by Caroline Sinders (2018).
<br><br>
In the second step, the algorithm counts relatively against all the other documents in the same dataset, using the <em>Inversed Document Frequency</em> (IDF). This part of the algorithm, which is Karen Spärck Jones’ addition, introduced a subtle form of inversed relative counting throughout all the documents in the dataset. Instead of just counting word-frequency in one document, Karen proposed to count in a relative inter-document way.
<br><br>
This means that when a word only appears in one or a few documents, that its value is greatly enlarged. The concequence being that words as <em><em>the</em></em> or <em><em>it</em></em> will be given a very low number, as they appear in all the documents. And specific words, such as <em>paranodal</em> in <em>A Feminist Server Manifesto</em>, will get a very high value as this word is only used 4 times in the whole dataset and all of those 4 occurances where in this manifesto.
<br><br>
Another example is <em>SCUM</em>. Although the word <em>SCUM</em> is not the most commonly used word in the <em>S.C.U.M. Manifesto</em>, it is the word that gets the highest score: relative to all the other manifesto's, <em>SCUM</em> is mostly used in this manifesto. This increases the score a lot.
</p>
</div>
<div class="cross">
<br><br>
<p class="note">[cyber/technofeminist manifestos]</p>
<br>
<p class="techfem">
The collection of cyber/technofeminist manifestos includes the following documents:
<br><br>
<em>The Manifesto of Futurist Woman</em> [EN] <br>
written by Valentine de Saintpoint (1912)<br><br>
<em>S.C.U.M manifesto</em> [EN]<br>
written by Valerie Solanas (1967)<br><br>
<em>A Cyborg Manifesto</em> [EN] <br>
written by Donna Haraway (1984)<br><br>
<em>RIOT GRRRL MANIFESTO</em> [EN] <br>
published in Bikini Zine (1989)<br><br>
<em>Cyberfeminist manifesto for the 21st century</em> [EN] <br>
written by VNS Matrix (1991)<br><br>
<em>Bitch Mutant Manifesto</em> [EN] <br>
written by VNS Matrix (1996)<br><br>
<em>Cyberfeminism is not</em> [EN, DE, NL, FR] <br>
written by Old Boys Network (OBN) (1997)<br><br>
<em>Refugia</em> [EN] <br>
written by SubRosa (2002)<br><br>
<em>Glitch Manifesto </em>[EN] <br>
written by Rosa Menkman (2009)<br><br>
<em>Glitch Feminism Manifesto</em> [EN] <br>
written by Legacy Russell (2012)<br><br>
<em>The Mundane Afrofuturist Manifesto</em> [EN] <br>
written by Martine Syms (2013)<br><br>
<em>Wages for Facebook</em> [EN] <br>
written by Laurel Ptak (2013)<br><br>
<em>A Feminist Server Manifesto </em>[EN] <br>
published by Constant (2014)<br><br>
<em>Gynepunk Manifesto</em> [EN] <br>
written by Gynepunk (2014)<br><br>
<em>tRANShACKfEMINISta</em> [EN] <br>
written by Pechblenda Lab (2014)<br><br>
<em>Manifesto for the Gynecene</em> [EN] <br>
written by Alexandra Pirici and Raluca Voinea (2015)<br><br>
<em>The 3D Additivist Manifesto</em> [EN]<br>
written by Morehshin Allahyari and Daniel Rourke (2015)<br><br>
<em>Xenofeminist manifesto</em> [EN]<br>
written by Laboria Cuboniks (2015)<br><br>
<em>Feminist Principles of the Internet </em>[EN] <br>
collective authorship, organized by Association for Progressive Communications (APC) (2016)<br><br>
<em>Hackers of Resistance Manifesto</em> [EN] <br>
written by HORS (2018)<br><br>
<em>Purple Noise Manifesto</em> [EN] <br>
written by Cornelia Sollfrank (2018)<br><br>
<em>The Call for Feminist Data</em> [EN] <br>
written by Caroline Sinders (2018)<br><br>
<em>Cyberwitches Manifesto </em>[EN] <br>
written by Lucile Haute (2019)<br>
<br>
</p>
<p class="tfidf">The algorithm introduces the idea of a <em>context specific way</em> of counting words.
<br />
<br />
Karen's IDF part of the TF-IDF algorithm creates an ecosystem where the resulting numbers heavily depend on the presence of the other words. The deletion or addition of a document would change all the interrelations in the dataset, as the calculations fully depend on each other. Altough the practice of algorithmic text processing is inherently pretty brutal, as language is regarded as nothing but a <em>bag-of-words</em>, the TF-IDF algorithm and its algorithmic character, give us a way of counting that creates situated datasets where values are determined by their self-created context.
</p>
<br>
<br>
</div>
</div>
{% endblock %}

31
templates/en/index.html

@ -1,43 +1,24 @@
{% extends "en/base.html" %}
{% block results %}
<blockquote>
This tool allows for cross-readings through a collection of <em>cyber/technofeminist manifestos</em><br>
and the <em>TF-IDF algorithm</em>, an algorithm that has been very important for online search engines.
</blockquote>
<!-- <p>Psst, this is a cross-reading tool that operates on two axes ...</p> -->
<!-- <p>Tip: Try to search for a single word.</p> -->
<div class="guides">
<ol>
<li>
You can explore these manifests by typing a keyword in the search bar or by clicking on the list of suggested keywords below. The results display sentences from the different manifestos in which the search word appears. The colour changes correspond to the different manifestos from which they are derived. You can print extracts by clicking on the printer icon.
</li>
<li>
You can simply browse through this list of manifests and read them in their entirety and in their original web environment (right-hand column).
</li>
<li>
If you click on the small icon next to the manifest title, you can read the manifest through the prism of the TD-IDF algorithm. This algorithm identifies the most important words within a document. It is crucial for a large number of online search engines. It was developed in part by British computer scientist Karen Spärck Jones. For more information on how it works, see <a href="/{{ lang }}/about">about</a>.
</li>
</ol>
</div>
{% endblock %}
{% block suggestions %}
<h1>Cross-reading suggestions (manual selection):</h1>
<!-- <h1>Cross-reading suggestions (manual selection):</h1>
<div>
{% for word in suggestions %}
<strong class="query"><a href="/{{ lang }}/?q={{word}}">{{ word.strip() }}</a></strong>
{% endfor %}
</div>
<br>
<h1>Cross-reading suggestions (algorithmic selection):</h1>
<br> -->
<!-- <h1>Cross-reading suggestions:</h1>
<div>
{% for word in mappings %}
<strong class="query"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
<strong class="query"><a href="/{{ lang }}/?q={{ word }}">{{ word.strip() }}</a></strong>
{% endfor %}
</div>
<br>
<p>Read more about the <a href="/{{ lang }}/mappings/{{ filenames[0] }}">TF-IDF algorithm and contrast mappings</a>.</p>
<br>
<p>Read more about <a href="/{{ lang }}/about">cross-readings</a>.</p>
<br>
<br> -->
{% endblock %}

11
templates/en/list.html

@ -0,0 +1,11 @@
{% extends "en/base.html" %}
{% block title %} - {{ list_type }}{% endblock %}
{% block content %}
<div id="list">
<h1>{{ list_type }} * {{ filename | prettyfilename }}</h1>
{% for value, word in list | sort(reverse=True) %}
<div><strong><a href="/en/?q={{ word}}">{{ word }}</a></strong> <sup>({{ value }})</sup></div>
{% endfor %}
</div>
{% endblock %}

2
templates/en/manifesto.html

@ -9,6 +9,8 @@
{% block manifesto %}
<div id="manifesto_content_wrapper">
<br>
<br>
{% for line in manifesto %}
<p>{{ line | replace(' •', ' ') }}<br></p>
{% endfor %}

14
templates/fr/mappings.html → templates/en/mapping.html

@ -1,17 +1,19 @@
{% extends "fr/base.html" %}
{% extends "en/base.html" %}
{% block title %}{% endblock %}
{% block txtlist %}
{% block search %}
{% endblock %}
{% block results %}
<h1>Contrast mappings, cross-reading with algorithmic results.</h1>
<div id="mappings">
{% for manifesto, items in mappings.items() %}
<h1>{{ manifesto }}</h1>
{% for tfidf, word in items %}
<br><br>
<h1>{{ manifesto | prettyfilename }}</h1>
{% for sentence in mappings %}
<p class="sentence">
{% for word, tfidf in sentence %}
<strong class="query" style="font-size:{{ 50 + tfidf }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
</p>
{% endfor %}
</div>
{% endblock %}

59
templates/en/mappings-name.html

@ -1,59 +0,0 @@
{% extends "en/base.html" %}
{% block title %}{% endblock %}
{% block search %}
{% endblock %}
{% block results %}
<div class="cross">
<br><br>
<p class="note">[Note on contrast mappings]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<code>
def tfidf(query, words, corpus):<br /><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Term Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for word in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query == word:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf = tf_count/len(words)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Inverse Document Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for words in corpus:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tfidf_value = tf * idf<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return tf_count, tf_count, tfidf_value
</code>
<br><br>
The TF-IDF algorithm, shown above in the programming language Python, weaves a layer of contrast into the text. Not literally, but in the form of numbers. The most contrastful words are those that the algorithm consideres as the most important words for that text.
<br><br>
These contrast mappings allow for reading across the manifesto and the algorithm.
<br><br>
The TF-IDF values are calculated in two steps. The algorithm first counts the <em>Term Frequency</em> (TF) by counting the appearance of a word in the text, relatively to the total number of words in the document. This way of relative frequency counting makes it possible to compare wordcounts between documents with variating lengths. This makes it possible to compare Donna Harraway's long essay <em><em>A Cyborg Manifesto</em></em> (1984) with the relatively short text of <em><em>The Call for Feminist Data</em></em> written by Caroline Sinders (2018).
<br><br>
In the second step, the algorithm counts relatively against all the other documents in the same dataset, using the <em>Inversed Document Frequency</em> (IDF). This part of the algorithm, which is Karen Spärck Jones’ addition, introduced a subtle form of inversed relative counting throughout all the documents in the dataset. Instead of just counting word-frequency in one document, Karen proposed to count in a relative inter-document way.
<br><br>
This means that when a word only appears in one or a few documents, that its value is greatly enlarged. The concequence being that words as <em><em>the</em></em> or <em><em>it</em></em> will be given a very low number, as they appear in all the documents. And specific words, such as <em>paranodal</em> in <em>A Feminist Server Manifesto</em>, will get a very high value as this word is only used 4 times in the whole dataset and all of those 4 occurances where in this manifesto.
<br><br>
Another example is <em>SCUM</em>. Although the word <em>SCUM</em> is not the most commonly used word in the <em>S.C.U.M. Manifesto</em>, it is the word that gets the highest score: relative to all the other manifesto's, <em>SCUM</em> is mostly used in this manifesto. This increases the score a lot.
</p>
</div>
<div id="mappings">
<h1>{{ manifesto | prettyfilename }}</h1>
{% for sentence in mappings %}
<p class="sentence">
{% for word, tfidf in sentence %}
<strong class="query" style="font-size:{{ 50 + tfidf }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
</p>
{% endfor %}
</div>
{% endblock %}
{% block suggestions %}
{% endblock %}

17
templates/en/mappings.html

@ -1,17 +0,0 @@
{% extends "en/base.html" %}
{% block title %}{% endblock %}
{% block txtlist %}
{% endblock %}
{% block results %}
<h1>Contrast mappings, cross-reading with algorithmic results.</h1>
<div id="mappings">
{% for manifesto, items in mappings.items() %}
<h1>{{ manifesto }}</h1>
{% for tfidf, word in items %}
<strong class="query" style="font-size:{{ 50 + tfidf }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
{% endfor %}
</div>
{% endblock %}

27
templates/en/ordered.html

@ -1,27 +0,0 @@
{% extends "en/base.html" %}
{% block title %}{% endblock %}
{% block txtlist %}
{% endblock %}
{% block results %}
<h1>lists</h1>
<div id="listing_per_manifesto" class="listings">
{% for manifesto, words in results.items()|sort %}
<span class="result">
<div class="ascii">
/\|\/\<br>
_)&nbsp;&nbsp;&nbsp;&nbsp;(__<br>
\_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_/ <br>
)&nbsp;&nbsp;&nbsp;&nbsp;\ <br>
\/\|\/
</div>
<h2>{{manifesto}}</h2>
{% for value, word in words %}
<strong style="font-size:{{value * 50000}}%;"><a href="{{ url_for('index')}}?q={{word}}">{{word}}</a></strong>
{% endfor %}
</span>
{% endfor %}
<hr>
</div>
{% endblock %}

103
templates/en/results.html

@ -1,14 +1,14 @@
{% extends "en/base.html" %}
{% block title %}{{query}}{% endblock %}
{% block title %}- {{ query }}{% endblock %}
{% block nav %}
<div id="print" class="blink {{ connection }}">
<a href="?q={{ query }}&print=now"><img src="/static/images/epson.png"></a>
<div id="print" class="{{ connection }}">
<a href="?q={{ query }}&print=now"><button></button></a>
</div>
<script>
(function () {
var printing = false,
button = document.querySelector('#print a');
button = document.querySelector('#print button');
button.addEventListener('click', function (e) {
if (!printing) {
@ -26,23 +26,31 @@
{% block results %}
{% if results == {} %}
<div id="notused">This word could not be found.</div>
{% else %}
<div class="cross">
<p class="note">[Note on the search results]</p>
<p class="tfidf">Once a search query is submitted, the <em>TF-IDF</em> starts to go through all the manifestos in the dataset, to see if a word is used, and if yes, to put it in the list of search results. The list is sorted according to the importance of the word <strong>{{ query }} </strong> to each manifesto. </p>
<p class="techfem">The search results are snippets, statements, quotes or questions, threaded together by one single word, create a cross-reading index. The occurances of <strong> {{ query }}</strong> in the different manifestos, become eachother complexifiers. </p>
<div id="notused">
This word could not be found.
<br>
<br>
<div>
Please note that ...
<br>
<br>
... the cross-reader can only search for one word
<br>
... "-" or "_" are understood as spaces
<br>
... search results are not case sensitive
</div>
</div>
{% else %}
<div id="results">
<h1>Cross-reading through the manifestos along the axes of <strong class="query">{{ query }}</strong>:</h1>
<h1>Cross-readings along the axes of <strong class="query">{{ query }}</strong>:</h1>
<div class="results">
{% for x, manifesto in results.items() %}
{% for sentence in manifesto.html %}
<div id="{{ x }}_{{ loop.index }}" class="result">
<div class="title">
{{ manifesto.name }}
<div><a class="contrast" href="/en/mapping/{{ manifesto.filename }}"></a></div>
</div>
<div class="sentence">{{ sentence }}</div>
</div>
@ -53,49 +61,47 @@
{% endif %}
{% endblock %}
{% block suggestions %}
<div id="suggestions">
<h1>SUGGESTIONS</h1>
{% if analytics %}
{% if analytics %}
{% block suggestions %}
<div id="suggestions">
<br>
<br>
<br>
<br>
<h1>SUGGESTIONS</h1>
{% if analytics.stemmer %}
<div id="similars" class="analytics stemmer">
<h2>Similar but not the same to <em>{{ query }}</em>:</h2>
{% for word in analytics.stemmer %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
<div id="similars" class="analytics stemmer">
<h2>Similar but not the same to <em>{{ query }}</em>:</h2>
{% for word in analytics.stemmer %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endfor%}
</div>
<br>
{% endif%}
{% if analytics.suggestions %}
<div class="suggestions tfidf">
<h1>Also specific to <em>{{ results[0]['name'] }}</em>: <br></h1>
<div class="">
{% for word, idf in analytics.suggestions %}
{% if loop.index < 50 %}
{% if word == query %}
<strong class="word">{{ word }}</strong>
{% else %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endif%}
{% endif%}
{% endfor%}
</div>
<br>
{% endif%}
{% endif%}
<div class="suggestions techfem">
<h1>Cross-reading suggestions (manual selection):</h1>
{% for word in suggestions %}
<strong class="query"><a href="?q={{word}}">{{ word.strip() }}</a></strong>
{% endfor %}
</div>
{% if analytics.mappings %}
<br>
<div class="suggestions tfidf">
<h1>Cross-reading suggestions (algorithmic selection) through <em>{{ results[0]['name']}}</em>: <br></h1>
<div class="">
{% for tfidf, word in analytics.mappings[:50] %}
{% if word == query %}
<strong class="word">{{ word }}</strong>
{% else %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endif%}
{% endfor%}
<br>
</div>
<br>
<div><a class="contrast" href="/{{ lang}}/mappings/{{ results[0]['filename'].strip() | replace('.txt','') }}">Read more ◐</a></div>
{% endif%}
</div>
{% endif%}
</div>
{% endblock %}
{% endif%}
<div class="cross">
<!-- <div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
The <em>TF-IDF algorithm</em> is an activator. Activating non-linear threads through a dataset of words.
@ -108,5 +114,4 @@
<em>&quot;Nothing should be accepted as fixed, permanent, or 'given' -- neither material conditions nor social forms..&quot;</em> (Xenofeminist manifesto), <br>
<em>&quot;So that is why no revolution should be without her.&quot;</em> (The Manifesto of Futurist Woman)
</p>
</div>
{% endblock %}
</div> -->

170
templates/fr/about.html

@ -1,170 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{% endblock %}
{% block search %}
{% endblock %}
{% block content %}
<br>
<br>
<div id="intro" class="cross">
<p>La lecture transversale permet un type de lecture spécifique, ne poursuivant pas un ordre linéaire, selon un parcours choisi. La lecture devient un acte de création de relations et de tissage de connections, via la traversée de différents domaines.</p>
<p>Cette liseuse transversale cyber/technoféministe s’établit sur deux axes, alliant la lecture d’un corpus de textes et celle d’un outil technologique. Le processus de lecture englobe un ensemble de manifestes ainsi que l’algorithme utilisé pour ce faire.</p>
<p>Ces lectures transversales connectent ...</p>
<p class="tfidf">... et l’algorithme TF-IDF, de l’anglais <em>Term Frequency Inverse Document Frequency</em></p>
<p class="techfem">... une <em>collection de manifestes cyber et technoféministes</em></p>
<p class="tfidf">Le TF-IDF est un algorithme utilisé communément afin d’identifier les mots les plus importants au sein d’un document. Cet algorithme a été en partie développé par l’informaticienne Spärck Jones dans les années 70. Il est devenu l’un des algorithmes les plus importants pour un grand nombre de moteurs de recherche en ligne tels que Yandex ou Google. L’algorithme transforme les documents textuels en listes, où les résultats de recherche sont triés. Il utilise un mode de comptage inversé, sensible aux variations présentes au sein de ces documents.</p>
<p class="techfem">Les manifestes cyber/technoféministes lient pensée féministe et technologie, en introduisant le concept de serveurs féministes, des figures cyborg, des cyber-sorcières, voire des plaidoyers à la faveur du glitch comme artefact culturel numérique. Cette collection, évidemment non exhaustive, rassemble divers documents technoféministes publiés entre 1912 et 2019. Bien que ces manifestes évoquent des questions et préoccupations diverses, ils convergent sur le plan de l’énergie déployée. Ils posent l’urgence d’établir un constat, prêts à être mis en oeuvre.
<br><br>
Par ailleurs, il convient de noter que Karen Spärck Jones défendait la place des femmes dans le milieu informatique. <em>“J’ai essayé de réfléchir un peu – mais c’est très décourageant! - à la façon de parvenir à ce que plus de femmes soient présentes en informatique. Globalement, chaque personne réfléchissant sur le sujet finit par être déprimée, car nous reculons plus que nous ne progressons.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>Ces deux axes, celui de l’algorithme et celui des manifestes, opèrent ensemble. Ils se soutiennent et se renforcent mutuellement, créant de nouvelles dimensions de lectures via cette liseuse transversale.</p>
<p>L’algorithme TF-IDF génère une lecture transversale des manifestes tout en répondant à une requête. Il en ressort une liste de résultats autour du terme; un ensemble de déclarations, questions et préoccupations autour d’un même terme. Simultanément, l’algorithme interagit avec le format du manifeste : il est sensible aux puces typographiques, aux répétitions et aux mots uniques – des éléments qui caractérisent ces documents d’ordre déclaratif. L’algorithme donne la priorité aux formes textuelles très contrastées par rapport à celles ayant un style plus académique, à la répétition sur la diversité de vocabulaire, et à l’usage de mots uniques sur les mots plus communs.</p>
<p>Cet outil de lecture transversale est donc à considérer tel un exercice de lecture, à travers le champ commun de la pensée technoféministe et d’un outil de classification algorithmique.</p>
</div>
<div id ="colophon">
<h1>Colophon</h1>
<p>
La <em>cyber/technofeminist cross-reader</em> a été développée par <a href="http://manettaberends.nl/">Manetta Berends</a><br>
pour l’exposition <em>Computer Grrrls</em> à Paris (Mars - Juillet 2019).<br>
</p>
<br>
<p>
Commission par:<br />
Inke Arns (Hartware Medien Kunst Verein, Dortmund)<br>
Marie Lechner (La Gaîté Lyrique, Paris)<br />
<br />
Curation des manifestes Cyber/technoféministes par:<br>
Inke Arns<br>
Marie Lechner<br>
<br>
Traduction française: <br />
Julie Boschat-Thorez<br>
<br />
Polices d’écriture:<br />
Go-Mono<br />
Liberation Sans Narrow Bold<br />
<br />
Logiciel:<br />
Flask<br />
NLTK<br />
<br />
Copyleft:<br>
Le <em>cyber/technofeminist cross-reader</em> est un travail libre,<br>
vous pouvez le copier, le distribuer, et le modifier <br>
sous les termes de la <a href="http://artlibre.org/licence/lal/en/">Licence artistique libre</a>.
<br>
<br>
Code:<br>
<a href="https://git.vvvvvvaria.org/mb/cross-reader">https://git.vvvvvvaria.org/mb/cross-reader</a><br />
<br>
Ce projet a été réalisé avec le soutien du fond DICRéAM, Paris.
</p>
</div>
<div class="cross">
<p class="note">[Note sur la contextualisation]</p>
<p class="techfem">
La collection des manifestes cyber/technoféministes comprend les documents suivants:
<br><br>
<em>Manifeste de la Femme Futuriste</em> [FR]<br>
<em>The Manifesto of Futurist Woman</em> [EN] <br>
par Valentine de Saintpoint (1912)<br><br>
<em>S.C.U.M manifesto</em> [EN, FR]<br>
par Valerie Solanas (1967)<br><br>
<em>A Cyborg Manifesto</em> [EN] <br>
<em>Manifeste Cyborg</em> [FR] <br>
par Donna Haraway (1984)<br><br>
<em>RIOT GRRRL MANIFESTO</em> [EN] <br>
publié par Bikini Zine (1989)<br><br>
<em>Cyberfeminist manifesto for the 21st century</em> [EN, FR] <br>
par VNS Matrix (1991)<br><br>
<em>Bitch Mutant Manifesto</em> [EN] <br>
par VNS Matrix (1996)<br><br>
<em>Cyberfeminism is not</em> [EN, DE, NL, FR] <br>
par Old Boys Network (OBN) (1997)<br><br>
<em>Refugia</em> [EN] <br>
par SubRosa (2002)<br><br>
<em>Glitch Manifesto </em>[EN] <br>
par Rosa Menkman (2009)<br><br>
<em>Glitch Feminism Manifesto</em> [EN] <br>
par Legacy Russell (2012)<br><br>
<em>The Mundane Afrofuturist Manifesto</em> [EN] <br>
par Martine Syms (2013)<br><br>
<em>Wages for Facebook</em> [EN] <br>
par Laurel Ptak (2013)<br><br>
<em>A Feminist Server Manifesto </em>[EN] <br>
publié par Constant (2014)<br><br>
<em>Gynepunk Manifesto</em> [EN, ES, FR] <br>
par Gynepunk (2014)<br><br>
<em>tRANShACKfEMINISta</em> [EN, ES, IT] <br>
par Pechblenda Lab (2014)<br><br>
<em>Manifesto for the Gynecene</em> [EN] <br>
par Alexandra Pirici and Raluca Voinea (2015)<br><br>
<em>The 3D Additivist Manifesto</em> [EN] + other languages available<br>
par Morehshin Allahyari and Daniel Rourke (2015)<br><br>
<em>Xenofeminist manifesto</em> [EN, FR] + other languages available<br>
par Laboria Cuboniks (2015)<br><br>
<em>Feminist Principles of the Internet </em>[EN] <br>
Rédaction collective, coordonnée par la «Association for Progressive Communications» (APC) (2016)<br><br>
<em>Hackers of Resistance Manifesto</em> [EN] <br>
par HORS (2018)<br><br>
<em>Purple Noise Manifesto</em> [EN] <br>
par Cornelia Sollfrank (2018)<br><br>
<em>The Call for Feminist Data</em> [EN] <br>
par Caroline Sinders (2018)<br><br>
<em>Cyberwitches Manifesto </em>[EN, FR] <br>
par Lucile Haute (2019)<br>
<br>
</p>
<p class="tfidf">L’algorithme amorce des idées sur le comptage localisé de mots.
<br />
<br />
La partie IDF (de l’algorithme TF-IDF), rédigée par Karen Spärck Jones, créé un ecosystème au sein duquel les valeurs obtenues dépendent de la présence d’autres mots. La supression ou l’ajout d’un document affecte les relations entre l’ensemble des documents, car les calculs se basent sur leur totalité. Bien que les algorithmes de traitement de texte aient une approche fondamentalement brutale, puisque le langage n’y est considéré que comme un ensemble de données, l’algorithme TF-IDF exerce d’une méthode de comptage contextualisante. Les valeurs accordées aux textes sont déterminées par le contexte créé via leur association.
</p>
<hr>
<div>
Avis à l'utilisateur concernant les documents protégés par le droit d'auteur dans cette collection
<br><br>
Certains des manifestes de cette collection sont protégés par la loi sur le droit d'auteur, lorsque le droit d'auteur appartient à des tiers. L'utilisation équitable n'autorise que certaines utilisations limitées du contenu. L'auteur de ce projet utilise le contenu d'une tierce partie dans le cadre d'une doctrine d'utilisation équitable et met à votre disposition un outil de navigation et de lecture croisée. Les contenus de tiers sont utilisés pour créer un point d'accès, pour les lire, les explorer et les étudier.
</div>
<br>
<br>
</div>
</div>
{% endblock %}

96
templates/fr/base.html

@ -1,96 +0,0 @@
<!DOCTYPE html>
<html lang='fr'>
<head>
<meta charset="utf-8" />
<title>{% block title %}cyber/technofeminist cross-readings{% endblock %}</title>
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/stylesheet.css')}}" />
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery-3.3.1.min.js')}}"></script>
</head>
<body>
<div id="txt-list">
<p>Liste des manifestes:</p>
<ul>
{% for filename in filenames | sort %}
<li>
<a href="/{{ lang }}/manifesto/{{ filename | replace('.txt','') }}">{{ filename | prettyfilename }}</a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"><i></i></a>
</li>
{% endfor %}
<ul>
{% block txtlist %}
{% endblock %}
</div>
<div id="wrapper">
<div id="nav-wrapper">
<div id="colophon_button">
<a href="/en">EN</a> / FR
&nbsp;
<a href="/{{ lang }}/about">à propos</a>
</div>
<div id="logo">
<a href="/{{ lang }}/">cyber/technofeminist <br>cross-readings</a>
</div>
{% block search %}
<div id="search">
<form action="" method="GET">
<input id="query" name="q" value="{{query}}"/>
<input id="submit" type="submit" value="search"/>
</form>
<script>
(function () {
var searching = false,
button = document.querySelector('#search #submit');
button.addEventListener('click', function (e) {
if (!searching) {
searching = true;
}
else {
e.preventDefault();
alert('Already searching ...');
}
})
})();
</script>
</div>
{% endblock %}
{% block nav %}
{% endblock %}
</div>
<div id="content">
{% block content %}
{% endblock %}
{% block results %}
{% endblock %}
{% block manifesto %}
{% endblock %}
{% block suggestions %}
{% endblock %}
</div>
</div>
</body>
<script>
// refresh when there is no (mouse or keyboard) activity for 5 minutes
var time = new Date().getTime();
$(document.body).bind("mousemove keypress", function(e) {
time = new Date().getTime();
});
function refresh() {
if(new Date().getTime() - time >= 300000){
console.log('refresh!');
window.location.href = '/fr/';
} else {
setTimeout(refresh, 300000);
}
}
setTimeout(refresh, 300000);
// prevent links from opening in new tab
var links = document.links;
for (var i = 0; i < links.length; i++) {
links[i].target = "_self";
}
</script>
</html>

41
templates/fr/index.html

@ -1,41 +0,0 @@
{% extends "fr/base.html" %}
{% block results %}
<blockquote>Cet outil permet des lectures croisées à travers une <em>collection de manifestes cyber/technoféministes</em><br>
et <em>l'algorithme TF-IDF</em>, un algorithme qui a été très important pour les moteurs de recherche en ligne.</blockquote>
<div class="guides">
<ol>
<li>
Vous pouvez explorer ces manifestes en tapant un mot-clé dans la barre de recherche ou en cliquant sur la liste des mots-clés suggérés ci-dessous. Les résultats affichent des phrases extraites des différents manifestes dans lesquelles le mot recherché apparaît. Les changements de couleur correspondent aux différents manifestes dont ils sont issus. Vous pouvez en imprimer des extraits en cliquant sur l’icône de l’imprimante.
</li>
<li>
Vous pouvez simplement parcourir cette liste de manifestes et les lire dans leur intégralité et dans leur environnement web d’origine (colonne de droite).
</li>
<li>
Si vous cliquez sur la petite icône placée à côté du titre du manifeste, vous pouvez lire le manifeste à travers le prisme de l’algorithme TD-IDF. Cet algorithme permet d’identifier les mots les plus importants au sein d’un document. Il est crucial pour un grand nombre de moteurs de recherche en ligne. Il a été développé en partie par l’informaticienne britannique Karen Spärck Jones. Pour en savoir plus sur son mode de fonctionnement, voir <a href="/{{ lang }}/about">a propos</a>.
</li>
</ol>
</div>
{% endblock %}
{% block suggestions %}
<h1>Suggestions de lectures croisées (sélection manuelle):</h1>
<div>
{% for word in suggestions %}
<strong class="query"><a href="/{{ lang}}/?q={{ word.strip() }}">{{ word.strip() }}</a></strong>
{% endfor %}
</div>
<br>
<h1>Suggestions de lectures croisées (sélection des algorithmes):</h1>
<div>
{% for word in mappings %}
<strong class="query"> <a href="/{{ lang }}/?q={{ word.strip() }}">{{ word.strip() }}</a> </strong>
{% endfor %}
</div>
<br>
<p>Pour en lire plus au sujet <a href="/{{ lang}}/mappings/{{ filenames[0] }}">de l’algorithme TF-IDF et du mapping de contraste</a>.</p>
<br>
<br>
{% endblock %}

17
templates/fr/manifesto.html

@ -1,17 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{% endblock %}
{% block search %}
{% endblock %}
{% block content %}
{% endblock %}
{% block manifesto %}
<div id="manifesto_content_wrapper">
{% for line in manifesto %}
<p>{{ line | replace(' •', ' ') }}<br></p>
{% endfor %}
<br>
</div>
{% endblock %}

58
templates/fr/mappings-name.html

@ -1,58 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{% endblock %}
{% block search %}
{% endblock %}
{% block results %}
<div class="cross">
<p class="note">[Note sur les mappings de contraste]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<code>
def tfidf(query, words, corpus):<br /><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Term Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for word in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query == word:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tf = tf_count/len(words)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Inverse Document Frequency<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count = 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for words in corpus:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if query in words:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idf_count += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tfidf_value = tf * idf<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return tf_count, tf_count, tfidf_value
</code>
<br><br>
L’algorithme TF-IDF, formaté ci dessus dans le language de programmation Python, intègre un niveau de contraste au sein du texte, sous une forme numérique. Les mots se démarquant le plus fortement sont considérés par l’algorithme comme les plus importants pour ce texte.
<br><br>
Ces mappings de contraste permettent une lecture simultannée des manifestes et de l’algorithme.
<br><br>
Les valeurs TF-IDF sont calculées en deux étapes. Premièrement, l’algorithme compte la fréquence <em>Term Frequency (TF)</em> en recherchant l’apparition d’un mot dans le texte, proportionellement au nombre total de mots au sein de ce texte. Cette façon de rechercher la fréquence rend possible la comparaison du nombre de mots entre des documents de largeur variable. Ceci rend la comparaison possible entre le très long <em>Manifeste Cyborg</em> de Donna Haraway (1984) et le Call for Feminist Data de Caroline Sinders (2018), lui-même relativement succint.
<br><br>
Lors de la seconde étape, l’algorithme établira un comptage comparatif avec tous les autres documents dans l’ensemble donné, en utilisant la partie <em>Inversed Document Frequency (IDF)</em>. Cette partie de l’algorithme, qui constitue la contribution de Karen Spärck Jones, a introduit une forme subtile d’inversion relative à travers tous les documents d’un ensemble donné. Plutôt que de se limiter à un calcul de fréquence au sein d’un document, Karen a proposé de comparer cette fréquence entre tous les documents. Cela signifie que lorsqu’un mot n’apparaît qu’au sein d’une quantité très restreinte de documents, sa valeur sera élargie.
<br><br>
En conséquence, des mots tels que <em>“le”</em>, <em>“elle”</em> ou <em>“il”</em> obtiendront un nombre très petit, puisqu’ils apparaissent fréquemment. Le terme paranodal n’apparaît que 4 fois dans A Feminist Server Manifesto. Il s’agit d’un terme très fort et specifique, n’apparaissant dans aucun autre du corpus.
<br><br>
Autre cas de figure est <em>SCUM</em>. Bien que le mot <em>SCUM</em> ne soit pas le mot le plus utilisé dans le <em>S.C.U.M Manifesto</em>, il s’agit du mot obtenant le score le plus élevé: en comparaison avec tous les autres manifestes, le mot <em>SCUM</em> est principalement utilisé dans cet ouvrage ce qui a pour conséquence d’augmenter son score très fortement.
</p>
</div>
<div id="mappings">
<h1>{{ manifesto | prettyfilename }}</h1>
{% for sentence in mappings %}
<p class="sentence">
{% for word, tfidf in sentence %}
<strong class="query" style="font-size:{{ 50 + tfidf }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
</p>
{% endfor %}
</div>
{% endblock %}
{% block suggestions %}
{% endblock %}

27
templates/fr/ordered.html

@ -1,27 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{% endblock %}
{% block txtlist %}
{% endblock %}
{% block results %}
<h1>lists</h1>
<div id="listing_per_manifesto" class="listings">
{% for manifesto, words in results.items()|sort %}
<span class="result">
<div class="ascii">
/\|\/\<br>
_)&nbsp;&nbsp;&nbsp;&nbsp;(__<br>
\_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_/ <br>
)&nbsp;&nbsp;&nbsp;&nbsp;\ <br>
\/\|\/
</div>
<h2>{{manifesto}}</h2>
{% for value, word in words %}
<strong style="font-size:{{value * 50000}}%;"><a href="{{ url_for('index')}}?q={{word}}">{{word}}</a></strong>
{% endfor %}
</span>
{% endfor %}
<hr>
</div>
{% endblock %}

125
templates/fr/results.html

@ -1,125 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{{ query }} - cyber/technofeminist cross-readings{% endblock %}
{% block nav %}
<div id="print" class="blink {{ connection }}">
<a href="?q={{ query }}&print=now"><img src="/static/images/epson.png"></a>
</div>
<script>
(function () {
var printing = false,
button = document.querySelector('#print a');
button.addEventListener('click', function (e) {
if (!printing) {
printing = true;
button.classList.add('printing');
}
else {
e.preventDefault();
alert('Already printing ...');
}
})
})();
</script>
{% endblock %}
{% block results %}
{% if results == {} %}
<div id="notused">Ce mot n'a pas pu être trouvé.</div>
{% else %}
<div class="cross">
<p class="note">[Note sur les résultats de recherche]</p>
<p class="tfidf">Lorsqu’une requête est soumise, le <em>TF-IDF</em> commence à parcourir la totalité des manifestes de l’ensemble donné afin de vérifier si un mot y est utilisé, et si c’est le cas, de l’ajouter à la liste des résultats. Le tri au sein de la liste est effectué en fonction de l’importance du mot <strong>{{ query }}</strong> à l’intérieur de chaque manifeste.</p>
<p class="techfem">Les résultats de recherche sont des extraits, des déclarations, des citations ou des questions, reliés entre eux par un mot unique, formant un index de lecture croisée autour de <strong>{{ query }}</strong>. Les occurrences de <strong>{{ query }}</strong> dans chaque manifeste augmentent la complexité des relations qu’ils entretiennent. </p>
<br>
<br>
</div>
<div id="results">
<h1>Lecture transversale des manifestes selon l’axe de <strong class="query">{{ query }}</strong>:</h1>
<div class="results">
{% for x, manifesto in results.items() %}
{% for sentence in manifesto.html %}
<div id="{{ x }}_{{ loop.index }}" class="result">
<div class="title">
{{ manifesto.name }}
</div>
<div class="sentence">{{ sentence }}</div>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
{% endif %}
{% if analytics %}
<div id="analytics">
<h1>SUGGESTIONS</h1>
{% if analytics.stemmer %}
<div id="similars" class="analytics stemmer">
<h2>Similaire mais différent de <em>{{ query }}</em>:</h2>
{% for word in analytics.stemmer %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endfor%}
</div>
<br>
{% endif%}
</div> <!-- #analytics -->
{% endif%}
{% endblock %}
{% block suggestions %}
<div id="suggestions">
<div class="suggestions techfem">
<h1>Suggestions de lectures croisées (sélection manuelle):</h1>
{% for word in suggestions %}
<strong class="query"><a href="?q={{word}}">{{ word.strip() }}</a></strong>
{% endfor %}
</div>
{% if analytics.mappings %}
<br>
<div class="suggestions tfidf">
<h1>Suggestions de lectures croisées (sélection des algorithmes) à <em>{{ results[0]['name']}}</em>: <br></h1>
<div class="">
{% for tfidf, word in analytics.mappings[:50] %}
{% if word == query %}
<strong class="word">{{ word }}</strong>
{% else %}
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endif%}
{% endfor%}
</div>
<br>
<br>
<div><a class="contrast" href="/{{ lang}}/mappings/{{ results[0]['filename'].strip() | replace('.txt','') }}">Pour approfondir l’exploration du mapping <br>de contraste appliqué au texte entier <br>(<em>{{ results[0]['name'].strip() }}</em>) par ici ◐.</a></div>
</div>
{% endif%}
</div>
<div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
L’algorithme <em>TF-IDF</em> est un catalyseur, générant des connections multidimentionelles à travers un ensemble de mots, qui constituent ici les données.
<br><br>
Tel un guide pour le lecteur, l’algorithme délivre un classement, en décidant de l’importance du terme de recherche au sein de chaque manifeste.
</p>
<p class="techfem">
Les <em>manifestes cyber et technoféministes</em> sont écrits et publiés dans un but d’application. Ils émettent des déclarations sur les intentions, motivations et vues spécifiques sur la technologie. Leurs styles d’écriture, aussi différents soient-ils, sont souvent basés sur la mise en forme de déclarations courtes, voire même militantes.
<br><br>
<em>«Rien ne devrait être admis comme figé, permanent ou «donné» – ni les conditions matérielles ni les formes sociales»</em> (Manifeste Xénoféministe), <br>
<em>«Voilà pourquoi aucune révolution ne doit lui rester étrangère.»</em> (Le manifeste de la femme futuriste)
</p>
</div>
<!--
<h1>Request conditional fragments:</h1>
<div id="suggestions">
{% for word in conditionals %}
<strong class="query"><a href="?q={{ word }}&conditional=True">{{ word.strip() }}</a></strong>
{% endfor %}
</div> -->
{% endblock %}

26
tfidf.py

@ -16,25 +16,16 @@ def tfidf(query, words, corpus):
if query == word:
tf_count += 1
tf = tf_count/len(words)
# print('TF count:', tf_count)
# print('Total number of words:', len(words))
# print('TF - count/total', tf_count/len(words))
# Inverse Document Frequency
idf_count = 0
for words in corpus:
if query in words:
idf_count += 1
# print('count:', idf_count)
idf = log(len(corpus)/idf_count)
# print('Total number of documents:', len(corpus))
# print('documents/count', len(corpus)/idf_count)
# print('IDF - log(documents/count)', log(len(corpus)/idf_count))
tfidf_value = tf * idf
# print('TF-IDF:', tfidf_value)
return tf_count, tf_count, tfidf_value
return tf_count, idf_count, tfidf_value
def get_language(manifesto):
language = re.search(r'\[.*\]', manifesto, flags=re.IGNORECASE).group().replace('[','').replace(']','').lower()
@ -50,12 +41,10 @@ def load_text_files():
for manifesto in sorted(os.listdir(dir)):
manifesto = manifesto.replace('.txt','')
# print('Manifesto:', manifesto)
language = get_language(manifesto)
if language == 'en+de+nl+fr': # exception for OBN manifesto
language = 'en'
languages[manifesto] = language
# print('Language:', language)
lines = open('{}/{}.txt'.format(dir, manifesto), "r").read() # list of lines in .txt file
lines = lines.replace('', '. ') # turn custom linebreaks into full-stops to let the tokenizer recognize them as end-of-lines
words = [word for word in tokenizer.tokenize(lines)] # all words of one manifesto, in reading order
@ -109,9 +98,12 @@ def create_index():
if 'tfidf' not in index[manifesto]:
index[manifesto]['tfidf'] = {}
index[manifesto]['tfidf'][word] = tfidf_value
# if 'tf' not in index[manifesto]:
# index[manifesto]['tf'] = {}
# index[manifesto]['tf'][word] = tf_count
if 'idf' not in index[manifesto]:
index[manifesto]['idf'] = {}
index[manifesto]['idf'][word] = idf_count
if 'tf' not in index[manifesto]:
index[manifesto]['tf'] = {}
index[manifesto]['tf'][word] = tf_count
index[manifesto]['name'] = make_human_readable_name(manifesto)
index[manifesto]['language'] = language
@ -121,4 +113,6 @@ def create_index():
out.close()
print('*index created*')
# create_index()
if __name__ == '__main__':
create_index()

52
words.txt

@ -1,52 +0,0 @@
différence
feminist
noise
hack
machine
code
local
error
virus
radical
cyborg
réseau
personal
technology
technologie
clitoris
matrix
difference
DIY
binary
hybrid
grrrl
girls
open
free
tools
fight
conflict
software
hardware
gender
network
connection
cyberspace
alien
imagination
future
emancipatory
banana
fiction
virtual
capitalism
bodies
glitch
power
automation
agency
travail
genre
intimate
Loading…
Cancel
Save