[GRASS-SVN] r69294 - in grass-addons/grass7/vector: . v.in.pygbif

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Aug 29 01:34:19 PDT 2016


Author: sbl
Date: 2016-08-29 01:34:19 -0700 (Mon, 29 Aug 2016)
New Revision: 69294

Added:
   grass-addons/grass7/vector/v.in.pygbif/
   grass-addons/grass7/vector/v.in.pygbif/Makefile
   grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.html
   grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.py
Log:
Added new addon: v.in.pygbif from Code Sprint

Added: grass-addons/grass7/vector/v.in.pygbif/Makefile
===================================================================
--- grass-addons/grass7/vector/v.in.pygbif/Makefile	                        (rev 0)
+++ grass-addons/grass7/vector/v.in.pygbif/Makefile	2016-08-29 08:34:19 UTC (rev 69294)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.in.pygbif
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script


Property changes on: grass-addons/grass7/vector/v.in.pygbif/Makefile
___________________________________________________________________
Added: svn:mime-type
   + text/x-makefile
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.html
===================================================================
--- grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.html	                        (rev 0)
+++ grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.html	2016-08-29 08:34:19 UTC (rev 69294)
@@ -0,0 +1,56 @@
+<h2>DESCRIPTION:</h2>
+<p>The module <em>v.in.pygbif</em> is a wrapper around the 
+<a href=http://pygbif.readthedocs.io/en/latest/index.html>pygbif</a> package. 
+Through pygbif, it allows to download data from the Global Biodiversity 
+Information Facility (<a href=www.gbif.org>GBIF</a>) using different search / 
+filter criteria.</p>
+<p>The point data is downloaded and projected into the current location. By default 
+import is limited to the current computational region in order to avoid 
+possible projection errors, e.g. when projecting global data into UTM locations. 
+However, in lat/lon location this limitation can be skiped using the <b><em>-r</em></b>
+flag.</p>
+<p>Terminology in v.in.pygbif is oriented on the <em>Darwin Core</em> standard:
+<a href=http://rs.tdwg.org/dwc/> http://rs.tdwg.org/dwc/</a>.</p>
+</div>
+
+<div id="examples">
+
+<h2>EXAMPLES:</h2>
+<div class="code"><pre>
+# Check matching taxon names and alternatives in GBIF:
+v.in.pygbif species="Poa,Plantago" rank=genus  -p
+
+# Get number of occurrences for two geni:
+v.in.pygbif species="Poa,Plantago" rank=genus  -o
+
+# Get number of occurrences for two species:
+v.in.pygbif species="Poa pratensis,Plantago media" rank=species  -o
+
+# Fetch occurrences for two species into a map for each species:
+v.in.pygbif species="Poa pratensis,Plantago media" rank=species output=gbif -i
+
+</pre></div>
+</div>
+
+<div id="seealso">
+
+<h2>SEE ALSO:</h2>
+<a href="v.in.gbif.html">v.in.gbif</a>
+</div>
+
+<div id="references">
+
+<h2>REFERENCES:</h2>
+<a href=http://pygbif.readthedocs.io/en/latest/index.html>
+http://pygbif.readthedocs.io/en/latest/index.html</a><br>
+<a href=http://www.gbif.org>
+http://www.gbif.org</a><br>
+<a href=http://www.gbif.org/developer/summary>
+http://www.gbif.org/developer/summary</a>
+</div>
+
+<div id="author">
+
+<h2>AUTHOR:</h2>
+Stefan Blumentrath, Norwegian Institute for Nature Research, Oslo, Norway
+</div>


Property changes on: grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.html
___________________________________________________________________
Added: svn:mime-type
   + text/html
