Browse Source

Fix genre graph not displaying

- take top genres/artists for graphs
- improve graphs' appearance
- update pip packages
master
Kevin Mok 5 years ago
parent
commit
670693203e
Signed by: Kevin-Mok GPG Key ID: AEA75288DC135CF5
  1. 10
      api/utils.py
  2. 29
      api/views.py
  3. 27
      graphs/static/graphs/scripts/genre_graph.js
  4. 8
      graphs/templates/graphs/genre_graph.html
  5. 49
      requirements.txt
  6. 2
      update-history.sh

10
api/utils.py

@ -222,9 +222,13 @@ def get_artists_in_genre(user, genre):
processed_artist_counts = {}
for artist in user_artists:
processed_artist_counts[artist.name] = round(artist.track_set
.filter(genre=genre_obj, users=user)
.count() * track_count / total_artist_counts, 2)
# TODO: figure out collab problem #
# artist_count = math.floor(artist.track_set.filter(genre=genre_obj,
# users=user).count() * track_count / total_artist_counts)
artist_count = artist.track_set.filter(genre=genre_obj,
users=user).count()
if artist_count > 0:
processed_artist_counts[artist.name] = artist_count
return processed_artist_counts
# }}} get_artists_in_genre #

29
api/views.py

@ -141,7 +141,7 @@ def get_artist_data(request, user_secret):
artist_counts = Artist.objects.annotate(num_songs=Count('track',
filter=Q(track__users=user)))
processed_artist_counts = [{'name': artist.name, 'num_songs': artist.num_songs}
for artist in artist_counts]
for artist in artist_counts if artist.num_songs > 1]
if CONSOLE_LOGGING:
pprint(processed_artist_counts)
return JsonResponse(data=processed_artist_counts, safe=False)
@ -175,7 +175,6 @@ def get_audio_feature_data(request, audio_feature, user_secret):
# get_genre_data {{{ #
def get_genre_data(request, user_secret):
"""Return genre data needed to create the graph
TODO
@ -187,27 +186,17 @@ def get_genre_data(request, user_secret):
# annotates each genre and not each Track, due to the earlier values() call
.annotate(num_songs=Count('genre'))
)
genre_counts = [genre_dict for genre_dict in genre_counts if
genre_dict['num_songs'] > 3]
# genre_counts is a QuerySet with the format
# [{'genre': 'classical', 'num_songs': 100}, {'genre': 'pop', 'num_songs': 50}...]
for genre_dict in genre_counts:
genre_dict['artists'] = get_artists_in_genre(user, genre_dict['genre'])
'''
Now genre_counts has the format
[
{'genre': 'classical',
'num_songs': 100,
'artists': {
'Helene Grimaud': 40.5,
'Beethoven': 31.2,
'Mozart': 22...
}
},
{'genre': 'pop',
'num_songs': 150,
'artists': {...}
},...
]
Now genre_counts has the format [ {'genre': 'classical', 'num_songs': 100,
'artists': { 'Helene Grimaud': 40.5, 'Beethoven': 31.2, ... }},... ]
'''
for genre_dict in genre_counts:
genre_dict['artists'] = get_artists_in_genre(user, genre_dict['genre'])
if CONSOLE_LOGGING:
print("*** Genre Breakdown ***")
pprint(list(genre_counts))

27
graphs/static/graphs/scripts/genre_graph.js

@ -25,7 +25,7 @@ function create_genre_graph(data) {
// y.domain([0, d3.max(data, function(d) { return d.num_songs; }) * 1.25]).nice();
y.domain([0, d3.max(data, function(d) {
return d.num_songs; // returns the maximum number of songs in the genre
})]).nice();
}) * 1.6]).nice();
// }}} domains //
@ -37,6 +37,9 @@ function create_genre_graph(data) {
let colorScale = d3.scaleOrdinal().range(randomColor({
count: max_artists,
luminosity: 'light',
// hue: '#3399FF',
// hue: '#00ced1',
hue: '#0099CC',
}));
// }}} setup bar colors //
@ -72,8 +75,8 @@ function create_genre_graph(data) {
.attr("height", d => y(d.data[0]) - y(d.data[1]))
.attr("width", x.bandwidth())
.attr('fill', (d, i) => colorScale(i))
// keep 3 significant figures in the song count label
.append('title').text(d => d.key + ': ' + (d.data[1] - d.data[0]).toPrecision(3));
.style('font-size', '1.5em')
.append('title').text(d => d.key + ': ' + (d.data[1] - d.data[0]).toPrecision(1));
// }}} add bars //
@ -84,6 +87,7 @@ function create_genre_graph(data) {
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll(".tick text")
.style('font-size', '1.5em')
.call(wrap, x.bandwidth());
// }}} x-axis //
@ -97,13 +101,26 @@ function create_genre_graph(data) {
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("fill", "white")
.style('font-size', '2em')
.attr("text-anchor", "start")
.text("Songs");
// }}} y-axis //
// title {{{ //
g.append("text")
.attr('x', (width / 2))
.attr('y', (margin.top / 2))
.attr('fill', "white")
.attr('text-anchor', 'middle')
.attr("font-weight", "bold")
.style('font-size', '2em')
.text('Genre Graph (With Artists)');
// }}} title //
}
}

8
graphs/templates/graphs/genre_graph.html

@ -14,13 +14,14 @@
<title>Genre Graph</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" href="{% sass_src 'scss/custom.scss' %}"> -->
<link rel="stylesheet" href="{% sass_src 'scss/custom.scss' %}">
</head>
<!-- }}} header -->
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.5.2/randomColor.min.js"></script>
{% load static %}
<script src="{% static "graphs/scripts/genre_graph.js" %}"></script>
@ -35,9 +36,10 @@
</div>
</div>
</div>
<svg id="genre-graph" width="600" height="400"
{% comment %} <svg id="genre-graph" width="600" height="400"
viewBox="0 0 600 400"
perserveAspectRatio="xMinYMid">
perserveAspectRatio="xMinYMid"> {% endcomment %}
<svg id="genre-graph" width="1500" height="900">
</svg>
<script>
let svg = d3.select("svg"),

49
requirements.txt

@ -1,40 +1,37 @@
astroid==2.0.4
certifi==2018.10.15
astroid==2.2.4
certifi==2018.11.29
chardet==3.0.4
Django==2.1.3
django-appconf==1.0.2
defusedxml==0.5.0
Django==2.1.7
django-appconf==1.0.3
django-compressor==2.2
django-crispy-forms==1.7.2
django-filter==2.0.0
django-filter==2.1.0
django-sass-processor==0.7.2
django-tables2==2.0.3
djangorestframework==3.9.0
docopt==0.6.2
django-tables2==2.0.5
djangorestframework==3.9.2
et-xmlfile==1.0.1
idna==2.7
isort==4.3.4
idna==2.8
isort==4.3.12
jdcal==1.4
lazy-object-proxy==1.3.1
libsass==0.16.0
libsass==0.17.0
mccabe==0.6.1
odfpy==1.3.6
openpyxl==2.5.10
pkg-resources==0.0.0
psycopg2==2.7.6.1
psycopg2-binary==2.7.6.1
pylint==2.1.1
python-dateutil==2.7.5
pytz==2018.7
odfpy==1.4.0
openpyxl==2.6.1
psycopg2-binary==2.7.7
pylint==2.3.1
python-dateutil==2.8.0
pytz==2018.9
PyYAML==3.13
rcssmin==1.0.6
requests==2.20.1
rjsmin==1.0.12
six==1.11.0
requests==2.21.0
rjsmin==1.1.0
six==1.12.0
tablib==0.12.1
typed-ast==1.1.0
typed-ast==1.3.1
unicodecsv==0.14.1
urllib3==1.24.1
wrapt==1.10.11
xlrd==1.1.0
wrapt==1.11.1
xlrd==1.2.0
xlwt==1.3.0
yarg==0.1.9

2
update-history.sh

@ -1 +1,3 @@
#!/bin/bash
/home/kevin/coding/spotify-lib-vis/bin/python /home/kevin/coding/spotify-lib-vis/src/manage.py update-history >> /home/kevin/coding/spotify-lib-vis/src/api/management/commands/update-history.log
Loading…
Cancel
Save