diff --git a/charts.py b/charts.py
new file mode 100644
index 0000000..0107a61
--- /dev/null
+++ b/charts.py
@@ -0,0 +1,73 @@
+from svg.charts import pie
+import math
+from lxml import etree
+
+def createPie(data, gaps = 0):
+ total = sum(data.values())
+ colours = ['#268ED7','#6A4F8D', '#A03D4F','#DC7432','#F6DC3B','#76B33B', '#267B60']
+ svg = '"
+ return svg
+ # data is now in fractions
+
+def polarToCartesian(centerX, centerY, radius, angleInDegrees):
+ """
+ Adapted from http://stackoverflow.com/a/18473154
+ """
+ angleInRadians = (angleInDegrees - 90) * math.pi / 180.0;
+
+ return {
+ "x": str(centerX + (radius * math.cos(angleInRadians))),
+ "y": str(centerY + (radius * math.sin(angleInRadians)))
+ }
+
+def describeArc(x, y, radius, startAngle, endAngle):
+ """
+ Adapted from http://stackoverflow.com/a/18473154
+ """
+ start = polarToCartesian(x, y, radius, endAngle)
+ end = polarToCartesian(x, y, radius, startAngle)
+
+ largeArcFlag = "0" if endAngle - startAngle <= 180 else "1";
+
+ d = " ".join([
+ "M", start['x'], start['y'],
+ "A", str(radius), str(radius), "0", largeArcFlag, "0", end['x'], end['y']
+ ]);
+
+ return d
+
+
+ # g = pie.Pie({})
+ # options = dict(
+ # width=640,
+ # height=480,
+ # fields=list(data.keys()),
+ # graph_title='Question 7',
+ # # expand_greatest = True,
+ # show_data_labels = True,
+ # compress=False,
+ # css_inline=True,
+ # )
+ # g.__dict__.update(options)
+ # g.add_data({'data': list(data.values()), 'title': 'Female'})
+ # # g.add_data({'data': [0, 2, 1, 5, 4], 'title': 'Male'})
+ # return str(g.burn())
\ No newline at end of file
diff --git a/models.py b/models.py
index 52b6eff..c6f1ce7 100644
--- a/models.py
+++ b/models.py
@@ -47,3 +47,34 @@ class Artwork(BaseModel):
def getAges():
r = Artwork.select(fn.Distinct(Artwork.age)).dicts()
return [a['age'] for a in r]
+
+def getEmotionCountsFromArtworks(artworks):
+ emotions = {}
+ for artwork in artworks:
+ e = artwork.emotion.name
+ if e in emotions:
+ emotions[e] += 1
+ else:
+ emotions[e] = 1
+ return emotions
+
+def getEmotionFractionsFromArtworks(artworks):
+ emotions = getEmotionCountsFromArtworks(artworks)
+ total = sum(emotions.values())
+ for e in emotions:
+ emotions[e] = emotions[e] / total
+ return emotions
+
+def getAgeFractionsFromArtworks(artworks):
+ ages = {}
+ for artwork in artworks:
+ age = artwork.age
+ if age in ages:
+ ages[age] += 1
+ else:
+ ages[age] = 1
+
+ total = sum(ages.values())
+ for age in ages:
+ ages[age] = ages[age] / total
+ return ages
\ No newline at end of file
diff --git a/server.py b/server.py
index a351799..7164d30 100644
--- a/server.py
+++ b/server.py
@@ -3,6 +3,9 @@ import os
import tornado.ioloop
import tornado.web
import colour
+import charts
+from PIL import Image
+import io
models.db.connect()
@@ -25,12 +28,26 @@ class MainHandler(tornado.web.RequestHandler):
html = loader.load('index.html').generate(host=self.request.host, emotions=emotions, ages=models.getAges(), groups=models.Group.select())
self.write(html)
+class ThumbHandler(tornado.web.RequestHandler):
+ def get(self, imgId):
+ artwork = models.Artwork.select().where(models.Artwork.id == imgId).get()
+ if artwork is None:
+ self.send_error(404)
+ else:
+ img = Image.open(artwork.filename)
+ img.thumbnail((200,200))
+ fp = io.BytesIO()
+ img.save(fp, "jpeg")
+ fp.seek(0)
+ self.set_header("Content-Type","image/jpeg")
+ self.set_header("Cache-Control","max-age=2592000, public")
+ self.write(fp.read())
+
class ColourHandler(tornado.web.RequestHandler):
def get(self):
req_group = self.get_query_argument("group", default=None)
req_age = self.get_query_argument("age", default=None)
req_emotion = self.get_query_argument("emotion", default=None)
- req_elId = self.get_query_argument("elId", default="")
q = models.Artwork.select()
if req_group is not None:
@@ -42,14 +59,39 @@ class ColourHandler(tornado.web.RequestHandler):
emotion = models.Emotion.get(models.Emotion.id == req_emotion)
q = q.where(models.Artwork.emotion == emotion)
images = q
- svg = colour.getSvgFromDbImages(images, elId = req_elId)
- self.write(svg)
+ svg = colour.getSvgFromDbImages(images)
+
+ imgHtml = "";
+
+ statHtml = "";
+
+ self.write("\n".join([svg, imgHtml, statHtml]) )
if __name__ == "__main__":
print("Start server", config)
app = tornado.web.Application([
(r"/", MainHandler),
(r"/colours", ColourHandler),
- ])
+ (r"/thumbs/(\d+)", ThumbHandler),
+ ], debug=True)
app.listen(config['port'])
tornado.ioloop.IOLoop.current().start()
diff --git a/templates/index.html b/templates/index.html
index 687c60f..a163d08 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -7,6 +7,8 @@
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QAdwB3AHctbh3qAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QMFFQkN1CxOCgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAXElEQVRo3u3YQRHAIAxFwVAT1L85gopgoNdc6D4DmZ1/y8hcFc3N+XafiCcuCQQEBAQEBAQEBAQEBAQEBATkV5BRVe0Pur3TIiAgICAgICAgICAgICAgICAgIB8dr84LFaZAYuYAAAAASUVORK5CYII=');
font-family: monospace;
font-size: 12pt;
+ height:100%;
+ margin:0;
}
body.loading #colourImage{
opacity: 0;
@@ -17,6 +19,9 @@
position: absolute;
left:0;top:0;right:0;bottom: 0;
}
+ aside{
+ padding:0.3em;
+ }
aside ul{
list-style: none;
}
@@ -42,8 +47,26 @@
float:left;
}
+ aside#works{
+ display:none;
+ float:left;
+ width:5em;
+ overflow-y: auto;
+ height:100vh;
+ margin-left:1em;
+ }
+ aside#works img{
+ width:100%;
+ }
+
aside#stats{
float:right;
+ text-align: center;
+ padding-right:1em;
+ }
+ aside#stats svg{
+ width:15em;
+ height:15em;
}
#spinner{
@@ -123,10 +146,11 @@
}
function transferComplete(evt, r)
{
- // console.log(evt);
var div = document.createElement('div');
div.innerHTML = evt.target.response;
document.getElementById('colourImage').innerHTML = div.children[0].innerHTML;
+ document.getElementById('works').innerHTML = div.children[1].innerHTML;
+ document.getElementById('stats').innerHTML = div.children[2].innerHTML;
document.body.classList.remove('loading');
}
function transferFailed(evt)
@@ -139,26 +163,36 @@
}
var links = document.getElementById('selects').getElementsByTagName("li");
+
+ function loadResults(type, value)
+ {
+ document.body.classList.add('loading');
+ // document.getElementById('colourImage').innerHTML = "";
+ var oReq = new XMLHttpRequest();
+ oReq.addEventListener("progress", updateProgress);
+ oReq.addEventListener("load", transferComplete);
+ oReq.addEventListener("error", transferFailed);
+ oReq.addEventListener("abort", transferCanceled);
+ oReq.open("GET", "/colours?"+type+"="+value);
+ oReq.send()
+
+ for(let unsetLink of links) {
+ if(unsetLink.dataset.param == type && unsetLink.dataset.id == value) {
+ unsetLink.classList.add('selected');
+ } else {
+ unsetLink.classList.remove('selected');
+ }
+ }
+ }
+
for(let link of links)
{
link.onclick = function() {
- document.body.classList.add('loading');
- // document.getElementById('colourImage').innerHTML = "";
- console.log('click',this.dataset.param, this.dataset.id);
- var oReq = new XMLHttpRequest();
- oReq.addEventListener("progress", updateProgress);
- oReq.addEventListener("load", transferComplete);
- oReq.addEventListener("error", transferFailed);
- oReq.addEventListener("abort", transferCanceled);
- oReq.open("GET", "/colours?"+this.dataset.param+"="+this.dataset.id+"&elId=colourImage");
- oReq.send()
-
- for(let unsetLink of links) {
- unsetLink.classList.remove('selected');
- }
- this.classList.add('selected');
+ loadResults(this.dataset.param, this.dataset.id);
}.bind(link)
}
+
+ loadResults("no", "thing");
// var colourImage = document.getElementById('colourImage');
// var i = 0;
// for(let circle of colourImage.children) {