From bf6821032e14570bd26946bae01dc1b8cd14e467 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 15 Feb 2017 15:03:57 -0500 Subject: [PATCH 01/57] arcpy --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b8ae7d2..8d433db 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,14 @@ # developython Python Training for the DEVELOP program. -# Setup Instructions (User Account & GDAL) +# Setup Instructions + +1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ +2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). +3. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt +4. _Create script:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\ebsmith2\AppData\Local\Continuum\Anaconda2\site_packages\` + +--- 1. [Download](http://www.continuum.io/downloads#_windows) and install Anaconda for Windows 64-Bit (Python 2.7) 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). From 4b376300c8f23371c31f6cdd98f401647495610b Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 15 Feb 2017 15:04:34 -0500 Subject: [PATCH 02/57] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d433db..625133f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). 3. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt -4. _Create script:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\ebsmith2\AppData\Local\Continuum\Anaconda2\site_packages\` +4. _Create script for this:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\` --- From 3ad9f062dba7c2af976a6a2562dd293a77c2a42d Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 15 Feb 2017 15:15:12 -0500 Subject: [PATCH 03/57] latest These are Mac/Linux instructions which will not work on a user-privileged Windows machine. Going off the reservation now. --- gdal_env_setup_instructions.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdal_env_setup_instructions.txt b/gdal_env_setup_instructions.txt index 5d3b991..41fdef9 100644 --- a/gdal_env_setup_instructions.txt +++ b/gdal_env_setup_instructions.txt @@ -1,4 +1,4 @@ -# This works as of 12/15/16 +# This works as of 12/15/16 (02/15/2017 - conda version has been updated to 4.3) # First, Download anaconda # Check version From fc281cf8cd9dd670d342ea35b1d0437029d49c86 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 15 Feb 2017 15:15:38 -0500 Subject: [PATCH 04/57] Create 20170215_conda.txt --- 20170215_conda.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 20170215_conda.txt diff --git a/20170215_conda.txt b/20170215_conda.txt new file mode 100644 index 0000000..2e84547 --- /dev/null +++ b/20170215_conda.txt @@ -0,0 +1,27 @@ +The following NEW packages will be INSTALLED: + + gdal: 2.1.0-py27_0 + geos: 3.5.0-vc9_0 [vc9] + hdf4: 4.2.12-vc9_0 [vc9] + kealib: 1.4.6-vc9_0 [vc9] + libgdal: 2.1.0-vc9_0 [vc9] + libnetcdf: 4.3.3.1-vc9_4 [vc9] + proj4: 4.9.2-vc9_0 [vc9] + xerces-c: 3.1.4-vc9_0 [vc9] + +The following packages will be UPDATED: + + anaconda: 4.3.0-np111py27_0 --> custom-py27_0 + +The following packages will be DOWNGRADED due to dependency conflicts: + + jpeg: 9b-vc9_0 [vc9] --> 8d-vc9_2 [vc9] + libtiff: 4.0.6-vc9_3 [vc9] --> 4.0.6-vc9_2 [vc9] + pillow: 4.0.0-py27_0 --> 3.4.2-py27_0 + qt: 5.6.2-vc9_3 [vc9] --> 5.6.2-vc9_0 [vc9] + + +The following NEW packages will be INSTALLED: + + libnetcdf: 4.3.3.1-vc9_4 [vc9] + netcdf4: 1.2.4-np111py27_0 From 8ee82e2907e64a7b797e9f1d91399b68303d7b00 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 15 Feb 2017 15:33:16 -0500 Subject: [PATCH 05/57] Update README.md --- README.md | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 625133f..f96b3d1 100644 --- a/README.md +++ b/README.md @@ -7,31 +7,7 @@ Python Training for the DEVELOP program. 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). 3. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 4. _Create script for this:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\` +5. `conda update conda` +6. `conda install gdal netCDF4` ---- - -1. [Download](http://www.continuum.io/downloads#_windows) and install Anaconda for Windows 64-Bit (Python 2.7) -2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Do not add it to your path (can change depending upon use with GDAL). -4. Start -> All Programs -> Anaconda 2 (64-Bit) -> Anaconda Prompt -5. `conda install netCDF4 basemap` -6. `conda install conda=4.1.11` -7. `conda install -c conda-forge gdal` -8. `conda install h5py` -8. Close your Anaconda Prompt to retain the changes and then open again to test installation. - -### And if all else fails: - -1. `conda install conda=4.1.11` -2. Exit Anaconda Prompt -3. `conda create -n GDAL python=2.7 gdal -c conda-forge` -4. `activate GDAL` - -To Test GDAL install: - -1. Download this [file](https://drive.google.com/file/d/0B9m0kGaHo6cnM0JxbkM5aFZvN28/view?usp=sharing) -2. `cd` to Downloads directory -3. `gdalwarp -t_srs "EPSG:32645" 1400412014302_to_1400412014206.tif test.tif` - -# TODO: -1. Connect arcpy with Anaconda exterior to ArcGIS. +_To Do:_ Correct GDAL_DATA env var to be `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Library\share\gdal` From 17dd9c8ba5c248db82441d096b497b22e95a1152 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 19 Feb 2017 14:56:56 -0500 Subject: [PATCH 06/57] Add files via upload --- gdal_instructions_Win7.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 gdal_instructions_Win7.txt diff --git a/gdal_instructions_Win7.txt b/gdal_instructions_Win7.txt new file mode 100644 index 0000000..0df68e0 --- /dev/null +++ b/gdal_instructions_Win7.txt @@ -0,0 +1,16 @@ +1. Open Anaconda prompt +2. Create GDAL environment and install GDAL with 'conda create -n gdal_works gdal' +3. Navigate to environment folder with 'cd %LOCALAPPDATA%\Continuum\Anaconda2\envs\gdal_works' +4. They should exist, but if they do not: + - mkdir .\etc\conda\activate.d + - mkdir .\etc\conda\deactivate.d +5. Create env_vars.bat in activate.d and add text 'set GDAL_DATA=%LOCALAPPDATA%\Continuum\Anaconda2\envs\gdal_works\Library\share\gdal' +6. Create env_vars.bat in deactivate.d and add text 'set GDAL_DATA=' +7. Back in prompt, type 'activate gdal_works' +8. To test: + - Download https://drive.google.com/file/d/0B8toI67HoVSrdkxYc2ZSX3NGcUk/view?usp=sharing + - In Anaconda prompt, navigate to folder with above file, which is an SRTM tile in HGT format + - To test GDAL installation in general, type 'gdal_translate N10E034.hgt N10E034.tif' + - There should now be a GeoTIFF version of this file + - To test whether GDAL_DATA is set properly, type 'gdalwarp -t_srs "EPSG:32636" N10E034.tif N10E034_utm.tif' + - There should now be a GeoTIFF version of the file in UTM Zone 36 N projection (originally in unprojected WGS84). Confirm that both new files look reasonable in a GIS. \ No newline at end of file From 49213bab8f6b83ca6fdbda98fc1288aadb787ba1 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 19 Feb 2017 15:00:44 -0500 Subject: [PATCH 07/57] Update and rename gdal_env_setup_instructions.txt to gdal_instructions_MacLinux.txt These instructions most likely work on a Mac OS, and therefore might be useful if any of the DEVELOP interns want to go that route with their personal systems. However, they do not apply to Windows. --- ...env_setup_instructions.txt => gdal_instructions_MacLinux.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename gdal_env_setup_instructions.txt => gdal_instructions_MacLinux.txt (86%) diff --git a/gdal_env_setup_instructions.txt b/gdal_instructions_MacLinux.txt similarity index 86% rename from gdal_env_setup_instructions.txt rename to gdal_instructions_MacLinux.txt index 41fdef9..7983d55 100644 --- a/gdal_env_setup_instructions.txt +++ b/gdal_instructions_MacLinux.txt @@ -27,7 +27,7 @@ conda list # Set environment variable. export GDAL_DATA=/Users/aakashahamed/anaconda2/envs/gdal_conda/share/gdal # or whatever path -# Test that the install works. Follow instructions here: https://github.com/edmondb/developython +# Test that the install works. See Windows 7 instructions. # Install some other libs conda install --name gdal_conda scikit-learn From abeca4d104986e6b89af0c80c847035b524d6f23 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 19 Feb 2017 15:10:13 -0500 Subject: [PATCH 08/57] Updated to reflect new GDAL instructions Performed some testing on my system, and I think the GDAL_DATA issues is resolved. It would still be nice to script some of that setup. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f96b3d1..c783803 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,5 @@ Python Training for the DEVELOP program. 3. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 4. _Create script for this:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\` 5. `conda update conda` -6. `conda install gdal netCDF4` - -_To Do:_ Correct GDAL_DATA env var to be `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Library\share\gdal` +6. `conda install netCDF4` +7. _Write script for most of this as well:_ Follow GDAL setup instructions. From c61b1c38d79099ac5785b20e46a842fee3555922 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 19 Feb 2017 15:17:20 -0500 Subject: [PATCH 09/57] Added deactivation instructions --- gdal_instructions_Win7.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gdal_instructions_Win7.txt b/gdal_instructions_Win7.txt index 0df68e0..35f40eb 100644 --- a/gdal_instructions_Win7.txt +++ b/gdal_instructions_Win7.txt @@ -13,4 +13,7 @@ - To test GDAL installation in general, type 'gdal_translate N10E034.hgt N10E034.tif' - There should now be a GeoTIFF version of this file - To test whether GDAL_DATA is set properly, type 'gdalwarp -t_srs "EPSG:32636" N10E034.tif N10E034_utm.tif' - - There should now be a GeoTIFF version of the file in UTM Zone 36 N projection (originally in unprojected WGS84). Confirm that both new files look reasonable in a GIS. \ No newline at end of file + - There should now be a GeoTIFF version of the file in UTM Zone 36 N projection (originally in unprojected WGS84). + Confirm that both new files look reasonable in a GIS. +9. If you wish to use Jupyter Notebook or Spyder with GDAL, you must install and launch them through this environment +10. If you wish to deactivate GDAL environment, type 'deactivate' in prompt From 77050aae123909072a5f1235618782bde207c4b3 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Tue, 21 Feb 2017 19:23:32 -0500 Subject: [PATCH 10/57] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c783803..f4fb4f7 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt -4. _Create script for this:_ `Copy C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\` +3. Copy `C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. +4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` -7. _Write script for most of this as well:_ Follow GDAL setup instructions. +7. Follow [GDAL setup instructions](https://github.com/edmondb/developython/blob/master/gdal_instructions_Win7.txt) for Windows. From e0779f2c75aba454612e7a968b2b6a1b6312b1f0 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Tue, 21 Feb 2017 20:12:13 -0500 Subject: [PATCH 11/57] spring 2017 week 1 --- Lectures/Week_01/week_1.ipynb | 482 ++++++++++++++++++++++++++++++++++ 1 file changed, 482 insertions(+) create mode 100644 Lectures/Week_01/week_1.ipynb diff --git a/Lectures/Week_01/week_1.ipynb b/Lectures/Week_01/week_1.ipynb new file mode 100644 index 0000000..3dad674 --- /dev/null +++ b/Lectures/Week_01/week_1.ipynb @@ -0,0 +1,482 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Introduction\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### February 22, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### About Our Setup\n", + "\n", + "---\n", + "\n", + "* Anaconda - Virtual environment (don't need to be root/admin), completely free (and easily managed)\n", + "* Enthought Canopy - Virtual environment, not free to add packages/libraries, having several versions gets messy\n", + "\n", + "##### Computer Setup Instructions\n", + "\n", + "[Basic Setup](https://github.com/edmondb/developython/blob/master/README.md)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Who Are We?\n", + "\n", + "---\n", + "\n", + "* Alfred Hubbard\n", + "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The Python Programming Language - A Synopsis\n", + "\n", + "---\n", + "\n", + "* Interpreted (think language translator between you and the computer)\n", + "* Open Source (1991 by Guido van Rossum after Monty Python's Flying Circus)\n", + "* Object-Oriented (makes programming very, very flexible and customizable)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4 Ways to Run Python Code (i.e., approaches to the interpreter)\n", + "\n", + "* As a .py script (plain text document with python code, I use this method most)\n", + "* In the Python shell (from the command line - not a good option)\n", + "* In the iPython shell (interactive, better - still not a good option)\n", + "* In a Jupter notebook (shareable, you are seeing one now, can run as a script or document)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# As a script\n", + "\n", + "---\n", + "\n", + "1. Open the helloworld.py script in your text editor to see the contents of this Python script.\n", + "2. In a terminal/command prompt/Anaconda prompt, type:\n", + "\n", + " ```bash\n", + " $ python helloworld.py\n", + " ```\n", + "\n", + "3. You should see the output on the screen.\n", + "\n", + "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. (Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The # (Shebang)\n", + "\n", + "In scripts (Unix/Linux platforms), you can add a line to the top so you can make the script executable and not have to type `python` to run the script. This, for Python is one of the following:\n", + "\n", + "* The Python that comes with Linux/Unix OS:\n", + "```python\n", + "#! /usr/bin/python\n", + "```\n", + "* The first Python interpreter in your PATH environment variable:\n", + "```python\n", + "#! /usr/bin/env python\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jupyter/IPython notebook\n", + "\n", + "---\n", + "\n", + "1. From terminal/command prompt/Anaconda prompt type:\n", + "\n", + " ```bash\n", + " jupyter notebook\n", + " ```\n", + "\n", + "2. This directs you to a web browser and you can navigate to an already existing notebook or create one (right side menu New -> Python [default]).\n", + "3. This will open up a new Untitled notebook where you can directly input Python code, Markup formatted text, or have raw text.\n", + "4. Type:\n", + "\n", + " ```python\n", + " print('Hello world!')\n", + " ```\n", + "\n", + "5. Press __```Shift-Enter```__, __```Cntrl-Enter```__, or click __Cells -> Run Cells__ or use the Play button near the top of the page.\n", + "6. You will see the output now.\n", + "7. Exit via closing the browser windows and stopping the server running (Cntrl + Enter) in the terminal/command prompt." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Script vs. Notebook\n", + "\n", + "* Script is all code. This makes managing it easier when you work on a supercomputer.\n", + "* Notebook allows you to put plots (aka output) with your code.\n", + "* Notebooks are better for reports/presentations (or testing).\n", + "* Scripts have less overhead (not tested)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic Calculator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# mathematical operations\n", + "2 + 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# store inside a variable\n", + "result = -2*(4+9)\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import math\n", + "\n", + "math.pi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Python imports are like libraries/utilities that others have written for you to use. You can import packages (set of scripts) or modules (single scripts).\n", + "\n", + "Basic Example:\n", + "\n", + "```python\n", + "import numpy\n", + "print(numpy)\n", + "```\n", + " \n", + "1. Imports can be renamed:\n", + "\n", + " ```python\n", + " import numpy as np\n", + " print(np)\n", + " ```\n", + "\n", + "2. You can import submodules directly:\n", + "\n", + " ```python\n", + " from numpy import ma\n", + " print(ma)\n", + " ```\n", + "\n", + "3. You can import specific parts of modules as well (i.e., an object, function, or class within the module):\n", + "\n", + " ```python\n", + " from numpy.ma import masked_array\n", + " print(masked_array)\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# PEP8\n", + "\n", + "The Python Style Guide tells you the best way to perform imports, name functions, and overall coding advice. It used to be called PEP8 (Python Enhancement Proposal 8), but in 2016, it was renamed to pycodestyle.\n", + "\n", + "* [PEP8](http://www.python.org/dev/peps/pep-0008/)\n", + "* [pycodestyle](http://github.com/PyCQA/pycodestyle)\n", + "* [pep8](http://pep8.readthedocs.io/en/release-1.7.x/) - a Python package that checks your code for you.\n", + "* [pep8.org](http://pep8.org) - a more human friendly approach" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Strings (Short Version)\n", + "\n", + "* Single-quotes: `'a string'`\n", + "* Double-quotes: `\"another string\"`\n", + "* Joining/concatenation: `'FirstName' + 'LastName'`\n", + "\n", + "There are multi-line strings (used also for code commenting):\n", + "\n", + "```python\n", + "'''this\n", + "is\n", + "a multi-\n", + "line string.'''\n", + "\n", + "\"\"\"as is\n", + "this \n", + "one\"\"\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The Print Statement\n", + "\n", + "Python 2.x:\n", + "```python\n", + "print 'Hi class!'\n", + "\n", + "print('Hello, class!')\n", + "```\n", + "\n", + "Python 3.x:\n", + "```python\n", + "print('Hello, class!')\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Sring Fomatting\n", + "\n", + "* Old Way (like other languages):\n", + " ```python\n", + " print('This is a shortened number: %3.2f' % (3.1432953265328))\n", + " ```\n", + "* New Way:\n", + " ```python\n", + " print('This is a shortened number: {:3.2f}'.format(3.1432953265328))\n", + " ```\n", + "\n", + "Good resource to compare: [PyFormat](http://pyformat.info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Numerical Expressions\n", + "\n", + "* Python distinguishes between strings and numbers:\n", + "\n", + "```python\n", + "b = 1.2 # b is a number\n", + "b = `1.2` # b is a string\n", + "a = 0.5 * b # illegal: b is NOT converted\n", + "a = 0.5 * float(b) # this works\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Types\n", + "\n", + "| Type | Range | To Define | To Convert |\n", + "|------|-------|-----------|------------|\n", + "|float |numbers|x=1.0 |z=float(x) |\n", + "|integer|numbers|x=1 |z=int(x) |\n", + "|complex|complex numbers|x=3j|z=complex(a,b)|\n", + "|string|text string|x='test'|z=str(x)|\n", + "|boolean|True or False|x=True|z=bool(x)|" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Iterables\n", + "\n", + "---\n", + "\n", + "__Mutable__ - Changeable \n", + "__Immutable__ - Not Changeable\n", + "\n", + "* Lists:\n", + "\n", + " ```python\n", + " a_list = ['item 1', 'something else', 2, True, 'and so on']\n", + " another = list('hello')\n", + " ```\n", + "\n", + " * think grocery list (can be changed, sorted)\n", + " * loop/iterate upon each item (could take a while)\n", + "* Tuples\n", + " * permanant (not changing) lists\n", + " \n", + " ```python\n", + " numbers = (1,2,3)\n", + " first, second, third = numbers\n", + " another = tuple('one', 'two')\n", + " ```\n", + " \n", + "* Dictionaries\n", + " * key/value paring (like word/meaning in a dictionary)\n", + " * keys are strings or integers\n", + " \n", + " ```python\n", + " d = {'key1':'value', 'key2':20, 3:['a', 'list'], 'k5':{'a':'nested','dict':'!'}}\n", + " another = dict(key='value', key2='another')\n", + " ```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Examples: List\n", + "groceries = ['eggs', 'milk', 'bacon']\n", + "groceries.append('coffee')\n", + "groceries.remove('eggs')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Another example - list\n", + "L = [] # declare empty list \n", + "L.append(1.2) # add a number 1.2 \n", + "L.append('a') # add a text element \n", + "L[0] = 1.3 # change an item \n", + "del L[1] # delete an item \n", + "len(L) # length of list \n", + "L.count(x) # count the number of times x occurs \n", + "L.index(x) # return the index of the first occurrence of x \n", + "L.remove(x) # delete the first occurrence of x \n", + "L.reverse() # reverse the order of elements in the list \n", + "L = ['a'] + ['b'] # can combine two lists together" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Slicing\n", + "\n", + "---\n", + "\n", + "```\n", + " +---+---+---+---+---+---+ \n", + " | P | y | t | h | o | n | \n", + " +---+---+---+---+---+---+ \n", + " 0 1 2 3 4 5 6 \n", + "-6 -5 -4 -3 -2 -1\n", + "```\n", + "\n", + "In Python, indexes start at 0, not 1. The above shows slicing on a string, but we can also slice lists and tuples." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# slicing example\n", + "print(groceries)\n", + "print(groceries[0])\n", + "print(groceries[-1])\n", + "print(groceries[2])\n", + "print(groceries[:2])\n", + "print(groceries[-3:])\n", + "print(groceries[10])\n", + "print(groceries[::2])" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} From ead9b0f9298e4e7c8432f5ae91054b2386691dbb Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:31:24 -0500 Subject: [PATCH 12/57] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4fb4f7..62d7483 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Copy `C:\Python27\ArcGIS10.3\Lib\site-packages\Desktop10.3.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. +3. Copy `C:\Python27\ArcGIS10.`__x__`\Lib\site-packages\Desktop10.`__x__`.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` From aab5ceaabd7e28a8f7ee3de7b77a7b5ceeabcdfc Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:32:10 -0500 Subject: [PATCH 13/57] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62d7483..9cb7a88 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Copy `C:\Python27\ArcGIS10.`__x__`\Lib\site-packages\Desktop10.`__x__`.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. +3. Copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` From 5f2e0eb927d4cb32ab13d4e2c7fe832335f3b92b Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:46:53 -0500 Subject: [PATCH 14/57] Fixed typos --- Lectures/Week_01/01_intro.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lectures/Week_01/01_intro.ipynb b/Lectures/Week_01/01_intro.ipynb index 5c414ac..0f47093 100644 --- a/Lectures/Week_01/01_intro.ipynb +++ b/Lectures/Week_01/01_intro.ipynb @@ -33,7 +33,7 @@ "---\n", "\n", "* Aakash Ahamed - Physical Scientist (Code 617), former DEVELOPer, Remote sensing researcher nowcasting floods and impacts from MODIS \n", - "* Brent Smith - Scientific Programmer/Analyst, GMAO-er Operations developer and overal Python guru, Theoretical Physicist" + "* Brent Smith - Scientific Programmer/Analyst, GMAO-er Operations developer and overall Python guru, Theoretical Physicist" ] }, { @@ -492,7 +492,7 @@ } }, "source": [ - "# Sring Fomatting\n", + "# String Fomatting\n", "\n", "* Old Way (like other languages):\n", " ```python\n", From 21ff2b3d84a67c46c496b10f4ca071c69f725161 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:48:58 -0500 Subject: [PATCH 15/57] Added bio for Alfred --- Lectures/Week_01/01_intro.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_01/01_intro.ipynb b/Lectures/Week_01/01_intro.ipynb index 0f47093..63f6245 100644 --- a/Lectures/Week_01/01_intro.ipynb +++ b/Lectures/Week_01/01_intro.ipynb @@ -32,8 +32,8 @@ "\n", "---\n", "\n", - "* Aakash Ahamed - Physical Scientist (Code 617), former DEVELOPer, Remote sensing researcher nowcasting floods and impacts from MODIS \n", "* Brent Smith - Scientific Programmer/Analyst, GMAO-er Operations developer and overall Python guru, Theoretical Physicist" + "* Alfred Hubbard - Scientific Programmer/Analyst; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science\n", ] }, { From c707cb73112be1312177c80ace737d7738bee115 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:50:27 -0500 Subject: [PATCH 16/57] Fixed error --- Lectures/Week_01/01_intro.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lectures/Week_01/01_intro.ipynb b/Lectures/Week_01/01_intro.ipynb index 63f6245..74f7195 100644 --- a/Lectures/Week_01/01_intro.ipynb +++ b/Lectures/Week_01/01_intro.ipynb @@ -32,8 +32,8 @@ "\n", "---\n", "\n", - "* Brent Smith - Scientific Programmer/Analyst, GMAO-er Operations developer and overall Python guru, Theoretical Physicist" - "* Alfred Hubbard - Scientific Programmer/Analyst; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science\n", + "* Brent Smith - Scientific Programmer/Analyst, GMAO-er Operations developer and overall Python guru, Theoretical Physicist\n", + "* Alfred Hubbard - Scientific Programmer/Analyst; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" ] }, { From aec433b5ddc4910eae16a8f7f548d743f99af9ef Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:51:49 -0500 Subject: [PATCH 17/57] Corrected date --- Lectures/Week_01/01_intro.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_01/01_intro.ipynb b/Lectures/Week_01/01_intro.ipynb index 74f7195..a7a5d4c 100644 --- a/Lectures/Week_01/01_intro.ipynb +++ b/Lectures/Week_01/01_intro.ipynb @@ -17,7 +17,7 @@ "\n", "### Goddard Space Flight Center\n", "\n", - "#### September 21, 2016" + "#### February 22, 2017" ] }, { From c9eb0ba8cd1e8b89013c7ab6c9fe034e5123012c Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:57:39 -0500 Subject: [PATCH 18/57] Added bio; fixed typos --- Lectures/Week_01/week_1.ipynb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_01/week_1.ipynb b/Lectures/Week_01/week_1.ipynb index 3dad674..a199616 100644 --- a/Lectures/Week_01/week_1.ipynb +++ b/Lectures/Week_01/week_1.ipynb @@ -44,8 +44,9 @@ "\n", "---\n", "\n", - "* Alfred Hubbard\n", - "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics" + "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics\n", + "* Alfred Hubbard - Scientific Programmer/Analyst; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" + ] }, { @@ -90,7 +91,7 @@ "\n", "3. You should see the output on the screen.\n", "\n", - "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. (Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." + "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." ] }, { @@ -298,7 +299,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Sring Fomatting\n", + "# String Fomatting\n", "\n", "* Old Way (like other languages):\n", " ```python\n", From e441e9513542aeb5f5d934ad08a050a76d0c5824 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 09:59:03 -0500 Subject: [PATCH 19/57] Added code --- Lectures/Week_01/week_1.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_01/week_1.ipynb b/Lectures/Week_01/week_1.ipynb index a199616..6868226 100644 --- a/Lectures/Week_01/week_1.ipynb +++ b/Lectures/Week_01/week_1.ipynb @@ -45,7 +45,7 @@ "---\n", "\n", "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics\n", - "* Alfred Hubbard - Scientific Programmer/Analyst; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" + "* Alfred Hubbard - Scientific Programmer/Analyst, Code 618; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" ] }, From d1a2d23e708e98f4ac634f58cf25f7de830856ae Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 22 Feb 2017 14:30:07 -0500 Subject: [PATCH 20/57] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cb7a88..fac8fea 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\site_packages\`. +3. Copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` From a23554fc6266d20955efb10543f1926460dfedb2 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Wed, 22 Feb 2017 16:15:53 -0500 Subject: [PATCH 21/57] Corrected typos --- Lectures/Week_01/week_1.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lectures/Week_01/week_1.ipynb b/Lectures/Week_01/week_1.ipynb index 6868226..840cc05 100644 --- a/Lectures/Week_01/week_1.ipynb +++ b/Lectures/Week_01/week_1.ipynb @@ -71,7 +71,7 @@ "* As a .py script (plain text document with python code, I use this method most)\n", "* In the Python shell (from the command line - not a good option)\n", "* In the iPython shell (interactive, better - still not a good option)\n", - "* In a Jupter notebook (shareable, you are seeing one now, can run as a script or document)" + "* In a Jupyter notebook (shareable, you are seeing one now, can run as a script or document)" ] }, { @@ -374,7 +374,7 @@ " ```\n", " \n", "* Dictionaries\n", - " * key/value paring (like word/meaning in a dictionary)\n", + " * key/value pairing (like word/meaning in a dictionary)\n", " * keys are strings or integers\n", " \n", " ```python\n", From 59806e868fea99b50349fe72ce5d009752a57fd6 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 27 Feb 2017 10:00:34 -0500 Subject: [PATCH 22/57] typo fix --- Lectures/Week_01/week_1.ipynb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_01/week_1.ipynb b/Lectures/Week_01/week_1.ipynb index 6868226..7263312 100644 --- a/Lectures/Week_01/week_1.ipynb +++ b/Lectures/Week_01/week_1.ipynb @@ -46,7 +46,6 @@ "\n", "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics\n", "* Alfred Hubbard - Scientific Programmer/Analyst, Code 618; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" - ] }, { @@ -71,7 +70,7 @@ "* As a .py script (plain text document with python code, I use this method most)\n", "* In the Python shell (from the command line - not a good option)\n", "* In the iPython shell (interactive, better - still not a good option)\n", - "* In a Jupter notebook (shareable, you are seeing one now, can run as a script or document)" + "* In a Jupyter notebook (shareable, you are seeing one now, can run as a script or document)" ] }, { @@ -461,7 +460,7 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [default]", + "display_name": "Python 2", "language": "python", "name": "python2" }, @@ -475,7 +474,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, From 6b3e64954853015c27e042e7eb80f95da276a965 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 27 Feb 2017 10:43:06 -0500 Subject: [PATCH 23/57] lecture 2 --- Lectures/Week_02/sample.txt | 6 - Lectures/Week_02/week_2.ipynb | 717 ++++++++++++++++++++++++++++++++++ 2 files changed, 717 insertions(+), 6 deletions(-) delete mode 100644 Lectures/Week_02/sample.txt create mode 100644 Lectures/Week_02/week_2.ipynb diff --git a/Lectures/Week_02/sample.txt b/Lectures/Week_02/sample.txt deleted file mode 100644 index 2645268..0000000 --- a/Lectures/Week_02/sample.txt +++ /dev/null @@ -1,6 +0,0 @@ -Here's some content. - -More content. - - -And yet, content. diff --git a/Lectures/Week_02/week_2.ipynb b/Lectures/Week_02/week_2.ipynb new file mode 100644 index 0000000..21da3c3 --- /dev/null +++ b/Lectures/Week_02/week_2.ipynb @@ -0,0 +1,717 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Introduction Part II\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### February 27, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic File Input/Output (IO)\n", + "\n", + "---\n", + "\n", + "Types of Files:\n", + "* ASCII\n", + "* Binary" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Write an ASCII File" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "f = open('sample.txt', 'w')\n", + "contents = f.write('Here is some content.\\nMore content.\\n\\nAnd even more content.')\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read an ASCII File" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "f = open('sample.txt', 'r')\n", + "contents = f.read()\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Helpful\n", + "\n", + "1. `f.mode`\n", + "2. dir(f)\n", + "3. read(64) # reads 64-byte chunk\n", + "4. read() # reads entire file (puts file pointer at end of file after read)\n", + "5. readline()\n", + "6. readlines()\n", + "7. File access modes: (r, w, a, + versions, b versions)\n", + "\n", + "[Reading and Writing Files](http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A Better Way\n", + "\n", + "---\n", + "\n", + "```python\n", + "with open('sample.txt', 'r') as f:\n", + " contents = f.read()\n", + "```\n", + "\n", + "Why might this be better?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Deliminated Files\n", + "\n", + "---\n", + "\n", + "```python\n", + "import csv\n", + "f = open('my_file.csv', 'rb')\n", + "data = cvs.reader(f) # and writer\n", + "f.close()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Binary Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "s = \"Hello world!\"\n", + "with open('foo.bin','wb') as f:\n", + " f.write(s)\n", + "\n", + "with open('foo.bin','r') as f:\n", + " s = f.read()\n", + "print(s)\n", + "\n", + "# The differences between binary and ascii encoding won't be obvious for simple alphanumeric \n", + "# strings, but will become important if you're processing text that includes characters not \n", + "# in the ascii character set.\n", + "a = \"a\"\n", + "print(' '.join(format(ord(x), 'b') for x in a))\n", + "print int('1100001', 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is also the `pickle` module, but I will only say this: it is used to store data quickly, but not intended to store large amounts of data. It is binary and you create pickles of data and then unpickle the data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conditionals" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Booleans\n", + "\n", + "---\n", + "\n", + "Either `True` or `False` represent booleans. You can also use repsectively a 1 or 0 for binary booleans.\n", + "\n", + "What happens if you use the number 5 as a boolean?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### the `if` statement\n", + "\n", + "---\n", + "\n", + "```python\n", + "if conditional:\n", + " # Python statements when condition evaluates to True\n", + " # Indented for context\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if True:\n", + " print('This if statement is True.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### the `if`-`else` statement\n", + "\n", + "---\n", + "\n", + "```python\n", + "if conditional:\n", + " # python code\n", + "else another_conditional:\n", + " # python code when another_condition evaluates to True AND evaluates to False\n", + " # again, indented for context\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Note:__ You cannot have an __`else`__ statement without an __`if`__ statement." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### More Choices: the `elif` statement\n", + "\n", + "---\n", + "\n", + "```python\n", + "if conditional:\n", + " # python code\n", + "elif second:\n", + " # python code\n", + "elif third:\n", + " # python code\n", + "# and so on\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Note:__ Notice that there is no __`else`__ statement above. It is not required, but the __`else`__ statement is availble to be used if all the above conditionasl evaluate to be False." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# What's the output?\n", + "a = 5\n", + "if a > 10:\n", + " print('Door number 1.')\n", + "elif a == 2:\n", + " print('Door number 2.')\n", + "elif not True:\n", + " print('Door number 3.')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "if (1 != 2) or False:\n", + " print('Combined logic is fun!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Iterative Programming / Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### the `for` loop\n", + "\n", + "---\n", + "\n", + "```python\n", + "for item in iterable:\n", + " # Python code\n", + "```\n", + "\n", + "The `for` loop processes until the last element of iterable has been used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "total = 0\n", + "\n", + "for number in range(5):\n", + " # number = 0, 1, 2, 3, 4\n", + " total = total + 1\n", + "\n", + "print(total)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "students = ['Bob', 'Sue', 'Joe', 'Betty']\n", + "\n", + "for student in students[:2]:\n", + " # student is a temporary variable pointing to the current item\n", + " print(student)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Specifying a change of direction\n", + "\n", + "---\n", + "\n", + "Use the keywords __`continue`__, __`break`__, or __`pass`__ to change the behavior of conditionals and loops." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "total = 0\n", + "\n", + "for number in range(10):\n", + " if number == 5:\n", + " break\n", + " total = total + 1\n", + "\n", + "print(total)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### the `while` loop\n", + "\n", + "---\n", + "\n", + "```python\n", + "while condition:\n", + " # Python code\n", + "```\n", + "\n", + "The `while` loop continues to process indefinitely until `condition` evaluates to False." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "i = 50\n", + "\n", + "while i >= 7:\n", + " print(i)\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Warning!\n", + "\n", + "Think about your code before you run it. Without close inspection, you can create an infinite loop in your program." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Nested Loops\n", + "\n", + "As your programs become more and more complex, you will need to iterate over multiple items at once, such as subitems of an iterable's item. We can do this with nested loops.\n", + "\n", + "One example of this is 2D data (or a matrix). We can loop over the matrix by the columns then rows, or vice versa." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "x = np.array(range(20))\n", + "x = x.reshape(5,4)\n", + "print('x:')\n", + "print(x)\n", + "print('')\n", + "\n", + "for i in x: # rows\n", + " print(i)\n", + " for j in i: # columns\n", + " print(j)\n", + " print('')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NumPy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "li = [1,2,3,4,5]\n", + "arr = np.array([1,2,3,4,5])\n", + "print(arr)\n", + "print(type(arr))\n", + "print(type(li))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* Basic array construct is a `ndarray` for `n`-dimensional arrays, but we can have 1-D arrays too.\n", + "\n", + " (__Note:__ You usually don't create an `ndarray` directly, but through the `array` method.)\n", + " \n", + "* Behave like lists when they are 1-D.\n", + "* Biggest difference: all elements are of the same data type! This allows for much faster computation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(li[-1])\n", + "print(arr[-1])\n", + "\n", + "# let's try to change these\n", + "li[3] = 'a string'\n", + "arr[3] = -1\n", + "print(li)\n", + "print(arr)\n", + "\n", + "print(arr.dtype) # type for elements of array\n", + "arr = np.array([1.5, 2.5, 3.5, 4.5, 5.5, -6.5], dtype=np.uint8)\n", + "print(arr)\n", + "print(np.uint8(1.5))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arr = np.ones((3,2))\n", + "#print(arr)\n", + "arr = np.zeros((6,2))\n", + "#print(arr)\n", + "arr = np.empty((2,5,2), dtype=np.float64)\n", + "#print(arr)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arr = np.linspace(-5, 5, 11, dtype=np.int64) # start, stop, num\n", + "#print(arr)\n", + "\n", + "arr = np.logspace(0, 10, num=10, base=10., dtype=np.int64) # base ** start, base ** stop\n", + "#print(arr)\n", + "\n", + "arr = np.arange(-5, 500, 3, float) # start, stop, increment\n", + "#print(arr)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multidimensional Arrays" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arr = np.array([[0.2, 5.3],[7.4, 8.2]])\n", + "print(arr)\n", + "print(arr[:-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Array Operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arr = np.array([[0.2, 5.3],[7.4, 8.2]])\n", + "b = 3*arr -1\n", + "print(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "print(arr.mean())\n", + "print(arr.std())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reference Links\n", + "\n", + "* [NumPy Reference](http://docs.scipy.org/doc/numpy/reference/)\n", + "* [Tentative NumPy Tutorial](http://scipy.github.io/old-wiki/pages/Tentative_NumPy_Tutorial.html)\n", + "* [for MATLAB users](http://mathesaurus.sourceforge.net/matlab-numpy.html)\n", + "* [for R users](http://mathesaurus.sourceforge.net/r-numpy.html)\n", + "* [NumPy for Biologists](http://people.duke.edu/~ccc14/pcfb/numerics.html)\n", + "* [SciPy 2012 Video](http://www.youtube.com/watch?v=3Fp1zn5ao2M)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Matplotlib" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "x = [0,1,2,3,4,5]\n", + "y = [1,2,3,4,5,6]\n", + "plt.plot(x, y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# plot with legend\n", + "plt.plot(x, y, label='a line')\n", + "plt.legend(loc=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "x = np.linspace(-np.pi, np.pi, 256, endpoint=True)\n", + "cos, sin = np.cos(x), np.sin(x)\n", + "\n", + "plt.plot(x, cos)\n", + "plt.plot(x, sin)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multiple Figures - One Plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.figure(1)\n", + "plt.subplot(211)\n", + "plt.plot(x, cos)\n", + "\n", + "plt.subplot(212)\n", + "plt.plot(x, sin)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### References\n", + "\n", + "* [Matplotlib tutorial](http://www.labri.fr/perso/nrougier/teaching/matplotlib/)\n", + "* [gallery](http://matplotlib.org/gallery.html)\n", + "* [examples](http://matplotlib.org/examples/index.html)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b7ef81f71abfe1e4cc8b7edd6757db6c7c573958 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 27 Feb 2017 11:05:23 -0500 Subject: [PATCH 24/57] Corrected a couple typos --- Lectures/Week_02/week_2.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_02/week_2.ipynb b/Lectures/Week_02/week_2.ipynb index 21da3c3..9e1a140 100644 --- a/Lectures/Week_02/week_2.ipynb +++ b/Lectures/Week_02/week_2.ipynb @@ -117,7 +117,7 @@ "```python\n", "import csv\n", "f = open('my_file.csv', 'rb')\n", - "data = cvs.reader(f) # and writer\n", + "data = csv.reader(f) # and writer\n", "f.close()\n", "```" ] @@ -175,7 +175,7 @@ "\n", "---\n", "\n", - "Either `True` or `False` represent booleans. You can also use repsectively a 1 or 0 for binary booleans.\n", + "Either `True` or `False` represent booleans. You can also use respectively a 1 or 0 for binary booleans.\n", "\n", "What happens if you use the number 5 as a boolean?" ] @@ -254,7 +254,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "__Note:__ Notice that there is no __`else`__ statement above. It is not required, but the __`else`__ statement is availble to be used if all the above conditionasl evaluate to be False." + "__Note:__ Notice that there is no __`else`__ statement above. It is not required, but the __`else`__ statement is available to be used if all the above conditionals evaluate to be False." ] }, { @@ -307,7 +307,7 @@ " # Python code\n", "```\n", "\n", - "The `for` loop processes until the last element of iterable has been used." + "The `for` loop processes until the last element of the iterable has been used." ] }, { From cfac0fc41f460d72c8e01c6b3baeb353b48fbd14 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 27 Feb 2017 14:15:06 -0500 Subject: [PATCH 25/57] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fac8fea..4ad5d75 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. Copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. +3. After installing Anaconda, copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` From f07c9fc055d744aa2790cffd61c1de8ced5bb96c Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 27 Feb 2017 14:35:06 -0500 Subject: [PATCH 26/57] Added note about hidden folders --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ad5d75..d22c7d9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Python Training for the DEVELOP program. 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. After installing Anaconda, copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. +3. After installing Anaconda, copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. Note that AppData is a hidden folder, so you must either enable Windows Explorer to show hidden folders or type in the path by hand to the navigation bar of Windows Explorer. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt 5. `conda update conda` 6. `conda install netCDF4` From 241fb26c26944713f38a647d8f13c54222c92d9d Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 1 Mar 2017 09:38:39 -0500 Subject: [PATCH 27/57] lecture 3 --- Lectures/Week_03/week_3.ipynb | 540 ++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) create mode 100644 Lectures/Week_03/week_3.ipynb diff --git a/Lectures/Week_03/week_3.ipynb b/Lectures/Week_03/week_3.ipynb new file mode 100644 index 0000000..d0e044e --- /dev/null +++ b/Lectures/Week_03/week_3.ipynb @@ -0,0 +1,540 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# matplotlib and HDF\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### March 1, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# matplotlib\n", + "\n", + "---\n", + "\n", + "* [matplotlib Website](http://matplotlib.org)\n", + "* Visualization package of Python (2D/3d) meant to be a replacement for Matlab\n", + "* Version 2.0 is most recent (lots of fixes!)\n", + "* Earth Science visualizations - typically mixture of matplotlib and other packages for projections ([Basemap](http://matplotlib.org/basemap/), [cartopy](http://scitools.org.uk/cartopy/))\n", + "* [PlotLy](http://plot.ly) - javascript alternative\n", + "* [How to make beautiful data visualizations in Python with matplotlib](http://www.randalolson.com/2014/06/28/how-to-make-beautiful-data-visualizations-in-python-with-matplotlib/)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Basic Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "\n", + "#plt.plot(x, y, 'red-circle')\n", + "plt.plot(2.5, 4.1, 'ro')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ The statement __`%matplotlib inline`__ is only for the notebook and tells the interpreter to display the plot within the notebook.\n", + "\n", + "If you were to put this in a .py script, you will want either of the following:\n", + "\n", + "* __`plt.show()`__ if you are running a script and want to view the plot interactively.\n", + "* __`plt.savefig('filename.png')`__ if you want to save the image to a file." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Drawing a Line" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = [0,1,2,3,4,5]\n", + "y = [1,2,3,4,5,6]\n", + "plt.plot(x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding Features (Legend)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# plot with legend\n", + "plt.plot(x, y, label='a line')\n", + "plt.legend(loc=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multiple Lines" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "x = np.linspace(-np.pi, np.pi, 256, endpoint=True)\n", + "cos, sin = np.cos(x), np.sin(x)\n", + "\n", + "plt.plot(x, cos, label='cosine')\n", + "plt.plot(x, sin, label='sine')\n", + "plt.legend()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multiple Plots, Single Figure" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.figure(1)\n", + "plt.subplot(211)\n", + "plt.plot(x, cos, color='C0') # notice the color name\n", + "\n", + "plt.subplot(212)\n", + "plt.plot(x, sin, color='C1')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "---\n", + "\n", + "# NOTICE\n", + "\n", + "---\n", + "\n", + "__Run this line from your Anaconda Prompt (March 1, 2017)__\n", + "```bash\n", + "conda update hdf4\n", + "```\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Heirarchical Data Format (HDF)\n", + "\n", + "---\n", + "\n", + "Two types of HDF files:\n", + "* [HDF5](http://www.hdfgroup.org): A structured file of groups of fields of variables of dimensions. ([h5py](http://www.h5py.org))\n", + "* [netCDF](http://www.unidata.ucar.edu/software/netcdf/): A simpler HDF file with only one group (netCDF3 and older do not support groups) of fields of variables of dimensions. ([netCDF4](http://unidata.github.io/netcdf4-python/))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating Files" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import netCDF4 as nc\n", + "\n", + "f = nc.Dataset('test.nc', 'w')\n", + "f.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import h5py as h5\n", + "\n", + "f = h5.File('test.h5', 'w')\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Looking inside\n", + "\n", + "---\n", + "\n", + "From Anaconda Prompt:\n", + "\n", + "```bash\n", + "ncdump -h filename.nc\n", + "\n", + "ncdump -h filename.h5\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Structure\n", + "\n", + "---\n", + "\n", + "* Groups\n", + "* Dimensions\n", + "* Variables\n", + "* Attributes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Groups" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# netCDF\n", + "rootgrp = nc.Dataset('test.nc', 'a')\n", + "fcstgrp = rootgrp.createGroup('forecasts')\n", + "anlgrp = rootgrp.createGroup('analyses')\n", + "\n", + "# we can also create them like folders\n", + "fcst1 = rootgrp.createGroup('/forecasts/model1')\n", + "fcst2 = rootgrp.createGroup('/forecasts/model2')\n", + "\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# HDF\n", + "rootgrp = h5.File('test.h5', 'a')\n", + "fcstgrp = rootgrp.create_group('forecasts')\n", + "anlgrp = rootgrp.create_group('analyses')\n", + "\n", + "# can again also create like folders\n", + "fcst1 = rootgrp.create_group('/forecasts/model1')\n", + "fcst2 = rootgrp.create_group('/forecasts/model2')\n", + "\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "root group (NETCDF4 data model, file format HDF5):\n", + " dimensions(sizes): \n", + " variables(dimensions): \n", + " groups: forecasts, analyses\n", + "\n", + "\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# let's look inside these:\n", + "f = nc.Dataset('test.nc', 'r')\n", + "print(f)\n", + "#print('\\n')\n", + "#print(f.groups)\n", + "f.close()\n", + "\n", + "print('\\n')\n", + "\n", + "f = h5.File('test.h5', 'r')\n", + "print(f)\n", + "#print(f.keys())\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dimensions" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# netCDF (netCDF3 can only have 1 unlimmited dimension)\n", + "rootgrp = nc.Dataset('test.nc', 'a')\n", + "level = rootgrp.createDimension('level', None) # or 0\n", + "time = rootgrp.createDimension('time', None) # or 0\n", + "lat = rootgrp.createDimension('lat', 73)\n", + "lon = rootgrp.createDimension('lon', 144)\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# HDF doesn't really have dimensions" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OrderedDict([(u'level', (unlimited): name = 'level', size = 0\n", + "), (u'time', (unlimited): name = 'time', size = 0\n", + "), (u'lat', : name = 'lat', size = 73\n", + "), (u'lon', : name = 'lon', size = 144\n", + ")])\n" + ] + } + ], + "source": [ + "# let's look inside these:\n", + "f = nc.Dataset('test.nc', 'r')\n", + "print(f.dimensions)\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Variables" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from numpy.random import uniform" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# netCDF\n", + "rootgrp = nc.Dataset('test.nc', 'a')\n", + "times = rootgrp.createVariable('time', 'f8', ('time',))\n", + "levels = rootgrp.createVariable('level', 'i4', ('level',))\n", + "latitudes = rootgrp.createVariable('latitude', 'f4', ('lat',))\n", + "longitudes = rootgrp.createVariable('longitude', 'f4', ('lon',))\n", + "\n", + "temp = rootgrp.createVariable('temp', 'f4', ('time','level','lat','lon',))\n", + "\n", + "# write some sample data\n", + "latitudes[:] = np.arange(-90, 91, 2.5)\n", + "longitudes[:] = np.arange(-180, 180, 2.5)\n", + "levels[:] = [1000., 850., 700., 500., 300., 250., 200., 150., 100., 50.]\n", + "temp[0:5, 0:10, :, :] = uniform(size=(5,10,len(latitudes), len(longitudes)))\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# HDF (has datasets)\n", + "rootgrp = h5.File('test.h5', 'a')\n", + "# maxshape is only if you need unlimited dimensions\n", + "temp = rootgrp.create_dataset('temp', (5,10, 73, 144,), maxshape=(None, None, 73, 144), dtype='f4')\n", + "# here, you just assign data to temp\n", + "temp[:] = uniform(size=(5, 10, 73, 144))\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[u'time', u'level', u'latitude', u'longitude', u'temp']\n", + "[[ 0.64189696 0.93760121 0.57146317 0.80668706]\n", + " [ 0.61306697 0.62045872 0.08019656 0.50558686]\n", + " [ 0.541444 0.43847674 0.64054775 0.87512076]\n", + " [ 0.54317957 0.51097864 0.32800439 0.41129491]]\n", + "\n", + "[[ 0.41212252 0.04802058 0.88053972 0.18834125]\n", + " [ 0.06324196 0.02606479 0.8399592 0.9500618 ]\n", + " [ 0.8730737 0.61149395 0.36391962 0.07006889]\n", + " [ 0.80869991 0.72067267 0.46312308 0.82502639]]\n" + ] + } + ], + "source": [ + "# let's look inside these:\n", + "rootgrp = nc.Dataset('test.nc', 'a')\n", + "print(rootgrp.variables.keys())\n", + "print(rootgrp.variables['temp'][0,0,[0,1,2,3],[0,1,2,3]])\n", + "rootgrp.close()\n", + "\n", + "rootgrp = h5.File('test.h5', 'r')\n", + "print(rootgrp['temp'])\n", + "print(rootgrp['temp'][0, 0, 0:4, 0:4])\n", + "rootgrp.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Attributes\n", + "\n", + "---\n", + "\n", + "This is just the metadata for the variables/groups." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 544cf54315caac06aeb23f6c7b578908928cc9b6 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Wed, 1 Mar 2017 09:39:51 -0500 Subject: [PATCH 28/57] removed output --- Lectures/Week_03/week_3.ipynb | 75 +++++++---------------------------- 1 file changed, 15 insertions(+), 60 deletions(-) diff --git a/Lectures/Week_03/week_3.ipynb b/Lectures/Week_03/week_3.ipynb index d0e044e..75bd457 100644 --- a/Lectures/Week_03/week_3.ipynb +++ b/Lectures/Week_03/week_3.ipynb @@ -202,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "collapsed": false }, @@ -216,7 +216,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "collapsed": true }, @@ -268,7 +268,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "collapsed": true }, @@ -288,7 +288,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "collapsed": true }, @@ -308,27 +308,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "root group (NETCDF4 data model, file format HDF5):\n", - " dimensions(sizes): \n", - " variables(dimensions): \n", - " groups: forecasts, analyses\n", - "\n", - "\n", - "\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# let's look inside these:\n", "f = nc.Dataset('test.nc', 'r')\n", @@ -354,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "collapsed": true }, @@ -371,7 +355,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "collapsed": true }, @@ -382,23 +366,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "OrderedDict([(u'level', (unlimited): name = 'level', size = 0\n", - "), (u'time', (unlimited): name = 'time', size = 0\n", - "), (u'lat', : name = 'lat', size = 73\n", - "), (u'lon', : name = 'lon', size = 144\n", - ")])\n" - ] - } - ], + "outputs": [], "source": [ "# let's look inside these:\n", "f = nc.Dataset('test.nc', 'r')\n", @@ -415,7 +387,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "collapsed": true }, @@ -427,7 +399,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "collapsed": true }, @@ -452,7 +424,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "collapsed": true }, @@ -469,28 +441,11 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[u'time', u'level', u'latitude', u'longitude', u'temp']\n", - "[[ 0.64189696 0.93760121 0.57146317 0.80668706]\n", - " [ 0.61306697 0.62045872 0.08019656 0.50558686]\n", - " [ 0.541444 0.43847674 0.64054775 0.87512076]\n", - " [ 0.54317957 0.51097864 0.32800439 0.41129491]]\n", - "\n", - "[[ 0.41212252 0.04802058 0.88053972 0.18834125]\n", - " [ 0.06324196 0.02606479 0.8399592 0.9500618 ]\n", - " [ 0.8730737 0.61149395 0.36391962 0.07006889]\n", - " [ 0.80869991 0.72067267 0.46312308 0.82502639]]\n" - ] - } - ], + "outputs": [], "source": [ "# let's look inside these:\n", "rootgrp = nc.Dataset('test.nc', 'a')\n", From 15b21326b7f7463160cf28f0268f1d706e132d8b Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sat, 4 Mar 2017 16:06:13 -0500 Subject: [PATCH 29/57] Fixed else typo --- Lectures/Week_02/week_2.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lectures/Week_02/week_2.ipynb b/Lectures/Week_02/week_2.ipynb index 9e1a140..0f89e3e 100644 --- a/Lectures/Week_02/week_2.ipynb +++ b/Lectures/Week_02/week_2.ipynb @@ -218,8 +218,8 @@ "```python\n", "if conditional:\n", " # python code\n", - "else another_conditional:\n", - " # python code when another_condition evaluates to True AND evaluates to False\n", + "else:\n", + " # python code when condition evaluates to False\n", " # again, indented for context\n", "```" ] From 7f8df2e445a96f326a0a40484f95f7d47133f88d Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 6 Mar 2017 08:06:31 -0500 Subject: [PATCH 30/57] Add files via upload --- Lectures/Week_04/week_4.ipynb | 514 ++++++++++++++++++++++++++++++++++ 1 file changed, 514 insertions(+) create mode 100644 Lectures/Week_04/week_4.ipynb diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb new file mode 100644 index 0000000..350c08a --- /dev/null +++ b/Lectures/Week_04/week_4.ipynb @@ -0,0 +1,514 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# GIS Automation through ArcPy\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### March 6, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ArcPy\n", + "\n", + "---\n", + "\n", + "* Python module created by Esri to allow ArcGIS tools to be called from Python\n", + "* This enables all manner of geoprocessing to be done in an automated fashion, as ArcPy can replicate most of the functionality of ArcGIS for Desktop\n", + "* While ArcGIS comes with its own version of Python, ArcPy can be used with other Python installations, as we will do in this course\n", + "* For reference, see the documentation for your version of ArcGIS. The help page for each tool has a description of the Python syntax and (usually) short example scripts.\n", + " * For instance: http://desktop.arcgis.com/en/arcmap/10.4/tools/data-management-toolbox/clip.htm (scroll down)\n", + "* Another resource: [Penn State online course](https://www.e-education.psu.edu/geog485/node/91) covering the same subject matter as this lecture, GIS automation with Python.\n", + "* Possibly the best resource of all: Google\n", + " * While not as well supported as the really popular Python packages (i.e. NumPy, matplotlib, etc.), enough people use ArcPy that you will find decent support on forums like Stack Overflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example Project: Fun with MODIS LST Data\n", + "\n", + "---\n", + "\n", + "* To get a feel for automating typical GIS tasks, we will work through a short project where we:\n", + " * download some MODIS land surface temperature (LST) data\n", + " * extract the bands we want to GeoTIFF\n", + " * perform some analysis, including raster math and conditionals\n", + " * resample the output\n", + " * ... and repeat\n", + "\n", + "### Test ArcPy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import arcpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download data\n", + "\n", + "---\n", + "\n", + "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "\n", + "Copy it to the directory where you want to store your data.\n", + "\n", + "### Set working directory\n", + "\n", + "---\n", + "\n", + "ArcPy needs to know where to look for inputs and save outputs on your computer. You can specify an absolute path for every file, meaning a path including not only the file name but all the parent directories, including the drive name (i.e. C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\\\\thatwasalotoftyping.tif). However, this can grow tedious, so it is usually easier to set the workspace environment (more on these later) to a location of your choosing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Change this path to the directory where you saved the MODIS data in the above step. Now, all you need to provide is a file name, and ArcPy will automatically go to this folder.\n", + "\n", + "Another consideration is that, by default, ArcPy will not permit you to overwrite files that already exist. When you are developing a script, this is usually not what you want (but not always - be careful!). Allow ArcPy to overwrite output as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.overwriteOutput = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract from HDF to GeoTIFF\n", + "\n", + "---\n", + "\n", + "With many data types, we would be ready to jump straight in to geoprocessing. However, with MODIS data we have an immediate hurdle: HDF. Fully-featured handling of HDF files requires special Python packages, like h5py, as covered in the previous lecture. For our project, however, this would be overkill. Instead, we can use ArcPy's Extract SubDataset to pull out the data we want into a GeoTIFF.\n", + "\n", + "Let's extract the daytime LST data, which is subdataset 0:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "day_LST = MODIS_file.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, day_LST, subdataset_index=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To inspect the output, open ArcMap and load this file. Add an imagery basemap as well and compare the two, noting areas of high and low temperature values. Do you see anything strange?\n", + "\n", + "### Perform analysis\n", + "\n", + "---\n", + "\n", + "#### Raster Math\n", + "\n", + "The above data has been scaled to allow it to be stored in an integer format, but this makes it difficult to interpret. To convert it back to Kelvin, we must apply the scale factor, which in this case is 0.02. To do this, we will perform some raster math." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "day_LST_sc = arcpy.Raster(day_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ArcPy allows basic math operations to be applied on a pixel-by-pixel basis with Python syntax, but it is necessary to create an ArcPy Raster object from your raster file on disk. The math operation returns another ArcPy Raster object, which we have assigned to __day_LST_sc__. Think of these Raster objects in an analogous manner to the data types we covered before, like string, float, int, etc. They can be used in other math operations and passed to some (but not all) ArcGIS tools that take raster input.\n", + "\n", + "Notice the lines before and after the middle block. Raster math requires the Spatial Analyst extension, so it is necessary to check out a license for this extension first. Checking the license back in at the end is not necessary for the code to function, but it is good practice, because your organization may have a license server with limited keys.\n", + "\n", + "At the moment, our scaled daytime LST raster only exists in memory - we have not saved it to disk. To do so:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "path = MODIS_file.rstrip(\".hdf\") + \"_scale.tif\"\n", + "day_LST_sc.save(path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Math with multiple rasters\n", + "\n", + "In a similar manner, two or more rasters can be used in a formula using simple Python syntax. But first, we need two rasters! Let's repeat the above steps with the nighttime LST band (subdataset 4), from the same MODIS file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "night_LST = MODIS_file.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, night_LST, subdataset_index=4)\n", + "\n", + "scale = 0.02\n", + "night_LST_sc = arcpy.Raster(night_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ In this case, we did not save the scaled raster to disk. This is not actually necessary to use it in later operations, and not saving intermediates is a good way to conserve disk space.\n", + "\n", + "Now, let's compute the difference between the daytime and nighttime LST:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "diff = day_LST_sc - night_LST_sc\n", + "diff.save(MODIS_file.rstrip(\".hdf\")+\"_diff.tif\")\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This will create a new Raster object where each pixel corresponds to the difference between the two old rasters. Open this new raster in ArcMap and compare it to a basemap.\n", + "\n", + "#### Conditionals\n", + "\n", + "Suppose we want to know where the above difference exceeds a certain threshold. We can answer this question using the Con tool, available with the Spatial Analyst extension." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "thres = 15\n", + "diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + "diff_thres.save(MODIS_file.rstrip(\".hdf\")+\"_thres.tif\")\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The middle block of code will create and save a raster that contains a 1 wherever the day-night difference exceeds 15, and a 0 wherever it does not.\n", + "\n", + "### Resample\n", + "\n", + "---\n", + "\n", + "We now have a nice Boolean raster that we could use as a mask in some larger project. However, what if the other members of our project are working with the MODIS red and NIR bands, which are 250 m resolution? We can be helpful, and resample our raster to this resolution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "out_cellsize = 231.6563583\n", + "res = MODIS_file.rstrip(\".hdf\") + \"_res.tif\"\n", + "arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could have performed this resampling at any point in our processing chain, but we chose to do so at the end. Why might this be best?\n", + "\n", + "### Repeat as necessary\n", + "\n", + "---\n", + "\n", + "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", + "\n", + "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", + "* winter: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", + "* spring: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", + "* and fall: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", + "\n", + "Move these to the same folder you have been using.\n", + "\n", + "Now, let's put everything we did above in a loop:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff.save(f.rstrip(\".hdf\")+\"_diff.tif\")\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres.save(f.rstrip(\".hdf\")+\"_thres.tif\")\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Tip:_ If you need to get the names of many files in a folder and don't want to do a lot of tedious typing, check out the [glob](https://docs.python.org/2/library/glob.html) module.\n", + "\n", + "\n", + "\n", + "# Other Considerations\n", + "\n", + "---\n", + "\n", + "### Environments\n", + "\n", + "---\n", + "\n", + "ArcGIS uses environment settings to control the specific characteristics of your current geoprocessing environment. In the above script, we are using two already: workspace and overwrite output. Environments are a powerful way to control the exact way in which your script executes. As another example, let's say that within our MODIS tile, we only really care about Virginia (because it is objectively better than all of these other states), and we want to limit output to this state.\n", + "\n", + "One approach might be to clip each input raster with a shapefile, but we have to do this for each input. In this case, we only have two per iteration, but in other projects we might have a lot more. A more elegant approach is to use the mask environment setting.\n", + "\n", + "Download [this](https://drive.google.com/file/d/0B8toI67HoVSrVzV3aUcwc3FBcG8/view?usp=sharing) shapefile of Virginia, and extract it to your work directory. Then, rerun our script with the mask environment set at the top:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.env.mask = \"Virginia.shp\"\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff.save(f.rstrip(\".hdf\")+\"_diff.tif\")\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres.save(f.rstrip(\".hdf\")+\"_thres.tif\")\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")\n", + "\n", + "arcpy.env.workspace = None\n", + "arcpy.env.overwriteOutput = None\n", + "arcpy.env.mask = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspect the output. If everything worked properly, you should only see data over the scenic Commonwealth of Virginia\n", + "\n", + "__Very important note:__ The nature of environment settings is that they apply to your _entire processing environment_, which means they will stick around for future processes you run in the same session of Python. Old environment settings can lead to mysterious errors, confusion, and general gnashing of teeth. I highly recommend that you clear out your environment settings at the end of your script by setting them to `None`, as I have done above. Even better, clear them immediately after they are no longer needed, in case your script crashes before it completes.\n", + "\n", + "### Editing locks\n", + "\n", + "---\n", + "\n", + "Whenever a program is using a file, it creates a lock that prevents other programs from editing the same file. Python is no different. In general, these should disappear after a script is finished executing. For reasons that are not entirely clear to me, ArcPy often retains locks on ArcPy objects created by a script even said script has completed. This will create problems if you then try to edit the file that object is pointing to in a different program. Therefore, it is also good practice to clear variables that point to ArcPy objects after they are no longer necessary. To accomplish that in our script, add the following to the end:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "day_LST_sc = None\n", + "night_LST_sc = None\n", + "diff = None\n", + "diff_thres = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On the other side of the same coin, Python will not be able to edit a file that is locked by another application. In the context of geoprocessing, this can happen because you ran your code, viewed the output in ArcMap, and tried to rerun your code without removing said output from ArcMap. Some of you may have already experienced this phenomenon during this lesson. If you're me, this happens _all the time_..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From c012e8315dc3f10620e180f1ca2ec79f62583c73 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 6 Mar 2017 08:11:52 -0500 Subject: [PATCH 31/57] Format tweaks --- Lectures/Week_04/week_4.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index 350c08a..5e70d16 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -75,7 +75,8 @@ "\n", "---\n", "\n", - "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "Download this MODIS image: \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", From ff40bc6f981a36a0358ff5add78ebf47b87770cb Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 6 Mar 2017 08:13:16 -0500 Subject: [PATCH 32/57] More formatting --- Lectures/Week_04/week_4.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index 5e70d16..b8b1a97 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -76,7 +76,7 @@ "---\n", "\n", "Download this MODIS image: \n", - "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf\n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", From 6a700dce9137711b132b7c3ea9dd4db6b627b681 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 6 Mar 2017 08:43:51 -0500 Subject: [PATCH 33/57] text fix --- Lectures/Week_04/week_4.ipynb | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index b8b1a97..447f6f9 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -75,8 +75,8 @@ "\n", "---\n", "\n", - "Download this MODIS image: \n", - "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf\n", + "Download this MODIS image: \n", + "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf_\n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", @@ -179,7 +179,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "ArcPy allows basic math operations to be applied on a pixel-by-pixel basis with Python syntax, but it is necessary to create an ArcPy Raster object from your raster file on disk. The math operation returns another ArcPy Raster object, which we have assigned to __day_LST_sc__. Think of these Raster objects in an analogous manner to the data types we covered before, like string, float, int, etc. They can be used in other math operations and passed to some (but not all) ArcGIS tools that take raster input.\n", + "ArcPy allows basic math operations to be applied on a pixel-by-pixel basis with Python syntax, but it is necessary to create an ArcPy Raster object from your raster file on disk. The math operation returns another ArcPy Raster object, which we have assigned to __day_LST_sc__. Think of these Raster objects in an analogous manner to the data types we covered before, like `string`, `float`, `int`, etc. They can be used in other math operations and passed to some (but not all) ArcGIS tools that take raster input.\n", "\n", "Notice the lines before and after the middle block. Raster math requires the Spatial Analyst extension, so it is necessary to check out a license for this extension first. Checking the license back in at the end is not necessary for the code to function, but it is good practice, because your organization may have a license server with limited keys.\n", "\n", @@ -275,7 +275,7 @@ "\n", "thres = 15\n", "diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", - "diff_thres.save(MODIS_file.rstrip(\".hdf\")+\"_thres.tif\")\n", + "diff_thres.save(MODIS_file.rstrip(\".hdf\") + \"_thres.tif\")\n", "\n", "arcpy.CheckInExtension(\"spatial\")" ] @@ -319,9 +319,12 @@ "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", "\n", "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", - "* winter: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", - "* spring: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", - "* and fall: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", + "* winter: \n", + "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf_\n", + "* spring: \n", + "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf_\n", + "* and fall: \n", + "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf_\n", "\n", "Move these to the same folder you have been using.\n", "\n", @@ -381,7 +384,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "_Tip:_ If you need to get the names of many files in a folder and don't want to do a lot of tedious typing, check out the [glob](https://docs.python.org/2/library/glob.html) module.\n", + "> _Tip:_ If you need to get the names of many files in a folder and don't want to do a lot of tedious typing, check out the [glob](https://docs.python.org/2/library/glob.html) module.\n", "\n", "\n", "\n", @@ -393,7 +396,7 @@ "\n", "---\n", "\n", - "ArcGIS uses environment settings to control the specific characteristics of your current geoprocessing environment. In the above script, we are using two already: workspace and overwrite output. Environments are a powerful way to control the exact way in which your script executes. As another example, let's say that within our MODIS tile, we only really care about Virginia (because it is objectively better than all of these other states), and we want to limit output to this state.\n", + "ArcGIS uses environment settings to control the specific characteristics of your current geoprocessing environment. In the above script, we are using two already: workspace and overwriting output. Environments are a powerful way to control the exact way in which your script executes. As another example, let's say that within our MODIS tile, we only really care about Virginia (because it is objectively better than all of these other states), and we want to limit output to this state.\n", "\n", "One approach might be to clip each input raster with a shapefile, but we have to do this for each input. In this case, we only have two per iteration, but in other projects we might have a lot more. A more elegant approach is to use the mask environment setting.\n", "\n", @@ -458,7 +461,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Inspect the output. If everything worked properly, you should only see data over the scenic Commonwealth of Virginia\n", + "Inspect the output. If everything worked properly, you should only see data over the scenic Commonwealth of Virginia.\n", "\n", "__Very important note:__ The nature of environment settings is that they apply to your _entire processing environment_, which means they will stick around for future processes you run in the same session of Python. Old environment settings can lead to mysterious errors, confusion, and general gnashing of teeth. I highly recommend that you clear out your environment settings at the end of your script by setting them to `None`, as I have done above. Even better, clear them immediately after they are no longer needed, in case your script crashes before it completes.\n", "\n", From fea6845ef8e582bb32867127519d47e6aa9f1c51 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 6 Mar 2017 16:20:27 -0500 Subject: [PATCH 34/57] link update --- Lectures/Week_04/week_4.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index 447f6f9..cc35a70 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -76,7 +76,7 @@ "---\n", "\n", "Download this MODIS image: \n", - "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf_\n", + "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_\n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", @@ -320,11 +320,11 @@ "\n", "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", "* winter: \n", - "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf_\n", + "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_\n", "* spring: \n", - "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf_\n", + "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_\n", "* and fall: \n", - "_ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf_\n", + "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_\n", "\n", "Move these to the same folder you have been using.\n", "\n", From 1c9e6e9270bef517152714911486bfe1200f1e96 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 6 Mar 2017 16:27:34 -0500 Subject: [PATCH 35/57] ftp fix --- Lectures/Week_04/week_4.ipynb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index cc35a70..a0364e7 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -75,8 +75,7 @@ "\n", "---\n", "\n", - "Download this MODIS image: \n", - "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_\n", + "Download this _[MODIS image](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_.\n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", @@ -319,12 +318,9 @@ "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", "\n", "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", - "* winter: \n", - "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_\n", - "* spring: \n", - "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_\n", - "* and fall: \n", - "_[ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_\n", + "* _[winter](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_\n", + "* _[spring](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_\n", + "* and _[fall](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_\n", "\n", "Move these to the same folder you have been using.\n", "\n", From bba0e0f906847dbfdf765034cfdd800243dce752 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 6 Mar 2017 16:31:37 -0500 Subject: [PATCH 36/57] ftp again --- Lectures/Week_04/week_4.ipynb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index a0364e7..bfd1648 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -75,7 +75,8 @@ "\n", "---\n", "\n", - "Download this _[MODIS image](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_.\n", + "Download this _[MODIS image](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_. \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf\n", "\n", "Copy it to the directory where you want to store your data.\n", "\n", @@ -318,9 +319,12 @@ "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", "\n", "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", - "* _[winter](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_\n", - "* _[spring](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_\n", - "* and _[fall](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_\n", + "* _[winter](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_ \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", + "* _[spring](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_ \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", + "* and _[fall](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_ \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", "\n", "Move these to the same folder you have been using.\n", "\n", From eedde2cc7feef86cab80585132137c24939642d3 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 6 Mar 2017 16:38:15 -0500 Subject: [PATCH 37/57] ftp github issue --- Lectures/Week_04/week_4.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lectures/Week_04/week_4.ipynb b/Lectures/Week_04/week_4.ipynb index bfd1648..094782a 100644 --- a/Lectures/Week_04/week_4.ipynb +++ b/Lectures/Week_04/week_4.ipynb @@ -75,7 +75,7 @@ "\n", "---\n", "\n", - "Download this _[MODIS image](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf)_. \n", + "Download this _MODIS image_. \n", "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf\n", "\n", "Copy it to the directory where you want to store your data.\n", @@ -319,11 +319,11 @@ "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", "\n", "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", - "* _[winter](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf)_ \n", + "* _winter_ \n", "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", - "* _[spring](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf)_ \n", + "* _spring_ \n", "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", - "* and _[fall](ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf)_ \n", + "* and _fall_ \n", "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", "\n", "Move these to the same folder you have been using.\n", From 858f04e42260ab21fd9e0d8b2ea79006f7eec882 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 13 Mar 2017 14:13:47 -0400 Subject: [PATCH 38/57] Week 5 lecture uploaded --- Lectures/week_5.ipynb | 458 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 Lectures/week_5.ipynb diff --git a/Lectures/week_5.ipynb b/Lectures/week_5.ipynb new file mode 100644 index 0000000..3b84f88 --- /dev/null +++ b/Lectures/week_5.ipynb @@ -0,0 +1,458 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# GDAL\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### March 13, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# What is GDAL?\n", + "\n", + "---\n", + "\n", + "* __Geospatial Data Abstraction Library__ - A programmatic way to do geoprocessing, providing similar capabilities to those available in ArcGIS\n", + "* Useful for building automated systems, performing repetitive analysis, etc.\n", + "* Developed by Frank Warmerdam, Sean Gilles, et al.\n", + "* Both ArcGIS and QGIS use GDAL \"under the hood\"\n", + "* When people say GDAL, they really mean the GDAL sub-library of the OSGeo (Open Source Geospatial Foundation) package. OSGeo has two sub-libraries:\n", + " * gdal - reading, processing, writing raster data\n", + " * ogr - reading, processing, writing vector data\n", + " * This lecture will only cover gdal, but note that you will need ogr to do anything significant with vector data\n", + "* GDAL has been built to work with several different languages, including Python, R, C, and C++, but some of its most useful capabilities exist as standalone command line tools - essentially, these are their own little programs that can only be started through the command line\n", + " * We will look at both the GDAL Python functions and some of the most useful command line tools\n", + "* [OSGeo site](http://osgeo.org)\n", + "* [GDAL Python reference](http://gdal.org/python/)\n", + "* [GDAL Python tips](https://trac.osgeo.org/gdal/wiki/PythonGotchas)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# GDAL vs. ArcPy - Pros and Cons\n", + "\n", + "---\n", + "\n", + "* GDAL is faster and more accurate\n", + "* GDAL typically provides more flexibility and control\n", + "* Some things can be done in GDAL that simply aren't possible (to my knowledge) in ArcGIS, such as reprojecting between certain coordinate systems\n", + "* GDAL is free and open source\n", + "* However, GDAL is significantly less user-friendly, because:\n", + " * There is no GUI version of the software, like ArcMap for ArcGIS\n", + " * The documentation is primarily written for programmers, and is generally light on explanation\n", + "* To summarize, you can expect a steep learning curve with GDAL, but you will ultimately be able to do some cool stuff" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Example Project: More fun with MODIS\n", + "\n", + "---\n", + "\n", + "To explore GDAL and allow comparisons between GDAL and ArcPy, we will examine some of the same steps we took in our project last week, namely:\n", + "* Extracting a single subdataset from a MODIS HDF file\n", + "* Opening this data with Python and doing some math\n", + "* Writing the modified data back to disk\n", + "\n", + "We will also perform a new step, which is not possible with ArcGIS: reprojecting the data from its native sinusoidal coordinate system to WGS 1984.\n", + "\n", + "__Important:__ Before beginning this lecture, you should have followed the GDAL installation instructions, available from the root directory of the DEVELOP Python GitHub." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download data\n", + "\n", + "---\n", + "\n", + "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "\n", + "Copy it to the directory where you want to store your data. You may already have this image from last week's ArcPy lecture.\n", + "\n", + "### Get metadata\n", + "\n", + "---\n", + "\n", + "We want to extract a subdataset from this HDF file, but suppose we don't know what that subdataset is called? Navigate to your working directory, and type the following in the command line:\n", + "\n", + "```> gdalinfo MOD11A2.A2016201.h11v05.006.2016242234243.hdf```\n", + "\n", + "This is a lot of information, but it should look familiar from the HDF/netCDF lecture. If you look closely, you will seen the names and descriptions of each subdataset. For example, the full name of the daytime LST subdataset is ```HDF4_EOS:EOS_GRID:\"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\":MODIS_Grid_8Day_1km_LST:LST_Day_1km```\n", + "\n", + "### Extract subdataset\n", + "\n", + "---\n", + "\n", + "To extract the daytime LST subdataset, we will use one of the most useful GDAL command line tools: ```gdal_translate```. This tool is most commonly used for converting data from one file format to another. If you don't have experience running command line tools, the general format is:\n", + "* Name of tool first\n", + "* Optional parameters specified as ```-OptParam ArgumentForOptParam```\n", + "* Required arguments\n", + "\n", + "In the case of ```gdal_translate```, there are two required arguments: the names of the input and output files. There are also numerous optional arguments that can be used to pack in additional functionality, such as altering the output bit depth and resampling the data. To extract the subdataset, go to your command line and type:\n", + "\n", + "```> gdal_translate HDF4_EOS:EOS_GRID:\"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\":MODIS_Grid_8Day_1km_LST:LST_Day_1km MOD11A2.A2016201.h11v05.006.2016242234243_dayLST.tif```\n", + "\n", + "In this case, we are not using any optional arguments, merely providing the name of the subdataset we care about and an output file name. Now, even with copy/pasting, tab-filling, etc., it would be tedious to do this for numerous images. Let's take a look at how we might call this command from Python, using the ```subprocess``` module." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('Input file size is 1200, 1200\\r\\n0...10...20...30...40...50...60...70...80...90...100 - done.\\r\\n', '')\n" + ] + } + ], + "source": [ + "import subprocess\n", + "import os\n", + "\n", + "#Change system to working directory\n", + "workdir = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "os.chdir(workdir)\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "\n", + "#Send gdal_translate command to system shell, capture result, and print it\n", + "dayLST_fname = MODIS_file.rstrip('.hdf')+'_GDAL_dayLST.tif'\n", + "trans_day_cmd = ['gdal_translate', 'HDF4_EOS:EOS_GRID:\"'+MODIS_file+\\\n", + " '\":MODIS_Grid_8Day_1km_LST:LST_Day_1km', dayLST_fname]\n", + "p_trans_day = subprocess.Popen(trans_day_cmd, stdout=subprocess.PIPE, \n", + " stderr=subprocess.PIPE)\n", + "print(p_trans_day.communicate())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ```subprocess.Popen``` takes a list of string arguments that comprise your command. Every separate element of a command should be its own element in this list. Note that this includes the name of an optional parameter and the argument for that parameter.\n", + "\n", + "Optionally, ```subprocess.Popen``` also allows us to capture the ```stdout``` and ```stderr``` streams. These are the output and error streams for programs run in the command line, and contain output messages and errors, respectively. It is common to save these to a text file to view later, but in this case we are just printing them using the ```communicate()``` method.\n", + "\n", + "### Opening raster data in Python\n", + "\n", + "---\n", + "\n", + "We have just covered an example of using GDAL command line tools, and calling those tools from Python. As mentioned above, many of GDAL's most useful capabilities are command line tools such as this, but GDAL also has a Python-specific library that allows us to perform some operations entirely in Python, without sending any commands to the system. In some cases, this Python library duplicates the capabilities of the command line tools, and in that case, it is generally better to use the command line tool, as they tend to be better supported. However, the Python library allows us to do some uniquely cool things, such as opening a raster as a NumPy array." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "from osgeo import gdal\n", + "import numpy as np\n", + "\n", + "gdal.UseExceptions()\n", + "\n", + "#Change system to working directory\n", + "workdir = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "os.chdir(workdir)\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "dayLST_fname = MODIS_file.rstrip('.hdf')+'_GDAL_dayLST.tif'\n", + "\n", + "#Register driver for this file type\n", + "driver = gdal.GetDriverByName(\"GTiff\")\n", + "driver.Register()\n", + "#Open raster as GDAL dataset\n", + "dayLST_dataset = gdal.Open(dayLST_fname)\n", + "#Get geotransform and projection from GDAL dataset. These contain \n", + "#the geospatial information of the data, and we will need them \n", + "#later to write the array back to a raster file.\n", + "geotrans = dayLST_dataset.GetGeoTransform()\n", + "proj = dayLST_dataset.GetProjection()\n", + "#Open the only band in the dataset. Note that band numbering \n", + "#starts from 1 as far as GDAL is concerned.\n", + "dayLST_band = dayLST_dataset.GetRasterBand(1)\n", + "#Pull data from band into a NumPy array\n", + "dayLST_array = dayLST_band.ReadAsArray()\n", + "#Get the NoData value for this band\n", + "fillval = dayLST_band.GetNoDataValue()\n", + "#Create a new masked array, where all areas of NoData are masked \n", + "#out\n", + "dayLST_ma_array = np.ma.masked_equal(dayLST_array, fillval)\n", + "#Empty band and dataset objects to avoid lock issues later. Be \n", + "#sure to empty the band object first, as there can be problems \n", + "#otherwise.\n", + "dayLST_band = None\n", + "dayLST_dataset = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There's a lot going on here, so let's unpack it:\n", + "```Python\n", + "#Register driver for this file type\n", + "driver = gdal.GetDriverByName(\"GTiff\")\n", + "driver.Register()\n", + "```\n", + "GDAL has a separate driver for each supported raster format, and it is necessary to register this driver so that GDAL knows how to open a given file. It is also possible to register all drivers at once, but we will need our driver later to write the data to disk, so we want to use ```GetDriverByName```.\n", + "```Python\n", + "#Open raster as GDAL dataset\n", + "dayLST_dataset = gdal.Open(dayLST_fname)\n", + "#Get geotransform and projection from GDAL dataset. These contain \n", + "#the geospatial information of the data, and we will need them \n", + "#later to write the array back to a raster file.\n", + "geotrans = dayLST_dataset.GetGeoTransform()\n", + "proj = dayLST_dataset.GetProjection()\n", + "```\n", + "This first line opens the raster as a GDAL dataset object, which you can think of as the umbrella which encompasses all aspects of a raster, including both metadata and data. After that, we need to retrieve two pieces of metadata, the geotransform and the projection. Opening raster data in a NumPy array is powerful, but NumPy can't store the geospatial information, so we need to keep track of that ourselves.\n", + "```Python\n", + "#Open the only band in the dataset. Note that band numbering \n", + "#starts from 1 as far as GDAL is concerned.\n", + "dayLST_band = dayLST_dataset.GetRasterBand(1)\n", + "#Pull data from band into a NumPy array\n", + "dayLST_array = dayLST_band.ReadAsArray()\n", + "```\n", + "The dataset object contains all of the bands in the dataset, which in this case is only one band. We are retrieving that band and using ```ReadAsArray``` to load it into a NumPy array.\n", + "```Python\n", + "#Get the NoData value for this band\n", + "fillval = dayLST_band.GetNoDataValue()\n", + "#Create a new masked array, where all areas of NoData are masked \n", + "#out\n", + "dayLST_ma_array = np.ma.masked_equal(dayLST_array, fillval)\n", + "```\n", + "Another important piece of metadata is the NoData value. As with the geotransform and projection, we need to keep track of this for writing the data later. However, we also need it now, because we are going to create a NumPy masked array.\n", + "\n", + "A masked array is the same as a normal NumPy array, except it contains a second Boolean array that is used for masking. Any cell that is ```True``` in this Boolean array will be masked in the data, and these masked cells will not be included in any NumPy operations. In this case, we are using ```masked_equal``` to create an array that is masked everywhere the NoData value is present. Now we can do math with this array and not worry about NoData values throwing things off.\n", + "```Python\n", + "#Empty band and dataset objects to avoid lock issues later. Be \n", + "#sure to empty the band object first, as there can be problems \n", + "#otherwise.\n", + "dayLST_band = None\n", + "dayLST_dataset = None\n", + "```\n", + "As was the case when working with ArcPy, leaving the GDAL objects lying around can lead to issues later, as these objects point to the files on disk.\n", + "\n", + "### Raster math\n", + "\n", + "---\n", + "\n", + "Or, more properly, NumPy math. While opening this data as a NumPy array was, let's be honest, a pain in the butt, now we have a NumPy array of our data, and we can do just about anything we want with it. NumPy has an expansive library of mathematical operations - it is called Numerical Python for a reason. For even more possibilities, check out the SciPy library, which is built on top of NumPy.\n", + "\n", + "In the interests of time and continuity with the ArcPy lecture, we will simply rescale the data. As with ArcPy objects, NumPy will automatically apply simple mathematical operations elementwise to the array." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "scale = 0.02\n", + "dayLST_array_sc = dayLST_ma_array * scale" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Writing the array back to a raster\n", + "\n", + "---\n", + "\n", + "After we have manipulated the data to our heart's content, we need to write it back to a raster format. In many ways, this is just the reverse of what we did above to read it into an array." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "gdal.UseExceptions()\n", + "\n", + "#Create new dataset to contain output\n", + "scale_fname = MODIS_file.rstrip('.hdf')+'_GDAL_scale.tif'\n", + "out_dataset = driver.Create(scale_fname, dayLST_array_sc.shape[1], \n", + " dayLST_array_sc.shape[0], eType = gdal.GDT_UInt16)\n", + "#Set geotransform and projection of output dataset\n", + "out_dataset.SetGeoTransform(geotrans)\n", + "out_dataset.SetProjection(proj)\n", + "#Create a band for our data\n", + "out_band = out_dataset.GetRasterBand(1)\n", + "#Write our data to the band\n", + "out_band.WriteArray(dayLST_array_sc)\n", + "#Tell the raster which value signifies NoData\n", + "out_band.SetNoDataValue(fillval)\n", + "#Write the data from memory to disk. Not strictly necessary, as \n", + "#this should occur anyway at some point, but it is good practice.\n", + "out_band.FlushCache()\n", + "#Clear band and dataset to avoid lock problems\n", + "out_band = None\n", + "out_dataset = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's unpack this one as well:\n", + "```Python\n", + "#Create new dataset to contain output\n", + "scale_fname = MODIS_file.rstrip('.hdf')+'_GDAL_scale.tif'\n", + "out_dataset = driver.Create(scale_fname, dayLST_array_sc.shape[1], \n", + " dayLST_array_sc.shape[0], eType = gdal.GDT_UInt16)\n", + "```\n", + "Here we use our driver object to create a new dataset with the file name, dimensions, and data type of our choosing. Note the data type has to be specified as a ```GDALDataType``` object, the reference for which can be found [here](http://www.gdal.org/gdal_8h.html#a22e22ce0a55036a96f652765793fb7a4).\n", + "```Python\n", + "#Set geotransform and projection of output dataset\n", + "out_dataset.SetGeoTransform(geotrans)\n", + "out_dataset.SetProjection(proj)\n", + "```\n", + "As mentioned above, the NumPy array isn't storing our geospatial metadata, so here we give that information to our new dataset object.\n", + "```Python\n", + "#Create a band for our data\n", + "out_band = out_dataset.GetRasterBand(1)\n", + "#Write our data to the band\n", + "out_band.WriteArray(dayLST_array_sc)\n", + "```\n", + "These lines create a band for the output data, and assign the data to that band. We could create more bands in the same way if we were working with multiband rasters.\n", + "```Python\n", + "#Tell the raster which value signifies NoData\n", + "out_band.SetNoDataValue(fillval)\n", + "```\n", + "A NoData value is just a number unless the raster knows which number signifies NoData. This line provides that information.\n", + "```Python\n", + "#Write the data from memory to disk. Not strictly necessary, as \n", + "#this should occur anyway at some point, but it is good practice.\n", + "out_band.FlushCache()\n", + "```\n", + "Even though we \"wrote\" the array above, this is line that actually writes the data to disk. This should happen anyway when we \"close\" the dataset below, but it is good practice.\n", + "```Python\n", + "#Clear band and dataset to avoid lock problems\n", + "out_band = None\n", + "out_dataset = None\n", + "```\n", + "Clearing out these objects is helpful to avoid lock problems, as mentioned above. You can think of this as \"closing\" the file, from GDAL's perspective.\n", + "\n", + "### Reprojecting raster data\n", + "\n", + "---\n", + "\n", + "Up until this point, we have been duplicating the capabilities of ArcGIS in GDAL. This can be handy because GDAL generally performs things more quickly, more accurately, and provides more control over the process. It is also free, which is nice if you don't have an ArcGIS license. However, you have probably noticed that doing these things in GDAL is, on the surface at least, more complex than doing them with ArcPy. We haven't covered anything where you strictly _need_ GDAL. So, in this last section, we will go over something that strictly requires GDAL: reprojecting data from MODIS sinusoidal to WGS 1984.\n", + "\n", + "To do this, we will be using the extremely powerful ```gdalwarp``` command line tool. In addition to reprojecting, this tool can be used for clipping, masking, resampling, etc., but it is designed around reprojection. To do this from the command line, type:\n", + "```\n", + "> gdalwarp -t_srs \"EPSG:4326\" in_file out_file\n", + "```\n", + "Replace ```in_file``` with the name of our MODIS raster, and replace ```out_file``` with an output file name of your choosing. To call this tool from Python, you would use ```subprocess```, as above:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('0...10...20...30...40...50...60...70...80...90...100 - done.\\r\\n', '')\n" + ] + } + ], + "source": [ + "import subprocess\n", + "import os\n", + "\n", + "#Change system to working directory\n", + "workdir = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "os.chdir(workdir)\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "scale_fname = MODIS_file.rstrip('.hdf')+'_GDAL_scale.tif'\n", + "\n", + "#Send gdalwarp command to system shell, capture result, and print it\n", + "reproj_fname = MODIS_file.rstrip('.hdf')+'_GDAL_reproj.tif'\n", + "reproj_cmd = ['gdalwarp', '-t_srs', 'EPSG:4326', scale_fname, reproj_fname]\n", + "p_reproj = subprocess.Popen(reproj_cmd, stdout=subprocess.PIPE, \n", + " stderr=subprocess.PIPE)\n", + "print(p_reproj.communicate())" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} From 1a751e8ecd22b013415cddbe4b84c7d54a5da34a Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 13 Mar 2017 14:52:01 -0400 Subject: [PATCH 39/57] updated --- Lectures/{ => Week_05}/week_5.ipynb | 30 +++++++---------------------- 1 file changed, 7 insertions(+), 23 deletions(-) rename Lectures/{ => Week_05}/week_5.ipynb (97%) diff --git a/Lectures/week_5.ipynb b/Lectures/Week_05/week_5.ipynb similarity index 97% rename from Lectures/week_5.ipynb rename to Lectures/Week_05/week_5.ipynb index 3b84f88..776cf10 100644 --- a/Lectures/week_5.ipynb +++ b/Lectures/Week_05/week_5.ipynb @@ -135,19 +135,11 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('Input file size is 1200, 1200\\r\\n0...10...20...30...40...50...60...70...80...90...100 - done.\\r\\n', '')\n" - ] - } - ], + "outputs": [], "source": [ "import subprocess\n", "import os\n", @@ -184,7 +176,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "collapsed": true }, @@ -290,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "collapsed": false }, @@ -313,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "collapsed": false }, @@ -400,19 +392,11 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('0...10...20...30...40...50...60...70...80...90...100 - done.\\r\\n', '')\n" - ] - } - ], + "outputs": [], "source": [ "import subprocess\n", "import os\n", From bd4ed8a826e67f721369568de04336fa477dccc9 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 13 Mar 2017 15:28:45 -0400 Subject: [PATCH 40/57] Update week_5.ipynb --- Lectures/Week_05/week_5.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_05/week_5.ipynb b/Lectures/Week_05/week_5.ipynb index 776cf10..1ec5ecb 100644 --- a/Lectures/Week_05/week_5.ipynb +++ b/Lectures/Week_05/week_5.ipynb @@ -9,7 +9,7 @@ }, "source": [ "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", - "![DEVELOP](../../../DEVELOP_logo.png)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", "\n", "---\n", "\n", From 4016ec635143e4d3865cc5eb73a25facb045906b Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 13 Mar 2017 15:39:16 -0400 Subject: [PATCH 41/57] spaces --- Lectures/Week_05/week_5.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures/Week_05/week_5.ipynb b/Lectures/Week_05/week_5.ipynb index 776cf10..320e6cb 100644 --- a/Lectures/Week_05/week_5.ipynb +++ b/Lectures/Week_05/week_5.ipynb @@ -103,7 +103,7 @@ "\n", "---\n", "\n", - "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", "\n", "Copy it to the directory where you want to store your data. You may already have this image from last week's ArcPy lecture.\n", "\n", From ed6fdadc71d3fdc9aef81d5ca6eaa30c47319150 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 13 Mar 2017 15:42:32 -0400 Subject: [PATCH 42/57] fix --- Lectures/Week_05/week_5.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lectures/Week_05/week_5.ipynb b/Lectures/Week_05/week_5.ipynb index c04325e..9bd478a 100644 --- a/Lectures/Week_05/week_5.ipynb +++ b/Lectures/Week_05/week_5.ipynb @@ -103,7 +103,8 @@ "\n", "---\n", "\n", - "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "Download this MODIS image: \n", + "ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", "\n", "Copy it to the directory where you want to store your data. You may already have this image from last week's ArcPy lecture.\n", "\n", From c471ebc580870daf03acbb017aba42b4aabdd51b Mon Sep 17 00:00:00 2001 From: alfredhub Date: Thu, 30 Mar 2017 16:21:48 -0400 Subject: [PATCH 43/57] Add files via upload --- Lectures/Week_04/arcpy_demo.py | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Lectures/Week_04/arcpy_demo.py diff --git a/Lectures/Week_04/arcpy_demo.py b/Lectures/Week_04/arcpy_demo.py new file mode 100644 index 0000000..3849aee --- /dev/null +++ b/Lectures/Week_04/arcpy_demo.py @@ -0,0 +1,61 @@ +""" +Author: Alfred Hubbard +Version: 1.0 +Start Date: 3/5/17 +Description: This script demonstrates basic concepts of ArcPy. +""" + +import arcpy + +workdir = "C:\\Users\\abhubba1\\Documents\\Python Scripts\\DEVELOP_class" +arcpy.env.workspace = workdir +arcpy.env.mask = "Virginia.shp" +arcpy.env.overwriteOutput = True + +arcpy.CheckOutExtension("spatial") + +scale = 0.02 +thres = 15 +out_cellsize = 231.6563583 +MODIS_files = ["MOD11A2.A2016017.h11v05.006.2016234002041.hdf", + "MOD11A2.A2016105.h11v05.006.2016242152502.hdf", + "MOD11A2.A2016201.h11v05.006.2016242234243.hdf", + "MOD11A2.A2016289.h11v05.006.2016302010943.hdf"] + +for f in MODIS_files: + + #Extract from HDF + day_LST = f.rstrip(".hdf") + "_dayLST.tif" + arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0) + night_LST = f.rstrip(".hdf") + "_nightLST.tif" + arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4) + + #Scale + day_LST_sc = arcpy.Raster(day_LST) * scale + night_LST_sc = arcpy.Raster(night_LST) * scale + + #Perform subtraction + diff = day_LST_sc - night_LST_sc + diff.save(f.rstrip(".hdf")+"_diff.tif") + + #Apply conditional + diff_thres = arcpy.sa.Con(diff > thres, 1, 0) + diff_thres.save(f.rstrip(".hdf")+"_thres.tif") + + #Resample + res = f.rstrip(".hdf") + "_res.tif" + arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize) + + #Clear variables to avoid locks + day_LST_sc = None + night_LST_sc = None + diff = None + diff_thres = None + +arcpy.CheckInExtension("spatial") + +#Empty environment settings to prevent them operating on subsequent +#runs in the same Python session +arcpy.env.workspace = None +arcpy.env.overwriteOutput = None +arcpy.env.mask = None \ No newline at end of file From 573ef8026b0f29ac2ba0d411e1dea456d2f04973 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Thu, 30 Mar 2017 16:22:07 -0400 Subject: [PATCH 44/57] Add files via upload --- Lectures/Week_05/gdal_demo.py | 120 ++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Lectures/Week_05/gdal_demo.py diff --git a/Lectures/Week_05/gdal_demo.py b/Lectures/Week_05/gdal_demo.py new file mode 100644 index 0000000..f785251 --- /dev/null +++ b/Lectures/Week_05/gdal_demo.py @@ -0,0 +1,120 @@ +""" +Author: Alfred Hubbard +Version: 1.0 +Start Date: 3/7/17 +Description: This script demonstrates basic applications of GDAL. +""" + +import subprocess +import os + +import numpy as np +from osgeo import gdal + +workdir = "C:\\Users\\abhubba1\\Documents\\Python Scripts\\DEVELOP_class" +os.chdir(workdir) + +#By default the GDAL Python API does not return errors to the Python +#console; this reverses that setting +gdal.UseExceptions() + +scale = 0.02 +thres = 15 +out_cellsize = '231.6563583' +MODIS_files = ["MOD11A2.A2016017.h11v05.006.2016234002041.hdf", + "MOD11A2.A2016105.h11v05.006.2016242152502.hdf", + "MOD11A2.A2016201.h11v05.006.2016242234243.hdf", + "MOD11A2.A2016289.h11v05.006.2016302010943.hdf"] + +for f in MODIS_files: + + #Extract single subdataset from HDF and save as GeoTIFF + dayLST_fname = f.rstrip('.hdf')+'_GDAL_dayLST.tif' + trans_day_cmd = ['gdal_translate', 'HDF4_EOS:EOS_GRID:"'+f+\ + '":MODIS_Grid_8Day_1km_LST:LST_Day_1km', dayLST_fname] + p_trans_day = subprocess.Popen(trans_day_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in p_trans_day.communicate(): + print(line) + nightLST_fname = f.rstrip('.hdf')+'_GDAL_nightLST.tif' + trans_night_cmd = ['gdal_translate', 'HDF4_EOS:EOS_GRID:"'+f+\ + '":MODIS_Grid_8Day_1km_LST:LST_Night_1km', + nightLST_fname] + p_trans_night = subprocess.Popen(trans_night_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in p_trans_night.communicate(): + print(line) + + #Register driver for this file type + driver = gdal.GetDriverByName("GTiff") + driver.Register() + #Open raster as GDAL dataset + dayLST_dataset = gdal.Open(dayLST_fname) + #Get geotransform and projection from GDAL dataset. These contain + #the geospatial information of the data, and we will need them + #later to write the array back to a raster file. + geotrans = dayLST_dataset.GetGeoTransform() + proj = dayLST_dataset.GetProjection() + #Open the only band in the dataset. Note that band numbering + #starts from 1 as far as GDAL is concerned. + dayLST_band = dayLST_dataset.GetRasterBand(1) + #Pull data from band into a NumPy array + dayLST_array = dayLST_band.ReadAsArray() + #Get the NoData value for this band + fillval = dayLST_band.GetNoDataValue() + #Create a new masked array, where all areas of NoData are masked + #out + dayLST_ma_array = np.ma.masked_equal(dayLST_array, fillval) + #Empty band and dataset objects to avoid lock issues later. Be + #sure to empty the band object first, as there can be problems + #otherwise. + dayLST_band = None + dayLST_dataset = None + + nightLST_dataset = gdal.Open(nightLST_fname) + nightLST_band = nightLST_dataset.GetRasterBand(1) + nightLST_array = nightLST_band.ReadAsArray() + nightLST_ma_array = np.ma.masked_equal(nightLST_array, fillval) + nightLST_band = None + nightLST_dataset = None + + #Apply scale factor + dayLST_array_sc = dayLST_ma_array * scale + nightLST_array_sc = nightLST_ma_array * scale + + #Compute difference + diff = dayLST_array_sc - nightLST_array_sc + + #Apply conditional + diff_thres = np.ma.where(diff>thres, 1, 0) + new_fillval = 7 + diff_thres[diff_thres.mask] = new_fillval + + #Create new dataset to contain output + thres_fname = f.rstrip('.hdf')+'_GDAL_thres.tif' + out_dataset = driver.Create(thres_fname, diff_thres.shape[1], + diff_thres.shape[0]) + #Set geotransform and projection of output dataset + out_dataset.SetGeoTransform(geotrans) + out_dataset.SetProjection(proj) + #Create a band for our data + out_band = out_dataset.GetRasterBand(1) + #Write our data to the band + out_band.WriteArray(diff_thres) + #Tell the raster which value signifies NoData + out_band.SetNoDataValue(new_fillval) + #Write the data from memory to disk. Not strictly necessary, as + #this should occur anyway at some point, but it is good practice. + out_band.FlushCache() + #Clear band and dataset to avoid lock problems + out_band = None + out_dataset = None + + #Resample + res_fname = f.rstrip('.hdf')+'_GDAL_res.tif' + res_cmd = ['gdal_translate', '-tr', out_cellsize, out_cellsize, + thres_fname, res_fname] + p_res = subprocess.Popen(res_cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + for line in p_res.communicate(): + print(line) \ No newline at end of file From c5f794f4947f5011add07af41f2bfb38f5e2463a Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 5 Jun 2017 09:10:55 -0400 Subject: [PATCH 45/57] cleaning --- .../20170215_conda.txt | 0 Archive/Agenda_F2016.md | 25 + err.png => Archive/err.png | Bin .../gdal_instructions_MacLinux.txt | 0 .../gdal_instructions_Win7.txt | 0 Lectures/Week_01/01_intro.ipynb | 2 +- Lectures/Week_02/sample.ipynb | 6 +- Lectures/Week_03/week_3.ipynb | 505 +++++++++++++++--- Lectures/Week_04/Basemap.ipynb | 6 +- Lectures/Week_05/week_5.ipynb | 2 + README.md | 8 +- 11 files changed, 483 insertions(+), 71 deletions(-) rename 20170215_conda.txt => Archive/20170215_conda.txt (100%) create mode 100644 Archive/Agenda_F2016.md rename err.png => Archive/err.png (100%) rename gdal_instructions_MacLinux.txt => Archive/gdal_instructions_MacLinux.txt (100%) rename gdal_instructions_Win7.txt => Archive/gdal_instructions_Win7.txt (100%) diff --git a/20170215_conda.txt b/Archive/20170215_conda.txt similarity index 100% rename from 20170215_conda.txt rename to Archive/20170215_conda.txt diff --git a/Archive/Agenda_F2016.md b/Archive/Agenda_F2016.md new file mode 100644 index 0000000..79960f9 --- /dev/null +++ b/Archive/Agenda_F2016.md @@ -0,0 +1,25 @@ +### Lectures + +* __September 21 (2-5pm)__ - Python Intro + * [Introduction - Python code & the Interpreter (1 hr)](http://github.com/edmondb/developython/blob/master/Lectures/Week_01/01_intro.ipynb) + * [Data Structures (30 min)](http://github.com/edmondb/developython/blob/master/Lectures/Week_01/02_data_structures.ipynb) + +* __September 28 (2-5pm)__ - Python Intro (Part 2) + * [File I/O (30 min)](http://github.com/edmondb/developython/blob/master/Lectures/Week_02/03_FileIO.ipynb) + * [Loops and Conditionals (30 min)](http://github.com/edmondb/developython/blob/master/Lectures/Week_02/04_conditionals_loops.ipynb) + * [numpy (30 min)](http://github.com/edmondb/developython/blob/master/Lectures/Week_02/05_numpy.ipynb) + +* __October 12 (2-3:30pm)__ - Scientific Programming with GDAL + * [matplotlib (30 min)](http://github.com/edmondb/developython/blob/master/Lectures/Week_03/01_matplotlib.ipynb) + * [GDAL (1 hr)](http://github.com/edmondb/developython/blob/master/Lectures/Week_03/gdal/gdal.ipynb) + +* __October 27 (2:30-4pm)__ - Earth Science Data + * [netCDF3/4 (30 min)]() + * [HDF-5 and h5py (30 min)]() + * [Basemap (30 min)]() + +* __Extras__ - Advanced Topics + * arcPy + * Automation + * Multiprocessing + * OOP diff --git a/err.png b/Archive/err.png similarity index 100% rename from err.png rename to Archive/err.png diff --git a/gdal_instructions_MacLinux.txt b/Archive/gdal_instructions_MacLinux.txt similarity index 100% rename from gdal_instructions_MacLinux.txt rename to Archive/gdal_instructions_MacLinux.txt diff --git a/gdal_instructions_Win7.txt b/Archive/gdal_instructions_Win7.txt similarity index 100% rename from gdal_instructions_Win7.txt rename to Archive/gdal_instructions_Win7.txt diff --git a/Lectures/Week_01/01_intro.ipynb b/Lectures/Week_01/01_intro.ipynb index a7a5d4c..e1788a8 100644 --- a/Lectures/Week_01/01_intro.ipynb +++ b/Lectures/Week_01/01_intro.ipynb @@ -563,7 +563,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.11" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/Lectures/Week_02/sample.ipynb b/Lectures/Week_02/sample.ipynb index 70bab38..ce24501 100644 --- a/Lectures/Week_02/sample.ipynb +++ b/Lectures/Week_02/sample.ipynb @@ -931,9 +931,9 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [Root]", + "display_name": "Python 2", "language": "python", - "name": "Python [Root]" + "name": "python2" }, "language_info": { "codemirror_mode": { @@ -945,7 +945,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/Lectures/Week_03/week_3.ipynb b/Lectures/Week_03/week_3.ipynb index 75bd457..badcde9 100644 --- a/Lectures/Week_03/week_3.ipynb +++ b/Lectures/Week_03/week_3.ipynb @@ -45,17 +45,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD8CAYAAACMwORRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADNNJREFUeJzt3V+MpfVdx/H3x12QWkto3OmfMNCxsQ2lDVQcsZEmIsaE\nAoFWSSRKN6k1G4xWemGo9KKJ8cbL1Yt2syFGGzSbJkLTrLRN7Ra5AKqzZbt0u9ggbv+Qmh2wFqm0\n7Ha/XswhTIczzDkzZ+bsfHm/kpOc8zy/mfP77TP7nmfOnDMnVYUkqZefmvYEJEmTZ9wlqSHjLkkN\nGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDW0c1p3vGvXrpqbm5vW3UvStnT48OGnqmpmrXFTi/vc\n3BwLCwvTuntJ2paSfHOUcT4sI0kNGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDU0ctyT7EjySJKD\nQ/bdlORokiNJFpK8e7LTlCSNY5wXMd0OHAfOH7Lvi8BnqqqSXAZ8CrhkAvOTJK3DSGfuSWaB64G7\nhu2vqmfrxXfafjXgu25L0hSN+rDMXuAO4MxqA5K8L8ljwD8Bvz+BuUmS1mnNuCe5AThZVYdfblxV\n3VtVlwDvBf5ilc+1Z/CY/MLi4uK6JixJWtsoZ+5XATcmOQEcAK5Jcvdqg6vqAeDNSXYN2be/quar\nan5mZs0/aiZJWqc1415Vd1bVbFXNAbcAh6rq1uVjkvxCkgyuXwH8NPD0JsxXkjSCdf/J3yS3AVTV\nPuC3gd1JTgHPAb+z7BeskqQtlmk1eH5+vvx77pI0niSHq2p+rXG+QlWSGjLuktSQcZekhoy7JDVk\n3CWpIeMuSQ0Zd0lqyLhLUkPGXZIaMu6S1JBxl6SGjLskNWTcJakh4y5JDRl3SWrIuEtSQ8Zdkhoy\n7pLUkHGXpIaMuyQ1ZNwlqSHjLkkNGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDVk3CWpIeMuSQ0Z\nd0lqyLhLUkPGXZIaMu6S1JBxl6SGjLskNWTcJakh4y5JDRl3SWpo5Lgn2ZHkkSQHh+z7vSRHkzya\n5MEkl092mpKkcewcY+ztwHHg/CH7/hP4tar6XpL3APuBX5nA/CRJ6zDSmXuSWeB64K5h+6vqwar6\n3uDmw8DsZKYnSVqPUR+W2QvcAZwZYewHgc+ue0aSpA1bM+5JbgBOVtXhEcb+Oktx/8gq+/ckWUiy\nsLi4OPZkJUmjGeXM/SrgxiQngAPANUnuXjkoyWUsPWxzU1U9PewTVdX+qpqvqvmZmZkNTFuS9HLW\njHtV3VlVs1U1B9wCHKqqW5ePSXIxcA/w/qr6xqbMVJI0snGeLfMTktwGUFX7gI8BPwd8PAnA6aqa\nn8gMJUljS1VN5Y7n5+drYWFhKvctSdtVksOjnDz7ClVJasi4S1JDxl2SGjLuktSQcZekhoy7JDVk\n3CWpIeMuSQ0Zd0lqyLhLUkPGXZIaMu6S1JBxl6SGjLskNWTcJakh4y5JDRl3SWrIuEtSQ8Zdkhoy\n7pLUkHGXpIaMuyQ1ZNwlqSHjLkkNGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDVk3CWpIeMuSQ0Z\nd0lqyLhLUkPGXZIaMu6S1JBxl6SGjLskNWTcJamhkeOeZEeSR5IcHLLvkiQPJflRkj+d7BQlSePa\nOcbY24HjwPlD9v038CfAeycxKWlanucUP+Q0RRHCeezkXM6Z9rSksY105p5kFrgeuGvY/qo6WVX/\nBpya4NykLfU8p3iOUxQFQFE8xyme98ta29CoD8vsBe4AzmziXKSp+iGnx9ounc3WjHuSG4CTVXV4\no3eWZE+ShSQLi4uLG/100kS9cMY+6nbpbDbKmftVwI1JTgAHgGuS3L2eO6uq/VU1X1XzMzMz6/kU\n0qYJGWu7dDZbM+5VdWdVzVbVHHALcKiqbt30mUlb7LxVnl+w2nbpbLbur9oktwFU1b4kbwAWWHom\nzZkkHwYurapnJjNNafO98KwYny2jDsaKe1XdD9w/uL5v2fb/AmYnOTFpGs7lHGOuFnyFqiQ1ZNwl\nqSHjLkkNGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDVk3CWpIeMuSQ0Zd0lqyLhLUkPGXZIaMu6S\n1JBxl6SGjLskNWTcJakh4y5JDRl3SWrIuEtSQ8Zdkhoy7pLUkHGXpIaMuyQ1ZNwlqSHjLkkNGXdJ\nasi4S1JDxl2SGjLuktSQcZekhoy7JDVk3CWpIeMuSQ0Zd0lqyLhLUkPGXZIaMu6S1JBxl6SGRo57\nkh1JHklycMi+JPnrJI8nOZrkislOU5I0jnHO3G8Hjq+y7z3AWwaXPcAnNjgvSdIGjBT3JLPA9cBd\nqwy5CfhkLXkYuCDJGyc0R0nSmEY9c98L3AGcWWX/hcC3l93+zmDbT0iyJ8lCkoXFxcWxJipJGt2a\ncU9yA3Cyqg5v9M6qan9VzVfV/MzMzEY/nSRpFaOcuV8F3JjkBHAAuCbJ3SvGPAlctOz27GCbJGkK\n1ox7Vd1ZVbNVNQfcAhyqqltXDPsMsHvwrJl3Ad+vqu9OfrqSpFHsXO8HJrkNoKr2AfcB1wGPA/8H\nfGAis5MkrctYca+q+4H7B9f3LdtewB9NcmKSpPXzFaqS1JBxl6SGjLskNWTcJakh4y5JDRl3SWrI\nuEtSQ8Zdkhoy7pLUkHGXpIaMuyQ1ZNwlqSHjLkkNGXdJasi4S1JDxl2SGjLuktSQcZekhoy7JDVk\n3CWpIeMuSQ0Zd0lqyLhLUkPGXZIaMu6S1JBxl6SGjLskNWTcJakh4y5JDRl3SWrIuEtSQ8Zdkhoy\n7pLUkHGXpIaMuyQ1ZNwlqSHjLkkNGXdJasi4S1JDa8Y9yXlJ/jXJV5McS/LnQ8a8Nsm9SY4Oxr5j\nc6YrSRrFKGfuPwKuqarLgXcC1yZ514oxHwWOVNVlwG7gryY7TUnSONaMey15dnDznMGlVgy7FDg0\nGP8YMJfk9ZOcqCRpdCM95p5kR5IjwEngC1X15RVDvgr81mDslcCbgNlJTlSSNLqR4l5VP66qd7IU\n7CuHPKb+l8AFg28AHwIeAX688vMk2ZNkIcnC4uLiBqcuSVrNWM+Wqar/Ab4EXLti+zNV9YHBN4Dd\nwAzwxJCP319V81U1PzMzs4FpS5JezijPlplJcsHg+quA3wQeWzHmgiTnDm7+AfBAVT0z6clKkkaz\nc4QxbwT+LskOlr4ZfKqqDia5DaCq9gFvG4wp4Bjwwc2asCRpbWvGvaqOAr84ZPu+ZdcfAt462alJ\nktbLV6hKUkPGXZIaMu6S1JBxl6SGjLskNWTcJakh4y5JDaVq5R943KI7ThaBb07lzjdmF/DUtCex\nxVxzf6+09cL2XfObqmrNv98ytbhvV0kWqmp+2vPYSq65v1faeqH/mn1YRpIaMu6S1JBxH9/+aU9g\nClxzf6+09ULzNfuYuyQ15Jm7JDVk3IEkFyX5UpKvJzmW5PaXGfvLSU4nuXnZtmuT/HuSx5P82dbM\nemMmsOYTSR5NciTJwtbMemNGWXOSq5N8f7CuI0k+tmxfy+O8xppbHufBuKsH6zqW5F+Wbd92x3mo\nqnrFX1h6Q5IrBtdfA3wDuHTIuB3AIeA+4OZl2/4DeDNwLktvFv6Sjz3bLhtZ82D7CWDXtNcx6TUD\nVwMHV/l3aHmcV1tz8+N8AfB14OLB7ddt5+M87OKZO1BV362qrwyu/y9wHLhwyNAPAf8InFy27Urg\n8ap6oqqeBw4AN23ylDdsg2velsZY8zDdj3MbI675d4F7qupbg3EvfH1vy+M8jHFfIckcS+889eUV\n2y8E3gd8YsWHXAh8e9nt77DN/vOsY80ABfxzksNJ9mz2HCdttTUP/GqSo0k+m+Ttg21tj/PAsDVD\n3+P8VuC1Se4frG33YPu2P84vGOU9VF8xkvwsS2epH66XvsH3XuAjVXUmydZPbpNsYM3vrqonk7wO\n+EKSx6rqgS2Y8oatseavsPSj+rNJrgM+Dbxlq+c4aRtYc9fjvBP4JeA3gFcBDyV5eIunuKmM+0CS\nc1j6Qvj7qrpnyJB54MAgcruA65KcBp4ELlo2bnaw7ay33jVX1aer6klY+nE2yb0s/Th71v+nX2vN\nyyNQVfcl+XiSXTQ+zqutuaqe6nqcWTojf7qqfgD8IMkDwOWD7dvyOL/EtB/0PxsuQIBPAntHHP+3\nvPgL1Z3AE8DP8+IvYN4+7TVt8ppfDbxm2fUHgWunvaZJrBl4Ay++/uNK4FuDj2t7nF9mzZ2P89uA\nLw6O688AXwPesV2P87CLZ+5LrgLeDzya5Mhg20eBiwGqat9qH1hVp5P8MfB5ln7T/jdVdWyT5zsJ\n614z8Hrg3sEZ/U7gH6rqc5s410kZZc03A384+KnsOeCWWqpB5+M8dM1J2h7nqjqe5HPAUeAMcFdV\nfQ1gmx7nl/AVqpLUkM+WkaSGjLskNWTcJakh4y5JDRl3SWrIuEtSQ8Zdkhoy7pLU0P8DlDxC9Prf\nuLQAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "#plt.plot(x, y, 'red-circle')\n", - "plt.plot(2.5, 4.1, 'ro')" + "plt.plot(2.5, 4.1, 'o', color='#F0FFF5')" ] }, { @@ -79,15 +100,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "x = [0,1,2,3,4,5]\n", "y = [1,2,3,4,5,6]\n", - "plt.plot(x, y)" + "plt.plot(x, y, '--')" ] }, { @@ -99,15 +141,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# plot with legend\n", "plt.plot(x, y, label='a line')\n", - "plt.legend(loc=0)" + "plt.legend(loc='upper right')" ] }, { @@ -119,11 +182,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\nARzauCD6Tu+nAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import numpy as np\n", "\n", @@ -135,6 +219,69 @@ "plt.legend()" ] }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-3.14159265 -3.11695271 -3.09231277 -3.06767283 -3.04303288 -3.01839294\n", + " -2.993753 -2.96911306 -2.94447311 -2.91983317 -2.89519323 -2.87055329\n", + " -2.84591335 -2.8212734 -2.79663346 -2.77199352 -2.74735358 -2.72271363\n", + " -2.69807369 -2.67343375 -2.64879381 -2.62415386 -2.59951392 -2.57487398\n", + " -2.55023404 -2.52559409 -2.50095415 -2.47631421 -2.45167427 -2.42703432\n", + " -2.40239438 -2.37775444 -2.3531145 -2.32847456 -2.30383461 -2.27919467\n", + " -2.25455473 -2.22991479 -2.20527484 -2.1806349 -2.15599496 -2.13135502\n", + " -2.10671507 -2.08207513 -2.05743519 -2.03279525 -2.0081553 -1.98351536\n", + " -1.95887542 -1.93423548 -1.90959553 -1.88495559 -1.86031565 -1.83567571\n", + " -1.81103577 -1.78639582 -1.76175588 -1.73711594 -1.712476 -1.68783605\n", + " -1.66319611 -1.63855617 -1.61391623 -1.58927628 -1.56463634 -1.5399964\n", + " -1.51535646 -1.49071651 -1.46607657 -1.44143663 -1.41679669 -1.39215674\n", + " -1.3675168 -1.34287686 -1.31823692 -1.29359698 -1.26895703 -1.24431709\n", + " -1.21967715 -1.19503721 -1.17039726 -1.14575732 -1.12111738 -1.09647744\n", + " -1.07183749 -1.04719755 -1.02255761 -0.99791767 -0.97327772 -0.94863778\n", + " -0.92399784 -0.8993579 -0.87471795 -0.85007801 -0.82543807 -0.80079813\n", + " -0.77615819 -0.75151824 -0.7268783 -0.70223836 -0.67759842 -0.65295847\n", + " -0.62831853 -0.60367859 -0.57903865 -0.5543987 -0.52975876 -0.50511882\n", + " -0.48047888 -0.45583893 -0.43119899 -0.40655905 -0.38191911 -0.35727916\n", + " -0.33263922 -0.30799928 -0.28335934 -0.2587194 -0.23407945 -0.20943951\n", + " -0.18479957 -0.16015963 -0.13551968 -0.11087974 -0.0862398 -0.06159986\n", + " -0.03695991 -0.01231997 0.01231997 0.03695991 0.06159986 0.0862398\n", + " 0.11087974 0.13551968 0.16015963 0.18479957 0.20943951 0.23407945\n", + " 0.2587194 0.28335934 0.30799928 0.33263922 0.35727916 0.38191911\n", + " 0.40655905 0.43119899 0.45583893 0.48047888 0.50511882 0.52975876\n", + " 0.5543987 0.57903865 0.60367859 0.62831853 0.65295847 0.67759842\n", + " 0.70223836 0.7268783 0.75151824 0.77615819 0.80079813 0.82543807\n", + " 0.85007801 0.87471795 0.8993579 0.92399784 0.94863778 0.97327772\n", + " 0.99791767 1.02255761 1.04719755 1.07183749 1.09647744 1.12111738\n", + " 1.14575732 1.17039726 1.19503721 1.21967715 1.24431709 1.26895703\n", + " 1.29359698 1.31823692 1.34287686 1.3675168 1.39215674 1.41679669\n", + " 1.44143663 1.46607657 1.49071651 1.51535646 1.5399964 1.56463634\n", + " 1.58927628 1.61391623 1.63855617 1.66319611 1.68783605 1.712476\n", + " 1.73711594 1.76175588 1.78639582 1.81103577 1.83567571 1.86031565\n", + " 1.88495559 1.90959553 1.93423548 1.95887542 1.98351536 2.0081553\n", + " 2.03279525 2.05743519 2.08207513 2.10671507 2.13135502 2.15599496\n", + " 2.1806349 2.20527484 2.22991479 2.25455473 2.27919467 2.30383461\n", + " 2.32847456 2.3531145 2.37775444 2.40239438 2.42703432 2.45167427\n", + " 2.47631421 2.50095415 2.52559409 2.55023404 2.57487398 2.59951392\n", + " 2.62415386 2.64879381 2.67343375 2.69807369 2.72271363 2.74735358\n", + " 2.77199352 2.79663346 2.8212734 2.84591335 2.87055329 2.89519323\n", + " 2.91983317 2.94447311 2.96911306 2.993753 3.01839294 3.04303288\n", + " 3.06767283 3.09231277 3.11695271 3.14159265]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "x = np.linspace(-np.pi, np.pi, 256, endpoint=True)\n", + "print(x)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -144,40 +291,132 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\ngg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "plt.figure(1)\n", "plt.subplot(211)\n", - "plt.plot(x, cos, color='C0') # notice the color name\n", + "plt.plot(x, cos) # notice the color name\n", + "plt.plot(x, sin)\n", "\n", "plt.subplot(212)\n", - "plt.plot(x, sin, color='C1')" + "plt.plot(x, sin)" ] }, { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "\n", - "---\n", - "\n", - "# NOTICE\n", - "\n", - "---\n", - "\n", - "__Run this line from your Anaconda Prompt (March 1, 2017)__\n", - "```bash\n", - "conda update hdf4\n", - "```\n", - "\n", - "---\n", - "\n", - "---" + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function subplot in module matplotlib.pyplot:\n", + "\n", + "subplot(*args, **kwargs)\n", + " Return a subplot axes positioned by the given grid definition.\n", + " \n", + " Typical call signature::\n", + " \n", + " subplot(nrows, ncols, plot_number)\n", + " \n", + " Where *nrows* and *ncols* are used to notionally split the figure\n", + " into ``nrows * ncols`` sub-axes, and *plot_number* is used to identify\n", + " the particular subplot that this function is to create within the notional\n", + " grid. *plot_number* starts at 1, increments across rows first and has a\n", + " maximum of ``nrows * ncols``.\n", + " \n", + " In the case when *nrows*, *ncols* and *plot_number* are all less than 10,\n", + " a convenience exists, such that the a 3 digit number can be given instead,\n", + " where the hundreds represent *nrows*, the tens represent *ncols* and the\n", + " units represent *plot_number*. For instance::\n", + " \n", + " subplot(211)\n", + " \n", + " produces a subaxes in a figure which represents the top plot (i.e. the\n", + " first) in a 2 row by 1 column notional grid (no grid actually exists,\n", + " but conceptually this is how the returned subplot has been positioned).\n", + " \n", + " .. note::\n", + " \n", + " Creating a new subplot with a position which is entirely inside a\n", + " pre-existing axes will trigger the larger axes to be deleted::\n", + " \n", + " import matplotlib.pyplot as plt\n", + " # plot a line, implicitly creating a subplot(111)\n", + " plt.plot([1,2,3])\n", + " # now create a subplot which represents the top plot of a grid\n", + " # with 2 rows and 1 column. Since this subplot will overlap the\n", + " # first, the plot (and its axes) previously created, will be removed\n", + " plt.subplot(211)\n", + " plt.plot(range(12))\n", + " plt.subplot(212, facecolor='y') # creates 2nd subplot with yellow background\n", + " \n", + " If you do not want this behavior, use the\n", + " :meth:`~matplotlib.figure.Figure.add_subplot` method or the\n", + " :func:`~matplotlib.pyplot.axes` function instead.\n", + " \n", + " Keyword arguments:\n", + " \n", + " *facecolor*:\n", + " The background color of the subplot, which can be any valid\n", + " color specifier. See :mod:`matplotlib.colors` for more\n", + " information.\n", + " \n", + " *polar*:\n", + " A boolean flag indicating whether the subplot plot should be\n", + " a polar projection. Defaults to *False*.\n", + " \n", + " *projection*:\n", + " A string giving the name of a custom projection to be used\n", + " for the subplot. This projection must have been previously\n", + " registered. See :mod:`matplotlib.projections`.\n", + " \n", + " .. seealso::\n", + " \n", + " :func:`~matplotlib.pyplot.axes`\n", + " For additional information on :func:`axes` and\n", + " :func:`subplot` keyword arguments.\n", + " \n", + " :file:`examples/pie_and_polar_charts/polar_scatter_demo.py`\n", + " For an example\n", + " \n", + " **Example:**\n", + " \n", + " .. plot:: mpl_examples/subplots_axes_and_figures/subplot_demo.py\n", + "\n" + ] + } + ], + "source": [ + "help(plt.subplot)" ] }, { @@ -202,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "collapsed": false }, @@ -210,13 +449,13 @@ "source": [ "import netCDF4 as nc\n", "\n", - "f = nc.Dataset('test.nc', 'w')\n", + "f = nc.Dataset('test.nc4', 'w')\n", "f.close()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": { "collapsed": true }, @@ -268,14 +507,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ "# netCDF\n", - "rootgrp = nc.Dataset('test.nc', 'a')\n", + "rootgrp = nc.Dataset('test.nc4', 'a')\n", "fcstgrp = rootgrp.createGroup('forecasts')\n", "anlgrp = rootgrp.createGroup('analyses')\n", "\n", @@ -288,7 +527,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "metadata": { "collapsed": true }, @@ -308,24 +547,54 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "root group (NETCDF4 data model, file format HDF5):\n", + " dimensions(sizes): \n", + " variables(dimensions): \n", + " groups: forecasts, analyses\n", + "\n", + "\n", + "\n", + "OrderedDict([(u'forecasts', \n", + "group /forecasts:\n", + " dimensions(sizes): \n", + " variables(dimensions): \n", + " groups: model1, model2\n", + "), (u'analyses', \n", + "group /analyses:\n", + " dimensions(sizes): \n", + " variables(dimensions): \n", + " groups: \n", + ")])\n", + "\n", + "\n", + "\n", + "[u'analyses', u'forecasts']\n" + ] + } + ], "source": [ "# let's look inside these:\n", - "f = nc.Dataset('test.nc', 'r')\n", + "f = nc.Dataset('test.nc4', 'r')\n", "print(f)\n", - "#print('\\n')\n", - "#print(f.groups)\n", + "print('\\n')\n", + "print(f.groups)\n", "f.close()\n", "\n", "print('\\n')\n", "\n", "f = h5.File('test.h5', 'r')\n", "print(f)\n", - "#print(f.keys())\n", + "print(f.keys())\n", "f.close()" ] }, @@ -338,14 +607,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ "# netCDF (netCDF3 can only have 1 unlimmited dimension)\n", - "rootgrp = nc.Dataset('test.nc', 'a')\n", + "rootgrp = nc.Dataset('test.nc4', 'a')\n", "level = rootgrp.createDimension('level', None) # or 0\n", "time = rootgrp.createDimension('time', None) # or 0\n", "lat = rootgrp.createDimension('lat', 73)\n", @@ -366,14 +635,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 59, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OrderedDict([(u'level', (unlimited): name = 'level', size = 0\n", + "), (u'time', (unlimited): name = 'time', size = 0\n", + "), (u'lat', : name = 'lat', size = 73\n", + "), (u'lon', : name = 'lon', size = 144\n", + ")])\n" + ] + } + ], "source": [ "# let's look inside these:\n", - "f = nc.Dataset('test.nc', 'r')\n", + "f = nc.Dataset('test.nc4', 'r')\n", "print(f.dimensions)\n", "f.close()" ] @@ -387,7 +668,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 60, "metadata": { "collapsed": true }, @@ -399,14 +680,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 61, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# netCDF\n", - "rootgrp = nc.Dataset('test.nc', 'a')\n", + "rootgrp = nc.Dataset('test.nc4', 'a')\n", "times = rootgrp.createVariable('time', 'f8', ('time',))\n", "levels = rootgrp.createVariable('level', 'i4', ('level',))\n", "latitudes = rootgrp.createVariable('latitude', 'f4', ('lat',))\n", @@ -424,7 +705,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 62, "metadata": { "collapsed": true }, @@ -441,14 +722,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[u'time', u'level', u'latitude', u'longitude', u'temp']\n", + "[[ 0.41015527 0.40631986 0.10267066 0.93808627]\n", + " [ 0.47038493 0.55063295 0.91086882 0.52334672]\n", + " [ 0.27892506 0.48110983 0.4794006 0.95779741]\n", + " [ 0.72449797 0.19362372 0.81611872 0.01212891]]\n", + "\n", + "[[ 0.49607593 0.88358039 0.81215775 0.99389112]\n", + " [ 0.51340181 0.61961353 0.93530029 0.74421412]\n", + " [ 0.53950232 0.62176359 0.27123785 0.41296488]\n", + " [ 0.17852955 0.70025551 0.62833965 0.86961234]]\n" + ] + } + ], "source": [ "# let's look inside these:\n", - "rootgrp = nc.Dataset('test.nc', 'a')\n", + "rootgrp = nc.Dataset('test.nc4', 'a')\n", "print(rootgrp.variables.keys())\n", "print(rootgrp.variables['temp'][0,0,[0,1,2,3],[0,1,2,3]])\n", "rootgrp.close()\n", @@ -469,6 +767,93 @@ "\n", "This is just the metadata for the variables/groups." ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "f = nc.Dataset('/Users/ebsmith2/Downloads/GEOS.fp.fcst.inst1_2d_hwl_Nx.20170301_12+20170301_1000.V01.nc4', 'r')" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\n", + "root group (NETCDF4 data model, file format HDF5):\n", + " Title: 2d,1-Hourly,Instantaneous,Single-Level,Forecast,Hyperwall\n", + " History: File written by MAPL_CFIO\n", + " Source: GEOSadas-5_16_5_OPS\n", + " Contact: http://gmao.gsfc.nasa.gov\n", + " Conventions: CF\n", + " Institution: NASA Global Modeling and Assimilation Office\n", + " References: see MAPL documentation\n", + " Filename: GEOS.fp.fcst.inst1_2d_hwl_Nx.20170301_12+20170301_1000.V01.nc4\n", + " Comment: NetCDF-4\n", + " dimensions(sizes): lon(1152), lat(721), time(1)\n", + " variables(dimensions): float64 \u001b[4mlon\u001b[0m(lon), float64 \u001b[4mlat\u001b[0m(lat), int32 \u001b[4mtime\u001b[0m(time), float32 \u001b[4mBCCMASS\u001b[0m(time,lat,lon), float32 \u001b[4mBCEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mBCFLUXU\u001b[0m(time,lat,lon), float32 \u001b[4mBCFLUXV\u001b[0m(time,lat,lon), float32 \u001b[4mBCSMASS\u001b[0m(time,lat,lon), float32 \u001b[4mCFC12strat\u001b[0m(time,lat,lon), float32 \u001b[4mCFC12trop\u001b[0m(time,lat,lon), float32 \u001b[4mCO2CL\u001b[0m(time,lat,lon), float32 \u001b[4mCOCL\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLbbae\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLbbaf\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLbbgl\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLbbla\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLbbna\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLnbas\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLnbeu\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLnbgl\u001b[0m(time,lat,lon), float32 \u001b[4mCOCLnbna\u001b[0m(time,lat,lon), float32 \u001b[4mCOSC\u001b[0m(time,lat,lon), float32 \u001b[4mDUCMASS\u001b[0m(time,lat,lon), float32 \u001b[4mDUEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mDUFLUXU\u001b[0m(time,lat,lon), float32 \u001b[4mDUFLUXV\u001b[0m(time,lat,lon), float32 \u001b[4mDUSMASS\u001b[0m(time,lat,lon), float32 \u001b[4mDUSMASS25\u001b[0m(time,lat,lon), float32 \u001b[4mNISMASS\u001b[0m(time,lat,lon), float32 \u001b[4mNISMASS25\u001b[0m(time,lat,lon), float32 \u001b[4mOCCMASS\u001b[0m(time,lat,lon), float32 \u001b[4mOCEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mOCFLUXU\u001b[0m(time,lat,lon), float32 \u001b[4mOCFLUXV\u001b[0m(time,lat,lon), float32 \u001b[4mOCSMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSLP\u001b[0m(time,lat,lon), float32 \u001b[4mSO2CMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSO2SMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSO4CMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSO4SMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSSCMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSSEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mSSFLUXU\u001b[0m(time,lat,lon), float32 \u001b[4mSSFLUXV\u001b[0m(time,lat,lon), float32 \u001b[4mSSSMASS\u001b[0m(time,lat,lon), float32 \u001b[4mSSSMASS25\u001b[0m(time,lat,lon), float32 \u001b[4mSUEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mSUFLUXU\u001b[0m(time,lat,lon), float32 \u001b[4mSUFLUXV\u001b[0m(time,lat,lon), float32 \u001b[4mTO3\u001b[0m(time,lat,lon), float32 \u001b[4mTOTANGSTR\u001b[0m(time,lat,lon), float32 \u001b[4mTOTEXTTAU\u001b[0m(time,lat,lon), float32 \u001b[4mTOTSCATAU\u001b[0m(time,lat,lon)\n", + " groups: " + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(f.variables['SLP'][0][::-1], cmap='jet')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/Lectures/Week_04/Basemap.ipynb b/Lectures/Week_04/Basemap.ipynb index 25445ce..b005c62 100644 --- a/Lectures/Week_04/Basemap.ipynb +++ b/Lectures/Week_04/Basemap.ipynb @@ -134,9 +134,9 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [conda root]", + "display_name": "Python 2", "language": "python", - "name": "conda-root-py" + "name": "python2" }, "language_info": { "codemirror_mode": { @@ -148,7 +148,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.12" + "version": "2.7.13" } }, "nbformat": 4, diff --git a/Lectures/Week_05/week_5.ipynb b/Lectures/Week_05/week_5.ipynb index 9bd478a..f819e76 100644 --- a/Lectures/Week_05/week_5.ipynb +++ b/Lectures/Week_05/week_5.ipynb @@ -114,6 +114,8 @@ "\n", "We want to extract a subdataset from this HDF file, but suppose we don't know what that subdataset is called? Navigate to your working directory, and type the following in the command line:\n", "\n", + "> gdalinfo MOD11A2.A2016201.h11v05.006.2016242234243.hdf\n", + "\n", "```> gdalinfo MOD11A2.A2016201.h11v05.006.2016242234243.hdf```\n", "\n", "This is a lot of information, but it should look familiar from the HDF/netCDF lecture. If you look closely, you will seen the names and descriptions of each subdataset. For example, the full name of the daytime LST subdataset is ```HDF4_EOS:EOS_GRID:\"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\":MODIS_Grid_8Day_1km_LST:LST_Day_1km```\n", diff --git a/README.md b/README.md index d22c7d9..fb68d8e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # developython + +![logo](DEVELOP_logo.png) + Python Training for the DEVELOP program. # Setup Instructions 1. [Download](https://www.continuum.io/downloads) and install __Anaconda for Windows 32-Bit (Python 2.7)__ 2. Do not make it your default Python (possible conflicts with other Python versions or if using arcPy). -3. After installing Anaconda, copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. Note that AppData is a hidden folder, so you must either enable Windows Explorer to show hidden folders or type in the path by hand to the navigation bar of Windows Explorer. +3. After installing Anaconda, copy `C:\Python27\ArcGIS10.x\Lib\site-packages\Desktop10.x.pth` to (replace __username__ here) `C:\Users\`__username__`\AppData\Local\Continuum\Anaconda2\Lib\site_packages\`. Note that AppData is a hidden folder, so you must either enable Windows Explorer to show hidden folders or type in the path by hand to the navigation bar of Windows Explorer. 4. Start -> All Programs -> Anaconda 2 (32-Bit) -> Anaconda Prompt -5. `conda update conda` -6. `conda install netCDF4` -7. Follow [GDAL setup instructions](https://github.com/edmondb/developython/blob/master/gdal_instructions_Win7.txt) for Windows. From f8af84d5681e7eba6058c1be6054bfe3f571e86b Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 5 Jun 2017 09:11:24 -0400 Subject: [PATCH 46/57] fancy --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index fb68d8e..ab6e34c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ -# developython - ![logo](DEVELOP_logo.png) - +--- Python Training for the DEVELOP program. # Setup Instructions From c5099b625938b34ca55c2498a234cc083c6ce1b0 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 5 Jun 2017 09:45:34 -0400 Subject: [PATCH 47/57] archive and week 1 start --- .../Lectures_201702}/Week_01/01_intro.ipynb | 0 .../Week_01/02_data_structures.ipynb | 0 .../Lectures_201702}/Week_01/helloworld.py | 0 .../Lectures_201702}/Week_01/readme.md | 0 .../Lectures_201702}/Week_01/week_1.ipynb | 0 .../Lectures_201702}/Week_02/03_FileIO.ipynb | 0 .../Week_02/04_conditionals_loops.ipynb | 0 .../Lectures_201702}/Week_02/05_numpy.ipynb | 0 .../Lectures_201702}/Week_02/sample.csv | 0 .../Lectures_201702}/Week_02/sample.ipynb | 0 .../Lectures_201702}/Week_02/week_2.ipynb | 0 .../Week_03/01_matplotlib.ipynb | 0 .../Week_03/gdal/array2raster.py | 0 .../Lectures_201702}/Week_03/gdal/gdal.ipynb | 0 .../Week_03/gdal/gdal_commands.txt | 0 .../Week_03/gdal/gdal_example.py | 0 .../Lectures_201702}/Week_03/week_3.ipynb | 0 .../Lectures_201702}/Week_04/Basemap.ipynb | 0 .../Lectures_201702}/Week_04/HDF.ipynb | 0 .../Lectures_201702}/Week_04/arcpy_demo.py | 0 .../Lectures_201702}/Week_04/week_4.ipynb | 0 .../Lectures_201702}/Week_05/gdal_demo.py | 0 .../Lectures_201702}/Week_05/week_5.ipynb | 0 .../Lectures_201702}/readme.md | 0 Lectures_201706/Week_01/helloworld.py | 3 + Lectures_201706/Week_01/readme.md | 1 + Lectures_201706/Week_01/setup_intro.ipynb | 313 ++++++++++++++++++ 27 files changed, 317 insertions(+) rename {Lectures => Archive/Lectures_201702}/Week_01/01_intro.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_01/02_data_structures.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_01/helloworld.py (100%) rename {Lectures => Archive/Lectures_201702}/Week_01/readme.md (100%) rename {Lectures => Archive/Lectures_201702}/Week_01/week_1.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/03_FileIO.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/04_conditionals_loops.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/05_numpy.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/sample.csv (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/sample.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_02/week_2.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/01_matplotlib.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/gdal/array2raster.py (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/gdal/gdal.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/gdal/gdal_commands.txt (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/gdal/gdal_example.py (100%) rename {Lectures => Archive/Lectures_201702}/Week_03/week_3.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_04/Basemap.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_04/HDF.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_04/arcpy_demo.py (100%) rename {Lectures => Archive/Lectures_201702}/Week_04/week_4.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/Week_05/gdal_demo.py (100%) rename {Lectures => Archive/Lectures_201702}/Week_05/week_5.ipynb (100%) rename {Lectures => Archive/Lectures_201702}/readme.md (100%) create mode 100644 Lectures_201706/Week_01/helloworld.py create mode 100644 Lectures_201706/Week_01/readme.md create mode 100644 Lectures_201706/Week_01/setup_intro.ipynb diff --git a/Lectures/Week_01/01_intro.ipynb b/Archive/Lectures_201702/Week_01/01_intro.ipynb similarity index 100% rename from Lectures/Week_01/01_intro.ipynb rename to Archive/Lectures_201702/Week_01/01_intro.ipynb diff --git a/Lectures/Week_01/02_data_structures.ipynb b/Archive/Lectures_201702/Week_01/02_data_structures.ipynb similarity index 100% rename from Lectures/Week_01/02_data_structures.ipynb rename to Archive/Lectures_201702/Week_01/02_data_structures.ipynb diff --git a/Lectures/Week_01/helloworld.py b/Archive/Lectures_201702/Week_01/helloworld.py similarity index 100% rename from Lectures/Week_01/helloworld.py rename to Archive/Lectures_201702/Week_01/helloworld.py diff --git a/Lectures/Week_01/readme.md b/Archive/Lectures_201702/Week_01/readme.md similarity index 100% rename from Lectures/Week_01/readme.md rename to Archive/Lectures_201702/Week_01/readme.md diff --git a/Lectures/Week_01/week_1.ipynb b/Archive/Lectures_201702/Week_01/week_1.ipynb similarity index 100% rename from Lectures/Week_01/week_1.ipynb rename to Archive/Lectures_201702/Week_01/week_1.ipynb diff --git a/Lectures/Week_02/03_FileIO.ipynb b/Archive/Lectures_201702/Week_02/03_FileIO.ipynb similarity index 100% rename from Lectures/Week_02/03_FileIO.ipynb rename to Archive/Lectures_201702/Week_02/03_FileIO.ipynb diff --git a/Lectures/Week_02/04_conditionals_loops.ipynb b/Archive/Lectures_201702/Week_02/04_conditionals_loops.ipynb similarity index 100% rename from Lectures/Week_02/04_conditionals_loops.ipynb rename to Archive/Lectures_201702/Week_02/04_conditionals_loops.ipynb diff --git a/Lectures/Week_02/05_numpy.ipynb b/Archive/Lectures_201702/Week_02/05_numpy.ipynb similarity index 100% rename from Lectures/Week_02/05_numpy.ipynb rename to Archive/Lectures_201702/Week_02/05_numpy.ipynb diff --git a/Lectures/Week_02/sample.csv b/Archive/Lectures_201702/Week_02/sample.csv similarity index 100% rename from Lectures/Week_02/sample.csv rename to Archive/Lectures_201702/Week_02/sample.csv diff --git a/Lectures/Week_02/sample.ipynb b/Archive/Lectures_201702/Week_02/sample.ipynb similarity index 100% rename from Lectures/Week_02/sample.ipynb rename to Archive/Lectures_201702/Week_02/sample.ipynb diff --git a/Lectures/Week_02/week_2.ipynb b/Archive/Lectures_201702/Week_02/week_2.ipynb similarity index 100% rename from Lectures/Week_02/week_2.ipynb rename to Archive/Lectures_201702/Week_02/week_2.ipynb diff --git a/Lectures/Week_03/01_matplotlib.ipynb b/Archive/Lectures_201702/Week_03/01_matplotlib.ipynb similarity index 100% rename from Lectures/Week_03/01_matplotlib.ipynb rename to Archive/Lectures_201702/Week_03/01_matplotlib.ipynb diff --git a/Lectures/Week_03/gdal/array2raster.py b/Archive/Lectures_201702/Week_03/gdal/array2raster.py similarity index 100% rename from Lectures/Week_03/gdal/array2raster.py rename to Archive/Lectures_201702/Week_03/gdal/array2raster.py diff --git a/Lectures/Week_03/gdal/gdal.ipynb b/Archive/Lectures_201702/Week_03/gdal/gdal.ipynb similarity index 100% rename from Lectures/Week_03/gdal/gdal.ipynb rename to Archive/Lectures_201702/Week_03/gdal/gdal.ipynb diff --git a/Lectures/Week_03/gdal/gdal_commands.txt b/Archive/Lectures_201702/Week_03/gdal/gdal_commands.txt similarity index 100% rename from Lectures/Week_03/gdal/gdal_commands.txt rename to Archive/Lectures_201702/Week_03/gdal/gdal_commands.txt diff --git a/Lectures/Week_03/gdal/gdal_example.py b/Archive/Lectures_201702/Week_03/gdal/gdal_example.py similarity index 100% rename from Lectures/Week_03/gdal/gdal_example.py rename to Archive/Lectures_201702/Week_03/gdal/gdal_example.py diff --git a/Lectures/Week_03/week_3.ipynb b/Archive/Lectures_201702/Week_03/week_3.ipynb similarity index 100% rename from Lectures/Week_03/week_3.ipynb rename to Archive/Lectures_201702/Week_03/week_3.ipynb diff --git a/Lectures/Week_04/Basemap.ipynb b/Archive/Lectures_201702/Week_04/Basemap.ipynb similarity index 100% rename from Lectures/Week_04/Basemap.ipynb rename to Archive/Lectures_201702/Week_04/Basemap.ipynb diff --git a/Lectures/Week_04/HDF.ipynb b/Archive/Lectures_201702/Week_04/HDF.ipynb similarity index 100% rename from Lectures/Week_04/HDF.ipynb rename to Archive/Lectures_201702/Week_04/HDF.ipynb diff --git a/Lectures/Week_04/arcpy_demo.py b/Archive/Lectures_201702/Week_04/arcpy_demo.py similarity index 100% rename from Lectures/Week_04/arcpy_demo.py rename to Archive/Lectures_201702/Week_04/arcpy_demo.py diff --git a/Lectures/Week_04/week_4.ipynb b/Archive/Lectures_201702/Week_04/week_4.ipynb similarity index 100% rename from Lectures/Week_04/week_4.ipynb rename to Archive/Lectures_201702/Week_04/week_4.ipynb diff --git a/Lectures/Week_05/gdal_demo.py b/Archive/Lectures_201702/Week_05/gdal_demo.py similarity index 100% rename from Lectures/Week_05/gdal_demo.py rename to Archive/Lectures_201702/Week_05/gdal_demo.py diff --git a/Lectures/Week_05/week_5.ipynb b/Archive/Lectures_201702/Week_05/week_5.ipynb similarity index 100% rename from Lectures/Week_05/week_5.ipynb rename to Archive/Lectures_201702/Week_05/week_5.ipynb diff --git a/Lectures/readme.md b/Archive/Lectures_201702/readme.md similarity index 100% rename from Lectures/readme.md rename to Archive/Lectures_201702/readme.md diff --git a/Lectures_201706/Week_01/helloworld.py b/Lectures_201706/Week_01/helloworld.py new file mode 100644 index 0000000..db55787 --- /dev/null +++ b/Lectures_201706/Week_01/helloworld.py @@ -0,0 +1,3 @@ +print('Hello world!') + +print('Howdy class!') diff --git a/Lectures_201706/Week_01/readme.md b/Lectures_201706/Week_01/readme.md new file mode 100644 index 0000000..3e2694a --- /dev/null +++ b/Lectures_201706/Week_01/readme.md @@ -0,0 +1 @@ +# Week 1 diff --git a/Lectures_201706/Week_01/setup_intro.ipynb b/Lectures_201706/Week_01/setup_intro.ipynb new file mode 100644 index 0000000..26ac42e --- /dev/null +++ b/Lectures_201706/Week_01/setup_intro.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Setup & Introduction\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### June 5, 2017\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Our Setup\n", + "\n", + "---\n", + "\n", + "* Anaconda - Virtual environment (don't need to be root/admin), completely free (and easily managed), from Continuum\n", + "* Enthought Canopy - Virtual environment, not free to add packages/libraries, having several versions gets messy, more business oriented (weirdly is part of Continuum)\n", + "\n", + "##### Computer Setup Instructions\n", + "\n", + "[Basic Setup](https://github.com/edmondb/developython/blob/master/README.md)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Who Are We?\n", + "\n", + "---\n", + "\n", + "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics\n", + "* Alfred Hubbard - Scientific Programmer/Analyst, Code 618; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The Python Programming Language - A Synopsis\n", + "\n", + "---\n", + "\n", + "* Interpreted (think language translator between you and the computer)\n", + "* Ways to run Python Code:\n", + " * __As a .py script (plain text document with python code, I use this method most)__\n", + " * In the Python shell (from the command line - not a good option)\n", + " * In the iPython shell (interactive, better - still not a good option)\n", + " * __In a Jupyter notebook (shareable, you are seeing one now, can run as a script or document)__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### As a script\n", + "\n", + "---\n", + "\n", + "1. Open the helloworld.py script in your text editor to see the contents of this Python script.\n", + "2. In a terminal/command prompt/Anaconda prompt, type:\n", + "\n", + " ```bash\n", + " $ python helloworld.py\n", + " ```\n", + "\n", + "3. You should see the output on the screen.\n", + "\n", + "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Jupyter notebook\n", + "\n", + "---\n", + "\n", + "1. From terminal/command prompt/Anaconda prompt type:\n", + "\n", + " ```bash\n", + " jupyter notebook\n", + " ```\n", + "\n", + "2. This directs you to a web browser and you can navigate to an already existing notebook or create one (right side menu New -> Python [default]).\n", + "3. This will open up a new Untitled notebook where you can directly input Python code, Markup formatted text, or have raw text.\n", + "4. Type:\n", + "\n", + " ```python\n", + " print('Hello world!')\n", + " ```\n", + "\n", + "5. Press __```Shift-Enter```__, __```Cntrl-Enter```__, or click __Cells -> Run Cells__ or use the Play button near the top of the page.\n", + "6. You will see the output now.\n", + "7. Exit via closing the browser windows and stopping the server running (Cntrl + Enter) in the terminal/command prompt." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quick Python Intro\n", + "\n", + "---\n", + "\n", + "Based off of: [Learn X in Y](http://learnxinyminutes.com/docs/python/)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Single line comments start with a number symbol.\n", + "\n", + "\"\"\" Multiline strings can be written\n", + " using three \"s or 's, and are often used\n", + " as comments\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-26\n" + ] + } + ], + "source": [ + "# store inside a variable\n", + "result = -2*(4+9)\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.141592653589793" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Imports\n", + "\n", + "import math\n", + "math.pi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Python imports are like libraries/utilities that others have written for you to use. You can import packages (set of scripts) or modules (single scripts).\n", + "\n", + "The Python Style Guide tells you the best way to perform imports, name functions, and overall coding advice. It used to be called PEP8 (Python Enhancement Proposal 8), but in 2016, it was renamed to pycodestyle.\n", + "\n", + "* [PEP8](http://www.python.org/dev/peps/pep-0008/)\n", + "* [pep8.org](http://pep8.org) - a more human friendly approach" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Strings__\n", + "\n", + "* Single-quotes: `'a string'`\n", + "* Double-quotes: `\"another string\"`\n", + "* Joining/concatenation: `'FirstName' + 'LastName'`\n", + "* Formatting: [PyFormat](http://pyformat.info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Iterables__\n", + "\n", + "* Lists (think strings as a list of characters; grocery lists):\n", + "\n", + " ```python\n", + " a_list = ['item 1', 'something else', 2, True, 'and so on']\n", + " another = list('hello')\n", + " ```\n", + "* Tuples (like lists, but not changing)\n", + " \n", + " ```python\n", + " numbers = (1,2,3)\n", + " first, second, third = numbers\n", + " another = tuple('one', 'two')\n", + " ```\n", + " \n", + "* Dictionaries (key/value pairing; like a word dictionary)\n", + " \n", + " ```python\n", + " d = {'key1':'value', 'key2':20, 3:['a', 'list'], 'k5':{'a':'nested','dict':'!'}}\n", + " another = dict(key='value', key2='another')\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Control flow__\n", + "\n", + "---\n", + "\n", + "__conditionals__\n", + "\n", + "```python\n", + "some_var = 5\n", + "\n", + "if some_var > 10:\n", + " print(\"some_var is totally bigger than 10.\")\n", + "elif some_var < 10: # This elif clause is optional.\n", + " print(\"some_var is smaller than 10.\")\n", + "else: # This is optional too.\n", + " print(\"some_var is indeed 10.\")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__loops__\n", + "\n", + "```python\n", + "for i in range(4):\n", + " print(i)\n", + "```\n", + "\n", + "```python\n", + "# conditionally based\n", + "x = 0\n", + "while x < 4:\n", + " print(x)\n", + " x += 1\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 723c302059c5f4c8898aa1ad7bdcdcfb6cc41596 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Mon, 5 Jun 2017 09:46:45 -0400 Subject: [PATCH 48/57] touched file --- Lectures_201706/readme.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Lectures_201706/readme.md diff --git a/Lectures_201706/readme.md b/Lectures_201706/readme.md new file mode 100644 index 0000000..e69de29 From 0f4eb4eea1b85e3171e915e1ad6339c784040984 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Tue, 6 Jun 2017 09:19:19 -0400 Subject: [PATCH 49/57] final --- Lectures_201706/Week_01/setup_intro.ipynb | 43 +++-------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/Lectures_201706/Week_01/setup_intro.ipynb b/Lectures_201706/Week_01/setup_intro.ipynb index 26ac42e..a51370d 100644 --- a/Lectures_201706/Week_01/setup_intro.ipynb +++ b/Lectures_201706/Week_01/setup_intro.ipynb @@ -138,17 +138,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-26\n" - ] - } - ], + "outputs": [], "source": [ "# store inside a variable\n", "result = -2*(4+9)\n", @@ -157,20 +149,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3.141592653589793" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Imports\n", "\n", @@ -271,22 +252,6 @@ " x += 1\n", "```" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Break" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] } ], "metadata": { From 0c2111ebb59cd2eaef63fe0eac23364d7d9d3ae3 Mon Sep 17 00:00:00 2001 From: Brent Smith Date: Tue, 13 Jun 2017 12:46:36 -0400 Subject: [PATCH 50/57] week 2 --- Lectures_201706/Week_02/intro_cont.ipynb | 246 +++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 Lectures_201706/Week_02/intro_cont.ipynb diff --git a/Lectures_201706/Week_02/intro_cont.ipynb b/Lectures_201706/Week_02/intro_cont.ipynb new file mode 100644 index 0000000..bb52a75 --- /dev/null +++ b/Lectures_201706/Week_02/intro_cont.ipynb @@ -0,0 +1,246 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Introduction Continued\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### June 13, 2017\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recap\n", + "\n", + "---\n", + "\n", + "* Anaconda installation - virtual environment - using the Jupyter notebook (not the only way to execute Python code)\n", + "* Python as a calculator (simple math)\n", + "* Imports and the power they possess\n", + "* Strings, formatting, and printing\n", + "* Data types\n", + "* Conditionals\n", + "* Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting this lecture...\n", + "\n", + "---\n", + "\n", + "You can download this lecture here by copying all the text and then saving it in an ASCII file (using a text editor) with the .ipynb extension. We will be using the code in this notebook interactively and you will probably want to run it yourself.\n", + "\n", + "# Important\n", + "\n", + "Please install the _netCDF4_ Python package first from your Anaconda command prompt via:\n", + "\n", + "```bash\n", + "conda install netCDF4\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### File I/O\n", + "\n", + "---\n", + "\n", + "File types:\n", + "* __ASCII/Binary__ - simple (binary isn't if you don't know the format)\n", + "* __CSV/JSON files__ - need specific format reader/writer package\n", + "* __Earth Science Structured data - HDF, netCDF4, etc.__ - more complex" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ASCII/Binary\n", + "\n", + "---\n", + "\n", + "Old:\n", + "```python\n", + "f = open('filename.ascii', 'w')\n", + "f.write('Hi there.')\n", + "f.close()\n", + "```\n", + "\n", + "New:\n", + "```python\n", + "with open('filename.ascii', 'w') as f:\n", + " f.write('Hi there.')\n", + "```\n", + "\n", + "__Note:__ Binary read/write is simply just adding a _'b'_ after the mode of opening the file (eg. 'wb' for writing binary). \n", + "> __File modes:__ r, w, a, + versions, b versions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Although I'm not going to cover them, CSV and JSON file content types are very useful in applications today. Most web applications (GET/POST requests) use JSON for data transactions. The __[csv](http://docs.python.org/2/library/csv.html)__ and __[json](http://docs.python.org/2/library/json.html)__ packages are very useful for dealing with these data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> _pickles..._ Python has this thing called pickles where you \"temporarily\" store data. It's a binary file, but is only for small storage that is needed for a short time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Science Structured Data\n", + "\n", + "---\n", + "\n", + "The __[h5py]()__ and __[netCDF4]()__ Python packages are very useful for reading structured data (multidimensional, multivariate, time-series, etc.). Here, we are going to look at reading and visualizing some structured data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ISS RapidScat Data - netCDF4\n", + "\n", + "---\n", + "\n", + "- Make sure you have installed the _netCDF4_ Python package.\n", + "- Retrieve the data via FTP:\n", + "\n", + "[Link for manual download via FTP](ftp://podaac-ftp.jpl.nasa.gov/allData/rapidscat/L2B12/v1.3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import ftplib\n", + "\n", + "ftp = ftplib.FTP('podaac-ftp.jpl.nasa.gov')\n", + "ftp.login()\n", + "ftp.cwd('allData/rapidscat/L2B12/v1.3/2016/232')\n", + "ftp.retrbinary('RETR rs_l2b_v1.3_10827_201609290531.nc.gz', open('ISS.nc.gz', 'wb').write)\n", + "ftp.quit()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "- Manually unzip/uncompress this file.\n", + "- Let's read the data now..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import netCDF4 as nc\n", + "\n", + "f = nc.Dataset('ISS.nc', 'r')\n", + "print(f.variables.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z = f.variables['retrieved_wind_speed']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z.dimensions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing\n", + "\n", + "---\n", + "\n", + "Matplotlib is basically Python's replacement for Matlab. Here is an example of plotting data from our file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = plt.figure(figsize = (20,20))\n", + "ax = fig.add_subplot(111)\n", + "img = ax.imshow(f.variables['retrieved_wind_speed'][:].transpose(), interpolation=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could extend this to actually visualize the data plotted on a map (using the Basemap package) and manipulate the NumPy array to give us statistics or further insight into what the data shows us and how it is characterized." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 27b898383a74d14b529918b2fd11d09b0fa7baf2 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Thu, 15 Jun 2017 14:54:33 -0400 Subject: [PATCH 51/57] Empty --- Lectures_201706/Week_03/empty | 1 + 1 file changed, 1 insertion(+) create mode 100644 Lectures_201706/Week_03/empty diff --git a/Lectures_201706/Week_03/empty b/Lectures_201706/Week_03/empty new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Lectures_201706/Week_03/empty @@ -0,0 +1 @@ + From 16bc825593b683ec2d3a998efd7a6c13eb871458 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Thu, 15 Jun 2017 14:58:18 -0400 Subject: [PATCH 52/57] Uploaded lecture --- Lectures_201706/Week_03/Week_03.ipynb | 533 ++++++++++++++++++++++++++ 1 file changed, 533 insertions(+) create mode 100644 Lectures_201706/Week_03/Week_03.ipynb diff --git a/Lectures_201706/Week_03/Week_03.ipynb b/Lectures_201706/Week_03/Week_03.ipynb new file mode 100644 index 0000000..aa6e43f --- /dev/null +++ b/Lectures_201706/Week_03/Week_03.ipynb @@ -0,0 +1,533 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# GIS Automation through ArcPy\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### March 6, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ArcPy\n", + "\n", + "---\n", + "\n", + "* Python package created by Esri to allow ArcGIS tools to be called from Python\n", + "* This enables all manner of geoprocessing to be done in an automated fashion, as ArcPy can replicate most of the functionality of ArcGIS for Desktop\n", + "* While ArcGIS comes with its own version of Python, ArcPy can be used with other Python installations, as we will do in this course\n", + "* For reference, see the documentation for your version of ArcGIS. The help page for each tool has a description of the Python syntax and (usually) short example scripts.\n", + " * For instance: http://desktop.arcgis.com/en/arcmap/10.4/tools/data-management-toolbox/clip.htm (scroll down)\n", + "* Another resource: [Penn State online course](https://www.e-education.psu.edu/geog485/node/91) covering the same subject matter as this lecture, GIS automation with Python.\n", + "* Possibly the best resource of all: Google\n", + " * While not as well supported as the really popular Python packages (i.e. NumPy, matplotlib, etc.), enough people use ArcPy that you will find decent support on forums like Stack Overflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example Project: Fun with MODIS LST Data\n", + "\n", + "---\n", + "\n", + "* To get a feel for automating typical GIS tasks, we will work through a short project where we:\n", + " * download some MODIS land surface temperature (LST) data\n", + " * extract the bands we want to GeoTIFF\n", + " * perform some analysis, including raster math and conditionals\n", + " * resample the output\n", + " * ... and repeat\n", + "\n", + "### Test ArcPy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import arcpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download data\n", + "\n", + "---\n", + "\n", + "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "\n", + "Copy it to the directory where you want to store your data.\n", + "\n", + "### Set working directory\n", + "\n", + "---\n", + "\n", + "ArcPy needs to know where to look for inputs and save outputs on your computer. You can specify an absolute path for every file, meaning a path including not only the file name but all the parent directories, including the drive name (i.e. C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\\\\thatwasalotoftyping.tif). However, this can grow tedious, so it is usually easier to set the workspace environment (more on these later) to a location of your choosing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Change this path to the directory where you saved the MODIS data in the above step. Now, all you need to provide is a file name, and ArcPy will automatically go to this folder.\n", + "\n", + "Another consideration is that, by default, ArcPy will not permit you to overwrite files that already exist. When you are developing a script, this is usually not what you want (but not always - be careful!). Allow ArcPy to overwrite output as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.overwriteOutput = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract from HDF to GeoTIFF\n", + "\n", + "---\n", + "\n", + "With many data types, we would be ready to jump straight in to geoprocessing. However, with MODIS data we have an immediate hurdle: HDF. Fully-featured handling of HDF files requires special Python packages, like h5py, as covered in the previous lecture. For our project, however, this would be overkill. Instead, we can use ArcPy's Extract SubDataset to pull out the data we want into a GeoTIFF.\n", + "\n", + "Let's extract the daytime LST data, which is subdataset 0:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "day_LST = MODIS_file.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, day_LST, subdataset_index=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ `rstrip` is a string method that removes the string given in the parentheses from the end (right side) of the input string.\n", + "\n", + "To inspect the output, open ArcMap and load this file. Add an imagery basemap as well and compare the two, noting areas of high and low temperature values. Do you see anything strange?\n", + "\n", + "### Perform analysis\n", + "\n", + "---\n", + "\n", + "#### Raster Math\n", + "\n", + "The above data has been scaled to allow it to be stored in an integer format, but this makes it difficult to interpret. To convert it back to Kelvin, we must apply the scale factor, which in this case is 0.02. To do this, we will perform some raster math." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "day_LST_sc = arcpy.Raster(day_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ArcPy allows basic math operations to be applied on a pixel-by-pixel basis with Python syntax, but it is necessary to create an ArcPy Raster object from your raster file on disk. The math operation returns another ArcPy Raster object, which we have assigned to `day_LST_sc`. Think of these Raster objects in an analogous manner to the data types we covered before, like string, float, int, etc. They can be used in other math operations and passed to some (but not all) ArcGIS tools that take raster input.\n", + "\n", + "Notice the lines before and after the middle block. Raster math requires the Spatial Analyst extension, so it is necessary to check out a license for this extension first. Checking the license back in at the end is not necessary for the code to function, but it is good practice, because your organization may have a license server with limited keys.\n", + "\n", + "At the moment, our scaled daytime LST raster only exists in memory - we have not saved it to disk. To do so:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "path = MODIS_file.rstrip(\".hdf\") + \"_scale.tif\"\n", + "day_LST_sc.save(path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Math with multiple rasters\n", + "\n", + "In a similar manner, two or more rasters can be used in a formula using simple Python syntax. But first, we need two rasters! Let's repeat the above steps with the nighttime LST band (subdataset 4), from the same MODIS file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "night_LST = MODIS_file.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, night_LST, subdataset_index=4)\n", + "\n", + "scale = 0.02\n", + "night_LST_sc = arcpy.Raster(night_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ In this case, we did not save the scaled raster to disk. This is not actually necessary to use it in later operations, and not saving intermediates is a good way to conserve disk space.\n", + "\n", + "_Another Note:_ In these examples, we are checking the spatial analyst extension in and out each time, but, if you are writing a long script, it is only necessary to do this once, at the beginning and end.\n", + "\n", + "Now, let's compute the difference between the daytime and nighttime LST:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "diff = day_LST_sc - night_LST_sc\n", + "diff_path = MODIS_file.rstrip(\".hdf\")+\"_diff.tif\"\n", + "diff.save(diff_path)\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This will create a new Raster object where each pixel corresponds to the difference between the two old rasters. Open this new raster in ArcMap and compare it to a basemap.\n", + "\n", + "#### Conditionals\n", + "\n", + "Suppose we want to know where the above difference exceeds a certain threshold. We can answer this question using the Con tool, available with the Spatial Analyst extension." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "thres = 15\n", + "diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + "diff_thres_path = MODIS_file.rstrip(\".hdf\")+\"_thres.tif\"\n", + "diff_thres.save(diff_thres_path)\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The middle block of code will create and save a raster that contains a 1 wherever the day-night difference exceeds 15, and a 0 wherever it does not.\n", + "\n", + "### Resample\n", + "\n", + "---\n", + "\n", + "We now have a nice Boolean raster that we could use as a mask in some larger project. However, what if the other members of our project are working with the MODIS red and NIR bands, which are 250 m resolution? We can be helpful, and resample our raster to this resolution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "out_cellsize = 231.6563583\n", + "res = MODIS_file.rstrip(\".hdf\") + \"_res.tif\"\n", + "arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could have performed this resampling at any point in our processing chain, but we chose to do so at the end. Why might this be best?\n", + "\n", + "### Repeat as necessary\n", + "\n", + "---\n", + "\n", + "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", + "\n", + "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", + "* winter: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", + "* spring: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", + "* and fall: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", + "\n", + "Move these to the same folder you have been using.\n", + "\n", + "Now, let's put everything we did above in a loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'CheckedIn'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff_path = f.rstrip(\".hdf\")+\"_diff.tif\"\n", + " diff.save(diff_path)\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres_path = f.rstrip(\".hdf\")+\"_thres.tif\"\n", + " diff_thres.save(diff_thres_path)\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Tip:_ If you need to get the names of many files in a folder and don't want to do a lot of tedious typing, check out the [glob](https://docs.python.org/2/library/glob.html) package.\n", + "\n", + "\n", + "\n", + "# Other Considerations\n", + "\n", + "---\n", + "\n", + "### Environments\n", + "\n", + "---\n", + "\n", + "ArcGIS uses environment settings to control the specific characteristics of your current geoprocessing environment. In the above script, we are using two already: workspace and overwrite output. Environments are a powerful way to control the exact way in which your script executes. As another example, let's say that within our MODIS tile, we only really care about Virginia (because it is objectively better than all of these other states), and we want to limit output to this state.\n", + "\n", + "One approach might be to clip each input raster with a shapefile, but we have to do this for each input. In this case, we only have two per iteration, but in other projects we might have a lot more. A more elegant approach is to use the mask environment setting.\n", + "\n", + "Download [this](https://drive.google.com/file/d/0B8toI67HoVSrVzV3aUcwc3FBcG8/view?usp=sharing) shapefile of Virginia, and extract it to your work directory. Then, rerun our script with the mask environment set at the top:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.env.mask = \"Virginia.shp\"\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff.save(f.rstrip(\".hdf\")+\"_diff.tif\")\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres.save(f.rstrip(\".hdf\")+\"_thres.tif\")\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")\n", + "\n", + "arcpy.env.workspace = None\n", + "arcpy.env.overwriteOutput = None\n", + "arcpy.env.mask = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspect the output. If everything worked properly, you should only see data over the scenic Commonwealth of Virginia\n", + "\n", + "__Very important note:__ The nature of environment settings is that they apply to your _entire processing environment_, which means they will stick around for future processes you run in the same session of Python. Old environment settings can lead to mysterious errors, confusion, and general gnashing of teeth. I highly recommend that you clear out your environment settings at the end of your script by setting them to `None`, as I have done above. Even better, clear them immediately after they are no longer needed, in case your script crashes before it completes.\n", + "\n", + "### Editing locks\n", + "\n", + "---\n", + "\n", + "Whenever a program is using a file, it creates a lock that prevents other programs from editing the same file. Python is no different. In general, these should disappear after a script is finished executing. For reasons that are not entirely clear to me, ArcPy often retains locks on ArcPy objects created by a script even said script has completed. This will create problems if you then try to edit the file that object is pointing to in a different program. Therefore, it is also good practice to clear variables that point to ArcPy objects after they are no longer necessary. To accomplish that in our script, add the following to the end:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "day_LST_sc = None\n", + "night_LST_sc = None\n", + "diff = None\n", + "diff_thres = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On the other side of the same coin, Python will not be able to edit a file that is locked by another application. In the context of geoprocessing, this can happen because you ran your code, viewed the output in ArcMap, and tried to rerun your code without removing said output from ArcMap. Some of you may have already experienced this phenomenon during this lesson. If you're me, this happens _all the time_..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 43425d70f47d8ab36c845a937407398fed27de49 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Thu, 15 Jun 2017 14:58:36 -0400 Subject: [PATCH 53/57] Delete empty --- Lectures_201706/Week_03/empty | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Lectures_201706/Week_03/empty diff --git a/Lectures_201706/Week_03/empty b/Lectures_201706/Week_03/empty deleted file mode 100644 index 8b13789..0000000 --- a/Lectures_201706/Week_03/empty +++ /dev/null @@ -1 +0,0 @@ - From 54d700d4104157cb30e6f3ff6a1705309ce0736b Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 24 Sep 2017 13:24:37 -0400 Subject: [PATCH 54/57] Archived summer lectures; created new copies for fall --- .../Lectures_201706}/Week_01/helloworld.py | 0 .../Lectures_201706}/Week_01/readme.md | 0 .../Week_01/setup_intro.ipynb | 0 .../Lectures_201706}/Week_02/intro_cont.ipynb | 0 .../Lectures_201706}/Week_03/Week_03.ipynb | 0 .../Lectures_201706}/readme.md | 0 Lectures_201709/Week_01/helloworld.py | 3 + Lectures_201709/Week_01/readme.md | 1 + Lectures_201709/Week_01/setup_intro.ipynb | 278 +++++++++ Lectures_201709/Week_02/intro_cont.ipynb | 246 ++++++++ Lectures_201709/Week_03/GIS_programming.ipynb | 533 ++++++++++++++++++ Lectures_201709/readme.md | 0 12 files changed, 1061 insertions(+) rename {Lectures_201706 => Archive/Lectures_201706}/Week_01/helloworld.py (100%) rename {Lectures_201706 => Archive/Lectures_201706}/Week_01/readme.md (100%) rename {Lectures_201706 => Archive/Lectures_201706}/Week_01/setup_intro.ipynb (100%) rename {Lectures_201706 => Archive/Lectures_201706}/Week_02/intro_cont.ipynb (100%) rename {Lectures_201706 => Archive/Lectures_201706}/Week_03/Week_03.ipynb (100%) rename {Lectures_201706 => Archive/Lectures_201706}/readme.md (100%) create mode 100644 Lectures_201709/Week_01/helloworld.py create mode 100644 Lectures_201709/Week_01/readme.md create mode 100644 Lectures_201709/Week_01/setup_intro.ipynb create mode 100644 Lectures_201709/Week_02/intro_cont.ipynb create mode 100644 Lectures_201709/Week_03/GIS_programming.ipynb create mode 100644 Lectures_201709/readme.md diff --git a/Lectures_201706/Week_01/helloworld.py b/Archive/Lectures_201706/Week_01/helloworld.py similarity index 100% rename from Lectures_201706/Week_01/helloworld.py rename to Archive/Lectures_201706/Week_01/helloworld.py diff --git a/Lectures_201706/Week_01/readme.md b/Archive/Lectures_201706/Week_01/readme.md similarity index 100% rename from Lectures_201706/Week_01/readme.md rename to Archive/Lectures_201706/Week_01/readme.md diff --git a/Lectures_201706/Week_01/setup_intro.ipynb b/Archive/Lectures_201706/Week_01/setup_intro.ipynb similarity index 100% rename from Lectures_201706/Week_01/setup_intro.ipynb rename to Archive/Lectures_201706/Week_01/setup_intro.ipynb diff --git a/Lectures_201706/Week_02/intro_cont.ipynb b/Archive/Lectures_201706/Week_02/intro_cont.ipynb similarity index 100% rename from Lectures_201706/Week_02/intro_cont.ipynb rename to Archive/Lectures_201706/Week_02/intro_cont.ipynb diff --git a/Lectures_201706/Week_03/Week_03.ipynb b/Archive/Lectures_201706/Week_03/Week_03.ipynb similarity index 100% rename from Lectures_201706/Week_03/Week_03.ipynb rename to Archive/Lectures_201706/Week_03/Week_03.ipynb diff --git a/Lectures_201706/readme.md b/Archive/Lectures_201706/readme.md similarity index 100% rename from Lectures_201706/readme.md rename to Archive/Lectures_201706/readme.md diff --git a/Lectures_201709/Week_01/helloworld.py b/Lectures_201709/Week_01/helloworld.py new file mode 100644 index 0000000..db55787 --- /dev/null +++ b/Lectures_201709/Week_01/helloworld.py @@ -0,0 +1,3 @@ +print('Hello world!') + +print('Howdy class!') diff --git a/Lectures_201709/Week_01/readme.md b/Lectures_201709/Week_01/readme.md new file mode 100644 index 0000000..3e2694a --- /dev/null +++ b/Lectures_201709/Week_01/readme.md @@ -0,0 +1 @@ +# Week 1 diff --git a/Lectures_201709/Week_01/setup_intro.ipynb b/Lectures_201709/Week_01/setup_intro.ipynb new file mode 100644 index 0000000..a51370d --- /dev/null +++ b/Lectures_201709/Week_01/setup_intro.ipynb @@ -0,0 +1,278 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Setup & Introduction\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### June 5, 2017\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Our Setup\n", + "\n", + "---\n", + "\n", + "* Anaconda - Virtual environment (don't need to be root/admin), completely free (and easily managed), from Continuum\n", + "* Enthought Canopy - Virtual environment, not free to add packages/libraries, having several versions gets messy, more business oriented (weirdly is part of Continuum)\n", + "\n", + "##### Computer Setup Instructions\n", + "\n", + "[Basic Setup](https://github.com/edmondb/developython/blob/master/README.md)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Who Are We?\n", + "\n", + "---\n", + "\n", + "* Brent Smith - Senior Scientific Programmer/Analyst, Code 610.1 GMAO - Operational developer, background: theoretical space physics\n", + "* Alfred Hubbard - Scientific Programmer/Analyst, Code 618; maps floods, vegetation, and sometimes other stuff with remotely sensed imagery; uses Python regularly to aid GIS analysis; background in biology and environmental science" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The Python Programming Language - A Synopsis\n", + "\n", + "---\n", + "\n", + "* Interpreted (think language translator between you and the computer)\n", + "* Ways to run Python Code:\n", + " * __As a .py script (plain text document with python code, I use this method most)__\n", + " * In the Python shell (from the command line - not a good option)\n", + " * In the iPython shell (interactive, better - still not a good option)\n", + " * __In a Jupyter notebook (shareable, you are seeing one now, can run as a script or document)__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### As a script\n", + "\n", + "---\n", + "\n", + "1. Open the helloworld.py script in your text editor to see the contents of this Python script.\n", + "2. In a terminal/command prompt/Anaconda prompt, type:\n", + "\n", + " ```bash\n", + " $ python helloworld.py\n", + " ```\n", + "\n", + "3. You should see the output on the screen.\n", + "\n", + "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Jupyter notebook\n", + "\n", + "---\n", + "\n", + "1. From terminal/command prompt/Anaconda prompt type:\n", + "\n", + " ```bash\n", + " jupyter notebook\n", + " ```\n", + "\n", + "2. This directs you to a web browser and you can navigate to an already existing notebook or create one (right side menu New -> Python [default]).\n", + "3. This will open up a new Untitled notebook where you can directly input Python code, Markup formatted text, or have raw text.\n", + "4. Type:\n", + "\n", + " ```python\n", + " print('Hello world!')\n", + " ```\n", + "\n", + "5. Press __```Shift-Enter```__, __```Cntrl-Enter```__, or click __Cells -> Run Cells__ or use the Play button near the top of the page.\n", + "6. You will see the output now.\n", + "7. Exit via closing the browser windows and stopping the server running (Cntrl + Enter) in the terminal/command prompt." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quick Python Intro\n", + "\n", + "---\n", + "\n", + "Based off of: [Learn X in Y](http://learnxinyminutes.com/docs/python/)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Single line comments start with a number symbol.\n", + "\n", + "\"\"\" Multiline strings can be written\n", + " using three \"s or 's, and are often used\n", + " as comments\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# store inside a variable\n", + "result = -2*(4+9)\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Imports\n", + "\n", + "import math\n", + "math.pi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Python imports are like libraries/utilities that others have written for you to use. You can import packages (set of scripts) or modules (single scripts).\n", + "\n", + "The Python Style Guide tells you the best way to perform imports, name functions, and overall coding advice. It used to be called PEP8 (Python Enhancement Proposal 8), but in 2016, it was renamed to pycodestyle.\n", + "\n", + "* [PEP8](http://www.python.org/dev/peps/pep-0008/)\n", + "* [pep8.org](http://pep8.org) - a more human friendly approach" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Strings__\n", + "\n", + "* Single-quotes: `'a string'`\n", + "* Double-quotes: `\"another string\"`\n", + "* Joining/concatenation: `'FirstName' + 'LastName'`\n", + "* Formatting: [PyFormat](http://pyformat.info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Iterables__\n", + "\n", + "* Lists (think strings as a list of characters; grocery lists):\n", + "\n", + " ```python\n", + " a_list = ['item 1', 'something else', 2, True, 'and so on']\n", + " another = list('hello')\n", + " ```\n", + "* Tuples (like lists, but not changing)\n", + " \n", + " ```python\n", + " numbers = (1,2,3)\n", + " first, second, third = numbers\n", + " another = tuple('one', 'two')\n", + " ```\n", + " \n", + "* Dictionaries (key/value pairing; like a word dictionary)\n", + " \n", + " ```python\n", + " d = {'key1':'value', 'key2':20, 3:['a', 'list'], 'k5':{'a':'nested','dict':'!'}}\n", + " another = dict(key='value', key2='another')\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Control flow__\n", + "\n", + "---\n", + "\n", + "__conditionals__\n", + "\n", + "```python\n", + "some_var = 5\n", + "\n", + "if some_var > 10:\n", + " print(\"some_var is totally bigger than 10.\")\n", + "elif some_var < 10: # This elif clause is optional.\n", + " print(\"some_var is smaller than 10.\")\n", + "else: # This is optional too.\n", + " print(\"some_var is indeed 10.\")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__loops__\n", + "\n", + "```python\n", + "for i in range(4):\n", + " print(i)\n", + "```\n", + "\n", + "```python\n", + "# conditionally based\n", + "x = 0\n", + "while x < 4:\n", + " print(x)\n", + " x += 1\n", + "```" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Lectures_201709/Week_02/intro_cont.ipynb b/Lectures_201709/Week_02/intro_cont.ipynb new file mode 100644 index 0000000..bb52a75 --- /dev/null +++ b/Lectures_201709/Week_02/intro_cont.ipynb @@ -0,0 +1,246 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# Introduction Continued\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### June 13, 2017\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recap\n", + "\n", + "---\n", + "\n", + "* Anaconda installation - virtual environment - using the Jupyter notebook (not the only way to execute Python code)\n", + "* Python as a calculator (simple math)\n", + "* Imports and the power they possess\n", + "* Strings, formatting, and printing\n", + "* Data types\n", + "* Conditionals\n", + "* Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Getting this lecture...\n", + "\n", + "---\n", + "\n", + "You can download this lecture here by copying all the text and then saving it in an ASCII file (using a text editor) with the .ipynb extension. We will be using the code in this notebook interactively and you will probably want to run it yourself.\n", + "\n", + "# Important\n", + "\n", + "Please install the _netCDF4_ Python package first from your Anaconda command prompt via:\n", + "\n", + "```bash\n", + "conda install netCDF4\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### File I/O\n", + "\n", + "---\n", + "\n", + "File types:\n", + "* __ASCII/Binary__ - simple (binary isn't if you don't know the format)\n", + "* __CSV/JSON files__ - need specific format reader/writer package\n", + "* __Earth Science Structured data - HDF, netCDF4, etc.__ - more complex" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ASCII/Binary\n", + "\n", + "---\n", + "\n", + "Old:\n", + "```python\n", + "f = open('filename.ascii', 'w')\n", + "f.write('Hi there.')\n", + "f.close()\n", + "```\n", + "\n", + "New:\n", + "```python\n", + "with open('filename.ascii', 'w') as f:\n", + " f.write('Hi there.')\n", + "```\n", + "\n", + "__Note:__ Binary read/write is simply just adding a _'b'_ after the mode of opening the file (eg. 'wb' for writing binary). \n", + "> __File modes:__ r, w, a, + versions, b versions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Although I'm not going to cover them, CSV and JSON file content types are very useful in applications today. Most web applications (GET/POST requests) use JSON for data transactions. The __[csv](http://docs.python.org/2/library/csv.html)__ and __[json](http://docs.python.org/2/library/json.html)__ packages are very useful for dealing with these data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> _pickles..._ Python has this thing called pickles where you \"temporarily\" store data. It's a binary file, but is only for small storage that is needed for a short time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Science Structured Data\n", + "\n", + "---\n", + "\n", + "The __[h5py]()__ and __[netCDF4]()__ Python packages are very useful for reading structured data (multidimensional, multivariate, time-series, etc.). Here, we are going to look at reading and visualizing some structured data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ISS RapidScat Data - netCDF4\n", + "\n", + "---\n", + "\n", + "- Make sure you have installed the _netCDF4_ Python package.\n", + "- Retrieve the data via FTP:\n", + "\n", + "[Link for manual download via FTP](ftp://podaac-ftp.jpl.nasa.gov/allData/rapidscat/L2B12/v1.3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import ftplib\n", + "\n", + "ftp = ftplib.FTP('podaac-ftp.jpl.nasa.gov')\n", + "ftp.login()\n", + "ftp.cwd('allData/rapidscat/L2B12/v1.3/2016/232')\n", + "ftp.retrbinary('RETR rs_l2b_v1.3_10827_201609290531.nc.gz', open('ISS.nc.gz', 'wb').write)\n", + "ftp.quit()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "- Manually unzip/uncompress this file.\n", + "- Let's read the data now..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import netCDF4 as nc\n", + "\n", + "f = nc.Dataset('ISS.nc', 'r')\n", + "print(f.variables.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z = f.variables['retrieved_wind_speed']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "z.dimensions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing\n", + "\n", + "---\n", + "\n", + "Matplotlib is basically Python's replacement for Matlab. Here is an example of plotting data from our file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig = plt.figure(figsize = (20,20))\n", + "ax = fig.add_subplot(111)\n", + "img = ax.imshow(f.variables['retrieved_wind_speed'][:].transpose(), interpolation=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could extend this to actually visualize the data plotted on a map (using the Basemap package) and manipulate the NumPy array to give us statistics or further insight into what the data shows us and how it is characterized." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Lectures_201709/Week_03/GIS_programming.ipynb b/Lectures_201709/Week_03/GIS_programming.ipynb new file mode 100644 index 0000000..aa6e43f --- /dev/null +++ b/Lectures_201709/Week_03/GIS_programming.ipynb @@ -0,0 +1,533 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![NASA](http://www.nasa.gov/sites/all/themes/custom/nasatwo/images/nasa-logo.svg)\n", + "![DEVELOP](../../DEVELOP_logo.png)\n", + "\n", + "---\n", + "\n", + "# GIS Automation through ArcPy\n", + "\n", + "### Goddard Space Flight Center\n", + "\n", + "#### March 6, 2017\n", + "\n", + "---\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ArcPy\n", + "\n", + "---\n", + "\n", + "* Python package created by Esri to allow ArcGIS tools to be called from Python\n", + "* This enables all manner of geoprocessing to be done in an automated fashion, as ArcPy can replicate most of the functionality of ArcGIS for Desktop\n", + "* While ArcGIS comes with its own version of Python, ArcPy can be used with other Python installations, as we will do in this course\n", + "* For reference, see the documentation for your version of ArcGIS. The help page for each tool has a description of the Python syntax and (usually) short example scripts.\n", + " * For instance: http://desktop.arcgis.com/en/arcmap/10.4/tools/data-management-toolbox/clip.htm (scroll down)\n", + "* Another resource: [Penn State online course](https://www.e-education.psu.edu/geog485/node/91) covering the same subject matter as this lecture, GIS automation with Python.\n", + "* Possibly the best resource of all: Google\n", + " * While not as well supported as the really popular Python packages (i.e. NumPy, matplotlib, etc.), enough people use ArcPy that you will find decent support on forums like Stack Overflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example Project: Fun with MODIS LST Data\n", + "\n", + "---\n", + "\n", + "* To get a feel for automating typical GIS tasks, we will work through a short project where we:\n", + " * download some MODIS land surface temperature (LST) data\n", + " * extract the bands we want to GeoTIFF\n", + " * perform some analysis, including raster math and conditionals\n", + " * resample the output\n", + " * ... and repeat\n", + "\n", + "### Test ArcPy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import arcpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download data\n", + "\n", + "---\n", + "\n", + "Download this MODIS image: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/201/MOD11A2.A2016201.h11v05.006.2016242234243.hdf \n", + "\n", + "Copy it to the directory where you want to store your data.\n", + "\n", + "### Set working directory\n", + "\n", + "---\n", + "\n", + "ArcPy needs to know where to look for inputs and save outputs on your computer. You can specify an absolute path for every file, meaning a path including not only the file name but all the parent directories, including the drive name (i.e. C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\\\\thatwasalotoftyping.tif). However, this can grow tedious, so it is usually easier to set the workspace environment (more on these later) to a location of your choosing:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Change this path to the directory where you saved the MODIS data in the above step. Now, all you need to provide is a file name, and ArcPy will automatically go to this folder.\n", + "\n", + "Another consideration is that, by default, ArcPy will not permit you to overwrite files that already exist. When you are developing a script, this is usually not what you want (but not always - be careful!). Allow ArcPy to overwrite output as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "arcpy.env.overwriteOutput = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract from HDF to GeoTIFF\n", + "\n", + "---\n", + "\n", + "With many data types, we would be ready to jump straight in to geoprocessing. However, with MODIS data we have an immediate hurdle: HDF. Fully-featured handling of HDF files requires special Python packages, like h5py, as covered in the previous lecture. For our project, however, this would be overkill. Instead, we can use ArcPy's Extract SubDataset to pull out the data we want into a GeoTIFF.\n", + "\n", + "Let's extract the daytime LST data, which is subdataset 0:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "day_LST = MODIS_file.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, day_LST, subdataset_index=0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ `rstrip` is a string method that removes the string given in the parentheses from the end (right side) of the input string.\n", + "\n", + "To inspect the output, open ArcMap and load this file. Add an imagery basemap as well and compare the two, noting areas of high and low temperature values. Do you see anything strange?\n", + "\n", + "### Perform analysis\n", + "\n", + "---\n", + "\n", + "#### Raster Math\n", + "\n", + "The above data has been scaled to allow it to be stored in an integer format, but this makes it difficult to interpret. To convert it back to Kelvin, we must apply the scale factor, which in this case is 0.02. To do this, we will perform some raster math." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "day_LST_sc = arcpy.Raster(day_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ArcPy allows basic math operations to be applied on a pixel-by-pixel basis with Python syntax, but it is necessary to create an ArcPy Raster object from your raster file on disk. The math operation returns another ArcPy Raster object, which we have assigned to `day_LST_sc`. Think of these Raster objects in an analogous manner to the data types we covered before, like string, float, int, etc. They can be used in other math operations and passed to some (but not all) ArcGIS tools that take raster input.\n", + "\n", + "Notice the lines before and after the middle block. Raster math requires the Spatial Analyst extension, so it is necessary to check out a license for this extension first. Checking the license back in at the end is not necessary for the code to function, but it is good practice, because your organization may have a license server with limited keys.\n", + "\n", + "At the moment, our scaled daytime LST raster only exists in memory - we have not saved it to disk. To do so:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "path = MODIS_file.rstrip(\".hdf\") + \"_scale.tif\"\n", + "day_LST_sc.save(path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Math with multiple rasters\n", + "\n", + "In a similar manner, two or more rasters can be used in a formula using simple Python syntax. But first, we need two rasters! Let's repeat the above steps with the nighttime LST band (subdataset 4), from the same MODIS file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "MODIS_file = \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\"\n", + "night_LST = MODIS_file.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + "arcpy.ExtractSubDataset_management(MODIS_file, night_LST, subdataset_index=4)\n", + "\n", + "scale = 0.02\n", + "night_LST_sc = arcpy.Raster(night_LST) * scale\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Note:_ In this case, we did not save the scaled raster to disk. This is not actually necessary to use it in later operations, and not saving intermediates is a good way to conserve disk space.\n", + "\n", + "_Another Note:_ In these examples, we are checking the spatial analyst extension in and out each time, but, if you are writing a long script, it is only necessary to do this once, at the beginning and end.\n", + "\n", + "Now, let's compute the difference between the daytime and nighttime LST:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "diff = day_LST_sc - night_LST_sc\n", + "diff_path = MODIS_file.rstrip(\".hdf\")+\"_diff.tif\"\n", + "diff.save(diff_path)\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This will create a new Raster object where each pixel corresponds to the difference between the two old rasters. Open this new raster in ArcMap and compare it to a basemap.\n", + "\n", + "#### Conditionals\n", + "\n", + "Suppose we want to know where the above difference exceeds a certain threshold. We can answer this question using the Con tool, available with the Spatial Analyst extension." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "thres = 15\n", + "diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + "diff_thres_path = MODIS_file.rstrip(\".hdf\")+\"_thres.tif\"\n", + "diff_thres.save(diff_thres_path)\n", + "\n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The middle block of code will create and save a raster that contains a 1 wherever the day-night difference exceeds 15, and a 0 wherever it does not.\n", + "\n", + "### Resample\n", + "\n", + "---\n", + "\n", + "We now have a nice Boolean raster that we could use as a mask in some larger project. However, what if the other members of our project are working with the MODIS red and NIR bands, which are 250 m resolution? We can be helpful, and resample our raster to this resolution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "out_cellsize = 231.6563583\n", + "res = MODIS_file.rstrip(\".hdf\") + \"_res.tif\"\n", + "arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could have performed this resampling at any point in our processing chain, but we chose to do so at the end. Why might this be best?\n", + "\n", + "### Repeat as necessary\n", + "\n", + "---\n", + "\n", + "We have output (hopefully), but only for one raster file, and when has a project ever involved only one raster file?? The efficiency of scripting ArcGIS in Python becomes apparent when one must do the same thing many times, which should sound like something you have already learned... loops!\n", + "\n", + "First, we'll need some more data. Since we already have a summer image, let's download files from:\n", + "* winter: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/017/MOD11A2.A2016017.h11v05.006.2016234002041.hdf\n", + "* spring: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/105/MOD11A2.A2016105.h11v05.006.2016242152502.hdf\n", + "* and fall: ftp://ladsweb.nascom.nasa.gov/allData/6/MOD11A2/2016/289/MOD11A2.A2016289.h11v05.006.2016302010943.hdf\n", + "\n", + "Move these to the same folder you have been using.\n", + "\n", + "Now, let's put everything we did above in a loop:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'CheckedIn'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff_path = f.rstrip(\".hdf\")+\"_diff.tif\"\n", + " diff.save(diff_path)\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres_path = f.rstrip(\".hdf\")+\"_thres.tif\"\n", + " diff_thres.save(diff_thres_path)\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "_Tip:_ If you need to get the names of many files in a folder and don't want to do a lot of tedious typing, check out the [glob](https://docs.python.org/2/library/glob.html) package.\n", + "\n", + "\n", + "\n", + "# Other Considerations\n", + "\n", + "---\n", + "\n", + "### Environments\n", + "\n", + "---\n", + "\n", + "ArcGIS uses environment settings to control the specific characteristics of your current geoprocessing environment. In the above script, we are using two already: workspace and overwrite output. Environments are a powerful way to control the exact way in which your script executes. As another example, let's say that within our MODIS tile, we only really care about Virginia (because it is objectively better than all of these other states), and we want to limit output to this state.\n", + "\n", + "One approach might be to clip each input raster with a shapefile, but we have to do this for each input. In this case, we only have two per iteration, but in other projects we might have a lot more. A more elegant approach is to use the mask environment setting.\n", + "\n", + "Download [this](https://drive.google.com/file/d/0B8toI67HoVSrVzV3aUcwc3FBcG8/view?usp=sharing) shapefile of Virginia, and extract it to your work directory. Then, rerun our script with the mask environment set at the top:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import arcpy\n", + "\n", + "arcpy.env.workspace = \"C:\\\\Users\\\\abhubba1\\\\Documents\\\\Python Scripts\\\\DEVELOP_class\"\n", + "arcpy.env.overwriteOutput = True\n", + "arcpy.env.mask = \"Virginia.shp\"\n", + "arcpy.CheckOutExtension(\"spatial\")\n", + "\n", + "scale = 0.02\n", + "thres = 15\n", + "out_cellsize = 231.6563583\n", + "MODIS_files = [\"MOD11A2.A2016017.h11v05.006.2016234002041.hdf\", \n", + " \"MOD11A2.A2016105.h11v05.006.2016242152502.hdf\", \n", + " \"MOD11A2.A2016201.h11v05.006.2016242234243.hdf\", \n", + " \"MOD11A2.A2016289.h11v05.006.2016302010943.hdf\"]\n", + "\n", + "for f in MODIS_files:\n", + " \n", + " #Extract from HDF\n", + " day_LST = f.rstrip(\".hdf\") + \"_dayLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, day_LST, subdataset_index=0)\n", + " night_LST = f.rstrip(\".hdf\") + \"_nightLST.tif\"\n", + " arcpy.ExtractSubDataset_management(f, night_LST, subdataset_index=4)\n", + " \n", + " #Scale\n", + " day_LST_sc = arcpy.Raster(day_LST) * scale\n", + " night_LST_sc = arcpy.Raster(night_LST) * scale\n", + " \n", + " #Perform subtraction\n", + " diff = day_LST_sc - night_LST_sc\n", + " diff.save(f.rstrip(\".hdf\")+\"_diff.tif\")\n", + " \n", + " #Apply conditional\n", + " diff_thres = arcpy.sa.Con(diff > thres, 1, 0)\n", + " diff_thres.save(f.rstrip(\".hdf\")+\"_thres.tif\")\n", + " \n", + " #Resample\n", + " res = f.rstrip(\".hdf\") + \"_res.tif\"\n", + " arcpy.Resample_management(diff_thres, res, cell_size=out_cellsize)\n", + " \n", + "arcpy.CheckInExtension(\"spatial\")\n", + "\n", + "arcpy.env.workspace = None\n", + "arcpy.env.overwriteOutput = None\n", + "arcpy.env.mask = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspect the output. If everything worked properly, you should only see data over the scenic Commonwealth of Virginia\n", + "\n", + "__Very important note:__ The nature of environment settings is that they apply to your _entire processing environment_, which means they will stick around for future processes you run in the same session of Python. Old environment settings can lead to mysterious errors, confusion, and general gnashing of teeth. I highly recommend that you clear out your environment settings at the end of your script by setting them to `None`, as I have done above. Even better, clear them immediately after they are no longer needed, in case your script crashes before it completes.\n", + "\n", + "### Editing locks\n", + "\n", + "---\n", + "\n", + "Whenever a program is using a file, it creates a lock that prevents other programs from editing the same file. Python is no different. In general, these should disappear after a script is finished executing. For reasons that are not entirely clear to me, ArcPy often retains locks on ArcPy objects created by a script even said script has completed. This will create problems if you then try to edit the file that object is pointing to in a different program. Therefore, it is also good practice to clear variables that point to ArcPy objects after they are no longer necessary. To accomplish that in our script, add the following to the end:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "day_LST_sc = None\n", + "night_LST_sc = None\n", + "diff = None\n", + "diff_thres = None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "On the other side of the same coin, Python will not be able to edit a file that is locked by another application. In the context of geoprocessing, this can happen because you ran your code, viewed the output in ArcMap, and tried to rerun your code without removing said output from ArcMap. Some of you may have already experienced this phenomenon during this lesson. If you're me, this happens _all the time_..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Lectures_201709/readme.md b/Lectures_201709/readme.md new file mode 100644 index 0000000..e69de29 From db06eae058dd93f1431b24908218521a76cbaac3 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 24 Sep 2017 15:16:13 -0400 Subject: [PATCH 55/57] Date correction, small clarifications, etc. --- Lectures_201709/Week_01/setup_intro.ipynb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Lectures_201709/Week_01/setup_intro.ipynb b/Lectures_201709/Week_01/setup_intro.ipynb index a51370d..054cd50 100644 --- a/Lectures_201709/Week_01/setup_intro.ipynb +++ b/Lectures_201709/Week_01/setup_intro.ipynb @@ -9,11 +9,11 @@ "\n", "---\n", "\n", - "# Setup & Introduction\n", + "# Setup & Introduction to Python\n", "\n", "### Goddard Space Flight Center\n", "\n", - "#### June 5, 2017\n", + "#### September 20, 2017\n", "\n", "---" ] @@ -79,7 +79,9 @@ "\n", "3. You should see the output on the screen.\n", "\n", - "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory." + "__Caveat:__ Your prompt should be at the directory containg the helloworld.py script. Perform an ```ls``` (Mac/Linux) or ```dir``` (Windows) to see if that file is in your current working directory.\n", + "\n", + "To access a more feature-rich Python code editor, search for and open the __Spyder__ application, which should have been installed with Anaconda. This program features a code editor on the left, a Python console on the lower right, some contextual help on the upper right, and an assortment of helpful tools across the top of the screen." ] }, { @@ -106,7 +108,9 @@ "\n", "5. Press __```Shift-Enter```__, __```Cntrl-Enter```__, or click __Cells -> Run Cells__ or use the Play button near the top of the page.\n", "6. You will see the output now.\n", - "7. Exit via closing the browser windows and stopping the server running (Cntrl + Enter) in the terminal/command prompt." + "7. Exit via closing the browser windows and stopping the server running (Cntrl + Enter) in the terminal/command prompt.\n", + "\n", + "_Note:_ The lectures for this course (i.e. what you are looking at RIGHT NOW) are Jupyter notebooks, and can be opened and run using the above instructions." ] }, { @@ -139,7 +143,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# store inside a variable\n", @@ -150,7 +156,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Imports\n", From b296b3cfb4419f7ec54d5f5738263008017f8936 Mon Sep 17 00:00:00 2001 From: alfredhub Date: Sun, 24 Sep 2017 15:17:11 -0400 Subject: [PATCH 56/57] Added section on NumPy --- Lectures_201709/Week_02/intro_cont.ipynb | 191 ++++++++++++++++++++++- 1 file changed, 183 insertions(+), 8 deletions(-) diff --git a/Lectures_201709/Week_02/intro_cont.ipynb b/Lectures_201709/Week_02/intro_cont.ipynb index bb52a75..2196911 100644 --- a/Lectures_201709/Week_02/intro_cont.ipynb +++ b/Lectures_201709/Week_02/intro_cont.ipynb @@ -9,11 +9,11 @@ "\n", "---\n", "\n", - "# Introduction Continued\n", + "# Basic Python Continued\n", "\n", "### Goddard Space Flight Center\n", "\n", - "#### June 13, 2017\n", + "#### September 25, 2017\n", "\n", "---" ] @@ -107,6 +107,173 @@ "> _pickles..._ Python has this thing called pickles where you \"temporarily\" store data. It's a binary file, but is only for small storage that is needed for a short time." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### NumPy: Multidimensional Arrays in Python\n", + "\n", + "---\n", + "\n", + "__[numpy](https://docs.scipy.org/doc/numpy-1.13.0/reference/)__ is short for numerical Python, and is a very powerful and well-supported package that adds multidimensional arrays and numerous mathematical and statistical operations to Python. An even more feature-rich and powerful option is __[scipy](https://docs.scipy.org/doc/scipy/reference/)__, which expands on __```numpy```__.\n", + "\n", + "The core element of __```numpy```__ is the n-dimensional array, or ndarray. To create an array, one has multiple options, including entering numbers directly:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 5 8]\n", + " [5 7 2]]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "a = np.array([[1,5,8],[5,7,2]])\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "...converting from a list or other iterable:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5 6 8 3 8 4]\n" + ] + } + ], + "source": [ + "l = [5,6,8,3,8,4]\n", + "a = np.array(l)\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "...or using one of the specialized constructor functions to make arrays full of ones, random values, or, in this case, zeros:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 0. 0. 0.]\n", + " [ 0. 0. 0.]\n", + " [ 0. 0. 0.]]\n" + ] + } + ], + "source": [ + "a = np.zeros((3,3))\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are also ways to read text files directly into NumPy arrays (```loadtxt``` or ```genfromtext```).\n", + "\n", + "Once you have an array, there are numerous operations available to you, both element-wise (i.e. performed on each value of the array):" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 6 8 17]\n", + " [ 5 10 9]]\n", + "[[15 9 27]\n", + " [ 0 9 21]]\n" + ] + } + ], + "source": [ + "a = np.array([[1,5,8],[5,7,2]])\n", + "b = np.array([[5,3,9],[0,3,7]])\n", + "c = a + b\n", + "print(c)\n", + "d = b * 3\n", + "print(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "...and across an entire array:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "28\n", + "4.5\n" + ] + } + ], + "source": [ + "total = np.sum(a)\n", + "print(total)\n", + "avg = np.mean(b)\n", + "print(avg)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NumPy has many other cool abilities, like performing math along specific axes of an array (e.g. summing all of the columns of a 2D array) and using masks. Finally, particularly enthusiastic geospatial analysts can apply NumPy's extensive capabilities to raster images by reading said rasters into NumPy and then manipulating to their heart's content. Two ways to perform this conversion are 1) __[GDAL](https://github.com/edmondb/developython/blob/master/Archive/Lectures_201702/Week_05/week_5.ipynb)__, a powerful raster analysis program covered in a lecture from a previous term (see link) or 2) ```arcpy.RasterToNumPyArray```, a simpler but more constrained option.\n", + "\n", + "However, for analysis problems where NumPy or SciPy's mathematical and statistical capabilities are not necessary, processing rasters directly in ArcPy (to be covered in the next lecture), will be most straightforward." + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -115,7 +282,7 @@ "\n", "---\n", "\n", - "The __[h5py]()__ and __[netCDF4]()__ Python packages are very useful for reading structured data (multidimensional, multivariate, time-series, etc.). Here, we are going to look at reading and visualizing some structured data." + "The __[h5py](http://docs.h5py.org/en/latest/)__ and __[netcdf4](http://unidata.github.io/netcdf4-python/)__ Python packages are very useful for reading structured data (multidimensional, multivariate, time-series, etc.). Here, we are going to look at reading and visualizing some structured data." ] }, { @@ -162,7 +329,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "%matplotlib inline\n", @@ -177,7 +346,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "z = f.variables['retrieved_wind_speed']" @@ -186,7 +357,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "z.dimensions" @@ -200,13 +373,15 @@ "\n", "---\n", "\n", - "Matplotlib is basically Python's replacement for Matlab. Here is an example of plotting data from our file." + "Matplotlib is basically Python's replacement for Matlab's plotting capabilities. Here is an example of plotting data from our file." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "fig = plt.figure(figsize = (20,20))\n", From 7973b9bb1557feb1a96075266bb1fb0260dcb95e Mon Sep 17 00:00:00 2001 From: alfredhub Date: Mon, 16 Oct 2017 09:28:12 -0400 Subject: [PATCH 57/57] Corrected date --- Lectures_201709/Week_03/GIS_programming.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lectures_201709/Week_03/GIS_programming.ipynb b/Lectures_201709/Week_03/GIS_programming.ipynb index aa6e43f..2b0b696 100644 --- a/Lectures_201709/Week_03/GIS_programming.ipynb +++ b/Lectures_201709/Week_03/GIS_programming.ipynb @@ -13,7 +13,7 @@ "\n", "### Goddard Space Flight Center\n", "\n", - "#### March 6, 2017\n", + "#### October 16, 2017\n", "\n", "---\n", "\n",