Skip to main content

Release notes *2.5.9*

· 4 min read

It contains the major improvements for NeuralNet standard package, provides more features for graphics and insets. We also fixed many bugs in wljs-export-html and in WXF deserializer. New examples are available in Animation folder.

Download original notebook

const balloonContainer = document.getElementById("balloon-container");

function random(num) {
  return Math.floor(Math.random() * num);
}

function getRandomStyles() {
  var r = random(255);
  var g = random(255);
  var b = random(255);
  var mt = random(200);
  var ml = random(50);
  var dur = random(5) + 5;
  return `
  background-color: rgba(${r},${g},${b},0.7);
  color: rgba(${r},${g},${b},0.7); 
  box-shadow: inset -7px -3px 10px rgba(${r - 10},${g - 10},${b - 10},0.7);
  margin: ${mt}px 0 0 ${ml}px;
  animation: float ${dur}s ease-in infinite
  `;
}

function createBalloons(num) {
  for (var i = num; i > 0; i--) {
    var balloon = document.createElement("div");
    balloon.className = "balloon";
    balloon.style.cssText = getRandomStyles();
    balloonContainer.append(balloon);
  }
}

function removeBalloons() {
  balloonContainer.style.opacity = 0;
  setTimeout(() => {
    balloonContainer.remove()
  }, 500)
}

createBalloons(10);
setTimeout(removeBalloons, 15000);

return '';

Inset

An update for Inset expression

Now you can put any expression on top of your Graphics object. Please, make sure this expression supports WLJS Execution Enveroment (see top line of reference )

For example

