From bb2077afe967df9c64e4b3c6f93c9fc151a434a7 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 14:26:27 -0800 Subject: [PATCH 01/14] Remove pyastar2d TPL, migrated to batbot-pyastar2d fork --- .../workflows/python-publish-linux.yml | 53 ----- .../workflows/python-publish-macos.yml | 52 ----- .../workflows/python-publish-windows.yml | 52 ----- tpl/pyastar2d/.gitignore | 12 -- tpl/pyastar2d/.travis.yml | 17 -- tpl/pyastar2d/LICENSE | 21 -- tpl/pyastar2d/MANIFEST.in | 2 - tpl/pyastar2d/README.md | 158 -------------- tpl/pyastar2d/examples/example.py | 19 -- tpl/pyastar2d/examples/maze_solver.py | 75 ------- tpl/pyastar2d/pyproject.toml | 3 - tpl/pyastar2d/requirements-dev.txt | 4 - tpl/pyastar2d/requirements.txt | 2 - tpl/pyastar2d/setup.py | 52 ----- tpl/pyastar2d/src/cpp/astar.cpp | 193 ------------------ .../src/cpp/experimental_heuristics.cpp | 42 ---- .../src/cpp/experimental_heuristics.h | 20 -- tpl/pyastar2d/src/pyastar2d/__init__.py | 3 - tpl/pyastar2d/src/pyastar2d/astar_wrapper.py | 76 ------- tpl/pyastar2d/tests/test_astar.py | 141 ------------- 20 files changed, 997 deletions(-) delete mode 100644 tpl/pyastar2d/.github/workflows/python-publish-linux.yml delete mode 100644 tpl/pyastar2d/.github/workflows/python-publish-macos.yml delete mode 100644 tpl/pyastar2d/.github/workflows/python-publish-windows.yml delete mode 100644 tpl/pyastar2d/.gitignore delete mode 100644 tpl/pyastar2d/.travis.yml delete mode 100644 tpl/pyastar2d/LICENSE delete mode 100644 tpl/pyastar2d/MANIFEST.in delete mode 100644 tpl/pyastar2d/README.md delete mode 100644 tpl/pyastar2d/examples/example.py delete mode 100644 tpl/pyastar2d/examples/maze_solver.py delete mode 100644 tpl/pyastar2d/pyproject.toml delete mode 100644 tpl/pyastar2d/requirements-dev.txt delete mode 100644 tpl/pyastar2d/requirements.txt delete mode 100644 tpl/pyastar2d/setup.py delete mode 100644 tpl/pyastar2d/src/cpp/astar.cpp delete mode 100644 tpl/pyastar2d/src/cpp/experimental_heuristics.cpp delete mode 100644 tpl/pyastar2d/src/cpp/experimental_heuristics.h delete mode 100644 tpl/pyastar2d/src/pyastar2d/__init__.py delete mode 100644 tpl/pyastar2d/src/pyastar2d/astar_wrapper.py delete mode 100644 tpl/pyastar2d/tests/test_astar.py diff --git a/tpl/pyastar2d/.github/workflows/python-publish-linux.yml b/tpl/pyastar2d/.github/workflows/python-publish-linux.yml deleted file mode 100644 index 5c0c809..0000000 --- a/tpl/pyastar2d/.github/workflows/python-publish-linux.yml +++ /dev/null @@ -1,53 +0,0 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Upload Python Package Linux - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.7' - - name: Run tests - run: | - pip install . - pip install -r requirements-dev.txt - py.test - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install twine build - - name: Build source distribution - run: | - python -m build --sdist - - name: Build manylinux Python wheels - uses: RalfG/python-wheels-manylinux-build@v0.4.2-manylinux2014_x86_64 - with: - python-versions: 'cp37-cp37m cp38-cp38 cp39-cp39 cp310-cp310' - build-requirements: 'numpy' - - name: Publish distribution 📦 to Test PyPI - env: - TWINE_USERNAME: __token__ - #TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - #python -m twine upload --repository testpypi dist/*-manylinux*.whl dist/*.tar.gz --verbose --skip-existing - python -m twine upload dist/*-manylinux*.whl dist/*.tar.gz --verbose --skip-existing diff --git a/tpl/pyastar2d/.github/workflows/python-publish-macos.yml b/tpl/pyastar2d/.github/workflows/python-publish-macos.yml deleted file mode 100644 index bebb882..0000000 --- a/tpl/pyastar2d/.github/workflows/python-publish-macos.yml +++ /dev/null @@ -1,52 +0,0 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Upload Python Package MacOs - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - - runs-on: macos-11 - - strategy: - matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: "${{ matrix.python-version }}" - - name: Run tests - run: | - pip install . - pip install -r requirements-dev.txt - py.test - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install wheel twine - - name: "Build package for python ${{ matrix.python-version }}" - run: | - python setup.py bdist_wheel - - name: Publish distribution 📦 to Test PyPI - env: - TWINE_USERNAME: __token__ - #TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - #python -m twine upload --repository testpypi dist/* --verbose --skip-existing - python -m twine upload dist/* --verbose --skip-existing diff --git a/tpl/pyastar2d/.github/workflows/python-publish-windows.yml b/tpl/pyastar2d/.github/workflows/python-publish-windows.yml deleted file mode 100644 index 9c0a51a..0000000 --- a/tpl/pyastar2d/.github/workflows/python-publish-windows.yml +++ /dev/null @@ -1,52 +0,0 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Upload Python Package Windows - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - deploy: - - runs-on: windows-2022 - - strategy: - matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: "${{ matrix.python-version }}" - - name: Run tests - run: | - pip install . - pip install -r requirements-dev.txt - py.test - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install wheel twine - - name: "Build package for python ${{ matrix.python-version }}" - run: | - python setup.py bdist_wheel - - name: Publish distribution 📦 to Test PyPI - env: - TWINE_USERNAME: __token__ - #TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - #python -m twine upload --repository testpypi dist/* --verbose --skip-existing - python -m twine upload dist/* --verbose --skip-existing diff --git a/tpl/pyastar2d/.gitignore b/tpl/pyastar2d/.gitignore deleted file mode 100644 index 2aaa22d..0000000 --- a/tpl/pyastar2d/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -*.swp -*.swo -*.so -*.pyc -*.png -*.cache -*.egg-info -*.eggs -.vscode -*.o -build/ -.DS_Store diff --git a/tpl/pyastar2d/.travis.yml b/tpl/pyastar2d/.travis.yml deleted file mode 100644 index 89a2808..0000000 --- a/tpl/pyastar2d/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: python -python: - - 3.8 -before_install: - - pip install -U pip -# command to install dependencies -install: - - pip install -r requirements-dev.txt - - pip install coveralls # python-coveralls leads to this issue: https://github.com/z4r/python-coveralls/issues/73 - - pip install . -# command to run tests -script: - - pytest --cov pyastar2d --cov-report term-missing -after_success: - - coveralls -notifications: - email: false diff --git a/tpl/pyastar2d/LICENSE b/tpl/pyastar2d/LICENSE deleted file mode 100644 index 8f0a412..0000000 --- a/tpl/pyastar2d/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Hendrik Weideman - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/tpl/pyastar2d/MANIFEST.in b/tpl/pyastar2d/MANIFEST.in deleted file mode 100644 index 4c89ab4..0000000 --- a/tpl/pyastar2d/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include requirements.txt -include src/cpp/experimental_heuristics.h diff --git a/tpl/pyastar2d/README.md b/tpl/pyastar2d/README.md deleted file mode 100644 index e51093a..0000000 --- a/tpl/pyastar2d/README.md +++ /dev/null @@ -1,158 +0,0 @@ -[![Build Status](https://travis-ci.com/hjweide/pyastar2d.svg?branch=master)](https://travis-ci.com/hjweide/pyastar2d) -[![Coverage Status](https://coveralls.io/repos/github/hjweide/pyastar2d/badge.svg?branch=master)](https://coveralls.io/github/hjweide/pyastar2d?branch=master) -[![PyPI version](https://badge.fury.io/py/pyastar2d.svg)](https://badge.fury.io/py/pyastar2d) -# PyAstar2D -This is a very simple C++ implementation of the A\* algorithm for pathfinding -on a two-dimensional grid. The solver itself is implemented in C++, but is -callable from Python. This combines the speed of C++ with the convenience of -Python. - -I have not done any formal benchmarking, but the solver finds the solution to a -1802 by 1802 maze in 0.29s and a 4008 by 4008 maze in 0.83s when running on my -nine-year-old Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz. See [Example -Results](#example-results) for more details. - -See `src/cpp/astar.cpp` for the core C++ implementation of the A\* shortest -path search algorithm, `src/pyastar2d/astar_wrapper.py` for the Python wrapper -and `examples/example.py` for example usage. - -When determining legal moves, 4-connectivity is the default, but it is possible -to set `allow_diagonal=True` for 8-connectivity. - -## Installation -Instructions for installing `pyastar2d` are given below. - -### From PyPI -The easiest way to install `pyastar2d` is directly from the Python package index: -``` -pip install pyastar2d -``` - -### From source -You can also install `pyastar2d` by cloning this repository and building it -yourself. If running on Linux or MacOS, simply run -```bash -pip install . -```` -from the root directory. If you are using Windows you may have to install Cython manually first: -```bash -pip install Cython -pip install . -``` -To check that everything worked, run the example: -```bash -python examples/example.py -``` - -### As a dependency -Include `pyastar2d` in your `requirements.txt` to install from `pypi`, or add -this line to `requirements.txt`: -``` -pyastar2d @ git+git://github.com/hjweide/pyastar2d.git@master#egg=pyastar2d -``` - -## Usage -A simple example is given below: -```python -import numpy as np -import pyastar2d -# The minimum cost must be 1 for the heuristic to be valid. -# The weights array must have np.float32 dtype to be compatible with the C++ code. -weights = np.array([[1, 3, 3, 3, 3], - [2, 1, 3, 3, 3], - [2, 2, 1, 3, 3], - [2, 2, 2, 1, 3], - [2, 2, 2, 2, 1]], dtype=np.float32) -# The start and goal coordinates are in matrix coordinates (i, j). -path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=True) -print(path) -# The path is returned as a numpy array of (i, j) coordinates. -array([[0, 0], - [1, 1], - [2, 2], - [3, 3], - [4, 4]]) -``` -Note that all grid points are represented as `(i, j)` coordinates. An example -of using `pyastar2d` to solve a maze is given in `examples/maze_solver.py`. - -## Example Results - -To test the implementation, I grabbed two nasty mazes from Wikipedia. They are -included in the ```mazes``` directory, but are originally from here: -[Small](https://upload.wikimedia.org/wikipedia/commons/c/cf/MAZE.png) and -[Large](https://upload.wikimedia.org/wikipedia/commons/3/32/MAZE_2000x2000_DFS.png). -I load the ```.png``` files as grayscale images, and set the white pixels to 1 -(open space) and the black pixels to `INF` (walls). - -To run the examples specify the input and output files using the `--input` and -`--output` flags. For example, the following commands will solve the small and -large mazes: -``` -python examples/maze_solver.py --input mazes/maze_small.png --output solns/maze_small.png -python examples/maze_solver.py --input mazes/maze_large.png --output solns/maze_large.png -``` - -### Small Maze (1802 x 1802): -```bash -time python examples/maze_solver.py --input mazes/maze_small.png --output solns/maze_small.png -Loaded maze of shape (1802, 1802) from mazes/maze_small.png -Found path of length 10032 in 0.292794s -Plotting path to solns/maze_small.png -Done - -real 0m1.214s -user 0m1.526s -sys 0m0.606s -``` -The solution found for the small maze is shown below: -Maze Small Solution - -### Large Maze (4002 x 4002): -```bash -time python examples/maze_solver.py --input mazes/maze_large.png --output solns/maze_large.png -Loaded maze of shape (4002, 4002) from mazes/maze_large.png -Found path of length 783737 in 0.829181s -Plotting path to solns/maze_large.png -Done - -real 0m29.385s -user 0m29.563s -sys 0m0.728s -``` -The solution found for the large maze is shown below: -Maze Large Solution - -## Motivation -I recently needed an implementation of the A* algorithm in Python to find the -shortest path between two points in a cost matrix representing an image. -Normally I would simply use [networkx](https://networkx.github.io/), but for -graphs with millions of nodes the overhead incurred to construct the graph can -be expensive. Considering that I was only interested in graphs that may be -represented as two-dimensional grids, I decided to implement it myself using -this special structure of the graph to make various optimizations. -Specifically, the graph is represented as a one-dimensional array because there -is no need to store the neighbors. Additionally, the lookup tables for -previously-explored nodes (their costs and paths) are also stored as -one-dimensional arrays. The implication of this is that checking the lookup -table can be done in O(1), at the cost of using O(n) memory. Alternatively, we -could store only the nodes we traverse in a hash table to reduce the memory -usage. Empirically I found that replacing the one-dimensional array with a -hash table (`std::unordered_map`) was about five times slower. - -## Tests -The default installation does not include the dependencies necessary to run the -tests. To install these, first run -```bash -pip install -r requirements-dev.txt -``` -before running -```bash -py.test -``` -The tests are fairly basic but cover some of the -more common pitfalls. Pull requests for more extensive tests are welcome. - -## References -1. [A\* search algorithm on Wikipedia](https://en.wikipedia.org/wiki/A*_search_algorithm#Pseudocode) -2. [Pathfinding with A* on Red Blob Games](http://www.redblobgames.com/pathfinding/a-star/introduction.html) diff --git a/tpl/pyastar2d/examples/example.py b/tpl/pyastar2d/examples/example.py deleted file mode 100644 index 53b8fa1..0000000 --- a/tpl/pyastar2d/examples/example.py +++ /dev/null @@ -1,19 +0,0 @@ -import numpy as np -import pyastar2d - -# The start and goal coordinates are in matrix coordinates (i, j). -start = (0, 0) -goal = (4, 4) - -# The minimum cost must be 1 for the heuristic to be valid. -weights = np.array( - [[1, 3, 3, 3, 3], [2, 1, 3, 3, 3], [2, 2, 1, 3, 3], [2, 2, 2, 1, 3], [2, 2, 2, 2, 1]], - dtype=np.float32, -) -print('Cost matrix:') -print(weights) -path = pyastar2d.astar_path(weights, start, goal, allow_diagonal=True) - -# The path is returned as a numpy array of (i, j) coordinates. -print(f'Shortest path from {start} to {goal} found:') -print(path) diff --git a/tpl/pyastar2d/examples/maze_solver.py b/tpl/pyastar2d/examples/maze_solver.py deleted file mode 100644 index cde508c..0000000 --- a/tpl/pyastar2d/examples/maze_solver.py +++ /dev/null @@ -1,75 +0,0 @@ -import argparse -import time -from os.path import basename, join - -import imageio -import numpy as np -import pyastar2d - - -def parse_args(): - parser = argparse.ArgumentParser('An example of using pyastar2d to find the solution to a maze') - parser.add_argument( - '--input', - type=str, - default='mazes/maze_small.png', - help='Path to the black-and-white image to be used as input.', - ) - parser.add_argument( - '--output', - type=str, - help='Path to where the output will be written', - ) - - args = parser.parse_args() - - if args.output is None: - args.output = join('solns', basename(args.input)) - - return args - - -def main(): - args = parse_args() - maze = imageio.imread(args.input) - - if maze is None: - print(f'No file found: {args.input}') - return - else: - print(f'Loaded maze of shape {maze.shape} from {args.input}') - - grid = maze.astype(np.float32) - grid[grid == 0] = np.inf - grid[grid == 255] = 1 - - assert grid.min() == 1, 'cost of moving must be at least 1' - - # start is the first white block in the top row - (start_j,) = np.where(grid[0, :] == 1) - start = np.array([0, start_j[0]]) - - # end is the first white block in the final column - (end_i,) = np.where(grid[:, -1] == 1) - end = np.array([end_i[0], grid.shape[0] - 1]) - - t0 = time.time() - # set allow_diagonal=True to enable 8-connectivity - path = pyastar2d.astar_path(grid, start, end, allow_diagonal=False) - dur = time.time() - t0 - - if path.shape[0] > 0: - print(f'Found path of length {path.shape[0]} in {dur:.6f}s') - maze = np.stack((maze, maze, maze), axis=2) - maze[path[:, 0], path[:, 1]] = (255, 0, 0) - - print(f'Plotting path to {args.output}') - imageio.imwrite(args.output, maze) - else: - print('No path found') - - print('Done') - - -if __name__ == '__main__': - main() diff --git a/tpl/pyastar2d/pyproject.toml b/tpl/pyastar2d/pyproject.toml deleted file mode 100644 index 9ee21c9..0000000 --- a/tpl/pyastar2d/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools>=64", "wheel", "numpy"] -build-backend = "setuptools.build_meta" diff --git a/tpl/pyastar2d/requirements-dev.txt b/tpl/pyastar2d/requirements-dev.txt deleted file mode 100644 index a7f9fc1..0000000 --- a/tpl/pyastar2d/requirements-dev.txt +++ /dev/null @@ -1,4 +0,0 @@ -pytest -pytest-cov -pytest-pep8 -pyyaml diff --git a/tpl/pyastar2d/requirements.txt b/tpl/pyastar2d/requirements.txt deleted file mode 100644 index 3a353ed..0000000 --- a/tpl/pyastar2d/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -imageio -numpy diff --git a/tpl/pyastar2d/setup.py b/tpl/pyastar2d/setup.py deleted file mode 100644 index ddfe4aa..0000000 --- a/tpl/pyastar2d/setup.py +++ /dev/null @@ -1,52 +0,0 @@ -import pathlib - -from setuptools import Extension, find_packages, setup - -# Use pathlib for paths -here = pathlib.Path(__file__).parent.resolve() - -# Read README and requirements -long_description = (here / 'README.md').read_text(encoding='utf-8') -install_requires = (here / 'requirements.txt').read_text().splitlines() - - -class get_numpy_include: - """Defer numpy import until it is actually installed.""" - - def __str__(self): - import numpy - - return numpy.get_include() - - -# Define the C++ extension -astar_module = Extension( - name='pyastar2d.astar', - sources=[ - 'src/cpp/astar.cpp', - 'src/cpp/experimental_heuristics.cpp', - ], - include_dirs=[ - 'src/cpp', - get_numpy_include(), - ], - extra_compile_args=['-shared'], - language='c++', -) - -# Define package metadata -setup( - name='pyastar2d', - version='1.0.7', - author='Hendrik Weideman', - author_email='hjweide@gmail.com', - description='A simple implementation of the A* algorithm for path-finding on a two-dimensional grid.', - long_description=long_description, - long_description_content_type='text/markdown', - url='https://github.com/hjweide/pyastar2d', - packages=find_packages(where='src', exclude=('tests',)), - package_dir={'': 'src'}, - install_requires=install_requires, - python_requires='>=3.7', - ext_modules=[astar_module], -) diff --git a/tpl/pyastar2d/src/cpp/astar.cpp b/tpl/pyastar2d/src/cpp/astar.cpp deleted file mode 100644 index 727b05a..0000000 --- a/tpl/pyastar2d/src/cpp/astar.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -const float INF = std::numeric_limits::infinity(); - -// represents a single pixel -class Node { - public: - int idx; // index in the flattened grid - float cost; // cost of traversing this pixel - int path_length; // the length of the path to reach this node - - Node(int i, float c, int path_length) : idx(i), cost(c), path_length(path_length) {} -}; - -// the top of the priority queue is the greatest element by default, -// but we want the smallest, so flip the sign -bool operator<(const Node &n1, const Node &n2) { - return n1.cost > n2.cost; -} - -// See for various grid heuristics: -// http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S7 -// L_\inf norm (diagonal distance) -inline float linf_norm(int i0, int j0, int i1, int j1) { - return std::max(std::abs(i0 - i1), std::abs(j0 - j1)); -} - -// L_1 norm (manhattan distance) -inline float l1_norm(int i0, int j0, int i1, int j1) { - return std::abs(i0 - i1) + std::abs(j0 - j1); -} - -// Tie breaker heuristic (distance to direct line between start and goal) -inline float tie_breaker(int i0, int j0, int is, int js, int ig, int jg) { - return 0.001 * abs((j0 - jg)*(is - ig) - (js - jg)*(i0 - ig)); -} - -// weights: flattened h x w grid of costs -// h, w: height and width of grid -// start, goal: index of start/goal in flattened grid -// diag_ok: if true, allows diagonal moves (8-conn.) -// paths (output): for each node, stores previous node in path -static PyObject *astar(PyObject *self, PyObject *args) { - const PyArrayObject* weights_object; - int h; - int w; - int start; - int goal; - int diag_ok; - int heuristic_override; - - if (!PyArg_ParseTuple( - args, "Oiiiiii", // i = int, O = object - &weights_object, - &h, &w, - &start, &goal, - &diag_ok, &heuristic_override - )) - return NULL; - - float* weights = (float*) weights_object->data; - int* paths = new int[h * w]; - int path_length = -1; - - Node start_node(start, 0., 1); - - float* costs = new float[h * w]; - for (int i = 0; i < h * w; ++i) - costs[i] = INF; - costs[start] = 0.; - - std::priority_queue nodes_to_visit; - nodes_to_visit.push(start_node); - - int* nbrs = new int[8]; - - int goal_i = goal / w; - int goal_j = goal % w; - int start_i = start / w; - int start_j = start % w; - - heuristic_ptr heuristic_func = select_heuristic(heuristic_override); - - while (!nodes_to_visit.empty()) { - // .top() doesn't actually remove the node - Node cur = nodes_to_visit.top(); - - if (cur.idx == goal) { - path_length = cur.path_length; - break; - } - - nodes_to_visit.pop(); - - int row = cur.idx / w; - int col = cur.idx % w; - // check bounds and find up to eight neighbors: top to bottom, left to right - nbrs[0] = (diag_ok && row > 0 && col > 0) ? cur.idx - w - 1 : -1; - nbrs[1] = (row > 0) ? cur.idx - w : -1; - nbrs[2] = (diag_ok && row > 0 && col + 1 < w) ? cur.idx - w + 1 : -1; - nbrs[3] = (col > 0) ? cur.idx - 1 : -1; - nbrs[4] = (col + 1 < w) ? cur.idx + 1 : -1; - nbrs[5] = (diag_ok && row + 1 < h && col > 0) ? cur.idx + w - 1 : -1; - nbrs[6] = (row + 1 < h) ? cur.idx + w : -1; - nbrs[7] = (diag_ok && row + 1 < h && col + 1 < w ) ? cur.idx + w + 1 : -1; - - float heuristic_cost, current_i, current_j; - for (int i = 0; i < 8; ++i) { - if (nbrs[i] >= 0) { - // Calculate the coordinates of the neighbor - current_i = nbrs[i] / w; - current_j = nbrs[i] % w; - - // Calculate the tie breaker heuristic - float tie_break = tie_breaker( - current_i, current_j, start_i, start_j, goal_i, goal_j); - - // Sum of the cost so far and the cost of this move - float new_cost = costs[cur.idx] + weights[nbrs[i]] + tie_break; - if (new_cost < costs[nbrs[i]]) { - // estimate the cost to the goal based on legal moves - // Get the heuristic method to use - if (heuristic_override == DEFAULT) { - if (diag_ok) { - heuristic_cost = linf_norm(current_i, current_j, goal_i, goal_j); - } else { - heuristic_cost = l1_norm(current_i, current_j, goal_i, goal_j); - } - } else { - heuristic_cost = heuristic_func( - current_i, current_j, goal_i, goal_j, start_i, start_j); - } - - // paths with lower expected cost are explored first - float priority = new_cost + heuristic_cost; - nodes_to_visit.push(Node(nbrs[i], priority, cur.path_length + 1)); - - costs[nbrs[i]] = new_cost; - paths[nbrs[i]] = cur.idx; - } - } - } - } - - PyObject *return_val; - if (path_length >= 0) { - npy_intp dims[2] = {path_length, 2}; - PyArrayObject* path = (PyArrayObject*) PyArray_SimpleNew(2, dims, NPY_INT32); - npy_int32 *iptr, *jptr; - int idx = goal; - for (npy_intp i = dims[0] - 1; i >= 0; --i) { - iptr = (npy_int32*) (path->data + i * path->strides[0]); - jptr = (npy_int32*) (path->data + i * path->strides[0] + path->strides[1]); - - *iptr = idx / w; - *jptr = idx % w; - - idx = paths[idx]; - } - - return_val = PyArray_Return(path); - } - else { - return_val = Py_BuildValue(""); // no soln --> return None - } - - delete[] costs; - delete[] nbrs; - delete[] paths; - - return return_val; -} - -static PyMethodDef astar_methods[] = { - {"astar", (PyCFunction)astar, METH_VARARGS, "astar"}, - {NULL, NULL, 0, NULL} -}; - -static struct PyModuleDef astar_module = { - PyModuleDef_HEAD_INIT,"astar", NULL, -1, astar_methods -}; - -PyMODINIT_FUNC PyInit_astar(void) { - import_array(); - return PyModule_Create(&astar_module); -} diff --git a/tpl/pyastar2d/src/cpp/experimental_heuristics.cpp b/tpl/pyastar2d/src/cpp/experimental_heuristics.cpp deleted file mode 100644 index c6a5a17..0000000 --- a/tpl/pyastar2d/src/cpp/experimental_heuristics.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Please note below heuristics are experimental and only for pretty lines. -// They may not take the shortest path and require additional cpu cycles. - -#include -#include -#include - - -heuristic_ptr select_heuristic(int h) { - switch (h) { - case ORTHOGONAL_X: - return orthogonal_x; - case ORTHOGONAL_Y: - return orthogonal_y; - default: - return NULL; - } -} - -// Orthogonal x (moves by x first, then half way by y) -float orthogonal_x(int i0, int j0, int i1, int j1, int i2, int j2) { - int di = std::abs(i0 - i1); - int dim = std::abs(i1 - i2); - int djm = std::abs(j1 - j2); - if (di > (dim * 0.5)) { - return di + djm; - } else { - return std::abs(j0 - j1); - } -} - -// Orthogonal y (moves by y first, then half way by x) -float orthogonal_y(int i0, int j0, int i1, int j1, int i2, int j2) { - int dj = std::abs(j0 - j1); - int djm = std::abs(j1 - j2); - int dim = std::abs(i1 - i2); - if (dj > (djm * 0.5)) { - return dj + dim; - } else { - return std::abs(i0 - i1); - } -} diff --git a/tpl/pyastar2d/src/cpp/experimental_heuristics.h b/tpl/pyastar2d/src/cpp/experimental_heuristics.h deleted file mode 100644 index 98c0562..0000000 --- a/tpl/pyastar2d/src/cpp/experimental_heuristics.h +++ /dev/null @@ -1,20 +0,0 @@ -// Please note below heuristics are experimental and only for pretty lines. -// They may not take the shortest path and require additional cpu cycles. - -#ifndef EXPERIMENTAL_HEURISTICS_H_ -#define EXPERIMENTAL_HEURISTICS_H_ - - -enum Heuristic { DEFAULT, ORTHOGONAL_X, ORTHOGONAL_Y }; - -typedef float (*heuristic_ptr)(int, int, int, int, int, int); - -heuristic_ptr select_heuristic(int); - -// Orthogonal x (moves by x first, then half way by y) -float orthogonal_x(int, int, int, int, int, int); - -// Orthogonal y (moves by y first, then half way by x) -float orthogonal_y(int, int, int, int, int, int); - -#endif diff --git a/tpl/pyastar2d/src/pyastar2d/__init__.py b/tpl/pyastar2d/src/pyastar2d/__init__.py deleted file mode 100644 index d0cd0a2..0000000 --- a/tpl/pyastar2d/src/pyastar2d/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from pyastar2d.astar_wrapper import Heuristic, astar_path - -__all__ = ['astar_path', 'Heuristic'] diff --git a/tpl/pyastar2d/src/pyastar2d/astar_wrapper.py b/tpl/pyastar2d/src/pyastar2d/astar_wrapper.py deleted file mode 100644 index b8a7f7d..0000000 --- a/tpl/pyastar2d/src/pyastar2d/astar_wrapper.py +++ /dev/null @@ -1,76 +0,0 @@ -import ctypes -from enum import IntEnum -from typing import Optional, Tuple - -import numpy as np -import pyastar2d.astar - -# Define array types -ndmat_f_type = np.ctypeslib.ndpointer(dtype=np.float32, ndim=1, flags='C_CONTIGUOUS') -ndmat_i2_type = np.ctypeslib.ndpointer(dtype=np.int32, ndim=2, flags='C_CONTIGUOUS') - -# Define input/output types -pyastar2d.astar.restype = ndmat_i2_type # Nx2 (i, j) coordinates or None -pyastar2d.astar.argtypes = [ - ndmat_f_type, # weights - ctypes.c_int, # height - ctypes.c_int, # width - ctypes.c_int, # start index in flattened grid - ctypes.c_int, # goal index in flattened grid - ctypes.c_bool, # allow diagonal - ctypes.c_int, # heuristic_override -] - - -class Heuristic(IntEnum): - """The supported heuristics.""" - - DEFAULT = 0 - ORTHOGONAL_X = 1 - ORTHOGONAL_Y = 2 - - -def astar_path( - weights: np.ndarray, - start: Tuple[int, int], - goal: Tuple[int, int], - allow_diagonal: bool = False, - heuristic_override: Heuristic = Heuristic.DEFAULT, -) -> Optional[np.ndarray]: - """ - Run astar algorithm on 2d weights. - - param np.ndarray weights: A grid of weights e.g. np.ones((10, 10), dtype=np.float32) - param Tuple[int, int] start: (i, j) - param Tuple[int, int] goal: (i, j) - param bool allow_diagonal: Whether to allow diagonal moves - param Heuristic heuristic_override: Override heuristic, see Heuristic(IntEnum) - - """ - assert ( - weights.dtype == np.float32 - ), f'weights must have np.float32 data type, but has {weights.dtype}' - # For the heuristic to be valid, each move must cost at least 1. - if weights.min(axis=None) < 1.0: - raise ValueError('Minimum cost to move must be 1, but got %f' % (weights.min(axis=None))) - # Ensure start is within bounds. - if start[0] < 0 or start[0] >= weights.shape[0] or start[1] < 0 or start[1] >= weights.shape[1]: - raise ValueError(f'Start of {start} lies outside grid.') - # Ensure goal is within bounds. - if goal[0] < 0 or goal[0] >= weights.shape[0] or goal[1] < 0 or goal[1] >= weights.shape[1]: - raise ValueError(f'Goal of {goal} lies outside grid.') - - height, width = weights.shape - start_idx = np.ravel_multi_index(start, (height, width)) - goal_idx = np.ravel_multi_index(goal, (height, width)) - - path = pyastar2d.astar.astar( - weights.flatten(), - height, - width, - start_idx, - goal_idx, - allow_diagonal, - int(heuristic_override), - ) - return path diff --git a/tpl/pyastar2d/tests/test_astar.py b/tpl/pyastar2d/tests/test_astar.py deleted file mode 100644 index 532a660..0000000 --- a/tpl/pyastar2d/tests/test_astar.py +++ /dev/null @@ -1,141 +0,0 @@ -import numpy as np -import pyastar2d -import pytest -from pyastar2d import Heuristic - - -def test_small(): - weights = np.array( - [[1, 3, 3, 3, 3], [2, 1, 3, 3, 3], [2, 2, 1, 3, 3], [2, 2, 2, 1, 3], [2, 2, 2, 2, 1]], - dtype=np.float32, - ) - # Run down the diagonal. - path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=True) - expected = np.array([[0, 0], [1, 1], [2, 2], [3, 3], [4, 4]]) - - assert np.all(path == expected) - - # Down, right, down, right, etc. - path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=False) - expected = np.array([[0, 0], [1, 0], [1, 1], [2, 1], [2, 2], [3, 2], [3, 3], [4, 3], [4, 4]]) - - assert np.all(path == expected) - - -def test_no_solution(): - # Vertical wall. - weights = np.ones((5, 5), dtype=np.float32) - weights[:, 2] = np.inf - - path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=True) - assert not path - - # Horizontal wall. - weights = np.ones((5, 5), dtype=np.float32) - weights[2, :] = np.inf - - path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=True) - assert not path - - -def test_match_reverse(): - # Might fail if there are multiple paths, but this should be rare. - h, w = 25, 25 - weights = (1.0 + 5.0 * np.random.random((h, w))).astype(np.float32) - - fwd = pyastar2d.astar_path(weights, (0, 0), (h - 1, w - 1)) - rev = pyastar2d.astar_path(weights, (h - 1, w - 1), (0, 0)) - - assert np.all(fwd[::-1] == rev) - - fwd = pyastar2d.astar_path(weights, (0, 0), (h - 1, w - 1), allow_diagonal=True) - rev = pyastar2d.astar_path(weights, (h - 1, w - 1), (0, 0), allow_diagonal=True) - - assert np.all(fwd[::-1] == rev) - - -def test_narrow(): - # Column weights. - weights = np.ones((5, 1), dtype=np.float32) - path = pyastar2d.astar_path(weights, (0, 0), (4, 0)) - - expected = np.array([[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]]) - - assert np.all(path == expected) - - # Row weights. - weights = np.ones((1, 5), dtype=np.float32) - path = pyastar2d.astar_path(weights, (0, 0), (0, 4)) - - expected = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]]) - - assert np.all(path == expected) - - -def test_bad_heuristic(): - # For valid heuristics, the cost to move must be at least 1. - weights = (1.0 + 5.0 * np.random.random((10, 10))).astype(np.float32) - # An element smaller than 1 should raise a ValueError. - bad_cost = np.random.random() / 2.0 - weights[4, 4] = bad_cost - - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 0), (9, 9)) - assert '.f' % bad_cost in exc.value.args[0] - - -def test_invalid_start_and_goal(): - weights = (1.0 + 5.0 * np.random.random((10, 10))).astype(np.float32) - # Test bad start indices. - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (-1, 0), (9, 9)) - assert '-1' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (10, 0), (9, 9)) - assert '10' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, -1), (9, 9)) - assert '-1' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 10), (9, 9)) - assert '10' in exc.value.args[0] - # Test bad goal indices. - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 0), (-1, 9)) - assert '-1' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 0), (10, 9)) - assert '10' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 0), (0, -1)) - assert '-1' in exc.value.args[0] - with pytest.raises(ValueError) as exc: - pyastar2d.astar_path(weights, (0, 0), (0, 10)) - assert '10' in exc.value.args[0] - - -def test_bad_weights_dtype(): - weights = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]], dtype=np.float64) - with pytest.raises(AssertionError) as exc: - pyastar2d.astar_path(weights, (0, 0), (2, 2)) - assert 'float64' in exc.value.args[0] - - -def test_orthogonal_x(): - weights = np.ones((5, 5), dtype=np.float32) - path = pyastar2d.astar_path( - weights, (0, 0), (4, 4), allow_diagonal=False, heuristic_override=Heuristic.ORTHOGONAL_X - ) - expected = np.array([[0, 0], [1, 0], [2, 0], [2, 1], [2, 2], [2, 3], [3, 3], [3, 4], [4, 4]]) - - assert np.all(path == expected) - - -def test_orthogonal_y(): - weights = np.ones((5, 5), dtype=np.float32) - path = pyastar2d.astar_path( - weights, (0, 0), (4, 4), allow_diagonal=False, heuristic_override=Heuristic.ORTHOGONAL_Y - ) - expected = np.array([[0, 0], [0, 1], [0, 2], [1, 2], [2, 2], [3, 2], [3, 3], [4, 3], [4, 4]]) - - assert np.all(path == expected) From 0f638059a70fa8a048e0ad5fc733d3e95d7c54b2 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 14:26:50 -0800 Subject: [PATCH 02/14] Revamped GitHub action workflows --- .github/workflows/codeql-analysis.yaml | 14 +++-- .github/workflows/docker-publish.yaml | 48 +++++++++------- .github/workflows/python-publish.yaml | 77 +++++++++++++++----------- .github/workflows/testing.yaml | 35 +++++------- 4 files changed, 95 insertions(+), 79 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 09bb853..b43860d 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -1,10 +1,12 @@ name: "CodeQL" on: - push: - branches: [ main ] pull_request: - branches: [ main ] + branches: + - main + push: + branches: + - main schedule: - cron: '0 0 * * 1' @@ -23,12 +25,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/docker-publish.yaml b/.github/workflows/docker-publish.yaml index da2779b..35ffc43 100644 --- a/.github/workflows/docker-publish.yaml +++ b/.github/workflows/docker-publish.yaml @@ -25,18 +25,15 @@ jobs: steps: - name: Checkout code - uses: nschloe/action-cached-lfs-checkout@v1.1.3 + uses: nschloe/action-cached-lfs-checkout@v1.2.3 with: - exclude: "batbot/*/models/pytorch/" + exclude: "examples/example[2-4].wav" - - uses: docker/setup-qemu-action@v1 + - uses: docker/setup-qemu-action@v3 name: Set up QEMU id: qemu - with: - image: tonistiigi/binfmt:latest - platforms: all - - uses: docker/setup-buildx-action@v1 + - uses: docker/setup-buildx-action@v3 name: Set up Docker Buildx id: buildx @@ -45,35 +42,43 @@ jobs: # Log into container registries - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: - username: batbot - password: ${{ secrets.BATBOT_DOCKER_HUB_TOKEN }} + username: ${{ vars.BATBOT_DOCKERHUB_USERNAME }} + password: ${{ secrets.BATBOT_DOCKERHUB_TOKEN }} - # Push tagged image (version tag + latest) to registries - - name: Tagged Docker Hub - if: ${{ github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') }} - run: | - VERSION=$(echo ${GITHUB_REF} | sed 's#.*/v##') - echo "IMAGE_TAG=${VERSION}" >> $GITHUB_ENV + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - # Push bleeding-edge image (main tag) to registries - - name: Bleeding Edge Docker Hub - if: github.ref == 'refs/heads/main' + # Push bleeding-edge image ("" tag) to registries + - name: Bleeding Edge Docker Hub (Default Option) run: | - echo "IMAGE_TAG=main" >> $GITHUB_ENV + TAG=$(echo ${GITHUB_REF_NAME} | sed 's/\//-/') + echo "IMAGE_TAG=${TAG}" >> $GITHUB_ENV - # Push nightly image (nightly tag) to registries + # Push nightly image ("nightly" tag) to registries - name: Nightly Docker Hub if: github.event_name == 'schedule' run: | echo "IMAGE_TAG=nightly" >> $GITHUB_ENV + # Push tagged image ("" tag) to registries + - name: Tagged Docker Hub + if: ${{ github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') }} + run: | + VERSION=$(echo ${GITHUB_REF} | sed 's#.*/v##') + echo "IMAGE_TAG=${VERSION}" >> $GITHUB_ENV + # Build images - name: Build Batbot run: | docker buildx build \ -t kitware/batbot:${{ env.IMAGE_TAG }} \ + -t ghcr.io/kitware/batbot:${{ env.IMAGE_TAG }} \ --platform linux/amd64 \ --push \ . @@ -84,6 +89,7 @@ jobs: run: | docker buildx build \ -t kitware/batbot:latest \ + -t ghcr.io/kitware/batbot:latest \ --platform linux/amd64 \ --push \ . diff --git a/.github/workflows/python-publish.yaml b/.github/workflows/python-publish.yaml index ba70428..2a0d59d 100644 --- a/.github/workflows/python-publish.yaml +++ b/.github/workflows/python-publish.yaml @@ -4,6 +4,7 @@ on: push: branches: - main + - jrp/ci-cd-fixes jobs: @@ -14,16 +15,16 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - python-version: [3.8] + python-version: [3.12] steps: - name: Checkout code - uses: nschloe/action-cached-lfs-checkout@v1.1.3 + uses: nschloe/action-cached-lfs-checkout@v1.2.3 with: - exclude: "batbot/*/models/pytorch/" + exclude: "examples/example[2-4].wav" - - uses: actions/setup-python@v2 - name: Install Python + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} @@ -33,8 +34,9 @@ jobs: pip install build python -m build --wheel --outdir dist/ . - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v6 with: + name: artifact-wheel-${{ matrix.os }}-${{ matrix.python-version }} path: ./dist/*.whl build_sdist: @@ -42,14 +44,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: nschloe/action-cached-lfs-checkout@v1.1.3 + uses: nschloe/action-cached-lfs-checkout@v1.2.3 with: - exclude: "batbot/*/models/pytorch/" + exclude: "examples/example[2-4].wav" - - uses: actions/setup-python@v2 - name: Install Python + - name: Set up Python 3.12 + uses: actions/setup-python@v6 with: - python-version: '3.8' + python-version: '3.12' - name: Build sdist run: | @@ -57,57 +59,68 @@ jobs: pip install build python -m build --sdist --outdir dist/ . - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v6 with: + name: artifact-sdist path: ./dist/*.tar.gz test_wheel: needs: [build_wheels, build_sdist] runs-on: ubuntu-latest - env: - CLASSIFIER_BATCH_SIZE: 16 # test wheel if: github.event_name == 'push' steps: - - uses: actions/setup-python@v2 - name: Install Python + - name: Set up Python 3.12 + uses: actions/setup-python@v6 with: - python-version: '3.8' + python-version: '3.12' - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v7 with: - name: artifact - path: dist + path: artifact - name: Install wheel run: | pip install --upgrade pip pip install wheel + find . + mkdir dist + cp artifact/*-ubuntu-*/*.whl dist/ + cp artifact/*/*.tar.gz dist/ pip install dist/*.whl - name: Test module run: | - python -c "import batbot; batbot.fetch(); batbot.example();" + python -c "import batbot;" - - name: Test CLI - run: | - batbot fetch - batbot example + # - name: Test CLI + # run: | + # batbot example upload_pypi: needs: [test_wheel] runs-on: ubuntu-latest # upload to PyPI on every tag starting with 'v' if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') + environment: + name: pypi + url: https://pypi.org/p/batbot + permissions: + id-token: write steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v7 with: - name: artifact - path: dist + path: artifact + + - name: Install wheel + run: | + find . + mkdir dist + cp artifact/*-ubuntu-*/*.whl dist/ + cp artifact/*/*.tar.gz dist/ - - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 with: - user: __token__ - password: ${{ secrets.PYPI_PASSWORD }} - # To test: repository_url: https://test.pypi.org/legacy/ + password: ${{ secrets.BATBOT_PYPI_TOKEN }} diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 6a5dbd9..3847e7b 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -8,55 +8,50 @@ on: push jobs: test: runs-on: ubuntu-latest + continue-on-error: true strategy: fail-fast: false matrix: # Use the same Python version used the Dockerfile - python-version: [3.9] + python-version: [3.12] env: OS: ubuntu-latest PYTHON: ${{ matrix.python-version }} - CLASSIFIER_BATCH_SIZE: 16 steps: # Checkout and env setup - name: Checkout code - uses: nschloe/action-cached-lfs-checkout@v1.1.3 + uses: nschloe/action-cached-lfs-checkout@v1.2.3 with: - exclude: "batbot/*/models/pytorch/" + exclude: "examples/example[3-4].wav" - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements.optional.txt + pip install -r requirements/runtime.txt + pip install -r requirements/optional.txt + pip install -e . - - name: Lint with flake8 + - name: Check with pre-commit run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --show-source --statistics - # exit-zero treats all errors as warnings. - flake8 . --count --exit-zero --max-complexity=10 --statistics + SKIP=hadolint pre-commit + SKIP=hadolint pre-commit run --all-files - - name: Run tests + - name: Run tests and coverage run: | set -ex - pytest --cov=./ --cov-append --random-order-seed=1 - - - name: Run coverage - run: | - coverage xml + pytest --cov=batbot --cov-append --cov-report=xml --random-order-seed=1 - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1.2.1 + uses: codecov/codecov-action@v5 with: - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.BATBOT_CODECOV_TOKEN }} files: ./coverage/coverage.xml env_vars: OS,PYTHON fail_ci_if_error: true From 4a77aa66cf6475775b12c5792328a4c9d84b8058 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 14:28:19 -0800 Subject: [PATCH 03/14] Updated build environment and Docker instructions with pyastar2d --- Dockerfile | 15 ++++++--------- pyproject.toml | 1 + requirements/optional.txt | 12 +++++++++--- requirements/runtime.txt | 11 ++++------- setup.cfg | 19 +++++-------------- 5 files changed, 25 insertions(+), 33 deletions(-) diff --git a/Dockerfile b/Dockerfile index b486449..7e57c27 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,14 +31,11 @@ RUN python3 -m venv /venv # hadolint ignore=DL3003,DL3013 RUN /venv/bin/pip install --no-cache-dir -r requirements/runtime.txt \ && /venv/bin/pip install --no-cache-dir -r requirements/optional.txt \ - && cd tpl/pyastar2d/ \ - && /venv/bin/pip install --no-cache-dir -e . \ - && cd ../.. \ - && /venv/bin/pip install --no-cache-dir -e . \ - && if [ "$(uname -m)" != "aarch64" ] \ - ; then \ - /venv/bin/pip uninstall -y onnxruntime \ - /venv/bin/pip install --no-cache-dir onnxruntime-gpu \ - ; fi + && /venv/bin/pip install --no-cache-dir -e . + # && if [ "$(uname -m)" != "aarch64" ] \ + # ; then \ + # /venv/bin/pip uninstall -y onnxruntime \ + # /venv/bin/pip install --no-cache-dir onnxruntime-gpu \ + # ; fi CMD [".", "/venv/bin/activate", "&&", "exec", "python", "app.py"] diff --git a/pyproject.toml b/pyproject.toml index d1e6ae6..9787c3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,3 @@ [build-system] requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/requirements/optional.txt b/requirements/optional.txt index c9f61f3..8dcdc59 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -2,10 +2,11 @@ black codecov coverage flake8 -imageio +# gradio ipython -line_profiler -onnx +isort +# onnx +# onnxruntime pre-commit pytest pytest-benchmark[histogram] @@ -15,7 +16,12 @@ pytest-profiling pytest-random-order pytest-sugar pytest-xdist +pyupgrade pyyaml +rstcheck +rstcheck[sphinx] Sphinx>=5,<6 sphinx_rtd_theme +# torch +# torchvision xdoctest diff --git a/requirements/runtime.txt b/requirements/runtime.txt index c0f4bc6..9f94278 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -1,19 +1,16 @@ click -codecov -coverage cryptography cython -gradio -imgaug librosa +line_profiler matplotlib numpy -onnxruntime opencv-python-headless Pillow pooch +pyastar2d @ git+https://github.com/bluemellophone/batbot-pyastar2d@master rich +scikit-image +shapely sphinx-click -torch -torchvision tqdm diff --git a/setup.cfg b/setup.cfg index cd2fb4f..d73eb80 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,26 +16,23 @@ project_urls = [options] packages = find: platforms = any -include_package_data = True +include_package_data = true install_requires = click - codecov - coverage cryptography cython - gradio - imgaug librosa + line_profiler matplotlib numpy - onnxruntime opencv-python-headless Pillow pooch + pyastar2d @ git+https://github.com/bluemellophone/batbot-pyastar2d@master rich + scikit-image + shapely sphinx-click - torch - torchvision tqdm python_requires = >=3.7 @@ -43,12 +40,6 @@ python_requires = >=3.7 console_scripts = batbot = batbot.batbot:cli -[bdist_wheel] -universal = 1 - -[aliases] -test=pytest - [tool:pytest] minversion = 5.4 addopts = -v -p no:doctest --xdoctest --xdoctest-style=google --random-order --random-order-bucket=global --cov=./ --cov-report html -m "not separate" --durations-min=1.0 --color=yes --code-highlight=yes --show-capture=log -ra From e1ccb4226f7ded73b613a0f8b36de4fee4b2a118 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 14:28:51 -0800 Subject: [PATCH 04/14] Bug fixes for macOS and loosen tests --- batbot/__init__.py | 3 +- batbot/spectrogram/__init__.py | 337 ++++++++++++++++++--------------- tests/test_batbot.py | 8 - tests/test_spectrogram.py | 2 +- 4 files changed, 191 insertions(+), 159 deletions(-) diff --git a/batbot/__init__.py b/batbot/__init__.py index 9180fb8..111778f 100644 --- a/batbot/__init__.py +++ b/batbot/__init__.py @@ -94,7 +94,8 @@ def pipeline( """ # Generate spectrogram output_paths, metadata_path, metadata = spectrogram.compute(filepath) - raise NotImplementedError + + return output_paths, metadata_path def batch( diff --git a/batbot/spectrogram/__init__.py b/batbot/spectrogram/__init__.py index 074030a..5cfa2d5 100644 --- a/batbot/spectrogram/__init__.py +++ b/batbot/spectrogram/__init__.py @@ -114,9 +114,6 @@ def plot_histogram( output_path='.', output_filename='histogram.png', ): - if output_path is None: - return - if max_val is None: max_val = int(image.max()) @@ -140,11 +137,16 @@ def plot_histogram( hist_original = (hist_original / hist_original.max()) * hist.max() hist_ = np.argmax(hist) - hist_std = np.abs(image - hist_).mean() + image_ = image.astype(np.int32) + hist_std = np.abs(image_ - hist_).mean() csum = np.cumsum(hist) / hist.sum() csum_ = np.where(csum >= csum_threshold)[0].min() + retval = med_, std_, (hist_, hist_std) + if output_path is None: + return retval + y_max = hist.max() * 1.01 # Plot the histogram plt.figure(figsize=(7, 7)) @@ -165,7 +167,7 @@ def plot_histogram( [0, y_max], color='grey', linestyle='--', - label=f'Histogram Peak ({hist_:0.01f})', + label=f'Histogram Peak ({hist_:0.01f} +/- {hist_std:0.01f})', ) plt.plot( [csum_] * 2, @@ -193,7 +195,7 @@ def plot_histogram( ) plt.close('all') - return med_, std_, (hist_, hist_std) + return retval def generate_waveplot( @@ -830,7 +832,7 @@ def calculate_astar_grid_and_endpoints( costs = segment.copy() segmentmask_ = np.logical_not(segmentmask) costs[segmentmask_] = 0 - write_contour_debug_image(costs, index, 7, 'costs', output_path=output_path) + write_contour_debug_image(costs, index, 8, 'costs', output_path=output_path) ys, xs = np.where(costs > 0) points = np.stack([ys, xs], axis=1, dtype=np.float32) @@ -857,15 +859,15 @@ def calculate_astar_grid_and_endpoints( grid += 1 assert grid.min() > 0 - if output_path: - bounds = np.where(np.sum(costs, axis=0) > 0) - left = int(np.min(bounds)) - right = int(np.max(bounds)) - bounds = np.where(np.sum(costs, axis=1) > 0) - top = int(np.min(bounds)) - bottom = int(np.max(bounds)) - boundary = (top, bottom, left, right) + bounds = np.where(np.sum(costs, axis=0) > 0) + left = int(np.min(bounds)) + right = int(np.max(bounds)) + bounds = np.where(np.sum(costs, axis=1) > 0) + top = int(np.min(bounds)) + bottom = int(np.max(bounds)) + boundary = (top, bottom, left, right) + if output_path: height, width = costs.shape value = np.iinfo(canvas.dtype).max @@ -879,7 +881,7 @@ def calculate_astar_grid_and_endpoints( cv2.circle(canvas, begin[::-1], 5, (0, value, 0), -1) cv2.circle(canvas, end[::-1], 5, (0, 0, value), -1) - write_contour_debug_image(canvas, index, 7, 'endpoints', output_path=output_path) + write_contour_debug_image(canvas, index, 8, 'endpoints', output_path=output_path) costs = segment.astype(np.float32) segmentmask_ = segmentmask.astype(np.float32) @@ -1070,44 +1072,45 @@ def scale_pdf_contour(segment, index, output_path='.'): if np.any(np.isnan(y)): return segment, None, None - # Plot the histogram - plt.figure(figsize=(7, 7)) - plt.title('Inverse PDF Scaling', y=1.16) - plt.xlim([segment.min(), segment.max()]) - plt.ylim([-0.01, 1.01]) - plt.xlabel('Frequency') - plt.ylabel('Probability') - - plt.axvspan(peak_db - 3 * peak_db_std, peak_db + 3 * peak_db_std, color='grey', alpha=0.15) - plt.axvspan(peak_db - 2 * peak_db_std, peak_db + 2 * peak_db_std, color='grey', alpha=0.15) - plt.axvspan( - peak_db - 1 * peak_db_std, - peak_db + 1 * peak_db_std, - color='grey', - alpha=0.15, - label='Standard Deviations σ={1,2,3}', - ) - plt.plot( - [peak_db] * 2, [0, 1], color='orange', linestyle='--', label='Peak Histogram Frequency' - ) - plt.axhline(0, color='black', linestyle='--', alpha=0.5) - plt.axhline(1, color='black', linestyle='--', alpha=0.5) - plt.plot(x, scaling, label='Weighting') + if output_path: + # Plot the histogram + plt.figure(figsize=(7, 7)) + plt.title('Inverse PDF Scaling', y=1.16) + plt.xlim([segment.min(), segment.max()]) + plt.ylim([-0.01, 1.01]) + plt.xlabel('Frequency') + plt.ylabel('Probability') + + plt.axvspan(peak_db - 3 * peak_db_std, peak_db + 3 * peak_db_std, color='grey', alpha=0.15) + plt.axvspan(peak_db - 2 * peak_db_std, peak_db + 2 * peak_db_std, color='grey', alpha=0.15) + plt.axvspan( + peak_db - 1 * peak_db_std, + peak_db + 1 * peak_db_std, + color='grey', + alpha=0.15, + label='Standard Deviations σ={1,2,3}', + ) + plt.plot( + [peak_db] * 2, [0, 1], color='orange', linestyle='--', label='Peak Histogram Frequency' + ) + plt.axhline(0, color='black', linestyle='--', alpha=0.5) + plt.axhline(1, color='black', linestyle='--', alpha=0.5) + plt.plot(x, scaling, label='Weighting') - plt.legend( - bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), - loc=3, - ncol=1, - mode='expand', - borderaxespad=0.0, - ) + plt.legend( + bbox_to_anchor=(0.0, 1.02, 1.0, 0.102), + loc=3, + ncol=1, + mode='expand', + borderaxespad=0.0, + ) - plt.savefig( - join(output_path, f'contour.{index}.00.histogram.scaling.png'), - dpi=150, - bbox_inches='tight', - ) - plt.close('all') + plt.savefig( + join(output_path, f'contour.{index}.00.histogram.scaling.png'), + dpi=150, + bbox_inches='tight', + ) + plt.close('all') scaling = np.hstack((scaling, scaling[-1:])) mask = scaling[segment - segment.min()] @@ -1137,12 +1140,13 @@ def find_contour_and_peak( ) # Display the image and plot all contours found - fig, ax = plt.subplots() - ax.imshow(segment, cmap=plt.cm.gray) - ax.set_xticks([]) - ax.set_xticklabels([]) - ax.set_yticks([]) - ax.set_yticklabels([]) + if output_path: + fig, ax = plt.subplots() + ax.imshow(segment, cmap=plt.cm.gray) + ax.set_xticks([]) + ax.set_xticklabels([]) + ax.set_yticks([]) + ax.set_yticklabels([]) max_points = [Point(*value) for value in max_locations] counter = {} @@ -1154,10 +1158,12 @@ def find_contour_and_peak( if polygon.contains(max_point): found.append(max_location) if len(found) > 0: - ax.plot(contour[:, 1], contour[:, 0], linewidth=2) x = gaussian_filter1d(contour[:, 1], sigma) y = gaussian_filter1d(contour[:, 0], sigma) - ax.plot(x, y, linewidth=1, linestyle='--') + + if output_path: + ax.plot(contour[:, 1], contour[:, 0], linewidth=2) + ax.plot(x, y, linewidth=1, linestyle='--') contour_ = np.vstack((y, x), dtype=contour.dtype).T polygon_ = Polygon(contour).convex_hull @@ -1167,13 +1173,14 @@ def find_contour_and_peak( rr, cc = draw.polygon(contour_[:, 0], contour_[:, 1], shape=segment.shape) segmentmask[rr, cc] = True - plt.savefig( - join(output_path, f'contour.{index}.05.contour.png'), - dpi=150, - pad_inches=0, - bbox_inches='tight', - ) - plt.close('all') + if output_path: + plt.savefig( + join(output_path, f'contour.{index}.05.contour.png'), + dpi=150, + pad_inches=0, + bbox_inches='tight', + ) + plt.close('all') # segmentmask = np.ones(segment.shape, dtype=bool) @@ -1220,11 +1227,12 @@ def calculate_harmonic_and_echo_flags( harmonic_peak = None if harmonic_flag: - temp = canvas.copy() - temp[:, :, 2][harmonic] = np.iinfo(original.dtype).max - canvas = np.around( - (canvas.astype(np.float32) * 0.5) + (temp.astype(np.float32) * 0.5) - ).astype(canvas.dtype) + if output_path: + temp = canvas.copy() + temp[:, :, 2][harmonic] = np.iinfo(original.dtype).max + canvas = np.around( + (canvas.astype(np.float32) * 0.5) + (temp.astype(np.float32) * 0.5) + ).astype(canvas.dtype) try: temp = original.copy() temp[~harmonic] = 0 @@ -1235,11 +1243,12 @@ def calculate_harmonic_and_echo_flags( echo_peak = None if echo_flag: - temp = canvas.copy() - temp[:, :, 0][echo] = np.iinfo(original.dtype).max - canvas = np.around( - (canvas.astype(np.float32) * 0.5) + (temp.astype(np.float32) * 0.5) - ).astype(canvas.dtype) + if output_path: + temp = canvas.copy() + temp[:, :, 0][echo] = np.iinfo(original.dtype).max + canvas = np.around( + (canvas.astype(np.float32) * 0.5) + (temp.astype(np.float32) * 0.5) + ).astype(canvas.dtype) try: temp = original.copy() temp[~echo] = 0 @@ -1253,7 +1262,7 @@ def calculate_harmonic_and_echo_flags( @lp def compute_wrapper( - wav_filepath, annotations=None, output_folder='.', bitdepth=16, debug=True, **kwargs + wav_filepath, annotations=None, output_folder='.', bitdepth=16, debug=False, **kwargs ): """ Compute the spectrograms for a given input WAV and saves them to disk. @@ -1299,6 +1308,7 @@ def compute_wrapper( bands = bands[::-1] y_step_freq = float(bands[0] - bands[1]) x_step_ms = float((1e3 * duration) / stft_db.shape[1]) + bands = np.around(bands).astype(np.int32).tolist() # # Save the spectrogram image to disk # cv2.imwrite('debug.tif', stft_db, [cv2.IMWRITE_TIFF_COMPRESSION, 1]) @@ -1338,6 +1348,8 @@ def compute_wrapper( } metas = [] for index, (start, stop) in tqdm.tqdm(list(enumerate(ranges))): + if index == 1: + break segment = stft_db[:, start:stop] # Step 0.1 - Debugging setup and find peak amplitude (will return None if disabled) @@ -1388,12 +1400,12 @@ def compute_wrapper( original, index, segmentmask, harmonic, echo, canvas, output_path=debug_path ) - # Step 8 - Remove harmonic and echo from segmentation + # Remove harmonic and echo from segmentation segment = remove_harmonic_and_echo( segment, index, harmonic, echo, threshold, output_path=debug_path ) - # Step 7 - Calculate the A* cost grid and start/end points + # Step 8 - Calculate the A* cost grid and start/end points costs, grid, begin, end, boundary = calculate_astar_grid_and_endpoints( segment, index, segmentmask, peak, canvas, output_path=debug_path ) @@ -1406,17 +1418,17 @@ def compute_wrapper( if not significant: continue - # Step 8 - Extract optimal path from start to end using the cost grid + # Step 9 - Extract optimal path from start to end using the cost grid path = extract_contour_path(grid, begin, end, canvas, index, output_path=debug_path) - # Step 9 - Extract contour keypoints + # Step 10 - Extract contour keypoints path_smoothed, (knee, fc, heel), slopes = extract_contour_keypoints( path, canvas, index, peak, output_path=debug_path ) - # Step 10 - Collect chirp metadata + # Step 11 - Collect chirp metadata metadata = { - 'curve.(khz,ms)': [ + 'curve.(hz,ms)': [ ( bands[y], (start + x) * x_step_ms, @@ -1430,19 +1442,19 @@ def compute_wrapper( 'fc.ms': (start + bands[fc[1]]) * x_step_ms, 'hi fc:knee.ms': (start + bands[knee[1]]) * x_step_ms, 'lo fc:heel.ms': (start + bands[heel[1]]) * x_step_ms, - 'bandwidth.khz': bandwidth, - 'hi f.khz': bands[top], - 'lo f.khz': bands[bottom], - 'peak f.khz': bands[peak[0]], - 'fc.khz': bands[fc[0]], - 'hi fc:knee.khz': bands[knee[0]], - 'lo fc:heel.khz': bands[heel[0]], + 'bandwidth.hz': bandwidth, + 'hi f.hz': bands[top], + 'lo f.hz': bands[bottom], + 'peak f.hz': bands[peak[0]], + 'fc.hz': bands[fc[0]], + 'hi fc:knee.hz': bands[knee[0]], + 'lo fc:heel.hz': bands[heel[0]], 'harmonic.flag': harmonic_flag, 'harmonic peak f.ms': (start + hamonic_peak[1]) * x_step_ms if harmonic_flag else None, - 'harmonic peak f.khz': bands[hamonic_peak[0]] if harmonic_flag else None, + 'harmonic peak f.hz': bands[hamonic_peak[0]] if harmonic_flag else None, 'echo.flag': echo_flag, 'echo peak f.ms': (start + echo_peak[1]) * x_step_ms if echo_flag else None, - 'echo peak f.khz': bands[echo_peak[0]] if echo_flag else None, + 'echo peak f.hz': bands[echo_peak[0]] if echo_flag else None, } metadata.update(slopes) @@ -1450,18 +1462,20 @@ def compute_wrapper( for key, value in list(metadata.items()): if value is None: continue - if key.endswith('.ms') or key.endswith('.khz'): + if key.endswith('.ms'): metadata[key] = round(float(value), 3) + if key.endswith('.hz'): + metadata[key] = int(round(value)) if key.endswith('.flag'): metadata[key] = bool(value) if key.endswith('.y_px/x_px'): key_ = key.replace('.y_px/x_px', '.khz/ms') - metadata[key_] = round(float(value * (y_step_freq / x_step_ms)), 9) + metadata[key_] = round(float(value * ((y_step_freq / 1000.0) / x_step_ms)), 3) metadata.pop(key) - if key.endswith('.(khz,ms)'): + if key.endswith('.(hz,ms)'): metadata[key] = [ ( - round(float(val1), 3), + int(round(val1)), round(float(val2), 3), ) for val1, val2 in value @@ -1477,60 +1491,81 @@ def compute_wrapper( segments['stft_db'].append(stft_db[:, start + trim_begin : start + trim_end]) segments['waveplot'].append(waveplot[:, start + trim_begin : start + trim_end]) segments['costs'].append(costs[:, trim_begin:trim_end]) - segments['canvas'].append(canvas[:, trim_begin:trim_end]) + if debug_path: + segments['canvas'].append(canvas[:, trim_begin:trim_end]) - for key in segments: + for key in list(segments.keys()): value = segments[key] - segments[key] = np.hstack(value) if len(value) > 0 else None.copy() + if len(value) == 0: + segments.pop(key) + continue + segments[key] = np.hstack(value) if debug_path: cv2.imwrite(join(debug_path, 'spectrogram.tif'), stft_db, [cv2.IMWRITE_TIFF_COMPRESSION, 1]) - cv2.imwrite( - join(debug_path, 'spectrogram.compressed.tif'), - segments['stft_db'], - [cv2.IMWRITE_TIFF_COMPRESSION, 1], - ) cv2.imwrite(join(debug_path, 'spectrogram.waveplot.png'), waveplot) - cv2.imwrite(join(debug_path, 'spectrogram.compressed.waveplot.png'), segments['waveplot']) - temp_top = np.stack((segments['stft_db'], segments['stft_db'], segments['stft_db']), axis=2) - temp_bot = cv2.resize( - segments['waveplot'], temp_top.shape[:2][::-1], interpolation=cv2.INTER_LINEAR - ) - temp_bot = temp_bot.astype(np.float32) * ( - np.iinfo(temp_top.dtype).max / np.iinfo(temp_bot.dtype).max - ) - temp_bot = np.around(temp_bot).astype(temp_top.dtype) - temp = np.vstack((temp_top, temp_bot)) - cv2.imwrite(join(debug_path, 'spectrogram.compressed.combined.png'), temp) - cv2.imwrite( - join(debug_path, 'spectrogram.compressed.threshold.tif'), - segments['costs'], - [cv2.IMWRITE_TIFF_COMPRESSION, 1], - ) - temp = segments['costs'].copy() - flags = segments['costs'] == 0 - temp = normalize_stft(temp, None, np.uint8) - temp = cv2.applyColorMap(temp, cv2.COLORMAP_JET) - temp[:, :, 0][flags] = 0 - temp[:, :, 1][flags] = 0 - temp[:, :, 2][flags] = 0 - cv2.imwrite( - join(debug_path, 'spectrogram.compressed.threshold.jet.tif'), - temp, - [cv2.IMWRITE_TIFF_COMPRESSION, 1], - ) - cv2.imwrite( - join(debug_path, 'spectrogram.compressed.keypoints.tif'), - segments['canvas'], - [cv2.IMWRITE_TIFF_COMPRESSION, 1], - ) + + if 'stft_db' in segments: + cv2.imwrite( + join(debug_path, 'spectrogram.compressed.tif'), + segments['stft_db'], + [cv2.IMWRITE_TIFF_COMPRESSION, 1], + ) + + if 'waveplot' in segments: + cv2.imwrite( + join(debug_path, 'spectrogram.compressed.waveplot.png'), segments['waveplot'] + ) + + if 'stft_db' in segments and 'waveplot' in segments: + temp_top = np.stack( + (segments['stft_db'], segments['stft_db'], segments['stft_db']), axis=2 + ) + temp_bot = cv2.resize( + segments['waveplot'], temp_top.shape[:2][::-1], interpolation=cv2.INTER_LINEAR + ) + temp_bot = temp_bot.astype(np.float32) * ( + np.iinfo(temp_top.dtype).max / np.iinfo(temp_bot.dtype).max + ) + temp_bot = np.around(temp_bot).astype(temp_top.dtype) + temp = np.vstack((temp_top, temp_bot)) + cv2.imwrite(join(debug_path, 'spectrogram.compressed.combined.png'), temp) + + if 'costs' in segments: + cv2.imwrite( + join(debug_path, 'spectrogram.compressed.threshold.tif'), + segments['costs'], + [cv2.IMWRITE_TIFF_COMPRESSION, 1], + ) + temp = segments['costs'].copy() + flags = segments['costs'] == 0 + temp = normalize_stft(temp, None, np.uint8) + temp = cv2.applyColorMap(temp, cv2.COLORMAP_JET) + temp[:, :, 0][flags] = 0 + temp[:, :, 1][flags] = 0 + temp[:, :, 2][flags] = 0 + cv2.imwrite( + join(debug_path, 'spectrogram.compressed.threshold.jet.tif'), + temp, + [cv2.IMWRITE_TIFF_COMPRESSION, 1], + ) + + if 'canvas' in segments: + cv2.imwrite( + join(debug_path, 'spectrogram.compressed.keypoints.tif'), + segments['canvas'], + [cv2.IMWRITE_TIFF_COMPRESSION, 1], + ) output_paths = [] compressed_paths = [] datas = [ (output_paths, 'jpg', stft_db), - (compressed_paths, 'compressed.jpg', segments['stft_db']), ] + if 'stft_db' in segments: + datas += [ + (compressed_paths, 'compressed.jpg', segments['stft_db']), + ] for accumulator, tag, data in datas: if data.dtype != np.uint8: @@ -1559,29 +1594,33 @@ def compute_wrapper( metadata = { 'wav.path': wav_filepath, 'spectrogram': { - 'true.path': output_paths, + 'uncompressed.path': output_paths, 'compressed.path': compressed_paths, }, 'threshold.amp': int(round(255.0 * (threshold / max_value))), - 'sr.khz': sr, + 'sr.hz': int(sr), 'duration.ms': round(duration * 1e3, 3), 'frequencies': { - 'min.khz': int(FREQ_MIN), - 'max.khz': int(FREQ_MAX), - 'pixels.khz': [round(float(band), 3) for band in bands], + 'min.hz': int(FREQ_MIN), + 'max.hz': int(FREQ_MAX), + 'pixels.hz': bands, }, 'size': { - 'true': { + 'uncompressed': { 'width.px': stft_db.shape[1], 'height.px': stft_db.shape[0], }, - 'compressed': { - 'width.px': segments['stft_db'].shape[1], - 'height.px': segments['stft_db'].shape[0], - }, + 'compressed': None, }, 'segments': metas, } + if 'stft_db' in segments: + metadata['size']['compressed'] = ( + { + 'width.px': segments['stft_db'].shape[1], + 'height.px': segments['stft_db'].shape[0], + }, + ) metadata_path = join(output_folder, f'{base}.metadata.json') with open(metadata_path, 'w') as metafile: diff --git a/tests/test_batbot.py b/tests/test_batbot.py index 3a1db9b..73bfea8 100644 --- a/tests/test_batbot.py +++ b/tests/test_batbot.py @@ -1,13 +1,5 @@ import batbot -def test_fetch(): - batbot.fetch(pull=False) - batbot.fetch(pull=True) - - batbot.fetch(pull=False, config='usgs') - batbot.fetch(pull=True, config='usgs') - - def test_example(): batbot.example() diff --git a/tests/test_spectrogram.py b/tests/test_spectrogram.py index 69f8fe5..dcf03d5 100644 --- a/tests/test_spectrogram.py +++ b/tests/test_spectrogram.py @@ -4,5 +4,5 @@ def test_spectrogram_compute(): from batbot.spectrogram import compute - wav_filepath = abspath(join('examples', 'example1.wav')) + wav_filepath = abspath(join('examples', 'example2.wav')) output_paths, metadata_path, metadata = compute(wav_filepath) From d25c0ff4bbcbf0828cb0ce48568df67fe10a58dc Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 14:29:04 -0800 Subject: [PATCH 05/14] Updated project files and README --- .gitignore | 2 ++ ISSUES.rst | 7 +++- MANIFEST.in | 2 -- README.rst | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 100 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 27845ac..fc61cae 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ output.*.jpg *.log* +build/ +dist/ *.egg-info/ .coverage* diff --git a/ISSUES.rst b/ISSUES.rst index 4838b22..078a561 100644 --- a/ISSUES.rst +++ b/ISSUES.rst @@ -2,4 +2,9 @@ Known Issues ============ -N/A +TODO: +- Fix CI/CD docker build +- Add API documentation, tutorials, and examples +- Create example notebooks with Google colab +- Crate discord / discourse community board +- [BatAI] Upload training scripts with MLFlow support, database export with celery diff --git a/MANIFEST.in b/MANIFEST.in index 3a2e5b8..e38272b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,3 @@ -include pyproject.toml - # Include the README and SECURITY documents include *.rst diff --git a/README.rst b/README.rst index 6461011..011c392 100644 --- a/README.rst +++ b/README.rst @@ -9,6 +9,94 @@ Kitware BatBot .. sectnum:: +Development Environment +----------------------- + +.. code-block:: bash + # Find repo on host machine + cd ~/code/batbot + + # Build Docker image + docker build -t kitware/batbot:latest . + + # Start Docker container using image + docker run \ + -it \ + --rm \ + --entrypoint bash \ + --name batbot \ + -v $(pwd):/code \ + kitware/batbot:latest + + ######################## + # Inside the container # + ######################## + + # Activate Python environment + source /venv/bin/activate + + # Install local version + pip install -e . + + # Run batbot + batbot --help + +Spectrogram Extraction +---------------------- + +Here are the steps for extracting the compressed spectrogram: + +* Create the STFT + + * Load the original waveform at the original sample rate + * Resample waveform to 250kHz + * Convert to a STFT spectrogram (fft=512, method=blackmanharris, window=256, hop=16) + * Convert complex power STFT to amplitude STFT (dB) + +* Normalize the STFT + + * Trim STFT to minimum and maximum frequencies (5kHz to 120kHz) + * Subtract the per-freqency median dB (reduce any spectral bias / shift) + * Set global dynamic range to -80 dB from the global maximum amplitude + * Calculate the global median non-minimum dB (greater than -80dB) + * Calculate the median absolute deviation (MAD) + * Autogain the dynamic range to (5 * MAD) below the global amplitude median, if necessary + +* Quantize the STFT + + * Quantize the floating-point amplitude STFT to a 16-bit integer representation spanning the full dynamic range (65,536 bins) + * Vertically flip the spectrogram (low frequencies on bottom) and convert to a C-contiguous array + +* Find Candidate Chirps + + * Create a 12ms sliding window with a 3ms stride + * Keep the time windows that show a substantial right-skew across 10% of the frequency range + * Add any user-provided time windows (annotations) to the found candidates windows + * Merge any overlapping time windows into a set of contiguous time ranges + * Tighten the candidate time ranges (and separate as needed) by repeating the same skew-based filter with a smaller sliding window and stride + +* Extract Chirp Metrics + + * *for each candidate chirp* + * *Start*: First, find the peak amplitude location. + * Step 1 - Normalize the chirp to the full 16-bit range. Calculate a histogram and identify the most common dB and standard deviation. Scale the amplitude values using an inverted PDF, weighting each value by its inverse probability of being noise (values below the most common dB are set to zero) + * Step 2 - Apply a median filter and re-normalize + * Step 3 - Apply a morphological open operation + * Step 4 - Blur the chirp (k=5) and re-normalize + * Step 5 - Find contours using the "marching squares" algorithm and select the one that contains the peak amplitude. Extract the convex hull of the contour and smooth the resulting outline + * Step 6 - Extract a segmentation mask for the contour + * Step 7 - Locate the harmonic (doubling the frequency) and echo (right edge of the contour to the end of the chirp time range) regions. Remove any overlapping noise from the chirp contour. + * Step 8 - Locate the start, end, and characteristic frequency points (peak amplitude) and calculate an optimization cost grid for the contour using the masked amplitudes. + * Step 9 - Solve a minimum distance optimization using A* that also maximizes the amplutide values from start to end points. + * Step 10 - Smooth the contour path, extract the contour's slope, then identify the knee, heel, and other defining attributes. + * *End*: Finally, if any of the above steps fails, or the chirp's attributes do not make semantic sense, then skip the candidate chirp. + +* Create Output + + * Collect all valid chirps regions and metadata, create a compressed spectrogram + * Write the 16-bit spectrogram as a series of 8-bit JPEGs image chunks (max width per chunk 50k pixels) + * Write the file and chirp metadata to a JSON file. + How to Install -------------- @@ -200,16 +288,16 @@ Reference `pre-commit's installation instructions `_. Furthermore, try to conform to ``PEP8``. You should set up your preferred editor to use ``flake8`` as its Python linter, but pre-commit will ensure compliance before a git commit is completed. This will use the ``flake8`` configuration within ``setup.cfg``, which ignores several errors and stylistic considerations. See the ``setup.cfg`` file for a full and accurate listing of stylistic codes to ignore. -.. |Tests| image:: https://github.com/Kitware/batbot/actions/workflows/testing.yml/badge.svg?branch=main - :target: https://github.com/Kitware/batbot/actions/workflows/testing.yml +.. |Tests| image:: https://github.com/Kitware/batbot/actions/workflows/testing.yaml/badge.svg?branch=main + :target: https://github.com/Kitware/batbot/actions/workflows/testing.yaml :alt: GitHub CI .. |Codecov| image:: https://codecov.io/gh/Kitware/batbot/branch/main/graph/badge.svg?token=FR6ITMWQNI :target: https://app.codecov.io/gh/Kitware/batbot :alt: Codecov -.. |Wheel| image:: https://github.com/Kitware/batbot/actions/workflows/python-publish.yml/badge.svg - :target: https://github.com/Kitware/batbot/actions/workflows/python-publish.yml +.. |Wheel| image:: https://github.com/Kitware/batbot/actions/workflows/python-publish.yaml/badge.svg + :target: https://github.com/Kitware/batbot/actions/workflows/python-publish.yaml :alt: Python Wheel .. |Docker| image:: https://img.shields.io/docker/image-size/kitware/batbot/latest From 6b3f228de2f3df00ee79aeb6e6f3d50697b465c7 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 15:02:27 -0800 Subject: [PATCH 06/14] Small action tweaks --- .github/workflows/codeql-analysis.yaml | 8 ++++---- .github/workflows/testing.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index b43860d..d5bbf7e 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -21,16 +21,16 @@ jobs: language: [ 'python' ] steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 3847e7b..a524773 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -8,7 +8,6 @@ on: push jobs: test: runs-on: ubuntu-latest - continue-on-error: true strategy: fail-fast: false matrix: @@ -49,6 +48,7 @@ jobs: pytest --cov=batbot --cov-append --cov-report=xml --random-order-seed=1 - name: Upload coverage to Codecov + continue-on-error: true uses: codecov/codecov-action@v5 with: token: ${{ secrets.BATBOT_CODECOV_TOKEN }} From 75b079cd89c0d641a1da3038911cdbc4ec9cb3c8 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 15:14:28 -0800 Subject: [PATCH 07/14] Remove break --- batbot/spectrogram/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/batbot/spectrogram/__init__.py b/batbot/spectrogram/__init__.py index 5cfa2d5..4adaaae 100644 --- a/batbot/spectrogram/__init__.py +++ b/batbot/spectrogram/__init__.py @@ -1348,8 +1348,6 @@ def compute_wrapper( } metas = [] for index, (start, stop) in tqdm.tqdm(list(enumerate(ranges))): - if index == 1: - break segment = stft_db[:, start:stop] # Step 0.1 - Debugging setup and find peak amplitude (will return None if disabled) From 49ef635a45542d3754f35ffa200c5ba369d4c8cd Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 16:06:42 -0800 Subject: [PATCH 08/14] Add project logo --- README.rst | 4 ++++ assets/logo.png | Bin 0 -> 237374 bytes 2 files changed, 4 insertions(+) create mode 100644 assets/logo.png diff --git a/README.rst b/README.rst index 011c392..fde5711 100644 --- a/README.rst +++ b/README.rst @@ -4,6 +4,10 @@ Kitware BatBot |Tests| |Codecov| |Wheel| |Docker| |ReadTheDocs| |Huggingface| +image:: https://raw.githubusercontent.com/Kitware/batbot/jrp/ci-cd-fixes/assets/logo.png + :alt: Batbot + :align: center + .. contents:: Quick Links :backlinks: none diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4501cb8a59603dcf7567e1134606229661048a7c GIT binary patch literal 237374 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�DbQ!WN_ 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 UlW5CL-T(jq07*qoM6N<$f-~lbR{#J2 literal 0 HcmV?d00001 From 8bd21cb7a9fa0c43b0029fb745e66dc7d3f9b962 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 16:12:41 -0800 Subject: [PATCH 09/14] Updated URL --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index fde5711..5bfed5f 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ Kitware BatBot |Tests| |Codecov| |Wheel| |Docker| |ReadTheDocs| |Huggingface| -image:: https://raw.githubusercontent.com/Kitware/batbot/jrp/ci-cd-fixes/assets/logo.png +.. image:: https://github.com/Kitware/batbot/raw/jrp/ci-cd-fixes/assets/logo.png :alt: Batbot :align: center From 328ab81adb2c8ea1f463a702b4df8994a114b857 Mon Sep 17 00:00:00 2001 From: Jason Parham Date: Thu, 1 Jan 2026 16:14:05 -0800 Subject: [PATCH 10/14] Updated code block --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 5bfed5f..f5513c2 100644 --- a/README.rst +++ b/README.rst @@ -17,6 +17,7 @@ Development Environment ----------------------- .. code-block:: bash + # Find repo on host machine cd ~/code/batbot From a6ff93834e5274e48e96aea2910e1305a94e5130 Mon Sep 17 00:00:00 2001 From: "trevor.stout" Date: Fri, 9 Jan 2026 18:08:32 -0500 Subject: [PATCH 11/14] Various fixes, now using global call contour threshold --- batbot/spectrogram/__init__.py | 167 ++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 74 deletions(-) diff --git a/batbot/spectrogram/__init__.py b/batbot/spectrogram/__init__.py index 4adaaae..8b3f967 100644 --- a/batbot/spectrogram/__init__.py +++ b/batbot/spectrogram/__init__.py @@ -68,6 +68,8 @@ def get_slope_islands(slope_flags): def merge_ranges(ranges, max_val): merged = [] merge = [] + # sort by range start times in case ranges are out of order + ranges = sorted(ranges) for values in ranges: values = list(values) if len(merge) == 0: @@ -136,14 +138,12 @@ def plot_histogram( hist = gaussian_filter1d(hist, smoothing, mode='nearest') hist_original = (hist_original / hist_original.max()) * hist.max() - hist_ = np.argmax(hist) - image_ = image.astype(np.int32) - hist_std = np.abs(image_ - hist_).mean() + mode_ = np.argmax(hist) # histogram mode csum = np.cumsum(hist) / hist.sum() csum_ = np.where(csum >= csum_threshold)[0].min() - retval = med_, std_, (hist_, hist_std) + retval = med_, std_, mode_ if output_path is None: return retval @@ -159,15 +159,15 @@ def plot_histogram( plt.axhline(0, color='black') plt.plot(hist_original, label='Histogram Raw (Non-zero)', color='orange', alpha=0.8) plt.plot(hist, label='Histogram Smoothed (Non-zero)') - plt.plot(csum * y_max, label='Cumulitive Sum') + plt.plot(csum * y_max, label='Cumulative Sum') plt.plot([mean_] * 2, [0, y_max], color='black', linestyle='--', label=f'Mean ({mean_:0.01f})') plt.plot([med_] * 2, [0, y_max], color='red', linestyle='--', label=f'Median ({med_:0.01f})') plt.plot( - [hist_] * 2, + [mode_] * 2, [0, y_max], color='grey', linestyle='--', - label=f'Histogram Peak ({hist_:0.01f} +/- {hist_std:0.01f})', + label=f'Histogram Peak ({mode_:0.01f} +/- {std_:0.01f})', ) plt.plot( [csum_] * 2, @@ -176,7 +176,7 @@ def plot_histogram( linestyle='--', label=f'CSUM >= {csum_threshold:0.02f} ({csum_:0.01f})', ) - plt.axvspan(hist_ - hist_std, hist_ + hist_std, color='grey', alpha=0.1) + plt.axvspan(mode_ - std_, mode_ + std_, color='grey', alpha=0.1) # plt.plot([med_ - std_] * 2, [0, hist.max()], color='blue', linestyle='--', label=f'Median +/- MAD [{med_ - std_:0.01f} - {med_ + std_:0.01f}]') # plt.plot([med_ + std_] * 2, [0, hist.max()], color='blue', linestyle='--') @@ -259,26 +259,30 @@ def load_stft( ) # Convert the complex power (amplitude + phase) into amplitude (decibels) stft_db = librosa.power_to_db(np.abs(stft) ** 2, ref=np.max) + # Retrieve time vector in seconds corresponding to STFT + time_vec = librosa.frames_to_time(range(stft_db.shape[1]), sr=sr, hop_length=hop_length, n_fft=n_fft) # Remove frequencies that we do not need [FREQ_MIN - FREQ_MAX] - bands = librosa.fft_frequencies(sr=sr, n_fft=n_fft) + bands = librosa.fft_frequencies(sr=sr, n_fft=n_fft) # band center frequencies + delta_f = bands[1] - bands[0] # bandwidth goods = [] for index in range(len(bands)): - band_min = bands[index] - band_max = bands[index + 1] if index < len(bands) - 1 else np.inf + band_min = bands[index] - delta_f/2.0 + band_max = bands[index] + delta_f/2.0 + # accept bands with any part of their range within interval [FREQ_MIN, FREQ_MAX] if FREQ_MIN <= band_max and band_min <= FREQ_MAX: goods.append(index) min_index = min(goods) - max_index = max(goods) + 1 + max_index = max(goods) # Return only valid frequency bands - stft_db = stft_db[min_index:max_index, :] - bands = bands[min_index:max_index] + stft_db = stft_db[min_index:max_index+1, :] + bands = bands[min_index:max_index+1] waveplot = generate_waveplot(waveform, stft_db, hop_length=hop_length) - return stft_db, waveplot, sr, bands, duration, min_index + return stft_db, waveplot, sr, bands, duration, min_index, time_vec def gain_stft(stft_db, gain_db=80.0, autogain_stddev=5.0): @@ -333,11 +337,18 @@ def normalize_stft(data, value=1.0, dtype=None): return data -def calculate_window_and_stride(stft_db, duration, window_size_ms=12, strides_per_window=3): +def calculate_window_and_stride(stft_db, duration, window_size_ms=12, strides_per_window=3, time_vec=None): # Create a horizontal (time) sliding window of Numpy views # Window: ~12ms # Stride: ~4ms - window = stft_db.shape[1] / (duration * 1e3) * window_size_ms + if time_vec is not None: + # use the precise center time per STFT column if provided + delta_t = time_vec[1] - time_vec[0] + window = window_size_ms / delta_t / 1e3 + else: + # estimate the window size based on audio file length and STFT length + window = stft_db.shape[1] / (duration * 1e3) * window_size_ms + stride = window / strides_per_window window = int(round(window)) @@ -347,7 +358,7 @@ def calculate_window_and_stride(stft_db, duration, window_size_ms=12, strides_pe def create_coarse_candidates(stft_db, window, stride, threshold_stddev=3.0): - # Re-calculate the non-zero median DB and MAD + # Re-calculate the non-zero median DB and MAD (scaled like std) temp = stft_db[stft_db > 0] med_db = np.median(temp) std_db = scipy.stats.median_abs_deviation(temp, axis=None, scale='normal') @@ -377,11 +388,11 @@ def create_coarse_candidates(stft_db, window, stride, threshold_stddev=3.0): def filter_candidates_to_ranges( stft_db, candidates, window=16, skew_stddev=2.0, area_percent=0.10, output_path=None ): - # Filter the candidates based on their Normal distribution skewness + # Filter the candidates based on their distribution skewness stride_ = 2 buffer = int(round(window / stride_ / 2)) - idxs = [] + reject_idxs = [] ranges = [] for index, (idx, start, stop) in tqdm.tqdm(list(enumerate(candidates))): # Extract the candidate window of the STFT @@ -395,7 +406,7 @@ def filter_candidates_to_ranges( # Center and clip the skew values skew_thresh = calculate_mean_within_stddev_window(skews, skew_stddev) - # IMPROTANT: Only center positive (right-sided) global skew for the global candidate calculation + # IMPORTANT: Only center positive (right-sided) global skew for the global candidate calculation skew_thresh = max(0, skew_thresh) skews = normalize_skew(skews, skew_thresh) @@ -440,13 +451,13 @@ def filter_candidates_to_ranges( ) plt.close('all') else: - idxs.append(idx) + reject_idxs.append(idx) - return ranges, idxs + return ranges, reject_idxs def plot_chirp_candidates( - stft_db, candidate_dbs, ranges, idxs, output_path='.', output_filename='candidates.png' + stft_db, candidate_dbs, ranges, reject_idxs, output_path='.', output_filename='candidates.png' ): if output_path is None: return @@ -455,7 +466,7 @@ def plot_chirp_candidates( cv2.imwrite(join(output_path, f'chirp.{index}.png'), stft_db[:, start:stop]) candidate_dbs_ = candidate_dbs.copy() - candidate_dbs[idxs] = np.nan + candidate_dbs[reject_idxs] = np.nan flags = np.isnan(candidate_dbs) candidate_dbs[flags] = np.nanmin(candidate_dbs) @@ -574,13 +585,6 @@ def tighten_ranges( island_stop += start ranges_.append((island_start, island_stop)) - x = candidate.copy() - for a, b in islands_plotting: - x[:, a] = np.iinfo(x.dtype).max - x[:, b] = np.iinfo(x.dtype).max - # candidate[:, a] = np.iinfo(candidate.dtype).max - # candidate[:, b] = np.iinfo(candidate.dtype).max - # cv2.imwrite('temp2.tif', x) if output_path: # Plot the skew and spectrogram @@ -712,7 +716,7 @@ def normalize_contour(segment, index, dtype=None, blur=True, kernel=5, output_pa if blur: # segment = cv2.erode(segment, np.ones((3, 3), np.uint8), iterations=1) - segment = cv2.GaussianBlur(segment, (kernel, kernel), cv2.BORDER_DEFAULT) + segment = cv2.GaussianBlur(segment, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) segment = normalize_stft(segment, None, dtype) @@ -751,7 +755,8 @@ def find_contour_connected_components(segment, index, locations, sequence=4, out def find_harmonic(segmentmask, index, freq_offset, kernel=15, output_path='.'): h = segmentmask.shape[0] locations = np.array(np.where(segmentmask)) - locations[0] = h - ((h - locations[0]) * 2 + freq_offset) + # convert mask to first harmonic (doubled frequency), accounting for flipped frequency axis + locations[0] = h - ((h - locations[0] + freq_offset) * 2) flags = np.logical_and(0 <= locations[0], locations[0] < h) locations = locations[:, flags] @@ -762,7 +767,7 @@ def find_harmonic(segmentmask, index, freq_offset, kernel=15, output_path='.'): harmonic[tuple(locations)] = True harmonic_ = harmonic.astype(np.uint8) * 255 - harmonic_ = cv2.GaussianBlur(harmonic_, (kernel, kernel), cv2.BORDER_DEFAULT) + harmonic_ = cv2.GaussianBlur(harmonic_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) write_contour_debug_image(harmonic_, index, 7, 'harmonic', output_path) return harmonic @@ -783,7 +788,7 @@ def find_echo(segmentmask, index, kernel=15, output_path='.'): echo[maxy, maxx:] = True echo_ = echo.astype(np.uint8) * 255 - echo_ = cv2.GaussianBlur(echo_, (kernel, kernel), cv2.BORDER_DEFAULT) + echo_ = cv2.GaussianBlur(echo_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) write_contour_debug_image(echo_, index, 7, 'echo', output_path) return echo @@ -795,13 +800,13 @@ def remove_harmonic_and_echo( combined = np.logical_or(harmonic, echo) combined_ = combined.astype(np.uint8) * 255 - combined_ = cv2.GaussianBlur(combined_, (kernel, kernel), cv2.BORDER_DEFAULT) + combined_ = cv2.GaussianBlur(combined_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) / 255.0 write_contour_debug_image(combined_, index, 7, 'combined', output_path) dtype = segment.dtype segment = segment.astype(np.float32) - segment *= 1.0 - combined.astype(np.float32) + segment *= 1.0 - combined_.astype(np.float32) if None not in {med_db, std_db}: segment_threshold = med_db - std_db @@ -885,7 +890,7 @@ def calculate_astar_grid_and_endpoints( costs = segment.astype(np.float32) segmentmask_ = segmentmask.astype(np.float32) - segmentmask_ = cv2.GaussianBlur(segmentmask_, (kernel, kernel), cv2.BORDER_DEFAULT) + segmentmask_ = cv2.GaussianBlur(segmentmask_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) costs *= segmentmask_ costs = normalize_stft(costs, None, segment.dtype) @@ -932,9 +937,11 @@ def extract_contour_keypoints( der1 = np.nan_to_num(der1, nan=der1min, posinf=der1max, neginf=der1min) der1 = gaussian_filter1d(der1, contour_smoothing_sigma, mode='nearest') + # Retrieve first (knee) and last (heel) locations where slope (dy/dx) magnitude approaches the median value slope_thresh = np.abs(np.median(der1)) slope_flags = np.abs(der1) <= slope_thresh knee_idx, heel_idx = get_slope_islands(slope_flags) + # Retrieve location of minimum slope magnitude between knee and heel fc_idx = knee_idx + int(np.argmin(np.abs(der1[knee_idx:heel_idx]))) if output_path: @@ -1046,7 +1053,7 @@ def significant_contour_path( def scale_pdf_contour(segment, index, output_path='.'): segment = normalize_stft(segment, None, segment.dtype) - med_db, std_db, (peak_db, peak_db_std) = plot_histogram( + med_db, std_db, peak_db = plot_histogram( segment, smoothing=512, ignore_zeros=True, @@ -1057,7 +1064,7 @@ def scale_pdf_contour(segment, index, output_path='.'): assert segment.min() == 0 assert segment.max() == np.iinfo(segment.dtype).max - dist = scipy.stats.norm(peak_db, peak_db_std) + dist = scipy.stats.norm(peak_db, std_db) steps = segment.max() x = np.linspace(0, steps, steps) y = dist.pdf(x) @@ -1081,11 +1088,11 @@ def scale_pdf_contour(segment, index, output_path='.'): plt.xlabel('Frequency') plt.ylabel('Probability') - plt.axvspan(peak_db - 3 * peak_db_std, peak_db + 3 * peak_db_std, color='grey', alpha=0.15) - plt.axvspan(peak_db - 2 * peak_db_std, peak_db + 2 * peak_db_std, color='grey', alpha=0.15) + plt.axvspan(peak_db - 3 * std_db, peak_db + 3 * std_db, color='grey', alpha=0.15) + plt.axvspan(peak_db - 2 * std_db, peak_db + 2 * std_db, color='grey', alpha=0.15) plt.axvspan( - peak_db - 1 * peak_db_std, - peak_db + 1 * peak_db_std, + peak_db - 1 * std_db, + peak_db + 1 * std_db, color='grey', alpha=0.15, label='Standard Deviations σ={1,2,3}', @@ -1119,7 +1126,7 @@ def scale_pdf_contour(segment, index, output_path='.'): write_contour_debug_image(segment, index, 1, 'cdf', output_path) - return segment, peak_db, peak_db_std + return segment, peak_db, std_db def morph_open_contour(segment, index, output_path='.'): @@ -1131,9 +1138,14 @@ def morph_open_contour(segment, index, output_path='.'): def find_contour_and_peak( - segment, index, max_locations, peak_db, peak_db_std, threshold_std=2.0, sigma=5, output_path='.' + segment, index, max_locations, peak_db=None, peak_db_std=None, threshold_std=2.0, sigma=5, output_path='.', threshold=None ): - threshold = peak_db - threshold_std * peak_db_std + + if not threshold: + # Apply threshold equal to normalized (and smoothed) segment histogram mode, + # minus the estimated noise standard deviation scaled by threshold_std + # (note that these were computed prior to CDF weighting) + threshold = peak_db - threshold_std * peak_db_std contours = measure.find_contours( segment, level=threshold, fully_connected='high', positive_orientation='high' @@ -1211,7 +1223,7 @@ def calculate_harmonic_and_echo_flags( nonzeros = original > 0 negative = ~np.logical_or(np.logical_or(harmonic, echo), segmentmask) negative_ = negative.astype(np.uint8) * 255 - negative_ = cv2.GaussianBlur(negative_, (kernel, kernel), cv2.BORDER_DEFAULT) + negative_ = cv2.GaussianBlur(negative_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) write_contour_debug_image(negative_, index, 7, 'negative', output_path=output_path) negative_skew = scipy.stats.skew(original[np.logical_and(nonzeros, negative)]) @@ -1221,9 +1233,9 @@ def calculate_harmonic_and_echo_flags( - negative_skew ) - shew_thesh = np.abs(negative_skew * 0.1) - harmonic_flag = harmonic_skew >= shew_thesh - echo_flag = echo_skew >= shew_thesh + skew_thresh = np.abs(negative_skew * 0.1) + harmonic_flag = harmonic_skew >= skew_thresh + echo_flag = echo_skew >= skew_thresh harmonic_peak = None if harmonic_flag: @@ -1294,7 +1306,7 @@ def compute_wrapper( debug_path = get_debug_path(output_folder, wav_filepath, enabled=debug) # Load the spectrogram from a WAV file on disk - stft_db, waveplot, sr, bands, duration, freq_offset = load_stft(wav_filepath) + stft_db, waveplot, sr, bands, duration, freq_offset, time_vec = load_stft(wav_filepath) # Apply a dynamic range to a fixed dB range stft_db = gain_stft(stft_db) @@ -1307,34 +1319,37 @@ def compute_wrapper( stft_db = np.ascontiguousarray(stft_db[::-1, :]) bands = bands[::-1] y_step_freq = float(bands[0] - bands[1]) - x_step_ms = float((1e3 * duration) / stft_db.shape[1]) + x_step_ms = float(1e3 * (time_vec[1] - time_vec[0])) bands = np.around(bands).astype(np.int32).tolist() # # Save the spectrogram image to disk # cv2.imwrite('debug.tif', stft_db, [cv2.IMWRITE_TIFF_COMPRESSION, 1]) - # Plot the historgram, ignoring any non-zero values (will no-op if output_path is None) - plot_histogram(stft_db, ignore_zeros=True, output_path=debug_path) + # Plot the histogram, ignoring any non-zero values (will no-op if output_path is None) + global_med_db, global_std_db, global_peak_db = plot_histogram(stft_db, ignore_zeros=True, smoothing=512, output_path=debug_path) + # Estimate a global threshold for finding the edges of bat call contours + global_threshold_std = 2.0 + global_threshold = global_peak_db - global_threshold_std * global_std_db # Get a distribution of the max candidate locations - window, stride = calculate_window_and_stride(stft_db, duration) - candidates, candidate_dbs = create_coarse_candidates(stft_db, window, stride) + window, stride = calculate_window_and_stride(stft_db, duration, time_vec=time_vec) + candidates, candidate_max_dbs = create_coarse_candidates(stft_db, window, stride) # Filter all candidates to the ranges that have a substantial right-side skew - ranges, idxs = filter_candidates_to_ranges(stft_db, candidates, output_path=debug_path) + ranges, reject_idxs = filter_candidates_to_ranges(stft_db, candidates, output_path=debug_path) # Add in user-specified annotations to ranges if annotations: for start, stop in annotations: - start_px = int(np.around((start / duration) * stft_db.shape[1])) - stop_px = int(np.around((stop / duration) * stft_db.shape[1])) + 1 + start_px = int(np.argmin(np.abs(time_vec - start))) + stop_px = int(np.argmin(np.abs(time_vec - stop)) + 1) ranges.append((start_px, stop_px)) # Merge all range segments into contiguous range blocks ranges = merge_ranges(ranges, stft_db.shape[1]) # Plot the chirp candidates (will no-op if output_path is None) - plot_chirp_candidates(stft_db, candidate_dbs, ranges, idxs, output_path=debug_path) + plot_chirp_candidates(stft_db, candidate_max_dbs, ranges, reject_idxs, output_path=debug_path) # Tighten the ranges by looking for substantial right-side skew (use stride for a smaller sampling window) ranges = tighten_ranges(stft_db, ranges, stride, duration, output_path=debug_path) @@ -1374,8 +1389,9 @@ def compute_wrapper( # segment, med_db, std_db, peak_db = threshold_contour(segment, index, output_path=debug_path) # Step 5 - Find primary contour that contains max amplitude - segmentmask, peak, threshold = find_contour_and_peak( - segment, index, max_locations, peak_db, peak_db_std, output_path=debug_path + # (To use a local instead of global threshold, remove the threshold argument here) + segmentmask, peak, segment_threshold = find_contour_and_peak( + segment, index, max_locations, peak_db, peak_db_std, output_path=debug_path, threshold=global_threshold ) if peak is None: @@ -1400,24 +1416,24 @@ def compute_wrapper( # Remove harmonic and echo from segmentation segment = remove_harmonic_and_echo( - segment, index, harmonic, echo, threshold, output_path=debug_path + segment, index, harmonic, echo, global_threshold, output_path=debug_path ) - # Step 8 - Calculate the A* cost grid and start/end points - costs, grid, begin, end, boundary = calculate_astar_grid_and_endpoints( + # Step 8 - Calculate the A* cost grid and bat call start/end points + costs, grid, call_begin, call_end, boundary = calculate_astar_grid_and_endpoints( segment, index, segmentmask, peak, canvas, output_path=debug_path ) top, bottom, left, right = boundary # Skip chirp if the extracted path covers a small duration or bandwidth bandwidth, duration_, significant = significant_contour_path( - begin, end, y_step_freq, x_step_ms + call_begin, call_end, y_step_freq, x_step_ms ) if not significant: continue # Step 9 - Extract optimal path from start to end using the cost grid - path = extract_contour_path(grid, begin, end, canvas, index, output_path=debug_path) + path = extract_contour_path(grid, call_begin, call_end, canvas, index, output_path=debug_path) # Step 10 - Extract contour keypoints path_smoothed, (knee, fc, heel), slopes = extract_contour_keypoints( @@ -1436,6 +1452,7 @@ def compute_wrapper( 'start.ms': (start + left) * x_step_ms, 'end.ms': (start + right) * x_step_ms, 'duration.ms': (right - left) * x_step_ms, + 'threshold.amp': int(round(255.0 * (segment_threshold / np.iinfo(stft_db.dtype).max))), 'peak f.ms': (start + peak[1]) * x_step_ms, 'fc.ms': (start + bands[fc[1]]) * x_step_ms, 'hi fc:knee.ms': (start + bands[knee[1]]) * x_step_ms, @@ -1481,10 +1498,11 @@ def compute_wrapper( metas.append(metadata) - trim_ms = 1.0 - trim = int(round(trim_ms / x_step_ms)) - trim_begin = max(0, min(segment.shape[1], begin[1] - trim)) - trim_end = max(0, min(segment.shape[1], end[1] + trim)) + # Trim segment around the bat call with a small buffer + buffer_ms = 1.0 + buffer_pix = int(round(buffer_ms / x_step_ms)) + trim_begin = max(0, min(segment.shape[1], call_begin[1] - buffer_pix)) + trim_end = max(0, min(segment.shape[1], call_end[1] + buffer_pix)) segments['stft_db'].append(stft_db[:, start + trim_begin : start + trim_end]) segments['waveplot'].append(waveplot[:, start + trim_begin : start + trim_end]) @@ -1492,6 +1510,7 @@ def compute_wrapper( if debug_path: segments['canvas'].append(canvas[:, trim_begin:trim_end]) + # Concatenate extracted, trimmed segments and other matrices for key in list(segments.keys()): value = segments[key] if len(value) == 0: @@ -1595,7 +1614,7 @@ def compute_wrapper( 'uncompressed.path': output_paths, 'compressed.path': compressed_paths, }, - 'threshold.amp': int(round(255.0 * (threshold / max_value))), + 'mean_threshold.amp': int(round(255.0 * (global_threshold / max_value))), 'sr.hz': int(sr), 'duration.ms': round(duration * 1e3, 3), 'frequencies': { From 550f4c0b3a9e6843af8e181d9322e5183d55c972 Mon Sep 17 00:00:00 2001 From: "trevor.stout" Date: Fri, 9 Jan 2026 18:18:49 -0500 Subject: [PATCH 12/14] Changed metadata name --- batbot/spectrogram/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/batbot/spectrogram/__init__.py b/batbot/spectrogram/__init__.py index 8b3f967..e4522d6 100644 --- a/batbot/spectrogram/__init__.py +++ b/batbot/spectrogram/__init__.py @@ -1614,7 +1614,7 @@ def compute_wrapper( 'uncompressed.path': output_paths, 'compressed.path': compressed_paths, }, - 'mean_threshold.amp': int(round(255.0 * (global_threshold / max_value))), + 'global_threshold.amp': int(round(255.0 * (global_threshold / max_value))), 'sr.hz': int(sr), 'duration.ms': round(duration * 1e3, 3), 'frequencies': { From 5a22f235a18fa4d3f768c1828df787eb24c8f21e Mon Sep 17 00:00:00 2001 From: "trevor.stout" Date: Mon, 12 Jan 2026 10:57:00 -0500 Subject: [PATCH 13/14] Linting --- batbot/spectrogram/__init__.py | 82 ++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/batbot/spectrogram/__init__.py b/batbot/spectrogram/__init__.py index e4522d6..baf5537 100644 --- a/batbot/spectrogram/__init__.py +++ b/batbot/spectrogram/__init__.py @@ -138,7 +138,7 @@ def plot_histogram( hist = gaussian_filter1d(hist, smoothing, mode='nearest') hist_original = (hist_original / hist_original.max()) * hist.max() - mode_ = np.argmax(hist) # histogram mode + mode_ = np.argmax(hist) # histogram mode csum = np.cumsum(hist) / hist.sum() csum_ = np.where(csum >= csum_threshold)[0].min() @@ -260,16 +260,18 @@ def load_stft( # Convert the complex power (amplitude + phase) into amplitude (decibels) stft_db = librosa.power_to_db(np.abs(stft) ** 2, ref=np.max) # Retrieve time vector in seconds corresponding to STFT - time_vec = librosa.frames_to_time(range(stft_db.shape[1]), sr=sr, hop_length=hop_length, n_fft=n_fft) + time_vec = librosa.frames_to_time( + range(stft_db.shape[1]), sr=sr, hop_length=hop_length, n_fft=n_fft + ) # Remove frequencies that we do not need [FREQ_MIN - FREQ_MAX] - bands = librosa.fft_frequencies(sr=sr, n_fft=n_fft) # band center frequencies - delta_f = bands[1] - bands[0] # bandwidth + bands = librosa.fft_frequencies(sr=sr, n_fft=n_fft) # band center frequencies + delta_f = bands[1] - bands[0] # bandwidth goods = [] for index in range(len(bands)): - band_min = bands[index] - delta_f/2.0 - band_max = bands[index] + delta_f/2.0 + band_min = bands[index] - delta_f / 2.0 + band_max = bands[index] + delta_f / 2.0 # accept bands with any part of their range within interval [FREQ_MIN, FREQ_MAX] if FREQ_MIN <= band_max and band_min <= FREQ_MAX: goods.append(index) @@ -277,8 +279,8 @@ def load_stft( max_index = max(goods) # Return only valid frequency bands - stft_db = stft_db[min_index:max_index+1, :] - bands = bands[min_index:max_index+1] + stft_db = stft_db[min_index : max_index + 1, :] + bands = bands[min_index : max_index + 1] waveplot = generate_waveplot(waveform, stft_db, hop_length=hop_length) @@ -337,7 +339,9 @@ def normalize_stft(data, value=1.0, dtype=None): return data -def calculate_window_and_stride(stft_db, duration, window_size_ms=12, strides_per_window=3, time_vec=None): +def calculate_window_and_stride( + stft_db, duration, window_size_ms=12, strides_per_window=3, time_vec=None +): # Create a horizontal (time) sliding window of Numpy views # Window: ~12ms # Stride: ~4ms @@ -348,7 +352,7 @@ def calculate_window_and_stride(stft_db, duration, window_size_ms=12, strides_pe else: # estimate the window size based on audio file length and STFT length window = stft_db.shape[1] / (duration * 1e3) * window_size_ms - + stride = window / strides_per_window window = int(round(window)) @@ -585,7 +589,6 @@ def tighten_ranges( island_stop += start ranges_.append((island_start, island_stop)) - if output_path: # Plot the skew and spectrogram plt.figure() @@ -716,7 +719,9 @@ def normalize_contour(segment, index, dtype=None, blur=True, kernel=5, output_pa if blur: # segment = cv2.erode(segment, np.ones((3, 3), np.uint8), iterations=1) - segment = cv2.GaussianBlur(segment, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) + segment = cv2.GaussianBlur( + segment, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) segment = normalize_stft(segment, None, dtype) @@ -767,7 +772,9 @@ def find_harmonic(segmentmask, index, freq_offset, kernel=15, output_path='.'): harmonic[tuple(locations)] = True harmonic_ = harmonic.astype(np.uint8) * 255 - harmonic_ = cv2.GaussianBlur(harmonic_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) + harmonic_ = cv2.GaussianBlur( + harmonic_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) write_contour_debug_image(harmonic_, index, 7, 'harmonic', output_path) return harmonic @@ -788,7 +795,9 @@ def find_echo(segmentmask, index, kernel=15, output_path='.'): echo[maxy, maxx:] = True echo_ = echo.astype(np.uint8) * 255 - echo_ = cv2.GaussianBlur(echo_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) + echo_ = cv2.GaussianBlur( + echo_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) write_contour_debug_image(echo_, index, 7, 'echo', output_path) return echo @@ -800,7 +809,12 @@ def remove_harmonic_and_echo( combined = np.logical_or(harmonic, echo) combined_ = combined.astype(np.uint8) * 255 - combined_ = cv2.GaussianBlur(combined_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) / 255.0 + combined_ = ( + cv2.GaussianBlur( + combined_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) + / 255.0 + ) write_contour_debug_image(combined_, index, 7, 'combined', output_path) dtype = segment.dtype @@ -890,7 +904,9 @@ def calculate_astar_grid_and_endpoints( costs = segment.astype(np.float32) segmentmask_ = segmentmask.astype(np.float32) - segmentmask_ = cv2.GaussianBlur(segmentmask_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) + segmentmask_ = cv2.GaussianBlur( + segmentmask_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) costs *= segmentmask_ costs = normalize_stft(costs, None, segment.dtype) @@ -1138,12 +1154,20 @@ def morph_open_contour(segment, index, output_path='.'): def find_contour_and_peak( - segment, index, max_locations, peak_db=None, peak_db_std=None, threshold_std=2.0, sigma=5, output_path='.', threshold=None + segment, + index, + max_locations, + peak_db=None, + peak_db_std=None, + threshold_std=2.0, + sigma=5, + output_path='.', + threshold=None, ): if not threshold: - # Apply threshold equal to normalized (and smoothed) segment histogram mode, - # minus the estimated noise standard deviation scaled by threshold_std + # Apply threshold equal to normalized (and smoothed) segment histogram mode, + # minus the estimated noise standard deviation scaled by threshold_std # (note that these were computed prior to CDF weighting) threshold = peak_db - threshold_std * peak_db_std @@ -1223,7 +1247,9 @@ def calculate_harmonic_and_echo_flags( nonzeros = original > 0 negative = ~np.logical_or(np.logical_or(harmonic, echo), segmentmask) negative_ = negative.astype(np.uint8) * 255 - negative_ = cv2.GaussianBlur(negative_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT) + negative_ = cv2.GaussianBlur( + negative_, (kernel, kernel), sigmaX=4, sigmaY=4, borderType=cv2.BORDER_DEFAULT + ) write_contour_debug_image(negative_, index, 7, 'negative', output_path=output_path) negative_skew = scipy.stats.skew(original[np.logical_and(nonzeros, negative)]) @@ -1326,7 +1352,9 @@ def compute_wrapper( # cv2.imwrite('debug.tif', stft_db, [cv2.IMWRITE_TIFF_COMPRESSION, 1]) # Plot the histogram, ignoring any non-zero values (will no-op if output_path is None) - global_med_db, global_std_db, global_peak_db = plot_histogram(stft_db, ignore_zeros=True, smoothing=512, output_path=debug_path) + global_med_db, global_std_db, global_peak_db = plot_histogram( + stft_db, ignore_zeros=True, smoothing=512, output_path=debug_path + ) # Estimate a global threshold for finding the edges of bat call contours global_threshold_std = 2.0 global_threshold = global_peak_db - global_threshold_std * global_std_db @@ -1391,7 +1419,13 @@ def compute_wrapper( # Step 5 - Find primary contour that contains max amplitude # (To use a local instead of global threshold, remove the threshold argument here) segmentmask, peak, segment_threshold = find_contour_and_peak( - segment, index, max_locations, peak_db, peak_db_std, output_path=debug_path, threshold=global_threshold + segment, + index, + max_locations, + peak_db, + peak_db_std, + output_path=debug_path, + threshold=global_threshold, ) if peak is None: @@ -1433,7 +1467,9 @@ def compute_wrapper( continue # Step 9 - Extract optimal path from start to end using the cost grid - path = extract_contour_path(grid, call_begin, call_end, canvas, index, output_path=debug_path) + path = extract_contour_path( + grid, call_begin, call_end, canvas, index, output_path=debug_path + ) # Step 10 - Extract contour keypoints path_smoothed, (knee, fc, heel), slopes = extract_contour_keypoints( From 4467c699def2208cb0ba3300db20541c8787a930 Mon Sep 17 00:00:00 2001 From: "trevor.stout" Date: Tue, 13 Jan 2026 10:47:39 -0500 Subject: [PATCH 14/14] ignoring vscode files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fc61cae..fde0cdc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ docs/_build/ example*.jpg example*.json +.vscode/*