Пример #1
0
 def get_bbox(self, taxon_key: int) -> LatLonBBox:
     """
     Given a taxon key, query the GBIF map API for a bounding box for the taxon.
     Args:
         taxon_key (int): The taxon ID to look up.
     Returns:
         LatLonBBox: bounding box for the taxon key.
     """
     params = {"taxonKey": taxon_key}
     url = "v2/map/occurrence/density/capabilities.json"
     metadata = self.get_bbox_meta(url, params)
     left = metadata.left
     right = metadata.right
     top = metadata.top
     bottom = metadata.bottom
     bbox = LatLonBBox(left=left, top=top, right=right, bottom=bottom)
     return bbox
Пример #2
0
class TestFindTiles:
    @pytest.mark.parametrize(
        "bbox, start_zoom, end_zoom, name, am_invalid",
        [
            (
                LatLonBBox(east=175.781248,
                           south=-42.032974,
                           west=173.671878,
                           north=-40.979897),
                0,
                8,
                "Wellington Test - general area test.",
                False,
            ),
            (
                LatLonBBox(
                    west=-179.99999999291,
                    south=16.9397716157348,
                    east=179.326113654898,
                    north=71.9081724700314,
                ),
                0,
                1,  # Ideally 2, but for the baseline, 1 is fine.
                "Bald Eagle - AM wrap with zoom.",
                True,
            ),
            (
                LatLonBBox(
                    west=-172.813477719954,
                    south=-82.1269032464488,
                    east=179.326113654898,
                    north=-39.6895335169534,
                ),
                0,
                1,
                "Emperor Pengiun - Antartica.",
                False,  # This technically doesn't quite cross the AM, I guess.
            ),
            (
                LatLonBBox(
                    west=-163.830324878759,
                    south=47.02752144317,
                    east=163.156438540747,
                    north=71.9081724700314,
                ),
                0,
                1,
                "Gray-headed Chickadee- No AM wrap.",
                False,
            ),
            (
                LatLonBBox(
                    west=-91.965102149197,
                    south=-1.38713438223174,
                    east=-89.2701562968385,
                    north=0.421740150964651,
                ),
                0,
                8,
                "Galapagos Pengiun - small area",
                False,
            ),
            (
                LatLonBBox(
                    west=-178.203369424671,
                    south=-52.691212723642,
                    east=179.326113654898,
                    north=-28.7802470429875,
                ),
                0,
                1,  # should be 4 with AM wrap.
                "Tui - AM wrap with more zoom.",
                True,
            ),
            (
                LatLonBBox(
                    west=-151.253910901085,
                    south=4.9495734055138,
                    east=5.05294853571131,
                    north=63.6299576758096,
                ),
                0,
                2,
                "Gray Catbird - 3x1 line",
                False,
            ),
            (
                LatLonBBox(
                    west=63.4434420034802,
                    south=6.76762999637114,
                    east=109.257521493576,
                    north=35.0816917166643,
                ),
                0,
                3,
                "Rufous Treepie",
                False,
            ),
            (
                LatLonBBox(
                    west=160.15,
                    south=-53.38,
                    east=-176.17,
                    north=-25.13,
                ),
                0,
                4,
                "New Zealand well-formed AM cross - west > east.",
                False,
            ),
            (
                LatLonBBox(west=165, north=-29, east=185, south=-53),
                0,
                4,
                "Tui - AM cross.",
                False,
            ),
        ],
    )
    def test_bbox_to_tiles(self, bbox, start_zoom, end_zoom, name, am_invalid):
        res = bounding_box_to_tiles(bbox, start_zoom)
        print(f"res ({len(res)}):\n", res)
        if not res:
            assert am_invalid
            assert len(res) == 0
            assert res.zoom is not None
        elif len(res) == 1:
            assert res[0].zoom == end_zoom
            assert not am_invalid
        else:
            assert res[0].zoom == end_zoom
            assert res[1].zoom == end_zoom
            assert not am_invalid
