SlideShare a Scribd company logo
SAVING GAIA
w/jQuery Mobile, OpenLayers and GeoDjango
CALVIN CHENG
     www.calvinx.com
www.od-eon.com/blogs/calvin
1   Context


         2    Technology Stack



                    3   Installation
4   Django GeoModel & ORM



         5   Geospatial Libraries



                    6   Utilities
7   GeoAdmin



        8   OpenLayers


                 9   jQuery (Mobile)
10   Possibilities



          11   Conclusion
1
Context
REDDCalculator.com (Beta)         SEC (Closed Beta)




                                                          LUC
                                                      (Coming Soon!)




                                                !



          ENVIRONMENTAL iTOOLS
 Spatially Explicit Scenario Analysis: Norway-Indonesia’s Forest Moratorium
 Species Extinction Calculator (SEC)
 Land Use Calculator (LUC)
SPECIES WHA--??
Species Extinction Calculator (SEC)
4%




                       4"
&'#()#*%
           123#
              !"#$$%&'()*"+,-./0"



            !"#$%
3,000


                       2,250


   Number of species   1,500


                        750


                          0
                               100   200   300       400       500        600   700   800
                                                 Area conserved (km sq)




                                     SPECIES-AREA
More habitats conserved (Area) = More fauna diversity (Species)
+)
!) )
 &,-




! )
    *
 "#$%$&'(
            ( )
             .
             &,-




             .
                 )
             "#$%$&'(
                        )
!"#$%&'()3+(451"67(&/&012(

                     !"#$%&'()*+(,-.&(&/&012(
0$1,23+4")56)'."+4,2+"+'*,'7$2/+)$4"'8$*.51'

                   !"#$%&"'"(")*+',-'-,."+*'"/#"+'
                                                                   N
                                                            # $ % "i $ ! i
                                                                  i =1

!                              -
                                                     M




                           (                                )
                                        #% "!$ j
        )              )                )
                   *
    &+,                              &+,             j =1




!                                     -                )
               )
    "#$%$&'(                                "#$%$&'(
MATRIX-CALIBRATED SPECIES-AREA
Accounts for taxon-specific responses to different components of the landscape
EXAMPLE OF AN AREA?
Conservation Forests, National Reserves etc
    Borneo 743,330 square kilometres
USERS AND USE-CASE
Conservation scientists and Land owners define areas which are
conserved by plotting polygons on a map source (e.g. Google Maps).

Areas which are slated for development are also marked.

By quantifying area conservation goals (areas conserved before and after
development) and its impact on the loss of species, SEC is a tool which
helps people make better trade-off decisions.
USERS AND USE-CASE
REDDCalculator.com computes the socio-economic trade-offs and
results as a consequence of the Norway-Indonesia REDD+ Moratorium.
2
Technology Stack
Layers & Features (‘Vector Objects’)
 jQuery &
OpenLayers                                                    User Interface
                              Map Source


KML   GML    WKT     GeoJSON          GeoRSS        Others    Data (serialized)

               GeoDjango                                       Python Logic


                                                              C/C++ Libraries
                                                             w/ Python Bindings
                                                                & Datastore
3
Installation
(2.7)
(trunk)
sudo -u postgres psql -d yourdatabase_name -f { ... }/postgis.sql

sudo -u postgres psql -d yourdatabase_name -f { ... }/postgis_comments.sql

sudo -u postgres psql -d yourdatabase_name -f { ... }/spatial_ref_sys.sql
sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/
software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/
contrib/postgis-1.5/postgis.sql

sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/
software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/
contrib/postgis-1.5/postgis_comments.sql

sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/
software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/
contrib/postgis-1.5/spatial_ref_sys.sql
Portage exists
But here’s a magical way - https://github.com/stefantalpalaru/dotfiles/
tree/master/Gentoo/custom%20overlay/portage/dev-db/postgis -
custom postgis ebuild modified by Stefan
add ebuild to local ‘overlay’ (a gentoo terminology)
emerge postgis
edit configuration file in /etc/conf.d/postgis and add in the postgresql
database that you need ‘postgis-enabled’
emerge --config postgis
# settings.py

INSTALLED_APPS = (
  # Core Django Apps
  'django.contrib.contenttypes',
  'django.contrib.auth',
  'django.contrib.sessions',
  'django.contrib.sites',
  'django.contrib.admin',
  'django.contrib.admindocs',
  'django.contrib.flatpages',
  'django.contrib.humanize',
  'django.contrib.comments',
  'django.contrib.markup',
  'django.contrib.webdesign',
  'django.contrib.sitemaps',

    'django.contrib.gis',
    # Custom Apps for REDDCalculator.com
    'updatemodel',
    'location',
    'areadata',

    # Generic and reusable apps for most projects
    'south',
    'django_cherrypy_odeon',
    'misc',
    'cron',
    'notify',
    'log',
    'homepage',
    'userprofile',
)
# settings.py

DATABASES = {
        'default': {

           'ENGINE':
             'django.contrib.gis.db.backends.postgis',
           ‘NAME’: ‘yourdatabase_name’,
           'USER': 'yourdatabase_user’,
           'PASSWORD': 'yourdatabase_password',
           'HOST': 'your_ip_or_domain',
    }
}
4
 Django
GeoModel
 & APIs
from django.contrib.gis.db import models
from django.contrib.gis.db import models

class Province(models.Model):
   name = models.CharField(max_length=256)
   name_long = models.CharField(max_length=256, null=True)
   island = models.ForeignKey(Location, null=True)
   geom = models.MultiPolygonField(srid=4326, null=True)
   objects = models.GeoManager()
from django.contrib.gis.db import models

class Province(models.Model):
   name = models.CharField(max_length=256)
   name_long = models.CharField(max_length=256,
null=True)
   island = models.ForeignKey(Location, null=True)
   geom = models.MultiPolygonField(srid=4326, null=True, 
           geography=True)
   objects = models.GeoManager()
What are the geometry fields available to us in django?
GEOS: OGC simple feature implementation

 PointField
 MultiPointField

 LineStringField
 MultiLineStringField

 PolygonField
 MultiPolygonField

 GeometryCollectionField
PointField




         (x, y)
MultiPointField




((x1, y1), (x2, y2), (x3, y3))
LineStringField




((x1, y1), (x2, y2), (x3, y3), (x4, y4))
MultiLineStringField




(((x1, y1), (x2, y2), (x3, y3), (x4,
     y4)),((x5, y5), (x6, y6)))
PolygonField




((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1))
MultiPolygonField




((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)),
     ((x5, y5), (x6, y6), (x7, y7), (x5, y5)))
GeometryCollectionField




((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)),
          ((x5, y5), (x6, y6), (x7, y7)),
                    ((x8, y8)))
Practical Example #1: Species Extinction Calculator
Practical Example #2: REDDCalculator.com
from django.contrib.gis.gdal import datasource, spatialreference
from django.contrib.gis.geos import multipolygon, geosgeometry

shapefile = os.path.abspath(os.path.join(os.path.dirname(__file__),
'../../../../proj_public/media/files/giveshapefile.shp'))

ds = DataSource(shapefile)

layer = ds[0] # Checked in Python shell that this has only 1 layer
from django.contrib.gis.db import models

class AreaData(models.Model):
   district = models.ForeignKey(District) # District is FKed to Province
   land_use = models.IntegerField(choices=VEGETATION_TYPES)
   allocation = models.IntegerField(choices=
                                   CHOICES['LAND_ALLOCATION'])
   intact = models.IntegerField()
   concession = models.CharField(max_length=255, blank=True)
   peat = models.CharField(max_length=255, blank=True)
   area = models.FloatField(help_text='hectares')
   fid = models.IntegerField()
   # ... and any other.
   geom = models.MultiPolygonField(srid=4326, null=True)
   objects = models.GeoManager()
area = AreaData.objects.get(fid = feature.fid)
geometry_name = feature.geom.geom_type.name
geometry_object = feature.geom.transform(SpatialReference(4326),
clone=True).geos

# update our area object with the geom data from our shape file
if geometry_name == 'Polygon':
    # If our geometry object is a Polygon, we cast as MultiPolygon first
    geometry_object = MultiPolygon(geometry_object)

area.geom = geometry_object
area.save()
5
Geospatial
 Libraries
GEOS   GDAL   PROJ.4


  Mapnik   GeoIP
GEOS                Geometry Engine - Open Source



What does it do?

  Works with django GIS app to give us GeoModels!
GEOS                Geometry Engine - Open Source



