Code for the geospatial quality assessment methods of the VertNet set of APIs. Author: Javier Otegui
The current base URL for the API is:
http://api-geospatial.vertnet-portal.appspot.com/geospatial
Given that it is designed to be an open service to the community, no credentials whatsoever are required. But we reserve the right to close it at any moment if we suspect there is being misuse.
This API operates on Primary Biodiversity Records, i.e., the most basic, interpretation-free pieces of information about the occurrence of an organism (taxonomic identification, or "what") in a specific place (geospatial location, or "where") and a moment in time (temporal location, or "when"). It feeds on a single record or a set of records that describe such occurrence. Specifically, the geospatial issues service works with the "what" and the "where", meaning it is more useful if such pieces of information are provided to the API.
While there is no minimum set of required values to pass to the service in order for it to work, the amount of tests to be performed depends on the information provided. One can simply call the base URL and it will return a set of empty fields. To fully leverage the potential of the API, however, a user should send a well-defined set of values. These values must conform to the DarwinCore Standard, and currently, the API works on these variables:
- decimalLatitude: Value for the Latitude in decimal degrees format (e.g. 42.332)
- decimalLongitude: Value for the Longitude in decimal degrees format (e.g. -1.833)
- countryCode: 2 character ISO code for the country
- scientificName
Caveat: while the API accepts scientific names as specified in the DarwinCore Standard, currently some tools only work if the "Genus"+"Specific Epithet" binomial is provided in this field. Thus, instead of "Puma concolor (Linnaeus, 1771)", we recommend using just "Puma concolor" in the 'scientificName' field.
When working with multiple records (see below how to do this with the POST method), the API accepts more than just these fields. One can send as many key-value pairs as he/she wants, and the API will just by-pass them. They will be presented in the output, though, so it is a good practice to include a field with any type of identification (like an occurrenceID).
The output of the API will always be a JSON document, whether it is a single-record or a multi-record assessment. Actually, the API will return the same document that was provided, with the addition of the flags
element. This new element contains the results of the geospatial and spatio-taxonomic checks the API has performed. The attributes in this flags
element are one or more of these (depending on the information provided):
hasCoordinates
: always. True if coordinates have been sent to the API. False otherwise.hasCountry
: always. True if a country value has been sent to the API. False otherwise.hasScientificName
: always. True if a scientific name has been sent to the API. False otherwise.validCoordinates
: only ifhasCoordinates
is true. True if supplied values conform to the natural limits of coordinates. False otherwise.validCountry
: only ifhasCountry
is true. True if supplied value corresponds to an existing 2-character code for a country. False otherwise.highPrecisionCoordinates
: only ifvalidCoordinates
is true. True if coordinates have at least 3 decimal figures. False otherwise.nonZeroCoordinates
: only ifvalidCoordinates
is true. False if both coordinates are 0. True otherwise.coordinatesInsideCountry
: Only ifvalidCoordinates
andvalidCountry
are true. True if coordinates fall inside the specified country. False otherwise.transposedCoordinates
: Only ifcoordinatesInsideCountry
is false. True if swapping the coordinates makes them right. False otherwise. This operation can be performed alongnegatedLatitude
andnegatedLongitude
.negatedLatitude
: Only ifcoordinatesInsideCountry
is false. True if negating the latitude makes coordinates right. False otherwise. This operation can be performed alongtransposedCoordinates
andnegatedLongitude
.negatedLongitude
: Only ifcoordinatesInsideCountry
is false. True if negating the longitude makes coordinates right. False otherwise. This operation can be performed alongtransposedCoordinates
andnegatedLatitude
.distanceToCountryInKm
: Only ifcoordinatesInsideCountry
,transposedCoordinates
,negatedLatitude
andnegatedLongitude
are false. This will show the distance to the closest point of the country boundaries, in Km.coordinatesInsideRangeMap
: Only ifhasScientificName
andvalidCoordinates
are true. True if coordinates fall inside the IUCN range map for the specified species. False otherwise.distanceToRangeMapInKm
: Only ifcoordinatesInsideRangeMap
is false. This will show the distance to the closest point of the species range map, in Km.
GET
requests can be used to assess the quality of a single record. Parameters must be passed urlencoded via the querystring. Here is an example of a working GET
request:
curl -H "Content-Type: application/json" "http://api-dev.vertnet-portal.appspot.com/geospatial?decimalLatitude=42.332&decimalLongitude=-1.833&countryCode=ES&scientificName=Puma%20concolor"
When using the API in this way, the result is the provided set of values plus the flags
element, but everything apart from the aforementioned four DarwinCore elements will be ignored, and if any of these four elements is missing, it will appear as an empty string. Here is the output of the previous example:
{
"decimalLatitude": "42.332",
"decimalLongitude": "-1.833",
"scientificName": "Puma concolor",
"countryCode": "ES",
"flags": {
"validCountry": "True",
"coordinatesInsideCountry": "True",
"distanceToRangeMapInKm": 6892.799,
"hasScientificName": "True",
"nonZeroCoordinates": "True",
"highPrecisionCoordinates": "True",
"hasCoordinates": "True",
"validCoordinates": "True",
"coordinatesInsideRangeMap": "False",
"hasCountry": "True"
}
}
More than one record can be checked in a single request by passing the records in JSON format in the body of a POST
request. All the records must be wrapped in a list. Here is an example of a working POST
request:
// body.json
[
{
"occurrenceId": 1,
"decimalLatitude": 42.388,
"decimalLongitude": -1.833,
"countryCode": "ES",
"scientificName": "Abies alba"
},
{
"occurrenceId": 2,
"decimalLongitude": -1.833,
"countryCode": "ES",
"scientificName": "Puma concolor"
},...
]
curl -H "Content-Type: application/json" -X POST -d @body.json "http://api-dev.vertnet-portal.appspot.com/geospatial"
In this case, the extra fields -- like occurrenceId
-- will not be ignored and will be part of the result.