Py.Cafe

onorena/

solara-water-quality-tracking

Tracking Water Quality Changes Post Puracé Volcanic Eruption

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import solara
import solara.lab
from datetime import datetime, timedelta

dftrial = pd.read_excel('https://github.com/onorena/purace/raw/main/purace.xlsx')

# Define variables and their ranges
variables = {
    'Resultado_Conductividad': (80, 90),
    'Resultado_Cloruros': (5, 10),
    'Resultado_Sulfatos': (10, 10.5),
    'Resultado_Floruros': (0.05, 0.15),
    'Resultado_Nitratos': (0.5, 3),
    'Resultado_Nitritos': (0.009, 0.015),
    'Resultado_Calcio': (5, 10),
    'Resultado_Magnesio': (2.5, 10),
    'Resultado_Hierro_Total': (0.09, 0.20),
    'Resultado_Molibdeno': (0.0049, 0.0051),
    'Resultado_Zinc': (0.05, 0.10),
    'Resultado_Fosfatos': (0.1, 0.3)
}

municipalities = [
    'CAJIBIO', 'EL TAMBO', 'INZA', 'LA SIERRA', 'LA VEGA', 'PATIA',
    'PIENDAMO', 'PURACE', 'ROSAS', 'SILVIA', 'SOTARA', 'SUCRE',
    'TIMBIO', 'TOTORO', 'ISNOS', 'LA ARGENTINA', 'LA PLATA', 'OPORAPA',
    'SALADOBLANCO', 'SAN AGUSTIN'
]

# Define the date range
start_date = datetime.strptime('08/05/2024', '%d/%m/%Y')
end_date = datetime.strptime('15/05/2024', '%d/%m/%Y')
date_range = pd.date_range(start_date, end_date)

# Function to generate uniform data within a specified range
def generate_uniform_data(low, high, size):
    return np.random.uniform(low, high, size)

# Generate synthetic data
synthetic_data = []

for municipality in municipalities:
    for date in date_range:
        record = {
            'Municipio PP': municipality,
            'Fecha de toma': date,
            'Año': date.year
        }
        for variable, (low, high) in variables.items():
            record[variable] = generate_uniform_data(low, high, 1)[0]
        
        synthetic_data.append(record)

# Convert to DataFrame
synthetic_df = pd.DataFrame(synthetic_data)

# Append to existing datarm dataframe using pd.concat
dftrial = pd.concat([dftrial, synthetic_df], ignore_index=True)

# Optimize plotting

# Create a new column for the period category
def categorize_date(date):
    if date.year == 2023:
        return '2023'
    elif date <= pd.Timestamp('2024-05-06'):
        return '01/01/2024 a 06/05/2024'
    elif (date > pd.Timestamp('2024-05-06')) and (date < pd.Timestamp('2024-05-15')):
        return '07/05/2024 a 14/05/2024'
    else:
        return '15/05/2024 a 21/05/2021'

dftrial['Período'] = dftrial['Fecha de toma'].apply(categorize_date)

# Define a custom color palette
custom_palette = {
    '2023': 'tab:blue',
    '01/01/2024 a 06/05/2024': 'tab:orange',
    '07/05/2024 a 14/05/2024': 'tab:green',
    '15/05/2024 a 21/05/2021' : 'tab:cyan'
}

# Create date interval dropdown
date_intervals = ['2023', '01/01/2024 a 06/05/2024', '07/05/2024 a 14/05/2024', '15/05/2024 a 21/05/2024']
date_interval_dropdown = solara.reactive(date_intervals[0])

dftrial['Período'] = dftrial['Fecha de toma'].apply(categorize_date)

coltrial = ['Resultado_Conductividad', 'Resultado_Cloruros', 'Resultado_Sulfatos',
           'Resultado_Floruros', 'Resultado_Nitratos', 'Resultado_Nitritos',
           'Resultado_Calcio', 'Resultado_Magnesio', 'Resultado_Hierro_Total',
           'Resultado_Molibdeno', 'Resultado_Zinc', 'Resultado_Fosfatos']

x_axis = solara.reactive('Resultado_Conductividad')

