{ "cells": [ { "cell_type": "markdown", "id": "acf1fcbb", "metadata": {}, "source": [ "# Embed the multicolorfits web GUI in a notebook\n", "\n", "This tutorial shows how to run the full browser GUI **inside** Jupyter,\n", "Google Colab, VS Code notebooks, or Binder — useful for workshops and demos.\n", "\n", "**Requirements:** `pip install multicolorfits[web]` (FastAPI + uvicorn).\n", "\n", "See also: `mcf.gui()` for a blocking desktop-style launch that opens a\n", "separate browser tab." ] }, { "cell_type": "code", "execution_count": null, "id": "582e7dba", "metadata": {}, "outputs": [], "source": [ "import multicolorfits as mcf" ] }, { "cell_type": "markdown", "id": "e0ae94db", "metadata": {}, "source": [ "## Quick embed (auto-detect environment)\n", "\n", "`gui_embed()` starts the server in a background thread and shows an inline\n", "iframe (Jupyter / VS Code), Colab's port proxy, or prints the URL when run\n", "as a plain script." ] }, { "cell_type": "code", "execution_count": null, "id": "6526a384", "metadata": {}, "outputs": [], "source": [ "# Uncomment when FITS paths are available on this machine:\n", "# s = mcf.McfSession()\n", "# s.load_files(\n", "# ['halpha.fits', 'oiii.fits'],\n", "# colors=['#C11B17', '#4CC417'],\n", "# labels=['Hα', '[OIII]'],\n", "# )\n", "# mcf.gui_embed(session=s, height=950)" ] }, { "cell_type": "markdown", "id": "2c33f86e", "metadata": {}, "source": [ "## Google Colab\n", "\n", "Upload FITS files to the VM (or mount Drive), then force Colab display mode:\n", "\n", "```python\n", "from google.colab import files\n", "uploaded = files.upload() # pick local FITS files\n", "paths = list(uploaded.keys())\n", "mcf.gui_embed(files=paths, display='colab', height=900, print_url=True)\n", "```\n", "\n", "**Note:** Colab paths live only in the notebook VM — preload with `files=`\n", "rather than paths from your laptop." ] }, { "cell_type": "markdown", "id": "5b11d1fb", "metadata": {}, "source": [ "## Local Jupyter / VS Code notebooks\n", "\n", "```python\n", "mcf.gui_embed(session=s, display='iframe', height=900)\n", "```\n", "\n", "The iframe loads `http://127.0.0.1:` on the same machine as the kernel." ] }, { "cell_type": "markdown", "id": "0111e2a2", "metadata": {}, "source": [ "## URL only / scripting\n", "\n", "```python\n", "url = mcf.gui_embed(display='none', return_url=True)\n", "# or\n", "srv = mcf.start_gui_server(session=s)\n", "print(srv.url)\n", "```\n", "\n", "Use `display='none'` when you want a handle to `GuiServer` without rendering,\n", "or `return_url=True` for automation and tests." ] }, { "cell_type": "markdown", "id": "300170d8", "metadata": {}, "source": [ "## Binder / JupyterHub\n", "\n", "When `JUPYTERHUB_SERVICE_PREFIX` is set, `gui_embed()` automatically uses the\n", "hub's `/proxy/{port}/` URL in the iframe. Override with `proxy_url=` if your\n", "deployment uses a custom layout." ] }, { "cell_type": "markdown", "id": "a1230be4", "metadata": {}, "source": [ "## Caveats\n", "\n", "| Topic | Guidance |\n", "|-------|----------|\n", "| **Blocking `mcf.gui()`** | Opens a tab and blocks the cell — use `gui_embed()` instead. |\n", "| **Port clashes** | The launcher picks the next free port if 8321 is busy. |\n", "| **Large FITS** | Upload/mount data in cloud notebooks; preload with `files=`. |\n", "| **Two views** | Don't pass `open_browser=True` when embedding — you'll get a popup *and* an iframe. |\n", "| **Qt GUI** | `gui_qt()` needs a display server; prefer the web GUI in notebooks. |\n", "| **Stopping** | The server is a daemon thread; it stops when the kernel exits. `srv.stop()` is best-effort. |" ] }, { "cell_type": "code", "execution_count": null, "id": "f532b949", "metadata": {}, "outputs": [], "source": [ "# Detect environment (None outside IPython):\n", "# mcf.detect_notebook_environment()" ] } ], "metadata": { "jupytext": { "formats": "ipynb,py:percent", "kernelspec": { "display_name": "Python 3", "name": "python3" }, "main_language": "python" } }, "nbformat": 4, "nbformat_minor": 5 }