def test_compound_input_units_equivalencies():
    """
    Test setting input_units_equivalencies on one of the models.
    """

    s1 = Shift(10 * u.deg)
    s1.input_units_equivalencies = {'x': u.pixel_scale(0.5 * u.deg / u.pix)}
    s2 = Shift(10 * u.deg)
    sp = Shift(10 * u.pix)

    cs = s1 | s2
    assert cs.input_units_equivalencies == {'x': u.pixel_scale(0.5 * u.deg / u.pix)}

    out = cs(10 * u.pix)
    assert_quantity_allclose(out, 25 * u.deg)

    cs = sp | s1
    assert cs.input_units_equivalencies is None

    out = cs(10 * u.pix)
    assert_quantity_allclose(out, 20 * u.deg)

    cs = s1 & s2
    assert cs.input_units_equivalencies == {'x0': u.pixel_scale(0.5 * u.deg / u.pix)}

    cs = cs.rename('TestModel')
    out = cs(20 * u.pix, 10 * u.deg)
    assert_quantity_allclose(out, 20 * u.deg)

    with pytest.raises(UnitsError) as exc:
        out = cs(20 * u.pix, 10 * u.pix)
    assert exc.value.args[0] == "Shift: Units of input 'x', pix (unknown), could not be converted to required input units of deg (angle)"
Exemplo n.º 2
0
def test_simple_gwcs():
    # https://gwcs.readthedocs.io/en/latest/#getting-started
    shift_by_crpix = models.Shift(-(2048 - 1) * u.pix) & models.Shift(-(1024 - 1) * u.pix)
    matrix = np.array([[1.290551569736E-05, 5.9525007864732E-06],
                       [5.0226382102765E-06, -1.2644844123757E-05]])
    rotation = models.AffineTransformation2D(matrix * u.deg, translation=[0, 0] * u.deg)
    rotation.input_units_equivalencies = {"x": u.pixel_scale(1 * (u.deg / u.pix)),
                                          "y": u.pixel_scale(1 * (u.deg / u.pix))}
    rotation.inverse = models.AffineTransformation2D(np.linalg.inv(matrix) * u.pix,
                                                     translation=[0, 0] * u.pix)
    rotation.inverse.input_units_equivalencies = {"x": u.pixel_scale(1 * (u.pix / u.deg)),
                                                  "y": u.pixel_scale(1 * (u.pix / u.deg))}
    tan = models.Pix2Sky_TAN()
    celestial_rotation = models.RotateNative2Celestial(
        5.63056810618 * u.deg, -72.05457184279 * u.deg, 180 * u.deg)
    det2sky = shift_by_crpix | rotation | tan | celestial_rotation
    det2sky.name = "linear_transform"
    detector_frame = cf.Frame2D(name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix))
    sky_frame = cf.CelestialFrame(reference_frame=ICRS(), name='icrs', unit=(u.deg, u.deg))
    pipeline = [(detector_frame, det2sky), (sky_frame, None)]
    w = gwcs.wcs.WCS(pipeline)

    result = wcs_utils.get_compass_info(w, (1024, 2048), r_fac=0.25)
    assert_allclose(result[:-1], (1024.0, 512.0,
                                  1131.0265005852038, 279.446189124443,
                                  1262.0057201165127, 606.2863901330095,
                                  155.2870478938214, -86.89813081941797))
    assert not result[-1]
def test1(tmpdir, ret=False):
    shift_by_crpix = models.Shift(-2048 * u.pix) & models.Shift(-1024 * u.pix)
    matrix = np.array([[1.290551569736E-05, 5.9525007864732E-06],
                       [5.0226382102765E-06, -1.2644844123757E-05]])
    rotation = models.AffineTransformation2D(matrix * u.deg,
                                             translation=[0, 0] * u.deg)
    rotation.input_units_equivalencies = {
        "x": u.pixel_scale(1 * u.deg / u.pix),
        "y": u.pixel_scale(1 * u.deg / u.pix)
    }
    rotation.inverse = models.AffineTransformation2D(
        np.linalg.inv(matrix) * u.pix, translation=[0, 0] * u.pix)
    rotation.inverse.input_units_equivalencies = {
        "x": u.pixel_scale(1 * u.pix / u.deg),
        "y": u.pixel_scale(1 * u.pix / u.deg)
    }
    tan = models.Pix2Sky_TAN()
    celestial_rotation = models.RotateNative2Celestial(5.63056810618 * u.deg,
                                                       -72.05457184279 * u.deg,
                                                       180 * u.deg)
    det2sky = shift_by_crpix | rotation | tan | celestial_rotation
    det2sky.name = "linear_transform"
    detector_frame = cf.Frame2D(name="detector",
                                axes_names=("x", "y"),
                                unit=(u.pix, u.pix))
    sky_frame = cf.CelestialFrame(reference_frame=coords.ICRS(),
                                  name='icrs',
                                  unit=(u.deg, u.deg))
    pipeline = [(detector_frame, det2sky), (sky_frame, None)]
    wcsobj = gwcs.wcs.WCS(pipeline)
    wcs_set = WcsSet(default=wcsobj, extra=wcsobj)
    tree = {'wcs_set': wcs_set}
    if ret:
        return wcs_set
    helpers.assert_roundtrip_tree(tree, tmpdir)
Exemplo n.º 4
0
def gwcs_simple_imaging_units():
    shift_by_crpix = models.Shift(-2048 * u.pix) & models.Shift(-1024 * u.pix)
    matrix = np.array([[1.290551569736E-05, 5.9525007864732E-06],
                       [5.0226382102765E-06, -1.2644844123757E-05]])
    rotation = models.AffineTransformation2D(matrix * u.deg,
                                             translation=[0, 0] * u.deg)
    rotation.input_units_equivalencies = {
        "x": u.pixel_scale(1 * u.deg / u.pix),
        "y": u.pixel_scale(1 * u.deg / u.pix)
    }
    rotation.inverse = models.AffineTransformation2D(
        np.linalg.inv(matrix) * u.pix, translation=[0, 0] * u.pix)
    rotation.inverse.input_units_equivalencies = {
        "x": u.pixel_scale(1 * u.pix / u.deg),
        "y": u.pixel_scale(1 * u.pix / u.deg)
    }
    tan = models.Pix2Sky_TAN()
    celestial_rotation = models.RotateNative2Celestial(5.63056810618 * u.deg,
                                                       -72.05457184279 * u.deg,
                                                       180 * u.deg)
    det2sky = shift_by_crpix | rotation | tan | celestial_rotation
    det2sky.name = "linear_transform"

    detector_frame = cf.Frame2D(name="detector",
                                axes_names=("x", "y"),
                                unit=(u.pix, u.pix))
    sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(),
                                  name='icrs',
                                  unit=(u.deg, u.deg))
    pipeline = [(detector_frame, det2sky), (sky_frame, None)]
    return wcs.WCS(pipeline)
Exemplo n.º 5
0
def test_add_equivelencies():
    e1 = u.pixel_scale(10*u.arcsec/u.pixel) + u.temperature_energy()
    assert isinstance(e1, Equivalency)
    assert e1.name == ["pixel_scale", "temperature_energy"]
    assert isinstance(e1.kwargs, list)
    assert e1.kwargs == [dict({'pixscale': 10*u.arcsec/u.pix}), dict()]

    e2 = u.pixel_scale(10*u.arcsec/u.pixel) + [1, 2,3]
    assert isinstance(e2, list)
