Skip to content

Sampo-AI-OS/fractal-scope

Repository files navigation

FractalScope — Material Pore Analysis Platform

Python FastAPI SQLAlchemy Docker Tests

Fractal dimension analysis platform for composite material microstructure research. Built to support the study of pore evolution in eco-friendly curing agent and cement-stabilised loess composites.

This repository is a curated public edition created for the Sampo AI OS portfolio. It is intended to be a clean, reviewable product showcase rather than a raw copy of the original internal working folder.

See PUBLIC_EDITION_SCOPE.md for what is included here and what was intentionally excluded from the original source project.

Interface Snapshot

FractalScope UI

Scientific basis: Dynamic Response and Pore Evolution Mechanism of Composite Improved Loess Using an Eco-Friendly Curing Agent and Cement — Tianshui Normal University


What is this?

FractalScope computes the box-counting fractal dimension (D) of composite material microstructures from SEM/TEM images. The D-value is a single number (1.0–3.0) that quantifies the geometric complexity of a material's pore network — a higher D means a denser, more interconnected microstructure.

D range Classification Meaning
< 1.7 Linear Structure Weakly cemented, minimal porosity branching
1.7–2.0 Porous Network Natural loess, lightly treated composites
2.0–2.4 Composite Matrix Cement-stabilised with interlocking pore networks
> 2.4 Dense Composite Full hydration, hierarchical pore collapse

Who is this for?

  • Materials scientists studying composite soil stabilisation
  • Civil engineers researching eco-friendly curing agents
  • R&D labs working on loess, ceramics, or polymer microstructure characterisation

Architecture

┌─────────────────────────────────────────────────────┐
│  Browser (React 18 + D3.js)                         │
│  • Material catalogue with auto-generated IDs       │
│  • SEM/TEM image drop-zone                          │
│  • D3 gauge + trend chart                           │
└──────────────────┬──────────────────────────────────┘
                   │ HTTP
┌──────────────────▼──────────────────────────────────┐
│  FastAPI (main.py)                                  │
│  GET  /           → SPA frontend                    │
│  GET  /health     → status check                    │
│  POST /analyze/{id}          → simulation mode      │
│  POST /analyze-image/{id}    → real image mode      │
└──────┬───────────────────────┬──────────────────────┘
       │                       │
┌──────▼──────┐    ┌───────────▼────────────────────┐
│ fractal_    │    │ FractalAnalysisService.py       │
│ analysis.py │    │ • Simulation fallback           │
│ • PIL/OpenCV│    │ • DB persistence (SQLAlchemy)   │
│ • Otsu      │    └───────────┬────────────────────┘
│   threshold │                │
│ • Box-      │    ┌───────────▼────────────────────┐
│   counting  │    │ material_metadata.py            │
│ • log-log   │    │ • Material ORM model            │
│   regression│    │ • SQLite (dev) / PostgreSQL     │
└─────────────┘    └────────────────────────────────┘

Quick Start

Local development (recommended)

# 1. Clone and enter project
cd fractal-scope

# 2. Create virtual environment
python -m venv .venv
.venv\Scripts\activate          # Windows
# source .venv/bin/activate     # Linux/macOS

# 3. Install dependencies
pip install -r requirements.txt

# 4. Run tests
pytest tests/ -v

# 5. Start server
uvicorn main:app --host 0.0.0.0 --port 8000 --reload \
  --reload-dir . --reload-exclude ".venv"

Open http://localhost:8000 in your browser.

Supported Python version for the reproducible local and Docker path is currently 3.11+.

Docker (production with PostgreSQL)

docker compose up --build

The app starts on port 8000, PostgreSQL on port 5432. The app waits for the database healthcheck before starting.

If those host ports are already in use, override them without editing the compose file:

$env:APP_PORT=18000
$env:DB_PORT=15432
docker compose up --build

The container still listens internally on ports 8000 and 5432. Only the host-side bindings change.

docker compose down       # stop
docker compose down -v    # stop + delete database volume

Using the Application

1. Select material type

Choose from the Material Catalogue dropdown in the sidebar. The ID is auto-generated in a standardised format:

Preset ID format example
Untreated Loess LOESS-NAT-001
Cement-Stabilised Loess LOESS-CEM-001
Eco-Agent Treated Loess LOESS-ECO-5PCT-001
Eco-Agent + Cement LOESS-ECO-CEM-5PCT-001
Ceramic Matrix CER-001
Custom manually entered

For eco-agent presets, set the concentration slider (0–20%) to match your specimen.

2. Attach a SEM/TEM image (optional)

Drop a greyscale or colour SEM/TEM image onto the drop zone, or click to browse. Supported formats: PNG, TIFF, JPG, BMP.

  • With image: real box-counting analysis via OpenCV + NumPy → result badge shows Real Image
  • Without image: random simulation for demonstration → badge shows Simulation

3. Add lab notes

Optional free-text field for curing conditions, temperature, loading frequency etc. The notes are shown in the current browser session and included in the local Recent Analyses view.

4. Run analysis

Click 🔬 Analyze SEM Image (or Run Simulation). Results appear immediately:

  • Gauge needle moves to computed D-value
  • Classification chip and interpretation text update
  • Entry added to the local Recent Analyses history in the UI
  • Fractal result persisted to the database