Other Details
   Required dependency for django GIS app
   C++
  Implements OGC simple feature for SQL specification
  OGC = Open Geospatial Consortium
  e.g. sudo port install geos
GDAL                 Geospatial Data Abstraction Library



What does it do?

  Reads and writes to a variety of vector file formats, e.g. shp
GDAL               Geospatial Data Abstraction Library



Other Details

  C/C++
  Implements OGC simple feature specification
  e.g. sudo port install gdal
PROJ.4             Cartographic Projections Library



What does it do?

  Manages spatial reference systems and projections e.g. the
  mercator projection commonly used by Google Maps, MapQuest
  etc
PROJ.4               Cartographic Projections Library



Other Details

  Required dependency for PostGIS
  C
  Ensures that geometry objects stored in PostGIS use the
  appropriate projection
  sudo port install libproj4
Mapnik             Toolkit for developing Mapping Applications



What does it do?

  For the control freak in you :-)
  Build your own maps, control and customize every single detail
Mapnik             Toolkit for developing Mapping Applications



Other Details

  C++
  Uses boost for python interface
  No py27-mapnik yet. Solution? Create your own local portfile
  using py26-mapnik
  sudo port install py27-mapnik
GeoIP              Locate users by IP address



What does it do?

  Determines the location of app user via user’s IP address
GeoIP              Locate users by IP address



Other Details

  C
  No py27-geoip yet. Solution? Create your own local portfile using
  py26-geoip
  sudo port install libgeoip py27-libgeoip
6
Utilities
LayerMapping




./manage.py ogrinspect       ./manage.py ogrinfo
./manage.py ogrinspect
         and
    LayerMapping
$ ./manage.py ogrinspect ../proj_public/media/files/redd_data/
kalimantan_universe.shp Location --srid=4326 --mapping

# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models
class Location(models.Model):
   island = models.CharField(max_length=50)
   geom = models.MultiPolygonField(srid=4326)
   objects = models.GeoManager()

# Auto-generated `LayerMapping` dictionary for Location model
location_mapping = {
   'island' : 'island',
   'geom' : 'MULTIPOLYGON',
}
# models.py
from django.contrib.gis.db import models

class Location(models.Model):
   island = models.CharField(max_length=50)
   geom = models.MultiPolygonField(srid=4326)
   objects = models.GeoManager()

# Auto-generated `LayerMapping` dictionary for Kalimantan model
location_mapping = {
  'island' : 'island',
  'geom' : 'MULTIPOLYGON',
}
import os
from django.contrib.gis.utils import LayerMapping
from django.contrib.gis.gdal import DataSource
from location.models import Location, location_mapping

shapefile = os.path.abspath(os.path.join(os.path.dirname(__file__),
'../../../../proj_public/media/files/kalimantan_universe.shp'))
ds = DataSource(shapefile)
layer = ds[0] # Checked in Python shell that this has only 1 layer
kalimantan = LayerMapping(Location,
                                  shapefile,
                                  location_mapping,
                                  transform = True,
                                  encoding='iso-8859-1')
kalimantan.save(strict = True, verbose = True)
7
GeoAdmin
from django.contrib.gis import admin as geoadmin
from location.models import Location

admin.site.register(Location, geoadmin.GeoModelAdmin)
8
OpenLayers
“ OpenLayers is a pure JavaScript library for
  displaying map data in most modern web browsers,
  with no server-side dependencies. ”
9
 jQuery
(mobile)
“ jQuery Mobile is a Touch-Optimized Web
  Framework for Smartphones and Tablets. ”
+   +
$(document).ready(function(){
  $('#map_delete').hide()

  // Define a custom styles which will be used by our polygon layer
  var style = $.extend(true, {}, OpenLayers.Feature.Vector.style['default']) // get a copy of default style
  style.pointRadius = 15
  var styleMap = new OpenLayers.StyleMap({"default": style})

  // Define a custom style which will be used by our background layer
  var backgroundStyle = $.extend(true, {}, OpenLayers.Feature.Vector.style['default']) // get copy
  backgroundStyle.fillOpacity = "0.1"
  backgroundStyle.fillColor = "#000000"
  backgroundStyle.strokeColor = "#999999"
  var backgroundStyleMap = new OpenLayers.StyleMap({"default": backgroundStyle})

  // Define our background layer
  backgroundLayer = new OpenLayers.Layer.Vector("Background Layer", {styleMap:
backgroundStyleMap} )
// Define our vector layer
polygonLayer = new OpenLayers.Layer.Vector("Polygon Layer", {styleMap: styleMap})
polygonLayer.events.on({
   'featureselected': show_delete_button,
   'featureunselected': hide_delete_button
})

// Define our toolbar, panels and associated controls
// pinch and zoom is defined in touch navigation
var touchNavigation = new OpenLayers.Control.TouchNavigation({
   dragPanOptions: {
      interval: 100,
      enableKinetic: true
   }
})

// define our zoom panel
var zoomPanel = new OpenLayers.Control.ZoomPanel()

// define our layer switcher
var layerSwitcher = new OpenLayers.Control.LayerSwitcher()
// controls
drawControl = new OpenLayers.Control.DrawFeature(polygonLayer, OpenLayers.Handler.Polygon,
                                                       { displayClass: 'olControlDrawFeaturePolygon'});
selectControl = new OpenLayers.Control.SelectFeature(polygonLayer,
                                                       { clickout: true });
editControl = new OpenLayers.Control.ModifyFeature(polygonLayer,
                                                       { selectControl: selectControl,
                                                         vertexRenderIntent: 'temporary',
                                                         displayClass: 'olControlModifyFeature'});
// define our custom control tool bar
var toolbar = new OpenLayers.Control.Panel({displayClass: 'olControlEditingToolbar'});
toolbar.addControls([
    //this control is just there to be able to deactivate the drawing tools and pan the map
    drawControl,
    editControl,
    new OpenLayers.Control({ displayClass: 'olControlNavigation' })
]);
// Define Map Layers
var gphy = new OpenLayers.Layer.Google("Google Physical", {type: google.maps.MapTypeId.TERRAIN});
var gmap = new OpenLayers.Layer.Google("Google Streets", {numZoomLevels: 20});
var ghyb = new OpenLayers.Layer.Google("Google Hybrid", {type: google.maps.MapTypeId.HYBRID,
                                                             numZoomLevels: 20});
var gsat = new OpenLayers.Layer.Google("Google Satellite", {type: google.maps.MapTypeId.SATELLITE,
                                                             numZoomLevels: 20});

// Feed the controls and layers defined above to our map object
map = new OpenLayers.Map({
   div: 'map',
   controls: [zoomPanel, touchNavigation, layerSwitcher, toolbar],
   layers: [ghyb, gphy, gmap, gsat, backgroundLayer, polygonLayer]
})
// Google.v3 uses EPSG:900913 as projection, so we have to transform our coordinates
 mapProjection = map.getProjectionObject()
 map.setCenter(new OpenLayers.LonLat(map_center_lon, map_center_lat).transform(defaultProjection,
mapProjection), map_zoom)

   // if there's a Total Landscape Area polygon, we will draw it on the backgroundLayer.
   if (background_coords_json){
       var pointList = []
       for (var i=0; i<background_coords_json.length; i++) {
          var point = new OpenLayers.Geometry.Point(background_coords_json[i][0], background_coords_json[i]
[1])
          pointList.push(point.transform(defaultProjection, mapProjection));
       }
       var linearRing = new OpenLayers.Geometry.LinearRing(pointList)
       totalAreaPolygon = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([linearRing]))
       backgroundLayer.addFeatures([totalAreaPolygon])
   }
// draw the existing features into the polygonLayer
  var loaded_features = []
  for (var i=0; i<list_of_coords_json.length; i++) {
     var pointList = []
     for (var j=0; j<list_of_coords_json[i].length; j++) {
        var point = new OpenLayers.Geometry.Point(list_of_coords_json[i][j][0], list_of_coords_json[i][j][1])
        pointList.push(point.transform(defaultProjection, mapProjection));
     }
     var linearRing = new OpenLayers.Geometry.LinearRing(pointList)
     var polygonFeature = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([linearRing]),
                                                           {fid: list_of_coords_ids_json[i]})
     loaded_features.push(polygonFeature)
  }
  polygonLayer.addFeatures(loaded_features)
  polygonLayer.events.on({ "featuremodified": polygonSave, "featureadded": polygonSave,
       "vertexmodified": adjustVertex, "sketchstarted": adjustVertex, "sketchmodified": adjustVertex })

  // confirmation dialog
  $('#project_map_delete_polygon_yes').click(delete_polygon)
})
/* END of $(document).ready() */
10
Possibilities
1. Offline Maps for Field Usage

   2. Remote Controlled UAV for data collection

