3535PARAMCODES_URL = "https://help.waterdata.usgs.gov/code/parameter_cd_nm_query?"
3636ALLPARAMCODES_URL = "https://help.waterdata.usgs.gov/code/parameter_cd_query?"
3737
38- WATERSERVICES_SERVICES = ["dv" , "iv" , "site" , "stat" ]
38+ WATERSERVICES_SERVICES = ["dv" , "iv" , "site" , "stat" , "gwlevels" ]
3939WATERDATA_SERVICES = [
40- "gwlevels" ,
4140 "measurements" ,
4241 "peaks" ,
4342 "pmcodes" ,
@@ -322,35 +321,46 @@ def get_gwlevels(
322321 """
323322 _check_sites_value_types (sites )
324323
325- # Make kwargs backwards compatible with waterservices
326- # vocabulary
327- if "startDT" in kwargs :
328- kwargs ["begin_date" ] = kwargs .pop ("startDT" )
329- if "endDT" in kwargs :
330- kwargs ["end_date" ] = kwargs .pop ("endDT" )
331- if "sites" in kwargs :
332- kwargs ["site_no" ] = kwargs .pop ("sites" )
333- if "stateCd" in kwargs :
334- kwargs ["state_cd" ] = kwargs .pop ("stateCd" )
335-
336- kwargs ["begin_date" ] = kwargs .pop ("begin_date" , start )
337- kwargs ["end_date" ] = kwargs .pop ("end_date" , end )
338- kwargs ["site_no" ] = kwargs .pop ("site_no" , sites )
324+ kwargs ["startDT" ] = kwargs .pop ("startDT" , start )
325+ kwargs ["endDT" ] = kwargs .pop ("endDT" , end )
326+ kwargs ["sites" ] = kwargs .pop ("sites" , sites )
339327 kwargs ["multi_index" ] = multi_index
340328
341- response = query_waterdata ("gwlevels" , format = "rdb" , ssl_check = ssl_check , ** kwargs )
329+ response = query_waterservices ("gwlevels" , format = "rdb" , ssl_check = ssl_check , ** kwargs )
342330
343331 df = _read_rdb (response .text )
344332
345- if datetime_index is True :
333+ if datetime_index is True and "lev_tz_cd" in df . columns :
346334 df = format_datetime (df , "lev_dt" , "lev_tm" , "lev_tz_cd" )
335+ elif datetime_index is True :
336+ # Fallback if lev_tz_cd is missing (e.g. some modern services)
337+ # Try to use 'tz_cd' if it exists, otherwise just format date/time
338+ tz_col = "lev_tz_cd" if "lev_tz_cd" in df .columns else "tz_cd"
339+ if "lev_dt" in df .columns and "lev_tm" in df .columns :
340+ if tz_col in df .columns :
341+ df = format_datetime (df , "lev_dt" , "lev_tm" , tz_col )
342+ else :
343+ # If no TZ, just combine dt and tm
344+ df ["datetime" ] = pd .to_datetime (
345+ df ["lev_dt" ] + " " + df ["lev_tm" ], format = "mixed" , utc = True
346+ )
347347
348348 # Filter by kwarg parameterCd because the service doesn't do it
349349 if "parameterCd" in kwargs :
350350 pcodes = kwargs ["parameterCd" ]
351351 if isinstance (pcodes , str ):
352352 pcodes = [pcodes ]
353- df = df [df ["parameter_cd" ].isin (pcodes )]
353+ if "parameter_cd" in df .columns :
354+ df = df [df ["parameter_cd" ].isin (pcodes )]
355+ elif len (pcodes ) == 1 :
356+ # If the column is missing (modern service) but we requested one pcode,
357+ # we can safely add it to the dataframe for backward compatibility.
358+ df ["parameter_cd" ] = pcodes [0 ]
359+ # No need to filter since we just added it as the only value.
360+ else :
361+ # Multiple pcodes requested but only one returned (or none)
362+ # Add the column but don't fill it if we can't be sure
363+ df ["parameter_cd" ] = pd .NA
354364
355365 return format_response (df , ** kwargs ), NWIS_Metadata (response , ** kwargs )
356366
@@ -1342,6 +1352,12 @@ def _read_rdb(rdb):
13421352 A formatted pandas data frame
13431353
13441354 """
1355+ if "<html>" in rdb .lower () or "<!doctype html>" in rdb .lower ():
1356+ raise ValueError (
1357+ "Received HTML response instead of RDB. This often indicates "
1358+ "that the service has been moved or is currently unavailable."
1359+ )
1360+
13451361 count = 0
13461362
13471363 for line in rdb .splitlines ():
@@ -1352,8 +1368,8 @@ def _read_rdb(rdb):
13521368 else :
13531369 break
13541370
1355- fields = re . split ( "[ \t ]" , rdb .splitlines ()[count ])
1356- fields = [field .replace ("," , "" ) for field in fields ]
1371+ fields = rdb .splitlines ()[count ]. split ( " \t " )
1372+ fields = [field .replace ("," , "" ). strip () for field in fields if field . strip () ]
13571373 dtypes = {
13581374 "site_no" : str ,
13591375 "dec_long_va" : float ,
@@ -1370,6 +1386,7 @@ def _read_rdb(rdb):
13701386 na_values = "NaN" ,
13711387 dtype = dtypes ,
13721388 )
1389+ # print(f"DEBUG: _read_rdb columns: {df.columns.tolist()}")
13731390
13741391 df = format_response (df )
13751392 return df
0 commit comments