Пример #3
0
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
Пример #4
0
def bounding_box_to_tiles(
    bbox: geo.LatLonBBox, start_zoom: int = 0, size: int = 512, alt_bbox: bool = False
) -> Tuple["TileArray"]:
    """
    Takes a bounding box and finds the TileArray that best covers that bounding box.
    This may result in tiles that are across the anti-meridian from the rest.
    The end result is a TileArray of either 4, 6 or 9 tiles that fully contain the bounding box.
    In the event that the bounding box crosses the antimeridian, will return two TileArrays, one for each side.
        While a TileArray can store non-contiguous tiles, this is easier for now.
    Args:
        bbox (LatLonBBox): Bounding box to find the tile covering for.
        start_zoom (int, optional): starting zoom level. Probably best to leave this as the default. Defaults to 0.
        size (int, optional): Size of the map, in pixels. Should be a multiple of 256. Defaults to 512.
    Returns:
        Tuple["TileArray"]: A TileArray covering the bounding box that isn't larger than size.
            If the antimeridian is crossed, this will return two TileArrays, one for each side, except in the case of zoom = 1, in which case all tiles are returned.
            If there's a bad bounding box, returns an empty TileArray. Eventually, this should try an alternative approach to finding the proper covering.
    """
    n = bbox.north
    w = bbox.west
    s = bbox.south
    e = bbox.east
    zoom_level = start_zoom
    bad_bbox = False
    # Is this likely to be an incorrect bounding box that forgets that the map is actually a cynlinder?
    # This is really just a heuristic test for an incorrect bounding box, because it's hard to deal with bad data.
    if -180 < w < -178 and 178 < e < 180:
        print("Probable incorrect bounding box due to antimeridian crossing.")
        if alt_bbox:
            print("alt bounding box override.")
        else:
            bad_bbox = True

    if (w > e or abs(w) > 180 or abs(e) > 180) and not bad_bbox:
        print("Bbox crosses anti-meridian.")
        bbox_west, bbox_east = bbox.am_split()
        tile_west, alt_west, zoom_west = _bounding_box_candidates(
            bbox_west, zoom_level, size
        )
        tile_east, alt_east, zoom_east = _bounding_box_candidates(
            bbox_east, zoom_level, size
        )
        print("West:")
        pprint(tile_west)
        print("West alt:")
        pprint(alt_west)
        print("East:")
        pprint(tile_east)
        print("East alt:")
        pprint(alt_east)
        # If one bbox is tigher than the other, this is a problem. Only take the furthest out one.
        minimum_zoom = min(zoom_west, zoom_east) - 1
        if zoom_west != zoom_east:
            print("Mixed zoom found for bbox!")
            print("bboxtt zoom:", zoom_west, zoom_east, minimum_zoom)
        # This may be the only fix, but it may need some edge case handling.
        # This is to avoid getting both bounding boxes showing tiles for the whole planet. Each tile should only be returned once.
        if minimum_zoom == 1:
            tids = [TileID(z=1, x=x, y=y) for x in (0, 1) for y in (0, 1)]
            ta = empty_tilearray_from_ids(tids)
            return (ta,)
        # Ignore the alts, because they're spurious for this case as a 2x2 split across the am will always trigger the alt for a 2x 2x2 bbox, which is wrong.
        # best_west = _best_tile_covering(bbox_west, tile_west, alt_west, minimum_zoom)
        # best_east = _best_tile_covering(bbox_east, tile_east, alt_east, minimum_zoom)
        best_west = _best_tile_covering(bbox_west, tile_west, TileArray(), minimum_zoom)
        best_east = _best_tile_covering(bbox_east, tile_east, TileArray(), minimum_zoom)
        return best_west, best_east
    else:
        tile_ids, tile_ids_alt, end_zoom_level = _bounding_box_candidates(
            bbox, zoom_level, size
        )
        best = _best_tile_covering(bbox, tile_ids, tile_ids_alt, end_zoom_level)
        if not bad_bbox:
            return (best,)
        else:
            return TileArray(zoom_level=end_zoom_level)
