Exemple #1
0
def test_transforms_compound(tmpdir):
    tree = {
        'compound':
        astmodels.Shift(1) & astmodels.Shift(2) | astmodels.Sky2Pix_TAN()
        | astmodels.Rotation2D()
        | astmodels.AffineTransformation2D([[2, 0], [0, 2]], [42, 32]) +
        astmodels.Rotation2D(32)
    }

    helpers.assert_roundtrip_tree(tree, tmpdir)
Exemple #2
0
def fpa2asdf(fpafile, outname, ref_kw):
    """
    Create an asdf reference file with the FPA description.

    The CDP2 delivery includes a fits file - "FPA.fpa" which is the
    input to this function. This file is converted to asdf and is a
    reference file of type "FPA".

    nirspec_fs_ref_tools.fpa2asdf('Ref_Files/CoordTransform/Description/FPA.fpa', 'fpa.asdf')

    Parameters
    ----------
    fpafile : str
        A fits file with FPA description (FPA.fpa)
    outname : str
        Name of output ASDF file.
    """
    with open(fpafile) as f:
        lines = [l.strip() for l in f.readlines()]

    # NRS1
    ind = lines.index("*SCA491_PitchX")
    scalex_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x')
    ind = lines.index("*SCA491_PitchY")
    scaley_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y')
    ind = lines.index("*SCA491_RotAngle")
    rot_nrs1 = models.Rotation2D(np.rad2deg(-float(lines[ind + 1])),
                                 name='fpa_rotation')
    ind = lines.index("*SCA491_PosX")
    shiftx_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x')
    ind = lines.index("*SCA491_PosY")
    shifty_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y')

    # NRS2
    ind = lines.index("*SCA492_PitchX")
    scalex_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x')
    ind = lines.index("*SCA492_PitchY")
    scaley_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y')
    ind = lines.index("*SCA492_RotAngle")
    rot_nrs2 = models.Rotation2D(np.rad2deg(float(lines[ind + 1])),
                                 name='fpa_rotation')
    ind = lines.index("*SCA492_PosX")
    shiftx_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x')
    ind = lines.index("*SCA492_PosY")
    shifty_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y')
    tree = ref_kw.copy()
    tree['NRS1'] = (shiftx_nrs1 & shifty_nrs1) | rot_nrs1 | (scalex_nrs1
                                                             & scaley_nrs1)
    tree['NRS2'] = (shiftx_nrs2 & shifty_nrs2) | rot_nrs2 | (scalex_nrs2
                                                             & scaley_nrs2)
    fasdf = AsdfFile()
    fasdf.tree = tree
    fasdf.write_to(outname)
    return fasdf
Exemple #3
0
def test_inverse_transforms(tmpdir):
    rotation = astmodels.Rotation2D(32)
    rotation.inverse = astmodels.Rotation2D(45)

    real_rotation = astmodels.Rotation2D(32)

    tree = {'rotation': rotation, 'real_rotation': real_rotation}

    def check(ff):
        assert ff.tree['rotation'].inverse.angle == 45

    helpers.assert_roundtrip_tree(tree, tmpdir, asdf_check_func=check)
def ifu_slicer2asdf(ifuslicer, author, description, useafter):
    """
    Create an asdf reference file with the MSA description.

    ifu_slicer2asdf("IFU_slicer.sgd", "ifu_slicer.asdf")

    Parameters
    ----------
    ifuslicer : str
        A fits file with the IFU slicer description
    outname : str
        Name of output ASDF file.
    """
    f = fits.open(ifuslicer)
    data = f[1].data
    header = f[1].header
    shiftx = models.Shift(header['XREF'], name='ifuslicer_x')
    shifty = models.Shift(header['YREF'], name='ifuslicer_y')
    rot = models.Rotation2D(np.rad2deg(header['ROT']), name='ifuslicer_rotate')
    model = rot | shiftx & shifty
    f.close()

    slicer_model = IFUSlicerModel()
    slicer_model.model = model
    slicer_model.data = data
    slicer_model.meta.author = author
    slicer_model.meta.description = description
    slicer_model.meta.useafter = useafter
    slicer_model.meta.pedigree = "GROUND"
    return slicer_model
