Skip to content

nqminds/nqm-irimager

Repository files navigation

nqm.irimager

PyPI - Version Code style: black Linting: Pylint Imports: isort Managed by PDM Documentation on GitHub Pages Test GitHub Action

Python module for interfacing with EvoCortex IRImagerDirect SDK.

Setup

nqm.irimager uses the EvoCortex IRImagerDirect SDK (also known as libirimager).

Before using nqm.irimager, you'll need to perform the following setup for each camera you have:

Installing pre-built wheel from PyPI

nqm.irimager publishes pre-built binary wheels for a couple of targets to PyPI, so you may just be able to run:

pip install nqm.irimager

Compiling your own wheel

You can compile nqm.irimager from source for testing, or if you want to use a target that we don't yet publish binaries for.

You'll need a compiler that supports at least C++17.

Installing libirimager

nqm.irimager requires the EvoCortex IRImagerDirect SDK (known as libirimager). Please follow the instructions on their webpage to install the package.

It's possible to install a mocked version of nqm.irimager for testing by defining SKBUILD_CMAKE_DEFINE='IRImager_mock=ON' whiling building nqm.irimager.

Install nqm.irimager

This repo uses PEP621 to manage dependencies. scikit-build-core is used to compile the project as a build-system.build-backend.

We recommend using PDM for local development.

pdm install

Usage example

See documentation for the full API reference, but using this library is as easy as:

import datetime
import logging
from nqm.irimager import IRImager, LoggerContextManager

logging.basicConfig()
logging.getLogger().setLevel(1) # trace

# Your XML config,
# see http://documentation.evocortex.com/libirimager2/html/Overview.html#subsec_overview_config_file
XML_CONFIG = "tests/__fixtures__/[email protected]"
with LoggerContextManager():
  irimager = IRImager(XML_CONFIG)
  with irimager:
    print(f"Started at {datetime.datetime.now()}")
    while True: # press CTRL+C to stop this program
        try:
          array, timestamp = irimager.get_frame()
        except error:
          print(f"Stopped at {datetime.datetime.now()}")
          raise error
        frame_in_celsius = array / (10 ** irimager.get_temp_range_decimal()) - 100
        print(f"At {timestamp}: Average temperature is {frame_in_celsius.mean()}")

Development

Pre-commit checks (linting and type checks)

This project uses pre-commit to check code. You may wish to run pdm run pre-commit install to automatically run checks before you run git commit.

Additionally, you can run pdm run pre-commit run --all to check all changes.

Tests

Tests are written using pytest, and can be run with:

pdm run pytest

C++ unit tests

Some C++ tests are written using GoogleTest and gMock.

As these tests need the [Development.Embed][FindPython3] Python3 embedding artifact (which aren't available on most systems), you must opt-in to building and running these tests by using:

SKBUILD_CMAKE_DEFINE="BUILD_TESTING=ON" pdm install && pdm run pytest

If you want to use both BUILD_TESTING=ON and IRImager_mock=ON, you can do the following:

SKBUILD_CMAKE_DEFINE='BUILD_TESTING=ON;IRImager_mock=ON' pdm install && pdm run pytest

Mypy stubtest

You can use Mypy's stubtest tool to automatically check whether the types in a stub file match the implementation.

For most Python code, we put the type information directly in the implementation, so we only need this for C/C++ Python extensions, like the nqm.irimager module.

Note

The error: nqm.irimager.IRImager is inconsistent, metaclass differs errors are expected, due to the inability to stub built-in pybind11 types.

me@user:~$ MYPYPATH=src .venv/bin/stubtest nqm.irimager
error: nqm.irimager.IRImager is inconsistent, metaclass differs
Stub: in file src/nqm/irimager/__init__.pyi:11
N/A
Runtime:
<class 'pybind11_builtins.pybind11_type'>

Found 1 error (checked 1 module)

Documentation

Sphinx is used to generate documentation in the docs/ directory.

sphinx.ext.napoleon automatically parses Google-style Python docstrings.

pdm run sphinx-build -M html docs/ build/

Publishing a new release

To publish a new release to PyPI, do:

  1. Make a new commit called chore: release v1.X.X This should change:
    • The project.version field in the pyproject.toml file (e.g.
      version = "1.0.0"
      )
    • Make a new entry in the CHANGELOG.md file, moving any appropriate entries from the Unreleased section.
  2. Push the commit to GitHub.
  3. Make a new GitHub release for the commit you made, copying the CHANGELOG.md entry for the release notes.
  4. The build.yml GitHub Action should automatically build and publish the new release to PyPI.
  5. Merge the released commit to the main branch if you haven't already.