-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path04-NCDatasets-tutorial.jl
301 lines (262 loc) · 10.1 KB
/
04-NCDatasets-tutorial.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .jl
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.14.4
# kernelspec:
# display_name: Julia 1.8.0
# language: julia
# name: julia-1.8
# ---
# # Tutorials
#
# ## Data from Copernicus Marine
#
# This examples shows how to download sea surface temperature from the
# [Mediterranean Sea High Resolution and Ultra High Resolution Sea Surface Temperature Analysis ](https://doi.org/10.48670/moi-00172) provided by
# [Copernicus Marine Service](https://marine.copernicus.eu/).
# Username and password are obtained after [registration](https://resources.marine.copernicus.eu/registration-form).
# The username and password can be added to the URL. For example
# `https://example.org/path` should become `https://username:password@example.org/path`:
using NCDatasets, PyPlot, Statistics, URIs
# Add here your username and password so that the following lines read:
# ```julia
# username = "me";
# password = "paßwörth";
# ```
username = ENV["CMEMS_USERNAME"];
password = ENV["CMEMS_PASSWORD"];
# Add username and password to url
url = "https://nrt.cmems-du.eu/thredds/dodsC/SST_MED_SST_L4_NRT_OBSERVATIONS_010_004_a_V2"
url2 = string(URI(URI(url),userinfo = string(username,":",password)));
# Note this will output the URL with username/password. Add a semicolon to the
# next line to surpress the output
ds = NCDataset(url2)
# But we will use a local file to save bandwith
close(ds)
url2 = "SST_MED_SST_L4_NRT_OBSERVATIONS_010_004_a_V2_slice1.nc"
ds = NCDataset(url2)
# Load the data
ncvar = ds["analysed_sst"];
SST = ncvar[:,:,1]
lon = ds["lon"][:]
lat = ds["lat"][:]
time = ds["time"][1]
# Make a plot
clf()
pcolormesh(lon,lat,nomissing(SST,NaN)')
cbar = colorbar(orientation="horizontal")
cbar.set_label(ncvar.attrib["units"])
gca().set_aspect(1/cosd(mean(lat)))
title("$(ncvar.attrib["long_name"]) $time")
# Alternatively, one can also create the files `.netrc` and `.ncrc` in the your home directory with your credentials as explained for the NASA EarthData example which allows you to manage your passwords in a central configuration file and reduce the risk to accidentally share your credentials.
# ## Data from NASA EarthData
#
# This example shows show to download data via OPeNDAP from the [NASA EarthData](https://www.earthdata.nasa.gov/)
# which requires a username and password.
#
# You need to be registered at [https://urs.earthdata.nasa.gov/users/new](https://urs.earthdata.nasa.gov/users/new)
# to get your credentials.
#
# Simply adding username and password to the URL for NASA Earth Data OPeNDPAP services is unfortunately not sufficient as it uses a different authentication mechanism.
#
# Create a `.netrc` file with the following content in your home directory:
#
# ```
# machine urs.earthdata.nasa.gov
# login YOUR_USERNAME
# password YOUR_PASSWORD
# ```
#
# where `YOUR_USERNAME` and `YOUR_PASSWORD` is your Earth Data username and password.
#
# Create a `.ncrc` file with the following content in your home directory:
#
# ```
# HTTP.NETRC=/home/abarth/.netrc
# ```
#
# where `HTTP.NETRC` is the full path to your new `.netrc` file.
# Note: if you are using docker, your home directory is `/home/jovan/`.
# You can test whether your configuration files are correct independently of NCDatasets
# by using the tool `ncdump` (one line):
#
# ```bash
# ncdump -h "https://opendap.earthdata.nasa.gov/providers/POCLOUD/collections/GHRSST%20Level%204%20MUR%20Global%20Foundation%20Sea%20Surface%20Temperature%20Analysis%20(v4.1)/granules/20190101090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1"
# ```
#
# This should return the metadata of the OPeNDAP resource:
#
# ```
# netcdf \20190101090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04 {
# dimensions:
# lat = 17999 ;
# lon = 36000 ;
# time = 1 ;
# variables:
# short analysed_sst(time, lat, lon) ;
# [...]
# ```
#
#
# This is the typically error message which is returned when the credentials are not configured properly:
#
# ```
# syntax error, unexpected WORD_WORD, expecting SCAN_ATTR or SCAN_DATASET or SCAN_ERROR
# context: HTTP^ Basic: Access denied.
# ```
#
# When there is an error on the server side (500 internal server error), you might get the following error:
#
# ```
# syntax error, unexpected $end, expecting SCAN_ATTR or SCAN_DATASET or SCAN_ERROR
# context: ^
# ncdump: https://opendap.earthdata.nasa.gov/providers/POCLOUD/collections/GHRSST%20Level%204%20MUR%20Global%20Foundation%20Sea%20Surface%20Temperature%20Analysis%20(v4.1)/granules/20190101090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1: NetCDF: Malformed or inaccessible DAP2 DDS or DAP4 DMR response
# ```
# Creating these configuration files is a bit fidely from jupyerlab.
# You can create these programmatically via these commands (where you need to put your username and password):
# +
write(expanduser("~/.netrc"),"""
machine urs.earthdata.nasa.gov
login USERNAME
password PASSWORD
""");
write(expanduser("~/.ncrc"),"""
HTTP.NETRC=$(expanduser("~/.netrc"))
""");
# -
# Check the content of the file with:
print(read(expanduser("~/.netrc"),String))
print(read(expanduser("~/.ncrc"),String))
# > **_Important:_** You must *restart* julia (e.g. Kernel > Restart Kernel if you use Jupyterlab)
#
# Here we use the [GHRSST Level 4 MUR Global Foundation Sea Surface Temperature Analysis (v4.1)](https://podaac.jpl.nasa.gov/dataset/MUR-JPL-L4-GLOB-v4.1) dataset.
# In the following example, we download the data via OPeNDAP for a chosen bounding box and given time instance.
# +
using NCDatasets, PyPlot, Dates, Statistics
url = "https://opendap.earthdata.nasa.gov/providers/POCLOUD/collections/GHRSST%20Level%204%20MUR%20Global%20Foundation%20Sea%20Surface%20Temperature%20Analysis%20(v4.1)/granules/20190101090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1"
ds = NCDataset(url)
# -
# Did you got an "Access denied" error? If yes, please check:
# * check your credentials at https://urs.earthdata.nasa.gov/
# * check the content of your files in `~/.ncrc` and `~/.netrc`
# * restart Julia
# * check the `ncdump -h` shell command above in a terminal
# * be aware that a `.ncrc` file in your current directory overrides the file in your home directory
# Bounding box
# range of longitude
lonr = (-6, 37.0)
# range of latitude
latr = (29, 45.875)
# Load a subset
# +
ds_subset = NCDatasets.@select(
ds["analysed_sst"],
$lonr[1] <= lon <= $lonr[2] && $latr[1] <= lat <= $latr[2])
ncvar = ds_subset["analysed_sst"]
SST = ncvar[:,:,1]
lon = ds_subset["lon"][:]
lat = ds_subset["lat"][:]
time = ds_subset["time"][1]
# -
# Make a plot
clf()
pcolormesh(lon,lat,nomissing(SST,NaN)');
gca().set_aspect(1/cosd(mean(lat)))
cbar = colorbar(orientation="horizontal")
cbar.set_label(ncvar.attrib["units"])
plt.title("$(ncvar.attrib["long_name"]) $time")
# ## Access data from S3 object storage
# NASA EarthData is also available from AWS S3 object storage at the AWS region us-west-2. This example assumes that you have access to an AWS instance in this region (available thought e.g. [Pangeo Cloud](https://pangeo.io/cloud.html) after registration thanks to funding from the NSF and the fine folks at [Pangeo](https://github.com/pangeo-data)).
#
# The S3 access token available from [https://archive.podaac.earthdata.nasa.gov/s3credentials](https://archive.podaac.earthdata.nasa.gov/s3credentials) are only valid for 1 hour. It is therefore preferable to get this token programmatically using your EarthData username and password. The function `earthdata_s3credentials` is a translation of ["Sample script to receive credentials"](https://web.archive.org/web/20220623090241/https://nasa.github.io/cumulus-distribution-api/#temporary-s3-credentials) to Julia:
#
# ```julia
# using AWS, Base64, JSON3, HTTP, NCDatasets, URIs
# using AWS: @service
# @service S3
#
# function earthdata_s3credentials(
# username, password;
# credentials_url = "https://archive.podaac.earthdata.nasa.gov/s3credentials")
#
# origin = URI(credentials_url).scheme
#
# resp = HTTP.get(credentials_url,redirect=false)
# authorize_url = Dict(resp.headers)["Location"]
#
# auth = base64encode(string(username,":",password))
#
# resp2 = HTTP.post(authorize_url,["Origin" => origin],
# "credentials=$auth",redirect=false)
# redirect_url=Dict(resp2.headers)["Location"]
#
# # cookie jar
# jar = Dict{String, Set{HTTP.Cookie}}()
#
# # raises a 500 error, as in the shell script, but we get a cookie!
# HTTP.get(redirect_url; cookies=true,
# cookiejar = jar, redirect = false,
# status_exception = false)
#
# resp4 = HTTP.get(credentials_url; cookies=true, cookiejar = jar, redirect = false)
#
# cred = JSON3.read(resp4.body)
# return cred
# end
#
# # add your credentials here (or get it programmatically from environment variables or a file)
# username = "..."
# password = "..."
#
# cred = earthdata_s3credentials(username,password)
# @info "Token expires: $(cred.expiration)"
#
#
# ENV["AWS_ACCESS_KEY_ID"] = cred.accessKeyId;
# ENV["AWS_SECRET_ACCESS_KEY"] = cred.secretAccessKey;
# ENV["AWS_SESSION_TOKEN"] = cred.sessionToken;
#
# c = AWS.global_aws_config();
#
# resp = S3.list_objects("podaac-ops-cumulus-protected",
# Dict("prefix" => "MODIS_TERRA_L3_SST_MID-IR_DAILY_4KM_NIGHTTIME_V2019.0/",
# "delimiter" => '/'))
#
# # download the first object
# data = S3.get_object("podaac-ops-cumulus-protected",resp["Contents"][1]["Key"]);
#
# # load the NetCDF dataset
# ds = NCDataset("temp-memory","r",memory = data)
# ```
#
# Output:
# ```
# CDataset: temp-memory
# Group: /
#
# Dimensions
# lat = 4320
# lon = 8640
# rgb = 3
# eightbitcolor = 256
#
# Variables
# sst4 (8640 × 4320)
# Datatype: Int16
# Dimensions: lon × lat
# Attributes:
# long_name = 4um Sea Surface Temperature
# [...]
# ```
#
# The example requires NCDatasets 0.12.5 which allows one to read a NetCDF dataset directly from a vector of bytes in memory.
#
# To debug, it is useful to run the `aws` shell command to list all keys in the buckets (it requires the `AWS_*` environment variables to be set):
#
# ```bash
# aws s3 ls s3://podaac-ops-cumulus-protected/MODIS_TERRA_L3_SST_THERMAL_DAILY_4KM_NIGHTTIME_V2019.0/
# ```