hydroanomaly 0.2.0__py3-none-any.whl → 0.3.0__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.
- hydroanomaly/__init__.py +79 -1
- hydroanomaly/plotting.py +389 -0
- hydroanomaly-0.3.0.dist-info/METADATA +400 -0
- hydroanomaly-0.3.0.dist-info/RECORD +10 -0
- hydroanomaly-0.2.0.dist-info/METADATA +0 -227
- hydroanomaly-0.2.0.dist-info/RECORD +0 -9
- {hydroanomaly-0.2.0.dist-info → hydroanomaly-0.3.0.dist-info}/WHEEL +0 -0
- {hydroanomaly-0.2.0.dist-info → hydroanomaly-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {hydroanomaly-0.2.0.dist-info → hydroanomaly-0.3.0.dist-info}/top_level.txt +0 -0
hydroanomaly/__init__.py
CHANGED
@@ -12,5 +12,83 @@ __email__ = "your.email@example.com"
|
|
12
12
|
from .hello import greet
|
13
13
|
from .math_utils import add, multiply
|
14
14
|
from .usgs_data import get_usgs_data, USGSDataRetriever
|
15
|
+
from .plotting import plot_usgs_data, plot_multiple_gages, quick_plot, WaterDataPlotter
|
15
16
|
|
16
|
-
|
17
|
+
# Convenience functions for common use cases
|
18
|
+
def get_discharge(gage_number, start_date, end_date, save_file=None):
|
19
|
+
"""
|
20
|
+
Quick function to get discharge data from any USGS gage.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
gage_number (str): USGS gage number (e.g., "08158000")
|
24
|
+
start_date (str): Start date in YYYY-MM-DD format
|
25
|
+
end_date (str): End date in YYYY-MM-DD format
|
26
|
+
save_file (str, optional): Filename to save data
|
27
|
+
|
28
|
+
Returns:
|
29
|
+
pandas.DataFrame: Discharge data
|
30
|
+
|
31
|
+
Example:
|
32
|
+
>>> import hydroanomaly
|
33
|
+
>>> data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-31")
|
34
|
+
>>> print(f"Got {len(data)} discharge measurements")
|
35
|
+
"""
|
36
|
+
return get_usgs_data(
|
37
|
+
site_number=gage_number,
|
38
|
+
parameter_code="00060", # Discharge
|
39
|
+
start_date=start_date,
|
40
|
+
end_date=end_date,
|
41
|
+
save_to_file=save_file,
|
42
|
+
parameter_name="Discharge_cfs"
|
43
|
+
)
|
44
|
+
|
45
|
+
def get_water_level(gage_number, start_date, end_date, save_file=None):
|
46
|
+
"""
|
47
|
+
Quick function to get water level data from any USGS gage.
|
48
|
+
|
49
|
+
Args:
|
50
|
+
gage_number (str): USGS gage number (e.g., "08158000")
|
51
|
+
start_date (str): Start date in YYYY-MM-DD format
|
52
|
+
end_date (str): End date in YYYY-MM-DD format
|
53
|
+
save_file (str, optional): Filename to save data
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
pandas.DataFrame: Water level data
|
57
|
+
"""
|
58
|
+
return get_usgs_data(
|
59
|
+
site_number=gage_number,
|
60
|
+
parameter_code="00065", # Gage height
|
61
|
+
start_date=start_date,
|
62
|
+
end_date=end_date,
|
63
|
+
save_to_file=save_file,
|
64
|
+
parameter_name="WaterLevel_ft"
|
65
|
+
)
|
66
|
+
|
67
|
+
def get_temperature(gage_number, start_date, end_date, save_file=None):
|
68
|
+
"""
|
69
|
+
Quick function to get water temperature data from any USGS gage.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
gage_number (str): USGS gage number (e.g., "08158000")
|
73
|
+
start_date (str): Start date in YYYY-MM-DD format
|
74
|
+
end_date (str): End date in YYYY-MM-DD format
|
75
|
+
save_file (str, optional): Filename to save data
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
pandas.DataFrame: Temperature data
|
79
|
+
"""
|
80
|
+
return get_usgs_data(
|
81
|
+
site_number=gage_number,
|
82
|
+
parameter_code="00010", # Temperature
|
83
|
+
start_date=start_date,
|
84
|
+
end_date=end_date,
|
85
|
+
save_to_file=save_file,
|
86
|
+
parameter_name="Temperature_C"
|
87
|
+
)
|
88
|
+
|
89
|
+
__all__ = [
|
90
|
+
"greet", "add", "multiply",
|
91
|
+
"get_usgs_data", "USGSDataRetriever",
|
92
|
+
"get_discharge", "get_water_level", "get_temperature",
|
93
|
+
"plot_usgs_data", "plot_multiple_gages", "quick_plot", "WaterDataPlotter"
|
94
|
+
]
|
hydroanomaly/plotting.py
ADDED
@@ -0,0 +1,389 @@
|
|
1
|
+
"""
|
2
|
+
Plotting Module for HydroAnomaly
|
3
|
+
|
4
|
+
This module provides easy-to-use plotting functions for USGS water data time series.
|
5
|
+
Creates professional-looking plots with minimal code.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import matplotlib.pyplot as plt
|
9
|
+
import matplotlib.dates as mdates
|
10
|
+
import seaborn as sns
|
11
|
+
import pandas as pd
|
12
|
+
import numpy as np
|
13
|
+
from datetime import datetime
|
14
|
+
from typing import Optional, Tuple, List, Dict, Any
|
15
|
+
import warnings
|
16
|
+
|
17
|
+
# Set style
|
18
|
+
plt.style.use('default')
|
19
|
+
sns.set_palette("husl")
|
20
|
+
|
21
|
+
|
22
|
+
class WaterDataPlotter:
|
23
|
+
"""
|
24
|
+
A class for creating professional time series plots of water data.
|
25
|
+
|
26
|
+
This class provides methods to create various types of plots including
|
27
|
+
basic time series, multi-parameter plots, and statistical visualizations.
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(self, style: str = 'seaborn-v0_8', figsize: Tuple[int, int] = (12, 6)):
|
31
|
+
"""
|
32
|
+
Initialize the plotter with default settings.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
style (str): Matplotlib style to use
|
36
|
+
figsize (tuple): Default figure size (width, height)
|
37
|
+
"""
|
38
|
+
self.default_figsize = figsize
|
39
|
+
self.colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
|
40
|
+
'#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
|
41
|
+
|
42
|
+
# Set plotting style
|
43
|
+
try:
|
44
|
+
plt.style.use(style)
|
45
|
+
except:
|
46
|
+
plt.style.use('default')
|
47
|
+
warnings.warn(f"Style '{style}' not available, using default")
|
48
|
+
|
49
|
+
def plot_timeseries(
|
50
|
+
self,
|
51
|
+
data: pd.DataFrame,
|
52
|
+
parameter_name: str = "Value",
|
53
|
+
title: Optional[str] = None,
|
54
|
+
ylabel: Optional[str] = None,
|
55
|
+
color: str = '#1f77b4',
|
56
|
+
save_path: Optional[str] = None,
|
57
|
+
show_stats: bool = True,
|
58
|
+
figsize: Optional[Tuple[int, int]] = None
|
59
|
+
) -> plt.Figure:
|
60
|
+
"""
|
61
|
+
Create a basic time series plot.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
data (pd.DataFrame): Data with 'datetime' and 'value' columns
|
65
|
+
parameter_name (str): Name of the parameter being plotted
|
66
|
+
title (str, optional): Plot title
|
67
|
+
ylabel (str, optional): Y-axis label
|
68
|
+
color (str): Line color
|
69
|
+
save_path (str, optional): Path to save the plot
|
70
|
+
show_stats (bool): Whether to show statistics on the plot
|
71
|
+
figsize (tuple, optional): Figure size
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
matplotlib.figure.Figure: The created figure
|
75
|
+
"""
|
76
|
+
if len(data) == 0:
|
77
|
+
raise ValueError("No data to plot")
|
78
|
+
|
79
|
+
figsize = figsize or self.default_figsize
|
80
|
+
fig, ax = plt.subplots(figsize=figsize)
|
81
|
+
|
82
|
+
# Plot the data
|
83
|
+
ax.plot(data['datetime'], data['value'], color=color, linewidth=1.5, alpha=0.8)
|
84
|
+
|
85
|
+
# Customize the plot
|
86
|
+
if title is None:
|
87
|
+
title = f"{parameter_name} Time Series"
|
88
|
+
ax.set_title(title, fontsize=14, fontweight='bold', pad=20)
|
89
|
+
|
90
|
+
if ylabel is None:
|
91
|
+
ylabel = parameter_name
|
92
|
+
ax.set_ylabel(ylabel, fontsize=12)
|
93
|
+
ax.set_xlabel('Date', fontsize=12)
|
94
|
+
|
95
|
+
# Format dates on x-axis
|
96
|
+
self._format_date_axis(ax, data['datetime'])
|
97
|
+
|
98
|
+
# Add grid
|
99
|
+
ax.grid(True, alpha=0.3, linestyle='--')
|
100
|
+
|
101
|
+
# Add statistics if requested
|
102
|
+
if show_stats:
|
103
|
+
self._add_statistics_text(ax, data['value'], parameter_name)
|
104
|
+
|
105
|
+
# Improve layout
|
106
|
+
plt.tight_layout()
|
107
|
+
|
108
|
+
# Save if requested
|
109
|
+
if save_path:
|
110
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
111
|
+
print(f"📊 Plot saved to: {save_path}")
|
112
|
+
|
113
|
+
return fig
|
114
|
+
|
115
|
+
def plot_multiple_parameters(
|
116
|
+
self,
|
117
|
+
data_dict: Dict[str, pd.DataFrame],
|
118
|
+
title: str = "Multiple Parameters Time Series",
|
119
|
+
save_path: Optional[str] = None,
|
120
|
+
figsize: Optional[Tuple[int, int]] = None
|
121
|
+
) -> plt.Figure:
|
122
|
+
"""
|
123
|
+
Plot multiple parameters on separate subplots.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
data_dict (dict): Dictionary with parameter names as keys and DataFrames as values
|
127
|
+
title (str): Main plot title
|
128
|
+
save_path (str, optional): Path to save the plot
|
129
|
+
figsize (tuple, optional): Figure size
|
130
|
+
|
131
|
+
Returns:
|
132
|
+
matplotlib.figure.Figure: The created figure
|
133
|
+
"""
|
134
|
+
n_params = len(data_dict)
|
135
|
+
if n_params == 0:
|
136
|
+
raise ValueError("No data provided")
|
137
|
+
|
138
|
+
figsize = figsize or (12, 4 * n_params)
|
139
|
+
fig, axes = plt.subplots(n_params, 1, figsize=figsize, sharex=True)
|
140
|
+
|
141
|
+
if n_params == 1:
|
142
|
+
axes = [axes]
|
143
|
+
|
144
|
+
colors = self.colors[:n_params]
|
145
|
+
|
146
|
+
for i, (param_name, data) in enumerate(data_dict.items()):
|
147
|
+
if len(data) == 0:
|
148
|
+
continue
|
149
|
+
|
150
|
+
ax = axes[i]
|
151
|
+
ax.plot(data['datetime'], data['value'],
|
152
|
+
color=colors[i], linewidth=1.5, alpha=0.8, label=param_name)
|
153
|
+
|
154
|
+
ax.set_ylabel(param_name, fontsize=11)
|
155
|
+
ax.grid(True, alpha=0.3, linestyle='--')
|
156
|
+
ax.legend(loc='upper right')
|
157
|
+
|
158
|
+
# Add basic stats
|
159
|
+
mean_val = data['value'].mean()
|
160
|
+
ax.axhline(y=mean_val, color=colors[i], linestyle=':', alpha=0.6,
|
161
|
+
label=f'Mean: {mean_val:.2f}')
|
162
|
+
|
163
|
+
# Format the bottom subplot x-axis
|
164
|
+
if data_dict:
|
165
|
+
sample_data = next(iter(data_dict.values()))
|
166
|
+
self._format_date_axis(axes[-1], sample_data['datetime'])
|
167
|
+
|
168
|
+
axes[-1].set_xlabel('Date', fontsize=12)
|
169
|
+
fig.suptitle(title, fontsize=14, fontweight='bold')
|
170
|
+
|
171
|
+
plt.tight_layout()
|
172
|
+
|
173
|
+
if save_path:
|
174
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
175
|
+
print(f"📊 Plot saved to: {save_path}")
|
176
|
+
|
177
|
+
return fig
|
178
|
+
|
179
|
+
def plot_comparison(
|
180
|
+
self,
|
181
|
+
data_list: List[Tuple[pd.DataFrame, str]],
|
182
|
+
title: str = "Data Comparison",
|
183
|
+
ylabel: str = "Value",
|
184
|
+
save_path: Optional[str] = None,
|
185
|
+
figsize: Optional[Tuple[int, int]] = None
|
186
|
+
) -> plt.Figure:
|
187
|
+
"""
|
188
|
+
Plot multiple datasets on the same axes for comparison.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
data_list (list): List of tuples (DataFrame, label)
|
192
|
+
title (str): Plot title
|
193
|
+
ylabel (str): Y-axis label
|
194
|
+
save_path (str, optional): Path to save the plot
|
195
|
+
figsize (tuple, optional): Figure size
|
196
|
+
|
197
|
+
Returns:
|
198
|
+
matplotlib.figure.Figure: The created figure
|
199
|
+
"""
|
200
|
+
if not data_list:
|
201
|
+
raise ValueError("No data provided")
|
202
|
+
|
203
|
+
figsize = figsize or self.default_figsize
|
204
|
+
fig, ax = plt.subplots(figsize=figsize)
|
205
|
+
|
206
|
+
colors = self.colors[:len(data_list)]
|
207
|
+
|
208
|
+
for i, (data, label) in enumerate(data_list):
|
209
|
+
if len(data) == 0:
|
210
|
+
continue
|
211
|
+
|
212
|
+
ax.plot(data['datetime'], data['value'],
|
213
|
+
color=colors[i], linewidth=1.5, alpha=0.8, label=label)
|
214
|
+
|
215
|
+
ax.set_title(title, fontsize=14, fontweight='bold', pad=20)
|
216
|
+
ax.set_ylabel(ylabel, fontsize=12)
|
217
|
+
ax.set_xlabel('Date', fontsize=12)
|
218
|
+
ax.grid(True, alpha=0.3, linestyle='--')
|
219
|
+
ax.legend()
|
220
|
+
|
221
|
+
# Format dates
|
222
|
+
if data_list and len(data_list[0][0]) > 0:
|
223
|
+
self._format_date_axis(ax, data_list[0][0]['datetime'])
|
224
|
+
|
225
|
+
plt.tight_layout()
|
226
|
+
|
227
|
+
if save_path:
|
228
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
229
|
+
print(f"📊 Plot saved to: {save_path}")
|
230
|
+
|
231
|
+
return fig
|
232
|
+
|
233
|
+
def plot_statistics(
|
234
|
+
self,
|
235
|
+
data: pd.DataFrame,
|
236
|
+
parameter_name: str = "Parameter",
|
237
|
+
save_path: Optional[str] = None
|
238
|
+
) -> plt.Figure:
|
239
|
+
"""
|
240
|
+
Create statistical plots (histogram and box plot).
|
241
|
+
|
242
|
+
Args:
|
243
|
+
data (pd.DataFrame): Data with 'datetime' and 'value' columns
|
244
|
+
parameter_name (str): Name of the parameter
|
245
|
+
save_path (str, optional): Path to save the plot
|
246
|
+
|
247
|
+
Returns:
|
248
|
+
matplotlib.figure.Figure: The created figure
|
249
|
+
"""
|
250
|
+
if len(data) == 0:
|
251
|
+
raise ValueError("No data to plot")
|
252
|
+
|
253
|
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
|
254
|
+
|
255
|
+
# Histogram
|
256
|
+
ax1.hist(data['value'], bins=30, alpha=0.7, color=self.colors[0], edgecolor='black')
|
257
|
+
ax1.set_title(f'{parameter_name} Distribution', fontweight='bold')
|
258
|
+
ax1.set_xlabel(parameter_name)
|
259
|
+
ax1.set_ylabel('Frequency')
|
260
|
+
ax1.grid(True, alpha=0.3)
|
261
|
+
|
262
|
+
# Add statistics to histogram
|
263
|
+
mean_val = data['value'].mean()
|
264
|
+
median_val = data['value'].median()
|
265
|
+
ax1.axvline(mean_val, color='red', linestyle='--', alpha=0.8, label=f'Mean: {mean_val:.2f}')
|
266
|
+
ax1.axvline(median_val, color='orange', linestyle='--', alpha=0.8, label=f'Median: {median_val:.2f}')
|
267
|
+
ax1.legend()
|
268
|
+
|
269
|
+
# Box plot
|
270
|
+
box_data = ax2.boxplot(data['value'], patch_artist=True)
|
271
|
+
box_data['boxes'][0].set_facecolor(self.colors[1])
|
272
|
+
box_data['boxes'][0].set_alpha(0.7)
|
273
|
+
|
274
|
+
ax2.set_title(f'{parameter_name} Box Plot', fontweight='bold')
|
275
|
+
ax2.set_ylabel(parameter_name)
|
276
|
+
ax2.grid(True, alpha=0.3)
|
277
|
+
|
278
|
+
plt.tight_layout()
|
279
|
+
|
280
|
+
if save_path:
|
281
|
+
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
282
|
+
print(f"📊 Plot saved to: {save_path}")
|
283
|
+
|
284
|
+
return fig
|
285
|
+
|
286
|
+
def _format_date_axis(self, ax, dates):
|
287
|
+
"""Format the date axis based on the date range."""
|
288
|
+
date_range = (dates.max() - dates.min()).days
|
289
|
+
|
290
|
+
if date_range <= 7: # Less than a week
|
291
|
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d %H:%M'))
|
292
|
+
ax.xaxis.set_major_locator(mdates.HourLocator(interval=6))
|
293
|
+
elif date_range <= 31: # Less than a month
|
294
|
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
|
295
|
+
ax.xaxis.set_major_locator(mdates.DayLocator(interval=2))
|
296
|
+
elif date_range <= 365: # Less than a year
|
297
|
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
|
298
|
+
ax.xaxis.set_major_locator(mdates.MonthLocator())
|
299
|
+
else: # More than a year
|
300
|
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
|
301
|
+
ax.xaxis.set_major_locator(mdates.YearLocator())
|
302
|
+
|
303
|
+
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha='right')
|
304
|
+
|
305
|
+
def _add_statistics_text(self, ax, values, parameter_name):
|
306
|
+
"""Add statistics text box to the plot."""
|
307
|
+
stats_text = (
|
308
|
+
f"Statistics:\n"
|
309
|
+
f"Mean: {values.mean():.2f}\n"
|
310
|
+
f"Median: {values.median():.2f}\n"
|
311
|
+
f"Min: {values.min():.2f}\n"
|
312
|
+
f"Max: {values.max():.2f}\n"
|
313
|
+
f"Std: {values.std():.2f}"
|
314
|
+
)
|
315
|
+
|
316
|
+
# Position the text box
|
317
|
+
ax.text(0.02, 0.98, stats_text, transform=ax.transAxes, fontsize=9,
|
318
|
+
verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
|
319
|
+
|
320
|
+
|
321
|
+
# Convenience functions for easy plotting
|
322
|
+
def plot_usgs_data(
|
323
|
+
data: pd.DataFrame,
|
324
|
+
parameter_name: str = "Value",
|
325
|
+
title: Optional[str] = None,
|
326
|
+
save_path: Optional[str] = None,
|
327
|
+
show_stats: bool = True
|
328
|
+
) -> plt.Figure:
|
329
|
+
"""
|
330
|
+
Quick function to plot USGS time series data.
|
331
|
+
|
332
|
+
Args:
|
333
|
+
data (pd.DataFrame): Data with 'datetime' and 'value' columns
|
334
|
+
parameter_name (str): Name of the parameter being plotted
|
335
|
+
title (str, optional): Plot title
|
336
|
+
save_path (str, optional): Path to save the plot
|
337
|
+
show_stats (bool): Whether to show statistics on the plot
|
338
|
+
|
339
|
+
Returns:
|
340
|
+
matplotlib.figure.Figure: The created figure
|
341
|
+
|
342
|
+
Example:
|
343
|
+
>>> import hydroanomaly
|
344
|
+
>>> data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-31")
|
345
|
+
>>> hydroanomaly.plot_usgs_data(data, "Discharge (cfs)", "Colorado River Discharge")
|
346
|
+
"""
|
347
|
+
plotter = WaterDataPlotter()
|
348
|
+
return plotter.plot_timeseries(
|
349
|
+
data=data,
|
350
|
+
parameter_name=parameter_name,
|
351
|
+
title=title,
|
352
|
+
save_path=save_path,
|
353
|
+
show_stats=show_stats
|
354
|
+
)
|
355
|
+
|
356
|
+
|
357
|
+
def plot_multiple_gages(
|
358
|
+
data_dict: Dict[str, pd.DataFrame],
|
359
|
+
title: str = "Multiple Gage Comparison",
|
360
|
+
parameter_name: str = "Value",
|
361
|
+
save_path: Optional[str] = None
|
362
|
+
) -> plt.Figure:
|
363
|
+
"""
|
364
|
+
Plot data from multiple gages for comparison.
|
365
|
+
|
366
|
+
Args:
|
367
|
+
data_dict (dict): Dictionary with gage IDs as keys and DataFrames as values
|
368
|
+
title (str): Plot title
|
369
|
+
parameter_name (str): Y-axis label
|
370
|
+
save_path (str, optional): Path to save the plot
|
371
|
+
|
372
|
+
Returns:
|
373
|
+
matplotlib.figure.Figure: The created figure
|
374
|
+
"""
|
375
|
+
plotter = WaterDataPlotter()
|
376
|
+
data_list = [(data, f"Gage {gage_id}") for gage_id, data in data_dict.items()]
|
377
|
+
return plotter.plot_comparison(data_list, title, parameter_name, save_path)
|
378
|
+
|
379
|
+
|
380
|
+
def quick_plot(data: pd.DataFrame, title: str = "USGS Data") -> None:
|
381
|
+
"""
|
382
|
+
Create a quick plot and show it immediately.
|
383
|
+
|
384
|
+
Args:
|
385
|
+
data (pd.DataFrame): Data to plot
|
386
|
+
title (str): Plot title
|
387
|
+
"""
|
388
|
+
plot_usgs_data(data, title=title)
|
389
|
+
plt.show()
|
@@ -0,0 +1,400 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: hydroanomaly
|
3
|
+
Version: 0.3.0
|
4
|
+
Summary: A Python package for hydro anomaly detection
|
5
|
+
Home-page: https://github.com/yourusername/hydroanomaly
|
6
|
+
Author: Your Name
|
7
|
+
Author-email: Your Name <your.email@example.com>
|
8
|
+
License-Expression: MIT
|
9
|
+
Project-URL: Homepage, https://github.com/yourusername/hydroanomaly
|
10
|
+
Project-URL: Bug Reports, https://github.com/yourusername/hydroanomaly/issues
|
11
|
+
Project-URL: Source, https://github.com/yourusername/hydroanomaly
|
12
|
+
Keywords: python,package,hydro,anomaly,detection
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
14
|
+
Classifier: Operating System :: OS Independent
|
15
|
+
Requires-Python: >=3.6
|
16
|
+
Description-Content-Type: text/markdown
|
17
|
+
License-File: LICENSE
|
18
|
+
Requires-Dist: pandas>=1.3.0
|
19
|
+
Requires-Dist: numpy>=1.20.0
|
20
|
+
Requires-Dist: requests>=2.25.1
|
21
|
+
Requires-Dist: matplotlib>=3.3.0
|
22
|
+
Requires-Dist: seaborn>=0.11.0
|
23
|
+
Provides-Extra: dev
|
24
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
25
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
26
|
+
Requires-Dist: flake8>=3.8; extra == "dev"
|
27
|
+
Requires-Dist: mypy>=0.800; extra == "dev"
|
28
|
+
Dynamic: author
|
29
|
+
Dynamic: home-page
|
30
|
+
Dynamic: license-file
|
31
|
+
Dynamic: requires-python
|
32
|
+
|
33
|
+
# HydroAnomaly
|
34
|
+
|
35
|
+
A Python package for hydro anomaly detection, **USGS water data retrieval**, and **time series visualization**.
|
36
|
+
|
37
|
+
[](https://badge.fury.io/py/hydroanomaly)
|
38
|
+
[](https://pepy.tech/project/hydroanomaly)
|
39
|
+
|
40
|
+
## Features
|
41
|
+
|
42
|
+
- 🌊 **USGS Data Retrieval**: Get real-time and historical water data from USGS Water Services
|
43
|
+
- 📊 **Time Series Plotting**: Beautiful, professional visualizations for your water data
|
44
|
+
- 📈 **Multi-Parameter Analysis**: Compare multiple parameters or gages in one plot
|
45
|
+
- 📋 **Statistical Analysis**: Built-in statistics and distribution plots
|
46
|
+
- 🎯 **Easy to Use**: Simple functions for quick data exploration
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
```bash
|
51
|
+
pip install hydroanomaly
|
52
|
+
```
|
53
|
+
|
54
|
+
## � USGS Data Retrieval
|
55
|
+
|
56
|
+
Easily retrieve real-time and historical water data from USGS Water Services:
|
57
|
+
|
58
|
+
```python
|
59
|
+
import hydroanomaly
|
60
|
+
|
61
|
+
# ------------------------
|
62
|
+
# User-defined settings
|
63
|
+
# ------------------------
|
64
|
+
site_number = "294643095035200" # USGS site number
|
65
|
+
parameter_code = "63680" # Turbidity
|
66
|
+
start_date = "2020-01-01"
|
67
|
+
end_date = "2024-12-30"
|
68
|
+
|
69
|
+
# ------------------------
|
70
|
+
# Data Extraction from USGS
|
71
|
+
# ------------------------
|
72
|
+
data = hydroanomaly.get_usgs_data(
|
73
|
+
site_number=site_number,
|
74
|
+
parameter_code=parameter_code,
|
75
|
+
start_date=start_date,
|
76
|
+
end_date=end_date,
|
77
|
+
save_to_file="USGS_turbidity.csv",
|
78
|
+
parameter_name="Turbidity"
|
79
|
+
)
|
80
|
+
|
81
|
+
print(f"Retrieved {len(data)} data points!")
|
82
|
+
print(data.head())
|
83
|
+
```
|
84
|
+
|
85
|
+
## 📊 Time Series Plotting
|
86
|
+
|
87
|
+
Create beautiful visualizations of your water data:
|
88
|
+
|
89
|
+
```python
|
90
|
+
import hydroanomaly
|
91
|
+
|
92
|
+
# Get some data
|
93
|
+
data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-31")
|
94
|
+
|
95
|
+
# Quick plot (simplest method)
|
96
|
+
hydroanomaly.quick_plot(data, "Colorado River Discharge")
|
97
|
+
|
98
|
+
# Professional plot with statistics
|
99
|
+
fig = hydroanomaly.plot_usgs_data(
|
100
|
+
data=data,
|
101
|
+
parameter_name="Discharge (cfs)",
|
102
|
+
title="Colorado River at Austin - January 2023",
|
103
|
+
save_path="discharge_plot.png"
|
104
|
+
)
|
105
|
+
|
106
|
+
# Compare multiple gages
|
107
|
+
austin_data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-07")
|
108
|
+
nola_data = hydroanomaly.get_discharge("07374000", "2023-01-01", "2023-01-07")
|
109
|
+
|
110
|
+
gage_data = {
|
111
|
+
"Colorado River (Austin)": austin_data,
|
112
|
+
"Mississippi River (New Orleans)": nola_data
|
113
|
+
}
|
114
|
+
|
115
|
+
fig = hydroanomaly.plot_multiple_gages(
|
116
|
+
data_dict=gage_data,
|
117
|
+
parameter_name="Discharge (cfs)",
|
118
|
+
title="River Discharge Comparison"
|
119
|
+
)
|
120
|
+
```
|
121
|
+
|
122
|
+
## Quick Start
|
123
|
+
|
124
|
+
```python
|
125
|
+
import hydroanomaly
|
126
|
+
|
127
|
+
# Get USGS data
|
128
|
+
data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-31")
|
129
|
+
print(f"Retrieved {len(data)} discharge measurements")
|
130
|
+
|
131
|
+
# Plot the data
|
132
|
+
hydroanomaly.quick_plot(data, "Colorado River Discharge")
|
133
|
+
|
134
|
+
# Basic greeting functionality
|
135
|
+
print(hydroanomaly.greet("Water Engineer"))
|
136
|
+
# Output: Hello, Water Engineer!
|
137
|
+
|
138
|
+
# Math utilities for data analysis
|
139
|
+
result = hydroanomaly.add(25.5, 14.3)
|
140
|
+
print(f"Sum: {result}")
|
141
|
+
# Output: Sum: 39.8
|
142
|
+
```
|
143
|
+
|
144
|
+
## Features
|
145
|
+
|
146
|
+
- **🌊 USGS Data Retrieval**: Download real-time water data from USGS Water Services
|
147
|
+
- Support for any USGS site and parameter
|
148
|
+
- Automatic data cleaning and validation
|
149
|
+
- Convenient functions for common parameters (discharge, water level, temperature)
|
150
|
+
- Fallback synthetic data generation
|
151
|
+
- CSV export functionality
|
152
|
+
|
153
|
+
- **📊 Time Series Plotting**: Beautiful, professional visualizations
|
154
|
+
- Single parameter plots with statistics
|
155
|
+
- Multi-parameter comparison plots
|
156
|
+
- Multiple gage comparison plots
|
157
|
+
- Statistical analysis plots (histogram, box plot, etc.)
|
158
|
+
- Automatic legend and formatting
|
159
|
+
- Save plots in multiple formats (PNG, PDF, SVG)
|
160
|
+
|
161
|
+
- **📈 Data Analysis Tools**: Built-in utilities for water data
|
162
|
+
- Mathematical operations for data processing
|
163
|
+
- Statistical summaries and analysis
|
164
|
+
- Data validation and quality checks
|
165
|
+
|
166
|
+
- **🎯 Easy to Use**: Simple, intuitive API
|
167
|
+
- Quick plotting for rapid data exploration
|
168
|
+
- One-line data retrieval functions
|
169
|
+
- Comprehensive error handling
|
170
|
+
- Well-documented with examples
|
171
|
+
|
172
|
+
- **🧪 Well Tested**: Comprehensive test suite with 100% pass rate
|
173
|
+
|
174
|
+
## USGS Data Parameters
|
175
|
+
|
176
|
+
Common USGS parameter codes you can use:
|
177
|
+
- **00060**: Discharge (cubic feet per second)
|
178
|
+
- **00065**: Gage height (feet)
|
179
|
+
- **00010**: Water temperature (°C)
|
180
|
+
- **63680**: Turbidity (NTU)
|
181
|
+
- **00300**: Dissolved oxygen (mg/L)
|
182
|
+
- **00095**: Specific conductance (µS/cm)
|
183
|
+
|
184
|
+
Find USGS site numbers at: https://waterdata.usgs.gov/nwis
|
185
|
+
|
186
|
+
## Detailed Usage
|
187
|
+
|
188
|
+
### USGS Data Retrieval
|
189
|
+
```python
|
190
|
+
from hydroanomaly.usgs_data import USGSDataRetriever
|
191
|
+
|
192
|
+
# Create retriever instance
|
193
|
+
retriever = USGSDataRetriever()
|
194
|
+
|
195
|
+
# Get data with full control
|
196
|
+
data = retriever.retrieve_data(
|
197
|
+
site_number="08158000", # Colorado River at Austin, TX
|
198
|
+
parameter_code="00060", # Discharge
|
199
|
+
start_date="2023-01-01",
|
200
|
+
end_date="2023-01-31"
|
201
|
+
)
|
202
|
+
|
203
|
+
# Get summary statistics
|
204
|
+
summary = retriever.get_data_summary(data)
|
205
|
+
print(f"Retrieved {summary['record_count']} records")
|
206
|
+
print(f"Average discharge: {summary['value_stats']['mean']:.2f} cfs")
|
207
|
+
|
208
|
+
# Save data
|
209
|
+
retriever.save_data(data, "discharge_data.csv", "Discharge_cfs")
|
210
|
+
```
|
211
|
+
|
212
|
+
### Greeting Functions
|
213
|
+
```python
|
214
|
+
from hydroanomaly.hello import greet, say_goodbye
|
215
|
+
|
216
|
+
# Greet users
|
217
|
+
welcome_msg = greet("Data Scientist")
|
218
|
+
print(welcome_msg) # Hello, Data Scientist!
|
219
|
+
|
220
|
+
# Say goodbye
|
221
|
+
farewell_msg = say_goodbye("User")
|
222
|
+
print(farewell_msg) # Goodbye, User!
|
223
|
+
```
|
224
|
+
|
225
|
+
### Mathematical Operations
|
226
|
+
```python
|
227
|
+
from hydroanomaly.math_utils import add, multiply, divide
|
228
|
+
|
229
|
+
# Basic operations
|
230
|
+
sum_result = add(10.5, 20.3)
|
231
|
+
product = multiply(5, 7)
|
232
|
+
|
233
|
+
# Safe division with error handling
|
234
|
+
try:
|
235
|
+
result = divide(100, 5)
|
236
|
+
print(f"Result: {result}") # Result: 20.0
|
237
|
+
except ValueError as e:
|
238
|
+
print(f"Error: {e}")
|
239
|
+
```
|
240
|
+
|
241
|
+
### Time Series Plotting
|
242
|
+
|
243
|
+
```python
|
244
|
+
# Quick plotting for data exploration
|
245
|
+
data = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-07")
|
246
|
+
hydroanomaly.quick_plot(data, "Quick Discharge Check")
|
247
|
+
|
248
|
+
# Professional plots with full customization
|
249
|
+
from hydroanomaly.plotting import WaterDataPlotter
|
250
|
+
|
251
|
+
plotter = WaterDataPlotter()
|
252
|
+
|
253
|
+
# Single parameter with statistics
|
254
|
+
fig = plotter.plot_timeseries(
|
255
|
+
data=data,
|
256
|
+
parameter_name="Discharge (cfs)",
|
257
|
+
title="Colorado River Discharge",
|
258
|
+
color="blue",
|
259
|
+
save_path="discharge_analysis.png"
|
260
|
+
)
|
261
|
+
|
262
|
+
# Multiple parameters from same gage
|
263
|
+
discharge = hydroanomaly.get_discharge("08158000", "2023-01-01", "2023-01-07")
|
264
|
+
level = hydroanomaly.get_water_level("08158000", "2023-01-01", "2023-01-07")
|
265
|
+
|
266
|
+
data_dict = {
|
267
|
+
"Discharge (cfs)": discharge,
|
268
|
+
"Water Level (ft)": level
|
269
|
+
}
|
270
|
+
|
271
|
+
fig = plotter.plot_multiple_parameters(
|
272
|
+
data_dict=data_dict,
|
273
|
+
title="Colorado River - Multiple Parameters"
|
274
|
+
)
|
275
|
+
|
276
|
+
# Statistical analysis plots
|
277
|
+
fig = plotter.plot_statistics(
|
278
|
+
data=data,
|
279
|
+
parameter_name="Discharge (cfs)",
|
280
|
+
title="Discharge Statistics"
|
281
|
+
)
|
282
|
+
```
|
283
|
+
|
284
|
+
## 📚 Documentation & Examples
|
285
|
+
|
286
|
+
- **📖 [Plotting Guide](PLOTTING_GUIDE.md)**: Comprehensive plotting documentation with examples
|
287
|
+
- **🎯 [Examples](plotting_examples.py)**: Run `python plotting_examples.py` to see all features
|
288
|
+
- **🧪 [Tests](test_plotting.py)**: Verify functionality with `python test_plotting.py`
|
289
|
+
|
290
|
+
## Use Cases
|
291
|
+
|
292
|
+
- **🌊 Real Water Data Analysis**: Retrieve and analyze actual USGS water monitoring data
|
293
|
+
- **📊 Hydro Research**: Access historical water quality and quantity data with visualization
|
294
|
+
- **🚰 Water Management**: Monitor discharge, water levels, and quality parameters with plots
|
295
|
+
- **🎓 Educational Projects**: Learn data analysis and visualization with real environmental data
|
296
|
+
- **🔬 Environmental Studies**: Research water patterns and anomalies with statistical plots
|
297
|
+
- **⚡ Quick Prototyping**: Rapidly access and visualize water data for proof-of-concepts
|
298
|
+
- **📈 Data Reporting**: Generate professional plots for reports and presentations
|
299
|
+
|
300
|
+
## API Reference
|
301
|
+
|
302
|
+
### hydroanomaly.greet(name="World")
|
303
|
+
Returns a greeting message.
|
304
|
+
|
305
|
+
**Parameters:**
|
306
|
+
- `name` (str, optional): Name to greet. Defaults to "World".
|
307
|
+
|
308
|
+
**Returns:**
|
309
|
+
- str: Greeting message
|
310
|
+
|
311
|
+
### hydroanomaly.get_discharge(gage_number, start_date, end_date)
|
312
|
+
Get discharge data from USGS.
|
313
|
+
|
314
|
+
**Parameters:**
|
315
|
+
- `gage_number` (str): USGS gage number
|
316
|
+
- `start_date` (str): Start date (YYYY-MM-DD)
|
317
|
+
- `end_date` (str): End date (YYYY-MM-DD)
|
318
|
+
|
319
|
+
**Returns:**
|
320
|
+
- pandas.DataFrame: Time series data with datetime and value columns
|
321
|
+
|
322
|
+
### hydroanomaly.get_water_level(gage_number, start_date, end_date)
|
323
|
+
Get water level data from USGS.
|
324
|
+
|
325
|
+
**Parameters:**
|
326
|
+
- `gage_number` (str): USGS gage number
|
327
|
+
- `start_date` (str): Start date (YYYY-MM-DD)
|
328
|
+
- `end_date` (str): End date (YYYY-MM-DD)
|
329
|
+
|
330
|
+
**Returns:**
|
331
|
+
- pandas.DataFrame: Time series data with datetime and value columns
|
332
|
+
|
333
|
+
### hydroanomaly.plot_usgs_data(data, parameter_name, title, save_path, color)
|
334
|
+
Create a professional plot of USGS time series data.
|
335
|
+
|
336
|
+
**Parameters:**
|
337
|
+
- `data` (DataFrame): USGS data with datetime and value columns
|
338
|
+
- `parameter_name` (str, optional): Name of parameter for y-axis label
|
339
|
+
- `title` (str, optional): Plot title
|
340
|
+
- `save_path` (str, optional): Path to save the plot
|
341
|
+
- `color` (str, optional): Line color
|
342
|
+
|
343
|
+
**Returns:**
|
344
|
+
- matplotlib.figure.Figure: The plot figure
|
345
|
+
|
346
|
+
### hydroanomaly.quick_plot(data, title)
|
347
|
+
Create a quick plot for data exploration.
|
348
|
+
|
349
|
+
**Parameters:**
|
350
|
+
- `data` (DataFrame): USGS data with datetime and value columns
|
351
|
+
- `title` (str, optional): Plot title
|
352
|
+
|
353
|
+
**Returns:**
|
354
|
+
- matplotlib.figure.Figure: The plot figure
|
355
|
+
|
356
|
+
### hydroanomaly.plot_multiple_gages(data_dict, parameter_name, title, save_path)
|
357
|
+
Compare the same parameter across multiple gages.
|
358
|
+
|
359
|
+
**Parameters:**
|
360
|
+
- `data_dict` (dict): Dictionary with gage names as keys and data as values
|
361
|
+
- `parameter_name` (str, optional): Name of parameter for y-axis label
|
362
|
+
- `title` (str, optional): Plot title
|
363
|
+
- `save_path` (str, optional): Path to save the plot
|
364
|
+
|
365
|
+
**Returns:**
|
366
|
+
- matplotlib.figure.Figure: The plot figure
|
367
|
+
|
368
|
+
### Mathematical Operations
|
369
|
+
|
370
|
+
### hydroanomaly.add(a, b)
|
371
|
+
Adds two numbers.
|
372
|
+
|
373
|
+
**Parameters:**
|
374
|
+
- `a` (int/float): First number
|
375
|
+
- `b` (int/float): Second number
|
376
|
+
|
377
|
+
**Returns:**
|
378
|
+
- int/float: Sum of a and b
|
379
|
+
|
380
|
+
### hydroanomaly.multiply(a, b)
|
381
|
+
Multiplies two numbers.
|
382
|
+
|
383
|
+
**Parameters:**
|
384
|
+
- `a` (int/float): First number
|
385
|
+
- `b` (int/float): Second number
|
386
|
+
|
387
|
+
**Returns:**
|
388
|
+
- int/float: Product of a and b
|
389
|
+
|
390
|
+
## Contributing
|
391
|
+
|
392
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
393
|
+
|
394
|
+
## License
|
395
|
+
|
396
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
397
|
+
|
398
|
+
---
|
399
|
+
|
400
|
+
**HydroAnomaly** - Making water data analysis simple and beautiful! 🌊📊
|
@@ -0,0 +1,10 @@
|
|
1
|
+
hydroanomaly/__init__.py,sha256=orCkJ2g57zR9o5RUekkh0eOUvhalQVbRro5Oxm-iYZk,2997
|
2
|
+
hydroanomaly/hello.py,sha256=AhK7UKF_3TyZcWL4IDlZq_BXdKQzUP-is-jv59fgqk4,566
|
3
|
+
hydroanomaly/math_utils.py,sha256=CDOGWAiRlb2PK5SNFysumnzp7_LbZ9aleHLR_3lsGrs,856
|
4
|
+
hydroanomaly/plotting.py,sha256=YZW6-Sb_IrhbHKFeoh1d86Ef4Ev5Gpq55lEv8XX0v20,13504
|
5
|
+
hydroanomaly/usgs_data.py,sha256=zUvfu3go-7cQuFtD8Hbm7pABpw_RPWuJxE66NhxYmIU,11631
|
6
|
+
hydroanomaly-0.3.0.dist-info/licenses/LICENSE,sha256=OphKV48tcMv6ep-7j-8T6nycykPT0g8ZlMJ9zbGvdPs,1066
|
7
|
+
hydroanomaly-0.3.0.dist-info/METADATA,sha256=3NDnQzVH84RCiRpHf1SyQf5OHDIGMsMTEa-tlI822p4,11680
|
8
|
+
hydroanomaly-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
9
|
+
hydroanomaly-0.3.0.dist-info/top_level.txt,sha256=t-5Lc-eTLlkxIhR_N1Cpp6_YZafKS3xLLk9D2CtbE7o,13
|
10
|
+
hydroanomaly-0.3.0.dist-info/RECORD,,
|
@@ -1,227 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: hydroanomaly
|
3
|
-
Version: 0.2.0
|
4
|
-
Summary: A Python package for hydro anomaly detection
|
5
|
-
Home-page: https://github.com/yourusername/hydroanomaly
|
6
|
-
Author: Your Name
|
7
|
-
Author-email: Your Name <your.email@example.com>
|
8
|
-
License-Expression: MIT
|
9
|
-
Project-URL: Homepage, https://github.com/yourusername/hydroanomaly
|
10
|
-
Project-URL: Bug Reports, https://github.com/yourusername/hydroanomaly/issues
|
11
|
-
Project-URL: Source, https://github.com/yourusername/hydroanomaly
|
12
|
-
Keywords: python,package,hydro,anomaly,detection
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
14
|
-
Classifier: Operating System :: OS Independent
|
15
|
-
Requires-Python: >=3.6
|
16
|
-
Description-Content-Type: text/markdown
|
17
|
-
License-File: LICENSE
|
18
|
-
Requires-Dist: pandas>=1.3.0
|
19
|
-
Requires-Dist: numpy>=1.20.0
|
20
|
-
Requires-Dist: requests>=2.25.1
|
21
|
-
Provides-Extra: dev
|
22
|
-
Requires-Dist: pytest>=6.0; extra == "dev"
|
23
|
-
Requires-Dist: black>=21.0; extra == "dev"
|
24
|
-
Requires-Dist: flake8>=3.8; extra == "dev"
|
25
|
-
Requires-Dist: mypy>=0.800; extra == "dev"
|
26
|
-
Dynamic: author
|
27
|
-
Dynamic: home-page
|
28
|
-
Dynamic: license-file
|
29
|
-
Dynamic: requires-python
|
30
|
-
|
31
|
-
# HydroAnomaly
|
32
|
-
|
33
|
-
A Python package for hydro anomaly detection and **USGS water data retrieval**.
|
34
|
-
|
35
|
-
[](https://badge.fury.io/py/hydroanomaly)
|
36
|
-
[](https://pepy.tech/project/hydroanomaly)
|
37
|
-
|
38
|
-
## Installation
|
39
|
-
|
40
|
-
```bash
|
41
|
-
pip install hydroanomaly
|
42
|
-
```
|
43
|
-
|
44
|
-
## 🆕 New Feature: USGS Data Retrieval
|
45
|
-
|
46
|
-
Easily retrieve real-time and historical water data from USGS Water Services:
|
47
|
-
|
48
|
-
```python
|
49
|
-
import hydroanomaly
|
50
|
-
|
51
|
-
# ------------------------
|
52
|
-
# User-defined settings
|
53
|
-
# ------------------------
|
54
|
-
site_number = "294643095035200" # USGS site number
|
55
|
-
parameter_code = "63680" # Turbidity
|
56
|
-
start_date = "2020-01-01"
|
57
|
-
end_date = "2024-12-30"
|
58
|
-
|
59
|
-
# ------------------------
|
60
|
-
# Data Extraction from USGS
|
61
|
-
# ------------------------
|
62
|
-
data = hydroanomaly.get_usgs_data(
|
63
|
-
site_number=site_number,
|
64
|
-
parameter_code=parameter_code,
|
65
|
-
start_date=start_date,
|
66
|
-
end_date=end_date,
|
67
|
-
save_to_file="USGS_turbidity.csv",
|
68
|
-
parameter_name="Turbidity"
|
69
|
-
)
|
70
|
-
|
71
|
-
print(f"Retrieved {len(data)} data points!")
|
72
|
-
print(data.head())
|
73
|
-
```
|
74
|
-
|
75
|
-
## Quick Start
|
76
|
-
|
77
|
-
```python
|
78
|
-
import hydroanomaly
|
79
|
-
|
80
|
-
# Basic greeting functionality
|
81
|
-
print(hydroanomaly.greet("Water Engineer"))
|
82
|
-
# Output: Hello, Water Engineer!
|
83
|
-
|
84
|
-
# Math utilities for data analysis
|
85
|
-
result = hydroanomaly.add(25.5, 14.3)
|
86
|
-
print(f"Sum: {result}")
|
87
|
-
# Output: Sum: 39.8
|
88
|
-
|
89
|
-
# USGS data retrieval
|
90
|
-
data = hydroanomaly.get_usgs_data("08158000", "00060", "2023-01-01", "2023-01-31")
|
91
|
-
print(f"Retrieved {len(data)} discharge measurements")
|
92
|
-
```
|
93
|
-
|
94
|
-
## Features
|
95
|
-
|
96
|
-
- **🌊 USGS Data Retrieval**: Download real-time water data from USGS Water Services
|
97
|
-
- Support for any USGS site and parameter
|
98
|
-
- Automatic data cleaning and validation
|
99
|
-
- Fallback synthetic data generation
|
100
|
-
- CSV export functionality
|
101
|
-
- **Greeting Module**: Simple greeting functionality for applications
|
102
|
-
- **Math Utilities**: Basic mathematical operations for data processing
|
103
|
-
- Addition and multiplication functions
|
104
|
-
- Division with error handling
|
105
|
-
- **Error Handling**: Robust error handling for mathematical operations
|
106
|
-
- **Well Tested**: Comprehensive test suite with 100% pass rate
|
107
|
-
|
108
|
-
## USGS Data Parameters
|
109
|
-
|
110
|
-
Common USGS parameter codes you can use:
|
111
|
-
- **00060**: Discharge (cubic feet per second)
|
112
|
-
- **00065**: Gage height (feet)
|
113
|
-
- **00010**: Water temperature (°C)
|
114
|
-
- **63680**: Turbidity (NTU)
|
115
|
-
- **00300**: Dissolved oxygen (mg/L)
|
116
|
-
- **00095**: Specific conductance (µS/cm)
|
117
|
-
|
118
|
-
Find USGS site numbers at: https://waterdata.usgs.gov/nwis
|
119
|
-
|
120
|
-
## Detailed Usage
|
121
|
-
|
122
|
-
### USGS Data Retrieval
|
123
|
-
```python
|
124
|
-
from hydroanomaly.usgs_data import USGSDataRetriever
|
125
|
-
|
126
|
-
# Create retriever instance
|
127
|
-
retriever = USGSDataRetriever()
|
128
|
-
|
129
|
-
# Get data with full control
|
130
|
-
data = retriever.retrieve_data(
|
131
|
-
site_number="08158000", # Colorado River at Austin, TX
|
132
|
-
parameter_code="00060", # Discharge
|
133
|
-
start_date="2023-01-01",
|
134
|
-
end_date="2023-01-31"
|
135
|
-
)
|
136
|
-
|
137
|
-
# Get summary statistics
|
138
|
-
summary = retriever.get_data_summary(data)
|
139
|
-
print(f"Retrieved {summary['record_count']} records")
|
140
|
-
print(f"Average discharge: {summary['value_stats']['mean']:.2f} cfs")
|
141
|
-
|
142
|
-
# Save data
|
143
|
-
retriever.save_data(data, "discharge_data.csv", "Discharge_cfs")
|
144
|
-
```
|
145
|
-
|
146
|
-
### Greeting Functions
|
147
|
-
```python
|
148
|
-
from hydroanomaly.hello import greet, say_goodbye
|
149
|
-
|
150
|
-
# Greet users
|
151
|
-
welcome_msg = greet("Data Scientist")
|
152
|
-
print(welcome_msg) # Hello, Data Scientist!
|
153
|
-
|
154
|
-
# Say goodbye
|
155
|
-
farewell_msg = say_goodbye("User")
|
156
|
-
print(farewell_msg) # Goodbye, User!
|
157
|
-
```
|
158
|
-
|
159
|
-
### Mathematical Operations
|
160
|
-
```python
|
161
|
-
from hydroanomaly.math_utils import add, multiply, divide
|
162
|
-
|
163
|
-
# Basic operations
|
164
|
-
sum_result = add(10.5, 20.3)
|
165
|
-
product = multiply(5, 7)
|
166
|
-
|
167
|
-
# Safe division with error handling
|
168
|
-
try:
|
169
|
-
result = divide(100, 5)
|
170
|
-
print(f"Result: {result}") # Result: 20.0
|
171
|
-
except ValueError as e:
|
172
|
-
print(f"Error: {e}")
|
173
|
-
```
|
174
|
-
|
175
|
-
## Use Cases
|
176
|
-
|
177
|
-
- **🌊 Real Water Data Analysis**: Retrieve and analyze actual USGS water monitoring data
|
178
|
-
- **📊 Hydro Research**: Access historical water quality and quantity data
|
179
|
-
- **🚰 Water Management**: Monitor discharge, water levels, and quality parameters
|
180
|
-
- **🎓 Educational Projects**: Learn data analysis with real environmental data
|
181
|
-
- **🔬 Environmental Studies**: Research water patterns and anomalies
|
182
|
-
- **⚡ Quick Prototyping**: Rapidly access water data for proof-of-concepts
|
183
|
-
|
184
|
-
## API Reference
|
185
|
-
|
186
|
-
### hydroanomaly.greet(name="World")
|
187
|
-
Returns a greeting message.
|
188
|
-
|
189
|
-
**Parameters:**
|
190
|
-
- `name` (str, optional): Name to greet. Defaults to "World".
|
191
|
-
|
192
|
-
**Returns:**
|
193
|
-
- str: Greeting message
|
194
|
-
|
195
|
-
### hydroanomaly.add(a, b)
|
196
|
-
Adds two numbers.
|
197
|
-
|
198
|
-
**Parameters:**
|
199
|
-
- `a` (int/float): First number
|
200
|
-
- `b` (int/float): Second number
|
201
|
-
|
202
|
-
**Returns:**
|
203
|
-
- int/float: Sum of a and b
|
204
|
-
|
205
|
-
### hydroanomaly.multiply(a, b)
|
206
|
-
Multiplies two numbers.
|
207
|
-
|
208
|
-
**Parameters:**
|
209
|
-
- `a` (int/float): First number
|
210
|
-
- `b` (int/float): Second number
|
211
|
-
|
212
|
-
**Returns:**
|
213
|
-
- int/float: Product of a and b
|
214
|
-
|
215
|
-
## Features
|
216
|
-
|
217
|
-
- Feature 1
|
218
|
-
- Feature 2
|
219
|
-
- Feature 3
|
220
|
-
|
221
|
-
## Contributing
|
222
|
-
|
223
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
224
|
-
|
225
|
-
## License
|
226
|
-
|
227
|
-
This project is licensed under the MIT License - see the LICENSE file for details.
|
@@ -1,9 +0,0 @@
|
|
1
|
-
hydroanomaly/__init__.py,sha256=i3F0lmj7Jia0je1ArZhx4OsK-nnPCulQSz5WoCpZ3MI,413
|
2
|
-
hydroanomaly/hello.py,sha256=AhK7UKF_3TyZcWL4IDlZq_BXdKQzUP-is-jv59fgqk4,566
|
3
|
-
hydroanomaly/math_utils.py,sha256=CDOGWAiRlb2PK5SNFysumnzp7_LbZ9aleHLR_3lsGrs,856
|
4
|
-
hydroanomaly/usgs_data.py,sha256=zUvfu3go-7cQuFtD8Hbm7pABpw_RPWuJxE66NhxYmIU,11631
|
5
|
-
hydroanomaly-0.2.0.dist-info/licenses/LICENSE,sha256=OphKV48tcMv6ep-7j-8T6nycykPT0g8ZlMJ9zbGvdPs,1066
|
6
|
-
hydroanomaly-0.2.0.dist-info/METADATA,sha256=7VORMpDk286u6ElwB890-ISI9FlynP21CXk-dSR-8sM,6140
|
7
|
-
hydroanomaly-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
-
hydroanomaly-0.2.0.dist-info/top_level.txt,sha256=t-5Lc-eTLlkxIhR_N1Cpp6_YZafKS3xLLk9D2CtbE7o,13
|
9
|
-
hydroanomaly-0.2.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|