Ejemplo n.º 1
0
def module4(path_emission_cdf, path_area_cdf, path_reduction_txt,
            path_base_conc_cdf, path_model_cdf, path_result_cdf,
            downscale_request, *progresslog):

    # get precursor list from model
    rootgrp = Dataset(path_model_cdf, 'r')
    precursor_lst = getattr(rootgrp, 'Order_Pollutant').split(', ')
    rootgrp.close()

    # module 4 can be ran independently without progress log argument or...
    if progresslog:
        progresslog_filename = progresslog[0]
        progress_dict = read_progress_log(progresslog_filename)
    # called by another model which passes a progress log argument
    else:
        progresslog_filename = path_result_cdf + 'progresslog'
        write_progress_log(progresslog_filename, 0, 1)
        progress_dict = read_progress_log(progresslog_filename)

    # calculate the delta emissions, dictionary per pollutant a matrix of dimension n_lat x n_lon
    mod1_res = module1(path_emission_cdf, path_area_cdf, path_reduction_txt,
                       path_base_conc_cdf, path_model_cdf, path_result_cdf,
                       downscale_request, progresslog_filename)
    delta_conc = mod1_res['delta_conc']
    delta_emis_dict = mod1_res['delta_emis_dict']
    n_lat = mod1_res['n_lat']
    n_lon = mod1_res['n_lon']

    # remove progress log if he was made inside module 4, not if it was an external argument
    if not progresslog:
        remove(progresslog_filename)

    # only if only one precursor is reduced delta_emission is used for potency calculations
    # check this
    emission_reduction_dict = create_emission_reduction_dict(
        path_reduction_txt)
    number_reduced_precursors = 0
    for precursor in precursor_lst:
        sum_reductions = 0
        for snap in emission_reduction_dict[precursor].keys():
            sum_reductions += emission_reduction_dict[precursor][snap]
        if sum_reductions > 0:
            number_reduced_precursors += 1
            reduced_precursor = precursor
            delta_emis = delta_emis_dict[precursor]
            # print('precusor %s was reduced' % precursor)
    if number_reduced_precursors != 1:
        reduced_precursor = ''
    # print(sum(delta_emis))

    # read baseline concentrations
    rootgrp = Dataset(path_base_conc_cdf, 'r')
    conc = rootgrp.variables['conc'][:]

    #ENR 20180126 - fix for NO2. in case of NO2, load NO2 and not NOx variable as baseline
    if (path_model_cdf.find('NO2eq') > -1):
        conc = rootgrp.variables['NO2'][:]

    # close model netcdf
    rootgrp.close()

    # calculate different potencies
    #------------------------------
    #     print('check delta conc')
    #     print(sum(delta_conc))
    # Delta_C/alfa
    DC_alpha = delta_conc / (alpha_potency / 100.0)

    DC_C_alpha = delta_conc / conc / (alpha_potency / 100.0)

    if number_reduced_precursors == 1:
        ## select reduced precursor automatically !!!!!!!!!!!
        DC_DE = zeros((n_lat, n_lon))
        DC_DE = delta_conc / delta_emis_dict[reduced_precursor].sum() * 1000
#         for i in range(n_lat):
#             for j in range(n_lon):
#                 if delta_emis_dict[reduced_precursor][i, j] > 0:
# DC_DE[i, j] = delta_conc[i, j] / delta_emis_dict[reduced_precursor][i, j]
#                     DC_DE[i, j] = delta_conc[i, j] / DE

