Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/live' into eatyourpeas/issue422
Browse files Browse the repository at this point in the history
  • Loading branch information
eatyourpeas committed Dec 14, 2024
2 parents 22bd681 + f990139 commit 486384b
Show file tree
Hide file tree
Showing 2 changed files with 385 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends 'dashboard/base_card.html' %}
{% extends 'dashboard/components/bases/base_card.html' %}
{% block card_title %}
Distribution of patients ({{ pdu_object.lead_organisation_name }} {{ pdu_object.pz_code }})
{% endblock card_title %}
Expand Down
384 changes: 384 additions & 0 deletions project/npda/views/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,390 @@ def add_number_of_figures_coloured_for_chart(
return dict(value_counts_dict)


@login_and_otp_required()
def get_colored_figures_chart_partial(
request,
colored: int,
total_figures: int,
):

if not request.htmx:
return HttpResponseBadRequest("This view is only accessible via HTMX")

# Get a list of booleans to determine which figures are colored (to iterate easily in the
# template)
is_colored = [True if i < colored else False for i in range(total_figures)]

return render(
request,
"dashboard/colored_figures_chart_partial.html",
context={
"is_colored": is_colored,
},
)


def get_total_eligible_pts_diabetes_type_value_counts(
eligible_pts_queryset: QuerySet,
) -> dict:
"""Gets value counts dict for total eligible patients stratified by diabetes type"""

eligible_pts_diabetes_type_counts = eligible_pts_queryset.values(
"diabetes_type"
).annotate(count=Count("diabetes_type"))
eligible_pts_diabetes_type_value_counts = defaultdict(int)
for item in eligible_pts_diabetes_type_counts:
diabetes_type = item["diabetes_type"]
count = item["count"]

# These are T1/T2DM types
if diabetes_type == 1:
diabetes_type_str = "T1DM"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count
elif diabetes_type == 2:
diabetes_type_str = "T2DM"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count
else:
# Count as 'Other rare forms'
diabetes_type_str = "Other rare forms"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count

# Convert to percentages
eligible_pts_diabetes_type_value_counts = convert_value_counts_dict_to_pct(
eligible_pts_diabetes_type_value_counts
)

return eligible_pts_diabetes_type_value_counts


def get_pt_characteristics_value_counts_pct(
kpi_name_registry: KPIRegistry,
kpi_calculations_object: dict,
) -> dict[
Literal["care", "died_or_transitioned", "comorbidity_and_testing"],
dict[Literal["total_eligible", "total_ineligible", "pct"], int],
]:
"""Gets value counts dict for:
care
- age_gte_12yo (KPI4)
- complete_year_of_care (KPI5)
- age_gte_12yo_and_complete_year_of_care (KPI6)
died_or_transitioned
- died (KPI8)
- transitioned (KPI9)
comorbidity_and_testing
- coeliac (KPI10)
- thyroid (kpi11)
- ketone_testing (KPI12)
NOTE: rounds DOWN (convert float to int) for percentage calculation
"""
# Get attribute names and labels
relevant_kpis = [4, 5, 6, 8, 9, 10, 11, 12]
kpi_attr_names = [
kpi_name_registry.get_attribute_name(kpi) for kpi in relevant_kpis
]

value_counts = defaultdict(lambda: {"count": 0, "total": 0, "pct": 0})
# These are all just counts so only total_eligble and total_ineligible have values
for kpi_attr in kpi_attr_names:

total_eligible = kpi_calculations_object[kpi_attr]["total_eligible"]
total_ineligible = kpi_calculations_object[kpi_attr]["total_ineligible"]

# Need all 3 for front end chart
value_counts[kpi_attr]["count"] = total_eligible
value_counts[kpi_attr]["total"] = total_eligible + total_ineligible
value_counts[kpi_attr]["pct"] = (
int(total_eligible / value_counts[kpi_attr]["total"] * 100)
if value_counts[kpi_attr]["total"] > 0
else 0
)

# Now put into the 3 categories
categories_vc = defaultdict(dict)
for kpi in [4, 5, 6]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["care"][kpi_attr] = value_counts[kpi_attr]

for kpi in [8, 9]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["died_or_transitioned"][kpi_attr] = value_counts[kpi_attr]

for kpi in [10, 11, 12]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["comorbidity_and_testing"][kpi_attr] = value_counts[kpi_attr]

return dict(categories_vc)


def get_pt_demographic_value_counts(
all_eligible_pts_queryset: QuerySet[Patient],
) -> tuple[
dict[Literal["Female", "Male", "Unknown"], int],
dict[str, int],
dict[
Literal[
1,
2,
3,
4,
5,
],
int,
],
]:
"""Get value counts for pt demographics:
- sex
- ethnicity
- imd
"""

all_values = all_eligible_pts_queryset.values(
"sex", "ethnicity", "index_of_multiple_deprivation_quintile"
)
sex_map = dict(SEX_TYPE)
sex_counts = Counter(sex_map[item["sex"]] for item in all_values)
ethnicity_map = dict(ETHNICITIES)
ethnicity_counts = Counter(ethnicity_map[item["ethnicity"]] for item in all_values)
imd_map = {
1: "1st Quintile",
2: "2nd Quintile",
3: "3rd Quintile",
4: "4th Quintile",
5: "5th Quintile",
}
imd_counts = Counter(
imd_map[item["index_of_multiple_deprivation_quintile"]] for item in all_values
)

return (
sex_counts,
ethnicity_counts,
imd_counts,
)


def add_number_of_figures_coloured_for_chart(
value_counts_dict: dict[
Literal["care", "died_or_transitioned", "comorbidity_and_testing"],
dict[Literal["total_eligible", "total_ineligible", "pct"], int],
],
n_figures_total: int = 5,
) -> dict[
Literal["total_eligible", "total_ineligible", "pct", "figures_coloured"], int
]:
"""
Add number of figures coloured to a value counts dict
"""
# divisor is 100 / n_figures_total
divisor = 100 / n_figures_total

for category, vcs in value_counts_dict.items():
for key, value in vcs.items():
value_counts_dict[category][key]["figures_coloured"] = int(
value["pct"] / divisor
)

return dict(value_counts_dict)


@login_and_otp_required()
def get_colored_figures_chart_partial(
request,
colored: int,
total_figures: int,
):

if not request.htmx:
return HttpResponseBadRequest("This view is only accessible via HTMX")

# Get a list of booleans to determine which figures are colored (to iterate easily in the
# template)
is_colored = [True if i < colored else False for i in range(total_figures)]

return render(
request,
"dashboard/colored_figures_chart_partial.html",
context={
"is_colored": is_colored,
},
)


def get_total_eligible_pts_diabetes_type_value_counts(
eligible_pts_queryset: QuerySet,
) -> dict:
"""Gets value counts dict for total eligible patients stratified by diabetes type"""

eligible_pts_diabetes_type_counts = eligible_pts_queryset.values(
"diabetes_type"
).annotate(count=Count("diabetes_type"))
eligible_pts_diabetes_type_value_counts = defaultdict(int)
for item in eligible_pts_diabetes_type_counts:
diabetes_type = item["diabetes_type"]
count = item["count"]

# These are T1/T2DM types
if diabetes_type == 1:
diabetes_type_str = "T1DM"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count
elif diabetes_type == 2:
diabetes_type_str = "T2DM"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count
else:
# Count as 'Other rare forms'
diabetes_type_str = "Other rare forms"
eligible_pts_diabetes_type_value_counts[diabetes_type_str] += count

# Convert to percentages
eligible_pts_diabetes_type_value_counts = convert_value_counts_dict_to_pct(
eligible_pts_diabetes_type_value_counts
)

return eligible_pts_diabetes_type_value_counts


def get_pt_characteristics_value_counts_pct(
kpi_name_registry: KPIRegistry,
kpi_calculations_object: dict,
) -> dict[
Literal["care", "died_or_transitioned", "comorbidity_and_testing"],
dict[Literal["total_eligible", "total_ineligible", "pct"], int],
]:
"""Gets value counts dict for:
care
- age_gte_12yo (KPI4)
- complete_year_of_care (KPI5)
- age_gte_12yo_and_complete_year_of_care (KPI6)
died_or_transitioned
- died (KPI8)
- transitioned (KPI9)
comorbidity_and_testing
- coeliac (KPI10)
- thyroid (kpi11)
- ketone_testing (KPI12)
NOTE: rounds DOWN (convert float to int) for percentage calculation
"""
# Get attribute names and labels
relevant_kpis = [4, 5, 6, 8, 9, 10, 11, 12]
kpi_attr_names = [
kpi_name_registry.get_attribute_name(kpi) for kpi in relevant_kpis
]

value_counts = defaultdict(lambda: {"count": 0, "total": 0, "pct": 0})
# These are all just counts so only total_eligble and total_ineligible have values
for kpi_attr in kpi_attr_names:

total_eligible = kpi_calculations_object[kpi_attr]["total_eligible"]
total_ineligible = kpi_calculations_object[kpi_attr]["total_ineligible"]

# Need all 3 for front end chart
value_counts[kpi_attr]["count"] = total_eligible
value_counts[kpi_attr]["total"] = total_eligible + total_ineligible
value_counts[kpi_attr]["pct"] = (
int(total_eligible / value_counts[kpi_attr]["total"] * 100)
if value_counts[kpi_attr]["total"] > 0
else 0
)

# Now put into the 3 categories
categories_vc = defaultdict(dict)
for kpi in [4, 5, 6]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["care"][kpi_attr] = value_counts[kpi_attr]

for kpi in [8, 9]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["died_or_transitioned"][kpi_attr] = value_counts[kpi_attr]

for kpi in [10, 11, 12]:
kpi_attr = kpi_name_registry.get_attribute_name(kpi)
categories_vc["comorbidity_and_testing"][kpi_attr] = value_counts[kpi_attr]

return dict(categories_vc)


def get_pt_demographic_value_counts(
all_eligible_pts_queryset: QuerySet[Patient],
) -> tuple[
dict[Literal["Female", "Male", "Unknown"], int],
dict[str, int],
dict[
Literal[
1,
2,
3,
4,
5,
],
int,
],
]:
"""Get value counts for pt demographics:
- sex
- ethnicity
- imd
"""

all_values = all_eligible_pts_queryset.values(
"sex", "ethnicity", "index_of_multiple_deprivation_quintile"
)
sex_map = dict(SEX_TYPE)
sex_counts = Counter(sex_map[item["sex"]] for item in all_values)
ethnicity_map = dict(ETHNICITIES)
ethnicity_counts = Counter(ethnicity_map[item["ethnicity"]] for item in all_values)
imd_map = {
1: "1st Quintile",
2: "2nd Quintile",
3: "3rd Quintile",
4: "4th Quintile",
5: "5th Quintile",
}
imd_counts = Counter(
imd_map[item["index_of_multiple_deprivation_quintile"]] for item in all_values
)

return (
sex_counts,
ethnicity_counts,
imd_counts,
)


def add_number_of_figures_coloured_for_chart(
value_counts_dict: dict[
Literal["care", "died_or_transitioned", "comorbidity_and_testing"],
dict[Literal["total_eligible", "total_ineligible", "pct"], int],
],
n_figures_total: int = 5,
) -> dict[
Literal["total_eligible", "total_ineligible", "pct", "figures_coloured"], int
]:
"""
Add number of figures coloured to a value counts dict
"""
# divisor is 100 / n_figures_total
divisor = 100 / n_figures_total

for category, vcs in value_counts_dict.items():
for key, value in vcs.items():
value_counts_dict[category][key]["figures_coloured"] = int(
value["pct"] / divisor
)

return dict(value_counts_dict)


def convert_value_counts_dict_to_pct(value_counts_dict: dict):
"""
Convert a value counts dict to percentages
Expand Down

0 comments on commit 486384b

Please sign in to comment.