diff --git a/.gitignore b/.gitignore index fff9635901acfebe93ff008cb9eae743ad3c3c43..565881829e14d90966bd3d3dc4f9e20e279ce0c9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea *.o *.mod +.vscode diff --git a/new_masks/basins.yml b/new_masks/basins.yml new file mode 100644 index 0000000000000000000000000000000000000000..201d6fe02166b44f491f270f472db1486961e59d --- /dev/null +++ b/new_masks/basins.yml @@ -0,0 +1,438 @@ +basins: + Global_Ocean: + - {lat: [-90, 90], lon: [-180, 180]} + + Northern_Hemisphere: + - {lat: [0, 90], lon: [-180, 180]} + + Southern_Hemisphere: + - {lat: [-90, 0], lon: [-180, 180]} + + Antarctic_Ocean: + - {lat: [-90, -40], lon: [-180, 180]} + + Mediterranean_Sea: + - {lat: [30, 40], lon: [-5, 0]} + - {lat: [30, 46], lon: [0, 28]} + - {lat: [30, 40], lon: [28, 40]} + + North_Atlantic_Ocean: + - {basin: Atlantic_Ocean} + - {lat: [32, 82], lon: [-180, 180], action: intersection} + - {basin: Mediterranean_Sea, action: remove} + + Greenland_Sea: + - {lat: [76, 81], lon: [-30, 17]} + - {lat: [75, 76], lon: [-30, 12]} + - {lat: [74, 75], lon: [-30, 9]} + - {lat: [73, 74], lon: [-30, 4]} + - {lat: [72, 73], lon: [-30, 0]} + - {lat: [71, 72], lon: [-30, -3]} + - {lat: [70, 71], lon: [-30, -8]} + + Icelandic_Sea: + - {lat: [69, 70], lon: [-29, -9]} + - {lat: [68, 69], lon: [-28, -10]} + - {lat: [67, 68], lon: [-25, -11]} + - {lat: [66, 67], lon: [-23, -12]} + - {lat: [65, 66], lon: [-20, -13]} + + Norwegian_Sea: + - {lat: [75, 76], lon: [12, 17]} + - {lat: [74, 75], lon: [9, 18]} + - {lat: [73, 74], lon: [4, 19]} + - {lat: [72, 73], lon: [0, 21]} + - {lat: [71, 72], lon: [-3, 23]} + - {lat: [70, 71], lon: [-8, 25]} + - {lat: [66, 70], lon: [-13, 25]} + - {lat: [62, 66], lon: [-6, 15]} + - {lat: [61, 62], lon: [0, 15]} + - {lat: [63, 64], lon: [-8, -6]} + - {lat: [64, 66], lon: [-10, -6]} + - {lat: [65, 66], lon: [-13, -6]} + - {basin: Icelandic_Sea, action: remove} + + Barents_Sea: + - {lat: [76, 80], lon: [17, 65]} + - {lat: [75, 76], lon: [17, 62]} + - {lat: [74, 75], lon: [18, 59]} + - {lat: [73, 74], lon: [19, 58]} + - {lat: [72, 73], lon: [21, 56]} + - {lat: [71, 72], lon: [23, 56]} + - {lat: [70, 71], lon: [25, 57]} + - {lat: [66, 70], lon: [25, 60]} + - {lat: [63, 66], lon: [30, 45]} + + Kara_Sea: + - {lat: [79, 80], lon: [65, 96]} + - {lat: [76, 79], lon: [65, 105]} + - {lat: [75, 76], lon: [62, 100]} + - {lat: [74, 75], lon: [59, 100]} + - {lat: [73, 74], lon: [58, 100]} + - {lat: [71, 73], lon: [56, 100]} + - {lat: [70, 71], lon: [57, 100]} + - {lat: [66, 70], lon: [60, 90]} + + Laptev_Sea: + - {lat: [80, 81], lon: [96, 102]} + - {lat: [79, 80], lon: [100, 111]} + - {lat: [78, 79], lon: [105, 120]} + - {lat: [77, 78], lon: [105, 129]} + - {lat: [76, 77], lon: [100, 138]} + - {lat: [70, 76], lon: [105, 140]} + - {basin: Kara_Sea, action: remove} + + East_Siberian_Sea: + - {lat: [74, 75], lon: [140, 146]} + - {lat: [73, 74], lon: [140, 154]} + - {lat: [72, 73], lon: [140, 162]} + - {lat: [71, 72], lon: [140, 170]} + - {lat: [70, 71], lon: [140, 179]} + - {lat: [69, 70], lon: [140, 178]} + - {lat: [68, 69], lon: [140, 178]} + + Chukchi_Sea: + - {lat: [66, 71], lon: [-180, -156]} + - {lat: [66, 71], lon: [179, 180]} + - {lat: [69, 70], lon: [178, 180]} + + Okhotsk: + - {lat: [43, 44], lon: [141, 146]} + - {lat: [44, 45], lon: [141, 147]} + - {lat: [45, 46], lon: [141, 150]} + - {lat: [46, 47], lon: [141, 150]} + - {lat: [47, 48], lon: [141, 151]} + - {lat: [48, 49], lon: [141, 152.5]} + - {lat: [49, 50], lon: [141, 154]} + - {lat: [50, 51], lon: [141, 155.5]} + - {lat: [51, 52], lon: [139, 157]} + - {lat: [52, 63], lon: [135, 157]} + - {lat: [58, 63], lon: [157, 163]} + - {lat: [60, 63], lon: [162, 164]} + - {lat: [48, 51], lon: [151, 157]} + + Bering: + - {lat: [58, 66], lon: [-180, -154]} + - {lat: [55, 66], lon: [161, 180]} + - {lat: [53, 60], lon: [160, 180]} + - {lat: [56, 60], lon: [-180, -155]} + - {lat: [55, 58], lon: [-180, -157]} + - {lat: [55, 58], lon: [163, 180]} + - {lat: [54, 57], lon: [-180, -160]} + - {lat: [54, 57], lon: [167, 180]} + - {lat: [54, 56], lon: [-180, -165]} + - {lat: [54, 56], lon: [171, 180]} + - {lat: [53, 55], lon: [-180, -170]} + - {lat: [53, 55], lon: [174, 180]} + - {lat: [53, 54], lon: [-180, -174]} + - {lat: [53, 54], lon: [177, 180]} + - {lat: [52, 53], lon: [-180, -178]} + - {basin: Okhotsk, action: remove} + + Beaufort_Sea: + - {lat: [75, 76], lon: [-130, -124]} + - {lat: [74, 75], lon: [-136, -124]} + - {lat: [73, 74], lon: [-143, -125]} + - {lat: [72, 73], lon: [-149, -125]} + - {lat: [71, 72], lon: [-156, -126]} + - {lat: [70, 71], lon: [-156, -126]} + - {lat: [69, 70], lon: [-156, -127]} + - {lat: [73, 77], lon: [-124, -120]} + - {lat: [73, 75], lon: [-125, -124]} + - {lat: [69, 73], lon: [-127, -124]} + + Baffin_Bay: + - {lat: [70, 81], lon: [-84, -45]} + - {lat: [66, 70], lon: [-70, -45]} + - {lat: [62, 66], lon: [-66, -45]} + - {lat: [61, 62], lon: [-65, -45]} + + Hudson: + - {lat: [50, 67], lon: [-95, -66]} + - {lat: [67, 70], lon: [-85, -70]} + - {lat: [59, 62], lon: [-66, -65]} + + Labrador_Sea: + - {lat: [60, 61], lon: [-65, -45]} + - {lat: [59, 60], lon: [-65, -46]} + - {lat: [58, 59], lon: [-64, -46]} + - {lat: [57, 58], lon: [-63, -47]} + - {lat: [56, 57], lon: [-62, -47]} + - {lat: [55, 56], lon: [-61, -48]} + - {lat: [54, 55], lon: [-60, -48]} + - {lat: [53, 54], lon: [-59, -49]} + - {lat: [51, 53], lon: [-58, -49]} + - {lat: [48.5, 52], lon: [-57, -50]} + - {lat: [50, 51], lon: [-56, -50]} + - {lat: [47.5, 50], lon: [-56, -51]} + + Irminger_Sea: + - {lat: [58.3, 67.5], lon: [-46, -40]} + - {lat: [60, 67.5], lon: [-40, -35]} + - {lat: [61, 68], lon: [-35, -23]} + - {basin: Icelandic_Sea, action: remove} + - {basin: Labrador_Sea, action: remove} + + NorthWest_Passage: + - {lat: [73, 77], lon: [-120, -84]} + - {lat: [67, 73], lon: [-124, -85]} + - {lat: [76, 77], lon: [-120, -84]} + - {lat: [77, 78], lon: [-116, -84]} + - {lat: [78, 79], lon: [-108, -84]} + - {lat: [79, 80], lon: [-100, -84]} + - {lat: [80, 81], lon: [-93, -84]} + - {lat: [81, 82], lon: [-85, -84]} + - {lat: [82, 83], lon: [-77, -75]} + + CanArch: + - {basin: NorthWest_Passage} + + Lincoln_Sea: + - {lat: [81, 84], lon: [-60, -32]} + - {lat: [81, 83], lon: [-70, -60]} + + Nordic_Seas: + - {basin: Icelandic_Sea} + - {basin: Norwegian_Sea} + - {basin: Greenland_Sea} + + Grnland: + - {basin: Icelandic_Sea} + - {basin: Norwegian_Sea} + - {basin: Greenland_Sea} + + Arctic_Marginal_seas: + - {basin: Icelandic_Sea} + - {basin: Norwegian_Sea} + - {basin: Greenland_Sea} + - {basin: Barents_Sea} + - {basin: Kara_Sea} + - {basin: Baffin_Bay} + - {basin: Laptev_Sea} + - {basin: Hudson} + - {basin: East_Siberian_Sea} + - {basin: Beaufort_Sea} + - {basin: NorthWest_Passage} + - {basin: Chukchi_Sea} + - {basin: Bering} + - {basin: Okhotsk} + + Central_Arctic_1: + - {basin: Arctic_Marginal_seas} + - {lat: [70, 90], lon: [-180, 180], action: intersection} + - {basin: Lincoln_Sea, action: remove} + + Central_Arctic: + - {basin: Central_Arctic_1} + - {basin: Lincoln_Sea} + + Western_Central_Arctic: + - {lat: [70, 90], lon: [-180, -90]} + - {lat: [70, 90], lon: [90, 180]} + - {basin: Central_Arctic, action: intersection} + + Eastern_Central_Arctic: + - {basin: Central_Arctic} + - {lat: [70, 90], lon: [-90, 90], action: intersection} + + Arctic_Ocean: + - {basin: Arctic_Marginal_seas} + - {lat: [0, 90], lon: [-180, 180], action: intersection} + - {basin: Central_Arctic} + + Arctic_Ocean: + - {lat: [70, 90], lon: [-180, 180]} + + Baltic_Sea: + - {lat: [50, 66], lon: [15, 30]} + - {lat: [50, 56], lon: [10, 15]} + + StLawr: + - {lat: [48, 52], lon: [-70, -55]} + - {lat: [47, 48], lon: [-70, -58]} + - {lat: [46, 47], lon: [-70, -59]} + - {lat: [45, 46], lon: [-70, -60]} + + Caspian_Sea: + - {lat: [35, 50], lon: [45, 60]} + + Fram_Strait: + - {lat: [80, 81], lon: [-30, 17]} + + Bering_Strait: + - {lat: [65, 66], lon: [-175, -165]} + + Nares_Strait: + - {lat: [80, 81], lon: [-84, -45]} + + Kara_Gate_Strait: + - {lat: [70, 71], lon: [57, 59]} + - {lat: [69, 70], lon: [60, 61]} + + Vilkitsky_Strait: + - {lat: [76, 79], lon: [100, 105]} + - {lat: [70, 76], lon: [99, 100]} + + Weddell_Sea: + - {lat: [-90, -40], lon: [-65, -15]} + + Ross_Sea: + - {lat: [-90, -40], lon: [-180, -140]} + - {lat: [-90, -40], lon: [160, 180]} + + Amundsen_Sea: + - {lat: [-90, -40], lon: [-140, -90]} + + Bellingshausen_Sea: + - {lat: [-90, -40], lon: [-90, -65]} + + Antarctic_Atlantic_Sector: + - {lat: [-90, -40], lon: [-15, 22]} + + Antarctic_Indian_Sector: + - {lat: [-90, -40], lon: [22, 160]} + + LAT80N: + - {lat: [80, 90], lon: [-180, 180]} + + CntArcticRing1: + - {lat: [78, 86], lon: [0, 45]} + + CntArcticRing2: + - {lat: [78, 86], lon: [45, 90]} + + CntArcticRing3: + - {lat: [78, 86], lon: [90, 135]} + + CntArcticRing4: + - {lat: [78, 86], lon: [135, 180]} + + CntArcticRing5: + - {lat: [78, 86], lon: [-180, -135]} + + CntArcticRing6: + - {lat: [78, 86], lon: [-135, -90]} + + CntArcticRing7: + - {lat: [78, 86], lon: [-90, -45]} + + CntArcticRing8: + - {lat: [78, 86], lon: [-45, 0]} + + CntArctic: + - {lat: [86, 90], lon: [-180, 180]} + + Barkara: + - {basin: Barents_Sea} + - {basin: Kara_Sea} + + Laptev-East_Siberian_Seas: + - {basin: East_Siberian_Sea} + - {basin: Laptev_Sea} + + Canadian_Waters: + - {basin: NorthWest_Passage} + - {basin: Baffin_Bay} + - {basin: Hudson} + - {basin: Labrador_Sea} + + Beaufort-Chukchi_Sea: + - {basin: Beaufort_Sea} + - {basin: Chukchi_Sea} + + Laptev-East_Siberian-Chukchi_Seas: + - {basin: East_Siberian_Sea} + - {basin: Laptev_Sea} + - {basin: Chukchi_Sea} + + Nordic-Barents_Seas: + - {basin: Nordic_Seas} + - {basin: Barents_Sea} + + Serreze_Arctic: + - {basin: Central_Arctic} + - {basin: Barents_Sea} + - {basin: Kara_Sea} + - {basin: Laptev_Sea} + - {basin: East_Siberian_Sea} + - {basin: Chukchi_Sea} + - {basin: Beaufort_Sea} + + North_Hemisphere_Ocean: + - {basin: Northern_Hemisphere} + - {basin: Caspian_Sea, action: remove} + - {basin: Baltic_Sea, action: remove} + + Baffin: + - {basin: Baffin_Bay} + - {basin: Labrador_Sea} + + ArctOcn: + - {basin: Central_Arctic} + - {basin: Lincoln_Sea} + - {basin: Chukchi_Sea} + - {basin: East_Siberian_Sea} + - {basin: Laptev_Sea} + - {basin: Beaufort_Sea} + + OpenOcean: + - {basin: Northern_Hemisphere} + - {basin: Arctic_Ocean, action: remove} + - {basin: Labrador_Sea, action: remove} + - {basin: StLawr, action: remove} + + TotalArc: + - {basin: Baffin_Bay} + - {basin: Barents_Sea} + - {basin: Beaufort_Sea} + - {basin: Bering} + - {basin: NorthWest_Passage} + - {basin: Central_Arctic} + - {basin: Chukchi_Sea} + - {basin: East_Siberian_Sea} + - {basin: Greenland_Sea} + - {basin: Hudson} + - {basin: Icelandic_Sea} + - {basin: Labrador_Sea} + - {basin: Laptev_Sea} + - {basin: Norwegian_Sea} + - {basin: Okhotsk} + - {basin: Lincoln_Sea} + - {basin: Irminger_Sea} + + North_Atlantic-Arctic: + - {basin: North_Atlantic_Ocean} + - {basin: Barents_Sea} + - {basin: Hudson, action: remove} + - {basin: CanArch, action: remove} + - {basin: Baltic_Sea, action: remove} + + Subpolar_Gyre: + - {basin: North_Atlantic-Arctic} + - {basin: Baffin_Bay, action: remove} + - {basin: Nordic-Barents_Seas, action: remove} + + Arctic_Ocean-North_Atlantic: + - {basin: North_Atlantic-Arctic} + - {basin: Kara_Sea} + - {basin: ArctOcn} + + Nino1+2: + - {lat: [-10, 0], lon: [-90, -80]} + + Nino3: + - {lat: [-5, 5], lon: [-150, -90]} + + Nino3.4: + - {lat: [-5, 5], lon: [-170, -120]} + + Nino4: + - {lat: [-5, 5], lon: [-180, -150]} + - {lat: [-5, 5], lon: [160, 180]} + + AMV_North_Atlantic: + - {lat: [0, 60], lon:[-80, 0]} + + AMV_trend: + - {lat: [-60, 60], lon: [-180, 180]} + \ No newline at end of file diff --git a/new_masks/create_basins_mask.py b/new_masks/create_basins_mask.py new file mode 100644 index 0000000000000000000000000000000000000000..3774b7bbabec3fb02f69c9efa9db6f0a664d3958 --- /dev/null +++ b/new_masks/create_basins_mask.py @@ -0,0 +1,148 @@ +import os +from six import iteritems, string_types +import numpy as np +import iris +from iris.cube import CubeList +from iris.coords import AuxCoord +from iris.util import squeeze +import yaml +from numba import vectorize, int8, float32 + +def create_mask(mesh_file, maskglo_file, config_file=None): + if not config_file: + cwd = os.path.dirname(os.path.realpath(__file__)) + config_file = os.path.join(cwd, 'basins.yml') + + with open(config_file, 'r') as yfile: + config = yaml.safe_load(yfile) + + sea_mask = squeeze(iris.load_cube(mesh_file, 'tmask'))[0, ...] + lat = iris.load_cube(mesh_file, 'nav_lat').data + lon = iris.load_cube(mesh_file, 'nav_lon').data + basins = CubeList() + basin_model = sea_mask.copy() + + basins_from_file = { + 'Atlantic_Ocean': 'tmaskatl', + 'Pacific_Ocean': 'tmaskpac', + 'Indian_Ocean': 'tmaskind', + } + for basin, variable in iteritems(basins_from_file): + mask = squeeze(iris.load_cube(maskglo_file, variable)).data.astype(np.int8) + basin_mask = basin_model.copy() * mask + basins.append(prepare_cube(basin_mask, basin)) + + print('\nCreating basins from boxes') + for basin, basin_config in iteritems(config['basins']): + print('Creating basin', basin, 'from', basin_config) + mask = create_basin(flatten_list(basin_config), lat, lon, basins) + basin_mask = basin_model.copy() * mask + basins.append(prepare_cube(basin_mask, basin)) + + print('Merging and saving') + basins = basins.merge_cube() + basins.add_aux_coord( + AuxCoord(lat, 'latitude', 'nav_lat'), + (1, 2) + ) + basins.add_aux_coord( + AuxCoord(lat, 'longitude', 'nav_lon'), + (1, 2) + ) + iris.save( + basins, + 'basins.nc', + zlib=True, + chunksizes=(1, basins.shape[1], basins.shape[2]) + ) + + import matplotlib + matplotlib.use('Qt5Agg') + import matplotlib.pyplot as plt + import iris.quickplot as qplt + print(basins) + basins.remove_coord('latitude') + basins.remove_coord('longitude') + for basin_slice in basins.slices_over('region'): + basin_slice.long_name = basin_slice.coord('region').points[0] + basin_slice.standard_name = None + qplt.pcolormesh(basin_slice) + plt.show() + +def flatten_list(config): + final_list = [] + for conf in config: + if isinstance(conf, dict) or isinstance(conf, string_types): + final_list.append(conf) + else: + final_list.extend(conf) + return final_list + +def create_basin(box_list, lat, lon, basins): + if not box_list: + return None + + mask = None + for box in box_list: + if 'lat' in box: + current_box = apply_config(box['lat'][0], box['lat'][1], lat) * apply_config(box['lon'][0], box['lon'][1], lon) + if mask is None: + mask = current_box + continue + next_mask = current_box + elif 'basin' in box: + sea = basins.extract(iris.Constraint(region=box['basin']))[0] + if mask is None: + mask = sea.data.copy() + continue + next_mask = sea.data + action = box.get('action', 'add') + if action == 'add': + mask = add(mask, next_mask) + elif action == 'remove': + mask = remove(mask, next_mask) + elif action == 'intersection': + mask = intersection(mask, next_mask) + + return mask + +def prepare_cube(cube, basin): + cube.add_aux_coord(AuxCoord([basin], var_name='region')) + cube.var_name = 'basin' + cube.standard_name = 'region' + cube.long_name = 'Regional masks' + cube.attributes = {} + return cube + +@vectorize([int8(float32, float32, float32)], nopython=True) +def apply_config(min, max, data): + if data < min: + return 0 + if data > max: + return 0 + return 1 + +@vectorize([int8(int8, int8)], nopython=True) +def add(mask1, mask2): + if mask1 + mask2 > 0: + return 1 + return 0 + +@vectorize([int8(int8, int8)], nopython=True) +def remove(mask1, mask2): + if mask1 - mask2 < 1: + return 0 + return 1 + +@vectorize([int8(int8, int8)], nopython=True) +def intersection(mask1, mask2): + if mask1 and mask2: + return 1 + return 0 + + +if __name__ == "__main__": + create_mask( + '/Users/nube/cpg_tools/new_masks/mesh_mask_nemo.Ec3.2_O1L75.nc', + '/Users/nube/cpg_tools/new_masks/new_maskglo.Ec3.2_O1L75.nc', + ) \ No newline at end of file