dendrograms / astrodendro

Generate a dendrogram from a dataset
https://dendrograms.readthedocs.io/
Other
37 stars 38 forks source link

Show coordinate axes on image, rather than pixel axes #96

Open tomr-stargazer opened 10 years ago

tomr-stargazer commented 10 years ago

When I compute a dendrogram of the CO survey, using the syntax

>>> from astrodendro import Dendrogram
>>> d = Dendrogram.compute(array)

after using astropy.io.fits.getdata to extract the CO datacube, my dendrograms always are displayed with pixel values instead of (l, b, v) coordinates. I'm guessing this is at least partly because I'm passing the data in as a pure ndarray instead of giving the whole FITS object, hence the dendrogram doesn't know anything about the scaling factors.

example image in (l, v) space, where (l) should run from 180->0->360->180 from left-to-right: image

Is there a good way to get the coordinate scaling back into the dendrogram so that I can show plots in (l, b, v)?

astrofrog commented 10 years ago

Good idea :) Glue has the same issue, and in both cases this will be solved very soon with the WCSAxes that I'm developing as part of Astropy!

tomr-stargazer commented 10 years ago

Glad to see that the confluence of technology is providing such solutions!

tomr-stargazer commented 10 years ago

@astrofrog, I am curious if there are any updates re: WCSAxes now that some time has passed?

astrofrog commented 10 years ago

@tomr-stargazer - indeed! It is now already functional (though not quite release ready): http://wcsaxes.readthedocs.org/en/latest/

But feel free to try it out and report any issues! Feel free to also try incorporating it into the viewer.

tomr-stargazer commented 10 years ago

Hi all,

Good news: I've had some success building some WCSAxes functionality into the dendrogram viewer. There's still a notable kink I ran into when wrapping around in Galactic coordinates -- see the following examples:

wcsaxes_in_perseus_demo wcsaxes_cogal_botched_demo

In the latter example, you can see that the X-axis coordinates just give up when they hit zero, rather than wrapping around properly - I'm raising this as an issue over at WCSAxes (now live: https://github.com/astrofrog/wcsaxes/issues/39).

Are there thoughts on how this functionality should be exposed to the user?

My current, crude implementation looks something like this:

from astropy.io.fits import getdata

datacube, datacube_header = getdata(data_path+data_file, memmap=True, header=True)
datacube_wcs = wcs.wcs.WCS(datacube_header)
d = astrodendro.Dendrogram.compute(
        datacube, **kwargs) # min_delta, etc

# I wrote a function to turn a '3D' WCS object 
# into a '2D' one that WCSAxes would accept
wcs_2d = make_2d_wcs_from_3d_wcs(datacube_wcs)

# this produces the above result
d.viewer(wcs=wcs_2d)

where the changes to viewer.py and dendrogram.py are simple, documented here: https://github.com/tomr-stargazer/astrodendro/compare/wcs_axes?expand=1

However, I think a better user interface would involve passing the WCS object to the dendrogram when it's generated, and then when d.viewer() is called, the viewer automatically uses the WCS object (if it passes some validation test) to make a WCSAxes, and then it just uses WCS coordinates. The tricky thing about that is I'd be adding another keyword to astrodendro.Dendrogram.compute(), like so:


datacube, datacube_header = getdata(data_path+data_file, header=True)
datacube_wcs = wcs.wcs.WCS(datacube_header)
wcs_2d = make_2d_wcs_from_3d_wcs(datacube_wcs)

d = astrodendro.Dendrogram.compute(
        datacube, wcs=wcs_2d, **kwargs) 

# since `d` was created with the wcs keyword set, the viewer will use WCSAxes like the images above.
d.viewer()

If there are any thoughts on this user interface, let me know -- otherwise I'll probably submit a pull request in the next couple of days.

keflavich commented 10 years ago

This is a great place for integration with spectral_cube....

@tomr-stargazer This function: make_2d_wcs_from_3d_wcs can probably be replaced with wcs_2d = datacube_wcs.sub([wcs.WCSSUB_CELESTIAL]), even if that's all it does internally.

Since the viewer can deal with cubes natively, I think the conversion from 3d WCS to 2d WCS should be hidden from the user: the viewer should figure out what needs to be passed to wcsaxes for proper behavior.

tomr-stargazer commented 10 years ago

Thanks for the .sub([wcs.WCSSUB_CELESTIAL]) tip! I never would have figured that out.

I agree that the conversion should be hidden from the user. Given that, do you have thoughts on where the WCS object should be passed into the dendrogram? At compute time or at view time?

keflavich commented 10 years ago

Good question, but I think at compute time makes sense - there are some computed features of the dendrogram that depend on the units in the header, so all of that information should be passed at compute time. I think of the units & WCS as "properties of the dendrogram object", so they should be part of initialization.

ChrisBeaumont commented 10 years ago

Yeah, WCS should probably be passed at compute-time (note to self/others: we need to make sure that such information is somehow stored and read during saving/loading)

I'm luke-warm about pulling in a spectral-cube dependency.

Also, the WCSAxes stuff already has slice keyword for specifying which 2D slice through a cube you are viewing, and handles making a 2D wcs object for you -- see, e.g., https://github.com/glue-viz/glue/blob/master/glue/clients/image_client.py#L241

the slices keyword is a tuple like ('x', 'y', 35) (I believe the order follows the FITS convention, reverse of the numpy convention)

tomr-stargazer commented 10 years ago

I'm implementing this right now. Are there any problems with making wcsaxes a viewer dependency?

astrofrog commented 10 years ago

@tomr-stargazer - I don't think there are any issues with making wcsaxes an optional dependency, it's planned for inclusion in the core package anyway.