# create a result netcdf
# -----------------------
    if progress_dict['start'] != -1:
        filename_result_cdf = path_result_cdf + 'potencies.nc'
        rootgrp = Dataset(filename_result_cdf, 'w', format='NETCDF3_CLASSIC')

        # create dimensions in the netcdf file
        rootgrp.createDimension('latitude', n_lat)
        rootgrp.createDimension('longitude', n_lon)
        latitudes = rootgrp.createVariable('latitude', 'f4', ('latitude', ))
        latitudes.units = "degrees_north"
        longitudes = rootgrp.createVariable('longitude', 'f4', ('longitude', ))
        longitudes.units = "degrees_east"
        latitudes[:] = mod1_res['latitude_array']
        longitudes[:] = mod1_res['longitude_array']

        # create potency variables data
        DC_alpha_var = rootgrp.createVariable('DC_alpha', 'f4', (
            'latitude',
            'longitude',
        ))
        DC_alpha_var[:] = DC_alpha
        DC_C_alpha_var = rootgrp.createVariable('DC_C_alpha', 'f4', (
            'latitude',
            'longitude',
        ))
        DC_C_alpha_var[:] = DC_C_alpha
        if number_reduced_precursors == 1:
            DC_DE_var = rootgrp.createVariable('DC_DE', 'f4', (
                'latitude',
                'longitude',
            ))
            DC_DE_var[:] = DC_DE

        delta_conc_var = rootgrp.createVariable('delta_conc_var', 'f4', (
            'latitude',
            'longitude',
        ))
        delta_conc_var[:] = delta_conc
        delta_emis_var = rootgrp.createVariable('delta_emis_var', 'f4', (
            'latitude',
            'longitude',
        ))
        delta_emis_var[:] = delta_emis

        rootgrp.close()

    # create a results object
    mod4_res = {}
    mod4_res['n_lat'] = n_lat
    mod4_res['n_lon'] = n_lon
    mod4_res['latitude_array'] = mod1_res['latitude_array']
    mod4_res['longitude_array'] = mod1_res['longitude_array']
    # add DC_alpha to the result dictionary
    mod4_res['DC_alpha'] = DC_alpha
    # add DC_C_alpha to the result dictionary
    mod4_res['DC_C_alpha'] = DC_C_alpha
    if number_reduced_precursors == 1:
        # add DC_DE to the result dictionary
        mod4_res['DC_DE'] = DC_DE

    return mod4_res