3. Crunch collected data and generate visualizations
Offline Maps for Field Usage
Layers & Features (Saved Locally, Syncing)
   Native
iOS/Android                                                            Native?
                      Map Source (Local Map Tiles)


KML   GML     WKT      GeoJSON        GeoRSS       Others       Data Transfer

                GeoDjango                                      Python Logic


                                                              C/C++ Libraries
                                                             w/ Python Bindings
                                                                & Datastore
The Problem with iOS MapKit Framework


MKMapView class implements Google Maps API natively

Unfortunately, Google Maps terms of use prevents us from caching
or storing map tiles locally
Alternative? https://github.com/route-me/route-me


Supports many map sources - OpenStreetMap, Microsoft
VirtualEarth, CloudMade, OpenAerialMap, OpenCycleMap,
SpatialCloud

OpenStreetMap permits map tile caching and local storage

Supports 2 offline, database-backed formats DBMap and MBTiles
A Comparison


                          MKMapKit     Route-Me

 Embed in iOS App           YES          YES

     Interaction            YES          YES

   Geolocalization          YES          YES

Different Map Sources       NO           YES

    Offline Maps            NO           YES
The Problem with Android Google Maps Framework


Renders Google Maps of course

Support for alternative map sources is important
Alternative? https://github.com/camptocamp/android-gis.git


 Supports many map sources - OpenStreetMap, Microsoft
 VirtualEarth, CloudMade, OpenAerialMap, OpenCycleMap,
 SpatialCloud

 OpenStreetMap permits map tile caching and local storage

 Supports 2 offline, database-backed formats DBMap and MBTiles
Benefits
  Fast
  (obviously, since Map Tiles are stored locally)
  100% Offline
  Stored as blob data for SQLite Client Access
Remote Controlled UAVs?
Collect Real Data

                             =>

         Effects on Landscape Change on Species
       e.g. obtain actual change in Forest Boundaries
(instead of just predicting on map on current prediction tool)
Prediction is great.

But we want real world data from primary forests!
http://www.youtube.com/watch?v=xjLXL72Medw&feature=autoshare
Crunch Collected Data

           =>

  2 possible approaches

- Decoupled R and Python
- Integrated Approach RPy Option
Decouple R and Python

Python retrieves data from django/postgresql
Python converts data shapefiles, images etc
Launches R given a *.r file with Scientist’s parameters
R does the analysis
Python does post-processing, projecting data etc
Integrated R & Python with RPy

 R and Python closely coupled
 RPy and RPy2 provides an interface to R Programming Language
 Python retrieves and organizes parameters from django/postgresql
 RPy module imported and R commands are executed within the
Python script file
11
Conclusion
Getting a GPS fix via Satellite?
Mathematical Modelling, Scenario Analysis
      for Environmental Policies
REDDCalculator.com (Live)         SEC (Closed Beta)




                                                          LUC
                                                      (Coming Soon!)




                                                !



          ENVIRONMENTAL iTOOLS
 Spatially Explicit Scenario Analysis: Norway-Indonesia’s Forest Moratorium
 Species Extinction Calculator (SEC)
 Land Use Calculator (LUC)
Species Extinction Calculator and REDDCalculator:

Mathematical Models and Formulas by Koh et. al are completely
translated into Python

Land Use Calculator:

Ditto. Coming Soon!
Key Takeaways
Mapnik is useful for rasterizing vector objects when we encounter large
datasets (in our case, 200 MB+ of protected areas in Kalimantan).

(jQuery Mobile) Web App can benefit from optimization through django
caching. To be done right after EuroPython! And besides jQuery Mobile
Beta 1 has just been released on Monday (20 June 2011)! :-)

Usability and App Responsiveness can possibly be improved, Out-Field/
Offline Benefits attainable, if we move interface elements and Map Tiles
into a native app (Android or iOS).
geography=True/False in a GeoDjango field

2 ways to import data from a given GIS Shape File

(1) LayerMapping

(2) Direct Assignment to obj.geom attribute as mentioned.
“ Advancing Environmental Sciences:

 helping people, scientists, NGOs and governments make
 practical Land Area Usage and Conservation Decisions
 using jQuery (Mobile), OpenLayers and GeoDjango! ”
Gotchas?
Make sure Projections/Datum in your shape file source corresponds
with your geometry field’s SRID and Map Source

Using LayerMapping?

transform = True

Directly creating or saving into an object’s attribute?

geometry_object = feature.geom.transform(SpatialReference(4326),
clone=True).geos
area.geom = geometry_object
area.save()
Credits
+ North-South Fund




Prof. Koh Lian Pin                 Prof. Matthew Hansen             Prof. Holly Gibbs
ETH Zurich, Dept of Env Sciences   South Dakota State University    Stanford Dept of Environmental
NUS, Dept of Biological Sciences   GIS Center of Excellence         Earth System Sciences
Stefan Talpalaru                  Liviu Bogdan Chiributa   That’s Me! :-)
Odeon Consulting Group            Odeon Consulting Group   Odeon Consulting Group




                         + ........
Previous GeoDjango Presentations + my little contribution

   www.geodjango.org/presentations

   www.od-eon.com/presentations
Questions and Discussion welcome!

    calvin.cheng@od-eon.com

More Related Content

What's hot

Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
Brian Lonsdorf
 
Data Munging in R - Chicago R User Group
Data Munging in R - Chicago R User GroupData Munging in R - Chicago R User Group
Data Munging in R - Chicago R User Group
designandanalytics
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
niklal
 
Rug hogan-10-03-2012
Rug hogan-10-03-2012Rug hogan-10-03-2012
Rug hogan-10-03-2012
designandanalytics
 
The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202
Mahmoud Samir Fayed
 
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 AutumnGoptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
Masashi Shibata
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
Howard Lewis Ship
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
Scott Leberknight
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeMongoDB
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指す
Yasuo Harada
 
Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1
ilesh raval
 
Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1
Sultan Khan
 
DroidKnight 2018 State machine by Selaed class
DroidKnight 2018 State machine by Selaed classDroidKnight 2018 State machine by Selaed class
DroidKnight 2018 State machine by Selaed classMyeongin Woo
 
Recent Changes to jQuery's Internals
Recent Changes to jQuery's InternalsRecent Changes to jQuery's Internals
Recent Changes to jQuery's Internals
jeresig
 
Writing Clean Code in Swift
Writing Clean Code in SwiftWriting Clean Code in Swift
Writing Clean Code in Swift
Derek Lee Boire
 
Javascript essential-pattern
Javascript essential-patternJavascript essential-pattern
Javascript essential-pattern
偉格 高
 
this
thisthis
jQuery%20on%20Rails%20Presentation
jQuery%20on%20Rails%20PresentationjQuery%20on%20Rails%20Presentation
jQuery%20on%20Rails%20Presentationguestcf600a
 

What's hot (19)

Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
 
Data Munging in R - Chicago R User Group
Data Munging in R - Chicago R User GroupData Munging in R - Chicago R User Group
Data Munging in R - Chicago R User Group
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 
Rug hogan-10-03-2012
Rug hogan-10-03-2012Rug hogan-10-03-2012
Rug hogan-10-03-2012
 
The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202The Ring programming language version 1.8 book - Part 65 of 202
The Ring programming language version 1.8 book - Part 65 of 202
 
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 AutumnGoptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
Goptuna Distributed Bayesian Optimization Framework at Go Conference 2019 Autumn
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指す
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1Jquery 13 cheatsheet_v1
Jquery 13 cheatsheet_v1
 
Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1Jquery 1.3 cheatsheet_v1
Jquery 1.3 cheatsheet_v1
 
DroidKnight 2018 State machine by Selaed class
DroidKnight 2018 State machine by Selaed classDroidKnight 2018 State machine by Selaed class
DroidKnight 2018 State machine by Selaed class
 
Recent Changes to jQuery's Internals
Recent Changes to jQuery's InternalsRecent Changes to jQuery's Internals
Recent Changes to jQuery's Internals
 
Writing Clean Code in Swift
Writing Clean Code in SwiftWriting Clean Code in Swift
Writing Clean Code in Swift
 
Javascript essential-pattern
Javascript essential-patternJavascript essential-pattern
Javascript essential-pattern
 
this
thisthis
this
 
jQuery%20on%20Rails%20Presentation
jQuery%20on%20Rails%20PresentationjQuery%20on%20Rails%20Presentation
jQuery%20on%20Rails%20Presentation
 

