As I (and others) have argued elsewhere (Van Zundert 2016., Van Zundert & Andrews 2016) interfaces are questionable goodies. Certainly if we are trying to uncover the outlines of a new computational literacy that would serve hermeneutic purposes in the scholarly domain, then hiding the code behind several layers of interface is part of the problem rather than the solution. Yet we cannot do without interface when we are working with any (digital) computational technology. Even computer languages themselves are in fact interfaces towards underlying machine code, byte code and eventually the hardware flipflops within the microchips of computers themselves. Graphical interfaces are the top most interfaces of a stack of interfaces that stand between the user and what is actually going on inside the computer. These interfaces are not neutral lenses, they filter, transform, and adapt digital information into a form that designers, engineers, and computer scientists think are suitable to users of any or a particular kind. The point of this notebook is to argue and search for a computational literacy that allows humanities researchers to engage with text through code in a more hermeneutic fashion, focusing away a bit from the well trodden paths of big data and statistic modeling.
In this respect chapter 4 of this notebook comes far more closer to what I have in mind than the currently last chapter on visualization. There we find the start of an attempt to OO model the parts of a text. If anything it is the work of that chapter that should be discussed, progressed, and elaborated, much rather than to package up the results in some visualization which in many respects is more of an end than the start of a journey.
Yet, no computational humanities application feels remotely complete at this moment in time without some visualization. Hence we try to add some wow-factor in this chapter. I contend however that like authors write novels and scholars learned books, at some point New Literacy will make writing the hybrid form of code and text as found in this notebook by far complete enough. Reaching that point would indeed mean a New Literacy has taken root within humanities (or well beyond) as a new semiotic to speak of and about culture and science.
As the focus switches from an 'internal' object oriented modeling towards the 'external' visualization, I need to switch to a different tool set. The Jupyter Notebook at this moment (it is Wednesday June 8th of 2016 when I write this) does support Ruby, but the iRuby back end (or kernel) is not very well adapted yet to outputting anything different than text results. So it will not allow me to inject HTML, SVG or any other formats nicely fit for creating visualizations. That is why this chapter is partly written in Python. Actually only very partly, just enough to allow me to write the most part in Javascript, CSS and HTML.
This note book integration code for this visualization is greatly indepted to the example for integrating technologies into Jupyter Notebooks given by Brian Coffey and summarized by K. Hong. The visualization is based on the ideas of hive plots (Krzywinski, M. et al., 2012 and the code driving the visualization is certainly indepted to the examples by Mike Bostock (https://bost.ocks.org/mike/hive/ and https://bl.ocks.org/mbostock/2066415).
In [6]:
from IPython.display import HTML
HTML('''
<script src="resources/d3/d3.min.js"></script>
<script src="resources/d3/d3.hive.min.js"></script>
''')
Out[6]:
Then we create a template that will let iPython take care of all the html chore that we need but do not want to waste time on.
In [7]:
from string import Template
html_template = Template('''
<style> $css_text </style>
<script> $js_text </script>
<div id="chart"></div>
<div id="info_text"></div>
''')
So that we can concentrate on what's mildy important, like the CSS styling…
In [8]:
css_text = '''
.axis {
stroke: #000;
stroke-width: 1.5px;
}
.node circle {
stroke: #000;
}
.link {
fill: none;
stroke: #999;
stroke-width: 1.5px;
stroke-opacity: .3;
}
.link.active {
stroke: red;
stroke-width: 2px;
stroke-opacity: 1;
}
.node circle.active {
stroke: red;
stroke-width: 3px;
}
#info_text {
height: 100px;
}
'''
And the real important JavaScript that actually takes in the data, constructs the plot, and adds a little interactivity.
In [9]:
js_text = '''
var width = 970,
height = 800,
innerRadius = 40,
outerRadius = 15000;
number_of_categories = 2
var nodes;
d3.json("./resources/visualization_data.json", function(data) {
nodes = data.nodes;
} );
var links = [];
var node_index = 0;
var last_text_node_index = nodes.length;
nodes.forEach( function( node ) {
if( node.denotation != null ){
var annotation_index = 0;
node.denotation.annotations.forEach( function( annotation ) {
var annotation_node = { x: 1, y: annotation_index, text: annotation.annotation };
nodes.push( annotation_node );
var link = {source: nodes[node_index], target: nodes[annotation_index + last_text_node_index]};
links.push( link );
annotation_index += 1;
})
}
node_index += 1;
})
// Range
var angle = d3.scale.ordinal().domain(d3.range( number_of_categories ))
.rangePoints([ 0.1 * Math.PI, 0.4 * Math.PI ]),
radius = d3.scale.linear().domain([0,1500]).range([innerRadius, outerRadius]),
color = d3.scale.category10().domain(d3.range(20));
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 100 + "," + height + ")");
svg.selectAll(".axis")
.data(d3.range( number_of_categories ) )
.enter().append("line")
.attr("class", "axis")
.attr("transform", function(d) { return "rotate(" + degrees(angle(d)) + ")"; })
.attr("x1", radius.range()[0])
.attr("x2", radius.range()[1]);
svg.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", d3.hive.link()
.angle(function(d) { return angle(d.x); })
.radius(function(d) { return radius(d.y+4); }))
.style("stroke", function(d) { return color(d.source.x); })
.on("mouseover", linkMouseover)
.on("mouseout", mouseout);
svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("transform", function(d) { return "rotate(" + degrees(angle(d.x)) + ")"; })
.attr("cx", function(d) { return radius(d.y+4); })
.attr("r", 5)
.style("fill", function(d) { return color(d.x); })
.on("mouseover", nodeMouseover)
.on("mouseout", mouseout);
function degrees(radians) {
return radians / Math.PI * 180 - 90;
}
// Highlight the link and connected nodes on mouseover.
function linkMouseover(d) {
svg.selectAll(".link").classed("active", function(p) {
if ( p === d ) { this.style="stroke: red" }
return p === d;
});
svg.selectAll(".node circle").classed("active", function(p) {
return p === d.source || p === d.target;
});
info.text(d.source.wrd + " → " + d.target.text);
}
// Highlight the node and connected links on mouseover.
function nodeMouseover(d) {
svg.selectAll(".link").classed("active", function(p) {
if ( p.source === d || p.target === d ) { this.style="stroke: red;" }
return p.source === d || p.target === d;
});
d3.select(this).classed("active", function(p) {
this.style="stroke: red; fill: " + color(d.x) + ";";
return true;
});
info.text(d.wrd);
}
// Clear any highlighted nodes or links.
function mouseout(d) {
svg.selectAll(".active").classed("active", function(p) {
var style;
if( p.source != null ) {
style = "stroke: " + color(p.source.x) + ";";
} else {
style = "stroke: " + color(p.x) + "; fill: " + color(p.x) + ";";
}
this.style = style;
return false;
});
info.text(defaultInfo);
}
// Initialize the info display.
var info = d3.select("#info_text")
.text(defaultInfo = "Move over nodes or links to browse data");
'''
And finally we can combine the CSS and JS code with the template, which will add the visualization into the output of the cell below.
In [10]:
HTML(html_template.substitute({'css_text': css_text, 'js_text': js_text}))
Out[10]:
What do we see? Basically the chart plots the words of the text (blue) and the annotations made on the text (orange). It also expresses by connectors which annotations are connected to which words. Moving over the dots and connectors reveals some information tied to the nodes and edges. Because I have so far only annotated the first word we end up with a fairly simple chart obviously. When the network of add sources (each source would add an axis) grows and the net of annotations thickens, the plot will become more interesting to view.
Again however, I would stress that this is just one of a million interfaces/visualizations we could put over or on the object model that I have been starting on in chapter 4. I picked this visualization because of its aesthetics mostly, and because it seems to be a good choice to gain some overview of complex networks. However, does it reveal anything scholarly useful about the object of the scholarly knowledge and activity that went into creating those? I am unsure, but the hybrid computer literacy that underlies or instance chapter 4 seems to me to be much more revealing of such. Including, to be fair, the little power we can still wield hermeneutically with such code in New Literacy. More practice and experimenting is needed to develop and understand the make up and mechanism of this New Literacy.
Zundert van, J.J., 2016. The Case of the Bold Button: Social Shaping of Technology and the Digital Scholarly Edition. Digital Scholarship in the Humanities. Available at: http://dsh.oxfordjournals.org/content/early/2016/03/06/llc.fqw012 [Accessed June 8, 2016].
Zundert van, J. & Andrews, T.L., 2016. Apparatus vs. Graph: New Models and Interfaces for Text. In F. Hadler & J. Haupt, eds. Interface Critique. Kaleidogramme. Berlin: Kulturverlag Kadmos.
Krzywinski, M. et al., 2012. Hive plots—rational approach to visualizing networks. 2012; 13:627-644. Briefings in Bioinformatics, 13(5), pp.627–644.
</small>
In [ ]: