310 lines
13 KiB
JavaScript
Executable File
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
|
|
});
|
|
|
|
});
|
|
|
|
|