Skip to content

Process

ARProcess

ARProcess(**kwargs)

Bases: RandomVariable

RandomVariable representing an an AR(p) process.

Source code in pyrenew/metaclass.py
47
48
49
50
51
def __init__(self, **kwargs):
    """
    Default constructor
    """
    pass

sample

sample(
    noise_name: str,
    n: int,
    autoreg: ArrayLike,
    init_vals: ArrayLike,
    noise_sd: float | ArrayLike,
) -> ArrayLike

Sample from the AR process

Parameters:

Name Type Description Default
noise_name str

A name for the sample site holding the Normal(0, noise_sd) noise for the AR process. Passed to numpyro.primitives.sample.

required
n int

Length of the sequence.

required
autoreg ArrayLike

Autoregressive coefficients. The length of the array's first dimension determines the order \(p\) of the AR process.

required
init_vals ArrayLike

Array of initial values. Must have the same first dimension size as the order.

required
noise_sd float | ArrayLike

Standard deviation of the AR process Normal noise, which by definition has mean 0.

required

Returns:

Type Description
ArrayLike

with first dimension of length n and additional dimensions as inferred from the shapes of autoreg, init_vals, and noise_sd.

Notes

The first dimension of the return value with be of length n and represents time. Trailing dimensions follow standard numpy broadcasting rules and are determined from the second through n th dimensions, if any, of autoreg and init_vals, as well as the all dimensions of noise_sd (i.e. jax.numpy.shape(autoreg)[1:], jax.numpy.shape(init_vals)[1:] and jax.numpy.shape(noise_sd)

Those shapes must be broadcastable together via jax.lax.broadcast_shapes. This can be used to produce multiple AR processes of the same order but with either shared or different initial values, AR coefficient vectors, and/or and noise standard deviation values.

Source code in pyrenew/process/ar.py
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def sample(
    self,
    noise_name: str,
    n: int,
    autoreg: ArrayLike,
    init_vals: ArrayLike,
    noise_sd: float | ArrayLike,
) -> ArrayLike:
    """
    Sample from the AR process

    Parameters
    ----------
    noise_name
        A name for the sample site holding the
        Normal(`0`, `noise_sd`) noise for the AR process.
        Passed to [`numpyro.primitives.sample`][].
    n
        Length of the sequence.
    autoreg
        Autoregressive coefficients.
        The length of the array's first
        dimension determines the order $p$
        of the AR process.
    init_vals
        Array of initial values. Must have the
        same first dimension size as the order.
    noise_sd
        Standard deviation of the AR
        process Normal noise, which by
        definition has mean 0.

    Returns
    -------
    ArrayLike
        with first dimension of length `n`
        and additional dimensions as inferred
        from the shapes of `autoreg`,
        `init_vals`, and `noise_sd`.

    Notes
    -----
    The first dimension of the return value
    with be of length `n` and represents time.
    Trailing dimensions follow standard numpy
    broadcasting rules and are determined from
    the second through `n` th dimensions, if any,
    of `autoreg` and `init_vals`, as well as the
    all dimensions of `noise_sd` (i.e.
    `jax.numpy.shape(autoreg)[1:]`,
    `jax.numpy.shape(init_vals)[1:]`
    and `jax.numpy.shape(noise_sd)`

    Those shapes must be
    broadcastable together via
    [`jax.lax.broadcast_shapes`][]. This can
    be used to produce multiple AR processes of the
    same order but with either shared or different initial
    values, AR coefficient vectors, and/or
    and noise standard deviation values.
    """
    autoreg = jnp.atleast_1d(autoreg)
    init_vals = jnp.atleast_1d(init_vals)
    noise_sd = jnp.array(noise_sd)
    # noise_sd can be a scalar, but
    # autoreg and init_vals must have a
    # a first dimension (time),
    # as the order of the process is
    # inferred from that first dimension

    order = autoreg.shape[0]
    n_inits = init_vals.shape[0]

    try:
        noise_shape = jax.lax.broadcast_shapes(
            init_vals.shape[1:],
            autoreg.shape[1:],
            noise_sd.shape,
        )
    except Exception as e:
        raise ValueError(
            "Could not determine a "
            "valid shape for the AR process noise "
            "from the shapes of the init_vals, "
            "autoreg, and noise_sd arrays. "
            "See ARProcess.sample() documentation "
            "for details."
        ) from e

    if not n_inits == order:
        raise ValueError(
            "Initial values array must have the same "
            "first dimension length as the order p of "
            "the AR process. The order is given by "
            "the first dimension length of the array "
            "of autoregressive coefficients. Got an initial "
            f"value array with first dimension {n_inits} for "
            f"a process of order {order}"
        )

    history_shape = (order,) + noise_shape

    try:
        inits_broadcast = jnp.broadcast_to(init_vals, history_shape)
    except Exception as e:
        raise ValueError(
            "Could not broadcast init_vals "
            f"(shape {init_vals.shape}) "
            "to the expected shape of the process "
            f"history (shape {history_shape}). "
            "History shape is determined by the "
            "shapes of the init_vals, autoreg, and "
            "noise_sd arrays. See ARProcess "
            "documentation for details"
        ) from e

    inits_flipped = jnp.flip(inits_broadcast, axis=0)

    def transition(recent_vals, _):  # numpydoc ignore=GL08
        with numpyro.handlers.reparam(config={noise_name: LocScaleReparam(0)}):
            next_noise = numpyro.sample(
                noise_name,
                numpyro.distributions.Normal(
                    loc=jnp.zeros(noise_shape), scale=noise_sd
                ),
            )

        dot_prod = jnp.einsum("i...,i...->...", autoreg, recent_vals)
        new_term = dot_prod + next_noise
        new_recent_vals = jnp.concatenate(
            [
                new_term[jnp.newaxis, ...],
                # concatenate as (1 time unit,) + noise_shape
                # array
                recent_vals,
            ],
            axis=0,
        )[:order]

        return new_recent_vals, new_term

    if n > order:
        _, ts = scan(
            f=transition,
            init=inits_flipped,
            xs=None,
            length=(n - order),
        )

        ts_with_inits = jnp.concatenate(
            [inits_broadcast, ts],
            axis=0,
        )
    else:
        ts_with_inits = inits_broadcast
    return ts_with_inits[:n]

validate staticmethod

validate()

Validates input parameters, implementation pending.

Source code in pyrenew/process/ar.py
181
182
183
184
185
186
@staticmethod
def validate():  # numpydoc ignore=RT01
    """
    Validates input parameters, implementation pending.
    """
    return None

DayOfWeekEffect

DayOfWeekEffect(offset: int, quantity_to_broadcast: RandomVariable)

Bases: PeriodicEffect

Weekly effect with repeating values from a random variable.

Default constructor for DayOfWeekEffect class.

Parameters:

Name Type Description Default
offset int

Relative point at which data starts, must be between 0 and 6.

required
quantity_to_broadcast RandomVariable

Values to be broadcasted (repeated or tiled).

required

Returns:

Type Description
None
Source code in pyrenew/process/periodiceffect.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
def __init__(
    self,
    offset: int,
    quantity_to_broadcast: RandomVariable,
):
    """
    Default constructor for DayOfWeekEffect class.

    Parameters
    ----------
    offset
        Relative point at which data starts, must be between 0 and
        6.
    quantity_to_broadcast
        Values to be broadcasted (repeated or tiled).

    Returns
    -------
    None
    """

    DayOfWeekEffect.validate(offset)

    super().__init__(
        offset=offset,
        quantity_to_broadcast=quantity_to_broadcast,
    )

    return None

validate staticmethod

validate(offset: int)

Validate the input parameters.

Parameters:

Name Type Description Default
offset int

Relative point at which data starts, must be between 0 and 6.

required

Returns:

Type Description
None
Source code in pyrenew/process/periodiceffect.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
@staticmethod
def validate(
    offset: int,
):
    """
    Validate the input parameters.

    Parameters
    ----------
    offset
        Relative point at which data starts, must be between 0 and 6.

    Returns
    -------
    None
    """
    assert isinstance(offset, int), "offset must be an integer."

    assert 0 <= offset <= 6, "offset must be between 0 and 6."

    return None

DifferencedProcess

DifferencedProcess(
    fundamental_process: RandomVariable, differencing_order: int, **kwargs
)

Bases: RandomVariable

Class for differenced stochastic process \(X(t)\), constructed by placing a fundamental stochastic process on the \(n^{th}\) differences (rates of change). See https://otexts.com/fpp3/stationarity.html for a discussion of differencing in the context of discrete timeseries data.

Notes

The order of differencing is the discrete analogue of the order of a derivative in single variable calculus. A first difference (derivative) represents a rate of change. A second difference (derivative) represents the rate of change of that rate of change, et cetera.

Default constructor

Parameters:

Name Type Description Default
fundamental_process RandomVariable

Stochastic process for the differences. Must accept an n argument specifying the number of samples to draw.

required
differencing_order int

How many fold-differencing the the process represents. Must be an integer greater than or equal to 1. 1 represents a process on the first differences (the rate of change), 2 a process on the 2nd differences (rate of change of the rate of change), et cetera.

required

Returns:

Type Description
None
Source code in pyrenew/process/differencedprocess.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def __init__(
    self,
    fundamental_process: RandomVariable,
    differencing_order: int,
    **kwargs,
) -> None:
    """
    Default constructor

    Parameters
    ----------
    fundamental_process
        Stochastic process for the
        differences. Must accept an
        `n` argument specifying the number
        of samples to draw.
    differencing_order
        How many fold-differencing the
        the process represents. Must be
        an integer greater than or
        equal to 1. 1 represents a process
        on the first differences (the rate
        of change), 2 a process on the
        2nd differences (rate of change of
        the rate of change), et cetera.

    Returns
    -------
    None
    """
    self.assert_valid_differencing_order(differencing_order)
    self.fundamental_process = fundamental_process
    self.differencing_order = differencing_order
    super().__init__(**kwargs)

assert_valid_differencing_order staticmethod

assert_valid_differencing_order(differencing_order: Any)

To be valid, a differencing order must be an integer and must be strictly positive. This function raises a value error if its argument is not a valid differencing order.

Parameters:

Name Type Description Default
differencing_order Any

Potential differencing order to validate.

required

Returns:

Type Description
None

or raises a ValueError

Source code in pyrenew/process/differencedprocess.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
@staticmethod
def assert_valid_differencing_order(differencing_order: Any):
    """
    To be valid, a differencing order must
    be an integer and must be strictly positive.
    This function raises a value error if its
    argument is not a valid differencing order.

    Parameters
    ----------
    differencing_order
        Potential differencing order to validate.

    Returns
    -------
    None
        or raises a [`ValueError`][]
    """
    if not isinstance(differencing_order, int):
        raise ValueError(
            "differencing_order must be an integer. "
            f"got type {type(differencing_order)} "
            f"and value {differencing_order}"
        )
    if not differencing_order >= 1:
        raise ValueError(
            "differencing_order must be an integer "
            "greater than or equal to 1. Got "
            f"{differencing_order}"
        )

sample

sample(
    init_vals: ArrayLike,
    n: int,
    *args,
    fundamental_process_init_vals: ArrayLike = None,
    **kwargs,
) -> ndarray

Sample from the process

Parameters:

Name Type Description Default
init_vals ArrayLike

initial values for the \(0^{th}\) through \((n-1)^{st}\) differences, passed as the init_diff_vals argument to pyrenew.math.integrate_discrete.

required
n int

Number of values to sample. Will sample n - differencing_order values from self.fundamental_process to ensure that the de-differenced output is of length n.

required
*args

Additional positional arguments passed to self.fundamental_process.sample

()
fundamental_process_init_vals ArrayLike

Initial values for the fundamental process. Passed as the init_vals keyword argument to self.fundamental_process.sample. Default None.

None
**kwargs

Keyword arguments passed to self.fundamental_process.sample().

{}

Returns:

Type Description
ndarray

An array representing the undifferenced timeseries

Source code in pyrenew/process/differencedprocess.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def sample(
    self,
    init_vals: ArrayLike,
    n: int,
    *args,
    fundamental_process_init_vals: ArrayLike = None,
    **kwargs,
) -> jnp.ndarray:
    """
    Sample from the process

    Parameters
    ----------
    init_vals
        initial values for the $0^{th}$ through
        $(n-1)^{st}$ differences, passed as the
        `init_diff_vals` argument to
        [`pyrenew.math.integrate_discrete`][].

    n
        Number of values to sample. Will sample
        `n - differencing_order` values from
        `self.fundamental_process` to ensure
        that the de-differenced output is of length
        `n`.

    *args
        Additional positional arguments passed to
        `self.fundamental_process.sample`

    fundamental_process_init_vals
        Initial values for the fundamental process.
        Passed as the `init_vals` keyword argument
        to `self.fundamental_process.sample`.
        Default `None`.

    **kwargs
        Keyword arguments passed to
        `self.fundamental_process.sample()`.

    Returns
    -------
    jnp.ndarray
        An array representing the undifferenced timeseries
    """
    if not isinstance(n, int):
        raise ValueError(f"n must be an integer. Got {type(n)}")
    if n < 1:
        raise ValueError(f"n must be positive. Got {n}")

    init_vals = jnp.atleast_1d(init_vals)
    n_inits = init_vals.shape[0]

    if not n_inits == self.differencing_order:
        raise ValueError(
            "Must have exactly as many "
            "initial difference values as "
            "the differencing order, given "
            "in the sequence $X(t=0), X^1(t=1),$ "
            "et cetera. "
            f"Got {n_inits} values "
            "for a process of order "
            f"{self.differencing_order}."
        )
    n_diffs = n - self.differencing_order

    if n_diffs > 0:
        diff_samp = self.fundamental_process.sample(
            *args,
            n=n_diffs,
            init_vals=fundamental_process_init_vals,
            **kwargs,
        )
        diffs = diff_samp
    else:
        diffs = jnp.array([])
    integrated_ts = integrate_discrete(init_vals, diffs)[:n]
    return integrated_ts

validate

validate()

Empty validation method.

Source code in pyrenew/process/differencedprocess.py
100
101
102
103
104
def validate(self):
    """
    Empty validation method.
    """
    pass

IIDRandomSequence

IIDRandomSequence(element_rv: RandomVariable, **kwargs)

Bases: RandomVariable

Class for constructing random sequence of independent and identically distributed elements given an arbitrary RandomVariable representing those elements.

Default constructor

Parameters:

Name Type Description Default
element_rv RandomVariable

RandomVariable representing a single element in the sequence.

required

Returns:

Type Description
None
Source code in pyrenew/process/iidrandomsequence.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def __init__(
    self,
    element_rv: RandomVariable,
    **kwargs,
) -> None:
    """
    Default constructor

    Parameters
    ----------
    element_rv
        RandomVariable representing a single element
        in the sequence.

    Returns
    -------
    None
    """
    super().__init__(**kwargs)
    self.element_rv = element_rv

sample

sample(n: int, *args, vectorize: bool = False, **kwargs) -> ArrayLike

Sample an IID random sequence.

Parameters:

Name Type Description Default
n int

Length of the sequence to sample.

required
*args

Additional positional arguments passed to self.element_rv.sample()

()
vectorize bool

Sample vectorized? If True, use the pyrenew.metaclass.RandomVariable's expand_by() method, if available, and fall back on numpyro.contrib.control_flow.scan otherwise. If False, always use numpyro.contrib.control_flow.scan. Default False.

False
**kwargs

Additional keyword arguments passed to self.element_rv.sample.

{}

Returns:

Type Description
ArrayLike

n samples from self.distribution`.

Source code in pyrenew/process/iidrandomsequence.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def sample(self, n: int, *args, vectorize: bool = False, **kwargs) -> ArrayLike:
    """
    Sample an IID random sequence.

    Parameters
    ----------
    n
        Length of the sequence to sample.

    *args
        Additional positional arguments passed
        to self.element_rv.sample()

    vectorize
        Sample vectorized? If True, use the
        [`pyrenew.metaclass.RandomVariable`][]'s
        `expand_by()` method, if available,
        and fall back on [`numpyro.contrib.control_flow.scan`][]
        otherwise.
        If False, always use
        [`numpyro.contrib.control_flow.scan`][].
        Default False.

    **kwargs
        Additional keyword arguments passed to
        `self.element_rv.sample`.

    Returns
    -------
    ArrayLike
        `n` samples from self.distribution`.
    """

    if vectorize and hasattr(self.element_rv, "expand_by"):
        result = self.element_rv.expand_by((n,)).sample(*args, **kwargs)
    else:

        def transition(_carry, _x):
            # numpydoc ignore=GL08
            el = self.element_rv.sample(*args, **kwargs)
            return None, el

        _, result = scan(
            transition,
            xs=None,
            init=None,
            length=n,
        )

    return result

validate staticmethod

validate()

Validates input parameters, implementation pending.

Source code in pyrenew/process/iidrandomsequence.py
91
92
93
94
95
96
97
@staticmethod
def validate():
    """
    Validates input parameters, implementation pending.
    """
    super().validate()
    return None

PeriodicEffect

PeriodicEffect(offset: int, quantity_to_broadcast: RandomVariable)

Bases: RandomVariable

Periodic effect with repeating values from a random variable.

Default constructor for PeriodicEffect class.

Parameters:

Name Type Description Default
offset int

Relative point at which data starts, must be between 0 and period_size - 1.

required
quantity_to_broadcast RandomVariable

Values to be broadcasted (repeated or tiled).

required

Returns:

Type Description
None
Source code in pyrenew/process/periodiceffect.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def __init__(
    self,
    offset: int,
    quantity_to_broadcast: RandomVariable,
):
    """
    Default constructor for PeriodicEffect class.

    Parameters
    ----------
    offset
        Relative point at which data starts, must be between 0 and
        period_size - 1.
    quantity_to_broadcast
        Values to be broadcasted (repeated or tiled).

    Returns
    -------
    None
    """

    PeriodicEffect.validate(quantity_to_broadcast)

    self.offset = offset

    self.quantity_to_broadcast = quantity_to_broadcast

sample

sample(duration: int, **kwargs)

Sample from the process.

Parameters:

Name Type Description Default
duration int

Number of timepoints to sample.

required
**kwargs

Additional keyword arguments passed through to the quantity_to_broadcast.

{}

Returns:

Type Description
ArrayLike
Source code in pyrenew/process/periodiceffect.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def sample(self, duration: int, **kwargs):
    """
    Sample from the process.

    Parameters
    ----------
    duration
        Number of timepoints to sample.
    **kwargs
        Additional keyword arguments passed through to the `quantity_to_broadcast`.

    Returns
    -------
    ArrayLike
    """

    return au.tile_until_n(
        data=self.quantity_to_broadcast.sample(**kwargs),
        n_timepoints=duration,
        offset=self.offset,
    )

validate staticmethod

validate(quantity_to_broadcast: RandomVariable) -> None

Validate the broadcasting quatity.

Parameters:

Name Type Description Default
quantity_to_broadcast RandomVariable

Values to be broadcasted (repeated or tiled).

required

Returns:

Type Description
None
Source code in pyrenew/process/periodiceffect.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@staticmethod
def validate(quantity_to_broadcast: RandomVariable) -> None:
    """
    Validate the broadcasting quatity.

    Parameters
    ----------
    quantity_to_broadcast
        Values to be broadcasted (repeated or tiled).

    Returns
    -------
    None
    """

    assert isinstance(quantity_to_broadcast, RandomVariable)

    return None

RandomWalk

RandomWalk(step_rv: RandomVariable, **kwargs)

Bases: DifferencedProcess

Class for a Markovian random walk with an arbitrary step distribution, implemented via DifferencedProcess and IIDRandomSequence

Default constructor

Parameters:

Name Type Description Default
step_rv RandomVariable

RandomVariable representing a single step (difference) in the random walk.

required
**kwargs

Additional keyword arguments passed to the parent class constructor.

{}

Returns:

Type Description
None
Source code in pyrenew/process/randomwalk.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def __init__(
    self,
    step_rv: RandomVariable,
    **kwargs,
):
    """
    Default constructor

    Parameters
    ----------
    step_rv
        RandomVariable representing a single step
        (difference) in the random walk.

    **kwargs
        Additional keyword arguments passed to the parent
        class constructor.

    Returns
    -------
    None
    """
    super().__init__(
        fundamental_process=IIDRandomSequence(element_rv=step_rv),
        differencing_order=1,
        **kwargs,
    )

RtPeriodicDiffARProcess

RtPeriodicDiffARProcess(
    name: str,
    offset: int,
    period_size: int,
    log_rt_rv: RandomVariable,
    autoreg_rv: RandomVariable,
    periodic_diff_sd_rv: RandomVariable,
    ar_process_suffix: str = "_first_diff_ar_process_noise",
)

Bases: RandomVariable

Periodic Rt with autoregressive first differences

Notes

This class samples a periodic reproduction number \(\mathcal{R}(t)\) by placing an AR(1) process on the first differences in \(\log[\mathcal{R}(t)]\). Formally:

\[ \log[\mathcal{R}^\mathrm{u}(t_3)] \sim \mathrm{Normal}\left(\log[\mathcal{R}^\mathrm{u}(t_2)] \ + \beta \left(\log[\mathcal{R}^\mathrm{u}(t_2)] - \ \log[\mathcal{R}^\mathrm{u}(t_1)]\right), \sigma_r \right) \]
where \(\mathcal{R}^\mathrm{u}(t)\) is the periodic reproduction number at time \(t\), \(\beta\) is the autoregressive parameter, and \(\sigma_r\) is the standard deviation of the noise.

Default constructor for RtPeriodicDiffARProcess class.

Parameters:

Name Type Description Default
name str

Name of the site.

required
offset int

Relative point at which data starts, must be between 0 and period_size - 1.

required
log_rt_rv RandomVariable

Log Rt prior for the first two observations.

required
autoreg_rv RandomVariable

Autoregressive parameter.

required
periodic_diff_sd_rv RandomVariable

Standard deviation of the noise.

required
ar_process_suffix str

Suffix to append to the pyrenew.metaclass.RandomVariable's name when naming the pyrenew.metaclass.RandomVariable that represents the underlying AR process noise. Default "_first_diff_ar_process_noise".

'_first_diff_ar_process_noise'

Returns:

Type Description
None
Source code in pyrenew/process/rtperiodicdiffar.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def __init__(
    self,
    name: str,
    offset: int,
    period_size: int,
    log_rt_rv: RandomVariable,
    autoreg_rv: RandomVariable,
    periodic_diff_sd_rv: RandomVariable,
    ar_process_suffix: str = "_first_diff_ar_process_noise",
) -> None:
    """
    Default constructor for RtPeriodicDiffARProcess class.

    Parameters
    ----------
    name
        Name of the site.
    offset
        Relative point at which data starts, must be between 0 and
        period_size - 1.
    log_rt_rv
        Log Rt prior for the first two observations.
    autoreg_rv
        Autoregressive parameter.
    periodic_diff_sd_rv
        Standard deviation of the noise.
    ar_process_suffix
        Suffix to append to the [`pyrenew.metaclass.RandomVariable`][]'s `name`
        when naming the [`pyrenew.metaclass.RandomVariable`][] that represents
        the underlying AR process noise.
        Default "_first_diff_ar_process_noise".

    Returns
    -------
    None
    """

    self.validate(
        log_rt_rv=log_rt_rv,
        autoreg_rv=autoreg_rv,
        periodic_diff_sd_rv=periodic_diff_sd_rv,
    )

    self.name = name
    self.period_size = period_size
    self.offset = offset
    self.log_rt_rv = log_rt_rv
    self.autoreg_rv = autoreg_rv
    self.periodic_diff_sd_rv = periodic_diff_sd_rv
    self.ar_process_suffix = ar_process_suffix

    self.ar_diff = DifferencedProcess(
        fundamental_process=ARProcess(),
        differencing_order=1,
    )

    return None

sample

sample(duration: int, **kwargs) -> ArrayLike

Samples the periodic \(\mathcal{R}(t)\) with autoregressive first differences.

Parameters:

Name Type Description Default
duration int

Duration of the sequence.

required
**kwargs

Additional keyword arguments passed through to internal sample calls, should there be any.

{}

Returns:

Type Description
ArrayLike

Sampled \(\mathcal{R}(t)\) values.

Source code in pyrenew/process/rtperiodicdiffar.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def sample(
    self,
    duration: int,
    **kwargs,
) -> ArrayLike:
    """
    Samples the periodic $\\mathcal{R}(t)$
    with autoregressive first differences.

    Parameters
    ----------
    duration
        Duration of the sequence.
    **kwargs
        Additional keyword arguments passed through to
        internal `sample` calls, should there be any.

    Returns
    -------
    ArrayLike
        Sampled $\\mathcal{R}(t)$ values.
    """

    # Initial sample
    log_rt_rv = self.log_rt_rv(**kwargs).squeeze()
    b = self.autoreg_rv(**kwargs).squeeze()
    s_r = self.periodic_diff_sd_rv(**kwargs).squeeze()

    # How many periods to sample?
    n_periods = (duration + self.period_size - 1) // self.period_size

    # Running the process

    log_rt = self.ar_diff(
        noise_name=f"{self.name}{self.ar_process_suffix}",
        n=n_periods,
        init_vals=jnp.array(log_rt_rv[0]),
        autoreg=b,
        noise_sd=s_r,
        fundamental_process_init_vals=jnp.array(log_rt_rv[1] - log_rt_rv[0]),
    )

    return au.repeat_until_n(
        data=jnp.exp(log_rt),
        n_timepoints=duration,
        offset=self.offset,
        period_size=self.period_size,
    )

validate staticmethod

validate(log_rt_rv: any, autoreg_rv: any, periodic_diff_sd_rv: any) -> None

Validate the input parameters.

Parameters:

Name Type Description Default
log_rt_rv any

Log Rt prior for the first two observations.

required
autoreg_rv any

Autoregressive parameter.

required
periodic_diff_sd_rv any

Standard deviation of the noise.

required

Returns:

Type Description
None
Source code in pyrenew/process/rtperiodicdiffar.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@staticmethod
def validate(
    log_rt_rv: any,
    autoreg_rv: any,
    periodic_diff_sd_rv: any,
) -> None:
    """
    Validate the input parameters.

    Parameters
    ----------
    log_rt_rv
        Log Rt prior for the first two observations.
    autoreg_rv
        Autoregressive parameter.
    periodic_diff_sd_rv
        Standard deviation of the noise.

    Returns
    -------
    None
    """

    assert isinstance(log_rt_rv, RandomVariable)
    assert isinstance(autoreg_rv, RandomVariable)
    assert isinstance(periodic_diff_sd_rv, RandomVariable)

    return None

RtWeeklyDiffARProcess

RtWeeklyDiffARProcess(
    name: str,
    offset: int,
    log_rt_rv: RandomVariable,
    autoreg_rv: RandomVariable,
    periodic_diff_sd_rv: RandomVariable,
)

Bases: RtPeriodicDiffARProcess

Weekly Rt with autoregressive first differences.

Default constructor for RtWeeklyDiffARProcess class.

Parameters:

Name Type Description Default
name str

Name of the site.

required
offset int

Relative point at which data starts, must be between 0 and 6.

required
log_rt_rv RandomVariable

Log Rt prior for the first two observations.

required
autoreg_rv RandomVariable

Autoregressive parameter.

required
periodic_diff_sd_rv RandomVariable

Standard deviation of the noise.

required

Returns:

Type Description
None
Source code in pyrenew/process/rtperiodicdiffar.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
def __init__(
    self,
    name: str,
    offset: int,
    log_rt_rv: RandomVariable,
    autoreg_rv: RandomVariable,
    periodic_diff_sd_rv: RandomVariable,
) -> None:
    """
    Default constructor for RtWeeklyDiffARProcess class.

    Parameters
    ----------
    name
        Name of the site.
    offset
        Relative point at which data starts, must be between 0 and 6.
    log_rt_rv
        Log Rt prior for the first two observations.
    autoreg_rv
        Autoregressive parameter.
    periodic_diff_sd_rv
        Standard deviation of the noise.

    Returns
    -------
    None
    """

    super().__init__(
        name=name,
        offset=offset,
        period_size=7,
        log_rt_rv=log_rt_rv,
        autoreg_rv=autoreg_rv,
        periodic_diff_sd_rv=periodic_diff_sd_rv,
    )

    return None

StandardNormalRandomWalk

StandardNormalRandomWalk(step_rv_name: str, **kwargs)

Bases: RandomWalk

A random walk with standard Normal (mean = 0, standard deviation = 1) steps, implmemented via the base RandomWalk class.

Default constructor

Parameters:

Name Type Description Default
step_rv_name str

Name for the DistributionalVariable from which the Normal(0, 1) steps are sampled.

required
**kwargs

Additional keyword arguments passed to the parent class constructor.

{}
Return

None

Source code in pyrenew/process/randomwalk.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def __init__(
    self,
    step_rv_name: str,
    **kwargs,
):
    """
    Default constructor
    Parameters
    ----------
    step_rv_name
        Name for the DistributionalVariable
        from which the Normal(0, 1)
        steps are sampled.
    **kwargs
        Additional keyword arguments passed
        to the parent class constructor.
    Return
    ------
    None
    """
    super().__init__(
        step_rv=DistributionalVariable(
            name=step_rv_name, distribution=dist.Normal(0.0, 1.0)
        ),
        **kwargs,
    )

StandardNormalSequence

StandardNormalSequence(
    element_rv_name: str, element_shape: tuple = None, **kwargs
)

Bases: IIDRandomSequence

Class for a sequence of IID standard Normal (mean = 0, sd = 1) random variables.

Default constructor

Parameters:

Name Type Description Default
element_rv_name str

Name for the internal element_rv, here a DistributionalVariable encoding a standard Normal (mean = 0, sd = 1) distribution.

required
element_shape tuple

Shape for each element in the sequence. If None, elements are scalars. Default None.

None

Returns:

Type Description
None
Source code in pyrenew/process/iidrandomsequence.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def __init__(
    self,
    element_rv_name: str,
    element_shape: tuple = None,
    **kwargs,
):
    """
    Default constructor

    Parameters
    ----------
    element_rv_name
        Name for the internal element_rv, here a
        DistributionalVariable encoding a
        standard Normal (mean = 0, sd = 1)
        distribution.
    element_shape
        Shape for each element in the sequence.
        If None, elements are scalars. Default
        None.

    Returns
    -------
    None
    """
    if element_shape is None:
        element_shape = ()
    super().__init__(
        element_rv=DistributionalVariable(
            name=element_rv_name, distribution=dist.Normal(0, 1)
        ).expand_by(element_shape)
    )