diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..75a7044
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,6 @@
+# AI-Fibrosis Project Instructions
+
+## Project Structure
+- **Frontend:** Located in `/NAFLD/javascript/nafld-app/`. Built with React.
+- **Backend:** Located in `/NAFLD/src/py-src/`. Built with Flask.
+- **AI Models:** Located in `/NAFLD/src/py-src/models/`.
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 0248d26..dad7ce2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,4 +169,11 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
\ No newline at end of file
+#.idea/
+
+# Project-specific ignores
+Reduc/
+PCAtests/
+ClusterDiagnostic/
+NAFLD/src/py-src/users.db
+NAFLD/src/py-src/.jwt_secret
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..6f3a291
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "liveServer.settings.port": 5501
+}
\ No newline at end of file
diff --git a/NAFLD/javascript/nafld-app/public/faviconliver.png b/NAFLD/javascript/nafld-app/public/faviconliver.png
new file mode 100644
index 0000000..13aee99
Binary files /dev/null and b/NAFLD/javascript/nafld-app/public/faviconliver.png differ
diff --git a/NAFLD/javascript/nafld-app/public/index.html b/NAFLD/javascript/nafld-app/public/index.html
index 8d1e67f..b7cc747 100644
--- a/NAFLD/javascript/nafld-app/public/index.html
+++ b/NAFLD/javascript/nafld-app/public/index.html
@@ -2,14 +2,14 @@
◀ ▶ magnifying glass threshold adjustments apply to the area under observation only
+
+
+ ▲
+ Zoom In
+
+
+ ▼
+ Zoom Out
+
+
+ ◀
+ − Threshold
+
+
+ ▶
+ + Threshold
+
+
+ Ctrl+Z
+ Undo
+
+
+ Ctrl+R
+ Reset Area
+
+
+
+ ) : (
+
+ {algorithm === 'unet' ? (
+ <>
+
+ Visualization & Extent: The heatmap shows Tiny U-Net Round 1 fibrosis probability across the uploaded image.
+
+
+ Staging: Disease category is classified from the U-Net mask using the same VGG16, PCA, and Fuzzy C-Means classifier.
+
+ >
+ ) : (
+ <>
+
+ Visualization & Extent: White pixels indicate detected collagen fibers
+ isolated via colour deconvolution and adaptive thresholding.
+
+
+ Staging: Disease category is classified by analyzing the
+ architectural patterns of these fibers using a VGG16 neural network and Fuzzy C-Means clustering.
+
+ You have made fine area adjustments that will be
+ reset to a general threshold. This cannot be undone.
+
+
Press Esc to cancel
+
+
+
+
+
+
+ )}
+
+ {showHelp && (
+
setShowHelp(false)}>
+
e.stopPropagation()}>
+
+
How to Use fibrosisai
+
+
+
Analysis
+
Upload an image (SVS, TIF, JPG, PNG, BMP) by clicking or dragging into the left panel. The AI pipeline will automatically extract collagen fibers via colour deconvolution and compute a fibrosis extent percentage. The original image appears on the left and the fibrosis mask on the right.
+
+
+
+
Baseline Threshold
+
After analysis, the right panel provides a Baseline Threshold slider and number field. This controls the global sensitivity for detecting fibrosis. Once you set a baseline you are happy with, stick to fine area adjustments rather than changing the baseline again. Changing the baseline resets all area edits. Use Reset to baseline AI estimate only for a full reset.
+
+
+
+
Magnifying Glass & Fine Adjustments
+
Hover over the original image to activate the magnifying glass. Use arrow keys to zoom and adjust the threshold for just the area under observation:
+
+
▲▼ Zoom in / out
+
◀▶ Decrease / increase area threshold
+
Q Inspect area and instantly compute extent (left lens) and stage classification (right lens) for the region under the magnifier. Auto-cancels when the cursor moves.
+
Ctrl+R Reset observed area to original threshold
+
Ctrl+Z Undo all increments made to the last modified area
+
Esc Close overlays
+
+
+
+
+
Mini-Map
+
When area adjustments are made, a Modified Areas Map appears in the diagnosis panel showing which regions have been modified (green) vs. the original AI threshold (white). The map updates live as you undo or reset regions.
+
+
+
+
Diagnose
+
Classification is a separate step from analysis. Once you have refined the fibrosis mask to your satisfaction, click Diagnose to run VGG16 feature extraction and Fuzzy C-Means clustering on the refined mask. For large images, each tile is classified individually and results are averaged from the most severe patches.
+
After diagnosis, a radar chart shows probabilistic membership across four fibrosis stages. Use Re-diagnose after making further threshold adjustments. Analyze Patch Results highlights the five most severe tiles on the mask image with red outlines.
+
+
+
+
Exports
+
Download CSV exports the fibrosis percentage and classification scores (when available). Save Mask downloads the current fibrosis mask image (including any threshold adjustments).
+
+
+
Press Esc to close
+
+
+ )}
+
);
-}
-
-export default ImageSubmission;
\ No newline at end of file
+};
+
+export default ImageSubmission;
diff --git a/NAFLD/javascript/nafld-app/src/Login.js b/NAFLD/javascript/nafld-app/src/Login.js
new file mode 100644
index 0000000..1bbf461
--- /dev/null
+++ b/NAFLD/javascript/nafld-app/src/Login.js
@@ -0,0 +1,299 @@
+import { useState } from "react";
+
+const API_BASE = process.env.REACT_APP_API_URL || "http://127.0.0.1:5000";
+
+const FEATURES = [
+ { title: "Colour Deconvolution", desc: "Isolates collagen fibers from PSR-stained tissue via optical density separation" },
+ { title: "Adaptive Thresholding", desc: "Automatically determines the optimal binary threshold to quantify fibrosis extent" },
+ { title: "Interactive Refinement", desc: "Fine-tune the fibrosis mask with a magnifying glass, per-area threshold adjustments, and live mini-map" },
+ { title: "VGG16 Deep Features", desc: "Extracts high-level architectural patterns from tissue patches using a pretrained CNN" },
+ { title: "Fuzzy C-Means Staging", desc: "Classifies the refined mask into probabilistic stages with worst-patch analysis" },
+];
+
+const Login = ({ onLogin }) => {
+ const [username, setUsername] = useState("");
+ const [password, setPassword] = useState("");
+ const [error, setError] = useState("");
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ setError("");
+
+ if (!username.trim() || !password) {
+ setError("Username and password are required.");
+ return;
+ }
+
+ setIsLoading(true);
+ try {
+ const res = await fetch(`${API_BASE}/login`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ username: username.trim(), password }),
+ });
+ const data = await res.json();
+ if (!res.ok) {
+ setError(data.error || "Login failed.");
+ return;
+ }
+ sessionStorage.setItem("access_token", data.access_token);
+ sessionStorage.setItem("refresh_token", data.refresh_token);
+ sessionStorage.setItem("username", data.username);
+ onLogin(data.username);
+ } catch (err) {
+ setError("Unable to connect to the server.");
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return (
+
+ {/* Network constellation background */}
+
+
+
+ {/* Left panel -- feature showcase */}
+
+
+
fibrosisai
+
AI-powered unsupervised classification and quantification of liver fibrosis