Skip to content

Commit

Permalink
Merge pull request #88 from Jai0212/Jai.TLI-101.e-Multiple-Model-Upload
Browse files Browse the repository at this point in the history
Jai/TLI 101.e -- Added ability to upload multiple model and fixed graphs
  • Loading branch information
armaganngul authored Nov 22, 2024
2 parents 101004c + c502d0e commit ba8c977
Show file tree
Hide file tree
Showing 15 changed files with 479 additions and 68 deletions.
Binary file modified .DS_Store
Binary file not shown.
Binary file modified backend/ml_model/model_with_score.pkl
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
352 changes: 352 additions & 0 deletions database/output.csv

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
width: 100%; /* Makes the chart take up full width of the container */
max-width: 800px; /* Limit the maximum width of the chart */
margin: 0 auto; /* Centers the chart horizontally */
padding: 20px;
padding-bottom: 14px;
padding-left: 14px;
padding-right: 38px;
padding-top: 20px;
box-sizing: border-box;
}

Expand Down
54 changes: 35 additions & 19 deletions frontend/src/pages/DashboardPage/ChartComponenet/ChartComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import React, {
useEffect,
useRef,
useImperativeHandle,
forwardRef,
useState,
} from "react";
import React, { useEffect, useRef, useImperativeHandle, forwardRef, useState } from "react";
import Chart from "chart.js/auto";
import "./ChartComponent.css";

Expand All @@ -20,7 +14,7 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {

// Step 1: Identify unique feature1 values and assign colors dynamically
const uniqueFeature1Groups = Array.from(
new Set(chartData.map((item) => item.feature1))
new Set(chartData.map((item) => item.feature1))
);
const colorPalette = [
"rgba(54, 162, 235, 0.7)",
Expand All @@ -35,7 +29,7 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {

// Step 2: Sort and prepare data for the chart
const sortedChartData = [...chartData].sort((a, b) =>
a.feature1.localeCompare(b.feature1)
a.feature1.localeCompare(b.feature1)
);

const labels = sortedChartData.map((item) => item.feature2); // Only feature2 labels
Expand All @@ -55,10 +49,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {
data: accuracyData.map((d) => ({ x: d.label, y: d.accuracy })),
backgroundColor: accuracyData.map((d) => d.color), // Bars are filled with the color for each feature1 group
borderColor: accuracyData.map(
(d) => (d.accuracy > sliderValue ? "rgba(255, 0, 0, 1)" : d.color) // Red border if above threshold, else use the same color as fill
(d) => (d.accuracy > sliderValue ? "rgba(255, 0, 0, 1)" : d.color) // Red border if above threshold, else use the same color as fill
),
borderWidth: accuracyData.map(
(d) => (d.accuracy > sliderValue ? 3 : 1) // Increased border width if above threshold, else default
(d) => (d.accuracy > sliderValue ? 3 : 1) // Increased border width if above threshold, else default
),
borderCapStyle: "round",
borderJoinStyle: "round",
Expand Down Expand Up @@ -102,11 +96,33 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {
offset: true,
display: false,
},
title: {
display: true, // Display the x-axis title
text: 'Demographics', // Set the x-axis label
font: {
size: 16, // Font size for the title
weight: 'bold', // Make the title bold
},
padding: {
top: 8, // Space above the title
},
},
},
y: {
min: 0,
max: 1,
beginAtZero: true,
title: {
display: true, // Display the y-axis title
text: 'Accuracy', // Set the y-axis label
font: {
size: 16, // Font size for the title
weight: 'bold', // Make the title bold
},
padding: {
bottom: 8, // Space below the title
},
},
},
},
responsive: true,
Expand Down Expand Up @@ -159,10 +175,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {
ctx.save();
ctx.fillStyle = "rgba(200, 200, 200, 0.3)";
ctx.fillRect(
left,
chartArea.top,
right - left,
chartArea.bottom - chartArea.top
left,
chartArea.top,
right - left,
chartArea.bottom - chartArea.top
);
ctx.restore();
},
Expand All @@ -181,10 +197,10 @@ const ChartComponent = forwardRef(({ chartData, sliderValue }, ref) => {
}));

return (
<div className="chart-container">
<canvas ref={chartRef} />
</div>
<div className="chart-container">
<canvas ref={chartRef} />
</div>
);
});

export default ChartComponent;
export default ChartComponent;
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ input[type="file"] {

/* Style for the Download Graph button */
.file-import-container button:nth-child(3) {
background-color: #45a049;
background-color: #0088cc;
color: #fafafa;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useImperativeHandle, forwardRef } from "react
import Chart from "chart.js/auto";
import './ChartComponent2.css';

const ChartComponent2 = forwardRef(({ chartData }, ref) => {
const ChartComponent2 = forwardRef(({ chartData, generationalResults }, ref) => {
const chartRef = useRef(null);
const myChartRef = useRef(null);

Expand All @@ -27,11 +27,49 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => {
ticks: {
autoSkip: false, // Ensure all x-axis labels are shown
},
title: {
display: true, // Show the title
text: 'Model Name', // Set the x-axis title
font: {
size: 15, // Increase the font size
weight: 'bold',
},
}
},
y: {
min: 0,
max: 1,
beginAtZero: true, // Ensure y-axis starts at zero
title: {
display: true, // Show the title
text: 'Bias', // Set the y-axis title
font: {
size: 15, // Increase the font size
weight: 'bold', // Make the text bold
},
},
},
},
plugins: {
tooltip: {
callbacks: {
label: (tooltipItem) => {
const index = tooltipItem.dataIndex; // Get the index of the hovered bar

// Access the generational result for the hovered bar
const generationalResult = generationalResults[index];

// Build the custom tooltip content using generationalResults data
return [
`Bias: ${tooltipItem.raw}`, // Bias value of the hovered bar
`Race: ${generationalResult.race}`,
`Gender: ${generationalResult.gender}`,
`Age: ${generationalResult.age_groups}`,
`State: ${generationalResult.state}`,
`Variance: ${generationalResult.variance}`,
];
},
},
},
},
},
Expand All @@ -42,7 +80,7 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => {
myChartRef.current.destroy(); // Cleanup on component unmount
}
};
}, [chartData]);
}, [chartData, generationalResults]);