def ifu_slicer2asdf(ifuslicer, outname, ref_kw):
    """
    Create an asdf reference file with the MSA description.

    ifu_slicer2asdf("IFU_slicer.sgd", "ifu_slicer.asdf")

    Parameters
    ----------
    ifuslicer : str
        A fits file with the IFU slicer description
    outname : str
        Name of output ASDF file.
    """
    f = fits.open(ifuslicer)
    tree = ref_kw.copy()
    data = f[1].data
    header = f[1].header
    shiftx = models.Shift(header['XREF'], name='ifu_slicer_xref')
    shifty = models.Shift(header['YREF'], name='ifu_slicer_yref')
    rot = models.Rotation2D(header['ROT'], name='ifu_slicer_rot')
    model = rot | shiftx & shifty
    tree['model'] = model
    tree['data'] = f[1].data
    f.close()
    fasdf = AsdfFile()
    fasdf.tree = tree
    fasdf.add_history_entry("Build 6")
    fasdf.write_to(outname)
    return fasdf
Exemple #6
0
def pcf_forward(pcffile, outname):
    """
    Create the **IDT** forward transform from collimator to gwa.
    """
    with open(pcffile) as f:
        lines = [l.strip() for l in f.readlines()]

    factors = lines[lines.index('*Factor 2') + 1].split()
    # factor==1/factor in backward msa2ote direction and factor==factor in sky2detector direction
    scale = models.Scale(float(factors[0]), name="x_scale") & \
          models.Scale(float(factors[1]), name="y_scale")

    rotation_angle = lines[lines.index('*Rotation') + 1]
    # The minius sign here is because astropy.modeling has the opposite direction of rotation than the idl implementation
    rotation = models.Rotation2D(-float(rotation_angle), name='rotation')


    # Here the model is called "output_shift" but in the team version it is the "input_shift".
    input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split()
    input_rot_shift = models.Shift(-float(input_rot_center[0]), name='input_x_shift') & \
                 models.Shift(-float(input_rot_center[1]), name='input_y_shift')


    # Here the model is called "input_shift" but in the team version it is the "output_shift".
    output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split()
    output_rot_shift = models.Shift(float(output_rot_center[0]), name='output_x_shift') & \
                  models.Shift(float(output_rot_center[1]), name='output_y_shift')

    degree = int(lines[lines.index('*FitOrder') + 1])
    xcoeff_index = lines.index('*xForwardCoefficients 21 2')
    xlines = lines[xcoeff_index + 1: xcoeff_index + 22]
    xcoeff_forward = coeffs_from_pcf(degree, xlines)
    x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_forward)

    ycoeff_index = lines.index('*yForwardCoefficients 21 2')
    ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22])
    y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_forward)

    xcoeff_index = lines.index('*xBackwardCoefficients 21 2')
    xcoeff_backward = coeffs_from_pcf(degree, lines[xcoeff_index + 1: xcoeff_index + 22])
    x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_backward)

    ycoeff_index = lines.index('*yBackwardCoefficients 21 2')
    ycoeff_backward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22])
    y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_backward)

    x_poly_forward.inverse = x_poly_backward
    y_poly_forward.inverse = y_poly_backward

    poly_mapping1  = Mapping((0, 1, 0, 1))
    poly_mapping1.inverse = Identity(2)
    poly_mapping2 = Identity(2)
    poly_mapping2.inverse = Mapping((0, 1, 0, 1))

    model = input_rot_shift | rotation | scale | output_rot_shift | \
          poly_mapping1 | x_poly_forward & y_poly_forward | poly_mapping2
    f = AsdfFile()
    f.tree = {'model': model}
    f.write_to(outname)
Exemple #7
0
def test_fix_inputs(tmpdir):
    model = astmodels.Pix2Sky_TAN() | astmodels.Rotation2D()
    tree = {
        'compound': fix_inputs(model, {'x': 45}),
        'compound1': fix_inputs(model, {0: 45})
    }

    helpers.assert_roundtrip_tree(tree, tmpdir)
Exemple #8
0
def test_compound_deepcopy():
    model = (models.Gaussian1D(10, 2, 3) | models.Shift(2)) & models.Rotation2D(21.3)
    new_model = model.deepcopy()
    assert id(model) != id(new_model)
    assert id(model._leaflist) != id(new_model._leaflist)
    assert id(model[0]) != id(new_model[0])
    assert id(model[1]) != id(new_model[1])
    assert id(model[2]) != id(new_model[2])
Exemple #9
0
def test_domain(tmpdir):
    def check(ff):
        assert ff.tree['rot'].meta['domain'] == {
            'lower': 0, 'upper': 1, 'includes_lower': True}

    model = astmodels.Rotation2D(23)
    model.meta['domain'] = {'lower': 0, 'upper': 1, 'includes_lower': True}
    tree = {'rot': model}
    helpers.assert_roundtrip_tree(tree, tmpdir, check)
Exemple #10
0
def test_calculate_affine_matrices(angle, scale, xoffset, yoffset):
    m = ((models.Scale(scale) & models.Scale(scale)) | models.Rotation2D(angle)
         | (models.Shift(xoffset) & models.Shift(yoffset)))
    affine = adwcs.calculate_affine_matrices(m, (100, 100))
    assert_allclose(affine.offset, (yoffset, xoffset), atol=1e-10)
    angle = math.radians(angle)
    assert_allclose(affine.matrix,
                    ((scale * math.cos(angle), scale * math.sin(angle)),
                     (-scale * math.sin(angle), scale * math.cos(angle))),
                    atol=1e-10)
Exemple #11
0
def test_LabelMapperRange():
    sel = create_range_mapper()
    assert(sel(6, 2) == 4.2)

    with pytest.raises(TypeError):
        selector.LabelMapperRange(('x', 'y'),
                                  mapper={(1, 5): models.Rotation2D(23),
                                          (7, 10): models.Shift(1)
                                          }
                                  )
Exemple #12
0
def _create_wcs_from_offsets(adinput, adref, center_of_rotation=None):
    """
    This function uses the POFFSET, QOFFSET, and PA header keywords to create
    a new WCS for an image. Its primary role is for GNIRS. For ease, it works
    out the (RA,DEC) of the centre of rotation in the reference image and
    determines where in the input image this is.

    Parameters
    ----------
    adinput: AstroData
        The input image whose WCS needs to be rewritten
    adreference: AstroData
        The reference image with a trustworthy WCS
    center_of_rotation: 2-tuple
        Location of rotation center (x, y)
    """
    log = logutils.get_logger(__name__)
    if len(adinput) != len(adref):
        log.warning("Number of extensions in input files are different. "
                    "Cannot correct WCS.")
        return adinput

    log.stdinfo("Updating WCS of {} based on {}".format(adinput.filename,
                                                        adref.filename))
    try:
        xdiff = adref.detector_x_offset() - adinput.detector_x_offset()
        ydiff = adref.detector_y_offset() - adinput.detector_y_offset()
        pa1 = adref.phu['PA']
        pa2 = adinput.phu['PA']
    except (KeyError, TypeError):  # TypeError if offset is None
        log.warning("Cannot obtain necessary offsets from headers "
                    "so no change will be made")
        return adinput

    # We expect mosaicked inputs but there's no reason why this couldn't
    # work for all extensions in an image
    for extin, extref in zip(adinput, adref):
        # Will need to have some sort of LUT here eventually. But for now...
        if center_of_rotation is None:
            center_of_rotation = (630.0, 520.0) if 'GNIRS' in adref.tags \
                else tuple(0.5*(x-1) for x in extref.data.shape[::-1])

        wcsref = WCS(extref.hdr)
        ra0, dec0 = wcsref.all_pix2world(center_of_rotation[0],
                                         center_of_rotation[1], 1)
        extin.hdr['CRVAL1'] = float(ra0)
        extin.hdr['CRVAL2'] = float(dec0)
        extin.hdr['CRPIX1'] = center_of_rotation[0] - xdiff
        extin.hdr['CRPIX2'] = center_of_rotation[1] - ydiff
        cd = models.Rotation2D(angle=pa1-pa2)(*wcsref.wcs.cd)
        extin.hdr['CD1_1'] = cd[0][0]
        extin.hdr['CD1_2'] = cd[0][1]
        extin.hdr['CD2_1'] = cd[1][0]
        extin.hdr['CD2_2'] = cd[1][1]
    return adinput
Exemple #13
0
def test_LabelMapperDict():
    dmapper = create_scalar_mapper()
    sel = selector.LabelMapperDict(('x', 'y'), dmapper, atol=10**-3,
                                   inputs_mapping=models.Mapping((0,), n_inputs=2))
    assert(sel(-1.9580, 2) == dmapper[-1.95805483](-1.95805483, 2))

    with pytest.raises(TypeError):
        selector.LabelMapperDict(('x', 'y'),
                                 mapper={1: models.Rotation2D(23),
                                         2: models.Shift(1)
                                         }
                                 )
