# Using matplotlib in Perl 6 (part 3)

2017-03-06 00:15,

This is Part 3 in a series. You can start at the Intro here.

So far this Perl 6 wrapper class for matplotlib is going well. With the first graph in the gallery under my belt, I moved on to second example, `fill_demo.py`. Here's the Python code

```import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 1, 500)
y = np.sin(4 * np.pi * x) * np.exp(-5 * x)

fig, ax = plt.subplots()

ax.fill(x, y, zorder=10)
ax.grid(True, zorder=5)
plt.show()```

Being a rather simple graph, you might think that the Perl code would be fairly straight forward, and you'd be right. The only minor curveball is another numpy function `linspace`, and that rather hairy looking operation for the `y` value.

To reiterate what I've said in previous parts, I'm not familiar with numpy at all. Or at least, I wasn't before I started working on these graphs. I inserted a `print(x)` into the Python code to see what `linspace` did. In hindsight, the name is obvious; It simply creates a linearly spaced sequence of numbers. Here's a quick demonstration

```>>> numpy.linspace(0, 1, 3)
array([ 0. ,  0.5,  1. ])
>>> numpy.linspace(0, 1, 5)
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ])
>>> numpy.linspace(0, 1, 6)
array([ 0. ,  0.2,  0.4,  0.6,  0.8,  1. ])```

In the case of `x` in the graph, it's a sequence of 500 numbers evenly spaced from 0 to 1. So how would I do this in Perl. It is a monotonic sequence, so maybe the Sequence operator can help us again. So far we've seen a couple simple Sequences. The most simple sequence defines the start of a number series, and Perl lazily generates the rest.

```> 0, 2, 4, 8 ... 1024
(0 2 4 8 16 32 64 128 256 512 1024)```

This is nice and all, but I had to define 4 numbers for Perl to understand that sequence. If I dropped the `8`, then it would have generated a sequence of even numbers. Instead, I can define a function which calculates how the next value should be generated.

```> 0, 2, * × 2 ... 1024
(0 2 4 8 16 32 64 128 256 512 1024)```

Here we see our old friend, the Whatever `*`. This time I'm asking for the Sequence starting `0, 2`, then I define a mini-function that takes Whatever the last number in the Sequence was and multiplies it by 2. Sequences are a fascinating part of Perl 6 that could occupy a blog post all their own, but for now, that's enough of a foundation to create a simplified `linspace` function.

```sub linspace( \$start, \$end, \$steps ) {
my \$step = ( \$end - \$start ) ÷ ( \$steps - 1 );
return \$start, * + \$step ... \$end;
}

linspace( 0, 1, 3 ); # Result: (0, 0.5, 1)
linspace( 0, 1, 5 ); # Result: (0, 0.25, 0.5, 0.75, 1)
linspace( 0, 1, 6 ); # Result: (0, 0.2, 0.4, 0.6, 0.8, 1)```

This function does what I need, but it could stand to be a little more robust. I'll make a module to house this function, just in case I need it for future plots. I'll also add type constraints to the parameters, and multiple dispatch functions to handle steps of 0 or 1. I'm calling my library `Numpl`. Any resemblance to actual libraries is purely coincidental.

```class Numpl {

proto method linspace( Real \$start, Real \$end, Int \$steps ) { * }

multi method linspace( \$start, \$end, 0 ) { Empty }

multi method linspace( \$start, \$end, 1 ) { \$start }

multi method linspace( \$start, \$end, Int \$steps ) {
my \$step = ( \$end - \$start ) ÷ ( \$steps - 1 );
return \$start, * + \$step ... \$end
}
}```

So that was a very scenic tour around the Sequence operator, but now that we have a `linspace` function, the rest is smooth sailing. Getting back to the plot, the final code now looks like this.

```use Matplotlib;
use Numpl;

my \$plt = Matplotlib.new;

my @x = Numpl.linspace( 0, 1, 500 );
my @y = @x.map(-> \$x {
sin( 4 × π × \$x ) × exp( -5 × \$x )
});

my ( \$fig, \$ax ) = \$plt.subplots();

\$ax.fill( \$@x, \$@y, :zorder(10) );
\$ax.grid( True, :zorder(5) );
\$plt.show();```

Oh yeah, there was that hairy looking operation for the `y` values. To refresh your memory, the python looked like this

`y = np.sin(4 * np.pi * x) * np.exp(-5 * x)`

I can pretty much copy this operation exactly as it appears and put it inside the map. I've put the map operation on it's own line as I think this aids readability.

You might have also noticed I'm using proper `@arrays` in this one, and there is a valid reason for this. Sequences are lazy, and typically can only be iterated over once. `x` is iterated over in the map and that would prevent any later iterations. Here I've assigned the Sequence to a fully reified Array, which also means the Sequence is evaluated eagerly at assignment (ie. not lazily). As covered in part 2, Python doesn't like Perl arrays as positional arguments, so I coerce them to scalar values when I pass them.

The other way I could have handled this was to coerce my Sequence to a List on assignment like so.

`my \$x = Numpl.linspace( 0, 1, 500 ).List;`

Then I could have assigned it to a scalar variable and still be free to iterate over it as many times as I like. If you have no need for laziness from your `linspace` function, you could modify it to return a reified List either coercing the return value as above, or by instructing the Sequence to be eagerly evaluated.

```return ( \$start, * + \$step ... \$end ).List
# or
return eager \$start, * + \$step ... \$end```

But I like to be able to control the laziness of my `linspace` result from outside the function.

Whichever way you do it, the end result should look like this The wrapper module is working out well... a little too well. I wanted to tackle something a little more complex, and scrolling through the matplotlib gallery I saw it. It's high time for a histogram.

To be continued...