CoolFace
Apppublic

trhacknon/Spotify

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
app.py328 linesDownload Raw Back to root
1import json2from urllib import request3from fastapi import FastAPI4from starlette.middleware.sessions import SessionMiddleware5from starlette.responses import HTMLResponse, RedirectResponse6from starlette.requests import Request7import gradio as gr8import uvicorn9from fastapi.responses import HTMLResponse10from fastapi.responses import RedirectResponse11import pandas as pd12 13import spotipy14from spotipy import oauth215 16import heatmap17 18import numpy as np19 20import matplotlib.pyplot as plt21from matplotlib.patches import Circle, RegularPolygon22from matplotlib.path import Path23from matplotlib.projections.polar import PolarAxes24from matplotlib.projections import register_projection25from matplotlib.spines import Spine26from matplotlib.transforms import Affine2D27import matplotlib28 29matplotlib.use('SVG')30 31 32def get_features2(spotify):33    features = []34    for index in range(0, 10):35        results = spotify.current_user_saved_tracks(offset=index*50, limit=50)36        track_ids = [item['track']['id'] for item in results['items']]37        features.extend(spotify.audio_features(track_ids))38 39    df = pd.DataFrame(data=features)40    names = [41        'danceability',42        'energy',43        # 'loudness',44        'speechiness',45        'acousticness',46        'instrumentalness',47        'liveness',48        'valence',49    ]50    features_means = df[names].mean()51    return names, features_means.values52 53 54def radar_factory(num_vars, frame='circle'):55    """56    Create a radar chart with `num_vars` axes.57 58    This function creates a RadarAxes projection and registers it.59 60    Parameters61    ----------62    num_vars : int63        Number of variables for radar chart.64    frame : {'circle', 'polygon'}65        Shape of frame surrounding axes.66 67    """68    # calculate evenly-spaced axis angles69    theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)70 71    class RadarTransform(PolarAxes.PolarTransform):72 73        def transform_path_non_affine(self, path):74            # Paths with non-unit interpolation steps correspond to gridlines,75            # in which case we force interpolation (to defeat PolarTransform's76            # autoconversion to circular arcs).77            if path._interpolation_steps > 1:78                path = path.interpolated(num_vars)79            return Path(self.transform(path.vertices), path.codes)80 81    class RadarAxes(PolarAxes):82 83        name = 'radar'84        PolarTransform = RadarTransform85 86        def __init__(self, *args, **kwargs):87            super().__init__(*args, **kwargs)88            # rotate plot such that the first axis is at the top89            self.set_theta_zero_location('N')90 91        def fill(self, *args, closed=True, **kwargs):92            """Override fill so that line is closed by default"""93            return super().fill(closed=closed, *args, **kwargs)94 95        def plot(self, *args, **kwargs):96            """Override plot so that line is closed by default"""97            lines = super().plot(*args, **kwargs)98            for line in lines:99                self._close_line(line)100 101        def _close_line(self, line):102            x, y = line.get_data()103            # FIXME: markers at x[0], y[0] get doubled-up104            if x[0] != x[-1]:105                x = np.append(x, x[0])106                y = np.append(y, y[0])107                line.set_data(x, y)108 109        def set_varlabels(self, labels):110            self.set_thetagrids(np.degrees(theta), labels)111 112        def _gen_axes_patch(self):113            # The Axes patch must be centered at (0.5, 0.5) and of radius 0.5114            # in axes coordinates.115            if frame == 'circle':116                return Circle((0.5, 0.5), 0.5)117            elif frame == 'polygon':118                return RegularPolygon((0.5, 0.5), num_vars,119                                      radius=.5, edgecolor="k")120            else:121                raise ValueError("Unknown value for 'frame': %s" % frame)122 123        def _gen_axes_spines(self):124            if frame == 'circle':125                return super()._gen_axes_spines()126            elif frame == 'polygon':127                # spine_type must be 'left'/'right'/'top'/'bottom'/'circle'.128                spine = Spine(axes=self,129                              spine_type='circle',130                              path=Path.unit_regular_polygon(num_vars))131                # unit_regular_polygon gives a polygon of radius 1 centered at132                # (0, 0) but we want a polygon of radius 0.5 centered at (0.5,133                # 0.5) in axes coordinates.134                spine.set_transform(Affine2D().scale(.5).translate(.5, .5)135                                    + self.transAxes)136                return {'polar': spine}137            else:138                raise ValueError("Unknown value for 'frame': %s" % frame)139 140    register_projection(RadarAxes)141    return theta142 143def get_spider_plot(request: gr.Request):144    token = request.request.session.get('token')145    sp = spotipy.Spotify(token)146    names, data = get_features2(sp)147 148    theta = radar_factory(len(names), frame='polygon')149 150    fig = plt.figure(figsize=(9, 9))151    ax = fig.add_axes([0, 0, 1, 1], projection='radar')152 153    # Plot the four cases from the example data on separate axes154    title = 'test'155    ax.set_rgrids([0.2, 0.4, 0.6, 0.8])156    ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),157                    horizontalalignment='center', verticalalignment='center')158 159    ax.plot(theta, data)160    ax.fill(theta, data, alpha=0.25, label='_nolegend_')161 162    ax.set_varlabels(names)163 164    return fig165 166 167PORT_NUMBER = 8080168SPOTIPY_CLIENT_ID = 'c087fa97cebb4f67b6f08ba841ed8378'169SPOTIPY_CLIENT_SECRET = 'ae27d6916d114ac4bb948bb6c58a72d9'170SPOTIPY_REDIRECT_URI = 'https://hf-hackathon-2023-01-spotify.hf.space'171SCOPE = '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'172 173sp_oauth = oauth2.SpotifyOAuth(SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET, SPOTIPY_REDIRECT_URI, scope=SCOPE)174 175app = FastAPI()176app.add_middleware(SessionMiddleware, secret_key="w.o.w")177 178@app.get('/', response_class=HTMLResponse)179async def homepage(request: Request):180    token = request.session.get('token')181    if token:182        return RedirectResponse("/gradio")183 184    url = str(request.url)185    code = sp_oauth.parse_response_code(url)186    if code != url:187        token_info = sp_oauth.get_access_token(code)188        request.session['token'] = token_info['access_token']189        return RedirectResponse("/gradio")190 191    auth_url = sp_oauth.get_authorize_url()192    return "<a href='" + auth_url + "'>Login to Spotify</a>"193 194 195 196from vega_datasets import data197 198iris = data.iris()199 200 201def scatter_plot_fn_energy(request: gr.Request):202 203    token = request.request.session.get('token')204    if token:205        sp = spotipy.Spotify(token)206        results = sp.current_user()207        print(results)208    df = get_features(sp)209    return gr.ScatterPlot(210        value=df,211        x="danceability",212        y="energy"213    )214 215def scatter_plot_fn_liveness(request: gr.Request):216    token = request.request.session.get('token')217    if token:218        sp = spotipy.Spotify(token)219        results = sp.current_user()220        print(results)221    df = get_features(sp)222    print(df)223    return gr.ScatterPlot(224        value=df,225        x="acousticness",226        y="liveness"227    )228 229def heatmap_plot_fn(request: gr.Request):230    token = request.request.session.get('token')231    if token:232        sp = spotipy.Spotify(token)233        data = heatmap.build_heatmap(heatmap.fetch_recent_songs(sp))234        fig, ax = heatmap.plot(data)235        return fig236 237 238def get_features(spotify):239    features = []240    for index in range(0, 10):241        results = spotify.current_user_saved_tracks(offset=index*50, limit=50)242        track_ids = [item['track']['id'] for item in results['items']]243        features.extend(spotify.audio_features(track_ids))244 245    df = pd.DataFrame(data=features)246    names = [247        'danceability',248        'energy',249        'loudness',250        'speechiness',251        'acousticness',252        'instrumentalness',253        'liveness',254        'valence',255        'tempo',256    ]257 258    # print (features_means.to_json())259    return df260 261 262def get_features(spotify):263    features = []264    for index in range(0, 10):265        results = spotify.current_user_saved_tracks(offset=index*50, limit=50)266        track_ids = [item['track']['id'] for item in results['items']]267        features.extend(spotify.audio_features(track_ids))268 269    df = pd.DataFrame(data=features)270    names = [271        'danceability', 272        'energy',273        'loudness',274        'speechiness',275        'acousticness',276        'instrumentalness',277        'liveness',278        'valence',279        'tempo',280    ]281    features_means = df[names].mean()282    # print (features_means.to_json())283    return features_means284 285 286##########287def get_started():288    # redirects to spotify and comes back289    # then generates plots290    return291 292with gr.Blocks() as demo:293    gr.Markdown(" ## Spotify Analyzer 🥳🎉")294    gr.Markdown("This app analyzes how cool your music taste is. We dare you to take this challenge!")295    with gr.Row():296        get_started_btn = gr.Button("Get Started")297    with gr.Row():298        spider_plot = gr.Plot()299    # with gr.Row():300    #     with gr.Column():301    #         with gr.Row():302    #             with gr.Column():303    #                 energy_plot = gr.ScatterPlot(show_label=False).style(container=True)304    #             with gr.Column():305    #                 liveness_plot = gr.ScatterPlot(show_label=False).style(container=True)306    with gr.Row():307        gr.Markdown(" ### We have recommendations for you!")308    with gr.Row():309        heatmap_plot = gr.Plot()310    with gr.Row():311        gr.Markdown(" ### We have recommendations for you!")312    with gr.Row():313        gr.Dataframe(314            headers=["Song", "Album", "Artist"],315            datatype=["str", "str", "str"],316            label="Reccomended Songs",317            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.318        )319    320    demo.load(fn=get_spider_plot, outputs = spider_plot)321    demo.load(fn=heatmap_plot_fn, outputs = heatmap_plot)322    # demo.load(fn=scatter_plot_fn_energy, outputs = energy_plot)323    # demo.load(fn=scatter_plot_fn_liveness, outputs = liveness_plot)324 325 326gradio_app = gr.mount_gradio_app(app, demo, "/gradio")327uvicorn.run(app, host="0.0.0.0", port=7860)328