def _apply_model_to_wcs(adinput, transform=None, keyword_comments=None):
    """
    This function modifies the WCS of input images according to astropy
    Models that describe how to map the input image pixels to their
    correct location, i.e., an input pixel (x,y) should have the world
    coordinates WCS(m(x,y)), where m is the transformation model.

    Parameters
    ----------
    adinput: list of AD objects
        input images for WCS to be modified
    transform: list of Models
        transformations (in pixel space)
    keyword_comments: dict
        the comment for each FITS keyword

    Returns
    -------
    list of ADs: modified AD instances
    """
    if len(transform) != len(adinput):
        raise IOError("List of models have the same number of "
                      "elements as adinput")

    for ad, model in zip(adinput, transform):
        crpix1 = ad.hdr['CRPIX1'][0]
        crpix2 = ad.hdr['CRPIX2'][0]
        newcrpix = model.inverse(crpix1, crpix2)

        # Determine total magnification and rotation from all relevant
        # model components
        magnification = np.multiply.reduce([
            getattr(model, p).value for p in model.param_names if 'factor' in p
        ])
        rotation = np.add.reduce([
            getattr(model, p).value for p in model.param_names if 'angle' in p
        ])

        cdmatrix = [[
            ad.hdr['CD{}_{}'.format(i, j)][0] / magnification for j in [1, 2]
        ] for i in [1, 2]]
        m = models.Rotation2D(-rotation)
        newcdmatrix = m(*cdmatrix)
        for ax in 1, 2:
            ad.hdr.set('CRPIX{}'.format(ax),
                       newcrpix[ax - 1],
                       comment=keyword_comments["CRPIX{}".format(ax)])
            for ax2 in 1, 2:
                ad.hdr.set('CD{}_{}'.format(ax, ax2),
                           newcdmatrix[ax - 1][ax2 - 1],
                           comment=keyword_comments['CD{}_{}'.format(ax, ax2)])
    return adinput
Exemple #15
0
def msa2asdf(msafile, author, description, useafter):
    """
    Create an asdf reference file with the MSA description.

    mas2asfdf("MSA.msa", "msa.asdf")

    Parameters
    ----------
    msafile : str
        A fits file with MSA description (MSA.msa)
    outname : str
        Name of output ASDF file.
    """
    f = fits.open(msafile)
    data = f[5].data  # SLITS and IFU
    header = f[5].header
    shiftx = models.Shift(header['SLITXREF'], name='msa_slit_x')
    shifty = models.Shift(header['SLITYREF'], name='msa_slit_y')
    slitrot = models.Rotation2D(np.rad2deg(header['SLITROT']),
                                name='msa_slit_rot')
    msa_model = MSAModel()
    msa_model.Q5.model = slitrot | shiftx & shifty
    msa_model.Q5.data = f[5].data
    for i in range(1, 5):
        header = f[i].header
        shiftx = models.Shift(header['QUADXREF'], name='msa_Q{0}_x'.format(i))
        shifty = models.Shift(header['QUADYREF'], name='msa_Q{0}_y'.format(i))
        slitrot = models.Rotation2D(np.rad2deg(header['QUADROT']),
                                    name='msa_Q{0}_rot'.format(i))
        model = slitrot | shiftx & shifty
        data = f[i].data
        name = "Q{0}".format(i)
        setattr(msa_model, name, {'model': model, 'data': data})
    f.close()
    msa_model.meta.author = author
    msa_model.meta.description = description
    msa_model.meta.useafter = useafter
    msa_model.meta.pedigree = 'GROUND'
    return msa_model
def msa2asdf(msafile, outname, ref_kw):
    """
    Create an asdf reference file with the MSA description.

    mas2asfdf("MSA.msa", "msa.asdf")

    Parameters
    ----------
    msafile : str
        A fits file with MSA description (MSA.msa)
    outname : str
        Name of output ASDF file.
    """
    f = fits.open(msafile)
    tree = ref_kw.copy()
    data = f[5].data  # SLITS and IFU
    header = f[5].header
    shiftx = models.Shift(header['SLITXREF'], name='slit_xref')
    shifty = models.Shift(header['SLITYREF'], name='slit_yref')
    slitrot = models.Rotation2D(header['SLITROT'], name='slit_rot')

    tree[5] = {}
    tree[5]['model'] = slitrot | shiftx & shifty
    tree[5]['data'] = f[5].data
    for i in range(1, 5):
        header = f[i].header
        shiftx = models.Shift(header['QUADXREF'], name='msa_xref')
        shifty = models.Shift(header['QUADYREF'], name='msa_yref')
        slitrot = models.Rotation2D(header['QUADROT'], name='msa_rot')
        tree[i] = {}
        tree[i]['model'] = slitrot | shiftx & shifty
        tree[i]['data'] = f[i].data

    f.close()
    fasdf = AsdfFile()
    fasdf.tree = tree
    fasdf.add_history_entry("Build 6")
    fasdf.write_to(outname)
    return fasdf