Пример #5
0
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)
Пример #6
0
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")
Пример #7
0
class TestLatLonBbox:
    @pytest.mark.parametrize(
        "latlon_in, latlon_out, zoom",
        [
            ((28.304380682962783, -15.468750000000012), (28.3, -15.5), 0),
            ((28.304380682962783, -15.468750000000012), (28.30, -15.47), 5),
            ((28.304380682962783, -15.468750000000012), (28.3044, -15.4688), 12),
            ((0.0, 0.0), (0.0, 0.0), 42),
            ((-89.86367491884421, 75.43308649874739), (-89.8637, 75.4331), 12),
        ],
    )
    def test_truncate_precision(self, latlon_in, latlon_out, zoom):
        latlon_in = LatLon(*latlon_in)
        res = geo.truncate_latlon_precision(latlon_in, zoom)
        assert res == LatLon(*latlon_out)

    @pytest.mark.parametrize(
        "roundtrip",
        [False, True],
    )
    @pytest.mark.parametrize(
        "pixels, latlon, zoom, tile_size",
        [
            ((245, 153), (-33.1, 164.5), 0, 256),
            ((256, 173), (-53.3, 180.0), 0, 256),
            ((1, 149), (-28.3, -178.6), 0, 256),
            ((4, 164), (-45.1, -174.4), 0, 256),
            ((0, 0), (85.1, -180.0), 0, 256),
            ((128, 128), (0.0, 0.0), 0, 256),
            ((256, 256), (-85.1, 180.0), 0, 256),
            ((987, 808), (-71.5, 167.0), 0, 1024),
            ((525, 761), (41.9, -87.7), 3, 256),
        ],
    )
    def test_pixels_to_lat_lon(self, pixels, latlon, zoom, tile_size, roundtrip):
        pixels = Pixel(*pixels)
        latlon = LatLon(*latlon)
        print(pixels, latlon, zoom, tile_size, roundtrip)
        result_lat_lon = geo.pixels_to_lat_lon(pixels, zoom, tile_size)
        result_pixels = geo.lat_lon_to_pixels(result_lat_lon, zoom, tile_size)
        assert result_lat_lon == latlon
        if not roundtrip:
            assert result_pixels == pixels

    @pytest.mark.parametrize(
        "latlon, pixels, zoom",
        [
            (LatLon(lat=6.7, lon=109.2), Pixel(206, 123), 0),
        ],
    )
    def test_lat_lon_to_pixels(self, latlon, zoom, pixels):
        res = geo.lat_lon_to_pixels(latlon, zoom)
        assert res == pixels
        # res2 = geo.pixels_to_lat_lon(pixels, zoom)
        # assert res2 == latlon

    @pytest.mark.parametrize(
        "bbox, other_bbox, result",
        [
            (
                LatLonBBox(left=-180.0, right=180.0, top=90.0, bottom=-90.0),
                LatLonBBox(left=-180.0, right=180.0, top=90.0, bottom=-90.0),
                True,
            ),
            (
                LatLonBBox(left=-90.0, right=90.0, top=45.0, bottom=-45.0),
                LatLonBBox(left=-180.0, right=180.0, top=90.0, bottom=-90.0),
                False,
            ),
            (
                LatLonBBox(left=-90.0, right=90.0, top=45.0, bottom=-45.0),
                LatLonBBox(left=-90.0, right=90.0, top=44.99, bottom=-45.0),
                True,
            ),
        ],
    )
    def test_contains(self, bbox, other_bbox, result):
        assert bbox.contains(other_bbox) == result

    @pytest.mark.parametrize(
        "pixels_bbox, zoom, tile_size, truncate, expected",
        [
            (
                PixBbox(0, 0, 255, 255),
                0,
                256,
                True,
                LatLonBBox(bottom=-84.9, left=-180.0, top=85.1, right=178.6),
            ),
            # (PixBbox(1, 149, 256, 173), 0, 256, True, LatLonBBox(0, 0, 0, 0)),
        ],
    )
    def test_pixel_bbox_to_latlon_bbox(
        self, pixels_bbox, zoom, tile_size, truncate, expected
    ):
        res = geo.bounding_pixels_to_lat_lon(pixels_bbox, zoom, tile_size, truncate)
        assert res == expected

    @pytest.mark.parametrize(
        "latlon_tl, latlon_br",
        [
            (LatLon(lat=45, lon=90), LatLon(lat=-45, lon=-90)),
            (LatLon(lat=90, lon=180), LatLon(lat=-90, lon=-180)),
            (LatLon(lat=90, lon=180), LatLon(lat=0, lon=0)),
            (LatLon(lat=0, lon=0), LatLon(lat=-90, lon=-180)),
        ],
    )
    def test_bbox_lat_clamp(self, latlon_tl, latlon_br):
        test_bbox = LatLonBBox(
            left=latlon_tl.lon,
            top=latlon_tl.lat,
            right=latlon_br.lon,
            bottom=latlon_br.lat,
        )
        test_bbox.clamp_lat()
        print(test_bbox)
        assert test_bbox.top <= constants.max_latitude
        assert test_bbox.bottom >= -constants.max_latitude
