310 lines
13 KiB
JavaScript
Executable File

// train a new model
import { create_dataframe, create_div } from './methods.js'
$(document).ready(function () {
document.getElementById("classifier").addEventListener("change", function (e) {
var classifier = document.getElementById("classifier").value
const checkboxes = document.querySelectorAll('.form-check-input');
if (classifier == "wildboar_knn" || classifier == "wildboar_rsf") {
// Loop through each checkbox and disable it
$("#parameters_div").hide()
$("#preprocessing").show()
$("#ratio").show()
$("#autoencoder_div").hide()
}
if (classifier == "glacier") {
// Loop through each checkbox and disable it
$("#parameters_div").show()
$("#ratio").hide()
$("#preprocessing").hide()
$("#autoencoder_div").show()
}
});
$('.train_test').click(function () {
const classifier = document.getElementById("classifier").value;
const errorMessage = $("#error_message_new_x_2");
let array_preprocessing = [];
let test_set_ratio, class_label, autoencoder;
let data_to_pass = {};
// Helper function to show errors
function showError(message) {
errorMessage.text(message);
errorMessage.show();
}
// Helper function to get checked values of checkboxes by name
function getCheckedValues(name) {
return Array.from(document.getElementsByName(name))
.filter((elem) => elem.checked)
.map((elem) => elem.value);
}
// Check if a classifier is selected
if (!classifier) {
// Show loader while training
showError("Please select a classifier before proceeding.");
return;
}
// Check if at least one preprocessing checkbox is checked
const anyPreprocessingChecked = getCheckedValues("boxes").length > 0;
if (!anyPreprocessingChecked && classifier !== "glacier") {
showError("Please select at least one preprocessing option.");
return;
}
// Hide the error message if validations pass
errorMessage.hide();
$("#train_test_btn").hide()
// Show loader while training
$("#loader_train").removeClass("d-none").show();
// Set up data to pass based on classifier
if (classifier === "glacier") {
autoencoder = document.getElementById("autoencoder").value;
data_to_pass = {
action: "train",
model_name: classifier,
autoencoder: autoencoder
};
} else {
test_set_ratio = document.getElementById("slider").value;
class_label = document.getElementById("class_label_train")?.value || "";
array_preprocessing = getCheckedValues("boxes");
data_to_pass = {
action: "train",
model_name: classifier,
test_set_ratio: test_set_ratio,
array_preprocessing: JSON.stringify(array_preprocessing),
class_label: class_label
};
}
// AJAX request for training
const csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
$.ajax({
method: 'POST',
url: '',
headers: { 'X-CSRFToken': csrftoken },
data: data_to_pass,
processData: true,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function (ret) {
$("#loader_train").hide();
try {
$("#train_test_btn").show()
// if they already exist, remove them and update them
if (document.getElementById("principle_component_analysis")) {
$("#principle_component_analysis").remove();
}
if (document.getElementById("class_report")) {
$("#class_report").remove();
}
if (document.getElementById("feature_importance")) {
$("#feature_importance").remove();
}
if (document.getElementById("classifier_data")) {
$("#classifier_data").remove();
}
if (document.getElementById("tsne_plot")) {
$("#tsne_plot").remove();
}
var ret = JSON.parse(ret)
// Parse successful response data
const class_report = ret["class_report"];
const classifier_data = ret["classifier_data"];
const pca = ret["pca"];
const dataset_type = ret["dataset_type"];
$("#tab").show();
if (dataset_type == "timeseries") {
// For timeseries datasets
const tsne = ret["tsne"];
$("#tsne-tab-nav").show();
const col_div_tsne = create_div("tsne_plot", "plotly_fig");
col_div_tsne.insertAdjacentHTML('beforeend', tsne);
$("#tsne_container").append(col_div_tsne);
} else {
// For other datasets
$("#feature-tab-nav").show();
const feature_importance = ret["feature_importance"];
const col_div_fi = create_div("feature_importance", "plotly_fig");
col_div_fi.insertAdjacentHTML('beforeend', feature_importance);
$("#fi_container").append(col_div_fi);
}
// Create and append dataframes
const tb = create_dataframe(classifier_data, "details_container");
const cr_tb = create_dataframe(class_report, "cr_container");
// Create and append plots
const col_div_pca = create_div("principle_component_analysis", "plotly_fig");
col_div_pca.insertAdjacentHTML('beforeend', pca);
const col_div_class_report = create_div("class_report", "plotly_fig sticky-top-table");
col_div_class_report.append(cr_tb);
const col_div_classifier_data = create_div("classifier_data", "plotly_fig sticky-top-table");
col_div_classifier_data.append(tb);
// Append content to modal tabs
$("#classification_report").append(col_div_class_report);
$("#details").append(col_div_classifier_data);
$("#pca_container").append(col_div_pca);
// Show modal for analysis
$("#modelAnalysisModal").modal("show");
} catch (e) {
console.error("Error processing response:", e);
$("#modelAnalysisModal").modal("show");
}
},
error: function (ret) {
$("#loader_train").hide();
// Prepare error message
const errorMessage = $("#error_message_new_x_2");
const errorMessageText = $("#error_message_text");
let backendErrorMessage = "An error occurred."; // Default message
try {
if (ret.responseJSON && ret.responseJSON.message) {
backendErrorMessage = ret.responseJSON.message + ret.responseJSON.line;
} else if (ret.responseText) {
const parsedResponse = JSON.parse(ret.responseText);
backendErrorMessage = parsedResponse.message || backendErrorMessage;
}
} catch (e) {
console.error("Error parsing error response:", e);
backendErrorMessage = ret.responseText || "Unknown error.";
}
// Display error message and trigger modal
errorMessageText.text(backendErrorMessage);
errorMessage.show();
}
});
});
document.getElementById("discard-model").addEventListener("click", function () {
// Append a confirmation message to the modal
const modalBody = document.querySelector("#modelAnalysisModal .modal-body");
const messageContainer = document.createElement("div");
messageContainer.id = "discard-message";
messageContainer.className = "alert"; // Bootstrap class for alert styles
// Add a message to confirm the user's decision
messageContainer.classList.add("alert-warning");
messageContainer.innerHTML = `
<i class="fas fa-exclamation-triangle mr-2"></i>
Are you sure you want to discard this model? This action cannot be undone.
<div class="mt-3">
<button id="confirm-discard" class="btn btn-danger btn-sm">Yes, Discard</button>
<button id="cancel-discard" class="btn btn-secondary btn-sm">Cancel</button>
</div>
`;
modalBody.appendChild(messageContainer);
// Add event listeners for confirm and cancel buttons
document.getElementById("confirm-discard").addEventListener("click", function () {
// Data to send in the AJAX request
const data = { action: "discard_model" };
// Fetch CSRF token (assuming Django or similar framework)
const csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
// Send AJAX POST request to the backend
$.ajax({
method: "POST",
url: "", // Replace with your actual backend URL
headers: { "X-CSRFToken": csrftoken }, // Include CSRF token
data: data,
success: function (response) {
// Update the modal with a success message
messageContainer.classList.remove("alert-warning");
messageContainer.classList.add("alert-success");
messageContainer.innerHTML = `
<i class="fas fa-check-circle mr-2"></i>
The model has been successfully discarded.
`;
// Optionally close the modal after a delay
setTimeout(() => {
$("#modelAnalysisModal").modal("hide");
// Optionally refresh the page or update UI
// location.reload(); // Uncomment to refresh the page
}, 2000);
},
error: function (xhr) {
// Update the modal with an error message
messageContainer.classList.remove("alert-warning");
messageContainer.classList.add("alert-danger");
const errorMessage = xhr.responseJSON?.message || "An error occurred while discarding the model.";
messageContainer.innerHTML = `
<i class="fas fa-times-circle mr-2"></i>
Failed to discard the model: ${errorMessage}.
`;
},
});
});
// Cancel discard operation
document.getElementById("cancel-discard").addEventListener("click", function () {
// Remove the confirmation message
modalBody.removeChild(messageContainer);
});
});
document.getElementById("save-model").addEventListener("click", function () {
// Get the modal body element
const modalBody = document.querySelector("#modelAnalysisModal .modal-body");
// Create a confirmation message container
const confirmationMessage = document.createElement("div");
confirmationMessage.className = "alert alert-success mt-3"; // Bootstrap alert styles
confirmationMessage.innerHTML = `
<i class="fas fa-check-circle mr-2"></i>
The model has been successfully saved!
`;
// Clear existing content in the modal body (optional)
modalBody.innerHTML = "";
// Append the confirmation message to the modal body
modalBody.appendChild(confirmationMessage);
// Set a timeout to hide the modal after showing the message
setTimeout(() => {
$("#modelAnalysisModal").modal("hide");
// Optionally reset the modal body content after hiding
setTimeout(() => {
modalBody.innerHTML = `
<div class="alert alert-info">
<i class="fas fa-info-circle mr-2"></i>
After training your model/classifier, you should now decide whether to <strong>keep</strong> it or <strong>discard</strong> it based on its performance metrics and visualizations below.
</div>
<!-- Tabs Navigation and other content here -->
`;
}, 500); // Small delay to ensure the modal is fully hidden before resetting
}, 2000); // Hide the modal after 2 seconds
});
});