Skip to content

Commit

Permalink
Merge branch 'main' into final-presentation
Browse files Browse the repository at this point in the history
  • Loading branch information
tkv29 committed May 27, 2024
2 parents e86f14c + 127c998 commit 2be3411
Show file tree
Hide file tree
Showing 81 changed files with 3,894 additions and 2,076 deletions.
5 changes: 4 additions & 1 deletion install-dependencies-unix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ sudo apt-get update && apt-get upgrade -y

sudo apt install python3 graphviz -y

pip install -r requirements.txt
# add Graphviz to the system path
echo 'export PATH=$PATH:/usr/local/bin/graphviz' >> ~/.bashrc
source ~/.bashrc

pip install -r requirements.txt
9 changes: 8 additions & 1 deletion install-dependencies-windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@
winget install Python --accept-source-agreements --accept-package-agreements
winget install graphviz --accept-source-agreements --accept-package-agreements

# add Graphviz to the system path
$graphvizPath = "C:\Program Files\Graphviz\bin"
$envPath = [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine)
if (-not ($envPath).Contains($graphvizPath)) {
[Environment]::SetEnvironmentVariable("Path", $envPath + ";" + $graphvizPath, [EnvironmentVariableTarget]::Machine)
}

# install python packages
pip install -r .\requirements.txt
pip install -r .\requirements.txt
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ pre-commit~=3.6.2
plotly~=5.22.0
pandas~=2.1.3
numpy~=1.26.2
jinja2~=3.1.4
regex~=2024.5.15
Binary file modified tracex_project/db.sqlite3
Binary file not shown.
88 changes: 83 additions & 5 deletions tracex_project/db_results/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""Implementation of forms for the database result app."""
from typing import List, Tuple, Any

from django import forms
from django.utils.safestring import mark_safe
from extraction.models import Cohort
from extraction.models import PatientJourney
from tracex.forms import BaseEventForm


class PatientJourneySelectForm(forms.Form):
Expand All @@ -15,13 +20,86 @@ def __init__(self, *args, **kwargs):
"selected_patient_journey"
].choices = self.get_patient_journey_choices()

def get_patient_journey_choices(self):
def get_patient_journey_choices(self) -> List[Tuple[str, str]]:
"""Retrieves the available patient journey choices with existing metrics from the database."""
patient_journeys = PatientJourney.manager.exclude(
trace__events__metrics__activity_relevance__isnull=True,
trace__events__metrics__timestamp_correctness__isnull=True,
trace__events__metrics__correctness_confidence__isnull=True,
patient_journeys = PatientJourney.manager.filter(
trace__events__metrics__isnull=False
).distinct()
choices = [(pj.name, pj.name) for pj in patient_journeys]

return choices


class EvaluationForm(BaseEventForm):
"""Form for evaluating the extraction result."""

min_age = forms.IntegerField(
required=False,
widget=forms.NumberInput(attrs={"id": "min-age"}),
)
max_age = forms.IntegerField(
required=False,
widget=forms.NumberInput(attrs={"id": "max-age"}),
)
none_age = forms.BooleanField(
label=mark_safe("<i>Include elements with None values</i>"),
required=False,
widget=forms.CheckboxInput(),
)
sex = forms.MultipleChoiceField(
label="Sex:",
choices=[],
widget=forms.CheckboxSelectMultiple(),
required=False,
)
condition = forms.MultipleChoiceField(
label="Condition:",
choices=[],
widget=forms.CheckboxSelectMultiple(),
required=False,
)
preexisting_condition = forms.MultipleChoiceField(
label="Preexisting Condition:",
choices=[],
widget=forms.CheckboxSelectMultiple(),
required=False,
)
origin = forms.MultipleChoiceField(
label="Origin:",
choices=[],
widget=forms.CheckboxSelectMultiple(attrs={"class": "origin-checkbox"}),
required=False,
)

def __init__(self, *args, **kwargs):
"""Initializes the EvaluationForm."""
config = kwargs.get("initial", None)
super().__init__(*args, **kwargs)

self.label_suffix = ""

if config:
self.fields["min_age"].initial = config.get("min_age")
self.fields["max_age"].initial = config.get("max_age")

self.fields["condition"].choices = self.get_choices("condition")
self.fields["preexisting_condition"].choices = self.get_choices(
"preexisting_condition"
)
self.fields["origin"].choices = self.get_choices("origin")
self.fields["sex"].choices = self.get_choices("sex")

@staticmethod
def get_choices(category: str) -> List[Tuple[Any, Any]]:
"""Get all choices available in the database for a given category."""
choices = Cohort.manager.values_list(category, flat=True).distinct()
none_info_text = mark_safe("<i>Include elements with None values</i>")
choices = [
(
"None" if choice is None else choice,
none_info_text if choice is None else choice,
)
for choice in choices
]
# sort by name, but put None values at the end
return sorted(choices, key=lambda x: (x[0] == "None", x[1]))
50 changes: 50 additions & 0 deletions tracex_project/db_results/static/db_results/js/filter_toggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
$(document).ready(function () {
// Toggle visibility for multiple elements
setupToggleButton('#toggleButton1', '#contentWrapper1');
setupToggleButton('#toggleButton2', '#contentWrapper2');

// Setup age range slider
setupAgeSlider();

// Setup checkbox toggles for multiple groups
setupCheckboxToggle('#toggleAll', '.origin-checkbox input[type="checkbox"]');
setupCheckboxToggle('#togglesex', 'input[name="sex"]');
setupCheckboxToggle('#toggleCondition', 'input[name="condition"]');
setupCheckboxToggle('#togglePreexistingCondition', 'input[name="preexisting_condition"]');
});

function setupToggleButton(buttonSelector, contentSelector) {
$(buttonSelector).click(function () {
$(contentSelector).toggle();
});
}

function setupAgeSlider() {
const ageSlider = document.getElementById('age-slider');
const minAgeField = document.getElementById('min-age');
const maxAgeField = document.getElementById('max-age');

noUiSlider.create(ageSlider, {
start: [minAgeField.value || 0, maxAgeField.value || 100],
connect: true,
range: {
'min': 0,
'max': 100
}
});

ageSlider.noUiSlider.on('update', function (values) {
minAgeField.value = Math.round(values[0]);
maxAgeField.value = Math.round(values[1]);
});

minAgeField.addEventListener('change', () => ageSlider.noUiSlider.set([minAgeField.value, null]));
maxAgeField.addEventListener('change', () => ageSlider.noUiSlider.set([null, maxAgeField.value]));
}

function setupCheckboxToggle(toggleSelector, checkboxSelector) {
document.querySelector(toggleSelector).addEventListener('change', function() {
document.querySelectorAll(checkboxSelector)
.forEach(checkbox => checkbox.checked = this.checked);
});
}
90 changes: 61 additions & 29 deletions tracex_project/db_results/static/db_results/js/metrics-dashboard.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,72 @@
// Constants for color thresholds and descriptions
const GREEN_THRESHOLD = 0.7;
const ORANGE_THRESHOLD = 0.5;
const COLORS = {
GREEN: 'green',
ORANGE: 'orange',
RED: 'red'
};

// Constants for content matching
const CONTENT_MATCH = {
HIGH_RELEVANCE: 'High Relevance',
TRUE: 'True',
LOW_RELEVANCE: 'Low Relevance',
FALSE: 'False'
};

// Helper function to set the tile color based on predefined color rules.
function setTileColor(tile, color) {
tile.style.backgroundColor = color;
}

// Updates the tile color based on the average time correctness ratio.
function updateAvgTimeCorrTileColor(ratio, tile) {
if (ratio >= 0.7) {
tile.style.backgroundColor = 'green';
} else if (ratio >= 0.5) {
tile.style.backgroundColor = 'orange';
} else {
tile.style.backgroundColor = 'red';
}
if (ratio >= GREEN_THRESHOLD) {
setTileColor(tile, COLORS.GREEN);
} else if (ratio >= ORANGE_THRESHOLD) {
setTileColor(tile, COLORS.ORANGE);
} else {
setTileColor(tile, COLORS.RED);
}
}

// Updates the tile color based on the frequency metric's content.
function updateFrequentMetricTileColor(content, tile) {
if (content === 'High Relevance' || content === 'True') {
tile.style.backgroundColor = 'green';
} else if (content === 'Low Relevance' || content === 'False') {
tile.style.backgroundColor = 'red';
} else {
tile.style.backgroundColor = 'orange';
switch (content) {
case CONTENT_MATCH.HIGH_RELEVANCE:
case CONTENT_MATCH.TRUE:
setTileColor(tile, COLORS.GREEN);
break;
case CONTENT_MATCH.LOW_RELEVANCE:
case CONTENT_MATCH.FALSE:
setTileColor(tile, COLORS.RED);
break;
default:
setTileColor(tile, COLORS.ORANGE);
}
}

// Utility function to get tile and content from a given element id.
function getTileAndContent(id) {
const element = document.getElementById(id);
const tile = element.closest('.metric-tile');
const content = element.textContent.trim();
return { tile, content };
}

const avgTimeStampCorr = document.getElementById('avgTimeStampCorr');
const avgTimeStampCorrTile = avgTimeStampCorr.closest('.metric-tile');
const avgTimeStampCorrContent = parseFloat(avgTimeStampCorr.textContent);
updateAvgTimeCorrTileColor(avgTimeStampCorrContent, avgTimeStampCorrTile);
// Update tile color for average timestamp correctness.
const avgTimeStampCorr = getTileAndContent('avgTimeStampCorr');
const avgTimeStampCorrContent = parseFloat(avgTimeStampCorr.content);
updateAvgTimeCorrTileColor(avgTimeStampCorrContent, avgTimeStampCorr.tile);

const most_frequent_timestamp_correctness = document.getElementById('most_frequent_timestamp_correctness');
const most_frequent_timestamp_correctness_tile = most_frequent_timestamp_correctness.closest('.metric-tile');
const most_frequent_timestamp_correctness_content = most_frequent_timestamp_correctness.textContent.trim();
updateFrequentMetricTileColor(most_frequent_timestamp_correctness_content, most_frequent_timestamp_correctness_tile);
// Update tile color for the most frequent timestamp correctness.
const mostFreqTimestampCorr = getTileAndContent('most_frequent_timestamp_correctness');
updateFrequentMetricTileColor(mostFreqTimestampCorr.content, mostFreqTimestampCorr.tile);

const most_frequent_category = document.getElementById('most_frequent_category');
const most_frequent_category_tile = most_frequent_category.closest('.metric-tile');
const most_frequent_category_content = most_frequent_category.textContent.trim();
updateFrequentMetricTileColor(most_frequent_category_content, most_frequent_category_tile);
// Update tile color for the most frequent category.
const mostFreqCategory = getTileAndContent('most_frequent_category');
updateFrequentMetricTileColor(mostFreqCategory.content, mostFreqCategory.tile);

// Trigger a resize event for the plots to adapt to the new size
setTimeout(function() {
window.dispatchEvent(new Event('resize'));
}, 0);
// Trigger a resize event for the plots to adapt to the new size.
setTimeout(() => window.dispatchEvent(new Event('resize')), 0);
44 changes: 23 additions & 21 deletions tracex_project/db_results/templates/db_results_overview.html
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Database Results</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static '/tracex/css/style.css' %}">
</head>
<html lang="en">
<head>
<title>Database Results</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static '/tracex/css/styles.css' %}">
</head>
<body class="main_body">
<img src="{% static '/tracex/img/database_results_logo.png' %}" alt="Database Results Logo" class="database_results_logo">
<h2>Welcome to the Database Results</h2>
<p> The Database Results page presents a comprehensive overview of the data gathered from the system. It offers insights into various aspects of the database, including metrics, analyses and filter possibilities.</p>
<p> Please select if you want to see the Metrics Dashboard or the Evaluation.</p>
<img src="{% static '/tracex/img/database_results_logo.png' %}" alt="Database Results Logo"
class="database_results_logo">
<h2>Welcome to the Database Results</h2>
<p> The Database Results page presents a comprehensive overview of the data gathered from the system. It offers insights
into various aspects of the database, including metrics, analyses and filter possibilities.</p>
<p> Please select if you want to see the Metrics Dashboard or the Evaluation.</p>

<div class="button-container">
<a href="{% url 'metrics_overview' %}">
<button class="menu_button">Go to Metrics Dashboard</button>
</a>
<a>
<button class="menu_button">Go to Evaluation</button>
</a>
</div>

<a href="{% url 'landing_page' %}">
<button class="menu_button">Return to TracEX menu</button>
<div class="button-container">
<a href="{% url 'metrics_overview' %}">
<button class="menu_button">Go to Metrics Dashboard</button>
</a>
<a href="{% url 'evaluation' %}">
<button class="menu_button">Go to Evaluation</button>
</a>
</div>

<a href="{% url 'landing_page' %}">
<button class="menu_button">Return to TracEX Menu</button>
</a>
</body>
</html>
Loading

0 comments on commit 2be3411

Please sign in to comment.