Exemple #17
0
def test_fix_inputs(tmpdir):

    with warnings.catch_warnings():
        # Some schema files are missing from asdf<=2.4.2 which causes warnings
        if LooseVersion(asdf.__version__) <= '2.4.2':
            warnings.filterwarnings('ignore', 'Unable to locate schema file')

        model = astmodels.Pix2Sky_TAN() | astmodels.Rotation2D()
        tree = {
            'compound': fix_inputs(model, {'x': 45}),
            'compound1': fix_inputs(model, {0: 45})
        }

        helpers.assert_roundtrip_tree(tree, tmpdir)
Exemple #18
0
def lrs(input_model, reference_files):
    """
    Create the WCS pipeline for a MIRI fixed slit observation.

    reference_files = {"specwcs": 'MIRI_FM_MIRIMAGE_P750L_DISTORTION_04.02.00.fits'}
    """
    detector = cf.Frame2D(name='detector',
                          axes_order=(0, 1),
                          unit=(u.pix, u.pix))
    focal_spatial = cf.Frame2D(name='focal',
                               axes_order=(0, 1),
                               unit=(u.arcmin, u.arcmin))
    sky = cf.CelestialFrame(reference_frame=coord.ICRS())
    spec = cf.SpectralFrame(name='wavelength',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('lambda', ))
    focal = cf.CompositeFrame([focal_spatial, spec])

    ref = fits.open(reference_files['specwcs'])
    ldata = ref[1].data
    if input_model.meta.exposure.type.lower() == 'mir_lrs-fixedslit':
        zero_point = ref[1].header['imx'], ref[1].header['imy']
    elif input_model.meta.exposure.type.lower() == 'mir_lrs-slitless':
        #zero_point = ref[1].header['imysltl'], ref[1].header['imxsltl']
        #zero point in reference file is wrong
        # This should eb moved eventually to the reference file.
        zero_point = [35, 442]  #[35, 763] # account for subarray
    lrsdata = np.array([l for l in ldata])
    x0 = lrsdata[:, 3]
    x1 = lrsdata[:, 5]
    y0 = lrsdata[:, 4]
    domain = [{
        'lower': x0.min() + zero_point[0],
        'upper': x1.max() + zero_point[0]
    }, {
        'lower': (y0.min() + zero_point[1]),
        'upper': (y0.max() + zero_point[1])
    }]
    log.info("Setting domain to {0}".format(domain))
    lrs_wav_model = jwmodels.LRSWavelength(lrsdata, zero_point)
    ref.close()
    angle = np.arctan(0.00421924)
    spatial = models.Rotation2D(angle)
    det2focal = models.Mapping((0, 1, 0, 1)) | spatial & lrs_wav_model
    det2focal.meta['domain'] = domain
    pipeline = [(detector, det2focal), (focal, None)]
    #(sky, None)
    #]
    return pipeline
Exemple #19
0
 def wcs(self):
     """Return the WCS modified by the translation/scaling/rotation"""
     wcs = self._wcs.deepcopy()
     x_offset = self.x_offset.value
     y_offset = self.y_offset.value
     angle = self.angle.value
     factor = self.factor.value
     wcs.wcs.crpix += np.array([x_offset, y_offset])
     if factor != 1:
         wcs.wcs.cd *= factor
     if angle != 0.0:
         m = models.Rotation2D(angle)
         wcs.wcs.cd = m(*wcs.wcs.cd)
     return wcs
Exemple #20
0
def test_Gaussian2DRotation():
    amplitude = 42
    x_mean, y_mean = 0, 0
    x_stddev, y_stddev = 2, 3
    theta = Angle(10, 'deg')
    pars = dict(amplitude=amplitude, x_mean=x_mean, y_mean=y_mean,
                x_stddev=x_stddev, y_stddev=y_stddev)
    rotation = models.Rotation2D(angle=theta.degree)
    point1 = (x_mean + 2 * x_stddev, y_mean + 2 * y_stddev)
    point2 = rotation(*point1)
    g1 = models.Gaussian2D(theta=0, **pars)
    g2 = models.Gaussian2D(theta=theta.radian, **pars)
    value1 = g1(*point1)
    value2 = g2(*point2)
    assert_allclose(value1, value2)
