hydroanomaly 0.4.0__py3-none-any.whl → 0.6.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 +37 -137
- hydroanomaly/sentinel_bands.py +157 -0
- hydroanomaly/usgs_turbidity.py +150 -0
- hydroanomaly/visualize.py +226 -0
- {hydroanomaly-0.4.0.dist-info → hydroanomaly-0.6.0.dist-info}/METADATA +2 -2
- hydroanomaly-0.6.0.dist-info/RECORD +9 -0
- hydroanomaly/hello.py +0 -29
- hydroanomaly/math_utils.py +0 -50
- hydroanomaly/plotting.py +0 -389
- hydroanomaly/sentinel_data.py +0 -516
- hydroanomaly/usgs_data.py +0 -311
- hydroanomaly-0.4.0.dist-info/RECORD +0 -11
- {hydroanomaly-0.4.0.dist-info → hydroanomaly-0.6.0.dist-info}/WHEEL +0 -0
- {hydroanomaly-0.4.0.dist-info → hydroanomaly-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {hydroanomaly-0.4.0.dist-info → hydroanomaly-0.6.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,226 @@
|
|
1
|
+
"""
|
2
|
+
Simple Time Series Visualization
|
3
|
+
|
4
|
+
This module provides simple functions to visualize time series data.
|
5
|
+
That's it - nothing else!
|
6
|
+
"""
|
7
|
+
|
8
|
+
import matplotlib.pyplot as plt
|
9
|
+
import matplotlib.dates as mdates
|
10
|
+
import pandas as pd
|
11
|
+
import numpy as np
|
12
|
+
from datetime import datetime
|
13
|
+
|
14
|
+
|
15
|
+
def plot_timeseries(data: pd.DataFrame, title: str = "Time Series Data", save_file: str = None) -> None:
|
16
|
+
"""
|
17
|
+
Create a simple time series plot.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
data (pd.DataFrame): DataFrame with datetime index and numeric columns
|
21
|
+
title (str): Title for the plot
|
22
|
+
save_file (str): Optional filename to save the plot
|
23
|
+
|
24
|
+
Example:
|
25
|
+
>>> plot_timeseries(turbidity_data, "Turbidity Over Time", "turbidity_plot.png")
|
26
|
+
"""
|
27
|
+
|
28
|
+
if data.empty:
|
29
|
+
print("❌ No data to plot")
|
30
|
+
return
|
31
|
+
|
32
|
+
print(f"📊 Creating plot: {title}")
|
33
|
+
|
34
|
+
# Create figure
|
35
|
+
plt.figure(figsize=(12, 6))
|
36
|
+
|
37
|
+
# Plot each column
|
38
|
+
for column in data.columns:
|
39
|
+
if pd.api.types.is_numeric_dtype(data[column]):
|
40
|
+
plt.plot(data.index, data[column], label=column, linewidth=1.5, alpha=0.8)
|
41
|
+
|
42
|
+
# Format plot
|
43
|
+
plt.title(title, fontsize=14, fontweight='bold', pad=20)
|
44
|
+
plt.xlabel('Date', fontsize=12)
|
45
|
+
plt.ylabel('Value', fontsize=12)
|
46
|
+
plt.grid(True, alpha=0.3)
|
47
|
+
|
48
|
+
# Format x-axis dates
|
49
|
+
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
|
50
|
+
plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=3))
|
51
|
+
plt.xticks(rotation=45)
|
52
|
+
|
53
|
+
# Add legend if multiple columns
|
54
|
+
if len(data.columns) > 1:
|
55
|
+
plt.legend()
|
56
|
+
|
57
|
+
plt.tight_layout()
|
58
|
+
|
59
|
+
# Save if requested
|
60
|
+
if save_file:
|
61
|
+
plt.savefig(save_file, dpi=300, bbox_inches='tight')
|
62
|
+
print(f"💾 Plot saved as {save_file}")
|
63
|
+
|
64
|
+
plt.show()
|
65
|
+
print("✅ Plot created successfully!")
|
66
|
+
|
67
|
+
|
68
|
+
def plot_turbidity(turbidity_data: pd.DataFrame, save_file: str = None) -> None:
|
69
|
+
"""
|
70
|
+
Create a turbidity-specific plot with appropriate formatting.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
turbidity_data (pd.DataFrame): DataFrame with turbidity values
|
74
|
+
save_file (str): Optional filename to save the plot
|
75
|
+
"""
|
76
|
+
|
77
|
+
if turbidity_data.empty:
|
78
|
+
print("❌ No turbidity data to plot")
|
79
|
+
return
|
80
|
+
|
81
|
+
print("🌫️ Creating turbidity plot")
|
82
|
+
|
83
|
+
plt.figure(figsize=(12, 6))
|
84
|
+
|
85
|
+
# Plot turbidity
|
86
|
+
column_name = turbidity_data.columns[0]
|
87
|
+
plt.plot(turbidity_data.index, turbidity_data.iloc[:, 0],
|
88
|
+
color='brown', linewidth=1.5, alpha=0.8)
|
89
|
+
|
90
|
+
# Add threshold lines for water quality assessment
|
91
|
+
plt.axhline(y=10, color='orange', linestyle='--', alpha=0.7, label='Moderate (10 NTU)')
|
92
|
+
plt.axhline(y=25, color='red', linestyle='--', alpha=0.7, label='High (25 NTU)')
|
93
|
+
|
94
|
+
# Format plot
|
95
|
+
plt.title('💧 Turbidity Time Series', fontsize=14, fontweight='bold', pad=20)
|
96
|
+
plt.xlabel('Date', fontsize=12)
|
97
|
+
plt.ylabel('Turbidity (NTU)', fontsize=12)
|
98
|
+
plt.grid(True, alpha=0.3)
|
99
|
+
|
100
|
+
# Format x-axis
|
101
|
+
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
|
102
|
+
plt.xticks(rotation=45)
|
103
|
+
|
104
|
+
plt.legend()
|
105
|
+
plt.tight_layout()
|
106
|
+
|
107
|
+
# Save if requested
|
108
|
+
if save_file:
|
109
|
+
plt.savefig(save_file, dpi=300, bbox_inches='tight')
|
110
|
+
print(f"💾 Turbidity plot saved as {save_file}")
|
111
|
+
|
112
|
+
plt.show()
|
113
|
+
print("✅ Turbidity plot created!")
|
114
|
+
|
115
|
+
|
116
|
+
def plot_sentinel(sentinel_data: pd.DataFrame, save_file: str = None) -> None:
|
117
|
+
"""
|
118
|
+
Create a Sentinel satellite data plot.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
sentinel_data (pd.DataFrame): DataFrame with Sentinel band values
|
122
|
+
save_file (str): Optional filename to save the plot
|
123
|
+
"""
|
124
|
+
|
125
|
+
if sentinel_data.empty:
|
126
|
+
print("❌ No Sentinel data to plot")
|
127
|
+
return
|
128
|
+
|
129
|
+
print("🛰️ Creating Sentinel bands plot")
|
130
|
+
|
131
|
+
plt.figure(figsize=(12, 8))
|
132
|
+
|
133
|
+
# Define colors for different bands
|
134
|
+
band_colors = {
|
135
|
+
'B2': 'blue', # Blue band
|
136
|
+
'B3': 'green', # Green band
|
137
|
+
'B4': 'red', # Red band
|
138
|
+
'B8': 'darkred', # NIR band
|
139
|
+
'NDVI': 'darkgreen'
|
140
|
+
}
|
141
|
+
|
142
|
+
# Plot each band
|
143
|
+
for column in sentinel_data.columns:
|
144
|
+
color = band_colors.get(column, 'black')
|
145
|
+
plt.plot(sentinel_data.index, sentinel_data[column],
|
146
|
+
label=column, color=color, linewidth=2, marker='o', markersize=4)
|
147
|
+
|
148
|
+
# Format plot
|
149
|
+
plt.title('🛰️ Sentinel Satellite Data', fontsize=14, fontweight='bold', pad=20)
|
150
|
+
plt.xlabel('Date', fontsize=12)
|
151
|
+
plt.ylabel('Digital Number / Index Value', fontsize=12)
|
152
|
+
plt.grid(True, alpha=0.3)
|
153
|
+
|
154
|
+
# Format x-axis
|
155
|
+
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
|
156
|
+
plt.xticks(rotation=45)
|
157
|
+
|
158
|
+
plt.legend()
|
159
|
+
plt.tight_layout()
|
160
|
+
|
161
|
+
# Save if requested
|
162
|
+
if save_file:
|
163
|
+
plt.savefig(save_file, dpi=300, bbox_inches='tight')
|
164
|
+
print(f"💾 Sentinel plot saved as {save_file}")
|
165
|
+
|
166
|
+
plt.show()
|
167
|
+
print("✅ Sentinel plot created!")
|
168
|
+
|
169
|
+
|
170
|
+
def plot_comparison(data1: pd.DataFrame, data2: pd.DataFrame,
|
171
|
+
label1: str = "Dataset 1", label2: str = "Dataset 2",
|
172
|
+
title: str = "Data Comparison", save_file: str = None) -> None:
|
173
|
+
"""
|
174
|
+
Create a comparison plot of two time series datasets.
|
175
|
+
|
176
|
+
Args:
|
177
|
+
data1 (pd.DataFrame): First dataset
|
178
|
+
data2 (pd.DataFrame): Second dataset
|
179
|
+
label1 (str): Label for first dataset
|
180
|
+
label2 (str): Label for second dataset
|
181
|
+
title (str): Plot title
|
182
|
+
save_file (str): Optional filename to save the plot
|
183
|
+
"""
|
184
|
+
|
185
|
+
if data1.empty and data2.empty:
|
186
|
+
print("❌ No data to plot")
|
187
|
+
return
|
188
|
+
|
189
|
+
print(f"📊 Creating comparison plot: {title}")
|
190
|
+
|
191
|
+
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=True)
|
192
|
+
|
193
|
+
# Plot first dataset
|
194
|
+
if not data1.empty:
|
195
|
+
ax1.plot(data1.index, data1.iloc[:, 0], color='blue', linewidth=1.5, alpha=0.8)
|
196
|
+
ax1.set_title(f'{label1}', fontsize=12, fontweight='bold')
|
197
|
+
ax1.set_ylabel('Value', fontsize=10)
|
198
|
+
ax1.grid(True, alpha=0.3)
|
199
|
+
|
200
|
+
# Plot second dataset
|
201
|
+
if not data2.empty:
|
202
|
+
ax2.plot(data2.index, data2.iloc[:, 0], color='red', linewidth=1.5, alpha=0.8)
|
203
|
+
ax2.set_title(f'{label2}', fontsize=12, fontweight='bold')
|
204
|
+
ax2.set_ylabel('Value', fontsize=10)
|
205
|
+
ax2.grid(True, alpha=0.3)
|
206
|
+
|
207
|
+
# Format x-axis
|
208
|
+
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
|
209
|
+
plt.xticks(rotation=45)
|
210
|
+
ax2.set_xlabel('Date', fontsize=12)
|
211
|
+
|
212
|
+
plt.suptitle(title, fontsize=14, fontweight='bold')
|
213
|
+
plt.tight_layout()
|
214
|
+
|
215
|
+
# Save if requested
|
216
|
+
if save_file:
|
217
|
+
plt.savefig(save_file, dpi=300, bbox_inches='tight')
|
218
|
+
print(f"💾 Comparison plot saved as {save_file}")
|
219
|
+
|
220
|
+
plt.show()
|
221
|
+
print("✅ Comparison plot created!")
|
222
|
+
|
223
|
+
|
224
|
+
# Simple aliases
|
225
|
+
plot = plot_timeseries
|
226
|
+
visualize = plot_timeseries
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hydroanomaly
|
3
|
-
Version: 0.
|
4
|
-
Summary: A Python package for hydro anomaly detection
|
3
|
+
Version: 0.6.0
|
4
|
+
Summary: A Python package for hydro anomaly detection with simple USGS data retrieval
|
5
5
|
Home-page: https://github.com/yourusername/hydroanomaly
|
6
6
|
Author: Your Name
|
7
7
|
Author-email: Your Name <your.email@example.com>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
hydroanomaly/__init__.py,sha256=pbS4SUDEYV8e9we3YqAe3Jo-EKX77eCdwirofp4Yk_4,1313
|
2
|
+
hydroanomaly/sentinel_bands.py,sha256=Zvy9vJ7RooJTWLJK-ihGZ6CEneQcHVJ8I5MgueYcoyQ,5534
|
3
|
+
hydroanomaly/usgs_turbidity.py,sha256=r0ozmiZXVYjtu04UnT3ijxra_WQVUUpus7WLcYCH3iM,4921
|
4
|
+
hydroanomaly/visualize.py,sha256=gkLgI3agx291jK5o08nYEbEpGpr6cD-6aAKn2Ha2Lqk,6937
|
5
|
+
hydroanomaly-0.6.0.dist-info/licenses/LICENSE,sha256=OphKV48tcMv6ep-7j-8T6nycykPT0g8ZlMJ9zbGvdPs,1066
|
6
|
+
hydroanomaly-0.6.0.dist-info/METADATA,sha256=cZxYHfAnYHP1Wqspxf--JUBlKDKs29mhybbhslS1Zx0,11873
|
7
|
+
hydroanomaly-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
hydroanomaly-0.6.0.dist-info/top_level.txt,sha256=t-5Lc-eTLlkxIhR_N1Cpp6_YZafKS3xLLk9D2CtbE7o,13
|
9
|
+
hydroanomaly-0.6.0.dist-info/RECORD,,
|
hydroanomaly/hello.py
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Hello module - provides greeting functionality
|
3
|
-
"""
|
4
|
-
|
5
|
-
|
6
|
-
def greet(name="World"):
|
7
|
-
"""
|
8
|
-
Greet someone with a friendly message.
|
9
|
-
|
10
|
-
Args:
|
11
|
-
name (str): The name of the person to greet. Defaults to "World".
|
12
|
-
|
13
|
-
Returns:
|
14
|
-
str: A greeting message.
|
15
|
-
"""
|
16
|
-
return f"Hello, {name}!"
|
17
|
-
|
18
|
-
|
19
|
-
def say_goodbye(name="World"):
|
20
|
-
"""
|
21
|
-
Say goodbye to someone.
|
22
|
-
|
23
|
-
Args:
|
24
|
-
name (str): The name of the person to say goodbye to. Defaults to "World".
|
25
|
-
|
26
|
-
Returns:
|
27
|
-
str: A goodbye message.
|
28
|
-
"""
|
29
|
-
return f"Goodbye, {name}!"
|
hydroanomaly/math_utils.py
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Math utilities module - provides basic mathematical functions
|
3
|
-
"""
|
4
|
-
|
5
|
-
|
6
|
-
def add(a, b):
|
7
|
-
"""
|
8
|
-
Add two numbers together.
|
9
|
-
|
10
|
-
Args:
|
11
|
-
a (int/float): First number
|
12
|
-
b (int/float): Second number
|
13
|
-
|
14
|
-
Returns:
|
15
|
-
int/float: Sum of a and b
|
16
|
-
"""
|
17
|
-
return a + b
|
18
|
-
|
19
|
-
|
20
|
-
def multiply(a, b):
|
21
|
-
"""
|
22
|
-
Multiply two numbers together.
|
23
|
-
|
24
|
-
Args:
|
25
|
-
a (int/float): First number
|
26
|
-
b (int/float): Second number
|
27
|
-
|
28
|
-
Returns:
|
29
|
-
int/float: Product of a and b
|
30
|
-
"""
|
31
|
-
return a * b
|
32
|
-
|
33
|
-
|
34
|
-
def divide(a, b):
|
35
|
-
"""
|
36
|
-
Divide two numbers.
|
37
|
-
|
38
|
-
Args:
|
39
|
-
a (int/float): Dividend
|
40
|
-
b (int/float): Divisor
|
41
|
-
|
42
|
-
Returns:
|
43
|
-
float: Result of a divided by b
|
44
|
-
|
45
|
-
Raises:
|
46
|
-
ValueError: If b is zero
|
47
|
-
"""
|
48
|
-
if b == 0:
|
49
|
-
raise ValueError("Cannot divide by zero")
|
50
|
-
return a / b
|