Showing preview only (976K chars total). Download the full file or copy to clipboard to get everything.
Repository: kbarbary/sep
Branch: main
Commit: 93b3ac52e0f6
Files: 61
Total size: 935.7 KB
Directory structure:
gitextract_54cmwk4y/
├── .clang-format
├── .github/
│ └── workflows/
│ ├── build-wheels-upload-pypi.yml
│ └── python-package-tox.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── AUTHORS.md
├── CHANGES.md
├── CMakeLists.txt
├── FindSEP.cmake
├── MANIFEST.in
├── Makefile
├── README.md
├── bench.py
├── codemeta.json
├── ctest/
│ ├── compare.py
│ └── test_image.c
├── data/
│ ├── README.md
│ ├── back.fits
│ ├── default.conv
│ ├── default.nnw
│ ├── default.param
│ ├── default.sex
│ ├── image.cat
│ ├── image.fits
│ └── rms.fits
├── docs/
│ ├── Makefile
│ ├── apertures.rst
│ ├── changelogs/
│ │ ├── changelog.rst
│ │ ├── changes_to_c_api.rst
│ │ ├── new_changes.rst
│ │ └── original_changes.md
│ ├── conf.py
│ ├── filter.rst
│ ├── index.rst
│ ├── reference.rst
│ ├── rtd-pip-requirements
│ └── tutorial.ipynb
├── licenses/
│ ├── BSD_LICENSE.txt
│ ├── LGPL_LICENSE.txt
│ └── MIT_LICENSE.txt
├── paper/
│ ├── paper.bib
│ └── paper.md
├── pyproject.toml
├── sep.pyx
├── setup.py
├── src/
│ ├── analyse.c
│ ├── aperture.c
│ ├── aperture.i
│ ├── background.c
│ ├── convolve.c
│ ├── deblend.c
│ ├── extract.c
│ ├── extract.h
│ ├── lutz.c
│ ├── overlap.h
│ ├── sep.h
│ ├── sepcore.h
│ └── util.c
├── test.py
└── tox.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
# 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
================================================
FILE: .github/workflows/build-wheels-upload-pypi.yml
================================================
# GitHub action for building the distribution and wheels of the sep package
# and uploading them to the PyPI package index.
name: build-wheels-upload-pypi
on: [push, workflow_dispatch]
# push:
# # Run this action on the trigger event when *any* tag is pushed
# tags:
# - '*'
jobs:
# This action is split into three jobs:
# - Building the source distribution
# - Building the wheels for the distribution
# - Uploading the artifacts to PyPI package
# 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.
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: install_python
uses: actions/setup-python@v5
with:
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 setuptools twine numpy wheel cython build
- name: Build sdist
run: python -m build --sdist
- name: Show files
run: ls -lh dist
shell: bash
- name: Check metadata
run: twine check dist/*
- name: Upload sdist
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.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.12"]
os: [windows-latest, macos-latest, ubuntu-24.04, ubuntu-24.04-arm]
steps:
- uses: actions/checkout@v4
- name: checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install cibuildwheel
run: python -m pip install cibuildwheel
- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
env:
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
CIBW_MANYLINUX_I686_IMAGE: manylinux2014
CIBW_BUILD_VERBOSITY: 1
CIBW_SKIP: '*-musllinux_*'
CIBW_ARCHS_LINUX: "auto"
- name: Show files
run: ls -lh wheelhouse
shell: bash
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.os }}
path: ./wheelhouse/*.whl
upload_to_pypi:
# Finally we collect all out data from the artifacts and put them back to
# dist directory for upload. The final step waits for the other jobs to be
# finished and starts only if the trigger event of the action was a push
# of a tag starting with <v> as version separation. All other jobs run
# without heading <v>
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@v5
- uses: actions/download-artifact@v4
with:
pattern: dist*
merge-multiple: true
path: dist
- name: upload_to_pypi
uses: pypa/gh-action-pypi-publish@release/v1
# with:
# repository-url: https://test.pypi.org/legacy/
================================================
FILE: .github/workflows/python-package-tox.yml
================================================
# 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: CI
on: [push, workflow_call, workflow_dispatch, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
os: [windows-latest, macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install Tox and any other packages
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`, append platform
run: tox
env:
PLATFORM: ${{ matrix.os }}
================================================
FILE: .gitignore
================================================
# emacs
*~
# --------------------------------------------
# C
*.o
*.os
*.so
*.so.*
*.dylib
*.dylib.*
*.a
ctest/test_image
# generated by tests
data/sep.cat
data/sepback.fits
# scons
.sconsign.dblite
# tarball
sep-*.tar.gz
# -------------------------------------------
# Python
__pycache__
docs/_build
docs/api
build/
MANIFEST
*.egg-info
# pytest
.pytest_cache
.cache
# generated C file
sep.c
# PyCharm
.idea
.project
# Eclipse
.pydevproject
# Jupyter
.ipynb_checkpoints
# tox
.tox
# version
*_version.py
================================================
FILE: .pre-commit-config.yaml
================================================
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]
================================================
FILE: .readthedocs.yaml
================================================
# 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
================================================
FILE: AUTHORS.md
================================================
* Emmanuel Bertin (bertin@iap.fr) : original SExtractor code
* Kyle Barbary (@kbarbary) : Conversion of SExtractor code to library
* Kyle Boone (@kboone) : Bugfix, matched filter
* Thomas Robitaille (@astrofrog) : Exact aperture overlap code
* Matt Craig (@mwcraig) : Windows & OS X support
* Curtis McCully (@cmccully): Parameter uncertainties
* Evert Rol (@evertrol): setup.py fixes
* 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.
================================================
FILE: CHANGES.md
================================================
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)
=======================
* 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.3.5 (12 June 2024)
=====================
* 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).
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 2.6)
project(sep C)
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/")
include(GNUInstallDirs)
set(SOURCES
${CMAKE_SOURCE_DIR}/src/analyse.c
${CMAKE_SOURCE_DIR}/src/convolve.c
${CMAKE_SOURCE_DIR}/src/deblend.c
${CMAKE_SOURCE_DIR}/src/extract.c
${CMAKE_SOURCE_DIR}/src/lutz.c
${CMAKE_SOURCE_DIR}/src/aperture.c
${CMAKE_SOURCE_DIR}/src/background.c
${CMAKE_SOURCE_DIR}/src/util.c
)
include_directories(${CMAKE_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/src ${CFITSIO_INCLUDE_DIR})
link_directories(${CMAKE_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/src)
add_library(sep SHARED ${SOURCES})
set_target_properties(sep PROPERTIES OUTPUT_NAME sep)
set_target_properties(sep PROPERTIES VERSION 0.6.0 SOVERSION 0)
set_target_properties(sep PROPERTIES C_VISIBILITY_PRESET hidden)
if (MSVC)
add_definitions(-D_USE_MATH_DEFINES)
else ()
add_compile_options(-Wcast-qual)
target_link_libraries(sep m)
endif()
install(TARGETS sep LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES ${CMAKE_SOURCE_DIR}/src/sep.h DESTINATION include)
================================================
FILE: FindSEP.cmake
================================================
# - Try to find SEP
# Once done this will define
#
# SEP_FOUND - system has SEP
# SEP_INCLUDE_DIR - the SEP include directory
# SEP_LIBRARIES - Link these to use SEP
# SEP_VERSION_STRING - Human readable version number of sep
# SEP_VERSION_MAJOR - Major version number of sep
# SEP_VERSION_MINOR - Minor version number of sep
# Copyright (c) 2017, Ilia Platone, <info@iliaplatone.com>
# Based on FindLibfacile by Carsten Niehaus, <cniehaus@gmx.de>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (SEP_LIBRARIES)
# in cache already
set(SEP_FOUND TRUE)
message(STATUS "Found SEP: ${SEP_LIBRARIES}")
else (SEP_LIBRARIES)
find_library(SEP_LIBRARIES NAMES sep
PATHS
${_obLinkDir}
${GNUWIN32_DIR}/lib
/usr/local/lib
)
if(SEP_LIBRARIES)
set(SEP_FOUND TRUE)
else (SEP_LIBRARIES)
set(SEP_FOUND FALSE)
endif(SEP_LIBRARIES)
if (SEP_FOUND)
if (NOT SEP_FIND_QUIETLY)
message(STATUS "Found SEP: ${SEP_LIBRARIES}")
endif (NOT SEP_FIND_QUIETLY)
else (SEP_FOUND)
if (SEP_FIND_REQUIRED)
message(FATAL_ERROR "SEP not found. Please install libsep-dev")
endif (SEP_FIND_REQUIRED)
endif (SEP_FOUND)
mark_as_advanced(SEP_LIBRARIES)
endif (SEP_LIBRARIES)
================================================
FILE: MANIFEST.in
================================================
include README.md
include CHANGES.md
include AUTHORS.md
include licenses/*
include pyproject.toml
include src/*.[c,h,i]
include sep.pyx
exclude sep.c
================================================
FILE: Makefile
================================================
OS ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
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.$(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.$(MAJOR)
SONAME_FULL = libsep.so.$(MAJOR).$(MINOR).$(CURRENT_MICRO)
SONAME_FLAG = -soname
LDPATHENV = LD_LIBRARY_PATH
else
$(error OS not yet supported)
endif
endif
INSTALL ?= install
DESTDIR =
PREFIX ?= /usr/local
LIBDIR = $(PREFIX)/lib
INCLUDEDIR = $(PREFIX)/include
CC?=gcc
AR?=ar
CPPFLAGS ?=
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)
OBJS = src/analyse.o src/convolve.o src/deblend.o src/extract.o \
src/lutz.o src/aperture.o src/background.o src/util.o
default: all
src/analyse.o src/convolve.o src/deblend.o src/extract.o src/lutz.o: src/%.o: src/%.c src/extract.h src/sepcore.h src/sep.h
$(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/$*.c -o $@
src/aperture.o: src/aperture.c src/aperture.i src/overlap.h src/sepcore.h src/sep.h
$(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/aperture.c -o $@
src/background.o src/util.o: src/%.o: src/%.c src/sepcore.h src/sep.h
$(CC) $(CPPFLAGS) $(CFLAGS_LIB) -c src/$*.c -o $@
src/$(SONAME_FULL) src/$(SONAME_MAJOR) src/$(SONAME) &: $(OBJS)
$(CC) $(LDFLAGS_LIB) $^ -lm -o src/$(SONAME_FULL)
ln -sf $(SONAME_FULL) src/$(SONAME_MAJOR)
ln -sf $(SONAME_FULL) src/$(SONAME)
src/libsep.a: $(OBJS)
$(AR) rcs src/libsep.a $^
install: all
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -m u=rw,g=r,o=r src/sep.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) -m u=rwx,g=rx,o=rx src/$(SONAME_FULL) $(DESTDIR)$(LIBDIR)
ln -sf $(SONAME_FULL) $(DESTDIR)$(LIBDIR)/$(SONAME_MAJOR)
ln -sf $(SONAME_FULL) $(DESTDIR)$(LIBDIR)/$(SONAME)
$(INSTALL) -m u=rw,g=r,o=r src/libsep.a $(DESTDIR)$(LIBDIR)
uninstall:
rm $(DESTDIR)$(INCLUDEDIR)/sep.h
rm $(DESTDIR)$(LIBDIR)/$(SONAME_FULL)
rm $(DESTDIR)$(LIBDIR)/$(SONAME_MAJOR)
rm $(DESTDIR)$(LIBDIR)/$(SONAME)
rm $(DESTDIR)$(LIBDIR)/libsep.a
test: ctest/test_image
$(LDPATHENV)=src ctest/test_image data/image.fits data/sep.cat
ctest/compare.py data/image.cat data/sep.cat
ctest/test_image: ctest/test_image.c src/$(SONAME)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Lsrc ctest/test_image.c -lm -lsep -o ctest/test_image
clean:
rm -f src/*.o src/*.a src/libsep.* ctest/test_image
all: src/$(SONAME_FULL) src/libsep.a
.PHONY: all test clean library install uninstall
================================================
FILE: README.md
================================================
SEP
===
Python and C library for Source Extraction and Photometry.
[](https://pypi.python.org/pypi/sep)
[](https://pypi.python.org/pypi/sep)
[](https://github.com/sep-developers/sep/actions)
[](https://sep.readthedocs.io/en/latest/?badge=latest)
[](http://dx.doi.org/10.21105/joss.00058)
*"... [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
-----
[Source Extractor](http://www.astromatic.net/software/sextractor)
(Bertin & Arnouts 1996) is a widely used
command-line program for segmentation and analysis of astronomical
images. It reads in FITS format files, performs a configurable series
of tasks, including background estimation, source detection,
deblending and a wide array of source measurements, and finally
outputs a FITS format catalog file.
While Source Extractor is highly useful, the fact that it can only be
used as an executable can limit its applicability or lead to awkward
workflows. There is often a desire to have programmatic access to
perform one or more of the above tasks on in-memory images as part of
a larger custom analysis.
**SEP makes the core algorithms of Source Extractor available as a
library of stand-alone functions and classes.** These operate directly
on in-memory arrays (no FITS files or configuration files). The code
is derived from the Source Extractor code base (written in C) and aims
to produce results compatible with Source Extractor whenever possible.
SEP consists of a C library with no dependencies outside the standard
library, and a Python module that wraps the C library in a Pythonic
API. The Python wrapper operates on NumPy arrays with NumPy as its
only dependency. See below for language-specfic build and usage
instructions.
Python
------
**Documentation:** http://sep.readthedocs.io
**Requirements:**
- Python 3.9+
- numpy 1.23+
**Install release version:**
SEP can be installed with [pip](https://pip.pypa.io):
```
python -m pip install sep
```
If you get an error about permissions, you are probably using your
system Python. In this case, we recommend using [pip's "user
install"](https://pip.pypa.io/en/latest/user_guide/#user-installs)
option to install sep into your user directory:
```
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.
**Install development version:**
Building the development version (from github) requires Cython.
Build and install in the usual place:
```
python -m pip install --editable .
```
**Run tests:** Tests require the [pytest](http://pytest.org) Python
package. To run the tests, execute `./test.py` in the top-level
directory. Some tests require a FITS reader (either fitsio or astropy)
and will be skipped if neither is present.
C Library
---------
_Note: The build process only works on Linux and OS X._
**CMake:** To build using CMake, enter these commands:
```
cd sep
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ../
```
and follow next steps from the build folder
**Build:** To build the C library from source:
```
make
```
**Run tests:**
```
make test
```
**Install** The static library and header can be installed with
```
make install
make PREFIX=/path/to/prefix install
```
This will install the shared and static library in `/path/to/prefix/lib`
and header file in `/path/to/prefix/include`. The default prefix is
`/usr/local`.
**API:** The C library API is documented in the header file
[sep.h](src/sep.h).
**Rust bindings:** Low-level Rust wrapper for the C library can be found at https://crates.io/crates/sep-sys
Contributing
------------
- 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
[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/sep-developers/sep/discussions/).
Citation
--------
If you use SEP in a publication, please cite the following article in the Journal of Open Source Software:
[](http://dx.doi.org/10.21105/joss.00058)
Please also cite the original Source Extractor paper ([Bertin & Arnouts
1996](http://adsabs.harvard.edu/abs/1996A%26AS..117..393B)).
The DOI for the sep v1.0.0 code release is:
[](http://dx.doi.org/10.5281/zenodo.159035)
License
-------
The license for all parts of the code derived from Source Extractor is
LGPLv3. The license for code derived from photutils (`src/overlap.h`)
is BSD 3-clause. Finally, the license for the Python wrapper
(`sep.pyx`) is MIT. The license for the library as a whole is
therefore LGPLv3. The license for each file is explicitly stated at
the top of the file and the full text of each license can be found in
`licenses`.
FAQ
---
**Why isn't the C library part of Source Extractor?**
Source Extractor is *not* designed as a library with an
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
core of the Source Extractor program with little gain for the executable.
**What sort of changes?**
- Source Extractor reads in only a small portion of each image at a
time. This allows it to keep its memory footprint extremely low and
to operate on images that are much larger than the system's physical
memory. It also means that a FITS reader is deeply integrated into
the code. SEP operates on images in memory, so all the FITS I/O
machinery in Source Extractor is not used here.
- Error handling: When it encounters a problem, Source Extractor
immediately exits with an error message. This is fine for an
executable, but a library function doesn't have that luxury. Instead
it must ensure that allocated memory is freed and return an error
code.
- Options: Source Extractor has many options that affect its behavior. These
are stored in a global structure used throughout the executable. In SEP,
options for a particular function are passed as function parameters.
- Array types: Source Extractor can operate on FITS images containing various
types of data (float, double, int, etc). Internally, it does this by
converting all data to `float` immediately when reading from disk.
SEP does something similar, but in memory: SEP functions typically convert
input arrays to float on the fly within each function, then perform
all operations as floating point.
**Is SEP as fast as Source Extractor?**
It's fast. It should be similar to Source Extractor as a lot of the code
is identical. Source Extractor has the advantage of doing all the
operations (detection and analysis) simultaneously on each image
section, which may confer CPU cache advantages, but this hasn't been
tested at all. On the other hand, depending on your usage SEP might
let you avoid writing files to disk, which is likely to be a bigger
win.
**What happens when Source Extractor is updated in the future?**
SEP can be considered a fork of the Source Extractor code base: it's
development will not track that of Source Extractor in any automated
way. However, the algorithms implemented so far in SEP are stable in
Source Extractor: the SEP code was forked from v2.18.11, yet it is tested
against the results of v2.8.6. This indicates that the algorithms have
not changed in Source Extractor over the last few years.
**In the Python interface, why do I have to byte swap data when using
astropy.io.fits?**
This occurs because FITS files have big-endian [byte
order](http://en.wikipedia.org/wiki/Endianness), whereas most widely
used CPUs have little-endian byte order. In order for the CPU to
operate on the data, it must be byte swapped at *some point.* Some
FITS readers such as [fitsio](http://github.com/esheldon/fitsio) do
the byte swap immediately when reading the data from disk to memory,
returning numpy arrays in native (little-endian) byte order. However,
astropy.io.fits does not (for reasons having to do with memory
mapping). Most of the time you never notice this because when you do
any numpy operations on such arrays, numpy uses an intermediate buffer
to byte swap the array behind the scenes and returns the result as a
native byte order array. Internally, SEP is not using numpy
operations; it's just getting a pointer to the data in the array and
passing it to C code. As the C code does not include functionality to
do buffered byte swapping, the input array must already be in native
byte order.
It would be possible to add buffered byte swapping capability to the
SEP code, but it would increase the code complexity. A simpler
alternative would be to make a byte swapped copy of the entire input
array, whenever necessary. However, this would significantly increase
memory use, and would have to be done repeatedly in multiple SEP
functions: `Background`, `extract`, `sum_circle`, etc. Each would make
a copy of the entire data array. Given these considerations, it seemed
best to just explicitly tell the user to do the byte swap operation
themselves so they could just do it once, immediately after reading in
the data.
**I have more questions!**
Open a discussion on the [GitHub Discussions page](https://github.com/sep-developers/sep/discussions/categories/q-a)!
================================================
FILE: bench.py
================================================
#!/usr/bin/env python
"""Benchmarking SEP against equivalent photutils functions."""
from __future__ import print_function
import time
from pathlib import Path
import numpy as np
import sep
# try to import photutils for comparison timing
try:
import photutils
HAVE_PHOTUTILS = True
except ImportError:
HAVE_PHOTUTILS = False
# 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
NEED_BYTESWAP = True
except ImportError:
HAVE_FITS = False
import argparse
parser = argparse.ArgumentParser(description="SEP Benchmark script.")
parser.add_argument(
"-c",
"--condensed",
default=False,
action="store_true",
help="Only run a condensed subset of the benchmarks.",
)
parser.add_argument(
"-t",
"--tiles",
default=4,
type=int,
help=(
"The maximum number of tiles for the image background benchmark, "
"i.e. the image size will be `(t*256)^2`."
),
)
parser.add_argument(
"-a",
"--apertures",
default=1000,
type=int,
help=(
"The number of apertures to use for benchmarking the aperture "
"photometry, by default 1000."
),
)
parser.add_argument(
"-r",
"--radii",
default=[3, 5, 10, 20],
type=float,
nargs="+",
help=(
"The radii of the apertures to test. Ignored if the `--condensed` "
"flag is passed, otherwise defaults to `3, 5, 10, 20`."
),
)
parser.add_argument(
"-n",
"--nloop",
default=50,
type=int,
help=("The number of loops to run for all tests, by default 50."),
)
args = parser.parse_args()
if HAVE_FITS:
rawdata = getdata(
Path(__file__).parent / "data" / "image.fits"
) # original is 256 x 256
if NEED_BYTESWAP:
rawdata = rawdata.astype(rawdata.dtype.newbyteorder("="))
else:
print("No FITS reader found, generating random data instead.")
rawdata = np.random.random((256, 256))
data = np.tile(rawdata, (4, 4))
print("test image shape:", data.shape)
print("test image dtype:", data.dtype)
t0 = time.time()
bkg = sep.Background(data) # estimate background
t1 = time.time()
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.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.0e3))
t0 = time.time()
rmsarr = bkg.rms()
t1 = time.time()
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.0e3, len(objects)))
# --------------------------------------------------------------------------
# Background subtraction
print("")
if HAVE_PHOTUTILS:
print("sep version: ", sep.__version__)
print("photutils version:", photutils.__version__)
print(
"""
| test | sep | photutils | ratio |
|-------------------------|-----------------|-----------------|--------|"""
)
blankline = (
"| | | | |"
)
else:
print("sep version: ", sep.__version__)
print(
"""
| test | sep |
|-------------------------|-----------------|"""
)
blankline = "| | |"
for ntile in np.arange(1, args.tiles + 1, dtype=int):
data = np.tile(rawdata, (ntile, ntile))
line = "| {0:4d}^2 image background |".format(data.shape[0])
t0 = time.time()
for _ in range(0, args.nloop):
bkg = sep.Background(data)
t1 = time.time()
t_sep = (t1 - t0) * 1.0e3 / args.nloop
line += " {0:7.2f} ms |".format(t_sep)
if HAVE_PHOTUTILS:
t0 = time.time()
for _ in range(0, args.nloop):
from photutils import background
bkg = background.Background2D(data, (64, 64)) # estimate background
t1 = time.time()
t_pu = (t1 - t0) * 1.0e3 / args.nloop
line += " {0:7.2f} ms | {1:6.2f} |".format(t_pu, t_pu / t_sep)
print(line)
# ------------------------------------------------------------------------------
# Circular aperture photometry benchmarks
if not args.condensed:
print(blankline)
line = "| **aperture photometry** | |"
if HAVE_PHOTUTILS:
line += " | |"
print(line)
data = np.ones((2000, 2000), dtype=np.float32)
x = np.random.uniform(200.0, 1800.0, args.apertures)
y = np.random.uniform(200.0, 1800.0, args.apertures)
if args.condensed:
r_list = [5.0]
subpix_list = [(5, "subpixel", "subpix=5"), (0, "exact", "exact")]
else:
r_list = args.radii
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:
line = "| circles r={0:2d} {1:8s} |".format(int(r), label)
t0 = time.time()
for _ in range(0, args.nloop):
flux, fluxerr, flag = sep.sum_circle(data, x, y, r, subpix=subpix)
t1 = time.time()
t_sep = (t1 - t0) * 1.0e6 / args.apertures / args.nloop
line += " {0:7.2f} us/aper |".format(t_sep)
if HAVE_PHOTUTILS:
from photutils import aperture
apertures = photutils.aperture.CircularAperture(np.column_stack((x, y)), r)
t0 = time.time()
for _ in range(0, args.nloop):
res = photutils.aperture.aperture_photometry(
data, apertures, method=method, subpixels=subpix
)
t1 = time.time()
t_pu = (t1 - t0) * 1.0e6 / args.apertures / args.nloop
line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep)
print(line)
if not args.condensed:
print(blankline)
a = 1.0
b = 1.0
theta = np.pi / 4.0
for r in r_list:
for subpix, method, label in subpix_list:
line = "| ellipses r={0:2d} {1:8s} |".format(int(r), label)
t0 = time.time()
for _ in range(0, args.nloop):
flux, fluxerr, flag = sep.sum_ellipse(
data, x, y, a, b, theta, r, subpix=subpix
)
t1 = time.time()
t_sep = (t1 - t0) * 1.0e6 / args.apertures / args.nloop
line += " {0:7.2f} us/aper |".format(t_sep)
if HAVE_PHOTUTILS:
from photutils import aperture
apertures = photutils.aperture.EllipticalAperture(
np.column_stack((x, y)), a * r, b * r, theta
)
t0 = time.time()
for _ in range(0, args.nloop):
res = photutils.aperture.aperture_photometry(
data, apertures, method=method, subpixels=subpix
)
t1 = time.time()
t_pu = (t1 - t0) * 1.0e6 / args.apertures / args.nloop
line += " {0:7.2f} us/aper | {1:6.2f} |".format(t_pu, t_pu / t_sep)
print(line)
================================================
FILE: codemeta.json
================================================
{
"@context": "https://raw.githubusercontent.com/mbjones/codemeta/master/codemeta.jsonld",
"@type": "Code",
"author": [
{
"@id": "http://orcid.org/0000-0002-2532-3696",
"@type": "Person",
"email": "kylebarbary@gmail.com",
"name": "Kyle Barbary",
"affiliation": "University of California, Berkeley"
}
],
"identifier": "http://dx.doi.org/10.5281/zenodo.159035",
"codeRepository": "https://github.com/kbarbary/sep",
"datePublished": "2016-09-30",
"dateModified": "2016-09-30",
"dateCreated": "2016-09-30",
"description": "Python and C library for Source Extraction and Photometry",
"keywords": "astronomy, Python, image analysis",
"license": "LGPL v3.0",
"title": "SEP",
"version": "v1.0.0"
}
================================================
FILE: ctest/compare.py
================================================
#!/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"):
l = line.strip()
if len(l) == 0 or l[0] == "#":
continue
items = l.split()
typed_items = []
for it in items:
try:
typed_items.append(int(it))
except ValueError:
typed_items.append(float(it))
rows.append(typed_items)
return rows
def fracdiff(x, y):
"""
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__":
fname1, fname2 = sys.argv[1:3]
ref = read_table(fname1)
sep = read_table(fname2)
# sort by y coordinate
ref.sort(key=lambda row: row[2])
sep.sort(key=lambda row: row[2])
assert len(ref) == len(sep)
for i in range(len(ref)):
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")
================================================
FILE: ctest/test_image.c
================================================
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "sep.h"
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) {
int i, npix;
double *im, *imt;
im = (double *)malloc((npix = nx * ny) * sizeof(double));
imt = im;
for (i = 0; i < npix; i++, imt++) {
*imt = 1.0;
}
return im;
}
float * uniformf(float a, float b, int n)
/* an array of n random numbers from the uniform interval (a, b) */
{
int i;
float * result;
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) {
int i, npix;
float *im, *imt;
im = (float *)malloc((npix = nx * ny) * sizeof(float));
imt = im;
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)
/* n = sersic index */
{
int xmin, xmax, ymin, ymax;
int x, y;
int rmax = (int)r;
xmin = (int)xc - rmax;
xmin = (xmin < 0) ? 0 : xmin;
xmax = (int)xc + rmax;
xmax = (xmax > w) ? w : xmax;
ymin = (int)yc - rmax;
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;
}
}
}
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!!
*/
{
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");
}
}
/* an extremely dumb reader for our specific test FITS file! */
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 tmp;
int status = 0;
float bscale, bzero;
/* hard-code image size & element size */
*nx = 256;
*ny = 256;
elsize = 2;
nel = *nx * *ny;
bscale = 2.92273835509;
bzero = 3713.66692596;
f = fopen(fname, "r");
/* 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;
}
/* 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;
}
}
/* move to next 2880 byte boundary. */
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;
}
/* 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;
}
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;
}
exit:
free(rawbytes);
return status;
}
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;
*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];
}
return imout;
}
void print_time(char * s, uint64_t tdiff) {
printf("%-25s%6.1f ms\n", s, (double)tdiff / 1000000.);
}
int main(int argc, char ** argv) {
char *fname1, *fname2;
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;
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);
}
fname1 = argv[1];
fname2 = argv[2];
/* read in image */
status = read_test_image(fname1, &data, &nx, &ny);
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,
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);
/* evaluate background */
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);
/* 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);
/* 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
);
t1 = gettime_ns();
if (status) {
goto exit;
}
print_time("sep_extract()", t1 - t0);
/* aperture photometry */
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
);
}
t1 = gettime_ns();
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);
catout = fopen(fname2, "w+");
fprintf(catout, "# SEP catalog\n");
fprintf(catout, "# 1 NUMBER\n");
fprintf(catout, "# 2 X_IMAGE (0-indexed)\n");
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]
);
}
fclose(catout);
/* clean-up & 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");
}
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);
}
*/
================================================
FILE: data/README.md
================================================
Test Data
---------
The comparison catalog file `image.cat` is generated by running
```
sextractor image.fits -CATALOG_NAME image.cat
```
in this directory.
================================================
FILE: data/back.fits
================================================
SIMPLE = T / file does conform to FITS standard BITPIX = -32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 256 / length of data axis 1 NAXIS2 = 256 / length of data axis 2 EXTEND = T / FITS dataset may contain extensions COMMENT FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H CRPIX1 = -7.670000000000000E+02 / Reference pixel CRVAL1 = 1.000000000000E+00 / Coordinate at reference pixel CDELT1 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE1 = ' ' / Units of coordinate CRPIX2 = -5.110000000000000E+02 / Reference pixel CRVAL2 = 1.000000000000E+00 / Coordinate at reference pixel CDELT2 = 1.000000000000E+00 / Coordinate increment per pixel CTYPE2 = ' ' / Units of coordinate BUNIT = ' ' / Units of data values BSCALE = 1.00000000 / Scaling factor: r = f*i + z BZERO = 0.00000000 / Zero offset: r = f*i + z DATAMAX = 9.852823437500E+04 / Maximum data value DATAMIN = 3.713666992188E+03 / Minimum data value ORIGIN = 'SExtractor' / Written by MIDAS DATE = '31/08/93' / Date of writting: DD/MM/YY FILENAME= 'NA36Rm50.bdf' / Original file name MIDASFTP= 'IMAGE ' / MIDAS File Type OBJECT = 'NA36Rc50 sum of 3 frames' / MIDAS desc.: IDENT(1) DATE-OBS= '26/10/92' / MIDAS desc.: O_TIME(1) MJD-OBS = 4.892162787000E+04 / MIDAS desc.: O_TIME(4) TM-START= 1.104800000000E+04 / MIDAS desc.: O_TIME(5) EXPTIME = 1.200000000000E+03 / MIDAS desc.: O_TIME(7) INSTRUME= 'EMMI ' / MIDAS desc.: INSTRUME(1) COMMENT IP_JIDNT 7 / IHAP: identifier system \COMMENT COMMENT IP_JSEQ 24887 / IHAP: sequence number \COMMENT COMMENT IP_AHGC 2857.489 / IHAP: high cut \COMMENT COMMENT IP_ALWC 2112.953 / IHAP: low cut \COMMENT COMMENT IP_ASCX 1. / IHAP: scaling in x \COMMENT COMMENT IP_ASCY 1. / IHAP: scaling in y \COMMENT COMMENT IP_FILE 'IHAP/FITS/EM9210260304099.FITS::USER ' / IHAP: Begin of keywor\COMMENT d COMMENT IP_FEND / IHAP: End of keyword file \COMMENT COMMENT EXPTIME 400.000 \COMMENT COMMENT IP_CBEND / IHAP: comment block end \COMMENT TELESCOP= 'ESONTTB ' / MIDAS desc.: TELESCOP(1) OBSERVER= 'LAPPARENT' / MIDAS desc.: OBSERVER(1) RA = 5.648170000000E+00 / MIDAS desc.: RA(1) DEC = -3.018297000000E+01 / MIDAS desc.: DEC(1) AIRMASS = 1.068349957466E+00 / MIDAS desc.: AIRMASS(1) ESO-LOG 00:00:00> DATE = '1992-10-26' / Mon Oct 26, 1992 ESO-LOG 03:04:08>-START EXPO EMMI RED / Start exp. on EMMI Red CC ESO-LOG 03:04:09> EXPO EMMI RED NO = 24887 / Exp. num. on EMMI Red CCD ESO-LOG 03:10:52>-STOP EXPO EMMI RED / Stop exp. on EMMI Red CCD HISTORY COMPUTE/IMAG imAR0051.bdf = #0001-bias50 \HISTORY COMPUTE/IMAG imAR0051.bdf = #0001 - 1.51001E-01 \HISTORY COMPUTE/IMAG NA36Rc501 = #0001 * 1.00000E+03 / fRc50 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc501 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc503 \HISTORY COMPUTE/IMAG NA36Rc50 = NA36Rc50 + NA36Rc502 \HISTORY EXTRACT/IMAG intex = NA36Rc50[@0019,@0003:@1042,@1026] \HISTORY Renamed from intex.bdf to NA36Rc50.bdf \HISTORY SELE/TABL cursor MA36Rc50 2 0. 3 Y MA36Rc50 \HISTORY READ/TABL cursor interclean 0 6.85000E+03 3 Y \HISTORY interclean Renamed from interclean.bdf to MA36Rm\HISTORY 50.bdf READ/TABL cursor MA36Rm50 0 \HISTORY 6850 3 Y MA36Rm50 READ/TABL cursor MA\HISTORY 36Rm50 0 6850 3 Y MA36Rm50 READ/TABL \HISTORY cursor MA36Rm50 0 6850 3 Y MA36Rm50 RA = 5.648169994354E+00 / MIDAS desc.: O_POS(1) DEC = -3.018300056458E+01 / MIDAS desc.: O_POS(2) AIRMASS = 1.068349957466E+00 / MIDAS desc.: O_AIRM(1) HIERARCH ESO GEN ID = 'ARC-0001/1.2' HIERARCH ESO GEN PROJ ID = '000.00.000' HIERARCH ESO GEN EXPO NO = 24887 HIERARCH ESO GEN EXPO TYPE = 'SCI ' HIERARCH ESO GEN EXPO LST = 2.420000000000E+03 HIERARCH ESO TEL ID = 'ESONTTB ' HIERARCH ESO TEL LON = 7.073450000000E+01 HIERARCH ESO TEL LAT = -2.925840000000E+01 HIERARCH ESO TEL ALTITUDE = 2440 HIERARCH ESO TEL FOCU LEN = 3.848200000000E+01 HIERARCH ESO TEL FOCU SCALE = 1.489000000000E+00 HIERARCH ESO TEL TRAK RATEA = 4.200000000000E-03 HIERARCH ESO TEL TRAK RATED = 0.000000000000E+00 HIERARCH ESO ADA ID = 'ADAPTB ' HIERARCH ESO ADA MODE = 'STD ' HIERARCH ESO ADA ROT = 0.000000000000E+00 HIERARCH ESO ADA GUID-1 X = 1.294000000000E-02 HIERARCH ESO ADA GUID-1 Y = 1.717000000000E-01 HIERARCH ESO ADA GUID-2 X = 5.070000000000E-04 HIERARCH ESO ADA GUID-2 Y = 1.110000000000E-03 HIERARCH ESO INS ID = 'EMMI #1 ' HIERARCH ESO INS COMP ID = 'HP RTE-A V5' HIERARCH ESO INS MODE = 'RILD ' HIERARCH ESO INS OPTI-2 NO = 1 HIERARCH ESO INS OPTI-2 TYPE = 'MIRROR ' HIERARCH ESO INS OPTI-2 ID = 'RILD MIR' HIERARCH ESO INS OPTI-2 NAME = 'RILD ' HIERARCH ESO INS OPTI-3 NO = 1 HIERARCH ESO INS OPTI-3 TYPE = 'FREE ' HIERARCH ESO INS MIRR-3 NAME = 'UPPER RED' HIERARCH ESO INS MIRR-3 ST = 0 HIERARCH ESO INS OPTI-7 NO = 3 HIERARCH ESO INS OPTI-7 TYPE = 'FILTER ' HIERARCH ESO INS OPTI-7 ID = '#608 ' HIERARCH ESO INS OPTI-7 NAME = 'R ' HIERARCH ESO INS OPTI-9 NO = 9 HIERARCH ESO INS OPTI-9 TYPE = 'FREE ' HIERARCH ESO DET NAME = 'THX31156' HIERARCH ESO DET ID = 'ccd$18 ' HIERARCH ESO DET TYPE = 'CCD Four_Phase' HIERARCH ESO DET PIXSIZE = 1.900000000000E-05 HIERARCH ESO DET BITS = 16 HIERARCH ESO DET FRAM NAXIS1 = 1060 HIERARCH ESO DET FRAM CRVAL1 = 1 HIERARCH ESO DET FRAM CRPIX1 = 1 HIERARCH ESO DET FRAM CDELT1 = 1 HIERARCH ESO DET FRAM NAXIS2 = 1040 HIERARCH ESO DET FRAM CRVAL2 = 1 HIERARCH ESO DET FRAM CRPIX2 = 1 HIERARCH ESO DET FRAM CDELT2 = 1 HIERARCH ESO DET DKTIME = 4.000000000000E+02 HIERARCH ESO DET TEMP_VAR = 1.000000000000E-01 HIERARCH ESO DET TEMPMEAN = 1.376000000000E+02 HIERARCH ESO DET COMP ID = 'ccdr-V1.0' HIERARCH ESO DET PARM1 = 'CLOCK=tho1k' HIERARCH ESO DET PARM2 = 'HLO1 : 2.02 VLO1 : 1.01 VDD1 : 23.03' HIERARCH ESO DET PARM3 = 'HHI1 : 15.00 VHI1 : 12.01 VDR1 : 13.98' HIERARCH ESO DET PARM4 = 'HLO2 : 2.02 RLO1 : 1.01 VGS1 : 4.99' HIERARCH ESO DET PARM5 = 'HHI2 : 15.03 RHI1 : 10.07 ICCD1 : 0.00' HIERARCH ESO DET PARM6 = 'TL 1, 5 telem. data' HIERARCH ESO DET DATE = 1.989794555664E+03 HIERARCH ESO DET MODE = 'SLOW ' HIERARCH ESO DET GAIN = 1 HIERARCH ESO DET AD_VALUE = 2.100000000000E+00 HIERARCH ESO DET DIT = 4.000000000000E+02 HIERARCH ESO DET SHUT TMOPEN = 5.000000000000E-01 HIERARCH ESO DET SHUT TMCLOS = 5.000000000000E-01 HISTORY ESO-DESCRIPTORS START ................ HISTORY 'WIND_RAW' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_RAW' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.5800000E+02 3.2767000E+04 2.3813201E+03 5.6562799E+02 2.4699001E+10 HISTORY 3.8941301E+14 2.4969999E+09 2.3490701E+03 2.3460000E+03 2.0070000E+03 HISTORY 1.6000000E+01 6.5800000E+02 3.2767000E+04 HISTORY HISTORY 'WIND_OVER' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+01 1.0290000E+03 1.0550000E+03 1.0390000E+03 HISTORY HISTORY 'STAT_OVER' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 2.1200000E+02 2.4400000E+02 2.2111700E+02 2.5815699E+00 1.0815500E+07 HISTORY 2.3924700E+09 2.5441800E+06 2.2058000E+02 2.2050000E+02 3.3000000E+01 HISTORY 1.0000000E+00 2.1200000E+02 2.4400000E+02 HISTORY HISTORY 'BIAS_FRAME' ,'C*1 ' , 1, 7,'7A1',' ',' ' HISTORY bias50 HISTORY HISTORY 'BIAS_OVER_DIFF' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.5100101E-01 HISTORY HISTORY 'FLAT_WIND' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 4.5000000E+02 3.8000000E+02 7.4000000E+02 6.2000000E+02 HISTORY HISTORY 'FLAT_BKG' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.1311699E+03 HISTORY HISTORY 'SKIM_FRAC' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.5154400E-04 HISTORY HISTORY 'AV_WIND_NAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'FLAT_FRAME' ,'C*1 ' , 1, 5,'5A1',' ',' ' HISTORY fRc50 HISTORY HISTORY 'WIND_FIN' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.9000000E+01 3.0000000E+00 1.0420000E+03 1.0260000E+03 HISTORY HISTORY 'STAT_FIN' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 6.0423798E+02 3.2842602E+04 2.1606499E+03 5.5936798E+02 2.0734501E+10 HISTORY 3.5516501E+14 2.2656100E+09 2.1273799E+03 2.1162400E+03 2.0150000E+03 HISTORY 1.6000000E+01 6.0423798E+02 3.2842602E+04 HISTORY HISTORY 'WIND_SUM' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 1.0000000E+00 1.0000000E+00 1.0240000E+03 1.0240000E+03 HISTORY HISTORY 'STAT_SUM' ,'R*4 ' , 1, 13,'5E14.7',' ',' ' HISTORY 3.7136699E+03 9.8528203E+04 6.9033799E+03 1.6677500E+03 6.1352398E+11 HISTORY 2.8897399E+16 7.2387098E+09 6.8047002E+03 6.7938701E+03 2.0480000E+03 HISTORY 4.6318802E+01 3.7136699E+03 9.8528203E+04 HISTORY HISTORY 'LHCUTS' ,'R*4 ' , 1, 4,'5E14.7',' ',' ' HISTORY 5.5000000E+03 9.0000000E+03 3.7136670E+03 9.8528234E+04 HISTORY HISTORY 'DISPLAY_DATA' ,'I*4 ' , 1, 9,'7I10',' ',' ' HISTORY 2 2 513 513 0 -1 -1 HISTORY -1 -1 HISTORY HISTORY 'BOX_MIN' ,'R*4 ' , 1, 6,'5E14.7',' ',' ' HISTORY 3.2100000E+02 2.1500000E+02 6.9644336E+03 6.3300000E+02 4.2300000E+02 HISTORY 6.8900532E+03 HISTORY HISTORY 'IJBORDER' ,'I*4 ' , 1, 4,'7I10',' ',' ' HISTORY 1 1 1024 1024 HISTORY HISTORY 'LHCUT' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 3.6236699E+03 8.0148297E+04 HISTORY HISTORY 'ZEROMAGN' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 2.4671000E+01 HISTORY HISTORY 'SEEING' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 1.8308023E+00 9.6358800E-01 HISTORY HISTORY 'PAIRSPRT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 3.1899800E+00 HISTORY HISTORY 'MULTDTCT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 4.1900001E+00 HISTORY HISTORY 'PRFLCTRL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY -5 HISTORY HISTORY 'OUPROFIL' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 5 HISTORY HISTORY 'STMETRIC' ,'R*4 ' , 1, 2,'5E14.7',' ',' ' HISTORY 9.3000001E-01 5.5799999E+00 HISTORY HISTORY 'BRGHTLMT' ,'R*4 ' , 1, 1,'5E14.7',' ',' ' HISTORY 1.8387699E+01 HISTORY HISTORY 'NBSTARS' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 17 HISTORY HISTORY 'PSFTAB' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'THRESHOLD' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 6.8047002E+03 1.1384800E+02 1.6730800E+00 2.0000000E+00 2.5446301E+01 HISTORY HISTORY 'N_SEARCH_ANA' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 822 806 HISTORY HISTORY 'N_STAR_GAL_DEF' ,'I*4 ' , 1, 3,'7I10',' ',' ' HISTORY 46 744 16 HISTORY HISTORY 'HIST_BINS' ,'R*4 ' , 1, 5,'5E14.7',' ',' ' HISTORY 2.5600000E+02 2.8824686E+02 3.7136670E+03 7.7216609E+04 0.0000000E+00 HISTORY HISTORY 'HISTOGRAM' ,'I*4 ' , 1, 256,'7I10',' ',' ' HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 10 64 23 12 HISTORY 3 3 4 4 3 1 2 HISTORY 0 0 1 1 0 1 0 HISTORY 0 0 0 3 0 1 0 HISTORY 0 1 0 1 0 1 0 HISTORY 0 0 1 1 0 1 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 1 1 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 1 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 1 0 0 0 0 0 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 0 1 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 1 0 0 HISTORY 0 1 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 1 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 0 0 0 0 0 HISTORY 0 0 1 0 0 0 0 HISTORY 0 0 1 0 HISTORY HISTORY 'STATISTIC' ,'R*4 ' , 1, 11,'5E14.7',' ',' ' HISTORY 3.7136670E+03 9.8528234E+04 6.9033760E+03 1.6677493E+03 6.1352378E+11 HISTORY 2.8897433E+16 7.2387144E+09 6.5048496E+03 3.8995779E+03 2.5600000E+02 HISTORY 3.7182184E+02 HISTORY HISTORY 'WINDOW_FROM' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1 1 HISTORY HISTORY 'WINDOW_TO' ,'I*4 ' , 1, 2,'7I10',' ',' ' HISTORY 1024 1024 HISTORY HISTORY 'NBMODIF' ,'I*4 ' , 1, 1,'7I10',' ',' ' HISTORY 1 HISTORY HISTORY 'STARS' ,'R*4 ' , 1, 51,'5E14.7',' ',' ' HISTORY 2.6300000E+02 8.8700000E+02 4.6759199E+04 7.5000000E+01 5.6300000E+02 HISTORY 1.5854400E+04 1.3000000E+01 3.1300000E+02 4.9727699E+04 3.3900000E+02 HISTORY 4.3300000E+02 9.6787102E+04 7.0100000E+02 1.6300000E+02 1.2378200E+04 HISTORY 8.5500000E+02 2.5500000E+02 3.5242898E+04 7.6100000E+02 3.3300000E+02 HISTORY 1.4904300E+04 1.0110000E+03 3.5700000E+02 2.5686801E+04 9.0700000E+02 HISTORY 4.0100000E+02 1.6969100E+04 8.4900000E+02 5.2500000E+02 1.4543700E+04 HISTORY 9.1700000E+02 5.4500000E+02 4.4644398E+04 7.7700000E+02 5.7700000E+02 HISTORY 3.6737199E+04 1.0010000E+03 6.9500000E+02 9.8214500E+04 8.2500000E+02 HISTORY 8.0100000E+02 2.0127900E+04 6.3100000E+02 6.3500000E+02 1.6520199E+04 HISTORY 5.8500000E+02 6.7500000E+02 1.5727300E+04 6.5900000E+02 6.6500000E+02 HISTORY 2.1833900E+04 HISTORY HISTORY 'DPROFILE' ,'R*4 ' , 1, 25,'5E14.7',' ',' ' HISTORY 3.2567519E-01 6.4562768E-01 6.5725815E-01 5.2960014E-01 4.1916752E-01 HISTORY 3.0000001E-01 2.8000000E-01 2.5999999E-01 2.3999999E-01 2.0000000E-01 HISTORY 1.8000001E-01 1.6000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 1.4000000E-01 HISTORY HISTORY ESO-DESCRIPTORS END ................ END EZvEYEYAEXEXEWeEVEV"EU~ETET3ESERER9EQEPEP8EOENEN1EMELEL#EKsEJEJEI_EHEGEGIEFEEEE3EDECECEBjEAEAE@WE?E>E>FE=E<E<9E;E:E:4E9E8E85E7E6E6@E5E4E4TE3E3E2tE1E1;E0E0E/qE.E.HE-E-&E,E,E+E*E*sE)E)lE(E(oE'E'}E'E&E&!E%E%FE$E$wE$E#E#TE"E"E"JE!E!E!WE!E E cE EEEEEEEEYE&EEEErEKE)EEEEEEE|EnEaEXEPELEHEHEJENEUE^EiEvEEEEEEE
E'EFEfEEEEE&EQE~EEEEBEwEEE E XE E E!E!DE!E!E"E"EE"E"E#E#YE#E#E$4E$~E$E%E%fE%E&E&VE&E&E'NE'E'E(NE(E(E)UE)E*E*bE*E+E+tE+E,/E,E,E-JE-E. E.iE.E/*E/E/E0OE0E1E1wE1E2=E2E3E3hE3E40E4E4E5\E5E6$E6E6E7PE7E8E8|E8E9BE9E:E:jE:E;.E;E;E<RE<E=E=tE=E>2E>E>E?JE?E@E@`E@EAEAnEXEX]EWEW*EVEUEUVETETESwERER2EQEPEPDEOENENKEMELELNEKEJEJLEIEHEHFEGEFEF=EEEDED4ECEBEB*EA}E@E@#E?vE>E>E=rE<E<E;tE:E:"E9zE8E8.E7E6E6AE5E4E4^E3E3"E2E1E1RE0E0$E/E.E.jE-E-LE,E,4E+E+%E*E*E)E)E(E('E'E':E&E&UE%E%{E%E$E$HE#E#E#+E"E"}E")E!E!E!<E E E JE EEtE2EEEEIEEEEEdE?EEEEEEEErEcEXENEFEBE@E?E@EEELEUE`EmE|EEEEEEEE>E_EEEEE ELEyEEEE@EuEEE E ZE E E!E!IE!E!E"E"NE"E"E# E#hE#E#E$FE$E$E%0E%E%E&$E&vE&E'E'tE'E("E(zE(E),E)E)E*>E*E*E+VE+E,E,tE,E-4E-E-E.ZE.E/ E/E/E0LE0E1E1{E1E2EE2E3E3xE3E4EE4E5E5yE5E6FE6E7E7{E7E8HE8E9E9{E9E:FE:E;E;wE;E<?E<E=E=iE=E>/E>E>E?RE?E@E@pE@EA.EAEAEBCEWhEVEVBEUEUET|ESESHEREREQrEPEP4EOENENOEMEMELcEKEKEJpEIEI"EHzEGEG*EFEEEE.EDECEC2EBEAEA7E@E?E?<E>E=E=DE<E;E;QE:E:E9bE8E8E7{E6E6:E5E4E4`E3E3*E2E1E1bE0E08E/E/E.E-E-lE,E,XE+E+LE*E*HE)E)JE(E(UE'E'jE&E&E&E%E%EE$E$zE$E#E#^E#E"E"ZE" E!E!qE!"E E E 4EEEaE EEEnE;EEEEEYE4EEEEEEExEhEZENEEE>E9E6E6E8E=EDELEWEdEtEEEEEEEE7EXE{EEEEEFEuEEEE=EtEEE E [E E E!E!NE!E!E"E"XE"E"E#-E#vE#E$
E$ZE$E$E%JE%E%E&@E&E&E'BE'E'E(LE(E) E)\E)E*E*tE*E+4E+E+E,VE,E-E-~E-E.FE.E/E/vE/E0BE0E1E1xE1E2HE2E3E3E3E4SE4E5&E5E5E6bE6E76E7E8E8rE8E9CE9E:E:~E:E;NE;E<E<E<E=RE=E>E>E>E?LE?E@E@vE@EA:EAEAEBZEBECEUEUNETET-ESESERqEQEQDEPEPEOtENEN<EMEMELbEKEK"EJEIEI=EHEGEGTEFEFEEhEDEDECzEBEB1EAE@E@BE?E>E>VE=E=E<kE;E;&E:E9E9CE8E8E7fE6E6,E5E4E4\E3E3,E2E2E1lE0E0HE/E/*E.E.E-E,E,xE+E+oE*E*mE)E)sE(E(E(E'E'&E&E&JE%E%vE%E$E$JE#E#E#6E"E"E"9E!E!E!VE! E E kE EEEPEEEEbE-EEEEvENE*EEEEEEEqE`EREFE>E6E2E0E0E2E6E<EEEPE]EnE~EEEEEEE1EREvEEEEEBEqEEEE<EsEEE "E ]E E E!E!TE!E!E"E"cE"E"E#<E#E#E$ E$oE$E%E%bE%E&
E&`E&E'E'gE'E(E(vE(E)0E)E)E*LE*E+E+pE+E,6E,E,E-bE-E..E.E.E/eE/E06E0E1E1rE1E2GE2E3E3E3E4_E4E56E5E6E6zE6E7SE7E8+E8E9E9oE9E:FE:E;E;E;E<]E<E=2E=E>E>lE>E?>E?E@
E@rE@EA<EAEBEBhEBEC,ECECETJESES4EREREQEPEPeEOEO=ENENEM|ELELKEKEKEJ{EIEICEHEHEGjEFEF,EEEDEDNECECEBnEAEA-E@E?E?LE>E>E=mE<E</E;E:E:VE9E9E8E7E7JE6E6E5E4E4QE3E3(E2E2E1qE0E0SE/E/:E.E.&E-E-E,E,E+E+E*E*E)E)!E(E(6E'E'SE&E&xE&E%E%@E$E$|E$E#E#iE#E"E"lE"E!E!E!?E E E XE EEEAEEEEVE"EEEEmEGE"E EEEEE}EkE[EMEAE8E1E,E*E*E,E0E7E@EJEXEgExEEEEEEE+EMEqEEEEE?EnEEEE:ErEEE $E `E E E!E!ZE!E!E"&E"mE"E"E#JE#E#E$4E$E$E%(E%|E%E&'E&E&E'1E'E'E(CE(E) E)^E)E* E*E*E+HE+E,E,xE,E-DE-E.E.~E.E/PE/E0&E0E0E1iE1E2CE2E3E3E3E4hE4E5DE5E6"E6E6E7oE7E8ME8E9*E9E:E:wE:E;SE;E<.E<E= E=wE=E>OE>E?'E?E?E@fE@EA7EAEBEBnEBEC;ECEDEDhEDERER1EQEQ EPEP EO~ENENaEMEM@ELELEKEJEJ\EIEI0EHEHEGhEFEF6EEEEEDhECEC1EBEAEA`E@E@(E?E>E>VE=E= E<E;E;OE:E:E9E8E8SE7E7%E6E5E5eE4E4>E3E3E2E1E1nE0E0VE/E/BE.E.4E-E-+E,E,(E+E++E*E*5E)E)FE(E(]E'E'}E'E&E&:E%E%pE%
E$E$NE#E#E#CE"E"E"LE!E!E!nE!)E E E EEEEtE4EEEELEEEEEeE@EEEEEEExEfEUEGE<E2E,E&E$E$E&E*E1E:EEEREaErEEEEEEE&EHElEEEE
E:EiEEEE8EpEEE $E aE E E!E!^E!E!E".E"vE"E#E#XE#E#E$FE$E$E%?E%E%E&CE&E&E'RE'E(E(lE(E),E)E)E*SE*E+E+E+E,PE,E-!E-E-E.`E.E/8E/E0E0~E0E1[E1E29E2E3E3E3E4jE4E5LE5E6/E6E7E7E7E8hE8E9LE9E:/E:E;E;E;E<eE<E=EE=E>$E>E?E?rE?E@ME@EA&EAEAEBiEBEC=ECEDEDuEDEEBEEEQEPEPEOEOENEMEMrELEL\EKEKCEJEJ$EIEIEHrEGEGNEFEF&EEEDEDhECEC>EBEBEA{E@E@NE?E?E>E=E=[E<E</E;E;E:nE9E9CE8E8E7E6E6dE5E5BE4E4"E3E3E2zE1E1dE0E0RE/E/DE.E.<E-E-8E,E,:E+E+BE*E*PE)E)dE(E(E(E'E'7E&E&fE%E%E%:E$E$|E$"E#E#rE#E"E"|E".E!E!E!XE!E E E 7EEEhE(EEEyEDEEEEE`E;EEEEEEEtEbEREDE8E/E(E#E E E"E&E.E6EAENE]EnEEEEEEE"EDEgEEEE E7EhEEE E7EpEEE %E cE E E!"E!eE!E!E"8E"E"E#E#fE#E$E$XE$E% E%VE%E&E&`E&E'E'vE'E(4E(E(E)XE)E* E*E*E+TE+E,&E,E,E-fE-E.>E.E/E/E/E0gE0E1HE1E2*E2E3E3E3E4hE4E5NE5E67E6E7 E7E8 E8~E8E9gE9E:PE:E;9E;E<"E<E=E=|E=E>bE>E?FE?E@)E@EA
EAxEAEBVEBEC2ECEDEDvEDEEJEEEFEFEOEOENENEMEMEL|EKEKpEJEJbEIEINEHEH9EGEGEFEFEEuEDEDWECEC6EBEBEAE@E@`E?E?<E>E>E=E<E<bE;E;?E:E:E9E8E8kE7E7ME6E60E5E5E4E3E3sE2E2`E1E1RE0E0FE/E/?E.E.<E-E-?E,E,FE+E+RE*E*eE)E)~E)E(E(0E'E'ZE&E&E&&E%E%bE%E$E$LE#E#E#JE"E"E"\E"E!E!E!BE!E E pE 'EEE[EEEEpE<E
EEEE[E5EEEEEEEpE^ENE@E4E+E$EEEEE"E)E1E;EHEXEhE|EEEEEEE=EaEEEEE3EcEEEE5EnEEE &E eE E E!&E!jE!E!E"?E"E"E#$E#sE#E$E$iE$E%E%mE%E& E&|E&E'7E'E'E(ZE(E) E)E)E*RE*E+"E+E+E,bE,E-<E-E.E.E.E/hE/E0JE0E10E1E2E2E3 E3uE3E4`E4E5ME5E6:E6E7(E7E8E8E9E9~E9E:mE:E;\E;E<JE<E=7E=E>$E>E?E?E?E@mE@EATEAEB:EBECECECEDmEDEEIEEEF"EFEFEGaEMEMlELELsEKEKxEJEJxEIEIrEHEHjEGEG`EFEFPEEEE@EDED-ECECEBEBEAuE@E@\E?E?CE>E>)E=E=E<E;E;gE:E:NE9E95E8E8E7E7E6}E5E5jE4E4YE3E3JE2E2@E1E18E0E02E/E/2E.E.6E-E->E,E,LE+E+^E*E*vE*E)E)$E(E(KE'E'xE'E&E&IE%E%E%+E$E$vE$E#E#wE#$E"E"E"?E!E!E!nE!.E E E aE EEEQEEEEiE6EEEE~EVE0EEEEEEEnE[EJE<E1E(E EEEEEE$E,E6ECEREcEvEEEEEEE7E\EEEE E.E^EEEE2ElEEE &E fE E E!(E!nE!E!E"FE"E"E#/E#E#E$%E${E$E%)E%E%E&:E&E&E'WE'E(E(~E(E)JE)E*E*E*E+XE+E,1E,E-E-~E-E._E.E/CE/E0+E0E1E1E2 E2wE2E3eE3E4VE4E5GE5E6;E6E7.E7E8#E8E9E9E:
E:E;E;{E;E<pE<E=cE=E>WE>E?HE?E@8E@EA(EAEBEBEBECtECED[EDEE?EEEF EFEG EGlEGEHFELDEKEKXEJEJdEIEIoEHEHvEGEGyEFEFyEEEEvEDEDpECEChEBEB]EAEAQE@E@BE?E?4E>E>%E=E=E<E<E;{E:E:kE9E9\E8E8NE7E7?E6E63E5E5)E4E4!E3E3E2E2E1E1E0E0E/E/ E.E.*E-E-:E,E,LE+E+dE*E*E*E)E)8E(E(dE'E'E'0E&E&lE&E%E%RE$E$E$IE#E#E#RE#E"E"mE"&E!E!E!\E!E E E UE EEEKEEEEfE4EEEE~EVE1EEEEEEEoE]ELE>E2E(E EEEEEE$E,E6ECEREbEuEEEEEEE6EZEEEEE-E^EEEE4EmEEE )E jE E E!/E!vE!E"E"QE"E"E#=E#E#E$8E$E$E%@E%E%E&VE&E'E'xE'E(BE(E)E)vE)E*JE*E+#E+E+E,nE,E-PE-E.5E.E/E/E0E0~E0E1nE1E2_E2E3RE3E4HE4E5>E5E67E6E70E7E8)E8E9#E9E:E:E;E;E<E<E=E=E>E>E? E?|E?E@sE@EAhEAEBZEBECLECED:EDEE(EEEFEFEFEGjEGEHLEHEI*EJEJ,EIEIDEHEH\EGEGmEFEF{EF EEEE
EDEDECECEBEBEAEAE@E@E?E?E>E> E=E=E<E;E;yE:E:tE9E9mE8E8gE7E7bE6E6_E5E5\E4E4[E3E3\E2E2aE1E1fE0E0pE/E/|E/E.E.E-E-*E,E,DE+E+bE*E*E*E)E)CE(E(tE(E'E'GE&E&E&(E%E%rE%E$E$mE$E#E#yE#+E"E"E"OE"
E!E!E!HE!E E E IE EEEBEEEEaE.EEEE{ETE/E
EEEEEEmEZEJE<E0E&EEEEEEE E(E2E?ENE^EpEEEEEEE0ETEzEEEE(EYEEEE0EkEEE )E jE E E!2E!xE!E"E"XE"E"E#HE#E#E$FE$E$E%TE%E&E&pE&E'4E'E'E(dE(E)6E)E*E*xE*E+TE+E,6E,E-E-E.E.xE.E/fE/E0VE0E1JE1E2@E2E38E3E42E4E5.E5E6+E6E7*E7E8)E8E9)E9E:*E:E;*E;E<+E<E=+E=E>+E>E?*E?E@(E@EA%EAEB EBECECEDEDEEEE|EEEFnEFEG\EGEHEEHEI,EIEJEHEHEHEGEG<EFEFXEEEEpEDEDEDECEC"EBEB0EAEA=E@E@FE?E?OE>E>UE=E=[E<E<`E;E;dE:E:gE9E9kE8E8oE7E7sE6E6xE5E5~E5E4E4
E3E3E2E2 E1E1.E0E0@E/E/TE.E.kE-E-E-E,E,4E+E+ZE*E*E*E)E)IE(E(E(E'E'YE&E&E&AE%E%E%6E$E$E$<E#E#E#RE#E"E"wE"2E!E!E!qE!5E E E E >EEEyE;E EEE\E,EEEEzESE.EEEEEEEnEZEJE<E0E&EEEEEEEE&E0E;EIEZEmEEEEEE
E,EPEvEEEE$EUEEEE.EjEEE )E kE E E!6E!~E!E"E"`E"E# E#SE#E#E$WE$E%
E%jE%E&)E&E&E'RE'E( E(E(E)_E)E*9E*E+E+E+E,pE,E-ZE-E.HE.E/:E/E0-E0E1$E1E2E2E3E3E4E4E5E5E6E6E7#E7E8'E8E9-E9E:3E:E;:E;E<AE<E=HE=E>NE>E?TE?E@XE@EA[EAEB]EBEC]ECED[EDEEVEEEFPEFEGFEGEH8EHEI(EIEJEJEJEGNEFEF|EFEEEE8EDED\ECEC|ECEBEB(EAEA@E@E@XE?E?nE>E>E> E=E=E<E<)E;E;9E:E:GE9E9TE8E8bE7E7qE6E6E6E5E5E4E4'E3E39E2E2NE1E1dE0E0{E0E/E/$E.E.CE-E-fE,E,E, E+E+JE*E*zE*E)E)JE(E(E($E'E'gE'
E&E&VE%E%E%RE$E$E$\E$
E#E#uE#,E"E"E"[E"E!E!E!^E!$E E E zE 5EEEsE6EEEE[E+EEEEzETE0EEEEEEEoE\ELE>E1E'EEEEEEEE%E/E:EJEYEkEEEEEEE)ELEsEEEE"EREEEE-EjEEE ,E nE E E!;E!E!E"E"hE"E#E#`E#E$
E$gE$E% E%E%E&BE&E'
E'pE'E(CE(E)E)E)E*gE*E+JE+E,3E,E- E-E.E.E/E/E/E0{E0E1xE1E2xE2E3zE3E4E5E5E6
E6E7E7E8E8E9(E9E:4E:E;BE;E<NE<E=[E=E>hE>E?sE?E@~EAEAEBEBECECEDEDEEEEEFEFEGEGEHEHEIEIEJEJ~EJEKlEKEEEE<EDEDqED
ECEC9EBEBdEAEAEA E@E@EE?E?hE>E>E>E=E=3E<E<OE;E;jE:E:E:E9E9(E8E8@E7E7XE6E6qE5E5E5E4E4/E3E3KE2E2gE1E1E1E0E05E/E/XE.E.~E.E-E-<E,E,jE,E+E+4E*E*jE*E)E)DE(E(E(&E'E'pE'E&E&eE&E%E%gE%E$E$xE$*E#E#E#ME#E"E"E">E!E!E!E!LE!E E E pE ,EEEoE3EEEEZE*EEEE|EVE2EEEEEEEpE^EME>E2E(E EEEEEEE#E-E8EFEVEhE|EEEEEE%EHEoEEEEENEEEE*EgEEE +E nE E E!<E!E!E" E"oE"E#E#jE#E$E$wE$E%3E%E%E&YE&E'%E'E'E(dE(E)?E)E* E*E+E+|E+E,hE,E-[E-E.QE.E/KE/E0IE0E1JE1E2NE2E3TE3E4^E4E5jE5E6wE6E7E8E8E9E9E:2E:E;DE;E<WE<E=kE=E>~E?E?E@E@EA*EAEB:EBECGECEDUEDEE^EEEFhEFEGlEGEHnEHEIoEIEJjEJEKcEKELVELECECEC3EBEBnEB
EAEA@E@E@tE@E?E?>E>E>jE>