Viewers also liked

Desenvolvimento de aplicações geográficas utilizando Django/Geodjango
Desenvolvimento de aplicações geográficas utilizando Django/GeodjangoDesenvolvimento de aplicações geográficas utilizando Django/Geodjango
Desenvolvimento de aplicações geográficas utilizando Django/Geodjango
Rafael Chagas
 
KISD E-Rate Overview
KISD E-Rate OverviewKISD E-Rate Overview
KISD E-Rate OverviewEnidL
 
zhng your vim
zhng your vimzhng your vim
zhng your vim
Calvin Cheng
 
Django101 geodjango
Django101 geodjangoDjango101 geodjango
Django101 geodjango
Calvin Cheng
 

Viewers also liked (6)

Desenvolvimento de aplicações geográficas utilizando Django/Geodjango
Desenvolvimento de aplicações geográficas utilizando Django/GeodjangoDesenvolvimento de aplicações geográficas utilizando Django/Geodjango
Desenvolvimento de aplicações geográficas utilizando Django/Geodjango
 
Python story
Python storyPython story
Python story
 
KISD E-Rate Overview
KISD E-Rate OverviewKISD E-Rate Overview
KISD E-Rate Overview
 
zhng your vim
zhng your vimzhng your vim
zhng your vim
 
Django101 geodjango
Django101 geodjangoDjango101 geodjango
Django101 geodjango
 
Pythonic
PythonicPythonic
Pythonic
 

Similar to Saving Gaia with GeoDjango

Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Rafael Soto
 
PyDX Presentation about Python, GeoData and Maps
PyDX Presentation about Python, GeoData and MapsPyDX Presentation about Python, GeoData and Maps
PyDX Presentation about Python, GeoData and Maps
Hannes Hapke
 
GeoDjango & HTML5 Geolocation
GeoDjango & HTML5 GeolocationGeoDjango & HTML5 Geolocation
GeoDjango & HTML5 Geolocation
John Paulett
 
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜Takahiro Inoue
 
Geolocation on Rails
Geolocation on RailsGeolocation on Rails
Geolocation on Railsnebirhos
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macrosunivalence
 
OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011chelm
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
Peter Higgins
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
Alberto Paro
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
Alberto Paro
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
Daniel Cukier
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
Baishampayan Ghose
 
10. R getting spatial
10.  R getting spatial10.  R getting spatial
10. R getting spatial
ExternalEvents
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
Domenic Denicola
 
R getting spatial
R getting spatialR getting spatial
R getting spatial
FAO
 
Scaling up data science applications
Scaling up data science applicationsScaling up data science applications
Scaling up data science applications
Kexin Xie
 
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
Databricks
 
Hadoop I/O Analysis
Hadoop I/O AnalysisHadoop I/O Analysis
Hadoop I/O Analysis
Richard McDougall
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 

Similar to Saving Gaia with GeoDjango (20)

Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011Demoiselle Spatial Latinoware 2011
Demoiselle Spatial Latinoware 2011
 
PyDX Presentation about Python, GeoData and Maps
PyDX Presentation about Python, GeoData and MapsPyDX Presentation about Python, GeoData and Maps
PyDX Presentation about Python, GeoData and Maps
 
GeoDjango & HTML5 Geolocation
GeoDjango & HTML5 GeolocationGeoDjango & HTML5 Geolocation
GeoDjango & HTML5 Geolocation
 
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜
Map Reduce 〜入門編:仕組みの理解とアルゴリズムデザイン〜
 
Geolocation on Rails
Geolocation on RailsGeolocation on Rails
Geolocation on Rails
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macros
 
Pycon2011
Pycon2011Pycon2011
Pycon2011
 
OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
 
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
10. R getting spatial
10.  R getting spatial10.  R getting spatial
10. R getting spatial
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
R getting spatial
R getting spatialR getting spatial
R getting spatial
 
Scaling up data science applications
Scaling up data science applicationsScaling up data science applications
Scaling up data science applications
 
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
Scaling Up: How Switching to Apache Spark Improved Performance, Realizability...
 
Hadoop I/O Analysis
Hadoop I/O AnalysisHadoop I/O Analysis
Hadoop I/O Analysis
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 

More from Calvin Cheng

FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/SovrinFOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
Calvin Cheng
 
Hashgraph as Code
Hashgraph as CodeHashgraph as Code
Hashgraph as Code
Calvin Cheng
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
Calvin Cheng
 
Functional Programming for OO Programmers (part 1)
Functional Programming for OO Programmers (part 1)Functional Programming for OO Programmers (part 1)
Functional Programming for OO Programmers (part 1)
Calvin Cheng
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4
Calvin Cheng
 
iOS Beginners Lesson 3
iOS Beginners Lesson 3iOS Beginners Lesson 3
iOS Beginners Lesson 3
Calvin Cheng
 
iOS Beginners Lesson 2
iOS Beginners Lesson 2iOS Beginners Lesson 2
iOS Beginners Lesson 2
Calvin Cheng
 
iOS Beginners Lesson 1
iOS Beginners Lesson 1iOS Beginners Lesson 1
iOS Beginners Lesson 1
Calvin Cheng
 
So, you want to build a Bluetooth Low Energy device?
So, you want to build a Bluetooth Low Energy device?So, you want to build a Bluetooth Low Energy device?
So, you want to build a Bluetooth Low Energy device?
Calvin Cheng
 
Learning iOS and hunting NSZombies in 3 weeks
Learning iOS and hunting NSZombies in 3 weeksLearning iOS and hunting NSZombies in 3 weeks
Learning iOS and hunting NSZombies in 3 weeks
Calvin Cheng
 
Ladypy 01
Ladypy 01Ladypy 01
Ladypy 01
Calvin Cheng
 
Agile Apps with App Engine
Agile Apps with App EngineAgile Apps with App Engine
Agile Apps with App Engine
Calvin Cheng
 

More from Calvin Cheng (13)

FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/SovrinFOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
FOSSASIA 2018 Self-Sovereign Identity with Hyperledger Indy/Sovrin
 
Hashgraph as Code
Hashgraph as CodeHashgraph as Code
Hashgraph as Code
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
Functional Programming for OO Programmers (part 1)
Functional Programming for OO Programmers (part 1)Functional Programming for OO Programmers (part 1)
Functional Programming for OO Programmers (part 1)
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4
 
iOS Beginners Lesson 3
iOS Beginners Lesson 3iOS Beginners Lesson 3
iOS Beginners Lesson 3
 
iOS Beginners Lesson 2
iOS Beginners Lesson 2iOS Beginners Lesson 2
iOS Beginners Lesson 2
 
iOS Beginners Lesson 1
iOS Beginners Lesson 1iOS Beginners Lesson 1
iOS Beginners Lesson 1
 
So, you want to build a Bluetooth Low Energy device?
So, you want to build a Bluetooth Low Energy device?So, you want to build a Bluetooth Low Energy device?
So, you want to build a Bluetooth Low Energy device?
 
Fabric
FabricFabric
Fabric
 
Learning iOS and hunting NSZombies in 3 weeks
Learning iOS and hunting NSZombies in 3 weeksLearning iOS and hunting NSZombies in 3 weeks
Learning iOS and hunting NSZombies in 3 weeks
 
Ladypy 01
Ladypy 01Ladypy 01
Ladypy 01
 
Agile Apps with App Engine
Agile Apps with App EngineAgile Apps with App Engine
Agile Apps with App Engine
 

Recently uploaded

Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
UiPathCommunity
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
Globus
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 

Recently uploaded (20)

Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 

