sgspy 1.0.2__cp313-cp313-manylinux_2_28_x86_64.whl

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.
Files changed (40) hide show
  1. sgspy/__init__.py +82 -0
  2. sgspy/_sgs.cpython-313-x86_64-linux-gnu.so +0 -0
  3. sgspy/calculate/__init__.py +18 -0
  4. sgspy/calculate/pca/__init__.py +2 -0
  5. sgspy/calculate/pca/pca.py +158 -0
  6. sgspy/calculate/representation/__init__.py +2 -0
  7. sgspy/calculate/representation/representation.py +3 -0
  8. sgspy/sample/__init__.py +30 -0
  9. sgspy/sample/ahels/__init__.py +2 -0
  10. sgspy/sample/ahels/ahels.py +3 -0
  11. sgspy/sample/clhs/__init__.py +2 -0
  12. sgspy/sample/clhs/clhs.py +202 -0
  13. sgspy/sample/nc/__init__.py +2 -0
  14. sgspy/sample/nc/nc.py +3 -0
  15. sgspy/sample/srs/__init__.py +2 -0
  16. sgspy/sample/srs/srs.py +228 -0
  17. sgspy/sample/strat/__init__.py +2 -0
  18. sgspy/sample/strat/strat.py +394 -0
  19. sgspy/sample/systematic/__init__.py +2 -0
  20. sgspy/sample/systematic/systematic.py +233 -0
  21. sgspy/stratify/__init__.py +27 -0
  22. sgspy/stratify/breaks/__init__.py +2 -0
  23. sgspy/stratify/breaks/breaks.py +222 -0
  24. sgspy/stratify/kmeans/__init__.py +2 -0
  25. sgspy/stratify/kmeans/kmeans.py +3 -0
  26. sgspy/stratify/map/__init__.py +2 -0
  27. sgspy/stratify/map/map_stratifications.py +244 -0
  28. sgspy/stratify/poly/__init__.py +2 -0
  29. sgspy/stratify/poly/poly.py +170 -0
  30. sgspy/stratify/quantiles/__init__.py +2 -0
  31. sgspy/stratify/quantiles/quantiles.py +276 -0
  32. sgspy/utils/__init__.py +18 -0
  33. sgspy/utils/plot.py +143 -0
  34. sgspy/utils/raster.py +605 -0
  35. sgspy/utils/vector.py +268 -0
  36. sgspy-1.0.2.data/data/sgspy/libonedal.so.3 +0 -0
  37. sgspy-1.0.2.data/data/sgspy/proj.db +0 -0
  38. sgspy-1.0.2.dist-info/METADATA +13 -0
  39. sgspy-1.0.2.dist-info/RECORD +40 -0
  40. sgspy-1.0.2.dist-info/WHEEL +5 -0
