Pictograph SDK — vendored YOLOX architecture
============================================

This directory contains source code derived from YOLOX, redistributed under the
Apache License, Version 2.0. The full licence text is in ./LICENSE.

Origin
------
    Project:  YOLOX
    Commit:   6ddff4824372906469a7fae2dc3206c7aa4bbaee
    Upstream: https://github.com/Megvii-BaseDetection/YOLOX
    Copyright (c) Megvii Inc. All rights reserved.
    Licensed under the Apache License, Version 2.0.

That commit is the one pinned by
`pictograph-backend/modal/pictograph_training_service.py` (`YOLOX_SHA`), i.e. the
architecture the weights we publish were trained as. A verbatim source tarball of
it is mirrored at
`gs://pictograph-app/dependencies/YOLOX-6ddff4824372906469a7fae2dc3206c7aa4bbaee.tar.gz`
per the repo's Modal image dependency policy, so this tree can be re-diffed
against its source even if the upstream repository disappears.

WHAT IS HERE
------------
The model-construction subset only — `yolox/models/`, minus two files:

    network_blocks.py   BaseConv / DWConv / CSPLayer / Focus / SPPBottleneck / …
    darknet.py          CSPDarknet backbone
    yolo_pafpn.py       YOLOPAFPN neck
    yolo_head.py        YOLOXHead (incl. decode_outputs)
    yolox.py            the YOLOX module itself
    losses.py           IOUloss — constructed in YOLOXHead.__init__, so it is
                        required to build the module even though the loss is
                        never evaluated at inference
    _upstream_utils.py  the four `yolox.utils` helpers yolo_head.py imports

    NOT vendored: build.py (torch.hub model-zoo downloads) and yolo_fpn.py (the
    Darknet-53 FPN neck — no Pictograph pipeline trains it).

1,251 of the upstream package's 7,691 Python lines (16.3%), plus 127 lines of
gathered utils. Data loading, the `Exp` system, the trainer, evaluators, COCO
metrics, the distributed/EMA/MLflow utilities and the ONNX/TensorRT export tools
are not vendored.

NOTICE OF MODIFICATION (Apache-2.0 section 4b)
----------------------------------------------
Every file in this directory carries a header stating whether it was modified.
The changes are:

1.  A provenance header was prepended to each file, replacing the upstream
    three-line shebang/coding/copyright preamble (whose copyright line is
    reproduced in the new header).

2.  `yolo_head.py` — its ONE `from yolox.utils import bboxes_iou, cxcywh2xyxy,
    meshgrid, visualize_assign` line is redirected onto `._upstream_utils`, and
    its `from loguru import logger` is dropped in favour of the `logger` that
    same module exports. No other line of the file changed. Importing
    `yolox.utils` as a package would drag in the distributed-training, MLflow,
    EMA, LR-scheduler and COCO-metric modules, none of which a rebuilt
    checkpoint touches.

3.  `_upstream_utils.py` is a gathering file, not a rewrite: `meshgrid` (from
    `yolox/utils/compat.py`), `bboxes_iou` and `cxcywh2xyxy` (from
    `yolox/utils/boxes.py`), and `random_color` and `visualize_assign` (from
    `yolox/utils/demo_utils.py`) are VERBATIM. The single substitution is
    `logger`, which upstream binds to `loguru.logger`: it is bound to the
    standard library's `logging.getLogger("pictograph.inference")` instead, so
    that `loguru` is not a runtime dependency of `pip install pictograph` for
    two log calls on a label-assignment path a `.eval()`-mode checkpoint never
    reaches.

4.  `__init__.py` is original Pictograph work, not derived from YOLOX. It
    exposes `build_yolox(depth, width, num_classes)`, which assembles the same
    `YOLOX(YOLOPAFPN, YOLOXHead)` the training pipeline's `DynamicExp.get_model`
    does.

No file in this directory has been altered in a way that changes the numerical
behaviour of the model it builds.

WHY VENDORED RATHER THAN DEPENDED ON
------------------------------------
See the module docstring in ./__init__.py. In short: PyPI's `yolox` is 0.3.0
(2022), sdist-only, and its `setup.py` asserts torch is importable in order to
compile a C++ extension — so pip cannot build it as a declared dependency at all
(`AssertionError: torch is required for pre-compiling ops`, reproduced in a clean
venv). It is also a different architecture from the pinned SHA, and its
`install_requires` would put a second `cv2` provider into the environment. The
only other option, a `git+https://…@<sha>` direct reference, is rejected by PyPI
at upload time (PEP 440), so a published wheel cannot declare one.
