geoarray 0.17.2__tar.gz → 0.18.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {geoarray-0.17.2 → geoarray-0.18.0}/.gitlab-ci.yml +9 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/AUTHORS.rst +1 -4
- {geoarray-0.17.2 → geoarray-0.18.0}/CONTRIBUTING.rst +1 -1
- {geoarray-0.17.2 → geoarray-0.18.0}/HISTORY.rst +17 -0
- {geoarray-0.17.2/geoarray.egg-info → geoarray-0.18.0}/PKG-INFO +6 -5
- {geoarray-0.17.2 → geoarray-0.18.0}/README.rst +1 -1
- {geoarray-0.17.2 → geoarray-0.18.0}/examples/notebooks/features_and_usage.ipynb +2 -2
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/__init__.py +5 -1
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/baseclasses.py +125 -135
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/masks.py +1 -1
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/metadata.py +25 -13
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/subsetting.py +1 -1
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray/version.py +3 -3
- {geoarray-0.17.2 → geoarray-0.18.0/geoarray.egg-info}/PKG-INFO +6 -5
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray.egg-info/requires.txt +3 -3
- {geoarray-0.17.2 → geoarray-0.18.0}/setup.py +4 -3
- {geoarray-0.17.2 → geoarray-0.18.0}/.coveragerc +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/.editorconfig +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/.gitattributes +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/.github/ISSUE_TEMPLATE.md +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/.gitignore +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/LICENSE +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/MANIFEST.in +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/Makefile +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/Makefile +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/_build/html/_static/file.png +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/_build/html/_static/minus.png +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/_build/html/_static/plus.png +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/authors.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/conf.py +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/contributing.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/history.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/index.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/installation.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/make.bat +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/readme.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/docs/usage.rst +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray.egg-info/SOURCES.txt +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray.egg-info/dependency_links.txt +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray.egg-info/not-zip-safe +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/geoarray.egg-info/top_level.txt +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/setup.cfg +0 -0
- {geoarray-0.17.2 → geoarray-0.18.0}/tox.ini +0 -0
|
@@ -12,6 +12,10 @@ test_geoarray:
|
|
|
12
12
|
stage: test
|
|
13
13
|
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
|
|
14
14
|
script:
|
|
15
|
+
# TODO remove as soon as CI runner is rebuilt
|
|
16
|
+
- mamba env remove -n ci_env
|
|
17
|
+
- mamba env create --name ci_env -f tests/CI_docker/context/environment_geoarray.yml
|
|
18
|
+
|
|
15
19
|
- source activate ci_env
|
|
16
20
|
|
|
17
21
|
# update py_tools_ds
|
|
@@ -63,6 +67,10 @@ test_geoarray_install:
|
|
|
63
67
|
script:
|
|
64
68
|
- mamba update -n base mamba conda
|
|
65
69
|
|
|
70
|
+
# TODO remove as soon as CI runner is rebuilt
|
|
71
|
+
- pip install --force-reinstall zstandard
|
|
72
|
+
- pip install --force-reinstall zstd
|
|
73
|
+
|
|
66
74
|
# create geoarray environment from environment_geoarray.yml
|
|
67
75
|
- mamba env create --name geoarray_test -f tests/CI_docker/context/environment_geoarray.yml
|
|
68
76
|
- source activate geoarray_test
|
|
@@ -71,6 +79,7 @@ test_geoarray_install:
|
|
|
71
79
|
- pip install -e .
|
|
72
80
|
- cd ..
|
|
73
81
|
- pwd
|
|
82
|
+
|
|
74
83
|
- ls
|
|
75
84
|
|
|
76
85
|
# test importability
|
|
@@ -5,12 +5,9 @@ Credits
|
|
|
5
5
|
Development Lead
|
|
6
6
|
----------------
|
|
7
7
|
|
|
8
|
-
* Daniel Scheffler <danschef@gfz-potsdam.de>
|
|
9
|
-
** <https://www.gfz-potsdam.de/staff/daniel.scheffler/sec14/>
|
|
10
|
-
|
|
8
|
+
* `Daniel Scheffler <https://www.gfz-potsdam.de/staff/daniel.scheffler/sec14/>`__ <danschef@gfz-potsdam.de>
|
|
11
9
|
|
|
12
10
|
Contributors
|
|
13
11
|
------------
|
|
14
12
|
|
|
15
13
|
* Jessica Palka <jessica.palka@gfz-potsdam.de>
|
|
16
|
-
|
|
@@ -101,7 +101,7 @@ Before you submit a pull request, check that it meets these guidelines:
|
|
|
101
101
|
2. If the pull request adds functionality, the docs should be updated. Put
|
|
102
102
|
your new functionality into a function with a docstring, and add the
|
|
103
103
|
feature to the list in README.rst.
|
|
104
|
-
3. The pull request should work for Python 3.8, 3.9, 3.10, and 3.
|
|
104
|
+
3. The pull request should work for Python 3.8, 3.9, 3.10, 3.11, and 3.12. Check
|
|
105
105
|
https://travis-ci.org/danschef/geoarray/pull_requests
|
|
106
106
|
and make sure that the tests pass for all supported Python versions.
|
|
107
107
|
|
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
0.18.0 (05.07.2024)
|
|
6
|
+
-------------------
|
|
7
|
+
|
|
8
|
+
* !47: Fixed missing handling of int64 input values for GDAL_Metadata.__getitem__
|
|
9
|
+
and improved coverage of GDAL_Metadata.
|
|
10
|
+
* !48: Revised tests to use pytest plain assertions.
|
|
11
|
+
* !49: Improved documentation of expected order of array dimensions (closes #43).
|
|
12
|
+
* !50: Fixed #46 (Numpy 2.0 support: `can_cast` not supported for python dtypes).
|
|
13
|
+
* !51: Fixed GDAL-3.9-related RuntimeError within GeoArray.save by using context managers.
|
|
14
|
+
Bumped minimal version of GDAL to 3.8 due to usage of context managers.
|
|
15
|
+
* !52: Use GDAL context managers where ever possible.
|
|
16
|
+
* Added official support for Python 3.12.
|
|
17
|
+
* !53: Removed Test_GeoArray.test_show_map_noepsg because newer versions of pyproj do not
|
|
18
|
+
return None as EPSG code anymore (at least not with the given WKT).
|
|
19
|
+
* !54: Fixed DeprecationWarning (replaced deprecated pkgutil.find_loader with importlib.util.find_spec).
|
|
20
|
+
|
|
21
|
+
|
|
5
22
|
0.17.2 (23.11.2023)
|
|
6
23
|
-------------------
|
|
7
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: geoarray
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.0
|
|
4
4
|
Summary: Fast Python interface for geodata - either on disk or in memory.
|
|
5
5
|
Home-page: https://git.gfz-potsdam.de/danschef/geoarray
|
|
6
6
|
Author: Daniel Scheffler
|
|
@@ -15,13 +15,14 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
19
|
Requires-Python: >=3.8
|
|
19
20
|
Description-Content-Type: text/x-rst
|
|
20
21
|
License-File: LICENSE
|
|
21
22
|
License-File: AUTHORS.rst
|
|
22
23
|
Requires-Dist: cartopy>=0.20
|
|
23
24
|
Requires-Dist: dill
|
|
24
|
-
Requires-Dist: gdal>=
|
|
25
|
+
Requires-Dist: gdal>=3.8.0
|
|
25
26
|
Requires-Dist: matplotlib
|
|
26
27
|
Requires-Dist: numpy
|
|
27
28
|
Requires-Dist: pandas
|
|
@@ -38,7 +39,7 @@ Requires-Dist: sphinx_rtd_theme; extra == "doc"
|
|
|
38
39
|
Provides-Extra: test
|
|
39
40
|
Requires-Dist: cartopy>=0.20; extra == "test"
|
|
40
41
|
Requires-Dist: dill; extra == "test"
|
|
41
|
-
Requires-Dist: gdal>=
|
|
42
|
+
Requires-Dist: gdal>=3.8.0; extra == "test"
|
|
42
43
|
Requires-Dist: matplotlib; extra == "test"
|
|
43
44
|
Requires-Dist: numpy; extra == "test"
|
|
44
45
|
Requires-Dist: pandas; extra == "test"
|
|
@@ -58,7 +59,7 @@ Provides-Extra: dev
|
|
|
58
59
|
Requires-Dist: setuptools-git; extra == "dev"
|
|
59
60
|
Requires-Dist: cartopy>=0.20; extra == "dev"
|
|
60
61
|
Requires-Dist: dill; extra == "dev"
|
|
61
|
-
Requires-Dist: gdal>=
|
|
62
|
+
Requires-Dist: gdal>=3.8.0; extra == "dev"
|
|
62
63
|
Requires-Dist: matplotlib; extra == "dev"
|
|
63
64
|
Requires-Dist: numpy; extra == "dev"
|
|
64
65
|
Requires-Dist: pandas; extra == "dev"
|
|
@@ -155,7 +156,7 @@ open source packages that may cause problems when installed with pip. Therefore,
|
|
|
155
156
|
to resolve the following dependencies before the pip installer is run:
|
|
156
157
|
|
|
157
158
|
* cartopy >=0.20
|
|
158
|
-
* gdal >=
|
|
159
|
+
* gdal >=3.8.0
|
|
159
160
|
* geopandas
|
|
160
161
|
* holoviews # optional, in case you want to use interactive plotting
|
|
161
162
|
* matplotlib
|
|
@@ -77,7 +77,7 @@ open source packages that may cause problems when installed with pip. Therefore,
|
|
|
77
77
|
to resolve the following dependencies before the pip installer is run:
|
|
78
78
|
|
|
79
79
|
* cartopy >=0.20
|
|
80
|
-
* gdal >=
|
|
80
|
+
* gdal >=3.8.0
|
|
81
81
|
* geopandas
|
|
82
82
|
* holoviews # optional, in case you want to use interactive plotting
|
|
83
83
|
* matplotlib
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"from geoarray import GeoArray\n",
|
|
65
65
|
"import numpy as np\n",
|
|
66
66
|
"\n",
|
|
67
|
-
"testarray = np.random.randint(1,10, (250, 250, 8))\n",
|
|
67
|
+
"testarray = np.random.randint(1,10, (250, 250, 8)) # (250 rows, 250 columns, 8 bands)\n",
|
|
68
68
|
"\n",
|
|
69
69
|
"gA = GeoArray(testarray,\n",
|
|
70
70
|
" geotransform=[640605.0, 30.0, -0.0, 5754285.0, -0.0, -30.0],\n",
|
|
@@ -767,4 +767,4 @@
|
|
|
767
767
|
},
|
|
768
768
|
"nbformat": 4,
|
|
769
769
|
"nbformat_minor": 4
|
|
770
|
-
}
|
|
770
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# you may not use this file except in compliance with the License.
|
|
16
16
|
# You may obtain a copy of the License at
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
19
19
|
#
|
|
20
20
|
# Unless required by applicable law or agreed to in writing, software
|
|
21
21
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
# limitations under the License.
|
|
25
25
|
|
|
26
26
|
import os
|
|
27
|
+
from osgeo import gdal as _gdal
|
|
27
28
|
if 'MPLBACKEND' not in os.environ:
|
|
28
29
|
os.environ['MPLBACKEND'] = 'Agg'
|
|
29
30
|
|
|
@@ -47,6 +48,9 @@ __all__ = ['__version__',
|
|
|
47
48
|
'CloudMask'
|
|
48
49
|
]
|
|
49
50
|
|
|
51
|
+
# enable GDAL exceptions
|
|
52
|
+
_gdal.UseExceptions()
|
|
53
|
+
|
|
50
54
|
# $PROJ_LIB was renamed to $PROJ_DATA in proj=9.1.1, which leads to issues with fiona>=1.8.20,<1.9
|
|
51
55
|
# https://github.com/conda-forge/pyproj-feedstock/issues/130
|
|
52
56
|
# -> fix it by setting PROJ_DATA
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# you may not use this file except in compliance with the License.
|
|
16
16
|
# You may obtain a copy of the License at
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
19
19
|
#
|
|
20
20
|
# Unless required by applicable law or agreed to in writing, software
|
|
21
21
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
import os
|
|
28
28
|
import warnings
|
|
29
|
-
from
|
|
29
|
+
from importlib.util import find_spec
|
|
30
30
|
from collections import OrderedDict
|
|
31
31
|
from copy import copy, deepcopy
|
|
32
32
|
from numbers import Number
|
|
@@ -104,7 +104,7 @@ class GeoArray(object):
|
|
|
104
104
|
) -> None:
|
|
105
105
|
"""Get an instance of GeoArray.
|
|
106
106
|
|
|
107
|
-
:param path_or_array: a numpy.ndarray or a valid file path
|
|
107
|
+
:param path_or_array: a numpy.ndarray (rows, columns, bands) or a valid file path
|
|
108
108
|
:param geotransform: GDAL geotransform of the given array or file on disk
|
|
109
109
|
:param projection: projection of the given array or file on disk as WKT string
|
|
110
110
|
(only needed if GeoArray is instanced with an array)
|
|
@@ -321,7 +321,7 @@ class GeoArray(object):
|
|
|
321
321
|
|
|
322
322
|
@geotransform.setter
|
|
323
323
|
def geotransform(self, gt: Union[tuple, list]):
|
|
324
|
-
assert isinstance(gt, (list, tuple)) and len(gt) == 6
|
|
324
|
+
assert isinstance(gt, (list, tuple)) and len(gt) == 6, \
|
|
325
325
|
'geotransform must be a list with 6 numbers. Got %s.' % str(gt)
|
|
326
326
|
|
|
327
327
|
for i in gt:
|
|
@@ -549,7 +549,7 @@ class GeoArray(object):
|
|
|
549
549
|
# assert self._footprint_poly
|
|
550
550
|
# for XY in self.corner_coord:
|
|
551
551
|
# assert self.GeoArray.box.mapPoly.contains(Point(XY)) or self.GeoArray.box.mapPoly.touches(Point(XY)), \
|
|
552
|
-
# "The corner position '%s' is outside
|
|
552
|
+
# "The corner position '%s' is outside the %s." % (XY, self.imName)
|
|
553
553
|
|
|
554
554
|
return self._footprint_poly
|
|
555
555
|
|
|
@@ -823,42 +823,40 @@ class GeoArray(object):
|
|
|
823
823
|
"""
|
|
824
824
|
if not self._gdalDataset_meta_already_set:
|
|
825
825
|
assert self.filePath
|
|
826
|
-
ds = gdal.Open(self.filePath)
|
|
827
|
-
if not ds:
|
|
828
|
-
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
829
826
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
self._geotransform = list(ds.GetGeoTransform())
|
|
827
|
+
with gdal.Open(self.filePath) as ds:
|
|
828
|
+
if not ds:
|
|
829
|
+
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
834
830
|
|
|
835
|
-
|
|
836
|
-
|
|
831
|
+
# set private class variables (in order to avoid recursion error)
|
|
832
|
+
self._shape = tuple([ds.RasterYSize, ds.RasterXSize] + ([ds.RasterCount] if ds.RasterCount > 1 else []))
|
|
833
|
+
self._dtype = gdal_array.GDALTypeCodeToNumericTypeCode(ds.GetRasterBand(1).DataType)
|
|
834
|
+
self._geotransform = list(ds.GetGeoTransform())
|
|
837
835
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
self._projection = CRS(wkt).to_wkt(version="WKT1_GDAL") if not isLocal(wkt) else ''
|
|
836
|
+
# somehow GDAL reads arbitrary geotransforms as (0, 1, 0, 0, 0, 1) instead of (0, 1, 0, 0, 0, -1)
|
|
837
|
+
self._geotransform[5] = -abs(self._geotransform[5]) # => force ygsd to be negative
|
|
841
838
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
self.nodata = band.GetNoDataValue()
|
|
846
|
-
self.nodata = band.GetNoDataValue()
|
|
839
|
+
# consequently use WKT1 strings here as GDAL always exports transformation results as WKT1
|
|
840
|
+
wkt = ds.GetProjection()
|
|
841
|
+
self._projection = CRS(wkt).to_wkt(version="WKT1_GDAL") if not isLocal(wkt) else ''
|
|
847
842
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
843
|
+
if 'nodata' not in self._initParams or self._initParams['nodata'] is None:
|
|
844
|
+
band = ds.GetRasterBand(1)
|
|
845
|
+
# FIXME this does not support different nodata values within the same file
|
|
846
|
+
self.nodata = band.GetNoDataValue()
|
|
847
|
+
self.nodata = band.GetNoDataValue()
|
|
852
848
|
|
|
853
|
-
|
|
854
|
-
self.
|
|
849
|
+
# set metadata attribute
|
|
850
|
+
if self.is_inmem or not self.filePath:
|
|
851
|
+
# metadata cannot be read from disk -> set it to the default
|
|
852
|
+
self._metadata = GDAL_Metadata(nbands=self.bands, nodata_allbands=self._nodata)
|
|
855
853
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
self.bandnames = self.metadata.band_meta['band_names']
|
|
854
|
+
else:
|
|
855
|
+
self._metadata = GDAL_Metadata(filePath=self.filePath)
|
|
859
856
|
|
|
860
|
-
|
|
861
|
-
|
|
857
|
+
# copy over the band names
|
|
858
|
+
if 'band_names' in self.metadata.band_meta and self.metadata.band_meta['band_names']:
|
|
859
|
+
self.bandnames = self.metadata.band_meta['band_names']
|
|
862
860
|
|
|
863
861
|
self._gdalDataset_meta_already_set = True
|
|
864
862
|
|
|
@@ -871,12 +869,11 @@ class GeoArray(object):
|
|
|
871
869
|
:param getitem_params: a list of slices in the form [row_slice, col_slice, band_slice]
|
|
872
870
|
:return out_arr: the output array
|
|
873
871
|
"""
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
872
|
+
with gdal.Open(path) as ds:
|
|
873
|
+
if not ds:
|
|
874
|
+
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
877
875
|
|
|
878
|
-
|
|
879
|
-
del ds
|
|
876
|
+
R, C, B = ds.RasterYSize, ds.RasterXSize, ds.RasterCount
|
|
880
877
|
|
|
881
878
|
# convert getitem_params to subset area to be read #
|
|
882
879
|
rS, rE, cS, cE, bS, bE, bL = [None] * 7
|
|
@@ -996,23 +993,21 @@ class GeoArray(object):
|
|
|
996
993
|
if out_arr is None:
|
|
997
994
|
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
998
995
|
else:
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
if out_arr is None:
|
|
1004
|
-
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
1005
|
-
del band
|
|
1006
|
-
else:
|
|
1007
|
-
out_arr = np.empty((rE - rS + 1, cE - cS + 1, len(bL)))
|
|
1008
|
-
for i, bIdx in enumerate(bL):
|
|
1009
|
-
band = ds.GetRasterBand(bIdx + 1)
|
|
1010
|
-
out_arr[:, :, i] = band.ReadAsArray(cS, rS, cE - cS + 1, rE - rS + 1)
|
|
996
|
+
with gdal.Open(path) as ds:
|
|
997
|
+
if len(bL) == 1:
|
|
998
|
+
band = ds.GetRasterBand(bL[0] + 1)
|
|
999
|
+
out_arr = band.ReadAsArray(cS, rS, cE - cS + 1, rE - rS + 1)
|
|
1011
1000
|
if out_arr is None:
|
|
1012
1001
|
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
1013
1002
|
del band
|
|
1014
|
-
|
|
1015
|
-
|
|
1003
|
+
else:
|
|
1004
|
+
out_arr = np.empty((rE - rS + 1, cE - cS + 1, len(bL)))
|
|
1005
|
+
for i, bIdx in enumerate(bL):
|
|
1006
|
+
band = ds.GetRasterBand(bIdx + 1)
|
|
1007
|
+
out_arr[:, :, i] = band.ReadAsArray(cS, rS, cE - cS + 1, rE - rS + 1)
|
|
1008
|
+
if out_arr is None:
|
|
1009
|
+
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
1010
|
+
del band
|
|
1016
1011
|
|
|
1017
1012
|
out_arr = _ensure_np_shape_consistency_3D_2D(out_arr)
|
|
1018
1013
|
|
|
@@ -1076,111 +1071,102 @@ class GeoArray(object):
|
|
|
1076
1071
|
#########################################
|
|
1077
1072
|
# write output dataset and set metadata #
|
|
1078
1073
|
#########################################
|
|
1074
|
+
with gdal.config_options(
|
|
1075
|
+
dict(
|
|
1076
|
+
GDAL_PAM_ENABLED='NO', # disable to write separate metadata XML files
|
|
1077
|
+
)
|
|
1078
|
+
):
|
|
1079
1079
|
|
|
1080
|
-
try:
|
|
1081
1080
|
# ENVI #
|
|
1082
1081
|
########
|
|
1083
1082
|
if fmt == 'ENVI':
|
|
1084
|
-
# NOTE: The dataset
|
|
1083
|
+
# NOTE: The dataset must be written BEFORE metadata are added. Otherwise, metadata are not written.
|
|
1085
1084
|
|
|
1086
1085
|
# write ds_src to disk and re-open it to add the metadata
|
|
1087
1086
|
gdal.Translate(out_path, ds_src, format=fmt, creationOptions=creationOptions)
|
|
1088
1087
|
del ds_src
|
|
1089
|
-
# os.environ['GDAL_PAM_ENABLED'] = 'NO'
|
|
1090
|
-
ds_out = gdal.Open(out_path, gdal.GA_Update)
|
|
1091
|
-
|
|
1092
|
-
for bidx in range(self.bands):
|
|
1093
|
-
band = ds_out.GetRasterBand(bidx + 1)
|
|
1094
|
-
|
|
1095
|
-
if 'band_names' in envi_metadict:
|
|
1096
|
-
bandname = str(self.metadata.band_meta['band_names'][bidx]).strip()
|
|
1097
|
-
band.SetDescription(bandname)
|
|
1098
|
-
assert band.GetDescription() == bandname
|
|
1099
1088
|
|
|
1100
|
-
|
|
1089
|
+
with gdal.Open(out_path, gdal.GA_Update) as ds_out:
|
|
1101
1090
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
del envi_metadict['band_names']
|
|
1091
|
+
for bidx in range(self.bands):
|
|
1092
|
+
band = ds_out.GetRasterBand(bidx + 1)
|
|
1105
1093
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1094
|
+
if 'band_names' in envi_metadict:
|
|
1095
|
+
bandname = str(self.metadata.band_meta['band_names'][bidx]).strip()
|
|
1096
|
+
band.SetDescription(bandname)
|
|
1097
|
+
assert band.GetDescription() == bandname
|
|
1109
1098
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
envi_metadict['data_ignore_value'] = str(self.metadata.band_meta['nodata'][0])
|
|
1114
|
-
else:
|
|
1115
|
-
warnings.warn("Band-specific nodata values are not supported by the ENVI header format.")
|
|
1099
|
+
# avoid that band names are written to global meta
|
|
1100
|
+
if 'band_names' in envi_metadict:
|
|
1101
|
+
del envi_metadict['band_names']
|
|
1116
1102
|
|
|
1117
|
-
|
|
1103
|
+
# the expected key name is 'data_ignore_value', see below
|
|
1104
|
+
if 'nodata' in envi_metadict:
|
|
1105
|
+
del envi_metadict['nodata']
|
|
1118
1106
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1107
|
+
# set data_ignore_value in case self.metadata.band_meta contains a unique nodata value
|
|
1108
|
+
if 'nodata' in self.metadata.band_meta:
|
|
1109
|
+
if len(set(self.metadata.band_meta['nodata'])) == 1:
|
|
1110
|
+
envi_metadict['data_ignore_value'] = str(self.metadata.band_meta['nodata'][0])
|
|
1111
|
+
else:
|
|
1112
|
+
warnings.warn("Band-specific nodata values are not supported "
|
|
1113
|
+
"by the ENVI header format.")
|
|
1121
1114
|
|
|
1122
|
-
|
|
1115
|
+
ds_out.SetMetadata(envi_metadict, 'ENVI')
|
|
1123
1116
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1117
|
+
if 'description' in envi_metadict:
|
|
1118
|
+
ds_out.SetDescription(envi_metadict['description'])
|
|
1126
1119
|
|
|
1127
1120
|
else:
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
ds_out = ds_src
|
|
1132
|
-
|
|
1133
|
-
# set metadata
|
|
1134
|
-
if self.metadata.all_meta:
|
|
1135
|
-
|
|
1136
|
-
# set global domain metadata
|
|
1137
|
-
if self.metadata.global_meta:
|
|
1138
|
-
ds_out.SetMetadata(dict((k, repr(v)) for k, v in self.metadata.global_meta.items()))
|
|
1121
|
+
try:
|
|
1122
|
+
ds_out = ds_src
|
|
1123
|
+
del ds_src
|
|
1139
1124
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1125
|
+
# set metadata
|
|
1126
|
+
if self.metadata.all_meta:
|
|
1142
1127
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1128
|
+
# set global domain metadata
|
|
1129
|
+
if self.metadata.global_meta:
|
|
1130
|
+
ds_out.SetMetadata(dict((k, repr(v)) for k, v in self.metadata.global_meta.items()))
|
|
1145
1131
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
bandmeta = bandmeta_dict[bidx].copy()
|
|
1132
|
+
if 'description' in envi_metadict:
|
|
1133
|
+
ds_out.SetDescription(envi_metadict['description'])
|
|
1149
1134
|
|
|
1150
|
-
#
|
|
1151
|
-
|
|
1152
|
-
# meta2write = dict((k, repr(v)) for k, v in self.metadata.band_meta.items() if v is not np.nan)
|
|
1135
|
+
# set band domain metadata
|
|
1136
|
+
bandmeta_dict = self.metadata.to_DataFrame().astype(str).to_dict()
|
|
1153
1137
|
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
del bandmeta['band_names']
|
|
1138
|
+
for bidx in range(self.bands):
|
|
1139
|
+
band = ds_out.GetRasterBand(bidx + 1)
|
|
1140
|
+
bandmeta = bandmeta_dict[bidx].copy()
|
|
1158
1141
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1142
|
+
# filter global metadata out
|
|
1143
|
+
bandmeta = {k: v for k, v in bandmeta.items() if k not in self.metadata.global_meta}
|
|
1144
|
+
# meta2write = dict((k, repr(v))
|
|
1145
|
+
# for k, v in self.metadata.band_meta.items() if v is not np.nan)
|
|
1162
1146
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1147
|
+
if 'band_names' in bandmeta:
|
|
1148
|
+
bandname = str(self.metadata.band_meta['band_names'][bidx]).strip()
|
|
1149
|
+
band.SetDescription(bandname)
|
|
1150
|
+
del bandmeta['band_names']
|
|
1165
1151
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1152
|
+
if 'nodata' in bandmeta:
|
|
1153
|
+
band.SetNoDataValue(self.metadata.band_meta['nodata'][bidx])
|
|
1154
|
+
del bandmeta['nodata']
|
|
1168
1155
|
|
|
1169
|
-
|
|
1156
|
+
if bandmeta:
|
|
1157
|
+
band.SetMetadata(bandmeta)
|
|
1170
1158
|
|
|
1171
|
-
|
|
1172
|
-
# -> writes the in-memory array or transforms the linked dataset into the target format
|
|
1173
|
-
gdal.Translate(out_path, ds_out, format=fmt, creationOptions=creationOptions)
|
|
1174
|
-
del ds_src
|
|
1159
|
+
ds_out.FlushCache()
|
|
1175
1160
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1161
|
+
# write ds_out to disk,
|
|
1162
|
+
# -> writes the in-memory array or transforms the linked dataset into the target format
|
|
1163
|
+
gdal.Translate(out_path, ds_out, format=fmt, creationOptions=creationOptions)
|
|
1179
1164
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1165
|
+
finally:
|
|
1166
|
+
del ds_out
|
|
1182
1167
|
|
|
1183
|
-
|
|
1168
|
+
if not os.path.exists(out_path):
|
|
1169
|
+
raise Exception(gdal.GetLastErrorMsg())
|
|
1184
1170
|
|
|
1185
1171
|
def dump(self, out_path: str) -> None:
|
|
1186
1172
|
"""Serialize the whole object instance to disk using dill."""
|
|
@@ -1215,10 +1201,14 @@ class GeoArray(object):
|
|
|
1215
1201
|
xdim, ydim = None, None
|
|
1216
1202
|
in_nodata = nodataVal if nodataVal is not None else self.nodata
|
|
1217
1203
|
out_nodata = in_nodata if in_nodata is not None else -9999
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1204
|
+
|
|
1205
|
+
# use meaningful numeric data type for output image, compatible to the output nodata value
|
|
1206
|
+
out_dtype = np.result_type(np.array(out_nodata), image2plot)
|
|
1207
|
+
if not np.can_cast(out_dtype, np.float32):
|
|
1208
|
+
out_dtype = np.float32 # more than float32 is not needed
|
|
1209
|
+
elif out_dtype == bool:
|
|
1210
|
+
out_dtype = int
|
|
1211
|
+
image2plot = image2plot.astype(out_dtype)
|
|
1222
1212
|
|
|
1223
1213
|
# rotated images always have to be resampled for plotting
|
|
1224
1214
|
if not ignore_rotation and self.is_rotated:
|
|
@@ -1351,7 +1341,7 @@ class GeoArray(object):
|
|
|
1351
1341
|
image2plot = np.ma.masked_equal(image2plot, nodataVal)
|
|
1352
1342
|
|
|
1353
1343
|
# check availability of holoviews
|
|
1354
|
-
if interactive and not
|
|
1344
|
+
if interactive and not find_spec('holoviews'):
|
|
1355
1345
|
warnings.warn("Interactive mode requires holoviews. Install it by running, e.g., "
|
|
1356
1346
|
"'conda install -c conda-forge holoviews'. Using non-interactive mode.")
|
|
1357
1347
|
interactive = False
|
|
@@ -1507,7 +1497,7 @@ class GeoArray(object):
|
|
|
1507
1497
|
|
|
1508
1498
|
def show_footprint(self):
|
|
1509
1499
|
"""Show a web map containing the computed footprint of the GeoArray instance in a Jupyter notebook."""
|
|
1510
|
-
if not
|
|
1500
|
+
if not find_spec('folium') or not find_spec('geojson'):
|
|
1511
1501
|
raise ImportError(
|
|
1512
1502
|
"This method requires the libraries 'folium' and 'geojson'. They can be installed with "
|
|
1513
1503
|
"the shell command 'pip install folium geojson'.")
|
|
@@ -1554,7 +1544,7 @@ class GeoArray(object):
|
|
|
1554
1544
|
image2plot = data
|
|
1555
1545
|
|
|
1556
1546
|
plt.figure(figsize=figsize)
|
|
1557
|
-
plt.hist(list(image2plot.flat), density=normed, bins=bins, color='gray', range=
|
|
1547
|
+
plt.hist(list(image2plot.flat), density=normed, bins=bins, color='gray', range=(vmin, vmax))
|
|
1558
1548
|
plt.xlabel('Pixel value')
|
|
1559
1549
|
plt.ylabel('Probabilty' if normed else 'Count')
|
|
1560
1550
|
plt.show()
|
|
@@ -1761,7 +1751,7 @@ class GeoArray(object):
|
|
|
1761
1751
|
"""Return the array data of GeoArray at a given geographic position.
|
|
1762
1752
|
|
|
1763
1753
|
NOTE: The given mapBounds are snapped to the pixel grid of GeoArray. If the given mapBounds include areas
|
|
1764
|
-
outside
|
|
1754
|
+
outside the extent of GeoArray, these areas are filled with the fill value of GeoArray.
|
|
1765
1755
|
|
|
1766
1756
|
:param mapBounds: xmin, ymin, xmax, ymax
|
|
1767
1757
|
:param mapBounds_prj: WKT projection string or EPSG code corresponding to mapBounds
|
|
@@ -1980,7 +1970,7 @@ class GeoArray(object):
|
|
|
1980
1970
|
coordinates.
|
|
1981
1971
|
:param band: the band index of the band of interest. If None, the values of all bands are
|
|
1982
1972
|
returned.
|
|
1983
|
-
:param offside_val: fill value in case input coordinates are geographically outside
|
|
1973
|
+
:param offside_val: fill value in case input coordinates are geographically outside the GeoArray
|
|
1984
1974
|
instance
|
|
1985
1975
|
:return: - int in case only a singe coordinate is passed
|
|
1986
1976
|
- np.ndarray with shape [Nx1] in case only one band is requested
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# you may not use this file except in compliance with the License.
|
|
16
16
|
# You may obtain a copy of the License at
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
19
19
|
#
|
|
20
20
|
# Unless required by applicable law or agreed to in writing, software
|
|
21
21
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# you may not use this file except in compliance with the License.
|
|
16
16
|
# You may obtain a copy of the License at
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
19
19
|
#
|
|
20
20
|
# Unless required by applicable law or agreed to in writing, software
|
|
21
21
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -160,9 +160,7 @@ class GDAL_Metadata(object):
|
|
|
160
160
|
not filePath.startswith('NETCDF'):
|
|
161
161
|
raise FileNotFoundError(filePath)
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
try:
|
|
163
|
+
with gdal.Open(filePath) as ds:
|
|
166
164
|
if not ds:
|
|
167
165
|
raise Exception('Error reading file: ' + gdal.GetLastErrorMsg())
|
|
168
166
|
|
|
@@ -230,9 +228,6 @@ class GDAL_Metadata(object):
|
|
|
230
228
|
# self.df[b] = meta_gs
|
|
231
229
|
del band
|
|
232
230
|
|
|
233
|
-
finally:
|
|
234
|
-
del ds
|
|
235
|
-
|
|
236
231
|
return self.all_meta
|
|
237
232
|
|
|
238
233
|
def __repr__(self) -> str:
|
|
@@ -251,7 +246,21 @@ class GDAL_Metadata(object):
|
|
|
251
246
|
# subset bands
|
|
252
247
|
if bands2extract is not None:
|
|
253
248
|
if isinstance(bands2extract, list):
|
|
254
|
-
|
|
249
|
+
if not len(set([type(i) for i in bands2extract])) == 1:
|
|
250
|
+
raise ValueError("List items of 'bands2extract' should all have the same type.")
|
|
251
|
+
if not isinstance(bands2extract[0], str):
|
|
252
|
+
bands2extract = np.array(bands2extract)
|
|
253
|
+
else:
|
|
254
|
+
if 'band_names' not in meta_sub.band_meta:
|
|
255
|
+
raise ValueError('String input is only supported if band names are set.')
|
|
256
|
+
bandnames = meta_sub.band_meta['band_names']
|
|
257
|
+
out = []
|
|
258
|
+
for b in bands2extract:
|
|
259
|
+
if b in bandnames:
|
|
260
|
+
out.append(bandnames.index(b))
|
|
261
|
+
else:
|
|
262
|
+
raise ValueError(f"'{b}' is not a valid band name.")
|
|
263
|
+
bands2extract = np.array(out)
|
|
255
264
|
elif isinstance(bands2extract, (np.ndarray, slice)):
|
|
256
265
|
pass # all fine
|
|
257
266
|
else:
|
|
@@ -267,6 +276,9 @@ class GDAL_Metadata(object):
|
|
|
267
276
|
|
|
268
277
|
# subset metadata keys
|
|
269
278
|
if keys2extract:
|
|
279
|
+
if isinstance(keys2extract, list) and not list(set([type(i) for i in keys2extract])) == [str]:
|
|
280
|
+
raise ValueError("List items of 'keys2extract' should all be of type string.")
|
|
281
|
+
|
|
270
282
|
keys2extract = [keys2extract] if isinstance(keys2extract, str) else keys2extract
|
|
271
283
|
|
|
272
284
|
# global_meta = meta_sub.global_meta.copy()
|
|
@@ -284,22 +296,22 @@ class GDAL_Metadata(object):
|
|
|
284
296
|
return meta_sub
|
|
285
297
|
|
|
286
298
|
def __getitem__(self, given: Union[int, slice, str, list, np.ndarray]) -> 'GDAL_Metadata':
|
|
287
|
-
if isinstance(given, int):
|
|
299
|
+
if isinstance(given, (int, np.integer)):
|
|
288
300
|
return self.get_subset(bands2extract=slice(given, given + 1))
|
|
289
301
|
elif isinstance(given, slice):
|
|
290
302
|
return self.get_subset(bands2extract=given)
|
|
291
303
|
elif isinstance(given, str):
|
|
292
|
-
return self.get_subset(
|
|
304
|
+
return self.get_subset(bands2extract=[given])
|
|
293
305
|
elif isinstance(given, list):
|
|
294
306
|
if isinstance(given[0], str):
|
|
295
|
-
return self.get_subset(
|
|
296
|
-
elif isinstance(given[0], int):
|
|
307
|
+
return self.get_subset(bands2extract=given)
|
|
308
|
+
elif isinstance(given[0], (int, np.integer)):
|
|
297
309
|
return self.get_subset(bands2extract=given)
|
|
298
310
|
else:
|
|
299
311
|
raise TypeError(given, 'Given list must contain string or integer items.')
|
|
300
312
|
elif isinstance(given, np.ndarray):
|
|
301
313
|
if given.ndim != 1:
|
|
302
|
-
raise
|
|
314
|
+
raise ValueError(given, 'Given numpy array must be one-dimensional.')
|
|
303
315
|
return self.get_subset(bands2extract=given)
|
|
304
316
|
else:
|
|
305
317
|
raise TypeError(given)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# you may not use this file except in compliance with the License.
|
|
16
16
|
# You may obtain a copy of the License at
|
|
17
17
|
#
|
|
18
|
-
#
|
|
18
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
19
19
|
#
|
|
20
20
|
# Unless required by applicable law or agreed to in writing, software
|
|
21
21
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# you may not use this file except in compliance with the License.
|
|
14
14
|
# You may obtain a copy of the License at
|
|
15
15
|
#
|
|
16
|
-
#
|
|
16
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
17
17
|
#
|
|
18
18
|
# Unless required by applicable law or agreed to in writing, software
|
|
19
19
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
# limitations under the License.
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
__version__ = '0.
|
|
26
|
-
__versionalias__ = '
|
|
25
|
+
__version__ = '0.18.0'
|
|
26
|
+
__versionalias__ = '20240705.01'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: geoarray
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.0
|
|
4
4
|
Summary: Fast Python interface for geodata - either on disk or in memory.
|
|
5
5
|
Home-page: https://git.gfz-potsdam.de/danschef/geoarray
|
|
6
6
|
Author: Daniel Scheffler
|
|
@@ -15,13 +15,14 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
19
|
Requires-Python: >=3.8
|
|
19
20
|
Description-Content-Type: text/x-rst
|
|
20
21
|
License-File: LICENSE
|
|
21
22
|
License-File: AUTHORS.rst
|
|
22
23
|
Requires-Dist: cartopy>=0.20
|
|
23
24
|
Requires-Dist: dill
|
|
24
|
-
Requires-Dist: gdal>=
|
|
25
|
+
Requires-Dist: gdal>=3.8.0
|
|
25
26
|
Requires-Dist: matplotlib
|
|
26
27
|
Requires-Dist: numpy
|
|
27
28
|
Requires-Dist: pandas
|
|
@@ -38,7 +39,7 @@ Requires-Dist: sphinx_rtd_theme; extra == "doc"
|
|
|
38
39
|
Provides-Extra: test
|
|
39
40
|
Requires-Dist: cartopy>=0.20; extra == "test"
|
|
40
41
|
Requires-Dist: dill; extra == "test"
|
|
41
|
-
Requires-Dist: gdal>=
|
|
42
|
+
Requires-Dist: gdal>=3.8.0; extra == "test"
|
|
42
43
|
Requires-Dist: matplotlib; extra == "test"
|
|
43
44
|
Requires-Dist: numpy; extra == "test"
|
|
44
45
|
Requires-Dist: pandas; extra == "test"
|
|
@@ -58,7 +59,7 @@ Provides-Extra: dev
|
|
|
58
59
|
Requires-Dist: setuptools-git; extra == "dev"
|
|
59
60
|
Requires-Dist: cartopy>=0.20; extra == "dev"
|
|
60
61
|
Requires-Dist: dill; extra == "dev"
|
|
61
|
-
Requires-Dist: gdal>=
|
|
62
|
+
Requires-Dist: gdal>=3.8.0; extra == "dev"
|
|
62
63
|
Requires-Dist: matplotlib; extra == "dev"
|
|
63
64
|
Requires-Dist: numpy; extra == "dev"
|
|
64
65
|
Requires-Dist: pandas; extra == "dev"
|
|
@@ -155,7 +156,7 @@ open source packages that may cause problems when installed with pip. Therefore,
|
|
|
155
156
|
to resolve the following dependencies before the pip installer is run:
|
|
156
157
|
|
|
157
158
|
* cartopy >=0.20
|
|
158
|
-
* gdal >=
|
|
159
|
+
* gdal >=3.8.0
|
|
159
160
|
* geopandas
|
|
160
161
|
* holoviews # optional, in case you want to use interactive plotting
|
|
161
162
|
* matplotlib
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cartopy>=0.20
|
|
2
2
|
dill
|
|
3
|
-
gdal>=
|
|
3
|
+
gdal>=3.8.0
|
|
4
4
|
matplotlib
|
|
5
5
|
numpy
|
|
6
6
|
pandas
|
|
@@ -12,7 +12,7 @@ shapely
|
|
|
12
12
|
setuptools-git
|
|
13
13
|
cartopy>=0.20
|
|
14
14
|
dill
|
|
15
|
-
gdal>=
|
|
15
|
+
gdal>=3.8.0
|
|
16
16
|
matplotlib
|
|
17
17
|
numpy
|
|
18
18
|
pandas
|
|
@@ -47,7 +47,7 @@ pydocstyle
|
|
|
47
47
|
[test]
|
|
48
48
|
cartopy>=0.20
|
|
49
49
|
dill
|
|
50
|
-
gdal>=
|
|
50
|
+
gdal>=3.8.0
|
|
51
51
|
matplotlib
|
|
52
52
|
numpy
|
|
53
53
|
pandas
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
# you may not use this file except in compliance with the License.
|
|
17
17
|
# You may obtain a copy of the License at
|
|
18
18
|
#
|
|
19
|
-
#
|
|
19
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
20
20
|
#
|
|
21
21
|
# Unless required by applicable law or agreed to in writing, software
|
|
22
22
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -40,7 +40,7 @@ with open("geoarray/version.py") as version_file:
|
|
|
40
40
|
req = [
|
|
41
41
|
'cartopy>=0.20', # older versions require pyepsg
|
|
42
42
|
'dill',
|
|
43
|
-
'gdal>=
|
|
43
|
+
'gdal>=3.8.0', # use of context managers
|
|
44
44
|
'matplotlib',
|
|
45
45
|
'numpy',
|
|
46
46
|
'pandas',
|
|
@@ -89,7 +89,8 @@ setup(
|
|
|
89
89
|
'Programming Language :: Python :: 3.8',
|
|
90
90
|
'Programming Language :: Python :: 3.9',
|
|
91
91
|
'Programming Language :: Python :: 3.10',
|
|
92
|
-
'Programming Language :: Python :: 3.11'
|
|
92
|
+
'Programming Language :: Python :: 3.11',
|
|
93
|
+
'Programming Language :: Python :: 3.12'
|
|
93
94
|
],
|
|
94
95
|
python_requires='>=3.8',
|
|
95
96
|
test_suite='tests',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|