Skip to content

Commit b1c6f75

Browse files
committed
Merge branch 'main' into development
2 parents b01ac71 + 47521db commit b1c6f75

22 files changed

+816
-425
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ jobs:
4646
python -m pip install .
4747
conda list
4848
49+
- name: Install netrc for authentication
50+
shell: bash -l {0}
51+
run: |
52+
echo "${{ secrets.NETRC }}" > $HOME/.netrc
53+
chmod 600 $HOME/.netrc
54+
4955
- name: Run tests
5056
shell: bash -l {0}
5157
run: |

examples/cmr_debug_regions.ipynb

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
"- Creates a leaflet map for creating regions of interest\n",
1010
"- Queries CMR for granules and granule polygons\n",
1111
"- Plots granule polygons on map\n",
12-
"- Retrieves and plots granule tracks on map"
12+
"- Retrieves and plots granule tracks on map\n",
13+
"\n",
14+
"### Jupyter and SlideRule\n",
15+
"[Jupyter widgets](https://ipywidgets.readthedocs.io) are used to set parameters for the SlideRule API. \n",
16+
"\n",
17+
"Regions of interest for submitting to SlideRule are drawn on a [ipyleaflet](https://ipyleaflet.readthedocs.io) map. "
1318
]
1419
},
1520
{
@@ -49,7 +54,17 @@
4954
"cell_type": "markdown",
5055
"metadata": {},
5156
"source": [
52-
"#### Set ICESat-2 Product"
57+
"### Set ICESat-2 Product \n",
58+
"\n",
59+
"- [ATL03: Global Geolocated Photon Data](https://nsidc.org/data/atl03)\n",
60+
"- [ATL06: Land Ice Height](https://nsidc.org/data/atl06)\n",
61+
"- [ATL08: Land and Vegetation Height](https://nsidc.org/data/atl08)\n",
62+
"\n",
63+
"### Interactive Mapping with Leaflet\n",
64+
"\n",
65+
"Interactive maps within the SlideRule python API are built upon [ipyleaflet](https://ipyleaflet.readthedocs.io).\n",
66+
"\n",
67+
"There are 3 projections available within SlideRule for mapping ([Global](https://epsg.io/3857), [North](https://epsg.io/5936) and [South](https://epsg.io/3031)). "
5368
]
5469
},
5570
{
@@ -62,13 +77,16 @@
6277
"icesat2.init(\"slideruleearth.io\", loglevel=logging.WARNING)\n",
6378
"icesat2.get_version()\n",
6479
"\n",
65-
"# dropdown menu for ICESat-2 product\n",
66-
"product_select = widgets.Dropdown(\n",
67-
" options=['ATL03','ATL06','ATL08'],\n",
68-
" description='Product:',\n",
69-
" disabled=False\n",
70-
")\n",
71-
"display(product_select)"
80+
"# display widgets for setting ICESat-2 parameters\n",
81+
"# and the interactive map projection\n",
82+
"SRwidgets = ipysliderule.widgets()\n",
83+
"widgets.VBox([\n",
84+
" SRwidgets.product,\n",
85+
" SRwidgets.release,\n",
86+
" SRwidgets.start_date,\n",
87+
" SRwidgets.end_date,\n",
88+
" SRwidgets.projection\n",
89+
"])"
7290
]
7391
},
7492
{
@@ -84,8 +102,8 @@
84102
"metadata": {},
85103
"outputs": [],
86104
"source": [
87-
"# create ipyleaflet map in projection\n",
88-
"m = ipysliderule.leaflet('Global', center=(-25.3,131))\n",
105+
"# create ipyleaflet map in specified projection\n",
106+
"m = ipysliderule.leaflet(SRwidgets.projection.value)\n",
89107
"m.map"
90108
]
91109
},
@@ -102,16 +120,22 @@
102120
"metadata": {},
103121
"outputs": [],
104122
"source": [
123+
"%%time\n",
105124
"# for each region of interest\n",
106125
"granule_list = []\n",
107126
"granule_polygons = []\n",
108127
"for poly in m.regions:\n",
109128
" # polygon from map\n",
110-
" resources,polygons = icesat2.cmr(polygon=poly,\n",
111-
" short_name=product_select.value,\n",
112-
" return_polygons=True)\n",
113-
" granule_list.extend(resources)\n",
114-
" granule_polygons.extend(polygons)\n",
129+
" resources,metadata = icesat2.cmr(polygon=poly,\n",
130+
" short_name=SRwidgets.product.value,\n",
131+
" time_start=SRwidgets.time_start,\n",
132+
" time_end=SRwidgets.time_end,\n",
133+
" version=SRwidgets.release.value,\n",
134+
" return_metadata=True)\n",
135+
" # for each granule resource\n",
136+
" for i,resource in enumerate(resources):\n",
137+
" granule_list.append(resource)\n",
138+
" granule_polygons.append(metadata[i].geometry)\n",
115139
"# print list of granules\n",
116140
"num_granules = len(granule_list)\n",
117141
"logging.info('Number of Granules: {0:d}'.format(num_granules))\n",
@@ -156,16 +180,18 @@
156180
"granule_indices = list(granule_select.index)\n",
157181
"cmap = iter(cm.viridis(np.linspace(0,1,len(granule_indices))))\n",
158182
"for g in granule_indices:\n",
159-
" locations = [(p['lat'],p['lon']) for p in granule_polygons[g]]\n",
160183
" color = colors.to_hex(next(cmap))\n",
161-
" polygon = ipysliderule.ipyleaflet.Polygon(\n",
162-
" locations=locations,\n",
163-
" color=color,\n",
164-
" fill_color=color,\n",
165-
" opacity=0.8,\n",
166-
" weight=1, \n",
184+
" geojson = ipysliderule.ipyleaflet.GeoJSON(\n",
185+
" data=granule_polygons[g].__geo_interface__,\n",
186+
" style=dict(\n",
187+
" color=color,\n",
188+
" fill_color=color,\n",
189+
" opacity=0.8,\n",
190+
" weight=1,\n",
191+
" )\n",
167192
" )\n",
168-
" m.map.add_layer(polygon)"
193+
" m.map.add_layer(geojson)\n",
194+
" "
169195
]
170196
},
171197
{
@@ -270,6 +296,7 @@
270296
"metadata": {},
271297
"outputs": [],
272298
"source": [
299+
"%%time\n",
273300
"# granule resources for selected segments\n",
274301
"perf_start = time.perf_counter()\n",
275302
"gdf = sliderule.icesat2.__emptyframe()\n",
@@ -282,9 +309,6 @@
282309
" gdf = gdf.append(future.result())\n",
283310
"\n",
284311
"# Display Statistics\n",
285-
"perf_stop = time.perf_counter()\n",
286-
"perf_duration = perf_stop - perf_start\n",
287-
"print(\"Completed in {:.3f} seconds of wall-clock time\".format(perf_duration))\n",
288312
"print(\"Reference Ground Tracks: {}\".format(gdf[\"rgt\"].unique()))\n",
289313
"print(\"Cycles: {}\".format(gdf[\"cycle\"].unique()))\n",
290314
"print(\"Received {} segments\".format(gdf.shape[0]))"
@@ -343,7 +367,7 @@
343367
"name": "python",
344368
"nbconvert_exporter": "python",
345369
"pygments_lexer": "ipython3",
346-
"version": "3.8.13"
370+
"version": "3.10.6"
347371
}
348372
},
349373
"nbformat": 4,