Added: svn:keywords
   + Author Date Id
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.py
===================================================================
--- grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.py	2016-08-29 08:34:19 UTC (rev 69294)
@@ -0,0 +1,606 @@
+#!/usr/bin/env python
+
+"""
+MODULE:    v.in.pygbif
+
+AUTHOR(S): Stefan Blumentrath < stefan.blumentrath AT nina.no>
+           Helmut Kudrnovsky <alectoria AT gmx at>
+
+PURPOSE:   Search and import GBIF species distribution data directly from
+           GBIF API using pygbif
+
+COPYRIGHT: (C) 2016 by the GRASS Development Team
+
+           This program is free software under the GNU General Public
+           License (>=v2). Read the file COPYING that comes with GRASS
+           for details.
+"""
+
+"""
+To Dos:
+- use proper cleanup routine, esp if using csv + vrt (copy from other modules)
+- handle layers in mask input
+"""
+
+#%module
+#% description: Search and import GBIF species distribution data
+#% keyword: vector
+#% keyword: geometry
+#%end
+
+#%option G_OPT_V_OUTPUT
+#% key: output
+#% description: Name of resulting vector map with species occurrences
+#% required : yes
+#%end
+
+#%option
+#% key: species
+#% description: Comma separated list of species names or keys to fetch data for
+#% required : yes
+#%end
+
+#%option G_OPT_V_INPUT
+#% key: mask
+#% description: Vector map that delimits region of interest
+#% guisection: Spatial filter
+#% required: no
+#%end
+
+#%option
+#% key: date_from
+#% type: string
+#% description: Lower bound of acceptable dates (format: yyyy, yyyy-MM, yyyy-MM-dd, or MM-dd)
+#% guisection: Temporal filter
+#% required: no
+#%end
+
+#%option
+#% key: date_to
+#% type: string
+#% description:  Upper bound of acceptable dates (format: yyyy, yyyy-MM, yyyy-MM-dd, or MM-dd)
+#% guisection: Temporal filter
+#% required: no
+#%end
+
+# Import will allways be limited to current region except for latlon locations
+#%flag
+#% key: r
+#% description: Do not limit import to current region (works only in lat/lon)
+#% guisection: Spatial filter
+#%end
+
+#%flag
+#% key: p
+#% description: Print result from matching species names and exit
+#% suppress_required: yes
+#%end
+
+#%flag
+#% key: i
+#% description: Produce individual map for each species
+#%end
+
+#%flag
+#% key: g
+#% description: Print result from matching species names in shell script style and exit
+#% suppress_required: yes
+#%end
+
+#%flag
+#% key: o
+#% description: Print number of matching occurrences per species and exit
+#% suppress_required: yes
+#%end
+
+#%option
+#% key: basisofrecord
+#% type: string
+#% description: Accepted basis of records
+#% guisection: Context filter
+#% required: no
+#% multiple: no
+#% options: ALL,FOSSIL_SPECIMEN,HUMAN_OBSERVATION,LITERATURE,LIVING_SPECIMEN,MACHINE_OBSERVATION,OBSERVATION,PRESERVED_SPECIMEN,UNKNOWN
+#% answer: ALL
+#%end
+
+#%option
+#% key: rank
+#% type: string
+#% description: Rank of the taxon to search for
+#% guisection: Context filter
+#% required: yes
+#% multiple: no
+#% options: class,cultivar,cultivar_group,domain,family,form,genus,informal,infrageneric_name,infraorder,infraspecific_name,infrasubspecific_name,kingdom,order,phylum,section,series,species,strain,subclass,subfamily,subform,subgenus,subkingdom,suborder,subphylum,subsection,subseries,subspecies,subtribe,subvariety,superclass,superfamily,superorder,superphylum,suprageneric_name,tribe,unranked,variety
+#% answer: species
+#%end
+
+#%option
+#% key: recordedby
+#% type: string
+#% description: The person who recorded the occurrence.
+#% guisection: Context filter
+#%end
+
+#%option
+#% key: institutioncode
+#% type: string
+#% description: An identifier of any form assigned by the source to identify the institution the record belongs to.
+#% guisection: Context filter
+#%end
+
+#%option
+#% key: country
+#% type: string
+#% description: The 2-letter country code (as per ISO-3166-1) of the country in which the occurrence was recorded
+#% guisection: Spatial filter
+#%end
+
+#%option
+#% key: continent
+#% type: string
+#% description: The continent in which the occurrence was recorded
+#% guisection: Spatial filter
+#% options: africa, antarctica, asia, europe, north_america, oceania, south_america
+#%end
+
+#%flag
+#% key: n
+#% description: Do not limit search to records with coordinates
+#% guisection: Spatial filter
+#%end
+
+#%flag
+#% key: s
+#% description: Do also import occurrences with spatial issues
+#% guisection: Spatial filter
+#%end
+
+import sys
+import os
+import math
+from osgeo import ogr
+from osgeo import osr
+import grass.script as grass
+from grass.pygrass.vector import Vector
+from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector.geometry import Point
+from dateutil.parser import parse
+
+if not os.environ.has_key("GISBASE"):
+    grass.message("You must be in GRASS GIS to run this program.")
+    sys.exit(1)
+
+try:
+    from pygbif import occurrences
+    from pygbif import species
+except ImportError:
+    grass.fatal(_("Cannot import pygbif (https://github.com/sckott/pygbif)"
+                  " library."
+                  " Please install it (pip install pygbif)"
+                  " or ensure that it is on path"
+                  " (use PYTHONPATH variable)."))
+
+
+def main():
+
+    # Parse input options
+    output = options['output']
+    mask = options['mask']
+    species_maps = flags['i']
+    no_region_limit = flags['r']
+    print_species = flags['p']
+    print_species_shell = flags['g']
+    print_occ_number = flags['o']
+    allow_no_geom = flags['n']
+    hasGeoIssue = flags['s']
+    splist = options['species'].split(',')
+    institutionCode = options['institutioncode']
+    basisofrecord = options['basisofrecord']
+    recordedby = options['recordedby'].split(',')
+    date_from = options['date_from']
+    date_to = options['date_to']
+    country = options['country']
+    continent = options['continent']
+    rank = options['rank']
+
+    # Define static variable
+    # Number of occurrences to fetch in one request
+    chunk_size = 300
+    # lat/lon proj string
+    latlon = '+proj=longlat +no_defs +a=6378137 +rf=298.257223563 +towgs84=0.000,0.000,0.000'
+    # List attributes available in Darwin Core
+    # not all attributes are returned in each request
+    # to avoid key errors when accessing the dictionary returned by pygbif
+    # presence of DWC keys in the returned dictionary is checked using this list
+    # The number of keys in this list has to be equal to the number of columns
+    # in the attribute table and the attributes written for each occurrence
+    dwc_keys = ['key', 'taxonRank', 'taxonKey', 'taxonID', 'scientificName',
+                'species', 'speciesKey', 'genericName', 'genus', 'genusKey',
+                'family', 'familyKey', 'order', 'orderKey', 'class',
+                'classKey', 'phylum', 'phylumKey', 'kingdom', 'kingdomKey',
+                'eventDate', 'verbatimEventDate', 'startDayOfYear',
+                'endDayOfYear', 'year', 'month', 'day', 'occurrenceID',
+                'occurrenceStatus', 'occurrenceRemarks', 'Habitat',
+                'basisOfRecord', 'preparations', 'sex', 'type', 'locality',
+                'verbatimLocality', 'decimalLongitude', 'decimalLatitude',
+                'geodeticDatum', 'higerGeography', 'continent', 'country',
+                'countryCode', 'stateProvince', 'gbifID', 'protocol',
+                'identifier', 'recordedBy', 'identificationID', 'identifiers',
+                'dateIdentified', 'modified', 'institutionCode',
+                'lastInterpreted', 'lastParsed', 'references', 'relations',
+                'catalogNumber', 'occurrenceDetails', 'datasetKey',
+                'datasetName', 'collectionCode', 'rights', 'rightsHolder',
+                'license', 'publishingOrgKey', 'publishingCountry',
+                'lastCrawled', 'specificEpithet', 'facts', 'issues',
+                'extensions', 'language']
+    # Deinfe columns for attribute table
+    cols = [(u'cat',       'INTEGER PRIMARY KEY'),
+            (u'g_key',       'integer'),
+            (u'g_taxonrank',       'varchar(50)'),
+            (u'g_taxonkey',       'integer'),
+            (u'g_taxonid',       'varchar(50)'),
+            (u'g_scientificname',       'varchar(255)'),
+            (u'g_species',       'varchar(255)'),
+            (u'g_specieskey',       'integer'),
+            (u'g_genericname',       'varchar(255)'),
+            (u'g_genus',       'varchar(50)'),
+            (u'g_genuskey',       'integer'),
+            (u'g_family',       'varchar(50)'),
+            (u'g_familykey',       'integer'),
+            (u'g_order',       'varchar(50)'),
+            (u'g_orderkey',       'integer'),
+            (u'g_class',       'varchar(50)'),
+            (u'g_classkey',       'integer'),
+            (u'g_phylum',       'varchar(50)'),
+            (u'g_phylumkey',       'integer'),
+            (u'g_kingdom',       'varchar(50)'),
+            (u'g_kingdomkey',       'integer'),
+            (u'g_eventdate',       'text'),
+            (u'g_verbatimeventdate',       'varchar(50)'),
+            (u'g_startDayOfYear',       'integer'),
+            (u'g_endDayOfYear',       'integer'),
+            (u'g_year',       'integer'),
+            (u'g_month',       'integer'),
+            (u'g_day',       'integer'),
+            (u'g_occurrenceid',       'varchar(255)'),
+            (u'g_occurrenceStatus',       'varchar(50)'),
+            (u'g_occurrenceRemarks',       'varchar(50)'),
+            (u'g_Habitat',       'varchar(50)'),
+            (u'g_basisofrecord',       'varchar(50)'),
+            (u'g_preparations',       'varchar(50)'),
+            (u'g_sex',       'varchar(50)'),
+            (u'g_type',       'varchar(50)'),
+            (u'g_locality',       'varchar(255)'),
+            (u'g_verbatimlocality',       'varchar(255)'),
+            (u'g_decimallongitude',       'double precision'),
+            (u'g_decimallatitude',       'double precision'),
+            (u'g_geodeticdatum',       'varchar(50)'),
+            (u'g_higerGeography',       'varchar(255)'),
+            (u'g_continent',       'varchar(50)'),
+            (u'g_country',       'varchar(50)'),
+            (u'g_countryCode',       'varchar(50)'),
+            (u'g_stateProvince',       'varchar(50)'),
+            (u'g_gbifid',       'varchar(255)'),
+            (u'g_protocol',       'varchar(255)'),
+            (u'g_identifier',       'varchar(50)'),
+            (u'g_recordedby',       'varchar(255)'),
+            (u'g_identificationid',       'varchar(255)'),
+            (u'g_identifiers',       'text'),
+            (u'g_dateidentified',       'text'),
+            (u'g_modified',       'text'),
+            (u'g_institutioncode',       'varchar(50)'),
+            (u'g_lastinterpreted',       'text'),
+            (u'g_lastparsed',       'text'),
+            (u'g_references',       'varchar(255)'),
+            (u'g_relations',       'text'),
+            (u'g_catalognumber',       'varchar(50)'),
+            (u'g_occurrencedetails',       'text'),
+            (u'g_datasetkey',       'varchar(50)'),
+            (u'g_datasetname',       'varchar(255)'),
+            (u'g_collectioncode',       'varchar(50)'),
+            (u'g_rights',       'varchar(255)'),
+            (u'g_rightsholder',       'varchar(255)'),
+            (u'g_license',       'varchar(50)'),
+            (u'g_publishingorgkey',       'varchar(50)'),
+            (u'g_publishingcountry',       'varchar(50)'),
+            (u'g_lastcrawled',       'text'),
+            (u'g_specificepithet',       'varchar(50)'),
+            (u'g_facts',       'text'),
+            (u'g_issues',       'text'),
+            (u'g_extensions',       'text'),
+            (u'g_language',       'varchar(50)')]
+
+    # Set temporal filter if requested by user
+    # Initialize eventDate filter
+    eventDate = None
+    # Check if date from is compatible (ISO compliant)
+    if date_from:
+        try:
+            parse(date_from)
+        except:
+            grass.fatal("Invalid invalid start date provided")
+
+        if date_from and not date_to:
+            eventDate = '{}'.format(date_from)
+    # Check if date to is compatible (ISO compliant)
+    if date_to:
+        try:
+            parse(date_to)
+        except:
+            grass.fatal("Invalid invalid end date provided")
+        # Check if date to is after date_from
+        if parse(date_from) < parse(date_to):
+            eventDate = '{},{}'.format(date_from, date_to)
+        else:
+            grass.fatal("Invalid date range: End date has to be after start date!")
+    # Set filter on basisOfRecord if requested by user
+    if basisofrecord == 'ALL':
+        basisOfRecord = None
+    else:
+        basisOfRecord = basisofrecord
+    # Allow also occurrences with spatial issues if requested by user
+    hasGeospatialIssue = False
+    if hasGeoIssue:
+        hasGeospatialIssue = True
+    # Allow also occurrences without coordinates if requested by user
+    hasCoordinate = True
+    if allow_no_geom:
+        hasCoordinate = False
+
+    # Set reporjection parameters
+    # Set target projection of current LOCATION
+    target = osr.SpatialReference()
+    target.ImportFromProj4(grass.read_command('g.proj', flags='fj'))
+    if target == 'XY location (unprojected)':
+        grass.fatal("Sorry, XY locations are not supported!")
+
+    # Set source projection from GBIF
+    source = osr.SpatialReference()
+    source.ImportFromEPSG(4326)
+    if target != source:
+        transform = osr.CoordinateTransformation(source, target)
+        reverse_transform = osr.CoordinateTransformation(target, source)
+
+    # Generate WKT polygon to use for spatial filtering if requested
+    if mask:
+        if len(mask.split('@')) == 2:
+            m = VectorTopo(mask.split('@')[0], mapset=mask.split('@')[1])
+        else:
+            m = VectorTopo(mask)
+        if not m.exist():
+            grass.fatal('Could not find vector map <{}>'.format(mask))
+        m.open('r')
+        if not m.is_open():
+            grass.fatal('Could not open vector map <{}>'.format(mask))
+
+        # Use map Bbox as spatial filter if map contains <> 1 area
+        if m.number_of('areas') == 1:
+            region_pol = str(m.read(1)).replace('LINESTRING', 'POLYGON(') + ')'
+        else:
+            bbox = str(m.bbox()).replace('Bbox(', '').replace(' ', '').rstrip(')').split(',')
+            region_pol = 'POLYGON(({0} {1}, {0} {3}, {2} {3}, {2} {1}, {0} {1}))'.format(bbox[2],
+                         bbox[0], bbox[3], bbox[1])
+        m.close()
+    else:
+        # Do not limit import spatially if LOCATION is able to take global data
+        if no_region_limit:
+            if target != latlon:
+                grass.fatal('Import of data outside the current region is'
+                            'only supported in an WGS84 location!')
+            pol = None
+        else:
+            # Limit import spatially to current region
+            # if LOCATION is !NOT! able to take global data
+            # to avoid pprojection ERRORS
+            region = grass.parse_command('g.region', flags='g')
+            region_pol = 'POLYGON(({0} {1}, {0} {3}, {2} {3}, {2} {1}, {0} {1}))'.format(region['e'],
+                         region['n'], region['w'], region['s'])
+
+    # Do not reproject in latlon LOCATIONS
+    if target != source:
+        pol = ogr.CreateGeometryFromWkt(region_pol)
+        pol.Transform(reverse_transform)
+        pol = pol.ExportToWkt()
+    else:
+        pol = region_pol
+
+    # Create output map if not output maps for each species are requested
+    if not species_maps and not print_species and not print_species_shell and not print_occ_number:
+        mapname = output
+        new = Vector(mapname)
+        new.open('w', tab_name=mapname, tab_cols=cols)
+        cat = 1
+
+    # Import data for each species
+    for s in splist:
+        # Get the taxon key if not the taxon key is provided as input
+        try:
+            key = int(s)
+        except:
+            try:
+                species_match = species.name_backbone(s, rank=rank,
+                                                      strict=False,
+                                                      verbose=True)
+                key = species_match['usageKey']
+            except:
+                grass.error('Data request for taxon {} faild. Are you online?'.format(s))
+                continue
+
+        # Return matching taxon and alternatives and exit
+        if print_species:
+            print 'Matching taxon for {} is:'.format(s)
+            print species_match['scientificName'] + ' ' + species_match['status']
+            if 'alternatives' in species_match.keys():
+                print 'Alternative matches might be:'.format(s)
+                for m in species_match['alternatives']:
+                    print m['scientificName'] + ' ' + m['status']
+            else:
+                print 'No alternatives found for the given taxon'
+            continue
+        if print_species_shell:
+            for m in species_match['alternatives']:
+                print m['scientificName'] + ' ' + m['status']
+            continue
+        try:
+            returns_n = occurrences.search(taxonKey=key,
+                                           hasGeospatialIssue=hasGeospatialIssue,
+                                           hasCoordinate=hasCoordinate,
+                                           institutionCode=institutionCode,
+                                           basisOfRecord=basisOfRecord,
+                                           recordedBy=recordedby,
+                                           eventDate=eventDate,
+                                           continent=continent,
+                                           country=country,
+                                           geometry=pol,
+                                           limit=1)['count']
+        except:
+            grass.error('Data request for taxon {} faild. Are you online?'.format(s))
+            returns_n = 0
+
+        # Exit if search does not give a return
+        # Print only number of returns for the given search and exit
+        if print_occ_number:
+            grass.message('Found {0} occurrences for taxon {1}...'.format(returns_n, s))
+            continue
+        elif returns_n <= 0:
+            grass.warning('No occurrences for current search for taxon {0}...'.format(s))
+            continue
+
+        # Get the number of chunks to download
+        chunks = int(math.ceil(returns_n / float(chunk_size)))
+        grass.verbose('Downloading {0} occurrences for taxon {1}...'.format(returns_n, s))
+
+        # Create a map for each species if requested using map name as suffix
+        if species_maps:
+            mapname = '{}_{}'.format(s.replace(' ', '_'), output)
+
+            new = Vector(mapname)
+            new.open('w', tab_name=mapname, tab_cols=cols)
+            cat = 1
+
+        # Download the data from GBIF
+        for c in range(chunks):
+            returns = occurrences.search(taxonKey=key,
+                                         hasGeospatialIssue=hasGeospatialIssue,
+                                         hasCoordinate=hasCoordinate,
+                                         institutionCode=institutionCode,
+                                         basisOfRecord=basisOfRecord,
+                                         recordedBy=recordedby,
+                                         eventDate=eventDate,
+                                         continent=continent,
+                                         country=country,
+                                         geometry=pol,
+                                         limit=chunk_size,
+                                         offset=c * chunk_size)
+
+            # Write the returned data to map and attribute table
+            for res in returns['results']:
+                if source != target:
+                    point = ogr.CreateGeometryFromWkt('POINT ({} {})'.format(res['decimalLongitude'], res['decimalLatitude']))
+                    point.Transform(transform)
+                    x = point.GetX()
+                    y = point.GetY()
+                else:
+                    x = res['decimalLatitude']
+                    x = res['decimalLongitude']
+
+                point = Point(x, y)
+
+                for k in dwc_keys:
+                    if k not in res.keys():
+                        res.update({k: 1})
+
+                new.write(point, cat=cat, attrs=(
+                          res['key'],
+                          res['taxonRank'],
+                          res['taxonKey'],
+                          res['taxonID'],
+                          res['scientificName'],
+                          res['species'],
+                          res['speciesKey'],
+                          res['genericName'],
+                          res['genus'],
+                          res['genusKey'],
+                          res['family'],
+                          res['familyKey'],
+                          res['order'],
+                          res['orderKey'],
+                          res['class'],
+                          res['classKey'],
+                          res['phylum'],
+                          res['phylumKey'],
+                          res['kingdom'],
+                          res['kingdomKey'],
+                          str(res['eventDate']),
+                          str(res['verbatimEventDate']),
+                          res['startDayOfYear'],
+                          res['endDayOfYear'],
+                          res['year'],
+                          res['month'],
+                          res['day'],
+                          res['occurrenceID'],
+                          res['occurrenceStatus'],
+                          res['occurrenceRemarks'],
+                          res['Habitat'],
+                          res['basisOfRecord'],
+                          res['preparations'],
+                          res['sex'],
+                          res['type'],
+                          res['locality'],
+                          res['verbatimLocality'],
+                          res['decimalLongitude'],
+                          res['decimalLatitude'],
+                          res['geodeticDatum'],
+                          res['higerGeography'],
+                          res['continent'],
+                          res['country'],
+                          res['countryCode'],
+                          res['stateProvince'],
+                          res['gbifID'],
+                          res['protocol'],
+                          res['identifier'],
+                          res['recordedBy'],
+                          res['identificationID'],
+                          ','.join(res['identifiers']),
+                          str(res['dateIdentified']),
+                          str(res['modified']),
+                          res['institutionCode'],
+                          str(res['lastInterpreted']),
+                          str(res['lastParsed']),
+                          res['references'],
+                          ','.join(res['relations']),
+                          res['catalogNumber'],
+                          str(res['occurrenceDetails']),
+                          res['datasetKey'],
+                          res['datasetName'],
+                          res['collectionCode'],
+                          res['rights'],
+                          res['rightsHolder'],
+                          res['license'],
+                          res['publishingOrgKey'],
+                          res['publishingCountry'],
+                          str(res['lastCrawled']),
+                          res['specificEpithet'],
+                          ','.join(res['facts']),
+                          ','.join(res['issues']),
+                          ','.join(res['extensions']),
+                          res['language'],))
+
+                cat = cat + 1
+
+        # Close the current map if a map for each species is requested
+        if species_maps:
+            new.table.conn.commit()
+            new.close
+
+    # Close the output map if not a map for each species is requested
+    if not species_maps and not print_species and not print_species_shell and not print_occ_number:
+        new.table.conn.commit()
+        new.close
+
+# Run the module
+# ToDo: Add an atexit procedure which closes and removes the current map
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())


Property changes on: grass-addons/grass7/vector/v.in.pygbif/v.in.pygbif.py
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native



More information about the grass-commit mailing list