Exemple #1
0
def find_lat_index_bins(basin, lat):
    """
    find index of latitude bin in coefficients list

    Parameters
    ----------
    basin : basin.
    lat : latitude position.

    Returns
    -------
    latindex : index of bin.

    """
    s, monthdummy, lat0, lat1, lon0, lon1 = Basins_WMO(basin)
    base = 5
    latindex = np.floor(float(lat - lat0) / base)
    return latindex
Exemple #2
0
def Check_if_landfall(lat, lon, basin, land_mask):
    """
    Parameters
    ----------
    lat : latitude position of TC
    lon : longitude position of TC
    lat1 : upper left corner latitude coordinate of basin
    lon0 : upper left corner longitude coordinate of basin
    land_mask : land-sea mask

    Returns
    -------
    l : 0=no landfall, 1=landfall

    """
    s, monthdummy, lat0_WMO, lat1_WMO, lon0_WMO, lon1_WMO = Basins_WMO(basin)

    x = int(10 * (lon - lon0_WMO))
    y = int(10 * (lat1_WMO - lat))
    l = land_mask[y, x]
    return l
Exemple #3
0
#==============================================================================
# Step 1: Define basin and number of years to run
#==============================================================================
#please set basin (EP,NA,NI,SI,SP,WP)
basin = 'EP'
loop = 0  #ranges between 0 and 9 to simulate slices of 1000 years

total_years = 1000  #set the total number of years you'd like to simulate

TC_data = [
]  #This list is composed of: [year,storm number,lat,lon,pressure,wind,rmax,category,Holland B parameter,precipitation,landfall flag]
#==============================================================================
#     Step 2: load grid with weighted genesis counts
#==============================================================================
for year in range(0, total_years):
    storms_per_year, genesis_month, lat0, lat1, lon0, lon1 = Basins_WMO(basin)

    if storms_per_year > 0:
        #==============================================================================
        # Step 3: Generate (list of) genesis locations
        #==============================================================================
        lon_genesis_list, lat_genesis_list = Startingpoint(
            storms_per_year, genesis_month, basin)

        #==============================================================================
        # Step 4: Generate initial conditions
        #==============================================================================
        latlist, lonlist, landfalllist = TC_movement(lon_genesis_list,
                                                     lat_genesis_list, basin)

        TC_data = TC_pressure(basin, latlist, lonlist, landfalllist, year,
Exemple #4
0
def TC_movement(lon_genesis_list, lat_genesis_list, basin):
    """
    Parameters
    ----------
    lon_genesis_list : list of longitudinal positions of genesis in a year
    lat_genesis_list : list of latitudinal positions of genesis in a year
    basin : basin
    
    Returns
    ---------
    latall : all latitude positions of the eye of TC for every TC in a year
    lonall : all longitude positions of the eye of TC for every TC in a year
    landfallall : landfall (0=no 1=yes) along the track for every TC in a year
    """

    basins = ['EP', 'NA', 'NI', 'SI', 'SP', 'WP']
    basin_name = dict(zip(basins, [0, 1, 2, 3, 4, 5]))
    idx = basin_name[basin]

    constants_all = np.load(os.path.join(__location__,
                                         'TRACK_COEFFICIENTS.npy'),
                            allow_pickle=True,
                            encoding='latin1').item()

    land_mask = np.loadtxt(
        os.path.join(__location__, 'Land_ocean_mask_' + str(basin) + '.txt'))

    constants = constants_all[idx]

    s, monthdummy, lat0, lat1, lon0, lon1 = Basins_WMO(basin)
    latall = []
    lonall = []
    landfallall = []

    for lat_genesis, lon_genesis in zip(lat_genesis_list, lon_genesis_list):
        #load data for longitude/latitude
        latlijst = []
        lonlijst = []
        landfalllijst = []
        lat = lat_genesis
        lon = lon_genesis
        latlijst.append(lat)
        lonlijst.append(lon)
        landfall = Check_if_landfall(lat, lon, lat1, lon0,
                                     land_mask)  #1=landfall 0=no landfall
        landfalllijst.append(landfall)

        var = 0  #var is the 'stop-parameter'. The track generation ends when the storm moves over land or out of the basin
        while var == 0:
            ind = int(find_lat_index_bins(basin, lat))
            #constants values for latitude/longitude
            [
                a0, a1, b0, b1, b2, Elatmu, Elatstd, Elonmu, Elonstd, Dlat0mu,
                Dlat0std, Dlon0mu, Dlon0std
            ] = constants[ind]

            if len(
                    latlijst
            ) == 1:  #if this is the first time step after genesis, we need to sample the first change in lon/lat/pressure
                dlat0 = np.random.normal(Dlat0mu, Dlat0std, 1)
                dlon0 = np.random.normal(Dlon0mu, Dlon0std, 1)

            dlat1 = LAT_JAMES_MASON(dlat0, lat, b0, b1, b2)
            if basin == 'SP' or basin == 'SI':
                if lat > -10.:
                    dlat1 = float(dlat1 -
                                  np.abs(np.random.normal(Elatmu, Elatstd)))
                else:
                    dlat1 = float(dlat1 + np.random.normal(Elatmu, Elatstd))

            else:
                if lat < 10.:
                    dlat1 = float(dlat1 +
                                  np.abs(np.random.normal(Elatmu, Elatstd)))
                else:
                    dlat1 = float(dlat1 + np.random.normal(Elatmu, Elatstd))

            dlon1 = LON_JAMES_MASON(dlon0, a0, a1)
            epsilon = np.random.normal(Elonmu, Elonstd)
            dlon1 = float(dlon1 + epsilon)
            if np.abs(lat) >= 45:
                if dlon1 < 0.:
                    dlon1 = 0

            lat = round(dlat1 + lat, 1)
            lon = round(dlon1 + lon, 1)

            dlat0 = dlat1
            dlon0 = dlon1

            if lat <= lat1 - 0.1 and lat > lat0 and lon <= lon1 - 0.1 and lon > lon0:  #if storm is still inside the domain. The 0.1's are added to make sure we don't end up at the upper/rightmost edge
                latlijst.append(lat)
                lonlijst.append(lon)
                landfall = Check_if_landfall(
                    lat, lon, lat1, lon0, land_mask)  #1=landfall 0=no landfall
                landfalllijst.append(landfall)

            else:  #the storm has moved out of the domain. Stop the algorithm
                var = 1
                latall.append(
                    latlijst
                )  #all locations of all storms (seperate entries) are contained in these two lists
                lonall.append(lonlijst)
                landfallall.append(landfalllijst)

    return (latall, lonall, landfallall)
Exemple #5
0
def confidence_interval(data, confidence=0.95):
    a = 1.0 * np.array(data)
    n = len(a)
    m, se = np.mean(a), scipy.stats.sem(a)
    h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)
    return m+h, m-h