Пример #8
0
 def test_property_direct(self):
     a = LatLonBBox(20.0, 40.0, 40.0, -40.0).center
     assert a == LatLon(30.0, 0.0)
     assert type(a) == LatLon
Пример #9
0
 def test_area_ni(self):
     with pytest.raises(NotImplementedError):
         _ = LatLonBBox(12, 45, 39, 124).area
Пример #10
0
 def test_property_aliases(self):
     bbx = LatLonBBox(-110.39, 24.06, -110.25, 24.17)
     assert bbx.xy_dims == bbx.range
Пример #11
0
 def test_comparison_srs(self, in_bbox, srs):
     assert LatLonBBox(*in_bbox) != LatLonBBox(*in_bbox, srs=srs)
Пример #12
0
 def test_comparison(self, in_bbox, comp, not_eq):
     res_bbox = LatLonBBox(*in_bbox)
     if not_eq:
         assert res_bbox != tuple(reversed(in_bbox))
     else:
         assert res_bbox == comp
Пример #13
0
 def test_creation(self, in_bbox):
     res_bbox = LatLonBBox(*in_bbox)
     assert res_bbox == in_bbox
Пример #14
0
class TestLatLonBbox:
    @pytest.mark.parametrize(
        "in_bbox",
        [
            (-54.75, -68.25, -54.85, -68.35),
        ],
    )
    def test_creation(self, in_bbox):
        res_bbox = LatLonBBox(*in_bbox)
        assert res_bbox == in_bbox

    @pytest.mark.parametrize(
        "not_eq",
        [
            True,
            False,
        ],
    )
    @pytest.mark.parametrize(
        "in_bbox, comp",
        [
            (
                (
                    -90.0,
                    -45.0,
                    90.0,
                    45.0,
                ),
                (-90.0, -45.0, 90.0, 45.0),
            ),
            (
                (
                    1,
                    2,
                    3,
                    4,
                ),
                [1, 2, 3, 4],
            ),
            (
                (
                    1,
                    2,
                    3,
                    4,
                ),
                LatLonBBox(1, 2, 3, 4),
            ),
        ],
    )
    def test_comparison(self, in_bbox, comp, not_eq):
        res_bbox = LatLonBBox(*in_bbox)
        if not_eq:
            assert res_bbox != tuple(reversed(in_bbox))
        else:
            assert res_bbox == comp

    @pytest.mark.parametrize(
        "in_bbox, srs",
        [
            ((-54.75, -68.25, -54.85, -68.35), "EPSG:4326"),
        ],
    )
    def test_comparison_srs(self, in_bbox, srs):
        assert LatLonBBox(*in_bbox) != LatLonBBox(*in_bbox, srs=srs)

    @pytest.mark.parametrize(
        "in_bbox",
        [
            (1, 2, 3, 4),
        ],
    )
    def test_get_set_alt(self, in_bbox):
        res_bbox = LatLonBBox(*in_bbox)
        assert res_bbox.maxlat == in_bbox[1]
        res_bbox.left = 7
        assert res_bbox.left == 7
        assert res_bbox.west == 7

        res_bbox.minx = 3
        assert res_bbox.left == 3
        assert res_bbox.west == 3

    def test_property_aliases(self):
        bbx = LatLonBBox(-110.39, 24.06, -110.25, 24.17)
        assert bbx.xy_dims == bbx.range

    def test_property_direct(self):
        a = LatLonBBox(20.0, 40.0, 40.0, -40.0).center
        assert a == LatLon(30.0, 0.0)
        assert type(a) == LatLon

    @pytest.mark.parametrize(
        "in_bbox, prop, res",
        [
            (LatLonBBox(-180.0, 90.0, 180.0, -90.0), "tl", LatLon(90.0, -180.0)),
            (LatLonBBox(-180.0, 90.0, 180.0, -90.0), "br", LatLon(-90.0, 180)),
            (LatLonBBox(-54.75, -68.25, -54.85, -68.35), "tl", LatLon(-68.25, -54.75)),
            (LatLonBBox(-54.75, -68.25, -54.85, -68.35), "br", LatLon(-68.35, -54.85)),
            (LatLonBBox(-54.75, -68.25, -54.85, -68.35), "xy_dims", (0.1, 0.1)),
            (LatLonBBox(20.0, 40.0, 40.0, -40.0), "xy_dims", (20.0, 80.0)),
            (LatLonBBox(1.0, 2.0, 1.0, 4.0), "xy_dims", (0.0, 2.0)),
            (
                LatLonBBox(-54.75, -68.25, -54.85, -68.35),
                "center",
                LatLon(-54.80, -68.30),
            ),
        ],
    )
    def test_properties(self, in_bbox, prop, res):
        a = object.__getattribute__(in_bbox, prop)
        assert pytest.approx(a) == res
        assert type(a) == type(res)

    def test_area_ni(self):
        with pytest.raises(NotImplementedError):
            _ = LatLonBBox(12, 45, 39, 124).area

    @pytest.mark.parametrize(
        "latlon, zoom, pixels",
        [
            (
                LatLonBBox(west=-180.0, north=85.0, east=180.0, south=-85.0),
                0,
                PixBbox(left=0, top=0, right=256, bottom=256),
            ),
            (
                LatLonBBox(-54.75, -68.25, -54.85, -68.35),
                4,
                PixBbox(1425, 3123, 1424, 3126),
            ),
            (
                LatLonBBox(-54.75, 68.25, 54.85, -68.35),
                5,
                PixBbox(2850, 1945, 5344, 6253),
            ),
            (
                LatLonBBox(20.0, 40.0, 40.0, -40.0),
                0,
                PixBbox(142, 97, 156, 159),
            ),
            (
                LatLonBBox(-54.75, -68.25, -54.85, -68.35),
                15,
                PixBbox(2918537, 6396732, 2916206, 6403034),
            ),
        ],
    )
    def test_latlon_to_pixels(self, latlon, zoom, pixels):
        res = geo.bounding_lat_lon_to_pixels(latlon, zoom)
        print("res", res)
        assert [a for a in res] == [a for a in pixels]
        # coordinate origin is lower left corner.
        # make sure the results are in this order.
        assert res.left >= res.left
        assert res.top <= res.bottom

    @pytest.mark.parametrize(
        "latlon, result",
        [
            (
                LatLonBBox(north=45.0, south=-45.0, west=-90.0, east=90.0),
                None,
            ),
            (
                LatLonBBox(north=45.0, south=-45.0, west=90.0, east=-90.0),
                (
                    LatLonBBox(north=45.0, south=-45.0, west=90.0, east=180.0),
                    LatLonBBox(north=45.0, south=-45.0, west=-180.0, east=-90.0),
                ),
            ),
            (
                LatLonBBox(left=165, top=-29, right=185, bottom=-53),
                (
                    LatLonBBox(left=165, top=-29, right=180.0, bottom=-53),
                    LatLonBBox(left=-180.0, top=-29, right=-175, bottom=-53),
                ),
            ),
            (
                LatLonBBox(left=-185, top=-29, right=-165, bottom=-53),
                (
                    LatLonBBox(left=175.0, top=-29, right=180, bottom=-53),
                    LatLonBBox(left=-180, top=-29, right=-165, bottom=-53),
                ),
            ),
            (
                LatLonBBox(left=99, top=72, right=379, bottom=9),
                (
                    LatLonBBox(left=99, top=72, right=180, bottom=9),
                    LatLonBBox(left=-180, top=72, right=19, bottom=9),
                ),
            ),
        ],
    )
    def test_antimeridian_split(self, latlon, result):
        res = latlon.am_split()
        if res is None:
            assert res == result
        else:
            assert res[0] == result[0]
            assert res[1] == result[1]