Saving Gaia with GeoDjango

  • 1. SAVING GAIA w/jQuery Mobile, OpenLayers and GeoDjango
  • 2. CALVIN CHENG www.calvinx.com www.od-eon.com/blogs/calvin
  • 3. 1 Context 2 Technology Stack 3 Installation
  • 4. 4 Django GeoModel & ORM 5 Geospatial Libraries 6 Utilities
  • 5. 7 GeoAdmin 8 OpenLayers 9 jQuery (Mobile)
  • 6. 10 Possibilities 11 Conclusion
  • 8. REDDCalculator.com (Beta) SEC (Closed Beta) LUC (Coming Soon!) ! ENVIRONMENTAL iTOOLS Spatially Explicit Scenario Analysis: Norway-Indonesia’s Forest Moratorium Species Extinction Calculator (SEC) Land Use Calculator (LUC)
  • 9.
  • 11. 4% 4" &'#()#*% 123# !"#$$%&'()*"+,-./0" !"#$%
  • 12. 3,000 2,250 Number of species 1,500 750 0 100 200 300 400 500 600 700 800 Area conserved (km sq) SPECIES-AREA More habitats conserved (Area) = More fauna diversity (Species)
  • 13.
  • 14. +) !) ) &,- ! ) * "#$%$&'( ( ) . &,- . ) "#$%$&'( )
  • 15. !"#$%&'()3+(451"67(&/&012( !"#$%&'()*+(,-.&(&/&012(
  • 16. 0$1,23+4")56)'."+4,2+"+'*,'7$2/+)$4"'8$*.51' !"#$%&"'"(")*+',-'-,."+*'"/#"+' N # $ % "i $ ! i i =1 ! - M ( ) #% "!$ j ) ) ) * &+, &+, j =1 ! - ) ) "#$%$&'( "#$%$&'(
  • 17. MATRIX-CALIBRATED SPECIES-AREA Accounts for taxon-specific responses to different components of the landscape
  • 18. EXAMPLE OF AN AREA? Conservation Forests, National Reserves etc Borneo 743,330 square kilometres
  • 19. USERS AND USE-CASE Conservation scientists and Land owners define areas which are conserved by plotting polygons on a map source (e.g. Google Maps). Areas which are slated for development are also marked. By quantifying area conservation goals (areas conserved before and after development) and its impact on the loss of species, SEC is a tool which helps people make better trade-off decisions.
  • 20. USERS AND USE-CASE REDDCalculator.com computes the socio-economic trade-offs and results as a consequence of the Norway-Indonesia REDD+ Moratorium.
  • 21.
  • 23. Layers & Features (‘Vector Objects’) jQuery & OpenLayers User Interface Map Source KML GML WKT GeoJSON GeoRSS Others Data (serialized) GeoDjango Python Logic C/C++ Libraries w/ Python Bindings & Datastore
  • 25. (2.7)
  • 27. sudo -u postgres psql -d yourdatabase_name -f { ... }/postgis.sql sudo -u postgres psql -d yourdatabase_name -f { ... }/postgis_comments.sql sudo -u postgres psql -d yourdatabase_name -f { ... }/spatial_ref_sys.sql
  • 28. sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/ software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/ contrib/postgis-1.5/postgis.sql sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/ software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/ contrib/postgis-1.5/postgis_comments.sql sudo -u postgres psql -d yourdatabase_name -f /opt/local/var/macports/ software/postgis/1.5.2_1+postgresql90/opt/local/share/postgresql90/ contrib/postgis-1.5/spatial_ref_sys.sql
  • 29. Portage exists But here’s a magical way - https://github.com/stefantalpalaru/dotfiles/ tree/master/Gentoo/custom%20overlay/portage/dev-db/postgis - custom postgis ebuild modified by Stefan add ebuild to local ‘overlay’ (a gentoo terminology) emerge postgis edit configuration file in /etc/conf.d/postgis and add in the postgresql database that you need ‘postgis-enabled’ emerge --config postgis
  • 30. # settings.py INSTALLED_APPS = ( # Core Django Apps 'django.contrib.contenttypes', 'django.contrib.auth', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.admindocs', 'django.contrib.flatpages', 'django.contrib.humanize', 'django.contrib.comments', 'django.contrib.markup', 'django.contrib.webdesign', 'django.contrib.sitemaps', 'django.contrib.gis', # Custom Apps for REDDCalculator.com 'updatemodel', 'location', 'areadata', # Generic and reusable apps for most projects 'south', 'django_cherrypy_odeon', 'misc', 'cron', 'notify', 'log', 'homepage', 'userprofile', )
  • 31. # settings.py DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', ‘NAME’: ‘yourdatabase_name’, 'USER': 'yourdatabase_user’, 'PASSWORD': 'yourdatabase_password', 'HOST': 'your_ip_or_domain', } }
  • 34. from django.contrib.gis.db import models class Province(models.Model): name = models.CharField(max_length=256) name_long = models.CharField(max_length=256, null=True) island = models.ForeignKey(Location, null=True) geom = models.MultiPolygonField(srid=4326, null=True) objects = models.GeoManager()
  • 35. from django.contrib.gis.db import models class Province(models.Model): name = models.CharField(max_length=256) name_long = models.CharField(max_length=256, null=True) island = models.ForeignKey(Location, null=True) geom = models.MultiPolygonField(srid=4326, null=True, geography=True) objects = models.GeoManager()
  • 36. What are the geometry fields available to us in django?
  • 37. GEOS: OGC simple feature implementation PointField MultiPointField LineStringField MultiLineStringField PolygonField MultiPolygonField GeometryCollectionField
  • 38. PointField (x, y)
  • 40. LineStringField ((x1, y1), (x2, y2), (x3, y3), (x4, y4))
  • 41. MultiLineStringField (((x1, y1), (x2, y2), (x3, y3), (x4, y4)),((x5, y5), (x6, y6)))
  • 42. PolygonField ((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1))
  • 43. MultiPolygonField ((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)), ((x5, y5), (x6, y6), (x7, y7), (x5, y5)))
  • 44. GeometryCollectionField ((x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)), ((x5, y5), (x6, y6), (x7, y7)), ((x8, y8)))
  • 45. Practical Example #1: Species Extinction Calculator
  • 46. Practical Example #2: REDDCalculator.com
  • 47. from django.contrib.gis.gdal import datasource, spatialreference from django.contrib.gis.geos import multipolygon, geosgeometry shapefile = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../proj_public/media/files/giveshapefile.shp')) ds = DataSource(shapefile) layer = ds[0] # Checked in Python shell that this has only 1 layer
  • 48. from django.contrib.gis.db import models class AreaData(models.Model): district = models.ForeignKey(District) # District is FKed to Province land_use = models.IntegerField(choices=VEGETATION_TYPES) allocation = models.IntegerField(choices= CHOICES['LAND_ALLOCATION']) intact = models.IntegerField() concession = models.CharField(max_length=255, blank=True) peat = models.CharField(max_length=255, blank=True) area = models.FloatField(help_text='hectares') fid = models.IntegerField() # ... and any other. geom = models.MultiPolygonField(srid=4326, null=True) objects = models.GeoManager()
  • 49. area = AreaData.objects.get(fid = feature.fid) geometry_name = feature.geom.geom_type.name geometry_object = feature.geom.transform(SpatialReference(4326), clone=True).geos # update our area object with the geom data from our shape file if geometry_name == 'Polygon': # If our geometry object is a Polygon, we cast as MultiPolygon first geometry_object = MultiPolygon(geometry_object) area.geom = geometry_object area.save()
  • 51. GEOS GDAL PROJ.4 Mapnik GeoIP
  • 52. GEOS Geometry Engine - Open Source What does it do? Works with django GIS app to give us GeoModels!
  • 53. GEOS Geometry Engine - Open Source Other Details Required dependency for django GIS app C++ Implements OGC simple feature for SQL specification OGC = Open Geospatial Consortium e.g. sudo port install geos
  • 54. GDAL Geospatial Data Abstraction Library What does it do? Reads and writes to a variety of vector file formats, e.g. shp
  • 55. GDAL Geospatial Data Abstraction Library Other Details C/C++ Implements OGC simple feature specification e.g. sudo port install gdal
  • 56. PROJ.4 Cartographic Projections Library What does it do? Manages spatial reference systems and projections e.g. the mercator projection commonly used by Google Maps, MapQuest etc
  • 57. PROJ.4 Cartographic Projections Library Other Details Required dependency for PostGIS C Ensures that geometry objects stored in PostGIS use the appropriate projection sudo port install libproj4
  • 58. Mapnik Toolkit for developing Mapping Applications What does it do? For the control freak in you :-) Build your own maps, control and customize every single detail
  • 59. Mapnik Toolkit for developing Mapping Applications Other Details C++ Uses boost for python interface No py27-mapnik yet. Solution? Create your own local portfile using py26-mapnik sudo port install py27-mapnik
  • 60. GeoIP Locate users by IP address What does it do? Determines the location of app user via user’s IP address
  • 61. GeoIP Locate users by IP address Other Details C No py27-geoip yet. Solution? Create your own local portfile using py26-geoip sudo port install libgeoip py27-libgeoip
  • 63. LayerMapping ./manage.py ogrinspect ./manage.py ogrinfo
  • 64. ./manage.py ogrinspect and LayerMapping
  • 65. $ ./manage.py ogrinspect ../proj_public/media/files/redd_data/ kalimantan_universe.shp Location --srid=4326 --mapping # This is an auto-generated Django model module created by ogrinspect. from django.contrib.gis.db import models class Location(models.Model): island = models.CharField(max_length=50) geom = models.MultiPolygonField(srid=4326) objects = models.GeoManager() # Auto-generated `LayerMapping` dictionary for Location model location_mapping = { 'island' : 'island', 'geom' : 'MULTIPOLYGON', }
  • 66. # models.py from django.contrib.gis.db import models class Location(models.Model): island = models.CharField(max_length=50) geom = models.MultiPolygonField(srid=4326) objects = models.GeoManager() # Auto-generated `LayerMapping` dictionary for Kalimantan model location_mapping = { 'island' : 'island', 'geom' : 'MULTIPOLYGON', }
  • 67. import os from django.contrib.gis.utils import LayerMapping from django.contrib.gis.gdal import DataSource from location.models import Location, location_mapping shapefile = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../proj_public/media/files/kalimantan_universe.shp')) ds = DataSource(shapefile) layer = ds[0] # Checked in Python shell that this has only 1 layer kalimantan = LayerMapping(Location, shapefile, location_mapping, transform = True, encoding='iso-8859-1') kalimantan.save(strict = True, verbose = True)
  • 69. from django.contrib.gis import admin as geoadmin from location.models import Location admin.site.register(Location, geoadmin.GeoModelAdmin)
  • 70.
  • 72. “ OpenLayers is a pure JavaScript library for displaying map data in most modern web browsers, with no server-side dependencies. ”
  • 74. “ jQuery Mobile is a Touch-Optimized Web Framework for Smartphones and Tablets. ”
  • 75. + +
  • 76. $(document).ready(function(){ $('#map_delete').hide() // Define a custom styles which will be used by our polygon layer var style = $.extend(true, {}, OpenLayers.Feature.Vector.style['default']) // get a copy of default style style.pointRadius = 15 var styleMap = new OpenLayers.StyleMap({"default": style}) // Define a custom style which will be used by our background layer var backgroundStyle = $.extend(true, {}, OpenLayers.Feature.Vector.style['default']) // get copy backgroundStyle.fillOpacity = "0.1" backgroundStyle.fillColor = "#000000" backgroundStyle.strokeColor = "#999999" var backgroundStyleMap = new OpenLayers.StyleMap({"default": backgroundStyle}) // Define our background layer backgroundLayer = new OpenLayers.Layer.Vector("Background Layer", {styleMap: backgroundStyleMap} )
  • 77. // Define our vector layer polygonLayer = new OpenLayers.Layer.Vector("Polygon Layer", {styleMap: styleMap}) polygonLayer.events.on({ 'featureselected': show_delete_button, 'featureunselected': hide_delete_button }) // Define our toolbar, panels and associated controls // pinch and zoom is defined in touch navigation var touchNavigation = new OpenLayers.Control.TouchNavigation({ dragPanOptions: { interval: 100, enableKinetic: true } }) // define our zoom panel var zoomPanel = new OpenLayers.Control.ZoomPanel() // define our layer switcher var layerSwitcher = new OpenLayers.Control.LayerSwitcher()
  • 78. // controls drawControl = new OpenLayers.Control.DrawFeature(polygonLayer, OpenLayers.Handler.Polygon, { displayClass: 'olControlDrawFeaturePolygon'}); selectControl = new OpenLayers.Control.SelectFeature(polygonLayer, { clickout: true }); editControl = new OpenLayers.Control.ModifyFeature(polygonLayer, { selectControl: selectControl, vertexRenderIntent: 'temporary', displayClass: 'olControlModifyFeature'}); // define our custom control tool bar var toolbar = new OpenLayers.Control.Panel({displayClass: 'olControlEditingToolbar'}); toolbar.addControls([ //this control is just there to be able to deactivate the drawing tools and pan the map drawControl, editControl, new OpenLayers.Control({ displayClass: 'olControlNavigation' }) ]);
  • 79. // Define Map Layers var gphy = new OpenLayers.Layer.Google("Google Physical", {type: google.maps.MapTypeId.TERRAIN}); var gmap = new OpenLayers.Layer.Google("Google Streets", {numZoomLevels: 20}); var ghyb = new OpenLayers.Layer.Google("Google Hybrid", {type: google.maps.MapTypeId.HYBRID, numZoomLevels: 20}); var gsat = new OpenLayers.Layer.Google("Google Satellite", {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 20}); // Feed the controls and layers defined above to our map object map = new OpenLayers.Map({ div: 'map', controls: [zoomPanel, touchNavigation, layerSwitcher, toolbar], layers: [ghyb, gphy, gmap, gsat, backgroundLayer, polygonLayer] })
  • 80.
  • 81. // Google.v3 uses EPSG:900913 as projection, so we have to transform our coordinates mapProjection = map.getProjectionObject() map.setCenter(new OpenLayers.LonLat(map_center_lon, map_center_lat).transform(defaultProjection, mapProjection), map_zoom) // if there's a Total Landscape Area polygon, we will draw it on the backgroundLayer. if (background_coords_json){ var pointList = [] for (var i=0; i<background_coords_json.length; i++) { var point = new OpenLayers.Geometry.Point(background_coords_json[i][0], background_coords_json[i] [1]) pointList.push(point.transform(defaultProjection, mapProjection)); } var linearRing = new OpenLayers.Geometry.LinearRing(pointList) totalAreaPolygon = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([linearRing])) backgroundLayer.addFeatures([totalAreaPolygon]) }
  • 82. // draw the existing features into the polygonLayer var loaded_features = [] for (var i=0; i<list_of_coords_json.length; i++) { var pointList = [] for (var j=0; j<list_of_coords_json[i].length; j++) { var point = new OpenLayers.Geometry.Point(list_of_coords_json[i][j][0], list_of_coords_json[i][j][1]) pointList.push(point.transform(defaultProjection, mapProjection)); } var linearRing = new OpenLayers.Geometry.LinearRing(pointList) var polygonFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([linearRing]), {fid: list_of_coords_ids_json[i]}) loaded_features.push(polygonFeature) } polygonLayer.addFeatures(loaded_features) polygonLayer.events.on({ "featuremodified": polygonSave, "featureadded": polygonSave, "vertexmodified": adjustVertex, "sketchstarted": adjustVertex, "sketchmodified": adjustVertex }) // confirmation dialog $('#project_map_delete_polygon_yes').click(delete_polygon) }) /* END of $(document).ready() */
  • 84. 1. Offline Maps for Field Usage 2. Remote Controlled UAV for data collection 3. Crunch collected data and generate visualizations
  • 85. Offline Maps for Field Usage
  • 86. Layers & Features (Saved Locally, Syncing) Native iOS/Android Native? Map Source (Local Map Tiles) KML GML WKT GeoJSON GeoRSS Others Data Transfer GeoDjango Python Logic C/C++ Libraries w/ Python Bindings & Datastore
  • 87. The Problem with iOS MapKit Framework MKMapView class implements Google Maps API natively Unfortunately, Google Maps terms of use prevents us from caching or storing map tiles locally
  • 88. Alternative? https://github.com/route-me/route-me Supports many map sources - OpenStreetMap, Microsoft VirtualEarth, CloudMade, OpenAerialMap, OpenCycleMap, SpatialCloud OpenStreetMap permits map tile caching and local storage Supports 2 offline, database-backed formats DBMap and MBTiles
  • 89. A Comparison MKMapKit Route-Me Embed in iOS App YES YES Interaction YES YES Geolocalization YES YES Different Map Sources NO YES Offline Maps NO YES
  • 90. The Problem with Android Google Maps Framework Renders Google Maps of course Support for alternative map sources is important
  • 91. Alternative? https://github.com/camptocamp/android-gis.git Supports many map sources - OpenStreetMap, Microsoft VirtualEarth, CloudMade, OpenAerialMap, OpenCycleMap, SpatialCloud OpenStreetMap permits map tile caching and local storage Supports 2 offline, database-backed formats DBMap and MBTiles
  • 92. Benefits Fast (obviously, since Map Tiles are stored locally) 100% Offline Stored as blob data for SQLite Client Access
  • 94. Collect Real Data => Effects on Landscape Change on Species e.g. obtain actual change in Forest Boundaries (instead of just predicting on map on current prediction tool)
  • 95. Prediction is great. But we want real world data from primary forests!
  • 96.
  • 97.
  • 98.
  • 100. Crunch Collected Data => 2 possible approaches - Decoupled R and Python - Integrated Approach RPy Option
  • 101. Decouple R and Python Python retrieves data from django/postgresql Python converts data shapefiles, images etc Launches R given a *.r file with Scientist’s parameters R does the analysis Python does post-processing, projecting data etc
  • 102. Integrated R & Python with RPy R and Python closely coupled RPy and RPy2 provides an interface to R Programming Language Python retrieves and organizes parameters from django/postgresql RPy module imported and R commands are executed within the Python script file
  • 104. Getting a GPS fix via Satellite?
  • 105. Mathematical Modelling, Scenario Analysis for Environmental Policies
  • 106.
  • 107. REDDCalculator.com (Live) SEC (Closed Beta) LUC (Coming Soon!) ! ENVIRONMENTAL iTOOLS Spatially Explicit Scenario Analysis: Norway-Indonesia’s Forest Moratorium Species Extinction Calculator (SEC) Land Use Calculator (LUC)
  • 108. Species Extinction Calculator and REDDCalculator: Mathematical Models and Formulas by Koh et. al are completely translated into Python Land Use Calculator: Ditto. Coming Soon!
  • 110. Mapnik is useful for rasterizing vector objects when we encounter large datasets (in our case, 200 MB+ of protected areas in Kalimantan). (jQuery Mobile) Web App can benefit from optimization through django caching. To be done right after EuroPython! And besides jQuery Mobile Beta 1 has just been released on Monday (20 June 2011)! :-) Usability and App Responsiveness can possibly be improved, Out-Field/ Offline Benefits attainable, if we move interface elements and Map Tiles into a native app (Android or iOS).
  • 111. geography=True/False in a GeoDjango field 2 ways to import data from a given GIS Shape File (1) LayerMapping (2) Direct Assignment to obj.geom attribute as mentioned.
  • 112. “ Advancing Environmental Sciences: helping people, scientists, NGOs and governments make practical Land Area Usage and Conservation Decisions using jQuery (Mobile), OpenLayers and GeoDjango! ”
  • 114. Make sure Projections/Datum in your shape file source corresponds with your geometry field’s SRID and Map Source Using LayerMapping? transform = True Directly creating or saving into an object’s attribute? geometry_object = feature.geom.transform(SpatialReference(4326), clone=True).geos area.geom = geometry_object area.save()
  • 116. + North-South Fund Prof. Koh Lian Pin Prof. Matthew Hansen Prof. Holly Gibbs ETH Zurich, Dept of Env Sciences South Dakota State University Stanford Dept of Environmental NUS, Dept of Biological Sciences GIS Center of Excellence Earth System Sciences
  • 117. Stefan Talpalaru Liviu Bogdan Chiributa That’s Me! :-) Odeon Consulting Group Odeon Consulting Group Odeon Consulting Group + ........
  • 118. Previous GeoDjango Presentations + my little contribution www.geodjango.org/presentations www.od-eon.com/presentations
  • 119. Questions and Discussion welcome! calvin.cheng@od-eon.com

