u/Inst2f

Image 1 — Do you like flowers?
Image 2 — Do you like flowers?
▲ 23 r/wljs+2 crossposts

Do you like flowers?

A small MarkovJunior-style rewrite engine in vanilla (almost) Wolfram Language https://github.com/JerryI/MarkovJunior

Why WL? It is generally built around pattern matching; therefore, MarkovJunior can be implemented easily using native ReplaceAll, Rule, and Pattern symbols. Most of the code is used for building a friendly API and performing error checks.

For example random filling can be done using:

Black -> Red

For self-avoiding walk:

{a___, Red,Black,Black, b___} :> {a, White,Gray,Red, b}

For this particular example (flowers) it is written as a set of replacing rules, which gradually build soil/sky and then grows some flowers...

AppendTo[rules, {
1, 1, Automatic, {
(* seed the soil region *)
Black -> Yellow
}
}];

AppendTo[rules, {
1, 3, Automatic, {
(* seed several sky regions *)
Black -> Red
}
}];

AppendTo[rules, {
1, Infinity, Automatic, {
(* grow the sky and soil regions from their seeds *)
{a___, Red,Black, b___} :> {a, Red,Red, b},
{a___, Yellow,Black, b___} :> {a, Yellow,Yellow, b}
}
}];

AppendTo[rules, {
All, Infinity, Automatic, {
(* convert temporary region colors into sky and soil *)
{a___, Red, b___} :> {a, LightBlue, b},
{a___, Yellow, b___} :> {a, Brown, b}
}
}];

