#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright 2018 Open Energy Efficiency, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import json
from .connections import metadata_db_connection_proxy
from .exceptions import UnrecognizedUSAFIDError, UnrecognizedZCTAError
from .utils import lazy_property
from .validation import valid_zcta_or_raise
__all__ = ("get_lat_long_climate_zones", "get_zcta_metadata", "zcta_to_lat_long")
class CachedData(object):
@lazy_property
def climate_zone_geometry(self):
try:
from shapely.geometry import shape
except ImportError: # pragma: no cover
raise ImportError(
"Matching by lat/lng within climate zone requires shapely"
)
conn = metadata_db_connection_proxy.get_connection()
cur = conn.cursor()
cur.execute(
"""
select
iecc_climate_zone, geometry
from
iecc_climate_zone_metadata
"""
)
iecc_climate_zones = [
(cz_id, shape(json.loads(geometry))) for (cz_id, geometry) in cur.fetchall()
]
cur.execute(
"""
select
iecc_moisture_regime, geometry
from
iecc_moisture_regime_metadata
"""
)
iecc_moisture_regimes = [
(cz_id, shape(json.loads(geometry))) for (cz_id, geometry) in cur.fetchall()
]
cur.execute(
"""
select
ba_climate_zone, geometry
from
ba_climate_zone_metadata
"""
)
ba_climate_zones = [
(cz_id, shape(json.loads(geometry))) for (cz_id, geometry) in cur.fetchall()
]
cur.execute(
"""
select
ca_climate_zone, geometry
from
ca_climate_zone_metadata
"""
)
ca_climate_zones = [
(cz_id, shape(json.loads(geometry))) for (cz_id, geometry) in cur.fetchall()
]
return (
iecc_climate_zones,
iecc_moisture_regimes,
ba_climate_zones,
ca_climate_zones,
)
cached_data = CachedData()
[docs]def get_lat_long_climate_zones(latitude, longitude):
""" Get climate zones that contain lat/long coordinates.
Parameters
----------
latitude : float
Latitude of point.
longitude : float
Longitude of point.
Returns
-------
climate_zones: dict of str
Region ids for each climate zone type.
"""
try:
from shapely.geometry import Point
except ImportError: # pragma: no cover
raise ImportError("Finding climate zone of lat/long points requires shapely.")
(
iecc_climate_zones,
iecc_moisture_regimes,
ba_climate_zones,
ca_climate_zones,
) = cached_data.climate_zone_geometry
point = Point(longitude, latitude) # x,y
climate_zones = {}
for iecc_climate_zone, shape in iecc_climate_zones:
if shape.contains(point):
climate_zones["iecc_climate_zone"] = iecc_climate_zone
break
else:
climate_zones["iecc_climate_zone"] = None
for iecc_moisture_regime, shape in iecc_moisture_regimes:
if shape.contains(point):
climate_zones["iecc_moisture_regime"] = iecc_moisture_regime
break
else:
climate_zones["iecc_moisture_regime"] = None
for ba_climate_zone, shape in ba_climate_zones:
if shape.contains(point):
climate_zones["ba_climate_zone"] = ba_climate_zone
break
else:
climate_zones["ba_climate_zone"] = None
for ca_climate_zone, shape in ca_climate_zones:
if shape.contains(point):
climate_zones["ca_climate_zone"] = ca_climate_zone
break
else:
climate_zones["ca_climate_zone"] = None
return climate_zones
[docs]def zcta_to_lat_long(zcta):
"""Get location of ZCTA centroid
Retrieves latitude and longitude of centroid of ZCTA
to use for matching with weather station.
Parameters
----------
zcta : str
ID of the target ZCTA.
Returns
-------
latitude : float
Latitude of centroid of ZCTA.
longitude : float
Target Longitude of centroid of ZCTA.
"""
valid_zcta_or_raise(zcta)
conn = metadata_db_connection_proxy.get_connection()
cur = conn.cursor()
cur.execute(
"""
select
latitude
, longitude
from
zcta_metadata
where
zcta_id = ?
""",
(zcta,),
)
# match existence checked in validate_zcta_or_raise(zcta)
latitude, longitude = cur.fetchone()
return float(latitude), float(longitude)