population-trend 3.0.0__py3-none-any.whl → 3.1.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.
@@ -1,6 +1,8 @@
1
1
  """A template Python module"""
2
2
 
3
- __version__ = "3.0.0"
3
+ __version__ = "3.1.0"
4
4
  from .cli import * # noqa
5
5
  from .filter_data import * # noqa
6
6
  from .population_growth_model import * # noqa
7
+ from .calculate_growth_rates import * # noqa
8
+ from bootstrapping_tools import * # noqa
@@ -0,0 +1,206 @@
1
+ from bootstrapping_tools import (
2
+ lambda_calculator,
3
+ power_law,
4
+ bootstrap_from_time_series,
5
+ get_bootstrap_deltas,
6
+ generate_latex_interval_string,
7
+ calculate_p_values,
8
+ )
9
+ from matplotlib.ticker import MaxNLocator
10
+
11
+ import json
12
+ import matplotlib.pyplot as plt
13
+ import numpy as np
14
+
15
+
16
+ def do_nothing():
17
+ pass
18
+
19
+
20
+ def fit_population_model(seasons_series, data_series):
21
+ parameters = lambda_calculator(seasons_series, data_series)
22
+ model = power_law(
23
+ seasons_series - seasons_series.iloc[0],
24
+ parameters[0],
25
+ parameters[1],
26
+ )
27
+ return model
28
+
29
+
30
+ def calculate_porcentual_diff(x, y):
31
+ return 100 * (x - y) / y
32
+
33
+
34
+ def generate_number_and_season_string(number, season):
35
+ return "{} ({})".format(
36
+ number,
37
+ season,
38
+ )
39
+
40
+
41
+ def calculate_seasons_intervals(seasons):
42
+ years = []
43
+ first_index = 0
44
+ for index in np.where(np.diff(seasons) != 1)[0]:
45
+ if seasons[first_index] == seasons[index]:
46
+ years.append(f"{seasons[index]}")
47
+ else:
48
+ years.append(f"{seasons[first_index]}-{seasons[index]}")
49
+ first_index = index + 1
50
+ years.append(f"{seasons[first_index]}-{seasons[-1]}")
51
+ return years
52
+
53
+
54
+ def calculate_interest_numbers(cantidad_nidos, model):
55
+ first_number = generate_number_and_season_string(
56
+ cantidad_nidos["Maxima_cantidad_nidos"].iloc[0],
57
+ cantidad_nidos["Temporada"].iloc[0],
58
+ )
59
+ first_number_calculated = generate_number_and_season_string(
60
+ model.iloc[0], cantidad_nidos["Temporada"].iloc[0]
61
+ )
62
+ last_number = "{{{:,.0f}}} ({})".format(
63
+ cantidad_nidos["Maxima_cantidad_nidos"].iloc[-1],
64
+ int(cantidad_nidos["Temporada"].iloc[-1]),
65
+ )
66
+ last_number_calculated = generate_number_and_season_string(
67
+ model.iloc[-1],
68
+ cantidad_nidos["Temporada"].iloc[-1],
69
+ )
70
+ return first_number, first_number_calculated, last_number, last_number_calculated
71
+
72
+
73
+ def calculate_percent_diff_in_seasons(cantidad_nidos, model):
74
+ if cantidad_nidos["Maxima_cantidad_nidos"].iloc[0] == 0:
75
+ porcentaje_cambio = calculate_porcentual_diff(model.iloc[-1], model.iloc[0])
76
+ else:
77
+ porcentaje_cambio = calculate_porcentual_diff(
78
+ model.iloc[-1], cantidad_nidos["Maxima_cantidad_nidos"].iloc[0]
79
+ )
80
+ return porcentaje_cambio
81
+
82
+
83
+ class Bootstrap_from_time_series_parameterizer:
84
+ def __init__(self, blocks_length=3, N=2000):
85
+ self.parameters = dict(
86
+ dataframe=None,
87
+ column_name="Maxima_cantidad_nidos",
88
+ N=N,
89
+ return_distribution=True,
90
+ blocks_length=blocks_length,
91
+ )
92
+
93
+ def set_data(self, data):
94
+ self.parameters["dataframe"] = data
95
+
96
+
97
+ Bootstrap = dict(
98
+ default=Bootstrap_from_time_series_parameterizer(),
99
+ testing=Bootstrap_from_time_series_parameterizer(blocks_length=2, N=100),
100
+ )
101
+
102
+
103
+ class Bootstrap_from_time_series:
104
+ def __init__(self, bootstrap_parametrizer):
105
+ self.parameters = bootstrap_parametrizer.parameters
106
+ self.lambdas_distribution, self.intervals = self._calculate_distribution_and_interval()
107
+ self.season_series = self.parameters["dataframe"]["Temporada"]
108
+ self.data_series = self.parameters["dataframe"][self.parameters["column_name"]]
109
+ self.lambdas = [interval[0] for interval in self.intervals]
110
+
111
+ def get_distribution(self):
112
+ return self.lambdas_distribution
113
+
114
+ def _calculate_distribution_and_interval(self):
115
+ lambdas_distribution, intervals = bootstrap_from_time_series(**self.parameters)
116
+ return lambdas_distribution, intervals
117
+
118
+ def get_inferior_central_and_superior_limit(self):
119
+ inferior_limit, central, superior_limit = get_bootstrap_deltas(
120
+ self.lambdas, **{"decimals": 2}
121
+ )
122
+ return inferior_limit, central, superior_limit
123
+
124
+ def get_lambda_interval_latex_string(self):
125
+ lambda_latex_string = generate_latex_interval_string(self.lambdas, **{"decimals": 2})
126
+ return lambda_latex_string
127
+
128
+ def generate_season_interval(self):
129
+ return "({}-{})".format(
130
+ self.season_series.min(axis=0),
131
+ self.season_series.max(axis=0),
132
+ )
133
+
134
+ def get_monitored_seasons(self):
135
+ monitored_seasons = np.sort(self.season_series.astype(int).unique())
136
+ if len(monitored_seasons) == 1:
137
+ return f"{monitored_seasons[0]}"
138
+ else:
139
+ seasons_intervals = calculate_seasons_intervals(monitored_seasons)
140
+ return ",".join(seasons_intervals)
141
+
142
+ def xxfit_population_model(self):
143
+ parameters = lambda_calculator(self.season_series, self.data_series)
144
+ model = power_law(
145
+ self.season_series - self.season_series.iloc[0],
146
+ parameters[0],
147
+ parameters[1],
148
+ )
149
+ return model
150
+
151
+ def save_intervals(self, output_path):
152
+ json_dict = {
153
+ "intervals": list(self.intervals),
154
+ "lambda_latex_interval": self.get_lambda_interval_latex_string(),
155
+ }
156
+ with open(output_path, "w") as file:
157
+ json.dump(json_dict, file)
158
+
159
+
160
+ def calculate_growth_rates_table(bootstrap: Bootstrap_from_time_series_parameterizer):
161
+ bootstraper = Bootstrap_from_time_series(bootstrap)
162
+ df = bootstrap.parameters["dataframe"]
163
+ model = bootstraper.xxfit_population_model()
164
+ inferior_limit, central, superior_limit = bootstraper.get_inferior_central_and_superior_limit()
165
+ lambda_latex_string = bootstraper.get_lambda_interval_latex_string()
166
+ bootstrap_distribution = bootstraper.get_distribution()
167
+ lambdas_distribution = [interval[0] for interval in bootstrap_distribution]
168
+ p_value_mayor, p_value_menor = calculate_p_values(lambdas_distribution)
169
+ intervalo = bootstraper.generate_season_interval()
170
+ monitored_seasons = bootstraper.get_monitored_seasons()
171
+ porcentaje_cambio = calculate_percent_diff_in_seasons(df, model)
172
+ (
173
+ first_number,
174
+ _,
175
+ last_number,
176
+ last_number_calculated,
177
+ ) = calculate_interest_numbers(df, model)
178
+ return [
179
+ intervalo,
180
+ first_number,
181
+ last_number,
182
+ last_number_calculated,
183
+ lambda_latex_string,
184
+ df["Latitud"].iloc[0],
185
+ central,
186
+ f"-{inferior_limit}",
187
+ f"+{superior_limit}",
188
+ f"{{{int(porcentaje_cambio):,}}}",
189
+ p_value_mayor,
190
+ p_value_menor,
191
+ monitored_seasons,
192
+ ]
193
+
194
+
195
+ def set_axis_plot_config(ax):
196
+ ax.xaxis.set_major_locator(MaxNLocator(integer=True))
197
+ ax.spines["right"].set_visible(False)
198
+ ax.spines["top"].set_visible(False)
199
+ plt.yticks(rotation=90, size=20)
200
+ locs_x, labels_x = plt.xticks()
201
+ locs_y, labels_y = plt.yticks()
202
+ plt.xticks(locs_x[1:], size=20)
203
+ plt.xlim(locs_x[0], locs_x[-1])
204
+ plt.ylim(0, locs_y[-1])
205
+ plt.xlabel("Año", size=20, labelpad=10)
206
+ plt.ylabel("Cantidad de parejas reproductoras", size=20)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: population_trend
3
- Version: 3.0.0
3
+ Version: 3.1.0
4
4
  Summary: A template Python module
