diff --git a/demos/dot-and-numericalsgps.ipynb b/demos/dot-and-numericalsgps.ipynb new file mode 100644 index 0000000..63d77b3 --- /dev/null +++ b/demos/dot-and-numericalsgps.ipynb @@ -0,0 +1,828 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NumericalSgps and dot\n", + "\n", + "Some examples of `JupyterSplashDot` combined with the package [NumericalSgps](https://gap-packages.github.io/numericalsgps/).\n", + "\n", + "We start by loading the package `NumericalSgps`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "true" + ] + }, + "execution_count": 1, + "metadata": { + "text/plain": "" + }, + "output_type": "execute_result" + } + ], + "source": [ + "LoadPackage(\"num\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`DotBinaryRelation` can be used to produce a dot (graphviz) string from a binary relation." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "digraph NSGraph{rankdir = TB; edge[dir=back];\n", + "1 [label=\"1\"];\n", + "2 [label=\"2\"];\n", + "2 -> 1;\n", + "}" + ] + } + ], + "source": [ + "br:=BinaryRelationByElements(Domain([1,2]), [DirectProductElement([1,2])]);;\n", + "Print(DotBinaryRelation(br));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The output binary relation can be visualized with `JupyterSplashDot`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 4, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterSplashDot(DotBinaryRelation(br));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also visualize the Hasse diagram of the set of gaps (with respect to the ordering induced by the semigroup)." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 7, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "s:=NumericalSemigroup(3,5,7);;\n", + "hs:=HasseDiagramOfNumericalSemigroup(s,Gaps(s));;\n", + "JupyterSplashDot(DotBinaryRelation(hs));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Hasse diagram of the oversemigroups (with respect to inclusion) of a numerical semigroup can be drawn as follows." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "〈 2, 3 〉\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "〈 3, 4, 5 〉\n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "〈 3, 5, 7 〉\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 8, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterSplashDot(DotOverSemigroups(s));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or the ways a numerical semigroup decomposes as gluings of numerical semigroups." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "〈 4, 6, 9 〉\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "〈 4 〉 + 〈 6, 9 〉\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "〈 4, 6 〉 + 〈 9 〉\n", + "\n", + "\n", + "\n", + "0->7\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "〈 2, 3 〉\n", + "\n", + "\n", + "\n", + "1->3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "〈 2 〉 + 〈 3 〉\n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "4->6\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "〈 2, 3 〉\n", + "\n", + "\n", + "\n", + "7->8\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "7->9\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "10\n", + "\n", + "〈 2 〉 + 〈 3 〉\n", + "\n", + "\n", + "\n", + "8->10\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "11\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "10->11\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "12\n", + "\n", + "〈 1 〉\n", + "\n", + "\n", + "\n", + "10->12\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 9, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterSplashDot(DotTreeOfGluingsOfNumericalSemigroup( NumericalSemigroup(4,6,9)));\t" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also depict the factorization graph of an integer with respect to a set of non-negative integers; edges are labelled with distances between nodes and the red ones are a minimal spanning tree." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + " (5, 1, 0)\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + " (0, 4, 0)\n", + "\n", + "\n", + "\n", + "1--2\n", + "\n", + "5\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + " (1, 2, 1)\n", + "\n", + "\n", + "\n", + "1--3\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + " (2, 0, 2)\n", + "\n", + "\n", + "\n", + "1--4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "2--3\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "2--4\n", + "\n", + "4\n", + "\n", + "\n", + "\n", + "3--4\n", + "\n", + "2\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 11, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "f:=FactorizationsIntegerWRTList(20,[3,5,7]);;\n", + "JupyterSplashDot(DotFactorizationGraph(f));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can have a look at the Hasse diagram of the Apéry set of a numerical semigroup (with respect to the ordering induced by the semigroup)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "NSGraph\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "13\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "15\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "26\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "27\n", + "\n", + "\n", + "\n", + "5->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "6\n", + "\n", + "28\n", + "\n", + "\n", + "\n", + "6->2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "6->3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "7\n", + "\n", + "39\n", + "\n", + "\n", + "\n", + "7->4\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "8\n", + "\n", + "41\n", + "\n", + "\n", + "\n", + "8->4\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "8->6\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "9\n", + "\n", + "42\n", + "\n", + "\n", + "\n", + "9->3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "9->5\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "10\n", + "\n", + "54\n", + "\n", + "\n", + "\n", + "10->5\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "10->7\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "10->8\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 12, + "metadata": { + "image/svg+xml": { + "height": 500, + "width": 500 + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterSplashDot(DotBinaryRelation(HasseDiagramOfAperyListOfNumericalSemigroup(NumericalSemigroup(10,13,15,27))));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Other examples can be found on the Dot Functions chapter of the `numbericalsgps` package documentation." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "GAP 4", + "language": "gap", + "name": "gap-4" + }, + "language_info": { + "codemirror_mode": "gap", + "file_extension": ".g", + "mimetype": "text/x-gap", + "name": "GAP 4", + "nbconvert_exporter": "", + "pygments_lexer": "gap", + "version": "4.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/demos/tikz-and-intpic.ipynb b/demos/tikz-and-intpic.ipynb new file mode 100644 index 0000000..2bf5631 --- /dev/null +++ b/demos/tikz-and-intpic.ipynb @@ -0,0 +1,191 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# IntPic\n", + "\n", + "This is a notebook showing some drawings related to numerical semigroups produced with the package [IntPic](https://www.gap-system.org/Packages/intpic.html) and the help of `JupyterSplashTikZ`.\n", + "\n", + "We start by loading the package and setting the scale to 1.5, so that the pictures show bigger in the notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "true" + ] + }, + "execution_count": 1, + "metadata": { + "text/plain": "" + }, + "output_type": "execute_result" + } + ], + "source": [ + "LoadPackage(\"IntPic\");\n", + "IP_TikzDefaultOptionsForArraysOfIntegers.scale:=\"1.5\";;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we emphasize the \"small elements\" of the numerical semigroup $\\langle 5,7\\rangle$." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ns:=NumericalSemigroup(13,15,17);;\n", + "tkz := TikzCodeForNumericalSemigroup(ns,[\"small_elements\"]);;\n", + "JupyterSplashTikZ(tkz);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can modify the options to display the semigroup on a table instead." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ns := NumericalSemigroup(5,7);; \n", + "opts:=rec(ns_table := true,negatives:=false);;\n", + "tkz := TikzCodeForNumericalSemigroup(ns,[\"small_elements\"],opts);;\n", + "JupyterSplashTikZ(tkz);" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " " + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "opts := rec(ns_table:=true,colors:=[\"blue\", \"red!70\", \"-red\", \"black!40\"]);;\n", + "highlights := [\"conductor\", \"min_generators\", \"small_elements\"];;\n", + "tkz := TikzCodeForNumericalSemigroup(ns,highlights,opts);;\n", + "JupyterSplashTikZ(tkz);" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "scrolled": true, + "vscode": { + "languageId": "gap" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " " + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ns := NumericalSemigroup(7,11,38,41);;\n", + "highlights := [\"conductor\", \"min_generators\", \"small_elements\"];;\n", + "options := rec(ns_table:=true,colors:=[\"blue\", \"red!70\", \"-red\", \"black!40\"],negatives:=false);;\n", + "tkz := TikzCodeForNumericalSemigroup(ns,highlights,options);;\n", + "JupyterSplashTikZ(tkz);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "GAP 4", + "language": "gap", + "name": "gap-4" + }, + "language_info": { + "codemirror_mode": "gap", + "file_extension": ".g", + "mimetype": "text/x-gap", + "name": "GAP 4", + "nbconvert_exporter": "", + "pygments_lexer": "gap", + "version": "4.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/doc/_Chapter_Jupyter_Kernel.xml b/doc/_Chapter_Jupyter_Kernel.xml new file mode 100644 index 0000000..9d0448f --- /dev/null +++ b/doc/_Chapter_Jupyter_Kernel.xml @@ -0,0 +1,35 @@ + + + + +Jupyter Kernel + +

+ A Jupyter Kernel is an object that can handles the Jupyter Protocol. +

+

+Functions + +

+ + + + Opens a file that is used to log all jupyter protocol + messages. + + + + + + + + Closes the protocol log. + + + + +

+ + +
+ diff --git a/doc/_Chunks.xml b/doc/_Chunks.xml new file mode 100644 index 0000000..e69de29 diff --git a/doc/_entities.xml b/doc/_entities.xml new file mode 100644 index 0000000..9ae54c0 --- /dev/null +++ b/doc/_entities.xml @@ -0,0 +1,8 @@ +crypting'> +json'> +uuid'> +https://jupyter.org'> +https://zeromq.org'> +IO'> +ZeroMQInterface'> +JupyterKernel'> diff --git a/gap/JupyterRenderable.gd b/gap/JupyterRenderable.gd index 8c56c7c..4b65aaa 100644 --- a/gap/JupyterRenderable.gd +++ b/gap/JupyterRenderable.gd @@ -42,6 +42,7 @@ DeclareOperation("JupyterRenderable", [IsObject, IsObject] ); #! Method that provides rich viewing experience if #! code used inside Jupyter DeclareOperation("JupyterRender", [IsObject]); +DeclareOperation("JupyterRender", [IsRecord]); #! @Description #! Accessor for data in a JupyterRenderable diff --git a/gap/JupyterRenderable.gi b/gap/JupyterRenderable.gi index 6543b33..61866b9 100644 --- a/gap/JupyterRenderable.gi +++ b/gap/JupyterRenderable.gi @@ -34,3 +34,8 @@ function(data, metadata) return Objectify( JupyterRenderableType , rec( data := data, metadata := metadata ) ); end); + +InstallMethod( JupyterRender, "for a record", [ IsRecord ], + r -> Objectify( JupyterRenderableType + , rec( data := rec( text\/plain := String(r) ) + , metadata := rec() ) ) ); diff --git a/gap/JupyterUtil.gd b/gap/JupyterUtil.gd index 79e3075..b76a96f 100644 --- a/gap/JupyterUtil.gd +++ b/gap/JupyterUtil.gd @@ -1,5 +1,9 @@ #! @Chapter Jupyter Utility Functions -#! @Section Functions +#! +#! Several utility functions for GAP Jupyter Kernel +#! +#! @Section Print and complete functions +#! #! @Description #! Jupyter printing DeclareGlobalFunction("JUPYTER_print"); @@ -28,3 +32,24 @@ DeclareGlobalFunction("JUPYTER_Inspect"); #! Don't trust this function. DeclareGlobalFunction("ISO8601Stamp"); +#! @Description +#! @Arguments dot +#! The input is a dot (grpahviz) string. +#! +#! The output is the graph corresponding to the dot string. +#! +#! Examples can be found in the numericalsgps notebook in the demo folder +#! +#! Prerrequisites: dot must be installed in the system. +DeclareGlobalFunction("JupyterSplashDot"); + +#! @Description +#! @Arguments tikz +#! The input is a string containing a tikzfigure. +#! +#! The output is the figure corresponding to that tikzfigure. +#! +#! Examples can be found in the inpic notebook in the demo folder +#! +#! Prerrequisites: pdflatex, pdfinfo, pdftoppm, and base64 must be installed in the system. +DeclareGlobalFunction("JupyterSplashTikZ"); diff --git a/gap/JupyterUtil.gi b/gap/JupyterUtil.gi index c7937bb..78b0c5e 100644 --- a/gap/JupyterUtil.gi +++ b/gap/JupyterUtil.gi @@ -1,10 +1,5 @@ -InstallMethod( JupyterRender, [ IsRecord ], - r -> Objectify( JupyterRenderableType - , rec( data := rec( text\/plain := String(r) ) - , metadata := rec() ) ) ); - # This is still an ugly hack, but its already much better than before! -BindGlobal("JupyterSplashDot", +InstallGlobalFunction("JupyterSplashDot", function(dot) local fn, fd, r; @@ -43,13 +38,13 @@ function(group) end); # To show TikZ in a GAP jupyter notebook -BindGlobal("JupyterSplashTikZ", +InstallGlobalFunction("JupyterSplashTikZ", function(tikz) - local tmpdir, fn, header, ltx, svgfile, stream, svgdata, tojupyter, hasbp, img, b64file; + local tmpdir, fn, header, ltx, pngfile, stream, pngdata, tojupyter, hasbp, img, b64file, b64cmd, dims, dimsfile, pdffile, dimx; - hasbp:=PositionSublist(tikz,"begin{tikzpicture}")<>fail; + hasbp:=PositionSublist(tikz,"begin[border=2pt]{tikzpicture}")<>fail; - header:=Concatenation( "\\documentclass[crop,tikz]{standalone}\n", + header:=Concatenation( "\\documentclass[crop,tikz,border=2pt]{standalone}\n", "\\usepackage{pgfplots}", "\\makeatletter\n", "\\batchmode\n", @@ -75,40 +70,58 @@ function(tikz) Concatenation( fn, ".tex" ), " > ", Concatenation( fn, ".log2" ) ); Exec( ltx ); - if not( IsExistingFile( Concatenation(fn, ".pdf") ) ) then + pdffile:=Concatenation(fn, ".pdf"); + if not( IsExistingFile( pdffile ) ) then tojupyter := rec( json := true, name := "stdout", data := "No pdf was created; pdflatex is installed in your system?",metadata:=rec() ); + Info(InfoWarning,1,"No pdf was created; pdflatex is installed in your system?"); return JupyterRenderable(tojupyter.data, tojupyter.metadata); fi; - svgfile := Concatenation( fn, ".svg" ); - b64file := Concatenation( fn, ".b64" ); - if ARCH_IS_MAC_OS_X() then - ltx := Concatenation( "pdf2svg ", Concatenation( fn, ".pdf" ), " ", - svgfile, "; base64 -i ", svgfile," >> ", b64file ); - - else - ltx := Concatenation( "pdf2svg ", Concatenation( fn, ".pdf" ), " ", - svgfile, "; base64 ", svgfile," >> ", b64file ); - fi; - Exec( ltx ); - if not( IsExistingFile( svgfile ) ) then + dimsfile:=Concatenation(fn, "-dims.txt"); + ltx:=Concatenation("pdfinfo ",pdffile," | grep \"Page size\" > ",dimsfile); + Exec(ltx); + if not( IsExistingFile( dimsfile ) ) then tojupyter := rec( json := true, name := "stdout", - data := "No svg was created; pdf2svg is installed in your system?", metadata := rec()); + data := "pdfinfo missing in your system",metadata:=rec() ); + Info(InfoWarning,1,"No pdf was created; pdflatex is installed in your system?"); return JupyterRenderable(tojupyter.data, tojupyter.metadata); fi; - stream := InputTextFile( b64file ); - if stream <> fail then - svgdata := ReadAll( stream ); - CloseStream( stream ); - else + + stream := InputTextFile( dimsfile ); + dims:= ReadAll( stream ); + NormalizeWhitespace(dims); + CloseStream( stream ); + dimx:=Float(NormalizedWhitespace(dims{[PositionSublist(dims,": ")+2..PositionSublist(dims," x")]})); + + pngfile := Concatenation( fn, ".png" ); + ltx := Concatenation( "pdftoppm -r 300 -png ", pdffile, " > ", pngfile); + Exec( ltx ); + + if not( IsExistingFile( pngfile ) ) then tojupyter := rec( json := true, name := "stdout", - data := Concatenation( "Unable to render ", tikz ), metadata := rec() ); + data := "No png was created; pdftoppm is installed in your system?",metadata:=rec() ); + Info(InfoWarning,1,"No png was created; are convert and pdftoppm installed in your system?"); return JupyterRenderable(tojupyter.data, tojupyter.metadata); fi; - img:=Concatenation(""); - return Objectify( JupyterRenderableType, rec( data := rec( ("text/html") := img), metadata:=rec() )); + b64file := Concatenation( fn, ".b64" ); + if ARCH_IS_MAC_OS_X() then + b64cmd:="base64 -i "; + else + b64cmd:="base64 "; + fi; + + ltx := Concatenation( b64cmd, pngfile," > ", b64file ); + Exec( ltx ); + stream := InputTextFile( b64file ); + pngdata:= ReadAll( stream ); + CloseStream( stream ); + + + img:=Concatenation("\n "); + + return Objectify( JupyterRenderableType, rec( data := rec( ("text/html") := img), metadata:=rec( ) )); end); # This is really not what I should be doing here...