Exemplo n.º 6
0
def test_pixel_scale_invalid_scale_unit():

    pixscale = 0.4 * u.arcsec
    pixscale2 = 0.4 * u.arcsec / u.pix ** 2

    with pytest.raises(u.UnitsError, match="pixel dimension"):
        u.pixel_scale(pixscale)
    with pytest.raises(u.UnitsError, match="pixel dimension"):
        u.pixel_scale(pixscale2)
Exemplo n.º 7
0
def test_add_equivelencies():
    e1 = u.pixel_scale(10*u.arcsec/u.pixel) + u.temperature_energy()
    assert isinstance(e1, Equivalency)
    assert e1.name == ["pixel_scale", "temperature_energy"]
    assert isinstance(e1.kwargs, list)
    assert e1.kwargs == [dict({'pixscale': 10*u.arcsec/u.pix}), dict()]

    e2 = u.pixel_scale(10*u.arcsec/u.pixel) + [1, 2, 3]
    assert isinstance(e2, list)
 def setup(self):
     aff = models.AffineTransformation2D(matrix=[[1, 0], [0, 1]] * u.arcsec,
                                         translation=[0, 0] * u.arcsec)
     aff.input_units_equivalencies = {'x': u.pixel_scale(1 * u.arcsec/u.pix),
                                      'y': u.pixel_scale(1 * u.arcsec/u.pix)}
     self.model = (models.Shift(-10.5 * u.pix) & models.Shift(-13.2 * u.pix) |
                   aff |
                   models.Scale(.01 * u.arcsec) & models.Scale(.04 * u.deg) |
                   models.Pix2Sky_TAN() |
                   models.RotateNative2Celestial(5.6 * u.deg, -72.05 * u.deg, 180 * u.deg))
Exemplo n.º 9
0
 def setup(self):
     aff = models.AffineTransformation2D(matrix=[[1, 0], [0, 1]] * u.arcsec,
                                         translation=[0, 0] * u.arcsec)
     aff.input_units_equivalencies = {'x': u.pixel_scale(1 * u.arcsec/u.pix),
                                      'y': u.pixel_scale(1 * u.arcsec/u.pix)}
     self.model = (models.Shift(-10.5 * u.pix) & models.Shift(-13.2 * u.pix) |
                   aff |
                   models.Scale(.01 * u.arcsec) & models.Scale(.04 * u.deg) |
                   models.Pix2Sky_TAN() |
                   models.RotateNative2Celestial(5.6 * u.deg, -72.05 * u.deg, 180 * u.deg))
Exemplo n.º 10
0
def load_wcs(input_model, reference_files={}):
    """
    Create a gWCS object and store it in ``Model.meta``.

    Parameters
    ----------
    input_model : `~jwst.datamodels.DataModel`
        The exposure.
    reference_files : dict
        A dict {reftype: reference_file_name} containing all
        reference files that apply to this exposure.
    """

    if "wcsinfo" not in input_model.meta:
        input_model.meta.cal_step.assign_wcs = "SKIPPED"
        log.warning("assign_wcs: SKIPPED")
        return input_model
    else:
        output_model = input_model.copy()
        shift_by_crpix = models.Shift(
            -(input_model.meta.wcsinfo.crpix1 - 1) * u.pix
        ) & models.Shift(-(input_model.meta.wcsinfo.crpix2 - 1) * u.pix)
        pix2sky = getattr(
            models, "Pix2Sky_{}".format(input_model.meta.wcsinfo.ctype1[-3:])
        )()
        celestial_rotation = models.RotateNative2Celestial(
            input_model.meta.wcsinfo.crval1 * u.deg,
            input_model.meta.wcsinfo.crval2 * u.deg,
            180 * u.deg,
        )
        pix2sky.input_units_equivalencies = {
            "x": u.pixel_scale(input_model.meta.wcsinfo.cdelt1 * u.deg / u.pix),
            "y": u.pixel_scale(input_model.meta.wcsinfo.cdelt2 * u.deg / u.pix),
        }
        det2sky = shift_by_crpix | pix2sky | celestial_rotation
        det2sky.name = "linear_transform"
        detector_frame = cf.Frame2D(
            name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix)
        )
        sky_frame = cf.CelestialFrame(
            reference_frame=getattr(
                coord, input_model.meta.coordinates.reference_frame
            )(),
            name="sky_frame",
            unit=(u.deg, u.deg),
        )
        pipeline = [(detector_frame, det2sky), (sky_frame, None)]

        wcs = WCS(pipeline)
        output_model.meta.wcs = wcs
        output_model.meta.cal_step.assign_wcs = "COMPLETE"
    return output_model
Exemplo n.º 11
0
def test_compound_and_equiv_call():
    """
    Check that equivalencies work when passed to evaluate, for a composite model
    with two inputs.
    """
    s1 = Shift(10 * u.deg)
    s2 = Shift(10 * u.deg)

    cs = s1 & s2

    out = cs(10 * u.pix, 10 * u.pix, equivalencies={'x0': u.pixel_scale(0.5 * u.deg / u.pix),
                                                    'x1': u.pixel_scale(0.5 * u.deg / u.pix)})
    assert_quantity_allclose(out[0], 15 * u.deg)
    assert_quantity_allclose(out[1], 15 * u.deg)
Exemplo n.º 12
0
def test_compound_and_equiv_call():
    """
    Check that equivalencies work when passed to evaluate, for a compsite model
    with two inputs.
    """
    s1 = Shift(10 * u.deg)
    s2 = Shift(10 * u.deg)

    cs = s1 & s2

    out = cs(10 * u.pix, 10 * u.pix, equivalencies={'x0': u.pixel_scale(0.5 * u.deg / u.pix),
                                                    'x1': u.pixel_scale(0.5 * u.deg / u.pix)})
    assert_quantity_allclose(out[0], 15 * u.deg)
    assert_quantity_allclose(out[1], 15 * u.deg)
Exemplo n.º 13
0
def get_src_img(pos, survey, angular=None, level=0, **kwargs):
    if level > 5:
        print("Failing")
        raise ValueError("Too many failed attempts. ")

    sv_survey = {"first": "VLA FIRST (1.4 GHz)", "wise": "WISE 3.4"}
    survey = sv_survey[survey] if survey in sv_survey else survey

    if angular is None:
        FITS_SIZE = 5 * u.arcmin
    else:
        FITS_SIZE = (angular).to(u.arcsecond)

    CELL_SIZE = 2.0 * u.arcsec / u.pix
    imsize = FITS_SIZE.to("pix", equivalencies=u.pixel_scale(CELL_SIZE))

    try:
        images = SkyView.get_images(
            pos,
            survey,
            pixels=int(imsize.value),
            width=FITS_SIZE,
            height=FITS_SIZE,
            coordinates="J2000",
        )
    except:
        import time

        time.sleep(4)
        get_src_img(pos, survey, angular=angular, level=level + 1)

    return images[0]
Exemplo n.º 14
0
    def kernel_size_px(self):
        """
        Returns a 2-tuple specifying the half-size of the beam image to be
        initialized, in pixels.

        The interpolation may become unstable if the image is severely
        undersampled, pixel sizes of more than 8 arcsec are not recommended.

        Returns
        -------
        out : 2-tuple, each element an integer.
        """

        if self.px_size > 12. * U.arcsec:
            warnings.warn(
                "Using WSRT beam with datacube pixel size >> 8 arcsec,"
                " beam interpolation may fail.")
        freq = self.vel.to(U.GHz, equivalencies=U.doppler_radio(f_HI))
        bheader, bdata = self._load_beamfile()
        centroid = self._centroid()
        aspect_x, aspect_y = np.floor(bdata.shape[0] // 2 *
                                      np.sin(self.dec)), bdata.shape[1] // 2
        aspect_x = aspect_x * np.abs((bheader['CDELT1'] * U.deg)).to(U.arcsec)\
            * (centroid[2] / freq).to(U.dimensionless_unscaled)
        aspect_y = aspect_y * (bheader['CDELT2'] * U.deg).to(U.arcsec) \
            * (centroid[2] / freq).to(U.dimensionless_unscaled)
        return tuple([
            (a.to(U.pix, U.pixel_scale(self.px_size / U.pix))).value + 1
            for a in (aspect_x, aspect_y)
        ])
