@@ -16601,3 +16601,167 @@ def get_overture_latest_release(patch=False) -> str:
1660116601 except KeyError as e:
1660216602 print(f"Key error: {e}")
1660316603 raise
16604+
16605+
16606+ def set_proj_lib_path(verbose=False):
16607+ """
16608+ Set the PROJ_LIB and GDAL_DATA environment variables based on the current conda environment.
16609+
16610+ This function attempts to locate and set the correct paths for PROJ_LIB and GDAL_DATA
16611+ by checking multiple possible locations within the conda environment structure.
16612+
16613+ Args:
16614+ verbose (bool): If True, print additional information during the process.
16615+
16616+ Returns:
16617+ bool: True if both paths were set successfully, False otherwise.
16618+ """
16619+ import sys
16620+
16621+ try:
16622+ from rasterio.env import set_gdal_config
16623+
16624+ # Get conda environment path
16625+ conda_env_path = os.environ.get("CONDA_PREFIX") or sys.prefix
16626+
16627+ # Define possible paths for PROJ_LIB
16628+ possible_proj_paths = [
16629+ os.path.join(conda_env_path, "share", "proj"),
16630+ os.path.join(conda_env_path, "Library", "share", "proj"),
16631+ os.path.join(conda_env_path, "Library", "share"),
16632+ ]
16633+
16634+ # Define possible paths for GDAL_DATA
16635+ possible_gdal_paths = [
16636+ os.path.join(conda_env_path, "share", "gdal"),
16637+ os.path.join(conda_env_path, "Library", "share", "gdal"),
16638+ os.path.join(conda_env_path, "Library", "data", "gdal"),
16639+ os.path.join(conda_env_path, "Library", "share"),
16640+ ]
16641+
16642+ # Set PROJ_LIB environment variable
16643+ proj_set = False
16644+ for proj_path in possible_proj_paths:
16645+ if os.path.exists(proj_path) and os.path.isdir(proj_path):
16646+ # Verify it contains projection data
16647+ if os.path.exists(os.path.join(proj_path, "proj.db")):
16648+ os.environ["PROJ_LIB"] = proj_path
16649+ if verbose:
16650+ print(f"PROJ_LIB set to: {proj_path}")
16651+ proj_set = True
16652+ break
16653+
16654+ # Set GDAL_DATA environment variable
16655+ gdal_set = False
16656+ for gdal_path in possible_gdal_paths:
16657+ if os.path.exists(gdal_path) and os.path.isdir(gdal_path):
16658+ # Verify it contains the header.dxf file or other critical GDAL files
16659+ if os.path.exists(
16660+ os.path.join(gdal_path, "header.dxf")
16661+ ) or os.path.exists(os.path.join(gdal_path, "gcs.csv")):
16662+ os.environ["GDAL_DATA"] = gdal_path
16663+ if verbose:
16664+ print(f"GDAL_DATA set to: {gdal_path}")
16665+ gdal_set = True
16666+ break
16667+
16668+ # If paths still not found, try a last-resort approach
16669+ if not proj_set or not gdal_set:
16670+ # Try a deep search in the conda environment
16671+ for root, dirs, files in os.walk(conda_env_path):
16672+ if not gdal_set and "header.dxf" in files:
16673+ os.environ["GDAL_DATA"] = root
16674+ if verbose:
16675+ print(f"GDAL_DATA set to: {root} (deep search)")
16676+ gdal_set = True
16677+
16678+ if not proj_set and "proj.db" in files:
16679+ os.environ["PROJ_LIB"] = root
16680+ if verbose:
16681+ print(f"PROJ_LIB set to: {root} (deep search)")
16682+ proj_set = True
16683+
16684+ if proj_set and gdal_set:
16685+ break
16686+
16687+ set_gdal_config("PROJ_LIB", os.environ["PROJ_LIB"])
16688+ set_gdal_config("GDAL_DATA", os.environ["GDAL_DATA"])
16689+
16690+ except Exception as e:
16691+ print(f"Error setting projection library paths: {e}")
16692+ return
16693+
16694+
16695+ def read_vector(source, layer=None, **kwargs):
16696+ """Reads vector data from various formats including GeoParquet.
16697+
16698+ This function dynamically determines the file type based on extension
16699+ and reads it into a GeoDataFrame. It supports both local files and HTTP/HTTPS URLs.
16700+
16701+ Args:
16702+ source: String path to the vector file or URL.
16703+ layer: String or integer specifying which layer to read from multi-layer
16704+ files (only applicable for formats like GPKG, GeoJSON, etc.).
16705+ Defaults to None.
16706+ **kwargs: Additional keyword arguments to pass to the underlying reader.
16707+
16708+ Returns:
16709+ geopandas.GeoDataFrame: A GeoDataFrame containing the vector data.
16710+
16711+ Raises:
16712+ ValueError: If the file format is not supported or source cannot be accessed.
16713+
16714+ Examples:
16715+ Read a local shapefile
16716+ >>> gdf = read_vector("path/to/data.shp")
16717+ >>>
16718+ Read a GeoParquet file from URL
16719+ >>> gdf = read_vector("https://example.com/data.parquet")
16720+ >>>
16721+ Read a specific layer from a GeoPackage
16722+ >>> gdf = read_vector("path/to/data.gpkg", layer="layer_name")
16723+ """
16724+
16725+ import urllib.parse
16726+
16727+ import fiona
16728+
16729+ # Determine if source is a URL or local file
16730+ parsed_url = urllib.parse.urlparse(source)
16731+ is_url = parsed_url.scheme in ["http", "https"]
16732+
16733+ # If it's a local file, check if it exists
16734+ if not is_url and not os.path.exists(source):
16735+ raise ValueError(f"File does not exist: {source}")
16736+
16737+ # Get file extension
16738+ _, ext = os.path.splitext(source)
16739+ ext = ext.lower()
16740+
16741+ # Handle GeoParquet files
16742+ if ext in [".parquet", ".pq", ".geoparquet"]:
16743+ return gpd.read_parquet(source, **kwargs)
16744+
16745+ # Handle common vector formats
16746+ if ext in [".shp", ".geojson", ".json", ".gpkg", ".gml", ".kml", ".gpx"]:
16747+ # For formats that might have multiple layers
16748+ if ext in [".gpkg", ".gml"] and layer is not None:
16749+ return gpd.read_file(source, layer=layer, **kwargs)
16750+ return gpd.read_file(source, **kwargs)
16751+
16752+ # Try to use fiona to identify valid layers for formats that might have them
16753+ # Only attempt this for local files as fiona.listlayers might not work with URLs
16754+ if layer is None and ext in [".gpkg", ".gml"] and not is_url:
16755+ try:
16756+ layers = fiona.listlayers(source)
16757+ if layers:
16758+ return gpd.read_file(source, layer=layers[0], **kwargs)
16759+ except Exception:
16760+ # If listing layers fails, we'll fall through to the generic read attempt
16761+ pass
16762+
16763+ # For other formats or when layer listing fails, attempt to read using GeoPandas
16764+ try:
16765+ return gpd.read_file(source, **kwargs)
16766+ except Exception as e:
16767+ raise ValueError(f"Could not read from source '{source}': {str(e)}")
0 commit comments