useImperativeHandle(ref, () => ({
downloadChart() {
Expand All @@ -60,4 +98,4 @@ const ChartComponent2 = forwardRef(({ chartData }, ref) => {
);
});

export default ChartComponent2;
export default ChartComponent2;
68 changes: 39 additions & 29 deletions frontend/src/pages/ModelTester/ControlButtons2/ControlButtons2.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ const ControlButton2 = ({ setUploadedFiles }) => {

if (!files.length) return; // If no files are selected, exit

if (uploadedFiles.length === 5) {
alert("You can only upload 5 models at a time.");
if (uploadedFiles.length === 5 || uploadedFiles.length + files.length > 5) {
alert("You can only upload 5 models.");
return;
}

Expand All @@ -80,33 +80,41 @@ const ControlButton2 = ({ setUploadedFiles }) => {

for (let i = 0; i < files.length; i++) {
const file = files[i];
if (!file.name.endsWith(".pkl")) {
alert("Please upload a model in .pkl format.");
return;
}

if (!currUser || !file) {
alert("Error: Missing required data.");
return;
}

if (uploadedFiles.includes(file.name)) {
if (!file.name.endsWith(".pkl")) {
alert("Please upload a model in .pkl format.");
return;
}

if (newUploadedFiles.includes(file.name)) {
alert(`File with name ${file.name} already uploaded.`);
continue;
return;
}

if (file.name === "model.pkl") {
alert("You cannot upload a file named model.pkl.");
continue;
return;
}

const formData = new FormData();
formData.append("curr_user", currUser);
formData.append("model_file", file);
formData.append("dashboard", file.name);
newUploadedFiles.push(file.name);
}

// Prepare for the file upload
const uploadedFilesToPush = [...uploadedFiles];

try {
// Make a POST request to upload models
const uploadPromises = Array.from(files).map(async (file) => {
const formData = new FormData();
formData.append("curr_user", currUser);
formData.append("model_file", file);
formData.append("dashboard", file.name);

try {
// Make a POST request to upload model
const response = await fetch(`${VITE_BACKEND_URL}/api/upload-model`, {
method: "POST",
body: formData,
Expand All @@ -121,25 +129,27 @@ const ControlButton2 = ({ setUploadedFiles }) => {

const responseData = await response.json();
console.log("Success:", responseData.message);
alert("Model uploaded successfully!");

// Add the file to the list of uploaded files
newUploadedFiles.push(file.name);
uploadedFilesToPush.push(file.name); // Add to local list of uploaded files
});

// Update the state with the new list of uploaded files
setUploadedFiles(newUploadedFiles);
setUploadedFilesState(newUploadedFiles); // Update local state
// Wait for all files to be uploaded
await Promise.all(uploadPromises);

// Save the new list to localStorage
localStorage.setItem("uploadedFiles", JSON.stringify(newUploadedFiles));
// Update the state with the new list of uploaded files
setUploadedFiles(uploadedFilesToPush);
setUploadedFilesState(uploadedFilesToPush); // Update local state

// Reset the file input after uploading
event.target.value = null;
// Save the new list to localStorage
localStorage.setItem("uploadedFiles", JSON.stringify(uploadedFilesToPush));

} catch (error) {
console.error("Error during model upload:", error);
alert("Error during model upload: " + error.message);
}
// Reset the file input after uploading
event.target.value = null;

alert("Model(s) uploaded successfully!");
} catch (error) {
console.error("Error during model upload:", error);
alert("Error during model upload: " + error.message);
}
};

Expand Down
16 changes: 7 additions & 9 deletions frontend/src/pages/ModelTester/Dashboard2/Dashboard2.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ const Dashboard2 = () => {
const [currUser, setCurrUser] = useState("");

const backgroundColours = [
"#00CC00", // Darker bright green 1
"#66CC66", // Darker bright green 2
"#66FF66", // Bright green 3 (unchanged)
"#99CC99", // Darker bright green 4
"#99FF99", // Bright green 5 (unchanged)
"#FF5733", // Vibrant Red
"#33FF57", // Vibrant Green
"#3357FF", // Vibrant Blue
"#F3F33B", // Bright Yellow
"#F33BF3", // Bright Purple
];

const [graphData, setGraphData] = useState({
labels: ["Model 1", "Model 2", "Model 3", "Model 4", "Model 5"],
datasets: [
{
label: "Models",
label: "Bias",
data: [0, 0, 0, 0, 0],
backgroundColor: backgroundColours,
},
Expand All @@ -30,8 +30,6 @@ const Dashboard2 = () => {

const [uploadedFiles, setUploadedFiles] = useState([]);

const tempUploadedFiles = ['model1', 'model2', 'model3', 'model4', 'model5'];

const [generationResults, setGenerationResults] = useState([]);

const fetchEmailAndDemographics = async () => {
Expand Down Expand Up @@ -188,7 +186,7 @@ const Dashboard2 = () => {

<div className="chart-section">
{Object.keys(graphData).length > 0 && (
<ChartComponent2 chartData={graphData} />
<ChartComponent2 chartData={graphData} generationalResults={generationResults} />
)}
</div>
</div>
Expand Down
6 changes: 0 additions & 6 deletions package-lock.json

This file was deleted.

0 comments on commit ba8c977

Please sign in to comment.