Skip to main content

markinp

CI PyPI Python versions Docs License: MIT DOI

Read, validate, and build Program MARK encounter-history (.inp) files — with error messages that actually tell you what to fix.

markinp removes the most common friction in the capture–recapture workflow: hand-building .inp files in a text editor or Excel, and only discovering formatting mistakes when MARK rejects the file with an unhelpful message.

It does three things and nothing more:

  1. validate an existing .inp file and report precise, actionable errors;
  2. inspect an .inp file and summarize its structure;
  3. build a valid .inp file from a tidy capture table (CSV).

Disclaimer. markinp is an independent, unofficial utility. It is not affiliated with, endorsed by, or maintained by the authors of Program MARK or RMark. "MARK" is referenced only to describe the file format it interoperates with. markinp never fits models or computes statistics — it does file I/O and validation only.

Note on the name. The command and PyPI package are markinp (the name markio was already taken on PyPI).

🌐 No install? Validate an .inp file in your browser — runs entirely client-side; your data never leaves your device.


Install

pip install markinp

60-second quickstart

Validate a file you already have:

markinp validate captures.inp
markinp validate captures.inp

Structure: 4 occasions, 2 groups, 1 covariate, live_recapture
Records:   3   Individuals: 7

Summary: 0 errors, 0 warnings, 0 infos  ->  PASS

When something is wrong, you get the line and the fix — not a traceback:

  MK001  ERROR   line 12: record is not terminated by a semicolon
           hint: Add a ';' at the end of this line to close the record ...

Inspect the inferred structure:

markinp inspect captures.inp

Build an .inp from a tidy CSV:

# long format: one row per (individual x occasion)
markinp build captures.csv -o out.inp \
    --id-col id --occasion-col occasion --detect-col detected \
    --group-col sex --covariate-cols weight

Validate many files at once (exits non-zero if any fail):

markinp validate data/*.inp --strict

Every command accepts --json for machine-readable output and exits non-zero when errors are found, so markinp validate drops straight into CI.

Guard a pipeline (CI & pre-commit)

GitHub Action — fail a build when any .inp file is malformed:

# .github/workflows/validate-inp.yml
name: Validate .inp
on: [push, pull_request]
jobs:
  markinp:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: leonbzt/markinp@v0
        with:
          files: "data/**/*.inp"
          args: "--strict"

pre-commit hook — validate .inp files before every commit:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/leonbzt/markinp
    rev: v0.1.0
    hooks:
      - id: markinp-validate

Use it as a library

The CLI is a thin wrapper; everything is importable:

from markinp import parse_text, validate

result = parse_text("1001 1;\n0101 2;\n")
for diag in validate(result.dataset):
    print(diag.code, diag.message)

The .inp format in one minute

Each record is one line ending in ;. Whitespace separates the fields:

[/* comment */]  HISTORY  FREQ_1 [FREQ_2 ...]  [COV_1 ...]  ;  [/* comment */]
  • HISTORY — one character per sampling occasion (1 = detected, 0 = not).
  • FREQ — one integer count per group; may be negative for losses on capture.
  • COV — optional numeric individual covariates (no missing values allowed).
/* ind 001 */ 1001 1 0 10.2;
/* ind 002 */ 1101 0 2 9.5;
0101 3 1 8.1;

The number of occasions, groups, and covariates is usually not stored in the file, so markinp infers it. Tighten the checks by asserting what you expect:

markinp validate captures.inp --occasions 4 --groups 2 --covariates 1

Error codes

Every problem is reported as a stable, documented diagnostic code (MK001 …). See docs/error-codes.md for the full reference. Highlights:

Code Meaning
MK001 Record not terminated by ;
MK002 History length differs between records
MK004 Wrong number of frequency columns for the group count
MK007 Missing / non-numeric covariate
MK011 All-zero history (warning; not flagged for occupancy)
MK012 Negative frequency — loss on capture (warning)
MK021 Occupancy history is all . — site never surveyed (warning)
MK900 Specialized format detected; only partially validated (info)

--strict promotes warnings to errors. Exit code is 0 when there are no errors and 1 otherwise.

Scope

markinp fully supports the standard 0/1 encounter-history format (live recapture / CJS / Jolly-Seber / closed captures) and the occupancy / detection-history format (0/1 plus . for a not-surveyed occasion, as used by MARK, unmarked, and PRESENCE). For occupancy it treats an all-zero site as valid data, flags an all-. site (MK021), and can build an occupancy .inp from a tidy site × survey CSV (--data-type occupancy) without ever mistaking a missing survey for a non-detection. Known-fate, dead-recovery (Brownie), multistrata, and other multi-state formats are detected and structurally checked only (see MK900); full support is a later milestone. markinp will always tell you honestly when it can only partially validate a file.

Development

pip install -e ".[dev]"
ruff check .
mypy markinp
pytest

Testing

The suite includes a fixture that triggers every diagnostic code, round-trip (parse → write → parse) stability checks, and build → validate round-trips.

To try it on real data, point markinp at a folder of .inp files:

markinp validate path/to/*.inp        # batch validate; exits 1 if any fail
markinp inspect path/to/one.inp       # summarize inferred structure

A local sample_data/ folder of third-party MARK example files is not part of this repository (licensing), but is handy as a regression corpus — running markinp validate sample_data/*.inp over it is a quick way to smoke-test a change against a wide variety of real files. Note that false-positive, robust-design, and multistrata files are outside markinp's fully-supported scope (standard 0/1 and occupancy) and will be flagged accordingly (see docs/error-codes.md).

Citation

If markinp helps your work, please cite it. The concept DOI below always resolves to the latest version; see CITATION.cff for full metadata (and the version-specific DOI).

Botzenhardt, L. markinp: read, validate, and build Program MARK encounter-history (.inp) files. https://doi.org/10.5281/zenodo.21145090

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

markinp-0.3.0.tar.gz (91.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

markinp-0.3.0-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file markinp-0.3.0.tar.gz.

File metadata

  • Download URL: markinp-0.3.0.tar.gz
  • Upload date:
  • Size: 91.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for markinp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 4c9a8e3adb458372db3c3cdee804b2b54a880652692783c9bc2cbe36a33e03f5
MD5 31faf173318f8e7ca750ba8fce99834e
BLAKE2b-256 8b9db8b07daa06e9b07b01603fe7c8747f6b6115748718bf526830c14da775d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for markinp-0.3.0.tar.gz:

Publisher: release.yml on leonbzt/markinp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file markinp-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: markinp-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 27.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for markinp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 742927ad42e4b92df310fc225faadbef6f61693a4baef852af1eeada5cecfbf8
MD5 c362e185c94c726a8c85dd7578f2422b
BLAKE2b-256 b3ec297e2c17587d97c22fbb97a860062d60910ab9c2ee04f4ae0a683d81c5ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for markinp-0.3.0-py3-none-any.whl:

Publisher: release.yml on leonbzt/markinp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page