<!-- Thank you for contributing to Pyodide! All improvements are welcome,
     so don't be afraid to make a PR. -->

<!-- [IMPORTANT] Note on CI failures:
     Currently, we are having issues with selenium-based tests.
     Don't panic if the CI fails on your PR because of timeouts.
     It's probably not your fault. We will investigate :) -->

### Description

<!-- Please explain what your PR is about:
     - reasoning for the change
     - some details of updated code
     - any noteworthy choices to be aware of
	Please refer to any related issues by #<issue_id> -->

Bumping MPL version - it turns out that Hist (which uses boost-histogram) depends on mplhep, which in turn requires matplotlib 3.4+. So I migrated the patches and bumped MPL.

I noticed micropip doesn't seem to respect extras, that is, `await micropip.install("hist[plot]")` doesn't seem to work. (will investigate later)

* Updated matplotlib to 3.5
    * Added fonttools
* Updated yt to 4
    * Added `cmyt` and `unyt`, which I am pretty sure are yt specific. At least by looking at the name. 😆 
    * Also `colorspacious`
    * Also `tdqm`
    * Also `tomli` and `tomli-w` (backported from the next yt release to avoid adding a dead dependency `toml`)

Closes #2088 too. Also 3.5 was the first version to officially support 3.10, I think.
chore: matplotlib 3.5.1, yt 4. <!-- Thank you for contributing to Pyodide! All improvements are welcome,
     so don't be afraid to make a PR. -->

<!-- [IMPORTANT] Note on CI failures:
     Currently, we are having issues with selenium-based tests.
     Don't panic if the CI fails on your PR because of timeouts.
     It's probably not your fault. We will investigate :) -->

### Description

<!-- Please explain what your PR is about:
     - reasoning for the change
     - some details of updated code
     - any noteworthy choices to be aware of
	Please refer to any related issues by #<issue_id> -->

Bumping MPL version - it turns out that Hist (which uses boost-histogram) depends on mplhep, which in turn requires matplotlib 3.4+. So I migrated the patches and bumped MPL.

I noticed micropip doesn't seem to respect extras, that is, `await micropip.install("hist[plot]")` doesn't seem to work. (will investigate later)

* Updated matplotlib to 3.5
    * Added fonttools
* Updated yt to 4
    * Added `cmyt` and `unyt`, which I am pretty sure are yt specific. At least by looking at the name. 😆 
    * Also `colorspacious`
    * Also `tdqm`
    * Also `tomli` and `tomli-w` (backported from the next yt release to avoid adding a dead dependency `toml`)

Closes #2088 too. Also 3.5 was the first version to officially support 3.10, I think.
# setup: N=10
# run: julia(1., 1., N, 1.5, 10., 1e4)

# pythran export julia(float, float, int, float, float, float)
import numpy as np


def kernel(zr, zi, cr, ci, lim, cutoff):
    """Computes the number of iterations `n` such that
    |z_n| > `lim`, where `z_n = z_{n-1}**2 + c`.
    """
    count = 0
    while ((zr * zr + zi * zi) < (lim * lim)) and count < cutoff:
        zr, zi = zr * zr - zi * zi + cr, 2 * zr * zi + ci
        count += 1
    return count


def julia(cr, ci, N, bound=1.5, lim=1000.0, cutoff=1e6):
    """Pure Python calculation of the Julia set for a given `c`.  No NumPy
    array operations are used.
    """
    julia = np.empty((N, N), np.uint32)
    grid_x = np.linspace(-bound, bound, N)
    for i, x in enumerate(grid_x):
        for j, y in enumerate(grid_x):
            julia[i, j] = kernel(x, y, cr, ci, lim, cutoff)
    return julia

# setup: N=10
# run: julia(1., 1., N, 1.5, 10., 1e4)

# pythran export julia(float, float, int, float, float, float)
import numpy as np


def kernel(zr, zi, cr, ci, lim, cutoff):
    """Computes the number of iterations `n` such that
    |z_n| > `lim`, where `z_n = z_{n-1}**2 + c`.
    """
    count = 0
    while ((zr * zr + zi * zi) < (lim * lim)) and count < cutoff:
        zr, zi = zr * zr - zi * zi + cr, 2 * zr * zi + ci
        count += 1
    return count


def julia(cr, ci, N, bound=1.5, lim=1000.0, cutoff=1e6):
    """Pure Python calculation of the Julia set for a given `c`.  No NumPy
    array operations are used.
    """
    julia = np.empty((N, N), np.uint32)
    grid_x = np.linspace(-bound, bound, N)
    for i, x in enumerate(grid_x):
        for j, y in enumerate(grid_x):
            julia[i, j] = kernel(x, y, cr, ci, lim, cutoff)
    return julia
