def __myGetAxisWeights(x, i, axisoptions=None): """ Assume x is an MV2 duh! and get the weights associated with axis index i. index i can be any of the dimensions in x whose bounds are available. If bounds are not available then an error is raised. """ if x.getAxis(i).isLatitude(): Lataxis = x.getAxis(i) xgr = cdms2.createGenericGrid(Lataxis[:], numpy.array(range(1), numpy.float), latBounds=Lataxis.getBounds()) xlatwt, xlonwt = xgr.getWeights() return xlatwt elif x.getAxis(i).isLongitude(): Lonaxis = x.getAxis(i) xgr = cdms2.createGenericGrid(numpy.array(range(1), numpy.float), Lonaxis[:], lonBounds=Lonaxis.getBounds()) xlatwt, xlonwt = xgr.getWeights() return xlonwt else: axis_bounds = x.getAxis(i).getBounds() if axis_bounds is None: ax=x.getAxis(i) if axisoptions is not None: axo=cdms2.orderparse(axisoptions) if (i in axo ) or (ax.isTime() and 't' in axo) or (ax.isLevel() and 'z' in axo) or ('('+ax.id+')' in axo): raise AveragerError, 'Bounds not available to compute weights on dimension: '+ax.id else: axis_wts=numpy.ones(x.getAxis(i)[:].shape) else: raise AveragerError, 'Bounds not available to compute weights for dimension: '+ax.id else: axis_wts = abs(axis_bounds[..., 1] - axis_bounds[..., 0]) return axis_wts
def _check_axisoptions(x, axisoptions): """checks the axis=options to make sure that it is valid""" axlist = cdms2.orderparse(axisoptions) if Ellipsis in axlist: raise AveragerError, 'Error: Ellipsis (...) not allowed in axis options' try: cdms2.order2index(x.getAxisList(), axisoptions) return axlist except: raise AveragerError, 'Error: You have specified an invalid axis= option.'
def check_order(var, allowed, vertical=None, copy=False, reorder=False, extended=None, getorder=False): """Check that the axis order of a variable is matches at least one the specifed valid orders :Params: - **var**: MV2 array. - **allowed**: A single order string or a list. It should contain one or several of these letters: - ``x``: longitudes, - ``y``: latitudes, - ``z``: vertical levels, - ``t``: time axis, - ``d``: data values (ignored), - ``-``: any kind of axis. :Return: ``var``, or ``var, order, reordered`` if **reorder** is True. """ # Check allowed orders # - consistency if not isinstance(allowed, (list, tuple)): allowed = [allowed] else: allowed = list(allowed) withd = 'd' in allowed[0] get_rank = lambda o: len(o.replace('d', '')) rank = get_rank(allowed[0]) for order in allowed: try: cdms2.orderparse(order.lower().replace('d', '')) except: raise VACUMMError("Wrong allowed order: "+order) if ('d' in order and not withd) or ('d' not in order and withd): raise VACUMMError("'d' only partially present in allowed order: %s"%allowed) if get_rank(order)!=rank: raise VACUMMError("Inconsistent ranks between allowed orders: %s"%[get_rank(o) for o in allowed]) # - check extended mode if extended is None: # extended? re_upper = re.compile('[XYZT]').search for order in allowed: if re_upper(order) is not None: extended = True # force extended mode break else: extended = False if extended is False: # lower allowed = [order.lower() for order in allowed] else: #add tolerance for lower case orders re_sub = re.compile('[xyzt]').sub allowed = allowed+[re_sub('-', order) for order in allowed] # - unique and lower case _, idx = N.unique(allowed, return_index=True) idx = N.sort(idx) allowed = N.array(allowed)[idx].tolist() # - restrict to vertical or horizontal (1D data only) if vertical is not None and len(allowed[0])==2: allowed = [oo for oo in allowed if oo[int(vertical)]=='d'] # Data order data_cdms_order = get_order(var) # Loop on allowed orders from vacumm.misc.grid.misc import get_axis, var2d reordered = False for allowed_order in allowed: # Handle data case d = allowed_order.find('d') if d!=-1: allowed_order = allowed_order.replace('d', '') # pure axis # Check cdms order allowed_cdms_order = allowed_order.lower() # lower case if order_match(data_cdms_order, allowed_cdms_order, strict='right'): break # It is already good # Try to reorder if reorder: try: reordered = cdms2.order2index(var.getAxisList(), allowed_cdms_order) new_var = var.reorder(allowed_cdms_order) if allowed_cdms_order[-1]=='x' and len(get_axis(new_var, -1).shape)==2: # 2D axes del var var = var2d(new_var, MV2.transpose(get_axis(new_var, 0)), MV2.transpose(get_axis(new_var, -1)), copy=0) set_order(new_var, allowed_cdms_order) else: del var var = new_var data_cdms_order = get_order(var) break # No error so it worked and we leave except: continue else: raise VACUMMError('Wrong type of axes. Possible forms are: %s'%', '.join(allowed)) if not getorder: return var if d!=-1: data_cdms_order = cdms2.orderparse(data_cdms_order) data_cdms_order.insert(d, 'd') data_cdms_order = ''.join(data_cdms_order) return var, data_cdms_order, reordered
def __check_weightoptions(x, axisoptions, weightoptions): """ Checks the weights=options to make sure that it is valid. Default: 'weighted' weight options are one of 'weighted', 'unweighted', an array of weights for each dimension or a MaskedVariable of the same shape as the data x. - 'weighted' means use the grid information to generate weights for that dimension or if multiple axes are passed, generate goes ahead and generates the full masked area weights. - 'unweighted' means use equal weights for all the grid points in that axis. - Also an array of weights (of the same shape as the dimension being averaged over or same shape as V) can be passed. """ # # Since the _check_axisoptions was passed, the variable x has already been reordered # to the required order..... check it anyway. # # __DEBUG__ = 0 # if __DEBUG__: print 'Axis options entering __check_weightoptions = ', axisoptions # axisindex = cdms2.order2index(x.getAxisList(), axisoptions) if __DEBUG__: print 'This should be 0,1,2... etc. is it? ', axisindex # axislist = cdms2.orderparse(axisoptions) if __DEBUG__: print 'axislist = ', axislist # if not isinstance(weightoptions, types.ListType): # # We have either 1 axis only or multiple axes and one MV2 of weights # if MV2.isMaskedVariable(weightoptions): # # Weight passed is an MV2. Probably OK # try: # We had required that the weights be of the same rank as the variable to be averaged. weightoptions = weightoptions(order=axisoptions) # # KRISHNA : check this for combinewts!! # ## if x.shape != weightoptions.shape: ## raise AveragerError, \ ## 'Error: Shape of weight array does not match shape of data array' ## # end of if x.shape != weightoptions.shape: if __DEBUG__: print '... definitely OK' except: raise AveragerError, \ 'Error: Did not find the axes requested in the Masked variable.' elif len(axislist) == 1: # # Only one axis to reduce over....' # figure out if it is an array (numpy or numpy.ma) or 'equal' or 'generate' or something else # if __DEBUG__: print 'I have only 1 axis and 1 option' weightoptions = __check_each_weight_option(x, axislist[0], axisindex[0], weightoptions) else: # # More than 1 axis to reduce over, and not an MV2 of the same dimensionality as x! # if weightoptions in ['generate','weighted']: weightoptions = area_weights(x,axisoptions) else: # Cannot do this because 'generate' was not passed with multiple axes. raise AveragerError, 'Error: Multiple axes passed without weights to match' # end of if weightoptions == 'generate': else: # # I have a list of weightoptions i.e more than 1 axis in axisoption # # # We have multiple axes to deal with each with a weight.... # for i in range(len(axislist)): weightoptions[i] = __check_each_weight_option(x, axislist[i], axisindex[i], weightoptions[i]) # end of for i in range(len(axislist)): # if len(axislist) < len(weightoptions): for j in range(len(axislist), len(weightoptions), 1): weightoptions[j] = __check_each_weight_option(x, None, j, weightoptions[j]) # end of if len(axislist) < len(weightoptions): # end of if not isinstance(weightoptions, types.ListType): # if __DEBUG__: print 'Successful with __check_weightoptions' # return weightoptions
def __check_weightoptions(x, axisoptions, weightoptions): """ Checks the weights=options to make sure that it is valid. Default: 'weighted' weight options are one of 'weighted', 'unweighted', an array of weights for each dimension or a MaskedVariable of the same shape as the data x. - 'weighted' means use the grid information to generate weights for that dimension or if multiple axes are passed, generate goes ahead and generates the full masked area weights. - 'unweighted' means use equal weights for all the grid points in that axis. - Also an array of weights (of the same shape as the dimension being averaged over or same shape as V) can be passed. """ # # Since the _check_axisoptions was passed, the variable x has already been reordered # to the required order..... check it anyway. # # __DEBUG__ = 0 # if __DEBUG__: print 'Axis options entering __check_weightoptions = ', axisoptions # axisindex = cdms2.order2index(x.getAxisList(), axisoptions) if __DEBUG__: print 'This should be 0,1,2... etc. is it? ', axisindex # axislist = cdms2.orderparse(axisoptions) if __DEBUG__: print 'axislist = ', axislist # if not isinstance(weightoptions, types.ListType): # # We have either 1 axis only or multiple axes and one MV2 of weights # if MV2.isMaskedVariable(weightoptions): # # Weight passed is an MV2. Probably OK # try: # We had required that the weights be of the same rank as the variable to be averaged. weightoptions = weightoptions(order=axisoptions) # # KRISHNA : check this for combinewts!! # ## if x.shape != weightoptions.shape: ## raise AveragerError, \ ## 'Error: Shape of weight array does not match shape of data array' ## # end of if x.shape != weightoptions.shape: if __DEBUG__: print '... definitely OK' except: raise AveragerError, \ 'Error: Did not find the axes requested in the Masked variable.' elif len(axislist) == 1: # # Only one axis to reduce over....' # figure out if it is an array (numpy or numpy.ma) or 'equal' or 'generate' or something else # if __DEBUG__: print 'I have only 1 axis and 1 option' weightoptions = __check_each_weight_option(x, axislist[0], axisindex[0], weightoptions) else: # # More than 1 axis to reduce over, and not an MV2 of the same dimensionality as x! # if weightoptions in ['generate', 'weighted']: weightoptions = area_weights(x, axisoptions) else: # Cannot do this because 'generate' was not passed with multiple axes. raise AveragerError, 'Error: Multiple axes passed without weights to match' # end of if weightoptions == 'generate': else: # # I have a list of weightoptions i.e more than 1 axis in axisoption # # # We have multiple axes to deal with each with a weight.... # for i in range(len(axislist)): weightoptions[i] = __check_each_weight_option( x, axislist[i], axisindex[i], weightoptions[i]) # end of for i in range(len(axislist)): # if len(axislist) < len(weightoptions): for j in range(len(axislist), len(weightoptions), 1): weightoptions[j] = __check_each_weight_option( x, None, j, weightoptions[j]) # end of if len(axislist) < len(weightoptions): # end of if not isinstance(weightoptions, types.ListType): # if __DEBUG__: print 'Successful with __check_weightoptions' # return weightoptions
def check_order(var, allowed, vertical=None, copy=False, reorder=False, extended=None, getorder=False): """Check that the axis order of a variable is matches at least one the specifed valid orders :Params: - **var**: MV2 array. - **allowed**: A single order string or a list. It should contain one or several of these letters: - ``x``: longitudes, - ``y``: latitudes, - ``z``: vertical levels, - ``t``: time axis, - ``d``: data values (ignored), - ``-``: any kind of axis. :Return: ``var``, or ``var, order, reordered`` if **reorder** is True. """ # Check allowed orders # - consistency if not isinstance(allowed, (list, tuple)): allowed = [allowed] else: allowed = list(allowed) withd = 'd' in allowed[0] get_rank = lambda o: len(o.replace('d', '')) rank = get_rank(allowed[0]) for order in allowed: try: cdms2.orderparse(order.lower().replace('d', '')) except: raise VACUMMError("Wrong allowed order: " + order) if ('d' in order and not withd) or ('d' not in order and withd): raise VACUMMError( "'d' only partially present in allowed order: %s" % allowed) if get_rank(order) != rank: raise VACUMMError("Inconsistent ranks between allowed orders: %s" % [get_rank(o) for o in allowed]) # - check extended mode if extended is None: # extended? re_upper = re.compile('[XYZT]').search for order in allowed: if re_upper(order) is not None: extended = True # force extended mode break else: extended = False if extended is False: # lower allowed = [order.lower() for order in allowed] else: #add tolerance for lower case orders re_sub = re.compile('[xyzt]').sub allowed = allowed + [re_sub('-', order) for order in allowed] # - unique and lower case _, idx = N.unique(allowed, return_index=True) idx = N.sort(idx) allowed = N.array(allowed)[idx].tolist() # - restrict to vertical or horizontal (1D data only) if vertical is not None and len(allowed[0]) == 2: allowed = [oo for oo in allowed if oo[int(vertical)] == 'd'] # Data order data_cdms_order = get_order(var) # Loop on allowed orders from vacumm.misc.grid.misc import get_axis, var2d reordered = False for allowed_order in allowed: # Handle data case d = allowed_order.find('d') if d != -1: allowed_order = allowed_order.replace('d', '') # pure axis # Check cdms order allowed_cdms_order = allowed_order.lower() # lower case if order_match(data_cdms_order, allowed_cdms_order, strict='right'): break # It is already good # Try to reorder if reorder: try: reordered = cdms2.order2index(var.getAxisList(), allowed_cdms_order) new_var = var.reorder(allowed_cdms_order) if allowed_cdms_order[-1] == 'x' and len( get_axis(new_var, -1).shape) == 2: # 2D axes del var var = var2d(new_var, MV2.transpose(get_axis(new_var, 0)), MV2.transpose(get_axis(new_var, -1)), copy=0) set_order(new_var, allowed_cdms_order) else: del var var = new_var data_cdms_order = get_order(var) break # No error so it worked and we leave except: continue else: raise VACUMMError('Wrong type of axes. Possible forms are: %s' % ', '.join(allowed)) if not getorder: return var if d != -1: data_cdms_order = cdms2.orderparse(data_cdms_order) data_cdms_order.insert(d, 'd') data_cdms_order = ''.join(data_cdms_order) return var, data_cdms_order, reordered