Ejemplo n.º 2
0
def module1(path_emission_cdf, path_area_cdf, path_reduction_txt,
            path_base_conc_cdf, path_model_cdf, path_result_cdf,
            downscale_request, *progresslog):

    pollName = path_model_cdf.split('SR_')[1].split('.nc')[0]

    # check if a progess log file was passed as argument
    if progresslog:
        progress_dict = read_progress_log(progresslog[0])
        write_netcdf_output = False
    else:
        progress_dict = {'start': 0.0, 'divisor': 1.0}
        write_netcdf_output = True

    #M read the model netcdf
    # ---------------------
    rootgrp = Dataset(path_model_cdf, 'r')
    longitude_array = rootgrp.variables['lon'][0, :]
    latitude_array = rootgrp.variables['lat'][:, 0]
    n_lon = len(longitude_array)  # len(rootgrp.dimensions['longitude'])
    n_lat = len(latitude_array)  # len(rootgrp.dimensions['latitude'])

    #####
    #20180129 - EP - generalization to read 'radius of influence' variable, both written in matlab or python
    for nameatt in Dataset(path_model_cdf, 'r').ncattrs():
        if nameatt[0:6] == 'Radius':
            radiusofinfluence = nameatt
    inner_radius = int(getattr(Dataset(path_model_cdf, 'r'),
                               radiusofinfluence))
    #inner_radius = int(getattr(rootgrp, 'Radius of influence'))
    #####

    precursor_lst = getattr(rootgrp, 'Order_Pollutant').split(', ')
    alpha = rootgrp.variables['alpha'][:, :, :]
    omega = rootgrp.variables['omega'][:, :, :]

    # put alpha and omega in a dictionary
    alpha_dict = {}
    omega_dict = {}
    for i in range(len(precursor_lst)):
        alpha_dict[precursor_lst[i]] = alpha[i, :, :]
        omega_dict[precursor_lst[i]] = omega[i, :, :]

    # close model netcdf
    rootgrp.close()

    # calculate the delta emissions, dictionary per pollutant a matrix of dimension n_lat x n_lon
    delta_emission_dict = create_delta_emission(
        path_emission_cdf, precursor_lst, path_area_cdf, path_reduction_txt,
        path_result_cdf, write_netcdf_output, pollName, downscale_request)

    # make a window
    window = create_window(inner_radius)
    (n_lon_inner_win, n_lat_inner_win) = window.shape

    pad_delta_emission_dict = {}
    for precursor in precursor_lst:
        pad_delta_emission_dict[precursor] = lib.pad(
            delta_emission_dict[precursor],
            inner_radius,
            'constant',
            constant_values=0)

    # apply source receptor relationships
    # -----------------------------------
    last_progress_print = time()
    delta_conc = zeros((n_lat, n_lon)) * float('nan')
    cell_counter = 0
    n_cell = n_lat * n_lon

    # initialize a OmegaPowerWindows class
    win_pow_omega = OmegaPowerWindows(2 * inner_radius + 1)

    # loop over all cells of the domain
    for ie in range(n_lat):
        if (time() - last_progress_print) > 1:
            if progress_dict['start'] >= 0:
                progress = progress_dict['start'] + float(
                    cell_counter) / float(
                        n_cell) * 100 / progress_dict['divisor']
                sys.stdout.write('\r')
                sys.stdout.flush()
                sys.stdout.write('progress:%f\r' % progress)
                sys.stdout.flush()
                last_progress_print = time()

        for je in range(n_lon):
            for precursor in precursor_lst:
                # apply averaging window
                alpha_ij = alpha_dict[precursor][ie, je]
                omega_ij = omega_dict[precursor][ie, je]

                if not (isnan(alpha_ij)):
                    # if the model is available remove NaN value
                    if isnan(delta_conc[ie, je]):
                        delta_conc[ie, je] = 0
                    # select the window of emissions around the target cell
                    emissions_centre = pad_delta_emission_dict[precursor][ie:(
                        ie + n_lon_inner_win), je:(je + n_lat_inner_win)]
                    # apply the weights to the emissions and sum them over the whole window
                    weighted_emissions_centre = (
                        win_pow_omega.getOmegaPowerWindow(omega_ij) *
                        emissions_centre).sum()
                    # sum the contribution of the precursor
                    delta_conc[ie, je] = delta_conc[
                        ie, je] + alpha_ij * weighted_emissions_centre

            # update the cellcounter for the progress bar
            cell_counter += 1

    # In the case of NO2 the variable 'delta_conc' contains the NOx concentrations as NO2-equivalent.
    # NO2 concentration and concentration difference are calculated applying an empiric formula
    # check if the pollutant is NO2, if so NO2 has to be calculated from NOx results w/ function 'deltaNOx_to_deltaNO2'
    if (path_model_cdf.find('NO2eq') > -1):
        rootgrp = Dataset(path_base_conc_cdf, 'r')
        base_conc_nox = rootgrp.variables['conc'][:]
        base_conc_no2 = rootgrp.variables['NO2'][:]
        rootgrp.close()
        delta_conc = deltaNOx_to_deltaNO2(delta_conc, base_conc_nox,
                                          base_conc_no2)

    #20210202EP, read units to save correct units as output, for delta_conc
    rootgrp = Dataset(path_base_conc_cdf, 'r')
    units_for_output = rootgrp.variables['conc'].units

    # create a result netcdf
    # -----------------------
    if write_netcdf_output == True:
        filename_result_cdf = path_result_cdf + 'DCconc_emepV434_camsV42_' + pollName + '.nc'

        #20220530 change name of emission file in case of downscaling
        if downscale_request == 1:
            filename_result_cdf = path_result_cdf + 'DCconc_emepV434_camsV42_' + pollName[
                0:8] + 'P' + pollName[8:] + '_.nc'

        rootgrp = Dataset(filename_result_cdf, 'w', format='NETCDF3_CLASSIC')

        # create dimensions in the netcdf file
        rootgrp.createDimension('latitude', n_lat)
        rootgrp.createDimension('longitude', n_lon)
        latitudes = rootgrp.createVariable('latitude', 'f4', ('latitude', ))
        latitudes.units = "degrees_north"
        longitudes = rootgrp.createVariable('longitude', 'f4', ('longitude', ))
        longitudes.units = "degrees_east"
        latitudes[:] = latitude_array
        longitudes[:] = longitude_array

        # create delta concentration data
        delta_conc_pol = rootgrp.createVariable('delta_conc', 'f4', (
            'latitude',
            'longitude',
        ))
        delta_conc_pol.units = units_for_output  #u'\u03BC'+'g/m'+ u'\u00B3' # 'ug/m3' '\u03bcg/m\u00B3'
        delta_conc_pol[:] = delta_conc

        rootgrp.close()

    # create a results object
    mod1_res = {}
    mod1_res['delta_conc'] = delta_conc
    mod1_res['delta_emis_dict'] = delta_emission_dict
    mod1_res['n_lat'] = n_lat
    mod1_res['n_lon'] = n_lon
    mod1_res['latitude_array'] = latitude_array
    mod1_res['longitude_array'] = longitude_array

    return mod1_res
