def test_map_bounds(): locations = [ # North Pole [90, -180], [90, 0], [90, 180], [90, 179], # Equator [0, -180], [0, 0], [0, 180], # South Pole [-90, -180], [-90, 0], [-90, 180] ] invalid_locations = [ [-90.1, 0], [90.1, 0], [0, -180.1], [0, 180.1], [0, 360], ] gebco = Gebco() for location in locations: assert gebco.get_height(*location)['altitude_m'] != gebco.NODATA # out of bounds for location in invalid_locations: with pytest.raises(ValueError): gebco.get_height(*location)
def __init__(self): self.wb = WaterBodies() self.srtm = Srtm1() self.gebco = Gebco() self.dgm = Dgm200() self.terr50 = Terrain50() self.sources = [self.terr50, self.dgm, self.gebco]
def test_check_for_metadata_get_min_height(): gebco = Gebco() data = gebco.get_min_height(51, 7, 52, 8) assert data['h_min'] != gebco.NODATA assert isinstance(data['h_min'], float) assert isinstance(data['location_min'], list) assert data['counter_min'] >= 0 assert isinstance(data['source'], str) assert isinstance(data['attributions'], list)
def test_check_for_metadata_get_height(): gebco = Gebco() for location in [[53.57, 9.98], [52.51, 13.42], [47.94, 8.3], [-41, 172]]: data = gebco.get_height(*location) assert data['altitude_m'] != gebco.NODATA assert isinstance(data['source'], str) assert isinstance(data['attributions'], list) assert data['distance_m'] >= 0 assert data['distance_m'] < 654.86 assert isinstance(data['lat_found'], float) assert isinstance(data['lon_found'], float)
class HeightInfo: attribution_name = 'height_info' NODATA = -32768 def __init__(self): self.wb = WaterBodies() self.srtm = Srtm1() self.gebco = Gebco() self.dgm = Dgm200() self.terr50 = Terrain50() self.sources = [self.terr50, self.dgm, self.gebco] def get_height(self, lat, lon): """ Get the elevation of the given location from the best available data source. :param lat: float -- latitude. :param lon: float -- longitude. :returns: dict """ wb_data = self.wb.get_data_at_position(lat, lon) wb_label = wb_data['label'] wb_attributions = wb_data['attributions'] is_ocean = wb_label == 'Ocean' dgm200_result = self.dgm.get_height(lat, lon) if dgm200_result['distance_m'] < 25 and (dgm200_result['altitude_m'] != self.dgm.NODATA) and not is_ocean: # prefer sea floor bathymetry if possible dgm200_result['wb_label'] = wb_label dgm200_result['attributions'] += wb_attributions return dgm200_result terr50_result = self.terr50.get_height(lat, lon) h_terr50 = terr50_result['altitude_m'] if h_terr50 != self.terr50.NODATA and not is_ocean or h_terr50 > 0: # prefer sea floor bathymetry if possible terr50_result['wb_label'] = wb_label terr50_result['attributions'] += wb_attributions return terr50_result srtm1_result = self.srtm.get_height(lat, lon) h_srtm1 = srtm1_result['altitude_m'] if h_srtm1 != self.srtm.NODATA and not is_ocean or h_srtm1 > 0: # prefer sea floor bathymetry if possible srtm1_result['wb_label'] = wb_label srtm1_result['attributions'] += wb_attributions return srtm1_result if dgm200_result['altitude_m'] != self.dgm.NODATA and not is_ocean: # prefer sea floor bathymetry if possible dgm200_result['wb_label'] = wb_label dgm200_result['attributions'] += wb_attributions return dgm200_result gebco_result = self.gebco.get_height(lat, lon) if gebco_result['altitude_m'] != self.gebco.NODATA: gebco_result['wb_label'] = wb_label gebco_result['attributions'] += wb_attributions return gebco_result else: return { 'altitude_m': self.NODATA, 'lat': lat, 'lon': lon, 'distance_m': 0, 'source': 'NODATA', 'wb_label': wb_label, 'attributions': wb_attributions} def get_max_height(self, lat_ll, lon_ll, lat_ur, lon_ur): if not (-90 <= lat_ll <= 90 and -180 <= lon_ll <= 180 and -90 <= lat_ur <= 90 and -180 <= lon_ur <= 180): raise ValueError('invalid coordinates ({}, {}), ({}, {})'.format( lat_ll, lon_ll, lat_ur, lon_ur)) result = { 'location_max': [], 'h_max': self.NODATA, 'counter_max': 0, 'source': self.attribution_name, 'attributions': []} # consider only correctly defined rectangle: if lat_ll > lat_ur or lon_ll > lon_ur: return result for source in self.sources: result = source.get_max_height(lat_ll, lon_ll, lat_ur, lon_ur) if result['h_max'] != source.NODATA: return result def get_min_height(self, lat_ll, lon_ll, lat_ur, lon_ur): if not (-90 <= lat_ll <= 90 and -180 <= lon_ll <= 180 and -90 <= lat_ur <= 90 and -180 <= lon_ur <= 180): raise ValueError('invalid coordinates ({}, {}), ({}, {})'.format( lat_ll, lon_ll, lat_ur, lon_ur)) result = { 'location_min': [], 'h_min': self.NODATA, 'counter_min': 0, 'source': self.attribution_name, 'attributions': []} # consider only correctly defined rectangle: if lat_ll > lat_ur or lon_ll > lon_ur: return result for source in self.sources: result = source.get_min_height(lat_ll, lon_ll, lat_ur, lon_ur) if result['h_min'] != source.NODATA: return result def get_min_max_height(self, lat_ll, lon_ll, lat_ur, lon_ur): if not (-90 <= lat_ll <= 90 and -180 <= lon_ll <= 180 and -90 <= lat_ur <= 90 and -180 <= lon_ur <= 180): raise ValueError('invalid coordinates ({}, {}), ({}, {})'.format( lat_ll, lon_ll, lat_ur, lon_ur)) result = { 'location_max': [], 'h_max': self.NODATA, 'counter_max': 0, 'location_min': [], 'h_min': self.NODATA, 'counter_min': 0, 'source': self.attribution_name, 'attributions': []} # consider only correctly defined rectangle: if lat_ll > lat_ur or lon_ll > lon_ur: return result max_found = False min_found = False for source in self.sources: if not max_found and not min_found: _result = source.get_min_max_height(lat_ll, lon_ll, lat_ur, lon_ur) min_locations = _result['location_min'] max_locations = _result['location_max'] min_is_ocean = [ self.wb.get_data_at_position(lat, lon)['label'] == 'Ocean' for lat, lon in min_locations] max_is_ocean = [ self.wb.get_data_at_position(lat, lon)['label'] == 'Ocean' for lat, lon in max_locations] if 0 < len(min_locations) < 50 and (not any(min_is_ocean) or source.seabed_included): min_found = True _result['source_min'] = _result['source'] if 0 < len(max_locations) < 50 and (not any(max_is_ocean) or source.seabed_included): max_found = True _result['source_max'] = _result['source'] if not min_found and not max_found: continue elif not max_found: _result = source.get_max_height(lat_ll, lon_ll, lat_ur, lon_ur) max_locations = _result['location_max'] max_is_ocean = [ self.wb.get_data_at_position(lat, lon)['label'] == 'Ocean' for lat, lon in max_locations] if 0 < len(max_locations) < 50 and (not any(max_is_ocean) or source.seabed_included): max_found = True _result['source_max'] = _result['source'] else: continue elif not min_found: _result = source.get_min_height(lat_ll, lon_ll, lat_ur, lon_ur) min_locations = _result['location_min'] min_is_ocean = [ self.wb.get_data_at_position(lat, lon)['label'] == 'Ocean' for lat, lon in min_locations] if 0 < len(min_locations) < 50 and (not any(min_is_ocean) or source.seabed_included): min_found = True _result['source_min'] = _result['source'] else: continue else: break _result.pop('attributions') _result.pop('source') result.update(_result) return result
#!/usr/bin/python # -*- coding: utf-8 -*- import time import json from height_map.terr50 import Terrain50 from height_map.srtm1 import Srtm1 from height_map.dgm200 import Dgm200 from height_map.gebco import Gebco from height_map.height_info import HeightInfo dgm200 = Dgm200() terr50 = Terrain50() srtm1 = Srtm1() gebco = Gebco() height_info = HeightInfo() def get_height(lat, lon): srtm1_result = srtm1.get_height(lat, lon) terr50_result = terr50.get_height(lat, lon) dgm200_result = dgm200.get_height(lat, lon) gebco_result = gebco.get_height(lat, lon) results = {'request': {'lat': lat, 'lon': lon}} if srtm1_result['altitude_m'] != srtm1.NODATA: results['SRTM1'] = srtm1_result if terr50_result['altitude_m'] != terr50.NODATA: results['TERR50'] = terr50_result if dgm200_result['altitude_m'] != dgm200.NODATA: results['DGM200'] = dgm200_result
def test_missing_file_operation(): with pytest.raises(FileNotFoundError): Gebco(file_name='missing_file.tif') with pytest.raises(FileNotFoundError): Gebco(path='non_existent_path')
def test_content_get_height(): gebco = Gebco() # Hambach open pit assert math.isclose(gebco.get_height(50.91, 6.51)['altitude_m'], -94.83, abs_tol=16) # storage pool in Geeste assert math.isclose(gebco.get_height(52.588, 7.294)['altitude_m'], 34, abs_tol=16) # Black Forest assert math.isclose(gebco.get_height(47.94, 8.3)['altitude_m'], 927.52, abs_tol=16) # farmland in the Emsland region assert math.isclose(gebco.get_height(52.78, 7.4)['altitude_m'], 32.61, abs_tol=16) # high moor in the Emsland region assert math.isclose(gebco.get_height(52.8, 7.4)['altitude_m'], 24.64, abs_tol=16) # lowest location of this dataset in Germany assert math.isclose(gebco.get_height(50.92, 6.5)['altitude_m'], -192.2, abs_tol=16) # highest location of this dataset in the bounding box of Germany assert math.isclose(gebco.get_height(47.420833, 13.0625)['altitude_m'], 2818.2, abs_tol=16) # lowest location assert math.isclose(gebco.get_height(11.366667, 142.5875)['altitude_m'], -10952, abs_tol=16) # highest location assert math.isclose(gebco.get_height(27.9875, 86.925)['altitude_m'], 8613.2, abs_tol=16) # London, River Thames assert math.isclose(gebco.get_height(51.499, -0.122)['altitude_m'], 6.98, abs_tol=16) # London, The Serpentine assert math.isclose(gebco.get_height(51.5052, -0.1666)['altitude_m'], 20.96, abs_tol=16) # London, Round Pond assert math.isclose(gebco.get_height(51.5058, -0.1834)['altitude_m'], 28.96, abs_tol=16) # London, Hyde Park assert math.isclose(gebco.get_height(51.509, -0.163)['altitude_m'], 28.96, abs_tol=16) # London, Kensington Gardens assert math.isclose(gebco.get_height(51.507, -0.179)['altitude_m'], 25.95, abs_tol=16) # North Sea assert math.isclose(gebco.get_height(53.8, 6.9)['altitude_m'], -22.04, abs_tol=16) # Dead Sea assert math.isclose(gebco.get_height(31.52, 35.48)['altitude_m'], -415, abs_tol=16) # IJsselmeer assert math.isclose(gebco.get_height(52.74, 5.42)['altitude_m'], -4.28, abs_tol=16) # Markermeer assert math.isclose(gebco.get_height(52.54, 5.22)['altitude_m'], -3.89, abs_tol=16) # Naples harbour assert math.isclose(gebco.get_height(40.836, 14.262)['altitude_m'], -14.21, abs_tol=16) # Lake Constance assert math.isclose(gebco.get_height(47.56, 9.5)['altitude_m'], 392, abs_tol=16) # Salt Lake City assert math.isclose(gebco.get_height(40.8, -112)['altitude_m'], 1289.59, abs_tol=16) # Tokyo assert math.isclose(gebco.get_height(35.68, 139.77)['altitude_m'], 20.31, abs_tol=16)
def test_check_bounds_get_min_max_height(): gebco = Gebco() # in bounds _result = gebco.get_min_max_height(52.5, 5, 53, 5.5) assert _result['h_max'] != gebco.NODATA assert _result['h_min'] != gebco.NODATA # invalid coordinates with pytest.raises(ValueError): gebco.get_min_max_height(52.5, 5, 91, 5.5) with pytest.raises(ValueError): gebco.get_min_max_height(-91, 5, 53, 5.5) with pytest.raises(ValueError): gebco.get_min_max_height(52.5, -181, 53, 5.5) with pytest.raises(ValueError): gebco.get_min_max_height(52.5, 5, 53, 181) # incorrect rectangle _result = gebco.get_min_max_height(54.886907, 15.570925, 47.240591, 6.093066) assert _result['h_max'] == gebco.NODATA assert _result['h_min'] == gebco.NODATA # highest and lowest location in the bounding box of Germany _result = gebco.get_min_max_height(47.240591, 6.093066, 54.886907, 15.570925) assert math.isclose(_result['h_max'], 2818.2, abs_tol=16) assert math.isclose(_result['h_min'], -195.2, abs_tol=16) # highest and lowest location of the world _result = gebco.get_min_max_height(-90, -180, 90, 180) assert math.isclose(_result['h_max'], 8613.2, abs_tol=16) assert math.isclose(_result['h_min'], -10952, abs_tol=16)
def test_check_bounds_get_min_height(): gebco = Gebco() # in bounds assert gebco.get_min_height(52.5, 5, 53, 5.5)['h_min'] != gebco.NODATA # invalid coordinates with pytest.raises(ValueError): gebco.get_min_height(52.5, 5, 91, 5.5) with pytest.raises(ValueError): gebco.get_min_height(-91, 5, 53, 5.5) with pytest.raises(ValueError): gebco.get_min_height(52.5, -181, 53, 5.5) with pytest.raises(ValueError): gebco.get_min_height(52.5, 5, 53, 181) # incorrect rectangle assert gebco.get_min_height(54.886907, 15.570925, 47.240591, 6.093066)['h_min'] == gebco.NODATA # lowest location in the bounding box of Germany assert math.isclose(gebco.get_min_height(47.240591, 6.093066, 54.886907, 15.570925)['h_min'], -195.2, abs_tol=16) # lowest location of the world assert math.isclose(gebco.get_min_height(-90, -180, 90, 180)['h_min'], -10952, abs_tol=16)