Exemplo n.º 15
0
def test_compound_input_units_equivalencies():
    """
    Test setting input_units_equivalencies on one of the models.
    """

    s1 = Shift(10 * u.deg)
    s1.input_units_equivalencies = {'x': u.pixel_scale(0.5 * u.deg / u.pix)}
    s2 = Shift(10 * u.deg)
    sp = Shift(10 * u.pix)

    cs = s1 | s2

    out = cs(10 * u.pix)
    assert_quantity_allclose(out, 25 * u.deg)

    cs = sp | s1

    out = cs(10 * u.pix)
    assert_quantity_allclose(out, 20 * u.deg)

    cs = s1 & s2
    cs = cs.rename('TestModel')
    out = cs(20 * u.pix, 10 * u.deg)
    assert_quantity_allclose(out, 20 * u.deg)

    with pytest.raises(UnitsError) as exc:
        out = cs(20 * u.pix, 10 * u.pix)
    assert exc.value.args[0] == "TestModel: Units of input 'x1', pix (unknown), could not be converted to required input units of deg (angle)"
Exemplo n.º 16
0
    def __init__(self, *args, **kwargs):

        # Must be set AFTER the super() call
        time = kwargs.pop("time", None)
        beam = kwargs.pop("beam", None)
        fake_sources = kwargs.pop("fake_sources", None)
        sources = kwargs.pop("sources", None)

        super(NikaMap, self).__init__(*args, **kwargs)

        if isinstance(self.wcs, WCS):
            pixsize = np.abs(self.wcs.wcs.cdelt[0]) * u.deg
        else:
            pixsize = np.abs(self.meta.get("header", {"CDELT": 1}).get("CDELT1", 1)) * u.deg

        self._pixel_scale = u.pixel_scale(pixsize / u.pixel)

        if time is not None:
            self.time = time
        else:
            self.time = np.zeros(self.data.shape) * u.s

        if beam is None:
            # Default gaussian beam
            bmaj = self.meta.get("header", {"BMAJ": 1}).get("BMAJ", 1) * u.deg
            self.beam = NikaBeam(bmaj, pixel_scale=self._pixel_scale)
        else:
            self.beam = beam

        self.fake_sources = fake_sources
        self.sources = sources
Exemplo n.º 17
0
    def _add_attr_img_width_pix_arcsec(self):
        """ 
		creating attributes 
		self.img_width_pix (int)
		self.img_height_pix (int)
		self.img_height_arcsec (angular quantity)
		self.img_width_arcsec (angular quantity)
		which are self.img_width and img_height but changed to indicated units 
		"""
        survey_pixelscale = u.pixel_scale(self.pixsize / u.pixel)

        if hasattr(self.img_width, 'unit'):
            nwpix = (self.img_width.to(u.pix, survey_pixelscale) / u.pix).to(
                u.dimensionless_unscaled)
            self.img_width_pix = int(np.floor(nwpix))
            self.img_width_arcsec = self.img_width.to(u.arcsec,
                                                      survey_pixelscale)
        else:
            raise ValueError('self.img_width has no angular units')

        if hasattr(self.img_height, 'unit'):
            nhpix = (self.img_height.to(u.pix, survey_pixelscale) / u.pix).to(
                u.dimensionless_unscaled)
            self.img_height_pix = int(np.floor(nhpix))
            self.img_height_arcsec = self.img_height.to(
                u.arcsec, survey_pixelscale)
        else:
            raise ValueError('self.img_height has no angular units')
Exemplo n.º 18
0
def test_affine_with_quantities():
    x = 1
    y = 2
    xdeg = (x * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix))
    ydeg = (y * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix))
    xpix = x * u.pix
    ypix = y * u.pix

    # test affine with matrix only
    qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg)
    with pytest.raises(ValueError):
        qx1, qy1 = qaff(xpix, ypix, equivalencies={
            'x': u.pixel_scale(2.5 * u.deg / u.pix),
            'y': u.pixel_scale(2.5 * u.deg / u.pix)})

    # test affine with matrix and translation
    qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg,
                                              translation=[1, 2] * u.deg)
    qx1, qy1 = qaff(xpix, ypix, equivalencies={
        'x': u.pixel_scale(2.5 * u.deg / u.pix),
        'y': u.pixel_scale(2.5 * u.deg / u.pix)})
    aff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]], translation=[1, 2])
    x1, y1 = aff(xdeg.value, ydeg.value)
    assert_quantity_allclose(qx1, x1 * u.deg)
    assert_quantity_allclose(qy1, y1 * u.deg)

    # test the case of WCS PC and CDELT transformations
    pc = np.array([[0.86585778922708, 0.50029020461607],
                   [-0.50029020461607, 0.86585778922708]])
    cdelt = np.array([[1, 3.0683055555556E-05], [3.0966944444444E-05, 1]])
    matrix = cdelt * pc
    qaff = projections.AffineTransformation2D(matrix=matrix * u.deg,
                                              translation=[0, 0] * u.deg)

    inv_matrix = np.linalg.inv(matrix)
    inv_qaff = projections.AffineTransformation2D(matrix=inv_matrix * u.pix,
                                                  translation=[0, 0] * u.pix)
    qaff.inverse = inv_qaff
    qx1, qy1 = qaff(xpix, ypix, equivalencies={
            'x': u.pixel_scale(1 * u.deg / u.pix),
            'y': u.pixel_scale(1 * u.deg / u.pix)})
    x1, y1 = qaff.inverse(qx1, qy1, equivalencies={
        'x': u.pixel_scale(1 * u.deg / u.pix),
        'y': u.pixel_scale(1 * u.deg / u.pix)})
    assert_quantity_allclose(x1, xpix)
    assert_quantity_allclose(y1, ypix)
Exemplo n.º 19
0
def test_affine_with_quantities():
    x = 1
    y = 2
    xdeg = (x * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix))
    ydeg = (y * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix))
    xpix = x * u.pix
    ypix = y * u.pix

    # test affine with matrix only
    qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg)
    with pytest.raises(ValueError):
        qx1, qy1 = qaff(xpix, ypix, equivalencies={
            'x': u.pixel_scale(2.5 * u.deg / u.pix),
            'y': u.pixel_scale(2.5 * u.deg / u.pix)})

    # test affine with matrix and translation
    qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg,
                                              translation=[1, 2] * u.deg)
    qx1, qy1 = qaff(xpix, ypix, equivalencies={
        'x': u.pixel_scale(2.5 * u.deg / u.pix),
        'y': u.pixel_scale(2.5 * u.deg / u.pix)})
    aff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]], translation=[1, 2])
    x1, y1 = aff(xdeg.value, ydeg.value)
    assert_quantity_allclose(qx1, x1 * u.deg)
    assert_quantity_allclose(qy1, y1 * u.deg)

    # test the case of WCS PC and CDELT transformations
    pc = np.array([[0.86585778922708, 0.50029020461607],
                   [-0.50029020461607, 0.86585778922708]])
    cdelt = np.array([[1, 3.0683055555556E-05], [3.0966944444444E-05, 1]])
    matrix = cdelt * pc
    qaff = projections.AffineTransformation2D(matrix=matrix * u.deg,
                                              translation=[0, 0] * u.deg)

    inv_matrix = np.linalg.inv(matrix)
    inv_qaff = projections.AffineTransformation2D(matrix=inv_matrix * u.pix,
                                                  translation=[0, 0] * u.pix)
    qaff.inverse = inv_qaff
    qx1, qy1 = qaff(xpix, ypix, equivalencies={
            'x': u.pixel_scale(1 * u.deg / u.pix),
            'y': u.pixel_scale(1 * u.deg / u.pix)})
    x1, y1 = qaff.inverse(qx1, qy1, equivalencies={
        'x': u.pixel_scale(1 * u.deg / u.pix),
        'y': u.pixel_scale(1 * u.deg / u.pix)})
    assert_quantity_allclose(x1, xpix)
    assert_quantity_allclose(y1, ypix)
