|
1 | 1 | """Tilesets command line interface""" |
2 | 2 |
|
| 3 | +import os |
3 | 4 | import base64 |
4 | 5 | import builtins |
5 | 6 | import json |
6 | 7 | import re |
7 | 8 | import tempfile |
| 9 | +from glob import glob |
8 | 10 | from urllib.parse import parse_qs, urlencode, urlparse |
9 | 11 |
|
10 | 12 | import click |
@@ -840,6 +842,112 @@ def validate_stream(features): |
840 | 842 | yield feature |
841 | 843 |
|
842 | 844 |
|
| 845 | +@cli.command("estimate-cu") |
| 846 | +@click.argument("tileset", required=True, type=str) |
| 847 | +@click.option( |
| 848 | + "--sources", |
| 849 | + "-s", |
| 850 | + required=False, |
| 851 | + type=click.Path(exists=False), |
| 852 | + help="Local sources represented in your tileset's recipe", |
| 853 | +) |
| 854 | +@click.option( |
| 855 | + "--num-bands", |
| 856 | + "-b", |
| 857 | + required=False, |
| 858 | + type=int, |
| 859 | + default=15, |
| 860 | + help="The number of bands your recipe is selecting", |
| 861 | +) |
| 862 | +@click.option("--minzoom", required=False, type=int, help="The minzoom value override") |
| 863 | +@click.option("--maxzoom", required=False, type=int, help="The maxzoom value override") |
| 864 | +@click.option( |
| 865 | + "--raw", required=False, type=bool, default=False, is_flag=True, help="Raw CU value" |
| 866 | +) |
| 867 | +@click.option("--token", "-t", required=False, type=str, help="Mapbox access token") |
| 868 | +def estimate_cu( |
| 869 | + tileset, |
| 870 | + num_bands=15, |
| 871 | + minzoom=None, |
| 872 | + maxzoom=None, |
| 873 | + sources=None, |
| 874 | + raw=False, |
| 875 | + token=None, |
| 876 | +): |
| 877 | + """ |
| 878 | + Estimates the CUs that will be consumed when processing your recipe into a tileset. |
| 879 | + Requires extra installation steps: see https://github.com/mapbox/tilesets-cli/blob/master/README.md |
| 880 | + """ |
| 881 | + |
| 882 | + rio = utils.load_module("rasterio") |
| 883 | + |
| 884 | + if sources is None: |
| 885 | + click.echo(f"[warning] estimating '{tileset}' with a default global bounds") |
| 886 | + sources = "" |
| 887 | + |
| 888 | + total_size = 0 |
| 889 | + overall_bounds = None |
| 890 | + src_list = glob(sources) |
| 891 | + |
| 892 | + if len(src_list) > 0: |
| 893 | + with rio.open(src_list[0], mode="r") as ds: |
| 894 | + overall_bounds = ds.bounds |
| 895 | + |
| 896 | + total_size += os.path.getsize(src_list[0]) |
| 897 | + |
| 898 | + if len(src_list) > 1: |
| 899 | + for source in src_list: |
| 900 | + try: |
| 901 | + with rio.open(source, mode="r") as ds: |
| 902 | + if ds.bounds.left < overall_bounds.left: |
| 903 | + overall_bounds.left = ds.bounds.left |
| 904 | + if ds.bounds.right > overall_bounds.right: |
| 905 | + overall_bounds.right = ds.bounds.right |
| 906 | + if ds.bounds.top > overall_bounds.top: |
| 907 | + overall_bounds.top = ds.bounds.top |
| 908 | + if ds.bounds.bottom < overall_bounds.bottom: |
| 909 | + overall_bounds.bottom = ds.bounds.bottom |
| 910 | + |
| 911 | + total_size += os.path.getsize(source) |
| 912 | + except Exception: |
| 913 | + click.echo(f"[warning] skipping invalid source '{source}'") |
| 914 | + |
| 915 | + s = utils._get_session() |
| 916 | + mapbox_api = utils._get_api() |
| 917 | + mapbox_token = utils._get_token(token) |
| 918 | + url = "{0}/tilesets/v1/{1}/estimate".format(mapbox_api, tileset) |
| 919 | + |
| 920 | + query_params = { |
| 921 | + "filesize": total_size, |
| 922 | + "band_count": num_bands, |
| 923 | + "access_token": mapbox_token, |
| 924 | + } |
| 925 | + |
| 926 | + if overall_bounds is not None: |
| 927 | + query_params["bounds"] = json.dumps([*overall_bounds]) |
| 928 | + |
| 929 | + if minzoom is not None: |
| 930 | + query_params["minzoom"] = minzoom |
| 931 | + |
| 932 | + if maxzoom is not None: |
| 933 | + query_params["maxzoom"] = maxzoom |
| 934 | + |
| 935 | + response = s.get(url, params=query_params) |
| 936 | + |
| 937 | + if not response.ok: |
| 938 | + raise errors.TilesetsError(response.text) |
| 939 | + |
| 940 | + parsed = json.loads(response.text) |
| 941 | + if "cu" not in parsed: |
| 942 | + raise errors.TilesetsError(response.text) |
| 943 | + |
| 944 | + click.echo( |
| 945 | + response.text |
| 946 | + if raw |
| 947 | + else f"\nEstimated CUs for '{tileset}': {click.style(parsed['cu'], bold=True, fg=155)}. To publish your tileset, run 'tilesets publish'." |
| 948 | + ) |
| 949 | + |
| 950 | + |
843 | 951 | @cli.command("estimate-area") |
844 | 952 | @cligj.features_in_arg |
845 | 953 | @click.option( |
|
0 commit comments