Skip to content
Merged
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
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.4.3"
[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Expand All @@ -16,4 +17,5 @@ DelimitedFiles = "1"
LinearAlgebra = "1"
Printf = "1"
StaticArrays = "0.5, 0.6, 0.7, 0.8, 0.9, 0.10, 0.11, 0.12, 1.0"
Interpolations = "0.13.4"
julia = "1.10"
1 change: 1 addition & 0 deletions src/AstroLib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ __precompile__()
module AstroLib
using Dates, LinearAlgebra, Printf
using StaticArrays
using Interpolations

# Note on function definitions in this package. Most functions are defined as
# follows:
Expand Down
248 changes: 248 additions & 0 deletions src/frebin.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# This file is a part of AstroLib.jl. License is MIT "Expat".
# Copyright (C) 2016 Mosè Giordano.

function _frebin(image::AbstractArray{T}, nsout::S, nlout::S, total::Bool) where {T<:AbstractFloat,S<:Integer}

Check warning on line 4 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L4

Added line #L4 was not covered by tests

# Determine the size of the input array
ns = size(image, 1)
nl = length(image)/ns

Check warning on line 8 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L7-L8

Added lines #L7 - L8 were not covered by tests

# Determine if the new sizes are integral factors of the original sizes
sbox = ns/nsout
lbox = nl/nlout

Check warning on line 12 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L11-L12

Added lines #L11 - L12 were not covered by tests

# Contraction by an integral amount
if (sbox == round(Int, sbox)) && (lbox == round(Int, lbox)) && (ns % nsout == 0) && (nl % nlout == 0)
array_shaped = reshape(image, (Int(sbox), nsout, Int(lbox), nlout))
return dropdims(sum(array_shaped, dims=(1,3)), dims=(1,3)) .* (total ? 1.0 : 1 ./ (sbox.*lbox))

Check warning on line 17 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L15-L17

Added lines #L15 - L17 were not covered by tests
end

# Expansion by an integral amount
if (nsout % ns == 0) && (nlout % nl == 0)
xindex = (1:nsout) / (nsout/ns)
if isone(nl) # 1D case, linear interpolation
interpfunc = extrapolate(interpolate(image, BSpline(Constant())), Flat())
return interpfunc(xindex) * (total ? sbox : 1.)

Check warning on line 25 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L21-L25

Added lines #L21 - L25 were not covered by tests
end
yindex = (1:nlout) / (nlout/nl)
interpfunc = extrapolate(interpolate(image, BSpline(Constant())), Flat())
return [interpfunc(x, y) for x in xindex, y in yindex] .* (total ? sbox.*lbox : 1.)

Check warning on line 29 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L27-L29

Added lines #L27 - L29 were not covered by tests
end

ns1 = ns-1
nl1 = nl-1

Check warning on line 33 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L32-L33

Added lines #L32 - L33 were not covered by tests

# Do 1D case separately
if isone(nl)
result = zeros(eltype(image), nsout)
for i ∈ 0:nsout-1
rstart = i*sbox # starting position for each box
istart = floor(Int, rstart)
rstop = rstart + sbox # ending position for each box
istop = Int(clamp(floor(rstop), 0, ns1))
frac1 = rstart-istart
frac2 = 1.0 - (rstop-istop)

Check warning on line 44 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L36-L44

Added lines #L36 - L44 were not covered by tests

# add pixel values from istart to istop and subtract fractional pixel from istart to start and
# fractional pixel from rstop to istop

result[i+1] = sum(image[istart+1:istop+1]) - frac1*image[istart+1] - frac2*image[istop+1]
end
return result .* (total ? 1.0 : 1 ./ (sbox.*lbox))

Check warning on line 51 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L49-L51

Added lines #L49 - L51 were not covered by tests
end

# Now, do 2D case
# First, bin second dimension
temp = zeros(eltype(image), ns, nlout)

Check warning on line 56 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L56

Added line #L56 was not covered by tests
# Loop on output image lines
for i ∈ 0:nlout-1
rstart = i*lbox # starting position for each box
istart = floor(Int, rstart)
rstop = rstart + lbox
istop = Int(clamp(floor(rstop), 0, nl1))
frac1 = rstart-istart
frac2 = 1.0 - (rstop-istop)

Check warning on line 64 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L58-L64

Added lines #L58 - L64 were not covered by tests

# add pixel values from istart to istop and subtract fractional pixel from istart to start and
# fractional pixel from rstop to istop

if istart == istop
temp[:,i+1] .= (1 .- frac1 .- frac2).*image[:,istart+1]

Check warning on line 70 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L69-L70

Added lines #L69 - L70 were not covered by tests
else
temp[:,i+1] .= dropdims(sum(image[:,istart+1:istop+1], dims=2), dims=2) .- frac1.*image[:,istart+1] .- frac2.*image[:,istop+1]

Check warning on line 72 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L72

Added line #L72 was not covered by tests
end
end
temp = temp'

Check warning on line 75 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L74-L75

Added lines #L74 - L75 were not covered by tests
# Bin in first dimension
result = zeros(eltype(image), nlout, nsout)

Check warning on line 77 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L77

Added line #L77 was not covered by tests
# Loop on output image samples
for i ∈ 0:nsout-1
rstart = i*sbox # starting position for each box
istart = floor(Int, rstart)
rstop = rstart + sbox # ending position for each box
istop = Int(clamp(floor(rstop), 0, ns1))
frac1 = rstart-istart
frac2 = 1.0 - (rstop-istop)

Check warning on line 85 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L79-L85

Added lines #L79 - L85 were not covered by tests

# add pixel values from istart to istop and subtract fractional pixel from istart to start and
# fractional pixel from rstop to istop

if istart == istop
result[:,i+1] .= (1 .- frac1 .- frac2).*temp[:,istart+1]

Check warning on line 91 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L90-L91

Added lines #L90 - L91 were not covered by tests
else
result[:,i+1] .= dropdims(sum(temp[:,istart+1:istop+1], dims=2), dims=2) .- frac1.*temp[:,istart+1] .- frac2.*temp[:,istop+1]

Check warning on line 93 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L93

Added line #L93 was not covered by tests
end
end
return transpose(result) .* (total ? 1.0 : 1 ./ (sbox.*lbox))

Check warning on line 96 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L95-L96

Added lines #L95 - L96 were not covered by tests

end

"""
frebin(image, nsout, nlout=1, total=false) -> rebinned_image

### Purpose ###

Shrink or expand the size of an array an arbitrary amount using interpolation

### Arguments ###

* `image`: the array representing the 1D or 2D image to be rebinned.
* `nsout`: number of samples in the output image, numeric scalar.
* `nlout` (optional): number of lines in the output image, numeric scalar (default = 1).
* `total` (optional boolean keyword): if true, the output pixels will be the
sum of pixels within the appropriate box of the input image.
Otherwise they will be the average. Use of the `total` keyword
conserves total counts.

### Output ###

The resized image is returned as the function result.

### Examples ###

Suppose one has an 800 x 800 image array, im, that must be expanded to
a size 850 x 900 while conserving the total counts. The pixel values are
the sum of the x and y coordinates in the original image:

```jldoctest
julia> using AstroLib

julia> image = [x+y for x in 1:800, y in 1:800];

julia> size(image)
(800, 800)

julia> sum(image)
512640000

julia> image1 = frebin(image, 850, 900, total=true);

julia> size(image1)
(850, 900)

julia> sum(image1) ≈ sum(image)
true
```

If the new dimensions are integer ratios of the original
dimensions, some optimizations can be performed. We can
also choose to preserve the *average* pixel value rather
than the *total* pixel value in the image:

```jldoctest
julia> using AstroLib

julia> image = [x+y for x in 1:800, y in 1:800];

julia> size(image)
(800, 800)

julia> sum(image)/length(image)
801.0

julia> image1 = frebin(image, 400, 400, total=false);

julia> size(image1)
(400, 400)

julia> (sum(image1)/length(image1)) ≈ (sum(image)/length(image))
true

julia> image2 = frebin(image, 1600, 1600, total=false);

julia> size(image2)
(1600, 1600)

julia> (sum(image2)/length(image2)) ≈ (sum(image)/length(image))
true
```

Of course, this works with 1D arrays as well:

```jldoctest
julia> using AstroLib

julia> image = [x for x in 1:800];

julia> size(image)
(800,)

julia> sum(image)
320400

julia> sum(image)/length(image)
400.5

julia> image1 = frebin(image, 1600);

julia> size(image1)
(1600,)

julia> (sum(image1)/length(image1)) ≈ (sum(image)/length(image))
true

julia> image2 = frebin(image, 410, total=true);

julia> size(image2)
(410,)

julia> sum(image2) ≈ sum(image)
true
```

### Notes ###

If the input image sizes are a multiple of the output image sizes
then `frebin` is equivalent to summing over the grid multiples for
compression, and simple pixel duplication on expansion.

If the number of output pixels are not integers, the output image
size will be truncated to an integer. The platescale, however, will
reflect the non-integer number of pixels. For example, if you want to
bin a 100 x 100 integer image such that each output pixel is 3.1
input pixels in each direction use:
n = 100/3.1 # 32.2581
image_out = frebin(image,n,n)

The output image will be 32 x 32 and a small portion at the trailing
edges of the input image will be ignored.

### History ###

Adapted from May 1998 STIS version, written D. Lindler, ACC
Added /NOZERO, use INTERPOLATE instead of CONGRID, June 98 W. Landsman
Fixed for nsout non-integral but a multiple of image size Aug 98 D.Lindler
DJL, Oct 20, 1998, Modified to work for floating point image sizes when
expanding the image.
Improve speed by addressing arrays in memory order W.Landsman Dec/Jan 2001

Code of this function is based on IDL Astronomy User's Library.
"""
function frebin(image::AbstractArray{R}, nsout::Real, nlout::Real=1; total::Bool=false) where {R<:Real}

Check warning on line 241 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L241

Added line #L241 was not covered by tests

# check that the image dimensions are either 1D or 2D
nd = ndims(image)
@assert nd in (1,2) "The input image must be either 1D or 2D!"

Check warning on line 245 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L244-L245

Added lines #L244 - L245 were not covered by tests

_frebin(float(image), promote(floor(Int, nsout), floor(Int, nlout))..., total)

Check warning on line 247 in src/frebin.jl

View check run for this annotation

Codecov / codecov/patch

src/frebin.jl#L247

Added line #L247 was not covered by tests
end
97 changes: 97 additions & 0 deletions src/fshift.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# This file is a part of AstroLib.jl. License is MIT "Expat".
# Copyright (C) 2016 Mosè Giordano.

function _fshift(image::AbstractArray{T}, Δx::T, Δy::T) where {T<:AbstractFloat}

Check warning on line 4 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L4

Added line #L4 was not covered by tests

# Separate shift into an integer and fractional shift
intx = floor(Int, Δx)
inty = floor(Int, Δy)
fracx = Δx - intx
fracy = Δy - inty

Check warning on line 10 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L7-L10

Added lines #L7 - L10 were not covered by tests
# note: the idl version has branches checking if fracx and fracy are negative.
# these are not necessary here because we're using the floor function rather than
# a truncation of a float to an integer, so intx/y will always be <= Δx/y.

# Shift by the integer portion
s = circshift(image, (intx, inty))
if iszero(fracx) && iszero(fracy)
return s

Check warning on line 18 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L16-L18

Added lines #L16 - L18 were not covered by tests
end

# Use bilinear interpolation between four pixels
return s .* ((1 .- fracx) .* (1 .- fracy)) .+

Check warning on line 22 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L22

Added line #L22 was not covered by tests
circshift(s, (0,1)) .* ((1 .- fracx) .* fracy) .+
circshift(s, (1,0)) .* (fracx .* (1 .- fracy)) .+
circshift(s, (1,1)) .* fracx .* fracy
end

"""
fshift(image, Δx, Δy) -> shifted_image

### Purpose ###

Routine to shift an image by non-integer values

### Arguments ###

* `image`: 2D image to be shifted.
* `Δx`: shift in x
* `Δy`: shift in y

### Output ###

Shifted image is returned as the function results

### Example ###

Suppose we want to shift a 10x10 image by 0.5 pixels in the
x and y directions. The pixel values are the sum of the x and
y coordinates:

```jldoctest
julia> using AstroLib

julia> image = [x+y for x in 1:10, y in 1:10];

julia> fshift(image, 0.5, 0.5)
10×10 Matrix{Float64}:
11.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
7.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0
8.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0
9.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0
10.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0
11.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
12.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0
13.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0
14.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0
15.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0

julia> fshift(image, -3, -1)
10×10 Matrix{Float64}:
6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 5.0
7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 6.0
8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 7.0
9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 8.0
10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 9.0
11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 10.0
12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 20.0 11.0
3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 2.0
4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 3.0
5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 4.0
```

### History ###

version 2 D. Lindler May, 1992 - rewritten for IDL version 2
19-may-1992 JKF/ACC - move to GHRS DAF.

Code of this function is based on IDL Astronomy User's Library.

"""
function fshift(image::AbstractArray{R}, Δx::Real, Δy::Real) where {R<:Real}

Check warning on line 91 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L91

Added line #L91 was not covered by tests
# check that the image dimensions are 2D
nd = ndims(image)
@assert nd == 2 "The input image must be 2D!"

Check warning on line 94 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L93-L94

Added lines #L93 - L94 were not covered by tests

_fshift(float(image), promote(float(Δx), float(Δy))...)

Check warning on line 96 in src/fshift.jl

View check run for this annotation

Codecov / codecov/patch

src/fshift.jl#L96

Added line #L96 was not covered by tests
end
6 changes: 6 additions & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ export euler
include("flux2mag.jl")
export flux2mag

include("frebin.jl")
export frebin

include("fshift.jl")
export fshift

include("gal_uvw.jl")
export gal_uvw

Expand Down
Loading