Exemplo n.º 20
0
def get_pixel_scale(file: Union['fits.hdu_list.hdulist.HDUList', 'str'],
                    ext: int = 0,
                    astropy_units: bool = False):
    """
    Using the FITS file header, obtains the pixel scale of the file (in degrees).
    Declination scale is the true angular size of the pixel.
    Assumes that the change in spherical distortion in RA over the width of the image is negligible.
    :param file:
    :return: Tuple containing the pixel scale of the FITS file: (ra scale, dec scale)
        If astropy_units is True, returns it as an astropy pixel_scale equivalency.
    """
    # TODO: Rewrite photometry functions to use this

    file, path = path_or_hdu(file)

    header = file[ext].header
    image = file[ext].data

    # To take (very roughly) into account the spherical distortion to the RA, we obtain an RA pixel scale by dividing
    # the difference in RA across the image by the number of pixels. It's good enough to give an average value, and the
    # difference SHOULD be pretty tiny across the image.

    w = wcs.WCS(header)
    end = image.shape[0] - 1
    ra_pixel_scale = (w.pixel_to_world(0, 0).ra.deg -
                      w.pixel_to_world(end, 0).ra.deg) / end

    # By comparison the pixel scale in declination is easy to obtain - as DEC is undistorted, it is simply the true
    # pixel scale of the image, which the header stores.
    dec_pixel_scale = w.pixel_scale_matrix[1, 1]
    if dec_pixel_scale == 0:
        dec_pixel_scale = w.pixel_scale_matrix[1, 0]

    if path:
        file.close()

    ra_pixel_scale = abs(ra_pixel_scale)
    dec_pixel_scale = abs(dec_pixel_scale)

    if astropy_units:
        ra_pixel_scale = units.pixel_scale(ra_pixel_scale * units.deg /
                                           units.pixel)
        dec_pixel_scale = units.pixel_scale(dec_pixel_scale * units.deg /
                                            units.pixel)

    return ra_pixel_scale, dec_pixel_scale
Exemplo n.º 21
0
def gwcs_2d_shift_scale_quantity():
    m4 = models.Shift(1 * u.pix) & models.Shift(2 * u.pix)
    m5 = models.Scale(5 * u.deg)
    m6 = models.Scale(10 * u.deg)
    m5.input_units_equivalencies = {'x': u.pixel_scale(1 * u.deg / u.pix)}
    m6.input_units_equivalencies = {'x': u.pixel_scale(1 * u.deg / u.pix)}
    m5.inverse = models.Scale(1. / 5 * u.pix)
    m6.inverse = models.Scale(1. / 10 * u.pix)
    m5.inverse.input_units_equivalencies = {
        'x': u.pixel_scale(1 * u.pix / u.deg)
    }
    m6.inverse.input_units_equivalencies = {
        'x': u.pixel_scale(1 * u.pix / u.deg)
    }
    m7 = m5 & m6
    m8 = m4 | m7
    pipe2 = [(detector_2d, m8), (icrs_sky_frame, None)]
    return wcs.WCS(pipe2)
Exemplo n.º 22
0
def test_equivelency():
    ps = u.pixel_scale(10*u.arcsec/u.pix)
    assert isinstance(ps, Equivalency)
    assert isinstance(ps.name, list)
    assert len(ps.name) == 1
    assert ps.name[0] == "pixel_scale"
    assert isinstance(ps.kwargs, list)
    assert len(ps.kwargs) == 1
    assert ps.kwargs[0] == dict({'pixscale': 10*u.arcsec/u.pix})
Exemplo n.º 23
0
def test_equivelency():
    ps = u.pixel_scale(10*u.arcsec/u.pix)
    assert isinstance(ps, Equivalency)
    assert isinstance(ps.name, list)
    assert len(ps.name) == 1
    assert ps.name[0] == "pixel_scale"
    assert isinstance(ps.kwargs, list)
    assert len(ps.kwargs) == 1
    assert ps.kwargs[0] == dict({'pixscale': 10*u.arcsec/u.pix})
Exemplo n.º 24
0
def test_compound_pipe_equiv_call():
    """
    Check that equivalencies work when passed to evaluate, for a chained model
    (which has one input).
    """
    s1 = Shift(10 * u.deg)
    s2 = Shift(10 * u.deg)

    cs = s1 | s2

    out = cs(10 * u.pix, equivalencies={'x': u.pixel_scale(0.5 * u.deg / u.pix)})
    assert_quantity_allclose(out, 25 * u.deg)
Exemplo n.º 25
0
def test_compound_pipe_equiv_call():
    """
    Check that equivalencies work when passed to evaluate, for a chained model
    (which has one input).
    """
    s1 = Shift(10 * u.deg)
    s2 = Shift(10 * u.deg)

    cs = s1 | s2

    out = cs(10 * u.pix, equivalencies={'x': u.pixel_scale(0.5 * u.deg / u.pix)})
    assert_quantity_allclose(out, 25 * u.deg)
Exemplo n.º 26
0
    def kernel_size_px(self):
        """
        Returns a 2-tuple specifying the half-size of the beam image to be
        initialized, in pixels.

        Returns
        -------
        out : 2-tuple, each element an integer.
        """

        size = np.ceil((self.bmaj * self.truncate).to(
            U.pix, U.pixel_scale(self.px_size / U.pix))).value + 1
        return size, size
Exemplo n.º 27
0
    def _init_sm_lengths(self, source=None, datacube=None):
        """
        Determine kernel sizes in pixel units.

        Parameters
        ----------
        source : martini.sources.SPHSource (or inheriting class) instance
            The source providing the kernel sizes.

        datacube : martini.DataCube instance
            The datacube providing the pixel scale.
        """
        self.sm_lengths = np.arctan(
            source.hsm_g / source.sky_coordinates.distance).to(
                U.pix, U.pixel_scale(datacube.px_size / U.pix))

        return
Exemplo n.º 28
0
    def _prune_source(self):
        """
        Determines which particles cannot contribute to the DataCube and
        removes them to speed up calculation. Assumes the kernel is 0 at
        distances greater than the kernel size (which may differ from the
        SPH smoothing length).
        """

        # pixels indexed from 0 (not like in FITS!) for better use with numpy
        origin = 0
        skycoords = self.source.sky_coordinates
        particle_coords = np.vstack(
            self.datacube.wcs.sub(3).wcs_world2pix(
                skycoords.ra.to(self.datacube.units[0]),
                skycoords.dec.to(self.datacube.units[1]),
                skycoords.radial_velocity.to(self.datacube.units[2]),
                origin)) * U.pix
        # could use a function bound to source which returns the size of the
        # kernel, in case this isn't equal to the smoothing length for some
        # kernel
        sm_length = np.arctan(
            self.source.hsm_g / self.source.sky_coordinates.distance).to(
                U.pix, U.pixel_scale(self.datacube.px_size / U.pix))
        sm_range = np.ceil(
            sm_length * self.sph_kernel.size_in_fwhm
        ).astype(int)
        spectrum_half_width = self.spectral_model.half_width(self.source) / \
            self.datacube.channel_width
        reject_conditions = (
            (particle_coords[:2] + sm_range[np.newaxis] <
             0 * U.pix).any(axis=0),
            particle_coords[0] - sm_range >
            (self.datacube.n_px_x + self.datacube.padx * 2) * U.pix,
            particle_coords[1] - sm_range >
            (self.datacube.n_px_y + self.datacube.pady * 2) * U.pix,
            particle_coords[2] + 4 * spectrum_half_width * U.pix < 0 * U.pix,
            particle_coords[2] - 4 * spectrum_half_width * U.pix >
            self.datacube.n_channels * U.pix,
        )
        reject_mask = np.zeros(particle_coords[0].shape)
        for condition in reject_conditions:
            reject_mask = np.logical_or(reject_mask, condition)
        self.source.apply_mask(np.logical_not(reject_mask))
        return
