Spaces:
Build error
Build error
| import json | |
| from urllib import request | |
| from fastapi import FastAPI | |
| from starlette.middleware.sessions import SessionMiddleware | |
| from starlette.responses import HTMLResponse, RedirectResponse | |
| from starlette.requests import Request | |
| import gradio as gr | |
| import uvicorn | |
| from fastapi.responses import HTMLResponse | |
| from fastapi.responses import RedirectResponse | |
| import pandas as pd | |
| import spotipy | |
| from spotipy import oauth2 | |
| import heatmap | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from matplotlib.patches import Circle, RegularPolygon | |
| from matplotlib.path import Path | |
| from matplotlib.projections.polar import PolarAxes | |
| from matplotlib.projections import register_projection | |
| from matplotlib.spines import Spine | |
| from matplotlib.transforms import Affine2D | |
| import matplotlib | |
| matplotlib.use('SVG') | |
| def get_features2(spotify): | |
| features = [] | |
| for index in range(0, 10): | |
| results = spotify.current_user_saved_tracks(offset=index*50, limit=50) | |
| track_ids = [item['track']['id'] for item in results['items']] | |
| features.extend(spotify.audio_features(track_ids)) | |
| df = pd.DataFrame(data=features) | |
| names = [ | |
| 'danceability', | |
| 'energy', | |
| # 'loudness', | |
| 'speechiness', | |
| 'acousticness', | |
| 'instrumentalness', | |
| 'liveness', | |
| 'valence', | |
| ] | |
| features_means = df[names].mean() | |
| return names, features_means.values | |
| def radar_factory(num_vars, frame='circle'): | |
| """ | |
| Create a radar chart with `num_vars` axes. | |
| This function creates a RadarAxes projection and registers it. | |
| Parameters | |
| ---------- | |
| num_vars : int | |
| Number of variables for radar chart. | |
| frame : {'circle', 'polygon'} | |
| Shape of frame surrounding axes. | |
| """ | |
| # calculate evenly-spaced axis angles | |
| theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False) | |
| class RadarTransform(PolarAxes.PolarTransform): | |
| def transform_path_non_affine(self, path): | |
| # Paths with non-unit interpolation steps correspond to gridlines, | |
| # in which case we force interpolation (to defeat PolarTransform's | |
| # autoconversion to circular arcs). | |
| if path._interpolation_steps > 1: | |
| path = path.interpolated(num_vars) | |
| return Path(self.transform(path.vertices), path.codes) | |
| class RadarAxes(PolarAxes): | |
| name = 'radar' | |
| PolarTransform = RadarTransform | |
| def __init__(self, *args, **kwargs): | |
| super().__init__(*args, **kwargs) | |
| # rotate plot such that the first axis is at the top | |
| self.set_theta_zero_location('N') | |
| def fill(self, *args, closed=True, **kwargs): | |
| """Override fill so that line is closed by default""" | |
| return super().fill(closed=closed, *args, **kwargs) | |
| def plot(self, *args, **kwargs): | |
| """Override plot so that line is closed by default""" | |
| lines = super().plot(*args, **kwargs) | |
| for line in lines: | |
| self._close_line(line) | |
| def _close_line(self, line): | |
| x, y = line.get_data() | |
| # FIXME: markers at x[0], y[0] get doubled-up | |
| if x[0] != x[-1]: | |
| x = np.append(x, x[0]) | |
| y = np.append(y, y[0]) | |
| line.set_data(x, y) | |
| def set_varlabels(self, labels): | |
| self.set_thetagrids(np.degrees(theta), labels) | |
| def _gen_axes_patch(self): | |
| # The Axes patch must be centered at (0.5, 0.5) and of radius 0.5 | |
| # in axes coordinates. | |
| if frame == 'circle': | |
| return Circle((0.5, 0.5), 0.5) | |
| elif frame == 'polygon': | |
| return RegularPolygon((0.5, 0.5), num_vars, | |
| radius=.5, edgecolor="k") | |
| else: | |
| raise ValueError("Unknown value for 'frame': %s" % frame) | |
| def _gen_axes_spines(self): | |
| if frame == 'circle': | |
| return super()._gen_axes_spines() | |
| elif frame == 'polygon': | |
| # spine_type must be 'left'/'right'/'top'/'bottom'/'circle'. | |
| spine = Spine(axes=self, | |
| spine_type='circle', | |
| path=Path.unit_regular_polygon(num_vars)) | |
| # unit_regular_polygon gives a polygon of radius 1 centered at | |
| # (0, 0) but we want a polygon of radius 0.5 centered at (0.5, | |
| # 0.5) in axes coordinates. | |
| spine.set_transform(Affine2D().scale(.5).translate(.5, .5) | |
| + self.transAxes) | |
| return {'polar': spine} | |
| else: | |
| raise ValueError("Unknown value for 'frame': %s" % frame) | |
| register_projection(RadarAxes) | |
| return theta | |
| def get_spider_plot(request: gr.Request): | |
| token = request.request.session.get('token') | |
| sp = spotipy.Spotify(token) | |
| names, data = get_features2(sp) | |
| theta = radar_factory(len(names), frame='polygon') | |
| fig = plt.figure(figsize=(9, 9)) | |
| ax = fig.add_axes([0, 0, 1, 1], projection='radar') | |
| # Plot the four cases from the example data on separate axes | |
| title = 'test' | |
| ax.set_rgrids([0.2, 0.4, 0.6, 0.8]) | |
| ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1), | |
| horizontalalignment='center', verticalalignment='center') | |
| ax.plot(theta, data) | |
| ax.fill(theta, data, alpha=0.25, label='_nolegend_') | |
| ax.set_varlabels(names) | |
| return fig | |
| PORT_NUMBER = 8080 | |
| SPOTIPY_CLIENT_ID = 'c087fa97cebb4f67b6f08ba841ed8378' | |
| SPOTIPY_CLIENT_SECRET = 'ae27d6916d114ac4bb948bb6c58a72d9' | |
| SPOTIPY_REDIRECT_URI = 'https://hf-hackathon-2023-01-spotify.hf.space' | |
| SCOPE = 'ugc-image-upload user-read-playback-state user-modify-playback-state user-read-currently-playing app-remote-control streaming playlist-read-private playlist-read-collaborative playlist-modify-private playlist-modify-public user-follow-modify user-follow-read user-read-playback-position user-top-read user-read-recently-played user-library-modify user-library-read user-read-email user-read-private' | |
| sp_oauth = oauth2.SpotifyOAuth(SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET, SPOTIPY_REDIRECT_URI, scope=SCOPE) | |
| app = FastAPI() | |
| app.add_middleware(SessionMiddleware, secret_key="w.o.w") | |
| async def homepage(request: Request): | |
| token = request.session.get('token') | |
| if token: | |
| return RedirectResponse("/gradio") | |
| url = str(request.url) | |
| code = sp_oauth.parse_response_code(url) | |
| if code != url: | |
| token_info = sp_oauth.get_access_token(code) | |
| request.session['token'] = token_info['access_token'] | |
| return RedirectResponse("/gradio") | |
| auth_url = sp_oauth.get_authorize_url() | |
| return "<a href='" + auth_url + "'>Login to Spotify</a>" | |
| from vega_datasets import data | |
| iris = data.iris() | |
| def scatter_plot_fn_energy(request: gr.Request): | |
| token = request.request.session.get('token') | |
| if token: | |
| sp = spotipy.Spotify(token) | |
| results = sp.current_user() | |
| print(results) | |
| df = get_features(sp) | |
| return gr.ScatterPlot( | |
| value=df, | |
| x="danceability", | |
| y="energy" | |
| ) | |
| def scatter_plot_fn_liveness(request: gr.Request): | |
| token = request.request.session.get('token') | |
| if token: | |
| sp = spotipy.Spotify(token) | |
| results = sp.current_user() | |
| print(results) | |
| df = get_features(sp) | |
| print(df) | |
| return gr.ScatterPlot( | |
| value=df, | |
| x="acousticness", | |
| y="liveness" | |
| ) | |
| def heatmap_plot_fn(request: gr.Request): | |
| token = request.request.session.get('token') | |
| if token: | |
| sp = spotipy.Spotify(token) | |
| data = heatmap.build_heatmap(heatmap.fetch_recent_songs(sp)) | |
| fig, ax = heatmap.plot(data) | |
| return fig | |
| def get_features(spotify): | |
| features = [] | |
| for index in range(0, 10): | |
| results = spotify.current_user_saved_tracks(offset=index*50, limit=50) | |
| track_ids = [item['track']['id'] for item in results['items']] | |
| features.extend(spotify.audio_features(track_ids)) | |
| df = pd.DataFrame(data=features) | |
| names = [ | |
| 'danceability', | |
| 'energy', | |
| 'loudness', | |
| 'speechiness', | |
| 'acousticness', | |
| 'instrumentalness', | |
| 'liveness', | |
| 'valence', | |
| 'tempo', | |
| ] | |
| # print (features_means.to_json()) | |
| return df | |
| def get_features(spotify): | |
| features = [] | |
| for index in range(0, 10): | |
| results = spotify.current_user_saved_tracks(offset=index*50, limit=50) | |
| track_ids = [item['track']['id'] for item in results['items']] | |
| features.extend(spotify.audio_features(track_ids)) | |
| df = pd.DataFrame(data=features) | |
| names = [ | |
| 'danceability', | |
| 'energy', | |
| 'loudness', | |
| 'speechiness', | |
| 'acousticness', | |
| 'instrumentalness', | |
| 'liveness', | |
| 'valence', | |
| 'tempo', | |
| ] | |
| features_means = df[names].mean() | |
| # print (features_means.to_json()) | |
| return features_means | |
| ########## | |
| def get_started(): | |
| # redirects to spotify and comes back | |
| # then generates plots | |
| return | |
| with gr.Blocks() as demo: | |
| gr.Markdown(" ## Spotify Analyzer 🥳🎉") | |
| gr.Markdown("This app analyzes how cool your music taste is. We dare you to take this challenge!") | |
| with gr.Row(): | |
| get_started_btn = gr.Button("Get Started") | |
| with gr.Row(): | |
| spider_plot = gr.Plot() | |
| # with gr.Row(): | |
| # with gr.Column(): | |
| # with gr.Row(): | |
| # with gr.Column(): | |
| # energy_plot = gr.ScatterPlot(show_label=False).style(container=True) | |
| # with gr.Column(): | |
| # liveness_plot = gr.ScatterPlot(show_label=False).style(container=True) | |
| with gr.Row(): | |
| gr.Markdown(" ### We have recommendations for you!") | |
| with gr.Row(): | |
| heatmap_plot = gr.Plot() | |
| with gr.Row(): | |
| gr.Markdown(" ### We have recommendations for you!") | |
| with gr.Row(): | |
| gr.Dataframe( | |
| headers=["Song", "Album", "Artist"], | |
| datatype=["str", "str", "str"], | |
| label="Reccomended Songs", | |
| value=[["Fired Up", "Fired Up", "Randy Houser"], ["Something Just Like This", "Memories... Do Not Open", "The Chainsmokers"]] # TODO: replace with actual reccomendations once get_started() is implemeted. | |
| ) | |
| demo.load(fn=get_spider_plot, outputs = spider_plot) | |
| demo.load(fn=heatmap_plot_fn, outputs = heatmap_plot) | |
| # demo.load(fn=scatter_plot_fn_energy, outputs = energy_plot) | |
| # demo.load(fn=scatter_plot_fn_liveness, outputs = liveness_plot) | |
| gradio_app = gr.mount_gradio_app(app, demo, "/gradio") | |
| uvicorn.run(app, host="0.0.0.0", port=7860) | |