Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5eea46e
cleanup
icweaver Oct 24, 2025
31ae4ff
Merge branch 'main' into photometry-migration
icweaver Oct 24, 2025
094e895
README cleanup
icweaver Oct 24, 2025
95def04
interpolator typo
icweaver Oct 24, 2025
b284dd2
toml cleanup
icweaver Oct 24, 2025
fd7a128
docs up
icweaver Oct 24, 2025
e66baf3
doc meta cleanup
icweaver Oct 24, 2025
16eb116
update CI workflow
icweaver Oct 24, 2025
1e9ee37
tests up
icweaver Oct 24, 2025
ffa1ac0
add Photometry.jl #75
icweaver Oct 24, 2025
4cd479d
import --> using
icweaver Oct 24, 2025
a91961d
explicit imports
icweaver Oct 24, 2025
84f8190
set prettyurls to true
icweaver Oct 24, 2025
b9790c5
v2 test framework
icweaver Oct 25, 2025
af24ac7
use [workspace]
icweaver Oct 25, 2025
12cbc8e
ci: auto threads
icweaver Oct 25, 2025
744f54c
just use single threaded parallel tests
icweaver Oct 25, 2025
8091c59
update test discovery
icweaver Oct 25, 2025
bfaac38
Update test/runtests.jl
icweaver Oct 25, 2025
bea83de
add compat
icweaver Oct 26, 2025
471c582
what u doin
icweaver Oct 26, 2025
0b45b12
ci: args test
icweaver Oct 26, 2025
25c64ab
ci: --verbose test
icweaver Oct 26, 2025
cf3c4d0
read a book ian
icweaver Oct 26, 2025
1d1dd1c
doc permissions
icweaver Oct 26, 2025
f40900d
ci: try to fix docs syntax
icweaver Oct 26, 2025
2197535
not needed, added keys separately
icweaver Oct 26, 2025
512480b
Update docs/make.jl
icweaver Oct 26, 2025
c5e0fc5
Update src/BackgroundMeshes.jl
icweaver Oct 26, 2025
b3e6342
Update test/Project.toml
icweaver Oct 26, 2025
c5c39c0
typo
icweaver Oct 26, 2025
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
13 changes: 10 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@ jobs:
strategy:
fail-fast: false
matrix:
version: ['1.6', '1', 'nightly']
os: [ubuntu-latest, macOS-latest, windows-latest]
arch: [x64]
version:
- "min"
- "1"
- "pre"
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- 'default'
steps:
- uses: actions/checkout@v5
- uses: julia-actions/setup-julia@v2
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ Interpolations = "0.12,0.13,0.14, 0.15, 0.16"
NearestNeighbors = "0.4"
Statistics = "1.6"
StatsBase = "0.28,0.29,0.30,0.31,0.32,0.33, 0.34"
julia = "1.6"
julia = "1.10"
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaAstro.github.io/BackgroundMeshes.jl/stable/)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaAstro.github.io/BackgroundMeshes.jl/dev/)

