Source code for geonum.topodataaccess

# -*- coding: utf-8 -*-
#
# Geonum is a Python library for geographical calculations in 3D
# Copyright (C) 2017 Jonas Gliss (jonasgliss@gmail.com)
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License a
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
Access and handling of topographic data
"""
import numpy as np
import os

from geonum.exceptions import InvalidTopoMode, TopoAccessError
from geonum.topoaccessbase import SRTMAccess, Etopo1Access

[docs] class TopoDataAccess(object): """Factory class for accessing topographic data This is a high-level factory class which handles the access of topography data. Registered topographic datasets can be found in :attr:`REGISTERED` Default access mode is SRTM (topographic dataset from NASA `Shuttle Radar Topography Mission <https://www2.jpl.nasa.gov/srtm/>`__). Example ------- >>> acc = TopoDataAccess(mode='srtm') >>> topo_data = acc.get_data(lat0=5, lon0=30, lat1=15, lon1=40) Note ---- For developers: the registered access classes (such as :class:`SRTMAccess`) should be based on (or follow the API of) template base class :class:`TopoAccessBase`. Attributes ---------- mode : str current access mode (string specifying which topographic dataset is supposed to be used for access). local_path : str local path to etopo data (only relevant for etopo1 mode) Parameters ---------- mode : str one of the supported data access types (cf. keys of :attr:`REGISTERED`) local_path : str local path to etopo data (only relevant for etopo1 mode) """ #: supported access modes (topographic datasets) REGISTERED = dict(srtm = SRTMAccess, etopo1 = Etopo1Access) DEFAULT_MODE = 'srtm' def __init__(self, mode=None, local_path=None): if mode is None: mode = self.DEFAULT_MODE #mode and data access variables if not mode in self.REGISTERED: raise InvalidTopoMode(mode) self.mode = mode self.local_path = local_path @property def modes(self): """List of supported topographic datasets""" return list(self.REGISTERED.keys()) @property def supported(self): """List of supported datasets (wrapper for :attr:`modes`)""" return self.modes def __deepcopy__(self, memo): return TopoDataAccess(self.mode, self.local_path)
[docs] def get_data(self, lat0, lon0, lat1=None, lon1=None, mode=None, local_path=None, check_allnan=True, **access_opts): """Retrieve data from topography file Parameters ---------- lat0 : float start longitude for data extraction lon0 : float start latitude for data extraction lat1 : float stop longitude for data extraction (default: None). If None only data around lon0, lat0 will be extracted. lon1 : float stop latitude for data extraction (default: None). If None only data around lon0, lat0 will be extracted mode : str, optional mode specifying the topographic dataset that is supposed to be used local_path : str, optional local path where topography data is stored (can be dictionary or filepath, is passed to corresponding access class and handled as implemented there) check_allnan : bool if True and all retrieved values are NaN, then an error is thrown **access_opts additional access options that may be specific for the mode specified (e.g. search_database in case of etopo1) Returns ------- TopoData object containing the data Raises ------ TopoAccessError if access fails """ if mode is not None: if not mode in self.REGISTERED: raise InvalidTopoMode(mode) self.mode = mode if local_path is not None and os.path.exists(local_path): self.local_path=local_path access = self.REGISTERED[self.mode](local_path=self.local_path, **access_opts) data = access.get_data(lat0, lon0, lat1, lon1) if check_allnan and np.isnan(data.data).all(): raise TopoAccessError('Failed to retrieve TopoData ({}): ' 'all values are NaN'.format(self.mode)) return data