Slide 1

Slide 1 text

Satellite  mapping  for  everyone   Chris  Waigl   @chrys   Talk  presented  at  PyCon  2015,  Montréal   1  

Slide 2

Slide 2 text

SATELLITE  MAPPING  FOR  PYTHON   PROGRAMMERS   …  and  Python  programming  for  satellite  mappers   2  

Slide 3

Slide 3 text

There  have  been  many  great  talks  about   geospatial  Python  or  GIS  (geographic   information  systems)  at  previous  PyCons…   •  Mele  Sax-­‐Barnett  (PyCon  2014)   •  Jason  Scheirer  (PyCon  2012)   •  Zain  Memon  (PyCon  2012)   •  Sara  Safavi  (PyTexas  2014)     •  …     (They  are  all  on  pyvideo.org.)   3  

Slide 4

Slide 4 text

…  but  they  have  all  focused  on  vector  data,   not  raster  data.   4   Prakash,  Waigl,  McNabb,  UAF  

Slide 5

Slide 5 text

Both  are…  just  data.  We  can  deal  with  data.    vector  data     5   tabular/key-­‐value  data   geolocation  data   metadata   2D  arrays  (stacked)   geolocation  data   metadata   raster  data  

Slide 6

Slide 6 text

Using  raster  data  is  not  (really)  harder.   •  OK,  fewer  people  do  it.     •  BUT  a  lot  of  data  is  freely  available.     •  Landsat,  for  example:   –  30  m  spatial  resolution  (mostly)   –  since  the  80s,  and  early  version  70s   –  any  point  on  the  globe  (except  the  poles)   –  public  domain   •  more  users  ⇒  better  tools   6  

Slide 7

Slide 7 text

Satellite  mapping  for  Python  programmers   Why  would  you  want  to  do  this?   Where  would  you  get  data  and  what  does  it   look  like?   How  can  you  make  maps  from  it  most   efficiently?         7  

Slide 8

Slide 8 text

WHY  SATELLITE  MAPPING?   …  and  first:  what  is  satellite  mapping?     8  

Slide 9

Slide 9 text

Polar  orbiting  (=  sun-­‐synchronous)  satellite   (EUMETSAT  =  European  met  satellite  agency)   9   Video  at  https://youtu.be/y_jM_BxQGvE    

Slide 10

Slide 10 text

Let’s  get  used  to  some  basic  concepts.   •  swath  width  (in  km)     •  orbital  inclination   •  repeat  interval   •  trade-­‐off  between  spatial  and  temporal   resolution   •  coordinate  reference  system  (and  map   projection)   10  

Slide 11

Slide 11 text

Example:  Maybe  you  live  in  a  place  like  this.   2012  vs.  2013,  May.   11   upenn.edu   earthobservatory.nasa.gov  

Slide 12

Slide 12 text

Example:  Maybe  you  live  in  a  place  like  this.   2012  vs.  2013,  May.   12   upenn.edu   earthobservatory.nasa.gov  

Slide 13

Slide 13 text

30  ×  30  m  imagery:  visualize  changes  on  a  city  or   regional  scale.  Example:  Las  Vegas,  1984  vs  2009   13   earthobservatory.nasa.gov  

Slide 14

Slide 14 text

30  ×  30  m  imagery:  visualize  changes  on  a  city  or   regional  scale.  Example:  Las  Vegas,  1984  vs  2009   14   earthobservatory.nasa.gov  

Slide 15

Slide 15 text

Higher  resolution  images  are  available.   15   Alaska  SDMI,   SPOT5,  source:   GINA,  UAF  

Slide 16

Slide 16 text

Higher  resolution  images  are  available.   16   Alaska  SDMI,   SPOT5,  source:   GINA,  UAF  

Slide 17

Slide 17 text

SPOT5  2.5  m  resolution,  village  of  Togiak   17   Alaska  SDMI,   SPOT5,  source:   GINA,  UAF  

Slide 18

Slide 18 text

Visual  data  journalism  :  The  ProPublica  project   on  Louisiana’s  disappearing  coastline   18  

Slide 19

Slide 19 text

A  LOOK  AT  SOME  DATA   Where  to  get  it,  what  it  looks  like   19  

Slide 20

Slide 20 text

Back  to  raster  and  vector  data.  How  do  we   process  this?     20   Prakash,  Waigl,  McNabb,  UAF  

Slide 21

Slide 21 text

matplotlib   We  have  a  hierarchy  of  libraries  at  our   disposal  to  deal  with  the  data.       UPPER  CASE:  C  libraries   lower  case:  Python  libraries   21   HDF5   (h5py)   pygaarst   HDF4   (python-­‐hdf4)   GDAL/OGR  (osgeo)   shapely   fiona   GEOS   PROJ4   (pyproj)   numpy   rasterio   …  

