def append_Time_andDatetime_to_netcdf(fname_davitnc, fname_mossconc=None, time_var_name='time', dummy_values=False, log=True):
        # --------------------------------------------------
        # 3.1) fill netcdf with time variables (TIME and DATATIME)
        # --------------------------------------------------
        if dummy_values is False:

            _nc = Dataset(fname_mossconc, mode='r')
            time_var_units = _nc.variables[time_var_name].units
            max_t          = _nc.variables[time_var_name][:].max()
            min_t          = _nc.variables[time_var_name][:].min()
            _nc.close()
        else:
            time_var_units = 'seconds since 2000-01-01 00:00:00'
            max_t = 60*60*24
            min_t = 0



        var = process_cdl.cdlVariable()
        var.set_name('nMesh2_time')
        var.set_dtype('double')
        var.set_dims(('nMesh2_time', ))
        var.set_fillvalue(False)
        var.set_attr('long_name', "time")
        # because currently MOSSCO writes a time output as "hours since 2009-01-02 00:00:00",
        # it is nessesary to modify it. Will be removed, after corrections in MOSSCO.
        var.set_attr('units', time_var_units+' 01:00')  # '01:00 is indicating timezone, see CF conventions for details'
        var.set_attr('name_id', 1640)
        var.set_attr('axis', "T")
        var.set_attr('bounds', "nMesh2_time_bnd")
        var.set_attr('calendar', "gregorian")
        var.set_attr('standard_name', "time")
        if dummy_values:
            var.set_attr('comment', "warning: dummy values are used")


        var_data = np.array([min_t])
        append_VariableData_to_netcdf(fname_davitnc, var, var_data, fv=var.get_fillvalue(), log=log)
        del var
        

        var = process_cdl.cdlVariable()
        var.set_name('nMesh2_time_bnd')
        var.set_dtype('double')
        var.set_dims(('nMesh2_time', 'two'))
        var.set_fillvalue(False)
        if dummy_values:
            var.set_attr('comment', "warning: dummy values are used")

        var_data = np.array([min_t, max_t])
        append_VariableData_to_netcdf(fname_davitnc, var, var_data, fv=var.get_fillvalue(), log=log)
        del var


        if dummy_values is False:
            var = process_cdl.cdlVariable()
            var.set_name('nMesh2_data_time')
            var.set_dtype('double')
            var.set_dims(('nMesh2_data_time', ))
            var.set_fillvalue(False)
            var.set_attr('long_name', "time")
            var.set_attr('units', time_var_units + ' 01:00')
            var.set_attr('name_id', 1640)
            var.set_attr('axis', "T")
            var.set_attr('calendar', "gregorian")
            var.set_attr('standard_name', "time")
            var_data = process_mossco_netcdf.read_mossco_nc_1d(fname_mossconc, 'time')
            append_VariableData_to_netcdf(fname_davitnc, var, var_data, fv=var.get_fillvalue(), log=log)
            del var
