From 54fe45229ab87bf2c11d485ed856c57268ce0cbb Mon Sep 17 00:00:00 2001 From: Milan anand raj <84122339+manandraj20@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:06:15 +0530 Subject: [PATCH 1/5] readme updated for contact matrix --- README.rst | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/README.rst b/README.rst index a87601f..4836bd3 100644 --- a/README.rst +++ b/README.rst @@ -110,43 +110,32 @@ Contact Pattern Matrix Estimation Description -Estimates the contact matrix by analyzing transactional data for different age groups across various merchandise categories. +Estimates the contact matrix by analyzing transactional activities from different age groups. Assumptions -#. Proportion of Age Groups : Assumed participation in merchandise categories follows an age group proportion map. - - * References: `research paper `_ - - * This age group distribution for various merchandise categories can be made more accurate by referring to the data from ``_. - - .. code-block:: python - - age_group_proportion_map = { - 'Airlines': [25, 40, 15], - 'Bars/Discotheques': [50, 35, 15], - 'Hospitals' : [15, 20, 30], - 'Drug Stores/Pharmacies' : [15, 20, 30 ], - 'Computer Network/Information Services': [40, 35, 20], - 'General Retail Stores': [20, 35, 25], - 'Grocery Stores/Supermarkets': [20, 35, 25], - 'Utilities: Electric, Gas, Water': [15, 30, 30], - 'Hotels/Motels': [20, 25, 30], - 'Restaurants': [25, 25, 25] - } - +#. There is a mixing factor for each age group, used to scale its population size when calculating the total number of contacts it makes with people from other age groups. #. The persons, involved in the transactions, only make contact with individuals also involved in the transactions from the data. #. Every transaction under ``nb_transactions`` is done by a unique individual and this is true across different merchant IDs as well. Thus, total number of unique individuals is equal to the total number of transactions across all the merchant IDs. -#. The contacts among various age groups is exclusive ie every individual, from any given age group, make contact with distinct individuals from other age groups.. In the video, they also took this assumptions. +#. The contacts among various age groups is exclusive i.e., every individual, from any given age group, make contact with distinct individuals from other age groups.. In the video, they also took this assumptions. Algorithm +Computing the contact patterns across the whole country. + +#. First, calculate the private counts of the total number of transactions for each city in the dataset. +#. Using these city-level transaction counts, calculate the private counts of the total number of transactions for each age group. + For this, the age-group-wise merchandise consumption distribution, referred to as D, is required. + + *We use a machine learning approach to estimate the age-group-wise merchandise consumption distribution, D, as described below:* + *The process begins with an initial estimate of D. Using this estimate, a contact matrix is calculated through the algorithm being described.* + *Next, a loss function is chosen to quantify the difference between the ground truth contact matrix and the estimated contact matrix.* + *This loss function is iteratively minimized by updating the values in D.* + *However, a limitation of this approach is the need to learn D separately for each country, assuming the ground truth contact matrix is available and aligns with the timeframe of the transaction data.* + +#. Calculate the count of contacts between each pair of age groups for each city, and then average these counts across all cities to derive the contact matrix. +#. Finally, to introduce symmetry in the contact matrix and account for different mixing factors across age groups, multiply the contact matrix by the mixing factor vector and then average it with its transpose. + *The mixing factor is estimated using the same approach as for the age-group-wise merchandise consumption distribution, D.* -#. Filter Week : Select the specific week for analysis. -#. Filter City : Choose the city of interest (e.g., ``Bogotá``). -#. Filter OFFLINE Transactions : Only consider offline transactions. -#. Group by Merchant Category : Sum the number of transactions (``nb_transactions``). -#. Private Count of Postal Codes: Obtain the private count of unique postal codes for each merchant category and week. -#. Compute Private Mean Transactions : Calculate the average number of transactions per zip code using the age group proportion map. Sensitivity and Epsilon Analysis From a1ed3ba41a52fb3f87350538f1ba8edf0a20c930 Mon Sep 17 00:00:00 2001 From: Milan anand raj <84122339+manandraj20@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:16:04 +0530 Subject: [PATCH 2/5] readme updated for contact matrix --- README.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 4836bd3..24e9cbb 100644 --- a/README.rst +++ b/README.rst @@ -120,7 +120,7 @@ Assumptions #. The contacts among various age groups is exclusive i.e., every individual, from any given age group, make contact with distinct individuals from other age groups.. In the video, they also took this assumptions. Algorithm -Computing the contact patterns across the whole country. +*Computing the contact patterns across the whole country.* #. First, calculate the private counts of the total number of transactions for each city in the dataset. #. Using these city-level transaction counts, calculate the private counts of the total number of transactions for each age group. @@ -145,6 +145,11 @@ Sensitivity and Epsilon Analysis * Epsilon Budget: The epsilon spent per timestep is ∈ . * Scale Calculation: ``Scale = (3 * no_of_time_steps * uppper_bound) / ∈``. +Methods of Evaluating Contact Matrix + +* Displaying a heatmap of the absolute differences between the ground truth contact matrix and the estimated contact matrix provides a clear visual representation of discrepancies. This helps identify which age group segments show the greatest deviations and in which direction. These insights are valuable for refining the model around specific age groups with larger differences, thereby improving accuracy. Additionally, this method can be extended to track shifts in the contact matrix over time, revealing cross-age group interactions that have increased, decreased, or remained stable. Such trends are instrumental in informing targeted policies. +* Calculating the aggregate sum of the absolute differences between corresponding elements of the ground truth and estimated contact matrices quantifies the overall discrepancy. This metric offers an intuitive understanding of the total divergence between the two matrices in absolute numerical terms, serving as a straightforward and effective measure for model evaluation. + Challenges * Ensuring the contact matrix accurately reflects transaction participation from different age groups. From 700c1f52e5bc7b4ec07a1dc771c94558eda58316 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 7 Dec 2024 14:05:09 +0530 Subject: [PATCH 3/5] vizualization of tools --- dash_app.py | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 dash_app.py diff --git a/dash_app.py b/dash_app.py new file mode 100644 index 0000000..5c746de --- /dev/null +++ b/dash_app.py @@ -0,0 +1,271 @@ +import dash +from dash import dcc, html +from dash.dependencies import Input, Output +from datetime import datetime +import pandas as pd +import numpy as np +import sys +import os +import random +from src.DP_epidemiology.utilities import * +from src.DP_epidemiology.hotspot_analyzer import hotspot_analyzer +from src.DP_epidemiology.mobility_analyzer import mobility_analyzer +from src.DP_epidemiology.pandemic_adherence_analyzer import pandemic_adherence_analyzer +from src.DP_epidemiology.contact_matrix import get_age_group_count_map, get_contact_matrix_country + +import plotly.express as px +import plotly.graph_objects as go +import opendp.prelude as dp + +dp.enable_features("contrib", "floating-point", "honest-but-curious") + + +def create_dash_app(df: pd.DataFrame, df_google_mobility_data: pd.DataFrame = None): + cities = { + "Medellin": (6.2476, -75.5658), + "Bogota": (4.7110, -74.0721), + "Brasilia": (-15.7975, -47.8919), + "Santiago": (-33.4489, -70.6693) + } + category_list = ['grocery_and_pharmacy', 'transit_stations', 'retail_and_recreation', "other"] + entry_types = ["luxury", "essential", "other"] + age_groups = ['0-4', '5-9', '10-14', '15-19', '20-24', '25-29', '30-34', '35-39', '40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '70-74', '75+'] + scaling_factor = pd.read_csv('fractions_offline.csv')['0'].values + P = np.array([4136344, 4100716, 3991988, 3934088, 4090149, 4141051, 3895117, 3439202, + 3075077, 3025100, 3031855, 2683253, 2187561, 1612948, 1088448, 1394217]) + consumption_distribution_raw = pd.read_csv(r"consumption_distribution.csv") + categories = consumption_distribution_raw['categories'].values + consumption_distribution = {} + for category in categories: + consumption_distribution[category] = consumption_distribution_raw[consumption_distribution_raw['categories'] == category].values[0][:-1] + + app = dash.Dash(__name__) + + app.layout = html.Div([ + dcc.Tabs([ + dcc.Tab(label='Hotspot Analysis', children=[ + dcc.DatePickerSingle(id='hotspot-start-date-picker', date='2019-01-01'), + dcc.DatePickerSingle(id='hotspot-end-date-picker', date='2019-12-31'), + dcc.Slider(id='hotspot-epsilon-slider', min=0, max=10, step=0.1, value=1, marks={i: str(i) for i in range(11)}), + dcc.Dropdown(id='hotspot-city-dropdown', options=[{'label': city, 'value': city} for city in cities.keys()], value='Medellin'), + dcc.Graph(id='hotspot-geo-plot') + ]), + dcc.Tab(label='Mobility Analysis', children=[ + dcc.DatePickerSingle(id='mobility-start-date-picker', date='2019-01-01'), + dcc.DatePickerSingle(id='mobility-end-date-picker', date='2019-12-31'), + dcc.Slider(id='mobility-epsilon-slider', min=0, max=10, step=0.1, value=1, marks={i: str(i) for i in range(11)}), + dcc.Dropdown(id='mobility-city-dropdown', options=[{'label': city, 'value': city} for city in cities.keys()], value='Medellin'), + dcc.Dropdown(id='mobility-category-list-dropdown', options=[{'label': category, 'value': category} for category in category_list], value='transit_stations'), + dcc.Graph(id='mobility-graph') + ]), + dcc.Tab(label='Pandemic Adherence Analysis', children=[ + dcc.DatePickerSingle(id='adherence-start-date-picker', date='2019-01-01'), + dcc.DatePickerSingle(id='adherence-end-date-picker', date='2019-12-31'), + dcc.Slider(id='adherence-epsilon-slider', min=0, max=10, step=0.1, value=1, marks={i: str(i) for i in range(11)}), + dcc.Dropdown(id='adherence-city-dropdown', options=[{'label': city, 'value': city} for city in cities.keys()], value='Medellin'), + dcc.Dropdown(id='adherence-entry-type-dropdown', options=[{'label': entry_type, 'value': entry_type} for entry_type in entry_types], value='luxury'), + dcc.Graph(id='adherence-graph') + ]), + dcc.Tab(label='Contact Matrix Analysis', children=[ + dcc.DatePickerSingle(id='matrix-start-date-picker', date='2019-01-01'), + dcc.DatePickerSingle(id='matrix-end-date-picker', date='2019-12-31'), + dcc.Slider(id='matrix-epsilon-slider', min=0, max=10, step=0.1, value=1, marks={i: str(i) for i in range(11)}), + dcc.Dropdown(id='matrix-city-dropdown', options=[{'label': city, 'value': city} for city in cities.keys()], value='Medellin'), + dcc.Graph(id='matrix-heatmap'), + html.Div(id='matrix-output', style={'whiteSpace': 'pre-line'}) + ]), + dcc.Tab(label='Mobility Validation', children=[ + dcc.DatePickerSingle(id='validation-start-date-picker', date='2020-02-15'), + dcc.DatePickerSingle(id='validation-end-date-picker', date='2020-12-31'), + dcc.Slider(id='validation-epsilon-slider', min=0, max=10, step=0.1, value=1, marks={i: str(i) for i in range(11)}), + dcc.Dropdown(id='validation-city-dropdown', options=[{'label': city, 'value': city} for city in cities.keys()], value='Medellin'), + dcc.Dropdown(id='validation-category-list-dropdown', options=[{'label': category, 'value': category} for category in category_list], value='transit_stations'), + dcc.Graph(id='validation-mobility-graph') + ]) + ]) + ]) + + @app.callback( + Output('hotspot-geo-plot', 'figure'), + [Input('hotspot-start-date-picker', 'date'), + Input('hotspot-end-date-picker', 'date'), + Input('hotspot-epsilon-slider', 'value'), + Input('hotspot-city-dropdown', 'value')] + ) + def update_hotspot_graph(start_date, end_date, epsilon, city): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') + output = hotspot_analyzer(df, start_date, end_date, city, epsilon) + filtered_df = get_coordinates(output) + fig = px.scatter_geo( + filtered_df, + lat='Latitude', + lon='Longitude', + color='nb_transactions', + size='nb_transactions', + hover_name='merch_postal_code', + hover_data={'merch_postal_code': True, 'nb_transactions': True, 'Latitude': False, 'Longitude': False}, + projection='mercator', + title=f"Transaction Locations in {city} from {start_date.date()} to {end_date.date()} with epsilon={epsilon}", + color_continuous_scale=px.colors.sequential.Plasma + ) + fig.update_geos(center=dict(lat=cities[city][0], lon=cities[city][1]), projection_scale=2.5) + return fig + + @app.callback( + Output('mobility-graph', 'figure'), + [Input('mobility-start-date-picker', 'date'), + Input('mobility-end-date-picker', 'date'), + Input('mobility-city-dropdown', 'value'), + Input('mobility-category-list-dropdown', 'value'), + Input('mobility-epsilon-slider', 'value')] + ) + def update_mobility_graph(start_date, end_date, city_filter, category, epsilon): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') + filtered_df = mobility_analyzer(df, start_date, end_date, city_filter, category, epsilon) + fig = px.line( + filtered_df, + x='date', + y='nb_transactions', + title=f"Mobility Analysis for {city_filter} and category {category} from {start_date.date()} to {end_date.date()} with epsilon={epsilon}", + labels={'nb_transactions': 'Number of Transactions', 'date': 'Date'} + ) + if city_filter == "Bogota": + events = [ + ("Isolation Start Drill", "2020-03-20"), + ("National Quarantine", "2020-03-26"), + ("Gender Restriction", "2020-04-16"), + ("Day Without VAT (IVA)", "2020-06-19"), + ("Lockdown 1", "2020-07-15"), + ("Lockdown 2", "2020-07-30"), + ("Lockdown 3", "2020-08-13"), + ("Lockdown 4", "2020-08-20"), + ("End of National Quarantine", "2020-09-04"), + ("Day Without VAT", "2020-11-19"), + ("Candle Day", "2020-12-07"), + ("Start of Novenas", "2020-12-16"), + ("Lockdown 1 (2021)", "2021-01-05"), + ("Lockdown 2 (2021)", "2021-01-12"), + ("Lockdown 3 (2021)", "2021-01-18"), + ("Lockdown 4 (2021)", "2021-01-28"), + ("Holy Week", "2021-03-28"), + ("Model 4x3", "2021-04-06"), + ("Model 4x3 (Extension)", "2021-04-06"), + ("Vaccination Stage 1", "2021-02-18"), + ("Vaccination Stage 2", "2021-03-08"), + ("Vaccination Stage 3", "2021-05-22"), + ("Vaccination Stage 4", "2021-06-17"), + ("Vaccination Stage 5", "2021-07-17"), + ("Riots and Social Unrest", "2021-05-01") + ] + for event, date in events: + fig.add_shape(type="line", x0=date, y0=0, x1=date, y1=1, xref='x', yref='paper', line=dict(color="Red", width=2, dash="dash")) + fig.add_annotation(x=date, y=1, xref='x', yref='paper', text=event, showarrow=True, arrowhead=1, ax=-10, ay=-40, font=dict(color="Red")) + return fig + + @app.callback( + Output('adherence-graph', 'figure'), + [Input('adherence-start-date-picker', 'date'), + Input('adherence-end-date-picker', 'date'), + Input('adherence-city-dropdown', 'value'), + Input('adherence-entry-type-dropdown', 'value'), + Input('adherence-epsilon-slider', 'value')] + ) + def update_adherence_graph(start_date, end_date, city_filter, essential_or_luxury, epsilon): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') + filtered_df = pandemic_adherence_analyzer(df, start_date, end_date, city_filter, essential_or_luxury, epsilon) + fig = px.line( + filtered_df, + x='date', + y='nb_transactions', + title=f"Pandemic adherence Analysis for {city_filter} from {start_date.date()} to {end_date.date()} with epsilon={epsilon}", + labels={'nb_transactions': 'Number of Transactions', 'date': 'Date'} + ) + if city_filter == "Bogota": + events = [ + ("Isolation Start Drill", "2020-03-20"), + ("National Quarantine", "2020-03-26"), + ("Gender Restriction", "2020-04-16"), + ("Day Without VAT (IVA)", "2020-06-19"), + ("Lockdown 1", "2020-07-15"), + ("Lockdown 2", "2020-07-30"), + ("Lockdown 3", "2020-08-13"), + ("Lockdown 4", "2020-08-20"), + ("End of National Quarantine", "2020-09-04"), + ("Day Without VAT", "2020-11-19"), + ("Candle Day", "2020-12-07"), + ("Start of Novenas", "2020-12-16"), + ("Lockdown 1 (2021)", "2021-01-05"), + ("Lockdown 2 (2021)", "2021-01-12"), + ("Lockdown 3 (2021)", "2021-01-18"), + ("Lockdown 4 (2021)", "2021-01-28"), + ("Holy Week", "2021-03-28"), + ("Model 4x3", "2021-04-06"), + ("Model 4x3 (Extension)", "2021-04-06"), + ("Vaccination Stage 1", "2021-02-18"), + ("Vaccination Stage 2", "2021-03-08"), + ("Vaccination Stage 3", "2021-05-22"), + ("Vaccination Stage 4", "2021-06-17"), + ("Vaccination Stage 5", "2021-07-17"), + ("Riots and Social Unrest", "2021-05-01") + ] + for event, date in events: + fig.add_shape(type="line", x0=date, y0=0, x1=date, y1=1, xref='x', yref='paper', line=dict(color="Red", width=2, dash="dash")) + fig.add_annotation(x=date, y=1, xref='x', yref='paper', text=event, showarrow=True, arrowhead=1, ax=-10, ay=-40, font=dict(color="Red")) + return fig + + @app.callback( + [Output('matrix-heatmap', 'figure'), + Output('matrix-output', 'children')], + [Input('matrix-start-date-picker', 'date'), + Input('matrix-end-date-picker', 'date'), + Input('matrix-city-dropdown', 'value'), + Input('matrix-epsilon-slider', 'value')] + ) + def update_contact_matrix(start_date, end_date, city, epsilon): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') + counts_per_city = [] + for city in cities: + counts = get_age_group_count_map(df, age_groups, consumption_distribution, start_date, end_date, city) + counts_per_city.append(list(counts.values())) + contact_matrix = get_contact_matrix_country(counts_per_city, P, scaling_factor) + fig = px.imshow(contact_matrix, labels=dict(x="Age Group", y="Age Group", color="Contact Rate"), x=age_groups, y=age_groups, color_continuous_scale='viridis') + matrix_output = f"Contact Matrix:\n{np.array_str(contact_matrix, precision=2, suppress_small=True)}" + return fig, matrix_output + + @app.callback( + Output('validation-mobility-graph', 'figure'), + [Input('validation-start-date-picker', 'date'), + Input('validation-end-date-picker', 'date'), + Input('validation-city-dropdown', 'value'), + Input('validation-category-list-dropdown', 'value'), + Input('validation-epsilon-slider', 'value')] + ) + def update_validation_graph(start_date, end_date, city_filter, category, epsilon): + start_date = datetime.strptime(start_date, '%Y-%m-%d') + end_date = datetime.strptime(end_date, '%Y-%m-%d') + filtered_df_transactional = mobility_analyzer(df, start_date, end_date, city_filter, category, epsilon) + offset = filtered_df_transactional["date"].iloc[0] + filtered_df_google = preprocess_google_mobility(df_google_mobility_data, start_date, end_date, city_filter, category, offset) + fig = go.Figure() + fig.add_trace(go.Scatter(x=filtered_df_transactional['date'], y=filtered_df_transactional['nb_transactions'], mode='lines', name='Transactional Mobility', yaxis='y1')) + fig.add_trace(go.Scatter(x=filtered_df_google['date'], y=filtered_df_google[category], mode='lines', name='Google Mobility', yaxis='y2')) + fig.update_layout( + title=f"Mobility Analysis for {city_filter} and category {category} from {start_date.date()} to {end_date.date()} with epsilon={epsilon}", + xaxis_title='Date', + yaxis=dict(title='Transactional Mobility', titlefont=dict(color='blue'), tickfont=dict(color='blue')), + yaxis2=dict(title='Google Mobility', titlefont=dict(color='red'), tickfont=dict(color='red'), overlaying='y', side='right'), + legend_title='Data Source' + ) + return fig + + return app + +# Example usage: +df = pd.read_csv(r'D:\workspace\pet_local\technical_phase_data.csv') +df_google_mobility_data = pd.read_csv('D:\workspace\PETs_challenge_data.csv') +app = create_dash_app(df, df_google_mobility_data) +app.run_server(debug=True) \ No newline at end of file From 413ff0e39d58853d0402ecf8a6119278cb4cdb21 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 7 Dec 2024 22:47:23 +0530 Subject: [PATCH 4/5] removed cache --- .../__pycache__/__init__.cpython-310.pyc | Bin 203 -> 0 bytes .../__pycache__/contact_matrix.cpython-310.pyc | Bin 4829 -> 0 bytes .../hotspot_analyzer.cpython-310.pyc | Bin 1599 -> 0 bytes .../mobility_analyzer.cpython-310.pyc | Bin 3036 -> 0 bytes .../pandemic_adherence_analyzer.cpython-310.pyc | Bin 1388 -> 0 bytes .../pandemic_stage_analyzer.cpython-310.pyc | Bin 1406 -> 0 bytes .../__pycache__/utilities.cpython-310.pyc | Bin 13783 -> 0 bytes .../__pycache__/viz.cpython-310.pyc | Bin 11375 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/DP_epidemiology/__pycache__/__init__.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/contact_matrix.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/hotspot_analyzer.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/mobility_analyzer.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/pandemic_adherence_analyzer.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/pandemic_stage_analyzer.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/utilities.cpython-310.pyc delete mode 100644 src/DP_epidemiology/__pycache__/viz.cpython-310.pyc diff --git a/src/DP_epidemiology/__pycache__/__init__.cpython-310.pyc b/src/DP_epidemiology/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index f34107dc718f10f2fd40644d6c3bb1dd9a2a64f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 203 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 Makkw&px$r)0K!Sq%K!iX diff --git a/src/DP_epidemiology/__pycache__/mobility_analyzer.cpython-310.pyc b/src/DP_epidemiology/__pycache__/mobility_analyzer.cpython-310.pyc deleted file mode 100644 index 06fa5669fcbdb251b86fe03ff357c923efd6fafc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3036 zcmZ`*NpB=c70$@L_Qh_u?VhE&X@)L@4b$8jL=T!~#D&4A8-Y?KrLr=js?w92A|l&U zR_3VyahYE*Lb8wZm*R>9@?RL%_p++oULaHP#fumFTO;dqni_mR{M(P`PrI7-S8Uw; zfTw)|MRbX#QH_#V^GIFmo>AAPXV$glSy1b-o!FjD)?=N-_1q2JNSa=2L${NT2MfY@ zBkmmU%k7*kKmnZjBFW++z@OL9r-HQadrjYb=c zoF337vuO)Tn;p^)do*j(F75rn^xpd){r%0DHXYC*jCr5#)NAbCTWLG8OCQiZ82JGu zueI^RE0omdW1?IdNG79%jdf*Ed8T?n7_yjgU{fC%PMD>VN7M7}EY1QMrSqdai&A+$ zTx2N|@@QJfqp;vnR)}-`_!t%?-&Z=Fsiu$tmp<;GT$aLeNSR?Im&#$eh~g{_Ej-EQ z8$fMC`4o!y696TZMfJ+2M&(ema;a4{pl(vTYEh?ZH?&eO$-Z`~QTI@*It>tJ+1b@f z8;bcztGcCjK`ynbC-s#kjj~Z1EBz%>t+HKHW=UX;=E?xBRXU|xT4i@-zSOFI*)Mx5 z6j$@xC$lIG;?b-~Lm6f1NM@s)Ga7|*w8*5$p?srrFf{Gz_qwKWG(Oc!r@rJtDuQ~F zP$mk1quHu%!g#pwLtxA^zEtkdBOXT}&npMI{|*H{_mi=Wla??w%<`q$Pl7L)4?E{P z3z-mpoWTlkAl0gSW>E|qsA1iZ98L@C`>0;EvzZ#bMV2TMf4UqGIPS(>ga!hhjkf@l zJQysofjbL2U+pn8m6!=UI_YmvzHM^{y%0x2A@-FN-{{z2S*}NDF_KasQ;4#!=}1k_E9`_@6F5?${TS2sKtb{ohSP z|5w}8{|POZKSOD|TSExZ{ji>T`dg9neH?s%a0u{!Y&o1b>33_f@ z`aeL|4gLdM@&TRQ3=2VAdy;wx?0J^WV|IPzx+6pv-F_%RY}XO;3B((zl^6q!(uBBW zuk6Yx9ZC)$ogHYED@m=(b*~G(4XH!yb5;an;fk#EswvG2h}+ofGhoIv$xZ$tHIUk)yYWseRn zbvPF!*LuXxrG_aMqWAFgwP9j(uI=>v@O2pF%Tbsmc>!r|bix8IAgc2hqx0@4Na-j) zdK<(Adol7FtO#R>3qcBr&7_f#%8Iiyh_dFK2aw28m<(}iY$!Y9(L72$GfaY9bs$GF zo@a3#ps#RuMb13;bum3KK^FB(R>3d|4>;g97--jNKzUxFLe&yzfycFO_)n12&2o4m<;S4ZxS&iqTSBL~H-M|5 z7UF0MX$UFLUf293Oy&kct-KyfgDHfN84F|qcF9k0aXWw{4k~hjsX$>U^Aw(N%ApZY z19%*`z7L6*`Mx^1lLwCriD@umLN#7N!vBopctc1qr20Kr=daozYYE&Ca~(`fvUD|<;NRZ-ebUuG(p@srpN@_n{}*%yOq>7! diff --git a/src/DP_epidemiology/__pycache__/pandemic_adherence_analyzer.cpython-310.pyc b/src/DP_epidemiology/__pycache__/pandemic_adherence_analyzer.cpython-310.pyc deleted file mode 100644 index 354cf23a456d0128c1975e40a5f09028d1257496..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1388 zcmaJ>&5I;86i-qgUDe<7p{(v@SVe4M=CIyG+=U&*lMc9oGz}qLNq5(5by6g$)gG%4 z(jNRHJWL<`k0e)51O5emzhrh`P%zDU`IjoL>zWm14G(%hOtw(q0{|loZCE&KrALG`ducxguw05RBh* zgfCpzSf(xYC%H^WeyhbrX*cdj7$c-DSw)qmRr5`wH?AXUQ&vhAsfY1u9DwxpGa&N= zFpjq=C)*B>wi%DNIZw7-kUgGm`#EY!iyxp%#5-@I?I4G5ZwJSy?EobY(RSFPYrIF> zktI81qaAvJY}|I+Xh(w9Z{wgPEryeNy9m5#o3(kHw!>Zg1Z~IdxE<|$w(_e-i&C=c zWYNgNmP(#jby91=%fgCJhTg#>GBEI`eDCYoUu3 zHBBuvEx^50dUMl(r6mxI?CGTA12zy=sCwfbtl0}e;nrHK0+LEA1#tl8zboNvCavp* zm_=E^weBz&R>L>IeKgek=+&X+OYbtxn$9?Q5YuqJUWEUi1C$(z$9RH?G&z z9(}Of@x3qg^=GtDmFq3FYU=qW7@2Q~Tg_h{w8Psx++`s6`aW;4!B}V$mzaW8!lhDt zO`+E^28GyM3H=k&j{wbY-xVLszBEFc*$cC3=CjYGIM?M%F*{d9vxe3)vx|?P(|W~> zppU(7=mJ{tqM27^K|d9&vMc&*#i~lkrI;CA%+4>Us7o%^rK;3&Gpm{OMnM^02`ywH z=pBqRD9ywFSswsK^B7o6VjO0WBpPBu#yBH!9Aol#M#x`TME>l?n`=jGvi3jT_T$`+(=~YA_Kial+n;|$PHBuFRwm>2B{hjulY_PymliY*}M{TA((Bn zfR?J6UAdG&0VQ`GHaEc$U&4cT9bRh5;E#||3cVvJb#MGDBWH~*tJ0QmRDKS{{zUuz tk+Iq(;qMW!hXUPWZ+W2Ehik=~N_^yBi#Z0Cp$z-khdCtgkPN>|{sBQ7sCWPX diff --git a/src/DP_epidemiology/__pycache__/pandemic_stage_analyzer.cpython-310.pyc b/src/DP_epidemiology/__pycache__/pandemic_stage_analyzer.cpython-310.pyc deleted file mode 100644 index fc5a76dd9fe99e23faf1411c072b928048d1d08b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1406 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 From c87ddca5e81169350295f9872abf02d177f70258 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 7 Dec 2024 23:42:07 +0530 Subject: [PATCH 5/5] documentaation on gui --- docs/usage.rst | 86 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/docs/usage.rst b/docs/usage.rst index 83dc89d..c52c122 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -231,4 +231,88 @@ For example: >>> app.run_server(debug=True) .. image:: images/contact_matrix.png - :alt: matrix \ No newline at end of file + :alt: matrix + +Dash Application for Mobility and Pandemic Analysis +=================================================== + +This module creates a Dash web application for analyzing mobility and pandemic adherence using transactional and Google mobility data. The application provides multiple tabs for different types of analysis, including hotspot analysis, mobility analysis, pandemic adherence analysis, contact matrix analysis, and mobility validation. + +Functions +--------- + +create_dash_app(df: pd.DataFrame, df_google_mobility_data: pd.DataFrame = None) + Creates and returns a Dash application. + + Parameters: + df (pd.DataFrame): DataFrame containing transactional data. + df_google_mobility_data (pd.DataFrame, optional): DataFrame containing Google mobility data. + + Returns: + app (dash.Dash): Dash application instance. + +Example Usage +------------- + +.. code-block:: python + + import pandas as pd + from dash_app import create_dash_app + + # Load data + df = pd.read_csv(r'D:\workspace\pet_local\technical_phase_data.csv') + df_google_mobility_data = pd.read_csv('D:\workspace\PETs_challenge_data.csv') + + # Create and run the Dash app + app = create_dash_app(df, df_google_mobility_data) + app.run_server(debug=True) + +Application Layout +------------------ + +The application consists of the following tabs: + +1. **Hotspot Analysis**: + - Date pickers for selecting start and end dates. + - Slider for selecting epsilon value. + - Dropdown for selecting city. + - Geo plot displaying transaction locations. + +2. **Mobility Analysis**: + - Date pickers for selecting start and end dates. + - Slider for selecting epsilon value. + - Dropdown for selecting city. + - Dropdown for selecting category. + - Line graph displaying mobility analysis. + +3. **Pandemic Adherence Analysis**: + - Date pickers for selecting start and end dates. + - Slider for selecting epsilon value. + - Dropdown for selecting city. + - Dropdown for selecting entry type (luxury, essential, other). + - Line graph displaying pandemic adherence analysis. + +4. **Contact Matrix Analysis**: + - Date pickers for selecting start and end dates. + - Slider for selecting epsilon value. + - Dropdown for selecting city. + - Heatmap displaying contact matrix. + - Text output displaying contact matrix values. + +5. **Mobility Validation**: + - Date pickers for selecting start and end dates. + - Slider for selecting epsilon value. + - Dropdown for selecting city. + - Dropdown for selecting category. + - Line graph displaying mobility validation analysis. + +Callbacks +--------- + +The application uses several callbacks to update the graphs based on user inputs. Each tab has its own callback function to handle the updates. + +- `update_hotspot_graph`: Updates the hotspot geo plot. +- `update_mobility_graph`: Updates the mobility analysis graph. +- `update_adherence_graph`: Updates the pandemic adherence analysis graph. +- `update_contact_matrix`: Updates the contact matrix heatmap and text output. +- `update_validation_graph`: Updates the mobility validation graph. \ No newline at end of file