Slide 22

Slide 22 text

Simple  case:  highly  pre-­‐processed  file  (NASA).   Imagine  you  live  close  to  a  mine  like  this:     22   mtpolley_oli_2014210_geo.tif  

Slide 23

Slide 23 text

Simple  case:  highly  pre-­‐processed  file  (NASA).   …  and  then  one  day  this  happens:     23   mtpolley_oli_2014217_geo.tif  

Slide 24

Slide 24 text

Exploring  a  dataset  with  GDAL   >>>  from  osgeo  import  gdal   >>>  gdal.UseExceptions()   >>>   >>>  ds  =  gdal.Open(fpath)   >>>  print(ds.GetDescription())   mtpolley_oli_2014210_clip.tif   24  

Slide 25

Slide 25 text

GDAL:  Dataset  attributes  and  methods   >>>  print(ds.RasterCount)   3   >>>  print(ds.RasterXSize)   1200   >>>  print(ds.RasterYSize)   900   >>>  print(ds.GetProjection())   PROJCS["WGS  84  /  UTM  zone   10N",GEOGCS["WGS   84",DATUM["WGS_1984",SPHEROID["WGS  84", 6378137,298.257223563,  …]   25  

Slide 26

Slide 26 text

Exploring  a  dataset  with  rasterio   >>>  import  rasterio   >>>   >>>  with  rasterio.open(fname)  as  src:   >>>          print(src.width,  src.height)   >>>          print(src.crs)   >>>          print(src.crs_wkt)   >>>          print(src.bounds)   >>>          print(src.count)   >>>          print(src.indexes)   26  

Slide 27

Slide 27 text

Exploring  a  dataset  with  rasterio   1200  900   {'init':  u'epsg:32610'}   PROJCS["WGS  84  /  UTM  zone  10N"....]   BoundingBox(left=586762.5,   bottom=5816392.5,  right=604762.5,   top=5829892.5)   3   [1,  2,  3]   27  

Slide 28

Slide 28 text

Accessing  the  data  with  GDAL   >>>  ds  =  gdal.Open(fpath)   >>>  band1  =  ds.GetRasterBand(1)   >>>  data  =  band1.ReadAsArray()   >>>  print(type(data))     28  

Slide 29

Slide 29 text

Accessing  the  data  with  rasterio   >>>  with  rasterio.open(fname)  as  src:          b1,  b2,  b3  =  src.read()   >>>  print(type(b1))       29  

Slide 30

Slide 30 text

Both  GDAL  and  rasterio  have  command-­‐line   interfaces   $  gdalinfo  mtpolley_oli_2014210_geo.tif   [a  whole  slew  of  information]   $  rio  info  mtpolley_oli_2014210_geo.tif   [a  concise  summary  as  in  JSON  format]       BUT:  GDAL  scripts  are  very  powerful,  especially   gdal_transform  and  gdal_merge.py:     •  cropping  (“subsetting”)  and  RGB  composites   •  read  the  source  code  of  the  Python  scripts  for   more  complicated  tasks   30  

Slide 31

Slide 31 text

Full-­‐scale  Landsat  data  recommended  portal   (and  many  others):  earthexplorer.usgs.gov   31  

Slide 32

Slide 32 text

Inspect  and  download:   32  

Slide 33

Slide 33 text

Landsat  full  scene  data   Downloaded  file,  for  example:   LC80680152014261LGN00.tar.gz  (980  MB)           33   LC80680152013258LGN00_B1.TIF    (each  138  MB)   LC80680152013258LGN00_B10.TIF   LC80680152013258LGN00_B11.TIF   …   LC80680152013258LGN00_B8.TIF   LC80680152013258LGN00_B9.TIF   LC80680152013258LGN00_BQA.TIF   LC80680152013258LGN00_MTL.txt  

Slide 34

Slide 34 text

Introduction  to  remote  sensing  in  1  min   34   band  =  channel  =  layer       radiometric  resolution  =    bit  depth  (8  bit,  12  bit,  16  bit)  

Slide 35

Slide 35 text

Landsat  full  scene  data  basics:   Landsat  5,  7:   •  8  bit  ,  approx.  200-­‐500  MB  per  zip  file   •  8  bands:  use  7/5/3  for  false-­‐natural  color  RGB   Landsat  8:   •  16  bit,  approx.  1  GB  per  zip  file   •  11  bands:  use  7/6/4  for  false-­‐natural  color  RGB   35  

Slide 36

Slide 36 text

Life  beyond  Landsat:  Datasets  may  have   subdatasets  and  more  complicated  geolocation   36   You  may  encounter  data  in   HDF4  or  HDF5  format.     This  data  has  subdatasets.  It   may  have  groups  of   subdatasets.     >>>  sd  =  ds.GetSubDatasets()     >>>  gdal.Open(sd[2][0])     Use  h5py  or  python-­‐hdf4   libraries  instead  of  GDAL.  

Slide 37

Slide 37 text

PYTHON  MAPPING  IN  DETAIL   A  worked  example   37  

Slide 38

Slide 38 text

Example:  Let’s  look  at  the  coast  right  here  in   Eastern  Canada   38  

Slide 39

Slide 39 text

National  Snow  and  Ice  Data  Center  (NSIDC):  How   much  ice  is  there  in  the  winter  in  St.  Laurence  Bay   39  

Slide 40

Slide 40 text

Step  1:  Read  the  documentation   •  GeoTiff  files  (one  of  the  options)   •  25x25  km  pixel  size   •  polar  stereographic  projection   •  8  bit  data   •  0-­‐250  maps  to  0-­‐100%  sea  ice  cover   •  251-­‐255:  used  for  special  data  values:   coastline,  land,  no  data,  bad  data…   40  

Slide 41

Slide 41 text

Use  pygaarst  to  manipulte  the  data     (https://github.com/chryss/pygaarst)   >>>  import  numpy  as  np   >>>  from  pygaarst  import  raster   >>>  nsdic  =  raster.GeoTIFF(fn)   >>>  print(nsdic.nrow,  nsdic.ncol)   448  304   >>>  icedat  =  np.empty_like(nsdic.data)   >>>  icedat[:]  =  nsdic.data/2.5   >>>  maskdat  =  np.empty_like(nsdic.data)   >>>  maskdat  =  np.ma.MaskedArray(nsdic.data,   mask=nsdic.data  <=  250)   41  

Slide 42

Slide 42 text

…  and  matplotlib  …   >>>  f,  ax  =  plt.subplots()   >>>  plt1  =  ax.imshow(icedat,   cmap="Blues_r",  vmin=0,  vmax=100,   interpolation='nearest')   >>>  plt2  =  ax.imshow(maskdat,  vmin=251,   vmax=255,  cmap=customcmap,   interpolation='nearest')   42  

Slide 43

Slide 43 text

43  

Slide 44

Slide 44 text

Find  the  Gulf  of  St.  Laurence  and  Anticosti   Island  …     >>>  lat_center,  lon_center  =  49.5,  -­‐63   >>>  geog2stereo  =  nsdic.coordtrans   >>>  x_center,  y_center  =   geog2stereo(lon_center,  lat_center)     >>>  i_center,  j_center  =   nsdic.xy2ij(x_center,  y_center,   precise=True)   >>>  print(i_center,  j_center)   407.930553598  97.4816627248     44  

Slide 45

Slide 45 text

45  

Slide 46

Slide 46 text

Use  the  basemap  toolkit  to  map  the  data  in   Albers  Equal  Area  projection   >>>  from  mpl_toolkits.basemap  import  Basemap     >>>  fig  =  plt.figure())   >>>  bmap  =  Basemap(width=…,  height=…,   resolution='i',  projection='aea',  lat_1=40.,   lat_2=60.,  lat_0=50.,  lon_0=-­‐63.)   >>>  x,  y  =  bmap(nsdic.Lon,  nsdic.Lat)   >>>  implt  =  bmap.pcolormesh(x,  y,   np.flipud(icedat),  …)     >>>  x,  y  =  bmap(lon_center,  lat_center)   >>>  bmap.scatter(x,  y,  marker='o',  c='tomato',   s=150,  zorder=20,  label='Anticosti',  alpha=0.7)   >>>  bmap.drawcoastlines(zorder=10)   >>>  bmap.drawrivers(color=water)   >>>  …     46  

Slide 47

Slide 47 text

47  

Slide 48

Slide 48 text

To  sum  up   •  Satellite  data  is  available  for  your  use   •  Tools  are  powerful  and  usability  is   improving   •  Find  the  last  example  as  an  IPython   notebook  on   http://nbviewer.ipython.org/gist/chryss/ 0e7894d9dc78a0c31708     •  If  you  would  like  to  get  together,  find  me   and  let’s  talk   48  

Slide 49

Slide 49 text

COLLEGE OF NATURAL SCIENCE & MATHEMATICS University of Alaska Fairbanks NASA  Earth  and  Space   Science  Fellowship   Thank  you!     49