Exemple #21
0
    def rotate(self, angle):
        """
        Modify the CD matrices of all the headers to effect a rotation.
        This assumes that the CRVALi keywords are the same in all headers
        or else this modification may be inconsistent.

        Parameters
        ----------
        angle: float
            Rotation angle (degrees)
        """
        for ext in self:
            cd_matrix = models.Rotation2D(angle)(*WCS(ext.hdr).wcs.cd)
            ext.hdr.update({
                'CD{}_{}'.format(i + 1, j + 1): cd_matrix[i][j]
                for i in (0, 1) for j in (0, 1)
            })
            ext.wcs = adwcs.fitswcs_to_gwcs(ext.hdr)
        self.phu['PA'] = (self.phu.get('PA', 0) + angle) % 360
Exemple #22
0
def test_fix_inputs(tmpdir):

    with warnings.catch_warnings():
        # Some schema files are missing from asdf<=2.4.2 which causes warnings
        if Version(asdf.__version__) <= Version('2.5.1'):
            warnings.filterwarnings('ignore', 'Unable to locate schema file')

        model0 = astmodels.Pix2Sky_TAN()
        model0.input_units_equivalencies = {'x': u.dimensionless_angles(),
                                            'y': u.dimensionless_angles()}
        model1 = astmodels.Rotation2D()
        model = model0 | model1

        tree = {
            'compound': fix_inputs(model, {'x': 45}),
            'compound1': fix_inputs(model, {0: 45})
        }

        helpers.assert_roundtrip_tree(tree, tmpdir)
Exemple #23
0
def test_Ellipse2D():
    """Test Ellipse2D model."""
    amplitude = 7.5
    x0, y0 = 15, 15
    theta = Angle(45, 'deg')
    em = models.Ellipse2D(amplitude, x0, y0, 7, 3, theta.radian)
    y, x = np.mgrid[0:30, 0:30]
    e = em(x, y)
    assert np.all(e[e > 0] == amplitude)
    assert e[y0, x0] == amplitude

    rotation = models.Rotation2D(angle=theta.degree)
    point1 = [2, 0]      # Rotation2D center is (0, 0)
    point2 = rotation(*point1)
    point1 = np.array(point1) + [x0, y0]
    point2 = np.array(point2) + [x0, y0]
    e1 = models.Ellipse2D(amplitude, x0, y0, 7, 3, theta=0.)
    e2 = models.Ellipse2D(amplitude, x0, y0, 7, 3, theta=theta.radian)
    assert e1(*point1) == e2(*point2)
Exemple #24
0
def msa2asdf(msafile, outname, ref_kw):
    """
    Create an asdf reference file with the MSA description.

    The CDP2 delivery includes a fits file - "MSA.msa".
    This file is converted to asdf and serves as a reference file of type "REGIONS".

    mas2asfdf("MSA.msa", "msa.asdf") --> creates an 85MB file

    Parameters
    ----------
    msafile : str
        A fits file with MSA description (MSA.msa)
    outname : str
        Name of output ASDF file.
    """
    f = fits.open(msafile)
    tree = ref_kw.copy()
    data = f[5].data  # SLITS and IFU
    header = f[5].header
    shiftx = models.Shift(header['SLITXREF'], name='slit_xref')
    shifty = models.Shift(header['SLITYREF'], name='slit_yref')
    slitrot = models.Rotation2D(header['SLITROT'], name='slit_rot')
    for j, slit in enumerate(
        ['S200A1', 'S200A2', 'S400A1', 'S1600A1', 'S200B1', 'IFU']):
        slitdata = data[j]
        t = {}
        for i, s in enumerate(['xcenter', 'ycenter', 'xsize', 'ysize']):
            t[s] = slitdata[i + 1]
        model = models.Scale(t['xsize']) & models.Scale(t['ysize']) | \
              models.Shift(t['xcenter']) & models.Shift(t['ycenter']) | \
              slitrot | shiftx & shifty
        t['model'] = model
        tree[slit] = t

    f.close()
    fasdf = AsdfFile()
    fasdf.tree = tree
    fasdf.write_to(outname)
    return fasdf
