diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e1601ada2..0bbffeb17 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,26 +4,21 @@ repos: hooks: - id: validate-pyproject - - repo: https://github.com/psf/black - rev: 22.12.0 - hooks: - - id: black - language_version: python - - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: - id: isort language_version: python - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.238 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.4 hooks: - id: ruff args: ["--fix"] + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.11.2 hooks: - id: mypy language_version: python diff --git a/docs/src/examples/notebooks/Working_with_Algorithm.ipynb b/docs/src/examples/notebooks/Working_with_Algorithm.ipynb index b76b379d2..19233ce51 100644 --- a/docs/src/examples/notebooks/Working_with_Algorithm.ipynb +++ b/docs/src/examples/notebooks/Working_with_Algorithm.ipynb @@ -39,7 +39,9 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind." + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")" ] }, { @@ -70,9 +72,9 @@ "# Fetch dataset Metadata\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/info\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(r)" @@ -97,21 +99,19 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"]\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"],\n", ")\n", "\n", "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Office fédéral de topographie swisstopo\"\n", + " tiles=r[\"tiles\"][0], opacity=1, attr=\"Office fédéral de topographie swisstopo\"\n", ").add_to(m)\n", "m" ] @@ -127,24 +127,22 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", " # rio-tiler cannot rescale automatically the data when using a colormap\n", " \"rescale\": \"1615.812,2015.09448\",\n", " \"colormap_name\": \"terrain\",\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"]\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"],\n", ")\n", "\n", "aod_layer = TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Office fédéral de topographie swisstopo\"\n", + " tiles=r[\"tiles\"][0], opacity=1, attr=\"Office fédéral de topographie swisstopo\"\n", ")\n", "aod_layer.add_to(m)\n", "m" @@ -200,26 +198,22 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", " \"algorithm\": \"hillshade\",\n", " # Hillshade algorithm use a 3pixel buffer so we need\n", " # to tell the tiler to apply a 3 pixel buffer around each tile\n", " \"buffer\": 3,\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"]\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"],\n", ")\n", "\n", - "aod_layer = TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Yo!!\"\n", - ")\n", + "aod_layer = TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Yo!!\")\n", "aod_layer.add_to(m)\n", "m" ] @@ -241,31 +235,27 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", " \"algorithm\": \"contours\",\n", " \"algorithm_params\": json.dumps(\n", " {\n", - " \"increment\": 20, # contour line every 20 meters\n", - " \"thickness\": 2, # 2m thickness\n", + " \"increment\": 20, # contour line every 20 meters\n", + " \"thickness\": 2, # 2m thickness\n", " \"minz\": 1600,\n", - " \"maxz\": 2000\n", + " \"maxz\": 2000,\n", " }\n", " ),\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"]\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"],\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Yo!!\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Yo!!\").add_to(m)\n", "m" ] }, @@ -278,31 +268,27 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", " \"algorithm\": \"contours\",\n", " \"algorithm_params\": json.dumps(\n", " {\n", - " \"increment\": 5, # contour line every 5 meters\n", - " \"thickness\": 1, # 1m thickness\n", + " \"increment\": 5, # contour line every 5 meters\n", + " \"thickness\": 1, # 1m thickness\n", " \"minz\": 1600,\n", - " \"maxz\": 2000\n", + " \"maxz\": 2000,\n", " }\n", " ),\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"]\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"],\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Yo!!\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Yo!!\").add_to(m)\n", "m" ] }, diff --git a/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF.ipynb b/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF.ipynb index 75084fbe3..dcc679ad8 100644 --- a/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF.ipynb +++ b/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF.ipynb @@ -70,7 +70,9 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind." + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")" ] }, { @@ -88,40 +90,25 @@ "source": [ "# use geojson.io\n", "geojson = {\n", - " \"type\": \"FeatureCollection\",\n", - " \"features\": [\n", - " {\n", - " \"type\": \"Feature\",\n", - " \"properties\": {},\n", - " \"geometry\": {\n", - " \"type\": \"Polygon\",\n", - " \"coordinates\": [\n", - " [\n", - " [\n", - " -74.1796875,\n", - " 45.18978009667531\n", - " ],\n", - " [\n", - " -73.092041015625,\n", - " 45.18978009667531\n", - " ],\n", - " [\n", - " -73.092041015625,\n", - " 46.00459325574482\n", - " ],\n", - " [\n", - " -74.1796875,\n", - " 46.00459325574482\n", - " ],\n", - " [\n", - " -74.1796875,\n", - " 45.18978009667531\n", - " ]\n", - " ]\n", - " ]\n", - " }\n", - " }\n", - " ]\n", + " \"type\": \"FeatureCollection\",\n", + " \"features\": [\n", + " {\n", + " \"type\": \"Feature\",\n", + " \"properties\": {},\n", + " \"geometry\": {\n", + " \"type\": \"Polygon\",\n", + " \"coordinates\": [\n", + " [\n", + " [-74.1796875, 45.18978009667531],\n", + " [-73.092041015625, 45.18978009667531],\n", + " [-73.092041015625, 46.00459325574482],\n", + " [-74.1796875, 46.00459325574482],\n", + " [-74.1796875, 45.18978009667531],\n", + " ]\n", + " ],\n", + " },\n", + " }\n", + " ],\n", "}\n", "\n", "bounds = featureBounds(geojson)" @@ -135,8 +122,8 @@ "source": [ "m = Map(\n", " tiles=\"OpenStreetMap\",\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=6\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=6,\n", ")\n", "\n", "GeoJson(geojson).add_to(m)\n", @@ -174,13 +161,13 @@ "session = boto3_session(region_name=\"us-west-2\")\n", "client = session.client(\"s3\")\n", "\n", - "bucket = \"omi-no2-nasa\" #https://registry.opendata.aws/omi-no2-nasa/\n", + "bucket = \"omi-no2-nasa\" # https://registry.opendata.aws/omi-no2-nasa/\n", "\n", "\n", "def list_objects(bucket, prefix):\n", " \"\"\"AWS s3 list objects.\"\"\"\n", "\n", - " paginator = client.get_paginator('list_objects_v2')\n", + " paginator = client.get_paginator(\"list_objects_v2\")\n", "\n", " files = []\n", " for subset in paginator.paginate(Bucket=bucket, Prefix=prefix):\n", @@ -188,13 +175,14 @@ "\n", " return files\n", "\n", + "\n", "list_files = list_objects(bucket, \"OMI-Aura_L3\")\n", "\n", "print(\"Archive Size\")\n", "files = [r[\"Key\"] for r in list_files]\n", "print(f\"Found {len(files)} OMI-NO2 files\")\n", "\n", - "size = sum([r[\"Size\"]/1000000. for r in list_files])\n", + "size = sum([r[\"Size\"] / 1000000.0 for r in list_files])\n", "print(f\"Size of the archive: {size} Mo ({size / 1000} Go)\")" ] }, @@ -238,7 +226,11 @@ }, "outputs": [], "source": [ - "files_Oct5 = list(filter(lambda x: (x.split(\"_\")[2][5:7] == \"10\") & (x.split(\"_\")[2][7:9] == \"05\"), files))\n", + "files_Oct5 = list(\n", + " filter(\n", + " lambda x: (x.split(\"_\")[2][5:7] == \"10\") & (x.split(\"_\")[2][7:9] == \"05\"), files\n", + " )\n", + ")\n", "print(len(files_Oct5))\n", "print(files_Oct5)" ] @@ -286,10 +278,7 @@ "# Fetch File Metadata to get min/max rescaling values (because the file is stored as float32)\n", "\n", "r = httpx.get(\n", - " f\"{titiler_endpoint}/cog/statistics\",\n", - " params = {\n", - " \"url\": _url(files[0])\n", - " }\n", + " f\"{titiler_endpoint}/cog/statistics\", params={\"url\": _url(files[0])}\n", ").json()\n", "\n", "print(json.dumps(r, indent=4))" @@ -303,25 +292,22 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": _url(files[2]),\n", " \"rescale\": \"0,3000000000000000\",\n", " \"colormap_name\": \"viridis\",\n", - " }\n", + " },\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=6\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=6\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"NASA\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"NASA\").add_to(m)\n", "\n", - "GeoJson(geojson, style_function=lambda feature: {\"fill\": False, \"color\": \"red\"}).add_to(m)\n", + "GeoJson(geojson, style_function=lambda feature: {\"fill\": False, \"color\": \"red\"}).add_to(\n", + " m\n", + ")\n", "\n", "m" ] @@ -347,6 +333,7 @@ "\n", "xmin, ymin, xmax, ymax = bounds\n", "\n", + "\n", "def fetch_bbox(file):\n", " url = f\"{titiler_endpoint}/cog/bbox/{xmin},{ymin},{xmax},{ymax}.npy\"\n", " params = {\n", @@ -362,6 +349,7 @@ " datetime.datetime.strptime(file.split(\"_\")[2].replace(\"m\", \"\"), \"%Y%m%d\"),\n", " )\n", "\n", + "\n", "# small tool to filter invalid response from the API\n", "def _filter_futures(tasks):\n", " for future in tasks:\n", @@ -397,25 +385,20 @@ "outputs": [], "source": [ "with futures.ThreadPoolExecutor(max_workers=10) as executor:\n", - " future_work = [\n", - " executor.submit(fetch_bbox, file) for file in files_15\n", - " ]\n", + " future_work = [executor.submit(fetch_bbox, file) for file in files_15]\n", "\n", " for f in tqdm(futures.as_completed(future_work), total=len(future_work)):\n", " pass\n", "\n", - "values, dates = zip(*list(_filter_futures(future_work)))\n", + "values, dates = zip(*list(_filter_futures(future_work)))\n", "\n", - "max_values = [\n", - " v[1]\n", - " for v in values\n", - "]\n", + "max_values = [v[1] for v in values]\n", "\n", "fig, ax1 = plt.subplots(dpi=300)\n", "fig.autofmt_xdate()\n", "\n", "ax1.plot(dates, max_values, label=\"No2\")\n", - "ax1.xaxis.set_major_locator(mdates.YearLocator(1,7))\n", + "ax1.xaxis.set_major_locator(mdates.YearLocator(1, 7))\n", "\n", "ax1.set_xlabel(\"Dates\")\n", "ax1.set_ylabel(\"No2\")\n", @@ -437,19 +420,14 @@ "outputs": [], "source": [ "with futures.ThreadPoolExecutor(max_workers=50) as executor:\n", - " future_work = [\n", - " executor.submit(fetch_bbox, file) for file in files\n", - " ]\n", + " future_work = [executor.submit(fetch_bbox, file) for file in files]\n", "\n", " for f in tqdm(futures.as_completed(future_work), total=len(future_work)):\n", " pass\n", "\n", - "values, dates = zip(*list(_filter_futures(future_work)))\n", + "values, dates = zip(*list(_filter_futures(future_work)))\n", "\n", - "max_values = [\n", - " v[1]\n", - " for v in values\n", - "]\n", + "max_values = [v[1] for v in values]\n", "\n", "fig, ax1 = plt.subplots(dpi=150)\n", "fig.autofmt_xdate()\n", diff --git a/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF_simple.ipynb b/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF_simple.ipynb index 61022008b..68fc67891 100644 --- a/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF_simple.ipynb +++ b/docs/src/examples/notebooks/Working_with_CloudOptimizedGeoTIFF_simple.ipynb @@ -50,7 +50,9 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "url = \"https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif\"" ] }, @@ -70,9 +72,9 @@ "# Fetch File Metadata to get min/max rescaling values (because the file is stored as float32)\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/info\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", @@ -95,9 +97,9 @@ "# Fetch File Metadata to get min/max rescaling values (because the file is stored as float32)\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/statistics\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(json.dumps(r, indent=4))" @@ -118,21 +120,16 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=13\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=13\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"DigitalGlobe OpenData\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"DigitalGlobe OpenData\").add_to(m)\n", "\n", "m" ] @@ -150,24 +147,25 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "url = \"https://data.geo.admin.ch/ch.swisstopo.swissalti3d/swissalti3d_2019_2573-1085/swissalti3d_2019_2573-1085_0.5_2056_5728.tif\"\n", "\n", "# Fetch File Metadata to get min/max rescaling values (because the file is stored as float32)\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/info\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(r)\n", "print(\"Data is of type:\", r[\"dtype\"])\n", "\n", "# This dataset has statistics metadata\n", - "minv, maxv = r[\"band_metadata\"][0][1][\"STATISTICS_MINIMUM\"], r[\"band_metadata\"][0][1][\"STATISTICS_MAXIMUM\"]\n", - "print(\"With values from \", minv, \"to \", maxv)\n", - "\n" + "minv, maxv = (\n", + " r[\"band_metadata\"][0][1][\"STATISTICS_MINIMUM\"],\n", + " r[\"band_metadata\"][0][1][\"STATISTICS_MAXIMUM\"],\n", + ")\n", + "print(\"With values from \", minv, \"to \", maxv)" ] }, { @@ -179,9 +177,9 @@ "# We could get the min/max values using the statistics endpoint\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/statistics\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(json.dumps(r[\"b1\"], indent=4))" @@ -205,22 +203,18 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url,\n", - " }\n", + " },\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"] + 1\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"] + 1,\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Swisstopo\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Swisstopo\").add_to(m)\n", "m" ] }, @@ -241,24 +235,16 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", - " \"url\": url,\n", - " \"rescale\": f\"{minv},{maxv}\",\n", - " \"colormap_name\": \"terrain\"\n", - " }\n", + " params={\"url\": url, \"rescale\": f\"{minv},{maxv}\", \"colormap_name\": \"terrain\"},\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"] + 1\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"] + 1,\n", ")\n", "\n", - "TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Swisstopo\"\n", - ").add_to(m)\n", + "TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Swisstopo\").add_to(m)\n", "m" ] }, @@ -282,34 +268,27 @@ "cmap = json.dumps(\n", " [\n", " # ([min, max], [r, g, b, a])\n", - " ([0, 1500], [255,255,204, 255]),\n", - " ([1500, 1700], [161,218,180, 255]),\n", - " ([1700, 1900], [65,182,196, 255]),\n", - " ([1900, 2000], [44,127,184, 255]),\n", - " ([2000, 3000], [37,52,148, 255]),\n", + " ([0, 1500], [255, 255, 204, 255]),\n", + " ([1500, 1700], [161, 218, 180, 255]),\n", + " ([1700, 1900], [65, 182, 196, 255]),\n", + " ([1900, 2000], [44, 127, 184, 255]),\n", + " ([2000, 3000], [37, 52, 148, 255]),\n", " ]\n", ")\n", "# https://colorbrewer2.org/#type=sequential&scheme=YlGnBu&n=5\n", "\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", - " \"url\": url,\n", - " \"colormap\": cmap\n", - " }\n", + " params={\"url\": url, \"colormap\": cmap},\n", ").json()\n", "\n", "bounds = r[\"bounds\"]\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=r[\"minzoom\"] + 1\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=r[\"minzoom\"] + 1,\n", ")\n", "\n", - "aod_layer = TileLayer(\n", - " tiles=r[\"tiles\"][0],\n", - " opacity=1,\n", - " attr=\"Swisstopo\"\n", - ")\n", + "aod_layer = TileLayer(tiles=r[\"tiles\"][0], opacity=1, attr=\"Swisstopo\")\n", "aod_layer.add_to(m)\n", "m" ] diff --git a/docs/src/examples/notebooks/Working_with_MosaicJSON.ipynb b/docs/src/examples/notebooks/Working_with_MosaicJSON.ipynb index e6ce954be..40a54b4f7 100644 --- a/docs/src/examples/notebooks/Working_with_MosaicJSON.ipynb +++ b/docs/src/examples/notebooks/Working_with_MosaicJSON.ipynb @@ -117,13 +117,13 @@ "session = boto3_session(region_name=\"us-west-2\")\n", "client = session.client(\"s3\")\n", "\n", - "bucket = \"noaa-eri-pds\" #https://registry.opendata.aws/omi-no2-nasa/\n", + "bucket = \"noaa-eri-pds\" # https://registry.opendata.aws/omi-no2-nasa/\n", "\n", "\n", "def list_objects(bucket, prefix):\n", " \"\"\"AWS s3 list objects.\"\"\"\n", "\n", - " paginator = client.get_paginator('list_objects_v2')\n", + " paginator = client.get_paginator(\"list_objects_v2\")\n", "\n", " files = []\n", " for subset in paginator.paginate(Bucket=bucket, Prefix=prefix):\n", @@ -131,6 +131,7 @@ "\n", " return [r[\"Key\"] for r in files]\n", "\n", + "\n", "files = list_objects(bucket, \"2020_Nashville_Tornado/20200307a_RGB\")\n", "files = [f\"s3://{bucket}/{f}\" for f in files if f.endswith(\".tif\")]\n", "\n", @@ -173,6 +174,7 @@ "from geojson_pydantic.features import Feature\n", "from geojson_pydantic.geometries import Polygon\n", "\n", + "\n", "def dms_to_degree(v: str) -> float:\n", " \"\"\"convert degree minute second to decimal degrees.\n", "\n", @@ -182,7 +184,10 @@ " minutes = int(v[3:5])\n", " seconds = int(v[5:7])\n", " direction = v[-1].upper()\n", - " return (float(deg) + float(minutes)/60 + float(seconds)/(60*60)) * (-1 if direction in ['W', 'S'] else 1)\n", + " return (float(deg) + float(minutes) / 60 + float(seconds) / (60 * 60)) * (\n", + " -1 if direction in [\"W\", \"S\"] else 1\n", + " )\n", + "\n", "\n", "def fname_to_feature(src_path: str) -> Feature:\n", " bname = os.path.basename(src_path)\n", @@ -193,16 +198,14 @@ " lat = dms_to_degree(\"0\" + lat_dms)\n", "\n", " return Feature(\n", - " geometry=Polygon.from_bounds(\n", - " lon, lat - 0.025, lon + 0.025, lat\n", - " ),\n", + " geometry=Polygon.from_bounds(lon, lat - 0.025, lon + 0.025, lat),\n", " properties={\n", " \"path\": src_path,\n", - " }\n", + " },\n", " )\n", - "features = [\n", - " fname_to_feature(f).dict(exclude_none=True) for f in files\n", - "]\n", + "\n", + "\n", + "features = [fname_to_feature(f).dict(exclude_none=True) for f in files]\n", "\n", "# OR We could use Rasterio/rio-tiler\n", "\n", @@ -230,20 +233,23 @@ "metadata": {}, "outputs": [], "source": [ - "geojson = {'type': 'FeatureCollection', 'features': features}\n", + "geojson = {\"type\": \"FeatureCollection\", \"features\": features}\n", "\n", "bounds = featureBounds(geojson)\n", "\n", "m = Map(\n", " tiles=\"OpenStreetMap\",\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=6\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=6,\n", ")\n", "\n", "geo_json = GeoJson(\n", " data=geojson,\n", " style_function=lambda x: {\n", - " 'opacity': 1, 'dashArray': '1', 'fillOpacity': 0, 'weight': 1\n", + " \"opacity\": 1,\n", + " \"dashArray\": \"1\",\n", + " \"fillOpacity\": 0,\n", + " \"weight\": 1,\n", " },\n", ")\n", "geo_json.add_to(m)\n", @@ -279,10 +285,11 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "# We are creating the mosaicJSON using the features we created earlier\n", "# by default MosaicJSON.from_feature will look in feature.properties.path to get the path of the dataset\n", - "mosaicdata = MosaicJSON.from_features(features, minzoom=info.minzoom, maxzoom=info.maxzoom)\n", + "mosaicdata = MosaicJSON.from_features(\n", + " features, minzoom=info.minzoom, maxzoom=info.maxzoom\n", + ")\n", "with MosaicBackend(\"NOAA_Nashville_Tornado.json.gz\", mosaic_def=mosaicdata) as mosaic:\n", " mosaic.write(overwrite=True)\n", " print(mosaic.info())" @@ -296,20 +303,21 @@ }, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/mosaicjson/WebMercatorQuad/tilejson.json\",\n", " params={\n", " # For this demo we are use the same mosaic but stored on the web\n", " \"url\": \"https://gist.githubusercontent.com/vincentsarago/c6ace3ccd29a82a4a5531693bbcd61fc/raw/e0d0174a64a9acd2fb820f2c65b1830aab80f52b/NOAA_Nashville_Tornado.json\"\n", - " }\n", + " },\n", ").json()\n", "print(r)\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=13\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=13\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -317,13 +325,16 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"NOAA\"\n", + " attr=\"NOAA\",\n", ")\n", "\n", "geo_json = GeoJson(\n", " data=geojson,\n", " style_function=lambda x: {\n", - " 'opacity': 1, 'dashArray': '1', 'fillOpacity': 0, 'weight': 1\n", + " \"opacity\": 1,\n", + " \"dashArray\": \"1\",\n", + " \"fillOpacity\": 0,\n", + " \"weight\": 1,\n", " },\n", ")\n", "tiles.add_to(m)\n", diff --git a/docs/src/examples/notebooks/Working_with_NumpyTile.ipynb b/docs/src/examples/notebooks/Working_with_NumpyTile.ipynb index 6c6b4944e..d3e46e00e 100755 --- a/docs/src/examples/notebooks/Working_with_NumpyTile.ipynb +++ b/docs/src/examples/notebooks/Working_with_NumpyTile.ipynb @@ -54,7 +54,9 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "url = \"https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif\"" ] }, @@ -88,7 +90,9 @@ "# Call TiTiler endpoint using the first tile\n", "\n", "tile = tiles[0]\n", - "r = httpx.get(f\"{titiler_endpoint}/cog/tiles/WebMercatorQuad/{tile.z}/{tile.x}/{tile.y}.npy?url={url}\")" + "r = httpx.get(\n", + " f\"{titiler_endpoint}/cog/tiles/WebMercatorQuad/{tile.z}/{tile.x}/{tile.y}.npy?url={url}\"\n", + ")" ] }, { diff --git a/docs/src/examples/notebooks/Working_with_STAC.ipynb b/docs/src/examples/notebooks/Working_with_STAC.ipynb index e502e1748..65755832e 100644 --- a/docs/src/examples/notebooks/Working_with_STAC.ipynb +++ b/docs/src/examples/notebooks/Working_with_STAC.ipynb @@ -150,7 +150,9 @@ "outputs": [], "source": [ "# Endpoint variables\n", - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "stac_endpoint = \"https://earth-search.aws.element84.com/v0/search\"" ] }, @@ -174,48 +176,33 @@ "outputs": [], "source": [ "geojson = {\n", - " \"type\": \"FeatureCollection\",\n", - " \"features\": [\n", - " {\n", - " \"type\": \"Feature\",\n", - " \"properties\": {},\n", - " \"geometry\": {\n", - " \"type\": \"Polygon\",\n", - " \"coordinates\": [\n", - " [\n", - " [\n", - " 30.810813903808594,\n", - " 29.454247067148533\n", - " ],\n", - " [\n", - " 30.88600158691406,\n", - " 29.454247067148533\n", - " ],\n", - " [\n", - " 30.88600158691406,\n", - " 29.51879923863822\n", - " ],\n", - " [\n", - " 30.810813903808594,\n", - " 29.51879923863822\n", - " ],\n", - " [\n", - " 30.810813903808594,\n", - " 29.454247067148533\n", - " ]\n", - " ]\n", - " ]\n", - " }\n", - " }\n", - " ]\n", + " \"type\": \"FeatureCollection\",\n", + " \"features\": [\n", + " {\n", + " \"type\": \"Feature\",\n", + " \"properties\": {},\n", + " \"geometry\": {\n", + " \"type\": \"Polygon\",\n", + " \"coordinates\": [\n", + " [\n", + " [30.810813903808594, 29.454247067148533],\n", + " [30.88600158691406, 29.454247067148533],\n", + " [30.88600158691406, 29.51879923863822],\n", + " [30.810813903808594, 29.51879923863822],\n", + " [30.810813903808594, 29.454247067148533],\n", + " ]\n", + " ],\n", + " },\n", + " }\n", + " ],\n", "}\n", "\n", "bounds = featureBounds(geojson)\n", "\n", "m = Map(\n", " tiles=\"OpenStreetMap\",\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=11\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=11,\n", ")\n", "\n", "geo_json = GeoJson(data=geojson)\n", @@ -238,24 +225,30 @@ }, "outputs": [], "source": [ - "start = datetime.datetime.strptime(\"2019-01-01\", \"%Y-%m-%d\").strftime(\"%Y-%m-%dT00:00:00Z\")\n", - "end = datetime.datetime.strptime(\"2019-12-11\", \"%Y-%m-%d\").strftime(\"%Y-%m-%dT23:59:59Z\")\n", + "start = datetime.datetime.strptime(\"2019-01-01\", \"%Y-%m-%d\").strftime(\n", + " \"%Y-%m-%dT00:00:00Z\"\n", + ")\n", + "end = datetime.datetime.strptime(\"2019-12-11\", \"%Y-%m-%d\").strftime(\n", + " \"%Y-%m-%dT23:59:59Z\"\n", + ")\n", "\n", "# POST body\n", "query = {\n", " \"collections\": [\"sentinel-s2-l2a-cogs\"],\n", " \"datetime\": f\"{start}/{end}\",\n", " \"query\": {\n", - " \"eo:cloud_cover\": {\n", - " \"lt\": 5\n", - " },\n", + " \"eo:cloud_cover\": {\"lt\": 5},\n", " },\n", " \"intersects\": geojson[\"features\"][0][\"geometry\"],\n", " \"limit\": 100,\n", " \"fields\": {\n", - " 'include': ['id', 'properties.datetime', 'properties.eo:cloud_cover'], # This will limit the size of returned body\n", - " 'exclude': ['assets', 'links'] # This will limit the size of returned body\n", - " }\n", + " \"include\": [\n", + " \"id\",\n", + " \"properties.datetime\",\n", + " \"properties.eo:cloud_cover\",\n", + " ], # This will limit the size of returned body\n", + " \"exclude\": [\"assets\", \"links\"], # This will limit the size of returned body\n", + " },\n", "}\n", "\n", "# POST Headers\n", @@ -285,14 +278,17 @@ "source": [ "m = Map(\n", " tiles=\"OpenStreetMap\",\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=8\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=8,\n", ")\n", "\n", "geo_json = GeoJson(\n", " data=data,\n", " style_function=lambda x: {\n", - " 'opacity': 1, 'dashArray': '1', 'fillOpacity': 0, 'weight': 1\n", + " \"opacity\": 1,\n", + " \"dashArray\": \"1\",\n", + " \"fillOpacity\": 0,\n", + " \"weight\": 1,\n", " },\n", ")\n", "geo_json.add_to(m)\n", @@ -315,7 +311,14 @@ "fig = plt.figure(dpi=100)\n", "fig.autofmt_xdate()\n", "ax = fig.add_subplot(1, 1, 1)\n", - "ax.plot(dates, cloudcover, label=\"Cloud Cover\", color=\"tab:red\", linewidth=0.4, linestyle=\"-.\")\n", + "ax.plot(\n", + " dates,\n", + " cloudcover,\n", + " label=\"Cloud Cover\",\n", + " color=\"tab:red\",\n", + " linewidth=0.4,\n", + " linestyle=\"-.\",\n", + ")\n", "\n", "ax.legend()" ] @@ -362,26 +365,37 @@ "outputs": [], "source": [ "# Get Tile URL\n", - "item = url_template.format(id=sceneid[-1])\n", + "item = url_template.format(id=sceneid[-1])\n", "print(item)\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = (\n", + " params=(\n", " (\"url\", item),\n", " # Simple RGB combination (True Color)\n", - " (\"assets\", \"B04\"), # red, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"assets\", \"B03\"), # green, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"assets\", \"B02\"), # blue, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"color_formula\", \"Gamma RGB 3.5 Saturation 1.7 Sigmoidal RGB 15 0.35\"), # We use a rio-color formula to make the tiles look nice\n", + " (\n", + " \"assets\",\n", + " \"B04\",\n", + " ), # red, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"assets\",\n", + " \"B03\",\n", + " ), # green, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"assets\",\n", + " \"B02\",\n", + " ), # blue, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"color_formula\",\n", + " \"Gamma RGB 3.5 Saturation 1.7 Sigmoidal RGB 15 0.35\",\n", + " ), # We use a rio-color formula to make the tiles look nice\n", " (\"minzoom\", 8), # By default titiler will use 0\n", - " (\"maxzoom\", 14), # By default titiler will use 24\n", - " )\n", + " (\"maxzoom\", 14), # By default titiler will use 24\n", + " ),\n", ").json()\n", "print(r)\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -389,7 +403,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"Digital Earth Africa\"\n", + " attr=\"Digital Earth Africa\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -405,22 +419,33 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = (\n", + " params=(\n", " (\"url\", url_template.format(id=sceneid[0])),\n", " # False Color Infrared\n", - " (\"assets\", \"B08\"), # nir, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"assets\", \"B04\"), # red, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"assets\", \"B03\"), # green, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", - " (\"color_formula\", \"Gamma RGB 3.5 Saturation 1.7 Sigmoidal RGB 15 0.35\"), # We use a rio-color formula to make the tiles look nice\n", + " (\n", + " \"assets\",\n", + " \"B08\",\n", + " ), # nir, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"assets\",\n", + " \"B04\",\n", + " ), # red, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"assets\",\n", + " \"B03\",\n", + " ), # green, in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " (\n", + " \"color_formula\",\n", + " \"Gamma RGB 3.5 Saturation 1.7 Sigmoidal RGB 15 0.35\",\n", + " ), # We use a rio-color formula to make the tiles look nice\n", " (\"minzoom\", 8), # By default titiler will use 0\n", - " (\"maxzoom\", 14), # By default titiler will use 24\n", - " )\n", + " (\"maxzoom\", 14), # By default titiler will use 24\n", + " ),\n", ").json()\n", "print(r)\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -428,7 +453,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"Digital Earth Africa\"\n", + " attr=\"Digital Earth Africa\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -444,7 +469,7 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": url_template.format(id=sceneid[0]),\n", " \"expression\": \"(B08-B04)/(B08+B04)\", # NDVI (nir-red)/(nir+red), in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", " # We need to tell rio-tiler that each asset is a Band\n", @@ -452,15 +477,14 @@ " \"asset_as_band\": True,\n", " \"rescale\": \"-1,1\",\n", " \"minzoom\": 8, # By default titiler will use 0\n", - " \"maxzoom\": 14, # By default titiler will use 24\n", + " \"maxzoom\": 14, # By default titiler will use 24\n", " \"colormap_name\": \"viridis\",\n", - " }\n", + " },\n", ").json()\n", "print(r)\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -468,7 +492,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"Digital Earth Africa\"\n", + " attr=\"Digital Earth Africa\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -489,7 +513,7 @@ "metadata": {}, "outputs": [], "source": [ - "def fetch_bbox_array(sceneid, bbox, assets = None, expression = None, **kwargs):\n", + "def fetch_bbox_array(sceneid, bbox, assets=None, expression=None, **kwargs):\n", " \"\"\"Helper function to fetch and decode Numpy array using Titiler endpoint.\"\"\"\n", " # STAC ITEM URL\n", " stac_item = f\"https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/{sceneid}\"\n", @@ -500,9 +524,12 @@ " params = ((\"url\", stac_item), (\"max_size\", 1024))\n", " if assets:\n", " for asset in assets:\n", - " params += ((\"assets\", asset), )\n", + " params += ((\"assets\", asset),)\n", " elif expression:\n", - " params += ((\"expression\", expression), (\"asset_as_band\", True),)\n", + " params += (\n", + " (\"expression\", expression),\n", + " (\"asset_as_band\", True),\n", + " )\n", " else:\n", " raise Exception(\"Missing band or expression input\")\n", "\n", @@ -515,6 +542,7 @@ "\n", " return sceneid, data[0:-1], data[-1]\n", "\n", + "\n", "def _filter_futures(tasks):\n", " for future in tasks:\n", " try:\n", @@ -522,6 +550,7 @@ " except Exception:\n", " pass\n", "\n", + "\n", "def _stats(data, mask):\n", " arr = numpy.ma.array(data)\n", " arr.mask = mask == 0\n", @@ -537,7 +566,9 @@ "outputs": [], "source": [ "# Fetch one data\n", - "_, data, mask = fetch_bbox_array(sceneid[0], bounds, assets=[\"B02\"], width=128, height=128)\n", + "_, data, mask = fetch_bbox_array(\n", + " sceneid[0], bounds, assets=[\"B02\"], width=128, height=128\n", + ")\n", "\n", "print(data.shape)\n", "print(mask.shape)\n", @@ -560,30 +591,32 @@ "bbox_worker = partial(\n", " fetch_bbox_array,\n", " bbox=bounds,\n", - " assets=(\"B04\", \"B03\", \"B02\"), #(\"red\", \"green\", \"blue\"), in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", + " assets=(\n", + " \"B04\",\n", + " \"B03\",\n", + " \"B02\",\n", + " ), # (\"red\", \"green\", \"blue\"), in next STAC item version (see https://github.com/cogeotiff/rio-tiler-pds/issues/63)\n", " color_formula=\"gamma RGB 3.5, saturation 1.7, sigmoidal RGB 15 0.35\",\n", " width=64,\n", " height=64,\n", ")\n", "\n", "with futures.ThreadPoolExecutor(max_workers=10) as executor:\n", - " future_work = [\n", - " executor.submit(bbox_worker, scene) for scene in sceneid\n", - " ]\n", + " future_work = [executor.submit(bbox_worker, scene) for scene in sceneid]\n", "\n", " for f in tqdm(futures.as_completed(future_work), total=len(future_work)):\n", " pass\n", "\n", - "results_rgb = list(_filter_futures(future_work))\n", + "results_rgb = list(_filter_futures(future_work))\n", "\n", "print(\"diplay all results\")\n", "\n", - "fig = plt.figure(figsize=(10,20))\n", + "fig = plt.figure(figsize=(10, 20))\n", "col = 5\n", "row = math.ceil(len(dates) / col)\n", "for i in range(1, len(results_rgb) + 1):\n", " fig.add_subplot(row, col, i)\n", - " plt.imshow(reshape_as_image(results_rgb[i-1][1]))" + " plt.imshow(reshape_as_image(results_rgb[i - 1][1]))" ] }, { @@ -605,21 +638,19 @@ ")\n", "\n", "with futures.ThreadPoolExecutor(max_workers=10) as executor:\n", - " future_work = [\n", - " executor.submit(bbox_worker, scene) for scene in sceneid\n", - " ]\n", + " future_work = [executor.submit(bbox_worker, scene) for scene in sceneid]\n", "\n", " for f in tqdm(futures.as_completed(future_work), total=len(future_work)):\n", " pass\n", "\n", - "results_ndvi = list(_filter_futures(future_work))\n", + "results_ndvi = list(_filter_futures(future_work))\n", "\n", - "fig = plt.figure(figsize=(10,20))\n", + "fig = plt.figure(figsize=(10, 20))\n", "col = 5\n", "row = math.ceil(len(dates) / col)\n", "for i in range(1, len(results_rgb) + 1):\n", " fig.add_subplot(row, col, i)\n", - " plt.imshow(results_ndvi[i-1][1][0])" + " plt.imshow(results_ndvi[i - 1][1][0])" ] }, { diff --git a/docs/src/examples/notebooks/Working_with_STAC_simple.ipynb b/docs/src/examples/notebooks/Working_with_STAC_simple.ipynb index d43f62cb4..ffc594007 100644 --- a/docs/src/examples/notebooks/Working_with_STAC_simple.ipynb +++ b/docs/src/examples/notebooks/Working_with_STAC_simple.ipynb @@ -68,7 +68,9 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "stac_item = \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2A_30TVT_20221112_0_L2A\"" ] }, @@ -107,8 +109,8 @@ "\n", "m = Map(\n", " tiles=\"OpenStreetMap\",\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=8\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2),\n", + " zoom_start=8,\n", ")\n", "\n", "geo_json = GeoJson(data=item)\n", @@ -127,11 +129,14 @@ "# Get Tile URL\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/info\",\n", - " params = (\n", + " params=(\n", " (\"url\", stac_item),\n", " # Get info for multiple assets\n", - " (\"assets\",\"visual\"), (\"assets\",\"red\"), (\"assets\",\"blue\"), (\"assets\",\"green\"),\n", - " )\n", + " (\"assets\", \"visual\"),\n", + " (\"assets\", \"red\"),\n", + " (\"assets\", \"blue\"),\n", + " (\"assets\", \"green\"),\n", + " ),\n", ").json()\n", "print(r)" ] @@ -151,17 +156,16 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": stac_item,\n", " \"assets\": \"visual\",\n", " \"minzoom\": 8, # By default titiler will use 0\n", - " \"maxzoom\": 14, # By default titiler will use 24\n", - " }\n", + " \"maxzoom\": 14, # By default titiler will use 24\n", + " },\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -169,7 +173,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"ESA\"\n", + " attr=\"ESA\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -191,18 +195,17 @@ "# Get Tile URL\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = {\n", + " params={\n", " \"url\": stac_item,\n", " \"assets\": \"visual\",\n", " \"asset_bidx\": \"visual|3,1,2\",\n", " \"minzoom\": 8, # By default titiler will use 0\n", - " \"maxzoom\": 14, # By default titiler will use 24\n", - " }\n", + " \"maxzoom\": 14, # By default titiler will use 24\n", + " },\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=12\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=12\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -210,7 +213,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"ESA\"\n", + " attr=\"ESA\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -225,7 +228,7 @@ "# Get Tile URL\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = (\n", + " params=(\n", " (\"url\", stac_item),\n", " (\"assets\", \"red\"),\n", " (\"assets\", \"green\"),\n", @@ -238,12 +241,11 @@ " (\"minzoom\", 8),\n", " (\"maxzoom\", 14),\n", " (\"rescale\", \"0,2000\"),\n", - " )\n", + " ),\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=11\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=11\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -251,7 +253,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"ESA\"\n", + " attr=\"ESA\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -273,7 +275,7 @@ "# Get Tile URL\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = (\n", + " params=(\n", " (\"url\", stac_item),\n", " (\"expression\", \"(nir-red)/(nir+red)\"), # NDVI\n", " # We need to tell rio-tiler that each asset is a Band\n", @@ -283,12 +285,11 @@ " (\"minzoom\", 8),\n", " (\"maxzoom\", 14),\n", " (\"colormap_name\", \"viridis\"),\n", - " )\n", + " ),\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -296,7 +297,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"ESA\"\n", + " attr=\"ESA\",\n", ")\n", "tiles.add_to(m)\n", "m" @@ -318,19 +319,18 @@ "# Get Tile URL\n", "r = httpx.get(\n", " f\"{titiler_endpoint}/stac/WebMercatorQuad/tilejson.json\",\n", - " params = (\n", + " params=(\n", " (\"url\", stac_item),\n", " (\"expression\", \"(nir_b1-red_b1)/(nir_b1+red_b1)\"), # NDVI\n", " (\"rescale\", \"-1,1\"),\n", " (\"minzoom\", 8),\n", " (\"maxzoom\", 14),\n", " (\"colormap_name\", \"viridis\"),\n", - " )\n", + " ),\n", ").json()\n", "\n", "m = Map(\n", - " location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),\n", - " zoom_start=10\n", + " location=((bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2), zoom_start=10\n", ")\n", "\n", "tiles = TileLayer(\n", @@ -338,7 +338,7 @@ " min_zoom=r[\"minzoom\"],\n", " max_zoom=r[\"maxzoom\"],\n", " opacity=1,\n", - " attr=\"ESA\"\n", + " attr=\"ESA\",\n", ")\n", "tiles.add_to(m)\n", "m" diff --git a/docs/src/examples/notebooks/Working_with_Statistics.ipynb b/docs/src/examples/notebooks/Working_with_Statistics.ipynb index 947d91eec..83adc19c0 100644 --- a/docs/src/examples/notebooks/Working_with_Statistics.ipynb +++ b/docs/src/examples/notebooks/Working_with_Statistics.ipynb @@ -40,7 +40,9 @@ "import httpx\n", "import json\n", "\n", - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", "cog_url = \"https://opendata.digitalglobe.com/events/mauritius-oil-spill/post-event/2020-08-12/105001001F1B5B00/105001001F1B5B00.tif\"" ] }, @@ -76,9 +78,9 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/info\",\n", - " params = {\n", + " params={\n", " \"url\": cog_url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(json.dumps(r))" @@ -114,9 +116,9 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/statistics\",\n", - " params = {\n", + " params={\n", " \"url\": cog_url,\n", - " }\n", + " },\n", ").json()\n", "\n", "print(json.dumps(r))" @@ -147,11 +149,11 @@ "source": [ "r = httpx.get(\n", " f\"{titiler_endpoint}/cog/statistics\",\n", - " params = {\n", + " params={\n", " \"url\": cog_url,\n", - " \"expression\": \"(b2-b1)/(b1+b2-b3)\", # expression for the VARI\n", - " \"histogram_range\": \"-1,1\"\n", - " }\n", + " \"expression\": \"(b2-b1)/(b1+b2-b3)\", # expression for the VARI\n", + " \"histogram_range\": \"-1,1\",\n", + " },\n", ").json()\n", "\n", "print(json.dumps(r))" @@ -244,14 +246,14 @@ "r = httpx.post(\n", " f\"{titiler_endpoint}/cog/statistics\",\n", " data=mahebourg,\n", - " params = {\n", + " params={\n", " \"url\": cog_url,\n", " \"max_size\": 1024,\n", " },\n", " timeout=20,\n", ").json()\n", "\n", - "print(json.dumps(r))\n" + "print(json.dumps(r))" ] }, { diff --git a/docs/src/examples/notebooks/Working_with_nonWebMercatorTMS.ipynb b/docs/src/examples/notebooks/Working_with_nonWebMercatorTMS.ipynb index 21a4daedc..e2744b8c3 100644 --- a/docs/src/examples/notebooks/Working_with_nonWebMercatorTMS.ipynb +++ b/docs/src/examples/notebooks/Working_with_nonWebMercatorTMS.ipynb @@ -51,7 +51,7 @@ " TileLayer,\n", " WMSLayer,\n", " GeoJSON,\n", - " projections\n", + " projections,\n", ")" ] }, @@ -61,8 +61,10 @@ "metadata": {}, "outputs": [], "source": [ - "titiler_endpoint = \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", - "url = \"https://s3.amazonaws.com/opendata.remotepixel.ca/cogs/natural_earth/world.tif\" # Natural Earth WORLD tif" + "titiler_endpoint = (\n", + " \"https://titiler.xyz\" # Developmentseed Demo endpoint. Please be kind.\n", + ")\n", + "url = \"https://s3.amazonaws.com/opendata.remotepixel.ca/cogs/natural_earth/world.tif\" # Natural Earth WORLD tif" ] }, { @@ -104,7 +106,7 @@ "outputs": [], "source": [ "r = httpx.get(\n", - " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\", params = {\"url\": url}\n", + " f\"{titiler_endpoint}/cog/WebMercatorQuad/tilejson.json\", params={\"url\": url}\n", ").json()\n", "\n", "m = Map(center=(0, 0), zoom=2, basemap={}, crs=projections.EPSG3857)\n", @@ -130,7 +132,7 @@ "outputs": [], "source": [ "r = httpx.get(\n", - " f\"{titiler_endpoint}/cog/WorldCRS84Quad/tilejson.json\", params = {\"url\": url}\n", + " f\"{titiler_endpoint}/cog/WorldCRS84Quad/tilejson.json\", params={\"url\": url}\n", ").json()\n", "\n", "m = Map(center=(0, 0), zoom=1, basemap={}, crs=projections.EPSG4326)\n", @@ -156,22 +158,15 @@ "outputs": [], "source": [ "r = httpx.get(\n", - " f\"{titiler_endpoint}/cog/EuropeanETRS89_LAEAQuad/tilejson.json\", params = {\"url\": url}\n", + " f\"{titiler_endpoint}/cog/EuropeanETRS89_LAEAQuad/tilejson.json\", params={\"url\": url}\n", ").json()\n", "\n", "my_projection = {\n", - " 'name': 'EPSG:3035',\n", - " 'custom': True, #This is important, it tells ipyleaflet that this projection is not on the predefined ones.\n", - " 'proj4def': '+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',\n", - " 'origin': [6500000.0, 5500000.0],\n", - " 'resolutions': [\n", - " 8192.0,\n", - " 4096.0,\n", - " 2048.0,\n", - " 1024.0,\n", - " 512.0,\n", - " 256.0\n", - " ]\n", + " \"name\": \"EPSG:3035\",\n", + " \"custom\": True, # This is important, it tells ipyleaflet that this projection is not on the predefined ones.\n", + " \"proj4def\": \"+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\",\n", + " \"origin\": [6500000.0, 5500000.0],\n", + " \"resolutions\": [8192.0, 4096.0, 2048.0, 1024.0, 512.0, 256.0],\n", "}\n", "\n", "m = Map(center=(50, 65), zoom=0, basemap={}, crs=my_projection)\n", diff --git a/pyproject.toml b/pyproject.toml index 6f3c5f094..f176dfdb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,7 @@ known_third_party = [ ] default_section = "THIRDPARTY" -[tool.ruff] +[tool.ruff.lint] select = [ "D1", # pydocstyle errors "E", # pycodestyle errors @@ -111,6 +111,9 @@ ignore = [ "B008", # do not perform function calls in argument defaults "B905", # ignore zip() without an explicit strict= parameter, only support with python >3.10 ] +exclude = [ + "*.ipynb" +] [tool.mypy] no_implicit_optional = true diff --git a/src/titiler/application/tests/conftest.py b/src/titiler/application/tests/conftest.py index 967990102..b883ab570 100644 --- a/src/titiler/application/tests/conftest.py +++ b/src/titiler/application/tests/conftest.py @@ -34,6 +34,7 @@ def app(set_env) -> TestClient: def mock_RequestGet(src_path): """Mock Requests.""" + # HTTP class MockResponse: def __init__(self, data): diff --git a/src/titiler/application/tests/routes/test_stac.py b/src/titiler/application/tests/routes/test_stac.py index 395daff53..f159a40c7 100644 --- a/src/titiler/application/tests/routes/test_stac.py +++ b/src/titiler/application/tests/routes/test_stac.py @@ -1,6 +1,5 @@ """test /COG endpoints.""" - from typing import Dict from unittest.mock import patch diff --git a/src/titiler/application/titiler/application/main.py b/src/titiler/application/titiler/application/main.py index 9594277de..1a0518c82 100644 --- a/src/titiler/application/titiler/application/main.py +++ b/src/titiler/application/titiler/application/main.py @@ -1,4 +1,5 @@ """titiler app.""" + import logging import re diff --git a/src/titiler/core/tests/test_cache_middleware.py b/src/titiler/core/tests/test_cache_middleware.py index f5489da26..d6b17d095 100644 --- a/src/titiler/core/tests/test_cache_middleware.py +++ b/src/titiler/core/tests/test_cache_middleware.py @@ -1,6 +1,5 @@ """Test titiler.core.CacheControlMiddleware.""" - from fastapi import FastAPI, Path from starlette.responses import Response from starlette.testclient import TestClient diff --git a/src/titiler/core/tests/test_dependencies.py b/src/titiler/core/tests/test_dependencies.py index bfcd9069a..e0b636818 100644 --- a/src/titiler/core/tests/test_dependencies.py +++ b/src/titiler/core/tests/test_dependencies.py @@ -147,7 +147,6 @@ def test_default(): @dataclass class dep(dependencies.DefaultDependency): - v: int # make sure we can unpack the class diff --git a/src/titiler/core/tests/test_factories.py b/src/titiler/core/tests/test_factories.py index b35b1ce91..5f163241a 100644 --- a/src/titiler/core/tests/test_factories.py +++ b/src/titiler/core/tests/test_factories.py @@ -1638,7 +1638,6 @@ def test_TilerFactory_WithGdalEnv(): assert response.json()["overviews"] class ReaddirType(str, Enum): - false = "false" true = "true" empty_dir = "empty_dir" diff --git a/src/titiler/core/titiler/core/dependencies.py b/src/titiler/core/titiler/core/dependencies.py index 110b677cc..9fc96b88a 100644 --- a/src/titiler/core/titiler/core/dependencies.py +++ b/src/titiler/core/titiler/core/dependencies.py @@ -72,6 +72,7 @@ def keys(self): warnings.warn( "Dict unpacking will be removed for `DefaultDependency` in titiler 0.19.0", DeprecationWarning, + stacklevel=1, ) return self.__dict__.keys() @@ -233,6 +234,7 @@ def __post_init__(self): warnings.warn( "Both `asset_bidx` and `bidx` passed; only `asset_bidx` will be considered.", UserWarning, + stacklevel=1, ) @@ -249,6 +251,7 @@ def __post_init__(self): warnings.warn( "Both `asset_bidx` and `bidx` passed; only `asset_bidx` will be considered.", UserWarning, + stacklevel=1, ) @@ -305,6 +308,7 @@ def __post_init__(self): warnings.warn( "Both `asset_bidx` and `bidx` passed; only `asset_bidx` will be considered.", UserWarning, + stacklevel=1, ) @@ -434,7 +438,7 @@ class ImageRenderingParams(DefaultDependency): ] = None -RescaleType = List[Tuple[float, ...]] +RescaleType = List[Tuple[float, float]] def RescalingParams( @@ -460,6 +464,7 @@ def RescalingParams( assert ( len(parsed) == 2 ), f"Invalid rescale values: {rescale}, should be of form ['min,max', 'min,max'] or [[min,max], [min, max]]" + rescale_array.append(parsed) return rescale_array diff --git a/src/titiler/core/titiler/core/errors.py b/src/titiler/core/titiler/core/errors.py index 678aa01ac..3d517f284 100644 --- a/src/titiler/core/titiler/core/errors.py +++ b/src/titiler/core/titiler/core/errors.py @@ -66,5 +66,5 @@ def add_exception_handlers( """ Add exception handlers to the FastAPI app. """ - for (exc, code) in status_codes.items(): + for exc, code in status_codes.items(): app.add_exception_handler(exc, exception_handler_factory(code)) diff --git a/src/titiler/core/titiler/core/factory.py b/src/titiler/core/titiler/core/factory.py index 7f32e5abb..d1b68b44b 100644 --- a/src/titiler/core/titiler/core/factory.py +++ b/src/titiler/core/titiler/core/factory.py @@ -274,9 +274,9 @@ class TilerFactory(BaseFactory): img_part_dependency: Type[DefaultDependency] = PartFeatureParams # Post Processing Dependencies (algorithm) - process_dependency: Callable[ - ..., Optional[BaseAlgorithm] - ] = available_algorithms.dependency + process_dependency: Callable[..., Optional[BaseAlgorithm]] = ( + available_algorithms.dependency + ) # Image rendering Dependencies rescale_dependency: Callable[..., Optional[RescaleType]] = RescalingParams @@ -671,8 +671,11 @@ async def tileset( } ) - qs = [(key, value) for (key, value) in request.query_params._list] - query_string = f"?{urlencode(qs)}" if qs else "" + query_string = ( + f"?{urlencode(request.query_params._list)}" + if request.query_params._list + else "" + ) links = [ { @@ -1440,12 +1443,7 @@ def info_geojson( type="Feature", bbox=bounds, geometry=geometry, - properties={ - asset: asset_info - for asset, asset_info in src_dst.info( - **asset_params.as_dict() - ).items() - }, + properties=src_dst.info(**asset_params.as_dict()), ) @self.router.get( diff --git a/src/titiler/core/titiler/core/models/OGC.py b/src/titiler/core/titiler/core/models/OGC.py index 87a399e1d..6c26175c0 100644 --- a/src/titiler/core/titiler/core/models/OGC.py +++ b/src/titiler/core/titiler/core/models/OGC.py @@ -168,9 +168,9 @@ class BoundingBox(BaseModel): ), ] crs: Annotated[Optional[CRSType], Field(json_schema_extra={"title": "CRS"})] = None - orderedAxes: Annotated[ - Optional[List[str]], Field(max_length=2, min_length=2) - ] = None + orderedAxes: Annotated[Optional[List[str]], Field(max_length=2, min_length=2)] = ( + None + ) # Ref: https://github.com/opengeospatial/ogcapi-tiles/blob/master/openapi/schemas/tms/propertiesSchema.yaml diff --git a/src/titiler/core/titiler/core/routing.py b/src/titiler/core/titiler/core/routing.py index d0dcf3e46..7c85991ce 100644 --- a/src/titiler/core/titiler/core/routing.py +++ b/src/titiler/core/titiler/core/routing.py @@ -29,6 +29,7 @@ def apiroute_factory(env: Optional[Dict] = None) -> Type[APIRoute]: "'apiroute_factory' has been deprecated and will be removed" "in titiler 0.1.0. Please see `environment_dependency` option in endpoint factories.", DeprecationWarning, + stacklevel=1, ) class EnvAPIRoute(APIRoute): @@ -82,7 +83,8 @@ def add_route_dependencies( route.dependant.dependencies.insert( # type: ignore 0, get_parameterless_sub_dependant( - depends=depends, path=route.path_format # type: ignore + depends=depends, + path=route.path_format, # type: ignore ), ) diff --git a/src/titiler/core/titiler/core/utils.py b/src/titiler/core/titiler/core/utils.py index aa234cd0d..637b1831d 100644 --- a/src/titiler/core/titiler/core/utils.py +++ b/src/titiler/core/titiler/core/utils.py @@ -73,6 +73,7 @@ def render_image( warnings.warn( f"Invalid type: `{data.dtype}` for the `{output_format}` driver. Data will be rescaled using min/max type bounds or dataset_statistics.", InvalidDatatypeWarning, + stacklevel=1, ) data = rescale_array(data, mask, in_range=datatype_range) @@ -84,6 +85,7 @@ def render_image( warnings.warn( f"Invalid type: `{data.dtype}` for the `{output_format}` driver. Data will be rescaled using min/max type bounds or dataset_statistics.", InvalidDatatypeWarning, + stacklevel=1, ) data = rescale_array(data, mask, in_range=datatype_range) @@ -95,6 +97,7 @@ def render_image( warnings.warn( f"Invalid type: `{data.dtype}` for the `{output_format}` driver. Data will be rescaled using min/max type bounds or dataset_statistics.", InvalidDatatypeWarning, + stacklevel=1, ) data = rescale_array(data, mask, in_range=datatype_range) diff --git a/src/titiler/extensions/titiler/extensions/stac.py b/src/titiler/extensions/titiler/extensions/stac.py index 4c47284d8..8bec06c70 100644 --- a/src/titiler/extensions/titiler/extensions/stac.py +++ b/src/titiler/extensions/titiler/extensions/stac.py @@ -128,9 +128,7 @@ def create_stac( ] = -1, ): """Create STAC item.""" - properties = ( - {} - ) # or properties = properties or {} if we add properties in Query + properties = {} # or properties = properties or {} if we add properties in Query dt = None if datetime: diff --git a/src/titiler/extensions/titiler/extensions/wms.py b/src/titiler/extensions/titiler/extensions/wms.py index b63ac0b68..2d7347288 100644 --- a/src/titiler/extensions/titiler/extensions/wms.py +++ b/src/titiler/extensions/titiler/extensions/wms.py @@ -380,12 +380,12 @@ def wms( # noqa: C901 ) as src_dst: layers_dict[layer]["srs"] = f"EPSG:{src_dst.crs.to_epsg()}" layers_dict[layer]["bounds"] = src_dst.bounds - layers_dict[layer][ - "bounds_wgs84" - ] = src_dst.get_geographic_bounds(WGS84_CRS) - layers_dict[layer][ - "abstract" - ] = src_dst.info().model_dump_json() + layers_dict[layer]["bounds_wgs84"] = ( + src_dst.get_geographic_bounds(WGS84_CRS) + ) + layers_dict[layer]["abstract"] = ( + src_dst.info().model_dump_json() + ) # Build information for the whole service minx, miny, maxx, maxy = zip( diff --git a/src/titiler/mosaic/titiler/mosaic/factory.py b/src/titiler/mosaic/titiler/mosaic/factory.py index 03dab94a8..3c7e8bf39 100644 --- a/src/titiler/mosaic/titiler/mosaic/factory.py +++ b/src/titiler/mosaic/titiler/mosaic/factory.py @@ -102,9 +102,9 @@ class MosaicTilerFactory(BaseFactory): tile_dependency: Type[DefaultDependency] = TileParams # Post Processing Dependencies (algorithm) - process_dependency: Callable[ - ..., Optional[BaseAlgorithm] - ] = available_algorithms.dependency + process_dependency: Callable[..., Optional[BaseAlgorithm]] = ( + available_algorithms.dependency + ) # Image rendering Dependencies rescale_dependency: Callable[..., Optional[RescaleType]] = RescalingParams @@ -427,8 +427,11 @@ async def tileset( } ) - qs = [(key, value) for (key, value) in request.query_params._list] - query_string = f"?{urlencode(qs)}" if qs else "" + query_string = ( + f"?{urlencode(request.query_params._list)}" + if request.query_params._list + else "" + ) links = [ { @@ -582,7 +585,6 @@ def tile( reader_options=reader_params.as_dict(), **backend_params.as_dict(), ) as src_dst: - if MOSAIC_STRICT_ZOOM and ( z < src_dst.minzoom or z > src_dst.maxzoom ): diff --git a/src/titiler/xarray/notebooks/xarray_dataset_cache.ipynb b/src/titiler/xarray/notebooks/xarray_dataset_cache.ipynb index 23e87b7a4..e515e12c8 100644 --- a/src/titiler/xarray/notebooks/xarray_dataset_cache.ipynb +++ b/src/titiler/xarray/notebooks/xarray_dataset_cache.ipynb @@ -13,7 +13,6 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "import pickle\n", "from typing import Any, Callable, List, Optional\n", "\n", @@ -82,7 +81,7 @@ " datetime=self.datetime,\n", " drop_dim=self.drop_dim,\n", " )\n", - " super().__attrs_post_init__()\n" + " super().__attrs_post_init__()" ] }, { diff --git a/src/titiler/xarray/tests/fixtures/generate_fixtures.ipynb b/src/titiler/xarray/tests/fixtures/generate_fixtures.ipynb index 94c747837..137c104c1 100644 --- a/src/titiler/xarray/tests/fixtures/generate_fixtures.ipynb +++ b/src/titiler/xarray/tests/fixtures/generate_fixtures.ipynb @@ -113,7 +113,7 @@ "source": [ "# Zarr Pyramid\n", "def create_dataset(decimation: int = 0):\n", - " dec = decimation or 1 # make sure we don't / by 0\n", + " dec = decimation or 1 # make sure we don't / by 0\n", " width = 2000 // dec\n", " height = 1000 // dec\n", "\n", @@ -133,6 +133,7 @@ " data.attrs.update({\"valid_min\": arr.min(), \"valid_max\": arr.max(), \"fill_value\": 0})\n", " return data.to_dataset(name=\"dataset\")\n", "\n", + "\n", "for ix, dec in enumerate([0, 2, 4]):\n", " ds = create_dataset(dec)\n", " ds.to_zarr(store=\"pyramid.zarr\", mode=\"w\", group=ix)" @@ -158,8 +159,8 @@ "with fsspec.open(\"dataset_3d.nc\", mode=\"rb\", anon=True) as infile:\n", " h5chunks = SingleHdf5ToZarr(infile, \"dataset_3d.nc\", inline_threshold=100)\n", "\n", - " with open(\"reference.json\", 'w') as f:\n", - " f.write(json.dumps(h5chunks.translate()));\n" + " with open(\"reference.json\", \"w\") as f:\n", + " f.write(json.dumps(h5chunks.translate()))" ] }, { diff --git a/src/titiler/xarray/tests/test_dependencies.py b/src/titiler/xarray/tests/test_dependencies.py index ae3b28929..511f91a53 100644 --- a/src/titiler/xarray/tests/test_dependencies.py +++ b/src/titiler/xarray/tests/test_dependencies.py @@ -1,6 +1,5 @@ """test dependencies.""" - from fastapi import Depends, FastAPI, Path from starlette.testclient import TestClient from typing_extensions import Annotated diff --git a/src/titiler/xarray/tests/test_factory.py b/src/titiler/xarray/tests/test_factory.py index dc98511b2..3a03b75d5 100644 --- a/src/titiler/xarray/tests/test_factory.py +++ b/src/titiler/xarray/tests/test_factory.py @@ -1,4 +1,5 @@ """test titiler.xarray factory.""" + import os import pytest @@ -48,8 +49,6 @@ def app(): app = FastAPI() app.include_router(md.router, prefix="/md") - client = TestClient(app) - with TestClient(app) as client: yield client