sgspy 1.0.1__cp313-cp313-manylinux_2_39_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 +152 -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 +198 -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 +224 -0
  17. sgspy/sample/strat/__init__.py +2 -0
  18. sgspy/sample/strat/strat.py +390 -0
  19. sgspy/sample/systematic/__init__.py +2 -0
  20. sgspy/sample/systematic/systematic.py +229 -0
  21. sgspy/stratify/__init__.py +27 -0
  22. sgspy/stratify/breaks/__init__.py +2 -0
  23. sgspy/stratify/breaks/breaks.py +218 -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 +240 -0
  28. sgspy/stratify/poly/__init__.py +2 -0
  29. sgspy/stratify/poly/poly.py +166 -0
  30. sgspy/stratify/quantiles/__init__.py +2 -0
  31. sgspy/stratify/quantiles/quantiles.py +272 -0
  32. sgspy/utils/__init__.py +18 -0
  33. sgspy/utils/plot.py +143 -0
  34. sgspy/utils/raster.py +602 -0
  35. sgspy/utils/vector.py +262 -0
  36. sgspy-1.0.1.data/data/sgspy/libonedal.so.3 +0 -0
  37. sgspy-1.0.1.data/data/sgspy/proj.db +0 -0
  38. sgspy-1.0.1.dist-info/METADATA +13 -0
  39. sgspy-1.0.1.dist-info/RECORD +40 -0
  40. sgspy-1.0.1.dist-info/WHEEL +5 -0
