Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Almost usable, some dodgy JS though

  • Loading branch information...
commit 8ea59708d61dcdac039bedec42e88071032ac82f 1 parent d520989
tim authored
4 forms.py
View
@@ -12,6 +12,6 @@
)
class requestForm(forms.Form):
- url = forms.URLField(help_text="please enter a URI beginning http://data.kasabi.com/dataset/discogs/")
+ url = forms.URLField(help_text="Enter the URL of a discogs artist, for example: http://www.discogs.com/artist/Frankie+Knuckles")
year = forms.IntegerField(min_value=1000, max_value=2012)
- query = forms.ChoiceField(query_choices)
+ #query = forms.ChoiceField(query_choices)
BIN  forms.pyc
View
Binary file not shown
0  manage.py 100755 → 100644
View
File mode changed
BIN  manage.pyc
View
Binary file not shown
98 templates/root.html
View
@@ -12,19 +12,42 @@
position:absolute;
left:1em;
top:1em;
+ font-family:Cambria, Georgia, 'Times New Roman', serif;
+ font-size:0.8em;
+ color:#121212;
+ /**background-color:#E5FFF6;**/
+ border-radius:2em;
+ width:450px;
+ padding-bottom:0.8em;
+}
+form p span.helptext{
+ display:block;
+ font-style:italic;
+ margin-left:91px;
+ width:300px;
}
form p label {
- width:100px;
+ width:85px;
display:inline-block;
text-align:right;
}
form input[value="find"]{
- margin-left:106px;
+ margin-left:91px;
+}
+form h2{
+ margin-left:65px;
+ text-decoration:underline;
+ font-weight:400;
+ font-weight:2em;
}
circle {
stroke-width: 1.5px;
}
-
+.legend{
+ position:absolute;
+ right:10em;
+ bottom:2em;
+}
line {
stroke: #999;
}
@@ -37,7 +60,7 @@
e.preventDefault();
var url = $('input[name="url"]').val();
var year = $('input[name="year"]').val();
- var query = $('select[name="query"]').val();
+ //var query = $('select[name="query"]').val();
var csrfmiddlewaretoken = $('input[name="csrfmiddlewaretoken"]').val();
$.ajax({
type : 'POST',
@@ -45,19 +68,21 @@
data: {
url : url,
year : year,
- query : query,
+ //query : query,
csrfmiddlewaretoken : csrfmiddlewaretoken
},
success : function(json){
- var w = $(window).width(),
+ d3.selectAll("svg").remove();
+
+ var w = $(window).width(),
h = $(window).height(),
r = 10,
fill = d3.scale.category20();
var force = d3.layout.force()
- .gravity(.01)
- .charge(-50)
- .linkDistance(60)
+ .gravity(0.05)
+ .charge(-200)
+ .linkDistance(80)
.size([w, h]);
var svg = d3.select("body").append("svg:svg")
@@ -66,7 +91,8 @@
var link = svg.selectAll("line")
.data(json.links)
- .enter().append("svg:line");
+ .enter().append("svg:line")
+ .style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll("g.node")
.data(json.nodes)
@@ -74,22 +100,65 @@
.attr("class", "node")
.call(force.drag);
+ var types = {};
+
node
.append("svg:circle")
.attr("r", r - .75)
- .style("fill", function(d) { return fill(d.group); })
- .style("stroke", function(d) { return d3.rgb(fill(d.group)).darker(); });
+ .style("fill", function(d) {
+ if(!types[d.type]){
+ types[d.type] = 1;
+ } else {
+ types[d.type]++;
+ }
+ return fill(d.type);
+ })
+ .style("stroke", function(d) { return d3.rgb(fill(d.type)).darker(); })
+ .on("click", function(d){
+ alert(d.discogs);
+ });
+
+ var legend = svg.append("svg:g")
+ .attr("class", "legend")
+ .attr("transform", "translate("+(w-100)+","+(h-40)+")scale(-1,-1)");
+
+ var types_array = (function() {
+ var a = [];
+ for(var t in types) {
+ a.push({'name':t,'value':types[t]});
+ }
+ return a;
+ })();
+
+ var labels = legend.selectAll("g.label")
+ .data(types_array)
+ .append("svg:circle")
+ .attr("r", function(d){return d.value;})
+ .style("fill", function(d){return fill(d.name);})
+ .style("stroke", function(d) { return d3.rgb(fill(t.name)).darker(); })
+ .append("svg:text")
+ .attr("class", "nodetext")
+ .attr("dx", 12)
+ .attr("dy", ".3em")
+ .text(function(d){return d.name;});
+
node
.append("svg:title")
- .text(function(d) { return d.artist; });
+ .text(function(d) { return d.discogs; });
node
.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".3em")
- .text(function(d) { return d.name; });
+ .text(function(d) {
+ if (d.title){
+ return d.title;
+ } else {
+ return d.name;
+ }
+ });
force
.nodes(json.nodes)
@@ -121,6 +190,7 @@
</head>
<body>
<form method="">
+ <h2>Visualise activity slice by year</h2>
{% csrf_token %}
{{ form.as_p}}
<input type="submit" value="find">
BIN  testBed.pyc
View
Binary file not shown
236 views.py
View
@@ -12,43 +12,61 @@
from discorrelate.forms import requestForm
from json import JSONEncoder
-import discogs_client as discogsAPI
-import pytassium
-
-def SPARQLAndRespond(dataset, query):
- response, data = dataset.select(query)
+#import discogs_client as discogsAPI
+import re
+
+def getQuery(apiKey, dataset, query):
+ import httplib2
+ import urllib
+ h = httplib2.Http(".cache")
+ baseURL = "http://api.kasabi.com/dataset/%s/apis/sparql?" % dataset
+ params = urllib.urlencode({'apikey':apiKey, 'query':query, 'output':'json'})
+ response, content = h.request(baseURL+params)
if response.status in range(200,300):
- # data now contains a dictionary of results
- #import pprint
- #pprint.pprint(data)
- return data
+ import simplejson as json
+ return json.loads(content)
else:
print "Oh no! %d %s " % (response.status, response.reason)
return False
-def jsonTree(s, p, o):
- sent = dict()
- sent[s[0][0]] = s[1][0][s[0][0]].decode()
- objects = dict()
- for i, result in enumerate(o[1]):
- node = dict()
- for varName in result:
- node[varName] = result[varName].decode()
- objects['node'+str(i)] = node
- sent[p] = objects
- return simplejson.dumps(sent)
-
-def jsonNodeLink(s,p,o):
- nodes = []
- links = []
- nodes.append({s[0][0] : s[1][0][s[0][0]].decode()})
- for i, result in enumerate(o[1]):
- node = dict()
- for varName in result:
- node[varName] = result[varName].decode()
- nodes.append(node)
- links.append({'source':0,'target':i+1,'value':10})
- return simplejson.dumps({'nodes':nodes, 'links':links})
+def flatten(results):
+ nodes, links = [], []
+ nodesLookup = {} # A dictionary to lookup which nodes have already been encountered
+ linksLookup = {} # Dictionary of tuples where (linkStart,linkFinish)
+ for subject in results:
+ if not subject in nodesLookup:
+ nodesLookup[subject] = len(nodes)
+ nodes.append({}) # add blank node, will fill with properties later
+ for predicate in results[subject]:
+ if predicate == 'http://data.rewire.it#linked':
+ # this predicate has been reserved to specify links
+ objects = results[subject][predicate]
+ for object in objects:
+ if not object['value'] in nodesLookup:
+ nodesLookup[object['value']] = len(nodes)
+ nodes.append({}) # add blank node, will fill with properties later
+
+ # now add the links
+ linkStart = nodesLookup[subject]
+ linkEnd = nodesLookup[object['value']]
+ link = (linkStart, linkEnd)
+ if not link in links:
+ linksLookup[link] = len(links)
+ links.append({'source':linkStart,'target':linkEnd,'value':1})
+ else:
+ newValue = links[linksLookup[link]]['value']+1
+ links[linksLookup[link]]['value'] = newValue
+ else:
+ # any predicate not specified as a link is added to the node as a property
+
+ #get last bit of URL to use as property name (bit after the last / or #)
+ splits = re.split(r'[/|#]', predicate)
+ propName = splits[len(splits)-1]
+ objects = results[subject][predicate]
+ for object in objects:
+ nodes[nodesLookup[subject]][propName] = object['value']
+
+ return simplejson.dumps({'nodes':nodes,'links':links})
def root(request):
if not request.POST:
@@ -57,56 +75,120 @@ def root(request):
c.update(csrf(request))
return render_to_response('root.html',c)
url = request.POST.get('url')
- query = request.POST.get('query')
+ year = request.POST.get('year')
+ #query = request.POST.get('query')
+
+
+ q="""
+ PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+ PREFIX mo: <http://purl.org/ontology/mo/>
+ PREFIX dateIssued: <http://purl.org/dc/terms/issued>
+ PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
+ PREFIX dc: <http://purl.org/dc/terms/>
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
- if query == 'labels':
- q = """
- PREFIX foaf: <http://xmlns.com/foaf/0.1/>
- PREFIX mo: <http://purl.org/ontology/mo/>
- SELECT DISTINCT ?artist ?name WHERE{
- <""" + url + """> foaf:made ?release.
- ?release mo:publisher ?label.
- ?release2 mo:publisher ?label.
- ?artist foaf:made ?release2.
- ?artist foaf:name ?name.
- }
- """
+ PREFIX INPUT: <%(url)s>
+
+ CONSTRUCT{
+ ?NODEartist1 <http://data.rewire.it#linked> ?NODErelease1;
+ foaf:name ?artist1Name;
+ mo:discogs ?artist1Discogs;
+ rdf:type ?artist1Type.
+
+ ?NODErelease1 <http://data.rewire.it#linked> ?NODElabel;
+ dc:title ?release1Title;
+ mo:discogs ?release1Discogs;
+ rdf:type ?release1Type.
+
+ ?NODElabel <http://data.rewire.it#linked> ?NODErelease2;
+ foaf:name ?labelName;
+ mo:discogs ?labelDiscogs;
+ rdf:type ?labelType.
- elif query == 'colabs':
- q = """
- PREFIX foaf: <http://xmlns.com/foaf/0.1/>
- PREFIX mo: <http://purl.org/ontology/mo/>
- PREFIX dc: <http://purl.org/dc/terms/>
- SELECT DISTINCT ?artist ?name WHERE{
- <""" + url + """> foaf:made ?release.
- ?artist foaf:made ?release.
- ?artist foaf:name ?name.
- }
- """
+ ?NODEartist2 <http://data.rewire.it#linked> ?NODErelease2;
+ foaf:name ?artist2name;
+ mo:discogs ?artist2Discogs;
+ rdf:type ?artist2Type.
+
+ ?NODErelease2 dc:title ?release2Title;
+ mo:discogs ?release2Discogs;
+ rdf:type ?release2Type.
+
+ }
+ WHERE{
+ ?NODEartist1 mo:discogs INPUT:;
+ foaf:name ?artist1Name;
+ mo:discogs ?artist1Discogs;
+ rdf:type ?artist1Type;
+ foaf:made ?NODErelease1.
- elif query == 'comps':
- q = """
- PREFIX foaf: <http://xmlns.com/foaf/0.1/>
- PREFIX mo: <http://purl.org/ontology/mo/>
- PREFIX dc: <http://purl.org/dc/terms/>
- SELECT DISTINCT ?artist ?name WHERE{
- <""" + url + """> foaf:made ?release.
- ?artist foaf:made ?release.
- ?artist foaf:name ?name.
- }
- """
+ ?NODErelease1 dateIssued: "%(year)s"^^xsd:year;
+ dc:title ?release1Title;
+ rdf:type ?release1Type;
+ mo:discogs ?release1Discogs.
+
+ # - - - - - - - - - - - - - - - - -
+
+ ?NODErelease1 mo:publisher ?NODElabel.
+
+ ?NODElabel foaf:name ?labelName;
+ mo:discogs ?labelDiscogs;
+ rdf:type ?labelType.
+
+ # - - - - - - - - - - - - - - - - -
- discogsAPI.user_agent = 'discorrelate/0.1 +http://www.rewire.it'
+ ?NODErelease2 mo:publisher ?NODElabel.
+
+ ?NODErelease2 dateIssued: "%(year)s"^^xsd:year;
+ dc:title ?release2Title;
+ mo:discogs ?release2Discogs;
+ rdf:type ?release2Type.
+
+ # - - - - - - - - - - - - - - - - -
+
+ ?NODErelease2 foaf:maker ?NODEartist2.
+
+ ?NODEartist2 foaf:name ?artist2name;
+ mo:discogs ?artist2Discogs;
+ rdf:type ?artist2Type.
+ }
+ LIMIT 100
+ """% {'url':url,'year':year}
+
+ #discogsAPI.user_agent = 'discorrelate/0.1 +http://www.rewire.it'
+ print q
apiKey = '5dac588049e18e51fead5e788dc2449e38c2077a'
- Discogs = pytassium.Dataset('discogs', apiKey)
-
- rootQuery = """PREFIX foaf: <http://xmlns.com/foaf/0.1/>
- Select ?name where{<""" + url + """> foaf:name ?name.
- }"""
- subject = SPARQLAndRespond(Discogs, rootQuery)
- results = SPARQLAndRespond(Discogs, q)
- jsonny = jsonNodeLink(subject, query, results)
+ results = getQuery(apiKey, "discogs", q)
+
+ jsonny = flatten(results)
- return HttpResponse(jsonny, content_type="application/json; charset=utf8")
+ return HttpResponse(jsonny, content_type="application/json; charset=utf8")
+
+# elif query == 'colabs':
+# q = """
+# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+# PREFIX mo: <http://purl.org/ontology/mo/>
+# PREFIX dc: <http://purl.org/dc/terms/>
+# CONSTRUCT {
+#
+# }
+# SELECT DISTINCT ?artist ?name WHERE{
+# <""" + url + """> foaf:made ?release.
+# ?artist foaf:made ?release.
+# ?artist foaf:name ?name.
+# }
+# """
+#
+# elif query == 'comps':
+# q = """
+# PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+# PREFIX mo: <http://purl.org/ontology/mo/>
+# PREFIX dc: <http://purl.org/dc/terms/>
+# SELECT DISTINCT ?artist ?name WHERE{
+# <""" + url + """> foaf:made ?release.
+# ?artist foaf:made ?release.
+# ?artist foaf:name ?name.
+# }
+# """
BIN  views.pyc
View
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.