Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jai/TLI 101.e -- Added ability to upload multiple model and fixed graphs #88

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
Binary file modified backend/ml_model/model_with_score.pkl
Binary file not shown.
armaganngul marked this conversation as resolved.
Show resolved Hide resolved
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good! can we do this for chart component1 as well?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I already did that!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great thank you!

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these colors need to change (I assume the CSS will handle that?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, this is just placeholder, we need to revamp the entire theme and layout of this page

"#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} />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain what generationalResults const do?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a variable for storing the tooltip hover data for each bar of the graph

)}
</div>
</div>
Expand Down
6 changes: 0 additions & 6 deletions package-lock.json

This file was deleted.