def append_sigma_vertical_coord_vars(list_with_filenames, nLayers, nc_out_fname, add_eta=False, add_depth=False, mask=None, sigma_varname='level', log=False):
    ''' Appends variables that define vertical position of layers...
            - nMesh2_layer_3d                       >>> 1d sigma coords of cell center
            - Mesh2_face_z_face_3d                  >>> elevation cell center values
            - Mesh2_face_z_face_3d_bnd              >>> elevation cell border values
            - (optionaly) Mesh2_face_Wasserstand_2d >>> water level
            - (optionaly) Mesh2_face_depth_2d       >>> bottom depth
        ... to passed `nc_out_fname` netcdf file
        
    Args:
    -----
        list_with_filenames (list of str):
            list with names of netcdf files. The var `sigma_varname` will be searched within this files
        nLayers (int):
            number of vertical layers
        nc_out_fname (str):
            filename of the output netcdf file
        add_eta (bool):
            flag to add variable "Mesh2_face_Wasserstand_2d" to file `nc_out_fname`.
            This is useful because, most likely this var is already appended or will be
            appended to file based on DICTIONARY4
        add_depth (bool):
            flag to add variable "Mesh2_face_depth_2d" to file `nc_out_fname`
            This is useful because, most likely this var is already appended or will be
            appended to file based on DICTIONARY4
        mask (2D array of bool):
            2d array of (y, x) dimensions with boolean mask (to treat NaN cells)
        sigma_varname (str):
            name of the varable to get sigma-layer info from
        log (bool):
            flag to print output
        
    '''
    _i = '\t'
    _n = 'append_sigma_vertical_coord_vars()'
    sprint(_n, 'Appending sigma_vertical coordinates ...', log=log, mode='bold')
    # ----------------------------------------
    # ----------------------------------------
    # ---------------  SIGMA   ---------------
    # ----------------------------------------
    # ----------------------------------------
    var = process_cdl.cdlVariable()
    var.set_name('nMesh2_layer_3d')
    var.set_dtype('double')
    var.set_dims(('nMesh2_layer_3d', ))
    var.set_fillvalue(False)
    var.set_attr('standard_name', 'ocean_sigma_coordinate')
    var.set_attr('long_name', "sigma at layer midpoints")
    var.set_attr('positive', 'up')
    var.set_attr('formula_terms', 'sigma: nMesh2_layer_3d eta: Mesh2_face_Wasserstand_2d depth: Mesh2_face_depth_2d')

    sigma, sigma_type = process_mossco_netcdf.get_sigma_coordinates(list_with_filenames, nLayers, sigma_varname=sigma_varname, waterdepth_varname='water_depth_at_soil_surface', layerdepth_varname='getmGrid3D_getm_layer', indent=_i, log=log)
    if sigma_type == 'center':
        pass
    elif sigma_type == 'border':
        sigma = process_mixed_data.create_sigma_coords_of_layer_center(sigma)

    append_VariableData_to_netcdf(nc_out_fname, var, sigma, fv=var.get_fillvalue(), log=log, indent=_i)
    del var

    bathymetry = None
    for nc_file in list_with_filenames:
        root_grp = Dataset(nc_file, mode='r')
        if 'bathymetry' in root_grp.variables.keys() and bathymetry is None:
            bathymetry = process_mossco_netcdf.read_mossco_nc_rawvar(nc_file, 'bathymetry')
        root_grp.close()
        del root_grp

    # ----------------------------------------
    # ----------------------------------------
    # ---------------  ETA   -----------------
    # ----------------------------------------
    # ----------------------------------------
    var_e = process_cdl.cdlVariable()
    var_e.set_name('Mesh2_face_Wasserstand_2d')
    var_e.set_dtype('float')
    var_e.set_dims(('nMesh2_data_time', 'nMesh2_face'))
    var_e.set_fillvalue(False)
    var_e.set_attr('long_name', "Wasserstand, Face (Polygon)")
    var_e.set_attr('standard_name', 'sea_surface_height')
    var_e.set_attr('units', 'm')
    var_e.set_attr('name_id', 3)
    var_e.set_attr('cell_measures', 'area: Mesh2_face_wet_area')
    var_e.set_attr('cell_measures', 'nMesh2_data_time: point area: mean')
    var_e.set_attr('coordinates', 'Mesh2_face_x Mesh2_face_y Mesh2_face_lon Mesh2_face_lat')
    var_e.set_attr('grid_mapping', 'Mesh2_crs')
    var_e.set_attr('mesh', 'Mesh2')
    var_e.set_attr('location', 'face')

    sprint(_n, ' Get waterlevel ...', log=log, mode='bold')
    water_level = process_mossco_netcdf.get_water_level(list_with_filenames, wl_vname='water_level',
                    water_depth_at_soil_surface_vname='water_depth_at_soil_surface', bathymetry_vname='bathymetry',
                    log=log, indent=_i)
    # append var after


    # ----------------------------------------
    # ----------------------------------------
    # --------------  DEPTH   ----------------
    # ----------------------------------------
    # ----------------------------------------
    var_d = process_cdl.cdlVariable()
    var_d.set_name('Mesh2_face_depth_2d')
    var_d.set_dtype('double')
    var_d.set_dims(('nMesh2_time', 'nMesh2_face'))
    var_d.set_fillvalue(False)
    var_d.set_attr('long_name', "Topographie")
    var_d.set_attr('standard_name', 'sea_floor_depth_below_geoid')
    var_d.set_attr('units', 'm')
    var_d.set_attr('name_id', 17)
    var_d.set_attr('cell_measures', 'area: Mesh2_face_area')
    var_d.set_attr('cell_measures', 'nMesh2_time: mean area: mean')
    var_d.set_attr('coordinates', 'Mesh2_face_x Mesh2_face_y Mesh2_face_lon Mesh2_face_lat')
    var_d.set_attr('grid_mapping', 'Mesh2_crs')
    var_d.set_attr('mesh', 'Mesh2')
    var_d.set_attr('location', 'face')
    # append var after

    # ----------------------------------------
    # ----------------------------------------
    # ------------  ELEVATION   --------------
    # ----------------------------------------
    
    # ----------------------------------------
    # FACE cell center values.....
    # ----------------------------------------
    var1 = process_cdl.cdlVariable()
    var1.set_name('Mesh2_face_z_face_3d')
    var1.set_dtype('float')
    var1.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_face'))
    var1.set_fillvalue(None)
    var1.set_attr('long_name', 'z_face [ face ]')
    var1.set_attr('units', 'm')
    var1.set_attr('positive', 'up')
    var1.set_attr('name_id', 1702)
    var1.set_attr('bounds', 'Mesh2_face_z_face_bnd_3d')
    var1.set_attr('standard_name', 'depth')
   
    # ----------------------------------------
    # FACE cell border values.....
    # ----------------------------------------
    var2 = process_cdl.cdlVariable()
    var2.set_name('Mesh2_face_z_face_bnd_3d')
    var2.set_dtype('float')
    var2.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_face', 'two'))
    var2.set_fillvalue(None)
    var2.set_attr('long_name', 'elevations of lower and upper layer-boundaries')
    var2.set_attr('units', 'm')

    sprint(_n, ' Get elevation of cell centers and cell borders ...', log=log, mode='bold')
    elev, elev_borders = process_mixed_data.create_layer_elevation_from_sigma_coords(water_level, sigma, bathymetry, log=log, indent=_i)
    

    var_data1  = process_mixed_data.flatten_xy_data(elev, mask=mask)
    var_data2 = process_mixed_data.flatten_xy_data(elev_borders, mask=mask)
    
    append_VariableData_to_netcdf(nc_out_fname, var1, var_data1, fv=var1.get_fillvalue(), log=log, indent=_i)
    append_VariableData_to_netcdf(nc_out_fname, var2, var_data2, fv=var2.get_fillvalue(), log=log, indent=_i)
    del var1, var2



    if add_depth:
        var_data = process_mixed_data.flatten_xy_data(bathymetry, mask=mask)
        append_VariableData_to_netcdf(nc_out_fname, var_d, var_data, fv=var_d.get_fillvalue(), log=log, indent=_i)
        del var_d
    if add_eta:
        var_data = process_mixed_data.flatten_xy_data(water_level, mask=mask)
        append_VariableData_to_netcdf(nc_out_fname, var_e, var_data, fv=var_e.get_fillvalue(), log=log, indent=_i)
        del var_e

    if log:
        print '-'*25+'\n'