Exemplo n.º 29
0
def moffat_psf(fwhm, pixel_scale=0.2, shape=41, alpha=4.765):
    """
    Moffat point-spread function.

    Parameters
    ----------
    fwhm : float or `~astropy.units.Quantity`
        Full width at half maximum of the psf. If a float is given, the units
        will be assumed to be arcsec. The units can be angular or in pixels.
    pixel_scale : float or `~astropy.units.Quantity`, optional
        The pixel scale of the psf image. If a float is given, the units are 
        assumed to be arcsec / pixel (why would you want anything different?).
    shape : int or list-like, optional
        Shape of the psf image. Must be odd. If an int is given, the x and y 
        dimensions will be set to this value: (shape, shape).
    alpha : float, optional
        Power index of the Moffat model.

    Returns
    -------
    psf : `~numpy.ndarray`
        The PSF image normalized such that its sum is equal to one. 

    Notes
    -----
    The default value `alpha = 4.765` is a fit to the prediction from 
    atmospheric turbulence theory (`Trujillo et al. 2001 
    <https://ui.adsabs.harvard.edu/abs/2001MNRAS.328..977T/abstract>`_).
    """
    fwhm = check_units(fwhm, 'arcsec')
    pixel_scale = check_units(pixel_scale, u.arcsec / u.pixel)
    y_size, x_size = _check_shape(shape)

    width = fwhm.to('pixel', u.pixel_scale(pixel_scale)).value
    gamma = width / (2 * np.sqrt(2**(1 / alpha) - 1))
    model = Moffat2DKernel(gamma=gamma,
                           alpha=alpha,
                           x_size=x_size,
                           y_size=y_size)
    model.normalize()
    psf = model.array
    return psf
Exemplo n.º 30
0
    def __init__(self,
                 sp,
                 scale_radius,
                 xy_dim,
                 pixel_scale,
                 dx=0,
                 dy=0,
                 labels=None):

        self.sp = sp
        self.mag_limit = sp.mag_limit
        self.mag_limit_band = sp.mag_limit_band
        self.smooth_model = None

        if self.mag_limit is not None and sp.frac_num_sampled < 1.0:
            _rs = check_units(scale_radius, 'kpc').to('Mpc').value
            _distance = check_units(sp.distance, 'Mpc').to('Mpc').value
            _pixel_scale = check_units(pixel_scale, u.arcsec / u.pixel)

            self.r_sky = np.arctan2(_rs, _distance) * u.radian.to('arcsec')
            self.r_sky *= u.arcsec
            r_pix = self.r_sky.to('pixel', u.pixel_scale(_pixel_scale)).value

            xy_dim = check_xy_dim(xy_dim)
            x_0, y_0 = xy_dim // 2
            x_0 += dx
            y_0 += dy

            self.smooth_model = Plummer2D(x_0=x_0, y_0=y_0, scale_radius=r_pix)

        self.xy_kw = dict(num_stars=sp.num_stars,
                          scale_radius=scale_radius,
                          distance=sp.distance,
                          xy_dim=xy_dim,
                          pixel_scale=pixel_scale,
                          dx=dx,
                          dy=dy,
                          random_state=sp.rng)

        _xy = plummer_xy(**self.xy_kw)
        super(PlummerSP, self).__init__(_xy, sp.mag_table, xy_dim, pixel_scale,
                                        labels)
Exemplo n.º 31
0
def test_pixel_scale():
    pix = 75*u.pix
    asec = 30*u.arcsec

    pixscale = 0.4*u.arcsec/u.pix
    pixscale2 = 2.5*u.pix/u.arcsec

    assert_quantity_allclose(pix.to(u.arcsec, u.pixel_scale(pixscale)), asec)
    assert_quantity_allclose(pix.to(u.arcmin, u.pixel_scale(pixscale)), asec)

    assert_quantity_allclose(pix.to(u.arcsec, u.pixel_scale(pixscale2)), asec)
    assert_quantity_allclose(pix.to(u.arcmin, u.pixel_scale(pixscale2)), asec)

    assert_quantity_allclose(asec.to(u.pix, u.pixel_scale(pixscale)), pix)
    assert_quantity_allclose(asec.to(u.pix, u.pixel_scale(pixscale2)), pix)
Exemplo n.º 32
0
def test_pixel_scale():
    pix = 75*u.pix
    asec = 30*u.arcsec

    pixscale = 0.4*u.arcsec/u.pix
    pixscale2 = 2.5*u.pix/u.arcsec

    assert_quantity_allclose(pix.to(u.arcsec, u.pixel_scale(pixscale)), asec)
    assert_quantity_allclose(pix.to(u.arcmin, u.pixel_scale(pixscale)), asec)

    assert_quantity_allclose(pix.to(u.arcsec, u.pixel_scale(pixscale2)), asec)
    assert_quantity_allclose(pix.to(u.arcmin, u.pixel_scale(pixscale2)), asec)

    assert_quantity_allclose(asec.to(u.pix, u.pixel_scale(pixscale)), pix)
    assert_quantity_allclose(asec.to(u.pix, u.pixel_scale(pixscale2)), pix)
Exemplo n.º 33
0
def test_pixel_scale_acceptable_scale_unit():

    pix = 75 * u.pix
    v = 3000 * (u.cm / u.s)

    pixscale = 0.4 * (u.m / u.s / u.pix)
    pixscale2 = 2.5 * (u.pix / (u.m / u.s))

    assert_quantity_allclose(pix.to(u.m / u.s, u.pixel_scale(pixscale)), v)
    assert_quantity_allclose(pix.to(u.km / u.s, u.pixel_scale(pixscale)), v)

    assert_quantity_allclose(pix.to(u.m / u.s, u.pixel_scale(pixscale2)), v)
    assert_quantity_allclose(pix.to(u.km / u.s, u.pixel_scale(pixscale2)), v)

    assert_quantity_allclose(v.to(u.pix, u.pixel_scale(pixscale)), pix)
    assert_quantity_allclose(v.to(u.pix, u.pixel_scale(pixscale2)), pix)
