openforis-whisp 2.0.0b2__py3-none-any.whl → 3.0.0a1__py3-none-any.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.
@@ -4,7 +4,7 @@ from shapely.geometry import shape
4
4
  from pathlib import Path
5
5
 
6
6
  # Existing imports
7
- from typing import List, Any
7
+ from typing import List, Any, Union
8
8
  from geojson import Feature, FeatureCollection, Polygon, Point
9
9
  import json
10
10
  import os
@@ -13,32 +13,32 @@ import ee
13
13
 
14
14
 
15
15
  def convert_geojson_to_ee(
16
- geojson_filepath: Any, enforce_wgs84: bool = True, strip_z_coords: bool = True
16
+ geojson_filepath: Union[str, Path, dict],
17
+ enforce_wgs84: bool = True,
18
+ strip_z_coords: bool = True,
17
19
  ) -> ee.FeatureCollection:
18
20
  """
19
- Reads a GeoJSON file from the given path and converts it to an Earth Engine FeatureCollection.
21
+ Converts GeoJSON data to an Earth Engine FeatureCollection.
22
+ Accepts either a file path or a GeoJSON dictionary object.
20
23
  Optionally checks and converts the CRS to WGS 84 (EPSG:4326) if needed.
21
24
  Automatically handles 3D coordinates by stripping Z values when necessary.
22
25
 
23
26
  Args:
24
- geojson_filepath (Any): The filepath to the GeoJSON file.
27
+ geojson_filepath (Union[str, Path, dict]): The filepath to the GeoJSON file (str or Path)
28
+ or a GeoJSON dictionary object.
25
29
  enforce_wgs84 (bool): Whether to enforce WGS 84 projection (EPSG:4326). Defaults to True.
30
+ Only applies when input is a file path (dicts are assumed to be in WGS84).
26
31
  strip_z_coords (bool): Whether to automatically strip Z coordinates from 3D geometries. Defaults to True.
27
32
 
28
33
  Returns:
29
34
  ee.FeatureCollection: Earth Engine FeatureCollection created from the GeoJSON.
30
35
  """
31
- if isinstance(geojson_filepath, (str, Path)):
36
+ if isinstance(geojson_filepath, dict):
37
+ # Input is already a GeoJSON dictionary - skip file reading
38
+ geojson_data = geojson_filepath
39
+ elif isinstance(geojson_filepath, (str, Path)):
32
40
  file_path = os.path.abspath(geojson_filepath)
33
41
 
34
- # Apply print_once deduplication for file reading message
35
- if not hasattr(convert_geojson_to_ee, "_printed_file_messages"):
36
- convert_geojson_to_ee._printed_file_messages = set()
37
-
38
- if file_path not in convert_geojson_to_ee._printed_file_messages:
39
- print(f"Reading GeoJSON file from: {file_path}")
40
- convert_geojson_to_ee._printed_file_messages.add(file_path)
41
-
42
42
  # Use GeoPandas to read the file and handle CRS
43
43
  gdf = gpd.read_file(file_path)
44
44
 