Ejemplo n.º 3
0
def module1(path_emission_cdf, path_area_cdf, path_reduction_txt,
            path_base_conc_cdf, path_model_cdf, path_result_cdf, *progresslog):

    # check if a progess log file was passed as argument
    if progresslog:
        progress_dict = read_progress_log(progresslog[0])
        write_netcdf_output = False
    else:
        progress_dict = {'start': 0.0, 'divisor': 1.0}
        write_netcdf_output = True

    # read the model netcdf
    # ---------------------
    rootgrp = Dataset(path_model_cdf, 'r')
    longitude_array = rootgrp.variables['lon'][0, :]
    latitude_array = rootgrp.variables['lat'][:, 0]
    n_lon = len(longitude_array)  # len(rootgrp.dimensions['longitude'])
    n_lat = len(latitude_array)  # len(rootgrp.dimensions['latitude'])
    inner_radius = int(getattr(rootgrp, 'Radius of influence'))
    precursor_lst = getattr(rootgrp, 'Order_Pollutant').split(', ')
    alpha = rootgrp.variables['alpha'][:, :, :]
    omega = rootgrp.variables['omega'][:, :, :]
    flatWeight = rootgrp.variables['flatWeight'][:, :, :]

    # put alpha and omega in a dictionary
    alpha_dict = {}
    omega_dict = {}
    flatWeight_dict = {}
    for i in range(len(precursor_lst)):
        alpha_dict[precursor_lst[i]] = alpha[i, :, :]
        omega_dict[precursor_lst[i]] = omega[i, :, :]
        flatWeight_dict[precursor_lst[i]] = flatWeight[i, :, :]

    # close model netcdf
    rootgrp.close()

    # calculate the delta emissions, dictionary per pollutant a matrix of dimension n_lat x n_lon
    delta_emission_dict = create_delta_emission(path_emission_cdf,
                                                precursor_lst, path_area_cdf,
                                                path_reduction_txt,
                                                path_result_cdf,
                                                write_netcdf_output)

    # make a window
    window = create_window(inner_radius)
    (n_lon_inner_win, n_lat_inner_win) = window.shape

    # create flat window and a inner window
    borderweight = window[inner_radius, 0]

    window_ones = ones(window.shape)
    for i in range(n_lat_inner_win):
        for j in range(n_lon_inner_win):
            if window[i, j] < borderweight:
                window[i, j] = 0
                window_ones[i, j] = 0

    pad_delta_emission_dict = {}
    for precursor in precursor_lst:
        pad_delta_emission_dict[precursor] = lib.pad(
            delta_emission_dict[precursor],
            inner_radius,
            'constant',
            constant_values=0)

    # apply source receptor relationships
    # -----------------------------------
    last_progress_print = time()
    #     calculate weighted emissions for all precursors
    #     norm_delta_conc = zeros((n_lat, n_lon))
    delta_conc = zeros((n_lat, n_lon)) * float('nan')
    cell_counter = 0
    n_cell = n_lat * n_lon

    # dictionary with sum of emissions over full domain per precursor
    sum_emissions_flat = {}
    for precursor in precursor_lst:
        sum_emissions_flat[precursor] = delta_emission_dict[precursor].sum()

    for ie in range(n_lat):
        if (time() - last_progress_print) > 1:
            if progress_dict['start'] >= 0:
                progress = progress_dict['start'] + float(
                    cell_counter) / float(
                        n_cell) * 100 / progress_dict['divisor']
                sys.stdout.write('\r')
                sys.stdout.flush()
                sys.stdout.write('progress:%f\r' % progress)
                sys.stdout.flush()
                last_progress_print = time()

        for je in range(n_lon):
            for precursor in precursor_lst:
                # apply averaging window
                alpha_ij = alpha_dict[precursor][ie, je]
                omega_ij = omega_dict[precursor][ie, je]
                flatWeight_ij = flatWeight_dict[precursor][ie, je]

                if not (isnan(alpha_ij)):
                    # if the model is available remove NaN value
                    if isnan(delta_conc[ie, je]):
                        delta_conc[ie, je] = 0
                    # update or recalculate flat weighted emissions for each precursor