Exemple #25
0
def test_Rotation2D_errors():
    model = models.Rotation2D(angle=90 * u.deg)

    # Bad evaluation input shapes
    x = np.array([1, 2])
    y = np.array([1, 2, 3])
    message = "Expected input arrays to have the same shape"

    with pytest.raises(ValueError) as err:
        model.evaluate(x, y, model.angle)
    assert str(err.value) == message
    with pytest.raises(ValueError) as err:
        model.evaluate(y, x, model.angle)
    assert str(err.value) == message

    # Bad evaluation units
    x = np.array([1, 2])
    y = np.array([1, 2])
    message = "x and y must have compatible units"
    with pytest.raises(u.UnitsError) as err:
        model.evaluate(x * u.m, y, model.angle)
    assert str(err.value) == message
Exemple #26
0
    def add_galaxy(self,
                   amplitude=None,
                   n=4.0,
                   r_e=1.0,
                   axis_ratio=1.0,
                   pa=0.0,
                   x=None,
                   y=None):
        """
        Adds a Sersic profile galaxy, convolved with the seeing, at the
        specified location.

        Parameters
        ----------
        amplitude: float
            Peak pixel value
        n: float
            Sersic index
        r_e: float
            effective radius (arcseconds)
        axis_ratio: float
            ratio of major to minor axis
        pa: float
            position angle of major axis
        x, y: float [0-indexed]
            location of centre of star in pixels
            (Decorated by @convert_rd2xy so ra, dec can be specified)
        """
        obj = ((models.Shift(-x) & models.Shift(-y))
               | models.Rotation2D(self.phu.get('PA', 0) - pa) |
               (models.Scale(axis_ratio) & models.Identity(1)) | Sersic(
                   amplitude=amplitude, r_e=r_e / self.pixel_scale(), n=n))
        ygrid, xgrid = np.mgrid[:self.data.shape[-2], :self.data.shape[-1]]
        obj_data = obj(xgrid, ygrid)
        sigma = 0.42466 * self.seeing / self.pixel_scale()
        convolved_data = gaussian_filter(obj_data,
                                         sigma=sigma,
                                         mode='constant')
        self.add(convolved_data)
Exemple #27
0
def test_adjust_wcs_to_reference(astrofaker, no_wcs, rotate, scale):
    scale = False
    mods = [models.Identity(2)]
    for params in MODEL_PARMS:
        m = models.Shift(params[0]) & models.Shift(params[1])
        if rotate:
            m |= models.Rotation2D(params[2])
        if scale:
            m |= models.Scale(params[3]) & models.Scale(params[3])
        mods.append(m)
    adinputs = make_images(astrofaker, mods=mods)
    if no_wcs:
        for ad in adinputs:
            del ad[0].hdr['CD*']
            ad[0].wcs = None
    p = NIRIImage(adinputs)
    p.detectSources()
    p.adjustWCSToReference(first_pass=45 if no_wcs else 5,
                           rotate=rotate,
                           scale=scale)

    # We're going to confirm that a grid of input points are transformed
    # correctly, rather than comparing the components of the registration
    # model with the original model
    yin, xin = np.mgrid[:1000:100, :1000:100]
    for i, (ad, m) in enumerate(zip(p.streams['main'], mods)):
        if i == 0:  # the Identity model: nothing to check
            continue
        m_regist = ad[0].wcs.forward_transform[:m.n_submodels]
        print(m_regist)

        xref, yref = m(xin, yin)
        xout, yout = m_regist(xin, yin)
        np.testing.assert_allclose(xref, xout, atol=0.1)
        np.testing.assert_allclose(yref, yout, atol=0.1)
        rms = np.sqrt(((xref - xout)**2 + (yref - yout)**2).mean())
        assert rms < 0.05
Exemple #28
0
def test_name(tmpdir):
    def check(ff):
        assert ff.tree['rot'].name == 'foo'

    tree = {'rot': astmodels.Rotation2D(23, name='foo')}
    helpers.assert_roundtrip_tree(tree, tmpdir, asdf_check_func=check)