sgspy/utils/vector.py ADDED
@@ -0,0 +1,268 @@
1
+ # ******************************************************************************
2
+ #
3
+ # Project: sgs
4
+ # Purpose: GDALDataset wrapper for vector operations
5
+ # Author: Joseph Meyer
6
+ # Date: June, 2025
7
+ #
8
+ # ******************************************************************************
9
+
10
+ import sys
11
+ import os
12
+ import site
13
+ import tempfile
14
+ from typing import Optional
15
+ import warnings
16
+
17
+ import matplotlib.pyplot as plt
18
+ import matplotlib #fpr type checking matplotlib.axes.Axes
19
+
20
+ from.import plot
21
+ from .plot import plot_vector
22
+
23
+ #ensure _sgs binary can be found
24
+ site_packages = list(filter(lambda x : 'site-packages' in x, site.getsitepackages()))[0]
25
+ sys.path.append(os.path.join(site_packages, "sgspy"))
26
+ sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
27
+ from _sgs import GDALRasterWrapper
28
+
29
+ from _sgs import GDALVectorWrapper
30
+
31
+ try:
32
+ import geopandas as gpd
33
+ GEOPANDAS = True
34
+ except ImportError as e:
35
+ GEOPANDAS = False
36
+
37
+ PROJDB_PATH = os.path.join(sys.prefix, "sgspy")
38
+
39
+ ##
40
+ # @ingroup user_utils
41
+ # This class represents a spatial vector, and is used as an input to many sgs functions.
42
+ #
43
+ # It has a number of additional uses, including displaying info about the vector, converting
44
+ # to a GDAL or GeoPandas object.
45
+ #
46
+ # Accessing vector info:
47
+ #
48
+ # vector metadata can be displayed using the info() function. All layers
49
+ # are displayed unless a specific layer is specified. The per-layer info
50
+ # includes: name, number of features, number of fields, geomtype, and bounds.
51
+ #
52
+ # Public Attributes:
53
+ # --------------------
54
+ # layer_names : list[str] @n
55
+ # a list of layer names
56
+ #
57
+ # Public Methods:
58
+ # --------------------
59
+ # info() @n
60
+ # takes an optional argument specify the band, and prints vector metadata to console
61
+ class SpatialVector:
62
+
63
+ def __init__(self,
64
+ image: str | GDALVectorWrapper):
65
+ """
66
+ Constructing method for the SpatialVector class.
67
+
68
+ Has one required parameter to specify a gdal dataset. The following
69
+ attributes are populated:
70
+ self.cpp_vector
71
+ self.layer_names
72
+
73
+ Parameters
74
+ --------------------
75
+ image: str | GDALVectorWrapper
76
+ specifies a path to a vector file or the C++ class object itself
77
+ """
78
+ if type(image) is str:
79
+ self.cpp_vector = GDALVectorWrapper(image, PROJDB_PATH)
80
+ elif type(image) is GDALVectorWrapper:
81
+ self.cpp_vector = image
82
+ else:
83
+ raise TypeError("'image' parameter to SpatialVector constructor must be of type str or GDALVectorWrapper.")
84
+
85
+ self.layers = self.cpp_vector.get_layer_names()
86
+
87
+ def print_info(self,
88
+ layer_name: str,
89
+ layer_info: dict):
90
+ """
91
+ prints layer information using the layer_info from self.cpp_vector.
92
+
93
+ This is an internal function not meant to be used by the end user.
94
+
95
+ Parameters
96
+ --------------------
97
+ name : str
98
+ str containing the layer name
99
+ layer_info : dict
100
+ dict containing 'feature_count', 'field_count', 'geometry_type', 'xmax', 'xmin', 'ymax', and 'ymin' items
101
+ """
102
+ print("{} layer info:".format(layer_name))
103
+ print("feature count: {}".format(layer_info['feature_count']))
104
+ print("field count: {}".format(layer_info['field_count']))
105
+ print("geometry type: {}".format(layer_info['geometry_type']))
106
+ print("bounds (xmin, xmax, ymin, ymax): ({}, {}, {}, {})".format(
107
+ layer_info['xmin'],
108
+ layer_info['xmax'],
109
+ layer_info['ymin'],
110
+ layer_info['ymax']
111
+ ))
112
+ if layer_info['crs']: print("crs: {}".format(layer_info['crs']))
113
+ print()
114
+
115
+ def info(self,
116
+ layer: Optional[int | str] = None):
117
+ """
118
+ calls self.print_info depending on layer parameter. If no layer is given,
119
+ print all layers. A layer may be specified by either a str or an int.
120
+
121
+ Parameters
122
+ --------------------
123
+ layer : str or int
124
+ specifies the layer to print information on
125
+ """
126
+ if layer is not None and type(layer) not in [int, str]:
127
+ raise TypeError("'layer' parameter, if given, must be of type int or str.")
128
+
129
+ if type(layer) == str:
130
+ self.print_info(layer, self.cpp_vector.get_layer_info(layer))
131
+ elif type(layer) == int:
132
+ self.print_info(self.layers[layer], self.cpp_vector.get_layer_info(self.layers[layer]))
133
+ else:
134
+ for layer in self.layers:
135
+ self.print_info(layer, self.cpp_vector.get_layer_info(layer))
136
+
137
+ def samples_as_wkt(self):
138
+ """
139
+ Calls get_wkt_points on the underlying cpp class, to return
140
+ the samples as wkt strings.
141
+
142
+ This function requires that there be a layer named 'samples' which
143
+ is comprised entirely of Points or MultiPoints. These conditions
144
+ will be satisfied if this SpatialVector is the output of one of the
145
+ sampling functions in the sgs package.
146
+ """
147
+ if "samples" not in self.layers:
148
+ print("this vector does not have a layer 'samples'")
149
+ else:
150
+ return self.cpp_vector.get_wkt_points('samples')
151
+
152
+ def plot(self,
153
+ geomtype: str,
154
+ ax: Optional[matplotlib.axes.Axes] = None,
155
+ layer: Optional[int | str] = None,
156
+ **kwargs):
157
+ """
158
+ Calls plot_vector on self.
159
+
160
+ Paramters
161
+ --------------------
162
+ ax : matplotlib.axes.Axes
163
+ axes to plot the raster on
164
+ geomtype : str
165
+ the geometry type to try to print
166
+ layer : None | int | str
167
+ specification of which layer to print
168
+ **kwargs
169
+ any parameter which may be passed ot matplotlib.pyplot.plot
170
+ """
171
+
172
+ if ax is not None:
173
+ plot_vector(self, ax, geomtype, layer, **kwargs)
174
+ else:
175
+ fig, ax = plt.subplots()
176
+ plot_vector(self, ax, geomtype, layer, **kwargs)
177
+ plt.show()
178
+
179
+ @classmethod
180
+ def from_geopandas(cls, obj, layer_name: str=None):
181
+ """
182
+ This function is used to convert a geopandas object into an sgspy.SpatialVector. The geopandas object
183
+ may either by of type GeoDataFrame or GeoSeries.
184
+
185
+ If a particular layer name is desired, it can be passed as a parameter.
186
+
187
+ Examples:
188
+
189
+ gdf = gpd.read_file("access.shp")
190
+ access = sgspy.SpatialVector.from_geopandas(gdf)
191
+
192
+
193
+ gs = gpd['geometry'] #geometry column is a geoseries
194
+ access = sgspy.SpatialVector.from_geopandas(gs)
195
+
196
+
197
+ gdf = gpd.read_file("access.shp")
198
+ gdf = gdf[gdf == "LineString"]
199
+ access = sgspy.SpatialVector.from_geopandas(gdf)
200
+ """
201
+ if layer_name is not None and type(layer_name) is not str:
202
+ raise TypeError("layer_name, if given, must be of type 'str'.")
203
+
204
+ if not GEOPANDAS:
205
+ raise RuntimeError("from_geopandas() can only be called if geopandas was successfully imported, but it wasn't.")
206
+
207
+ if type(obj) is not gpd.geodataframe.GeoDataFrame and type(obj) is not gpd.geoseries.GeoSeries:
208
+ raise TypeError("the object passed must be of type geopandas GeoDataFrame or GeoSeries")
209
+
210
+ #get a the geopandas object as a geoseries
211
+ if type(obj) is gpd.geodataframe.GeoDataFrame:
212
+ if 'geometry' not in obj.columns:
213
+ raise RuntimeError("'geometry' must be a column in the geodataframe passed")
214
+ gdf = obj
215
+ gs = gdf['geometry']
216
+ else:
217
+ gs = obj
218
+ gdf = gpd.GeoDataFrame(gs)
219
+
220
+ if layer_name is None: layer_name = 'geopandas_geodataframe'
221
+ projection = gs.crs.to_wkt()
222
+
223
+ # the conversion to geojson may raise a warning about how the projection is unable to be converted to the new format correctly
224
+ #
225
+ # however, we have the projection from the geodataframes geoseries crs, so it won't be an issue
226
+ with warnings.catch_warnings():
227
+ warnings.simplefilter("ignore")
228
+ geojson = gdf.to_json().encode('utf-8')
229
+
230
+ cpp_vector = GDALVectorWrapper(geojson, projection, layer_name, PROJDB_PATH)
231
+ return cls(cpp_vector)
232
+
233
+ def to_geopandas(self):
234
+ """
235
+ This function is used to convert an sgspy.SpatialVector into a geopandas geodataframe.
236
+
237
+ Examples:
238
+
239
+ access = sgspy.SpatialVector("access.shp")
240
+ gdf = access.to_geopandas()
241
+ """
242
+ if not GEOPANDAS:
243
+ raise RuntimeError("to_geopandas() can only be called if geopandas was successfully imported, but it wasn't.")
244
+
245
+ tempdir = tempfile.gettempdir()
246
+ file = os.path.join(tempdir, "temp.geojson")
247
+
248
+ #get the projection info
249
+ projection = self.cpp_vector.get_projection()
250
+
251
+ #write the dataset to a tempfile
252
+ self.cpp_vector.write(file)
253
+
254
+ # This method of writing to a file then reading from that file is definitely clunky,
255
+ # however it's easy. Theres the possiblity of iterating through every field within
256
+ # every feature, and needing to then call a different function depending on the data
257
+ # type of the field (because C++ types are rigid). That may still be done in the future,
258
+ # but for now this works.
259
+
260
+ #have geopandas read the tempfile
261
+ gdf = gpd.read_file(file)
262
+ if projection != "": gdf.set_crs(projection, inplace=True, allow_override=True)
263
+
264
+ #remove the geojson file
265
+ os.remove(file)
266
+
267
+ return gdf
268
+
Binary file
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.1
2
+ Name: sgspy
3
+ Version: 1.0.2
4
+ Requires-Dist: numpy
5
+ Requires-Dist: matplotlib
6
+ Requires-Dist: daal==2025.9.0
7
+ Requires-Dist: tbb==2022.*
8
+ Requires-Dist: mkl==2025.3.0
9
+ Requires-Dist: onemkl-license==2025.3.0
10
+ Provides-Extra: test
11
+ Requires-Dist: pytest; extra == "test"
12
+ Requires-Dist: geopandas; extra == "test"
13
+
@@ -0,0 +1,40 @@
1
+ sgspy/__init__.py,sha256=ONzqVZBLUs0Zm4s-x09HDoVWICfjDeygpzBscn9JHA0,2582
2
+ sgspy/_sgs.cpython-313-x86_64-linux-gnu.so,sha256=TfFOr1UZP8mCbG5KS7nL5opDzWu2WWOdVJeRDPalOdI,86466384
3
+ sgspy/calculate/__init__.py,sha256=CA6GtS3Lym_TtYYlMp6j02uf57DDlq3vGzN8qXxYDuc,331
4
+ sgspy/calculate/pca/__init__.py,sha256=L6jpsKWDSch-Rq4CqJSBO0elALd_yzuvTY2JASAipB8,39
5
+ sgspy/calculate/pca/pca.py,sha256=yaaZitdTQ0p25REkpUQwnIxNi0kiCeOE8mkxWl8aoZg,5422
6
+ sgspy/calculate/representation/__init__.py,sha256=yiDee7Cw6LnAbuATKMWXneVPBwhogV_5rIunK-USh7I,72
7
+ sgspy/calculate/representation/representation.py,sha256=nKNNlWmmF1uFyM9KuD9Y8Qj-YfYGfpSRuPZ_zUpNalE,72
8
+ sgspy/sample/__init__.py,sha256=Z20McdhG5A4J5qtwZ9O7CyH_tbXNKnYA54WINVwU-F0,422
9
+ sgspy/sample/ahels/__init__.py,sha256=2oAo9Fkck1BRqyVNfzr9rbWvQ4Jt2lg72EG7SIVbKzU,45
10
+ sgspy/sample/ahels/ahels.py,sha256=skPsJ3OhQAHBP9wHY3LGVlmnqkRlsidAFkv7CqpgWHM,63
11
+ sgspy/sample/clhs/__init__.py,sha256=vddVyTqOvsBoODikmdValw-pwEfYohlHo4Wlz-MnyQE,42
12
+ sgspy/sample/clhs/clhs.py,sha256=0F3Z4pIUZ0FeOPtK5WRO2ToNt7JF0M0Uh7Yw_yLU6uo,7528
13
+ sgspy/sample/nc/__init__.py,sha256=c5P2cH42Q23-hBguVF81b8KbcaFypg1PBw0TGY7nf6o,36
14
+ sgspy/sample/nc/nc.py,sha256=77sqsBpNYsyqVRoAoEnhAGM_WjQrNBnyHTdSUc67334,60
15
+ sgspy/sample/srs/__init__.py,sha256=0_Qm4f_6iE1Ds4AHQp_8t9UZZ7I0m46xWRvL4o6pKow,39
16
+ sgspy/sample/srs/srs.py,sha256=QqV1xdHo9a-jQv4C4nrtOpZdxVys_xmrDcYhR0LdwKA,7974
17
+ sgspy/sample/strat/__init__.py,sha256=WYiabUGZckk38Qhr1fFXhS8sh9BqyXtGEBPJ9lstpJo,45
18
+ sgspy/sample/strat/strat.py,sha256=KPzwzEj2HACUsOuMDrbUZOTM8GM3q6ldT6EAVDYuw2M,16171
19
+ sgspy/sample/systematic/__init__.py,sha256=frl-x5lN3zY7Q5HzbvwT0zz50Byh7VDoSgYDcG_vKbA,60
20
+ sgspy/sample/systematic/systematic.py,sha256=HPM2VTzFm2Q5Ge2Qhq-3yqL-u-KuiBCr2QzBiRykRVo,8336
21
+ sgspy/stratify/__init__.py,sha256=RULBeQemsCmVjHu57Me2tptDIlhe64M_PtvCsRpXe4Q,399
22
+ sgspy/stratify/breaks/__init__.py,sha256=45VAzOTJVGOn4kfU8w-mA2lq4PP5Z0PZjWbIt6RLj_k,48
23
+ sgspy/stratify/breaks/breaks.py,sha256=ekkanqFzjE3cUhVO9vwnukodJdnaSf3HXzOKBV6zhwo,9099
24
+ sgspy/stratify/kmeans/__init__.py,sha256=PjR6Uh8xhpId2HIl7vbysdduQpXO7l00FDmR9QAWa4M,48
25
+ sgspy/stratify/kmeans/kmeans.py,sha256=unem1jiJAwzdfdGnCRYn-47eeZXJccCaT7nL9d5ViXs,64
26
+ sgspy/stratify/map/__init__.py,sha256=uw8HivY0wg9Tke4XI8vtHCMNMYJOmncHb2Enl3jTg7s,71
27
+ sgspy/stratify/map/map_stratifications.py,sha256=RYdpBsZV61Evo73OzGx2KUXC0IufcgsZ6iChXh2PvWQ,10652
28
+ sgspy/stratify/poly/__init__.py,sha256=CfCIvJBQIqqS8aQG-52Ja9bRxrBN1jbcUBTkbkhD9KY,42
29
+ sgspy/stratify/poly/poly.py,sha256=Dt_wTxshxw02lbKVjLgS1yFWh5qJbVklTnVqPdzrSW0,6233
30
+ sgspy/stratify/quantiles/__init__.py,sha256=_g9MTbV7PIZxdshhEvJtZRLBCS5ehoUqZNCMBHrnOsQ,57
31
+ sgspy/stratify/quantiles/quantiles.py,sha256=ZjMoJNt2WUkpE7Jsbs_nPQcNP9rvf4EMYUyVOmGr9Y4,12195
32
+ sgspy/utils/__init__.py,sha256=XXEYEVdjUa345mCs0d5Bj7lVCyHEwMoDvselH-Deebs,287
33
+ sgspy/utils/plot.py,sha256=9gnW0C8vK5AUDKBi00830V9i5ciXVXROTH7A1TLqN0c,5528
34
+ sgspy/utils/raster.py,sha256=EOSZJOoWZ7IKo_iar4iHiWV74q_IT9HNQ4NRIfVoIQg,22945
35
+ sgspy/utils/vector.py,sha256=vHkIg7v85ljgO6MsRt-cRxLVw_bAZQPbiRto8k4YQko,9576
36
+ sgspy-1.0.2.data/data/sgspy/libonedal.so.3,sha256=sAmzMql47Yy9eO70uraCrAoAkJiYfYLMXs5CrwTr82I,10841849
37
+ sgspy-1.0.2.data/data/sgspy/proj.db,sha256=sGOmBu2wzZwqDJ9V5yu9mez2dvZCrqH4izR1mp9Q0Lk,9359360
38
+ sgspy-1.0.2.dist-info/METADATA,sha256=hiYB5ZO_eU0RMBYvkhNY45vq2MA07RhGMZb3EDhJJwQ,325
39
+ sgspy-1.0.2.dist-info/WHEEL,sha256=22Lftwvjz7BjVNTxxDM8SyAm3GLe_fJvO71HQ9qo0Mw,99
40
+ sgspy-1.0.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: meson
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-manylinux_2_28_x86_64
5
+