# To access dataset using Earthaccess
import earthaccess
# To access dataset without Earthaccess
import os
import s3fs
import requests
import glob
# To open dataset
import xarray as xr
# For plotting
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
From the PO.DAAC Cookbook, to access the GitHub version of the notebook, follow this link.
Ocean Satellite and In-situ Comparison in the Cloud
Summary
Here, we compare salinity from the SMAP satellite and Saildrone in-situ measurements. Both datasets are located within the cloud.
Follow along with the Data in Action story:
By the end of this notebook, you will have recreated a similar plot to the one featured in this Data-in-Action story:
https://podaac.jpl.nasa.gov/DataAction-2021-10-05-Monitoring-Changes-in-the-Arctic-Using-Saildrone-SMAP-Satellite-and-Ocean-Models-Data
Shortnames of datasets used here:
SMAP_RSS_L3_SSS_SMI_8DAY-RUNNINGMEAN_V5: https://podaac.jpl.nasa.gov/dataset/SMAP_RSS_L3_SSS_SMI_8DAY-RUNNINGMEAN_V5
SAILDRONE_ARCTIC: https://podaac.jpl.nasa.gov/dataset/SAILDRONE_ARCTIC
Requirements
1. Compute environment
This tutorial can only be run in the following environments: - AWS instance running in us-west-2: NASA Earthdata Cloud data in S3 can be directly accessed via temporary credentials; this access is limited to requests made within the US West (Oregon) (code: us-west-2
) AWS region.
2. Earthdata Login
An Earthdata Login account is required to access data, as well as discover restricted data, from the NASA Earthdata system. Thus, to access NASA data, you need Earthdata Login. Please visit https://urs.earthdata.nasa.gov to register and manage your Earthdata Login account. This account is free to create and only takes a moment to set up.
3. netrc File
You will need a .netrc
file containing your NASA Earthdata Login credentials in order to execute the notebooks. A .netrc
file can be created manually within text editor and saved to your home directory. For additional information see: Authentication for NASA Earthdata tutorial.
Import Libraries
SMAP dataset
Search for and open this dataset as an example of using Earthaccess
= earthaccess.login(strategy="netrc") auth
You're now authenticated with NASA Earthdata Login
Using token with expiration date: 06/18/2023
Using .netrc file for EDL
="SMAP_RSS_L3_SSS_SMI_8DAY-RUNNINGMEAN_V5"
short_name
= earthaccess.search_data(
results =short_name,
short_name=True,
cloud_hosted=("2019-05-01T00:00:00", "2019-10-01T00:00:00"),
temporal=(-170,65,-160,71) # (west, south, east, north)
bounding_box )
Granules found: 122
= xr.open_mfdataset(earthaccess.open(results)) ds_sss
Opening 122 granules, approx size: 0.0 GB
= -170
plot_west = -160
plot_east = 60
plot_south = 75
plot_north
= [plot_south, plot_north], [plot_west+360, plot_east+360] # Turn the longitudes in (-180,0) to (0,360)
lat_bnds, lon_bnds = ds_sss.sel(lat=slice(*lat_bnds), lon=slice(*lon_bnds))
ds_sss_subset_0 'latitude'] = ds_sss_subset_0.lat
ds_sss_subset_0['longitude'] = ds_sss_subset_0.lon-360
ds_sss_subset_0[= ds_sss_subset_0.swap_dims({'lat':'latitude', 'lon':'longitude'})
ds_sss_subset ds_sss_subset
<xarray.Dataset> Dimensions: (longitude: 40, latitude: 60, time: 122, uncertainty_components: 9, iceflag_components: 3) Coordinates: lon (longitude) float32 190.1 190.4 ... 199.6 199.9 lat (latitude) float32 60.12 60.38 60.62 ... 74.62 74.88 * time (time) datetime64[ns] 2019-04-27T12:00:00 ... 201... * latitude (latitude) float32 60.12 60.38 60.62 ... 74.62 74.88 * longitude (longitude) float32 -169.9 -169.6 ... -160.4 -160.1 Dimensions without coordinates: uncertainty_components, iceflag_components Data variables: (12/19) nobs (time, latitude, longitude) float64 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> nobs_RF (time, latitude, longitude) float64 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> nobs_40km (time, latitude, longitude) float64 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> sss_smap (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> sss_smap_RF (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> sss_smap_unc (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> ... ... fland (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> gice_est (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> surtep (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> winspd (time, latitude, longitude) float32 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> sea_ice_zones (time, latitude, longitude) int8 dask.array<chunksize=(1, 60, 40), meta=np.ndarray> anc_sea_ice_flag (time, latitude, longitude, iceflag_components) int8 dask.array<chunksize=(1, 60, 40, 3), meta=np.ndarray> Attributes: (12/65) Conventions: CF-1.7, ACDD-1.3 title: SMAP ocean surfac... version: V5.0 Validated Re... summary: The dataset conta... acknowledgement: Funded under Subc... processing_level: L3 ... ... Source_of_SMAP_SSS_retrievals: T. Meissner, F. W... Source_of_ancillary_SST: Canada Meteorolog... Source_of_ancillary_CCMP_wind_speed: Mears, C. et al.,... Source_of_ancillary_AMSR2_sea_ice_flag_and_correction: Meissner, T. and ... Source_of_ancillary_land_mask: 1 km land/water m... Source_of_ancillary_reference_SSS_from_HYCOM: Hybrid Coordinate...
= ds_sss_subset.sss_smap.mean(dim = 'time', skipna = True)
subset_mean_values subset_mean_values
<xarray.DataArray 'sss_smap' (latitude: 60, longitude: 40)> dask.array<mean_agg-aggregate, shape=(60, 40), dtype=float32, chunksize=(60, 40), chunktype=numpy.ndarray> Coordinates: lon (longitude) float32 190.1 190.4 190.6 190.9 ... 199.4 199.6 199.9 lat (latitude) float32 60.12 60.38 60.62 60.88 ... 74.38 74.62 74.88 * latitude (latitude) float32 60.12 60.38 60.62 60.88 ... 74.38 74.62 74.88 * longitude (longitude) float32 -169.9 -169.6 -169.4 ... -160.6 -160.4 -160.1
Saildrone dataset
Accessing this dataset as an example of using s3fs
= 'https://archive.podaac.earthdata.nasa.gov/s3credentials' s3_cred_endpoint
def get_temp_creds():
= s3_cred_endpoint
temp_creds_url return requests.get(temp_creds_url).json()
= get_temp_creds()
temp_creds_req #temp_creds_req # !!! BEWARE, removing the # on this line will print your temporary S3 credentials.
= s3fs.S3FileSystem(anon=False,
fs_s3 =temp_creds_req['accessKeyId'],
key=temp_creds_req['secretAccessKey'],
secret=temp_creds_req['sessionToken'],
token={'region_name':'us-west-2'}) client_kwargs
= os.path.join('podaac-ops-cumulus-protected/','SAILDRONE_ARCTIC','saildrone-*-1_minutes-*.nc')
bucket = fs_s3.glob(bucket)
sd_files = [fs_s3.open(file) for file in sorted(sd_files)]
saildrone_fileslen(saildrone_files)
2
= xr.open_dataset(saildrone_files[0])
sd6 = xr.open_dataset(saildrone_files[1])
sd7 sd7
<xarray.Dataset> Dimensions: (trajectory: 1, obs: 215731) Coordinates: latitude (trajectory, obs) float64 ... longitude (trajectory, obs) float64 ... time (trajectory, obs) datetime64[ns] ... * trajectory (trajectory) float32 1.037e+03 Dimensions without coordinates: obs Data variables: (12/79) SOG (trajectory, obs) float64 ... SOG_FILTERED_MEAN (trajectory, obs) float64 ... SOG_FILTERED_STDDEV (trajectory, obs) float64 ... SOG_FILTERED_MAX (trajectory, obs) float64 ... SOG_FILTERED_MIN (trajectory, obs) float64 ... COG (trajectory, obs) float64 ... ... ... TEMP_O2_RBR_MEAN (trajectory, obs) float64 ... TEMP_O2_RBR_STDDEV (trajectory, obs) float64 ... CHLOR_WETLABS_MEAN (trajectory, obs) float64 ... CHLOR_WETLABS_STDDEV (trajectory, obs) float64 ... CHLOR_RBR_MEAN (trajectory, obs) float64 ... CHLOR_RBR_STDDEV (trajectory, obs) float64 ... Attributes: (12/45) title: Arctic NASA MISST 2019 Mission summary: Saildrone surface observational data for the N... ncei_template_version: NCEI_NetCDF_Trajectory_Template_v2.0 Conventions: CF-1.6, ACDD-1.3 netcdf_version: 4.6.3 featureType: trajectory ... ... keywords_vocabulary: NASA/GCMD publisher_name: Saildrone publisher_url: www.saildrone.com publisher_email: support@saildrone.com acknowledgment: Saildrone. 2019. Saildrone Arctic field campai... processing_level: Level 2
Plot salinity side-by-side from SMAP and from Saildrone vehicle 1036
= plt.figure(figsize= (16,10))
fig
= 1
rows = 2
columns = fig.add_subplot(rows, columns, 1, projection=ccrs.PlateCarree())
ax
ax.add_feature(cartopy.feature.RIVERS)
ax.coastlines()
ax.set_extent([plot_west, plot_east, plot_south, plot_north])= subset_mean_values.plot.pcolormesh(add_colorbar = False)
s = ax.gridlines(color='gray',alpha=0.6,draw_labels=True)
gl 'SMAP, May-Oct 2019')
plt.title(= False
gl.top_labels = True
gl.left_labels = False
gl.right_labels = LONGITUDE_FORMATTER
gl.xformatter = LATITUDE_FORMATTER
gl.yformatter = plt.colorbar(s, ax = ax)
cb 'Salinity (PSU)')
cb.set_label(
= fig.add_subplot(rows, columns, 2, projection=ccrs.PlateCarree())
ax
ax.add_feature(cartopy.feature.RIVERS)
ax.coastlines()
ax.set_extent([plot_west, plot_east, plot_south, plot_north])= plt.scatter(sd6.longitude, sd6.latitude, s = 0.5, c = sd6.SAL_SBE37_MEAN, vmin = 25, vmax = 35, cmap = 'rainbow', transform = ccrs.PlateCarree())
s6 = ax.gridlines(color='gray',alpha=0.6,draw_labels=True)
gl 'Saildrone vehicle 1036, May-Oct 2019')
plt.title(= False
gl.top_labels = True
gl.left_labels = False
gl.right_labels = LONGITUDE_FORMATTER
gl.xformatter = LATITUDE_FORMATTER
gl.yformatter = plt.colorbar(s, ax = ax)
cb 'Salinity (PSU)')
cb.set_label('salinity_comparison_sd1036.png') plt.savefig(
Plot salinity side-by-side from SMAP and from Saildrone vehicle 1037
= plt.figure(figsize= (16,10))
fig
= 1
rows = 2
columns = fig.add_subplot(rows, columns, 1, projection=ccrs.PlateCarree())
ax
ax.add_feature(cartopy.feature.RIVERS)
ax.coastlines()
ax.set_extent([plot_west, plot_east, plot_south, plot_north])= subset_mean_values.plot.pcolormesh(add_colorbar=False)
s = ax.gridlines(color='gray',alpha=0.6,draw_labels=True)
gl 'SMAP, May-Oct 2019')
plt.title(= False
gl.top_labels = True
gl.left_labels = False
gl.right_labels = LONGITUDE_FORMATTER
gl.xformatter = LATITUDE_FORMATTER
gl.yformatter = plt.colorbar(s, ax = ax)
cb 'Salinity (PSU)')
cb.set_label(
= fig.add_subplot(rows, columns, 2, projection=ccrs.PlateCarree())
ax
ax.add_feature(cartopy.feature.RIVERS)
ax.coastlines()
ax.set_extent([plot_west, plot_east, plot_south, plot_north])= plt.scatter(sd7.longitude, sd7.latitude, s = 0.5, c = sd7.SAL_SBE37_MEAN, vmin = 25, vmax = 35, cmap = 'rainbow', transform = ccrs.PlateCarree())
s6 = ax.gridlines(color='gray',alpha=0.6,draw_labels=True)
gl 'Saildrone vehicle 1037, May-Oct 2019')
plt.title(= False
gl.top_labels = True
gl.left_labels = False
gl.right_labels = LONGITUDE_FORMATTER
gl.xformatter = LATITUDE_FORMATTER
gl.yformatter = plt.colorbar(s, ax = ax)
cb 'Salinity (PSU)')
cb.set_label('salinity_comparison_sd1037.png') plt.savefig(