#==============================================================================
# Make a list of different return periods
#==============================================================================
returnperiods=[]
returnperiods.extend(np.linspace(10,100,10))
returnperiods.extend(np.linspace(200,1000,9))
returnperiods.extend(np.linspace(2000,10000,9))

lat0,lat1,lon0,lon1=Basins_WMO(basin)[2:]
# =============================================================================
# Make a list of all lon/lat points in the basin
# =============================================================================

res=0.1
if lat0>0:
    latspace=np.arange(lat0+res/2.,lat1+res/2.,res)
else:
    latspace=np.arange(lat0-res/2.,lat1-res/2.,res)

lonspace=np.arange(lon0+res/2.,lon1+res/2.,res)

points=[(i,j) for i in latspace for j in lonspace]

all_data={i:[] for i in range(len(points))}
Exemple #6
0
def TC_pressure(basin, latlist, lonlist, landfalllist, year, storms, monthlist,
                TC_data):
    """
    Calculate TC pressure

    Parameters
    ----------
    basin : basin.
    latlist : array of TC track latitude positions.
    lonlist : array of TC track longitude positions.
    landfalllist : array of TC landfall (0=no 1=yes).
    year : year
    storms : number of storms.
    monthlist : months of TC occurrence.
    TC_data : array of TC data.

    Returns
    -------
    TC_data : array of TC data + new TCs

    """

    basin_name = dict(
        zip(['EP', 'NA', 'NI', 'SI', 'SP', 'WP'], [0, 1, 2, 3, 4, 5]))

    idx = basin_name[basin]

    latidx_penv = np.linspace(90, -90, 721)
    lonidx_penv = np.linspace(0, 359.75, 1440)

    JM_pressure = np.load(
        os.path.join(__location__, 'COEFFICIENTS_JM_PRESSURE.npy')).item()

    Genpres = np.load(os.path.join(__location__,
                                   'DP0_PRES_GENESIS.npy')).item()

    WPR_coefficients = np.load(
        os.path.join(__location__, 'COEFFICIENTS_WPR_PER_MONTH.npy')).item()

    Genwind = np.load(os.path.join(__location__, 'GENESIS_WIND.npy')).item()

    intlist = [5, 3, 2, 5, 5, 5]

    int_thres = intlist[idx]

    s, monthdummy, lat0, lat1, lon0, lon1 = Basins_WMO(basin)

    wind_threshold = 18.  #if vmax<18, the storm is a tropical depression and we stop tracking it.

    for storm_number, month, latfull, lonfull, landfallfull in zip(
            range(0, int(storms)), monthlist, latlist, lonlist, landfalllist):
        i = 0
        vmax = 0
        count = 0
        p = np.nan

        #This is the full MSLP field, with lat0=90 deg, lat1=-90 deg, lon0=0 deg, lon1=359.75 deg. len(lat)=721, len(lon)=1440
        Penv_field = np.loadtxt(
            os.path.join(dir_path, 'Monthly_mean_MSLP_' + str(month) + '.txt'))

        constants_pressure = JM_pressure[idx][month]
        constants_pressure = np.array(constants_pressure)

        coef = WPR_coefficients[idx][month]
        coef = np.array(coef)

        p_threshold = min(constants_pressure[:, 6]) - 10.

        EP = Genpres[idx][month]

        while i < len(latfull):
            lat, lon, landfall = latfull[i], lonfull[i], landfallfull[i]

            lat_dummy = np.abs(latidx_penv - lat).argmin()
            lon_dummy = np.abs(lonidx_penv - lon).argmin()

            Penv = Penv_field[lat_dummy, lon_dummy]

            if lat0 <= lat <= lat1 and lon0 <= lon <= lon1:  #make sure we're inside the basin

                if ((p < p_threshold)
                        | math.isnan(p)):  #something went wrong. start again
                    i = 0
                    vmax = 0

                if i == 0:
                    vmax = random.choice(Genwind[idx][month])
                    p = Calculate_Pressure(vmax, Penv, coef)

                    pressure_list = []
                    wind_list = []
                    #at genesis, we need to sample the genesis pressure and dp1. This is done basin-wide:

                    [Pmu, Pstd, DP0mu, DP0std, dpmin, dpmax] = EP
                    dp0 = np.random.normal(DP0mu, DP0std)

                    dp1 = -1. * np.abs(dp0)

                    pressure_list.append(p)

                    wind_list.append(vmax)

                    i = i + 1

                #next: check if the storm makes landfall. In that case, we move to the dissipation-formula
                if landfall == 1:  #landfall --> use Kaplan and DeMaria Formula for dissipation
                    if ((p < p_threshold) | math.isnan(p)):
                        print('Landfall', p, p_threshold)
                        i = 0
                        vmax = 0

                    elif vmax < wind_threshold or p > Penv:  #The storm makes landfall as a tropical depression
                        TC_data = add_parameters_to_TC_data(
                            pressure_list, wind_list, latfull, lonfull, year,
                            storm_number, month, basin, landfallfull,
                            pressure_list, TC_data, idx)
                        i = 1000000000000000

                    else:
                        #calculate the landfall pressure

                        ind = int(
                            find_index_pressure(
                                basin, lat, lon, lat0, lon0,
                                lon1))  #find index for pressure

                        [c0, c1, c2, c3, EPmu, EPstd,
                         mpi] = constants_pressure[ind]
                        y = PRESSURE_JAMES_MASON(dp1, p, c0, c1, c2, c3, mpi)
                        epsilon = np.random.normal(EPmu, EPstd)
                        dp0 = float(y + epsilon)

                        while dp0 < dpmin:  #if more intensification than seen in the underlying dataset
                            if y - dpmin > EPmu - 2. * EPstd:  #epsilon should be resampled
                                epsilon = np.random.normal(EPmu, EPstd)
                                dp0 = y + epsilon
                            else:  #y is already smaller than dpmin.
                                dp0 = np.random.uniform(dpmin, 0)

                        while dp0 > dpmax:  #if more weakening than seen in the underlying dataset
                            if y - dpmax < EPmu + 2. * EPstd:
                                epsilon = np.random.normal(EPmu, EPstd)
                                dp0 = y + epsilon
                            else:
                                dp0 = np.random.uniform(0, dpmax)

                        if p < mpi:  #if pressure has dropped below mpi
                            if dp0 < 0:  #if intensification
                                if count < 2:  #if intensification has been going on for less than 2 time steps
                                    count = count + 1
                                else:
                                    dp0 = abs(dp0)

                        else:  #the storm is above mpi
                            count = 0

                        p = round(dp0 + p, 1)
                        dp1 = dp0

                        if vmax < wind_threshold or p > Penv:  #The storm is no longer a tropical storm
                            #print('Dissipated',len(pressure_list),len(landfallfull))
                            TC_data = add_parameters_to_TC_data(
                                pressure_list, wind_list, latfull, lonfull,
                                year, storm_number, month, basin, landfallfull,
                                pressure_list, TC_data, idx)
                            i = 10000000000000000000000000000000

                        else:
                            pressure_list.append(p)

                            vmax = Calculate_Vmax(Penv, p, coef)
                            vmax = round(vmax, 1)
                            wind_list.append(vmax)

                    if any(
                            c < 1 for c in landfallfull[i:]
                    ):  #check whether the storm moves back over the ocean

                        check_move_ocean = i + np.where(
                            np.array(landfallfull[i:]) == 0.)[0][0]
                        #storm moves back over open ocean: apply decay function for i till check_move_ocean

                        if check_move_ocean > i + 3:  #if this is not the case, we're crossing a very small island and no decay function should be used then

                            decay_pressure, decay_wind = decay_after_landfall(
                                lat, lon, latfull[i:i + check_move_ocean],
                                lonfull[i:i + check_move_ocean], p, coef, Penv)
                            for d in range(len(decay_pressure)):
                                pressure_list.append(decay_pressure[d])
                                wind_list.append(decay_wind[d])

                        #if the storm has decayed before moving back over the ocean:
                        if wind_list[-1] < wind_threshold:
                            TC_data = add_parameters_to_TC_data(
                                pressure_list, wind_list, latfull, lonfull,
                                year, storm_number, month, basin, landfallfull,
                                pressure_list, TC_data, idx)

                            i = 10000000000000000000000000.

                        #if the storm has not decayed:
                        else:
                            dp1 = pressure_list[-1] - pressure_list[-2]
                            p = pressure_list[-1]
                            i = check_move_ocean

                    else:  #the storm does not move back over open ocean, so use the decay function until the storm has dissipated
                        decay_pressure, decay_wind = decay_after_landfall(
                            lat, lon, latfull[i:], lonfull[i:], p, coef, Penv)
                        for d in range(len(decay_pressure)):
                            pressure_list.append(decay_pressure[d])
                            wind_list.append(decay_wind[d])

                        #print('Decayed over land',len(pressure_list),len(landfallfull))
                        TC_data = add_parameters_to_TC_data(
                            pressure_list, wind_list, latfull, lonfull, year,
                            storm_number, month, basin, landfallfull,
                            pressure_list, TC_data, idx)

                        i = 1000000000000

                else:  #no landfall
                    if ((p < p_threshold) | math.isnan(p)):
                        print('No landfall', p, p_threshold)
                        i = 0
                        vmax = 0

                    elif vmax < wind_threshold or p > Penv and i > 3:  #The storm is no longer a tropical storm
                        #print('Dissipated',len(pressure_list),len(landfallfull))
                        TC_data = add_parameters_to_TC_data(
                            pressure_list, wind_list, latfull, lonfull, year,
                            storm_number, month, basin, landfallfull,
                            pressure_list, TC_data, idx)

                        i = 1000000000000000

                    else:  #apply James-Mason formula to find next change in pressure
                        ind = int(
                            find_index_pressure(
                                basin, lat, lon, lat0, lon0,
                                lon1))  #find index for pressure

                        [c0, c1, c2, c3, EPmu, EPstd,
                         mpi] = constants_pressure[ind]

                        y = PRESSURE_JAMES_MASON(dp1, p, c0, c1, c2, c3, mpi)

                        epsilon = np.random.normal(EPmu, EPstd)

                        dp0 = float(y + epsilon)

                        while dp0 < dpmin:  #if more intensification than seen in the underlying dataset
                            if y - dpmin > EPmu - 2. * EPstd:  #epsilon should be resampled
                                epsilon = np.random.normal(EPmu, EPstd)
                                dp0 = y + epsilon
                            else:  #y is already smaller than dpmin.
                                dp0 = np.random.uniform(dpmin, 0)

                        while dp0 > dpmax:  #if more weakening than seen in the underlying dataset
                            if y - dpmax < EPmu + 2. * EPstd:
                                epsilon = np.random.normal(EPmu, EPstd)
                                dp0 = y + epsilon
                            else:
                                dp0 = np.random.uniform(0, dpmax)

                        if p < mpi:  #if pressure has dropped below mpi
                            if dp0 < 0:  #if intensification
                                if count < 2:  #if intensification has been going on for less than 2 time steps
                                    count = count + 1
                                else:
                                    dp0 = abs(dp0)

                        else:  #the storm is above mpi
                            count = 0

                        if i < int_thres:
                            dp0 = -1. * np.abs(dp0)
                        p = round(dp0 + p, 1)
                        dp1 = dp0

                        if vmax < wind_threshold or p > Penv:  #The storm is no longer a tropical storm
                            #print('Dissipated',len(pressure_list),len(landfallfull))
                            TC_data = add_parameters_to_TC_data(
                                pressure_list, wind_list, latfull, lonfull,
                                year, storm_number, month, basin, landfallfull,
                                pressure_list, TC_data, idx)
                            i = 10000000000000000000000000000000

                        else:
                            pressure_list.append(p)

                            vmax = Calculate_Vmax(Penv, p, coef)
                            vmax = round(vmax, 1)
                            wind_list.append(vmax)

                            i = i + 1

            else:  #we are outside the basin. Move on to the next storm
                TC_data = add_parameters_to_TC_data(pressure_list, wind_list,
                                                    latfull, lonfull, year,
                                                    storm_number, month, basin,
                                                    landfallfull,
                                                    pressure_list, TC_data,
                                                    idx)
                i = 100000000000000000.

        if i == len(latfull):
            TC_data = add_parameters_to_TC_data(pressure_list, wind_list,
                                                latfull, lonfull, year,
                                                storm_number, month, basin,
                                                landfallfull, pressure_list,
                                                TC_data, idx)

    return (TC_data)
