bulum 0.3.3.dev1__py3-none-any.whl → 0.3.4.dev1__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.
- bulum/__init__.py +2 -2
- bulum/clim/__init__.py +1 -1
- bulum/clim/clim.py +148 -148
- bulum/clim/tests/test_clim.py +71 -71
- bulum/demo.py +5 -5
- bulum/io/__init__.py +6 -6
- bulum/io/csv_io.py +94 -94
- bulum/io/general_io.py +55 -55
- bulum/io/idx_io.py +341 -341
- bulum/io/iqqm_out_reader.py +367 -367
- bulum/io/lqn_io.py +75 -75
- bulum/io/res_csv_io.py +203 -203
- bulum/io/tests/test_csv_io.py +55 -55
- bulum/io/tests/test_general_io.py +22 -22
- bulum/io/tests/test_idx_io.py +112 -112
- bulum/io/tests/test_iqqm_out_reader.py +48 -48
- bulum/io/tests/test_lqn_io.py +52 -52
- bulum/io/tests/test_res_csv_io.py +60 -60
- bulum/maps/__init__.py +1 -1
- bulum/maps/station_maps.py +136 -136
- bulum/plots/__init__.py +4 -4
- bulum/plots/altair_plots.py +850 -850
- bulum/plots/ensemble_altair_plots.py +104 -104
- bulum/plots/node_diagrams.py +10 -10
- bulum/plots/plot_functions.py +106 -106
- bulum/plots/tests/__init__.py +1 -1
- bulum/plots/tests/test_plot_functions.py +222 -222
- bulum/stats/__init__.py +6 -6
- bulum/stats/aggregate_stats.py +196 -196
- bulum/stats/ensemble_stats.py +140 -140
- bulum/stats/negflo.py +783 -783
- bulum/stats/qastat2s/__init__.py +30 -0
- bulum/stats/qastat2s/reportcard_data.py +828 -0
- bulum/stats/qastat2s/reportcard_plot.py +774 -0
- bulum/stats/qastat2s/tests/test_qastat2s.py +112 -0
- bulum/stats/reliability_stats_class.py +282 -282
- bulum/stats/stochastic_data_check.py +541 -541
- bulum/stats/storage_level_assessment.py +838 -838
- bulum/stats/swflo2s/swflo2s.py +163 -163
- bulum/stats/swflo2s/tests/test_swflo2s.py +58 -58
- bulum/stats/tests/test_negflo.py +359 -359
- bulum/stats/tests/test_stats.py +365 -365
- bulum/stats/tests/test_storage_level_assessment.py +749 -749
- bulum/stoch/generate.py +91 -91
- bulum/stoch/tests/test_stoch.py +13 -13
- bulum/test_circular_import.py +26 -26
- bulum/trans/tests/test_trans.py +20 -20
- bulum/trans/transformers.py +100 -100
- bulum/utils/__init__.py +16 -16
- bulum/utils/dataframe_extensions.py +1224 -1224
- bulum/utils/dataframe_functions.py +399 -399
- bulum/utils/datetime_functions.py +790 -790
- bulum/utils/interpolation.py +62 -62
- bulum/utils/tests/test_ensembles.py +710 -710
- bulum/utils/tests/test_interpolation.py +87 -87
- bulum/utils/tests/test_parametrized.py +218 -218
- bulum/utils/tests/test_tsdf.py +540 -540
- bulum/utils/tests/test_utils.py +701 -701
- bulum/version.py +5 -5
- {bulum-0.3.3.dev1.dist-info → bulum-0.3.4.dev1.dist-info}/METADATA +139 -139
- bulum-0.3.4.dev1.dist-info/RECORD +69 -0
- {bulum-0.3.3.dev1.dist-info → bulum-0.3.4.dev1.dist-info}/licenses/LICENSE.md +595 -595
- bulum-0.3.3.dev1.dist-info/RECORD +0 -65
- {bulum-0.3.3.dev1.dist-info → bulum-0.3.4.dev1.dist-info}/WHEEL +0 -0
- {bulum-0.3.3.dev1.dist-info → bulum-0.3.4.dev1.dist-info}/top_level.txt +0 -0
bulum/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .version import __version__
|
|
2
|
-
from .demo import *
|
|
1
|
+
from .version import __version__
|
|
2
|
+
from .demo import *
|
|
3
3
|
#from .stoch import *
|
bulum/clim/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
from .clim import *
|
|
1
|
+
from .clim import *
|
bulum/clim/clim.py
CHANGED
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import pandas as pd
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def derive_transformation_curves(original_ts: pd.Series, augmented_ts: pd.Series, season_start_months=[1,2,3,4,5,6,7,8,9,10,11,12], epsilon=1e-3) -> dict:
|
|
6
|
-
"""Returns a dictionary of exceedence-based transformation curves - one for
|
|
7
|
-
each season with the season's start month as the key. These are tables that
|
|
8
|
-
map from exceedance (cunnane plotting position as a fraction) to a scaling
|
|
9
|
-
factor. These are intended to be used to effectively summarise
|
|
10
|
-
climate-change adjustments, and allow them to be transported from one
|
|
11
|
-
timeseries to another.
|
|
12
|
-
|
|
13
|
-
Parameters
|
|
14
|
-
----------
|
|
15
|
-
original_ts : pd.Series
|
|
16
|
-
augmented_ts : pd.Series
|
|
17
|
-
season_start_months : list, optional
|
|
18
|
-
Defaults to [1,2,3,4,5,6,7,8,9,10,11,12].
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
df = pd.DataFrame()
|
|
22
|
-
df["x"] = original_ts
|
|
23
|
-
df["y"] = augmented_ts
|
|
24
|
-
df = df.dropna() # Force common period
|
|
25
|
-
answer = {}
|
|
26
|
-
for i in range(len(season_start_months)):
|
|
27
|
-
# Get a list of the months in this season
|
|
28
|
-
start_month = season_start_months[i]
|
|
29
|
-
season_len = (season_start_months + [m + 12 for m in season_start_months])[i + 1] - start_month
|
|
30
|
-
months_in_this_season = [1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12][start_month - 1: start_month - 1 + season_len]
|
|
31
|
-
# Find the data for this season
|
|
32
|
-
df_m = df[[int(d[5:7]) in months_in_this_season for d in df.index]] #d[5:7] is the month part of the date string
|
|
33
|
-
x = np.sort(df_m.x.values)
|
|
34
|
-
y = np.sort(df_m.y.values)
|
|
35
|
-
# The transformation factor is y/x except when the original value x is zero (<epsilon) in which case we default to 1.0
|
|
36
|
-
f = np.where(x < epsilon, 1.0, y / x)
|
|
37
|
-
n = len(x)
|
|
38
|
-
ii = [i + 1 for i in range(n)] #index starting at 1
|
|
39
|
-
p = [(i - 0.4)/(n + 0.2) for i in ii]
|
|
40
|
-
answer[start_month] = [p,f]
|
|
41
|
-
return answer
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def apply_transformation_curves(tranformation_curves: dict, series: pd.Series) -> pd.Series:
|
|
45
|
-
"""Applies seasonal transformation curves to an input series.
|
|
46
|
-
Refer to the function `derive_transformation_curves`.
|
|
47
|
-
|
|
48
|
-
Parameters
|
|
49
|
-
----------
|
|
50
|
-
tranformation_curves : dict
|
|
51
|
-
series : pd.Series
|
|
52
|
-
|
|
53
|
-
Returns
|
|
54
|
-
-------
|
|
55
|
-
pd.Series
|
|
56
|
-
"""
|
|
57
|
-
dates = series.index
|
|
58
|
-
answer = series.copy()
|
|
59
|
-
# Apply each transformation curves to the whole series. Splice the appropriate
|
|
60
|
-
# parts (seasons) into the 'answer' series as we go.
|
|
61
|
-
season_start_months = sorted(tranformation_curves.keys())
|
|
62
|
-
for i in range(len(season_start_months)):
|
|
63
|
-
# Identify the transform curve for this season
|
|
64
|
-
start_month = season_start_months[i]
|
|
65
|
-
t = tranformation_curves[start_month]
|
|
66
|
-
xp = t[0]
|
|
67
|
-
fp = t[1]
|
|
68
|
-
# Get a list of the months in this season
|
|
69
|
-
season_len = (season_start_months + [m + 12 for m in season_start_months])[i + 1] - start_month
|
|
70
|
-
months_in_this_season = [1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12][start_month - 1: start_month - 1 + season_len]
|
|
71
|
-
# Find the data for this season
|
|
72
|
-
m = len(series)
|
|
73
|
-
season_dates = pd.Series([d for d in dates if int(d[5:7]) in months_in_this_season]) #d[5:7] is the month part of the date string
|
|
74
|
-
values = answer[season_dates]
|
|
75
|
-
# And get their ranks and plotting positions
|
|
76
|
-
rank_starting_at_one = values.rank(ascending=True) # This function is nice because equal values are assigned the same (averaged) rank.
|
|
77
|
-
n = len(values)
|
|
78
|
-
p = [(r - 0.4)/(n + 0.2) for r in rank_starting_at_one] # Cunnane plotting position
|
|
79
|
-
f = np.interp(p, xp, fp) # interpolated scaling factors
|
|
80
|
-
# Calcualte new values and update the answer
|
|
81
|
-
new_values = pd.Series([values.iloc[i] * f[i] for i in range(n)], index=season_dates)
|
|
82
|
-
answer.update(new_values)
|
|
83
|
-
# Return a pd.Series so user can easily join it back into a dataframe
|
|
84
|
-
return pd.Series(answer, index=dates, name=series.name)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def derive_transformation_factors(original_ts: pd.Series, augmented_ts: pd.Series, season_start_months=[1,2,3,4,5,6,7,8,9,10,11,12], epsilon=1e-3) -> dict:
|
|
88
|
-
"""Returns a dictionary of transformation factors - one for each season
|
|
89
|
-
with the season's start month as the key. These scaling factors are intended to
|
|
90
|
-
be used to effectively summarise climate-change adjustments, and allow them to be
|
|
91
|
-
transported from one timeseries to another.
|
|
92
|
-
|
|
93
|
-
Parameters
|
|
94
|
-
----------
|
|
95
|
-
original_ts : pd.Series
|
|
96
|
-
augmented_ts : pd.Series
|
|
97
|
-
season_start_months : list, optional
|
|
98
|
-
[1,2,3,4,5,6,7,8,9,10,11,12].
|
|
99
|
-
epsilon : float
|
|
100
|
-
Threshold below which values are treated as zero, and the associated factor defaults to 1.
|
|
101
|
-
|
|
102
|
-
"""
|
|
103
|
-
# Create a map of month -> season_start_month (for all months)
|
|
104
|
-
month_to_season_map = {}
|
|
105
|
-
key = max(season_start_months)
|
|
106
|
-
for m in [1,2,3,4,5,6,7,8,9,10,11,12]:
|
|
107
|
-
if m in season_start_months:
|
|
108
|
-
key = m
|
|
109
|
-
month_to_season_map[m] = key
|
|
110
|
-
# Put the data in a dataframe, and groupby season start month
|
|
111
|
-
df = pd.DataFrame()
|
|
112
|
-
df["x"] = original_ts
|
|
113
|
-
df["y"] = augmented_ts
|
|
114
|
-
df = df.dropna() # Force common period
|
|
115
|
-
df['m'] = df.index.month
|
|
116
|
-
df['s'] = df['m'].map(month_to_season_map)
|
|
117
|
-
df2 = df.groupby('s').agg('sum')
|
|
118
|
-
df2['f'] = np.where(df2.x < epsilon, 1.0, df2.y / df2.x)
|
|
119
|
-
return df2['f'].to_dict()
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def apply_transformation_factors(transformation_factors: dict, series: pd.Series) -> pd.Series:
|
|
123
|
-
"""Applies seasonal transformation factors to an input series.
|
|
124
|
-
Refer to the function `derive_transformation_curves`.
|
|
125
|
-
|
|
126
|
-
Parameters
|
|
127
|
-
----------
|
|
128
|
-
transformation_curves : dict
|
|
129
|
-
series : pd.Series
|
|
130
|
-
|
|
131
|
-
"""
|
|
132
|
-
# Create a map of month -> factor (containing all months)
|
|
133
|
-
season_start_months = sorted(transformation_factors.keys())
|
|
134
|
-
month_to_factor_map = {}
|
|
135
|
-
key = max(season_start_months)
|
|
136
|
-
for m in [1,2,3,4,5,6,7,8,9,10,11,12]:
|
|
137
|
-
if m in season_start_months:
|
|
138
|
-
key = m
|
|
139
|
-
month_to_factor_map[m] = transformation_factors[key]
|
|
140
|
-
# Apply transformation factors to the whole series. Splice the appropriate
|
|
141
|
-
df = pd.DataFrame()
|
|
142
|
-
df['x'] = series
|
|
143
|
-
df['m'] = df.index.month
|
|
144
|
-
df['f'] = df['m'].map(month_to_factor_map)
|
|
145
|
-
df['y'] = df['x'] * df['f']
|
|
146
|
-
answer = df['y']
|
|
147
|
-
answer.name = series.name
|
|
148
|
-
return answer
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def derive_transformation_curves(original_ts: pd.Series, augmented_ts: pd.Series, season_start_months=[1,2,3,4,5,6,7,8,9,10,11,12], epsilon=1e-3) -> dict:
|
|
6
|
+
"""Returns a dictionary of exceedence-based transformation curves - one for
|
|
7
|
+
each season with the season's start month as the key. These are tables that
|
|
8
|
+
map from exceedance (cunnane plotting position as a fraction) to a scaling
|
|
9
|
+
factor. These are intended to be used to effectively summarise
|
|
10
|
+
climate-change adjustments, and allow them to be transported from one
|
|
11
|
+
timeseries to another.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
original_ts : pd.Series
|
|
16
|
+
augmented_ts : pd.Series
|
|
17
|
+
season_start_months : list, optional
|
|
18
|
+
Defaults to [1,2,3,4,5,6,7,8,9,10,11,12].
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
df = pd.DataFrame()
|
|
22
|
+
df["x"] = original_ts
|
|
23
|
+
df["y"] = augmented_ts
|
|
24
|
+
df = df.dropna() # Force common period
|
|
25
|
+
answer = {}
|
|
26
|
+
for i in range(len(season_start_months)):
|
|
27
|
+
# Get a list of the months in this season
|
|
28
|
+
start_month = season_start_months[i]
|
|
29
|
+
season_len = (season_start_months + [m + 12 for m in season_start_months])[i + 1] - start_month
|
|
30
|
+
months_in_this_season = [1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12][start_month - 1: start_month - 1 + season_len]
|
|
31
|
+
# Find the data for this season
|
|
32
|
+
df_m = df[[int(d[5:7]) in months_in_this_season for d in df.index]] #d[5:7] is the month part of the date string
|
|
33
|
+
x = np.sort(df_m.x.values)
|
|
34
|
+
y = np.sort(df_m.y.values)
|
|
35
|
+
# The transformation factor is y/x except when the original value x is zero (<epsilon) in which case we default to 1.0
|
|
36
|
+
f = np.where(x < epsilon, 1.0, y / x)
|
|
37
|
+
n = len(x)
|
|
38
|
+
ii = [i + 1 for i in range(n)] #index starting at 1
|
|
39
|
+
p = [(i - 0.4)/(n + 0.2) for i in ii]
|
|
40
|
+
answer[start_month] = [p,f]
|
|
41
|
+
return answer
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def apply_transformation_curves(tranformation_curves: dict, series: pd.Series) -> pd.Series:
|
|
45
|
+
"""Applies seasonal transformation curves to an input series.
|
|
46
|
+
Refer to the function `derive_transformation_curves`.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
tranformation_curves : dict
|
|
51
|
+
series : pd.Series
|
|
52
|
+
|
|
53
|
+
Returns
|
|
54
|
+
-------
|
|
55
|
+
pd.Series
|
|
56
|
+
"""
|
|
57
|
+
dates = series.index
|
|
58
|
+
answer = series.copy()
|
|
59
|
+
# Apply each transformation curves to the whole series. Splice the appropriate
|
|
60
|
+
# parts (seasons) into the 'answer' series as we go.
|
|
61
|
+
season_start_months = sorted(tranformation_curves.keys())
|
|
62
|
+
for i in range(len(season_start_months)):
|
|
63
|
+
# Identify the transform curve for this season
|
|
64
|
+
start_month = season_start_months[i]
|
|
65
|
+
t = tranformation_curves[start_month]
|
|
66
|
+
xp = t[0]
|
|
67
|
+
fp = t[1]
|
|
68
|
+
# Get a list of the months in this season
|
|
69
|
+
season_len = (season_start_months + [m + 12 for m in season_start_months])[i + 1] - start_month
|
|
70
|
+
months_in_this_season = [1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12][start_month - 1: start_month - 1 + season_len]
|
|
71
|
+
# Find the data for this season
|
|
72
|
+
m = len(series)
|
|
73
|
+
season_dates = pd.Series([d for d in dates if int(d[5:7]) in months_in_this_season]) #d[5:7] is the month part of the date string
|
|
74
|
+
values = answer[season_dates]
|
|
75
|
+
# And get their ranks and plotting positions
|
|
76
|
+
rank_starting_at_one = values.rank(ascending=True) # This function is nice because equal values are assigned the same (averaged) rank.
|
|
77
|
+
n = len(values)
|
|
78
|
+
p = [(r - 0.4)/(n + 0.2) for r in rank_starting_at_one] # Cunnane plotting position
|
|
79
|
+
f = np.interp(p, xp, fp) # interpolated scaling factors
|
|
80
|
+
# Calcualte new values and update the answer
|
|
81
|
+
new_values = pd.Series([values.iloc[i] * f[i] for i in range(n)], index=season_dates)
|
|
82
|
+
answer.update(new_values)
|
|
83
|
+
# Return a pd.Series so user can easily join it back into a dataframe
|
|
84
|
+
return pd.Series(answer, index=dates, name=series.name)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def derive_transformation_factors(original_ts: pd.Series, augmented_ts: pd.Series, season_start_months=[1,2,3,4,5,6,7,8,9,10,11,12], epsilon=1e-3) -> dict:
|
|
88
|
+
"""Returns a dictionary of transformation factors - one for each season
|
|
89
|
+
with the season's start month as the key. These scaling factors are intended to
|
|
90
|
+
be used to effectively summarise climate-change adjustments, and allow them to be
|
|
91
|
+
transported from one timeseries to another.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
original_ts : pd.Series
|
|
96
|
+
augmented_ts : pd.Series
|
|
97
|
+
season_start_months : list, optional
|
|
98
|
+
[1,2,3,4,5,6,7,8,9,10,11,12].
|
|
99
|
+
epsilon : float
|
|
100
|
+
Threshold below which values are treated as zero, and the associated factor defaults to 1.
|
|
101
|
+
|
|
102
|
+
"""
|
|
103
|
+
# Create a map of month -> season_start_month (for all months)
|
|
104
|
+
month_to_season_map = {}
|
|
105
|
+
key = max(season_start_months)
|
|
106
|
+
for m in [1,2,3,4,5,6,7,8,9,10,11,12]:
|
|
107
|
+
if m in season_start_months:
|
|
108
|
+
key = m
|
|
109
|
+
month_to_season_map[m] = key
|
|
110
|
+
# Put the data in a dataframe, and groupby season start month
|
|
111
|
+
df = pd.DataFrame()
|
|
112
|
+
df["x"] = original_ts
|
|
113
|
+
df["y"] = augmented_ts
|
|
114
|
+
df = df.dropna() # Force common period
|
|
115
|
+
df['m'] = df.index.month
|
|
116
|
+
df['s'] = df['m'].map(month_to_season_map)
|
|
117
|
+
df2 = df.groupby('s').agg('sum')
|
|
118
|
+
df2['f'] = np.where(df2.x < epsilon, 1.0, df2.y / df2.x)
|
|
119
|
+
return df2['f'].to_dict()
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def apply_transformation_factors(transformation_factors: dict, series: pd.Series) -> pd.Series:
|
|
123
|
+
"""Applies seasonal transformation factors to an input series.
|
|
124
|
+
Refer to the function `derive_transformation_curves`.
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
transformation_curves : dict
|
|
129
|
+
series : pd.Series
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
# Create a map of month -> factor (containing all months)
|
|
133
|
+
season_start_months = sorted(transformation_factors.keys())
|
|
134
|
+
month_to_factor_map = {}
|
|
135
|
+
key = max(season_start_months)
|
|
136
|
+
for m in [1,2,3,4,5,6,7,8,9,10,11,12]:
|
|
137
|
+
if m in season_start_months:
|
|
138
|
+
key = m
|
|
139
|
+
month_to_factor_map[m] = transformation_factors[key]
|
|
140
|
+
# Apply transformation factors to the whole series. Splice the appropriate
|
|
141
|
+
df = pd.DataFrame()
|
|
142
|
+
df['x'] = series
|
|
143
|
+
df['m'] = df.index.month
|
|
144
|
+
df['f'] = df['m'].map(month_to_factor_map)
|
|
145
|
+
df['y'] = df['x'] * df['f']
|
|
146
|
+
answer = df['y']
|
|
147
|
+
answer.name = series.name
|
|
148
|
+
return answer
|
bulum/clim/tests/test_clim.py
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
import os
|
|
3
|
-
import bulum.io as bio
|
|
4
|
-
import bulum.clim as ocl
|
|
5
|
-
import bulum.utils as out
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Tests(unittest.TestCase):
|
|
10
|
-
|
|
11
|
-
@classmethod
|
|
12
|
-
def setUpClass(cls):
|
|
13
|
-
os.makedirs("./trash", exist_ok=True)
|
|
14
|
-
return super().setUpClass()
|
|
15
|
-
|
|
16
|
-
def test_load_data_into_df(self):
|
|
17
|
-
"""
|
|
18
|
-
The purpose of this is just to test that if I load 2 different files as
|
|
19
|
-
dataframes, and then simply put them together. I.e. does it join on the
|
|
20
|
-
dates? YES IT APPEARS TO LEFT-JOIN on the dates from the first file.
|
|
21
|
-
"""
|
|
22
|
-
df1 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
23
|
-
df2 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
24
|
-
df3 = pd.DataFrame()
|
|
25
|
-
df3["x"] = df1
|
|
26
|
-
df3["y"] = df2
|
|
27
|
-
# print(df3.head())
|
|
28
|
-
# print(df3.tail())
|
|
29
|
-
self.assertTrue(len(df3) == len(df1))
|
|
30
|
-
self.assertAlmostEqual(df3.x.values[-1], 136) # these values should line up despite different starting dates for each file
|
|
31
|
-
self.assertAlmostEqual(df3.y.values[-1], 62) # these values should line up despite different starting dates for each file
|
|
32
|
-
# And now doe the same again with files loaded in the opposite order
|
|
33
|
-
df1 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
34
|
-
df2 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
35
|
-
df3 = pd.DataFrame()
|
|
36
|
-
df3["x"] = df1
|
|
37
|
-
df3["y"] = df2
|
|
38
|
-
# print(df3.head())
|
|
39
|
-
# print(df3.tail())
|
|
40
|
-
self.assertTrue(len(df3) == len(df1))
|
|
41
|
-
self.assertAlmostEqual(df3.x.values[-1], 62) # these values should line up despite different starting dates for each file
|
|
42
|
-
self.assertAlmostEqual(df3.y.values[-1], 136) # these values should line up despite different starting dates for each file
|
|
43
|
-
|
|
44
|
-
def test_get_exc_transform(self):
|
|
45
|
-
"""
|
|
46
|
-
This gets transformation curves based on current & future climate datasets, and then checks that the transformation
|
|
47
|
-
curves have the same total number of points regardless of whether we use default seasons (monthly) or define 3 custom
|
|
48
|
-
seasons.
|
|
49
|
-
"""
|
|
50
|
-
current_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")
|
|
51
|
-
future_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")
|
|
52
|
-
answer1 = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"])
|
|
53
|
-
answer2 = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"], season_start_months=[3, 7, 9])
|
|
54
|
-
total_len_1 = sum([len(a[1]) for a in answer1.values()])
|
|
55
|
-
total_len_2 = sum([len(a[1]) for a in answer2.values()])
|
|
56
|
-
self.assertEqual(total_len_1, total_len_2)
|
|
57
|
-
self.assertTrue(total_len_1 > 0)
|
|
58
|
-
|
|
59
|
-
def test_apply_transformation_curves(self):
|
|
60
|
-
current_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")
|
|
61
|
-
future_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")
|
|
62
|
-
t = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"])
|
|
63
|
-
answer = pd.DataFrame()
|
|
64
|
-
answer["RexCurrent"] = current_climate["FRex_FR.qqm"]
|
|
65
|
-
answer["RexCurrent"] = future_climate["FRex_FR.qqm"]
|
|
66
|
-
answer["Transf"] = ocl.apply_transformation_curves(t, current_climate["FRex_FR.qqm"])
|
|
67
|
-
# print(answer["Current"].sum())
|
|
68
|
-
# print(answer["Future"].sum())
|
|
69
|
-
# print(answer["Transf"].sum())
|
|
70
|
-
self.assertAlmostEqual(answer["Transf"].sum(), 4845710.795475168) # Actually haven't checked that this is the correct answer but looks plausible.
|
|
71
|
-
answer.to_csv("./trash/transformed.csv")
|
|
1
|
+
import unittest
|
|
2
|
+
import os
|
|
3
|
+
import bulum.io as bio
|
|
4
|
+
import bulum.clim as ocl
|
|
5
|
+
import bulum.utils as out
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Tests(unittest.TestCase):
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def setUpClass(cls):
|
|
13
|
+
os.makedirs("./trash", exist_ok=True)
|
|
14
|
+
return super().setUpClass()
|
|
15
|
+
|
|
16
|
+
def test_load_data_into_df(self):
|
|
17
|
+
"""
|
|
18
|
+
The purpose of this is just to test that if I load 2 different files as
|
|
19
|
+
dataframes, and then simply put them together. I.e. does it join on the
|
|
20
|
+
dates? YES IT APPEARS TO LEFT-JOIN on the dates from the first file.
|
|
21
|
+
"""
|
|
22
|
+
df1 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
23
|
+
df2 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
24
|
+
df3 = pd.DataFrame()
|
|
25
|
+
df3["x"] = df1
|
|
26
|
+
df3["y"] = df2
|
|
27
|
+
# print(df3.head())
|
|
28
|
+
# print(df3.tail())
|
|
29
|
+
self.assertTrue(len(df3) == len(df1))
|
|
30
|
+
self.assertAlmostEqual(df3.x.values[-1], 136) # these values should line up despite different starting dates for each file
|
|
31
|
+
self.assertAlmostEqual(df3.y.values[-1], 62) # these values should line up despite different starting dates for each file
|
|
32
|
+
# And now doe the same again with files loaded in the opposite order
|
|
33
|
+
df1 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
34
|
+
df2 = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")["FRex_FR.qqm"]
|
|
35
|
+
df3 = pd.DataFrame()
|
|
36
|
+
df3["x"] = df1
|
|
37
|
+
df3["y"] = df2
|
|
38
|
+
# print(df3.head())
|
|
39
|
+
# print(df3.tail())
|
|
40
|
+
self.assertTrue(len(df3) == len(df1))
|
|
41
|
+
self.assertAlmostEqual(df3.x.values[-1], 62) # these values should line up despite different starting dates for each file
|
|
42
|
+
self.assertAlmostEqual(df3.y.values[-1], 136) # these values should line up despite different starting dates for each file
|
|
43
|
+
|
|
44
|
+
def test_get_exc_transform(self):
|
|
45
|
+
"""
|
|
46
|
+
This gets transformation curves based on current & future climate datasets, and then checks that the transformation
|
|
47
|
+
curves have the same total number of points regardless of whether we use default seasons (monthly) or define 3 custom
|
|
48
|
+
seasons.
|
|
49
|
+
"""
|
|
50
|
+
current_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")
|
|
51
|
+
future_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")
|
|
52
|
+
answer1 = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"])
|
|
53
|
+
answer2 = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"], season_start_months=[3, 7, 9])
|
|
54
|
+
total_len_1 = sum([len(a[1]) for a in answer1.values()])
|
|
55
|
+
total_len_2 = sum([len(a[1]) for a in answer2.values()])
|
|
56
|
+
self.assertEqual(total_len_1, total_len_2)
|
|
57
|
+
self.assertTrue(total_len_1 > 0)
|
|
58
|
+
|
|
59
|
+
def test_apply_transformation_curves(self):
|
|
60
|
+
current_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.withmissing.csv", date_format=r"%Y-%m-%d")
|
|
61
|
+
future_climate = bio.read_ts_csv("./src/bulum/clim/tests/Flow.out.RCP85_P2050_GCM8.csv", date_format=r"%Y-%m-%d")
|
|
62
|
+
t = ocl.derive_transformation_curves(current_climate["FRex_FR.qqm"], future_climate["FRex_FR.qqm"])
|
|
63
|
+
answer = pd.DataFrame()
|
|
64
|
+
answer["RexCurrent"] = current_climate["FRex_FR.qqm"]
|
|
65
|
+
answer["RexCurrent"] = future_climate["FRex_FR.qqm"]
|
|
66
|
+
answer["Transf"] = ocl.apply_transformation_curves(t, current_climate["FRex_FR.qqm"])
|
|
67
|
+
# print(answer["Current"].sum())
|
|
68
|
+
# print(answer["Future"].sum())
|
|
69
|
+
# print(answer["Transf"].sum())
|
|
70
|
+
self.assertAlmostEqual(answer["Transf"].sum(), 4845710.795475168) # Actually haven't checked that this is the correct answer but looks plausible.
|
|
71
|
+
answer.to_csv("./trash/transformed.csv")
|
bulum/demo.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
def hello_world():
|
|
2
|
-
print("Hello world!")
|
|
3
|
-
|
|
4
|
-
if __name__ == "__main__":
|
|
5
|
-
print(type(hello_world))
|
|
1
|
+
def hello_world():
|
|
2
|
+
print("Hello world!")
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
print(type(hello_world))
|
|
6
6
|
hello_world()
|
bulum/io/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from .csv_io import *
|
|
2
|
-
from .res_csv_io import *
|
|
3
|
-
from .idx_io import *
|
|
4
|
-
from .iqqm_out_reader import *
|
|
5
|
-
from .lqn_io import *
|
|
6
|
-
from .general_io import *
|
|
1
|
+
from .csv_io import *
|
|
2
|
+
from .res_csv_io import *
|
|
3
|
+
from .idx_io import *
|
|
4
|
+
from .iqqm_out_reader import *
|
|
5
|
+
from .lqn_io import *
|
|
6
|
+
from .general_io import *
|