[![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/B/BackgroundMeshes.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/report.html)
[![Build Status](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml?query=branch%3Amain)
[![CI](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml?query=branch%3Amain)
[![Coverage](https://codecov.io/gh/JuliaAstro/BackgroundMeshes.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/JuliaAstro/BackgroundMeshes.jl)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)

Expand Down
8 changes: 3 additions & 5 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@ AstroImages = "fe3fc30c-9b16-11e9-1c73-17dabf39f4ad"
BackgroundMeshes = "b200be5e-c4c1-4b3d-840b-d423a53b46f3"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[sources]
BackgroundMeshes = {path = ".."}

[compat]
AstroImages = "0.5"
Documenter = "1"
FITSIO = "0.17"
Literate = "2"
Plots = "1"
StableRNGs = "1"
Statistics = "1"

[sources.BackgroundMeshes]
path = ".."
31 changes: 12 additions & 19 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
using BackgroundMeshes
using Documenter
using Documenter.Remotes: GitHub
using Literate: markdown

# preprocess tutorials using Literate
srcdir = abspath(joinpath(@__DIR__, "..", "examples"))
outdir = abspath(joinpath(@__DIR__, "src"))

examples = map(Iterators.filter(endswith(".jl"), readdir(srcdir; join=true))) do file
markdown(file, outdir)
return replace(basename(file), ".jl" => ".md")
end

# regular documenter process
DocTestSetup = quote
setup = quote
using BackgroundMeshes
using StableRNGs
rng = StableRNG(1)
end
DocMeta.setdocmeta!(BackgroundMeshes, :DocTestSetup, DocTestSetup; recursive=true)

DocMeta.setdocmeta!(BackgroundMeshes, :DocTestSetup, setup; recursive=true)

pages = [
"Home" => "index.md",
"Examples" => examples,
"Examples" => ["examples/1_basics.md", "examples/2_background_estimation.md"],
"API/Reference" => "api.md",
]

Expand All @@ -35,14 +25,17 @@ makedocs(;
prettyurls = get(ENV, "CI", "false") == "true",
canonical = "https://JuliaAstro.github.io/BackgroundMeshes.jl",
edit_link = "main",
assets = String[],
),
pages,
checkdocs = :exports,
)

# clean up markdown files generated by Literate
map(f -> rm(joinpath(outdir, f)), examples)

# CI only: deploy docs
deploydocs(; repo="github.com/JuliaAstro/BackgroundMeshes.jl", devbranch="main")
in_CI_env = get(ENV, "CI", "false") == "true"
if in_CI_env
deploydocs(;
repo = "github.com/JuliaAstro/BackgroundMeshes.jl",
push_preview = true,
devbranch = "main",
)
end
54 changes: 29 additions & 25 deletions examples/1. Basics.jl → docs/src/examples/1_basics.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#=
# 1. Basics

Let's dig into the basics of how these background meshes work. Let's start by creating some data.
For this image, I'll create a 2-D polynomial gradient across a 1000x1000 image.
=#
For this image, we'll create a 2-D polynomial gradient across a 1000x1000 image:

```@example ex
using AstroImages
using BackgroundMeshes
using Random
Expand All @@ -15,13 +15,13 @@ xs = range(0, 1; length=1000)
ys = xs'
data = xs .* ys
implot(data)
```

#=
## Mesh size

Background meshes are defined by a grid of sub-images across the original data. Within these sub-images we use various statistics to estimate the background signal. Here we show directly how the sub-image size (i.e., mesh size) affects the background estimation
=#
Background meshes are defined by a grid of sub-images across the original data. Within these sub-images we use various statistics to estimate the background signal. Here we show directly how the sub-image size (i.e., mesh size) affects the background estimation:

```@example ex
box_sizes = (10, 50, 100)
backgrounds = map(n -> first(estimate_background(data, n; location=mean)), box_sizes)
plot(
Expand All @@ -30,31 +30,36 @@ plot(
implot(backgrounds[3]; title="N=100", cbar=false);
layout=(1, 3),
)
```

#=
## Location Estimators

As mentioned above, statistics are calculated inside each of the sub-images. Depending on your workflow and data quality, you can choose between a variety of estimators
As mentioned above, statistics are calculated inside each of the sub-images. Depending on your workflow and data quality, you can choose between a variety of estimators:

1. `mean` or `median` from Statistics
2. [`SourceExtractorBackground`](@ref)
3. [`MMMBackground`](@ref)
4. [`BiweightLocationBackground`](@ref)
1. [`SourceExtractorBackground`](@ref)
1. [`MMMBackground`](@ref)
1. [`BiweightLocationBackground`](@ref)

See the [`LocationEstimator`](@ref BackgroundMeshes.LocationEstimator) docs for more information about each estimator. Let's create some data with outliers and look at how each estimator handles the outliers:

See the [`LocationEstimator`](@ref BackgroundMeshes.LocationEstimator) docs for more information about each estimator. Let's create some data with outliers and look at how each estimator handles the outliers
=#
```@example ex
true_background = 10
sub_img = randn(rng, 100, 100) .+ true_background
## add in hot pixels

# Add in hot pixels
x_idxs = rand(rng, axes(sub_img, 1), 50)
y_idxs = rand(rng, axes(sub_img, 2), 50)
for (x, y) in zip(x_idxs, y_idxs)
sub_img[x, y] = 2^16
end

implot(sub_img; clims=zscale(sub_img))
```

# now, how does each estimator compare
Let's see how each estimator compares:

```@example ex
bkgs = [
"mean" => mean(sub_img),
"median" => median(sub_img),
Expand All @@ -64,22 +69,22 @@ bkgs = [
]
scatter(first.(bkgs), last.(bkgs); lab="")
hline!([true_background]; c=:black, ls=:dash, lab="true value")
#=
```

here we see that `median` and [`BiweightLocationBackground`](@ref) do a good job of estimating the background despite the outliers, however the outliers can be removed ahead of time with a tool like [LACosmic.jl](https://github.com/JuliaAstro/LACosmic.jl).
Here we see that `median` and [`BiweightLocationBackground`](@ref) do a good job of estimating the background despite the outliers, however the outliers can be removed ahead of time with a tool like [LACosmic.jl](https://github.com/JuliaAstro/LACosmic.jl).

## RMS Estimators

Within each sub-image we also calulate the root-mean-square (RMS) estimate of noise, which can be forward propagated in your analysis.

1. [`StdRMS`](@ref)
2. [`MADStdRMS`](@ref)
3. [`BiweightScaleRMS`](@ref)
1. [`MADStdRMS`](@ref)
1. [`BiweightScaleRMS`](@ref)

See the [`RMSEstimator`](@ref BackgroundMeshes.RMSEstimator) docs for more information about each estimator. Let's create some data with outliers and look at how each estimator handles the outliers
=#
See the [`RMSEstimator`](@ref BackgroundMeshes.RMSEstimator) docs for more information about each estimator. Let's create some data with outliers and look at how each estimator handles the outliers:

## use same data before N(10, 1)
```@example ex
# Use same data before N(10, 1)
true_rms = 1
rmss = [
"std" => StdRMS()(sub_img),
Expand All @@ -88,7 +93,6 @@ rmss = [
]
scatter(first.(rmss), last.(rmss); lab="")
hline!([true_rms]; c=:black, ls=:dash, lab="true value")
```

#=
again, we see the median-based [`MADStdRMS`](@ref) as well as the [`BiweightScaleRMS`](@ref) do well despite the outliers.
=#
Again, we see the median-based [`MADStdRMS`](@ref) as well as the [`BiweightScaleRMS`](@ref) do well despite the outliers.
106 changes: 106 additions & 0 deletions docs/src/examples/2_background_estimation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# 2. Background Estimation on Real Data

Estimating backgrounds is an important step in performing photometry. Ideally, we could perfectly describe the background with a scalar value or with some distribution. Unfortunately, it's impossible for us to precisely separate the background and foreground signals. Here, we use mixture of robust statistical estimators and meshing to let us get the spatially varying background from an astronomical photo.

Let's show an example:

```@example ex
using AstroImages
using BackgroundMeshes
using FITSIO
using Plots

# Download our image, courtesy of astropy
url = "https://rawcdn.githack.com/astropy/photutils-datasets/8c97b4fa3a6c9e6ea072faeed2d49a20585658ba/data/M6707HH.fits"
hdu = FITS(download(url))
image = read(hdu[1])

# Plot
function imshow(image; kwargs...)
xs, ys = axes(image)
data = transpose(image)
heatmap(xs, ys, data;
aspect_ratio = 1,
xlim = extrema(xs),
ylim = extrema(ys),
kwargs...
)
end

imshow(image)
```

Now let's try and estimate the background using [`estimate_background`](@ref). First, we'll sigma-clip to try and remove the signals from the stars. Then, the background is broken down into boxes, in this case of size `(50, 50)`. Within each box, the given statistical estimators get the background value and RMS. By default, we use [`SourceExtractorBackground`](@ref) and [`StdRMS`](@ref). This creates a low-resolution image, which we then need to resize. We can accomplish this using an interpolator, by default a cubic-spline interpolator via [`ZoomInterpolator`](@ref). The end result is a smooth estimate of the spatially varying background and background RMS.

```@example ex
# Sigma-clip
clipped = sigma_clip(image, 1; fill=NaN)

# Get background and background rms with box-size (50, 50)
bkg, bkg_rms = estimate_background(clipped, 50)

# Plot
plot(
imshow(image; title="Original"),
imshow(clipped; title="Sigma-Clipped"),
imshow(bkg; title="Background"),
imshow(bkg_rms; title="Background RMS");
layout = (2, 2),
ticks = false,
)
```

We could apply a median filter, too, by specifying `filter_size`:

```@example ex
# Get background and background rms with box-size (50, 50) and filter_size (5, 5)
bkg_f, bkg_rms_f = estimate_background(clipped, 50; filter_size = 5)

# Plot
plot(
imshow(bkg; title="Unfiltered", ylabel="Background"),
imshow(bkg_f; title="Filtered"),
imshow(bkg_rms; ylabel="RMS"),
imshow(bkg_rms_f);
layout = (2, 2),
ticks = false,
)
```

Now we can see our image after subtracting the filtered background and ready for further analysis!

```@example ex
subt = image .- bkg_f[axes(image)...]

# Plot
plot(
imshow(image; title="Original", colorbar=false),
imshow(subt; title="Subtracted");
layout = (1, 2),
size = (600, 260),
xlims = (400, 800),
ylims = ( 400, 800),
clims = (minimum(subt), maximum(image)),
ticks = false,
aspect_ratio = 1,
)
```

### IDW Interpolator

Here is a quick example using the [`IDWInterpolator`](@ref):

```@example ex
b1, r1 = estimate_background(clipped, 50; filter_size=5)
b2, r2 = estimate_background(clipped, 50; itp=IDWInterpolator(50), filter_size=5)

# Plot
plot(
imshow(b1; title="ZoomInterpolator", ylabel="Background"),
imshow(b2; title="IDWInterpolator"),
imshow(r1; ylabel="RMS"),
imshow(r2);
layout = (2, 2),
ticks = false,
)
```
26 changes: 7 additions & 19 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
```@meta
CurrentModule = BackgroundMeshes
```

# BackgroundMeshes.jl

[![Code](https://img.shields.io/badge/Code-GitHub-black.svg)](https://github.com/JuliaAstro/BackgroundMeshes.jl)
[![Build Status](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml?query=branch%3Amain)
[![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/B/BackgroundMeshes.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/report.html)
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaAstro.github.io/BackgroundMeshes.jl/stable/)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaAstro.github.io/BackgroundMeshes.jl/dev/)

[![CI](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/JuliaAstro/BackgroundMeshes.jl/actions/workflows/CI.yml?query=branch%3Amain)
[![Coverage](https://codecov.io/gh/JuliaAstro/BackgroundMeshes.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/JuliaAstro/BackgroundMeshes.jl)
[![License](https://img.shields.io/github/license/JuliaAstro/BackgroundMeshes.jl?color=yellow)](https://github.com/JuliaAstro/BackgroundMeshes.jl/blob/main/LICENSE)
[![License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)

Create meshes for estimating the background in astronomical images. Originally a submodule of [Photometry.jl](https://github.com/JuliaAstro/Photometry.jl).

## Installation
## Quickstart

Currently, this package is unregistered and must be installed directly from this repository using the built-in package manager

```julia-repl
julia> ]
# Or, using Pkg; Pkg.add(url = "https://github.com/JuliaAstro/BackgroundMeshes.jl")
pkg> add https://github.com/JuliaAstro/BackgroundMeshes.jl
```

```julia-repl
julia> using Pkg; Pkg.add("https://github.com/JuliaAstro/BackgroundMeshes.jl")
```

To load this package

```julia-repl
julia> using BackgroundMeshes
```

For more information, see the [Pkg documentation](https://docs.julialang.org/en/v1/stdlib/Pkg/).

## Contributing and Support

If you would like to contribute, feel free to open a [pull request](https://github.com/JuliaAstro/BackgroundMeshes.jl/pulls). If you want to discuss something before contributing, head over to [discussions](https://github.com/JuliaAstro/BackgroundMeshes.jl/discussions) and join or open a new topic. If you're having problems with something, please open an [issue](https://github.com/JuliaAstro/BackgroundMeshes.jl/issues).
Expand Down
Loading
Loading