Developer Onboarding
Welcome to nitid — a compact, Apache-2.0 library around the D-FINE family of real-time detectors. This guide is for developers joining the project. The user-facing docs live in the rest of docs/; this page covers the architecture decisions you need to understand before touching the code.
1. Get the repo running
Prerequisites: Python 3.10+, uv.
git clone https://github.com/Nitidio/nitid.git && cd nitid
uv sync --extra dev # installs runtime + pytest, ruff, mypy
Verify everything works:
uv run pytest tests/unit # ~seconds, no GPU, no checkpoint required
uv run ruff check .
uv run mypy dfine/
2. Project layout
nitid/ Public Python package — import NITID from here
cli.py `nitid` CLI entry point (`dfine` is a back-compat alias)
convert_checkpoint.py Maintainer utility for raw upstream checkpoints
dfine/ Internal implementation and compatibility namespace
nitid.py NITID public class and model-name mapping
model.py D-FINE backend class and checkpoint validation
predictor.py Inference worker
trainer.py Fine-tuning worker
validator.py COCO evaluation worker
exporter.py ONNX / OpenVINO / TorchScript / TensorRT export worker
results.py Results + Boxes + Masks + SemanticMask return types
nn/ Integrated detection, segmentation, and semantic architectures/losses
utils/ sources.py (LoadSource), plotting, misc helpers
tools/
visualize_augmentations.py Source-checkout maintainer utility
configs/
datasets/ coco.yml and example_custom.yml
tests/
unit/ Pure Python — no GPU or downloaded checkpoint
integration/ Use tiny_checkpoint fixture (see §5)
conftest.py Session-scoped fixture that builds a tiny model at test time
docs/ All documentation lives here
3. The architecture in one paragraph
NITID is the recommended class users touch. It accepts supported model names
or self-contained .pth checkpoints and delegates predict,
track, train, val, and export to internal workers. Model construction,
losses, and postprocessing live under dfine/nn/. The checkpoint's embedded
task selects detection, instance segmentation, or semantic segmentation; an
explicitly requested task must match it.
4. Model core
dfine/nn/native_build.py is the construction boundary for supported tasks.
Keep architecture settings in dfine/nn/configs.py, route checkpoint
construction through build_model, and route losses through build_criterion.
Do not add import-path mutation or runtime source discovery: the installed
package must contain everything required to construct a model.
Detection and instance segmentation share the backbone, encoder, transformer
decoder, boxes, and class logits. task="segment" enables the mask head and
mask losses. Semantic segmentation adds a dense decoder on shared features.
New code must preserve strict state-dict compatibility with published
checkpoints.
5. Wrapped checkpoint format
Runtime checkpoints are self-contained dicts with these keys:
| Key | Content |
|---|---|
model |
Model state_dict (EMA weights preferred over raw weights) |
config |
Full D-FINE config dict (all __include__ directives resolved) |
names |
{int: str} class index → name mapping |
epoch |
Last saved epoch |
metrics |
Metrics dict from the epoch |
Official model names perform the download/preparation step automatically. The raw-checkpoint conversion tool exists for maintainers and unusual research workflows; it should not be part of the normal user path.
Why self-contained files? So users never have to track a separate config file. One file = one model. This also means build_model forces HGNetv2.pretrained=False (weights come from the checkpoint, not ImageNet) and build_postprocessor forces remap_mscoco_category=False (names come from checkpoint["names"], not a hardcoded COCO mapping).
6. Running the tests
Unit tests
uv run pytest tests/unit
No GPU or downloaded checkpoint is needed. These test pure Python logic, model construction, Results/Boxes/Masks, export argument validation, and dataset parsing.
Integration tests
uv run pytest tests/integration
# or run everything:
uv run pytest
Integration tests use the tiny_checkpoint session fixture in tests/conftest.py. It builds a real D-FINE-S model with random weights entirely in memory — no download required. The fixture overrides num_layers=1, num_queries=10, num_denoising=0, depth_mult=0.1 to keep build time fast (<10 s).
tests/integration/test_train.pyverifies the fine-tuning and validation pipelines using the tiny checkpoint on CPU.
7. Code conventions
| Setting | Value |
|---|---|
| Line length | 100 (E501 ignored; the formatter enforces it) |
| Python target | 3.10 — use X \| Y unions only with from __future__ import annotations |
| Linter | ruff check . |
| Type checker | mypy dfine/ |
| Test runner | pytest |
Write no comments unless the why is genuinely non-obvious. Never add docstrings beyond a single short line. The existing codebase is intentionally sparse — match that style.
8. Inference data flow (follow the code)
Understanding this path makes the codebase navigable:
DFINE.predict()
└─ DFINEPredictor.predict()
└─ LoadSource (dfine/utils/sources.py)
yields (tensor [1,3,H,W], orig_img HWC BGR, path_str)
└─ DFINE.forward() → logits + boxes, and query masks for segmentation
└─ DFINEPostProcessor(raw, orig_target_sizes)
→ [{labels, boxes, scores}] boxes: absolute xyxy pixel coords
└─ Results(boxes=[N,6], masks=[N,H,W] for segmentation)
The 300 queries are D-FINE's fixed-size output head. After postprocessing only the above-threshold detections remain in Boxes._data.
9. Getting a real checkpoint (for manual testing)
The integration tests use synthetic tiny models — they never need to download a real checkpoint. For manual testing, prefer official model names:
uv run nitid predict model=model1s task=detect source=image.jpg conf=0.5
uv run nitid predict model=model1s task=segment source=image.jpg conf=0.5
If you are maintaining support for a new upstream checkpoint, use the conversion tool explicitly:
uv run python -m nitid.convert_checkpoint \
--weights upstream_checkpoint.pth \
--model model1l \
--task detect \
--output model1l_detect.pth
Class names default to the COCO names bundled with the package; pass
--names my_dataset.yml (a YAML file with a names mapping) for other datasets.
10. Where things can go wrong
| Symptom | Cause | Fix |
|---|---|---|
KeyError: 'config' loading a .pth |
File is not a nitid runtime checkpoint | Use a supported model name, a training checkpoint, or the maintainer conversion tool |
AMP has no effect warning |
Running on CPU with amp=True |
Expected — silently degrades to FP32 |
| Explicit task does not match checkpoint | Checkpoint opened with the wrong task | Select a matching model/task pair |
Further reading
| Doc | When to read it |
|---|---|
quickstart.md |
User-facing getting-started guide (good context for what new users experience) |
api_reference.md |
Full DFINE class API with all parameters |
fine_tuning.md |
Dataset format, AMP, EMA, all training parameters |
export.md |
ONNX, TorchScript, TensorRT — options and constraints |
macos_docker_setup.md |
Setup docker for linux enviroment in MacOS Apple silicon |