Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/alternative_interface/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
from django.urls import path
from django.urls.resolvers import URLPattern
from alternative_interface.views import alternative_interface_view
from alternative_interface.views import (
alternative_interface_view,
get_available_geos_ajax,
get_chart_data_ajax,
)

urlpatterns: list[URLPattern] = [
path("alternative_interface", alternative_interface_view, name="alternative_interface"),
path("api/get_available_geos", get_available_geos_ajax, name="get_available_geos_ajax"),
path("api/get_chart_data", get_chart_data_ajax, name="get_chart_data_ajax"),
]
158 changes: 104 additions & 54 deletions src/alternative_interface/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from django.shortcuts import render
import logging

from django.db.models import Case, When, Value, IntegerField
from alternative_interface.models import ExpressViewIndicator
from epiportal.settings import ALTERNATIVE_INTERFACE_VERSION
from django.http import JsonResponse
from django.shortcuts import render

from alternative_interface.models import ExpressViewIndicator
from alternative_interface.utils import get_available_geos, get_chart_data
from epiportal.settings import ALTERNATIVE_INTERFACE_VERSION

logger = logging.getLogger(__name__)

MENU_ITEMS_DISPLAY_ORDER_NUMBER = {
"Influenza": 1,
Expand All @@ -13,21 +17,53 @@
"Influenza-Like Illness (ILI)": 4,
}

HEADER_DESCRIPTION = "Discover, display and download real-time infectious disease indicators (time series) that track a variety of pathogens, diseases and syndromes in a variety of locations (primarily within the USA). Browse the list, or filter it first by locations and pathogens of interest, by surveillance categories, and more. Expand any row to expose and select from a set of related indicators, then hit 'Show Selected Indicators' at bottom to plot or export your selected indicators, or to generate code snippets to retrieve them from the Delphi Epidata API. Most indicators are served from the Delphi Epidata real-time repository, but some may be available only from third parties or may require prior approval."

def _convert_indicators_to_dicts(indicators_qs):
"""Convert queryset of ExpressViewIndicator to list of dictionaries."""
return [
{
"_endpoint": (
indicator.indicator.indicator_set.epidata_endpoint
if indicator.indicator.indicator_set
else ""
),
"name": indicator.indicator.name,
"data_source": (
indicator.indicator.source.name
if indicator.indicator.source
else "Unknown"
),
"time_type": indicator.indicator.time_type,
"indicator_set_short_name": (
indicator.indicator.indicator_set.short_name
if indicator.indicator.indicator_set
else "Unknown"
),
"member_short_name": (
indicator.indicator.member_short_name
if indicator.indicator.member_short_name
else "Unknown"
),
}
for indicator in indicators_qs
]


def _get_indicators_queryset(pathogen_filter):
"""Get optimized queryset for indicators filtered by pathogen."""
return (
ExpressViewIndicator.objects.filter(menu_item=pathogen_filter)
.select_related("indicator__indicator_set", "indicator__source")
)


def alternative_interface_view(request):
"""Main view for the alternative interface dashboard."""
try:
ctx = {}
ctx["header_description"] = HEADER_DESCRIPTION
ctx["alternative_interface_version"] = ALTERNATIVE_INTERFACE_VERSION
# Get filters from URL parameters
pathogen_filter = request.GET.get("pathogen", "")
geography_filter = request.GET.get("geography", "")
ctx["selected_pathogen"] = pathogen_filter
ctx["selected_geography"] = geography_filter

# Fetch pathogens for dropdown
# Fetch pathogens for dropdown - optimized query
pathogens_qs = (
ExpressViewIndicator.objects.annotate(
order_number=Case(
Expand All @@ -44,51 +80,65 @@ def alternative_interface_view(request):
.order_by("order_number")
)
pathogens = [item["menu_item"] for item in pathogens_qs]
ctx["pathogens"] = pathogens

indicators_qs = ExpressViewIndicator.objects.filter(
menu_item=pathogen_filter
).prefetch_related("indicator")

# Convert to list of dictionaries
ctx["indicators"] = [
{
"_endpoint": (
indicator.indicator.indicator_set.epidata_endpoint
if indicator.indicator.indicator_set
else ""
),
"name": indicator.indicator.name,
"data_source": (
indicator.indicator.source.name
if indicator.indicator.source
else "Unknown"
),
"time_type": indicator.indicator.time_type,
"indicator_set_short_name": (
indicator.indicator.indicator_set.short_name
if indicator.indicator.indicator_set
else "Unknown"
),
"member_short_name": (
indicator.indicator.member_short_name
if indicator.indicator.member_short_name
else "Unknown"
),
}
for indicator in indicators_qs
]

ctx["available_geos"] = get_available_geos(ctx["indicators"])

if geography_filter:
ctx["chart_data"] = get_chart_data(ctx["indicators"], geography_filter)
else:
ctx["chart_data"] = []

# Get indicators with optimized query
indicators_qs = _get_indicators_queryset(pathogen_filter)
indicators = _convert_indicators_to_dicts(indicators_qs)

ctx = {
"alternative_interface_version": ALTERNATIVE_INTERFACE_VERSION,
"selected_pathogen": pathogen_filter,
"selected_geography": geography_filter,
"pathogens": pathogens,
"indicators": indicators,
"available_geos": get_available_geos(indicators),
"chart_data": (
get_chart_data(indicators, geography_filter)
if geography_filter
else []
),
}

return render(
request, "alternative_interface/alter_dashboard.html", context=ctx
)
except Exception as e:
from django.http import HttpResponse
logger.exception("Error loading alternative interface page")
return JsonResponse({"error": str(e)}, status=500)


return HttpResponse(f"Error loading page: {str(e)}")
def get_available_geos_ajax(request):
"""AJAX endpoint to get available geographies for a selected pathogen."""
try:
pathogen_filter = request.GET.get("pathogen", "")

if not pathogen_filter:
return JsonResponse({"available_geos": []})

indicators_qs = _get_indicators_queryset(pathogen_filter)
indicators = _convert_indicators_to_dicts(indicators_qs)
available_geos = get_available_geos(indicators)

return JsonResponse({"available_geos": available_geos})
except Exception as e:
logger.exception("Error fetching available geos")
return JsonResponse({"error": str(e)}, status=500)


def get_chart_data_ajax(request):
"""AJAX endpoint to get chart data for selected pathogen and geography."""
try:
pathogen_filter = request.GET.get("pathogen", "")
geography_filter = request.GET.get("geography", "")

if not pathogen_filter or not geography_filter:
return JsonResponse({"chart_data": {}})

indicators_qs = _get_indicators_queryset(pathogen_filter)
indicators = _convert_indicators_to_dicts(indicators_qs)
chart_data = get_chart_data(indicators, geography_filter)

return JsonResponse({"chart_data": chart_data})
except Exception as e:
logger.exception("Error fetching chart data")
return JsonResponse({"error": str(e)}, status=500)
Loading
Loading