def calculate(mouth_dict, basin, load, traveltime, sumtime, avgtime, sumload):
    '''
    This function calculates the the sum and the average of the product of residence_time and load.
    This must be an index for the travel time of the load in a river basin.
    sumtime,avgtime and sumload are attributes which are in mouth_dict. They must be given as text.
    '''

    loadtime = ascraster.duplicategrid(traveltime)

    # Calculate the travel time for the N load
    loadtime.multiply(load, default_nodata_value=0.0)
    # Check whether sumtime is a valid attribute of the mouth_dict dictionairy.
    for key in list(mouth_dict.keys()):
        try:
            sumtime_riv = getattr(mouth_dict[key], sumtime)
        except AttributeError:
            # Make attribute in the mouth_dict dictionary
            setattr(mouth_dict[key], sumtime, 0.0)

    # Aggregate traveltime over the river basin.
    aggregate.aggregate_grid(basin, loadtime, mouth_dict, item=sumtime)

    # Calculate the average traveltime for each river basin
    for key in list(mouth_dict.keys()):
        try:
            sumtime_riv = getattr(mouth_dict[key], sumtime)
            sumload_riv = getattr(mouth_dict[key], sumload)
            setattr(mouth_dict[key], avgtime, sumtime_riv / sumload_riv)
        except ZeroDivisionError:
            setattr(mouth_dict[key], avgtime, 0.0)
예제 #2
0
def calculate(mouth_dict, basin, load, traveltime, sumtime, avgtime, sumload):
    """
    This function calculates the the sum and the average of the product of residence_time and load.
    This must be an index for the travel time of the load in a river basin.
    sumtime,avgtime and sumload are attributes which are in mouth_dict. They must be given as text.
    """

    loadtime = ascraster.duplicategrid(traveltime)

    # Calculate the travel time for the N load
    loadtime.multiply(load, default_nodata_value=0.0)
    # Check whether sumtime is a valid attribute of the mouth_dict dictionairy.
    for key in mouth_dict.keys():
        try:
            sumtime_riv = getattr(mouth_dict[key], sumtime)
        except AttributeError:
            # Make attribute in the mouth_dict dictionary
            setattr(mouth_dict[key], sumtime, 0.0)

    # Aggregate traveltime over the river basin.
    aggregate.aggregate_grid(basin, loadtime, mouth_dict, item=sumtime)

    # Calculate the average traveltime for each river basin
    for key in mouth_dict.keys():
        try:
            sumtime_riv = getattr(mouth_dict[key], sumtime)
            sumload_riv = getattr(mouth_dict[key], sumload)
            setattr(mouth_dict[key], avgtime, sumtime_riv / sumload_riv)
        except ZeroDivisionError:
            setattr(mouth_dict[key], avgtime, 0.0)
