{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Libraries Needed","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import plotly.express as px\nimport plotly\n\nfrom wordcloud import WordCloud\nimport datetime as dt\nfrom sklearn import preprocessing\nimport librosa as lb\nimport librosa.display as lbd\nimport librosa.feature as lbf\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\nimport plotly.offline\nsns.set(style='darkgrid')\nplt.rcParams['figure.figsize'] = (16,8)\nimport IPython.display as ipd\nimport ipywidgets as ipw\nfrom bs4 import BeautifulSoup\nimport requests\nimport warnings\nwarnings.filterwarnings('ignore')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"link = 'https://ebird.org/species/'\naudios = '../input/birdsong-recognition/train_audio/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/birdsong-recognition/train.csv\")\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"print(len(set(train[\"species\"])))\nprint(len(set(train[\"ebird_code\"])))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"train.describe()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"train.info()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Some Feature Engineering","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"train['year'] = train['date'].apply(lambda x: x.split('-')[0])\ntrain['month'] = train['date'].apply(lambda x: x.split('-')[1])\ntrain['day_of_month'] = train['date'].apply(lambda x: x.split('-')[2])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Exploratory Data Analysis","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true,"collapsed":true},"cell_type":"code","source":"col = sorted(list(train['ebird_code'].unique()))\n\nfor temp in range(2,8):\n    ## SCRAPING FOR BIRD DESCRIPTION and IMAGE URL\n    URL = str(link+col[temp])\n    page = requests.get(URL)\n    soup = BeautifulSoup(page.content, 'html.parser')\n    result = soup.find_all('p', class_='u-stack-sm')\n    res = soup.find_all('figure', class_='MediaFeed-item'); \n    img = res[0].find_all('img')[0].get('src')\n    description = result[0].text\n\n    ## PUTTING EVERYTHING IN A VARIABLE\n    ad = os.listdir(str(audios+col[temp]))[10]\n    df = train[train['filename']==ad].reset_index()\n    spec = str(df['species'][0]+' ('+df['sci_name'][0] + ')')\n    loc = df['location'][0]\n    time = str(df['date'][0]+' (yyyy-mm-dd) '+df['time'][0]+' hrs')\n    recordist = df['recordist'][0]\n    elev = df['elevation'][0]\n\n    ## DISPLAYING IN THE NOTEBOOK\n    ipd.display(ipd.HTML('<head> <body> <h1 style = \"font-size:46px; font-family:sans; background-color:Lavender;\"> {} </h1>\\\n                            <p style=\"text-align:left; color:black; font-family:verdana; font-size:19px;\"> <br> <img src= {} \\\n                            style=\"float:right;width:50%;height:50%;\"> <br> &emsp; {}<br><br><b> Located at:</b>{}<br><b>Date & Time \\\n                            of recording:</b> {}<br><b>Elevation: </b>{}<br><b>Recordist: </b>{}</br></p>\\\n                            <h3 style = \"font-family:verdana; font-size:26px\">Audio:</h3> </body></head>'.format(spec,img,description,loc,time,elev,recordist)))\n    ipd.display(ipd.Audio(str(audios+col[temp]+'/'+ad), embed=True))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"temp = pd.DataFrame({'Number of Missing Values': pd.Series(train.isnull().sum().sort_values(ascending=False))[:5]})\ntemp['Feature'] = temp.index\ntemp = temp.reset_index(drop=True)\nfig = px.bar(data_frame=temp,x=\"Feature\",y=\"Number of Missing Values\",color=\"Feature\",orientation='v',title='Missing Values in the Train Data',hover_data=[\"Feature\"])\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There are some features with Null Values namely Playback_used,bird_Seen,description and backgroud have more Null Values in them ","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"year = train[\"year\"].value_counts()\nyear_df = pd.DataFrame({\"year\":year.index,\"frequency\":year.values})\nyear_df = year_df.sort_values(by=\"year\",ascending=False)\nfig = px.bar(data_frame=year_df[:30],x=\"year\",y=\"frequency\",color=\"year\",title=\"On which Year Most Recordings Happen?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"month = train[\"month\"].value_counts()\nmonth_df = pd.DataFrame({\"month\":month.index,\"frequency\":month.values})\nmonth_df = month_df.sort_values(by=\"month\",ascending=False)\nfig = px.bar(data_frame=month_df[:30],x=\"month\",y=\"frequency\",color=\"month\",title=\"On which Month Most Recordings Happen?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"species = train[\"species\"].value_counts()\nspecies_df = pd.DataFrame({\"species\":species.index,\"count\":species.values})\nfig = px.bar(data_frame=species_df,x=\"species\",y=\"count\",color=\"species\",orientation='v',title='Count of Data Available for different bird species',hover_data=[\"species\"])\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"pitch = train[\"pitch\"].value_counts()\npitch_df = pd.DataFrame({\"pitch\":pitch.index,\"frequency\":pitch.values})\npitch_df = pitch_df.sort_values(by=\"pitch\",ascending=False)\nfig = px.bar(data_frame=pitch_df,x=\"pitch\",y=\"frequency\",color=\"pitch\",title=\"On which Pitch Most Bird sings?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"seen = train[\"bird_seen\"].value_counts()\nseen_df = pd.DataFrame({\"seen\":seen.index,\"frequency\":seen.values})\nseen_df = seen_df.sort_values(by=\"seen\",ascending=False)\nfig = px.bar(data_frame=seen_df[:30],x=\"seen\",y=\"frequency\",color=\"seen\",title=\"Did the Author saw the bird?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"group_seen = train.groupby([\"bird_seen\",\"species\"]).size().reset_index()\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"group_seen_no = group_seen[group_seen[\"bird_seen\"]==\"no\"]\ngroup_seen_yes = group_seen[group_seen[\"bird_seen\"]==\"yes\"]","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def generate_word_cloud(text):\n    wordcloud = WordCloud(\n        width = 500,\n        height = 1000,\n        background_color = 'black').generate((\" \").join(text))\n    fig = plt.figure(\n        figsize = (40, 30),\n        facecolor = 'k',\n        edgecolor = 'k')\n    plt.imshow(wordcloud, interpolation = 'bilinear')\n    plt.axis('off')\n    plt.tight_layout(pad=0)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Species which were not seen","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"generate_word_cloud(list(group_seen_no.species.values))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Species which are seen","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"generate_word_cloud(list(group_seen_yes.species.values))","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"adjusted_type = train['type'].apply(lambda x: x.split(',')).reset_index().explode(\"type\")\n\n# Strip of white spaces and convert to lower chars\nadjusted_type = adjusted_type['type'].apply(lambda x: x.strip().lower()).reset_index()\nadjusted_type['type'] = adjusted_type['type'].replace('calls', 'call')\ntop_15 = list(adjusted_type['type'].value_counts().reset_index()['index'])\ndata = adjusted_type[adjusted_type['type'].isin(top_15)]\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"bird_call = data[\"type\"].value_counts()\nbird_call_df = pd.DataFrame({\n    \"type\":bird_call.index,\n    \"frequency\":bird_call.values\n})\nfig = px.bar(data_frame=bird_call_df[:15],x=\"type\",y=\"frequency\",color=\"type\",hover_name=\"type\",title=\"Which type of bird call did bird uses ?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"elevation = train[\"elevation\"].value_counts()\nelevation_df = pd.DataFrame({\"elevation\":elevation.index,\"frequency\":elevation.values})\nfig = px.bar(data_frame=elevation_df[:50],x=\"elevation\",y=\"frequency\",color=\"elevation\",title=\"At Which Elevation did the bird found?\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"collapsed":true},"cell_type":"code","source":"fig = go.Figure(data=go.Scattergeo(lon=train['longitude'], lat = train['latitude'], mode='markers', text = train['location'], marker=dict(size=4,\n                                                                                                               opacity=0.6,\n                                                                                                               symbol='square',\n                                                                                                               line=dict(width=1,\n                                                                                                                        color='white'),\n                                                                                                               colorscale='Blues',\n                                                                                                               color='blue')))\nfig.update_layout(geo_scope='world', title = 'Recordings from world'); \n\nplotly.offline.iplot(fig)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"fig = go.Figure(data=go.Scattergeo(lon=train['longitude'], lat = train['latitude'], mode='markers', text = train['location'], marker=dict(size=4,\n                                                                                                               opacity=0.6,\n                                                                                                               symbol='square',\n                                                                                                               line=dict(width=1,\n                                                                                                                        color='white'),\n                                                                                                               colorscale='Blues',\n                                                                                                               color='blue')))\nfig.update_layout(geo_scope='usa', title = 'Recordings from USA')\n\nplotly.offline.iplot(fig)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"fig = go.Figure(data=go.Scattergeo(lon=train['longitude'], lat = train['latitude'], mode='markers', text = train['location'], marker=dict(size=4,\n                                                                                                               opacity=0.6,\n                                                                                                               symbol='square',\n                                                                                                               line=dict(width=1,\n                                                                                                                        color='white'),\n                                                                                                               colorscale='Blues',\n                                                                                                               color='blue')))\nfig.update_layout(geo_scope='europe', title = 'Recordings from EUROPE')\n\nplotly.offline.iplot(fig)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"values_df= train.groupby([\"species\",\"author\"]).size().reset_index()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"values_df = values_df.rename(columns={0: \"Count\"})\nvalues_df = values_df.sort_values(by=\"Count\",ascending=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"fig = px.bar(data_frame=values_df[:500],x=\"author\",hover_name=\"species\",y=\"Count\",color=\"author\")\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Let's Dive in Audio Files","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create Full Path so we can access data more easily\nbase_dir = '../input/birdsong-recognition/train_audio/'\ntrain['full_path'] = base_dir + train['ebird_code'] + '/' + train['filename']\n\n# Now let's sample a fiew audio files\namered = train[train['ebird_code'] == \"amered\"].sample(1, random_state = 33)['full_path'].values[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ipd.Audio(amered)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Importing 1 file\ny, sr = lb.load(amered)\n\nprint('y:', y, '\\n')\nprint('y shape:', np.shape(y), '\\n')\nprint('Sample Rate (KHz):', sr, '\\n')\n\n# Verify length of the audio\nprint('Check Len of Audio:', 661794/sr)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"audio_amered,sr_new = lb.effects.trim(y)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"lb.display.waveplot(y = audio_amered, sr = sr, color = \"#A300F9\")\nplt.title(\"Sound Waves as 2D\")\nplt.ylabel(\"amered\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"An Audio File consist of two components\n* Sound sequence of vibrations in varying pressure strengths (y)\n* Sampling Rate (sr) is the number of samples of audio carried per second, measured in Hz or kHz","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"\n# 2. Fourier Transform 🥁\n\nFunction that gets a signal in the time domain as input, and outputs its decomposition into frequencies. Transform both the y-axis (frequency) to log scale, and the “color” axis (amplitude) to Decibels, which is approx. the log scale of amplitudes.\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\n# Default FFT window size\nn_fft = 2048 # FFT window size\nhop_length = 512 # number audio of frames between STFT columns (looks like a good default)\n\n# Short-time Fourier transform (STFT)\nD_amered = np.abs(lb.stft(audio_amered, n_fft = n_fft, hop_length = hop_length))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Shape of D object:', np.shape(D_amered))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# 3. Spectrogram 🎷\n\nWhat is a spectrogram? A spectrogram is a visual representation of the spectrum of frequencies of a signal as it varies with time. When applied to an audio signal, spectrograms are sometimes called sonographs, voiceprints, or voicegrams (wiki).\n\nHere we convert the frequency axis to a logarithmic one.\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"DB_amered = lb.amplitude_to_db(D_amered, ref = np.max)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"lb.display.specshow(DB_amered, sr = sr, hop_length = hop_length, x_axis = 'time', \n                         y_axis = 'log', cmap = 'cool')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# 4. Mel Spectrogram 🎷\n\nThe Mel Scale, mathematically speaking, is the result of some non-linear transformation of the frequency scale. The Mel Spectrogram is a normal Spectrogram, but with a Mel Scale on the y axis.\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"# Create the Mel Spectrograms\nS_amered = lb.feature.melspectrogram(y, sr=sr)\nS_DB_amered = lb.amplitude_to_db(S_amered, ref=np.max)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"lb.display.specshow(S_DB_amered, sr = sr, hop_length = hop_length, x_axis = 'time', \n                         y_axis = 'log', cmap = 'rainbow')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# 5. Zero Crossing Rate 🚷\n\n the rate at which the signal changes from positive to negative or back.\n\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"zero_amered = lb.zero_crossings(audio_amered, pad=False)\nprint(\"{}change rate is {}\".format(\"armed\",sum(zero_amered)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# 6. Harmonics and Perceptrual 🎹\n\n    Harmonics are characteristichs that represent the sound color\n    Perceptrual shock wave represents the sound rhythm and emotion\n\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"\n\ny_harm_haiwoo, y_perc_haiwoo = lb.effects.hpss(audio_amered)\n\nplt.figure(figsize = (16, 6))\nplt.plot(y_perc_haiwoo, color = '#FFB100')\nplt.plot(y_harm_haiwoo, color = '#A300F9')\nplt.legend((\"Perceptrual\", \"Harmonics\"))\nplt.title(\"Harmonics and Perceptrual : Haiwoo Bird\", fontsize=16);\n\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# Calculate the Spectral Centroids\nspectral_centroids = lb.feature.spectral_centroid(audio_amered, sr=sr)[0]\n\n# Shape is a vector\nprint('Centroids:', spectral_centroids, '\\n')\nprint('Shape of Spectral Centroids:', spectral_centroids.shape, '\\n')\n\n# Computing the time variable for visualization\nframes = range(len(spectral_centroids))\n\n# Converts frame counts to time (seconds)\nt = lb.frames_to_time(frames)\n\nprint('frames:', frames, '\\n')\nprint('t:', t)\n\n# Function that normalizes the Sound Data\ndef normalize(x, axis=0):\n    return preprocessing.minmax_scale(x, axis=axis)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"#Plotting the Spectral Centroid along the waveform\nplt.figure(figsize = (16, 6))\nlb.display.waveplot(audio_amered, sr=sr, alpha=0.4, color = '#A300F9', lw=3)\nplt.plot(t, normalize(spectral_centroids), color='#FFB100', lw=2)\nplt.legend([\"Spectral Centroid\", \"Wave\"])\nplt.title(\"Spectral Centroid: Cangoo Bird\", fontsize=16);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 8. Chroma Frequencies\n\nChroma features are an interesting and powerful representation for music audio in which the entire spectrum is projected onto 12 bins representing the 12 distinct semitones (or chromas) of the musical octave.\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"# Increase or decrease hop_length to change how granular you want your data to be\nhop_length = 5000\n\n# Chromogram Vesspa\nchromagram = lb.feature.chroma_stft(audio_amered, sr=sr, hop_length=hop_length)\nprint('Chromogram Vesspa shape:', chromagram.shape)\n\nplt.figure(figsize=(16, 6))\nlb.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='twilight')\n\nplt.title(\"Chromogram Vesspa\", fontsize=16);\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 9. Spectral Rolloff 🥏\n\nIs a measure of the shape of the signal. It represents the frequency below which a specified percentage of the total spectral energy (e.g. 85%) lies.\n","execution_count":null},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"# Spectral RollOff Vector\nspectral_rolloff = lb.feature.spectral_rolloff(audio_amered, sr=sr)[0]\n\n# Computing the time variable for visualization\nframes = range(len(spectral_rolloff))\n# Converts frame counts to time (seconds)\nt = lb.frames_to_time(frames)\n\n# The plot\nplt.figure(figsize = (16, 6))\nlb.display.waveplot(audio_amered, sr=sr, alpha=0.4, color = '#A300F9', lw=3)\nplt.plot(t, normalize(spectral_rolloff), color='#FFB100', lw=3)\nplt.legend([\"Spectral Rolloff\", \"Wave\"])\nplt.title(\"Spectral Rolloff: Amered Bird\", fontsize=16)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"References :\n> https://pypi.org/project/librosa/\n\n>https://www.kaggle.com/navinmundhra/birdcall-starter-extensive-eda-fe\n\n>https://www.kaggle.com/andradaolteanu/birdcall-recognition-eda-and-audio-fe","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}