Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for RGB #22

Merged
merged 5 commits into from
Aug 20, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Interact = "c601a237-2ae4-5e1e-952c-7a85b0c7eef1"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Reproject = "d1dcc2e6-806e-11e9-2897-3f99785db2ae"
WCS = "15f3aee2-9e10-537f-b834-a6fb8bdb944d"
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"

[compat]
julia = "^1.0.0"
Expand Down
41 changes: 32 additions & 9 deletions src/AstroImages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ __precompile__()

module AstroImages

using FITSIO, FileIO, Images, Interact, Reproject, WCS
using FITSIO, FileIO, Images, Interact, Reproject, WCS, MappedArrays

export load, AstroImage, ccd2rgb

Expand Down Expand Up @@ -85,9 +85,21 @@ for n in (8, 16, 32, 64)
end
end

struct AstroImage{T<:Real,C<:Color, N}
mutable struct Properties{P <: Union{AbstractFloat, FixedPoint}}
rgb_image::MappedArrays.MultiMappedArray{RGB{P},2,Tuple{Array{P,2},Array{Float64,2},Array{P,2}},Type{RGB{P}},typeof(ImageCore.extractchannels)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That Float64 should probably be P?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, missed that

function Properties{P}(;kvs...) where P
obj = new{P}()
for (k,v) in kvs
setproperty!(obj, k, v)
end
return obj
end
end

struct AstroImage{T<:Real,C<:Color, N, P}
data::NTuple{N, Matrix{T}}
wcs::NTuple{N, WCSTransform}
property::Properties{P}
end

"""
Expand All @@ -97,13 +109,22 @@ end
Construct an `AstroImage` object of `data`, using `color` as color map, `Gray` by default.
"""
AstroImage(color::Type{<:Color}, data::Matrix{T}, wcs::WCSTransform) where {T<:Real} =
AstroImage{T,color, 1}((data,), (wcs,))
AstroImage(color::Type{<:Color}, data::NTuple{N, Matrix{T}}, wcs::NTuple{N, WCSTransform}) where {T<:Real, N} =
AstroImage{T,color, N}(data, wcs)
AstroImage(data::Matrix{T}) where {T<:Real} = AstroImage{T,Gray,1}((data,), (WCSTransform(2),))
AstroImage(data::NTuple{N, Matrix{T}}) where {T<:Real, N} = AstroImage{T,Gray,N}(data, ntuple(i-> WCSTransform(2), N))
AstroImage(data::Matrix{T}, wcs::WCSTransform) where {T<:Real} = AstroImage{T,Gray,1}((data,), (wcs,))
AstroImage(data::NTuple{N, Matrix{T}}, wcs::NTuple{N, WCSTransform}) where {T<:Real, N} = AstroImage{T,Gray,N}(data, wcs)
AstroImage{T,color, 1, AbstractFloat}((data,), (wcs,), Properties{AbstractFloat}())
function AstroImage(color::Type{<:Color}, data::NTuple{N, Matrix{T}}, wcs::NTuple{N, WCSTransform}) where {T<:Real, N}
if N == 3 && color == RGB && T <: Union{AbstractFloat, FixedPoint}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not

if N == 3 && color == RGB
    if T <: Union{AbstractFloat, FixedPoint}
        ...
    else
        ...
    end

instead of repeating conditions multiple times?

Actually, why not using multiple method instead of having runtime checks on parameters?

img = ccd2rgb((data[1], wcs[1]),(data[2], wcs[2]),(data[3], wcs[3]))
return AstroImage{T,color,N, widen(T)}(data, wcs, Properties{widen(T)}(rgb_image = img))
elseif N == 3 && color == RGB
img = ccd2rgb((data[1], wcs[1]),(data[2], wcs[2]),(data[3], wcs[3]))
return AstroImage{T,color,N, AbstractFloat}(data, wcs, Properties{AbstractFloat}(rgb_image = img))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the parameter is abstract here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giordano The parameter is Abstract here for the following reasons:

  • When we fixed the MappedArrays type for rgb_image, the RGB subtype in it can only have P as an AbstractFloat or FixedPoint numbers.
  • Also, note that we are not filling rgb_image in all cases. So, when I simply passed T as a parameter (as done in the previous commit), it generated errors when T was not AbstractFloat or FixedPoint.
  • A solution for this was to pass a valid parameter just for the sake of passing it (when rgb_image is not getting filled). That's what is done except in one case where rgb_image is filled and the type isn't a valid one. The type needs to be in the above-mentioned domain as per Images.jl.

else
return AstroImage{T,color, N, AbstractFloat}(data, wcs, Properties{AbstractFloat}())
end
end
AstroImage(data::Matrix{T}) where {T<:Real} = AstroImage{T,Gray,1, AbstractFloat}((data,), (WCSTransform(2),), Properties{AbstractFloat}())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why the last parameter of the returned object is abstract?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason as above.

AstroImage(data::NTuple{N, Matrix{T}}) where {T<:Real, N} = AstroImage{T,Gray,N, AbstractFloat}(data, ntuple(i-> WCSTransform(2), N), Properties{AbstractFloat}())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason as above.

AstroImage(data::Matrix{T}, wcs::WCSTransform) where {T<:Real} = AstroImage{T,Gray,1, AbstractFloat}((data,), (wcs,), Properties{AbstractFloat}())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstract parameter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason as above.

AstroImage(data::NTuple{N, Matrix{T}}, wcs::NTuple{N, WCSTransform}) where {T<:Real, N} = AstroImage{T,Gray,N, AbstractFloat}(data, wcs, Properties{AbstractFloat}())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstract parameter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason as above.


"""
AstroImage([color=Gray,] filename::String, n::Int=1)
Expand All @@ -130,6 +151,8 @@ AstroImage(color::Type{<:Color}, fits::NTuple{N, FITS}, ext::NTuple{N, Int}) whe

AstroImage(files::NTuple{N,String}) where {N} =
AstroImage(Gray, load(files)...)
AstroImage(color::Type{<:Color}, files::NTuple{N,String}) where {N} =
AstroImage(color, load(files)...)
AstroImage(file::String) = AstroImage((file,))

# Lazily render the image as a Matrix{Color}, upon request.
Expand Down
7 changes: 7 additions & 0 deletions test/ccd2rgb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,11 @@ end
@test isapprox(red.(asinh_res), red.(asinh_ans), nans = true, rtol = 3e-5)
@test isapprox(blue.(asinh_res), blue.(asinh_ans), nans = true, rtol = 3e-5)
@test isapprox(green.(asinh_res), green.(asinh_ans), nans = true, rtol = 3e-5)

@testset "AstroImage using ccd2rgb" begin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably test coverage can be improved for this new feature

Copy link
Member Author

@aquatiko aquatiko Aug 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part takes relatively large time compared to other tests. So, I wanted to keep non-redundant tests only (as AstroImage is tested very comprehensively through other tests). Also, in the next PR, I'm adding more fields and already written more tests in this very @testset.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit worried by the fact this takes a lot of time. Does it mean that performance is that bad?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproject is the bottleneck where it takes around 20 seconds to reproject an image of size 1024*1024.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't sound like a good news

img = AstroImage(RGB, (joinpath("data","casa_0.5-1.5keV.fits"), joinpath("data","casa_1.5-3.0keV.fits"),
joinpath("data","casa_4.0-6.0keV.fits")))

@test RGB.(img.property.rgb_image) isa Array{RGB{Float64},2}
end
end