# -*- coding: iso-8859-15 -*-
# Python tools
# From L. Fita work in different places: CCRC (Australia), LMD (France)
# More information at: http://www.xn--llusfb-5va.cat/python/PyNCplot
#
# pyNCplot and its component generic_tools.py comes with ABSOLUTELY NO WARRANTY. 
# This work is licendes under a Creative Commons 
#   Attribution-ShareAlike 4.0 International License (http://creativecommons.org/licenses/by-sa/4.0)
#

import numpy as np
from netCDF4 import Dataset as NetCDFFile
import os
import re
import numpy.ma as ma
from cStringIO import StringIO
import sys

main = 'nc_var_tools.py'

errormsg='ERROR -- error -- ERROR -- error'
warnmsg='WARNING -- warning -- WARNING -- warning'

fillValue = 1.e20
fillValueF = 1.e20 
fillValueD = 1.e20 
fillValueC = '-'
fillValueI = -99999
fillValueI16 = -99999
fillValueF64 = 1.e20
fillValueI32 = -99999

# 12 Months
shortmon = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

# For variables_values

# Variable name might come with a statistical surname...
statsurname=['min','max','mean','std', 'sum', 'turb', 'var']

# masked array (for type tests)
mamat = ma.masked_equal([0,1],1)

####### Content
# ASCII_LaTeX: Function to transform from an ASCII character to LaTeX codification
# ASCII_to: Function to provide the equivalence text to a given lenguage omitting certain characters
# auto_val: Function to provide a value following an 'auto' configuration
# Capturing: Class to capture the standard output from a function
# CF_gribequiv: Function to provide the GRIB variable code number from a CF name
# CFmonthU_daysU: Function to transform from a CF date series with units as 'months since [DATE]' to 'days since [DATE]'
# CFvar_DIAGvar: Function to provide which model diagnostic values can provide a CF-variable from ASCII file
# CFvar_MODvar: Function to provide which model values can provide a CF-variable from ASCII file
# chainSnumHierarchy: Class to provide the structure of a `ChainStrNum' hierarchy
# chainSnum_levnext: Function to provide the next value for a given level from a chainStrnum hirerarchy of numbers
# chainSnum_num: Function to pass a `ChainStrNum' string to a number
# changedate360: Class to change a date  on a 360 days/yr (or 12 30-days months) calendar
# check_timestep: Function to check if a time-units are 'timestep' based. If it's the case, transform them
# coincident_CFtimes: Function to make coincident times for two different sets of CFtimes
# coldec_hex: Function to pas a decimal ([r,g,b]; [0.,1.]) color to hexadecimal (#[RR][GG][BB], 00-64, 0A-FF)
# colhex_dec: Function to pas a hexadecimal (#[RR][GG][BB]; 00-64, 0A-FF) color to decimal ([0.,1.])
# color_deg: Function to generate a degradation of colors in rgb base
# contflow: Function to bring back the increment in j,i grid points according to a trip: (inflow directions)
# crossingpoint_2Dlines: Function to determinant the crossing point between two lines in a plane
# curvelocalize_2D: Function to provide the localization a curve in a 2D field of positions via the equivalent
#   i,j-quads within which the curve lays (-1, no value for the given quad [2x2 points around]) and provide 
#   the weights of the quad to perform a distance-weighted mean at the given curve point
# DateTimeStr_date: Function to transform a string date-time ([YYYY][MM][DD][HH][MI][SS] format) to a date object
# datetimeStr_datetime: Function to transform a string date-time ([YYYY]-[MM]-[DD]_[HH]:[MI]:[SS] format) to a date object
# dictionary_key: Function to provide the first key in a dictionay with a given value
# dictionary_key_list: Function to provide the first key in a dictionary of lists with a given value
# dictKeysVals_stringList: Function to provide strings from a dictionary with keys which contain values of lists
# dictvar_listS: Function to provide a Dc string separated list of DVs separated [key] [value] couples following a list of keys
# diff_dates360: Function to provide the number of seconds of difference between two dates (dateA - dateB) on a 
#   360 days/yr (or 12 30-days months) calendar
# dtsec360dyr: Class to operate a number of seconds to a date in a 360 days/yr (or 12 30-days months) calendar
# files_folder_HMT: Function to retrieve a list of files from a folder [fold] and files with [head]*[middle]*[tail]
# get_configuration: Function to get the configuration from an ASCII external file
# get_specdictionary_HMT: Function to get specific values from a dictionary by selcting that keys with H*M*T
# grib_CFequiv: Function to provide the CF name of a GRIB variable code number
# ijlonlat: Function to provide the imin,jmin imax,jmax of a lon,lat box
# incomming_flow: Function to determine if a fgrid-flow inflows to the central grid point
# index_flatten_mat: Function to provide the matrix coordinates of an index from its flatten version
# index_mat_way: Function to look for a value within a matrix following a direction
# index_mat: Function to provide the coordinates of a given value inside a matrix
# index_vec: Function to provide the coordinates of a given value inside a vector
# int_to_roman: Convert an integer to Roman numerals
# julday_360d: Function to provide the julian day of a date in a 360 days/yr (or 12 30-days months) calendar
# latex_fig_array: Function to add an array of figures to an existing tex file
# latex_text: Function to transform a text to LaTeX following style rules
# linearint_weights: Function to provide the weights for a linear interpolation of a value between a couple of values as a weighted distance mean
# linearint_3x3weights: Function to provide the weights for a linear interpolation of a value inside a 3x3 matrix of values as a weighted distance mean
# list_combos: Function to construct a new list with all possible N-combinations of the list-values
# list_coincidences: Function to provide the coincidences between two lists
# list_differences: Function to provide the differences between two lists
# list_norepeatcombos: Function to all possible (Num-1)-combinations of a Num values without repetitions
# lstring_values: Function to provide a new list-string from a string which is a list of word separated by a character if some values
#   are repeated they are not included
# multi_index_mat: Function to provide the multiple coordinates of a given value inside a matrix
# multi_index_string: Function to provide the indeces of every repetition of a group of characters within a string
# num_chainSnum: Function to pass a value to a `ChainStrNum' number
# num_ordinal: Function to provide the ordinal of a given number, language, format and gender
# num_split: Function to split a string at each numeric value keeping the number as the last character of each cut
# oper_submatrix: Function to perform an operation of a given matrix along a sub-set of values along its dimensions
# operations: Function to perform different operations to a pair of matrices of values
# period_information_360d: Function to provide the information of a given period idate, edate (dates in 
#  [YYYY][MM][DD][HH][MI][SS] format) in a 360 years calendar
# points_2Dline: Function to define a line from a pair of points on a plane
# PolyArea: Function to compute the area of the polygon following 'Shoelace formula'
# pretty_int: Function to plot nice intervals
# prime_decomposition: Function to decompose a given number with its multiple prime numbers
# prime_numbers: Function to find all the prime numbers up to a given value above 17
# printing_dictionary: Function to print the content of a dictionary
# provide_slices: Function to provide a list of slices for a matrix giving a sub-section of running dimensions
# radius_angle: Function to generate a matrix with the angle at a given point
# radius_dist: Function to generate a matrix with the distance at a given point
# rectangular_spiral: Function to provide a rectangular spiral (along x,y-axis values) of values
# replace_list: Function to replace a value in a given list
# roman_to_int: Convert a roman numeral to an integer
# same_shape: Function to check if two matrices have the same shape
# search_sec_list: Function to provide the values and indices on a list which matches a section of a string
# significant_decomposition: Function to decompose a given number by its signifcant potencies
# singleline_printing_class: Function to print all the values of a given class in a single line to be parseavel
# stagger_unstagger: Function to de-stagger a variable
# std_stats2Val: two variables standard Statistics class 
# Str_Bool: Function to transform from a String value to a boolean one
# str_list: Function to obtain a list from a string givin a split character
# str_list_k: Function to obtain a list of types of values from a string giving a split character
# stringS_dictvar: Function to provide a dictionary from a Srting which list of DVs separated [key] [value] couples
# stringList_dictKeysVals: Function to provide a dictionary with keys which contain values of lists from a string
# subbasin_point: Function to provide sub-basins given a grid point following a matrix of trips
# timestep_conform: Function to provide the time-step in seconds which conforms 1 temporal unit and the resultant number
#   of time-steps for a whole period is multiple of a given number
# timefmt_timelab: Function to transform from C-like time format to general one
# unitsdsDate: Function to know how many units of time are from a given pair of dates
# vals_around: Function to provide the 3x3 values around a given j,i point

def searchInlist(listname, nameFind):
    """ Function to search a value within a list
    listname = list
    nameFind = value to find
    >>> searInlist(['1', '2', '3', '5'], '5')
    True
    """
    for x in listname:
      if x == nameFind:
        return True
    return False

def values_line(line, splitv, chars):
    """ Function to retrieve values from a line of ASCII text removing a series of characters
      line= line of ASCII text to work with
      splitv= character to use to split with the line
      chars= list of characters/strings to remove
    >>> values_line('0.0 0.0 1 [ 0 0 ]', ' ', ['[', ']'])
    ['0.0', '0.0', '1', '0', '0']
    """
    fname = 'values_line'

    vals = line.replace('\n', '')
    for ic in chars:
        vals = vals.replace(ic, '')

    vals0 = vals.split(splitv)
    vals = []
    for val in vals0:
        if not len(val) == 0: vals.append(val)

    return vals

def filexist(filen, emsg, fmsg):
    """ Check existence of a file 
    filen= file name
    emsg= general error message
    fmsg= message before generic text of inexistence of file
    """
    if not os.path.isfile(filen):
        print emsg
        print '  ' + fmsg + ' file "' + filen + '" does not exist !!'
        print emsg
        quit(-1)    

    return

def reduce_spaces(string):
    """ Function to give words of a line of text removing any extra space
    """
    values = string.replace('\n','').split(' ')
    vals = []
    for val in values:
         if len(val) > 0:
             vals.append(val)

    return vals

def reduce_tabulars(string):
    """ Function to give words of a line of text removing any extra space and tabular separation
    """
    values = string.replace('\n','').split('\t')
    vals = []
    for val in values:
         if len(val) > 0:
             vals.append(val)

    return vals

def check_arguments(funcname,args,expectargs,char):
    """ Function to check the number of arguments if they are coincident
    check_arguments(funcname,Nargs,args,char)
      funcname= name of the function/program to check
      args= passed arguments
      expectargs= expected arguments
      char= character used to split the arguments
    """

    fname = 'check_arguments'

    Nvals = len(args.split(char))
    Nargs = len(expectargs.split(char))

    if Nvals != Nargs:
        print errormsg
        print '  ' + fname + ': wrong number of arguments:',Nvals," passed to  '",   \
          funcname, "' which requires:",Nargs,'!!'
        print '     # given expected _______'
        Nmax = np.max([Nvals, Nargs])
        for ia in range(Nmax):
            if ia > Nvals-1:
                aval = ' '
            else:
                aval = args.split(char)[ia]
            if ia > Nargs-1:
                aexp = ' '
            else:
                aexp = expectargs.split(char)[ia]

            print '    ', ia, aval, aexp
        quit(-1)

    return

def Str_Bool(val):
    """ Function to transform from a String value to a boolean one
    >>> Str_Bool('True')
    True
    >>> Str_Bool('0')
    False
    >>> Str_Bool('no')
    False
    """

    fname = 'Str_Bool'

    truelist = ['True', 'true', '1', 'Yes', 'yes', 'T', 't'] 
    falselist = ['False', 'false', '0', 'No', 'no', 'F', 'f']

    if searchInlist(truelist,val): 
        boolv = True
    elif searchInlist(falselist, val):
        boolv = False
    else:
        print errormsg
        print '  ' + fname + ": value '" + val + "' not ready!!"
        quit(-1)

    return boolv

def Nchar(N,string):
    """ Function to provide 'N' times concatenated 'string'
      N= number of copies
      strin= string to reproduce
    >>> Nchar(4,'#')
    ####
    """
    fname = 'Nchar'

    newstring=''
    for it in range(N):
        newstring=newstring + string

    return newstring

def string_dicvals_char(dictionary, string, char):
    """ Function to provide a string taking values from a given [string] where each single character 
      coincide with the key of the dictionary [dictionary], separated by a given set of characters [char]
      dictionary= dictionary of the values dim([c]) = {[value]}
      string = [c1][...[cN]] String with the combination of [c]s
      >>> dictvals = {'i': 'dimx', 'j': 'dimy', 'k': 'dimz', 't': 'dimt'}
      >>> string_dicvals_char(dictvals, 'ijkt', ', ')
      dimx, dimy, dimz, dimt
    """
    fname = 'string_dicvals_char'

    Lstring = len(string)
    newstring = ''
    for ic in range(Lstring):
        cc = string[ic:ic+1]
        if not dictionary.has_key(cc):
            print errormsg
            print '  ' + fname + ": dictionary of values does not have character '" +\
              cc + "' !!"
            print '    it has:',dictionary

        if ic == 0:
            newstring = dictionary[cc]
        else:
            newstring = newstring + char + dictionary[cc]

    return newstring

def substring(stringv,pos,char):
    """ Function to substitute a character of a given string
      stringv= string to change
      pos= position to change
      char= characters to use as substitution
    >>> substring('0123456',2,'ii')
    01ii3456
    """
    fname = 'substring'

# From: http://stackoverflow.com/questions/1228299/change-one-character-in-a-string-in-python
    newstring = stringv[:pos] + char + stringv[pos+1:]

    return newstring

def list_combos(listv,Ncombos):
    """ Function to construct a new list with all possible N-combinations of the list-values
      listv= list of values
      Ncombos= number of combinations
      >>> list_combos(['a', 'b', 'c', 'd'],1)
      ['a', 'b', 'c', 'd', 'aa', 'ab', 'ac', 'ad', 'ba', 'bb', 'bc', 'bd', 'ca', 'cb', 'cc', 'cd', 'da', 'db', 'dc', 'dd']
    """
    fname = 'list_combos'

    newlist = list(listv)
    Nlvs = len(listv)
    for ic in range(Ncombos):
        prevlist = list(newlist)
        for lv in prevlist:
            for ilv in listv:
                newlist.append(lv + ilv)

    return newlist

def list_norepeatcombos(Num):
    """ Function to all possible (Num-1)-combinations of a Num values without repetitions
      Num= number of elements
    >>> list_norepeatcombos(4)
    [[0], [1], [2], [3], [0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3], [0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 1, 2, 3]]
    """
    from math import factorial
    fname = 'list_norepeatcombos'

    listv = range(Num)
    # Single values are also combinations!
    combos = []
    for i in range(Num):
        combos.append([i])

    samevals = []
    diffvals = []
    for iv in listv:
        if not searchInlist(diffvals,iv): diffvals.append(iv)
        if searchInlist(samevals,iv): samevals.append(iv)

    Nlvs = len(listv)
    # Number of possible combinations
    for ic in range(2,Nlvs+1):
        Ncombs = factorial(Nlvs)/(factorial(ic)*factorial(Nlvs-ic))
        combo = range(ic)
        # Getting the limits for each element of the combination of ic-elements
        limitcombo = range(ic)
        for icc in range(ic):
            limitcombo[icc] = Nlvs-ic+icc
      
        combos.append(combo)
        ncombo = list(combo)
        for ico in range(Ncombs):
           # Incrementing the last coordinate
            ncombo[ic-1] = ncombo[ic-1] + 1
            if ncombo[ic-1] > limitcombo[ic-1]:
                # looping all over the others if there is an overpass of the value
                #   previous coordinate will be incremented and the following ones 
                #   will be incremented by 1 starting from the new assigned previous 
                #   value
                for icc in range(1,ic):
                    # Incrementing the previous one
                    ncombo[ic-icc-1] = ncombo[ic-icc-1]+1
                    # Incrementing the following ones since the value at the previous 
                    #   position
                    for iccc in range(ic-icc,ic):
                        ncombo[iccc] = ncombo[iccc-1]+1
                    if ncombo[ic-icc-1] <= limitcombo[ic-icc-1]: 
                        combos.append(list(ncombo))
                        break
            else:
                combos.append(list(ncombo))

    return combos

def datetimeStr_datetime(StringDT):
    """ Function to transform a string date ([YYYY]-[MM]-[DD]_[HH]:[MI]:[SS] format) to a date object
    >>> datetimeStr_datetime('1976-02-17_00:00:00')
    1976-02-17 00:00:00
    """
    import datetime as dt

    fname = 'datetimeStr_datetime'

    dateD = np.zeros((3), dtype=int)
    timeT = np.zeros((3), dtype=int)

    dateD[0] = int(StringDT[0:4])
    dateD[1] = int(StringDT[5:7])
    dateD[2] = int(StringDT[8:10])

    trefT = StringDT.find(':')
    if not trefT == -1:
#        print '  ' + fname + ': refdate with time!'
        timeT[0] = int(StringDT[11:13])
        timeT[1] = int(StringDT[14:16])
        timeT[2] = int(StringDT[17:19])

    if int(dateD[0]) == 0:
        print warnmsg
        print '    ' + fname + ': 0 reference year!! changing to 1'
        dateD[0] = 1 
 
    newdatetime = dt.datetime(dateD[0], dateD[1], dateD[2], timeT[0], timeT[1], timeT[2])

    return newdatetime

def datetimeStr_conversion(StringDT,typeSi,typeSo):
    """ Function to transform a string date to an another date object
    StringDT= string with the date and time
    typeSi= type of datetime string input
    typeSo= type of datetime string output
      [typeSi/o]
        'cfTime',[units]: time in CF-convention format [units] = [tunits] since [refdate]
        'matYmdHMS': numerical vector with [[YYYY], [MM], [DD], [HH], [MI], [SS]]
        'YmdHMS': [YYYY][MM][DD][HH][MI][SS] format
        'Y-m-d_H:M:S': [YYYY]-[MM]-[DD]_[HH]:[MI]:[SS] format
        'Y-m-d H:M:S': [YYYY]-[MM]-[DD] [HH]:[MI]:[SS] format
        'Y/m/d H-M-S': [YYYY]/[MM]/[DD] [HH]-[MI]-[SS] format
        'WRFdatetime': [Y], [Y], [Y], [Y], '-', [M], [M], '-', [D], [D], '_', [H], 
          [H], ':', [M], [M], ':', [S], [S]
    >>> datetimeStr_conversion('1976-02-17_08:32:05','Y-m-d_H:M:S','matYmdHMS')
    [1976    2   17    8   32    5]
    >>> datetimeStr_conversion(str(137880),'cfTime,minutes since 1979-12-01_00:00:00','Y/m/d H-M-S')
    1980/03/05 18-00-00
    >>> datetimeStr_conversion('1980/03/05 18-00-00','Y/m/d H-M-S','cfTime,minutes since 1979-12-01_00:00:00')
    137880.0
    """
    import datetime as dt

    fname = 'datetimeStr_conversion'

    if StringDT[0:1] == 'h':
        print fname + '_____________________________________________________________'
        print datetimeStr_conversion.__doc__
        quit()

    if typeSi[0:6] == 'cfTime':
        timeval = np.float(StringDT)
        tunits = typeSi.split(',')[1].split(' ')[0]
        Srefdate = typeSi.split(',')[1].split(' ')[2]

# Does reference date contain a time value [YYYY]-[MM]-[DD] [HH]:[MI]:[SS]
##
        yrref=Srefdate[0:4]
        monref=Srefdate[5:7]
        dayref=Srefdate[8:10]

        trefT = typeSi.split(',')[1].find(':')
        if not trefT == -1:
            if len(typeSi.split(',')[1].split(' ')) == 3:
                horref=Srefdate[11:13]
                minref=Srefdate[14:16]
                secref=Srefdate[17:19]
            else:
                Sreftime = typeSi.split(',')[1].split(' ')[3]
                horref=Sreftime[0:2]
                minref=Sreftime[3:5]
                secref=Sreftime[6:8]                
            refdate = datetimeStr_datetime( yrref + '-' + monref + '-' + dayref +    \
              '_' + horref + ':' + minref + ':' + secref)
        else:
            refdate = datetimeStr_datetime( yrref + '-' + monref + '-' + dayref +    \
              + '_00:00:00')

        if tunits == 'weeks':
            newdate = refdate + dt.timedelta(weeks=float(timeval))
        elif tunits == 'days':
            newdate = refdate + dt.timedelta(days=float(timeval))
        elif tunits == 'hours':
            newdate = refdate + dt.timedelta(hours=float(timeval))
        elif tunits == 'minutes':
            newdate = refdate + dt.timedelta(minutes=float(timeval))
        elif tunits == 'seconds':
            newdate = refdate + dt.timedelta(seconds=float(timeval))
        elif tunits == 'milliseconds':
            newdate = refdate + dt.timedelta(milliseconds=float(timeval))
        else:
              print errormsg
              print '    timeref_datetime: time units "' + tunits + '" not ready!!!!'
              quit(-1)

        yr = newdate.year
        mo = newdate.month
        da = newdate.day
        ho = newdate.hour
        mi = newdate.minute
        se = newdate.second
    elif typeSi == 'matYmdHMS':
        yr = StringDT[0]
        mo = StringDT[1]
        da = StringDT[2]
        ho = StringDT[3]
        mi = StringDT[4]
        se = StringDT[5]
    elif typeSi == 'YmdHMS':
        yr = int(StringDT[0:4])
        mo = int(StringDT[4:6])
        da = int(StringDT[6:8])
        ho = int(StringDT[8:10])
        mi = int(StringDT[10:12])
        se = int(StringDT[12:14])
    elif typeSi == 'Y-m-d_H:M:S':
        dateDT = StringDT.split('_')
        dateD = dateDT[0].split('-')
        timeT = dateDT[1].split(':')
        yr = int(dateD[0])
        mo = int(dateD[1])
        da = int(dateD[2])
        ho = int(timeT[0])
        mi = int(timeT[1])
        se = int(timeT[2])
    elif typeSi == 'Y-m-d H:M:S':
        dateDT = StringDT.split(' ')
        dateD = dateDT[0].split('-')
        timeT = dateDT[1].split(':')
        yr = int(dateD[0])
        mo = int(dateD[1])
        da = int(dateD[2])
        ho = int(timeT[0])
        mi = int(timeT[1])
        se = int(timeT[2])
    elif typeSi == 'Y/m/d H-M-S':
        dateDT = StringDT.split(' ')
        dateD = dateDT[0].split('/')
        timeT = dateDT[1].split('-')
        yr = int(dateD[0])
        mo = int(dateD[1])
        da = int(dateD[2])
        ho = int(timeT[0])
        mi = int(timeT[1])
        se = int(timeT[2])
    elif typeSi == 'WRFdatetime':
        yr = int(StringDT[0])*1000 + int(StringDT[1])*100 + int(StringDT[2])*10 +    \
          int(StringDT[3])
        mo = int(StringDT[5])*10 + int(StringDT[6])
        da = int(StringDT[8])*10 + int(StringDT[9])
        ho = int(StringDT[11])*10 + int(StringDT[12])
        mi = int(StringDT[14])*10 + int(StringDT[15])
        se = int(StringDT[17])*10 + int(StringDT[18])
    else:
        print errormsg
        print '  ' + fname + ': type of String input date "' + typeSi +              \
          '" not ready !!!!'
        quit(-1)

    if typeSo[0:6] == 'cfTime':
        tunits = typeSo.split(',')[1].split(' ')[0]
        Srefdate = typeSo.split(',')[1].split(' ')[2]

# Does reference date contain a time value [YYYY]-[MM]-[DD] [HH]:[MI]:[SS]
##
        yrref=Srefdate[0:4]
        monref=Srefdate[5:7]
        dayref=Srefdate[8:10]

        trefT = typeSo.split(',')[1].find(':')
        if not trefT == -1:
#            print '  ' + fname + ': refdate with time!'
            if len(typeSo.split(',')[1].split(' ')) == 3:
                horref=Srefdate[11:13]
                minref=Srefdate[14:16]
                secref=Srefdate[17:19]
            else:
                Sreftime = typeSo.split(',')[1].split(' ')[3]
                horref=Sreftime[0:2]
                minref=Sreftime[3:5]
                secref=Sreftime[6:8]                

            refdate = datetimeStr_datetime( yrref + '-' + monref + '-' + dayref +    \
              '_' + horref + ':' + minref + ':' + secref)
        else:
            refdate = datetimeStr_datetime( yrref + '-' + monref + '-' + dayref +    \
              + '_00:00:00')
        datei = dt.datetime(yr, mo, da, ho, mi, se)
        difft = datei - refdate

        if searchInlist(dir(difft),'total_seconds'):
            totsecs = difft.total_seconds()
        else:
            totsecs = difft.days()*24*3600. + difft.seconds()

        if tunits == 'weeks':
            cfdt = totsecs / (7*24*3600)
        elif tunits == 'days':
            cfdt = totsecs / (24*3600)
        elif tunits == 'hours':
            cfdt = totsecs / (3600)
        elif tunits == 'minutes':
            cfdt = totsecs / (60)
        elif tunits == 'seconds':
            cfdt = totsecs
        elif tunits == 'milliseconds':
            cfdt = totsecs*100.
        else:
              print errormsg
              print '    timeref_datetime: time units "' + tunits + '" not ready!!!!'
              quit(-1)
        dateYmdHMS = cfdt
        
    elif typeSo == 'matYmdHMS':
        dateYmdHMS = np.zeros((6), dtype=int)
        dateYmdHMS[0] =  yr
        dateYmdHMS[1] =  mo
        dateYmdHMS[2] =  da
        dateYmdHMS[3] =  ho
        dateYmdHMS[4] =  mi
        dateYmdHMS[5] =  se
    elif typeSo == 'YmdHMS':
        dateYmdHMS = str(yr).zfill(4) + str(mo).zfill(2) + str(da).zfill(2) +        \
          str(ho).zfill(2) + str(mi).zfill(2) + str(se).zfill(2)
    elif typeSo == 'Y-m-d_H:M:S':
        dateYmdHMS = str(yr).zfill(4) + '-' + str(mo).zfill(2) + '-' +               \
          str(da).zfill(2) + '_' + str(ho).zfill(2) + ':' + str(mi).zfill(2) + ':' + \
          str(se).zfill(2)
    elif typeSo == 'Y-m-d H:M:S':
        dateYmdHMS = str(yr).zfill(4) + '-' + str(mo).zfill(2) + '-' +               \
          str(da).zfill(2) + ' ' + str(ho).zfill(2) + ':' + str(mi).zfill(2) + ':' + \
          str(se).zfill(2)
    elif typeSo == 'Y/m/d H-M-S':
        dateYmdHMS = str(yr).zfill(4) + '/' + str(mo).zfill(2) + '/' +               \
          str(da).zfill(2) + ' ' + str(ho).zfill(2) + '-' + str(mi).zfill(2) + '-' + \
          str(se).zfill(2) 
    elif typeSo == 'WRFdatetime':
        dateYmdHMS = []
        yM = yr/1000
        yC = (yr-yM*1000)/100
        yD = (yr-yM*1000-yC*100)/10
        yU = yr-yM*1000-yC*100-yD*10

        mD = mo/10
        mU = mo-mD*10
        
        dD = da/10
        dU = da-dD*10

        hD = ho/10
        hU = ho-hD*10

        miD = mi/10
        miU = mi-miD*10

        sD = se/10
        sU = se-sD*10

        dateYmdHMS.append(str(yM))
        dateYmdHMS.append(str(yC))
        dateYmdHMS.append(str(yD))
        dateYmdHMS.append(str(yU))
        dateYmdHMS.append('-')
        dateYmdHMS.append(str(mD))
        dateYmdHMS.append(str(mU))
        dateYmdHMS.append('-')
        dateYmdHMS.append(str(dD))
        dateYmdHMS.append(str(dU))
        dateYmdHMS.append('_')
        dateYmdHMS.append(str(hD))
        dateYmdHMS.append(str(hU))
        dateYmdHMS.append(':')
        dateYmdHMS.append(str(miD))
        dateYmdHMS.append(str(miU))
        dateYmdHMS.append(':')
        dateYmdHMS.append(str(sD))
        dateYmdHMS.append(str(sU))
    else:
        print errormsg
        print '  ' + fname + ': type of output date "' + typeSo + '" not ready !!!!'
        quit(-1)

    return dateYmdHMS

def period_information(idate, edate, totunits):
    """ Function to provide the information of a given period idate, edate (dates in [YYYY][MM][DD][HH][MI][SS] format)
      [idate]= initial date of the period (in [YYYY][MM][DD][HH][MI][SS] format)
      [edate]= end date of the period (in [YYYY][MM][DD][HH][MI][SS] format)
      [totunits]= latest number of entire temporal units to compute: 'year', 'month', 'day', 'hour', 'minute', 'second'

    resultant information given as ',' list of:
      [dT]: sign of the temporal increment ('pos', 'neg')
      [idate]: initial date as [YYYY]:[MM]:[DD]:[HH]:[MI]:[SS]
      [edate]: end date as [YYYY]:[MM]:[DD]:[HH]:[MI]:[SS]
      [Nsecs]: total seconds between dates
      [Nyears]: Number of years taken as entire units ([iYYYY]0101000000 to [eYYYY+1]0101000000)
      [ExactYears]: Exact year-dates of the period as a '@' separated list of  [YYYY]0101000000
      [Nmonths]: Number of months taken as entire units ([iYYYY][iMM]01000000 to [eYYYY][eMM+1]01000000)
      [ExactMonths]: Exact mon-dates of the period as  a '@' separated list of [YYYY][MM]01000000
      [Ndays]: Number of days taken as entire units ([iYYYY][iMM][iDD]000000 to [eYYYY][eMM][eDD+1]000000)
      [ExactDays]: Exact day-dates of the period as  a '@' separated list of [YYYY][MM][DD]000000
      [Nhours]: Number of hours taken as entire units ([iYYYY][iMM][iDD][iHH]0000 to [eYYYY][eMM][eDD][eHH+1]0000)
      [ExactHours]: Exact hour-dates of the period as a '@' separated list of [YYYY][MM][DD][HH]0000
      [Nminutes]: Number of minutes taken as entire units ([iYYYY][iMM][iDD][iHH][iMI]00 to [eYYYY][eMM][eDD][eHH][eMI+1]00)
      [ExactMinutes]: Exact minutes-dates of the period as a '@' separated list of [YYYY][MM][DD][HH][MI]00
      [Nsecs]: Number of minutes taken as entire units ([iYYYY][iMM][iDD][iHH][iMI][iS] to [eYYYY][eMM][eDD][eHH][eMI][eSE+1])
      [ExactSeconds]: Exact seconds-dates of the period as a '@' separated list of [YYYY][MM][DD][HH][MI][SS]

    >>> period_information( '19760217083110', '19770828000000', 'month')
    pos,1976:02:17:08:31:10,1977:08:28:00:00:00,48180530.0,19,19760201000000@19760301000000@19760401000000@
    19760501000000@19760601000000@19760701000000@19760801000000@19760901000000@19761001000000@19761101000000@
    19761201000000@19770101000000@19770201000000@19770301000000@19770401000000@19770501000000@19770601000000@
    19770701000000@19770801000000@19770901000000
    """
    import datetime as dt

    fname = 'period_information'

    if idate == 'h':
        print fname + '_____________________________________________________________'
        print period_information.__doc__
        quit()

    expectargs = '[idate],[edate],[totunits]'
 
    check_arguments(fname,str(idate)+','+str(edate)+','+str(totunits),expectargs,',')

    readyT = ['year','month','week','day','hour','minute','second']

# Checking length
    Lidate = len(idate)
    Ledate = len(edate)

    if Lidate != Ledate:
        print errormsg
        print '   ' + fname + ': string dates of the period have different length !!'
        print "    idate: '" + idate + "' (L=", Lidate, ") edate: '" + edate +       \
          "' (L=", Ledate, ')'
        quit(-1)
    else:
        if Lidate != 14:
            print errormsg
            print '  ' + fname + ": wrong initial date: '" + idate + "' must " +     \
              'have 14 characters!!'
            print '    and it has:', Lidate
            quit(-1)
        if Ledate != 14:
            print errormsg
            print '  ' + fname + ": wrong end date: '" + edate + "' must " +         \
              'have 14 characters!!'
            print '    and it has:', Ledate
            quit(-1)

# Checking for right order of dates
    if int(idate) > int(edate):
        print warnmsg
        print '  ' + fname + ": initial date '" + idate + "' after end date '" +     \
          edate + "' !!"
        print "  re-sorting them!"
        i1 = edate
        e1 = idate
        idate = i1 
        edate = e1
        oinf = 'neg'
    else:
        oinf = 'pos'

# Year, month, day, hour, minute, second initial date
    iyrS = idate[0:4]
    imoS = idate[4:6]
    idaS = idate[6:8]
    ihoS = idate[8:10]
    imiS = idate[10:12]
    iseS = idate[12:14]

    oinf = oinf + ',' + iyrS+':'+imoS+':'+idaS+':'+ihoS+':'+imiS+':'+iseS

# Year, month, day, hour, minute, second end date
    eyrS = edate[0:4]
    emoS = edate[4:6]
    edaS = edate[6:8]
    ehoS = edate[8:10]
    emiS = edate[10:12]
    eseS = edate[12:14]

    oinf = oinf + ',' + eyrS+':'+emoS+':'+edaS+':'+ehoS+':'+emiS+':'+eseS

    idateT = dt.datetime(int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),int(iseS))
    edateT = dt.datetime(int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS))

# Seconds between dates
    DT = edateT - idateT
    # Python version depending
    if searchInlist(dir(DT), 'total_seconds'):
        Nsecs = DT.total_seconds()
    else:
        Nsecs = DT.days*24*3600. + DT.seconds

    oinf = oinf + ',' + str(Nsecs)

# Looking for number of years tacking exact beginning of the units [iYYYY]0101000000, [eYYYY+1]0101000000
##
    if totunits == 'year':
        itime = int(iyrS)
        if edate[4:15] != '0101000000':
            etime = int(eyrS)+1
        else:
            etime = int(eyrS)

        itimeT = dt.datetime(itime,1,1,0,0,0)

        Nyears = 1
        ExactYears = itimeT.strftime("%Y%m%d%H%M%S")
        it = int(iyrS)
        while it + 1 <= etime:
            it = it + 1
            Nyears = Nyears + 1
            itT = dt.datetime(it,1,1,0,0,0)
            ExactYears = ExactYears + '@' + itT.strftime("%Y%m%d%H%M%S")

        oinf = oinf + ',' + str(Nyears) + ',' + ExactYears

# Looking for number of months tacking exact beginning of the units [iYYYY][iMM]01000000, [eYYYY][eMM+1]01000000
##
    elif totunits == 'month':
        itime = int(iyrS)*100 + int(imoS)
        if edate[6:15] != '01000000':
            emo1 = int(emoS)+1
            if emo1 > 13:
                eyr1 = str(int(eyrS) + 1)
                emo1 = 01
            else:
                eyr1 = eyrS
            
        else:
            eyr1 = eyrS
            emo1 = emoS
    
        etime = int(eyr1)*100 + int(emo1) 
        itimeT = dt.datetime(int(iyrS),int(imoS),1,0,0,0)
        
        Nmonths = 1
        ExactMonths = itimeT.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + 1 <= etime:
            it = it + 1
            Nmonths = Nmonths + 1
            ityr = it/100
            itmo = it - ityr*100
            if itmo > 12:
                ityr = ityr + 1
                itmo = 1
                it = ityr * 100 + itmo
    
            itT = dt.datetime(ityr,itmo,1,0,0,0)
            ExactMonths = ExactMonths + '@' + itT.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Nmonths) + ',' + ExactMonths

# Looking for number of days tacking exact beginning of the units [iYYYY][iMM][iDD]000000, [eYYYY][eMM][eDD+7]000000
##
    elif totunits == 'week':
        itime = dt.datetime(int(iyrS),int(imoS),int(idaS),0,0,0)
        if edate[8:15] != '000000':
            etime = dt.datetime(int(eyrS), int(emoS), int(edaS)+7,0,0,0)
        else:
            etime = edateT

        Nweeks = 1
        ExactDays = itime.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + dt.timedelta(days=7) <= etime:
            it = it + dt.timedelta(days=7)
            Nweeks = Nweeks + 1
            ExactDays = ExactDays + '@' + it.strftime("%Y%m%d%H%M%S")

        oinf = oinf + ',' + str(Nweeks) + ',' + ExactDays

# Looking for number of days tacking exact beginning of the units [iYYYY][iMM][iDD]000000, [eYYYY][eMM][eDD+1]000000
##
    elif totunits == 'day':
        itime = dt.datetime(int(iyrS),int(imoS),int(idaS),0,0,0)
        if edate[8:15] != '000000':
            etime = dt.datetime(int(eyrS), int(emoS), int(edaS)+1,0,0,0)
        else:
            etime = edateT
    
        Ndays = 1
        ExactDays = itime.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + dt.timedelta(days=1) <= etime:
            it = it + dt.timedelta(days=1)
            Ndays = Ndays + 1
            ExactDays = ExactDays + '@' + it.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Ndays) + ',' + ExactDays

# Looking for number of hours tacking exact beginning of the units [iYYYY][iMM][iDD][iHH]0000, [eYYYY][eMM][eDD][iHH+1]0000
##
    elif totunits == 'hour':
        itime = dt.datetime(int(iyrS),int(imoS),int(idaS),int(ihoS),0,0)
        if edate[10:15] != '0000':
            etime = dt.datetime(int(eyrS), int(emoS), int(edaS), int(ehoS)+1,0,0)
        else:
            etime = edateT
    
        Nhours = 1
        ExactHours = itime.strftime("%Y%m%d%H%M%S")
        it = itime
        while it  + dt.timedelta(hours=1) <= etime:
            it = it + dt.timedelta(hours=1)
            Nhours = Nhours + 1
            ExactHours = ExactHours + '@' + it.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Nhours) + ',' + ExactHours

# Looking for number of minutes tacking exact beginning of the units [iYYYY][iMM][iDD][iHH][iMI]00, [eYYYY][eMM][eDD][iHH][iMI+1]00
##
    elif totunits == 'minute':
        itime = dt.datetime(int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),0)
        if edate[12:15] != '00':
            etime = dt.datetime(int(eyrS), int(emoS), int(edaS), int(ehoS), int(emiS)+1,0)
        else:
            etime = edateT

        Nminutes = 1
        ExactMinutes = itime.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + dt.timedelta(minutes=1) <= etime:
            it = it + dt.timedelta(minutes=1)
            Nminutes = Nminutes + 1
            ExactMinutes = ExactMinutes + '@' + it.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Nminutes) + ',' + ExactMinutes

# Looking for number of seconds tacking exact beginning of the units [iYYYY][iMM][iDD][iHH][iMI][iSE], 
#   [eYYYY][eMM][eDD][iHH][iMI][iSE+1]
##
    elif totunits == 'second':
        itime = dt.datetime(int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),int(iseS))
        if edate[12:15] != '00':
            etime = dt.datetime(int(eyrS), int(emoS), int(edaS), int(ehoS), int(emiS), int(eseS)+1)
        else:
            etime = edateT

        Nseconds = 1
        ExactSeconds = itime.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + dt.timedelta(seconds=1) < etime:
            it = it + dt.timedelta(seconds=1)
            Nseconds = Nseconds + 1
            ExactSeconds = ExactSeconds + '@' + it.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Nseconds) + ',' + ExactSeconds

    else:
        print errormsg
        print '  '+ fname + ": totalunits '" + totunits + "' not ready !!"
        print '    total time units ready:', readyT
        quit(-1)

    return oinf

def diff_dates360(dateA,dateB):
    """ Function to provide the number of seconds of difference between two dates (dateA - dateB) on a 
      360 days/yr (or 12 30-days months) calendar
      dateA= date in [Y, m, d, h, mi, s]
      dateB= date in [Y, m, d, h, mi, s]
      >>> diff_dates360([1976,2,17,8,29,30], [1976,2,27,8,29,30])
      -864000
    """
    fname = 'diff_dates360'

    # Reference date January first 1
    refdate = np.array([1,1,1,0,0,0])

    diffdatesA = np.array(dateA) - np.array(refdate)
    diffdatesB = np.array(dateB) - np.array(refdate)

    # seconds by time-units
    minsec = 60
    hoursec = 60 * minsec
    daysec = 24 * hoursec
    monsec = 30 * daysec
    yrsec = 12 * monsec
    secs = [yrsec,monsec,daysec,hoursec,minsec,1]

    dsecsA  = np.sum(diffdatesA*secs)
    dsecsB  = np.sum(diffdatesB*secs)

    diffsecs = dsecsA - dsecsB

    return diffsecs

def changedate360(idate,val,unit):
    """ Class to change a date  on a 360 days/yr (or 12 30-days months) calendar
      idate = date to change  [Y, m, d, h, mi, s]
      val = value to change
      unit= units to change [0: year; 1: month; 2: day; 3: hour; 4: minute; 5: second]
    >>> changedate360([1976,2,17,8,29,15],55,4)
    [1976, 2, 17, 9, 24, 15]
    >>> changedate360([1976,2,17,8,29,15],-55,5)
    [1976, 2, 17, 8, 28, 20]
    changedate360([1976,12,29,23,59,15],55,5)
    [1977, 1, 1, 0, 0, 10]
    """
    fname = 'changedate360'

    sgn = np.abs(val)/val

    newdate = list(idate)

    Sunits = ['year', 'month', 'day', 'hour', 'minute', 'second']
    # Maximum values for the time-unit
    tumaxs = [1e9, 13, 31, 24, 60, 60]
    # Minimum values for the time-unit
    tumins = [1, 1, 1, 0, 0, 0]

    if val > tumaxs[unit]:
        print errormsg
        print '  ' + fname + ': value to change:', val," for unit: '"+Sunits[unit]+  \
          "' bigger than its limit:", tumaxs[unit]
        quit(-1)

    newval = idate[unit] + val
    for itu in range(unit,-1,-1):
        if newval >= tumaxs[itu]:
            if itu > 2:
                newdate[itu] = newval - tumaxs[itu]
            else:
                newdate[itu] = newval - tumaxs[itu] + 1
            if newdate[itu] < tumins[itu]: newdate[itu] = tumins[itu]
            newdate[itu-1] = newdate[itu-1] + 1
        elif newval < tumins[itu]:
            newdate[itu] = newdate[itu] + val + tumaxs[itu] + tumins[itu]
            newdate[itu-1] = newdate[itu-1] - 1
        else:
            newdate[itu] = newval
            break
        newval = newdate[itu-1]
 
    return newdate

def julday_360d(date):
    """ Function to provide the julian day of a date in a 360 days/yr (or 12 30-days months) calendar
      date=  date [Y, m, d, h, mi, s]
      >>> julday_360d([1976,2,17,8,30,2])
      47
    """
    fname = 'julday_360d'

    julday = (date[1]-1)*30 + date[2]

    return julday

class dtsec360dyr(object):
    """ Class to operate a number of seconds to a date in a 360 days/yr (or 12 30-days months) calendar
      date = initial date [Y, m, d, h, mi, s]
      delatsec = diferential of seconds to use
      self.year= year new date
      self.month= month new date
      self.day= day new date
      self.hour= hour new date
      self.minute= minute new date
      self.second= second new date
      self.dyear= increment in years
      self.dmonth= increment in months
      self.dday= increment in days
      self.dhour= increment in hours
      self.dminute= increment in minutes
      self.dsecond= increment in seconds
      self.newdate= resultant date as [Y, m, d, h, mi, s]
      >>> dtsec360dyr([1976,2,17,8,27,0], 3680)
      1976 2 17 9 28 20
      0 0 0 1 1 20
      >>> dtsec360dyr([1976,2,17,8,27,0], -3680)
      1976 2 17 7 25 40
      0 0 0 -1 -1 -20
    """
    def __init__(self, date, deltasec):
        fname = 'dtsec360dyr'
        minsec = 60
        hoursec = 60 * minsec
        daysec = 24 * hoursec
        monsec = 30 * daysec
        yrsec = 12 * monsec
        secs = [yrsec,monsec,daysec,hoursec,minsec,1]

        self.year = None
        self.month = None
        self.day = None
        self.hour = None
        self.minute = None
        self.second = None
        self.dyear = None
        self.dmonth = None
        self.dday = None
        self.dhour = None
        self.dminute = None
        self.dsecond = None
        self.newdate = None
        if date is not None and deltasec is not None:
            absdelta = np.abs(deltasec)
            sign  = deltasec/absdelta
            newdate = list(date)
            Ndeltas = np.zeros((6), dtype=int)
            for idt in range(6):
                Ndeltas[idt] = (absdelta-np.sum(Ndeltas[0:idt]*secs[0:idt]))/secs[idt]
                if Ndeltas[idt] != 0:
                    newdate = changedate360(newdate,sign*Ndeltas[idt],idt)

            self.year = newdate[0]
            self.month = newdate[1]
            self.day = newdate[2]
            self.hour = newdate[3]
            self.minute = newdate[4]
            self.second = newdate[5]
            self.dyear = sign*Ndeltas[0]
            self.dmonth = sign*Ndeltas[1]
            self.dday = sign*Ndeltas[2]
            self.dhour = sign*Ndeltas[3]
            self.dminute = sign*Ndeltas[4]
            self.dsecond = sign*Ndeltas[5]
            self.newdate = newdate

def period_information_360d(idate, edate, totunits):
    """ Function to provide the information of a given period idate, edate (dates in [YYYY][MM][DD][HH][MI][SS] format) in a 
      360 years calendar
      [idate]= initial date of the period (in [YYYY][MM][DD][HH][MI][SS] format)
      [edate]= end date of the period (in [YYYY][MM][DD][HH][MI][SS] format)
      [totunits]= latest number of entire temporal units to compute: 'year', 'month', 'day', 'hour', 'minute', 'second'

    resultant information given as ',' list of:
      [dT]: sign of the temporal increment ('pos', 'neg')
      [idate]: initial date as [YYYY]:[MM]:[DD]:[HH]:[MI]:[SS]
      [edate]: end date as [YYYY]:[MM]:[DD]:[HH]:[MI]:[SS]
      [Nsecs]: total seconds between dates
      [Nyears]: Number of years taken as entire units ([iYYYY]0101000000 to [eYYYY+1]0101000000)
      [ExactYears]: Exact year-dates of the period as a '@' separated list of  [YYYY]0101000000
      [Nmonths]: Number of months taken as entire units ([iYYYY][iMM]01000000 to [eYYYY][eMM+1]01000000)
      [ExactMonths]: Exact mon-dates of the period as  a '@' separated list of [YYYY][MM]01000000
      [Ndays]: Number of days taken as entire units ([iYYYY][iMM][iDD]000000 to [eYYYY][eMM][eDD+1]000000)
      [ExactDays]: Exact day-dates of the period as  a '@' separated list of [YYYY][MM][DD]000000
      [Nhours]: Number of hours taken as entire units ([iYYYY][iMM][iDD][iHH]0000 to [eYYYY][eMM][eDD][eHH+1]0000)
      [ExactHours]: Exact hour-dates of the period as a '@' separated list of [YYYY][MM][DD][HH]0000
      [Nminutes]: Number of minutes taken as entire units ([iYYYY][iMM][iDD][iHH][iMI]00 to [eYYYY][eMM][eDD][eHH][eMI+1]00)
      [ExactMinutes]: Exact minutes-dates of the period as a '@' separated list of [YYYY][MM][DD][HH][MI]00
      [Nsecs]: Number of minutes taken as entire units ([iYYYY][iMM][iDD][iHH][iMI][iS] to [eYYYY][eMM][eDD][eHH][eMI][eSE+1])
      [ExactSeconds]: Exact seconds-dates of the period as a '@' separated list of [YYYY][MM][DD][HH][MI][SS]

    >>> period_information_360d( '19760217083110', '19770128000000', 'week')
    pos,1976:02:17:08:31:10,1977:01:28:00:00:00,29863730.0,49,19760217000000@19760224000000@19760301000000@19760308000000@
    19760315000000@19760322000000@19760329000000@19760406000000@19760413000000@19760420000000@19760427000000@
    19760504000000@19760511000000@19760518000000@19760525000000@19760602000000@19760609000000@19760616000000@
    19760623000000@19760630000000@19760707000000@19760714000000@19760721000000@19760728000000@19760805000000@
    19760812000000@19760819000000@19760826000000@19760903000000@19760910000000@19760917000000@19760924000000@
    19761001000000@19761008000000@19761015000000@19761022000000@19761029000000@19761106000000@19761113000000@
    19761120000000@19761127000000@19761204000000@19761211000000@19761218000000@19761225000000@19770102000000@
    19770109000000@19770116000000@19770123000000
    """
    import datetime as dt

    fname = 'period_information_360d'

    if idate == 'h':
        print fname + '_____________________________________________________________'
        print period_information_360d.__doc__
        quit()

    expectargs = '[idate],[edate],[totunits]'
 
    check_arguments(fname,str(idate)+','+str(edate)+','+str(totunits),expectargs,',')

    readyT = ['year','month','week','day','hour','minute','second']

    # Seconds time-units
    minsec = 60
    hoursec = 60 * minsec
    daysec = 24 * hoursec
    monsec = 30 * daysec
    yrsec = 12 * monsec
    secs = [yrsec,monsec,daysec,hoursec,minsec,1]

# Checking length
    Lidate = len(idate)
    Ledate = len(edate)

    if Lidate != Ledate:
        print errormsg
        print '   ' + fname + ': string dates of the period have different length !!'
        print "    idate: '" + idate + "' (L=", Lidate, ") edate: '" + edate +       \
          "' (L=", Ledate, ')'
        quit(-1)
    else:
        if Lidate != 14:
            print errormsg
            print '  ' + fname + ": wrong initial date: '" + idate + "' must " +     \
              'have 14 characters!!'
            print '    and it has:', Lidate
            quit(-1)
        if Ledate != 14:
            print errormsg
            print '  ' + fname + ": wrong end date: '" + edate + "' must " +         \
              'have 14 characters!!'
            print '    and it has:', Ledate
            quit(-1)

# Checking for right order of dates
    if int(idate) > int(edate):
        print warnmsg
        print '  ' + fname + ": initial date '" + idate + "' after end date '" +     \
          edate + "' !!"
        print "  re-sorting them!"
        i1 = edate
        e1 = idate
        idate = i1 
        edate = e1
        oinf = 'neg'
    else:
        oinf = 'pos'

# Year, month, day, hour, minute, second initial date
    iyrS = idate[0:4]
    imoS = idate[4:6]
    idaS = idate[6:8]
    ihoS = idate[8:10]
    imiS = idate[10:12]
    iseS = idate[12:14]

    oinf = oinf + ',' + iyrS+':'+imoS+':'+idaS+':'+ihoS+':'+imiS+':'+iseS

# Year, month, day, hour, minute, second end date
    eyrS = edate[0:4]
    emoS = edate[4:6]
    edaS = edate[6:8]
    ehoS = edate[8:10]
    emiS = edate[10:12]
    eseS = edate[12:14]

    oinf = oinf + ',' + eyrS+':'+emoS+':'+edaS+':'+ehoS+':'+emiS+':'+eseS

    idateT = dt.datetime(int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),int(iseS))
    edateT = dt.datetime(int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS))

# Seconds between dates
    DT = edateT - idateT
    # Python version depending
    if searchInlist(dir(DT), 'total_seconds'):
        Nsecs = DT.total_seconds()
    else:
        Nsecs = DT.days*24*3600. + DT.seconds

    oinf = oinf + ',' + str(Nsecs)

    daysYr = 360
    months = np.ones((12), dtype=int)*1

# Looking for number of years tacking exact beginning of the units [iYYYY]0101000000, [eYYYY+1]0101000000
##
    if totunits == 'year':
        itime = int(iyrS)
        if edate[4:15] != '0101000000':
            etime = int(eyrS)+1
        else:
            etime = int(eyrS)

        itimeT = dt.datetime(itime,1,1,0,0,0)

        Nyears = 1
        ExactYears = itimeT.strftime("%Y%m%d%H%M%S")
        it = int(iyrS)
        while it + 1 <= etime:
            it = it + 1
            Nyears = Nyears + 1
            itT = dt.datetime(it,1,1,0,0,0)
            ExactYears = ExactYears + '@' + itT.strftime("%Y%m%d%H%M%S")

        oinf = oinf + ',' + str(Nyears) + ',' + ExactYears

# Looking for number of months tacking exact beginning of the units [iYYYY][iMM]01000000, [eYYYY][eMM+1]01000000
##
    elif totunits == 'month':
        itime = int(iyrS)*100 + int(imoS)
        if edate[6:15] != '01000000':
            emo1 = int(emoS)+1
            if emo1 > 13:
                eyr1 = str(int(eyrS) + 1)
                emo1 = 01
            else:
                eyr1 = eyrS
            
        else:
            eyr1 = eyrS
            emo1 = emoS
    
        etime = int(eyr1)*100 + int(emo1) 
        itimeT = dt.datetime(int(iyrS),int(imoS),1,0,0,0)
        
        Nmonths = 1
        ExactMonths = itimeT.strftime("%Y%m%d%H%M%S")
        it = itime
        while it + 1 <= etime:
            it = it + 1
            Nmonths = Nmonths + 1
            ityr = it/100
            itmo = it - ityr*100
            if itmo > 12:
                ityr = ityr + 1
                itmo = 1
                it = ityr * 100 + itmo
    
            itT = dt.datetime(ityr,itmo,1,0,0,0)
            ExactMonths = ExactMonths + '@' + itT.strftime("%Y%m%d%H%M%S")
    
        oinf = oinf + ',' + str(Nmonths) + ',' + ExactMonths

# Looking for number of weeks tacking exact beginning of the units [iYYYY][iMM][iDD]000000, [eYYYY][eMM][eDD+7]000000
##
    elif totunits == 'week':
        itime = [int(iyrS),int(imoS),int(idaS),0,0,0]
        if edate[8:15] != '000000':
            etime = [int(eyrS), int(emoS), int(edaS)+7,0,0,0]
        else:
            etime = [int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS)]

        ExactDays = datetimeStr_conversion(itime,'matYmdHMS','YmdHMS')

        erefsecs = diff_dates360(etime,[1,1,1,0,0,0])

        Nweeks = 1
        it = itime
        refsecs = diff_dates360(it,[1,1,1,0,0,0])
        while refsecs + 7*daysec <= erefsecs:
            refsecs = refsecs + 7*daysec
            dateincr = dtsec360dyr(it,7*daysec)
            it = dateincr.newdate
            Nweeks = Nweeks + 1
            ExactDays = ExactDays + '@' + datetimeStr_conversion(it,'matYmdHMS','YmdHMS')

        oinf = oinf + ',' + str(Nweeks) + ',' + ExactDays

# Looking for number of days tacking exact beginning of the units [iYYYY][iMM][iDD]000000, [eYYYY][eMM][eDD+1]000000
##
    elif totunits == 'day':
        itime = [int(iyrS),int(imoS),int(idaS),0,0,0]
        if edate[8:15] != '000000':
            etime = [int(eyrS), int(emoS), int(edaS)+1,0,0,0]
        else:
            etime = [int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS)]

        ExactDays = datetimeStr_conversion(itime,'matYmdHMS','YmdHMS')

        erefsecs = diff_dates360(etime,[1,1,1,0,0,0])

        Ndays = 1
        it = itime
        refsecs = diff_dates360(it,[1,1,1,0,0,0])
        while refsecs + 1*daysec <= erefsecs:
            refsecs = refsecs + 1*daysec
            dateincr = dtsec360dyr(it,1*daysec)
            it = dateincr.newdate
            Ndays = Ndayss + 1
            ExactDays = ExactDays + '@' + datetimeStr_conversion(it,'matYmdHMS','YmdHMS')

        oinf = oinf + ',' + str(Ndays) + ',' + ExactDays

# Looking for number of hours tacking exact beginning of the units [iYYYY][iMM][iDD][iHH]0000, [eYYYY][eMM][eDD][iHH+1]0000
##
    elif totunits == 'hour':
        itime = [int(iyrS),int(imoS),int(idaS),int(ihoS),0,0]
        if edate[10:15] != '0000':
            etime = [int(eyrS), int(emoS), int(edaS), int(ehoS)+1,0,0]
        else:
            etime = [int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS)]
    
        Nhours = 1
        ExactHours = datetimeStr_conversion(itime,'matYmdHMS','YmdHMS')
        erefsecs = diff_dates360(etime,[1,1,1,0,0,0])
        it = itime
        refsecs = diff_dates360(it,[1,1,1,0,0,0])
        while refsecs + 1*daysec <= erefsecs:
            refsecs = refsecs + 1*hoursec
            dateincr = dtsec360dyr(it,1*hoursec)
            it = dateincr.newdate
            Nhours = Nhours + 1
            ExactHours = ExactHours + '@' + datetimeStr_conversion(it,'matYmdHMS','YmdHMS')
    
        oinf = oinf + ',' + str(Nhours) + ',' + ExactHours

# Looking for number of minutes tacking exact beginning of the units [iYYYY][iMM][iDD][iHH][iMI]00, [eYYYY][eMM][eDD][iHH][iMI+1]00
##
    elif totunits == 'minute':
        itime = [int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),0]
        if edate[12:15] != '00':
            etime = [int(eyrS), int(emoS), int(edaS), int(ehoS), int(emiS)+1,0]
        else:
            etime = [int(eyrS),int(emoS),int(edaS),int(ehoS),int(emiS),int(eseS)]

        Nminutes = 1
        ExactMinutes = datetimeStr_conversion(itime,'matYmdHMS','YmdHMS')
        erefsecs = diff_dates360(etime,[1,1,1,0,0,0])
        it = itime
        refsecs = diff_dates360(it,[1,1,1,0,0,0])
        while refsecs + 1*minsec <= erefsecs:
            refsecs = refsecs + 1*minsec
            dateincr = dtsec360dyr(it,1*hoursec)
            Nminutes = Nminutes + 1
            ExactMinutes = ExactMinutes +'@' + datetimeStr_conversion(it,'matYmdHMS',\
              'YmdHMS')
    
        oinf = oinf + ',' + str(Nminutes) + ',' + ExactMinutes

# Looking for number of seconds tacking exact beginning of the units [iYYYY][iMM][iDD][iHH][iMI][iSE], 
#   [eYYYY][eMM][eDD][iHH][iMI][iSE+1]
##
    elif totunits == 'second':
        itime = [int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),int(iseS)]
        if edate[12:15] != '00':
            etime = [int(eyrS), int(emoS), int(edaS), int(ehoS), int(emiS), int(eseS)+1]
        else:
            etime = [int(iyrS),int(imoS),int(idaS),int(ihoS),int(imiS),int(iseS)]

        Nseconds = 1
        ExactSeconds = datetimeStr_conversion(itime,'matYmdHMS','YmdHMS')
        erefsecs = diff_dates360(etime,[1,1,1,0,0,0])
        it = itime
        refsecs = diff_dates360(it,[1,1,1,0,0,0])
        while refsecs + 1 <= erefsecs:
            refsecs = refsecs + 1
            dateincr = dtsec360dyr(it,1*hoursec)
            Nseconds = Nseconds + 1
            ExactSeconds = ExactSeconds + '@'+ datetimeStr_conversion(it,'matYmdHMS',\
              'YmdHMS')
    
        oinf = oinf + ',' + str(Nseconds) + ',' + ExactSeconds

    else:
        print errormsg
        print '  '+ fname + ": totalunits '" + totunits + "' not ready !!"
        print '    total time units ready:', readyT
        quit(-1)

    return oinf

def variables_values(varName):
    """ Function to provide values to plot the different variables values from ASCII file
      'variables_values.dat'
    variables_values(varName)
      [varName]= name of the variable
        return: [var name], [std name], [minimum], [maximum], 
          [long name]('|' for spaces), [units], [color palette] (following: 
          http://matplotlib.org/1.3.1/examples/color/colormaps_reference.html)
     [varn]: original name of the variable
       NOTE: It might be better doing it with an external ASII file. But then we 
         got an extra dependency...
    >>> variables_values('WRFght')
    ['z', 'geopotential_height', 0.0, 80000.0, 'geopotential|height', 'm2s-2', 'rainbow']
    """
    import subprocess as sub

    fname='variables_values'

    if varName == 'h':
        print fname + '_____________________________________________________________'
        print variables_values.__doc__
        quit()

# This does not work....
#    folderins = sub.Popen(["pwd"], stdout=sub.PIPE)
#    folder = list(folderins.communicate())[0].replace('\n','')
# From http://stackoverflow.com/questions/4934806/how-can-i-find-scripts-directory-with-python
    folder = os.path.dirname(os.path.realpath(__file__))

    infile = folder + '/variables_values.dat'

    if not os.path.isfile(infile):
        print errormsg
        print '  ' + fname + ": File '" + infile + "' does not exist !!"
        quit(-1)

# Variables with a statistical section on their name...
    NOstatsvars = ['zmaxth', 'zmax_th', 'lmax_th', 'lmaxth']

    ifst = False
    if not searchInlist(NOstatsvars, varName.lower()):
        for st in statsurname:
            if varName.find(st) > -1:
                print '    '+ fname + ": varibale '" + varName + "' with a " +       \
                  "statistical surname: '",st,"' !!"
                varName = varName.replace(st,'')
                ifst = True
    varn = varName

    ncf = open(infile, 'r')

    for line in ncf:
        if line[0:1] != '#':
            values = line.replace('\n','').split(',')
            if len(values) != 8:
                print errormsg
                print "problem in varibale:'", values[0],                            \
                  'it should have 8 values and it has',len(values)
                quit(-1)

            if varn[0:6] == 'varDIM': 
# Variable from a dimension (all with 'varDIM' prefix)
                Lvarn = len(varn)
                varvals = [varn[6:Lvarn+1], varn[6:Lvarn+1], 0., 1.,                 \
                  "variable|from|size|of|dimension|'" + varn[6:Lvarn+1] + "'", '1',  \
                   'rainbow']
            else:
                varvals = [values[1].replace(' ',''), values[2].replace(' ',''),     \
                  np.float(values[3]), np.float(values[4]),values[5].replace(' ',''),\
                  values[6].replace(' ',''), values[7].replace(' ','')]
            if values[0] == varn:
                ncf.close()
                return varvals
                break

    print errormsg
    print '  ' + fname + ": variable '" + varn + "' not defined !!!"
    ncf.close()
    quit(-1)

    return 

def CFvar_MODvar(varn):
    """ Function to provide which model values can provide a CF-variable from ASCII file
      'variables_values.dat'
    CFvar_MODvar(varn)
      [varn]= CF name of the variable
    >>> CFvar_MODvar('hfss')
    ['hfss', 'LSENS', 'sens', 'HFX', 'hfx']
    >>> CFvar_MODvar('clm')
    ['clm', 'cldm', 'LCLDM', 'Mid-level cloudiness']
    >>> CFvar_MODvar('pr')
    ['pr', 'RAINTOT', 'precip', 'LPRECIP', 'Precip Totale liq+sol']
    """
    import subprocess as sub

    fname='CFvar_MODvar'

    if varn == 'h':
        print fname + '_____________________________________________________________'
        print CFvar_MODvar.__doc__
        quit()

    folder = os.path.dirname(os.path.realpath(__file__))

    infile = folder + '/variables_values.dat'

    if not os.path.isfile(infile):
        print errormsg
        print '  ' + fname + ": File '" + infile + "' does not exist !!"
        quit(-1)

    ncf = open(infile, 'r')

    MODvars = []
    for line in ncf:
        if line[0:1] != '#':
            values = line.replace('\n','').split(',')
            varvals = [values[1].replace(' ',''), values[2].replace(' ',''),         \
              np.float(values[3]), np.float(values[4]),values[5].replace(' ',''),    \
              values[6].replace(' ',''), values[7].replace(' ','')]
            if varvals[0] == varn: MODvars.append(values[0])

    if len(MODvars) == 0:
#        print errormsg
#        print '  ' + fname + ": variable '" + varn + "' not defined !!!"
        ncf.close()
        return None
    else:
        return MODvars

def CFvar_DIAGvar(varn):
    """ Function to provide which model diagnostic values can provide a CF-variable from ASCII file
      'diagnostics.inf' (reference for diagnostics.py')
       [CFname], [moddiag], [varcombo]
         [CFname]: CF name of the variable
         [moddiag]: name of the diagnosted variable (for `diagnostic.py')
         [varcombo]: combnination of variables to be used to compute diagnostic
    CFvar_DIAGvar(varn)
      [varn]= CF name of the variable
    >>> CFvar_DIAGvar('pr')
    {'RAINTOT': ['RAINC', 'RAINNC']}
    >>> CFvar_DIAGvar('hurs')
    {'TSrhs': ['psfc', 't', 'q'], 'LMDZrhs': ['psol', 't2m', 'q2m'], 'WRFrhs': ['PSFC', 'T2', 'Q2']}
    >>> CFvar_DIAGvar('wss')
    {'wss': [['U10', 'V10'], ['u10m', 'v10m']]}
    """
    import subprocess as sub

    fname='CFvar_DIAGvar'

    if varn == 'h':
        print fname + '_____________________________________________________________'
        print CFvar_DIAGvar.__doc__
        quit()

    folder = os.path.dirname(os.path.realpath(__file__))

    infile = folder + '/diagnostics.inf'
    if not os.path.isfile(infile):
        print errormsg
        print '  ' + fname + ": File '" + infile + "' does not exist !!"
        quit(-1)

    ncf = open(infile, 'r')

    MODvars = {}
    for line in ncf:
        if line[0:1] != '#':
            values = line.replace('\n','').replace(' ','').split(',')
            if values[0] == varn: 
                MODdiags = values[2].split('@')
                if MODvars.has_key(values[1]):
                    oldvals = MODvars[values[1]]
                    oldvals = [oldvals, MODdiags]
                    MODvars[values[1]] = oldvals
                else:
                    MODvars[values[1]] = MODdiags

    if len(MODvars) == 0:
#        print errormsg
#        print '  ' + fname + ": variable '" + varn + "' not defined !!!"
        ncf.close()
        return None
    else:
        ncf.close()
        return MODvars

def variables_values_old(varName):
    """ Function to provide values to plot the different variables
    variables_values(varName)
      [varName]= name of the variable
        return: [var name], [std name], [minimum], [maximum], 
          [long name]('|' for spaces), [units], [color palette] (following: 
          http://matplotlib.org/1.3.1/examples/color/colormaps_reference.html)
     [varn]: original name of the variable
       NOTE: It might be better doing it with an external ASII file. But then we 
         got an extra dependency...
    >>> variables_values('WRFght')
    ['z', 'geopotential_height', 0.0, 80000.0, 'geopotential|height', 'm2s-2', 'rainbow']
    """
    fname='variables_values'

    if varName == 'h':
        print fname + '_____________________________________________________________'
        print variables_values.__doc__
        quit()

# Variable name might come with a statistical surname...
    stats=['min','max','mean','stdv', 'sum']

    ifst = False
    for st in stats:
        if varName.find(st) > -1:
            print '    '+ fname + ": varibale '" + varName + "' with a statistical "+\
              " surname: '",st,"' !!"
            Lst = len(st)
            LvarName = len(varName)
            varn = varName[0:LvarName - Lst]
            ifst = True
            break
    if not ifst:
        varn = varName

    if varn[0:6] == 'varDIM': 
# Variable from a dimension (all with 'varDIM' prefix)
        Lvarn = len(varn)
        varvals = [varn[6:Lvarn+1], varn[6:Lvarn+1], 0., 1.,                         \
          "variable|from|size|of|dimension|'" + varn[6:Lvarn+1] + "'", '1', 'rainbox']
    elif varn == 'a_tht' or varn == 'LA_THT':
        varvals = ['ath', 'total_thermal_plume_cover', 0., 1.,                       \
        'total|column|thermal|plume|cover', '1', 'YlGnBu']
    elif varn == 'acprc' or varn == 'RAINC':
        varvals = ['acprc', 'accumulated_cmulus_precipitation', 0., 3.e4,            \
          'accumulated|cmulus|precipitation', 'mm', 'Blues']
    elif varn == 'acprnc' or varn == 'RAINNC':
        varvals = ['acprnc', 'accumulated_non-cmulus_precipitation', 0., 3.e4,       \
          'accumulated|non-cmulus|precipitation', 'mm', 'Blues']
    elif varn == 'bils' or varn == 'LBILS':
        varvals = ['bils', 'surface_total_heat_flux', -100., 100.,                   \
          'surface|total|heat|flux', 'Wm-2', 'seismic']
    elif varn == 'landcat' or varn == 'category':
        varvals = ['landcat', 'land_categories', 0., 22., 'land|categories', '1',    \
          'rainbow']
    elif varn == 'c' or varn == 'QCLOUD' or varn == 'oliq' or varn == 'OLIQ':
        varvals = ['c', 'condensed_water_mixing_ratio', 0., 3.e-4,                   \
          'condensed|water|mixing|ratio', 'kgkg-1', 'BuPu']
    elif varn == 'ci' or varn == 'iwcon' or varn == 'LIWCON':
        varvals = ['ci', 'cloud_iced_water_mixing_ratio', 0., 0.0003,                \
         'cloud|iced|water|mixing|ratio', 'kgkg-1', 'Purples']
    elif varn == 'cl' or varn == 'lwcon' or varn == 'LLWCON':
        varvals = ['cl', 'cloud_liquidwater_mixing_ratio', 0., 0.0003,               \
         'cloud|liquid|water|mixing|ratio', 'kgkg-1', 'Blues']
    elif varn == 'cld' or varn == 'CLDFRA' or varn == 'rneb' or varn == 'lrneb' or   \
      varn == 'LRNEB':
        varvals = ['cld', 'cloud_area_fraction', 0., 1., 'cloud|fraction', '1',      \
          'gist_gray']
    elif varn == 'cldc' or varn == 'rnebcon' or varn == 'lrnebcon' or                \
      varn == 'LRNEBCON':
        varvals = ['cldc', 'convective_cloud_area_fraction', 0., 1.,                 \
          'convective|cloud|fraction', '1', 'gist_gray']
    elif varn == 'cldl' or varn == 'rnebls' or varn == 'lrnebls' or varn == 'LRNEBLS':
        varvals = ['cldl', 'large_scale_cloud_area_fraction', 0., 1.,                \
          'large|scale|cloud|fraction', '1', 'gist_gray']
    elif varn == 'clt' or varn == 'CLT' or varn == 'cldt' or                         \
      varn == 'Total cloudiness':
        varvals = ['clt', 'cloud_area_fraction', 0., 1., 'total|cloud|cover', '1',   \
          'gist_gray']
    elif varn == 'cll' or varn == 'cldl' or varn == 'LCLDL' or                       \
      varn == 'Low-level cloudiness':
        varvals = ['cll', 'low_level_cloud_area_fraction', 0., 1.,                   \
          'low|level|(p|>|680|hPa)|cloud|fraction', '1', 'gist_gray']
    elif varn == 'clm' or varn == 'cldm' or varn == 'LCLDM' or                       \
      varn == 'Mid-level cloudiness':
        varvals = ['clm', 'mid_level_cloud_area_fraction', 0., 1.,                   \
          'medium|level|(440|<|p|<|680|hPa)|cloud|fraction', '1', 'gist_gray']
    elif varn == 'clh' or varn == 'cldh' or varn == 'LCLDH' or                       \
      varn == 'High-level cloudiness':
        varvals = ['clh', 'high_level_cloud_area_fraction', 0., 1.,                  \
          'high|level|(p|<|440|hPa)|cloud|fraction', '1', 'gist_gray']
    elif varn == 'clmf' or varn == 'fbase' or varn == 'LFBASE':
        varvals = ['clmf', 'cloud_base_max_flux', -0.3, 0.3, 'cloud|base|max|flux',  \
          'kgm-2s-1', 'seismic']
    elif varn == 'clp' or varn == 'pbase' or varn == 'LPBASE':
        varvals = ['clp', 'cloud_base_pressure', -0.3, 0.3, 'cloud|base|pressure',   \
          'Pa', 'Reds']
    elif varn == 'cpt' or varn == 'ptconv' or varn == 'LPTCONV':
        varvals = ['cpt', 'convective_point', 0., 1., 'convective|point', '1',       \
          'seismic']
    elif varn == 'dqajs' or varn == 'LDQAJS':
        varvals = ['dqajs', 'dry_adjustment_water_vapor_tendency', -0.0003, 0.0003,  \
        'dry|adjustment|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqcon' or varn == 'LDQCON':
        varvals = ['dqcon', 'convective_water_vapor_tendency', -3e-8, 3.e-8,         \
        'convective|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqdyn' or varn == 'LDQDYN':
        varvals = ['dqdyn', 'dynamics_water_vapor_tendency', -3.e-7, 3.e-7,          \
        'dynamics|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqeva' or varn == 'LDQEVA':
        varvals = ['dqeva', 'evaporation_water_vapor_tendency', -3.e-6, 3.e-6,       \
        'evaporation|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqlscst' or varn == 'LDQLSCST':
        varvals = ['dqlscst', 'stratocumulus_water_vapor_tendency', -3.e-7, 3.e-7,   \
        'stratocumulus|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqlscth' or varn == 'LDQLSCTH': 
        varvals = ['dqlscth', 'thermals_water_vapor_tendency', -3.e-7, 3.e-7,        \
        'thermal|plumes|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqlsc' or varn == 'LDQLSC':
        varvals = ['dqlsc', 'condensation_water_vapor_tendency', -3.e-6, 3.e-6,      \
        'condensation|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqphy' or varn == 'LDQPHY':
        varvals = ['dqphy', 'physics_water_vapor_tendency', -3.e-7, 3.e-7,           \
        'physics|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqthe' or varn == 'LDQTHE':
        varvals = ['dqthe', 'thermals_water_vapor_tendency', -3.e-7, 3.e-7,          \
        'thermal|plumes|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqvdf' or varn == 'LDQVDF':
        varvals = ['dqvdf', 'vertical_difussion_water_vapor_tendency', -3.e-8, 3.e-8,\
        'vertical|difussion|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dqwak' or varn == 'LDQWAK':
        varvals = ['dqwak', 'wake_water_vapor_tendency', -3.e-7, 3.e-7,              \
        'wake|water|vapor|tendency', 'kg/kg/s', 'seismic']
    elif varn == 'dta' or varn == 'tnt' or varn == 'LTNT':
        varvals = ['dta', 'tendency_air_temperature', -3.e-3, 3.e-3,                 \
        'tendency|of|air|temperature', 'K/s', 'seismic']
    elif varn == 'dtac' or varn == 'tntc' or varn == 'LTNTC':
        varvals = ['dtac', 'moist_convection_tendency_air_temperature', -3.e-3,      \
        3.e-3, 'moist|convection|tendency|of|air|temperature', 'K/s', 'seismic']
    elif varn == 'dtar' or varn == 'tntr' or varn == 'LTNTR':
        varvals = ['dtar', 'radiative_heating_tendency_air_temperature', -3.e-3,     \
          3.e-3, 'radiative|heating|tendency|of|air|temperature', 'K/s', 'seismic']
    elif varn == 'dtascpbl' or varn == 'tntscpbl' or varn == 'LTNTSCPBL':
        varvals = ['dtascpbl',                                                       \
          'stratiform_cloud_precipitation_BL_mixing_tendency_air_temperature',       \
          -3.e-6, 3.e-6,                                                             \
          'stratiform|cloud|precipitation|Boundary|Layer|mixing|tendency|air|'       +
          'temperature', 'K/s', 'seismic']
    elif varn == 'dtajs' or varn == 'LDTAJS':
        varvals = ['dtajs', 'dry_adjustment_thermal_tendency', -3.e-5, 3.e-5,        \
        'dry|adjustment|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtcon' or varn == 'LDTCON':
        varvals = ['dtcon', 'convective_thermal_tendency', -3.e-5, 3.e-5,            \
        'convective|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtdyn' or varn == 'LDTDYN':
        varvals = ['dtdyn', 'dynamics_thermal_tendency', -3.e-4, 3.e-4,              \
        'dynamics|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dteva' or varn == 'LDTEVA':
        varvals = ['dteva', 'evaporation_thermal_tendency', -3.e-3, 3.e-3,           \
        'evaporation|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtlscst' or varn == 'LDTLSCST':
        varvals = ['dtlscst', 'stratocumulus_thermal_tendency', -3.e-4, 3.e-4,       \
        'stratocumulus|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtlscth' or varn == 'LDTLSCTH':
        varvals = ['dtlscth', 'thermals_thermal_tendency', -3.e-4, 3.e-4,            \
        'thermal|plumes|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtlsc' or varn == 'LDTLSC':
        varvals = ['dtlsc', 'condensation_thermal_tendency', -3.e-3, 3.e-3,          \
        'condensation|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtlwr' or varn == 'LDTLWR':
        varvals = ['dtlwr', 'long_wave_thermal_tendency', -3.e-3, 3.e-3, \
        'long|wave|radiation|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtphy' or varn == 'LDTPHY':
        varvals = ['dtphy', 'physics_thermal_tendency', -3.e-4, 3.e-4,               \
        'physics|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtsw0' or varn == 'LDTSW0':
        varvals = ['dtsw0', 'cloudy_sky_short_wave_thermal_tendency', -3.e-4, 3.e-4, \
        'cloudy|sky|short|wave|radiation|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtthe' or varn == 'LDTTHE':
        varvals = ['dtthe', 'thermals_thermal_tendency', -3.e-4, 3.e-4,              \
        'thermal|plumes|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtvdf' or varn == 'LDTVDF':
        varvals = ['dtvdf', 'vertical_difussion_thermal_tendency', -3.e-5, 3.e-5,    \
        'vertical|difussion|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'dtwak' or varn == 'LDTWAK':
        varvals = ['dtwak', 'wake_thermal_tendency', -3.e-4, 3.e-4,                  \
        'wake|thermal|tendency', 'K/s', 'seismic']
    elif varn == 'ducon' or varn == 'LDUCON':
        varvals = ['ducon', 'convective_eastward_wind_tendency', -3.e-3, 3.e-3,      \
        'convective|eastward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'dudyn' or varn == 'LDUDYN':
        varvals = ['dudyn', 'dynamics_eastward_wind_tendency', -3.e-3, 3.e-3,        \
        'dynamics|eastward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'duvdf' or varn == 'LDUVDF':
        varvals = ['duvdf', 'vertical_difussion_eastward_wind_tendency', -3.e-3,     \
         3.e-3, 'vertical|difussion|eastward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'dvcon' or varn == 'LDVCON':
        varvals = ['dvcon', 'convective_difussion_northward_wind_tendency', -3.e-3,  \
         3.e-3, 'convective|northward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'dvdyn' or varn == 'LDVDYN':
        varvals = ['dvdyn', 'dynamics_northward_wind_tendency', -3.e-3,              \
         3.e-3, 'dynamics|difussion|northward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'dvvdf' or varn == 'LDVVDF':
        varvals = ['dvvdf', 'vertical_difussion_northward_wind_tendency', -3.e-3,    \
         3.e-3, 'vertical|difussion|northward|wind|tendency', 'ms-2', 'seismic']
    elif varn == 'etau' or varn == 'ZNU':
        varvals = ['etau', 'etau', 0., 1, 'eta values on half (mass) levels', '-',   \
        'reds']
    elif varn == 'evspsbl' or varn == 'LEVAP' or varn == 'evap' or varn == 'SFCEVPde':
        varvals = ['evspsbl', 'water_evaporation_flux', 0., 1.5e-4,                  \
          'water|evaporation|flux', 'kgm-2s-1', 'Blues']
    elif varn == 'evspsbl' or varn == 'SFCEVPde':
        varvals = ['evspsblac', 'water_evaporation_flux_ac', 0., 1.5e-4,             \
          'accumulated|water|evaporation|flux', 'kgm-2', 'Blues']
    elif varn == 'g' or varn == 'QGRAUPEL':
        varvals = ['g', 'grauepl_mixing_ratio', 0., 0.0003, 'graupel|mixing|ratio',  \
          'kgkg-1', 'Purples']
    elif varn == 'h2o' or varn == 'LH2O':
        varvals = ['h2o', 'water_mass_fraction', 0., 3.e-2,                          \
          'mass|fraction|of|water', '1', 'Blues']
    elif varn == 'h' or varn == 'QHAIL':
        varvals = ['h', 'hail_mixing_ratio', 0., 0.0003, 'hail|mixing|ratio',        \
          'kgkg-1', 'Purples']
    elif varn == 'hfls' or varn == 'LH' or varn == 'LFLAT' or varn == 'flat':
        varvals = ['hfls', 'surface_upward_latent_heat_flux', -400., 400.,           \
          'upward|latnt|heat|flux|at|the|surface', 'Wm-2', 'seismic']
    elif varn == 'hfss' or varn == 'LSENS' or varn == 'sens':
        varvals = ['hfss', 'surface_upward_sensible_heat_flux', -150., 150.,         \
          'upward|sensible|heat|flux|at|the|surface', 'Wm-2', 'seismic']
    elif varn == 'hus' or varn == 'WRFrh' or varn == 'LMDZrh' or varn == 'rhum' or   \
      varn == 'LRHUM':
        varvals = ['hus', 'specific_humidity', 0., 1., 'specific|humidty', '1',      \
          'BuPu']
    elif varn == 'huss' or varn == 'WRFrhs' or varn == 'LMDZrhs' or varn == 'rh2m' or\
      varn == 'LRH2M':
        varvals = ['huss', 'specific_humidity', 0., 1., 'specific|humidty|at|2m',    \
          '1', 'BuPu']
    elif varn == 'i' or varn == 'QICE':
        varvals = ['i', 'iced_water_mixing_ratio', 0., 0.0003,                       \
         'iced|water|mixing|ratio', 'kgkg-1', 'Purples']
    elif varn == 'lat' or varn == 'XLAT' or varn == 'XLAT_M' or varn == 'latitude':
        varvals = ['lat', 'latitude', -90., 90., 'latitude', 'degrees North',        \
          'seismic']
    elif varn == 'lcl' or varn == 's_lcl' or varn == 'ls_lcl' or varn == 'LS_LCL':
        varvals = ['lcl', 'condensation_level', 0., 2500., 'level|of|condensation',  \
          'm', 'Greens']
    elif varn == 'lambdath' or varn == 'lambda_th' or varn == 'LLAMBDA_TH':
        varvals = ['lambdath', 'thermal_plume_vertical_velocity', -30., 30.,         \
          'thermal|plume|vertical|velocity', 'm/s', 'seismic']
    elif varn == 'lmaxth' or varn == 'LLMAXTH':
        varvals = ['lmaxth', 'upper_level_thermals', 0., 100., 'upper|level|thermals'\
          , '1', 'Greens']
    elif varn == 'lon' or varn == 'XLONG' or varn == 'XLONG_M':
        varvals = ['lon', 'longitude', -180., 180., 'longitude', 'degrees East',     \
          'seismic']
    elif varn == 'longitude':
        varvals = ['lon', 'longitude', 0., 360., 'longitude', 'degrees East',        \
          'seismic']
    elif varn == 'orog' or varn == 'HGT' or varn == 'HGT_M':
        varvals = ['orog', 'orography',  0., 3000., 'surface|altitude', 'm','terrain']
    elif varn == 'pfc' or varn == 'plfc' or varn == 'LPLFC':
        varvals = ['pfc', 'pressure_free_convection', 100., 1100.,                   \
          'pressure|free|convection', 'hPa', 'BuPu']
    elif varn == 'plcl' or varn == 'LPLCL':
        varvals = ['plcl', 'pressure_lifting_condensation_level', 700., 1100.,       \
          'pressure|lifting|condensation|level', 'hPa', 'BuPu']
    elif varn == 'pr' or varn == 'RAINTOT' or varn == 'precip' or                    \
      varn == 'LPRECIP' or varn == 'Precip Totale liq+sol':
        varvals = ['pr', 'precipitation_flux', 0., 1.e-4, 'precipitation|flux',      \
          'kgm-2s-1', 'BuPu']
    elif varn == 'prprof' or varn == 'vprecip' or varn == 'LVPRECIP':
        varvals = ['prprof', 'precipitation_profile', 0., 1.e-3,                     \
          'precipitation|profile', 'kg/m2/s', 'BuPu']
    elif varn == 'prprofci' or varn == 'pr_con_i' or varn == 'LPR_CON_I':
        varvals = ['prprofci', 'precipitation_profile_convective_i', 0., 1.e-3,      \
          'precipitation|profile|convective|i', 'kg/m2/s', 'BuPu']
    elif varn == 'prprofcl' or varn == 'pr_con_l' or varn == 'LPR_CON_L':
        varvals = ['prprofcl', 'precipitation_profile_convective_l', 0., 1.e-3,      \
          'precipitation|profile|convective|l', 'kg/m2/s', 'BuPu']
    elif varn == 'prprofli' or varn == 'pr_lsc_i' or varn == 'LPR_LSC_I':
        varvals = ['prprofli', 'precipitation_profile_large_scale_i', 0., 1.e-3,     \
          'precipitation|profile|large|scale|i', 'kg/m2/s', 'BuPu']
    elif varn == 'prprofll' or varn == 'pr_lsc_l' or varn == 'LPR_LSC_L':
        varvals = ['prprofll', 'precipitation_profile_large_scale_l', 0., 1.e-3,     \
          'precipitation|profile|large|scale|l', 'kg/m2/s', 'BuPu']
    elif varn == 'pracc' or varn == 'ACRAINTOT':
        varvals = ['pracc', 'precipitation_amount', 0., 100.,                        \
          'accumulated|precipitation', 'kgm-2', 'BuPu']
    elif varn == 'prc' or varn == 'LPLUC' or varn == 'pluc' or varn == 'WRFprc' or   \
      varn == 'RAINCde':
        varvals = ['prc', 'convective_precipitation_flux', 0., 2.e-4,                \
          'convective|precipitation|flux', 'kgm-2s-1', 'Blues']
    elif varn == 'prci' or varn == 'pr_con_i' or varn == 'LPR_CON_I':
        varvals = ['prci', 'convective_ice_precipitation_flux', 0., 0.003,           \
          'convective|ice|precipitation|flux', 'kgm-2s-1', 'Purples']
    elif varn == 'prcl' or varn == 'pr_con_l' or varn == 'LPR_CON_L':
        varvals = ['prcl', 'convective_liquid_precipitation_flux', 0., 0.003,        \
          'convective|liquid|precipitation|flux', 'kgm-2s-1', 'Blues']
    elif varn == 'pres' or varn == 'presnivs' or varn == 'pressure' or               \
      varn == 'lpres' or varn == 'LPRES':
        varvals = ['pres', 'air_pressure', 0., 103000., 'air|pressure', 'Pa',        \
          'Blues']
    elif varn == 'prls' or varn == 'WRFprls' or varn == 'LPLUL' or varn == 'plul' or \
       varn == 'RAINNCde':
        varvals = ['prls', 'large_scale_precipitation_flux', 0., 2.e-4,              \
          'large|scale|precipitation|flux', 'kgm-2s-1', 'Blues']
    elif varn == 'prsn' or varn == 'SNOW' or varn == 'snow' or varn == 'LSNOW':
        varvals = ['prsn', 'snowfall', 0., 1.e-4, 'snowfall|flux', 'kgm-2s-1', 'BuPu']
    elif varn == 'prw' or varn == 'WRFprh':
        varvals = ['prw', 'atmosphere_water_vapor_content', 0., 10.,                 \
          'water|vapor"path', 'kgm-2', 'Blues']
    elif varn == 'ps' or varn == 'psfc' or varn =='PSFC' or varn == 'psol' or        \
      varn == 'Surface Pressure':
        varvals=['ps', 'surface_air_pressure', 85000., 105400., 'surface|pressure',  \
          'hPa', 'cool']
    elif varn == 'psl' or varn == 'mslp' or varn =='WRFmslp':
        varvals=['psl', 'air_pressure_at_sea_level', 85000., 104000.,                \
          'mean|sea|level|pressure', 'Pa', 'Greens']
    elif varn == 'qth' or varn == 'q_th' or varn == 'LQ_TH':
        varvals = ['qth', 'thermal_plume_total_water_content', 0., 25.,              \
          'total|water|cotent|in|thermal|plume', 'mm', 'YlOrRd']
    elif varn == 'r' or varn == 'QVAPOR' or varn == 'ovap' or varn == 'LOVAP':
        varvals = ['r', 'water_mixing_ratio', 0., 0.03, 'water|mixing|ratio',        \
          'kgkg-1', 'BuPu']
    elif varn == 'r2' or varn == 'Q2':
        varvals = ['r2', 'water_mixing_ratio_at_2m', 0., 0.03, 'water|mixing|' +     \
          'ratio|at|2|m','kgkg-1', 'BuPu']
    elif varn == 'rsds' or varn == 'SWdnSFC' or varn == 'SWdn at surface' or         \
      varn == 'SWDOWN':
        varvals=['rsds', 'surface_downwelling_shortwave_flux_in_air',  0., 1200.,    \
          'downward|SW|surface|radiation', 'Wm-2' ,'Reds']
    elif varn == 'rsdsacc':
        varvals=['rsdsacc', 'accumulated_surface_downwelling_shortwave_flux_in_air', \
          0., 1200., 'accumulated|downward|SW|surface|radiation', 'Wm-2' ,'Reds']
    elif varn == 'rvor' or varn == 'WRFrvor':
        varvals = ['rvor', 'air_relative_vorticity', -2.5E-3, 2.5E-3,                \
          'air|relative|vorticity', 's-1', 'seismic']
    elif varn == 'rvors' or varn == 'WRFrvors':
        varvals = ['rvors', 'surface_air_relative_vorticity', -2.5E-3, 2.5E-3,       \
          'surface|air|relative|vorticity', 's-1', 'seismic']
    elif varn == 's' or varn == 'QSNOW':
        varvals = ['s', 'snow_mixing_ratio', 0., 0.0003, 'snow|mixing|ratio',        \
          'kgkg-1', 'Purples']
    elif varn == 'stherm' or varn == 'LS_THERM':
        varvals = ['stherm', 'thermals_excess', 0., 0.8, 'thermals|excess', 'K',     \
          'Reds']
    elif varn == 'ta' or varn == 'WRFt' or varn == 'temp' or varn == 'LTEMP' or      \
      varn == 'Air temperature':
        varvals = ['ta', 'air_temperature', 195., 320., 'air|temperature', 'K',      \
          'YlOrRd']
    elif varn == 'tah' or varn == 'theta' or varn == 'LTHETA':
        varvals = ['tah', 'potential_air_temperature', 195., 320.,                   \
          'potential|air|temperature', 'K', 'YlOrRd']
    elif varn == 'tas' or varn == 'T2' or varn == 't2m' or varn == 'T2M' or          \
      varn == 'Temperature 2m':
        varvals = ['tas', 'air_temperature', 240., 310., 'air|temperature|at|2m', '  \
          K', 'YlOrRd']
    elif varn == 'tds' or varn == 'TH2':
        varvals = ['tds', 'air_dew_point_temperature', 240., 310.,                   \
          'air|dew|point|temperature|at|2m', 'K', 'YlGnBu']
    elif varn == 'tke' or varn == 'TKE' or varn == 'tke' or varn == 'LTKE':
        varvals = ['tke', 'turbulent_kinetic_energy', 0., 0.003,                     \
          'turbulent|kinetic|energy', 'm2/s2', 'Reds']
    elif varn == 'time'or varn == 'time_counter':
        varvals = ['time', 'time', 0., 1000., 'time',                                \
          'hours|since|1949/12/01|00:00:00', 'Reds']
    elif varn == 'tmla' or varn == 's_pblt' or varn == 'LS_PBLT':
        varvals = ['tmla', 'atmosphere_top_boundary_layer_temperature', 250., 330.,  \
          'atmosphere|top|boundary|layer|temperature', 'K', 'Reds']
    elif varn == 'ua' or varn == 'vitu' or varn == 'U' or varn == 'Zonal wind' or    \
      varn == 'LVITU':
        varvals = ['ua', 'eastward_wind', -30., 30., 'eastward|wind', 'ms-1',        \
          'seismic']
    elif varn == 'uas' or varn == 'u10m' or varn == 'U10' or varn =='Vent zonal 10m':
        varvals = ['uas', 'eastward_wind', -30., 30., 'eastward|2m|wind',    \
          'ms-1', 'seismic']
    elif varn == 'va' or varn == 'vitv' or varn == 'V' or varn == 'Meridional wind'  \
      or varn == 'LVITV':
        varvals = ['va', 'northward_wind', -30., 30., 'northward|wind', 'ms-1',      \
          'seismic']
    elif varn == 'vas' or varn == 'v10m' or varn == 'V10' or                         \
      varn =='Vent meridien 10m':
        varvals = ['vas', 'northward_wind', -30., 30., 'northward|2m|wind', 'ms-1',  \
          'seismic']
    elif varn == 'wakedeltaq' or varn == 'wake_deltaq' or varn == 'lwake_deltaq' or  \
      varn == 'LWAKE_DELTAQ':
        varvals = ['wakedeltaq', 'wake_delta_vapor', -0.003, 0.003,                  \
          'wake|delta|mixing|ratio', '-', 'seismic']
    elif varn == 'wakedeltat' or varn == 'wake_deltat' or varn == 'lwake_deltat' or  \
      varn == 'LWAKE_DELTAT':
        varvals = ['wakedeltat', 'wake_delta_temp', -0.003, 0.003,                   \
          'wake|delta|temperature', '-', 'seismic']
    elif varn == 'wakeh' or varn == 'wake_h' or varn == 'LWAKE_H':
        varvals = ['wakeh', 'wake_height', 0., 1000., 'height|of|the|wakes', 'm',    \
          'YlOrRd']
    elif varn == 'wakeomg' or varn == 'wake_omg' or varn == 'lwake_omg' or           \
      varn == 'LWAKE_OMG':
        varvals = ['wakeomg', 'wake_omega', 0., 3., 'wake|omega', \
          '-', 'BuGn']
    elif varn == 'wakes' or varn == 'wake_s' or varn == 'LWAKE_S':
        varvals = ['wakes', 'wake_area_fraction', 0., 0.5, 'wake|spatial|fraction',  \
          '1', 'BuGn']
    elif varn == 'wa' or varn == 'W' or varn == 'Vertical wind':
        varvals = ['wa', 'upward_wind', -10., 10., 'upward|wind', 'ms-1',            \
          'seismic']
    elif varn == 'wap' or varn == 'vitw' or varn == 'LVITW':
        varvals = ['wap', 'upward_wind', -3.e-10, 3.e-10, 'upward|wind', 'mPa-1',    \
          'seismic']
    elif varn == 'wss' or varn == 'SPDUV':
        varvals = ['wss', 'air_velocity',  0., 30., 'surface|horizontal|wind|speed', \
          'ms-1', 'Reds']
# Water budget
# Water budget de-accumulated
    elif varn == 'ccond' or varn == 'CCOND' or varn == 'ACCCONDde':
        varvals = ['ccond', 'cw_cond',  0., 30.,                                     \
          'cloud|water|condensation', 'mm', 'Reds']
    elif varn == 'wbr' or varn == 'ACQVAPORde':
        varvals = ['wbr', 'wbr',  0., 30., 'Water|Budget|water|wapor', 'mm', 'Blues']
    elif varn == 'diabh' or varn == 'DIABH' or varn == 'ACDIABHde':
        varvals = ['diabh', 'diabh',  0., 30., 'diabatic|heating', 'K', 'Reds']
    elif varn == 'wbpw' or varn == 'WBPW' or varn == 'WBACPWde':
        varvals = ['wbpw', 'water_budget_pw',  0., 30., 'Water|Budget|water|content',\
           'mms-1', 'Reds']
    elif varn == 'wbf' or varn == 'WBACF' or varn == 'WBACFde':
        varvals = ['wbf', 'water_budget_hfcqv',  0., 30.,                       \
          'Water|Budget|horizontal|convergence|of|water|vapour|(+,|' +   \
          'conv.;|-,|div.)', 'mms-1', 'Reds']
    elif varn == 'wbfc' or varn == 'WBFC' or varn == 'WBACFCde':
        varvals = ['wbfc', 'water_budget_fc',  0., 30.,                         \
          'Water|Budget|horizontal|convergence|of|cloud|(+,|conv.;|-,|' +\
          'div.)', 'mms-1', 'Reds']
    elif varn == 'wbfp' or varn == 'WBFP' or varn == 'WBACFPde':
        varvals = ['wbfp', 'water_budget_cfp',  0., 30.,                        \
          'Water|Budget|horizontal|convergence|of|precipitation|(+,|' +  \
          'conv.;|-,|div.)', 'mms-1', 'Reds']
    elif varn == 'wbz' or varn == 'WBZ' or varn == 'WBACZde':
        varvals = ['wbz', 'water_budget_z',  0., 30.,                           \
          'Water|Budget|vertical|convergence|of|water|vapour|(+,|conv.' +\
          ';|-,|div.)', 'mms-1', 'Reds']
    elif varn == 'wbc' or varn == 'WBC' or varn == 'WBACCde':
        varvals = ['wbc', 'water_budget_c',  0., 30.,                           \
          'Water|Budget|Cloud|water|species','mms-1', 'Reds']
    elif varn == 'wbqvd' or varn == 'WBQVD' or varn == 'WBACQVDde':
        varvals = ['wbqvd', 'water_budget_qvd',  0., 30.,                       \
          'Water|Budget|water|vapour|divergence', 'mms-1', 'Reds']
    elif varn == 'wbqvblten' or varn == 'WBQVBLTEN' or varn == 'WBACQVBLTENde':
        varvals = ['wbqvblten', 'water_budget_qv_blten',  0., 30.,              \
          'Water|Budget|QV|tendency|due|to|pbl|parameterization',        \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbqvcuten' or varn == 'WBQVCUTEN' or varn == 'WBACQVCUTENde':
        varvals = ['wbqvcuten', 'water_budget_qv_cuten',  0., 30.,              \
          'Water|Budget|QV|tendency|due|to|cu|parameterization',         \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbqvshten' or varn == 'WBQVSHTEN' or varn == 'WBACQVSHTENde':
        varvals = ['wbqvshten', 'water_budget_qv_shten',  0., 30.,              \
          'Water|Budget|QV|tendency|due|to|shallow|cu|parameterization', \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbpr' or varn == 'WBP' or varn == 'WBACPde':
        varvals = ['wbpr', 'water_budget_pr',  0., 30.,                         \
          'Water|Budget|recipitation', 'mms-1', 'Reds']
    elif varn == 'wbpw' or varn == 'WBPW' or varn == 'WBACPWde':
        varvals = ['wbpw', 'water_budget_pw',  0., 30.,                         \
          'Water|Budget|water|content', 'mms-1', 'Reds']
    elif varn == 'wbcondt' or varn == 'WBCONDT' or varn == 'WBACCONDTde':
        varvals = ['wbcondt', 'water_budget_condt',  0., 30.,                   \
          'Water|Budget|condensation|and|deposition', 'mms-1', 'Reds']
    elif varn == 'wbqcm' or varn == 'WBQCM' or varn == 'WBACQCMde':
        varvals = ['wbqcm', 'water_budget_qcm',  0., 30.,                       \
          'Water|Budget|hydrometeor|change|and|convergence', 'mms-1', 'Reds']
    elif varn == 'wbsi' or varn == 'WBSI' or varn == 'WBACSIde':
        varvals = ['wbsi', 'water_budget_si',  0., 30.,                         \
          'Water|Budget|hydrometeor|sink', 'mms-1', 'Reds']
    elif varn == 'wbso' or varn == 'WBSO' or varn == 'WBACSOde':
        varvals = ['wbso', 'water_budget_so',  0., 30.,                         \
          'Water|Budget|hydrometeor|source', 'mms-1', 'Reds']
# Water Budget accumulated
    elif varn == 'ccondac' or varn == 'ACCCOND':
        varvals = ['ccondac', 'cw_cond_ac',  0., 30.,                                \
          'accumulated|cloud|water|condensation', 'mm', 'Reds']
    elif varn == 'rac' or varn == 'ACQVAPOR':
        varvals = ['rac', 'ac_r',  0., 30., 'accumualted|water|wapor', 'mm', 'Blues']
    elif varn == 'diabhac' or varn == 'ACDIABH':
        varvals = ['diabhac', 'diabh_ac',  0., 30., 'accumualted|diabatic|heating',  \
          'K', 'Reds']
    elif varn == 'wbpwac' or varn == 'WBACPW':
        varvals = ['wbpwac', 'water_budget_pw_ac',  0., 30.,                         \
          'Water|Budget|accumulated|water|content', 'mm', 'Reds']
    elif varn == 'wbfac' or varn == 'WBACF':
        varvals = ['wbfac', 'water_budget_hfcqv_ac',  0., 30.,                       \
          'Water|Budget|accumulated|horizontal|convergence|of|water|vapour|(+,|' +   \
          'conv.;|-,|div.)', 'mm', 'Reds']
    elif varn == 'wbfcac' or varn == 'WBACFC':
        varvals = ['wbfcac', 'water_budget_fc_ac',  0., 30.,                         \
          'Water|Budget|accumulated|horizontal|convergence|of|cloud|(+,|conv.;|-,|' +\
          'div.)', 'mm', 'Reds']
    elif varn == 'wbfpac' or varn == 'WBACFP':
        varvals = ['wbfpac', 'water_budget_cfp_ac',  0., 30.,                        \
          'Water|Budget|accumulated|horizontal|convergence|of|precipitation|(+,|' +  \
          'conv.;|-,|div.)', 'mm', 'Reds']
    elif varn == 'wbzac' or varn == 'WBACZ':
        varvals = ['wbzac', 'water_budget_z_ac',  0., 30.,                           \
          'Water|Budget|accumulated|vertical|convergence|of|water|vapour|(+,|conv.' +\
          ';|-,|div.)', 'mm', 'Reds']
    elif varn == 'wbcac' or varn == 'WBACC':
        varvals = ['wbcac', 'water_budget_c_ac',  0., 30.,                           \
          'Water|Budget|accumulated|Cloud|water|species','mm', 'Reds']
    elif varn == 'wbqvdac' or varn == 'WBACQVD':
        varvals = ['wbqvdac', 'water_budget_qvd_ac',  0., 30.,                       \
          'Water|Budget|accumulated|water|vapour|divergence', 'mm', 'Reds']
    elif varn == 'wbqvbltenac' or varn == 'WBACQVBLTEN':
        varvals = ['wbqvbltenac', 'water_budget_qv_blten_ac',  0., 30.,              \
          'Water|Budget|accumulated|QV|tendency|due|to|pbl|parameterization',        \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbqvcutenac' or varn == 'WBACQVCUTEN':
        varvals = ['wbqvcutenac', 'water_budget_qv_cuten_ac',  0., 30.,              \
          'Water|Budget|accumulated|QV|tendency|due|to|cu|parameterization',         \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbqvshtenac' or varn == 'WBACQVSHTEN':
        varvals = ['wbqvshtenac', 'water_budget_qv_shten_ac',  0., 30.,              \
          'Water|Budget|accumulated|QV|tendency|due|to|shallow|cu|parameterization', \
          'kg kg-1 s-1', 'Reds']
    elif varn == 'wbprac' or varn == 'WBACP':
        varvals = ['wbprac', 'water_budget_pr_ac',  0., 30.,                         \
          'Water|Budget|accumulated|precipitation', 'mm', 'Reds']
    elif varn == 'wbpwac' or varn == 'WBACPW':
        varvals = ['wbpwac', 'water_budget_pw_ac',  0., 30.,                         \
          'Water|Budget|accumulated|water|content', 'mm', 'Reds']
    elif varn == 'wbcondtac' or varn == 'WBACCONDT':
        varvals = ['wbcondtac', 'water_budget_condt_ac',  0., 30.,                   \
          'Water|Budget|accumulated|condensation|and|deposition', 'mm', 'Reds']
    elif varn == 'wbqcmac' or varn == 'WBACQCM':
        varvals = ['wbqcmac', 'water_budget_qcm_ac',  0., 30.,                       \
          'Water|Budget|accumulated|hydrometeor|change|and|convergence', 'mm', 'Reds']
    elif varn == 'wbsiac' or varn == 'WBACSI':
        varvals = ['wbsiac', 'water_budget_si_ac',  0., 30.,                         \
          'Water|Budget|accumulated|hydrometeor|sink', 'mm', 'Reds']
    elif varn == 'wbsoac' or varn == 'WBACSO':
        varvals = ['wbsoac', 'water_budget_so_ac',  0., 30.,                         \
          'Water|Budget|accumulated|hydrometeor|source', 'mm', 'Reds']

    elif varn == 'xtime' or varn == 'XTIME':
        varvals = ['xtime', 'time',  0., 1.e5, 'time',                               \
          'minutes|since|simulation|start', 'Reds']
    elif varn == 'x' or varn == 'X':
        varvals = ['x', 'x',  0., 100., 'x', '-', 'Reds']
    elif varn == 'y' or varn == 'Y':
        varvals = ['y', 'y',  0., 100., 'y', '-', 'Blues']
    elif varn == 'z' or varn == 'Z':
        varvals = ['z', 'z',  0., 100., 'z', '-', 'Greens']
    elif varn == 'zg' or varn == 'WRFght' or varn == 'Geopotential height' or        \
      varn == 'geop' or varn == 'LGEOP':
        varvals = ['zg', 'geopotential_height', 0., 80000., 'geopotential|height',   \
          'm2s-2', 'rainbow']
    elif varn == 'zmaxth' or varn == 'zmax_th'  or varn == 'LZMAX_TH':
        varvals = ['zmaxth', 'thermal_plume_height', 0., 4000.,                     \
          'maximum|thermals|plume|height', 'm', 'YlOrRd']
    elif varn == 'zmla' or varn == 's_pblh' or varn == 'LS_PBLH':
        varvals = ['zmla', 'atmosphere_boundary_layer_thickness', 0., 2500.,         \
          'atmosphere|boundary|layer|thickness', 'm', 'Blues']
    else:
        print errormsg
        print '  ' + fname + ": variable '" + varn + "' not defined !!!"
        quit(-1)

    return varvals

def numVector_String(vec,char):
    """ Function to transform a vector of numbers to a single string [char] separated
    numVector_String(vec,char)
      vec= vector with the numerical values
      char= single character to split the values
    >>> print numVector_String(np.arange(10),' ')
    0 1 2 3 4 5 6 7 8 9
    """
    fname = 'numVector_String'

#    if vec == 'h':
#        print fname + '_____________________________________________________________'
#        print numVector_String.__doc__
#        quit()

    Nvals = len(vec)

    string=''
    for i in range(Nvals):
        if i == 0:
            string = str(vec[i])
        else:
            string = string + char + str(vec[i])

    return string

def index_vec(vec,val):
    """ Function to provide the coordinates of a given value inside a vector
    index_vec(vec,val)
      vec= vector with values
      val= value to search
    >>> index_vec(np.arange(27),22)
    22
    """

    fname = 'index_vec'

    vecv = np.array(vec)

    valpos = -1
    for i in range(vecv.shape[0]):
        if vecv[i] == val:
            valpos = i
            break

    return valpos

def index_mat(mat,val,quitval=True):
    """ Function to provide the coordinates of a given value inside a matrix
    index_mat(mat,val)
      mat= matrix with values
      val= value to search
      quitval= Whether one should arise quit signal in case no grid-point is found
    >>> index_mat(np.arange(27).reshape(3,3,3),22)
    [2 1 1]
    """
    fname = 'index_mat'

    matshape = mat.shape

    matlist = list(mat.flatten())

    # From: https://www.google.com.ar/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwj30JLKjMfQAhUEthoKHVAkAwoQFggtMAI&url=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F7571635%2Ffastest-way-to-check-if-a-value-exist-in-a-list&usg=AFQjCNFboI4YVafR26qSpyj5zx5GrQ3LGQ&bvm=bv.139782543,d.d2s
    if not val in matlist:
        print errormsg
        print '  ' + fname + ': matrix does not content ', val,' !!'
        if quitval:
            quit(-1)
        else:
            return -1
    ifound = matlist.index(val)

    Ndims = len(matshape)
    valpos = np.zeros((Ndims), dtype=int)
    baseprevdims = np.zeros((Ndims), dtype=int)

    for dimid in range(Ndims):
        baseprevdims[dimid] = np.product(matshape[dimid+1:Ndims])
        if dimid == 0:
            alreadyplaced = 0
        else:
            alreadyplaced = np.sum(baseprevdims[0:dimid]*valpos[0:dimid])
        valpos[dimid] = int((ifound - alreadyplaced )/ baseprevdims[dimid])

    return valpos

def multi_index_mat(mat,val):
    """ Function to provide the multiple coordinates of a given value inside a matrix
    index_mat(mat,val)
      mat= matrix with values
      val= value to search
    >>> vals = np.ones((24), dtype=np.float).reshape(2,3,4)
    vals[:,:,2] = 0.
    vals[1,:,:] = np.pi
    vals[:,2,:] = -1.
    multi_index_mat(vals,1.)
    [array([0, 0, 0]), array([0, 0, 1]), array([0, 0, 3]), array([0, 1, 0]), array([0, 1, 1]), array([0, 1, 3])]
    """
    fname = 'multi_index_mat'

    matshape = mat.shape

    ivalpos = []
    matlist = list(mat.flatten())
    Lmatlist = len(matlist)
    
    val0 = val - val
    if val != val0:
        valdiff = val0
    else:
        valdiff = np.ones((1), dtype = type(val))
    
    ifound = 0
    while ifound < Lmatlist:
        if matlist.count(val) == 0:
            ifound = Lmatlist + 1
        else:
            ifound = matlist.index(val)

            Ndims = len(matshape)
            valpos = np.zeros((Ndims), dtype=int)
            baseprevdims = np.zeros((Ndims), dtype=int)

            for dimid in range(Ndims):
                baseprevdims[dimid] = np.product(matshape[dimid+1:Ndims])
                if dimid == 0:
                    alreadyplaced = 0
                else:
                    alreadyplaced = np.sum(baseprevdims[0:dimid]*valpos[0:dimid])
                valpos[dimid] = int((ifound - alreadyplaced )/ baseprevdims[dimid])
            matlist[ifound] = valdiff
            ivalpos.append(valpos)

    return ivalpos

def multi_index_string(String, char):
    """ Function to provide the indeces of every repetition of a group of characters within a string
      String= string to look in
      char= chain of character to look for
    >>> multi_index_string('12345654321','2')
    [1, 9]
    >>> multi_index_string('12345654321','7')
    []
    >>> multi_index_string('1234565432123456','23')
    [1, 11]
    """
    fname = 'multi_index_string'

    Lstring = len(String)
    Lchar = len(char)

    newstring = String + ''
    indices = []

    iss = 0
    while iss < Lstring:
        if newstring.find(char) != -1:
            ichar = newstring.find(char)
            indices.append(ichar+iss)
            print newstring, ':', ichar
            newstring = newstring[ichar+iss+Lchar:-1]
            iss = iss + ichar + Lchar
        else:
            iss = Lstring

    return indices

def addfileInfile(origfile,destfile,addfile,addsign):
    """ Function to add the content of a file [addfile] to another one [origfile] at 
      a given position [addsign] creating a new file called [destfile]
      origfile= original file
      destfile= destination file
      addfile= content of the file to add
      addsign= sign where to add the file
    """
    fname = 'addfileInfile'

    if not os.path.isfile(origfile):
        print errormsg
        print '  ' + fname + ": original file '" + origfile + "' does not exist !!"
        quit(-1)

    if not os.path.isfile(addfile):
        print errormsg
        print '  ' + fname + ": adding file '" + addfile + "' does not exist !!"
        quit(-1)
    
    ofile = open(origfile, 'r')

# Inspecting flag
##
    Nfound = 0
    for line in ofile:
        if line == addsign + '\n': Nfound = Nfound + 1

    if Nfound == 0:
        print errormsg
        print '  ' + fname + ": adding sign '" + addsign + "' not found !!"
        quit(-1)
    print '  '+ fname + ': found', Nfound," times sign '" + addsign + "' "

    ofile.seek(0)
    dfile = open(destfile, 'w')

    for line in ofile:
        if line != addsign + '\n':
            dfile.write(line)
        else:
            afile = open(addfile,'r')
            for aline in afile:
                print aline
                dfile.write(aline)

            afile.close()

    ofile.close()
    dfile.close()

    print main + " successful writting of file '" + destfile + "' !!"
    return


####### ###### ##### #### ### ## #

def valmodoper(varVal, valuesS):
    """ Function to run the modification of a variable
      varVAl= matrix with the values
      valuesS= [modins],[[modval1],...,[modvalN]] modification instruction, value with which modify
        [modins]: Modifiers:
          sumc: add [modval1]
          subc: remove [modval1]
          mulc: multiply by [modval1]
          divc: divide by [modval1]
          lowthres: if [val] < [modval1]; val = [modval2]
          upthres: if [val] > [modval1]; val = [modval2]
          lowthres@oper: if [val] < [modval1]; val = [oper] (operation as [modval2],[modval3])
          upthres@oper: if [val] > [modval1]; val = [oper] (operation as [modval2],[modval3])
          potc: [val] ** [modval1]
    """
    fname='valmodoper'

    if valuesS == 'h':
        print fname + '_____________________________________________________________'
        print valmodoper.__doc__
        quit()

    valsS = valuesS.split(',')
    modins = valsS[0]
    modval = float(valsS[1])

    opers = ['sumc', 'subc', 'mulc', 'divc', 'lowthres', 'upthres', 'lowthres@oper', \
      'upthres@oper', 'potc']

    if modins == 'sumc':
        varVal[:] = varVal[:] + modval
    elif modins == 'subc':
        varVal[:] = varVal[:] - modval
    elif modins == 'mulc':
        varVal[:] = varVal[:] * modval
    elif modins == 'divc':
        varVal[:] = varVal[:] / modval
    elif modins == 'lowthres':
        varVal2 = np.where(varVal[:] < float(valsS[1]), float(valsS[2]), varVal[:])
        varVal[:] = varVal2
    elif modins == 'upthres':
        varVal2 = np.where(varVal[:] > float(valsS[1]), float(valsS[2]), varVal[:])
        varVal[:] = varVal2
    elif modins == 'lowthres@oper':
        if valsS[2] == 'sumc': 
           varVal2 = np.where(varVal[:] < float(valsS[1]),                           \
             varVal[:] + float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'subc': 
           varVal2 = np.where(varVal[:] < float(valsS[1]),                           \
             varVal[:] - float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'mulc': 
           varVal2 = np.where(varVal[:] < float(valsS[1]),                           \
             varVal[:] * float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'divc': 
           varVal2 = np.where(varVal[:] < float(valsS[1]),                           \
             varVal[:] / float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'potc': 
           varVal2 = np.where(varVal[:] < float(valsS[1]),                           \
             varVal[:] ** float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        else:
            print errormsg
            print '  ' + fname + ": Operation to modify values '" + modins +         \
              "' is not defined !!"
            quit(-1)
    elif modins == 'upthres@oper':
        if valsS[2] == 'sumc': 
           varVal2 = np.where(varVal[:] > float(valsS[1]),                           \
             varVal[:] + float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'subc': 
           varVal2 = np.where(varVal[:] > float(valsS[1]),                           \
             varVal[:] - float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'mulc': 
           varVal2 = np.where(varVal[:] > float(valsS[1]),                           \
             varVal[:] * float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'divc': 
           varVal2 = np.where(varVal[:] > float(valsS[1]),                           \
             varVal[:] / float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        elif valsS[2] == 'potc': 
           varVal2 = np.where(varVal[:] > float(valsS[1]),                           \
             varVal[:] ** float(valsS[3]), varVal[:])
           varVal[:] = varVal2
        else:
            print errormsg
            print '  ' + fname + ": Operation to modify values '" + modins +         \
              "' is not defined !!"
            quit(-1)
    elif modins == 'potc':
        varVal[:] = varVal[:] ** modval
    else: 
        print errormsg
        print '  ' + fname + ": Operation to modify values '" + modins +             \
          "' is not defined !!"
        print '    available:', opers
        quit(-1)

    return varVal

def rangedim(end, shape):
    """Gives the instruction to retrieve values from a dimension of a variable
    >>> print rangedim(-1, 15)
    15
    """
    if end == -1:
      return shape
    else:
      return end

def dateStr_date(StringDate):
  """ Function to transform a string date ([YYYY]-[MM]-[DD] format) to a date object
  >>> dateStr_date('1976-02-17')
  1976-02-17
  """
  import datetime as dt

  dateD = StringDate.split('-')
  if int(dateD[0]) == 0:
    print warnmsg
    print '    dateStr_date: 0 reference year!! changing to 1'
    dateD[0] = 1
  newdate = dt.date(int(dateD[0]), int(dateD[1]), int(dateD[2]))
  return newdate

def timeStr_time(StringDate):
  """ Function to transform a string date ([HH]:[MI]:[SS] format) to a time object
  >>> timeStr_datetime('04:32:54')
  04:32:54
  """
  import datetime as dt

  timeT = StringDate.split(':')
  if len(timeT) == 3:
    newtime = dt.time(int(timeT[0]), int(timeT[1]), int(timeT[2]))
  else:
    newtime = dt.time(int(timeT[0]), int(timeT[1]), 0)

  return newtime

def DateTimeStr_date(StringDate):
    """ Function to transform a string date-time ([YYYY][MM][DD][HH][MI][SS] format) to a date object
    >>> DateTimeStr_date('19760217083205')
    1976-02-17 08:32:05
    """
    import datetime as dt

    yr = int(StringDate[0:4])
    mo = int(StringDate[4:6])
    da = int(StringDate[6:8])
    ho = int(StringDate[8:10])
    mi = int(StringDate[10:12])
    se = int(StringDate[12:14])

    if yr == 0:
      print warnmsg
      print '     ' + fname + ': 0 reference year!! changing to 1'
      yr = 1
    newdate = dt.datetime(yr, mo, da, ho, mi, se)

    return newdate

def timeref_datetime(refd, timeval, tu):
    """ Function to transform from a [timeval] in [tu] units from the time referece [tref] to datetime object
    refd: time of reference (as datetime object)
    timeval: time value (as [tu] from [tref])
    tu: time units
    >>> timeref = date(1949,12,1,0,0,0)
    >>> timeref_datetime(timeref, 229784.36, hours)
    1976-02-17 08:21:36
    """
    import datetime as dt
    import numpy as np

## Not in timedelta
#    if tu == 'years':
#        realdate = refdate + dt.timedelta(years=float(timeval))
#    elif tu == 'months':
#        realdate = refdate + dt.timedelta(months=float(timeval))
    if tu == 'weeks':
        realdate = refd + dt.timedelta(weeks=float(timeval))
    elif tu == 'days':
        realdate = refd + dt.timedelta(days=float(timeval))
    elif tu == 'hours':
        realdate = refd + dt.timedelta(hours=float(timeval))
    elif tu == 'minutes':
        realdate = refd + dt.timedelta(minutes=float(timeval))
    elif tu == 'seconds':
        realdate = refd + dt.timedelta(seconds=float(timeval))
    elif tu == 'milliseconds':
        realdate = refd + dt.timedelta(milliseconds=float(timeval))
    else:
          print errormsg
          print '    timeref_datetime: time units "' + tu + '" not ready!!!!'
          quit(-1)

    return realdate

def timeref_datetime_mat(refd, timeval, tu):
    """ Function to transform from a [timeval] in [tu] units from the time referece [tref] to matrix with: year, day, month, hour, minute, second
    refd: time of reference (as datetime object)
    timeval: time value (as [tu] from [tref])
    tu: time units
    >>> timeref = date(1949,12,1,0,0,0)
    >>> timeref_datetime(timeref, 229784.36, hours)
    [1976    2   17    8   36   21]
    """
    import datetime as dt
    import numpy as np


    realdates = np.zeros(6, dtype=int)
## Not in timedelta
#    if tu == 'years':
#        realdate = refdate + dt.timedelta(years=float(timeval))
#    elif tu == 'months':
#        realdate = refdate + dt.timedelta(months=float(timeval))
    if tu == 'weeks':
        realdate = refd + dt.timedelta(weeks=float(timeval))
    elif tu == 'days':
        realdate = refd + dt.timedelta(days=float(timeval))
    elif tu == 'hours':
        realdate = refd + dt.timedelta(hours=float(timeval))
    elif tu == 'minutes':
        realdate = refd + dt.timedelta(minutes=float(timeval))
    elif tunits == 'seconds':
        realdate = refd + dt.timedelta(seconds=float(timeval))
    elif tunits == 'milliseconds':
        realdate = refd + dt.timedelta(milliseconds=float(timeval))
    else:
          print errormsg
          print '    timeref_datetime: time units "' + tu + '" not ready!!!!'
          quit(-1)

    realdates[0] = int(realdate.year)
    realdates[1] = int(realdate.month)
    realdates[2] = int(realdate.day)
    realdates[3] = int(realdate.hour)
    realdates[4] = int(realdate.second)
    realdates[5] = int(realdate.minute)

    return realdates

def realdatetime_CFcompilant(times, Srefdate, tunits):
    """ Function to transform a matrix with real time values ([year, month, day, hour, minute, second]) to a netCDF one
    times= matrix with times
    Srefdate= reference date ([YYYY][MM][DD][HH][MI][SS] format)
    tunits= units of time respect to Srefdate
    >>> realdatetime_CFcompilant(np.array([ [1976, 2, 17, 8, 20, 0], [1976, 2, 18, 8, 20, 0]], dtype=int), '19491201000000', 'hours')
    [ 229784.33333333  229808.33333333]
    """ 

    import datetime as dt
    yrref=int(Srefdate[0:4])
    monref=int(Srefdate[4:6])
    dayref=int(Srefdate[6:8])
    horref=int(Srefdate[8:10])
    minref=int(Srefdate[10:12])
    secref=int(Srefdate[12:14])
 
    refdate=dt.datetime(yrref, monref, dayref, horref, minref, secref)

    dimt=times.shape[0]
        
    cfdates = np.zeros((dimt), dtype=np.float64)
    if tunits == 'weeks':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = (cfdate.days + cfdate.seconds/(3600.*24.))/7.
    elif tunits == 'days':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days + cfdate.seconds/(3600.*24.)
    elif tunits == 'hours':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24. + cfdate.seconds/3600.
    elif tunits == 'minutes':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24.*60. + cfdate.seconds/60.
    elif tunits == 'seconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24.*3600. + cfdate.seconds
    elif tunits == 'milliseconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*1000.*24.*3600. + cfdate.seconds*1000.
    elif tunits == 'microseconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*1000000.*24.*3600. + cfdate.seconds*1000000.
    else:
        print errormsg
        print '  ' + fname + ': time units "' + tunits + '" is not ready!!!'
        quit(-1)

    return cfdates

def netCDFdatetime_realdatetime(units, tcalendar, times):
    """ Function to transfrom from netCDF CF-compilant times to real time
    """
    import datetime as dt

    txtunits = units.split(' ')
    tunits = txtunits[0]
    Srefdate = txtunits[len(txtunits) - 1]

# Calendar type
##
    is360 = False
    if tcalendar is not None:
      print '  netCDFdatetime_realdatetime: There is a calendar attribute'
      if tcalendar == '365_day' or tcalendar == 'noleap':
          print '    netCDFdatetime_realdatetime: No leap years!'
          isleapcal = False
      elif tcalendar == 'proleptic_gregorian' or tcalendar == 'standard' or tcalendar == 'gregorian':
          isleapcal = True
      elif tcalendar == '360_day':
          is360 = True
          isleapcal = False
      else:
          print errormsg
          print '    netCDFdatetime_realdatetime: Calendar "' + tcalendar + '" not prepared!'
          quit(-1)

# Does reference date contain a time value [YYYY]-[MM]-[DD] [HH]:[MI]:[SS]
##
    timeval = Srefdate.find(':')

    if not timeval == -1:
        print '  netCDFdatetime_realdatetime: refdate with time!'
        refdate = datetimeStr_datetime(txtunits[len(txtunits) - 2] + '_' + Srefdate)
    else:
        refdate = dateStr_date(Srefdate)

    dimt = len(times)
#    datetype = type(dt.datetime(1972,02,01))
#    realdates = np.array(dimt, datetype)
#    print realdates

## Not in timedelta
#  if tunits == 'years':
#    for it in range(dimt):
#      realdate = refdate + dt.timedelta(years=float(times[it]))
#      realdates[it] = int(realdate.year)
#  elif tunits == 'months':
#    for it in range(dimt):
#      realdate = refdate + dt.timedelta(months=float(times[it]))
#      realdates[it] = int(realdate.year)
#    realdates = []
    realdates = np.zeros((dimt, 6), dtype=int)
    if tunits == 'weeks':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(weeks=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'days':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(days=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'hours':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(hours=float(times[it]))
#            if not isleapcal:
#                Nleapdays = cal.leapdays(int(refdate.year), int(realdate.year))
#                realdate = realdate - dt.timedelta(days=Nleapdays)
#            if is360:
#                Nyears360 = int(realdate.year) - int(refdate.year) + 1
#                realdate = realdate -dt.timedelta(days=Nyears360*5)
#            realdates[it] = realdate
#        realdates = refdate + dt.timedelta(hours=float(times))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'minutes':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(minutes=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'seconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(seconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'milliseconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(milliseconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'microseconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(microseconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    else:
        print errormsg
        print '  netCDFdatetime_realdatetime: time units "' + tunits + '" is not ready!!!'
        quit(-1)

    return realdates

def date_juliandate(refyr, TOTsecs):
    """ Function to transform from a total quantity of seconds since the 
      beginning of a year to 360 days / year calendar
      TOTsecs= total number of seconds
    """
    fname = 'date_juliandate'

    secsYear = 3600*24*30*12.
    secsMonth = 3600*24*30.
    secsDay = 3600*24.
    secsHour = 3600.
    secsMinute = 60.

    rldate = np.zeros((6), dtype=int)
    rldate[0] = refyr 
    if TOTsecs > secsYear:
        rldate[0] = refyr + int(TOTsecs/secsYear) + 1
        TOTsecs = TOTsecs - int(TOTsecs/secsYear)*secsYear

    if np.mod(TOTsecs,secsMonth) == 0:
        rldate[1] = int(TOTsecs/secsMonth)
    else:
        rldate[1] = int(TOTsecs/secsMonth) + 1
    TOTsecs = TOTsecs - int(TOTsecs/secsMonth)*secsMonth

    if np.mod(TOTsecs,secsDay) == 0:
        rldate[2] = int(TOTsecs/secsDay)
    else:
        rldate[2] = int(TOTsecs/secsDay) + 1
    TOTsecs = TOTsecs - int(TOTsecs/secsDay)*secsDay

    if np.mod(TOTsecs,secsHour) == 0:
        rldate[3] = int(TOTsecs/secsHour)
    else:
        rldate[3] = int(TOTsecs/secsHour) + 1
    TOTsecs = TOTsecs - int(TOTsecs/secsHour)*secsHour

    if np.mod(TOTsecs,secsMinute) == 0:
        rldate[4] = int(TOTsecs/secsMinute)
    else:
        rldate[4] = int(TOTsecs/secsMinute) + 1
    TOTsecs = TOTsecs - int(TOTsecs/secsMinute)*secsMinute

    rldate[5] = TOTsecs

#    print refyr,TOTsecs,':',rldate
#    quit()

    return rldate

def CFtimes_datetime(ncfile, tname):
    """ Provide date/time array from a file with a series of netCDF CF-compilant time variable
    ncfile = netCDF file name
    tname = name of the variable time in [ncfile]
    output:
      array(dimt, 0) = year
      array(dimt, 1) = month
      array(dimt, 2) = day
      array(dimt, 3) = hour
      array(dimt, 4) = minute
      array(dimt, 5) = second
    """
    import datetime as dt
    fname = 'CFtimes_datetime'

    times = ncfile.variables[tname]
    timevals = times[:]

    attvar = times.ncattrs()
    if not searchInlist(attvar, 'units'):
        print errormsg
        print '  ' + fname + ": '" + tname + "' does not have attribute: 'units'"
        quit(-1)
    else:
        units = times.getncattr('units')
  
    txtunits = units.split(' ')
    tunits = txtunits[0]
    Srefdate = txtunits[len(txtunits) - 1]
# Does reference date contain a time value [YYYY]-[MM]-[DD] [HH]:[MI]:[SS]
##
    timeval = Srefdate.find(':')

    if not timeval == -1:
#        print '  refdate with time!'
        refdate = datetimeStr_datetime(txtunits[len(txtunits) - 2] + '_' + Srefdate)
    else:
        refdate = dateStr_date(Srefdate)

    dimt = len(timevals)
    realdates = np.zeros((dimt, 6), dtype=int)

    secsDay=3600*24.

# Checking calendar! 
## 
    y360 = False
    daycal360 = ['earth_360d', '360d', '360days', '360_day']
    if searchInlist(attvar, 'calendar'):
        calendar = times.getncattr('calendar')
        if searchInlist(daycal360,calendar):
            print warnmsg
            print '  ' + fname + ': calendar of 12 months of 30 days !!'
            y360 = True

## Not in timedelta
#    if tunits == 'years':
#        for it in range(dimt):
#            realdate = refdate + dt.timedelta(years=float(times[it]))
#            realdates[it] = int(realdate.year)
#    elif tunits == 'months':
#        for it in range(dimt):
#            realdate = refdate + dt.timedelta(months=float(times[it]))
#            realdates[it] = int(realdate.year)
    if y360:
        if tunits == 'weeks':
            for it in range(dimt):
                deltat = dt.timedelta(weeks=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        elif tunits == 'days':
            for it in range(dimt):
                deltat = dt.timedelta(days=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        elif tunits == 'hours':
           for it in range(dimt):
                realdate = dt.timedelta(hours=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        elif tunits == 'minutes':
           for it in range(dimt):
                realdate = dt.timedelta(minutes=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        elif tunits == 'seconds':
           for it in range(dimt):
                realdate = dt.timedelta(seconds=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        elif tunits == 'miliseconds':
           for it in range(dimt):
                realdate = dt.timedelta(miliseconds=float(times[it]))
                Tsecs = deltat.days*secsDay + deltat.seconds + deltat.microseconds/1000.
                realdates[it,:] = date_juliandate(refdate.year,Tsecs)
        else:
              print errormsg
              print '    CFtimes_datetime: time units "' + tunits + '" not ready!!!!'
              quit(-1)
    else:
        if tunits == 'weeks':
            for it in range(dimt):
                realdate = refdate + dt.timedelta(weeks=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        elif tunits == 'days':
            for it in range(dimt):
                realdate = refdate + dt.timedelta(days=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        elif tunits == 'hours':
           for it in range(dimt):
                realdate = refdate + dt.timedelta(hours=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        elif tunits == 'minutes':
           for it in range(dimt):
                realdate = refdate + dt.timedelta(minutes=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        elif tunits == 'seconds':
           for it in range(dimt):
                realdate = refdate + dt.timedelta(seconds=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        elif tunits == 'milliseconds':
           for it in range(dimt):
                realdate = refdate + dt.timedelta(milliseconds=float(times[it]))
                realdates[it,0] = int(realdate.year)
                realdates[it,1] = int(realdate.month)
                realdates[it,2] = int(realdate.day)
                realdates[it,3] = int(realdate.hour)
                realdates[it,4] = int(realdate.second)
                realdates[it,5] = int(realdate.minute)
        else:
              print errormsg
              print '    CFtimes_datetime: time units "' + tunits + '" not ready!!!!'
              quit(-1)
    
    return realdates

class statsValWeigthed(object):
  """Weigthed Statistics class providing:
  vals = values (can be a matrix)
  wgs = weights (can be a matrix)
  self.meanv: mean weigthed value
  self.mean2v: mean quadratic weigthed value
  self.stdv: weigthed standard deviation
  self.Nokvalue non None values of a list of values 
  self.meanwgt: mean of the weigths
  self.mean2wgt: cuadratic mean of the weigths
  self.stdwgt: standard deviation of the weigths
  """

  def __init__(self, vals, wgs):
    if vals is None:
      self.Nv = None
      self.meanv = None
      self.mean2v = None
      self.stdv = None
      self.Nokvalues = None
      self.meanwgt = None
      self.mean2wgt = None
      self.stdwgt = None
    else:
      values = vals.flatten() 
      weights = wgs.flatten()
      self.Nv=len(values)
      self.meanv=0.
      self.mean2v=0.
      self.stdv=0.
      self.meanwgt = 0.
      self.mean2wgt = 0.
      self.stdwgt = 0.
      self.Nokvalues = 0

      for inum in range(self.Nv):
        if not values[inum] is None:
          self.Nokvalues = self.Nokvalues + 1
          self.meanv = self.meanv+values[inum]*weights[inum]
          self.mean2v = self.mean2v+values[inum]*weights[inum]*values[inum]
          self.meanwgt = self.meanwgt+weights[inum]
          self.mean2wgt = self.mean2wgt+weights[inum]*weights[inum]

      self.meanv = self.meanv/float(self.meanwgt)
      self.mean2v = self.mean2v/float(self.meanwgt)
      self.stdv = np.sqrt(self.mean2v-self.meanv*self.meanv)
      self.meanwgt = self.meanwgt/float(self.Nokvalues)
      self.mean2wgt = self.mean2wgt/float(self.Nokvalues)
      self.stdwgt = np.sqrt(self.mean2wgt-self.meanwgt*self.meanwgt)

    return

class statsValWeighted_missVal(object):
  """Weighted Statistics taking into account a missing value class providing:
  vals = values (can be a matrix)
  wgs = weights (can be a matrix)
  missVal= missing value
  self.meanv: mean weigthed value
  self.mean2v: mean quadratic weigthed value
  self.stdv: weigthed standard deviation
  self.Nokvalue non None values of a list of values 
  self.meanwgt: mean of the weigths
  self.mean2wgt: cuadratic mean of the weigths
  self.stdwgt: standard deviation of the weigths
  self.quantilesv: quantiles of the weighted values
  """

  def __init__(self, vals, wgs, missVal):

    fname='statsValWeigthed_missVal'
    if vals is None:
      self.Nv = None
      self.meanv = None
      self.mean2v = None
      self.stdv = None
      self.Nokvalues = None
      self.meanwgt = None
      self.mean2wgt = None
      self.stdwgt = None
      self.quantilesv = None
    else:    
      Npt = 1
      for idim in range(len(vals.shape)):
        Npt = Npt * vals.shape[idim]
      if np.sum(vals >= missVal) == Npt:
          print errormsg
          print '  ' + fname + ' all values get missing!!'
          print errormsg
          quit(-1)
      vals0 = np.where(vals >= missVal, None, vals)
      values = vals0.flatten() 
      weights = wgs.flatten()
      self.Nv=Npt
      self.meanv=0.
      self.mean2v=0.
      self.stdv=0.
      self.meanwgt = 0.
      self.mean2wgt = 0.
      self.stdwgt = 0.
      self.Nokvalues = 0

      valswgt = values
      for inum in range(self.Nv):
        if not values[inum] is None:
          self.Nokvalues = self.Nokvalues + 1
          valswgt[inum] = valswgt[inum]*weights[inum]
          self.meanv = self.meanv+values[inum]*weights[inum]
          self.mean2v = self.mean2v+values[inum]*weights[inum]*values[inum]
          self.meanwgt = self.meanwgt+weights[inum]
          self.mean2wgt = self.mean2wgt+weights[inum]*weights[inum]

      self.meanv = self.meanv/float(self.meanwgt)
      self.mean2v = self.mean2v/float(self.meanwgt)
      self.stdv = np.sqrt(self.mean2v-self.meanv*self.meanv)
      valswgt = valswgt/np.float(self.meanwgt)
      self.meanwgt = self.meanwgt/float(self.Nokvalues)
      self.mean2wgt = self.mean2wgt/float(self.Nokvalues)
      self.stdwgt = np.sqrt(self.mean2wgt-self.meanwgt*self.meanwgt)
      valsq=Quantiles(valswgt, 20)
      self.quantilesv=valsq.quantilesv

    return

class std_stats2Val(object):
  """two variables standard Statistics class providing:
  vals1 = variable 1
  vals2 = variable 2
  self.bias=mean(var1-var2) 
  self.mae=mean(abs(var1-var2)) 
  self.rmse=sqrt((var1-var2)**2)
  self.explvar = stddev1/stddev2
  self.correlation (and p-value) 
  """

  def __init__(self, vals1, vals2):
    import numpy as np
    from scipy import stats as sts

    fname = 'std_stats2Val'

    if vals1 is None:
      self.bias = None
      self.mae = None
      self.rmse = None
      self.explvar = None
      self.corr = None
    else:
      values1 = vals1.flatten() 
      values2 = vals2.flatten() 

      Nvals1 = len(values1)
      Nvals2 = len(values2)


      if not len(values1) == len(values2):
        print errormsg
        print '    ' + fname + ': lengths of variables differ!! Lvar1: ', Nvals1,    \
          ' Lvar2: ', Nvals2,' statistics between them can not be computed!'
        quit(-1)

      self.bias = 0.
      self.mae = 0.
      self.rmse = 0.
      self.explvar = 0.
      self.corr = np.zeros(2, dtype=np.float)

      for inum in range(Nvals1):
          Sval = values1[inum] - values2[inum]
          self.mae = self.mae + abs(Sval)
          self.rmse = self.rmse + Sval**2

      self.bias = np.mean(vals1) - np.mean(vals2)
      self.mae = self.mae/Nvals1
      self.rmse = np.sqrt(self.rmse/Nvals1)
      self.explvar = np.var(vals1)/np.var(vals2)

      self.corr[0], self.corr[1] = sts.pearsonr(values1, values2)

    return

class stats2Val(object):
  """two variables Statistics class providing:
  vals1 = variable 1
  vals2 = variable 2
  power = power of the polynomial fitting to apply between both variables
  self.min[var], self.max[var], self.mean[var], self.mean2[var], self.std[var] of 
    [var] = var1+var2[v1Av2], var1-var2[v1Sv2], var1/var2[v1Dv2], var1*var2[v1Pv2]
  self.Nokvalues1: number of correct values of variable 1
  self.Nokvalues2: number of correct values of variable 2
  self.Nokvalues12: number of correct coincident values of variable 1 and variable 2
  self.mae=mean(abs(var1-var2)) 
  self.rmse=sqrt((var1-var2)**2) 
  self.correlation (and p-value) 
  self.linRegress: linear regression [trend, intercept, regression coefficient, p_value, standard error]
  self.polRegress: polinomial Regresion  of degree [power] [coef**[power], coef**[power-1], ...., coef**0]
  """

  def __init__(self, vals1, vals2, power):
    import numpy as np
    from scipy import stats as sts

    if vals1 is None:
      self.Nv = None
      self.Nokvalues1 = None
      self.Nokvalues2 = None
      self.Nokvalues12 = None
      self.NDvalNone = None
      self.minv1Av2 = None
      self.maxv1Av2 = None
      self.meanv1Av2 = None
      self.mean2v1Av2 = None
      self.stdv1Av2 = None
      self.minv1Sv2 = None
      self.maxv1Sv2 = None
      self.meanv1Sv2 = None
      self.mean2v1Sv2 = None
      self.stdv1Sv2 = None
      self.minv1Dv2 = None
      self.maxv1Dv2 = None
      self.meanv1Dv2 = None
      self.mean2v1Dv2 = None
      self.stdv1Dv2 = None
      self.minv1Pv2 = None
      self.maxv1Pv2 = None
      self.meanv1Pv2 = None
      self.mean2v1Pv2 = None
      self.stdv1Pv2 = None
      self.bias = None
      self.mae = None
      self.rmse = None
      self.corr = None
      self.linRegress = None
      self.polRegress = None
      self.polRegressResidual = None
      self.polRegressRes = None
      self.polRegressSingVal = None
    else:
      values1 = vals1.flatten() 
      values2 = vals2.flatten() 

      if not len(values1) == len(values2):
        print errormsg
        print '    stats2Val: lengths of variables differ!! Lvar1: ', len(values1), ' Lvar2: ',len(values2),' statistics between them can not be computed!'
        quit(-1)

      self.Nv=len(values1)
      self.minv1Av2=10000000000.
      self.maxv1Av2=-self.minv1Av2
      self.meanv1Av2=0.
      self.mean2v1Av2=0.
      self.stdv1Av2=0.
      self.minv1Sv2=self.minv1Av2
      self.maxv1Sv2=-self.minv1Av2
      self.meanv1Sv2=0.
      self.mean2v1Sv2=0.
      self.stdv1Sv2=0.
      self.minv1Dv2=self.minv1Av2
      self.maxv1Dv2=-self.minv1Av2
      self.meanv1Dv2=0.
      self.mean2v1Dv2=0.
      self.stdv1Dv2=0.
      self.minv1Pv2=self.minv1Av2
      self.maxv1Pv2=-self.minv1Av2
      self.meanv1Pv2=0.
      self.mean2v1Pv2=0.
      self.stdv1Pv2=0.
      self.bias = 0.
      self.mae = 0.
      self.rmse = 0.
      self.corr = np.zeros(2, dtype=np.float)
      self.linRegress = np.zeros(5, float)
      self.polRegress = np.zeros(power+1, float)
      self.polRegressResidual = 0.
      self.polRegressSingVal = np.zeros(power+1, float)

# v1 [+ / - / / / *] v2
##
      self.Nokvalues1 = 0
      self.Nokvalues2 = 0
      self.Nokvalues12 = 0
      self.NDvalNone = 0
      for inum in range(self.Nv):
        if not values1[inum] is None:
          self.Nokvalues1 = self.Nokvalues1 + 1
        if not values2[inum] is None:
          self.Nokvalues2 = self.Nokvalues2 + 1
        if not values1[inum] is None and not values2[inum] is None:
          self.Nokvalues12 = self.Nokvalues12 + 1
          Aval = values1[inum] + values2[inum]
          Sval = values1[inum] - values2[inum]
          Pval = values1[inum] * values2[inum]
          if np.isinf(values1[inum] / values2[inum]) or np.isnan(values1[inum] / values2[inum]):
            if self.NDvalNone < 1:
               print warnmsg
               print '      stats2Val: val1/val2 inf or Nan!!!!'
            Dval = None
            self.NDvalNone = self.NDvalNone + 1
          else:
            Dval = values1[inum] / values2[inum]

          self.bias = self.bias + Sval
          self.mae = self.mae + abs(Sval)
          self.rmse = self.rmse + Sval**2

          if Aval < self.minv1Av2:
            self.minv1Av2 = Aval
          if Aval > self.maxv1Av2:
            self.maxv1Av2 = Aval
          if Sval < self.minv1Sv2:
            self.minv1Sv2 = Sval
          if Sval > self.maxv1Sv2:
            self.maxv1Sv2 = Sval
          if not Dval is None and Dval < self.minv1Dv2:
            self.minv1Dv2 = Dval
          if not Dval is None and  Dval > self.maxv1Dv2:
            self.maxv1Dv2 = Dval
          if Pval < self.minv1Pv2:
            self.minv1Pv2 = Pval
          if Pval > self.maxv1Pv2:
            self.maxv1Pv2 = Pval

          self.meanv1Av2 = self.meanv1Av2+Aval
          self.mean2v1Av2 = self.mean2v1Av2+Aval*Aval
          self.meanv1Sv2 = self.meanv1Sv2+Sval
          self.mean2v1Sv2 = self.mean2v1Sv2+Sval*Sval
          if not Dval is None:
            self.meanv1Dv2 = self.meanv1Dv2+Dval
            self.mean2v1Dv2 = self.mean2v1Dv2+Dval*Dval
          self.meanv1Pv2 = self.meanv1Pv2+Pval
          self.mean2v1Pv2 = self.mean2v1Pv2+Pval*Pval

##      print 'Nokvalues1: ', self.Nokvalues1, 'Nokvalues2: ', self.Nokvalues2, 'Nokvalues12: ', float(self.Nokvalues12), 'NDvalNone: ',self.NDvalNone
      self.meanv1Av2 = self.meanv1Av2/float(self.Nokvalues12)
      self.mean2v1Av2 = self.mean2v1Av2/float(self.Nokvalues12)
      self.stdv1Av2 = np.sqrt(self.mean2v1Av2-self.meanv1Av2*self.meanv1Av2)
      self.meanv1Sv2 = self.meanv1Sv2/float(self.Nokvalues12)
      self.mean2v1Sv2 = self.mean2v1Sv2/float(self.Nokvalues12)
      self.stdv1Sv2 = np.sqrt(self.mean2v1Sv2-self.meanv1Sv2*self.meanv1Sv2)
      if self.Nokvalues12 - self.NDvalNone == 0:
          self.meanv1Dv2 = None
          self.mean2v1Dv2 = None
          self.stdv1Dv2 = None
          print warnmsg
          print '      stats2Val: all values of val1/val2 are None!'
      else:
          self.meanv1Dv2 = self.meanv1Dv2/(float(self.Nokvalues12 - self.NDvalNone))
          self.mean2v1Dv2 = self.mean2v1Dv2/(float(self.Nokvalues12 - self.NDvalNone))
          self.stdv1Dv2 = np.sqrt(self.mean2v1Dv2-self.meanv1Dv2*self.meanv1Dv2)
      self.meanv1Pv2 = self.meanv1Pv2/float(self.Nokvalues12)
      self.mean2v1Pv2 = self.mean2v1Pv2/float(self.Nokvalues12)
      self.stdv1Pv2 = np.sqrt(self.mean2v1Pv2-self.meanv1Pv2*self.meanv1Pv2)

      self.bias = self.bias/self.Nokvalues12
      self.mae = self.mae/self.Nokvalues12
      self.rmse = np.sqrt(self.rmse/self.Nokvalues12)

      self.corr[0], self.corr[1] = sts.pearsonr(values1, values2)
      self.linRegress[0], self.linRegress[1], self.linRegress[2], self.linRegress[3], self.linRegress[4] = sts.linregress(values1, values2)

      polyfitvals=np.polyfit(values1, values2, power, full = True)

      self.polRegress = polyfitvals[0]
      self.polRegressRes = polyfitvals[1]
      self.polRegressSingVal = polyfitvals[3]

    return

class stats2Val_missVal(object):
  """two variables Statistics taking into account a missing value class providing:
  vals1 = variable 1
  vals2 = variable 2
  missVal = missing value
  power = power of the polynomial fitting to apply between both variables
  self.min[var], self.max[var], self.mean[var], self.mean2[var], self.std[var] of 
    [var] = var1+var2[v1Av2], var1-var2[v1Sv2], var1/var2[v1Dv2], var1*var2[v1Pv2]
  self.Nokvalues1: number of correct values of variable 1
  self.Nokvalues2: number of correct values of variable 2
  self.Nokvalues12: number of correct coincident values of variable 1 and variable 2
  self.mae=mean(abs(var1-var2)) 
  self.rmse=sqrt((var1-var2)**2) 
  self.correlation (and p-value) 
  self.linRegress: linear regression [trend, intercept, regression coefficient, p_value, standard error]
  self.polRegress: polinomial Regresion  of degree [power] [coef**[power], coef**[power-1], ...., coef**0]
  """

  def __init__(self, vals1, vals2, power, missVal):
    import numpy as np
    from scipy import stats as sts

    fname='stats2Val_missVal'
    if vals1 is None:
      self.Nv = None
      self.Nokvalues1 = None
      self.Nokvalues2 = None
      self.Nokvalues12 = None
      self.NDvalNone = None
      self.minv1Av2 = None
      self.maxv1Av2 = None
      self.meanv1Av2 = None
      self.mean2v1Av2 = None
      self.stdv1Av2 = None
      self.minv1Sv2 = None
      self.maxv1Sv2 = None
      self.meanv1Sv2 = None
      self.mean2v1Sv2 = None
      self.stdv1Sv2 = None
      self.minv1Dv2 = None
      self.maxv1Dv2 = None
      self.meanv1Dv2 = None
      self.mean2v1Dv2 = None
      self.stdv1Dv2 = None
      self.minv1Pv2 = None
      self.maxv1Pv2 = None
      self.meanv1Pv2 = None
      self.mean2v1Pv2 = None
      self.stdv1Pv2 = None
      self.mae = None
      self.rmse = None
      self.corr = None
      self.linRegress = None
      self.polRegress = None
      self.polRegressResidual = None
      self.polRegressRes = None
      self.polRegressSingVal = None
    else:
      Npt1 = 1
      for idim in range(len(vals1.shape)):
        Npt1 = Npt1 * vals1.shape[idim]
      if np.sum(vals1 >= missVal) == Npt1:
          print errormsg
          print '  ' + fname + ' all values 1 get missing!!'
          print errormsg
          quit(-1)
      Npt2 = 1
      for idim in range(len(vals2.shape)):
        Npt2 = Npt2 * vals2.shape[idim]
      if np.sum(vals2 >= missVal) == Npt2:
          print errormsg
          print '  ' + fname + ' all values 2 get missing!!'
          print errormsg
          quit(-1)
      vals10 = np.where(abs(vals1) >= missVal, None, vals1)
      vals20 = np.where(abs(vals2) >= missVal, None, vals2)
      values1 = vals10.flatten() 
      values2 = vals20.flatten() 

      if not len(values1) == len(values2):
        print errormsg
        print '    stats2Val: lengths of variables differ!! Lvar1: ', len(values1), ' Lvar2: ',len(values2),' statistics between them can not be computed!'
        quit(-1)

      self.Nv=Npt1
      self.minv1Av2=10000000000.
      self.maxv1Av2=-self.minv1Av2
      self.meanv1Av2=0.
      self.mean2v1Av2=0.
      self.stdv1Av2=0.
      self.minv1Sv2=self.minv1Av2
      self.maxv1Sv2=-self.minv1Av2
      self.meanv1Sv2=0.
      self.mean2v1Sv2=0.
      self.stdv1Sv2=0.
      self.minv1Dv2=self.minv1Av2
      self.maxv1Dv2=-self.minv1Av2
      self.meanv1Dv2=0.
      self.mean2v1Dv2=0.
      self.stdv1Dv2=0.
      self.minv1Pv2=self.minv1Av2
      self.maxv1Pv2=-self.minv1Av2
      self.meanv1Pv2=0.
      self.mean2v1Pv2=0.
      self.stdv1Pv2=0.
      self.mae = 0.
      self.rmse = 0.
      self.corr = np.array([0., 0.])
      self.linRegress = np.zeros(5, float)
      self.polRegress = np.zeros(power+1, float)
      self.polRegressResidual = 0.
      self.polRegressSingVal = np.zeros(power+1, float)

# v1 [+ / - / / / *] v2
##
      self.Nokvalues1 = 0
      self.Nokvalues2 = 0
      self.Nokvalues12 = 0
      self.NDvalNone = 0
      for inum in range(self.Nv):
        if not values1[inum] is None:
          self.Nokvalues1 = self.Nokvalues1 + 1
        if not values2[inum] is None:
          self.Nokvalues2 = self.Nokvalues2 + 1
        if not values1[inum] is None and not values2[inum] is None:
          self.Nokvalues12 = self.Nokvalues12 + 1
          Aval = values1[inum] + values2[inum]
          Sval = values1[inum] - values2[inum]
          Pval = values1[inum] * values2[inum]
          if np.isinf(values1[inum] / values2[inum]) or np.isnan(values1[inum] / values2[inum]):
            if self.NDvalNone < 1:
               print warnmsg
               print '      stats2Val: val1/val2 inf or Nan!!!!'
            Dval = None
            self.NDvalNone = self.NDvalNone + 1
          else:
            Dval = values1[inum] / values2[inum]

          self.mae = self.mae + abs(Sval)
          self.rmse = self.rmse + Sval**2

          if Aval < self.minv1Av2:
            self.minv1Av2 = Aval
          if Aval > self.maxv1Av2:
            self.maxv1Av2 = Aval
          if Sval < self.minv1Sv2:
            self.minv1Sv2 = Sval
          if Sval > self.maxv1Sv2:
            self.maxv1Sv2 = Sval
          if not Dval is None and Dval < self.minv1Dv2:
            self.minv1Dv2 = Dval
          if not Dval is None and  Dval > self.maxv1Dv2:
            self.maxv1Dv2 = Dval
          if Pval < self.minv1Pv2:
            self.minv1Pv2 = Pval
          if Pval > self.maxv1Pv2:
            self.maxv1Pv2 = Pval

          self.meanv1Av2 = self.meanv1Av2+Aval
          self.mean2v1Av2 = self.mean2v1Av2+Aval*Aval
          self.meanv1Sv2 = self.meanv1Sv2+Sval
          self.mean2v1Sv2 = self.mean2v1Sv2+Sval*Sval
          if not Dval is None:
            self.meanv1Dv2 = self.meanv1Dv2+Dval
            self.mean2v1Dv2 = self.mean2v1Dv2+Dval*Dval
          self.meanv1Pv2 = self.meanv1Pv2+Pval
          self.mean2v1Pv2 = self.mean2v1Pv2+Pval*Pval

##      print 'Nokvalues1: ', self.Nokvalues1, 'Nokvalues2: ', self.Nokvalues2, 'Nokvalues12: ', float(self.Nokvalues12), 'NDvalNone: ',self.NDvalNone
      self.meanv1Av2 = self.meanv1Av2/float(self.Nokvalues12)
      self.mean2v1Av2 = self.mean2v1Av2/float(self.Nokvalues12)
      self.stdv1Av2 = np.sqrt(self.mean2v1Av2-self.meanv1Av2*self.meanv1Av2)
      self.meanv1Sv2 = self.meanv1Sv2/float(self.Nokvalues12)
      self.mean2v1Sv2 = self.mean2v1Sv2/float(self.Nokvalues12)
      self.stdv1Sv2 = np.sqrt(self.mean2v1Sv2-self.meanv1Sv2*self.meanv1Sv2)
      if self.Nokvalues12 - self.NDvalNone == 0:
          self.meanv1Dv2 = None
          self.mean2v1Dv2 = None
          self.stdv1Dv2 = None
          print warnmsg
          print '      stats2Val: all values of val1/val2 are None!'
      else:
          self.meanv1Dv2 = self.meanv1Dv2/(float(self.Nokvalues12 - self.NDvalNone))
          self.mean2v1Dv2 = self.mean2v1Dv2/(float(self.Nokvalues12 - self.NDvalNone))
          self.stdv1Dv2 = np.sqrt(self.mean2v1Dv2-self.meanv1Dv2*self.meanv1Dv2)
      self.meanv1Pv2 = self.meanv1Pv2/float(self.Nokvalues12)
      self.mean2v1Pv2 = self.mean2v1Pv2/float(self.Nokvalues12)
      self.stdv1Pv2 = np.sqrt(self.mean2v1Pv2-self.meanv1Pv2*self.meanv1Pv2)

      self.mae = self.mae/self.Nokvalues12
      self.rmse = np.sqrt(self.rmse/self.Nokvalues12)

      vals1Nomiss = np.ones(len(values1), dtype=bool)
      vals2Nomiss = np.ones(len(values1), dtype=bool)

      for i in range(len(values1)):
          if values1[i] is None:
              vals1Nomiss[i] = False

      for i in range(len(values2)):
          if values2[i] is None:
              vals2Nomiss[i] = False

      v1 = np.array(values1[vals1Nomiss], dtype=float)
      v2 = np.array(values2[vals2Nomiss], dtype=float)

      if not v1.shape == v2.shape:
          print errormsg
          print '  ' + fname + ': variables without missing values v1: ',v1.shape , ' and v2: ',v2.shape ,' do not have the same shape! '
          print errormsg
          quit(-1)

      self.corr = sts.pearsonr(v1, v2)

      self.linRegress[0], self.linRegress[1], self.linRegress[2], self.linRegress[3], self.linRegress[4] = sts.linregress(v1, v2)

      polyfitvals=np.polyfit(v1, v2, power, full = True)

      self.polRegress = polyfitvals[0]
      self.polRegressRes = polyfitvals[1]
      self.polRegressSingVal = polyfitvals[3]

    return

def mask_2masked(vals1, vals2):
    """ Function to provide the boolean matrix (in opposite way as it is in the mask) as combination of mask from to masked matrices
    """
    import numpy.ma as ma
    fname = 'mask_2masked'

#    if len(vals1.shape) != len(vals2.shape):
#        print errormsg
#        print '  ' + fname + ' matrix 1 :', len(vals1.shape), ' and matrix 2 ', len(vals2.shape), ' have different size!'
#        print errormsg
#        quit(-1)

#    for idim in range(len(vals1.shape)):
#        if vals1.shape[idim] != vals2.shape[idim]:
#            print errormsg
#            print '  ' + fname + ' dimension ', idim,' from matrix 1 :', vals1.shape[idim], ' and matrix 2 ', \
#                vals2.shape[idim], ' have different size!'
#            print errormsg
#            quit(-1)

    if type(vals1) == type(ma.array(1)):
        mask1array=np.where(ma.getmaskarray(vals1) == False, True, False)
    else:
        mask1array=np.ones(vals1.shape, dtype=bool)

    if type(vals2) == type(ma.array(1)):
        mask2array=np.where(ma.getmaskarray(vals2) == False, True, False)
    else:
        mask2array=np.ones(vals2.shape, dtype=bool)

    mask12 = mask1array*mask2array

    return mask12

def mask_pearsonr(xvals, yvals):
    """ Function to compute a pearson correlation from mask matrices
    """
    from scipy import stats as sts
    fillVal = 1.e20
    maskxy = mask_2masked(xvals, yvals)

    if np.sum(maskxy) > 1:
        pearsonr = sts.pearsonr(xvals[maskxy], yvals[maskxy])
        if np.isnan(pearsonr[0]) or np.isnan(pearsonr[1]): 
           pearsonr = ( fillVal, fillVal)
    else:
        pearsonr = (fillVal, fillVal)

    return pearsonr

def mask_quantiles(maskmat, Nquants):
    """ Function to provide the quantiles of a masked array 20 for %5 bins (21 in total)
    """
    import numpy.ma as ma

    fillValue = 1.e20

    sortmat = maskmat.flatten().copy()
    sortmat.sort()
    quants = np.zeros(Nquants+1, dtype=type(maskmat[0]))
    Nv = ma.size(maskmat)
    NoMask=maskmat.count()

    if NoMask < Nquants:
        quants[:] = fillValue
    else:
        for iq in range(Nquants):
            quants[iq] = sortmat[int((NoMask-1)*iq/(Nquants))]

        quants[Nquants] = sortmat[NoMask-1]

    return quants

def percendone(nvals,tot,percen,msg):
    """ Function to provide the percentage of an action across the matrix
    nvals=number of values
    tot=total number of values
    percen=percentage frequency for which the message is wanted
    msg= message
    """
    from sys import stdout

    num = int(tot * percen/100)
    if (nvals%num == 0): 
        print '\r        ' + msg + '{0:8.3g}'.format(nvals*100./tot) + ' %',
        stdout.flush()

    return ''

def mask_linregres(vals1, vals2):
    """ Function to compute a linear regression from masked data
    vals1: x-values for the regresion
    vals2: y-values for the regresion
    """
    import numpy.ma as ma

    fname = 'mask_linregres'

    missval1 = vals1.get_fill_value()    
    missval2 = vals2.get_fill_value()    

    vals10 = np.where(abs(vals1) >= abs(missval1*0.9), None, vals1)
    vals20 = np.where(abs(vals2) >= abs(missval2*0.9), None, vals2)

    values1 = vals10.flatten() 
    values2 = vals20.flatten() 

    vals1Nomiss = np.ones(len(values1), dtype=bool)
    vals2Nomiss = np.ones(len(values2), dtype=bool)

    for i in range(len(values1)):
        if values1[i] is None:
            vals1Nomiss[i] = False
    for i in range(len(values2)):
        if values2[i] is None:
            vals2Nomiss[i] = False

    v1 = np.array(values1[vals1Nomiss], dtype=float)
    v2 = np.array(values2[vals2Nomiss], dtype=float)

    if len(v1) != len(v2):
        print errormsg
        print fname + ': length of masked matrices mat1:',len(v1),'and mat2:',len(v2),'does not match!'
        print errormsg
        quit(-1)

    linregres = np.array(sts.linregress(v1, v2), dtype= np.float64)

    return linregres

def mask_space_stats(maskmat,statsvals,dim):
    """ Function to give back the multi-dimensional statisitcs of a given masked array
    maskmat=multidimensional masked array
    statsvals=[statn]:[values] 
      [statn]: statistics to do: 
        'quant', quantiles
      [values]: value for the statistics: Nquantiles
    dim= dimension to run the statistics
    """
    from sys import stdout

    fname = 'mask_space_stats'

    statn=statsvals.split(':')[0]
    if len(statsvals.split(':')) > 1:
        values=statsvals.split(':')[1]

    maskshape = maskmat.shape
    Ndims = len(maskshape)
    if statn == 'quant':
        if len(statsvals.split(':')) == 1:
            print errormsg
            print fname + ': statistics "' + statn + '" requires a value!!!'
            print errormsg
            quit(-1)
        Nquants=int(values)
        if Ndims == 2:
            if dim == 0:
                statval = np.ones((21, maskshape[1]), dtype=np.float64)*fillValue
                for i in range(maskshape[1]):
                   percendone(i, maskshape[1], 5, 'quantiles')
                   statval[:,i] = mask_quantiles(maskmat[:,i],Nquants)
            if dim == 1:
                statval = np.ones((21, maskshape[0]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                   percendone(i, maskshape[0], 5, 'quantiles')
                   statval[:,i] = mask_quantiles(statval[i,:],Nquants)
        elif Ndims == 3:
            if dim == 0:
                statval = np.ones((21, maskshape[1], maskshape[2]), dtype=np.float64)*fillValue
                for i in range(maskshape[1]):
                    for j in range(maskshape[2]):
                        percendone(i*maskshape[2] + j, maskshape[1]*maskshape[2], 5, 'quantiles')
                        statval[:,i,j] = mask_quantiles(maskmat[:,i,j],Nquants)
            if dim == 1:
                statval = np.ones((21, maskshape[0], maskshape[2]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                    for j in range(maskshape[2]):
                        percendone(i*maskshape[2] + j, maskshape[0]*maskshape[2], 5, 'quantiles')
                        statval[:,i,j] = mask_quantiles(maskmat[i,:,j],Nquants)
            if dim == 2:
                statval = np.ones((21, maskshape[0], maskshape[1]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                    for j in range(maskshape[1]):
                        percendone(i*maskshape[1] + j, maskshape[0]*maskshape[1], 5, 'quantiles')
                        statval[:,i,j] = mask_quantiles(maskmat[i,j,:],Nquants)
        elif Ndims == 4:
            if dim == 0:
                statval = np.ones((21, maskshape[1], maskshape[2], maskshape[3]), dtype=np.float64)*fillValue
                for i in range(maskshape[1]):
                    for j in range(maskshape[2]):
                        for k in range(maskshape[3]):
                            percendone(i*maskshape[1]*maskshape[2] + j*maskshape[2] + k, maskshape[1]*maskshape[2]*maskshape[3], 5, 'quantiles')
                            statval[:,i,j,k] = mask_quantiles(maskmat[:,i,j,k],Nquants)
            if dim == 1:
                statval = np.ones((21, maskshape[0], maskshape[2], maskshape[3]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                    for j in range(maskshape[2]):
                        for k in range(maskshape[3]):
                            percendone(i*maskshape[0]*maskshape[2] + j*maskshape[2] + k, maskshape[0]*maskshape[2]*maskshape[3], 5, 'quantiles')
                            statval[:,i,j,k] = mask_quantiles(maskmat[i,:,j,k],Nquants)
            if dim == 2:
                statval = np.ones((21, maskshape[0], maskshape[1], maskshape[3]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                    for j in range(maskshape[1]):
                        for k in range(maskshape[3]):
                            percendone(i*maskshape[0]*maskshape[1] + j*maskshape[1] + k, maskshape[0]*maskshape[1]*maskshape[3], 5, 'quantiles')
                            statval[:,i,j,k] = mask_quantiles(maskmat[i,j,:,k],Nquants)
            if dim == 3:
                statval = np.ones((21, maskshape[0], maskshape[1], maskshape[2]), dtype=np.float64)*fillValue
                for i in range(maskshape[0]):
                    for j in range(maskshape[1]):
                        for k in range(maskshape[2]):
                            percendone(i*maskshape[0]*maskshape[1] + j*maskshape[1] + k, maskshape[0]*maskshape[1]*maskshape[2], 5, 'quantiles')
                            statval[:,i,j,k] = mask_quantiles(maskmat[i,j,k,:],Nquants)
        else:
            print errormsg
            print fname + ': size of matrix ', Ndims,'not ready!!!'
            print errormsg
            quit(-1)

    else:
        print errormsg
        print fname + ':  statistics "' + statn + '" not ready!!!!'
        print errormsg
        quit(-1)

    print stdout.write("\n")
    
    return statval

class statsVal(object):
  """Statistics class providing
  vals = variable
  self.Nv = number of values
  self.minv = minimum value
  self.maxv = maximum value
  self.meanv = mean value
  self.mean2v = cuadratic mean value
  self.stdv = standard deviation value
  self.Nokvalues = number of correct values of variable
  self.quantilesv = quantiles (%5 bins) of the variable
  """

  def __init__(self, vals):
    if vals is None:
      self.Nv = None
      self.minv = None
      self.maxv = None
      self.meanv = None
      self.mean2v = None
      self.stdv = None
      self.Nokvalues = None
      self.quantilesv = None
    else:
      values = vals.flatten() 
      self.Nv=len(values)
      self.minv=10000000000.
      self.maxv=-100000000.
      self.meanv=0.
      self.mean2v=0.
      self.stdv=0.

      sortedvalues = sorted(values)

      self.Nokvalues = 0
      for inum in range(self.Nv):
        if not values[inum] is None:
          self.Nokvalues = self.Nokvalues + 1
          if values[inum] < self.minv:
            self.minv = values[inum]
          if values[inum] > self.maxv:
            self.maxv = values[inum]

          self.meanv = self.meanv+values[inum]
          self.mean2v = self.mean2v+values[inum]*values[inum]

      self.meanv = self.meanv/float(self.Nokvalues)
      self.mean2v = self.mean2v/float(self.Nokvalues)
      self.stdv = np.sqrt(self.mean2v-self.meanv*self.meanv)
      self.quantilesv = []
      for iq in range(20):
        self.quantilesv.append(sortedvalues[int((self.Nv-1)*iq/20)])

      self.quantilesv.append(sortedvalues[self.Nv-1])
      self.medianv = self.quantilesv[10]

    return

class Quantiles(object):
    """ Class to provide quantiles from a given array of values
    """

    def __init__(self, values, Nquants):
        import numpy.ma as ma

        if values is None:
            self.quantilesv = None

        else:
            self.quantilesv = []

            vals0 = values.flatten()
            Nvalues = len(vals0)
            vals = ma.masked_equal(vals0, None)
            Nvals=len(vals.compressed())

            sortedvals = sorted(vals.compressed())
            for iq in range(Nquants):
                self.quantilesv.append(sortedvals[int((Nvals-1)*iq/Nquants)])

            self.quantilesv.append(sortedvals[Nvals-1])

        return

class statsVal_missVal(object):
  """Statistics class tacking into account a missing value providing
  vals = variable
  missval = missing value
  self.Nv = number of values
  self.minv = minimum value
  self.maxv = maximum value
  self.meanv = mean value
  self.mean2v = cuadratic mean value
  self.stdv = standard deviation value
  self.Nokvalues = number of correct values of variable
  self.quantilesv = quantiles (%5 bins) of the variable
  """

  def __init__(self, vals, missVal):
    fname='statsVal_missVal'
  
    if vals is None:
      self.Nv = None
      self.minv = None
      self.maxv = None
      self.meanv = None
      self.mean2v = None
      self.stdv = None
      self.Nokvalues = None
      self.quantilesv = None
    else:
      Npt = 1
      for idim in range(len(vals.shape)):
        Npt = Npt * vals.shape[idim]
      if np.sum(vals >= missVal) == Npt:
          print errormsg
          print '  ' + fname + ' all values get missing!!'
          print errormsg
          quit(-1)

      vals1 = np.where(abs(vals) >= missVal, None, vals)
      vals0 = np.where(np.isnan(vals1), None, vals1)

      values = vals0.flatten() 
      self.Nv=Npt
      self.minv=10000000000.
      self.maxv=-100000000.
      self.meanv=0.
      self.mean2v=0.
      self.stdv=0.

      sortedvalues = sorted(values)

      self.Nokvalues = 0
      for inum in range(self.Nv):
        if not values[inum] is None:
          self.Nokvalues = self.Nokvalues + 1
          if values[inum] < self.minv:
            self.minv = values[inum]
          if values[inum] > self.maxv:
            self.maxv = values[inum]

          self.meanv = self.meanv+values[inum]
          self.mean2v = self.mean2v+values[inum]*values[inum]

      self.meanv = self.meanv/float(self.Nokvalues)
      self.mean2v = self.mean2v/float(self.Nokvalues)
      self.stdv = np.sqrt(self.mean2v-self.meanv*self.meanv)
      self.quantilesv = []
      for iq in range(20):
        self.quantilesv.append(sortedvalues[int((self.Nv-1)*iq/20)])

      self.quantilesv.append(sortedvalues[self.Nv-1])
      self.medianv = self.quantilesv[10]

    return

def printing_class(classobj):
    """ Function to print all the values of a given class
    """

    valscls = vars(classobj)
    for attrcls in valscls:
        print attrcls, ':', valscls[attrcls]

    return

def fmtprinting_class(classobj):
    """ Function to print all the values of a given class
    """

    valscls = vars(classobj)
    for attrcls in valscls:
        print '@' + attrcls + '@', ':', valscls[attrcls]

    return

def singleline_printing_class(classobj):
    """ Function to print all the values of a given class in a single line to be parseavel
      output as: 'singleline_printing_class[attrval]';'[attrval]';'...
        [attrval] = @'[attribute]'@='[value]('!' for spaces)
    """
    fname='singleline_printing_class'

    valscls = vars(classobj)
    sline=fname + ' '

    for attrcls in valscls:
        sline = sline + '@' + attrcls + '@=' + str(valscls[attrcls]).replace(' ','!') + ";"

    print sline
    return

def cycl_incr(cyclval,cycle,ninc):
    """ Function to increment a cyclic value [cyclval] with a cycle [cycle] a given number [ninc] of times
    >>> cycl_incr(1,4,1)
    2
    >>> cycl_incr(3,4,1)
    0
    >>> cycl_incr(1,4,10)
    3
    """

    if ninc >= cycle:
        print 'cycl_incr: WARNING -- warning -- WARNING -- warning'
        print '    given increment: ', ninc,' is larger than the cycle !!'
        ninc = ninc - cycle*int(ninc/cycle)
        print '    reducing it to: ', ninc

    val=cyclval + ninc
    if val >= cycle:
        val=cyclval + ninc - cycle

    return val

def times_4seasons(tvals, integrity):
    """ Function to split a time series in matricial date format ([:,year,mon,day,hour,minute,second]) in the four stations DJF,MAM,JJA,SON
    tvals= matrix withe times as [:,year,mon,day,hour,minute,second]
    integrity= only give values for entire seasons [True, 3 months for the season], or just split the values by seasons [False] 
    """
    fillVal=1.e20

#    print tvals

    dt=tvals.shape[0]
    seasons=np.ones((dt,4),dtype=bool)
    seasons=seasons*False

    monseas=[12,3,6,9]
    firstseas=False

    for it in range(dt):
        if not firstseas:
            if integrity:
                for iseas in range(4):
                    if tvals[it,1] == monseas[iseas]:
                        nseas=iseas
                        seasons[it,nseas]=True
                        firstseas=True
                        begseas=it
            else:
                for iseas in range(4):
                    for imon in range(3):
                        if tvals[it,1] == cycl_incr(monseas[iseas],12,imon):
                            nseas=iseas
                            seasons[it,nseas]=True
                            firstseas=True                    
        else:
            newseas=cycl_incr(nseas,4,1)
            if tvals[it,1] == monseas[newseas]:
                seasons[it,newseas] = True
                nseas=newseas
                begseas=it
            else:
                seasons[it,nseas] = True

    endseas = it
##    print 'Last season: ',nseas,' beginnig: ',begseas,' ending: ',endseas

# Checking integrity of last season (has to have 3 months)
##
    if integrity:
        fullseas=True
        Nmon=np.unique(tvals[begseas:endseas+1,1])
        for it in range(begseas,endseas): fullseas=fullseas*seasons[it,nseas]
        if len(Nmon) < 3 or not fullseas:
            seasons[begseas:endseas+1,nseas] = False

    return seasons

def realdatetime_CFcompilant(times, Srefdate, tunits):
    """ Function to transform a matrix with real time values ([year, month, day, hour, minute, second]) to a netCDF one
    times= matrix with times
    Srefdate= reference date ([YYYY][MM][DD][HH][MI][SS] format)
    tunits= units of time respect to Srefdate
    >>> realdatetime_CFcompilant(np.array([ [1976, 2, 17, 8, 20, 0], [1976, 2, 18, 8, 20, 0]], dtype=int), '19491201000000', 'hours')
    [ 229784.33333333  229808.33333333]
    """ 

    import datetime as dt
    yrref=int(Srefdate[0:4])
    monref=int(Srefdate[4:6])
    dayref=int(Srefdate[6:8])
    horref=int(Srefdate[8:10])
    minref=int(Srefdate[10:12])
    secref=int(Srefdate[12:14])
 
    refdate=dt.datetime(yrref, monref, dayref, horref, minref, secref)

    dimt=times.shape[0]
        
    cfdates = np.zeros((dimt), dtype=np.float64)
    if tunits == 'weeks':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = (cfdate.days + cfdate.seconds/(3600.*24.))/7.
    elif tunits == 'days':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days + cfdate.seconds/(3600.*24.)
    elif tunits == 'hours':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24. + cfdate.seconds/3600.
    elif tunits == 'minutes':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24.*60. + cfdate.seconds/60.
    elif tunits == 'seconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*24.*3600. + cfdate.seconds
    elif tunits == 'milliseconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*1000.*24.*3600. + cfdate.seconds*1000.
    elif tunits == 'microseconds':
        for it in range(dimt):
            cfdate = dt.datetime(times[it,0], times[it,1], times[it,2], times[it,3], times[it,4], times[it,5]) - refdate
            cfdates[it] = cfdate.days*1000000.*24.*3600. + cfdate.seconds*1000000.
    else:
        print errormsg
        print '  ' + fname + ': time units "' + tunits + '" is not ready!!!'
        quit(-1)

    return cfdates

def realdatetime1_CFcompilant(time, Srefdate, tunits):
    """ Function to transform a matrix with a real time value ([year, month, day, 
      hour, minute, second]) to a netCDF one
        time= matrix with time
        Srefdate= reference date ([YYYY][MM][DD][HH][MI][SS] format)
        tunits= units of time respect to Srefdate
    >>> realdatetime1_CFcompilant([1976, 2, 17, 8, 20, 0], '19491201000000', 'hours')
    229784.33333333
    """ 

    import datetime as dt
    yrref=int(Srefdate[0:4])
    monref=int(Srefdate[4:6])
    dayref=int(Srefdate[6:8])
    horref=int(Srefdate[8:10])
    minref=int(Srefdate[10:12])
    secref=int(Srefdate[12:14])
 
    refdate=dt.datetime(yrref, monref, dayref, horref, minref, secref)

    if tunits == 'weeks':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5])-refdate
        cfdates = (cfdate.days + cfdate.seconds/(3600.*24.))/7.
    elif tunits == 'days':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5]) - refdate
        cfdates = cfdate.days + cfdate.seconds/(3600.*24.)
    elif tunits == 'hours':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5]) - refdate
        cfdates = cfdate.days*24. + cfdate.seconds/3600.
    elif tunits == 'minutes':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5]) - refdate
        cfdates = cfdate.days*24.*60. + cfdate.seconds/60.
    elif tunits == 'seconds':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5]) - refdate
        cfdates = cfdate.days*24.*3600. + cfdate.seconds
    elif tunits == 'milliseconds':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],time[5]) - refdate
        cfdates = cfdate.days*1000.*24.*3600. + cfdate.seconds*1000.
    elif tunits == 'microseconds':
        cfdate = dt.datetime(time[0],time[1],time[2],time[3],time[4],times[5]) - refdate
        cfdates = cfdate.days*1000000.*24.*3600. + cfdate.seconds*1000000.
    else:
        print errormsg
        print '  ' + fname + ': time units "' + tunits + '" is not ready!!!'
        quit(-1)

    return cfdates

def netCDFdatetime_realdatetime(units, tcalendar, times):
    """ Function to transfrom from netCDF CF-compilant times to real time
    [units]= CF time units [tunits] since [YYYY]-[MM]-[HH] [[HH]:[MI]:[SS]]
    [tcalendar]= time calendar
    [times]= CF time values
    """
    import datetime as dt

    txtunits = units.split(' ')
    tunits = txtunits[0]
    Srefdate = txtunits[len(txtunits) - 1]

# Calendar type
##
    is360 = False
    if tcalendar is not None:
      print '  netCDFdatetime_realdatetime: There is a calendar attribute'
      if tcalendar == '365_day' or tcalendar == 'noleap':
          print '    netCDFdatetime_realdatetime: No leap years!'
          isleapcal = False
      elif tcalendar == 'proleptic_gregorian' or tcalendar == 'standard' or tcalendar == 'gregorian':
          isleapcal = True
      elif tcalendar == '360_day':
          is360 = True
          isleapcal = False
      else:
          print errormsg
          print '    netCDFdatetime_realdatetime: Calendar "' + tcalendar + '" not prepared!'
          quit(-1)

# Does reference date contain a time value [YYYY]-[MM]-[DD] [HH]:[MI]:[SS]
##
    timeval = Srefdate.find(':')

    if not timeval == -1:
        print '  netCDFdatetime_realdatetime: refdate with time!'
        refdate = datetimeStr_datetime(txtunits[len(txtunits) - 2] + '_' + Srefdate)
    else:
        refdate = dateStr_date(Srefdate)

    dimt = len(times)
#    datetype = type(dt.datetime(1972,02,01))
#    realdates = np.array(dimt, datetype)
#    print realdates

## Not in timedelta
#  if tunits == 'years':
#    for it in range(dimt):
#      realdate = refdate + dt.timedelta(years=float(times[it]))
#      realdates[it] = int(realdate.year)
#  elif tunits == 'months':
#    for it in range(dimt):
#      realdate = refdate + dt.timedelta(months=float(times[it]))
#      realdates[it] = int(realdate.year)
#    realdates = []
    realdates = np.zeros((dimt, 6), dtype=int)
    if tunits == 'weeks':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(weeks=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'days':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(days=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'hours':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(hours=float(times[it]))
#            if not isleapcal:
#                Nleapdays = cal.leapdays(int(refdate.year), int(realdate.year))
#                realdate = realdate - dt.timedelta(days=Nleapdays)
#            if is360:
#                Nyears360 = int(realdate.year) - int(refdate.year) + 1
#                realdate = realdate -dt.timedelta(days=Nyears360*5)
#            realdates[it] = realdate
#        realdates = refdate + dt.timedelta(hours=float(times))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'minutes':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(minutes=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'seconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(seconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'milliseconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(milliseconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    elif tunits == 'microseconds':
        for it in range(dimt):
            realdate = refdate + dt.timedelta(microseconds=float(times[it]))
            realdates[it,:]=[realdate.year, realdate.month, realdate.day, realdate.hour, realdate.minute, realdate.second]
    else:
        print errormsg
        print '  netCDFdatetime_realdatetime: time units "' + tunits + '" is not ready!!!'
        quit(-1)

    return realdates

class cls_yearly_means(object):
    """ Class to compute the yearly mean of a time series of values
      tvals=time values (year, month, day, hour, minute, second) format
      values=time-series of values
      dateref= reference date [YYYY][MM][DD][HH][MI][SS] format
      tunits= time units
      self.dimt = Number of values
      self.yrv = yearly mean values
      self.yrt = years of the mean values
    >>> timesv = netCDFdatetime_realdatetime('days since 1949-12-01 00:00:00', 'standard', np.arange(1129))
    >>> valuesv = np.zeros((1129), dtype=np.float)
    >>> valuesv[0:31] = 0.
    >>> valuesv[31:394] = 1.
    >>> valuesv[395:761] = 2.
    >>> valuesv[761:1127] = 3.
    >>> valuesv[1127:1129] = 4.

    >>> yrlmeans = cls_yearly_means(timesv, valuesv, '19491201000000', 'days')
    >>> print yrlmeans.dimt,yrlmeans.yrv, yrlmeans.yrt 
    5 [ 0.  1.  2.  3.  4.] [ 1949.  1950.  1951.  1952.  1953.]
    """
    def __init__(self, tvals, values, dateref, tunits):

        import numpy.ma as ma
        fillVal=1.e20
        fname = 'cls_yearly_means'

        if tvals is None:
            self.dimt = None
            self.yrv = None
            self.yrt = None

        elif tvals == 'h':
            print fname + '_____________________________________________________________'
            print cls_yearly_means.__doc__
            quit()

        else:
            dt=len(values)
            if dt > 0:
                years = np.unique(tvals[:,0])
                Nyrs = len(years)
                yrmean = np.zeros((Nyrs), dtype=np.float)
                yrt = np.zeros((Nyrs), dtype=np.float)

                iiyr = tvals[0,0]
                yrmean[0] = values[0]
                yrt[0] = iiyr
                iit = 0
                for iyr in range(Nyrs):
                    nvals = 1
                    for it in range(iit+1,dt):
#                        print iyr, iiyr, it, tvals[it,0],':',values[it],'->',yrmean[iyr]
                        if tvals[it,0] == iiyr:
                            yrmean[iyr] = yrmean[iyr] + values[it]
                            nvals = nvals + 1
                        else:
                            yrmean[iyr] = yrmean[iyr] / (nvals*1.)
                            iiyr = tvals[it,0]
                            yrmean[iyr + 1] = values[it]
                            yrt[iyr+1] = iiyr
                            iit = it
                            break

                yrmean[Nyrs-1] = yrmean[Nyrs-1]/nvals
                self.dimt = Nyrs
                self.yrv = yrmean
                self.yrt = yrt
            else:
                print errormsg
                print '  ' + fname + ': No values passed!'
                print '    values:', values
                quit(-1)

        return

class cls_seasonal_means(object):
    """ Class to compute the seasonal mean of a time series of values
    tvals=time values (year, month, day, hour, minute, second) format
    values=time-series of values
    dateref= reference date [YYYY][MM][DD][HH][MI][SS] format
    tunits= time units
    self.dimt = Number of values
    self.seasv = seasonal mean values
    self.seast = seasonal time mean values
    """
    def __init__(self, tvals, values, dateref, tunits):

        import numpy.ma as ma
        fillVal=1.e20
        fname = 'cls_seasonal_means'

        if tvals is None:
            self.dimt = None
            self.seasv = None
            self.seast = None

        else:
            tseasons=times_4seasons(tvals, True)

            dt=len(values)
            seasvals=np.ones((dt/12,4), dtype=np.float64)*fillVal
            seastimes=np.zeros((dt/12,4), dtype=np.float64)
            dates = realdatetime_CFcompilant(tvals, dateref, tunits)

            for iseas in range(4):
                for it in range(dt):
                    if tseasons[it,iseas]:
                        tfirstseas=int(it/11)
                        firstseas=True
##                        print '  first time-step of season ', iseas, ' is: ',it,' position: ',tfirstseas
                        break
                for itt in range(it, dt-1,12):
                    seasvals[int(itt/12),iseas]=(values[itt] + values[itt+1] + values[itt+2])/3.
                    seastimes[int(itt/12),iseas]=dates[itt] + (dates[itt+2] - dates[itt])/2.
##                    print itt, values[itt], values[itt+1], values[itt+2], '--->', seasvals[int(itt/12),iseas]

            self.dimt = dt/12
            self.seasv = ma.masked_equal(seasvals, fillVal)
            self.seast = ma.masked_equal(seastimes, fillVal)

        return

class cls_seasonal_accums(object):
    """ Class to compute the seasonal accumulations of a time series of values
    tvals=time values (year, month, day, hour, minute, second) format
    values=time-series of values
    dateref= reference date [YYYY][MM][DD][HH][MI][SS] format
    tunits= time units
    self.dimt = Number of values
    self.seasv = seasonal mean values
    self.seast = seasonal time mean values
    """
    def __init__(self, tvals, values, dateref, tunits):
        import numpy.ma as ma
        fillVal=1.e20

        if tvals is None:
            self.dimt = None
            self.seasv = None
            self.seast = None

        else:
            tseasons=times_4seasons(tvals, True)

            dt=len(values)
            seasvals=np.ones((dt/12,4), dtype=np.float64)*fillVal
            seastimes=np.zeros((dt/12,4), dtype=np.float64)
            dates = realdatetime_CFcompilant(tvals, dateref, tunits)

            for iseas in range(4):
                for it in range(dt):
                    if tseasons[it,iseas]:
                        tfirstseas=int(it/11)
                        firstseas=True
#                        print '  first time-step of season ', iseas, ' is: ',it,' position: ',tfirstseas
                        break
                for itt in range(it, dt-1,12):
                    seasvals[int(itt/12),iseas]=values[itt] + values[itt+1] + values[itt+2]
                    seastimes[int(itt/12),iseas]=dates[itt] + (dates[itt+2] - dates[itt])/2.

            self.dimt = dt/12
            self.seasv = ma.masked_equal(seasvals, fillVal)
            self.seast = ma.masked_equal(seastimes, fillVal)

        return

def seasonal_means(tvals, values):
    """ Function to compute the seasonal mean of a time series of values
    tvals=time values (year, month, day, hour, minute, second) format
    values=time-series of values
    """
    fillVal=1.e20

    tseasons=times_4seasons(tvals, True)

    dt=len(values)
    seasvals=np.ones((dt/4,4), dtype=np.float64)
    seasvals=seasvals*fillVal

    for iseas in range(4):
        for it in range(dt):
            if tseasons[it,iseas]:
                tfirstseas=int(it/11)
                firstseas=True
#                print '  first time-step of season ', iseas, ' is: ',it,' position: ',tfirstseas
                break
        for itt in range(it, dt-1,12):
            seasvals[int(itt/12),iseas]=(values[itt] + values[itt+1] + values[itt+2])/3.

    return seasvals

def seasonal_accum(tvals, values):
    """ Function to compute the seasonal accumulation of a time series of values
    tvals=time values (year, month, day, hour, minute, second) format
    values=time-series of values
    """
    fillVal=1.e20

    tseasons=times_4seasons(tvals, True)

    dt=len(values)
    seasvals=np.ones((dt/4,4), dtype=np.float64)
    seasvals=seasvals*fillVal

    for iseas in range(4):
        for it in range(dt):
            if tseasons[it,iseas]:
                tfirstseas=int(it/11)
                firstseas=True
#                print '  first time-step of season ', iseas, ' is: ',it,' position: ',tfirstseas
                break
        for itt in range(it, dt-1,12):
            seasvals[int(itt/11),iseas]=values[itt] + values[itt+1] + values[itt+2]

    return seasvals

def load_variable_lastdims(var, prevdims, Nlastdims):
    """ Function to load the last [Nlastdims] dimensions of a variable [var] at the other dimensions at [prevdims]
    >>> load_variable_lastdims(np.array(range(5*5*5)).reshape(5,5,5), [1,2], 1)
    [35 36 37 38 39]
    """
    fname='load_variable_lastdims'

    dims=var.shape
    Ndims=len(dims)

    Nprevdims = len(prevdims)
    if not Nprevdims + Nlastdims == Ndims:
        print erromsg
        print '  ' + fname + ': number of dimensions previous (',Nprevdim,') and last (',Nlastdims, ') does not match with variable size: ',Ndims,' !!!!'
        print errormsg
        quit(-1)

    if Nlastdims > Ndims-1:
        print errormsg
        print '  ' + fname + ': number of last dimensions ', Nlastdims,' >= than the number of dimensions of the variable ', Ndims,' !!!!'
        print errormsg
        quit(-1)

    if Ndims == 1:
        loadvar = var[:]
    elif Ndims == 2:
        loadvar = var[prevdims[0], :]
    elif Ndims == 3:
        if Nlastdims == 1:
            loadvar = var[prevdims[0], prevdims[1], :]
        else:
            loadvar = var[prevdims[0], :, :]
    elif Ndims == 4:
        if Nlastdims == 1:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], :]
        elif Nlastdims == 2:
            loadvar = var[prevdims[0], prevdims[1], :, :]
        else:
            loadvar = var[prevdims[0], :, :, :]
    elif Ndims == 5:
        if Nlastdims == 1:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], prevdims[3], :]
        elif Nlastdims == 2:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], :, :]
        elif Nlastdims == 3:
            loadvar = var[prevdims[0], prevdims[1], :, :, :]
        else:
            loadvar = var[prevdims[0], :, :, :, :]
    elif Ndims == 6:
        if Nlastdims == 1:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], prevdims[3], prevdims[4], :]
        elif Nlastdims == 2:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], prevdims[3], :, :]
        elif Nlastdims == 3:
            loadvar = var[prevdims[0], prevdims[1], prevdims[2], :, :, :]
        elif Nlastdims == 4:
            loadvar = var[prevdims[0], prevdims[1], :, :, :, :]
        else:
            loadvar = var[prevdims[0], :, :, :, :]
    else:
        print errormsg
        print '  ' + fname + ' variable size ', Ndims, ' not ready!!!'
        print errormsg
        quit(-1)

    return loadvar

def indices_mask(mask):
    """ Function to retrieve the indices from a 2D mask
    mask= 2D mask matrix
    mat=np.array(range(100), dtype=float).reshape((10,10))
    >>> mask1= mat >= 45. 
    >>> mask2= mat <= 55.
    >>> mask = mask1 * mask2
    indices_mask(mask)
    [[4 5]
    [4 6]
    [4 7]
    [4 8]
    [4 9]
    [5 0]
    [5 1]
    [5 2]
    [5 3]
    [5 4]
    [5 5]]
    """
    dy=mask.shape[0]
    dx=mask.shape[1]

    Nptmask = np.sum(mask)
    maskindices = np.zeros((Nptmask,2), dtype=int)
    ij=0
    for j in range(dy):
        for i in range(dx):
            if mask[j,i] == True:
                maskindices[ij,0] = j
                maskindices[ij,1] = i
                ij = ij + 1

    return maskindices

def typemod(value, typeval):
    """ Function to give back a value in a given dtype
    >>> print(typemod(8.2223, 'np.float64'))
    <type 'numpy.float64'>
    >>> print(typemod(8.2223, 'tuple'))
    <type 'tuple'>
    """
    fname='typemod'

    if typeval == 'int':
        return int(value)
    elif typeval == 'long':
        return long(value)
    elif typeval == 'float':
        return float(value)
    elif typeval == 'complex':
        return complex(value)
    elif typeval == 'str' or typeval == 'S':
        return str(value)
    elif typeval == 'bool':
        return bool(value)
    elif typeval == 'list':
        newval = []
        newval.append(value)
        return newval
    elif typeval == 'dic':
        newval = {}
        newval[value] = value
        return newval
    elif typeval == 'tuple':
        newv = []
        newv.append(value)
        newval = tuple(newv)
        return newval
    elif typeval == 'np.int8':
        return np.int8(value)
    elif typeval == 'np.int16':
        return np.int16(value)
    elif typeval == 'np.int32':
        return np.int32(value)
    elif typeval == 'np.int64':
        return np.int64(value)
    elif typeval == 'np.uint8':
        return np.uint8(value)
    elif typeval == 'np.uint16':
        return np.uint16(value)
    elif typeval == 'np.np.uint32':
        return np.uint32(value)
    elif typeval == 'np.uint64':
        return np.uint64(value)
    elif typeval == 'np.float' or typeval == 'R':
        return np.float(value)
    elif typeval == 'np.float16':
        return np.float16(value)
    elif typeval == 'np.float32':
        return np.float32(value)
    elif typeval == 'float32':
        return np.float32(value)
    elif typeval == 'np.float64':
        return np.float64(value)
    elif typeval == 'float64':
        return np.float64(value)
    elif typeval == 'np.complex':
        return np.complex(value)
    elif typeval == 'np.complex64':
        return np.complex64(value)
    elif typeval == 'np.complex128':
        return np.complex128(value)
    else:
        print errormsg
        print fname + ':  data type "' + typeval + '" is not ready !'
        print errormsg
        quit(-1)

    return

def diffdate_units(diffdate, units):
    """ Function to transform a difference of dates to a certain units
    diffdate = difference of dates (as timedelta)
    units = units to transform: 'weeks', 'days', 'hours', 'minutes', 'seconds', 'miliseconds', 'nanoseconds'
    >>> diffdate_units(dt.datetime(1976, 2, 17, 8, 32, 5) - dt.datetime(1949, 12, 1, 0, 0, 0), 'seconds')
    827224325.0
    """
    fname = 'diffdate_units'

    if units == 'weeks':
        diffunits = diffdate.days/7. + diffdate.seconds/(3600.*24.*7.)
    elif units == 'days':
        diffunits = diffdate.days + diffdate.seconds/(3600.*24.)
    elif units == 'hours':
        diffunits = diffdate.days*24. + diffdate.seconds/(3600.)
    elif units == 'minutes':
        diffunits = diffdate.days*24.*60. + diffdate.seconds/(60.)
    elif units == 'seconds':
        diffunits = diffdate.days*24.*3600. + diffdate.seconds
    elif units == 'miliseconds':
        diffunits = diffdate.days*24.*3600.*1000. + diffdate.seconds*1000.
    elif units == 'nanoseconds':
        diffunits = diffdate.days*24.*3600.*1000000. + diffdate.seconds*1000000.
    else:
        print errormsg
        print fname + ': time units "' + units + '" not ready!!!'
        print errormsg
        quit(-1)

    return diffunits

def days_month(year,month):
    """ Function to give the number of days of a month of a given year
    >>> days_month(1976,2)
    29
    """
    import datetime as dt

    date1=dt.date(year,month,1)
    date2=dt.date(year,month+1,1)

    diffdate = date2-date1
    return diffdate.days

def mid_period(yr1,mon1,day1,hour1,min1,sec1,yr2,mon2,day2,hour2,min2,sec2):
    """ Function to give the mid poiint of a period
    >>> mid_period(1976,2,1,0,0,0,1976,3,1,0,0,0)
    [1976    2   15   12    0    0]
    """
    import datetime as dt

    date1=dt.datetime(yr1,mon1,day1,hour1,min1,sec1)
    date2=dt.datetime(yr2,mon2,day2,hour2,min2,sec2)

    diffdate = date2-date1
    diffseconds = diffdate.days*24*3600 + diffdate.seconds
    diff2 = dt.timedelta(seconds=diffseconds/2)
    datenew = date1 + diff2
    datenewvals = np.array([datenew.year, datenew.month, datenew.day, datenew.hour,  \
      datenew.minute, datenew.second])

    return datenewvals

def days_year(year):
    """ Function to give the number of days of a year
    >>> days_year(1976)
    366
    """
    import datetime as dt

    date1=dt.date(year,1,1)
    date2=dt.date(year+1,1,1)

    diffdate = date2-date1
    return diffdate.days

def days_period(yeari,yearf):
    """ Function to give the number of days for a period
    >>> days_period(1976,1980)
    1827
    """

    ndays=0    
    for iyr in range(yearf-yeari+1):
        ndays=ndays+days_year(yeari+iyr)

    return ndays

class ysubsetstats(object):
    """ Class to compute multi-year statistics of a given subset of values 
    values= values to use
    dates=dates of the values in matrix format ([year], [month], [day], [hour], [minute], [second])
    sec=section to use for the period='year', 'month', 'day', 'hour', 'minute', 'second'
    vali=initial value of the period
    valf=final value of the period
    Nq= number of quantiles (20 for 5% bins, it is going to produce 21 values)
    missval= missing value
      self.Nvalues = Number of non masked values
      self.min = minimum non masked value
      self.max = maximum non masked value
      self.mean = mean non masked value
      self.mean2 = quandratic mean non masked value
      self.stdev = standard deviation non masked value
      self.quantiles = quantiles non masked value
    """  
    def __init__(self, values, dates, sec, vali, valf, Nq, missVal):
        import numpy.ma as ma

        fname = 'ysubsetstats'
  
        if values is None:
            self.Nvalues = None
            self.min = None

            self.max = None
            self.mean = None
            self.mean2 = None
            self.stdev = None
            self.quantiles = None

        else:
            Nvalues = len(values)
            Ndates = len(dates)

            if Nvalues != Ndates:
                print errormsg
                print fname + ': number of values ', Nvalues,' does not coincide with the number of dates ',Ndates, '!!!!!!'
                print errormsg
                quit(-1)

            initialsub = np.zeros(Nvalues, dtype=bool)
            endsub = initialsub.copy()

            if missVal > 0.:
                valuesmask = ma.masked_greater_equal(values, missVal*0.9)
            else:
                valuesmask = ma.masked_less_equal(values, missVal*0.9)

            if sec == 'year':
                isec = 0
            elif sec == 'month':
                isec = 1
            elif sec == 'day':
                isec = 2
            elif sec == 'hour':
                isec = 3
            elif sec == 'minute':
                isec = 4
            elif sec == 'second':
                isec = 5
            else:
                print errormsg
                print fname + ': sction "' + sec + '" not ready!!!!'
                print errormsg
                quit(-1)
    
            if vali < valf:
                timesmaskperi = ma.masked_less(dates[:,isec], vali)
                timesmaskperf = ma.masked_greater(dates[:,isec], valf)
            else:
                timesmaskperi = ma.masked_less(dates[:,isec], valf)
                timesmaskperf = ma.masked_greater(dates[:,isec], vali)

            finalmask = valuesmask.mask+timesmaskperi.mask+timesmaskperf.mask
            finalvalues = ma.array(values, mask=finalmask)

            finalvalues2 = finalvalues*finalvalues

            self.Nvalues = finalvalues.count()
            self.min = finalvalues.min()
            self.max = finalvalues.max()
            self.mean = finalvalues.mean()
            self.mean2 = finalvalues2.mean()
            self.stdev = finalvalues.std()
            self.quantiles = mask_quantiles(finalvalues, Nq) 

        return

def give_fix1dim_values(mat,iddim,dimval):
    """ Function to return matrix values when one dimension has been removed at a 
      given value
    mat = matrix
    iddim = dimesion to remove (starting from 0 tacking the right most)
    dimval = value of the dimension

    >>> matrix = np.array( (range(27)), dtype=np.float).reshape(3,3,3)
    give_fix1dim_values(matrix,2,2)
    [[[  0.   1.   2.]
      [  3.   4.   5.]
      [  6.   7.   8.]]

     [[  9.  10.  11.]
      [ 12.  13.  14.]
      [ 15.  16.  17.]]]
    """
    fname='give_fix1dim_values'

# Not working ma.squeeze
##    import numpy.ma as ma
##    print ma.squeeze(mat, axis = (idim,))
    
    matshape = mat.shape
    mattype = mat.dtype
    matmask = np.ones( tuple(matshape), dtype=bool)

    zerodims=np.ones( (6), dtype=int)
    Ndims = len(matshape)
    if Ndims > 6: 
        print errmsg
        print '  ' + fname + ' number of dimensions: ',Ndims,' not ready!!!!!'
        quit(-1)

    zerodims[5-Ndims+1:6] = matshape

    newdims = list(matshape)
    newdims[Ndims-1-iddim] = matshape[iddim]-1

    mask = np.ones(tuple(zerodims), dtype=bool)
    vals = np.zeros(tuple(zerodims), dtype=mattype)
    vals[0:zerodims[0],0:zerodims[1],0:zerodims[2],0:zerodims[3],0:zerodims[4],
      0:zerodims[5]] = mat

    for i5 in range(zerodims[5]):
        for i4 in range(zerodims[4]):
            for i3 in range(zerodims[3]):
                for i2 in range(zerodims[2]):
                    for i1 in range(zerodims[1]):
                        for i0 in range(zerodims[0]):
#                            print 'iddim:',iddim,'dimval:',dimval,'-->',i0,i1,i2,i3,i4,i5
                            if iddim == 5 and dimval == i0:
                                mask[i0,i1,i2,i3,i4,i5] = False
                            elif iddim == 4 and dimval == i1:
                                mask[i0,i1,i2,i3,i4,i5] = False
                            elif iddim == 3 and dimval == i2:
                                mask[i0,i1,i2,i3,i4,i5] = False
                            elif iddim == 2 and dimval == i3:
                                mask[i0,i1,i2,i3,i4,i5] = False
                            elif iddim == 1 and dimval == i4:
                                mask[i0,i1,i2,i3,i4,i5] = False
                            elif iddim == 0 and dimval == i5:
                                mask[i0,i1,i2,i3,i4,i5] = False

    newmat = vals[mask].reshape(tuple(newdims))
#    print 'newmat dim:',iddim,'val:',dimval,':',newdims,'______'
#    print newmat
   
    return newmat

def portion_fix1dim_values(mat,iddim,dimval):
    """ Function to return that portion of the matrix values when one dimension has
      been removed at a given value
    mat = matrix
    iddim = dimesion to remove (starting from 0 tacking the right most)
    dimval = value of the dimension

    >>> matrix = np.array( (range(27)), dtype=np.float).reshape(3,3,3)
    portion_fix1dim_values(matrix,2,2)
    [[ 18.  19.  20.]
     [ 21.  22.  23.]
     [ 24.  25.  26.]]
    """
    fname='portion_fix1dim_values'

# Not working ma.squeeze
##    import numpy.ma as ma
##    print ma.squeeze(mat, axis = (idim,))
    
    matshape = mat.shape
    mattype = mat.dtype
    matmask = np.zeros( tuple(matshape), dtype=bool)

    zerodims=np.ones( (6), dtype=int)
    Ndims = len(matshape)

    if Ndims > 6: 
        print errmsg
        print '  ' + fname + ' number of dimensions: ',Ndims,' not ready!!!!!'
        quit(-1)

    zerodims[5-Ndims+1:6] = matshape

    newdims = []
    for idim in range(Ndims):
        if idim != iddim:
            newdims.append(matshape[idim])

    newdims.reverse()

    mask = np.zeros(tuple(zerodims), dtype=bool)
    vals = np.zeros(tuple(zerodims), dtype=mattype)
    vals[0:zerodims[0],0:zerodims[1],0:zerodims[2],0:zerodims[3],0:zerodims[4],
      0:zerodims[5]] = mat

    for i5 in range(zerodims[5]):
        for i4 in range(zerodims[4]):
            for i3 in range(zerodims[3]):
                for i2 in range(zerodims[2]):
                    for i1 in range(zerodims[1]):
                        for i0 in range(zerodims[0]):
#                            print 'iddim:',iddim,'dimval:',dimval,'-->',i0,i1,i2,i3,i4,i5
                            if iddim == 5 and dimval == i0:
                                mask[i0,i1,i2,i3,i4,i5] = True
                            elif iddim == 4 and dimval == i1:
                                mask[i0,i1,i2,i3,i4,i5] = True
                            elif iddim == 3 and dimval == i2:
                                mask[i0,i1,i2,i3,i4,i5] = True
                            elif iddim == 2 and dimval == i3:
                                mask[i0,i1,i2,i3,i4,i5] = True
                            elif iddim == 1 and dimval == i4:
                                mask[i0,i1,i2,i3,i4,i5] = True
                            elif iddim == 0 and dimval == i5:
                                mask[i0,i1,i2,i3,i4,i5] = True

#    print 'newmat dim:',iddim,'val:',dimval,':',newdims,'______'
    newmat = vals[mask].reshape(tuple(newdims))
#    print newmat
   
    return newmat

def retype(val, vtype):
    """ Function to transform a value to a given type
    retype(val, vtype)
      [val]= value
      [vtype]= type to transform
    >>> retype(0, type(True))
    False
    """
    fname = 'retype'

    if val == 'h':
        print fname + '_____________________________________________________________'
        print retype.__doc__
        quit()

    if vtype == type(int(1)):
        newval = int(val)
    elif vtype == type(float(1)):
        newval = float(val)
#    elif vtype == type(float32(1)):
#        newval = float32(val)
    elif vtype == type(np.int(1)):
        typeinf = np.iinfo(np.int)
        if (abs(np.float64(val)) > typeinf.max):
            print warnmsg
            print '  ' + fname + ': value to transform ', val,' overpasses type:',   \
               vtype,' limits!!'
            print '  Changing value to kind largest allowed value:', typeinf.max
            newval = abs(np.float64(val))/np.float64(val) * np.int(typeinf.max)
        else:
            newval = np.int(val)
    elif vtype == type(np.int16(1)):
        typeinf = np.iinfo(np.int16)
        if (abs(np.float64(val)) > typeinf.max):
            print warnmsg
            print '  ' + fname + ': value to transform ', val,' overpasses type:',   \
               vtype,' limits!!'
            print '  Changing value to kind largest allowed value:', typeinf.max
            newval = abs(np.float64(val))/np.float64(val) * np.int16(typeinf.max)
        else:
            newval = np.int16(val)
    elif vtype == type(np.int32(1)):
        typeinf = np.iinfo(np.int32)
        if (np.abs(np.float64(val)) > typeinf.max):
            print warnmsg
            print '  ' + fname + ': value to transform ', val,' overpasses type:',   \
               vtype,' limits!!'
            print '  Changing value to kind largest allowed value:', typeinf.max
            newval = abs(np.float64(val))/np.float64(val) * np.int32(typeinf.max)
        else:
            newval = np.int32(np.float64(val))
    elif vtype == type(np.int64(1)):
        newval = np.int64(val)
    elif vtype == type(np.float(1)):
        newval = np.float(val)
#    elif vtype == type(np.float16(1)):
#        newval = np.float16(val)
    elif vtype == type(np.float32(1)):
        newval = np.float32(val)
    elif vtype == type(np.float64(1)):
        newval = np.float64(val)
    elif vtype == type(True):
        if val == 0:
            newval = False
        else:
            newval = True
    elif vtype == '|S1' or vtype == type('s'):
        newval = str(val)
    else:
        print errormsg
        print '  ' + fname + ': variable type "', vtype, '" not ready!!!'
        quit(-1)

    return newval

class stats_space2D(object):
    """spatial statistics for a 2D file:
      vals= variable ro check (assuming var[t,dy,dx])
        self.minv[t]: spatial minimum at each time-step
        self.maxv[t]: spatial maximum at each time-step
        self.meanv[t]: spatial mean at each time-step
        self.mean2v[t]: spatial quadratic mean at each time-step
        self.stdv[t]: spatial standard deviation at each time-step
        self.anomv[t]: spatial anomaly from the whole mean at each time-step
    """
  
    def __init__(self, vals):
        from scipy import stats as sts
        fname = 'stats_space2D'

        if vals1 == 'h':
            print fname + '_____________________________________________________________'
            print stats_space2Dvars.__doc__
            quit()

        if vals1 is None:
            self.minv = None
            self.maxv = None
            self.meanv = None
            self.mean2v = None
            self.stdv = None
        else:
            dimt = vals.shape[0]
            stats=np.zeros((dimt,5), dtype=np.float)
            absmean = np.mean(vals)

            for it in range(dimt):
                stats[it,0]=np.min(vals[it,:,:])
                stats[it,1]=np.max(vals[it,:,:])
                stats[it,2]=np.mean(vals[it,:,:])
                stats[it,3]=np.mean(vals[it,:,:]*vals[it,:,:])
                stats[it,4]=absmean - stats[it,2]

            stats = np.where(stats > 0.1*fillValue, fillValue, stats)
            stats = np.where(stats is nan, fillValue, stats)
            stats = np.where(stats is np.inf, fillValue, stats)
            stats = np.where(stats is None, fillValue, stats)

            self.minv=stats[:,0]
            self.maxv=stats[:,1]
            self.meanv=stats[:,2]
            self.mean2v=stats[:,3]
            self.stdv=np.sqrt(stats[:,3]-stats[:,2]*stats[:,2])
            self.anomv=stats[:,4]

        return

class stats_space2Dvars(object):
    """spatial statistics beween 2 2D files:
    valsA = variable 1 (assuming var[t,dy,dx])
    valsB = variable 2 (assuming var[t,dy,dx])
    self.min[t,var], self.max[t,var], self.mean[t,var], self.mean2[t,var], 
      self.std[t,var]
      [var] = var1+var2[v1Av2], var1-var2[v1Sv2], var1/var2[v1Dv2], var1*var2[v1Pv2]

    self.mae=mean[t,abs(var1-var2)]
    self.correlation=correlation[var1,var2] (and p-value) 
    self.bias=[t,mean(var1)-mean(var2)]
    self.meancorrelation=correlation[mean(var1),mean(var2)] (and p-value) 
    """

    def __init__(self, vals1, vals2):
        from scipy import stats as sts
        fname = 'stats_space2Dvars'

        if vals1 == 'h':
            print fname + '_____________________________________________________________'
            print stats_space2Dvars.__doc__
            quit()

        if vals1 is None:
            self.minv1Av2 = None
            self.maxv1Av2 = None
            self.meanv1Av2 = None
            self.mean2v1Av2 = None
            self.stdv1Av2 = None
            self.minv1Sv2 = None
            self.maxv1Sv2 = None
            self.meanv1Sv2 = None
            self.mean2v1Sv2 = None
            self.stdv1Sv2 = None
            self.minv1Dv2 = None
            self.maxv1Dv2 = None
            self.meanv1Dv2 = None
            self.mean2v1Dv2 = None
            self.stdv1Dv2 = None
            self.minv1Pv2 = None
            self.maxv1Pv2 = None
            self.meanv1Pv2 = None
            self.mean2v1Pv2 = None
            self.stdv1Pv2 = None
            self.mae = None
            self.corr = None
        else:
            dimt = vals1.shape[0]
            stats=np.zeros((dimt,26), dtype=np.float)
            meanvals1 = np.zeros((dimt), dtype=np.float)
            meanvals2 = np.zeros((dimt), dtype=np.float)
    
            for it in range(dimt):
                v1 = vals1[it,:,:].flatten() 
                v2 = vals2[it,:,:].flatten() 

# add
                vs = v1 + v2
                stats[it,0] = np.min(vs)
                stats[it,1] = np.max(vs)
                stats[it,2] = np.mean(vs)
                stats[it,3] = np.mean(vs*vs)
                stats[it,4] = np.sqrt(stats[it,3] - stats[it,2]*stats[it,2])
# sub
                stats[it,20] = np.mean(np.abs(v1-v2))
                vs = v1 - v2
                stats[it,5] = np.min(vs)
                stats[it,6] = np.max(vs)
                stats[it,7] = np.mean(vs)
                stats[it,8] = np.mean(vs*vs)
                stats[it,9] = np.sqrt(stats[it,8] - stats[it,7]*stats[it,7])

# mul
                vs = v1 * v2
                stats[it,10] = np.min(vs)
                stats[it,11] = np.max(vs)
                stats[it,12] = np.mean(vs)
                stats[it,13] = np.mean(vs*vs)
                stats[it,14] = np.sqrt(stats[it,13] - stats[it,12]*stats[it,12])
# div
                vs = v1 / v2
                stats[it,15] = np.min(vs)
                stats[it,16] = np.max(vs)
                stats[it,17] = np.mean(vs)
                stats[it,18] = np.mean(vs*vs)
                stats[it,19] = np.sqrt(stats[it,18] - stats[it,17]*stats[it,17])
# corr
                stats[it,21], stats[it,22] = mask_pearsonr(v1, v2)

# Mean values
                meanvals1[it] = np.mean(v1)
                meanvals2[it] = np.mean(v2)
                stats[it,23] =  meanvals1[it] - meanvals2[it]
            
            stats = np.where(stats > 0.1*fillValue, fillValue, stats)
            stats = np.where(stats is np.nan, fillValue, stats)
            stats = np.where(stats is np.inf, fillValue, stats)
            stats = np.where(stats is None, fillValue, stats)

            self.minv1Av2 = stats[:,0]
            self.maxv1Av2 = stats[:,1]
            self.meanv1Av2 = stats[:,2]
            self.meanv21Av2 = stats[:,3]
            self.stdv1Av2 = stats[:,4]

            self.minv1Sv2 = stats[:,5]
            self.maxv1Sv2 = stats[:,6]
            self.meanv1Sv2 = stats[:,7]
            self.meanv21Sv2 = stats[:,8]
            self.stdv1Sv2 = stats[:,9]

            self.minv1Pv2 = stats[:,10]
            self.maxv1Pv2 = stats[:,11]
            self.meanv1Pv2 = stats[:,12]
            self.meanv21Pv2 = stats[:,13]
            self.stdv1Pv2 = stats[:,14]

            self.minv1Dv2 = stats[:,15]
            self.maxv1Dv2 = stats[:,16]
            self.meanv1Dv2 = stats[:,17]
            self.meanv21Dv2 = stats[:,18]
            self.stdv1Dv2 = stats[:,19]

            self.mae = stats[:,20]
            self.corr = stats[:,21]
            self.p_value = stats[:,22]

            self.bias = stats[:,23]
            self.meancorr, self.meanp_value = sts.pearsonr(meanvals1, meanvals2)

        return

class stats_time2D(object):
    """temporal statistics for a 2D file:
      vals= variable ro check (assuming var[t,dy,dx])
        self.minv[t]: temporal minimum at each grid point
        self.maxv[t]: temporal maximum at each grid point
        self.meanv[t]: temporal mean at each grid point
        self.mean2v[t]: temporal quadratic mean at each grid point
        self.stdv[t]: temporal standard deviation at each grid point
        self.anomv[t]: temporal anomaly from the whole mean at each grid point
    """
  
    def __init__(self, vals):
        from scipy import stats as sts
        fname = 'stats_time2D'

        if vals1 == 'h':
            print fname + '_____________________________________________________________'
            print stats_time2Dvars.__doc__
            quit()

        if vals1 is None:
            self.minv = None
            self.maxv = None
            self.meanv = None
            self.mean2v = None
            self.stdv = None
        else:
            dimx = vals.shape[2]
            dimy = vals.shape[1]
            stats=np.zeros((dimy,dimx,5), dtype=np.float)
            absmean = np.mean(vals,axis=0)

            stats[:,:,0]=np.min(vals, axis=0)
            stats[:,:,1]=np.max(vals, axis=0)
            stats[:,:,2]=np.mean(vals, axis=0)
            stats[:,:,3]=np.mean(vals*vals, axis=0)
            stats[:,:,4]=absmean - stats[:,:,2]

            stats = np.where(stats > 0.1*fillValue, fillValue, stats)
            stats = np.where(stats is np.nan, fillValue, stats)
            stats = np.where(stats is np.inf, fillValue, stats)
            stats = np.where(stats is None, fillValue, stats)

            self.minv=stats[:,:,0]
            self.maxv=stats[:,:,1]
            self.meanv=stats[:,:,2]
            self.mean2v=stats[:,:,3]
            self.stdv=np.sqrt(stats[:,:,3]-stats[:,:,2]*stats[:,:,2])
            self.anomv=stats[:,:,4]

        return

class stats_time2Dvars(object):
    """temporal statistics beween 2 2D files:
    valsA = variable 1 (assuming var[t,dy,dx])
    valsB = variable 2 (assuming var[t,dy,dx])
    self.min[dy,dx,var], self.max[dy,dx,var], self.mean[dy,dx,var], 
      self.mean2[dy,dx,var], self.std[dy,dx,var]
      [var] = var1+var2[v1Av2], var1-var2[v1Sv2], var1/var2[v1Dv2], var1*var2[v1Pv2]

    self.mae=mean[dy,dx,abs(var1-var2)]
    self.correlation=correlation[var1,var2] (and p-value) 
    self.bias=[dy,dx,mean(var1)-mean(var2)]
    self.meancorrelation=correlation[mean(var1),mean(var2)] (and p-value) 
    """

    def __init__(self, vals1, vals2):
        from scipy import stats as sts
        fname = 'stats_time2Dvars'

        if vals1 == 'h':
            print fname + '_____________________________________________________________'
            print stats_time2Dvars.__doc__
            quit()

        if vals1 is None:
            self.minv1Av2 = None
            self.maxv1Av2 = None
            self.meanv1Av2 = None
            self.mean2v1Av2 = None
            self.stdv1Av2 = None
            self.minv1Sv2 = None
            self.maxv1Sv2 = None
            self.meanv1Sv2 = None
            self.mean2v1Sv2 = None
            self.stdv1Sv2 = None
            self.minv1Dv2 = None
            self.maxv1Dv2 = None
            self.meanv1Dv2 = None
            self.mean2v1Dv2 = None
            self.stdv1Dv2 = None
            self.minv1Pv2 = None
            self.maxv1Pv2 = None
            self.meanv1Pv2 = None
            self.mean2v1Pv2 = None
            self.stdv1Pv2 = None
            self.mae = None
            self.corr = None
        else:
            dimx = vals1.shape[1]
            dimy = vals1.shape[1]
            stats=np.zeros((dimy,dimx,24), dtype=np.float)
            meanvals1 = np.zeros((dimy,dimx), dtype=np.float)
            meanvals2 = np.zeros((dimy,dimx), dtype=np.float)
# add
            vs = vals1 + vals2
            stats[:,:,0] = np.min(vs,axis=0)
            stats[:,:,1] = np.max(vs,axis=0)
            stats[:,:,2] = np.mean(vs,axis=0)
            stats[:,:,3] = np.mean(vs*vs,axis=0)
            stats[:,:,4] = np.sqrt(stats[:,:,3] - stats[:,:,2]*stats[:,:,2])
# sub
            stats[:,:,20] = np.mean(np.abs(vals1-vals2), axis=0)
            vs = vals1 - vals2
            stats[:,:,5] = np.min(vs,axis=0)
            stats[:,:,6] = np.max(vs,axis=0)
            stats[:,:,7] = np.mean(vs,axis=0)
            stats[:,:,8] = np.mean(vs*vs,axis=0)
            stats[:,:,9] = np.sqrt(stats[:,:,8] - stats[:,:,7]*stats[:,:,7])
# mul
            vs = vals1 * vals2
            stats[:,:,10] = np.min(vs,axis=0)
            stats[:,:,11] = np.max(vs,axis=0)
            stats[:,:,12] = np.mean(vs,axis=0)
            stats[:,:,13] = np.mean(vs*vs,axis=0)
            stats[:,:,14] = np.sqrt(stats[:,:,13] - stats[:,:,12]*stats[:,:,12])
# div
            vs = vals1 / vals2
            stats[:,:,15] = np.min(vs,axis=0)
            stats[:,:,16] = np.max(vs,axis=0)
            stats[:,:,17] = np.mean(vs,axis=0)
            stats[:,:,18] = np.mean(vs*vs,axis=0)
            stats[:,:,19] = np.sqrt(stats[:,:,18] - stats[:,:,17]*stats[:,:,17])


# Mean values
            meanvals1[:,:] = np.mean(vals1,axis=0)
            meanvals2[:,:] = np.mean(vals2,axis=0)
            stats[:,:,23] =  meanvals1[:,:] - meanvals2[:,:]
            
# corr
            self.meancorr, self.meanp_value = sts.pearsonr(meanvals1.flatten(), meanvals2.flatten())

            for j in range(dimy):
                for i in range(dimx):
                    stats[j,i,21], stats[j,i,22] = sts.pearsonr(vals1[:,j,i], vals2[:,j,i])

            stats = np.where(stats > 0.1*fillValue, fillValue, stats)
            stats = np.where(stats is np.nan, fillValue, stats)
            stats = np.where(stats is np.inf, fillValue, stats)
            stats = np.where(stats is None, fillValue, stats)

            self.minv1Av2 = stats[:,:,0]
            self.maxv1Av2 = stats[:,:,1]
            self.meanv1Av2 = stats[:,:,2]
            self.meanv21Av2 = stats[:,:,3]
            self.stdv1Av2 = stats[:,:,4]

            self.minv1Sv2 = stats[:,:,5]
            self.maxv1Sv2 = stats[:,:,6]
            self.meanv1Sv2 = stats[:,:,7]
            self.meanv21Sv2 = stats[:,:,8]
            self.stdv1Sv2 = stats[:,:,9]

            self.minv1Pv2 = stats[:,:,10]
            self.maxv1Pv2 = stats[:,:,11]
            self.meanv1Pv2 = stats[:,:,12]
            self.meanv21Pv2 = stats[:,:,13]
            self.stdv1Pv2 = stats[:,:,14]

            self.minv1Dv2 = stats[:,:,15]
            self.maxv1Dv2 = stats[:,:,16]
            self.meanv1Dv2 = stats[:,:,17]
            self.meanv21Dv2 = stats[:,:,18]
            self.stdv1Dv2 = stats[:,:,19]

            self.mae = stats[:,:,20]
            self.corr = stats[:,:,21]
            self.p_value = stats[:,:,22]

            self.bias = stats[:,:,23]

        return

#vals1 = np.arange(27).reshape(3,3,3)*1.
#vals2 = np.arange(1,28).reshape(3,3,3)*1.

#printing_class(stats_time2Dvars(vals1,vals2))

def file_nlines(filen,char):
    """ Function to provide the number of lines of a file
    filen= name of the file
    char= character as no line
    >>> file_nlines('trajectory.dat','#')
    49
    """
    fname = 'file_nlines'

    if not os.path.isfile(filen):
        print errormsg
        print '  ' + fname + ' file: "' + filen + '" does not exist !!'
        quit(-1)

    fo = open(filen,'r')

    nlines=0
    for line in fo: 
        if line[0:1] != char: nlines = nlines + 1

    fo.close()

    return nlines

def table_tex(tablevals, colnames, rownames, of):
    """ Function to write into a LaTeX tabular from a table of values
      tablevals = (ncol nrow) of values
      colnames = list with ncol labels for the columns (1 more than data for the row names)
      rownames = list with nrow labels for the rows
      of= object ASCII file to write the table
    """
    errormsg = 'ERROR -- error -- ERROR -- error'

    fname = 'table_tex'

    Ncol = tablevals.shape[0]
    Nrow = tablevals.shape[1]

    if Ncol + 1 != len(colnames):
        print errormsg
        print '  ' + fname + ': wrong number of column names!!'
        print '    data has:', Ncol, 'and you provided:', len(colnames)
        print '    remember to provide one more for the label of the rows!'
        print '    you provide:',colnames
        quit(-1)

    if Nrow != len(rownames):
        print errormsg
        print '  ' + fname + ': wrong number of row names!!'
        print '    data has:', Nrow, 'and you provided:', len(rownames)
        print '    you provide:',rownames
        quit(-1)

    colcs = ''
    colns = ''
    for icol in colnames:
        colcs = colcs + 'c'
        if icol == colnames[0]:
            colns = ' {\\bfseries{' + icol + '}}'
        else:
            colns = colns + ' & {\\bfseries{' + icol + '}}'

    of.write('\n')
    of.write("%Automatically written file from function '" + fname + "'\n")
    of.write('\\begin{tabular}{l'+colcs+'}\n')
    of.write(colns + ' \\\\ \\hline\n')

    ir = 0
    for irow in rownames:
        rowns = '{\\bfseries{' + irow + '}}'
        for ic in range(Ncol):
            rowns = rowns + ' & ' + str(tablevals[ic,ir])
        rowns = rowns + ' \\\\'

        of.write(rowns + '\n')
        ir = ir + 1

    of.write('\\end{tabular}\n')

    return

def table_tex_file(Ncol, Nrow, tablevals, colnames, rownames, ofile):
    """ Function to write into a file a LaTeX tabular from a table of values
      tablevals = (ncol nrow) of values
      colnames = list with ncol labels for the columns (1 more than data for the row names)
      rownames = list with nrow labels for the rows
      ofile= ASCII file to write the table
    >>> values = np.arange(15).reshape(5,3)
    >>> colns = ['a','b','c','d','e']
    >>> rowns = ['i','ii','iii']
    >>> table_text_file(5, 3, values, colns, rowns, 'table.tex')
    """
    fname = 'table_tex_file'

    objf = open(ofile, 'w')
    objf.write('\\documentclass{article}\n')
    objf.write('\n')
    objf.write('\\begin{document}\n')

    table_tex(tablevals, colnames, rownames, objf)

    objf.write('\\end{document}\n')
    objf.close()

    print fname + "': successfull written of '" + ofile + "' !!"

    return

def radius_dist(dx,dy,ptx,pty):
    """ Function to generate a matrix with the distance at a given point
    radius_dist(dx,dy,ptx,pty)
      [dx/y]: dimension of the matrix
      [ptx/y]: grid point coordinates of the point
    >>> radius_dist(5,4,2,2)
    [[ 2.82842712  2.23606798  2.          2.23606798  2.82842712]
     [ 2.23606798  1.41421356  1.          1.41421356  2.23606798]
     [ 2.          1.          0.          1.          2.        ]
     [ 2.23606798  1.41421356  1.          1.41421356  2.23606798]]
    """

    fname = 'radius_dist'

    if ptx < 0 or ptx > dx-1 or pty < 0 or pty > dy-1:
        print errormsg
        print '  ' + fname + ': wrong point coordinates:',dx,',',dy,'for matrix;',dx \
         ,'x',dy
        quit(-1)

    xdist =  np.zeros((dy,dx), dtype=np.float)
    ydist =  np.zeros((dy,dx), dtype=np.float)
    dist =  np.zeros((dy,dx), dtype=np.float)

    for ix in range(dx):
        xdist[:,ix] = np.float(ix-ptx)
    for iy in range(dy):
        ydist[iy,:] = np.float(pty-iy)

    dist = np.sqrt(xdist*xdist + ydist*ydist)

    return dist

def radius_angle(dx,dy,ptx,pty):
    """ Function to generate a matrix with the angle at a given point
    radius_angle(dx,dy,ptx,pty)
      [dx/y]: dimension of the matrix
      [ptx/y]: grid point coordinates of the point
    >>> radius_angle(5,4,2,2)*180./np.pi
    [[ 315.          333.43494882    0.           26.56505118   45.        ]
     [ 296.56505118  315.            0.           45.           63.43494882]
     [ 270.          270.            0.           90.           90.        ]
     [ 243.43494882  225.          180.          135.          116.56505118]]
    """
    fname = 'radius_angle'

    if ptx < 0 or ptx > dx-1 or pty < 0 or pty > dy-1:
        print errormsg
        print '  ' + fname + ': wrong point coordinates:',dx,',',dy,'for matrix;',dx \
         ,'x',dy
        quit(-1)

    xdist =  np.zeros((dy,dx), dtype=np.float)
    ydist =  np.zeros((dy,dx), dtype=np.float)
    angle =  np.zeros((dy,dx), dtype=np.float)

    for ix in range(dx):
        xdist[:,ix] = np.float(ix-ptx)
    for iy in range(dy):
        ydist[iy,:] = np.float(pty-iy)

    angle = np.arctan2(xdist,ydist)
    angle = np.where(angle < 0., angle + 2*np.pi, angle)

    return angle

def lonlat2D(lon,lat):
    """ Function to return lon, lat 2D matrices from any lon,lat matrix
      lon= matrix with longitude values
      lat= matrix with latitude values
    """
    fname = 'lonlat2D'

    if len(lon.shape) != len(lat.shape):
        print errormsg
        print '  ' + fname + ': longitude values with shape:', lon.shape,            \
          'is different than latitude values with shape:', lat.shape, '(dif. size) !!'
        quit(-1)

    if len(lon.shape) == 3:
        lonvv = lon[0,:,:]
        latvv = lat[0,:,:]
    elif len(lon.shape) == 2:
        lonvv = lon[:]
        latvv = lat[:]
    elif len(lon.shape) == 1:
        lonlatv = np.meshgrid(lon[:],lat[:])
        lonvv = lonlatv[0]
        latvv = lonlatv[1]

    return lonvv, latvv

def interpolate_locs(locs,coords,kinterp):
    """ Function to provide interpolate locations on a given axis
    interpolate_locs(locs,axis,kinterp)
      locs= locations to interpolate
      coords= axis values with the reference of coordinates
      kinterp: kind of interpolation
        'lin': linear
    >>> coordinates = np.arange((10), dtype=np.float)
    >>> values = np.array([-1.2, 2.4, 5.6, 7.8, 12.0])
    >>> interpolate_locs(values,coordinates,'lin')
    [ -1.2   2.4   5.6   7.8  13. ]
    >>> coordinates[0] = 0.5
    >>> coordinates[2] = 2.5
    >>> interpolate_locs(values,coordinates,'lin')
    [ -3.4          1.93333333   5.6          7.8         13.        ]
    """

    fname = 'interpolate_locs'

    if locs == 'h':
        print fname + '_____________________________________________________________'
        print interpolate_locs.__doc__
        quit()

    Nlocs = locs.shape[0]
    Ncoords = coords.shape[0]

    dcoords = coords[Ncoords-1] - coords[0]

    intlocs = np.zeros((Nlocs), dtype=np.float)
    minc = np.min(coords)
    maxc = np.max(coords)

    for iloc in range(Nlocs):
        for icor in range(Ncoords-1):
            if locs[iloc] < minc and dcoords > 0.:
                a = 0.
                b = 1. / (coords[1] - coords[0])
                c = coords[0]
            elif locs[iloc] > maxc and dcoords > 0.:
                a = (Ncoords-1)*1.
                b = 1. / (coords[Ncoords-1] - coords[Ncoords-2])
                c = coords[Ncoords-2]
            elif locs[iloc] < minc and dcoords < 0.:
                a = (Ncoords-1)*1.
                b = 1. / (coords[Ncoords-1] - coords[Ncoords-2])
                c = coords[Ncoords-2]
            elif locs[iloc] > maxc and dcoords < 0.:
                a = 0.
                b = 1. / (coords[1] - coords[0])
                c = coords[0]
            elif locs[iloc] >= coords[icor] and locs[iloc] < coords[icor+1] and dcoords > 0.:
                a = icor*1.
                b = 1. / (coords[icor+1] - coords[icor])
                c = coords[icor]
                print coords[icor], locs[iloc], coords[icor+1], ':', icor, '->', a, b
            elif locs[iloc] <= coords[icor] and locs[iloc] > coords[icor+1] and dcoords < 0.:
                a = icor*1.
                b = 1. / (coords[icor+1] - coords[icor])
                c = coords[icor]

        if kinterp == 'lin':
            intlocs[iloc] = a + (locs[iloc] - c)*b
        else:
            print errormsg
            print '  ' + fname + ": interpolation kind '" + kinterp + "' not ready !!!!!"
            quit(-1)

    return intlocs

def vertical_interpolation2D(varb,vart,zorigvals,znewval,kinterp):
    """ Function to vertically integrate a 3D variable
    vertical_interpolation2D(varb,vart,zorigvals,znewval)
      varb= values at the base of the interval of interpolation (2D field)
      vart= values at the top of the interval of interpolation (2D field)
      zorigvals= pair of original values (2, 2D field)
      znewval= new value to interpolate
      Possible cases:
        zorigvals[0,:,:] <= znewval < zorigvals[1,:,:]
        znewval <= zorigvals[0,:,:] < zorigvals[1,:,:]
        zorigvals[0,:,:] < zorigvals[1,:,:] <= znewval
      kinterp: kind of interpolation
        'lin': linear
    >>> dx=5
    >>> dy=7
    >>> vals1 = np.ones((dy,dx), dtype=np.float)
    >>> vals2 = np.ones((dy,dx), dtype=np.float)*2.

    >>> zbase = np.zeros((2,dy,dx), dtype=np.float)
    >>> zbase[0,:,:] = 0.5
    >>> zbase[1,:,:] = 1.

    >>> vertical_interpolation2D(vals1,vals2, zbase, newz,'lin')
    [[ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]
     [ 1.5  1.5  1.5  1.5  1.5]]
    """

    fname = 'vertical_interpolation2D'

    if varb == 'h':
        print fname + '_____________________________________________________________'
        print vertical_interpolation2D.__doc__
        quit()

    newvar = np.zeros((varb.shape), dtype=np.float)
    if kinterp == 'lin':
##        print '  ' + fname + ' Vertical linear interpolation at',znewval
# Standard linear interpolation (y = a + b*incz)
#   a = zorig[0], b = (vart-varb)/(zorig[1]-zorig[0])), incz = znewval - zorig[0]
        a = varb
        b = np.where(zorigvals[1,:,:] == zorigvals[0,:,:], 0.,                       \
          (vart - varb)/(zorigvals[1,:,:] - zorigvals[0,:,:]))
        incz = np.ones((varb.shape), dtype=np.float)*znewval - zorigvals[0,:,:]

        newvar = a + b*incz
# Too code for not be used... but maybe?
#        dx=varb.shape[1]
#        dy=varb.shape[0]
#        for j in range(dy):
#            for i in range(dx):
#                  if zorigvals[1,j,i] == zorigvals[0,j,i]: print 'equals!',          \
#                    zorigvals[1,j,i], zorigvals[0,j,i],':',newvar[j,i],'@',vart[j,i]
#                  if zorigvals[0,j,i] != zorigvals[0,j,i]: print '0 Nan',            \
#                    zorigvals[0,j,i],':',newvar[j,i],'@',vart[j,i]
#                  if zorigvals[1,j,i] != zorigvals[1,j,i]: print '1 Nan',            \
#                    zorigvals[1,j,i],':',newvar[j,i],'@',vart[j,i]
#                  if zorigvals[0,j,i] is None: print '0 None', zorigvals[0,j,i],':', \
#                    newvar[j,i],'@',vart[j,i]
#                  if zorigvals[1,j,i] is None: print '1 None', zorigvals[1,j,i],':', \
#                    newvar[j,i],'@',vart[j,i]
    else:
        print errormsg
        print '  ' + fname + ": interpolation kind '" + kinterp + "' not ready !!!!!"
        quit(-1)

    return newvar

#dx=5
#dy=7
#vals1 = np.ones((dy,dx), dtype=np.float)
#vals2 = np.ones((dy,dx), dtype=np.float)*2.

#zbase = np.zeros((2,dy,dx), dtype=np.float)
#zbase[0,:,:] = 0.5
#for i in range(dx):
#    for j in range(dy):
#        zbase[1,j,i] = np.sqrt((j-dy/2.)**2. + (i-dx/2.)**2.) /                      \
#          np.sqrt((dy/2.)**2.+(dy/2.)**2.) + 1.

#zbase[1,:,:] = 1.

#newz = 0.75

#print vertical_interpolation2D(vals1,vals2, zbase, newz,'lin')

def vertical_interpolation(varb,vart,zorigvals,znewval,kinterp):
    """ Function to vertically integrate a 1D variable
    vertical_interpolation(varb,vart,zorigvals,znewval)
      varb= values at the base of the interval of interpolation
      vart= values at the top of the interval of interpolation
      zorigvals= pair of original values (2)
      znewval= new value to interpolate
      Possible cases:
        zorigvals[0,:] <= znewval < zorigvals[1,:]
        znewval <= zorigvals[0,:] < zorigvals[1,:]
        zorigvals[0,:] < zorigvals[1,:] <= znewval
      kinterp: kind of interpolation
        'lin': linear
    >>> dx=5
    >>> vals1 = np.ones((dx), dtype=np.float)
    >>> vals2 = np.ones((dx), dtype=np.float)*2.

    >>> zbase = np.zeros((2,dx), dtype=np.float)
    >>> zbase[0,:] = 0.5
    >>> for i in range(dx):
    >>>     zbase[1,i] = i + 1.

    >>> newz = 0.75
    >>> vertical_interpolation2D(vals1,vals2, zbase, newz,'lin')
    [ 1.5         1.16666667  1.1         1.07142857  1.05555556]
    """

    fname = 'vertical_interpolation'

    if varb == 'h':
        print fname + '_____________________________________________________________'
        print vertical_interpolation.__doc__
        quit()

    newvar = np.zeros((varb.shape), dtype=np.float)
    if kinterp == 'lin':
##        print '  ' + fname + ' Vertical linear interpolation at',znewval
# Standard linear interpolation (y = a + b*incz)
#   a = zorig[0], b = (vart-varb)/(zorig[1]-zorig[0])), incz = znewval - zorig[0]
        a = varb
        b = np.where(zorigvals[1,:] == zorigvals[0,:], 0.,                           \
          (vart - varb)/(zorigvals[1,:] - zorigvals[0,:]))
        incz = np.ones((varb.shape), dtype=np.float)*znewval - zorigvals[0,:]

        newvar = a + b*incz
    else:
        print errormsg
        print '  ' + fname + ": interpolation kind '" + kinterp + "' not ready !!!!!"
        quit(-1)

    return newvar

def interpolate_3D(zorigvs, varv, zintvs, kint):
    """ Function to interpolate a 3D variable
    interpolate_3D(zintvs, varv, zorigvals)
      zorigvs= original 3D z values
      varv= 3D variable to interpolate
      zintvs= new series of z values to interpolate
      kint= kind of interpolation
        'lin': linear
    """
    fname = 'interpolate_3D'

    if zorigvs == 'h':
        print fname + '_____________________________________________________________'
        print interpolate_3D.__doc__
        quit()

    Ninv = len(zintvs)
    dimv = varv.shape

# Sense of the original z-variable
    Lzorig = zorigvs.shape[0]
    incz = zorigvs[Lzorig-1,0,0] - zorigvs[0,0,0]

    varin = np.zeros((Ninv,dimv[1],dimv[2]), dtype=np.float)

    for ilev in range(Ninv):
#        print ' vertical interpolate level: ',zintvs[ilev]
        valinf = np.zeros((dimv[1], dimv[2]), dtype=np.float)
        valsup = np.zeros((dimv[1], dimv[2]), dtype=np.float)
        zorigv = np.zeros((2,dimv[1], dimv[2]), dtype=np.float)
        for j in range(valinf.shape[0]):
            for i in range(valinf.shape[1]):
                
                if np.min(zorigvs[:,j,i]) > zintvs[ilev] and incz > 0.:
                    valinf[j,i] = varv[0,j,i]
                    valsup[j,i] = varv[1,j,i]
                    zorigv[0,j,i] = zorigvs[0,j,i]
                    zorigv[1,j,i] = zorigvs[1,j,i]
                elif np.max(zorigvs[:,j,i]) < zintvs[ilev] and incz < 0.:
                    valinf[j,i] = varv[0,j,i]
                    valsup[j,i] = varv[1,j,i]
                    zorigv[0,j,i] = zorigvs[0,j,i]
                    zorigv[1,j,i] = zorigvs[1,j,i]
                elif np.max(zorigvs[:,j,i]) < zintvs[ilev] and incz > 0.:
                    valinf[j,i] = varv[Lzorig-2,j,i]
                    valsup[j,i] = varv[Lzorig-1,j,i]
                    zorigv[0,j,i] = zorigvs[Lzorig-2,j,i]
                    zorigv[1,j,i] = zorigvs[Lzorig-1,j,i]
                elif np.min(zorigvs[:,j,i]) > zintvs[ilev] and incz < 0.:
                    valinf[j,i] = varv[Lzorig-2,j,i]
                    valsup[j,i] = varv[Lzorig-1,j,i]
                    zorigv[0,j,i] = zorigvs[Lzorig-2,j,i]
                    zorigv[1,j,i] = zorigvs[Lzorig-1,j,i]
#                    print 'top: ',i,j,':',zorigv[0,j,i], zintvs[ilev], zorigv[1,j,i]
                else:
                    for z in range(Lzorig-1):
                        if (zorigvs[z,j,i]-zintvs[ilev])*(zorigvs[z+1,j,i]-          \
                          zintvs[ilev]) <= 0.:
                            valinf[j,i] = varv[z,j,i]
                            valsup[j,i] = varv[z+1,j,i]
                            zorigv[0,j,i] = zorigvs[z,j,i]
                            zorigv[1,j,i] = zorigvs[z+1,j,i]
                            break

#        print 'zorigvs: ',zorigvs[:,0,0]
#        print '  valinf:', valinf[0,0]
#        print '  valsup:', valsup[0,0]
#        print '  zorigv 0:',zorigv[0,0,0]
#        print '  zorigv 1:',zorigv[1,0,0]

        varin[ilev,:,:] = vertical_interpolation2D(valinf,valsup,zorigv,             \
          zintvs[ilev], kint)
#        print '  varin:',varin[ilev,0,0]
#        quit()

#    quit()
    return varin

def interpolate_2D(zorigvs0, varv0, zdim, zintvs, kint):
    """ Function to interpolate a 2D variable
    interpolate_2D(zintvs, varv, zorigvals)
      zorigvs= original 2D z values
      varv= 2D variable to interpolate
      zdim= number of the dimension with the z-values
      zintvs= new series of z values to interpolate
      kint= kind of interpolation
        'lin': linear
    """
    fname = 'interpolate_2D'

    if zorigvs0 == 'h':
        print fname + '_____________________________________________________________'
        print interpolate_2D.__doc__
        quit()

    Ninv = len(zintvs)
    if zdim == 0:
        varv = varv0
        zorigvs = zorigvs0
    else:
        varv = np.transpose(varv0)
        zorigvs = np.transpose(zorigvs0)

    dimv = varv.shape

# Sense of the original z-variable
    Lzorig = zorigvs.shape[0]
    incz = zorigvs[Lzorig-1,0] - zorigvs[0,0]

    varin = np.zeros((Ninv,dimv[1]), dtype=np.float)

    for ilev in range(Ninv):
        valinf = np.zeros((dimv[1]), dtype=np.float)
        valsup = np.zeros((dimv[1]), dtype=np.float)
        zorigv = np.zeros((2,dimv[1]), dtype=np.float)
        for i in range(valinf.shape[0]):   
            if np.min(zorigvs[:,i]) > zintvs[ilev] and incz > 0.:
                valinf[i] = varv[0,i]
                valsup[i] = varv[1,i]
                zorigv[0,i] = zorigvs[0,i]
                zorigv[1,i] = zorigvs[1,i]
            elif np.max(zorigvs[:,i]) < zintvs[ilev] and incz < 0.:
                valinf[i] = varv[0,i]
                valsup[i] = varv[1,i]
                zorigv[0,i] = zorigvs[0,i]
                zorigv[1,i] = zorigvs[1,i]
            elif np.max(zorigvs[:,i]) < zintvs[ilev] and incz > 0.:
                valinf[i] = varv[Lzorig-2,i]
                valsup[i] = varv[Lzorig-1,i]
                zorigv[0,i] = zorigvs[Lzorig-2,i]
                zorigv[1,i] = zorigvs[Lzorig-1,i]
            elif np.min(zorigvs[:,i]) > zintvs[ilev] and incz < 0.:
                valinf[i] = varv[Lzorig-2,i]
                valsup[i] = varv[Lzorig-1,i]
                zorigv[0,i] = zorigvs[Lzorig-2,i]
                zorigv[1,i] = zorigvs[Lzorig-1,i]
            else:
                for z in range(Lzorig-1):
                    if (zorigvs[z,i]-zintvs[ilev])*(zorigvs[z+1,i]-                  \
                      zintvs[ilev]) <= 0.:
                        valinf[i] = varv[z,i]
                        valsup[i] = varv[z+1,i]
                        zorigv[0,i] = zorigvs[z,i]
                        zorigv[1,i] = zorigvs[z+1,i]
                        break

        varin[ilev,:] = vertical_interpolation(valinf,valsup,zorigv,                 \
          zintvs[ilev], kint)

    if zdim == 0:
        varin0 = varin
    else:
        varin0 = np.transpose(varin)

    return varin0

def list_toVec(listv, kind):
    """ Function to transform from a list of values to a vector
    list_toVec(listv, kind)
      listv= list with the values 
      kind= kind of values
      >>> list_toVec(['1', 2, '3', 4, 5, '6.9', 7, 9], 'npfloat')
      [ 1.   2.   3.   4.   5.   6.9  7.   9. ]
    """

    fname = 'list_toVec'

    if listv == 'h':
        print fname + '_____________________________________________________________'
        print list_toVec.__doc__
        quit()

    Nvals = len(listv)

    if kind == 'npfloat':
        vecv = np.zeros((Nvals), dtype=np.float)
        for iv in range(Nvals):
            vecv[iv] = np.float(listv[iv])
    else:
        print errormsg
        print '  ' + fname + ': type of value "' + kind + '" not ready!!'
        quit(-1)

    return vecv

def running_mean(values, run):
    """ Function to compute a running mean of a series of values
      running_mean(vals, int)
      [vals]: series of values
      [run]: interval to use to compute the running mean 
        NOTE: resultant size would be the same but with None except at [run/2,size(vals)-run/2]
      >>> running_mean(np.arange(100),10)
      [None None None None None 4.5 5.5 6.5 7.5 8.5 9.5 10.5 11.5 12.5 13.5 14.5
       15.5 16.5 17.5 18.5 19.5 20.5 21.5 22.5 23.5 24.5 25.5 26.5 27.5 28.5 29.5
       30.5 31.5 32.5 33.5 34.5 35.5 36.5 37.5 38.5 39.5 40.5 41.5 42.5 43.5 44.5
       45.5 46.5 47.5 48.5 49.5 50.5 51.5 52.5 53.5 54.5 55.5 56.5 57.5 58.5 59.5
       60.5 61.5 62.5 63.5 64.5 65.5 66.5 67.5 68.5 69.5 70.5 71.5 72.5 73.5 74.5
       75.5 76.5 77.5 78.5 79.5 80.5 81.5 82.5 83.5 84.5 85.5 86.5 87.5 88.5 89.5
       90.5 91.5 92.5 93.5 None None None None None]
    """
    fname = 'running_mean'

    if values == 'h':
        print fname + '_____________________________________________________________'
        print running_mean.__doc__
        quit()

    runmean = np.ones((len(values)), dtype=np.float)*fillValue

    for ip in range(run/2,len(values)-run/2):
        runmean[ip] = np.mean(values[ip-run/2:ip+run/2])

    runmean = np.where(runmean == fillValue, None, runmean)

    return runmean

def files_folder_HMT(folder='.',head='',middle='',tail=''):
    """ Function to retrieve a list of files from a folder [fold] and files with [head]*[middle]*[tail]
    >>> files_folder_HMT('.','t','wrf','mean.nc')
    ['clt_wrfout_tmean.nc', 'tas_wrfout_tmean.nc', 'ta_wrfout_xmean.nc']
    >>> files_folder_HMT(folder='/home/lluis/etudes/WRF_LMDZ/WaquaL_highres/tests/model_graphics/WRF/current', \
      head='hfls', tail='.nc')
    ['hfls_wrfout.nc', 'hfls_wrfout_tmean.nc']
    """
    import subprocess as sub
    fname = 'files_folder'

    if folder == 'h':
        print fname + '_____________________________________________________________'
        print files_folder.__doc__
        quit()

    # FROM: http://stackoverflow.com/questions/9997048/python-subprocess-wildcard-usage
    ins = folder + "/" + head + "*" + middle + '*' + tail
    #ins = folder + "/"
    #files = sub.Popen(["/bin/ls","-1R",ins], shell=True, stdout=sub.PIPE)
    files = sub.Popen("/bin/ls -1R " + ins, shell=True, stdout=sub.PIPE)
    fileslist = files.communicate()
    listfiles0 = str(fileslist).replace("'",'').replace('(','').replace(')','').split('\\n')

# Filtering output
    listfiles = []
    for ifile in listfiles0:
        print 'file:', ifile, '<>', ifile.find(head) != -1 and  ifile.find(middle) != -1 and ifile.find(tail) != -1 
        if ifile.find(head) != -1 and  ifile.find(middle) != -1 and                  \
          ifile.find(tail) != -1:
            indhead = ifile.index(head)
            indmiddle = ifile.index(middle)
            if indmiddle == 0: indmiddle = indhead
            indtail = ifile.index(tail)
            if indtail == 0: indtail = inhead + inmiddle
            if indhead <= indmiddle <= indtail: listfiles.append(ifile)

    return listfiles

def files_folder(folder,headfile):
    """ Function to retrieve a list of files from a folder [fold] and head [headfile]
    >>> files_folder('/media/data2/etudes/WRF_LMDZ/WL_HyMeX_HighRes/medic950116/', 
      'wrfout_d03')
    ['wrfout_d03_1995-01-13_02:00:00', 'wrfout_d03_1995-01-13_04:00:00', 'wrfout_d03_1995-01-13_06:00:00', 
     'wrfout_d03_1995-01-13_06:15:00', 'wrfout_d03_1995-01-13_08:15:00', 'wrfout_d03_1995-01-13_10:15:00',
     'wrfout_d03_1995-01-13_12:15:00', 'wrfout_d03_1995-01-13_14:15:00', 'wrfout_d03_1995-01-13_16:15:00',     
     (...)
     'wrfout_d03_1995-01-17_18:15:00', 'wrfout_d03_1995-01-17_20:15:00', 'wrfout_d03_1995-01-17_22:15:00']
    """
    import subprocess as sub
    fname = 'files_folder'

    if folder == 'h':
        print fname + '_____________________________________________________________'
        print files_folder.__doc__
        quit()

#    ins = folder + "/" + headfile + "*"
    ins = folder + "/"
#    print 'ins:',ins
    files = sub.Popen(["/bin/ls","-1",ins], stdout=sub.PIPE)
    fileslist = files.communicate()
    listfiles0 = str(fileslist).replace("'",'').replace('(','').replace(')','').split('\\n')

# Filtering output
    Lheader=len(headfile)
    listfiles = []
    for ifile in listfiles0:
        if ifile[0:Lheader] == headfile:
            listfiles.append(ifile)

    return listfiles

def count_cond(var, val, con):
    """ Function to count values of a variable which attain a condition
      [var]= variable
      [val]= value
      [con]= statistics/condition
        'eq': equal than [val]
        'neq': not equal than [val]
        'lt': less than [val]
        'le': less and equal than [val]
        'gt': greater than [val]
        'ge': greater and equal than [val]
        'in': inside the range [val[0]] <= [var] <= [val[1]] (where [val]=[val1, val2]
        'out': inside the range [val[0]] > [var]; [val[1]] < [var] (where [val]=[val1, val2]
      >>> vals = np.arange(100)
      >>> count_cond(vals,50,'eq')
      1
      >>> count_cond(vals,50,'neq')
      99
      >>> count_cond(vals,50,'lt')
      50
      >>> count_cond(vals,50,'le')
      51
      >>> count_cond(vals,50,'gt')
      49
      >>> count_cond(vals,50,'ge')
      50
      >>> count_cond(vals,[25,75],'in')
      51
      >>> count_cond(vals,[25,75],'out')
      49
    """
    fname = 'count_cond'

    cons = ['eq', 'neq', 'lt', 'le', 'gt', 'ge', 'in', 'out']

    if con == 'eq':
        Nvals = np.sum(var == val)
    elif con == 'neq':
        Nvals = np.sum(var != val)
    elif con == 'lt':
        Nvals = np.sum(var < val)
    elif con == 'le':
        Nvals = np.sum(var <= val)
    elif con == 'gt':
        Nvals = np.sum(var > val)
    elif con == 'ge':
        Nvals = np.sum(var >= val)
    elif con == 'in':
        if len(val) != 2:
            print errormsg
            print '  ' + fname + ": for condition '" + con + "' we must have two " + \
              " values!!" 
            print '  we have:',  val
            quit(-1)
        Nvals = np.sum((var >= val[0])*(var <= val[1]))
    elif con == 'out':
        if len(val) != 2:
            print errormsg
            print '  ' + fname + ": for condition '" + con + "' we must have two " + \
              " values!!" 
            print '  we have:',  val
            quit(-1)
        Nvals = np.sum((var < val[0])+(var > val[1]))
    else:
        print errormsg
        print '  ' + fname + ": condition '" + con + "' not ready!!"
        print '  only ready:', cons
        quit(-1)

    return Nvals

def check_timestep(otval):
    """ Function to check if a time-units are 'timestep' based. If it's the case, transform them
      otval = time variable object
    """
    fname = 'check_timestep'

    varatrs = otval.ncattrs()

    if not searchInlist(varatrs, 'units'):
        print errormsg
        print '  ' + main+'.'+fname + ": object variable without 'units' attribute!!"
        print '    attributes found:', varatrs
        quit(-1)

    tunits = otval.getncattr('units')
    if tunits.split(' ')[0] == 'timesteps':
        print warnmsg
        print '  ' + fname + ": time variable with 'timesteps' as units !!"
        print '    modifying time values'

        dimvn = otval.dimensions[0]

        # looking for units of time-step as 'clever' combination with dimension name?
        Tunitssecs = ['second', 'minute', 'hour', 'day']
        foundCFunits = False
        Tunitsguess = []
        for Tunit in Tunitssecs:
            attrn = Tunit[0:1]
            if searchInlist(varatrs,dimvn+'_'+attrn):
                CFtu = Tunit + 's'
                foundCFunits = True
                break
            Tunitsguess.append(dimvn+'_'+attrn)
            attrn = Tunit[0:3]
            if searchInlist(varatrs,dimvn+'_'+attrn):
                CFtu = Tunit + 's'
                foundCFunits = True
                break
            Tunitsguess.append(dimvn+'_'+attrn)
            attrn = Tunit
            if searchInlist(varatrs,dimvn+'_'+attrn):
                CFtu = Tunit + 's'
                foundCFunits = True
                break
            Tunitsguess.append(dimvn+'_'+attrn)
            attrn = Tunit + 's'
            if searchInlist(varatrs,dimvn+'_'+attrn):
                CFtu = Tunit + 's'
                foundCFunits = True
                break
            Tunitsguess.append(dimvn+'_'+attrn)

        if not foundCFunits:
            print errormsg
            print '  ' + fname + ": time-variable with units as 'timesteps' does " + \
              'not have a prepared way:', Tunitsguess, 'to find its units !!'
            print "    variables' attributes:", varatrs
            quit(-1)

        CFtv = otval.getncattr(dimvn+'_'+attrn)
        newTS = [CFtu] + tunits.split(' ')[1:]
        newTunits = ' '.join(newTS)
        newTvals = otval[:]*CFtv
    else:
        newTunits = tunits
        newTvals = otval[:]

    return newTunits, newTvals

def coincident_CFtimes(tvalB, tunitA, tunitB):
    """ Function to make coincident times for two different sets of CFtimes
    tvalB= time values B
    tunitA= time units times A to which we want to make coincidence
    tunitB= time units times B
    >>> coincident_CFtimes(np.arange(10),'seconds since 1949-12-01 00:00:00',
      'hours since 1949-12-01 00:00:00')
    [     0.   3600.   7200.  10800.  14400.  18000.  21600.  25200.  28800.  32400.]
    >>> coincident_CFtimes(np.arange(10),'seconds since 1949-12-01 00:00:00',
      'hours since 1979-12-01 00:00:00')
    [  9.46684800e+08   9.46688400e+08   9.46692000e+08   9.46695600e+08
       9.46699200e+08   9.46702800e+08   9.46706400e+08   9.46710000e+08
       9.46713600e+08   9.46717200e+08]
    """
    import datetime as dt
    fname = 'coincident_CFtimes'

    trefA = tunitA.split(' ')[2] + ' ' + tunitA.split(' ')[3]
    trefB = tunitB.split(' ')[2] + ' ' + tunitB.split(' ')[3]
    tuA = tunitA.split(' ')[0]
    tuB = tunitB.split(' ')[0]

    if tuA != tuB:
        if tuA == 'microseconds':
            if tuB == 'microseconds':
                tB = tvalB*1.
            elif tuB == 'seconds':
                tB = tvalB*10.e6
            elif tuB == 'minutes':
                tB = tvalB*60.*10.e6
            elif tuB == 'hours':
                tB = tvalB*3600.*10.e6
            elif tuB == 'days':
                tB = tvalB*3600.*24.*10.e6
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'seconds':
            if tuB == 'microseconds':
                tB = tvalB/10.e6
            elif tuB == 'seconds':
                tB = tvalB*1.
            elif tuB == 'minutes':
                tB = tvalB*60.
            elif tuB == 'hours':
                tB = tvalB*3600.
            elif tuB == 'days':
                tB = tvalB*3600.*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'minutes':
            if tuB == 'microseconds':
                tB = tvalB/(60.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/60.
            elif tuB == 'minutes':
                tB = tvalB*1.
            elif tuB == 'hours':
                tB = tvalB*60.
            elif tuB == 'days':
                tB = tvalB*60.*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'hours':
            if tuB == 'microseconds':
                tB = tvalB/(3600.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/3600.
            elif tuB == 'minutes':
                tB = tvalB/60.
            elif tuB == 'hours':
                tB = tvalB*1.
            elif tuB == 'days':
                tB = tvalB*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'days':
            if tuB == 'microseconds':
                tB = tvalB/(24.*3600.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/(24.*3600.)
            elif tuB == 'minutes':
                tB = tvalB/(24.*60.)
            elif tuB == 'hours':
                tB = tvalB/24.
            elif tuB == 'days':
                tB = tvalB*1.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        else:
            print errormsg
            print '  ' + fname + ": time untis: '" + tuA + "' not ready !!"
            quit(-1)
    else:
        tB = tvalB*1.

    if trefA != trefB:
        trefTA = dt.datetime.strptime(trefA, '%Y-%m-%d %H:%M:%S')
        trefTB = dt.datetime.strptime(trefB, '%Y-%m-%d %H:%M:%S')

        difft = trefTB - trefTA
        if searchInlist(difft.keys(), 'total_seconds'):
            diffv = difft.total_seconds*10.e6
        else:
            diffv = difft.days*24.*3600.*10.e6 + difft.seconds*10.e6 + difft.microseconds
        print '  ' + fname + ': different reference refA:',trefTA,'refB',trefTB
        print '    difference:',difft,':',diffv,'microseconds'

        if tuA == 'microseconds':
            tB = tB + diffv
        elif tuA == 'seconds':
            tB = tB + diffv/10.e6
        elif tuA == 'minutes':
            tB = tB + diffv/(60.*10.e6)
        elif tuA == 'hours':
            tB = tB + diffv/(3600.*10.e6)
        elif tuA == 'dayss':
            tB = tB + diffv/(24.*3600.*10.e6)
        else:
            print errormsg
            print '  ' + fname + ": time untis: '" + tuA + "' not ready !!"
            quit(-1)

    return tB

def wdismean(pos,val4):
    """ Function to compute the mean value weighted to its 4 distances
      pos= x,y position within the 'square'
      val4= values at the four vertexs (2,2)
    >>>position = [0.005,0.005]
    >>>val4 = np.zeros((2,2), dtype=np.float)
    >>>val4 = np.arange(4).reshape(2,2)
    0.035707955234
    """
    fname = 'wdismean'

    dist = np.zeros((2,2), dtype=np.float)    
    dist[0,0] = np.sqrt(pos[0]*pos[0]+pos[1]*pos[1])
    dist[0,1] = np.sqrt(pos[0]*pos[0]+(1.-pos[1])*(1.-pos[1]))
    dist[1,0] = np.sqrt((1.-pos[0])*(1.-pos[0])+pos[1]*pos[1])
    dist[1,1] = np.sqrt((1.-pos[0])*(1.-pos[0])+(1.-pos[1])*(1.-pos[1]))

    if np.min(dist) == 0.:
        pos0 = index_mat(dist, 0.)
        dist[:,:] = 0.
        posmean = val4[pos0[0], pos0[1]]
    else:
        totdist = np.sum(1./dist)
        posmean = np.sum(val4.flatten()/dist.flatten())/totdist

    return posmean

def read_ASCIIlist(filen):
    """ Function to build a list from an ASCII lines file
      filen= name of the ASCII file
    """
    import os
    fname = 'read_ASCIIlist'

    if not os.path.isfile(filen):
        print errormsg
        print '  ' + fname + ":  ASCII types file '" + filen + "' does not exist !!"
        quit(-1)

    of = open(filen, 'r')
    filevals = []
    for linef in of:
        filevals.append(linef.replace('\n',''))
    of.close()

    return filevals

def radial_points(angle,dist):
    """ Function to provide a number of grid point positions for a given angle
      angle= desired angle (rad)
      dist= number of grid points
    >>> radial_points(0.5*np.pi,5)
    [[  6.12323400e-17   1.00000000e+00]
     [  1.22464680e-16   2.00000000e+00]
     [  1.83697020e-16   3.00000000e+00]
     [  2.44929360e-16   4.00000000e+00]
     [  3.06161700e-16   5.00000000e+00]]
    """
    fname = 'radial_points'
    radpos = np.zeros((dist,2), dtype=np.float)

    for ip in range(dist):
        radpos[ip,0] = (ip+1.)*np.cos(angle)
        radpos[ip,1] = (ip+1.)*np.sin(angle)

    return radpos

def read_SQradii(filename='SQradii.dat', Npt=-1, maxradii=None):
    """ Function to read the outcome of the function `squared_radial'
      filename= Name of the outcome file of the function 
      Npt= Number of points on each grid
      maxradii= allowed maximum radii
      'SQradii.dat': file with the radii and paris of integers after ran squared_radial(1000)
    """
    fname = 'read_SQradii'

    if not os.path.isfile(filename):
        print errormsg
        print '  ' + fname + ": file '" + filename + "' not found!!"
        quit(-1)

    infile = open(filename, 'r')

    gridradii = {}
    Nradii = {}
    radii = []
    for line in infile:
        values = values_line(line, ' ', ['[', ']'])
        rad = np.float(values[0])
# Limited by a given radii
        if maxradii is not None and rad > maxradii: break
        Nrad = int(values[2])
        couples = []
        Nradgood = 0
        if Nrad > 1:
           Ncouples = 0
           for ic in range(Nrad):
               ix = int(values[3 + ic*2])
               iy = int(values[3 + ic*2 + 1])
               if ix <= Npt and iy <= Npt:
                   couples.append(np.array([ix,iy]))
                   Nradgood = Nradgood + 1
               elif ix > Npt and iy > Npt: break
        else:
             ix = int(values[3])
             iy = int(values[4])
             if ix <= Npt and iy <= Npt:
                 couples.append(np.array([ix,iy]))
                 Nradgood = Nradgood + 1
             elif ix > Npt and iy > Npt: break

        if Nradgood > 0:
            Nradii[rad] = Nradgood
            finalcouples = np.zeros((Nradgood,2), dtype=int)
            for ic in range(Nradgood):
                finalcouples[ic,:] = couples[ic]
            gridradii[rad] = finalcouples

#    for rad in sorted(gridradii.keys()):
#        print rad, gridradii[rad]

    return gridradii

def grid_combinations(x,y):
    """ Function to provide all the possible grid points combination for a given pair of values
      x,y= pair of grid points
    >>>grid_combinations(1,2)
    [[1, 2], [-1, 2], [-1, -2], [1, -2], [2, 1], [-2, 1], [-2, -1], [2, -1]]
    """
    fname = 'grid_combinations'

    gridcomb = []
    gridcomb.append([x,y])
    if x != 0: gridcomb.append([-x,y])
    if x != 0 and y != 0: gridcomb.append([-x,-y])
    if y != 0: gridcomb.append([x,-y])

    if x != y:
        gridcomb.append([y,x])
        if y != 0: gridcomb.append([-y,x])
        if x != 0 and y != 0: gridcomb.append([-y,-x])
        if x != 0: gridcomb.append([y,-x])

    return gridcomb

def radii_points(xpos,ypos,Lrad,Nang,dx,dy):
    """ Function to provide the grid points for radial cross sections, by angle and radii and `squared' radii
      xpos= x position of the center
      ypos= y position of the center
      Lrad= length of the maximum radi in grid points
      Nang= number of equivalent angles
      dx= x size of the domain of values
      dy= y size of the domain of values
      >>> radpos, SQradpos = radii_points(12,12,1,8,25,25)
      radpos:
      [[[ 13.          12.        ]]
       [[ 12.70710678  12.70710678]]
       [[ 12.          13.        ]]
       [[ 11.29289322  12.70710678]]
       [[ 11.          12.        ]]
       [[ 11.29289322  11.29289322]]
       [[ 12.          11.        ]]
       [[ 12.70710678  11.29289322]]]
      SQradpos:
      {1.0: [[13, 12], [11, 12], [12, 13], [12, 11]], 1.41421356237: [[13, 13], [11, 13], [11, 11], [13, 11]]}
    """
    fname = 'radii_points'

    radiipos = np.zeros((Nang, Lrad, 2), dtype = np.float)
    SQradiipos = {}

# Getting the range of radii:
    pairsSQradii = read_SQradii(Npt=Lrad)
    SQradii = pairsSQradii.keys()
    Nradii = len(SQradii)

# Angle loop
    for ia in range(Nang):
        angle = 2.*np.pi*ia/Nang
        posangle = np.zeros((Lrad,2), dtype=np.float)

# Points at that given angle
        pangle = radial_points(angle,Lrad)
        posangle[:,0] = pangle[:,0] + xpos
        posangle[:,1] = pangle[:,1] + ypos

        for ip in range(Lrad):
            iipos = int(posangle[ip,0])
            jjpos = int(posangle[ip,1])

# Creation of a matrix with all the grid points at each time-step
            if iipos >= 0 and iipos < dx-1 and jjpos >= 0 and jjpos < dy-1:
                radiipos[ia,ip,0] = posangle[ip,0]
                radiipos[ia,ip,1] = posangle[ip,1]

# SQ radii values

# Radii loop (avoiding 0)
    pairswithin = {}
    for ir in range(1,Nradii):
        pairs = pairsSQradii[SQradii[ir]]

# pairs loop
        Npairs = len(pairs.flatten())/2
        pairsw = []
        for ip in range(Npairs):
            if Npairs == 0: 
                break
            else:
                allpairs = grid_combinations(pairs[ip,0],pairs[ip,1])                
            for iap in range(len(allpairs)):
                ppos = allpairs[iap]
                iipos = xpos + ppos[0]
                jjpos = ypos + ppos[1]

# Creation of a matrix with all the grid points at each time-step
                if iipos >= 0 and iipos < dx and jjpos >= 0 and jjpos < dy:
                    pairsw.append([iipos,jjpos])

        SQradiipos[SQradii[ir]] = pairsw

    return radiipos, SQradiipos

def hor_weight_int(SWval, SEval, NWval, NEval, xpos, ypos):
    """ Function to weighted by distance interpolate a horizontal value from it closest 4 neighbourgs 
      field= a 4 points representing the environment of a given point
      xpos, ypos: position to which one want to interpolate (relative to 0,0 at the corner SW)
    >>> hor_weight_int(1., 1., 1., 2., 0.75, 0.75)
    1.44888128193
    """
    fname = 'hor_weight_int'

    vals = np.array([SWval, SEval, NWval, NEval])
    print vals
    if xpos > 1.: 
        print errormsg
        print '  ' + fname + ': Wrong position to interpolate! (',xpos,',',ypos,     \
          ') must be within (1,1) !!'
        quit(-1)

    vertexs = np.zeros((4,2), dtype=np.float) 
    vertexs[0,0] = 0.
    vertexs[0,1] = 0.
    vertexs[1,0] = 1.
    vertexs[1,1] = 0.
    vertexs[2,0] = 0.
    vertexs[2,1] = 1.
    vertexs[3,0] = 1.
    vertexs[3,1] = 1.
    print vertexs

    dist = np.sqrt((vertexs[:,0]-xpos)**2 + (vertexs[:,1]-ypos)**2)
    print dist
    done = False
    for id in range(4):
        if dist[id] == 0.: 
            intval = vals[id]
            done = True

    if not done: intval = np.sum(vals/dist)/np.sum(1./dist)

    return intval

def rmNOnum(string):
    """ Removing from a string all that characters which are not numbers
    # From: http://stackoverflow.com/questions/4289331/python-extract-numbers-from-a-string
    """
    fname = 'rmNOnum'

    newstr = str(re.findall("[-+]?\d+[\.]?\d*", string)[0])

    return newstr

def values_fortran_fmt(lin,fFMT):
    """ Function to give back the values of an ASCII line according to its fortran printing format
      lin= ASCII line
      fFMT= list with the fortran FORMAT formats
    forline = 'Natchitoches (RGNL)        1 11 0011  ( 31.733, -93.100) (  28, 157) ( 31.761, -93.113)   41.2 meters'
    formats = ['A26', 'I2', 'I3', 'A6', 'A2', 'F7.3', 'A1', 'F8.3', 'A3', 'I4', 'A1', 'I4',
      'A3', 'F7.3', 'A1', 'F8.3', 'A2', 'F6.1', 'A7']
    >>> values_fortran_fmt(forline, formats)
    ['Natchitoches (RGNL)        ', 1, 11, ' 0011  ', ' ( ', 31.733, ', ', -93.1, ') ( ', 28, ', ', 157, ')
      ( ', 31.761, ', ', -93.113, ')  ', 41.2, ' meters']
    """
    fname = 'values_fortran_fmt'

    afmts = ['A', 'D', 'F', 'I']

    if lin == 'h':
        print fname + '_____________________________________________________________'
        print values_fortran_fmt.__doc__
        quit()

    fvalues = []
    ichar=0
    ival = 0
    for ft in fFMT:
        Lft = len(ft)
        if ft[0:1] == 'A' or ft[0:1] == 'a':
            Lfmt = int(ft[1:Lft+1])
            fvalues.append(lin[ichar:ichar+Lfmt+1])
            ichar = ichar + Lfmt
        elif ft[0:1] == 'F' or ft[0:1] == 'f':
            if ft.find('.') != -1:
                Lft = len(ft.split('.')[0])
            Lfmt = int(ft[1:Lft])
            fvalues.append(np.float(rmNOnum(lin[ichar:ichar+Lfmt+1])))
            ichar = ichar + Lfmt
        elif ft[0:1] == 'D' or ft[0:1] == 'd':
            if ft.find('.') != -1:
                Lft = len(ft.split('.')[0])
            Lfmt = int(ft[1:Lft])
            fvalues.append(np.float64(rmNOnum(lin[ichar:ichar+Lfmt+1])))
            ichar = ichar + Lfmt
        elif ft[0:1] == 'I' or ft[0:1] == 'i':
            Lfmt = int(ft[1:Lft+1])
            fvalues.append(int(rmNOnum(lin[ichar:ichar+Lfmt+1])))
            ichar = ichar + Lfmt
        elif ft.find('X') != -1 or ft.find('x') != -1:
            print '    ' + fname + ': skipping space'
            ichar = ichar + int(rmNOnum(ft))
        else:
            print errormsg
            print '  ' + fname + ": format '" + ft[0:1] + "' not ready!!"
            print '    Available formats:',afmts
            quit(-1)

        ival = ival + 1

    return fvalues

def reduce_last_spaces(string):
    """ Function to reduce the last right spaces from a string
      string= string to remove the spaces at the righ side of the string
    >>> reduce_last_spaces('Hola Lluis      ')
    'Hola Lluis'
    """
    fname = 'reduce_last_spaces'

    Lstring = len(string)
    if Lstring < 1:
        print errormsg
        print '  ' + fname + ": String '" + string + "' too short !!"
        quit(-1)

    firstspace = -1
    for istr in range(Lstring-1,0,-1):
        if string[istr:istr+1] == ' ':
            firstspace = istr
        else:
            break

    if firstspace == -1:
        firstspace = Lstring + 1

    newstr = string[0:firstspace]

    return newstr

def squared_radial(Npt):
    """ Function to provide the series of radii as composite of pairs (x,y) of gid cells
      Npt= largest amount of grid points on x and y directions
    >>> squared_radial(5)
    [[0.0, 0, 0], [1.0, 1, 0], [1.4142135623730951, 1, 1], [2.0, 2, 0], [2.2360679774997898, 2, 1], [2.8284271247461903, 2, 2], [3.0, 3, 0], [3.1622776601683795, 3, 1], [3.6055512754639891, 3, 2], [4.0, 4, 0], [4.1231056256176606, 4, 1], [4.2426406871192848, 3, 3], [4.4721359549995796, 4, 2], [5.0, array([4, 3]), array([5, 0])], [5.0990195135927845, 5, 1], [5.3851648071345037, 5, 2], [5.6568542494923806, 4, 4], [5.8309518948453007, 5, 3], [6.4031242374328485, 5, 4], [7.0710678118654755, 5, 5]]
    """
    fname = 'squared_radial'
    if Npt == 'h':
        print fname + '_____________________________________________________________'
        print squared_radial.__doc__
        quit()

    radii = []
    gridradii = {}
    singradii = []
    Nradii = {}

# Computing all radii
##
    for i in range(Npt+1):
        if np.mod(i,100) == 0: print 'done: ',i
        for j in range(i+1):
#            ir = np.float(i)
#            jr = np.float(j)
            ir = np.float64(i)
            jr = np.float64(j)
            rad = np.sqrt(ir*ir + jr*jr)
            if not searchInlist(singradii, rad):
                singradii.append(rad)
                gridradii[rad] = np.array([i,j], dtype=int)
                Nradii[rad] = 1
            else:
#                print warnmsg
#                print '  ' + fname + ': repeated radii',rad,'!!'
#                print '    Previous values:', gridradii[rad]

                oldvalues = gridradii[rad]
                Nradii[rad] = Nradii[rad] + 1
                newvalues = np.zeros((Nradii[rad],2), dtype=int)
                if Nradii[rad] == 2:
                    newvalues[0,:] = oldvalues
                    Nstart = 1
                else:
                    Nstart = 0
                for Nr in range(Nstart,Nradii[rad]-1):
                    newvalues[Nr,:] = oldvalues[Nr,:]
                newvalues[Nradii[rad]-1,:] = np.array([i,j], dtype=int)
                gridradii[rad] = newvalues

# Sorting values
##
## Only required to downwrite the output file
#    radiif = open('SQradii.dat', 'w')
#    radii = []
#    prevrad = 0.
#    for rad in sorted(gridradii.keys()):
#        dradii = rad - prevrad
## Check fo repeated values
#        radii.append([rad, gridradii[rad][0], gridradii[rad][1]])
#        radiif.write(str(rad) + ' ' + str(dradii) + ' ' + str(Nradii[rad]) + ' [ '+  \
#          numVector_String(gridradii[rad].flatten(), ' ') + ' ] \n')
#        prevrad = rad.copy()

#    radiif.close()
    return gridradii

def fillvalue_kind(vartype, fillval0):
    """ Function to provide the fiven fill_Value for a kind of variable
      [vartype]= type of the variable
      [fillval0]= value to take as fill value, 'std' for the standard value
           Float = 1.e20
           Character = '-'
           Integer = -99999
           Integer16 = -99999
           Float64 = 1.e20
           Integer32 = -99999
    """
    fname = 'fillvalue_kind'
    if vartype == 'h':
        print fname + '_____________________________________________________________'
        print fillvalue_kind.__doc__
        quit()

    if vartype == type('c'):
        if fillval0 == 'std':
            fillval = fillvalueC
        else:
            fillval = fillval0
    elif vartype == type(int(1)):
        if fillval0 == 'std':
            fillval = fillValueI
        else:
            fillval = int(fillval0)
    elif vartype == type(np.int16(1)):
        if fillval0 == 'std':
            fillval = np.int(9999999)
        else:
            fillval = np.int16(fillval0)
    elif vartype == type(np.int32(1)):
        if fillval0 == 'std':
            fillval = np.int32(fillValueI)
        else:
            fillval = np.int32(fillval0)
    elif vartype == type(np.float(1.)):
        if fillval0 == 'std':
            fillval = np.float(fillValueF)
        else:
            fillval = np.float(fillval0)
    elif vartype == type(np.float32(1.)):
        if fillval0 == 'std':
            fillval = np.float32(fillValueF)
        else:
            fillval = np.float32(fillval0)
    elif vartype == type(np.float64(1.)):
        if fillval0 == 'std':
            fillval = np.float64(fillValueF)
        else:
            fillval = np.float64(fillval0)
    else:
        print errormsg
        print '  ' + fname + ': variable type', vartype, 'not ready !!'
        quit(-1)

    return fillval

def varval_ind(var, ind):
    """ Function to provide a value from a variable providing a value for each index
      var= variable
      ind= list of indices for each dimension of the variable
    """
    fname = 'varval_ind'
    if len(var.shape) != len(ind):
        print errormsg
        print '  ' + fname + ': different shape:', var.shape,'and indices:', ind, '!!'
        quit(-1)

    varslice=[]
    for iv in ind:
        varslice.append(iv)

    val = varval_ind[slice(varslice)]

    return val

def CoarselonlatFind(ilon, ilat, lonv, latv, per):
    """ Function to search a given value from a coarser version of the data
      ilon, ilat= original 2D matrices with the longitudes and the latitudes
      lonv, latv= longitude and latitude to find
      per= period (as fraction over 1) of the fractions of the original grid to use to explore
      >>> npt=100
      >>> lonval0 = np.arange(0.,npt*1.,1.)
      >>> latval0 = np.arange(0.,npt*1.,1.)
      >>> lonval = np.zeros((npt,npt), dtype=np.float)
      >>> latval = np.zeros((npt,npt), dtype=np.float)

      >>> for i in range(npt):
      >>>     lonval[:,i] = lonval0[i]
      >>>     latval[i,:] = latval0[i]
      >>> CoarselonlatFind(lonval, latval, 5.25, 5.25, .1)
      (array([5, 5]), 0.35355339059327379)
    """
    fname = 'CoarselonlatFind'

    dx = ilon.shape[1]
    dy = ilon.shape[0]

    nlon = np.min(ilon)
    xlon = np.max(ilon)
    nlat = np.min(ilat)
    xlat = np.max(ilat)

    if lonv < nlon or lonv > xlon:
        print errormsg
        print '  ' + fname + ': longitude outside data range!!'
        print '    given value:', lonv,'outside [',nlon,',',xlon,']'
        quit(-1) 
    if latv < nlat or latv > xlat:
        print errormsg
        print '  ' + fname + ': latitude outside data range!!'
        print '    given value:', latv,'outside [',nlat,',',xlat,']'
        quit(-1) 

    fracx = int(dx*per)
    fracy = int(dy*per)

    fraclon = ilon[::fracy,::fracx]
    fraclat = ilat[::fracy,::fracx]
    fracdx = fraclon.shape[1]
    fracdy = fraclon.shape[0]

#    print 'fraclon _______'
#    print fraclon

#    print 'fraclat _______'
#    print fraclat

# Fraction point
    difffraclonlat = np.sqrt((fraclon-lonv)**2. + (fraclat-latv)**2.)
    mindifffracLl = np.min(difffraclonlat)
    ilatlonfrac = index_mat(difffraclonlat, mindifffracLl)

#    print 'mindifffracLl:', mindifffracLl, 'ilatlonfrac:', ilatlonfrac
#    print 'frac lon, lat:', fraclon[ilatlonfrac[0],ilatlonfrac[1]], ',',             \
#      fraclat[ilatlonfrac[0],ilatlonfrac[1]]
#    print 'values lon, lat:', lonv, latv
      
# Providing fraction range
    if fraclon[ilatlonfrac[0],ilatlonfrac[1]] >= lonv and                            \
      fraclat[ilatlonfrac[0],ilatlonfrac[1]] >= latv:
#        ifracbeg = [ilatlonfrac[0]-1, ilatlonfrac[1]-1]
#        ifracend = [ilatlonfrac[0], ilatlonfrac[1]]
        if ilatlonfrac[0] > 0: 
            iybeg = (ilatlonfrac[0]-1)*fracy
            iyend = ilatlonfrac[0]*fracy+1
        else:
            iybeg = 0
            iyend = fracy+1
        if ilatlonfrac[1] > 0: 
            ixbeg = (ilatlonfrac[1]-1)*fracx
            ixend = ilatlonfrac[1]*fracx+1
        else:
            ixbeg = 0
            ixend = fracx+1
    elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] < lonv and                           \
      fraclat[ilatlonfrac[0],ilatlonfrac[1]] >= latv:
#        ifracbeg = [ilatlonfrac[0]-1, ilatlonfrac[1]]
#        ifracend = [ilatlonfrac[0], ilatlonfrac[1]+1]
        if ilatlonfrac[0] > 0: 
            iybeg = (ilatlonfrac[0]-1)*fracy
            iyend = ilatlonfrac[0]*fracy+1
        else:
            iybeg = 0
            iyend = fracy+1
        if ilatlonfrac[1] < fracdx:
            if ilatlonfrac[1] != 0:
                ixbeg = (ilatlonfrac[1]-1)*fracx
                ixend = ilatlonfrac[1]*fracx+1
            else:
                ixbeg = 0
                ixend = fracx+1
        else:
            ixbeg = fracdx*fracx
            ixend = dx+1
    elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] < lonv and                           \
      fraclat[ilatlonfrac[0],ilatlonfrac[1]] < latv:
#        ifracbeg = [ilatlonfrac[0], ilatlonfrac[1]]
#        ifracend = [ilatlonfrac[0]+1, ilatlonfrac[1]+1]
        if ilatlonfrac[0] < fracdy: 
            if ilatlonfrac[0] != 0:
                iybeg = (ilatlonfrac[0]-1)*fracy
                iyend = ilatlonfrac[0]*fracy+1
            else:
                iybeg = 0
                iyend = fracy+1
        else:
            iybeg = fracdy*fracy
            iyend = dy+1
        if ilatlonfrac[1] < fracdx: 
            if ilatlonfrac[1] != 0:
                ixbeg = (ilatlonfrac[1]-1)*fracx
                ixend = ilatlonfrac[1]*fracx+1
            else:
                ixbeg = 0
                ixend = fracx+1
        else:
            ixbeg = fracdx*fracx
            ixend = dx+1
    elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] >= lonv and                          \
      fraclat[ilatlonfrac[0],ilatlonfrac[1]] < latv:
#        ifracbeg = [ilatlonfrac[0], ilatlonfrac[1]-1]
#        ifracend = [ilatlonfrac[0]+1, ilatlonfrac[1]]
        if ilatlonfrac[0] < fracdy: 
            if ilatlonfrac[0] != 0:
                iybeg = (ilatlonfrac[0]-1)*fracy
                iyend = ilatlonfrac[0]*fracy+1
            else:
                iybeg = 0
                iyend = fracy+1
        else:
            iybeg = fracdy*fracy
            iyend = dy+1
        if ilatlonfrac[1] > 0: 
            ixbeg = (ilatlonfrac[1]-1)*fracx
            ixend = ilatlonfrac[1]*fracx+1
        else:
            ixbeg = 0
            ixend = fracx+1

#    ibeg = [iybeg, ixbeg]
#    iend = [iyend, ixend]
#    print 'find window; beginning', ibeg, 'end:', iend
    lon = ilon[iybeg:iyend,ixbeg:ixend]
    lat = ilat[iybeg:iyend,ixbeg:ixend]

#    print 'lon _______'
#    print lon
#    print 'lat _______'
#    print lat

# Find point
    difflonlat = np.sqrt((lon-lonv)**2. + (lat-latv)**2.)
    mindiffLl = np.min(difflonlat)
    ilatlon = index_mat(difflonlat, mindiffLl)

    ilatlon[0] = ilatlon[0] + iybeg
    ilatlon[1] = ilatlon[1] + ixbeg

#    print 'mindiffLl:', mindiffLl, 'ilatlon:', ilatlon
#    print 'lon, lat:', lon[ilatlon[0],ilatlon[1]], ',', lat[ilatlon[0],ilatlon[1]]
#    quit()

    return ilatlon, mindiffLl

def CoarselonlatFindAll(onc, ilon, ilat, longvs, latvs, per, frac, out):
    """ Function to search all values from a coarser version of the data
      onc= netCDF object from an existing file
      ilon, ilat= original 2D matrices with the longitudes and the latitudes
      lonv, latv= longitude and latitude to find
      per= period (as fraction over 1) of the fractions of the original grid to use to explore
      frac= frequency of points at which syncronize file with calculations
      out= True/False if outcome is required
      >>> npt=100
      >>> lonval0 = np.arange(0.,npt*1.,1.)
      >>> latval0 = np.arange(0.,npt*1.,1.)
      >>> lonval = np.zeros((npt,npt), dtype=np.float)
      >>> latval = np.zeros((npt,npt), dtype=np.float)
      >>> lonvalues = np.arange(0.25,10.,0.25)
      >>> latvalues = np.arange(0.25,10.,0.25)

      >>> for i in range(npt):
      >>>     lonval[:,i] = lonval0[i]
      >>>     latval[i,:] = latval0[i]
      >>> CoarselonlatFindAll(onewnc, lonval, latval, lovalues, latvalues, .1, 100)
      (array([5, 5]), 0.35355339059327379)
    """
    fname = 'CoarselonlatFindAll'

    dx = ilon.shape[1]
    dy = ilon.shape[0]

    nlon = np.min(ilon)
    xlon = np.max(ilon)
    nlat = np.min(ilat)
    xlat = np.max(ilat)

    Nallpts = len(longvs)

    fracx = int(dx*per)
    fracy = int(dy*per)

    fraclon = ilon[::fracy,::fracx]
    fraclat = ilat[::fracy,::fracx]
    fracdx = fraclon.shape[1]
    fracdy = fraclon.shape[0]

#    print 'fraclon _______'
#    print fraclon

#    print 'fraclat _______'
#    print fraclat

    if out:
        ilatlon = np.zeros((2,Nallpts), dtype=int)
        mindiffLl = np.zeros((Nallpts), dtype=np.float)

    iptpos=0
    for iv in range(Nallpts):
        lonv = longvs[iv]
        latv = latvs[iv]

        if lonv < nlon or lonv > xlon:
            print errormsg
            print '  ' + fname + ': longitude outside data range!!'
            print '    given value:', lonv,'outside [',nlon,',',xlon,']'
            quit(-1) 
        if latv < nlat or latv > xlat:
            print errormsg
            print '  ' + fname + ': latitude outside data range!!'
            print '    given value:', latv,'outside [',nlat,',',xlat,']'
            quit(-1) 

# Fraction point
        difffraclonlat = np.sqrt((fraclon-lonv)**2. + (fraclat-latv)**2.)
        mindifffracLl = np.min(difffraclonlat)
        ilatlonfrac = index_mat(difffraclonlat, mindifffracLl)

#        print 'values lon, lat:', lonv, latv
#        print 'mindifffracLl:', mindifffracLl, 'ilatlonfrac:', ilatlonfrac
#        print 'frac lon, lat:', fraclon[ilatlonfrac[0],ilatlonfrac[1]], ',',         \
#          fraclat[ilatlonfrac[0],ilatlonfrac[1]]
      
# Providing fraction range
        if fraclon[ilatlonfrac[0],ilatlonfrac[1]] >= lonv and                        \
          fraclat[ilatlonfrac[0],ilatlonfrac[1]] >= latv:
#            ifracbeg = [ilatlonfrac[0]-1, ilatlonfrac[1]-1]
#            ifracend = [ilatlonfrac[0], ilatlonfrac[1]]
            if ilatlonfrac[0] > 0: 
                iybeg = (ilatlonfrac[0]-1)*fracy
                iyend = ilatlonfrac[0]*fracy+1
            else:
                iybeg = 0
                iyend = fracy+1
            if ilatlonfrac[1] > 0: 
                ixbeg = (ilatlonfrac[1]-1)*fracx
                ixend = ilatlonfrac[1]*fracx+1
            else:
                ixbeg = 0
                ixend = fracx+1
        elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] < lonv and                       \
          fraclat[ilatlonfrac[0],ilatlonfrac[1]] >= latv:
#            ifracbeg = [ilatlonfrac[0]-1, ilatlonfrac[1]]
#            ifracend = [ilatlonfrac[0], ilatlonfrac[1]+1]
            if ilatlonfrac[0] > 0: 
                iybeg = (ilatlonfrac[0]-1)*fracy
                iyend = ilatlonfrac[0]*fracy+1
            else:
                iybeg = 0
                iyend = fracy+1
            if ilatlonfrac[1] < fracdx:
                if ilatlonfrac[1] != 0:
                    ixbeg = (ilatlonfrac[1]-1)*fracx
                    ixend = ilatlonfrac[1]*fracx+1
                else:
                    ixbeg = 0
                    ixend = fracx+1
            else:
                ixbeg = fracdx*fracx
                ixend = dx+1
        elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] < lonv and                       \
          fraclat[ilatlonfrac[0],ilatlonfrac[1]] < latv:
#            ifracbeg = [ilatlonfrac[0], ilatlonfrac[1]]
#            ifracend = [ilatlonfrac[0]+1, ilatlonfrac[1]+1]
            if ilatlonfrac[0] < fracdy: 
                if ilatlonfrac[0] != 0:
                    iybeg = (ilatlonfrac[0]-1)*fracy
                    iyend = ilatlonfrac[0]*fracy+1
                else:
                    iybeg = 0
                    iyend = fracy+1
            else:
                iybeg = fracdy*fracy
                iyend = dy+1
            if ilatlonfrac[1] < fracdx: 
                if ilatlonfrac[1] != 0:
                    ixbeg = (ilatlonfrac[1]-1)*fracx
                    ixend = ilatlonfrac[1]*fracx+1
                else:
                    ixbeg = 0
                    ixend = fracx+1
            else:
                ixbeg = fracdx*fracx
                ixend = dx+1
        elif fraclon[ilatlonfrac[0],ilatlonfrac[1]] >= lonv and                      \
          fraclat[ilatlonfrac[0],ilatlonfrac[1]] < latv:
#            ifracbeg = [ilatlonfrac[0], ilatlonfrac[1]-1]
#            ifracend = [ilatlonfrac[0]+1, ilatlonfrac[1]]
            if ilatlonfrac[0] < fracdy: 
                if ilatlonfrac[0] != 0:
                    iybeg = (ilatlonfrac[0]-1)*fracy
                    iyend = ilatlonfrac[0]*fracy+1
                else:
                    iybeg = 0
                    iyend = fracy+1
            else:
                iybeg = fracdy*fracy
                iyend = dy+1
            if ilatlonfrac[1] > 0: 
                ixbeg = (ilatlonfrac[1]-1)*fracx
                ixend = ilatlonfrac[1]*fracx+1
            else:
                ixbeg = 0
                ixend = fracx+1
    
#        ibeg = [iybeg, ixbeg]
#        iend = [iyend, ixend]
#        print 'find window; beginning', ibeg, 'end:', iend
        lon = ilon[iybeg:iyend,ixbeg:ixend]
        lat = ilat[iybeg:iyend,ixbeg:ixend]
#        print 'Looking within _______'
#        print 'lon:',lon[0,0],',',lon[-1,-1]
#        print 'lat:',lat[0,0],',',lat[-1,-1]
    
#        print 'lon _______'
#        print lon
#        print 'lat _______'
#        print lat
    
# Find point
        difflonlat = np.sqrt((lon-lonv)**2. + (lat-latv)**2.)
        if out:
            mindiffLl[iv] = np.min(difflonlat)
            ilatlon[:,iv] = index_mat(difflonlat, mindiffLl)
            ilatlon[0,iv] = ilatlon[0,iv] + iybeg
            ilatlon[1,iv] = ilatlon[1,iv] + ixbeg
        else:
            mindiffLl = np.min(difflonlat)
            ilatlon = index_mat(difflonlat, mindiffLl)
            ilatlon[0] = ilatlon[0] + iybeg
            ilatlon[1] = ilatlon[1] + ixbeg

#        print 'mindiffLl:', mindiffLl, 'ilatlon:', ilatlon
#        print 'lon, lat:', lon[ilatlon[0],ilatlon[1]], ',', lat[ilatlon[0],ilatlon[1]]
#        quit()

#        if mindiffLl == 0. and type(newvar[ilatlon[0],ilatlon[1]]) == type(amsk): 
#            percendone(iv,Ninpts,0.5,'done:')
        if mindiffLl == 0.: 
            iptpos = iptpos + 1
# Speeding it up!
#            if mindiffLl > mindiff:
#                print errormsg
#                print '  ' + fname + ': for point #', iv,'lon,lat in ' +             \
#                  'incomplet map:', lonvs[iv], ',', latvs[iv], 'there is ' +         \
#                  'not a set of lon,lat in the completed map closer than: ',         \
#                  mindiff, '!!'
#                print '    minimum difference:', mindiffLl
#                quit(-1)

# Speeding it up!
#            if ilatlon[0] >= 0 and ilatlon[1] >= 0:
#                newvar[ilatlon[0],ilatlon[1]] = ovar[iv]
#                newvarin[ilatlon[0],ilatlon[1]] = iv
#                newvarinpt[iv] = 1
#                newvarindiff[iv] = mindiffLl
            newvar[ilatlon[0],ilatlon[1]] = ovar[iv]
            newvarin[ilatlon[0],ilatlon[1]] = iv
            newvarinpt[iv] = 1
            newvarindiff[iv] = mindiffLl

#                print 'Lluis iv:', newvarin[ilatlon[0],ilatlon[1]],                  \
#                  'localized:', newvarinpt[iv], 'values:',                           \
#                  newvar[ilatlon[0],ilatlon[1]], 'invalues:', ovar[iv],              \
#                  'mindist:', newvarindiff[iv], 'point:',ilatlon    
#            else:
#                print errormsg
#                print '  ' + fname + ': point iv:', iv, 'at', lonvs[iv], ',',        \
#                  latvs[iv],' not relocated !!'
#                print '    mindiffl:', mindiffLl, 'ilon:', ilatlon[1],               \
#                  'ilatlon:', ilatlon[1]
#                quit(-1)
            if np.mod(iptpos,fracs) == 0: 
                onc.sync()
    if out:
        return ilatlon, mindiffLl
    else:
        return

def lonlatFind(ilon, ilat, lonv, latv):
    """ Function to search a given value from a lon, lat 2D data
      ilon, ilat= original 2D matrices with the longitudes and the latitudes
      lonv, latv= longitude and latitude to find
      >>> npt=100
      >>> lonval0 = np.arange(0.,npt*1.,1.)
      >>> latval0 = np.arange(0.,npt*1.,1.)
      >>> lonval = np.zeros((npt,npt), dtype=np.float)
      >>> latval = np.zeros((npt,npt), dtype=np.float)

      >>> for i in range(npt):
      >>>     lonval[:,i] = lonval0[i]
      >>>     latval[i,:] = latval0[i]
      >>> lonlatFind(lonval, latval, 5.25, 5.25)
      (array([5, 5]), 0.35355339059327379)
    """
    fname = 'lonlatFind'

    dx = ilon.shape[1]
    dy = ilon.shape[0]

    nlon = np.min(ilon)
    xlon = np.max(ilon)
    nlat = np.min(ilat)
    xlat = np.max(ilat)

    if lonv < nlon or lonv > xlon:
        print errormsg
        print '  ' + fname + ': longitude outside data range!!'
        print '    given value:', lonv,'outside [',nlon,',',xlon,']'
        quit(-1) 
    if latv < nlat or latv > xlat:
        print errormsg
        print '  ' + fname + ': latitude outside data range!!'
        print '    given value:', latv,'outside [',nlat,',',xlat,']'
        quit(-1) 

# Find point
    difflonlat = np.sqrt((ilon-lonv)**2. + (ilat-latv)**2.)
    mindiffLl = np.min(difflonlat)
    ilatlon = index_mat(difflonlat, mindiffLl)

#    print 'mindiffLl:', mindiffLl, 'ilatlon:', ilatlon
#    print 'lon, lat:', lon[ilatlon[0],ilatlon[1]], ',', lat[ilatlon[0],ilatlon[1]]

    return ilatlon, mindiffLl

def PolyArea(x,y):
    """ Function to compute the area of the polygon following 'Shoelace formula'
      from: http://stackoverflow.com/questions/24467972/calculate-area-of-polygon-given-x-y-coordinates
      x: x-values of the vertexs of the polygon
      y: y-values of the vertexs of the polygon
    >>> x = np.array([-0.5,0.5,0.5,-0.5])
    >>> y = np.array([0.5,0.5,-0.5,-0.5])
    >>> PolyArea(x,y)
    1.0
    """
    fname = 'PolyArea'

    return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1)))

def ijlonlat(lon, lat, nlon, xlon, nlat, xlat):
    """ Function to provide the imin,jmin imax,jmax of a lon,lat box
      lon= 2D matrix with the longitudes
      lat= 2D matrix with the latitudes
      nlon, xlon= minimun, maximum of the longitudes for the lon,lat box
      nlat, xlat= minimun, maximum of the latitudes for the lon,lat box
    """
    fname = 'ijlonlat'

    if nlon < np.min(lon):
        print errormsg
        print '  ' + fname + ': minimum longitude:',nlon,'too small!!'
        print '    smallest possible:',np.min(lon)
        quit(-1)
    if xlon > np.max(lon):
        print errormsg
        print '  ' + fname + ': maximum longitude:',xlon,'too large!!'
        print '    largest possible:',np.max(lon)
        quit(-1)
    if nlat < np.min(lat):
        print errormsg
        print '  ' + fname + ': minimum laitude:',nlat,'too small!!'
        print '    smallest possible:',np.min(lat)
        quit(-1)
    if xlat > np.max(lat):
        print errormsg
        print '  ' + fname + ': maximum latitude:',xlat,'too large!!'
        print '    largest possible:',np.max(lat)
        quit(-1)

    nlonv = np.abs(lon - nlon)
    xlonv = np.abs(lon - xlon)
    nlatv = np.abs(lat - nlat)
    xlatv = np.abs(lat - xlat)

    ni0 = index_mat(nlonv,np.min(nlonv))[1]
    xi0 = index_mat(xlonv,np.min(xlonv))[1] + 1
    nj0 = index_mat(nlatv,np.min(nlatv))[0]
    xj0 = index_mat(xlatv,np.min(xlatv))[0] + 1

    if ni0 > xi0:
        ni = xi0
        xi = ni0
    else:
        ni = ni0
        xi = xi0

    if nj0 > xj0:
        nj = xj0
        xj = nj0
    else:
        nj = nj0
        xj = xj0

    return ni,xi,nj,xj

def significant_decomposition(num,minpot):
    """ Function to decompose a given number by its signifcant potencies
      returns: [numPot], [Potlist], [Diglist]
        [numPot]: number of potencies
        [Potlist]: list of potencies
        [Diglist]: list of digits
        Thus:
          num <> np.sum([Diglist]*10.**[Potlist])

      num= number to decompose
      minpot= minumum potence to decompose
    >>> significant_decomposition(np.pi,-6)
    7, [0.0, -1.0, -2.0, -3.0, -4.0, -5.0, -6.0], [3, 1, 4, 1, 5, 9, 2]
    """
    fname = 'significant_decomposition'

    potencies = []
    potval = []

    anum = np.abs(num)
    diff = anum*1.
    iipot = 1
    pot = np.floor(np.log10(anum))
    if pot < minpot:
        print errormsg
        print '  ' + fname + ': required minimum potency:', minpot, 'is smaller ' + \
          'than the potency of the value:', pot, '!!'
        print '    minimum value 10**minpot:', 10**(minpot), '>', anum
        print "    reduce 'minpot'"
        quit(-1)

    while pot > minpot:
        if diff >= 10.**(pot-1):
            pot = np.floor(np.log10(diff))
            potv = np.int(diff/(10.**pot))
#            print 'Lluis:',np.log10(diff), pot,':',10.**pot,':',diff/(10.**pot),'.',potv,'.',potv*10.**pot,diff
        else:
            potv = 0
            pot = pot - 1
#            print 'Lluis:','*****', pot,':',10.**pot,':',diff/(10.**pot),'.',potv,'.',potv*10.**pot,diff

        diff = diff - potv*10.**pot
#        print '  real diff', diff
        potencies.append(pot)
        potval.append(potv)
        iipot = iipot + 1

    return iipot, potencies, potval

def unitsDate(refdate, date, units):
    """ Function to know how many units of time are from a given pair of dates
      refdate= date of reference (as [YYYY][MM][DD][HH][MI][SS])
      date= date to look for (as [YYYY][MM][DD][HH][MI][SS])
      units= units of time ('century', 'year', 'month', 'day', 'week', 'hour', 'minute', 'second')
    >>> unitsDate('19490101000000', '19760217082932', 'second')
    856081772.0
    >>> unitsDate('19490101000000', '19760217082932', 'minute')
    237800.492222
    """
    import datetime as dt
    fname = 'unitsDate'

    yrref=int(refdate[0:4])
    monref=int(refdate[4:6])
    dayref=int(refdate[6:8])
    horref=int(refdate[8:10])
    minref=int(refdate[10:12])
    secref=int(refdate[12:14])

    yrd=int(date[0:4])
    mond=int(date[4:6])
    dayd=int(date[6:8])
    hord=int(date[8:10])
    mind=int(date[10:12])
    secd=int(date[12:14])

    refdateT = dt.datetime(yrref, monref, dayref, horref, minref, secref)
    ddateT = dt.datetime(yrd, mond, dayd, hord, mind, secd)

    diffT = ddateT - refdateT

    if searchInlist(dir(diffT), 'total_seconds'):
        totsecs = diffT.total_seconds()
    else:
        totsecs = diffT.days*24*3600. + diffT.seconds

    if units == 'century':
        times = totsecs / (100.*365.*24.*3600.)
    elif units == 'year':
        times = totsecs / (365.*24.*3600.)
    elif units == 'month':
        print errormsg
        print '  ' + fname + "' units '" + units + "' not ready!!"
        quit(-1)
    elif units == 'week':
        times = totsecs / (7.*24.*3600.)
    elif units == 'day':
        times = totsecs / (24.*3600.)
    elif units == 'hour':
        times = totsecs / (3600.)
    elif units == 'minute':
        times = totsecs / (3600.)
    elif units == 'second':
        times = totsecs / (1.)

    return times

#print unitsDate('19490101000000', '19760217082932', 'second')
#print unitsDate('19490101000000', '19760217082932', 'minute')

def incomming_flow(dirs):
    """ Function to determine if a fgrid-flow inflows to the central grid point
      dirs = [3,3] matrix with the trip: (inflow directions)
          1: N,  2: NE,  3: E,  4: SE,  5: S,  6: SW:  7: W,  8: NW
        being:
          0,0: NW point, 0,1: N point, 0,2: NE point, 
          1,0: W point, 1,1: grid-point, 1,2: E point,
          2,0: SW point, 2,1: S point, 2,2: SE point
    >>> dirflow = np.array([5, 5, 5, 98, 7, 7, 1, 1, 1], dtype=int).reshape(3,3)
    >>> print dirflow
    [[5 5 5]
     [98 7 7]
     [1 1 1]]
    >>> print incomming_flow(dirflow)
    [[False  True False]
     [False False  True]
     [False  True False]]
    """
    fname = 'incomming_flow'

    inflow = np.zeros((3,3), dtype=bool)

    rightinflow = np.zeros((3,3), dtype=int)
    rightinflow[0,0] = 4
    rightinflow[0,1] = 5
    rightinflow[0,2] = 6
    rightinflow[1,0] = 3
    rightinflow[1,1] = 0
    rightinflow[1,2] = 7
    rightinflow[2,0] = 2
    rightinflow[2,1] = 1
    rightinflow[2,2] = 8

    inflow = np.where(dirs == rightinflow, True, False)

    return inflow

def contflow(dirflow):
    """ Function to bring back the increment in j,i grid points according to a trip: (inflow directions)
          1: N,  2: NE,  3: E,  4: SE,  5: S,  6: SW:  7: W,  8: NW
    >>> contflow(2)
    [1 1]
    >>> contflow(7)
    [0 -1]
    >>> contflow(98)
    [-1 -1]
    """
    fname = 'contflow'
    inc = np.ones((2), dtype=int)*(-1)

    if dirflow == 1: #N
        inc[0] = 1
        inc[1] = 0
    elif dirflow == 2: #NE
        inc[0] = 1
        inc[1] = 1
    elif dirflow == 3: #E
        inc[0] = 0
        inc[1] = 1
    elif dirflow == 4: #SE
        inc[0] = -1
        inc[1] = 1
    elif dirflow == 5: #S
        inc[0] = -1
        inc[1] = 0
    elif dirflow == 6: #SW
        inc[0] = -1
        inc[1] = -1
    elif dirflow == 7: #W
        inc[0] = 0
        inc[1] = -1
    elif dirflow == 8: #NW
        inc[0] = 1
        inc[1] = -1
    else: #
        inc[0] = -1
        inc[1] = -1

    return inc

def vals_around(vals,pt):
    """ Function to provide the 3x3 values around a given j,i point
      vals = matrix of values
      pt = j,i point to serch around
    >>> vals_around(np.arange(16).reshape(4,4), [3, 3])
    [[10.0 11.0 None]
     [14.0 15.0 None]
     [None None None]]
    """
    import numpy.ma as ma
    fname = 'vals_around'

    # Issues with 'None'
    #vals3x3 = np.array([None]*9).reshape(3,3)
    vals3x3 = ma.masked_equal(np.ones((3,3), dtype=np.float), 1.)

    dx = vals.shape[1]
    dy = vals.shape[0]

    nx = np.max([0,pt[1]-1])
    xx = np.min([dx-1,pt[1]+1]) + 1
    ny = np.max([0,pt[0]-1])
    xy = np.min([dy-1,pt[0]+1]) + 1

    vals3x3[1-(pt[0]-ny):1+(xy-pt[0]),1-(pt[1]-nx):1+(xx-pt[1])] = vals[ny:xy,nx:xx]

    return vals3x3

def dictionary_key(dictv, val):
    """ Function to provide the first key in a dictionay with a given value
      ditcv= dictionary
      val= value to search
    >>> dictionary_key({'i': 1, 'ii': 2, 'iii': 3, 'iv': 4}, 3)
    'iii'
    """
    fname = 'dictionary_key'

    keyval = None
    for keyv in dictv.keys():
        if dictv[keyv] == val:
            keyval = keyv
            break

    return keyval

def dictionary_key_list(dictv, val):
    """ Function to provide the first key in a dictionay of lists with a given value
      ditcv= dictionary
      val= value to search
    >>> dictionary_key_list({'i': [1, 0, -1], 'ii': [2, 8, 16], 'iii': [-3, 3, 9], 'iv': [4]}, 3)
    'iii'
    """
    fname = 'dictionary_key'

    keyval = None
    for keyv in dictv.keys():
        if searchInlist(dictv[keyv],val):
            keyval = keyv
            break

    return keyval

def num_chainSnum(val):
    """ Function to pass a value to a `ChainStrNum' number
        `ChainStrNum:' hirerarchy classification where each levels is a significant number within a string:
            1 lev.: [n]
            2 lev.: [n][m]
            3 lev.: [n][m][l]
            ...
          NOTE: when a given level has more than 9 values in a given potency of 10, then 'a' is attached in the front: 'a'[i]
          NOTE: when a given level has more than 19 values in a given potency of 10, then 'b' is attached in the front: 'b'[i]
          NOTE: when a given level has more than 29 values in a given potency of 10, then 'c' is attached in the front: 'c'[i]
          (...)
          NOTE: when a given level has more than 89 values in a given potency of 10, then 'i' is attached in the front: 'i'[i]
          NOTE: 'o' is for that potencies of 10 without value
      val = value to transform
    >>> num_chainSnum(3)
    3
    >>> num_chainSnum(1976)
    aig6
    >>> num_chainSnum(12010)
    aboa0
    """
    fname = 'num_chainSnum'

    npot = np.int(np.log10(val))

    chainSnum=''
    if npot > 0:
        Nvals, pots, vals = significant_decomposition(val,0)
        rest = 0
        for ipot in range(npot):
            rest = rest + int(vals[ipot]*10**pots[ipot])
            if vals[ipot] > 0:
                chainSnum = chainSnum + chr(96+vals[ipot])
            else:
                chainSnum = chainSnum + 'o'

        num = val - rest
    else:
        num = val
    chainSnum = chainSnum + str(num)

    return chainSnum

def chainSnum_num(cSnum):
    """ Function to pass a `ChainStrNum' string to number
        `ChainStrNum:' hierarchy classification where each levels is a significant number within a string:
            1 lev.: [n]
            2 lev.: [n][m]
            3 lev.: [n][m][l]
            ...
          NOTE: when a given level has more than 9 values in a given potency of 10, then 'a' is attached in the front: 'a'[i]
          NOTE: when a given level has more than 19 values in a given potency of 10, then 'b' is attached in the front: 'b'[i]
          NOTE: when a given level has more than 29 values in a given potency of 10, then 'c' is attached in the front: 'c'[i]
          (...)
          NOTE: when a given level has more than 89 values in a given potency of 10, then 'i' is attached in the front: 'i'[i]
          NOTE: 'o' is for that potencies of 10 without value
      cSnum = value to transform
    >>> num_chainSnum('3')
    3
    >>> num_chainSnum('aig6')
    1976
    >>> num_chainSnum('aboa0')
    12010
    """
    fname = 'chainSnum_num'

    num = 0
    LcSnum = len(cSnum)
    if LcSnum > 1:
        for ic in range(LcSnum-1):
            ipot = ord(cSnum[ic:ic+1]) - 96
            if ipot < 0 or ipot > 9 and ipot != ord('o') - 96:
                print errormsg
                print '  ' + fname + ": wrong character '" + cSnum[ic:ic+1] + "' !!", ipot
                print "    'ChainStrNum' codification only allows 'a' to 'i' and 'o'"
                quit(-1)
            else:
                if ipot == ord('o') - 96: ipot = 0

            num = num + int(ipot*10**(LcSnum-ic-1))

    num = num + int(cSnum[LcSnum-1:LcSnum])

    return num

def num_split(string):
    """ Function to split a string at each numeric value keeping the number as the last character of each cut
      string= string to cut
    >>> num_split('asd123asdsa1')
    ['asd1', '2', '3', 'asdsa1']
    """
    fname = 'num_split'

    Lstring = len(string)
    cuts = []
    newcut = ''
    for ic in range(Lstring):
        sc = string[ic:ic+1]
        newcut = newcut + sc
        if ord(sc) >= 48 and ord(sc) <= 57:
            cuts.append(newcut)
            newcut = ''

    return cuts

def chainSnum_levnext(parentlev, ChainStrNums):
    """ Function to provide the next value for a given level from a chainStrnum hirerarchy of numbers
      prevlev: parent level of the desired level
      ChainStrNums: list of strings as `ChainStrNum'
        `ChainStrNum:' hierarchyc classification where each levels is a significant number within a string:
            1 lev.: [n]
            2 lev.: [n][m]
            3 lev.: [n][m][l]
            ...
          NOTE: when a given level has more than 9 values in a given potency of 10, then 'a' is attached in the front: 'a'[i]
          NOTE: when a given level has more than 19 values in a given potency of 10, then 'b' is attached in the front: 'b'[i]
          NOTE: when a given level has more than 29 values in a given potency of 10, then 'c' is attached in the front: 'c'[i]
          (...)
          NOTE: when a given level has more than 89 values in a given potency of 10, then 'i' is attached in the front: 'i'[i]
          NOTE: 'o' is for that potencies of 10 without value
    >>> ChainStrNums = ['1', '2', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a0', '111', '112', '113', '121', '122' ]
    >>> chainSnum_levnext('',ChainStrNums)
    3
    >>> chainSnum_levnext('1',ChainStrNums)
    1a1
    >>> chainSnum_levnext('12',ChainStrNums)
    123
    >>> chainSnum_levnextt('111',ChainStrNums)
    1111
    """
    fname = 'chainSnum_levnext'

# Number of levels of the parent level
    if len(parentlev) > 0:
        parentlevs = num_split(parentlev)
        Nparentlevs = len(parentlevs)
    else:
        parentlevs = ['']
        Nparentlevs = 0

#    print '  ' + fname + ' parentlev:', parentlev,'Nlevs:', Nparentlevs,'parentlevs:',parentlevs

# Level to increment
    lev = Nparentlevs + 1

    rightvals = []
    for istr in ChainStrNums:
        levs = num_split(istr)
        if len(levs) == lev:
            parent = ''
            for ilev in range(len(levs)-1):
                parent = parent + levs[ilev]

            if parent == parentlev:
                rightvals.append(chainSnum_num(levs[lev-1]))

    if len(rightvals) > 0:
        newnum = np.max(rightvals)
        newchainSnum = num_chainSnum(newnum + 1)
    else:
        newchainSnum = '1'

    return parentlev + newchainSnum

class chainSnumHierarchy(object):
    """ Function to provide the structure of a `ChainStrNum' hierarchy
      ChainStrNums: list of strings as `ChainStrNum'
        Nlevs: number of levels
        levs: all the strings
        xlevs: list with the maximum number of each level
        Llev[N]: numbers of values in level N (up to 10 levels)
        xlev[N]: maximun numbers of a level N (up to 10 levels)
        Slev[N]: strings of level N (up to 10 levels)
        Nlev[N]: numbers of level N (up to 10 levels)

        # methods
        levincr([ChainStrNum]): method to increase `ChainStrNum' level

        `ChainStrNum:' hierarchyc classification where each levels is a significant number within a string:
            1 lev.: [n]
            2 lev.: [n][m]
            3 lev.: [n][m][l]
            ...
          NOTE: when a given level has more than 9 values in a given potency of 10, then 'a' is attached in the front: 'a'[i]
          NOTE: when a given level has more than 19 values in a given potency of 10, then 'b' is attached in the front: 'b'[i]
          NOTE: when a given level has more than 29 values in a given potency of 10, then 'c' is attached in the front: 'c'[i]
          (...)
          NOTE: when a given level has more than 89 values in a given potency of 10, then 'i' is attached in the front: 'i'[i]
          NOTE: 'o' is for that potencies of 10 without value
    """
    fname = 'chainSnumHierarchy'

    def __init__(self,ChainStrNums):
        self.Nchars = len(ChainStrNums)
        self.Nlevs = 0
        self.levs = []
        self.xlevs = []
        self.Llev1 = None
        self.Llev2 = None
        self.Llev3 = None
        self.Llev4 = None
        self.Llev5 = None
        self.Llev6 = None
        self.Llev7 = None
        self.Llev8 = None
        self.Llev9 = None
        self.Llev10 = None
        self.xlev1 = None
        self.xlev2 = None
        self.xlev3 = None
        self.xlev4 = None
        self.xlev5 = None
        self.xlev6 = None
        self.xlev7 = None
        self.xlev8 = None
        self.xlev9 = None
        self.xlev10 = None
        self.Slev1 = []
        self.Slev2 = []
        self.Slev3 = []
        self.Slev4 = []
        self.Slev5 = []
        self.Slev6 = []
        self.Slev7 = []
        self.Slev8 = []
        self.Slev9 = []
        self.Slev10 = []
        self.Nlev1 = []
        self.Nlev2 = []
        self.Nlev3 = []
        self.Nlev4 = []
        self.Nlev5 = []
        self.Nlev6 = []
        self.Nlev7 = []
        self.Nlev8 = []
        self.Nlev9 = []
        self.Nlev10 = []

        levsNvals = np.zeros((11,self.Nchars), dtype=int)
        ilevvals = np.zeros((11), dtype=int)
        xtrmlevs = []

        Svals1 = []
        Svals2 = []
        Svals3 = []
        Svals4 = []
        Svals5 = []
        Svals6 = []
        Svals7 = []
        Svals8 = []
        Svals9 = []
        Svals10 = []
        for istr in ChainStrNums:
            levs = num_split(istr)
            Nlevs = len(levs)
            if Nlevs > self.Nlevs: self.Nlevs = Nlevs
            if Nlevs > 10:
                print errormsg
                print '  ' + fname + ': too levels:', Nlevs, " in StringNum '" +     \
                  istr + "' !!"
                print '    increase in the code the number of levels in the class'
                quit(-1)
            ilevvals[Nlevs] = ilevvals[Nlevs] + 1
            if Nlevs == 1: Svals1.append(istr)
            if Nlevs == 2: Svals2.append(istr)
            if Nlevs == 3: Svals3.append(istr)
            if Nlevs == 4: Svals4.append(istr)
            if Nlevs == 5: Svals5.append(istr)
            if Nlevs == 6: Svals6.append(istr)
            if Nlevs == 7: Svals7.append(istr)
            if Nlevs == 8: Svals8.append(istr)
            if Nlevs == 9: Svals9.append(istr)
            if Nlevs == 10: Svals10.append(istr)

            levsNvals[Nlevs,ilevvals[Nlevs]] = chainSnum_num(levs[Nlevs-1])

        valslist = ChainStrNums.sort()
        self.levs = valslist
        # 1st lev
        self.Llev1 = ilevvals[1]
        Svlist = Svals1
        Nvlist = list(levsNvals[1,1:self.Llev1+1])
        self.xlev1 = np.max(Nvlist)
        xtrmlevs.append(self.xlev1)
        Svlist.sort()
        Nvlist.sort()
        self.Slev1 = Svlist
        self.Nlev1 = Nvlist
        # 2nd lev
        if self.Nlevs > 1:
            self.Llev2 = ilevvals[2]
            Svlist = Svals2
            Nvlist = list(levsNvals[2,1:self.Llev2+1])
            self.xlev2 = np.max(Nvlist)
            xtrmlevs.append(self.xlev2)
            Svlist.sort()
            Nvlist.sort()
            self.Slev2 = Svlist
            self.Nlev2 = Nvlist
        # 3rd lev
        if self.Nlevs > 2:
            self.Llev3 = ilevvals[3]
            Svlist = Svals3
            Nvlist = list(levsNvals[3,1:self.Llev3+1])
            self.xlev3 = np.max(Nvlist)
            xtrmlevs.append(self.xlev3)
            Svlist.sort()
            Nvlist.sort()
            self.Slev3 = Svlist
            self.Nlev3 = Nvlist
        # 4th lev
        if self.Nlevs > 3:
            self.Llev4 = ilevvals[4]
            Svlist = Svals4
            Nvlist = list(levsNvals[4,1:self.Llev4+1])
            self.xlev4 = np.max(Nvlist)
            xtrmlevs.append(self.xlev4)
            Svlist.sort()
            Nvlist.sort()
            self.Slev4 = Svlist
            self.Nlev4 = Nvlist
        # 5th lev
        if self.Nlevs > 4:
            self.Llev5 = ilevvals[5]
            Svlist = Svals5
            Nvlist = list(levsNvals[5,1:self.Llev5+1])
            self.xlev5 = np.max(Nvlist)
            xtrmlevs.append(self.xlev5)
            Svlist.sort()
            Nvlist.sort()
            self.Slev5 = Svlist
            self.Nlev5 = Nvlist
        # 6th lev
        if self.Nlevs > 5:
            self.Llev6 = ilevvals[6]
            Svlist = Svals6
            Nvlist = list(levsNvals[6,1:self.Llev6+1])
            self.xlev6 = np.max(Nvlist)
            xtrmlevs.append(self.xlev6)
            Svlist.sort()
            Nvlist.sort()
            self.Slev6 = Svlist
            self.Nlev6 = Nvlist
        # 7th lev
        if self.Nlevs > 6:
            self.Llev7 = ilevvals[7]
            Svlist = Svals7
            Nvlist = list(levsNvals[7,1:self.Llev7+1])
            self.xlev7 = np.max(Nvlist)
            xtrmlevs.append(self.xlev7)
            Svlist.sort()
            Nvlist.sort()
            self.Slev7 = Svlist
            self.Nlev7 = Nvlist
        # 8th lev
        if self.Nlevs > 7:
            self.Llev8 = ilevvals[8]
            Svlist = Svals8
            Nvlist = list(levsNvals[8,1:self.Llev8+1])
            self.xlev8 = np.max(Nvlist)
            xtrmlevs.append(self.xlev8)
            Svlist.sort()
            Nvlist.sort()
            self.Slev8 = Svlist
            self.Nlev8 = Nvlist
        # 9th lev
        if self.Nlevs > 9:
            self.Llev9 = ilevvals[9]
            Svlist = Svals9
            Nvlist = list(levsNvals[9,1:self.Llev9+1])
            self.xlev9 = np.max(Nvlist)
            xtrmlevs.append(self.xlev9)
            Svlist.sort()
            Nvlist.sort()
            self.Slev9 = Svlist
            self.Nlev9 = Nvlist
        # 10th lev
        if self.Nlevs > 9:
            self.Llev10 = ilevvals[10]
            Svlist = Svals10
            Nvlist = list(levsNvals[10,1:self.Llev10+1])
            self.xlev10 = np.max(Nvlist)
            xtrmlevs.append(self.xlev10)
            Svlist.sort()
            Nvlist.sort()
            self.Slev10 = Svlist
            self.Nlev10 = Nvlist
        self.xlevs = xtrmlevs

    def levincr(self,plev):
        """ Method to increase a given plevel level
        levincr(self,plev): 
        >>> ChainStrNums = ['1', '2', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a0', '111', '112', '113', '121', '122' ]
        >>> CSN_hyr = chainSnumHierarchy(ChainStrNums)
        >>> CSN_hyr.levincr('11')
        114
        """
        return chainSnum_levnext(plev, ChainStrNums)

#ChainStrNums = ['1', '2', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a0', '111', '112', '113', '121', '122' ]
#CSN_hyr = chainSnumHierarchy(ChainStrNums)

#print CSN_hyr.levincr.__doc__
#quit()

def index_mat_way(mat,val,way):
    """ Function to look for a value within a matrix following a way and direction
      mat: matrix
      val: value to search
      way: way of search
        'anticlockwise12': looking in an anti-clockwise direction starting at 12
        'anticlockwise6': looking in an anti-clockwise direction starting at 6
        'clockwise12': looking in an clockwise direction starting at 12
        'clockwise6': looking in an clockwise direction starting at 6
    >>> mat = np.arange(20).reshape(4,5)
    >>> mat[2,1] = 3
    >>> index_mat_way(mat,3,'clockwise12')
    [array([0, 3]), array([2, 1])]
    >>> index_mat_way(mat,3,'anticlockwise12') 
    [array([2, 1]), array([0, 3])]
    """
    fname = 'index_mat_way'

    ways = ['anticlockwise12', 'anticlockwise6', 'clockwise12', 'clockwise6']

    Ndims = len(mat.shape)
    dx = mat.shape[Ndims-1]
    dy = mat.shape[Ndims-2]

    diffmat = np.abs(mat - val)
    mindiff = np.min(diffmat)
    if np.sum(diffmat == mindiff) == 1:
        ijindex = index_mat(diffmat,mindiff)
        return ijindex

    if Ndims > 2: dz = mat.shape[Ndims-3]
    if Ndims > 3: dt = mat.shape[Ndims-4]

    if way == 'anticlockwise12':
# Sorting following a double criteria, first angle and then distance taken from the
#   center in the anti-clockwise direction starting at 12
        if Ndims > 2:
            print errormsg
            print '  ' + fame + ': wiht more than 2-dims:', Ndims, "'" + way +       \
              "' is not possible !!"
            quit(-1)
 
        distrad = radius_dist(dx,dy,dx/2,dy/2)
        distangle = radius_angle(dx,dy,dx/2,dy/2)
        distangle = np.where(distangle >= np.pi, distangle - 2.*np.pi, distangle)
        distangle = np.where(distangle > 0., 2.* np.pi - distangle, -distangle)

        sortedij = {}
        minangle = 10000.
        notfound = np.zeros((dy,dx), dtype=bool)
        maskdistrad = ma.array(distrad, mask=notfound)
        maskdistangle = ma.array(distangle, mask=notfound)
        for ip in range(dx*dy):
            minangle = np.min(maskdistangle)
            jiangle = multi_index_mat(maskdistangle, minangle)
            mindist = 10000.
            for ia in range(len(jiangle)):
                iaji = jiangle[ia]
                if maskdistrad[iaji[0], iaji[1]] < mindist: 
                    mindist = maskdistrad[iaji[0], iaji[1]]
                    idistangle = iaji
            notfound[idistangle[0],idistangle[1]] = True
            sortedij[ip] = idistangle

    elif way == 'anticlockwise6':
# Sorting following a double criteria, first angle and then distance taken from the
#   center in the anti-clockwise direction starting at 6
        if Ndims > 2:
            print errormsg
            print '  ' + fame + ': wiht more than 2-dims:', Ndims, "'" + way +       \
              "' is not possible !!"
            quit(-1)
 
        distrad = radius_dist(dx,dy,dx/2,dy/2)
        distangle = radius_angle(dx,dy,dx/2,dy/2)
        distangle = np.where(distangle > np.pi, distangle - 2.*np.pi, distangle)
        distangle = np.where(distangle >= 0., np.pi - distangle, np.pi-distangle)

        sortedij = {}
        minangle = 10000.
        notfound = np.zeros((dy,dx), dtype=bool)
        maskdistrad = ma.array(distrad, mask=notfound)
        maskdistangle = ma.array(distangle, mask=notfound)
        for ip in range(dx*dy):
            minangle = np.min(maskdistangle)
            jiangle = multi_index_mat(maskdistangle, minangle)
            mindist = 10000.
            for ia in range(len(jiangle)):
                iaji = jiangle[ia]
                if maskdistrad[iaji[0], iaji[1]] < mindist: 
                    mindist = maskdistrad[iaji[0], iaji[1]]
                    idistangle = iaji
            notfound[idistangle[0],idistangle[1]] = True
            sortedij[ip] = idistangle

    elif way == 'clockwise12':
# Sorting following a double criteria, first angle and then distance taken from the
#   center in the cloc-kwise direction starting at 12
        if Ndims > 2:
            print errormsg
            print '  ' + fame + ': wiht more than 2-dims:', Ndims, "'" + way +       \
              "' is not possible !!"
            quit(-1)
 
        distrad = radius_dist(dx,dy,dx/2,dy/2)
        distangle = radius_angle(dx,dy,dx/2,dy/2)

        sortedij = {}
        minangle = 10000.
        notfound = np.zeros((dy,dx), dtype=bool)
        maskdistrad = ma.array(distrad, mask=notfound)
        maskdistangle = ma.array(distangle, mask=notfound)
        for ip in range(dx*dy):
            minangle = np.min(maskdistangle)
            jiangle = multi_index_mat(maskdistangle, minangle)
            mindist = 10000.
            for ia in range(len(jiangle)):
                iaji = jiangle[ia]
                if maskdistrad[iaji[0], iaji[1]] < mindist: 
                    mindist = maskdistrad[iaji[0], iaji[1]]
                    idistangle = iaji
            notfound[idistangle[0],idistangle[1]] = True
            sortedij[ip] = idistangle

    elif way == 'clockwise6':
# Sorting following a double criteria, first angle and then distance taken from the
#   center in the clockwise direction starting at 6
        if Ndims > 2:
            print errormsg
            print '  ' + fame + ': wiht more than 2-dims:', Ndims, "'" + way +       \
              "' is not possible !!"
            quit(-1)
 
        distrad = radius_dist(dx,dy,dx/2,dy/2)
        distangle = radius_angle(dx,dy,dx/2,dy/2)
        distangle = np.where(distangle >= np.pi, distangle - 2.*np.pi, distangle)
        distangle = np.where(distangle > 0., np.pi + distangle, np.pi+distangle)

        sortedij = {}
        minangle = 10000.
        notfound = np.zeros((dy,dx), dtype=bool)
        maskdistrad = ma.array(distrad, mask=notfound)
        maskdistangle = ma.array(distangle, mask=notfound)
        for ip in range(dx*dy):
            minangle = np.min(maskdistangle)
            jiangle = multi_index_mat(maskdistangle, minangle)
            mindist = 10000.
            for ia in range(len(jiangle)):
                iaji = jiangle[ia]
                if maskdistrad[iaji[0], iaji[1]] < mindist: 
                    mindist = maskdistrad[iaji[0], iaji[1]]
                    idistangle = iaji
            notfound[idistangle[0],idistangle[1]] = True
            sortedij[ip] = idistangle

    else:
        print errormsg
        print '  ' + fname + ": way of search '" + way + "' not ready !!"
        print '    available ways:', ways

    indices = []
    for ij in range(dx*dy):
        sij = sortedij[ij]
        sval = mat[sij[0], sij[1]]
        if sval == val:
            indices.append(sij)

    return indices

def subbasin_point_orig(trips, pt):
    """ Function to provide sub-basins given a grid point following a matrix of trips
      trips= matrix of trips values
        1: N,  2: NE,  3: E,  4: SE,  5: S,  6: SW:  7: W,  8: NW
      pt= point within the trip matrix
    """
    fname = 'subbasin_point'

    subbasin = np.zeros((trips.shape), dtype=bool)
    TOTtrips = len(trips.flatten())

# Dictionary with the j,i points of all the subbasin
    ijsubbasin = {}
# Dictionary to tell if a given j,i sub-basin point has been localized (as number from ijsubbasin)
    ijfound = {}
# Dictionary to tell if a given sub-flow has been finished (when Narrive == 0)
    subfinished = {}
# Dictionary with the list of points which are contained in a sub-flow
    ijsubflow = {}
# Number of ji sub-basin points
    Nij = 1

    subbasin[pt[0], pt[1]] = True
    ijsubbasin[Nij] = np.array(pt)
    ijfound[Nij] = False
    ijsubflow[str(Nij)] = [Nij]
    subfinished[str(Nij)] = False

# Loop around all sub-flows
##
    while np.sum(subfinished.values) != 0 and np.sum(ijfound.values) != 0:
        Njipt = dictionary_key(subfinished, False)
        if Njipt is not None:
#            print Njipt, 'points subflow:', ijsubflow[Njipt]
            for ipt in ijsubflow[Njipt]:
                if ijfound[ipt] == False:
                    jipt = ijsubbasin[ipt]
                    break
#            print '  working from point:', ipt, 'ji pair:', jipt
            ijfound[ipt] = True
            Nij = ipt
        else:
# Keep searching since there are grid-points not found!
#            print '  ' + fname + ': Keep searching since there are grid-points not found!!'
#            print ijfound
            Nij = dictionary_key(ijfound, False)
            if Nij is None:
                return subbasin, ijsubflow, ijsubbasin

            ijfound[Nij] = True
            jipt = ijsubbasin[Nij]
            parentNjipt = dictionary_key_list(ijsubflow, Nij)
            Njipt = chainSnum_levnext(parentNjipt, ijsubflow.keys())
#            print '  ' + fname + "new sub-flow '" + Njipt + "' !!"
            subfinished[Njipt] = False
            Nij = np.max(ijfound.keys())

#        print 'Lluis Nij:', Nij
# Looking for which point of the sub-flow retake the search
        if Nij == 1:
            ipt = 1
            jipt = pt

        ardtrips = vals_around(trips,jipt)
#        print '  ' + fname + 'ardtrips _______'
#        print ardtrips

        arrive = incomming_flow(ardtrips)
        Narrive = np.sum(arrive)
#        print Nij, '  ' + fname + ' Narrive:', Narrive
        if Narrive == 0:
            ijfound[Nij] = True
            subfinished[Njipt] = True
        else:
#            print '  ' + fname + 'arrive _______'
#            print arrive
            followvals = np.zeros((3,3), dtype=bool)
            followvals = arrive
            parentNjipt = Njipt

            for ifollow in range(Narrive):
#                print 'ifollow:',ifollow,'/',Narrive

# We only want to work with that ij, which have not yet been found
                while np.sum(followvals) != 0:
#                    print Nij,'  Looking for a non-located point in subbasin ________'
#                    print subbasin[jipt[0]-1:jipt[0]+2,jipt[1]-1:jipt[1]+2]
                    jifollow = index_mat(followvals, True)
                    jiequiv = jifollow - [1,1]
                    if subbasin[jipt[0]+jiequiv[0], jipt[1]+jiequiv[1]] == False:
                        Nij = np.max(ijfound.keys()) + 1
                        jiptnew = jipt + jiequiv
                        if ifollow != 0:
# Avoiding repetition of sub-flow name
                            if len(ijsubflow.keys()) > 1:
                                Njipt = chainSnum_levnext(parentNjipt, ijsubflow.keys())
                            else:
                                Njipt = '11'
                        else:
                            Njipt = parentNjipt
#                        print '  ' + fname + "new sub-flow '" + Njipt + "' !!"
                        subfinished[Njipt] = False
                        subbasin[jipt[0]+jiequiv[0], jipt[1]+jiequiv[1]] = True
                        ijfound[Nij] = False
                        ijsubbasin[Nij] = jiptnew
                        if ijsubflow.has_key(Njipt):
                            subflowpts = ijsubflow[Njipt]
                            subflowpts.append(Nij)
                            ijsubflow[Njipt] = subflowpts
                        else:
                            ijsubflow[Njipt] = [Nij]
                        break
                    else:
                        followvals[jifollow[0],jifollow[1]] = False
                        if np.sum(followvals) == 0:
                            ijfound[Nij] = True
                            subfinished[Njipt] = True
#                            print Nij,"  subflow '" + Njipt + "' finished!!"
                            break

                if Nij > TOTtrips:
                    print errormsg
                    print '  ' + fname + ': sub-flow point', Nij, 'larger than ' +   \
                      'the number of trips', TOTtrips,'!!'
                    quit()

#            if ijsubflow.has_key(Njipt): 
#                print "Lluis points of subflow: '" + Njipt + "' _______=", ijsubflow[Njipt]
#                for isub in ijsubflow[Njipt]:
#                    print '  ' , isub , ':', ijsubbasin[isub], ijfound[isub]
#            if Nij == 10: print 'Nij = 9:', ijfound[9]

#        print subbasin
#        if Nij > 4: quit()

    return subbasin

def subbasin_point(trips, pt, direction):
    """ Function to provide sub-basins given a grid point following a matrix of trips
      trips= matrix of trips values
        1: N,  2: NE,  3: E,  4: SE,  5: S,  6: SW:  7: W,  8: NW
      pt= point within the trip matrix
      direction= searching direction river-up ('left': clockwise, 'right': anti-clockwise)
    """
    fname = 'subbasin_point'

    subbasin = np.zeros((trips.shape), dtype=bool)
    TOTtrips = len(trips.flatten())

# Dictionary with the j,i points of all the subbasin
    ijsubbasin = {}
# Dictionary to tell if a given j,i sub-basin point has been localized (as number from ijsubbasin)
    ijfound = {}
# Dictionary to tell if a given sub-flow has been finished (when Narrive == 0)
    subfinished = {}
# Dictionary with the list of points which are contained in a sub-flow
    ijsubflow = {}
# Number of ji sub-basin points
    Nij = 1

    subbasin[pt[0], pt[1]] = True
    ijsubbasin[Nij] = np.array(pt)
    ijfound[Nij] = False
    ijsubflow[str(Nij)] = [Nij]
    subfinished[str(Nij)] = False

# Loop around all sub-flows
##
    while np.sum(subfinished.values) != 0 and np.sum(ijfound.values) != 0:
        Njipt = dictionary_key(subfinished, False)
        if Njipt is not None:
#            print Njipt, 'points subflow:', ijsubflow[Njipt]
            for ipt in ijsubflow[Njipt]:
                if ijfound[ipt] == False:
                    jipt = ijsubbasin[ipt]
                    break
#            print '  working from point:', ipt, 'ji pair:', jipt
            ijfound[ipt] = True
            Nij = ipt
        else:
# Keep searching since there are grid-points not found!
#            print '  ' + fname + ': Keep searching since there are grid-points not found!!'
#            print ijfound
            Nij = dictionary_key(ijfound, False)
            if Nij is None:
                return subbasin, ijsubflow, ijsubbasin

            ijfound[Nij] = True
            jipt = ijsubbasin[Nij]
            parentNjipt = dictionary_key_list(ijsubflow, Nij)
            Njipt = chainSnum_levnext(parentNjipt, ijsubflow.keys())
#            print '  ' + fname + "new sub-flow '" + Njipt + "' !!"
            subfinished[Njipt] = False
            Nij = np.max(ijfound.keys())

#        print 'Lluis Nij:', Nij
# Looking for which point of the sub-flow retake the search
        if Nij == 1:
            ipt = 1
            jipt = pt

        ardtrips = vals_around(trips,jipt)
#        print '  ' + fname + 'ardtrips _______'
#        print ardtrips

        arrive = incomming_flow(ardtrips)
        Narrive = np.sum(arrive)
#        print Nij, '  ' + fname + ' Narrive:', Narrive
        if Narrive == 0:
            ijfound[Nij] = True
            subfinished[Njipt] = True
        else:
#            print '  ' + fname + 'arrive _______'
#            print arrive
            followvals = np.zeros((3,3), dtype=bool)
            followvals = arrive
            parentNjipt = Njipt

            for ifollow in range(Narrive):
#                print 'ifollow:',ifollow,'/',Narrive

# We only want to work with that ij, which have not yet been found
                while np.sum(followvals) != 0:
#                    print Nij,'  Looking for a non-located point in subbasin ________'
#                    print subbasin[jipt[0]-1:jipt[0]+2,jipt[1]-1:jipt[1]+2]

# Searching direction river-up. 'left': starting from the left, 'right' starting from the right
                    if direction == 'left':
                        jifollow0 = index_mat_way(followvals, True, 'clockwise6')
                    elif direction == 'right':
                        jifollow0 = index_mat_way(followvals, True, 'anticlockwise6')
                    if len(jifollow0) > 1 and type(jifollow0) == type([2]):
                        jifollow = jifollow0[0]
                    else:
                        jifollow = jifollow0
## orig ##                   jifollow = index_mat(followvals, True)
                    jiequiv = jifollow - [1,1]
                    if subbasin[jipt[0]+jiequiv[0], jipt[1]+jiequiv[1]] == False:
                        Nij = np.max(ijfound.keys()) + 1
                        jiptnew = jipt + jiequiv
                        if ifollow != 0:
# Avoiding repetition of sub-flow name
                            if len(ijsubflow.keys()) > 1:
                                Njipt = chainSnum_levnext(parentNjipt, ijsubflow.keys())
                            else:
                                Njipt = '11'
                        else:
                            Njipt = parentNjipt
#                        print '  ' + fname + "new sub-flow '" + Njipt + "' !!"
                        subfinished[Njipt] = False
                        subbasin[jipt[0]+jiequiv[0], jipt[1]+jiequiv[1]] = True
                        ijfound[Nij] = False
                        ijsubbasin[Nij] = jiptnew
                        if ijsubflow.has_key(Njipt):
                            subflowpts = ijsubflow[Njipt]
                            subflowpts.append(Nij)
                            ijsubflow[Njipt] = subflowpts
                        else:
                            ijsubflow[Njipt] = [Nij]
                        break
                    else:
                        followvals[jifollow[0],jifollow[1]] = False
                        if np.sum(followvals) == 0:
                            ijfound[Nij] = True
                            subfinished[Njipt] = True
#                            print Nij,"  subflow '" + Njipt + "' finished!!"
                            break

                if Nij > TOTtrips:
                    print errormsg
                    print '  ' + fname + ': sub-flow point', Nij, 'larger than ' +   \
                      'the number of trips', TOTtrips,'!!'
                    quit()

#            if ijsubflow.has_key(Njipt): 
#                print "Lluis points of subflow: '" + Njipt + "' _______=", ijsubflow[Njipt]
#                for isub in ijsubflow[Njipt]:
#                    print '  ' , isub , ':', ijsubbasin[isub], ijfound[isub]
#            if Nij == 10: print 'Nij = 9:', ijfound[9]

#        print subbasin
#        if Nij > 4: quit()

    return subbasin

## Caceres
#rivers = np.array([7, 1, 1, 1, 1, 5, 5, 1, \
#  7, 1, 6, 3, 5, 5, 6, 5, \
#  8, 7, 5, 3, 5, 6, 3, 5, \
#  1, 1, 3, 5, 5, 7, 5, 5, \
#  3, 3, 5, 6, 5, 5, 5, 7 ], dtype=int).reshape(5,8)

#point = [4,4]

# Porto Do Alegre
#rivers = np.array([5, 5, 1, 7, 1, 8, 8, 2, \
#  5, 6, 5, 7, 7, 1, 3, 1, \
#  6, 3, 5, 1, 3, 3, 3, 3, \
#  7, 5, 5, 5, 5, 5, 5, 1, \
#  5, 5, 7, 7, 7, 6, 7, 7, \
#  5, 5, 7, 7, 7, 7, 8, 7, \
#  6, 6, 7, 7, 7, 7, 7, 7, \
#  5, 7, 7, 7, 8, 7, 7, 6, \
#  6, 7, 7, 7, 7, 7, 7, 6], dtype=int).reshape(9,8)

#point = [7,0]

#print rivers
#print rivers[point[0], point[1]]
#direc = 'left'

#masksubbasin, subflows, subflowspt = subbasin_point_dir(rivers, point, 'right')
#print rivers
#print masksubbasin
#for subflow in subflows:
#  print subflow, ':', subflows[subflow]
#  for isub in subflows[subflow]:
#      print '  ' , isub , ':', subflowspt[isub]

#print 'Total sub-basin:', np.sum(masksubbasin)
#quit()

def color_deg(colors, Nsteps, typedeg, values=None):
    """ Function to generate a degradation of colors in rgb base
      colors= list of colors to use [r,g,b] r,g,b <= 1.
      Nsteps= number of steps (NOTE: final number of colors might differ from this value)
      typedeg= type of degradate
        'std': simple linear degradation between equi-spaced colors 
        'vals': change of colors at a given value (it requires [values])
      values= list of values to use as reference (when applicable)
      provides: [colordeg], [Ncolors]
        [colordeg] = (4, [Ncolors]) matrix with
          [0,:]= assigned value to the color (for 'std': counter)
          [1:4,:]= r,g,b color
    >>> color_deg([ [1.,0.,0.], [0.,1.,0.], [0.,0.,1.] ], 10, 'std')
    [[ 0.     0.125  0.25   0.375  0.5    0.625  0.75   0.875  1.    ]
     [ 1.     0.75   0.5    0.25   0.     0.     0.     0.     0.    ]
     [ 0.     0.25   0.5    0.75   1.     0.75   0.5    0.25   0.    ]
     [ 0.     0.     0.     0.     0.     0.25   0.5    0.75   1.    ]]
    defcolors = color_deg([ [1.,0.,0.], [0.,1.,0.], [0.,0.,1.]], 12, 'vals', [-3., 0., 3.])
    [[-3.  -2.4 -1.8 -1.2 -0.6  0.   0.6  1.2  1.8  2.4  3. ]
     [ 1.   0.8  0.6  0.4  0.2  0.   0.   0.   0.   0.   0. ]
     [ 0.   0.2  0.4  0.6  0.8  1.   0.8  0.6  0.4  0.2  0. ]
     [ 0.   0.   0.   0.   0.   0.   0.2  0.4  0.6  0.8  1. ]]
    """
    fname = 'color_deg'

    colordeg = np.zeros((4,Nsteps), dtype=np.float)
    Ncols = len(colors)
    cols = np.zeros((3,Ncols), dtype=np.float)
    for icol in range(Ncols):
        cols[:,icol] = np.array(colors[icol])
    
    if Ncols > Nsteps:
        print warnmsg
        print '  ' + fname + ': too few steps:', Nsteps, 'for the number of colors:',\
          Ncols,'!!'
        print '    directly assigning the given color'
        Nfincol = Nsteps
        if Nsteps > 1:
            for istp in range(Nsteps):
                colordeg[0,istp] = istp / (Nsteps-1.)
                colordeg[1:4,istp] = cols[:,istp]
        else:
            colordeg[0,0] = 1.
            colordeg[1:4,0] = cols[:,0]
    else:
        if typedeg == 'std':
            Nstepcols = np.int(Nsteps*1. / (Ncols-1.))
            iicol = 0
            for icol in range(Ncols-1):
                dcolors = (cols[:,icol+1]- cols[:,icol])/(Nstepcols-1.)
# Toavoid repetition of the color
                if icol == 0: 
                    ibeg = 0
                else:
                    ibeg = 1
                for i in range(ibeg,Nstepcols):
                    colordeg[0,iicol] = iicol*1.
                    colordeg[1:4,iicol] = cols[:,icol] + dcolors*i
                    iicol = iicol + 1
            Nfincol = iicol-1
            colordeg[0,:] = colordeg[0,:]/(Nfincol*1.)

        elif typedeg == 'vals':
            if values is None:
                print errormsg
                print '  ' + fname + ": type '" + typedeg + "' require values !!"
                quit(-1)
            Nvals = len(values)
            if Nvals != Ncols:
                print errormsg
                print '  ' + fname + ': different number of values:', Nvals,         \
                  'and colors:', Ncols, '!!'
                print '    provided values:', values
                print '    provided colors:', cols
                quit(-1)
            TOTrange = values[Nvals-1] - values[0]
            iicol = 0
            for icol in range(Ncols-1):
                pairange = values[icol+1] - values[icol]
                drange = pairange / TOTrange
                Nstepcols = np.int(Nsteps*drange)
                dcolors = (cols[:,icol+1]-cols[:,icol])/(Nstepcols-1.)
# To avoid repetition of the color
                if icol == 0: 
                    ibeg = 0
                else:
                    ibeg = 1
                for i in range(ibeg,Nstepcols):
                    colordeg[0,iicol] = values[icol]+i*pairange/(Nstepcols-1)
                    colordeg[1:4,iicol] = cols[:,icol] + dcolors*i
                    iicol = iicol + 1
            Nfincol = iicol - 1
        else:
            print errormsg
            print '  ' + fname + ": degradation type '" + typedeg + "' not ready !!"
            quit(-1)

    degcolor = np.zeros((4,Nfincol), dtype=np.float)
    degcolor = colordeg[:,0:Nfincol+1]

    return degcolor

def colhex_dec(col):
    """ Function to pas a hexadecimal (#[RR][GG][BB]; 00-64, 0A-FF) color to decimal ([0.,1.])
      col= '#'[RR][GG][BB] hexadecimal color string
      >>>colhex_dec('#000000')
      [0.0, 0.0, 0.0]
      >>>colhex_dec('#00FF00')
      [0.0, 1.0, 0.0]
      >>>colhex_dec('#3264EE')
      [0.19607843137254902, 0.39215686274509803, 0.9333333333333333]
    """
    fname = 'colhex_dec'
    hexred = col[1:3]
    hexgreen = col[3:5]
    hexblue = col[5:7]

    deccol = [int(hexred, 16)/255., int(hexgreen, 16)/255., int(hexblue, 16)/255.,]

    return deccol

def coldec_hex(col):
    """ Function to pas a decimal ([r,g,b]; [0.,1.]) color to hexadecimal (#[RR][GG][BB], 00-64, 0A-FF)
      col= '#'[RR][GG][BB] hexadecimal color string
      >>>coldec_hex([0.0, 0.0, 0.0])
      #000000
      >>>coldec_hex([0.0, 1.0, 0.0])
      #00FF00
      >>>coldec_hex([0.19607843137254902, 0.39215686274509803, 0.9333333333333333])
      #3264EE
    """
    fname = 'coldec_hex'

    hexred = '{0:X}'.format(int(col[0]*255)).zfill(2)
    hexgreen = '{0:X}'.format(int(col[1]*255)).zfill(2)
    hexblue = '{0:X}'.format(int(col[2]*255)).zfill(2)

    if hexred == '0': hexred = '00' 
    if hexgreen == '0': hexgreen = '00'
    if hexblue == '0': hexblue = '00'

    hexcol = '#' + hexred + hexgreen + hexblue

    return hexcol

def str_list(string, cdiv):
    """ Function to obtain a list from a string givin a split character
      string= String from which to obtain a list ('None' for None)
      cdiv= character to use to split the string
    >>> str_list('1:@#:$:56', ':')
    ['1', '@#', '$', '56']
    >>> str_list('1@#$56', ':')
    ['1@#$56']
    """
    fname = 'str_list'

    if string.find(cdiv) != -1:
        listv = string.split(cdiv)
    else:
        if string == 'None':
            listv = None
        else:
            listv = [string]

    return listv

def str_list_k(string, cdiv, kind):
    """ Function to obtain a list of types of values from a string giving a split character
      string= String from which to obtain a list ('None' for None)
      cdiv= character to use to split the string
      kind= kind of desired value (as string like: 'np.float', 'int', 'np.float64', ....)
    >>> str_list_k('1:@#:$:56', ':', 'S')
    ['1', '@#', '$', '56']
    >>> str_list_k('1:3.4:12.3', ':', 'np.float64')
    [1.0, 3.3999999999999999, 12.300000000000001]
    """
    fname = 'str_list'

    if string.find(cdiv) != -1:
        listv = string.split(cdiv)
    else:
        if string == 'None':
            listv = None
        else:
            listv = [string]

    if listv is not None:
        finalist = []
        for lv in listv:
            finalist.append(typemod(lv, kind))
    else:
        finalist = None

    return finalist

def stagger_unstagger(varv, dndims, udims):
    """ Function to de-stagger a variable
      varv= values of the variable to de-stagger
      dndims = dn[x/y/z/t] list of the names of the dimenions of the variable      
      udims = ud[x/y/z/t] unstaggered dictionary with the dimenions of the variable

    >>> mat = np.arange((20), dtype=np.float).reshape(5,4)
    >>> dmat = ['dystaggered','dx']
    >>> unstagdims = {'dy': 4, 'dx': 4}
    >>> stagger_unstagger(mat, dmat, unstagdims)
    [[  2.   3.   4.   5.]
     [  6.   7.   8.   9.]
     [ 10.  11.  12.  13.]
     [ 14.  15.  16.  17.]]
    """
    fname = 'stagger_unstagger'

    udndims = list(udims.keys())

    idim = 0
    vdstaggered = {}
    newdims = []

    idim = 0
    for vd in dndims:
        if searchInlist(udndims, vd):
            if varv.shape[idim] - 1 == udims[vd]:
                vdstaggered[vd] =  varv.shape[idim] - 1
            else:
                vdstaggered[vd] = varv.shape[idim]
        else:
            vdstaggered[vd] = varv.shape[idim] - 1
            print '  ' + fname + ": new dimension '" + vd + "' with length :",       \
              varv.shape[idim], 'as staggered dim'
        newdims.append(vdstaggered[vd])
        idim = idim + 1

    if len(vdstaggered) > 1:
        destagger_varv = np.zeros(tuple(newdims), dtype=np.float)

        ndim = 0
        upstagslc = []
        downstagslc = []
        for vd in dndims:
            idim = dndims.index(vd)
            if vdstaggered[vd] != varv.shape[idim]:
                upstagslc.append(slice(1,varv.shape[idim]))
                downstagslc.append(slice(0,varv.shape[idim]-1))
            else:
                upstagslc.append(slice(0,varv.shape[idim]))
                downstagslc.append(slice(0,varv.shape[idim]))
        destagger_varv = 0.5*(varv[tuple(upstagslc)] + varv[tuple(downstagslc)])
    
        return destagger_varv
    else:
        return varv

def CFmonthU_daysU(datev,tunits):
    """ Function to transform from a CF date series with units as 'months since [DATE]' to 'days since [DATE]'
      datev= series of dates to transform
      tunits= time units of the dates
    >>> CFmonthU_daysU([1,2,3,4,5,6,17,18,], 'months since 1979-12-01 00:00:00')
    array([  31.,   62.,   91.,  122.,  152.,  183.,  517.,  548.])
    """
    import datetime as dt
    fname = 'CFmonthU_secondsU'

    if tunits.find('month') == -1:
        print errormsg
        print '  ' + fname + ": times do not have 'months' as units !!"
        print "    they have: '" + tunits + "'"
        quit(-1)

    secstunits = tunits.replace('_',' ').split(' ')
    newtunits = 'days'
    for itsec in range(1,len(secstunits)):
        newtunits = newtunits + ' ' + secstunits[itsec]

    yr = np.int(secstunits[2].split('-')[0])
    mm = np.int(secstunits[2].split('-')[1])
    dd = np.int(secstunits[2].split('-')[2])

    if tunits.find(':') != -1:
        hh = np.int(secstunits[3].split(':')[0])
        mi = np.int(secstunits[3].split(':')[1])
        ss = np.int(secstunits[3].split(':')[2])
    else:
        hh = 0
        mi = 0
        ss = 0

    refT = dt.datetime(yr, mm, dd, hh, mi, ss)

    refm = 0
    newdatev = np.zeros((len(datev)), dtype=np.float)
    for itv in range(len(datev)):
        while mm + datev[itv] - refm > 12.:
            yr = int(yr + 1)
            refm = refm + 12

        newmm = mm + datev[itv] - refm
        if newmm/int(newmm) - 1. != 0.:
            print warnmsg
            print '  ' + fname + ': fractional months values', newmm, '!!'
            mmdec = newmm - int(newmm)*1.
            newmm = np.int(newmm)
            if newmm + 1 > 12:
                daysnextmon = 31
            else:
                daysnextmon = days_month(yr,newmm+1)
            newdd = daysnextmon*mmdec 
            dddec = newdd - int(newdd)*1.
            newdd = int(newdd)
            newhh = dddec*24.
            hhdec = newhh - int(newhh)*1.
            newhh = int(newhh)
            newmi = hhdec*60.
            midec = newmi - int(newmi)*1.
            newmi = int(newmi)
            newss = midec*60.
            ssdec = newss - int(newss)*1.
            newss = int(newss)
            if ssdec != 0.: print '    residual seconds after adjustmen:', ssdec
        else:
            newmm = np.int(newmm)
            newdd = np.int(dd)
            newhh = np.int(hh)
            newmi = np.int(mi)
            newss = np.int(ss)

        idate = dt.datetime(yr, newmm, newdd, newhh, newmi, newss)
        
        diffT = idate - refT
        if searchInlist(dir(dt.timedelta), 'total_seconds'):
            newdatev[itv] = diffT.total_seconds()/(3600.*24.)
        else:
            newdatev[itv] = diffT.days() + diffT.seconds()/(3600.*24)

    return newdatev, newtunits

def get_configuration(configfile,glob):
    """ Function to get the configuration from an ASCII external file with [arg] = [value]
     returned as a dictionay as configuration[arg] = [value]
     '#' for comentaries in the ASCII file
    configfile= ASCII file to read
    glob= do we want vairables as global ones? (True/False)
    """
    fname = 'get_configuration'

    if not os.path.isfile(configfile):
        print errormsg
        print '  ' + fmsg + ': configuratio file "' + filen + '" does not exist !!'
        quit(-1)    

    of = open(configfile, 'r')

    config = {}
    for line in of:
        if line[0:1] != '#' and len(line) > 1:
            arg = line.replace('\n','').split('=')[0].replace(' ','')
            val = line.replace('\n','').split('=')[1].replace(' ','')
            config[arg] = val
# From: http://stackoverflow.com/questions/11553721/using-a-string-variable-as-a-variable-name
             #exec( "pyHOME = '" + conf['pyHOME'] + "'")

# From: http://stackoverflow.com/questions/1373164/how-do-i-create-a-variable-number-of-variables-in-python
            if glob: globals()[arg] = val

    of.close()

    return config

#conf = get_configuration('model_graphics.dat',False)
#print pyHOME

def printing_dictionary(dictv):
    """ Function to print the content of a dictionary
      dictv= dictionary to print
    """
    fname = 'printing_dictionary'

    for key in dictv.keys():
        print '    # ' + key + ':', dictv[key]

    return

def get_specdictionary_HMT(dictv,H='',M='',T=''):
    """ Function to get specific values from a dictionary by selcting that keys with H*M*T
      dictv= dictionary with the values
      H= head of the key (empty for nothing)
      M= middle of the key (empty for nothing)
      T= tail of the key (empty for nothing)
    >>> dictrom = {'i':1, 'ii':2, 'iii':3, 'iv':4, 'v':5, 'vi':6, 'vii':2, 'viii':8, 'ix':9, 'x':10, 'xi':11 }
    >>> get_specdictionary_HTM(dictrom,H='i')
    {'ii': 2, 'ix': 9, 'iii': 3, 'i': 1, 'iv': 4}
    >>> get_specdictionary_HTM(dictrom,M='i')
    {'vii': 2, 'iii': 3, 'viii': 8}
    >>> get_specdictionary_HTM(dictrom,T='i')
    {'xi': 11, 'i': 1, 'vi': 6, 'vii': 2, 'ii': 2, 'viii': 8, 'iii': 3}
    >>> get_specdictionary_HMT(dictrom,H='v',M='i')
    {'vii': 2, 'viii': 8}
    >>> get_specdictionary_HMT(dictrom,H='x',T='i')
    {'xi': 11}
    >>> get_specdictionary_HMT(dictrom,M='i',T='x')
    None
    >>> get_specdictionary_HMT(dictrom,H='v',M='i',T='i')
    {'vii': 2, 'viii': 8}
    """
    fname = 'get_specdictionary_HMT'
    
    LH = len(H)
    LM = len(M)
    LT = len(T)

    dictkeys = dictv.keys()

    #print '  ' + fname + ': H=',H,'M=',M,'T=',T,'_______'
    # Looking for heads
    if LH > 0:
        Hkeys = []
        for key in dictkeys:
            if key[0:LH] == H: Hkeys.append(key)
        #print '    Hkeys:', Hkeys
    # Looking for middles
    if LM > 0:
        Mkeys = []
        for key in dictkeys:
            Lkey = len(key)
            if len(key[1:Lkey-1]) < LM:
                print warnmsg
                print '  ' + fname + ": key '" + key + "' too short for M='" + M +   \
                  "' !!"
            if key[1:Lkey-1].find(M) != -1: Mkeys.append(key)
        #print '    Mkeys:', Mkeys
    # Looking for tails
    if LT > 0:
        Tkeys = []
        for key in dictkeys:
            Lkey = len(key)
            if key[Lkey-LT:Lkey+1] == T: Tkeys.append(key)
        #print '    Tkeys:', Tkeys

    # Coincidences
    if LH > 0:
        if LM > 0:
            coinlistA = list(set(Hkeys).intersection(set(Mkeys)))
            if LT > 0:
                coinlist = list(set(coinlistA).intersection(set(Tkeys)))
            else:
                coinlist = list(coinlistA)
        elif LT > 0:
            coinlist = list(set(Hkeys).intersection(set(Tkeys)))
        else:
            coinlist = list(Hkeys)
    elif LM > 0:
        if LT > 0:
            coinlist = list(set(Mkeys).intersection(set(Tkeys)))
        else:
            coinlist = list(Mkeys)
    elif LT > 0:
        coinlist = list(Tkeys)

    if len(coinlist) > 0:
        newdictv = {}
        for key in coinlist:
            newdictv[key] = dictv[key]
    else:
        newdictv= None

    return newdictv

def dictKeysVals_stringList(dictv,cD=',',cK='@',cV='|'):
    """ Function to provide strings from a dictionary with keys which contain values of lists
      dictv= dictionary with the values
      cD= character to use to separate keys
      cK= character to use to separate keys from their values
      cV= character to use to separate the values for each key
    >>> dictvals = {'Spain': ['Madrid', 'Santander', 'Sevilla', 'Toledo'], 'France': ['Paris', 'Marseille', 'Tolouse']}
    >>> dictKeysVals_stringList(dictvals)
    Spain@Madrid|Santander|Sevilla|Toledo,France@Paris|Marseille|Tolouse
    """
    fname = 'dictKeysVals_stringList'

    ik = 0

    if len(dictv.keys()) < 1:
        print errormsg
        print '  ' + fname + ': empty dictionary !!'
        quit(-1)

    string = ''
    for key in dictv.keys():
        if ik == 0:
            string = key + cK
        else:
            string = string + cD + key + cK

        dictval = dictv[key]
        if type(dictval) == type(list([1,2])):
            iv = 0
            for val in dictval:
                if iv == 0:
                    string = string + val
                else:
                    string = string + cV + val
                iv = iv + 1
        elif type(dictval) == type('A'):
            string = string + dictval

        ik = ik + 1
    return string

def stringList_dictKeysVals(string,cD=',',cK='@',cV='|'):
    """ Function to provide a dictionary with keys which contain values of lists from a string
      string= dictionary with the values
      cD= character to use to separate keys
      cK= character to use to separate keys from their values
      cV= character to use to separate the values for each key
    >>> stringv = 'Spain@Madrid|Santander|Sevilla|Toledo,France@Paris|Marseille|Tolouse'
    >>> dictKeysVals_stringList(stringv)
    {'Spain': ['Madrid', 'Santander', 'Sevilla', 'Toledo'], 'France': ['Paris', 'Marseille', 'Tolouse']}
    """
    fname = 'stringList_dictKeysVals'

    dictv = {}

    dvs = string.split(cD)
    for dv in dvs:
        key = dv.replace('\n','').split(cK)[0]
        vals = dv.replace('\n','').split(cK)[1].split(cV)

        dictv[key] = vals

    return dictv

class Capturing(list):
    """ Class to capture the standard output from a function
      from: http://stackoverflow.com/questions/16571150/how-to-capture-stdout-output-from-a-python-function-call
      Usage:

      'output' is now a list containing the lines printed by the function call.
      >>> romdict = {'i': 1, 'ii': 2, 'iii': 3, 'iv': 4, 'v':5, 'vi':6, 'vii':7, 'viii':8, 'ix': 9, 'x':10}
      >>> with Capturing() as output:
      >>>    printing_dictionary(romdict)
      >>> print output
      ['    # i: 1', '    # ii: 2', '    # iii: 3', '    # iv: 4']
    """
    def __enter__(self):
        self._stdout = sys.stdout
        sys.stdout = self._stringio = StringIO()
        return self
    def __exit__(self, *args):
        self.extend(self._stringio.getvalue().splitlines())
        sys.stdout = self._stdout

def search_sec_list(listv,sec):
    """ Function to provide the values and indices on a list which matches a section of a string
      listv= list to find matches
      sec= section to search for
    >>> romlist = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x', 'xi']
    >>> search_sec_list(romlist,'ii')
    (['ii', 'iii', 'vii', 'viii'], [1, 2, 6, 7])
    """
    fname = 'search_sec_list'

    matches = []
    locs = []
    il = 0
    for string in listv:
        if string.find(sec) != -1:
            matches.append(string)
            locs.append(il)
        il = il + 1

    if len(locs) < 1:
        matches = None
        locs = None

    return matches, locs

def dictvar_listS(listv, dictv, Dc=',', DVs=':'):
    """ Function to provide a Dc string separated list of DVs separated [key] [value] couples following a list of keys
      listv: list of keys from dictionary to use
      dictv= dictionary with values to build the string
      Sc: character to separate key values
      DVs: character to separate key-value couples
    >>> romdict = {'i': 1, 'ii': 2, 'iii': 3, 'iv': 4, 'v':5, 'vi':6, 'vii':7, 'viii':8, 'ix': 9, 'x':10}
    >>> dictvar_listS(['i', 'iv', 'vii'],romdict,',',':')
    i:1,iv:4,vii:7
    """
    fname = 'dictvar_listS'
    ik = 0
    for key in listv:
        if not dictv.has_key(key):
            print errormsg
            print '  ' + fname + ": dictionary does not have key '" + key + "' !!" 
            print '    available keys:', dictv.keys()
            quit(-1)
        else:
            if ik == 0:
                stringv = str(key) + DVs + str(dictv[key])
            else:
                stringv = stringv + Dc + str(key) + DVs + str(dictv[key])

            ik = ik + 1

    return stringv

def stringS_dictvar(stringv, Dc=',', DVs=':'):
    """ Function to provide a dictionary from a Srting which list of DVs separated [key] [value] couples
      stringv: String with a dictionary content as [key1][DVs][val1][Dc][key2][DVs][Val2][Dc]...
      Sc: character to separate key values
      DVs: character to separate key-value couples
    >>> stringS_dictvar('i:1,iv:4,vii:7',',',':')
    {'i': '1', 'vii': '7', 'iv': '4'}
    """
    fname = 'stringS_dictvar'
    dictv = {}
    for Svals in stringv.split(Dc):
        keyn = Svals.split(DVs)[0]
        valn = Svals.split(DVs)[1]
        dictv[keyn] = valn

    return dictv

def list_coincidences(listA, listB):
    """ Function to provide the  coincdences between two lists
      listA= list with values
      listB= list with values to match with
    >>> list_coincidences(range(10),range(8,15))
    [8, 9], [8, 9], [0, 1]
    """
    fname = 'list_coincidences'

    coinc = list(set(listA).intersection(set(listB)))
    Acoin = []
    Bcoin = []

    # Positions in each list
    for coinv in coinc:
        Acoin.append(listA.index(coinv))
        Bcoin.append(listB.index(coinv))

    return coinc, Acoin, Bcoin

def list_differences(listA, listB):
    """ Function to provide the differences between two lists
      listA= list with values to match with
      listB= list with values
    >>> list_coincidences(range(10),range(8,15))
    [10, 11, 12, 13, 14], [2, 3, 4, 5, 6]
    """
    fname = 'list_differences'

    # Not coincident of B in A
    diffs = list(set(listB).difference(set(listA)))
    Bdiff = []

    for diff in diffs:
        Bdiff.append(listB.index(diff))

    return diffs, Bdiff


def coincident_CFtimes(tvalB, tunitA, tunitB):
    """ Function to make coincident times for two different sets of CFtimes
    tvalB= time values B
    tunitA= time units times A to which we want to make coincidence
    tunitB= time units times B
    >>> coincident_CFtimes(np.arange(10),'seconds since 1949-12-01 00:00:00',
      'hours since 1949-12-01 00:00:00')
    [     0.   3600.   7200.  10800.  14400.  18000.  21600.  25200.  28800.  32400.]
    >>> coincident_CFtimes(np.arange(10),'seconds since 1949-12-01 00:00:00',
      'hours since 1979-12-01 00:00:00')
    [  9.46684800e+08   9.46688400e+08   9.46692000e+08   9.46695600e+08
       9.46699200e+08   9.46702800e+08   9.46706400e+08   9.46710000e+08
       9.46713600e+08   9.46717200e+08]
    """
    import datetime as dt
    fname = 'coincident_CFtimes'

    tunitA = tunitA.replace('_',' ')
    tunitB = tunitB.replace('_',' ')

    trefA = tunitA.split(' ')[2] + ' ' + tunitA.split(' ')[3]
    trefB = tunitB.split(' ')[2] + ' ' + tunitB.split(' ')[3]
    tuA = tunitA.split(' ')[0]
    tuB = tunitB.split(' ')[0]

#    if tuB == 'months':
#        tvalB, tunitB  = gen.CFmonthU_daysU(tvalB, tunitB)
#        tuB = tunitB.split(' ')[0]

    if tuA != tuB:
        if tuA == 'microseconds':
            if tuB == 'microseconds':
                tB = tvalB*1.
            elif tuB == 'seconds':
                tB = tvalB*10.e6
            elif tuB == 'minutes':
                tB = tvalB*60.*10.e6
            elif tuB == 'hours':
                tB = tvalB*3600.*10.e6
            elif tuB == 'days':
                tB = tvalB*3600.*24.*10.e6
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'seconds':
            if tuB == 'microseconds':
                tB = tvalB/10.e6
            elif tuB == 'seconds':
                tB = tvalB*1.
            elif tuB == 'minutes':
                tB = tvalB*60.
            elif tuB == 'hours':
                tB = tvalB*3600.
            elif tuB == 'days':
                tB = tvalB*3600.*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'minutes':
            if tuB == 'microseconds':
                tB = tvalB/(60.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/60.
            elif tuB == 'minutes':
                tB = tvalB*1.
            elif tuB == 'hours':
                tB = tvalB*60.
            elif tuB == 'days':
                tB = tvalB*60.*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'hours':
            if tuB == 'microseconds':
                tB = tvalB/(3600.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/3600.
            elif tuB == 'minutes':
                tB = tvalB/60.
            elif tuB == 'hours':
                tB = tvalB*1.
            elif tuB == 'days':
                tB = tvalB*24.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        elif tuA == 'days':
            if tuB == 'microseconds':
                tB = tvalB/(24.*3600.*10.e6)
            elif tuB == 'seconds':
                tB = tvalB/(24.*3600.)
            elif tuB == 'minutes':
                tB = tvalB/(24.*60.)
            elif tuB == 'hours':
                tB = tvalB/24.
            elif tuB == 'days':
                tB = tvalB*1.
            else:
                print errormsg
                print '  ' + fname + ": combination of time untis: '" + tuA +        \
                  "' & '" + tuB + "' not ready !!"
                quit(-1)
        else:
            print errormsg
            print '  ' + fname + ": time untis: '" + tuA + "' not ready !!"
            quit(-1)
    else:
        tB = tvalB*1.

    if trefA != trefB:
        trefTA = dt.datetime.strptime(trefA, '%Y-%m-%d %H:%M:%S')
        trefTB = dt.datetime.strptime(trefB, '%Y-%m-%d %H:%M:%S')

        difft = trefTB - trefTA
        diffv = difft.days*24.*3600.*10.e6 + difft.seconds*10.e6 + difft.microseconds
        print '  ' + fname + ': different reference refA:',trefTA,'refB',trefTB
        print '    difference:',difft,':',diffv,'microseconds'

        if tuA == 'microseconds':
            tB = tB + diffv
        elif tuA == 'seconds':
            tB = tB + diffv/10.e6
        elif tuA == 'minutes':
            tB = tB + diffv/(60.*10.e6)
        elif tuA == 'hours':
            tB = tB + diffv/(3600.*10.e6)
        elif tuA == 'days':
            tB = tB + diffv/(24.*3600.*10.e6)
        else:
            print errormsg
            print '  ' + fname + ": time untis: '" + tuA + "' not ready !!"
            quit(-1)

    return tB

def same_shape(mat1,mat2,quitval=True):
    """ Function to check if two matrices have the same shape
      mat1,2= matrices to check
    """
    fname = 'same_shape'

    same = True

    shape1 = mat1.shape
    shape2 = mat2.shape

    Ndims1 = len(shape1)
    Ndims2 = len(shape2)

    if Ndims1 != Ndims2:
        print errormsg
        print '  ' + fname + ': mat1 and mat2 have different number of dimensions !!'
        print '    Ndims mat 1:', Ndims1,' Ndims mat2:', Ndims2
        print '    shape mat 1:', shape1, 'mat 2:', shape2
        same = False
        if quitval: quit(-1)

    for idn in range(Ndims1):
        if shape1[idn] != shape2[idn]:
            print errormsg
            print '  ' +fname+ ': length of',idn,'diemsion in mat1 and mat2 differ !!'
            print '    Length mat 1:', shape1[idn],' Length mat2:', shape2[idn]
            print '    shape mat 1:', shape1, 'mat 2:', shape2
            same = False
            if quitval: quit(-1)
    
    return same

def index_flatten_mat(index,Ldims):
    """ Function to provide the matrix coordinates of an index from its flatten version
      index= index of the matrix's flatten version
      Ldims= lengths of the dimensions of the matrix
    >>> index_flatten_mat(17,[3,3,3])
    [1 2 2]
    """
    fname = 'index_flatten_mat'
    Ndims = len(Ldims)

    if index < Ldims[Ndims-1]:
        indices = np.zeros((len(Ldims)), dtype=int)
        indices[Ndims-1] = index
    else:
        for idn in range(1,Ndims):
            indices = np.zeros((len(Ldims)), dtype=int)
            subsize = int(np.prod(Ldims[Ndims-idn-1:Ndims]))
            # Reaching depth level in the matrix
            if subsize > idn:
                # Getting index for each dimension from the depth
                prevsubsizeind = index
                for idnd in range(Ndims-idn, Ndims):
                    prevsubsize = int(np.prod(Ldims[idnd:Ndims]))
                    Nprevsubsize = int(prevsubsizeind/prevsubsize)
                    indices[idnd-1] = Nprevsubsize
                    prevsubsizeind = prevsubsizeind - Nprevsubsize*prevsubsize
                # Final index
                indices[Ndims-1] = prevsubsizeind
                
    return indices

def oper_submatrix(mat,dimns,submatval,oper,opdims):
    """ Function to perform an operation of a given matrix along a sub-set of values along its dimensions
      mat= matrix with values
      dimns= names of the matrix dimensions
      submatval= matrix value to use with some dimensions reduced
      oper= operation to perform
        'sumc', add [val]
        'subc', substraction [val]
        'mulc', multiply by [val] 
        'divc', divide by [val] 
        'lowthres',[val]: modify all values below [val] to submatval
        'upthres',[val]: modify all values above [val] to submatval
      opdims= dimensions of the operation
      >>> mat = np.arange(12).reshape(3,2,2)
      >>> dimsn = ['time', 'lon', 'lat']
      >>> oper_submatrix(mat, dimsn, np.matrix([[1., 1.],[2., 2.]]), 'sumc', ['time'])
      [[[ 1  2]
       [ 4  5]]

       [[ 5  6]
        [ 8  9]]

       [[ 9 10]
        [12 13]]
    """
    fname = 'oper_submatrix'

    operations = ['sumc', 'subc', 'mulc', 'divc', 'lowthres', 'upthres']
    matype = mat.dtype

    if oper.find(',') != -1:
        opern = oper.split(',')[0]
        val = retype(oper.split(',')[1], matype)
    else:
        opern = oper

    Ndims = len(dimns)
    # Getting the slice, on '-1', dimension to operate along
    # Keeping in 'ldimuse': length of the dimensions of the values to use
    # Keeping in 'ldimop': length of the dimension to operate along
    idim = 0
    ldimuse = []
    ldimop = []
    slicevals = []

    for dimn in dimns:
        if searchInlist(opdims,dimn):
            for dn in opdims:
                if dimn == dn:
                    slicevals.append(-1)
                    ldimop.append(mat.shape[idim])
                    break
        else:
            slicevals.append(mat.shape[idim])
            ldimuse.append(mat.shape[idim])
        idim = idim + 1

    if len(ldimop) == 0:
        print errormsg
        print '  ' + fname + ': no dimensions found for the operation !!'
        print '    dimensions in file:', dimns
        print '    dimensions for the operation:', opdims
        quit(-1)

    Ndop = len(opdims)
    Ntotdims = np.prod(ldimop)

    # Checking for coincidence in shapes
    try:
        with Capturing() as output:
            same_shape(submatval,np.zeros(ldimuse))
    except:
        print errormsg
        print '  ' + fname + ': shape of matrix to use and shape of values to ' +    \
          'operate differ!!'
        for sout in output: print sout
        quit(-1)

    # Operation
    newmat = np.zeros(tuple(mat.shape), dtype=mat.dtype)
    for ijk in range(Ntotdims):
        ijkop = -1
        opslice = []
        idcalc = index_flatten_mat(ijk,ldimop)
        for idn in range(Ndims):
            if slicevals[idn] == -1:
                ijkop = ijkop + 1

                opslice.append(idcalc[ijkop])
            else:
                opslice.append(slice(0,slicevals[idn]))

        if opern == 'sumc':
            newmat[tuple(opslice)] = mat[tuple(opslice)] + submatval
        elif opern == 'subc':
            newmat[tuple(opslice)] = mat[tuple(opslice)] - submatval
        elif opern == 'mulc':
            newmat[tuple(opslice)] = mat[tuple(opslice)] * submatval
        elif opern == 'divc':
            newmat[tuple(opslice)] = mat[tuple(opslice)] / submatval
        elif opern == 'lowthres':
            newmat[tuple(opslice)] = np.where(mat[tuple(opslice)] < val, submatval,  \
              mat[tuple(opslice)])
        elif opern == 'upthres':
            newmat[tuple(opslice)] = np.where(mat[tuple(opslice)] > val, submatval,  \
              mat[tuple(opslice)])
        else:
            print errormsg
            print '  ' + fname + ": operation '" + opern + "' not ready !!"
            print '    ready operations:', operations
            quit(-1)

    return newmat

def ASCII_to(text,to,nochg=None):
    """ Function to provide the equivalence text to a given lenguage omitting certain characters
      text= text to transform
      to= language to use
        'tex': LaTeX
      nochg: a list with characters to be omitted
    >>> ASCII_to('à$353\pol', 'tex')
    \`a\$353\textbackslashpol
    >>> ASCII_to('à$353\pol', 'tex', ['$'])
    \`a$353\textbackslashpol
    >>> NOchange = ['_', '^', '\\', '&', '$']
    >>> ASCII_to('$[spatial\ cloud\ cover]^{sub-section}_{cld\ >\ 80000.}\ (%)$', 'tex', NOchange)
    $[spatial\ cloud\ cover]^{sub-section}_{cld\ >\ 80000.}\ (\%)$
    """
    fname = 'ASCII_to'
    langs = ['tex']

    #From: http://tex.stackexchange.com/questions/14872/croatian-serbian-letters-in-cv-problem
    # From: https://www.dpg-tagung.de/dd14/infochars.html?language=en
    # From: http://mirror.neu.edu.cn/CTAN/info/symbols/comprehensive/symbols-a4.pdf
    texchars = {'\\': '\\textbackslash', \
      'á': "\\'a", 'é': "\\'e", 'í': "\\'i", 'ó': "\\'o", 'ú': "\\'u",               \
      'ć': "\\'c", 'ǵ': "\\'g", 'ḱ': "\\'k", 'ĺ': "\\'l", 'ḿ': "\\'m", 'ń': "\\'n",  \
      'ṕ': "\\'p", 'ŕ': "\\'r", 'ś': "\\'s", 'ẃ': "\\'w", 'ý': "\\'y", 'ź': "\\'z",  \
      'à': "\\`a", 'è': "\\`e", 'ì': "\\`i", 'ò': "\\`o", 'ù': "\\`u",               \
      'ǹ': "\\`n", 'ẁ': "\\`w", 'ỳ': "\\`y",                                         \
      'â': "\\^a", 'ê': "\\^e", 'î': "\\^i", 'ô': "\\^o", 'û': "\\^u",               \
      'ĉ': "\\^c", 'ĝ': "\\^g", 'ĥ': "\\^h", 'ĵ': "\\^j", 'ŝ': "\\^s", 'ŵ': "\\^w",  \
      'ŷ': "\\^y", 'ẑ': "\\^z",                                                      \
      'ä': '\\"a', 'ë': '\\"e', 'ï': '\\"i', 'ö': '\\"o', 'ü': '\\"u',               \
      'ḧ': '\\"h', 'ẗ': '\\"t', 'ẅ': '\\"w', 'ẍ': '\\"x', 'ÿ': '\\"y',               \
      'ă': '\\u{a}', 'ĕ': '\\u{e}', 'ĭ': '\\u{i}', 'ŏ': '\\u{o}', 'ŭ': '\\u{u}',     \
      'ğ': '\\u{g}',                                                                 \
      'ǎ': '\\v{a}', 'ě': '\\v{e}', 'ǐ': '\\v{i}', 'ǒ': '\\v{o}', 'ǔ': '\\v{u}',     \
      'č': '\\v{c}', 'ď': '\\v{d}', 'ǧ': '\\v{g}', 'ȟ': '\\v{h}', 'ǰ': '\\v{j}',     \
      'ǩ': '\\v{k}', 'ľ': '\\v{l}', 'ň': '\\v{n}', 'ř': '\\v{r}', 'š': '\\v{s}',     \
      'ť': '\\v{t}', 'ž': '\\v{z}',                                                  \
      'å': '\\a{}', 'ů': '\\r{u}', 'ẘ': '\\r{w}', 'ẙ': '\\r{y}',                     \
      'ã': '\\~{a}', 'ẽ': '\\~{e}', 'ĩ': '\\~{i}', 'õ': '\\~{o}', 'ũ': '\\~{u}',     \
      'ñ': '\\~{n}', 'ṽ': '\\~{v}', 'ỹ': '\\~{y}',                                   \
      'ç': '\\c{c}', 'ḑ': '\\c{d}', 'ȩ': '\\c{e}', 'ģ': '\\c{g}', 'ḩ': '\\c{h}',     \
      'ķ': '\\c{k}', 'ļ': '\\c{l}', 'ņ': '\\c{n}', 'ŗ': '\\c{r}', 'ş': '\\c{s}',     \
      'ţ': '\\c{t}',                                                                 \
      'ł': '\\l{}', 'ø': '\\o{}', 'đ': '\\dj{}', 'ß': '\\ss{}',                      \
      'æ': '\\ae{}', 'œ': '\\oe{}',                                                  \
      'Á': "\\'A", 'É': "\\'E", 'Í': "\\'I", 'Ó': "\\'O", 'Ú': "\\'U",               \
      'Ć': "\\'C", 'Ǵ': "\\'G", 'Ḱ': "\\'K", 'Ĺ': "\\'L", 'Ḿ': "\\'M", 'Ń': "\\'N",  \
      'Ṕ': "\\'P", 'Ŕ': "\\'R", 'Ś': "\\'S", 'Ẃ': "\\'W", 'Ý': "\\'Y", 'Ź': "\\'Z",  \
      'À': "\\`A", 'È': "\\`E", 'Ì': "\\`I", 'Ò': "\\`O", 'Ù': "\\`U",               \
      'Ǹ': "\\`N", 'Ẁ': "\\`W", 'Ỳ': "\\`Y",                                         \
      'Â': "\\^A", 'Ê': "\\^E", 'Î': "\\^I", 'Ô': "\\^O", 'Û': "\\^U",               \
      'Ĉ': "\\^C", 'Ĝ': "\\^G", 'Ĥ': "\\^H", 'Ĵ': "\\^J", 'Ŝ': "\\^S", 'Ŵ': "\\^W",  \
      'Ŷ': "\\^Y", 'Ẑ': "\\^Z",                                                      \
      'Ä': '\\"A', 'Ë': '\\"E', 'Ï': '\\"I', 'Ö': '\\"O', 'Ü': '\\"U',               \
      'Ḧ': '\\"H', 'Ẅ': '\\"W', 'Ẍ': '\\"X', 'Ÿ': '\\"Y',                            \
      'Ă': '\\u{A}', 'Ĕ': '\\u{E}', 'Ĭ': '\\u{I}', 'Ŏ': '\\u{O}', 'Ŭ': '\\u{U}',     \
      'Ğ': '\\u{G}', 'Ž': '\\u{Z}',                                                  \
      'Ǎ': '\\v{A}', 'Ě': '\\v{E}', 'Ǐ': '\\v{I}', 'Ǒ': '\\v{O}', 'Ǔ': '\\v{U}',     \
      'Č': '\\v{C}', 'Ď': '\\v{D}', 'Ǧ': '\\v{G}', 'Ȟ': '\\v{H}', 'Ǩ': '\\v{K}',     \
      'Ľ': '\\v{L}', 'Ň': '\\v{N}', 'Ř': '\\v{R}', 'Š': '\\v{S}', 'Ť': '\\v{T}',     \
      'Ž': '\\v{Z}',                                                                 \
      'Å': '\\AA{}', 'Ů': '\\r{U}',                                                  \
      'Ã': '\\~{A}', 'Ẽ': '\\~{E}', 'Ĩ': '\\~{I}', 'Õ': '\\~{O}', 'Ũ': '\\~{U}',     \
      'Ñ': '\\~{N}', 'Ṽ': '\\~{V}', 'Ỹ': '\\~{Y}',                                   \
      'Ç': '\\c{C}', 'Ḑ': '\\c{D}', 'Ȩ': '\\c{E}', 'Ģ': '\\c{G}', 'Ḩ': '\\c{H}',     \
      'Ķ': '\\c{K}', 'Ļ': '\\c{L}', 'Ņ': '\\c{N}', 'Ŗ': '\\c{R}', 'Ş': '\\c{S}',     \
      'Ţ': '\\c{T}',                                                                 \
      'Ł': '\\L{}', 'Ø': '\\O{}', 'Đ': '\\DJ{}',                                     \
      'Æ': '\\AE{}', 'Œ': '\\OE{}',                                                  \
      # '¡': '!`, '¿': '¿`'
      '¡': '\\textexclamdown', '¿': '\\textquestiondown',                            \
      '%': '\\%', '#': '\\#', '&': '\\&', '$': '\\$',                                \
      '_': '\\_', '–': '--', '·': '\\textperiodcentered', '|': '\\textbar',          \
      '<': '\\textless', '>': '\\textgreater',                                       \
      '': '*', 'ª': '\\textordfeminine', 'º': '\\textordmasculine',                \
      '°': '$^{\\circ}$', '²': '$^{2}$',                                             \
      '\n': '\\\\\n', '\t': '\\medskip',                                             \
      '“': '\\textquotedblleft', '”': '\\textquotedblright', '^': '\^{}', '’': "'",  \
      '≥': '$\geq$', '~': '$\sim$'}

    if to == 'tex':
        chars = texchars
        # Specific first characters to change
        firstchars = ['\\']
    else:
        print errormsg
        print '  ' + fname + ": language '" + to + "' not ready !!"
        print '    available languages:', langs
        quit(-1)

    if nochg is not None:
        for noc in nochg:
            if  not chars.has_key(noc):
                print errormsg
                print '  ' + fname + ": language '" + to + "' does not have '" +     \
                  noc + "' to change !!"
                quit(-1)
            chars.pop(noc)
            if searchInlist(firstchars,noc): firstchars.remove(noc)

    newtext = text
    for char in firstchars:
#        newtext = newtext.replace(char.decode('iso-8859-15'),chars[char].decode('iso-8859-15'))
        newtext = newtext.replace(char,chars[char])
        chars.pop(char)

    for char in chars.keys():
        newtext = newtext.replace(char,chars[char])

    # There are some issues one inside a math environment
    #   $ (...) $<$ (...)$: will not work! need to be $ (...) < (...)$
    CHANGEinsideMATH = ['$<$', '$>$', '$^{a}$', '$^{o}$', '$^{\circ}$']
    Nchgmath = len(CHANGEinsideMATH)

    Lnewtext = len(newtext)
    mathpos = []
    for ic in range(Lnewtext):
        if newtext[ic] == '$': 
            mathpos.append(ic)

    # Dictionary with locations within line of the dangerous strings...
    mathchg = {}
    for icS in CHANGEinsideMATH:
        indices = multi_index_string(newtext,icS)
        if len(indices) > 0:
            mathchg[icS] = indices

    Lmathpos = len(mathpos)
    # All this only has sens if at least there are 4 $!
    if Lmathpos >= 4:
        for imath in range(Lmathpos,0,-2):
            for chars in mathchg.keys():
                positions = mathchg[chars]
                Lchars = len(chars)
                for ipos in positions:
                    if mathpos[imath-4] < ipos and mathpos[imath-2] == ipos + Lchars - 1:
                        print '  ' + fname + ": removing '" + chars + "'"
                        Lnewstring = len(newtext)
                        newstring = newtext[0:ipos] + chars.replace('$','') +        \
                          newtext[ipos+Lchars:Lnewstring+1]
                        newtext = newstring

    return newtext

#NOchange = ['_', '^', '\\', '&', '$']

def ASCII_LaTeX(ln):
    """ Function to transform from an ASCII character to LaTeX codification
    >>> ASCII_LaTeX('Laboratoire de Météorologie Dynamique però Hovmöller \¿')
    Laboratoire de M\'et\'eorologie Dynamique per\`o Hovm\"oller \textbackslash¿`
    """

    newln = ln.replace('\\', '\\textbackslash')

    newln = newln.replace('á', "\\'a")
    newln = newln.replace('é', "\\'e")
    newln = newln.replace('í', "\\'i")
    newln = newln.replace('ó', "\\'o")
    newln = newln.replace('ú', "\\'u")

    newln = newln.replace('à', "\\`a")
    newln = newln.replace('è', "\\`e")
    newln = newln.replace('ì', "\\`i")
    newln = newln.replace('ò', "\\`o")
    newln = newln.replace('ù', "\\`u")

    newln = newln.replace('â', "\\^a")
    newln = newln.replace('ê', "\\^e")

    newln = newln.replace('î', "\\^i")
    newln = newln.replace('ô', "\\^o")
    newln = newln.replace('û', "\\^u")

    newln = newln.replace('ä', '\\"a')
    newln = newln.replace('ë', '\\"e')
    newln = newln.replace('ï', '\\"i')
    newln = newln.replace('ö', '\\"o')
    newln = newln.replace('\xf6', '\\"o')
    newln = newln.replace('ü', '\\"u')

    newln = newln.replace('ç', '\c{c}')
    newln = newln.replace('ñ', '\~{n}')

    newln = newln.replace('Á', "\\'A")
    newln = newln.replace('É', "\\'E")
    newln = newln.replace('Í', "\\'I")
    newln = newln.replace('Ó', "\\'O")
    newln = newln.replace('Ú', "\\'U")

    newln = newln.replace('À', "\\`A")
    newln = newln.replace('È', "\\`E")
    newln = newln.replace('Ì', "\\`I")
    newln = newln.replace('Ò', "\\`O")
    newln = newln.replace('Ù', "\\`U")

    newln = newln.replace('Â', "\\^A")
    newln = newln.replace('Ê', "\\^E")
    newln = newln.replace('Î', "\\^I")
    newln = newln.replace('Ô', "\\^O")
    newln = newln.replace('Û', "\\^U")

    newln = newln.replace('Ä', '\\"A')
    newln = newln.replace('Ë', '\\"E')
    newln = newln.replace('Ï', '\\"I')
    newln = newln.replace('Ö', '\\"O')
    newln = newln.replace('Ü', '\\"U')

    newln = newln.replace('Ç', '\\c{C}')
    newln = newln.replace('Ñ', '\\~{N}')

    newln = newln.replace('¡', '!`')
    newln = newln.replace('¿', '¿`')
    newln = newln.replace('%', '\\%')
    newln = newln.replace('#', '\\#')
    newln = newln.replace('&', '\\&')
    newln = newln.replace('$', '\\$')
    newln = newln.replace('_', '\\_')
    newln = newln.replace('·', '\\textperiodcentered')
    newln = newln.replace('<', '\\tetxless')
    newln = newln.replace('>', '\\textgreater')
    newln = newln.replace('', '*')
#    newln = newln.replace('º', '$^{\\circ}$')
    newln = newln.replace('ª', '$^{a}$')
    newln = newln.replace('º', '$^{o}$')
    newln = newln.replace('°', '$^{\\circ}$')
    newln = newln.replace('\n', '\\\\\n')
    newln = newln.replace('\t', '\\medskip')
    newln = newln.replace('“', '``')
    newln = newln.replace('”', '\'\'')

    return newln

def latex_text(itext):
    """ Function to transform a text to LaTeX following style rules
      itext: original text
      >>> latex_text('US use the dolar $ as in AUS')
      US use the dolar \$ as in AUS
      >>> latex_text('definition of sinus: $\sin=\\frac{a}{\\sqrt{a^2+b^2}}$')
      definition of sinus: $\sin=\frac{a}{\sqrt{a^2+b^2}}$
      >>> latex_text('WRF_LMDZ$_{current}^{AR40}$')
      WRF\_LMDZ$_{current}^{AR40}$
      >>> latex_text('Lluís Fita$_{1976/02/17}$')
      Llu\'is Fita$_{1976/02/17}$
    """
    fname = 'latex_text'

    # Sesitive characters which might interfer with the mathematical environment
    symbs = {'sub': '_', 'sup':'^', 'slash':'\\', 'and': '&'}

    # Do not change that sensitive_math which are between $ (from mathematical notation)
    latexsymb = {}

    Litext = len(itext)
    for ic in range(Litext):
        if itext[ic] == '$': 
            if latexsymb.has_key('math'):
                vals = latexsymb['math']
                vals.append(ic)
            else:
                vals = [ic]
            latexsymb['math'] = vals
        elif itext[ic] == '_': 
            if latexsymb.has_key('sub'):
                vals = latexsymb['sub']
                vals.append(ic)
            else:
                vals = [ic]
            latexsymb['sub'] = vals
        elif itext[ic] == '^':
            if latexsymb.has_key('sup'):
                vals = latexsymb['sup']
                vals.append(ic)
            else:
                vals = [ic]
            latexsymb['sup'] = vals
        elif itext[ic] == '\\':
            if latexsymb.has_key('slash'):
                vals = latexsymb['slash']
                vals.append(ic)
            else:
                vals = [ic]
            latexsymb['slash'] = vals
        elif itext[ic] == '&':
            if latexsymb.has_key('and'):
                vals = latexsymb['and']
                vals.append(ic)
            else:
                vals = [ic]
            latexsymb['and'] = vals

    #print fname + "; Lluis itext '" + itext + "'"
    #printing_dictionary(latexsymb) 

    latextext = itext + ''
    for car in symbs.keys():
        changecar = ASCII_LaTeX(symbs[car])
        if latexsymb.has_key(car):
            if not latexsymb.has_key('math') or len(latexsymb['math']) == 1:
                latextext = latextext.replace(symbs[car],changecar)
            else:
                # Changing that characters which are outside an even 'math' pair
                mathpos = latexsymb['math']
                Nmath = len(mathpos)
                if np.mod(Nmath,2) != 0 and Nmath > 1:
                    print errormsg
                    print '  '+fname + ': even number', Nmath,' of math symbols $ !!'
                    print '    impossible to determine where starts math environment '
                    print "    change text: '" + itext + "'"
                    quit(-1)

                for isymb in latexsymb[car]:
                    Ltxt = len(latextext)
                    if Nmath == 2:
                        # Case with only 2 $
                        mathbeg = mathpos[0]
                        mathend = mathpos[1]
                        if isymb < mathbeg or isymb > mathend:
                            headtxt = latextext[0:isymb]
                            tailtxt = latextext[isymb+1:Ltxt+1]
                            latextext = headtxt + changecar + tailtxt
                    else:
                        # Case with more than 2 $
                        for imath in range(0,Nmath,2):
                            mathbeg = mathpos[imath]
                            mathend = mathpos[imath+1]
                            if imath+1 == Nmath-1:
                                mathnext = Ltxt
                            else:
                                mathnext = mathpos[imath+2]
                            if isymb < mathbeg and (isymb > mathend and isymb < mathnext):
                                headtxt = latextext[0:isymb]
                                tailtxt = latextext[isymb+1:Ltxt+1]
                                latextext = headtxt + changecar + tailtxt
                                break
    # Only 1 mathematical sign
    Ltxt = len(latextext)
    if latexsymb.has_key('math') and len(latexsymb['math']) == 1:
        isymb = latexsymb['math'][0]
        headtxt = latextext[0:isymb]
        tailtxt = latextext[isymb+1:Ltxt+1]
        latextext = headtxt + '\\$' + tailtxt

    NOchange = ['_', '^', '\\', '&', '$']
    latextext = ASCII_to(latextext, 'tex', NOchange)

    return latextext

def replace_list(listv,oldv,newv):
    """ Function to replace a value in a given list
      listv= list of values
      oldv= value to replace
      newv= value to use
    >>> replace_list(range(10),3,'iii')
    [0, 1, 2, 'iii', 4, 5, 6, 7, 8, 9]
    """
    fname = 'replace_list'

    newlist = list(listv)
    iv = 0
    for vv in listv:
        if vv == oldv: newlist[iv] = newv
        iv = iv + 1

    return newlist 

def pretty_int(minv,maxv,Nint):
    """ Function to plot nice intervals
      minv= minimum value
      maxv= maximum value
      Nint= number of intervals
    >>> pretty_int(23.50,67.21,5)
    [ 25.  30.  35.  40.  45.  50.  55.  60.  65.]
    >>> pretty_int(-23.50,67.21,15)
    [  0.  20.  40.  60.]
    >>> pretty_int(14.75,25.25,5)
    [ 16.  18.  20.  22.  24.]
    >>> pretty_int(-20.,20.,10)
    [-20. -15. -10.  -5.   0.   5.  10.  15.]
    """ 
    fname = 'pretty_int'
    nice_int = [1,2,5]

    interval = np.abs(maxv - minv)

    if interval <= 0.:
        print errormsg
        print '  ' + fname + ': wrong interval',interval,'!!'
        print '    it can not be negative or zero'
        quit(-1)

    potinterval = np.log10(interval)
    Ipotint = int(potinterval)
    intvalue = np.float(interval / np.float(Nint))

# new
    potinterval = np.log10(intvalue)
    Ipotint = np.floor(potinterval)

#    print fname + '; Lluis: interval:', interval, 'intavlue:', intvalue, 'potinterval:', potinterval, \
#     'Ipotint:', Ipotint, 'intvalue:', intvalue

    mindist = 10.e15
    for inice in nice_int:
#        print inice,':',inice*10.**Ipotint,np.abs(inice*10.**Ipotint - intvalue),mindist
        if np.abs(inice*10.**Ipotint - intvalue) < mindist:
            mindist = np.abs(inice*10.**Ipotint - intvalue)
            closestint = inice

    Ibeg = int(minv / (closestint*10.**Ipotint))

    values = []
    val = closestint*(Ibeg)*10.**(Ipotint)
    dval = closestint*10.**(Ipotint)

#    print 'closestint:',closestint,'Ibeg:',Ibeg,'val:',val,'dval:',dval

    while val < maxv:
        values.append(val)
        val = val + dval

    return np.array(values, dtype=np.float)

def prime_numbers(value):
    """ Function to find all the prime numbers up to a given value above 17
      value: limiting value to use
    >>> primes(100)
    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
    """
    fname = 'prime_numbers'

    primes = [2,3,5,7,11,13,17]
    lastprime = 17
    for i in range(lastprime+1,value):
        #print '  ',i,value
        isprime = False
        for ip in primes:
            # No need to find allover the previous primes, just as big as the half
            if ip < i/2:
                if np.mod(i,ip) == 0:
                    isprime = False
                    break
                else:
                    isprime = True
        if isprime:
            primes.append(i)
            lastprime = i
            #print fname + ': prime number',i,'!!'
    return primes

def prime_decomposition(num):
    """ Function to decompose a given number with its multiple prime numbers
      fname= num
    >>> prime_decomposition(100)
    {2: 2, 5: 2}
    """
    fname = 'prime_decomposition'

    decomposition = {}

    # Prime numbers
    primnums = prime_numbers(num)

    inum = num
    while inum > primnums[0]:
        for primn in primnums:
            if np.mod(inum,primn) == 0:
                inum = inum / primn
                if decomposition.has_key(primn):
                    decomposition[primn] = decomposition[primn] + 1
                else:
                    decomposition[primn] = 1
                break

    return decomposition

def timestep_conform(TOTtime,tunit,multnum):
    """ Function to provide the time-step in seconds which conforms 1 temporal unit and the resultant number of time-steps for
     a whole period is multiple of a given number
      TOTtime: period [seconds]
      tunit: temporal unit at which the time-step has to conform [seconds]
      multnum: number to which the resultant number of time-step for `TOTtime' have to be multiple
    >>> timestep_conform(86400,3600,5)
    [4, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 30, 36, 40, 45, 48, 60, 72, 80, 90, 120, 144, 180, 240, 360, 720]
    """
    fname = 'timestep_conform'

    # Possible fractions
    tunitdecompos = prime_decomposition(tunit)

    allvals = []
    for prime in tunitdecompos.keys():
        for it in range(tunitdecompos[prime]):
            allvals.append(prime)

    Nallvals = len(allvals)
    allcombinations = list_norepeatcombos(Nallvals)
    Ncombos = len(allcombinations)
    
    # It might be a far more efficient way? I'm lazy...
    timestep = []
    for ic in range(Ncombos):
        combo = allcombinations[ic]
        val = 1
        for icc in combo:
            val = val*allvals[icc]

        if not searchInlist(timestep,val) and np.mod(TOTtime/val,multnum) == 0: 
            timestep.append(val)

    timestep.sort()
    return timestep

def matoperations(opN,matA,matB=None):
    """ Function to perform different operations to a pair of matrices of values
      opN: name of the operation
        'add': adding matB to matA (matA + matB)
        'addc',[modval1]: add [modval1]
        'centerderiv',[N],[ord],[dim]: un-scaled center [N]-derivative of order [ord] along dimension [dim] of matA
        'div': dividing by matB (matA / matB)
        'divc',[modval1]: divide by [modval1]
        'forwrdderiv',[N],[ord],[dim]: un-scaled forward [N]-derivative of order [ord] along dimension [dim] of matA
        'inv': inverting matA (1/matA)
        'lowthres',[modval1],[modval2]: if [val] < [modval1]; val = [modval2]
        'lowthres@oper',[modval1],[oper],[modval2]: if [val] < [modval1]; val = [oper] (operation as [modval2])
        'mul': multiplying ny matB (matA * matB)
        'mulc',[modval1]: multiply by [modval1]
        'pot': powering with matB (matA ** matB)
        'potc',[modval1]: [val] ** [modval1]
        'repl',[modval1]: replace values of matA with values from matB except matB = [modval1]
        'replbig',[modval1]: replace values of matA with values from matB except matB > [modval1]
        'repless',[modval1]: replace values of matA with values from matB except matB < [modval1]
        'sub': substracting matB to matA (matA - matB)
        'subc',[modval1]: remove [modval1]
        'upthres',[modval1],[modval2]: if [val] > [modval1]; val = [modval2]
        'upthres@oper',[modval1],[oper],[modval2]: if [val] > [modval1]; val = [oper] (operation with [modval2])
      matA: initial values
      matB: values to operate with
    >>> matoperations('centerderiv,1,8,0',np.arange(81.).reshape(9,9))
    [[ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 9.  9.  9.  9.  9.  9.  9.  9.  9.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]], '1-center_deriv_ord(8)[0]'
    >>> matoperations('forwrdderiv,2,2,0',np.arange(81.).reshape(9,9))
    [[ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.  0.  0.  0.]], '2-forward_deriv_ord(2)[0]'
    >>> matoperations('upthres,4,3',np.arange(81).reshape(9,9))
    [[0 1 2 3 4 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]
     [3 3 3 3 3 3 3 3 3]], '>4 [=3]'
    >>> matoperations('lowthres@oper,37,divc,7',np.arange(81).reshape(9,9))
    [[ 0  0  0  0  0  0  0  1  1]
     [ 1  1  1  1  1  2  2  2  2]
     [ 2  2  2  3  3  3  3  3  3]
     [ 3  4  4  4  4  4  4  4  5]
     [ 5 37 38 39 40 41 42 43 44]
     [45 46 47 48 49 50 51 52 53]
     [54 55 56 57 58 59 60 61 62]
     [63 64 65 66 67 68 69 70 71]
     [72 73 74 75 76 77 78 79 80]], '<37 [=/7]'
    """
    fname = 'matoperations'
    newmat = None

    matAshape = list(matA.shape)

    # From: https://en.wikipedia.org/wiki/Finite_difference_coefficient
    # Coefficients for center derivatives at different orders (as key)
    centerderiv = np.zeros((6,8,9), dtype=np.float)
    # Different available orders for each derivative
    centerorder = {}
    centerorder[0] = [1,3,5,7]
    centerorder[1] = [1,3,5,7]
    centerorder[2] = [1,3,5]
    centerorder[3] = [1,3,5]
    centerorder[4] = [1]
    centerorder[5] = [1]

    # First derivative
    centerderiv[0,1,:]= [        0.,        0.,        0.,    -1./2.,        0.,     1./2.,        0.,        0.,        0.]
    centerderiv[0,3,:]= [        0.,        0.,    1./12.,    -2./3.,        0.,     2./3.,   -1./12.,        0.,        0.]
    centerderiv[0,5,:]= [        0.,   -1./60.,    3./20.,    -3./4.,        0.,     3./4.,   -3./20.,     1./60,        0.]
    centerderiv[0,7,:]= [   1./280.,  -4./105.,     1./5.,    -4./5.,        0.,     4./5.,    -1./5.,   4./105.,  -1./280.]
    # Second derivative
    centerderiv[1,1,:]= [        0.,        0.,       0.,         1.,       -2.,        1.,        0.,        0.,        0.]
    centerderiv[1,3,:]= [        0.,        0.,   -1./12.,     4./3.,    -5./2.,     4./3.,   -1./12.,        0.,        0.]
    centerderiv[1,5,:]= [        0.,    1./90.,   -3./20.,     3./2.,  -49./18.,     3./2.,   -.3/20.,    1./90.,        0.]
    centerderiv[1,7,:]= [  -1./560.,   8./315.,    -1./5.,     8./5., -205./72.,     8./5.,    -1./5.,   8./315.,  -1./560.]
    # 3rd derivative
    centerderiv[2,1,:]= [        0.,        0.,    -1./2.,        1.,        0.,       -1.,     1./2.,        0.,        0.]
    centerderiv[2,3,:]= [        0.,     1./8.,       -1.,    13./8.,        0.,   -13./8.,        1.,    -1./8.,        0.]
    centerderiv[2,5,:]= [  -7./240.,    3./10.,-169./120.,   61./30.,        0.,  -61./30., 169./120.,   -3./10.,   7./240.]
    # 4th derivative
    centerderiv[3,1,:]= [        0.,        0.,        1.,       -4.,        6.,       -4.,        1.,        0.,        0.]
    centerderiv[3,3,:]= [        0.,    -1./6.,        2.,   -13./2.,    28./3.,   -13./2.,        2.,    -1./6.,        0.] 
    centerderiv[3,5,:]= [   7./240.,    -2./5.,  169./60., -122./15.,    91./8., -122./15.,  169./60.,    -2./5.,   7./240.] 
    # 5th derivative
    centerderiv[4,1,:]= [        0.,    -1./2.,        2.,    -5./2.,        0.,     5./2.,       -2.,     1./2.,        0.]
    # 6th derivative
    centerderiv[5,1,:]= [        0.,        1.,       -6.,       15.,      -20.,       15.,       -6.,        1.,        0.]

    # Coefficients for forward derivatives at different orders (as key)
    forwrdderiv = np.zeros((6,6,9), dtype=np.float)
    # Different available orders for each derivative
    forwrdorder = {}
    forwrdorder[0] = range(6)
    forwrdorder[1] = range(6)
    forwrdorder[2] = range(6)
    forwrdorder[3] = range(4)

    # First derivative
    forwrdderiv[0,0,:]= [       -1.,        1.,        0.,        0.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[0,1,:]= [    -3./2.,        2.,    -1./2.,        0.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[0,2,:]= [   -11./6.,        3.,    -3./2.,     1./3.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[0,3,:]= [  -25./12.,        4.,       -3.,     4./3.,    -1./4.,        0.,        0.,        0.,        0.]
    forwrdderiv[0,4,:]= [ -137./60.,        5.,       -5.,    10./3.,    -5./4.,     1./5.,        0.,        0.,        0.]
    forwrdderiv[0,5,:]= [  -49./20.,        6.,   -15./2.,    20./3.,   -15./4.,     6./5.,    -1./6.,        0.,        0.]
    # Second derivative
    forwrdderiv[1,0,:]= [        1.,       -2.,        1.,        0.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[1,1,:]= [        2.,       -5.,        4.,       -1.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[1,2,:]= [   35./12.,   -26./3.,    19./2.,   -14./3.,   11./12.,        0.,        0.,        0.,        0.]
    forwrdderiv[1,3,:]= [    15./4.,   -77./6.,   107./6.,      -13.,   61./12.,    -5./6.,        0.,        0.,        0.]
    forwrdderiv[1,4,:]= [  203./45.,   -87./5.,   117./4.,  -254./9.,    33./2.,   -27./5., 137./180.,        0.,        0.]
    forwrdderiv[1,5,:]= [  469./90., -223./10.,  879./20., -949./18.,       41., -201./10.,1019./180.,   -7./10.,        0.]
    # 3rd derivative
    forwrdderiv[2,0,:]= [       -1.,        3.,       -3.,        1.,        0.,        0.,        0.,        0.,        0.]
    forwrdderiv[2,1,:]= [    -5./2.,        9.,      -12.,        7.,    -3./2.,        0.,        0.,        0.,        0.]
    forwrdderiv[2,2,:]= [   -17./4.,    71./4.,   -59./2.,    49./2.,   -41./4.,     7./4.,        0.,        0.,        0.]
    forwrdderiv[2,3,:]= [   -49./8.,       29.,  -461./8.,       62.,  -307./8.,       13.,   -15./8.,        0.,        0.]
    forwrdderiv[2,4,:]= [-967./120.,  638./15.,-3929./40.,   389./3.,-2545./24.,   268./5.,-1849./120,   29./15.,        0.]
    forwrdderiv[2,5,:]= [ -801./80.,   349./6.,-18353./120,2391./10., -1457./6., 4891./30.,  -561./8.,  527./30.,-469./240.]
    # 4th derivative
    forwrdderiv[3,0,:]= [        1.,       -4.,        6.,       -4.,        1.,        0.,        0.,        0.,        0.]
    forwrdderiv[3,1,:]= [        3.,      -14.,       26.,      -24.,       11.,       -2.,        0.,        0.,        0.]
    forwrdderiv[3,2,:]= [    35./6.,      -31.,   137./2.,  -242./3.,   107./2.,      -19.,    17./6.,        0.,        0.]
    forwrdderiv[3,3,:]= [    28./3.,  -111./2.,      142., -1219./6.,      176.,  -185./2.,    82./3.,    -7./2.,        0.]
    forwrdderiv[3,4,:]= [ 1069./80.,-1316./15.,15289./60., -2144./5.,10993./24.,-4772./15., 2803./20., -536./15., 967./240.]

    # Dictionary with the description of the operations
    Lopn = {'add': '+', 'addc': '+', 'div': '/', 'divc': '/', 'inv': '^(-1)',        \
      'lowthres': '<', 'mul': '*', 'mulc': '*', 'pot': '^', 'potc': '^',             \
      'repl': 'repl_excpt', 'replbig': 'repl_excpt_bigger',                          \
      'repless': 'repl_excpt_less', 'sub': '-', 'subc': '-', 'upthres': '<'}
    # Operations by constant value
    Lopnc = {'addc': '+', 'divc': '/', 'inv': '^{-1)', 'mulc': '*', 'potc': '^',     \
      'repl': 'repl_excpt', 'replbig': 'repl_excpt_bigger',                          \
      'repless': 'repl_excpt_less', 'subc': '-'}

    # Available operations
    opavail = ['add', 'addc', 'centerderiv', 'div', 'divc', 'forwrdderiv', 'inv',    \
      'lowthres', 'lowthres@oper', 'mul', 'mulc', 'pot', 'potc', 'repl', 'replbig',  \
      'repless', 'sub', 'subc', 'upthres', 'upthres@oper']
    opavailc = ['addc', 'divc', 'inv', 'mulc', 'potc', 'subc']

    valtype = matA.dtype

    if opN[0:4] == 'addc':
        opn = 'addc'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['addc'] = '+' + str(value1)
    elif opN[0:11] == 'centerderiv':
        opn = 'centerderiv'
        Nderiv = int(opN.split(',')[1])
        order = int(opN.split(',')[2])
        dim = int(opN.split(',')[3])
        Lopn[opn]= str(Nderiv)+'-center_deriv_ord('+str(order)+ ')[' + str(dim) + ']'
        if not centerorder.has_key(Nderiv-1):
            print errormsg
            print '  ' + fname + ': ', Nderiv,'-center derivative does not exist!!'
            print '  existing ones:', list(centeroder.keys())+1
            quit()
        derivorders = centerorder[Nderiv-1]
        if not searchInlist(derivorders,order-1):
            print errormsg
            print '  ' + fname + ': ', Nderiv,'-center derivative does not have ' +  \
              'order:',  order,'!!'
            print '  existing ones:', np.array(derivorders) + 1
            quit()
        if dim > len(matAshape)-1:
            print errormsg
            print '  '+fname+ ': wrong dimension:', dim, 'to compute the center-' +  \
              'derivative!!'
            print '  matrix has a smaller rank:', len(matAshape)
            quit(-1)
        derivcoeff = centerderiv[Nderiv-1,order-1,:]
    elif opN[0:4] == 'divc':
        opn = 'divc'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['divc'] = '/' + str(value1)         
    elif opN[0:11] == 'forwrdderiv':
        opn = 'forwrdderiv'
        Nderiv = int(opN.split(',')[1])
        order = int(opN.split(',')[2])
        dim = int(opN.split(',')[3])
        Lopn[opn]= str(Nderiv)+'-forward_deriv_ord('+str(order)+ ')[' + str(dim) + ']'
        if not forwrdorder.has_key(Nderiv-1):
            print errormsg
            print '  ' + fname + ': ', Nderiv,'-forward derivative does not exist!!'
            print '  existing ones:', list(forwrdoder.keys())+1
            quit()
        derivorders = forwrdorder[Nderiv-1]
        if not searchInlist(derivorders,order-1):
            print errormsg
            print '  ' + fname + ': ', Nderiv,'-forward derivative does not have ' + \
              'order:',  order,'!!'
            print '  existing ones:', np.array(derivorders) + 1
            quit()
        if dim > len(matAshape)-1:
            print errormsg
            print '  '+fname+ ': wrong dimension:', dim, 'to compute the forward-' + \
              'derivative!!'
            print '  matrix has a smaller rank:', len(matAshape)
            quit(-1)
        derivcoeff = forwrdderiv[Nderiv-1,order-1,:]
    elif opN[0:8] == 'lowthres' and opN.find('@') == -1:
        opn = 'lowthres'
        value1 = retype(opN.split(',')[1], valtype)
        value2 = retype(opN.split(',')[2], valtype)
        Lopn['lowthres'] = '<' + str(value1) + ' [=' + str(value2) +']'         
    elif opN[0:13] == 'lowthres@oper':
        opn = 'lowthres@oper'
        value1 = retype(opN.split(',')[1], valtype)
        value2 = opN.split(',')[2]
        value3 = retype(opN.split(',')[3], valtype)
        if not Lopnc.has_key(value2):
            print errormsg
            print '  ' + fname + ": second operation '" + value2 + "' not ready !!"
            print '    available ones:', opavailc
            quit(-1)        
        Lopn['lowthres@oper'] = '<' + str(value1) + ' [=' + Lopnc[value2] +          \
          str(value3) + ']'
    elif opN[0:4] == 'mulc':
        opn = 'mulc'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['mulc'] = '*' + str(value1)         
    elif opN[0:4] == 'potc':
        opn = 'potc'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['potc'] = '^' + str(value1)         
    elif opN[0:4] == 'repl' and opN.split(',')[0] == 'repl':
        opn = 'repl'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['repl'] = 'repl_excpt(' + str(value1) + ')'
    elif opN[0:7] == 'replbig':
        opn = 'replbig'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['replbig'] = 'repl_excpt(<' + str(value1) + ')'
    elif opN[0:7] == 'repless':
        opn = 'repless'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['repless'] = 'repl_excpt(>' + str(value1) + ')'
    elif opN[0:4] == 'subc':
        opn = 'subc'
        value1 = retype(opN.split(',')[1], valtype)
        Lopn['subc'] = '-' + str(value1)         
    elif opN[0:7] == 'upthres' and opN.find('@') == -1:
        opn = 'upthres'
        value1 = retype(opN.split(',')[1], valtype)
        value2 = retype(opN.split(',')[2], valtype)
        Lopn['upthres'] = '>' + str(value1) + ' [=' + str(value2) +']'         
    elif opN[0:12] == 'upthres@oper':
        opn = 'upthres@oper'
        value1 = retype(opN.split(',')[1], valtype)
        value2 = opN.split(',')[2]
        value3 = retype(opN.split(',')[3], valtype)
        if not Lopnc.has_key(value2):
            print errormsg
            print '  ' + fname + ": second operation '" + value2 + "' not ready !!"
            print '    available ones:', opavailc
            quit(-1)        
        Lopn['upthres@oper'] = '>' + str(value1) + ' [=' + Lopnc[value2] +           \
          str(value3) +']'         
    else:
        opn = opN
   
    # Carrying on the operation
    if opn == 'add':
        newmat = matA + matB
    elif opn == 'addc':
        newmat = matA + value1
    elif opn == 'centerderiv':
        sdim = matAshape[dim]
        # Getting the different slices for each coefficient
        # newmat = matA_4*coef_4 + matA_3*coef_3 + matA_2*coef_2 + matA_1*coef_1 + 
        #   matA*coef0 + matA1*coef1 + mat2*coef2 + matA3*coef3 + mat4*coef4
        newmat = np.zeros(tuple(matAshape), dtype=valtype)
        mat0 = []
        mat1_ = []
        mat1 = []
        mat2_ = []
        mat2 = []
        mat3_ = []
        mat3 = []
        mat4_ = []
        mat4 = []

        Nterms = 2*int((Nderiv-1)/2)+order+1
        for idim in range(len(matAshape)):
            if idim == dim:
                sd = (Nterms-1)/2
                ed = sdim - (Nterms-1)/2
                mat0.append(slice(sd,ed))
                mat1_.append(slice(sd-1,ed-1))
                mat1.append(slice(sd+1,ed+1))
                mat2_.append(slice(sd-2,ed-2))
                mat2.append(slice(sd+2,ed+2))
                mat3_.append(slice(sd-3,ed-3))
                mat3.append(slice(sd+3,ed+3))
                mat4_.append(slice(sd-4,ed-4))
                mat4.append(slice(sd+4,ed+4))
            else:
                mat0.append(slice(0,matAshape[idim]+1))
                mat1_.append(slice(0,matAshape[idim]+1))
                mat1.append(slice(0,matAshape[idim]+1))
                mat2_.append(slice(0,matAshape[idim]+1))
                mat2.append(slice(0,matAshape[idim]+1))
                mat3_.append(slice(0,matAshape[idim]+1))
                mat3.append(slice(0,matAshape[idim]+1))
                mat4_.append(slice(0,matAshape[idim]+1))
                mat4.append(slice(0,matAshape[idim]+1))
        if Nterms == 3:
            newmat[tuple(mat0)] = matA[tuple(mat1_)]*derivcoeff[3] +                 \
              matA[tuple(mat0)]*derivcoeff[4] + matA[tuple(mat1)]*derivcoeff[5]
        elif Nterms == 5:
            newmat[tuple(mat0)] = matA[tuple(mat2_)]*derivcoeff[2] +                 \
              matA[tuple(mat1_)]*derivcoeff[3] +                                     \
              matA[tuple(mat0)]*derivcoeff[4] +                                      \
              matA[tuple(mat1)]*derivcoeff[5] + matA[tuple(mat2)]*derivcoeff[6]
        elif Nterms == 7:
            newmat[tuple(mat0)] = matA[tuple(mat3_)]*derivcoeff[1] +                 \
              matA[tuple(mat2_)]*derivcoeff[2] + matA[tuple(mat1_)]*derivcoeff[3] +  \
              matA[tuple(mat0)]*derivcoeff[4] +                                      \
              matA[tuple(mat1)]*derivcoeff[5] + matA[tuple(mat2)]*derivcoeff[6] +    \
              matA[tuple(mat3)]*derivcoeff[7]
        elif Nterms == 9:
            newmat[tuple(mat0)] = matA[tuple(mat4_)]*derivcoeff[0] +                 \
              matA[tuple(mat3_)]*derivcoeff[1] + matA[tuple(mat2_)]*derivcoeff[2] +  \
              matA[tuple(mat1_)]*derivcoeff[3] +                                     \
              matA[tuple(mat0)]*derivcoeff[4] +                                      \
              matA[tuple(mat1)]*derivcoeff[5] + matA[tuple(mat2)]*derivcoeff[6] +    \
              matA[tuple(mat3)]*derivcoeff[7] + matA[tuple(mat4)]*derivcoeff[8]
    elif opn == 'div':
        newmat = matA / matB
    elif opn == 'divc':
        newmat = matA / value1
    elif opn == 'forwrdderiv':
        sdim = matAshape[dim]
        # Getting the different slices for each coefficient
        # newmat = matA0*coef0 + matA1*coef1 + matA2*coef2 + matA3*coef3 + 
        #   matA4*coef4 + matA5*coef5 + matA6*coef6 + matA7*coef7 + matA8*coef8
        newmat = np.zeros(tuple(matAshape), dtype=valtype)
        mat0 = []
        mat1 = []
        mat2 = []
        mat3 = []
        mat4 = []
        mat5 = []
        mat6 = []
        mat7 = []
        mat8 = []

        Nterms = Nderiv + order
        for idim in range(len(matAshape)):
            if idim == dim:
                sd = 0
                ed = sdim-Nterms+1
                mat0.append(slice(sd,ed))
                mat1.append(slice(sd+1,ed+1))
                mat2.append(slice(sd+2,ed+2))
                mat3.append(slice(sd+3,ed+3))
                mat4.append(slice(sd+4,ed+4))
                mat5.append(slice(sd+5,ed+5))
                mat6.append(slice(sd+6,ed+6))
                mat7.append(slice(sd+7,ed+7))
                mat8.append(slice(sd+8,ed+8))
            else:
                mat0.append(slice(0,matAshape[idim]+1))
                mat1.append(slice(0,matAshape[idim]+1))
                mat2.append(slice(0,matAshape[idim]+1))
                mat3.append(slice(0,matAshape[idim]+1))
                mat4.append(slice(0,matAshape[idim]+1))
                mat5.append(slice(0,matAshape[idim]+1))
                mat6.append(slice(0,matAshape[idim]+1))
                mat7.append(slice(0,matAshape[idim]+1))
                mat8.append(slice(0,matAshape[idim]+1))
        if Nterms == 2:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1]
        elif Nterms == 3:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2]
        elif Nterms == 4:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3]
        elif Nterms == 5:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3] + matA[tuple(mat4)]*derivcoeff[4]
        elif Nterms == 6:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3] + matA[tuple(mat4)]*derivcoeff[4] +    \
              matA[tuple(mat5)]*derivcoeff[5]
        elif Nterms == 7:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3] + matA[tuple(mat4)]*derivcoeff[4] +    \
              matA[tuple(mat5)]*derivcoeff[5] + matA[tuple(mat6)]*derivcoeff[6]
        elif Nterms == 8:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3] + matA[tuple(mat4)]*derivcoeff[4] +    \
              matA[tuple(mat5)]*derivcoeff[5] + matA[tuple(mat6)]*derivcoeff[6] +    \
              matA[tuple(mat7)]*derivcoeff[7]
        elif Nterms == 9:
            newmat[tuple(mat0)] = matA[tuple(mat0)]*derivcoeff[0] +                  \
              matA[tuple(mat1)]*derivcoeff[1] + matA[tuple(mat2)]*derivcoeff[2] +    \
              matA[tuple(mat3)]*derivcoeff[3] + matA[tuple(mat4)]*derivcoeff[4] +    \
              matA[tuple(mat5)]*derivcoeff[5] + matA[tuple(mat6)]*derivcoeff[6] +    \
              matA[tuple(mat7)]*derivcoeff[7] + matA[tuple(mat8)]*derivcoeff[8]
    elif opn == 'inv':
        newmat = retype(1., valtype) / matA
    elif opn == 'lowthres':
        newmat = np.where(matA < value1, value2, matA)
    elif opn == 'lowthres@oper':
        if value2 == 'addc':
            newmat = np.where(matA < value1, matA + value3, matA)
        elif value2 == 'divc':
            newmat = np.where(matA < value1, matA / value3, matA)
        elif value2 == 'inv':
            newmat = np.where(matA < value1, retype(1.,valtype) / matA, matA)
        elif value2 == 'mulc':
            newmat = np.where(matA < value1, matA * value3, matA)
        elif value2 == 'potc':
            newmat = np.where(matA < value1, matA ** value3, matA)
        elif value2 == 'subc':
            newmat = np.where(matA < value1, matA - value3, matA)
        else:
            print errormsg
            print '  ' + fname + ": second operation '" + value2 + "' not ready !!"
            print '    available ones:', opavailc
            quit(-1)
    elif opn == 'mul':
        newmat = matA * matB
    elif opn == 'mulc':
        newmat = matA * value1
    elif opn == 'pot':
        newmat = matA ** matB
    elif opn == 'potc':
        newmat = matA ** value1
    elif opn == 'repl':
        newmat = np.where(matB == value1, matA, matB)
    elif opn == 'replbig':
        newmat = np.where(matB > value1, matA, matB)
    elif opn == 'repless':
        newmat = np.where(matB < value1, matA, matB)
    elif opn == 'sub':
        newmat = matA - matB
    elif opn == 'subc':
        newmat = matA - value1
    elif opn == 'upthres':
        newmat = np.where(matA > value1, value2, matA)
    elif opn == 'upthres@oper':
        if value2 == 'addc':
            newmat = np.where(matA > value1, matA + value3, matA)
        elif value2 == 'divc':
            newmat = np.where(matA > value1, matA / value3, matA)
        elif value2 == 'inv':
            newmat = np.where(matA > value1, retype(1.,valtype) / matA, matA)
        elif value2 == 'mulc':
            newmat = np.where(matA > value1, matA * value3, matA)
        elif value2 == 'potc':
            newmat = np.where(matA > value1, matA ** value3, matA)
        elif value2 == 'subc':
            newmat = np.where(matA > value1, matA - value3, matA)
        else:
            print errormsg
            print '  ' + fname + ": second operation '" + value2 + "' not ready !!"
            print '    available ones:', opavailc
            quit(-1)
    else:
        print '  ' + fname + ": operation '" + opn + "' does not exist !!"
        print '  available ones:', opavail
        quit(-1)

    return newmat, Lopn[opn]

def latex_fig_array(figs, obf, figcaption, figlabel, dist='sqr', refsize=0.9,        \
  width='auto', height='None', dorest='nothing'):
    """ Function to add an array of figures to an existing tex file
      figs= list of figures names (with path)
      obf= already exisiting object open tex file 
      figcaption= caption for the figure
      figlabel= label for the figure
      dist= kind of distribution
        'sqr': squared, figures are equivenly distributed in rows and columns (sqrt(Nfigs), default)
        [Ncol]'x'Nrow: a given number of columns and rows
      refsize= refernce images size (0.9, default)
      width= with of the figures
        'None': no value passed
        'auto': getting according to fractions of [refsize]\textwidth (default)
        [value]: exactly as it is desired (e.g.: '0.3\\textwidht', '5cm' ...)
      height= height of the figures
        'None': no value passed (default)
        'auto': getting according to fractions of [refsize]\textheight
        [value]: exactly as it is desired (e.g.: '0.3\\textheight', '5cm' ...)
      dorest= what to do with the last row if it does not fill the number of columns
        'nothing': left empty columns (default)
        'center': center the figures
    >>> latex_fig_array(['figs/figA.png','figs/figB.png','figs/figC.png','figs/figD.png','figs/figE.png'], \
    objf, 'figure test', 'fig:test', dist='2x3', width='None', height='auto', dorest='center')
    \begin{figure}
    \begin{center}
    \begin{tabular}{cc}
    \includegraphics[height=0.3\textheight]{figs/figA.png}
    &
    \includegraphics[height=0.3\textheight]{figs/figB.png}
    \\
    \includegraphics[height=0.3\textheight]{figs/figC.png}
    &
    \includegraphics[height=0.3\textheight]{figs/figD.png}
    \\
    \multicolumn{2}{c}{\begin{tabular}{c}
    \includegraphics[height=0.3\textheight]{figs/figE.png}
    \end{tabular}}
    \end{tabular}
    \end{center}
    \caption{figure test}
    \label{fig:test}
    \end{figure}
    """
    fname = 'latex_fig_array'

    if type(figs) == type('s'):
        figs = list(figs)

    Nfig = len(figs)

    if dist == 'sqr':
        Ncol = int(np.sqrt(Nfig))
        Nrow = Nfig/Ncol
        Nrest = np.mod(Nfig,Ncol)
        if Nrest != 0: Nrow = Nrow + 1
    elif dist.find('x') != -1:
        Ncol = int(dist.split('x')[0])
        Nrow = int(dist.split('x')[1])
        Nrest = np.mod(Nfig,Ncol)
        if Ncol*Nrow < Nfig:
            print errormsg
            print '  ' + fname +': wrong number of rows and columns!!'
            print "  passed value of '" + dist + "' does not fit", Nfig, 'figures'
            quit(-1)
    else:
        print errormsg
        print '  ' + fname + ": figure distribution '" + dist + "' does not exist!!"
        print "    existing ones: 'sqr', [Ncol]x[Nrow]"
        quit(-1)
        
    # Special case on Nfigs == 2
    if Nfig == 2:
        Ncol = 2
        Nrow = 1
        Nrest = np.mod(Nfig,Ncol)

    # We prefer lines of figures rather than columns
    print 'Lluis Ncol:', Ncol, 'Nrow:', Nrow
    if dist == 'sqr' and (Ncol < Nrow):
        vc = Ncol
        vr = Nrow
        Ncol = vr
        Nrow = vc
        Nrest = np.mod(Nfig,Ncol)

    print '  ' + fname + ': table of figures of: ', Ncol, 'columns', Nrow, 'rows'

    # Checking for row/column size consistency definition
    if width == 'auto' and height == 'None' and Nrow > Ncol:
        print warnmsg
        print '  ' + fname + ': changing autmoatic configuration !!'
        print '   row-based definition of image sizes since number of rows:', Nrow,  \
          'is larger than the number of columns:', Ncol
        print "    from width='auto', height='None'"
        print "    to width='None', height='auto'"
        width = 'None'
        height = 'auto'

    # Width and height section
    widthheight = ''
    if width != 'None':
        if width == 'auto':
            sec = np.float(refsize)/Ncol
            widthheight = 'width=' + str(sec) + '\\textwidth'
        else:
            widthheight = 'width=' + width

    if height != 'None':
        if len(widthheight) > 0: widthheight = widthheight + ', '
        if height == 'auto':
            sec = np.float(refsize)/Nrow
            widthheight = widthheight + 'height=' + str(sec) + '\\textheight'
        else:
            widthheight = widthheight + 'height=' + height
    # num cols
    cS = ''
    for ic in range(Ncol): cS = cS + 'c'
    
    obf.write('\n')
    obf.write('\\begin{figure}\n')
    obf.write('\\begin{center}\n')

    # loop of figures distributed by Ncol, Nrow
    if Nfig > 1:
        obf.write('\\begin{tabular}{' + cS + '}\n')
        iifig = 0
        for irow in range(Nrow):
            if irow < Nrow -1 or (irow == Nrow - 1 and dorest == 'nothing'):
                for icol in range(Ncol):
                    # Getting figure name if it does exist
                    if iifig <= Nfig - 1:
                        fign = figs[iifig]
                        obf.write('\\includegraphics[' + widthheight + ']{' +fign+ '}\n')
                        if icol < Ncol - 1:
                            obf.write('&\n')
                        elif irow != Nrow - 1:
                            obf.write('\\\\\n')
                    else:
                        if icol < Ncol -2: obf.write('&\n')
                    iifig = iifig + 1
            elif irow == Nrow -1 and dorest == 'center':
                crestS = ''
                if Nrest != 0: 
                    for irc in range(Nrest): crestS = crestS + 'c'
                    obf.write('\\multicolumn{'+str(Ncol)+'}{c}{\\begin{tabular}{' +  \
                      crestS + '}\n')
                    for icol in range(Nrest):
                        fign = figs[iifig]
                        obf.write('\\includegraphics[' + widthheight + ']{' + fign + \
                          '}\n')
                        if icol < Nrest - 1:
                            obf.write('&\n')
                        else:
                            obf.write('\\end{tabular}}\n')
                        iifig = iifig + 1
                else:
                    # Case with images which fulfill the last row
                    for icol in range(Ncol):
                        fign = figs[iifig]
                        obf.write('\\includegraphics[' + widthheight + ']{' + fign + \
                          '}\n')
                        if icol < Ncol - 1:
                            obf.write('&\n')
                        iifig = iifig + 1
    
        obf.write('\\end{tabular}\n')
    else:
        print warnmsg
        print '  ' + fname + ': passed a single figure!!'
        fign = figs[0]
        obf.write('\\includegraphics[' + widthheight + ']{' +fign+ '}\n')

    obf.write('\\end{center}\n')
    obf.write('\\caption{' + figcaption + '}\n')
    obf.write('\\label{' + figlabel + '}\n')
    obf.write('\\end{figure}\n')
    obf.write('\n')

    return

def lstring_values(liststring,sepchar,finalchar):
    """ Function to provide a new list-string from a string which is a list of word separated by a character if some values
      are repeated they are not included
      liststring= string of [sepchar] separated list of words
      sepchar= original character used to separate different words
      finalchar= final character used to separated values at the resultant string
      >>> lstring_values('tas-tas','-',':')
      tas
      >>> lstring_values('tturb-xmean-last@tturb-xmean-last','@','-')
      tturb-xmean-last
    """
    fname = 'lstring_values'

    words = liststring.split(sepchar)
    newwords = []
    for word in words:
        if not searchInlist(newwords,word): newwords.append(word)

    newstring = finalchar.join(newwords)

    return newstring

#quit()

def int_to_roman(input, romanchar='U'):
   """
   FROM: http://code.activestate.com/recipes/81611-roman-numerals/
   Convert an integer to Roman numerals.
     input= number to transform
     romanchar= type of characters
       'l': lower romans: i, v, c, ...
       'U': upper romans: I, V, C, ... (default)
   Examples:
   >>> int_to_roman(0)
   Traceback (most recent call last):
   ValueError: Argument must be between 1 and 3999

   >>> int_to_roman(-1)
   Traceback (most recent call last):
   ValueError: Argument must be between 1 and 3999

   >>> int_to_roman(1.5)
   Traceback (most recent call last):
   TypeError: expected integer, got <type 'float'>

   >>> for i in range(1, 21): print int_to_roman(i)
   ...
   I
   II
   III
   IV
   V
   VI
   VII
   VIII
   IX
   X
   XI
   XII
   XIII
   XIV
   XV
   XVI
   XVII
   XVIII
   XIX
   XX
   >>> print int_to_roman(2000)
   MM
   >>> print int_to_roman(1999)
   MCMXCIX
   """
   if type(input) != type(1):
      raise TypeError, "expected integer, got %s" % type(input)
   if not 0 < input < 4000:
      raise ValueError, "Argument must be between 1 and 3999"   
   ints = (1000, 900,  500, 400, 100,  90, 50,  40, 10,  9,   5,  4,   1)
   if romanchar == 'U':
     nums = ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')
   elif romanchar == 'l':
     nums = ('m', 'cm', 'd', 'cd', 'c', 'xc', 'l', 'xl', 'x', 'ix', 'v', 'iv', 'i')
   else:
       print errormsg
       print '  ' + fname + ": roman char '" + romanchar + "' not ready!!"
       print "    authorized ones: 'U', 'l'"
       quit(-1)
   result = ""
   for i in range(len(ints)):
      count = int(input / ints[i])
      result += nums[i] * count
      input -= ints[i] * count
   return result

def roman_to_int(input, romanchar='U'):
   """
   FROM: http://code.activestate.com/recipes/81611-roman-numerals/
   Convert a roman numeral to an integer.
     input= roman number to transform
     romanchar= type of characters
       'l': lower romans: i, v, c, ...
       'U': upper romans: I, V, C, ... (default)
   >>> r = range(1, 4000)
   >>> nums = [int_to_roman(i) for i in r]
   >>> ints = [roman_to_int(n) for n in nums]
   >>> print r == ints
   1

   >>> roman_to_int('VVVIV')
   Traceback (most recent call last):
    ...
   ValueError: input is not a valid roman numeral: VVVIV
   >>> roman_to_int(1)
   Traceback (most recent call last):
    ...
   TypeError: expected string, got <type 'int'>
   >>> roman_to_int('a')
   Traceback (most recent call last):
    ...
   ValueError: input is not a valid roman numeral: A
   >>> roman_to_int('IL')
   Traceback (most recent call last):
    ...
   ValueError: input is not a valid roman numeral: IL
   """
   if type(input) != type(""):
      raise TypeError, "expected string, got %s" % type(input)
   input = input.upper()
   if romanchar == 'U':
       nums = ['M', 'D', 'C', 'L', 'X', 'V', 'I']
   elif romanchar == 'l':
       nums = ['m', 'd', 'c', 'l', 'x', 'v', 'i']
   else:
       print errormsg
       print '  ' + fname + ": roman char '" + romanchar + "' not ready!!"
       print "    authorized ones: 'U', 'l'"
       quit(-1)

   ints = [1000, 500, 100, 50,  10,  5,   1]
   places = []
   for c in input:
      if not c in nums:
         raise ValueError, "input is not a valid roman numeral: %s" % input
   for i in range(len(input)):
      c = input[i]
      value = ints[nums.index(c)]
      # If the next place holds a larger number, this value is negative.
      try:
         nextvalue = ints[nums.index(input[i +1])]
         if nextvalue > value:
            value *= -1
      except IndexError:
         # there is no next place.
         pass
      places.append(value)
   sum = 0
   for n in places: sum += n
   # Easiest test for validity...
   if int_to_roman(sum) == input:
      return sum
   else:
      raise ValueError, 'input is not a valid roman numeral: %s' % input

def linearint_weights(vals, intval):
    """ Function to provide the weights for a linear interpolation of a value between a couple of values as a weighted distance mean
      vals: couple of values
      intval: value to interpolate between [vals]
    >>> linearint_weights([1., 2.], 1.5)
    [0.5  0.5]
    >>> linearint_weights([-2., -1.], -1.0005)
    [  5.00000000e-04   9.99500000e-01]
    """
    fname = 'linear_weights'

    if vals[0] > vals[1]: 
        sign = 'neg'
    else:
        sign = 'pos'

    if sign == 'neg' and not (intval <= vals[0] and intval >= vals[1]):
        print errormsg
        print '  ' + fname + ': wrong value:', intval , ' to interpolate for:',      \
          vals, ' range'
        quit(-1)

    if sign == 'pos' and not (intval >= vals[0] and intval <= vals[1]):
        print intval >= vals[0]
        print intval <= vals[1]
        print errormsg
        print '  ' + fname + ': wrong value:', intval , ' to interpolate for:',      \
          vals, ' range'
        quit(-1)

    inc = np.abs(vals[0] - vals[1])
    linearwgt = [np.abs(intval - vals[0]), np.abs(intval - vals[1])]
    linearwgt = 1. - linearwgt / inc

    return linearwgt

def linearint_3x3weights(xvals, yvals, intval0):
    """ Function to provide the weights for a linear interpolation of a value inside a 3x3 matrix of values as a weighted distance mean
      xvals: 3x3 matrix of x-values
      yvals: 3x3 matrix of y-values
      intval: value to interpolate between [yintval, xintval]
      It returns: 
        * 3x3 matrix with weights (zero if are above the 4th shortest distacce, masked values for outside dx,dy positions) 
        * Number of closest grid points (<=4)
        * 2x9 matrix with distance-sorted positions within the 3x3 matrix
    xvals = ma.masked_equal(np.zeros(9).reshape(3,3),0.)
    xvals[:,0] = 1.
    xvals[:,1] = 2.
    xvals[:,2] = 3.
    xvals.mask[2,2] = True
    yvals = xvals.transpose()
    >>> linearint_3x3weights(xvals, yvals, [1.5, 2.5])
    (masked_array(data =
     [[0.0 0.25 0.25]
     [0.0 0.25 0.25]
     [0.0 0.0 --]],
                 mask =
     [[False False False]
     [False False False]
     [False False  True]],
           fill_value = 1e+20)
    , 4, array([[ 0,  0,  1,  1,  0,  1,  2,  2, -1],
           [ 1,  2,  1,  2,  0,  0,  1,  0, -1]]))
    """
    fname = 'linear_3x3wegiths'

    intval = np.array(intval0, dtype=np.float)

    # Check data
    nx = xvals.min()
    xx = xvals.max()
    ny = yvals.min()
    xy = yvals.max()

    #print 'Lluis intval:', intval
    #print '  ' + fname + ' Lluis xvals ____'
    #print xvals

    #print '  ' + fname + ' Lluis yvals ____'
    #print yvals

    if not intval[1] >= nx and intval[1] <= xx:
        print errormsg
        print '  ' + fname + ': wrong value:', intval[1] , ' to interpolate for ' +  \
          'x-range:'
        for i in range(3):
            print '    ', xvals[:,i]
        quit(-1)
    if not intval[0] >= ny and intval[0] <= xy:
        print errormsg
        print '  ' + fname + ': wrong value:', intval[0] , ' to interpolate for ' +  \
          'y-range:'
        for i in range(3):
            print '    ', yvals[:,i]
        quit(-1)

    dist = np.sqrt( (xvals-intval[1])**2 + (yvals-intval[0])**2)
    inc = np.sum(dist)
    #print 'inc:', inc, 'intval', intval, 'dist ___'
    #for i in range(3):
    #    print dist[:,i]

    ijvals = dist.copy()
    distpos = np.ones((2,9), dtype=int)*(-1)

    # shortest minium distance
    sortdist = list(dist.compressed())
    sortdist.sort()
    iijj = 0    
    if sortdist[0] == 0.:
        ij = index_mat(ijvals,0.)
        distpos[:,iijj] = ij[:]
        wgt = np.zeros((3,3), dtype=np.float)
        wgt[ij[0], ij[1]] = 1.
        return wgt, 1, distpos

    # Getting ij values of distances, removing he already localized values
    iijj = 0
    for ijdist in sortdist:
        if ijdist is not ma.masked:
            ij = index_mat(ijvals,ijdist)
            distpos[:,iijj] = ij[:]
            ijvals[ij[0],ij[1]] = fillValueF
            iijj = iijj + 1

    # Normalizing values (only the first 4)
    if iijj >= 3:
        inc = np.sum(1./np.array(sortdist[0:4]))
        maxdist = sortdist[3]
        Nvals = 4
    else:
        inc = np.sum(1./np.array(sortdist[0:iijj]))
        maxdist = sortdist[iijj]
        Nvals = iijj

    wgt = np.where(dist <= maxdist, 1./dist/inc, 0.)
    # Case with more than 4 points with less distance than `maxdist' (point at the diagonal)
    if np.sum(wgt) > 1.000001:
        print 'maxdist:', maxdist
        wgt = np.where(dist <= maxdist, dist, 0.)
        inc = 0.
        wgtflat = wgt.flatten()
        for i in range(9):
            if wgtflat[i] > 0.: inc = inc + 1./wgtflat[i]
        wgt = np.where(wgt > 0., 1./wgt/inc, 0.)
        Nvals = np.sum(wgt > 0.)

    if np.all(wgt == 0.):
        print errormsg
        print '  ' + fname + ': no point found !!'
        print '    point to interpolate:', intval0, ' around x & y & dist _____'
        for i in range(3):
            print xvals[:,i], '&', yvals[:,i], '&', dist[:,i]
        print '    sortdist:', sortdist, 'weights _____'
        for i in range(3):
            print wgt[:,i]
        quit(-1)

#    print 'Lluis weights _______', sortdist[0:4],'max:',maxdist,'sum:',np.sum(wgt)
#    for i in range(3):
#        print wgt[:,i]

    return wgt, Nvals, distpos
 
def curvelocalize_2D(curve,xvals,yvals):
    """ Function to provide the localization a curve in a 2D field of positions via the equivalent i,j-quads 
      within which the curve lays (-1, no value for the given quad [2x2 points around]) and provide the weights
      of the quad to perform a distance-weighted mean at the given curve point
             x,y_j,i       x,y_j,i+1

                curve(k)

                           curve(k+1)

             x,y_j-1,i     x,y_j-1,i+1

      curve= [2, Npts] matrix of values of the curve
        yval0, xval0
        yval1, xval1
        (...)
        yvalNpts, xvalNpts
      xvals= 2D matrix of x-coordinate values
      yvals= 2D matrix of y-coordinate values
      RETURNS: 
        curvloc= [Npts,2] matrix with the closest i,j grid point in the 2D space of the field positions
        curvweights= [Npts,3,3] 3x3 matrix weights around the curve position
        Nwgt= Number of weights
        ijaorund3x3= [Npts,2,9] distance (in xval, yval units) to the curve position
        exctcurvloc= [Npts,2] matrix with the exact i,j grid point in the 2D space of the field positions
    """
    fname = 'curvelocalize_2D'

    Npts = curve.shape[0]

    curvloc = np.ones((curve.shape), dtype=int)*(-1)
    Nwgts = np.zeros((Npts), dtype=int)
    curveweights = np.zeros((Npts,3,3), dtype=np.float)
    ijaround3x3 = np.zeros((Npts,2,9), dtype=int)
    exctcurvloc = np.ones((curve.shape), dtype=np.float)*(-1)

    for icv in range(Npts):
        # Closest grid-point
        dist = np.sqrt((xvals - curve[icv,1])**2 + (yvals - curve[icv,0])**2)
        mindist = np.min(dist)
        ijloc = index_mat(dist,mindist)

        if np.any(ijloc == -1): 
            print errormsg
            print '  ', fname, ': curve position:', curve[icv,:], 'not found !!'
            quit(-1)
        curvloc[icv,0] = ijloc[0]
        curvloc[icv,1] = ijloc[1]

        # Values around the nearest 2D-point to the curve point
        xaroundvls = vals_around(xvals,ijloc)
        yaroundvls = vals_around(yvals,ijloc)

        curveweights[icv,:,:], Nwgts[icv], ijaround3x3[icv,:,:] =                    \
          linearint_3x3weights(xaroundvls, yaroundvls, curve[icv,:])
        exctcurvloc[icv,:] = curvloc[icv,:]

        for ip in range(Nwgts[icv]):
            ipy = ijaround3x3[icv,0,ip]
            ipx = ijaround3x3[icv,1,ip]
            exctcurvloc[icv,0] = np.float(exctcurvloc[icv,0]) + curveweights[icv,ipy,ipx]*(ipy-1.)
            exctcurvloc[icv,1] = np.float(exctcurvloc[icv,1]) + curveweights[icv,ipy,ipx]*(ipx-1.)
            #print '    ' + fname + 'ip:', ip, 'ipy:', ipy-1., 'wgt:', curveweights[icv,ipy,ipx], \
            #  'exctcurv:', exctcurvloc[icv,0]
        #print '  ' + fname + ' icv:', icv, 'curve:', curve[icv,:], 'ijloc:', ijloc, \
        #  'cwgt:', curveweights[icv,:,:], 'exctloc:', exctcurvloc[icv,:]
#    quit()

    return curvloc, curveweights, Nwgts, ijaround3x3, exctcurvloc
#
#lon1d = np.arange(10)
#lat1d = np.arange(-5,5)
#dx = lon1d.shape[0]
#dy = lat1d.shape[0]
#
#lons = np.zeros((dy,dx), dtype=np.float)
#lats = np.zeros((dy,dx), dtype=np.float)
#
#for iy in range(dy):
#    lons[iy,:] = lon1d
#for ix in range(dx):
#    lats[:,ix] = lat1d
#
#Ncurve = 12
#iicurve = 0
#eicurve = dx-1
#ijcurve = 1
#ejcurve = dy-3
#iloncurve = lon1d[iicurve]
#eloncurve = lon1d[eicurve]
#ilatcurve = lat1d[ijcurve]
#elatcurve = lat1d[ejcurve]
#Dxcurve = (eloncurve-iloncurve)/(Ncurve-1.)
#Dycurve = (elatcurve-ilatcurve)/(Ncurve-1.)
#
#curve = np.zeros((Ncurve,2), dtype=np.float)
#for icv in range(Ncurve):
#    curve[icv,0] = ilatcurve + Dycurve*icv
#    curve[icv,1] = iloncurve + Dxcurve*icv
#
#print 'Curve origin:', ilatcurve, ',', iloncurve
#print 'Curve ending:', elatcurve, ',', eloncurve
#
#print curve
#
#loccurve, wgts, Nwgts, loc3x3, exctloccurve = curvelocalize_2D(curve,lons,lats)
#for ipt in range(Ncurve):
#    print 'pos:', ipt, 'curve:', curve[ipt,:],'loccurve:', loccurve[ipt,:], 'wgts:', wgts[ipt,:,:], 'Nwgts:', Nwgts[ipt], 'loc3x3:', loc3x3[ipt,:], 'exctloccurve:', exctloccurve[ipt,:]
#    for iw in range(Nwgts[ipt]):
#        iwy = loc3x3[ipt,0,iw]
#        iwx = loc3x3[ipt,1,iw]
#        print '   sort wgts:', iw,' iwy,iwx:', iwy,',',iwx, 'wgt:', wgts[ipt,iwy,iwx]

def num_ordinal(num, lang='eng', kind='numOr', fmt='ascii', gender='masc'):
    """ Function to provide the ordinal of a given number, language, format and gender
      num= number to provide the ordinal
      lang= language of the ordinal
        'eng': English
      kind= kind of the ordinal
        'numOr': as num[Ord]
        'Ordinal': long ordinal (not fully ready)
      fmt= format of the ordinal
        'ascii': standard ASCII
        'utf': utf-8 (with accents)
      gender= gender of the ordinal
        'fem': femenin
        'masc': masculin
      >>> num_ordinal(2, 'eng', 'numOr', 'ascii')
      '2nd'
      >>> num_ordinal(2, 'eng', 'Ordinal', 'ascii')
      'second'
      >>> num_ordinal(7, 'cat', 'Ordinal', 'utf')
      'setè'
      >>> num_ordinal(1, 'cat', 'Ordinal', 'utf', fem)
      'primera'
    """
    fname = 'num_ordinal'

    languages = ['cat', 'eng']
    kinds = ['numOr', 'Ordinal']
    formats = ['ascii', 'utf']
    genders = ['fem', 'masc']

    if not searchInlist(languages, lang):
        print errormsg
        print '  ' + fname + ": language '" + lang + "' not ready !!"
        print '    available ones:', languages
        quit(-1)

    if not searchInlist(kinds, kind):
        print errormsg
        print '  ' + fname + ": kind '" + kind + "' not ready !!"
        print '    available ones:', kinds
        quit(-1)

    if not searchInlist(formats, fmt):
        print errormsg
        print '  ' + fname + ": format '" + fmt + "' not ready !!"
        print '    available ones:', fomrats
        quit(-1)

    if not searchInlist(genders, gender):
        print errormsg
        print '  ' + fname + ": gender '" + gender + "' not ready !!"
        print '    available ones:', genders
        quit(-1)

    # Catalan
    # short ordinals  ([fem, masc])
    catord = {1: ['era', 'er'], 2: ['ona', 'on'], 3: ['era', 'er'], 4: ['rta', 'rt']}
    # Last special ordinal
    catlastord = 4
    # generic ordinal ([fem, masc])
    catgenord = ['ena', 'è']
    # long ordinals
    catLord = {1: ['primera', 'primer'], 2: ['segona', 'segon'], 3: ['tercera',      \
      'tercer'], 4: ['quarta', 'quart'], 5: ['cinquena', 'cinquè'], 6: ['sisena',    \
      'sisè'], 7: ['setena', 'setè'], 8: ['vuitena', 'vuitè'], 9: ['novena', 'novè']}

    # English 
    # short ordinals ([fem, masc])
    engord = {1: ['st', 'st'], 2: ['nd', 'nd'], 3: ['rd', 'rd']}
    # Last special ordinal
    englastord = 3
    # generic ordinal ([fem, masc])
    enggenord = ['th','th']
    # long ordinals
    engLord = {1: ['first', 'first'], 2: ['second', 'second'], 3: ['third', 'third'],\
      4: ['fourth', 'fourth'], 5: ['fifth', 'fifth'],  6: ['sixth','sixth'],         \
      7: ['seventh', 'seventh'], 8: ['eight', 'eight'], 9: ['nineth', 'nineth']}

    if lang == 'cat':
        ords = catord
        lastord = catlastord
        genord = catgenord
        Lords = catLord
    elif lang == 'eng':
        ords = engord
        lastord = englastord
        genord = enggenord
        Lords = engLord

    Snum = str(num)
    if num > 10:
        LSnum = len(Snum)
        Senu = Snum[LSnum:LSnum+1]
    else:
        Senu = Snum

    # Ordinal
    if num < lastord:
       Ord = ords[num]
    else:
       Ord = genord 
    if gender == 'fem': Sord = Ord[0]
    else: Sord = Ord[1]

    # Long ordinal
    if num < 10:
       LOrd = Lords[num]
    else:
       print warnmsg
       print '  ' + fname + ' long ordinal not ready for:', num, '!!'
       LOrd = 'None'
    if gender == 'fem': SLord = LOrd[0]
    else: SLord = LOrd[1]

    if kind == 'numOr':
        stringv = Sord
    elif kind == 'Ordinal':
        stringv = SLord
    else:
        print errormsg
        print '  ' + fname + ": kind '" + kind + "' not ready !!"
        print '    available ones:', kinds
        quit(-1)

    return stringv

def auto_val(valchk, aval):
    """ Function to provide a value following an 'auto' configuration
      valchk= value to take (if != 'auto'), value is transformed to the type(aval)
      aval= value to take when it is configured as 'auto'
      >>> auto_val('auto', 3.)
      3.
      >>> auto_val('2.3456', 3.)
      2.3456
    """
    fname = 'auto_val'

    if valchk == 'auto':
        autoval = aval
    else:
        autoval = retype(valchk, type(aval))

    return autoval

def rectangular_spiral(Ntimes, dunits):
    """ Function to provide a rectangular spiral (along x,y-axis values) of values
      Ntimes: number of loops of the spiral (increasing by 1 along each axis
      dunits: units interval from which assign a value for each spiral value
    >>> rectangular_spiral(3, 3600.)
    array([ 0.,  1.,  1.,  0., -1., -1., -1.,  0.,  1.,  2.,  2.,  0., -2., -2., -2.,  
        0 array([ 0.,  0.,  1.,  1.,  1.,  0., -1., -1., -1.,  0.,  2.,  2.,  2.,
        0., -2., -2., -2.,  0.,  3.,  3.,  3.,  0., -3., -3., -3.]), [0.0, 3600.0, 
        7200.0, 10800.0, 14400.0, 18000.0, 21600.0, 25200.0, 28800.0, 32400.0, 36000.0, 
        39600.0, 43200.0, 46800.0, 50400.0, 54000.0, 57600.0, 61200.0, 64800.0, 68400.0, 
        72000.0, 75600.0, 79200.0, 82800.0, 86400.0])
    """
    fname = 'rectangular_spiral'

    # Wind test values
    uwindtestv0 = [1., 1., 0., -1., -1., -1., 0., 1. ]
    vwindtestv0 = [0., 1., 1., 1., 0., -1., -1., -1. ]

    Nvals = len(uwindtestv0)

    uwindtestv = np.zeros((Nvals*Ntimes+1), dtype=np.float)
    vwindtestv = np.zeros((Nvals*Ntimes+1), dtype=np.float)

    for i in range(Ntimes):
        uwindtestv[i*Nvals+1:(i+1)*Nvals+1] = np.array(uwindtestv0)*(i+1)
        vwindtestv[i*Nvals+1:(i+1)*Nvals+1] = np.array(vwindtestv0)*(i+1)

    dimt = len(uwindtestv)
    twindtestv = []
    for it in range(dimt):
        twindtestv.append(dtsecs*it)

    return uwindtestv, vwindtestv, twindtestv

def timefmt_timelab(timefmt):
    """ Function to transform from C-like time format to general one
      timefmt= C-like instruction for time
      %y as [YY], %Y as [YYYY], %m as [MM], %d as [DD], %h as [HH], %M as [MI], %S as [SS]
    >>> timefmt_timelab('$%d^{%H}$')
    $[DD]^{[HH]}$
    """
    fname = 'timefmt_timelab'

    # Dictionary wtth the equivalencies
    dictchanges = {'%y': '[YY]', '%Y': '[YYYY]', '%m': '[MM]', '%d': '[DD]',         \
      '%H': '[HH]', '%M': '[MI]', '%S': '[SS]'}
    timelab = timefmt
    for chg in dictchanges.keys():
        newv = dictchanges[chg]
        timelab = timelab.replace(chg, newv)

    if timelab.find('%') != -1:
        print warnsmg
        print '  '+fname+": unsuccesfull substitution of all C-like values from '" + \
          timefmt + "' !!"

    return timelab

def grib_CFequiv(gribcode, table):
    """ Function to provide the CF name of a GRIB variable code number
      gridcode= grib number to search for the reference
      table= gribd table reference
      returns list with [CFname], [GRistdbname], [Griblong_name], [Gribunits]]
    >>> grib_CFequiv(129, '128ECMWF')
    ['z', 'Z', 'Geopotential', 'm2s-2']
    """
    fname = 'grib_CFequiv'

    availtables = ['128ECMWF']

    if table == '128ECMWF':
        # Source: https://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc
        
        gribCF = {129: ['z', 'z', 'Geopotential', 'm2 s-2'],                         \
          130: ['ta', 't', 'Temperature', 'K'],                                      \
          131: ['ua', 'u', 'U velocity', 'm s-1'],                                   \
          132: ['va', 'v', 'U velocity', 'm s-1'],                                   \
          134: ['ps', 'sp', 'Surface pressure', 'Pa'],                               \
          151: ['psl', 'msl', 'Mean sea-level pressure', 'Pa'],                      \
          157: ['hur', 'r', 'Relative humidity', '%']}
    
    else:
        print errormsg
        print '  ' + fname + ": grib table '" + table + "' not ready !!"
        print '    available ones:', availtables
        quit(-1)

    if not gribCF.has_key(gribcode):
        print errormsg
        print '  ' + fname + ": table '" + table + "' does not have grib code :",    \
          gribcode, '!!'
        print '   available ones:', gribCF.keys() 
        quit(-1)

    CFname = gribCF[gribcode]

    return CFname

def CF_gribequiv(CFname, table):
    """ Function to provide the GRIB variable code number from a CF name
      CFname= CF-variable name
      table= gribd table reference
    >>> CF_gribequiv('ua', '128ECMWF')
    [131, 'U', 'U velocity', 'm s-1']
    """
    fname = 'CF_gribequiv'

    availtables = ['128ECMWF']

    if table == '128ECMWF':
        # Source: https://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc
        gribCF = {129: ['z', 'z', 'Geopotential', 'm2 s-2'],                         \
          130: ['ta', 't', 'Temperature', 'K'],                                      \
          131: ['ua', 'u', 'U velocity', 'm s-1'],                                   \
          132: ['va', 'v', 'U velocity', 'm s-1'],                                   \
          134: ['ps', 'sp', 'Surface pressure', 'Pa'],                               \
          151: ['psl', 'msl', 'Mean sea-level pressure', 'Pa'],                      \
          157: ['hur', 'r', 'Relative humidity', '%']}
    
    else:
        print errormsg
        print '  ' + fname + ": grib table '" + table + "' not ready !!"
        print '    available ones:', availtables
        quit(-1)

    # Inverting dictionaries (no need to hand write two dictionaries!)
    # For single values
    # FROM: http://stackoverflow.com/questions/483666/python-reverse-invert-a-mapping
    # CFgrib = dict((gribCF[k], k) for k in gribCF)
    CFgrib = {}
    for kv in gribCF.keys():
        vals = gribCF[kv]
        newkv = vals[0]
        vals[0] = kv
        CFgrib[newkv] = vals

    if not CFgrib.has_key(CFname):
        print errormsg
        print '  ' + fname + ": table '" + table + "' does not have CF name :" +     \
          CFname + "' !!"
        print '   available ones:', CFgrib.keys() 
        quit(-1)

    gribcode = CFgrib[CFname]

    return gribcode

def crossingpoint_2Dlines(line1, line2):
    """ Function to determinant the crossing point between two lines in a plane
      line1= [a,b,c] terms of the polynomial representation of line1 ax+by+d
      line2= [a,b,c] terms of the polynomial representation of line2 ax+by+d
    >>> crossingpoint_2Dlines(np.array([1,-1,0]), np.array([1,1,-3]))
    [[ 1.5  1.5]]
    """
    fname = 'crossingpoint_2lines'

    if len(line1.shape) != len(line2.shape):
        print errormsg
        print '  ' + fname + ': rank difference between lines !!'
        print '    shape line1:', line1.shape, 'line2:', line2.shape
        quit(-1)

    #determinant
    matA = np.array([line1[0:2], line2[0:2]])
    detA = np.linalg.det(matA)

    # x-det
    matX = np.array([[-line1[2],-line1[1]], [line2[2],line2[1]]])
    detX = np.linalg.det(matX)

    # y-det
    matY = np.array([[line1[0],line1[2]], [-line2[0],-line2[2]]])
    detY = np.linalg.det(matY)

    #print 'mat A:'
    #print matA
    #print 'mat X:'
    #print matX
    #print 'mat Y:'
    #print matY

    #print 'det A:', detA, 'X:', detX, 'Y:', detY

    x = detX / detA
    y = detY / detA

    return np.array([[x, y]])

#print crossingpoint_2Dlines(np.array([1,-1,0]), np.array([1,1,-3]))

def points_2Dline(pt1, pt2):
    """ Function to define a line from a pair of points on a plane
          it returns the terms of the polynomial description of the line ax+by+c=0 [a,b,c]
      pt1= first point [x,y]
      pt2= second point [x,y]
    >>> points_2Dline(np.array([1,1]), np.array([2,2]))
    [1 -1 0]
    points_2Dline(np.array([1,2]), np.array([2,1]))
    [1 1 -3]
    """
    fname = 'points_2Dline'

    # minus
    minuseq = pt1 - pt2
    b = -minuseq[0]/minuseq[1]

    # plus
    pluseq = pt1 + pt2  
    subsb = pluseq[1]*b

    subsa = pluseq[0] + subsb

    c = -subsa/2

    return np.array([1, b, c])

def provide_slices(dimns, dimzs, rundims):
    """ Function to provide a list of slices for a matrix giving a sub-section of running dimensions
        dimns: list of names of dimensions
        dimzs: list of sizes of dimensions in the same order as in [dimns]
        rundims: name of dimensions to allow to run
    >>> provide_slices(['z', 't', 'y', 'x'], [2, 3, 10, 20], ['t', 'z', 'l'])
    [[1, 2, slice(0, 10, None), slice(0, 20, None)], 
     [0, 1, slice(0, 10, None), slice(0, 20, None)], 
     [1, 1, slice(0, 10, None), slice(0, 20, None)], 
     [0, 0, slice(0, 10, None), slice(0, 20, None)], 
     [1, 0, slice(0, 10, None), slice(0, 20, None)], 
     [0, 2, slice(0, 10, None), slice(0, 20, None)]]
    """
    fname = 'provide_slices'

    Ndims = len(dimns)

    # Checking presence of dimension in list of dimensions
    Tslicesize = 1
    origslicesize = {}
    runslicesize = {}
    for dimn in rundims:
        if not searchInlist(dimns, dimn):
            #print warnmsg
            #print '  ' + fname + ": dimension '" + dimn + "' not in list !!"
            #print '    removing it'
            rundims.remove(dimn)

    for dimn in dimns:
        idim = index_vec(dimns, dimn)
        origslicesize[dimn] = dimzs[idim]
        if searchInlist(rundims, dimn):
            runslicesize[dimn] = dimzs[idim] - 1
            Tslicesize = Tslicesize*dimzs[idim]

    #print '  ' + fname + ': Total number of slices to provide:', Tslicesize,         \
    #  'along:', runslicesize

    slices = []
    for il in range(Tslicesize):
        islice = []
        alreadychanged = False
        for idim in range(Ndims):
            dimn = dimns[idim]
            if searchInlist(rundims,dimn):
                islice.append(runslicesize[dimn])
                # Only running value for a given dimension for the next
                if not alreadychanged:
                    runslicesize[dimn] = runslicesize[dimn] - 1
                    alreadychanged = True
                    if runslicesize[dimn] < 0:
                        runslicesize[dimn] = origslicesize[dimn] - 1
                        for rdimn in rundims:
                            if rdimn != dimn:
                                runslicesize[rdimn] = runslicesize[rdimn] - 1
                                if runslicesize[rdimn] >= 0:
                                    break
                                else:
                                    runslicesize[rdimn] = origslicesize[rdimn] - 1
            else:
                islice.append(slice(0,origslicesize[dimn]))

        slices.append(islice)

    return slices

#quit()
