-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdrifter_functions_2021.py
303 lines (241 loc) · 13.2 KB
/
drifter_functions_2021.py
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
302
303
# -*- coding: utf-8 -*-
"""
Created on Thu Jun 17 12:29:04 2021
@author: markl
A collection of functions to extract observational drifter data from
ERDDAP, plot the drifter on googlemaps and basemap. Originally made for BoF
Manuscript but generalizable.
"""
import pandas as pd
import sys
import numpy as np
from datetime import datetime as dt
import pytz
import urllib3
import pygmaps
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
#To make inputs empty
#BoF_box = []
#time_range = []
#depth_range = []
#Your geographic, temporal, and depth ranges here
BoF_box = [-64.72, -67.35, 45.33, 44.23] # maxlon, minlon,maxlat,minlat, for BoF range
time_range = [dt(2010, 11, 3, 0, 0, 0, 0, pytz.UTC),
dt(2020, 12, 29, 0, 0, 0, 0, pytz.UTC)] # start time and end time
depth_range = [-40, 40] #min depth and max depth (meters)
def getobs_drift_by_info(gbox,input_time,depths):
"""
Function written by Mark (modified from Huaxin's code)
and used by plot_drift_gmap and plot_drift_basemap,(compatible with other functions)
parameters: gbox (geographic box w/min and max lat/lon), input_time, and depths(min and max)
return: ids, times, latitude,longitude, depths
input_time can must contain two values: start_time & end_time
example: input_time=[dt(2012,1,1,0,0,0,0,pytz.UTC),dt(2012,2,1,0,0,0,0,pytz.UTC)]
Purpose: by user inputs (spatial, temporal, depth ranges), generate a URL
to find all drifter observations within specified ranges. Then return the
relevant data from ERDDAP site from those obeservations
"""
#Sequence of conditions to define ERDDAP URL based on all possible queries
if gbox == [] and input_time == [] and depths == []:
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'
elif gbox == [] and input_time == []:
depth_min = depths[0]
depth_max = depths[1]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&time%3E='\
+'&depth%3E='+str(depth_min) +'&depth%3C='+str(depth_max)
elif gbox == [] and depths == []:
time_min=input_time[0].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z') # change time format
time_max=input_time[1].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z')
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&time%3E='+str(time_min)\
+'&time%3C='+str(time_max)
elif input_time == [] and depths == []:
lon_max=gbox[0];lon_min=gbox[1];lat_max=gbox[2];lat_min=gbox[3]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&latitude%3E='+str(lat_min)\
+'&latitude%3C='+str(lat_max)+'&longitude%3E='+str(lon_min)\
+'&longitude%3C='+str(lon_max)
elif gbox == []:
time_min=input_time[0].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z') # change time format
time_max=input_time[1].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z')
depth_min = depths[0]
depth_max = depths[1]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&time%3E='+str(time_min)\
+'&time%3C='+str(time_max)+'&depth%3E='+str(depth_min)\
+'&depth%3C='+str(depth_max)
elif input_time == []:
lon_max=gbox[0];lon_min=gbox[1];lat_max=gbox[2];lat_min=gbox[3]
depth_min = depths[0]
depth_max = depths[1]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv0?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&latitude%3E='+str(lat_min)\
+'&latitude%3C='+str(lat_max)+'&longitude%3E='+str(lon_min)\
+'&longitude%3C='+str(lon_max)+'&depth%3E='+str(depth_min)\
+'&depth%3C='+str(depth_max)
elif depths == []:
time_min=input_time[0].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z') # change time format
time_max=input_time[1].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z')
lon_max=gbox[0];lon_min=gbox[1];lat_max=gbox[2];lat_min=gbox[3]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&time%3E='+str(time_min)\
+'&time%3C='+str(time_max)+'&latitude%3E='+str(lat_min)\
+'&latitude%3C='+str(lat_max)+'&longitude%3E='+str(lon_min)\
+'&longitude%3C='+str(lon_max)
else:
time_min=input_time[0].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z') # change time format
time_max=input_time[1].strftime('%Y-%m-%d'+'T'+'%H:%M:%S'+'Z')
lon_max=gbox[0];lon_min=gbox[1];lat_max=gbox[2];lat_min=gbox[3]
depth_min = depths[0]
depth_max = depths[1]
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&time%3E='+str(time_min)\
+'&time%3C='+str(time_max)+'&latitude%3E='+str(lat_min)\
+'&latitude%3C='+str(lat_max)+'&longitude%3E='+str(lon_min)\
+'&longitude%3C='+str(lon_max)+'&depth%3E='+str(depth_min)\
+'&depth%3C='+str(depth_max)
df = pd.read_csv(url,skiprows=[1]) #make drifter info table, USE THIS NORMALLY
#df = pd.read_csv(r'C:\Users\markl\.spyder-py3\example_data.csv', skiprows=[1]) example for testing
df.sort_values(by='time', ascending = True, inplace = True) #sort by date in ascending order
#define outputs
ids = df.id.values
times = df.time.values
latitudes = df.latitude.values
longitudes = df.longitude.values
depths = df.depth.values
#print(url) for testing
return ids, times, latitudes, longitudes, depths
def getobs_drift_by_ids(identity):
"""
Function written by Mark (modified from Huaxin's code)
and used by plot_drift_gmap and plot_drift_basemap (compatible with other functions)
parameters: identity (drifter id#)
return: ids, times, latitudes, longitudes, depths
Purpose: based on user specified ID, output ALL drifter data from that deployment
Not limited to geographic or temporal range
"""
#Generate the URL
url ='https://comet.nefsc.noaa.gov/erddap/tabledap/drifters.csv?'\
+'id%2Ctime%2Clatitude%2Clongitude%2Cdepth'+'&id%3E=%22'\
+str(identity)+'%22&id%3C=%22'+str(identity)+'%22'
df = pd.read_csv(url,skiprows=[1]) #drifter info table, USE THIS NORMALLY
df.sort_values(by='time', ascending = True, inplace = True) #sort by date in ascending order
#define outputs
ids = df.id.values
times = df.time.values
latitudes = df.latitude.values
longitudes = df.longitude.values
depths = df.depth.values
return ids, times, latitudes, longitudes,depths
def plot_drift_release_gmap():
"""
Function written by Mark (modified from Huaxin's code)
parameters: none
output: saves a google map .html to your current file path, interactive online
Purpose: Generate a google map of drifter RELEASES given that they pass through
a certain geographic region, time, and depth range
"""
ids, times, lats, lons, depths = getobs_drift_by_info(BoF_box,time_range,depth_range) #define inputs
id = list(set(ids))
#print(np.mean(lats)) for testing
#print(np.mean(lons))
print("There are " +str(len(id))+ " drifters that passed through the specified area and depth on their deployment.")
mymap = pygmaps.pygmaps(np.mean(lats), np.mean(lons), 12) #initialize gmap
for k in range(len(id)): #loop through the list of IDs generated by getobs_drift_by_info
ids1, times1, lats1, lons1, depths1 = getobs_drift_by_ids(id[k]) #define new inputs by ID
first_ping_time = np.min(times1) #earliest and latest pings
last_ping_time = np.max(times1)
first_ping_index = np.argmin(times1) #index of those pings
last_ping_index = np.argmax(times1)
first_ping_location = [lats1[first_ping_index],lons1[first_ping_index]] #position of those pings
last_ping_location = [lats1[last_ping_index],lons1[last_ping_index]]
#helpful info for the user
print("Drifter #" +str(id[k]) + " was released at " + str(first_ping_time)\
+ "(index " +str(first_ping_index)+ ") location:(" \
+ str(first_ping_location[0])+','+str(first_ping_location[1])\
+ ") and stopped transmitting at " + str(last_ping_time)\
+"(index " + str(last_ping_index)+ ") location:("\
+ str(last_ping_location[0])+','+str(last_ping_location[1]) + ")")
for j in range(len(ids1)): #add point for the first ping of every deployment
mymap.addpoint(lats1[first_ping_index], lons1[first_ping_index], 'black')
#mymap.draw('./' + dt.datetime.now().strftime('%Y-%m-%d %H:%M') + '.html')
mymap.draw('driftreleasemapALLTIME.html') #change this filename based on user
def plot_drift_tracks_gmap():
"""
UPDATE THIS
Function written by Mark (modified from Huaxin's code)
parameters: none
output: saves a google map .html to your current file path, interactive online
Purpose: Generate a google map of drifter tracks given that they pass through
a certain geographic region, time, and depth range
"""
ids, times, lats, lons, depths = getobs_drift_by_info(BoF_box,time_range,depth_range) #define inputs
id = list(set(ids))
#print(np.mean(lats)) for testing
#print(np.mean(lons))
print("There are " +str(len(id))+ " drifters that passed through the specified area and depth on their deployment.")
mymap = pygmaps.pygmaps(np.mean(lats), np.mean(lons), 12) #initialize gmap
for k in range(len(id)): #loop through the list of IDs generated by getobs_drift_by_info
#print(id[k]) for testing
path = []
ids1, times1, lats1, lons1, depths1 = getobs_drift_by_ids(id[k]) #define new inputs by ID
for j in range(len(ids1)): #add point for each satellite ping
#mymap.addpoint(lats1[0], lons1[0], 'black') this is for other function (release)
mymap.addradpoint(lats1[j], lons1[j],295,'black')
path.append((lats1[j], lons1[j]))
mymap.addpath(path)
#mymap.addradpoint(lats1[0], lons1[0], 295, "red") beginning
#mymap.addradpoint(lats1[-1], lons1[-1], 295, "blue") end
#
#mymap.draw('./' + dt.datetime.now().strftime('%Y-%m-%d %H:%M') + '.html')
mymap.draw('drifttrackmap.html') #change this filename based on user
def plot_drift_release_basemap():
"""
UPDATE THIS -- to be fixed
Function written by Mark
parameters: none
output: basemap plot
Purpose: Generate a basemap of drifter RELEASES given that they pass through
a certain geographic region, time, and depth range
"""
ids, times, lats, lons, depths = getobs_drift_by_info(BoF_box,time_range,depth_range)
id = list(set(ids))
res = 'h'
mymap = Basemap(projection='lcc', resolution=res, width = 2E5, height = 2E5, lat_0 =np.mean(lats), lon_0=np.mean(lons))
mymap.fillcontinents(color = 'grey')
mymap.drawcoastlines()
mymap.drawmapboundary()
for k in range(len(id)):
#need to use the getobs_drift_by_id here to eliminate all other values.
#FIX WHEN ERDDAP IS UP
ids1, times1, lats1, lons1, depths1 = getobs_drift_by_ids(id[k])
first_ping_time = np.min(times1) #earliest and latest pings
last_ping_time = np.max(times1)
first_ping_index = np.argmin(times1) #index of those pings
last_ping_index = np.argmax(times1)
first_ping_location = [lats1[first_ping_index],lons1[first_ping_index]] #position of those pings
last_ping_location = [lats1[last_ping_index],lons1[last_ping_index]]
#helpful info for the user
print("Drifter #" +str(id[k]) + " was released at " + str(first_ping_time)\
+ "(index " +str(first_ping_index)+ ") location:(" \
+ str(first_ping_location[0])+','+str(first_ping_location[1])\
+ ") and stopped transmitting at " + str(last_ping_time)\
+"(index " + str(last_ping_index)+ ") location:("\
+ str(last_ping_location[0])+','+str(last_ping_location[1]) + ")")
for j in range(len(ids1)): #add point for the first ping of every deployment
x,y = mymap(lons1[first_ping_index], lats1[first_ping_index])
mymap.plot(x,y,'bo', markersize=3)
#mymap.draw('./' + dt.datetime.now().strftime('%Y-%m-%d %H:%M') + '.html')
plt.savefig('drifterreleasebasemap.png')
plt.show()
#MAKE A PLOT DRIFT TRACK BASEMAP PLOT_DRIFT_TRACK_BASEMAP
#def plot_drift_tracks_basemap():
#
if __name__ == '__main__':
# obs_id = 196440671 #drifter ID from ERDDAP
# ids, times, obs_lat, obs_lon, depths = getobs_drift_by_ids(obs_id)
# print(times)
plot_drift_release_gmap()