Exemplo n.º 34
0
def gaussian_psf(fwhm, pixel_scale=0.2, shape=41):
    """
    Gaussian point-spread function.

    Parameters
    ----------
    fwhm : float or `~astropy.units.Quantity`
        Full width at half maximum of the psf. If a float is given, the units
        will be assumed to be `~astropy.units.arcsec`. The units can be angular 
        or in pixels.
    pixel_scale : float or `~astropy.units.Quantity`, optional
        The pixel scale of the psf image. If a float is given, the units are 
        assumed to be `~astropy.units.arcsec` per `~astropy.units.pixel` 
        (why would you want anything different?).
    shape : int or list-like, optional
        Shape of the psf image. Must be odd. If an int is given, the x and y 
        dimensions will be set to this value: (shape, shape).

    Returns
    -------
    psf : `~numpy.ndarray`
        The PSF image normalized such that its sum is equal to one. 
    """

    fwhm = check_units(fwhm, 'arcsec')
    pixel_scale = check_units(pixel_scale, u.arcsec / u.pixel)
    y_size, x_size = _check_shape(shape)

    width = fwhm.to('pixel', u.pixel_scale(pixel_scale)).value
    width *= gaussian_fwhm_to_sigma
    model = Gaussian2DKernel(x_stddev=width,
                             y_stddev=width,
                             x_size=x_size,
                             y_size=y_size)
    model.normalize()
    psf = model.array
    return psf
Exemplo n.º 35
0
    def __delta_sky_to_pixels(self) -> Tuple[np.ndarray, np.ndarray]:
        """Transform the spherical offsets from the sky-reference frame to a
        pixel-reference frame. 
        
        Returns:
            Tuple[np.ndarray, np.ndarray] -- Coordinates in a pixel-reference frame
        """
        offsets = self.coords["offsets-angular"]

        if self.pixel_scale is None:
            return offsets

        pixel_scale = (self.pixel_scale if isinstance(self.pixel_scale, tuple)
                       else (self.pixel_scale, self.pixel_scale))
        pixel_scale = tuple(
            [u.pixel_scale(ps / u.pixel) for ps in pixel_scale])

        # RA increases right-to-left. The opposite of an array
        offsets = (
            -offsets[0].to(u.pixel, pixel_scale[0]),
            offsets[1].to(u.pixel, pixel_scale[1]),
        )

        return offsets
Exemplo n.º 36
0
	def _add_attr_img_width_pix_arcsec(self):
		""" 
		creating attributes 
		self.img_width_pix (int)
		self.img_height_pix (int)
		self.img_height_arcsec (angular quantity)
		self.img_width_arcsec (angular quantity)
		which are self.img_width and img_height but changed to indicated units 
		"""
		survey_pixelscale = u.pixel_scale(self.pixsize/u.pixel)

		if hasattr(self.img_width, 'unit'): 
			nwpix = (self.img_width.to(u.pix, survey_pixelscale)/u.pix).to(u.dimensionless_unscaled)
			self.img_width_pix = int(np.floor(nwpix))
			self.img_width_arcsec = self.img_width.to(u.arcsec, survey_pixelscale)
		else: 
			raise ValueError('self.img_width has no angular units')

		if hasattr(self.img_height, 'unit'): 
			nhpix = (self.img_height.to(u.pix, survey_pixelscale)/u.pix).to(u.dimensionless_unscaled)
			self.img_height_pix = int(np.floor(nhpix))
			self.img_height_arcsec = self.img_height.to(u.arcsec, survey_pixelscale)
		else: 
			raise ValueError('self.img_height has no angular units')
Exemplo n.º 37
0
def fit_alignment_box(region, box_size=30, verbose=False, seeing=None,
                      medfilt=False):
    pixelscale = u.pixel_scale(0.1798*u.arcsec/u.pixel)
    if medfilt is True:
        region = median_filter(region, size=(3,3))

    # Estimate center of alignment box
    threshold_pct = 80
    window = region.data > np.percentile(region.data, threshold_pct)
    alignment_box_position = ndimage.measurements.center_of_mass(window)

    offset_val = np.median(region.data[~window])
    offset = models.Const2D(offset_val)

    # Determine fluctuations in sky
    sky_amplitude = np.median(region.data[window])
    sky_fluctuations = np.std(region.data[window])

    # Detect box edges
    gradx = np.gradient(region.data, axis=1)
    horizontal_profile = np.sum(gradx, axis=0)
    h_edges = fit_CSU_edges(horizontal_profile)
    grady = np.gradient(region.data, axis=0)
    vertical_profile = np.sum(grady, axis=1)
    v_edges = fit_CSU_edges(vertical_profile)

    # Estimate stellar position
    maxr = np.max(region.data)
    starloc = (np.where(region == maxr)[0][0],
               np.where(region == maxr)[1][0])

    # Build model of sky, star, & box
    boxamplitude = 1

    box = mosfireAlignmentBox(boxamplitude, alignment_box_position[1], alignment_box_position[0],\
                       abs(h_edges[0]-h_edges[1]), abs(v_edges[0]-v_edges[1]))
    box.amplitude.fixed = True
    box.x_width.min = 10
    box.y_width.min = 10

    sky = models.Const2D(sky_amplitude)
    sky.amplitude.min = 0

    star_amplitude = maxr - sky_amplitude
    star_sigma = star_amplitude / sky_fluctuations
    if star_sigma < 5:
        if verbose: print(f'No star detected.  sigma={star_sigma:.1f}')
        return [None]*4
    else:
        if verbose: print(f'Detected peak pixel {star_sigma:.1f} sigma above sky.')
    star = models.Gaussian2D(amplitude=star_amplitude,
                             x_mean=starloc[1], y_mean=starloc[0],
                             x_stddev=2, y_stddev=2)
#     print(h_edges)
#     print(v_edges)
#     star.y_mean.min = v_edges[0]
#     star.y_mean.max = v_edges[1]
#     star.x_mean.min = h_edges[0]
#     star.x_mean.max = h_edges[1]
    star.amplitude.min = 5*sky_fluctuations
    star.x_stddev.min = 1 # FWHM = 2.355*stddev = 0.42 arcsec FWHM
    star.x_stddev.max = 4 # FWHM = 2.355*stddev = 1.47 arcsec FWHM
    star.y_stddev.min = 1
    star.y_stddev.max = 4

    if seeing is not None and seeing > 0:
        sigma = (seeing / 2.355 * u.arcsec).to(u.pixel, equivalencies=pixelscale)
        star.x_stddev.min = max(2, sigma.value-1)
        star.y_stddev.min = max(2, sigma.value-1)
        star.x_stddev.max = min(sigma.value+1, 4)
        star.y_stddev.max = min(sigma.value+1, 4)
#         print(f"Using seeing value {seeing} arcsec. sigma limits {star.x_stddev.min}, {star.x_stddev.max} pix")

    model = box*(sky + star) + offset

#     modelim = np.zeros((61,61))
#     fitim = np.zeros((61,61))
#     for i in range(0,60):
#         for j in range(0,60):
#             modelim[j,i] = model(i,j)
#             fitim[j,i] = model(i,j)
#     residuals = region.data-fitim
#     residualsum = np.sum(residuals)
#     import pdb ; pdb.set_trace()

    fitter = fitting.LevMarLSQFitter()
    y, x = np.mgrid[:2*box_size+1, :2*box_size+1]
    fit = fitter(model, x, y, region.data)

    FWHMx = 2*(2*np.log(2))**0.5*fit.x_stddev_2.value * u.pix
    FWHMy = 2*(2*np.log(2))**0.5*fit.y_stddev_2.value * u.pix
    FWHM = (FWHMx**2 + FWHMy**2)**0.5/2**0.5
    FWHMarcsec = FWHM.to(u.arcsec, equivalencies=pixelscale)
    sky_amplitude = fit.amplitude_1.value
    star_flux = 2*np.pi*fit.amplitude_2.value*fit.x_stddev_2.value*fit.y_stddev_2.value
    star_amplitude = fit.amplitude_2.value
    boxpos_x = fit.x_0_0.value
    boxpos_y = fit.y_0_0.value
    star_x = fit.x_mean_2.value
    star_y = fit.y_mean_2.value

    if verbose: print(f"  Box X Center = {boxpos_x:.0f}")
    if verbose: print(f"  Box Y Center = {boxpos_y:.0f}")
    if verbose: print(f"  Sky Brightness = {fit.amplitude_1.value:.0f} ADU")
    if verbose: print(f"  Stellar FWHM = {FWHMarcsec:.2f}")
    if verbose: print(f"  Stellar Xpos = {star_x:.0f}")
    if verbose: print(f"  Stellar Xpos = {star_y:.0f}")
    if verbose: print(f"  Stellar Amplitude = {star_amplitude:.0f} ADU")
    if verbose: print(f"  Stellar Flux (fit) = {star_flux:.0f} ADU")

    result = {'Star X': star_x,
              'Star Y': star_y,
              'Star Amplitude': star_amplitude,
              'Sky Amplitude': sky_amplitude,
              'FWHM pix': FWHM.value,
              'FWHM arcsec': FWHMarcsec,
              'Box X': boxpos_x,
              'Box Y': boxpos_y,
#               'Residuals': residuals,
             }
    return result