예제 #3
0
def calculate(params, mask, mouth_dict, lake_icell_dict, basin, discharge,
              lddmap, Pload):
    '''
    This function calculates the retention in the grid cells.
    '''

    # Read in the PCGLOBWB files
    water_storage_file = params.water_storage
    water_storage = ascraster.Asciigrid(ascii_file=water_storage_file,\
                                    mask=mask,numtype=float)

    flooding_depth_file = params.flooding_depth
    flooding_depth = ascraster.Asciigrid(ascii_file=flooding_depth_file,\
                                    mask=mask,numtype=float)

    flooding_fraction = ascraster.Asciigrid(ascii_file=params.flooding_fraction,\
                                    mask=mask,numtype=float)

    fraction_water_grid = ascraster.Asciigrid(ascii_file=params.fraction_water,\
                                  mask=mask,numtype=float)

    cellarea_grid = ascraster.Asciigrid(ascii_file=params.cellarea,\
                                    mask=mask,numtype=float)

    lakeid_grid = ascraster.Asciigrid(ascii_file=params.lakeid,\
                                    mask=mask,numtype=int)

    outlakeid_grid = ascraster.Asciigrid(ascii_file=params.outlakeid,\
                                    mask=mask,numtype=int)

    water_area_grid = ascraster.Asciigrid(ascii_file=params.water_area,\
                                    mask=mask,numtype=int)

    # Water volume flooding area
    volume_flooding_grid = ascraster.duplicategrid(flooding_depth)
    volume_flooding_grid.multiply(flooding_fraction, default_nodata_value=0.0)
    volume_flooding_grid.multiply(cellarea_grid, default_nodata_value=0.0)
    volume_flooding_grid.write_ascii_file(
        os.path.join(params.outputdir, "volume_flooding_grid.asc"))

    # Water volume of river.
    volume_river_grid = ascraster.duplicategrid(water_storage)
    volume_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "volume_river_grid.asc"))

    # Area water of river.
    area_river_grid = ascraster.duplicategrid(cellarea_grid)
    area_river_grid.multiply(fraction_water_grid, default_nodata_value=0.0)
    area_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "area_river_grid.asc"))

    # Correct river volume and area when there is a reservoir or a lake.
    for icell in range(lakeid_grid.length):
        id = lakeid_grid.get_data(icell, -1)
        if (id > 0):
            # It is a lake or reservoir
            # Check whether it is a outlet of a lake or reservoir
            id = outlakeid_grid.get_data(icell, -1)
            if (id > 0):
                # It is an outlet. So put lake properties into the gridcell
                volume_river_grid.set_data(icell,
                                           water_storage.get_data(icell, 0.0))
                area_river_grid.set_data(icell,
                                         water_area_grid.get_data(icell, 0.0))
            else:
                # It is not an outlet. So remove the calculated river properties.
                volume_river_grid.set_data(icell, 0.0)
                area_river_grid.set_data(icell, 0.0)

    volume_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "volume_river_grid_with_lakes.asc"))
    area_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "area_river_grid_with_lakes.asc"))

    # Depth water of river in metres
    depth_river_grid = ascraster.duplicategrid(volume_river_grid)
    depth_river_grid.divide(area_river_grid, default_nodata_value=0.0)
    depth_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "depth_river_grid.asc"))

    # Change water_storage from m3 into km3
    volume_river_grid.multiply(1.0e-9)
    volume_flooding_grid.multiply(1.0e-9)

    # Residence time is the volume divided by discharge.
    # Water storage is in km3. Discharge is km3/yr. So residence time is in years.
    residence_time_river_grid = ascraster.duplicategrid(volume_river_grid)
    residence_time_flooding_grid = ascraster.duplicategrid(
        volume_flooding_grid)

    # Calculate residence times by dividing water_storage through discharge.
    residence_time_river_grid.divide(discharge, default_nodata_value=0.0)
    residence_time_flooding_grid.divide(
        discharge,
        default_nodata_value=0.0,
        maximum=params.max_residence_time_per_cell)

    # If residence times are very high (e.g in dry areas),
    # set the residence time to a maximum
    # Apply maximum on gridcells which are not the outlet of a reservoir or lake.
    # In the flooding map there are no lakes/reservoirs
    for icell in range(residence_time_river_grid.length):
        resi = residence_time_river_grid.get_data(icell, -1)
        if (resi > params.max_residence_time_per_cell):
            # Check whether this is a outlet of a lake or reservoir
            try:
                outcell = lake_icell_dict[icell].outcell
                if (outcell == 1):
                    # Outlet of a lake/reservoir
                    if (resi > params.max_residence_time_per_lake):
                        resi = params.max_residence_time_per_lake
                else:
                    resi = params.max_residence_time_per_cell
                residence_time_river_grid.set_data(icell, resi)
            except KeyError:
                # This is no reservoir or lake
                residence_time_river_grid.set_data(
                    icell, params.max_residence_time_per_cell)
    residence_time_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "residence_time_river_grid.asc"))
    residence_time_flooding_grid.write_ascii_file(
        os.path.join(params.outputdir, "residence_time_flooding_grid.asc"))

    # Put residence time of the water body (lakes and reservoirs) in the grid.
    for icell in lake_icell_dict:
        if (lake_icell_dict[icell].outcell == 1):
            lake_icell_dict[
                icell].residence_time = residence_time_river_grid.get_data(
                    icell, 0.0)

    # Calculate the water volume in the grid cell
    volume_grid = ascraster.duplicategrid(volume_flooding_grid)
    volume_grid.add(volume_river_grid, default_nodata_value=0.0)
    volume_grid.write_ascii_file(
        os.path.join(params.outputdir, "volume_grid.asc"))

    # Calculate the average residence time with as weighing factors the volumes of the flooding - river
    residence_time_grid = ascraster.duplicategrid(volume_river_grid)
    residence_time_grid.multiply(residence_time_river_grid,
                                 default_nodata_value=0.0)
    temp_grid = ascraster.duplicategrid(volume_flooding_grid)
    temp_grid.multiply(residence_time_flooding_grid, default_nodata_value=0.0)
    residence_time_grid.add(temp_grid, default_nodata_value=0.0)
    residence_time_grid.divide(volume_grid, default_nodata_value=0.0)
    del temp_grid

    # Write residence_time to output file:
    residence_time_grid.write_ascii_file(
        os.path.join(params.outputdir, "residence_time.asc"))

    # Calculate the travel time of each grid cell to the river mouth
    traveltime = accuflux.accutime(lddmap, residence_time_grid,
                                   lake_icell_dict)
    traveltime.write_ascii_file(
        os.path.join(params.outputdir, "traveltime.asc"))

    # Aggregate traveltime over the river basin.
    aggregate.aggregate_grid(basin,
                             traveltime,
                             mouth_dict,
                             item="sum_traveltime")

    # Calculate the average traveltime for each river basin
    for key in list(mouth_dict.keys()):
        try:
            mouth_dict[key].avg_traveltime = mouth_dict[
                key].sum_traveltime / mouth_dict[key].number_of_cells
        except ZeroDivisionError:
            mouth_dict[key].avg_traveltime = 0.0
        except AttributeError:
            pass

    # Calculate the hydraulic load (Hl = depth/residence_time)
    hydraulic_load_flooding_grid = ascraster.duplicategrid(flooding_depth)
    hydraulic_load_flooding_grid.divide(residence_time_flooding_grid,
                                        default_nodata_value=0.0)
    hydraulic_load_river_grid = ascraster.duplicategrid(depth_river_grid)
    hydraulic_load_river_grid.divide(residence_time_river_grid,
                                     default_nodata_value=0.0)
    hydraulic_load_river_grid.write_ascii_file(
        os.path.join(params.outputdir, "hydraulic_load_river.asc"))
    hydraulic_load_flooding_grid.write_ascii_file(
        os.path.join(params.outputdir, "hydraulic_load_flooding.asc"))
    # Calculate the average hydraulic load with as weighing factors the volumes of the flooding - river
    hydraulic_load_grid = ascraster.duplicategrid(volume_river_grid)
    hydraulic_load_grid.multiply(hydraulic_load_river_grid,
                                 default_nodata_value=0.0)
    temp_grid = ascraster.duplicategrid(volume_flooding_grid)
    temp_grid.multiply(hydraulic_load_flooding_grid, default_nodata_value=0.0)
    hydraulic_load_grid.add(temp_grid, default_nodata_value=0.0)
    hydraulic_load_grid.divide(volume_grid, default_nodata_value=0.0)
    del temp_grid

    # Write hydraulic load to output file:
    hydraulic_load_grid.write_ascii_file(
        os.path.join(params.outputdir, "hydraulic_load.asc"))

    temperature_grid = ascraster.Asciigrid(ascii_file=params.water_temperature,\
                                      mask=mask,numtype=float)

    # Read endoreic lakes
    endo_lakes_grid = ascraster.Asciigrid(ascii_file=params.endo_lakes,\
                                      mask=mask,numtype=int)

    # Calculate the retention for rivers.
    retention_river_grid = ascraster.duplicategrid(volume_river_grid)
    for icell in range(retention_river_grid.length):
        id = endo_lakes_grid.get_data(icell, 0)
        if (id > 0):
            # This is an endoreic lake. So the calculation
            retention_river_grid.set_data(icell, 1.0)
            continue

        vol = volume_river_grid.get_data(icell, -1)
        if (vol > 0):
            temperature = temperature_grid.get_data(icell, 20.0)
            hydraulic_load = hydraulic_load_river_grid.get_data(icell, 0.0)
            ret = calculate_retention(params, hydraulic_load, vol, temperature)
            retention_river_grid.set_data(icell, ret)
        else:
            retention_river_grid.set_data(icell, 0.0)

    # Calculate the retention for flood planes.
    retention_flooding_grid = ascraster.duplicategrid(volume_flooding_grid)
    for icell in range(retention_flooding_grid.length):
        vol = volume_flooding_grid.get_data(icell, -1)
        if (vol > 0):
            temperature = temperature_grid.get_data(icell, 20.0)
            hydraulic_load = hydraulic_load_flooding_grid.get_data(icell, 0.0)
            ret = calculate_retention(params, hydraulic_load, vol, temperature)
            retention_flooding_grid.set_data(icell, ret)
        else:
            retention_flooding_grid.set_data(icell, 0.0)

    # Calculate the average retention with as weighing factors the volumes of the flooding - river
    retention_grid = ascraster.duplicategrid(volume_river_grid)
    retention_grid.multiply(retention_river_grid, default_nodata_value=0.0)
    temp_grid = ascraster.duplicategrid(volume_flooding_grid)
    temp_grid.multiply(retention_flooding_grid, default_nodata_value=0.0)
    retention_grid.add(temp_grid, default_nodata_value=0.0)
    retention_grid.divide(water_storage, default_nodata_value=0.0)
    del temp_grid

    # Set the lake database
    for icell in range(outlakeid_grid.length):
        if (id > 0):
            # It is an outlet. So put lake properties into the gridcell
            # Recalculate the temperature
            temp = 0.0
            number_of_cells = len(lake_icell_dict[icell].cells)
            for item in range(number_of_cells):
                icell_lake = lake_icell_dict[icell].cells[item]
                temp += temperature.get_data(icell_lake, 0.0)
            # Take average over the cells.
            temperature_cell = temp / float(number_of_cells)
            ret_cell = retention_river_grid.get_data(icell, 0.0)
            setattr(lake_icell_dict[icell], "retention", ret_cell)
            setattr(lake_icell_dict[icell], "fraction_water", -99)
            setattr(lake_icell_dict[icell], "temperature", temperature_cell)

    accuPload = P_accuflux(params, mask, lake_icell_dict, lddmap, Pload,
                           retention_grid)

    return residence_time_grid, traveltime, retention_grid, accuPload, hydraulic_load_grid
