The layer method

The layer method is unique among all staircase.Stairs methods - it is the only mutator method, i.e. it is the only method which modifies the step function in place, as opposed to acting on a copy. It is a very flexible method, taking full advantage of defaults and weak typing afforded by Python.

The layer method was introduced in How do I create my step function?, in which parameters were either all numbers, or all vectors. Advanced usage allows certain combinations of these, and may allow vectors of different lengths. Understanding these features is key to ensure they do not result in bugs, or unwanted effects.

For those who are mathematically inclined, a set of axioms pertaining to the layer method can be found at the bottom of the page. The expected behaviour of any call to staircase.Stairs.layer() can be derived from these axioms. Alternatively, the key ideas are summarised below:

1) A null value in the start parameter corresponds to -infinity. A null value in the end parameter corresponds to infinity.

../_images/layering-1.png

2) A scalar value for start is equivalent to [start]. A scalar value for end is equivalent to [end].

../_images/layering-2.png

3) If start and end are vectors of differing size, then null values are appended to the smallest till they are equal in length.

And don’t forget the meaning of null values according to rule 1!

../_images/layering-3.png

4) A scalar value for value is equivalent to a vector, filled with value, whose length is equal to the larger of start and end.

../_images/layering-4.png

5) A vector value for value must have the same length as the largest of start and end.

An error will result otherwise.

Test your knowledge

What do you think the result of sc.Stairs().layer() might be? See discussion and answer in Gotchas.

Axioms

infi= inf (infinity) for all i

  • .layer(s, e) = .layer(s, e, None) = .layer(s, e, 1)

  • .layer(s, None, v) = .layer(s, inf, v)

  • .layer(None, e, v) = .layer(-inf, e, v)

  • .layer(s, e, v) is the same as .layer(s, None, v).layer(s, None, -v) provided s, e not None

  • .layer([s], _, _) = .layer(s, _, _)

  • .layer(_, [e], _) = .layer(_, e, _)

  • .layer([s1, …, sn], [e1, …, en], v) = .layer([s1, …, sn], [e1, …, en], [v1, …, vn]) where vi= v for all i

  • .layer([s1, …, sn], [e1, …, en], [v1, …, vn]) = layer([s1, …, sn-1], [e1, …, en-1], [v1, …, vn-1]).layer(sn, en, vn)

  • .layer([s1, …, sn], [e1, …, ek], _) = .layer([s1, …, sn], [e1, …, ek, inf1, …, infn-k,], _) if n > k

  • .layer([s1, …, sn], [e1, …, ek], _) = .layer([s1, …, sn, -inf1, …, -infk-n,], [e1, …, ek], _) if k > n