def append_test_Mesh2_face_z_3d_and_Mesh2_face_z_3d_bnd(fname_davit, nx=0, ny=0, mask=None, log=False):
    '''
                    DUMMY VALUES!!!
    Function appends to DAVIT netcdf following variables:
        Mesh2_face_z_face_3d
        Mesh2_face_z_face_bnd_3d
        Mesh2_edge_z_edge_3d
        Mesh2_edge_z_edge_bnd_3d

    The data stored is artificial (!!!):
        - layers are in down-positiv order (first layer is at surface)
        - each layer is 1m thick
        - layer-borders are (0,1), (1,2), (2,3), ..., (NLAYERS-1, NLAYERS) in meters
    '''
    '''
    INPUT:
        fname_davit, fname_mossco  - strings, pathes to files
        mask - an boolean mask 2D array. See function process_mossco_netcdf.make_mask_array_from_mossco_bathymetry()
        log  - boolean Flag to print output in console


    CDL EXAMPLE:
    float Mesh2_face_z_face_3d(nMesh2_data_time, nMesh2_layer_3d, nMesh2_face) ;
        Mesh2_face_z_face_3d:long_name = "z_face [ face ]" ;
        Mesh2_face_z_face_3d:units = "m" ;
        Mesh2_face_z_face_3d:name_id = 1702 ;
        Mesh2_face_z_face_3d:positive = "down" ;
        Mesh2_face_z_face_3d:bounds = "Mesh2_face_z_face_bnd_3d" ;
        Mesh2_face_z_face_3d:standard_name = "depth" ;
    '''

    if log: print 'running: append_test_Mesh2_face_z_3d_and_Mesh2_face_z_3d_bnd()'
    
    # get dimensions....
    # ----------------------------------------------------------------------------
    _nc = Dataset(fname_davit, mode='r')
    try:
        nt = _nc.dimensions['nMesh2_data_time'].__len__()
    except:
        nt = _nc.dimensions['nMesh2_time'].__len__()
    
    nz     = _nc.dimensions['nMesh2_layer_3d'].__len__()
    nFaces = _nc.dimensions['nMesh2_face'].__len__()
    nEdges = _nc.dimensions['nMesh2_edge'].__len__()
    _nc.close()

    if log:
        print 'nZ, nY, nX =', nz, ny, nx
        print 'nTimesteps =', nt
        print 'nFaces =', nFaces
        print 'nEdges =', nEdges


    # FACE middle values.....
    # ----------------------------------------------------------------------------
    var = process_cdl.cdlVariable()
    var.set_name('Mesh2_face_z_face_3d')
    var.set_dtype('float')
    var.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_face'))
    var.set_fillvalue(None)
    var.set_attr('long_name', 'z_face [ face ]')
    var.set_attr('units', 'm')
    var.set_attr('positive', 'down')
    var.set_attr('name_id', 1702)
    var.set_attr('bounds', 'Mesh2_face_z_face_bnd_3d')
    var.set_attr('standard_name', 'depth')
    var.set_attr('comment', "warning: dummy values are used")

    davit_dummy = np.zeros((nt, nz, nFaces))
    for z in xrange(nz):
        davit_dummy[:, z, :] = nz-z-0.5  # this equation will produce values like 0.5, 1.5, 2.5, ..., nz-1.0-0.5
    

    var_data = davit_dummy
    append_VariableData_to_netcdf(fname_davit, var, var_data, fv=var.get_fillvalue(), log=log)
    del var

    # FACE bounds values...
    # ----------------------------------------------------------------------------
    if log: print '{0}{1}\n{0}'.format('+'*50+'\n', 'Face Bounds')

    var = process_cdl.cdlVariable()
    var.set_name('Mesh2_face_z_face_bnd_3d')
    var.set_dtype('float')
    var.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_face', 'two'))
    var.set_fillvalue(None)
    var.set_attr('name_id', 1703)
    #var.set_attr('units', 'm')
    var.set_attr('comment', "warning: dummy values are used")

    davit_dummy = np.zeros((nt, nz, nFaces, 2))
    for z in xrange(nz):
        davit_dummy[:, z, :, 0] = nz-z-1.  # this equation will produce values like 0, 1, 2, ... nz-z
        davit_dummy[:, z, :, 1] = nz-z+0.  # this equation will produce values like 1, 2, 3, ... nz-z+1


    var_data = davit_dummy
    append_VariableData_to_netcdf(fname_davit, var, var_data, fv=var.get_fillvalue(), log=log)
    del var


    if log: print '{0}{1}\n{0}'.format('+'*50+'\n', 'EDGE')

    # EDGE middle values.....
    # ----------------------------------------------------------------------------
    var = process_cdl.cdlVariable()
    var.set_name('Mesh2_edge_z_edge_3d')
    var.set_dtype('float')
    var.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_edge'))
    var.set_fillvalue(None)
    var.set_attr('long_name', 'z_edge [ edge ]')
    var.set_attr('units', 'm')
    var.set_attr('positive', 'down')
    var.set_attr('name_id', 1707)
    var.set_attr('bounds', 'Mesh2_edge_z_edge_bnd_3d')
    var.set_attr('standard_name', 'depth')
    var.set_attr('comment', "warning: dummy values are used")

    davit_dummy = np.zeros((nt, nz, nEdges))
    for z in xrange(nz):
        davit_dummy[:, z, :] = nz-z-0.5  # this equation will produce values like 0.5, 1.5, 2.5, ..., nz-1.0-0.5
    

    var_data = davit_dummy
    append_VariableData_to_netcdf(fname_davit, var, var_data, fv=var.get_fillvalue(), log=log)
    del var

    # EDGE bounds values...
    # ----------------------------------------------------------------------------
    if log: print '{0}{1}\n{0}'.format('+'*50+'\n', 'EDGE Bounds')

    var = process_cdl.cdlVariable()
    var.set_name('Mesh2_edge_z_edge_bnd_3d')
    var.set_dtype('float')
    var.set_dims(('nMesh2_data_time', 'nMesh2_layer_3d', 'nMesh2_edge', 'two'))
    var.set_fillvalue(None)
    var.set_attr('name_id', 1708)
    #var.set_attr('units', 'm')
    var.set_attr('comment', "warning: dummy values are used")
    
    davit_dummy = np.zeros((nt, nz, nEdges, 2))

    for z in xrange(nz):
        davit_dummy[:, z, :, 0] = nz-z-1.  # this equation will produce values like 0, 1, 2, ... nz-z
        davit_dummy[:, z, :, 1] = nz-z+0.  # this equation will produce values like 1, 2, 3, ... nz-z+1


    var_data = davit_dummy
    append_VariableData_to_netcdf(fname_davit, var, var_data, fv=var.get_fillvalue(), log=log)
    del var
    if log: print 'finished: append_test_Mesh2_face_z_3d_and_Mesh2_face_z_3d_bnd()'