{ "cells": [ { "cell_type": "markdown", "id": "2a21efb9", "metadata": { "execution": {} }, "source": [ "\"Open   \"Open" ] }, { "cell_type": "markdown", "id": "e79e6195", "metadata": { "execution": {} }, "source": [ "# Tutorial 3: Content Enhancements\n", "\n", "**Week 1, Day 1: Instructions**\n", "\n", "**By Neuromatch**\n", "\n", "__Content creators:__ Viviana Greco\n", "\n", "__Content reviewers:__ Konstantine Tsafatinos\n", "\n", "__Production editors:__ Konstantine Tsafatinos\n", "\n", "
\n", "\n", "Acknowledgments: [Ella Batty, Spiros Chavlis and neuromatch]" ] }, { "cell_type": "markdown", "id": "2e1685a5", "metadata": { "execution": {} }, "source": [ "___\n", "\n", "# Tutorial Objectives\n", "\n", "*Estimated timing of tutorial: [15 mins]*\n", "\n", "In this tutorial, we'll dive into enhancing your content by integrating various media and interactive elements.\n", "\n", "By the end of this tutorial, you will:\n", "\n", "- learn how to add Airtable links\n", "- learn how to embed videos \n", "- learn how to integrate Kaggle/Collab Buttons\n", "- learn how to upload data to OSF and access it from Jupyter Books" ] }, { "cell_type": "markdown", "id": "6e6328a8", "metadata": { "execution": {} }, "source": [ "---\n", "\n", "# Section 1: How to add Airtable links\n", " " ] }, { "cell_type": "markdown", "id": "29492952", "metadata": { "execution": {} }, "source": [ "Airtable links should be added at the end of the OUTRO page of each tutorial." ] }, { "cell_type": "markdown", "id": "599e8aa1", "metadata": { "execution": {} }, "source": [ "Steps:" ] }, { "cell_type": "markdown", "id": "d99d752c", "metadata": { "execution": {} }, "source": [ "1. Request the Airtable Link\n", "2. Add Image button\n", "3. Embed and test the button" ] }, { "cell_type": "markdown", "id": "60cc05b6", "metadata": { "execution": {} }, "source": [ "**Request the Airtable Link**\n", "\n", "\n", "Reach Out to Neuromatch Staff: Request the specific Airtable link for the day. You will receive a link that resembles:\n", "https://portal.neuromatchacademy.org/api/redirect/to/48f385bc-3cd4-4516-96bb-46bdbdccbe9a" ] }, { "cell_type": "markdown", "id": "a1e320ad", "metadata": { "execution": {} }, "source": [ "**Add the Image Button**\n", "\n", "The button image is stored in the \"static\" folder within \"tutorials\" and is named \"button.png\". You can access it on GitHub using this URL:\n", "\n", "https://github.com/neuromatch/course-content-template/blob/main/tutorials/static/button.png?raw=1\n", "\n", "**Note:** Please refrain from altering this image." ] }, { "cell_type": "markdown", "id": "e3643ebf", "metadata": { "execution": {} }, "source": [ "**Embed the image button into your markdown cells**\n", "\n", "Insert the following HTML code to add the image button:\n", "\n", "```\n", "\n", " \"button\n", "\n", "```\n", "\n", "Replace YOUR_AIRTABLE_LINK_HERE with the link provided by Neuromatch staff.\n", "\n", "Ex:\n", "\n", "```\n", "\n", " \"button\n", "\n", "```\n", "\n", "After embedding the button click on it to ensure it redirects correctly to the Airtable survey." ] }, { "cell_type": "markdown", "id": "7c033e9a", "metadata": { "execution": {} }, "source": [ "---\n", "\n", "# Section 2: How to embed videos\n", " " ] }, { "cell_type": "markdown", "id": "c2b8ab03", "metadata": { "execution": {} }, "source": [ "When adding videos to your content, please follow the guidelines outlined below:" ] }, { "cell_type": "markdown", "id": "4e21b25d", "metadata": { "execution": {} }, "source": [ "1. Utilize the Provided Code: Use the code template provided below. A few important notes about the code:\n", "\n", "- **PlayVideo Class & display_videos Function:** Avoid making modifications to the PlayVideo class or the display_videos function. \n", "

\n", "2. Update the **video_ids** List: Your main focus should be on modifying the video_ids list. Here, you specify the video platform and the corresponding video ID:\n", "\n", "- **Youtube** Videos: Adopt the format ('Youtube', '\\'). The \\ can be found in the video's Youtube URL. For example, in the URL https://www.youtube.com/watch?v=KUdKlJxtjQw, the video ID is KUdKlJxtjQw.

\n", "\n", "\n", "- **Bilibili** Videos: Use the format ('Bilibili', '\\'). The \\ represents Bilibili's unique ID for that video.

\n", "\n", "- **OSF** Videos: The format is ('Osf', '\\').

\n", "\n", "3. Run the Code: After updating the video_ids list, execute the entire code block to display the videos within your notebook.

\n", "\n", "\n", "4. Instructions on how to upload video to these platform can be found [here](https://neuromatch.slite.com/app/channels/g2mc8TY_Sk-ush)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "5467f4b0", "metadata": { "cellView": "form", "execution": {}, "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# @markdown\n", "\n", "from ipywidgets import widgets\n", "from IPython.display import YouTubeVideo\n", "from IPython.display import IFrame\n", "from IPython.display import display\n", "\n", "\n", "class PlayVideo(IFrame):\n", " def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n", " self.id = id\n", " if source == 'Bilibili':\n", " src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n", " elif source == 'Osf':\n", " src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n", " super(PlayVideo, self).__init__(src, width, height, **kwargs)\n", "\n", "\n", "def display_videos(video_ids, W=400, H=300, fs=1):\n", " tab_contents = []\n", " for i, video_id in enumerate(video_ids):\n", " out = widgets.Output()\n", " with out:\n", " if video_ids[i][0] == 'Youtube':\n", " video = YouTubeVideo(id=video_ids[i][1], width=W,\n", " height=H, fs=fs, rel=0)\n", " print(f'Video available at https://youtube.com/watch?v={video.id}')\n", " else:\n", " video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n", " height=H, fs=fs, autoplay=False)\n", " if video_ids[i][0] == 'Bilibili':\n", " print(f'Video available at https://www.bilibili.com/video/{video.id}')\n", " elif video_ids[i][0] == 'Osf':\n", " print(f'Video available at https://osf.io/{video.id}')\n", " display(video)\n", " tab_contents.append(out)\n", " return tab_contents\n", "\n", "\n", "video_ids = [('Youtube', ''), ('Bilibili', ''), ('Osf', '')]\n", "tab_contents = display_videos(video_ids, W=730, H=410)\n", "tabs = widgets.Tab()\n", "tabs.children = tab_contents\n", "for i in range(len(tab_contents)):\n", " tabs.set_title(i, video_ids[i][0])\n", "display(tabs)" ] }, { "cell_type": "markdown", "id": "fb863895", "metadata": { "execution": {} }, "source": [ "## Section 2.1: Tag at the top of the video code cell \n", "\n", "In the W#D#_Intro.ipynb and W#D#_Outro.ipynb, use **# @markdown** at the top of the video code cell. \n", "\n", "In the W#D#_Tutorial# use **# @title Video \\: Title of the video**" ] }, { "cell_type": "markdown", "id": "5f427f95", "metadata": { "execution": {} }, "source": [ "## Section 2.2: Add video links in the material.yml file\n", "\n", "When you add or modify videos in the Jupyter Notebook, it's also essential to keep the materials.yml file up-to-date. Here's how to do it: Remember that the main structure for this File has been already explaineed in W1D1_Tutorial2, Section 4. \n", "\n", "```\n", "- day: W1D1\n", " category: Course Content Template Instructions \n", " \n", " # Replace with the Youtube video link from W#D#_Intro.ipynb. Example:\n", " intro: https://www.youtube.com/watch?v=KxldhMR5PxA \n", " \n", " # Replace with the Bilibili video link from W#D#_Intro.ipynb. Example:\n", " intro_bilibili: https://www.bilibili.com/video/BV1HT4y1E7U4/\n", " \n", " name: Instructions \n", " \n", " # Replace with the Youtube video link from W#D#_Outro.ipynb. Example:\n", " outro: https://www.youtube.com/watch?v=KZQXfQL1SH4\n", " \n", " # Replace with the Bilibili video link from W#D#_Outro.ipynb. Example:\n", " outro_bilibili: https://www.bilibili.com/video/BV1vv411i7SG/\n", " \n", " # Replace with the Youtube playlist link. Example:\n", " playlist: https://www.youtube.com/playlist?list=PLkBQOLLbi18ObAiSOZ42YBwOQIKNvspeI\n", "``` " ] }, { "cell_type": "code", "execution_count": null, "id": "e0b259bd", "metadata": { "execution": {} }, "outputs": [], "source": [ "## Section 2.3: Video embedding example\n", "\n", "# @markdown\n", "from ipywidgets import widgets\n", "from IPython.display import YouTubeVideo\n", "from IPython.display import IFrame\n", "from IPython.display import display\n", "\n", "\n", "class PlayVideo(IFrame):\n", " def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n", " self.id = id\n", " if source == 'Bilibili':\n", " src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n", " elif source == 'Osf':\n", " src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n", " super(PlayVideo, self).__init__(src, width, height, **kwargs)\n", "\n", "\n", "def display_videos(video_ids, W=400, H=300, fs=1):\n", " tab_contents = []\n", " for i, video_id in enumerate(video_ids):\n", " out = widgets.Output()\n", " with out:\n", " if video_ids[i][0] == 'Youtube':\n", " video = YouTubeVideo(id=video_ids[i][1], width=W,\n", " height=H, fs=fs, rel=0)\n", " print(f'Video available at https://youtube.com/watch?v={video.id}')\n", " else:\n", " video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n", " height=H, fs=fs, autoplay=False)\n", " if video_ids[i][0] == 'Bilibili':\n", " print(f'Video available at https://www.bilibili.com/video/{video.id}')\n", " elif video_ids[i][0] == 'Osf':\n", " print(f'Video available at https://osf.io/{video.id}')\n", " display(video)\n", " tab_contents.append(out)\n", " return tab_contents\n", "\n", "\n", "video_ids = [('Youtube', 'W5o_HTsef0I'), ('Bilibili', 'BV1ho4y1C7Eo')]\n", "tab_contents = display_videos(video_ids, W=730, H=410)\n", "tabs = widgets.Tab()\n", "tabs.children = tab_contents\n", "for i in range(len(tab_contents)):\n", " tabs.set_title(i, video_ids[i][0])\n", "display(tabs)" ] }, { "cell_type": "markdown", "id": "65ad3198", "metadata": { "execution": {} }, "source": [ "---\n", "\n", "# Section 3: Add and test buttons for Kaggle/Colab" ] }, { "cell_type": "markdown", "id": "485fa49c", "metadata": { "execution": {} }, "source": [ "**COLAB** \n", "\n", "\n", "STEP 1: The URL structure for Google Colab links that point to GitHub repositories is:\n", "https://colab.research.google.com/github/[USERNAME]/[REPOSITORY]/blob/[BRANCH]/[PATH_TO_NOTEBOOK].ipynb\n", "\n", "Replace:\n", "- [USERNAME] with the GitHub organization name ⟶ ask Konstantine if in the future this will be Neuromatch or Neuromatch Academy.\n", "- [REPOSITORY] with the name of the GitHub repository.\n", "- [BRANCH] with the name of the branch - usually this will be `main`\n", "- [PATH_TO_NOTEBOOK].ipynb with the relative path to the notebook in the repository.\n", "\n", "\n", "STEP 2: Embed the Button in Jupyter Book\n", "Use the following HTML to add the Google Colab button:\n", "```\n", " \"Open\n", "```\n", "\n", "Replace YOUR_GENERATED_LINK_HERE with the link you generated in step 1.\n", "\n", "For example: \n", "```\"Open   \n", "```\n", "\n", "**KAGGLE**\n", "\n", "\n", "STEP 1: The URL structure to open notebooks in Kaggle from a GitHub repository is:\n", "https://kaggle.com/kernels/welcome?src=https://raw.githubusercontent.com/[USERNAME]/[REPOSITORY]/[BRANCH]/[PATH_TO_NOTEBOOK].ipynb\n", "\n", "Replace:\n", "- [USERNAME] with the GitHub organization name.\n", "- [REPOSITORY] with the name of the GitHub repository.\n", "- [BRANCH] with the name of the branch - - usually this will be `main`\n", "- [PATH_TO_NOTEBOOK].ipynb with the relative path to the notebook in your repository.\n", "\n", "\n", "STEP 2: Embed the Button in Jupyter Book\n", "\n", "Use the following HTML to add the Kaggle button:\n", "```\n", " \"Open\n", "```\n", "\n", "Replace YOUR_GENERATED_LINK_HERE with the link you generated in step 1.\n", "\n", "For example: \n", "```\n", "\"Open\n", "```" ] }, { "cell_type": "markdown", "id": "3d9cdb65", "metadata": { "execution": {} }, "source": [ "Test the Button for both Colab and Kaggle:\n", "\n", "- After embedding the button in your Jupyter book and publishing the changes:\n", "- Click on the \"Open In Colab\" button or \"Open In Kaggle\" button.\n", "\n", "This should open a new tab, and the notebook should be loaded into Google Colab / Kaggle directly from the GitHub repository." ] }, { "cell_type": "markdown", "id": "79f6b6aa", "metadata": { "execution": {} }, "source": [ "---\n", "\n", "# Section 4: Uploade data to OSF and access it from Jupyter " ] }, { "cell_type": "markdown", "id": "3e9dfd65", "metadata": { "execution": {} }, "source": [ "**Uploading Data to OSF:**\n", "\n", "1. Navigate to the OSF Neuromatch Academy page. If you already have an account, log in using your credentials. If not, create a new account.\n", "\n", "2. Upload Data: Choose or create the appropriate project/folder in which you want to upload the data. Click on Files, then Upload (+) to add your data files.\n", "\n", "3. Grab the Link ID: Once the data or file is uploaded, each file or folder will have a unique link ID. This ID can be found in the URL of the uploaded file. Example URL: https://osf.io/6dxwe/ - Here, 6dxwe is the unique link ID." ] }, { "cell_type": "markdown", "id": "40a9b5a1", "metadata": { "execution": {} }, "source": [ "When uploading materials to OSF, please maintain the following structure:\n", "\n", "**For New Courses:** Use the structure adopted by the \"Climatematch\" course as a template (e.g., Climatematch/2023/Projects)\n", "\n", "**For Existing Courses:** If you're adding materials to a course that already has content on OSF, follow the established structure. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "markdown", "id": "42416117", "metadata": { "execution": {}, "tags": [ "remove-input" ] }, "source": [ "# @markdown\n", "from IPython.display import IFrame\n", "from ipywidgets import widgets\n", "out = widgets.Output()\n", "with out:\n", " print(f\"If you want to download the slides: https://osf.io/download//\")\n", " display(IFrame(src=f\"https://mfr.ca-1.osf.io/render?url=https://osf.io//?direct%26mode=render%26action=download%26mode=render\", width=730, height=410))\n", "display(out)" ] }, { "cell_type": "markdown", "id": "37ce90ee", "metadata": { "execution": {} }, "source": [ "To check storage limits imposed by OSF please visit the (website) [https://help.osf.io/article/386-project-storage#:~:text=OSF%20will%20limit%20the%20capacity,for%20storage%20management%20wherever%20possible.] \n", "\n", "Here's what you need to know about storage Limits:\n", "\n", "- Private Projects: Limited to 5 GB using OSF Storage.\n", "- Public Projects: Can utilize up to 50 GB with OSF Storage." ] } ], "metadata": { "colab": { "collapsed_sections": [], "include_colab_link": true, "name": "W1D1_Tutorial3", "toc_visible": true }, "kernel": { "display_name": "Python 3", "language": "python", "name": "python3" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.18" } }, "nbformat": 4, "nbformat_minor": 5 }