diff --git a/lib/wasm.js b/lib/wasm_tinygo.js similarity index 100% rename from lib/wasm.js rename to lib/wasm_tinygo.js diff --git a/notebooks/deno_tinygo_wasm.ipynb b/notebooks/deno_tinygo_wasm.ipynb index 6f584b5..c76e9bc 100644 --- a/notebooks/deno_tinygo_wasm.ipynb +++ b/notebooks/deno_tinygo_wasm.ipynb @@ -12,21 +12,21 @@ "Stats initialized\n", "\n", "Linear Regression Line:\n", - "\tEstimated offset is: 1.474039\n", - "\tEstimated slope is: 3.000136\n", - "\tR^2 is: 0.999989\n" + "\tEstimated offset is: -2.258540\n", + "\tEstimated slope is: -0.024285\n", + "\tR^2 is: 0.882633\n" ] } ], "source": [ - "import stats from \"https://l12.xyz/x/shortcuts/raw/stat/mod.ts\";\n", + "import stats from \"../stat/mod.ts\";\n", "\n", "const xs = [];\n", "const ys = [];\n", "\n", "for (let i = 0; i < 100; i++) {\n", " xs.push(i);\n", - " ys.push((1 + 3 * i) + Math.random());\n", + " ys.push(1 - Math.log(2 * i + 3 + Math.random() * 10));\n", "}\n", "\n", "const linreg = stats.LinearRegression(xs, ys, [], false);\n", @@ -40,24 +40,54 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "![name](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkAAAAGACAIAAADK+EpIAAAmjUlEQVR4nOzde1xVZd738WtvNgKCnERAUINU8ITgoGJqNiZmHtIZ0UJLU7PsTnN00rLRGqe08nBnivcMjo4yORo6ZKaYR4ReKXkgxVTExAQBRUDOIIe9Wc9rWnPvmwexKWOzvODz/qP2ta7Fdf0We7O/rrXXXsugKIoAAEA2Bq0LAH4Gk8lkZWWldRWNJiYmZvfu3a6uruvWrbPoRElJSbt37759+3ZERITBwF89mgm91gUA/3Lo0KGJEyfa2dlNnDjx0KFDQojCwsLFixd7eXn5+fktXbrUZDJlZ2c7OTl9/vnnWhfbOBITE1etWrV582ZzJBcXFy9atKhdu3YODg6vv/56RkaGuvzIkSNPPfVUnz59IiMj72+uvn37Dh06NDIy0mQyNd4WAFpTgAdDfHy8ECI+Pr7uwsDAwHHjxqmPq6urly5dev369XuNUFNTs2/fPstX2jheffXV6dOn37187dq1QogNGzbUXRgaGnru3LlfMt2RI0eEEJWVlb9kEOCBwh4YpGFtbf3HP/6xY8eOdRfW/RB3x44dn332Wb2futenvLW1tUKI7OzsVatW/cQf+RH/8UfuXiErK8vGxubuNefMmRMSErJo0aLc3Fx1yY4dO3r27Nm7d++fW9V9u7taPizHA4gAgzT+/Oc/BwcH79q1S30/nTdvXmho6IwZM4KDg4uLi2NjY99+++2jR49OmjTp3Llz6idMoaGh06dPHz58+JtvvlldXa2OExkZ+fjjj7/yyiuDBw/u2rXroEGDamtr33333YCAgPj4+PDw8EGDBgkh3n///SeffPLZZ58NCAhQj1seO3Zs5MiRM2bMmDZtmpeXl6ura0RExNtvv92nTx/14KfRaLy77A0bNjzxxBPTpk0bOnToqlWr1OB89913T548efjw4UmTJm3btq3u+nq9fuPGjWVlZfPnzxdClJeXr169+p133qk37LJly3r16vXCCy98++23QojDhw+PHz9+wYIFRqPxL3/5y/Dhw6dMmRIQELB169Z6P1hcXLxgwYKAgIDS0lIhRERERP/+/Xfu3Gn+5QwbNmz69OmhoaFpaWnqsdyxY8eOHz9+8uTJ48aNa9SnFPhltN4FBP5NPYS4bt26r+ro0qWL+RCioiienp6bNm1SFOXQoUNeXl61tbWKokRFRRUWFiqK8pvf/GbmzJnqmt98802rVq0yMzMVRamsrOzVq9eyZcsURTl79qxOp7t27ZqiKDk5OUKIuLg4RVGysrKEEO+9996lS5fmz5+vKMq7775rMpkURXn77be7du2qDhseHj5u3LjS0tKKiopnn33Wzc0tLy9PUZQ9e/YIIU6ePFlvo/bs2ePm5lZUVKQoSlFRkaenZ1RUlNo1ZsyYl19++V6/jT/84Q/qR4Nvvvnm1q1b716htra2S5cuU6ZMMS8ZPHhwSUmJoigrV66sqKhQFGXdunUuLi5qb91DiMeOHRNCqFUpiuLj4xMZGakoSkJCQps2bQoKChRFee+99/r06aNu/oQJE9Q1P/roo/t6bgGLYA8MD5bz588fq6O8vLzB1aqrq3Nzc48ePSqEeP75552dneutsHnz5n79+nXo0EEIYWNjExYWtmXLFiHExYsXDQaDj4+PEMLDw8PBwUHdz1CNGjWqW7duH374oRBiyZIlev2//kC6du1qPponhGjTpo2Dg4Odnd1vf/vboqIiNzc3IcSYMWPUvKxXxt/+9rdhw4Y5OTkJIZycnEaPHq2W8R+99dZbXbt2ffHFF5OSkp577rm7V9DpdK+++urOnTvz8vLU7Ozdu3ebNm2EEAsXLrSzs1MrLywsbHC/sEH/+Mc/HnnkERcXFyHEgAEDkpOTy8vLq6urz5w5c+XKFSHE7373u584FNAEOKEWD5bJkyf/+te/Njejo6MbXO2JJ54ICwsbPnx4nz59fve7302dOrXeCunp6e7u7uZm+/bt1bM/AgICampqrl275uvre/PmzbKysoCAgAanOHz48I4dOxwcHNT37rvVPR9dp9OpaXd3GUOGDKlbhron9B/Z2tq+8847kyZN2rRp073WmT59+ltvvbVx48Y//OEPf/3rX1977TV1+fHjx6Oiolq3bp2dna3W9lNmFEJcv379ypUr06ZNE0JUVFT07t07Pz//1VdfPXjwYPfu3YcPH7548eLBgwf/xNEASyPAICVra+vo6Og//elP69evnz59usFgmDx5ct0V7O3ty8rKzM3KykpXV1edTte7d+8lS5aMGTPmscceu3Tp0sqVKx955JG7xz916tRvf/vblJSUTp06/eMf/zh+/Pj91Wlvb19VVWVuVlVVqXtsP4W6J6TuVDWoTZs2M2bMiIyMnDVrVm5ubo8ePYQQV65cefzxx8+ePdujR4+DBw9++umnP71aOzs7f3//qKioesvPnDlz7Nix9957b9iwYRcvXuzSpctPHxOwHA4hQkrnzp27c+eOv79/RETEiBEjTp06pS5XT5EQQgQGBtY9NpiamqruaVVUVBw/fjwhIWHt2rXx8fELFy5scPzTp0+7urp26tTpF9ZZr4xLly7da4fv/sydOzc7Ozs8PHz69OnqkjNnzlhbW3fv3t186uDdJxBaW1sLIUpKSuot9/f3T0lJqXfI8euvvxZCDB48eO/evfb29snJyY1YP/BLEGB4UFRUVJj/q6qpqTEajdXV1eav36qf3Aohzp49u3LlyqqqqvT09JSUlMcee0wI4efnl5iY+M0336Snp7/yyit37tzZvHmz0Wg8duzYnj173n//ffWzooSEhEmTJk2ePHnixIkzZ848cODA3e/13bp1y8zM3LRpU1xcnPrF6noF1Ht8d1O1cOHC8+fP79u3z2g07t279+zZs0uWLDFvXd2ds7upZwmq/70XX1/fp556KjU11Xx+oL+/f3l5+X//938nJCSop5aYyzP/18/Pz8bGZsmSJQcOHNi4caN66ocQYvbs2YWFhc8///xXX3117ty5uLg4IcSWLVv2799vMpkSExOrq6v79ev3n55JoIlYLV26VOsaAHHo0KHjx48PGTIkKyvLaDR27ty5sLBw9erV/v7+Xl5eiYmJgYGB69ev79mzZ1lZWW1tbVBQ0DfffLNt27YTJ07MnTv3N7/5jfrenZ6efvHixR49evj4+Dz//PMJCQlbt24tLy9/5513goKC1Hf8S5cudezY0dnZ2dHRMS0tbdmyZRMnTty1a1dISMjVq1ddXV09PDwefvhhb2/vxMREk8n04osv2tjYZGRklJWVFRUVubi4FBcX63S6o0ePDhw48MyZMwEBAREREcHBwYWFhV26dHF0dDRvl4uLy6RJk2JjY7dv324wGD744IPOnTsLIbZt22ZjY+Po6JiUlNSzZ09bW9t6v5DVq1dnZGQMGTIkIyMjJSWlf//+9/rV+fr69u7du0+fPmrT09PT39//5MmT5eXls2bNcnBwSE1N1ev1R48eHTx48JkzZ3x9fd3d3fv375+amlpYWBgaGvrwww/n5+d36tTJx8dn8uTJ6enpR48evX79emBgoLe3d9u2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)" + "![name](data:image/png;base64,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)" ] }, - "execution_count": 6, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import plot from \"../plot/mod.ts?5\";\n", + "import plot from \"../plot/mod.ts?6\";\n", "\n", - "plot.DrawHist(ys, 16, { title : \"Histogram of Y values\" });\n" + "plot.DrawPlot(\n", + " { \n", + " title: \"Test\", \n", + " //XLabel: \"X\", \n", + " YLabel: \"Y\", \n", + " width: 7.5, \n", + " height: 5 \n", + " }, \n", + " { type: \"scatter\", data: [xs, ys], legend: \"Data\", glyphStyleColor: \"#ff0000\" },\n", + " { type: \"line\", data: [xs, ys], legend: \"Line\", lineStyleColor: \"#00ff00\" },\n", + ");\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{ alpha: \u001b[33m-2.258539916346346\u001b[39m, beta: \u001b[33m-0.02428470043839821\u001b[39m }" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stats.LinearRegression(xs, ys, [], false);" ] } ], diff --git a/plot/main.go b/plot/main.go index 2276bb2..2568d22 100644 --- a/plot/main.go +++ b/plot/main.go @@ -12,6 +12,7 @@ import ( func InitPlotExports(this js.Value, args []js.Value) interface{} { exports := args[0] exports.Set("Hist", js.FuncOf(src.HistPlot)) + exports.Set("Plot", js.FuncOf(src.Plot)) return nil } diff --git a/plot/mod.wasm b/plot/mod.wasm index 27176c5..56f147f 100755 Binary files a/plot/mod.wasm and b/plot/mod.wasm differ diff --git a/plot/src/Plot.go b/plot/src/Plot.go new file mode 100644 index 0000000..0ec3d15 --- /dev/null +++ b/plot/src/Plot.go @@ -0,0 +1,208 @@ +//go:build js && wasm +// +build js,wasm + +package src + +import ( + "image/color" + "syscall/js" + + "github.com/gonum/stat" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/vg" + "gonum.org/v1/plot/vg/draw" +) + +func Plot(this js.Value, args []js.Value) interface{} { + plt := plot.New() + opts := args[0] + var ( + title = opts.Get("title").String() + XLabel = opts.Get("XLabel").String() + YLabel = opts.Get("YLabel").String() + width = 7.5 + height = 4.25 + ) + if !opts.Get("width").IsUndefined() { + width = opts.Get("width").Float() + } + if !opts.Get("height").IsUndefined() { + height = opts.Get("height").Float() + } + if opts.Get("title").IsUndefined() { + title = "Plot" + } + if opts.Get("XLabel").IsUndefined() { + XLabel = "X" + } + if opts.Get("YLabel").IsUndefined() { + YLabel = "Y" + } + + plt.Title.Text = title + plt.X.Label.Text = XLabel + plt.Y.Label.Text = YLabel + plt.Add(plotter.NewGrid()) + + lines := make([]plot.Plotter, 0) + for i, arg := range args { + if i == 0 { + continue + } + PlotterLinesFromJSObject(arg, plt, &lines) + } + plt.Add(lines...) + plt.Legend.Top = true + + writer, err := plt.WriterTo(vg.Length(width)*vg.Inch, vg.Length(height)*vg.Inch, "png") + if err != nil { + panic(err) + } + b64string := WriterToBase64String(writer) + return b64string +} + +func PlotterLinesFromJSObject(object js.Value, plt *plot.Plot, plotters *[]plot.Plotter) { + var ( + typ = object.Get("type").String() + data = object.Get("data") + legend = "" + glyphColor = object.Get("glyphColor") + glyphRadius = object.Get("glypRadius") + glyphShape = object.Get("glyphShape") + lineWidth = object.Get("lineWidth") + lineColor = object.Get("lineColor") + lineDashes = object.Get("lineDashes") + ) + + shapeGlyph := func(g *draw.GlyphStyle) { + if !glyphShape.IsUndefined() { + shape := glyphShape.String() + switch shape { + case "cross": + g.Shape = draw.CrossGlyph{} + case "plus": + g.Shape = draw.PlusGlyph{} + case "ring": + g.Shape = draw.RingGlyph{} + case "square": + g.Shape = draw.SquareGlyph{} + case "triangle": + g.Shape = draw.TriangleGlyph{} + case "pyramid": + g.Shape = draw.PyramidGlyph{} + } + } + } + + radiusGlyph := func(r *vg.Length) { + if !glyphRadius.IsUndefined() { + *r = vg.Points(glyphRadius.Float()) + } + } + + dashLine := func(l *[]vg.Length) { + if !lineDashes.IsUndefined() { + w := lineDashes.Index(0).Float() + h := lineDashes.Index(1).Float() + *l = []vg.Length{vg.Points(w), vg.Points(h)} + } + } + + applyColor := func(p *color.Color, hex js.Value) { + if !hex.IsUndefined() { + *p = HexToRGBA(hex.String()) + } + } + + if !object.Get("legend").IsUndefined() { + legend = object.Get("legend").String() + } + if data.IsUndefined() { + panic("data is undefined") + } + + XYs := XYFromJSObject(data) + if XYs == nil { + XYs = XYFromJSValues(data.Index(0), data.Index(1)) + } + + switch typ { + case "scatter": + s, err := plotter.NewScatter(XYs) + if err != nil { + panic(err) + } + applyColor(&s.GlyphStyle.Color, glyphColor) + shapeGlyph(&s.GlyphStyle) + radiusGlyph(&s.GlyphStyle.Radius) + *plotters = append(*plotters, s) + if legend != "" { + plt.Legend.Add(legend, s) + } + case "line": + l, err := plotter.NewLine(XYs) + if err != nil { + panic(err) + } + applyColor(&l.LineStyle.Color, lineColor) + dashLine(&l.LineStyle.Dashes) + if !lineWidth.IsUndefined() { + l.LineStyle.Width = vg.Points(lineWidth.Float()) + } + *plotters = append(*plotters, l) + if legend != "" { + plt.Legend.Add(legend, l) + } + case "linePoints": + l, lp, err := plotter.NewLinePoints(XYs) + if err != nil { + panic(err) + } + if !lineWidth.IsUndefined() { + l.LineStyle.Width = vg.Points(lineWidth.Float()) + } + applyColor(&l.LineStyle.Color, lineColor) + dashLine(&l.LineStyle.Dashes) + shapeGlyph(&lp.GlyphStyle) + applyColor(&lp.GlyphStyle.Color, glyphColor) + radiusGlyph(&lp.GlyphStyle.Radius) + *plotters = append(*plotters, l, lp) + if legend != "" { + plt.Legend.Add(legend, l, lp) + } + case "fitLinear": + X := make([]float64, len(XYs)) + Y := make([]float64, len(XYs)) + min := XYs[0].Y + max := XYs[0].Y + for i, xy := range XYs { + X[i] = xy.X + Y[i] = xy.Y + if xy.Y < min { + min = xy.Y + } + if xy.Y > max { + max = xy.Y + } + } + a, b := stat.LinearRegression(X, Y, nil, false) + l, err := plotter.NewLine(plotter.XYs{ + {X: X[0], Y: a + b*X[0]}, + {X: X[len(X)-1], Y: a + b*X[len(X)-1]}, + }) + if err != nil { + panic(err) + } + applyColor(&l.LineStyle.Color, lineColor) + dashLine(&l.LineStyle.Dashes) + if !lineWidth.IsUndefined() { + l.LineStyle.Width = vg.Points(lineWidth.Float()) + } + *plotters = append(*plotters, l) + if legend != "" { + plt.Legend.Add(legend, l) + } + } +} diff --git a/plot/src/utils.go b/plot/src/utils.go index bc24cb0..8d01e57 100644 --- a/plot/src/utils.go +++ b/plot/src/utils.go @@ -9,6 +9,9 @@ import ( "fmt" "image/color" "io" + "syscall/js" + + "gonum.org/v1/plot/plotter" ) func WriterToBase64String(writer io.WriterTo) string { @@ -36,3 +39,23 @@ func HexToRGBA(hex string) color.RGBA { } return c } + +func XYFromJSObject(object js.Value) plotter.XYs { + var ( + x = object.Get("x") + y = object.Get("y") + ) + if x.IsUndefined() || y.IsUndefined() { + return nil + } + return XYFromJSValues(x, y) +} + +func XYFromJSValues(x, y js.Value) plotter.XYs { + xy := make(plotter.XYs, x.Length()) + for i := range xy { + xy[i].X = x.Index(i).Float() + xy[i].Y = y.Index(i).Float() + } + return xy +} diff --git a/stat/mod.ts b/stat/mod.ts index 6e49a25..d4dcba6 100644 --- a/stat/mod.ts +++ b/stat/mod.ts @@ -1,4 +1,4 @@ -import "../lib/wasm.js"; +import "../lib/wasm_tinygo.js"; import type { Stat } from "./types.ts"; // @ts-expect-error: no types