Skip to content

utils

clean_types(d)

cleans up nested dict/list/tuple/other d for exporting as yaml

Converts library specific types to python native types, including numpy dtypes, OrderedDict, numpy arrays

https://stackoverflow.com/questions/59605943/python-convert-types-in-deeply-nested-dictionary-or-array

Source code in slimfit/utils.py
 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
def clean_types(d: Any) -> Any:
    """cleans up nested dict/list/tuple/other `d` for exporting as yaml

    Converts library specific types to python native types, including numpy dtypes,
    OrderedDict, numpy arrays

    # https://stackoverflow.com/questions/59605943/python-convert-types-in-deeply-nested-dictionary-or-array

    """
    if isinstance(d, np.floating):
        return float(d)

    if isinstance(d, np.integer):
        return int(d)

    if isinstance(d, np.ndarray):
        return d.tolist()

    if isinstance(d, list):
        return [clean_types(item) for item in d]

    if isinstance(d, tuple):
        return tuple(clean_types(item) for item in d)

    if isinstance(d, OrderedDict):
        return clean_types(dict(d))

    if isinstance(d, dict):
        return {k: clean_types(v) for k, v in d.items()}

    else:
        return d

format_indexer(indexer)

Format a tuple of slice objects into a string that can be used to index a numpy array.

More or less the inverse of numpy.index_exp.

Parameters:

Name Type Description Default
indexer tuple[slice, int, None, Ellipsis]

Tuple of indexing objects.

required
Source code in slimfit/utils.py
122
123
124
125
126
127
128
129
130
131
132
133
def format_indexer(indexer: tuple[slice, int, None, Ellipsis]) -> str:
    """Format a tuple of slice objects into a string that can be used to index a numpy array.

    More or less the inverse of `numpy.index_exp`.


    Args:
        indexer: Tuple of indexing objects.

    """

    return f"[{', '.join(_format_indexer(sl) for sl in indexer)}]"

get_bounds(parameters)

Get bounds for minimization. Args: parameters: Iterable of Parameter objects.

Returns:

Type Description
Optional[list[tuple[Optional[float], Optional[float]]]]

Either a list of tuples to pass to scipy.minimize or None, if there are no bounds.

Source code in slimfit/utils.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def get_bounds(
    parameters: Iterable[Parameter],
) -> Optional[list[tuple[Optional[float], Optional[float]]]]:
    """
    Get bounds for minimization.
    Args:
        parameters: Iterable of Parameter objects.

    Returns:
        Either a list of tuples to pass to `scipy.minimize` or None, if there are no bounds.
    """
    bounds = [(p.vmin, p.vmax) for p in parameters]

    if all([(None, None) == b for b in bounds]):
        return None
    else:
        return bounds

intersecting_component_symbols(model_components, symbols)

Finds and groups model components which have intersecting symbols.

Parameters:

Name Type Description Default
model_components list[tuple[Symbol, NumExprBase]]

Model components.

required
symbols set[Symbol]

Set of symbols to consider for intersections.

required

Returns:

Type Description
list[Model]

Reconstructed models (assuming orignal model was a product of models).

Source code in slimfit/utils.py
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
def intersecting_component_symbols(
    model_components: list[tuple[Symbol, NumExprBase]],
    symbols: set[Symbol],
) -> list[Model]:
    """
    Finds and groups model components which have intersecting symbols.

    Args:
        model_components: Model components.
        symbols: Set of symbols to consider for intersections.

    Returns:
        Reconstructed models (assuming orignal model was a product of models).
    """

    seen_models = []
    seen_sets = []
    for lhs, num_expr in model_components:
        param_set = num_expr.symbols & symbols
        # param_set = set(num_expr.free_parameters.keys())

        found = False
        # look for sets of parameters we've seen so far, if found, append to the list of sets
        for i, test_set in enumerate(seen_sets):
            if param_set & test_set:
                # add additional items to this set of parameters
                test_set |= param_set
                seen_models[i].append((lhs, num_expr))
                found = True
        if not found:
            seen_sets.append(param_set)
            seen_models.append([(lhs, num_expr)])

    # Next, piece together the dependent model parts as Model objects, restoring original multiplications
    sub_models = []
    for components in seen_models:
        model_dict = defaultdict(list)
        for lhs, rhs in components:
            model_dict[lhs].append(rhs)

        model_dict = {
            lhs: rhs[0] if len(rhs) == 1 else Mul(*rhs) for lhs, rhs in model_dict.items()
        }
        sub_models.append(Model(model_dict))

    return sub_models