5
5
  Home-page: https://github.com/IslasGECI/population_trend
6
6
  Author: Ciencia de Datos • GECI
@@ -8,7 +8,7 @@ Author-email: ciencia.datos@islas.org.mx
8
8
  Requires-Python: >=3.9
9
9
  Description-Content-Type: text/markdown
10
10
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
- Requires-Dist: bootstrapping-tools==1.1.1
11
+ Requires-Dist: bootstrapping-tools==2.0.0
12
12
  Requires-Dist: geci-plots
13
13
  Requires-Dist: typer
14
14
 
@@ -0,0 +1,9 @@
1
+ population_trend/__init__.py,sha256=mr5F6CLyrEM5ITNVsP0YgFZff-b2E7GRbunCPuELGiA,251
2
+ population_trend/calculate_growth_rates.py,sha256=SQobh1f2xKFKu7MO7To7avxU2Cym1ebu2tKfpbLTpbo,6901
3
+ population_trend/cli.py,sha256=CkzXmfjekIV4RplUyJo1Af-GI22zovB4u5alt8BNYIo,1894
4
+ population_trend/filter_data.py,sha256=D0Y1vztcbbo98af9q7wRhlHfH__bNFI8tnVOdJY6hu0,403
5
+ population_trend/population_growth_model.py,sha256=fSUKg8UH-pdN1tNYskGcMmmiqqAy9Ciz0E4X-IeP9WM,4361
6
+ population_trend-3.1.0.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
7
+ population_trend-3.1.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
8
+ population_trend-3.1.0.dist-info/METADATA,sha256=e5YM8iZ6yCz3b9uRIrFOa2AeXa6uIPQ4bW77D0NAPno,1504
9
+ population_trend-3.1.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- population_trend/__init__.py,sha256=FT9rFbM8pRxixs5itfeXniGnSsbiZtuZ7bu_Ar8LEpI,163
2
- population_trend/cli.py,sha256=CkzXmfjekIV4RplUyJo1Af-GI22zovB4u5alt8BNYIo,1894
3
- population_trend/filter_data.py,sha256=D0Y1vztcbbo98af9q7wRhlHfH__bNFI8tnVOdJY6hu0,403
4
- population_trend/population_growth_model.py,sha256=fSUKg8UH-pdN1tNYskGcMmmiqqAy9Ciz0E4X-IeP9WM,4361
5
- population_trend-3.0.0.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
6
- population_trend-3.0.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
7
- population_trend-3.0.0.dist-info/METADATA,sha256=9DcQkh2bjrLU5e03CBPSBo970FgoSn9Na26OATSlKYk,1504
8
- population_trend-3.0.0.dist-info/RECORD,,