#                     if sum_emissions_flat[precursor] == None:
#                         sum_emissions_flat[precursor] = pad_delta_emission_dict[precursor][ie:(ie + n_lon_outer_win), je:(je + n_lat_outer_win)].sum()
#                     else:
# update flat weight emissions
#                         sum_emissions_flat[precursor] -= pad_delta_emission_dict[precursor][ie:(ie + n_lon_outer_win), (je - 1)].sum()
#                         sum_emissions_flat[precursor] += pad_delta_emission_dict[precursor][ie:(ie + n_lon_outer_win), (je + n_lat_outer_win - 1)].sum()

# apply the weight to the flat weighted emissions
                    weighted_emissions_flat = flatWeight_ij * sum_emissions_flat[
                        precursor]

                    # calculate the inner variable weighted emissions
                    #                     ring = outer_radius - inner_radius
                    #                     emissions_centre = pad_delta_emission_dict[precursor][(ie + ring):(ie + n_lon_outer_win - ring), (je + ring):(je + n_lat_outer_win - ring)]
                    emissions_centre = pad_delta_emission_dict[precursor][ie:(
                        ie + n_lon_inner_win), je:(je + n_lat_inner_win)]

                    # weighted_emissions_centre = (power(weights_centre, omega_ij) * emissions_centre).sum()
                    weighted_emissions_centre = (
                        (power(window, omega_ij) - window_ones * flatWeight_ij)
                        * emissions_centre).sum()
                    # to avoid that the little triangles in the 4 corners of the centre area are not counted
                    # weighted_emissions_centre[weighted_emissions_centre < 0] = 0
                    # sum the contribution of the precursor
                    delta_conc[ie, je] = delta_conc[ie, je] + alpha_ij * (
                        weighted_emissions_centre + weighted_emissions_flat)

            cell_counter += 1

    # In the case of NO2 the variable 'delta_conc' contains the NOx concentrations as NO2-equivalent.
    # NO2 concentration and concentration difference are calculated applying an empiric formula
    # check if the pollutant is NO2, if so NO2 has to be calculated from NOx results w/ function 'deltaNOx_to_deltaNO2'
    if (path_model_cdf.find('NO2eq') > -1):
        rootgrp = Dataset(path_base_conc_cdf, 'r')
        base_conc_nox = rootgrp.variables['conc'][:]
        base_conc_no2 = rootgrp.variables['NO2'][:]
        rootgrp.close()
        delta_conc = deltaNOx_to_deltaNO2(delta_conc, base_conc_nox,
                                          base_conc_no2)

    # create a result netcdf
    # -----------------------
    if write_netcdf_output == True:
        filename_result_cdf = path_result_cdf + 'delta_concentration.nc'
        rootgrp = Dataset(filename_result_cdf, 'w', format='NETCDF3_CLASSIC')

        # create dimensions in the netcdf file
        rootgrp.createDimension('latitude', n_lat)
        rootgrp.createDimension('longitude', n_lon)
        latitudes = rootgrp.createVariable('latitude', 'f4', ('latitude', ))
        latitudes.units = "degrees_north"
        longitudes = rootgrp.createVariable('longitude', 'f4', ('longitude', ))
        longitudes.units = "degrees_east"
        latitudes[:] = latitude_array
        longitudes[:] = longitude_array

        # create delta concentration data
        delta_conc_pol = rootgrp.createVariable('delta_concentration', 'f4', (
            'latitude',
            'longitude',
        ))
        delta_conc_pol.units = 'ug/m3'
        delta_conc_pol[:] = delta_conc

        rootgrp.close()

    # create a results object
    mod1_res = {}
    mod1_res['delta_conc'] = delta_conc
    mod1_res['delta_emis_dict'] = delta_emission_dict
    mod1_res['n_lat'] = n_lat
    mod1_res['n_lon'] = n_lon
    mod1_res['latitude_array'] = latitude_array
    mod1_res['longitude_array'] = longitude_array

    return mod1_res