Draw audio feature bar charts
Started work on drawing the bar charts for audio features.
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from .models import Track, Artist, AudioFeatures, User
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
admin.site.register(Track)
|
||||||
|
admin.site.register(Artist)
|
||||||
|
admin.site.register(AudioFeatures)
|
||||||
|
admin.site.register(User)
|
||||||
|
|||||||
@@ -51,10 +51,14 @@ class Track(models.Model):
|
|||||||
runtime = models.PositiveSmallIntegerField()
|
runtime = models.PositiveSmallIntegerField()
|
||||||
name = models.CharField(max_length=150)
|
name = models.CharField(max_length=150)
|
||||||
users = models.ManyToManyField(User, blank=True)
|
users = models.ManyToManyField(User, blank=True)
|
||||||
genre = models.CharField(max_length=30)
|
genre = models.CharField(max_length=30, default="")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
track_str = "{}, genre: {}, artists: [".format(self.name, self.genre)
|
||||||
|
for artist in self.artists.all():
|
||||||
|
track_str += "{}, ".format(artist.name)
|
||||||
|
track_str += "]"
|
||||||
|
return track_str
|
||||||
|
|
||||||
# }}} Track #
|
# }}} Track #
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
* Retrieves data for a specific audio feature for a certain user
|
* Retrieves data for a specific audio feature for a certain user
|
||||||
* @param audioFeature: the audio feature for which data will be retrieved
|
* @param audioFeature: the audio feature for which data will be retrieved
|
||||||
* @param clientSecret: the client secret, needed for security
|
* @param clientSecret: the client secret, needed for security
|
||||||
|
* @param chartElement: the SVG element in which the data will be plotted
|
||||||
*/
|
*/
|
||||||
function getAudioFeatureData(audioFeature, userSecret) {
|
function plotAudioFeatureData(audioFeature, userSecret, chartElement) {
|
||||||
let httpRequest = new XMLHttpRequest();
|
let httpRequest = new XMLHttpRequest();
|
||||||
/*
|
/*
|
||||||
* Handler for the response
|
* Handler for the response
|
||||||
@@ -12,10 +13,7 @@ function getAudioFeatureData(audioFeature, userSecret) {
|
|||||||
if (httpRequest.readyState === XMLHttpRequest.DONE) {
|
if (httpRequest.readyState === XMLHttpRequest.DONE) {
|
||||||
if (httpRequest.status === 200) {
|
if (httpRequest.status === 200) {
|
||||||
let responseData = JSON.parse(httpRequest.responseText);
|
let responseData = JSON.parse(httpRequest.responseText);
|
||||||
// TODO: The data points need to be plotted instead
|
|
||||||
for (let data of responseData.data_points) {
|
|
||||||
console.log(data);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
alert("There was a problem with the login request, please try again!");
|
alert("There was a problem with the login request, please try again!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,71 @@
|
|||||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
|
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
<p>Logged in as {{ id }}</p>
|
<p>Logged in as {{ id }}</p>
|
||||||
|
<script src="https://d3js.org/d3.v5.js"></script>
|
||||||
<script src="{% static "spotifyvis/scripts/user_data.js" %}"></script>
|
<script src="{% static "spotifyvis/scripts/user_data.js" %}"></script>
|
||||||
<script>
|
<script>
|
||||||
sessionStorage.setItem('user_secret', "{{ user_secret }}");
|
sessionStorage.setItem('user_secret', "{{ user_secret }}");
|
||||||
getAudioFeatureData('instrumentalness', sessionStorage.getItem('user_secret'));
|
let width = 480, height = 300;
|
||||||
|
|
||||||
|
let instrumData = {
|
||||||
|
"0-0.25": 0,
|
||||||
|
"0.25-0.5": 0,
|
||||||
|
"0.5-0.75": 0,
|
||||||
|
"0.75-1.0": 0,
|
||||||
|
};
|
||||||
|
// define the vertical scaling function
|
||||||
|
let vScale = d3.scaleLinear().range([height, 0]);
|
||||||
|
|
||||||
|
// getAudioFeatureData('instrumentalness', sessionStorage.getItem('user_secret'));
|
||||||
|
d3.json("{% url 'get_audio_feature_data' audio_feature='instrumentalness' client_secret=user_secret %}")
|
||||||
|
.then(function(response) {
|
||||||
|
for (let dataPoint of response.data_points) {
|
||||||
|
dataPoint = parseFloat(dataPoint);
|
||||||
|
if (dataPoint > 0.75) {
|
||||||
|
instrumData["0.75-1.0"] += 1;
|
||||||
|
} else if (dataPoint > 0.5) {
|
||||||
|
instrumData["0.5-0.75"] += 1;
|
||||||
|
} else if (dataPoint > 0.25) {
|
||||||
|
instrumData["0.25-0.5"] += 1;
|
||||||
|
} else {
|
||||||
|
instrumData["0-0.25"] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dataSet = Object.values(instrumData);
|
||||||
|
let dataRanges = Object.keys(instrumData); // Ranges of audio features, e.g. 0-0.25, 0.25-0.5, etc
|
||||||
|
let dataArr = [];
|
||||||
|
// turn the counts into an array of objects, e.g. {range: "0-0.25", counts: 5}
|
||||||
|
for (let i = 0; i < dataRanges.length; i++) {
|
||||||
|
dataArr.push({
|
||||||
|
range: dataRanges[i],
|
||||||
|
counts: instrumData[dataRanges[i]]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
vScale.domain([0, d3.max(dataSet)]);
|
||||||
|
|
||||||
|
let hScale = d3.scaleBand().domain(dataRanges).rangeRound([0, width]);
|
||||||
|
|
||||||
|
let barWidth = width / dataSet.length;
|
||||||
|
|
||||||
|
let instrumSVG = d3.select('body')
|
||||||
|
.append('svg').attr('width', width).attr('height', height);
|
||||||
|
|
||||||
|
let xAxis = d3.axisBottom().scale(hScale);
|
||||||
|
let yAxis = d3.axisLeft().scale(vScale);
|
||||||
|
|
||||||
|
let instrumBar = instrumSVG.selectAll('g')
|
||||||
|
.data(dataArr)
|
||||||
|
.enter().append('g')
|
||||||
|
.attr("transform", function(d) { return "translate(" + hScale(d.range) + ",0)"; });
|
||||||
|
|
||||||
|
instrumBar.append('rect')
|
||||||
|
.attr('y', function(d) { return vScale(d.counts); })
|
||||||
|
.attr("height", function(d) { return height - vScale(d.counts); })
|
||||||
|
.attr("width", function(d) { return hScale(d.range); });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -401,11 +401,10 @@ def get_artists_in_genre(user, genre):
|
|||||||
:returns: dict of artists in the genre along with the number of songs they
|
:returns: dict of artists in the genre along with the number of songs they
|
||||||
have.
|
have.
|
||||||
"""
|
"""
|
||||||
artist_counts = (Artist.objects.filter(track__users=user)
|
artist_counts = (Artist.objects.filter(track__users=user).distinct()
|
||||||
.filter(track__genre=genre)
|
.filter(track__genre=genre).distinct()
|
||||||
# .annotate(num_songs=Count('track', filter=Q(track__genre=genre)))
|
.annotate(num_songs=Count('track'))
|
||||||
.annotate(num_songs=Count('track'))
|
)
|
||||||
)
|
|
||||||
processed_artist_counts = [{'name': artist.name, 'num_songs': artist.num_songs} for artist in artist_counts]
|
processed_artist_counts = [{'name': artist.name, 'num_songs': artist.num_songs} for artist in artist_counts]
|
||||||
# pprint.pprint(processed_artist_counts)
|
# pprint.pprint(processed_artist_counts)
|
||||||
return processed_artist_counts
|
return processed_artist_counts
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ def test_db(request):
|
|||||||
"""TODO
|
"""TODO
|
||||||
"""
|
"""
|
||||||
# user_id = "polarbier"
|
# user_id = "polarbier"
|
||||||
user_id = "35kxo00qqo9pd1comj6ylxjq7"
|
user_id = "chrisshyi13"
|
||||||
context = {
|
context = {
|
||||||
'user_secret': User.objects.get(user_id=user_id).user_secret,
|
'user_secret': User.objects.get(user_id=user_id).user_secret,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user