Project Structure

├── main.py                    # FastAPI app, endpoint routing
├── fractal_analysis.py        # Core algorithm: image load → box-counting → D
├── FractalAnalysisService.py  # Service layer: simulation + DB persistence
├── material_metadata.py       # SQLAlchemy ORM: Material table schema
├── requirements.txt           # Pinned production dependencies
├── pytest.ini                 # pytest configuration (asyncio_mode=auto)
├── Dockerfile                 # Production container image
├── docker-compose.yml         # App + PostgreSQL orchestration
├── frontend/
│   └── index.html             # Single-page app (React 18 + D3.js v7)
├── tests/
│   ├── test_fractal.py        # Unit tests: image loading, box-counting
│   └── test_analysis.py       # Integration tests: service + SQLite

API Reference

Method Endpoint Description
GET / Serves the frontend SPA
GET /health {"status": "ok"}
GET /docs Swagger UI (auto-generated)
POST /analyze/{material_id} Simulation analysis, persists to DB
POST /analyze-image/{material_id} Real image analysis (multipart/form-data, field: file)

Example — image upload via curl:

curl -X POST "http://localhost:8000/analyze-image/LOESS-NAT-001" \
  -F "file=@sample_sem.png"
# → {"material_id": "LOESS-NAT-001", "fractal_dim": 1.87, "source": "image"}

Running Tests

pytest tests/ -v

The current curated public edition passes 6 automated tests.

Tests use SQLite in-memory — no database setup required.


Roadmap: How to Make This a Useful Research Tool

The current implementation is a working demo. Below are the concrete next steps to turn it into a production research tool, roughly in priority order.

Phase 1 — Real image pipeline (highest impact)

  • AI-assisted segmentation — replace Otsu thresholding with a lightweight U-Net or scikit-image morphological_chan_vese to better separate pore space from solid matrix in noisy SEM images
  • Multi-scale box-counting — extend box sizes beyond 8–64px to cover the full image resolution; currently only 4 data points are used for the log-log regression
  • Batch upload — accept a ZIP of images for a single specimen, average the D-values, report standard deviation
  • Image preview in UI — show the uploaded image alongside its binarised version so the researcher can verify segmentation quality before accepting the result

Phase 2 — Data management

  • Export to CSV/Excel — download all analysis results with metadata for use in statistical analysis (R, SPSS, Origin)
  • Export to PDF report — auto-generated per-specimen report with gauge, interpretation, and lab notes
  • Specimen comparison view — side-by-side D-value comparison across multiple IDs (e.g. 0% vs 5% vs 10% eco-agent concentration)
  • Database migrations — add Alembic for schema versioning so production data survives upgrades

Phase 3 — Scientific validation

  • Calibration mode — upload images with known D-values (synthetic fractals) to validate algorithm accuracy
  • Literature reference values — display expected D-range for each material type based on published papers
  • Uncertainty estimation — report confidence interval on D using bootstrap resampling across box sizes
  • Correlation with mechanical properties — if stress-strain data is available, show scatter plot of D vs. compressive strength

Phase 4 — Collaboration & deployment

  • User authentication — simple API key or OAuth2 so multiple researchers can share the same instance without overwriting each other's results
  • Project/experiment grouping — organise analyses into named experiments (e.g. "28-day curing series")
  • Public cloud deployment — Dockerfile + docker-compose are ready; configure a reverse proxy (Nginx/Caddy) with HTTPS for institutional access
  • Federated data — allow partner institutions to contribute results without sharing raw images (privacy-preserving)

Dependencies

Package Version Purpose
fastapi 0.111.0 REST API framework
uvicorn 0.29.0 ASGI server
sqlalchemy 2.0.36 ORM, database abstraction
numpy 2.4.4 Numerical array operations
Pillow 12.2.0 Image loading
opencv-python 4.13.0.92 Otsu thresholding, image preprocessing
psycopg2-binary 2.9.7 PostgreSQL driver (production)
aiofiles 23.2.1 Async file I/O
python-multipart 0.0.9 Multipart file upload parsing
pytest + pytest-asyncio latest Test framework

Scientific Background

The fractal dimension D is computed using the box-counting method:

$$D = -\lim_{\epsilon \to 0} \frac{\log N(\epsilon)}{\log \epsilon}$$

where $N(\epsilon)$ is the number of boxes of side length $\epsilon$ needed to cover the structure. In practice, a log-log linear regression is fitted across box sizes [8, 16, 32, 64] pixels:

$$D \approx -\text{slope}\left(\log \epsilon,\ \log N(\epsilon)\right)$$

The image is first converted to a binary mask using Otsu's method (OpenCV), which automatically finds the optimal threshold to separate pore space (black) from solid matrix (white) without manual parameter tuning.

Reference range for loess composites (from the source paper):

  • Untreated loess: D ≈ 1.85–2.05
  • Cement-stabilised (7%): D ≈ 2.15–2.35
  • Eco-agent + cement: D ≈ 2.30–2.55

Public Release Note

This repository is the curated public edition prepared for publication. The original working project contained additional internal staging materials that were intentionally excluded from this copy.

About

Material pore analysis platform for fractal-dimension estimation from SEM and related microstructure images.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages