Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ jobs:
strategy:
matrix:
include:
- name: Code style checks
os: ubuntu-latest
python: 3.x
toxenv: codestyle

- name: Python 3.10 with minimal dependencies
os: ubuntu-latest
python: '3.10'
Expand Down
66 changes: 66 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
ci:
autofix_prs: false
autoupdate_schedule: 'monthly'

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-added-large-files
args: ["--enforce-all", "--maxkb=300"]
exclude: "^(\
cextern/wcslib/C/flexed/.*|\
CHANGES.rst|\
)$"
# Prevent giant files from being committed.
- id: check-case-conflict
# Check for files with names that would conflict on a case-insensitive
# filesystem like MacOS HFS+ or Windows FAT.
- id: check-json
# Attempts to load all json files to verify syntax.
- id: check-merge-conflict
# Check for files that contain merge conflict strings.
- id: check-symlinks
# Checks for symlinks which do not point to anything.
- id: check-toml
# Attempts to load all TOML files to verify syntax.
- id: check-xml
# Attempts to load all xml files to verify syntax.
- id: check-yaml
# Attempts to load all yaml files to verify syntax.
exclude: ".*(.github.*)$"
- id: detect-private-key
# Checks for the existence of private keys.
- id: end-of-file-fixer
# Makes sure files end in a newline and only a newline.
exclude: ".*(data.*|extern.*|licenses.*|_static.*|_parsetab.py)$"
# - id: fix-encoding-pragma # covered by pyupgrade
- id: trailing-whitespace
# Trims trailing whitespace.
exclude_types: [python] # Covered by Ruff W291.
exclude: ".*(data.*|extern.*|licenses.*|_static.*)$"

- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: rst-directive-colons
# Detect mistake of rst directive not ending with double colon.
- id: rst-inline-touching-normal
# Detect mistake of inline code touching normal text in rst.
- id: text-unicode-replacement-char
# Forbid files which have a UTF-8 Unicode replacement character.

- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
args: ["--write-changes"]
additional_dependencies:
- tomli

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]
- id: ruff-format
2 changes: 1 addition & 1 deletion astropy_healpix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Packages may add whatever they like to this file, but
# should keep this content at the top.
# ----------------------------------------------------------------------------
from ._astropy_init import * # noqa
from ._astropy_init import * # noqa
# ----------------------------------------------------------------------------

from .high_level import * # noqa
Expand Down
5 changes: 3 additions & 2 deletions astropy_healpix/_astropy_init.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
import os

__all__ = ['__version__', 'test']
__all__ = ["__version__", "test"]

try:
from .version import version as __version__
except ImportError:
__version__ = ''
__version__ = ""

# Create the test function for self test
from astropy.tests.runner import TestRunner

test = TestRunner.make_test_runner_in(os.path.dirname(__file__))
189 changes: 122 additions & 67 deletions astropy_healpix/bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@


# Copied from https://github.com/kwgoodman/bottleneck/blob/master/bottleneck/benchmark/autotimeit.py
def autotimeit(stmt, setup='pass', repeat=3, mintime=0.2):
def autotimeit(stmt, setup="pass", repeat=3, mintime=0.2):
timer = timeit.Timer(stmt, setup)
number, time1 = autoscaler(timer, mintime)
time2 = timer.repeat(repeat=repeat - 1, number=number)
Expand All @@ -47,89 +47,105 @@
if time > mintime:
return number, time
number *= 10
raise RuntimeError('function is too fast to test')
raise RuntimeError("function is too fast to test")

Check warning on line 50 in astropy_healpix/bench.py

View check run for this annotation

Codecov / codecov/patch

astropy_healpix/bench.py#L50

Added line #L50 was not covered by tests


def get_import(package, function):
if package == 'astropy_healpix':
return f'from astropy_healpix.healpy import {function}'
if package == "astropy_healpix":
return f"from astropy_healpix.healpy import {function}"
else:
return f'from healpy import {function}'
return f"from healpy import {function}"


def bench_pix2ang(size=None, nside=None, nest=None, package=None, fast=False):
setup = '\n'.join([
get_import(package, 'pix2ang'),
'import numpy as np',
f'nside={nside}',
f'ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)',
f'nest={nest}'])

stmt = 'pix2ang(nside, ipix, nest)'
setup = "\n".join(
[
get_import(package, "pix2ang"),
"import numpy as np",
f"nside={nside}",
f"ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)",
f"nest={nest}",
]
)

stmt = "pix2ang(nside, ipix, nest)"

return autotimeit(stmt=stmt, setup=setup, repeat=1, mintime=0 if fast else 0.1)


def bench_ang2pix(size=None, nside=None, nest=None, package=None, fast=False):
setup = '\n'.join([
get_import(package, 'ang2pix'),
'import numpy as np',
f'nside={nside}',
f'lon=360 * np.random.random({size})',
f'lat=180 * np.random.random({size}) - 90',
f'nest={nest}'])

stmt = 'ang2pix(nside, lon, lat, nest, lonlat=True)'
setup = "\n".join(
[
get_import(package, "ang2pix"),
"import numpy as np",
f"nside={nside}",
f"lon=360 * np.random.random({size})",
f"lat=180 * np.random.random({size}) - 90",
f"nest={nest}",
]
)

stmt = "ang2pix(nside, lon, lat, nest, lonlat=True)"

return autotimeit(stmt=stmt, setup=setup, repeat=1, mintime=0 if fast else 0.1)