sgspy/utils/vector.py ADDED
@@ -0,0 +1,262 @@
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 tempfile
13
+ from typing import Optional
14
+ import warnings
15
+
16
+ import matplotlib.pyplot as plt
17
+ import matplotlib #fpr type checking matplotlib.axes.Axes
18
+
19
+ from.import plot
20
+ from .plot import plot_vector
21
+
22
+ sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
23
+ from _sgs import GDALVectorWrapper
24
+
25
+ try:
26
+ import geopandas as gpd
27
+ GEOPANDAS = True
28
+ except ImportError as e:
29
+ GEOPANDAS = False
30
+
31
+ PROJDB_PATH = os.path.join(sys.prefix, "sgspy")
32
+
33
+ ##
34
+ # @ingroup user_utils
35
+ # This class represents a spatial vector, and is used as an input to many sgs functions.
36
+ #
37
+ # It has a number of additional uses, including displaying info about the vector, converting
38
+ # to a GDAL or GeoPandas object.
39
+ #
40
+ # Accessing vector info:
41
+ #
42
+ # vector metadata can be displayed using the info() function. All layers
43
+ # are displayed unless a specific layer is specified. The per-layer info
44
+ # includes: name, number of features, number of fields, geomtype, and bounds.
45
+ #
46
+ # Public Attributes:
47
+ # --------------------
48
+ # layer_names : list[str] @n
49
+ # a list of layer names
50
+ #
51
+ # Public Methods:
52
+ # --------------------
53
+ # info() @n
54
+ # takes an optional argument specify the band, and prints vector metadata to console
55
+ class SpatialVector:
56
+
57
+ def __init__(self,
58
+ image: str | GDALVectorWrapper):
59
+ """
60
+ Constructing method for the SpatialVector class.
61
+
62
+ Has one required parameter to specify a gdal dataset. The following
63
+ attributes are populated:
64
+ self.cpp_vector
65
+ self.layer_names
66
+
67
+ Parameters
68
+ --------------------
69
+ image: str | GDALVectorWrapper
70
+ specifies a path to a vector file or the C++ class object itself
71
+ """
72
+ if type(image) is str:
73
+ self.cpp_vector = GDALVectorWrapper(image, PROJDB_PATH)
74
+ elif type(image) is GDALVectorWrapper:
75
+ self.cpp_vector = image
76
+ else:
77
+ raise TypeError("'image' parameter to SpatialVector constructor must be of type str or GDALVectorWrapper.")
78
+
79
+ self.layers = self.cpp_vector.get_layer_names()
80
+
81
+ def print_info(self,
82
+ layer_name: str,
83
+ layer_info: dict):
84
+ """
85
+ prints layer information using the layer_info from self.cpp_vector.
86
+
87
+ This is an internal function not meant to be used by the end user.
88
+
89
+ Parameters
90
+ --------------------
91
+ name : str
92
+ str containing the layer name
93
+ layer_info : dict
94
+ dict containing 'feature_count', 'field_count', 'geometry_type', 'xmax', 'xmin', 'ymax', and 'ymin' items
95
+ """
96
+ print("{} layer info:".format(layer_name))
97
+ print("feature count: {}".format(layer_info['feature_count']))
98
+ print("field count: {}".format(layer_info['field_count']))
99
+ print("geometry type: {}".format(layer_info['geometry_type']))
100
+ print("bounds (xmin, xmax, ymin, ymax): ({}, {}, {}, {})".format(
101
+ layer_info['xmin'],
102
+ layer_info['xmax'],
103
+ layer_info['ymin'],
104
+ layer_info['ymax']
105
+ ))
106
+ if layer_info['crs']: print("crs: {}".format(layer_info['crs']))
107
+ print()
108
+
109
+ def info(self,
110
+ layer: Optional[int | str] = None):
111
+ """
112
+ calls self.print_info depending on layer parameter. If no layer is given,
113
+ print all layers. A layer may be specified by either a str or an int.
114
+
115
+ Parameters
116
+ --------------------
117
+ layer : str or int
118
+ specifies the layer to print information on
119
+ """
120
+ if layer is not None and type(layer) not in [int, str]:
121
+ raise TypeError("'layer' parameter, if given, must be of type int or str.")
122
+
123
+ if type(layer) == str:
124
+ self.print_info(layer, self.cpp_vector.get_layer_info(layer))
125
+ elif type(layer) == int:
126
+ self.print_info(self.layers[layer], self.cpp_vector.get_layer_info(self.layers[layer]))
127
+ else:
128
+ for layer in self.layers:
129
+ self.print_info(layer, self.cpp_vector.get_layer_info(layer))
130
+
131
+ def samples_as_wkt(self):
132
+ """
133
+ Calls get_wkt_points on the underlying cpp class, to return
134
+ the samples as wkt strings.
135
+
136
+ This function requires that there be a layer named 'samples' which
137
+ is comprised entirely of Points or MultiPoints. These conditions
138
+ will be satisfied if this SpatialVector is the output of one of the
139
+ sampling functions in the sgs package.
140
+ """
141
+ if "samples" not in self.layers:
142
+ print("this vector does not have a layer 'samples'")
143
+ else:
144
+ return self.cpp_vector.get_wkt_points('samples')
145
+
146
+ def plot(self,
147
+ geomtype: str,
148
+ ax: Optional[matplotlib.axes.Axes] = None,
149
+ layer: Optional[int | str] = None,
150
+ **kwargs):
151
+ """
152
+ Calls plot_vector on self.
153
+
154
+ Paramters
155
+ --------------------
156
+ ax : matplotlib.axes.Axes
157
+ axes to plot the raster on
158
+ geomtype : str
159
+ the geometry type to try to print
160
+ layer : None | int | str
161
+ specification of which layer to print
162
+ **kwargs
163
+ any parameter which may be passed ot matplotlib.pyplot.plot
164
+ """
165
+
166
+ if ax is not None:
167
+ plot_vector(self, ax, geomtype, layer, **kwargs)
168
+ else:
169
+ fig, ax = plt.subplots()
170
+ plot_vector(self, ax, geomtype, layer, **kwargs)
171
+ plt.show()
172
+
173
+ @classmethod
174
+ def from_geopandas(cls, obj, layer_name: str=None):
175
+ """
176
+ This function is used to convert a geopandas object into an sgspy.SpatialVector. The geopandas object
177
+ may either by of type GeoDataFrame or GeoSeries.
178
+
179
+ If a particular layer name is desired, it can be passed as a parameter.
180
+
181
+ Examples:
182
+
183
+ gdf = gpd.read_file("access.shp")
184
+ access = sgspy.SpatialVector.from_geopandas(gdf)
185
+
186
+
187
+ gs = gpd['geometry'] #geometry column is a geoseries
188
+ access = sgspy.SpatialVector.from_geopandas(gs)
189
+
190
+
191
+ gdf = gpd.read_file("access.shp")
192
+ gdf = gdf[gdf == "LineString"]
193
+ access = sgspy.SpatialVector.from_geopandas(gdf)
194
+ """
195
+ if layer_name is not None and type(layer_name) is not str:
196
+ raise TypeError("layer_name, if given, must be of type 'str'.")
197
+
198
+ if not GEOPANDAS:
199
+ raise RuntimeError("from_geopandas() can only be called if geopandas was successfully imported, but it wasn't.")
200
+
201
+ if type(obj) is not gpd.geodataframe.GeoDataFrame and type(obj) is not gpd.geoseries.GeoSeries:
202
+ raise TypeError("the object passed must be of type geopandas GeoDataFrame or GeoSeries")
203
+
204
+ #get a the geopandas object as a geoseries
205
+ if type(obj) is gpd.geodataframe.GeoDataFrame:
206
+ if 'geometry' not in obj.columns:
207
+ raise RuntimeError("'geometry' must be a column in the geodataframe passed")
208
+ gdf = obj
209
+ gs = gdf['geometry']
210
+ else:
211
+ gs = obj
212
+ gdf = gpd.GeoDataFrame(gs)
213
+
214
+ if layer_name is None: layer_name = 'geopandas_geodataframe'
215
+ projection = gs.crs.to_wkt()
216
+
217
+ # the conversion to geojson may raise a warning about how the projection is unable to be converted to the new format correctly
218
+ #
219
+ # however, we have the projection from the geodataframes geoseries crs, so it won't be an issue
220
+ with warnings.catch_warnings():
221
+ warnings.simplefilter("ignore")
222
+ geojson = gdf.to_json().encode('utf-8')
223
+
224
+ cpp_vector = GDALVectorWrapper(geojson, projection, layer_name, PROJDB_PATH)
225
+ return cls(cpp_vector)
226
+
227
+ def to_geopandas(self):
228
+ """
229
+ This function is used to convert an sgspy.SpatialVector into a geopandas geodataframe.
230
+
231
+ Examples:
232
+
233
+ access = sgspy.SpatialVector("access.shp")
234
+ gdf = access.to_geopandas()
235
+ """
236
+ if not GEOPANDAS:
237
+ raise RuntimeError("to_geopandas() can only be called if geopandas was successfully imported, but it wasn't.")
238
+
239
+ tempdir = tempfile.gettempdir()
240
+ file = os.path.join(tempdir, "temp.geojson")
241
+
242
+ #get the projection info
243
+ projection = self.cpp_vector.get_projection()
244
+
245
+ #write the dataset to a tempfile
246
+ self.cpp_vector.write(file)
247
+
248
+ # This method of writing to a file then reading from that file is definitely clunky,
249
+ # however it's easy. Theres the possiblity of iterating through every field within
250
+ # every feature, and needing to then call a different function depending on the data
251
+ # type of the field (because C++ types are rigid). That may still be done in the future,
252
+ # but for now this works.
253
+
254
+ #have geopandas read the tempfile
255
+ gdf = gpd.read_file(file)
256
+ if projection != "": gdf.set_crs(projection, inplace=True, allow_override=True)
257
+
258
+ #remove the geojson file
259
+ os.remove(file)
260
+
261
+ return gdf
262
+
Binary file
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.1
2
+ Name: sgspy
3
+ Version: 1.0.1
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=ojc5-WYs7tqo76skUh-sIT-HsgEkL0Pdbm4aS6fnfyk,86554776
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=zp6JFyURJ6U5LU9zxzfeDAVY7p_d-5jAJWDDe6wRFn0,5172
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=rUlzZyWqJ790hnRPkZaQc8fHfTVpq-GbT-VJjUCtSsU,7346
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=YX00DS0WJ-8W8se25bckCnBKdnvbCcb7_wqlIOvhrfY,7792
17
+ sgspy/sample/strat/__init__.py,sha256=WYiabUGZckk38Qhr1fFXhS8sh9BqyXtGEBPJ9lstpJo,45
18
+ sgspy/sample/strat/strat.py,sha256=GPHWTyQDWcxjd6hYtsQbCM8yK8tgCo9FkIi6Pq0j3bA,15989
19
+ sgspy/sample/systematic/__init__.py,sha256=frl-x5lN3zY7Q5HzbvwT0zz50Byh7VDoSgYDcG_vKbA,60
20
+ sgspy/sample/systematic/systematic.py,sha256=LqQWuVhsMCbQEvSOSQLkA--Hfn98PrTtmTATR8X9m4A,8154
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=f3Mu4UDSrfg8-ECAWCLITSyuwkKuMZ0PDuu9lx3eIog,8917
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=-7Pl3t1aMXeGWf5WDOOoaWEEAjYZ0vi0gNaJAs_nT8s,10470
28
+ sgspy/stratify/poly/__init__.py,sha256=CfCIvJBQIqqS8aQG-52Ja9bRxrBN1jbcUBTkbkhD9KY,42
29
+ sgspy/stratify/poly/poly.py,sha256=I8jjxePcs_Xfw-VwukuhtBqXvnrBcxwO6MVzkhHvJKs,6051
30
+ sgspy/stratify/quantiles/__init__.py,sha256=_g9MTbV7PIZxdshhEvJtZRLBCS5ehoUqZNCMBHrnOsQ,57
31
+ sgspy/stratify/quantiles/quantiles.py,sha256=SsoqZ2AqN8Te_YSCl4Mvr7OGZLoPOgsSBcEfyjQAk1E,12013
32
+ sgspy/utils/__init__.py,sha256=XXEYEVdjUa345mCs0d5Bj7lVCyHEwMoDvselH-Deebs,287
33
+ sgspy/utils/plot.py,sha256=9gnW0C8vK5AUDKBi00830V9i5ciXVXROTH7A1TLqN0c,5528
34
+ sgspy/utils/raster.py,sha256=vvmJIhiLfeMsQQHOSVSuGaZ9KN1939vb1P_7Dy5XPxY,22810
35
+ sgspy/utils/vector.py,sha256=cHaGaVniPRORmorFWqgTzEIUn2nvP1COgDJNvg3XXq0,9352
36
+ sgspy-1.0.1.data/data/sgspy/libonedal.so.3,sha256=0FmPIIAgbC8csMYFZoAznAUaSY4I6E7QpVOLRQetSvE,10841849
37
+ sgspy-1.0.1.data/data/sgspy/proj.db,sha256=sGOmBu2wzZwqDJ9V5yu9mez2dvZCrqH4izR1mp9Q0Lk,9359360
38
+ sgspy-1.0.1.dist-info/METADATA,sha256=ApiRB7L0MnAaLiAo3bdBDg2hunTrd_lrGDhIn1hMmhw,325
39
+ sgspy-1.0.1.dist-info/WHEEL,sha256=NXj1RQbUB6HkzPejON5mCWDbz1FztCTfn6HYGK8gUks,99
40
+ sgspy-1.0.1.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_39_x86_64
5
+