EXTREMUM_web/base/static/js/counterfactuals.js

518 lines
22 KiB
JavaScript
Executable File

import { create_selection, create_dataframe, create_div, transpose_table } from './methods.js'
// Add event listeners to both buttons
if (document.getElementById("new_x")) {
document.getElementById("new_x").addEventListener('click', function () {
// Add 'active' class to new_x and remove it from load_x
$("#new_x").classList.add('active');
$("#load_x").classList.remove('active');
});
}
if (document.getElementById("#load_x")) {
document.getElementById("#load_x").addEventListener('click', function () {
// Add 'active' class to load_x and remove it from new_x
$("#load_x").classList.add('active');
$("#new_x").classList.remove('active');
});
}
$(document).ready(function () {
if (document.getElementById("classifier")) {
document.getElementById("classifier").addEventListener("change", function (e) {
var classifier = document.getElementById("classifier").value
if (classifier == "wildboar_knn" || classifier == "wildboar_rsf") {
// Loop through each checkbox and disable it
$("#pre_computed_counterfactuals").hide()
$("#class_label_container").show()
$("#pre_computed_counterfactuals").hide()
$("#entries_container_glacier").hide()
$("#cfbtn_container_2").hide()
$("#saved_experiments").hide()
$("#new_experiment_details").hide()
}
if (classifier == "glacier") {
// Loop through each checkbox and disable it
// $("#constraint_div").show()
// $("#w_value_div").show()
// $("#cfbtn_container_2").show()
$("#class_label_container").show()
// $("#pre_computed_counterfactuals").show()
// $("#class_label_container").show()
$("#saved_experiments").show()
}
});
}
$('#class_label_container').change(function () {
$("#entries_container").show()
});
$('#pre_computed_counterfactuals').change(function () {
$("#entries_container_glacier").show()
});
$('.plot_sample').click(function (event) {
$("#cfbtn_check").hide()
document.getElementById("success-message").style.display = "none";
let isValid = true;
var errorMessage = "";
if (!$("input:radio[name=class_label]:checked").val()) {
console.log($("input:radio[name=class_label]:checked").val())
isValid = false;
errorMessage += 'Select the class label of the sample you want to use for the experiment.\n';
}
if (!document.getElementById("entries").value) {
console.log($('#entries').val())
isValid = false;
errorMessage += 'Select a sample.\n';
}
if (!isValid) {
event.preventDefault();
document.getElementById('error_message_new_x_2').style.display = 'block';
document.getElementById('error_message_new_x_2').textContent = errorMessage;
} else {
document.getElementById('error_message_new_x_2').style.display = 'none';
var class_label = $("input:radio[name=class_label]:checked").val();
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
var cfrow_id = document.getElementById("entries").value;
var model_name = "";
if (document.getElementById("classifier")) {
// class_label = $("input:radio[name=class_label]:checked").val();
model_name = document.getElementById("classifier").value
}
$("#ecg_data_container").hide();
if ($("#ecg_data_example")) {
$("#ecg_data_example").remove()
}
if ($("#ecg_cf")) {
$("#ecg_cf").remove();
$("#cf_ecg_container").hide();
}
$("#class_label_loader").show();
$.ajax({
method: 'POST',
url: '',
headers: { 'X-CSRFToken': csrftoken, },
data: { 'action': "class_label_selection", 'class_label': class_label, 'cfrow_id': cfrow_id, "model_name": model_name },
success: function (ret) {
$("#class_label_loader").hide();
var ret = JSON.parse(ret)
var fig = ret["fig"]
// create div elements for plots
var ecg_data_div = create_div("ecg_data_example", "plotly_fig")
ecg_data_div.insertAdjacentHTML('beforeend', fig);
$("#ecg_data_container").show();
$("#ecg_data").append(ecg_data_div);
$("#cfbtn_container").show()
$("#cfbtn").show()
},
error: function (ret) {
console.log(":(")
}
});
}
});
$('#constraint').change(function () {
$("#error_message_new_x").hide()
})
$('#new_x').click(function () {
// button new experiment is clicked
$("#new_experiment_details").show()
$("#cfbtn_container_2").show()
$("#class_label_container").hide()
$("#constraint_div").show()
$("#ecg_data_container").hide()
$("#cf_ecg_container").hide()
$("#cfbtn_container").hide()
$("#saved_experiments").hide()
})
$('#load_x').click(function () {
// button load experiment is clicked
$("#new_experiment_details").hide()
$("#saved_experiments").show()
// $("#class_label_container").show()
$("#error_message_new_x").hide()
})
$('.compute_counterfactual').click(function (event) {
// only for glacier
let isValid = true;
var errorMessage = "";
if (!$('#constraint').val()) {
isValid = false;
errorMessage += 'Please select a constraint.\n';
}
if (!isValid) {
event.preventDefault();
document.getElementById('error_message_new_x').style.display = 'block';
document.getElementById('error_message_new_x').textContent = errorMessage;
} else {
document.getElementById('error-message').style.display = 'hide';
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
var data_to_pass = {}
var constraint = ""
var w_value = ""
var model_name = ""
model_name = document.getElementById("classifier").value
if (model_name == "glacier") {
w_value = document.getElementById("slider").value
constraint = document.getElementById("constraint").value
}
data_to_pass = { "action": 'compute_cf', "constraint": constraint, 'w_value': w_value, 'model_name': model_name }
$("#cfbtn_2").hide()
$("#cfbtn_loader_2").show()
$.ajax({
method: 'POST',
url: '',
headers: { 'X-CSRFToken': csrftoken },
data: data_to_pass,
processData: true, // This should be `true` for form data
contentType: 'application/x-www-form-urlencoded; charset=UTF-8', // Standard form content type
success: function (ret) {
$("#no-precomputed").hide()
$("#cfbtn_loader_2").hide()
$("#cfbtn_2").show()
// add the new experiment in the list
var ret = JSON.parse(ret)
var experiment_dict = ret["experiment_dict"]
var outter_form_check = document.createElement("div")
outter_form_check.setAttribute("class", "form-check")
var input_element = document.createElement("input")
input_element.setAttribute("class", "form-check-input")
input_element.setAttribute("type", "radio")
input_element.setAttribute("name", "experiment")
input_element.setAttribute("value", experiment_dict["constraint"])
var label_element = document.createElement("label")
label_element.setAttribute("class", "form-check-label")
label_element.innerHTML = experiment_dict["constraint"]
outter_form_check.append(input_element)
outter_form_check.append(label_element)
$("#saved_experiments_elements").append(outter_form_check)
}
});
}
});
document.getElementById('saved_experiments_elements').addEventListener('change', function (event) {
// Check if a radio button is selected
if (document.querySelector('input[name="experiment"]:checked')) {
$("#error-message").hide()
}
});
if (document.getElementById('toggle-btn')) {
document.getElementById('toggle-btn').addEventListener('click', function () {
const dropdown = document.getElementById('dropdown-div');
const arrow = document.getElementById('toggle-btn');
if (dropdown.style.display === "none") {
// Expand the content
dropdown.style.display = "block";
arrow.classList.remove('rotate-down');
arrow.classList.add('rotate-up');
} else {
// Collapse the content
dropdown.style.display = "none";
arrow.classList.remove('rotate-up');
arrow.classList.add('rotate-down');
}
});
}
$('.run_counterfactual').click(function (event) {
// check if all the requirements are met
// run counterfactuals is the result of a load button click
// which leads to selection of pre computed experiments,
// class label and entri example
// all these should be selected otherwise error message
// #saved_experiments_elements
// #class_label
// #entries
let isValid = true;
let errorMessage = '';
if (!($("#class_label_container").css("display") === "none")) {
console.log(!$('input[name="class_label"]:checked').val())
if (!$('input[name="class_label"]:checked')) {
isValid = false;
errorMessage += 'Please select a class label and then an example entry.\n';
}
}
// Check if a radio button is selected
if (!($("#saved_experiments").css("display") === "none")) {
if (!$('input[name="experiment"]:checked').val()) {
isValid = false;
errorMessage += 'Please select an experiment.\n';
}
}
if (!($("#entries_container").css("display") === "none")) {
if ($('#entries').val() === '') {
isValid = false;
errorMessage += 'Please select example entry.\n';
}
}
if (document.getElementById("features_to_vary") && !($("#features_to_vary").css("display") === "none")) {
if (document.querySelectorAll('input[name="features_to_vary_boxes"]:checked').length === 0) {
isValid = false;
errorMessage += 'Please select features.\n';
}
}
// If not valid, show error message
if (!isValid) {
event.preventDefault();
document.getElementById('error-message').style.display = 'block';
document.getElementById('error-message').textContent = errorMessage;
} else {
document.getElementById('error-message').style.display = 'hide';
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
var data_to_pass = {}
var constraint = ""
var w_value = ""
var model_name = ""
var features_to_vary = []
if (document.getElementById("classifier")) {
model_name = document.getElementById("classifier").value
constraint = $("input:radio[name=experiment]:checked").val();
data_to_pass = { 'action': "cf", "constraint": constraint, "w_value": w_value, "model_name": model_name }
} else {
model_name = $("input:radio[name=modeling_options]:checked").val();
document.getElementsByName("features_to_vary_boxes").forEach(function (elem) {
if (elem.checked == true) {
features_to_vary.push(elem.value);
}
});
data_to_pass = { 'action': "cf", "features_to_vary": JSON.stringify(features_to_vary), "model_name": model_name }
}
// hide button and original point row
// replace with loader
$("#cfbtn_loader").show()
$("#cfbtn").hide()
$.ajax({
method: 'POST',
url: '',
headers: { 'X-CSRFToken': csrftoken },
data: data_to_pass,
processData: true, // This should be `true` for form data
contentType: 'application/x-www-form-urlencoded; charset=UTF-8', // Standard form content type
success: function (ret) {
$("#cfbtn_loader").hide()
// $("#cftable_container").hide()
// $("#cfbtn_container").hide()
// add <input type="reset" value="Reset">
if (!document.getElementById("reset")) {
var reset = document.createElement('input')
reset.setAttribute("id", "reset")
reset.setAttribute("type", "reset")
reset.setAttribute("value", "Reset")
$("#reset_div").append(reset)
$("#reset_div").show()
}
// load parameters
var ret = JSON.parse(ret)
var dataset_type = ret["dataset_type"]
if ("message" in ret) {
$("#cfbtn_container").show()
event.preventDefault();
document.getElementById('error-message').style.display = 'block';
document.getElementById('error-message').textContent = ret["message"];
} else {
if (dataset_type == "tabular") {
var tsne = ret["tsne"]
var num_counterfactuals = ret["num_counterfactuals"]
var clicked_point = ret["clicked_point"]
// $("#og_cf_row").show()
$("#cf_results").show()
// create tsne div
$("#tsne_enhanced_plot").remove()
var iDiv = create_div('tsne_enhanced_plot', 'plotly_fig');
iDiv.insertAdjacentHTML('beforeend', tsne);
$("#tsne_enhanced_container").append(iDiv);
$("#cfbtn").innerHTML = "Run again!"
$("#cfbtn").show()
// create counterfactuals list
var text_array = []
for (var i = 1; i <= num_counterfactuals; i++) {
text_array.push("Counterfactual " + i)
}
var value_array = []
for (var i = 0; i < num_counterfactuals; i++) {
value_array.push(i)
}
var cf_selection = create_selection(text_array, "counterfactuals_selection", value_array, null)
// add placeholder
var placeholder = document.createElement("option");
placeholder.value = "Pick a counterfactual...";
placeholder.text = "Pick a counterfactual...";
placeholder.disable = true;
placeholder.selected = true;
placeholder.hidden = true;
cf_selection.appendChild(placeholder);
// remove data if displayed
if (document.getElementById("counterfactuals_selection")) {
$("#counterfactuals_selection").remove();
}
// cf_selection
$("#cf_selection").append(cf_selection);
$("#og_cf_headers").show()
// clicked point data
var transposed_clicked_point = transpose_table(clicked_point)
var cp_tb = create_dataframe(transposed_clicked_point, "clicked_point")
cp_tb.setAttribute("style", "flex-direction: row; width: 100%;")
if (document.getElementById("clicked_point")) {
$("#clicked_point").remove();
}
// $("#original_data").append(cp_tb)
// $("#counterfactual").append(cf_tb);
}
else if (dataset_type == "timeseries") {
// ecg
$("#cfbtn_container").show();
$("#cfbtn").show()
var fig = ret["fig"]
var iDiv = document.createElement('div');
iDiv.id = 'ecg_cf';
iDiv.innerHTML = fig
iDiv.setAttribute("class", "plotly_fig")
if ($("#ecg_cf")) {
$("#ecg_cf").remove();
}
$("#cf_ecg_container").show();
$("#cf_ecg_data").append(iDiv);
}
$("#cfbtn_check").show()
document.getElementById("success-message").style.display = "block";
}
},
error: function (row) {
console.log("it didnt work");
}
});
}
});
if (document.getElementById('cf_selection')) {
document.getElementById('cf_selection').onchange = (event) => {
// counterfactuals id
var cf_id = event.target.value;
// inputText is the row id of the counter factual
// Send ajax request to backend and inquire for the
// respective counterfactual. When it is acquired
// replace current counterfactual view with that...
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
$("#run_counterfactual_loader").show();
$("#reset_div").hide();
$.ajax({
method: 'POST',
url: '',
headers: { 'X-CSRFToken': csrftoken },
data: { 'cf_id': cf_id, 'action': "counterfactual_select" },
success: function (ret) {
// stop loader
$("#cf_results").show()
$("#og_cf_row").show()
$("#run_counterfactual_loader").hide();
$("#reset_div").show();
var ret = JSON.parse(ret)
var row = ret["row"]
// var clicked_point = ret["clicked_point_differences"]
// counterfactual
var transposed_row = transpose_table(row)
var cf_tb = create_dataframe(transposed_row, "counterfactual_selected")
// // clicked point differences
// var transposed_clicked_point = transpose_table(clicked_point)
// var cp_tb = create_dataframe(transposed_clicked_point, "clicked_point_differences")
if (document.getElementById("counterfactual_selected")) {
$("#counterfactual_selected").remove();
}
if (document.getElementById("clicked_point_differences")) {
$("#clicked_point_differences").remove();
}
$("#counterfactual").append(cf_tb);
// add new tsne
var fig = ret["fig"]
if (document.getElementById("tsne_enhanced_plot")) {
$("#tsne_enhanced_plot").remove()
}
var iDiv = create_div('tsne_enhanced_plot', "plotly_fig");
iDiv.insertAdjacentHTML('beforeend', fig);
$("#tsne_enhanced_container").append(iDiv);
},
error: function (row) {
console.log("it didnt work");
}
});
}
}
});
$(document).ready(function () {
// Scroll the first element into view
if (document.getElementById("cfbtn_check")) {
$('#cfbtn_check').click(function (event) {
const enhanced = document.getElementById('enhanced');
if (enhanced) {
enhanced.scrollIntoView({ behavior: 'smooth' });
}
// Scroll the second element into view
const timeseriesCfGenerated = document.getElementById('timeseries_cf_generated');
if (timeseriesCfGenerated) {
timeseriesCfGenerated.scrollIntoView({ behavior: 'smooth' });
}
})
}
});
document.getElementById("learnMoreBtn").addEventListener("click", function () {
$('#glacierInfoModal').modal('show');
});