def bench_nest2ring(size=None, nside=None, package=None, fast=False):
setup = '\n'.join([
get_import(package, 'nest2ring'),
'import numpy as np',
f'nside={nside}',
f'ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)'])
setup = "\n".join(
[
get_import(package, "nest2ring"),
"import numpy as np",
f"nside={nside}",
f"ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)",
]
)

stmt = 'nest2ring(nside, ipix)'
stmt = "nest2ring(nside, ipix)"

return autotimeit(stmt=stmt, setup=setup, repeat=1, mintime=0 if fast else 0.1)


def bench_ring2nest(size=None, nside=None, package=None, fast=False):
setup = '\n'.join([
get_import(package, 'ring2nest'),
'import numpy as np',
f'nside={nside}',
f'ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)'])
setup = "\n".join(
[
get_import(package, "ring2nest"),
"import numpy as np",
f"nside={nside}",
f"ipix=(np.random.random({size}) * 12 * nside ** 2).astype(np.int64)",
]
)

stmt = 'ring2nest(nside, ipix)'
stmt = "ring2nest(nside, ipix)"

return autotimeit(stmt=stmt, setup=setup, repeat=1, mintime=0 if fast else 0.1)


def bench_get_interp_weights(size=None, nside=None, nest=None, package=None, fast=False):
setup = '\n'.join([
get_import(package, 'get_interp_weights'),
'import numpy as np',
f'nside={nside}',
f'lon=360 * np.random.random({size})',
f'lat=180 * np.random.random({size}) - 90',
f'nest={nest}'])
def bench_get_interp_weights(
size=None, nside=None, nest=None, package=None, fast=False
):
setup = "\n".join(
[
get_import(package, "get_interp_weights"),
"import numpy as np",
f"nside={nside}",
f"lon=360 * np.random.random({size})",
f"lat=180 * np.random.random({size}) - 90",
f"nest={nest}",
]
)

stmt = 'get_interp_weights(nside, lon, lat, nest=nest, lonlat=True)'
stmt = "get_interp_weights(nside, lon, lat, nest=nest, lonlat=True)"

return autotimeit(stmt=stmt, setup=setup, repeat=1, mintime=0 if fast else 0.1)


def run_single(name, benchmark, fast=False, **kwargs):

time_self = benchmark(package='astropy_healpix', fast=fast, **kwargs)
time_self = benchmark(package="astropy_healpix", fast=fast, **kwargs)
results_single = dict(function=name, time_self=time_self, **kwargs)

if HEALPY_INSTALLED:
time_healpy = bench_ang2pix(package='healpy', fast=fast, **kwargs)
results_single['time_healpy'] = time_healpy
time_healpy = bench_ang2pix(package="healpy", fast=fast, **kwargs)
results_single["time_healpy"] = time_healpy

return results_single

Expand All @@ -146,60 +162,99 @@
for nest in [True, False]:
for size in SIZES:
for nside in [1, 128]:
results.append(run_single('pix2ang', bench_pix2ang, fast=fast,
size=size, nside=nside, nest=nest))
results.append(
run_single(
"pix2ang",
bench_pix2ang,
fast=fast,
size=size,
nside=nside,
nest=nest,
)
)

for nest in [True, False]:
for size in SIZES:
for nside in [1, 128]:
results.append(run_single('ang2pix', bench_ang2pix, fast=fast,
size=size, nside=nside, nest=nest))
results.append(
run_single(
"ang2pix",
bench_ang2pix,
fast=fast,
size=size,
nside=nside,
nest=nest,
)
)

for size in SIZES:
for nside in [1, 128]:
results.append(run_single('nest2ring', bench_nest2ring, fast=fast,
size=size, nside=nside))
results.append(
run_single(
"nest2ring", bench_nest2ring, fast=fast, size=size, nside=nside
)
)

for size in SIZES:
for nside in [1, 128]:
results.append(run_single('ring2nest', bench_ring2nest, fast=fast,
size=size, nside=nside))
results.append(
run_single(
"ring2nest", bench_ring2nest, fast=fast, size=size, nside=nside
)
)

for nest in [True, False]:
for size in SIZES:
for nside in [1, 128]:
results.append(run_single('get_interp_weights', bench_get_interp_weights,
fast=fast, size=size,
nside=nside, nest=nest))
results.append(
run_single(
"get_interp_weights",
bench_get_interp_weights,
fast=fast,
size=size,
nside=nside,
nest=nest,
)
)

return results


def bench_report(results):
"""Print a report for given benchmark results to the console."""

table = Table(names=['function', 'nest', 'nside', 'size',
'time_healpy', 'time_self', 'ratio'],
dtype=['S20', bool, int, int, float, float, float], masked=True)
table = Table(
names=[
"function",
"nest",
"nside",
"size",
"time_healpy",
"time_self",
"ratio",
],
dtype=["S20", bool, int, int, float, float, float],
masked=True,
)
for row in results:
table.add_row(row)

table['time_self'].format = '10.7f'
table["time_self"].format = "10.7f"

if HEALPY_INSTALLED:
table['ratio'] = table['time_self'] / table['time_healpy']
table['time_healpy'].format = '10.7f'
table['ratio'].format = '7.2f'
table["ratio"] = table["time_self"] / table["time_healpy"]
table["time_healpy"].format = "10.7f"
table["ratio"].format = "7.2f"

table.pprint(max_lines=-1)


def main(fast=False):
"""Run all benchmarks and print report to the console."""
print('Running benchmarks...\n')
print("Running benchmarks...\n")
results = bench_run(fast=fast)
bench_report(results)


if __name__ == '__main__':
if __name__ == "__main__":
main()
Loading
Loading