@@ -56,15 +56,17 @@ def convert_geojson_to_ee(
56
56
  # Check and convert CRS if needed
57
57
  if enforce_wgs84:
58
58
  if gdf.crs is None:
59
- print("Warning: Input GeoJSON has no CRS defined, assuming WGS 84")
59
+ # Assuming WGS 84 if no CRS defined
60
+ pass
60
61
  elif gdf.crs != "EPSG:4326":
61
- print(f"Converting CRS from {gdf.crs} to WGS 84 (EPSG:4326)")
62
62
  gdf = gdf.to_crs("EPSG:4326")
63
63
 
64
64
  # Convert to GeoJSON
65
65
  geojson_data = json.loads(gdf.to_json())
66
66
  else:
67
- raise ValueError("Input must be a file path (str or Path)")
67
+ raise ValueError(
68
+ "Input must be a file path (str or Path) or a GeoJSON dictionary object (dict)"
69
+ )
68
70
 
69
71
  validation_errors = validate_geojson(geojson_data)
70
72
  if validation_errors:
@@ -101,7 +103,7 @@ def convert_geojson_to_ee(
101
103
 
102
104
  success_message_key = f"z_coords_success_{file_path}"
103
105
  if success_message_key not in convert_geojson_to_ee._printed_z_messages:
104
- print("Successfully converted after stripping Z coordinates")
106
+ print("Successfully converted after stripping Z coordinates")
105
107
  convert_geojson_to_ee._printed_z_messages.add(success_message_key)
106
108
 
107
109
  return feature_collection
@@ -250,6 +252,58 @@ def convert_shapefile_to_ee(shapefile_path):
250
252
  return roi
251
253
 
252
254
 
255
+ # def convert_ee_to_df(
256
+ # ee_object,
257
+ # columns=None,
258
+ # remove_geom=False,
259
+ # **kwargs,
260
+ # ):
261
+ # """Converts an ee.FeatureCollection to pandas dataframe.
262
+
263
+ # Args:
264
+ # ee_object (ee.FeatureCollection): ee.FeatureCollection.
265
+ # columns (list): List of column names. Defaults to None.
266
+ # remove_geom (bool): Whether to remove the geometry column. Defaults to True.
267
+ # kwargs: Additional arguments passed to ee.data.computeFeature.
268
+
269
+ # Raises:
270
+ # TypeError: ee_object must be an ee.FeatureCollection
271
+
272
+ # Returns:
273
+ # pd.DataFrame: pandas DataFrame
274
+ # """
275
+ # if isinstance(ee_object, ee.Feature):
276
+ # ee_object = ee.FeatureCollection([ee_object])
277
+
278
+ # if not isinstance(ee_object, ee.FeatureCollection):
279
+ # raise TypeError("ee_object must be an ee.FeatureCollection")
280
+
281
+ # try:
282
+ # if remove_geom:
283
+ # data = ee_object.map(
284
+ # lambda f: ee.Feature(None, f.toDictionary(f.propertyNames().sort()))
285
+ # )
286
+ # else:
287
+ # data = ee_object
288
+
289
+ # kwargs["expression"] = data
290
+ # kwargs["fileFormat"] = "PANDAS_DATAFRAME"
291
+
292
+ # df = ee.data.computeFeatures(kwargs)
293
+
294
+ # if isinstance(columns, list):
295
+ # df = df[columns]
296
+
297
+ # if remove_geom and ("geometry" in df.columns):
298
+ # df = df.drop(columns=["geometry"], axis=1)
299
+
300
+ # # Sorting columns is not supported server-side and is removed from this function.
301
+
302
+ # return df
303
+ # except Exception as e:
304
+ # raise Exception(e)
305
+
306
+
253
307
  def convert_ee_to_df(
254
308
  ee_object,
255
309
  columns=None,
@@ -257,49 +311,37 @@ def convert_ee_to_df(
257
311
  sort_columns=False,
258
312
  **kwargs,
259
313
  ):
260
- """Converts an ee.FeatureCollection to pandas dataframe.
314
+ """
315
+ Converts an ee.FeatureCollection to pandas DataFrame, maximizing server-side operations.
261
316
 
262
317
  Args:
263
318
  ee_object (ee.FeatureCollection): ee.FeatureCollection.
264
- columns (list): List of column names. Defaults to None.
265
- remove_geom (bool): Whether to remove the geometry column. Defaults to True.
266
- sort_columns (bool): Whether to sort the column names. Defaults to False.
267
- kwargs: Additional arguments passed to ee.data.computeFeature.
268
-
269
- Raises:
270
- TypeError: ee_object must be an ee.FeatureCollection
319
+ columns (list): List of column names to select (server-side if possible).
320
+ remove_geom (bool): Remove geometry column server-side.
321
+ kwargs: Additional arguments for ee.data.computeFeatures.
271
322
 
272
323
  Returns:
273
324
  pd.DataFrame: pandas DataFrame
274
325
  """
326
+ import ee
327
+
275
328
  if isinstance(ee_object, ee.Feature):
276
329
  ee_object = ee.FeatureCollection([ee_object])
277
330
 
278
331
  if not isinstance(ee_object, ee.FeatureCollection):
279
332
  raise TypeError("ee_object must be an ee.FeatureCollection")
280
333
 
281
- try:
282
- if remove_geom:
283
- data = ee_object.map(
284
- lambda f: ee.Feature(None, f.toDictionary(f.propertyNames().sort()))
285
- )
286
- else:
287
- data = ee_object
334
+ # Server-side: select columns and remove geometry
335
+ if columns is not None:
336
+ ee_object = ee_object.select(columns)
337
+ if remove_geom:
338
+ ee_object = ee_object.map(lambda f: ee.Feature(None, f.toDictionary()))
288
339
 
289
- kwargs["expression"] = data
340
+ try:
341
+ kwargs["expression"] = ee_object
290
342
  kwargs["fileFormat"] = "PANDAS_DATAFRAME"
291
-
292
343
  df = ee.data.computeFeatures(kwargs)
293
344
 
294
- if isinstance(columns, list):
295
- df = df[columns]
296
-
297
- if remove_geom and ("geometry" in df.columns):
298
- df = df.drop(columns=["geometry"], axis=1)
299
-
300
- if sort_columns:
301
- df = df.reindex(sorted(df.columns), axis=1)
302
-
303
345
  return df
304
346
  except Exception as e:
305
347
  raise Exception(e)
@@ -443,7 +485,7 @@ def convert_csv_to_geojson(
443
485
  try:
444
486
  df = pd.read_csv(csv_filepath)
445
487
 
446
- df_to_geojson(df, geojson_filepath, geo_column)
488
+ convert_df_to_geojson(df, geojson_filepath, geo_column)
447
489
 
448
490
  except Exception as e:
449
491
  print(f"An error occurred while converting CSV to GeoJSON: {e}")