Editor's Notes

  1. * hallo and thank you for joining me here to learn more about geodjango, jquery mobile and openlayers.\n* This is my first time at europython and I am glad to be here, learning so much from you, my python peers.\n
  2. * I am Calvin and I work as a user-interface/python developer in a company incorporated in Singapore.\n* We are a very small and relatively young software development team (3-4 years old), but our company is unusual because we work with customers from all over the world.\n* We are very fortunate to be able to work on some really fascinating projects and amazing customers for the past 2 to 3 years.\n* We have built all sorts of application including game and social network ones.\n* But over the past couple of years, we have discovered that we are especially passionate about building software related to science.* Specifically, in our various projects with ETH Zurich, I am learning a lot about GIS (Geographical Information System) in relation to Conservation Biology and Environmental Science.\n* In a separate and unrelated project with the University of Southern California, our team has the opportunity of helping neuroscience researches archive and understand neural circuitry - a fascinating and ever-evolving domain as scientists learn more about different parts of the mammalian brain. \n
  3. * Today, I will be talking about the context in which jQuery Mobile, OpenLayers and GeoDjango are applied to help scientists, NGOs and governments make practical land use and conservation decisions.\n* I will illustrate the technology stack that we have used and talk briefly about the installation process for various GeoDjango dependencies on Mac OS X and Gentoo. \n* We usually use Gentoo on our servers. Yes I know, it&amp;#x2019;s nuts but that&amp;#x2019;s what Stefan, my colleague and CTO in Odeon, is proficient with, with over 11 years of experience.\n* My weapon of choice for my interface design and python work is my Macbook.\n
  4. * We will of course, have some code examples showing how we set up the Models in our environmental science apps and how we use the GeoDjango ORM to update our database with information from the user or from existing shapefile datasource.\n* In order for us to work effectively, it also helps to understand a little about what goes on behind the scenes and what each of the geospatial libraries we have installed do.\n* It also helps for us to understand some of the helper functions, otherwise known as utilities, in GeoDjango helps make life easier when we want to inspect a shape file or write our model knowing what to expect from the shape file.\n\n
  5. * Part of what makes django so wonderful is its django admin feature. The good news, of course, is that when geodjango was officially merged into django trunk as the GIS contrib app, they have also made GeoAdmin awesome by automagically showing the geographical feature on a map using openlayers in the admin.\n* Section 8 and 9 actually go hand-in-hand together and I will show you some example javascript code there.\n
  6. * In the last part of my presentation, I will explore different ways, possible ways to improve the app in our next development iteration.\n* And finally, summarize the lessons learnt in our first development iteration.\n
  7. \n
  8. * There are 3 tools under active development for environmental scientists at ETH Zurich.\n* The first app is reddcalculator.com, which is a tool to illustrate socioeconomic consequences, job losses and gains as a result of implementing the Norway-Indonesia REDD Moratorium.\n* REDD stands for &amp;#x201C;Reducing Emissions from Deforestation and Forest Degradation in Developing countries&amp;#x201D;.\n* The idea is to assign a financial value for the carbon stored in forests and offer incentives for developing countries to reduce emissions from forested lands and invest in low-carbon paths to sustainable development.\n* The 2nd tool is species extinction calculator, which is a mathematical model designed by a group of Environmental Scientists, Koh Et Al, to predict species loss as a consequence of change in their habitat or the landscape.\n* The land use calculator is a generalized model, similar to what we have already done in reddcalculator.com and predicts socioeconomic consequences of land use decisions and policies. \n\n
  9. * We will begin by talking about the Species Extinction Calculator, an app which is currently under closed beta.\n
  10. * Orangutan\n* Clouded Leopard\n* Pygmy Elephants\n* Sumatran Rhino\n* These are the 4 major species that are going extinct in a South East Asian island called Borneo.\n* As our human activities reduce the natural habitats, forests and food available to these species, they are directly affected and begin to disappear from Earth.\n* While I am not a green activist or terrorist, it saddens me that the species diversity in this world are dramatically reduced as a consequence of our actions.\n* Following Ms Ravenscroft admonition to adopt Diversity as a Dependency in the Python community on Monday, I am proposing that we consider our friends in the animal kingdom part of beauty and diversity of the Python community.\n* After all, Python&amp;#x2019;s logo is pretty much represented by 2 very cute blue and yellow snakes.\n* So, on a serious note, this project is very much about using Python code to help decision makers understand the consequence of their actions and help people make better decisions on land use and socio-economic tradeoffs.\n
  11. * So, this is where it begins. Species extinction in the old days have been simply correlated to Area loss using the Arrhenius equation.\n\n
  12. * Here&amp;#x2019;s a graphical representation of the Arrhenius formula.\n* But of course, this is an outdated model and is wildly inaccurate.\n
  13. * Modern conservation biologists and environmental scientists needed a more accurate prediction model\n* And they realise that land-use change on a mainland often creates landscapes that kind of look like islands of forests in an ocean of other land uses\n\n
  14. * So this is what modern environmental scientists adopted as a working model.\n* The species-area model is often used by conservation biologists to predict biodiversity loss based upon forest loss\n* S(new) refers to species after an area of interest (also referred to as the &amp;#x201C;Total Landscape Area&amp;#x201D;) has been modified by human activity.\n* S(original) refers to the original number of species residing in the area.\n* Ditto for A\n* Z is an arbitrary number which varies according to various other conditions\n
  15. However, there are 2 problems with this approach...\n#1: it assumes that the landscape matrix, the land uses in-between forest fragments, are completely inhospitable to any species, which obviously is not always true\n#2: it assumes that species are not affected by edge effects: deleterious effects on a forest fragment mediated by biophysical interactions near the interface between forest and matrix\nAlthough ecologists know that these assumptions are unrealistic, the species-area model continues to be used in assessments of biodiversity loss and in conservation planning. That was what motivated Koh et. al to develop a better tool \n\n
  16. * Koh et al&amp;#x2019;s improved model addresses those shortcomings by accounting for how species respond to changes in composition &amp; quality of the matrix, and it also accounts for effects of forest edges\n* These improvements allow for predictions of extinction risks that are specific to the landscape and the taxon of interest\n* Result? An improved accuracy in predicting how land use changes affect species diversity\n* This new model of predicting species response to land use changes has been accepted in Conservation Biology and Journal of Applied Ecology.\n\n
  17. * This gives us a beautiful 3 dimensional graph as above.\n* So how does all these formulas relate to what we do with a GIS (Geographical Information System) application using GeoDjango?\n
  18. * Area, of course. Calculating and defining the area is core to producing a reasonably accurate prediction estimate for policy making by governments, NGOs and the united nation.\n* 3rd largest island in the world. (after greenland and new guinea). Ref: http://en.wikipedia.org/wiki/List_of_islands_by_area\n*The island is divided among three countries: Brunei, Indonesia and Malaysia. Approximately 73% of the island is Indonesian territory. The Malaysian states of Sabah and Sarawak in the north occupy about 26% of the island. The sovereign state of Brunei, located on the north coast, comprises about 1% of Borneo&apos;s land area. It has the oldest rainforest in the world ahead of the Amazon rainforest inBrazil.\n
  19. * 3rd largest island in the world. (after greenland and new guinea). Ref: http://en.wikipedia.org/wiki/List_of_islands_by_area\n* Specifically Kalimantan\n\n
  20. * Loss of species, carbon emissions as a balance against employment and financial losses\n\n
  21. * Here&amp;#x2019;s an example screen shot of polygons plotted by land owners in collaboration with environmental scientists.\n* We will go into the code details and what each of these polygons in a while.\n* But first, for those not familiar with terminologies and the basic concepts of Geographical Information Systems (GIS) software, I will provide a simple overview of the technology stack and associated libraries which you will need to install before getting started.\n
  22. \n
  23. * The user interface\n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. * &amp;#x201C;from django.db import models&amp;#x201D; is, of course, the usual way we import the django models class before writing our custom models.\n* For our model to contain GIS capabilities, like storing a geographical feature as an attribute, we will simply subclass from django.contrib.gis.db instead.\n\n
  34. * add the geometry field you need. in this example, &amp;#x201C;geom&amp;#x201D; is our geometry field and it is a contains a MultiPolygon object using the datum WGS84 (i.e. 4326)\n* \n\n
  35. * an interesting note about the geography attribute in a GeoDjango Field\n* polygons computed are assumed to be based on its 2D area.\n* by stating geography=True, areas computed will based on the ellipsoidal surface area, which gives a more accurate result at the expense of slightly poorer performance\n* in other words, you need to take a design decision on this trade-off.\n
  36. * &amp;#x201C;from django.db import models&amp;#x201D; is, of course, the usual way we import the django models class before writing our custom models.\n* For our model to contain GIS capabilities, like storing a geographical feature as an attribute, we will simply subclass from django.contrib.gis.db instead.\n\n
  37. \n\n
  38. * represented by coordinates, specific to the projection or datum\n\n
  39. * represented by coordinates, specific to the projection or datum\n\n
  40. * represented by coordinates, specific to the projection or datum\n\n
  41. * represented by coordinates, specific to the projection or datum\n\n
  42. * represented by coordinates, specific to the projection or datum\n\n
  43. * obviously :-) more than 1 or more Polygons stored in this field!\n\n
  44. * A collection of different geometries can be stored in the field\n\n
  45. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  46. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  47. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  48. * Here&amp;#x2019;s an example showing you how I have set up our AreaData class. The attributes in the AreaData class includes the MultiPolygonField as well as other information I need for Species Extinction computation.\n\n
  49. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n\n
  65. * ogrinspect is a really useful django management command which comes with django.contrib.gis.\n* It inspects a given .shp file (Shape File) and auto generates a suggested model and LayerMapping dictionary.\n\n
  66. * So as suggested by ogrinspect, we should define the location_mapping dictionary if we decide to use the LayerMapping utility to import shapefile data into your postgis database.\n\n
  67. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n* The strict parameter, when True, is to stop the execution of model mapping upon the first error encountered. For me, I wanted to know when an error has occurred when I importing the data in the shapefile, hence, I specify it to be True. The default is False, which means that it will attempt to continue even if it encounters an error.\n\n
  68. \n
  69. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  70. * Using GeoDjango APIs with a model containing a MultiPolygonField!\n\n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. * Here, in this OpenLayer javascript, we define custom controls for the user and assign it to the toolbar variable, which is later on assigned to the controls attribute in the next slide.\n
  79. * Placing the various map options from Google Map Source, and in the above code, rendering the Google Hybrid code in priority.\n* Google Hybrid. Google Physical. Google Street Maps. Google Satellite.\n* backgroundLayer contains holds the grey border, transparent polygon -&gt; &amp;#x201C;Total Landscape Area&amp;#x201D;, more expressively understood as &amp;#x201C;the area we are interested in&amp;#x201D;\n* polygonLayer contains either the &amp;#x201C;Before&amp;#x201D; we change the landscape polygons, each representing different landscape type (which is referred to by the scientists as a &amp;#x2018;Matrix&amp;#x2019;)\n* Or &amp;#x201C;After&amp;#x201D;.\n* Once we have &amp;#x201C;Total Landscape Polygon&amp;#x201D; defined, &amp;#x201C;Before polygons defined&amp;#x201D;, &amp;#x201C;After polygons&amp;#x201D; defined, we can compute &amp;#x201C;expected species loss&amp;#x201D;\n
  80. * Here, you can visualize what I just explained.\n
  81. * When we first define our Total Landscape Area polygon, we don&amp;#x2019;t need the backgroundLayer.* The backgroundLayer is intended to display the Total Landscape Area polygon already defined when the User is plotting out his &amp;#x201C;Before&amp;#x201D; or &amp;#x201C;After&amp;#x201D; polygons.\n
  82. \n
  83. \n
  84. \n\n
  85. \n\n
  86. * The user interface comprising jQuery Mobile and OpenLayers could be completely replaced by native ones so land surveyors can work independent of 3G/Edge Network availability.\n* Sending field data into the server only when 3G/Edge Network are available.\n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. * MBTiles is a specification for storing tiled map data in SQLite databases for immediate use and for transfer. The files are designed for portability of thousands, hundreds of thousands, or even millions of standard map tile images in a single file.* This makes it easy to manage and share map tiles\n\n
  93. \n\n
  94. \n\n
  95. \n
  96. \n\n
  97. \n\n
  98. \n\n
  99. \n\n
  100. \n\n
  101. \n\n
  102. \n\n
  103. \n
  104. * There are interesting products and satellite services in the market that work with Android and iOS devices.\n* An example is TomTom. This is something I have yet to explore in detail but it is an interesting feature that would empower field work for scientists and land owners where terrestrial 3G network isn&amp;#x2019;t available.\n
  105. \n\n
  106. * Here&amp;#x2019;s one of the excel file holding all the formulas our scientist collaborators have painstakingly built.\n
  107. \n
  108. * Translation of excel formulas and vbscript (ack!) to Python\n
  109. \n\n
  110. \n\n
  111. * The geography argument in our GeoDjango field is an important factor when considering the accuracy of the area in your defined Polygon.* The default is False. When we specify it to be True, area computation for the given Polygon or MultiPolygon assumes a surface area on an ellipsoidal earth. \n* This computation is done at the expense of some performance loss.\n* geography=False computes area ased on a flat, 2D polygon area.\n* LayerMapping versus directly assigning to \n\n
  112. \n\n
  113. \n\n
  114. \n
  115. \n
  116. \n
  117. \n
  118. * First, I must say that django GIS&amp;#x2019;s documentation is kickass. If my presentation is not clear in anyway, I am pretty sure Django GIS documentation will help you out.\n* I have also listed a very comprehensive list of really good presentations relating to GeoDjango. If you are serious about GIS development, I encourage you to go through every single one of them.\n* I will, of course, upload this presentation, my little contribution to the fascinating world of GeoDjango online. You should be able to find it on the 2nd url by tomorrow.\n
  119. * GIS is a really fascinating topic in the world of Python and Django.\n* I am new to the topic and have much to learn!\n* I will be happy to link up with any geodjango developers out there to share our skills and knowledge.\n\n