Exemple #7
0
def Startingpoint(no_storms, monthlist, basin):
    """
    This function samples the genesis locations of every TC in a given year

    Parameters
    ----------
    no_storms : number of TCs in given year
    monthlist : months in which TCs were formed.
    basin : basin.

    Returns
    -------
    lon_coordinates : list of longitude coordinates of genesis locations
    lat_coordinates : list of latitude coordinates of genesis locations

    """
    basins = ['EP', 'NA', 'NI', 'SI', 'SP', 'WP']
    basin_name = dict(zip(basins, [0, 1, 2, 3, 4, 5]))
    idx = basin_name[basin]

    lon_coordinates = []
    lat_coordinates = []
    weighted_list_index = []
    weighted_list = []

    s, monthdummy, lat0, lat1, lon0, lon1 = Basins_WMO(basin)

    land_mask = np.loadtxt(
        os.path.join(dir_path, 'Land_ocean_mask_' + str(basin) + '.txt'))

    for month in monthlist:

        grid_copy = np.loadtxt(
            os.path.join(
                dir_path,
                'GRID_GENESIS_MATRIX_' + str(idx) + '_' + str(month) + '.txt'))

        grid_copy = np.array(grid_copy)
        grid_copy = np.round(grid_copy, 1)
        #==============================================================================
        # Make a list with weighted averages. The corresponding grid-index is calculated as len(col)*row_index+col_index
        #==============================================================================

        for i in range(0, len(grid_copy[:, 0])):
            for j in range(0, len(grid_copy[0, :])):
                if grid_copy[i, j] > -1:
                    value = int(10 * grid_copy[i, j])
                else:
                    value = 0
                if value > 0.:
                    for k in range(0, value):
                        weighted_list.append(value)
                        weighted_list_index.append(i *
                                                   (len(grid_copy[0, :]) - 1) +
                                                   j)

        #==============================================================================
        # The starting longitude and latitude coordinates
        #==============================================================================
        var = 0
        while var == 0:
            idx0 = random.choice(weighted_list_index)

            row = int(np.floor(idx0 / (len(grid_copy[0, :]) - 1)))
            col = int(idx0 % (len(grid_copy[0, :]) - 1))
            lat_pert = random.uniform(
                0, 0.94
            )  #take 0.94 to make sure the randomly selected point is still inside the grid box after rounding off.
            lon_pert = random.uniform(0, 0.94)
            lon = lon0 + round(col + lon_pert, 1)
            lat = lat1 - round(row + lat_pert, 1)

            if lon < lon1 and lat < lat1:
                check = Check_if_landfall(
                    lat, lon, basin,
                    land_mask)  #make sure the coordinate isn't on land

                if basin == 'EP':
                    check = Check_NA_formation(lat, lon)
                if basin == 'NA':
                    check = Check_EP_formation(lat, lon)

                if check == 0:
                    lon_coordinates.append(lon)
                    lat_coordinates.append(lat)
                    var = 1
                else:
                    var = 0

        if len(lon_coordinates) == no_storms:
            return lon_coordinates, lat_coordinates