-
-
Notifications
You must be signed in to change notification settings - Fork 15
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
ValueError: Input data is not 2-dimensional on add_image_layer #288
Comments
Hi Davide, To load an individual channel, you'll have to open the FITS file yourself and be a bit more explicit about which data to use. Something like: from astropy.io import fits
from astropy.wcs import WCS
with fits.open(image_path) as hdu_list:
hdu = hdu_list[0]
wcs = WCS(hdu.header)
data = hdu.data[...,0] # pick out the specific plane we want
layer = wwt.layers.add_image_layer((data, wcs)) Or you could average the three color channels together ( The WWT rendering engine does not support rendering FITS data into individual color RGB color channels into a single image. If you don't want or need to be able to adjust the stretch/colorscale on the fly, you could achieve that effect by pre-converting the data into a JPEG-type image and loading that image into WWT, probably using toasty to do that data processing. Hopefully that answers your question, but please follow up here if you have any more! |
thanks, since is not possible to work with RGB directly, is it possible to render RGB images one channel at the time (e.g. calling 3 times add_image_layer) with WWT but still have a colored image in the end? |
I suppose you could create three image layers, set them all to have partial opacity, and use different color maps for each. It would not be the same as proper RGB display, but it might be good enough depending on your goals. Is your original data a JPEG file? If so, using toasty would probably be the best approach. JPEG images are treated a little differently than FITS files but I can walk you through how to display your image. By adjusting the stretch and colorscale on the fly, I mean that you can dynamically adjust how the FITS data are turned into colors: so that you can emphasis light or dark regions, choose how values are turned into colors, etc. If you are using raw astronomical data with a high dynamic range, this is almost always necessary. If your original data is a JPEG file or similar, this is probably not something that you need to do. |
I have fits/tiff or jpeg, it's not a problem convert from one format to another. but I assume that in the fits I can integrate the coordinates. |
Hi Davide, Two questions for you:
|
for the first question, I prefer python, but if you have also the command line would be great as well. |
Hi Davide, Here's an example program along those lines: #! /usr/bin/env python
"""
Convert a FITS file with three data planes, treated as R/G/B, into a "study"
format viewable in WWT.
"""
from astropy.io import fits
from astropy.visualization import make_lupton_rgb
from astropy.wcs import WCS
from toasty.builder import Builder
from toasty.image import Image
from toasty.pyramid import PyramidIO
def process_rgb_fits(fits_path, output_path):
# Load fits image and coordinates
with fits.open(fits_path) as hdu_list:
hdu = hdu_list[0]
wcs = WCS(hdu.header)
data = hdu.data
# The tuning parameters here are specific to my sample file:
rgb = make_lupton_rgb(
data[...,0], data[...,1], data[...,2],
minimum = 1.6 * data.min(),
stretch = 100,
)
# Now `rgb` is a 1000×1000×3 uint8 image, and `wcs` gives WCS coordinates
# specifying its position on the sky. Convert to WWT "study" format using Toasty:
wcs = wcs.dropaxis(2) # drop non-sky axis from WCS
# EDIT: XXX This is wrong! See comment below.
rgb = rgb[::-1] # vertical flip from FITS raster convention to JPEG-like
# END EDIT
img = Image.from_array(rgb, wcs=wcs, default_format='png')
pio = PyramidIO(output_path, default_format='png')
builder = Builder(pio)
builder.make_thumbnail_from_other(img)
builder.set_name('My RGB Image')
builder.tile_base_as_study(img, cli_progress=True)
builder.apply_wcs_info(img.wcs, img.width, img.height)
builder.cascade(cli_progress=True)
builder.write_index_rel_wtml()
if __name__ == '__main__':
process_rgb_fits('w5_rgb.fits', 'tiled') For the sake of convenience I've used the Astropy Lupton function to get the FITS data into 24-bit RGB color, but for that part you can use whatever suits your needs. Running this program will create a directory named
where the I hope this helps! |
I found the error, there was a mistake in the channels dimension. the fixed part is
instead of
|
Hi Davide — hmm, what is the scale of the misalignment? There is a known (and very annoying!) astrometric error in the default DSS optical sky map at the level of ~1.5 arcsec ... but it looks like the issue you are seeing is a lot bigger than that, I think? If it's close, the "PanSTARRS 3pi" sky map has astrometry that is much more accurate. When there's an image parity flip (i.e. the If your error is bigger than the known DSS error, would you mind sending me the file at |
thanks! I sent you an email |
Thanks! Sorry, I gave some wrong advice — I need to tighten up my thinking about image parity. We need to flip the WCS, not the data. The code in the middle should be like this: wcs = wcs.dropaxis(2) # drop non-sky axis from WCS
# Flip parity of the projection
h = wcs.to_header()
h['PC1_2'] *= -1
h['PC2_2'] *= -1
h['CRPIX2'] = rgb.shape[0] + 1 - h['CRPIX2']
wcs = WCS(h)
img = Image.from_array(rgb, wcs=wcs, default_format='png') When I try this, it lines up perfectly! The conversion of the FITS data to a nice RGB will require some manual exploration — check out the astropy.visualization package for some helpful routines. |
thanks! yes the image was original not stretched. |
@davidenitti Sure, I'm happy to answer questions!
The core processing only works one image at a time, and writes out a separate
Do you mean, is there a way to view your images using local software, not through the
WWT does have a "Black Sky Background" choice that is, well, just black. In pywwt I believe that you can just set the background attribute to |
thanks!
with
if I put black I get:
regardless the background, I don't see the images in the wwt. |
do you have an idea how to solve the issue? |
Sorry for the delay replying here. I think you're close! First, for the black background, that CORS error with 'Black Sky Background' should be spurious. I think you can ignore it. For the Once you have done that, try something like this: from pywwt.qt import WWTQtClient
from astropy.coordinates import SkyCoord
url_path = 'http://127.0.0.1:7005/index.wtml' # NOTE: remove the `_rel` in the filename here
image_name = 'My RGB Image' # this should be the "Name" of the image in the WTML file (which is just XML text)
image_pos = SkyCoord.from_name('M82') # this can be any SkyCoord. `from_name()` looks up a position from SIMBAD/NED
wwt = WWTQtClient(block_until_ready=True)
wwt.load_image_collection(url_path)
wwt.background = 'Black Sky Background'
wwt.foreground = image_name
wwt.foreground_opacity = 1
wwt.center_on_coordinates(image_pos)
wwt.wait() Commentary:
I hope this helps! |
thanks for the reply, but it does not work.
on python the code you suggested runs without errors, but I only see the unwanted deep sky background, so the background is not black as expected and I also don't see my images. I get a black background only with note that maybe there is an error here?
|
@davidenitti If that's your WTML, are you setting As a test, if you set |
yes I set the name properly, that's not the problem I think. |
My apologies, I've been tied up with a proposal this week, but next week I'll have some more time. I'm sure that this is very close to working the way that you want. |
thanks for the support! |
Hi Davide, I apologize that it took so long to follow up here. But I think I have a solution for you, if you're still looking for one! I finally figured out the core issue here. The problem is that the This is a weakness in our Python API, since what you were doing (the code that I wrote!) is totally sensible but doesn't actually work. When using Qt, one can work around this with a manual delay: wwt = WWTQtClient(block_until_ready=True)
wwt.load_image_collection(url_path)
wwt.wait(duration=1) # NEW CODE: manual delay, duration measured in seconds
wwt.background = 'Black Sky Background'
wwt.foreground = image_name
wwt.foreground_opacity = 1
wwt.center_on_coordinates(image_pos)
wwt.wait() This is itself imperfect because it assumes that the WTML will take less than 1 second to load, but it should be "good enough" in many cases. I feel foolish for not thinking of this sooner. And we also need to provide a better API here since the behavior is very surprising and not helpful for our users. |
thanks! I'll test it soon! |
When I use
layer = wwt.layers.add_image_layer(image=image_path)
on an rgb fits (3D array) file I get the error:ValueError: Input data is not 2-dimensional
is there a way to load rgb fits or a way to load the color channels separately and get an rgb image?
The text was updated successfully, but these errors were encountered: