Check that a machine can do the work#

matmelt doctor answers one question — would a run start right now? — and it answers it for the machines the run would actually use, not for the interpreter MatMelt happens to be installed in.

$ matmelt doctor

Exit 0 means ready. Exit 1 means it found problems and printed them. Exit 2 means the config file itself is wrong, so nothing was checked.

Read the two tables#

The first table probes each configured backend. The second probes each stage’s science dependency in that stage’s own interpreter, on whichever machine that stage runs on.

                              Backend reachability
┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Backend ┃ Kind         ┃ Status  ┃ Detail                                    ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ laptop  │ LocalBackend │ healthy │ work_dir ~/matmelt-demo/materials-jobs    │
│         │              │         │ writable                                  │
└─────────┴──────────────┴─────────┴───────────────────────────────────────────┘
                                Stage readiness
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Stage     ┃ Needs       ┃ Interpreter ┃ Where ┃ Status ┃ Detail              ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ compose   │ smact       │ python3     │ local │ ok     │ smact importable    │
│ structure │ pyxtal      │ python3     │ local │ ok     │ pyxtal importable   │
│ screen    │ mace        │ python3     │ local │ ok     │ mace importable     │
│ extract   │ stdlib only │ python3     │ local │ ok     │ standard library    │
│           │             │             │       │        │ only -- always      │
│           │             │             │       │        │ ready               │
└───────────┴─────────────┴─────────────┴───────┴────────┴─────────────────────┘
Seed enumeration: 2 element(s) -> 3 combination(s) (size 1: 2, size 2: 1).
doctor: all checks passed.

Three lines are worth reading rather than skimming:

  • Where says which machine the dependency was probed on. local is this machine; a remote stage shows user@host, because the science stack has to be where the job runs, not where you typed the command.

  • extract is always ready. Its runner is standard-library only. That is a contract the test suite enforces, not a coincidence.

  • Seed enumeration is the size of the search you are about to start, reported before any work happens.

Fix a missing dependency#

A stage whose package is missing is MISSING, and the command to fix it is printed under the table — pointed at the right interpreter:

│ compose   │ smact       │ /usr/bin/pyth… │ local │ MISSING │ ModuleNotFound… │
│           │             │                │       │         │ No module named │
│           │             │                │       │         │ 'smact'         │
│ screen    │ mace        │ /usr/bin/pyth… │ local │ MISSING │ ModuleNotFound… │
│           │             │                │       │         │ No module named │
│           │             │                │       │         │ 'mace'          │
└───────────┴─────────────┴────────────────┴───────┴─────────┴─────────────────┘
To fix the missing requirements, run:
  /usr/bin/python3 -m pip install smact
  /usr/bin/python3 -m pip install mace-torch

Copy those lines rather than composing your own: the import name and the package name differ more often than you would like — mace is installed by pip install mace-torch.

If the interpreter is wrong rather than the environment, fix the stage’s python option instead (Configuration reference).

Diagnose a remote#

For a stage wired to an ssh_exec backend, both tables reach across the network, and the fix hint becomes a remote one:

│ cluster │ SshExecBackend │ DOWN    │ alice@cluster.example.org: work dir     │
│         │                │         │ /tmp/matmelt-jobs not usable (ssh exit  │
│         │                │         │ 255) ssh: Could not resolve hostname    │
│         │                │         │ cluster.example.org: Name or service    │
│         │                │         │ not known                               │
...
│ screen    │ mace        │ /opt/scien… │ alice@clust… │ MISSING │ ssh: Could  │
...
To fix the missing requirements, run:
  ssh alice@cluster.example.org /opt/science-venv/bin/python -m pip install
mace-torch

The Detail column carries the SSH client’s own message, so the usual causes — unknown host, refused key, wrong username — are distinguishable without turning on any debugging. Connections use BatchMode=yes, so key-based access must already work non-interactively; MatMelt never prompts for a password.

Check the screening model#

When screen has no model_path, doctor says what will be downloaded, how big it is, and where it will land:

Screen model: ok -- no model_path configured: the MACE-MP foundation model
(size=medium) will be downloaded on first use into the mace cache
(~/.cache/mace) -- a one-time download on the order of hundreds of MB. It will
NOT be downloaded without your consent.

That is informational, not a problem. A model_path that is set but missing is a problem, and is reported as one. When the stage runs remotely, the file is checked on the remote.

Script it#

--json prints the same findings as data, with nothing else on stdout:

$ matmelt doctor --json
top-level keys: ['aiida', 'backends', 'config', 'enumeration', 'model', 'ok', 'requirements']

Each entry under requirements carries the stage, the interpreter, the requirement (null for extract), whether it is satisfied, where it was probed, and the exact install_command when it is not:

$ matmelt doctor --json | python3 -c "
import json, sys
for r in json.load(sys.stdin)['requirements']:
    if not r['satisfied']:
        print(r['stage'], '->', r['install_command'])
"
compose -> /usr/bin/python3 -m pip install smact
screen -> /usr/bin/python3 -m pip install mace-torch

ok is the same verdict as the exit code, so a CI gate is matmelt doctor --json | jq -e .ok.