lab_weather/geocoder/ottawa_parcel.py

158 lines
4.4 KiB
Python

#!/usr/bin/python
# coding: utf8
from __future__ import absolute_import
import logging
from geocoder.base import OneResult, MultipleResultsQuery
class OttawaParcelIdResult(OneResult):
@property
def ok(self):
return bool(self.address_id)
@property
def address_id(self):
return self.raw.get('attributes', {}).get('PI Municipal Address ID')
class OttawaParcelIdQuery(MultipleResultsQuery):
# XXX 8 sept 2017: Service still available ? not documented and returning 403
_URL = 'http://maps.ottawa.ca/arcgis/rest/services/Property_Parcels/MapServer/find'
_RESULT_CLASS = OttawaParcelIdResult
_KEY_MANDATORY = False
def _build_params(self, location, provider_key, **kwargs):
return {
'searchText': location,
'layers': 0,
'f': 'json',
'sr': 4326,
}
def _adapt_results(self, json_response):
return json_response.get('results', [])
class OttawaParcelResult(OneResult):
@property
def ok(self):
return bool(self.geometry)
@property
def length(self):
"""Length in Feet (f)"""
length = self.parse['attributes'].get('Shape_Length')
if length:
return round(float(length))
@property
def area(self):
"""Square Foot Area (sqft)"""
area = self.parse['attributes'].get('Shape_Area')
if area:
return round(float(area) * 10.76391)
@property
def frontage(self):
"""Length in Feet (f)"""
if self.length and self.area:
return round(self.area / self.length)
@property
def municipality(self):
return self._clean(self.parse['attributes'].get('MUNICIPALITY_NAME'))
@property
def housenumber(self):
return self._clean(self.parse['attributes'].get('ADDRESS_NUMBER'))
@property
def suffix(self):
return self._clean(self.parse['attributes'].get('SUFFIX'))
@property
def public_land(self):
return self._clean(self.parse['attributes'].get('PUBLICLAND'))
@property
def street(self):
return self._clean(self.parse['attributes'].get('ROAD_NAME'))
@property
def legal_unit(self):
return self._clean(self.parse['attributes'].get('LEGAL_UNIT'))
@property
def pin(self):
return self._clean(self.parse['attributes'].get('PIN_NUMBER'))
@property
def geometry(self):
return self.parse['geometry']
@property
def postal(self):
return self._clean(self.parse['attributes'].get('POSTAL_CODE'))
def _clean(self, item):
if item:
return item.strip()
class OttawaParcelQuery(MultipleResultsQuery):
"""
Ottawa ArcGIS REST Services
===========================
Geocoding is the process of assigning a location, usually in the form of
coordinate values (points), to an address by comparing the descriptive
location elements in the address to those present in the reference
material. Addresses come in many forms, ranging from the common address
format of a house number followed by the street name and succeeding
information to other location descriptions such as postal zone or census
tract. An address includes any type of information that distinguishes
a place.
API Reference
-------------
http://maps.ottawa.ca/ArcGIS/rest/services/
compositeLocator/GeocodeServer/findAddressCandidates
"""
provider = 'ottawa'
method = 'parcel'
_URL = 'http://maps.ottawa.ca/arcgis/rest/services/Property_Parcels/MapServer/find'
_RESULT_CLASS = OttawaParcelResult
_KEY_MANDATORY = False
def _build_params(self, location, provider_key, **kwargs):
ids = OttawaParcelIdQuery(location)
if not ids.address_id:
raise ValueError("Could not get any Id for given location")
return {
'searchText': ids.address_id,
'layers': 2,
'f': 'json',
'sr': 4326,
}
def _adapt_results(self, json_response):
return json_response.get('results', [])
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
area = 2123
length = 100
frontage = 21
location = '169 Carillon'
g = OttawaParcelQuery(location, timeout=10.0)
print('%s: %i x %i = %i' % (location, g.frontage, g.length, g.area))
print('453 Booth: %i x %i = %i' % (frontage, length, area))
print('%i x %i = %i' % (g.frontage - frontage, g.length - length, g.area - area))