{ "cells": [ { "cell_type": "markdown", "id": "4dbf39b1-1bfe-4656-8a1b-641b9e0618fe", "metadata": {}, "source": [ "# Yet Another JDesmos Demo\n", "\n", "In a [recent article](https://codesolid.com/math/desmos-jupyter/), we announced the availability of JDesmos, a small library for embedding [Desmos Graphs](https://www.desmos.com/calculator) in Jupyter. This article is only a modest reworking of a JDesmos sample we published to the [GitHub repository](https://github.com/codesolid/jdesmos) to serve as further documentation.\n", "\n", "## Usage: \n", "```pip install jdesmos```\n", "\n", "Shown below is a simple usage example.\n", "\n", "*Note: Apparently, GitHub disables JavaScript display output, so the graph will not display there. It **will** be available if you run install JDesmos and run this in a local Jupyter environment.*" ] }, { "cell_type": "code", "execution_count": 1, "id": "51ca1859-c1b4-462e-9932-5102d5c4c568", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.2\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" ] } ], "source": [ "# We can also install it within Jupyter\n", "!pip install jdesmos --quiet" ] }, { "cell_type": "code", "execution_count": 2, "id": "7db09f7a-59ba-4256-9fd4-2b43627fc2f7", "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "new Promise(function(resolve, reject) {\n", "\tvar script = document.createElement(\"script\");\n", "\tscript.onload = resolve;\n", "\tscript.onerror = reject;\n", "\tscript.src = \"https://www.desmos.com/api/v1.9/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6\";\n", "\tdocument.head.appendChild(script);\n", "}).then(() => {\n", "\n", " element.style.height = '480px';\n", " element.style.width = '100%';\n", " var calculator = Desmos.GraphingCalculator(element);\n", " calculator.setExpression({\"latex\": \"x^2 + 2\"});calculator.setExpression({\"latex\": \"y=2x + 1\"});calculator.setExpression({\"latex\": \"(1,3)\", \"label\": \"(1,3)\", \"showLabel\": true});\n", " \n", "});" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jdesmos import Desmos\n", "desmos = Desmos()\n", "desmos.add_latex('x^2 + 2')\n", "desmos.add_latex('y=2x + 1')\n", "desmos.add_expression({\"latex\": \"(1,3)\", \"label\": \"(1,3)\", \"showLabel\": True})\n", "desmos.display()" ] }, { "cell_type": "markdown", "id": "4ab60393-2621-414f-bd13-97fa5809ff40", "metadata": {}, "source": [ "## API\n", "\n", "JDesmos has a very lightweight API. \n", "\n", "* **\\_\\_init__**: By default, the constructor, ```JDesmos()``` creates a desmos object using the Desmos API \"demo\" api key (this can be overriden).\n", "* **add_latex**: This method adds a LaTeX expression to the Desmos graph. This string argument is the LaTeX equivalent of what would enter as a line in the Desmos online calculator.\n", "* **add_expression**: This method allows more flexibility than **add_latex**. The expression argument is a json string (or Python dict which will be translated into a json string). See the setExpression method of the [Desmos API documentation](https://www.desmos.com/api/v1.9/docs/index.html) for more information on the format of this object.\n", "* **display**: After calling ```add_expression``` or ```add_latex``` as needed to create populate the graph, call ```display``` to show the graph in the browser. Note that even though the graph was set up programatically, lines can be changed or added interactively in the resulting graph as you would in the Desmos graphing calculator. Note, however, that re-running the original code will delete any lines that were added interactively." ] }, { "cell_type": "markdown", "id": "4b4107e3-dcab-456c-95da-d3f4a46aa0ca", "metadata": {}, "source": [ "## Translating an ```add_expression``` example\n", "\n", "Here is an example from the desmos API documentation. Below this, we translate the example into the equivalent JDesmos calls.\n", "\n", "```JavaScript\n", "//Define a variable m. Doesn't graph anything.\n", "calculator.setExpression({ id: 'm', latex: 'm=2' });}|\n", "\n", "//Draw a red line with slope of m through the origin.\n", "//Because m = 2, this line will be of slope 2.\n", "calculator.setExpression({ id: 'line1', latex: 'y=mx', color: '#0000ff' });\n", "\n", "//Updating the value of m will change the slope of the line to 3\n", "grapher.setExpression({ id: 'm', latex: 'm=3' });\n", "\n", "//Inequality to shade a circle at the origin\n", "calculator.setExpression({ id: 'circle1', latex: 'x^2 + y^2 < 1' });\n", "\n", "//Restrict the slider for the m variable to the integers from 1 to 10\n", "calculator.setExpression({\n", " id: 'm',\n", " sliderBounds: { min: 1, max: 10, step: 1 }\n", "});\n", "```" ] }, { "cell_type": "code", "execution_count": 3, "id": "2c898aac-f9ba-48b9-b51f-0f5c615e6e5b", "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "new Promise(function(resolve, reject) {\n", "\tvar script = document.createElement(\"script\");\n", "\tscript.onload = resolve;\n", "\tscript.onerror = reject;\n", "\tscript.src = \"https://www.desmos.com/api/v1.9/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6\";\n", "\tdocument.head.appendChild(script);\n", "}).then(() => {\n", "\n", " element.style.height = '480px';\n", " element.style.width = '100%';\n", " var calculator = Desmos.GraphingCalculator(element);\n", " calculator.setExpression({ id: 'm', latex: 'm=2' });calculator.setExpression({ id: 'line1', latex: 'y=mx', color: '#ff0000' });calculator.setExpression({ id: 'm', latex: 'm=3' });calculator.setExpression({ id: 'circle1', latex: 'x^2 + y^2 < 1' });calculator.setExpression({id: 'm', sliderBounds: { min: 1, max: 10, step: 1 }});\n", " \n", "});" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "desmos = Desmos()\n", "\n", "# Define a variable m. Doesn't graph anything.\n", "desmos.add_expression(\"{ id: 'm', latex: 'm=2' }\")\n", "\n", "# Draw a red line with slope of m through the origin.\n", "# Because m = 2, this line will be of slope 2.\n", "desmos.add_expression(\"{ id: 'line1', latex: 'y=mx', color: '#ff0000' }\");\n", "\n", "# Updating the value of m will change the slope of the line to 3\n", "desmos.add_expression(\"{ id: 'm', latex: 'm=3' }\")\n", "\n", "# Inequality to shade a circle at the origin\n", "desmos.add_expression(\"{ id: 'circle1', latex: 'x^2 + y^2 < 1' }\");\n", "\n", "#Restrict the slider for the m variable to the integers from 1 to 10\n", "desmos.add_expression(\"{id: 'm', sliderBounds: { min: 1, max: 10, step: 1 }}\")\n", "\n", "# Call display to show the results\n", "desmos.display()" ] }, { "cell_type": "markdown", "id": "4de7f46d-d741-4379-ad55-0b11bbe5b3ef", "metadata": {}, "source": [ "## Using JDesmos With SymPy\n", "\n", "Because of SymPy's excellent support for LaTeX, it's quite simple to use SymPy's powerful CAS (Computer Algebra System) features and display the results in JDesmos. In the example below, we'll take the derivative of a function and draw a tangent line to a point on the curve, a classic Calculus 1 problem with some SymPy flavor." ] }, { "cell_type": "code", "execution_count": 4, "id": "f2e8983c-6401-4204-a17b-7220e898dd74", "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "new Promise(function(resolve, reject) {\n", "\tvar script = document.createElement(\"script\");\n", "\tscript.onload = resolve;\n", "\tscript.onerror = reject;\n", "\tscript.src = \"https://www.desmos.com/api/v1.9/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6\";\n", "\tdocument.head.appendChild(script);\n", "}).then(() => {\n", "\n", " element.style.height = '480px';\n", " element.style.width = '100%';\n", " var calculator = Desmos.GraphingCalculator(element);\n", " calculator.setExpression({\"latex\": \"x^{2}\"});calculator.setExpression({\"latex\": \"(2, 4)\", \"label\": \"(2, 4)\", \"showLabel\": true, \"color\": \"#000000\"});calculator.setExpression({\"latex\": \"y = 4 x - 4\"});\n", " \n", "});" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from sympy import symbols, diff, latex, Eq\n", "\n", "# Typical SymPy setup\n", "x,y = symbols('x y')\n", "\n", "# A simple function x squared\n", "f_of_x = x**2\n", "\n", "# Its derivative, 2x\n", "y_prime = diff(f_of_x)\n", "\n", "# We know that (2,4) is on the curve, but here we use SymPy to arrive at that.\n", "x_coord = 2\n", "\n", "# Figure out y_coordinate for this point based on \n", "# substituting into derivative (i.e., the slope function)\n", "y_coord = y_prime.subs(x, x_coord)\n", "\n", "# Construct the point on the graph and \n", "point = (x_coord, y_coord)\n", "assert point == (2,4)\n", "\n", "# Begin graphing\n", "desmos = Desmos()\n", "\n", "# Add the parabola\n", "desmos.add_latex(latex(f_of_x))\n", "\n", "# Add the point where tangent line will the curve\n", "desmos.add_expression({\"latex\": \"{0}\".format(point), \"label\": \"{0}\".format(point), \"showLabel\": True, \"color\": \"#000000\"})\n", "\n", "# Manually calculate the function for the slope of the tangent line at a point\n", "# using the point-slope formula, y1 - y2 = m(x1 - x2)\n", "# y - 4 = 4(x - 2)\n", "# y = 4x -8 + 4\n", "# y = 4x -4\n", "\n", "# Express the result in SymPy\n", "slope_equation = Eq(y, 4*x - 4)\n", "\n", "# Add the tangent line to our graph\n", "desmos.add_latex(latex(slope_equation))\n", "\n", "desmos.display()\n" ] }, { "cell_type": "code", "execution_count": null, "id": "a10d30cc-061f-420e-934c-ec5bffded8b9", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 5 }