def asqarray(array_like): """The value returned will always be a Quantity with array value""" if isinstance(array_like, list): if isinstance(array_like[0], Quantity): dim = array_like[0].dimension val_list = [] for q in array_like: if q.dimension == dim: val_list.append(q.value) res_val = np.array(val_list) else: raise DimensionError(q.dim, dim) return Quantity(res_val, dim) else: return quantify(array_like) elif isinstance(array_like, np.ndarray): if isinstance(array_like[0], Quantity): dim = array_like[0].dimension val_list = [] for q in array_like: if q.dimension == dim: val_list.append(q.value) res_val = np.array(val_list) else: raise DimensionError(q.dim, dim) return Quantity(res_val, dim) else: return quantify(array_like) else: raise ValueError("Type {type(array_like)} not supported")
def __init__(self, *args, min=None, max=None, cb_for_init=None, **kwargs): self._callbacks = [] if cb_for_init is not None: self._callbacks.append(cb_for_init) dim = args[1] if min is None: min_v = 0 min = Quantity(min_v, dim) else: min = quantify(min) if max is None: max_v = 100 max = Quantity(max_v, dim) else: max = quantify(max) if not min.dimension == max.dimension: raise DimensionError(min.dimension, max.dimension) if not dim == max.dimension: raise DimensionError(min.dimension, max.dimension) self.min_value = min.value self.max_value = max.value #self.value = args[0] super().__init__(*args, **kwargs)
def func_value(z_value, y_value, x_value, *args): x = Quantity(x_value, x0.dimension) y = Quantity(y_value, y0.dimension) z = Quantity(z_value, z0.dimension) res_raw = func(z, y, x, *args) raw = quantify(res_raw) return raw.value
def update_label_on_slider_change(change): new_left, new_right = change.new self.value_left = Quantity(new_left, self.dimension, favunit=self.favunit) self.value_right = Quantity(new_right, self.dimension, favunit=self.favunit) self.value = self.value_left, self.value_right self.label.value = str(self.value_left) + "-" + str( self.value_right)
def normal(loc=0.0, scale=1.0, size=None): loc = quantify(loc) scale = quantify(scale) if not loc.dimension == scale.dimension: raise DimensionError(loc.dimension, scale.dimension) samples = np.random.normal(loc=loc.value, scale=scale.value, size=size) return Quantity(samples, loc.dimension)
def uniform(low=0.0, high=1.0, size=None): low = quantify(low) high = quantify(high) if not low.dimension == high.dimension: raise DimensionError(low.dimension, high.dimension) samples = np.random.normal(low=low.value, high=high.value, size=size) return Quantity(samples, low.dimension)
def dblquad(func, x0, x1, y0, y1, *oargs, args=(), **kwargs): x0 = quantify(x0) x1 = quantify(x1) y0 = quantify(y0) y1 = quantify(y1) if not x0.dimension == x1.dimension: raise DimensionError(x0.dimension, x1.dimension) if not y0.dimension == y1.dimension: raise DimensionError(y0.dimension, y1.dimension) res = func(y0, x0, *args) res = quantify(res) res_dim = res.dimension def func_value(y_value, x_value, *args): x = Quantity(x_value, x0.dimension) y = Quantity(y_value, y0.dimension) res_raw = func(y, x, *args) raw = quantify(res_raw) return raw.value dblquad_value, prec = scipy.integrate.dblquad(func_value, x0.value, x1.value, y0.value, y1.value, *oargs, **kwargs) return Quantity(dblquad_value, res_dim * x0.dimension * y0.dimension).rm_dim_if_dimless(), prec
def quad(func, x0, x1, *oargs, args=(), **kwargs): """A wrapper on scipy.integrate.quad : - will check dimensions of x0 and x1 bounds - returned value's dimension is infered by calling func(x0) """ # Cast x bounds in Quantity and check dimension x0 = quantify(x0) x1 = quantify(x1) if not x0.dimension == x1.dimension: raise DimensionError(x0.dimension, x1.dimension) # Get output dimension res = func(x0, *args) res = quantify(res) res_dim = res.dimension # define a float-version for inputs and outputs def func_value(x_value, *oargs): # cast back in Quantity x = Quantity(x_value, x0.dimension) # compute Quantity result res_raw = func(x, *args) raw = quantify(res_raw) # return float-value return raw.value # compute integral with float-value version quad_value, prec = scipy.integrate.quad(func_value, x0.value, x1.value, *oargs, **kwargs) # cast back in Quantity with dimension f(x)dx return Quantity(quad_value, res_dim * x0.dimension).rm_dim_if_dimless(), prec
def func_value(x_value, *oargs): # cast back in Quantity x = Quantity(x_value, x0.dimension) # compute Quantity result res_raw = func(x, *args) raw = quantify(res_raw) # return float-value return raw.value
def root(func_cal, start, args=(), **kwargs): start = quantify(start) start_val = start.value start_dim = start.dimension def func_cal_float(x_float): q = Quantity(x_float, start_dim) return func_cal(q, *args) res = scipy.optimize.root(func_cal_float, start_val, **kwargs).x[0] return Quantity(res, start_dim)
def func_value(t_value, Y_value): # add back the units t = Quantity(t_value, t_span[0].dimension) if not_scalar: Y = np.array([ Quantity(y_value, y0.dimension) for y_value, y0 in zip(Y_value, Y0) ], dtype=object) else: Y = Quantity(Y_value, Y0[0].dimension) # compute with units res_raw = fun(t, Y) # extract the numerical value if not_scalar: raw = np.array([quantify(r) for r in res_raw], dtype=object) raw_value = np.array([r.value for r in raw]) else: raw_value = quantify(res_raw).value return raw_value
def list_of_Q_to_Q_array(Q_list): """Convert list of Quantity's object to a Quantity with array value. All Quantity must have the same dimension.""" first = quantify(Q_list[0]) dim = first.dimension val_list = [] for q in Q_list: q = quantify(q) if q.dimension == dim: val_list.append(q.value) else: raise ValueError return Quantity(np.array(val_list), dim)
def __init__(self, dimension=None, all_units=False, **kwargs): super().__init__(**kwargs) self.dimension = dimensionify(dimension) self.units = units self.units["-"] = Quantity(1, Dimension(None), symbol="-") # list of available units if self.dimension == Dimension(None) or all_units: self.favunit_str_list = [ u_str for u_str, u_q in self.units.items() ] else: self.favunit_str_list = [ u_str for u_str, u_q in self.units.items() if self.dimension == u_q.dimension ] self.favunit_str_list.append("-") self.value = self.units["-"] # dropdown self.favunit_dd = ipyw.Dropdown( options=self.favunit_str_list, # set init value value=str(self.value.symbol), description='Favunit:', layout=Layout(width="30%", margin="5px 5px 5px 5px", border="solid black"), ) self.children = [self.favunit_dd] ### 3. Change favunit # selection of favunit def update_favunit_on_favunit_dd_change(change): # retrieve new favunit q self.value = self.units[change.new] self.favunit_dd.observe(update_favunit_on_favunit_dd_change, names="value") def update_dd_value(change): self.favunit_dd.value = str(change.new.symbol) self.observe(update_dd_value, names="value")
def brentq(func_cal, start, stop, *oargs, args=(), **kwargs): start = quantify(start) stop = quantify(stop) if not start.dimension == stop.dimension: raise DimensionError(start.dimension, stop.dimension) start_val = start.value start_dim = start.dimension stop_val = stop.value def func_float(x): res = func_cal(Quantity(x, start_dim), *args) return quantify(res).value res = scipy.optimize.brentq(func_float, start_val, stop.value, *oargs) return Quantity(res, start_dim)
def tplquad(func, x0, x1, y0, y1, z0, z1, *args): x0 = quantify(x0) x1 = quantify(x1) y0 = quantify(y0) y1 = quantify(y1) z0 = quantify(z0) z1 = quantify(z1) if not x0.dimension == x1.dimension: raise DimensionError(x0.dimension, x1.dimension) if not y0.dimension == y1.dimension: raise DimensionError(y0.dimension, y1.dimension) if not z0.dimension == z1.dimension: raise DimensionError(z0.dimension, z1.dimension) res = func(z0, y0, x0, *args) res = quantify(res) res_dim = res.dimension def func_value(z_value, y_value, x_value, *args): x = Quantity(x_value, x0.dimension) y = Quantity(y_value, y0.dimension) z = Quantity(z_value, z0.dimension) res_raw = func(z, y, x, *args) raw = quantify(res_raw) return raw.value tplquad_value, prec = scipy.integrate.tplquad(func_value, x0.value, x1.value, y0.value, y1.value, z0.value, z1.value, args=args) return Quantity(tplquad_value, res_dim * x0.dimension * y0.dimension * z0.dimension).rm_dim_if_dimless(), prec
def solve_ivp(fun, t_span, Y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, args=None, **options): not_scalar = len(Y0) > 1 # first, quantify everything that could be quantity tstart, tstop = t_span t_span = quantify(tstart), quantify(tstop) if not t_span[0].dimension == t_span[1].dimension: print("error of dimension") if not_scalar: Y0 = np.array([quantify(y) for y in Y0], dtype=object) else: Y0 = [quantify(y) for y in Y0] if t_eval is not None: t_eval = quantify(t_eval) t_span_value = t_span[0].value, t_span[1].value Y0_value = [y.value for y in Y0] if t_eval is not None: t_eval_value = t_eval.value else: t_eval_value = None # second : rewrite everything without units def func_value(t_value, Y_value): # add back the units t = Quantity(t_value, t_span[0].dimension) if not_scalar: Y = np.array([ Quantity(y_value, y0.dimension) for y_value, y0 in zip(Y_value, Y0) ], dtype=object) else: Y = Quantity(Y_value, Y0[0].dimension) # compute with units res_raw = fun(t, Y) # extract the numerical value if not_scalar: raw = np.array([quantify(r) for r in res_raw], dtype=object) raw_value = np.array([r.value for r in raw]) else: raw_value = quantify(res_raw).value return raw_value # compute numerical solution sol = scipy.integrate.solve_ivp(func_value, t_span_value, Y0_value, method=method, t_eval=t_eval_value, dense_output=dense_output, events=events, vectorized=vectorized, args=args, **options) # "decorate" the solution with units sol.t = Quantity(sol.t, t_span[0].dimension) if not_scalar: soly_q = [] for y_value, y0 in zip(sol.y, Y0): soly_q.append(Quantity(y_value, y0.dimension)) arr_q = soly_q #np.array(soly_q, dtype=object) sol.y = arr_q else: sol.y = Quantity(sol.y, Y0[0].dimension) func_sol = sol.sol # for some reason the solution accepts 0*s as well as 0 @check_dimension(t_span[0].dimension) def sol_q(t): return Quantity(func_sol(t), Y0[0].dimension) #/t_span[0].dimension) sol.sol = sol_q return sol
# # %% [markdown] # ## Creation # Basic creation of dimension-full arrays : # %% import matplotlib.pyplot as plt import numpy as np import physipy from physipy import m, s, Quantity, Dimension, rad # %% x_samples = np.array([1, 2, 3, 4]) * m y_samples = Quantity(np.array([1, 2, 3, 4]), Dimension("T")) print(x_samples) print(y_samples) print(m * np.array([1, 2, 3, 4]) == x_samples) # multiplication is commutativ # %% [markdown] # ## Operation # Basic array operation are handled the 'expected' way : note that the resulting dimension are consistent with the operation applied : # %% print(x_samples + 1 * m) print(x_samples * 2) print(x_samples**2) print(1 / x_samples) # %% [markdown]
print(z / 2) #print(2//z) #print(z//2) # %% [markdown] # # Support with physipy # %% import physipy from physipy import m, cd, s, Quantity, Dimension # %% [markdown] # ## Construction # %% x = Quantity(mcerp.Normal(1, 2), Dimension("L")) x # %% # using multiplication # x = mcerp.Normal(1, 2)*s : NotUpcast: <class 'physipy.quantity.quantity.Quantity'> cannot be converted to a number with uncertainty x = m * mcerp.Normal(1, 2) x # %% [markdown] # ## Basic Operation # %% # with scalar scalar = 2 * m print(x + scalar)
def __init__( self, value=None, min=None, max=None, step=None, disabled=False, continuous_update=True, description="Quantity:", fixed_dimension=False, label=True, favunit=None, #placeholder="Type python expr", **kwargs): super().__init__(**kwargs) # quantity work # set dimension if value is not None: value = quantify(value) elif min is not None: value = min * 1 # to reset favunit else: value = 0.0 self.dimension = value.dimension # if true, any change in value must have same dimension as initial dimension self.fixed_dimension = fixed_dimension # set quantity self.value = value if favunit is None: self.favunit = value._pick_smart_favunit() else: self.favunit = favunit self.value.favunit = self.favunit # validate min if min is not None: qmin = quantify(min) if not qmin.dimension == self.value.dimension: raise DimensionError(qmin.dimension, self.value.dimension) else: qmin = Quantity(0.0, self.value.dimension) # validate max value if max is not None: qmax = quantify(max) if not qmax.dimension == self.value.dimension: raise DimensionError(qmax.dimension, self.value.dimension) else: qmax = Quantity(100.0, self.value.dimension) # validate step value if step is not None: qstep = quantify(step) if not qstep.dimension == self.value.dimension: raise DimensionError(qstep.dimension, self.value.dimension) else: qstep = Quantity(0.1, self.value.dimension) self.qstep = qstep self.qmin = qmin self.qmax = qmax # set slider widget self.slider = ipyw.FloatSlider( value=self.value.value, min=self.qmin.value, max=self.qmax.value, step=self.qstep.value, description=description, disabled=disabled, continuous_update=continuous_update, #orientation=orientation, readout=False, # to disable displaying readout value #readout_format=readout_format, #layout=Layout(width="50%", # margin="0px", # border="solid red"), ) # observe slider value : for interaction with the widget def update_label_on_slider_change(change): self.value = Quantity(change.new, self.value.dimension, favunit=self.favunit) self.label.value = str(self.value) self.slider.observe(update_label_on_slider_change, names="value") # observe self.value : when using the OOP interaction def update_slider_value(change): self.slider.value = change.new.value self.observe(update_slider_value, names="value") # display the quantity value of the slider in label self.label = ipyw.Label(value=str(self.value)) if label: self.children = [ self.slider, self.label, ] else: self.children = [ self.slider, ]
np.iterable(m) # %% type(m.value) # %% iter(m) # %% [markdown] tags=[] # ## Array repr with 0 value # Pick best favunit take the smallest when 0 is in the array with positiv and negativ values # %% from physipy import m, Quantity, Dimension import numpy as np Quantity(np.array([0, -1.2, 1.2]), Dimension("L")) # %% [markdown] # # Inplace change using asqarray # %% from physipy.quantity.utils import asqarray print(type(m.value)) arrq_9 = np.array([m.__copy__()], dtype=object) out = asqarray(arrq_9) # this changes the type of m value print(type(m.value)) # %% [markdown] # # Numpy trapz implementaion not called when only x or dx is a quantity
def decorated(x, y): x = quantify(x) y = quantify(y) if not x.dimension == y.dimension: raise DimensionError(x.dimension, y.dimension) return Quantity(math_func(x.value, y.value), x.dimension)
def decorated(x): x = quantify(x) return Quantity(math_func(x.value), x.dimension)
def sqrt(x): x = quantify(x) return Quantity(math.sqrt(x.value), x.dimension**0.5)
def copysign(x, y): x = quantify(x) y = quantify(y) return Quantity(math.copysign(x.value, y.value), x.dimension)
def sol_q(t): return Quantity(func_sol(t), Y0[0].dimension) #/t_span[0].dimension)
def func_float(x): res = func_cal(Quantity(x, start_dim), *args) return quantify(res).value
def __init__( self, min=None, max=None, step=None, disabled=False, continuous_update=True, description="Quantity:", fixed_dimension=False, label=True, #placeholder="Type python expr", favunit=None, **kwargs): """ kwargs are passed to Box. """ super().__init__(**kwargs) # quantity work # set dimension value = quantify(min) self.favunit = value.favunit or favunit self.dimension = value.dimension # if true, any change in value must have same dimension as initial dimension self.fixed_dimension = fixed_dimension qmin = quantify(min) qmax = quantify(max) qstep = Quantity(0.1, qmin.dimension) # set quantity self.value_left = qmin self.value_right = qmax self.qstep = qstep self.qmin = qmin self.qmax = qmax self.value = self.qmin, self.qmax # set text widget self.rslider = ipyw.FloatRangeSlider( value=[self.value_left.value, self.value_right.value], min=self.qmin.value, max=self.qmax.value, step=self.qstep.value, description=description, disabled=disabled, continuous_update=continuous_update, #orientation=orientation, readout=False, # to disable displaying readout value #readout_format=readout_format, #layout=Layout(width="50%", # margin="0px", # border="solid red"), ) def update_label_on_slider_change(change): new_left, new_right = change.new self.value_left = Quantity(new_left, self.dimension, favunit=self.favunit) self.value_right = Quantity(new_right, self.dimension, favunit=self.favunit) self.value = self.value_left, self.value_right self.label.value = str(self.value_left) + "-" + str( self.value_right) self.rslider.observe(update_label_on_slider_change, names="value") #def update_slider_value(change): # self.slider.value = change.new.value #self.observe(update_slider_value, names="value") # display the quantity value of the slider in label self.label = ipyw.Label(value=str(self.value_left) + "-" + str(self.value_right)) # todo : add callback to update frontend on value change def update_slider_value(change): self.rslider.value = change.new[0].value, change.new[1].value self.observe(update_slider_value, names="value") if label: self.children = [ self.rslider, self.label, ] else: self.children = [ self.rslider, ]
"perm": (perm, a), "pow": (math_pow, (a, 2)), "prod": (prod, [a, a]), "radians": (radians, a), "remainder": (remainder, (a, b)), "sin": (sin, a), "sinh": (sinh, a), "sqrt": (sqrt, a), "tan": (tan, a), "tanh": (tanh, a), "trunc": (trunc, a), } q_rad = 0.4 * rad q = 2.123 * m q_dimless = Quantity(1, Dimension(None)) physipy_math_params = { "acos": (physipy.math.acos, q_dimless), "acosh": (physipy.math.acosh, q_dimless), "asin": (physipy.math.asin, q_dimless), "asinh": (physipy.math.asinh, q_dimless), "atan": (physipy.math.atan, q_dimless), "atan2": (physipy.math.atan2, (q, q)), "atanh": (physipy.math.atanh, q_dimless), "ceil": (physipy.math.ceil, q), "coysign": (physipy.math.copysign, (q, q)), #"comb" :(comb , 10, 3), "cos": (physipy.math.cos, q), "cosh": (physipy.math.cosh, q), "degrees": (physipy.math.degrees, q),
def update_label_on_slider_change(change): self.value = Quantity(change.new, self.value.dimension, favunit=self.favunit) self.label.value = str(self.value)
def func_cal_float(x_float): q = Quantity(x_float, start_dim) return func_cal(q, *args)