~dricottone/filters

ref: f62c909a49e4a579a0b74b9b6632c25e127b3668 filters/rng/normal.py -rw-r--r-- 2.4 KiB
f62c909aDominic Ricottone Version 1.0.1; Cleaned up documentation 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
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
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
#!/usr/bin/env python3

"""rng normal [OPTIONS]
Uniform distribution - Generate random data from a normal distribution.

Options:
  -d, --delta   velocity of average per time unit [Default: 0]
  -m, --mu      average of distribution [Default: 0]
  -n, --number  number of random data points to generate [Default: 10]
  -s, --sigma   standard deviation of distribution [Default: 1]

Currently assumed that sigma is constant over time.
"""

import sys
import random
import itertools
from typing import Callable, List, Dict, Iterator

def cli_wrapper(**data: Dict):
    """Handler for the uniform distribution. Checks and cleans given options,
    and performs optional reporting.
    """
    _number = data["number"] if data["number"] is not None else 10
    _init_mu = data["mu"] if data["mu"] is not None else 0.0
    _sigma = data["sigma"] if data["sigma"] is not None else 1.0
    _init_velocity = data["delta"] if data["delta"] is not None else 0.0
    _acceleration = lambda x: x #constant acceleration

    _distribution = distribution(
        _init_mu,
        _sigma,
        _init_velocity,
        _acceleration,
    )

    if data["report"]:
        sys.stdout.write(
            report_header(_init_mu, _sigma, _init_velocity, _acceleration)
        )
    if _number > 0:
        for number in itertools.islice(_distribution, _number):
            sys.stdout.write("{0:.4f}\n".format(number))

def distribution(
    init_mu: float,
    sigma: float,
    init_velocity: float,
    acceleration: Callable[[float], float],
) -> Iterator[float]:
    """Generate random data.

    Arguments:
      init_mu        initial average of distribution
      sigma          sigma of distribution
      init_velocity  initial velocity of average per time unit
      acceleration   function of v1 <- v0
    """
    mu = init_mu
    velocity = init_velocity
    while True:
        yield random.normalvariate(mu, sigma)
        mu += velocity
        velocity = acceleration(velocity)

def report_header(
    init_mu: float,
    sigma: float,
    init_velocity: float,
    acceleration: Callable[[float], float],
) -> str:
    """Draw a report header summarizing the distribution."""
    _msg = (
        "Normal distribution",
        "  μ={0:.4f}, σ={1:.4f}".format(init_mu, sigma),
        "  dμ/dt={0:.4f}".format(init_velocity),
        "Obs.:",
        "========",
    )
    return "\n".join(_msg) + "\n"