Changeset 1096 in lmdz_wrf for trunk


Ignore:
Timestamp:
Sep 11, 2016, 8:23:07 PM (9 years ago)
Author:
lfita
Message:

Adding:

  • `index_flatten_mat': Function to provide the matrix coordinates of an index from its flatten version
  • `oper_submatrix': Function to perform an operation of a given matrix along a sub-set of values along its dimensions
  • `same_shape': Function to check if two matrices have the same shape
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/generic_tools.py

    r1094 r1096  
    4747# ijlonlat: Function to provide the imin,jmin imax,jmax of a lon,lat box
    4848# incomming_flow: Function to determine if a fgrid-flow inflows to the central grid point
     49# index_flatten_mat: Function to provide the matrix coordinates of an index from its flatten version
    4950# index_mat_way: Function to look for a value within a matrix following a direction
    5051# index_mat: Function to provide the coordinates of a given value inside a matrix
     
    5657# num_chainSnum: Function to pass a value to a `ChainStrNum' number
    5758# num_split: Function to split a string at each numeric value keeping the number as the last character of each cut
     59# oper_submatrix: Function to perform an operation of a given matrix along a sub-set of values along its dimensions
    5860# printing_dictionary: Function to print the content of a dictionary
    5961# PolyArea: Function to compute the area of the polygon following 'Shoelace formula'
    6062# radius_angle: Function to generate a matrix with the angle at a given point
    6163# radius_dist: Function to generate a matrix with the distance at a given point
     64# same_shape: Function to check if two matrices have the same shape
    6265# search_sec_list: Function to provide the values and indices on a list which matches a section of a string
    6366# significant_decomposition: Function to decompose a given number by its signifcant potencies
     
    85998602    return tB
    86008603
     8604def same_shape(mat1,mat2):
     8605    """ Function to check if two matrices have the same shape
     8606      mat1,2= matrices to check
     8607    """
     8608    fname = 'same_shape'
     8609
     8610    shape1 = mat1.shape
     8611    shape2 = mat2.shape
     8612
     8613    Ndims1 = len(shape1)
     8614    Ndims2 = len(shape2)
     8615
     8616    if Ndims1 != Ndims2:
     8617        print errormsg
     8618        print '  ' + fname + ': mat1 and mat2 have different number of dimensions !!'
     8619        print '    Ndims mat 1:', Ndims1,' Ndims mat2:', Ndims2
     8620        quit(-1)
     8621
     8622    for idn in range(Ndims1):
     8623        if shape1[idn] != shape2[idn]:
     8624            print errormsg
     8625            print '  ' +fname+ ': length of',idn,'diemsion in mat1 and mat2 differ !!'
     8626            print '    Length mat 1:', shape1[idn],' Length mat2:', shape2[idn]
     8627            quit(-1)
     8628
     8629    return
     8630
     8631def index_flatten_mat(index,Ldims):
     8632    """ Function to provide the matrix coordinates of an index from its flatten version
     8633      index= index of the matrix's flatten version
     8634      Ldims= lengths of the dimensions of the matrix
     8635    >>> index_flatten_mat(17,[3,3,3])
     8636    [1 2 2]
     8637    """
     8638    fname = 'index_flatten_mat'
     8639    Ndims = len(Ldims)
     8640
     8641    if index < Ldims[Ndims-1]:
     8642        indices = np.zeros((len(Ldims)), dtype=int)
     8643        indices[Ndims-1] = index
     8644    else:
     8645        for idn in range(1,Ndims):
     8646            indices = np.zeros((len(Ldims)), dtype=int)
     8647            subsize = int(np.prod(Ldims[Ndims-idn-1:Ndims]))
     8648            # Reaching depth level in the matrix
     8649            if subsize > idn:
     8650                # Getting index for each dimension from the depth
     8651                prevsubsizeind = index
     8652                for idnd in range(Ndims-idn, Ndims):
     8653                    prevsubsize = int(np.prod(Ldims[idnd:Ndims]))
     8654                    Nprevsubsize = int(prevsubsizeind/prevsubsize)
     8655                    indices[idnd-1] = Nprevsubsize
     8656                    prevsubsizeind = prevsubsizeind - Nprevsubsize*prevsubsize
     8657                # Final index
     8658                indices[Ndims-1] = prevsubsizeind
     8659               
     8660    return indices
     8661
     8662def oper_submatrix(mat,dimns,submatval,oper,opdims):
     8663    """ Function to perform an operation of a given matrix along a sub-set of values along its dimensions
     8664      mat= matrix with values
     8665      dimns= names of the matrix dimensions
     8666      submatval= matrix value to use with some dimensions reduced
     8667      oper= operation to perform
     8668        'sumc', add [val]
     8669        'subc', substraction [val]
     8670        'mulc', multiply by [val]
     8671        'divc', divide by [val]
     8672        'lowthres',[val]: modify all values below [val] to submatval
     8673        'upthres',[val]: modify all values above [val] to submatval
     8674      opdims= dimensions of the operation
     8675      >>> mat = np.arange(12).reshape(3,2,2)
     8676      >>> dimsn = ['time', 'lon', 'lat']
     8677      >>> oper_submatrix(mat, dimsn, np.matrix([[1., 1.],[2., 2.]]), 'sumc', ['time'])
     8678      [[[ 1  2]
     8679       [ 4  5]]
     8680
     8681       [[ 5  6]
     8682        [ 8  9]]
     8683
     8684       [[ 9 10]
     8685        [12 13]]
     8686    """
     8687    fname = 'dimoper_matrix'
     8688
     8689    operations = ['sumc', 'subc', 'mulc', 'divc', 'lowthres', 'upthres']
     8690    matype = mat.dtype
     8691
     8692    if oper.find(',') != -1:
     8693        opern = oper.split(',')[0]
     8694        val = retype(oper.split(',')[1], matype)
     8695    else:
     8696        opern = oper
     8697
     8698    Ndims = len(dimns)
     8699    # Getting the slice, on '-1', dimension to operate along
     8700    # Keeping in 'ldimuse': length of the dimensions of the values to use
     8701    # Keeping in 'ldimop': length of the dimension to operate along
     8702    idim = 0
     8703    ldimuse = []
     8704    ldimop = []
     8705    slicevals = []
     8706    for dimn in dimns:
     8707        for dn in opdims:
     8708            if dimn == dn:
     8709                slicevals.append(-1)
     8710                ldimop.append(mat.shape[idim])
     8711            else:
     8712                slicevals.append(mat.shape[idim])
     8713                ldimuse.append(mat.shape[idim])
     8714        idim = idim + 1
     8715
     8716    Ndop = len(opdims)
     8717    Ntotdims = np.prod(ldimop)
     8718
     8719    # Checking for coincidence in shapes
     8720    try:
     8721        with Capturing() as output:
     8722            same_shape(submatval,np.zeros(ldimuse))
     8723    except:
     8724        print errormsg
     8725        print '  ' + fname + ': shape of matrix to use and shape of values to ' +    \
     8726          'operate differ!!'
     8727        for sout in output: print sout
     8728        quit(-1)
     8729
     8730    # Operation
     8731    newmat = np.zeros(tuple(mat.shape), dtype=mat.dtype)
     8732    for ijk in range(Ntotdims):
     8733        ijkop = -1
     8734        opslice = []
     8735        idcalc = index_flatten_mat(ijk,ldimop)
     8736        for idn in range(Ndims):
     8737            if slicevals[idn] == -1:
     8738                ijkop = ijkop + 1
     8739                opslice.append(idcalc[ijkop])
     8740            else:
     8741                opslice.append(slice(0,slicevals[idn]))
     8742
     8743        if opern == 'sumc':
     8744            newmat[tuple(opslice)] = mat[tuple(opslice)] + submatval
     8745        elif opern == 'subc':
     8746            newmat[tuple(opslice)] = mat[tuple(opslice)] - submatval
     8747        elif opern == 'mulc':
     8748            newmat[tuple(opslice)] = mat[tuple(opslice)] * submatval
     8749        elif opern == 'divc':
     8750            newmat[tuple(opslice)] = mat[tuple(opslice)] / submatval
     8751        elif opern == 'lowthres':
     8752            newmat[tuple(opslice)] = np.where(mat[tuple(opslice)] < val, submatval,  \
     8753              mat[tuple(opslice)])
     8754        elif opern == 'upthres':
     8755            newmat[tuple(opslice)] = np.where(mat[tuple(opslice)] > val, submatval,  \
     8756              mat[tuple(opslice)])
     8757        else:
     8758            print errormsg
     8759            print '  ' + fname + ": operation '" + opern + "' not ready !!"
     8760            print '    ready operations:', operations
     8761            quit(-1)
     8762
     8763    return newmat
     8764
    86018765#quit()
    86028766
Note: See TracChangeset for help on using the changeset viewer.