spacetelescope / specviz

An interactive astronomical 1D spectra analysis tool.
http://specviz.readthedocs.io
BSD 3-Clause "New" or "Revised" License
43 stars 31 forks source link

specviz simple linemap incorrect? #690

Closed hcferguson closed 5 years ago

hcferguson commented 5 years ago

I'm not sure if I'm understanding what was intended for the simple linemap, but I'm not getting what I expected.

My understanding is that you select your wavelength range using ROIs on the 1D spectrum, and then choose Cube Operations -> simple linemap to sum over this wavelength region for every spaxel in the data cube, (regardless of whether the spectrum itself was selected from a subset). I expected the result to be a 2D image. What I'm getting back is a 3D image.

Looking at the code, it's not instantly obvious to me how it's supposed to work but (a) it looks like it is making a 3D image, and (b) I don't understand why it is doing this in a loop. If the mask is 0 where you should ignore and 1 where you should keep the data, then the line map is just (data*mask).sum(axis=0) assuming the spectral axis is axis 0.

Existing code in viewer.py:

    def _create_simple_linemap(self):
        def threadable_function(data, tracker):
            out = np.empty(shape=data.shape)
            mask = self.hub.region_mask

            for x in range(data.shape[1]):
                for y in range(data.shape[2]):
                    out[:, x, y] = np.sum(data[:, x, y][mask])
                    tracker()

            return out, data.meta.get('unit')
nmearl commented 5 years ago

The line map creates a new component in the glue data object. Components have to be the same shape as the data that comprises the object (in this case, 3D). However, every slice in the cube will be the same 2D image.

out[:, x, y] = np.sum(data[:, x, y][mask]) basically says "for every spaxel through this cube, set all values to the sum of the masked spaxel of the original data".

For example, if we consider something like data[:, 0, 0] = array([10., 10., 10., 10., 10.]) with a mask array([False, True, True, True, False]), the result is

In [21]: np.sum(data[:, 0, 0][mask])
Out[21]: 30.0

Setting this value into the out cube gives us

In [26]: out[:, 0, 0]
Out[26]: array([30., 30., 30., 30., 30.])
hcferguson commented 5 years ago

Interesting. But definitely not intuitive. I'm not sure this is desirable, but then I'm not sure of the downsides of having this be a separate dataset rather than a component of the 3D dataset.

For moment maps in cubeviz, we are able to create 2D images and have them available in the image viewers along with the 3D data cubes. But this does explain why they don't show up as options on the "overlay contour" menu, which only shows components.

nmearl commented 5 years ago

I can change this to be an overlap instead of a component.