Esempio n. 1
0
def test_link_editor():

    # Make sure that the WCSLink works property in the link editor and is
    # returned unmodified. The main way to check that is just to make sure that
    # the link round-trips when going through EditableLinkFunctionState.

    wcs1 = WCS(naxis=2)
    wcs1.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs1.wcs.set()

    data1 = Data(label='Data 1')
    data1.coords = WCSCoordinates(wcs=wcs1)
    data1['x'] = np.ones((2, 3))

    wcs2 = WCS(naxis=3)
    wcs2.wcs.ctype = 'GLON-CAR', 'FREQ', 'GLAT-CAR'
    wcs2.wcs.set()

    data2 = Data(label='Data 2')
    data2.coords = WCSCoordinates(wcs=wcs2)
    data2['x'] = np.ones((2, 3, 4))

    link1 = WCSLink(data1, data2)

    link2 = EditableLinkFunctionState(link1).link

    assert isinstance(link2, WCSLink)
    assert link2.data1.label == 'Data 1'
    assert link2.data2.label == 'Data 2'
Esempio n. 2
0
def test_clone_wcs_link():

    # Make sure that WCSLink can be serialized/deserialized

    wcs1 = WCS(naxis=2)
    wcs1.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs1.wcs.set()

    data1 = Data(label='Data 1')
    data1.coords = WCSCoordinates(wcs=wcs1)
    data1['x'] = np.ones((2, 3))

    wcs2 = WCS(naxis=3)
    wcs2.wcs.ctype = 'GLON-CAR', 'FREQ', 'GLAT-CAR'
    wcs2.wcs.set()

    data2 = Data(label='Data 2')
    data2.coords = WCSCoordinates(wcs=wcs2)
    data2['x'] = np.ones((2, 3, 4))

    link1 = WCSLink(data1, data2)
    link2 = clone(link1)

    assert isinstance(link2, WCSLink)
    assert link2.data1.label == 'Data 1'
    assert link2.data2.label == 'Data 2'
Esempio n. 3
0
def test_wcs_affine_approximation():

    wcs1 = WCS(naxis=2)
    wcs1.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs1.wcs.set()

    data1 = Data(label='Data 1')
    data1.coords = wcs1
    data1['x'] = np.ones((2, 3))

    wcs2 = WCS(naxis=2)
    wcs2.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs2.wcs.crpix = -3, 5
    wcs2.wcs.cd = [[2, -1], [1, 2]]
    wcs2.wcs.set()

    data2 = Data(label='Data 2')
    data2.coords = wcs2
    data2['x'] = np.ones((2, 3))

    link = WCSLink(data1, data2)

    affine_link = link.as_affine_link(tolerance=0.1)

    assert isinstance(affine_link, AffineLink)
    assert_allclose(affine_link.matrix,
                    [[0.4, 0.2, -3.4], [-0.2, 0.4, 4.2], [0, 0, 1]],
                    atol=1e-5)

    x1 = np.array([1.4, 3.2, 2.5])
    y1 = np.array([0.2, 4.3, 2.2])

    x2, y2 = link.forwards(x1, y1)
    x3, y3 = affine_link.forwards(x1, y1)

    assert_allclose(x2, x3, atol=1e-5)
    assert_allclose(y2, y3, atol=1e-5)

    x4, y4 = link.backwards(x1, y1)
    x5, y5 = affine_link.backwards(x1, y1)

    assert_allclose(x4, x5, atol=1e-5)
    assert_allclose(y4, y4, atol=1e-5)
Esempio n. 4
0
def test_wcs_offset_approximation():

    wcs1 = WCS(naxis=2)
    wcs1.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs1.wcs.set()

    data1 = Data(label='Data 1')
    data1.coords = wcs1
    data1['x'] = np.ones((2, 3))

    wcs2 = WCS(naxis=2)
    wcs2.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs2.wcs.crpix = -3, 5
    wcs2.wcs.set()

    data2 = Data(label='Data 2')
    data2.coords = wcs2
    data2['x'] = np.ones((2, 3))

    link = WCSLink(data1, data2)

    offset_link = link.as_affine_link(tolerance=0.1)

    assert isinstance(offset_link, OffsetLink)
    assert_allclose(offset_link.offsets, [3, -5])

    x1 = np.array([1.4, 3.2, 2.5])
    y1 = np.array([0.2, 4.3, 2.2])

    x2, y2 = link.forwards(x1, y1)
    x3, y3 = offset_link.forwards(x1, y1)

    assert_allclose(x2, x3, atol=1e-5)
    assert_allclose(y2, y3, atol=1e-5)

    x4, y4 = link.backwards(x1, y1)
    x5, y5 = offset_link.backwards(x1, y1)

    assert_allclose(x4, x5, atol=1e-5)
    assert_allclose(y4, y4, atol=1e-5)