Plot[x, {x,0,10}, Epilog->{Inset[EditorView["(*FB[*)((1)(*,*)/(*,*)(2))(*]FB*)"], {3,5}, {10,30}, {1,3}]}]
(*VB[*)(FrontEndRef["3ca22e97-4a4d-4068-b58a-dc793fdfd51b"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKGycnGhmlWprrmiSapOiaGJhZ6CaZWiTqpiSbWxqnpaSlmBomAQCF1hYI"*)(*]VB*)

Or even put a mermaid diagram using virtual cells

mermaid = CellView["graph LR
    A[Square Rect] -- Link text --> B((Circle))
    A --> C(Round Rect)
    B --> D{Rhombus}
    C --> D", "Display"->"mermaid"];
Plot[x, {x,0,10}, Epilog->{Inset[mermaid, {2,5}, {10,30}, {7,4}]}]
(*VB[*)(FrontEndRef["a0bb8b0e-c9e3-4c62-8ce0-b72f9844cf6f"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJxokJVkkGaTqJlumGuuaJJsZ6VokpxroJpkbpVlamJgkp5mlAQCR6BY5"*)(*]VB*)

Slides now supports scripts

All inline JS scripts provided in slide cells will be executed. Use them for whatever ideas you come up with.

Tube now supports dynamics

3D graphics primitive Tube now can be coupled to a dynamic symbol, as an example check this out 😉

(*BB[*)(* Just run this cell *)(*,*)(*"1:eJxTTMoPSmNhYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCS4g4Zyfm5uaV+KUXxEMUqxsbm6exgSSBPGCSnNSg9mAjOCSosy8dLBYSFFpKpoKkDkeqYkpEFXBILO1sCgJSczMQVYCAOFrJEU="*)(*]BB*)
RandomIntegerVectorWithinBox[min_List, max_List] := Table[
  RandomInteger[{min[[i]], max[[i]]}],
  {i, Length[min]}
]

PositionKey[pos_] := ToString[pos]

WithinBoundsQ[pos_, gridMin_, gridMax_] := And @@ Thread[pos >= gridMin] && And @@ Thread[pos <= gridMax]

IsUnoccupied[pos_, occupiedPositions_] := ! KeyExistsQ[occupiedPositions, PositionKey[pos]]

(* Main function to simulate a pipe *)
SimulatePipe[] := Module[
  {
    gridMin = {-10, -10, -10},
    gridMax = {10, 10, 10},
    occupiedPositions = <||>,
    currentPosition,
    positions,
    lastPosition,
    lastDirectionVector = Null,
    directionVector,
    newPosition,
    axis,
    dir,
    possibleDirections,
    triedDirections,
    moveMade
  },
  
  (* Initialize the starting position *)
  currentPosition = RandomIntegerVectorWithinBox[gridMin, gridMax];
  positions = {currentPosition};
  occupiedPositions[PositionKey[currentPosition]] = True;
  
  (* Simulate the pipe growth *)
  Function[Null,
    
    (* Initialize possible directions *)
    possibleDirections = {
      {1, 0, 0}, {-1, 0, 0},
      {0, 1, 0}, {0, -1, 0},
      {0, 0, 1}, {0, 0, -1}
    };
    
    (* Prioritize continuing in the same direction *)
    If[lastDirectionVector =!= Null && RandomReal[] < 0.5,
      (* Try to continue in the same direction *)
      directionVector = lastDirectionVector;
      possibleDirections = Prepend[DeleteCases[possibleDirections, directionVector], directionVector];,
      (* Shuffle possible directions *)
      possibleDirections = RandomSample[possibleDirections];
    ];
    
    triedDirections = {};
    moveMade = False;
    (* Try each possible direction *)
    Do[
      directionVector = dir;
      newPosition = currentPosition + directionVector;
      If[
        WithinBoundsQ[newPosition, gridMin, gridMax] && IsUnoccupied[newPosition, occupiedPositions],
        (* Valid move found *)
        positions = Append[positions, newPosition];
        occupiedPositions[PositionKey[newPosition]] = True;
        lastDirectionVector = directionVector;
        currentPosition = newPosition;
        moveMade = True;
        Break[];
      ];
      AppendTo[triedDirections, dir];
      ,
      {dir, possibleDirections}
    ];
    
    If[!moveMade,
      (* No valid moves, terminate simulation *)
      $Failed
    ,
      positions
    ]

    
  ]
  
]


With[{
  frame = CreateUUID[],
  win = CurrentWindow[]
},
  Module[{
    pipeFunction = Function[Null, $Failed],
    pipesNumber = 0,
    trigger = 1
  },

    EventHandler[frame, Function[Null,
      With[{
        result = pipeFunction[]
      },
        If[FailureQ[result],
          With[{
            segments = Unique["pipe"],
            generator = SimulatePipe[]
          },
            pipesNumber++;
            pipeFunction = Function[Null,
              With[{seg = generator[]}, 
                If[FailureQ[seg],
                  $Failed
                ,
                  segments = seg // N;
                ]
              ]
            ];

            pipeFunction[];

            FrontSubmit[{
              ColorData[97][pipesNumber],
              Tube[segments // Offload, 0.2]
            }, MetaMarker[marker], "Window"->win];
          ]
        ]
      ];

      trigger++;
    ]];
    

    Graphics3D[{
      Opacity[0], Cuboid[{-4,-4,-4}, {4,4,4}], Opacity[1], MetaMarker[marker],
      AnimationFrameListener[trigger // Offload, "Event"->frame]
    }]
  ]
]

Neural Networks

We have finally added partial support for NeuralNet package. You can see training progress, representations of different layers and etc

(*BB[*)(* try this one *)(*,*)(*"1:eJxTTMoPSmNhYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCS4g4Zyfm5uaV+KUXxEMUqxsbm6exgSSBPGCSnNSg9mAjOCSosy8dLBYSFFpKpoKkDkeqYkpEFXBILO1sCgJSczMQVYCAOFrJEU="*)(*]BB*)
trained = 
 NetTrain[LinearLayer[], {1 -> 1.9, 2 -> 4.1, 3 -> 6.0, 4 -> 8.1}]
trained[3]
6.04994535446167`

NetGraph is not supported as well as some icons. We need volunteers to work on it ;) Please contact us if you know something about ML and Wolfram Language Graphics.

net = NetModel["LeNet Trained on MNIST Data"]
(*VB[*)temporalStorage$145507(*,*)(*"1:eJwlkc1ymlAAhWmni06foslKoTNC0AvpTBb8KgISufyImSxALoLgRZErwmP0iWPSzTdnzu585yGp3ew7RVGXX3doadHWTVCgDv77RlEr1Cp5XOC3ER3Ib/T494j+Q49H9CP3Fy17rvQ566ZJdk6um7WriUoLxCQik3UiN2Ta6FZ13RZd4XhW7QwKhB5GfPrKX71DyxiZX6BFiWcaRrmNT5rImwKUjHNhYx/EVVmogw4uxpk3sdSnTlSd8c1JbvsK76Wj6857Z7pDVQ+APdv6ZlIvu6ZtNusF6QCBRsswSqhZAjzG58uC58VkZwqi4Os2hzrzGu3mg2jlicB2WllUcENAUg1zNvQYdWo+8VubKG6aghbXe51Z+GHiuRAxcbpayblEOCNQHe1UBvF0rlmT7el2jiBrH4+Ruc6k7HblUajLp0OQC7PVQV0aM2UC7tPDmMuP5kRhVWNZZumzUwrNRc+a5wS4kzBXeqDrd0mS8loP04jHrck+7V9eHj+dvwcyPX7/f9WPO1xSIfjzM6A4dXDVf7VeQ9AH8nGRcw=="*)(*]VB*)
net[(*VB[*)(FrontEndRef["7c52eb9d-6d46-4b1d-ab0a-a2043d2ccccc"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKmyebGqUmWabomqWYmOmaJBmm6CYmGSTqJhoZmBinGCWDAACODxZ6"*)(*]VB*)]
5

ok, kinda looks like 5

Some other examples

layer = NetInitialize @ LinearLayer[2, "Input" -> 2]
LinearLayer[(*VB[*) <|"Type" -> "Linear", "Arrays" -> <|"Weights" -> NumericArray[{{-0.3594474792480469, -0.04992305114865303}, {-1.127055048942566, 1.086535930633545}}, "Real32"], "Biases" -> NumericArray[{0., 0.}, "Real32"]|>, "Parameters" -> <|"OutputDimensions" -> {2}, "$OutputSize" -> 2, "$InputSize" -> 2, "$InputDimensions" -> {2}|>, "Inputs" -> <|"Input" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`AtomT]|>, "Outputs" -> <|"Output" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]|>|>, <|"Version" -> "14.1.2", "Unstable" -> False|> (*,*)(*"1:eJytUMsKwjAQrI+LXgQ9CJ7qL3j0ptBiQSy00rORbCWQbGSboEX8d9NUqVfBy7A7M8sMuzzrrBwEQVAtHGz1PdakThsihhfguVWKUe3ostd4Jg5i0mgi5IUgY5lshaGDnZbcDweNUPY/9F5UpjP5zWvzr7x3TmJAFQJu+cxpqTVXa0IuFGAlNFbrsD0cO4i4MJq8tyn/WD27wMxKyEfNAIzXKcra00ey8GuPqdMS/HuN9ktWyhcQzmJg"*)(*]VB*)]
NetExtract[LinearLayer[(*VB[*) <|"Type" -> "Linear", "Arrays" -> <|"Weights" -> NumericArray[{{-0.3594474792480469, -0.04992305114865303}, {-1.127055048942566, 1.086535930633545}}, "Real32"], "Biases" -> NumericArray[{0., 0.}, "Real32"]|>, "Parameters" -> <|"OutputDimensions" -> {2}, "$OutputSize" -> 2, "$InputSize" -> 2, "$InputDimensions" -> {2}|>, "Inputs" -> <|"Input" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`AtomT]|>, "Outputs" -> <|"Output" -> NeuralNetworks`TensorT[{2}, NeuralNetworks`RealT]|>|>, <|"Version" -> "14.1.2", "Unstable" -> False|> (*,*)(*"1:eJytUMsKwjAQrI+LXgQ9CJ7qL3j0ptBiQSy00rORbCWQbGSboEX8d9NUqVfBy7A7M8sMuzzrrBwEQVAtHGz1PdakThsihhfguVWKUe3ostd4Jg5i0mgi5IUgY5lshaGDnZbcDweNUPY/9F5UpjP5zWvzr7x3TmJAFQJu+cxpqTVXa0IuFGAlNFbrsD0cO4i4MJq8tyn/WD27wMxKyEfNAIzXKcra00ey8GuPqdMS/HuN9ktWyhcQzmJg"*)(*]VB*)], "Weights"] // Normal
{{-0.3594474792480469`,-0.04992305114865303`},{-1.127055048942566`,1.086535930633545`}}

Support for custom CSS

Open your settings and add any styles you want. This is a new step towards customization

Try this one

Print[Style["Hey", Red, 14]]
(*BB[*)("Hey")(*,*)(*"1:eJxTTMoPSmNiYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCRYg4ZGfkwJRxgkkgkuKMvPSnfIr0phBQhxAIsjdyTk/J78oE6QlkwFO8AEJiEaQMUGlOanBbHATwGIhRaWpAL9wHBA="*)(*]BB*)

You can also print Graphics if needed

Offset support for labels

It was always a bit of a pain to fight agains FrameLabel or AxesLabel and trying to position them. We extended the API for this (Mathematica does not have this feature)

Plot[PDF[NormalDistribution[0, 1], x], {x, -10, 10}, AxesLabel -> {
  {"wavenumber (cm^{-1})", {-100,-15}}, 
  {"absorption \\alpha", {112,0}}
}, PlotRange->Full]
(*VB[*)(FrontEndRef["257a6bab-bb74-4016-b624-a40b453a2e63"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKG5maJ5olJSbpJiWZm+iaGBia6SaZGZnoJpoYJJmYGicapZoZAwCDIRVZ"*)(*]VB*)

Support for Entity and Quantity

We recreated boxes for them

Quantity[1, "Millimeters"/"Seconds"]
(*VB[*)(q)(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB43kAgsTcwrySypdMqvyAQpgciwAomQzNzU4mCQGt/MnBwgpyS1qBghHZBfnloUzA5kBacm5+elFGf+BwIA5ecbxA=="*)(*]VB*)
Entity["Country", "Germany"]
(*VB[*)(Entity["Country", "Germany"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB4nkHDNK8ksqXTKrwhmB/Kc80vzSooqwWz31KLcxLxKAJLGDq8="*)(*]VB*)
%["Population"]
(*VB[*)(q)(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB43kAgsTcwrySypdMqvyFzA950lmA0oGJCaX5CTCgBVHw3o"*)(*]VB*)

Support for SystemOpen

Works only if use our desktop application (not a console version)

SystemOpen[NotebookDirectory[]]

Better Audio support

We also added a new snippet in the command palette

Record Voice

(*VB[*)(Notebook`Editor`Kernel`PCMAudio`Internal`dump$112924)(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKmyamJKUkmZnpJhoYJuqamKWY6CYmmVvqmpoYJZoYWBoaGpsmAwCODRWP"*)(*]VB*) // AudioPlot
(*VB[*)(FrontEndRef["fc127432-1b30-420d-b760-f91b0846329e"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKpyUbGpmbGBvpGiYZG+iaGBmk6CaZmxnoplkaJhlYmJgZG1mmAgB2gxTV"*)(*]VB*)

External API

We know, that normally libraries for Wolfram Language are distributed as WL Packages or paclets, which do not have support for shipping Javascript / CSS files and etc.

Now it is possible to inject them in a runtime, you have to do it only once

FrontEndRuntime[{"Modules", "js"}] = Append[FrontEndRuntime[{"Modules", "js"}], File["path to your JS"]] 

See docs for more information

To check if a code is running with WLJS frontend, you can check this system variable

Internal`Kernel`WLJSQ
True

Ballon animation by Jemima (codepen)