Before running MaterialGraph, ensure the following are installed:
- Python 3.11+
- PostgreSQL 15+
- Git
- Docker (required for the local Gitleaks pre-commit hook)
- Materials Project API Key
git clone https://github.com/MaterialGraph/materialgraph.git
cd materialgraphpython -m venv .venvActivate:
Windows
.venv\Scripts\activateLinux / macOS
source .venv/bin/activatepip install -r requirements.txt
pip install --no-deps -e .MaterialGraph uses Gitleaks as a defense-in-depth control against accidental credential commits.
The repository includes a version-controlled pre-commit hook in:
.githooks/pre-commit
After cloning the repository, enable the project hooks:
git config core.hooksPath .githooksVerify:
git config --get core.hooksPathExpected:
.githooks
The pre-commit hook scans staged changes with Gitleaks before Git creates a commit. A detected potential secret, or a failed scan, blocks the commit.
The scanner image is pinned by immutable digest, receives a read-only repository
mount, and runs without container networking. The reviewed update procedure is
documented in ../security/AUTOMATION_PINNING.md.
The hook currently runs Gitleaks through Docker, so Docker must be available when committing from a development environment.
Secret scanning also runs independently in GitHub Actions on pushes and pull requests. The CI scan provides a second layer of protection and does not replace the local pre-commit check.
Do not bypass a secret-scanning failure merely to complete a commit. Determine whether the finding is a real credential or a false positive before changing the scanner configuration.
Create a .env file:
DATABASE_URL=postgresql+psycopg://postgres:postgres@localhost/materialgraph
MATERIALS_PROJECT_API_KEY=your_materials_project_api_keyDATABASE_URL is required by the application and is also Alembic's default
migration target. A deployment may additionally set
DATABASE_MIGRATION_URL when migrations require a separate direct connection;
Alembic prefers that value when both variables are present. If neither database
variable is configured, migration commands fail without selecting a fallback
database.
The .env file is local configuration and must never be committed.
Use .env.example to document required variable names without storing credentials. Never place production passwords, API keys, access tokens, or connection strings containing real credentials in tracked files.
Before committing environment-related changes, verify:
git status --short
git ls-files -- .env.env must not appear as a tracked file.
PostgreSQL:
CREATE DATABASE materialgraph;alembic upgrade headMaterialGraph separates source acquisition from database writes. First build a
deterministic manifest. This requires MATERIALS_PROJECT_API_KEY but does not
write to the database:
Read the current source release before choosing the expected value (this makes one metadata request and does not fetch material records):
python -c "import os; from dotenv import load_dotenv; from mp_api.client import MPRester; load_dotenv(); print(MPRester(os.environ['MATERIALS_PROJECT_API_KEY']).get_database_version())"python -m scripts.import_materials_project \
--manifest ./materials-manifest.json \
--source-release 2026.09.01 \
--retrieved-at 2026-09-15T00:00:00+00:00Inspect and retain the reported manifest digest and counts. To apply the validated manifest to a test database in atomic chunks, provide a separate checkpoint path and the exact configured database name:
python -m scripts.import_materials_project \
--manifest ./materials-manifest.json \
--checkpoint ./materials-checkpoint.json \
--expected-database-name materialgraph_test \
--applyUse the actual Materials Project database version and retrieval start time; the example values are illustrative. The declared version is verified against the API heartbeat before each page, and both values are protected by the manifest digest.
If a chunk fails, rerun the same apply command. The validated checkpoint resumes at the last completed chunk and import-run identity. Proven source identities are classified as inserted, updated, or unchanged. Ambiguous identities fail safe as conflicts, and completed identical scopes record retirements without destructive material deletion.
The command refuses an unconfirmed database name and refuses a non-test database
unless --allow-non-test-database is supplied explicitly. Do not use that flag
without an approved production import procedure, backup, and rollback evidence.
Verify import:
python scripts/check_import_counts.pyExample output:
Materials: 28
Elements: 9
MaterialElements: 94
uvicorn app.main:app --reloadServer:
http://127.0.0.1:8000
Swagger UI:
http://127.0.0.1:8000/docs
Run all tests:
pytestRun specific test groups:
pytest tests/servicespytest tests/apiPOST /api/v1/screening/candidates
Evaluate battery material candidates under:
- lithium scarcity
- cobalt avoidance
- stability constraints
- supply-risk constraints
POST /api/v1/comparison/materials
Compare two candidate materials and receive:
- screening scores
- risk scores
- ranking explanations
POST /api/v1/scenarios/rank
Rank candidates under scenarios such as:
- lithium_supply_shock
- cobalt_avoidance
- low_supply_risk
POST /api/v1/sensitivity/material
Analyze candidate robustness under changing supply-risk conditions.
POST /api/v1/substitutions/analyze
Identify alternative candidate materials based on:
- chemistry similarity
- risk profile
- substitution potential