|
58 | 58 | " * MODIS/Terra Snow Cover Daily L3 Global 500m SIN Grid, Version 6: https://doi.org/10.5067/MODIS/MOD10A1.006\n",
|
59 | 59 | "\n",
|
60 | 60 | "\n",
|
61 |
| - "#### Other popular snow products:\n", |
| 61 | + "#### Other relevant snow products:\n", |
62 | 62 | "\n",
|
63 | 63 | "* [VIIRS Snow Data](http://nsidc.org/data/search/#sortKeys=score,,desc/facetFilters=%257B%2522facet_sensor%2522%253A%255B%2522Visible-Infrared%2520Imager-Radiometer%2520Suite%2520%257C%2520VIIRS%2522%255D%252C%2522facet_parameter%2522%253A%255B%2522SNOW%2520COVER%2522%252C%2522Snow%2520Cover%2522%255D%257D/pageNumber=1/itemsPerPage=25)\n",
|
64 | 64 | "\n",
|
65 |
| - "* [AMSR-E](https://nsidc.org/data/amsre)\n", |
66 |
| - " * AMSR-E/Aqua Daily L3 Global Snow Water Equivalent EASE-Grids, Version 2: https://doi.org/10.5067/AMSR-E/AE_DYSNO.002\n", |
67 |
| - " * AMSR-E/Aqua 5-Day L3 Global Snow Water Equivalent EASE-Grids, Version 2: https://doi.org/10.5067/AMSR-E/AE_5DSNO.002\n", |
68 |
| - " * AMSR-E/Aqua Monthly L3 Global Snow Water Equivalent EASE-Grids, Version 2: https://doi.org/10.5067/AMSR-E/AE_MOSNO.002\n", |
69 |
| - " \n", |
70 |
| - "* [AMSR-E/AMSR2 Unified Data](https://nsidc.org/data/amsre_amsr2)\n", |
71 |
| - " * AMSR-E/AMSR2 Unified L3 Global Daily 25 km EASE-Grid Snow Water Equivalent, Version 1: https://doi.org/10.5067/8AE2ILXB5SM6\n", |
72 |
| - " * AMSR-E/AMSR2 Unified L3 Global 5-Day 25 km EASE-Grid Snow Water Equivalent, Version 1: https://doi.org/10.5067/0PX911G6417E\n", |
73 |
| - " * AMSR-E/AMSR2 Unified L3 Global Monthly 25 km EASE-Grid Snow Water Equivalent, Version 1:\n", |
74 |
| - "https://doi.org/10.5067/43NH9LHM9YRK\n", |
| 65 | + "* [AMSR-E and AMSR-E/AMSR2 Unified Snow Data](http://nsidc.org/data/search/#sortKeys=score,,desc/facetFilters=%257B%2522facet_sensor%2522%253A%255B%2522Advanced%2520Microwave%2520Scanning%2520Radiometer-EOS%2520%257C%2520AMSR-E%2522%252C%2522Advanced%2520Microwave%2520Scanning%2520Radiometer%25202%2520%257C%2520AMSR2%2522%255D%252C%2522facet_parameter%2522%253A%255B%2522SNOW%2520WATER%2520EQUIVALENT%2522%252C%2522Snow%2520Water%2520Equivalent%2522%255D%257D/pageNumber=1/itemsPerPage=25)\n", |
75 | 66 | "\n",
|
76 |
| - "* [MEaSUREs](https://nsidc.org/data/measures)\n", |
77 |
| - " * MEaSUREs Northern Hemisphere Terrestrial Snow Cover Extent Daily 25km EASE-Grid 2.0, Version 1: https://doi.org/10.5067/MEASURES/CRYOSPHERE/nsidc-0530.001\n", |
78 |
| - " * MEaSUREs Northern Hemisphere Terrestrial Snow Cover Extent Weekly 100km EASE-Grid 2.0, Version 1: https://doi.org/10.5067/MEASURES/CRYOSPHERE/nsidc-0531.001" |
| 67 | + "* [MEaSUREs Snow Data](http://nsidc.org/data/search/#keywords=measures/sortKeys=score,,desc/facetFilters=%257B%2522facet_parameter%2522%253A%255B%2522SNOW%2520COVER%2522%255D%252C%2522facet_sponsored_program%2522%253A%255B%2522NASA%2520National%2520Snow%2520and%2520Ice%2520Data%2520Center%2520Distributed%2520Active%2520Archive%2520Center%2520%257C%2520NASA%2520NSIDC%2520DAAC%2522%255D%252C%2522facet_format%2522%253A%255B%2522NetCDF%2522%255D%252C%2522facet_temporal_duration%2522%253A%255B%252210%252B%2520years%2522%255D%257D/pageNumber=1/itemsPerPage=25)\n", |
| 68 | + " \n", |
| 69 | + "* Near-Real-Time SSM/I-SSMIS EASE-Grid Daily Global Ice Concentration and Snow Extent (NISE), Version 5: https://doi.org/10.5067/3KB2JPLFPK3R" |
79 | 70 | ]
|
80 | 71 | },
|
81 | 72 | {
|
|
96 | 87 | "source": [
|
97 | 88 | "import os\n",
|
98 | 89 | "import geopandas as gpd\n",
|
99 |
| - "import fiona\n", |
100 | 90 | "from shapely.geometry import Polygon, mapping\n",
|
101 | 91 | "from shapely.geometry.polygon import orient\n",
|
102 | 92 | "import pandas as pd \n",
|
|
108 | 98 | "import requests\n",
|
109 | 99 | "import json\n",
|
110 | 100 | "import pprint\n",
|
111 |
| - "import getpass\n", |
112 | 101 | "from rasterio.mask import mask\n",
|
| 102 | + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", |
113 | 103 | "\n",
|
114 | 104 | "\n",
|
115 | 105 | "# This is our functions module. We created several helper functions to discover, access, and harmonize the data below.\n",
|
|
125 | 115 | "\n",
|
126 | 116 | "## Data Discovery\n",
|
127 | 117 | "\n",
|
128 |
| - "Identify study area and explore data availability and coincident data over the same time and area. \n", |
| 118 | + "Start by identifying your study area and exploring coincident data over the same time and area. \n", |
129 | 119 | "\n",
|
130 |
| - "\n", |
131 |
| - "You can use NASA Earthdata Search to explore data availabilty and to access the same data below: \n", |
| 120 | + "NASA Earthdata Search can be used to visualize file coverage over mulitple data sets and to access the same data you will be working with below: \n", |
132 | 121 | "https://search.earthdata.nasa.gov/projects?projectId=5366449248\n"
|
133 | 122 | ]
|
134 | 123 | },
|
|
196 | 185 | "source": [
|
197 | 186 | "### Create data dictionary \n",
|
198 | 187 | "\n",
|
199 |
| - "Create a nested dictionary with each data set short name and version, as well as shared temporal range and polygonal area of interest. **Add shortname and version info**" |
| 188 | + "Create a nested dictionary with each data set shortname and version, as well as shared temporal range and polygonal area of interest. Data set shortnames, or IDs, as well as version numbers, are located at the top of every NSIDC landing page." |
200 | 189 | ]
|
201 | 190 | },
|
202 | 191 | {
|
|
292 | 281 | "cell_type": "markdown",
|
293 | 282 | "metadata": {},
|
294 | 283 | "source": [
|
295 |
| - "### Additional access and subsetting services\n", |
| 284 | + "### Additional data access and subsetting services\n", |
296 | 285 | "\n",
|
| 286 | + "#### API Access\n", |
297 | 287 | "Data can be accessed directly from our HTTPS file system through the URLs collected above, or through our Application Programming Interface (API). Our API offers you the ability to order data using specific temporal and spatial filters, as well as subset, reformat, and reproject select data sets. The same subsetting, reformatting, and reprojection services available on select data sets through NASA Earthdata Search can also be applied using this API. These options can be requested in a single access command without the need to script against our data directory structure. See our [programmatic access guide](https://nsidc.org/support/how/how-do-i-programmatically-request-data-services) for more information on API options. "
|
298 | 288 | ]
|
299 | 289 | },
|
|
303 | 293 | "source": [
|
304 | 294 | "#### Add service request options for MODIS data\n",
|
305 | 295 | "\n",
|
306 |
| - "According to https://nsidc.org/support/faq/what-data-subsetting-reformatting-and-reprojection-services-are-available-for-MODIS-data, we can see that spatial subsetting and GeoTIFF reformatting are available for MOD10A1 so those options are requested below.The area subset must be described as a bounding box, which can be created based on the polygon bounds above. We will also add GeoTIFF reformatting to the MOD10A1 data dictionary and the temporal range will be set based on the range of MOD10A1 files in the dataframe above. These new parameters will be added to the API request below." |
| 296 | + "According to https://nsidc.org/support/faq/what-data-subsetting-reformatting-and-reprojection-services-are-available-for-MODIS-data, we can see that spatial subsetting and GeoTIFF reformatting are available for MOD10A1 so those options are requested below. The area subset must be described as a bounding box, which can be created based on the polygon bounds above. We will also add GeoTIFF reformatting to the MOD10A1 data dictionary and the temporal range will be set based on the range of MOD10A1 files in the dataframe above. These new parameters will be added to the API request below." |
307 | 297 | ]
|
308 | 298 | },
|
309 | 299 | {
|
|
367 | 357 | " os.mkdir(path)\n",
|
368 | 358 | "os.chdir(path)\n",
|
369 | 359 | "#fn.cmr_download(urls)\n",
|
370 |
| - "#fn.cmr_download(api_request)" |
371 |
| - ] |
372 |
| - }, |
373 |
| - { |
374 |
| - "cell_type": "code", |
375 |
| - "execution_count": null, |
376 |
| - "metadata": {}, |
377 |
| - "outputs": [], |
378 |
| - "source": [ |
| 360 | + "#fn.cmr_download(api_request)\n", |
| 361 | + "\n", |
| 362 | + "\n", |
| 363 | + "# pull data from staged bucket for demonstration\n", |
379 | 364 | "!aws --no-sign-request s3 cp s3://snowex-aso-modis-tutorial-data/ ./ --recursive #access data in staged directory"
|
380 | 365 | ]
|
381 | 366 | },
|
|
457 | 442 | "cell_type": "markdown",
|
458 | 443 | "metadata": {},
|
459 | 444 | "source": [
|
460 |
| - "Further subset the SnowEx snow depth data to get within a 500 m radius of the [SNOTEL Mesa Lakes](https://wcc.sc.egov.usda.gov/nwcc/site?sitenum=622&state=co)\n", |
| 445 | + "We can further subset the SnowEx snow depth data to get within a 500 m radius of the [SNOTEL Mesa Lakes](https://wcc.sc.egov.usda.gov/nwcc/site?sitenum=622&state=co) site.\n", |
461 | 446 | "\n",
|
462 |
| - "First we'll create a new GeoDataFrame with the SNOTEL site location, set to our SnowEx UTM coordinate reference system and create a 500 meter buffer around this point. Then we'll subset the SnowEx points to the buffer and convert back to the WGS84 CRS:" |
| 447 | + "First we'll create a new geodataframe with the SNOTEL site location, set to our SnowEx UTM coordinate reference system, and create a 500 meter buffer around this point. Then we'll subset the SnowEx points to the buffer and convert back to the WGS84 CRS:" |
463 | 448 | ]
|
464 | 449 | },
|
465 | 450 | {
|
|
490 | 475 | "___\n",
|
491 | 476 | "## Read in Airborne Snow Observatory data and clip to SNOTEL buffer\n",
|
492 | 477 | "\n",
|
493 |
| - "The ASO L4 Lidar Snow Depth 3m UTM Grid data set is provided in GeoTIFF format, so we'll use the [Rasterio](https://rasterio.readthedocs.io/en/latest/) library to read in the data. " |
| 478 | + "Snow depth data from the ASO L4 Lidar Snow Depth 3m UTM Grid data set were calculated from surface elevation measured by the Riegl LMS-Q1560 airborne laser scanner (ALS). The data are provided in GeoTIFF format, so we'll use the [Rasterio](https://rasterio.readthedocs.io/en/latest/) library to read in the data. " |
494 | 479 | ]
|
495 | 480 | },
|
496 | 481 | {
|
|
510 | 495 | "source": [
|
511 | 496 | "### Clip data to SNOTEL buffer\n",
|
512 | 497 | "\n",
|
513 |
| - "In order to reduce the data volume to the buffered region of interest, we can clip, or subset this GeoTIFF to the same SNOTEL buffer:" |
| 498 | + "In order to reduce the data volume to the buffered region of interest, we can subset this GeoTIFF to the same SNOTEL buffer:" |
514 | 499 | ]
|
515 | 500 | },
|
516 | 501 | {
|
|
540 | 525 | "___ \n",
|
541 | 526 | "## Read in MODIS Snow Cover data \n",
|
542 | 527 | "\n",
|
543 |
| - "For GIS, we can also use Worldview: https://go.nasa.gov/2WdsIR3. Note that you may need to change this filename output if you download the data outside of the staged bucket. \n" |
| 528 | + "We are interested in the Normalized Difference Snow Index (NDSI) snow cover value from the MOD10A1 data set, which is an index that is related to the presence of snow in a pixel. According to the [MOD10A1 FAQ](https://nsidc.org/support/faq/what-ndsi-snow-cover-and-how-does-it-compare-fsc), snow cover is detected using the NDSI ratio of the difference in visible reflectance (VIS) and shortwave infrared reflectance (SWIR), where NDSI = ((band 4-band 6) / (band 4 + band 6)).\n", |
| 529 | + "\n", |
| 530 | + "Note that you may need to change this filename output below if you download the data outside of the staged bucket, as the output names may vary per request. " |
544 | 531 | ]
|
545 | 532 | },
|
546 | 533 | {
|
|
566 | 553 | "cell_type": "markdown",
|
567 | 554 | "metadata": {},
|
568 | 555 | "source": [
|
569 |
| - "First, set geometry for the SnowEx data" |
| 556 | + "In order to add data from these ASO and MODIS gridded data sets, we need to define the geometry parameters for theses, as well as the SnowEx data. The SnowEx geometry is set using the longitude and latitude values of the geodataframe:" |
570 | 557 | ]
|
571 | 558 | },
|
572 | 559 | {
|
|
583 | 570 | "cell_type": "markdown",
|
584 | 571 | "metadata": {},
|
585 | 572 | "source": [
|
586 |
| - "Then create are definitions for ASO and MODIS data since they are on regular grids:" |
587 |
| - ] |
588 |
| - }, |
589 |
| - { |
590 |
| - "cell_type": "markdown", |
591 |
| - "metadata": {}, |
592 |
| - "source": [ |
593 |
| - "Projection and extent metadata:" |
| 573 | + "With ASO and MODIS data on regular grids, we can create area definitions for these using projection and extent metadata:" |
594 | 574 | ]
|
595 | 575 | },
|
596 | 576 | {
|
|
642 | 622 | "source": [
|
643 | 623 | "### Interpolate ASO and MODIS values onto SnowEx points\n",
|
644 | 624 | "\n",
|
645 |
| - "To easily interpolate ASO snow depth and MODIS snow cover data to SnowEx snow depth points, we can use the `pyresample` library. The `radius_of_influence` parameter determines maximum radius to look for nearest neighbor interpolation.\n", |
646 |
| - "\n", |
647 |
| - "Masked arrays can be used as data input. In order to have undefined pixels masked out instead of assigned a fill value set fill_value=None when calling the resample_* function.\n" |
| 625 | + "To interpolate ASO snow depth and MODIS snow cover data to SnowEx snow depth points, we can use the `pyresample` library. The `radius_of_influence` parameter determines maximum radius to look for nearest neighbor interpolation." |
648 | 626 | ]
|
649 | 627 | },
|
650 | 628 | {
|
|
655 | 633 | "source": [
|
656 | 634 | "# add ASO values to geodataframe\n",
|
657 | 635 | "import warnings\n",
|
658 |
| - "warnings.filterwarnings('ignore') \n", |
| 636 | + "warnings.filterwarnings('ignore') # ignore warning when resampling to a different projection\n", |
659 | 637 | "gdf_buffer['aso_snow_depth'] = prs.kd_tree.resample_nearest(aso_geometry, aso_array, snowex_geometry, radius_of_influence=3)\n",
|
660 | 638 | "\n",
|
661 | 639 | "# add MODIS values to geodataframe\n",
|
662 |
| - "gdf_buffer['modis_ndsi'] = prs.kd_tree.resample_nearest(modis_geometry, modis_array, snowex_geometry, radius_of_influence=500)" |
663 |
| - ] |
664 |
| - }, |
665 |
| - { |
666 |
| - "cell_type": "code", |
667 |
| - "execution_count": null, |
668 |
| - "metadata": {}, |
669 |
| - "outputs": [], |
670 |
| - "source": [ |
| 640 | + "gdf_buffer['modis_ndsi'] = prs.kd_tree.resample_nearest(modis_geometry, modis_array, snowex_geometry, radius_of_influence=500)\n", |
| 641 | + "\n", |
671 | 642 | "gdf_buffer.head()"
|
672 | 643 | ]
|
673 | 644 | },
|
|
678 | 649 | "___ \n",
|
679 | 650 | "## Visualize data and export for further GIS analysis\n",
|
680 | 651 | "\n",
|
681 |
| - "Start with ASO data:" |
682 |
| - ] |
683 |
| - }, |
684 |
| - { |
685 |
| - "cell_type": "code", |
686 |
| - "execution_count": null, |
687 |
| - "metadata": {}, |
688 |
| - "outputs": [], |
689 |
| - "source": [ |
690 |
| - "gdf_buffer_aso_crs = gdf_buffer.to_crs('EPSG:32613')" |
| 652 | + "The rasterio plot module allows you to directly plot GeoTIFFs objects. The SnowEx `Thickness` values are plotted against the clipped ASO snow depth raster." |
691 | 653 | ]
|
692 | 654 | },
|
693 | 655 | {
|
|
696 | 658 | "metadata": {},
|
697 | 659 | "outputs": [],
|
698 | 660 | "source": [
|
| 661 | + "gdf_buffer_aso_crs = gdf_buffer.to_crs('EPSG:32613') \n", |
| 662 | + "\n", |
699 | 663 | "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
|
700 | 664 | "fig, ax = plt.subplots(figsize=(10, 10))\n",
|
701 | 665 | "show(clipped_aso, ax=ax)\n",
|
702 | 666 | "divider = make_axes_locatable(ax)\n",
|
703 |
| - "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.1)\n", |
| 667 | + "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.1) # fit legend to height of plot\n", |
704 | 668 | "gdf_buffer_aso_crs.plot(column='Thickness', ax=ax, cmap='OrRd', legend=True, cax=cax, legend_kwds=\n",
|
705 | 669 | " {'label': \"Snow Depth (m)\",});"
|
706 | 670 | ]
|
707 | 671 | },
|
708 | 672 | {
|
709 |
| - "cell_type": "code", |
710 |
| - "execution_count": null, |
| 673 | + "cell_type": "markdown", |
711 | 674 | "metadata": {},
|
712 |
| - "outputs": [], |
713 | 675 | "source": [
|
714 |
| - "gdf_buffer_modis_crs = gdf_buffer.to_crs('PROJCS[\"Sinusoidal Modis Spheroid\",GEOGCS[\"Unknown datum based upon the Authalic Sphere\",DATUM[\"Not_specified_based_on_Authalic_Sphere\",SPHEROID[\"Sphere\",6371007.181,887203.3395236016,AUTHORITY[\"EPSG\",\"7035\"]],AUTHORITY[\"EPSG\",\"6035\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4035\"]],PROJECTION[\"Sinusoidal\"],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]]')" |
| 676 | + "We can do the same for MOD10A1: This was subsetted to the entire Grand Mesa region defined by the SnowEx data set coverage. " |
715 | 677 | ]
|
716 | 678 | },
|
717 | 679 | {
|
|
720 | 682 | "metadata": {},
|
721 | 683 | "outputs": [],
|
722 | 684 | "source": [
|
723 |
| - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", |
| 685 | + "# Set dataframe to MOD10A1 Sinusoidal projection\n", |
| 686 | + "gdf_buffer_modis_crs = gdf_buffer.to_crs('PROJCS[\"Sinusoidal Modis Spheroid\",GEOGCS[\"Unknown datum based upon the Authalic Sphere\",DATUM[\"Not_specified_based_on_Authalic_Sphere\",SPHEROID[\"Sphere\",6371007.181,887203.3395236016,AUTHORITY[\"EPSG\",\"7035\"]],AUTHORITY[\"EPSG\",\"6035\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4035\"]],PROJECTION[\"Sinusoidal\"],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]]')\n", |
| 687 | + "\n", |
724 | 688 | "fig, ax = plt.subplots(figsize=(10, 10))\n",
|
725 | 689 | "show(modis, ax=ax)\n",
|
726 | 690 | "divider = make_axes_locatable(ax)\n",
|
727 |
| - "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.1)\n", |
| 691 | + "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.1) # fit legend to height of plot\n", |
728 | 692 | "gdf_buffer_modis_crs.plot(column='Thickness', ax=ax, cmap='OrRd', legend=True, cax=cax, legend_kwds=\n",
|
729 | 693 | " {'label': \"Snow Depth (m)\",});"
|
730 | 694 | ]
|
|
733 | 697 | "cell_type": "markdown",
|
734 | 698 | "metadata": {},
|
735 | 699 | "source": [
|
736 |
| - "### Export to Shapefile for GIS applications:" |
| 700 | + "### Additional data imagery services\n", |
| 701 | + "\n", |
| 702 | + "#### NASA Worldview and the Global Browse Imagery Service\n", |
| 703 | + "\n", |
| 704 | + "NASA’s EOSDIS Worldview mapping application provides the capability to interactively browse over 900 global, full-resolution satellite imagery layers and then download the underlying data. Many of the available imagery layers are updated within three hours of observation, essentially showing the entire Earth as it looks “right now.\"\n", |
| 705 | + "\n", |
| 706 | + "According to the [MOD10A1 landing page](https://nsidc.org/data/mod10a1), snow cover imagery layers from this data set are available through NASA Worldview. This layer can be downloaded as various image files including GeoTIFF using the snapshot feature at the top right of the page. This link presents the MOD10A1 NDSI layer over our time and area of interest: https://go.nasa.gov/35CgYMd. \n", |
| 707 | + "\n", |
| 708 | + "Additionally, the NASA Global Browse Imagery Service provides up to date, full resolution imagery for select NSIDC DAAC data sets as web services including WMTS, WMS, KML, and more. These layers can be accessed in GIS applications following guidance on the [GIBS documentation pages](https://wiki.earthdata.nasa.gov/display/GIBS/Geographic+Information+System+%28GIS%29+Usage). " |
| 709 | + ] |
| 710 | + }, |
| 711 | + { |
| 712 | + "cell_type": "markdown", |
| 713 | + "metadata": {}, |
| 714 | + "source": [ |
| 715 | + "### Export dataframe to Shapefile" |
737 | 716 | ]
|
738 | 717 | },
|
739 | 718 | {
|
740 | 719 | "cell_type": "markdown",
|
741 | 720 | "metadata": {},
|
742 | 721 | "source": [
|
743 |
| - "Write to shapefile for GIS applications:\n" |
| 722 | + "Finally, the dataframe can be exported as an Esri shapefile for further analysis in GIS:" |
744 | 723 | ]
|
745 | 724 | },
|
746 | 725 | {
|
|
0 commit comments