def __setattr__(self, name, value): if self._has_terms() and name in self._super_get('_plural'): # get the total number of arguments size = np.atleast_1d(flatten(getattr(self, name))).size # check shapes if isiterable(value): value = flatten(value) if len(value) != size: raise ValueError('Expected {} to have length {}, but found {} = {}'\ .format(name, size, name, value)) else: value = [value] * size # now set each term's sequence of arguments for term in self._get_terms()[::-1]: # skip intercept if term.isintercept: continue # how many values does this term get? n = np.atleast_1d(getattr(term, name)).size # get the next n values and set them on this term vals = [value.pop() for _ in range(n)][::-1] setattr(term, name, vals[0] if n == 1 else vals) term._validate_arguments() return super(MetaTermMixin, self).__setattr__(name, value)
def test_tensor_term_expands_args_to_match_penalties_and_terms(): tensor = te(0, 1, lam=3) assert len(tensor.lam) == 2 assert len(flatten(tensor.lam)) == 2 tensor = te(0, 1, penalties='auto') assert len(tensor.lam) == 2 assert len(flatten(tensor.lam)) == 2 tensor = te(0, 1, penalties=['auto', ['auto', 'auto']]) assert len(tensor.lam) == 2 assert len(flatten(tensor.lam)) == 3
def nice_repr(name, param_kvs, line_width=30, line_offset=5, decimals=3, args=None, flatten_attrs=True): """ tool to do a nice repr of a class. Parameters ---------- name : str class name param_kvs : dict dict containing class parameters names as keys, and the corresponding values as values line_width : int desired maximum line width. default: 30 line_offset : int desired offset for new lines default: 5 decimals : int number of decimal places to keep for float values default: 3 Returns ------- out : str nicely formatted repr of class instance """ if not param_kvs and not args : # if the object has no params it's easy return '{}()'.format(name) # sort keys and values ks = list(param_kvs.keys()) vs = list(param_kvs.values()) idxs = np.argsort(ks) param_kvs = [(ks[i],vs[i]) for i in idxs] if args is not None: param_kvs = [(None, arg) for arg in args] + param_kvs param_kvs = param_kvs[::-1] out = '' current_line = name + '(' while len(param_kvs) > 0: # flatten sub-term properties, but not `terms` k, v = param_kvs.pop() if flatten_attrs and k != 'terms': v = flatten(v) # round the floats first if issubclass(v.__class__, (float, np.ndarray)): v = round_to_n_decimal_places(v, n=decimals) v = str(v) else: v = repr(v) # handle args if k is None: param = '{},'.format(v) else: param = '{}={},'.format(k, v) # print if len(current_line + param) <= line_width: current_line += param else: out += current_line + '\n' current_line = ' '*line_offset + param if len(current_line) < line_width and len(param_kvs) > 0: current_line += ' ' out += current_line[:-1] # remove trailing comma out += ')' return out