examples/voila_demo.ipynb

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
"import logging\n",
7373
"import warnings\n",
7474
"import time\n",
75+
"import json\n",
76+
"from IPython.display import clear_output\n",
7577
"# atl03 plotting imports\n",
7678
"import numpy as np\n",
7779
"import matplotlib.lines\n",
@@ -123,15 +125,17 @@
123125
"# create global variables\n",
124126
"url_textbox = None\n",
125127
"atl06_rsps = None\n",
126-
"parms = None\n",
128+
"atl06_parms = None\n",
127129
"results = []\n",
128130
"SRwidgets = ipysliderule.widgets()\n",
129131
"points_dropdown = None\n",
130132
"update_button = widgets.Button(description=\"Update Map\")\n",
131133
"run_button = widgets.Button(description=\"Run SlideRule!\")\n",
132134
"run_output = widgets.Output()\n",
133135
"refresh_button = widgets.Button(description=\"Refresh Plot\")\n",
134-
"refresh_output = widgets.Output()"
136+
"refresh_output = widgets.Output()\n",
137+
"show_code06_button = widgets.Button(description=\"Show Code\")\n",
138+
"show_code06_output = widgets.Output()"
135139
]
136140
},
137141
{
@@ -228,7 +232,7 @@
228232
"\n",
229233
"# build and transmit requests to SlideRule\n",
230234
"def runSlideRule():\n",
231-
" global url_textbox, parms, results\n",
235+
" global url_textbox, atl06_parms, results\n",
232236
" \n",
233237
" # set the url for the sliderule service\n",
234238
" icesat2.init(url_textbox.value, loglevel=logging.ERROR, max_resources=1000)\n",
@@ -237,7 +241,7 @@
237241
" asset = SRwidgets.asset.value\n",
238242
"\n",
239243
" # build sliderule parameters using latest values from widget\n",
240-
" parms = {\n",
244+
" atl06_parms = {\n",
241245
" # surface type: 0-land, 1-ocean, 2-sea ice, 3-land ice, 4-inland water\n",
242246
" \"srt\": SRwidgets.surface_type.index,\n",
243247
" # length of ATL06-SR segment in meters\n",
@@ -267,10 +271,10 @@
267271
" # for each region of interest\n",
268272
" for poly in m.regions:\n",
269273
" # add polygon from map to sliderule parameters\n",
270-
" parms[\"poly\"] = poly \n",
274+
" atl06_parms[\"poly\"] = poly \n",
271275
" # make the request to the SlideRule (ATL06-SR) endpoint\n",
272276
" # and pass it the request parameters to request ATL06 Data\n",
273-
" gdf = gdf.append(icesat2.atl06p(parms, asset, callbacks={'eventrec': demo_logeventrec, 'exceptrec': demo_exceptrec}))\n",
277+
" gdf = gdf.append(icesat2.atl06p(atl06_parms, asset, callbacks={'eventrec': demo_logeventrec, 'exceptrec': demo_exceptrec}))\n",
274278
" \n",
275279
" return gdf\n",
276280
"\n",
@@ -287,25 +291,41 @@
287291
" max_plot_points = 10000\n",
288292
" if points_dropdown.value == \"100K\":\n",
289293
" max_plot_points = 100000\n",
290-
" elif points_dropdown.value == \"unlimited\":\n",
294+
" elif points_dropdown.value == \"all\":\n",
291295
" max_plot_points = 1000000000\n",
296+
" if max_plot_points > atl06_rsps.shape[0]:\n",
297+
" max_plot_points = atl06_rsps.shape[0]\n",
298+
" print(f'Plotting {max_plot_points} of {atl06_rsps.shape[0]} elevations. This may take 10-60+ seconds for larger point datasets.')\n",
292299
" m.GeoData(atl06_rsps, column_name=SRwidgets.variable.value, cmap=SRwidgets.colormap, max_plot_points=max_plot_points)\n",
293300
"\n",
294301
"# refresh action\n",
295302
"def on_refresh_clicked(b):\n",
296303
" global atl06_rsps\n",
297304
" with refresh_output:\n",
298-
" if atl06_rsps and atl06_rsps.shape[0] > 0:\n",
305+
" if atl06_rsps is not None and atl06_rsps.shape[0] > 0:\n",
299306
" max_plot_points = 10000\n",
300307
" if points_dropdown.value == \"100K\":\n",
301308
" max_plot_points = 100000\n",
302-
" elif points_dropdown.value == \"unlimited\":\n",
309+
" elif points_dropdown.value == \"all\":\n",
303310
" max_plot_points = 1000000000\n",
311+
" if max_plot_points > atl06_rsps.shape[0]:\n",
312+
" max_plot_points = atl06_rsps.shape[0]\n",
313+
" print(f'Plotting {max_plot_points} of {atl06_rsps.shape[0]} elevations. This may take 10-60+ seconds for larger point datasets.')\n",
304314
" m.GeoData(atl06_rsps, column_name=SRwidgets.variable.value, cmap=SRwidgets.colormap, max_plot_points=max_plot_points)\n",
305315
"\n",
316+
"# show code action\n",
317+
"def on_show_code06_clicked(b):\n",
318+
" global url_textbox, atl06_parms\n",
319+
" with show_code06_output:\n",
320+
" clear_output()\n",
321+
" print(f'icesat2.init(\"{url_textbox.value}\")')\n",
322+
" print('parms = ', json.dumps(atl06_parms, indent=4), sep='')\n",
323+
" print('gdf = icesat2.atl06p(parms, asset=\"nsidc-s3\")')\n",
324+
" \n",
306325
"# link buttons\n",
307326
"run_button.on_click(on_run_clicked)\n",
308-
"refresh_button.on_click(on_refresh_clicked)"
327+
"refresh_button.on_click(on_refresh_clicked)\n",
328+
"show_code06_button.on_click(on_show_code06_clicked)"
309329
]
310330
},
311331
{
@@ -339,7 +359,7 @@
339359
"\n",
340360
"# points to plot drop down\n",
341361
"points_dropdown = widgets.Dropdown(\n",
342-
" options = [\"10K\", \"100K\", \"unlimited\"],\n",
362+
" options = [\"10K\", \"100K\", \"all\"],\n",
343363
" value = \"10K\",\n",
344364
" description = \"Pts to Draw\",\n",
345365
" disabled = False,\n",
@@ -365,7 +385,8 @@
365385
"\n",
366386
"# display buttons\n",
367387
"display(run_button)\n",
368-
"display(refresh_button, refresh_output)"
388+
"display(refresh_button, refresh_output)\n",
389+
"display(show_code06_button, show_code06_output)"
369390
]
370391
},
371392
{
@@ -387,6 +408,9 @@
387408
"source": [
388409
"# globals for atl03 processing\n",
389410
"atl03_rsps = None\n",
411+
"atl03_parms = None\n",
412+
"show_code03_button = widgets.Button(description=\"Show Code\")\n",
413+
"show_code03_output = widgets.Output()\n",
390414
"elev_dropdown = None\n",
391415
"pc_button = widgets.Button(description=\"Plot Photon Cloud\")\n",
392416
"pc_output = widgets.Output()\n",
@@ -439,7 +463,7 @@
439463
"%matplotlib widget\n",
440464
"# ATL03 Subsetter\n",
441465
"def runATL03Subsetter():\n",
442-
" global url_textbox, parms\n",
466+
" global url_textbox, atl03_parms\n",
443467
" \n",
444468
" # set the url for the sliderule service\n",
445469
" if url_textbox.value == 'local':\n",
@@ -452,7 +476,7 @@
452476
" asset = SRwidgets.asset.value\n",
453477
"\n",
454478
" # build sliderule parameters using latest values from widget\n",
455-
" parms = {\n",
479+
" atl03_parms = {\n",
456480
" # processing parameters\n",
457481
" \"srt\": SRwidgets.surface_type.index,\n",
458482
" \"len\": SRwidgets.length.value,\n",
@@ -476,7 +500,7 @@
476500
" }\n",
477501
"\n",
478502
" # make call to sliderule\n",
479-
" rsps = icesat2.atl03sp(parms, asset)\n",
503+
" rsps = icesat2.atl03sp(atl03_parms, asset)\n",
480504
" \n",
481505
" # return geodataframe\n",
482506
" return rsps\n",
@@ -523,7 +547,19 @@
523547
" SRwidgets.ground_track.value = gt2str[feature[\"properties\"][\"gt\"]]\n",
524548
"\n",
525549
"# install click handler callback\n",
526-
"m.add_selected_callback(click_handler)"
550+
"m.add_selected_callback(click_handler)\n",
551+
"\n",
552+
"# show code action\n",
553+
"def on_show_code03_clicked(b):\n",
554+
" global url_textbox, atl03_parms\n",
555+
" with show_code03_output:\n",
556+
" clear_output()\n",
557+
" print(f'icesat2.init(\"{url_textbox.value}\")')\n",
558+
" print('parms = ', json.dumps(atl03_parms, indent=4), sep='')\n",
559+
" print('gdf = icesat2.atl03sp(parms, asset=\"nsidc-s3\")')\n",
560+
" \n",
561+
"# install click handler callback\n",
562+
"show_code03_button.on_click(on_show_code03_clicked)"
527563
]
528564
},
529565
{
@@ -560,15 +596,9 @@
560596
"display(SRwidgets.plot_classification)\n",
561597
"display(elev_dropdown)\n",
562598
"display(pc_button)\n",
563-
"display(pc_output)"
599+
"display(pc_output)\n",
600+
"display(show_code03_button, show_code03_output)"
564601
]
565-
},
566-
{
567-
"cell_type": "code",
568-
"execution_count": null,
569-
"metadata": {},
570-
"outputs": [],
571-
"source": []
572602
}
573603
],
574604
"metadata": {
@@ -605,7 +635,7 @@
605635
"name": "python",
606636
"nbconvert_exporter": "python",
607637
"pygments_lexer": "ipython3",
608-
"version": "3.8.13"
638+
"version": "3.8.15"
609639
},
610640
"toc-showtags": false
611641
},

0 commit comments

Comments
 (0)