[Git][debian-gis-team/xsar][master] 7 commits: New upstream version 2026.08.31
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Sat Sep 5 11:01:27 BST 2026
Antonio Valentino pushed to branch master at Debian GIS Project / xsar
Commits:
11c2532c by Antonio Valentino at 2026-09-05T09:40:51+00:00
New upstream version 2026.08.31
- - - - -
c99cbbee by Antonio Valentino at 2026-09-05T09:40:55+00:00
Update upstream source from tag 'upstream/2026.08.31'
Update to upstream version '2026.08.31'
with Debian dir 7eaa4d472f3402341729a0480eb07426c60160ca
- - - - -
5067cc77 by Antonio Valentino at 2026-09-05T09:41:45+00:00
New upstream release
- - - - -
a7aecc71 by Antonio Valentino at 2026-09-05T09:45:12+00:00
Drop dependency on cartopy
- - - - -
168eaaaa by Antonio Valentino at 2026-09-05T09:55:36+00:00
Add d/python3-xsar.lintian-overrides
- - - - -
9a2ffcaa by Antonio Valentino at 2026-09-05T09:57:31+00:00
Enable testing
- - - - -
481486f4 by Antonio Valentino at 2026-09-05T09:58:35+00:00
Set distributiom to unstable
- - - - -
21 changed files:
- .git_archival.txt
- .github/workflows/README.md
- .github/workflows/ci.yaml
- .github/workflows/conda-feedstock-check.yml
- .github/workflows/publish.yml
- .github/workflows/upstream-dev.yaml
- ci/requirements/environment.yaml
- debian/changelog
- debian/control
- + debian/python3-xsar.lintian-overrides
- debian/rules
- docs/conf.py
- docs/examples/mask.ipynb
- docs/examples/xsar_batch_datarmor.ipynb
- environment.yml
- pyproject.toml
- src/xsar/base_dataset.py
- src/xsar/base_meta.py
- src/xsar/config.yml
- src/xsar/ipython_backends.py
- test/test_invalid_mask_geometries.py
Changes:
=====================================
.git_archival.txt
=====================================
@@ -1 +1 @@
-ref-names: HEAD -> main, tag: 2026.02.10
\ No newline at end of file
+ref-names: HEAD -> main, tag: 2026.08.31
\ No newline at end of file
=====================================
.github/workflows/README.md
=====================================
@@ -20,7 +20,7 @@ The jobs contains 5 steps:
- Setup conda and create environment : using a community github action package [conda-incubator/setup-miniconda at v2](https://github.com/marketplace/actions/setup-miniconda)
- Install xsar dependencies
-- Check xsar environment: you can see in a debug job the version of conda, python, rasterio, gdal, cartopy and dask
+- Check xsar environment: you can see in a debug job the version of conda, python, rasterio, gdal and dask
- Install xsar
- Testing xsar : run the script test `test/test_xsar.py`
=====================================
.github/workflows/ci.yaml
=====================================
@@ -23,7 +23,7 @@ jobs:
outputs:
triggered: ${{ steps.detect-trigger.outputs.trigger-found }}
steps:
- - uses: actions/checkout at v6
+ - uses: actions/checkout at v7
with:
fetch-depth: 2
- uses: xarray-contrib/ci-trigger at v1
@@ -50,7 +50,7 @@ jobs:
steps:
- name: Checkout the repository
- uses: actions/checkout at v6
+ uses: actions/checkout at v7
with:
# need to fetch all tags to get a correct version
fetch-depth: 0 # fetch all branches and tags
@@ -62,7 +62,7 @@ jobs:
echo "CONDA_ENV_FILE=ci/requirements/environment.yaml" >> $GITHUB_ENV
- name: Setup micromamba
- uses: mamba-org/setup-micromamba at v2
+ uses: mamba-org/setup-micromamba at v3
with:
environment-file: ${{ env.CONDA_ENV_FILE }}
environment-name: xsar-tests
=====================================
.github/workflows/conda-feedstock-check.yml
=====================================
@@ -14,7 +14,7 @@ jobs:
# from https://michaelheap.com/dynamic-matrix-generation-github-actions/
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout at v6
+ - uses: actions/checkout at v7
- id: get-matrix
run: |
echo "get matrix for event ${{ github.event_name }}"
@@ -37,10 +37,10 @@ jobs:
shell: bash -l {0}
name: python ${{ matrix.python-version }} on ${{ matrix.os }}
steps:
- - uses: actions/checkout at v6
+ - uses: actions/checkout at v7
- name: Strip python version
run: cat environment.yml | egrep -vw python > environment-nopython.yml
- - uses: conda-incubator/setup-miniconda at v3
+ - uses: conda-incubator/setup-miniconda at v4
with:
auto-update-conda: true
activate-environment: xsar
=====================================
.github/workflows/publish.yml
=====================================
@@ -11,9 +11,9 @@ jobs:
if: github.repository == 'umr-lops/xsar'
steps:
- name: Checkout
- uses: actions/checkout at v6
+ uses: actions/checkout at v7
- name: Set up Python
- uses: actions/setup-python at v6
+ uses: actions/setup-python at v7
with:
python-version: "3.x"
- name: Install dependencies
@@ -27,7 +27,7 @@ jobs:
run: |
twine check dist/*
- name: Upload build artifacts
- uses: actions/upload-artifact at v6
+ uses: actions/upload-artifact at v7
with:
name: packages
path: dist/*
@@ -45,10 +45,10 @@ jobs:
steps:
- name: Download build artifacts
- uses: actions/download-artifact at v7
+ uses: actions/download-artifact at v8
with:
name: packages
path: dist/
- name: Publish to PyPI
- uses: pypa/gh-action-pypi-publish at ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
+ uses: pypa/gh-action-pypi-publish at dc37677b2e1c63e2034f94d8a5b11f265b73ba33
=====================================
.github/workflows/upstream-dev.yaml
=====================================
@@ -21,7 +21,7 @@ jobs:
outputs:
triggered: ${{ steps.detect-trigger.outputs.trigger-found }}
steps:
- - uses: actions/checkout at v6
+ - uses: actions/checkout at v7
with:
fetch-depth: 2
- uses: xarray-contrib/ci-trigger at v1.2
@@ -55,13 +55,13 @@ jobs:
steps:
- name: checkout the repository
- uses: actions/checkout at v6
+ uses: actions/checkout at v7
with:
# need to fetch all tags to get a correct version
fetch-depth: 0 # fetch all branches and tags
- name: set up conda environment
- uses: mamba-org/setup-micromamba at v2
+ uses: mamba-org/setup-micromamba at v3
with:
environment-file: ci/requirements/environment.yaml
environment-name: tests
=====================================
ci/requirements/environment.yaml
=====================================
@@ -19,7 +19,6 @@ dependencies:
- distributed
- aiohttp
- rasterio
- - cartopy
- pyproj
- scipy
- shapely
=====================================
debian/changelog
=====================================
@@ -1,9 +1,17 @@
-xsar (2026.02.10-2) UNRELEASED; urgency=medium
+xsar (2026.08.31-1) unstable; urgency=medium
- * Team upload.
+ [ Bas Couwenberg ]
* Bump Standards-Version to 4.7.4, no changes.
- -- Bas Couwenberg <sebastic at debian.org> Sat, 04 Apr 2026 10:25:20 +0200
+ [ Antonio Valentino ]
+ * New upstream release.
+ * debian/control:
+ - Drop dependency on cartopy.
+ * Add d/python3-xsar.lintian-overrides.
+ * debian/rules:
+ - Enable testing.
+
+ -- Antonio Valentino <antonio.valentino at tiscali.it> Sat, 05 Sep 2026 09:58:06 +0000
xsar (2026.02.10-1) unstable; urgency=medium
=====================================
debian/control
=====================================
@@ -9,7 +9,6 @@ Build-Depends: debhelper-compat (= 13),
python3-affine,
python3-aiohttp,
python3-all,
- python3-cartopy,
python3-dask,
python3-distributed,
python3-fiona,
=====================================
debian/python3-xsar.lintian-overrides
=====================================
@@ -0,0 +1,2 @@
+# False positive
+package-contains-documentation-outside-usr-share-doc [usr/lib/python3/*-packages/xsar-*.*-info/*.txt]
=====================================
debian/rules
=====================================
@@ -4,7 +4,6 @@ include /usr/share/dpkg/pkg-info.mk
export SETUPTOOLS_SCM_PRETEND_VERSION=$(DEB_VERSION_UPSTREAM)
export PYBUILD_NAME=xsar
-export PYBUILD_DISABLE=test
%:
dh $@ --buildsystem=pybuild
=====================================
docs/conf.py
=====================================
@@ -99,7 +99,7 @@ nbsphinx_timeout = 300
nbsphinx_prolog = """
Download this notebook from github_.
-.. _github: https://github.com/oarcher/xsar/tree/main/docs/{{ env.doc2path(env.docname, base=False) }}
+.. _github: https://github.com/umr-lops/xsar/tree/main/docs/{{ env.doc2path(env.docname, base=False) }}
----
"""
=====================================
docs/examples/mask.ipynb
=====================================
@@ -6,12 +6,7 @@
"id": "525f4c15-e090-4c0d-aba0-212138ea6a1a",
"metadata": {},
"outputs": [],
- "source": [
- "import xarray as xr\n",
- "import xsar\n",
- "import numpy as np\n",
- "import os"
- ]
+ "source": "import xarray as xr\nimport xsar\nimport numpy as np\nimport os\n\n# The default 'land' mask is read from the 'land_mask' key of ~/.xsar/config.yml.\n# For the docs (and RTD, which has no such config), we set it here to a small OSM clip\n# that only covers the example scenes below (~6 MB instead of the full ~748 MB).\nxsar.BaseMeta.set_mask_feature(\n 'land',\n os.path.join(xsar.get_test_file('masks/osm/land-osm-doc'), 'land_polygons.shp'),\n)"
},
{
"cell_type": "markdown",
@@ -40,8 +35,7 @@
"tags": []
},
"source": [
- "[xsar.Sentinel1Dataset.dataset](../basic_api.rst#xsar.Sentinel1Dataset.dataset) has a `land_mask` variable by default, rasterized from [cartopy.feature.NaturalEarthFeature('physical', 'land', '10m')](https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html#cartopy.feature.NaturalEarthFeature)\n",
- "\n"
+ "[xsar.Sentinel1Dataset.dataset](../basic_api.rst#xsar.Sentinel1Dataset.dataset) has a `land_mask` variable by default, rasterized from the shapefile given by the `land_mask` key of `~/.xsar/config.yml` (e.g. OSM land-polygons)\n"
]
},
{
@@ -76,7 +70,7 @@
"source": [
"### Adding masks\n",
"\n",
- "Masks can be added with [xsar.BaseMeta.set_mask_feature](../basic_api.rst#xsar.BaseMeta.set_mask_feature), providing a shapefile or a [cartopy.feature.Feature](https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html) object.\n",
+ "Masks can be added with [xsar.BaseMeta.set_mask_feature](../basic_api.rst#xsar.BaseMeta.set_mask_feature), providing a shapefile path (or any object exposing a `.geometries()` method).\n",
"\n",
"For a default mask for all SAFE, use classmethod `xsar.BaseMeta.set_mask_feature` \n",
"\n",
@@ -171,8 +165,7 @@
"tags": []
},
"source": [
- "[xsar.RadarSat2Dataset.dataset](../basic_api.rst#xsar.RadarSat2Dataset.dataset) has a `land_mask` variable by default, rasterized from [cartopy.feature.NaturalEarthFeature('physical', 'land', '10m')](https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html#cartopy.feature.NaturalEarthFeature)\n",
- "\n"
+ "[xsar.RadarSat2Dataset.dataset](../basic_api.rst#xsar.RadarSat2Dataset.dataset) has a `land_mask` variable by default, rasterized from the shapefile given by the `land_mask` key of `~/.xsar/config.yml` (e.g. OSM land-polygons)\n"
]
},
{
@@ -227,8 +220,7 @@
"tags": []
},
"source": [
- "[xsar.RcmDataset.dataset](../basic_api.rst#xsar.RcmDataset.dataset) has a `land_mask` variable by default, rasterized from [cartopy.feature.NaturalEarthFeature('physical', 'land', '10m')](https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html#cartopy.feature.NaturalEarthFeature)\n",
- "\n"
+ "[xsar.RcmDataset.dataset](../basic_api.rst#xsar.RcmDataset.dataset) has a `land_mask` variable by default, rasterized from the shapefile given by the `land_mask` key of `~/.xsar/config.yml` (e.g. OSM land-polygons)\n"
]
},
{
@@ -276,13 +268,29 @@
"source": [
"ds['sigma0_land'].sel(pol='HV').plot(vmin=0)"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "478442d3",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "3da62185",
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
"kernelspec": {
- "display_name": "env_xsar",
+ "display_name": "env_xsar (Slurm)",
"language": "python",
- "name": "python3"
+ "name": "env_xsar"
},
"language_info": {
"codemirror_mode": {
@@ -294,9 +302,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.15"
+ "version": "3.12.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
-}
+}
\ No newline at end of file
=====================================
docs/examples/xsar_batch_datarmor.ipynb
=====================================
@@ -51,12 +51,6 @@
"pip install git+https://github.com/umr-lops/xsarsea.git\n",
"```\n",
"\n",
- "This is needed for coastlines, because datarmor nodes don't have internet access\n",
- "\n",
- "```\n",
- "cartopy_feature_download.py --output `python -c 'import cartopy ; print(cartopy.config[\"data_dir\"])'` physical\n",
- "```\n",
- "\n",
"This is needed for https://datarmor-jupyterhub.ifremer.fr/\n",
"\n",
"```\n",
=====================================
environment.yml
=====================================
@@ -3,7 +3,6 @@ channels:
- conda-forge
dependencies:
- aiohttp
- - cartopy >=0.19.0
- dask >=2021.6.2
- gdal >=3.3
- geopandas
=====================================
pyproject.toml
=====================================
@@ -37,7 +37,6 @@ dependencies = [
"xarray>=2024.10.0",
'affine',
'rasterio',
- 'cartopy',
'fiona',
'pyproj',
'numpy',
=====================================
src/xsar/base_dataset.py
=====================================
@@ -553,17 +553,22 @@ class BaseDataset(ABC):
# transform * (x, y) -> (line, sample)
# (where (x, y) are index in out_shape)
# Affine.permutation() is used because (line, sample) is transposed from geographic
+ # coords label the pixel centers, while rasterio expects the transform
+ # to map pixel indices to the grid corner -> shift by half a step
+ dline = (line[-1] - line[0]) / (len(line) - 1)
+ dsample = (sample[-1] - sample[0]) / (len(sample) - 1)
transform = (
- Affine.translation(*chunk_coords[0])
- * Affine.scale(*[np.unique(np.diff(c))[0] for c in [line, sample]])
+ Affine.translation(line[0] - dline / 2,
+ sample[0] - dsample / 2)
+ * Affine.scale(dline, dsample)
* Affine.permutation()
)
raster_mask = rasterio.features.rasterize(
[vector_mask_coords],
out_shape=out_shape,
- all_touched=False,
+ all_touched=True,
transform=transform,
)
return raster_mask
@@ -732,9 +737,15 @@ class BaseDataset(ABC):
# (where (x, y) are index in out_shape)
# Affine.permutation() is used because (line, sample) is transposed from geographic
# this transform Affine seems to be sufficient approx for SLC -> curvilinear could be even better?
+ # coords label the pixel centers, while rasterio expects the transform
+ # to map pixel indices to the grid corner -> shift by half a step
+ dline = (line[-1] - line[0]) / (len(line) - 1)
+ dsample = (sample[-1] - sample[0]) / (len(sample) - 1)
+
transform = (
- Affine.translation(*chunk_coords[0])
- * Affine.scale(*[np.unique(np.diff(c))[0] for c in [line, sample]])
+ Affine.translation(line[0] - dline / 2,
+ sample[0] - dsample / 2)
+ * Affine.scale(dline, dsample)
* Affine.permutation()
)
=====================================
src/xsar/base_meta.py
=====================================
@@ -2,7 +2,6 @@ import copy
import logging
import warnings
-import cartopy
import rasterio
import shapely
from shapely.geometry import Polygon
@@ -16,7 +15,7 @@ from .raster_readers import available_rasters
from .base_dataset import BaseDataset
import geopandas as gpd
-from .utils import class_or_instancemethod, to_lon180, haversine
+from .utils import class_or_instancemethod, to_lon180, haversine, config
logger = logging.getLogger("xsar.base_meta")
logger.addHandler(logging.NullHandler())
@@ -30,6 +29,20 @@ warnings.filterwarnings(
np.errstate(invalid="ignore")
+# Default 'land' mask: shapefile path from the 'land_mask' key of the config.
+_DEFAULT_LAND = config.get("land_mask")
+
+
+class _ShapefileFeature:
+ """Minimal feature exposing ``.geometries()``, built from shapefile geometries (OSM, GSHHG...)."""
+
+ def __init__(self, geometries):
+ self._geometries = list(geometries)
+
+ def geometries(self):
+ return iter(self._geometries)
+
+
class BaseMeta(BaseDataset):
"""
Abstract class that defines necessary common functions for the computation of different SAR metadata
@@ -39,7 +52,7 @@ class BaseMeta(BaseDataset):
# default mask feature (see self.set_mask_feature and cls.set_mask_feature)
_mask_features_raw = {
- "land": cartopy.feature.NaturalEarthFeature("physical", "land", "10m")
+ "land": _DEFAULT_LAND
}
_mask_features = {}
@@ -64,11 +77,16 @@ class BaseMeta(BaseDataset):
self.rasters = available_rasters.iloc[0:0].copy()
def _get_mask_feature(self, name):
- # internal method that returns a cartopy feature from a mask name
+ # internal method that returns a feature (with a .geometries() method) from a mask name
if self._mask_features[name] is None:
feature = self._mask_features_raw[name]
+ if feature is None:
+ raise ValueError(
+ f"No feature set for mask '{name}'. Set 'land_mask' in "
+ f"~/.xsar/config.yml, or call set_mask_feature('{name}', '/path/to.shp')."
+ )
if isinstance(feature, str):
- # feature is a shapefile.
+ # feature is a shapefile (e.g. OSM land-polygons, GSHHG).
# we get the crs from the shapefile to be able to transform the footprint to this crs_in
# (so we can use `mask=` in gpd.read_file)
import fiona
@@ -91,14 +109,16 @@ class BaseMeta(BaseDataset):
with warnings.catch_warnings():
# ignore "RuntimeWarning: Sequential read of iterator was interrupted. Resetting iterator."
warnings.simplefilter("ignore", RuntimeWarning)
- feature = cartopy.feature.ShapelyFeature(
+ # wrap the shapefile geometries in a minimal feature exposing .geometries()
+ feature = _ShapefileFeature(
gpd.read_file(feature, mask=footprint_crs)
.to_crs(epsg=4326)
- .geometry,
- cartopy.crs.PlateCarree(),
+ .geometry
)
- if not isinstance(feature, cartopy.feature.Feature):
- raise TypeError("Expected a cartopy.feature.Feature type")
+ if not hasattr(feature, "geometries"):
+ raise TypeError(
+ "Expected a feature with a .geometries() method "
+ "(a shapefile path, or any feature exposing .geometries())")
self._mask_features[name] = feature
return self._mask_features[name]
@@ -106,33 +126,34 @@ class BaseMeta(BaseDataset):
@class_or_instancemethod
def set_mask_feature(self_or_cls, name, feature):
"""
- Set a named mask from a shapefile or a cartopy feature.
+ Set a named mask from a shapefile path.
Parameters
----------
name: str
mask name
- feature: str or cartopy.feature.Feature
- if str, feature is a path to a shapefile or whatever file readable with fiona.
- It is recommended to use str, as the serialization of cartopy feature might be big.
+ feature: str
+ path to a shapefile (or any file readable with fiona).
+ Any object exposing a ``.geometries()`` method is also accepted.
Examples
--------
- Add an 'ocean' mask at class level (ie as default mask):
+ Override the default 'land' mask with your own shapefile, at class level
+ (ie as default mask for every new meta):
```
- >>> xsar.RadarSat2Meta.set_mask_feature("ocean", cartopy.feature.OCEAN)
- >>> xsar.Sentinel1Meta.set_mask_feature("ocean", cartopy.feature.OCEAN)
+ >>> xsar.RadarSat2Meta.set_mask_feature("land", "/path/to/land_polygons.shp")
+ >>> xsar.Sentinel1Meta.set_mask_feature("land", "/path/to/land_polygons.shp")
```
- Add an 'ocean' mask at instance level (ie only for this self Sentinel1Meta (or RadarSat2Meta instance):
+ Add an extra named mask at instance level (only for this meta instance):
```
- >>> xsar.RadarSat2Meta.set_mask_feature("ocean", cartopy.feature.OCEAN)
- >>> xsar.Sentinel1Meta.set_mask_feature("ocean", cartopy.feature.OCEAN)
+ >>> meta.set_mask_feature("gshhg", "/path/to/GSHHS_h_L1.shp")
```
- High resoltion shapefiles can be found from openstreetmap.
+ High resolution land shapefiles can be found from openstreetmap.
It is recommended to use WGS84 with large polygons split from https://osmdata.openstreetmap.de/
+ The default 'land' mask is read from the 'land_mask' key of ~/.xsar/config.yml.
See Also
--------
@@ -166,24 +187,24 @@ class BaseMeta(BaseDataset):
if describe:
descr = self._mask_features_raw.get(name)
- # 1) if descr is a str ( shapefile file path in most of the case)
+ # 1) if descr is a str (shapefile path, e.g. OSM land-polygons / GSHHG):
+ # describe the mask by its source path -> ends up in the mask 'history' attr
+ if isinstance(descr, str):
+ return descr
# 2) if descr is None
if descr is None:
- descr = f"Unknown mask feature: {name}"
+ return f"Unknown mask feature: {name}"
- # 3) otherwise
+ # 3) otherwise a feature object: nice repr like 'module.Class name'
module = getattr(descr, "__module__", "unknown_module")
cls = descr.__class__.__name__
feat_name = getattr(descr, "name", f"{module}.{cls}")
- # nice repr for a class (like 'cartopy.feature.NaturalEarthFeature land')
- descr = "%s.%s %s" % (
+ return "%s.%s %s" % (
module,
cls,
feat_name,
)
-
- return descr
if self._mask_geometry[name] is None:
intersecting_geoms = self._get_mask_intersecting_geometries(name)
=====================================
src/xsar/config.yml
=====================================
@@ -2,3 +2,6 @@
data_dir: /tmp
auxiliary_dir:
path_auxiliary_df:
+# default 'land' mask: path to a shapefile (e.g. OSM land-polygons).
+# if empty, no default land mask, ValueError
+land_mask:
=====================================
src/xsar/ipython_backends.py
=====================================
@@ -4,7 +4,6 @@ try:
# make sure we are running from a notebook
# if test fail, nothing will be imported, and that will save lot of importtime
assert get_ipython() is not None
- import cartopy
import holoviews as hv
import geoviews as gv
import geoviews.feature as gf
@@ -51,10 +50,8 @@ def repr_mimebundle_Sentinel1Meta(self, include=None, exclude=None):
"""
)
- crs = cartopy.crs.PlateCarree()
-
world = gv.operation.resample_geometry(gf.land.geoms("10m")).opts(
- color="khaki", projection=crs, alpha=0.5
+ color="khaki", alpha=0.5
)
center = self.footprint.centroid
@@ -78,7 +75,7 @@ def repr_mimebundle_Sentinel1Meta(self, include=None, exclude=None):
footprint = (
gv.Polygons(footprints_df, label="footprint")
- .opts(projection=crs, xlim=xlim, ylim=ylim, alpha=0.5)
+ .opts(xlim=xlim, ylim=ylim, alpha=0.5)
.opts(
**(opts.get(hv.Store.current_backend) or {}),
backend=hv.Store.current_backend
@@ -87,7 +84,7 @@ def repr_mimebundle_Sentinel1Meta(self, include=None, exclude=None):
orbit = (
gv.Points(self.orbit["geometry"].to_crs("EPSG:4326"), label="orbit")
- .opts(projection=crs, xlim=xlim, ylim=ylim, alpha=0.5)
+ .opts(xlim=xlim, ylim=ylim, alpha=0.5)
.opts(
**(opts.get(hv.Store.current_backend) or {}),
backend=hv.Store.current_backend
=====================================
test/test_invalid_mask_geometries.py
=====================================
@@ -10,9 +10,7 @@ import pytest
import geopandas as gpd
from shapely.geometry import Polygon, MultiPolygon, box
from shapely.validation import explain_validity
-import cartopy
-
-from xsar.base_meta import BaseMeta
+from xsar.base_meta import BaseMeta, _ShapefileFeature
class DummyMeta(BaseMeta):
@@ -131,12 +129,9 @@ def test_get_mask_handles_self_intersecting_geometry(sentinel1_footprint):
# Get the problematic polygon
invalid_poly = get_problematic_gshhs_polygon()
- # Create a mock cartopy feature with the invalid geometry
+ # Create a mock shapefile feature with the invalid geometry
geoseries = gpd.GeoSeries([invalid_poly])
- mock_feature = cartopy.feature.ShapelyFeature(
- geoseries,
- cartopy.crs.PlateCarree()
- )
+ mock_feature = _ShapefileFeature(geoseries)
# Set the mask feature
meta.set_mask_feature("gshhs_test", mock_feature)
@@ -171,10 +166,7 @@ def test_get_mask_with_multiple_invalid_coastal_geometries(sentinel1_footprint):
# Create a mock feature with mixed geometries
geoseries = gpd.GeoSeries([valid_poly1, invalid_poly, valid_poly2])
- mock_feature = cartopy.feature.ShapelyFeature(
- geoseries,
- cartopy.crs.PlateCarree()
- )
+ mock_feature = _ShapefileFeature(geoseries)
# Set the mask feature
meta.set_mask_feature("gshhs_multiple", mock_feature)
@@ -223,10 +215,7 @@ def test_get_mask_caches_fixed_geometry(sentinel1_footprint):
invalid_poly = get_problematic_gshhs_polygon()
geoseries = gpd.GeoSeries([invalid_poly])
- mock_feature = cartopy.feature.ShapelyFeature(
- geoseries,
- cartopy.crs.PlateCarree()
- )
+ mock_feature = _ShapefileFeature(geoseries)
meta.set_mask_feature("gshhs_cache", mock_feature)
View it on GitLab: https://salsa.debian.org/debian-gis-team/xsar/-/compare/2acc41e5a644a5416b1fbb242902c87c9edb63e2...481486f43daf9595eaf918de64f61c7b3784a452
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/xsar/-/compare/2acc41e5a644a5416b1fbb242902c87c9edb63e2...481486f43daf9595eaf918de64f61c7b3784a452
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260905/1422d18b/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list