예제 #4
0
def calculate(params, mask, mouth_dict, basin):
    """
    Calculates the area of each grass and arable land use cell.
    It returns two ascraster object with the area grass and area arable land in ha
    """

    # Read grass files
    gras1 = ascraster.Asciigrid(ascii_file=params.pgrass, mask=mask, numtype=float)
    if params.ldebug:
        print params.pgrass + " has been read."

    gras2 = ascraster.Asciigrid(ascii_file=params.igrass, mask=mask, numtype=float)
    if params.ldebug:
        print params.igrass + " has been read."

    # Read crop files
    crop1 = ascraster.Asciigrid(ascii_file=params.cropmixp, mask=mask, numtype=float)
    if params.ldebug:
        print params.cropmixp + " has been read."

    crop2 = ascraster.Asciigrid(ascii_file=params.croppasp, mask=mask, numtype=float)
    if params.ldebug:
        print params.croppasp + " has been read."

    # Read land area
    landarea = ascraster.Asciigrid(ascii_file=params.landarea, mask=mask, numtype=float)
    if params.ldebug:
        print params.landarea + " has been read."

    # Aggregate landarea on river basin scale
    aggregate.aggregate_grid(basin, landarea, mouth_dict, item="landarea")

    # Make a copy (alias not a deepcopy) of the return values
    area_grass = gras1
    area_crop = crop1
    area_natural = landarea

    # Calculate the total grass and crop land in ha. Because the LU file are in percentage, and the
    # landarea is in km2, the product of (crop1_cell+crop2_cell) * landarea_cell is then in ha.
    for icell in range(crop1.length):
        crop1_cell = crop1.get_data(icell, 0.0)
        crop2_cell = crop2.get_data(icell, 0.0)
        gras1_cell = gras1.get_data(icell, 0.0)
        gras2_cell = gras2.get_data(icell, 0.0)
        landarea_cell = landarea.get_data(icell, 0.0)
        # Put result in crop1 and gras1
        crop_area = landarea_cell * (crop1_cell + crop2_cell)
        gras_area = landarea_cell * (gras1_cell + gras2_cell)
        if (crop_area + gras_area) - (100.0 * landarea_cell) > params.epsilon:
            print "Crop and grass area is too large: ", crop_area + gras_area, 100.0 * landarea_cell, (
                crop_area + gras_area
            ) - (100.0 * landarea_cell)
            try:
                fac = (100 * landarea_cell) / (crop_area + gras_area)
            except ZeroDivisionError:
                fac = 0.0
            crop_area *= fac
            gras_area *= fac

        nat_area = max(0.0, (100.0 * landarea_cell) - crop_area - gras_area)
        # Put result in the maps in km2 (factor 0.01)
        area_crop.set_data(icell, 0.01 * crop_area)
        area_grass.set_data(icell, 0.01 * gras_area)
        area_natural.set_data(icell, 0.01 * nat_area)

    # Aggregate landarea on river basin scale
    aggregate.aggregate_grid(basin, area_crop, mouth_dict, item="croparea")
    aggregate.aggregate_grid(basin, area_grass, mouth_dict, item="grasarea")
    aggregate.aggregate_grid(basin, area_natural, mouth_dict, item="natarea")

    # Calculate the number of cells in a region/basin
    one = ascraster.duplicategrid(landarea)
    # Set all cells to one.
    one.add_values(one.length * [1.0])
    aggregate.aggregate_grid(basin, one, mouth_dict, item="number_of_cells")

    # Delete the grid objects which are used anymore
    del crop1
    del crop2
    del gras1
    del gras2
    del landarea
    del one

    return area_grass, area_crop, area_natural
