Events demo with operations

This demo shows the operations available to be used with the events system.

In [160]:
from godot.core import num, tempo
from godot.core import autodif as ad

We define two functions which are simple sine/cosine taking the epoch MJD value.

In [161]:
def foo(e: tempo.Epoch):
    return ad.sin(e.mjd() * num.Pi)

def bar(e: tempo.Epoch):
    return ad.cos(e.mjd() * num.Pi)

Let's plot these functions! First we generate some plotting data.

In [162]:
start = tempo.Epoch("0.7 TDB")
end = tempo.Epoch("7.1 TDB")
ran = tempo.EpochRange(start, end)
grid = ran.createGridNum(10000)
t = [e.mjd() for e in grid]
x = [foo(e) for e in grid]
y = [bar(e) for e in grid]

Then we plot these with matplotlib

In [163]:
import matplotlib.pyplot as plt

def plot_foobar():
    plt.plot(t, x, label="foo")
    plt.plot(t, y, label="bar")
    plt.legend()
    plt.grid()

plt.figure(figsize=(10, 8))
plot_foobar()

We use these functions to define some events

In [164]:
from godot.core import events

eps = 1e-9
tol = 1e-9
ev_grid = ran.createGridNum(10)
limit_val = 0.1
foo_locs = events.generateEventSet(lambda e: foo(e) - limit_val, eps, ev_grid, tol)

We plot the roots

In [165]:
def plot_roots(roots, limit):
    locs = [entry.value().mjd() for entry in roots]
    vals = [foo(entry.value()) for entry in roots]
    plt.plot(locs, vals, "ok")
    plt.plot([ran.start().mjd(), ran.end().mjd()], [limit, limit], '--k', lw=1)

plt.figure(figsize=(10, 8))
plot_foobar()
plot_roots(foo_locs, limit_val)

Now we generate event interval for foo/bar functions when they are above/below a certain value.

In [166]:
foo_limit = 0.3
foo_above = events.generateEventIntervalSet(lambda e: foo(e) - foo_limit, eps, ev_grid, tol)
bar_limit = -0.4
bar_below = events.generateEventIntervalSet(lambda e: -(bar(e) - bar_limit), eps, ev_grid, tol)

We can plot these intervals as well

In [167]:
def plot_interval(func, interval, c, limit=None):
    for entry in interval:
        int_ran = tempo.EpochRange(entry.start().value(), entry.end().value())
        int_grid = int_ran.createGridNum(100)
        locs = [e.mjd() for e in int_grid]
        vals = [func(e) for e in int_grid]
        plt.plot(locs, vals, "-", color=c, lw=3)
        if limit:
            plt.plot([ran.start().mjd(), ran.end().mjd()], [limit, limit], '--', color=c, lw=1)

plt.figure(figsize=(10, 8))
plot_foobar()
plot_interval(foo, foo_above, "b", foo_limit)
plot_interval(bar, bar_below, "r", bar_limit)

Now we can start combining these event sets and interval! First we invert an interval.

In [168]:
foo_below = foo_above.complement()
bar_above = bar_below.complement()

plt.figure(figsize=(10, 8))
plot_foobar()
plot_interval(foo, foo_below, "b", foo_limit)
plot_interval(bar, bar_above, "r", bar_limit)

We can also combine two event interval sets by taking the overlap or merge of the two.

In [169]:
foo_above_and_bar_below = num.overlap(foo_above, bar_below)

plt.figure(figsize=(10, 8))
plot_foobar()
plot_interval(foo, foo_above, "b", foo_limit)
plot_interval(bar, bar_below, "r", bar_limit)
plot_interval(lambda e: foo_limit, foo_above_and_bar_below, "k")
plot_interval(lambda e: bar_limit, foo_above_and_bar_below, "k")
In [170]:
foo_above_and_bar_below = num.merge(foo_above, bar_below)

plt.figure(figsize=(10, 8))
plot_foobar()
plot_interval(foo, foo_above, "b", foo_limit)
plot_interval(bar, bar_below, "r", bar_limit)
plot_interval(lambda e: foo_limit, foo_above_and_bar_below, "k")
plot_interval(lambda e: bar_limit, foo_above_and_bar_below, "k")

We can also filter some events on an interval and keep the ones which fall within.

In [171]:
foo_locs_in_bar_below = num.filter(foo_locs, bar_below)

plt.figure(figsize=(10, 8))
plot_foobar()
plot_roots(foo_locs_in_bar_below, limit_val)
plot_interval(bar, bar_below, "r", bar_limit)
In [ ]: