Metadata-Version: 2.3
Name: timm-info
Version: 0.4.0
Summary: A timm model utility
Author: Ben Elfner
Author-email: Ben Elfner <belfner@belfner.com>
License: MIT
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Operating System :: Unix
Classifier: Operating System :: Microsoft :: Windows
Classifier: Topic :: Utilities
Requires-Dist: click>=8.0
Requires-Dist: timm>=0.9.0
Requires-Dist: torch>=2.0.0
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/belfner/timm-info
Description-Content-Type: text/markdown

timm-info
=========

A utility for exploring and analyzing PyTorch Image Models (timm).

## Installation

### Using uv (recommended)

```shell
uv add timm-info
```

### Using pip

```shell
pip install timm-info
```

## Development Setup

Clone the repository and set up your development environment:

```shell
git clone https://github.com/belfner/timm-info.git
cd timm-info
uv sync
uv run timminfo --help
```

Run tests:

```shell
uv run pytest
```

## Requirements

- Python 3.10+
- PyTorch 2.0+
- timm 0.9.0+
- click

## Usage

timm-info provides the CLI tool `timminfo` with commands: `search` and `info`

```
Usage: timminfo [OPTIONS] COMMAND [ARGS]...

  Timm model utility.

  Arguments that don't name a command are treated as model names and passed to
  'info', so 'timminfo NAME...' is shorthand for 'timminfo info NAME...' (e.g.
  'timminfo convnext_nano'). Run 'timminfo info -h' for its options.

Options:
  --version   Show the version and exit.
  -h, --help  Show this message and exit.

Commands:
  info    Get information about a particular timm model.
  search  Search for timm models.
```

### `info` shorthand

Because `info` is the default command, its model-name arguments can be passed
directly to `timminfo` without naming the command:

```shell
timminfo convnext_nano          # equivalent to: timminfo info convnext_nano
timminfo resnet50 efficientnet_b0
```

Explicit command names (`search`, `info`) still take precedence, so a model
named like a command must be requested with `timminfo info <name>`.

### search

`timminfo search ...`

```
Usage: timminfo search [OPTIONS] [NAME_PATTERN]...

  Search for timm models. Multiple patterns can be passed.

Options:
  -p, --pretrained                Only show pretrained models
  -l, --license                   Also show the licenses across each result's
                                  pretrained weights (comma-separated in
                                  'tsv'/'json' formats)
  -b, --by-license                Group results by license instead of by model
                                  (implies --license)
  -f, --format [pretty|tsv|json]  Output format. 'tsv'/'json' are machine-
                                  parsable.  [default: pretty]
  -h, --help                      Show this message and exit.
```

**Examples**


Command

```shell
timminfo search 'resnet50d*' 'xception*'
```

Output

```
Results for 'resnet50d*':
-------------------------
0. resnet50d

Results for 'xception*':
------------------------
0. xception41
1. xception41p
2. xception65
3. xception65p
4. xception71
```

---

Command (`-f tsv` prints a bare model name per line, for chaining I/O)

```shell
timminfo search -f tsv 'resnet50d*' 'xception*'
```

Output

```
resnet50d
xception41
xception41p
xception65
xception65p
xception71
```

---

Command

```shell
timminfo search -p 'resnet50d*' 'xception*'
```

<details>
<summary>Output</summary>

```
Results for 'resnet50d*':
-------------------------
0. resnet50d.a1_in1k
1. resnet50d.a2_in1k
2. resnet50d.a3_in1k
3. resnet50d.gluon_in1k
4. resnet50d.ra2_in1k
5. resnet50d.ra4_e3600_r224_in1k

Results for 'xception*':
------------------------
0. xception41.tf_in1k
1. xception41p.ra3_in1k
2. xception65.ra3_in1k
3. xception65.tf_in1k
4. xception65p.ra3_in1k
5. xception71.tf_in1k
```

</details>

---

Command (`-l`/`--license` resolves the licenses across each architecture's
pretrained weights. For a bare-architecture search each row becomes a checkbox
matrix with one column per distinct license present; a model whose weights carry
no resolvable license ticks the `unknown` column)

```shell
timminfo search -l 'convnext_atto*'
```

Output

```
Results for 'convnext_atto*':
-----------------------------
+---+-------------------+------------+---------+
| # | Model             | apache-2.0 | unknown |
+---+-------------------+------------+---------+
| 0 | convnext_atto     |     X      |    -    |
| 1 | convnext_atto_ols |     X      |    -    |
| 2 | convnext_atto_rms |     -      |    X    |
+---+-------------------+------------+---------+
```

---

Command (with `-p` each row is a single pretrained weight, so `-l` collapses to
one `License` column)

```shell
timminfo search -p -l 'resnet50d*'
```

Output

```
Results for 'resnet50d*':
-------------------------
+---+-------------------------------+------------+
| # | Model                         | License    |
+---+-------------------------------+------------+
| 0 | resnet50d.a1_in1k             | apache-2.0 |
| 1 | resnet50d.a2_in1k             | apache-2.0 |
| 2 | resnet50d.a3_in1k             | apache-2.0 |
| 3 | resnet50d.gluon_in1k          | apache-2.0 |
| 4 | resnet50d.ra2_in1k            | apache-2.0 |
| 5 | resnet50d.ra4_e3600_r224_in1k | apache-2.0 |
+---+-------------------------------+------------+
```

---

Command (in `tsv` format each model's licenses are appended tab-separated, and
comma-separated among themselves, for easy parsing)

```shell
timminfo search -f tsv -l 'xception*'
```

Output

```
xception41	apache-2.0
xception41p	apache-2.0
xception65	apache-2.0
xception65p	apache-2.0
xception71	apache-2.0
```

---

Command (`-b`/`--by-license` pivots the view: one row per license listing the
models that offer it. This implies `--license`)

```shell
timminfo search -b 'convnext_atto*'
```

Output

```
Results for 'convnext_atto*' by license:
----------------------------------------
+------------+----------------------------------+
| License    | Models                           |
+------------+----------------------------------+
| apache-2.0 | convnext_atto, convnext_atto_ols |
| unknown    | convnext_atto_rms                |
+------------+----------------------------------+
```

---

Command (`-f json` emits a single-line JSON array over all patterns. The
`licenses` field is `null` unless `-l`/`-b` requested license lookup, in which
case it is a list; the `-b` pivot instead serializes to `groups` with a `null`
license for the no-license bucket)

```shell
timminfo search -f json -l 'xception71'
```

Output

```json
[{"pattern": "xception71", "pretrained": false, "models": [{"name": "xception71", "licenses": ["apache-2.0"]}]}]
```

### info

`timminfo info ...`

```
Usage: timminfo info [OPTIONS] [NAME]...

  Get information about a particular timm model. Multiple names can be passed.

Options:
  -f, --format [pretty|json]  Output format. 'json' is machine-parsable.
                              [default: pretty]
  -h, --help                  Show this message and exit.
```

**Example**

The summary is rendered as a bordered table and includes the per-stage
downscaling factors and whether each stage downscales by an exact integer
factor. When a model has pretrained weights, a second table lists each weight
tag and its license.

Command

```shell
timminfo info convnextv2_atto efficientnet_b0
```

<details>
<summary>Output</summary>