AppendTo[rules, {
1, Infinity, All, {
(* plant the first stem segment along the soil line *)
{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, Brown,Brown,Brown, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , Brown,Brown,Brown, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];

AppendTo[rules, {
1, Infinity, "MirrorX", {
(* grow stems and leaves with mirrored variants *)
(* weight it with some probabillity as well *)
{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,Green, b2___},
{a3___, LightBlue,LightBlue,LightBlue, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,Green, b2 },
{a3 , LightBlue,LightBlue,LightBlue, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,Green, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , LightBlue,Green,Green, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a0___, LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,LightBlue,LightBlue, b0 },
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}]==Length[{a0}],

{
bf___,
{a0___, LightBlue,LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,Green,LightBlue,LightBlue, b1___},
{a2___, LightBlue,Green,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,LightBlue,LightBlue,LightBlue, b0 },
{a1 , LightBlue,LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,Green,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue,LightBlue, b3 },
af
} /; RandomReal[]<0.5 && Length[{a0}]==Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Red,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; RandomReal[]<0.2 && Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];

AppendTo[rules, {
All, Infinity, All, {
(* turn mature stems into blossoms *)
{
bf___,
{a0___, LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,Red,LightBlue, b1___},
{a2___, LightBlue,Green,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,Red,LightBlue, b0 },
{a1 , Red,Yellow,Red, b1 },
{a2 , LightBlue,Red,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; Length[{a0}]==Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];

u/Inst2f — 2 days ago
▲ 26 r/u_Inst2f+3 crossposts

Rewrite rules automaton

This idea is solely based on an amazing project MarkovJunior, which is essentially probabilistic pattern matching machine. I though, "ha. This must be the best fit for Wolfram Language!".

Indeed, no tricks were used, except mirroring and rotating the "canvas" to generalize 1D rules into 2D, the rest is purely default pattern matching of the language:

r[{before___, {a___, (RGBColor[1, 0, 0]),(GrayLevel[0]),(GrayLevel[0]), b___}, after___}] := 
  {before, {a, (RGBColor[0, 0, 1]),(RGBColor[0, 0, 1]),(RGBColor[1, 0, 0]), b}, after} /; (RandomReal[]&lt;=0.5);

r[{before___, {a___, (RGBColor[1, 0, 0]),n_,(RGBColor[0, 0, 1]), b___}, after___}] := 
  {before, {a, (RGBColor[0, 0, 1]),n,(RGBColor[1, 0, 0]), b}, after} /; (RandomReal[]&lt;=0.5);

r[any_] := any 

field = Table[(GrayLevel[0]), {30}, {30}];
field[[RandomInteger[{1,30}],RandomInteger[{1,30}]]] = (RGBColor[1, 0, 0]);

Refresh[ArrayPlot[field = applyInAllSymmetries[field]], 0.04]

where

rot[0][m_] := m;
rot[1][m_] := Transpose[Reverse[m]];
rot[2][m_] := Reverse[Reverse /@ m];
rot[3][m_] := Reverse[Transpose[m]];

mirror[m_] := Reverse /@ m;  (* left-right mirror *)

symmetries = Join[
   Table[rot[k], {k, 0, 3}],
   Table[rot[k] @* mirror, {k, 0, 3}]
];

inverseSymmetries = Join[
   Table[rot[Mod[-k, 4]], {k, 0, 3}],
   Table[mirror @* rot[Mod[-k, 4]], {k, 0, 3}]
];

applyInAllSymmetries[m_] :=
  Fold[
    #2[[2]][r[#2[[1]][#1]]] &amp;,
    m,
    Transpose[{symmetries, inverseSymmetries}]
  ];
u/Inst2f — 2 days ago
▲ 3 r/wljs

Singe line dynamic 3D plot

One of my favorite 1-line(er). Behind the scenes: Manipulate internally checks differences between two nearest states of Plot3D, then extracts changed vertices, indices and normals into 3 dynamic typed arrays. For all subsequent changes it syncs new data with 3 corresponding buffers of a GPU memory. If "too much" was changed it falls back to a full reevaluation, when all buffers are removed and are allocated back.

Manipulate[
  Plot3D[Sin[n x] Cos[n y], {x,-1,1}, {y,-1,1}], 
  {n, 1, 5, 0.3}, ContinuousAction-&gt;True
]
u/Inst2f — 5 days ago
▲ 3 r/wljs

Clouds generator using Gaussian noise

This is a 2D Gaussian random field with a 1/k^2 spectrum and linear dispersion ω∝k. We clip the field to positive values and square root it to give an edge to the "clouds":

n = 256;
k2 = Outer[Plus, #, #] &amp;[RotateRight[N@Range[-n, n - 1, 2]/n, n/2]^2];

spectrum = With[{d := RandomReal[NormalDistribution[], {n, n}]},
   (1/n) (d + I d)/(0.000001 + k2)]; 
spectrum[[1, 1]] *= 0;

im[p_] := Clip[Re[InverseFourier[spectrum Exp[I p]]], {0, ∞}]^0.5

p0 = p = Sqrt[k2];

buffer = im[p0 += p];

Image[buffer // Offload, "Real32", Epilog-&gt;{
    EventHandler[AnimationFrameListener[buffer // Offload], 
      Function[Null, buffer = im[p0 += 2 p]]
    ]
}]
u/Inst2f — 5 days ago
▲ 2 r/wljs

Rosetta - a beautiful spirograph

Spirograph-like curves arise from simple sums of rotating vectors; a tiny tweak in frequency or phase yields striking patterns. Here is my favorite example Rosetta:

Animate[ParametricPlot[{
  Power[I,-((20t)/(tt))]+3 Power[I,((20t)/(tt))]+Power[I,((20t)/(tt))]Sin[8 Pi ((20t)/(tt))/5],
  Power[I,-t]+3 Power[I,t],
  Power[I,-t]+3 Power[I,t]+Power[I,t]Sin[8 Pi t/5]
}//ReIm//Evaluate, {t,0,tt}, 
  PlotRange -&gt; {-5,5}, PlotPoints -&gt; 200,
  PlotStyle -&gt; {LightGray,Default,(Hue[0.353, 0.78, 0.49])}, Axes-&gt;False,
  Epilog -&gt; {
    {Thick,Red,Line[{ReIm[Power[I,-tt]+3 Power[I,tt]-Power[I,tt]],ReIm[Power[I,-tt]+3 Power[I,tt]+Power[I,tt]]}]}, {Thick,Circle[ReIm[Power[I,-tt]+3 Power[I,tt]+Power[I,tt]Sin[8 Pi tt/5]],0.1]}
  }, PlotPoints -&gt; 10
],{{tt,19.9},0.01,4 5, 0.1}, Appearance -&gt; None]
u/Inst2f — 5 days ago
▲ 1 r/wljs

Path-tracing renderer as a backend for 3D plots

Here is an example with Plot3D

Plot3D[Sin[x] Cos[y], {x,-10,10}, {y,-10,10}][[1]];
Graphics3D[{%, Graphics3D`Materials["Glass"], Red, Sphere[{0,0,2}, 4]}, "Renderer"-&gt;"PathTracing", Axes-&gt;True]
u/Inst2f — 5 days ago
▲ 1 r/wljs

WLJS 3.0.5 is out 🪴

This is the largest update for the last 2 years

Human-, LLM- and Git-friendly .wln format

This release introduces a new minimal .wln notebook format designed to be readable by humans, easy for LLMs to parse, and much friendlier to Git diffs. It uses simple YAML-like headers, while cell contents remain valid Wolfram Language expressions.

Older .wln notebooks remain fully supported.

  • Hot-reloading when notebooks are modified outside WLJS Notebook
  • Built-in AI Copilot removed in favor of external tools
  • New MCP server for Claude, Codex, and other coding agents
  • Updated wljs CLI
  • “Ask community” helper for creating GitHub Discussions posts
  • New InputColor UI element
  • HTMLView support for native image embedding
  • TeXView live updates and ImageSize option
  • Improved project-to-window behavior with copied HTML / JS outputs
  • Image3D color support and Offload updates
  • Added missing size argument to Inset
  • Kernel connection stability improvements via WTSP + shared memory

See more
https://wljs.io/releases/3.0.5

reddit.com
u/Inst2f — 6 days ago
▲ 2 r/wljs

I tried to do some motion design with WLJS

I recently started designing a visual explanation of `Image` object in Wolfram and how to animate with it. If it works out with writing script and overall idea, I will publish a video on Youtube.

The animation is recorded in real-time and is composed from async functions of WLJS standard library (similar to Manim). The pipeline is still a bit rough and needs polishing, but we are getting there...

u/Inst2f — 11 days ago
▲ 3 r/wljs+1 crossposts

Animating Raster Images in Notebooks Has Never Been Easier

No JSON. No Base64. Just raw RGBA data streamed directly from the computational kernel to the GPU.

In WLJS, reassigning new pixel data to a symbol is enough to update the raster image.

u/Inst2f — 12 days ago
▲ 1 r/wljs

WLJS is notebook interface (or IDE) combines live code in Wolfram, JavaScript, and other languages. We provide GUI building blocks for user input/output, a subset of LaTeX for equations, Markdown for narrative text, and data-driven presentations.

Think of it as a multi-tool platform for research, experiments, or as a powerful sandbox where you can try out your ideas, write a story about them, and then publish them on the web.

As an independent open-source project, we're unaffiliated with Wolfram or any company.

Please feel free to share your work with the community and post questions. This helps project to be alive.

reddit.com
u/Inst2f — 18 days ago
▲ 1 r/wljs

-  Built-in AI Copilot is retiring
-  MCP Server
-  CLI - interact with notebooks from the terminal, LLM-friendly
-  New `.wln` format - human-readable and git-diff-friendly (and unicode friendly!)
-  Hot-reloading - edits made outside the app sync back
-  `InputColor` element - new UI input in the standard library
-  `TeXView` upgrades - live updates support
-  "Ask Community" command - auto-posts your cell to GitHub Discussions

reddit.com
u/Inst2f — 19 days ago
▲ 10 r/wljs+1 crossposts

size = 0.7;
molecules = 500;
history = Table[{-50 + i, 0.0}, {i, 0, 50}];
temperature = 0.05`;
avgs = 0;
theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*);

EventHandler[
  InputRange[0.01,0.1,0.01,0.05, "Label"-&gt;"T"], 
  Function[s, temperature=s; theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*)]
]
EventHandler[
  InputRange[0.4,2.0,0.1,size, "Label"-&gt;"Size"], 
  Function[s, size=s; theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*)]
]

Row[{Module[{
  contents = {
    RandomReal[{-size,size},{molecules,2}],
    {Cos[#1],Sin[#1]}&amp; /@ RandomReal[{0,2 \[Pi]}, molecules], 
    Table[{0.5,0.5,1.}, {molecules}]
  } // Transpose, 
  data = {Table[{0,0,0}, {molecules}], Table[{0,0,0}, {molecules}]}//N, 
  indices = Range[molecules], collision = 0
},
  
    
    Graphics[
        {
            {EdgeForm[Black], GrayLevel[0.8], Rectangle[{-size, -size}//Offload, {size, size}//Offload]},
            GraphicsComplex[Offload[data[[1]]], {
                PointSize[0.01], Point[Offload[indices]]
              }, VertexColors-&gt;Offload[data[[2]]]
            ],
            EventHandler[
                AnimationFrameListener[Offload[data]],
                Function[Null,
                    
                    
                    collision = 0;
                    contents = ({#1[[1]] + #1[[2]] temperature, #1[[2]], 0.1 {0.5,1.0,1.0} + 0.90 #1[[3]]}&amp;) /@ contents;
                    contents = (
                        If[Abs[#1[[1, 2]]] &gt; size,
                            collision++;
                            {{#1[[1, 1]], 2 size Sign[#1[[1, 2]]] - #1[[1, 2]]}, {1, -1} #1[[2]], {1.,0.,1.}}
                            ,
                            #1
                        ]&amp;
                    ) /@ contents;
                    
                    contents = (
                        If[Abs[#1[[1, 1]]] &gt; size,
                            collision++;
                            {{2 size Sign[#1[[1, 1]]] - #1[[1, 1]], #1[[1, 2]]}, {-1, 1} #1[[2]], {1.,0.,1.}}
                            ,
                            #1
                        ]&amp;
                    ) /@ contents;
                    
                    data = {First /@ contents, Last /@ contents};

                    history[[1,2]] += collision/size;
                    
                    If[avgs &gt; 20.0,  
                      avgs=0;
                      history[[1,2]] /= 20.0;
                      history = Transpose[{history[[All,1]], RotateLeft[history[[All,2]], 1]}];
                    ];

                    avgs++;
                ]
            ]
        }, PlotRange-&gt;{{-1,1}, {-1,1}}
    ]
], Graphics[{Line[history//Offload], Red, Dashed, Line[{{-50, theory}, {0, theory}}//Offload]}, PlotRange-&gt;{{-50,0}, {0,100.0}}, TransitionType-&gt;None, ImageSize-&gt;300,Frame-&gt;True, FrameLabel-&gt;{"time", "P"}, "Controls"-&gt;False]}]
u/Inst2f — 22 days ago
▲ 2 r/wljs

Here is a code for this little demo:

size = 1.`;
number = 500;
fps = 0.0;
time = AbsoluteTime[];

TextView[fps//Offload, "Label"-&gt;"FPS"]

Module[{
  contents = (*BB[*)(Transpose[{RandomReal[{-size,size},{number,2}],({Cos[#1],Sin[#1]}&amp;)/@RandomReal[{0,2 \[Pi]},number], Table[{0.5,0.5,1.}, {number}]}])(*,*)(*"1:eJxTTMoPSmNmYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCRYg4ZGfk5LGBOLxAomwzNRyl9Tk/KLEkvyiYE6gSEhRYl5xQX5xajBISwhEKUhjUGlOajDYhNTEFFSlaIpYgQzXstS8ErCQX2lODgB64iTl"*)(*]BB*), 
  data = {Table[{0,0,0}, {number}],Table[{0,0,0}, {number}]}//N, 
  indices = Range[number], temperature = 0.05`, collision = 0
},
  
    
    Graphics[
        {
            GraphicsComplex[Offload[data[[1]]], {PointSize[0.01], Point[Offload[indices]]}, VertexColors-&gt;Offload[data[[2]]]]
            ,
            EventHandler[
                AnimationFrameListener[Offload[data]]
                ,
                Function[Null,
                    
                    
                    collision = 0;
                    contents = ({#1[[1]] + #1[[2]] temperature, #1[[2]], 0.1 {0.5,0.5,1.0} + 0.90 #1[[3]]}&amp;) /@ contents;
                    contents = (
                        If[Abs[#1[[1, 2]]] &gt; size,
                            {{#1[[1, 1]], 2 size Sign[#1[[1, 2]]] - #1[[1, 2]]}, {1, -1} #1[[2]], {1.,0.,0.}}
                            ,
                            #1
                        ]&amp;
                    ) /@ contents;
                    
                    contents = (
                        If[Abs[#1[[1, 1]]] &gt; size,
                            {{2 size Sign[#1[[1, 1]]] - #1[[1, 1]], #1[[1, 2]]}, {-1, 1} #1[[2]], {1.,0.,0.}}
                            ,
                            #1
                        ]&amp;
                    ) /@ contents;
                    
                    data = {First /@ contents, Last /@ contents};
                    
                    With[{now = AbsoluteTime[]},
                      If[Random[]&lt;0.3, fps = Round[fps 0.6 + 0.4/(now-time)]];
                      time = now;
                    ];
                ]
            ]
        }, PlotRange-&gt;{{-size,size}, {-size,size}}
    ]
]
u/Inst2f — 23 days ago
▲ 1 r/wljs

Ever wondered what happens when you push thousands of vertices into a graphics engine? GraphicsComplex can write directly into GPU buffers with no overhead. Let's see how far we can take it.

wljs.io
u/Inst2f — 29 days ago
▲ 5 r/wljs

A real-time animation based on the beautiful work of Simon Woods with a few adjustments

Basically we have a few rules for each point to follow:

  • it moves 0.5% toward the centre,
  • it takes a large step toward selected "friend", and a smaller step away from its "enemy".

At random times, one point picks a new "friend" and "enemy" points. Therese two are just indices. Color coding represents the speed.

Implementation is more or less described in the original post, I only optimized it for real-time animation using GraphicsComplex primitives, fixed size vertex buffer and added colors.

u/Inst2f — 29 days ago

For beginners: how to code a basic FDTD and add frequency-dependent permittivity

In this post, we attempt to solve Maxwell's equations for a 1D case with two interfaces. This work is based on John B. Schneider's Understanding the Finite-Difference Time-Domain Method, 2023.

I've never tried it in my life as a physicist, it is especially fun to add P, M (material equations), since it forces you to think in time-domain instead of frequency.

Since graphs and widgets are not easy to attach in reddit, here is a link to the full post: https://wljs.io/blog/fdtd

u/Inst2f — 3 months ago