Exemple #29
0
    def mosaicDetectors(self, adinputs=None, **params):
        """
        This primitive does a full mosaic of all the arrays in an AD object.
        An appropriate geometry_conf.py module containing geometric information
        is required.

        Parameters
        ----------
        suffix: str
            suffix to be added to output files.
        sci_only: bool
            mosaic only SCI image data. Default is False
        order: int (1-5)
            order of spline interpolation
        """
        log = self.log
        log.debug(gt.log_message("primitive", self.myself(), "starting"))
        timestamp_key = self.timestamp_keys[self.myself()]

        suffix = params['suffix']
        order = params['order']
        attributes = ['data'] if params['sci_only'] else None
        geotable = import_module('.geometry_conf', self.inst_lookups)

        adoutputs = []
        for ad in adinputs:
            if ad.phu.get(timestamp_key):
                log.warning("No changes will be made to {}, since it has "
                            "already been processed by mosaicDetectors".format(
                                ad.filename))
                adoutputs.append(ad)
                continue

            if len(ad) == 1:
                log.warning("{} has only one extension, so there's nothing "
                            "to mosaic".format(ad.filename))
                adoutputs.append(ad)
                continue

            # If there's an overscan section, we must trim it before mosaicking
            try:
                overscan_kw = ad._keyword_for('overscan_section')
            except AttributeError:  # doesn't exist for this AD, so carry on
                pass
            else:
                if overscan_kw in ad.hdr:
                    ad = gt.trim_to_data_section(ad, self.keyword_comments)

            # Create the blocks (individual physical detectors)
            array_info = gt.array_information(ad)
            blocks = [
                Block(ad[arrays], shape=shape) for arrays, shape in zip(
                    array_info.extensions, array_info.array_shapes)
            ]
            offsets = [
                ad[exts[0]].array_section() for exts in array_info.extensions
            ]

            detname = ad.detector_name()
            xbin, ybin = ad.detector_x_bin(), ad.detector_y_bin()
            geometry = geotable.geometry[detname]
            default_shape = geometry.get('default_shape')
            adg = AstroDataGroup()

            for block, origin, offset in zip(blocks, array_info.origins,
                                             offsets):
                # Origins are in (x, y) order in LUT
                block_geom = geometry[origin[::-1]]
                nx, ny = block_geom.get('shape', default_shape)
                nx /= xbin
                ny /= ybin
                shift = block_geom.get('shift', (0, 0))
                rot = block_geom.get('rotation', 0.)
                mag = block_geom.get('magnification', (1, 1))
                transform = Transform()

                # Shift the Block's coordinates based on its location within
                # the full array, to ensure any rotation takes place around
                # the true centre.
                if offset.x1 != 0 or offset.y1 != 0:
                    transform.append(
                        models.Shift(float(offset.x1) / xbin)
                        & models.Shift(float(offset.y1) / ybin))

                if rot != 0 or mag != (1, 1):
                    # Shift to centre, do whatever, and then shift back
                    transform.append(
                        models.Shift(-0.5 * (nx - 1)) & models.Shift(-0.5 *
                                                                     (ny - 1)))
                    if rot != 0:
                        # Cope with non-square pixels by scaling in one
                        # direction to make them square before applying the
                        # rotation, and then reversing that.
                        if xbin != ybin:
                            transform.append(
                                models.Identity(1) & models.Scale(ybin / xbin))
                        transform.append(models.Rotation2D(rot))
                        if xbin != ybin:
                            transform.append(
                                models.Identity(1) & models.Scale(xbin / ybin))
                    if mag != (1, 1):
                        transform.append(
                            models.Scale(mag[0]) & models.Scale(mag[1]))
                    transform.append(
                        models.Shift(0.5 * (nx - 1)) & models.Shift(0.5 *
                                                                    (ny - 1)))
                transform.append(
                    models.Shift(float(shift[0]) / xbin)
                    & models.Shift(float(shift[1]) / ybin))
                adg.append(block, transform)

            adg.set_reference()
            ad_out = adg.transform(attributes=attributes,
                                   order=order,
                                   process_objcat=False)

            ad_out.orig_filename = ad.filename
            gt.mark_history(ad_out,
                            primname=self.myself(),
                            keyword=timestamp_key)
            ad_out.update_filename(suffix=suffix, strip=True)
            adoutputs.append(ad_out)

        return adoutputs
Exemple #30
0
    with pytest.raises(ValueError):
        model(1, 2, 3)

    with pytest.raises(ValueError):
        model(1)

    with pytest.raises(ValueError):
        model(1, 2, t=12, r=3)


@pytest.mark.parametrize('model', [
    models.Gaussian1D(),
    models.Polynomial1D(1, ),
    models.Tabular1D(lookup_table=np.ones((5, ))),
    models.Rotation2D(),
    models.Pix2Sky_TAN()
])
@pytest.mark.skipif('not HAS_SCIPY')
def test_call_keyword_args_1(model):
    """
    Test calling a model with positional, keywrd and a mixture of both arguments.
    """
    positional = model(1)
    assert_allclose(positional, model(x=1))

    model.inputs = ('r', )
    assert_allclose(positional, model(r=1))

    with pytest.raises(ValueError):
        model(1, 2, 3)