1212import geopandas as gpd
1313import glob
1414from scipy import spatial
15+ from scipy .interpolate import RegularGridInterpolator
1516
1617from utils import distance , get_coords_from_polygon
1718
@@ -394,6 +395,122 @@ def create_fisheries_gfwv2_release_map(fisheries_filepath, mask_land_filepath):
394395 return agg_data_fisheries_info , model_agg_data_fisheries_info
395396
396397
398+ def create_global_concentrations_kaandorp_release_map (mask_land_filepath , mask_coast_filepath , coords_filepath ,
399+ kaandorp_filepath , distance_thresshold = 50. ):
400+ """
401+ Description
402+ ----------
403+
404+ A function to create a particle release map based on the global concentrations data produced by [@Kaandorp2023].
405+ We match this data to the model coastal and ocean cells for a better coverage release.
406+ We use only the 2020 data for all plastic class sizes, and for the ocean cells we only use the surface 0-5m depth.
407+ """
408+
409+ # Load in the data and select year 2020, all plastic sizes, and for ocean concentrations take the surface layer
410+ ds = xr .open_dataset (kaandorp_filepath )
411+ beach = ds ['concentration_beach_mass_log10' ].sel ({'size_nominal' :'all' , 'time' :2020 })
412+ ocean = ds ['concentration_mass_log10' ].sel ({'size_nominal' :'all' , 'time' :2020 , 'depth' :'0 - <5' })
413+
414+ # Load in coast mask and model coordinates
415+ data_mask_coast = xr .open_dataset (mask_coast_filepath )
416+ coords = xr .open_dataset (coords_filepath , decode_cf = False )
417+
418+ lats_coast = data_mask_coast ['lat' ].data [np .where (data_mask_coast ['mask_coast' ])]
419+ lons_coast = data_mask_coast ['lon' ].data [np .where (data_mask_coast ['mask_coast' ])]
420+
421+ # Tackle the beach concentrations first:
422+ # Create a list of lons, lats, concentration values
423+ lon_beach = beach .lon_beach .values
424+ lat_beach = beach .lat_beach .values
425+ conc_beach = np .power (10 ,beach .values ) # beach.values are in log10 form
426+
427+ # Load Natural Earth dataset for attaching country information to beach source
428+ shpfilename = shpreader .natural_earth (resolution = '50m' ,
429+ category = 'cultural' ,
430+ name = 'admin_0_countries' )
431+ reader = shpreader .Reader (shpfilename )
432+ countries = reader .records ()
433+
434+ countries_list = []
435+ for country in countries :
436+ continent = country .attributes ['CONTINENT' ]
437+ region_un = country .attributes ['REGION_UN' ]
438+ subregion = country .attributes ['SUBREGION' ]
439+ country_name = country .attributes ['NAME_LONG' ]
440+
441+ country_coords = get_coords_from_polygon (country .geometry )
442+ country_lons , country_lats = country_coords [:, 0 ], country_coords [:, 1 ]
443+
444+ country_df = pd .DataFrame ({'Continent' : np .repeat (continent , len (country_lons )),
445+ 'Region' : np .repeat (region_un , len (country_lons )),
446+ 'Subregion' : np .repeat (subregion , len (country_lons )),
447+ 'Country' : np .repeat (country_name , len (country_lons )),
448+ 'Longitude' : country_lons ,
449+ 'Latitude' : country_lats })
450+ countries_list .append (country_df )
451+ coastal_df = pd .concat (countries_list )
452+
453+ # Create coastal concentrations dataset
454+ coast_concentration_list = []
455+ distance_threshhold = 50.
456+
457+ for i , (lon , lat ) in enumerate (zip (lons_coast ,lats_coast )):
458+ # Find the closest beach concentration
459+ distances = distance (np .repeat (lon , len (lon_beach )), np .repeat (lat , len (lat_beach )), lon_beach , lat_beach )
460+ closest_beach_id = np .argmin (distances )
461+ if distances [closest_beach_id ] > distance_threshhold : # skip coastal grid cells not within a threshhold from a littered beach
462+ continue
463+ else :
464+ # Find the closest country point to the coastal cell to assign country information
465+ distances_country = distance (np .repeat (lon , len (coastal_df ['Longitude' ])),
466+ np .repeat (lat , len (coastal_df ['Latitude' ])),
467+ coastal_df ['Longitude' ],
468+ coastal_df ['Latitude' ])
469+ closest_country_id = np .argmin (distances_country )
470+
471+ coast_concentration_list .append ({'Continent' : coastal_df ['Continent' ].iloc [closest_country_id ],
472+ 'Region' : coastal_df ['Region' ].iloc [closest_country_id ],
473+ 'Subregion' : coastal_df ['Subregion' ].iloc [closest_country_id ],
474+ 'Country' : coastal_df ['Country' ].iloc [closest_country_id ],
475+ 'Longitude' : lon ,
476+ 'Latitude' : lat ,
477+ 'Concentration' : conc_beach [closest_beach_id ],
478+ 'ConcentrationType' : 'Beach' })
479+
480+ coast_concentration_df = pd .DataFrame .from_records (coast_concentration_list )
481+
482+ # Now tackle the surface ocean concentrations:
483+ conc_ocean = np .power (10 ,ocean .values ) # Values are in log10 space
484+
485+ data_mask_land = xr .open_dataset (mask_land_filepath )
486+ lats_ocean = data_mask_land ['lat' ].data [np .where (~ data_mask_land ['mask_land' ])]
487+ lons_ocean = data_mask_land ['lon' ].data [np .where (~ data_mask_land ['mask_land' ])]
488+
489+ # Function to interpolate the ocean concentrations
490+ f_interp_conc_ocean = RegularGridInterpolator ((ocean .lon , ocean .lat ), conc_ocean .T , method = 'nearest' , bounds_error = False , fill_value = None )
491+
492+ # Interpolate the ocean concentrations to the model grid cells
493+ interp_conc_ocean = f_interp_conc_ocean ((lons_ocean , lats_ocean ))
494+
495+ # Create ocean concentration dataset where values are non-NaN
496+ non_nan_id = ~ np .isnan (interp_conc_ocean )
497+ ocean_concentration_list = []
498+ for i in np .where (non_nan_id )[0 ]:
499+ ocean_concentration_list .append ({'Continent' : 'N/A' ,
500+ 'Region' : 'N/A' ,
501+ 'Subregion' : 'N/A' ,
502+ 'Country' : 'N/A' ,
503+ 'Longitude' : lons_ocean [i ],
504+ 'Latitude' : lats_ocean [i ],
505+ 'Concentration' : interp_conc_ocean [i ],
506+ 'ConcentrationType' : 'Ocean' })
507+ ocean_concentration_df = pd .DataFrame .from_records (ocean_concentration_list )
508+
509+ # Combine the two beach and ocean datasets
510+ concentration_df = pd .concat ([ocean_concentration_df , coast_concentration_df ])
511+
512+ return concentration_df
513+
397514output_data = '/Users/denes001/Research/Projects/PlasticParcels/PlasticParcels/data/release/generated_files/'
398515mask_land_filepath = '/Users/denes001/Research/Projects/PlasticParcels/PlasticParcels/data/output_data/masks/mask_land_NEMO0083.nc'
399516mask_coast_filepath = '/Users/denes001/Research/Projects/PlasticParcels/PlasticParcels/data/output_data/masks/mask_coast_NEMO0083.nc'
@@ -420,7 +537,7 @@ def create_fisheries_gfwv2_release_map(fisheries_filepath, mask_land_filepath):
420537if not os .path .isfile (output_name ):
421538 river_dataset = create_rivers_meijer_release_map (mask_coast_filepath = mask_coast_filepath ,
422539 river_filepath = river_filepath )
423- river_dataset .to_csv (output_data + 'river_emissions_NEMO0083.csv' )
540+ river_dataset .to_csv (output_name )
424541 print ("River mismanaged plastic waste file created:" , output_name )
425542else :
426543 print ("River mismanaged plastic waste file already exists:" , output_name )
@@ -438,3 +555,14 @@ def create_fisheries_gfwv2_release_map(fisheries_filepath, mask_land_filepath):
438555 print ("Fishing related plastic waste file created:" , output_name , 'and' , output_on_model_name )
439556else :
440557 print ("Fishing related plastic waste file already exists:" , output_name )
558+
559+ # Create current concentrations release data
560+ kaandorp_filepath = '/Users/denes001/Research/Projects/PlasticParcels/PlasticParcels/data/release/Kaandorp2023/AtlantECO-MAPS_Global_plastic_mass_budget_Kaandorp_etal_2023.nc'
561+ output_name = output_data + 'global_concentrations_NEMO0083.csv'
562+
563+ if not os .path .isfile (output_name ):
564+ concentration_dataset = create_global_concentrations_kaandorp_release_map (mask_land_filepath , mask_coast_filepath , coords_filepath , kaandorp_filepath , distance_thresshold = 50. )
565+ concentration_dataset .to_csv (output_name )
566+ print ("Concentration map file created:" , output_name )
567+ else :
568+ print ("Concentration map file already exists:" , output_name )
0 commit comments