def __init__ (self, *args): # {{{ from pygeode.tools import combine_axes from pygeode.var import combine_meta import numpy as np assert self.op is not None, "can't instantiate UfuncVar directly" ivars = [i for i,v in enumerate(args) if isinstance(v, Var)] vars = [args[i] for i in ivars] axes = combine_axes(vars) self.args = args self.ivars = ivars # dtype = common_dtype(args) # create some dummy scalar args to test the dtype dummy_dtypes = ['int64' if isinstance(a,(int, long)) else 'float64' if isinstance(a,float) else 'complex128' if isinstance(a,complex) else a.dtype for a in args] dummy_args = [np.array(1,dtype=d) for d in dummy_dtypes] dtype = self.op(*dummy_args).dtype # TODO: Type check arguments. numpy arrays probably shouldn't be allowed # Generate a default name symbol = self.symbol names = [(arg.name or '??') if isinstance(arg,Var) else str(arg) for arg in args] # Strip out parentheses if there's only one name? if len(names) == 1: if names[0].startswith('(') and names[0].endswith(')'): names[0] = names[0][1:-1] if symbol is None: name = self.op.__name__ + '(' + ','.join(names) + ')' elif isinstance(symbol,(list,tuple)): assert len(names) == 1 name = symbol[0] + names[0] + symbol[1] else: assert isinstance(symbol, str) name = '(' + symbol.join(names) + ')' # Special case: applying a scalar to a Var object with a simple name. # In this case, keep the original name. if len(args) == 2 and len(vars) == 1: # One scalar, one var if '(' not in vars[0].name and ')' not in vars[0].name: if self.symbol in ('+','-','*','/'): # Basic arithmetic only name = vars[0].name # # Copy any common generic metadata # self.atts = common_dict(v.atts for v in vars) # self.plotatts = common_dict(v.plotatts for v in vars) Var.__init__(self, axes, dtype=dtype) # Copy any common generic metadata combine_meta(vars, self) # Use our locally derived name (override combine_meta) self.name = name
def __init__(self, vars, iaxis=None): import pygeode.axis from pygeode.tools import common_dtype from pygeode.var import combine_meta import numpy as np # Use first var segment for the axes axes = list(vars[0].axes) naxes = len(axes) # For now, assume all segments have the same order of axes assert all(v.naxes == naxes for v in vars) for i in range(naxes): assert all(axes[i].isparentof(v.axes[i]) for v in vars) if iaxis is None: iaxis = set(i for v in vars for i in range(naxes) if v.axes[i] not in axes) assert len(iaxis) <= 1, "more than one varying axis id=%s for %s; can't concatenate"%(iaxis,repr(vars[0])) # Degenerate case: all segments have identical axes if len(iaxis) == 0: from warnings import warn warn ('all axes are identical. Creating a fake "concat" axis', stacklevel=2) iaxis = naxes axes.append(pygeode.axis.NamedAxis(len(vars), name='concat')) # Standard case: exactly one concatenation axis else: iaxis = iaxis.pop() if not iaxis is naxes: # Get a numerical dimension number iaxis = vars[0].whichaxis(iaxis) # Update the list of axes with the concatenated axis included values = [v.axes[iaxis].values for v in vars] values = np.concatenate(values) axes[iaxis] = axes[iaxis].withnewvalues(values) # Get the data type dtype = common_dtype(vars) Var.__init__(self, axes, dtype=dtype) # Grab metadata from the input variables combine_meta (vars, self) # # Assign a name (and other attributes??) to the var # name = set(v.name for v in vars if v.name != '') # if len(name) == 1: self.name = name.pop() # # # Combine the attributes (if applicable) # atts = common_dict([v.atts for v in vars]) # self.atts = atts # # Combine the plot attributes (if applicable) # plotatts = common_dict([v.plotatts for v in vars]) # self.plotatts = plotatts # Other stuff self.vars = vars self.iaxis = iaxis