Exemplo n.º 38
0
            y_0 = r_195[band]['y_0']
        elif got_one:
            x_0 = previous_centroid[0]
            y_0 = previous_centroid[1]

        print('{:s}: {:s}band: {:d}/{:d}. x_0: {:.3g}, y_0: {:.3g}.'.format(
            fname, band, int(index), int(len(fnames)), x_0, y_0)+\
              ' Got {:d} sources'.format(len(phot_table))
            )

        dist = np.sqrt( (phot_table['xcenter']-x_0)**2 +
                        (phot_table['ycenter']-y_0)**2 )
        phot_table['dist_from_r0_px'] = dist
        phot_table.sort(['dist_from_r0_px'])

        pisco_pixelscale = u.pixel_scale(0.069*u.arcsec/u.pixel)
        phot_table['dist_from_r0_as'] = phot_table['dist_from_r0_px'].to(
                u.arcsec, pisco_pixelscale)

        tr56 = phot_table[0]

        if tr56['dist_from_r0_as'] > 1.*u.arcsec:
            # NOTE: this approach (if there is a jump, just skip to the
            # next frame and ignore the last one) was "needed" b/c of one frame
            # in i-band images: tr_45?.fits (see notes for the correct number).
            # If you don't do this, get stuck on that frame.

            print('ERR: {:s} position of tr56 is {:.3g} ({:.3g}) from prev'.\
            format(fname, tr56['dist_from_r0_px'], tr56['dist_from_r0_as']))
            print('\tcontinue to next frame...')