def calculate_subgrid_retention(params,mask,mouth_dict,basin,lake_icell_dict,load,\
                                water_body,pnet,vf):
    '''
    The subgrid retention is based on Wollheim (2006, GBC). This method is based on the stream order.
    In each cell, which is not a lake or reservoir, the subgrid retention is calculated.
    Only the local situation is used. For the load only the diffuse source from this cell are used. 
    The runoff is used (so only local water). Also the concentration effect or temperature effect on retention is not used here.
    '''
    # Make the subgrid stream order properties.
    # Setup the stream order river length,area and distribution and flowpath. Everything is stored in params.
    define_subgrid_streamorder(params)

    # Set the relation between concentration and net uptake velocity
    try:
        accuflux_retention.set_conc_relation_retention(params)
    except AttributeError:
        # This function is only for N and not for P
        pass

    # Make output rasters
    load_grid       = ascraster.duplicategrid(load)
    retention      = ascraster.duplicategrid(load)

    # Make nodata on all cells.
    retention.add_values(retention.length*[retention.nodata_value])
    retentionload  = ascraster.duplicategrid(retention)

    # Read water temperature
    temperature = ascraster.Asciigrid(ascii_file=params.water_temperature,mask=mask,numtype=float)

    # Loop over all cells:    
    for icell in range(load_grid.length):
        # Get mass flux at the cell.
        load_cell = load_grid.get_data(icell)
        if (load_cell == None):
            # No data value
            continue
        if load_cell < 0.0:
            print("Negative mass flow of " + str(load_cell) + " at cell: " + str(icell))           
            # Go to next cell.
            continue

        # Retention in cell
        water_body_cell = water_body.get_data(icell,0)
        if (water_body_cell > 0):
            runoff_cell = pnet.get_data(icell,0.0)
            # Check whether this cell is an outflow of a lake/reservoir
            try:            
                loutflow = lake_icell_dict[icell].outcell
            except KeyError:
                # No lake or reservoir
                loutflow = -1
            try:
                if (loutflow == -1):
                    # Normal cell, no lake or reservoir.
                    # Default temperature of 20C because then temperature has no effect.
                    temperature_cell = temperature.get_data(icell,20.0)
                    ret_cell = calculate_localretention(params,runoff_cell,vf,load_cell,temperature_cell)

                else:
                    #TODO: local retention when it is a lake or reservoir. For example as normal retention * fr_land.
                    # Lake or reservoir.
                    ret_cell = 0.0

            except OverflowError:
                raise OverflowError
        else:
            ret_cell = 0.0

        # Fill retention grid with retention value and retention load
        retention.set_data(icell,ret_cell)
        retentionload.set_data(icell,load_cell*ret_cell)

    # Write to output files
    retention.write_ascii_file(os.path.join(params.outputdir,"retention_subgrid.asc"))
    retentionload.write_ascii_file(os.path.join(params.outputdir,"removed_subgridload.asc"))

    # Write in mouth_dict database
    aggregate.aggregate_grid(basin,retentionload,mouth_dict,item="retentionload_subgrid")
    aggregate.aggregate_grid(basin,load_grid,mouth_dict,item="subgrid_load")
    # Put the retention_subgrid of the river in the mouth database
    for key in list(mouth_dict.keys()):
        try:
            mouth_dict[key].retention_subgrid = mouth_dict[key].retentionload_subgrid/mouth_dict[key].subgrid_load
        except ZeroDivisionError:
            mouth_dict[key].retention_subgrid = 0.0

    return retentionload,retention
