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
|
# used if present. This may be useful to calculate statistical and systemic
|
||||||
# errors in one go.
|
# errors in one go.
|
||||||
print(result)
|
print(result)
|
||||||
# >> array([ 1.41421356, 35.35533906])
|
# >> (1.41421356, 35.35533906)
|
||||||
|
|
||||||
# As a goodie, you can print out the gaussian error distribution in
|
# As a goodie, you can print out the gaussian error distribution in
|
||||||
# symbolic form. (Works best in Jupyter Notebooks)
|
# 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))
|
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
|
### Dependencies
|
||||||
To make the calculation of complex values easier, one can define
|
To make the calculation of complex values easier, one can define
|
||||||
dependencies for a `SecondaryValue`:
|
dependencies for a `SecondaryValue`:
|
||||||
|
@ -90,14 +94,22 @@ dependencies for a `SecondaryValue`:
|
||||||
from SecondaryValue import SecondaryValue
|
from SecondaryValue import SecondaryValue
|
||||||
|
|
||||||
dep = SecondaryValue('u')
|
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
|
# 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)))
|
print(x(b=1, u=(1, 2)))
|
||||||
# >> (array([2., 2.]), {'a': array([1., 2.])})
|
# >> (2.0, 2.0)
|
||||||
|
|
||||||
# you can overwrite the dependency calculation
|
# you can overwrite the dependency calculation
|
||||||
print(x(b=1/2, a=1/2))
|
print(x(b=1/2, a=1/2))
|
||||||
# >> 1.0
|
# >> 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:
|
if name in kwargs:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tmp = sec_val(**kwargs)
|
# we always calculate the depndencies
|
||||||
kwargs[name] = tmp[0] if (len(tmp) > 1 and isinstance(tmp, tuple)) \
|
tmp = sec_val(retdeps=True, **kwargs)
|
||||||
else tmp
|
kwargs[name] = tmp[0]
|
||||||
calc_deps[name] = tmp
|
calc_deps[name] = tmp
|
||||||
|
|
||||||
return kwargs, calc_deps
|
return kwargs, calc_deps
|
||||||
|
@ -111,6 +111,7 @@ class SecondaryValue:
|
||||||
dep_values (the values and errors of the dependencies)
|
dep_values (the values and errors of the dependencies)
|
||||||
|
|
||||||
:rtype: Tuple
|
:rtype: Tuple
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
kwargs, dep_values = self._calc_deps(**kwargs)
|
kwargs, dep_values = self._calc_deps(**kwargs)
|
||||||
|
@ -125,7 +126,6 @@ class SecondaryValue:
|
||||||
kwargs = {var: val for var, val in kwargs.items() \
|
kwargs = {var: val for var, val in kwargs.items() \
|
||||||
if var in self._symbols}
|
if var in self._symbols}
|
||||||
|
|
||||||
|
|
||||||
max_uncertainties = max([len(val) for _, val in kwargs.items() \
|
max_uncertainties = max([len(val) for _, val in kwargs.items() \
|
||||||
if isinstance(val, Iterable)] or [0])
|
if isinstance(val, Iterable)] or [0])
|
||||||
|
|
||||||
|
@ -158,7 +158,6 @@ class SecondaryValue:
|
||||||
central_value = np.empty(value_length)
|
central_value = np.empty(value_length)
|
||||||
for i in range(0, value_length):
|
for i in range(0, value_length):
|
||||||
current_values = join_row(scalar_values, vector_values, i)
|
current_values = join_row(scalar_values, vector_values, i)
|
||||||
|
|
||||||
central_value[i] = self._parsed_lambda(**current_values)
|
central_value[i] = self._parsed_lambda(**current_values)
|
||||||
else:
|
else:
|
||||||
central_value = self._dtype(self._parsed_lambda(**scalar_values))
|
central_value = self._dtype(self._parsed_lambda(**scalar_values))
|
||||||
|
@ -204,22 +203,24 @@ class SecondaryValue:
|
||||||
|
|
||||||
return terms
|
return terms
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, retdeps=False, **kwargs):
|
||||||
"""Calculates a value from the expression by substituting
|
"""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
|
:rtype: numpy data type or np array of [value, errors, ...] or
|
||||||
a tuple the beforementioned as first element and a
|
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)
|
values, errors, dep_values = self._process_args(*args, **kwargs)
|
||||||
|
|
||||||
# calulate the central value
|
# calulate the central value
|
||||||
|
@ -237,7 +238,7 @@ class SecondaryValue:
|
||||||
result.insert(0, central_value)
|
result.insert(0, central_value)
|
||||||
result = tuple(result)
|
result = tuple(result)
|
||||||
|
|
||||||
if dep_values:
|
if retdeps:
|
||||||
return result, dep_values
|
return result, dep_values
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -293,5 +294,5 @@ def filter_out_vecotrized(dictionary):
|
||||||
return scalar, vector
|
return scalar, vector
|
||||||
|
|
||||||
def join_row(scalar, vector, index):
|
def join_row(scalar, vector, index):
|
||||||
return {**scalar, **{key: val[index] \
|
return {**scalar, **{key: val[index] \
|
||||||
for key, val in vector.items()}}
|
for key, val in vector.items()}}
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -6,7 +6,7 @@ def readme():
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
setup(name='SecondaryValue',
|
setup(name='SecondaryValue',
|
||||||
version='0.1.3',
|
version='0.1.4',
|
||||||
description='A helper to calculate the gaussian error propagation.',
|
description='A helper to calculate the gaussian error propagation.',
|
||||||
long_description=readme(),
|
long_description=readme(),
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
|
|
Loading…
Add table
Reference in a new issue