diff --git a/.github/workflows/check_tags.yml b/.github/workflows/check_tags.yml index d519d74..d4c87e0 100644 --- a/.github/workflows/check_tags.yml +++ b/.github/workflows/check_tags.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.10"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index bbfe56e..eb0b4bb 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -11,7 +11,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.8', '3.9'] + python-version: ['3.9', '3.10'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 82643ef..7b6cebd 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.9", "3.10"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} diff --git a/BUILD b/BUILD index c85f015..98c70f3 100644 --- a/BUILD +++ b/BUILD @@ -1 +1 @@ -4bbb195 +72de749 diff --git a/VERSION b/VERSION index 197c4d5..437459c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4.0 +2.5.0 diff --git a/src/manage.py b/src/manage.py index 9a237f8..6a57c48 100755 --- a/src/manage.py +++ b/src/manage.py @@ -1,5 +1,6 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" + import os import sys diff --git a/src/tags.json b/src/tags.json index 71c1cc6..54277b5 100644 --- a/src/tags.json +++ b/src/tags.json @@ -13,5 +13,6 @@ "hra": "Human Reference Atlas data", "sc": "Single cell analysis", "R": "Template written in R", - "zarr": "Using zarr file format" + "zarr": "Using zarr file format", + "cde": "Cell Distance Explorer" } \ No newline at end of file diff --git a/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/README.md b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/metadata.json b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/metadata.json new file mode 100644 index 0000000..4747f21 --- /dev/null +++ b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/metadata.json @@ -0,0 +1,13 @@ +{ + "title": "Human Reference Atlas (HRA) Cell Distance Explorer (CDE) Tutorial", + "description": "This notebook shows users how to get a sample dataset for the CDE and visualize it with the node-dist-vis and CDE Jupyter widget.", + "tags": [ + "hra", + "api", + "cde" + ], + "is_multi_dataset_template": true, + "template_format": "jinja", + "is_hidden": false, + "last_modified_unix_timestamp": 1770060963 +} diff --git a/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/render.py b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/render.py new file mode 100644 index 0000000..7fec3bd --- /dev/null +++ b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/render.py @@ -0,0 +1,6 @@ +from user_templates_api.templates.jupyter_lab.render import JupyterLabRender + + +class JupyterLabExampleJinjaRender(JupyterLabRender): + def __init__(self): + pass diff --git a/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/template.ipynb b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/template.ipynb new file mode 100644 index 0000000..c29fc58 --- /dev/null +++ b/src/user_templates_api/templates/jupyter_lab/templates/hra_cde_tutorial/template.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "879b7334", + "metadata": {}, + "source": [ + "# A notebook to demonstrate usage of the Jupyter Widget for the Cell Distance Explorer" + ] + }, + { + "cell_type": "markdown", + "id": "8b4cdba9", + "metadata": {}, + "source": "In this notebook, we download a sample dataset with 3D cell positions from the [Cell Distance Explorer (CDE)](https://apps.humanatlas.io/cde/) and then visualize it with the `node-dist-vis` and `CdeVisualization` Jupyter widgets." + }, + { + "cell_type": "markdown", + "id": "a124cb13", + "metadata": {}, + "source": [ + "# Install and import libraries" + ] + }, + { + "cell_type": "code", + "id": "d88ba163", + "metadata": {}, + "source": [ + "# Import native packages\n", + "import os\n", + "from pprint import pprint" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "code", + "id": "8919f99f", + "metadata": {}, + "source": [ + "#Install and import external packages\n", + "%pip install requests pandas ipywidgets hra_jupyter_widgets\n", + "\n", + "import requests\n", + "import pandas as pd\n", + "import ipywidgets as widgets\n", + "\n", + "# Import hra-jupyter-widgets. For documentation, please see https://github.com/x-atlas-consortia/hra-jupyter-widgets/blob/main/usage.ipynb\n", + "from hra_jupyter_widgets import (\n", + " # BodyUi,\n", + " CdeVisualization, # in this example, we will use this one...\n", + " # Eui,\n", + " # EuiOrganInformation,\n", + " # FtuExplorer,\n", + " # FtuExplorerSmall,\n", + " # MedicalIllustration,\n", + " # ModelViewer,\n", + " NodeDistVis, # ...and this one, but all of them are usable for different purposes!\n", + " # Rui,\n", + ")" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "id": "e3e9d5ff", + "metadata": {}, + "source": [ + "# Global variables" + ] + }, + { + "cell_type": "code", + "id": "572c2376", + "metadata": {}, + "source": [ + "output_file = \"sample_data.csv\"\n", + "output_folder = \"data\"\n", + "path = os.path.join(output_folder, output_file)" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "id": "ede91205", + "metadata": {}, + "source": [ + "# Download data" + ] + }, + { + "cell_type": "code", + "id": "19495224", + "metadata": {}, + "source": [ + "def download_public_sheet_as_csv(file_id, gid, path):\n", + " \n", + " # ensure output folder exists\n", + " os.makedirs(os.path.dirname(path), exist_ok=True)\n", + " \n", + " url = (\n", + " f\"https://docs.google.com/spreadsheets/d/{file_id}/export?format=csv&gid={gid}\"\n", + " )\n", + " response = requests.get(url)\n", + " if response.status_code == 200:\n", + " with open(path, \"wb\") as f:\n", + " f.write(response.content)\n", + " print(f\"Success: saved to {path}\")\n", + " else:\n", + " print(f\"Error {response.status_code}: could not download sheet\")\n", + "\n", + "\n", + "# Your sheet’s IDs\n", + "file_id = \"1EUf7CUZb0NprgxBeX3nS3GXyUM89edIRH6NSeUsR3nY\"\n", + "gid = \"47698780\"\n", + "\n", + "download_public_sheet_as_csv(file_id, gid,path)" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "id": "fc56fffb", + "metadata": {}, + "source": [ + "## Read data as DataFrame" + ] + }, + { + "cell_type": "code", + "id": "ab2354e9", + "metadata": {}, + "source": [ + "# Read the CSV file and convert it to a df\n", + "df = pd.read_csv(path)\n", + "df" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "markdown", + "id": "0ab66bee", + "metadata": {}, + "source": "## Visualize with CDE" + }, + { + "cell_type": "code", + "id": "e92f490f", + "metadata": {}, + "source": [ + "# Next, let's define a function that turns a DataFrame into a node list that can then be passed into the CdeVisualization or NodeDistVis widget\n", + "def make_node_list(df: pd.DataFrame, is_3d: bool = False):\n", + " \"\"\"Turn a DataFrame into a list of dicts for passing them into a HRA widget\n", + "\n", + " Args:\n", + " df (pd.DataFrame): A DataFrame with cells\n", + " \"\"\"\n", + "\n", + " # If the df does not have a z-axis column, let's add one and set all cells to 0\n", + " if not is_3d:\n", + " df.loc[:, (\"z\")] = 0\n", + " \n", + " node_list = [\n", + " {\"x\": row[\"x\"], \"y\": row[\"y\"], \"z\": row[\"z\"], \"Cell Type\": row[\"Cell Type\"]}\n", + " for index, row in df.iterrows()\n", + " ]\n", + "\n", + " return node_list" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "code", + "id": "9d51eff4", + "metadata": {}, + "source": [ + "# Prepare df_cells for visualization with NodeDistVis widget\n", + "node_list = make_node_list(df, True)\n", + "\n", + "# Let's inspect the first 5 rows\n", + "pprint(node_list[:5])" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "code", + "id": "7614f172", + "metadata": {}, + "source": [ + "# Let's instantiate the NodeDistVis class with some parameters. We pass in the node_list, indicate Endothelial cells as targets for the edges.\n", + "# As we are not supplying an edge list, we need to provide a max_edge_distance, which is set to 1000 (generously)\n", + "node_dist_vis = NodeDistVis(\n", + " nodes=node_list,\n", + " node_target_key=\"Cell Type\",\n", + " node_target_value=\"Endothelial\",\n", + " max_edge_distance=1000,\n", + ")\n", + "\n", + "# Display our new widget\n", + "display(node_dist_vis)" + ], + "outputs": [], + "execution_count": null + }, + { + "cell_type": "code", + "id": "9e9d46d5", + "metadata": {}, + "source": [ + "# Finally, let's instantiate the CDEVisualization class with our node_list as parameter.\n", + "cde = CdeVisualization(nodes=node_list)\n", + "\n", + "# Display our new widget\n", + "display(cde)" + ], + "outputs": [], + "execution_count": null + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.12.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}