예제 #6
0
def calculate(params,mask,mouth_dict,lake_icell_dict,basin,discharge,lddmap):
    '''
    This function calculates the residence time in the grid cells.
    '''

    # Read in the PCGLOBWB files
    water_storage_file = params.water_storage
    water_storage = ascraster.Asciigrid(ascii_file=water_storage_file,\
                                    mask=mask,numtype=float)
    # Change water_storage from m3 into km3
    water_storage.multiply(1.0e-9)         

    # Residence time is the volume divided by discharge. 
    # Water storage is in km3. Discharge is km3/yr. So residence time is in years.
    residence_time_grid = ascraster.duplicategrid(water_storage)
   
    # Calculate residence times by dividing water_storage through discharge.
    residence_time_grid.divide(discharge,default_nodata_value =  0.0)

    # If residence times are very high (e.g in dry areas),
    # set the residence time to a maximum
    # Apply maximum on gridcells which are not the outlet of a reservoir or lake.
    for icell in xrange(residence_time_grid.length):
        resi = residence_time_grid.get_data(icell,-1)
        if (resi > params.max_residence_time_per_cell):
            # Check whether this is a outlet of a lake or reservoir
            try:
                outcell = lake_icell_dict[icell].outcell
                if (outcell == 1):
                    # Outlet of a lake/reservoir
                    if (resi > params.max_residence_time_per_lake):
                        resi = params.max_residence_time_per_lake
                        # Change also the dictionary value of this waterbody
                        lake_icell_dict[icell].residence_time = resi
                else:
                    resi = params.max_residence_time_per_cell
                residence_time_grid.set_data(icell,resi)
            except KeyError:
                # This is no reservoir or lake
                residence_time_grid.set_data(icell,params.max_residence_time_per_cell)

    # Put residence time of the water body (lakes and reservoirs) in the grid.
    for icell in lake_icell_dict:
        if (lake_icell_dict[icell].outcell == 1):
            residence_time_grid.set_data(icell,lake_icell_dict[icell].residence_time)
            
    # Write residence_time to output file:
    residence_time_grid.write_ascii_file(os.path.join(params.outputdir,"residence_time.asc")) 
 
    # Calculate the travel time of each grid cell to the river mouth
    traveltime = accuflux.accutime(lddmap,residence_time_grid,lake_icell_dict)
    traveltime.write_ascii_file(os.path.join(params.outputdir,"traveltime.asc")) 

    # Aggregate traveltime over the river basin.
    aggregate.aggregate_grid(basin,traveltime,mouth_dict,item="sum_traveltime")

    # Calculate the average traveltime for each river basin
    for key in mouth_dict.keys():
        try:
            mouth_dict[key].avg_traveltime = mouth_dict[key].sum_traveltime/mouth_dict[key].number_of_cells 
        except ZeroDivisionError:
            mouth_dict[key].avg_traveltime = 0.0
        except AttributeError:
            pass

    return residence_time_grid,traveltime