Esempio n. 5
0
def test_wcs_no_approximation():

    wcs1 = WCS(naxis=2)
    wcs1.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs1.wcs.set()

    data1 = Data(label='Data 1')
    data1.coords = wcs1
    data1['x'] = np.ones((2, 3))

    wcs2 = WCS(naxis=2)
    wcs2.wcs.ctype = 'DEC--TAN', 'RA---TAN'
    wcs2.wcs.crval = 30, 50
    wcs2.wcs.set()

    data2 = Data(label='Data 2')
    data2.coords = wcs2
    data2['x'] = np.ones((2, 3))

    link = WCSLink(data1, data2)

    with pytest.raises(NoAffineApproximation):
        link.as_affine_link(tolerance=0.1)
Esempio n. 6
0
    def link_data(self,
                  link_type='pixels',
                  wcs_fallback_scheme='pixels',
                  wcs_use_affine=True,
                  error_on_fail=False):
        """(Re)link loaded data with the desired link type.
        All existing links will be replaced.

        .. warning::

            Any markers added would be removed. You can add back the markers
            manually using :meth:`add_markers`. During the markers removal,
            pan/zoom will also reset.

        Parameters
        ----------
        link_type : {'pixels', 'wcs'}
            Choose to link by pixels or WCS.

        wcs_fallback_scheme : {None, 'pixels'}
            If WCS linking failed, choose to fall back to linking by pixels or not at all.
            This is only used when ``link_type='wcs'``.
            Choosing `None` may result in some Imviz functionality not working properly.

        wcs_use_affine : bool
            Use an affine transform to represent the offset between images if possible
            (requires that the approximation is accurate to within 1 pixel with the
            full WCS transformations). If approximation fails, it will automatically
            fall back to full WCS transformation. This is only used when ``link_type='wcs'``.
            Affine approximation is much more performant at the cost of accuracy.

        error_on_fail : bool
            If `True`, any failure in linking will raise an exception.
            If `False`, warnings will be emitted as snackbar messages.
            When only warnings are emitted and no links are assigned,
            some Imviz functionality may not work properly.

        Raises
        ------
        ValueError
            Invalid inputs or reference data.

        """
        if len(self.app.data_collection) <= 1:  # No need to link, we are done.
            return

        if link_type not in ('pixels', 'wcs'):
            raise ValueError(
                f"link_type must be 'pixels' or 'wcs', got {link_type}")
        if link_type == 'wcs' and wcs_fallback_scheme not in (None, 'pixels'):
            raise ValueError("wcs_fallback_scheme must be None or 'pixels', "
                             f"got {wcs_fallback_scheme}")

        # Clear any existing markers. Otherwise, re-linking will crash.
        self.reset_markers()

        refdata, iref = get_reference_image_data(self.app)
        links_list = []
        ids0 = refdata.pixel_component_ids
        ndim_range = range(refdata.ndim)

        for i, data in enumerate(self.app.data_collection):
            # Do not link with self
            if i == iref:
                continue

            # We are not touching any existing Subsets. They keep their own links.
            if not layer_is_image_data(data):
                continue

            ids1 = data.pixel_component_ids
            try:
                if link_type == 'pixels':
                    new_links = [
                        LinkSame(ids0[i], ids1[i]) for i in ndim_range
                    ]
                else:  # 'wcs'
                    wcslink = WCSLink(data1=refdata,
                                      data2=data,
                                      cids1=ids0,
                                      cids2=ids1)
                    if wcs_use_affine:
                        try:
                            new_links = [wcslink.as_affine_link()]
                        except NoAffineApproximation:  # pragma: no cover
                            new_links = [wcslink]
                    else:
                        new_links = [wcslink]
            except Exception as e:
                if link_type == 'wcs' and wcs_fallback_scheme == 'pixels':
                    try:
                        new_links = [
                            LinkSame(ids0[i], ids1[i]) for i in ndim_range
                        ]
                    except Exception as e:  # pragma: no cover
                        if error_on_fail:
                            raise
                        else:
                            self.app.hub.broadcast(
                                SnackbarMessage(
                                    f"Error linking '{data.label}' to '{refdata.label}': "
                                    f"{repr(e)}",
                                    color="warning",
                                    timeout=8000,
                                    sender=self.app))
                            continue
                else:
                    if error_on_fail:
                        raise
                    else:
                        self.app.hub.broadcast(
                            SnackbarMessage(
                                f"Error linking '{data.label}' to '{refdata.label}': "
                                f"{repr(e)}",
                                color="warning",
                                timeout=8000,
                                sender=self.app))
                        continue
            links_list += new_links

        if len(links_list) > 0:
            with self.app.data_collection.delay_link_manager_update():
                self.app.data_collection.set_links(links_list)
            self.app.hub.broadcast(
                SnackbarMessage('Images successfully relinked',
                                color='success',
                                timeout=8000,
                                sender=self.app))