class TestCombinedGBIF: gbif: GBIF = GBIF() mapbox: MapBox = MapBox(token=get_token()) @pytest.mark.vcr("new") @pytest.mark.parametrize( "taxon_id, tile_ids", [ ( 2493091, (( TileID(15, 16826, 10770), TileID(15, 16826, 10771), TileID(15, 16827, 10770), TileID(15, 16827, 10771), )), ), ], ) def test_gbif_mapbox_comp(self, taxon_id, tile_ids): mpta = TileArray.from_dict({x: Tile(x) for x in tile_ids}) gbta = TileArray.from_dict({x: Tile(x) for x in tile_ids}) mapbox_tiles = self.mapbox.get_tiles(mpta) gbif_tiles = self.gbif.get_tiles(taxon_id, gbta) c_tiles = mapbox_tiles._composite_layer(gbif_tiles) c_tiles.name = "gbif+mapbox" final_image = c_tiles._composite_all() final_image.save(f"gbif+mapbox-{taxon_id}-final.png")
def test_creation_constructor(self, tile_ids, images): tile_array = TileArray.from_dict( {TileID(k): Tile(TileID(k), v) for k, v in zip(tile_ids, images)}) for tid in tile_ids: assert tid in tile_array pprint(tile_array)
def test_args_kwargs_creation(self, args, kwargs, exc, result): print("a", args, "k", kwargs) if exc: print("EXCEPTION!!!!!") with pytest.raises(exc): _ = TileID(*args, **kwargs) else: n = TileID(*args, **kwargs) assert (n.z, n.x, n.y) == result
class TestTile: @pytest.mark.parametrize( "tile_ids, images, names, tile_size", [ ( [TileID(0, 0, 0)], [create_blank_image(256, "RGB")], ["test_tile_creation"], 256, ), ], ) def test_creation(self, tile_ids, images, names, tile_size): for tid, img, name in zip(tile_ids, images, names): tile = Tile(tid=tid, img=img, name=name) assert tile.tid == tid assert tile.img == img assert tile.name == name assert tile.resolution == tile_size @pytest.mark.parametrize( "test_tile, m_tile", [ ( Tile(TileID(8, 4, 2), img=create_blank_image()), mercantile.Tile(z=8, x=4, y=2), ), ( Tile(TileID(4, 10, 9), img=create_blank_image()), mercantile.Tile(z=4, x=10, y=9), ), ], ) def test_to_mercantile(self, test_tile, m_tile): assert test_tile.asmercantile == m_tile @pytest.mark.parametrize( "tile, bounds", [ ( Tile(TileID(4, 10, 9), img=create_blank_image()), LatLonBBox( left=45.0, bottom=-40.97989806962013, right=67.5, top=-21.943045533438177, ), ), ], ) def test_tile_bounds(self, tile, bounds): assert tile.bounds == bounds
def test_get_map_tile(self, taxon_id, tile_size, map_type): if map_type == "hex": gb = self.gbif.get_hex_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) elif map_type == "square": gb = self.gbif.get_square_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) # else: # gb = self.gbif.get_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) gb.name = f"test_{taxon_id}-{map_type}-s{tile_size // 512 if tile_size is not None else 1}" exp = tile_size if tile_size is not None else 512 assert gb.resolution == exp
class TestMapBox: mapbox: MapBox = MapBox(token=get_token()) @pytest.mark.vcr("new") @pytest.mark.parametrize( "input_string, output", [ ("Vancouver, Canada", LatLon(-123.116838, 49.279862)), ("Vondelpark", LatLon(4.877867, 52.362441)), ], ) def test_geocode(self, input_string, output): res = self.mapbox.get_geocode(input_string) assert res == output def test_no_token(self): mp = MapBox() with pytest.raises(BaseMap.AuthMissingError): _ = mp.get_geocode("The Moon") @pytest.mark.vcr("new") @pytest.mark.parametrize( "tid, fmt, style, high_res", [ (TileID(0, 0, 0), "jpg90", "satellite", False), (TileID(6, 40, 44), "jpg90", "satellite", True), (TileID(2, 2, 2), "jpg90", "satellite", True), ], ) def test_get_tiles(self, tid, fmt, style, high_res): res = self.mapbox.get_tile(tid, fmt=fmt, style=style, high_res=high_res) assert res.resolution == 256 if not high_res else 512 print("res:", res) res.save() assert type(res) == Tile @pytest.mark.vcr("new") @pytest.mark.parametrize( "tile_array", [ ( TileID(15, 16826, 10770), TileID(15, 16826, 10771), TileID(15, 16827, 10770), TileID(15, 16827, 10771), ), ], ) def test_get_tilearray(self, tile_array): res_tiles = self.mapbox.get_tiles(tile_array) assert type(res_tiles) == TileArray for t in res_tiles.values(): t.save()
def make_map( self, species_code: str, mapbox: MapBox, map_size: int = 512, start_zoom: int = 0, ) -> "Image": range_tiles = self.get_tiles(species_code, start_zoom, map_size) if not range_tiles: img = mapbox.get_tile(TileID(0, 0, 0), high_res=True).img return img, True range_map = self.generate_range_map(mapbox, self, map_size, range_tiles) return range_map, False
def test_creation(self, input_tileid, expected_tileid, warn): print("itid", input_tileid) print("exid:", expected_tileid) with pytest.warns(warn) as warnings: new_tid = TileID(input_tileid) # if len(warnings) == 0 and warn: # print(warnings) # raise AssertionError("Warnings weren't raised.") # else: # new_tid = TileID(0, x=0, y=0) rz = new_tid.z rx = new_tid.x ry = new_tid.y assert expected_tileid == (rz, rx, ry)
def get_tile(self, tid: TileID, **kwargs) -> Tile: """ Downloads a tile given by the z, x and y coordinates with various options. Note that setting any of the parameters overrides the defaults from the object. Args: tid (TileID): tile id to download. fmt (str, optional): mapbox format. Defaults to "jpg90". style (str, optional): mapbox style. Defaults to "satellite". high_res (bool, optional): Enable high res (512x512) mode. Defaults to True. Raises: self.TokenMissingError: If there isn't a token. Returns: Tile: A tile representing this map tile or None if something failed. """ fmt = self.fmt style = self.style high_res = kwargs.get("high_res", self.high_res) if "fmt" in kwargs: fmt = kwargs["fmt"] if "style" in kwargs: style = kwargs["style"] if "high_res" in kwargs: high_res = kwargs["high_res"] z, x, y = tid # If the resolution is douled, MapBox only server every 2nd zoom level. # So if we're in this state, we need to take the next higher zoom level. # if high_res and z % 2 != 0: # z += 1 if not self.token: raise self.AuthMissingError("Mapbox auth token not set.") params = {"access_token": self.token} hr = "" if high_res: hr = "@2x" url = f"v4/mapbox.{style}/{z}/{x}/{y}{hr}.{fmt}" print("murl:", self.base_url + url) tile_id = TileID(z=z, x=x, y=y) tile = self.download_tile_url(tid=tile_id, tile_url=url, params=params) return tile
def get_tiles(self, species_code: str, zoom: int = 0, map_size: int = 512): bbox = self.get_bbox(species_code) if not bbox: return [] tiles = self.get_bbox_tiles(bbox, zoom, map_size) # eBird doesn't handle crossing the antimeridian well, so we need to "improvise" one. rsid = "" if not tiles: rsid = self.get_rsid(species_code, 0) proxy_tile = self.download_tile(TileID(0, 0, 0), rsid) _, _, proxy_bbox = self.find_image_bbox(proxy_tile.img, 0) print("proxy bbox:", proxy_bbox) tiles = self.get_bbox_tiles(proxy_bbox, zoom, map_size, True) print("ebgt2") pprint(tiles) if tiles[0].zoom >= 6 or not rsid: rsid = self.get_rsid(species_code, tiles[0].zoom) filled_tiles = [ TileArray.from_dict( {tid: self.download_tile(tid, rsid) for tid in a}) for a in tiles ] return filled_tiles
class TestTileArray: def create_tilearray(self, tids, imgs): tile_array = TileArray() for tid, img in zip(tids, imgs): tile = Tile(tid=tid, img=img) tile_array[tid] = tile return tile_array def test_creation(self, tile_ids, images): tile_array = self.create_tilearray(tile_ids, images) for tid, tile in tile_array.items(): assert tid in tile_ids pprint(tile_array) def test_creation_constructor(self, tile_ids, images): tile_array = TileArray.from_dict( {TileID(k): Tile(TileID(k), v) for k, v in zip(tile_ids, images)}) for tid in tile_ids: assert tid in tile_array pprint(tile_array) def test_set_name(self, tile_ids, images): ta = TileArray(name="testname") assert ta.name == "testname" ta.name = "newtestname" assert ta.name == "newtestname" ts2 = TileArray() ts2.name = "anothertestname" assert ts2.name == "anothertestname" @pytest.mark.parametrize( "dims", [ (2, 2), ], ) def test_dims(self, tile_ids, images, dims): tile_array = self.create_tilearray(tile_ids, images) assert tile_array.xy_dims == dims def test_mixed_zoom(self, tile_ids, images): fiddled_ids = [ TileID(z + 1 if x % 2 == 0 else z, x, y) for z, x, y in tile_ids ] with pytest.raises(TileArray.MixedZoomError): _ = self.create_tilearray(fiddled_ids, images) def test_change_zoom(self, tile_ids, images): tile_array = self.create_tilearray(tile_ids, images) with pytest.raises(TileArray.MixedZoomError): tile_array.zoom = tile_ids[0].z + 1 @pytest.mark.parametrize( "zoom, exc", [ ([1], None), ([1, 2], None), ([constants.max_zoom + 1], TileArray.ZoomRangeError), ([constants.min_zoom - 1], TileArray.ZoomRangeError), ], ) def test_change_zoom_empty(self, tile_ids, images, zoom, exc): print("zoom", zoom) print("exc", exc) tile_array = TileArray() for z in zoom: if exc: with pytest.raises(exc): tile_array.zoom = z else: tile_array.zoom = z @pytest.mark.parametrize( "test_line_ids, expected_sibling_ids", [ ( [ TileID(x=0, y=1, z=2), TileID(x=1, y=1, z=2), TileID(x=2, y=1, z=2) ], [ TileID(x=2, y=0, z=2), TileID(x=1, y=1, z=2), TileID(x=2, y=1, z=2), TileID(x=0, y=0, z=2), TileID(x=0, y=1, z=2), TileID(x=1, y=0, z=2), ], ), ( [ TileID(x=0, y=1, z=2), TileID(x=0, y=2, z=2), TileID(x=0, y=3, z=2) ], [ TileID(x=1, y=3, z=2), TileID(x=1, y=1, z=2), TileID(x=1, y=2, z=2), TileID(x=0, y=1, z=2), TileID(x=0, y=2, z=2), TileID(x=0, y=3, z=2), ], ), ( [TileID(x=0, y=0, z=3), TileID(x=0, y=1, z=3)], [ TileID(x=1, y=1, z=3), TileID(x=0, y=1, z=3), TileID(x=1, y=0, z=3), TileID(x=0, y=0, z=3), ], ), ( [TileID(x=0, y=0, z=4), TileID(x=1, y=0, z=4)], [ TileID(x=0, y=0, z=4), TileID(x=1, y=1, z=4), TileID(x=0, y=1, z=4), TileID(x=1, y=0, z=4), ], ), ( [TileID(x=3, y=0, z=5), TileID(x=4, y=0, z=5)], [ TileID(x=4, y=1, z=5), TileID(x=3, y=0, z=5), TileID(x=3, y=1, z=5), TileID(x=4, y=0, z=5), ], ), ( [TileID(x=3, y=3, z=6), TileID(x=3, y=4, z=6)], [ TileID(x=3, y=4, z=6), TileID(x=2, y=3, z=6), TileID(x=3, y=3, z=6), TileID(x=2, y=4, z=6), ], ), ( [TileID(x=-4, y=160, z=8), TileID(x=-3, y=160, z=8)], [ TileID(x=-4, y=160, z=8), TileID(x=-3, y=160, z=8), TileID(x=-4, y=161, z=8), TileID(x=-3, y=161, z=8), ], ), ], ) def test_find_filtered_siblings(self, test_line_ids, expected_sibling_ids, tile_ids, images): tile_array = self.create_tilearray( test_line_ids, [create_blank_image() for _ in range(len(test_line_ids))]) res = tile_array.find_line_sibling_tile_ids() assert isinstance(res, TileArray) for tid in expected_sibling_ids: assert tid in res.keys() def test_tilearray_from_tids(self, tile_ids, images): ta = empty_tilearray_from_ids(tile_ids) assert list(ta.keys()) == tile_ids assert [t.tid for t in ta.values()] == tile_ids @pytest.mark.parametrize( "result", [ LatLonBBox(left=-180.0, top=85.0511287798066, right=180.0, bottom=-85.0511287798066), LatLonBBox( left=4.85595703125, top=52.362183216744256, right=4.8779296875, bottom=52.34876318198808, ), ], ) @pytest.mark.skip("This passes, just needs to be parameterized correctly.") def test_tilearray_bbox(self, tile_ids, images, result): ta = empty_tilearray_from_ids(tile_ids) res = ta.bounds assert res == result @pytest.mark.parametrize( "result", [ (PixBbox(left=0, top=512, right=512, bottom=0), ), (PixBbox(left=4307456, top=5631488, right=4307968, bottom=5630976), ), ], ) @pytest.mark.skip("This passes, just needs to be parameterized correctly.") def test_tilearray_pixbbox(self, tile_ids, images, result): ta = empty_tilearray_from_ids(tile_ids) res = ta.pixel_bounds assert res == result
def test_as_url(self): tid = TileID(6, -8, 42) assert tid.urlform == "6/-8/42"
def test_iterable_tileid(self, test_id): z, x, y = TileID(test_id) assert (z, x, y) == (test_id)
class TestGBIF: gbif: Any = GBIF() @pytest.mark.vcr("new") @pytest.mark.parametrize( "species, taxon_id", [ ("Bushtit", ("Psaltriparus minimus", 2494988)), ("Barn Swallow", ("Hirundo rustica", 9515886)), ("Anna's Hummingbird", ("Calypte anna", 2476674)), ("Hirundo rustica", ("Hirundo rustica", 9515886)), ], ) def test_gbif_lookup(self, species, taxon_id): res = self.gbif.lookup_species(species) assert res == taxon_id @pytest.mark.vcr("new") @pytest.mark.parametrize( "taxon_id, lat_lon_bbox", [ (2494988, LatLonBBox(right=14, top=55, left=-127, bottom=15)), (5232445, LatLonBBox(right=10, top=54, left=-161, bottom=19)), (5228134, LatLonBBox(right=0, top=-38, left=-13, bottom=-38)), ], ) def test_get_bbox(self, taxon_id, lat_lon_bbox): res = self.gbif.get_bbox(taxon_id) assert res == lat_lon_bbox @pytest.mark.vcr("new") @pytest.mark.parametrize( "map_type", [ "hex", "square", ], ) @pytest.mark.parametrize( "taxon_id, tile_size", [ (9515886, None), (9515886, 256), (2494988, 512), ], ) def test_get_map_tile(self, taxon_id, tile_size, map_type): if map_type == "hex": gb = self.gbif.get_hex_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) elif map_type == "square": gb = self.gbif.get_square_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) # else: # gb = self.gbif.get_tile(tile_id=TileID(0, 0, 0), taxonKey=taxon_id, tile_size=tile_size) gb.name = f"test_{taxon_id}-{map_type}-s{tile_size // 512 if tile_size is not None else 1}" exp = tile_size if tile_size is not None else 512 assert gb.resolution == exp def test_high_res_override(self): assert mapbox.high_res is True res = mapbox.get_tiles([TileID(0, 0, 0)], high_res=False) assert res[TileID(0, 0, 0)].resolution == 256 res2 = mapbox.get_tiles([TileID(0, 0, 0)]) assert res2[TileID(0, 0, 0)].resolution == 512 @pytest.mark.vcr("new") @pytest.mark.parametrize( "map_type", [ "hex", "square", ], ) @pytest.mark.parametrize( "taxon_id, tile_ids_expected_image", [ ( 2482552, { TileID(7, 121, 26): True, TileID(7, 121, 27): True, TileID(7, 120, 27): True, TileID(7, 120, 26): False, }, ), ], ) def test_get_tilearray(self, taxon_id, tile_ids_expected_image, map_type): tile_ids = tile_ids_expected_image.keys() ta = TileArray.from_dict({x: Tile(x) for x in tile_ids}) ta = self.gbif.get_tiles(taxon_id, ta, mode=map_type) print(ta) for k, t in ta.items(): t.save() print("IE", k, tile_ids_expected_image[k]) print("timg", t.img)
class TestEbird: ebird: eBirdMap = eBirdMap() mapbox: MapBox = MapBox(token=get_token(), high_res=False) @pytest.mark.vcr("new") @pytest.mark.parametrize( "species_code, expected_bbox", [ ( "bushti", LatLonBBox( -128.796028798097, 51.8596628170432, -89.2701562968385, 14.126239979566, ), ), ( "tui1", LatLonBBox( -178.203369424671, -28.7802470429875, 179.326113654898, -52.691212723642, ), ), ( "", None, ), ( "redcro9", LatLonBBox( -115.321299536305, 43.2077783892461, -113.524668968066, 41.9867319031071, ), ), ], ) def test_get_bbox(self, species_code, expected_bbox): res = self.ebird.get_bbox(species_code) assert res == expected_bbox @pytest.mark.vcr("new") @pytest.mark.parametrize( "species_code", [ "bushti", ], ) def test_get_rsid(self, species_code): res = self.ebird.get_rsid(species_code) assert res @pytest.mark.vcr("new") @pytest.mark.parametrize( "tile_id, rsid", [ ( TileID(0, 0, 0), "RS108970032", ), ], ) def test_get_tile(self, tile_id, rsid): res = self.ebird.download_tile(tile_id, rsid) assert res.img @pytest.mark.vcr("new") @pytest.mark.parametrize( "species_code, expected_ids", [( "tui1", [(4, 15, 9), (4, 15, 10), (4, 0, 9), (4, 0, 10)], )], ) def test_get_tiles(self, species_code, expected_ids): res = self.ebird.get_tiles(species_code) print("res:\n", res) for x in res: for t in x.values(): t.save() for e in res: for x in e: assert tuple(x) in expected_ids @pytest.mark.vcr("new") @pytest.mark.parametrize( "species_code, size, no_data", [ ("tui1", 512, False), ("bushti", 512, False), ("pilwoo", 512, False), ("inirai1", 512, False), ("bkpwar", 512, False), ("baleag", 512, False), ("grycat", 512, False), ("kinpen1", 512, False), ("carchi", 512, False), ("arcter", 512, False), ("dodo1", 512, True), ("pifgoo", 512, False), ], ) def test_map_final(self, species_code, size, no_data): res, res_no_data = self.ebird.make_map(species_code, self.mapbox, size) assert res_no_data == no_data res.save(f"final-ebird-{species_code}_{size}.png")
def test_high_res_override(self): assert mapbox.high_res is True res = mapbox.get_tiles([TileID(0, 0, 0)], high_res=False) assert res[TileID(0, 0, 0)].resolution == 256 res2 = mapbox.get_tiles([TileID(0, 0, 0)]) assert res2[TileID(0, 0, 0)].resolution == 512
def test_mixed_zoom(self, tile_ids, images): fiddled_ids = [ TileID(z + 1 if x % 2 == 0 else z, x, y) for z, x, y in tile_ids ] with pytest.raises(TileArray.MixedZoomError): _ = self.create_tilearray(fiddled_ids, images)
top=-21.943045533438177, ), ), ], ) def test_tile_bounds(self, tile, bounds): assert tile.bounds == bounds # Just a 2x2 tilearray. @pytest.mark.parametrize( "tile_ids, images", [ ( [ TileID(1, 1, 1), TileID(1, 1, 0), TileID(1, 0, 1), TileID(1, 0, 0), ], [ create_blank_image(256, "RGB"), create_blank_image(256, "RGB"), create_blank_image(256, "RGB"), create_blank_image(256, "RGB"), ], ), ( [ TileID(15, 16826, 10770), TileID(15, 16826, 10771),
def test_assignment_fail(self): new_tid = TileID(0, 0, 0) with pytest.raises(FrozenInstanceError): new_tid.z = 42
def test_exceptions(self, input_val, exc): with pytest.raises(exc): new_tid = TileID(input_val)