예제 #7
0
def calculate(params, mask, mouth_dict, basin):
    '''
    Calculates the area of each grass and arable land use cell.
    It returns two ascraster object with the area grass and area arable land in ha
    '''

    # Read grass files
    gras1 = ascraster.Asciigrid(ascii_file=params.pgrass,
                                mask=mask,
                                numtype=float)
    if params.ldebug: print(params.pgrass + " has been read.")

    gras2 = ascraster.Asciigrid(ascii_file=params.igrass,
                                mask=mask,
                                numtype=float)
    if params.ldebug: print(params.igrass + " has been read.")

    # Read crop files
    crop1 = ascraster.Asciigrid(ascii_file=params.cropmixp,
                                mask=mask,
                                numtype=float)
    if params.ldebug: print(params.cropmixp + " has been read.")

    crop2 = ascraster.Asciigrid(ascii_file=params.croppasp,
                                mask=mask,
                                numtype=float)
    if params.ldebug: print(params.croppasp + " has been read.")

    # Read land area
    landarea = ascraster.Asciigrid(ascii_file=params.landarea,
                                   mask=mask,
                                   numtype=float)
    if params.ldebug: print(params.landarea + " has been read.")

    # Aggregate landarea on river basin scale
    aggregate.aggregate_grid(basin, landarea, mouth_dict, item="landarea")

    # Make a copy (alias not a deepcopy) of the return values
    area_grass = gras1
    area_crop = crop1
    area_natural = landarea

    # Calculate the total grass and crop land in ha. Because the LU file are in percentage, and the
    # landarea is in km2, the product of (crop1_cell+crop2_cell) * landarea_cell is then in ha.
    for icell in range(crop1.length):
        crop1_cell = crop1.get_data(icell, 0.0)
        crop2_cell = crop2.get_data(icell, 0.0)
        gras1_cell = gras1.get_data(icell, 0.0)
        gras2_cell = gras2.get_data(icell, 0.0)
        landarea_cell = landarea.get_data(icell, 0.0)
        # Put result in crop1 and gras1
        crop_area = landarea_cell * (crop1_cell + crop2_cell)
        gras_area = landarea_cell * (gras1_cell + gras2_cell)
        if ((crop_area + gras_area) - (100.0 * landarea_cell) > 1.):
            print("Crop and grass area is too large: ", crop_area + gras_area,
                  100. * landarea_cell,
                  (crop_area + gras_area) - (100.0 * landarea_cell))
            try:
                fac = (100 * landarea_cell) / (crop_area + gras_area)
            except ZeroDivisionError:
                fac = 0.0
            crop_area *= fac
            gras_area *= fac

        nat_area = max(0.0, (100.0 * landarea_cell) - crop_area - gras_area)
        # Put result in the maps in km2 (factor 0.01)
        area_crop.set_data(icell, 0.01 * crop_area)
        area_grass.set_data(icell, 0.01 * gras_area)
        area_natural.set_data(icell, 0.01 * nat_area)

    # Aggregate landarea on river basin scale
    aggregate.aggregate_grid(basin, area_crop, mouth_dict, item="croparea")
    aggregate.aggregate_grid(basin, area_grass, mouth_dict, item="grasarea")
    aggregate.aggregate_grid(basin, area_natural, mouth_dict, item="natarea")

    # Calculate the number of cells in a region/basin
    one = ascraster.duplicategrid(landarea)
    # Set all cells to one.
    one.add_values(one.length * [1.0])
    aggregate.aggregate_grid(basin, one, mouth_dict, item="number_of_cells")

    # Delete the grid objects which are used anymore
    del crop1
    del crop2
    del gras1
    del gras2
    del landarea
    del one

    return area_grass, area_crop, area_natural
