mirror of
https://github.com/vale981/SecondaryValue
synced 2025-03-04 16:41:38 -05:00
Make dependeny return optional => predictable.
This commit is contained in:
parent
e97c1d8838
commit
246a226c49
3 changed files with 35 additions and 22 deletions
20
Readme.md
20
Readme.md
|
@ -28,7 +28,7 @@ result = x(a=(1, 20), b=(2, 30), c=2)
|
|||
# used if present. This may be useful to calculate statistical and systemic
|
||||
# errors in one go.
|
||||
print(result)
|
||||
# >> array([ 1.41421356, 35.35533906])
|
||||
# >> (1.41421356, 35.35533906)
|
||||
|
||||
# As a goodie, you can print out the gaussian error distribution in
|
||||
# symbolic form. (Works best in Jupyter Notebooks)
|
||||
|
@ -82,6 +82,10 @@ x(a=([1,2,3], [1,2,3]), b=([1,2,3], 1))
|
|||
x(a=([1,2,3], [1,2,3]), b=([1,2], 1))
|
||||
```
|
||||
|
||||
If all the returned arrays in the tuple have the same shape, you can
|
||||
easily convert that tuple to a numpy array:
|
||||
`np.array(x(a=([1,2,3], [1,2,3]), b=([1,2,3], 1)))`
|
||||
|
||||
### Dependencies
|
||||
To make the calculation of complex values easier, one can define
|
||||
dependencies for a `SecondaryValue`:
|
||||
|
@ -90,14 +94,22 @@ dependencies for a `SecondaryValue`:
|
|||
from SecondaryValue import SecondaryValue
|
||||
|
||||
dep = SecondaryValue('u')
|
||||
x = SecondaryValue("a + b", dependencies={'a': dep})
|
||||
x = SecondaryValue("a + b", dependencies=dict(a=dep))
|
||||
|
||||
# x will now accept u as an additional kwarg and calculate d==dep on the fly
|
||||
# and return a dictionary containing it as a second return value.
|
||||
# and return a dictionary containing it as a second return value if you
|
||||
# specify `retdeps=True`.
|
||||
print(x(b=1, u=(1, 2), retdeps=True))
|
||||
# >> ((2.0, 2.0), {'a': ((1.0, 2.0), {})})
|
||||
|
||||
# To make the output predictable, the dependencies aren't returned by deafult.
|
||||
print(x(b=1, u=(1, 2)))
|
||||
# >> (array([2., 2.]), {'a': array([1., 2.])})
|
||||
# >> (2.0, 2.0)
|
||||
|
||||
# you can overwrite the dependency calculation
|
||||
print(x(b=1/2, a=1/2))
|
||||
# >> 1.0
|
||||
```
|
||||
|
||||
If there are no dependency values, an empty dict will be returned when
|
||||
`retdeps=True` is specified.
|
||||
|
|
|
@ -66,9 +66,9 @@ class SecondaryValue:
|
|||
if name in kwargs:
|
||||
continue
|
||||
|
||||
tmp = sec_val(**kwargs)
|
||||
kwargs[name] = tmp[0] if (len(tmp) > 1 and isinstance(tmp, tuple)) \
|
||||
else tmp
|
||||
# we always calculate the depndencies
|
||||
tmp = sec_val(retdeps=True, **kwargs)
|
||||
kwargs[name] = tmp[0]
|
||||
calc_deps[name] = tmp
|
||||
|
||||
return kwargs, calc_deps
|
||||
|
@ -111,6 +111,7 @@ class SecondaryValue:
|
|||
dep_values (the values and errors of the dependencies)
|
||||
|
||||
:rtype: Tuple
|
||||
|
||||
"""
|
||||
|
||||
kwargs, dep_values = self._calc_deps(**kwargs)
|
||||
|
@ -125,7 +126,6 @@ class SecondaryValue:
|
|||
kwargs = {var: val for var, val in kwargs.items() \
|
||||
if var in self._symbols}
|
||||
|
||||
|
||||
max_uncertainties = max([len(val) for _, val in kwargs.items() \
|
||||
if isinstance(val, Iterable)] or [0])
|
||||
|
||||
|
@ -158,7 +158,6 @@ class SecondaryValue:
|
|||
central_value = np.empty(value_length)
|
||||
for i in range(0, value_length):
|
||||
current_values = join_row(scalar_values, vector_values, i)
|
||||
|
||||
central_value[i] = self._parsed_lambda(**current_values)
|
||||
else:
|
||||
central_value = self._dtype(self._parsed_lambda(**scalar_values))
|
||||
|
@ -204,22 +203,24 @@ class SecondaryValue:
|
|||
|
||||
return terms
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
def __call__(self, *args, retdeps=False, **kwargs):
|
||||
"""Calculates a value from the expression by substituting
|
||||
variables by the values of the given keyword arguments. If an
|
||||
argument is specified as a tuplpe of (value, error) the
|
||||
gausssian error propagation will be computed.
|
||||
|
||||
The values and errors can be iterable, but must compatible shapes.
|
||||
The values and errors can be iterable, but must compatible
|
||||
shapes.
|
||||
|
||||
:returns: value or [value, error] or [value, error], dependencies
|
||||
:param retdeps: wether to return a dictionary with the
|
||||
calculated dependencies
|
||||
|
||||
:returns: value or [value, error] or [value, error, ...],
|
||||
dependencies
|
||||
|
||||
:rtype: numpy data type or np array of [value, errors, ...] or
|
||||
a tuple the beforementioned as first element and a
|
||||
dictionary with the calculated dependencies as a second value
|
||||
dictionary with the calculated dependencies as a
|
||||
second value
|
||||
"""
|
||||
|
||||
# process the keyword arguments
|
||||
# process the keyword arguments
|
||||
values, errors, dep_values = self._process_args(*args, **kwargs)
|
||||
|
||||
# calulate the central value
|
||||
|
@ -237,7 +238,7 @@ class SecondaryValue:
|
|||
result.insert(0, central_value)
|
||||
result = tuple(result)
|
||||
|
||||
if dep_values:
|
||||
if retdeps:
|
||||
return result, dep_values
|
||||
|
||||
return result
|
||||
|
@ -293,5 +294,5 @@ def filter_out_vecotrized(dictionary):
|
|||
return scalar, vector
|
||||
|
||||
def join_row(scalar, vector, index):
|
||||
return {**scalar, **{key: val[index] \
|
||||
for key, val in vector.items()}}
|
||||
return {**scalar, **{key: val[index] \
|
||||
for key, val in vector.items()}}
|
||||
|
|
2
setup.py
2
setup.py
|
@ -6,7 +6,7 @@ def readme():
|
|||
return f.read()
|
||||
|
||||
setup(name='SecondaryValue',
|
||||
version='0.1.3',
|
||||
version='0.1.4',
|
||||
description='A helper to calculate the gaussian error propagation.',
|
||||
long_description=readme(),
|
||||
long_description_content_type='text/markdown',
|
||||
|
|
Loading…
Add table
Reference in a new issue