{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 5. Spheres and spherical coordinates in higher dimensions\n", "\n", "This notebook is part of the [Introduction to manifolds in SageMath](https://sagemanifolds.obspm.fr/intro_to_manifolds.html) by Andrzej Chrzeszczyk (Jan Kochanowski University of Kielce, Poland)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'SageMath version 9.6, Release Date: 2022-05-15'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "version()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "In the `EuclideanSpace` class, the transitions from spherical to Cartesian and Cartesian to spherical coordinates are predefined in the case $n\\leq 3$ (SageMath 9.5).\n", " \n", "
\n", " \n", " **Example 5.1**\n", " \n", " Let us demonstrate spherical coordinates for $n=3$." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "x1 = r*cos(ph)*sin(th)\n", "x2 = r*sin(ph)*sin(th)\n", "x3 = r*cos(th)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.=EuclideanSpace(3,\"E\") # Euclidean space E^3\n", "cart=E.cartesian_coordinates() # Cartesian coordinates\n", "spher. = E.spherical_coordinates() # spherical coordinates\n", "E.coord_change(spher, cart).display() # transition spher -> cart " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "r = sqrt(x1^2 + x2^2 + x3^2)\n", "th = arctan2(sqrt(x1^2 + x2^2), x3)\n", "ph = arctan2(x2, x1)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "E.coord_change(cart, spher).display() # transition cart -> spher" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "The `manifolds.Sphere` module allows for **higher dimensions**.\n", "\n", "\n", "\n", "We can use predefined embeddings and transition functions on higher dimensional spheres.\n", "\n", "\n", "
\n", "\n", "**Example 5.2**\n", "\n", "Let us demonstrate the case of 3-dimensional sphere in $E^4$." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\begin{array}{llcl} \\iota:& \\mathbb{S}^{3} & \\longrightarrow & \\mathbb{E}^{4} \\\\ \\mbox{on}\\ A : & \\left(\\chi, \\theta, \\phi\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\cos\\left(\\phi\\right) \\sin\\left(\\chi\\right) \\sin\\left(\\theta\\right), \\sin\\left(\\chi\\right) \\sin\\left(\\phi\\right) \\sin\\left(\\theta\\right), \\cos\\left(\\theta\\right) \\sin\\left(\\chi\\right), \\cos\\left(\\chi\\right)\\right) \\end{array}\\)" ], "text/latex": [ "$\\displaystyle \\begin{array}{llcl} \\iota:& \\mathbb{S}^{3} & \\longrightarrow & \\mathbb{E}^{4} \\\\ \\mbox{on}\\ A : & \\left(\\chi, \\theta, \\phi\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\cos\\left(\\phi\\right) \\sin\\left(\\chi\\right) \\sin\\left(\\theta\\right), \\sin\\left(\\chi\\right) \\sin\\left(\\phi\\right) \\sin\\left(\\theta\\right), \\cos\\left(\\theta\\right) \\sin\\left(\\chi\\right), \\cos\\left(\\chi\\right)\\right) \\end{array}$" ], "text/plain": [ "iota: S^3 → E^4\n", "on A: (chi, theta, phi) ↦ (x1, x2, x3, x4) = (cos(phi)*sin(chi)*sin(theta), sin(chi)*sin(phi)*sin(theta), cos(theta)*sin(chi), cos(chi))" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%display latex\n", "dim=3 # dimension of the sphere (not the Euclidean space)\n", "Sph=manifolds.Sphere(dim) # sphere S^3\n", "spher = Sph.spherical_coordinates() # spherical coordinates on S^3\n", "Sph.embedding().disp() # embedding S^3 -> E^4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "The **stereographic projections** are also accessible in higher dimensions.\n", "\n", "
\n", "\n", "**Example 5.3**\n", "\n", "**Stereographic coordinates in $S^3$**." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\begin{array}{llcl} \\iota:& \\mathbb{S}^{3} & \\longrightarrow & \\mathbb{E}^{4} \\\\ \\mbox{on}\\ A : & \\left(\\chi, \\theta, \\phi\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\cos\\left(\\phi\\right) \\sin\\left(\\chi\\right) \\sin\\left(\\theta\\right), \\sin\\left(\\chi\\right) \\sin\\left(\\phi\\right) \\sin\\left(\\theta\\right), \\cos\\left(\\theta\\right) \\sin\\left(\\chi\\right), \\cos\\left(\\chi\\right)\\right) \\\\ \\mbox{on}\\ \\mathbb{S}^{3}\\setminus\\{\\mathrm{NP}\\} : & \\left(u, v, w\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\frac{2 \\, u}{u^{2} + v^{2} + w^{2} + 1}, \\frac{2 \\, v}{u^{2} + v^{2} + w^{2} + 1}, \\frac{2 \\, w}{u^{2} + v^{2} + w^{2} + 1}, \\frac{u^{2} + v^{2} + w^{2} - 1}{u^{2} + v^{2} + w^{2} + 1}\\right) \\\\ \\mbox{on}\\ \\mathbb{S}^{3}\\setminus\\{\\mathrm{SP}\\} : & \\left({u'}, {v'}, {w'}\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\frac{2 \\, {u'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, \\frac{2 \\, {v'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, \\frac{2 \\, {w'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, -\\frac{{u'}^{2} + {v'}^{2} + {w'}^{2} - 1}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}\\right) \\end{array}\\)" ], "text/latex": [ "$\\displaystyle \\begin{array}{llcl} \\iota:& \\mathbb{S}^{3} & \\longrightarrow & \\mathbb{E}^{4} \\\\ \\mbox{on}\\ A : & \\left(\\chi, \\theta, \\phi\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\cos\\left(\\phi\\right) \\sin\\left(\\chi\\right) \\sin\\left(\\theta\\right), \\sin\\left(\\chi\\right) \\sin\\left(\\phi\\right) \\sin\\left(\\theta\\right), \\cos\\left(\\theta\\right) \\sin\\left(\\chi\\right), \\cos\\left(\\chi\\right)\\right) \\\\ \\mbox{on}\\ \\mathbb{S}^{3}\\setminus\\{\\mathrm{NP}\\} : & \\left(u, v, w\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\frac{2 \\, u}{u^{2} + v^{2} + w^{2} + 1}, \\frac{2 \\, v}{u^{2} + v^{2} + w^{2} + 1}, \\frac{2 \\, w}{u^{2} + v^{2} + w^{2} + 1}, \\frac{u^{2} + v^{2} + w^{2} - 1}{u^{2} + v^{2} + w^{2} + 1}\\right) \\\\ \\mbox{on}\\ \\mathbb{S}^{3}\\setminus\\{\\mathrm{SP}\\} : & \\left({u'}, {v'}, {w'}\\right) & \\longmapsto & \\left({x_{1}}, {x_{2}}, {x_{3}}, {x_{4}}\\right) = \\left(\\frac{2 \\, {u'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, \\frac{2 \\, {v'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, \\frac{2 \\, {w'}}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}, -\\frac{{u'}^{2} + {v'}^{2} + {w'}^{2} - 1}{{u'}^{2} + {v'}^{2} + {w'}^{2} + 1}\\right) \\end{array}$" ], "text/plain": [ "iota: S^3 → E^4\n", "on A: (chi, theta, phi) ↦ (x1, x2, x3, x4) = (cos(phi)*sin(chi)*sin(theta), sin(chi)*sin(phi)*sin(theta), cos(theta)*sin(chi), cos(chi))\n", "on S^3-{NP}: (u, v, w) ↦ (x1, x2, x3, x4) = (2*u/(u^2 + v^2 + w^2 + 1), 2*v/(u^2 + v^2 + w^2 + 1), 2*w/(u^2 + v^2 + w^2 + 1), (u^2 + v^2 + w^2 - 1)/(u^2 + v^2 + w^2 + 1))\n", "on S^3-{SP}: (up, vp, wp) ↦ (x1, x2, x3, x4) = (2*up/(up^2 + vp^2 + wp^2 + 1), 2*vp/(up^2 + vp^2 + wp^2 + 1), 2*wp/(up^2 + vp^2 + wp^2 + 1), -(up^2 + vp^2 + wp^2 - 1)/(up^2 + vp^2 + wp^2 + 1))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# continuation\n", "%display latex\n", "stereoN, stereoS = Sph.coordinate_charts('stereographic',\n", " names=['u','v','w']) # stereographic projections in S^3\n", "Sph.embedding().disp() # show embeddings into E^4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have also the corresponding transitions in $S^3$ predefined." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left\\{\\begin{array}{lcl} u & = & \\frac{{u'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\\\ v & = & \\frac{{v'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\\\ w & = & \\frac{{w'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\end{array}\\right.\\)" ], "text/latex": [ "$\\displaystyle \\left\\{\\begin{array}{lcl} u & = & \\frac{{u'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\\\ v & = & \\frac{{v'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\\\ w & = & \\frac{{w'}}{{u'}^{2} + {v'}^{2} + {w'}^{2}} \\end{array}\\right.$" ], "text/plain": [ "u = up/(up^2 + vp^2 + wp^2)\n", "v = vp/(up^2 + vp^2 + wp^2)\n", "w = wp/(up^2 + vp^2 + wp^2)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = spher.domain() # domain of spherical coordinates\n", "# intersection of domains of stereoN and stereoS coordinates:\n", "W = Sph._stereoN_dom.intersection(Sph._stereoS_dom)\n", "# intersection of domains of stereoN,stereoS and spher coordinates:\n", "V=W.intersection(A) \n", " # transition spher -> stereoN:\n", "F1=Sph.coord_change(spher.restrict(V), stereoN.restrict(V))\n", " # transition stereoN -> spher:\n", "F2=Sph.coord_change( stereoN.restrict(V),spher.restrict(V))\n", " # transition spher -> stereoS \n", "F3=Sph.coord_change(spher.restrict(V), stereoS.restrict(V))\n", " # transition stereoS -> spher\n", "F4=Sph.coord_change( stereoS.restrict(V),spher.restrict(V))\n", " # transition stereoN -> stereoS\n", "F5=Sph.coord_change( stereoN.restrict(V),stereoS.restrict(V))\n", " # transition stereoS -> stereoN\n", "F6=Sph.coord_change( stereoS.restrict(V),stereoN.restrict(V))\n", "F6.disp()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\\(\\displaystyle \\left\\{\\begin{array}{lcl} {u'} & = & \\frac{u}{u^{2} + v^{2} + w^{2}} \\\\ {v'} & = & \\frac{v}{u^{2} + v^{2} + w^{2}} \\\\ {w'} & = & \\frac{w}{u^{2} + v^{2} + w^{2}} \\end{array}\\right.\\)" ], "text/latex": [ "$\\displaystyle \\left\\{\\begin{array}{lcl} {u'} & = & \\frac{u}{u^{2} + v^{2} + w^{2}} \\\\ {v'} & = & \\frac{v}{u^{2} + v^{2} + w^{2}} \\\\ {w'} & = & \\frac{w}{u^{2} + v^{2} + w^{2}} \\end{array}\\right.$" ], "text/plain": [ "up = u/(u^2 + v^2 + w^2)\n", "vp = v/(u^2 + v^2 + w^2)\n", "wp = w/(u^2 + v^2 + w^2)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "F5.disp()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Example 5.4**\n", "\n", "**Spherical coordinates in $R^4$**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use `manifolds.Sphere` to obtain the transition from spherical to Cartesian coordinates in $R^4$." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(r*cos(phi)*sin(chi)*sin(theta),\n", " r*sin(chi)*sin(phi)*sin(theta),\n", " r*cos(theta)*sin(chi),\n", " r*cos(chi))" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%display plain # to obtain output which can be re-used in the code\n", "dim=3 # dimension of the sphere\n", "r=var('r') # symbolic variable\n", "Sph=manifolds.Sphere(dim,radius=r) # 3-dim sphere with radius r\n", "Phi=Sph.embedding() # embedding into E^4\n", "E=Sph.ambient() # ambient space E^4\n", "fun=Phi.coord_functions() # embedding functions\n", "fun.expr() # show embedding functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result can be used to define the transition spherU -> cartU in $R^4$." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "x1 = r*cos(phi)*sin(chi)*sin(theta)\n", "x2 = r*sin(chi)*sin(phi)*sin(theta)\n", "x3 = r*cos(theta)*sin(chi)\n", "x4 = r*cos(chi)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R4=Manifold(4,'R^4',start_index=1) # manifold R^4\n", "cart.=R4.chart() # Cartesian coordinates in R^4\n", "U=R4.open_subset('U', # open subset of R^4 with half-\n", " coord_def={cart: (x2!=0, x1<0)}) # plane {x2 = 0, x1 ≥ 0} excluded\n", "cartU=cart.restrict(U) # restrict cart to U\n", " # spherical coordinates on U, use\n", " # names from the previous output!\n", "spherU.=U.chart(r'r:(0,+oo) chi:(0,pi):\\chi\\\n", " theta:(0,pi):\\theta phi:(-pi,pi):periodic:\\phi')\n", " # transition spherU -> cartU\n", "spher_to_cart = spherU.transition_map(cartU,fun.expr())\n", "spher_to_cart.disp() # show transition" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# spher_to_cart.inverse() does not work" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inverse transition can be defined as follows:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check of the inverse coordinate transformation:\n", " r == r *passed*\n", " chi == arctan2(r*sin(chi), r*cos(chi)) **failed**\n", " theta == arctan2(r*sin(chi)*sin(theta), r*cos(theta)*sin(chi)) **failed**\n", " phi == arctan2(r*sin(chi)*sin(phi)*sin(theta), r*cos(phi)*sin(chi)*sin(theta)) **failed**\n", " x1 == x1 *passed*\n", " x2 == x2 *passed*\n", " x3 == x3 *passed*\n", " x4 == x4 *passed*\n", "NB: a failed report can reflect a mere lack of simplification.\n" ] } ], "source": [ "fun=(sqrt(x1^2+x2^2+x3^2+x4^2), # functions defining\n", " atan2(sqrt(x1^2+x2^2+x3^2),x4), # inverse transition\n", " atan2(sqrt(x1^2+x2^2),x3), # spher -> cart\n", " atan2(x2,x1))\n", "spher_to_cart.set_inverse(*fun) # set inverse trans." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The failed computations reflect a lack of simplification in `SageMath` and can be checked by hand (https://en.wikipedia.org/wiki/Atan2)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Example 5.5**\n", "\n", "**Spherical coordinates in $R^5$**." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In 5-dimensional Euclidean space E^5\n", "the spherical coordinates are\n", "(x1, x2, x3, x4, x5) =\n" ] }, { "data": { "text/plain": [ "(r*cos(phi_4)*sin(phi_1)*sin(phi_2)*sin(phi_3),\n", " r*sin(phi_1)*sin(phi_2)*sin(phi_3)*sin(phi_4),\n", " r*cos(phi_3)*sin(phi_1)*sin(phi_2),\n", " r*cos(phi_2)*sin(phi_1),\n", " r*cos(phi_1))" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%display plain # We don't want the Latex output\n", "dim=4 # dimension of the sphere\n", "r=var('r') # symbolic variable\n", "Sph=manifolds.Sphere(dim,radius=r) # 4-dim sphere, radius r,in E^5\n", "Phi=Sph.embedding() # embedding S^4 -> E^5\n", "E=Sph.ambient() # ambient space E^5\n", "print(\"In\",E)\n", "print(\"the spherical coordinates are\")\n", "print(E.cartesian_coordinates()[:],\"=\")\n", "Phi.coord_functions()[:] # print coordinate functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the result we can define the transition spherU -> cartU in $R^5$." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "x1 = r*cos(phi4)*sin(phi1)*sin(phi2)*sin(phi3)\n", "x2 = r*sin(phi1)*sin(phi2)*sin(phi3)*sin(phi4)\n", "x3 = r*cos(phi3)*sin(phi1)*sin(phi2)\n", "x4 = r*cos(phi2)*sin(phi1)\n", "x5 = r*cos(phi1)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R5=Manifold(5,'R^5') # manifold R^5\n", "cart.=R5.chart() # Cartesian coord. in R^5\n", "U=R5.open_subset('U', # open subset of R^5,\n", " coord_def={cart:(x3!=0,x2!=0,x1<0)}) #{x3=0,x2=0,x1>=0} exclud.\n", "cartU=cart.restrict(U) # restrict Cart.coord.to U\n", "# use the same names as in the output of the previous command\n", "spherU.=U.chart(r'r:(0,+oo) phi1:(0,pi):\\phi_1\\\n", "phi2:(0,pi):\\phi_2 phi3:0,pi):\\phi_3 phi4:(-pi,pi):periodic:\\phi_4')\n", " # spherical coordinates on U\n", "spher_to_cart = spherU.transition_map(cartU, # define transition\n", "(r*cos(phi_4)*sin(phi_1)*sin(phi_2)*sin(phi_3), # spher -> cart\n", "r*sin(phi_1)*sin(phi_2)*sin(phi_3)*sin(phi_4),\n", "r*cos(phi_3)*sin(phi_1)*sin(phi_2),\n", "r*cos(phi_2)*sin(phi_1),\n", "r*cos(phi_1)))\n", "\n", "spher_to_cart.disp() # show transition " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "\n", "**Inverse transition**:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check of the inverse coordinate transformation:\n", " r == r *passed*\n", " phi1 == arctan2(r*sin(phi1), r*cos(phi1)) **failed**\n", " phi2 == arctan2(r*sin(phi1)*sin(phi2), r*cos(phi2)*sin(phi1)) **failed**\n", " phi3 == arctan2(r*abs(sin(phi3))*sin(phi1)*sin(phi2), r*cos(phi3)*sin(phi1)*sin(phi2)) **failed**\n", " phi4 == arctan2(r*sin(phi1)*sin(phi2)*sin(phi3)*sin(phi4), r*cos(phi4)*sin(phi1)*sin(phi2)*sin(phi3)) **failed**\n", " x1 == x1 *passed*\n", " x2 == x2 *passed*\n", " x3 == x3 *passed*\n", " x4 == x4 *passed*\n", " x5 == x5 *passed*\n", "NB: a failed report can reflect a mere lack of simplification.\n" ] } ], "source": [ "fun=(sqrt(x1^2+x2^2+x3^2+x4^2+x5^2), # functions defining the \n", " atan2(sqrt(x1^2+x2^2+x3^2+x4^2),x5), # inverse transition\n", " atan2(sqrt(x1^2+x2^2+x3^2),x4),\n", " atan2(sqrt(x1^2+x2^2),x3),\n", " atan2(x2,x1))\n", "cart_to_spher=spher_to_cart.set_inverse(*fun) # define inv. trans." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What's next?\n", "\n", "Take a look at the notebook [The notion of module](https://nbviewer.org/github/sagemanifolds/IntroToManifolds/blob/main/06Manifold_VectSpaces_Modules.ipynb)." ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.6", "language": "sage", "name": "sagemath" }, "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.8.10" } }, "nbformat": 4, "nbformat_minor": 4 }