```
+--------------------------------------+------------------------------+
|                           Model name | convnextv2_atto              |
|                     Number of params | 3,387,400                    |
|                 Estimated model size | 13.550 MB                    |
| Number of in features for classifier | 320                          |
|       Has extractable feature layers | True                         |
|             Number of feature layers | 4                            |
|       Number of channels per feature | [40, 80, 160, 320]           |
|        Downscaling factors per stage | [4x, 2x, 2x, 2x]             |
|           Downscaling type per stage | [exact, exact, exact, exact] |
|                Pretrained Input Size | (3, 224, 224)                |
+--------------------------------------+------------------------------+

+--------------------+--------------+
| Pretrained Weights | License      |
+--------------------+--------------+
|              fcmae | cc-by-nc-4.0 |
|      fcmae_ft_in1k | cc-by-nc-4.0 |
+--------------------+--------------+

+--------------------------------------+-------------------------------------+
|                           Model name | efficientnet_b0                     |
|                     Number of params | 4,007,548                           |
|                 Estimated model size | 16.030 MB                           |
| Number of in features for classifier | 1280                                |
|       Has extractable feature layers | True                                |
|             Number of feature layers | 5                                   |
|       Number of channels per feature | [16, 24, 40, 112, 320]              |
|        Downscaling factors per stage | [2x, 2x, 2x, 2x, 2x]                |
|           Downscaling type per stage | [exact, exact, exact, exact, exact] |
|                Pretrained Input Size | (3, 224, 224)                       |
+--------------------------------------+-------------------------------------+

+---------------------+------------+
|  Pretrained Weights | License    |
+---------------------+------------+
| ra4_e3600_r224_in1k | apache-2.0 |
|             ra_in1k | apache-2.0 |
+---------------------+------------+
```

</details>

---

Command (`-f json` emits one single-line JSON array over all requested models,
with every `ModelInfo` field; per-model errors go to stderr so stdout stays
valid JSON)

```shell
timminfo info -f json convnextv2_atto
```

<details>
<summary>Output</summary>

```json
[{"name": "convnextv2_atto", "num_params": 3387400, "model_size_mb": 13.5496, "classifier_num_in_features": 320, "has_features": true, "num_feature_layers": 4, "num_channels_per_feature": [40, 80, 160, 320], "downscaling_factors": ["4x", "2x", "2x", "2x"], "downscaling_exact": ["exact", "exact", "exact", "exact"], "pretrained_input_size": [3, 224, 224], "pretrained_weights": [{"tag": "fcmae", "license": "cc-by-nc-4.0"}, {"tag": "fcmae_ft_in1k", "license": "cc-by-nc-4.0"}]}]
```

</details>

## Programmatic use

The same functionality is available as an importable API. Processing returns
typed dataclasses (`ModelInfo`, `SearchResult`), and formatting is separate, so
you can consume the data or reuse the CLI's rendering. Importing `timm_info` is
cheap; `torch`/`timm` load only when you call a processing function.

```python
from timm_info import get_model_info, search_models

info = get_model_info("resnet50")
info.num_params                # 23508032
info.num_channels_per_feature  # [64, 256, 512, 1024, 2048]
info.downscaling_factors       # ['2x', '2x', '2x', '2x', '2x']
info.pretrained_weights        # [PretrainedWeight(tag='a1_in1k', license='apache-2.0'), ...]

result = search_models("resnet50*", pretrained=True, with_license=True)
[m.name for m in result.models]
result.models[0].licenses      # ['apache-2.0']  (sorted distinct licenses, or [] when none)
```

Regroup a search result by license with `search.pivot_result`, which returns a
`PivotResult` of `LicenseGroup`s (the `-b`/`--by-license` view):

```python
from timm_info import search

pivot = search.pivot_result(result)
[(g.license, g.models) for g in pivot.groups]   # [('apache-2.0', ['resnet50.a1_in1k', ...]), ...]
```

Render the same output the CLI prints. `format_search_result` and
`format_pivot_result` take the format name (`"pretty"` or `"tsv"`), and
`render_json` serializes a list of result dataclasses to the CLI's single-line
JSON array:

```python
from timm_info import rendering

print(rendering.format_model_info(info))
print(rendering.format_search_result(result, "pretty", show_license=True))
print(rendering.format_pivot_result(pivot, "pretty"))
print(rendering.render_json([result]))   # same JSON as `search -f json`
print(rendering.render_json([info]))      # same JSON as `info -f json`
```