Repository: sep-developers/sep (language: python)

Issue:
Naming convention
Rename all public functions to start with `sep_` to avoid namespace clashes.



Discussion / hints:
Done.


Fix patch:
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..790938e
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: MIT
+#
+# Copyright (c) 2023 Intercreate, Inc.
+# Author: J.P. Hutchins <jp@intercreate.io>
+#
+# Python(black)-inspired .clang-format for C repositories
+#
+# Includes Zephyr and Arm macro compatibility
+
+---
+BasedOnStyle: Google
+
+AlignAfterOpenBracket: BlockIndent
+AlignTrailingComments: false
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortEnumsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AttributeMacros:
+  - __aligned
+  - __deprecated
+  - __packed
+  - __printf_like
+  - __syscall
+  - __syscall_always_inline
+  - __subsystem
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+  AfterCaseLabel: false
+  AfterClass: false
+  AfterControlStatement: MultiLine
+  AfterEnum: false
+  AfterFunction: false
+  AfterNamespace: false
+  AfterObjCDeclaration: false
+  AfterStruct: false
+  AfterUnion: false
+  AfterExternBlock: false
+  BeforeCatch: false
+  BeforeElse: false
+  IndentBraces: false
+  SplitEmptyFunction: false
+  SplitEmptyRecord: false
+  SplitEmptyNamespace: false
+  BeforeLambdaBody: false
+  BeforeWhile: false
+BitFieldColonSpacing: After
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeBraces: Custom
+BreakStringLiterals: true
+ColumnLimit: 88
+DerivePointerAlignment: false
+ForEachMacros:
+  - 'FOR_EACH'
+  - 'FOR_EACH_FIXED_ARG'
+  - 'FOR_EACH_IDX'
+  - 'FOR_EACH_IDX_FIXED_ARG'
+  - 'FOR_EACH_NONEMPTY_TERM'
+  - 'RB_FOR_EACH'
+  - 'RB_FOR_EACH_CONTAINER'
+  - 'SYS_DLIST_FOR_EACH_CONTAINER'
+  - 'SYS_DLIST_FOR_EACH_CONTAINER_SAFE'
+  - 'SYS_DLIST_FOR_EACH_NODE'
+  - 'SYS_DLIST_FOR_EACH_NODE_SAFE'
+  - 'SYS_SFLIST_FOR_EACH_CONTAINER'
+  - 'SYS_SFLIST_FOR_EACH_CONTAINER_SAFE'
+  - 'SYS_SFLIST_FOR_EACH_NODE'
+  - 'SYS_SFLIST_FOR_EACH_NODE_SAFE'
+  - 'SYS_SLIST_FOR_EACH_CONTAINER'
+  - 'SYS_SLIST_FOR_EACH_CONTAINER_SAFE'
+  - 'SYS_SLIST_FOR_EACH_NODE'
+  - 'SYS_SLIST_FOR_EACH_NODE_SAFE'
+  - '_WAIT_Q_FOR_EACH'
+  - 'Z_FOR_EACH'
+  - 'Z_FOR_EACH_ENGINE'
+  - 'Z_FOR_EACH_EXEC'
+  - 'Z_FOR_EACH_FIXED_ARG'
+  - 'Z_FOR_EACH_FIXED_ARG_EXEC'
+  - 'Z_FOR_EACH_IDX'
+  - 'Z_FOR_EACH_IDX_EXEC'
+  - 'Z_FOR_EACH_IDX_FIXED_ARG'
+  - 'Z_FOR_EACH_IDX_FIXED_ARG_EXEC'
+  - 'Z_GENLIST_FOR_EACH_CONTAINER'
+  - 'Z_GENLIST_FOR_EACH_CONTAINER_SAFE'
+  - 'Z_GENLIST_FOR_EACH_NODE'
+  - 'Z_GENLIST_FOR_EACH_NODE_SAFE'
+  - 'STRUCT_SECTION_FOREACH'
+  - 'TYPE_SECTION_FOREACH'
+IncludeBlocks: Preserve
+IfMacros:
+  - 'CHECKIF'
+IndentCaseBlocks: true
+IndentCaseLabels: false
+IndentWidth: 2
+InsertBraces: true
+MaxEmptyLinesToKeep: 2
+PointerAlignment: Middle
+SortIncludes: CaseSensitive
+SpaceBeforeParens: ControlStatementsExceptControlMacros
+UseTab: Never
+WhitespaceSensitiveMacros:
+  - STRINGIFY
+  - Z_STRINGIFY
diff --git a/.github/workflows/build-wheels-upload-pypi.yml b/.github/workflows/build-wheels-upload-pypi.yml
index 7b9b0f7..37aa5a5 100644
--- a/.github/workflows/build-wheels-upload-pypi.yml
+++ b/.github/workflows/build-wheels-upload-pypi.yml
@@ -3,11 +3,11 @@
 
 name: build-wheels-upload-pypi
 
-on:
-  push:
-    # Run this action on the trigger event when *any* tag is pushed
-    tags:
-       - '*'
+on: [push, workflow_dispatch]
+  # push:
+  #   # Run this action on the trigger event when *any* tag is pushed
+  #   tags:
+  #      - '*'
 
 jobs:
 
@@ -18,7 +18,13 @@ jobs:
   # The first and second job run in parallel.
   # The uploading jos needs to have the other two finished without error.
 
+  # From now on, we run the tests before continuing with these jobs.
+
+  run_tests:
+    uses: ./.github/workflows/python-package-tox.yml
+
   build_sdist:
+    needs: [run_tests]
 
     # First the source distribution is done on ubuntu. This is not related
     # to any operating system, so we could do it on the default os.
@@ -27,21 +33,24 @@ jobs:
 
     steps:
       - name: checkout
-        uses: actions/checkout@v2
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+          fetch-tags: true
 
       - name: install_python
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v5
         with:
-          python-version: '3.9'
+          python-version: '3.12'
 
       # For the build, sep needs numpy and cython and we add twine and wheel
       # for better testing and checking.
 
       - name: Install dependencies
-        run: python -m pip install twine numpy wheel cython
+        run: python -m pip install setuptools twine numpy wheel cython build
 
       - name: Build sdist
-        run: python setup.py sdist
+        run: python -m build --sdist
 
       - name: Show files
         run: ls -lh dist
@@ -51,46 +60,52 @@ jobs:
         run: twine check dist/*
 
       - name: Upload sdist
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v4
         with:
           name: dist
           path: dist/*.tar.gz
 
   build_wheels:
+    needs: [run_tests]
 
     # Second the wheels are build for different OS and python versions. This is
     # done with the help of the `cibuildwheel` package.
     #
     # The wheels are built for Windows, Linux and MacOS and the python versions
-    # 3.5 - 3.10.
+    # 3.9 - 3.13.
     #
     # The three operating system could be done in parallel.
-
+    name: Build wheels on ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     env:
       CIBW_ARCHS_MACOS: "x86_64 universal2 arm64"
-      
+
     strategy:
       max-parallel: 4
       matrix:
-        python-version: [3.9]
+        python-version: ["3.12"]
         os: [windows-latest, macos-latest, ubuntu-latest]
         include:
           - os: ubuntu-20.04
             cibw_archs: "aarch64"
 
     steps:
-      - name: setup QEMU
-        if: matrix.cibw_archs == 'aarch64'
-        uses: docker/setup-qemu-action@v1
+      - uses: actions/checkout@v4
+
+      - name: Set up QEMU
+        if: runner.os == 'Linux'
+        uses: docker/setup-qemu-action@v3
         with:
           platforms: arm64
 
       - name: checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+          fetch-tags: true
 
       - name: Setup Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v3
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
 
@@ -101,7 +116,7 @@ jobs:
         if: matrix.cibw_archs == 'aarch64'
         run: python -m cibuildwheel --output-dir wheelhouse
         env:
-          CIBW_BUILD: "cp3*"
+          CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
           CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
           CIBW_MANYLINUX_I686_IMAGE: manylinux2014
           CIBW_BUILD_VERBOSITY: 1
@@ -112,7 +127,7 @@ jobs:
         if: matrix.cibw_archs != 'aarch64'
         run: python -m cibuildwheel --output-dir wheelhouse
         env:
-          CIBW_BUILD: "cp3*"
+          CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
           CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
           CIBW_MANYLINUX_I686_IMAGE: manylinux2014
           CIBW_BUILD_VERBOSITY: 1
@@ -124,9 +139,9 @@ jobs:
         shell: bash
 
       - name: Upload wheels
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v4
         with:
-          name: dist
+          name: dist-${{ matrix.os }}
           path: ./wheelhouse/*.whl
 
   upload_to_pypi:
@@ -139,21 +154,25 @@ jobs:
 
     runs-on: [ubuntu-latest]
     needs: [build_wheels, build_sdist]
+    environment:
+      name: pypi
+      url: https://pypi.org/p/sep
+    permissions:
+      id-token: write
 
     # upload to PyPI on every tag starting with 'v'
     if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
 
     steps:
-    - uses: actions/setup-python@v2
+    - uses: actions/setup-python@v5
 
-    - uses: actions/download-artifact@v2
+    - uses: actions/download-artifact@v4
       with:
-        name: dist
+        pattern: dist*
+        merge-multiple: true
         path: dist
 
     - name: upload_to_pypi
-      uses: pypa/gh-action-pypi-publish@v1.4.1
-      with:
-        user: __token__
-        password: ${{ secrets.PYPI_TOKEN }}
-        skip_existing: true
+      uses: pypa/gh-action-pypi-publish@release/v1
+      # with:
+      #   repository-url: https://test.pypi.org/legacy/
diff --git a/.github/workflows/python-package-tox.yml b/.github/workflows/python-package-tox.yml
index c034256..af50fa0 100644
--- a/.github/workflows/python-package-tox.yml
+++ b/.github/workflows/python-package-tox.yml
@@ -1,30 +1,31 @@
 # This workflow will install tox and use it to run tests.
 # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
 
-name: Python package
+name: CI
 
-on:
-  push:
-    branches: [ master ]
-  pull_request:
-    branches: [ master ]
+on: [push, workflow_call, workflow_dispatch, pull_request]
 
 jobs:
   build:
 
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python: [3.5, 3.8]
+        python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+        os: [windows-latest, macos-latest, ubuntu-latest]
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
       - name: Setup Python
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python }}
       - name: Install Tox and any other packages
-        run: pip install tox
+        run: |
+          python -m pip install --upgrade pip
+          python -m pip install tox tox-gh-actions
       - name: Run Tox
-        # Run tox using the version of Python in `PATH`
-        run: tox -e py
+        # Run tox using the version of Python in `PATH`, append platform
+        run: tox
+        env:
+          PLATFORM: ${{ matrix.os }}
diff --git a/.gitignore b/.gitignore
index bef801f..c4f278c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,7 +44,7 @@ sep.c
 
 # PyCharm
 .idea
-.project 
+.project
 
 # Eclipse
 .pydevproject
@@ -54,3 +54,6 @@ sep.c
 
 # tox
 .tox
+
+# version
+*_version.py
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..a126746
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,34 @@
+exclude: "^data/"
+repos:
+-   repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v5.0.0
+    hooks:
+    -   id: trailing-whitespace
+    -   id: end-of-file-fixer
+    -   id: check-yaml
+    -   id: check-added-large-files
+-   repo: https://github.com/pycqa/isort
+    rev: 5.13.2
+    hooks:
+    -   id: isort
+        name: isort (python)
+-   repo: https://github.com/psf/black
+    rev: 24.10.0
+    hooks:
+    -   id: black
+        args: [--preview]
+-   repo: https://github.com/numpy/numpydoc
+    rev: v1.8.0
+    hooks:
+    -   id: numpydoc-validation
+-   repo: https://github.com/sphinx-contrib/sphinx-lint
+    rev: v1.0.0
+    hooks:
+    -   id: sphinx-lint
+        args: [--enable=all, --disable=default-role, --max-line-length=75, -v]
+        files: ^docs\/|^.*\.(rst$|md$)
+-   repo: https://github.com/pre-commit/mirrors-clang-format
+    rev: v19.1.4
+    hooks:
+    -   id: clang-format
+        types_or: [c++, c, cuda]
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..c1fb2ee
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,39 @@
+# Read the Docs configuration file for Sphinx projects
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version and other tools you might need
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3.12"
+    # You can also specify other tool versions:
+    # nodejs: "20"
+    # rust: "1.70"
+    # golang: "1.20"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+  configuration: docs/conf.py
+  # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
+  # builder: "dirhtml"
+  # Fail on all warnings to avoid broken references
+  # fail_on_warning: true
+
+# Optionally build your docs in additional formats such as PDF and ePub
+# formats:
+#   - pdf
+#   - epub
+
+# Optional but recommended, declare the Python requirements required
+# to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+python:
+  install:
+    # - requirements: docs/requirements.txt
+    - method: pip
+      path: .
+      extra_requirements:
+      - docs
diff --git a/AUTHORS.md b/AUTHORS.md
index dc4769b..7063849 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -8,3 +8,5 @@
 * Joe Lyman (@lyalpha): Make deblending limit settable
 * Michael Wuertenberger (@mworion): PyPI wheels
 * Ingvar Stepanyan (@rreverser): Build system, public API and thread safety fixes.
+* Gabe Brammer (@gbrammer): Fix memory addressing with large arrays.
+* Peter Watson (@PJ-Watson): Add extraction from existing segmentation map.
diff --git a/CHANGES.md b/CHANGES.md
index 5bf0dc1..c831577 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,173 +1,79 @@
-v1.2.1 (1 June 2022)
-====================
-
-* Same as v1.2.0 but with new wheels for Python 3.10 and AArch64.
-
-v1.2.0 (1 May 2021)
-===================
-
-* Changed `numpy.float` and `numpy.int` types for deprecations in numpy 1.20 (#96).
-
-* Make it possible to safely invoke C library from multiple threads on
-  independent inputs.
-
-  Global config functions such as `set_sub_object_limit()`
-  and `set_extract_pixstack()` still configure global params
-  (once for all threads), while other functions will retain their data
-  in thread-local storages, so they can be invoked from multiple threads as
-  long as they work on independent structures.
-
-  Library compilation will now require a C11 compatible compiler, which should
-  be nowadays available on all supported platforms.
-
-* Mark some pointer parameters with `const *`. This is a backward-compatible
-  change, but makes it easier to extract constants that can be safely shared
-  between multiple threads and/or invocations.
-
-v1.1.1 (6 January 2021)
+v1.3.7 (8 November 2024)
+========================
+
+* Test against Python 3.13.
+* Update the Makefile to support Semantic Versioning from git tags.
+* Update the C libraries to allow for passing the version as a compiler
+  flag.
+* Update `setup.py` to pass the SCM version to the Cython compiler.
+* Include C tests in the Tox suite (for linux and macos only).
+* Document any and all changes to the C API since forking.
+* Restructure changelog documentation.
+
+v1.3.6 (7 October 2024)
 =======================
 
-* Same as v1.1.0 but with wheels built and uploaded to PyPI. Please report if you
-  have problems with wheels.
-
+* Fix wrong int type in Windows
+  ([#2](https://github.com/PJ-Watson/sep-pjw/issues/2), thanks to
+  @acenko for pointing this out).
+* Update tests to run on multiple operating systems.
 
-v1.1.0 (3 January 2021)
-=======================
-
-* Add segmentation masking to the photometry and kron/auto functions (#69).
-
-* Add functions `sep.set_sub_object_limit(limit)` and `sep.get_sub_object_limit()`
-  for modifying and retrieving the sub-object deblending limit. Previously this
-  parameter was hard-coded to 1024. 1024 is now the default value.
-
-* This and future versions are now Python 3 only. Python 2 is no longer
-  supported.
-
-* Modernize setup.py with pyproject.toml
-
-
-v1.0.3 (12 June 2018)
+v1.3.5 (12 June 2024)
 =====================
 
-* Fix double-free bug in sep_extract() arising when an error status occurs
-  and convolution is on. (#56)
-
-* Work around numpy dependency in setup. (#59)
-
-
-v1.0.2 (19 September 2017)
-==========================
-
-* Fix makefile so that `make install` works on OS X for the C library.
-  Python module and C code are unchanged.
-
-
-v1.0.1 (10 July 2017)
-=====================
-
-* Fix bug when using masked filter and noise array where objects with member
-  pixels at end of image (maximum y coordinate) were erroneously missed.
-
-
-v1.0.0 (30 September 2016)
-==========================
-
-* Remove features deprecated in previous versions.
-
-* Fix bug in Background.rms() giving nonsensical results.
-
-v0.6.0 (25 August 2016)
-=======================
-
-* New, more coherent C API. This change should be transparent to users
-  of the Python module.
-
-* Add variance uncertainty parameters `errx2`, `erry2` and `errxy` to
-  output of `sep.extract()`.
-
-* Add a minimum sigma to `sep.winpos()` to match Source Extractor
-  behavior.
-
-* Fix use of boolean masks in `sep.kron_radius()`. Formerly, using a
-  boolean mask resulted in nonsense results.
-
-* Fix segfault in `Background.back()` when box size is same as image size.
-
-* Fix bug in creating long error messages on Python 3.
-
-v0.5.2 (4 January 2016)
-=======================
-
-Adds OS X and Windows support.
-
-v0.5.1 (30 November 2015)
-=========================
-
-Bugfix release for problem in setup.py in packaged code.
-
-v0.5.0 (22 November 2015)
-=========================
-
-* `sep.extract()` now uses a more correct matched filter algorithm in the
-  presence of a noise array, rather than simple convolution. The `conv`
-  keyword has been changed to `filter_kernel` to reflect this, and a
-  `filter_type` keyword has been added to allow selecting the old behavior
-  of simple convolution.
-
-* `sep.extract()` now accepts a `mask` keyword argument.
-
-* `sep.extract()` can now return a segmentation map.
-
-* Special methods added to allow `data - bkg` and `np.array(bkg)` where
-  `bkg` is a Background object.
-
-v0.4.1 (10 November 2015)
-=========================
-
-Bugfix release, fixing error estimate in `sep.sum_circle` and
-`sep.sum_ellipse` when `bkgann` keyword argument is given.
-
-v0.4.0 (1 June 2015)
-====================
-
-* New `sep.winpos()` function.
-
-v0.3.0 (23 February 2015)
-=========================
-
-* New `sep.flux_radius()` function.
-
-v0.2.0 (13 December 2014)
-=========================
-
-* **[breaking change]** `theta` field in `extract()` output is now in
-  radians rather than degrees, for compatibility with new ellipse
-  aperture functions.
-
-* **[deprecation]** Change `mask_ellipse()` parameters from ellipse
-  coefficients to ellipse axes and position angle, to match aperture
-  functions. (Old behavior still works as well.)
-
-* **[deprecation]** Change `apercirc()` to `sum_circle()`, to match
-  new aperture functions. (Old name, `apercirc()`, still works.)
-
-* Add `sum_circann()`, `sum_ellipse()`, `sum_ellipann()`,
-  `kron_radius()`, `ellipse_coeffs()`, `ellipse_axes()` functions.
-
-* Exact mode aperture photometery in all functions, with `subpix=0`.
-
-* Enable variable thresholding in `sep.extract`. [#11]
-
-* Fix bug in background masking. This bug impacted masking in all
-  functions that used masking. Also affected C library.
-
-* More detail in error messages coming from within the C library.
-  More helpful error message for non-native byteorder arrays.
-
-* Add ability to change pixel stack size used in `extract()`, with
-  `set_extract_pixstack()` function
-
-v0.1.0 (11 August 2014)
-=======================
-
-This is the first official release.
+* Small fixes and updates to ensure compatibility with NumPy 2.0.
+
+v1.3.4 (21 February 2024)
+========================
+
+* Include .clang-format as a pre-commit hook, to ensure consistent code
+  style (improved readability, easier maintenance).
+* Fixed `make test` to account for the changes in
+  [v1.3.0](https://github.com/PJ-Watson/sep-pjw/releases/tag/v1.3.0).
+* All header files include the correct definitions.
+
+v1.3.3 (7 February 2024)
+========================
+
+* Add changelog to documentation.
+* Add tests for re-running with seg map.
+* Fix array boundary bugs when re-running with seg map.
+* Fix bug with precision loss when calculating threshold.
+* Improve error handling when object pixels exceed pix stack.
+
+v1.3.2 (5 February 2024)
+========================
+
+* Move documentation to new location, fix package names and imports.
+* Add wheels for Python 3.11/3.12.
+* Fix C compilation errors on windows (VLAs).
+* Publish updated version to PyPI under new name.
+
+v1.3.1 (31 January 2024)
+========================
+
+* Formatting changes (follow [black](https://github.com/psf/black)
+  formatting style).
+* Fix `bench.py` and `test.py`, removing deprecated functions.
+* Move metadata into `pyproject.toml`.
+* Add pre-commit hooks for code and docstring validation.
+* Change to dynamic versioning (git tag/commit based).
+
+v1.3.0 (1 December 2023)
+========================
+
+* The `segmentation_map` argument of `sep.extract()` will now accept
+  either an array or boolean. If an existing segmentation map is passed,
+  the object detection stage is skipped, and sources will be individually
+  analysed according to the provided map. This change is
+  backwards-compatible with respect to the Python module.
+
+  Please note that as no deblending is performed, the calculated
+  thresholds (and any dependent parameters) may not be the same as
+  originally derived.
+
+* Use 64-bit integers throughout, to fix memory addressing with large
+  arrays
+  ([#122](https://github.com/kbarbary/sep/issues/122 "Original issue"),
+  inspired by [Gabe Brammer's fork](https://github.com/gbrammer/sep)
+  with additional fixes).
diff --git a/FindSEP.cmake b/FindSEP.cmake
index 1f32ad4..54aa3b3 100644
--- a/FindSEP.cmake
+++ b/FindSEP.cmake
@@ -48,5 +48,5 @@ else (SEP_LIBRARIES)
   endif (SEP_FOUND)
 
   mark_as_advanced(SEP_LIBRARIES)
-  
+
 endif (SEP_LIBRARIES)
diff --git a/Makefile b/Makefile
index 2ba9cf9..bc8bc4e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,41 @@
 
 OS ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
 
-SOMAJOR = 1
-SOMINOR = 0
-SOBUGFIX = 3
+DESCRIBE           := $(shell git describe --match "v*" --always --tags)
+DESCRIBE_PARTS     := $(subst -, ,$(DESCRIBE))
+
+VERSION_TAG        := $(word 1,$(DESCRIBE_PARTS))
+COMMITS_SINCE_TAG  := $(word 2,$(DESCRIBE_PARTS))
+BUILD_ID           := $(word 3,$(DESCRIBE_PARTS))
+
+VERSION            := $(subst v,,$(VERSION_TAG))
+VERSION_PARTS      := $(subst ., ,$(VERSION))
+
+MAJOR              := $(word 1,$(VERSION_PARTS))
+MINOR              := $(word 2,$(VERSION_PARTS))
+MICRO              := $(word 3,$(VERSION_PARTS))
+
+NEXT_MICRO         := $(shell echo $$(($(MICRO)+1)))
+
+ifeq ($(strip $(COMMITS_SINCE_TAG)),)
+CURRENT_VERSION_MICRO := $(MAJOR).$(MINOR).$(MICRO)
+CURRENT_MICRO := $(MICRO)
+else
+CURRENT_VERSION_MICRO := $(MAJOR).$(MINOR).$(NEXT_MICRO)
+CURRENT_MICRO := $(NEXT_MICRO)-dev$(COMMITS_SINCE_TAG)$(if $(BUILD_ID),-${BUILD_ID},)
+endif
 
 ifeq ($(OS), darwin)
 SONAME = libsep.dylib
-SONAME_MAJOR = libsep.$(SOMAJOR).dylib
-SONAME_FULL = libsep.$(SOMAJOR).$(SOMINOR).$(SOBUGFIX).dylib
+SONAME_MAJOR = libsep.$(MAJOR).dylib
+SONAME_FULL = libsep.$(MAJOR).$(MINOR).$(CURRENT_MICRO).dylib
 SONAME_FLAG = -install_name
 LDPATHENV = DYLD_LIBRARY_PATH
 else
 ifeq ($(OS), linux)
 SONAME = libsep.so
-SONAME_MAJOR = libsep.so.$(SOMAJOR)
-SONAME_FULL = libsep.so.$(SOMAJOR).$(SOMINOR).$(SOBUGFIX)
+SONAME_MAJOR = libsep.so.$(MAJOR)
+SONAME_FULL = libsep.so.$(MAJOR).$(MINOR).$(CURRENT_MICRO)
 SONAME_FLAG = -soname
 LDPATHENV = LD_LIBRARY_PATH
 else
@@ -36,6 +56,7 @@ LDFLAGS ?=
 
 CPPFLAGS += -Isrc
 CFLAGS += -Wall -Wextra -Wcast-qual -O3 -fvisibility=hidden  # -Werror
+CFLAGS += -DSEP_VERSION_STRING=\"$(MAJOR).$(MINOR).$(CURRENT_MICRO)\"
 CFLAGS_LIB = $(CFLAGS) -fPIC
 LDFLAGS_LIB = $(LDFLAGS) -shared -Wl,$(SONAME_FLAG),$(SONAME_MAJOR)
 
diff --git a/README.md b/README.md
index a0141e2..f9259e4 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,37 @@
 SEP
 ===
 
-Python and C library for Source Extraction and Photometry
-
-![Build Status](https://github.com/kbarbary/sep/workflows/Python%20package/badge.svg)
-[![PyPI](https://img.shields.io/pypi/v/sep.svg)](https://pypi.python.org/pypi/sep)
+Python and C library for Source Extraction and Photometry, originally
+developed at [kbarbary/sep](https://github.com/kbarbary/sep) and later
+maintained at [PJ-Watson/sep-pjw](https://github.com/PJ-Watson/sep-pjw).
+
+[![PyPI](https://img.shields.io/pypi/v/sep?label=PyPI)](https://pypi.python.org/pypi/sep)
+[![PyPI - Downloads](https://img.shields.io/pypi/dm/sep?label=PyPI%20Downloads)
+](https://pypi.python.org/pypi/sep)
+![Build Status](https://github.com/sep-developers/sep/workflows/CI/badge.svg)
+[![Documentation Status](https://readthedocs.org/projects/sep-pjw/badge/?version=latest)](https://sep-pjw.readthedocs.io/en/latest/?badge=latest)
 [![JOSS](http://joss.theoj.org/papers/10.21105/joss.00058/status.svg)](http://dx.doi.org/10.21105/joss.00058)
 
-*"... [it's] an SEP: Somebody Else's Problem."  
+*"... [it's] an SEP: Somebody Else's Problem."
 "Oh, good. I can relax then."*
 
+SEP, SEP-PJW, and Package Names
+-------------------------------
+
+`sep` was originally released by Kyle Barbary, at
+[kbarbary/sep](https://github.com/kbarbary/sep) (``sep<=1.2.1``). For a
+brief period, the package was maintained by Peter Watson, under the
+`sep-pjw` package name, at
+[PJ-Watson/sep-pjw](https://github.com/PJ-Watson/sep-pjw) and
+[PyPI/sep-pjw](https://pypi.org/project/sep-pjw/)
+(``1.3.0<=sep-pjw<=1.3.8``). Both of these repositories will be archived,
+and future development will take place at
+[sep-developers/sep](<https://github.com/sep-developers/sep>)
+(``sep>=1.4.0``). Note that there may be some incompatibilities between
+``sep==1.2.1`` and ``sep==1.4.0`` when using the C-API directly (to fix
+an indexing bug arising with large arrays) - all changes are documented
+[here](https://sep-pjw.readthedocs.io/en/latest/changelogs/changes_to_c_api.html).
+
 
 About
 -----
@@ -43,19 +65,19 @@ instructions.
 Python
 ------
 
-**Documentation:** http://sep.readthedocs.io
+**Documentation:** http://sep-pjw.readthedocs.io
 
 **Requirements:**
 
-- Python 3.5+
-- numpy
+- Python 3.9+
+- numpy 1.23+
 
 **Install release version:**
 
 SEP can be installed with [pip](https://pip.pypa.io):
 
 ```
-pip install sep
+python -m pip install sep
 ```
 
 If you get an error about permissions, you are probably using your
@@ -64,7 +86,7 @@ install"](https://pip.pypa.io/en/latest/user_guide/#user-installs)
 option to install sep into your user directory:
 
 ```
-pip install --user sep
+python -m pip install --user sep
 ```
 
 Do **not** install sep or other third-party Python packages using
@@ -77,7 +99,7 @@ Building the development version (from github) requires Cython.
 Build and install in the usual place:
 
 ```
-./setup.py install
+python -m pip install --editable .
 ```
 
 **Run tests:** Tests require the [pytest](http://pytest.org) Python
@@ -133,14 +155,14 @@ and header file in `/path/to/prefix/include`. The default prefix is
 Contributing
 ------------
 
-- Report a bug or documentation issue: http://github.com/kbarbary/sep/issues
-- Ask (or answer) a question: https://github.com/kbarbary/sep/discussions/categories/q-a
+- Report a bug or documentation issue: http://github.com/sep-developers/issues
+- Ask (or answer) a question: https://github.com/sep-developers/sep/discussions/categories/q-a
 
 Development of SEP takes place on GitHub at
-http://github.com/kbarbary/sep.  Contributions of bug fixes,
+[sep-developers/sep](http://github.com/sep-developers/sep).  Contributions of bug fixes,
 documentation improvements and minor feature additions are welcome via
 GitHub pull requests. For major features, it is best to discuss the change first
-via [GitHub Discussions](https://github.com/kbarbary/sep/discussions/).
+via [GitHub Discussions](https://github.com/sep-developers/sep/discussions/).
 
 
 Citation
@@ -179,7 +201,7 @@ executable built on top of the library. In Source Extractor, background
 estimation, object detection and photometry are deeply integrated into the
 Source Extractor executable. Many changes to the code were necessary in
 order to put the functionality in stand-alone C functions. It's too much
-to ask of the Source Extractor developer to rewrite large parts of the 
+to ask of the Source Extractor developer to rewrite large parts of the
 core of the Source Extractor program with little gain for the executable.
 
 **What sort of changes?**
@@ -260,4 +282,4 @@ the data.
 
 **I have more questions!**
 
-Open a discussion on the [GitHub Discussions page](https://github.com/kbarbary/sep/discussions/categories/q-a)!
+Open a discussion on the [GitHub Discussions page](https://github.com/sep-developers/sep/discussions/categories/q-a)!
diff --git a/bench.py b/bench.py
index 05a6431..46be83a 100755
--- a/bench.py
+++ b/bench.py
@@ -1,14 +1,20 @@
 #!/usr/bin/env python
+
+"""Benchmarking SEP against equivalent photutils functions."""
+
 from __future__ import print_function
 
-from os.path import join
 import time
+from os.path import join
+
 import numpy as np
+
 import sep
 
 # try to import photutils for comparison timing
 try:
     import photutils
+
     HAVE_PHOTUTILS = True
 except ImportError:
     HAVE_PHOTUTILS = False
@@ -16,11 +22,13 @@
 # Try to import any FITS reader
 try:
     from fitsio import read as getdata
+
     HAVE_FITS = True
     NEED_BYTESWAP = False
 except ImportError:
     try:
         from astropy.io.fits import getdata
+
         HAVE_FITS = True
     except ImportError:
         HAVE_FITS = False
@@ -37,47 +45,53 @@
     t0 = time.time()
     bkg = sep.Background(data)  # estimate background
     t1 = time.time()
-    print("measure background: {0:6.2f} ms".format((t1-t0) * 1.e3))
+    print("measure background: {0:6.2f} ms".format((t1 - t0) * 1.0e3))
 
     t0 = time.time()
     bkg.subfrom(data)  # subtract it
     t1 = time.time()
-    print("subtract background: {0:6.2f} ms".format((t1-t0) * 1.e3))
+    print("subtract background: {0:6.2f} ms".format((t1 - t0) * 1.0e3))
 
     t0 = time.time()
     backarr = bkg.back(dtype=np.float64)  # background
     t1 = time.time()
-    print("background array: {0:6.2f} ms".format((t1-t0) * 1.e3))
+    print("background array: {0:6.2f} ms".format((t1 - t0) * 1.0e3))
 
     t0 = time.time()
     rmsarr = bkg.rms()
     t1 = time.time()
-    print("rms array: {0:6.2f} ms".format((t1-t0) * 1.e3))
+    print("rms array: {0:6.2f} ms".format((t1 - t0) * 1.0e3))
 
     t0 = time.time()
     objects = sep.extract(data, 1.5 * bkg.globalrms)
     t1 = time.time()
-    print("extract: {0:6.2f} ms  [{1:d} objects]"
-          .format((t1-t0) * 1.e3, len(objects)))
+    print(
+        "extract: {0:6.2f} ms  [{1:d} objects]".format((t1 - t0) * 1.0e3, len(objects))
+    )
 
-#--------------------------------------------------------------------------
+# --------------------------------------------------------------------------
 # Background subtraction
 
 print("")
 if HAVE_PHOTUTILS:
     print("sep version:      ", sep.__version__)
     print("photutils version:", photutils.__version__)
-    print("""
+    print(
+        """
 | test                    | sep             | photutils       | ratio  |
-|-------------------------|-----------------|-----------------|--------|""")
-    blankline = \
-"|                         |                 |                 |        |"
+|-------------------------|-----------------|-----------------|--------|"""
+    )
+    blankline = (
+        "|                         |                 |                 |        |"
+    )
 
 else:
     print("sep version: ", sep.__version__)
-    print("""
+    print(
+        """
 | test                    | sep             |
-|-------------------------|-----------------|""")
+|-------------------------|-----------------|"""
+    )
     blankline = "|                         |                 |"
 
 nloop = 50
@@ -90,23 +104,27 @@
     for _ in range(0, nloop):
         bkg = sep.Background(data)
     t1 = time.time()
-    t_sep = (t1-t0) * 1.e3 / nloop
+    t_sep = (t1 - t0) * 1.0e3 / nloop
     line += "      {0:7.2f} ms |".format(t_sep)
 
     if HAVE_PHOTUTILS:
         t0 = time.time()
         for _ in range(0, nloop):
             try:
-                bkg = photutils.Background(data, (64, 64))  # estimate background
+                bkg = photutils.background.Background(
+                    data, (64, 64)
+                )  # estimate background
             except AttributeError:
-                bkg = photutils.background.Background2D(data, (64, 64))  # estimate background
+                bkg = photutils.background.Background2D(
+                    data, (64, 64)
+                )  # estimate background
         t1 = time.time()
-        t_pu = (t1-t0) * 1.e3 / nloop
-        line += "      {0:7.2f} ms | {1:6.2f} |".format(t_pu, t_pu/t_sep)
+        t_pu = (t1 - t0) * 1.0e3 / nloop
+        line += "      {0:7.2f} ms | {1:6.2f} |".format(t_pu, t_pu / t_sep)
 
     print(line)
 
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
 # Circular aperture photometry benchmarks
 
 if not CONDENSED:
@@ -118,16 +136,19 @@
 
 naper = 1000
 data = np.ones((2000, 2000), dtype=np.float32)
-x = np.random.uniform(200., 1800., naper)
-y = np.random.uniform(200., 1800., naper)
+x = np.random.uniform(200.0, 1800.0, naper)
+y = np.random.uniform(200.0, 1800.0, naper)
 
 if CONDENSED:
-    r_list = [5.]
+    r_list = [5.0]
     subpix_list = [(5, "subpixel", "subpix=5"), (0, "exact", "exact")]
 else:
-    r_list = [3., 5., 10., 20.]
-    subpix_list = [(1, "center", "subpix=1"), (5, "subpixel", "subpix=5"),
-                   (0, "exact", "exact")]
+    r_list = [3.0, 5.0, 10.0, 20.0]
+    subpix_list = [
+        (1, "center", "subpix=1"),
+        (5, "subpixel", "subpix=5"),
+        (0, "exact", "exact"),
+    ]
 
 for r in r_list:
     for subpix, method, label in subpix_list:
@@ -138,27 +159,28 @@
         for _ in range(0, nloop):
             flux, fluxerr, flag = sep.sum_circle(data, x, y, r, subpix=subpix)
         t1 = time.time()
-        t_sep = (t1-t0) * 1.e6 / naper / nloop
+        t_sep = (t1 - t0) * 1.0e6 / naper / nloop
         line += " {0:7.2f} us/aper |".format(t_sep)
 
         if HAVE_PHOTUTILS:
-            apertures = photutils.aperture.CircularAperture(np.array((x, y)).T, r)
+            apertures = photutils.aperture.CircularAperture(np.column_stack((x, y)), r)
             t0 = time.time()
             for _ in range(0, nloop):
                 res = photutils.aperture.aperture_photometry(
-                    data, apertures, method=method, subpixels=subpix)
+                    data, apertures, method=method, subpixels=subpix
+                )
             t1 = time.time()
-            t_pu = (t1-t0) * 1.e6 / naper / nloop
-            line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu/t_sep)
+            t_pu = (t1 - t0) * 1.0e6 / naper / nloop
+            line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep)
 
         print(line)
 
 if not CONDENSED:
     print(blankline)
 
-a = 1.
-b = 1.
-theta = np.pi/4.
+a = 1.0
+b = 1.0
+theta = np.pi / 4.0
 
 for r in r_list:
     for subpix, method, label in subpix_list:
@@ -166,20 +188,24 @@
 
         t0 = time.time()
         for _ in range(0, nloop):
-            flux, fluxerr, flag = sep.sum_ellipse(data, x, y, a, b, theta, r,
-                                                subpix=subpix)
+            flux, fluxerr, flag = sep.sum_ellipse(
+                data, x, y, a, b, theta, r, subpix=subpix
+            )
         t1 = time.time()
-        t_sep = (t1-t0) * 1.e6 / naper / nloop
+        t_sep = (t1 - t0) * 1.0e6 / naper / nloop
         line += " {0:7.2f} us/aper |".format(t_sep)
 
         if HAVE_PHOTUTILS:
-            apertures = photutils.aperture.EllipticalAperture(np.array((x, y)).T, a*r, b*r, theta)
+            apertures = photutils.aperture.EllipticalAperture(
+                np.column_stack((x, y)), a * r, b * r, theta
+            )
             t0 = time.time()
             for _ in range(0, nloop):
                 res = photutils.aperture.aperture_photometry(
-                    data, apertures, method=method, subpixels=subpix)
+                    data, apertures, method=method, subpixels=subpix
+                )
             t1 = time.time()
-            t_pu = (t1-t0) * 1.e6 / naper / nloop
-            line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu/t_sep)
+            t_pu = (t1 - t0) * 1.0e6 / naper / nloop
+            line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep)
 
         print(line)
diff --git a/data/README.md b/data/README.md
index 9ea1124..ef316a8 100644
--- a/data/README.md
+++ b/data/README.md
@@ -7,4 +7,4 @@ The comparison catalog file `image.cat` is generated by running
 sextractor image.fits -CATALOG_NAME image.cat
 ```
 
-in this directory.
\ No newline at end of file
+in this directory.
diff --git a/docs/apertures.rst b/docs/apertures.rst
index b802b50..32a1055 100644
--- a/docs/apertures.rst
+++ b/docs/apertures.rst
@@ -4,7 +4,7 @@ Aperture photometry
 There are four aperture functions available:
 
 ==================  =========================
-Function            Sums data within...
+Function                Sums data within...
 ==================  =========================
 `sep.sum_circle`    circle(s)
 `sep.sum_circann`   circular annulus/annuli
@@ -13,7 +13,9 @@ Function            Sums data within...
 ==================  =========================
 
 The follow examples demonstrate options for circular aperture
-photometry. The other functions behave similarly. ::
+photometry. The other functions behave similarly.
+
+.. code-block:: python
 
    # sum flux in circles of radius=3.0
    flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0)
@@ -35,10 +37,12 @@ flexibly and efficiently calculated, depending on the characteristics
 of your data. The presence of an ``err`` or ``var`` keyword indicates
 a per-pixel noise, while the presense of a ``gain`` keyword indicates
 that the Poisson uncertainty on the total sum should be included. Some
-illustrative examples::
+illustrative examples:
+
+.. code-block:: python
 
    # Specify a per-pixel "background" error and a gain. This is suitable
-   # when the data have been background subtracted. 
+   # when the data have been background subtracted.
    flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0,
                                         err=bkg.globalrms, gain=1.0)
 
@@ -73,10 +77,12 @@ noise in each pixel, :math:`F` is the sum in the aperture and
 :math:`g` is the gain. The last term is not added if ``gain`` is
 `None`.
 
-**Masking** 
+**Masking**
 
 Apply a mask (same shape as data). Pixels where the mask is True are
-"corrected" to the average value within the aperture. ::
+"corrected" to the average value within the aperture.
+
+.. code-block:: python
 
    flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0,
                                         mask=mask)
@@ -84,7 +90,10 @@ Apply a mask (same shape as data). Pixels where the mask is True are
 **Local background subtraction**
 
 The `~sep.sum_circle` and `~sep.sum_ellipse` functions have options
-for performing local background subtraction. For example, to subtract the background calculated in an annulus between 6 and 8 pixel radius::
+for performing local background subtraction. For example, to subtract the
+background calculated in an annulus between 6 and 8 pixel radius:
+
+.. code-block:: python
 
    flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 3.0,
                                         mask=mask, bkgann=(6., 8.))
@@ -98,7 +107,9 @@ Equivalent of FLUX_AUTO (e.g., MAG_AUTO) in Source Extractor
 ------------------------------------------------------------
 
 This is a two-step process. First we calculate the Kron radius for each
-object, then we perform elliptical aperture photometry within that radius::
+object, then we perform elliptical aperture photometry within that radius:
+
+.. code-block:: python
 
    kronrad, krflag = sep.kron_radius(data, x, y, a, b, theta, 6.0)
    flux, fluxerr, flag = sep.sum_ellipse(data, x, y, a, b, theta, 2.5*kronrad,
@@ -110,7 +121,9 @@ This specific example is the equilvalent of setting ``PHOT_AUTOPARAMS
 ``sep.sum_ellipse``). The second Source Extractor parameter is a
 minimum diameter. To replicate Source Extractor behavior for non-zero
 values of the minimum diameter, one would put in logic to use circular
-aperture photometry if the Kron radius is too small. For example::
+aperture photometry if the Kron radius is too small. For example:
+
+.. code-block:: python
 
    r_min = 1.75  # minimum diameter = 3.5
    use_circle = kronrad * np.sqrt(a * b) < r_min
@@ -134,12 +147,16 @@ the circle containing the same flux as whatever ellipse Source
 Extractor used for ``FLUX_AUTO``.
 
 Given a previous calculation of ``flux`` as above, calculate the
-radius for a flux fraction of 0.5::
+radius for a flux fraction of 0.5:
+
+.. code-block:: python
 
     r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'], 0.5,
                               normflux=flux, subpix=5)
 
-And for multiple flux fractions::
+And for multiple flux fractions:
+
+.. code-block:: python
 
     r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'],
                               [0.5, 0.6], normflux=flux, subpix=5)
@@ -155,7 +172,9 @@ Extractor exactly, the right ``sig`` parameter (giving a description
 of the effective width) must be used for each object.  Source
 Extractor uses ``2.  / 2.35 * (half-light radius)`` where the
 half-light radius is calculated using ``flux_radius`` with a fraction
-of 0.5 and a normalizing flux of ``FLUX_AUTO``. The equivalent here is::
+of 0.5 and a normalizing flux of ``FLUX_AUTO``. The equivalent here is:
+
+.. code-block:: python
 
     sig = 2. / 2.35 * r  # r from sep.flux_radius() above, with fluxfrac = 0.5
     xwin, ywin, flag = sep.winpos(data, objs['x'], objs['y'], sig)
@@ -164,25 +183,42 @@ of 0.5 and a normalizing flux of ``FLUX_AUTO``. The equivalent here is::
 Segmentation-masked image measurements
 --------------------------------------
 
-SourceExtractor provides a mechanism for measuring the "AUTO" and "FLUX_RADIUS" parameters for a given object including a mask for neighboring sources.  In addition to the mask, setting the SourceExtractor parameter ``MASK_TYPE=CORRECT`` further fills the masked pixels of a given source with "good" pixel values reflected opposite of the masked pixels.  The ``SEP`` photometry and measurement functions provide an option for simple masking without reflection or subtracting neighbor flux.  
+SourceExtractor provides a mechanism for measuring the "AUTO" and
+"FLUX_RADIUS" parameters for a given object including a mask for
+neighboring sources. In addition to the mask, setting the SourceExtractor
+parameter ``MASK_TYPE=CORRECT`` further fills the masked pixels of a given
+source with "good" pixel values reflected opposite of the masked pixels.
+The ``SEP`` photometry and measurement functions provide an option for
+simple masking without reflection or subtracting neighbor flux.
 
-For example, using a segmentation array provided by ``sep.extract``, we can compute the masked ``flux_radius`` that could otherwise be artificially large due to flux from nearby sources::
+For example, using a segmentation array provided by ``sep.extract``, we
+can compute the masked ``flux_radius`` that could otherwise be
+artificially large due to flux from nearby sources:
+
+.. code-block:: python
 
     # list of object id numbers that correspond to the segments
     seg_id = np.arange(1, len(objs)+1, dtype=np.int32)
-    
-    r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'], 0.5,
-                              seg_id=seg_id, seg=seg, 
+
+    r, flag = sep.flux_radius(data, objs['x'], objs['y'], 6.*objs['a'],
+                              0.5, seg_id=seg_id, seg=seg,
                               normflux=flux, subpix=5)
 
-To enforce that a given measurement **only** includes pixels within a segment, provide negative values in the ``seg_id`` list.  Otherwise the mask for a given object will be pixels with ``(seg == 0) | (seg_id == id_i)``.
+To enforce that a given measurement **only** includes pixels within a
+segment, provide negative values in the ``seg_id`` list.  Otherwise the
+mask for a given object will be pixels with
+``(seg == 0) | (seg_id == id_i)``.
 
-The following functions include the segmentation masking: ``sum_circle``, ``sum_circann``, ``sum_ellipse``, ``sum_ellipann``, ``flux_radius`` , and ``kron_radius`` (``winpos`` **currently does not**). 
+The following functions include the segmentation masking:
+``sum_circle``, ``sum_circann``, ``sum_ellipse``, ``sum_ellipann``,
+``flux_radius`` , and ``kron_radius`` (``winpos`` **currently does not**).
 
 Masking image regions
 ---------------------
 
-Create a boolean array with elliptical regions set to True::
+Create a boolean array with elliptical regions set to True:
+
+.. code-block:: python
 
    mask = np.zeros(data.shape, dtype=np.bool)
    sep.mask_ellipse(mask, objs['x'], objs['y'], obs['a'], objs['b'],
diff --git a/docs/changelogs/changelog.rst b/docs/changelogs/changelog.rst
new file mode 100644
index 0000000..53931e4
--- /dev/null
+++ b/docs/changelogs/changelog.rst
@@ -0,0 +1,22 @@
+.. _changelog:
+
+Changelog
+=========
+
+
+Upgrading From kbarbary/sep
+---------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   changes_to_c_api
+
+Full Changelog
+--------------
+
+.. toctree::
+   :maxdepth: 2
+
+   new_changes
+   original_changes
diff --git a/docs/changelogs/changes_to_c_api.rst b/docs/changelogs/changes_to_c_api.rst
new file mode 100644
index 0000000..8e18e72
--- /dev/null
+++ b/docs/changelogs/changes_to_c_api.rst
@@ -0,0 +1,83 @@
+Changes to the C API
+====================
+
+This page details cumulative changes to the C API between v1.2.1 and
+v1.4.0, or since this package was forked from
+`kbarbary/sep <https://github.com/kbarbary/sep>`_. Almost all changes to
+the public API are to integer parameters, many of which have been changed
+from ``int`` to ``int64_t``, to fix problems which may arise with
+extremely large arrays. The other change of note is to the ``sep_image``
+struct, which enables the user to pass an existing segmentation map, and
+re-extract all morphological and photometric quantities on a different
+image.
+
+All changes here are transparent to users of the Python interface.
+
+.. c:struct::  sep_image
+
+ - Three new parameters have been added:
+
+   .. c:var:: int64_t * segids
+
+      The unique ids in an existing segmentation map.
+
+   .. c:var:: int64_t * idcounts
+
+      The number of occurrences of each unique id in an existing
+      segmentation map.
+
+   .. c:var:: int64_t numids
+
+      The total number of unique ids in an existing segmentation map.
+
+ - The type of ``w`` and ``h`` has changed from ``int`` to ``int64_t``.
+
+.. c:struct:: sep_bkg
+
+ - The type of the following parameters has changed from ``int`` to
+   ``int64_t``: ``w``, ``h``, ``bw``, ``bh``, ``nx``, ``ny``, and ``n``.
+
+.. c:struct:: sep_catalog
+
+ - The type of the following parameters has changed from ``int`` to
+   ``int64_t``: ``npix``, ``tnpix``, ``xmin``, ``xmax``, ``ymin``,
+   ``ymax``, ``xcpeak``, ``ycpeak``, ``xpeak``, ``ypeak``, ``pix``, and
+   ``objectspix``.
+
+.. c:function:: int sep_background()
+
+ - The type of the following parameters has changed from ``int`` to
+   ``int64_t``: ``bw``, ``bh``, ``fw``, and ``fh``.
+
+.. c:function:: float sep_bkg_pix()
+
+ - The type of ``x`` and ``y`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: int sep_bkg_line()
+
+ - The type of ``y`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: int sep_bkg_subline()
+
+ - The type of ``y`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: int sep_bkg_rmsline()
+
+ - The type of ``y`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: int sep_extract()
+
+ - The type of ``convw`` and ``convh`` has changed from ``int`` to
+   ``int64_t``.
+
+.. c:function:: int sep_sum_circann_multi()
+
+ - The type of ``n`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: int sep_flux_radius()
+
+ - The type of ``n`` has changed from ``int`` to ``int64_t``.
+
+.. c:function:: void sep_set_ellipse()
+
+ - The type of ``w`` and ``h`` has changed from ``int`` to ``int64_t``.
diff --git a/docs/changelogs/new_changes.rst b/docs/changelogs/new_changes.rst
new file mode 100644
index 0000000..fff7486
--- /dev/null
+++ b/docs/changelogs/new_changes.rst
@@ -0,0 +1,7 @@
+New Changelog
+=============
+
+**Full Changelog**
+
+.. include:: ../../CHANGES.md
+   :parser: myst_parser.sphinx_
diff --git a/docs/changelogs/original_changes.md b/docs/changelogs/original_changes.md
new file mode 100644
index 0000000..81d88cf
--- /dev/null
+++ b/docs/changelogs/original_changes.md
@@ -0,0 +1,179 @@
+Original Changelog
+==================
+
+This is the original changelog from [kbarbary/sep](https://github.com/kbarbary/sep),
+copied here for posterity.
+
+v1.2.1 (1 June 2022)
+--------------------
+
+* Same as v1.2.0 but with new wheels for Python 3.10 and AArch64.
+
+v1.2.0 (1 May 2021)
+-------------------
+
+* Changed `numpy.float` and `numpy.int` types for deprecations in numpy 1.20 (#96).
+
+* Make it possible to safely invoke C library from multiple threads on
+  independent inputs.
+
+  Global config functions such as `set_sub_object_limit()`
+  and `set_extract_pixstack()` still configure global params
+  (once for all threads), while other functions will retain their data
+  in thread-local storages, so they can be invoked from multiple threads as
+  long as they work on independent structures.
+
+  Library compilation will now require a C11 compatible compiler, which should
+  be nowadays available on all supported platforms.
+
+* Mark some pointer parameters with `const *`. This is a backward-compatible
+  change, but makes it easier to extract constants that can be safely shared
+  between multiple threads and/or invocations.
+
+v1.1.1 (6 January 2021)
+-----------------------
+
+* Same as v1.1.0 but with wheels built and uploaded to PyPI. Please report if you
+  have problems with wheels.
+
+
+v1.1.0 (3 January 2021)
+-----------------------
+
+* Add segmentation masking to the photometry and kron/auto functions (#69).
+
+* Add functions `sep.set_sub_object_limit(limit)` and `sep.get_sub_object_limit()`
+  for modifying and retrieving the sub-object deblending limit. Previously this
+  parameter was hard-coded to 1024. 1024 is now the default value.
+
+* This and future versions are now Python 3 only. Python 2 is no longer
+  supported.
+
+* Modernize setup.py with pyproject.toml
+
+
+v1.0.3 (12 June 2018)
+---------------------
+
+* Fix double-free bug in sep_extract() arising when an error status occurs
+  and convolution is on. (#56)
+
+* Work around numpy dependency in setup. (#59)
+
+
+v1.0.2 (19 September 2017)
+--------------------------
+
+* Fix makefile so that `make install` works on OS X for the C library.
+  Python module and C code are unchanged.
+
+
+v1.0.1 (10 July 2017)
+---------------------
+
+* Fix bug when using masked filter and noise array where objects with member
+  pixels at end of image (maximum y coordinate) were erroneously missed.
+
+
+v1.0.0 (30 September 2016)
+--------------------------
+
+* Remove features deprecated in previous versions.
+
+* Fix bug in Background.rms() giving nonsensical results.
+
+v0.6.0 (25 August 2016)
+-----------------------
+
+* New, more coherent C API. This change should be transparent to users
+  of the Python module.
+
+* Add variance uncertainty parameters `errx2`, `erry2` and `errxy` to
+  output of `sep.extract()`.
+
+* Add a minimum sigma to `sep.winpos()` to match Source Extractor
+  behavior.
+
+* Fix use of boolean masks in `sep.kron_radius()`. Formerly, using a
+  boolean mask resulted in nonsense results.
+
+* Fix segfault in `Background.back()` when box size is same as image size.
+
+* Fix bug in creating long error messages on Python 3.
+
+v0.5.2 (4 January 2016)
+-----------------------
+
+Adds OS X and Windows support.
+
+v0.5.1 (30 November 2015)
+-------------------------
+
+Bugfix release for problem in setup.py in packaged code.
+
+v0.5.0 (22 November 2015)
+-------------------------
+
+* `sep.extract()` now uses a more correct matched filter algorithm in the
+  presence of a noise array, rather than simple convolution. The `conv`
+  keyword has been changed to `filter_kernel` to reflect this, and a
+  `filter_type` keyword has been added to allow selecting the old behavior
+  of simple convolution.
+
+* `sep.extract()` now accepts a `mask` keyword argument.
+
+* `sep.extract()` can now return a segmentation map.
+
+* Special methods added to allow `data - bkg` and `np.array(bkg)` where
+  `bkg` is a Background object.
+
+v0.4.1 (10 November 2015)
+-------------------------
+
+Bugfix release, fixing error estimate in `sep.sum_circle` and
+`sep.sum_ellipse` when `bkgann` keyword argument is given.
+
+v0.4.0 (1 June 2015)
+--------------------
+
+* New `sep.winpos()` function.
+
+v0.3.0 (23 February 2015)
+-------------------------
+
+* New `sep.flux_radius()` function.
+
+v0.2.0 (13 December 2014)
+-------------------------
+
+* **[breaking change]** `theta` field in `extract()` output is now in
+  radians rather than degrees, for compatibility with new ellipse
+  aperture functions.
+
+* **[deprecation]** Change `mask_ellipse()` parameters from ellipse
+  coefficients to ellipse axes and position angle, to match aperture
+  functions. (Old behavior still works as well.)
+
+* **[deprecation]** Change `apercirc()` to `sum_circle()`, to match
+  new aperture functions. (Old name, `apercirc()`, still works.)
+
+* Add `sum_circann()`, `sum_ellipse()`, `sum_ellipann()`,
+  `kron_radius()`, `ellipse_coeffs()`, `ellipse_axes()` functions.
+
+* Exact mode aperture photometery in all functions, with `subpix=0`.
+
+* Enable variable thresholding in `sep.extract`. [#11]
+
+* Fix bug in background masking. This bug impacted masking in all
+  functions that used masking. Also affected C library.
+
+* More detail in error messages coming from within the C library.
+  More helpful error message for non-native byteorder arrays.
+
+* Add ability to change pixel stack size used in `extract()`, with
+  `set_extract_pixstack()` function
+
+v0.1.0 (11 August 2014)
+-----------------------
+
+This is the first official release.
diff --git a/docs/conf.py b/docs/conf.py
index e9aa230..5588fe8 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -12,41 +12,54 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys
+"""The sphinx configuration file for the SEP documentation."""
+
 import os
-import sphinx_rtd_theme
+import sys
+
 import sep
 
+try:
+    from sphinx_astropy.conf.v2 import *
+except ImportError:
+    print(
+        "ERROR: the documentation requires the sphinx-astropy package to be installed."
+    )
+    sys.exit(1)
+
 # generate api directory if it doesn't already exist
-if not os.path.exists('api'):
-    os.mkdir('api')
+if not os.path.exists("api"):
+    os.mkdir("api")
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-#sys.path.append(os.path.abspath('ext'))
+# sys.path.insert(0, os.path.abspath('.'))
+# sys.path.append(os.path.abspath('ext'))
 
 # -- General configuration ------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
-intersphinx_mapping = {
-    'python': ('http://docs.python.org/', None),
-    'numpy': ('http://docs.scipy.org/doc/numpy/', None)}
+# intersphinx_mapping = {
+#     "python": ("http://docs.python.org/", None),
+#     "numpy": ("http://docs.scipy.org/doc/numpy/", None),
+# }
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.autosummary',
-    'sphinx.ext.intersphinx',
-    'sphinx.ext.mathjax',
-    'numpydoc',
-    'nbsphinx',
-    'IPython.sphinxext.ipython_console_highlighting'
+    "sphinx.ext.autodoc",
+    "sphinx.ext.autosummary",
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.mathjax",
+    "numpydoc",
+    "nbsphinx",
+    "IPython.sphinxext.ipython_console_highlighting",
+    "sphinx_copybutton",
+    "myst_parser",
 ]
 numpydoc_show_class_members = False
 autosummary_generate = ["reference.rst"]
@@ -54,100 +67,101 @@
 autodoc_default_flags = ["members", "no-special-members"]
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = u'sep'
-copyright = u'2014-2016, Kyle Barbary and contributors'
+project = "sep"
+copyright = "2014-2024, Peter Watson and contributors"
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # THe short X.Y version.
-version = '.'.join(sep.__version__.split('.')[0:2])
+version = ".".join(sep.__version__.split(".")[0:2])
 
 # The full version, including alpha/beta/rc tags.
 release = sep.__version__
 
+html_title = f"{project} {release.split('+')[0]} documentation"
+
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
-#language = None
+# language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build', '**.ipynb_checkpoints']
+exclude_patterns = ["_build", "**.ipynb_checkpoints"]
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
-default_role = 'obj'
+default_role = "autolink"
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 # If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
 
 
 # -- Options for HTML output ----------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = "sphinx_rtd_theme"
-html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_theme = "pydata_sphinx_theme"
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
@@ -157,106 +171,100 @@
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'sepdoc'
+htmlhelp_basename = "sepdoc"
 
 
 # -- Options for LaTeX output ---------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+    # The paper size ('letterpaper' or 'a4paper').
+    #'papersize': 'letterpaper',
+    # The font size ('10pt', '11pt' or '12pt').
+    #'pointsize': '10pt',
+    # Additional stuff for the LaTeX preamble.
+    #'preamble': '',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  ('index', 'sep.tex', u'sep Documentation',
-   u'Kyle Barbary', 'manual'),
+    ("index", "sep.tex", "sep Documentation", "Peter Watson", "manual"),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output ---------------------------------------
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'sep', u'sep Documentation',
-     [u'Kyle Barbary'], 1)
-]
+man_pages = [("index", "sep", "sep Documentation", ["Peter Watson"], 1)]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output -------------------------------------------
@@ -265,19 +273,25 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'sep', u'sep Documentation',
-   u'Kyle Barbary', 'sep', 'One line description of project.',
-   'Miscellaneous'),
+    (
+        "index",
+        "sep",
+        "sep Documentation",
+        "Peter Watson",
+        "sep",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
diff --git a/docs/filter.rst b/docs/filter.rst
index 61ff6e6..25d5b0c 100644
--- a/docs/filter.rst
+++ b/docs/filter.rst
@@ -4,7 +4,11 @@ Matched Filter (Convolution)
 For source detection, SEP supports using a matched filter, which can
 give the optimal detection signal-to-noise for objects with some known
 shape. This is controlled using the ``filter_kernel`` keyword in
-`sep.extract`. For example::
+`sep.extract`. For example:
+
+.. code-block:: python
+
+    import sep
 
     kernel = np.array([[1., 2., 3., 2., 1.],
                        [2., 3., 5., 3., 2.],
@@ -14,7 +18,7 @@ shape. This is controlled using the ``filter_kernel`` keyword in
     objects = sep.extract(data, thresh, filter_kernel=kernel)
 
 If ``filter_kernel`` is not specified, a default 3-by-3 kernel
-is used. To disable filtering entirely, specify ``filter_kernel=None``. 
+is used. To disable filtering entirely, specify ``filter_kernel=None``.
 
 What array should be used for ``filter_kernel``? It should be
 approximately the shape of the objects you are trying to detect. For
@@ -40,7 +44,9 @@ each pixel. This is not available in Source Extractor. Some benefits
 of this method are that detector sensitivity can be taken into account
 and edge effects are handled gracefully. For example, suppose we have
 an image with noise that is higher in one region than another. This
-can often occur when coadding images::
+can often occur when coadding images:
+
+.. code-block:: python
 
     # create a small image with higher noise in the upper left
     n = 16
@@ -81,10 +87,10 @@ the object:
 Derivation of the matched filter formula
 ----------------------------------------
 
-Assume that we have an image containing a single point source. This produces a
-signal with PSF :math:`S_i` and noise :math:`N_i` at each pixel indexed by
-:math:`i`. Then the measured image data :math:`D_i` (i.e. our pixel values) is
-given by:
+Assume that we have an image containing a single point source. This
+produces a signal with PSF :math:`S_i` and noise :math:`N_i` at each pixel
+indexed by :math:`i`. Then the measured image data :math:`D_i` (i.e. our
+pixel values) is given by:
 
 .. math::
     D_i = S_i + N_i
@@ -95,9 +101,9 @@ output :math:`Y`:
 .. math::
     Y = \sum_i T_i D_i = T^T D
 
-We use matrix notation from here on and drop the explicit sums. Our objective
-is to find the transformation :math:`T_i` which maximizes the signal-to-noise
-ratio :math:`SNR`.
+We use matrix notation from here on and drop the explicit sums. Our
+objective is to find the transformation :math:`T_i` which maximizes the
+signal-to-noise ratio :math:`SNR`.
 
 .. math::
     SNR^2 = \frac{(T^T S)^2}{E[(T^T N)^2]}
@@ -105,14 +111,16 @@ ratio :math:`SNR`.
 We can expand the denominator as:
 
 .. math::
-    E[(T^T N)^2] = E[(T^T N)(N^T T)] = T^T \cdot E[N N^T] \cdot T = T^T C T
+    E[(T^T N)^2] = E[(T^T N)(N^T T)] = T^T \cdot E[N N^T] \cdot T
+    = T^T C T
 
-Where :math:`C_{ik}` is the covariance of the noise between pixels :math:`i`
-and :math:`k`. Now using the Cauchy-Schwarz inequality on the numerator:
+Where :math:`C_{ik}` is the covariance of the noise between pixels
+:math:`i` and :math:`k`. Now using the Cauchy-Schwarz inequality on the
+numerator:
 
 .. math::
-    (T^T S)^2 = (T^T C^{1/2} C^{-1/2} S)^2 \le (T^T C^{1/2})^2 (C^{-1/2} S)^2 =
-    (T^T C T) (S^T C^{-1} S)
+    (T^T S)^2 = (T^T C^{1/2} C^{-1/2} S)^2 \le (T^T C^{1/2})^2
+    (C^{-1/2} S)^2 = (T^T C T) (S^T C^{-1} S)
 
 since :math:`C^T = C`. The signal-to-noise ratio is therefore bounded by:
 
@@ -121,15 +129,16 @@ since :math:`C^T = C`. The signal-to-noise ratio is therefore bounded by:
     &SNR^2 \le S^T C^{-1} S
 
 Choosing :math:`T = \alpha C^{-1} S` where :math:`\alpha` is an arbitrary
-normalization constant, we get equality. Hence this choise of :math:`T` is the
-optimal linear tranformation. We normalize this linear transformation so that
-if there is no signal and only noise, we get an expected signal-to-noise ratio
-of 1. With this definition, the output :math:`SNR` represents the number of
-standard deviations above the background. This gives:
+normalization constant, we get equality. Hence this choise of :math:`T` is
+the optimal linear tranformation. We normalize this linear transformation
+so that if there is no signal and only noise, we get an expected
+signal-to-noise ratio of 1. With this definition, the output :math:`SNR`
+represents the number of standard deviations above the background. This
+gives:
 
 .. math::
-    &E[(T^T N)^2] = T^T C T = \alpha^2 S^T C^{-1} C C^{-1} S = \alpha^2 S^T
-    C^{-1} S = 1 \\ 
+    &E[(T^T N)^2] = T^T C T = \alpha^2 S^T C^{-1} C C^{-1} S = \alpha^2
+    S^T C^{-1} S = 1 \\
     &\alpha = \frac{1}{\sqrt{S^T C^{-1} S}}
 
 Putting everything together, our normalized linear transformation is:
@@ -137,7 +146,8 @@ Putting everything together, our normalized linear transformation is:
 .. math::
     T = \frac{C^{-1} S}{\sqrt{S^T C^{-1} S}}
 
-And the optimal signal-to-noise is given in terms of the known variables as:
+And the optimal signal-to-noise is given in terms of the known variables
+as:
 
 .. math::
     SNR = \frac{S^T C^{-1} D}{\sqrt{S^T C^{-1} S}}
diff --git a/docs/index.rst b/docs/index.rst
index 7c8f2a2..2dd8cb3 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -43,12 +43,30 @@ instructions.
 
 - Optimized matched filter for variable noise in source extraction.
 - Circular annulus and elliptical annulus aperture photometry functions.
-- Local background subtraction in shape consistent with aperture in aperture
-  photometry functions.
+- Local background subtraction in shape consistent with aperture in
+  aperture photometry functions.
 - Exact pixel overlap mode in all aperture photometry functions.
 - Masking of elliptical regions on images.
 
 
+SEP, SEP-PJW, and Package Names
+...............................
+
+``sep`` was originally released by Kyle Barbary, at
+`kbarbary/sep <https://github.com/kbarbary/sep>`_ (``sep<=1.2.1``). For a
+brief period, the package was maintained by Peter Watson, under the
+``sep-pjw`` package name, at
+`PJ-Watson/sep-pjw <https://github.com/PJ-Watson/sep-pjw>`_ and
+`PyPI/sep-pjw <https://pypi.org/project/sep-pjw/>`_
+(``1.3.0<=sep-pjw<=1.3.8``). Both of these repositories will be archived,
+and future development will take place at
+`sep-developers/sep <https://github.com/sep-developers/sep>`_
+(``sep>=1.4.0``).
+Note that there may be some incompatibilities between ``sep==1.2.1`` and
+``sep==1.4.0`` when using the C-API directly -- the changes are documented
+:doc:`here <changelogs/changes_to_c_api>`.
+
+
 Installation
 ------------
 
@@ -63,20 +81,20 @@ SEP can be installed with conda from the ``conda-forge`` channel::
 with pip
 ........
 
-SEP can also be installed with `pip <https://pip.pypa.io>`_. After ensuring
-that numpy is installed, run ::
+SEP can also be installed with `pip <https://pip.pypa.io>`_. After
+ensuring that numpy is installed, run ::
 
-    pip install sep
+    python -m pip install sep
 
 If you get an error about permissions, you are probably using your
 system Python. In this case, I recommend using `pip's "user install"
 <https://pip.pypa.io/en/latest/user_guide/#user-installs>`_ option to
 install sep into your user directory ::
 
-    pip install --user sep
+    python -m pip install --user sep
 
-Do **not** install sep or other third-party Python packages using ``sudo``
-unless you are fully aware of the risks.
+Do **not** install ``sep`` or other third-party Python packages using
+``sudo`` unless you are fully aware of the risks.
 
 
 Usage Guide
@@ -88,6 +106,7 @@ Usage Guide
    tutorial
    filter
    apertures
+   changelogs/changelog
 
 .. toctree::
    :hidden:
@@ -100,10 +119,11 @@ For complete API documentation, see :doc:`reference`.
 Contributing
 ------------
 
-Report a bug or documentation issue: http://github.com/kbarbary/sep/issues
+Report a bug or documentation issue:
+http://github.com/sep-developers/sep/issues
 
-Development of SEP takes place on GitHub at
-http://github.com/kbarbary/sep.  Contributions of bug fixes,
+Development of ``sep`` takes place on GitHub at
+http://github.com/sep-developers/sep.  Contributions of bug fixes,
 documentation improvements and minor feature additions are welcome via
 GitHub pull requests. For major features, it is best to open an issue
 discussing the change first.
diff --git a/docs/reference.rst b/docs/reference.rst
index 39f9f9d..07a114b 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -6,7 +6,7 @@ Reference/API
 
 .. autosummary::
    :toctree: api
-   
+
    sep.Background
    sep.extract
 
@@ -14,7 +14,7 @@ Reference/API
 
 .. autosummary::
    :toctree: api
-   
+
    sep.sum_circle
    sep.sum_circann
    sep.sum_ellipse
diff --git a/docs/rtd-pip-requirements b/docs/rtd-pip-requirements
index a21210b..66ede4f 100644
--- a/docs/rtd-pip-requirements
+++ b/docs/rtd-pip-requirements
@@ -4,4 +4,5 @@ nbsphinx
 matplotlib
 fitsio
 numpydoc
-jupyter
\ No newline at end of file
+jupyter
+sphinx-astropy[confv2]
diff --git a/docs/tutorial.ipynb b/docs/tutorial.ipynb
index fcf239f..9f8f7a7 100644
--- a/docs/tutorial.ipynb
+++ b/docs/tutorial.ipynb
@@ -351,23 +351,42 @@
     "```\n",
     "ValueError: Input array with dtype '>f4' has non-native byte order.\n",
     "Only native byte order arrays are supported. To change the byte\n",
-    "order of the array 'data', do 'data = data.byteswap().newbyteorder()'\n",
+    "order of the array 'data', do 'data = data.astype(data.dtype.newbyteorder(\"=\"))'\n",
     "```\n",
     "\n",
     "It is usually easiest to do this byte-swap operation directly after\n",
-    "reading the array from the FITS file. You can even perform the byte\n",
-    "swap in-place by doing\n",
+    "reading the array from the FITS file. The exact procedure is slightly different,\n",
+    "depending on the version of ``numpy``. For ``numpy<2.0``, the operation was:\n",
     "\n",
     "```python\n",
-    ">>> data = data.byteswap(inplace=True).newbyteorder()\n",
+    "# Byte order changed in-place\n",
+    ">>> data = data.byteswap(inplace=True).newbyteorder() \n",
+    "# Data copied to a new array\n",
+    ">>> new_data = data.byteswap().newbyteorder()\n",
+    "```\n",
+    "\n",
+    "For ``numpy>=2.0``, the correct operation is one of the following:\n",
+    "\n",
+    "```python\n",
+    "# Copies data to a new array, preserves the ordering of the original array\n",
+    ">>> new_data = data.astype(data.dtype.newbyteorder(\"=\")) \n",
+    "# The same outcome as the previous operation\n",
+    ">>> new_data = data.byteswap()\n",
+    ">>> new_data = new_data.view(new_data.dtype.newbyteorder(\"=\"))\n",
+    "# Changes data in-place\n",
+    ">>> data = data.byteswap()\n",
+    ">>> data = data.view(data.dtype.newbyteorder(\"=\"))\n",
     "```\n",
     "\n",
     "If you do this in-place operation, ensure that there are no other\n",
     "references to ``data``, as they will be rendered nonsensical.\n",
     "\n",
     "For the interested reader, this byteswap operation is necessary because\n",
-    "astropy.io.fits always returns big-endian byte order arrays, even on\n",
-    "little-endian machines. For more on this, see\n",
+    "``astropy.io.fits`` always returns big-endian byte order arrays, even on\n",
+    "little-endian machines. This is due to the FITS standard requiring\n",
+    "big-endian arrays (see the \n",
+    "[FITS Standard](https://fits.gsfc.nasa.gov/fits_standard.html)), and \n",
+    "``astropy.io.fits`` aiming for backwards compatibility.\n",
     "</div>"
    ]
   }
diff --git a/pyproject.toml b/pyproject.toml
index b0af0b5..8bf48b8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,93 @@
 [build-system]
-requires = ["setuptools", "wheel", "oldest-supported-numpy", "Cython"]
+requires = [
+    "setuptools>=61.0",
+    "wheel",
+    "numpy>=2.0.0rc2",
+    "Cython",
+    "setuptools_scm>=8.0",
+]
 build-backend = "setuptools.build_meta"
+
+[project]
+name = "sep"
+dynamic = ["version"]
+authors = [
+  { name="Emmanuel Bertin"},
+  { name="Kyle Barbary"},
+  { name="Kyle Boone"},
+  { name="Thomas Robitaille"},
+  { name="Matt Craig"},
+  { name="Curtis McCully"},
+  { name="Evert Rol"},
+  { name="Joe Lyman"},
+  { name="Michael Wuertenberger"},
+  { name="Ingvar Stepanyan"},
+  { name="Gabe Brammer"},
+  { name="Peter Watson"},
+]
+maintainers = [
+  { name="Peter Watson", email="peter.watson+sep@inaf.it" },
+]
+description="Astronomical source extraction and photometry library"
+readme = "README.md"
+license = { text =  "LGPLv3+" }
+classifiers=[
+    "Development Status :: 5 - Production/Stable",
+    "Programming Language :: Python :: 3",
+    "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
+    "Topic :: Scientific/Engineering :: Astronomy",
+    "Intended Audience :: Science/Research",
+]
+requires-python = ">=3.9"
+dependencies = [
+    "numpy>=1.23.5"
+]
+
+[project.optional-dependencies]
+docs = [
+    "sphinx-copybutton>=0.5",
+    "sphinx>=7.2",
+    "numpydoc>=1.6",
+    "matplotlib>=3.6",
+    "sphinx-astropy[confv2]>=1.9.1",
+    "nbsphinx>=0.9.3",
+    "pandoc>=2.3",
+    "fitsio>=1.2.1",
+    "jupyter",
+    "myst-parser>=2.0.0",
+]
+
+[project.urls]
+"Homepage" = "https://github.com/sep-developers/sep"
+"Bug Tracker" = "https://github.com/sep-developers/sep/issues"
+"Documentation" = "http://sep-pjw.readthedocs.org"
+
+[tool.setuptools_scm]
+version_file = "src/_version.py"
+
+[tool.black]
+line-length = 88
+target-version = ['py312']
+extend-exclude = '(.*.txt|.*.md|.*.toml|.*.odg)'
+preview = true
+
+[tool.isort]
+profile = "black"
+
+[tool.numpydoc_validation]
+checks = [
+    "all",   # report on all checks, except the below
+    "EX01",
+    "SA01",
+    "ES01",
+]
+exclude = [  # don't report on objects that match any of these regex
+    '\.undocumented_method$',
+    '\.__repr__$',
+    '\._.*$',  # Ignore anything that's private (e.g., starts with _)
+]
+override_SS05 = [  # override SS05 to allow docstrings starting with these words
+    '^Process ',
+    '^Assess ',
+    '^Access ',
+]
diff --git a/sep.pyx b/sep.pyx
index ca1795b..3be1a6d 100644
--- a/sep.pyx
+++ b/sep.pyx
@@ -6,16 +6,17 @@ Source Extraction and Photometry
 This module is a wrapper of the SEP C library.
 """
 import numpy as np
+
+cimport cython
 cimport numpy as np
+from cpython.mem cimport PyMem_Free, PyMem_Malloc
+from cpython.version cimport PY_MAJOR_VERSION
 from libc cimport limits
 from libc.math cimport sqrt
-cimport cython
-from cpython.mem cimport PyMem_Malloc, PyMem_Free
-from cpython.version cimport PY_MAJOR_VERSION
 
 np.import_array()  # To access the numpy C-API.
 
-__version__ = "1.2.1"
+from _version import version as __version__
 
 # -----------------------------------------------------------------------------
 # Definitions from the SEP C library
@@ -69,28 +70,31 @@ cdef extern from "sep.h":
         int ndtype
         int mdtype
         int sdtype
-        int w
-        int h
+        np.int64_t *segids
+        np.int64_t *idcounts
+        np.int64_t numids
+        np.int64_t w
+        np.int64_t h
         double noiseval
         short noise_type
         double gain
         double maskthresh
 
     ctypedef struct sep_bkg:
-        int w
-        int h
+        np.int64_t w
+        np.int64_t h
         float globalback
         float globalrms
 
     ctypedef struct sep_catalog:
-        int    nobj
-        float  *thresh
-        int    *npix
-        int    *tnpix
-        int    *xmin
-        int    *xmax
-        int    *ymin
-        int    *ymax
+        np.int64_t  nobj
+        float       *thresh
+        np.int64_t  *npix
+        np.int64_t  *tnpix
+        np.int64_t  *xmin
+        np.int64_t  *xmax
+        np.int64_t  *ymin
+        np.int64_t  *ymax
         double *x
         double *y
         double *x2
@@ -109,17 +113,17 @@ cdef extern from "sep.h":
         float  *flux
         float  *cpeak
         float  *peak
-        int    *xcpeak
-        int    *ycpeak
-        int    *xpeak
-        int    *ypeak
-        short  *flag
-        int    **pix
-        int    *objectspix
+        np.int64_t  *xcpeak
+        np.int64_t  *ycpeak
+        np.int64_t  *xpeak
+        np.int64_t  *ypeak
+        short       *flag
+        np.int64_t  **pix
+        np.int64_t  *objectspix
 
     int sep_background(const sep_image *im,
-                       int bw, int bh,
-                       int fw, int fh,
+                       np.int64_t bw, np.int64_t bh,
+                       np.int64_t fw, np.int64_t fh,
                        double fthresh,
                        sep_bkg **bkg)
 
@@ -135,7 +139,7 @@ cdef extern from "sep.h":
                     int thresh_type,
                     int minarea,
                     float *conv,
-                    int convw, int convh,
+                    np.int64_t convw, np.int64_t convh,
                     int filter_type,
                     int deblend_nthresh,
                     double deblend_cont,
@@ -190,7 +194,7 @@ cdef extern from "sep.h":
     void sep_ellipse_coeffs(double a, double b, double theta,
                             double *cxx, double *cyy, double *cxy)
 
-    void sep_set_ellipse(unsigned char *arr, int w, int h,
+    void sep_set_ellipse(unsigned char *arr, np.int64_t w, np.int64_t h,
                          double x, double y,
                          double cxx, double cyy, double cxy, double r,
                          unsigned char val)
@@ -227,7 +231,7 @@ cdef int _get_sep_dtype(dtype) except -1:
     raise ValueError('input array dtype not supported: {0}'.format(dtype))
 
 
-cdef int _check_array_get_dims(np.ndarray arr, int *w, int *h) except -1:
+cdef int _check_array_get_dims(np.ndarray arr, np.int64_t *w, np.int64_t *h) except -1:
     """Check some things about an array and return dimensions"""
 
     # Raise an informative message if array is not C-contiguous
@@ -294,13 +298,14 @@ cdef int _parse_arrays(np.ndarray data, err, var, mask, segmap,
     """Helper function for functions accepting data, error, mask & segmap arrays.
     Fills in an sep_image struct."""
 
-    cdef int ew, eh, mw, mh, sw, sh
+    cdef np.int64_t ew, eh, mw, mh, sw, sh
     cdef np.uint8_t[:,:] buf, ebuf, mbuf, sbuf
 
     # Clear im fields we might not touch (everything besides data, dtype, w, h)
     im.noise = NULL
     im.mask = NULL
     im.segmap = NULL
+    im.numids = 0
     im.ndtype = 0
     im.mdtype = 0
     im.noiseval = 0.0
@@ -438,7 +443,7 @@ cdef class Background:
         def __get__(self):
             return sep_bkg_globalrms(self.ptr)
 
-    def back(self, dtype=None):
+    def back(self, dtype=None, copy=None):
         """back(dtype=None)
 
         Create an array of the background.
@@ -468,7 +473,10 @@ cdef class Background:
         status = sep_bkg_array(self.ptr, &buf[0, 0], sep_dtype)
         _assert_ok(status)
 
-        return result
+        if copy:
+            return result.copy()
+        else:
+            return result
 
     def rms(self, dtype=None):
         """rms(dtype=None)
@@ -517,7 +525,8 @@ cdef class Background:
             that of the original image used to measure the background.
         """
 
-        cdef int w, h, status, sep_dtype
+        cdef np.int64_t w, h
+        cdef int status, sep_dtype
         cdef np.uint8_t[:, :] buf
 
         assert self.ptr is not NULL
@@ -534,8 +543,8 @@ cdef class Background:
         status = sep_bkg_subarray(self.ptr, &buf[0, 0], sep_dtype)
         _assert_ok(status)
 
-    def __array__(self, dtype=None):
-        return self.back(dtype=dtype)
+    def __array__(self, dtype=None, copy=None):
+        return self.back(dtype=dtype, copy=copy)
 
     def __rsub__(self, np.ndarray data not None):
         data = np.copy(data)
@@ -552,12 +561,12 @@ cdef class Background:
 # This needs to match the result from extract
 cdef packed struct Object:
     np.float64_t thresh
-    np.int_t npix
-    np.int_t tnpix
-    np.int_t xmin
-    np.int_t xmax
-    np.int_t ymin
-    np.int_t ymax
+    np.int64_t npix
+    np.int64_t tnpix
+    np.int64_t xmin
+    np.int64_t xmax
+    np.int64_t ymin
+    np.int64_t ymax
     np.float64_t x
     np.float64_t y
     np.float64_t x2
@@ -576,23 +585,25 @@ cdef packed struct Object:
     np.float64_t errx2
     np.float64_t erry2
     np.float64_t errxy
-    np.int_t xcpeak
-    np.int_t ycpeak
-    np.int_t xpeak
-    np.int_t ypeak
-    np.int_t flag
+    np.int64_t xcpeak
+    np.int64_t ycpeak
+    np.int64_t xpeak
+    np.int64_t ypeak
+    short flag
 
 default_kernel = np.array([[1.0, 2.0, 1.0],
                            [2.0, 4.0, 2.0],
                            [1.0, 2.0, 1.0]], dtype=np.float32)
 
+@cython.boundscheck(False)
+@cython.wraparound(False)
 def extract(np.ndarray data not None, float thresh, err=None, var=None,
             gain=None, np.ndarray mask=None, double maskthresh=0.0,
             int minarea=5,
             np.ndarray filter_kernel=default_kernel, filter_type='matched',
             int deblend_nthresh=32, double deblend_cont=0.005,
             bint clean=True, double clean_param=1.0,
-            segmentation_map=False):
+            segmentation_map=None):
     """extract(data, thresh, err=None, mask=None, minarea=5,
                filter_kernel=default_kernel, filter_type='matched',
                deblend_nthresh=32, deblend_cont=0.005, clean=True,
@@ -650,10 +661,16 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
         Perform cleaning? Default is True.
     clean_param : float, optional
         Cleaning parameter (see SExtractor manual). Default is 1.0.
-    segmentation_map : bool, optional
-        If True, also return a "segmentation map" giving the member
+    segmentation_map : `~numpy.ndarray` or bool, optional
+        If ``True``, also return a "segmentation map" giving the member
         pixels of each object. Default is False.
 
+        *New in v1.3.0*:
+        An existing segmentation map can also be supplied in
+        the form of an `~numpy.ndarray`. If this is the case, then the
+        object detection stage is skipped, and the objects in the
+        segmentation map are analysed and extracted.
+
     Returns
     -------
     objects : `~numpy.ndarray`
@@ -684,7 +701,7 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
         Array of integers with same shape as data. Pixels not belonging to
         any object have value 0. All pixels belonging to the ``i``-th object
         (e.g., ``objects[i]``) have value ``i+1``. Only returned if
-        ``segmentation_map=True``.
+        ``segmentation_map = True | ~numpy.ndarray``.
     """
 
     cdef int kernelw, kernelh, status, i, j
@@ -695,11 +712,37 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
     cdef float *kernelptr
     cdef np.int32_t[:, :] segmap_buf
     cdef np.int32_t *segmap_ptr
-    cdef int *objpix
+    cdef np.int64_t *objpix
     cdef sep_image im
+    cdef np.int64_t[:] idbuf, countbuf
 
     # parse arrays
-    _parse_arrays(data, err, var, mask, None, &im)
+    if type(segmentation_map) is np.ndarray:
+        _parse_arrays(data, err, var, mask, segmentation_map, &im)
+
+        ids, counts = np.unique(segmentation_map, return_counts=True)
+
+        # Remove non-object IDs:
+        filter_ids = ids>0
+        segids = np.ascontiguousarray(ids[filter_ids].astype(dtype=np.int64))
+        idcounts = np.ascontiguousarray(counts[filter_ids].astype(dtype=np.int64))
+        if np.nansum(idcounts)>get_extract_pixstack():
+            raise ValueError(
+                f"The number of object pixels ({np.nansum(idcounts)}) in "
+                "the segmentation map exceeds the allocated pixel stack "
+                f"({get_extract_pixstack()}). Use "
+                "`sep.set_extract_pixstack()` to increase the size, "
+                "or check that the correct segmentation map has been "
+                "supplied."
+            )
+
+        idbuf = segids.view(dtype=np.int64)
+        countbuf = idcounts.view(dtype=np.int64)
+        im.segids = <np.int64_t*>&idbuf[0]
+        im.idcounts = <np.int64_t*>&countbuf[0]
+        im.numids = len(segids)
+    else:
+        _parse_arrays(data, err, var, mask, None, &im)
     im.maskthresh = maskthresh
     if gain is not None:
         im.gain = gain
@@ -739,12 +782,12 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
     # Allocate result record array and fill it
     result = np.empty(catalog.nobj,
                       dtype=np.dtype([('thresh', np.float64),
-                                      ('npix', np.int_),
-                                      ('tnpix', np.int_),
-                                      ('xmin', np.int_),
-                                      ('xmax', np.int_),
-                                      ('ymin', np.int_),
-                                      ('ymax', np.int_),
+                                      ('npix', np.int64),
+                                      ('tnpix', np.int64),
+                                      ('xmin', np.int64),
+                                      ('xmax', np.int64),
+                                      ('ymin', np.int64),
+                                      ('ymax', np.int64),
                                       ('x', np.float64),
                                       ('y', np.float64),
                                       ('x2', np.float64),
@@ -763,11 +806,11 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
                                       ('flux', np.float64),
                                       ('cpeak', np.float64),
                                       ('peak', np.float64),
-                                      ('xcpeak', np.int_),
-                                      ('ycpeak', np.int_),
-                                      ('xpeak', np.int_),
-                                      ('ypeak', np.int_),
-                                      ('flag', np.int_)]))
+                                      ('xcpeak', np.int64),
+                                      ('ycpeak', np.int64),
+                                      ('xpeak', np.int64),
+                                      ('ypeak', np.int64),
+                                      ('flag', np.short)]))
 
     for i in range(catalog.nobj):
         result['thresh'][i] = catalog.thresh[i]
@@ -802,7 +845,7 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
         result['flag'][i] = catalog.flag[i]
 
     # construct a segmentation map, if it was requested.
-    if segmentation_map:
+    if type(segmentation_map) is np.ndarray or segmentation_map:
         # Note: We have to write out `(data.shape[0], data.shape[1])` because
         # because Cython turns `data.shape` later into an int pointer when
         # the function argument is typed as np.ndarray.
@@ -817,7 +860,7 @@ def extract(np.ndarray data not None, float thresh, err=None, var=None,
     # Free the C catalog
     sep_catalog_free(catalog)
 
-    if segmentation_map:
+    if type(segmentation_map) is np.ndarray or segmentation_map:
         return result, segmap
     else:
         return result
@@ -874,7 +917,7 @@ def sum_circle(np.ndarray data not None, x, y, r,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     bkgann : tuple, optional
         Length 2 tuple giving the inner and outer radius of a
@@ -1071,7 +1114,7 @@ def sum_circann(np.ndarray data not None, x, y, rin, rout,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     gain : float, optional
         Conversion factor between data array units and poisson counts,
@@ -1216,7 +1259,7 @@ def sum_ellipse(np.ndarray data not None, x, y, a, b, theta, r=1.0,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     bkgann : tuple, optional
         Length 2 tuple giving the inner and outer radius of a
@@ -1430,7 +1473,7 @@ def sum_ellipann(np.ndarray data not None, x, y, a, b, theta, rin, rout,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     subpix : int, optional
         Subpixel sampling factor. Default is 5.
@@ -1569,7 +1612,7 @@ def flux_radius(np.ndarray data not None, x, y, rmax, frac, normflux=None,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     subpix : int, optional
         Subpixel sampling factor. Default is 5.
@@ -1705,7 +1748,7 @@ def mask_ellipse(np.ndarray arr not None, x, y, a=None, b=None, theta=None,
         Scale factor of ellipse(s). Default is 1.
     """
 
-    cdef int w, h
+    cdef np.int64_t w, h
     cdef np.uint8_t[:,:] buf
     cdef double cxx_, cyy_, cxy_
 
@@ -1824,7 +1867,7 @@ def kron_radius(np.ndarray data not None, x, y, a, b, theta, r,
         and seg[j, i] != 0``). If ``seg_id`` is negative, all pixels other
         than those belonging to the object of interest are masked. (Pixel ``j,
         i`` is masked if ``seg[j, i] != -seg_id``).  NB: must be included if
-        ``segmap` is provided.
+        ``segmap`` is provided.
 
     Returns
     -------
diff --git a/setup.py b/setup.py
index 2a61ebd..2da55fa 100755
--- a/setup.py
+++ b/setup.py
@@ -1,25 +1,40 @@
-#!/usr/bin/env python
+"""Setup file to build the C library."""
 
 import os
 import re
 import sys
 from glob import glob
 
-from setuptools import setup
-from setuptools.dist import Distribution
-from setuptools.extension import Extension
+from setuptools import Extension, setup
+from setuptools_scm import ScmVersion, get_version
+from setuptools_scm.version import guess_next_version
+
+
+def _new_version_scheme(version: ScmVersion) -> str:
+
+    return version.format_next_version(guess_next_version, "{guessed}-dev{distance}")
+
+
+def _new_local_scheme(version: ScmVersion) -> str:
+
+    return version.format_choice("", "-{node}")
+
 
-# Synchronize version from code.
-fname = "sep.pyx"
-version = re.findall(r"__version__ = \"(.*?)\"", open(fname).read())[0]
+c_version_string = get_version(
+    version_scheme=_new_version_scheme,
+    local_scheme=_new_local_scheme,
+)
+
+# from setuptools import setup
+from setuptools.dist import Distribution
 
 # Detect if setup.py is being run with an argument that doesn't require
 # building anything. (egg info, help commands, etc)
-options = Distribution.display_option_names + ['help-commands', 'help']
+options = Distribution.display_option_names + ["help-commands", "help"]
 is_non_build = (
-    any('--' + opt in sys.argv for opt in options)
+    any("--" + opt in sys.argv for opt in options)
     or len(sys.argv) == 1
-    or sys.argv[1] in ('egg_info', 'clean', 'help')
+    or sys.argv[1] in ("egg_info", "clean", "help")
 )
 
 # extension module(s): only add if we actually need to build, because we need
@@ -30,35 +45,26 @@
 else:
     import numpy
     from Cython.Build import cythonize
-    sourcefiles = [fname] + glob(os.path.join("src", "*.c"))
+
+    sourcefiles = ["sep.pyx"] + glob(os.path.join("src", "*.c"))
     headerfiles = glob(os.path.join("src", "*.h"))
     include_dirs = [numpy.get_include(), "src"]
-    extensions = [Extension("sep", sourcefiles, include_dirs=include_dirs,
-                            depends=headerfiles, define_macros=[("_USE_MATH_DEFINES", "1")])]
-    extensions = cythonize(extensions)
-
-
-
-description = "Astronomical source extraction and photometry library"
-long_description = "http://sep.readthedocs.org"
-
-classifiers = [
-    "Development Status :: 5 - Production/Stable",
-    "Programming Language :: Python :: 3",
-    "License :: OSI Approved :: GNU Lesser General Public License v3 "
-    "or later (LGPLv3+)",
-    "Topic :: Scientific/Engineering :: Astronomy",
-    "Intended Audience :: Science/Research"]
+    extensions = [
+        Extension(
+            "sep",
+            sourcefiles,
+            include_dirs=include_dirs,
+            depends=headerfiles,
+            define_macros=[
+                ("_USE_MATH_DEFINES", "1"),
+                ("NPY_NO_DEPRECATED_API", "NPY_2_0_API_VERSION"),
+            ],
+            extra_compile_args=['-DSEP_VERSION_STRING="' + c_version_string + '"'],
+        )
+    ]
+    extensions = cythonize(
+        extensions,
+        language_level=3,
+    )
 
-setup(name="sep",
-      version=version,
-      description=description,
-      long_description=long_description,
-      license="LGPLv3+",
-      classifiers=classifiers,
-      url="https://github.com/kbarbary/sep",
-      author="Kyle Barbary",
-      author_email="kylebarbary@gmail.com",
-      python_requires='>=3.5',
-      install_requires=['numpy'],
-      ext_modules=extensions)
+setup(ext_modules=extensions)
diff --git a/src/analyse.c b/src/analyse.c
index 9dca687..5b5371e 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -1,32 +1,34 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include <math.h>
-#include <stdlib.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+
+#include "extract.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "extract.h"
 
 /********************************** cleanprep ********************************/
 /*
@@ -34,122 +36,117 @@
  * This used to be in analyse() / examineiso().
  */
 
-int analysemthresh(int objnb, objliststruct *objlist, int minarea,
-		   PIXTYPE thresh)
-{
-  objstruct *obj = objlist->obj+objnb;
-  pliststruct *pixel = objlist->plist;
-  pliststruct *pixt;
+int analysemthresh(int objnb, objliststruct * objlist, int minarea, PIXTYPE thresh) {
+  objstruct * obj = objlist->obj + objnb;
+  pliststruct * pixel = objlist->plist;
+  pliststruct * pixt;
   PIXTYPE tpix;
-  float     *heap,*heapt,*heapj,*heapk, swap;
-  int       j, k, h, status;
+  float *heap, *heapt, *heapj, *heapk, swap;
+  int j, k, h, status;
 
   status = RETURN_OK;
   heap = heapt = heapj = heapk = NULL;
   h = minarea;
 
-  if (obj->fdnpix < minarea)
-    {
-      obj->mthresh = 0.0;
-      return status;
-    }
+  if (obj->fdnpix < minarea) {
+    obj->mthresh = 0.0;
+    return status;
+  }
 
   QCALLOC(heap, float, minarea, status);
   heapt = heap;
 
   /*-- Find the minareath pixel in decreasing intensity for CLEANing */
-  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
-    {
-      /* amount pixel is above threshold */
-      tpix = PLISTPIX(pixt, cdvalue) - (PLISTEXIST(thresh)?
-					PLISTPIX(pixt, thresh):thresh);
-      if (h>0)
-        *(heapt++) = (float)tpix;
-      else if (h)
-        {
-	  if ((float)tpix>*heap)
-	    {
-	      *heap = (float)tpix;
-	      for (j=0; (k=(j+1)<<1)<=minarea; j=k)
-		{
-		  heapk = heap+k;
-		  heapj = heap+j;
-		  if (k != minarea && *(heapk-1) > *heapk)
-		    {
-		      heapk++;
-		      k++;
-		    }
-		  if (*heapj <= *(--heapk))
-		    break;
-		  swap = *heapk;
-		  *heapk = *heapj;
-		  *heapj = swap;
-		}
-	    }
+  for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix))
+  {
+    /* amount pixel is above threshold */
+    tpix = PLISTPIX(pixt, cdvalue)
+           - (PLISTEXIST(thresh) ? PLISTPIX(pixt, thresh) : thresh);
+    if (h > 0) {
+      *(heapt++) = (float)tpix;
+    } else if (h) {
+      if ((float)tpix > *heap) {
+        *heap = (float)tpix;
+        for (j = 0; (k = (j + 1) << 1) <= minarea; j = k) {
+          heapk = heap + k;
+          heapj = heap + j;
+          if (k != minarea && *(heapk - 1) > *heapk) {
+            heapk++;
+            k++;
+          }
+          if (*heapj <= *(--heapk)) {
+            break;
+          }
+          swap = *heapk;
+          *heapk = *heapj;
+          *heapj = swap;
         }
-      else
-        fqmedian(heap, minarea);
-      h--;
+      }
+    } else {
+      fqmedian(heap, minarea);
     }
+    h--;
+  }
 
   obj->mthresh = *heap;
 
- exit:
+exit:
   free(heap);
   return status;
 }
 
 /************************* preanalyse **************************************/
 
-void  preanalyse(int no, objliststruct *objlist)
-{
-  objstruct	*obj = &objlist->obj[no];
-  pliststruct	*pixel = objlist->plist, *pixt;
-  PIXTYPE	peak, cpeak, val, cval;
-  double	rv;
-  int		x, y, xmin,xmax, ymin,ymax, fdnpix;
-  int           xpeak, ypeak, xcpeak, ycpeak;
+void preanalyse(int no, objliststruct * objlist) {
+  objstruct * obj = &objlist->obj[no];
+  pliststruct *pixel = objlist->plist, *pixt;
+  PIXTYPE peak, cpeak, val, cval;
+  double rv;
+  int64_t x, y, xmin, xmax, ymin, ymax, fdnpix;
+  int64_t xpeak, ypeak, xcpeak, ycpeak;
 
   /*-----  initialize stacks and bounds */
   fdnpix = 0;
   rv = 0.0;
   peak = cpeak = -BIG;
-  ymin = xmin = 2*MAXPICSIZE;    /* to be really sure!! */
+  ymin = xmin = 2 * MAXPICSIZE; /* to be really sure!! */
   ymax = xmax = 0;
   xpeak = ypeak = xcpeak = ycpeak = 0; /* avoid -Wall warnings */
 
   /*-----  integrate results */
-  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
-    {
-      x = PLIST(pixt, x);
-      y = PLIST(pixt, y);
-      val = PLISTPIX(pixt, value);
-      cval = PLISTPIX(pixt, cdvalue);
-      if (peak < val)
-	{
-	  peak = val;
-	  xpeak = x;
-	  ypeak = y;
-	}
-      if (cpeak < cval)
-	{
-	  cpeak = cval;
-	  xcpeak = x;
-	  ycpeak = y;
-	}
-      rv += cval;
-      if (xmin > x)
-	xmin = x;
-      if (xmax < x)
-	xmax = x;
-      if (ymin > y)
-	ymin = y;
-      if (ymax < y)
-	ymax = y;
-      fdnpix++;
+  for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix))
+  {
+    x = PLIST(pixt, x);
+    y = PLIST(pixt, y);
+    val = PLISTPIX(pixt, value);
+    cval = PLISTPIX(pixt, cdvalue);
+    if (peak < val) {
+      peak = val;
+      xpeak = x;
+      ypeak = y;
+    }
+    if (cpeak < cval) {
+      cpeak = cval;
+      xcpeak = x;
+      ycpeak = y;
+    }
+    rv += cval;
+    if (xmin > x) {
+      xmin = x;
+    }
+    if (xmax < x) {
+      xmax = x;
+    }
+    if (ymin > y) {
+      ymin = y;
+    }
+    if (ymax < y) {
+      ymax = y;
     }
+    fdnpix++;
+  }
 
-  obj->fdnpix = (LONG)fdnpix;
+  obj->fdnpix = fdnpix;
   obj->fdflux = (float)rv;
   obj->fdpeak = cpeak;
   obj->dpeak = peak;
@@ -168,17 +165,13 @@ void  preanalyse(int no, objliststruct *objlist)
   If robust = 1, you must have run previously with robust=0
 */
 
-void  analyse(int no, objliststruct *objlist, int robust, double gain)
-{
-  objstruct	*obj = &objlist->obj[no];
-  pliststruct	*pixel = objlist->plist, *pixt;
-  PIXTYPE	peak, val, cval;
-  double	thresh,thresh2, t1t2,darea,
-                mx,my, mx2,my2,mxy, rv, rv2, tv,
-		xm,ym, xm2,ym2,xym,
-                temp,temp2, theta,pmx2,pmy2,
-                errx2, erry2, errxy, cvar, cvarsum;
-  int		x, y, xmin, ymin, area2, dnpix;
+void analyse(int no, objliststruct * objlist, int robust, double gain) {
+  objstruct * obj = &objlist->obj[no];
+  pliststruct *pixel = objlist->plist, *pixt;
+  PIXTYPE peak, val, cval;
+  double thresh, thresh2, t1t2, darea, mx, my, mx2, my2, mxy, rv, rv2, tv, xm, ym, xm2,
+      ym2, xym, temp, temp2, theta, pmx2, pmy2, errx2, erry2, errxy, cvar, cvarsum;
+  int64_t x, y, xmin, ymin, area2, dnpix;
 
   preanalyse(no, objlist);
 
@@ -190,109 +183,108 @@ void  analyse(int no, objliststruct *objlist, int robust, double gain)
   peak = obj->dpeak;
   rv = obj->fdflux;
   rv2 = rv * rv;
-  thresh2 = (thresh + peak)/2.0;
+  thresh2 = (thresh + peak) / 2.0;
   area2 = 0;
 
   xmin = obj->xmin;
   ymin = obj->ymin;
 
-  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
-    {
-      x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
-      y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */
-      cval = PLISTPIX(pixt, cdvalue);
-      tv += (val = PLISTPIX(pixt, value));
-      if (val>thresh)
-	dnpix++;
-      if (val > thresh2)
-	area2++;
-      mx += cval * x;
-      my += cval * y;
-      mx2 += cval * x*x;
-      my2 += cval * y*y;
-      mxy += cval * x*y;
-
+  for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix))
+  {
+    x = PLIST(pixt, x) - xmin; /* avoid roundoff errors on big images */
+    y = PLIST(pixt, y) - ymin; /* avoid roundoff errors on big images */
+    cval = PLISTPIX(pixt, cdvalue);
+    tv += (val = PLISTPIX(pixt, value));
+    if (val > thresh) {
+      dnpix++;
+    }
+    if (val > thresh2) {
+      area2++;
     }
+    mx += cval * x;
+    my += cval * y;
+    mx2 += cval * x * x;
+    my2 += cval * y * y;
+    mxy += cval * x * y;
+  }
 
   /* compute object's properties */
-  xm = mx / rv;    /* mean x */
-  ym = my / rv;    /* mean y */
+  xm = mx / rv; /* mean x */
+  ym = my / rv; /* mean y */
 
 
   /* In case of blending, use previous barycenters */
-  if ((robust) && (obj->flag & SEP_OBJ_MERGED))
-    {
-      double xn, yn;
-
-      xn = obj->mx-xmin;
-      yn = obj->my-ymin;
-      xm2 = mx2 / rv + xn*xn - 2*xm*xn;
-      ym2 = my2 / rv + yn*yn - 2*ym*yn;
-      xym = mxy / rv + xn*yn - xm*yn - xn*ym;
-      xm = xn;
-      ym = yn;
-    }
-  else
-    {
-      xm2 = mx2 / rv - xm * xm;	 /* variance of x */
-      ym2 = my2 / rv - ym * ym;	 /* variance of y */
-      xym = mxy / rv - xm * ym;	 /* covariance */
-
-    }
+  if ((robust) && (obj->flag & SEP_OBJ_MERGED)) {
+    double xn, yn;
+
+    xn = obj->mx - xmin;
+    yn = obj->my - ymin;
+    xm2 = mx2 / rv + xn * xn - 2 * xm * xn;
+    ym2 = my2 / rv + yn * yn - 2 * ym * yn;
+    xym = mxy / rv + xn * yn - xm * yn - xn * ym;
+    xm = xn;
+    ym = yn;
+  } else {
+    xm2 = mx2 / rv - xm * xm; /* variance of x */
+    ym2 = my2 / rv - ym * ym; /* variance of y */
+    xym = mxy / rv - xm * ym; /* covariance */
+  }
 
   /* Calculate the errors on the variances */
-  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
-    {
-      x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
-      y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */
-
-      cvar = PLISTEXIST(var)? PLISTPIX(pixt, var): 0.0;
-      if (gain > 0.0) {  /* add poisson noise if given */
-        cval = PLISTPIX(pixt, cdvalue);
-        if (cval > 0.0) cvar += cval / gain;
-      }
+  for (pixt = pixel + obj->firstpix; pixt >= pixel; pixt = pixel + PLIST(pixt, nextpix))
+  {
+    x = PLIST(pixt, x) - xmin; /* avoid roundoff errors on big images */
+    y = PLIST(pixt, y) - ymin; /* avoid roundoff errors on big images */
 
-      /* Note that this works for both blended and non-blended cases
-       * because xm is set to xn above for the blended case. */
-      cvarsum += cvar;
-      errx2 += cvar * (x - xm) * (x - xm);
-      erry2 += cvar * (y - ym) * (y - ym);
-      errxy += cvar * (x - xm) * (y - ym);
+    cvar = PLISTEXIST(var) ? PLISTPIX(pixt, var) : 0.0;
+    if (gain > 0.0) { /* add poisson noise if given */
+      cval = PLISTPIX(pixt, cdvalue);
+      if (cval > 0.0) {
+        cvar += cval / gain;
+      }
     }
+
+    /* Note that this works for both blended and non-blended cases
+     * because xm is set to xn above for the blended case. */
+    cvarsum += cvar;
+    errx2 += cvar * (x - xm) * (x - xm);
+    erry2 += cvar * (y - ym) * (y - ym);
+    errxy += cvar * (x - xm) * (y - ym);
+  }
   errx2 /= rv2;
   erry2 /= rv2;
   errxy /= rv2;
 
   /* Handle fully correlated x/y (which cause a singularity...) */
-  if ((temp2=xm2*ym2-xym*xym)<0.00694)
-    {
-      xm2 += 0.0833333;
-      ym2 += 0.0833333;
-      temp2 = xm2*ym2-xym*xym;
-      obj->flag |= SEP_OBJ_SINGU;
-
-      /* handle it for the error parameters */
-      cvarsum *= 0.08333/rv2;
-      if (errx2*erry2 - errxy * errxy < cvarsum * cvarsum) {
-        errx2 += cvarsum;
-        erry2 += cvarsum;
-      }
+  if ((temp2 = xm2 * ym2 - xym * xym) < 0.00694) {
+    xm2 += 0.0833333;
+    ym2 += 0.0833333;
+    temp2 = xm2 * ym2 - xym * xym;
+    obj->flag |= SEP_OBJ_SINGU;
+
+    /* handle it for the error parameters */
+    cvarsum *= 0.08333 / rv2;
+    if (errx2 * erry2 - errxy * errxy < cvarsum * cvarsum) {
+      errx2 += cvarsum;
+      erry2 += cvarsum;
     }
+  }
 
-  if ((fabs(temp=xm2-ym2)) > 0.0)
+  if ((fabs(temp = xm2 - ym2)) > 0.0) {
     theta = atan2(2.0 * xym, temp) / 2.0;
-  else
-    theta = PI/4.0;
+  } else {
+    theta = PI / 4.0;
+  }
 
-  temp = sqrt(0.25*temp*temp+xym*xym);
-  pmy2 = pmx2 = 0.5*(xm2+ym2);
-  pmx2+=temp;
-  pmy2-=temp;
+  temp = sqrt(0.25 * temp * temp + xym * xym);
+  pmy2 = pmx2 = 0.5 * (xm2 + ym2);
+  pmx2 += temp;
+  pmy2 -= temp;
 
   obj->dnpix = (LONG)dnpix;
   obj->dflux = tv;
-  obj->mx = xm+xmin;	/* add back xmin */
-  obj->my = ym+ymin;	/* add back ymin */
+  obj->mx = xm + xmin; /* add back xmin */
+  obj->my = ym + ymin; /* add back ymin */
   obj->mx2 = xm2;
   obj->errx2 = errx2;
   obj->my2 = ym2;
@@ -303,24 +295,22 @@ void  analyse(int no, objliststruct *objlist, int robust, double gain)
   obj->b = (float)sqrt(pmy2);
   obj->theta = theta;
 
-  obj->cxx = (float)(ym2/temp2);
-  obj->cyy = (float)(xm2/temp2);
-  obj->cxy = (float)(-2*xym/temp2);
+  obj->cxx = (float)(ym2 / temp2);
+  obj->cyy = (float)(xm2 / temp2);
+  obj->cxy = (float)(-2 * xym / temp2);
 
   darea = (double)area2 - dnpix;
-  t1t2 = thresh/thresh2;
+  t1t2 = thresh / thresh2;
 
   /* debugging */
-  /*if (t1t2>0.0 && !PLISTEXIST(thresh)) */  /* was: prefs.dweight_flag */
-  if (t1t2 > 0.0)
-    {
-      obj->abcor = (darea<0.0?darea:-1.0)/(2*PI*log(t1t2<1.0?t1t2:0.99)
-					   *obj->a*obj->b);
-      if (obj->abcor>1.0)
-	obj->abcor = 1.0;
-    }
-  else
-    {
+  /*if (t1t2>0.0 && !PLISTEXIST(thresh)) */ /* was: prefs.dweight_flag */
+  if (t1t2 > 0.0) {
+    obj->abcor = (darea < 0.0 ? darea : -1.0)
+                 / (2 * PI * log(t1t2 < 1.0 ? t1t2 : 0.99) * obj->a * obj->b);
+    if (obj->abcor > 1.0) {
       obj->abcor = 1.0;
     }
+  } else {
+    obj->abcor = 1.0;
+  }
 }
diff --git a/src/aperture.c b/src/aperture.c
index 5f49e0f..ef8b8f4 100644
--- a/src/aperture.c
+++ b/src/aperture.c
@@ -1,39 +1,41 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "overlap.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "overlap.h"
 
 #define FLUX_RADIUS_BUFSIZE 64
 
-#define WINPOS_NITERMAX 16      /* Maximum number of steps */
-#define WINPOS_NSIG     4       /* Measurement radius */
-#define WINPOS_STEPMIN  0.0001  /* Minimum change in position for continuing */
-#define WINPOS_FAC      2.0     /* Centroid offset factor (2 for a Gaussian) */
+#define WINPOS_NITERMAX 16 /* Maximum number of steps */
+#define WINPOS_NSIG 4 /* Measurement radius */
+#define WINPOS_STEPMIN 0.0001 /* Minimum change in position for continuing */
+#define WINPOS_FAC 2.0 /* Centroid offset factor (2 for a Gaussian) */
 
 /*
   Adding (void *) pointers is a GNU C extension, not part of standard C.
@@ -41,9 +43,9 @@
   (void *) to something the size of one byte.
 */
 #if defined(_MSC_VER)
-  #define MSVC_VOID_CAST (char *)
+#define MSVC_VOID_CAST (char *)
 #else
-  #define MSVC_VOID_CAST
+#define MSVC_VOID_CAST
 #endif
 
 /****************************************************************************/
@@ -57,43 +59,46 @@
    cxx*cyy - cxy*cxy/4. > 0.
    cxx + cyy > 0.
 */
-int sep_ellipse_axes(double cxx, double cyy, double cxy,
-                     double *a, double *b, double *theta)
-{
+int sep_ellipse_axes(
+    double cxx, double cyy, double cxy, double * a, double * b, double * theta
+) {
   double p, q, t;
 
   p = cxx + cyy;
   q = cxx - cyy;
-  t = sqrt(q*q + cxy*cxy);
+  t = sqrt(q * q + cxy * cxy);
 
   /* Ensure that parameters actually describe an ellipse. */
-  if ((cxx*cyy - cxy*cxy/4. <= 0.) || (p <= 0.))
+  if ((cxx * cyy - cxy * cxy / 4. <= 0.) || (p <= 0.)) {
     return NON_ELLIPSE_PARAMS;
+  }
 
   *a = sqrt(2. / (p - t));
   *b = sqrt(2. / (p + t));
 
   /* theta = 0 if cxy == 0, else (1/2) acot(q/cxy) */
-  *theta = (cxy == 0.) ? 0. : (q == 0. ? 0. : atan(cxy/q))/2.;
-  if (cxx>cyy)
-    *theta += PI/2.;
-  if (*theta > PI/2.)
+  *theta = (cxy == 0.) ? 0. : (q == 0. ? 0. : atan(cxy / q)) / 2.;
+  if (cxx > cyy) {
+    *theta += PI / 2.;
+  }
+  if (*theta > PI / 2.) {
     *theta -= PI;
+  }
 
   return RETURN_OK;
 }
 
-void sep_ellipse_coeffs(double a, double b, double theta,
-                        double *cxx, double *cyy, double *cxy)
-{
+void sep_ellipse_coeffs(
+    double a, double b, double theta, double * cxx, double * cyy, double * cxy
+) {
   double costheta, sintheta;
 
   costheta = cos(theta);
   sintheta = sin(theta);
 
-  *cxx = costheta*costheta/(a*a) + sintheta*sintheta/(b*b);
-  *cyy = sintheta*sintheta/(a*a) + costheta*costheta/(b*b);
-  *cxy = 2.*costheta*sintheta * (1./(a*a) - 1./(b*b));
+  *cxx = costheta * costheta / (a * a) + sintheta * sintheta / (b * b);
+  *cyy = sintheta * sintheta / (a * a) + costheta * costheta / (b * b);
+  *cxy = 2. * costheta * sintheta * (1. / (a * a) - 1. / (b * b));
 }
 
 /*****************************************************************************/
@@ -103,69 +108,80 @@ void sep_ellipse_coeffs(double a, double b, double theta,
  * parameters x, y, r. xmin is inclusive and xmax is exclusive.
  * Ensures that box is within image bound and sets a flag if it is not.
  */
-static void boxextent(double x, double y, double rx, double ry, int w, int h,
-                      int *xmin, int *xmax, int *ymin, int *ymax,
-                      short *flag)
-{
-  *xmin = (int)(x - rx + 0.5);
-  *xmax = (int)(x + rx + 1.4999999);
-  *ymin = (int)(y - ry + 0.5);
-  *ymax = (int)(y + ry + 1.4999999);
-  if (*xmin < 0)
-    {
-      *xmin = 0;
-      *flag |= SEP_APER_TRUNC;
-    }
-  if (*xmax > w)
-    {
-      *xmax = w;
-      *flag |= SEP_APER_TRUNC;
-    }
-  if (*ymin < 0)
-    {
-      *ymin = 0;
-      *flag |= SEP_APER_TRUNC;
-    }
-  if (*ymax > h)
-    {
-      *ymax = h;
-      *flag |= SEP_APER_TRUNC;
-    }
+static void boxextent(
+    double x,
+    double y,
+    double rx,
+    double ry,
+    int64_t w,
+    int64_t h,
+    int64_t * xmin,
+    int64_t * xmax,
+    int64_t * ymin,
+    int64_t * ymax,
+    short * flag
+) {
+  *xmin = (int64_t)(x - rx + 0.5);
+  *xmax = (int64_t)(x + rx + 1.4999999);
+  *ymin = (int64_t)(y - ry + 0.5);
+  *ymax = (int64_t)(y + ry + 1.4999999);
+  if (*xmin < 0) {
+    *xmin = 0;
+    *flag |= SEP_APER_TRUNC;
+  }
+  if (*xmax > w) {
+    *xmax = w;
+    *flag |= SEP_APER_TRUNC;
+  }
+  if (*ymin < 0) {
+    *ymin = 0;
+    *flag |= SEP_APER_TRUNC;
+  }
+  if (*ymax > h) {
+    *ymax = h;
+    *flag |= SEP_APER_TRUNC;
+  }
 }
 
 
-static void boxextent_ellipse(double x, double y,
-                              double cxx, double cyy, double cxy, double r,
-                              int w, int h,
-                              int *xmin, int *xmax, int *ymin, int *ymax,
-                              short *flag)
-{
+static void boxextent_ellipse(
+    double x,
+    double y,
+    double cxx,
+    double cyy,
+    double cxy,
+    double r,
+    int64_t w,
+    int64_t h,
+    int64_t * xmin,
+    int64_t * xmax,
+    int64_t * ymin,
+    int64_t * ymax,
+    short * flag
+) {
   double dxlim, dylim;
 
-  dxlim = cxx - cxy*cxy/(4.0*cyy);
-  dxlim = dxlim>0.0 ? r/sqrt(dxlim) : 0.0;
-  dylim = cyy - cxy*cxy/(4.0*cxx);
-  dylim = dylim > 0.0 ? r/sqrt(dylim) : 0.0;
+  dxlim = cxx - cxy * cxy / (4.0 * cyy);
+  dxlim = dxlim > 0.0 ? r / sqrt(dxlim) : 0.0;
+  dylim = cyy - cxy * cxy / (4.0 * cxx);
+  dylim = dylim > 0.0 ? r / sqrt(dylim) : 0.0;
   boxextent(x, y, dxlim, dylim, w, h, xmin, xmax, ymin, ymax, flag);
 }
 
 /* determine oversampled annulus for a circle */
-static void oversamp_ann_circle(double r, double *r_in2, double *r_out2)
-{
-   *r_in2 = r - 0.7072;
-   *r_in2 = (*r_in2 > 0.0) ? (*r_in2)*(*r_in2) : 0.0;
-   *r_out2 = r + 0.7072;
-   *r_out2 = (*r_out2) * (*r_out2);
+static void oversamp_ann_circle(double r, double * r_in2, double * r_out2) {
+  *r_in2 = r - 0.7072;
+  *r_in2 = (*r_in2 > 0.0) ? (*r_in2) * (*r_in2) : 0.0;
+  *r_out2 = r + 0.7072;
+  *r_out2 = (*r_out2) * (*r_out2);
 }
 
 /* determine oversampled "annulus" for an ellipse */
-static void oversamp_ann_ellipse(double r, double b, double *r_in2,
-                                 double *r_out2)
-{
-   *r_in2 = r - 0.7072/b;
-   *r_in2 = (*r_in2 > 0.0) ? (*r_in2)*(*r_in2) : 0.0;
-   *r_out2 = r + 0.7072/b;
-   *r_out2 = (*r_out2) * (*r_out2);
+static void oversamp_ann_ellipse(double r, double b, double * r_in2, double * r_out2) {
+  *r_in2 = r - 0.7072 / b;
+  *r_in2 = (*r_in2 > 0.0) ? (*r_in2) * (*r_in2) : 0.0;
+  *r_out2 = r + 0.7072 / b;
+  *r_out2 = (*r_out2) * (*r_out2);
 }
 
 /*****************************************************************************/
@@ -174,17 +190,17 @@ static void oversamp_ann_ellipse(double r, double b, double *r_in2,
 #define APER_NAME sep_sum_circle
 #define APER_ARGS double r
 #define APER_DECL double r2, r_in2, r_out2
-#define APER_CHECKS                             \
-  if (r < 0.0)                                  \
-    return ILLEGAL_APER_PARAMS
-#define APER_INIT                               \
-  r2 = r*r;                                     \
+#define APER_CHECKS \
+  if (r < 0.0)      \
+  return ILLEGAL_APER_PARAMS
+#define APER_INIT \
+  r2 = r * r;     \
   oversamp_ann_circle(r, &r_in2, &r_out2)
-#define APER_BOXEXTENT boxextent(x, y, r, r, im->w, im->h,              \
-                                 &xmin, &xmax, &ymin, &ymax, flag)
-#define APER_EXACT circoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, r)
-#define APER_RPIX2 dx*dx + dy*dy
-#define APER_RPIX2_SUBPIX dx1*dx1 + dy2
+#define APER_BOXEXTENT \
+  boxextent(x, y, r, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag)
+#define APER_EXACT circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, r)
+#define APER_RPIX2 dx * dx + dy * dy
+#define APER_RPIX2_SUBPIX dx1 * dx1 + dy2
 #define APER_COMPARE1 rpix2 < r_out2
 #define APER_COMPARE2 rpix2 > r_in2
 #define APER_COMPARE3 rpix2 < r2
@@ -208,21 +224,22 @@ static void oversamp_ann_ellipse(double r, double b, double *r_in2,
 #define APER_NAME sep_sum_ellipse
 #define APER_ARGS double a, double b, double theta, double r
 #define APER_DECL double cxx, cyy, cxy, r2, r_in2, r_out2
-#define APER_CHECKS                                                     \
-  if (!(r >= 0.0 && b >= 0.0 && a >= b &&                               \
-        theta >= -PI/2. && theta <= PI/2.))                             \
-    return ILLEGAL_APER_PARAMS
-#define APER_INIT                                               \
-  r2 = r*r;                                                     \
-  oversamp_ann_ellipse(r, b, &r_in2, &r_out2);                  \
-  sep_ellipse_coeffs(a, b, theta, &cxx, &cyy, &cxy);            \
-  a *= r;                                                       \
+#define APER_CHECKS                                                               \
+  if (!(r >= 0.0 && b >= 0.0 && a >= b && theta >= -PI / 2. && theta <= PI / 2.)) \
+  return ILLEGAL_APER_PARAMS
+#define APER_INIT                                    \
+  r2 = r * r;                                        \
+  oversamp_ann_ellipse(r, b, &r_in2, &r_out2);       \
+  sep_ellipse_coeffs(a, b, theta, &cxx, &cyy, &cxy); \
+  a *= r;                                            \
   b *= r
-#define APER_BOXEXTENT boxextent_ellipse(x, y, cxx, cyy, cxy, r, im->w, im->h, \
-                                         &xmin, &xmax, &ymin, &ymax, flag)
-#define APER_EXACT ellipoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, a, b, theta)
-#define APER_RPIX2 cxx*dx*dx + cyy*dy*dy + cxy*dx*dy
-#define APER_RPIX2_SUBPIX cxx*dx1*dx1 + cyy*dy2 + cxy*dx1*dy
+#define APER_BOXEXTENT                                                       \
+  boxextent_ellipse(                                                         \
+      x, y, cxx, cyy, cxy, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag \
+  )
+#define APER_EXACT ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a, b, theta)
+#define APER_RPIX2 cxx * dx * dx + cyy * dy * dy + cxy * dx * dy
+#define APER_RPIX2_SUBPIX cxx * dx1 * dx1 + cyy * dy2 + cxy * dx1 * dy
 #define APER_COMPARE1 rpix2 < r_out2
 #define APER_COMPARE2 rpix2 > r_in2
 #define APER_COMPARE3 rpix2 < r2
@@ -246,20 +263,21 @@ static void oversamp_ann_ellipse(double r, double b, double *r_in2,
 #define APER_NAME sep_sum_circann
 #define APER_ARGS double rin, double rout
 #define APER_DECL double rin2, rin_in2, rin_out2, rout2, rout_in2, rout_out2
-#define APER_CHECKS                             \
-  if (!(rin >= 0.0 && rout >= rin))             \
-    return ILLEGAL_APER_PARAMS
-#define APER_INIT                                       \
-  rin2 = rin*rin;                                       \
-  oversamp_ann_circle(rin, &rin_in2, &rin_out2);        \
-  rout2 = rout*rout;                                    \
+#define APER_CHECKS                 \
+  if (!(rin >= 0.0 && rout >= rin)) \
+  return ILLEGAL_APER_PARAMS
+#define APER_INIT                                \
+  rin2 = rin * rin;                              \
+  oversamp_ann_circle(rin, &rin_in2, &rin_out2); \
+  rout2 = rout * rout;                           \
   oversamp_ann_circle(rout, &rout_in2, &rout_out2)
-#define APER_BOXEXTENT boxextent(x, y, rout, rout, im->w, im->h, \
-                                 &xmin, &xmax, &ymin, &ymax, flag)
-#define APER_EXACT (circoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, rout) - \
-                    circoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, rin))
-#define APER_RPIX2 dx*dx + dy*dy
-#define APER_RPIX2_SUBPIX dx1*dx1 + dy2
+#define APER_BOXEXTENT \
+  boxextent(x, y, rout, rout, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag)
+#define APER_EXACT                                           \
+  (circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, rout) \
+   - circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, rin))
+#define APER_RPIX2 dx * dx + dy * dy
+#define APER_RPIX2_SUBPIX dx1 * dx1 + dy2
 #define APER_COMPARE1 (rpix2 < rout_out2) && (rpix2 > rin_in2)
 #define APER_COMPARE2 (rpix2 > rout_in2) || (rpix2 < rin_out2)
 #define APER_COMPARE3 (rpix2 < rout2) && (rpix2 > rin2)
@@ -282,26 +300,28 @@ static void oversamp_ann_ellipse(double r, double b, double *r_in2,
 
 #define APER_NAME sep_sum_ellipann
 #define APER_ARGS double a, double b, double theta, double rin, double rout
-#define APER_DECL                                               \
-  double cxx, cyy, cxy;                                         \
+#define APER_DECL       \
+  double cxx, cyy, cxy; \
   double rin2, rin_in2, rin_out2, rout2, rout_in2, rout_out2
-#define APER_CHECKS                                         \
-  if (!(rin >= 0.0 && rout >= rin && b >= 0.0 && a >= b &&  \
-        theta >= -PI/2. && theta <= PI/2.))                 \
-    return ILLEGAL_APER_PARAMS
-#define APER_INIT                                               \
-  rin2 = rin*rin;                                               \
-  oversamp_ann_ellipse(rin, b, &rin_in2, &rin_out2);            \
-  rout2 = rout*rout;                                            \
-  oversamp_ann_ellipse(rout, b, &rout_in2, &rout_out2);         \
+#define APER_CHECKS                                                          \
+  if (!(rin >= 0.0 && rout >= rin && b >= 0.0 && a >= b && theta >= -PI / 2. \
+        && theta <= PI / 2.))                                                \
+  return ILLEGAL_APER_PARAMS
+#define APER_INIT                                       \
+  rin2 = rin * rin;                                     \
+  oversamp_ann_ellipse(rin, b, &rin_in2, &rin_out2);    \
+  rout2 = rout * rout;                                  \
+  oversamp_ann_ellipse(rout, b, &rout_in2, &rout_out2); \
   sep_ellipse_coeffs(a, b, theta, &cxx, &cyy, &cxy)
-#define APER_BOXEXTENT boxextent_ellipse(x, y, cxx, cyy, cxy, rout, im->w, im->h, \
-                                         &xmin, &xmax, &ymin, &ymax, flag)
-#define APER_EXACT                                                      \
-  (ellipoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, a*rout, b*rout, theta) - \
-   ellipoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5, a*rin, b*rin, theta))
-#define APER_RPIX2 cxx*dx*dx + cyy*dy*dy + cxy*dx*dy
-#define APER_RPIX2_SUBPIX cxx*dx1*dx1 + cyy*dy2 + cxy*dx1*dy
+#define APER_BOXEXTENT                                                          \
+  boxextent_ellipse(                                                            \
+      x, y, cxx, cyy, cxy, rout, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag \
+  )
+#define APER_EXACT                                                                 \
+  (ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a * rout, b * rout, theta) \
+   - ellipoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, a * rin, b * rin, theta))
+#define APER_RPIX2 cxx * dx * dx + cyy * dy * dy + cxy * dx * dy
+#define APER_RPIX2_SUBPIX cxx * dx1 * dx1 + cyy * dy2 + cxy * dx1 * dy
 #define APER_COMPARE1 (rpix2 < rout_out2) && (rpix2 > rin_in2)
 #define APER_COMPARE2 (rpix2 > rout_in2) || (rpix2 < rin_out2)
 #define APER_COMPARE3 (rpix2 < rout2) && (rpix2 > rin2)
@@ -325,36 +345,46 @@ static void oversamp_ann_ellipse(double r, double b, double *r_in2,
  * This is just different enough from the other aperture functions
  * that it doesn't quite make sense to use aperture.i.
  */
-int sep_sum_circann_multi(const sep_image *im,
-                          double x, double y, double rmax, int n,
-                          int id,
-                          int subpix,
-                          short inflag,
-                          double *sum, double *sumvar, double *area,
-                          double *maskarea, short *flag)
-{
+int sep_sum_circann_multi(
+    const sep_image * im,
+    double x,
+    double y,
+    double rmax,
+    int64_t n,
+    int id,
+    int subpix,
+    short inflag,
+    double * sum,
+    double * sumvar,
+    double * area,
+    double * maskarea,
+    short * flag
+) {
   PIXTYPE pix, varpix;
   double dx, dy, dx1, dy2, offset, scale, scale2, tmp, rpix2;
-  int ix, iy, xmin, xmax, ymin, ymax, sx, sy, status, size, esize, msize, ssize;
-  long pos;
+  int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, size, esize, msize, ssize, pos;
+  int status;
   short errisarray, errisstd;
   const BYTE *datat, *errort, *maskt, *segt;
   converter convert, econvert, mconvert, sconvert;
   double rpix, r_out, r_out2, d, prevbinmargin, nextbinmargin, step, stepdens;
-  int j, ismasked;
+  int64_t j, ismasked;
 
   /* input checks */
-  if (rmax < 0.0 || n < 1)
+  if (rmax < 0.0 || n < 1) {
     return ILLEGAL_APER_PARAMS;
-  if (subpix < 1)
+  }
+  if (subpix < 1) {
     return ILLEGAL_SUBPIX;
+  }
 
   /* clear results arrays */
-  memset(sum, 0, (size_t)(n*sizeof(double)));
-  memset(sumvar, 0, (size_t)(n*sizeof(double)));
-  memset(area, 0, (size_t)(n*sizeof(double)));
-  if (im->mask)
-    memset(maskarea, 0, (size_t)(n*sizeof(double)));
+  memset(sum, 0, (size_t)(n * sizeof(double)));
+  memset(sumvar, 0, (size_t)(n * sizeof(double)));
+  memset(area, 0, (size_t)(n * sizeof(double)));
+  if (im->mask) {
+    memset(maskarea, 0, (size_t)(n * sizeof(double)));
+  }
 
   /* initializations */
   size = esize = msize = ssize = 0;
@@ -362,14 +392,14 @@ int sep_sum_circann_multi(const sep_image *im,
   errort = im->noise;
   *flag = 0;
   varpix = 0.0;
-  scale = 1.0/subpix;
-  scale2 = scale*scale;
-  offset = 0.5*(scale-1.0);
+  scale = 1.0 / subpix;
+  scale2 = scale * scale;
+  offset = 0.5 * (scale - 1.0);
 
   r_out = rmax + 1.5; /* margin for interpolation */
   r_out2 = r_out * r_out;
-  step = rmax/n;
-  stepdens = 1.0/step;
+  step = rmax / n;
+  stepdens = 1.0 / step;
   prevbinmargin = 0.7072;
   nextbinmargin = step - 0.7072;
   j = 0;
@@ -379,218 +409,214 @@ int sep_sum_circann_multi(const sep_image *im,
   errisstd = 0;
 
   /* get data converter(s) for input array(s) */
-  if ((status = get_converter(im->dtype, &convert, &size)))
+  if ((status = get_converter(im->dtype, &convert, &size))) {
     return status;
-  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
+  }
+  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) {
     return status;
-  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize)))
+  }
+  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) {
     return status;
+  }
 
   /* get image noise */
-  if (im->noise_type != SEP_NOISE_NONE)
-    {
-      errisstd = (im->noise_type == SEP_NOISE_STDDEV);
-      if (im->noise)
-        {
-          errisarray = 1;
-          if ((status = get_converter(im->ndtype, &econvert, &esize)))
-            return status;
-        }
-      else
-        {
-          varpix = (errisstd)?  im->noiseval * im->noiseval: im->noiseval;
-        }
+  if (im->noise_type != SEP_NOISE_NONE) {
+    errisstd = (im->noise_type == SEP_NOISE_STDDEV);
+    if (im->noise) {
+      errisarray = 1;
+      if ((status = get_converter(im->ndtype, &econvert, &esize))) {
+        return status;
+      }
+    } else {
+      varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval;
     }
+  }
 
 
   /* get extent of box */
-  boxextent(x, y, r_out, r_out, im->w, im->h, &xmin, &xmax, &ymin, &ymax,
-            flag);
+  boxextent(x, y, r_out, r_out, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag);
 
   /* loop over rows in the box */
-  for (iy=ymin; iy<ymax; iy++)
-    {
-      /* set pointers to the start of this row */
-      pos = (iy % im->h) * im->w + xmin;
-      datat = MSVC_VOID_CAST im->data + pos*size;
-      if (errisarray)
-        errort = MSVC_VOID_CAST im->noise + pos*esize;
-      if (im->mask)
-        maskt = MSVC_VOID_CAST im->mask + pos*msize;
-      if (im->segmap)
-        segt = MSVC_VOID_CAST im->segmap + pos*ssize;
+  for (iy = ymin; iy < ymax; iy++) {
+    /* set pointers to the start of this row */
+    pos = (iy % im->h) * im->w + xmin;
+    datat = MSVC_VOID_CAST im->data + pos * size;
+    if (errisarray) {
+      errort = MSVC_VOID_CAST im->noise + pos * esize;
+    }
+    if (im->mask) {
+      maskt = MSVC_VOID_CAST im->mask + pos * msize;
+    }
+    if (im->segmap) {
+      segt = MSVC_VOID_CAST im->segmap + pos * ssize;
+    }
 
-      /* loop over pixels in this row */
-      for (ix=xmin; ix<xmax; ix++)
-        {
-          dx = ix - x;
-          dy = iy - y;
-          rpix2 = dx*dx + dy*dy;
-          if (rpix2 < r_out2)
-            {
-              /* get pixel values */
-              pix = convert(datat);
-              if (errisarray)
-                {
-                  varpix = econvert(errort);
-                  if (errisstd)
-                    varpix *= varpix;
-                }
+    /* loop over pixels in this row */
+    for (ix = xmin; ix < xmax; ix++) {
+      dx = ix - x;
+      dy = iy - y;
+      rpix2 = dx * dx + dy * dy;
+      if (rpix2 < r_out2) {
+        /* get pixel values */
+        pix = convert(datat);
+        if (errisarray) {
+          varpix = econvert(errort);
+          if (errisstd) {
+            varpix *= varpix;
+          }
+        }
 
-              ismasked = 0;
-              if (im->mask)
-                {
-                  if (mconvert(maskt) > im->maskthresh)
-                    {
-                      *flag |= SEP_APER_HASMASKED;
-                      ismasked = 1;
-                    }
-                }
+        ismasked = 0;
+        if (im->mask) {
+          if (mconvert(maskt) > im->maskthresh) {
+            *flag |= SEP_APER_HASMASKED;
+            ismasked = 1;
+          }
+        }
 
-              /* Segmentation image:
-
-    	           If `id` is negative, require segmented pixels within the
-    	           aperture.
-
-    	           If `id` is positive, mask pixels with nonzero segment ids
-    	           not equal to `id`.
-
-    	      */
-    	      if (im->segmap)
-      	        {
-      	          if (id > 0)
-      	            {
-      	              if ((sconvert(segt) > 0.) & (sconvert(segt) != id))
-      	                {
-                          *flag |= SEP_APER_HASMASKED;
-      	                  ismasked = 1;
-      	                }
-      	            } else {
-    	              if (sconvert(segt) != -1*id)
-    	                {
-                          *flag |= SEP_APER_HASMASKED;
-    	                  ismasked = 1;
-    	                }
-      	            }
-      	        }
-
-              /* check if oversampling is needed (close to bin boundary?) */
-              rpix = sqrt(rpix2);
-              d = fmod(rpix, step);
-              if (d < prevbinmargin || d > nextbinmargin)
-                {
-                  dx += offset;
-                  dy += offset;
-                  for (sy=subpix; sy--; dy+=scale)
-                    {
-                      dx1 = dx;
-                      dy2 = dy*dy;
-                      for (sx=subpix; sx--; dx1+=scale)
-                        {
-                          j = (int)(sqrt(dx1*dx1+dy2)*stepdens);
-                          if (j < n)
-                            {
-                              if (ismasked)
-                                maskarea[j] += scale2;
-                              else
-                                {
-                                  sum[j] += scale2*pix;
-                                  sumvar[j] += scale2*varpix;
-                                }
-                              area[j] += scale2;
-                            }
-                        }
-                    }
-                }
-              else
-                /* pixel not close to bin boundary */
-                {
-                  j = (int)(rpix*stepdens);
-                  if (j < n)
-                    {
-                      if (ismasked)
-                        maskarea[j] += 1.0;
-                      else
-                        {
-                          sum[j] += pix;
-                          sumvar[j] += varpix;
-                        }
-                      area[j] += 1.0;
-                    }
+        /* Segmentation image:
+
+             If `id` is negative, require segmented pixels within the
+             aperture.
+
+             If `id` is positive, mask pixels with nonzero segment ids
+             not equal to `id`.
+
+        */
+        if (im->segmap) {
+          if (id > 0) {
+            if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) {
+              *flag |= SEP_APER_HASMASKED;
+              ismasked = 1;
+            }
+          } else {
+            if (sconvert(segt) != -1 * id) {
+              *flag |= SEP_APER_HASMASKED;
+              ismasked = 1;
+            }
+          }
+        }
+
+        /* check if oversampling is needed (close to bin boundary?) */
+        rpix = sqrt(rpix2);
+        d = fmod(rpix, step);
+        if (d < prevbinmargin || d > nextbinmargin) {
+          dx += offset;
+          dy += offset;
+          for (sy = subpix; sy--; dy += scale) {
+            dx1 = dx;
+            dy2 = dy * dy;
+            for (sx = subpix; sx--; dx1 += scale) {
+              j = (int64_t)(sqrt(dx1 * dx1 + dy2) * stepdens);
+              if (j < n) {
+                if (ismasked) {
+                  maskarea[j] += scale2;
+                } else {
+                  sum[j] += scale2 * pix;
+                  sumvar[j] += scale2 * varpix;
                 }
-            } /* closes "if pixel might be within aperture" */
-
-          /* increment pointers by one element */
-          datat += size;
-          if (errisarray)
-            errort += esize;
-          maskt += msize;
-          segt += ssize;
+                area[j] += scale2;
+              }
+            }
+          }
+        } else
+        /* pixel not close to bin boundary */
+        {
+          j = (int64_t)(rpix * stepdens);
+          if (j < n) {
+            if (ismasked) {
+              maskarea[j] += 1.0;
+            } else {
+              sum[j] += pix;
+              sumvar[j] += varpix;
+            }
+            area[j] += 1.0;
+          }
         }
+      } /* closes "if pixel might be within aperture" */
+
+      /* increment pointers by one element */
+      datat += size;
+      if (errisarray) {
+        errort += esize;
+      }
+      maskt += msize;
+      segt += ssize;
     }
+  }
 
 
   /* correct for masked values */
-  if (im->mask)
-    {
-      if (inflag & SEP_MASK_IGNORE)
-        for (j=n; j--;)
-          area[j] -= maskarea[j];
-      else
-        {
-          for (j=n; j--;)
-            {
-              tmp = area[j] == maskarea[j]? 0.0: area[j]/(area[j]-maskarea[j]);
-              sum[j] *= tmp;
-              sumvar[j] *= tmp;
-            }
-        }
+  if (im->mask) {
+    if (inflag & SEP_MASK_IGNORE) {
+      for (j = n; j--;) {
+        area[j] -= maskarea[j];
+      }
+    } else {
+      for (j = n; j--;) {
+        tmp = area[j] == maskarea[j] ? 0.0 : area[j] / (area[j] - maskarea[j]);
+        sum[j] *= tmp;
+        sumvar[j] *= tmp;
+      }
     }
+  }
 
   /* add poisson noise, only if gain > 0 */
-  if (im->gain > 0.0)
-    for (j=n; j--;)
-      if (sum[j] > 0.0)
+  if (im->gain > 0.0) {
+    for (j = n; j--;) {
+      if (sum[j] > 0.0) {
         sumvar[j] += sum[j] / im->gain;
+      }
+    }
+  }
 
   return status;
 }
 
 
 /* for use in flux_radius */
-static double inverse(double xmax, const double *y, int n, double ytarg)
-{
+static double inverse(double xmax, const double * y, int64_t n, double ytarg) {
   double step;
-  int i;
+  int64_t i;
 
-  step = xmax/n;
+  step = xmax / n;
   i = 0;
 
   /* increment i until y[i] is >= to ytarg */
-  while (i < n && y[i] < ytarg)
+  while (i < n && y[i] < ytarg) {
     i++;
+  }
 
-  if (i == 0)
-    {
-      if (ytarg <= 0. || y[0] == 0.)
-        return 0.;
-      return step * ytarg/y[0];
+  if (i == 0) {
+    if (ytarg <= 0. || y[0] == 0.) {
+      return 0.;
     }
-  if (i == n)
+    return step * ytarg / y[0];
+  }
+  if (i == n) {
     return xmax;
+  }
 
   /* note that y[i-1] corresponds to x=step*i. */
-  return step * (i + (ytarg - y[i-1])/(y[i] - y[i-1]));
+  return step * (i + (ytarg - y[i - 1]) / (y[i] - y[i - 1]));
 }
 
-int sep_flux_radius(const sep_image *im,
-                    double x, double y, double rmax, int id,
-                    int subpix, short inflag,
-                    const double *fluxtot, const double *fluxfrac, int n, double *r,
-                    short *flag)
-{
+int sep_flux_radius(
+    const sep_image * im,
+    double x,
+    double y,
+    double rmax,
+    int id,
+    int subpix,
+    short inflag,
+    const double * fluxtot,
+    const double * fluxfrac,
+    int64_t n,
+    double * r,
+    short * flag
+) {
   int status;
-  int i;
+  int64_t i;
   double f;
   double sumbuf[FLUX_RADIUS_BUFSIZE] = {0.};
   double sumvarbuf[FLUX_RADIUS_BUFSIZE];
@@ -598,41 +624,62 @@ int sep_flux_radius(const sep_image *im,
   double maskareabuf[FLUX_RADIUS_BUFSIZE];
 
   /* measure FLUX_RADIUS_BUFSIZE annuli out to rmax. */
-  status = sep_sum_circann_multi(im, x, y, rmax,
-                                 FLUX_RADIUS_BUFSIZE, id, subpix, inflag,
-                                 sumbuf, sumvarbuf, areabuf, maskareabuf,
-                                 flag);
+  status = sep_sum_circann_multi(
+      im,
+      x,
+      y,
+      rmax,
+      FLUX_RADIUS_BUFSIZE,
+      id,
+      subpix,
+      inflag,
+      sumbuf,
+      sumvarbuf,
+      areabuf,
+      maskareabuf,
+      flag
+  );
 
   /* sum up sumbuf array */
-  for (i=1; i<FLUX_RADIUS_BUFSIZE; i++)
-    sumbuf[i] += sumbuf[i-1];
+  for (i = 1; i < FLUX_RADIUS_BUFSIZE; i++) {
+    sumbuf[i] += sumbuf[i - 1];
+  }
 
   /* if given, use "total flux", else, use sum within rmax. */
-  f = fluxtot? *fluxtot : sumbuf[FLUX_RADIUS_BUFSIZE-1];
+  f = fluxtot ? *fluxtot : sumbuf[FLUX_RADIUS_BUFSIZE - 1];
 
   /* Use inverse to get the radii corresponding to the requested flux fracs */
-  for (i=0; i<n; i++)
+  for (i = 0; i < n; i++) {
     r[i] = inverse(rmax, sumbuf, FLUX_RADIUS_BUFSIZE, fluxfrac[i] * f);
+  }
 
   return status;
 }
 
 /*****************************************************************************/
 /* calculate Kron radius from pixels within an ellipse. */
-int sep_kron_radius(const sep_image *im, double x, double y,
-                    double cxx, double cyy, double cxy, double r, int id,
-                    double *kronrad, short *flag)
-{
+int sep_kron_radius(
+    const sep_image * im,
+    double x,
+    double y,
+    double cxx,
+    double cyy,
+    double cxy,
+    double r,
+    int id,
+    double * kronrad,
+    short * flag
+) {
   float pix;
   double r1, v1, r2, area, rpix2, dx, dy;
-  int ix, iy, xmin, xmax, ymin, ymax, status, size, msize, ssize;
-  long pos;
+  int64_t ix, iy, xmin, xmax, ymin, ymax, pos, size, msize, ssize;
+  int status;
   int ismasked;
 
   const BYTE *datat, *maskt, *segt;
   converter convert, mconvert, sconvert;
 
-  r2 = r*r;
+  r2 = r * r;
   r1 = v1 = 0.0;
   area = 0.0;
   *flag = 0;
@@ -640,132 +687,130 @@ int sep_kron_radius(const sep_image *im, double x, double y,
   size = msize = ssize = 0;
 
   /* get data converter(s) for input array(s) */
-  if ((status = get_converter(im->dtype, &convert, &size)))
+  if ((status = get_converter(im->dtype, &convert, &size))) {
+    return status;
+  }
+  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) {
+    return status;
+  }
+  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) {
     return status;
-  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
-      return status;
-  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize)))
-      return status;
+  }
 
   /* get extent of ellipse in x and y */
-  boxextent_ellipse(x, y, cxx, cyy, cxy, r, im->w, im->h,
-                    &xmin, &xmax, &ymin, &ymax, flag);
+  boxextent_ellipse(
+      x, y, cxx, cyy, cxy, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag
+  );
 
   /* loop over rows in the box */
-  for (iy=ymin; iy<ymax; iy++)
-    {
-      /* set pointers to the start of this row */
-      pos = (iy % im->h) * im->w + xmin;
-      datat = MSVC_VOID_CAST im->data + pos*size;
-      if (im->mask)
-        maskt = MSVC_VOID_CAST im->mask + pos*msize;
-      if (im->segmap)
-        segt = MSVC_VOID_CAST im->segmap + pos*ssize;
+  for (iy = ymin; iy < ymax; iy++) {
+    /* set pointers to the start of this row */
+    pos = (iy % im->h) * im->w + xmin;
+    datat = MSVC_VOID_CAST im->data + pos * size;
+    if (im->mask) {
+      maskt = MSVC_VOID_CAST im->mask + pos * msize;
+    }
+    if (im->segmap) {
+      segt = MSVC_VOID_CAST im->segmap + pos * ssize;
+    }
 
-      /* loop over pixels in this row */
-      for (ix=xmin; ix<xmax; ix++)
-        {
-          dx = ix - x;
-          dy = iy - y;
-          rpix2 = cxx*dx*dx + cyy*dy*dy + cxy*dx*dy;
-          if (rpix2 <= r2)
-            {
-              pix = convert(datat);
-              ismasked = 0;
-              if ((pix < -BIG) || (im->mask && mconvert(maskt) > im->maskthresh))
-                ismasked = 1;
-
-              /* Segmentation image:
-
-    	           If `id` is negative, require segmented pixels within the
-    	           aperture.
-
-    	           If `id` is positive, mask pixels with nonzero segment ids
-    	           not equal to `id`.
-
-    	      */
-    	      if (im->segmap)
-      	        {
-      	          if (id > 0)
-      	            {
-      	              if ((sconvert(segt) > 0.) & (sconvert(segt) != id))
-      	                {
-      	                  ismasked = 1;
-      	                }
-      	            } else {
-    	              if (sconvert(segt) != -1*id)
-    	                {
-    	                  ismasked = 1;
-    	                }
-      	            }
-      	        }
-
-              if (ismasked > 0)
-                {
-                  *flag |= SEP_APER_HASMASKED;
-                }
-              else
-                {
-                  r1 += sqrt(rpix2)*pix;
-                  v1 += pix;
-                  area++;
-                }
+    /* loop over pixels in this row */
+    for (ix = xmin; ix < xmax; ix++) {
+      dx = ix - x;
+      dy = iy - y;
+      rpix2 = cxx * dx * dx + cyy * dy * dy + cxy * dx * dy;
+      if (rpix2 <= r2) {
+        pix = convert(datat);
+        ismasked = 0;
+        if ((pix < -BIG) || (im->mask && mconvert(maskt) > im->maskthresh)) {
+          ismasked = 1;
+        }
+
+        /* Segmentation image:
+
+             If `id` is negative, require segmented pixels within the
+             aperture.
+
+             If `id` is positive, mask pixels with nonzero segment ids
+             not equal to `id`.
+
+        */
+        if (im->segmap) {
+          if (id > 0) {
+            if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) {
+              ismasked = 1;
             }
+          } else {
+            if (sconvert(segt) != -1 * id) {
+              ismasked = 1;
+            }
+          }
+        }
 
-          /* increment pointers by one element */
-          datat += size;
-          maskt += msize;
-          segt += ssize;
+        if (ismasked > 0) {
+          *flag |= SEP_APER_HASMASKED;
+        } else {
+          r1 += sqrt(rpix2) * pix;
+          v1 += pix;
+          area++;
         }
-    }
+      }
 
-  if (area == 0)
-    {
-      *flag |= SEP_APER_ALLMASKED;
-      *kronrad = 0.0;
-    }
-  else if (r1 <= 0.0 || v1 <= 0.0)
-    {
-      *flag |= SEP_APER_NONPOSITIVE;
-      *kronrad = 0.0;
-    }
-  else
-    {
-      *kronrad = r1 / v1;
+      /* increment pointers by one element */
+      datat += size;
+      maskt += msize;
+      segt += ssize;
     }
+  }
+
+  if (area == 0) {
+    *flag |= SEP_APER_ALLMASKED;
+    *kronrad = 0.0;
+  } else if (r1 <= 0.0 || v1 <= 0.0) {
+    *flag |= SEP_APER_NONPOSITIVE;
+    *kronrad = 0.0;
+  } else {
+    *kronrad = r1 / v1;
+  }
 
   return RETURN_OK;
 }
 
 
 /* set array values within an ellipse (uc = unsigned char array) */
-void sep_set_ellipse(unsigned char *arr, int w, int h,
-                     double x, double y, double cxx, double cyy, double cxy,
-                     double r, unsigned char val)
-{
-  unsigned char *arrt;
-  int xmin, xmax, ymin, ymax, xi, yi;
+void sep_set_ellipse(
+    unsigned char * arr,
+    int64_t w,
+    int64_t h,
+    double x,
+    double y,
+    double cxx,
+    double cyy,
+    double cxy,
+    double r,
+    unsigned char val
+) {
+  unsigned char * arrt;
+  int64_t xmin, xmax, ymin, ymax, xi, yi;
   double r2, dx, dy, dy2;
   short flag; /* not actually used, but input to boxextent */
 
   flag = 0;
-  r2 = r*r;
-
-  boxextent_ellipse(x, y, cxx, cyy, cxy, r, w, h,
-                    &xmin, &xmax, &ymin, &ymax, &flag);
-
-  for (yi=ymin; yi<ymax; yi++)
-    {
-      arrt = arr + (yi*w + xmin);
-      dy = yi - y;
-      dy2 = dy*dy;
-      for (xi=xmin; xi<xmax; xi++, arrt++)
-        {
-          dx = xi - x;
-          if ((cxx*dx*dx + cyy*dy2 + cxy*dx*dy) <= r2)
-            *arrt = val;
-        }
+  r2 = r * r;
+
+  boxextent_ellipse(x, y, cxx, cyy, cxy, r, w, h, &xmin, &xmax, &ymin, &ymax, &flag);
+
+  for (yi = ymin; yi < ymax; yi++) {
+    arrt = arr + (yi * w + xmin);
+    dy = yi - y;
+    dy2 = dy * dy;
+    for (xi = xmin; xi < xmax; xi++, arrt++) {
+      dx = xi - x;
+      if ((cxx * dx * dx + cyy * dy2 + cxy * dx * dy) <= r2) {
+        *arrt = val;
+      }
     }
+  }
 }
 
 /*****************************************************************************/
@@ -779,27 +824,37 @@ void sep_set_ellipse(unsigned char *arr, int w, int h,
  *
  */
 
-int sep_windowed(const sep_image *im,
-                 double x, double y, double sig, int subpix, short inflag,
-                 double *xout, double *yout, int *niter, short *flag)
-{
+int sep_windowed(
+    const sep_image * im,
+    double x,
+    double y,
+    double sig,
+    int subpix,
+    short inflag,
+    double * xout,
+    double * yout,
+    int * niter,
+    short * flag
+) {
   PIXTYPE pix, varpix;
   double dx, dy, dx1, dy2, offset, scale, scale2, tmp, dxpos, dypos, weight;
   double maskarea, maskweight, maskdxpos, maskdypos;
   double r, tv, twv, sigtv, totarea, overlap, rpix2, invtwosig2;
   double wpix;
-  int i, ix, iy, xmin, xmax, ymin, ymax, sx, sy, status, size, esize, msize;
-  long pos;
+  int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, pos, size, esize, msize;
+  int i, status;
   short errisarray, errisstd;
   const BYTE *datat, *errort, *maskt;
   converter convert, econvert, mconvert;
   double r2, r_in2, r_out2;
 
   /* input checks */
-  if (sig < 0.0)
+  if (sig < 0.0) {
     return ILLEGAL_APER_PARAMS;
-  if (subpix < 0)
+  }
+  if (subpix < 0) {
     return ILLEGAL_SUBPIX;
+  }
 
   /* initializations */
   size = esize = msize = 0;
@@ -809,193 +864,182 @@ int sep_windowed(const sep_image *im,
   errort = im->noise;
   *flag = 0;
   varpix = 0.0;
-  scale = 1.0/subpix;
-  scale2 = scale*scale;
-  offset = 0.5*(scale-1.0);
-  invtwosig2 = 1.0/(2.0*sig*sig);
+  scale = 1.0 / subpix;
+  scale2 = scale * scale;
+  offset = 0.5 * (scale - 1.0);
+  invtwosig2 = 1.0 / (2.0 * sig * sig);
   errisarray = 0;
   errisstd = 0;
 
   /* Integration radius */
-  r = WINPOS_NSIG*sig;
+  r = WINPOS_NSIG * sig;
 
   /* calculate oversampled annulus */
-  r2 = r*r;
+  r2 = r * r;
   oversamp_ann_circle(r, &r_in2, &r_out2);
 
   /* get data converter(s) for input array(s) */
-  if ((status = get_converter(im->dtype, &convert, &size)))
+  if ((status = get_converter(im->dtype, &convert, &size))) {
     return status;
-  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
+  }
+  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) {
     return status;
+  }
 
   /* get image noise */
-  if (im->noise_type != SEP_NOISE_NONE)
-    {
-      errisstd = (im->noise_type == SEP_NOISE_STDDEV);
-      if (im->noise)
-        {
-          errisarray = 1;
-          if ((status = get_converter(im->ndtype, &econvert, &esize)))
-            return status;
-        }
-      else
-        {
-          varpix = (errisstd)?  im->noiseval * im->noiseval: im->noiseval;
-        }
+  if (im->noise_type != SEP_NOISE_NONE) {
+    errisstd = (im->noise_type == SEP_NOISE_STDDEV);
+    if (im->noise) {
+      errisarray = 1;
+      if ((status = get_converter(im->ndtype, &econvert, &esize))) {
+        return status;
+      }
+    } else {
+      varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval;
     }
+  }
 
   /* iteration loop */
-  for (i=0; i<WINPOS_NITERMAX; i++)
-    {
-
-      /* get extent of box */
-      boxextent(x, y, r, r, im->w, im->h,
-                &xmin, &xmax, &ymin, &ymax, flag);
-
-      /* TODO: initialize values */
-      //mx2ph
-      //my2ph
-      // esum, emxy, emx2, emy2, mx2, my2, mxy
-      tv = twv = sigtv = 0.0;
-      overlap = totarea = maskarea = maskweight = 0.0;
-      dxpos = dypos = 0.0;
-      maskdxpos = maskdypos = 0.0;
-
-      /* loop over rows in the box */
-      for (iy=ymin; iy<ymax; iy++)
-        {
-          /* set pointers to the start of this row */
-          pos = (iy % im->h) * im->w + xmin;
-          datat = MSVC_VOID_CAST im->data + pos*size;
-          if (errisarray)
-            errort = MSVC_VOID_CAST im->noise + pos*esize;
-          if (im->mask)
-            maskt = MSVC_VOID_CAST im->mask + pos*msize;
-
-          /* loop over pixels in this row */
-          for (ix=xmin; ix<xmax; ix++)
-            {
-              dx = ix - x;
-              dy = iy - y;
-              rpix2 = dx*dx + dy*dy;
-              if (rpix2 < r_out2)
-                {
-                  if (rpix2 > r_in2)  /* might be partially in aperture */
-                    {
-                      if (subpix == 0)
-                        overlap = circoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5,
-                                              r);
-                      else
-                        {
-                          dx += offset;
-                          dy += offset;
-                          overlap = 0.0;
-                          for (sy=subpix; sy--; dy+=scale)
-                            {
-                              dx1 = dx;
-                              dy2 = dy*dy;
-                              for (sx=subpix; sx--; dx1+=scale)
-                                if (dx1*dx1 + dy2 < r2)
-                                  overlap += scale2;
-                            }
-                        }
-                    }
-                  else
-                    /* definitely fully in aperture */
-                    overlap = 1.0;
-
-                  /* get pixel value and variance value */
-                  pix = convert(datat);
-                  if (errisarray)
-                    {
-                      varpix = econvert(errort);
-                      if (errisstd)
-                        varpix *= varpix;
-                    }
-
-                  /* offset of this pixel from center */
-                  dx = ix - x;
-                  dy = iy - y;
-
-                  /* weight by gaussian */
-                  weight = exp(-rpix2*invtwosig2);
-
-                  if (im->mask && (mconvert(maskt) > im->maskthresh))
-                    {
-                      *flag |= SEP_APER_HASMASKED;
-                      maskarea += overlap;
-                      maskweight += overlap * weight;
-                      maskdxpos += overlap * weight * dx;
-                      maskdypos += overlap * weight * dy;
-                    }
-                  else
-                    {
-                      tv += pix * overlap;
-                      wpix = pix * overlap * weight;
-                      twv += wpix;
-                      dxpos += wpix * dx;
-                      dypos += wpix * dy;
-                    }
-
-                  totarea += overlap;
-
-                } /* closes "if pixel might be within aperture" */
-
-              /* increment pointers by one element */
-              datat += size;
-              if (errisarray)
-                errort += esize;
-              maskt += msize;
-            } /* closes loop over x */
-        } /* closes loop over y */
-
-      /* we're done looping over pixels for this iteration.
-       * Our summary statistics are:
-       *
-       * tv : total value
-       * twv : total weighted value
-       * dxpos : weighted dx
-       * dypos : weighted dy
-       */
-
-      /* Correct for masked values: This effectively makes it as if
-       * the masked pixels had the value of the average unmasked value
-       * in the aperture.
-       */
-      if (im->mask)
-        {
-          /* this option will probably not yield accurate values */
-          if (inflag & SEP_MASK_IGNORE)
-            totarea -= maskarea;
-          else
-            {
-              tmp = tv/(totarea-maskarea); /* avg unmasked pixel value */
-              twv += tmp * maskweight;
-              dxpos += tmp * maskdxpos;
-              dypos += tmp * maskdypos;
+  for (i = 0; i < WINPOS_NITERMAX; i++) {
+    /* get extent of box */
+    boxextent(x, y, r, r, im->w, im->h, &xmin, &xmax, &ymin, &ymax, flag);
+
+    /* TODO: initialize values */
+    // mx2ph
+    // my2ph
+    //  esum, emxy, emx2, emy2, mx2, my2, mxy
+    tv = twv = sigtv = 0.0;
+    overlap = totarea = maskarea = maskweight = 0.0;
+    dxpos = dypos = 0.0;
+    maskdxpos = maskdypos = 0.0;
+
+    /* loop over rows in the box */
+    for (iy = ymin; iy < ymax; iy++) {
+      /* set pointers to the start of this row */
+      pos = (iy % im->h) * im->w + xmin;
+      datat = MSVC_VOID_CAST im->data + pos * size;
+      if (errisarray) {
+        errort = MSVC_VOID_CAST im->noise + pos * esize;
+      }
+      if (im->mask) {
+        maskt = MSVC_VOID_CAST im->mask + pos * msize;
+      }
+
+      /* loop over pixels in this row */
+      for (ix = xmin; ix < xmax; ix++) {
+        dx = ix - x;
+        dy = iy - y;
+        rpix2 = dx * dx + dy * dy;
+        if (rpix2 < r_out2) {
+          if (rpix2 > r_in2) /* might be partially in aperture */ {
+            if (subpix == 0) {
+              overlap = circoverlap(dx - 0.5, dy - 0.5, dx + 0.5, dy + 0.5, r);
+            } else {
+              dx += offset;
+              dy += offset;
+              overlap = 0.0;
+              for (sy = subpix; sy--; dy += scale) {
+                dx1 = dx;
+                dy2 = dy * dy;
+                for (sx = subpix; sx--; dx1 += scale) {
+                  if (dx1 * dx1 + dy2 < r2) {
+                    overlap += scale2;
+                  }
+                }
+              }
             }
-        }
+          } else {
+            /* definitely fully in aperture */
+            overlap = 1.0;
+          }
+
+          /* get pixel value and variance value */
+          pix = convert(datat);
+          if (errisarray) {
+            varpix = econvert(errort);
+            if (errisstd) {
+              varpix *= varpix;
+            }
+          }
 
-      /* update center */
-      if (twv>0.0)
-        {
-          x += (dxpos /= twv) * WINPOS_FAC;
-          y += (dypos /= twv) * WINPOS_FAC;
+          /* offset of this pixel from center */
+          dx = ix - x;
+          dy = iy - y;
+
+          /* weight by gaussian */
+          weight = exp(-rpix2 * invtwosig2);
+
+          if (im->mask && (mconvert(maskt) > im->maskthresh)) {
+            *flag |= SEP_APER_HASMASKED;
+            maskarea += overlap;
+            maskweight += overlap * weight;
+            maskdxpos += overlap * weight * dx;
+            maskdypos += overlap * weight * dy;
+          } else {
+            tv += pix * overlap;
+            wpix = pix * overlap * weight;
+            twv += wpix;
+            dxpos += wpix * dx;
+            dypos += wpix * dy;
+          }
+
+          totarea += overlap;
+
+        } /* closes "if pixel might be within aperture" */
+
+        /* increment pointers by one element */
+        datat += size;
+        if (errisarray) {
+          errort += esize;
         }
-      else
-        break;
+        maskt += msize;
+      } /* closes loop over x */
+    } /* closes loop over y */
+
+    /* we're done looping over pixels for this iteration.
+     * Our summary statistics are:
+     *
+     * tv : total value
+     * twv : total weighted value
+     * dxpos : weighted dx
+     * dypos : weighted dy
+     */
+
+    /* Correct for masked values: This effectively makes it as if
+     * the masked pixels had the value of the average unmasked value
+     * in the aperture.
+     */
+    if (im->mask) {
+      /* this option will probably not yield accurate values */
+      if (inflag & SEP_MASK_IGNORE) {
+        totarea -= maskarea;
+      } else {
+        tmp = tv / (totarea - maskarea); /* avg unmasked pixel value */
+        twv += tmp * maskweight;
+        dxpos += tmp * maskdxpos;
+        dypos += tmp * maskdypos;
+      }
+    }
 
-      /* Stop here if position does not change */
-      if (dxpos*dxpos+dypos*dypos < WINPOS_STEPMIN*WINPOS_STEPMIN)
-        break;
+    /* update center */
+    if (twv > 0.0) {
+      x += (dxpos /= twv) * WINPOS_FAC;
+      y += (dypos /= twv) * WINPOS_FAC;
+    } else {
+      break;
+    }
+
+    /* Stop here if position does not change */
+    if (dxpos * dxpos + dypos * dypos < WINPOS_STEPMIN * WINPOS_STEPMIN) {
+      break;
+    }
 
-    } /* closes loop over interations */
+  } /* closes loop over interations */
 
   /* assign output results */
   *xout = x;
   *yout = y;
-  *niter = i+1;
+  *niter = i + 1;
 
   return status;
 }
diff --git a/src/aperture.i b/src/aperture.i
index fdfcb52..53bd089 100644
--- a/src/aperture.i
+++ b/src/aperture.i
@@ -1,24 +1,32 @@
 /*
-	Adding (void *) pointers is a GNU C extension, not part of standard C.
-	When compiling on Windows with MS Visual C compiler need to cast the
-	(void *) to something the size of one byte.
+        Adding (void *) pointers is a GNU C extension, not part of standard C.
+        When compiling on Windows with MS Visual C compiler need to cast the
+        (void *) to something the size of one byte.
 */
 #if defined(_MSC_VER)
-	#define MSVC_VOID_CAST (char *)
+#define MSVC_VOID_CAST (char *)
 #else
-  	#define MSVC_VOID_CAST
+#define MSVC_VOID_CAST
 #endif
 
-int APER_NAME(const sep_image *im,
-	      double x, double y, APER_ARGS, int id, int subpix, short inflag,
-	      double *sum, double *sumerr, double *area, short *flag)
-{
+int APER_NAME(
+    const sep_image * im,
+    double x,
+    double y,
+    APER_ARGS,
+    int id,
+    int subpix,
+    short inflag,
+    double * sum,
+    double * sumerr,
+    double * area,
+    short * flag
+) {
   PIXTYPE pix, varpix;
   double dx, dy, dx1, dy2, offset, scale, scale2, tmp;
   double tv, sigtv, totarea, maskarea, overlap, rpix2;
-  int ix, iy, xmin, xmax, ymin, ymax, sx, sy, status, size, esize, msize, ssize;
-  int ismasked;
-  long pos;
+  int64_t ix, iy, xmin, xmax, ymin, ymax, sx, sy, pos, size, esize, msize, ssize;
+  int ismasked, status;
   short errisarray, errisstd;
   const BYTE *datat, *errort, *maskt, *segt;
   converter convert, econvert, mconvert, sconvert;
@@ -26,8 +34,9 @@ int APER_NAME(const sep_image *im,
 
   /* input checks */
   APER_CHECKS;
-  if (subpix < 0)
+  if (subpix < 0) {
     return ILLEGAL_SUBPIX;
+  }
 
   /* initializations */
   size = esize = msize = ssize = 0;
@@ -37,168 +46,157 @@ int APER_NAME(const sep_image *im,
   errort = im->noise;
   *flag = 0;
   varpix = 0.0;
-  scale = 1.0/subpix;
-  scale2 = scale*scale;
-  offset = 0.5*(scale-1.0);
+  scale = 1.0 / subpix;
+  scale2 = scale * scale;
+  offset = 0.5 * (scale - 1.0);
   errisarray = 0;
   errisstd = 0;
 
   APER_INIT;
 
   /* get data converter(s) for input array(s) */
-  if ((status = get_converter(im->dtype, &convert, &size)))
+  if ((status = get_converter(im->dtype, &convert, &size))) {
     return status;
-  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
+  }
+  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize))) {
     return status;
+  }
 
-  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize)))
+  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize))) {
     return status;
+  }
 
   /* get image noise */
-  if (im->noise_type != SEP_NOISE_NONE)
-    {
-      errisstd = (im->noise_type == SEP_NOISE_STDDEV);
-      if (im->noise)
-        {
-          errisarray = 1;
-          if ((status = get_converter(im->ndtype, &econvert, &esize)))
-             return status;
-        }
-      else
-        {
-          varpix = (errisstd)?  im->noiseval * im->noiseval: im->noiseval;
-        }
+  if (im->noise_type != SEP_NOISE_NONE) {
+    errisstd = (im->noise_type == SEP_NOISE_STDDEV);
+    if (im->noise) {
+      errisarray = 1;
+      if ((status = get_converter(im->ndtype, &econvert, &esize))) {
+        return status;
+      }
+    } else {
+      varpix = (errisstd) ? im->noiseval * im->noiseval : im->noiseval;
     }
+  }
 
   /* get extent of box */
   APER_BOXEXTENT;
 
   /* loop over rows in the box */
-  for (iy=ymin; iy<ymax; iy++)
-    {
-      /* set pointers to the start of this row */
-      pos = (iy%im->h) * im->w + xmin;
-      datat = MSVC_VOID_CAST im->data + pos*size;
-      if (errisarray)
-	errort = MSVC_VOID_CAST im->noise + pos*esize;
-      if (im->mask)
-	maskt = MSVC_VOID_CAST im->mask + pos*msize;
-      if (im->segmap)
-  	segt = MSVC_VOID_CAST im->segmap + pos*ssize;
-
-      /* loop over pixels in this row */
-      for (ix=xmin; ix<xmax; ix++)
-	{
-	  dx = ix - x;
-	  dy = iy - y;
-	  rpix2 = APER_RPIX2;
-	  if (APER_COMPARE1)
-	    {
-	      if (APER_COMPARE2)  /* might be partially in aperture */
-		{
-		  if (subpix == 0)
-		    overlap = APER_EXACT;
-		  else
-		    {
-		      dx += offset;
-		      dy += offset;
-		      overlap = 0.0;
-		      for (sy=subpix; sy--; dy+=scale)
-			{
-			  dx1 = dx;
-			  dy2 = dy*dy;
-			  for (sx=subpix; sx--; dx1+=scale)
-			    {
-			      rpix2 = APER_RPIX2_SUBPIX;
-			      if (APER_COMPARE3)
-				overlap += scale2;
-			    }
-			}
-		    }
-		}
-	      else
-		/* definitely fully in aperture */
-		overlap = 1.0;
-
-	      pix = convert(datat);
-
-	      if (errisarray)
-		{
-		  varpix = econvert(errort);
-		  if (errisstd)
-		    varpix *= varpix;
-		}
-
-              ismasked = 0;
-	      if (im->mask && (mconvert(maskt) > im->maskthresh))
-	        {
-	          ismasked = 1;
-	        }
-
-	      /* Segmentation image:
-
-	           If `id` is negative, require segmented pixels within the
-	           aperture.
-
-	           If `id` is positive, mask pixels with nonzero segment ids
-	           not equal to `id`.
-
-	      */
-	      if (im->segmap)
-  	        {
-  	          if (id > 0)
-  	            {
-  	              if ((sconvert(segt) > 0.) & (sconvert(segt) != id))
-  	                {
-  	                  ismasked = 1;
-  	                }
-  	            } else {
-	              if (sconvert(segt) != -1*id)
-	                {
-	                  ismasked = 1;
-	                }
-  	            }
-  	        }
-
-	      if (ismasked > 0)
-	      	{
-		  *flag |= SEP_APER_HASMASKED;
-		  maskarea += overlap;
-		}
-	      else
-		{
-		  tv += pix*overlap;
-		  sigtv += varpix*overlap;
-		}
-
-	      totarea += overlap;
-
-	    } /* closes "if pixel might be within aperture" */
-
-	  /* increment pointers by one element */
-	  datat += size;
-	  if (errisarray)
-	    errort += esize;
-	  maskt += msize;
-	  segt += ssize;
-	}
+  for (iy = ymin; iy < ymax; iy++) {
+    /* set pointers to the start of this row */
+    pos = (iy % im->h) * im->w + xmin;
+    datat = MSVC_VOID_CAST im->data + pos * size;
+    if (errisarray) {
+      errort = MSVC_VOID_CAST im->noise + pos * esize;
+    }
+    if (im->mask) {
+      maskt = MSVC_VOID_CAST im->mask + pos * msize;
+    }
+    if (im->segmap) {
+      segt = MSVC_VOID_CAST im->segmap + pos * ssize;
+    }
+
+    /* loop over pixels in this row */
+    for (ix = xmin; ix < xmax; ix++) {
+      dx = ix - x;
+      dy = iy - y;
+      rpix2 = APER_RPIX2;
+      if (APER_COMPARE1) {
+        if (APER_COMPARE2) /* might be partially in aperture */ {
+          if (subpix == 0) {
+            overlap = APER_EXACT;
+          } else {
+            dx += offset;
+            dy += offset;
+            overlap = 0.0;
+            for (sy = subpix; sy--; dy += scale) {
+              dx1 = dx;
+              dy2 = dy * dy;
+              for (sx = subpix; sx--; dx1 += scale) {
+                rpix2 = APER_RPIX2_SUBPIX;
+                if (APER_COMPARE3) {
+                  overlap += scale2;
+                }
+              }
+            }
+          }
+        } else {
+          /* definitely fully in aperture */
+          overlap = 1.0;
+        }
+
+        pix = convert(datat);
+
+        if (errisarray) {
+          varpix = econvert(errort);
+          if (errisstd) {
+            varpix *= varpix;
+          }
+        }
+
+        ismasked = 0;
+        if (im->mask && (mconvert(maskt) > im->maskthresh)) {
+          ismasked = 1;
+        }
+
+        /* Segmentation image:
+
+            If `id` is negative, require segmented pixels within the
+            aperture.
+
+            If `id` is positive, mask pixels with nonzero segment ids
+            not equal to `id`.
+
+        */
+        if (im->segmap) {
+          if (id > 0) {
+            if ((sconvert(segt) > 0.) && (sconvert(segt) != id)) {
+              ismasked = 1;
+            }
+          } else {
+            if (sconvert(segt) != -1 * id) {
+              ismasked = 1;
+            }
+          }
+        }
+
+        if (ismasked > 0) {
+          *flag |= SEP_APER_HASMASKED;
+          maskarea += overlap;
+        } else {
+          tv += pix * overlap;
+          sigtv += varpix * overlap;
+        }
+
+        totarea += overlap;
+
+      } /* closes "if pixel might be within aperture" */
+
+      /* increment pointers by one element */
+      datat += size;
+      if (errisarray) {
+        errort += esize;
+      }
+      maskt += msize;
+      segt += ssize;
     }
+  }
 
   /* correct for masked values */
-  if (im->mask)
-    {
-      if (inflag & SEP_MASK_IGNORE)
-	totarea -= maskarea;
-      else
-	{
-	  tv *= (tmp = totarea/(totarea-maskarea));
-	  sigtv *= tmp;
-	}
+  if (im->mask) {
+    if (inflag & SEP_MASK_IGNORE) {
+      totarea -= maskarea;
+    } else {
+      tv *= (tmp = totarea / (totarea - maskarea));
+      sigtv *= tmp;
     }
+  }
 
   /* add poisson noise, only if gain > 0 */
-  if (im->gain > 0.0 && tv>0.0)
+  if (im->gain > 0.0 && tv > 0.0) {
     sigtv += tv / im->gain;
+  }
 
   *sum = tv;
   *sumerr = sqrt(sigtv);
diff --git a/src/background.c b/src/background.c
index cf88e18..ddd1c60 100644
--- a/src/background.c
+++ b/src/background.c
@@ -1,81 +1,106 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
 #include "sep.h"
 #include "sepcore.h"
 
-#define	BACK_MINGOODFRAC   0.5   /* min frac with good weights*/
-#define	QUANTIF_NSIGMA     5     /* histogram limits */
-#define	QUANTIF_NMAXLEVELS 4096  /* max nb of quantif. levels */
-#define	QUANTIF_AMIN       4     /* min nb of "mode pixels" */
+#define BACK_MINGOODFRAC 0.5 /* min frac with good weights*/
+#define QUANTIF_NSIGMA 5 /* histogram limits */
+#define QUANTIF_NMAXLEVELS 4096 /* max nb of quantif. levels */
+#define QUANTIF_AMIN 4 /* min nb of "mode pixels" */
 
 /* Background info in a single mesh*/
 typedef struct {
-  float	 mode, mean, sigma;	/* Background mode, mean and sigma */
-  LONG	 *histo;	       	/* Pointer to a histogram */
-  int	 nlevels;		/* Nb of histogram bins */
-  float	 qzero, qscale;		/* Position of histogram */
-  float	 lcut, hcut;		/* Histogram cuts */
-  int	 npix;			/* Number of pixels involved */
+  float mode, mean, sigma; /* Background mode, mean and sigma */
+  int64_t * histo; /* Pointer to a histogram */
+  int nlevels; /* Nb of histogram bins */
+  float qzero, qscale; /* Position of histogram */
+  float lcut, hcut; /* Histogram cuts */
+  int64_t npix; /* Number of pixels involved */
 } backstruct;
 
 /* internal helper functions */
-void backhisto(backstruct *backmesh,
-	       const PIXTYPE *buf, const PIXTYPE *wbuf, int bufsize,
-	       int n, int w, int bw, PIXTYPE maskthresh);
-void backstat(backstruct *backmesh,
-	      const PIXTYPE *buf, const PIXTYPE *wbuf, int bufsize,
-	      int n, int w, int bw, PIXTYPE maskthresh);
-int filterback(sep_bkg *bkg, int fw, int fh, double fthresh);
-float backguess(backstruct *bkg, float *mean, float *sigma);
-int makebackspline(const sep_bkg *bkg, float *map, float *dmap);
-
-
-int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
-                   double fthresh, sep_bkg **bkg)
-{
+void backhisto(
+    backstruct * backmesh,
+    const PIXTYPE * buf,
+    const PIXTYPE * wbuf,
+    int64_t bufsize,
+    int64_t n,
+    int64_t w,
+    int64_t bw,
+    PIXTYPE maskthresh
+);
+void backstat(
+    backstruct * backmesh,
+    const PIXTYPE * buf,
+    const PIXTYPE * wbuf,
+    int64_t bufsize,
+    int64_t n,
+    int64_t w,
+    int64_t bw,
+    PIXTYPE maskthresh
+);
+int filterback(sep_bkg * bkg, int64_t fw, int64_t fh, double fthresh);
+float backguess(backstruct * bkg, float * mean, float * sigma);
+int makebackspline(const sep_bkg * bkg, float * map, float * dmap);
+
+
+int sep_background(
+    const sep_image * image,
+    int64_t bw,
+    int64_t bh,
+    int64_t fw,
+    int64_t fh,
+    double fthresh,
+    sep_bkg ** bkg
+) {
   const BYTE *imt, *maskt;
-  int npix;                   /* size of image */
-  int nx, ny, nb;             /* number of background boxes in x, y, total */
-  int bufsize;                /* size of a "row" of boxes in pixels (w*bh) */
-  int elsize;                 /* size (in bytes) of an image array element */
-  int melsize;                /* size (in bytes) of a mask array element */
+  int64_t npix; /* size of image */
+  int64_t nx, ny, nb; /* number of background boxes in x, y, total */
+  int64_t bufsize; /* size of a "row" of boxes in pixels (w*bh) */
+  int64_t elsize; /* size (in bytes) of an image array element */
+  int64_t melsize; /* size (in bytes) of a mask array element */
   PIXTYPE *buf, *mbuf;
   const PIXTYPE *buft, *mbuft;
   PIXTYPE maskthresh;
   array_converter convert, mconvert;
-  backstruct *backmesh, *bm;  /* info about each background "box" */
-  sep_bkg *bkgout;          /* output */
-  int j,k,m, status;
+  backstruct *backmesh, *bm; /* info about each background "box" */
+  sep_bkg * bkgout; /* output */
+  int64_t j, k, m;
+  int status;
 
   status = RETURN_OK;
   npix = image->w * image->h;
   bufsize = image->w * bh;
   maskthresh = image->maskthresh;
-  if (image->mask == NULL) maskthresh = 0.0;
+  if (image->mask == NULL) {
+    maskthresh = 0.0;
+  }
 
   backmesh = bm = NULL;
   bkgout = NULL;
@@ -84,11 +109,13 @@ int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
   convert = mconvert = NULL;
 
   /* determine number of background boxes */
-  if ((nx = (image->w - 1) / bw + 1) < 1)
+  if ((nx = (image->w - 1) / bw + 1) < 1) {
     nx = 1;
-  if ((ny = (image->h - 1) / bh + 1) < 1)
+  }
+  if ((ny = (image->h - 1) / bh + 1) < 1) {
     ny = 1;
-  nb = nx*ny;
+  }
+  nb = nx * ny;
 
   /* Allocate temp memory & initialize */
   QCALLOC(backmesh, backstruct, nx, status);
@@ -118,31 +145,32 @@ int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
 
   /* get the correct array converter and element size, based on dtype code */
   status = get_array_converter(image->dtype, &convert, &elsize);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
-  if (image->mask)
-    {
-      status = get_array_converter(image->mdtype, &mconvert, &melsize);
-      if (status != RETURN_OK)
-	goto exit;
+  }
+  if (image->mask) {
+    status = get_array_converter(image->mdtype, &mconvert, &melsize);
+    if (status != RETURN_OK) {
+      goto exit;
     }
+  }
 
   /* If the input array type is not PIXTYPE, allocate a buffer to hold
      converted values */
-  if (image->dtype != PIXDTYPE)
-    {
-      QMALLOC(buf, PIXTYPE, bufsize, status);
-      buft = buf;
-      if (status != RETURN_OK)
-	goto exit;
+  if (image->dtype != PIXDTYPE) {
+    QMALLOC(buf, PIXTYPE, bufsize, status);
+    buft = buf;
+    if (status != RETURN_OK) {
+      goto exit;
     }
-  if (image->mask && (image->mdtype != PIXDTYPE))
-    {
-      QMALLOC(mbuf, PIXTYPE, bufsize, status);
-      mbuft = mbuf;
-      if (status != RETURN_OK)
-	goto exit;
+  }
+  if (image->mask && (image->mdtype != PIXDTYPE)) {
+    QMALLOC(mbuf, PIXTYPE, bufsize, status);
+    mbuft = mbuf;
+    if (status != RETURN_OK) {
+      goto exit;
     }
+  }
 
   /* loop over rows of background boxes.
    * (here, we could loop over individual boxes rather than entire
@@ -151,54 +179,57 @@ int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
    * because the pixel buffers are only read in from disk in
    * increments of a row of background boxes at a time.)
    */
-  for (j=0; j<ny; j++)
-    {
-      /* if the last row, modify the width appropriately*/
-      if (j == ny-1 && npix%bufsize)
-        bufsize = npix%bufsize;
-
-      /* convert this row to PIXTYPE and store in buffer(s)*/
-      if (image->dtype != PIXDTYPE)
-	convert(imt, bufsize, buf);
-      else
-	buft = (const PIXTYPE *)imt;
-
-      if (image->mask)
-	{
-	  if (image->mdtype != PIXDTYPE)
-	    mconvert(maskt, bufsize, mbuf);
-	  else
-	    mbuft = (const PIXTYPE *)maskt;
-	}
-
-      /* Get clipped mean, sigma for all boxes in the row */
-      backstat(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh);
-
-      /* Allocate histograms in each box in this row. */
-      bm = backmesh;
-      for (m=nx; m--; bm++)
-	if (bm->mean <= -BIG)
-	  bm->histo=NULL;
-	else
-	  QCALLOC(bm->histo, LONG, bm->nlevels, status);
-      backhisto(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh);
-
-      /* Compute background statistics from the histograms */
-      bm = backmesh;
-      for (m=0; m<nx; m++, bm++)
-	{
-	  k = m+nx*j;
-	  backguess(bm, bkgout->back+k, bkgout->sigma+k);
-	  free(bm->histo);
-	  bm->histo = NULL;
-	}
-
-      /* increment array pointers to next row of background boxes */
-      imt += elsize * bufsize;
-      if (image->mask)
-	maskt += melsize * bufsize;
+  for (j = 0; j < ny; j++) {
+    /* if the last row, modify the width appropriately*/
+    if (j == ny - 1 && npix % bufsize) {
+      bufsize = npix % bufsize;
+    }
+
+    /* convert this row to PIXTYPE and store in buffer(s)*/
+    if (image->dtype != PIXDTYPE) {
+      convert(imt, bufsize, buf);
+    } else {
+      buft = (const PIXTYPE *)imt;
+    }
+
+    if (image->mask) {
+      if (image->mdtype != PIXDTYPE) {
+        mconvert(maskt, bufsize, mbuf);
+      } else {
+        mbuft = (const PIXTYPE *)maskt;
+      }
+    }
+
+    /* Get clipped mean, sigma for all boxes in the row */
+    backstat(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh);
+
+    /* Allocate histograms in each box in this row. */
+    bm = backmesh;
+    for (m = nx; m--; bm++) {
+      if (bm->mean <= -BIG) {
+        bm->histo = NULL;
+      } else {
+        QCALLOC(bm->histo, int64_t, bm->nlevels, status);
+      }
+    }
+    backhisto(backmesh, buft, mbuft, bufsize, nx, image->w, bw, maskthresh);
+
+    /* Compute background statistics from the histograms */
+    bm = backmesh;
+    for (m = 0; m < nx; m++, bm++) {
+      k = m + nx * j;
+      backguess(bm, bkgout->back + k, bkgout->sigma + k);
+      free(bm->histo);
+      bm->histo = NULL;
     }
 
+    /* increment array pointers to next row of background boxes */
+    imt += elsize * bufsize;
+    if (image->mask) {
+      maskt += melsize * bufsize;
+    }
+  }
+
   /* free memory */
   free(buf);
   buf = NULL;
@@ -208,30 +239,31 @@ int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
   backmesh = NULL;
 
   /* Median-filter and check suitability of the background map */
-  if ((status = filterback(bkgout, fw, fh, fthresh)) != RETURN_OK)
+  if ((status = filterback(bkgout, fw, fh, fthresh)) != RETURN_OK) {
     goto exit;
+  }
 
   /* Compute 2nd derivatives along the y-direction */
-  if ((status = makebackspline(bkgout, bkgout->back, bkgout->dback)) !=
-      RETURN_OK)
+  if ((status = makebackspline(bkgout, bkgout->back, bkgout->dback)) != RETURN_OK) {
     goto exit;
-  if ((status = makebackspline(bkgout, bkgout->sigma, bkgout->dsigma)) !=
-      RETURN_OK)
+  }
+  if ((status = makebackspline(bkgout, bkgout->sigma, bkgout->dsigma)) != RETURN_OK) {
     goto exit;
+  }
 
   *bkg = bkgout;
   return status;
 
   /* If we encountered a problem, clean up any allocated memory */
- exit:
+exit:
   free(buf);
   free(mbuf);
-  if (backmesh)
-    {
-      bm = backmesh;
-      for (m=0; m<nx; m++, bm++)
-	free(bm->histo);
+  if (backmesh) {
+    bm = backmesh;
+    for (m = 0; m < nx; m++, bm++) {
+      free(bm->histo);
     }
+  }
   free(backmesh);
   sep_bkg_free(bkgout);
   *bkg = NULL;
@@ -242,270 +274,276 @@ int sep_background(const sep_image* image, int bw, int bh, int fw, int fh,
 /*
 Compute robust statistical estimators in a row of meshes.
 */
-void backstat(backstruct *backmesh,
-	      const PIXTYPE *buf, const PIXTYPE *wbuf, int bufsize,
-	      int n, int w, int bw, PIXTYPE maskthresh)
-{
-  backstruct	*bm;
-  double	pix, wpix, sig, mean, sigma, step;
-  const PIXTYPE	*buft,*wbuft;
-  PIXTYPE       lcut,hcut;
-  int		m,h,x,y, npix,wnpix, offset, lastbite;
-
-  h = bufsize/w;  /* height of background boxes in this row */
+void backstat(
+    backstruct * backmesh,
+    const PIXTYPE * buf,
+    const PIXTYPE * wbuf,
+    int64_t bufsize,
+    int64_t n,
+    int64_t w,
+    int64_t bw,
+    PIXTYPE maskthresh
+) {
+  backstruct * bm;
+  double pix, wpix, sig, mean, sigma, step;
+  const PIXTYPE *buft, *wbuft;
+  PIXTYPE lcut, hcut;
+  int64_t m, h, x, y, npix, wnpix, offset, lastbite;
+
+  h = bufsize / w; /* height of background boxes in this row */
   bm = backmesh;
   offset = w - bw;
-  step = sqrt(2/PI)*QUANTIF_NSIGMA/QUANTIF_AMIN;
-
-  for (m = n; m--; bm++,buf+=bw)
-    {
-      if (!m && (lastbite=w%bw))
-	{
-	  bw = lastbite;
-	  offset = w-bw;
-	}
-
-      mean = sigma = 0.0;
-      buft=buf;
-      npix = 0;
-
-      /* We separate the weighted case at this level to avoid penalty in CPU */
-      if (wbuf)
-	{
-	  wbuft = wbuf;
-	  for (y=h; y--; buft+=offset,wbuft+=offset)
-	    for (x=bw; x--;)
-	      {
-		pix = *(buft++);
-		if ((wpix = *(wbuft++)) <= maskthresh && pix > -BIG)
-		  {
-		    mean += pix;
-		    sigma += pix*pix;
-		    npix++;
-		  }
-	      }
-	}
-      else
-	for (y=h; y--; buft+=offset)
-	  for (x=bw; x--;)
-	    if ((pix = *(buft++)) > -BIG)
-	      {
-		mean += pix;
-		sigma += pix*pix;
-		npix++;
-	      }
-
-      /*-- If not enough valid pixels, discard this mesh */
-      if ((float)npix < (float)(bw*h*BACK_MINGOODFRAC))
-	{
-	  bm->mean = bm->sigma = -BIG;
-	  if (wbuf)
-	    wbuf += bw;
-	  continue;
-	}
-
-      mean /= (double)npix;
-      sigma = (sig = sigma/npix - mean*mean)>0.0? sqrt(sig):0.0;
-      lcut = bm->lcut = (PIXTYPE)(mean - 2.0*sigma);
-      hcut = bm->hcut = (PIXTYPE)(mean + 2.0*sigma);
-      mean = sigma = 0.0;
-      npix = wnpix = 0;
-      buft = buf;
-
-      /* do statistics for this mesh again, with cuts */
-      if (wbuf)
-	{
-	  wbuft=wbuf;
-	  for (y=h; y--; buft+=offset, wbuft+=offset)
-	    for (x=bw; x--;)
-	      {
-		pix = *(buft++);
-		if ((wpix = *(wbuft++))<=maskthresh && pix<=hcut && pix>=lcut)
-		  {
-		    mean += pix;
-		    sigma += pix*pix;
-		    npix++;
-		  }
-	      }
-	}
-      else
-	for (y=h; y--; buft+=offset)
-	  for (x=bw; x--;)
-	    {
-	      pix = *(buft++);
-	      if (pix<=hcut && pix>=lcut)
-		{
-		  mean += pix;
-		  sigma += pix*pix;
-		  npix++;
-		}
-	    }
-
-      bm->npix = npix;
-      mean /= (double)npix;
-      sig = sigma/npix - mean*mean;
-      sigma = sig>0.0 ? sqrt(sig):0.0;
-      bm->mean = mean;
-      bm->sigma = sigma;
-      if ((bm->nlevels = (int)(step*npix+1)) > QUANTIF_NMAXLEVELS)
-	bm->nlevels = QUANTIF_NMAXLEVELS;
-      bm->qscale = sigma>0.0? 2*QUANTIF_NSIGMA*sigma/bm->nlevels : 1.0;
-      bm->qzero = mean - QUANTIF_NSIGMA*sigma;
-
-      if (wbuf)
-	wbuf += bw;
+  step = sqrt(2 / PI) * QUANTIF_NSIGMA / QUANTIF_AMIN;
+
+  for (m = n; m--; bm++, buf += bw) {
+    if (!m && (lastbite = w % bw)) {
+      bw = lastbite;
+      offset = w - bw;
     }
+
+    mean = sigma = 0.0;
+    buft = buf;
+    npix = 0;
+
+    /* We separate the weighted case at this level to avoid penalty in CPU */
+    if (wbuf) {
+      wbuft = wbuf;
+      for (y = h; y--; buft += offset, wbuft += offset) {
+        for (x = bw; x--;) {
+          pix = *(buft++);
+          if ((wpix = *(wbuft++)) <= maskthresh && pix > -BIG) {
+            mean += pix;
+            sigma += pix * pix;
+            npix++;
+          }
+        }
+      }
+    } else {
+      for (y = h; y--; buft += offset) {
+        for (x = bw; x--;) {
+          if ((pix = *(buft++)) > -BIG) {
+            mean += pix;
+            sigma += pix * pix;
+            npix++;
+          }
+        }
+      }
+    }
+
+    /*-- If not enough valid pixels, discard this mesh */
+    if ((float)npix < (float)(bw * h * BACK_MINGOODFRAC)) {
+      bm->mean = bm->sigma = -BIG;
+      if (wbuf) {
+        wbuf += bw;
+      }
+      continue;
+    }
+
+    mean /= (double)npix;
+    sigma = (sig = sigma / npix - mean * mean) > 0.0 ? sqrt(sig) : 0.0;
+    lcut = bm->lcut = (PIXTYPE)(mean - 2.0 * sigma);
+    hcut = bm->hcut = (PIXTYPE)(mean + 2.0 * sigma);
+    mean = sigma = 0.0;
+    npix = wnpix = 0;
+    buft = buf;
+
+    /* do statistics for this mesh again, with cuts */
+    if (wbuf) {
+      wbuft = wbuf;
+      for (y = h; y--; buft += offset, wbuft += offset) {
+        for (x = bw; x--;) {
+          pix = *(buft++);
+          if ((wpix = *(wbuft++)) <= maskthresh && pix <= hcut && pix >= lcut) {
+            mean += pix;
+            sigma += pix * pix;
+            npix++;
+          }
+        }
+      }
+    } else {
+      for (y = h; y--; buft += offset) {
+        for (x = bw; x--;) {
+          pix = *(buft++);
+          if (pix <= hcut && pix >= lcut) {
+            mean += pix;
+            sigma += pix * pix;
+            npix++;
+          }
+        }
+      }
+    }
+
+    bm->npix = npix;
+    mean /= (double)npix;
+    sig = sigma / npix - mean * mean;
+    sigma = sig > 0.0 ? sqrt(sig) : 0.0;
+    bm->mean = mean;
+    bm->sigma = sigma;
+    if ((bm->nlevels = (int)(step * npix + 1)) > QUANTIF_NMAXLEVELS) {
+      bm->nlevels = QUANTIF_NMAXLEVELS;
+    }
+    bm->qscale = sigma > 0.0 ? 2 * QUANTIF_NSIGMA * sigma / bm->nlevels : 1.0;
+    bm->qzero = mean - QUANTIF_NSIGMA * sigma;
+
+    if (wbuf) {
+      wbuf += bw;
+    }
+  }
 }
 
 /******************************** backhisto *********************************/
 /*
 Fill histograms in a row of meshes.
 */
-void backhisto(backstruct *backmesh,
-	       const PIXTYPE *buf, const PIXTYPE *wbuf, int bufsize,
-	       int n, int w, int bw, PIXTYPE maskthresh)
-{
-  backstruct	*bm;
-  const PIXTYPE	*buft,*wbuft;
-  float	        qscale, cste, wpix;
-  LONG		*histo;
-  int		h,m,x,y, nlevels, lastbite, offset, bin;
-
-  h = bufsize/w;
+void backhisto(
+    backstruct * backmesh,
+    const PIXTYPE * buf,
+    const PIXTYPE * wbuf,
+    int64_t bufsize,
+    int64_t n,
+    int64_t w,
+    int64_t bw,
+    PIXTYPE maskthresh
+) {
+  backstruct * bm;
+  const PIXTYPE *buft, *wbuft;
+  float qscale, cste, wpix;
+  int64_t * histo;
+  int64_t h, m, x, y, nlevels, lastbite, offset, bin;
+
+  h = bufsize / w;
   bm = backmesh;
   offset = w - bw;
-  for (m=0; m++<n; bm++ , buf+=bw)
-    {
-      if (m==n && (lastbite=w%bw))
-	{
-	  bw = lastbite;
-	  offset = w-bw;
-	}
-
-      /*-- Skip bad meshes */
-      if (bm->mean <= -BIG)
-	{
-	  if (wbuf)
-	    wbuf += bw;
-	  continue;
-	}
-
-      nlevels = bm->nlevels;
-      histo = bm->histo;
-      qscale = bm->qscale;
-      cste = 0.499999 - bm->qzero/qscale;
-      buft = buf;
-
-      if (wbuf)
-	{
-	  wbuft = wbuf;
-	  for (y=h; y--; buft+=offset, wbuft+=offset)
-	    for (x=bw; x--;)
-	      {
-		bin = (int)(*(buft++)/qscale + cste);
-		if ((wpix = *(wbuft++))<=maskthresh && bin<nlevels && bin>=0)
-		  (*(histo+bin))++;
-	      }
-	  wbuf += bw;
-	}
-      else
-	for (y=h; y--; buft += offset)
-	  for (x=bw; x--;)
-	    {
-	      bin = (int)(*(buft++)/qscale + cste);
-
-	      if (bin>=0 && bin<nlevels)
-		(*(histo+bin))++;
-	    }
+  for (m = 0; m++ < n; bm++, buf += bw) {
+    if (m == n && (lastbite = w % bw)) {
+      bw = lastbite;
+      offset = w - bw;
+    }
+
+    /*-- Skip bad meshes */
+    if (bm->mean <= -BIG) {
+      if (wbuf) {
+        wbuf += bw;
+      }
+      continue;
+    }
+
+    nlevels = bm->nlevels;
+    histo = bm->histo;
+    qscale = bm->qscale;
+    cste = 0.499999 - bm->qzero / qscale;
+    buft = buf;
+
+    if (wbuf) {
+      wbuft = wbuf;
+      for (y = h; y--; buft += offset, wbuft += offset) {
+        for (x = bw; x--;) {
+          bin = (int64_t)(*(buft++) / qscale + cste);
+          if ((wpix = *(wbuft++)) <= maskthresh && bin < nlevels && bin >= 0) {
+            (*(histo + bin))++;
+          }
+        }
+      }
+      wbuf += bw;
+    } else {
+      for (y = h; y--; buft += offset) {
+        for (x = bw; x--;) {
+          bin = (int64_t)(*(buft++) / qscale + cste);
+
+          if (bin >= 0 && bin < nlevels) {
+            (*(histo + bin))++;
+          }
+        }
+      }
     }
   }
+}
 
 /******************************* backguess **********************************/
 /*
 Estimate the background from a histogram;
 */
-float backguess(backstruct *bkg, float *mean, float *sigma)
-
-#define	EPS	(1e-4)	/* a small number */
+float backguess(backstruct * bkg, float * mean, float * sigma)
+#define EPS (1e-4) /* a small number */
 
 {
-  LONG		*histo, *hilow, *hihigh, *histot;
+  int64_t *histo, *hilow, *hihigh, *histot;
   unsigned long lowsum, highsum, sum;
-  double	ftemp, mea, sig, sig1, med, dpix;
-  int		i, n, lcut,hcut, nlevelsm1, pix;
+  double ftemp, mea, sig, sig1, med, dpix;
+  int64_t i, n, lcut, hcut, nlevelsm1, pix;
 
   /* Leave here if the mesh is already classified as `bad' */
-  if (bkg->mean<=-BIG)
-    {
-      *mean = *sigma = -BIG;
-      return -BIG;
-    }
+  if (bkg->mean <= -BIG) {
+    *mean = *sigma = -BIG;
+    return -BIG;
+  }
 
   histo = bkg->histo;
-  hcut = nlevelsm1 = bkg->nlevels-1;
+  hcut = nlevelsm1 = bkg->nlevels - 1;
   lcut = 0;
 
-  sig = 10.0*nlevelsm1;
+  sig = 10.0 * nlevelsm1;
   sig1 = 1.0;
   mea = med = bkg->mean;
 
   /* iterate until sigma converges or drops below 0.1 (up to 100 iterations) */
-  for (n=100; n-- && (sig>=0.1) && (fabs(sig/sig1-1.0)>EPS);)
-    {
-      sig1 = sig;
-      sum = mea = sig = 0.0;
-      lowsum = highsum = 0;
-      histot = hilow = histo+lcut;
-      hihigh = histo+hcut;
-
-      for (i=lcut; i<=hcut; i++)
-	{
-	  if (lowsum<highsum)
-	    lowsum += *(hilow++);
-	  else
-	    highsum +=  *(hihigh--);
-	  sum += (pix = *(histot++));
-	  mea += (dpix = (double)pix*i);
-	  sig += dpix*i;
-	}
-
-      med = hihigh>=histo?((hihigh-histo) + 0.5 +
-			   ((double)highsum-lowsum)/(2.0*(*hilow>*hihigh?
-							   *hilow:*hihigh)))
-	: 0.0;
-      if (sum)
-	{
-	  mea /= (double)sum;
-	  sig = sig/sum - mea*mea;
-	}
-
-      sig = sig>0.0?sqrt(sig):0.0;
-      lcut = (ftemp=med-3.0*sig)>0.0 ?(int)(ftemp>0.0?ftemp+0.5:ftemp-0.5):0;
-      hcut = (ftemp=med+3.0*sig)<nlevelsm1 ?(int)(ftemp>0.0?ftemp+0.5:ftemp-0.5)
-	: nlevelsm1;
+  for (n = 100; n-- && (sig >= 0.1) && (fabs(sig / sig1 - 1.0) > EPS);) {
+    sig1 = sig;
+    sum = mea = sig = 0.0;
+    lowsum = highsum = 0;
+    histot = hilow = histo + lcut;
+    hihigh = histo + hcut;
+
+    for (i = lcut; i <= hcut; i++) {
+      if (lowsum < highsum) {
+        lowsum += *(hilow++);
+      } else {
+        highsum += *(hihigh--);
+      }
+      sum += (pix = *(histot++));
+      mea += (dpix = (double)pix * i);
+      sig += dpix * i;
+    }
 
+    med = hihigh >= histo ? ((hihigh - histo) + 0.5
+                             + ((double)highsum - lowsum)
+                                   / (2.0 * (*hilow > *hihigh ? *hilow : *hihigh)))
+                          : 0.0;
+    if (sum) {
+      mea /= (double)sum;
+      sig = sig / sum - mea * mea;
     }
-  *mean = fabs(sig)>0.0? (fabs(bkg->sigma/(sig*bkg->qscale)-1) < 0.0 ?
-			  bkg->qzero+mea*bkg->qscale
-			  :(fabs((mea-med)/sig)< 0.3 ?
-			    bkg->qzero+(2.5*med-1.5*mea)*bkg->qscale
-			    :bkg->qzero+med*bkg->qscale))
-    :bkg->qzero+mea*bkg->qscale;
 
-  *sigma = sig*bkg->qscale;
+    sig = sig > 0.0 ? sqrt(sig) : 0.0;
+    lcut = (ftemp = med - 3.0 * sig) > 0.0
+               ? (int64_t)(ftemp > 0.0 ? ftemp + 0.5 : ftemp - 0.5)
+               : 0;
+    hcut = (ftemp = med + 3.0 * sig) < nlevelsm1
+               ? (int64_t)(ftemp > 0.0 ? ftemp + 0.5 : ftemp - 0.5)
+               : nlevelsm1;
+  }
+  *mean = fabs(sig) > 0.0
+              ? (fabs(bkg->sigma / (sig * bkg->qscale) - 1) < 0.0
+                     ? bkg->qzero + mea * bkg->qscale
+                     : (fabs((mea - med) / sig) < 0.3
+                            ? bkg->qzero + (2.5 * med - 1.5 * mea) * bkg->qscale
+                            : bkg->qzero + med * bkg->qscale))
+              : bkg->qzero + mea * bkg->qscale;
+
+  *sigma = sig * bkg->qscale;
 
   return *mean;
 }
 
 /****************************************************************************/
 
-int filterback(sep_bkg *bkg, int fw, int fh, double fthresh)
+int filterback(sep_bkg * bkg, int64_t fw, int64_t fh, double fthresh)
 /* Median filterthe background map to remove the contribution
  * from bright sources. */
 {
-  float	*back, *sigma, *back2, *sigma2, *bmask, *smask, *sigmat;
+  float *back, *sigma, *back2, *sigma2, *bmask, *smask, *sigmat;
   float d2, d2min, med, val, sval;
-  int i, j, px, py, np, nx, ny, npx, npx2, npy, npy2, dpx, dpy, x, y, nmin;
+  int64_t i, j, px, py, np, nx, ny, npx, npx2, npy, npy2, dpx, dpy, x, y, nmin;
   int status;
 
   status = RETURN_OK;
@@ -514,120 +552,125 @@ int filterback(sep_bkg *bkg, int fw, int fh, double fthresh)
   nx = bkg->nx;
   ny = bkg->ny;
   np = bkg->n;
-  npx = fw/2;
-  npy = fh/2;
+  npx = fw / 2;
+  npy = fh / 2;
   npy *= nx;
 
-  QMALLOC(bmask, float, (2*npx+1)*(2*npy+1), status);
-  QMALLOC(smask, float, (2*npx+1)*(2*npy+1), status);
+  QMALLOC(bmask, float, (2 * npx + 1) * (2 * npy + 1), status);
+  QMALLOC(smask, float, (2 * npx + 1) * (2 * npy + 1), status);
   QMALLOC(back2, float, np, status);
   QMALLOC(sigma2, float, np, status);
 
   back = bkg->back;
   sigma = bkg->sigma;
-  val = sval = 0.0;  /* to avoid gcc -Wall warnings */
-
-/* Look for `bad' meshes and interpolate them if necessary */
-  for (i=0,py=0; py<ny; py++)
-    for (px=0; px<nx; px++,i++)
-      if ((back2[i]=back[i])<=-BIG)
-        {
-/*------ Seek the closest valid mesh */
+  val = sval = 0.0; /* to avoid gcc -Wall warnings */
+
+  /* Look for `bad' meshes and interpolate them if necessary */
+  for (i = 0, py = 0; py < ny; py++) {
+    for (px = 0; px < nx; px++, i++) {
+      if ((back2[i] = back[i]) <= -BIG) {
+        /*------ Seek the closest valid mesh */
         d2min = BIG;
-        nmin = 0.0;
-        for (j=0,y=0; y<ny; y++)
-          for (x=0; x<nx; x++,j++)
-            if (back[j]>-BIG)
-              {
-              d2 = (float)(x-px)*(x-px)+(y-py)*(y-py);
-              if (d2<d2min)
-                {
+        nmin = 0;
+        for (j = 0, y = 0; y < ny; y++) {
+          for (x = 0; x < nx; x++, j++) {
+            if (back[j] > -BIG) {
+              d2 = (float)(x - px) * (x - px) + (y - py) * (y - py);
+              if (d2 < d2min) {
                 val = back[j];
                 sval = sigma[j];
                 nmin = 1;
                 d2min = d2;
-                }
-              else if (d2==d2min)
-                {
+              } else if (d2 == d2min) {
                 val += back[j];
                 sval += sigma[j];
                 nmin++;
-                }
               }
-        back2[i] = nmin? val/nmin: 0.0;
-        sigma[i] = nmin? sval/nmin: 1.0;
+            }
+          }
         }
-  memcpy(back, back2, (size_t)np*sizeof(float));
+        back2[i] = nmin ? val / nmin : 0.0;
+        sigma[i] = nmin ? sval / nmin : 1.0;
+      }
+    }
+  }
+  memcpy(back, back2, (size_t)np * sizeof(float));
 
-/* Do the actual filtering */
-  for (py=0; py<np; py+=nx)
-    {
+  /* Do the actual filtering */
+  for (py = 0; py < np; py += nx) {
     npy2 = np - py - nx;
-    if (npy2>npy)
+    if (npy2 > npy) {
       npy2 = npy;
-    if (npy2>py)
+    }
+    if (npy2 > py) {
       npy2 = py;
-    for (px=0; px<nx; px++)
-      {
+    }
+    for (px = 0; px < nx; px++) {
       npx2 = nx - px - 1;
-      if (npx2>npx)
+      if (npx2 > npx) {
         npx2 = npx;
-      if (npx2>px)
+      }
+      if (npx2 > px) {
         npx2 = px;
-      i=0;
-      for (dpy = -npy2; dpy<=npy2; dpy+=nx)
-        {
-        y = py+dpy;
-        for (dpx = -npx2; dpx <= npx2; dpx++)
-          {
-          x = px+dpx;
-          bmask[i] = back[x+y];
-          smask[i++] = sigma[x+y];
-          }
-        }
-      if (fabs((med=fqmedian(bmask, i))-back[px+py])>=fthresh)
-        {
-        back2[px+py] = med;
-        sigma2[px+py] = fqmedian(smask, i);
-        }
-      else
-        {
-        back2[px+py] = back[px+py];
-        sigma2[px+py] = sigma[px+py];
+      }
+      i = 0;
+      for (dpy = -npy2; dpy <= npy2; dpy += nx) {
+        y = py + dpy;
+        for (dpx = -npx2; dpx <= npx2; dpx++) {
+          x = px + dpx;
+          bmask[i] = back[x + y];
+          smask[i++] = sigma[x + y];
         }
       }
+      if (fabs((med = fqmedian(bmask, i)) - back[px + py]) >= fthresh) {
+        back2[px + py] = med;
+        sigma2[px + py] = fqmedian(smask, i);
+      } else {
+        back2[px + py] = back[px + py];
+        sigma2[px + py] = sigma[px + py];
+      }
     }
+  }
 
   free(bmask);
   free(smask);
   bmask = smask = NULL;
-  memcpy(back, back2, np*sizeof(float));
+  memcpy(back, back2, np * sizeof(float));
   bkg->global = fqmedian(back2, np);
   free(back2);
   back2 = NULL;
-  memcpy(sigma, sigma2, np*sizeof(float));
+  memcpy(sigma, sigma2, np * sizeof(float));
   bkg->globalrms = fqmedian(sigma2, np);
 
-  if (bkg->globalrms <= 0.0)
-    {
-    sigmat = sigma2+np;
-    for (i=np; i-- && *(--sigmat)>0.0;);
-    if (i>=0 && i<(np-1))
-      bkg->globalrms = fqmedian(sigmat+1, np-1-i);
-    else
+  if (bkg->globalrms <= 0.0) {
+    sigmat = sigma2 + np;
+    for (i = np; i-- && *(--sigmat) > 0.0;)
+      ;
+    if (i >= 0 && i < (np - 1)) {
+      bkg->globalrms = fqmedian(sigmat + 1, np - 1 - i);
+    } else {
       bkg->globalrms = 1.0;
     }
+  }
 
   free(sigma2);
   sigma2 = NULL;
 
   return status;
 
- exit:
-  if (bmask) free(bmask);
-  if (smask) free(smask);
-  if (back2) free(back2);
-  if (sigma2) free(sigma2);
+exit:
+  if (bmask) {
+    free(bmask);
+  }
+  if (smask) {
+    free(smask);
+  }
+  if (back2) {
+    free(back2);
+  }
+  if (sigma2) {
+    free(sigma2);
+  }
   return status;
 }
 
@@ -636,9 +679,9 @@ int filterback(sep_bkg *bkg, int fw, int fh, double fthresh)
 /*
  * Pre-compute 2nd derivatives along the y direction at background nodes.
  */
-int makebackspline(const sep_bkg *bkg, float *map, float *dmap)
-{
-  int   x, y, nbx, nby, nbym1, status;
+int makebackspline(const sep_bkg * bkg, float * map, float * dmap) {
+  int64_t x, y, nbx, nby, nbym1;
+  int status;
   float *dmapt, *mapt, *u, temp;
   u = NULL;
   status = RETURN_OK;
@@ -646,124 +689,116 @@ int makebackspline(const sep_bkg *bkg, float *map, float *dmap)
   nbx = bkg->nx;
   nby = bkg->ny;
   nbym1 = nby - 1;
-  for (x=0; x<nbx; x++)
-    {
-      mapt = map+x;
-      dmapt = dmap+x;
-      if (nby>1)
-	{
-	  QMALLOC(u, float, nbym1, status); /* temporary array */
-	  *dmapt = *u = 0.0;	/* "natural" lower boundary condition */
-	  mapt += nbx;
-	  for (y=1; y<nbym1; y++, mapt+=nbx)
-	    {
-	      temp = -1/(*dmapt+4);
-	      *(dmapt += nbx) = temp;
-	      temp *= *(u++) - 6*(*(mapt+nbx)+*(mapt-nbx)-2**mapt);
-	      *u = temp;
-	    }
-	  *(dmapt+=nbx) = 0.0;	/* "natural" upper boundary condition */
-	  for (y=nby-2; y--;)
-	    {
-	      temp = *dmapt;
-	      dmapt -= nbx;
-	      *dmapt = (*dmapt*temp+*(u--))/6.0;
-	    }
-	  free(u);
-	  u = NULL;
-	}
-      else
-	*dmapt = 0.0;
+  for (x = 0; x < nbx; x++) {
+    mapt = map + x;
+    dmapt = dmap + x;
+    if (nby > 1) {
+      QMALLOC(u, float, nbym1, status); /* temporary array */
+      *dmapt = *u = 0.0; /* "natural" lower boundary condition */
+      mapt += nbx;
+      for (y = 1; y < nbym1; y++, mapt += nbx) {
+        temp = -1 / (*dmapt + 4);
+        *(dmapt += nbx) = temp;
+        temp *= *(u++) - 6 * (*(mapt + nbx) + *(mapt - nbx) - 2 * *mapt);
+        *u = temp;
+      }
+      *(dmapt += nbx) = 0.0; /* "natural" upper boundary condition */
+      for (y = nby - 2; y--;) {
+        temp = *dmapt;
+        dmapt -= nbx;
+        *dmapt = (*dmapt * temp + *(u--)) / 6.0;
+      }
+      free(u);
+      u = NULL;
+    } else {
+      *dmapt = 0.0;
     }
+  }
 
   return status;
 
- exit:
-  if (u) free(u);
+exit:
+  if (u) {
+    free(u);
+  }
   return status;
 }
 
 /*****************************************************************************/
 
-float sep_bkg_global(const sep_bkg *bkg)
-{
+float sep_bkg_global(const sep_bkg * bkg) {
   return bkg->global;
 }
 
-float sep_bkg_globalrms(const sep_bkg *bkg)
-{
+float sep_bkg_globalrms(const sep_bkg * bkg) {
   return bkg->globalrms;
 }
 
 
 /*****************************************************************************/
 
-float sep_bkg_pix(const sep_bkg *bkg, int x, int y)
+float sep_bkg_pix(const sep_bkg * bkg, int64_t x, int64_t y)
 /*
  * return background at position x,y.
  * (linear interpolation between background map vertices).
  */
 {
-  int    nx, ny, xl, yl, pos;
+  int64_t nx, ny, xl, yl, pos;
   double dx, dy, cdx;
-  float	 *b;
-  float  b0, b1, b2, b3;
+  float * b;
+  float b0, b1, b2, b3;
 
   b = bkg->back;
   nx = bkg->nx;
   ny = bkg->ny;
 
-  dx = (double)x/bkg->bw - 0.5;
-  dy = (double)y/bkg->bh - 0.5;
-  dx -= (xl = (int)dx);
-  dy -= (yl = (int)dy);
+  dx = (double)x / bkg->bw - 0.5;
+  dy = (double)y / bkg->bh - 0.5;
+  dx -= (xl = (int64_t)dx);
+  dy -= (yl = (int64_t)dy);
 
-  if (xl<0)
-    {
+  if (xl < 0) {
     xl = 0;
     dx -= 1.0;
-    }
-  else if (xl>=nx-1)
-    {
-    xl = nx<2 ? 0 : nx-2;
+  } else if (xl >= nx - 1) {
+    xl = nx < 2 ? 0 : nx - 2;
     dx += 1.0;
-    }
+  }
 
-  if (yl<0)
-    {
+  if (yl < 0) {
     yl = 0;
     dy -= 1.0;
-    }
-  else if (yl>=ny-1)
-    {
-    yl = ny<2 ? 0 : ny-2;
+  } else if (yl >= ny - 1) {
+    yl = ny < 2 ? 0 : ny - 2;
     dy += 1.0;
-    }
+  }
 
-  pos = yl*nx + xl;
+  pos = yl * nx + xl;
   cdx = 1 - dx;
 
-  b0 = *(b+=pos);		/* consider when nbackx or nbacky = 1 */
-  b1 = nx<2? b0:*(++b);
-  b2 = ny<2? *b:*(b+=nx);
-  b3 = nx<2? *b:*(--b);
+  b0 = *(b += pos); /* consider when nbackx or nbacky = 1 */
+  b1 = nx < 2 ? b0 : *(++b);
+  b2 = ny < 2 ? *b : *(b += nx);
+  b3 = nx < 2 ? *b : *(--b);
 
-  return (float)((1-dy)*(cdx*b0 + dx*b1) + dy*(dx*b2 + cdx*b3));
+  return (float)((1 - dy) * (cdx * b0 + dx * b1) + dy * (dx * b2 + cdx * b3));
 }
 
 
 /*****************************************************************************/
 
-int bkg_line_flt_internal(const sep_bkg *bkg, float *values, float *dvalues, int y,
-                          float *line)
+int bkg_line_flt_internal(
+    const sep_bkg * bkg, float * values, float * dvalues, int64_t y, float * line
+)
 /* Interpolate background at line y (bicubic spline interpolation between
  * background map vertices) and save to line.
  * (values, dvalues) is either (bkg->back, bkg->dback) or
  * (bkg->sigma, bkg->dsigma) depending on whether the background value or rms
  * is being evaluated. */
 {
-  int i,j,x,yl, nbx,nbxm1,nby, nx,width, ystep, changepoint, status;
-  float	dx,dx0,dy,dy3, cdx,cdy,cdy3, temp, xstep;
+  int64_t i, j, x, yl, nbx, nbxm1, nby, nx, width, ystep, changepoint;
+  int status;
+  float dx, dx0, dy, dy3, cdx, cdy, cdy3, temp, xstep;
   float *nodebuf, *dnodebuf, *u;
   float *node, *nodep, *dnode, *blo, *bhi, *dblo, *dbhi;
 
@@ -776,116 +811,108 @@ int bkg_line_flt_internal(const sep_bkg *bkg, float *values, float *dvalues, int
   nbx = bkg->nx;
   nbxm1 = nbx - 1;
   nby = bkg->ny;
-  if (nby > 1)
-    {
-      dy = (float)y/bkg->bh - 0.5;
-      dy -= (yl = (int)dy);
-      if (yl<0)
-	{
-	  yl = 0;
-	  dy -= 1.0;
-	}
-      else if (yl>=nby-1)
-	{
-	  yl = nby<2 ? 0 : nby-2;
-	  dy += 1.0;
-	}
-      /*-- Interpolation along y for each node */
-      cdy = 1 - dy;
-      dy3 = (dy*dy*dy-dy);
-      cdy3 = (cdy*cdy*cdy-cdy);
-      ystep = nbx*yl;
-      blo = values + ystep;
-      bhi = blo + nbx;
-      dblo = dvalues + ystep;
-      dbhi = dblo + nbx;
-      QMALLOC(nodebuf, float, nbx, status);  /* Interpolated background */
-      nodep = node = nodebuf;
-      for (x=nbx; x--;)
-	*(nodep++) = cdy**(blo++) + dy**(bhi++) + cdy3**(dblo++) +
-	  dy3**(dbhi++);
-
-      /*-- Computation of 2nd derivatives along x */
-      QMALLOC(dnodebuf, float, nbx, status);  /* 2nd derivative along x */
-      dnode = dnodebuf;
-      if (nbx>1)
-	{
-	  QMALLOC(u, float, nbxm1, status);  /* temporary array */
-	  *dnode = *u = 0.0;	/* "natural" lower boundary condition */
-	  nodep = node+1;
-	  for (x=nbxm1; --x; nodep++)
-	    {
-	      temp = -1/(*(dnode++)+4);
-	      *dnode = temp;
-	      temp *= *(u++) - 6*(*(nodep+1)+*(nodep-1)-2**nodep);
-	      *u = temp;
-	    }
-	  *(++dnode) = 0.0;	/* "natural" upper boundary condition */
-	  for (x=nbx-2; x--;)
-	    {
-	      temp = *(dnode--);
-	      *dnode = (*dnode*temp+*(u--))/6.0;
-	    }
-	  free(u);
-	  u = NULL;
-	  dnode--;
-	}
+  if (nby > 1) {
+    dy = (float)y / bkg->bh - 0.5;
+    dy -= (yl = (int64_t)dy);
+    if (yl < 0) {
+      yl = 0;
+      dy -= 1.0;
+    } else if (yl >= nby - 1) {
+      yl = nby < 2 ? 0 : nby - 2;
+      dy += 1.0;
     }
-  else
-    {
-      /*-- No interpolation and no new 2nd derivatives needed along y */
-      node = values;
-      dnode = dvalues;
+    /*-- Interpolation along y for each node */
+    cdy = 1 - dy;
+    dy3 = (dy * dy * dy - dy);
+    cdy3 = (cdy * cdy * cdy - cdy);
+    ystep = nbx * yl;
+    blo = values + ystep;
+    bhi = blo + nbx;
+    dblo = dvalues + ystep;
+    dbhi = dblo + nbx;
+    QMALLOC(nodebuf, float, nbx, status); /* Interpolated background */
+    nodep = node = nodebuf;
+    for (x = nbx; x--;) {
+      *(nodep++) = cdy * *(blo++) + dy * *(bhi++) + cdy3 * *(dblo++) + dy3 * *(dbhi++);
     }
 
-  /*-- Interpolation along x */
-  if (nbx>1)
-    {
-      nx = bkg->bw;
-      xstep = 1.0/nx;
-      changepoint = nx/2;
-      dx  = (xstep - 1)/2;	/* dx of the first pixel in the row */
-      dx0 = ((nx+1)%2)*xstep/2;	/* dx of the 1st pixel right to a bkgnd node */
-      blo = node;
-      bhi = node + 1;
-      dblo = dnode;
-      dbhi = dnode + 1;
-      for (x=i=0,j=width; j--; i++, dx += xstep)
-	{
-	  if (i==changepoint && x>0 && x<nbxm1)
-	    {
-	      blo++;
-	      bhi++;
-	      dblo++;
-	      dbhi++;
-	      dx = dx0;
-	    }
-	  cdx = 1 - dx;
-
-	  *(line++) = (float)(cdx*(*blo+(cdx*cdx-1)**dblo)
-			      + dx*(*bhi+(dx*dx-1)**dbhi));
-
-	  if (i==nx)
-	    {
-	      x++;
-	      i = 0;
-	    }
-	}
+    /*-- Computation of 2nd derivatives along x */
+    QMALLOC(dnodebuf, float, nbx, status); /* 2nd derivative along x */
+    dnode = dnodebuf;
+    if (nbx > 1) {
+      QMALLOC(u, float, nbxm1, status); /* temporary array */
+      *dnode = *u = 0.0; /* "natural" lower boundary condition */
+      nodep = node + 1;
+      for (x = nbxm1; --x; nodep++) {
+        temp = -1 / (*(dnode++) + 4);
+        *dnode = temp;
+        temp *= *(u++) - 6 * (*(nodep + 1) + *(nodep - 1) - 2 * *nodep);
+        *u = temp;
+      }
+      *(++dnode) = 0.0; /* "natural" upper boundary condition */
+      for (x = nbx - 2; x--;) {
+        temp = *(dnode--);
+        *dnode = (*dnode * temp + *(u--)) / 6.0;
+      }
+      free(u);
+      u = NULL;
+      dnode--;
     }
-  else
-    for (j=width; j--;)
-      {
-	*(line++) = (float)*node;
+  } else {
+    /*-- No interpolation and no new 2nd derivatives needed along y */
+    node = values;
+    dnode = dvalues;
+  }
+
+  /*-- Interpolation along x */
+  if (nbx > 1) {
+    nx = bkg->bw;
+    xstep = 1.0 / nx;
+    changepoint = nx / 2;
+    dx = (xstep - 1) / 2; /* dx of the first pixel in the row */
+    dx0 = ((nx + 1) % 2) * xstep / 2; /* dx of the 1st pixel right to a bkgnd node */
+    blo = node;
+    bhi = node + 1;
+    dblo = dnode;
+    dbhi = dnode + 1;
+    for (x = i = 0, j = width; j--; i++, dx += xstep) {
+      if (i == changepoint && x > 0 && x < nbxm1) {
+        blo++;
+        bhi++;
+        dblo++;
+        dbhi++;
+        dx = dx0;
+      }
+      cdx = 1 - dx;
+
+      *(line++) = (float)(cdx * (*blo + (cdx * cdx - 1) * *dblo)
+                          + dx * (*bhi + (dx * dx - 1) * *dbhi));
+
+      if (i == nx) {
+        x++;
+        i = 0;
       }
+    }
+  } else {
+    for (j = width; j--;) {
+      *(line++) = (float)*node;
+    }
+  }
 
- exit:
-  if (nodebuf) free(nodebuf);
-  if (dnodebuf) free(dnodebuf);
-  if (u) free(u);
+exit:
+  if (nodebuf) {
+    free(nodebuf);
+  }
+  if (dnodebuf) {
+    free(dnodebuf);
+  }
+  if (u) {
+    free(u);
+  }
   return status;
 }
 
-int sep_bkg_line_flt(const sep_bkg *bkg, int y, float *line)
+int sep_bkg_line_flt(const sep_bkg * bkg, int64_t y, float * line)
 /* Interpolate background at line y (bicubic spline interpolation between
  * background map vertices) and save to line */
 {
@@ -894,7 +921,7 @@ int sep_bkg_line_flt(const sep_bkg *bkg, int y, float *line)
 
 /*****************************************************************************/
 
-int sep_bkg_rmsline_flt(const sep_bkg *bkg, int y, float *line)
+int sep_bkg_rmsline_flt(const sep_bkg * bkg, int64_t y, float * line)
 /* Interpolate background rms at line y (bicubic spline interpolation between
  * background map vertices) and save to line */
 {
@@ -905,143 +932,153 @@ int sep_bkg_rmsline_flt(const sep_bkg *bkg, int y, float *line)
 /* Multiple dtype functions and convenience functions.
  * These mostly wrap the two "line" functions above. */
 
-int sep_bkg_line(const sep_bkg *bkg, int y, void *line, int dtype)
-{
+int sep_bkg_line(const sep_bkg * bkg, int64_t y, void * line, int dtype) {
   array_writer write_array;
-  int size, status;
-  float *tmpline;
+  int64_t size;
+  int status;
+  float * tmpline;
 
-  if (dtype == SEP_TFLOAT)
+  if (dtype == SEP_TFLOAT) {
     return sep_bkg_line_flt(bkg, y, (float *)line);
+  }
 
   tmpline = NULL;
 
   status = get_array_writer(dtype, &write_array, &size);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   QMALLOC(tmpline, float, bkg->w, status);
   status = sep_bkg_line_flt(bkg, y, tmpline);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   /* write to desired output type */
   write_array(tmpline, bkg->w, line);
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
-int sep_bkg_rmsline(const sep_bkg *bkg, int y, void *line, int dtype)
-{
+int sep_bkg_rmsline(const sep_bkg * bkg, int64_t y, void * line, int dtype) {
   array_writer write_array;
-  int size, status;
-  float *tmpline;
+  int64_t size;
+  int status;
+  float * tmpline;
 
-  if (dtype == SEP_TFLOAT)
+  if (dtype == SEP_TFLOAT) {
     return sep_bkg_rmsline_flt(bkg, y, (float *)line);
+  }
 
   tmpline = NULL;
 
   status = get_array_writer(dtype, &write_array, &size);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   QMALLOC(tmpline, float, bkg->w, status);
   status = sep_bkg_rmsline_flt(bkg, y, tmpline);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   /* write to desired output type */
   write_array(tmpline, bkg->w, line);
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
-int sep_bkg_array(const sep_bkg *bkg, void *arr, int dtype)
-{
-  int y, width, size, status;
+int sep_bkg_array(const sep_bkg * bkg, void * arr, int dtype) {
+  int64_t y, width, size;
+  int status;
   array_writer write_array;
-  float *tmpline;
-  BYTE *line;
+  float * tmpline;
+  BYTE * line;
 
   tmpline = NULL;
   status = RETURN_OK;
   width = bkg->w;
 
-  if (dtype == SEP_TFLOAT)
-    {
-      tmpline = (float *)arr;
-      for (y=0; y<bkg->h; y++, tmpline+=width)
-	if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK)
-	  return status;
-      return status;
+  if (dtype == SEP_TFLOAT) {
+    tmpline = (float *)arr;
+    for (y = 0; y < bkg->h; y++, tmpline += width) {
+      if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) {
+        return status;
+      }
     }
+    return status;
+  }
 
-  if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK)
+  if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK) {
     goto exit;
+  }
 
   QMALLOC(tmpline, float, width, status);
 
   line = (BYTE *)arr;
-  for (y=0; y<bkg->h; y++, line += size*width)
-    {
-      if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK)
-	goto exit;
-      write_array(tmpline, width, line);
+  for (y = 0; y < bkg->h; y++, line += size * width) {
+    if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) {
+      goto exit;
     }
+    write_array(tmpline, width, line);
+  }
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
-int sep_bkg_rmsarray(const sep_bkg *bkg, void *arr, int dtype)
-{
-  int y, width, size, status;
+int sep_bkg_rmsarray(const sep_bkg * bkg, void * arr, int dtype) {
+  int64_t y, width, size;
+  int status;
   array_writer write_array;
-  float *tmpline;
-  BYTE *line;
+  float * tmpline;
+  BYTE * line;
 
   tmpline = NULL;
   status = RETURN_OK;
   width = bkg->w;
 
-  if (dtype == SEP_TFLOAT)
-    {
-      tmpline = (float *)arr;
-      for (y=0; y<bkg->h; y++, tmpline+=width)
-	if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK)
-	  return status;
-      return status;
+  if (dtype == SEP_TFLOAT) {
+    tmpline = (float *)arr;
+    for (y = 0; y < bkg->h; y++, tmpline += width) {
+      if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK) {
+        return status;
+      }
     }
+    return status;
+  }
 
-  if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK)
+  if ((status = get_array_writer(dtype, &write_array, &size)) != RETURN_OK) {
     goto exit;
+  }
 
   QMALLOC(tmpline, float, width, status);
 
   line = (BYTE *)arr;
-  for (y=0; y<bkg->h; y++, line += size*width)
-    {
-      if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK)
-	goto exit;
-      write_array(tmpline, width, line);
+  for (y = 0; y < bkg->h; y++, line += size * width) {
+    if ((status = sep_bkg_rmsline_flt(bkg, y, tmpline)) != RETURN_OK) {
+      goto exit;
     }
+    write_array(tmpline, width, line);
+  }
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
-int sep_bkg_subline(const sep_bkg *bkg, int y, void *line, int dtype)
-{
+int sep_bkg_subline(const sep_bkg * bkg, int64_t y, void * line, int dtype) {
   array_writer subtract_array;
-  int status, size;
-  PIXTYPE *tmpline;
+  int status;
+  int64_t size;
+  PIXTYPE * tmpline;
 
   tmpline = NULL;
   status = RETURN_OK;
@@ -1049,26 +1086,28 @@ int sep_bkg_subline(const sep_bkg *bkg, int y, void *line, int dtype)
   QMALLOC(tmpline, PIXTYPE, bkg->w, status);
 
   status = sep_bkg_line_flt(bkg, y, tmpline);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   status = get_array_subtractor(dtype, &subtract_array, &size);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   subtract_array(tmpline, bkg->w, line);
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
-int sep_bkg_subarray(const sep_bkg *bkg, void *arr, int dtype)
-{
+int sep_bkg_subarray(const sep_bkg * bkg, void * arr, int dtype) {
   array_writer subtract_array;
-  int y, status, size, width;
-  PIXTYPE *tmpline;
-  BYTE *arrt;
+  int64_t y, size, width;
+  int status;
+  PIXTYPE * tmpline;
+  BYTE * arrt;
 
   tmpline = NULL;
   status = RETURN_OK;
@@ -1078,31 +1117,30 @@ int sep_bkg_subarray(const sep_bkg *bkg, void *arr, int dtype)
   QMALLOC(tmpline, PIXTYPE, width, status);
 
   status = get_array_subtractor(dtype, &subtract_array, &size);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
-  for (y=0; y<bkg->h; y++, arrt+=(width*size))
-    {
-      if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK)
-	goto exit;
-      subtract_array(tmpline, width, arrt);
+  for (y = 0; y < bkg->h; y++, arrt += (width * size)) {
+    if ((status = sep_bkg_line_flt(bkg, y, tmpline)) != RETURN_OK) {
+      goto exit;
     }
+    subtract_array(tmpline, width, arrt);
+  }
 
- exit:
+exit:
   free(tmpline);
   return status;
 }
 
 /*****************************************************************************/
 
-void sep_bkg_free(sep_bkg *bkg)
-{
-  if (bkg)
-    {
-      free(bkg->back);
-      free(bkg->dback);
-      free(bkg->sigma);
-      free(bkg->dsigma);
-    }
+void sep_bkg_free(sep_bkg * bkg) {
+  if (bkg) {
+    free(bkg->back);
+    free(bkg->dback);
+    free(bkg->sigma);
+    free(bkg->dsigma);
+  }
   free(bkg);
 }
diff --git a/src/convolve.c b/src/convolve.c
index 9b209cb..306ea24 100644
--- a/src/convolve.c
+++ b/src/convolve.c
@@ -20,13 +20,13 @@ f* GNU Lesser General Public License for more details.
 *
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
 #include <math.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "extract.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "extract.h"
 
 /* Convolve one line of an image with a given kernel.
  *
@@ -36,65 +36,68 @@ f* GNU Lesser General Public License for more details.
  * convw, convh : width and height of conv
  * buf : output convolved line (buf->dw elements long)
  */
-int convolve(arraybuffer *buf, int y, const float *conv, int convw, int convh,
-             PIXTYPE *out)
-{
-  int convw2, convn, cx, cy, i, dcx, y0;
-  PIXTYPE *line;    /* current line in input buffer */
-  PIXTYPE *outend;  /* end of output buffer */
+int convolve(
+    arraybuffer * buf,
+    int64_t y,
+    const float * conv,
+    int64_t convw,
+    int64_t convh,
+    PIXTYPE * out
+) {
+  int64_t convw2, convn, cx, cy, i, dcx, y0;
+  PIXTYPE * line; /* current line in input buffer */
+  PIXTYPE * outend; /* end of output buffer */
   PIXTYPE *src, *dst, *dstend;
 
   outend = out + buf->dw;
-  convw2 = convw/2;
-  y0 = y - convh/2;  /* start line in image */
+  convw2 = convw / 2;
+  y0 = y - convh / 2; /* start line in image */
 
   /* Cut off top of kernel if it extends beyond image */
-  if (y0 + convh > buf->dh)
+  if (y0 + convh > buf->dh) {
     convh = buf->dh - y0;
+  }
 
   /* cut off bottom of kernel if it extends beyond image */
-  if (y0 < 0)
-    {
-      convh = convh + y0;
-      conv += convw*(-y0);
-      y0 = 0;
-    }
+  if (y0 < 0) {
+    convh = convh + y0;
+    conv += convw * (-y0);
+    y0 = 0;
+  }
 
   /* check that buffer has needed lines */
-  if ((y0 < buf->yoff) || (y0+convh > buf->yoff + buf->bh))
+  if ((y0 < buf->yoff) || (y0 + convh > buf->yoff + buf->bh)) {
     return LINE_NOT_IN_BUF;
+  }
 
-  memset(out, 0, buf->dw*sizeof(PIXTYPE));  /* initialize output to zero */
+  memset(out, 0, buf->dw * sizeof(PIXTYPE)); /* initialize output to zero */
 
   /* loop over pixels in the convolution kernel */
   convn = convw * convh;
-  for (i=0; i<convn; i++)
-    {
-      cx = i % convw;  /* x index in conv kernel */
-      cy = i / convw;  /* y index in conv kernel */
-      line = buf->bptr + buf->bw * (y0 - buf->yoff + cy); /* start of line */
-
-      /* get start and end positions in the source and target line */
-      dcx = cx - convw2; /* offset of conv pixel from conv center;
-                            determines offset between in and out line */
-      if (dcx >= 0)
-	{
-	  src = line + dcx;
-	  dst = out;
-	  dstend = outend - dcx;
-	}
-      else
-	{
-	  src = line;
-	  dst = out - dcx;
-	  dstend = outend;
-	}
-
-      /* multiply and add the values */
-      while (dst < dstend)
-	*(dst++) += conv[i] * *(src++);
+  for (i = 0; i < convn; i++) {
+    cx = i % convw; /* x index in conv kernel */
+    cy = i / convw; /* y index in conv kernel */
+    line = buf->bptr + buf->bw * (y0 - buf->yoff + cy); /* start of line */
+
+    /* get start and end positions in the source and target line */
+    dcx = cx - convw2; /* offset of conv pixel from conv center;
+                          determines offset between in and out line */
+    if (dcx >= 0) {
+      src = line + dcx;
+      dst = out;
+      dstend = outend - dcx;
+    } else {
+      src = line;
+      dst = out - dcx;
+      dstend = outend;
     }
 
+    /* multiply and add the values */
+    while (dst < dstend) {
+      *(dst++) += conv[i] * *(src++);
+    }
+  }
+
   return RETURN_OK;
 }
 
@@ -120,95 +123,100 @@ int convolve(arraybuffer *buf, int y, const float *conv, int convw, int convh,
  * imbuf and nbuf should have same data dimensions and be on the same line
  * (their `yoff` fields should be the same).
  */
-int matched_filter(arraybuffer *imbuf, arraybuffer *nbuf, int y,
-                   const float *conv, int convw, int convh,
-                   PIXTYPE *work, PIXTYPE *out, int noise_type)
-{
-  int convw2, convn, cx, cy, i, dcx, y0;
+int matched_filter(
+    arraybuffer * imbuf,
+    arraybuffer * nbuf,
+    int64_t y,
+    const float * conv,
+    int64_t convw,
+    int64_t convh,
+    PIXTYPE * work,
+    PIXTYPE * out,
+    int noise_type
+) {
+  int64_t convw2, convn, cx, cy, i, dcx, y0;
   PIXTYPE imval, varval;
-  PIXTYPE *imline, *nline;    /* current line in input buffer */
-  PIXTYPE *outend;            /* end of output buffer */
+  PIXTYPE *imline, *nline; /* current line in input buffer */
+  PIXTYPE * outend; /* end of output buffer */
   PIXTYPE *src_im, *src_n, *dst_num, *dst_denom, *dst_num_end;
 
   outend = out + imbuf->dw;
-  convw2 = convw/2;
-  y0 = y - convh/2;  /* start line in image */
+  convw2 = convw / 2;
+  y0 = y - convh / 2; /* start line in image */
 
   /* Cut off top of kernel if it extends beyond image */
-  if (y0 + convh > imbuf->dh)
+  if (y0 + convh > imbuf->dh) {
     convh = imbuf->dh - y0;
+  }
 
   /* cut off bottom of kernel if it extends beyond image */
-  if (y0 < 0)
-    {
-      convh = convh + y0;
-      conv += convw*(-y0);
-      y0 = 0;
-    }
+  if (y0 < 0) {
+    convh = convh + y0;
+    conv += convw * (-y0);
+    y0 = 0;
+  }
 
   /* check that buffer has needed lines */
-  if ((y0 < imbuf->yoff) || (y0+convh > imbuf->yoff + imbuf->bh) ||
-      (y0 < nbuf->yoff)  || (y0+convh > nbuf->yoff + nbuf->bh))
+  if ((y0 < imbuf->yoff) || (y0 + convh > imbuf->yoff + imbuf->bh) || (y0 < nbuf->yoff)
+      || (y0 + convh > nbuf->yoff + nbuf->bh))
+  {
     return LINE_NOT_IN_BUF;
+  }
 
   /* check that image and noise buffer match */
-  if ((imbuf->yoff != nbuf->yoff) || (imbuf->dw != nbuf->dw))
-    return LINE_NOT_IN_BUF;  /* TODO new error status code */
+  if ((imbuf->yoff != nbuf->yoff) || (imbuf->dw != nbuf->dw)) {
+    return LINE_NOT_IN_BUF; /* TODO new error status code */
+  }
 
   /* initialize output buffers to zero */
-  memset(out, 0, imbuf->bw*sizeof(PIXTYPE));
-  memset(work, 0, imbuf->bw*sizeof(PIXTYPE));
+  memset(out, 0, imbuf->bw * sizeof(PIXTYPE));
+  memset(work, 0, imbuf->bw * sizeof(PIXTYPE));
 
   /* loop over pixels in the convolution kernel */
   convn = convw * convh;
-  for (i=0; i<convn; i++)
-    {
-      cx = i % convw;  /* x index in conv kernel */
-      cy = i / convw;  /* y index in conv kernel */
-      imline = imbuf->bptr + imbuf->bw * (y0 - imbuf->yoff + cy);
-      nline = nbuf->bptr + nbuf->bw * (y0 - nbuf->yoff + cy);
-
-      /* get start and end positions in the source and target line */
-      dcx = cx - convw2; /* offset of conv pixel from conv center;
-                            determines offset between in and out line */
-      if (dcx >= 0)
-	{
-	  src_im = imline + dcx;
-          src_n = nline + dcx;
-	  dst_num = out;
-          dst_denom = work;
-	  dst_num_end = outend - dcx;
-	}
-      else
-	{
-	  src_im = imline;
-          src_n = nline;
-	  dst_num = out - dcx;
-          dst_denom = work - dcx;
-	  dst_num_end = outend;
-	}
-
-      /* actually calculate values */
-      while (dst_num < dst_num_end)
-        {
-          imval = *src_im;
-          varval = (noise_type == SEP_NOISE_VAR)? (*src_n): (*src_n)*(*src_n);
-          if (varval != 0.0)
-            {
-              *dst_num   += conv[i] * imval / varval;
-              *dst_denom += conv[i] * conv[i] / varval;
-            }
-          src_im++;
-          src_n++;
-          dst_num++;
-          dst_denom++;
-        }
-    }  /* close loop over convolution kernel */
+  for (i = 0; i < convn; i++) {
+    cx = i % convw; /* x index in conv kernel */
+    cy = i / convw; /* y index in conv kernel */
+    imline = imbuf->bptr + imbuf->bw * (y0 - imbuf->yoff + cy);
+    nline = nbuf->bptr + nbuf->bw * (y0 - nbuf->yoff + cy);
+
+    /* get start and end positions in the source and target line */
+    dcx = cx - convw2; /* offset of conv pixel from conv center;
+                          determines offset between in and out line */
+    if (dcx >= 0) {
+      src_im = imline + dcx;
+      src_n = nline + dcx;
+      dst_num = out;
+      dst_denom = work;
+      dst_num_end = outend - dcx;
+    } else {
+      src_im = imline;
+      src_n = nline;
+      dst_num = out - dcx;
+      dst_denom = work - dcx;
+      dst_num_end = outend;
+    }
+
+    /* actually calculate values */
+    while (dst_num < dst_num_end) {
+      imval = *src_im;
+      varval = (noise_type == SEP_NOISE_VAR) ? (*src_n) : (*src_n) * (*src_n);
+      if (varval != 0.0) {
+        *dst_num += conv[i] * imval / varval;
+        *dst_denom += conv[i] * conv[i] / varval;
+      }
+      src_im++;
+      src_n++;
+      dst_num++;
+      dst_denom++;
+    }
+  } /* close loop over convolution kernel */
 
   /* take the square root of the denominator (work) buffer and divide the
    * numerator by it. */
-  for (dst_num=out, dst_denom=work; dst_num < outend; dst_num++, dst_denom++)
-      *dst_num = *dst_num / sqrt(*dst_denom);
+  for (dst_num = out, dst_denom = work; dst_num < outend; dst_num++, dst_denom++) {
+    *dst_num = *dst_num / sqrt(*dst_denom);
+  }
 
   return RETURN_OK;
 }
diff --git a/src/deblend.c b/src/deblend.c
index 5dae83c..05fe1aa 100644
--- a/src/deblend.c
+++ b/src/deblend.c
@@ -1,54 +1,55 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "extract.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "extract.h"
 
-#ifndef	RAND_MAX
-#define	RAND_MAX 2147483647
+#ifndef RAND_MAX
+#define RAND_MAX 2147483647
 #endif
-#define	NBRANCH	16    /* starting number per branch */
+#define NBRANCH 16 /* starting number per branch */
 
-static _Atomic int nsonmax	= 1024;  /* max. number sub-objects per level */
+static _Atomic int nsonmax = 1024; /* max. number sub-objects per level */
 
 /* get and set pixstack */
-void sep_set_sub_object_limit(int val)
-{
+void sep_set_sub_object_limit(int val) {
   nsonmax = val;
 }
 
-int sep_get_sub_object_limit()
-{
+int sep_get_sub_object_limit() {
   return nsonmax;
 }
 
 
 int belong(int, objliststruct *, int, objliststruct *);
-int *createsubmap(objliststruct *, int, int *, int *, int *, int *);
+int64_t *
+createsubmap(objliststruct *, int64_t, int64_t *, int64_t *, int64_t *, int64_t *);
 int gatherup(objliststruct *, objliststruct *);
 
 /******************************** deblend ************************************/
@@ -59,29 +60,32 @@ NOTE: Even if the object is not deblended, the output objlist threshold is
 
 This can return two error codes: DEBLEND_OVERFLOW or MEMORY_ALLOC_ERROR
 */
-int deblend(objliststruct *objlistin, objliststruct *objlistout,
-	    int deblend_nthresh, double deblend_mincont, int minarea,
-	    deblendctx *ctx)
-{
-  objstruct		*obj;
-  objliststruct	debobjlist, debobjlist2;
-  double		thresh, thresh0, value0;
-  int			h,i,j,k,l,m,subx,suby,subh,subw,
-                        xn,
-			nbm = NBRANCH,
-			status;
-  int                   *submap;
+int deblend(
+    objliststruct * objlistin,
+    objliststruct * objlistout,
+    int deblend_nthresh,
+    double deblend_mincont,
+    int minarea,
+    deblendctx * ctx
+) {
+  objstruct * obj;
+  objliststruct debobjlist, debobjlist2;
+  double thresh, thresh0, value0;
+  int64_t h, i, j, k, l, m, subx, suby, subh, subw, xn, nbm = NBRANCH;
+  int64_t * submap;
+  int status;
 
   submap = NULL;
   status = RETURN_OK;
   xn = deblend_nthresh;
+  l = 0;
 
   /* reset global static objlist for deblending */
-  objliststruct *const objlist = ctx->objlist;
-  memset(objlist, 0, (size_t)xn*sizeof(objliststruct));
+  objliststruct * const objlist = ctx->objlist;
+  memset(objlist, 0, (size_t)xn * sizeof(objliststruct));
 
   /* initialize local object lists */
-  debobjlist.obj = debobjlist2.obj =  NULL;
+  debobjlist.obj = debobjlist2.obj = NULL;
   debobjlist.plist = debobjlist2.plist = NULL;
   debobjlist.nobj = debobjlist2.nobj = 0;
   debobjlist.npix = debobjlist2.npix = 0;
@@ -91,123 +95,134 @@ int deblend(objliststruct *objlistin, objliststruct *objlistout,
    * lutz multiple times below, and we only want to create it once.
    */
   submap = createsubmap(objlistin, l, &subx, &suby, &subw, &subh);
-  if (!submap)
-    {
-      status = MEMORY_ALLOC_ERROR;
+  if (!submap) {
+    status = MEMORY_ALLOC_ERROR;
+    goto exit;
+  }
+
+  for (l = 0; l < objlistin->nobj && status == RETURN_OK; l++) {
+    /* set thresholds of object lists based on object threshold */
+    thresh0 = objlistin->obj[l].thresh;
+    objlistout->thresh = debobjlist2.thresh = thresh0;
+
+    /* add input object to global deblending objlist and one local objlist */
+    if ((status = addobjdeep(l, objlistin, &objlist[0])) != RETURN_OK) {
+      goto exit;
+    }
+    if ((status = addobjdeep(l, objlistin, &debobjlist2)) != RETURN_OK) {
       goto exit;
     }
-  for (l=0; l<objlistin->nobj && status == RETURN_OK; l++)
-    {
-      /* set thresholds of object lists based on object threshold */
-      thresh0 = objlistin->obj[l].thresh;
-      objlistout->thresh = debobjlist2.thresh = thresh0;
 
-      /* add input object to global deblending objlist and one local objlist */
-      if ((status = addobjdeep(l, objlistin, &objlist[0])) != RETURN_OK)
-        goto exit;
-      if ((status = addobjdeep(l, objlistin, &debobjlist2)) != RETURN_OK)
+    value0 = objlist[0].obj[0].fdflux * deblend_mincont;
+    ctx->ok[0] = (short)1;
+    for (k = 1; k < xn; k++) {
+      /*------ Calculate threshold */
+      thresh = objlistin->obj[l].fdpeak;
+      debobjlist.thresh =
+          thresh > 0.0 ? thresh0 * pow(thresh / thresh0, (double)k / xn) : thresh0;
+
+      /*--------- Build tree (bottom->up) */
+      if (objlist[k - 1].nobj >= nsonmax) {
+        status = DEBLEND_OVERFLOW;
         goto exit;
-
-      value0 = objlist[0].obj[0].fdflux*deblend_mincont;
-      ctx->ok[0] = (short)1;
-      for (k=1; k<xn; k++)
-        {
-          /*------ Calculate threshold */
-          thresh = objlistin->obj[l].fdpeak;
-          debobjlist.thresh = thresh > 0.0?
-        thresh0*pow(thresh/thresh0,(double)k/xn) : thresh0;
-
-          /*--------- Build tree (bottom->up) */
-          if (objlist[k-1].nobj>=nsonmax)
-        {
-          status = DEBLEND_OVERFLOW;
+      }
+
+      for (i = 0; i < objlist[k - 1].nobj; i++) {
+        status = lutz(
+            objlistin->plist,
+            submap,
+            subx,
+            suby,
+            subw,
+            &objlist[k - 1].obj[i],
+            &debobjlist,
+            minarea,
+            &ctx->lutz
+        );
+        if (status != RETURN_OK) {
           goto exit;
         }
 
-          for (i=0; i<objlist[k-1].nobj; i++)
-        {
-          status = lutz(objlistin->plist, submap, subx, suby, subw,
-                &objlist[k-1].obj[i], &debobjlist, minarea, &ctx->lutz);
-          if (status != RETURN_OK)
-            goto exit;
-
-          for (j=h=0; j<debobjlist.nobj; j++)
-            if (belong(j, &debobjlist, i, &objlist[k-1]))
-              {
+        for (j = h = 0; j < debobjlist.nobj; j++) {
+          if (belong(j, &debobjlist, i, &objlist[k - 1])) {
             debobjlist.obj[j].thresh = debobjlist.thresh;
-            if ((status = addobjdeep(j, &debobjlist, &objlist[k]))
-                != RETURN_OK)
+            if ((status = addobjdeep(j, &debobjlist, &objlist[k])) != RETURN_OK) {
               goto exit;
+            }
             m = objlist[k].nobj - 1;
-            if (m>=nsonmax)
+            if (m >= nsonmax) {
+              status = DEBLEND_OVERFLOW;
+              goto exit;
+            }
+            if (h >= nbm - 1) {
+              if (!(ctx->son = (short *)
+                        realloc(ctx->son, xn * nsonmax * (nbm += 16) * sizeof(short))))
               {
-                status = DEBLEND_OVERFLOW;
+                status = MEMORY_ALLOC_ERROR;
                 goto exit;
               }
-            if (h>=nbm-1)
-              if (!(ctx->son = (short *)
-                realloc(ctx->son,xn*nsonmax*(nbm+=16)*sizeof(short))))
-                {
-                  status = MEMORY_ALLOC_ERROR;
-                  goto exit;
-                }
-            ctx->son[k-1+xn*(i+nsonmax*(h++))] = (short)m;
-            ctx->ok[k+xn*m] = (short)1;
-              }
-          ctx->son[k-1+xn*(i+nsonmax*h)] = (short)-1;
-        }
+            }
+            ctx->son[k - 1 + xn * (i + nsonmax * (h++))] = (short)m;
+            ctx->ok[k + xn * m] = (short)1;
+          }
         }
+        ctx->son[k - 1 + xn * (i + nsonmax * h)] = (short)-1;
+      }
+    }
 
-      /*------- cut the right branches (top->down) */
-      for (k = xn-2; k>=0; k--)
-        {
-          obj = objlist[k+1].obj;
-          for (i=0; i<objlist[k].nobj; i++)
+    /*------- cut the right branches (top->down) */
+    for (k = xn - 2; k >= 0; k--) {
+      obj = objlist[k + 1].obj;
+      for (i = 0; i < objlist[k].nobj; i++) {
+        for (m = h = 0; (j = (int64_t)ctx->son[k + xn * (i + nsonmax * h)]) != -1; h++)
         {
-          for (m=h=0; (j=(int)ctx->son[k+xn*(i+nsonmax*h)])!=-1; h++)
-            {
-              if (obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0)
+          if (obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0) {
             m++;
-              ctx->ok[k+xn*i] &= ctx->ok[k+1+xn*j];
-            }
-          if (m>1)
+          }
+          ctx->ok[k + xn * i] &= ctx->ok[k + 1 + xn * j];
+        }
+        if (m > 1) {
+          for (h = 0; (j = (int64_t)ctx->son[k + xn * (i + nsonmax * h)]) != -1; h++) {
+            if (ctx->ok[k + 1 + xn * j]
+                && obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0)
             {
-              for (h=0; (j=(int)ctx->son[k+xn*(i+nsonmax*h)])!=-1; h++)
-            if (ctx->ok[k+1+xn*j] &&
-                obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0)
-              {
-                objlist[k+1].obj[j].flag |= SEP_OBJ_MERGED;
-                status = addobjdeep(j, &objlist[k+1], &debobjlist2);
-                if (status != RETURN_OK)
-                  goto exit;
+              objlist[k + 1].obj[j].flag |= SEP_OBJ_MERGED;
+              status = addobjdeep(j, &objlist[k + 1], &debobjlist2);
+              if (status != RETURN_OK) {
+                goto exit;
               }
-              ctx->ok[k+xn*i] = (short)0;
             }
+          }
+          ctx->ok[k + xn * i] = (short)0;
         }
-        }
+      }
+    }
 
-      if (ctx->ok[0])
-        status = addobjdeep(0, &debobjlist2, objlistout);
-      else
-        status = gatherup(&debobjlist2, objlistout);
+    if (ctx->ok[0]) {
+      status = addobjdeep(0, &debobjlist2, objlistout);
+    } else {
+      status = gatherup(&debobjlist2, objlistout);
+    }
+  }
 
+exit:
+  if (status == DEBLEND_OVERFLOW) {
+    put_errdetail(
+        "limit of sub-objects reached while deblending. Increase "
+        "it with sep.set_sub_object_limit(), decrease number of deblending "
+        "thresholds ,or increase the detection threshold."
+    );
   }
- exit:
-  if (status == DEBLEND_OVERFLOW)
-    put_errdetail("limit of sub-objects reached while deblending. Increase "
-          "it with sep.set_sub_object_limit(), decrease number of deblending "
-          "thresholds ,or increase the detection threshold.");
 
   free(submap);
   submap = NULL;
   free(debobjlist2.obj);
   free(debobjlist2.plist);
 
-  for (k=0; k<xn; k++)
-    {
-      free(objlist[k].obj);
-      free(objlist[k].plist);
-    }
+  for (k = 0; k < xn; k++) {
+    free(objlist[k].obj);
+    free(objlist[k].plist);
+  }
 
   free(debobjlist.obj);
   free(debobjlist.plist);
@@ -220,19 +235,19 @@ int deblend(objliststruct *objlistin, objliststruct *objlistout,
 /*
 Allocate the memory allocated by global pointers in refine.c
 */
-int allocdeblend(int deblend_nthresh, int w, int h, deblendctx *ctx)
-{
-  int status=RETURN_OK;
+int allocdeblend(int deblend_nthresh, int64_t w, int64_t h, deblendctx * ctx) {
+  int status = RETURN_OK;
   memset(ctx, 0, sizeof(deblendctx));
-  QMALLOC(ctx->son, short,  deblend_nthresh*nsonmax*NBRANCH, status);
-  QMALLOC(ctx->ok, short,  deblend_nthresh*nsonmax, status);
+  QMALLOC(ctx->son, short, deblend_nthresh * nsonmax * NBRANCH, status);
+  QMALLOC(ctx->ok, short, deblend_nthresh * nsonmax, status);
   QMALLOC(ctx->objlist, objliststruct, deblend_nthresh, status);
   status = lutzalloc(w, h, &ctx->lutz);
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   return status;
- exit:
+exit:
   freedeblend(ctx);
   return status;
 }
@@ -241,8 +256,7 @@ int allocdeblend(int deblend_nthresh, int w, int h, deblendctx *ctx)
 /*
 Free the memory allocated by global pointers in refine.c
 */
-void freedeblend(deblendctx *ctx)
-{
+void freedeblend(deblendctx * ctx) {
   lutzfree(&ctx->lutz);
   free(ctx->son);
   ctx->son = NULL;
@@ -257,16 +271,15 @@ void freedeblend(deblendctx *ctx)
 Collect faint remaining pixels and allocate them to their most probable
 progenitor.
 */
-int gatherup(objliststruct *objlistin, objliststruct *objlistout)
-{
-  char        *bmp;
-  float       *amp, *p, dx,dy, drand, dist, distmin;
-  objstruct   *objin = objlistin->obj, *objout, *objt;
+int gatherup(objliststruct * objlistin, objliststruct * objlistout) {
+  char * bmp;
+  float *amp, *p, dx, dy, drand, dist, distmin;
+  objstruct *objin = objlistin->obj, *objout, *objt;
 
-  pliststruct *pixelin = objlistin->plist, *pixelout, *pixt,*pixt2;
+  pliststruct *pixelin = objlistin->plist, *pixelout, *pixt, *pixt2;
 
-  int         i,k,l, *n, iclst, npix, bmwidth,
-              nobj = objlistin->nobj, xs,ys, x,y, status;
+  int64_t i, k, l, *n, iclst, npix, bmwidth, nobj = objlistin->nobj, xs, ys, x, y;
+  int status;
 
   bmp = NULL;
   amp = p = NULL;
@@ -277,98 +290,98 @@ int gatherup(objliststruct *objlistin, objliststruct *objlistout)
 
   QMALLOC(amp, float, nobj, status);
   QMALLOC(p, float, nobj, status);
-  QMALLOC(n, int, nobj, status);
+  QMALLOC(n, int64_t, nobj, status);
 
-  for (i=1; i<nobj; i++)
+  for (i = 1; i < nobj; i++) {
     analyse(i, objlistin, 0, 0.0);
+  }
 
   p[0] = 0.0;
-  bmwidth = objin->xmax - (xs=objin->xmin) + 1;
-  npix = bmwidth * (objin->ymax - (ys=objin->ymin) + 1);
-  if (!(bmp = (char *)calloc(1, npix*sizeof(char))))
-    {
-      bmp = NULL;
-      status = MEMORY_ALLOC_ERROR;
-      goto exit;
-    }
+  bmwidth = objin->xmax - (xs = objin->xmin) + 1;
+  npix = bmwidth * (objin->ymax - (ys = objin->ymin) + 1);
+  if (!(bmp = (char *)calloc(1, npix * sizeof(char)))) {
+    bmp = NULL;
+    status = MEMORY_ALLOC_ERROR;
+    goto exit;
+  }
 
-  for (objt = objin+(i=1); i<nobj; i++, objt++)
-    {
-      /*-- Now we have passed the deblending section, reset threshold */
-      objt->thresh = objlistin->thresh;
+  for (objt = objin + (i = 1); i < nobj; i++, objt++) {
+    /*-- Now we have passed the deblending section, reset threshold */
+    objt->thresh = objlistin->thresh;
 
-      /* ------------	flag pixels which are already allocated */
-      for (pixt=pixelin+objin[i].firstpix; pixt>=pixelin;
-	   pixt=pixelin+PLIST(pixt,nextpix))
-	bmp[(PLIST(pixt,x)-xs) + (PLIST(pixt,y)-ys)*bmwidth] = '\1';
+    /* ------------	flag pixels which are already allocated */
+    for (pixt = pixelin + objin[i].firstpix; pixt >= pixelin;
+         pixt = pixelin + PLIST(pixt, nextpix))
+    {
+      bmp[(PLIST(pixt, x) - xs) + (PLIST(pixt, y) - ys) * bmwidth] = '\1';
+    }
 
-      status = addobjdeep(i, objlistin, objlistout);
-      if (status != RETURN_OK)
-	goto exit;
-      n[i] = objlistout->nobj - 1;
+    status = addobjdeep(i, objlistin, objlistout);
+    if (status != RETURN_OK) {
+      goto exit;
+    }
+    n[i] = objlistout->nobj - 1;
 
-      dist = objt->fdnpix/(2*PI*objt->abcor*objt->a*objt->b);
-      amp[i] = dist<70.0? objt->thresh * expf(dist) : 4.0*objt->fdpeak;
+    dist = objt->fdnpix / (2 * PI * objt->abcor * objt->a * objt->b);
+    amp[i] = dist < 70.0 ? objt->thresh * expf(dist) : 4.0 * objt->fdpeak;
 
-      /* ------------ limitate expansion ! */
-      if (amp[i]>4.0*objt->fdpeak)
-	amp[i] = 4.0*objt->fdpeak;
+    /* ------------ limitate expansion ! */
+    if (amp[i] > 4.0 * objt->fdpeak) {
+      amp[i] = 4.0 * objt->fdpeak;
     }
+  }
 
-  objout = objlistout->obj;		/* DO NOT MOVE !!! */
+  objout = objlistout->obj; /* DO NOT MOVE !!! */
 
-  if (!(pixelout=realloc(objlistout->plist,
-					(objlistout->npix + npix)*plistsize)))
-    {
-      status = MEMORY_ALLOC_ERROR;
-      goto exit;
-    }
+  if (!(pixelout = realloc(objlistout->plist, (objlistout->npix + npix) * plistsize))) {
+    status = MEMORY_ALLOC_ERROR;
+    goto exit;
+  }
 
   objlistout->plist = pixelout;
   k = objlistout->npix;
-  iclst = 0;				/* To avoid gcc -Wall warnings */
-  for (pixt=pixelin+objin->firstpix; pixt>=pixelin;
-       pixt=pixelin+PLIST(pixt,nextpix))
-    {
-      x = PLIST(pixt,x);
-      y = PLIST(pixt,y);
-      if (!bmp[(x-xs) + (y-ys)*bmwidth])
-	{
-	  pixt2 = pixelout + (l=(k++*plistsize));
-	  memcpy(pixt2, pixt, (size_t)plistsize);
-	  PLIST(pixt2, nextpix) = -1;
-	  distmin = 1e+31;
-	  for (objt = objin+(i=1); i<nobj; i++, objt++)
-	    {
-	      dx = x - objt->mx;
-	      dy = y - objt->my;
-	      dist=0.5*(objt->cxx*dx*dx+objt->cyy*dy*dy+objt->cxy*dx*dy)/objt->abcor;
-	      p[i] = p[i-1] + (dist<70.0?amp[i]*expf(-dist) : 0.0);
-	      if (dist<distmin)
-		{
-		  distmin = dist;
-		  iclst = i;
-		}
-	    }
-	  if (p[nobj-1] > 1.0e-31)
-	    {
-	      drand = p[nobj-1]*rand_r(&randseed)/(float)RAND_MAX;
-	      for (i=1; i<nobj && p[i]<drand; i++);
-	      if (i==nobj)
-		i=iclst;
-	    }
-	  else
-	    i = iclst;
-	  objout[n[i]].lastpix=PLIST(pixelout+objout[n[i]].lastpix,nextpix)=l;
-	}
+  iclst = 0; /* To avoid gcc -Wall warnings */
+  for (pixt = pixelin + objin->firstpix; pixt >= pixelin;
+       pixt = pixelin + PLIST(pixt, nextpix))
+  {
+    x = PLIST(pixt, x);
+    y = PLIST(pixt, y);
+    if (!bmp[(x - xs) + (y - ys) * bmwidth]) {
+      pixt2 = pixelout + (l = (k++ * plistsize));
+      memcpy(pixt2, pixt, (size_t)plistsize);
+      PLIST(pixt2, nextpix) = -1;
+      distmin = 1e+31;
+      for (objt = objin + (i = 1); i < nobj; i++, objt++) {
+        dx = x - objt->mx;
+        dy = y - objt->my;
+        dist = 0.5 * (objt->cxx * dx * dx + objt->cyy * dy * dy + objt->cxy * dx * dy)
+               / objt->abcor;
+        p[i] = p[i - 1] + (dist < 70.0 ? amp[i] * expf(-dist) : 0.0);
+        if (dist < distmin) {
+          distmin = dist;
+          iclst = i;
+        }
+      }
+      if (p[nobj - 1] > 1.0e-31) {
+        drand = p[nobj - 1] * rand_r(&randseed) / (float)RAND_MAX;
+        for (i = 1; i < nobj && p[i] < drand; i++)
+          ;
+        if (i == nobj) {
+          i = iclst;
+        }
+      } else {
+        i = iclst;
+      }
+      objout[n[i]].lastpix = PLIST(pixelout + objout[n[i]].lastpix, nextpix) = l;
     }
+  }
 
   objlistout->npix = k;
-  if (!(objlistout->plist = realloc(pixelout,
-						   objlistout->npix*plistsize)))
+  if (!(objlistout->plist = realloc(pixelout, objlistout->npix * plistsize))) {
     status = MEMORY_ALLOC_ERROR;
+  }
 
- exit:
+exit:
   free(bmp);
   free(amp);
   free(p);
@@ -383,18 +396,19 @@ int gatherup(objliststruct *objlistin, objliststruct *objlistout)
  * first object are included in the pixels of the second object.
  */
 
-int belong(int corenb, objliststruct *coreobjlist,
-	   int shellnb, objliststruct *shellobjlist)
-{
-  objstruct   *cobj = &(coreobjlist->obj[corenb]),
-              *sobj = &(shellobjlist->obj[shellnb]);
+int belong(
+    int corenb, objliststruct * coreobjlist, int shellnb, objliststruct * shellobjlist
+) {
+  objstruct *cobj = &(coreobjlist->obj[corenb]), *sobj = &(shellobjlist->obj[shellnb]);
   pliststruct *cpl = coreobjlist->plist, *spl = shellobjlist->plist, *pixt;
 
-  int         xc=PLIST(cpl+cobj->firstpix,x), yc=PLIST(cpl+cobj->firstpix,y);
+  int64_t xc = PLIST(cpl + cobj->firstpix, x), yc = PLIST(cpl + cobj->firstpix, y);
 
-  for (pixt = spl+sobj->firstpix; pixt>=spl; pixt = spl+PLIST(pixt,nextpix))
-    if ((PLIST(pixt,x) == xc) && (PLIST(pixt,y) == yc))
+  for (pixt = spl + sobj->firstpix; pixt >= spl; pixt = spl + PLIST(pixt, nextpix)) {
+    if ((PLIST(pixt, x) == xc) && (PLIST(pixt, y) == yc)) {
       return 1;
+    }
+  }
 
   return 0;
 }
@@ -404,14 +418,19 @@ int belong(int corenb, objliststruct *coreobjlist,
 /*
 Create pixel-index submap for deblending.
 */
-int *createsubmap(objliststruct *objlistin, int no,
-		  int *subx, int *suby, int *subw, int *subh)
-{
-  objstruct	*obj;
-  pliststruct	*pixel, *pixt;
-  int		i, n, xmin,ymin, w, *pix, *pt, *submap;
-
-  obj = objlistin->obj+no;
+int64_t * createsubmap(
+    objliststruct * objlistin,
+    int64_t no,
+    int64_t * subx,
+    int64_t * suby,
+    int64_t * subw,
+    int64_t * subh
+) {
+  objstruct * obj;
+  pliststruct *pixel, *pixt;
+  int64_t i, n, xmin, ymin, w, *pix, *pt, *submap;
+
+  obj = objlistin->obj + no;
   pixel = objlistin->plist;
 
   *subx = xmin = obj->xmin;
@@ -419,18 +438,19 @@ int *createsubmap(objliststruct *objlistin, int no,
   *subw = w = obj->xmax - xmin + 1;
   *subh = obj->ymax - ymin + 1;
 
-  n = w**subh;
-  if (!(submap = pix = malloc(n*sizeof(int))))
+  n = w * *subh;
+  if (!(submap = pix = malloc(n * sizeof(int64_t)))) {
     return NULL;
+  }
   pt = pix;
-  for (i=n; i--;)
+  for (i = n; i--;) {
     *(pt++) = -1;
+  }
 
-  for (i=obj->firstpix; i!=-1; i=PLIST(pixt,nextpix))
-    {
-      pixt = pixel+i;
-      *(pix+(PLIST(pixt,x)-xmin) + (PLIST(pixt,y)-ymin)*w) = i;
-    }
+  for (i = obj->firstpix; i != -1; i = PLIST(pixt, nextpix)) {
+    pixt = pixel + i;
+    *(pix + (PLIST(pixt, x) - xmin) + (PLIST(pixt, y) - ymin) * w) = i;
+  }
 
   return submap;
 }
diff --git a/src/extract.c b/src/extract.c
index 93e6d73..7bffe95 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -1,80 +1,112 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /* Note: was scan.c in SExtractor. */
 
 #include <math.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "extract.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "extract.h"
 
-#define DETECT_MAXAREA 0             /* replaces prefs.ext_maxarea */
-#define	WTHRESH_CONVFAC	1e-4         /* Factor to apply to weights when */
-			             /* thresholding filtered weight-maps */
+#define DETECT_MAXAREA 0 /* replaces prefs.ext_maxarea */
+#define WTHRESH_CONVFAC 1e-4 /* Factor to apply to weights when */
+/* thresholding filtered weight-maps */
 
 /* globals */
-_Thread_local int plistexist_cdvalue, plistexist_thresh, plistexist_var;
-_Thread_local int plistoff_value, plistoff_cdvalue, plistoff_thresh, plistoff_var;
-_Thread_local int plistsize;
+_Thread_local int64_t plistexist_cdvalue, plistexist_thresh, plistexist_var;
+_Thread_local int64_t plistoff_value, plistoff_cdvalue, plistoff_thresh, plistoff_var;
+_Thread_local int64_t plistsize;
 _Thread_local unsigned int randseed;
 static _Atomic size_t extract_pixstack = 300000;
 
 /* get and set pixstack */
-void sep_set_extract_pixstack(size_t val)
-{
+void sep_set_extract_pixstack(size_t val) {
   extract_pixstack = val;
 }
 
-size_t sep_get_extract_pixstack()
-{
+size_t sep_get_extract_pixstack() {
   return extract_pixstack;
 }
 
-int sortit(infostruct *info, objliststruct *objlist, int minarea,
-	   objliststruct *finalobjlist,
-	   int deblend_nthresh, double deblend_mincont, double gain,
-	   deblendctx *deblendctx);
+int sortit(
+    infostruct * info,
+    objliststruct * objlist,
+    int minarea,
+    objliststruct * finalobjlist,
+    int deblend_nthresh,
+    double deblend_mincont,
+    double gain,
+    deblendctx * deblendctx
+);
+int segsortit(
+    infostruct * info,
+    objliststruct * objlist,
+    objliststruct * finalobjlist,
+    double gain
+);
 void plistinit(int hasconv, int hasvar);
-void clean(objliststruct *objlist, double clean_param, int *survives);
-PIXTYPE get_mean_thresh(infostruct *info, pliststruct *pixel);
-int convert_to_catalog(objliststruct *objlist, const int *survives,
-                       sep_catalog *cat, int w, int include_pixels);
-
-int arraybuffer_init(arraybuffer *buf, const void *arr, int dtype, int w, int h,
-                     int bufw, int bufh);
-void arraybuffer_readline(arraybuffer *buf);
-void arraybuffer_free(arraybuffer *buf);
+void clean(objliststruct * objlist, double clean_param, int * survives);
+PIXTYPE get_mean_thresh(infostruct * info, pliststruct * pixel);
+int convert_to_catalog(
+    objliststruct * objlist,
+    const int * survives,
+    sep_catalog * cat,
+    int64_t w,
+    int include_pixels
+);
+
+int arraybuffer_init(
+    arraybuffer * buf,
+    const void * arr,
+    int dtype,
+    int64_t w,
+    int64_t h,
+    int64_t bufw,
+    int64_t bufh
+);
+void arraybuffer_readline(arraybuffer * buf);
+void arraybuffer_free(arraybuffer * buf);
 
 /********************* array buffer functions ********************************/
 
 /* initialize buffer */
 /* bufw must be less than or equal to w */
-int arraybuffer_init(arraybuffer *buf, const void *arr, int dtype, int w, int h,
-                     int bufw, int bufh)
-{
-  int status, yl;
+int arraybuffer_init(
+    arraybuffer * buf,
+    const void * arr,
+    int dtype,
+    int64_t w,
+    int64_t h,
+    int64_t bufw,
+    int64_t bufh
+) {
+  int status;
+  int64_t yl;
   status = RETURN_OK;
 
   /* data info */
@@ -84,54 +116,55 @@ int arraybuffer_init(arraybuffer *buf, const void *arr, int dtype, int w, int h,
 
   /* buffer array info */
   buf->bptr = NULL;
-  QMALLOC(buf->bptr, PIXTYPE, bufw*bufh, status);
+  QMALLOC(buf->bptr, PIXTYPE, bufw * bufh, status);
   buf->bw = bufw;
   buf->bh = bufh;
 
   /* pointers to within buffer */
-  buf->midline = buf->bptr + bufw*(bufh/2);  /* ptr to middle buffer line */
-  buf->lastline = buf->bptr + bufw*(bufh-1);  /* ptr to last buffer line */
+  buf->midline = buf->bptr + bufw * (bufh / 2); /* ptr to middle buffer line */
+  buf->lastline = buf->bptr + bufw * (bufh - 1); /* ptr to last buffer line */
 
   status = get_array_converter(dtype, &(buf->readline), &(buf->elsize));
-  if (status != RETURN_OK)
+  if (status != RETURN_OK) {
     goto exit;
+  }
 
   /* initialize yoff */
   buf->yoff = -bufh;
 
   /* read in lines until the first data line is one line above midline */
-  for (yl=0; yl < bufh - bufh/2 - 1; yl++)
+  for (yl = 0; yl < bufh - bufh / 2 - 1; yl++) {
     arraybuffer_readline(buf);
+  }
 
   return status;
 
- exit:
+exit:
   free(buf->bptr);
   buf->bptr = NULL;
   return status;
 }
 
 /* read a line into the buffer at the top, shifting all lines down one */
-void arraybuffer_readline(arraybuffer *buf)
-{
-  PIXTYPE *line;
-  int y;
+void arraybuffer_readline(arraybuffer * buf) {
+  PIXTYPE * line;
+  int64_t y;
 
   /* shift all lines down one */
-  for (line = buf->bptr; line < buf->lastline; line += buf->bw)
+  for (line = buf->bptr; line < buf->lastline; line += buf->bw) {
     memcpy(line, line + buf->bw, sizeof(PIXTYPE) * buf->bw);
+  }
 
   /* which image line now corresponds to the last line in buffer? */
   buf->yoff++;
   y = buf->yoff + buf->bh - 1;
 
-  if (y < buf->dh)
-    buf->readline(buf->dptr + buf->elsize * buf->dw * y, buf->dw,
-                  buf->lastline);
+  if (y < buf->dh) {
+    buf->readline(buf->dptr + buf->elsize * buf->dw * y, buf->dw, buf->lastline);
+  }
 }
 
-void arraybuffer_free(arraybuffer *buf)
-{
+void arraybuffer_free(arraybuffer * buf) {
   free(buf->bptr);
   buf->bptr = NULL;
 }
@@ -154,67 +187,77 @@ void arraybuffer_free(arraybuffer *buf)
  * So, this routine sets masked pixels to zero in the image buffer and
  * infinity in the noise buffer (if present). It affects the first
  */
-void apply_mask_line(arraybuffer *mbuf, arraybuffer *imbuf, arraybuffer *nbuf)
-{
-  int i;
-
-  for (i=0; i<mbuf->bw; i++)
-    {
-      if (mbuf->lastline[i] > 0.0)
-        {
-          imbuf->lastline[i] = 0.0;
-          if (nbuf)
-            nbuf->lastline[i] = BIG;
-        }
+void apply_mask_line(arraybuffer * mbuf, arraybuffer * imbuf, arraybuffer * nbuf) {
+  int64_t i;
+
+  for (i = 0; i < mbuf->bw; i++) {
+    if (mbuf->lastline[i] > 0.0) {
+      imbuf->lastline[i] = 0.0;
+      if (nbuf) {
+        nbuf->lastline[i] = BIG;
+      }
     }
+  }
 }
 
 /****************************** extract **************************************/
-int sep_extract(const sep_image *image, float thresh, int thresh_type,
-                int minarea, const float *conv, int convw, int convh,
-		int filter_type, int deblend_nthresh, double deblend_cont,
-		int clean_flag, double clean_param,
-		sep_catalog **catalog)
-{
-  arraybuffer       dbuf, nbuf, mbuf;
-  infostruct        curpixinfo, initinfo, freeinfo;
-  objliststruct     objlist;
-  char              newmarker;
-  size_t            mem_pixstack;
-  int               nposize, oldnposize;
-  int               w, h;
-  int               co, i, luflag, pstop, xl, xl2, yl, cn;
-  int               stacksize, convn, status;
-  int               bufh;
-  int               isvarthresh, isvarnoise;
-  short             trunflag;
-  PIXTYPE           relthresh, cdnewsymbol, pixvar, pixsig;
-  float             sum;
-  pixstatus         cs, ps;
-
-  infostruct        *info, *store;
-  objliststruct     *finalobjlist;
-  pliststruct	    *pixel, *pixt;
-  char              *marker;
-  PIXTYPE           *scan, *cdscan, *wscan, *dummyscan;
-  PIXTYPE           *sigscan, *workscan;
-  float             *convnorm;
-  int               *start, *end, *survives;
-  pixstatus         *psstack;
-  char              errtext[512];
-  sep_catalog       *cat;
-  deblendctx        deblendctx;
+int sep_extract(
+    const sep_image * image,
+    float thresh,
+    int thresh_type,
+    int minarea,
+    const float * conv,
+    int64_t convw,
+    int64_t convh,
+    int filter_type,
+    int deblend_nthresh,
+    double deblend_cont,
+    int clean_flag,
+    double clean_param,
+    sep_catalog ** catalog
+) {
+  arraybuffer dbuf, nbuf, mbuf, sbuf;
+  infostruct curpixinfo, initinfo, freeinfo;
+  objliststruct objlist;
+  char newmarker;
+  size_t mem_pixstack;
+  int64_t nposize, oldnposize;
+  int64_t w, h;
+  int64_t co, i, pstop, xl, xl2, yl, cn;
+  int64_t ididx, numids, totnpix;
+  int64_t prevpix, bufh;
+  int64_t stacksize, convn;
+  int status, isvarthresh, isvarnoise, luflag;
+  short trunflag;
+  PIXTYPE relthresh, cdnewsymbol, pixvar, pixsig;
+  float sum;
+  pixstatus cs, ps;
+
+  infostruct *info, *store, *idinfo;
+  objliststruct * finalobjlist;
+  pliststruct *pixel, *pixt;
+  char * marker;
+  PIXTYPE *scan, *cdscan, *wscan, *dummyscan, *sscan;
+  PIXTYPE *sigscan, *workscan;
+  float * convnorm;
+  int64_t *start, *end, *cumcounts;
+  int * survives;
+  pixstatus * psstack;
+  char errtext[512];
+  sep_catalog * cat;
+  deblendctx deblendctx;
 
   status = RETURN_OK;
   pixel = NULL;
   convnorm = NULL;
-  scan = wscan = cdscan = dummyscan = NULL;
+  scan = wscan = cdscan = dummyscan = sscan = NULL;
   sigscan = workscan = NULL;
   info = NULL;
   store = NULL;
+  idinfo = NULL;
   marker = NULL;
   psstack = NULL;
-  start = end = NULL;
+  start = end = cumcounts = NULL;
   finalobjlist = NULL;
   survives = NULL;
   cat = NULL;
@@ -222,6 +265,10 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
   sum = 0.0;
   w = image->w;
   h = image->h;
+
+  numids = (image->numids) ? image->numids : 1;
+
+  prevpix = 0;
   isvarthresh = 0;
   relthresh = 0.0;
   pixvar = 0.0;
@@ -231,45 +278,57 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
 
   mem_pixstack = sep_get_extract_pixstack();
 
+  if (image->segmap) {
+    QCALLOC(cumcounts, int64_t, numids, status);
+    QCALLOC(idinfo, infostruct, numids, status);
+    totnpix = 0;
+    for (i = 0; i < numids; i++) {
+      cumcounts[i] = totnpix;
+      totnpix += image->idcounts[i];
+    }
+    if ((size_t)totnpix > mem_pixstack) {
+      goto exit;
+    }
+  }
+
   /* seed the random number generator consistently on each call to get
    * consistent results. rand_r() is used in deblending. */
   randseed = 1;
 
   /* Noise characteristics of the image: None, scalar or variable? */
-  if (image->noise_type == SEP_NOISE_NONE) { } /* nothing to do */
-  else if (image->noise == NULL) {
+  if (image->noise_type == SEP_NOISE_NONE) {
+  } /* nothing to do */
+  else if (image->noise == NULL)
+  {
     /* noise is constant; we can set pixel noise now. */
     if (image->noise_type == SEP_NOISE_STDDEV) {
       pixsig = image->noiseval;
       pixvar = pixsig * pixsig;
-    }
-    else if (image->noise_type == SEP_NOISE_VAR) {
+    } else if (image->noise_type == SEP_NOISE_VAR) {
       pixvar = image->noiseval;
       pixsig = sqrt(pixvar);
-    }
-    else {
+    } else {
       return UNKNOWN_NOISE_TYPE;
     }
-  }
-  else {
+  } else {
     /* noise is variable; we deal with setting pixvar and pixsig at each
      * pixel. */
     isvarnoise = 1;
   }
 
   /* Deal with relative thresholding. (For an absolute threshold
-  *  nothing needs to be done, as `thresh` should already contain the constant
-  *  threshold, and `isvarthresh` is already 0.) */
+   *  nothing needs to be done, as `thresh` should already contain the constant
+   *  threshold, and `isvarthresh` is already 0.) */
   if (thresh_type == SEP_THRESH_REL) {
-
     /* The image must have noise information. */
-    if (image->noise_type == SEP_NOISE_NONE) return RELTHRESH_NO_NOISE;
+    if (image->noise_type == SEP_NOISE_NONE) {
+      return RELTHRESH_NO_NOISE;
+    }
 
-    isvarthresh = isvarnoise;  /* threshold is variable if noise is */
+    isvarthresh = isvarnoise; /* threshold is variable if noise is */
     if (isvarthresh) {
       relthresh = thresh; /* used below to set `thresh` for each pixel. */
-    }
-    else {
+    } else {
       /* thresh is constant; convert relative threshold to absolute */
       thresh *= pixsig;
     }
@@ -279,16 +338,17 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
   objlist.thresh = thresh;
 
   /*Allocate memory for buffers */
-  stacksize = w+1;
+  stacksize = w + 1;
   QMALLOC(info, infostruct, stacksize, status);
   QCALLOC(store, infostruct, stacksize, status);
   QMALLOC(marker, char, stacksize, status);
   QMALLOC(dummyscan, PIXTYPE, stacksize, status);
   QMALLOC(psstack, pixstatus, stacksize, status);
-  QCALLOC(start, int, stacksize, status);
-  QMALLOC(end, int, stacksize, status);
-  if ((status = allocdeblend(deblend_nthresh, w, h, &deblendctx)) != RETURN_OK)
+  QCALLOC(start, int64_t, stacksize, status);
+  QMALLOC(end, int64_t, stacksize, status);
+  if ((status = allocdeblend(deblend_nthresh, w, h, &deblendctx)) != RETURN_OK) {
     goto exit;
+  }
 
   /* Initialize buffers for input array(s).
    * The buffer size depends on whether or not convolution is active.
@@ -296,40 +356,65 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
    * the buffer height equals the height of the convolution kernel.
    */
   bufh = conv ? convh : 1;
-  status = arraybuffer_init(&dbuf, image->data, image->dtype, w, h, stacksize,
-                            bufh);
-  if (status != RETURN_OK) goto exit;
+  status = arraybuffer_init(&dbuf, image->data, image->dtype, w, h, stacksize, bufh);
+  if (status != RETURN_OK) {
+    goto exit;
+  }
   if (isvarnoise) {
-      status = arraybuffer_init(&nbuf, image->noise, image->ndtype, w, h,
-                                stacksize, bufh);
-      if (status != RETURN_OK) goto exit;
+    status =
+        arraybuffer_init(&nbuf, image->noise, image->ndtype, w, h, stacksize, bufh);
+    if (status != RETURN_OK) {
+      goto exit;
     }
+  }
   if (image->mask) {
-      status = arraybuffer_init(&mbuf, image->mask, image->mdtype, w, h,
-                                stacksize, bufh);
-      if (status != RETURN_OK) goto exit;
+    status = arraybuffer_init(&mbuf, image->mask, image->mdtype, w, h, stacksize, bufh);
+    if (status != RETURN_OK) {
+      goto exit;
+    }
+  }
+  if (image->segmap) {
+    status =
+        arraybuffer_init(&sbuf, image->segmap, image->sdtype, w, h, stacksize, bufh);
+    if (status != RETURN_OK) {
+      goto exit;
     }
+  }
 
   /* `scan` (or `wscan`) is always a pointer to the current line being
    * processed. It might be the only line in the buffer, or it might be the
    * middle line. */
   scan = dbuf.midline;
-  if (isvarnoise)
+  if (isvarnoise) {
     wscan = nbuf.midline;
+  }
 
   /* More initializations */
   initinfo.pixnb = 0;
   initinfo.flag = 0;
   initinfo.firstpix = initinfo.lastpix = -1;
 
-  for (xl=0; xl<stacksize; xl++)
-    {
-      marker[xl]  = 0;
-      dummyscan[xl] = -BIG;
+  if (image->segmap) {
+    sscan = sbuf.midline;
+    for (i = 0; i < numids; i++) {
+      idinfo[i].pixnb = 0;
+      idinfo[i].flag = 0;
+      idinfo[i].firstpix = idinfo[i].lastpix = -1;
     }
+  }
+
+  for (xl = 0; xl < stacksize; xl++) {
+    marker[xl] = 0;
+    dummyscan[xl] = -BIG;
+  }
 
   co = pstop = 0;
-  objlist.nobj = 1;
+  if (image->segmap) {
+    objlist.nobj = numids;
+    QMALLOC(objlist.obj, objstruct, numids, status);
+  } else {
+    objlist.nobj = 1;
+  }
   curpixinfo.pixnb = 1;
 
   /* Init finalobjlist */
@@ -341,375 +426,412 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
 
   /* Allocate memory for the pixel list */
   plistinit((conv != NULL), (image->noise_type != SEP_NOISE_NONE));
-  if (!(pixel = objlist.plist = malloc(nposize=mem_pixstack*plistsize)))
-    {
-      status = MEMORY_ALLOC_ERROR;
-      goto exit;
-    }
+  if (!(pixel = objlist.plist = malloc(nposize = mem_pixstack * plistsize))) {
+    status = MEMORY_ALLOC_ERROR;
+    goto exit;
+  }
 
   /*----- at the beginning, "free" object fills the whole pixel list */
   freeinfo.firstpix = 0;
-  freeinfo.lastpix = nposize-plistsize;
+  freeinfo.lastpix = nposize - plistsize;
   pixt = pixel;
-  for (i=plistsize; i<nposize; i += plistsize, pixt += plistsize)
+  for (i = plistsize; i < nposize; i += plistsize, pixt += plistsize) {
     PLIST(pixt, nextpix) = i;
+  }
   PLIST(pixt, nextpix) = -1;
 
   /* can only use a matched filter when convolving and when there is a noise
    * array */
-  if (!(conv && isvarnoise))
+  if (!(conv && isvarnoise)) {
     filter_type = SEP_FILTER_CONV;
+  }
 
-  if (conv)
-    {
-      /* allocate memory for convolved buffers */
-      QMALLOC(cdscan, PIXTYPE, stacksize, status);
-      if (filter_type == SEP_FILTER_MATCHED)
-        {
-          QMALLOC(sigscan, PIXTYPE, stacksize, status);
-          QMALLOC(workscan, PIXTYPE, stacksize, status);
-        }
+  if (conv) {
+    /* allocate memory for convolved buffers */
+    QMALLOC(cdscan, PIXTYPE, stacksize, status);
+    if (filter_type == SEP_FILTER_MATCHED) {
+      QMALLOC(sigscan, PIXTYPE, stacksize, status);
+      QMALLOC(workscan, PIXTYPE, stacksize, status);
+    }
 
-      /* normalize the filter */
-      convn = convw * convh;
-      QMALLOC(convnorm, PIXTYPE, convn, status);
-      for (i=0; i<convn; i++)
-	sum += fabs(conv[i]);
-      for (i=0; i<convn; i++)
-	convnorm[i] = conv[i] / sum;
+    /* normalize the filter */
+    convn = convw * convh;
+    QMALLOC(convnorm, PIXTYPE, convn, status);
+    for (i = 0; i < convn; i++) {
+      sum += fabs(conv[i]);
     }
+    for (i = 0; i < convn; i++) {
+      convnorm[i] = conv[i] / sum;
+    }
+  }
 
   /*----- MAIN LOOP ------ */
-  for (yl=0; yl<=h; yl++)
-    {
-
-      ps = COMPLETE;
-      cs = NONOBJECT;
-
-      /* Need an empty line for Lutz' algorithm to end gracely */
-      if (yl==h)
-	{
-	  if (conv)
-	    {
-              free(cdscan);  // cdscan set to dummyscan below
-              if (filter_type == SEP_FILTER_MATCHED)
-              {
-                  for (xl=0; xl<stacksize; xl++)
-                  {
-                      sigscan[xl] = -BIG;
-                  }
-              }
-	    }
-	  cdscan = dummyscan;
-	}
+  for (yl = 0; yl <= h; yl++) {
+    ps = COMPLETE;
+    cs = NONOBJECT;
+
+    /* Need an empty line for Lutz' algorithm to end gracely */
+    if (yl == h) {
+      if (conv) {
+        free(cdscan);  // cdscan set to dummyscan below
+        if (filter_type == SEP_FILTER_MATCHED) {
+          for (xl = 0; xl < stacksize; xl++) {
+            sigscan[xl] = -BIG;
+          }
+        }
+      }
+      cdscan = dummyscan;
+    } else {
+      arraybuffer_readline(&dbuf);
+      if (isvarnoise) {
+        arraybuffer_readline(&nbuf);
+      }
+      if (image->mask) {
+        arraybuffer_readline(&mbuf);
+        apply_mask_line(&mbuf, &dbuf, (isvarnoise ? &nbuf : NULL));
+      }
+      if (image->segmap) {
+        arraybuffer_readline(&sbuf);
+      }
+
+      /* filter the lines */
+      if (conv) {
+        status = convolve(&dbuf, yl, convnorm, convw, convh, cdscan);
+        if (status != RETURN_OK) {
+          goto exit;
+        }
 
-      else
-	{
-          arraybuffer_readline(&dbuf);
-          if (isvarnoise)
-            arraybuffer_readline(&nbuf);
-          if (image->mask)
-            {
-              arraybuffer_readline(&mbuf);
-              apply_mask_line(&mbuf, &dbuf, (isvarnoise? &nbuf: NULL));
-            }
+        if (filter_type == SEP_FILTER_MATCHED) {
+          status = matched_filter(
+              &dbuf,
+              &nbuf,
+              yl,
+              convnorm,
+              convw,
+              convh,
+              workscan,
+              sigscan,
+              image->noise_type
+          );
+
+          if (status != RETURN_OK) {
+            goto exit;
+          }
+        }
+      } else {
+        cdscan = scan;
+      }
+    }
 
-	  /* filter the lines */
-	  if (conv)
-	    {
-              status = convolve(&dbuf, yl, convnorm, convw, convh, cdscan);
-              if (status != RETURN_OK)
-                goto exit;
+    trunflag = (yl == 0 || yl == h - 1) ? SEP_OBJ_TRUNC : 0;
+
+    for (xl = 0; xl <= w; xl++) {
+      if (xl == w) {
+        cdnewsymbol = -BIG;
+      } else {
+        cdnewsymbol = cdscan[xl];
+      }
+
+      newmarker = marker[xl]; /* marker at this pixel */
+      marker[xl] = 0;
+
+      curpixinfo.flag = trunflag;
+
+      /* set pixel variance/noise based on noise array */
+      if (isvarthresh) {
+        if (xl == w || yl == h) {
+          pixsig = pixvar = 0.0;
+        } else if (image->noise_type == SEP_NOISE_VAR) {
+          pixvar = wscan[xl];
+          pixsig = sqrt(pixvar);
+        } else if (image->noise_type == SEP_NOISE_STDDEV) {
+          pixsig = wscan[xl];
+          pixvar = pixsig * pixsig;
+        } else {
+          status = UNKNOWN_NOISE_TYPE;
+          goto exit;
+        }
 
-	      if (filter_type == SEP_FILTER_MATCHED)
-                {
-                  status = matched_filter(&dbuf, &nbuf, yl, convnorm, convw,
-                                          convh, workscan, sigscan,
-                                          image->noise_type);
+        /* set `thresh` (This is needed later, even
+         * if filter_type is SEP_FILTER_MATCHED */
+        thresh = relthresh * pixsig;
+      }
+
+      /* luflag: is pixel above thresh (Y/N)? */
+      /* First check if segmap exists */
+      if (image->segmap) {
+        if ((sscan[xl] > 0) && (xl != w) && (yl != h)) {
+          if (xl == 0 || xl == w - 1) {
+            curpixinfo.flag |= SEP_OBJ_TRUNC;
+          }
 
-                  if (status != RETURN_OK)
-                    goto exit;
-                }
+          for (ididx = 0; ididx < numids; ididx++) {
+            if (image->segids[ididx] == (int64_t)sscan[xl]) {
+              pixt = pixel + prevpix * plistsize;
+              prevpix = cumcounts[ididx] + idinfo[ididx].pixnb;
+              pixt = pixel + prevpix * plistsize;
+
+              PLIST(pixt, x) = xl;
+              PLIST(pixt, y) = yl;
+              PLIST(pixt, value) = scan[xl];
+              if (PLISTEXIST(cdvalue)) {
+                PLISTPIX(pixt, cdvalue) = cdnewsymbol;
+              };
+              if (PLISTEXIST(var)) {
+                PLISTPIX(pixt, var) = pixvar;
+              };
+              if (PLISTEXIST(thresh)) {
+                PLISTPIX(pixt, thresh) = thresh;
+              };
+
+              if (idinfo[ididx].pixnb == 0) {
+                idinfo[ididx].firstpix = prevpix * plistsize;
+                idinfo[ididx].pixnb = 1;
+              } else if (idinfo[ididx].pixnb == image->idcounts[ididx] - 1) {
+                idinfo[ididx].pixnb++;
+                idinfo[ididx].lastpix = prevpix * plistsize;
+                PLIST(pixt, nextpix) = -1;
+              } else {
+                idinfo[ididx].pixnb++;
+              };
+              break;
             }
-	  else
-	    {
-	      cdscan = scan;
-	    }
-	}
-
-      trunflag = (yl==0 || yl==h-1)? SEP_OBJ_TRUNC: 0;
-
-      for (xl=0; xl<=w; xl++)
-	{
-	  if (xl == w)
-	    cdnewsymbol = -BIG;
-	  else
-	    cdnewsymbol = cdscan[xl];
-
-	  newmarker = marker[xl];  /* marker at this pixel */
-	  marker[xl] = 0;
-
-	  curpixinfo.flag = trunflag;
-
-          /* set pixel variance/noise based on noise array */
-          if (isvarthresh) {
-            if (xl == w || yl == h) {
-              pixsig = pixvar = 0.0;
+          }
+        }
+      } else {
+        if (filter_type == SEP_FILTER_MATCHED) {
+          luflag = ((xl != w) && (sigscan[xl] > relthresh)) ? 1 : 0;
+        } else {
+          luflag = cdnewsymbol > thresh ? 1 : 0;
+        }
+
+        if (luflag) {
+          /* flag the current object if we're near the image bounds */
+          if (xl == 0 || xl == w - 1) {
+            curpixinfo.flag |= SEP_OBJ_TRUNC;
+          };
+
+          /* point pixt to first free pixel in pixel list */
+          /* and increment the "first free pixel" */
+          pixt = pixel + (cn = freeinfo.firstpix);
+          freeinfo.firstpix = PLIST(pixt, nextpix);
+          curpixinfo.lastpix = curpixinfo.firstpix = cn;
+
+          /* set values for the new pixel */
+          PLIST(pixt, nextpix) = -1;
+          PLIST(pixt, x) = xl;
+          PLIST(pixt, y) = yl;
+          PLIST(pixt, value) = scan[xl];
+          if (PLISTEXIST(cdvalue)) {
+            PLISTPIX(pixt, cdvalue) = cdnewsymbol;
+          };
+          if (PLISTEXIST(var)) {
+            PLISTPIX(pixt, var) = pixvar;
+          };
+          if (PLISTEXIST(thresh)) {
+            PLISTPIX(pixt, thresh) = thresh;
+          };
+
+          /* Check if we have run out of free pixels in objlist.plist */
+          if (freeinfo.firstpix == freeinfo.lastpix) {
+            status = PIXSTACK_FULL;
+            sprintf(
+                errtext,
+                "The limit of %d active object pixels over the "
+                "detection threshold was reached. Check that "
+                "the image is background subtracted and the "
+                "detection threshold is not too low. If you "
+                "need to increase the limit, use "
+                "set_extract_pixstack.",
+                (int)mem_pixstack
+            );
+            put_errdetail(errtext);
+            goto exit;
+
+            /* The code in the rest of this block increases the
+             * stack size as needed. Currently, it is never
+             * executed. This is because it isn't clear that
+             * this is a good idea: most times when the stack
+             * overflows it is due to user error: too-low
+             * threshold or image not background subtracted. */
+
+            /* increase the stack size */
+            oldnposize = nposize;
+            mem_pixstack = (int)(mem_pixstack * 2);
+            nposize = mem_pixstack * plistsize;
+            pixel = realloc(pixel, nposize);
+            objlist.plist = pixel;
+            if (!pixel) {
+              status = MEMORY_ALLOC_ERROR;
+              goto exit;
             }
-            else if (image->noise_type == SEP_NOISE_VAR) {
-              pixvar = wscan[xl];
-              pixsig = sqrt(pixvar);
+
+            /* set next free pixel to the start of the new block
+             * and link up all the pixels in the new block */
+            PLIST(pixel + freeinfo.firstpix, nextpix) = oldnposize;
+            pixt = pixel + oldnposize;
+            for (i = oldnposize + plistsize; i < nposize;
+                 i += plistsize, pixt += plistsize)
+            {
+              PLIST(pixt, nextpix) = i;
             }
-            else if (image->noise_type == SEP_NOISE_STDDEV) {
-              pixsig = wscan[xl];
-              pixvar = pixsig * pixsig;
+            PLIST(pixt, nextpix) = -1;
+
+            /* last free pixel is now at the end of the new block */
+            freeinfo.lastpix = nposize - plistsize;
+          }
+          /*------------------------------------------------------------*/
+
+          /* if the current status on this line is not already OBJECT... */
+          /* start segment */
+          if (cs != OBJECT) {
+            cs = OBJECT;
+            if (ps == OBJECT) {
+              if (start[co] == UNKNOWN) {
+                marker[xl] = 'S';
+                start[co] = xl;
+              } else {
+                marker[xl] = 's';
+              }
+            } else {
+              psstack[pstop++] = ps;
+              marker[xl] = 'S';
+              start[++co] = xl;
+              ps = COMPLETE;
+              info[co] = initinfo;
             }
-            else {
-              status = UNKNOWN_NOISE_TYPE;
-              goto exit;
+          }
+
+        } /* closes if pixel above threshold */
+
+        /* process new marker ---------------------------------------------*/
+        /* newmarker is marker[ ] at this pixel position before we got to
+          it. We'll only enter this if marker[ ] was set on a previous
+          loop iteration.   */
+        if (newmarker) {
+          if (newmarker == 'S') {
+            psstack[pstop++] = ps;
+            if (cs == NONOBJECT) {
+              psstack[pstop++] = COMPLETE;
+              info[++co] = store[xl];
+              start[co] = UNKNOWN;
+            } else {
+              update(&info[co], &store[xl], pixel);
             }
+            ps = OBJECT;
+          } else if (newmarker == 's') {
+            if ((cs == OBJECT) && (ps == COMPLETE)) {
+              pstop--;
+              xl2 = start[co];
+              update(&info[co - 1], &info[co], pixel);
+              if (start[--co] == UNKNOWN) {
+                start[co] = xl2;
+              } else {
+                marker[xl2] = 's';
+              }
+            }
+            ps = OBJECT;
+          } else if (newmarker == 'f') {
+            ps = INCOMPLETE;
+          } else if (newmarker == 'F') {
+            ps = psstack[--pstop];
+            if ((cs == NONOBJECT) && (ps == COMPLETE)) {
+              if (start[co] == UNKNOWN) {
+                if ((int64_t)info[co].pixnb >= minarea) {
+                  /* update threshold before object is processed */
+                  if (PLISTEXIST(thresh)) {
+                    objlist.thresh = get_mean_thresh(&info[co], objlist.plist);
+                  } else {
+                    objlist.thresh = thresh;
+                  }
 
-            /* set `thresh` (This is needed later, even
-             * if filter_type is SEP_FILTER_MATCHED */
-            thresh = relthresh * pixsig;
+                  status = sortit(
+                      &info[co],
+                      &objlist,
+                      minarea,
+                      finalobjlist,
+                      deblend_nthresh,
+                      deblend_cont,
+                      image->gain,
+                      &deblendctx
+                  );
+
+                  if (status != RETURN_OK) {
+                    goto exit;
+                  };
+                }
+
+                /* free the chain-list */
+                PLIST(pixel + info[co].lastpix, nextpix) = freeinfo.firstpix;
+                freeinfo.firstpix = info[co].firstpix;
+              } else {
+                marker[end[co]] = 'F';
+                store[start[co]] = info[co];
+              }
+              co--;
+              ps = psstack[--pstop];
+            }
           }
+        }
+        /* end of if (newmarker) ------------------------------------------*/
+
+        /* update the info or end segment */
+        if (luflag) {
+          update(&info[co], &curpixinfo, pixel);
+        } else if (cs == OBJECT) {
+          cs = NONOBJECT;
+          if (ps != COMPLETE) {
+            marker[xl] = 'f';
+            end[co] = xl;
+          } else {
+            ps = psstack[--pstop];
+            marker[xl] = 'F';
+            store[start[co]] = info[co];
+            co--;
+          }
+        }
+      }
+    } /*------------ End of the loop over the x's -----------------------*/
+  } /*---------------- End of the loop over the y's -----------------------*/
 
-          /* luflag: is pixel above thresh (Y/N)? */
-          if (filter_type == SEP_FILTER_MATCHED)
-            luflag = ((xl != w) && (sigscan[xl] > relthresh))? 1: 0;
-          else
-            luflag = cdnewsymbol > thresh? 1: 0;
-
-	  if (luflag)
-	    {
-	      /* flag the current object if we're near the image bounds */
-	      if (xl==0 || xl==w-1)
-		curpixinfo.flag |= SEP_OBJ_TRUNC;
-
-	      /* point pixt to first free pixel in pixel list */
-	      /* and increment the "first free pixel" */
-	      pixt = pixel + (cn=freeinfo.firstpix);
-	      freeinfo.firstpix = PLIST(pixt, nextpix);
-	      curpixinfo.lastpix = curpixinfo.firstpix = cn;
-
-	      /* set values for the new pixel */
-	      PLIST(pixt, nextpix) = -1;
-	      PLIST(pixt, x) = xl;
-	      PLIST(pixt, y) = yl;
-	      PLIST(pixt, value) = scan[xl];
-	      if (PLISTEXIST(cdvalue))
-		PLISTPIX(pixt, cdvalue) = cdnewsymbol;
-	      if (PLISTEXIST(var))
-		PLISTPIX(pixt, var) = pixvar;
-	      if (PLISTEXIST(thresh))
-		PLISTPIX(pixt, thresh) = thresh;
-
-	      /* Check if we have run out of free pixels in objlist.plist */
-	      if (freeinfo.firstpix==freeinfo.lastpix)
-		{
-		  status = PIXSTACK_FULL;
-		  sprintf(errtext,
-			  "The limit of %d active object pixels over the "
-			  "detection threshold was reached. Check that "
-			  "the image is background subtracted and the "
-			  "detection threshold is not too low. If you "
-                          "need to increase the limit, use "
-                          "set_extract_pixstack.",
-			  (int)mem_pixstack);
-		  put_errdetail(errtext);
-		  goto exit;
-
-		  /* The code in the rest of this block increases the
-		   * stack size as needed. Currently, it is never
-		   * executed. This is because it isn't clear that
-		   * this is a good idea: most times when the stack
-		   * overflows it is due to user error: too-low
-		   * threshold or image not background subtracted. */
-
-		  /* increase the stack size */
-		  oldnposize = nposize;
- 		  mem_pixstack = (int)(mem_pixstack * 2);
-		  nposize = mem_pixstack * plistsize;
-		  pixel = realloc(pixel, nposize);
-		  objlist.plist = pixel;
-		  if (!pixel)
-		    {
-		      status = MEMORY_ALLOC_ERROR;
-		      goto exit;
-		    }
-
-		  /* set next free pixel to the start of the new block
-		   * and link up all the pixels in the new block */
-		  PLIST(pixel+freeinfo.firstpix, nextpix) = oldnposize;
-		  pixt = pixel + oldnposize;
-		  for (i=oldnposize + plistsize; i<nposize;
-		       i += plistsize, pixt += plistsize)
-		    PLIST(pixt, nextpix) = i;
-		  PLIST(pixt, nextpix) = -1;
-
-		  /* last free pixel is now at the end of the new block */
-		  freeinfo.lastpix = nposize - plistsize;
-		}
-	      /*------------------------------------------------------------*/
-
-	      /* if the current status on this line is not already OBJECT... */
-	      /* start segment */
-	      if (cs != OBJECT)
-		{
-		  cs = OBJECT;
-		  if (ps == OBJECT)
-		    {
-		      if (start[co] == UNKNOWN)
-			{
-			  marker[xl] = 'S';
-			  start[co] = xl;
-			}
-		      else
-			marker[xl] = 's';
-		    }
-		  else
-		    {
-		      psstack[pstop++] = ps;
-		      marker[xl] = 'S';
-		      start[++co] = xl;
-		      ps = COMPLETE;
-		      info[co] = initinfo;
-		    }
-		}
-
-	    } /* closes if pixel above threshold */
-
-	  /* process new marker ---------------------------------------------*/
-	  /* newmarker is marker[ ] at this pixel position before we got to
-	     it. We'll only enter this if marker[ ] was set on a previous
-	     loop iteration.   */
-	  if (newmarker)
-	    {
-	      if (newmarker == 'S')
-		{
-		  psstack[pstop++] = ps;
-		  if (cs == NONOBJECT)
-		    {
-		      psstack[pstop++] = COMPLETE;
-		      info[++co] = store[xl];
-		      start[co] = UNKNOWN;
-		    }
-		  else
-		    update(&info[co], &store[xl], pixel);
-		  ps = OBJECT;
-		}
-
-	      else if (newmarker == 's')
-		{
-		  if ((cs == OBJECT) && (ps == COMPLETE))
-		    {
-		      pstop--;
-		      xl2 = start[co];
-		      update (&info[co-1],&info[co], pixel);
-		      if (start[--co] == UNKNOWN)
-			start[co] = xl2;
-		      else
-			marker[xl2] = 's';
-		    }
-		  ps = OBJECT;
-		}
-
-	      else if (newmarker == 'f')
-		ps = INCOMPLETE;
-
-	      else if (newmarker == 'F')
-		{
-		  ps = psstack[--pstop];
-		  if ((cs == NONOBJECT) && (ps == COMPLETE))
-		    {
-		      if (start[co] == UNKNOWN)
-			{
-			  if ((int)info[co].pixnb >= minarea)
-			    {
-			      /* update threshold before object is processed */
-			      if (PLISTEXIST(thresh))
-			    objlist.thresh = get_mean_thresh(&info[co], objlist.plist);
-			      else
-			    objlist.thresh = thresh;
-
-			      status = sortit(&info[co], &objlist, minarea,
-					      finalobjlist,
-					      deblend_nthresh,deblend_cont,
-                                              image->gain, &deblendctx);
-			      if (status != RETURN_OK)
-				goto exit;
-			    }
-
-			  /* free the chain-list */
-			  PLIST(pixel+info[co].lastpix, nextpix) =
-			    freeinfo.firstpix;
-			  freeinfo.firstpix = info[co].firstpix;
-			}
-		      else
-			{
-			  marker[end[co]] = 'F';
-			  store[start[co]] = info[co];
-			}
-		      co--;
-		      ps = psstack[--pstop];
-		    }
-		}
-	    }
-	  /* end of if (newmarker) ------------------------------------------*/
-
-	  /* update the info or end segment */
-	  if (luflag)
-	    {
-	      update(&info[co], &curpixinfo, pixel);
-	    }
-	  else if (cs == OBJECT)
-	    {
-	      cs = NONOBJECT;
-	      if (ps != COMPLETE)
-		{
-		  marker[xl] = 'f';
-		  end[co] = xl;
-		}
-	      else
-		{
-		  ps = psstack[--pstop];
-		  marker[xl] = 'F';
-		  store[start[co]] = info[co];
-		  co--;
-		}
-	    }
-
-	} /*------------ End of the loop over the x's -----------------------*/
-
-    } /*---------------- End of the loop over the y's -----------------------*/
-
-  /* convert `finalobjlist` to an array of `sepobj` structs */
-  /* if cleaning, see which objects "survive" cleaning. */
-  if (clean_flag)
-    {
+  if (image->segmap) {
+    for (i = 0; i < numids; i++) {
+      status = segsortit(&idinfo[i], &objlist, finalobjlist, image->gain);
+    }
+  } else {
+    /* convert `finalobjlist` to an array of `sepobj` structs */
+    /* if cleaning, see which objects "survive" cleaning. */
+    if (clean_flag) {
       /* Calculate mthresh for all objects in the list (needed for cleaning) */
-      for (i=0; i<finalobjlist->nobj; i++)
-	{
-	  status = analysemthresh(i, finalobjlist, minarea, thresh);
-	  if (status != RETURN_OK)
-	    goto exit;
-	}
+      for (i = 0; i < finalobjlist->nobj; i++) {
+        status = analysemthresh(i, finalobjlist, minarea, thresh);
+        if (status != RETURN_OK) {
+          goto exit;
+        }
+      }
 
       QMALLOC(survives, int, finalobjlist->nobj, status);
       clean(finalobjlist, clean_param, survives);
     }
-
+  }
   /* convert to output catalog */
   QCALLOC(cat, sep_catalog, 1, status);
   status = convert_to_catalog(finalobjlist, survives, cat, w, 1);
-  if (status != RETURN_OK) goto exit;
+  if (status != RETURN_OK) {
+    goto exit;
+  }
 
- exit:
+exit:
   if (finalobjlist) {
     free(finalobjlist->obj);
     free(finalobjlist->plist);
     free(finalobjlist);
   }
+  if (image->segmap) {
+    arraybuffer_free(&sbuf);
+    free(idinfo);
+    free(cumcounts);
+  }
   freedeblend(&deblendctx);
   free(pixel);
   free(info);
@@ -721,48 +843,91 @@ int sep_extract(const sep_image *image, float thresh, int thresh_type,
   free(end);
   free(survives);
   arraybuffer_free(&dbuf);
-  if (image->noise)
+  if (image->noise) {
     arraybuffer_free(&nbuf);
-  if (image->mask)
+  }
+  if (image->mask) {
     arraybuffer_free(&mbuf);
-  if (conv)
+  }
+  if (conv) {
     free(convnorm);
-  if (filter_type == SEP_FILTER_MATCHED)
-    {
-      free(sigscan);
-      free(workscan);
-    }
-
-  if (status != RETURN_OK)
-    {
-      /* free cdscan if we didn't do it on the last `yl` line */
-      if (conv && (cdscan != dummyscan))
-        free(cdscan);
+  }
+  if (filter_type == SEP_FILTER_MATCHED) {
+    free(sigscan);
+    free(workscan);
+  }
 
-      /* clean up catalog if it was allocated */
-      sep_catalog_free(cat);
-      cat = NULL;
+  if (status != RETURN_OK) {
+    /* free cdscan if we didn't do it on the last `yl` line */
+    if (conv && (cdscan != dummyscan)) {
+      free(cdscan);
     }
 
+    /* clean up catalog if it was allocated */
+    sep_catalog_free(cat);
+    cat = NULL;
+  }
+
   *catalog = cat;
   return status;
 }
 
+int segsortit(
+    infostruct * info,
+    objliststruct * objlist,
+    objliststruct * finalobjlist,
+    double gain
+) {
+  objstruct obj;
+  int status;
+
+  status = RETURN_OK;
+
+  /*----- Allocate memory to store object data */
+  objlist->obj = &obj;
+  objlist->nobj = 1;
+
+  memset(&obj, 0, (size_t)sizeof(objstruct));
+  objlist->npix = info->pixnb;
+  obj.firstpix = info->firstpix;
+  obj.lastpix = info->lastpix;
+  obj.flag = info->flag;
+
+  obj.thresh =
+      plistexist_thresh ? get_mean_thresh(info, objlist->plist) : objlist->thresh;
+
+  analyse(0, objlist, 1, gain);
+
+  status = addobjdeep(0, objlist, finalobjlist);
+
+  if (status != RETURN_OK) {
+    goto exit;
+  }
+
+exit:
+  return status;
+}
 
 /********************************* sortit ************************************/
 /*
 build the object structure.
 */
-int sortit(infostruct *info, objliststruct *objlist, int minarea,
-	   objliststruct *finalobjlist,
-	   int deblend_nthresh, double deblend_mincont, double gain,
-	   deblendctx *deblendctx)
-{
-  objliststruct	        objlistout, *objlist2;
-  objstruct	obj;
-  int 			i, status;
-
-  status=RETURN_OK;
+int sortit(
+    infostruct * info,
+    objliststruct * objlist,
+    int minarea,
+    objliststruct * finalobjlist,
+    int deblend_nthresh,
+    double deblend_mincont,
+    double gain,
+    deblendctx * deblendctx
+) {
+  objliststruct objlistout, *objlist2;
+  objstruct obj;
+  int64_t i;
+  int status;
+
+  status = RETURN_OK;
   objlistout.obj = NULL;
   objlistout.plist = NULL;
   objlistout.nobj = objlistout.npix = 0;
@@ -780,38 +945,40 @@ int sortit(infostruct *info, objliststruct *objlist, int minarea,
 
   preanalyse(0, objlist);
 
-  status = deblend(objlist, &objlistout, deblend_nthresh, deblend_mincont,
-		   minarea, deblendctx);
-  if (status)
-    {
-      /* formerly, this wasn't a fatal error, so a flag was set for
-       * the object and we continued. I'm leaving the flag-setting
-       * here in case we want to change this to a non-fatal error in
-       * the future, but currently the flag setting is irrelevant. */
-      objlist2 = objlist;
-      for (i=0; i<objlist2->nobj; i++)
-	objlist2->obj[i].flag |= SEP_OBJ_DOVERFLOW;
-      goto exit;
+  status = deblend(
+      objlist, &objlistout, deblend_nthresh, deblend_mincont, minarea, deblendctx
+  );
+  if (status) {
+    /* formerly, this wasn't a fatal error, so a flag was set for
+     * the object and we continued. I'm leaving the flag-setting
+     * here in case we want to change this to a non-fatal error in
+     * the future, but currently the flag setting is irrelevant. */
+    objlist2 = objlist;
+    for (i = 0; i < objlist2->nobj; i++) {
+      objlist2->obj[i].flag |= SEP_OBJ_DOVERFLOW;
     }
-  else
+    goto exit;
+  } else {
     objlist2 = &objlistout;
+  }
 
   /* Analyze the deblended objects and add to the final list */
-  for (i=0; i<objlist2->nobj; i++)
-    {
-      analyse(i, objlist2, 1, gain);
-
-      /* this does nothing if DETECT_MAXAREA is 0 (and it currently is) */
-      if (DETECT_MAXAREA && objlist2->obj[i].fdnpix > DETECT_MAXAREA)
-	continue;
-
-      /* add the object to the final list */
-      status = addobjdeep(i, objlist2, finalobjlist);
-      if (status != RETURN_OK)
-	goto exit;
+  for (i = 0; i < objlist2->nobj; i++) {
+    analyse(i, objlist2, 1, gain);
+
+    /* this does nothing if DETECT_MAXAREA is 0 (and it currently is) */
+    if (DETECT_MAXAREA && objlist2->obj[i].fdnpix > DETECT_MAXAREA) {
+      continue;
+    }
+
+    /* add the object to the final list */
+    status = addobjdeep(i, objlist2, finalobjlist);
+    if (status != RETURN_OK) {
+      goto exit;
     }
+  }
 
- exit:
+exit:
   free(objlistout.plist);
   free(objlistout.obj);
   return status;
@@ -824,104 +991,95 @@ Add object number `objnb` from list `objl1` to list `objl2`.
 Unlike `addobjshallow` this also copies plist pixels to the second list.
 */
 
-int addobjdeep(int objnb, objliststruct *objl1, objliststruct *objl2)
-{
-  objstruct	*objl2obj;
-  pliststruct	*plist1 = objl1->plist, *plist2 = objl2->plist;
-  int		fp, i, j, npx, objnb2;
+int addobjdeep(int objnb, objliststruct * objl1, objliststruct * objl2) {
+  objstruct * objl2obj;
+  pliststruct *plist1 = objl1->plist, *plist2 = objl2->plist;
+  int64_t fp, i, j, npx, objnb2;
 
-  fp = objl2->npix;      /* 2nd list's plist size in pixels */
-  j = fp*plistsize;      /* 2nd list's plist size in bytes */
-  objnb2 = objl2->nobj;  /* # of objects currently in 2nd list*/
+  fp = objl2->npix; /* 2nd list's plist size in pixels */
+  j = fp * plistsize; /* 2nd list's plist size in bytes */
+  objnb2 = objl2->nobj; /* # of objects currently in 2nd list*/
 
   /* Allocate space in `objl2` for the new object */
-  if (objnb2)
-    objl2obj = realloc(objl2->obj,
-				    (++objl2->nobj)*sizeof(objstruct));
-  else
-    objl2obj = malloc((++objl2->nobj)*sizeof(objstruct));
+  if (objnb2) {
+    objl2obj = realloc(objl2->obj, (++objl2->nobj) * sizeof(objstruct));
+  } else {
+    objl2obj = malloc((++objl2->nobj) * sizeof(objstruct));
+  }
 
-  if (!objl2obj)
+  if (!objl2obj) {
     goto earlyexit;
+  }
   objl2->obj = objl2obj;
 
   /* Allocate space for the new object's pixels in 2nd list's plist */
   npx = objl1->obj[objnb].fdnpix;
-  if (fp)
-    plist2 = realloc(plist2, (objl2->npix+=npx)*plistsize);
-  else
-    plist2 = malloc((objl2->npix=npx)*plistsize);
+  if (fp) {
+    plist2 = realloc(plist2, (objl2->npix += npx) * plistsize);
+  } else {
+    plist2 = malloc((objl2->npix = npx) * plistsize);
+  }
 
-  if (!plist2)
+  if (!plist2) {
     goto earlyexit;
+  }
   objl2->plist = plist2;
 
   /* copy the plist */
   plist2 += j;
-  for(i=objl1->obj[objnb].firstpix; i!=-1; i=PLIST(plist1+i,nextpix))
-    {
-      memcpy(plist2, plist1+i, (size_t)plistsize);
-      PLIST(plist2,nextpix) = (j+=plistsize);
-      plist2 += plistsize;
-    }
-  PLIST(plist2-=plistsize, nextpix) = -1;
+  for (i = objl1->obj[objnb].firstpix; i != -1; i = PLIST(plist1 + i, nextpix)) {
+    memcpy(plist2, plist1 + i, (size_t)plistsize);
+    PLIST(plist2, nextpix) = (j += plistsize);
+    plist2 += plistsize;
+  }
+  PLIST(plist2 -= plistsize, nextpix) = -1;
 
   /* copy the object itself */
   objl2->obj[objnb2] = objl1->obj[objnb];
-  objl2->obj[objnb2].firstpix = fp*plistsize;
-  objl2->obj[objnb2].lastpix = j-plistsize;
+  objl2->obj[objnb2].firstpix = fp * plistsize;
+  objl2->obj[objnb2].lastpix = j - plistsize;
 
   return RETURN_OK;
 
   /* if early exit, reset 2nd list */
- earlyexit:
+earlyexit:
   objl2->nobj--;
   objl2->npix = fp;
   return MEMORY_ALLOC_ERROR;
 }
 
 
-
 /****************************** plistinit ************************************
  * (originally init_plist() in sextractor)
 PURPOSE	initialize a pixel-list and its components.
  ***/
-void plistinit(int hasconv, int hasvar)
-{
-  pbliststruct	*pbdum = NULL;
+void plistinit(int hasconv, int hasvar) {
+  pbliststruct * pbdum = NULL;
 
   plistsize = sizeof(pbliststruct);
   plistoff_value = (char *)&pbdum->value - (char *)pbdum;
 
-  if (hasconv)
-    {
-      plistexist_cdvalue = 1;
-      plistoff_cdvalue = plistsize;
-      plistsize += sizeof(PIXTYPE);
-    }
-  else
-    {
-      plistexist_cdvalue = 0;
-      plistoff_cdvalue = plistoff_value;
-    }
-
-  if (hasvar)
-    {
-      plistexist_var = 1;
-      plistoff_var = plistsize;
-      plistsize += sizeof(PIXTYPE);
-
-      plistexist_thresh = 1;
-      plistoff_thresh = plistsize;
-      plistsize += sizeof(PIXTYPE);
-    }
-  else
-    {
-      plistexist_var = 0;
-      plistexist_thresh = 0;
-    }
-
+  if (hasconv) {
+    plistexist_cdvalue = 1;
+    plistoff_cdvalue = plistsize;
+    plistsize += sizeof(PIXTYPE);
+  } else {
+    plistexist_cdvalue = 0;
+    plistoff_cdvalue = plistoff_value;
+  }
 
+  if (hasvar) {
+    plistexist_var = 1;
+    plistoff_var = plistsize;
+    plistsize += sizeof(PIXTYPE);
+
+    plistexist_thresh = 1;
+    plistoff_thresh = plistsize;
+    plistsize += sizeof(PIXTYPE);
+  } else {
+    plistexist_var = 0;
+    plistexist_thresh = 0;
+  }
 }
 
 
@@ -931,97 +1089,101 @@ Fill a list with whether each object in the list survived the cleaning
 (assumes that mthresh has already been calculated for all objects in the list)
 */
 
-void clean(objliststruct *objlist, double clean_param, int *survives)
-{
-  objstruct     *obj1, *obj2;
-  int	        i,j;
-  double        amp,ampin,alpha,alphain, unitarea,unitareain,beta,val;
-  float	       	dx,dy,rlim;
+void clean(objliststruct * objlist, double clean_param, int * survives) {
+  objstruct *obj1, *obj2;
+  int64_t i, j;
+  double amp, ampin, alpha, alphain, unitarea, unitareain, beta, val;
+  float dx, dy, rlim;
 
   beta = clean_param;
 
   /* initialize to all surviving */
-  for (i=0; i<objlist->nobj; i++)
+  for (i = 0; i < objlist->nobj; i++) {
     survives[i] = 1;
+  }
 
   obj1 = objlist->obj;
-  for (i=0; i<objlist->nobj; i++, obj1++)
-    {
-      if (!survives[i])
-	continue;
-
-      /* parameters for test object */
-      unitareain = PI*obj1->a*obj1->b;
-      ampin = obj1->fdflux/(2*unitareain*obj1->abcor);
-      alphain = (pow(ampin/obj1->thresh, 1.0/beta)-1)*unitareain/obj1->fdnpix;
-
-      /* loop over remaining objects in list*/
-      obj2 = obj1 + 1;
-      for (j=i+1; j<objlist->nobj; j++, obj2++)
-	{
-	  if (!survives[j])
-	    continue;
-
-	  dx = obj1->mx - obj2->mx;
-	  dy = obj1->my - obj2->my;
-	  rlim = obj1->a + obj2->a;
-	  rlim *= rlim;
-	  if (dx*dx + dy*dy > rlim*CLEAN_ZONE*CLEAN_ZONE)
-	    continue;
-
-	  /* if obj1 is bigger, see if it eats obj2 */
-	  if (obj2->fdflux < obj1->fdflux)
-	    {
-	      val = 1 + alphain*(obj1->cxx*dx*dx + obj1->cyy*dy*dy +
-				 obj1->cxy*dx*dy);
-	      if (val>1.0 && ((float)(val<1e10?ampin*pow(val,-beta):0.0) >
-			      obj2->mthresh))
-		  survives[j] = 0; /* the test object eats this one */
-	    }
-
-	  /* if obj2 is bigger, see if it eats obj1 */
-	  else
-	    {
-	      unitarea = PI*obj2->a*obj2->b;
-	      amp = obj2->fdflux/(2*unitarea*obj2->abcor);
-	      alpha = (pow(amp/obj2->thresh, 1.0/beta) - 1) *
-		unitarea/obj2->fdnpix;
-	      val = 1 + alpha*(obj2->cxx*dx*dx + obj2->cyy*dy*dy +
-			       obj2->cxy*dx*dy);
-	      if (val>1.0 && ((float)(val<1e10?amp*pow(val,-beta):0.0) >
-			      obj1->mthresh))
-		survives[i] = 0;  /* this object eats the test object */
-	    }
-
-	} /* inner loop over objlist (obj2) */
-    } /* outer loop of objlist (obj1) */
+  for (i = 0; i < objlist->nobj; i++, obj1++) {
+    if (!survives[i]) {
+      continue;
+    }
+
+    /* parameters for test object */
+    unitareain = PI * obj1->a * obj1->b;
+    ampin = obj1->fdflux / (2 * unitareain * obj1->abcor);
+    alphain = (pow(ampin / obj1->thresh, 1.0 / beta) - 1) * unitareain / obj1->fdnpix;
+
+    /* loop over remaining objects in list*/
+    obj2 = obj1 + 1;
+    for (j = i + 1; j < objlist->nobj; j++, obj2++) {
+      if (!survives[j]) {
+        continue;
+      }
+
+      dx = obj1->mx - obj2->mx;
+      dy = obj1->my - obj2->my;
+      rlim = obj1->a + obj2->a;
+      rlim *= rlim;
+      if (dx * dx + dy * dy > rlim * CLEAN_ZONE * CLEAN_ZONE) {
+        continue;
+      }
+
+      /* if obj1 is bigger, see if it eats obj2 */
+      if (obj2->fdflux < obj1->fdflux) {
+        val = 1
+              + alphain
+                    * (obj1->cxx * dx * dx + obj1->cyy * dy * dy + obj1->cxy * dx * dy);
+        if (val > 1.0
+            && ((float)(val < 1e10 ? ampin * pow(val, -beta) : 0.0) > obj2->mthresh))
+        {
+          survives[j] = 0; /* the test object eats this one */
+        }
+      }
+
+      /* if obj2 is bigger, see if it eats obj1 */
+      else
+      {
+        unitarea = PI * obj2->a * obj2->b;
+        amp = obj2->fdflux / (2 * unitarea * obj2->abcor);
+        alpha = (pow(amp / obj2->thresh, 1.0 / beta) - 1) * unitarea / obj2->fdnpix;
+        val =
+            1
+            + alpha * (obj2->cxx * dx * dx + obj2->cyy * dy * dy + obj2->cxy * dx * dy);
+        if (val > 1.0
+            && ((float)(val < 1e10 ? amp * pow(val, -beta) : 0.0) > obj1->mthresh))
+        {
+          survives[i] = 0; /* this object eats the test object */
+        }
+      }
+
+    } /* inner loop over objlist (obj2) */
+  } /* outer loop of objlist (obj1) */
 }
 
 /************************** get_mean_thresh **********************************/
-/*
-Compute an average threshold from all pixels in the cluster
-*/
-PIXTYPE get_mean_thresh(infostruct *info, pliststruct *pixel)
-{
-  pliststruct   *pixt;
-  int           pix_accum=0;
-  PIXTYPE       thresh_accum=0;
-
-  for (pixt=pixel+info->firstpix; pixt>=pixel;
-       pixt=pixel+PLIST(pixt,nextpix))
-    {
-      thresh_accum += PLISTPIX(pixt,thresh);
-      pix_accum++;
-    }
+/* Compute an average threshold from all pixels in the cluster */
+
+PIXTYPE get_mean_thresh(infostruct * info, pliststruct * pixel) {
+  pliststruct * pixt;
+  int pix_accum = 0;
+  double thresh_accum = 0;
+
+  // Threshold must be cast to double to avoid precision loss
+  for (pixt = pixel + info->firstpix; pixt >= pixel;
+       pixt = pixel + PLIST(pixt, nextpix))
+  {
+    thresh_accum += (double)PLISTPIX(pixt, thresh);
+    pix_accum++;
+  }
 
-  return thresh_accum / pix_accum;
+  return (PIXTYPE)(thresh_accum / pix_accum);
 }
 
+
 /*****************************************************************************/
 /* sep_catalog manipulations */
 
-void free_catalog_fields(sep_catalog *catalog)
-{
+void free_catalog_fields(sep_catalog * catalog) {
   free(catalog->thresh);
   free(catalog->npix);
   free(catalog->tnpix);
@@ -1069,14 +1231,18 @@ void free_catalog_fields(sep_catalog *catalog)
  * `cat`:      catalog object to be filled.
  * `w`:        width of image (used to calculate linear indicies).
  */
-int convert_to_catalog(objliststruct *objlist, const int *survives,
-                       sep_catalog *cat, int w, int include_pixels)
-{
-  int i, j, k;
-  int totnpix;
+int convert_to_catalog(
+    objliststruct * objlist,
+    const int * survives,
+    sep_catalog * cat,
+    int64_t w,
+    int include_pixels
+) {
+  int64_t i, j, k;
+  int64_t totnpix;
   int nobj = 0;
   int status = RETURN_OK;
-  objstruct *obj;
+  objstruct * obj;
   pliststruct *pixt, *pixel;
 
   /* Set struct to zero in case the caller didn't.
@@ -1086,20 +1252,23 @@ int convert_to_catalog(objliststruct *objlist, const int *survives,
 
   /* Count number of surviving objects so that we can allocate the
      appropriate amount of space in the output catalog. */
-  if (survives)
-    for (i=0; i<objlist->nobj; i++) nobj += survives[i];
-  else
+  if (survives) {
+    for (i = 0; i < objlist->nobj; i++) {
+      nobj += survives[i];
+    }
+  } else {
     nobj = objlist->nobj;
+  }
 
   /* allocate catalog fields */
   cat->nobj = nobj;
   QMALLOC(cat->thresh, float, nobj, status);
-  QMALLOC(cat->npix, int, nobj, status);
-  QMALLOC(cat->tnpix, int, nobj, status);
-  QMALLOC(cat->xmin, int, nobj, status);
-  QMALLOC(cat->xmax, int, nobj, status);
-  QMALLOC(cat->ymin, int, nobj, status);
-  QMALLOC(cat->ymax, int, nobj, status);
+  QMALLOC(cat->npix, int64_t, nobj, status);
+  QMALLOC(cat->tnpix, int64_t, nobj, status);
+  QMALLOC(cat->xmin, int64_t, nobj, status);
+  QMALLOC(cat->xmax, int64_t, nobj, status);
+  QMALLOC(cat->ymin, int64_t, nobj, status);
+  QMALLOC(cat->ymax, int64_t, nobj, status);
   QMALLOC(cat->x, double, nobj, status);
   QMALLOC(cat->y, double, nobj, status);
   QMALLOC(cat->x2, double, nobj, status);
@@ -1118,108 +1287,106 @@ int convert_to_catalog(objliststruct *objlist, const int *survives,
   QMALLOC(cat->flux, float, nobj, status);
   QMALLOC(cat->cpeak, float, nobj, status);
   QMALLOC(cat->peak, float, nobj, status);
-  QMALLOC(cat->xcpeak, int, nobj, status);
-  QMALLOC(cat->ycpeak, int, nobj, status);
-  QMALLOC(cat->xpeak, int, nobj, status);
-  QMALLOC(cat->ypeak, int, nobj, status);
+  QMALLOC(cat->xcpeak, int64_t, nobj, status);
+  QMALLOC(cat->ycpeak, int64_t, nobj, status);
+  QMALLOC(cat->xpeak, int64_t, nobj, status);
+  QMALLOC(cat->ypeak, int64_t, nobj, status);
   QMALLOC(cat->cflux, float, nobj, status);
   QMALLOC(cat->flux, float, nobj, status);
   QMALLOC(cat->flag, short, nobj, status);
 
   /* fill output arrays */
-  j = 0;  /* running index in output array */
-  for (i=0; i<objlist->nobj; i++)
-    {
-      if ((survives == NULL) || survives[i])
-        {
-          obj = objlist->obj + i;
-          cat->thresh[j] = obj->thresh;
-          cat->npix[j] = obj->fdnpix;
-          cat->tnpix[j] = obj->dnpix;
-          cat->xmin[j] = obj->xmin;
-          cat->xmax[j] = obj->xmax;
-          cat->ymin[j] = obj->ymin;
-          cat->ymax[j] = obj->ymax;
-          cat->x[j] = obj->mx;
-          cat->y[j] = obj->my;
-          cat->x2[j] = obj->mx2;
-          cat->y2[j] = obj->my2;
-          cat->xy[j] = obj->mxy;
-          cat->errx2[j] = obj->errx2;
-          cat->erry2[j] = obj->erry2;
-          cat->errxy[j] = obj->errxy;
-
-          cat->a[j] = obj->a;
-          cat->b[j] = obj->b;
-          cat->theta[j] = obj->theta;
-
-          cat->cxx[j] = obj->cxx;
-          cat->cyy[j] = obj->cyy;
-          cat->cxy[j] = obj->cxy;
-
-          cat->cflux[j] = obj->fdflux; /* these change names */
-          cat->flux[j] = obj->dflux;
-          cat->cpeak[j] = obj->fdpeak;
-          cat->peak[j] = obj->dpeak;
-
-          cat->xpeak[j] = obj->xpeak;
-          cat->ypeak[j] = obj->ypeak;
-          cat->xcpeak[j] = obj->xcpeak;
-          cat->ycpeak[j] = obj->ycpeak;
-
-          cat->flag[j] = obj->flag;
-
-          j++;
-        }
+  j = 0; /* running index in output array */
+  for (i = 0; i < objlist->nobj; i++) {
+    if ((survives == NULL) || survives[i]) {
+      obj = objlist->obj + i;
+      cat->thresh[j] = obj->thresh;
+      cat->npix[j] = obj->fdnpix;
+      cat->tnpix[j] = obj->dnpix;
+      cat->xmin[j] = obj->xmin;
+      cat->xmax[j] = obj->xmax;
+      cat->ymin[j] = obj->ymin;
+      cat->ymax[j] = obj->ymax;
+      cat->x[j] = obj->mx;
+      cat->y[j] = obj->my;
+      cat->x2[j] = obj->mx2;
+      cat->y2[j] = obj->my2;
+      cat->xy[j] = obj->mxy;
+      cat->errx2[j] = obj->errx2;
+      cat->erry2[j] = obj->erry2;
+      cat->errxy[j] = obj->errxy;
+
+      cat->a[j] = obj->a;
+      cat->b[j] = obj->b;
+      cat->theta[j] = obj->theta;
+
+      cat->cxx[j] = obj->cxx;
+      cat->cyy[j] = obj->cyy;
+      cat->cxy[j] = obj->cxy;
+
+      cat->cflux[j] = obj->fdflux; /* these change names */
+      cat->flux[j] = obj->dflux;
+      cat->cpeak[j] = obj->fdpeak;
+      cat->peak[j] = obj->dpeak;
+
+      cat->xpeak[j] = obj->xpeak;
+      cat->ypeak[j] = obj->ypeak;
+      cat->xcpeak[j] = obj->xcpeak;
+      cat->ycpeak[j] = obj->ycpeak;
+
+      cat->flag[j] = obj->flag;
+
+      j++;
+    }
+  }
+
+  if (include_pixels) {
+    /* count the total number of pixels */
+    totnpix = 0;
+    for (i = 0; i < cat->nobj; i++) {
+      totnpix += cat->npix[i];
     }
 
-  if (include_pixels)
-    {
-      /* count the total number of pixels */
-      totnpix = 0;
-      for (i=0; i<cat->nobj; i++) totnpix += cat->npix[i];
+    /* allocate buffer for all objects' pixels */
+    QMALLOC(cat->objectspix, int64_t, totnpix, status);
 
-      /* allocate buffer for all objects' pixels */
-      QMALLOC(cat->objectspix, int, totnpix, status);
+    /* allocate array of pointers into the above buffer */
+    QMALLOC(cat->pix, int64_t *, nobj, status);
 
-      /* allocate array of pointers into the above buffer */
-      QMALLOC(cat->pix, int*, nobj, status);
+    pixel = objlist->plist;
 
-      pixel = objlist->plist;
+    /* for each object, fill buffer and direct object's to it */
+    k = 0; /* current position in `objectspix` buffer */
+    j = 0; /* output object index */
+    for (i = 0; i < objlist->nobj; i++) {
+      obj = objlist->obj + i; /* input object */
+      if ((survives == NULL) || survives[i]) {
+        /* point this object's pixel list into the buffer. */
+        cat->pix[j] = cat->objectspix + k;
 
-      /* for each object, fill buffer and direct object's to it */
-      k = 0; /* current position in `objectspix` buffer */
-      j = 0; /* output object index */
-      for (i=0; i<objlist->nobj; i++)
+        /* fill the actual pixel values */
+        for (pixt = pixel + obj->firstpix; pixt >= pixel;
+             pixt = pixel + PLIST(pixt, nextpix), k++)
         {
-          obj = objlist->obj + i; /* input object */
-          if ((survives == NULL) || survives[i])
-            {
-              /* point this object's pixel list into the buffer. */
-              cat->pix[j] = cat->objectspix + k;
-
-              /* fill the actual pixel values */
-              for (pixt=pixel+obj->firstpix; pixt>=pixel;
-                   pixt=pixel+PLIST(pixt,nextpix), k++)
-                {
-                  cat->objectspix[k] = PLIST(pixt,x) + w*PLIST(pixt,y);
-                }
-              j++;
-            }
+          cat->objectspix[k] = PLIST(pixt, x) + w * PLIST(pixt, y);
         }
+        j++;
+      }
     }
+  }
 
- exit:
-  if (status != RETURN_OK)
+exit:
+  if (status != RETURN_OK) {
     free_catalog_fields(cat);
+  }
 
   return status;
 }
 
 
-void sep_catalog_free(sep_catalog *catalog)
-{
-  if (catalog != NULL)
+void sep_catalog_free(sep_catalog * catalog) {
+  if (catalog != NULL) {
     free_catalog_fields(catalog);
+  }
   free(catalog);
 }
diff --git a/src/extract.h b/src/extract.h
index fca91af..7303626 100644
--- a/src/extract.h
+++ b/src/extract.h
@@ -1,168 +1,177 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define	UNKNOWN	        -1    /* flag for LUTZ */
-#define	CLEAN_ZONE      10.0  /* zone (in sigma) to consider for processing */
-#define CLEAN_STACKSIZE 3000  /* replaces prefs.clean_stacksize  */
-                              /* (MEMORY_OBJSTACK in sextractor inputs) */
-#define CLEAN_MARGIN    0  /* replaces prefs.cleanmargin which was set based */
-                           /* on stuff like apertures and vignet size */
-#define	MARGIN_SCALE   2.0 /* Margin / object height */
-#define	MARGIN_OFFSET  4.0 /* Margin offset (pixels) */
-#define	MAXDEBAREA     3   /* max. area for deblending (must be >= 1)*/
-#define	MAXPICSIZE     1048576 /* max. image size in any dimension */
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "sepcore.h"
+
+#define UNKNOWN -1 /* flag for LUTZ */
+#define CLEAN_ZONE 10.0 /* zone (in sigma) to consider for processing */
+#define CLEAN_STACKSIZE 3000 /* replaces prefs.clean_stacksize  */
+/* (MEMORY_OBJSTACK in sextractor inputs) */
+#define CLEAN_MARGIN 0 /* replaces prefs.cleanmargin which was set based */
+/* on stuff like apertures and vignet size */
+#define MARGIN_SCALE 2.0 /* Margin / object height */
+#define MARGIN_OFFSET 4.0 /* Margin offset (pixels) */
+#define MAXDEBAREA 3 /* max. area for deblending (must be >= 1)*/
+#define MAXPICSIZE 1048576 /* max. image size in any dimension */
 
 /* plist-related macros */
-#define	PLIST(ptr, elem)	(((pbliststruct *)(ptr))->elem)
-#define	PLISTEXIST(elem)	(plistexist_##elem)
-#define	PLISTPIX(ptr, elem)	(*((PIXTYPE *)((ptr)+plistoff_##elem)))
+#define PLIST(ptr, elem) (((pbliststruct *)(ptr))->elem)
+#define PLISTEXIST(elem) (plistexist_##elem)
+#define PLISTPIX(ptr, elem) (*((PIXTYPE *)((ptr) + plistoff_##elem)))
 
 /* Extraction status */
-typedef	enum {COMPLETE, INCOMPLETE, NONOBJECT, OBJECT} pixstatus;
+typedef enum {
+  COMPLETE,
+  INCOMPLETE,
+  NONOBJECT,
+  OBJECT
+} pixstatus;
 
 /* Temporary object parameters during extraction */
-typedef struct structinfo
-{
-  LONG	pixnb;	    /* Number of pixels included */
-  LONG	firstpix;   /* Pointer to first pixel of pixlist */
-  LONG	lastpix;    /* Pointer to last pixel of pixlist */
-  short	flag;	    /* Extraction flag */
+typedef struct structinfo {
+  int64_t pixnb; /* Number of pixels included */
+  int64_t firstpix; /* Pointer to first pixel of pixlist */
+  int64_t lastpix; /* Pointer to last pixel of pixlist */
+  short flag; /* Extraction flag */
 } infostruct;
 
-typedef	char pliststruct;      /* Dummy type for plist */
+typedef char pliststruct; /* Dummy type for plist */
 
-typedef struct
-{
-  int     nextpix;
-  int     x, y;
+typedef struct {
+  int64_t nextpix;
+  int64_t x, y;
   PIXTYPE value;
 } pbliststruct;
 
 /* array buffer struct */
-typedef struct
-{
-  const BYTE *dptr;         /* pointer to original data, can be any supported type */
-  int dtype;          /* data type of original data */
-  int dw, dh;         /* original data width, height */
-  PIXTYPE *bptr;      /* buffer pointer (self-managed memory) */
-  int bw, bh;         /* buffer width, height (bufw can be larger than w due */
-                      /* to padding). */
-  PIXTYPE *midline;   /* "middle" line in buffer (at index bh/2) */
-  PIXTYPE *lastline;  /* last line in buffer */
-  array_converter readline;  /* function to read a data line into buffer */
-  int elsize;         /* size in bytes of one element in original data */
-  int yoff;           /* line index in original data corresponding to bufptr */
+typedef struct {
+  const BYTE * dptr; /* pointer to original data, can be any supported type */
+  int dtype; /* data type of original data */
+  int64_t dw, dh; /* original data width, height */
+  PIXTYPE * bptr; /* buffer pointer (self-managed memory) */
+  int64_t bw, bh; /* buffer width, height (bufw can be larger than w due */
+  /* to padding). */
+  PIXTYPE * midline; /* "middle" line in buffer (at index bh/2) */
+  PIXTYPE * lastline; /* last line in buffer */
+  array_converter readline; /* function to read a data line into buffer */
+  int64_t elsize; /* size in bytes of one element in original data */
+  int64_t yoff; /* line index in original data corresponding to bufptr */
 } arraybuffer;
 
 
 /* globals */
-extern _Thread_local int plistexist_cdvalue, plistexist_thresh, plistexist_var;
-extern _Thread_local int plistoff_value, plistoff_cdvalue, plistoff_thresh, plistoff_var;
-extern _Thread_local int plistsize;
+extern _Thread_local int64_t plistexist_cdvalue, plistexist_thresh, plistexist_var;
+extern _Thread_local int64_t plistoff_value, plistoff_cdvalue, plistoff_thresh,
+    plistoff_var;
+extern _Thread_local int64_t plistsize;
 extern _Thread_local unsigned int randseed;
 
-typedef struct
-{
+typedef struct {
   /* thresholds */
-  float	   thresh;		             /* detect threshold (ADU) */
-  float	   mthresh;		             /* max. threshold (ADU) */
+  float thresh; /* detect threshold (ADU) */
+  float mthresh; /* max. threshold (ADU) */
 
   /* # pixels */
-  int	   fdnpix;		       	/* nb of extracted pix */
-  int	   dnpix;	       		/* nb of pix above thresh  */
-  int	   npix;       			/* "" in measured frame */
-  int	   nzdwpix;			/* nb of zero-dweights around */
-  int	   nzwpix;		       	/* nb of zero-weights inside */
+  int64_t fdnpix; /* nb of extracted pix */
+  int64_t dnpix; /* nb of pix above thresh  */
+  int64_t npix; /* "" in measured frame */
+  int64_t nzdwpix; /* nb of zero-dweights around */
+  int64_t nzwpix; /* nb of zero-weights inside */
 
   /* position */
-  int	   xpeak, ypeak;                     /* pos of brightest pix */
-  int	   xcpeak,ycpeak;                    /* pos of brightest pix */
-  double   mx, my;        	             /* barycenter */
-  int	   xmin,xmax,ymin,ymax,ycmin,ycmax;  /* x,y limits */
+  int64_t xpeak, ypeak; /* pos of brightest pix */
+  int64_t xcpeak, ycpeak; /* pos of brightest pix */
+  double mx, my; /* barycenter */
+  int64_t xmin, xmax, ymin, ymax, ycmin, ycmax; /* x,y limits */
 
   /* shape */
-  double   mx2,my2,mxy;			     /* variances and covariance */
-  float	   a, b, theta, abcor;		     /* moments and angle */
-  float	   cxx,cyy,cxy;			     /* ellipse parameters */
-  double   errx2, erry2, errxy;      /* Uncertainties on the variances */
+  double mx2, my2, mxy; /* variances and covariance */
+  float a, b, theta, abcor; /* moments and angle */
+  float cxx, cyy, cxy; /* ellipse parameters */
+  double errx2, erry2, errxy; /* Uncertainties on the variances */
 
   /* flux */
-  float	   fdflux;	       		/* integrated ext. flux */
-  float	   dflux;      			/* integrated det. flux */
-  float	   flux;       			/* integrated mes. flux */
-  float	   fluxerr;			/* integrated variance */
-  PIXTYPE  fdpeak;	       		/* peak intensity (ADU) */
-  PIXTYPE  dpeak;      			/* peak intensity (ADU) */
-  PIXTYPE  peak;       			/* peak intensity (ADU) */
+  float fdflux; /* integrated ext. flux */
+  float dflux; /* integrated det. flux */
+  float flux; /* integrated mes. flux */
+  float fluxerr; /* integrated variance */
+  PIXTYPE fdpeak; /* peak intensity (ADU) */
+  PIXTYPE dpeak; /* peak intensity (ADU) */
+  PIXTYPE peak; /* peak intensity (ADU) */
 
   /* flags */
-  short	   flag;			     /* extraction flags */
+  short flag; /* extraction flags */
 
   /* accessing individual pixels in plist*/
-  int	   firstpix;			     /* ptr to first pixel */
-  int	   lastpix;			     /* ptr to last pixel */
+  int64_t firstpix; /* ptr to first pixel */
+  int64_t lastpix; /* ptr to last pixel */
 } objstruct;
 
-typedef struct
-{
-  int           nobj;	  /* number of objects in list */
-  objstruct     *obj;	  /* pointer to the object array */
-  int           npix;	  /* number of pixels in pixel-list */
-  pliststruct   *plist;	  /* pointer to the pixel-list */
-  PIXTYPE       thresh;   /* detection threshold */
+typedef struct {
+  int64_t nobj; /* number of objects in list */
+  objstruct * obj; /* pointer to the object array */
+  int64_t npix; /* number of pixels in pixel-list */
+  pliststruct * plist; /* pointer to the pixel-list */
+  PIXTYPE thresh; /* detection threshold */
 } objliststruct;
 
 
-int analysemthresh(int objnb, objliststruct *objlist, int minarea,
-		   PIXTYPE thresh);
+int analysemthresh(int objnb, objliststruct * objlist, int minarea, PIXTYPE thresh);
 void preanalyse(int, objliststruct *);
 void analyse(int, objliststruct *, int, double);
 
 typedef struct {
-	infostruct  *info, *store;
-	char	   *marker;
-	pixstatus   *psstack;
-	int         *start, *end, *discan;
-	int         xmin, ymin, xmax, ymax;
+  infostruct *info, *store;
+  char * marker;
+  pixstatus * psstack;
+  int64_t *start, *end, *discan;
+  int64_t xmin, ymin, xmax, ymax;
 } lutzbuffers;
 
-int  lutzalloc(int, int, lutzbuffers *);
+int lutzalloc(int64_t, int64_t, lutzbuffers *);
 void lutzfree(lutzbuffers *);
-int  lutz(pliststruct *plistin,
-	  int *objrootsubmap, int subx, int suby, int subw,
-	  objstruct *objparent, objliststruct *objlist, int minarea,
-	  lutzbuffers *buffers);
+int lutz(
+    pliststruct * plistin,
+    int64_t * objrootsubmap,
+    int64_t subx,
+    int64_t suby,
+    int64_t subw,
+    objstruct * objparent,
+    objliststruct * objlist,
+    int minarea,
+    lutzbuffers * buffers
+);
 
 void update(infostruct *, infostruct *, pliststruct *);
 
 typedef struct {
-	objliststruct *objlist;
-	short *son, *ok;
-	lutzbuffers lutz;
+  objliststruct * objlist;
+  short *son, *ok;
+  lutzbuffers lutz;
 } deblendctx;
 
-int  allocdeblend(int deblend_nthresh, int w, int h, deblendctx *);
+int allocdeblend(int deblend_nthresh, int64_t w, int64_t h, deblendctx *);
 void freedeblend(deblendctx *);
-int  deblend(objliststruct *, objliststruct *, int, double, int, deblendctx *);
+int deblend(objliststruct *, objliststruct *, int, double, int, deblendctx *);
 
 /*int addobjshallow(objstruct *, objliststruct *);
 int rmobjshallow(int, objliststruct *);
@@ -170,8 +179,22 @@ void mergeobjshallow(objstruct *, objstruct *);
 */
 int addobjdeep(int, objliststruct *, objliststruct *);
 
-int convolve(arraybuffer *buf, int y, const float *conv, int convw, int convh,
-             PIXTYPE *out);
-int matched_filter(arraybuffer *imbuf, arraybuffer *nbuf, int y,
-                   const float *conv, int convw, int convh,
-                   PIXTYPE *work, PIXTYPE *out, int noise_type);
+int convolve(
+    arraybuffer * buf,
+    int64_t y,
+    const float * conv,
+    int64_t convw,
+    int64_t convh,
+    PIXTYPE * out
+);
+int matched_filter(
+    arraybuffer * imbuf,
+    arraybuffer * nbuf,
+    int64_t y,
+    const float * conv,
+    int64_t convw,
+    int64_t convh,
+    PIXTYPE * work,
+    PIXTYPE * out,
+    int noise_type
+);
diff --git a/src/lutz.c b/src/lutz.c
index 8e58183..fe87ba0 100644
--- a/src/lutz.c
+++ b/src/lutz.c
@@ -1,36 +1,37 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 /* Note: was extract.c in SExtractor. */
 
-#include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "extract.h"
 #include "sep.h"
 #include "sepcore.h"
-#include "extract.h"
 
-#define	NOBJ 256  /* starting number of obj. */
+#define NOBJ 256 /* starting number of obj. */
 
 void lutzsort(infostruct *, objliststruct *);
 
@@ -38,31 +39,32 @@ void lutzsort(infostruct *, objliststruct *);
 /*
 Allocate once for all memory space for buffers used by lutz().
 */
-int lutzalloc(int width, int height, lutzbuffers *buffers)
-{
-  int *discant;
-  int stacksize, i, status=RETURN_OK;
+int lutzalloc(int64_t width, int64_t height, lutzbuffers * buffers) {
+  int64_t * discant;
+  int64_t stacksize, i;
+  int status = RETURN_OK;
 
   memset(buffers, 0, sizeof(lutzbuffers));
 
-  stacksize = width+1;
+  stacksize = width + 1;
   buffers->xmin = buffers->ymin = 0;
-  buffers->xmax = width-1;
-  buffers->ymax = height-1;
+  buffers->xmax = width - 1;
+  buffers->ymax = height - 1;
   QMALLOC(buffers->info, infostruct, stacksize, status);
   QMALLOC(buffers->store, infostruct, stacksize, status);
   QMALLOC(buffers->marker, char, stacksize, status);
   QMALLOC(buffers->psstack, pixstatus, stacksize, status);
-  QMALLOC(buffers->start, int, stacksize, status);
-  QMALLOC(buffers->end, int, stacksize, status);
-  QMALLOC(buffers->discan, int, stacksize, status);
+  QMALLOC(buffers->start, int64_t, stacksize, status);
+  QMALLOC(buffers->end, int64_t, stacksize, status);
+  QMALLOC(buffers->discan, int64_t, stacksize, status);
   discant = buffers->discan;
-  for (i=stacksize; i--;)
+  for (i = stacksize; i--;) {
     *(discant++) = -1;
+  }
 
   return status;
 
- exit:
+exit:
   lutzfree(buffers);
 
   return status;
@@ -72,8 +74,7 @@ int lutzalloc(int width, int height, lutzbuffers *buffers)
 /*
 Free once for all memory space for buffers used by lutz().
 */
-void lutzfree(lutzbuffers *buffers)
-{
+void lutzfree(lutzbuffers * buffers) {
   free(buffers->discan);
   buffers->discan = NULL;
   free(buffers->info);
@@ -90,37 +91,38 @@ void lutzfree(lutzbuffers *buffers)
   buffers->end = NULL;
 }
 
-static const infostruct initinfo = {
-	.firstpix = -1,
-	.lastpix = -1
-};
+static const infostruct initinfo = {.firstpix = -1, .lastpix = -1};
 
 /********************************** lutz *************************************/
 /*
 C implementation of R.K LUTZ' algorithm for the extraction of 8-connected pi-
 xels in an image
 */
-int lutz(pliststruct *plistin,
-	 int *objrootsubmap, int subx, int suby, int subw,
-	 objstruct *objparent, objliststruct *objlist, int minarea,
-	 lutzbuffers *buffers)
-{
-  infostruct	curpixinfo;
-  objstruct		*obj;
-  pliststruct		*plist,*pixel, *plistint;
-
-  char			newmarker;
-  int			cn, co, luflag, pstop, xl,xl2,yl,
-                        out, deb_maxarea, stx,sty,enx,eny, step,
-                        nobjm = NOBJ,
-			inewsymbol, *iscan;
-  short		        trunflag;
-  PIXTYPE		thresh;
-  pixstatus		cs, ps;
+int lutz(
+    pliststruct * plistin,
+    int64_t * objrootsubmap,
+    int64_t subx,
+    int64_t suby,
+    int64_t subw,
+    objstruct * objparent,
+    objliststruct * objlist,
+    int minarea,
+    lutzbuffers * buffers
+) {
+  infostruct curpixinfo;
+  objstruct * obj;
+  pliststruct *plist, *pixel, *plistint;
+
+  char newmarker;
+  int64_t cn, co, luflag, pstop, xl, xl2, yl, out, deb_maxarea, stx, sty, enx, eny,
+      step, nobjm = NOBJ, inewsymbol, *iscan;
+  short trunflag;
+  PIXTYPE thresh;
+  pixstatus cs, ps;
 
   out = RETURN_OK;
 
-  deb_maxarea = minarea<MAXDEBAREA?minarea:MAXDEBAREA; /* 3 or less */
+  deb_maxarea = minarea < MAXDEBAREA ? minarea : MAXDEBAREA; /* 3 or less */
   plistint = plistin;
   stx = objparent->xmin;
   sty = objparent->ymin;
@@ -129,210 +131,183 @@ int lutz(pliststruct *plistin,
   thresh = objlist->thresh;
   cn = 0;
 
-  iscan = objrootsubmap + (sty-suby)*subw + (stx-subx);
+  iscan = objrootsubmap + (sty - suby) * subw + (stx - subx);
 
   /* As we only analyse a fraction of the map, a step occurs between lines */
-  step = subw - (++enx-stx);
+  step = subw - (++enx - stx);
   eny++;
 
   /*------Allocate memory to store object data */
   free(objlist->obj);
 
-  if (!(obj=objlist->obj=malloc(nobjm*sizeof(objstruct))))
-    {
-      out = MEMORY_ALLOC_ERROR;
-      plist = NULL;			/* To avoid gcc -Wall warnings */
-      goto exit_lutz;
-    }
+  if (!(obj = objlist->obj = malloc(nobjm * sizeof(objstruct)))) {
+    out = MEMORY_ALLOC_ERROR;
+    plist = NULL; /* To avoid gcc -Wall warnings */
+    goto exit_lutz;
+  }
 
   /*------Allocate memory for the pixel list */
   free(objlist->plist);
-  if (!(objlist->plist
-	= malloc((eny-sty)*(enx-stx)*plistsize)))
-    {
-      out = MEMORY_ALLOC_ERROR;
-      plist = NULL;			/* To avoid gcc -Wall warnings */
-      goto exit_lutz;
-    }
+  if (!(objlist->plist = malloc((eny - sty) * (enx - stx) * plistsize))) {
+    out = MEMORY_ALLOC_ERROR;
+    plist = NULL; /* To avoid gcc -Wall warnings */
+    goto exit_lutz;
+  }
 
   pixel = plist = objlist->plist;
 
   /*----------------------------------------*/
-  for (xl=stx; xl<=enx; xl++)
+  for (xl = stx; xl <= enx; xl++) {
     buffers->marker[xl] = 0;
+  }
 
   objlist->nobj = 0;
   co = pstop = 0;
   curpixinfo.pixnb = 1;
+  curpixinfo.flag = curpixinfo.firstpix = curpixinfo.lastpix = 0;
+
+  for (yl = sty; yl <= eny; yl++, iscan += step) {
+    ps = COMPLETE;
+    cs = NONOBJECT;
+    trunflag = (yl == 0 || yl == buffers->ymax) ? SEP_OBJ_TRUNC : 0;
+    if (yl == eny) {
+      iscan = buffers->discan;
+    }
 
-  for (yl=sty; yl<=eny; yl++, iscan += step)
-    {
-      ps = COMPLETE;
-      cs = NONOBJECT;
-      trunflag = (yl==0 || yl==buffers->ymax) ? SEP_OBJ_TRUNC : 0;
-      if (yl==eny)
-	iscan = buffers->discan;
-
-      for (xl=stx; xl<=enx; xl++)
-	{
-	  newmarker = buffers->marker[xl];
-	  buffers->marker[xl] = 0;
-	  if ((inewsymbol = (xl!=enx)?*(iscan++):-1) < 0)
-	    luflag = 0;
-	  else
-	    {
-	      curpixinfo.flag = trunflag;
-	      plistint = plistin+inewsymbol;
-	      luflag = (PLISTPIX(plistint, cdvalue) > thresh?1:0);
-	    }
-	  if (luflag)
-	    {
-	      if (xl==0 || xl==buffers->xmax)
-		curpixinfo.flag |= SEP_OBJ_TRUNC;
-	      memcpy(pixel, plistint, (size_t)plistsize);
-	      PLIST(pixel, nextpix) = -1;
-	      curpixinfo.lastpix = curpixinfo.firstpix = cn;
-	      cn += plistsize;
-	      pixel += plistsize;
-
-	      /*----------------- Start Segment -----------------------------*/
-	      if (cs != OBJECT)
-		{
-		  cs = OBJECT;
-		  if (ps == OBJECT)
-		    {
-		      if (buffers->start[co] == UNKNOWN)
-			{
-			  buffers->marker[xl] = 'S';
-			  buffers->start[co] = xl;
-			}
-		      else  buffers->marker[xl] = 's';
-		    }
-		  else
-		    {
-		      buffers->psstack[pstop++] = ps;
-		      buffers->marker[xl] = 'S';
-		      buffers->start[++co] = xl;
-		      ps = COMPLETE;
-		      buffers->info[co] = initinfo;
-		    }
-		}
-	    }
-
-	  /*-------------------Process New Marker ---------------------------*/
-	  if (newmarker)
-	    {
-	      if (newmarker == 'S')
-		{
-		  buffers->psstack[pstop++] = ps;
-		  if (cs == NONOBJECT)
-		    {
-		      buffers->psstack[pstop++] = COMPLETE;
-		      buffers->info[++co] = buffers->store[xl];
-		      buffers->start[co] = UNKNOWN;
-		    }
-		  else
-		    update(&buffers->info[co], &buffers->store[xl], plist);
-		  ps = OBJECT;
-		}
-
-	      else if (newmarker == 's')
-		{
-		  if ((cs == OBJECT) && (ps == COMPLETE))
-		    {
-		      pstop--;
-		      xl2 = buffers->start[co];
-		      update(&buffers->info[co-1], &buffers->info[co], plist);
-		      if (buffers->start[--co] == UNKNOWN)
-			buffers->start[co] = xl2;
-		      else
-			buffers->marker[xl2] = 's';
-		    }
-		  ps = OBJECT;
-		}
-	      else if (newmarker == 'f')
-		ps = INCOMPLETE;
-	      else if (newmarker == 'F')
-		{
-		  ps = buffers->psstack[--pstop];
-		  if ((cs == NONOBJECT) && (ps == COMPLETE))
-		    {
-		      if (buffers->start[co] == UNKNOWN)
-			{
-			  if ((int)buffers->info[co].pixnb >= deb_maxarea)
-			    {
-			      if (objlist->nobj>=nobjm)
-				if (!(obj = objlist->obj = (objstruct *)
-				      realloc(obj, (nobjm+=nobjm/2)*
-					      sizeof(objstruct))))
-				  {
-				    out = MEMORY_ALLOC_ERROR;
-				    goto exit_lutz;
-				  }
-			      lutzsort(&buffers->info[co], objlist);
-			    }
-			}
-		      else
-			{
-			  buffers->marker[buffers->end[co]] = 'F';
-			  buffers->store[buffers->start[co]] = buffers->info[co];
-			}
-		      co--;
-		      ps = buffers->psstack[--pstop];
-		    }
-		}
-	    }
-	  /* end process new marker -----------------------------------------*/
-
-	  if (luflag)
-	    update (&buffers->info[co],&curpixinfo, plist);
-	  else
-	    {
-	      /* ----------------- End Segment ------------------------------*/
-	      if (cs == OBJECT)
-		{
-		  cs = NONOBJECT;
-		  if (ps != COMPLETE)
-		    {
-		      buffers->marker[xl] = 'f';
-		      buffers->end[co] = xl;
-		    }
-		  else
-		    {
-		      ps = buffers->psstack[--pstop];
-		      buffers->marker[xl] = 'F';
-		      buffers->store[buffers->start[co]] = buffers->info[co];
-		      co--;
-		    }
-		}
-	    }
-	}
+    for (xl = stx; xl <= enx; xl++) {
+      newmarker = buffers->marker[xl];
+      buffers->marker[xl] = 0;
+      if ((inewsymbol = (xl != enx) ? *(iscan++) : -1) < 0) {
+        luflag = 0;
+      } else {
+        curpixinfo.flag = trunflag;
+        plistint = plistin + inewsymbol;
+        luflag = (PLISTPIX(plistint, cdvalue) > thresh ? 1 : 0);
+      }
+      if (luflag) {
+        if (xl == 0 || xl == buffers->xmax) {
+          curpixinfo.flag |= SEP_OBJ_TRUNC;
+        }
+        memcpy(pixel, plistint, (size_t)plistsize);
+        PLIST(pixel, nextpix) = -1;
+        curpixinfo.lastpix = curpixinfo.firstpix = cn;
+        cn += plistsize;
+        pixel += plistsize;
+
+        /*----------------- Start Segment -----------------------------*/
+        if (cs != OBJECT) {
+          cs = OBJECT;
+          if (ps == OBJECT) {
+            if (buffers->start[co] == UNKNOWN) {
+              buffers->marker[xl] = 'S';
+              buffers->start[co] = xl;
+            } else {
+              buffers->marker[xl] = 's';
+            }
+          } else {
+            buffers->psstack[pstop++] = ps;
+            buffers->marker[xl] = 'S';
+            buffers->start[++co] = xl;
+            ps = COMPLETE;
+            buffers->info[co] = initinfo;
+          }
+        }
+      }
+
+      /*-------------------Process New Marker ---------------------------*/
+      if (newmarker) {
+        if (newmarker == 'S') {
+          buffers->psstack[pstop++] = ps;
+          if (cs == NONOBJECT) {
+            buffers->psstack[pstop++] = COMPLETE;
+            buffers->info[++co] = buffers->store[xl];
+            buffers->start[co] = UNKNOWN;
+          } else {
+            update(&buffers->info[co], &buffers->store[xl], plist);
+          }
+          ps = OBJECT;
+        }
+
+        else if (newmarker == 's')
+        {
+          if ((cs == OBJECT) && (ps == COMPLETE)) {
+            pstop--;
+            xl2 = buffers->start[co];
+            update(&buffers->info[co - 1], &buffers->info[co], plist);
+            if (buffers->start[--co] == UNKNOWN) {
+              buffers->start[co] = xl2;
+            } else {
+              buffers->marker[xl2] = 's';
+            }
+          }
+          ps = OBJECT;
+        } else if (newmarker == 'f') {
+          ps = INCOMPLETE;
+        } else if (newmarker == 'F') {
+          ps = buffers->psstack[--pstop];
+          if ((cs == NONOBJECT) && (ps == COMPLETE)) {
+            if (buffers->start[co] == UNKNOWN) {
+              if ((int64_t)buffers->info[co].pixnb >= deb_maxarea) {
+                if (objlist->nobj >= nobjm) {
+                  if (!(obj = objlist->obj = (objstruct *)
+                            realloc(obj, (nobjm += nobjm / 2) * sizeof(objstruct))))
+                  {
+                    out = MEMORY_ALLOC_ERROR;
+                    goto exit_lutz;
+                  }
+                }
+                lutzsort(&buffers->info[co], objlist);
+              }
+            } else {
+              buffers->marker[buffers->end[co]] = 'F';
+              buffers->store[buffers->start[co]] = buffers->info[co];
+            }
+            co--;
+            ps = buffers->psstack[--pstop];
+          }
+        }
+      }
+      /* end process new marker -----------------------------------------*/
+
+      if (luflag) {
+        update(&buffers->info[co], &curpixinfo, plist);
+      } else {
+        /* ----------------- End Segment ------------------------------*/
+        if (cs == OBJECT) {
+          cs = NONOBJECT;
+          if (ps != COMPLETE) {
+            buffers->marker[xl] = 'f';
+            buffers->end[co] = xl;
+          } else {
+            ps = buffers->psstack[--pstop];
+            buffers->marker[xl] = 'F';
+            buffers->store[buffers->start[co]] = buffers->info[co];
+            co--;
+          }
+        }
+      }
     }
+  }
 
- exit_lutz:
+exit_lutz:
 
-  if (objlist->nobj && out == RETURN_OK)
-    {
-      if (!(objlist->obj=
-	    realloc(obj, objlist->nobj*sizeof(objstruct))))
-	out = MEMORY_ALLOC_ERROR;
-    }
-  else
-    {
-      free(obj);
-      objlist->obj = NULL;
+  if (objlist->nobj && out == RETURN_OK) {
+    if (!(objlist->obj = realloc(obj, objlist->nobj * sizeof(objstruct)))) {
+      out = MEMORY_ALLOC_ERROR;
     }
+  } else {
+    free(obj);
+    objlist->obj = NULL;
+  }
 
-  if (cn && out == RETURN_OK)
-    {
-      if (!(objlist->plist=realloc(plist,cn)))
-	out = MEMORY_ALLOC_ERROR;
-    }
-  else
-    {
-      free(objlist->plist);
-      objlist->plist = NULL;
+  if (cn && out == RETURN_OK) {
+    if (!(objlist->plist = realloc(plist, cn))) {
+      out = MEMORY_ALLOC_ERROR;
     }
+  } else {
+    free(objlist->plist);
+    objlist->plist = NULL;
+  }
 
   return out;
 }
@@ -341,9 +316,8 @@ int lutz(pliststruct *plistin,
 /*
 Add an object to the object list based on info (pixel info)
 */
-void  lutzsort(infostruct *info, objliststruct *objlist)
-{
-  objstruct *obj = objlist->obj+objlist->nobj;
+void lutzsort(infostruct * info, objliststruct * objlist) {
+  objstruct * obj = objlist->obj + objlist->nobj;
 
   memset(obj, 0, (size_t)sizeof(objstruct));
   obj->firstpix = info->firstpix;
@@ -360,18 +334,14 @@ void  lutzsort(infostruct *info, objliststruct *objlist)
 /*
 update object's properties each time one of its pixels is scanned by lutz()
 */
-void  update(infostruct *infoptr1, infostruct *infoptr2, pliststruct *pixel)
-{
+void update(infostruct * infoptr1, infostruct * infoptr2, pliststruct * pixel) {
   infoptr1->pixnb += infoptr2->pixnb;
   infoptr1->flag |= infoptr2->flag;
-  if (infoptr1->firstpix == -1)
-    {
-      infoptr1->firstpix = infoptr2->firstpix;
-      infoptr1->lastpix = infoptr2->lastpix;
-    }
-  else if (infoptr2->lastpix != -1)
-    {
-      PLIST(pixel+infoptr1->lastpix, nextpix) = infoptr2->firstpix;
-      infoptr1->lastpix = infoptr2->lastpix;
-    }
+  if (infoptr1->firstpix == -1) {
+    infoptr1->firstpix = infoptr2->firstpix;
+    infoptr1->lastpix = infoptr2->lastpix;
+  } else if (infoptr2->lastpix != -1) {
+    PLIST(pixel + infoptr1->lastpix, nextpix) = infoptr2->firstpix;
+    infoptr1->lastpix = infoptr2->lastpix;
+  }
 }
diff --git a/src/overlap.h b/src/overlap.h
index 8db9449..8f459bc 100644
--- a/src/overlap.h
+++ b/src/overlap.h
@@ -5,140 +5,145 @@
  * Original cython version by Thomas Robitaille. Converted to C by Kyle
  * Barbary. */
 
+#include <math.h>
+#include "sepcore.h"
+
 #if defined(_MSC_VER)
-  #define INLINE _inline
+#define INLINE _inline
 #else
-  #define INLINE inline
+#define INLINE inline
 #endif
 
 /* Return area of a circle arc between (x1, y1) and (x2, y2) with radius r */
 /* reference: http://mathworld.wolfram.com/CircularSegment.html */
-static INLINE double area_arc(double x1, double y1, double x2, double y2,
-			      double r)
-{
+static INLINE double area_arc(double x1, double y1, double x2, double y2, double r) {
   double a, theta;
 
-  a = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+  a = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
   theta = 2. * asin(0.5 * a / r);
   return 0.5 * r * r * (theta - sin(theta));
 }
 
 /* Area of a triangle defined by three verticies */
-static INLINE double area_triangle(double x1, double y1, double x2, double y2,
-				   double x3, double y3)
-{
-  return 0.5 * fabs(x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2));
+static INLINE double area_triangle(
+    double x1, double y1, double x2, double y2, double x3, double y3
+) {
+  return 0.5 * fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
 }
 
 /* Core of circular overlap routine.
  * Assumes that xmax >= xmin >= 0.0, ymax >= ymin >= 0.0.
  * (can always modify input to conform to this).
  */
-static INLINE double circoverlap_core(double xmin, double ymin,
-				      double xmax, double ymax, double r)
-{
+static INLINE double circoverlap_core(
+    double xmin, double ymin, double xmax, double ymax, double r
+) {
   double a, b, x1, x2, y1, y2, r2, xmin2, ymin2, xmax2, ymax2;
 
-  xmin2 = xmin*xmin;
-  ymin2 = ymin*ymin;
-  r2 = r*r;
-  if (xmin2 + ymin2 > r2)
+  xmin2 = xmin * xmin;
+  ymin2 = ymin * ymin;
+  r2 = r * r;
+  if (xmin2 + ymin2 > r2) {
     return 0.;
-
-  xmax2 = xmax*xmax;
-  ymax2 = ymax*ymax;
-  if (xmax2 + ymax2 < r2)
-    return (xmax-xmin)*(ymax-ymin);
-
-  a = xmax2 + ymin2;  /* (corner 1 distance)^2 */
-  b = xmin2 + ymax2;  /* (corner 2 distance)^2 */
-
-  if (a < r2 && b < r2)
-    {
-      x1 = sqrt(r2 - ymax2);
-      y1 = ymax;
-      x2 = xmax;
-      y2 = sqrt(r2 - xmax2);
-      return ((xmax-xmin)*(ymax-ymin) -
-	      area_triangle(x1, y1, x2, y2, xmax, ymax) +
-	      area_arc(x1, y1, x2, y2, r));
-    }
-
-  if (a < r2)
-    {
-      x1 = xmin;
-      y1 = sqrt(r2 - xmin2);
-      x2 = xmax;
-      y2 = sqrt(r2 - xmax2);
-      return (area_arc(x1, y1, x2, y2, r) +
-	      area_triangle(x1, y1, x1, ymin, xmax, ymin) +
-	      area_triangle(x1, y1, x2, ymin, x2, y2));
-    }
-
-  if (b < r2)
-    {
-      x1 = sqrt(r2 - ymin2);
-      y1 = ymin;
-      x2 = sqrt(r2 - ymax2);
-      y2 = ymax;
-      return (area_arc(x1, y1, x2, y2, r) +
-	      area_triangle(x1, y1, xmin, y1, xmin, ymax) +
-	      area_triangle(x1, y1, xmin, y2, x2, y2));
-    }
+  }
+
+  xmax2 = xmax * xmax;
+  ymax2 = ymax * ymax;
+  if (xmax2 + ymax2 < r2) {
+    return (xmax - xmin) * (ymax - ymin);
+  }
+
+  a = xmax2 + ymin2; /* (corner 1 distance)^2 */
+  b = xmin2 + ymax2; /* (corner 2 distance)^2 */
+
+  if (a < r2 && b < r2) {
+    x1 = sqrt(r2 - ymax2);
+    y1 = ymax;
+    x2 = xmax;
+    y2 = sqrt(r2 - xmax2);
+    return (
+        (xmax - xmin) * (ymax - ymin) - area_triangle(x1, y1, x2, y2, xmax, ymax)
+        + area_arc(x1, y1, x2, y2, r)
+    );
+  }
+
+  if (a < r2) {
+    x1 = xmin;
+    y1 = sqrt(r2 - xmin2);
+    x2 = xmax;
+    y2 = sqrt(r2 - xmax2);
+    return (
+        area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x1, ymin, xmax, ymin)
+        + area_triangle(x1, y1, x2, ymin, x2, y2)
+    );
+  }
+
+  if (b < r2) {
+    x1 = sqrt(r2 - ymin2);
+    y1 = ymin;
+    x2 = sqrt(r2 - ymax2);
+    y2 = ymax;
+    return (
+        area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, xmin, y1, xmin, ymax)
+        + area_triangle(x1, y1, xmin, y2, x2, y2)
+    );
+  }
 
   /* else */
   x1 = sqrt(r2 - ymin2);
   y1 = ymin;
   x2 = xmin;
   y2 = sqrt(r2 - xmin2);
-  return (area_arc(x1, y1, x2, y2, r) +
-	  area_triangle(x1, y1, x2, y2, xmin, ymin));
+  return (area_arc(x1, y1, x2, y2, r) + area_triangle(x1, y1, x2, y2, xmin, ymin));
 }
 
 
-
 /* Area of overlap of a rectangle and a circle */
-static double circoverlap(double xmin, double ymin, double xmax, double ymax,
-			  double r)
-{
+static double circoverlap(
+    double xmin, double ymin, double xmax, double ymax, double r
+) {
   /* some subroutines demand that r > 0 */
-  if (r <= 0.)
+  if (r <= 0.) {
     return 0.;
-
-  if (0. <= xmin)
-    {
-      if (0. <= ymin)
-	return circoverlap_core(xmin, ymin, xmax, ymax, r);
-      else if (0. >= ymax)
-	return circoverlap_core(-ymax, xmin, -ymin, xmax, r);
-      else
-	return (circoverlap(xmin, ymin, xmax, 0., r) +
-                circoverlap(xmin, 0., xmax, ymax, r));
+  }
+
+  if (0. <= xmin) {
+    if (0. <= ymin) {
+      return circoverlap_core(xmin, ymin, xmax, ymax, r);
+    } else if (0. >= ymax) {
+      return circoverlap_core(-ymax, xmin, -ymin, xmax, r);
+    } else {
+      return (
+          circoverlap(xmin, ymin, xmax, 0., r) + circoverlap(xmin, 0., xmax, ymax, r)
+      );
     }
-  else if (0. >= xmax)
-    {
-      if (0. <= ymin)
-	return circoverlap_core(-xmax, ymin, -xmin, ymax, r);
-      else if (0. >= ymax)
-	return circoverlap_core(-xmax, -ymax, -xmin, -ymin, r);
-      else
-	return (circoverlap(xmin, ymin, xmax, 0., r) +
-                circoverlap(xmin, 0., xmax, ymax, r));
+  } else if (0. >= xmax) {
+    if (0. <= ymin) {
+      return circoverlap_core(-xmax, ymin, -xmin, ymax, r);
+    } else if (0. >= ymax) {
+      return circoverlap_core(-xmax, -ymax, -xmin, -ymin, r);
+    } else {
+      return (
+          circoverlap(xmin, ymin, xmax, 0., r) + circoverlap(xmin, 0., xmax, ymax, r)
+      );
     }
-  else
-    {
-      if (0. <= ymin)
-	return (circoverlap(xmin, ymin, 0., ymax, r) +
-                circoverlap(0., ymin, xmax, ymax, r));
-      if (0. >= ymax)
-	return (circoverlap(xmin, ymin, 0., ymax, r) +
-                circoverlap(0., ymin, xmax, ymax, r));
-      else
-	return (circoverlap(xmin, ymin, 0., 0., r) +
-                circoverlap(0., ymin, xmax, 0., r) +
-                circoverlap(xmin, 0., 0., ymax, r) +
-                circoverlap(0., 0., xmax, ymax, r));
+  } else {
+    if (0. <= ymin) {
+      return (
+          circoverlap(xmin, ymin, 0., ymax, r) + circoverlap(0., ymin, xmax, ymax, r)
+      );
     }
+    if (0. >= ymax) {
+      return (
+          circoverlap(xmin, ymin, 0., ymax, r) + circoverlap(0., ymin, xmax, ymax, r)
+      );
+    } else {
+      return (
+          circoverlap(xmin, ymin, 0., 0., r) + circoverlap(0., ymin, xmax, 0., r)
+          + circoverlap(xmin, 0., 0., ymax, r) + circoverlap(0., 0., xmax, ymax, r)
+      );
+    }
+  }
 }
 
 /*
@@ -176,27 +181,23 @@ double circoverlap_new(double dx, double dy, double r)
 /*****************************************************************************/
 /* ellipse overlap functions */
 
-typedef struct
-{
+typedef struct {
   double x, y;
 } point;
 
 
-typedef struct
-{
+typedef struct {
   point p1, p2;
 } intersections;
 
-static INLINE void swap(double *a, double *b)
-{
+static INLINE void swap(double * a, double * b) {
   double temp;
   temp = *a;
   *a = *b;
   *b = temp;
 }
 
-static INLINE void swap_point(point *a, point *b)
-{
+static INLINE void swap_point(point * a, point * b) {
   point temp;
   temp = *a;
   *a = *b;
@@ -204,8 +205,7 @@ static INLINE void swap_point(point *a, point *b)
 }
 
 /* rotate values to the left: a=b, b=c, c=a */
-static INLINE void rotate(double *a, double *b, double *c)
-{
+static INLINE void rotate(double * a, double * b, double * c) {
   double temp;
   temp = *a;
   *a = *b;
@@ -214,23 +214,22 @@ static INLINE void rotate(double *a, double *b, double *c)
 }
 
 /* Check if a point (x,y) is inside a triangle */
-static int in_triangle(double x, double y, double x1, double y1,
-		       double x2, double y2, double x3, double y3)
-{
+static int in_triangle(
+    double x, double y, double x1, double y1, double x2, double y2, double x3, double y3
+) {
   int c;
 
   c = 0;
-  c += ((y1 > y) != (y2 > y)) && (x < (x2-x1) * (y-y1) / (y2-y1) + x1);
-  c += ((y2 > y) != (y3 > y)) && (x < (x3-x2) * (y-y2) / (y3-y2) + x2);
-  c += ((y3 > y) != (y1 > y)) && (x < (x1-x3) * (y-y3) / (y1-y3) + x3);
+  c += ((y1 > y) != (y2 > y)) && (x < (x2 - x1) * (y - y1) / (y2 - y1) + x1);
+  c += ((y2 > y) != (y3 > y)) && (x < (x3 - x2) * (y - y2) / (y3 - y2) + x2);
+  c += ((y3 > y) != (y1 > y)) && (x < (x1 - x3) * (y - y3) / (y1 - y3) + x3);
 
   return c % 2 == 1;
 }
 
 
 /* Intersection of a line defined by two points with a unit circle */
-static intersections circle_line(double x1, double y1, double x2, double y2)
-{
+static intersections circle_line(double x1, double y1, double x2, double y2) {
   double a, b, delta, dx, dy;
   double tol = 1.e-10;
   intersections inter;
@@ -238,70 +237,58 @@ static intersections circle_line(double x1, double y1, double x2, double y2)
   dx = x2 - x1;
   dy = y2 - y1;
 
-  if (fabs(dx) < tol && fabs(dy) < tol)
-    {
+  if (fabs(dx) < tol && fabs(dy) < tol) {
+    inter.p1.x = 2.;
+    inter.p1.y = 2.;
+    inter.p2.x = 2.;
+    inter.p2.y = 2.;
+  } else if (fabs(dx) > fabs(dy)) {
+    /* Find the slope and intercept of the line */
+    a = dy / dx;
+    b = y1 - a * x1;
+
+    /* Find the determinant of the quadratic equation */
+    delta = 1. + a * a - b * b;
+    if (delta > 0.) /* solutions exist */ {
+      delta = sqrt(delta);
+
+      inter.p1.x = (-a * b - delta) / (1. + a * a);
+      inter.p1.y = a * inter.p1.x + b;
+      inter.p2.x = (-a * b + delta) / (1. + a * a);
+      inter.p2.y = a * inter.p2.x + b;
+    } else /* no solution, return values > 1 */ {
       inter.p1.x = 2.;
       inter.p1.y = 2.;
       inter.p2.x = 2.;
       inter.p2.y = 2.;
     }
-  else if (fabs(dx) > fabs(dy))
-    {
-      /* Find the slope and intercept of the line */
-      a = dy / dx;
-      b = y1 - a * x1;
-
-      /* Find the determinant of the quadratic equation */
-      delta = 1. + a*a - b*b;
-      if (delta > 0.)  /* solutions exist */
-	{
-	  delta = sqrt(delta);
-
-	  inter.p1.x = (-a*b - delta) / (1. + a*a);
-	  inter.p1.y = a * inter.p1.x + b;
-	  inter.p2.x = (-a*b + delta) / (1. + a*a);
-	  inter.p2.y = a * inter.p2.x + b;
-	}
-      else  /* no solution, return values > 1 */
-	{
-	  inter.p1.x = 2.;
-	  inter.p1.y = 2.;
-	  inter.p2.x = 2.;
-	  inter.p2.y = 2.;
-	}
-    }
-  else
-    {
-      /* Find the slope and intercept of the line */
-      a = dx / dy;
-      b = x1 - a * y1;
-
-      /* Find the determinant of the quadratic equation */
-      delta = 1. + a*a - b*b;
-      if (delta > 0.)  /* solutions exist */
-	{
-	  delta = sqrt(delta);
-	  inter.p1.y = (-a*b - delta) / (1. + a*a);
-	  inter.p1.x = a * inter.p1.y + b;
-	  inter.p2.y = (-a*b + delta) / (1. + a*a);
-	  inter.p2.x = a * inter.p2.y + b;
-	}
-      else  /* no solution, return values > 1 */
-	{
-	  inter.p1.x = 2.;
-	  inter.p1.y = 2.;
-	  inter.p2.x = 2.;
-	  inter.p2.y = 2.;
-	}
+  } else {
+    /* Find the slope and intercept of the line */
+    a = dx / dy;
+    b = x1 - a * y1;
+
+    /* Find the determinant of the quadratic equation */
+    delta = 1. + a * a - b * b;
+    if (delta > 0.) /* solutions exist */ {
+      delta = sqrt(delta);
+      inter.p1.y = (-a * b - delta) / (1. + a * a);
+      inter.p1.x = a * inter.p1.y + b;
+      inter.p2.y = (-a * b + delta) / (1. + a * a);
+      inter.p2.x = a * inter.p2.y + b;
+    } else /* no solution, return values > 1 */ {
+      inter.p1.x = 2.;
+      inter.p1.y = 2.;
+      inter.p2.x = 2.;
+      inter.p2.y = 2.;
     }
+  }
 
   return inter;
 }
 
 /* The intersection of a line with the unit circle. The intersection the
  * closest to (x2, y2) is chosen. */
-static point circle_segment_single2(double x1, double y1, double x2, double y2)
-{
+static point circle_segment_single2(double x1, double y1, double x2, double y2) {
   double dx1, dy1, dx2, dy2;
   intersections inter;
   point pt1, pt2, pt;
@@ -316,18 +303,18 @@ static point circle_segment_single2(double x1, double y1, double x2, double y2)
   dx2 = fabs(pt2.x - x2);
   dy2 = fabs(pt2.y - y2);
 
-  if (dx1 > dy1)  /* compare based on x-axis */
+  if (dx1 > dy1) /* compare based on x-axis */ {
     pt = (dx1 > dx2) ? pt2 : pt1;
-  else
+  } else {
     pt = (dy1 > dy2) ? pt2 : pt1;
-     
+  }
+
   return pt;
 }
 
 /* Intersection(s) of a segment with the unit circle. Discard any
    solution not on the segment. */
-intersections circle_segment(double x1, double y1, double x2, double y2)
-{
+static inline intersections circle_segment(double x1, double y1, double x2, double y2) {
   intersections inter, inter_new;
   point pt1, pt2;
 
@@ -335,39 +322,35 @@ intersections circle_segment(double x1, double y1, double x2, double y2)
   pt1 = inter.p1;
   pt2 = inter.p2;
 
-  if ((pt1.x > x1 && pt1.x > x2) || (pt1.x < x1 && pt1.x < x2) ||
-      (pt1.y > y1 && pt1.y > y2) || (pt1.y < y1 && pt1.y < y2))
-    {
-      pt1.x = 2.;
-      pt1.y = 2.;
-    }
-  if ((pt2.x > x1 && pt2.x > x2) || (pt2.x < x1 && pt2.x < x2) ||
-      (pt2.y > y1 && pt2.y > y2) || (pt2.y < y1 && pt2.y < y2))
-    {
-      pt2.x = 2.;
-      pt2.y = 2.;
-    }
-
-  if (pt1.x > 1. && pt2.x < 2.)
-    {
-      inter_new.p1 = pt1;
-      inter_new.p2 = pt2;
-    }
-  else
-    {
-      inter_new.p1 = pt2;
-      inter_new.p2 = pt1;
-    }
+  if ((pt1.x > x1 && pt1.x > x2) || (pt1.x < x1 && pt1.x < x2)
+      || (pt1.y > y1 && pt1.y > y2) || (pt1.y < y1 && pt1.y < y2))
+  {
+    pt1.x = 2.;
+    pt1.y = 2.;
+  }
+  if ((pt2.x > x1 && pt2.x > x2) || (pt2.x < x1 && pt2.x < x2)
+      || (pt2.y > y1 && pt2.y > y2) || (pt2.y < y1 && pt2.y < y2))
+  {
+    pt2.x = 2.;
+    pt2.y = 2.;
+  }
+
+  if (pt1.x > 1. && pt2.x < 2.) {
+    inter_new.p1 = pt1;
+    inter_new.p2 = pt2;
+  } else {
+    inter_new.p1 = pt2;
+    inter_new.p2 = pt1;
+  }
   return inter_new;
 }
 
 
 /* Given a triangle defined by three points (x1, y1), (x2, y2), and
    (x3, y3), find the area of overlap with the unit circle. */
-static double triangle_unitcircle_overlap(double x1, double y1,
-					  double x2, double y2,
-					  double x3, double y3)
-{
+static double triangle_unitcircle_overlap(
+    double x1, double y1, double x2, double y2, double x3, double y3
+) {
   double d1, d2, d3, area, xp, yp;
   int in1, in2, in3, on1, on2, on3;
   int intersect13, intersect23;
@@ -375,50 +358,38 @@ static double triangle_unitcircle_overlap(double x1, double y1,
   point pt1, pt2, pt3, pt4, pt5, pt6;
 
   /* Find distance of all vertices to circle center */
-  d1 = x1*x1 + y1*y1;
-  d2 = x2*x2 + y2*y2;
-  d3 = x3*x3 + y3*y3;
+  d1 = x1 * x1 + y1 * y1;
+  d2 = x2 * x2 + y2 * y2;
+  d3 = x3 * x3 + y3 * y3;
 
   /* Order vertices by distance from origin */
-  if (d1 < d2)
-    {
-      if (d2 < d3)
-	{}
-      else if (d1 < d3)
-	{
-	  swap(&x2, &x3);
-	  swap(&y2, &y3);
-	  swap(&d2, &d3);
-	}
-      else
-	{
-	  rotate(&x1, &x3, &x2);
-	  rotate(&y1, &y3, &y2);
-	  rotate(&d1, &d3, &d2);
-	}
+  if (d1 < d2) {
+    if (d2 < d3) {
+    } else if (d1 < d3) {
+      swap(&x2, &x3);
+      swap(&y2, &y3);
+      swap(&d2, &d3);
+    } else {
+      rotate(&x1, &x3, &x2);
+      rotate(&y1, &y3, &y2);
+      rotate(&d1, &d3, &d2);
     }
-  else
-    {
-      if (d1 < d3)
-	{
-	  swap(&x1, &x2);
-	  swap(&y1, &y2);
-	  swap(&d1, &d2);
-	}
-      else if (d2 < d3)
-	{
-	  rotate(&x1, &x2, &x3);
-	  rotate(&y1, &y2, &y3);
-	  rotate(&d1, &d2, &d3);
-	}
-      else
-	{
-	  swap(&x1, &x3);
-	  swap(&y1, &y3);
-	  swap(&d1, &d3);
-	}
+  } else {
+    if (d1 < d3) {
+      swap(&x1, &x2);
+      swap(&y1, &y2);
+      swap(&d1, &d2);
+    } else if (d2 < d3) {
+      rotate(&x1, &x2, &x3);
+      rotate(&y1, &y2, &y3);
+      rotate(&d1, &d2, &d3);
+    } else {
+      swap(&x1, &x3);
+      swap(&y1, &y3);
+      swap(&d1, &d3);
     }
-     
+  }
+
   /* Determine number of vertices inside circle */
   in1 = d1 < 1.;
   in2 = d2 < 1.;
@@ -429,131 +400,123 @@ static double triangle_unitcircle_overlap(double x1, double y1,
   on2 = fabs(d2 - 1.) < 1.e-10;
   on3 = fabs(d3 - 1.) < 1.e-10;
 
-  if (on3 || in3) /* triangle completely within circle */
+  if (on3 || in3) /* triangle completely within circle */ {
     area = area_triangle(x1, y1, x2, y2, x3, y3);
+  }
 
   else if (in2 || on2)
-    {
-      /* If vertex 1 or 2 are on the edge of the circle, then we use
-       * the dot product to vertex 3 to determine whether an
-       * intersection takes place. */
-      intersect13 = !on1 || (x1*(x3-x1) + y1*(y3-y1) < 0.);
-      intersect23 = !on2 || (x2*(x3-x2) + y2*(y3-y2) < 0.);
-      if (intersect13 && intersect23)
-	{
-	  pt1 = circle_segment_single2(x1, y1, x3, y3);
-	  pt2 = circle_segment_single2(x2, y2, x3, y3);
-	  area = (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) +
-		  area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y) +
-		  area_arc(pt1.x, pt1.y, pt2.x, pt2.y, 1.));
-	}
-      else if (intersect13)
-	{
-	  pt1 = circle_segment_single2(x1, y1, x3, y3);
-	  area = (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y) +
-		  area_arc(x2, y2, pt1.x, pt1.y, 1.));
-	}
-      else if (intersect23)
-	{
-	  pt2 = circle_segment_single2(x2, y2, x3, y3);
-	  area = (area_triangle(x1, y1, x2, y2, pt2.x, pt2.y) +
-		  area_arc(x1, y1, pt2.x, pt2.y, 1.));
-	}
-      else
-	area = area_arc(x1, y1, x2, y2, 1.);
+  {
+    /* If vertex 1 or 2 are on the edge of the circle, then we use
+     * the dot product to vertex 3 to determine whether an
+     * intersection takes place. */
+    intersect13 = !on1 || (x1 * (x3 - x1) + y1 * (y3 - y1) < 0.);
+    intersect23 = !on2 || (x2 * (x3 - x2) + y2 * (y3 - y2) < 0.);
+    if (intersect13 && intersect23) {
+      pt1 = circle_segment_single2(x1, y1, x3, y3);
+      pt2 = circle_segment_single2(x2, y2, x3, y3);
+      area =
+          (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y)
+           + area_triangle(x2, y2, pt1.x, pt1.y, pt2.x, pt2.y)
+           + area_arc(pt1.x, pt1.y, pt2.x, pt2.y, 1.));
+    } else if (intersect13) {
+      pt1 = circle_segment_single2(x1, y1, x3, y3);
+      area =
+          (area_triangle(x1, y1, x2, y2, pt1.x, pt1.y)
+           + area_arc(x2, y2, pt1.x, pt1.y, 1.));
+    } else if (intersect23) {
+      pt2 = circle_segment_single2(x2, y2, x3, y3);
+      area =
+          (area_triangle(x1, y1, x2, y2, pt2.x, pt2.y)
+           + area_arc(x1, y1, pt2.x, pt2.y, 1.));
+    } else {
+      area = area_arc(x1, y1, x2, y2, 1.);
     }
-  else if (in1)
-    {
-      /* Check for intersections of far side with circle */
-      inter = circle_segment(x2, y2, x3, y3);
-      pt1 = inter.p1;
-      pt2 = inter.p2;
-      pt3 = circle_segment_single2(x1, y1, x2, y2);
-      pt4 = circle_segment_single2(x1, y1, x3, y3);
-
-      if (pt1.x > 1.)  /* indicates no intersection */
-	{
-	  /* check if the pixel vertex (x1, y2) and the origin are on
-	   * different sides of the circle segment. If they are, the
-	   * circle segment spans more than pi radians.
-	   * We use the formula (y-y1) * (x2-x1) > (y2-y1) * (x-x1)
-	   * to determine if (x, y) is on the left of the directed
-	   * line segment from (x1, y1) to (x2, y2) */
-	  if (((0.-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (0.-pt3.x)) !=
-	      ((y1-pt3.y) * (pt4.x-pt3.x) > (pt4.y-pt3.y) * (x1-pt3.x)))
-	    {
-	      area = (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) +
-		      PI - area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.));
-	    }
-	  else
-	    {
-	      area = (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) +
-		      area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.));
-	    }
-	}
-      else
-	{
-	  /* ensure that pt1 is the point closest to (x2, y2) */
-	  if (((pt2.x-x2)*(pt2.x-x2) + (pt2.y-y2)*(pt2.y-y2)) <
-	      ((pt1.x-x2)*(pt1.x-x2) + (pt1.y-y2)*(pt1.y-y2)))
-	    swap_point(&pt1, &pt2);
-
-	  area = (area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y) +
-		  area_triangle(x1, y1, pt1.x, pt1.y, pt2.x, pt2.y) +
-		  area_triangle(x1, y1, pt2.x, pt2.y, pt4.x, pt4.y) +
-		  area_arc(pt1.x, pt1.y, pt3.x, pt3.y, 1.) +
-		  area_arc(pt2.x, pt2.y, pt4.x, pt4.y, 1.));
-	}
+  } else if (in1) {
+    /* Check for intersections of far side with circle */
+    inter = circle_segment(x2, y2, x3, y3);
+    pt1 = inter.p1;
+    pt2 = inter.p2;
+    pt3 = circle_segment_single2(x1, y1, x2, y2);
+    pt4 = circle_segment_single2(x1, y1, x3, y3);
+
+    if (pt1.x > 1.) /* indicates no intersection */ {
+      /* check if the pixel vertex (x1, y2) and the origin are on
+       * different sides of the circle segment. If they are, the
+       * circle segment spans more than pi radians.
+       * We use the formula (y-y1) * (x2-x1) > (y2-y1) * (x-x1)
+       * to determine if (x, y) is on the left of the directed
+       * line segment from (x1, y1) to (x2, y2) */
+      if (((0. - pt3.y) * (pt4.x - pt3.x) > (pt4.y - pt3.y) * (0. - pt3.x))
+          != ((y1 - pt3.y) * (pt4.x - pt3.x) > (pt4.y - pt3.y) * (x1 - pt3.x)))
+      {
+        area =
+            (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y) + PI
+             - area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.));
+      } else {
+        area =
+            (area_triangle(x1, y1, pt3.x, pt3.y, pt4.x, pt4.y)
+             + area_arc(pt3.x, pt3.y, pt4.x, pt4.y, 1.));
+      }
+    } else {
+      /* ensure that pt1 is the point closest to (x2, y2) */
+      if (((pt2.x - x2) * (pt2.x - x2) + (pt2.y - y2) * (pt2.y - y2))
+          < ((pt1.x - x2) * (pt1.x - x2) + (pt1.y - y2) * (pt1.y - y2)))
+      {
+        swap_point(&pt1, &pt2);
+      }
+
+      area =
+          (area_triangle(x1, y1, pt3.x, pt3.y, pt1.x, pt1.y)
+           + area_triangle(x1, y1, pt1.x, pt1.y, pt2.x, pt2.y)
+           + area_triangle(x1, y1, pt2.x, pt2.y, pt4.x, pt4.y)
+           + area_arc(pt1.x, pt1.y, pt3.x, pt3.y, 1.)
+           + area_arc(pt2.x, pt2.y, pt4.x, pt4.y, 1.));
     }
-  else
-    {
-      inter = circle_segment(x1, y1, x2, y2);
-      pt1 = inter.p1;
-      pt2 = inter.p2;
-      inter = circle_segment(x2, y2, x3, y3);
-      pt3 = inter.p1;
-      pt4 = inter.p2;
-      inter = circle_segment(x3, y3, x1, y1);
-      pt5 = inter.p1;
-      pt6 = inter.p2;
-      if (pt1.x <= 1.)
-	{
-	  xp = 0.5 * (pt1.x + pt2.x);
-	  yp = 0.5 * (pt1.y + pt2.y);
-	  area = (triangle_unitcircle_overlap(x1, y1, x3, y3, xp, yp) +
-		  triangle_unitcircle_overlap(x2, y2, x3, y3, xp, yp));
-	}
-      else if (pt3.x <= 1.)
-	{
-	  xp = 0.5 * (pt3.x + pt4.x);
-	  yp = 0.5 * (pt3.y + pt4.y);
-	  area = (triangle_unitcircle_overlap(x3, y3, x1, y1, xp, yp) +
-		  triangle_unitcircle_overlap(x2, y2, x1, y1, xp, yp));
-	}
-      else if (pt5.x <= 1.)
-	{
-	  xp = 0.5 * (pt5.x + pt6.x);
-	  yp = 0.5 * (pt5.y + pt6.y);
-	  area = (triangle_unitcircle_overlap(x1, y1, x2, y2, xp, yp) +
-		  triangle_unitcircle_overlap(x3, y3, x2, y2, xp, yp));
-	}
-      else  /* no intersections */
-	{
-	  if (in_triangle(0., 0., x1, y1, x2, y2, x3, y3))
-	    return PI;
-	  else
-	    return 0.;
-	}
+  } else {
+    inter = circle_segment(x1, y1, x2, y2);
+    pt1 = inter.p1;
+    pt2 = inter.p2;
+    inter = circle_segment(x2, y2, x3, y3);
+    pt3 = inter.p1;
+    pt4 = inter.p2;
+    inter = circle_segment(x3, y3, x1, y1);
+    pt5 = inter.p1;
+    pt6 = inter.p2;
+    if (pt1.x <= 1.) {
+      xp = 0.5 * (pt1.x + pt2.x);
+      yp = 0.5 * (pt1.y + pt2.y);
+      area =
+          (triangle_unitcircle_overlap(x1, y1, x3, y3, xp, yp)
+           + triangle_unitcircle_overlap(x2, y2, x3, y3, xp, yp));
+    } else if (pt3.x <= 1.) {
+      xp = 0.5 * (pt3.x + pt4.x);
+      yp = 0.5 * (pt3.y + pt4.y);
+      area =
+          (triangle_unitcircle_overlap(x3, y3, x1, y1, xp, yp)
+           + triangle_unitcircle_overlap(x2, y2, x1, y1, xp, yp));
+    } else if (pt5.x <= 1.) {
+      xp = 0.5 * (pt5.x + pt6.x);
+      yp = 0.5 * (pt5.y + pt6.y);
+      area =
+          (triangle_unitcircle_overlap(x1, y1, x2, y2, xp, yp)
+           + triangle_unitcircle_overlap(x3, y3, x2, y2, xp, yp));
+    } else /* no intersections */ {
+      if (in_triangle(0., 0., x1, y1, x2, y2, x3, y3)) {
+        return PI;
+      } else {
+        return 0.;
+      }
     }
+  }
   return area;
 }
 
 /* exact overlap between a rectangle defined by (xmin, ymin, xmax,
    ymax) and an ellipse with major and minor axes rx and ry
    respectively and position angle theta. */
-static double ellipoverlap(double xmin, double ymin, double xmax, double ymax,
-			   double a, double b, double theta)
-{
+static double ellipoverlap(
+    double xmin, double ymin, double xmax, double ymax, double a, double b, double theta
+) {
   double cos_m_theta, sin_m_theta, scale;
   double x1, y1, x2, y2, x3, y3, x4, y4;
 
@@ -575,6 +538,7 @@ static double ellipoverlap(double xmin, double ymin, double xmax, double ymax,
 
   /* Divide resulting quadrilateral into two triangles and find
      intersection with unit circle */
-  return scale * (triangle_unitcircle_overlap(x1, y1, x2, y2, x3, y3) +
-		  triangle_unitcircle_overlap(x1, y1, x4, y4, x3, y3));
+  return scale
+         * (triangle_unitcircle_overlap(x1, y1, x2, y2, x3, y3)
+            + triangle_unitcircle_overlap(x1, y1, x4, y4, x3, y3));
 }
diff --git a/src/sep.h b/src/sep.h
index cb709c4..746e8e5 100644
--- a/src/sep.h
+++ b/src/sep.h
@@ -1,24 +1,27 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <stddef.h>
+#include <stdint.h>
 
 #ifdef _MSC_VER
 #define SEP_API __declspec(dllexport)
@@ -27,35 +30,35 @@
 #endif
 
 /* datatype codes */
-#define SEP_TBYTE        11  /* 8-bit unsigned byte */
-#define SEP_TINT         31  /* native int type */
-#define SEP_TFLOAT       42
-#define SEP_TDOUBLE      82
+#define SEP_TBYTE 11 /* 8-bit unsigned byte */
+#define SEP_TINT 31 /* native int type */
+#define SEP_TFLOAT 42
+#define SEP_TDOUBLE 82
 
 /* object & aperture flags */
-#define SEP_OBJ_MERGED       0x0001  /* object is result of deblending */
-#define SEP_OBJ_TRUNC        0x0002  /* object truncated at image boundary */
-#define SEP_OBJ_DOVERFLOW    0x0004  /* not currently used, but could be */
-#define SEP_OBJ_SINGU        0x0008  /* x,y fully correlated */
-#define SEP_APER_TRUNC       0x0010
-#define SEP_APER_HASMASKED   0x0020
-#define SEP_APER_ALLMASKED   0x0040
+#define SEP_OBJ_MERGED 0x0001 /* object is result of deblending */
+#define SEP_OBJ_TRUNC 0x0002 /* object truncated at image boundary */
+#define SEP_OBJ_DOVERFLOW 0x0004 /* not currently used, but could be */
+#define SEP_OBJ_SINGU 0x0008 /* x,y fully correlated */
+#define SEP_APER_TRUNC 0x0010
+#define SEP_APER_HASMASKED 0x0020
+#define SEP_APER_ALLMASKED 0x0040
 #define SEP_APER_NONPOSITIVE 0x0080
 
 /* noise_type values in sep_image */
-#define SEP_NOISE_NONE   0
+#define SEP_NOISE_NONE 0
 #define SEP_NOISE_STDDEV 1
-#define SEP_NOISE_VAR    2
+#define SEP_NOISE_VAR 2
 
 /* input flags for aperture photometry */
-#define SEP_MASK_IGNORE      0x0004
+#define SEP_MASK_IGNORE 0x0004
 
 /* threshold interpretation for sep_extract */
-#define SEP_THRESH_REL 0  /* in units of standard deviations (sigma) */
-#define SEP_THRESH_ABS 1  /* absolute data values */
+#define SEP_THRESH_REL 0 /* in units of standard deviations (sigma) */
+#define SEP_THRESH_ABS 1 /* absolute data values */
 
 /* filter types for sep_extract */
-#define SEP_FILTER_CONV    0
+#define SEP_FILTER_CONV 0
 #define SEP_FILTER_MATCHED 1
 
 /* structs ------------------------------------------------------------------*/
@@ -66,19 +69,22 @@
  * gain.
  */
 typedef struct {
-  const void *data;  /* data array                */
-  const void *noise; /* noise array (can be NULL) */
-  const void *mask;  /* mask array (can be NULL)  */
-  const void *segmap;/* segmap array (can be NULL)  */
-  int dtype;         /* element type of image     */
-  int ndtype;        /* element type of noise     */
-  int mdtype;        /* element type of mask      */
-  int sdtype;        /* element type of segmap    */
-  int w;             /* array width               */
-  int h;             /* array height              */
-  double noiseval;   /* scalar noise value; used only if noise == NULL */
-  short noise_type;  /* interpretation of noise value                  */
-  double gain;       /* (poisson counts / data unit)                   */
+  const void * data; /* data array                */
+  const void * noise; /* noise array (can be NULL) */
+  const void * mask; /* mask array (can be NULL)  */
+  const void * segmap; /* segmap array (can be NULL)  */
+  int dtype; /* element type of image     */
+  int ndtype; /* element type of noise     */
+  int mdtype; /* element type of mask      */
+  int sdtype; /* element type of segmap    */
+  int64_t * segids; /* unique ids in segmap */
+  int64_t * idcounts; /* counts of unique ids in segmap  */
+  int64_t numids; /* total number of unique ids in segmap */
+  int64_t w; /* array width               */
+  int64_t h; /* array height              */
+  double noiseval; /* scalar noise value; used only if noise == NULL */
+  short noise_type; /* interpretation of noise value                  */
+  double gain; /* (poisson counts / data unit)                   */
   double maskthresh; /* pixel considered masked if mask > maskthresh   */
 } sep_image;
 
@@ -88,16 +94,16 @@ typedef struct {
  * and its noise with splines.
  */
 typedef struct {
-  int w, h;          /* original image width, height */
-  int bw, bh;        /* single tile width, height */
-  int nx, ny;        /* number of tiles in x, y */
-  int n;             /* nx*ny */
-  float global;      /* global mean */
-  float globalrms;   /* global sigma */
-  float *back;       /* node data for interpolation */
-  float *dback;
-  float *sigma;
-  float *dsigma;
+  int64_t w, h; /* original image width, height */
+  int64_t bw, bh; /* single tile width, height */
+  int64_t nx, ny; /* number of tiles in x, y */
+  int64_t n; /* nx*ny */
+  float global; /* global mean */
+  float globalrms; /* global sigma */
+  float * back; /* node data for interpolation */
+  float * dback;
+  float * sigma;
+  float * dsigma;
 } sep_bkg;
 
 /* sep_catalog
@@ -106,28 +112,28 @@ typedef struct {
  * one entry per detected object.
  */
 typedef struct {
-  int    nobj;                 /* number of objects (length of all arrays) */
-  float	 *thresh;              /* threshold (ADU)                          */
-  int	 *npix;                 /* # pixels extracted (size of pix array)   */
-  int    *tnpix;                /* # pixels above thresh (unconvolved)      */
-  int	 *xmin, *xmax;
-  int    *ymin, *ymax;
-  double *x, *y;                 /* barycenter (first moments)               */
-  double *x2, *y2, *xy;		 /* second moments                           */
-  double *errx2, *erry2, *errxy;      /* second moment errors            */
-  float	 *a, *b, *theta;    /* ellipse parameters                       */
-  float	 *cxx, *cyy, *cxy;  /* ellipse parameters (alternative)         */
-  float	 *cflux;                /* total flux of pixels (convolved im)      */
-  float	 *flux;      		 /* total flux of pixels (unconvolved)       */
-  float  *cpeak;                /* peak intensity (ADU) (convolved)         */
-  float  *peak;                 /* peak intensity (ADU) (unconvolved)       */
-  int    *xcpeak, *ycpeak;       /* x, y coords of peak (convolved) pixel    */
-  int    *xpeak, *ypeak;         /* x, y coords of peak (unconvolved) pixel  */
-  short	 *flag;                 /* extraction flags                         */
-  int    **pix;             /* array giving indicies of object's pixels in   */
-                            /* image (linearly indexed). Length is `npix`.  */
-                            /* (pointer to within the `objectspix` buffer)  */
-  int    *objectspix;      /* buffer holding pixel indicies for all objects */
+  int nobj; /* number of objects (length of all arrays) */
+  float * thresh; /* threshold (ADU)                          */
+  int64_t * npix; /* # pixels extracted (size of pix array)   */
+  int64_t * tnpix; /* # pixels above thresh (unconvolved)      */
+  int64_t *xmin, *xmax;
+  int64_t *ymin, *ymax;
+  double *x, *y; /* barycenter (first moments)               */
+  double *x2, *y2, *xy; /* second moments                           */
+  double *errx2, *erry2, *errxy; /* second moment errors            */
+  float *a, *b, *theta; /* ellipse parameters                       */
+  float *cxx, *cyy, *cxy; /* ellipse parameters (alternative)         */
+  float * cflux; /* total flux of pixels (convolved im)      */
+  float * flux; /* total flux of pixels (unconvolved)       */
+  float * cpeak; /* peak intensity (ADU) (convolved)         */
+  float * peak; /* peak intensity (ADU) (unconvolved)       */
+  int64_t *xcpeak, *ycpeak; /* x, y coords of peak (convolved) pixel    */
+  int64_t *xpeak, *ypeak; /* x, y coords of peak (unconvolved) pixel  */
+  short * flag; /* extraction flags                         */
+  int64_t ** pix; /* array giving indicies of object's pixels in   */
+  /* image (linearly indexed). Length is `npix`.  */
+  /* (pointer to within the `objectspix` buffer)  */
+  int64_t * objectspix; /* buffer holding pixel indicies for all objects */
 } sep_catalog;
 
 
@@ -149,19 +155,23 @@ typedef struct {
  * - fw, fh = (3, 3)
  * - fthresh = 0.0
  */
-SEP_API int sep_background(const sep_image *image,
-                   int bw, int bh,   /* size of a single background tile */
-                   int fw, int fh,   /* filter size in tiles             */
-                   double fthresh,   /* filter threshold                 */
-                   sep_bkg **bkg);   /* OUTPUT                           */
+SEP_API int sep_background(
+    const sep_image * image,
+    int64_t bw,
+    int64_t bh, /* size of a single background tile */
+    int64_t fw,
+    int64_t fh, /* filter size in tiles             */
+    double fthresh, /* filter threshold                 */
+    sep_bkg ** bkg
+); /* OUTPUT                           */
 
 
 /* sep_bkg_global[rms]()
  *
  * Get the estimate of the global background "median" or standard deviation.
  */
-SEP_API float sep_bkg_global(const sep_bkg *bkg);
-SEP_API float sep_bkg_globalrms(const sep_bkg *bkg);
+SEP_API float sep_bkg_global(const sep_bkg * bkg);
+SEP_API float sep_bkg_globalrms(const sep_bkg * bkg);
 
 
 /* sep_bkg_pix()
@@ -169,7 +179,7 @@ SEP_API float sep_bkg_globalrms(const sep_bkg *bkg);
  * Return background at (x, y).
  * Unlike other routines, this uses simple linear interpolation.
  */
-SEP_API float sep_bkg_pix(const sep_bkg *bkg, int x, int y);
+SEP_API float sep_bkg_pix(const sep_bkg * bkg, int64_t x, int64_t y);
 
 
 /* sep_bkg_[sub,rms]line()
@@ -179,9 +189,9 @@ SEP_API float sep_bkg_pix(const sep_bkg *bkg, int x, int y);
  * The second function subtracts the background from the input array.
  * Line must be an array with same width as original image.
  */
-SEP_API int sep_bkg_line(const sep_bkg *bkg, int y, void *line, int dtype);
-SEP_API int sep_bkg_subline(const sep_bkg *bkg, int y, void *line, int dtype);
-SEP_API int sep_bkg_rmsline(const sep_bkg *bkg, int y, void *line, int dtype);
+SEP_API int sep_bkg_line(const sep_bkg * bkg, int64_t y, void * line, int dtype);
+SEP_API int sep_bkg_subline(const sep_bkg * bkg, int64_t y, void * line, int dtype);
+SEP_API int sep_bkg_rmsline(const sep_bkg * bkg, int64_t y, void * line, int dtype);
 
 
 /* sep_bkg_[sub,rms]array()
@@ -191,15 +201,15 @@ SEP_API int sep_bkg_rmsline(const sep_bkg *bkg, int y, void *line, int dtype);
  * The second function subtracts the background from the input array.
  * `arr` must be an array of the same size as original image.
  */
-SEP_API int sep_bkg_array(const sep_bkg *bkg, void *arr, int dtype);
-SEP_API int sep_bkg_subarray(const sep_bkg *bkg, void *arr, int dtype);
-SEP_API int sep_bkg_rmsarray(const sep_bkg *bkg, void *arr, int dtype);
+SEP_API int sep_bkg_array(const sep_bkg * bkg, void * arr, int dtype);
+SEP_API int sep_bkg_subarray(const sep_bkg * bkg, void * arr, int dtype);
+SEP_API int sep_bkg_rmsarray(const sep_bkg * bkg, void * arr, int dtype);
 
 /* sep_bkg_free()
  *
  * Free memory associated with bkg.
  */
-SEP_API void sep_bkg_free(sep_bkg *bkg);
+SEP_API void sep_bkg_free(sep_bkg * bkg);
 
 /*-------------------------- source extraction ------------------------------*/
 
@@ -218,20 +228,22 @@ SEP_API void sep_bkg_free(sep_bkg *bkg);
  * (the absolute threshold will be thresh*noise[i,j]).
  *
  */
-SEP_API int sep_extract(const sep_image *image,
-		float thresh,         /* detection threshold           [1.5] */
-                int thresh_type,      /* threshold units    [SEP_THRESH_REL] */
-		int minarea,          /* minimum area in pixels          [5] */
-		const float *conv,    /* convolution array (can be NULL)     */
-                                      /*               [{1 2 1 2 4 2 1 2 1}] */
-		int convw, int convh, /* w, h of convolution array     [3,3] */
-                int filter_type,      /* convolution (0) or matched (1)  [0] */
-		int deblend_nthresh,  /* deblending thresholds          [32] */
-		double deblend_cont,  /* min. deblending contrast    [0.005] */
-		int clean_flag,       /* perform cleaning?               [1] */
-		double clean_param,   /* clean parameter               [1.0] */
-                sep_catalog **catalog); /* OUTPUT catalog                    */
-
+SEP_API int sep_extract(
+    const sep_image * image,
+    float thresh, /* detection threshold           [1.5] */
+    int thresh_type, /* threshold units    [SEP_THRESH_REL] */
+    int minarea, /* minimum area in pixels          [5] */
+    const float * conv, /* convolution array (can be NULL)     */
+    /*               [{1 2 1 2 4 2 1 2 1}] */
+    int64_t convw,
+    int64_t convh, /* w, h of convolution array     [3,3] */
+    int filter_type, /* convolution (0) or matched (1)  [0] */
+    int deblend_nthresh, /* deblending thresholds          [32] */
+    double deblend_cont, /* min. deblending contrast    [0.005] */
+    int clean_flag, /* perform cleaning?               [1] */
+    double clean_param, /* clean parameter               [1.0] */
+    sep_catalog ** catalog
+); /* OUTPUT catalog                    */
 
 
 /* set and get the size of the pixel stack used in extract() */
@@ -243,7 +255,7 @@ SEP_API void sep_set_sub_object_limit(int val);
 SEP_API int sep_get_sub_object_limit(void);
 
 /* free memory associated with a catalog */
-SEP_API void sep_catalog_free(sep_catalog *catalog);
+SEP_API void sep_catalog_free(sep_catalog * catalog);
 
 /*-------------------------- aperture photometry ----------------------------*/
 
@@ -264,33 +276,70 @@ SEP_API void sep_catalog_free(sep_catalog *catalog);
  *        corrected. The area can differ from the exact area of a circle due
  *        to inexact subpixel sampling and intersection with array boundaries.
  */
-SEP_API int sep_sum_circle(const sep_image *image,
-		   double x,          /* center of aperture in x */
-		   double y,          /* center of aperture in y */
-		   double r,          /* radius of aperture */
-		   int id,            /* optional id to test against segmap array */
-		   int subpix,        /* subpixel sampling */
-		   short inflags,     /* input flags (see below) */
-		   double *sum,       /* OUTPUT: sum */
-		   double *sumerr,    /* OUTPUT: error on sum */
-		   double *area,      /* OUTPUT: area included in sum */
-		   short *flag);      /* OUTPUT: flags */
-
-
-SEP_API int sep_sum_circann(const sep_image *image,
-                    double x, double y, double rin, double rout,
-                    int id, int subpix, short inflags,
-		    double *sum, double *sumerr, double *area, short *flag);
-
-SEP_API int sep_sum_ellipse(const sep_image *image,
-		    double x, double y, double a, double b, double theta,
-		    double r, int id, int subpix, short inflags,
-		    double *sum, double *sumerr, double *area, short *flag);
-
-SEP_API int sep_sum_ellipann(const sep_image *image,
-		     double x, double y, double a, double b, double theta,
-		     double rin, double rout, int id, int subpix, short inflags,
-		     double *sum, double *sumerr, double *area, short *flag);
+SEP_API int sep_sum_circle(
+    const sep_image * image,
+    double x, /* center of aperture in x */
+    double y, /* center of aperture in y */
+    double r, /* radius of aperture */
+    int id, /* optional id to test against segmap array */
+    int subpix, /* subpixel sampling */
+    short inflags, /* input flags (see below) */
+    double * sum, /* OUTPUT: sum */
+    double * sumerr, /* OUTPUT: error on sum */
+    double * area, /* OUTPUT: area included in sum */
+    short * flag
+); /* OUTPUT: flags */
+
+
+SEP_API int sep_sum_circann(
+    const sep_image * image,
+    double x,
+    double y,
+    double rin,
+    double rout,
+    int id,
+    int subpix,
+    short inflags,
+    double * sum,
+    double * sumerr,
+    double * area,
+    short * flag
+);
+
+SEP_API int sep_sum_ellipse(
+    const sep_image * image,
+    double x,
+    double y,
+    double a,
+    double b,
+    double theta,
+    double r,
+    int id,
+    int subpix,
+    short inflags,
+    double * sum,
+    double * sumerr,
+    double * area,
+    short * flag
+);
+
+SEP_API int sep_sum_ellipann(
+    const sep_image * image,
+    double x,
+    double y,
+    double a,
+    double b,
+    double theta,
+    double rin,
+    double rout,
+    int id,
+    int subpix,
+    short inflags,
+    double * sum,
+    double * sumerr,
+    double * area,
+    short * flag
+);
 
 /* sep_sum_circann_multi()
  *
@@ -308,11 +357,21 @@ SEP_API int sep_sum_ellipann(const sep_image *image,
              annulus (if mask not NULL).
  * flag:     Output flag (non-array).
  */
-SEP_API int sep_sum_circann_multi(const sep_image *im,
-			  double x, double y, double rmax, int n, int id, int subpix,
-                          short inflag,
-			  double *sum, double *sumvar, double *area,
-			  double *maskarea, short *flag);
+SEP_API int sep_sum_circann_multi(
+    const sep_image * im,
+    double x,
+    double y,
+    double rmax,
+    int64_t n,
+    int id,
+    int subpix,
+    short inflag,
+    double * sum,
+    double * sumvar,
+    double * area,
+    double * maskarea,
+    short * flag
+);
 
 /* sep_flux_radius()
  *
@@ -328,10 +387,20 @@ SEP_API int sep_sum_circann_multi(const sep_image *im,
  * r : (output) result array of length n.
  * flag : (output) scalar flag
  */
-SEP_API int sep_flux_radius(const sep_image *im,
-		    double x, double y, double rmax, int id, int subpix, short inflag,
-		    const double *fluxtot, const double *fluxfrac, int n,
-		    double *r, short *flag);
+SEP_API int sep_flux_radius(
+    const sep_image * im,
+    double x,
+    double y,
+    double rmax,
+    int id,
+    int subpix,
+    short inflag,
+    const double * fluxtot,
+    const double * fluxfrac,
+    int64_t n,
+    double * r,
+    short * flag
+);
 
 /* sep_kron_radius()
  *
@@ -349,9 +418,18 @@ SEP_API int sep_flux_radius(const sep_image *im,
  * SEP_APER_NONPOSITIVE - There was a nonpositive numerator or deminator.
  *                        kronrad = 0.
  */
-SEP_API int sep_kron_radius(const sep_image *im, double x, double y,
-		    double cxx, double cyy, double cxy, double r, int id,
-		    double *kronrad, short *flag);
+SEP_API int sep_kron_radius(
+    const sep_image * im,
+    double x,
+    double y,
+    double cxx,
+    double cyy,
+    double cxy,
+    double r,
+    int id,
+    double * kronrad,
+    short * flag
+);
 
 
 /* sep_windowed()
@@ -366,9 +444,18 @@ SEP_API int sep_kron_radius(const sep_image *im, double x, double y,
  * xout, yout : output center.
  * niter      : number of iterations used.
  */
-SEP_API int sep_windowed(const sep_image *im,
-                 double x, double y, double sig, int subpix, short inflag,
-                 double *xout, double *yout, int *niter, short *flag);
+SEP_API int sep_windowed(
+    const sep_image * im,
+    double x,
+    double y,
+    double sig,
+    int subpix,
+    short inflag,
+    double * xout,
+    double * yout,
+    int * niter,
+    short * flag
+);
 
 
 /* sep_set_ellipse()
@@ -377,9 +464,18 @@ SEP_API int sep_windowed(const sep_image *im,
  *
  * Ellipse: cxx*(x'-x)^2 + cyy*(y'-y)^2 + cxy*(x'-x)*(y'-y) = r^2
  */
-SEP_API void sep_set_ellipse(unsigned char *arr, int w, int h,
-		     double x, double y, double cxx, double cyy, double cxy,
-		     double r, unsigned char val);
+SEP_API void sep_set_ellipse(
+    unsigned char * arr,
+    int64_t w,
+    int64_t h,
+    double x,
+    double y,
+    double cxx,
+    double cyy,
+    double cxy,
+    double r,
+    unsigned char val
+);
 
 
 /* sep_ellipse_axes()
@@ -394,15 +490,17 @@ SEP_API void sep_set_ellipse(unsigned char *arr, int w, int h,
  * b = semiminor axis
  * theta = angle in radians counter-clockwise from positive x axis
  */
-SEP_API int sep_ellipse_axes(double cxx, double cyy, double cxy,
-		     double *a, double *b, double *theta);
-SEP_API void sep_ellipse_coeffs(double a, double b, double theta,
-			double *cxx, double *cyy, double *cxy);
+SEP_API int sep_ellipse_axes(
+    double cxx, double cyy, double cxy, double * a, double * b, double * theta
+);
+SEP_API void sep_ellipse_coeffs(
+    double a, double b, double theta, double * cxx, double * cyy, double * cxy
+);
 
 /*----------------------- info & error messaging ----------------------------*/
 
 /* sep_version_string : library version (e.g., "0.2.0") */
-SEP_API extern const char *const sep_version_string;
+SEP_API extern const char * const sep_version_string;
 
 /* sep_get_errmsg()
  *
@@ -410,7 +508,7 @@ SEP_API extern const char *const sep_version_string;
  * error status value.  The message may be up to 60 characters long, plus
  * the terminating null character.
  */
-SEP_API void sep_get_errmsg(int status, char *errtext);
+SEP_API void sep_get_errmsg(int status, char * errtext);
 
 
 /* sep_get_errdetail()
@@ -418,4 +516,4 @@ SEP_API void sep_get_errmsg(int status, char *errtext);
  * Return a longer error message with more specifics about the problem.
  * The message may be up to 512 characters.
  */
-SEP_API void sep_get_errdetail(char *errtext);
+SEP_API void sep_get_errdetail(char * errtext);
diff --git a/src/sepcore.h b/src/sepcore.h
index f8a7396..aaf853d 100644
--- a/src/sepcore.h
+++ b/src/sepcore.h
@@ -1,91 +1,104 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-* SEP is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* SEP is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with SEP.  If not, see <http://www.gnu.org/licenses/>.
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+ *
+ * This file is part of SEP
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ * SEP is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SEP is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with SEP.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define	RETURN_OK           0  /* must be zero */
-#define MEMORY_ALLOC_ERROR  1
-#define PIXSTACK_FULL       2
-#define ILLEGAL_DTYPE       3
-#define ILLEGAL_SUBPIX      4
-#define NON_ELLIPSE_PARAMS  5
+#include <stdint.h>
+
+#define RETURN_OK 0 /* must be zero */
+#define MEMORY_ALLOC_ERROR 1
+#define PIXSTACK_FULL 2
+#define ILLEGAL_DTYPE 3
+#define ILLEGAL_SUBPIX 4
+#define NON_ELLIPSE_PARAMS 5
 #define ILLEGAL_APER_PARAMS 6
-#define DEBLEND_OVERFLOW    7
-#define LINE_NOT_IN_BUF     8
-#define RELTHRESH_NO_NOISE  9
-#define UNKNOWN_NOISE_TYPE  10
+#define DEBLEND_OVERFLOW 7
+#define LINE_NOT_IN_BUF 8
+#define RELTHRESH_NO_NOISE 9
+#define UNKNOWN_NOISE_TYPE 10
 
-#define	BIG 1e+30  /* a huge number (< biggest value a float can store) */
-#define	PI  M_PI
-#define	DEG (PI/180.0)	    /* 1 deg in radians */
+#define BIG 1e+30 /* a huge number (< biggest value a float can store) */
+#define PI M_PI
+#define DEG (PI / 180.0) /* 1 deg in radians */
 
-typedef	int	      LONG;
-typedef	unsigned int  ULONG;
-typedef	unsigned char BYTE;    /* a byte */
+typedef int LONG;
+typedef unsigned int ULONG;
+typedef unsigned char BYTE; /* a byte */
 
 /* keep these synchronized */
-typedef float         PIXTYPE;    /* type used inside of functions */
-#define PIXDTYPE      SEP_TFLOAT  /* dtype code corresponding to PIXTYPE */
+typedef float PIXTYPE; /* type used inside of functions */
+#define PIXDTYPE SEP_TFLOAT /* dtype code corresponding to PIXTYPE */
 
 
 /* signature of converters */
-typedef PIXTYPE (*converter)(const void *ptr);
-typedef void (*array_converter)(const void *ptr, int n, PIXTYPE *target);
-typedef void (*array_writer)(const float *ptr, int n, void *target);
+typedef PIXTYPE (*converter)(const void * ptr);
+typedef void (*array_converter)(const void * ptr, int64_t n, PIXTYPE * target);
+typedef void (*array_writer)(const float * ptr, int64_t n, void * target);
 
-#define	QCALLOC(ptr, typ, nel, status)				     	\
-  {if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ))))		\
-      {									\
-	char errtext[160];						\
-	sprintf(errtext, #ptr " (" #nel "=%lu elements) "		\
-		"at line %d in module " __FILE__ " !",			\
-		(size_t)(nel)*sizeof(typ), __LINE__);			\
-	put_errdetail(errtext);						\
-	status = MEMORY_ALLOC_ERROR;					\
-	goto exit;							\
-      };								\
+#define QCALLOC(ptr, typ, nel, status)                        \
+  {                                                           \
+    if (!(ptr = (typ *)calloc((size_t)(nel), sizeof(typ)))) { \
+      char errtext[160];                                      \
+      sprintf(                                                \
+          errtext,                                            \
+          #ptr " (" #nel                                      \
+               "=%lu elements) "                              \
+               "at line %d in module " __FILE__ " !",         \
+          (size_t)(nel) * sizeof(typ),                        \
+          __LINE__                                            \
+      );                                                      \
+      put_errdetail(errtext);                                 \
+      status = MEMORY_ALLOC_ERROR;                            \
+      goto exit;                                              \
+    };                                                        \
   }
 
-#define	QMALLOC(ptr, typ, nel, status)					\
-  {if (!(ptr = malloc((size_t)(nel)*sizeof(typ))))		\
-      {									\
-	char errtext[160];						\
-	sprintf(errtext, #ptr " (" #nel "=%lu elements) "		\
-		"at line %d in module " __FILE__ " !",			\
-		(size_t)(nel)*sizeof(typ), __LINE__);			\
-	put_errdetail(errtext);						\
-	status = MEMORY_ALLOC_ERROR;					\
-	goto exit;							\
-      };								\
+#define QMALLOC(ptr, typ, nel, status)                  \
+  {                                                     \
+    if (!(ptr = malloc((size_t)(nel) * sizeof(typ)))) { \
+      char errtext[160];                                \
+      sprintf(                                          \
+          errtext,                                      \
+          #ptr " (" #nel                                \
+               "=%lu elements) "                        \
+               "at line %d in module " __FILE__ " !",   \
+          (size_t)(nel) * sizeof(typ),                  \
+          __LINE__                                      \
+      );                                                \
+      put_errdetail(errtext);                           \
+      status = MEMORY_ALLOC_ERROR;                      \
+      goto exit;                                        \
+    };                                                  \
   }
 
-float fqmedian(float *ra, int n);
-void put_errdetail(const char *errtext);
+float fqmedian(float * ra, int64_t n);
+void put_errdetail(const char * errtext);
 
-int get_converter(int dtype, converter *f, int *size);
-int get_array_converter(int dtype, array_converter *f, int *size);
-int get_array_writer(int dtype, array_writer *f, int *size);
-int get_array_subtractor(int dtype, array_writer *f, int *size);
+int get_converter(int dtype, converter * f, int64_t * size);
+int get_array_converter(int dtype, array_converter * f, int64_t * size);
+int get_array_writer(int dtype, array_writer * f, int64_t * size);
+int get_array_subtractor(int dtype, array_writer * f, int64_t * size);
 
 #if defined(_MSC_VER)
 #define _Thread_local __declspec(thread)
-#define _Atomic // this isn't great, but we only use atomic for global settings
-#define rand_r(SEED) rand() // MSVC doesn't provide rand_r, but makes rand safe for re-entrancy
+#define _Atomic  // this isn't great, but we only use atomic for global settings
+#define rand_r(SEED) \
+  rand()  // MSVC doesn't provide rand_r, but makes rand safe for re-entrancy
 #endif
diff --git a/src/util.c b/src/util.c
index 9f49852..8ae8990 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,152 +1,132 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*
-* This file is part of SEP
-*
-* All content except array comparison functions fqcmp() and fqmedian() is
-* distributed under an MIT license.
-*
-* Copyright 2014 SEP developers
-*
-* Array comparison functions fqcmp() and fqmedian() are distributed under an
-* LGPL license:
-*
-* Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
-* Copyright 2014 SEP developers
-*
-*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include <math.h>
+ *
+ * This file is part of SEP
+ *
+ * All content except array comparison functions fqcmp() and fqmedian() is
+ * distributed under an MIT license.
+ *
+ * Copyright 2014 SEP developers
+ *
+ * Array comparison functions fqcmp() and fqmedian() are distributed under an
+ * LGPL license:
+ *
+ * Copyright 1993-2011 Emmanuel Bertin -- IAP/CNRS/UPMC
+ * Copyright 2014 SEP developers
+ *
+ *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
 #include "sep.h"
 #include "sepcore.h"
 
 #define DETAILSIZE 512
 
-const char *const sep_version_string = "1.2.0";
+#ifndef SEP_VERSION_STRING
+#define SEP_VERSION_STRING "1.3.6"
+#endif
+const char * const sep_version_string = SEP_VERSION_STRING;
 static _Thread_local char _errdetail_buffer[DETAILSIZE] = "";
 
 /****************************************************************************/
 /* data type conversion mechanics for runtime type conversion */
 
-PIXTYPE convert_dbl(const void *ptr)
-{
+PIXTYPE convert_dbl(const void * ptr) {
   return *(const double *)ptr;
 }
 
-PIXTYPE convert_flt(const void *ptr)
-{
+PIXTYPE convert_flt(const void * ptr) {
   return *(const float *)ptr;
 }
 
-PIXTYPE convert_int(const void *ptr)
-{
+PIXTYPE convert_int(const void * ptr) {
   return *(const int *)ptr;
 }
 
-PIXTYPE convert_byt(const void *ptr)
-{
+PIXTYPE convert_byt(const void * ptr) {
   return *(const BYTE *)ptr;
 }
 
 /* return the correct converter depending on the datatype code */
-int get_converter(int dtype, converter *f, int *size)
-{
+int get_converter(int dtype, converter * f, int64_t * size) {
   int status = RETURN_OK;
 
-  if (dtype == SEP_TFLOAT)
-    {
-      *f = convert_flt;
-      *size = sizeof(float);
-    }
-  else if (dtype == SEP_TINT)
-    {
-      *f = convert_int;
-      *size = sizeof(int);
-    }
-  else if (dtype == SEP_TDOUBLE)
-    {
-      *f = convert_dbl;
-      *size = sizeof(double);
-    }
-  else if (dtype == SEP_TBYTE)
-    {
-      *f = convert_byt;
-      *size = sizeof(BYTE);
-    }
-  else
-    {
-      *f = NULL;
-      *size = 0;
-      status = ILLEGAL_DTYPE;
-    }
+  if (dtype == SEP_TFLOAT) {
+    *f = convert_flt;
+    *size = sizeof(float);
+  } else if (dtype == SEP_TINT) {
+    *f = convert_int;
+    *size = sizeof(int);
+  } else if (dtype == SEP_TDOUBLE) {
+    *f = convert_dbl;
+    *size = sizeof(double);
+  } else if (dtype == SEP_TBYTE) {
+    *f = convert_byt;
+    *size = sizeof(BYTE);
+  } else {
+    *f = NULL;
+    *size = 0;
+    status = ILLEGAL_DTYPE;
+  }
   return status;
 }
 
 /* array conversions */
-void convert_array_flt(const void *ptr, int n, PIXTYPE *target)
-{
-  const float *source = ptr;
-  int i;
-  for (i=0; i<n; i++, source++)
+void convert_array_flt(const void * ptr, int64_t n, PIXTYPE * target) {
+  const float * source = ptr;
+  int64_t i;
+  for (i = 0; i < n; i++, source++) {
     target[i] = *source;
+  }
 }
 
-void convert_array_dbl(const void *ptr, int n, PIXTYPE *target)
-{
-  const double *source = ptr;
-  int i;
-  for (i=0; i<n; i++, source++)
+void convert_array_dbl(const void * ptr, int64_t n, PIXTYPE * target) {
+  const double * source = ptr;
+  int64_t i;
+  for (i = 0; i < n; i++, source++) {
     target[i] = *source;
+  }
 }
 
-void convert_array_int(const void *ptr, int n, PIXTYPE *target)
-{
-  const int *source = ptr;
-  int i;
-  for (i=0; i<n; i++, source++)
+void convert_array_int(const void * ptr, int64_t n, PIXTYPE * target) {
+  const int * source = ptr;
+  int64_t i;
+  for (i = 0; i < n; i++, source++) {
     target[i] = *source;
+  }
 }
 
-void convert_array_byt(const void *ptr, int n, PIXTYPE *target)
-{
-  const BYTE *source = ptr;
-  int i;
-  for (i=0; i<n; i++, source++)
+void convert_array_byt(const void * ptr, int64_t n, PIXTYPE * target) {
+  const BYTE * source = ptr;
+  int64_t i;
+  for (i = 0; i < n; i++, source++) {
     target[i] = *source;
+  }
 }
 
-int get_array_converter(int dtype, array_converter *f, int *size)
-{
+int get_array_converter(int dtype, array_converter * f, int64_t * size) {
   int status = RETURN_OK;
 
-  if (dtype == SEP_TFLOAT)
-    {
-      *f = convert_array_flt;
-      *size = sizeof(float);
-    }
-  else if (dtype == SEP_TBYTE)
-    {
-      *f = convert_array_byt;
-      *size = sizeof(BYTE);
-    }
-  else if (dtype == SEP_TINT)
-    {
-      *f = convert_array_int;
-      *size = sizeof(int);
-    }
-  else if (dtype == SEP_TDOUBLE)
-    {
-      *f = convert_array_dbl;
-      *size = sizeof(double);
-    }
-  else
-    {
-      *f = NULL;
-      *size = 0;
-      status = ILLEGAL_DTYPE;
-    }
+  if (dtype == SEP_TFLOAT) {
+    *f = convert_array_flt;
+    *size = sizeof(float);
+  } else if (dtype == SEP_TBYTE) {
+    *f = convert_array_byt;
+    *size = sizeof(BYTE);
+  } else if (dtype == SEP_TINT) {
+    *f = convert_array_int;
+    *size = sizeof(int);
+  } else if (dtype == SEP_TDOUBLE) {
+    *f = convert_array_dbl;
+    *size = sizeof(double);
+  } else {
+    *f = NULL;
+    *size = 0;
+    status = ILLEGAL_DTYPE;
+  }
   return status;
 }
 
@@ -154,186 +134,169 @@ int get_array_converter(int dtype, array_converter *f, int *size)
 /****************************************************************************/
 /* Copy a float array to various sorts of arrays */
 
-void write_array_dbl(const float *ptr, int n, void *target)
-{
-  double *t = target;
-  int i;
-  for (i=0; i<n; i++, ptr++)
+void write_array_dbl(const float * ptr, int64_t n, void * target) {
+  double * t = target;
+  int64_t i;
+  for (i = 0; i < n; i++, ptr++) {
     t[i] = (double)(*ptr);
+  }
 }
 
-void write_array_int(const float *ptr, int n, void *target)
-{
-  int *t = target;
-  int i;
-  for (i=0; i<n; i++, ptr++)
-    t[i] = (int)(*ptr+0.5);
+void write_array_int(const float * ptr, int64_t n, void * target) {
+  int * t = target;
+  int64_t i;
+  for (i = 0; i < n; i++, ptr++) {
+    t[i] = (int)(*ptr + 0.5);
+  }
 }
 
 /* return the correct writer depending on the datatype code */
-int get_array_writer(int dtype, array_writer *f, int *size)
-{
+int get_array_writer(int dtype, array_writer * f, int64_t * size) {
   int status = RETURN_OK;
 
-  if (dtype == SEP_TINT)
-    {
-      *f = write_array_int;
-      *size = sizeof(int);
-    }
-  else if (dtype == SEP_TDOUBLE)
-    {
-      *f = write_array_dbl;
-      *size = sizeof(double);
-    }
-  else
-    {
-      *f = NULL;
-      *size = 0;
-      status = ILLEGAL_DTYPE;
-    }
+  if (dtype == SEP_TINT) {
+    *f = write_array_int;
+    *size = sizeof(int);
+  } else if (dtype == SEP_TDOUBLE) {
+    *f = write_array_dbl;
+    *size = sizeof(double);
+  } else {
+    *f = NULL;
+    *size = 0;
+    status = ILLEGAL_DTYPE;
+  }
   return status;
 }
 
 /* subtract a float array from arrays of various types */
 
-void subtract_array_dbl(const float *ptr, int n, void *target)
-{
-  double *t = target;
-  int i;
-  for (i=0; i<n; i++, ptr++)
+void subtract_array_dbl(const float * ptr, int64_t n, void * target) {
+  double * t = target;
+  int64_t i;
+  for (i = 0; i < n; i++, ptr++) {
     t[i] -= (double)(*ptr);
+  }
 }
 
-void subtract_array_flt(const float *ptr, int n, void *target)
-{
-  float *t = target;
-  int i;
-  for (i=0; i<n; i++, ptr++)
+void subtract_array_flt(const float * ptr, int64_t n, void * target) {
+  float * t = target;
+  int64_t i;
+  for (i = 0; i < n; i++, ptr++) {
     t[i] -= *ptr;
+  }
 }
 
-void subtract_array_int(const float *ptr, int n, void *target)
-{
-  int *t = target;
-  int i;
-  for (i=0; i<n; i++, ptr++)
-    t[i] -= (int)(*ptr+0.5);
+void subtract_array_int(const float * ptr, int64_t n, void * target) {
+  int * t = target;
+  int64_t i;
+  for (i = 0; i < n; i++, ptr++) {
+    t[i] -= (int)(*ptr + 0.5);
+  }
 }
 
 /* return the correct subtractor depending on the datatype code */
-int get_array_subtractor(int dtype, array_writer *f, int *size)
-{
+int get_array_subtractor(int dtype, array_writer * f, int64_t * size) {
   int status = RETURN_OK;
   char errtext[80];
 
-  if (dtype == SEP_TFLOAT)
-    {
-      *f = subtract_array_flt;
-      *size = sizeof(float);
-    }
-  else if (dtype == SEP_TINT)
-    {
-      *f = subtract_array_int;
-      *size = sizeof(int);
-    }
-  else if (dtype == SEP_TDOUBLE)
-    {
-      *f = subtract_array_dbl;
-      *size = sizeof(double);
-    }
-  else
-    {
-      *f = NULL;
-      *size = 0;
-      status = ILLEGAL_DTYPE;
-      sprintf(errtext, "in get_array_subtractor(): %d", dtype);
-      put_errdetail(errtext);
-    }
+  if (dtype == SEP_TFLOAT) {
+    *f = subtract_array_flt;
+    *size = sizeof(float);
+  } else if (dtype == SEP_TINT) {
+    *f = subtract_array_int;
+    *size = sizeof(int);
+  } else if (dtype == SEP_TDOUBLE) {
+    *f = subtract_array_dbl;
+    *size = sizeof(double);
+  } else {
+    *f = NULL;
+    *size = 0;
+    status = ILLEGAL_DTYPE;
+    sprintf(errtext, "in get_array_subtractor(): %d", dtype);
+    put_errdetail(errtext);
+  }
   return status;
 }
 
 /*****************************************************************************/
 /* Error messaging */
 
-void sep_get_errmsg(int status, char *errtext)
+void sep_get_errmsg(int status, char * errtext)
 /* Return a short descriptive error message that corresponds to the input
  * error status value.  The message may be up to 60 characters long, plus
  * the terminating null character. */
 {
   errtext[0] = '\0';
-  switch (status)
-    {
-    case RETURN_OK:
-      strcpy(errtext, "OK - no error");
-      break;
-    case MEMORY_ALLOC_ERROR:
-      strcpy(errtext, "memory allocation");
-      break;
-    case PIXSTACK_FULL:
-      strcpy(errtext, "internal pixel buffer full");
-      break;
-    case DEBLEND_OVERFLOW:
-      strcpy(errtext, "object deblending overflow");
-      break;
-    case ILLEGAL_DTYPE:
-      strcpy(errtext, "dtype not recognized/unsupported");
-      break;
-    case ILLEGAL_SUBPIX:
-      strcpy(errtext, "subpix value must be nonnegative");
-      break;
-    case NON_ELLIPSE_PARAMS:
-      strcpy(errtext, "parameters do not describe ellipse");
-      break;
-    case ILLEGAL_APER_PARAMS:
-      strcpy(errtext, "invalid aperture parameters");
-      break;
-    case LINE_NOT_IN_BUF:
-      strcpy(errtext, "array line out of buffer");
-      break;
-   case RELTHRESH_NO_NOISE:
-      strcpy(errtext, "relative threshold but image has noise_type of NONE");
-      break;
-    case UNKNOWN_NOISE_TYPE:
-      strcpy(errtext, "image has unknown noise_type");
-      break;
-    default:
-       strcpy(errtext, "unknown error status");
-       break;
-    }
+  switch (status) {
+  case RETURN_OK:
+    strcpy(errtext, "OK - no error");
+    break;
+  case MEMORY_ALLOC_ERROR:
+    strcpy(errtext, "memory allocation");
+    break;
+  case PIXSTACK_FULL:
+    strcpy(errtext, "internal pixel buffer full");
+    break;
+  case DEBLEND_OVERFLOW:
+    strcpy(errtext, "object deblending overflow");
+    break;
+  case ILLEGAL_DTYPE:
+    strcpy(errtext, "dtype not recognized/unsupported");
+    break;
+  case ILLEGAL_SUBPIX:
+    strcpy(errtext, "subpix value must be nonnegative");
+    break;
+  case NON_ELLIPSE_PARAMS:
+    strcpy(errtext, "parameters do not describe ellipse");
+    break;
+  case ILLEGAL_APER_PARAMS:
+    strcpy(errtext, "invalid aperture parameters");
+    break;
+  case LINE_NOT_IN_BUF:
+    strcpy(errtext, "array line out of buffer");
+    break;
+  case RELTHRESH_NO_NOISE:
+    strcpy(errtext, "relative threshold but image has noise_type of NONE");
+    break;
+  case UNKNOWN_NOISE_TYPE:
+    strcpy(errtext, "image has unknown noise_type");
+    break;
+  default:
+    strcpy(errtext, "unknown error status");
+    break;
+  }
 }
 
-void sep_get_errdetail(char *errtext)
-{
+void sep_get_errdetail(char * errtext) {
   strcpy(errtext, _errdetail_buffer);
   memset(_errdetail_buffer, 0, DETAILSIZE);
 }
 
-void put_errdetail(const char *errtext)
-{
-   strcpy(_errdetail_buffer, errtext);
-
+void put_errdetail(const char * errtext) {
+  strcpy(_errdetail_buffer, errtext);
 }
 
 /*****************************************************************************/
 /* Array median */
 
-static int fqcmp(const void *p1, const void *p2)
+static int fqcmp(const void * p1, const void * p2)
 /* Sorting function for floats, used in fqmedian() below.
  * Return value is 1 if *p1>*p2, 0 if *p1==*p2, -1 otherwise */
 {
-  double f1=*((const float *)p1);
-  double f2=*((const float *)p2);
-  return f1>f2? 1 : (f1<f2? -1 : 0);
+  double f1 = *((const float *)p1);
+  double f2 = *((const float *)p2);
+  return f1 > f2 ? 1 : (f1 < f2 ? -1 : 0);
 }
 
-float fqmedian(float *ra, int n)
+float fqmedian(float * ra, int64_t n)
 /* Compute median of an array of floats.
  *
  * WARNING: input data are reordered! */
 {
   qsort(ra, n, sizeof(float), fqcmp);
-  if (n<2)
+  if (n < 2) {
     return *ra;
-  else
-    return n&1? ra[n/2] : (ra[n/2-1]+ra[n/2])/2.0;
+  } else {
+    return n & 1 ? ra[n / 2] : (ra[n / 2 - 1] + ra[n / 2]) / 2.0;
+  }
 }
diff --git a/tox.ini b/tox.ini
index 535aec1..d7322f7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,20 @@
 [tox]
-minversion = 3.3
-envlist = py3
+minversion = 4.0
+envlist = py-{linux,macos,windows}
 isolated_build = true
 
+[gh-actions:env]
+PLATFORM =
+    ubuntu-latest: linux
+    macos-latest: macos
+    windows-latest: windows
+
 [testenv]
 passenv = HOME
 deps = pytest
        astropy
-commands = pytest test.py
\ No newline at end of file
+allowlist_externals = make
+commands =
+       pytest test.py
+       linux: make test
+       macos: make test


Test patch:
diff --git a/ctest/compare.py b/ctest/compare.py
index aded581..d92b761 100755
--- a/ctest/compare.py
+++ b/ctest/compare.py
@@ -1,14 +1,31 @@
 #!/usr/bin/env python
 
+"""Compare the output from SEP against SExtractor."""
+
 from __future__ import print_function
 
 import sys
 
+
 def read_table(fname):
+    """
+    Read in a whitespace-separated table.
+
+    Parameters
+    ----------
+    fname : path-like
+        The filename of the table to be opened.
+
+    Returns
+    -------
+    List[List[int|float]]
+        A list of rows, each of which is a list of the values in that row.
+    """
     rows = []
-    for line in open(fname, 'r'):
+    for line in open(fname, "r"):
         l = line.strip()
-        if len(l) == 0 or l[0] == '#': continue
+        if len(l) == 0 or l[0] == "#":
+            continue
         items = l.split()
         typed_items = []
         for it in items:
@@ -19,12 +36,25 @@ def read_table(fname):
         rows.append(typed_items)
     return rows
 
+
 def fracdiff(x, y):
-    return abs((y - x) / max(y, x))
+    """
+    Return the fraction difference between two numbers.
 
+    Parameters
+    ----------
+    x, y : float
+        The numbers to be compared.
+
+    Returns
+    -------
+    float
+        The fractional difference.
+    """
+    return abs((y - x) / max(y, x))
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
 
     fname1, fname2 = sys.argv[1:3]
 
@@ -38,8 +68,8 @@ def fracdiff(x, y):
     assert len(ref) == len(sep)
 
     for i in range(len(ref)):
-        assert abs(ref[i][1] - sep[i][1] - 1.) < 1.e-3  # x coordinate
-        assert abs(ref[i][2] - sep[i][2] - 1.) < 1.e-3  # y coordinate
-        assert fracdiff(ref[i][12], sep[i][3]) < 2.e-4  # flux
+        assert abs(ref[i][1] - sep[i][1] - 1.0) < 1.0e-3  # x coordinate
+        assert abs(ref[i][2] - sep[i][2] - 1.0) < 1.0e-3  # y coordinate
+        assert fracdiff(ref[i][12], sep[i][3]) < 2.0e-4  # flux
 
     print("compare passed")
diff --git a/ctest/test_image.c b/ctest/test_image.c
index 0bd5d95..0969266 100644
--- a/ctest/test_image.c
+++ b/ctest/test_image.c
@@ -1,59 +1,59 @@
+#include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h>
 #include <string.h>
-#include <math.h>
 #include <sys/time.h>
+
 #include "sep.h"
 
-uint64_t gettime_ns()
-{
+uint64_t gettime_ns() {
   struct timeval tv;
   gettimeofday(&tv, NULL);
   return (uint64_t)tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
 }
 
-double *ones_dbl(int nx, int ny)
-{
+double * ones_dbl(int nx, int ny) {
   int i, npix;
   double *im, *imt;
 
-  im = (double *)malloc((npix = nx*ny)*sizeof(double));
+  im = (double *)malloc((npix = nx * ny) * sizeof(double));
   imt = im;
-  for (i=0; i<npix; i++, imt++)
+  for (i = 0; i < npix; i++, imt++) {
     *imt = 1.0;
+  }
 
   return im;
 }
 
-
-float *uniformf(float a, float b, int n)
+float * uniformf(float a, float b, int n)
 /* an array of n random numbers from the uniform interval (a, b) */
 {
   int i;
-  float *result;
+  float * result;
 
-  result = (float*)malloc(n*sizeof(float));
-  for (i=0; i<n; i++)
-    result[i] = a + (b-a) * rand() / ((double)RAND_MAX);
+  result = (float *)malloc(n * sizeof(float));
+  for (i = 0; i < n; i++) {
+    result[i] = a + (b - a) * rand() / ((double)RAND_MAX);
+  }
 
   return result;
 }
 
-float *ones(int nx, int ny)
-{
+float * ones(int nx, int ny) {
   int i, npix;
   float *im, *imt;
 
-  im = (float *)malloc((npix = nx*ny)*sizeof(float));
+  im = (float *)malloc((npix = nx * ny) * sizeof(float));
   imt = im;
-  for (i=0; i<npix; i++, imt++)
+  for (i = 0; i < npix; i++, imt++) {
     *imt = 1.0;
+  }
 
   return im;
 }
 
-void addbox(float *im, int w, int h, float xc, float yc, float r, float val)
+void addbox(float * im, int w, int h, float xc, float yc, float r, float val)
 /* n = sersic index */
 {
   int xmin, xmax, ymin, ymax;
@@ -62,21 +62,22 @@ void addbox(float *im, int w, int h, float xc, float yc, float r, float val)
   int rmax = (int)r;
 
   xmin = (int)xc - rmax;
-  xmin = (xmin < 0)? 0: xmin;
+  xmin = (xmin < 0) ? 0 : xmin;
   xmax = (int)xc + rmax;
-  xmax = (xmax > w)? w: xmax;
+  xmax = (xmax > w) ? w : xmax;
   ymin = (int)yc - rmax;
-  ymin = (ymin < 0)? 0: ymin;
+  ymin = (ymin < 0) ? 0 : ymin;
   ymax = (int)yc + rmax;
-  ymax = (ymax > h)? h: ymax;
-
-  for (y=ymin; y<ymax; y++)
-    for (x=xmin; x<xmax; x++)
-      im[x+w*y] += val;
+  ymax = (ymax > h) ? h : ymax;
 
+  for (y = ymin; y < ymax; y++) {
+    for (x = xmin; x < xmax; x++) {
+      im[x + w * y] += val;
+    }
+  }
 }
 
-void printbox(float *im, int w, int h, int xmin, int xmax, int ymin, int ymax)
+void printbox(float * im, int w, int h, int xmin, int xmax, int ymin, int ymax)
 /* print image values to the screen in a grid
 
    Don't make box size too big!!
@@ -84,24 +85,22 @@ void printbox(float *im, int w, int h, int xmin, int xmax, int ymin, int ymax)
 {
   int i, j;
 
-  for (j = ymin; j < ymax && j < h; j++)
-    {
-      for (i = xmin; i < xmax && i < w; i++)
-	printf("%6.2f ", im[w*j+i]);
-      printf("\n");
+  for (j = ymin; j < ymax && j < h; j++) {
+    for (i = xmin; i < xmax && i < w; i++) {
+      printf("%6.2f ", im[w * j + i]);
     }
+    printf("\n");
+  }
 }
 
-
 /* an extremely dumb reader for our specific test FITS file! */
-int read_test_image(char *fname, float **data, int *nx, int *ny)
-{
-  FILE *f;
-  char buf[80];  /* buffer to hold a line */
+int read_test_image(char * fname, float ** data, int64_t * nx, int64_t * ny) {
+  FILE * f;
+  char buf[80]; /* buffer to hold a line */
   long pos;
   size_t nbytes, nel, i, elsize, nread;
-  char *rawbytes = NULL;
-  short *rawdata;
+  char * rawbytes = NULL;
+  short * rawdata;
   char tmp;
   int status = 0;
   float bscale, bzero;
@@ -118,162 +117,208 @@ int read_test_image(char *fname, float **data, int *nx, int *ny)
 
   /* read first line and check if it is a FITS file */
   nread = fread(buf, 1, 80, f);
-  if (nread != 80) { status = 1; goto exit; }
-  if (strncmp(buf, "SIMPLE  =                    T", 30) != 0)
-    {
-      printf("not a FITS file");
-      status = 1;
-      goto exit;
-    }
+  if (nread != 80) {
+    status = 1;
+    goto exit;
+  }
+  if (strncmp(buf, "SIMPLE  =                    T", 30) != 0) {
+    printf("not a FITS file");
+    status = 1;
+    goto exit;
+  }
 
   /* read rows until we get to END keyword */
-  while (strncmp(buf, "END", 3) != 0)
-    {
-      nread = fread(buf, 1, 80, f);
-      if (nread != 80) { status = 1; goto exit; }
+  while (strncmp(buf, "END", 3) != 0) {
+    nread = fread(buf, 1, 80, f);
+    if (nread != 80) {
+      status = 1;
+      goto exit;
     }
+  }
 
   /* move to next 2880 byte boundary. */
-  pos = ftell(f) % 2880;  /* position in "page" */
-  if (pos != 0) fseek(f, 2880 - pos, SEEK_CUR);
+  pos = ftell(f) % 2880; /* position in "page" */
+  if (pos != 0) {
+    fseek(f, 2880 - pos, SEEK_CUR);
+  }
 
   /* read raw data bytes */
   nbytes = nel * elsize;
   rawbytes = (char *)malloc(nbytes);
   nread = fread(rawbytes, 1, nbytes, f);
-  if (nread != nbytes) { status = 1; goto exit; }
+  if (nread != nbytes) {
+    status = 1;
+    goto exit;
+  }
 
   /* swap bytes in raw data (FITS is big-endian) */
-  for (i=0; i<nbytes; i+=2)
-    {
-      tmp = rawbytes[i];
-      rawbytes[i] = rawbytes[i+1];
-      rawbytes[i+1] = tmp;
-    }
+  for (i = 0; i < nbytes; i += 2) {
+    tmp = rawbytes[i];
+    rawbytes[i] = rawbytes[i + 1];
+    rawbytes[i + 1] = tmp;
+  }
   rawdata = (short *)rawbytes; /* buffer is now little-endian */
 
   /* convert to float, applying bscale/bzero */
   *data = (float *)malloc(nel * sizeof(float));
-  for (i=0; i<nel; i++)
-    {
-      (*data)[i] = bscale * rawdata[i] + bzero;
-    }
+  for (i = 0; i < nel; i++) {
+    (*data)[i] = bscale * rawdata[i] + bzero;
+  }
 
- exit:
+exit:
   free(rawbytes);
 
   return status;
 }
 
-float *tile_flt(float *im, int nx, int ny, int ntilex, int ntiley,
-		int *nxout, int *nyout)
-{
+float * tile_flt(
+    float * im, int nx, int ny, int ntilex, int ntiley, int * nxout, int * nyout
+) {
   int i, x, y;
   int npixout;
-  float *imout;
+  float * imout;
 
   *nxout = ntilex * nx;
   *nyout = ntiley * ny;
   npixout = *nxout * *nyout;
 
-  imout = (float*)malloc(npixout*sizeof(float));
-  for (i=0; i<npixout; i++)
-    {
-      x = (i%(*nxout)) % nx; /* corresponding x on small im */
-      y = (i/(*nxout)) % ny; /* corresponding y on small im */
-      imout[i] = im[y*nx + x];
-    }
+  imout = (float *)malloc(npixout * sizeof(float));
+  for (i = 0; i < npixout; i++) {
+    x = (i % (*nxout)) % nx; /* corresponding x on small im */
+    y = (i / (*nxout)) % ny; /* corresponding y on small im */
+    imout[i] = im[y * nx + x];
+  }
   return imout;
 }
 
-void print_time(char *s, uint64_t tdiff)
-{
+void print_time(char * s, uint64_t tdiff) {
   printf("%-25s%6.1f ms\n", s, (double)tdiff / 1000000.);
 }
 
-int main(int argc, char **argv)
-{
+int main(int argc, char ** argv) {
   char *fname1, *fname2;
-  int i, status, nx, ny;
+  int i, status;
+  int64_t nx, ny;
   double *flux, *fluxerr, *fluxt, *fluxerrt, *area, *areat;
   short *flag, *flagt;
   float *data, *imback;
   uint64_t t0, t1;
-  sep_bkg *bkg = NULL;
-  float conv[] = {1,2,1, 2,4,2, 1,2,1};
-  sep_catalog *catalog = NULL;
-  FILE *catout;
+  sep_bkg * bkg = NULL;
+  float conv[] = {1, 2, 1, 2, 4, 2, 1, 2, 1};
+  sep_catalog * catalog = NULL;
+  FILE * catout;
 
   status = 0;
   flux = fluxerr = NULL;
   flag = NULL;
 
   /* Parse command-line arguments */
-  if (argc != 3)
-    {
-      printf("Usage: test-image IMAGE_NAME CATALOG_NAME\n");
-      exit(1);
-    }
+  if (argc != 3) {
+    printf("Usage: test-image IMAGE_NAME CATALOG_NAME\n");
+    exit(1);
+  }
   fname1 = argv[1];
   fname2 = argv[2];
 
   /* read in image */
   status = read_test_image(fname1, &data, &nx, &ny);
-  if (status) goto exit;
+  if (status) {
+    goto exit;
+  }
 
   /* test the version string */
   printf("sep version: %s\n", sep_version_string);
 
   /* background estimation */
   t0 = gettime_ns();
-  sep_image im = {data, NULL, NULL, NULL, SEP_TFLOAT, 0, 0, 0, nx, ny, 0.0, SEP_NOISE_NONE, 1.0, 0.0};
+  sep_image im = {
+      data,
+      NULL,
+      NULL,
+      NULL,
+      SEP_TFLOAT,
+      0,
+      0,
+      0,
+      0,
+      0,
+      0,
+      nx,
+      ny,
+      0.0,
+      SEP_NOISE_NONE,
+      1.0,
+      0.0
+  };
   status = sep_background(&im, 64, 64, 3, 3, 0.0, &bkg);
   t1 = gettime_ns();
-  if (status) goto exit;
-  print_time("sep_background()", t1-t0);
-
+  if (status) {
+    goto exit;
+  }
+  print_time("sep_background()", t1 - t0);
 
   /* evaluate background */
-  imback = (float *)malloc((nx * ny)*sizeof(float));
+  imback = (float *)malloc((nx * ny) * sizeof(float));
   t0 = gettime_ns();
   status = sep_bkg_array(bkg, imback, SEP_TFLOAT);
   t1 = gettime_ns();
-  if (status) goto exit;
-  print_time("sep_bkg_array()", t1-t0);
+  if (status) {
+    goto exit;
+  }
+  print_time("sep_bkg_array()", t1 - t0);
 
-    /* subtract background */
+  /* subtract background */
   t0 = gettime_ns();
   status = sep_bkg_subarray(bkg, data, im.dtype);
   t1 = gettime_ns();
-  if (status) goto exit;
-  print_time("sep_bkg_subarray()", t1-t0);
+  if (status) {
+    goto exit;
+  }
+  print_time("sep_bkg_subarray()", t1 - t0);
 
   /* extract sources
    * Note that we set deblend_cont = 1.0 to turn off deblending.
    */
   t0 = gettime_ns();
-  status = sep_extract(&im, 1.5*bkg->globalrms, SEP_THRESH_ABS,
-                       5, conv, 3, 3, SEP_FILTER_CONV,
-                       32, 1.0, 1, 1.0, &catalog);
+  status = sep_extract(
+      &im,
+      1.5 * bkg->globalrms,
+      SEP_THRESH_ABS,
+      5,
+      conv,
+      3,
+      3,
+      SEP_FILTER_CONV,
+      32,
+      1.0,
+      1,
+      1.0,
+      &catalog
+  );
   t1 = gettime_ns();
-  if (status) goto exit;
-  print_time("sep_extract()", t1-t0);
+  if (status) {
+    goto exit;
+  }
+  print_time("sep_extract()", t1 - t0);
 
   /* aperture photometry */
-  im.noise = &(bkg->globalrms);  /* set image noise level */
+  im.noise = &(bkg->globalrms); /* set image noise level */
   im.ndtype = SEP_TFLOAT;
   fluxt = flux = (double *)malloc(catalog->nobj * sizeof(double));
   fluxerrt = fluxerr = (double *)malloc(catalog->nobj * sizeof(double));
   areat = area = (double *)malloc(catalog->nobj * sizeof(double));
   flagt = flag = (short *)malloc(catalog->nobj * sizeof(short));
   t0 = gettime_ns();
-  for (i=0; i<catalog->nobj; i++, fluxt++, fluxerrt++, flagt++, areat++)
-    sep_sum_circle(&im,
-		   catalog->x[i], catalog->y[i], 5.0, 0, 5, 0,
-		   fluxt, fluxerrt, areat, flagt);
+  for (i = 0; i < catalog->nobj; i++, fluxt++, fluxerrt++, flagt++, areat++) {
+    sep_sum_circle(
+        &im, catalog->x[i], catalog->y[i], 5.0, 0, 5, 0, fluxt, fluxerrt, areat, flagt
+    );
+  }
   t1 = gettime_ns();
-  printf("sep_sum_circle() [r= 5.0]  %6.3f us/aperture\n",
-	 (double)(t1 - t0) / 1000. / catalog->nobj);
+  printf(
+      "sep_sum_circle() [r= 5.0]  %6.3f us/aperture\n",
+      (double)(t1 - t0) / 1000. / catalog->nobj
+  );
 
   /* print results */
   printf("writing to file: %s\n", fname2);
@@ -284,64 +329,64 @@ int main(int argc, char **argv)
   fprintf(catout, "# 3 Y_IMAGE (0-indexed)\n");
   fprintf(catout, "# 4 FLUX\n");
   fprintf(catout, "# 5 FLUXERR\n");
-  for (i=0; i<catalog->nobj; i++)
-    {
-      fprintf(catout, "%3d %#11.7g %#11.7g %#11.7g %#11.7g\n",
-	      i+1, catalog->x[i], catalog->y[i], flux[i], fluxerr[i]);
-    }
+  for (i = 0; i < catalog->nobj; i++) {
+    fprintf(
+        catout,
+        "%3d %#11.7g %#11.7g %#11.7g %#11.7g\n",
+        i + 1,
+        catalog->x[i],
+        catalog->y[i],
+        flux[i],
+        fluxerr[i]
+    );
+  }
   fclose(catout);
 
   /* clean-up & exit */
- exit:
+exit:
   sep_bkg_free(bkg);
   free(data);
   free(flux);
   free(fluxerr);
   free(flag);
-  if (status)
-    {
-      printf("FAILED with status: %d\n", status);
-      char errtext[512];
-      sep_get_errdetail(errtext);
-      puts(errtext);
-    }
-  else
-    {
-      printf("test_image passed\n");
-    }
+  if (status) {
+    printf("FAILED with status: %d\n", status);
+    char errtext[512];
+    sep_get_errdetail(errtext);
+    puts(errtext);
+  } else {
+    printf("test_image passed\n");
+  }
   return status;
 }
 
-
-  /***************************************************************************/
-  /* aperture photometry */
-
-  /*
-  int naper, j;
-  float *xcs, *ycs;
-
-  im = ones(nx, ny);
-  naper = 1000;
-  flux = fluxerr = 0.0;
-  flag = 0;
-
-  float rs[] = {3., 5., 10., 20.};
-  for (j=0; j<4; j++)
-    {
-      r = rs[j];
-      xcs = uniformf(2.*r, nx - 2.*r, naper);
-      ycs = uniformf(2.*r, ny - 2.*r, naper);
-
-      printf("sep_apercirc() [r=%4.1f]   ", r);
-      t0 = gettime_ns();
-      for (i=0; i<naper; i++)
-	sep_apercirc(im, NULL, SEP_TFLOAT, nx, ny, 0.0, 0.0,
-		     xcs[i], ycs[i], r, 5, &flux, &fluxerr, &flag);
-      t1 = gettime_ns();
-      printf("%6.3f us/aperture\n", (double)(t1 - t0) / 1000. / naper);
-      free(xcs);
-      free(ycs);
-    }
-  */
-
-
+/***************************************************************************/
+/* aperture photometry */
+
+/*
+int naper, j;
+float *xcs, *ycs;
+
+im = ones(nx, ny);
+naper = 1000;
+flux = fluxerr = 0.0;
+flag = 0;
+
+float rs[] = {3., 5., 10., 20.};
+for (j=0; j<4; j++)
+  {
+    r = rs[j];
+    xcs = uniformf(2.*r, nx - 2.*r, naper);
+    ycs = uniformf(2.*r, ny - 2.*r, naper);
+
+    printf("sep_apercirc() [r=%4.1f]   ", r);
+    t0 = gettime_ns();
+    for (i=0; i<naper; i++)
+      sep_apercirc(im, NULL, SEP_TFLOAT, nx, ny, 0.0, 0.0,
+                   xcs[i], ycs[i], r, 5, &flux, &fluxerr, &flag);
+    t1 = gettime_ns();
+    printf("%6.3f us/aperture\n", (double)(t1 - t0) / 1000. / naper);
+    free(xcs);
+    free(ycs);
+  }
+*/
diff --git a/test.py b/test.py
index 1cfb1f2..b8f4829 100755
--- a/test.py
+++ b/test.py
@@ -1,20 +1,30 @@
 #!/usr/bin/env py.test
-from __future__ import print_function, division
-# unicode_literals doesn't play well with numpy dtype field names
+
+"""Test the python functionality of SEP."""
+
+from __future__ import division, print_function
 
 import os
-import pytest
+
 import numpy as np
-from numpy.testing import assert_allclose, assert_equal, assert_approx_equal
+import pytest
+from numpy.lib import recfunctions as rfn
+from numpy.testing import assert_allclose, assert_approx_equal, assert_equal
+
 import sep
 
+# unicode_literals doesn't play well with numpy dtype field names
+
+
 # Try to import any FITS reader
 try:
     from fitsio import read as getdata
+
     NO_FITS = False
 except:
     try:
         from astropy.io.fits import getdata
+
         NO_FITS = False
     except:
         NO_FITS = True
@@ -23,25 +33,27 @@
 BACKIMAGE_FNAME = os.path.join("data", "back.fits")
 RMSIMAGE_FNAME = os.path.join("data", "rms.fits")
 IMAGECAT_FNAME = os.path.join("data", "image.cat")
-IMAGECAT_DTYPE = [('number', np.int64),
-                  ('x', np.float64),
-                  ('y', np.float64),
-                  ('xwin', np.float64),
-                  ('ywin', np.float64),
-                  ('x2', np.float64),
-                  ('y2', np.float64),
-                  ('xy', np.float64),
-                  ('errx2', np.float64),
-                  ('erry2', np.float64),
-                  ('errxy', np.float64),
-                  ('a', np.float64),
-                  ('flux_aper', np.float64),
-                  ('fluxerr_aper', np.float64),
-                  ('kron_radius', np.float64),
-                  ('flux_auto', np.float64),
-                  ('fluxerr_auto', np.float64),
-                  ('flux_radius', np.float64, (3,)),
-                  ('flags', np.int64)]
+IMAGECAT_DTYPE = [
+    ("number", np.int64),
+    ("x", np.float64),
+    ("y", np.float64),
+    ("xwin", np.float64),
+    ("ywin", np.float64),
+    ("x2", np.float64),
+    ("y2", np.float64),
+    ("xy", np.float64),
+    ("errx2", np.float64),
+    ("erry2", np.float64),
+    ("errxy", np.float64),
+    ("a", np.float64),
+    ("flux_aper", np.float64),
+    ("fluxerr_aper", np.float64),
+    ("kron_radius", np.float64),
+    ("flux_auto", np.float64),
+    ("fluxerr_auto", np.float64),
+    ("flux_radius", np.float64, (3,)),
+    ("flags", np.int64),
+]
 SUPPORTED_IMAGE_DTYPES = [np.float64, np.float32, np.int32]
 
 # If we have a FITS reader, read in the necessary test images
@@ -54,10 +66,17 @@
 # -----------------------------------------------------------------------------
 # Helpers
 
+
 def assert_allclose_structured(x, y):
-    """Assert that two structured arrays are close.
+    """
+    Assert that two structured arrays are close.
 
     Compares floats relatively and everything else exactly.
+
+    Parameters
+    ----------
+    x, y : array-like
+        Structured arrays to be compared.
     """
     assert x.dtype == y.dtype
     for name in x.dtype.names:
@@ -68,23 +87,41 @@ def assert_allclose_structured(x, y):
 
 
 def matched_filter_snr(data, noise, kernel):
-    """Super slow implementation of matched filter SNR for testing.
+    r"""
+    Super slow implementation of matched filter SNR for testing.
+
+    At each output pixel :math:`i`, the value is:
+
+    .. math::
+
+        \frac{\sum(\text{data}[i] * \text{kernel}[i] / \text{noise}[i]^2)}
+            {\sqrt\sum(\text{kernel}[i]^2 / \text{noise}[i]^2)}
 
-    At each pixel, value is
+    Parameters
+    ----------
+    data : array-like
+        The 2D data to be tested.
+    noise : array-like
+        The noise corresponding to the input ``data``.
+    kernel : array-like
+        The kernel used for filtering.
 
-        sum(data[i] * kernel[i] / noise[i]^2)
-        -------------------------------------
-        sqrt(sum(kernel[i]^2 / noise[i]^2))
+    Returns
+    -------
+    array-like
+        The output SNR array, the same size as ``data``.
     """
     ctr = kernel.shape[0] // 2, kernel.shape[1] // 2
-    kslice = ((0 - ctr[0], kernel.shape[0] - ctr[0]),  # range in axis 0
-              (0 - ctr[1], kernel.shape[1] - ctr[1]))  # range in axis 1
+    kslice = (
+        (0 - ctr[0], kernel.shape[0] - ctr[0]),  # range in axis 0
+        (0 - ctr[1], kernel.shape[1] - ctr[1]),
+    )  # range in axis 1
     out = np.empty_like(data)
 
     for y in range(data.shape[0]):
-        jmin = y + kslice[0][0] # min and max indicies to sum over
+        jmin = y + kslice[0][0]  # min and max indicies to sum over
         jmax = y + kslice[0][1]
-        kjmin = 0               # min and max kernel indicies to sum over
+        kjmin = 0  # min and max kernel indicies to sum over
         kjmax = kernel.shape[0]
 
         # if we're over the edge of the image, limit extent
@@ -98,9 +135,9 @@ def matched_filter_snr(data, noise, kernel):
             kjmax += offset
 
         for x in range(data.shape[1]):
-            imin = x + kslice[1][0] # min and max indicies to sum over
+            imin = x + kslice[1][0]  # min and max indicies to sum over
             imax = x + kslice[1][1]
-            kimin = 0               # min and max kernel indicies to sum over
+            kimin = 0  # min and max kernel indicies to sum over
             kimax = kernel.shape[1]
 
             # if we're over the edge of the image, limit extent
@@ -115,7 +152,7 @@ def matched_filter_snr(data, noise, kernel):
 
             d = data[jmin:jmax, imin:imax]
             n = noise[jmin:jmax, imin:imax]
-            w = 1. / n**2
+            w = 1.0 / n**2
             k = kernel[kjmin:kjmax, kimin:kimax]
             out[y, x] = np.sum(d * k * w) / np.sqrt(np.sum(k**2 * w))
 
@@ -125,9 +162,11 @@ def matched_filter_snr(data, noise, kernel):
 # -----------------------------------------------------------------------------
 # Test versus Source Extractor results
 
+
 @pytest.mark.skipif(NO_FITS, reason="no FITS reader")
 def test_vs_sextractor():
-    """Test behavior of sep versus sextractor.
+    """
+    Test behavior of sep versus sextractor.
 
     Note: we turn deblending off for this test. This is because the
     deblending algorithm uses a random number generator. Since the sequence
@@ -144,51 +183,60 @@ def test_vs_sextractor():
 
     # Test that SExtractor background is same as SEP:
     bkgarr = bkg.back(dtype=np.float32)
-    assert_allclose(bkgarr, image_refback, rtol=1.e-5)
+    assert_allclose(bkgarr, image_refback, rtol=1.0e-5)
 
-        # Test that SExtractor background rms is same as SEP:
+    # Test that SExtractor background rms is same as SEP:
     rmsarr = bkg.rms(dtype=np.float32)
-    assert_allclose(rmsarr, image_refrms, rtol=1.e-4)
+    assert_allclose(rmsarr, image_refrms, rtol=1.0e-4)
 
     # Extract objects (use deblend_cont=1.0 to disable deblending).
     bkg.subfrom(data)
     objs = sep.extract(data, 1.5, err=bkg.globalrms, deblend_cont=1.0)
-    objs = np.sort(objs, order=['y'])
+    objs = np.sort(objs, order=["y"])
 
     # Read SExtractor result
     refobjs = np.loadtxt(IMAGECAT_FNAME, dtype=IMAGECAT_DTYPE)
-    refobjs = np.sort(refobjs, order=['y'])
+    refobjs = np.sort(refobjs, order=["y"])
 
     # Found correct number of sources at the right locations?
-    assert_allclose(objs['x'], refobjs['x'] - 1., atol=1.e-3)
-    assert_allclose(objs['y'], refobjs['y'] - 1., atol=1.e-3)
+    assert_allclose(objs["x"], refobjs["x"] - 1.0, atol=1.0e-3)
+    assert_allclose(objs["y"], refobjs["y"] - 1.0, atol=1.0e-3)
 
     # Correct Variance and Variance Errors?
-    assert_allclose(objs['x2'], refobjs['x2'], atol=1.e-4)
-    assert_allclose(objs['y2'], refobjs['y2'], atol=1.e-4)
-    assert_allclose(objs['xy'], refobjs['xy'], atol=1.e-4)
-    assert_allclose(objs['errx2'], refobjs['errx2'], rtol=1.e-4)
-    assert_allclose(objs['erry2'], refobjs['erry2'], rtol=1.e-4)
-    assert_allclose(objs['errxy'], refobjs['errxy'], rtol=1.e-3)
+    assert_allclose(objs["x2"], refobjs["x2"], atol=1.0e-4)
+    assert_allclose(objs["y2"], refobjs["y2"], atol=1.0e-4)
+    assert_allclose(objs["xy"], refobjs["xy"], atol=1.0e-4)
+    assert_allclose(objs["errx2"], refobjs["errx2"], rtol=1.0e-4)
+    assert_allclose(objs["erry2"], refobjs["erry2"], rtol=1.0e-4)
+    assert_allclose(objs["errxy"], refobjs["errxy"], rtol=1.0e-3)
 
     # Test aperture flux
-    flux, fluxerr, flag = sep.sum_circle(data, objs['x'], objs['y'], 5.,
-                                         err=bkg.globalrms)
-    assert_allclose(flux, refobjs['flux_aper'], rtol=2.e-4)
-    assert_allclose(fluxerr, refobjs['fluxerr_aper'], rtol=1.0e-5)
+    flux, fluxerr, flag = sep.sum_circle(
+        data, objs["x"], objs["y"], 5.0, err=bkg.globalrms
+    )
+    assert_allclose(flux, refobjs["flux_aper"], rtol=2.0e-4)
+    assert_allclose(fluxerr, refobjs["fluxerr_aper"], rtol=1.0e-5)
 
     # check if the flags work at all (comparison values
     assert ((flag & sep.APER_TRUNC) != 0).sum() == 4
     assert ((flag & sep.APER_HASMASKED) != 0).sum() == 0
 
     # Test "flux_auto"
-    kr, flag = sep.kron_radius(data, objs['x'], objs['y'], objs['a'],
-                               objs['b'], objs['theta'], 6.0)
-
-    flux, fluxerr, flag = sep.sum_ellipse(data, objs['x'], objs['y'],
-                                          objs['a'], objs['b'],
-                                          objs['theta'], r=2.5 * kr,
-                                          err=bkg.globalrms, subpix=1)
+    kr, flag = sep.kron_radius(
+        data, objs["x"], objs["y"], objs["a"], objs["b"], objs["theta"], 6.0
+    )
+
+    flux, fluxerr, flag = sep.sum_ellipse(
+        data,
+        objs["x"],
+        objs["y"],
+        objs["a"],
+        objs["b"],
+        objs["theta"],
+        r=2.5 * kr,
+        err=bkg.globalrms,
+        subpix=1,
+    )
 
     # For some reason, one object doesn't match. It's very small
     # and kron_radius is set to 0.0 in SExtractor, but 0.08 in sep.
@@ -201,59 +249,82 @@ def test_vs_sextractor():
 
     # We use atol for radius because it is reported to nearest 0.01 in
     # reference objects.
-    assert_allclose(2.5*kr, refobjs['kron_radius'], atol=0.01, rtol=0.)
-    assert_allclose(flux, refobjs['flux_auto'], rtol=0.0005)
-    assert_allclose(fluxerr, refobjs['fluxerr_auto'], rtol=0.0005)
+    assert_allclose(2.5 * kr, refobjs["kron_radius"], atol=0.01, rtol=0.0)
+    assert_allclose(flux, refobjs["flux_auto"], rtol=0.0005)
+    assert_allclose(fluxerr, refobjs["fluxerr_auto"], rtol=0.0005)
 
     # Test using a mask in kron_radius and sum_ellipse.
     for dtype in [np.bool_, np.int32, np.float32, np.float64]:
         mask = np.zeros_like(data, dtype=dtype)
-        kr2, flag = sep.kron_radius(data, objs['x'], objs['y'],
-                                    objs['a'], objs['b'], objs['theta'],
-                                    6.0, mask=mask)
-        kr2[i] = 0.
+        kr2, flag = sep.kron_radius(
+            data,
+            objs["x"],
+            objs["y"],
+            objs["a"],
+            objs["b"],
+            objs["theta"],
+            6.0,
+            mask=mask,
+        )
+        kr2[i] = 0.0
         assert np.all(kr == kr2)
 
     # Test ellipse representation conversion
-    cxx, cyy, cxy = sep.ellipse_coeffs(objs['a'], objs['b'], objs['theta'])
-    assert_allclose(cxx, objs['cxx'], rtol=1.e-4)
-    assert_allclose(cyy, objs['cyy'], rtol=1.e-4)
-    assert_allclose(cxy, objs['cxy'], rtol=1.e-4)
+    cxx, cyy, cxy = sep.ellipse_coeffs(objs["a"], objs["b"], objs["theta"])
+    assert_allclose(cxx, objs["cxx"], rtol=1.0e-4)
+    assert_allclose(cyy, objs["cyy"], rtol=1.0e-4)
+    assert_allclose(cxy, objs["cxy"], rtol=1.0e-4)
 
-    a, b, theta = sep.ellipse_axes(objs['cxx'], objs['cyy'], objs['cxy'])
-    assert_allclose(a, objs['a'], rtol=1.e-4)
-    assert_allclose(b, objs['b'], rtol=1.e-4)
-    assert_allclose(theta, objs['theta'], rtol=1.e-4)
+    a, b, theta = sep.ellipse_axes(objs["cxx"], objs["cyy"], objs["cxy"])
+    assert_allclose(a, objs["a"], rtol=1.0e-4)
+    assert_allclose(b, objs["b"], rtol=1.0e-4)
+    assert_allclose(theta, objs["theta"], rtol=1.0e-4)
 
-    #test round trip
+    # test round trip
     cxx, cyy, cxy = sep.ellipse_coeffs(a, b, theta)
-    assert_allclose(cxx, objs['cxx'], rtol=1.e-4)
-    assert_allclose(cyy, objs['cyy'], rtol=1.e-4)
-    assert_allclose(cxy, objs['cxy'], rtol=1.e-4)
+    assert_allclose(cxx, objs["cxx"], rtol=1.0e-4)
+    assert_allclose(cyy, objs["cyy"], rtol=1.0e-4)
+    assert_allclose(cxy, objs["cxy"], rtol=1.0e-4)
 
     # test flux_radius
-    fr, flags = sep.flux_radius(data, objs['x'], objs['y'], 6.*refobjs['a'],
-                                [0.1, 0.5, 0.6], normflux=refobjs['flux_auto'],
-                                subpix=5)
+    fr, flags = sep.flux_radius(
+        data,
+        objs["x"],
+        objs["y"],
+        6.0 * refobjs["a"],
+        [0.1, 0.5, 0.6],
+        normflux=refobjs["flux_auto"],
+        subpix=5,
+    )
     assert_allclose(fr, refobjs["flux_radius"], rtol=0.04, atol=0.01)
 
     # test winpos
-    sig = 2. / 2.35 * fr[:, 1]  # flux_radius = 0.5
-    xwin, ywin, flag = sep.winpos(data, objs['x'], objs['y'], sig)
-    assert_allclose(xwin, refobjs["xwin"] - 1., rtol=0., atol=0.0015)
-    assert_allclose(ywin, refobjs["ywin"] - 1., rtol=0., atol=0.0015)
+    sig = 2.0 / 2.35 * fr[:, 1]  # flux_radius = 0.5
+    xwin, ywin, flag = sep.winpos(data, objs["x"], objs["y"], sig)
+    assert_allclose(xwin, refobjs["xwin"] - 1.0, rtol=0.0, atol=0.0015)
+    assert_allclose(ywin, refobjs["ywin"] - 1.0, rtol=0.0, atol=0.0015)
+
 
 # -----------------------------------------------------------------------------
 # Background
 
+
 def test_masked_background():
-    data = 0.1 * np.ones((6,6))
-    data[1,1] = 1.
-    data[4,1] = 1.
-    data[1,4] = 1.
-    data[4,4] = 1.
+    """
+    Check the background filtering.
 
-    mask = np.zeros((6,6), dtype=np.bool_)
+    Check that the derived background is consistent with an explicit
+    mask, masking no pixels. Also check that the expected result is
+    returned if certain pixels are masked.
+    """
+
+    data = 0.1 * np.ones((6, 6))
+    data[1, 1] = 1.0
+    data[4, 1] = 1.0
+    data[1, 4] = 1.0
+    data[4, 4] = 1.0
+
+    mask = np.zeros((6, 6), dtype=np.bool_)
 
     # Background array without mask
     sky = sep.Background(data, bw=3, bh=3, fw=1, fh=1)
@@ -278,7 +349,9 @@ def test_masked_background():
 
 @pytest.mark.skipif(NO_FITS, reason="no FITS reader")
 def test_background_special():
-    """Test special methods of Background"""
+    """
+    Test the special methods of `sep.Background`.
+    """
 
     bkg = sep.Background(image_data, bw=64, bh=64, fw=3, fh=3)
 
@@ -294,7 +367,9 @@ def test_background_special():
 
 
 def test_background_boxsize():
-    """Test that background works when boxsize is same as image"""
+    """
+    Test that `sep.Background` works when boxsize is same as image.
+    """
 
     ny, nx = 100, 100
     data = np.ones((ny, nx), dtype=np.float64)
@@ -303,7 +378,9 @@ def test_background_boxsize():
 
 
 def test_background_rms():
-    """Test that Background.rms() at least works"""
+    """
+    Test that `sep.Background.rms` at least works.
+    """
 
     ny, nx = 1024, 1024
     data = np.random.randn(ny, nx)
@@ -312,11 +389,19 @@ def test_background_rms():
     assert rms.dtype == np.float64
     assert rms.shape == (ny, nx)
 
+
 # -----------------------------------------------------------------------------
 # Extract
 
+
 @pytest.mark.skipif(NO_FITS, reason="no FITS reader")
 def test_extract_with_noise_array():
+    """
+    Test extraction with a flat noise array.
+
+    This checks that a constant noise array gives the same result as
+    extracting without a noise array, for a given threshold.
+    """
 
     # Get some background-subtracted test data:
     data = np.copy(image_data)
@@ -329,30 +414,41 @@ def test_extract_with_noise_array():
     # convolved. Near edges, the convolution doesn't adjust for pixels
     # off edge boundaries. As a result, the convolved noise map is not
     # all ones.
-    objects = sep.extract(data, 1.5*bkg.globalrms, filter_kernel=None)
-    objects2 = sep.extract(data, 1.5*bkg.globalrms, err=np.ones_like(data),
-                           filter_kernel=None)
-    names_to_remove = ['errx2', 'erry2', 'errxy']
+    # Deblending is also turned off, as this appears to differ slightly
+    # across platforms - see `test_vs_sextractor()`.
+    objects = sep.extract(
+        data, 1.5 * bkg.globalrms, filter_kernel=None, deblend_cont=1.0
+    )
+    objects2 = sep.extract(
+        data,
+        1.5 * bkg.globalrms,
+        err=np.ones_like(data),
+        filter_kernel=None,
+        deblend_cont=1.0,
+    )
+
+    names_to_remove = ["errx2", "erry2", "errxy"]
     names_to_keep = [i for i in objects.dtype.names if i not in names_to_remove]
     objects = objects[names_to_keep]
     objects2 = objects2[names_to_keep]
 
-    assert_equal(objects, objects2)
+    assert_allclose_structured(objects, objects2)
 
     # Less trivial test where thresh is realistic. Still a flat noise map.
     noise = bkg.globalrms * np.ones_like(data)
-    objects2 = sep.extract(data, 1.5, err=noise, filter_kernel=None)
+    objects2 = sep.extract(data, 1.5, err=noise, filter_kernel=None, deblend_cont=1.0)
 
-    names_to_remove = ['errx2', 'erry2', 'errxy']
+    names_to_remove = ["errx2", "erry2", "errxy"]
     names_to_keep = [i for i in objects.dtype.names if i not in names_to_remove]
     objects = objects[names_to_keep]
     objects2 = objects2[names_to_keep]
 
-    assert_equal(objects, objects2)
+    assert_allclose_structured(objects, objects2)
 
 
 def test_extract_with_noise_convolution():
-    """Test extraction when there is both noise and convolution.
+    """
+    Test extraction when there is both noise and convolution.
 
     This will use the matched filter implementation, and will handle bad pixels
     and edge effects gracefully.
@@ -363,15 +459,15 @@ def test_extract_with_noise_convolution():
     error = np.ones((20, 20))
 
     # Add some noise representing bad pixels. We do not want to detect these.
-    image[17, 3] = 100.
-    error[17, 3] = 100.
-    image[10, 0] = 100.
-    error[10, 0] = 100.
-    image[17, 17] = 100.
-    error[17, 17] = 100.
+    image[17, 3] = 100.0
+    error[17, 3] = 100.0
+    image[10, 0] = 100.0
+    error[10, 0] = 100.0
+    image[17, 17] = 100.0
+    error[17, 17] = 100.0
 
     # Add some real point sources that we should find.
-    image[3, 17] = 10.
+    image[3, 17] = 10.0
 
     image[6, 6] = 2.0
     image[7, 6] = 1.0
@@ -380,38 +476,49 @@ def test_extract_with_noise_convolution():
     image[6, 7] = 1.0
 
     objects = sep.extract(image, 2.0, minarea=1, err=error)
-    objects.sort(order=['x', 'y'])
+    objects.sort(order=["x", "y"])
 
     # Check that we recovered the two correct objects and not the others.
     assert len(objects) == 2
 
-    assert_approx_equal(objects[0]['x'], 6.)
-    assert_approx_equal(objects[0]['y'], 6.)
+    assert_approx_equal(objects[0]["x"], 6.0)
+    assert_approx_equal(objects[0]["y"], 6.0)
 
-    assert_approx_equal(objects[1]['x'], 17.)
-    assert_approx_equal(objects[1]['y'], 3.)
+    assert_approx_equal(objects[1]["x"], 17.0)
+    assert_approx_equal(objects[1]["y"], 3.0)
 
 
 def test_extract_matched_filter_at_edge():
-    """Exercise bug where bright star at end of image not detected
-    with noise array and matched filter on."""
+    """
+    Test bright source detection at the edge of an image.
+
+    Exercise bug where bright star at end of image not detected
+    with noise array and matched filter on.
+    """
 
     data = np.zeros((20, 20))
     err = np.ones_like(data)
-    kernel = np.array([[1., 2., 1.],
-                       [2., 4., 2.],
-                       [1., 2., 1.]])
+    kernel = np.array([[1.0, 2.0, 1.0], [2.0, 4.0, 2.0], [1.0, 2.0, 1.0]])
 
     data[18:20, 9:12] = kernel[0:2, :]
 
-    objects, pix = sep.extract(data, 2.0, err=err, filter_kernel=kernel,
-                               filter_type="matched", segmentation_map=True)
+    objects, pix = sep.extract(
+        data,
+        2.0,
+        err=err,
+        filter_kernel=kernel,
+        filter_type="matched",
+        segmentation_map=True,
+    )
     assert len(objects) == 1
     assert objects["npix"][0] == 6
 
 
 @pytest.mark.skipif(NO_FITS, reason="no FITS reader")
 def test_extract_with_mask():
+    """
+    Test that object detection only occurs in unmasked regions.
+    """
 
     # Get some background-subtracted test data:
     data = np.copy(image_data)
@@ -421,46 +528,142 @@ def test_extract_with_mask():
     # mask half the image
     ylim = data.shape[0] // 2
     mask = np.zeros(data.shape, dtype=np.bool_)
-    mask[ylim:,:] = True
+    mask[ylim:, :] = True
 
-    objects = sep.extract(data, 1.5*bkg.globalrms, mask=mask)
+    objects = sep.extract(data, 1.5 * bkg.globalrms, mask=mask)
 
     # check that we found some objects and that they are all in the unmasked
     # region.
     assert len(objects) > 0
-    assert np.all(objects['y'] < ylim)
+    assert np.all(objects["y"] < ylim)
 
 
 @pytest.mark.skipif(NO_FITS, reason="no FITS reader")
 def test_extract_segmentation_map():
+    """
+    Test the returned segmentation map.
+
+    Check that the segmentation map has the same dimensions as the input
+    image, and that the number of object pixels match the catalogue field.
+    """
 
     # Get some background-subtracted test data:
     data = np.copy(image_data)
     bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3)
     bkg.subfrom(data)
 
-    objects, segmap = sep.extract(data, 1.5*bkg.globalrms,
-                                  segmentation_map=True)
+    objects, segmap = sep.extract(data, 1.5 * bkg.globalrms, segmentation_map=True)
 
     assert type(segmap) is np.ndarray
     assert segmap.shape == data.shape
     for i in range(len(objects)):
-        assert objects["npix"][i] == (segmap == i+1).sum()
+        assert objects["npix"][i] == (segmap == i + 1).sum()
+
+
+@pytest.mark.skipif(NO_FITS, reason="no FITS reader")
+def test_extract_seg_map_array():
+    """
+    Test the extraction when an existing segmentation map is supplied.
+
+    Test that the returned catalogue is equal with and without a variable
+    noise array, and that the majority of fields match even when
+    deblending is performed on the original extraction.
+    """
+
+    # Get some background-subtracted test data:
+    data = np.copy(image_data)
+    bkg = sep.Background(data, bw=64, bh=64, fw=3, fh=3)
+    bkg.subfrom(data)
+
+    noise = bkg.globalrms * np.ones_like(data)
+
+    for err in [None, noise]:
+        # err=None
+        # err=noise
+
+        objects, segmap = sep.extract(data, 1.5, err, segmentation_map=True)
+
+        assert type(segmap) is np.ndarray
+        assert segmap.shape == data.shape
+        for i in range(len(objects)):
+            assert objects["npix"][i] == (segmap == i + 1).sum()
+
+        objects2, segmap2 = sep.extract(data, 1.5, err, segmentation_map=segmap)
+
+        # Test the values for which we expect an exact match
+        names_exact_match = [
+            "thresh",
+            "npix",
+            "tnpix",
+            "xmin",
+            "xmax",
+            "ymin",
+            "ymax",
+            "cflux",
+            "flux",
+            "cpeak",
+            "peak",
+            "xcpeak",
+            "ycpeak",
+            "xpeak",
+            "ypeak",
+        ]
+
+        # The position depends on the object being deblended. As no deblending
+        # is performed when a segmentation map is supplied, all derived
+        # parameters may vary slightly. We test those for which we have a
+        # measurement of the uncertainty
+        names_close = ["x", "y"]
+        names_close_var = ["x2", "y2"]
+
+        assert segmap2.shape == data.shape
+        for o_i, o_ii in zip(objects, objects2):
+            o_i_exact = o_i[names_exact_match]
+            o_ii_exact = o_ii[names_exact_match]
+            assert_equal(o_i_exact, o_ii_exact)
+
+            o_i_close = o_i[names_close]
+            o_ii_close = o_ii[names_close]
+            for n, v in zip(names_close, names_close_var):
+                if o_i["flag"] == 0:
+                    assert_equal(o_i[n], o_ii[n])
+                else:
+                    assert_allclose(o_i[n], o_ii[n], atol=np.sqrt(o_i[v]))
+
+        # Perform a second test with deblending disabled.
+        objects3, segmap3 = sep.extract(
+            data, 1.5, err, segmentation_map=True, deblend_cont=1.0
+        )
+
+        objects4, segmap4 = sep.extract(
+            data, 1.5, err, segmentation_map=segmap3, deblend_cont=1.0
+        )
+
+        # The flag will not be the same, as the second extraction does not test
+        # for deblended objects.
+        objects3 = rfn.drop_fields(objects3, "flag")
+        objects4 = rfn.drop_fields(objects4, "flag")
+        assert_allclose_structured(objects3, objects4)
 
 
 # -----------------------------------------------------------------------------
 # aperture tests
 
 naper = 1000
-x = np.random.uniform(200., 800., naper)
-y = np.random.uniform(200., 800., naper)
+x = np.random.uniform(200.0, 800.0, naper)
+y = np.random.uniform(200.0, 800.0, naper)
 data_shape = (1000, 1000)
 
+
 def test_aperture_dtypes():
-    """Ensure that all supported image dtypes work in sum_circle() and
-    give the same answer"""
+    """
+    Test the aperture extraction of multiple data types.
 
-    r = 3.
+    Ensure that all supported image dtypes work in sum_circle() and
+    give the same answer.
+    """
+
+    r = 3.0
 
     fluxes = []
     for dt in SUPPORTED_IMAGE_DTYPES:
@@ -477,118 +680,129 @@ def test_apertures_small_ellipse_exact():
 
     data = np.ones(data_shape)
     r = 0.3
-    rtol=1.e-10
-    flux, fluxerr, flag = sep.sum_ellipse(data, x, x, r, r, 0., subpix=0)
-    assert_allclose(flux, np.pi*r**2, rtol=rtol)
+    rtol = 1.0e-10
+    flux, fluxerr, flag = sep.sum_ellipse(data, x, x, r, r, 0.0, subpix=0)
+    assert_allclose(flux, np.pi * r**2, rtol=rtol)
+
 
 def test_apertures_all():
-    """Test that aperture subpixel sampling works"""
+    """
+    Test that aperture subpixel sampling works.
+    """
 
     data = np.random.rand(*data_shape)
-    r = 3.
-    rtol=1.e-8
+    r = 3.0
+    rtol = 1.0e-8
 
     for subpix in [0, 1, 5]:
-        flux_ref, fluxerr_ref, flag_ref = sep.sum_circle(data, x, y, r,
-                                                         subpix=subpix)
+        flux_ref, fluxerr_ref, flag_ref = sep.sum_circle(data, x, y, r, subpix=subpix)
 
-        flux, fluxerr, flag = sep.sum_circann(data, x, y, 0., r,
-                                              subpix=subpix)
+        flux, fluxerr, flag = sep.sum_circann(data, x, y, 0.0, r, subpix=subpix)
         assert_allclose(flux, flux_ref, rtol=rtol)
 
-        flux, fluxerr, flag = sep.sum_ellipse(data, x, y, r, r, 0.,
-                                              subpix=subpix)
+        flux, fluxerr, flag = sep.sum_ellipse(data, x, y, r, r, 0.0, subpix=subpix)
         assert_allclose(flux, flux_ref, rtol=rtol)
 
-        flux, fluxerr, flag = sep.sum_ellipse(data, x, y, 1., 1., 0., r=r,
-                                              subpix=subpix)
+        flux, fluxerr, flag = sep.sum_ellipse(
+            data, x, y, 1.0, 1.0, 0.0, r=r, subpix=subpix
+        )
         assert_allclose(flux, flux_ref, rtol=rtol)
 
 
-
 def test_apertures_exact():
-    """Test area as measured by exact aperture modes on array of ones"""
+    """
+    Test area as measured by exact aperture modes on array of ones.
+    """
 
-    theta = np.random.uniform(-np.pi/2., np.pi/2., naper)
+    theta = np.random.uniform(-np.pi / 2.0, np.pi / 2.0, naper)
     ratio = np.random.uniform(0.2, 1.0, naper)
-    r = 3.
+    r = 3.0
 
     for dt in SUPPORTED_IMAGE_DTYPES:
         data = np.ones(data_shape, dtype=dt)
-        for r in [0.5, 1., 3.]:
+        for r in [0.5, 1.0, 3.0]:
             flux, fluxerr, flag = sep.sum_circle(data, x, y, r, subpix=0)
-            assert_allclose(flux, np.pi*r**2)
+            assert_allclose(flux, np.pi * r**2)
 
-            rout = r*1.1
-            flux, fluxerr, flag = sep.sum_circann(data, x, y, r, rout,
-                                                  subpix=0)
-            assert_allclose(flux, np.pi*(rout**2 - r**2))
+            rout = r * 1.1
+            flux, fluxerr, flag = sep.sum_circann(data, x, y, r, rout, subpix=0)
+            assert_allclose(flux, np.pi * (rout**2 - r**2))
 
-            flux, fluxerr, flag = sep.sum_ellipse(data, x, y, 1., ratio,
-                                                  theta, r=r, subpix=0)
-            assert_allclose(flux, np.pi*ratio*r**2)
+            flux, fluxerr, flag = sep.sum_ellipse(
+                data, x, y, 1.0, ratio, theta, r=r, subpix=0
+            )
+            assert_allclose(flux, np.pi * ratio * r**2)
 
-            rout = r*1.1
-            flux, fluxerr, flag = sep.sum_ellipann(data, x, y, 1., ratio,
-                                                   theta, r, rout, subpix=0)
-            assert_allclose(flux, np.pi*ratio*(rout**2 - r**2))
+            rout = r * 1.1
+            flux, fluxerr, flag = sep.sum_ellipann(
+                data, x, y, 1.0, ratio, theta, r, rout, subpix=0
+            )
+            assert_allclose(flux, np.pi * ratio * (rout**2 - r**2))
 
 
 def test_aperture_bkgann_overlapping():
-    """Test bkgann functionality in circular & elliptical apertures."""
+    """
+    Test bkgann functionality in circular & elliptical apertures.
+    """
 
     # If bkgann overlaps aperture exactly, result should be zero
     # (with subpix=1)
     data = np.random.rand(*data_shape)
-    r = 5.
-    f, _, _ = sep.sum_circle(data, x, y, r, bkgann=(0., r), subpix=1)
-    assert_allclose(f, 0., rtol=0., atol=1.e-13)
+    r = 5.0
+    f, _, _ = sep.sum_circle(data, x, y, r, bkgann=(0.0, r), subpix=1)
+    assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13)
 
-    f, _, _ = sep.sum_ellipse(data, x, y, 2., 1., np.pi/4., r=r,
-                              bkgann=(0., r), subpix=1)
-    assert_allclose(f, 0., rtol=0., atol=1.e-13)
+    f, _, _ = sep.sum_ellipse(
+        data, x, y, 2.0, 1.0, np.pi / 4.0, r=r, bkgann=(0.0, r), subpix=1
+    )
+    assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13)
 
 
 def test_aperture_bkgann_ones():
-    """Test bkgann functionality with flat data"""
+    """
+    Test bkgann functionality with flat data.
+    """
 
     data = np.ones(data_shape)
-    r=5.
-    bkgann=(6., 8.)
+    r = 5.0
+    bkgann = (6.0, 8.0)
 
     # On flat data, result should be zero for any bkgann and subpix
-    f, fe, _ = sep.sum_circle(data, x, y, r, bkgann=bkgann, gain=1.)
-    assert_allclose(f, 0., rtol=0., atol=1.e-13)
+    f, fe, _ = sep.sum_circle(data, x, y, r, bkgann=bkgann, gain=1.0)
+    assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13)
 
     # for all ones data and no error array, error should be close to
     # sqrt(Npix_aper + Npix_ann * (Npix_aper**2 / Npix_ann**2))
     aper_area = np.pi * r**2
-    bkg_area = np.pi * (bkgann[1]**2 - bkgann[0]**2)
-    expected_error = np.sqrt(aper_area + bkg_area * (aper_area/bkg_area)**2)
+    bkg_area = np.pi * (bkgann[1] ** 2 - bkgann[0] ** 2)
+    expected_error = np.sqrt(aper_area + bkg_area * (aper_area / bkg_area) ** 2)
     assert_allclose(fe, expected_error, rtol=0.1)
 
-    f, _, _ = sep.sum_ellipse(data, x, y, 2., 1., np.pi/4., r, bkgann=bkgann)
-    assert_allclose(f, 0., rtol=0., atol=1.e-13)
+    f, _, _ = sep.sum_ellipse(data, x, y, 2.0, 1.0, np.pi / 4.0, r, bkgann=bkgann)
+    assert_allclose(f, 0.0, rtol=0.0, atol=1.0e-13)
+
 
 def test_masked_segmentation_measurements():
-    """Test measurements with segmentation masking"""
+    """
+    Test measurements with segmentation masking.
+    """
 
     NX = 100
-    data = np.zeros((NX*2,NX*2))
+    data = np.zeros((NX * 2, NX * 2))
     yp, xp = np.indices(data.shape)
 
     ####
     # Make two 2D gaussians that slightly overlap
 
     # width of the 2D objects
-    gsigma = 10.
+    gsigma = 10.0
 
     # offset between two gaussians in sigmas
     off = 4
 
-    for xy in [[NX,NX], [NX+off*gsigma, NX+off*gsigma]]:
-        R = np.sqrt((xp-xy[0])**2+(yp-xy[1])**2)
-        g_i = np.exp(-R**2/2/gsigma**2)
+    for xy in [[NX, NX], [NX + off * gsigma, NX + off * gsigma]]:
+        R = np.sqrt((xp - xy[0]) ** 2 + (yp - xy[1]) ** 2)
+        g_i = np.exp(-(R**2) / 2 / gsigma**2)
         data += g_i
 
     # Absolute total
@@ -597,99 +811,124 @@ def test_masked_segmentation_measurements():
     # Add some noise
     rms = 0.02
     np.random.seed(1)
-    data += np.random.normal(size=data.shape)*rms
+    data += np.random.normal(size=data.shape) * rms
 
     # Run source detection
-    objs, segmap = sep.extract(data, thresh=1.2, err=rms, mask=None,
-                               segmentation_map=True)
+    objs, segmap = sep.extract(
+        data, thresh=1.2, err=rms, mask=None, segmentation_map=True
+    )
 
-    seg_id = np.arange(1, len(objs)+1, dtype=np.int32)
+    seg_id = np.arange(1, len(objs) + 1, dtype=np.int32)
 
     # Compute Kron/Auto parameters
-    x, y, a, b = objs['x'], objs['y'], objs['a'], objs['b']
-    theta = objs['theta']
+    x, y, a, b = objs["x"], objs["y"], objs["a"], objs["b"]
+    theta = objs["theta"]
 
     kronrad, krflag = sep.kron_radius(data, x, y, a, b, theta, 6.0)
 
-    flux_auto, fluxerr, flag = sep.sum_ellipse(data, x, y, a, b, theta,
-                                               2.5*kronrad,
-                                               segmap=segmap, seg_id=seg_id,
-                                               subpix=1)
+    flux_auto, fluxerr, flag = sep.sum_ellipse(
+        data, x, y, a, b, theta, 2.5 * kronrad, segmap=segmap, seg_id=seg_id, subpix=1
+    )
 
     # Test total flux
-    assert_allclose(flux_auto, total_exact, rtol=5.e-2)
+    assert_allclose(flux_auto, total_exact, rtol=5.0e-2)
 
     # Flux_radius
     for flux_fraction in [0.2, 0.5]:
 
         # Exact solution
-        rhalf_exact = np.sqrt(-np.log(1-flux_fraction)*gsigma**2*2)
+        rhalf_exact = np.sqrt(-np.log(1 - flux_fraction) * gsigma**2 * 2)
 
         # Masked measurement
-        flux_radius, flag = sep.flux_radius(data, x, y, 6.*a, flux_fraction,
-                                        seg_id=seg_id, segmap=segmap,
-                                        normflux=flux_auto, subpix=5)
+        flux_radius, flag = sep.flux_radius(
+            data,
+            x,
+            y,
+            6.0 * a,
+            flux_fraction,
+            seg_id=seg_id,
+            segmap=segmap,
+            normflux=flux_auto,
+            subpix=5,
+        )
 
         # Test flux fraction
-        assert_allclose(flux_radius, rhalf_exact, rtol=5.e-2)
+        assert_allclose(flux_radius, rhalf_exact, rtol=5.0e-2)
 
     if False:
-        print('test_masked_flux_radius')
+        print("test_masked_flux_radius")
         print(total_exact, flux_auto)
         print(rhalf_exact, flux_radius)
 
+
 def test_mask_ellipse():
+    """
+    Test that the correct number of elements are masked with an ellipse.
+    """
     arr = np.zeros((20, 20), dtype=np.bool_)
 
     # should mask 5 pixels:
-    sep.mask_ellipse(arr, 10., 10., 1.0, 1.0, 0.0, r=1.001)
+    sep.mask_ellipse(arr, 10.0, 10.0, 1.0, 1.0, 0.0, r=1.001)
     assert arr.sum() == 5
 
     # should mask 13 pixels:
-    sep.mask_ellipse(arr, 10., 10., 1.0, 1.0, 0.0, r=2.001)
+    sep.mask_ellipse(arr, 10.0, 10.0, 1.0, 1.0, 0.0, r=2.001)
     assert arr.sum() == 13
 
 
 def test_flux_radius():
+    """
+    Test that the correct radius is returned for varying flux fractions.
+    """
     data = np.ones(data_shape)
-    fluxfrac = [0.2**2, 0.3**2, 0.7**2, 1.]
-    true_r = [2., 3., 7., 10.]
-    r, _ = sep.flux_radius(data, x, y, 10.*np.ones_like(x),
-                           [0.2**2, 0.3**2, 0.7**2, 1.], subpix=5)
+    fluxfrac = [0.2**2, 0.3**2, 0.7**2, 1.0]
+    true_r = [2.0, 3.0, 7.0, 10.0]
+    r, _ = sep.flux_radius(
+        data, x, y, 10.0 * np.ones_like(x), [0.2**2, 0.3**2, 0.7**2, 1.0], subpix=5
+    )
     for i in range(len(fluxfrac)):
         assert_allclose(r[:, i], true_r[i], rtol=0.01)
 
 
 def test_mask_ellipse_alt():
-    """mask_ellipse with cxx, cyy, cxy parameters."""
+    """
+    Mask_ellipse with cxx, cyy, cxy parameters.
+    """
     arr = np.zeros((20, 20), dtype=np.bool_)
 
     # should mask 5 pixels:
-    sep.mask_ellipse(arr, 10., 10., cxx=1.0, cyy=1.0, cxy=0.0, r=1.001)
+    sep.mask_ellipse(arr, 10.0, 10.0, cxx=1.0, cyy=1.0, cxy=0.0, r=1.001)
     assert arr.sum() == 5
 
     # should mask 13 pixels:
-    sep.mask_ellipse(arr, 10., 10., cxx=1.0, cyy=1.0, cxy=0.0, r=2.001)
+    sep.mask_ellipse(arr, 10.0, 10.0, cxx=1.0, cyy=1.0, cxy=0.0, r=2.001)
     assert arr.sum() == 13
 
 
 # -----------------------------------------------------------------------------
 # General behavior and utilities
 
+
 def test_byte_order_exception():
-    """Test that error about byte order is raised with non-native
+    """
+    Test that SEP will not run with non-native byte order.
+
+    Test that error about byte order is raised with non-native
     byte order input array. This should happen for Background, extract,
-    and aperture functions."""
+    and aperture functions.
+    """
 
     data = np.ones((100, 100), dtype=np.float64)
-    data = data.byteswap(True).newbyteorder()
+    data = data.view(data.dtype.newbyteorder("S"))
     with pytest.raises(ValueError) as excinfo:
         bkg = sep.Background(data)
-    assert 'byte order' in excinfo.value.args[0]
+    assert "byte order" in excinfo.value.args[0]
 
 
 def test_set_pixstack():
-    """Ensure that setting the pixel stack size works."""
+    """
+    Ensure that setting the pixel stack size works.
+    """
     old = sep.get_extract_pixstack()
     new = old * 2
     sep.set_extract_pixstack(new)
@@ -698,7 +937,9 @@ def test_set_pixstack():
 
 
 def test_set_sub_object_limit():
-    """Ensure that setting the sub-object deblending limit works."""
+    """
+    Ensure that setting the sub-object deblending limit works.
+    """
     old = sep.get_sub_object_limit()
     new = old * 2
     sep.set_sub_object_limit(new)
@@ -707,8 +948,12 @@ def test_set_sub_object_limit():
 
 
 def test_long_error_msg():
-    """Ensure that the error message is created successfully when
-    there is an error detail."""
+    """
+    Test the error handling in SEP.
+
+    Ensure that the error message is created successfully when
+    there is an error detail.
+    """
 
     # set extract pixstack to an insanely small value; this will trigger
     # a detailed error message when running sep.extract()