@solara.component
def Page():
    with solara.AppBarTitle():
        solara.Text("Parámetros fisicoquímicos del agua potable en los municipio en riesgo por erupción del volcán Puracé")
    with solara.lab.Tabs():
        with solara.lab.Tab("Introducción"):
            solara.Markdown(r''' <center> <h1>Seguimiento a la evolución de los parámetros fisicoquímicos reportados al SIVICAP en los municipios en riesgo por erupción del volcán Puracé</h1> </center> 
            <p style='text-align: justify;'>
            El 3 de mayo de 2024, el Servicio Geológico Colombiano (SGC) informó que el estado de alerta del volcán cambiaba a naranja, indicando así una mayor probabilidad de ocurrencia de una erupción. Los municipios de Cajibío, 
            El Tambo, Inza, La Sierra, La Vega, Patía, Piendamó, Puracé, Rosas, Silvia, Sotará, Sucre, Timbío, Totoró e Isnos en el Cauca y La Argentina, La Plata, Oporapa, Saladoblanco y San Agustín en el Huila, se encuentran en 
            la zona de riesgo por afectación debido a una probable erupción. La calidad del agua para consumo humano podría alterarse como consecuencia de la presencia de ceniza liberada por el volcán. Por esa razón, el Instituto 
            Nacional de Salud (INS) lleva a cabo un análisis del comportamiento de esos parámetros, de manera que se puedan identificar, anticipadamente, patrones o señales de alteración de la calidad del agua para consumo humano 
            que hagan necesario tomar medidas de prevención para proteger la salud de la población en la zona de riesgo. 
            </p>
            <p style='text-align: justify;'>
            Como parte de la vigilancia que las autoridades adelantan en su jurisdicción se reportaron al Sistema de Vigilancia de la Calidad del Agua Potable (SIVICAP), durante 2023, 365 registros de parámetros fisicoquímicos 
            evaluados en el agua para consumo humano, mientras que durante el período comprendido entre el 1 de enero de 2024 y el 7 de mayo de 2024 se hicieron 21 registros. En este análisis, se incluyeron los resultados de las 
            pruebas de conductividad, cloruros, sulfatos, fluoruros, nitratos, nitritos, calcio, magnesio, hierro total, molibdeno, zinc y fosfatos, que fueron objeto de seguimiento durante los períodos correspondientes al 2023, 
            entre el 1 de enero y el 7 de mayo de 2024, entre el 8 y el 15 de mayo de 2024, así como entre el 15 y 21 de mayo de 2024
            </p> 
            <p style='text-align: justify;'>
            A continuación, se puede consultar el comportamiento en forma de boxplots que muestran la distribución de los resultados para cada uno de los municipios y variables de interés descritas. En primer lugar, se puede 
            interactuar con cada variable, seleccionándola de un listado desplegable, con el fin de observar su comportamiento para cada uno de los municipios en riesgo; mientras que en la segunda figura se  muestra un panorama 
            general del comportamiento para todos los parámetros.
            </p>
            <center> <h1>Análisis del comportamiento de los parámetros reportado al SIVICAP</h1> </center>
            <p style='text-align: justify;'>
            Con base en el comportamiento observado en la figura, es claro que no se cuenta con datos suficientes, durante el período comprendido entre el 1 de enero de 2024 y el 7 de mayo de 2024, para poder comparar con el 
            comportamiento de referencia de los parámetros, que es el registrado durante 2023. En el caso de los nitratos, nitritos y magnesio se cuenta con datos para casi toso los municipios, pero solamente para 2023. Solo se 
            cuenta con datos del período que va desde el 1 de enero de 2024 al 7 de mayo de 2024 para cloruros en La Plata y San Agustín, en el Huila. Se requiere efectuar las mediciones correspondientes en todos los municipios 
            afectados para poder hacer una comparación efectiva e identificar así alguna anomalía en el comportamiento que sugiera una posible afectación a la calidad de la fuente de agua potable y permita tomar medidas de 
            protección temprana a la población de esos municipios. Los datos del período entre el 8 y el 15 de mayo de 2024 fueron generados artificialmente con el fin de ejemplificar el comportamiento que se podría presentar 
            en caso de no ocurrir una afectación debida a la ceniza del volcán y serán actualizados en la medida en que se cuente con datos reales.
            </p>
            ''')
        with solara.lab.Tab("Parámetro físicoquimico"):
            fig = px.box(dftrial, x_axis.value, 'Municipio PP', color='Período', 
                         category_orders={'Período': ['2023', '01/01/2024 a 07/05/2024', '08/05/2024 a 15/05/2024']},
                         labels={'Value': x_axis.value, 'Municipio PP': 'Municipio', 'Período': 'Período'},
                         title=f'Parámetros IRCA en los municipios en riesgo por erupción del volcán Puracé')
            fig.update_layout(boxmode='group', height=800, width=1200, title_x=0.5, legend_title_text='Período')
            solara.FigurePlotly(fig)
            solara.Select(label='X_axis', value=x_axis, values=coltrial)
        with solara.lab.Tab("Todos los parámetros"):
            solara.Select(label='Seleccionar Período', value=date_interval_dropdown, values=date_intervals)
            # Melt the dataframe to long format for Plotly
            df_long = dftrial.melt(id_vars=['Municipio PP', 'Fecha de toma', 'Período'], 
                      value_vars=variables,
                      var_name='Variable', value_name='Value')

            filtered_data = df_long[(df_long['Período'] == date_interval_dropdown.value)]
            fig = px.box(filtered_data, 
                         x='Value', y='Municipio PP', color='Período',
                         facet_col='Variable', facet_col_wrap=4,
                         category_orders={'Período': date_intervals},
                         labels={'Value': 'Valor', 'Variable': 'Parámetro', 'Municipio PP': 'Municipio'},
                         title=f'Parámetros IRCA en los municipios en riesgo por erupción del volcán Puracé')
            fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
            fig.update_yaxes(title_text='', dtick=1)
            fig.update_xaxes(matches=None, title_text='')
            fig.update_layout(
                boxmode='group',
                height=1000,
                width=1100,
                title_x=0.5,
                showlegend=False
            )
            solara.FigurePlotly(fig)