def calculate(params,mask,mouth_dict,lake_icell_dict,basin,discharge,lddmap):
    '''
    This function calculates the residence time in the grid cells.
    '''

    # Read water storage of rivers and lakes/reservoirs.
    water_storage = ascraster.Asciigrid(ascii_file=params.water_storage,\
                                    mask=mask,numtype=float)

    # Read rivers and lakes/reservoirs areas as fraction of the cellarea.
    fraction_waterbody_grid = ascraster.Asciigrid(ascii_file=params.fraction_water,\
                                    mask=mask,numtype=float)          

    # Read water depth of flooding areas.
    flooding_depth = ascraster.Asciigrid(ascii_file=params.flooding_depth,\
                                    mask=mask,numtype=float)  

    # Read flooding areas as fraction of the cellarea.
    flooding_fraction = ascraster.Asciigrid(ascii_file=params.flooding_fraction,\
                                    mask=mask,numtype=float)

    # Read the cellarea
    cellarea_grid = ascraster.Asciigrid(ascii_file=params.cellarea,\
                                    mask=mask,numtype=float)

    # Read lake/reservoir id
    lakeid_grid = ascraster.Asciigrid(ascii_file=params.lakeid,\
                                    mask=mask,numtype=int)

    # Read outlet cell of lake/reservoir id. Only outlet cell is filled.
    outlakeid_grid = ascraster.Asciigrid(ascii_file=params.outlakeid,\
                                    mask=mask,numtype=int)

    # Read area of lakes/reservoirs.
    waterbody_area_grid = ascraster.Asciigrid(ascii_file=params.water_area,\
                                    mask=mask,numtype=int)

    # Water volume flooding area in m3
    volume_flooding_grid = ascraster.duplicategrid(flooding_depth)
    volume_flooding_grid.multiply(flooding_fraction,default_nodata_value =  -1.0)
    volume_flooding_grid.multiply(cellarea_grid,default_nodata_value =  -1.0)


    # Water volume of waterbody (river,lakes or reservoir) in m3 as left over of water_storage minus flooding volume.
    volume_waterbody_grid = ascraster.duplicategrid(water_storage)
    volume_waterbody_grid.substract(volume_flooding_grid,default_nodata_value =  -1.0)

    # Area water of river in m2.
    area_waterbody_grid = ascraster.duplicategrid(cellarea_grid)
    area_waterbody_grid.multiply(fraction_waterbody_grid,default_nodata_value =  -1.0)

    # Correct river volume and area when there is a reservoir or a lake.
    for icell in range(lakeid_grid.length):
        id = lakeid_grid.get_data(icell,-1)
        if (id > 0):
           # It is a lake or reservoir
           # Check whether it is a outlet of a lake or reservoir
           id_lake = outlakeid_grid.get_data(icell,-1)
           if (id_lake > 0):
               # It is an outlet. So put lake properties into the gridcell
               volume_waterbody_grid.set_data(icell,water_storage.get_data(icell,0.0))
               area_waterbody_grid.set_data(icell,waterbody_area_grid.get_data(icell,0.0))
           else:
               # It is not an outlet. So remove the calculated river properties.
               volume_waterbody_grid.set_data(icell,0.0)
               area_waterbody_grid.set_data(icell,0.0)
    
    #volume_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"volume_waterbody_grid_negative.asc"))

    # Correct all the volumes which are negative.
    for icell in range(volume_waterbody_grid.length):     
        if (volume_waterbody_grid.get_data(icell,1.0) < 0.0):
            #print "Negative waterbody volume: ", volume_waterbody_grid.get_data(icell),\
            #      flooding_depth.get_data(icell),flooding_fraction.get_data(icell),\
            #      cellarea_grid.get_data(icell),water_storage.get_data(icell),fraction_waterbody_grid.get_data(icell)
            # When this happenes, we assume that the flooding is not correct. So the waterbody volume is equal to the water storage.
            # Water volume flooding is zero.
            volume_waterbody_grid.set_data(icell,water_storage.get_data(icell,0.0))
            volume_flooding_grid.set_data(icell,0.0)

    # Write volume in m3 and area in m2 to outputfile
    volume_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"volume_waterbody_grid.asc"))
    volume_flooding_grid.write_ascii_file(os.path.join(params.outputdir,"volume_flooding_grid.asc"))
    area_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"area_waterbody_grid.asc"))

    # Depth water of river in metres
    depth_waterbody_grid = ascraster.duplicategrid(volume_waterbody_grid)
    depth_waterbody_grid.divide(area_waterbody_grid,default_nodata_value =  -1.0)
    depth_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"depth_waterbody_grid.asc"))

    # Calculate the water volume in m3 in the grid cell
    volume_grid = ascraster.duplicategrid(volume_flooding_grid)
    volume_grid.add(volume_waterbody_grid,default_nodata_value = -1.0)
    volume_grid.write_ascii_file(os.path.join(params.outputdir,"volume_grid.asc"))

    # Change water_storage from m3 into km3
    volume_waterbody_grid.multiply(1.0e-9)
    volume_flooding_grid.multiply(1.0e-9)
    volume_grid.multiply(1.0e-9)

    # Residence time is the volume divided by discharge. 
    # Calculate the residence time as volume water body divided by corrected discharge
    # Corrected discharge is the discharge minus the water volume of the flooded area.
    
    # If residence times are very high (e.g in dry areas),
    # set the residence time to a maximum
    # Apply maximum on gridcells which are not the outlet of a reservoir or lake.
    residence_time_grid = ascraster.duplicategrid(volume_flooding_grid)
    for icell in range(residence_time_grid.length):
        # Check whether it is a lake/reservoir
        id = lakeid_grid.get_data(icell,-1)
        if (id > 0):
            # It is a lake or reservoir
            # Check whether it is a outlet of a lake or reservoir
            id_lake = outlakeid_grid.get_data(icell,-1)
            if (id_lake > 0):
                try:
                    resi = lake_icell_dict[icell].residence_time
                    # It is an outlet. So put lake properties into the gridcell         
                    if (lake_icell_dict[icell].residence_time > params.max_residence_time_per_lake):
                        # Change also the dictionary value of this waterbody
                        lake_icell_dict[icell].residence_time = params.max_residence_time_per_lake
                        resi = params.max_residence_time_per_lake
                except KeyError:
                     print(id , " has no residence time")
                     resi = 0.0           
            else:
                # Lake or reservoir but no outflow cell
                resi = 0.0
            residence_time_grid.set_data(icell,resi)
        else:
            # This is no reservoir or lake
            dis = discharge.get_data(icell,0.0)
            volume_flooded = volume_flooding_grid.get_data(icell,0.0)
            volume_waterbody = volume_waterbody_grid.get_data(icell,0.0)
            discharge_corrected = dis - volume_flooded
            if (dis <= 0.0):
                resi = 0.0
            elif (discharge_corrected >  volume_waterbody or volume_flooded <= 0.0):
                # Here we assume that there is enough water to feed the channel.
                resi = volume_waterbody/discharge_corrected
            else:
                # There is not enough water to feed the channel.
                # Now we take an volume weighed average of both residence times.
                volume_total = volume_waterbody + volume_flooded
                if (volume_total > 0.0):
                    try:
                        frac_flooded = volume_flooded/volume_total
                        resi_flooded = frac_flooded * volume_flooded/dis
                    except ZeroDivisionError:
                        frac_flooded = 0.0
                        resi_flooded = 0.0
                    try:
                        frac_waterbody = volume_waterbody/volume_total
                        resi_waterbody = frac_waterbody * volume_waterbody/dis
                    except ZeroDivisionError:
                        frac_waterbody = 0.0
                        resi_waterbody = 0.0

                    resi = resi_flooded + resi_waterbody
                else:
                    resi = 0.0
            resi = min(resi,params.max_residence_time_per_cell)
            residence_time_grid.set_data(icell,resi)
        
          
    # Write residence_time to output file:
    residence_time_grid.write_ascii_file(os.path.join(params.outputdir,"residence_time.asc"))     
 
    # Calculate the travel time of each grid cell to the river mouth
    traveltime = accuflux.accutime(lddmap,residence_time_grid,lake_icell_dict)
    traveltime.write_ascii_file(os.path.join(params.outputdir,"traveltime.asc")) 

    # Aggregate traveltime over the river basin.
    aggregate.aggregate_grid(basin,traveltime,mouth_dict,item="sum_traveltime")

    # Calculate the average traveltime for each river basin
    for key in list(mouth_dict.keys()):
        try:
            mouth_dict[key].avg_traveltime = mouth_dict[key].sum_traveltime/mouth_dict[key].number_of_cells 
        except ZeroDivisionError:
            mouth_dict[key].avg_traveltime = 0.0
        except AttributeError:
            pass

    return residence_time_grid,traveltime