Exemplo n.º 39
0
def given_cameras_get_stars_on_silicon(coords,
                                       cam_directions,
                                       verbose=True,
                                       withgaps=True):
    '''
    If the TESS spacecraft points in a particular direction, which stars fall on
    silicon?

    Args:

        coords (np.ndarray of astropy.coordinate.SkyCoords): array of astropy
        coordinates for the stars that will be either on, or not on silicon.

        cam_directions (list of float tuples): list with format:

            [ (cam1_elat, cam1_elon),
              (cam2_elat, cam2_elon),
              (cam3_elat, cam3_elon),
              (cam4_elat, cam4_elon) ],

        where all entries are tuples of floats, and "cam1_elat" means ecliptic
        latitude of camera 1 center.  This function will require that camera 2
        is 24 degrees from camera 1, camera 3 is 48 degrees from camera 1, and
        camera 4 is 72 degrees from camera 1.

    Returns:

        on_chip (np.ndarray): array of 1's and 0's for what falls on
        silicon, and what does not. Same length as coords.

    Nomenclature:
        "Sector" means one "grouping" of 4 cameras. There are 13 sectors over
        the first TESS year. "View" means one pointing of a camera, in a
        sector. There are 26*4=104 views over the first two years.  This
        function corresponds to only a single sector.
    '''

    n_coords = len(coords)
    if verbose:
        print('computing whether on silicon for {:d} objects'.format(n_coords))

    n_cameras = 4  # this will hopefully never change
    n_sectors = 1  # this function is for a single sector
    n_views = n_sectors * n_cameras

    # compute camera central coordinates for the first year, given the initial
    # longitude.
    views, cam_coords = [], []
    for n_camera, this_cam_dirn in zip(range(n_cameras), cam_directions):

        this_elat = this_cam_dirn[0] * u.deg
        this_elon = this_cam_dirn[1] * u.deg

        this_coord = SkyCoord(lon=this_elon,
                              lat=this_elat,
                              frame='barycentrictrueecliptic')

        views.append([
            n_camera, this_elon, this_elat, this_coord.icrs.ra,
            this_coord.icrs.dec
        ])

        cam_coords.append(this_coord)

    separations = [
        cam_coords[0].separation(cam_coords[1]).value,
        cam_coords[0].separation(cam_coords[2]).value,
        cam_coords[0].separation(cam_coords[3]).value
    ]

    np.testing.assert_array_almost_equal(
        separations, [24, 48, 72],
        decimal=2,
        err_msg='camera separations should be 24 degrees. have {:s}'.format(
            repr(cam_coords)))

    views_columns = ['n_camera', 'elon', 'elat', 'ra', 'dec']
    views = pd.DataFrame(views, columns=views_columns)

    # ccd info. see e.g., Huang et al, 2018. The gap size is a number inherited
    # from Josh Winn's code.
    fov = 24. * u.degree
    ccd_pix = 4096 * u.pix
    gap_pix = (2. / 0.015) * u.pix  # about 133 pixels per gap
    pixel_scale = u.pixel_scale(fov / (ccd_pix + gap_pix))
    ccd_center = np.ones(2) * (ccd_pix + gap_pix) / 2
    delt = (np.ones(2) * u.pix).to(u.degree, pixel_scale)

    elon = coords.barycentrictrueecliptic.lon.value
    elat = coords.barycentrictrueecliptic.lat.value
    ra = coords.icrs.ra.value
    dec = coords.icrs.dec.value

    onchip = np.zeros_like(ra)
    for ix, view in views.iterrows():

        # create new WCS object. See. e.g., Calabretta & Greisen 2002, paper
        # II, table 1. CRPIX: pixel-coordinates of reference pixel (center of
        # image). CRVAL: celestial long (RA) and lat (dec) of reference pixel.
        # CDELT: degrees per pixel at reference pixel location, i.e. the
        # coordinate scale. CTYPE: gnomic projection.
        w = wcs.WCS(naxis=2)
        w.wcs.crpix = ccd_center.value
        w.wcs.crval = [view['elon'].value, view['elat'].value]
        ###w.wcs.crval = [view['ra'].value, view['dec'].value] # either works
        w.wcs.cdelt = delt.value
        w.wcs.ctype = ['RA---TAN', 'DEC--TAN']

        # follow fits standards: The image pixel count starts with 1.
        x, y = w.wcs_world2pix(elon, elat, 1)
        ###x, y = w.wcs_world2pix(ra, dec, 1) # either works

        try:
            # the extra "1" is because of 1-based image count.
            if withgaps:
                onchip += (  # lower left CCD
                    ((x > 0.0) & (x <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.) &
                     (y > 0.0) & (y <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.))
                    |  # lower right CCD
                    ((x > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (x < (ccd_pix.value + gap_pix.value) - 1.) & (y > 0.0) &
                     (y < (ccd_pix.value - gap_pix.value) / 2. - 1.))
                    |  # upper right CCD
                    ((x > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (x < (ccd_pix.value + gap_pix.value) - 1.) &
                     (y > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (y < (ccd_pix.value + gap_pix.value) - 1.))
                    |  # upper left CCD 
                    ((x > 0.0) & (x <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.) &
                     (y > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (y < (ccd_pix.value + gap_pix.value) - 1.)))

            elif not withgaps:

                onchip += ((x > 0.) & (x < ccd_pix.value + gap_pix.value - 1.)
                           & (y > 0.) &
                           (y < ccd_pix.value + gap_pix.value - 1.))

        except Exception as e:

            print('failed computing onchip. error msg: {:s}'.format(e))
            return 0

    if verbose:
        print(
            'computed sector numbers for {:d} stars/objects'.format(n_coords))

    return onchip.astype(np.int)
Exemplo n.º 40
0
	def __init__(self, **kwargs):
		"""
		Imager, parent class for all obj operator for images

		Params
		------
		Operator params:
			/either
				obj (object of class obsobj): with attributes ra, dec, dir_obj
			/or  
				ra (float)
				dec (float)
				/either
					dir_obj (string)
				/or 
					dir_parent (string): attr dir_obj is set to dir_parent+'SDSSJXXXX+XXXX/'

		survey (str): 
			survey of the photometric system
			if not provided, use self.obj.survey. Raise exception if self.obj.survey does not exist. 

		z=-1 (float):  
			redshift, if not provided, use self.obj.z or self.obj.sdss.z. It does not automatically query sdss to get z. If nothing is pecified then set to -1. 

		center_mode='n/2' (str):
			how is image center defined in case of even n, 'n/2' or 'n/2-1'. Should be set to n/2-1 if the image is downloaded from HSC quarry. 


		Attributes
		----------
		Operator Attributes:	
			obj (instance of objObj)
			ra (float)
			dec (float)
			dir_obj (string)

		survey (str): e.g., 'hsc'
			survey of the photometric system
		z (float): 
			redshift
		pixsize (astropy angle quantity):
			in unit of arcsec
		pixelscale (astropy pixscale quantity):
			for pixel and arcsec conversion

		"""
		
		super(Imager, self).__init__(**kwargs)

		# set survey
		if hasattr(self.obj, 'survey'):
			default_survey = self.obj.survey
			self.survey = kwargs.pop('survey', default_survey)
		else: 
			self.survey = kwargs.pop('survey')

		# set up obj.survey
		if self.survey == 'hsc':
			self.obj.add_hsc()
		elif self.survey == 'sdss':
			self.obj.add_sdss()

		# set z
		if hasattr(self.obj, 'z'):
			self.z = kwargs.pop('z', self.obj.z)
		elif hasattr(self.obj, 'sdss'):
			self.z = kwargs.pop('z', self.obj.sdss.z) 
		elif 'z' in kwargs:
			self.z = kwargs.pop('z') 
		else: 
			print("[imager] not redshift used, assuming -1")
			self.z = -1

		# set center_mode
		self.center_mode = kwargs.pop('center_mode', 'n/2')

		# set pixsize
		self.pixsize = surveysetup.pixsize[self.survey]
		self.pixelscale = u.pixel_scale(self.pixsize/u.pixel)
Exemplo n.º 41
0
def given_one_camera_get_stars_on_silicon(coords,
                                          cam_direction,
                                          verbose=True,
                                          withgaps=True):
    '''
    If you have a single TESS camera, and it points in a particular direction,
    which sources fall on silicon?  (This is relevant in a niche case: you have
    made an incomplete set of lightcurves for some field, and a you have a list
    of coordinates, and you want to know which coordinates you would _expect_
    to have a lightcurve).

    Args:

        coords (np.ndarray of astropy.coordinate.SkyCoords): array of astropy
        coordinates for the stars that will be either on, or not on silicon.

        cam_direction (float tuple): tuple with format: (cam_elat, cam_elon)

        where "cam_elat" means ecliptic latitude of the camera's center.

    Returns:

        on_chip (np.ndarray): array of 1's and 0's for what falls on
        silicon, and what does not. Same length as coords.
    '''

    n_coords = len(coords)
    if verbose:
        print('computing whether on silicon for {:d} objects'.format(n_coords))

    n_cameras = 1  # this function is for a single camera's "view"
    n_sectors = 1  # this function is for a single sector
    n_views = n_sectors * n_cameras

    # compute camera central coordinates for the first year, given the initial
    # longitude.
    views, cam_coords = [], []

    this_elat = cam_direction[0] * u.deg
    this_elon = cam_direction[1] * u.deg
    this_coord = SkyCoord(lon=this_elon,
                          lat=this_elat,
                          frame='barycentrictrueecliptic')

    views = pd.DataFrame(
        {
            'n_camera': n_cameras,
            'elon': this_elon,
            'elat': this_elat,
            'ra': this_coord.icrs.ra,
            'dec': this_coord.icrs.dec
        },
        index=[0])

    # ccd info. see e.g., Huang et al, 2018. The gap size is a number inherited
    # from Josh Winn's code.
    fov = 24. * u.degree
    ccd_pix = 4096 * u.pix
    gap_pix = (2. / 0.015) * u.pix  # about 133 pixels per gap
    pixel_scale = u.pixel_scale(fov / (ccd_pix + gap_pix))
    ccd_center = np.ones(2) * (ccd_pix + gap_pix) / 2
    delt = (np.ones(2) * u.pix).to(u.degree, pixel_scale)

    elon = coords.barycentrictrueecliptic.lon.value
    elat = coords.barycentrictrueecliptic.lat.value
    ra = coords.icrs.ra.value
    dec = coords.icrs.dec.value

    onchip = np.zeros_like(ra)
    for ix, view in views.iterrows():

        # create new WCS object. See. e.g., Calabretta & Greisen 2002, paper
        # II, table 1. CRPIX: pixel-coordinates of reference pixel (center of
        # image). CRVAL: celestial long (RA) and lat (dec) of reference pixel.
        # CDELT: degrees per pixel at reference pixel location, i.e. the
        # coordinate scale. CTYPE: gnomic projection.
        w = wcs.WCS(naxis=2)
        w.wcs.crpix = ccd_center.value
        w.wcs.crval = [view['elon'], view['elat']]
        w.wcs.cdelt = delt.value
        w.wcs.ctype = ['RA---TAN', 'DEC--TAN']

        # follow fits standards: The image pixel count starts with 1.
        x, y = w.wcs_world2pix(elon, elat, 1)

        try:
            # the extra "1" is because of 1-based image count.
            if withgaps:
                onchip += (  # lower left CCD
                    ((x > 0.0) & (x <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.) &
                     (y > 0.0) & (y <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.))
                    |  # lower right CCD
                    ((x > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (x < (ccd_pix.value + gap_pix.value) - 1.) & (y > 0.0) &
                     (y < (ccd_pix.value - gap_pix.value) / 2. - 1.))
                    |  # upper right CCD
                    ((x > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (x < (ccd_pix.value + gap_pix.value) - 1.) &
                     (y > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (y < (ccd_pix.value + gap_pix.value) - 1.))
                    |  # upper left CCD 
                    ((x > 0.0) & (x <
                                  (ccd_pix.value - gap_pix.value) / 2. - 1.) &
                     (y > (ccd_pix.value + gap_pix.value) / 2. - 1.) &
                     (y < (ccd_pix.value + gap_pix.value) - 1.)))

            elif not withgaps:

                onchip += ((x > 0.) & (x < ccd_pix.value + gap_pix.value - 1.)
                           & (y > 0.) &
                           (y < ccd_pix.value + gap_pix.value - 1.))

        except Exception as e:

            print('failed computing onchip. error msg: {:s}'.format(e))
            return 0

    if verbose:
        print(
            'computed sector numbers for {:d} stars/objects'.format(n_coords))

    return onchip.astype(np.int)