Created
July 23, 2022 22:10
-
-
Save krassowski/5b370eeb626ae9bc84b38ca248b8066e to your computer and use it in GitHub Desktop.
rpy2-complex-heatmap-repro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"id": "2e5fc3f2-08fc-4ba4-b83e-7aae97c7c682", | |
"metadata": {}, | |
"source": [ | |
"# Demonstration" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"id": "df31a3e9-8817-49cd-87d6-ba05286b6720", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from heatmap_grammar.rpy2_helpers import rternalize_with_signature\n", | |
"from rpy2.rinterface import rternalize\n", | |
"from rpy2.robjects.packages import importr\n", | |
"\n", | |
"\n", | |
"base = importr('base')\n", | |
"complex_heatmap = importr('ComplexHeatmap')\n", | |
"\n", | |
"m = base.rbind(base.c(*range(10)), base.c(*range(10, 20)))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "e6a9f608-26f1-4367-8541-1522cc3ecca3", | |
"metadata": {}, | |
"source": [ | |
"## Works" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "6f2db710-f472-40da-aa43-0e4cf864bcd6", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@rternalize_with_signature\n", | |
"def draw_1(index, k, n):\n", | |
" print('success 1')\n", | |
" return 1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "153eceee-04fe-4da6-938f-d8a58ee87800", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"anno1 = complex_heatmap.AnnotationFunction(fun=draw_1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "dc3d6512-ad8b-49dd-894a-f95fa11cd37a", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 1\n" | |
] | |
} | |
], | |
"source": [ | |
"complex_heatmap.draw(\n", | |
" complex_heatmap.HeatmapAnnotation(df=m, foo=anno1)\n", | |
");" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "636885c4-2a94-4110-a16d-d9809aa33a81", | |
"metadata": {}, | |
"source": [ | |
"## Doesn't work" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"id": "e8321c10-b7c5-43c5-b65d-189ba3a1e165", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@rternalize\n", | |
"def draw_2(index, k, n):\n", | |
" print('success 2')\n", | |
" return 2" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"id": "ce72d657-64ef-4d40-8b2b-88308e1a2c24", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"anno2 = complex_heatmap.AnnotationFunction(fun=draw_2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"id": "4bec535a-b597-4f88-94f1-9ed9f042f256", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"R[write to console]: Error in object@fun(index, k, n) : '...' used in an incorrect context\n", | |
"\n", | |
"R[write to console]: In addition: \n", | |
"R[write to console]: Warning messages:\n", | |
"\n", | |
"R[write to console]: 1: `df` should be a data frame while not a matrix. Convert it to data\n", | |
"frame. \n", | |
"\n", | |
"R[write to console]: 2: `df` should be a data frame while not a matrix. Convert it to data\n", | |
"frame. \n", | |
"\n" | |
] | |
}, | |
{ | |
"ename": "RRuntimeError", | |
"evalue": "Error in object@fun(index, k, n) : '...' used in an incorrect context\n", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mRRuntimeError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m/tmp/ipykernel_526955/293212760.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m complex_heatmap.draw(\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mcomplex_heatmap\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mHeatmapAnnotation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfoo\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0manno2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m );\n", | |
"\u001b[0;32m~site-packages/rpy2/robjects/functions.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[0mv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mr_k\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 202\u001b[0;31m return (super(SignatureTranslatedFunction, self)\n\u001b[0m\u001b[1;32m 203\u001b[0m .__call__(*args, **kwargs))\n\u001b[1;32m 204\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~site-packages/rpy2/robjects/functions.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 123\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[0mnew_kwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpy2rpy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 125\u001b[0;31m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mFunction\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mnew_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnew_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 126\u001b[0m \u001b[0mres\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrpy2py\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mres\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 127\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mres\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~site-packages/rpy2/rinterface_lib/conversion.py\u001b[0m in \u001b[0;36m_\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 43\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_cdata_res_to_rinterface\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 44\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 45\u001b[0;31m \u001b[0mcdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 46\u001b[0m \u001b[0;31m# TODO: test cdata is of the expected CType\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0m_cdata_to_rinterface\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m~site-packages/rpy2/rinterface.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 811\u001b[0m )\n\u001b[1;32m 812\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merror_occured\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 813\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0membedded\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_rinterface\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_geterrmessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 814\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mres\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 815\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mRRuntimeError\u001b[0m: Error in object@fun(index, k, n) : '...' used in an incorrect context\n" | |
] | |
} | |
], | |
"source": [ | |
"complex_heatmap.draw(\n", | |
" complex_heatmap.HeatmapAnnotation(df=m, foo=anno2)\n", | |
");" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "41e151c5-ff02-48a2-a941-9fbc0a0ceb35", | |
"metadata": {}, | |
"source": [ | |
"# Attempts at narrowing it down" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "7e2d4618-0794-4644-9cec-fcf0ab8646e3", | |
"metadata": {}, | |
"source": [ | |
"## 1. Calling from Python works" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"id": "297bce7c-71fa-4118-81b7-8433784c311b", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 1\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<rpy2.rinterface.IntSexpVector object at 0x7f9ba88fd840> [RTYPES.INTSXP]" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"draw_1(1, 1, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"id": "3b5e5e2b-f275-4b29-861a-7f751a483a9d", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 2\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<rpy2.rinterface.IntSexpVector object at 0x7f9bb47d0940> [RTYPES.INTSXP]" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"draw_2(1, 1, 1)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "246490ec-060f-4dfe-89ea-caec29faaaf6", | |
"metadata": {}, | |
"source": [ | |
"## 2. Wrapping in env works" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "184748de-917d-4f74-a417-41fad02bff75", | |
"metadata": {}, | |
"source": [ | |
"The call in [`object@fun(index, k, n)`](https://github.com/jokergoo/ComplexHeatmap/blob/31cf7167ddc6fc0ff27fd14067d65871254e8866/R/AnnotationFunction-class.R#L355) is accutally occuring on an environment-wrapped fun, see [this](https://github.com/jokergoo/ComplexHeatmap/blob/31cf7167ddc6fc0ff27fd14067d65871254e8866/R/AnnotationFunction-class.R#L405-L409):\n", | |
"\n", | |
"```R\n", | |
"\t\tobject2@var_env = new.env()\n", | |
"\t\tfor(var in names(object@var_env)) {\n", | |
"\t\t\tobject2@var_env[[var]] = object@var_env[[var]]\n", | |
"\t\t}\n", | |
"\t\tenvironment(object2@fun) = object2@var_env\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"id": "ff43385c-4f1c-40cc-9b32-a0ab6e98f433", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"env = base.new_env()\n", | |
"assign_environment = base._env['environment<-']\n", | |
"wrapped_draw_1 = assign_environment(draw_1, env)\n", | |
"wrapped_draw_2 = assign_environment(draw_2, env)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"id": "d1b49903-f1ba-46ac-985d-a636a5376e87", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 1\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<rpy2.rinterface.IntSexpVector object at 0x7f9b9ef3cf40> [RTYPES.INTSXP]" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"wrapped_draw_1(1, 1, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"id": "bc42e017-22ea-4bf8-9621-4d3917022e23", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 2\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<rpy2.rinterface.IntSexpVector object at 0x7f9b9ef3d940> [RTYPES.INTSXP]" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"wrapped_draw_2(1, 1, 1)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "eaacd711-f499-4db4-a53f-e4fc88928fd7", | |
"metadata": {}, | |
"source": [ | |
"## 3. From R" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"id": "3aafd6cf-8f69-4ee8-9357-f8fed8edb0a9", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%load_ext rpy2.ipython" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"id": "e28fb917-37a4-4772-b286-8b39563ea08b", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"success 1\n", | |
"success 2\n", | |
"[1] 2\n" | |
] | |
} | |
], | |
"source": [ | |
"%%R -i draw_1 -i draw_2\n", | |
"draw_1(1, 1, 1)\n", | |
"draw_2(1, 1, 1)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"id": "b6ca8b80-d8ed-4670-8464-534ad5e0b186", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"function (index, k, n) \n", | |
"{\n", | |
" RPY2_ARGUMENTS <- base::list(\".Python\", <pointer: 0x7f9bdc717880>)\n", | |
" if (!base::missing(index)) {\n", | |
" RPY2_ARGUMENTS[[\"index\"]] <- index\n", | |
" }\n", | |
" if (!base::missing(k)) {\n", | |
" RPY2_ARGUMENTS[[\"k\"]] <- k\n", | |
" }\n", | |
" if (!base::missing(n)) {\n", | |
" RPY2_ARGUMENTS[[\"n\"]] <- n\n", | |
" }\n", | |
" do.call(.External, RPY2_ARGUMENTS)\n", | |
"}\n", | |
"<bytecode: 0x564831632d58>\n" | |
] | |
} | |
], | |
"source": [ | |
"%%R\n", | |
"draw_1" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"id": "1da26543-80ed-4ba3-9580-66b52a5a43f6", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"function (...) \n", | |
"{\n", | |
" .External(\".Python\", <pointer: 0x7f9ba8905a80>, ...)\n", | |
"}\n", | |
"<bytecode: 0x5648316c46b0>\n" | |
] | |
} | |
], | |
"source": [ | |
"%%R\n", | |
"draw_2" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "1155d3e0-2dff-425a-bc89-f2b0e59a74eb", | |
"metadata": {}, | |
"source": [ | |
"## 4. But the actual functions are different!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"id": "0e4233fe-0da5-41ff-9a84-ac017f2cc565", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"function (index, k, n) \n", | |
"{\n", | |
" RPY2_ARGUMENTS <- base::list(\".Python\", <pointer: 0x7f9bdc717880>)\n", | |
" if (!base::missing(index)) {\n", | |
" RPY2_ARGUMENTS[[\"index\"]] <- index\n", | |
" }\n", | |
" if (!base::missing(k)) {\n", | |
" RPY2_ARGUMENTS[[\"k\"]] <- k\n", | |
" }\n", | |
" if (!base::missing(n)) {\n", | |
" RPY2_ARGUMENTS[[\"n\"]] <- n\n", | |
" }\n", | |
" do.call(.External, RPY2_ARGUMENTS)\n", | |
"}\n", | |
"<bytecode: 0x564831632d58>\n" | |
] | |
} | |
], | |
"source": [ | |
"%%R -i anno1\n", | |
"anno1@fun" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"id": "bc476ff3-cd4f-4a34-a555-55e85e40f2da", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"function (index, k = 1, n = 1) \n", | |
"{\n", | |
" .External(\".Python\", <pointer: 0x7f9ba8905a80>, ...)\n", | |
"}\n" | |
] | |
} | |
], | |
"source": [ | |
"%%R -i anno2\n", | |
"anno2@fun" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "36079622-99f7-4e7d-bb06-bce5b0c54325", | |
"metadata": {}, | |
"source": [ | |
"Found it: https://github.com/jokergoo/ComplexHeatmap/blob/31cf7167ddc6fc0ff27fd14067d65871254e8866/R/AnnotationFunction-class.R#L220-L222:\n", | |
"\n", | |
"```R\n", | |
"if(length(as.list(formals(fun))) == 1) {\n", | |
"\tformals(fun) = alist(index = , k = 1, n = 1)\n", | |
"}\n", | |
"anno@fun = fun\n", | |
"```" | |
] | |
} | |
], | |
"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.8.6" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment